Note: This document doesn't document all existing devices. Check this instead: https://github.com/blocksds/libnds/blob/2d947e6a6709e646c3366425a840167f2ef5e9c1/source/arm9/peripherals/slot2.c
Author: AntonioND (antonio underscore nd at outlook dot com).
There are some GBA cartridges that have RAM chips and that can be inserted in the slot 2 of a Nintendo DS to provide additional RAM for the program running on the console. For example, the Nintendo DS Browser (which is a port of Opera) came with an official RAM expansion pack. There are also several unofficial RAM cartridges that can be used the same way. This document explains how to use the expansion cartridges from homebrew applications.
The documentation doesn't specify the size of any of the RAM chips. It simply autodetects the size by trying to write to the base address, reading from it, checking if the value is the expected one, and retrying after 512 KB. This seems to have been enough, which means that the RAM chips probably don't mirror. If they did, that routine wouldn't work.
Note that I have only been able to test on a SuperCard SD, as it is the only one I own. I have obtained the information below by reading other code and documentation found online, and the purpose of this document is for developers to be able to write new code that can interact with the expansion cartridges, and license it under their own terms, instead of using pre-made libraries.
Important notes:
- Remember to set the bus owner correctly to access the slot-2. For example, for the ARM9:
sysSetBusOwners(BUS_OWNER_ARM9, BUS_OWNER_ARM9);
- It is not possible to perform 8-bit writes to the RAM expansion cartridges. It is possible to read 8, 16 or 32 bits, and write 16 or 32 bits.
- Base address: 0x8000000
- The function to change mode is a series of 16-bit writes to address 0x9FFFFFE:
0xA55A 0xA55A mode mode
- Unlock: The mode value for RAM_RW is 0x5.
- Lock: The mode value for MEDIA is 0x3.
- Base address: 0x8000000
- The function to change mode seems to be a series of 16-bit reads. The read values are discarded:
0x08E00002 0x0800000E 0x08801FFC 0x0800104A 0x08800612 0x08000000 0x08801B66 0x08000000 + (mode << 1) 0x0800080E 0x08000000 0x080001E4 0x080001E4 0x08000188 0x08000188
- Unlock: The mode value for RAM_RW is 0x00400006
- Lock: The mode value for MEDIA is 0x00400003
- Base address: 0x9000000
- Unlock: Write 1 to 0x8240000.
- Lock: Write 0 to 0x8240000.
- Base address: 0x8000000
- The function to change mode seems to be a series of 16-bit reads. The read values are discarded:
0x09000000 0x09FFFFE0 0x09FFFFEC 0x09FFFFEC 0x09FFFFEC 0x09FFFFFC 0x09FFFFFC 0x09FFFFFC 0x09FFFF4A 0x09FFFF4A 0x09FFFF4A 0x09200000 + (mode << 1) 0x09FFFFF0 0x09FFFFE8
- Unlock: The mode value for RAM_RW is 6
- Lock: The mode value for MEDIA is 3
Base address: 0x8400000
The code for this cartridge is unusual. There are no lock or unlock functions, but the test routine tries to unlock two different ROM pages. All the described commands work by using 16-bit writes.
All commands sent to the EZ cartridge start by a "command start" routine:
0x9FE0000 = 0xD200 0x8000000 = 0x1500 0x8020000 = 0xD200 0x8040000 = 0x1500
Then, the command body is sent. After the command is sent, the "command end" routine is:
0x9FC0000 = 0x1500
The known commands that can be used as command body are:
- Set ROM page:
0x9880000 = page
- Enable NOR write:
0x9C40000 = 0x1500
- Disable NOR write:
0x9C40000 = 0xD200
The test function sets the ROM page to OS mode (page 0x8000). Then, it enables NOR writing, and checks if address 0x08400000 can be written (and it also checks that address 0x08000000 can't be written). If the conditions are met, this page can be used and no more tests are required.
If that page fails, you need to disable NOR writing, set the ROM page to 352 (why?), and enable NOR writing again. This time, only check if address 0x08400000 can be written.
My proposal would be to run the test command during the first "unlock" run, and save in a variable the ROM page that has worked. Then, we should be able to unlock and unlock the RAM by using the enable/disable NOR write commands.