diff --git a/BootLoader/Makefile b/BootLoader/Makefile index f8f4061..50e6921 100755 --- a/BootLoader/Makefile +++ b/BootLoader/Makefile @@ -24,7 +24,7 @@ SPECS := specs #--------------------------------------------------------------------------------- ARCH := -mthumb-interwork -march=armv4t -mtune=arm7tdmi -CFLAGS := -g -Wall -O2 \ +CFLAGS := -g -Wall -Oz \ -fomit-frame-pointer \ -ffast-math \ -Wall -Wextra -Werror \ diff --git a/BootLoader/source/common.h b/BootLoader/source/common.h index bf1cc08..7de1577 100755 --- a/BootLoader/source/common.h +++ b/BootLoader/source/common.h @@ -33,9 +33,19 @@ typedef struct sLauncherSettings { u8 twlCLK; u8 twlVRAM; u8 debugMode; + u8 fastBoot; + u8 unused2; } tLauncherSettings; -extern volatile tLauncherSettings* tmpData; +extern volatile tLauncherSettings* launchData; +extern volatile int language; +extern volatile bool scfgUnlock; +extern volatile bool twlMode; +extern volatile bool twlCLK; +extern volatile bool debugMode; + +#define CartHeaderCopy 0x02000000 +#define CartChipIDCopy 0x02000180 enum ERROR_CODES { ERR_NONE = 0x00, diff --git a/BootLoader/source/main.arm7.c b/BootLoader/source/main.arm7.c index d90ccb3..5af0327 100755 --- a/BootLoader/source/main.arm7.c +++ b/BootLoader/source/main.arm7.c @@ -53,15 +53,9 @@ External functions extern void arm7_clearmem (void* loc, size_t len); extern void arm7_reset (void); -static int language = -1; -static bool scfgUnlock = false; -static bool twlMode = false; -static bool twlCLK = false; -static bool debugMode = false; - static bool useTwlCfg = false; static int twlCfgLang = 0; - +// static bool useShortInit = false; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Important things @@ -375,7 +369,7 @@ static void arm7_readFirmware(tNDSHeader* ndsHeader) { tonccpy(PersonalData, currentSettings, sizeof(PERSONAL_DATA)); - if (useTwlCfg && (language == 0xFF || language == -1)) { language = twlCfgLang; } + if (useTwlCfg && (language == 0xFF)) { language = twlCfgLang; } if (language >= 0 && language <= 7) { // Change language @@ -420,8 +414,13 @@ static void arm7_resetMemory (void) { arm7_clearmem ((void*)0x037F8000, 96*1024); // clear most of EXRAM - except after 0x022FD800, which has the ARM9 code + // Skip 0x0200000 region if fastBoot enabled. (cart header copy stored here) + /*if (useShortInit) { + arm7_clearmem ((void*)0x02000200, 0x002FD600); + } else { + arm7_clearmem ((void*)0x02000000, 0x002FD800); + }*/ arm7_clearmem ((void*)0x02000000, 0x002FD800); - // clear last part of EXRAM, skipping the ARM9's section arm7_clearmem ((void*)0x023FE000, 0x2000); @@ -487,7 +486,15 @@ static u32 arm7_loadBinary (void) { tDSiHeader* twlHeaderTemp = (tDSiHeader*)TMP_HEADER; // Use same region cheat engine goes. Cheat engine will replace this later when it's not needed. // Init card + /*if (useShortInit) { + errorCode = cardInitShort((sNDSHeaderExt*)twlHeaderTemp, &chipID); + arm7_clearmem ((void*)0x02000200, 0x200); // clear temp header data + } else { + errorCode = cardInit((sNDSHeaderExt*)twlHeaderTemp, &chipID); + }*/ + errorCode = cardInit((sNDSHeaderExt*)twlHeaderTemp, &chipID); + if (errorCode)return errorCode; ndsHeader = loadHeader(twlHeaderTemp); // copy twlHeaderTemp to ndsHeader location @@ -518,19 +525,21 @@ static u32 arm7_loadBinary (void) { void arm7_main (void) { u32 errorCode; - - if (language != 0xFF)language = (int)tmpData->language; - if (tmpData->scfgUnlock > 0x00)scfgUnlock = true; - if (tmpData->twlMode > 0x00)twlMode = true; - if (tmpData->twlCLK > 0x00)twlCLK = true; - if (tmpData->debugMode > 0x00)debugMode = true; - + // Synchronise start while (ipcRecvState() != ARM9_START); ipcSendState(ARM7_START); // Wait until ARM9 is ready while (ipcRecvState() != ARM9_READY); + + if (language != 0xFF)language = (int)launchData->language; + if (launchData->scfgUnlock > 0x00)scfgUnlock = true; + if (launchData->twlMode > 0x00)twlMode = true; + if (launchData->twlCLK > 0x00)twlCLK = true; + if (launchData->debugMode > 0x00)debugMode = true; + // if (launchData->fastBoot > 0x00)useShortInit = true; + if (twlMode) { REG_MBK9=0x0300000F; @@ -582,7 +591,7 @@ void arm7_main (void) { REG_SCFG_EXT = 0x92A00000; } - if (twlCLK) { REG_SCFG_CLK = 0x0185; } else { REG_SCFG_CLK = 0x0101; } + if (twlCLK) { REG_SCFG_CLK = 0x0187; } else { REG_SCFG_CLK = 0x0101; } if (scfgUnlock) { REG_SCFG_EXT |= BIT(18); } else { REG_SCFG_EXT &= ~(1UL << 31); } setMemoryAddress(ndsHeader); diff --git a/BootLoader/source/main.arm9.c b/BootLoader/source/main.arm9.c index f3aff35..ca1efce 100755 --- a/BootLoader/source/main.arm9.c +++ b/BootLoader/source/main.arm9.c @@ -40,7 +40,7 @@ #include "common.h" #include "miniconsole.h" -#define TMP_DATA 0x027FC000 +#define LAUNCH_DATA 0x020007F0 volatile int arm9_stateFlag = ARM9_BOOT; volatile u32 arm9_errorCode = 0xFFFFFFFF; @@ -48,14 +48,16 @@ volatile bool arm9_errorClearBG = false; volatile bool consoleDebugMode = false; volatile u32 arm9_BLANK_RAM = 0; volatile u32 defaultFontPalSlot = 0; -volatile tLauncherSettings* tmpData = (tLauncherSettings*)TMP_DATA; -static bool scfgUnlock = false; -static bool TWLMODE = false; -static bool TWLVRAM = false; -static bool TWLCLK = false; -static bool debugMode = false; -static bool consoleInit = false; +volatile tLauncherSettings* launchData = (tLauncherSettings*)LAUNCH_DATA; + +volatile int language = -1; +volatile bool scfgUnlock = false; +volatile bool twlMode = false; +volatile bool twlCLK = false; +volatile bool TWLVRAM = false; +volatile bool debugMode = false; +volatile bool consoleInit = false; static char TXT_STATUS[] = "STATUS: "; static char TXT_ERROR[] = "ERROR: "; @@ -159,14 +161,16 @@ Written by Darkain, modified by Chishm void arm9_main (void) { register int i; - - if (tmpData->scfgUnlock == 0x01)scfgUnlock = true; - if (tmpData->twlMode == 0x01)TWLMODE = true; - if (tmpData->twlVRAM == 0x01)TWLVRAM = true; - if (tmpData->twlCLK == 0x01)TWLCLK = true; - if (tmpData->debugMode == 0x01)debugMode = true; - if (TWLMODE) { + + if (launchData->language != 0xFF)language = (u8)launchData->language; + if (launchData->scfgUnlock == 0x01)scfgUnlock = true; + if (launchData->twlMode == 0x01)twlMode = true; + if (launchData->twlVRAM == 0x01)TWLVRAM = true; + if (launchData->twlCLK == 0x01)twlCLK = true; + if (launchData->debugMode == 0x01)debugMode = true; + + if (twlMode) { *((vu32*)REG_MBK1)=0x8D898581; *((vu32*)REG_MBK2)=0x8C888480; *((vu32*)REG_MBK3)=0x9C989490; @@ -302,8 +306,8 @@ void arm9_main (void) { videoSetModeSub(0); REG_POWERCNT = 0x820F; - if (!TWLCLK)REG_SCFG_CLK = 0x80; - if (TWLMODE) { + if (!twlCLK)REG_SCFG_CLK = 0x80; + if (twlMode) { REG_SCFG_EXT = 0x82073100; REG_SCFG_RST = 1; } diff --git a/BootLoader/source/read_card.c b/BootLoader/source/read_card.c index b6c086b..7eafd06 100755 --- a/BootLoader/source/read_card.c +++ b/BootLoader/source/read_card.c @@ -24,21 +24,24 @@ #include #include #include +#include #include "encryption.h" #include "common.h" +#include "tonccpy.h" typedef union { char title[4]; u32 key; } GameCode; static u32 portFlags = 0; static u32 secureAreaData[CARD_SECURE_AREA_SIZE/sizeof(u32)]; +// static bool shortInit = false; static const u8 cardSeedBytes[] = {0xE8, 0x4D, 0x5A, 0xB1, 0x17, 0x8F, 0x99, 0xD5}; -static u32 getRandomNumber(void) { - return 4; // chosen by fair dice roll. - // guaranteed to be random. -} +// chosen by fair dice roll. +// guaranteed to be random. +// static u32 getRandomNumber(void) { return 4; } +static u32 getRandomNumber(void) { return rand(); } // make this actually random lol. :P static void decryptSecureArea (u32 gameCode, u32* secureArea) { int i; @@ -120,7 +123,7 @@ static void cardDelay (u16 readTimeout) { } -int cardInit (sNDSHeaderExt* ndsHeader, u32* chipID) { +u32 cardInit (sNDSHeaderExt* ndsHeader, u32* chipID) { u32 portFlagsKey1, portFlagsSecRead; bool normalChip; // As defined by GBAtek, normal chip secure area is accessed in blocks of 0x200, other chip in blocks of 0x1000 u32* secureArea; @@ -128,6 +131,7 @@ int cardInit (sNDSHeaderExt* ndsHeader, u32* chipID) { int i; u8 cmdData[8] __attribute__ ((aligned)); GameCode* gameCode; + // shortInit = false; // Dummy command sent after card reset cardParamCommand (CARD_CMD_DUMMY, 0, CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW | CARD_BLK_SIZE(1) | CARD_DELAY1(0x1FFF) | CARD_DELAY2(0x3F), NULL, 0); @@ -136,19 +140,10 @@ int cardInit (sNDSHeaderExt* ndsHeader, u32* chipID) { static_assert(sizeof(tNDSHeader) == 0x160, "tNDSHeader not packed properly"); // Read the header - cardParamCommand (CARD_CMD_HEADER_READ, 0, - CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW | CARD_BLK_SIZE(1) | CARD_DELAY1(0x1FFF) | CARD_DELAY2(0x3F), - (uint32*)ndsHeader, sizeof(tNDSHeader)); + cardParamCommand (CARD_CMD_HEADER_READ, 0, CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW | CARD_BLK_SIZE(1) | CARD_DELAY1(0x1FFF) | CARD_DELAY2(0x3F), (u32*)ndsHeader, sizeof(tNDSHeader)); // Check header CRC - if (ndsHeader->headerCRC16 != swiCRC16(0xFFFF, (void*)ndsHeader, 0x15E)) { - return ERR_HEAD_CRC; - } - - // Check logo CRC - /*if (ndsHeader->logoCRC16 != 0xCF56) { - return ERR_LOGO_CRC; - }*/ + if (ndsHeader->headerCRC16 != swiCRC16(0xFFFF, (void*)ndsHeader, 0x15E))return ERR_HEAD_CRC; // Initialise blowfish encryption for KEY1 commands and decrypting the secure area gameCode = (GameCode*)ndsHeader->gameCode; @@ -157,13 +152,10 @@ int cardInit (sNDSHeaderExt* ndsHeader, u32* chipID) { // Port 40001A4h setting for normal reads (command B7) portFlags = ndsHeader->cardControl13 & ~CARD_BLK_SIZE(7); // Port 40001A4h setting for KEY1 commands (usually 001808F8h) - portFlagsKey1 = CARD_ACTIVATE | CARD_nRESET | (ndsHeader->cardControl13 & (CARD_WR|CARD_CLK_SLOW)) | - ((ndsHeader->cardControlBF & (CARD_CLK_SLOW|CARD_DELAY1(0x1FFF))) + ((ndsHeader->cardControlBF & CARD_DELAY2(0x3F)) >> 16)); + portFlagsKey1 = CARD_ACTIVATE | CARD_nRESET | (ndsHeader->cardControl13 & (CARD_WR|CARD_CLK_SLOW)) | ((ndsHeader->cardControlBF & (CARD_CLK_SLOW|CARD_DELAY1(0x1FFF))) + ((ndsHeader->cardControlBF & CARD_DELAY2(0x3F)) >> 16)); // 1st Get ROM Chip ID - cardParamCommand (CARD_CMD_HEADER_CHIPID, 0, - (ndsHeader->cardControl13 & (CARD_WR|CARD_nRESET|CARD_CLK_SLOW)) | CARD_ACTIVATE | CARD_BLK_SIZE(7), - chipID, sizeof(u32)); + cardParamCommand (CARD_CMD_HEADER_CHIPID, 0, (ndsHeader->cardControl13 & (CARD_WR|CARD_nRESET|CARD_CLK_SLOW)) | CARD_ACTIVATE | CARD_BLK_SIZE(7), chipID, sizeof(u32)); // Adjust card transfer method depending on the most significant bit of the chip ID normalChip = ((*chipID) & 0x80000000) != 0; // ROM chip ID MSB @@ -187,9 +179,9 @@ int cardInit (sNDSHeaderExt* ndsHeader, u32* chipID) { // Set the KEY2 encryption registers REG_ROMCTRL = 0; REG_CARD_1B0 = cardSeedBytes[ndsHeader->deviceType & 0x07] | (key1data.nnn << 15) | (key1data.mmm << 27) | 0x6000; - REG_CARD_1B4 = 0x879b9b05; + REG_CARD_1B4 = 0x879B9B05; REG_CARD_1B8 = key1data.mmm >> 5; - REG_CARD_1BA = 0x5c; + REG_CARD_1BA = 0x5C; REG_ROMCTRL = CARD_nRESET | CARD_SEC_SEED | CARD_SEC_EN | CARD_SEC_DAT; // Update the DS card flags to suit KEY2 encryption @@ -208,9 +200,8 @@ int cardInit (sNDSHeaderExt* ndsHeader, u32* chipID) { // 2bbbbiii jjjkkkkk - Get Secure Area Block secureArea = secureAreaData; - portFlagsSecRead = (ndsHeader->cardControlBF & (CARD_CLK_SLOW|CARD_DELAY1(0x1FFF)|CARD_DELAY2(0x3F))) - | CARD_ACTIVATE | CARD_nRESET | CARD_SEC_EN | CARD_SEC_DAT; - + portFlagsSecRead = (ndsHeader->cardControlBF & (CARD_CLK_SLOW|CARD_DELAY1(0x1FFF)|CARD_DELAY2(0x3F))) | CARD_ACTIVATE | CARD_nRESET | CARD_SEC_EN | CARD_SEC_DAT; + for (secureBlockNumber = 4; secureBlockNumber < 8; secureBlockNumber++) { createEncryptedCommand (CARD_CMD_SECURE_READ, cmdData, secureBlockNumber); if (normalChip) { @@ -256,11 +247,10 @@ int cardInit (sNDSHeaderExt* ndsHeader, u32* chipID) { return ERR_NONE; } -void cardRead (u32 src, u32* dest, size_t size) -{ +void cardRead (u32 src, u32* dest, size_t size) { size_t readSize; - if (src < CARD_SECURE_AREA_OFFSET) { + if ((src < CARD_SECURE_AREA_OFFSET) /*&& !shortInit*/) { return; } else if (src < CARD_DATA_OFFSET) { // Read data from secure area @@ -273,12 +263,65 @@ void cardRead (u32 src, u32* dest, size_t size) while (size > 0) { readSize = size < CARD_DATA_BLOCK_SIZE ? size : CARD_DATA_BLOCK_SIZE; - cardParamCommand (CARD_CMD_DATA_READ, src, - (portFlags &~CARD_BLK_SIZE(7)) | CARD_ACTIVATE | CARD_nRESET | CARD_BLK_SIZE(1), - dest, readSize); + cardParamCommand (CARD_CMD_DATA_READ, src, (portFlags &~CARD_BLK_SIZE(7)) | CARD_ACTIVATE | CARD_nRESET | CARD_BLK_SIZE(1), dest, readSize); src += readSize; dest += readSize/sizeof(*dest); size -= readSize; } } +// If booted from DSi System Menu short cart init with no card reads or pokes to rom ctrl registers can be done. +// System Menu is nice enough to do this for you. :P +// (also is the case for booting from DS Download Play. ;) ) +/*u32 cardInitShort (sNDSHeaderExt* ndsHeader, u32* chipID) { + bool normalChip; // As defined by GBAtek, normal chip secure area is accessed in blocks of 0x200, other chip in blocks of 0x1000 + u32* secureArea; + GameCode* gameCode; + shortInit = true; + + // Verify that the ndsHeader is packed correctly, now that it's no longer __packed__ + static_assert(sizeof(tNDSHeader) == 0x160, "tNDSHeader not packed properly"); + + // Read the header + tonccpy(ndsHeader, (u32*)CartHeaderCopy, 0x180); + + // Check header CRC + if (ndsHeader->headerCRC16 != swiCRC16(0xFFFF, (void*)ndsHeader, 0x15E))return ERR_HEAD_CRC; + + // Initialise blowfish encryption for KEY1 commands and decrypting the secure area + gameCode = (GameCode*)ndsHeader->gameCode; + init_keycode (gameCode->key, 2, 8); + + // Port 40001A4h setting for normal reads (command B7) + portFlags = ndsHeader->cardControl13 & ~CARD_BLK_SIZE(7); + + // 1st Get ROM Chip ID + // chipID = *(u32*)0x02FFFC00; // This location contains cart's chipID when booting DSiWare that has Slot-1 access. + // chipID = *(u32*)0x027FF800; // This location contains cart's chipID for DS Download Play users + tonccpy(chipID, (u32*)CartChipIDCopy, 0x08); // This location contains cart's chipID when booting DSiWare that has Slot-1 access. + + // Adjust card transfer method depending on the most significant bit of the chip ID + normalChip = ((*chipID) & 0x80000000) != 0; // ROM chip ID MSB + + if (normalChip)cardDelay(ndsHeader->readTimeout); + + // 2bbbbiii jjjkkkkk - Get Secure Area Block + secureArea = secureAreaData; + shortInit = false; + u32 secureBlockSize = 0x800; + if (!normalChip)secureBlockSize = 0x1000; + cardRead (ndsHeader->arm9romOffset, secureArea, secureBlockSize); + + // Now deal with secure area decryption and verification + decryptSecureArea (gameCode->key, secureAreaData); + + secureArea = secureAreaData; + if (secureArea[0] == 0x72636e65 && secureArea[1] == 0x6a624f79) { + // Secure area exists, so just clear the tag + secureArea[0] = 0xe7ffdeff; + secureArea[1] = 0xe7ffdeff; + } + + return ERR_NONE; +}*/ + diff --git a/BootLoader/source/read_card.h b/BootLoader/source/read_card.h index c95087c..2750fe1 100755 --- a/BootLoader/source/read_card.h +++ b/BootLoader/source/read_card.h @@ -121,9 +121,9 @@ typedef struct { u8 dsi3[0x174]; } sNDSHeaderExt; -int cardInit (sNDSHeaderExt* ndsHeader, u32* chipID); - +u32 cardInit (sNDSHeaderExt* ndsHeader, u32* chipID); void cardRead (u32 src, u32* dest, size_t size); +// u32 cardInitShort (sNDSHeaderExt* ndsHeader, u32* chipID); #endif // READ_CARD_H diff --git a/NTR_Launcher.ini b/CartFiles/NTR_Launcher.ini similarity index 100% rename from NTR_Launcher.ini rename to CartFiles/NTR_Launcher.ini diff --git a/Makefile b/Makefile index 5dad9dc..6bb744c 100755 --- a/Makefile +++ b/Makefile @@ -13,15 +13,19 @@ export TARGET := NTR_Launcher export TOPDIR := $(CURDIR) export VERSION_MAJOR := 2 -export VERSION_MINOR := 7 +export VERSION_MINOR := 9 export VERSTRING := $(VERSION_MAJOR).$(VERSION_MINOR) -.PHONY: bootloader clean arm7/$(TARGET).elf arm9/$(TARGET).elf +# specify a directory which contains the nitro filesystem +# this is relative to the Makefile +NITRO_FILES := CartFiles + +.PHONY: bootloader ndsbootloader clean arm7/$(TARGET).elf arm9/$(TARGET).elf #--------------------------------------------------------------------------------- # main targets #--------------------------------------------------------------------------------- -all: bootloader $(TARGET).nds +all: bootloader ndsbootloader $(TARGET).nds dist: all @mkdir -p debug @@ -31,7 +35,8 @@ dist: all $(TARGET).nds: $(TARGET).arm7 $(TARGET).arm9 ndstool -c $(TARGET).nds -7 $(TARGET).arm7.elf -9 $(TARGET).arm9.elf \ -b $(CURDIR)/icon.bmp "NTR Launcher;Slot-1 Launcher;Apache Thunder & RocketRobz" \ - -g KKGP 01 "NTR Launcher" -z 80040000 -u 00030004 -a 00000138 -p 0001 + -g KKGP 01 "NTR Launcher" -z 80040000 -u 00030004 -a 00000138 -p 0001 \ + -d $(NITRO_FILES) @cp $(TARGET).nds 00000000.app $(TARGET).arm7 : arm7/$(TARGET).elf @@ -58,7 +63,9 @@ clean: @rm -fr $(TARGET).arm7.elf @rm -fr $(TARGET).arm9.elf @rm -fr 00000000.app + @rm -fr $(TARGET).cia @$(MAKE) -C bootloader clean + @$(MAKE) -C ndsbootloader clean @$(MAKE) -C arm9 clean @$(MAKE) -C arm7 clean @@ -67,4 +74,7 @@ data: bootloader: data @$(MAKE) -C bootloader + +ndsbootloader: data + @$(MAKE) -C ndsbootloader diff --git a/NTR_Launcher.dsi b/NTR_Launcher.dsi deleted file mode 100644 index 174e4ce..0000000 Binary files a/NTR_Launcher.dsi and /dev/null differ diff --git a/arm7/source/main.c b/arm7/source/main.c index d2d6fd5..28282b6 100755 --- a/arm7/source/main.c +++ b/arm7/source/main.c @@ -22,7 +22,164 @@ #include -bool SCFGCLKCheck = false; +#define REG_GPIO_WIFI *(vu16*)0x04004C04 + +static bool touchScreenCheck = false; + +static void NDSTouchscreenMode() { + u8 volLevel = 0xA7; + + // Touchscreen + cdcReadReg (0x63, 0x00); + cdcWriteReg(CDC_CONTROL, 0x3A, 0x00); + cdcReadReg (CDC_CONTROL, 0x51); + cdcReadReg (CDC_TOUCHCNT, 0x02); + cdcReadReg (CDC_CONTROL, 0x3F); + cdcReadReg (CDC_SOUND, 0x28); + cdcReadReg (CDC_SOUND, 0x2A); + cdcReadReg (CDC_SOUND, 0x2E); + cdcWriteReg(CDC_CONTROL, 0x52, 0x80); + cdcWriteReg(CDC_CONTROL, 0x40, 0x0C); + cdcWriteReg(CDC_SOUND, 0x24, 0xFF); + cdcWriteReg(CDC_SOUND, 0x25, 0xFF); + cdcWriteReg(CDC_SOUND, 0x26, 0x7F); + cdcWriteReg(CDC_SOUND, 0x27, 0x7F); + cdcWriteReg(CDC_SOUND, 0x28, 0x4A); + cdcWriteReg(CDC_SOUND, 0x29, 0x4A); + cdcWriteReg(CDC_SOUND, 0x2A, 0x10); + cdcWriteReg(CDC_SOUND, 0x2B, 0x10); + cdcWriteReg(CDC_CONTROL, 0x51, 0x00); + cdcReadReg (CDC_TOUCHCNT, 0x02); + cdcWriteReg(CDC_TOUCHCNT, 0x02, 0x98); + cdcWriteReg(CDC_SOUND, 0x23, 0x00); + cdcWriteReg(CDC_SOUND, 0x1F, 0x14); + cdcWriteReg(CDC_SOUND, 0x20, 0x14); + cdcWriteReg(CDC_CONTROL, 0x3F, 0x00); + cdcReadReg (CDC_CONTROL, 0x0B); + cdcWriteReg(CDC_CONTROL, 0x05, 0x00); + cdcWriteReg(CDC_CONTROL, 0x0B, 0x01); + cdcWriteReg(CDC_CONTROL, 0x0C, 0x02); + cdcWriteReg(CDC_CONTROL, 0x12, 0x01); + cdcWriteReg(CDC_CONTROL, 0x13, 0x02); + cdcWriteReg(CDC_SOUND, 0x2E, 0x00); + cdcWriteReg(CDC_CONTROL, 0x3A, 0x60); + cdcWriteReg(CDC_CONTROL, 0x01, 0x01); + cdcWriteReg(CDC_CONTROL, 0x39, 0x66); + cdcReadReg (CDC_SOUND, 0x20); + cdcWriteReg(CDC_SOUND, 0x20, 0x10); + cdcWriteReg(CDC_CONTROL, 0x04, 0x00); + cdcWriteReg(CDC_CONTROL, 0x12, 0x81); + cdcWriteReg(CDC_CONTROL, 0x13, 0x82); + cdcWriteReg(CDC_CONTROL, 0x51, 0x82); + cdcWriteReg(CDC_CONTROL, 0x51, 0x00); + cdcWriteReg(CDC_CONTROL, 0x04, 0x03); + cdcWriteReg(CDC_CONTROL, 0x05, 0xA1); + cdcWriteReg(CDC_CONTROL, 0x06, 0x15); + cdcWriteReg(CDC_CONTROL, 0x0B, 0x87); + cdcWriteReg(CDC_CONTROL, 0x0C, 0x83); + cdcWriteReg(CDC_CONTROL, 0x12, 0x87); + cdcWriteReg(CDC_CONTROL, 0x13, 0x83); + cdcReadReg (CDC_TOUCHCNT, 0x10); + cdcWriteReg(CDC_TOUCHCNT, 0x10, 0x08); + cdcWriteReg(0x04, 0x08, 0x7F); + cdcWriteReg(0x04, 0x09, 0xE1); + cdcWriteReg(0x04, 0x0A, 0x80); + cdcWriteReg(0x04, 0x0B, 0x1F); + cdcWriteReg(0x04, 0x0C, 0x7F); + cdcWriteReg(0x04, 0x0D, 0xC1); + cdcWriteReg(CDC_CONTROL, 0x41, 0x08); + cdcWriteReg(CDC_CONTROL, 0x42, 0x08); + cdcWriteReg(CDC_CONTROL, 0x3A, 0x00); + cdcWriteReg(0x04, 0x08, 0x7F); + cdcWriteReg(0x04, 0x09, 0xE1); + cdcWriteReg(0x04, 0x0A, 0x80); + cdcWriteReg(0x04, 0x0B, 0x1F); + cdcWriteReg(0x04, 0x0C, 0x7F); + cdcWriteReg(0x04, 0x0D, 0xC1); + cdcWriteReg(CDC_SOUND, 0x2F, 0x2B); + cdcWriteReg(CDC_SOUND, 0x30, 0x40); + cdcWriteReg(CDC_SOUND, 0x31, 0x40); + cdcWriteReg(CDC_SOUND, 0x32, 0x60); + cdcReadReg (CDC_CONTROL, 0x74); + cdcWriteReg(CDC_CONTROL, 0x74, 0x02); + cdcReadReg (CDC_CONTROL, 0x74); + cdcWriteReg(CDC_CONTROL, 0x74, 0x10); + cdcReadReg (CDC_CONTROL, 0x74); + cdcWriteReg(CDC_CONTROL, 0x74, 0x40); + cdcWriteReg(CDC_SOUND, 0x21, 0x20); + cdcWriteReg(CDC_SOUND, 0x22, 0xF0); + cdcReadReg (CDC_CONTROL, 0x51); + cdcReadReg (CDC_CONTROL, 0x3F); + cdcWriteReg(CDC_CONTROL, 0x3F, 0xD4); + cdcWriteReg(CDC_SOUND, 0x23, 0x44); + cdcWriteReg(CDC_SOUND, 0x1F, 0xD4); + cdcWriteReg(CDC_SOUND, 0x28, 0x4E); + cdcWriteReg(CDC_SOUND, 0x29, 0x4E); + cdcWriteReg(CDC_SOUND, 0x24, 0x9E); + cdcWriteReg(CDC_SOUND, 0x25, 0x9E); + cdcWriteReg(CDC_SOUND, 0x20, 0xD4); + cdcWriteReg(CDC_SOUND, 0x2A, 0x14); + cdcWriteReg(CDC_SOUND, 0x2B, 0x14); + cdcWriteReg(CDC_SOUND, 0x26, 0xA7); + cdcWriteReg(CDC_SOUND, 0x27, 0xA7); + cdcWriteReg(CDC_CONTROL, 0x40, 0x00); + cdcWriteReg(CDC_CONTROL, 0x3A, 0x60); + cdcWriteReg(CDC_SOUND, 0x26, volLevel); + cdcWriteReg(CDC_SOUND, 0x27, volLevel); + cdcWriteReg(CDC_SOUND, 0x2E, 0x03); + cdcWriteReg(CDC_TOUCHCNT, 0x03, 0x00); + cdcWriteReg(CDC_SOUND, 0x21, 0x20); + cdcWriteReg(CDC_SOUND, 0x22, 0xF0); + cdcReadReg (CDC_SOUND, 0x22); + cdcWriteReg(CDC_SOUND, 0x22, 0x00); + cdcWriteReg(CDC_CONTROL, 0x52, 0x80); + cdcWriteReg(CDC_CONTROL, 0x51, 0x00); + + // Set remaining values + cdcWriteReg(CDC_CONTROL, 0x03, 0x44); + cdcWriteReg(CDC_CONTROL, 0x0D, 0x00); + cdcWriteReg(CDC_CONTROL, 0x0E, 0x80); + cdcWriteReg(CDC_CONTROL, 0x0F, 0x80); + cdcWriteReg(CDC_CONTROL, 0x10, 0x08); + cdcWriteReg(CDC_CONTROL, 0x14, 0x80); + cdcWriteReg(CDC_CONTROL, 0x15, 0x80); + cdcWriteReg(CDC_CONTROL, 0x16, 0x04); + cdcWriteReg(CDC_CONTROL, 0x1A, 0x01); + cdcWriteReg(CDC_CONTROL, 0x1E, 0x01); + cdcWriteReg(CDC_CONTROL, 0x24, 0x80); + cdcWriteReg(CDC_CONTROL, 0x33, 0x34); + cdcWriteReg(CDC_CONTROL, 0x34, 0x32); + cdcWriteReg(CDC_CONTROL, 0x35, 0x12); + cdcWriteReg(CDC_CONTROL, 0x36, 0x03); + cdcWriteReg(CDC_CONTROL, 0x37, 0x02); + cdcWriteReg(CDC_CONTROL, 0x38, 0x03); + cdcWriteReg(CDC_CONTROL, 0x3C, 0x19); + cdcWriteReg(CDC_CONTROL, 0x3D, 0x05); + cdcWriteReg(CDC_CONTROL, 0x44, 0x0F); + cdcWriteReg(CDC_CONTROL, 0x45, 0x38); + cdcWriteReg(CDC_CONTROL, 0x49, 0x00); + cdcWriteReg(CDC_CONTROL, 0x4A, 0x00); + cdcWriteReg(CDC_CONTROL, 0x4B, 0xEE); + cdcWriteReg(CDC_CONTROL, 0x4C, 0x10); + cdcWriteReg(CDC_CONTROL, 0x4D, 0xD8); + cdcWriteReg(CDC_CONTROL, 0x4E, 0x7E); + cdcWriteReg(CDC_CONTROL, 0x4F, 0xE3); + cdcWriteReg(CDC_CONTROL, 0x58, 0x7F); + cdcWriteReg(CDC_CONTROL, 0x74, 0xD2); + cdcWriteReg(CDC_CONTROL, 0x75, 0x2C); + cdcWriteReg(CDC_SOUND, 0x22, 0x70); + cdcWriteReg(CDC_SOUND, 0x2C, 0x20); + + // Finish up! + cdcReadReg (CDC_TOUCHCNT, 0x02); + cdcWriteReg(CDC_TOUCHCNT, 0x02, 0x98); + cdcWriteReg(0xFF, 0x05, 0x00); //writeTSC(0x00, 0xFF); + + // Power management + writePowerManagement(PM_READ_REGISTER, 0x00); //*(unsigned char*)0x40001C2 = 0x80, 0x00; // read PWR[0] ;<-- also part of TSC ! + writePowerManagement(PM_CONTROL_REG, 0x0D); //*(unsigned char*)0x40001C2 = 0x00, 0x0D; // PWR[0]=0Dh ;<-- also part of TSC ! +} + void VcountHandler() { inputGetAndSend(); } @@ -52,6 +209,21 @@ int main(void) { i2cWriteRegister(0x4A, 0x12, 0x00); // Press power-button for auto-reset i2cWriteRegister(0x4A, 0x70, 0x01); // Bootflag = Warmboot/SkipHealthSafety - while (1) { swiWaitForVBlank(); } + while (1) { + if (!touchScreenCheck) { + if(fifoCheckValue32(FIFO_USER_01)) { + if (cdcReadReg(CDC_SOUND, 0x22) == 0xF0) { + // Switch touch mode to NTR + *(u16*)0x4004700 = 0x800F; + NDSTouchscreenMode(); + *(u16*)0x4000500 = 0x807F; + } + REG_GPIO_WIFI |= BIT(8); // Old NDS-Wifi mode + fifoSendValue32(FIFO_USER_02, 1); + touchScreenCheck = true; + } + } + swiWaitForVBlank(); + } } diff --git a/arm9/Makefile b/arm9/Makefile index 450e870..5a3b618 100755 --- a/arm9/Makefile +++ b/arm9/Makefile @@ -16,8 +16,8 @@ include $(DEVKITARM)/ds_rules #--------------------------------------------------------------------------------- BUILD := build IMAGES := graphics -SOURCES := source $(IMG_DATA) -INCLUDES := include +SOURCES := source common hbmenu $(IMG_DATA) +INCLUDES := include common hbmenu DATA := ../data MUSIC := music @@ -26,7 +26,7 @@ MUSIC := music #--------------------------------------------------------------------------------- ARCH := -march=armv5te -mtune=arm946e-s -mthumb -mthumb-interwork -CFLAGS := -g -Wall -O2\ +CFLAGS := -g -Wall -O2 \ -fomit-frame-pointer\ -ffast-math \ $(ARCH) @@ -803,22 +803,6 @@ BotDSi10.s : ../$(IMAGES)/BotDSi10.bmp BotDSi11.s : ../$(IMAGES)/BotDSi11.bmp grit $< -gB8 -gzl -fts -gTff00ff -o $@ -q -# generic fade from white to black -fade00.s : ../$(IMAGES)/fade00.bmp - grit $< -gB8 -gzl -fts -gTff00ff -o $@ -q - -fade01.s : ../$(IMAGES)/fade01.bmp - grit $< -gB8 -gzl -fts -gTff00ff -o $@ -q - -fade02.s : ../$(IMAGES)/fade02.bmp - grit $< -gB8 -gzl -fts -gTff00ff -o $@ -q - -fade03.s : ../$(IMAGES)/fade03.bmp - grit $< -gB8 -gzl -fts -gTff00ff -o $@ -q - -fade04.s : ../$(IMAGES)/fade04.bmp - grit $< -gB8 -gzl -fts -gTff00ff -o $@ -q - # generic bottom screen error message suberror00.s : ../$(IMAGES)/suberror00.bmp grit $< -gB8 -gzl -fts -gTff00ff -o $@ -q @@ -863,6 +847,25 @@ toperror2_05.s : ../$(IMAGES)/toperror2_05.bmp toperror2_06.s : ../$(IMAGES)/toperror2_06.bmp grit $< -gB8 -gzl -fts -gTff00ff -o $@ -q +loading.s : ../$(IMAGES)/loading.bmp + grit $< -gB8 -gzl -fts -gTff00ff -o $@ -q + +font.s : ../$(IMAGES)/font.bmp + grit $< -gt -pw16 -mR! -m! -gB4 -o $@ -q + +font6x8.s : ../$(IMAGES)/font6x8.bmp + grit $< -gB8 -gTFFFFFF -gzl -o $@ -q + +hbmenu_banner.s : ../$(IMAGES)/hbmenu_banner.bmp + grit $< -W3 -gT! -gzl -gB16 -o $@ -q + +hbmenu_banner_cartSelected.s : ../$(IMAGES)/hbmenu_banner_cartSelected.bmp + grit $< -W3 -gT! -gzl -gB16 -o $@ -q + +hbmenu_consolebg.s : ../$(IMAGES)/hbmenu_consolebg.bmp + grit $< -gB8 -gb -o $@ -q + + #--------------------------------------------------------------------------------- # rule to build soundbank from music files #--------------------------------------------------------------------------------- diff --git a/arm9/source/crc.c b/arm9/common/crc.c old mode 100755 new mode 100644 similarity index 100% rename from arm9/source/crc.c rename to arm9/common/crc.c diff --git a/arm9/source/crc.h b/arm9/common/crc.h old mode 100755 new mode 100644 similarity index 100% rename from arm9/source/crc.h rename to arm9/common/crc.h diff --git a/arm9/source/encryption.c b/arm9/common/encryption.c similarity index 100% rename from arm9/source/encryption.c rename to arm9/common/encryption.c diff --git a/arm9/source/encryption.h b/arm9/common/encryption.h similarity index 100% rename from arm9/source/encryption.h rename to arm9/common/encryption.h diff --git a/arm9/source/inifile.cpp b/arm9/common/inifile.cpp similarity index 100% rename from arm9/source/inifile.cpp rename to arm9/common/inifile.cpp diff --git a/arm9/source/inifile.h b/arm9/common/inifile.h similarity index 100% rename from arm9/source/inifile.h rename to arm9/common/inifile.h diff --git a/arm9/source/key1.h b/arm9/common/key1.h similarity index 100% rename from arm9/source/key1.h rename to arm9/common/key1.h diff --git a/arm9/source/key2.h b/arm9/common/key2.h similarity index 100% rename from arm9/source/key2.h rename to arm9/common/key2.h diff --git a/arm9/common/launcherData.h b/arm9/common/launcherData.h new file mode 100644 index 0000000..da1c8b4 --- /dev/null +++ b/arm9/common/launcherData.h @@ -0,0 +1,55 @@ +/* + NitroHax -- Cheat tool for the Nintendo DS + Copyright (C) 2008 Michael "Chishm" Chisholm + + 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 3 of the License, 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, see . +*/ + +#ifndef LAUNCHERDATA_H +#define LAUNCHERDATA_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define LAUNCH_DATA 0x020007F0 +#define CartHeaderCopy 0x02000000 +#define CartChipIDCopy 0x02000180 + +#define CartBannerBuffer 0x02500000 +// #define InitialCartBannerOffset 0x02FFC068 + +#define InitialCartHeaderTWL 0x02FFC000 // System Menu keeps cart's header here (if cart is present) on initial boot of any DSiWare! +#define InitialCartHeader 0x02FFFA80 // System Menu keeps cart's header here (if cart is present) on initial boot of any DSiWare! +#define InitialCartChipID 0x02FFFC00 // System Menu keeps cart's chip id here (if cart is present) on initial boot of any DSiWare! +#define InitialCartBannerOffset 0x02FFFAE8 + +typedef struct sLauncherSettings { + u8 language; + u8 scfgUnlock; + u8 twlMode; + u8 twlCLK; + u8 twlVRAM; + u8 debugMode; + u8 fastBoot; + u8 unused2; +} tLauncherSettings; + + +#ifdef __cplusplus +} +#endif + +#endif // LAUNCHERDATA_H + diff --git a/arm9/common/nds_card.c b/arm9/common/nds_card.c new file mode 100644 index 0000000..1a12b63 --- /dev/null +++ b/arm9/common/nds_card.c @@ -0,0 +1,52 @@ +/* + NitroHax -- Cheat tool for the Nintendo DS + Copyright (C) 2008 Michael "Chishm" Chisholm + + 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 3 of the License, 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, see . +*/ + +#include +#include +#include "nds_card.h" + +void CardReset (bool properReset) { + int i; + sysSetCardOwner (BUS_OWNER_ARM9); // Allow arm9 to access NDS cart + if (isDSiMode()) { + // Reset card slot + disableSlot1(); + for (i = 0; i < 15; i++) { swiWaitForVBlank(); } + enableSlot1(); + for (i = 0; i < 10; i++) { swiWaitForVBlank(); } + + if (!properReset) { + // Dummy command sent after card reset + cardParamCommand (CARD_CMD_DUMMY, 0, + CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW | CARD_BLK_SIZE(1) | CARD_DELAY1(0x1FFF) | CARD_DELAY2(0x3F), + NULL, 0); + } + } + if (!isDSiMode() || properReset) { + REG_ROMCTRL=0; + REG_AUXSPICNT=0; + for (i = 0; i < 10; i++) { swiWaitForVBlank(); } + REG_AUXSPICNT=CARD_CR1_ENABLE|CARD_CR1_IRQ; + REG_ROMCTRL=CARD_nRESET|CARD_SEC_SEED; + while (REG_ROMCTRL&CARD_BUSY); + cardReset(); + while (REG_ROMCTRL&CARD_BUSY); + } +} + + diff --git a/arm9/source/bios_decompress_callback.h b/arm9/common/nds_card.h old mode 100755 new mode 100644 similarity index 82% rename from arm9/source/bios_decompress_callback.h rename to arm9/common/nds_card.h index 618cb14..8e0d363 --- a/arm9/source/bios_decompress_callback.h +++ b/arm9/common/nds_card.h @@ -16,23 +16,21 @@ along with this program. If not, see . */ -#ifndef BIOS_DECOMPRESS_CALLBACK_H -#define BIOS_DECOMPRESS_CALLBACK_H +#ifndef NDS_CARD_H +#define NDS_CARD_H + +#include #ifdef __cplusplus extern "C" { #endif -#include -#include - -extern TDecompressionStream decompressBiosCallback; - +void CardReset (bool properReset); #ifdef __cplusplus } #endif -#endif // BIOS_DECOMPRESS_CALLBACK_H +#endif // NDS_CARD_H diff --git a/arm9/source/ndsheaderbanner.h b/arm9/common/ndsheaderbanner.h similarity index 100% rename from arm9/source/ndsheaderbanner.h rename to arm9/common/ndsheaderbanner.h diff --git a/arm9/common/nitrofs.c b/arm9/common/nitrofs.c new file mode 100644 index 0000000..39baf5a --- /dev/null +++ b/arm9/common/nitrofs.c @@ -0,0 +1,464 @@ +/* + nitrofs.c - eris's wai ossum nitro filesystem device driver + Based on information found at http://frangoassado.org/ds/rom_spec.txt and from the #dsdev ppls + Kallisti (K) 2008-01-26 All rights reversed. + + 2008-05-19 v0.2 - New And Improved!! :DDD + * fix'd the fseek SEEK_CUR issue (my fseek funct should not have returned a value :/) + * also thx to wintermute's input realized: + * if you dont give ndstool the -o wifilogo.bmp option it will run on emulators in gba mode + * you then dont need the gba's LOADEROFFSET, so it was set to 0x000 + + 2008-05-21 v0.3 - newer and more improved + * fixed some issues with ftell() (again was fseek's fault u_u;;) + * fixed possible error in detecting sc.gba files when using dldi + * readded support for .gba files in addition to .nds emu + * added stat() support for completedness :) + + 2008-05-22 v0.3.1 - slight update + * again fixed fseek(), this time SEEK_END oddly i kinda forgot about it >_> sry + * also went ahead and inlined the functions, makes slight proformance improvement + + 2008-05-26 v0.4 - added chdir + * added proper chdir functionality + + 2008-05-30 v0.5.Turbo - major speed improvement + * This version uses a single filehandle to access the .nds file when not in GBA mode + improving the speed it takes to open a .nds file by around 106ms. This is great for + situations requiring reading alot of seperate small files. However it does take a little + bit longer when reading from multiple files simultainously + (around 122ms over 10,327 0x100 byte reads between 2 files). + 2008-06-09 + * Fixed bug with SEEK_END where it wouldnt utilize the submitted position.. + (now can fseek(f,-128,SEEK_END) to read from end of file :D) + + 2008-06-18 v0.6.Turbo - . and .. :D + * Today i have added full "." and ".." support. + dirnext() will return . and .. first, and all relevent operations will + support . and .. in pathnames. + + 2009-05-10 v0.7.Turbo - small changes @_@?! + + 2009-08-08 v0.8.Turbo - fix fix fix + * fixed problem with some cards where the header would be loaded to GBA ram even if running + in NDS mode causing nitroFSInit() to think it was a valid GBA cart header and attempt to + read from GBA SLOT instead of SLOT 1. Fixed this by making it check that filename is not NULL + and then to try FAT/SLOT1 first. The NULL option allows forcing nitroFS to use gba. + + 2018-09-05 v0.9 - modernize devoptab (by RonnChyran) + * Updated for libsysbase change in devkitARM r46 and above. + +*/ + +#include +#include +#include +#include "nitrofs.h" +#include "tonccpy.h" + +//This seems to be a typo! memory.h has REG_EXEMEMCNT +#ifndef REG_EXMEMCNT +#define REG_EXMEMCNT (*(vuint16 *)0x04000204) +#endif + +#define __itcm __attribute__((section(".itcm"))) + +//Globals! +u32 fntOffset; //offset to start of filename table +u32 fatOffset; //offset to start of file alloc table +bool hasLoader; //single global nds filehandle (is null if not in dldi/fat mode) +u16 chdirpathid; //default dir path id... +FILE *ndsFile = NULL; +off_t ndsFileLastpos; //Used to determine need to fseek or not + +devoptab_t nitroFSdevoptab = { + "nitro", // const char *name; + sizeof(struct nitroFSStruct), // int structSize; + &nitroFSOpen, // int (*open_r)(struct _reent *r, void *fileStruct, const char *path,int flags,int mode); + &nitroFSClose, // int (*close_r)(struct _reent *r,void* fd); + NULL, // int (*write_r)(struct _reent *r,void* fd,const char *ptr,int len); + &nitroFSRead, // int (*read_r)(struct _reent *r,void* fd,char *ptr,int len); + &nitroFSSeek, // int (*seek_r)(struct _reent *r,void* fd,int pos,int dir); + &nitroFSFstat, // int (*fstat_r)(struct _reent *r,void* fd,struct stat *st); + &nitroFSstat, // int (*stat_r)(struct _reent *r,const char *file,struct stat *st); + NULL, // int (*link_r)(struct _reent *r,const char *existing, const char *newLink); + NULL, // int (*unlink_r)(struct _reent *r,const char *name); + &nitroFSChdir, // int (*chdir_r)(struct _reent *r,const char *name); + NULL, // int (*rename_r) (struct _reent *r, const char *oldName, const char *newName); + NULL, // int (*mkdir_r) (struct _reent *r, const char *path, int mode); + sizeof(struct nitroDIRStruct), // int dirStateSize; + &nitroFSDirOpen, // DIR_ITER* (*diropen_r)(struct _reent *r, DIR_ITER *dirState, const char *path); + &nitroDirReset, // int (*dirreset_r)(struct _reent *r, DIR_ITER *dirState); + &nitroFSDirNext, // int (*dirnext_r)(struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *filestat); + &nitroFSDirClose // int (*dirclose_r)(struct _reent *r, DIR_ITER *dirState); + +}; + +//K, i decided to inline these, improves speed slightly.. +//these 2 'sub' functions deal with actually reading from either gba rom or .nds file :) +//what i rly rly rly wanna know is how an actual nds cart reads from itself, but it seems no one can tell me ~_~ +//so, instead we have this weird weird haxy try gbaslot then try dldi method. If i (or you!!) ever do figure out +//how to read the proper way can replace these 4 functions and everything should work normally :) + +//reads from rom image either gba rom or dldi +static inline ssize_t nitroSubRead(off_t *npos, void *ptr, size_t len) +{ + if (ndsFile != NULL) + { //read from ndsfile + if (ndsFileLastpos != *npos) + fseek(ndsFile, *npos, SEEK_SET); //if we need to, move! (might want to verify this succeed) + len = fread(ptr, 1, len, ndsFile); + } + else + { //reading from gbarom + tonccpy(ptr, *npos + (void *)GBAROM, len); //len isnt checked here because other checks exist in the callers (hopefully) + } + if (len > 0) + *npos += len; + ndsFileLastpos = *npos; //save the current file nds pos + return (len); +} + +//seek around +static inline void nitroSubSeek(off_t *npos, int pos, int dir) +{ + if ((dir == SEEK_SET) || (dir == SEEK_END)) //otherwise just set the pos :) + *npos = pos; + else if (dir == SEEK_CUR) + *npos += pos; //see ez! +} + +//Figure out if its gba or ds, setup stuff +int __itcm +nitroFSInit(const char *ndsfile) +{ + off_t pos = 0; + char romstr[0x10]; + chdirpathid = NITROROOT; + ndsFileLastpos = 0; + if(ndsFile != NULL) { + fclose(ndsFile); + ndsFile = NULL; + } + if (ndsfile != NULL) + { + if ((ndsFile = fopen(ndsfile, "rb"))) + { + nitroSubRead(&pos, romstr, strlen(LOADERSTR)); + if (strncmp(romstr, LOADERSTR, strlen(LOADERSTR)) == 0) + { + nitroSubSeek(&pos, LOADEROFFSET + FNTOFFSET, SEEK_SET); + nitroSubRead(&pos, &fntOffset, sizeof(fntOffset)); + nitroSubSeek(&pos, LOADEROFFSET + FATOFFSET, SEEK_SET); + nitroSubRead(&pos, &fatOffset, sizeof(fatOffset)); + fatOffset += LOADEROFFSET; + fntOffset += LOADEROFFSET; + hasLoader = true; + } + else + { + nitroSubSeek(&pos, FNTOFFSET, SEEK_SET); + nitroSubRead(&pos, &fntOffset, sizeof(fntOffset)); + nitroSubSeek(&pos, FATOFFSET, SEEK_SET); + nitroSubRead(&pos, &fatOffset, sizeof(fatOffset)); + hasLoader = false; + } + setvbuf(ndsFile, NULL, _IONBF, 0); //we dont need double buffs u_u + if (fntOffset==0 || fatOffset==0) + { + return (0); + } + else + { + AddDevice(&nitroFSdevoptab); + return (1); + } + } + } + return (0); +} + +//Directory functs +DIR_ITER *nitroFSDirOpen(struct _reent *r, DIR_ITER *dirState, const char *path) +{ + struct nitroDIRStruct *dirStruct = (struct nitroDIRStruct *)dirState->dirStruct; //this makes it lots easier! + struct stat st; + char dirname[NITRONAMELENMAX]; + char *cptr; + char mydirpath[NITROMAXPATHLEN]; //to hold copy of path string + char *dirpath = mydirpath; + bool pathfound; + if ((cptr = strchr(path, ':'))) + path = cptr + 1; //move path past any device names (if it was nixy style wouldnt need this step >_>) + strncpy(dirpath, path, sizeof(mydirpath) - 1); //copy the string (as im gonna mutalate it) + dirStruct->pos = 0; + if (*dirpath == '/') //if first character is '/' use absolute root path plz + dirStruct->cur_dir_id = NITROROOT; //first root dir + else + dirStruct->cur_dir_id = chdirpathid; //else use chdirpath + nitroDirReset(r, dirState); //set dir to current path + do + { + while ((cptr = strchr(dirpath, '/')) == dirpath) + { + dirpath++; //move past any leading / or // together + } + if (cptr) + *cptr = 0; //erase / + if (*dirpath == 0) + { //are we at the end of the path string?? if so there is nothing to search for we're already here ! + pathfound = true; //mostly this handles searches for root or / or no path specified cases + break; + } + pathfound = false; + while (nitroFSDirNext(r, dirState, dirname, &st) == 0) + { + if ((st.st_mode == S_IFDIR) && !(strcmp(dirname, dirpath))) + { //if its a directory and name matches dirpath + dirStruct->cur_dir_id = dirStruct->dir_id; //move us to the next dir in tree + nitroDirReset(r, dirState); //set dir to current path we just found... + pathfound = true; + break; + } + }; + if (!pathfound) + break; + dirpath = cptr + 1; //move to right after last / we found + } while (cptr); // go till after the last / + if (pathfound) + { + return (dirState); + } + else + { + r->_errno = ENOENT; + return (NULL); + } +} + +int nitroFSDirClose(struct _reent *r, DIR_ITER *dirState) +{ + return (0); +} + +/*Consts containing relative system path strings*/ +const char *syspaths[2] = { + ".", + ".."}; + +//reset dir to start of entry selected by dirStruct->cur_dir_id which should be set in dirOpen okai?! +int nitroDirReset(struct _reent *r, DIR_ITER *dirState) +{ + struct nitroDIRStruct *dirStruct = (struct nitroDIRStruct *)dirState->dirStruct; //this makes it lots easier! + struct ROM_FNTDir dirsubtable; + off_t *pos = &dirStruct->pos; + nitroSubSeek(pos, fntOffset + ((dirStruct->cur_dir_id & NITRODIRMASK) * sizeof(struct ROM_FNTDir)), SEEK_SET); + nitroSubRead(pos, &dirsubtable, sizeof(dirsubtable)); + dirStruct->namepos = dirsubtable.entry_start; //set namepos to first entry in this dir's table + dirStruct->entry_id = dirsubtable.entry_file_id; //get number of first file ID in this branch + dirStruct->parent_id = dirsubtable.parent_id; //save parent ID in case we wanna add ../ functionality + dirStruct->spc = 0; //system path counter, first two dirnext's deliver . and .. + return (0); +} + +int nitroFSDirNext(struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *st) +{ + unsigned char next; + struct nitroDIRStruct *dirStruct = (struct nitroDIRStruct *)dirState->dirStruct; //this makes it lots easier! + off_t *pos = &dirStruct->pos; + if (dirStruct->spc <= 1) + { + if (st) + st->st_mode = S_IFDIR; + if ((dirStruct->spc == 0) || (dirStruct->cur_dir_id == NITROROOT)) + { // "." or its already root (no parent) + dirStruct->dir_id = dirStruct->cur_dir_id; + } + else + { // ".." + dirStruct->dir_id = dirStruct->parent_id; + } + strcpy(filename, syspaths[dirStruct->spc++]); + return (0); + } + nitroSubSeek(pos, fntOffset + dirStruct->namepos, SEEK_SET); + nitroSubRead(pos, &next, sizeof(next)); + // next: high bit 0x80 = entry isdir.. other 7 bits r size, the 16 bits following name are dir's entryid (starts with f000) + // 00 = endoftable // + if (next) + { + if (next & NITROISDIR) + { + if (st) + st->st_mode = S_IFDIR; + next &= NITROISDIR ^ 0xff; //invert bits and mask off 0x80 + nitroSubRead(pos, filename, next); + nitroSubRead(&dirStruct->pos, &dirStruct->dir_id, sizeof(dirStruct->dir_id)); //read the dir_id + //grr cant get the struct member size?, just wanna test it so moving on... + // nitroSubRead(pos,&dirStruct->dir_id,sizeof(u16)); //read the dir_id + dirStruct->namepos += next + sizeof(u16) + 1; //now we points to next one plus dir_id size:D + } + else + { + if (st) + st->st_mode = 0; + nitroSubRead(pos, filename, next); + dirStruct->namepos += next + 1; //now we points to next one :D + //read file info to get filesize (and for fileopen) + nitroSubSeek(pos, fatOffset + (dirStruct->entry_id * sizeof(struct ROM_FAT)), SEEK_SET); + nitroSubRead(pos, &dirStruct->romfat, sizeof(dirStruct->romfat)); //retrieve romfat entry (contains filestart and end positions) + dirStruct->entry_id++; //advance ROM_FNTStrFile ptr + if (st) + st->st_size = dirStruct->romfat.bottom - dirStruct->romfat.top; //calculate filesize + } + filename[(int)next] = 0; //zero last char + return (0); + } + else + { + r->_errno = EIO; + return (-1); + } +} + +//fs functs +int nitroFSOpen(struct _reent *r, void *fileStruct, const char *path, int flags, int mode) +{ + struct nitroFSStruct *fatStruct = (struct nitroFSStruct *)fileStruct; + struct nitroDIRStruct dirStruct; + DIR_ITER dirState; + dirState.dirStruct = &dirStruct; //create a temp dirstruct + struct _reent dre; + struct stat st; //all these are just used for reading the dir ~_~ + char dirfilename[NITROMAXPATHLEN]; // to hold a full path (i tried to avoid using so much stack but blah :/) + char *filename; // to hold filename + char *cptr; //used to string searching and manipulation + cptr = (char *)path + strlen(path); //find the end... + filename = NULL; + do + { + if ((*cptr == '/') || (*cptr == ':')) + { // split at either / or : (whichever comes first form the end!) + cptr++; + strncpy(dirfilename, path, cptr - path); //copy string up till and including/ or : zero rest + dirfilename[cptr - path] = 0; //it seems strncpy doesnt always zero?! + filename = cptr; //filename = now remainder of string + break; + } + } while (cptr-- != path); //search till start + if (!filename) + { //we didnt find a / or : ? shouldnt realyl happen but if it does... + filename = (char *)path; //filename = complete path + dirfilename[0] = 0; //make directory path "" + } + if (nitroFSDirOpen(&dre, &dirState, dirfilename)) + { + fatStruct->start = 0; + while (nitroFSDirNext(&dre, &dirState, dirfilename, &st) == 0) + { + if (!(st.st_mode & S_IFDIR) && (strcmp(dirfilename, filename) == 0)) + { //Found the *file* youre looking for!! + fatStruct->start = dirStruct.romfat.top; + fatStruct->end = dirStruct.romfat.bottom; + if (hasLoader) + { + fatStruct->start += LOADEROFFSET; + fatStruct->end += LOADEROFFSET; + } + break; + } + } + if (fatStruct->start) + { + nitroSubSeek(&fatStruct->pos, fatStruct->start, SEEK_SET); //seek to start of file + return (0); //woot! + } + nitroFSDirClose(&dre, &dirState); + } + if (r->_errno == 0) + { + r->_errno = ENOENT; + } + return (-1); //teh fail +} + +int nitroFSClose(struct _reent *r, void* fd) +{ + return (0); +} + +ssize_t nitroFSRead(struct _reent *r, void* fd, char *ptr, size_t len) +{ + struct nitroFSStruct *fatStruct = (struct nitroFSStruct *)fd; + off_t *npos = &fatStruct->pos; + if (*npos + len > fatStruct->end) + len = fatStruct->end - *npos; //dont let us read past the end plz! + if (*npos > fatStruct->end) + return (0); //hit eof + return (nitroSubRead(npos, ptr, len)); +} + +off_t nitroFSSeek(struct _reent *r, void* fd, off_t pos, int dir) +{ + //need check for eof here... + struct nitroFSStruct *fatStruct = (struct nitroFSStruct *)fd; + off_t *npos = &fatStruct->pos; + if (dir == SEEK_SET) + pos += fatStruct->start; //add start from .nds file offset + else if (dir == SEEK_END) + pos += fatStruct->end; //set start to end of file (useless?) + if (pos > fatStruct->end) + return (-1); //dont let us read past the end plz! + nitroSubSeek(npos, pos, dir); + return (*npos - fatStruct->start); +} + +int nitroFSFstat(struct _reent *r, void* fd, struct stat *st) +{ + struct nitroFSStruct *fatStruct = (struct nitroFSStruct *)fd; + st->st_size = fatStruct->end - fatStruct->start; + return (0); +} + +int nitroFSstat(struct _reent *r, const char *file, struct stat *st) +{ + struct nitroFSStruct fatStruct; + struct nitroDIRStruct dirStruct; + DIR_ITER dirState; + + if (nitroFSOpen(NULL, &fatStruct, file, 0, 0) >= 0) + { + st->st_mode = S_IFREG; + st->st_size = fatStruct.end - fatStruct.start; + return (0); + } + + dirState.dirStruct = &dirStruct; + if ((nitroFSDirOpen(r, &dirState, file) != NULL)) + { + + st->st_mode = S_IFDIR; + nitroFSDirClose(r, &dirState); + return (0); + } + r->_errno = ENOENT; + return (-1); +} + +int nitroFSChdir(struct _reent *r, const char *name) +{ + struct nitroDIRStruct dirStruct; + DIR_ITER dirState; + dirState.dirStruct = &dirStruct; + if ((name != NULL) && (nitroFSDirOpen(r, &dirState, name) != NULL)) + { + chdirpathid = dirStruct.cur_dir_id; + nitroFSDirClose(r, &dirState); + return (0); + } + else + { + r->_errno = ENOENT; + return (-1); + } +} \ No newline at end of file diff --git a/arm9/common/nitrofs.h b/arm9/common/nitrofs.h new file mode 100644 index 0000000..6d98b2e --- /dev/null +++ b/arm9/common/nitrofs.h @@ -0,0 +1,113 @@ +/* + nitrofs.h - eris's wai ossum nitro filesystem device driver header + Based on information found at http://frangoassado.org/ds/rom_spec.txt and from the #dsdev ppls + Kallisti (K) 2008-01-26 All rights reversed. + + 2008-05-19 v0.2 - New And Improved!! :DDD + * fix'd the fseek SEEK_CUR issue (my fseek funct should not have returned a value :/) + * also thx to wintermute's input realized: + * if you dont give ndstool the -o wifilogo.bmp option it will run on emulators in gba mode + * you then dont need the gba's LOADEROFFSET, so it was set to 0x000 + + 2008-05-21 v0.3 - newer and more improved + * fixed some issues with ftell() (again was fseek's fault u_u;;) + * fixed possible error in detecting sc.gba files when using dldi + * readded support for .gba files in addition to .nds emu + * added stat() support for completedness :) + + 2008-05-30 v0.5.Turbo - major speed improvement + * This version uses a single filehandle to access the .nds file when not in GBA mode + improving the speed it takes to open a .nds file by around 106ms. This is great for + situations requiring reading alot of seperate small files. However it does take a little + bit longer when reading from multiple files simultainously + (around 122ms over 10,327 0x100 byte reads between 2 files). + 2008-06-09 + * Fixed bug with SEEK_END where it wouldnt utilize the submitted position.. + (now can fseek(f,-128,SEEK_END) to read from end of file :D) + + 2008-06-18 v0.6.Turbo - . and .. :D + * Today i have added full "." and ".." support. + dirnext() will return . and .. first, and all relevent operations will + support . and .. in pathnames. + + 2018-09-05 v0.9 - modernize devoptab (by RonnChyran) + * Updated for libsysbase change in devkitARM r46 and above. +*/ + +#ifndef NITROFS_H +#define NITROFS_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + int nitroFSInit(const char *ndsfile); + DIR_ITER *nitroFSDirOpen(struct _reent *r, DIR_ITER *dirState, const char *path); + int nitroDirReset(struct _reent *r, DIR_ITER *dirState); + int nitroFSDirNext(struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *st); + int nitroFSDirClose(struct _reent *r, DIR_ITER *dirState); + int nitroFSOpen(struct _reent *r, void *fileStruct, const char *path, int flags, int mode); + int nitroFSClose(struct _reent *r, void *fd); + ssize_t nitroFSRead(struct _reent *r, void *fd, char *ptr, size_t len); + off_t nitroFSSeek(struct _reent *r, void *fd, off_t pos, int dir); + int nitroFSFstat(struct _reent *r, void *fd, struct stat *st); + int nitroFSstat(struct _reent *r, const char *file, struct stat *st); + int nitroFSChdir(struct _reent *r, const char *name); +#define LOADERSTR "PASS" //look for this +#define LOADERSTROFFSET 0xac +#define LOADEROFFSET 0x0200 +#define FNTOFFSET 0x40 +#define FATOFFSET 0x48 + +#define NITRONAMELENMAX 0x80 //max file name is 127 +1 for zero byte :D +#define NITROMAXPATHLEN 0x100 //256 bytes enuff? + +#define NITROROOT 0xf000 //root entry_file_id +#define NITRODIRMASK 0x0fff //remove leading 0xf + +#define NITROISDIR 0x80 //mask to indicate this name entry is a dir, other 7 bits = name length + + //Directory filename subtable entry structure + struct ROM_FNTDir + { + u32 entry_start; + u16 entry_file_id; + u16 parent_id; + }; + + //Yo, dis table is fat (describes the structures + struct ROM_FAT + { + u32 top; //start of file in rom image + u32 bottom; //end of file in rom image + }; + + struct nitroFSStruct + { + off_t pos; //where in the file am i? + off_t start; //where in the rom this file starts + off_t end; //where in the rom this file ends + }; + + struct nitroDIRStruct + { + off_t pos; //where in the file am i? + off_t namepos; //ptr to next name to lookup in list + struct ROM_FAT romfat; + u16 entry_id; //which entry this is (for files only) incremented with each new file in dir? + u16 dir_id; //which directory entry this is.. used ofc for dirs only + u16 cur_dir_id; //which directory entry we are using + u16 parent_id; //who is the parent of the current directory (this can be used to easily ../ ) + u8 spc; //system path count.. used by dirnext, when 0=./ 1=../ >=2 actual dirs + }; + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/arm9/source/read_card.c b/arm9/common/read_card.c similarity index 79% rename from arm9/source/read_card.c rename to arm9/common/read_card.c index b97387b..9b06a22 100644 --- a/arm9/source/read_card.c +++ b/arm9/common/read_card.c @@ -26,6 +26,7 @@ #include "encryption.h" #include "tonccpy.h" +#include "launcherData.h" enum { ERR_NONE = 0x00, @@ -33,13 +34,13 @@ enum { ERR_STS_LOAD_BIN = 0x02, ERR_STS_HOOK_BIN = 0x03, ERR_STS_START = 0x04, - // initCard error codes: - ERR_LOAD_NORM = 0x11, - ERR_LOAD_OTHR = 0x12, - ERR_SEC_NORM = 0x13, - ERR_SEC_OTHR = 0x14, - ERR_LOGO_CRC = 0x15, - ERR_HEAD_CRC = 0x16, + // initCard error codes: + ERR_LOAD_NORM = 0x11, + ERR_LOAD_OTHR = 0x12, + ERR_SEC_NORM = 0x13, + ERR_SEC_OTHR = 0x14, + ERR_LOGO_CRC = 0x15, + ERR_HEAD_CRC = 0x16, } ERROR_CODES; // NAND Card commands @@ -54,30 +55,24 @@ enum { #define CARD_CMD_NAND_UNKNOWN 0xBB #define CARD_CMD_NAND_READ_ID 0x94 -typedef union -{ - char title[4]; - u32 key; -} GameCode; +typedef union { char title[4]; u32 key; } GameCode; static bool twlBlowfish = false; - static bool normalChip = false; // As defined by GBAtek, normal chip secure area is accessed in blocks of 0x200, other chip in blocks of 0x1000 static u32 portFlags = 0; static u32 headerData[0x1000/sizeof(u32)] = {0}; static u32 secureArea[CARD_SECURE_AREA_SIZE/sizeof(u32)] = {0}; static u32 iCardId; +static bool noSlotCrypto = true; static bool nandChip = false; static int nandSection = -1; // -1 = ROM, above that is the current 128 KiB section in RW u32 cardNandRomEnd = 0; u32 cardNandRwStart = 0; -static const u8 cardSeedBytes[] = {0xE8, 0x4D, 0x5A, 0xB1, 0x17, 0x8F, 0x99, 0xD5}; +static const u8 cardSeedBytes[] = { 0xE8, 0x4D, 0x5A, 0xB1, 0x17, 0x8F, 0x99, 0xD5 }; -static u32 getRandomNumber(void) { - return rand(); -} +static u32 getRandomNumber(void) { return rand(); } //--------------------------------------------------------------------------------- // https://github.com/devkitPro/libnds/blob/105d4943dbac8f2bd99a47b22cd3ed48f96af083/source/common/card.c#L47-L62 @@ -106,16 +101,11 @@ static void cardPolledTransferWrite(u32 flags, u32 *buffer, u32 length, const u8 } while (REG_ROMCTRL & CARD_BUSY); } -static void decryptSecureArea (u32 gameCode, u32* secureArea, int iCardDevice) -{ +static void decryptSecureArea (u32 gameCode, u32* secureArea, int iCardDevice) { init_keycode (gameCode, 2, 8, iCardDevice); crypt_64bit_down (secureArea); - init_keycode (gameCode, 3, 8, iCardDevice); - - for (int i = 0; i < 0x200; i+= 2) { - crypt_64bit_down (secureArea + i); - } + for (int i = 0; i < 0x200; i+= 2)crypt_64bit_down (secureArea + i); } static struct { @@ -151,13 +141,10 @@ static void initKey1Encryption (u8* cmdData, int iCardDevice) { } // Note: cmdData must be aligned on a word boundary -static void createEncryptedCommand (u8 command, u8* cmdData, u32 block) -{ +static void createEncryptedCommand (u8 command, u8* cmdData, u32 block) { unsigned long iii, jjj; - if (command != CARD_CMD_SECURE_READ) { - block = key1data.llll; - } + if (command != CARD_CMD_SECURE_READ)block = key1data.llll; if (command == CARD_CMD_ACTIVATE_SEC) { iii = key1data.mmm; @@ -200,7 +187,6 @@ static void switchToTwlBlowfish(sNDSHeaderExt* ndsHeader) { if (twlBlowfish || ndsHeader->unitCode == 0) return; // Used for dumping the DSi arm9i/7i binaries - u32 portFlagsKey1, portFlagsSecRead; int secureBlockNumber; int i; @@ -317,8 +303,7 @@ static void switchToTwlBlowfish(sNDSHeaderExt* ndsHeader) { } -int cardInit (sNDSHeaderExt* ndsHeader) -{ +int cardInit (sNDSHeaderExt* ndsHeader) { u32 portFlagsKey1, portFlagsSecRead; normalChip = false; // As defined by GBAtek, normal chip secure area and header are accessed in blocks of 0x200, other chip in blocks of 0x1000 nandChip = false; @@ -327,7 +312,7 @@ int cardInit (sNDSHeaderExt* ndsHeader) int i; u8 cmdData[8] __attribute__ ((aligned)); GameCode* gameCode; - + noSlotCrypto = false; twlBlowfish = false; sysSetCardOwner (BUS_OWNER_ARM9); // Allow arm9 to access NDS cart @@ -368,8 +353,7 @@ int cardInit (sNDSHeaderExt* ndsHeader) tonccpy(ndsHeader, headerData, 0x200); - if ((ndsHeader->unitCode != 0) || (ndsHeader->dsi_flags != 0)) - { + if ((ndsHeader->unitCode != 0) || (ndsHeader->dsi_flags != 0)) { // Extended header found if(normalChip) { for(int i = 0; i < 8; i++) { @@ -481,10 +465,7 @@ int cardInit (sNDSHeaderExt* ndsHeader) cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData); //CycloDS doesn't like the dsi secure area being decrypted - if((ndsHeader->arm9romOffset != 0x4000) || secureArea[0] || secureArea[1]) - { - decryptSecureArea (gameCode->key, secureArea, 0); - } + if((ndsHeader->arm9romOffset != 0x4000) || secureArea[0] || secureArea[1])decryptSecureArea (gameCode->key, secureArea, 0); if (secureArea[0] == 0x72636e65 /*'encr'*/ && secureArea[1] == 0x6a624f79 /*'yObj'*/) { // Secure area exists, so just clear the tag @@ -510,22 +491,78 @@ int cardInit (sNDSHeaderExt* ndsHeader) return ERR_NONE; } -u32 cardGetId() { - return iCardId; +// If booted from DSi System Menu short cart init with no card reads or pokes to rom ctrl registers can be done. +// System Menu is nice enough to do this for you. :P +// (also is the case for booting from DS Download Play. ;) ) +int cardInitShort(sNDSHeaderExt* ndsHeader) { + normalChip = false; // As defined by GBAtek, normal chip secure area and header are accessed in blocks of 0x200, other chip in blocks of 0x1000 + nandChip = false; + nandSection = -1; + noSlotCrypto = true; + + GameCode* gameCode; + + twlBlowfish = false; + + sysSetCardOwner (BUS_OWNER_ARM9); // Allow arm9 to access NDS cart + + toncset(headerData, 0, 0x1000); + // tonccpy(headerData, (u32*)0x027FE940, 0x200); // Header of currently inserted cart is preserved here during DS Download Play. + tonccpy(headerData, (u32*)CartHeaderCopy, 0x180); // Header of currently inserted cart is preserved here from DSi System Menu on DSi consoles. + + iCardId = *(u32*)CartChipIDCopy; // This location contains cart's chipID when booting DSiWare that has Slot-1 access. + // iCardId = *(u32*)0x027FF800; // This location contains cart's chipID for DS Download Play users + + normalChip = (iCardId & BIT(31)) != 0; // ROM chip ID MSB + nandChip = (iCardId & BIT(27)) != 0; // Card has a NAND chip + + tonccpy(ndsHeader, headerData, 0x200); + + // Check header CRC + if (ndsHeader->headerCRC16 != swiCRC16(0xFFFF, (void*)ndsHeader, 0x15E))return ERR_HEAD_CRC; + + // Initialise blowfish encryption for KEY1 commands and decrypting the secure area + gameCode = (GameCode*)ndsHeader->gameCode; + init_keycode (gameCode->key, 2, 8, 0); + + // Port 40001A4h setting for normal reads (command B7) + portFlags = ndsHeader->cardControl13 & ~CARD_BLK_SIZE(7); + + if (secureArea[0] == 0x72636e65 /*'encr'*/ && secureArea[1] == 0x6a624f79 /*'yObj'*/) { + // Secure area exists, so just clear the tag + secureArea[0] = 0xe7ffdeff; + secureArea[1] = 0xe7ffdeff; + } + + // Set NAND card section location variables + if (nandChip) { + if(ndsHeader->nandRomEnd != 0) { + // TWL cards (Face Training) multiply by 0x80000 instead of 0x20000 + cardNandRomEnd = ndsHeader->nandRomEnd * (ndsHeader->unitCode == 0 ? 0x20000 : 0x80000); + cardNandRwStart = ndsHeader->nandRwStart * (ndsHeader->unitCode == 0 ? 0x20000 : 0x80000); + } else { + // Jam with the Band (J) (大合奏!バンドブラザーズ) doesn't have the RW section in the header + cardNandRomEnd = 0x7200000; + cardNandRwStart = 0x7200000; + } + } + + return ERR_NONE; } -void cardRead (u32 src, void* dest, bool nandSave) -{ +u32 cardGetId() { return iCardId; } + +void cardRead (u32 src, void* dest, bool nandSave) { sNDSHeaderExt* ndsHeader = (sNDSHeaderExt*)headerData; if (src >= 0 && src < 0x1000) { // Read header tonccpy (dest, (u8*)headerData + src, 0x200); return; - } else if (src < CARD_SECURE_AREA_OFFSET) { + } else if ((src < CARD_SECURE_AREA_OFFSET) && !noSlotCrypto) { toncset (dest, 0, 0x200); return; - } else if (src < CARD_DATA_OFFSET) { + } else if ((src < CARD_DATA_OFFSET) && !noSlotCrypto) { // Read data from secure area tonccpy (dest, (u8*)secureArea + src - CARD_SECURE_AREA_OFFSET, 0x200); return; @@ -547,20 +584,46 @@ void cardRead (u32 src, void* dest, bool nandSave) } } - cardParamCommand (CARD_CMD_DATA_READ, src, - portFlags | CARD_ACTIVATE | CARD_nRESET | CARD_BLK_SIZE(1), - dest, 0x200/sizeof(u32)); + cardParamCommand (CARD_CMD_DATA_READ, src, portFlags | CARD_ACTIVATE | CARD_nRESET | CARD_BLK_SIZE(1), dest, 0x200/sizeof(u32)); - if (src > ndsHeader->romSize && !(nandSave && src >= cardNandRwStart)) { - switchToTwlBlowfish(ndsHeader); + if (src > ndsHeader->romSize && !(nandSave && src >= cardNandRwStart) && !noSlotCrypto)switchToTwlBlowfish(ndsHeader); +} + +void cardReadAlt (u32 src, void* dest, size_t size) { + sNDSHeaderExt* ndsHeader = (sNDSHeaderExt*)headerData; + size_t readSize; + + if (src >= 0 && src < 0x1000) { + // Read header + tonccpy (dest, (u8*)headerData + src, 0x200); + return; + } else if ((src < CARD_SECURE_AREA_OFFSET) && !noSlotCrypto) { + toncset (dest, 0, 0x200); + return; + } else if ((src < CARD_DATA_OFFSET) && !noSlotCrypto) { + // Read data from secure area + tonccpy (dest, (u8*)secureArea + src - CARD_SECURE_AREA_OFFSET, 0x200); + return; + } else if ((ndsHeader->unitCode != 0) && (src >= ndsHeader->arm9iromOffset) && (src < ndsHeader->arm9iromOffset+CARD_SECURE_AREA_SIZE)) { + // Read data from secure area + tonccpy (dest, (u8*)secureArea + src - ndsHeader->arm9iromOffset, 0x200); + return; + } + + if ((src > ndsHeader->romSize) && !noSlotCrypto)switchToTwlBlowfish(ndsHeader); + + while (size > 0) { + readSize = size < CARD_DATA_BLOCK_SIZE ? size : CARD_DATA_BLOCK_SIZE; + cardParamCommand (CARD_CMD_DATA_READ, src, (portFlags &~CARD_BLK_SIZE(7)) | CARD_ACTIVATE | CARD_nRESET | CARD_BLK_SIZE(1), dest, readSize); + src += readSize; + dest += readSize/sizeof(*dest); + size -= readSize; } } // src must be a 0x800 byte array -void cardWriteNand (void* src, u32 dest) -{ - if (dest < cardNandRwStart || !nandChip) - return; +void cardWriteNand (void* src, u32 dest) { + if (dest < cardNandRwStart || !nandChip)return; if (nandSection != (dest - cardNandRwStart) / (128 << 10)) { if(nandSection != -1) // Need to switch back to ROM mode before switching to another RW section diff --git a/arm9/source/read_card.h b/arm9/common/read_card.h similarity index 93% rename from arm9/source/read_card.h rename to arm9/common/read_card.h index 300e860..f8821bc 100644 --- a/arm9/source/read_card.h +++ b/arm9/common/read_card.h @@ -40,8 +40,10 @@ extern u32 cardNandRomEnd; extern u32 cardNandRwStart; int cardInit (sNDSHeaderExt* ndsHeader); +int cardInitShort(sNDSHeaderExt* ndsHeader); void cardRead (u32 src, void* dest, bool nandSave); +void cardReadAlt (u32 src, void* dest, size_t size); u32 cardGetId (void); diff --git a/arm9/source/tonccpy.c b/arm9/common/tonccpy.c similarity index 100% rename from arm9/source/tonccpy.c rename to arm9/common/tonccpy.c diff --git a/arm9/source/tonccpy.h b/arm9/common/tonccpy.h similarity index 100% rename from arm9/source/tonccpy.h rename to arm9/common/tonccpy.h diff --git a/arm9/graphics/fade01.bmp b/arm9/graphics/fade01.bmp deleted file mode 100644 index e768691..0000000 Binary files a/arm9/graphics/fade01.bmp and /dev/null differ diff --git a/arm9/graphics/fade02.bmp b/arm9/graphics/fade02.bmp deleted file mode 100644 index 57c01e6..0000000 Binary files a/arm9/graphics/fade02.bmp and /dev/null differ diff --git a/arm9/graphics/fade03.bmp b/arm9/graphics/fade03.bmp deleted file mode 100644 index 9eddf04..0000000 Binary files a/arm9/graphics/fade03.bmp and /dev/null differ diff --git a/arm9/graphics/fade04.bmp b/arm9/graphics/fade04.bmp deleted file mode 100644 index f249720..0000000 Binary files a/arm9/graphics/fade04.bmp and /dev/null differ diff --git a/arm9/graphics/font.bmp b/arm9/graphics/font.bmp new file mode 100644 index 0000000..2ea9da3 Binary files /dev/null and b/arm9/graphics/font.bmp differ diff --git a/arm9/graphics/font6x8.bmp b/arm9/graphics/font6x8.bmp new file mode 100644 index 0000000..ded9b6b Binary files /dev/null and b/arm9/graphics/font6x8.bmp differ diff --git a/arm9/graphics/hbmenu_banner.bmp b/arm9/graphics/hbmenu_banner.bmp new file mode 100644 index 0000000..aa06188 Binary files /dev/null and b/arm9/graphics/hbmenu_banner.bmp differ diff --git a/arm9/graphics/hbmenu_banner_cartSelected.bmp b/arm9/graphics/hbmenu_banner_cartSelected.bmp new file mode 100644 index 0000000..41d6f2f Binary files /dev/null and b/arm9/graphics/hbmenu_banner_cartSelected.bmp differ diff --git a/arm9/graphics/hbmenu_consolebg.bmp b/arm9/graphics/hbmenu_consolebg.bmp new file mode 100644 index 0000000..fe2c0dd Binary files /dev/null and b/arm9/graphics/hbmenu_consolebg.bmp differ diff --git a/arm9/graphics/fade00.bmp b/arm9/graphics/loading.bmp similarity index 95% rename from arm9/graphics/fade00.bmp rename to arm9/graphics/loading.bmp index 377c08e..44782a4 100644 Binary files a/arm9/graphics/fade00.bmp and b/arm9/graphics/loading.bmp differ diff --git a/arm9/graphics/suberror00.bmp b/arm9/graphics/suberror00.bmp index 15129c5..56e88ea 100644 Binary files a/arm9/graphics/suberror00.bmp and b/arm9/graphics/suberror00.bmp differ diff --git a/arm9/graphics/suberror01.bmp b/arm9/graphics/suberror01.bmp index b44955b..ad165be 100644 Binary files a/arm9/graphics/suberror01.bmp and b/arm9/graphics/suberror01.bmp differ diff --git a/arm9/graphics/suberror02.bmp b/arm9/graphics/suberror02.bmp index 16a8621..1a4fa65 100644 Binary files a/arm9/graphics/suberror02.bmp and b/arm9/graphics/suberror02.bmp differ diff --git a/arm9/graphics/suberror03.bmp b/arm9/graphics/suberror03.bmp index 00b431d..a591c95 100644 Binary files a/arm9/graphics/suberror03.bmp and b/arm9/graphics/suberror03.bmp differ diff --git a/arm9/graphics/suberror04.bmp b/arm9/graphics/suberror04.bmp index 69217eb..598b453 100644 Binary files a/arm9/graphics/suberror04.bmp and b/arm9/graphics/suberror04.bmp differ diff --git a/arm9/graphics/suberror05.bmp b/arm9/graphics/suberror05.bmp index 807e9e9..f701bd7 100644 Binary files a/arm9/graphics/suberror05.bmp and b/arm9/graphics/suberror05.bmp differ diff --git a/arm9/graphics/suberror06.bmp b/arm9/graphics/suberror06.bmp index 1a772ec..7437afb 100644 Binary files a/arm9/graphics/suberror06.bmp and b/arm9/graphics/suberror06.bmp differ diff --git a/arm9/graphics/toperror2_00.bmp b/arm9/graphics/toperror2_00.bmp index b651f58..61647eb 100644 Binary files a/arm9/graphics/toperror2_00.bmp and b/arm9/graphics/toperror2_00.bmp differ diff --git a/arm9/graphics/toperror2_01.bmp b/arm9/graphics/toperror2_01.bmp index ef40549..88fc6eb 100644 Binary files a/arm9/graphics/toperror2_01.bmp and b/arm9/graphics/toperror2_01.bmp differ diff --git a/arm9/graphics/toperror2_02.bmp b/arm9/graphics/toperror2_02.bmp index 242c703..d4522af 100644 Binary files a/arm9/graphics/toperror2_02.bmp and b/arm9/graphics/toperror2_02.bmp differ diff --git a/arm9/graphics/toperror2_03.bmp b/arm9/graphics/toperror2_03.bmp index c2aa9a0..e3eafc4 100644 Binary files a/arm9/graphics/toperror2_03.bmp and b/arm9/graphics/toperror2_03.bmp differ diff --git a/arm9/graphics/toperror2_04.bmp b/arm9/graphics/toperror2_04.bmp index 242c703..d4522af 100644 Binary files a/arm9/graphics/toperror2_04.bmp and b/arm9/graphics/toperror2_04.bmp differ diff --git a/arm9/graphics/toperror2_05.bmp b/arm9/graphics/toperror2_05.bmp index ef40549..88fc6eb 100644 Binary files a/arm9/graphics/toperror2_05.bmp and b/arm9/graphics/toperror2_05.bmp differ diff --git a/arm9/graphics/toperror2_06.bmp b/arm9/graphics/toperror2_06.bmp index b651f58..61647eb 100644 Binary files a/arm9/graphics/toperror2_06.bmp and b/arm9/graphics/toperror2_06.bmp differ diff --git a/arm9/hbmenu/args.cpp b/arm9/hbmenu/args.cpp new file mode 100644 index 0000000..87d6c46 --- /dev/null +++ b/arm9/hbmenu/args.cpp @@ -0,0 +1,296 @@ +/*----------------------------------------------------------------- + Copyright (C) 2005 - 2017 + Michael "Chishm" Chisholm + Dave "WinterMute" Murphy + Claudio "sverx" + Michael "mtheall" Theall + + 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 + of the License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "args.h" + +using namespace std; + +static const string NDS_EXT = ".nds"; +static const string ARG_EXT = ".argv"; +static const string EXT_EXT = ".ext"; +static const char EXT_DIR[] = "/nds"; +static const char SEPARATORS[] = "\n\r\t "; + +/* Checks if s1 ends with s2, ignoring case. + Returns true if it does, false otherwise. + */ +static bool strCaseEnd(const string& s1, const string& s2) { + return (s1.size() >= s2.size() && + strcasecmp(s1.c_str() + s1.size() - s2.size(), s2.c_str()) == 0); +} + +/* Parses the contents of the file given by filename into argarray. Arguments + are tokenized based on whitespace. + */ +static bool parseArgFileAll(const string& filename, vector& argarray) { + FILE *argfile = fopen(filename.c_str(), "rb"); + if (!argfile) { + return false; + } + + char *line = NULL; + size_t lineSize = 0; + while (__getline(&line, &lineSize, argfile) >= 0) { + // Find comment and end string there + char *pstr = strchr(line, '#'); + if (pstr) { + *pstr = '\0'; + } + + // Tokenize arguments + char *saveptr; + pstr = strtok_r(line, SEPARATORS, &saveptr); + + while (pstr) { + argarray.emplace_back(pstr); + pstr = strtok_r(NULL, SEPARATORS, &saveptr); + } + } + + if (line) { + free(line); + } + + fclose(argfile); + + return argarray.size() > 0; +} + +/* Parses the argument file given by filename and returns the NDS file that it + * points to. + */ +static bool parseArgFileNds(const std::string& filename, std::string& ndsPath) { + bool success = false; + FILE *argfile = fopen(filename.c_str(), "rb"); + if (!argfile) { + return false; + } + + char *line = NULL; + size_t lineSize = 0; + while (__getline(&line, &lineSize, argfile) >= 0) { + char *pstr = NULL; + + // Find comment and end string there + pstr = strchr(line, '#'); + if (pstr) { + *pstr = '\0'; + } + + // Tokenize arguments + char *saveptr; + pstr = strtok_r(line, SEPARATORS, &saveptr); + + if (pstr) { + // Only want the first token, which should be the NDS file name + ndsPath = pstr; + success = true; + break; + } + } + + if (line) { + free(line); + } + + fclose(argfile); + + return success; +} + +/* Converts a plain filename into an absolute path. If it's already an absolute + * path, it is returned as-is. If basePath is NULL, the current working directory + * is used. + * Returns true on success, false on failure. + */ +static bool toAbsPath(const string& filename, const char* basePath, string& filePath) { + // Copy existing absolute or empty paths + if (filename.size() == 0 || filename[0] == '/') { + filePath = filename; + return true; + } + + if (basePath == NULL) { + // Get current working directory (uses C-strings) + vector cwd(PATH_MAX); + if (getcwd (cwd.data(), cwd.size()) == NULL) { + // Path was too long, abort + return false; + } + // Copy CWD into path + filePath = cwd.data(); + } else { + // Just copy the base path + filePath = basePath; + } + + // Ensure there's a path separator + if (filePath.back() != '/') { + filePath += '/'; + } + + // Now append the filename + filePath += filename; + + return true; +} + +/* Convert a dataFilePath to the path of the ext file that specifies the + * handler. + * Returns true on success, false on failure + */ +static bool toExtPath(const string& dataFilePath, string& extFilePath) { + // Figure out what the file extension is + size_t extPos = dataFilePath.rfind('.'); + if (extPos == string::npos) { + return false; + } + + extPos += 1; + if (extPos >= dataFilePath.size()) { + return false; + } + + // Construct handler path from extension. Handlers are in the EXT_DIR and + // end with EXT_EXT. + const string ext = dataFilePath.substr(extPos); + if (!toAbsPath(ext, EXT_DIR, extFilePath)) { + return false; + } + + extFilePath += EXT_EXT; + + return true; +} + +bool argsNdsPath(const std::string& filePath, std::string& ndsPath) { + if (strCaseEnd(filePath, NDS_EXT)) { + ndsPath = filePath; + return true; + } else if (strCaseEnd(filePath, ARG_EXT)) { + return parseArgFileNds(filePath, ndsPath); + } else { + // This is a data file associated with a handler NDS by an ext file + string extPath; + if (!toExtPath(filePath, extPath)) { + return false; + } + string ndsRelPath; + if (!parseArgFileNds(extPath, ndsRelPath)) { + return false; + } + // Handler is in EXT_DIR + return toAbsPath(ndsRelPath, EXT_DIR, ndsPath); + } + + return false; +} + +bool argsFillArray(const string& filePath, vector& argarray) { + // Ensure argarray is empty + argarray.clear(); + + if (strCaseEnd(filePath, NDS_EXT)) { + string absPath; + if (!toAbsPath(filePath, NULL, absPath)) { + return false; + } + argarray.push_back(move(absPath)); + } else if (strCaseEnd(filePath, ARG_EXT)) { + if (!parseArgFileAll(filePath, argarray)) { + return false; + } + // Ensure argv[0] is absolute path + string absPath; + if (!toAbsPath(argarray[0], NULL, absPath)) { + return false; + } + argarray[0] = absPath; + } else { + // This is a data file associated with a handler NDS by an ext file + string extPath; + + if (!toExtPath(filePath, extPath)) { + return false; + } + + // Read the arg file for the extension handler + if (!parseArgFileAll(extPath, argarray)) { + return false; + } + + // Extension handler relative path is relative to EXT_DIR, not CWD + string absPath; + if (!toAbsPath(argarray[0], EXT_DIR, absPath)) { + return false; + } + argarray[0] = absPath; + + // Add the data filename to the end. Its path is relative to CWD. + if (!toAbsPath(filePath, NULL, absPath)) { + return false; + } + argarray.push_back(move(absPath)); + } + + return argarray.size() > 0 && strCaseEnd(argarray[0], NDS_EXT); +} + +vector argsGetExtensionList() { + vector extensionList; + + // Always supported files: NDS binaries and predefined argument lists + extensionList.push_back(NDS_EXT); + extensionList.push_back(ARG_EXT); + + // Get a list of extension files: argument lists associated with a file type + DIR *dir = opendir (EXT_DIR); + if (dir) { + for (struct dirent* dirent = readdir(dir); dirent != NULL; dirent = readdir(dir)) { + // Add the name component of all files ending with EXT_EXT to the list + if (dirent->d_type != DT_REG) { + continue; + } + + if (dirent->d_name[0] != '.' && strCaseEnd(dirent->d_name, EXT_EXT)) { + size_t extPos = strlen(dirent->d_name) - EXT_EXT.size(); + dirent->d_name[extPos] = '\0'; + extensionList.push_back(dirent->d_name); + } + } + closedir(dir); + } + + return extensionList; +} + + diff --git a/arm9/hbmenu/args.h b/arm9/hbmenu/args.h new file mode 100644 index 0000000..3747356 --- /dev/null +++ b/arm9/hbmenu/args.h @@ -0,0 +1,47 @@ +/*----------------------------------------------------------------- + Copyright (C) 2005 - 2017 + Michael "Chishm" Chisholm + Dave "WinterMute" Murphy + Claudio "sverx" + Michael "mtheall" Theall + + 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 + of the License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +------------------------------------------------------------------*/ + +#ifndef ARGS_H +#define ARGS_H + +#include +#include + +/* Convert a file path of any type (e.g. .nds or .argv) into a path to the NDS + * file to be opened. The returned path may be absolute or relative to the + * current working directory. + * Returns true on success, false on failure. + */ +bool argsNdsPath(const std::string& filePath, std::string& ndsPath); + +/* Convert a file path of any type into an argument array by filling the array + * that is passed in. The first argument will be the full path to an NDS file. + * Returns true on success, false on failure. + */ +bool argsFillArray(const std::string& filePath, std::vector& argarray); + +/* Return a list of all file extensions that can be browsed and opened. + */ +std::vector argsGetExtensionList(); + +#endif // ARGS_H diff --git a/arm9/hbmenu/file_browse.cpp b/arm9/hbmenu/file_browse.cpp new file mode 100644 index 0000000..0f776d4 --- /dev/null +++ b/arm9/hbmenu/file_browse.cpp @@ -0,0 +1,361 @@ +/*----------------------------------------------------------------- + Copyright (C) 2005 - 2017 + Michael "Chishm" Chisholm + Dave "WinterMute" Murphy + Claudio "sverx" + + 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 + of the License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +------------------------------------------------------------------*/ + +#include "file_browse.h" +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "hbmenu.h" +#include "iconTitle.h" +#include "read_card.h" + +#include +#include "soundbank.h" +#include "soundbank_bin.h" + +#define SCREEN_COLS 30 +#define ENTRIES_PER_SCREEN 20 +#define ENTRIES_START_ROW 2 +#define ENTRY_PAGE_LENGTH 10 + +using namespace std; + +struct DirEntry { + string name; + bool isDirectory; +}; + +static mm_sound_effect sfxBack; +static mm_sound_effect sfxLaunch; +static mm_sound_effect sfxSelect; +static mm_sound_effect sfxWrong; +static bool audioReady = false; + +void InitAudio() { + mmInitDefaultMem((mm_addr)soundbank_bin); + + mmLoadEffect( SFX_BACK ); + mmLoadEffect( SFX_LAUNCH ); + mmLoadEffect( SFX_SELECT ); + mmLoadEffect( SFX_WRONG ); + + sfxBack = { + { SFX_BACK } , // id + (int)(1.0f * (1<<10)), // rate + 0, // handle + 255, // volume + 128, // panning + }; + + sfxLaunch = { + { SFX_LAUNCH } , // id + (int)(1.0f * (1<<10)), // rate + 0, // handle + 255, // volume + 128, // panning + }; + + sfxSelect = { + { SFX_SELECT } , // id + (int)(1.0f * (1<<10)), // rate + 0, // handle + 255, // volume + 128, // panning + }; + + sfxWrong = { + { SFX_WRONG } , // id + (int)(1.0f * (1<<10)), // rate + 0, // handle + 255, // volume + 128, // panning + }; + audioReady = true; +} + + +static ALIGN(4) sNDSHeaderExt ntrHeader; + +static bool cardInserted = false; +static bool cardLoaded = false; +static bool initialLoad = true; + +extern bool cartSelected; + + +static void cartCheck() { + switch (REG_SCFG_MC) { + case 0x10: { + if (!cardInserted)cardInserted = true; + initialLoad = false; + }break; + case 0x11: { + cardInserted = false; + initialLoad = false; + if (cartSelected)cartSelected = false; + }break; + case 0x18: { + cardInserted = true; + }break; + } + if (!cardInserted) { + if (cardLoaded) { + clearCartIcon(true); + cardLoaded = false; + if (cartSelected)cartSelected = false; + ToggleBackground(); + } + if (cartSelected)cartSelected = false; + return; + } + if (cardInserted && initialLoad) { + cardInitShort(&ntrHeader); + cartIconUpdate(0, initialLoad); + initialLoad = false; + cardLoaded = true; + } else if (cardInserted && !cardLoaded){ + cardInit(&ntrHeader); + for (int i = 0; i < 25; i++)swiWaitForVBlank(); + cartIconUpdate(ntrHeader.bannerOffset, false); + cardLoaded = true; + } +} + +bool nameEndsWith (const string& name, const vector extensionList) { + + if (name.size() == 0) return false; + if (name.front() == '.') return false; + + if (extensionList.size() == 0) return true; + + for (int i = 0; i < (int)extensionList.size(); i++) { + const string ext = extensionList.at(i); + if ( strcasecmp (name.c_str() + name.size() - ext.size(), ext.c_str()) == 0) return true; + } + return false; +} + +bool dirEntryPredicate (const DirEntry& lhs, const DirEntry& rhs) { + if (!lhs.isDirectory && rhs.isDirectory)return false; + if (lhs.isDirectory && !rhs.isDirectory)return true; + return strcasecmp(lhs.name.c_str(), rhs.name.c_str()) < 0; +} + +void getDirectoryContents (vector& dirContents, const vector extensionList) { + struct stat st; + + dirContents.clear(); + + DIR *pdir = opendir ("."); + + if (pdir == NULL) { + iprintf ("Unable to open the directory.\n"); + } else { + + while(true) { + DirEntry dirEntry; + + struct dirent* pent = readdir(pdir); + if(pent == NULL) break; + + stat(pent->d_name, &st); + dirEntry.name = pent->d_name; + dirEntry.isDirectory = (st.st_mode & S_IFDIR) ? true : false; + + if (dirEntry.name.compare(".") != 0 && (dirEntry.isDirectory || nameEndsWith(dirEntry.name, extensionList))) { + dirContents.push_back (dirEntry); + } + + } + + closedir(pdir); + } + + sort(dirContents.begin(), dirContents.end(), dirEntryPredicate); +} + +void getDirectoryContents (vector& dirContents) { + vector extensionList; + getDirectoryContents (dirContents, extensionList); +} + +void showDirectoryContents (const vector& dirContents, int startRow) { + char path[PATH_MAX]; + + getcwd(path, PATH_MAX); + + // Clear the screen + consoleClear(); + + // Print the path + if (strlen(path) < SCREEN_COLS) { + iprintf ("%s", path); + } else { + iprintf ("%s", path + strlen(path) - SCREEN_COLS); + } + + // Move to 2nd row + iprintf ("\x1b[1;0H"); + // Print line of dashes + iprintf ("------------------------------"); + + // Print directory listing + for (int i = 0; i < ((int)dirContents.size() - startRow) && i < ENTRIES_PER_SCREEN; i++) { + const DirEntry* entry = &dirContents.at(i + startRow); + char entryName[SCREEN_COLS + 1]; + + // Set row + iprintf ("\x1b[%d;0H", i + ENTRIES_START_ROW); + + if (entry->isDirectory) { + strncpy (entryName, entry->name.c_str(), SCREEN_COLS); + entryName[SCREEN_COLS - 3] = '\0'; + iprintf (" [%s]", entryName); + } else { + strncpy (entryName, entry->name.c_str(), SCREEN_COLS); + entryName[SCREEN_COLS - 1] = '\0'; + iprintf (" %s", entryName); + } + } +} + +string browseForFile (const vector& extensionList) { + if (!audioReady)InitAudio(); + int pressed = 0; + int screenOffset = 0; + int fileOffset = 0; + vector dirContents; + + getDirectoryContents (dirContents, extensionList); + showDirectoryContents (dirContents, screenOffset); + + while (true) { + // Clear old cursors + for (int i = ENTRIES_START_ROW; i < ENTRIES_PER_SCREEN + ENTRIES_START_ROW; i++) { + iprintf ("\x1b[%d;0H ", i); + } + // Show cursor + iprintf ("\x1b[%d;0H*", fileOffset - screenOffset + ENTRIES_START_ROW); + + iconTitleUpdate (dirContents.at(fileOffset).isDirectory, dirContents.at(fileOffset).name); + + // Power saving loop. Only poll the keys once per frame and sleep the CPU if there is nothing else to do + do { + cartCheck(); + scanKeys(); + pressed = keysDownRepeat(); + swiWaitForVBlank(); + } while (!pressed); + if (!cartSelected) { + if (pressed & KEY_UP) { fileOffset -= 1; mmEffectEx(&sfxSelect); } + if (pressed & KEY_DOWN) { fileOffset += 1; mmEffectEx(&sfxSelect); } + if (pressed & KEY_LEFT) { fileOffset -= ENTRY_PAGE_LENGTH; mmEffectEx(&sfxSelect); } + if (pressed & KEY_RIGHT) { fileOffset += ENTRY_PAGE_LENGTH; mmEffectEx(&sfxSelect); } + + if (fileOffset < 0)fileOffset = dirContents.size() - 1; // Wrap around to bottom of list + if (fileOffset > ((int)dirContents.size() - 1)) fileOffset = 0; // Wrap around to top of list + + // Scroll screen if needed + if (fileOffset < screenOffset) { + screenOffset = fileOffset; + showDirectoryContents (dirContents, screenOffset); + } + if (fileOffset > screenOffset + ENTRIES_PER_SCREEN - 1) { + screenOffset = fileOffset - ENTRIES_PER_SCREEN + 1; + showDirectoryContents (dirContents, screenOffset); + } + } + if ((pressed & KEY_X)) { + if (cardLoaded) { + mmEffectEx(&sfxSelect); + if (cartSelected) { + cartSelected = false; + ToggleBackground(); + } else if (cardLoaded) { + cartSelected = true; + ToggleBackground(); + } + } else { + mmEffectEx(&sfxWrong); + } + } + + + if (cartSelected) { + + if (pressed & KEY_UP)mmEffectEx(&sfxWrong); + if (pressed & KEY_DOWN)mmEffectEx(&sfxWrong); + if (pressed & KEY_LEFT)mmEffectEx(&sfxWrong); + if (pressed & KEY_RIGHT)mmEffectEx(&sfxWrong); + + + if ((pressed & KEY_A)) { + if (cardLoaded) { + mmEffectEx(&sfxLaunch); + // Clear the screen + consoleClear(); + return "CARTBOOT"; + } else { + mmEffectEx(&sfxWrong); + } + } + } else { + if (pressed & KEY_A) { + DirEntry* entry = &dirContents.at(fileOffset); + if (entry->isDirectory) { + mmEffectEx(&sfxSelect); + iprintf("Entering directory\n"); + // Enter selected directory + chdir (entry->name.c_str()); + getDirectoryContents (dirContents, extensionList); + screenOffset = 0; + fileOffset = 0; + showDirectoryContents (dirContents, screenOffset); + } else { + mmEffectEx(&sfxLaunch); + // Clear the screen + consoleClear(); + // Return the chosen file + return entry->name; + } + } + + if (pressed & KEY_B) { + mmEffectEx(&sfxBack); + // Go up a directory + chdir (".."); + getDirectoryContents (dirContents, extensionList); + screenOffset = 0; + fileOffset = 0; + showDirectoryContents (dirContents, screenOffset); + } + } + } +} + diff --git a/arm9/hbmenu/file_browse.h b/arm9/hbmenu/file_browse.h new file mode 100644 index 0000000..903b5aa --- /dev/null +++ b/arm9/hbmenu/file_browse.h @@ -0,0 +1,32 @@ +/*----------------------------------------------------------------- + Copyright (C) 2005 - 2017 + Michael "Chishm" Chisholm + Dave "WinterMute" Murphy + + 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 + of the License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +------------------------------------------------------------------*/ + +#ifndef FILE_BROWSE_H +#define FILE_BROWSE_H + +#include +#include + +std::string browseForFile (const std::vector& extensionList); + + + +#endif //FILE_BROWSE_H diff --git a/arm9/hbmenu/hbmenu.cpp b/arm9/hbmenu/hbmenu.cpp new file mode 100644 index 0000000..7becda1 --- /dev/null +++ b/arm9/hbmenu/hbmenu.cpp @@ -0,0 +1,106 @@ +/*----------------------------------------------------------------- + Copyright (C) 2005 - 2013 + Michael "Chishm" Chisholm + Dave "WinterMute" Murphy + Claudio "sverx" + + 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 + of the License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +------------------------------------------------------------------*/ +#include +#include +#include +#include +#include + +#include +#include + +#include "args.h" +#include "file_browse.h" +#include "font.h" +#include "hbmenu_consolebg.h" +#include "iconTitle.h" +#include "nds_loader_arm9.h" +#include "launcherData.h" +#include "../source/launch_engine.h" + +using namespace std; + + +static void InitGUI(void) { + iconTitleInit(); + videoSetModeSub(MODE_4_2D); + vramSetBankC(VRAM_C_SUB_BG); + int bgSub = bgInitSub(3, BgType_Bmp8, BgSize_B8_256x256, 1, 0); + PrintConsole *console = consoleInit(0, 0, BgType_Text4bpp, BgSize_T_256x256, 4, 6, false, false); + dmaCopy(hbmenu_consolebgBitmap, bgGetGfxPtr(bgSub), 256*256); + ConsoleFont font; + font.gfx = (u16*)fontTiles; + font.pal = (u16*)fontPal; + font.numChars = 95; + font.numColors = (fontPalLen / 2); + font.bpp = 4; + font.asciiOffset = 32; + font.convertSingleColor = true; + consoleSetFont(console, &font); + dmaCopy(hbmenu_consolebgPal, BG_PALETTE_SUB, 256*2); + BG_PALETTE_SUB[255] = RGB15(31,31,31); + keysSetRepeat(25,5); + consoleSetWindow(console, 1, 1, 30, 22); +} + +static int stop(void) { + while (1) { + scanKeys(); + while (!keysDown())swiWaitForVBlank(); + } + return 0; +} + +static int FileBrowser(tLauncherSettings launchdata) { + consoleClear(); + vector extensionList = argsGetExtensionList(); + chdir("sd:/NTR_Launcher"); + while(1) { + string filename = browseForFile(extensionList); + if (cartSelected)break; + // Construct a command line + vector argarray; + if (!argsFillArray(filename, argarray)) { + printf("Invalid NDS or arg file selected\n"); + } else { + iprintf("Running %s with %d parameters\n", argarray[0].c_str(), argarray.size()); + // Make a copy of argarray using C strings, for the sake of runNdsFile + vector c_args; + for (const auto& arg: argarray) { c_args.push_back(arg.c_str()); } + // Try to run the NDS file with the given arguments + int err = runNdsFile(c_args[0], c_args.size(), &c_args[0], launchdata); + iprintf("Start failed. Error %i\n", err); + break; + } + argarray.clear(); + } + if (cartSelected) { + runLaunchEngine(launchdata); + } + return stop(); +} + +void StartFileBrowser(tLauncherSettings launchdata) { + InitGUI(); + FileBrowser(launchdata); +} + diff --git a/arm9/hbmenu/hbmenu.h b/arm9/hbmenu/hbmenu.h new file mode 100644 index 0000000..d2a1cdd --- /dev/null +++ b/arm9/hbmenu/hbmenu.h @@ -0,0 +1,32 @@ +/*----------------------------------------------------------------- + Copyright (C) 2005 - 2017 + Michael "Chishm" Chisholm + Dave "WinterMute" Murphy + Claudio "sverx" + Michael "mtheall" Theall + + 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 + of the License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +------------------------------------------------------------------*/ + +#ifndef HBMENU_H +#define HBMENU_H + +#include "launcherData.h" + +void StartFileBrowser(tLauncherSettings launchdata); + +#endif // HBMENU_H + diff --git a/arm9/hbmenu/iconTitle.cpp b/arm9/hbmenu/iconTitle.cpp new file mode 100644 index 0000000..d84bb5d --- /dev/null +++ b/arm9/hbmenu/iconTitle.cpp @@ -0,0 +1,321 @@ +/*----------------------------------------------------------------- + Copyright (C) 2005 - 2013 + Michael "Chishm" Chisholm + Dave "WinterMute" Murphy + Claudio "sverx" + Michael "mtheall" Theall + + 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 + of the License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +------------------------------------------------------------------*/ + +#include +#include +#include +#include + +#include "args.h" +#include "hbmenu_banner.h" +#include "hbmenu_banner_cartSelected.h" +#include "font6x8.h" +#include "read_card.h" +#include "launcherData.h" + +#define TITLE_POS_X (13*8) +#define TITLE_POS_Y (10*4) + +#define CARTTITLE_OFFSET_Y 12 + +#define ICON_POS_X 26 +#define ICON_POS_Y 40 + +#define ICON2_POS_X 26 +#define ICON2_POS_Y 132 + + +#define TEXT_WIDTH ((22-4)*8/6) + +static int bg2, bg3; +static u16 *sprite; +static u16 *sprite2; + +static tNDSBanner banner; +static tNDSBanner* cartBanner; + +bool cartSelected = false; + +static inline void writecharRS (int row, int col, u16 car) { + // get map pointer + u16 *gfx = bgGetMapPtr(bg2); + // get old pair of values from VRAM + u16 oldval = gfx[row*(512/8/2)+(col/2)]; + + // clear the half we will update + oldval &= (col%2) ? 0x00FF : 0xFF00; + // apply the updated half + oldval |= (col%2) ? (car<<8) : car; + + // write back to VRAM + gfx[row*(512/8/2)+col/2] = oldval; +} + +static inline void writeRow (int rownum, const char* text, bool isCartBannerText) { + int row = rownum; + if (isCartBannerText)row = (rownum + CARTTITLE_OFFSET_Y); + int i,len,p=0; + len=strlen(text); + + if (len>TEXT_WIDTH)len=TEXT_WIDTH; + + // clear left part + for (i=0;i<(TEXT_WIDTH-len)/2;i++)writecharRS (row, i, 0); + + // write centered text + for (i=(TEXT_WIDTH-len)/2;i<((TEXT_WIDTH-len)/2+len);i++)writecharRS (row, i, text[p++]-' '); + + // clear right part + for (i=((TEXT_WIDTH-len)/2+len);i> Loading ... <<==", false); + writeRow (1,"=====================", false); +} + + +void iconTitleUpdate (int isdir, const std::string& name) { + writeRow (0, name.c_str(), false); + writeRow (1, "", false); + writeRow (2, "", false); + writeRow (3, "", false); + + if (isdir) { + // text + writeRow (2, "[directory]", false); + // icon + clearIcon(); + } else { + std::string ndsPath; + if (!argsNdsPath(name, ndsPath)) { + writeRow(2, "(invalid argv or NDS file!)", false); + clearIcon(); + return; + } + + unsigned int Icon_title_offset; + + // open file for reading info + FILE *fp = fopen (ndsPath.c_str(), "rb"); + + if (!fp) { + // text + writeRow (2,"(can't open file!)", false); + // icon + clearIcon(); + fclose (fp); + return; + } + + if (fseek (fp, offsetof(tNDSHeader, bannerOffset), SEEK_SET) != 0 || + fread (&Icon_title_offset, sizeof(int), 1, fp) != 1) { + // text + writeRow (2, "(can't read file!)", false); + // icon + clearIcon(); + fclose (fp); + return; + } + + if (Icon_title_offset == 0) { + // text + writeRow (2, "(no title/icon)", false); + // icon + clearIcon(); + fclose (fp); + return; + } + + if (fseek (fp, Icon_title_offset, SEEK_SET) != 0 || fread (&banner, sizeof(banner), 1, fp) != 1) { + // text + writeRow (2,"(can't read icon/title!)", false); + // icon + clearIcon(); + fclose (fp); + return; + } + + // close file! + fclose (fp); + + // turn unicode into ascii (kind of) + // and convert 0x0A into 0x00 + char *p = (char*)banner.titles[0]; + int rowOffset = 1; + int lineReturns = 0; + for (size_t i = 0; i < sizeof(banner.titles[0]); i = i+2) { + if ((p[i] == 0x0A) || (p[i] == 0xFF)) { + p[i/2] = 0; + lineReturns++; + } else { + p[i/2] = p[i]; + } + } + + if (lineReturns < 2)rowOffset = 2; // Recenter if bennar has less 2 or less rows of text maintaining empty row gap between nds file name and nds banner. + + // text + for (size_t i = 0; i < 3; ++i) { + writeRow(i+rowOffset, p, false); + p += strlen(p) + 1; + } + + // icon + DC_FlushAll(); + dmaCopy(banner.icon, sprite, sizeof(banner.icon)); + dmaCopy(banner.palette, SPRITE_PALETTE, sizeof(banner.palette)); + } +} + + +void cartIconUpdate (u32 BannerOffset, bool readExistingBanner) { + if(readExistingBanner) { + cardReadAlt(*(u32*)InitialCartBannerOffset, (u32*)CartBannerBuffer, 0x1000); + } else { + cardReadAlt(BannerOffset, (u32*)CartBannerBuffer, 0x1000); + } + switch (cartBanner->crc) { + case 0x0000: { + clearCartIcon(false); + writeRow (1,"(invalid icon/title!)", true); + return; + }break; + case 0xFFFF: { + clearCartIcon(false); + writeRow (1,"(invalid icon/title!)", true); + return; + }break; + default: { + writeRow (0, "", true); + writeRow (1, "", true); + writeRow (2, "", true); + // turn unicode into ascii (kind of) + // and convert 0x0A into 0x00 + char *p = (char*)cartBanner->titles[0]; + int rowOffset = 0; + int lineReturns = 0; + for (size_t i = 0; i < sizeof(cartBanner->titles[0]); i = i+2) { + if ((p[i] == 0x0A) || (p[i] == 0xFF)) { + p[i/2] = 0; + lineReturns++; + } else { + p[i/2] = p[i]; + } + } + + // Recenter text to center row if less then 2 rows of text. + // Default offset 0 instead of 1 since no NDS file name for this to account for. + if (lineReturns < 2 && lineReturns != 1) { + rowOffset = 1; + } else if (lineReturns == 1) { + rowOffset = 0; + } + + // text + for (size_t i = 0; i < 3; ++i) { + if ((i > 0) && (lineReturns == 1))rowOffset = 1; + writeRow(i+rowOffset, p, true); + p += strlen(p) + 1; + } + }break; + } + DC_FlushAll(); + dmaCopy(&cartBanner->icon, sprite2, 512); + dmaCopy(&cartBanner->palette, (u16*)((u32)SPRITE_PALETTE + 0x20), 0x20); +} + diff --git a/arm9/hbmenu/iconTitle.h b/arm9/hbmenu/iconTitle.h new file mode 100644 index 0000000..0f225cd --- /dev/null +++ b/arm9/hbmenu/iconTitle.h @@ -0,0 +1,30 @@ +/*----------------------------------------------------------------- + Copyright (C) 2005 - 2013 + Michael "Chishm" Chisholm + Dave "WinterMute" Murphy + Claudio "sverx" + + 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 + of the License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +------------------------------------------------------------------*/ +#include + +extern bool cartSelected; + +void clearCartIcon(bool clearBannerText); +void ToggleBackground(void); +void iconTitleInit (void); +void iconTitleUpdate (int isdir, const std::string& name); +void cartIconUpdate (u32 BannerOffset, bool readExistingBanner); diff --git a/arm9/hbmenu/nds_loader_arm9.c b/arm9/hbmenu/nds_loader_arm9.c new file mode 100644 index 0000000..0fb6b7c --- /dev/null +++ b/arm9/hbmenu/nds_loader_arm9.c @@ -0,0 +1,372 @@ +/*----------------------------------------------------------------- + Copyright (C) 2005 - 2010 + Michael "Chishm" Chisholm + Dave "WinterMute" Murphy + + 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 + of the License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +------------------------------------------------------------------*/ +#include +#include +#include +#include +#include + +#include +#include + +#include "load2_bin.h" + +#include "nds_loader_arm9.h" +#include "launcherData.h" + +#define LCDC_BANK_D (u16*)0x06860000 +#define STORED_FILE_CLUSTER (*(((u32*)LCDC_BANK_D) + 1)) +#define INIT_DISC (*(((u32*)LCDC_BANK_D) + 2)) +#define WANT_TO_PATCH_DLDI (*(((u32*)LCDC_BANK_D) + 3)) + +#define STORED_FILE_CLUSTER_OFFSET 4 +#define INIT_DISC_OFFSET 8 +#define WANT_TO_PATCH_DLDI_OFFSET 12 +#define ARG_START_OFFSET 16 +#define ARG_SIZE_OFFSET 20 +#define HAVE_DSISD_OFFSET 28 +#define DSIMODE_OFFSET 32 + +typedef signed int addr_t; +typedef unsigned char data_t; + +#define FIX_ALL 0x01 +#define FIX_GLUE 0x02 +#define FIX_GOT 0x04 +#define FIX_BSS 0x08 + +/*enum DldiOffsets { + DO_magicString = 0x00, // "\xED\xA5\x8D\xBF Chishm" + DO_magicToken = 0x00, // 0xBF8DA5ED + DO_magicShortString = 0x04, // " Chishm" + DO_version = 0x0C, + DO_driverSize = 0x0D, + DO_fixSections = 0x0E, + DO_allocatedSpace = 0x0F, + + DO_friendlyName = 0x10, + + DO_text_start = 0x40, // Data start + DO_data_end = 0x44, // Data end + DO_glue_start = 0x48, // Interworking glue start -- Needs address fixing + DO_glue_end = 0x4C, // Interworking glue end + DO_got_start = 0x50, // GOT start -- Needs address fixing + DO_got_end = 0x54, // GOT end + DO_bss_start = 0x58, // bss start -- Needs setting to zero + DO_bss_end = 0x5C, // bss end + + // IO_INTERFACE data + DO_ioType = 0x60, + DO_features = 0x64, + DO_startup = 0x68, + DO_isInserted = 0x6C, + DO_readSectors = 0x70, + DO_writeSectors = 0x74, + DO_clearStatus = 0x78, + DO_shutdown = 0x7C, + DO_code = 0x80 +};*/ + +static addr_t readAddr (data_t *mem, addr_t offset) { return ((addr_t*)mem)[offset/sizeof(addr_t)]; } + +static void writeAddr (data_t *mem, addr_t offset, addr_t value) { ((addr_t*)mem)[offset/sizeof(addr_t)] = value; } + +static void vramcpy (void* dst, const void* src, int len) { + u16* dst16 = (u16*)dst; + u16* src16 = (u16*)src; + + for ( ; len > 0; len -= 2) { *dst16++ = *src16++; } +} + +/* 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; + addr_t dataChunkEnd = (addr_t)(dataLen / sizeof(int)); + + for ( i = 0; i < dataChunkEnd; i++) { + if (dataChunk[i] == searchChunk) { + if ((i*sizeof(int) + searchLen) > dataLen)return -1; + if (memcmp (&data[i*sizeof(int)], search, searchLen) == 0)return i*sizeof(int); + } + } + 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 + +/*#define DEVICE_TYPE_DLDI 0x49444C44 + +static bool dldiPatchLoader (data_t *binData, u32 binSize, bool clearBSS) { + 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 + 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; + 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)return false; // does not have a DLDI section + + pDH = (data_t*)(io_dldi_data); + + pAH = &(binData[patchOffset]); + + if (*((u32*)(pDH + DO_ioType)) == DEVICE_TYPE_DLDI)return false; // No DLDI patch + + if (pDH[DO_driverSize] > pAH[DO_allocatedSpace])return false; // Not enough space for patch + + dldiFileSize = 1 << pDH[DO_driverSize]; + + memOffset = readAddr (pAH, DO_text_start); + if (memOffset == 0)memOffset = readAddr (pAH, DO_startup) - DO_code; + ddmemOffset = readAddr (pDH, DO_text_start); + relocationOffset = memOffset - ddmemOffset; + + ddmemStart = readAddr (pDH, DO_text_start); + ddmemSize = (1 << pDH[DO_driverSize]); + ddmemEnd = ddmemStart + ddmemSize; + + // Remember how much space is actually reserved + pDH[DO_allocatedSpace] = pAH[DO_allocatedSpace]; + // Copy the DLDI patch into the application + vramcpy (pAH, pDH, dldiFileSize); + + // Fix the section pointers in the header + writeAddr (pAH, DO_text_start, readAddr (pAH, DO_text_start) + relocationOffset); + writeAddr (pAH, DO_data_end, readAddr (pAH, DO_data_end) + relocationOffset); + writeAddr (pAH, DO_glue_start, readAddr (pAH, DO_glue_start) + relocationOffset); + writeAddr (pAH, DO_glue_end, readAddr (pAH, DO_glue_end) + relocationOffset); + writeAddr (pAH, DO_got_start, readAddr (pAH, DO_got_start) + relocationOffset); + writeAddr (pAH, DO_got_end, readAddr (pAH, DO_got_end) + relocationOffset); + writeAddr (pAH, DO_bss_start, readAddr (pAH, DO_bss_start) + relocationOffset); + writeAddr (pAH, DO_bss_end, readAddr (pAH, DO_bss_end) + relocationOffset); + // Fix the function pointers in the header + writeAddr (pAH, DO_startup, readAddr (pAH, DO_startup) + relocationOffset); + writeAddr (pAH, DO_isInserted, readAddr (pAH, DO_isInserted) + relocationOffset); + writeAddr (pAH, DO_readSectors, readAddr (pAH, DO_readSectors) + relocationOffset); + writeAddr (pAH, DO_writeSectors, readAddr (pAH, DO_writeSectors) + relocationOffset); + writeAddr (pAH, DO_clearStatus, readAddr (pAH, DO_clearStatus) + relocationOffset); + writeAddr (pAH, DO_shutdown, readAddr (pAH, 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(pAH, addrIter)) && (readAddr(pAH, addrIter) < ddmemEnd)) { + writeAddr (pAH, addrIter, readAddr(pAH, 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(pAH, addrIter)) && (readAddr(pAH, addrIter) < ddmemEnd)) { + writeAddr (pAH, addrIter, readAddr(pAH, 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(pAH, addrIter)) && (readAddr(pAH, addrIter) < ddmemEnd)) { + writeAddr (pAH, addrIter, readAddr(pAH, addrIter) + relocationOffset); + } + } + } + + if (clearBSS && (pDH[DO_fixSections] & FIX_BSS)) { + // Initialise the BSS to 0, only if the disc is being re-inited + memset (&pAH[readAddr(pDH, DO_bss_start) - ddmemStart] , 0, readAddr(pDH, DO_bss_end) - readAddr(pDH, DO_bss_start)); + } + + return true; +}*/ + +ITCM_CODE static void SetSCFG(u8 scfgUnlock, u8 twlMode, u8 twlCLK, u8 twlVRAM) { + + if (twlMode > 0) { + *((vu32*)REG_MBK1)=0x8D898581; + *((vu32*)REG_MBK2)=0x8C888480; + *((vu32*)REG_MBK3)=0x9C989490; + *((vu32*)REG_MBK4)=0x8C888480; + *((vu32*)REG_MBK5)=0x9C989490; + REG_MBK6=0x00000000; + REG_MBK7=0x07C03740; + REG_MBK8=0x07403700; + } else { + // MBK settings for NTR mode games + *((vu32*)REG_MBK1)=0x8D898581; + *((vu32*)REG_MBK2)=0x91898581; + *((vu32*)REG_MBK3)=0x91999591; + *((vu32*)REG_MBK4)=0x91898581; + *((vu32*)REG_MBK5)=0x91999591; + REG_MBK6 = 0x00003000; + REG_MBK7 = 0x00003000; + REG_MBK8 = 0x00003000; + } + + if (twlCLK == 0)REG_SCFG_CLK = 0x80; + if (twlMode > 0) { + REG_SCFG_EXT = 0x82073100; + REG_SCFG_RST = 1; + } else { + REG_SCFG_EXT=0x83002000; + } + if (twlVRAM == 0)REG_SCFG_EXT &= ~(1UL << 13); + if (scfgUnlock == 0x00)REG_SCFG_EXT &= ~(1UL << 31); + for (int i = 0; i < 10; i++) { while(REG_VCOUNT!=191); while(REG_VCOUNT==191); } +} + + +eRunNdsRetCode runNds (const void* loader, u32 loaderSize, u32 cluster, bool initDisc, bool dldiPatchNds, int argc, const char** argv, tLauncherSettings launchdata) { + char* argStart; + u16* argData; + u16 argTempVal = 0; + int argSize; + const char* argChar; + + bool scfgUnlock = false; + bool twlMode = false; + bool twlCLK = false; + bool twlVRAM = false; + + if (launchdata.scfgUnlock > 0x00)scfgUnlock = true; + if (launchdata.twlMode > 0x00)twlMode = true; + if (launchdata.twlCLK > 0x00)twlCLK = true; + if (launchdata.twlVRAM > 0x00)twlVRAM = true; + + if (!twlMode) { + fifoSendValue32(FIFO_USER_01, 1); + fifoWaitValue32(FIFO_USER_02); + } + + irqDisable(IRQ_ALL); + + SetSCFG(scfgUnlock, twlMode, twlCLK, twlVRAM); + + // Direct CPU access to VRAM bank C + VRAM_D_CR = VRAM_ENABLE | VRAM_D_LCD; + // Load the loader/patcher into the correct address + vramcpy (LCDC_BANK_D, loader, loaderSize); + + // Set the parameters for the loader + // STORED_FILE_CLUSTER = cluster; + writeAddr ((data_t*) LCDC_BANK_D, STORED_FILE_CLUSTER_OFFSET, cluster); + // INIT_DISC = initDisc; + writeAddr ((data_t*) LCDC_BANK_D, INIT_DISC_OFFSET, initDisc); + + writeAddr ((data_t*) LCDC_BANK_D, DSIMODE_OFFSET, isDSiMode()); + // if(argv[0][0]=='s' && argv[0][1]=='d') { + dldiPatchNds = false; + writeAddr ((data_t*) LCDC_BANK_D, HAVE_DSISD_OFFSET, 1); + // } + + // WANT_TO_PATCH_DLDI = dldiPatchNds; + // writeAddr ((data_t*) LCDC_BANK_D, WANT_TO_PATCH_DLDI_OFFSET, dldiPatchNds); + writeAddr ((data_t*) LCDC_BANK_D, WANT_TO_PATCH_DLDI_OFFSET, false); + // Give arguments to loader + argStart = (char*)LCDC_BANK_D + readAddr((data_t*)LCDC_BANK_D, ARG_START_OFFSET); + argStart = (char*)(((int)argStart + 3) & ~3); // Align to word + argData = (u16*)argStart; + argSize = 0; + + for (; argc > 0 && *argv; ++argv, --argc) { + for (argChar = *argv; *argChar != 0; ++argChar, ++argSize) { + if (argSize & 1) { + argTempVal |= (*argChar) << 8; + *argData = argTempVal; + ++argData; + } else { + argTempVal = *argChar; + } + } + if (argSize & 1) { *argData = argTempVal; ++argData; } + argTempVal = 0; + ++argSize; + } + + *argData = argTempVal; + + writeAddr ((data_t*) LCDC_BANK_D, ARG_START_OFFSET, (addr_t)argStart - (addr_t)LCDC_BANK_D); + writeAddr ((data_t*) LCDC_BANK_D, ARG_SIZE_OFFSET, argSize); + + /*if(dldiPatchNds) { + // Patch the loader with a DLDI for the card + if (!dldiPatchLoader ((data_t*)LCDC_BANK_D, loaderSize, initDisc))return RUN_NDS_PATCH_DLDI_FAILED; + }*/ + + irqDisable(IRQ_ALL); + + *(tLauncherSettings*)LAUNCH_DATA = launchdata; + + // Give the VRAM to the ARM7 + VRAM_D_CR = VRAM_ENABLE | VRAM_D_ARM7_0x06020000; + // Reset into a passme loop + REG_EXMEMCNT |= ARM7_OWNS_ROM | ARM7_OWNS_CARD; + *((vu32*)0x02FFFFFC) = 0; + *((vu32*)0x02FFFE04) = (u32)0xE59FF018; + *((vu32*)0x02FFFE24) = (u32)0x02FFFE04; + + resetARM7(0x06020000); + + swiSoftReset(); + return RUN_NDS_OK; +} + +eRunNdsRetCode runNdsFile (const char* filename, int argc, const char** argv, tLauncherSettings launchData) { + struct stat st; + char filePath[PATH_MAX]; + int pathLen; + const char* args[1]; + + + if (stat (filename, &st) < 0)return RUN_NDS_STAT_FAILED; + + if (argc <= 0 || !argv) { + // Construct a command line if we weren't supplied with one + if (!getcwd (filePath, PATH_MAX))return RUN_NDS_GETCWD_FAILED; + pathLen = strlen (filePath); + strcpy (filePath + pathLen, filename); + args[0] = filePath; + argv = args; + } + + // bool havedsiSD = false; + + // if(argv[0][0]=='s' && argv[0][1]=='d') havedsiSD = true; + + return runNds (load2_bin, load2_bin_size, st.st_ino, true, true, argc, argv, launchData); +} + diff --git a/arm9/hbmenu/nds_loader_arm9.h b/arm9/hbmenu/nds_loader_arm9.h new file mode 100644 index 0000000..0d5ff79 --- /dev/null +++ b/arm9/hbmenu/nds_loader_arm9.h @@ -0,0 +1,51 @@ +/*----------------------------------------------------------------- + Copyright (C) 2005 - 2010 + Michael "Chishm" Chisholm + Dave "WinterMute" Murphy + + 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 + of the License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +------------------------------------------------------------------*/ + +#ifndef NDS_LOADER_ARM9_H +#define NDS_LOADER_ARM9_H + +#include "launcherData.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + RUN_NDS_OK = 0, + RUN_NDS_STAT_FAILED, + RUN_NDS_GETCWD_FAILED, + RUN_NDS_PATCH_DLDI_FAILED, +} eRunNdsRetCode; + +#define LOAD_DEFAULT_NDS 0 + +eRunNdsRetCode runNds (const void* loader, u32 loaderSize, u32 cluster, bool initDisc, bool dldiPatchNds, int argc, const char** argv, tLauncherSettings launchdata); + +eRunNdsRetCode runNdsFile (const char* filename, int argc, const char** argv, tLauncherSettings launchData); + +// bool installBootStub(bool havedsiSD); + +#ifdef __cplusplus +} +#endif + +#endif // NDS_LOADER_ARM7_H + diff --git a/arm9/music/back.wav b/arm9/music/back.wav new file mode 100644 index 0000000..71dda5f Binary files /dev/null and b/arm9/music/back.wav differ diff --git a/arm9/music/dsboot.wav b/arm9/music/dsboot.wav index 0fc9475..55e5572 100644 Binary files a/arm9/music/dsboot.wav and b/arm9/music/dsboot.wav differ diff --git a/arm9/music/dsiboot.wav b/arm9/music/dsiboot.wav index c23579b..418343f 100644 Binary files a/arm9/music/dsiboot.wav and b/arm9/music/dsiboot.wav differ diff --git a/arm9/music/launch.wav b/arm9/music/launch.wav new file mode 100644 index 0000000..72529c1 Binary files /dev/null and b/arm9/music/launch.wav differ diff --git a/arm9/music/select.wav b/arm9/music/select.wav new file mode 100644 index 0000000..e0fea3b Binary files /dev/null and b/arm9/music/select.wav differ diff --git a/arm9/music/wrong.wav b/arm9/music/wrong.wav new file mode 100644 index 0000000..0f42033 Binary files /dev/null and b/arm9/music/wrong.wav differ diff --git a/arm9/source/bios_decompress_callback.c b/arm9/source/bios_decompress_callback.c deleted file mode 100755 index 92a79c8..0000000 --- a/arm9/source/bios_decompress_callback.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - NitroHax -- Cheat tool for the Nintendo DS - Copyright (C) 2008 Michael "Chishm" Chisholm - - 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 3 of the License, 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, see . -*/ - -#include "bios_decompress_callback.h" - -static int getSizeBiosCallback (uint8 * source, uint16 * dest, uint32 r2) -{ - (void)dest; - (void)r2; - return *((int*)source); -} - -static uint8 readByteBiosCallback (uint8 * source) -{ - return *source; -} - -TDecompressionStream decompressBiosCallback = -{ - getSizeBiosCallback, - (void*)0, - readByteBiosCallback -} ; - - diff --git a/arm9/source/bootsplash.cpp b/arm9/source/bootsplash.cpp index 359f2a2..b4fa3b8 100644 --- a/arm9/source/bootsplash.cpp +++ b/arm9/source/bootsplash.cpp @@ -19,14 +19,15 @@ #include #include #include +#include #include "soundbank.h" #include "soundbank_bin.h" - -#include "bios_decompress_callback.h" #include "bootsplash.h" +#include "loading.h" + // English #include "CartPrompt01.h" #include "CartPrompt02.h" @@ -266,11 +267,6 @@ #include "DSi35.h" // Error Splash -#include "fade00.h" -#include "fade01.h" -#include "fade02.h" -#include "fade03.h" -#include "fade04.h" #include "suberror00.h" #include "suberror01.h" #include "suberror02.h" @@ -333,47 +329,47 @@ void BootJingleDSi() { } void CartridgePrompt() { - swiDecompressLZSSVram ((void*)Bot05Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)Bot05Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], Bot05Pal, Bot05PalLen); for (int i = 0; i < 20; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)CartPrompt04Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)CartPrompt04Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], CartPrompt04Pal, CartPrompt04PalLen); for (int i = 0; i < 4; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)CartPrompt03Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)CartPrompt03Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], CartPrompt03Pal, CartPrompt03PalLen); for (int i = 0; i < 4; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)CartPrompt02Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)CartPrompt02Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], CartPrompt02Pal, CartPrompt02PalLen); for (int i = 0; i < 4; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)CartPrompt01Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)CartPrompt01Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], CartPrompt01Pal, CartPrompt01PalLen); for (int i = 0; i < 40; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)CartPrompt02Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)CartPrompt02Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], CartPrompt02Pal, CartPrompt02PalLen); for (int i = 0; i < 4; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)CartPrompt03Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)CartPrompt03Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], CartPrompt03Pal, CartPrompt03PalLen); for (int i = 0; i < 4; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)CartPrompt04Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)CartPrompt04Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], CartPrompt04Pal, CartPrompt04PalLen); for (int i = 0; i < 4; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)Bot05Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)Bot05Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], Bot05Pal, Bot05PalLen); for (int i = 0; i < 20; i++) { swiWaitForVBlank(); } @@ -382,47 +378,47 @@ void CartridgePrompt() { void CartridgePromptFR() { - swiDecompressLZSSVram ((void*)Bot05FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)Bot05FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], Bot05FRPal, Bot05FRPalLen); for (int i = 0; i < 20; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)CartPrompt04FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)CartPrompt04FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], CartPrompt04FRPal, CartPrompt04FRPalLen); for (int i = 0; i < 4; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)CartPrompt03FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)CartPrompt03FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], CartPrompt03FRPal, CartPrompt03FRPalLen); for (int i = 0; i < 4; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)CartPrompt02FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)CartPrompt02FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], CartPrompt02FRPal, CartPrompt02FRPalLen); for (int i = 0; i < 4; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)CartPrompt01FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)CartPrompt01FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], CartPrompt01FRPal, CartPrompt01FRPalLen); for (int i = 0; i < 40; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)CartPrompt02FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)CartPrompt02FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], CartPrompt02FRPal, CartPrompt02FRPalLen); for (int i = 0; i < 4; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)CartPrompt03FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)CartPrompt03FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], CartPrompt03FRPal, CartPrompt03FRPalLen); for (int i = 0; i < 4; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)CartPrompt04FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)CartPrompt04FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], CartPrompt04FRPal, CartPrompt04FRPalLen); for (int i = 0; i < 4; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)Bot05FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)Bot05FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], Bot05FRPal, Bot05PalLen); for (int i = 0; i < 20; i++) { swiWaitForVBlank(); } @@ -431,47 +427,47 @@ void CartridgePromptFR() { void CartridgePromptIT() { - swiDecompressLZSSVram ((void*)Bot05ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)Bot05ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], Bot05ITPal, Bot05ITPalLen); for (int i = 0; i < 20; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)CartPrompt04ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)CartPrompt04ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], CartPrompt04ITPal, CartPrompt04ITPalLen); for (int i = 0; i < 4; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)CartPrompt03ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)CartPrompt03ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], CartPrompt03ITPal, CartPrompt03ITPalLen); for (int i = 0; i < 4; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)CartPrompt02ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)CartPrompt02ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], CartPrompt02ITPal, CartPrompt02ITPalLen); for (int i = 0; i < 4; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)CartPrompt01ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)CartPrompt01ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], CartPrompt01ITPal, CartPrompt01ITPalLen); for (int i = 0; i < 40; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)CartPrompt02ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)CartPrompt02ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], CartPrompt02ITPal, CartPrompt02ITPalLen); for (int i = 0; i < 4; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)CartPrompt03ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)CartPrompt03ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], CartPrompt03ITPal, CartPrompt03ITPalLen); for (int i = 0; i < 4; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)CartPrompt04ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)CartPrompt04ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], CartPrompt04ITPal, CartPrompt04ITPalLen); for (int i = 0; i < 4; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)Bot05ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)Bot05ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], Bot05ITPal, Bot05ITPalLen); for (int i = 0; i < 20; i++) { swiWaitForVBlank(); } @@ -481,47 +477,47 @@ void CartridgePromptIT() { void CartridgePromptDSi() { - swiDecompressLZSSVram ((void*)BotDSi05Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)BotDSi05Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], BotDSi05Pal, Bot05PalLen); for (int i = 0; i < 20; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSiCartPrompt04Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)DSiCartPrompt04Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], DSiCartPrompt04Pal, DSiCartPrompt04PalLen); for (int i = 0; i < 4; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSiCartPrompt03Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)DSiCartPrompt03Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], DSiCartPrompt03Pal, DSiCartPrompt03PalLen); for (int i = 0; i < 4; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSiCartPrompt02Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)DSiCartPrompt02Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], DSiCartPrompt02Pal, DSiCartPrompt02PalLen); for (int i = 0; i < 4; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSiCartPrompt01Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)DSiCartPrompt01Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], DSiCartPrompt01Pal, DSiCartPrompt01PalLen); for (int i = 0; i < 40; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSiCartPrompt02Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)DSiCartPrompt02Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], DSiCartPrompt02Pal, DSiCartPrompt02PalLen); for (int i = 0; i < 4; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSiCartPrompt03Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)DSiCartPrompt03Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], DSiCartPrompt03Pal, DSiCartPrompt03PalLen); for (int i = 0; i < 4; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSiCartPrompt04Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)DSiCartPrompt04Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], DSiCartPrompt04Pal, DSiCartPrompt04PalLen); for (int i = 0; i < 4; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)BotDSi05Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)BotDSi05Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], BotDSi05Pal, BotDSi05PalLen); for (int i = 0; i < 20; i++) { swiWaitForVBlank(); } @@ -530,47 +526,47 @@ void CartridgePromptDSi() { void CartridgePromptNoHS() { - swiDecompressLZSSVram ((void*)WhiteTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)WhiteTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], WhitePal, WhitePalLen); for (int i = 0; i < 20; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)CartPromptNoHS04Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)CartPromptNoHS04Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], CartPromptNoHS04Pal, CartPrompt04PalLen); for (int i = 0; i < 4; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)CartPromptNoHS03Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)CartPromptNoHS03Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], CartPromptNoHS03Pal, CartPrompt03PalLen); for (int i = 0; i < 4; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)CartPromptNoHS02Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)CartPromptNoHS02Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], CartPromptNoHS02Pal, CartPrompt02PalLen); for (int i = 0; i < 4; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)CartPromptNoHS01Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)CartPromptNoHS01Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], CartPromptNoHS01Pal, CartPrompt01PalLen); for (int i = 0; i < 40; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)CartPromptNoHS02Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)CartPromptNoHS02Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], CartPromptNoHS02Pal, CartPrompt02PalLen); for (int i = 0; i < 4; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)CartPromptNoHS03Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)CartPromptNoHS03Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], CartPromptNoHS03Pal, CartPrompt03PalLen); for (int i = 0; i < 4; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)CartPromptNoHS04Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)CartPromptNoHS04Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], CartPromptNoHS04Pal, CartPrompt04PalLen); for (int i = 0; i < 4; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)WhiteTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)WhiteTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE_SUB[0], WhitePal, WhitePalLen); for (int i = 0; i < 20; i++) { swiWaitForVBlank(); } @@ -579,15 +575,15 @@ void CartridgePromptNoHS() { void BootSplashDSi(bool HealthandSafety_MSG, int language) { - swiDecompressLZSSVram ((void*)DSi01Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); - swiDecompressLZSSVram ((void*)BotDSi00Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)DSi01Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); + decompress ((void*)BotDSi00Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], DSi01Pal, DSi01PalLen); vramcpy_ui (&BG_PALETTE_SUB[0], BotDSi00Pal, BotDSi00PalLen); for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi01Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); - swiDecompressLZSSVram ((void*)BotDSi00Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)DSi01Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); + decompress ((void*)BotDSi00Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], DSi02Pal, DSi02PalLen); switch (language) { case 0: @@ -607,8 +603,8 @@ void BootSplashDSi(bool HealthandSafety_MSG, int language) { for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi01Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)BotDSi00Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + decompress ((void*)DSi01Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); + if(HealthandSafety_MSG) { decompress ((void*)BotDSi00Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } vramcpy_ui (&BG_PALETTE[0], DSi02Pal, DSi02PalLen); switch (language) { case 0: @@ -629,18 +625,18 @@ void BootSplashDSi(bool HealthandSafety_MSG, int language) { for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi01Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi01Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); switch (language) { case 0: case 2: case 3: case 4: case 5: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot01Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot01Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 1: default: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)BotDSi01Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)BotDSi01Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 6: case 7: @@ -674,26 +670,26 @@ void BootSplashDSi(bool HealthandSafety_MSG, int language) { for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi02Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi02Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); switch (language) { case 0: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot02JATiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot02JATiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 1: default: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)BotDSi02Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)BotDSi02Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 2: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot02FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot02FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 3: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot02DETiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot02DETiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 4: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot02ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot02ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 5: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot02ESTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot02ESTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 6: case 7: @@ -726,30 +722,30 @@ void BootSplashDSi(bool HealthandSafety_MSG, int language) { } for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi03Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi03Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); switch (language) { case 0: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot03JATiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot03JATiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 1: default: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)BotDSi03Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)BotDSi03Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 2: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot03FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot03FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 3: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot03DETiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot03DETiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 4: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot03ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot03ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 5: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot03ESTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot03ESTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 6: case 7: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot03JATiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot03JATiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; } vramcpy_ui (&BG_PALETTE[0], DSi03Pal, DSi03PalLen); @@ -780,26 +776,26 @@ void BootSplashDSi(bool HealthandSafety_MSG, int language) { for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi04Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi04Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); switch (language) { case 0: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot04JATiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot04JATiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 1: default: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)BotDSi04Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)BotDSi04Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 2: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot04FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot04FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 3: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot04DETiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot04DETiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 4: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot04ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot04ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 5: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot04ESTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot04ESTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 6: case 7: @@ -835,26 +831,26 @@ void BootSplashDSi(bool HealthandSafety_MSG, int language) { for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi05Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi05Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); switch (language) { case 0: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot05JATiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot05JATiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 1: default: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)BotDSi05Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)BotDSi05Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 2: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot05FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot05FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 3: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot05DETiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot05DETiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 4: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot05ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot05ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 5: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot05ESTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot05ESTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 6: case 7: @@ -888,117 +884,117 @@ void BootSplashDSi(bool HealthandSafety_MSG, int language) { for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi06Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi06Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], DSi06Pal, DSi06PalLen); for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi07Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi07Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], DSi07Pal, DSi07PalLen); for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi08Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi08Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], DSi08Pal, DSi08PalLen); for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi09Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi09Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], DSi09Pal, DSi09PalLen); for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi10Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi10Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], DSi10Pal, DSi10PalLen); for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi11Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi11Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], DSi11Pal, DSi11PalLen); for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi12Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi12Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], DSi12Pal, DSi12PalLen); for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi13Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi13Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], DSi13Pal, DSi13PalLen); for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi14Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi14Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], DSi14Pal, DSi14PalLen); for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi15Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi15Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], DSi15Pal, DSi15PalLen); for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi16Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi16Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], DSi16Pal, DSi16PalLen); for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi17Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi17Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], DSi17Pal, DSi17PalLen); for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi18Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi18Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], DSi18Pal, DSi18PalLen); for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi19Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi19Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], DSi19Pal, DSi19PalLen); for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi20Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi20Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], DSi20Pal, DSi20PalLen); for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi21Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi21Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], DSi21Pal, DSi21PalLen); for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi22Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi22Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], DSi22Pal, DSi22PalLen); for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi23Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi23Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], DSi23Pal, DSi23PalLen); for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi24Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi24Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], DSi24Pal, DSi24PalLen); for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi25Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi25Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], DSi25Pal, DSi25PalLen); for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi26Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi26Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], DSi26Pal, DSi26PalLen); for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi27Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi27Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], DSi27Pal, DSi27PalLen); for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi28Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi28Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], DSi28Pal, DSi28PalLen); if(REG_SCFG_MC == 0x11) { @@ -1040,26 +1036,26 @@ void BootSplashDSi(bool HealthandSafety_MSG, int language) { // Pause on frame 31 for a second for (int i = 0; i < 80; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi29Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi29Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); switch (language) { case 0: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot04JATiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot04JATiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 1: default: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)BotDSi06Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)BotDSi06Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 2: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot04FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot04FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 3: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot04DETiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot04DETiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 4: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot04ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot04ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 5: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot04ESTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot04ESTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 6: case 7: @@ -1093,26 +1089,26 @@ void BootSplashDSi(bool HealthandSafety_MSG, int language) { for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi30Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi30Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); switch (language) { case 0: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot03JATiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot03JATiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 1: default: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)BotDSi07Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)BotDSi07Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 2: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot03FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot03FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 3: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot03DETiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot03DETiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 4: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot03ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot03ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 5: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot03ESTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot03ESTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 6: case 7: @@ -1146,26 +1142,26 @@ void BootSplashDSi(bool HealthandSafety_MSG, int language) { for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi31Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi31Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); switch (language) { case 0: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot02JATiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot02JATiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 1: default: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)BotDSi08Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)BotDSi08Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 2: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot02FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot02FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 3: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot02DETiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot02DETiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 4: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot02ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot02ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 5: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot02ESTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot02ESTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 6: case 7: @@ -1199,7 +1195,7 @@ void BootSplashDSi(bool HealthandSafety_MSG, int language) { for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi32Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi32Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); switch (language) { case 0: case 2: @@ -1208,11 +1204,11 @@ void BootSplashDSi(bool HealthandSafety_MSG, int language) { case 5: case 6: case 7: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot01Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot01Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 1: default: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)BotDSi09Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)BotDSi09Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; } vramcpy_ui (&BG_PALETTE[0], DSi32Pal, DSi32PalLen); @@ -1234,7 +1230,7 @@ void BootSplashDSi(bool HealthandSafety_MSG, int language) { for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi33Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi33Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); switch (language) { case 0: case 2: @@ -1243,11 +1239,11 @@ void BootSplashDSi(bool HealthandSafety_MSG, int language) { case 5: case 6: case 7: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot00Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot00Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 1: default: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)BotDSi10Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)BotDSi10Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; } vramcpy_ui (&BG_PALETTE[0], DSi33Pal, DSi33PalLen); @@ -1269,7 +1265,7 @@ void BootSplashDSi(bool HealthandSafety_MSG, int language) { for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi34Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)DSi34Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); switch (language) { case 0: case 2: @@ -1281,7 +1277,7 @@ void BootSplashDSi(bool HealthandSafety_MSG, int language) { break; case 1: default: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)BotDSi11Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)BotDSi11Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; } vramcpy_ui (&BG_PALETTE[0], DSi34Pal, DSi34PalLen); @@ -1302,41 +1298,44 @@ void BootSplashDSi(bool HealthandSafety_MSG, int language) { for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi35Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)BotDSi00Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + decompress ((void*)DSi35Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); + if(HealthandSafety_MSG) { decompress ((void*)BotDSi00Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } vramcpy_ui (&BG_PALETTE[0], DSi35Pal, DSi35PalLen); if(HealthandSafety_MSG) { vramcpy_ui (&BG_PALETTE_SUB[0], BotDSi00Pal, BotDSi00PalLen); } - for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } + for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)DSi01Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); - vramcpy_ui (&BG_PALETTE[0], DSi01Pal, DSi01PalLen); + decompress ((void*)WhiteTiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); + vramcpy_ui (&BG_PALETTE[0], WhitePal, WhitePalLen); + + decompress ((void*)WhiteTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); + vramcpy_ui (&BG_PALETTE_SUB[0], WhitePal, WhitePalLen); } void BootSplashDS(bool HealthandSafety_MSG, int language) { // offsetting palletes by one frame during the fade in seems to fix black flicker at start. // only did this for about 5 frames. (time it takes for bottom screen to fade in) - swiDecompressLZSSVram ((void*)WhiteTiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); - swiDecompressLZSSVram ((void*)Bot00Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)WhiteTiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); + decompress ((void*)Bot00Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top001Pal, Top001PalLen); vramcpy_ui (&BG_PALETTE_SUB[0], Bot01Pal, Bot01PalLen); - swiDecompressLZSSVram ((void*)WhiteTiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); - swiDecompressLZSSVram ((void*)Bot00Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)WhiteTiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); + decompress ((void*)Bot00Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], WhitePal, WhitePalLen); vramcpy_ui (&BG_PALETTE_SUB[0], Bot00Pal, Bot00PalLen); - swiDecompressLZSSVram ((void*)WhiteTiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); - swiDecompressLZSSVram ((void*)Bot00Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)WhiteTiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); + decompress ((void*)Bot00Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], WhitePal, WhitePalLen); vramcpy_ui (&BG_PALETTE_SUB[0], Bot00Pal, Bot00PalLen); - swiDecompressLZSSVram ((void*)Top001Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot01Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + decompress ((void*)Top001Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); + if(HealthandSafety_MSG) { decompress ((void*)Bot01Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } vramcpy_ui (&BG_PALETTE[0], Top002Pal, Top002PalLen); switch (language) { case 0: @@ -1364,26 +1363,26 @@ void BootSplashDS(bool HealthandSafety_MSG, int language) { } - swiDecompressLZSSVram ((void*)Top002Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top002Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); switch (language) { case 0: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot02JATiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot02JATiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 1: default: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot02Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot02Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 2: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot02FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot02FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 3: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot02DETiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot02DETiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 4: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot02ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot02ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 5: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot02ESTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot02ESTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 6: case 7: @@ -1416,14 +1415,14 @@ void BootSplashDS(bool HealthandSafety_MSG, int language) { } - swiDecompressLZSSVram ((void*)Top003Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top003Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); switch (language) { case 0: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot03JATiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot03JATiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 1: default: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot03Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot03Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 2: if(HealthandSafety_MSG) { vramcpy_ui (&BG_PALETTE_SUB[0], Bot03FRPal, Bot03FRPalLen); } @@ -1468,26 +1467,26 @@ void BootSplashDS(bool HealthandSafety_MSG, int language) { } - swiDecompressLZSSVram ((void*)Top004Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top004Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); switch (language) { case 0: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot04JATiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot04JATiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 1: default: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot04Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot04Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 2: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot04FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot04FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 3: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot04DETiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot04DETiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 4: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot04ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot04ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 5: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot04ESTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot04ESTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 6: case 7: @@ -1520,26 +1519,26 @@ void BootSplashDS(bool HealthandSafety_MSG, int language) { } - swiDecompressLZSSVram ((void*)Top005Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top005Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); switch (language) { case 0: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot05JATiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot05JATiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 1: default: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot05Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot05Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 2: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot05FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot05FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 3: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot05DETiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot05DETiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 4: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot05ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot05ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 5: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot05ESTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot05ESTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 6: case 7: @@ -1555,16 +1554,16 @@ void BootSplashDS(bool HealthandSafety_MSG, int language) { if(HealthandSafety_MSG) { vramcpy_ui (&BG_PALETTE_SUB[0], Bot05Pal, Bot05PalLen); } break; case 2: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot05FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot05FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 3: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot05DETiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot05DETiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 4: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot05ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot05ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 5: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot05ESTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot05ESTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 6: case 7: @@ -1573,323 +1572,323 @@ void BootSplashDS(bool HealthandSafety_MSG, int language) { - swiDecompressLZSSVram ((void*)Top006Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top006Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top006Pal, Top006PalLen); - swiDecompressLZSSVram ((void*)Top007Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top007Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top007Pal, Top007PalLen); - swiDecompressLZSSVram ((void*)Top008Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top008Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top008Pal, Top008PalLen); - swiDecompressLZSSVram ((void*)Top009Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top009Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top009Pal, Top009PalLen); - swiDecompressLZSSVram ((void*)Top010Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top010Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top010Pal, Top010PalLen); - swiDecompressLZSSVram ((void*)Top011Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top011Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top011Pal, Top011PalLen); - swiDecompressLZSSVram ((void*)Top012Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top012Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top012Pal, Top012PalLen); - swiDecompressLZSSVram ((void*)Top013Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top013Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top013Pal, Top013PalLen); - swiDecompressLZSSVram ((void*)Top014Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top014Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top014Pal, Top014PalLen); - swiDecompressLZSSVram ((void*)Top015Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top015Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top015Pal, Top015PalLen); - swiDecompressLZSSVram ((void*)Top016Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top016Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top016Pal, Top016PalLen); - swiDecompressLZSSVram ((void*)Top017Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top017Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top017Pal, Top017PalLen); - swiDecompressLZSSVram ((void*)Top018Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top018Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top018Pal, Top018PalLen); - swiDecompressLZSSVram ((void*)Top019Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top019Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top019Pal, Top019PalLen); - swiDecompressLZSSVram ((void*)Top020Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top020Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top020Pal, Top020PalLen); - swiDecompressLZSSVram ((void*)Top021Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top021Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top021Pal, Top021PalLen); - swiDecompressLZSSVram ((void*)Top022Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top022Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top022Pal, Top022PalLen); - swiDecompressLZSSVram ((void*)Top023Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top023Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top023Pal, Top023PalLen); - swiDecompressLZSSVram ((void*)Top024Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top024Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top024Pal, Top024PalLen); - swiDecompressLZSSVram ((void*)Top025Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top025Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top025Pal, Top025PalLen); BootJingle(); - swiDecompressLZSSVram ((void*)Top026Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top026Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top026Pal, Top026PalLen); - swiDecompressLZSSVram ((void*)Top027Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top027Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top027Pal, Top027PalLen); - swiDecompressLZSSVram ((void*)Top028Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top028Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top028Pal, Top028PalLen); - swiDecompressLZSSVram ((void*)Top029Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top029Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top029Pal, Top029PalLen); - swiDecompressLZSSVram ((void*)Top030Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top030Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top030Pal, Top030PalLen); - swiDecompressLZSSVram ((void*)Top031Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top031Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top031Pal, Top031PalLen); - swiDecompressLZSSVram ((void*)Top032Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top032Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top032Pal, Top032PalLen); - swiDecompressLZSSVram ((void*)Top033Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top033Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top033Pal, Top033PalLen); - swiDecompressLZSSVram ((void*)Top034Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top034Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top034Pal, Top034PalLen); - swiDecompressLZSSVram ((void*)Top035Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top035Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top035Pal, Top035PalLen); - swiDecompressLZSSVram ((void*)Top036Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top036Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top036Pal, Top036PalLen); - swiDecompressLZSSVram ((void*)Top037Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top037Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top037Pal, Top037PalLen); - swiDecompressLZSSVram ((void*)Top038Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top038Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top038Pal, Top038PalLen); - swiDecompressLZSSVram ((void*)Top039Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top039Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top039Pal, Top039PalLen); - swiDecompressLZSSVram ((void*)Top040Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top040Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top040Pal, Top040PalLen); - swiDecompressLZSSVram ((void*)Top041Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top041Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top041Pal, Top041PalLen); - swiDecompressLZSSVram ((void*)Top042Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top042Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top042Pal, Top042PalLen); - swiDecompressLZSSVram ((void*)Top043Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top043Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top043Pal, Top043PalLen); - swiDecompressLZSSVram ((void*)Top044Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top044Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top044Pal, Top044PalLen); - swiDecompressLZSSVram ((void*)Top045Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top045Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top045Pal, Top045PalLen); - swiDecompressLZSSVram ((void*)Top046Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top046Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top046Pal, Top046PalLen); - swiDecompressLZSSVram ((void*)Top047Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top047Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top047Pal, Top047PalLen); - swiDecompressLZSSVram ((void*)Top048Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top048Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top048Pal, Top048PalLen); - swiDecompressLZSSVram ((void*)Top049Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top049Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top049Pal, Top049PalLen); - swiDecompressLZSSVram ((void*)Top050Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top050Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top050Pal, Top050PalLen); - swiDecompressLZSSVram ((void*)Top051Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top051Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top051Pal, Top051PalLen); - swiDecompressLZSSVram ((void*)Top052Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top052Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top052Pal, Top052PalLen); - swiDecompressLZSSVram ((void*)Top053Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top053Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top053Pal, Top053PalLen); - swiDecompressLZSSVram ((void*)Top054Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top054Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top054Pal, Top054PalLen); - swiDecompressLZSSVram ((void*)Top055Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top055Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top055Pal, Top055PalLen); - swiDecompressLZSSVram ((void*)Top056Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top056Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top056Pal, Top056PalLen); - swiDecompressLZSSVram ((void*)Top057Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top057Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top057Pal, Top057PalLen); - swiDecompressLZSSVram ((void*)Top058Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top058Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top058Pal, Top058PalLen); - swiDecompressLZSSVram ((void*)Top059Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top059Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top059Pal, Top059PalLen); - swiDecompressLZSSVram ((void*)Top060Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top060Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top060Pal, Top060PalLen); - swiDecompressLZSSVram ((void*)Top061Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top061Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top061Pal, Top061PalLen); - swiDecompressLZSSVram ((void*)Top062Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top062Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top062Pal, Top062PalLen); - swiDecompressLZSSVram ((void*)Top063Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top063Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top063Pal, Top063PalLen); - swiDecompressLZSSVram ((void*)Top064Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top064Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top064Pal, Top064PalLen); - swiDecompressLZSSVram ((void*)Top065Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top065Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top065Pal, Top065PalLen); - swiDecompressLZSSVram ((void*)Top066Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top066Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top066Pal, Top066PalLen); - swiDecompressLZSSVram ((void*)Top067Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top067Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top067Pal, Top067PalLen); - swiDecompressLZSSVram ((void*)Top068Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top068Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top068Pal, Top068PalLen); - swiDecompressLZSSVram ((void*)Top069Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top069Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top069Pal, Top069PalLen); - swiDecompressLZSSVram ((void*)Top070Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top070Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top070Pal, Top070PalLen); - swiDecompressLZSSVram ((void*)Top071Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top071Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top071Pal, Top071PalLen); - swiDecompressLZSSVram ((void*)Top072Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top072Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top072Pal, Top072PalLen); - swiDecompressLZSSVram ((void*)Top073Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top073Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top073Pal, Top073PalLen); - swiDecompressLZSSVram ((void*)Top074Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top074Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top074Pal, Top074PalLen); - swiDecompressLZSSVram ((void*)Top075Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top075Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top075Pal, Top075PalLen); - swiDecompressLZSSVram ((void*)Top076Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top076Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top076Pal, Top076PalLen); - swiDecompressLZSSVram ((void*)Top077Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top077Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top077Pal, Top077PalLen); - swiDecompressLZSSVram ((void*)Top078Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top078Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top078Pal, Top078PalLen); - swiDecompressLZSSVram ((void*)Top079Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top079Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top079Pal, Top079PalLen); - swiDecompressLZSSVram ((void*)Top080Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top080Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top080Pal, Top080PalLen); - swiDecompressLZSSVram ((void*)Top081Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top081Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top081Pal, Top081PalLen); - swiDecompressLZSSVram ((void*)Top082Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top082Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top082Pal, Top082PalLen); - swiDecompressLZSSVram ((void*)Top083Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top083Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top083Pal, Top083PalLen); - swiDecompressLZSSVram ((void*)Top084Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top084Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top084Pal, Top084PalLen); - swiDecompressLZSSVram ((void*)Top085Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top085Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top085Pal, Top085PalLen); - swiDecompressLZSSVram ((void*)Top086Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top086Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top086Pal, Top086PalLen); - swiDecompressLZSSVram ((void*)Top087Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top087Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top087Pal, Top087PalLen); - swiDecompressLZSSVram ((void*)Top088Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top088Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top088Pal, Top088PalLen); - swiDecompressLZSSVram ((void*)Top089Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top089Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top089Pal, Top089PalLen); - swiDecompressLZSSVram ((void*)Top090Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top090Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top090Pal, Top090PalLen); - swiDecompressLZSSVram ((void*)Top091Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top091Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top091Pal, Top091PalLen); - swiDecompressLZSSVram ((void*)Top092Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top092Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top092Pal, Top092PalLen); - swiDecompressLZSSVram ((void*)Top093Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top093Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top093Pal, Top093PalLen); - swiDecompressLZSSVram ((void*)Top094Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top094Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top094Pal, Top094PalLen); - swiDecompressLZSSVram ((void*)Top095Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top095Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top095Pal, Top095PalLen); - swiDecompressLZSSVram ((void*)Top096Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top096Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top096Pal, Top096PalLen); - swiDecompressLZSSVram ((void*)Top097Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top097Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top097Pal, Top097PalLen); - swiDecompressLZSSVram ((void*)Top098Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top098Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top098Pal, Top098PalLen); - swiDecompressLZSSVram ((void*)Top099Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top099Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top099Pal, Top099PalLen); - swiDecompressLZSSVram ((void*)Top100Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top100Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top100Pal, Top100PalLen); - swiDecompressLZSSVram ((void*)Top101Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top101Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top101Pal, Top101PalLen); - swiDecompressLZSSVram ((void*)Top102Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top102Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top102Pal, Top102PalLen); - swiDecompressLZSSVram ((void*)Top103Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top103Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top103Pal, Top103PalLen); - swiDecompressLZSSVram ((void*)Top104Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top104Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top104Pal, Top104PalLen); - swiDecompressLZSSVram ((void*)Top105Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top105Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top105Pal, Top105PalLen); - swiDecompressLZSSVram ((void*)Top106Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top106Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top106Pal, Top106PalLen); - swiDecompressLZSSVram ((void*)Top107Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top107Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top107Pal, Top107PalLen); - swiDecompressLZSSVram ((void*)Top108Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top108Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top108Pal, Top108PalLen); - swiDecompressLZSSVram ((void*)Top109Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top109Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top109Pal, Top109PalLen); - swiDecompressLZSSVram ((void*)Top110Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top110Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top110Pal, Top110PalLen); - swiDecompressLZSSVram ((void*)Top111Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top111Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top111Pal, Top111PalLen); if(REG_SCFG_MC == 0x11) { @@ -1931,50 +1930,50 @@ void BootSplashDS(bool HealthandSafety_MSG, int language) { // Pause on frame 111 for a second for (int i = 0; i < 80; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)Top112Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top112Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top112Pal, Top112PalLen); - swiDecompressLZSSVram ((void*)Top113Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top113Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top113Pal, Top113PalLen); - swiDecompressLZSSVram ((void*)Top114Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top114Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top114Pal, Top114PalLen); - swiDecompressLZSSVram ((void*)Top115Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top115Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top115Pal, Top115PalLen); - swiDecompressLZSSVram ((void*)Top116Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top116Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top116Pal, Top116PalLen); - swiDecompressLZSSVram ((void*)Top117Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top117Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top117Pal, Top117PalLen); - swiDecompressLZSSVram ((void*)Top118Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top118Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top118Pal, Top118PalLen); - swiDecompressLZSSVram ((void*)Top119Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top119Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], Top119Pal, Top119PalLen); - swiDecompressLZSSVram ((void*)Top120Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top120Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); switch (language) { case 0: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot04JATiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot04JATiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 1: default: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot04Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot04Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 2: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot04FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot04FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 3: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot04DETiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot04DETiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 4: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot04ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot04ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 5: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot04ESTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot04ESTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 6: case 7: @@ -2007,26 +2006,26 @@ void BootSplashDS(bool HealthandSafety_MSG, int language) { } - swiDecompressLZSSVram ((void*)Top121Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top121Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); switch (language) { case 0: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot03JATiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot03JATiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 1: default: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot03Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot03Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 2: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot03FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot03FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 3: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot03DETiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot03DETiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 4: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot03ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot03ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 5: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot03ESTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot03ESTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 6: case 7: @@ -2059,26 +2058,26 @@ void BootSplashDS(bool HealthandSafety_MSG, int language) { } - swiDecompressLZSSVram ((void*)Top122Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)Top122Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); switch (language) { case 0: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot02JATiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot02JATiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 1: default: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot02Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot02Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 2: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot02FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot02FRTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 3: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot02DETiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot02DETiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 4: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot02ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot02ITTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 5: - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot02ESTiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + if(HealthandSafety_MSG) { decompress ((void*)Bot02ESTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } break; case 6: case 7: @@ -2111,93 +2110,54 @@ void BootSplashDS(bool HealthandSafety_MSG, int language) { } - swiDecompressLZSSVram ((void*)Top123Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot09Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + decompress ((void*)Top123Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); + if(HealthandSafety_MSG) { decompress ((void*)Bot09Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } vramcpy_ui (&BG_PALETTE[0], Top123Pal, Top123PalLen); if(HealthandSafety_MSG) { vramcpy_ui (&BG_PALETTE_SUB[0], Bot09Pal, Bot09PalLen); } - swiDecompressLZSSVram ((void*)Top124Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); - if(HealthandSafety_MSG) { swiDecompressLZSSVram ((void*)Bot10Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); } + decompress ((void*)Top124Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); + if(HealthandSafety_MSG) { decompress ((void*)Bot10Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); } vramcpy_ui (&BG_PALETTE[0], Top124Pal, Top124PalLen); if(HealthandSafety_MSG) { vramcpy_ui (&BG_PALETTE_SUB[0], Bot10Pal, Bot10PalLen); } - swiDecompressLZSSVram ((void*)WhiteTiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); + decompress ((void*)WhiteTiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], WhitePal, WhitePalLen); + + decompress ((void*)WhiteTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); + vramcpy_ui (&BG_PALETTE_SUB[0], WhitePal, WhitePalLen); - + swiWaitForVBlank(); } -void FadeFX() { - - for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - - swiDecompressLZSSVram ((void*)fade00Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); - swiDecompressLZSSVram ((void*)fade00Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); - vramcpy_ui (&BG_PALETTE[0], fade00Pal, fade00PalLen); - vramcpy_ui (&BG_PALETTE_SUB[0], fade00Pal, fade00PalLen); - - for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - - swiDecompressLZSSVram ((void*)fade01Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); - swiDecompressLZSSVram ((void*)fade01Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); - vramcpy_ui (&BG_PALETTE[0], fade01Pal, fade01PalLen); - vramcpy_ui (&BG_PALETTE_SUB[0], fade01Pal, fade01PalLen); - - for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - - swiDecompressLZSSVram ((void*)fade02Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); - swiDecompressLZSSVram ((void*)fade02Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); - vramcpy_ui (&BG_PALETTE[0], fade02Pal, fade02PalLen); - vramcpy_ui (&BG_PALETTE_SUB[0], fade02Pal, fade02PalLen); - - for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - - swiDecompressLZSSVram ((void*)fade03Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); - swiDecompressLZSSVram ((void*)fade03Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); - vramcpy_ui (&BG_PALETTE[0], fade03Pal, fade03PalLen); - vramcpy_ui (&BG_PALETTE_SUB[0], fade03Pal, fade03PalLen); - - for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - - swiDecompressLZSSVram ((void*)fade04Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); - swiDecompressLZSSVram ((void*)fade04Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); - vramcpy_ui (&BG_PALETTE[0], fade04Pal, fade04PalLen); - vramcpy_ui (&BG_PALETTE_SUB[0], fade04Pal, fade04PalLen); - - for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } -} - void ErrorNoCard() { - FadeFX(); - - swiDecompressLZSSVram ((void*)toperror2_00Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); - swiDecompressLZSSVram ((void*)suberror00Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)toperror2_00Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); + decompress ((void*)suberror00Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], toperror2_00Pal, toperror2_00PalLen); vramcpy_ui (&BG_PALETTE_SUB[0], suberror00Pal, suberror00PalLen); for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)toperror2_01Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); - swiDecompressLZSSVram ((void*)suberror01Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)toperror2_01Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); + decompress ((void*)suberror01Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], toperror2_01Pal, toperror2_01PalLen); vramcpy_ui (&BG_PALETTE_SUB[0], suberror01Pal, suberror01PalLen); for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)toperror2_02Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); - swiDecompressLZSSVram ((void*)suberror02Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)toperror2_02Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); + decompress ((void*)suberror02Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], toperror2_02Pal, toperror2_02PalLen); vramcpy_ui (&BG_PALETTE_SUB[0], suberror02Pal, suberror02PalLen); for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)toperror2_03Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); - swiDecompressLZSSVram ((void*)suberror03Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)toperror2_03Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); + decompress ((void*)suberror03Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], toperror2_03Pal, toperror2_03PalLen); vramcpy_ui (&BG_PALETTE_SUB[0], suberror03Pal, suberror03PalLen); @@ -2206,31 +2166,40 @@ void ErrorNoCard() { // Wait for input, then fade out do { swiWaitForVBlank(); scanKeys(); } while (!keysDown()); - swiDecompressLZSSVram ((void*)toperror2_04Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); - swiDecompressLZSSVram ((void*)suberror04Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)toperror2_04Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); + decompress ((void*)suberror04Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], toperror2_04Pal, toperror2_04PalLen); vramcpy_ui (&BG_PALETTE_SUB[0], suberror04Pal, suberror04PalLen); for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - swiDecompressLZSSVram ((void*)toperror2_05Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); - swiDecompressLZSSVram ((void*)suberror05Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)toperror2_05Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); + decompress ((void*)suberror05Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], toperror2_05Pal, toperror2_05PalLen); vramcpy_ui (&BG_PALETTE_SUB[0], suberror05Pal, suberror05PalLen); - swiDecompressLZSSVram ((void*)toperror2_06Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); - swiDecompressLZSSVram ((void*)suberror06Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); + decompress ((void*)toperror2_06Tiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); + decompress ((void*)suberror06Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); vramcpy_ui (&BG_PALETTE[0], toperror2_06Pal, toperror2_06PalLen); vramcpy_ui (&BG_PALETTE_SUB[0], suberror06Pal, suberror06PalLen); + + decompress ((void*)WhiteTiles, (void*)CHAR_BASE_BLOCK_SUB(2), LZ77Vram); + vramcpy_ui (&BG_PALETTE_SUB[0], WhitePal, WhitePalLen); for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } - - swiDecompressLZSSVram ((void*)fade04Tiles, (void*)CHAR_BASE_BLOCK(2), 0, &decompressBiosCallback); - swiDecompressLZSSVram ((void*)fade04Tiles, (void*)CHAR_BASE_BLOCK_SUB(2), 0, &decompressBiosCallback); - vramcpy_ui (&BG_PALETTE[0], fade04Pal, fade04PalLen); - vramcpy_ui (&BG_PALETTE_SUB[0], fade04Pal, fade04PalLen); - - for (int i = 0; i < 2; i++) { swiWaitForVBlank(); } +} + + +void SimpleSplashInit() { + videoSetMode(MODE_0_2D | DISPLAY_BG0_ACTIVE); + vramSetBankA (VRAM_A_MAIN_BG_0x06000000); + REG_BG0CNT = BG_MAP_BASE(0) | BG_COLOR_256 | BG_TILE_BASE(2); + BG_PALETTE[0]=0; + u16* bgMapTop = (u16*)SCREEN_BASE_BLOCK(0); + for (int i = 0; i < CONSOLE_SCREEN_WIDTH*CONSOLE_SCREEN_HEIGHT; i++)bgMapTop[i] = (u16)i; + + decompress ((void*)loadingTiles, (void*)CHAR_BASE_BLOCK(2), LZ77Vram); + vramcpy_ui (&BG_PALETTE[0], loadingPal, loadingPalLen); } @@ -2250,17 +2219,15 @@ void BootSplashInit(bool UseNTRSplash, bool HealthandSafety_MSG, int language, b bgMapTop[i] = (u16)i; bgMapSub[i] = (u16)i; } - - if (DisplayErrorSplash) { - ErrorNoCard(); - return; - } - + + if (DisplayErrorSplash) { ErrorNoCard(); return; } + if(UseNTRSplash) { BootSplashDS(HealthandSafety_MSG, language); } else { BootSplashDSi(HealthandSafety_MSG, language); } + return; } diff --git a/arm9/source/bootsplash.h b/arm9/source/bootsplash.h index a7d4b7c..9a157f2 100644 --- a/arm9/source/bootsplash.h +++ b/arm9/source/bootsplash.h @@ -33,6 +33,7 @@ void CartridgePromptNoHS (void); void BootSplashDS (bool HealthandSafety_MSG, int language); void FadeFX (void); void ErrorNoCard (void); +void SimpleSplashInit(void); void BootSplashInit (bool UseNTRSplash, bool HealthandSafety_MSG, int language, bool DisplayErrorSplash); #ifdef __cplusplus diff --git a/arm9/source/launch_engine.c b/arm9/source/launch_engine.c index a296222..39ed94d 100644 --- a/arm9/source/launch_engine.c +++ b/arm9/source/launch_engine.c @@ -22,19 +22,10 @@ #include "load_bin.h" #include "launch_engine.h" #include "debugConsole.h" +#include "launcherData.h" #define LCDC_BANK_D (u16*)0x06860000 -#define TMP_DATA 0x027FC000 - -typedef struct sLauncherSettings { - u8 language; - u8 scfgUnlock; - u8 twlMode; - u8 twlCLK; - u8 twlVRAM; - u8 debugMode; -} tLauncherSettings; void vramcpy (void* dst, const void* src, int len) { u16* dst16 = (u16*)dst; @@ -47,17 +38,23 @@ extern void InitConsole(); extern bool ConsoleInit; -void runLaunchEngine (int language, bool scfgUnlock, bool TWLMODE, bool TWLCLK, bool TWLVRAM, bool debugMode) { - + +ITCM_CODE static void SETSCFG() { + REG_SCFG_EXT=0x83002000; + for(int i = 0; i < 8; i++) { while(REG_VCOUNT!=191); while(REG_VCOUNT==191); } +} + + +void runLaunchEngine (tLauncherSettings launchdata) { // Always init console so bootloader's new console can display error codes if needed. - if (!debugMode || !ConsoleInit) { InitConsole(); } else { consoleClear(); } - + if (!launchdata.debugMode || !ConsoleInit) { InitConsole(); } else { consoleClear(); } + irqDisable(IRQ_ALL); // Direct CPU access to VRAM bank D VRAM_D_CR = VRAM_ENABLE | VRAM_D_LCD; // Clear VRAM - memset (LCDC_BANK_D, 0x00, 128 * 1024); + // memset (LCDC_BANK_D, 0x00, 128 * 1024); // Load the loader/patcher into the correct address vramcpy (LCDC_BANK_D, load_bin, load_bin_size); @@ -69,21 +66,11 @@ void runLaunchEngine (int language, bool scfgUnlock, bool TWLMODE, bool TWLCLK, // Reset into a passme loop nocashMessage("Reset into a passme loop"); REG_EXMEMCNT |= ARM7_OWNS_ROM | ARM7_OWNS_CARD; - - REG_SCFG_EXT=0x83002000; - // for (int i = 0; i < 10; i++) { swiWaitForVBlank(); } + *(tLauncherSettings*)LAUNCH_DATA = launchdata; - tLauncherSettings* tmpData = (tLauncherSettings*)TMP_DATA; + SETSCFG(); - tmpData->language = 0xFF; - if (language != -1)tmpData->language = language; - if (scfgUnlock)tmpData->scfgUnlock = 0x01; - if (TWLMODE)tmpData->twlMode = 0x01; - if (TWLCLK)tmpData->twlCLK = 0x01; - if (TWLVRAM)tmpData->twlVRAM = 0x01; - if (debugMode)tmpData->debugMode = 0x01; - // Return to passme loop *(vu32*)0x027FFFFC = 0; *(vu32*)0x027FFE04 = (u32)0xE59FF018; // ldr pc, 0x02FFFE24 @@ -91,7 +78,6 @@ void runLaunchEngine (int language, bool scfgUnlock, bool TWLMODE, bool TWLCLK, // Reset ARM7 // nocashMessage("resetARM7"); resetARM7(0x06020000); - // swi soft reset // nocashMessage("swiSoftReset"); swiSoftReset(); diff --git a/arm9/source/launch_engine.h b/arm9/source/launch_engine.h index 6cba29c..0f8dbb5 100644 --- a/arm9/source/launch_engine.h +++ b/arm9/source/launch_engine.h @@ -20,12 +20,13 @@ #define LAUNCH_ENGINE_H #include +#include "launcherData.h" #ifdef __cplusplus extern "C" { #endif -void runLaunchEngine (int language, bool scfgUnlock, bool TWLMODE, bool TWLCLK, bool TWLVRAM, bool debugMode); +void runLaunchEngine (tLauncherSettings launchdata); #ifdef __cplusplus } diff --git a/arm9/source/main.cpp b/arm9/source/main.cpp index 21c7255..59e7cf0 100755 --- a/arm9/source/main.cpp +++ b/arm9/source/main.cpp @@ -30,14 +30,27 @@ #include "launch_engine.h" #include "crc.h" #include "tonccpy.h" -#include "read_card.h" +#include "nitrofs.h" +#include "nds_card.h" #include "debugConsole.h" +#include "hbmenu.h" +#include "launcherData.h" +#include "read_card.h" -sNDSHeaderExt ndsHeader; -char gameTitle[13] = {0}; -char gameCode[7] = {0}; +#define FILECOPYBUFFER 0x02000000 -const char* PROGVERSION = "2.7"; +ALIGN(4) struct { + sNDSHeader header; + char padding[0x200 - sizeof(sNDSHeader)]; +} ndsHeader; + +static char gameTitle[13] = {0}; +// static char gameCode[7] = {0}; +static char gameCode[5] = {0}; +static bool nitroFSMounted = false; +static ALIGN(4) sNDSHeaderExt ntrHeader; + +const char* PROGVERSION = "3.0"; off_t getFileSize(const char *fileName) { FILE* fp = fopen(fileName, "rb"); @@ -52,6 +65,7 @@ off_t getFileSize(const char *fileName) { } extern void InitConsole(); +extern void StartFileBrowser(tLauncherSettings launchdata); extern bool ConsoleInit; @@ -60,130 +74,230 @@ void DisplayText(const char* text, bool clear = false, bool noText = false){ if (clear)consoleClear(); printf("--------------------------------\n"); printf("----[NTR Launcher Debug Mode]---\n"); - printf("----------[Version: 2.7]--------\n"); + printf("----------[Version: 3.0]--------\n"); printf("--------------------------------\n\n"); if (!noText)printf(text); } void DoWait(int waitTime = 30){ - for (int i = 0; i < waitTime; i++) swiWaitForVBlank(); + for (int i = 0; i < waitTime; i++)swiWaitForVBlank(); }; -void DoCardInit(bool DebugMode) { + +bool MountNitroFS() { + if (nitroFSMounted)return nitroFSMounted; + nitroFSMounted = nitroFSInit("sd:/title/00030004/4b4b4750/content/00000000.app"); + if (nitroFSMounted)return nitroFSMounted; + nitroFSMounted = nitroFSInit("sd:/NTR_Launcher.nds"); + if (nitroFSMounted)return nitroFSMounted; + nitroFSMounted = nitroFSInit("sd:/nds/NTR_Launcher.nds"); + if (nitroFSMounted)return nitroFSMounted; + nitroFSMounted = nitroFSInit("sd:/homebrew/NTR_Launcher.nds"); + return nitroFSMounted; +} + +void StartStage2Mode(tLauncherSettings Launchdata) { + sysSetCardOwner (BUS_OWNER_ARM9); + StartFileBrowser(Launchdata); +} + + +bool DoCardInit(bool DebugMode, bool fastBoot) { + bool FastBoot = fastBoot; if (DebugMode){ DisplayText("CLR", true, true); DisplayText("Loading Cart details.\nPlease Wait...\n", true); } + switch (REG_SCFG_MC) { + case 0x10: { enableSlot1(); DoWait(10); FastBoot = false; }break; + case 0x11: { enableSlot1(); DoWait(10); FastBoot = false; }break; + } // Do cart init stuff to wake cart up. DLDI init may fail otherwise! - cardInit(&ndsHeader); - tonccpy(gameTitle, ndsHeader.gameTitle, 12); - tonccpy(gameCode, ndsHeader.gameCode, 6); - DoWait(60); + if (FastBoot) { + cardInitShort(&ntrHeader); + tonccpy(gameTitle, ntrHeader.gameTitle, 12); + tonccpy(gameCode, ntrHeader.gameCode, 4); + } else { + CardReset(true); + cardReadHeader((u8*)&ndsHeader); + CardReset(false); + tonccpy(gameTitle, ndsHeader.header.gameTitle, 12); + tonccpy(gameCode, ndsHeader.header.gameCode, 4); + } if (DebugMode) { DisplayText("CLR", true, true); iprintf("Detected Cart Name: %12s \n", gameTitle); iprintf("Detected Cart Game ID: %6s \n\n", gameCode); printf("Press any button to continue..."); - do { swiWaitForVBlank(); scanKeys(); } while (!keysDown()); + while (keysDown()) { swiWaitForVBlank(); scanKeys(); } + while (!keysDown()) { swiWaitForVBlank(); scanKeys(); } + } else { + DoWait(25); } + return FastBoot; } -/*void ResetSlot1() { - if (REG_SCFG_MC == 0x11)return; - disableSlot1(); - DoWait(); - enableSlot1(); -}*/ - -void DoSlotCheck(bool DebugMode) { - if (REG_SCFG_MC == 0x11) { - if(DebugMode) { - DisplayText("Please insert a cartridge...\n", true); - } else { - if (!ConsoleInit)InitConsole(); - consoleClear(); - printf("\n\n\n\n\n\n\n\n\n\n\n Please insert a cartridge... "); - } - REDO: - swiWaitForVBlank(); - do { swiWaitForVBlank(); } while (REG_SCFG_MC != 0x10); - enableSlot1(); - DoWait(60); - if (REG_SCFG_MC != 0x18) goto REDO; - } else if (REG_SCFG_MC == 0x10) { - enableSlot1(); +bool DoSlotCheck(bool DebugMode) { + bool slotReset = false; + switch (REG_SCFG_MC) { + case 0x11: { + if(DebugMode) { + DisplayText("Please insert a cartridge...\n", true); + } else { + if (!ConsoleInit)InitConsole(); + consoleClear(); + printf("\n\n\n\n\n\n\n\n\n\n\n Please insert a cartridge... "); + } + REDO: + swiWaitForVBlank(); + while (REG_SCFG_MC != 0x10)swiWaitForVBlank(); + enableSlot1(); + DoWait(60); + if (REG_SCFG_MC != 0x18) goto REDO; + slotReset = true; + }break; + case 0x10: { + slotReset = true; + enableSlot1(); + }break; } + return slotReset; } int main() { defaultExceptionHandler(); - bool scfgUnlock = false; - bool TWLMODE = false; - bool TWLCLK = false; // false == NTR, true == TWL - bool TWLVRAM = false; - - bool UseAnimatedSplash = false; - bool UseNTRSplash = true; - bool HealthAndSafety_MSG = true; + sysSetCardOwner(BUS_OWNER_ARM9); + + tLauncherSettings LaunchData = { 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF }; + + // Create backup of Cart header (if present) saved by DSi System Menu. + // It will not survive memory reallocation after dropping to NTR ram spec during bootloader. + tonccpy ((u32*)CartHeaderCopy, (u32*)InitialCartHeader, 0x200); int language = -1; + bool scfgunlock = false; + bool twlmode = false; + bool twlclk = false; + bool twlvram = false; + bool debugmode = false; + bool fastBoot = false; + bool stage2Menu = false; + + bool useAnimatedSplash = false; + bool useNTRSplash = true; + bool healthAndSafety_MSG = true; + + if (fatMountSimple("sd", get_io_dsisd())) { + if(access("sd:/NTR_Launcher", F_OK) != 0)mkdir("sd:/NTR_Launcher", 0777); + if ((access("sd:/NTR_Launcher/NTR_Launcher.ini", F_OK) != 0) && MountNitroFS()) { + FILE *src = fopen("nitro:/NTR_Launcher.ini", "rb"); + if (src) { + FILE *dest = fopen("sd:/NTR_Launcher/NTR_Launcher.ini", "wb"); + if (dest) { + fseek(src, 0, SEEK_END); + u32 fSize = ftell(src); + fseek(src, 0, SEEK_SET); + fread((void*)FILECOPYBUFFER, 1, fSize, src); + fwrite((void*)FILECOPYBUFFER, fSize, 1, dest); + fclose(src); + fclose(dest); + } + } + } + if (access("sd:/NTR_Launcher/NTR_Launcher.ini", F_OK) == 0) { + CIniFile ntrlauncher_config( "sd:/NTR_Launcher/NTR_Launcher.ini" ); + + twlclk = ntrlauncher_config.GetInt("NTRLAUNCHER","TWLCLOCK",0); + twlvram = ntrlauncher_config.GetInt("NTRLAUNCHER","TWLVRAM",0); + twlmode = ntrlauncher_config.GetInt("NTRLAUNCHER","TWLMODE",0); + scfgunlock = ntrlauncher_config.GetInt("NTRLAUNCHER","SCFGUNLOCK",0); + useAnimatedSplash = ntrlauncher_config.GetInt("NTRLAUNCHER","ANIMATEDSPLASH",0); + useNTRSplash = ntrlauncher_config.GetInt("NTRLAUNCHER","NTRSPLASH",0); + healthAndSafety_MSG = ntrlauncher_config.GetInt("NTRLAUNCHER","HEALTHSAFETYSPLASH",0); + + debugmode = ntrlauncher_config.GetInt("NTRLAUNCHER","DEBUGMODE",0); + language = ntrlauncher_config.GetInt("NTRLAUNCHER", "LANGUAGE", -1); + } + } + + scanKeys(); + swiWaitForVBlank(); - bool DebugMode = false; + if (scfgunlock)LaunchData.scfgUnlock = 0x01; + if (twlmode)LaunchData.twlMode = 0x01; + if (twlclk)LaunchData.twlCLK = 0x01; + if (twlvram)LaunchData.twlVRAM = 0x01; + if (fastBoot)LaunchData.fastBoot = 0x01; - if (fatInitDefault()) { - CIniFile ntrlauncher_config( "/NDS/NTR_Launcher.ini" ); - - TWLCLK = ntrlauncher_config.GetInt("NTRLAUNCHER","TWLCLOCK",0); - TWLVRAM = ntrlauncher_config.GetInt("NTRLAUNCHER","TWLVRAM",0); - TWLMODE = ntrlauncher_config.GetInt("NTRLAUNCHER","TWLMODE",0); - scfgUnlock = ntrlauncher_config.GetInt("NTRLAUNCHER","SCFGUNLOCK",0); - UseAnimatedSplash = ntrlauncher_config.GetInt("NTRLAUNCHER","ANIMATEDSPLASH",0); - UseNTRSplash = ntrlauncher_config.GetInt("NTRLAUNCHER","NTRSPLASH",0); - HealthAndSafety_MSG = ntrlauncher_config.GetInt("NTRLAUNCHER","HEALTHSAFETYSPLASH",0); - - DebugMode = ntrlauncher_config.GetInt("NTRLAUNCHER","DEBUGMODE",0); - language = ntrlauncher_config.GetInt("NTRLAUNCHER", "LANGUAGE", -1); + if (((keysHeld() & KEY_L) && (keysHeld() & KEY_R)) || (REG_SCFG_MC == 0x11))stage2Menu = true; + + if ((REG_SCFG_MC == 0x10) && !stage2Menu) { sysSetCardOwner (BUS_OWNER_ARM9); DoCardInit(false, false); } + + if (keysDown() & KEY_B) { + debugmode = true; + } else if (keysDown() & KEY_L) { + twlclk = false; twlvram = true; scfgunlock = false; twlmode = false; + } else if (keysDown() & KEY_R) { + twlclk = true; twlvram = true; scfgunlock = true; twlmode = true; } - ConsoleInit = DebugMode; - - if (DebugMode)UseAnimatedSplash = false; - - if (!UseAnimatedSplash) { - if (DebugMode)InitConsole(); - DoSlotCheck(DebugMode); + ConsoleInit = debugmode; + if (stage2Menu) { ConsoleInit = false; debugmode = false; } + if (debugmode)useAnimatedSplash = false; + if (!useAnimatedSplash) { + if (debugmode)InitConsole(); + // fastBoot = !DoSlotCheck(debugmode); + if (!stage2Menu)DoSlotCheck(debugmode); } else { char *p = (char*)PersonalData->name; for (int i = 0; i < 10; i++) { if (p[i*2] == 0x00) { p[i*2/2] = 0; } else { p[i*2/2] = p[i*2]; } } - if (language == -1) language = (PersonalData->language); - BootSplashInit(UseNTRSplash, HealthAndSafety_MSG, language, false); + if (language == -1)language = PersonalData->language; + BootSplashInit(useNTRSplash, healthAndSafety_MSG, (int)language, false); } - sysSetCardOwner (BUS_OWNER_ARM9); + if (language != -1)LaunchData.language = (u8)language; + if (scfgunlock)LaunchData.scfgUnlock = 0x01; + if (twlmode)LaunchData.twlMode = 0x01; + if (twlclk)LaunchData.twlCLK = 0x01; + if (twlvram)LaunchData.twlVRAM = 0x01; + if (debugmode)LaunchData.debugMode = 0x01; + /*if (fastBoot) { + LaunchData.fastBoot = 0x01; + } else { + LaunchData.fastBoot = 0x00; + }*/ - DoCardInit(DebugMode); - - // Force specific settings needed for proper support for retail TWL carts - if (!memcmp(gameTitle, "D!S!XTREME", 9)) { - // DS-Xtreme does not like running in TWL clock speeds. (write function likely goes too fast and semi-bricks hidden sector region randomly) - TWLCLK = false; - } - - while(1) { - // If SCFG_MC is returning as zero/null, this means SCFG_EXT registers are locked on arm9 or user attempted to run this while in NTR mode. - if((REG_SCFG_MC == 0x00) || (REG_SCFG_MC == 0x11) || (REG_SCFG_MC == 0x10)) { - if (UseAnimatedSplash) { - BootSplashInit(false, false, 0, true); + if (stage2Menu || (REG_SCFG_MC == 0x11)) { + StartStage2Mode(LaunchData); + } else { + // DoCardInit(debugmode, fastBoot); + DoCardInit(debugmode, false); + // DS-Xtreme does not like running in TWL clock speeds. + // (write function likely goes too fast and semi-bricks hidden sector region randomly when using official launcher) + if (!memcmp(gameTitle, "D!S!XTREME", 9)) { + scfgunlock = false; + twlclk = false; + twlvram = false; + twlmode = false; + } + while(1) { + // If SCFG_MC is returning as zero/null, this means SCFG_EXT registers are locked on arm9 or user attempted to run this while in NTR mode. + if((REG_SCFG_MC == 0x00) || (REG_SCFG_MC == 0x11) || (REG_SCFG_MC == 0x10)) { + if (useAnimatedSplash) { + BootSplashInit(false, false, 0, true); + } else { + DisplayText("Error has occured.!\nEither card ejected late,\nor NTR mode detected!\nPress any button to exit...", true); + do { swiWaitForVBlank(); scanKeys(); } while (!keysDown()); + } + break; } else { - DisplayText("Error has occured.!\nEither card ejected late,\nor NTR mode detected!\nPress any button to exit...", true); - do { swiWaitForVBlank(); scanKeys(); } while (!keysDown()); + runLaunchEngine(LaunchData); + break; } - break; - } else { - runLaunchEngine(language, scfgUnlock, TWLMODE, TWLCLK, TWLVRAM, DebugMode); + swiWaitForVBlank(); } } return 0; diff --git a/icon.bmp b/icon.bmp index 8c649ea..d1f628d 100755 Binary files a/icon.bmp and b/icon.bmp differ diff --git a/ndsbootloader/.gitignore b/ndsbootloader/.gitignore new file mode 100644 index 0000000..c6c6a5c --- /dev/null +++ b/ndsbootloader/.gitignore @@ -0,0 +1,3 @@ +*build +load.bin +load.elf diff --git a/ndsbootloader/Makefile b/ndsbootloader/Makefile new file mode 100644 index 0000000..bc6d0e2 --- /dev/null +++ b/ndsbootloader/Makefile @@ -0,0 +1,124 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- +ifeq ($(strip $(DEVKITARM)),) +$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM) +endif + +-include $(DEVKITARM)/ds_rules + +#--------------------------------------------------------------------------------- +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# INCLUDES is a list of directories containing extra header files +#--------------------------------------------------------------------------------- +TARGET := load2 +BUILD ?= build +SOURCES := source source/patches +INCLUDES := build ../include +DATA := ../data +SPECS := specs + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := -mthumb -mthumb-interwork + +CFLAGS := -g -Wall -Os \ + -mcpu=arm7tdmi -mtune=arm7tdmi -fomit-frame-pointer\ + -ffast-math \ + $(ARCH) + +CFLAGS += $(INCLUDE) $(EXTRA_CFLAGS) -DARM7 + +ASFLAGS := -g $(ARCH) $(EXTRA_CFLAGS) $(INCLUDE) +LDFLAGS = -nostartfiles -T $(TOPDIR)/load2.ld -Wl,-g $(ARCH) -Wl,-Map,$(TARGET).map + +LIBS := + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(LIBNDS) + + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export TOPDIR := $(CURDIR) +export LOADBIN := $(CURDIR)/../data/$(TARGET).bin +export LOADELF := $(CURDIR)/$(TARGET).elf +export DEPSDIR := $(CURDIR)/$(BUILD) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) + +export CC := $(PREFIX)gcc +export CXX := $(PREFIX)g++ +export AR := $(PREFIX)ar +export OBJCOPY := $(PREFIX)objcopy + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) + +export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) + +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) + +#--------------------------------------------------------------------------------- +# use CC for linking standard C +#--------------------------------------------------------------------------------- +export LD := $(CC) +#--------------------------------------------------------------------------------- + +.PHONY: $(BUILD) clean + +#--------------------------------------------------------------------------------- +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) -C $(BUILD) -f $(CURDIR)/Makefile + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) *.elf *.bin + + +#--------------------------------------------------------------------------------- +else + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +$(LOADBIN) : $(LOADELF) + @$(OBJCOPY) -O binary $< $@ + @echo built ... $(notdir $@) + + +$(LOADELF) : $(OFILES) + @echo linking $(notdir $@) + @$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@ + +arm9mpu_reset.o: mpu_reset.bin + +mpu_reset.bin: mpu_reset.elf + $(OBJCOPY) -O binary $< $@ + +mpu_reset.elf: $(TOPDIR)/arm9code/mpu_reset.s + $(CC) $(ASFLAGS) -Ttext=0 -x assembler-with-cpp -nostartfiles -nostdlib $< -o $@ + +-include $(DEPENDS) +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- \ No newline at end of file diff --git a/ndsbootloader/arm9code/mpu_reset.s b/ndsbootloader/arm9code/mpu_reset.s new file mode 100644 index 0000000..3d499dd --- /dev/null +++ b/ndsbootloader/arm9code/mpu_reset.s @@ -0,0 +1,110 @@ +/* + Copyright 2006 - 2015 Dave Murphy (WinterMute) + + 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 of the License, 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, see . + +*/ + +#include + + .text + .align 4 + + .arm + + .arch armv5te + .cpu arm946e-s + +@--------------------------------------------------------------------------------- + .global _start + .type _start STT_FUNC +@--------------------------------------------------------------------------------- +_start: +@--------------------------------------------------------------------------------- + @ Switch off MPU + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #PROTECT_ENABLE + mcr p15, 0, r0, c1, c0, 0 + + + adr r12, mpu_initial_data + ldmia r12, {r0-r10} + + mcr p15, 0, r0, c2, c0, 0 + mcr p15, 0, r0, c2, c0, 1 + mcr p15, 0, r1, c3, c0, 0 + mcr p15, 0, r2, c5, c0, 2 + mcr p15, 0, r3, c5, c0, 3 + mcr p15, 0, r4, c6, c0, 0 + mcr p15, 0, r5, c6, c1, 0 + mcr p15, 0, r6, c6, c3, 0 + mcr p15, 0, r7, c6, c4, 0 + mcr p15, 0, r8, c6, c6, 0 + mcr p15, 0, r9, c6, c7, 0 + mcr p15, 0, r10, c9, c1, 0 + + mov r0, #0 + mcr p15, 0, r0, c6, c2, 0 @ PU Protection Unit Data/Unified Region 2 + mcr p15, 0, r0, c6, c5, 0 @ PU Protection Unit Data/Unified Region 5 + + mrc p15, 0, r0, c9, c1, 0 @ DTCM + mov r0, r0, lsr #12 @ base + mov r0, r0, lsl #12 @ size + add r0, r0, #0x4000 @ dtcm top + + sub r0, r0, #4 @ irq vector + mov r1, #0 + str r1, [r0] + sub r0, r0, #4 @ IRQ1 Check Bits + str r1, [r0] + + sub r0, r0, #128 + bic r0, r0, #7 + + msr cpsr_c, #0xd3 @ svc mode + mov sp, r0 + sub r0, r0, #128 + msr cpsr_c, #0xd2 @ irq mode + mov sp, r0 + sub r0, r0, #128 + msr cpsr_c, #0xdf @ system mode + mov sp, r0 + + @ enable cache & tcm + mrc p15, 0, r0, c1, c0, 0 + ldr r1,= ITCM_ENABLE | DTCM_ENABLE | ICACHE_ENABLE | DCACHE_ENABLE + orr r0,r0,r1 + mcr p15, 0, r0, c1, c0, 0 + + ldr r10, =0x2FFFE04 + ldr r0, =0xE59FF018 + str r0, [r10] + add r1, r10, #0x20 + str r10, [r1] + bx r10 + + .pool + +mpu_initial_data: + .word 0x00000042 @ p15,0,c2,c0,0..1,r0 ;PU Cachability Bits for Data/Unified+Instruction Protection Region + .word 0x00000002 @ p15,0,c3,c0,0,r1 ;PU Write-Bufferability Bits for Data Protection Regions + .word 0x15111011 @ p15,0,c5,c0,2,r2 ;PU Extended Access Permission Data/Unified Protection Region + .word 0x05100011 @ p15,0,c5,c0,3,r3 ;PU Extended Access Permission Instruction Protection Region + .word 0x04000033 @ p15,0,c6,c0,0,r4 ;PU Protection Unit Data/Unified Region 0 + .word 0x0200002b @ p15,0,c6,c1,0,r5 ;PU Protection Unit Data/Unified Region 1 4MB + .word 0x08000035 @ p15,0,c6,c3,0,r6 ;PU Protection Unit Data/Unified Region 3 + .word 0x0300001b @ p15,0,c6,c4,0,r7 ;PU Protection Unit Data/Unified Region 4 + .word 0xffff001d @ p15,0,c6,c6,0,r8 ;PU Protection Unit Data/Unified Region 6 + .word 0x02fff017 @ p15,0,c6,c7,0,r9 ;PU Protection Unit Data/Unified Region 7 4KB + .word 0x0300000a @ p15,0,c9,c1,0,r10 ;TCM Data TCM Base and Virtual Size diff --git a/ndsbootloader/load2.ld b/ndsbootloader/load2.ld new file mode 100644 index 0000000..d1b71dc --- /dev/null +++ b/ndsbootloader/load2.ld @@ -0,0 +1,198 @@ +OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +MEMORY { + + vram : ORIGIN = 0x06020000, LENGTH = 64K +} + +__vram_start = ORIGIN(vram); +__vram_top = ORIGIN(vram)+ LENGTH(vram); +__sp_irq = __vram_top - 0x60; +__sp_svc = __sp_irq - 0x100; +__sp_usr = __sp_svc - 0x100; + +__irq_flags = __vram_top - 8; +__irq_vector = __vram_top - 4; + +SECTIONS +{ + .init : + { + __text_start = . ; + KEEP (*(.init)) + . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ + } >vram = 0xff + + .plt : + { + *(.plt) + } >vram = 0xff + + .text : /* ALIGN (4): */ + { + + *(.text*) + *(.stub) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.gnu.linkonce.t*) + *(.glue_7) + *(.glue_7t) + . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ + } >vram = 0xff + + .fini : + { + KEEP (*(.fini)) + } >vram =0xff + + __text_end = . ; + + .rodata : + { + *(.rodata) + *all.rodata*(*) + *(.roda) + *(.rodata.*) + *(.gnu.linkonce.r*) + SORT(CONSTRUCTORS) + . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ + } >vram = 0xff + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >vram + __exidx_start = .; + .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } >vram + __exidx_end = .; + +/* Ensure the __preinit_array_start label is properly aligned. We + could instead move the label definition inside the section, but + the linker would then create the section even if it turns out to + be empty, which isn't pretty. */ + . = ALIGN(32 / 8); + PROVIDE (__preinit_array_start = .); + .preinit_array : { KEEP (*(.preinit_array)) } >vram = 0xff + PROVIDE (__preinit_array_end = .); + PROVIDE (__init_array_start = .); + .init_array : { KEEP (*(.init_array)) } >vram = 0xff + PROVIDE (__init_array_end = .); + PROVIDE (__fini_array_start = .); + .fini_array : { KEEP (*(.fini_array)) } >vram = 0xff + PROVIDE (__fini_array_end = .); + + .ctors : + { + /* gcc uses crtbegin.o to find the start of the constructors, so + we make sure it is first. Because this is a wildcard, it + doesn't matter if the user does not actually link against + crtbegin.o; the linker won't look for a file to match a + wildcard. The wildcard also means that it doesn't matter which + directory crtbegin.o is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ + } >vram = 0xff + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ + } >vram = 0xff + + .eh_frame : + { + KEEP (*(.eh_frame)) + . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ + } >vram = 0xff + + .gcc_except_table : + { + *(.gcc_except_table) + . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ + } >vram = 0xff + .jcr : { KEEP (*(.jcr)) } >vram = 0 + .got : { *(.got.plt) *(.got) } >vram = 0 + + + .vram ALIGN(4) : + { + __vram_start = ABSOLUTE(.) ; + *(.vram) + *vram.*(.text) + . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ + __vram_end = ABSOLUTE(.) ; + } >vram = 0xff + + + .data ALIGN(4) : { + __data_start = ABSOLUTE(.); + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + CONSTRUCTORS + . = ALIGN(4); + __data_end = ABSOLUTE(.) ; + } >vram = 0xff + + + + .bss ALIGN(4) : + { + __bss_start = ABSOLUTE(.); + __bss_start__ = ABSOLUTE(.); + *(.dynbss) + *(.gnu.linkonce.b*) + *(.bss*) + *(COMMON) + . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ + } >vram + + __bss_end = . ; + __bss_end__ = . ; + + _end = . ; + __end__ = . ; + PROVIDE (end = _end); + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + .stack 0x80000 : { _stack = .; *(.stack) } + /* These must appear regardless of . */ +} diff --git a/ndsbootloader/source/arm7clear.s b/ndsbootloader/source/arm7clear.s new file mode 100644 index 0000000..52343e3 --- /dev/null +++ b/ndsbootloader/source/arm7clear.s @@ -0,0 +1,70 @@ +/*----------------------------------------------------------------- + + Copyright (C) 2005 Michael "Chishm" Chisholm + + 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 + of the License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + If you use this code, please give due credit and email me about your + project at chishm@hotmail.com +------------------------------------------------------------------*/ + + .arm + .global arm7clearRAM + .type arm7clearRAM STT_FUNC +arm7clearRAM: + + push {r0-r9} + // clear exclusive IWRAM + // 0380:0000 to 0380:FFFF, total 64KiB + mov r0, #0 + mov r1, #0 + mov r2, #0 + mov r3, #0 + mov r4, #0 + mov r5, #0 + mov r6, #0 + mov r7, #0 + mov r8, #0x03800000 + sub r8, #0x00008000 + mov r9, #0x03800000 + orr r9, r9, #0x10000 +clear_IWRAM_loop: + stmia r8!, {r0, r1, r2, r3, r4, r5, r6, r7} + cmp r8, r9 + blt clear_IWRAM_loop + + // clear most of EWRAM - except after RAM end - 0xc000, which has the bootstub + mov r8, #0x02000000 + + ldr r9,=0x4004008 + ldr r9,[r9] + ands r9,r9,#0x8000 + bne dsi_mode + + mov r9, #0x02400000 + b ds_mode +dsi_mode: + mov r9, #0x03000000 +ds_mode: + sub r9, #0x0000c000 +clear_EWRAM_loop: + stmia r8!, {r0, r1, r2, r3, r4, r5, r6, r7} + cmp r8, r9 + blt clear_EWRAM_loop + + pop {r0-r9} + + bx lr + diff --git a/ndsbootloader/source/arm9clear.arm.c b/ndsbootloader/source/arm9clear.arm.c new file mode 100644 index 0000000..c909f93 --- /dev/null +++ b/ndsbootloader/source/arm9clear.arm.c @@ -0,0 +1,68 @@ +#define ARM9 +#undef ARM7 + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "boot.h" + +/*------------------------------------------------------------------------- +resetMemory2_ARM9 +Clears the ARM9's DMA channels and resets video memory +Written by Darkain. +Modified by Chishm: + * Changed MultiNDS specific stuff +--------------------------------------------------------------------------*/ +void __attribute__ ((long_call)) __attribute__((naked)) __attribute__((noreturn)) resetMemory2_ARM9 (void) { + register int i; + + //clear out ARM9 DMA channels + for (i=0; i<4; i++) { + DMA_CR(i) = 0; + DMA_SRC(i) = 0; + DMA_DEST(i) = 0; + TIMER_CR(i) = 0; + TIMER_DATA(i) = 0; + } + + //set shared ram to ARM7 + WRAM_CR = 0x03; + + // Return to passme loop + *((vu32*)0x02FFFE04) = (u32)0xE59FF018; // ldr pc, 0x02FFFE24 + *((vu32*)0x02FFFE24) = (u32)0x02FFFE04; // Set ARM9 Loop address + + asm volatile( + "\tbx %0\n" + : : "r" (0x02FFFE04) + ); + while(1); +} + +/*------------------------------------------------------------------------- +startBinary_ARM9 +Jumps to the ARM9 NDS binary in sync with the display and ARM7 +Written by Darkain. +Modified by Chishm: + * Removed MultiNDS specific stuff +--------------------------------------------------------------------------*/ +void __attribute__ ((long_call)) __attribute__((noreturn)) __attribute__((naked)) startBinary_ARM9 (void) { + REG_IME=0; + REG_EXMEMCNT = 0xE880; + // set ARM9 load address to 0 and wait for it to change again + ARM9_START_FLAG = 0; + while(REG_VCOUNT!=191); + while(REG_VCOUNT==191); + while ( ARM9_START_FLAG != 1 ); + VoidFn arm9code = *(VoidFn*)(0x2FFFE24); + arm9code(); + while(1); +} + diff --git a/ndsbootloader/source/arm9mpu_reset.s b/ndsbootloader/source/arm9mpu_reset.s new file mode 100644 index 0000000..bbd10f0 --- /dev/null +++ b/ndsbootloader/source/arm9mpu_reset.s @@ -0,0 +1,6 @@ + .arm + .global mpu_reset, mpu_reset_end + +mpu_reset: + .incbin "mpu_reset.bin" +mpu_reset_end: diff --git a/ndsbootloader/source/bios.s b/ndsbootloader/source/bios.s new file mode 100644 index 0000000..e98f57c --- /dev/null +++ b/ndsbootloader/source/bios.s @@ -0,0 +1,13 @@ + .text + .align 4 + + .thumb + +@--------------------------------------------------------------------------------- + .global swiDelay + .thumb_func +@--------------------------------------------------------------------------------- +swiDelay: +@--------------------------------------------------------------------------------- + swi 0x03 + bx lr diff --git a/ndsbootloader/source/boot.c b/ndsbootloader/source/boot.c new file mode 100644 index 0000000..3b1aa38 --- /dev/null +++ b/ndsbootloader/source/boot.c @@ -0,0 +1,413 @@ +/*----------------------------------------------------------------- + boot.c + + BootLoader + Loads a file into memory and runs it + + All resetMemory and startBinary functions are based + on the MultiNDS loader by Darkain. + Original source available at: + http://cvs.sourceforge.net/viewcvs.py/ndslib/ndslib/examples/loader/boot/main.cpp + +License: + Copyright (C) 2005 Michael "Chishm" Chisholm + + 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 + of the License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + If you use this code, please give due credit and email me about your + project at chishm@hotmail.com + +Helpful information: + This code runs from VRAM bank C on ARM7 +------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include +#include "fat.h" +#include "dldi_patcher.h" +#include "card.h" +#include "boot.h" +#include "sdmmc.h" + +void arm7clearRAM(); + +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// Important things +#define TEMP_MEM 0x02FFD000 +#define TWL_HEAD 0x02FFE000 +#define NDS_HEAD 0x02FFFE00 +#define TEMP_ARM9_START_ADDRESS (*(vu32*)0x02FFFFF4) + +const char* bootName = "BOOT.NDS"; + +extern unsigned long _start; +extern unsigned long storedFileCluster; +extern unsigned long initDisc; +extern unsigned long wantToPatchDLDI; +extern unsigned long argStart; +extern unsigned long argSize; +extern unsigned long dsiSD; +extern unsigned long dsiMode; + +static bool scfgunlock = false; +static bool twlmode = false; +static bool twlclk = false; +static bool twlvram = false; + +#define LAUNCH_DATA 0x020007F0 + +typedef struct sLauncherSettings { + u8 language; + u8 scfgUnlock; + u8 twlMode; + u8 twlCLK; + u8 twlVRAM; + u8 debugMode; + u8 fastBoot; + u8 unused2; +} tLauncherSettings; + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// Firmware stuff + +#define FW_READ 0x03 + +void boot_readFirmware (uint32 address, uint8 * buffer, uint32 size) { + uint32 index; + + // Read command + while (REG_SPICNT & SPI_BUSY); + REG_SPICNT = SPI_ENABLE | SPI_CONTINUOUS | SPI_DEVICE_NVRAM; + REG_SPIDATA = FW_READ; + while (REG_SPICNT & SPI_BUSY); + + // Set the address + REG_SPIDATA = (address>>16) & 0xFF; + while (REG_SPICNT & SPI_BUSY); + REG_SPIDATA = (address>>8) & 0xFF; + while (REG_SPICNT & SPI_BUSY); + REG_SPIDATA = (address) & 0xFF; + while (REG_SPICNT & SPI_BUSY); + + for (index = 0; index < size; index++) { + REG_SPIDATA = 0; + while (REG_SPICNT & SPI_BUSY); + buffer[index] = REG_SPIDATA & 0xFF; + } + REG_SPICNT = 0; +} + + +static inline void copyLoop (u32* dest, const u32* src, u32 size) { + size = (size +3) & ~3; + do { + *dest++ = *src++; + } while (size -= 4); +} + +//#define resetCpu() __asm volatile("\tswi 0x000000\n"); + +static char boot_nds[] = "fat:/boot.nds"; +static unsigned long argbuf[4]; + +/*------------------------------------------------------------------------- +passArgs_ARM7 +Copies the command line arguments to the end of the ARM9 binary, +then sets a flag in memory for the loaded NDS to use +--------------------------------------------------------------------------*/ +void passArgs_ARM7 (void) { + u32 ARM9_DST = *((u32*)(NDS_HEAD + 0x028)); + u32 ARM9_LEN = *((u32*)(NDS_HEAD + 0x02C)); + u32* argSrc; + u32* argDst; + + if (!argStart || !argSize) { + + char *arg = boot_nds; + argSize = __builtin_strlen(boot_nds); + + if (dsiSD) { + arg++; + arg[0] = 's'; + arg[1] = 'd'; + } + __builtin_memcpy(argbuf,arg,argSize+1); + argSrc = argbuf; + } else { + argSrc = (u32*)(argStart + (int)&_start); + } + + if ( ARM9_DST == 0 && ARM9_LEN == 0) { + ARM9_DST = *((u32*)(NDS_HEAD + 0x038)); + ARM9_LEN = *((u32*)(NDS_HEAD + 0x03C)); + } + + + argDst = (u32*)((ARM9_DST + ARM9_LEN + 3) & ~3); // Word aligned + + 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) + { + u32* argDst2 = (u32*)((ARM9i_DST + ARM9i_LEN + 3) & ~3); // Word aligned + if (argDst2 > argDst) + argDst = argDst2; + } + } + + copyLoop(argDst, argSrc, argSize); + + __system_argv->argvMagic = ARGV_MAGIC; + __system_argv->commandLine = (char*)argDst; + __system_argv->length = argSize; +} + +/*------------------------------------------------------------------------- +resetMemory_ARM7 +Clears all of the NDS's RAM that is visible to the ARM7 +Written by Darkain. +Modified by Chishm: + * Added STMIA clear mem loop +--------------------------------------------------------------------------*/ +void resetMemory_ARM7 (void) { + int i; + u8 settings1, settings2; + u32 settingsOffset = 0; + + REG_IME = 0; + + for (i=0; i<16; i++) { + SCHANNEL_CR(i) = 0; + SCHANNEL_TIMER(i) = 0; + SCHANNEL_SOURCE(i) = 0; + SCHANNEL_LENGTH(i) = 0; + } + + REG_SOUNDCNT = 0; + + //clear out ARM7 DMA channels and timers + for (i=0; i<4; i++) { + DMA_CR(i) = 0; + DMA_SRC(i) = 0; + DMA_DEST(i) = 0; + TIMER_CR(i) = 0; + TIMER_DATA(i) = 0; + } + + arm7clearRAM(); + + REG_IE = 0; + REG_IF = ~0; + (*(vu32*)(0x04000000-4)) = 0; //IRQ_HANDLER ARM7 version + (*(vu32*)(0x04000000-8)) = ~0; //VBLANK_INTR_WAIT_FLAGS, ARM7 version + REG_POWERCNT = 1; //turn off power to stuff + + // Get settings location + boot_readFirmware((u32)0x00020, (u8*)&settingsOffset, 0x2); + settingsOffset *= 8; + + // Reload DS Firmware settings + boot_readFirmware(settingsOffset + 0x070, &settings1, 0x1); + boot_readFirmware(settingsOffset + 0x170, &settings2, 0x1); + + if ((settings1 & 0x7F) == ((settings2+1) & 0x7F)) { + boot_readFirmware(settingsOffset + 0x000, (u8*)0x02FFFC80, 0x70); + } else { + boot_readFirmware(settingsOffset + 0x100, (u8*)0x02FFFC80, 0x70); + } + + ((vu32*)0x040044f0)[2] = 0x202DDD1D; + ((vu32*)0x040044f0)[3] = 0xE1A00005; + while((*(vu32*)0x04004400) & 0x2000000); + +} + + +void loadBinary_ARM7 (u32 fileCluster) { + u32 ndsHeader[0x170>>2]; + + // read NDS header + fileRead ((char*)ndsHeader, fileCluster, 0, 0x170); + // read ARM9 info from NDS header + u32 ARM9_SRC = ndsHeader[0x020>>2]; + char* ARM9_DST = (char*)ndsHeader[0x028>>2]; + u32 ARM9_LEN = ndsHeader[0x02C>>2]; + // read ARM7 info from NDS header + u32 ARM7_SRC = ndsHeader[0x030>>2]; + char* ARM7_DST = (char*)ndsHeader[0x038>>2]; + u32 ARM7_LEN = ndsHeader[0x03C>>2]; + + // Load binaries into memory + fileRead(ARM9_DST, fileCluster, ARM9_SRC, ARM9_LEN); + fileRead(ARM7_DST, fileCluster, ARM7_SRC, ARM7_LEN); + + // first copy the header to its proper location, excluding + // the ARM9 start address, so as not to start it + TEMP_ARM9_START_ADDRESS = ndsHeader[0x024>>2]; // Store for later + ndsHeader[0x024>>2] = 0; + dmaCopyWords(3, (void*)ndsHeader, (void*)NDS_HEAD, 0x170); + + if (dsiMode && (ndsHeader[0x10>>2]&BIT(16+1))) { + // Read full TWL header + fileRead((char*)TWL_HEAD, fileCluster, 0, 0x1000); + + u32 ARM9i_SRC = *(u32*)(TWL_HEAD+0x1C0); + char* ARM9i_DST = (char*)*(u32*)(TWL_HEAD+0x1C8); + u32 ARM9i_LEN = *(u32*)(TWL_HEAD+0x1CC); + u32 ARM7i_SRC = *(u32*)(TWL_HEAD+0x1D0); + char* ARM7i_DST = (char*)*(u32*)(TWL_HEAD+0x1D8); + u32 ARM7i_LEN = *(u32*)(TWL_HEAD+0x1DC); + + if (ARM9i_LEN)fileRead(ARM9i_DST, fileCluster, ARM9i_SRC, ARM9i_LEN); + if (ARM7i_LEN)fileRead(ARM7i_DST, fileCluster, ARM7i_SRC, ARM7i_LEN); + } +} + +/*------------------------------------------------------------------------- +startBinary_ARM7 +Jumps to the ARM7 NDS binary in sync with the display and ARM9 +Written by Darkain. +Modified by Chishm: + * Removed MultiNDS specific stuff +--------------------------------------------------------------------------*/ +void startBinary_ARM7 (void) { + REG_IME=0; + while(REG_VCOUNT!=191); + while(REG_VCOUNT==191); + // copy NDS ARM9 start address into the header, starting ARM9 + *((vu32*)0x02FFFE24) = TEMP_ARM9_START_ADDRESS; + ARM9_START_FLAG = 1; + // Start ARM7 + VoidFn arm7code = *(VoidFn*)(0x2FFFE34); + arm7code(); +} +#ifndef NO_SDMMC +int sdmmc_sd_readsectors(u32 sector_no, u32 numsectors, void *out); +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// Main function +bool sdmmc_inserted() { return true; } + +bool sdmmc_startup() { + sdmmc_controller_init(true); + return sdmmc_sdcard_init() == 0; +} + +bool sdmmc_readsectors(u32 sector_no, u32 numsectors, void *out) { return sdmmc_sdcard_readsectors(sector_no, numsectors, out) == 0; } +#endif +void mpu_reset(); +void mpu_reset_end(); + +int main (void) { + + tLauncherSettings* tmpData = (tLauncherSettings*)LAUNCH_DATA; + + if (tmpData->scfgUnlock > 0x00)scfgunlock = true; + if (tmpData->twlMode > 0x00)twlmode = true; + if (tmpData->twlCLK > 0x00)twlclk = true; + if (tmpData->twlVRAM > 0x00)twlvram = true; + + if (twlmode) { + REG_MBK9=0x0300000F; + REG_MBK6=0x080037C0; + REG_MBK7=0x07C03740; + REG_MBK8=0x07403700; + } else { + REG_MBK9=0xFCFFFF0F; + REG_MBK6=0x09403900; + REG_MBK7=0x09803940; + REG_MBK8=0x09C03980; + } + +#ifdef NO_DLDI + dsiSD = true; + dsiMode = true; +#endif +#ifndef NO_SDMMC + if (dsiSD && dsiMode) { + _io_dldi.fn_readSectors = sdmmc_readsectors; + _io_dldi.fn_isInserted = sdmmc_inserted; + _io_dldi.fn_startup = sdmmc_startup; + } +#endif + u32 fileCluster = storedFileCluster; + // Init card + if(!FAT_InitFiles(initDisc))return -1; + /* Invalid file cluster specified */ + if ((fileCluster < CLUSTER_FIRST) || (fileCluster >= CLUSTER_EOF))fileCluster = getBootFileCluster(bootName); + if (fileCluster == CLUSTER_FREE)return -1; + + // ARM9 clears its memory part 2 + // copy ARM9 function to RAM, and make the ARM9 jump to it + copyLoop((void*)TEMP_MEM, (void*)resetMemory2_ARM9, resetMemory2_ARM9_size); + (*(vu32*)0x02FFFE24) = (u32)TEMP_MEM; // Make ARM9 jump to the function + // Wait until the ARM9 has completed its task + while ((*(vu32*)0x02FFFE24) == (u32)TEMP_MEM); + + // ARM9 sets up mpu + // copy ARM9 function to RAM, and make the ARM9 jump to it + copyLoop((void*)TEMP_MEM, (void*)mpu_reset, mpu_reset_end - mpu_reset); + (*(vu32*)0x02FFFE24) = (u32)TEMP_MEM; // Make ARM9 jump to the function + + // Wait until the ARM9 has completed its task + while ((*(vu32*)0x02FFFE24) == (u32)TEMP_MEM); + + // Get ARM7 to clear RAM + resetMemory_ARM7(); + + // ARM9 enters a wait loop + // copy ARM9 function to RAM, and make the ARM9 jump to it + copyLoop((void*)TEMP_MEM, (void*)startBinary_ARM9, startBinary_ARM9_size); + (*(vu32*)0x02FFFE24) = (u32)TEMP_MEM; // Make ARM9 jump to the function + + // Load the NDS file + loadBinary_ARM7(fileCluster); + +#ifndef NO_DLDI + // Patch with DLDI if desired + if (wantToPatchDLDI)dldiPatchBinary ((u8*)((u32*)NDS_HEAD)[0x0A], ((u32*)NDS_HEAD)[0x0B]); +#endif + +#ifndef NO_SDMMC + if (dsiSD && dsiMode) { + sdmmc_controller_init(true); + *(vu16*)(SDMMC_BASE + REG_SDDATACTL32) &= 0xFFFDu; + *(vu16*)(SDMMC_BASE + REG_SDDATACTL) &= 0xFFDDu; + *(vu16*)(SDMMC_BASE + REG_SDBLKLEN32) = 0; + } +#endif + // Pass command line arguments to loaded program + passArgs_ARM7(); + + if (twlclk) { REG_SCFG_CLK = 0x0187; } else { REG_SCFG_CLK = 0x0101; } + if (twlmode) { + REG_SCFG_EXT = 0x92FBFB06; + } else { + REG_SCFG_EXT = 0x92A00000; + REG_SCFG_ROM = 0x703; + } + if (scfgunlock) { REG_SCFG_EXT |= BIT(18); } else { REG_SCFG_EXT &= ~(1UL << 31); } + + startBinary_ARM7(); + + return 0; +} + diff --git a/ndsbootloader/source/boot.h b/ndsbootloader/source/boot.h new file mode 100644 index 0000000..20c8cc0 --- /dev/null +++ b/ndsbootloader/source/boot.h @@ -0,0 +1,11 @@ +#ifndef _BOOT_H_ +#define _BOOT_H_ + +#define resetMemory2_ARM9_size 0x400 +void __attribute__ ((long_call)) __attribute__((naked)) __attribute__((noreturn)) resetMemory2_ARM9(); +#define startBinary_ARM9_size 0x100 +void __attribute__ ((long_call)) __attribute__((noreturn)) __attribute__((naked)) startBinary_ARM9(); +#define ARM9_START_FLAG (*(vu8*)0x02FFFDFB) + +#endif // _BOOT_H_ + diff --git a/ndsbootloader/source/card.h b/ndsbootloader/source/card.h new file mode 100644 index 0000000..cd6f6fb --- /dev/null +++ b/ndsbootloader/source/card.h @@ -0,0 +1,45 @@ +/*----------------------------------------------------------------- + + Copyright (C) 2005 Michael "Chishm" Chisholm + + 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 + of the License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + If you use this code, please give due credit and email me about your + project at chishm@hotmail.com +------------------------------------------------------------------*/ + +#ifndef CARD_H +#define CARD_H + +#include "disc_io.h" +#include "io_dldi.h" + +static inline bool CARD_StartUp (void) { + return _io_dldi.fn_startup(); +} + +static inline bool CARD_IsInserted (void) { + return _io_dldi.fn_isInserted(); +} + +static inline bool CARD_ReadSector (u32 sector, void *buffer) { + return _io_dldi.fn_readSectors(sector, 1, buffer); +} + +static inline bool CARD_ReadSectors (u32 sector, int count, void *buffer) { + return _io_dldi.fn_readSectors(sector, count, buffer); +} + +#endif // CARD_H diff --git a/ndsbootloader/source/disc_io.h b/ndsbootloader/source/disc_io.h new file mode 100644 index 0000000..29033b7 --- /dev/null +++ b/ndsbootloader/source/disc_io.h @@ -0,0 +1,82 @@ +/* + disc_io.h + Interface template for low level disc functions. + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-07-11 - Chishm + * Original release + + 2006-07-16 - Chishm + * Renamed _CF_USE_DMA to _IO_USE_DMA + * Renamed _CF_ALLOW_UNALIGNED to _IO_ALLOW_UNALIGNED +*/ + +#ifndef _DISC_IO_H +#define _DISC_IO_H + +#include +#define BYTES_PER_SECTOR 512 + +//---------------------------------------------------------------------- +// Customisable features + +// Use DMA to read the card, remove this line to use normal reads/writes +// #define _IO_USE_DMA + +// Allow buffers not alligned to 16 bits when reading files. +// Note that this will slow down access speed, so only use if you have to. +// It is also incompatible with DMA +#define _IO_ALLOW_UNALIGNED + +#if defined _IO_USE_DMA && defined _IO_ALLOW_UNALIGNED + #error "You can't use both DMA and unaligned memory" +#endif + +#define FEATURE_MEDIUM_CANREAD 0x00000001 +#define FEATURE_MEDIUM_CANWRITE 0x00000002 +#define FEATURE_SLOT_GBA 0x00000010 +#define FEATURE_SLOT_NDS 0x00000020 + +typedef bool (* FN_MEDIUM_STARTUP)(void) ; +typedef bool (* FN_MEDIUM_ISINSERTED)(void) ; +typedef bool (* FN_MEDIUM_READSECTORS)(u32 sector, u32 numSectors, void* buffer) ; +typedef bool (* FN_MEDIUM_WRITESECTORS)(u32 sector, u32 numSectors, const void* buffer) ; +typedef bool (* FN_MEDIUM_CLEARSTATUS)(void) ; +typedef bool (* FN_MEDIUM_SHUTDOWN)(void) ; + +struct IO_INTERFACE_STRUCT { + unsigned long ioType ; + unsigned long features ; + FN_MEDIUM_STARTUP fn_startup ; + FN_MEDIUM_ISINSERTED fn_isInserted ; + FN_MEDIUM_READSECTORS fn_readSectors ; + FN_MEDIUM_WRITESECTORS fn_writeSectors ; + FN_MEDIUM_CLEARSTATUS fn_clearStatus ; + FN_MEDIUM_SHUTDOWN fn_shutdown ; +} ; + +typedef struct IO_INTERFACE_STRUCT IO_INTERFACE ; + +#endif // define _DISC_IO_H diff --git a/ndsbootloader/source/dldi_patcher.c b/ndsbootloader/source/dldi_patcher.c new file mode 100644 index 0000000..061b955 --- /dev/null +++ b/ndsbootloader/source/dldi_patcher.c @@ -0,0 +1,223 @@ +/*----------------------------------------------------------------- + + Copyright (C) 2005 Michael "Chishm" Chisholm + + 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 + of the License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + If you use this code, please give due credit and email me about your + project at chishm@hotmail.com +------------------------------------------------------------------*/ +#ifndef NO_DLDI +#include +#include +#include "dldi_patcher.h" + +#define FIX_ALL 0x01 +#define FIX_GLUE 0x02 +#define FIX_GOT 0x04 +#define FIX_BSS 0x08 + +enum DldiOffsets { + DO_magicString = 0x00, // "\xED\xA5\x8D\xBF Chishm" + DO_magicToken = 0x00, // 0xBF8DA5ED + DO_magicShortString = 0x04, // " Chishm" + DO_version = 0x0C, + DO_driverSize = 0x0D, + DO_fixSections = 0x0E, + DO_allocatedSpace = 0x0F, + + DO_friendlyName = 0x10, + + DO_text_start = 0x40, // Data start + DO_data_end = 0x44, // Data end + DO_glue_start = 0x48, // Interworking glue start -- Needs address fixing + DO_glue_end = 0x4C, // Interworking glue end + DO_got_start = 0x50, // GOT start -- Needs address fixing + DO_got_end = 0x54, // GOT end + DO_bss_start = 0x58, // bss start -- Needs setting to zero + DO_bss_end = 0x5C, // bss end + + // IO_INTERFACE data + DO_ioType = 0x60, + DO_features = 0x64, + DO_startup = 0x68, + DO_isInserted = 0x6C, + DO_readSectors = 0x70, + DO_writeSectors = 0x74, + DO_clearStatus = 0x78, + DO_shutdown = 0x7C, + DO_code = 0x80 +}; + +static addr_t readAddr (data_t *mem, addr_t offset) { + return ((addr_t*)mem)[offset/sizeof(addr_t)]; +} + +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) { + const int* dataChunk = (const int*) data; + int searchChunk = ((const int*)search)[0]; + addr_t i; + addr_t dataChunkEnd = (addr_t)(dataLen / sizeof(int)); + + for ( i = 0; i < dataChunkEnd; i++) { + if (dataChunk[i] == searchChunk) { + if ((i*sizeof(int) + searchLen) > dataLen) { + return -1; + } + if (memcmp (&data[i*sizeof(int)], search, searchLen) == 0) { + return i*sizeof(int); + } + } + } + + return -1; +} + +// 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 data_t _dldi_start[]; + +bool dldiPatchBinary (data_t *binData, u32 binSize) { + + 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 + 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; + data_t *pAH; + + data_t dldiMagicString[DLDI_MAGIC_LEN]; + size_t dldiFileSize = 0; + + // Find the DLDI reserved space in the file + demangleMagicString(dldiMagicString, dldiMagicStringMangled); + patchOffset = quickFind (binData, dldiMagicString, binSize, sizeof(dldiMagicString)); + + if (patchOffset < 0) { + // does not have a DLDI section + return false; + } + + pDH = _dldi_start; + pAH = &(binData[patchOffset]); + + 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; + } + + dldiFileSize = 1 << pDH[DO_driverSize]; + + memOffset = readAddr (pAH, DO_text_start); + if (memOffset == 0) { + memOffset = readAddr (pAH, DO_startup) - DO_code; + } + ddmemOffset = readAddr (pDH, DO_text_start); + relocationOffset = memOffset - ddmemOffset; + + ddmemStart = readAddr (pDH, DO_text_start); + ddmemSize = (1 << pDH[DO_driverSize]); + ddmemEnd = ddmemStart + ddmemSize; + + // Remember how much space is actually reserved + pDH[DO_allocatedSpace] = pAH[DO_allocatedSpace]; + // Copy the DLDI patch into the application + memcpy (pAH, pDH, dldiFileSize); + + // Fix the section pointers in the header + writeAddr (pAH, DO_text_start, readAddr (pAH, DO_text_start) + relocationOffset); + writeAddr (pAH, DO_data_end, readAddr (pAH, DO_data_end) + relocationOffset); + writeAddr (pAH, DO_glue_start, readAddr (pAH, DO_glue_start) + relocationOffset); + writeAddr (pAH, DO_glue_end, readAddr (pAH, DO_glue_end) + relocationOffset); + writeAddr (pAH, DO_got_start, readAddr (pAH, DO_got_start) + relocationOffset); + writeAddr (pAH, DO_got_end, readAddr (pAH, DO_got_end) + relocationOffset); + writeAddr (pAH, DO_bss_start, readAddr (pAH, DO_bss_start) + relocationOffset); + writeAddr (pAH, DO_bss_end, readAddr (pAH, DO_bss_end) + relocationOffset); + // Fix the function pointers in the header + writeAddr (pAH, DO_startup, readAddr (pAH, DO_startup) + relocationOffset); + writeAddr (pAH, DO_isInserted, readAddr (pAH, DO_isInserted) + relocationOffset); + writeAddr (pAH, DO_readSectors, readAddr (pAH, DO_readSectors) + relocationOffset); + writeAddr (pAH, DO_writeSectors, readAddr (pAH, DO_writeSectors) + relocationOffset); + writeAddr (pAH, DO_clearStatus, readAddr (pAH, DO_clearStatus) + relocationOffset); + 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)); + + 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)) { + writeAddr (pAH, addrIter, readAddr(pAH, 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(pAH, addrIter)) && (readAddr(pAH, addrIter) < ddmemEnd)) { + writeAddr (pAH, addrIter, readAddr(pAH, 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(pAH, addrIter)) && (readAddr(pAH, addrIter) < ddmemEnd)) { + writeAddr (pAH, addrIter, readAddr(pAH, addrIter) + relocationOffset); + } + } + } + + 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)); + } + + return true; +} +#endif \ No newline at end of file diff --git a/ndsbootloader/source/dldi_patcher.h b/ndsbootloader/source/dldi_patcher.h new file mode 100644 index 0000000..f54c531 --- /dev/null +++ b/ndsbootloader/source/dldi_patcher.h @@ -0,0 +1,32 @@ +/*----------------------------------------------------------------- + + Copyright (C) 2005 Michael "Chishm" Chisholm + + 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 + of the License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + If you use this code, please give due credit and email me about your + project at chishm@hotmail.com +------------------------------------------------------------------*/ + +#ifndef DLDI_PATCHER_H +#define DLDI_PATCHER_H + +#include + +typedef signed int addr_t; +typedef unsigned char data_t; +bool dldiPatchBinary (data_t *binData, u32 binSize); + +#endif // DLDI_PATCHER_H diff --git a/ndsbootloader/source/fat.c b/ndsbootloader/source/fat.c new file mode 100644 index 0000000..3a6243d --- /dev/null +++ b/ndsbootloader/source/fat.c @@ -0,0 +1,592 @@ +/*----------------------------------------------------------------- + fat.c + + NDS MP + GBAMP NDS Firmware Hack Version 2.12 + An NDS aware firmware patch for the GBA Movie Player. + By Michael Chisholm (Chishm) + + Filesystem code based on GBAMP_CF.c by Chishm (me). + +License: + Copyright (C) 2005 Michael "Chishm" Chisholm + + 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 + of the License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + If you use this code, please give due credit and email me about your + project at chishm@hotmail.com +------------------------------------------------------------------*/ + +#include "fat.h" +#include "card.h" + + +//--------------------------------------------------------------- +// FAT constants + +#define FILE_LAST 0x00 +#define FILE_FREE 0xE5 + +#define ATTRIB_ARCH 0x20 +#define ATTRIB_DIR 0x10 +#define ATTRIB_LFN 0x0F +#define ATTRIB_VOL 0x08 +#define ATTRIB_HID 0x02 +#define ATTRIB_SYS 0x04 +#define ATTRIB_RO 0x01 + +#define FAT16_ROOT_DIR_CLUSTER 0x00 + +// File Constants +#ifndef EOF +#define EOF -1 +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 +#endif + + +//----------------------------------------------------------------- +// FAT constants +#define CLUSTER_EOF_16 0xFFFF + +#define ATTRIB_ARCH 0x20 +#define ATTRIB_DIR 0x10 +#define ATTRIB_LFN 0x0F +#define ATTRIB_VOL 0x08 +#define ATTRIB_HID 0x02 +#define ATTRIB_SYS 0x04 +#define ATTRIB_RO 0x01 + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// Data Structures + +#define __PACKED __attribute__ ((__packed__)) + +// BIOS Parameter Block +typedef struct { + + u16 bytesPerSector; + u8 sectorsPerCluster; + u16 reservedSectors; + u8 numFATs; + u16 rootEntries; + u16 numSectorsSmall; + u8 mediaDesc; + u16 sectorsPerFAT; + u16 sectorsPerTrk; + u16 numHeads; + u32 numHiddenSectors; + u32 numSectors; +} __PACKED BIOS_BPB; + +// Boot Sector - must be packed +typedef struct +{ + u8 jmpBoot[3]; + u8 OEMName[8]; + BIOS_BPB bpb; + union // Different types of extended BIOS Parameter Block for FAT16 and FAT32 + { + struct + { + // Ext BIOS Parameter Block for FAT16 + u8 driveNumber; + u8 reserved1; + u8 extBootSig; + u32 volumeID; + u8 volumeLabel[11]; + u8 fileSysType[8]; + // Bootcode + u8 bootCode[448]; + } __PACKED fat16; + struct + { + // FAT32 extended block + u32 sectorsPerFAT32; + u16 extFlags; + u16 fsVer; + u32 rootClus; + u16 fsInfo; + u16 bkBootSec; + u8 reserved[12]; + // Ext BIOS Parameter Block for FAT16 + u8 driveNumber; + u8 reserved1; + u8 extBootSig; + u32 volumeID; + u8 volumeLabel[11]; + u8 fileSysType[8]; + // Bootcode + u8 bootCode[420]; + } __PACKED fat32; + } __PACKED extBlock; + + __PACKED u16 bootSig; + +} __PACKED BOOT_SEC; + +// _Static_assert(sizeof(BOOT_SEC) == 512); + +// Directory entry - must be packed +typedef struct +{ + u8 name[8]; + u8 ext[3]; + u8 attrib; + u8 reserved; + u8 cTime_ms; + u16 cTime; + u16 cDate; + u16 aDate; + u16 startClusterHigh; + u16 mTime; + u16 mDate; + u16 startCluster; + u32 fileSize; +} __PACKED DIR_ENT; + +// File information - no need to pack +typedef struct +{ + u32 firstCluster; + u32 length; + u32 curPos; + u32 curClus; // Current cluster to read from + int curSect; // Current sector within cluster + int curByte; // Current byte within sector + char readBuffer[512]; // Buffer used for unaligned reads + u32 appClus; // Cluster to append to + int appSect; // Sector within cluster for appending + int appByte; // Byte within sector for appending + bool read; // Can read from file + bool write; // Can write to file + bool append;// Can append to file + bool inUse; // This file is open + u32 dirEntSector; // The sector where the directory entry is stored + int dirEntOffset; // The offset within the directory sector +} FAT_FILE; + + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// Global Variables + +// _VARS_IN_RAM variables are stored in the largest section of WRAM +// available: IWRAM on NDS ARM7, EWRAM on NDS ARM9 and GBA + +// Locations on card +int discRootDir; +int discRootDirClus; +int discFAT; +int discSecPerFAT; +int discNumSec; +int discData; +int discBytePerSec; +int discSecPerClus; +int discBytePerClus; + +enum {FS_UNKNOWN, FS_FAT12, FS_FAT16, FS_FAT32} discFileSystem; + +// Global sector buffer to save on stack space +unsigned char globalBuffer[BYTES_PER_SECTOR]; + + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//FAT routines + +u32 FAT_ClustToSect (u32 cluster) { + return (((cluster-2) * discSecPerClus) + discData); +} + +/*----------------------------------------------------------------- +FAT_NextCluster +Internal function - gets the cluster linked from input cluster +-----------------------------------------------------------------*/ +u32 FAT_NextCluster(u32 cluster) +{ + u32 nextCluster = CLUSTER_FREE; + u32 sector; + int offset; + + + switch (discFileSystem) + { + case FS_UNKNOWN: + nextCluster = CLUSTER_FREE; + break; + + case FS_FAT12: + sector = discFAT + (((cluster * 3) / 2) / BYTES_PER_SECTOR); + offset = ((cluster * 3) / 2) % BYTES_PER_SECTOR; + CARD_ReadSector(sector, globalBuffer); + nextCluster = ((u8*) globalBuffer)[offset]; + offset++; + + if (offset >= BYTES_PER_SECTOR) { + offset = 0; + sector++; + } + + CARD_ReadSector(sector, globalBuffer); + nextCluster |= (((u8*) globalBuffer)[offset]) << 8; + + if (cluster & 0x01) { + nextCluster = nextCluster >> 4; + } else { + nextCluster &= 0x0FFF; + } + + break; + + case FS_FAT16: + sector = discFAT + ((cluster << 1) / BYTES_PER_SECTOR); + offset = cluster % (BYTES_PER_SECTOR >> 1); + + CARD_ReadSector(sector, globalBuffer); + // read the nextCluster value + nextCluster = ((u16*)globalBuffer)[offset]; + + if (nextCluster >= 0xFFF7) + { + nextCluster = CLUSTER_EOF; + } + break; + + case FS_FAT32: + sector = discFAT + ((cluster << 2) / BYTES_PER_SECTOR); + offset = cluster % (BYTES_PER_SECTOR >> 2); + + CARD_ReadSector(sector, globalBuffer); + // read the nextCluster value + nextCluster = (((u32*)globalBuffer)[offset]) & 0x0FFFFFFF; + + if (nextCluster >= 0x0FFFFFF7) + { + nextCluster = CLUSTER_EOF; + } + break; + + default: + nextCluster = CLUSTER_FREE; + break; + } + + return nextCluster; +} + +/*----------------------------------------------------------------- +ucase +Returns the uppercase version of the given char +char IN: a character +char return OUT: uppercase version of character +-----------------------------------------------------------------*/ +char ucase (char character) +{ + if ((character > 0x60) && (character < 0x7B)) + character = character - 0x20; + return (character); +} + +/*----------------------------------------------------------------- +FAT_InitFiles +Reads the FAT information from the CF card. +You need to call this before reading any files. +bool return OUT: true if successful. +-----------------------------------------------------------------*/ +bool FAT_InitFiles (bool initCard) +{ + int i; + int bootSector; + BOOT_SEC* bootSec; + + if (initCard && !CARD_StartUp()) + { + return (false); + } + + // Read first sector of card + if (!CARD_ReadSector (0, globalBuffer)) + { + return false; + } + // Check if there is a FAT string, which indicates this is a boot sector + if ((globalBuffer[0x36] == 'F') && (globalBuffer[0x37] == 'A') && (globalBuffer[0x38] == 'T')) + { + bootSector = 0; + } + // Check for FAT32 + else if ((globalBuffer[0x52] == 'F') && (globalBuffer[0x53] == 'A') && (globalBuffer[0x54] == 'T')) + { + bootSector = 0; + } + else // This is an MBR + { + // Find first valid partition from MBR + // First check for an active partition + for (i=0x1BE; (i < 0x1FE) && (globalBuffer[i] != 0x80); i+= 0x10); + // If it didn't find an active partition, search for any valid partition + if (i == 0x1FE) + for (i=0x1BE; (i < 0x1FE) && (globalBuffer[i+0x04] == 0x00); i+= 0x10); + + // Go to first valid partition + if ( i != 0x1FE) // Make sure it found a partition + { + bootSector = globalBuffer[0x8 + i] + (globalBuffer[0x9 + i] << 8) + (globalBuffer[0xA + i] << 16) + ((globalBuffer[0xB + i] << 24) & 0x0F); + } else { + bootSector = 0; // No partition found, assume this is a MBR free disk + } + } + + // Read in boot sector + bootSec = (BOOT_SEC*) globalBuffer; + CARD_ReadSector (bootSector, bootSec); + + // Store required information about the file system + if (bootSec->bpb.sectorsPerFAT != 0) + { + discSecPerFAT = bootSec->bpb.sectorsPerFAT; + } + else + { + discSecPerFAT = bootSec->extBlock.fat32.sectorsPerFAT32; + } + + if (bootSec->bpb.numSectorsSmall != 0) + { + discNumSec = bootSec->bpb.numSectorsSmall; + } + else + { + discNumSec = bootSec->bpb.numSectors; + } + + discBytePerSec = BYTES_PER_SECTOR; // Sector size is redefined to be 512 bytes + discSecPerClus = bootSec->bpb.sectorsPerCluster * bootSec->bpb.bytesPerSector / BYTES_PER_SECTOR; + discBytePerClus = discBytePerSec * discSecPerClus; + discFAT = bootSector + bootSec->bpb.reservedSectors; + + discRootDir = discFAT + (bootSec->bpb.numFATs * discSecPerFAT); + discData = discRootDir + ((bootSec->bpb.rootEntries * sizeof(DIR_ENT)) / BYTES_PER_SECTOR); + + if ((discNumSec - discData) / bootSec->bpb.sectorsPerCluster < 4085) + { + discFileSystem = FS_FAT12; + } + else if ((discNumSec - discData) / bootSec->bpb.sectorsPerCluster < 65525) + { + discFileSystem = FS_FAT16; + } + else + { + discFileSystem = FS_FAT32; + } + + if (discFileSystem != FS_FAT32) + { + discRootDirClus = FAT16_ROOT_DIR_CLUSTER; + } + else // Set up for the FAT32 way + { + discRootDirClus = bootSec->extBlock.fat32.rootClus; + // Check if FAT mirroring is enabled + if (!(bootSec->extBlock.fat32.extFlags & 0x80)) + { + // Use the active FAT + discFAT = discFAT + ( discSecPerFAT * (bootSec->extBlock.fat32.extFlags & 0x0F)); + } + } + + return (true); +} + + +/*----------------------------------------------------------------- +getBootFileCluster +-----------------------------------------------------------------*/ +u32 getBootFileCluster (const char* bootName) +{ + DIR_ENT dir; + int firstSector = 0; + bool notFound = false; + bool found = false; +// int maxSectors; + u32 wrkDirCluster = discRootDirClus; + u32 wrkDirSector = 0; + int wrkDirOffset = 0; + int nameOffset; + + dir.startCluster = CLUSTER_FREE; // default to no file found + dir.startClusterHigh = CLUSTER_FREE; + + + // Check if fat has been initialised + if (discBytePerSec == 0) + { + return (CLUSTER_FREE); + } + + char *ptr = (char*)bootName; + while (*ptr != '.') ptr++; + int namelen = ptr - bootName; + +// maxSectors = (wrkDirCluster == FAT16_ROOT_DIR_CLUSTER ? (discData - discRootDir) : discSecPerClus); + // Scan Dir for correct entry + firstSector = discRootDir; + CARD_ReadSector (firstSector + wrkDirSector, globalBuffer); + found = false; + notFound = false; + wrkDirOffset = -1; // Start at entry zero, Compensating for increment + while (!found && !notFound) { + wrkDirOffset++; + if (wrkDirOffset == BYTES_PER_SECTOR / sizeof (DIR_ENT)) + { + wrkDirOffset = 0; + wrkDirSector++; + if ((wrkDirSector == discSecPerClus) && (wrkDirCluster != FAT16_ROOT_DIR_CLUSTER)) + { + wrkDirSector = 0; + wrkDirCluster = FAT_NextCluster(wrkDirCluster); + if (wrkDirCluster == CLUSTER_EOF) + { + notFound = true; + } + firstSector = FAT_ClustToSect(wrkDirCluster); + } + else if ((wrkDirCluster == FAT16_ROOT_DIR_CLUSTER) && (wrkDirSector == (discData - discRootDir))) + { + notFound = true; // Got to end of root dir + } + CARD_ReadSector (firstSector + wrkDirSector, globalBuffer); + } + dir = ((DIR_ENT*) globalBuffer)[wrkDirOffset]; + found = true; + if ((dir.attrib & ATTRIB_DIR) || (dir.attrib & ATTRIB_VOL)) + { + found = false; + } + if(namelen<8 && dir.name[namelen]!=0x20) found = false; + for (nameOffset = 0; nameOffset < namelen && found; nameOffset++) + { + if (ucase(dir.name[nameOffset]) != bootName[nameOffset]) + found = false; + } + for (nameOffset = 0; nameOffset < 3 && found; nameOffset++) + { + if (ucase(dir.ext[nameOffset]) != bootName[nameOffset+namelen+1]) + found = false; + } + if (dir.name[0] == FILE_LAST) + { + notFound = true; + } + } + + // If no file is found, return CLUSTER_FREE + if (notFound) + { + return CLUSTER_FREE; + } + + return (dir.startCluster | (dir.startClusterHigh << 16)); +} + +/*----------------------------------------------------------------- +fileRead(buffer, cluster, startOffset, length) +-----------------------------------------------------------------*/ +u32 fileRead (char* buffer, u32 cluster, u32 startOffset, u32 length) +{ + int curByte; + int curSect; + + int dataPos = 0; + int chunks; + int beginBytes; + + if (cluster == CLUSTER_FREE || cluster == CLUSTER_EOF) + { + return 0; + } + + // Follow cluster list until desired one is found + for (chunks = startOffset / discBytePerClus; chunks > 0; chunks--) + { + cluster = FAT_NextCluster (cluster); + } + + // Calculate the sector and byte of the current position, + // and store them + curSect = (startOffset % discBytePerClus) / BYTES_PER_SECTOR; + curByte = startOffset % BYTES_PER_SECTOR; + + // Load sector buffer for new position in file + CARD_ReadSector( curSect + FAT_ClustToSect(cluster), globalBuffer); + curSect++; + + // Number of bytes needed to read to align with a sector + beginBytes = (BYTES_PER_SECTOR < length + curByte ? (BYTES_PER_SECTOR - curByte) : length); + + // Read first part from buffer, to align with sector boundary + for (dataPos = 0 ; dataPos < beginBytes; dataPos++) + { + buffer[dataPos] = globalBuffer[curByte++]; + } + + // Read in all the 512 byte chunks of the file directly, saving time + for ( chunks = ((int)length - beginBytes) / BYTES_PER_SECTOR; chunks > 0;) + { + int sectorsToRead; + + // Move to the next cluster if necessary + if (curSect >= discSecPerClus) + { + curSect = 0; + cluster = FAT_NextCluster (cluster); + } + + // Calculate how many sectors to read (read a maximum of discSecPerClus at a time) + sectorsToRead = discSecPerClus - curSect; + if(chunks < sectorsToRead) + sectorsToRead = chunks; + + // Read the sectors + CARD_ReadSectors(curSect + FAT_ClustToSect(cluster), sectorsToRead, buffer + dataPos); + chunks -= sectorsToRead; + curSect += sectorsToRead; + dataPos += BYTES_PER_SECTOR * sectorsToRead; + } + + // Take care of any bytes left over before end of read + if (dataPos < length) + { + + // Update the read buffer + curByte = 0; + if (curSect >= discSecPerClus) + { + curSect = 0; + cluster = FAT_NextCluster (cluster); + } + CARD_ReadSector( curSect + FAT_ClustToSect( cluster), globalBuffer); + + // Read in last partial chunk + for (; dataPos < length; dataPos++) + { + buffer[dataPos] = globalBuffer[curByte]; + curByte++; + } + } + + return dataPos; +} diff --git a/ndsbootloader/source/fat.h b/ndsbootloader/source/fat.h new file mode 100644 index 0000000..d39076b --- /dev/null +++ b/ndsbootloader/source/fat.h @@ -0,0 +1,46 @@ +/*----------------------------------------------------------------- + fat.h + + NDS MP + GBAMP NDS Firmware Hack Version 2.12 + An NDS aware firmware patch for the GBA Movie Player. + By Michael Chisholm (Chishm) + + Filesystem code based on GBAMP_CF.c by Chishm (me). + +License: + Copyright (C) 2005 Michael "Chishm" Chisholm + + 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 + of the License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + If you use this code, please give due credit and email me about your + project at chishm@hotmail.com +------------------------------------------------------------------*/ + +#ifndef FAT_H +#define FAT_H + +#include + +#define CLUSTER_FREE 0x00000000 +#define CLUSTER_EOF 0x0FFFFFFF +#define CLUSTER_FIRST 0x00000002 + +bool FAT_InitFiles (bool initCard); +u32 getBootFileCluster (const char* bootName); +u32 fileRead (char* buffer, u32 cluster, u32 startOffset, u32 length); +u32 FAT_ClustToSect (u32 cluster); + +#endif // FAT_H diff --git a/ndsbootloader/source/io_dldi.h b/ndsbootloader/source/io_dldi.h new file mode 100644 index 0000000..e0f4efa --- /dev/null +++ b/ndsbootloader/source/io_dldi.h @@ -0,0 +1,44 @@ +/* + io_dldi.h + + Reserved space for post-compilation adding of an extra driver + + Copyright (c) 2006 Michael "Chishm" Chisholm + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + 2006-12-22 - Chishm + * Original release +*/ + +#ifndef IO_DLDI_H +#define IO_DLDI_H + +// 'DLDD' +#define DEVICE_TYPE_DLDD 0x49444C44 + +#include "disc_io.h" + +// export interface +extern IO_INTERFACE _io_dldi ; + +#endif // define IO_DLDI_H diff --git a/ndsbootloader/source/io_dldi.s b/ndsbootloader/source/io_dldi.s new file mode 100644 index 0000000..3b7f244 --- /dev/null +++ b/ndsbootloader/source/io_dldi.s @@ -0,0 +1,124 @@ +/*----------------------------------------------------------------- + + Copyright (C) 2005 Michael "Chishm" Chisholm + + 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 + of the License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + If you use this code, please give due credit and email me about your + project at chishm@hotmail.com +------------------------------------------------------------------*/ +@--------------------------------------------------------------------------------- + .align 4 + .arm + .global _dldi_start + .global _io_dldi +@--------------------------------------------------------------------------------- +.equ FEATURE_MEDIUM_CANREAD, 0x00000001 +.equ FEATURE_MEDIUM_CANWRITE, 0x00000002 +.equ FEATURE_SLOT_GBA, 0x00000010 +.equ FEATURE_SLOT_NDS, 0x00000020 + + +_dldi_start: +#ifndef NO_DLDI + +@--------------------------------------------------------------------------------- +@ Driver patch file standard header -- 32 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 0x1a @ 32KiB @ Log [base-2] of the size of this driver in bytes. + .byte 0x00 @ Sections to fix + .byte 0x1a @ 32KiB @ Log [base-2] of the allocated space in bytes. + +@--------------------------------------------------------------------------------- +@ Text identifier - can be anything up to 47 chars + terminating null -- 32 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 + 32768) - . @ Fill to 32KiB + +_dldi_end: + .end +@--------------------------------------------------------------------------------- +#else +@--------------------------------------------------------------------------------- +@ 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 + + +#endif diff --git a/ndsbootloader/source/load_crt0.s b/ndsbootloader/source/load_crt0.s new file mode 100644 index 0000000..6c57e6d --- /dev/null +++ b/ndsbootloader/source/load_crt0.s @@ -0,0 +1,147 @@ +/*----------------------------------------------------------------- + + Copyright (C) 2005 Michael "Chishm" Chisholm + + 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 + of the License, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + If you use this code, please give due credit and email me about your + project at chishm@hotmail.com +------------------------------------------------------------------*/ + +@--------------------------------------------------------------------------------- + .section ".init" + .global _start + .global storedFileCluster + .global initDisc + .global wantToPatchDLDI + .global argStart + .global argSize + .global dsiSD + .global dsiMode +@--------------------------------------------------------------------------------- + .align 4 + .arm +@--------------------------------------------------------------------------------- +_start: +@--------------------------------------------------------------------------------- + b startUp + +storedFileCluster: + .word 0x0FFFFFFF @ default BOOT.NDS +initDisc: + .word 0x00000001 @ init the disc by default +wantToPatchDLDI: + .word 0x00000001 @ by default patch the DLDI section of the loaded NDS +@ Used for passing arguments to the loaded app +argStart: + .word _end - _start +argSize: + .word 0x00000000 +dldiOffset: + .word _dldi_start - _start +dsiSD: + .word 0 +dsiMode: + .word 0 + +startUp: + mov r0, #0x04000000 + mov r1, #0 + str r1, [r0,#0x208] @ REG_IME + str r1, [r0,#0x210] @ REG_IE + str r1, [r0,#0x218] @ REG_AUXIE + + mov r0, #0x12 @ Switch to IRQ Mode + msr cpsr, r0 + ldr sp, =__sp_irq @ Set IRQ stack + + mov r0, #0x13 @ Switch to SVC Mode + msr cpsr, r0 + ldr sp, =__sp_svc @ Set SVC stack + + mov r0, #0x1F @ Switch to System Mode + msr cpsr, r0 + ldr sp, =__sp_usr @ Set user stack + + ldr r0, =__bss_start @ Clear BSS section to 0x00 + ldr r1, =__bss_end + sub r1, r1, r0 + bl ClearMem + + mov r0, #0 @ int argc + mov r1, #0 @ char *argv[] + ldr r3, =main + bl _blx_r3_stub @ jump to user code + + @ If the user ever returns, restart + b _start + +@--------------------------------------------------------------------------------- +_blx_r3_stub: +@--------------------------------------------------------------------------------- + bx r3 + +@--------------------------------------------------------------------------------- +@ Clear memory to 0x00 if length != 0 +@ r0 = Start Address +@ r1 = Length +@--------------------------------------------------------------------------------- +ClearMem: +@--------------------------------------------------------------------------------- + mov r2, #3 @ Round down to nearest word boundary + add r1, r1, r2 @ Shouldn't be needed + bics r1, r1, r2 @ Clear 2 LSB (and set Z) + bxeq lr @ Quit if copy size is 0 + + mov r2, #0 +ClrLoop: + stmia r0!, {r2} + subs r1, r1, #4 + bne ClrLoop + bx lr + +@--------------------------------------------------------------------------------- +@ Copy memory if length != 0 +@ r1 = Source Address +@ r2 = Dest Address +@ r4 = Dest Address + Length +@--------------------------------------------------------------------------------- +CopyMemCheck: +@--------------------------------------------------------------------------------- + sub r3, r4, r2 @ Is there any data to copy? +@--------------------------------------------------------------------------------- +@ Copy memory +@ r1 = Source Address +@ r2 = Dest Address +@ r3 = Length +@--------------------------------------------------------------------------------- +CopyMem: +@--------------------------------------------------------------------------------- + mov r0, #3 @ These commands are used in cases where + add r3, r3, r0 @ the length is not a multiple of 4, + bics r3, r3, r0 @ even though it should be. + bxeq lr @ Length is zero, so exit +CIDLoop: + ldmia r1!, {r0} + stmia r2!, {r0} + subs r3, r3, #4 + bne CIDLoop + bx lr + +@--------------------------------------------------------------------------------- + .align + .pool + .end +@--------------------------------------------------------------------------------- diff --git a/ndsbootloader/source/sdmmc.c b/ndsbootloader/source/sdmmc.c new file mode 100644 index 0000000..1da63ee --- /dev/null +++ b/ndsbootloader/source/sdmmc.c @@ -0,0 +1,242 @@ +#ifndef NO_SDMMC +#include +#include +#include "sdmmc.h" + +static struct mmcdevice deviceSD; + +//--------------------------------------------------------------------------------- +int geterror(struct mmcdevice *ctx) { +//--------------------------------------------------------------------------------- + //if(ctx->error == 0x4) return -1; + //else return 0; + return (ctx->error << 29) >> 31; +} + + +//--------------------------------------------------------------------------------- +void setTarget(struct mmcdevice *ctx) { +//--------------------------------------------------------------------------------- + sdmmc_mask16(REG_SDPORTSEL,0x3,(u16)ctx->devicenumber); + setckl(ctx->clk); + if (ctx->SDOPT == 0) { + sdmmc_mask16(REG_SDOPT, 0, 0x8000); + } else { + sdmmc_mask16(REG_SDOPT, 0x8000, 0); + } + +} + + +//--------------------------------------------------------------------------------- +void sdmmc_send_command(struct mmcdevice *ctx, uint32_t cmd, uint32_t args) { +//--------------------------------------------------------------------------------- + int i; + bool getSDRESP = (cmd << 15) >> 31; + uint16_t flags = (cmd << 15) >> 31; + const bool readdata = cmd & 0x20000; + const bool writedata = cmd & 0x40000; + + if(readdata || writedata) + { + flags |= TMIO_STAT0_DATAEND; + } + + ctx->error = 0; + while((sdmmc_read16(REG_SDSTATUS1) & TMIO_STAT1_CMD_BUSY)); //mmc working? + sdmmc_write16(REG_SDIRMASK0,0); + sdmmc_write16(REG_SDIRMASK1,0); + sdmmc_write16(REG_SDSTATUS0,0); + sdmmc_write16(REG_SDSTATUS1,0); + sdmmc_write16(REG_SDCMDARG0,args &0xFFFF); + sdmmc_write16(REG_SDCMDARG1,args >> 16); + sdmmc_write16(REG_SDCMD,cmd &0xFFFF); + + uint32_t size = ctx->size; + uint16_t *dataPtr = (uint16_t*)ctx->data; + uint32_t *dataPtr32 = (uint32_t*)ctx->data; + + bool useBuf = ( NULL != dataPtr ); + bool useBuf32 = (useBuf && (0 == (3 & ((uint32_t)dataPtr)))); + + uint16_t status0 = 0; + + while(1) { + volatile uint16_t status1 = sdmmc_read16(REG_SDSTATUS1); + volatile uint16_t ctl32 = sdmmc_read16(REG_SDDATACTL32); + if((ctl32 & 0x100)) + { + if(readdata) { + if(useBuf) { + sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_RXRDY, 0); + if(size > 0x1FF) { + if(useBuf32) { + for(i = 0; i<0x200; i+=4) { + *dataPtr32++ = sdmmc_read32(REG_SDFIFO32); + } + } else { + for(i = 0; i<0x200; i+=2) { + *dataPtr++ = sdmmc_read16(REG_SDFIFO); + } + } + size -= 0x200; + } + } + + sdmmc_mask16(REG_SDDATACTL32, 0x800, 0); + } + } + + if(status1 & TMIO_MASK_GW) { + ctx->error |= 4; + break; + } + + if(!(status1 & TMIO_STAT1_CMD_BUSY)) { + status0 = sdmmc_read16(REG_SDSTATUS0); + if(sdmmc_read16(REG_SDSTATUS0) & TMIO_STAT0_CMDRESPEND) { + ctx->error |= 0x1; + } + if(status0 & TMIO_STAT0_DATAEND) { + ctx->error |= 0x2; + } + + if((status0 & flags) == flags) + break; + } + } + ctx->stat0 = sdmmc_read16(REG_SDSTATUS0); + ctx->stat1 = sdmmc_read16(REG_SDSTATUS1); + sdmmc_write16(REG_SDSTATUS0,0); + sdmmc_write16(REG_SDSTATUS1,0); + + if(getSDRESP != 0) { + ctx->ret[0] = sdmmc_read16(REG_SDRESP0) | (sdmmc_read16(REG_SDRESP1) << 16); + ctx->ret[1] = sdmmc_read16(REG_SDRESP2) | (sdmmc_read16(REG_SDRESP3) << 16); + ctx->ret[2] = sdmmc_read16(REG_SDRESP4) | (sdmmc_read16(REG_SDRESP5) << 16); + ctx->ret[3] = sdmmc_read16(REG_SDRESP6) | (sdmmc_read16(REG_SDRESP7) << 16); + } +} + + +//--------------------------------------------------------------------------------- +int sdmmc_cardinserted() { +//--------------------------------------------------------------------------------- + return 1; //sdmmc_cardready; +} + +//--------------------------------------------------------------------------------- +void sdmmc_controller_init(bool force) { +//--------------------------------------------------------------------------------- + deviceSD.isSDHC = 0; + deviceSD.SDOPT = 0; + deviceSD.res = 0; + deviceSD.initarg = 0; + deviceSD.clk = 0x80; + deviceSD.devicenumber = 0; + + *(vu16*)(SDMMC_BASE + REG_SDDATACTL32) &= 0xF7FFu; + *(vu16*)(SDMMC_BASE + REG_SDDATACTL32) &= 0xEFFFu; + *(vu16*)(SDMMC_BASE + REG_SDDATACTL32) |= 0x402u; + *(vu16*)(SDMMC_BASE + REG_SDDATACTL) = (*(vu16*)(SDMMC_BASE + REG_SDDATACTL) & 0xFFDD) | 2; + *(vu16*)(SDMMC_BASE + REG_SDDATACTL32) &= 0xFFFFu; + *(vu16*)(SDMMC_BASE + REG_SDDATACTL) &= 0xFFDFu; + *(vu16*)(SDMMC_BASE + REG_SDBLKLEN32) = 512; + *(vu16*)(SDMMC_BASE + REG_SDBLKCOUNT32) = 1; + *(vu16*)(SDMMC_BASE + REG_SDRESET) &= 0xFFFEu; + *(vu16*)(SDMMC_BASE + REG_SDRESET) |= 1u; + *(vu16*)(SDMMC_BASE + REG_SDIRMASK0) |= TMIO_MASK_ALL; + *(vu16*)(SDMMC_BASE + REG_SDIRMASK1) |= TMIO_MASK_ALL>>16; + *(vu16*)(SDMMC_BASE + 0x0fc) |= 0xDBu; //SDCTL_RESERVED7 + *(vu16*)(SDMMC_BASE + 0x0fe) |= 0xDBu; //SDCTL_RESERVED8 + *(vu16*)(SDMMC_BASE + REG_SDPORTSEL) &= 0xFFFCu; + *(vu16*)(SDMMC_BASE + REG_SDCLKCTL) = 0x20; + *(vu16*)(SDMMC_BASE + REG_SDOPT) = 0x40EE; + *(vu16*)(SDMMC_BASE + REG_SDPORTSEL) &= 0xFFFCu; + *(vu16*)(SDMMC_BASE + REG_SDBLKLEN) = 512; + *(vu16*)(SDMMC_BASE + REG_SDSTOP) = 0; + +} + +//--------------------------------------------------------------------------------- +int sdmmc_sdcard_init() { +//--------------------------------------------------------------------------------- + setTarget(&deviceSD); + swiDelay(0xF000); + sdmmc_send_command(&deviceSD,0,0); + sdmmc_send_command(&deviceSD,0x10408,0x1AA); + u32 temp = (deviceSD.error & 0x1) << 0x1E; + + u32 temp2 = 0; + do { + do { + sdmmc_send_command(&deviceSD,0x10437,deviceSD.initarg << 0x10); + sdmmc_send_command(&deviceSD,0x10769,0x00FF8000 | temp); + temp2 = 1; + } while ( !(deviceSD.error & 1) ); + + } while((deviceSD.ret[0] & 0x80000000) == 0); + + if(!((deviceSD.ret[0] >> 30) & 1) || !temp) + temp2 = 0; + + deviceSD.isSDHC = temp2; + + sdmmc_send_command(&deviceSD,0x10602,0); + if (deviceSD.error & 0x4) return -1; + + sdmmc_send_command(&deviceSD,0x10403,0); + if (deviceSD.error & 0x4) return -1; + deviceSD.initarg = deviceSD.ret[0] >> 0x10; + + sdmmc_send_command(&deviceSD,0x10609,deviceSD.initarg << 0x10); + if (deviceSD.error & 0x4) return -1; + + deviceSD.clk = 1; + setckl(1); + + sdmmc_send_command(&deviceSD,0x10507,deviceSD.initarg << 0x10); + if (deviceSD.error & 0x4) return -1; + + sdmmc_send_command(&deviceSD,0x10437,deviceSD.initarg << 0x10); + if (deviceSD.error & 0x4) return -1; + + sdmmc_send_command(&deviceSD,0x1076A,0x0); + if (deviceSD.error & 0x4) return -1; + + sdmmc_send_command(&deviceSD,0x10437,deviceSD.initarg << 0x10); + if (deviceSD.error & 0x4) return -1; + + deviceSD.SDOPT = 1; + sdmmc_send_command(&deviceSD,0x10446,0x2); + if (deviceSD.error & 0x4) return -1; + + sdmmc_send_command(&deviceSD,0x1040D,deviceSD.initarg << 0x10); + if (deviceSD.error & 0x4) return -1; + + sdmmc_send_command(&deviceSD,0x10410,0x200); + if (deviceSD.error & 0x4) return -1; + deviceSD.clk |= 0x200; + + return 0; + +} + +//--------------------------------------------------------------------------------- +int sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, void *out) { +//--------------------------------------------------------------------------------- + if (deviceSD.isSDHC == 0) + sector_no <<= 9; + setTarget(&deviceSD); + sdmmc_write16(REG_SDSTOP,0x100); + + sdmmc_write16(REG_SDBLKCOUNT32,numsectors); + sdmmc_write16(REG_SDBLKLEN32,0x200); + + sdmmc_write16(REG_SDBLKCOUNT,numsectors); + deviceSD.data = out; + deviceSD.size = numsectors << 9; + sdmmc_send_command(&deviceSD,0x33C12,sector_no); + return geterror(&deviceSD); +} +#endif \ No newline at end of file diff --git a/ndsbootloader/source/sdmmc.h b/ndsbootloader/source/sdmmc.h new file mode 100644 index 0000000..3313be1 --- /dev/null +++ b/ndsbootloader/source/sdmmc.h @@ -0,0 +1,194 @@ +#ifndef __SDMMC_H__ +#define __SDMMC_H__ + +#include + +#define DATA32_SUPPORT + +#define SDMMC_BASE 0x04004800 + + +#define REG_SDCMD 0x00 +#define REG_SDPORTSEL 0x02 +#define REG_SDCMDARG 0x04 +#define REG_SDCMDARG0 0x04 +#define REG_SDCMDARG1 0x06 +#define REG_SDSTOP 0x08 +#define REG_SDRESP 0x0c +#define REG_SDBLKCOUNT 0x0a + +#define REG_SDRESP0 0x0c +#define REG_SDRESP1 0x0e +#define REG_SDRESP2 0x10 +#define REG_SDRESP3 0x12 +#define REG_SDRESP4 0x14 +#define REG_SDRESP5 0x16 +#define REG_SDRESP6 0x18 +#define REG_SDRESP7 0x1a + +#define REG_SDSTATUS0 0x1c +#define REG_SDSTATUS1 0x1e + +#define REG_SDIRMASK0 0x20 +#define REG_SDIRMASK1 0x22 +#define REG_SDCLKCTL 0x24 + +#define REG_SDBLKLEN 0x26 +#define REG_SDOPT 0x28 +#define REG_SDFIFO 0x30 + +#define REG_SDDATACTL 0xd8 +#define REG_SDRESET 0xe0 +#define REG_SDPROTECTED 0xf6 //bit 0 determines if sd is protected or not? + +#define REG_SDDATACTL32 0x100 +#define REG_SDBLKLEN32 0x104 +#define REG_SDBLKCOUNT32 0x108 +#define REG_SDFIFO32 0x10C + +#define REG_CLK_AND_WAIT_CTL 0x138 +#define REG_RESET_SDIO 0x1e0 +//The below defines are from linux kernel drivers/mmc tmio_mmc.h. +/* Definitions for values the CTRL_STATUS register can take. */ +#define TMIO_STAT0_CMDRESPEND 0x0001 +#define TMIO_STAT0_DATAEND 0x0004 +#define TMIO_STAT0_CARD_REMOVE 0x0008 +#define TMIO_STAT0_CARD_INSERT 0x0010 +#define TMIO_STAT0_SIGSTATE 0x0020 +#define TMIO_STAT0_WRPROTECT 0x0080 +#define TMIO_STAT0_CARD_REMOVE_A 0x0100 +#define TMIO_STAT0_CARD_INSERT_A 0x0200 +#define TMIO_STAT0_SIGSTATE_A 0x0400 + +#define TMIO_STAT1_CMD_IDX_ERR 0x0001 +#define TMIO_STAT1_CRCFAIL 0x0002 +#define TMIO_STAT1_STOPBIT_ERR 0x0004 +#define TMIO_STAT1_DATATIMEOUT 0x0008 +#define TMIO_STAT1_RXOVERFLOW 0x0010 +#define TMIO_STAT1_TXUNDERRUN 0x0020 +#define TMIO_STAT1_CMDTIMEOUT 0x0040 +#define TMIO_STAT1_RXRDY 0x0100 +#define TMIO_STAT1_TXRQ 0x0200 +#define TMIO_STAT1_ILL_FUNC 0x2000 +#define TMIO_STAT1_CMD_BUSY 0x4000 +#define TMIO_STAT1_ILL_ACCESS 0x8000 + +#define SDMC_NORMAL 0x00000000 +#define SDMC_ERR_COMMAND 0x00000001 +#define SDMC_ERR_CRC 0x00000002 +#define SDMC_ERR_END 0x00000004 +#define SDMC_ERR_TIMEOUT 0x00000008 +#define SDMC_ERR_FIFO_OVF 0x00000010 +#define SDMC_ERR_FIFO_UDF 0x00000020 +#define SDMC_ERR_WP 0x00000040 +#define SDMC_ERR_ABORT 0x00000080 +#define SDMC_ERR_FPGA_TIMEOUT 0x00000100 +#define SDMC_ERR_PARAM 0x00000200 +#define SDMC_ERR_R1_STATUS 0x00000800 +#define SDMC_ERR_NUM_WR_SECTORS 0x00001000 +#define SDMC_ERR_RESET 0x00002000 +#define SDMC_ERR_ILA 0x00004000 +#define SDMC_ERR_INFO_DETECT 0x00008000 + +#define SDMC_STAT_ERR_UNKNOWN 0x00080000 +#define SDMC_STAT_ERR_CC 0x00100000 +#define SDMC_STAT_ERR_ECC_FAILED 0x00200000 +#define SDMC_STAT_ERR_CRC 0x00800000 +#define SDMC_STAT_ERR_OTHER 0xf9c70008 + +#define TMIO_MASK_ALL 0x837f031d + +#define TMIO_MASK_GW (TMIO_STAT1_ILL_ACCESS | TMIO_STAT1_CMDTIMEOUT | TMIO_STAT1_TXUNDERRUN | TMIO_STAT1_RXOVERFLOW | \ + TMIO_STAT1_DATATIMEOUT | TMIO_STAT1_STOPBIT_ERR | TMIO_STAT1_CRCFAIL | TMIO_STAT1_CMD_IDX_ERR) + +#define TMIO_MASK_READOP (TMIO_STAT1_RXRDY | TMIO_STAT1_DATAEND) +#define TMIO_MASK_WRITEOP (TMIO_STAT1_TXRQ | TMIO_STAT1_DATAEND) + +typedef struct mmcdevice { + u8* data; + u32 size; + u32 error; + u16 stat0; + u16 stat1; + u32 ret[4]; + u32 initarg; + u32 isSDHC; + u32 clk; + u32 SDOPT; + u32 devicenumber; + u32 total_size; //size in sectors of the device + u32 res; +} mmcdevice; + +enum { + MMC_DEVICE_SDCARD, + MMC_DEVICE_NAND, +}; + +void sdmmc_controller_init(bool force_init); +void sdmmc_initirq(); +int sdmmc_cardinserted(); + +int sdmmc_sdcard_init(); +int sdmmc_nand_init(); +void sdmmc_get_cid(int devicenumber, u32 *cid); + +static inline void sdmmc_nand_cid( u32 *cid) { + sdmmc_get_cid(MMC_DEVICE_NAND,cid); +} + +static inline void sdmmc_sdcard_cid( u32 *cid) { + sdmmc_get_cid(MMC_DEVICE_SDCARD,cid); +} + +int sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, void *out); +int sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, void *in); +int sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, void *out); +int sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, void *in); + +extern u32 sdmmc_cid[]; +extern int sdmmc_curdevice; + +//--------------------------------------------------------------------------------- +static inline u16 sdmmc_read16(u16 reg) { +//--------------------------------------------------------------------------------- + return *(vu16*)(SDMMC_BASE + reg); +} + +//--------------------------------------------------------------------------------- +static inline void sdmmc_write16(u16 reg, u16 val) { +//--------------------------------------------------------------------------------- + *(vu16*)(SDMMC_BASE + reg) = val; +} + +//--------------------------------------------------------------------------------- +static inline u32 sdmmc_read32(u16 reg) { +//--------------------------------------------------------------------------------- + return *(vu32*)(SDMMC_BASE + reg); +} + +//--------------------------------------------------------------------------------- +static inline void sdmmc_write32(u16 reg, u32 val) { +//--------------------------------------------------------------------------------- + *(vu32*)(SDMMC_BASE + reg) = val; +} + +//--------------------------------------------------------------------------------- +static inline void sdmmc_mask16(u16 reg, u16 clear, u16 set) { +//--------------------------------------------------------------------------------- + u16 val = sdmmc_read16(reg); + val &= ~clear; + val |= set; + sdmmc_write16(reg, val); +} + + +//--------------------------------------------------------------------------------- +static inline void setckl(u32 data) { +//--------------------------------------------------------------------------------- + sdmmc_mask16(REG_SDCLKCTL, 0x100, 0); + sdmmc_mask16(REG_SDCLKCTL, 0x2FF, data & 0x2FF); + sdmmc_mask16(REG_SDCLKCTL, 0x0, 0x100); +} + +#endif