diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..5cc2dca4 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "libnds32"] + path = libnds32 + url = https://github.com/lifehackerhansol/libnds32 diff --git a/Makefile b/Makefile index 814700ed..c86487bd 100644 --- a/Makefile +++ b/Makefile @@ -37,6 +37,7 @@ arm7/$(TARGET).elf: #--------------------------------------------------------------------------------- arm9/$(TARGET).elf: + @$(MAKE) -C libnds32 release @$(MAKE) -C arm9 #--------------------------------------------------------------------------------- @@ -50,6 +51,7 @@ clean: @rm -fr $(BUILD) $(TARGET).elf $(TARGET).nds @rm -fr $(TARGET).arm7.elf @rm -fr $(TARGET).arm9.elf + @$(MAKE) -C libnds32 clean @$(MAKE) -C bootloader clean @$(MAKE) -C bootstub clean @$(MAKE) -C arm9 clean diff --git a/README.md b/README.md index d775b2e6..5e0d738a 100644 --- a/README.md +++ b/README.md @@ -57,29 +57,30 @@ GodMode9i uses the same FRF font files as [GodMode9](https://github.com/d0k3/God When loading GodMode9i will try to load `/gm9i/font.frf` on your SD card and if that fails will load the default font. To change the default font when building GodMode9i, replace `data/font_default.frf` with your font. ## Credits -* [RocketRobz](https://github.com/RocketRobz): Main Developer. -* [Evie/Pk11](https://github.com/Epicpkmn11): Contributor. -* [zacchi4k](https://github.com/zacchi4k): Logo designer. -* [Edo9300](https://github.com/edo9300): Save reading code from his save manager tool. -* [endrift](https://github.com/endrift): GBA ROM dumping code from [duplo](https://github.com/endrift/duplo), used for 64MB ROMs. -* [JimmyZ](https://github.com/JimmyZ): NAND code from twlnf (with writing code stripped for safety reasons). -* [zoogie](https://github.com/zoogie): ConsoleID code (originating from dumpTool). -* [devkitPro](https://github.com/devkitPro): devkitARM, libnds, original nds-hb-menu code, and screenshot code. -* [d0k3](https://github.com/d0k3): Developer of GodMode9 for the Nintendo 3DS, which this is inspired by. -* [門真 なむ (Num Kadoma)](https://littlelimit.net): k6x8 font used for the default font's Kanji and 美咲ゴシック font in resources folder - * Additional Chinese is from [Angelic47/FontChinese7x7](https://github.com/Angelic47/FontChinese7x7) +- [RocketRobz](https://github.com/RocketRobz): Main Developer. +- [Evie/Pk11](https://github.com/Epicpkmn11): Contributor. +- [lifehackerhansol](https://github.com/lifehackerhansol): [libnds32](https://github.com/lifehackerhansol/libnds32) fork for 32KB DLDI driver support +- [zacchi4k](https://github.com/zacchi4k): Logo designer. +- [Edo9300](https://github.com/edo9300): Save reading code from his save manager tool. +- [endrift](https://github.com/endrift): GBA ROM dumping code from [duplo](https://github.com/endrift/duplo), used for 64MB ROMs. +- [JimmyZ](https://github.com/JimmyZ): NAND code from twlnf (with writing code stripped for safety reasons). +- [zoogie](https://github.com/zoogie): ConsoleID code (originating from dumpTool). +- [devkitPro](https://github.com/devkitPro): devkitARM, libnds, original nds-hb-menu code, and screenshot code. +- [d0k3](https://github.com/d0k3): Developer of GodMode9 for the Nintendo 3DS, which this is inspired by. +- [門真 なむ (Num Kadoma)](https://littlelimit.net): k6x8 font used for the default font's Kanji and 美咲ゴシック font in resources folder + - Additional Chinese is from [Angelic47/FontChinese7x7](https://github.com/Angelic47/FontChinese7x7) ### Translators -* Chinese (Simplified): [cai_miao](https://crowdin.com/profile/cai_miao), [James-Makoto](https://crowdin.com/profile/vcmod55) -* Dutch: [Minionguyjpro](https://crowdin.com/profile/minionguyjpro) -* French: [Benjamin](https://crowdin.com/profile/sombrabsol), [Dhalian.](https://crowdin.com/profile/dhalian3630) -* German: [redstonekasi](https://crowdin.com/profile/redstonekasi) -* Hebrew: [Yaniv Levin](https://crowdin.com/profile/y4niv) -* Hungarian: [Viktor Varga](http://github.com/vargaviktor) -* Italian: [Malick](https://crowdin.com/profile/malick1160), [TM-47](https://crowdin.com/profile/-tm-), [zacchi4k](https://crowdin.com/profile/zacchi4k) -* Japanese: [Cloud0835](https://crowdin.com/profile/cloud0835), [Pk11](https://github.com/Epicpkmn11) -* Romanian: [Tescu](https://crowdin.com/profile/tescu48) -* Russian: [Ckau](https://crowdin.com/profile/ckau), [Молодая Кукуруза](https://crowdin.com/profile/bessmertnyi_mikhail) -* Spanish: [Allinxter](https://crowdin.com/profile/allinxter), [beta215](https://crowdin.com/profile/beta215) -* Turkish: [Egehan.TWL](https://crowdin.com/profile/egehan.twl), [Grandmaquil](https://crowdin.com/profile/grandmaquil), [rewold20](https://crowdin.com/profile/rewold20) -* Ukrainian: [GriShafir](https://crowdin.com/profile/grishafir) +- Chinese (Simplified): [cai_miao](https://crowdin.com/profile/cai_miao), [James-Makoto](https://crowdin.com/profile/vcmod55) +- Dutch: [Minionguyjpro](https://crowdin.com/profile/minionguyjpro) +- French: [Benjamin](https://crowdin.com/profile/sombrabsol), [Dhalian.](https://crowdin.com/profile/dhalian3630) +- German: [redstonekasi](https://crowdin.com/profile/redstonekasi) +- Hebrew: [Yaniv Levin](https://crowdin.com/profile/y4niv) +- Hungarian: [Viktor Varga](http://github.com/vargaviktor) +- Italian: [Malick](https://crowdin.com/profile/malick1160), [TM-47](https://crowdin.com/profile/-tm-), [zacchi4k](https://crowdin.com/profile/zacchi4k) +- Japanese: [Cloud0835](https://crowdin.com/profile/cloud0835), [Pk11](https://github.com/Epicpkmn11) +- Romanian: [Tescu](https://crowdin.com/profile/tescu48) +- Russian: [Ckau](https://crowdin.com/profile/ckau), [Молодая Кукуруза](https://crowdin.com/profile/bessmertnyi_mikhail) +- Spanish: [Allinxter](https://crowdin.com/profile/allinxter), [beta215](https://crowdin.com/profile/beta215) +- Turkish: [Egehan.TWL](https://crowdin.com/profile/egehan.twl), [Grandmaquil](https://crowdin.com/profile/grandmaquil), [rewold20](https://crowdin.com/profile/rewold20) +- Ukrainian: [GriShafir](https://crowdin.com/profile/grishafir) diff --git a/arm9/Makefile b/arm9/Makefile index 8fca3f43..e059fdce 100644 --- a/arm9/Makefile +++ b/arm9/Makefile @@ -61,13 +61,14 @@ LDFLAGS = -specs=../ds_arm9_hi.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) #--------------------------------------------------------------------------------- # any extra libraries we wish to link with the project (order is important) #--------------------------------------------------------------------------------- -LIBS := -lfat -lnds9 +LIBS := -lfat -lnds329 #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing # include and lib #--------------------------------------------------------------------------------- LIBDIRS := $(CURDIR) ../ $(LIBNDS) +LIBDIRS32 := $(CURDIR)/../libnds32 #--------------------------------------------------------------------------------- # no real need to edit anything past this point unless you need to add additional @@ -114,7 +115,8 @@ export INCLUDE := $(foreach dir,$(INCLUDES),-iquote $(CURDIR)/$(dir)) \ $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ -I$(CURDIR)/$(BUILD) -export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \ + $(foreach dir,$(LIBDIRS32),-L$(dir)/lib) export OUTPUT := $(CURDIR)/$(TARGET) diff --git a/arm9/source/main.cpp b/arm9/source/main.cpp index 527ff7b7..27fbce9f 100644 --- a/arm9/source/main.cpp +++ b/arm9/source/main.cpp @@ -266,6 +266,14 @@ int main(int argc, char **argv) { swiWaitForVBlank(); } + if (nitroMounted && (strcmp(io_dldi_data->friendlyName, "NAND FLASH CARD LIBFATNRIO") == 0) && (*(u32*)0x02FF8000 != 0x53535A4C)) { + FILE* file = fopen("nitro:/dldi/nrio.lz77", "rb"); + fread((void*)0x02FF8004, 1, 0x3FFC, file); + fclose(file); + + *(u32*)0x02FF8000 = 0x53535A4C; + } + // Ensure gm9i folder exists char folderPath[10]; sprintf(folderPath, "%s:/gm9i", (sdMounted ? "sd" : "fat")); diff --git a/arm9/source/nds_loader_arm9.c b/arm9/source/nds_loader_arm9.c index be250dcd..33526b11 100644 --- a/arm9/source/nds_loader_arm9.c +++ b/arm9/source/nds_loader_arm9.c @@ -31,11 +31,19 @@ #include "tonccpy.h" #ifndef _NO_BOOTSTUB_ +struct __my_bootstub { + u64 bootsig; + VoidFn arm9reboot; + VoidFn arm7reboot; + u32 bootaddr; + u32 bootsize; +}; + #include "bootstub_bin.h" #endif #include "nds_loader_arm9.h" -#define LCDC_BANK_C (u16*)0x06840000 +#define LCDC_BANK_C (u16*)0x06848000 #define STORED_FILE_CLUSTER (*(((u32*)LCDC_BANK_C) + 1)) #define INIT_DISC (*(((u32*)LCDC_BANK_C) + 2)) #define WANT_TO_PATCH_DLDI (*(((u32*)LCDC_BANK_C) + 3)) @@ -120,7 +128,7 @@ static void writeAddr (data_t *mem, addr_t offset, addr_t value) { ((addr_t*)mem)[offset/sizeof(addr_t)] = value; } -static addr_t quickFind (const data_t* data, const data_t* search, size_t dataLen, size_t searchLen) { +/* static addr_t quickFind (const data_t* data, const data_t* search, size_t dataLen, size_t searchLen) { const int* dataChunk = (const int*) data; int searchChunk = ((const int*)search)[0]; addr_t i; @@ -138,18 +146,17 @@ static addr_t quickFind (const data_t* data, const data_t* search, size_t dataLe } return -1; -} +} */ // Normal DLDI uses "\xED\xA5\x8D\xBF Chishm" // Bootloader string is different to avoid being patched -static const data_t dldiMagicLoaderString[] = "\xEE\xA5\x8D\xBF Chishm"; // Different to a normal DLDI file +// static const data_t dldiMagicLoaderString[] = "\xEE\xA5\x8D\xBF Chishm"; // Different to a normal DLDI file #define DEVICE_TYPE_DLDI 0x49444C44 -static bool dldiPatchLoader (data_t *binData, u32 binSize, bool clearBSS) +static bool dldiPatchLoader (void) { addr_t memOffset; // Offset of DLDI after the file is loaded into memory - addr_t patchOffset; // Position of patch destination in the file addr_t relocationOffset; // Value added to all offsets within the patch to fix it properly addr_t ddmemOffset; // Original offset used in the DLDI file addr_t ddmemStart; // Start of range that offsets can be in the DLDI file @@ -158,39 +165,28 @@ static bool dldiPatchLoader (data_t *binData, u32 binSize, bool clearBSS) addr_t addrIter; - data_t *pDH; - data_t *pAH; - size_t dldiFileSize = 0; - - // Find the DLDI reserved space in the file - patchOffset = quickFind (binData, dldiMagicLoaderString, binSize, sizeof(dldiMagicLoaderString)); - if (patchOffset < 0) { - // does not have a DLDI section - return false; - } + data_t *pDH = (data_t*)(io_dldi_data); - pDH = (data_t*)(io_dldi_data); - - pAH = &(binData[patchOffset]); + data_t *pAH = (data_t*)0x02FF8000; if (*((u32*)(pDH + DO_ioType)) == DEVICE_TYPE_DLDI) { // No DLDI patch return false; } - if (pDH[DO_driverSize] > pAH[DO_allocatedSpace]) { - // Not enough space for patch - return false; + if (*(u32*)0x02FF8004 == 0x69684320 || *(u32*)0x02FF8000 == 0x53535A4C) { + return true; // Skip patching for existing or compressed DLDI file } - + dldiFileSize = 1 << pDH[DO_driverSize]; - memOffset = readAddr (pAH, DO_text_start); + /* memOffset = readAddr (pAH, DO_text_start); if (memOffset == 0) { memOffset = readAddr (pAH, DO_startup) - DO_code; - } + } */ + memOffset = 0x06000000; ddmemOffset = readAddr (pDH, DO_text_start); relocationOffset = memOffset - ddmemOffset; @@ -201,7 +197,7 @@ static bool dldiPatchLoader (data_t *binData, u32 binSize, bool clearBSS) // Remember how much space is actually reserved pDH[DO_allocatedSpace] = pAH[DO_allocatedSpace]; // Copy the DLDI patch into the application - tonccpy (pAH, pDH, dldiFileSize); + tonccpy (pAH, pDH, (dldiFileSize > 0x4000) ? 0x4000 : dldiFileSize); // Fix the section pointers in the header writeAddr (pAH, DO_text_start, readAddr (pAH, DO_text_start) + relocationOffset); @@ -220,7 +216,7 @@ static bool dldiPatchLoader (data_t *binData, u32 binSize, bool clearBSS) writeAddr (pAH, DO_clearStatus, readAddr (pAH, DO_clearStatus) + relocationOffset); writeAddr (pAH, DO_shutdown, readAddr (pAH, DO_shutdown) + relocationOffset); - if (pDH[DO_fixSections] & FIX_ALL) { + if (pDH[DO_fixSections] & FIX_ALL) { // Search through and fix pointers within the data section of the file for (addrIter = (readAddr(pDH, DO_text_start) - ddmemStart); addrIter < (readAddr(pDH, DO_data_end) - ddmemStart); addrIter++) { if ((ddmemStart <= readAddr(pAH, addrIter)) && (readAddr(pAH, addrIter) < ddmemEnd)) { @@ -229,7 +225,7 @@ static bool dldiPatchLoader (data_t *binData, u32 binSize, bool clearBSS) } } - if (pDH[DO_fixSections] & FIX_GLUE) { + if (pDH[DO_fixSections] & FIX_GLUE) { // Search through and fix pointers within the glue section of the file for (addrIter = (readAddr(pDH, DO_glue_start) - ddmemStart); addrIter < (readAddr(pDH, DO_glue_end) - ddmemStart); addrIter++) { if ((ddmemStart <= readAddr(pAH, addrIter)) && (readAddr(pAH, addrIter) < ddmemEnd)) { @@ -238,7 +234,7 @@ static bool dldiPatchLoader (data_t *binData, u32 binSize, bool clearBSS) } } - if (pDH[DO_fixSections] & FIX_GOT) { + if (pDH[DO_fixSections] & FIX_GOT) { // Search through and fix pointers within the Global Offset Table section of the file for (addrIter = (readAddr(pDH, DO_got_start) - ddmemStart); addrIter < (readAddr(pDH, DO_got_end) - ddmemStart); addrIter++) { if ((ddmemStart <= readAddr(pAH, addrIter)) && (readAddr(pAH, addrIter) < ddmemEnd)) { @@ -247,7 +243,7 @@ static bool dldiPatchLoader (data_t *binData, u32 binSize, bool clearBSS) } } - if (clearBSS && (pDH[DO_fixSections] & FIX_BSS)) { + if (/* clearBSS && */ (pDH[DO_fixSections] & FIX_BSS) && dldiFileSize <= 0x4000) { // Initialise the BSS to 0, only if the disc is being re-inited toncset (&pAH[readAddr(pDH, DO_bss_start) - ddmemStart] , 0, readAddr(pDH, DO_bss_end) - readAddr(pDH, DO_bss_start)); } @@ -321,7 +317,7 @@ int runNds (const void* loader, u32 loaderSize, u32 cluster, bool initDisc, bool if(dldiPatchNds) { // Patch the loader with a DLDI for the card - if (!dldiPatchLoader ((data_t*)LCDC_BANK_C, loaderSize, initDisc)) { + if (!dldiPatchLoader()) { return 3; } } @@ -348,7 +344,7 @@ int runNdsFile (const char* filename, int argc, const char** argv) { int pathLen; const char* args[1]; - + if (stat (filename, &st) < 0) { return 1; } @@ -372,8 +368,10 @@ int runNdsFile (const char* filename, int argc, const char** argv) { bool havedsiSD = false; if(argv[0][0]=='s' && argv[0][1]=='d') havedsiSD = true; - + + #ifndef _NO_BOOTSTUB_ installBootStub(havedsiSD); + #endif return runNds (load_bin, load_bin_size, st.st_ino, true, true, argc, argv); } @@ -398,34 +396,32 @@ int runNdsFile (const char* filename, int argc, const char** argv) { .word 0 */ -bool installBootStub(bool havedsiSD) { #ifndef _NO_BOOTSTUB_ +bool installBootStub(const bool havedsiSD) { extern char *fake_heap_end; - struct __bootstub *bootstub = (struct __bootstub *)fake_heap_end; + struct __my_bootstub *bootstub = (struct __my_bootstub *)fake_heap_end; u32 *bootloader = (u32*)(fake_heap_end+bootstub_bin_size); - memcpy(bootstub,bootstub_bin,bootstub_bin_size); - memcpy(bootloader,load_bin,load_bin_size); - bool ret = false; + tonccpy(bootstub,bootstub_bin,bootstub_bin_size); + tonccpy(bootloader,load_bin,load_bin_size); bootloader[8] = isDSiMode(); - if( havedsiSD) { - ret = true; - bootloader[3] = 0; // don't dldi patch + if (havedsiSD) { + if (memcmp(io_dldi_data->friendlyName, "Default", 7) != 0) { + dldiPatchLoader (); + } else { + bootloader[3] = 0; // don't dldi patch + } bootloader[7] = 1; // use internal dsi SD code } else { - ret = dldiPatchLoader((data_t*)bootloader, load_bin_size,false); + dldiPatchLoader (); } bootstub->arm9reboot = (VoidFn)(((u32)bootstub->arm9reboot)+fake_heap_end); bootstub->arm7reboot = (VoidFn)(((u32)bootstub->arm7reboot)+fake_heap_end); + bootstub->bootaddr += (u32)fake_heap_end; bootstub->bootsize = load_bin_size; DC_FlushAll(); - - return ret; -#else - return true; -#endif - } +#endif diff --git a/arm9/source/nds_loader_arm9.h b/arm9/source/nds_loader_arm9.h index 8d03d774..06c9997b 100644 --- a/arm9/source/nds_loader_arm9.h +++ b/arm9/source/nds_loader_arm9.h @@ -33,7 +33,7 @@ int runNds (const void* loader, u32 loaderSize, u32 cluster, bool initDisc, bool int runNdsFile (const char* filename, int argc, const char** argv); -bool installBootStub(bool havedsiSD); +void installBootStub(const bool havedsiSD); #ifdef __cplusplus } diff --git a/bootloader/load.ld b/bootloader/load.ld index 53f37287..566c3e6d 100644 --- a/bootloader/load.ld +++ b/bootloader/load.ld @@ -4,7 +4,7 @@ ENTRY(_start) MEMORY { - vram : ORIGIN = 0x06000000, LENGTH = 128K + vram : ORIGIN = 0x06008000, LENGTH = 128K - 32K } __vram_start = ORIGIN(vram); diff --git a/bootloader/source/boot.c b/bootloader/source/boot.c index 6c691599..e8392ae9 100644 --- a/bootloader/source/boot.c +++ b/bootloader/source/boot.c @@ -137,8 +137,9 @@ void passArgs_ARM7 (void) { argDst = (u32*)((ARM9_DST + ARM9_LEN + 3) & ~3); // Word aligned - if (dsiMode && (*(u8*)(NDS_HEAD + 0x012) & BIT(1))) - { + if (ARM9_LEN > 0x380000) { + argDst = (u32*)(TEMP_MEM - ((argSize/4)*4)); + } else if (dsiMode && (*(u8*)(NDS_HEAD + 0x012) & BIT(1))) { u32 ARM9i_DST = *((u32*)(TWL_HEAD + 0x1C8)); u32 ARM9i_LEN = *((u32*)(TWL_HEAD + 0x1CC)); if (ARM9i_LEN) @@ -334,6 +335,25 @@ int main (void) { #ifndef NO_SDMMC sdRead = (dsiSD && dsiMode); #endif + if (wantToPatchDLDI) { + toncset((u32*)0x06000000, 0, 0x8000); + if (*(u32*)0x02FF4184 == 0x69684320) { // DLDI ' Chi' string in bootstub space + bootloader in DLDI driver space + const u16 dldiFileSize = 1 << *(u8*)0x02FF418D; + tonccpy((u32*)0x06000000, (u32*)0x02FF4180, dldiFileSize); + dldiRelocateBinary(); + + toncset((u32*)0x02FF4000, 0, 0x8180); // Clear bootstub + DLDI driver + } else if (*(u32*)0x02FF8004 == 0x69684320) { // DLDI ' Chi' string + const u16 dldiFileSize = 1 << *(u8*)0x02FF800D; + tonccpy((u32*)0x06000000, (u32*)0x02FF8000, (dldiFileSize > 0x4000) ? 0x4000 : dldiFileSize); + dldiClearBss(); + } else if (*(u32*)0x02FF8000 == 0x53535A4C) { // LZ77 flag + dldiDecompressBinary(); + } else { + return -1; + } + } + u32 fileCluster = storedFileCluster; // Init card if(!FAT_InitFiles(initDisc)) diff --git a/bootloader/source/dldi_patcher.c b/bootloader/source/dldi_patcher.c index 13656f72..a7c38380 100644 --- a/bootloader/source/dldi_patcher.c +++ b/bootloader/source/dldi_patcher.c @@ -22,6 +22,7 @@ #ifndef NO_DLDI #include #include +#include "tonccpy.h" #include "dldi_patcher.h" #define FIX_ALL 0x01 @@ -76,7 +77,7 @@ static addr_t quickFind (const data_t* data, const data_t* search, size_t dataLe addr_t i; addr_t dataChunkEnd = (addr_t)(dataLen / sizeof(int)); - for ( i = 0; i < dataChunkEnd; i++) { + for (i = 0; i < dataChunkEnd; i++) { if (dataChunk[i] == searchChunk) { if ((i*sizeof(int) + searchLen) > dataLen) { return -1; @@ -90,11 +91,25 @@ static addr_t quickFind (const data_t* data, const data_t* search, size_t dataLe return -1; } -static const data_t dldiMagicString[] = "\xED\xA5\x8D\xBF Chishm"; // Normal DLDI file -static const data_t dldiMagicLoaderString[] = "\xEE\xA5\x8D\xBF Chishm"; // Different to a normal DLDI file +// Strings are stored with bit 0x20 flipped (case inverted) to prevent accidental DLDI patching of them +#define DLDI_MAGIC_LEN 12 +#define DLDI_MAGIC_MANGLE_VALUE 0x20 +static const data_t dldiMagicStringMangled[DLDI_MAGIC_LEN] = "\xCD\x85\xAD\x9F\0cHISHM"; // Normal DLDI file + +// Demangle the magic string by XORing every byte with 0x20, except the NULL terminator +static void demangleMagicString(data_t *dest, const data_t *src) { + int i; + + memcpy(dest, src, DLDI_MAGIC_LEN); + for (i = 0; i < DLDI_MAGIC_LEN - 1; ++i) { + dest[i] ^= DLDI_MAGIC_MANGLE_VALUE; + } +} + #define DEVICE_TYPE_DLDI 0x49444C44 -extern const u32 _io_dldi; +extern unsigned long dsiMode; +static data_t* _dldi_start = (data_t*)0x06000000; bool dldiPatchBinary (data_t *binData, u32 binSize) { @@ -110,17 +125,19 @@ bool dldiPatchBinary (data_t *binData, u32 binSize) { data_t *pDH; data_t *pAH; + data_t dldiMagicString[DLDI_MAGIC_LEN]; size_t dldiFileSize = 0; - + // Find the DLDI reserved space in the file - patchOffset = quickFind (binData, dldiMagicString, binSize, sizeof(dldiMagicLoaderString)); + demangleMagicString(dldiMagicString, dldiMagicStringMangled); + patchOffset = quickFind (binData, dldiMagicString, binSize, sizeof(dldiMagicString)); if (patchOffset < 0) { // does not have a DLDI section return false; } - pDH = (data_t*)(((u32*)(&_io_dldi)) - 24); + pDH = _dldi_start; pAH = &(binData[patchOffset]); if (*((u32*)(pDH + DO_ioType)) == DEVICE_TYPE_DLDI) { @@ -128,17 +145,34 @@ bool dldiPatchBinary (data_t *binData, u32 binSize) { return false; } - if (pDH[DO_driverSize] > pAH[DO_allocatedSpace]) { - // Not enough space for patch - return false; - } - dldiFileSize = 1 << pDH[DO_driverSize]; memOffset = readAddr (pAH, DO_text_start); if (memOffset == 0) { memOffset = readAddr (pAH, DO_startup) - DO_code; } + + const bool largeDldi = (pDH[DO_driverSize] > pAH[DO_allocatedSpace]); + + if (largeDldi) { + if (memOffset < 0x02000000 || memOffset >= 0x03000000) { + // Not enough space for patch in arm7 WRAM + return false; + } + + // u32** bootloader = (u32**)0x02FF4010; + const u32* bootloader = (u32*)0x02FF4168; + const u32 bootsize = *(u32*)0x02FF4014; + + tonccpy (pAH+DO_code, bootloader, bootsize); + *(u32*)0x02FF4010 = (u32)pAH+DO_code; + + // Relocate DLDI file to bootstub RAM space + pAH = (data_t*)(dsiMode ? 0x02FF4180 : 0x023F4180); + toncset (pAH, 0, 0x8000); + + memOffset = (addr_t)pAH; + } ddmemOffset = readAddr (pDH, DO_text_start); relocationOffset = memOffset - ddmemOffset; @@ -149,7 +183,7 @@ bool dldiPatchBinary (data_t *binData, u32 binSize) { // Remember how much space is actually reserved pDH[DO_allocatedSpace] = pAH[DO_allocatedSpace]; // Copy the DLDI patch into the application - memcpy (pAH, pDH, dldiFileSize); + tonccpy (pAH, pDH, dldiFileSize); // Fix the section pointers in the header writeAddr (pAH, DO_text_start, readAddr (pAH, DO_text_start) + relocationOffset); @@ -169,7 +203,7 @@ bool dldiPatchBinary (data_t *binData, u32 binSize) { writeAddr (pAH, DO_shutdown, readAddr (pAH, DO_shutdown) + relocationOffset); // Put the correct DLDI magic string back into the DLDI header - memcpy (pAH, dldiMagicString, sizeof (dldiMagicString)); + tonccpy (pAH, dldiMagicString, sizeof (dldiMagicString)); if (pDH[DO_fixSections] & FIX_ALL) { // Search through and fix pointers within the data section of the file @@ -200,9 +234,104 @@ bool dldiPatchBinary (data_t *binData, u32 binSize) { if (pDH[DO_fixSections] & FIX_BSS) { // Initialise the BSS to 0 - memset (&pAH[readAddr(pDH, DO_bss_start) - ddmemStart] , 0, readAddr(pDH, DO_bss_end) - readAddr(pDH, DO_bss_start)); + toncset (&pAH[readAddr(pDH, DO_bss_start) - ddmemStart] , 0, readAddr(pDH, DO_bss_end) - readAddr(pDH, DO_bss_start)); + } + + if (largeDldi) { + data_t* pAH2 = &(binData[patchOffset]); + tonccpy (pAH2, pAH, DO_code); } return true; } + +void dldiDecompressBinary (void) { + extern void LZ77_Decompress(u8* source, u8* destination); + LZ77_Decompress((u8*)0x02FF8004, (u8*)_dldi_start); + + dldiRelocateBinary(); +} + +void dldiRelocateBinary (void) { + addr_t memOffset; // Offset of DLDI after the file is loaded into memory + addr_t relocationOffset; // Value added to all offsets within the patch to fix it properly + addr_t ddmemOffset; // Original offset used in the DLDI file + addr_t ddmemStart; // Start of range that offsets can be in the DLDI file + addr_t ddmemEnd; // End of range that offsets can be in the DLDI file + addr_t ddmemSize; // Size of range that offsets can be in the DLDI file + addr_t addrIter; + + data_t *pDH = _dldi_start; + + memOffset = 0x06000000; + ddmemOffset = readAddr (pDH, DO_text_start); + relocationOffset = memOffset - ddmemOffset; + + ddmemStart = readAddr (pDH, DO_text_start); + ddmemSize = (1 << pDH[DO_driverSize]); + ddmemEnd = ddmemStart + ddmemSize; + + // Fix the function pointers in the header + writeAddr (pDH, DO_startup, readAddr (pDH, DO_startup) + relocationOffset); + writeAddr (pDH, DO_isInserted, readAddr (pDH, DO_isInserted) + relocationOffset); + writeAddr (pDH, DO_readSectors, readAddr (pDH, DO_readSectors) + relocationOffset); + writeAddr (pDH, DO_writeSectors, readAddr (pDH, DO_writeSectors) + relocationOffset); + writeAddr (pDH, DO_clearStatus, readAddr (pDH, DO_clearStatus) + relocationOffset); + writeAddr (pDH, DO_shutdown, readAddr (pDH, DO_shutdown) + relocationOffset); + + if (pDH[DO_fixSections] & FIX_ALL) { + // Search through and fix pointers within the data section of the file + for (addrIter = (readAddr(pDH, DO_text_start) - ddmemStart); addrIter < (readAddr(pDH, DO_data_end) - ddmemStart); addrIter++) { + if ((ddmemStart <= readAddr(pDH, addrIter)) && (readAddr(pDH, addrIter) < ddmemEnd)) { + writeAddr (pDH, addrIter, readAddr(pDH, addrIter) + relocationOffset); + } + } + } + + if (pDH[DO_fixSections] & FIX_GLUE) { + // Search through and fix pointers within the glue section of the file + for (addrIter = (readAddr(pDH, DO_glue_start) - ddmemStart); addrIter < (readAddr(pDH, DO_glue_end) - ddmemStart); addrIter++) { + if ((ddmemStart <= readAddr(pDH, addrIter)) && (readAddr(pDH, addrIter) < ddmemEnd)) { + writeAddr (pDH, addrIter, readAddr(pDH, addrIter) + relocationOffset); + } + } + } + + if (pDH[DO_fixSections] & FIX_GOT) { + // Search through and fix pointers within the Global Offset Table section of the file + for (addrIter = (readAddr(pDH, DO_got_start) - ddmemStart); addrIter < (readAddr(pDH, DO_got_end) - ddmemStart); addrIter++) { + if ((ddmemStart <= readAddr(pDH, addrIter)) && (readAddr(pDH, addrIter) < ddmemEnd)) { + writeAddr (pDH, addrIter, readAddr(pDH, addrIter) + relocationOffset); + } + } + } + + if (pDH[DO_fixSections] & FIX_BSS) { + // Initialise the BSS to 0 + toncset (&pDH[readAddr(pDH, DO_bss_start) - ddmemStart] , 0, readAddr(pDH, DO_bss_end) - readAddr(pDH, DO_bss_start)); + } + + // Fix the section pointers in the header + writeAddr (pDH, DO_text_start, readAddr (pDH, DO_text_start) + relocationOffset); + writeAddr (pDH, DO_data_end, readAddr (pDH, DO_data_end) + relocationOffset); + writeAddr (pDH, DO_glue_start, readAddr (pDH, DO_glue_start) + relocationOffset); + writeAddr (pDH, DO_glue_end, readAddr (pDH, DO_glue_end) + relocationOffset); + writeAddr (pDH, DO_got_start, readAddr (pDH, DO_got_start) + relocationOffset); + writeAddr (pDH, DO_got_end, readAddr (pDH, DO_got_end) + relocationOffset); + writeAddr (pDH, DO_bss_start, readAddr (pDH, DO_bss_start) + relocationOffset); + writeAddr (pDH, DO_bss_end, readAddr (pDH, DO_bss_end) + relocationOffset); +} + +void dldiClearBss (void) { + data_t *pDH = _dldi_start; + + addr_t ddmemSize = (1 << pDH[DO_driverSize]); // Size of range that offsets can be in the DLDI file + + if (ddmemSize <= 0x4000) return; // For <= 16KB DLDI file, BSS has already been cleared + + if (pDH[DO_fixSections] & FIX_BSS) { + // Initialise the BSS to 0 + toncset (&pDH[readAddr(pDH, DO_bss_start)] , 0, readAddr(pDH, DO_bss_end) - readAddr(pDH, DO_bss_start)); + } +} #endif \ No newline at end of file diff --git a/bootloader/source/dldi_patcher.h b/bootloader/source/dldi_patcher.h index f54c531b..956c3dc2 100644 --- a/bootloader/source/dldi_patcher.h +++ b/bootloader/source/dldi_patcher.h @@ -28,5 +28,8 @@ typedef signed int addr_t; typedef unsigned char data_t; bool dldiPatchBinary (data_t *binData, u32 binSize); +void dldiDecompressBinary (void); +void dldiRelocateBinary (void); +void dldiClearBss (void); #endif // DLDI_PATCHER_H diff --git a/bootloader/source/io_dldi.s b/bootloader/source/io_dldi.s index fdfbde11..bb5a8a2b 100644 --- a/bootloader/source/io_dldi.s +++ b/bootloader/source/io_dldi.s @@ -32,73 +32,6 @@ _dldi_start: -#ifndef NO_DLDI - -@--------------------------------------------------------------------------------- -@ Driver patch file standard header -- 16 bytes -#ifdef STANDARD_DLDI - .word 0xBF8DA5ED @ Magic number to identify this region -#else - .word 0xBF8DA5EE @ Magic number to identify this region -#endif - .asciz " Chishm" @ Identifying Magic string (8 bytes with null terminator) - .byte 0x01 @ Version number - .byte 0x0e @ 16KiB @ Log [base-2] of the size of this driver in bytes. - .byte 0x00 @ Sections to fix - .byte 0x0e @ 16KiB @ Log [base-2] of the allocated space in bytes. - -@--------------------------------------------------------------------------------- -@ Text identifier - can be anything up to 47 chars + terminating null -- 16 bytes - .align 4 - .asciz "Loader (No interface)" - -@--------------------------------------------------------------------------------- -@ Offsets to important sections within the data -- 32 bytes - .align 6 - .word _dldi_start @ data start - .word _dldi_end @ data end - .word 0x00000000 @ Interworking glue start -- Needs address fixing - .word 0x00000000 @ Interworking glue end - .word 0x00000000 @ GOT start -- Needs address fixing - .word 0x00000000 @ GOT end - .word 0x00000000 @ bss start -- Needs setting to zero - .word 0x00000000 @ bss end -@--------------------------------------------------------------------------------- -@ IO_INTERFACE data -- 32 bytes -_io_dldi: - .ascii "DLDI" @ ioType - .word 0x00000000 @ Features - .word _DLDI_startup @ - .word _DLDI_isInserted @ - .word _DLDI_readSectors @ Function pointers to standard device driver functions - .word _DLDI_writeSectors @ - .word _DLDI_clearStatus @ - .word _DLDI_shutdown @ - - -@--------------------------------------------------------------------------------- - -_DLDI_startup: -_DLDI_isInserted: -_DLDI_readSectors: -_DLDI_writeSectors: -_DLDI_clearStatus: -_DLDI_shutdown: - mov r0, #0x00 @ Return false for every function - bx lr - - - -@--------------------------------------------------------------------------------- - .align - .pool - - .space (_dldi_start + 16384) - . @ Fill to 16KiB - -_dldi_end: - .end -@--------------------------------------------------------------------------------- -#else @--------------------------------------------------------------------------------- @ IO_INTERFACE data -- 32 bytes _io_dldi: @@ -111,14 +44,27 @@ _io_dldi: .word _DLDI_clearStatus @ .word _DLDI_shutdown @ - _DLDI_startup: +_DLDI_startup: + mov r12, #0x06000000 + ldr r12, [r12, #0x68] + bx r12 _DLDI_isInserted: + mov r12, #0x06000000 + ldr r12, [r12, #0x6C] + bx r12 _DLDI_readSectors: + mov r12, #0x06000000 + ldr r12, [r12, #0x70] + bx r12 _DLDI_writeSectors: + mov r12, #0x06000000 + ldr r12, [r12, #0x74] + bx r12 _DLDI_clearStatus: + mov r12, #0x06000000 + ldr r12, [r12, #0x78] + bx r12 _DLDI_shutdown: - mov r0, #0x00 @ Return false for every function - bx lr - - -#endif + mov r12, #0x06000000 + ldr r12, [r12, #0x7C] + bx r12 diff --git a/bootloader/source/load_crt0.s b/bootloader/source/load_crt0.s index 6c57e6d9..b422d767 100644 --- a/bootloader/source/load_crt0.s +++ b/bootloader/source/load_crt0.s @@ -50,7 +50,7 @@ argStart: argSize: .word 0x00000000 dldiOffset: - .word _dldi_start - _start + .word 0 dsiSD: .word 0 dsiMode: diff --git a/bootloader/source/lzss.c b/bootloader/source/lzss.c new file mode 100644 index 00000000..d4a113b3 --- /dev/null +++ b/bootloader/source/lzss.c @@ -0,0 +1,27 @@ +#include +#include + +void LZ77_Decompress(u8* source, u8* destination) { + u32 leng = (source[1] | (source[2] << 8) | (source[3] << 16)); + int Offs = 4; + int dstoffs = 0; + while (true) { + u8 header = source[Offs++]; + for (int i = 0; i < 8; i++) { + if ((header & 0x80) == 0) destination[dstoffs++] = source[Offs++]; + else + { + u8 a = source[Offs++]; + u8 b = source[Offs++]; + int offs = (((a & 0xF) << 8) | b) + 1; + int length = (a >> 4) + 3; + for (int j = 0; j < length; j++) { + destination[dstoffs] = destination[dstoffs - offs]; + dstoffs++; + } + } + if (dstoffs >= (int)leng) return; + header <<= 1; + } + } +} diff --git a/bootstub/bootstub.s b/bootstub/bootstub.s index 579fb990..14a1d99c 100644 --- a/bootstub/bootstub.s +++ b/bootstub/bootstub.s @@ -25,6 +25,8 @@ _start: .ascii "bootstub" .word hook7from9 - _start .word hook9from7 - _start +_loader_addr: + .word _loader - _start _loader_size: .word 0 @@ -119,10 +121,10 @@ hook7from9: mov r0,#0x80 strb r0,[r3,#0x242-0x180] - adr r0, _loader + ldr r0, _loader_addr ldr r2, _loader_size mov r1, #0x06800000 - add r1, r1, #0x40000 + add r1, r1, #0x48000 add r2, r0, r2 _copyloader: ldr r4, [r0], #4 @@ -140,6 +142,7 @@ _copyloader: ldr r0, arm7bootaddr mov r1, #0x06000000 + add r1, r1, #0x8000 str r1, [r0] ldr r0, resetcode diff --git a/libnds32 b/libnds32 new file mode 160000 index 00000000..117e4642 --- /dev/null +++ b/libnds32 @@ -0,0 +1 @@ +Subproject commit 117e464254ec2767ee5ac8baac2536b1d4a41bac diff --git a/nitrofiles/dldi/nrio.lz77 b/nitrofiles/dldi/nrio.lz77 new file mode 100644 index 00000000..fc556a40 Binary files /dev/null and b/nitrofiles/dldi/nrio.lz77 differ