GBARunner2

By Gericom, Dec 4, 2016 516,157 3,011 99

  1. Gericom

    OP Gericom GBAtemp Maniac
    Member

    Joined:
    Jun 30, 2011
    Messages:
    1,355
    Country:
    Netherlands
    GBARunner2 is a hypervisor that runs GBA games on DS/DSi/3DS in DS mode, basically like Nintendont does for running Gamecube games on Wii.

    Download
    Source and releases can be found on github: https://github.com/Gericom/GBARunner2

    Compatibility List
    On the gbatemp wiki: https://wiki.gbatemp.net/wiki/GBARunner2
    Many thanks to @Dodain47 for investing so much time in testing games!

    Usage
    • Place a GBA bios on your sd card. Either /bios.bin or /gba/bios.bin will work.
      • Note: Do not use Normmatt's open-source GBA BIOS. It won't work, as many patches are applied at fixed addresses. The right checksums are listed below.
    • If you have a gba folder on the root of your sd, this folder will be opened by default
    • Do NOT use SRAM patches unless stated on the wiki. They cause problems with the internal patching of GBARunner2 and may actually break saving.
    • If you are using GBARunner2 with TWiLightMenu on a DSi or 3DS with the SD card, make sure you use the dldi on ARM7 build
    If you want to use existing save files, they should have the same name as the gba file but instead of .gba they should be .sav (so the save for mygame.gba is mygame.sav).

    BIOS Checksums
    The BIOS used should have the following checksums (checking one should be enough):
    • CRC32: 81977335
    • MD5: a860e8c0b6d573d191e4ec7db1b1e4f6
    • SHA1: 300c20df6731a33952ded8c436f7f186d25d3492
    • SHA256: fd2547724b505f487e6dcb29ec2ecff3af35a841a77ab2e85fd87350abd36570
    You can check the MD5 with WinMD5Free for example.
     
    Last edited by Gericom, Feb 5, 2020
  2. Mikemk

    Mikemk GBAtemp Advanced Maniac
    Member

    Joined:
    Mar 26, 2015
    Messages:
    1,895
    Country:
    United States
    Use mkdir in the Makefile to create a folder.
     
  3. Gericom

    OP Gericom GBAtemp Maniac
    Member

    Joined:
    Jun 30, 2011
    Messages:
    1,355
    Country:
    Netherlands
    I am simply going to remove the need for that folder.
     
  4. windwakr

    windwakr GBAtemp Fan
    Member

    Joined:
    Sep 13, 2009
    Messages:
    494
    Country:
    United States
    Very impressive. Can't wait to see the compatibility improve.

    Commit 6c1dc96:
    Advance Wars - Seems to run fast with good audio, but a lot of graphical bugs. Will freeze if you don't skip the intro.
    Zelda Minish Cap - Extremely slow, graphical bugs, garbage audio. Too slow to bother trying to get in game.
    Castlevania Circle of the Moon - Very slow, a few graphical bugs, good audio.
    Final Fantasy Tactics Advance - Extreme graphical bugs, title screen seems to have some sort of palette issue then freezes.


    Tested on a launch day phat(wow, it's 12 years old now) with an Acekard 2i.
     
    Last edited by windwakr, Dec 5, 2016
  5. VinLark

    VinLark This Machine Used To Kill Bourgeois Sentimentality
    Member

    Joined:
    Jun 11, 2016
    Messages:
    4,348
    Country:
    United States
    Wew lad, new NDS homebrew is always a site to see.

    I'll try this out when I can, I do want to see how this holds up to the other gba emulator. Nice!
     
    StrayGuitarist and DarkRioru like this.
  6. nxwing

    nxwing TYPE-MOON Enthusiast
    Member

    Joined:
    Jul 22, 2013
    Messages:
    2,175
    Country:
    Philippines
    This is pretty nice! I'll test it out with a few games and I'll try and make an entry on the wiki for this.
     
  7. Gericom

    OP Gericom GBAtemp Maniac
    Member

    Joined:
    Jun 30, 2011
    Messages:
    1,355
    Country:
    Netherlands
    Thanks, that would be nice. Make sure to include a field for the commit number, as things might change from commit to commit.
     
  8. Coto

    Coto -
    Member

    Joined:
    Jun 4, 2010
    Messages:
    2,700
    Country:
    Chile
    very nice work Gericom.!

    I might give some feedback as I get used to this codebase.
     
  9. Gericom

    OP Gericom GBAtemp Maniac
    Member

    Joined:
    Jun 30, 2011
    Messages:
    1,355
    Country:
    Netherlands
    I've commited some bugfixes, Super Mario Advance 3: Yoshi's Island now works and Mario and Luigi gets a little further. Some other games now boot aswell.
     
  10. raystriker

    raystriker The powers that be
    Member

    Joined:
    Dec 28, 2011
    Messages:
    1,472
    Country:
    India
    OT: There was a time when people used to get banned for asking whether the nds could emulate the gba.
    Thanks for reviving the gba hypervisor for nds, we've waited long enough :bow:
     
    Don Jon, ry755, emuashui and 5 others like this.
  11. Coto

    Coto -
    Member

    Joined:
    Jun 4, 2010
    Messages:
    2,700
    Country:
    Chile
    arm7 touchscreen
    I got RTC working in gbaemu4ds long ago so i'll share how it was done:

    (I just literally mapped them)

    first I used IPC to transfer stuff between ARM7->ARM9

    //ipc header definition
    Code:
    ipc.h
    
    //---------------------------------------------------------------------------------
    typedef struct sMyIPC {
    //---------------------------------------------------------------------------------
      int16 touchX,  touchY;  // raw x/y
       int16 touchXpx, touchYpx; // TFT x/y pixel
    
       int16 touchZ1,  touchZ2;  // TSC x-panel measurements
       uint16 tdiode1,  tdiode2;  // TSC temperature diodes
       uint32 temperature;  // TSC computed temperature
    
       uint16 buttons;  // keypad buttons
      uint16 buttons_xy_folding;  // X, Y, /PENIRQ buttons
    
       u8 touched;          //TSC touched?
      u8 touch_pendown;  //TSC already held before?
    
       uint16 battery;  // battery life status
       uint16 aux;  // SPI AUX port status
    
    
      //IPC Clock
      //[0]; //yy
      //[1]; //mth
      //[2]; //dd
      //[3]; //wat - day of week?
      //[4]; //hh
      //[5]; //mm
      //[6]; //ss
      u8 clockdata[0x20];
    
    
    } tMyIPC;
    
    //Shared Work  027FF000h 4KB  -  -  -  R/W
    //IPC Struct
    #define SHARED_ADDR_REGION ((tMyIPC volatile *)(0x027FF000))
    
    

    //ipc definition opcodes (i dont really care about BCD conversion....)
    Code:
    //gbaemu4ds clock opcodes
    u8 gba_get_yearbytertc(){
       return (u8)(u32)SHARED_ADDR_REGION->clockdata[0];
    }
    
    u8 gba_get_monthrtc(){
       return (u8)(u32)SHARED_ADDR_REGION->clockdata[1];
    }
    
    u8 gba_get_dayrtc(){
       return (u8)(u32)SHARED_ADDR_REGION->clockdata[2];
    }
    
    u8 gba_get_dayofweekrtc(){
       return (u8)(u32)SHARED_ADDR_REGION->clockdata[3];
    }
    
    
    u8 gba_get_hourrtc(){
       return (u8)(u32)SHARED_ADDR_REGION->clockdata[4];
    }
    
    u8 gba_get_minrtc(){
       return (u8)(u32)SHARED_ADDR_REGION->clockdata[5];
    }
    
    u8 gba_get_secrtc(){
       return (u8)(u32)SHARED_ADDR_REGION->clockdata[6];
    }
    
    


    //ARM7

    Code:
    touch_ipc.h
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    extern void updateMyIPC();
    
    #ifdef __cplusplus
    }
    #endif
    
    
    
    Code:
    touch_ipc.c
    
    #include "touch_ipc.h"
    #include "../../common/gba_ipc.h"
    
    #include <nds/ndstypes.h>
    #include <nds/system.h>
    #include <nds/arm7/touch.h>
    #include <nds/input.h>
    #include <nds/interrupts.h>
    
    #include <nds/bios.h>
    #include <nds/arm7/clock.h>
    #include <nds/ipc.h>
    #include <stdlib.h>
    
    //coto: use it at vcount interrupts so you save battery (or vblank but vcount works just fine)
    void updateMyIPC()
    {
       uint16 but=0, batt=0;
       int t1=0, t2=0;
       uint32 temp=0;
       u32 i=0;
       u8 clock_buf[sizeof(SHARED_ADDR_REGION->clockdata)];
    
      touchPosition tempPos;
      touchReadXY(&tempPos);
    
       // Read the touch screen
       but = REG_KEYXY;
       batt = touchRead(TSC_MEASURE_BATTERY);
       // Read the time
       rtcGetTimeAndDate(clock_buf);
    
       // Read the temperature
       temp = touchReadTemperature(&t1, &t2);
    
      // Update the IPC struct
       SHARED_ADDR_REGION->buttons     = but;
       SHARED_ADDR_REGION->touched  = ((tempPos.px > 0) || (tempPos.py > 0)) ? 1 : 0;
    
      //raw x/y
      SHARED_ADDR_REGION->touchX  = tempPos.rawx;
      SHARED_ADDR_REGION->touchY  = tempPos.rawy;
    
      //TFT x/y pixel
      SHARED_ADDR_REGION->touchXpx = tempPos.px;
      SHARED_ADDR_REGION->touchYpx = tempPos.py;
    
       SHARED_ADDR_REGION->touchZ1 = tempPos.z1;
       SHARED_ADDR_REGION->touchZ2 = tempPos.z2;
       SHARED_ADDR_REGION->battery     = batt;
    
      //Get time
      for(i=0; i< sizeof(clock_buf); i++){
      SHARED_ADDR_REGION->clockdata[i] = clock_buf[i];
      }
    
       SHARED_ADDR_REGION->temperature = temp;
       SHARED_ADDR_REGION->tdiode1 = t1;
       SHARED_ADDR_REGION->tdiode2 = t2;
    
    }
    
    


    //ARM9

    arm9 touchscreen handler (only if you want touchscreen on custom handlers)
    Code:
    touch_ipc.h
    
    
    #ifndef GBAEMU4DS_ARM9TOUCH
    #define GBAEMU4DS_ARM9TOUCH
    
    #include <nds.h>
    #include <nds/touch.h>
    
    #endif
    
    
    #ifdef __cplusplus
    extern "C"{
    #endif
    
    extern void touchReadXY_gbaemu4ds(touchPosition * touchpos_inst);
    
    #ifdef __cplusplus
    }
    #endif
    
    
    Code:
    touch_ipc.c
    
    #include "touch_ipc.h"
    #include <nds.h>
    #include <nds/touch.h>
    #include "../../../common/gba_ipc.h"
    
    //usage: struct touchPosition touchposition;
    //touchReadXY_gbaemu4ds(&touchposition);
    
    void touchReadXY_gbaemu4ds(touchPosition * touchpos_inst){
    
      touchpos_inst->rawx =  SHARED_ADDR_REGION->touchX;
      touchpos_inst->rawy =  SHARED_ADDR_REGION->touchY;
    
      //TFT x/y pixel
      touchpos_inst->px  =  SHARED_ADDR_REGION->touchXpx;
      touchpos_inst->py  =  SHARED_ADDR_REGION->touchYpx;
    
      touchpos_inst->z1  =  SHARED_ADDR_REGION->touchZ1;
      touchpos_inst->z2  =  SHARED_ADDR_REGION->touchZ2;
    }
    


    and then VBA libs:
    Code:
    RTC.H
    
    // -*- C++ -*-
    // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
    // Copyright (C) 1999-2003 Forgotten
    // Copyright (C) 2004 Forgotten and the VBA development team
    
    // This program is free software; you can redistribute it and/or modify
    // it under the terms of the GNU General Public License as published by
    // the Free Software Foundation; either version 2, or(at your option)
    // any later version.
    //
    // This program is distributed in the hope that it will be useful,
    // but WITHOUT ANY WARRANTY; without even the implied warranty of
    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    // GNU General Public License for more details.
    //
    // You should have received a copy of the GNU General Public License
    // along with this program; if not, write to the Free Software Foundation,
    // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    
    #ifndef VBA_RTC_H
    #define VBA_RTC_H
    extern u16 rtcRead(u32 address);
    extern bool rtcWrite(u32 address, u16 value);
    extern void rtcEnable(bool);
    extern bool rtcIsEnabled();
    extern void rtcReset();
    
    extern void rtcReadGame(gzFile file);
    extern void rtcSaveGame(gzFile file);
    
    #endif
    
    
    Code:
    RTC.C
    
    // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
    // Copyright (C) 1999-2003 Forgotten
    // Copyright (C) 2005 Forgotten and the VBA development team
    
    // This program is free software; you can redistribute it and/or modify
    // it under the terms of the GNU General Public License as published by
    // the Free Software Foundation; either version 2, or(at your option)
    // any later version.
    //
    // This program is distributed in the hope that it will be useful,
    // but WITHOUT ANY WARRANTY; without even the implied warranty of
    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    // GNU General Public License for more details.
    //
    // You should have received a copy of the GNU General Public License
    // along with this program; if not, write to the Free Software Foundation,
    // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    
    #include "ipc.h"
    
    #include "System.h"
    #include "GBA.h"
    #include "Globals.h"
    #include "Port.h"
    #include "Util.h"
    #include "NLS.h"
    
    #include <time.h>
    #include <nds/memory.h>//#include <memory.h> ichfly
    #include <nds/ndstypes.h>
    #include <nds/memory.h>
    #include <nds/bios.h>
    #include <nds/system.h>
    #include <nds/arm9/math.h>
    #include <nds/arm9/video.h>
    #include <nds/arm9/videoGL.h>
    #include <nds/arm9/trig_lut.h>
    #include <nds/arm9/sassert.h>
    
    enum RTCSTATE { IDLE, COMMAND, DATA, READDATA };
    
    typedef struct {
      u8 byte0;
      u8 byte1;
      u8 byte2;
      u8 command;
      int dataLen;
      int bits;
      RTCSTATE state;
      u8 data[12];
      // reserved variables for future
      u8 reserved[12];
      bool reserved2;
      u32 reserved3;
    } RTCCLOCKDATA;
    
    static RTCCLOCKDATA rtcClockData;
    static bool rtcEnabled = false;
    
    void rtcEnable(bool e)
    {
      rtcEnabled = e;
    }
    
    bool rtcIsEnabled()
    {
      return rtcEnabled;
    }
    
    u16 rtcRead(u32 address)
    {
      if(rtcEnabled) {
      if(address == 0x80000c8)
      return rtcClockData.byte2;
      else if(address == 0x80000c6)
      return rtcClockData.byte1;
      else if(address == 0x80000c4) {
      return rtcClockData.byte0;
      }
      }
    
      return READ16LE((&rom[address & 0x1FFFFFE])); //your little endian u16 read from gba map gets replaced here
    }
    
    static u8 toBCD(u8 value)
    {
      value = value % 100;
      int l = value % 10;
      int h = value / 10;
      return h * 16 + l;
    }
    
    bool rtcWrite(u32 address, u16 value)
    {
      if(!rtcEnabled)
      return false;
    
      if(address == 0x80000c8) {
      rtcClockData.byte2 = (u8)value; // enable ?
      } else if(address == 0x80000c6) {
      rtcClockData.byte1 = (u8)value; // read/write
      } else if(address == 0x80000c4) {
      if(rtcClockData.byte2 & 1) {
      if(rtcClockData.state == IDLE && rtcClockData.byte0 == 1 && value == 5) {
      rtcClockData.state = COMMAND;
      rtcClockData.bits = 0;
      rtcClockData.command = 0;
      } else if(!(rtcClockData.byte0 & 1) && (value & 1)) { // bit transfer
      rtcClockData.byte0 = (u8)value;
      switch(rtcClockData.state) {
      case COMMAND:
      rtcClockData.command |= ((value & 2) >> 1) << (7-rtcClockData.bits);
      rtcClockData.bits++;
      if(rtcClockData.bits == 8) {
      rtcClockData.bits = 0;
      switch(rtcClockData.command) {
      case 0x60:
      // not sure what this command does but it doesn't take parameters
      // maybe it is a reset or stop
      rtcClockData.state = IDLE;
      rtcClockData.bits = 0;
      break;
      case 0x62:
      // this sets the control state but not sure what those values are
      rtcClockData.state = READDATA;
      rtcClockData.dataLen = 1;
      break;
      case 0x63:
      rtcClockData.dataLen = 1;
      rtcClockData.data[0] = 0x40;
      rtcClockData.state = DATA;
      break;
      case 0x64:
      break;
      case 0x65:
      {
    
      /*
      struct tm *newtime;
      time_t long_time;
    
      time( &long_time );  // Get time as long integer.
      newtime = localtime( &long_time );// Convert to local time.
    
      rtcClockData.dataLen = 7;
      rtcClockData.data[0] = toBCD(newtime->tm_year);
      rtcClockData.data[1] = toBCD(newtime->tm_mon+1);
      rtcClockData.data[2] = toBCD(newtime->tm_mday);
      rtcClockData.data[3] = toBCD(newtime->tm_wday);
      rtcClockData.data[4] = toBCD(newtime->tm_hour);
      rtcClockData.data[5] = toBCD(newtime->tm_min);
      rtcClockData.data[6] = toBCD(newtime->tm_sec);
      rtcClockData.state = DATA;
      */
    
      //coto: own IPC.
      rtcClockData.dataLen = 7;
      rtcClockData.data[0] = toBCD(gba_get_yearbytertc());
      rtcClockData.data[1] = toBCD(gba_get_monthrtc());
      rtcClockData.data[2] = toBCD(gba_get_dayrtc());
      rtcClockData.data[3] = toBCD(gba_get_dayofweekrtc());
      rtcClockData.data[4] = toBCD(gba_get_hourrtc());
      rtcClockData.data[5] = toBCD(gba_get_minrtc());
      rtcClockData.data[6] = toBCD(gba_get_secrtc());
      rtcClockData.state = DATA;
    
      }
      break;
      case 0x67:
      {
      /*
      struct tm *newtime;
      time_t long_time;
    
      time( &long_time );  // Get time as long integer.
      newtime = localtime( &long_time ); // Convert to local time.
    
      rtcClockData.dataLen = 3;
      rtcClockData.data[0] = toBCD(newtime->tm_hour);
      rtcClockData.data[1] = toBCD(newtime->tm_min);
      rtcClockData.data[2] = toBCD(newtime->tm_sec);
      rtcClockData.state = DATA;
      */
    
      //coto: own IPC.
      rtcClockData.dataLen = 3;
      rtcClockData.data[0] = toBCD(gba_get_hourrtc());
      rtcClockData.data[1] = toBCD(gba_get_minrtc());
      rtcClockData.data[2] = toBCD(gba_get_secrtc());
      rtcClockData.state = DATA;
    
      }
      break;
      default:
      systemMessage(0, N_("Unknown RTC command %02x"), rtcClockData.command);
      rtcClockData.state = IDLE;
      break;
      }
      }
      break;
      case DATA:
      if(rtcClockData.byte1 & 2) {
      } else {
      rtcClockData.byte0 = (rtcClockData.byte0 & ~2) |
      ((rtcClockData.data[rtcClockData.bits >> 3] >>
      (rtcClockData.bits & 7)) & 1)*2;
      rtcClockData.bits++;
      if(rtcClockData.bits == 8*rtcClockData.dataLen) {
      rtcClockData.bits = 0;
      rtcClockData.state = IDLE;
      }
      }
      break;
      case READDATA:
      if(!(rtcClockData.byte1 & 2)) {
      } else {
      rtcClockData.data[rtcClockData.bits >> 3] =
      (rtcClockData.data[rtcClockData.bits >> 3] >> 1) |
      ((value << 6) & 128);
      rtcClockData.bits++;
      if(rtcClockData.bits == 8*rtcClockData.dataLen) {
      rtcClockData.bits = 0;
      rtcClockData.state = IDLE;
      }
      }
      break;
         default:
      break;
      }
      } else
      rtcClockData.byte0 = (u8)value;
      }
      }
      return true;
    }
    
    void rtcReset()
    {
      memset(&rtcClockData, 0, sizeof(rtcClockData));
    
      rtcClockData.byte0 = 0;
      rtcClockData.byte1 = 0;
      rtcClockData.byte2 = 0;
      rtcClockData.command = 0;
      rtcClockData.dataLen = 0;
      rtcClockData.bits = 0;
      rtcClockData.state = IDLE;
    }
    
    
    Then

    Code:
    //your little endian u16 write handler to gba map gets replaced here
    CPUWriteHalfWord(u32 address, u16 value){
      switch(address >> 24) {
      case 8:
      case 9:
      if(address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8) {
      if(!rtcWrite(address, value))
      goto unwritable;
      } else if(!agbPrintWrite(address, value)) goto unwritable;
      break;
      }
    
    }
    
    
    //your little endian u16 read handler from gba map gets replaced here
    u16 CPUReadHalfWord(u32 address){
    switch(address >> 24) {
      case 8:
      case 9:
      case 10:
      case 11:
      case 12:
      if(address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8)
      value = rtcRead(address);
      else
       {
         value = READ16LE(((u16 *)&rom[address & 0x1FFFFFE]));
       }
      break;
    
    }
    }
    
    

    so before gba execution begins you:
    Code:
    rtcReset();
    
    then
    
    rtcEnable(true); //nds7 RTC support.
    
    You could print the RTC values and see if they read the clock. Libnds does this but since we are in broken defaulttemplateland stuff like this must be done.

    edit: 06/12/2016 fixed SHARED_ADDR_REGION declaration usage across source files.
     
    Last edited by Coto, Dec 18, 2016
  12. DarkRioru

    DarkRioru reach for the stars
    Member

    Joined:
    Aug 29, 2015
    Messages:
    2,104
    Country:
    United States
    awesome! can it play games from a folder or is the runner.gba the only game I can run??
     
  13. Gericom

    OP Gericom GBAtemp Maniac
    Member

    Joined:
    Jun 30, 2011
    Messages:
    1,355
    Country:
    Netherlands
    This sounds like it should be quite straightforward to implement. I think I'll have a look at it.
    Currently it can only start runner.gba, but later on I want to implement a gui.
     
    TeamScriptKiddies, SLiV3R and Lunos like this.
  14. DaRk_ViVi

    DaRk_ViVi Sending you back... to the future!
    Member

    Joined:
    Apr 13, 2004
    Messages:
    1,087
    Country:
    Italy
    Great, I will test it ASAP!
    With the GUI coming in the future, would it be possible to provide precompiled .nds files that loads the bios.bin directly from the SD?
     
    TeamScriptKiddies likes this.
  15. Gericom

    OP Gericom GBAtemp Maniac
    Member

    Joined:
    Jun 30, 2011
    Messages:
    1,355
    Country:
    Netherlands
    Yes, I will be implementing that indeed later on. I was now mainly focusing on getting the games to run as good as possible.
     
    TeamScriptKiddies likes this.
  16. Coto

    Coto -
    Member

    Joined:
    Jun 4, 2010
    Messages:
    2,700
    Country:
    Chile
    Also remember that NIFI requires stable arm7 interrupts (if you ever want multiplayer working). Which is why I was asking to have a separate branch for ARM7 / ARM9 - libfat, C code (interrupts, timer cycles, IPC like the RTC example shown above). It will truly save you a lot of headaches once you start implementing more things that must be synced(which would be better to maintain to remove any race attack condition events).

    Also,if you run DSWIFI libs to sync at vblank nds clock cycle, its pretty stable.

    If you dont at least handle vblank properly in ARM9 NIFI will work but unstable (and socket-like services devkitpro, will cause lockups).

    edit: also I have flash/eeprom/sram handling like the RTC example working. If you are interested to see those examples (should be C code in my opinion) since it is not a timing dependant operation, unless you want to emulate the clockchip cycles (definitely not required)
     
    Last edited by Coto, Dec 6, 2016
    zfreeman likes this.
  17. xtheman

    xtheman GBAtemp Guru
    Member

    Joined:
    Jan 28, 2016
    Messages:
    5,837
    Country:
    United States
    This is great! I just ran this on my 3ds and it works perfectly
     
    TeamScriptKiddies likes this.
  18. Flame

    Flame Me > You
    Moderator

    Joined:
    Jul 15, 2008
    Messages:
    5,265
    great work. hope to see more of this project :yay:
     
    x65943 and TeamScriptKiddies like this.
  19. AtlasFontaine

    AtlasFontaine GBAtemp Maniac
    Member

    Joined:
    Jul 18, 2015
    Messages:
    1,095
    Country:
    Venezuela
    Tested Zelda minish cap (after SRAM patching it), it runs until the intro video, after ending the intro it crashes on black screen (graphics are messed up on title screen also).

    Tried Advanced Wars 2 Black Hole Rising but the game crashed right after the bios intro and showed this on the bottom screen:
    [​IMG]

    Castlevania Aria of Sorrow ran pretty good (60fps), I played it for 15 minutes.

    Completed the first level of Wario Land 4 and it worked perfectly.

    played Fire Emblem to the 2nd mission and it worked perfectly.
     
    Last edited by AtlasFontaine, Dec 6, 2016
  20. Gericom

    OP Gericom GBAtemp Maniac
    Member

    Joined:
    Jun 30, 2011
    Messages:
    1,355
    Country:
    Netherlands
    Thanks for your feedback, we really need a compatibility list like the one gbaemu4ds has. Would be interesting to compare compatibility too.
     
Draft saved Draft deleted
Loading...

Hide similar threads Similar threads with keywords - GBARunner2,