Skip to content

Commit

Permalink
Run DSiWare with SDMMC flag and redirect SD R/W to flashcard/DLDI
Browse files Browse the repository at this point in the history
Does not apply to B4DS mode and/or when running from CycloDS iEvolution
  • Loading branch information
RocketRobz committed Dec 4, 2024
1 parent 0ebe472 commit 00465a3
Show file tree
Hide file tree
Showing 16 changed files with 896 additions and 699 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ An alternative forwarder generator for 3DS users. YANBF forwarders are 3DS-mode
- [shutterbug2000](https://github.com/shutterbug2000): SDK5 support, help with DSi mode support, and some other implemented stuff
- [ahezard](https://github.com/ahezard): Starting the project, former lead developer
- [Pk11](https://github.com/Epicpkmn11): In-game menu, screenshot taking, manual loading, and translation management
- [Gericom](https://github.com/Gericom): Improving B4DS compatibility, parts of libtwl code used
- [Gericom](https://github.com/Gericom): Improving B4DS compatibility, parts of libtwl code used, and SD -> flashcard R/W patch for DSiWare

## Other
- [devkitPro](https://devkitpro.org): devkitARM and libnds
Expand Down
28 changes: 13 additions & 15 deletions retail/arm9/source/conf_sd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1432,9 +1432,9 @@ int loadFromSD(configuration* conf, const char *bootstrapPath) {
fclose(cebin);
}

if (isDSiMode() && unitCode > 0 && !conf->gameOnFlashcard) {
const bool sdNandFound = conf->sdNand && (access("sd:/shared1", F_OK) == 0);
const bool sdPhotoFound = conf->sdNand && (access("sd:/photo", F_OK) == 0);
if (isDSiMode() && unitCode > 0 && conf->sdFound) {
const bool sdNandFound = conf->sdNand && (access(conf->gameOnFlashcard ? "fat:/shared1" : "sd:/shared1", F_OK) == 0);
const bool sdPhotoFound = conf->sdNand && (access(conf->gameOnFlashcard ? "fat:/photo" : "sd:/photo", F_OK) == 0);

// Load device list
addTwlDevice(0, (u8)(sdNandFound ? 0 : 0x81), 0x06, "nand", "/");
Expand All @@ -1456,36 +1456,34 @@ int loadFromSD(configuration* conf, const char *bootstrapPath) {
}
}
addTwlDevice(0, (u8)((sdNandFound || sdPhotoFound) ? 0x10 : 0x31), 0x06, "photo", ((sdNandFound || sdPhotoFound) ? "sdmc:/photo" : "nand2:/photo"));
if (!conf->saveOnFlashcard) {
if (conf->saveOnFlashcard == conf->gameOnFlashcard) {
if (strlen(conf->prvPath) < 62 && prvSize > 0) {
if (strncasecmp(conf->prvPath, "sd:", 3) != 0) {
if (strncasecmp(conf->prvPath, "sd:", 3) != 0 && strncasecmp(conf->prvPath, "fat:", 4) != 0) {
const bool isSdmc = (strncasecmp(conf->prvPath, "sdmc:", 5) == 0);
addTwlDevice(0, (u8)((sdNandFound || isSdmc) ? 0x08 : 0x09), 0x06, "dataPrv", conf->prvPath);
} else {
char twlPath[64];
sprintf(twlPath, "sdmc%s", conf->prvPath+2);
sprintf(twlPath, "sdmc%s", conf->prvPath+(conf->saveOnFlashcard ? 3 : 2));

addTwlDevice(0, 0x08, 0x06, "dataPrv", twlPath);
}
}
if (strlen(conf->savPath) < 62 && pubSize > 0) {
if (strncasecmp(conf->savPath, "sd:", 3) != 0) {
if (strncasecmp(conf->savPath, "sd:", 3) != 0 && strncasecmp(conf->savPath, "fat:", 4) != 0) {
const bool isSdmc = (strncasecmp(conf->savPath, "sdmc:", 5) == 0);
addTwlDevice(0, (u8)((sdNandFound || isSdmc) ? 0x08 : 0x09), 0x06, "dataPub", conf->savPath);
} else {
char twlPath[64];
sprintf(twlPath, "sdmc%s", conf->savPath+2);
sprintf(twlPath, "sdmc%s", conf->savPath+(conf->saveOnFlashcard ? 3 : 2));

addTwlDevice(0, 0x08, 0x06, "dataPub", twlPath);
}
}
}

if (!conf->gameOnFlashcard && strlen(conf->appPath) < 62) {
char sdmcText[4] = {'s','d','m','c'};
tonccpy((char*)0x02EFF3C2, conf->appPath, strlen(conf->appPath));
tonccpy((char*)0x02EFF3C0, sdmcText, 4);
}
char sdmcText[4] = {'s','d','m','c'};
tonccpy((char*)(conf->gameOnFlashcard ? 0x02EFF3C1 : 0x02EFF3C2), conf->appPath, strlen(conf->appPath));
tonccpy((char*)0x02EFF3C0, sdmcText, 4);
}

if (REG_SCFG_EXT7 == 0) {
Expand Down Expand Up @@ -1514,7 +1512,7 @@ int loadFromSD(configuration* conf, const char *bootstrapPath) {
conf->valueBits2 |= BIT(6);
}

if (conf->gameOnFlashcard || !conf->isDSiWare) {
if (!conf->isDSiWare || !conf->sdFound) {
// Load external cheat engine binary
loadCardEngineBinary("nitro:/cardenginei_arm7_cheat.bin", (u8*)CHEAT_ENGINE_BUFFERED_LOCATION);

Expand Down Expand Up @@ -2471,7 +2469,7 @@ int loadFromSD(configuration* conf, const char *bootstrapPath) {
// Create AP-fixed overlay binary
createApFixOverlayBin(conf);

if (conf->gameOnFlashcard || !conf->isDSiWare) {
if ((!dsiFeatures() || conf->b4dsMode) || !conf->sdFound || !conf->isDSiWare) {
// Update modified date
FILE *savFile = fopen(conf->savPath, "r+");
if (savFile) {
Expand Down
2 changes: 1 addition & 1 deletion retail/bootloader/include/patch.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ u32* getOffsetFromBL(u32* blOffset);
u32* getOffsetFromBLX(u32* blxOffset);
const u16* generateA7InstrThumb(int arg1, int arg2);
void setBLThumb(int arg1, int arg2);
u16* getOffsetFromBLThumb(u16* blOffset);
u16* getOffsetFromBLThumb(const u16* blOffset);
void codeCopy(u32* dst, u32* src, u32 len);
void patchBinary(cardengineArm9* ce9, const tNDSHeader* ndsHeader, module_params_t* moduleParams);
u32 patchCardNdsArm9(
Expand Down
11 changes: 7 additions & 4 deletions retail/bootloader/source/arm7/patch_arm7.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,13 @@ void setBLThumb(int arg1, int arg2) {
*(u16*)(arg1 + 2) = instrs[1];
}

u16* getOffsetFromBLThumb(u16* blOffset) {
s16 codeOffset = blOffset[1];

return (u16*)((u32)blOffset + (codeOffset*2) + 4);
u16* getOffsetFromBLThumb(const u16* blOffset) {
const u32* instructionPointer = (u32*)blOffset;
u32 blInstruction1 = ((u16*)instructionPointer)[0];
u32 blInstruction2 = ((u16*)instructionPointer)[1];
u32 res = (u32)instructionPointer + 5 + ((int)((((blInstruction1 & 0x7FF) << 11) | (blInstruction2 & 0x7FF)) << 10) >> 9);
res--;
return (u16*)res;
}

static bool patchWramClear(const tNDSHeader* ndsHeader) {
Expand Down
1 change: 1 addition & 0 deletions retail/bootloaderi/include/find.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ u32* findCardCheckPullOutOffset(const tNDSHeader* ndsHeader, const module_params
u32* findCardIrqEnableOffset(const tNDSHeader* ndsHeader, const module_params_t* moduleParams);
//u32* findA7iStartOffset(void);
u32* findSdCardResetOffset(const tNDSHeader* ndsHeader, const module_params_t* moduleParams);
u32* findSdCardFuncsOffset(const tNDSHeader* ndsHeader);
u32* findAutoPowerOffOffset(const tNDSHeader* ndsHeader);

#endif // FIND_H
5 changes: 3 additions & 2 deletions retail/bootloaderi/include/patch.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@

//extern bool cardReadFound; // patch_arm9.c

#define patchOffsetCacheFileVersion 109 // Change when new functions are being patched, some offsets removed,
#define patchOffsetCacheFileVersion 110 // Change when new functions are being patched, some offsets removed,
// the offset order changed, and/or the function signatures changed (not added)

typedef struct patchOffsetCacheContents {
Expand Down Expand Up @@ -141,6 +141,7 @@ typedef struct patchOffsetCacheContents {
u32* cardCheckPullOutOffset;
u32 cardCheckPullOutChecked;
u32* sdCardResetOffset;
u32* sdCardFuncsOffset;
u32* autoPowerOffOffset;
u32* a7IrqHandlerOffset;
u32* a7IrqHandlerWordsOffset;
Expand All @@ -166,7 +167,7 @@ void setBLX(int arg1, int arg2);
u32* getOffsetFromBL(u32* blOffset);
u32* getOffsetFromBLX(u32* blxOffset);
const u16* generateA7InstrThumb(int arg1, int arg2);
u16* getOffsetFromBLThumb(u16* blOffset);
u16* getOffsetFromBLThumb(const u16* blOffset);
void setBLThumb(int arg1, int arg2);
void codeCopy(u32* dst, u32* src, u32 len);
void dsiWarePatch(cardengineArm9* ce9, const tNDSHeader* ndsHeader);
Expand Down
28 changes: 28 additions & 0 deletions retail/bootloaderi/source/arm7/find_arm7.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,10 @@ static const u16 sdCardResetSignatureThumbType4[7] = {0xF7FF, 0xFDB2, 0xF7FF, 0x
static const u16 sdCardResetSignatureThumbType5[7] = {0xF7FF, 0xFDC1, 0xF7FF, 0xFF5F, 0xF000, 0xF849, 0x1C05};
static const u16 sdCardResetSignatureThumbType6[7] = {0xF7FF, 0xFDCE, 0xF7FF, 0xFF68, 0xF000, 0xF85A, 0x1C05};

// SD card functions (SDK 5)
static const u32 sdCardFuncsSignature[4] = {0xE92D4018, 0xE24DDF5D, 0xE24DDB01, 0xE59FE050};
static const u32 sdCardFuncsSignatureThumb[4] = {0xB0FFB518, 0xB0DFB0FF, 0x4A0E490D, 0x64CA4469};

// Auto power-off (SDK 5)
static const u32 autoPowerOffSignature[4] = {0xE92D41F0, 0xE59F4070, 0xE1A08000, 0xE1A07001};
static const u16 autoPowerOffSignatureThumb[6] = {0xB5F8, 0x1C05, 0x1C0E, 0x2400, 0x27C5, 0xE019};
Expand Down Expand Up @@ -1543,6 +1547,30 @@ u32* findSdCardResetOffset(const tNDSHeader* ndsHeader, const module_params_t* m
return sdCardResetOffset;
}

u32* findSdCardFuncsOffset(const tNDSHeader* ndsHeader) {
dbg_printf("findSdCardFuncsOffset:\n");

u32* offset = findOffset(
__DSiHeader->arm7idestination, newArm7ibinarySize,
sdCardFuncsSignature, 4
);
if (!offset) {
offset = (u32*)findOffset(
__DSiHeader->arm7idestination, newArm7ibinarySize,
sdCardFuncsSignatureThumb, 4
);
}

if (offset) {
dbg_printf("SD Card functions found\n");
} else {
dbg_printf("SD Card functions not found\n");
}

dbg_printf("\n");
return offset;
}

u32* findAutoPowerOffOffset(const tNDSHeader* ndsHeader) {
dbg_printf("findAutoPowerOffOffset:\n");

Expand Down
28 changes: 21 additions & 7 deletions retail/bootloaderi/source/arm7/main.arm7.c
Original file line number Diff line number Diff line change
Expand Up @@ -1211,7 +1211,7 @@ static void startBinary_ARM7(void) {

static void setMemoryAddress(const tNDSHeader* ndsHeader, const module_params_t* moduleParams) {
if (ROMsupportsDsiMode(ndsHeader) && dsiModeConfirmed) {
if (isDSiWare && !(REG_SCFG_ROM & BIT(9))) {
if (isDSiWare && dsiSD && !(REG_SCFG_ROM & BIT(9))) {
u32* deviceListAddr = (u32*)(*(u32*)0x02FFE1D4);

dbg_printf("Device list address: ");
Expand Down Expand Up @@ -1382,7 +1382,7 @@ static void setMemoryAddress(const tNDSHeader* ndsHeader, const module_params_t*
toncset((u32*)0x02FFFD60, 0, 0xA0);
}

if (!gameOnFlashcard && isDSiWare) {
if (isDSiWare && dsiSD && !(REG_SCFG_ROM & BIT(9))) {
*(u16*)(0x02FFFC40) = 3; // Boot Indicator (NAND/SD)
return;
}
Expand Down Expand Up @@ -1571,7 +1571,7 @@ int arm7_main(void) {
dsiModeConfirmed = dsiMode && ROMsupportsDsiMode(&dsiHeaderTemp.ndshdr);
}
const char* romTid = getRomTid(&dsiHeaderTemp.ndshdr);
if (gameOnFlashcard || !isDSiWare) {
if (!isDSiWare || !dsiSD || (REG_SCFG_ROM & BIT(9))) {
extern u32 clusterCacheSize;
clusterCacheSize = 0x10000;
if (dsiModeConfirmed && ROMsupportsDsiMode(&dsiHeaderTemp.ndshdr)) {
Expand All @@ -1596,7 +1596,7 @@ int arm7_main(void) {
&& patchOffsetCache.type == 0) { // 0 = Regular, 1 = B4DS, 2 = HB
fileRead((char*)&patchOffsetCache, &patchOffsetCacheFile, 0, sizeof(patchOffsetCacheContents));
} else {
if (srlAddr == 0 && !isDSiWare) pleaseWaitOutput();
if (srlAddr == 0 && (!isDSiWare || !dsiSD || (REG_SCFG_ROM & BIT(9)))) pleaseWaitOutput();
patchOffsetCache.ver = patchOffsetCacheFileVersion;
patchOffsetCache.type = 0;
}
Expand Down Expand Up @@ -1642,7 +1642,7 @@ int arm7_main(void) {
*(u32*)0x02FFE1A0 = *(u32*)DONOR_ROM_MBK6_LOCATION;
*(u32*)0x02FFE1D4 = *(u32*)DONOR_ROM_DEVICE_LIST_LOCATION;
}
if (gameOnFlashcard || !isDSiWare) {
if (!isDSiWare || !dsiSD || (REG_SCFG_ROM & BIT(9))) {
/* if (consoleModel > 0) {
tonccpy((char*)0x0DF80000, (char*)0x02700000, 0x80000); // Move FAT table cache to debug RAM
romFile->fatTableCache = (u32*)((u32)romFile->fatTableCache+0xB880000);
Expand Down Expand Up @@ -1732,7 +1732,7 @@ int arm7_main(void) {
tonccpy(cheatEngineBuffer, (char*)CHEAT_ENGINE_BUFFERED_LOCATION, 0x400);
toncset((char*)CHEAT_ENGINE_BUFFERED_LOCATION, 0, 0x400);

if (!gameOnFlashcard && isDSiWare) {
if (isDSiWare && dsiSD && !(REG_SCFG_ROM & BIT(9))) {
extern void patchSharedFontPath(const cardengineArm9* ce9, const tNDSHeader* ndsHeader, const module_params_t* moduleParams, const ltd_module_params_t* ltdModuleParams);

const bool twlTouch = (cdcReadReg(CDC_SOUND, 0x22) == 0xF0 || i2cBricked);
Expand Down Expand Up @@ -1806,6 +1806,12 @@ int arm7_main(void) {
tonccpy((u32*)ce9Location, (u32*)CARDENGINEI_ARM9_BUFFERED_LOCATION, 0xC00);

tonccpy((u32*)ce7Location, (u32*)CARDENGINEI_ARM7_BUFFERED_LOCATION, 0x8400);
if (gameOnFlashcard || saveOnFlashcard) {
if (!dldiPatchBinary((data_t*)ce7Location, 0x8000, NULL)) {
dbg_printf("ce7 DLDI patch failed\n");
errorOutput();
}
}
cheatEngineOffset = ((ce7Location == CARDENGINEI_ARM7_DSIWARE_LOCATION3) ? CHEAT_ENGINE_DSIWARE_LOCATION3 : CHEAT_ENGINE_DSIWARE_LOCATION);
toncset((u32*)CARDENGINEI_ARM7_BUFFERED_LOCATION, 0, 0x8400);

Expand Down Expand Up @@ -1886,6 +1892,14 @@ int arm7_main(void) {
errorOutput();
}

if (gameOnFlashcard) {
extern bool patchSdCardFuncs(cardengineArm7* ce7, const tNDSHeader* ndsHeader);
if (!patchSdCardFuncs((cardengineArm7*)ce7Location, ndsHeader)) {
dbg_printf("ERR_LOAD_OTHR");
errorOutput();
}
}

extern void patchAutoPowerOff(const tNDSHeader* ndsHeader);
patchAutoPowerOff(ndsHeader);

Expand Down Expand Up @@ -2365,7 +2379,7 @@ int arm7_main(void) {
//fileWrite((char*)dsiHeaderTemp.arm9idestination, &ramDumpFile, 0, dsiHeaderTemp.arm9ibinarySize); // Dump (decrypted?) arm9 binary
}

if (ROMsupportsDsiMode(ndsHeader) && isDSiWare && !gameOnFlashcard && !(REG_SCFG_ROM & BIT(9))) {
if (ROMsupportsDsiMode(ndsHeader) && isDSiWare && dsiSD && !(REG_SCFG_ROM & BIT(9))) {
*(vu32*)0x400481C = 0; // Reset SD IRQ stat register
*(vu32*)0x4004820 = 0x8B7F0305; // Set SD IRQ mask register (Data won't read without the correct bytes!)
} /*else if (!isDSiWare) {
Expand Down
42 changes: 38 additions & 4 deletions retail/bootloaderi/source/arm7/patch_arm7.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,13 @@ void setBLThumb(int arg1, int arg2) {
*(u16*)(arg1 + 2) = instrs[1];
}

u16* getOffsetFromBLThumb(u16* blOffset) {
s16 codeOffset = blOffset[1];

return (u16*)((u32)blOffset + (codeOffset*2) + 4);
u16* getOffsetFromBLThumb(const u16* blOffset) {
const u32* instructionPointer = (u32*)blOffset;
u32 blInstruction1 = ((u16*)instructionPointer)[0];
u32 blInstruction2 = ((u16*)instructionPointer)[1];
u32 res = (u32)instructionPointer + 5 + ((int)((((blInstruction1 & 0x7FF) << 11) | (blInstruction2 & 0x7FF)) << 10) >> 9);
res--;
return (u16*)res;
}

u32 vAddrOfRelocSrc = 0;
Expand Down Expand Up @@ -583,6 +586,37 @@ static void patchSdCardReset(const tNDSHeader* ndsHeader, const module_params_t*
}
}

bool patchSdCardFuncs(cardengineArm7* ce7, const tNDSHeader* ndsHeader) {
u32* offset = patchOffsetCache.sdCardFuncsOffset;
if (!patchOffsetCache.sdCardFuncsOffset) {
offset = findSdCardFuncsOffset(ndsHeader);
if (offset) {
patchOffsetCache.sdCardFuncsOffset = offset;
}
}

if (!offset) {
return false;
}

u16* offsetThumb = (u16*)offset;
if (*offsetThumb == 0xB518) {
ce7->romPartLocation = (u32)getOffsetFromBLThumb((u16*)((u8*)offset - 0x20)); // getDriveStructAddr
ce7->romPartLocation++;
*(u32*)((u8*)offset + 0x44) = ce7->patches->arm7Functions->eepromProtect; // __patch_dsisdredirect_io
*(u32*)((u8*)offset + 0x48) = ce7->patches->arm7Functions->eepromPageErase; // __patch_dsisdredirect_control
} else {
ce7->romPartLocation = (u32)getOffsetFromBL((u32*)((u8*)offset - 0x20)); // getDriveStructAddr
*(u32*)((u8*)offset + 0x64) = ce7->patches->arm7Functions->eepromProtect; // __patch_dsisdredirect_io
*(u32*)((u8*)offset + 0x68) = ce7->patches->arm7Functions->eepromPageErase; // __patch_dsisdredirect_control
}

dbg_printf("sdCardFuncs location : ");
dbg_hexa((u32)offset);
dbg_printf("\n\n");
return true;
}

void patchAutoPowerOff(const tNDSHeader* ndsHeader) {
if (!i2cBricked || ndsHeader->unitCode == 0 || !dsiModeConfirmed) return;

Expand Down
2 changes: 1 addition & 1 deletion retail/bootloaderi/source/arm7/patch_arm9.c
Original file line number Diff line number Diff line change
Expand Up @@ -1638,7 +1638,7 @@ void patchSharedFontPath(const cardengineArm9* ce9, const tNDSHeader* ndsHeader,
dbg_hexa((u32)offset);
dbg_printf("\n\n");

if (gameOnFlashcard) {
if (REG_SCFG_ROM & BIT(9)) {
extern u32 iUncompressedSizei;

const u32* dsiSaveOpen = ce9->patches->dsiSaveOpen;
Expand Down
Loading

0 comments on commit 00465a3

Please sign in to comment.