DS Game Boy Advance Mode

The GBA wireless adaptor is not compatible with the DS wireless hardware.

There are no new registers visible between 0x04000000 to 0x04000900 on the DS, when in GBA mode. However, the undocumeted system control register at 0x04000800 is gone.

There is no known way to detect the X/Y button or touch screen in GBA mode. An interesting bug found while looking for X and Y is that the KEYS register messes up if both L and R shoulder buttons are pushed at the same time. I went back and verified that this also occurs on a normal GBA.

All GBA flash cartridges work, except for ones that do not fit, such as:

  • Visoly Flash Advance (Turbo) 64M (too much plastic)
  • Visoly eXtreme Flash Advance (bad contact)
  • e-Reader

You can try to put the PCB in another case. Do not try to force a cartridge inside the DS, or you may end up causing damage to both the DS and cartridge.

Detecting an NDS

The GBA mode BIOS is virtually identical (1 bit differs in an unused region at the end), and can be dumped in the same fashion. You *can* detect if you are running on a DS from a GBA flash cart.

Code Snippet:

uint32 getChecksum(void) {
// Figure out what we're running on
uint32 result;
asm volatile("swi 0x0D\n"
"mov r0, %0\n"
: "=r"(result) : : "r1", "r2", "r3"
);
return result;
}

...

value = getChecksum();
if (value == 0xBAAE1880)
drawString(0, 19, "Nintendo DS detected");
else if (value == 0xBAAE187F)
drawString(0, 19, "Nintendo GBA detected");
else
drawString(0, 19, "Emulator detected");

Values were obtained from a real DS and a real GBA (original jpn model, but the SP bios is the same). The bit that is different (1 instead of 0), is at 0x3F0C, and is completly unused during any normal boot process. It is specifically and only there to be detected by a bios dump or get checksum call.

Detecting GBA vs NDS mode on the ARM7

The 16 bit register at 0x04000136 is REG_KEYXY on the NDS and an unused IR register on the GBA. In GBA mode all reads return zero, while in NDS mode all reads return a non-zero value.

Resetting to GBA mode from NDS mode

The following piece of code will make the DS go into GBA mode:

       .arm      mov    r2, #0x40      swi    0x1F0000    

Before switching to GBA mode, make sure to check the GBA mode screen selection setting in the Firmware settings. If it is set to the top screen, make sure to set the LCD swap bit in the POWER_CR (see Power Management) using the ARM9 CPU. Also turn off the unused screen from the ARM7 CPU, using the SPI.

GBA screen borders

It is possible to place a border in the unused portion of the screen before switching to GBA mode, to give a similar effect to the Super Game Boy. This must be done before switching to GBA mode, since no NDS features are available after the switch.

Steps for a border:

  1. Set the display mode to a 2D, non frame buffered mode. It is important to not use a direct frame buffer mode, as this will limit the GBA display to 30 fps.
  2. Set VRAM banks A and B to the main display. Both banks are needed. (See 2D Core
  3. Copy the border to both VRAM bank A (at address 0x06800000) and B (at address 0x06820000). The border is a 256 * 192 pixel, 16 BPP bitmap, with the outer edges used as the visible in GBA mode. It must be copied to both banks, otherwise the screen will flicker due to the page flipping used by the hardware.
  4. Swap the LCD screens appropriate to the firmware settings, and turn off the unused screen.
  5. Restart in GBA mode.