Well, i was trying to allow SEDS to be distributed as a single .nds file, while it actually requires plenty of stubs to be installed on the flash card in order to re-load fresh updates of itself (or to return to the “runme” root program). Making sure that stubs (and runme) are downloaded on demand was quite easy, but then i stumbled upon an unexpected difficulty: DLDI patching.
As most modern linkers perform that “driver patching” automatically when loading our homebrew, we tend to forget that they even exists (especially me, since i’m owning a pre-DLDI linker that works with built-in drivers of the libfat :P). Arialia first notified me of that i was missing something in the process… Then began the hide-and-seek game with (undocumented?) process of loading and patching code with DLDI drivers.
A bit of googling could not locate chishm’s source for the NDS loader, but crawling the forum did. One of the nice things chishm does in his loader is to reuse the DLDI driver of the current binary to patch the loader (and the program to be loaded). Let’s see how it works.
pDH = (data_t*)(((u32*)(&_io_dldi)) -24);
pAH = &(binData[patchOffset]);
The first entry in the IOinterfaces table is reserved for DLDI devices. Note that the DLDI patcher will *keep* this “placeholder” interface so that, once patched, the driver’s description is still at _io_dldi ^_^. Moreover, right before the actual ioInterface structure, we can find a placeholder for the DLDI header, including code/data sizes, and location of the Global Offset Table required for patching.
if (*((u32*)(pDH + DO_ioType)) == DEVICE_TYPE_DLDI) {
// No DLDI patch
return false;
}
One of the tricks involved is that, if no DLDI driver is installed, the ioInterface’s “type” is set at compile-time to the “DLDI” string. Once patched, it gets replaced with the vendor/product mini-id (e.g. SCSD for Supercard, securedigital or MPCF for “media player, compactflash”, etc).
The rest is just going smoothly. I initially feared that the restriction of 16-bits access to the VRAM would doom the entire loading process, but obviously, it does not apply when VRAM is mapped as “LCD” (plain CPU access, offscreen). That’s nice.
ARM9: FIFO Init>ARM7: Booting>ARM7: Ready>ARM9: FAT Init>>Guru Meditation Error!>data abort!>pc: 0ffffffc addr: 0ffffffc>r0: 04000200>r1 06865960>r2 0000e000>r3 0000e880>r4 023f001c>r5 06820000>r6 00000000>r7 00000000>r8: 00000000>r9 00000000>r10 00000000>r11 00000000>r12 0b0bb910>sp 0b003cc8>lr 06861174>pc 10000004>>stack : 0 06865298 0 06820000 0 0 0 0 > 0 6860e64 0B000000 0 0 0680164 0*
LikeLike
>_< i just managed to get the patched exec_stub.arm9 dumped to a file... all the edited areas are garbage :P>>e.g. i have text_start = 0x0b0bb2c0 while i’d have expected 0x6865900 (from manually patched stub)…
LikeLike
“Position in file : 00005900>position in memory: 06865900>patch base address: 0200ff80>relocation offset : 04855980>patched successfully.
LikeLike