diff --git a/arm9/source/hardware.cpp b/arm9/source/hardware.cpp index 06db229..fa67bee 100644 --- a/arm9/source/hardware.cpp +++ b/arm9/source/hardware.cpp @@ -172,8 +172,10 @@ u32 hwDetect() // the same microSD card between Slot 1 and Slot 2, this should be the safest mode. // (If you know a smarter way of doing this, feel free to commit a patch!) // - if (slot2) - return 4; + // EDIT: and we can't test this here, since the ini file has not been parsed yet! + // + //if (slot2) + //return 4; // Try to identify download play mode. This also introduces various complications: // - The latest libnds versions include code for the SD-slot on the DSi. It does not work @@ -464,6 +466,126 @@ void hwErase() auxspi_erase(ir); } +// -------------------------------------------------------- +void hwBackupSlot2() +{ + u32 size_blocks = 0; + + swap_cart(); + displayPrintUpper(); + + bool ir = (slot_1_type == 1) ? true : false; + uint32 size = auxspi_save_size_log_2(ir); + uint8 type = auxspi_save_type(ir); + + // just select a filename, no extra work required! + char path[256]; + char fname[256] = ""; + fileSelect("/", path, fname, 0, true, false); + + // look for an unused filename + if (!fname[0]) { + sNDSHeader nds; + cardReadHeader((u8*)&nds); + uint32 cnt = 0; + sprintf(fname, "/%.12s.%i.sav", nds.gameTitle, cnt); + displayMessage2F(STR_HW_SEEK_UNUSED_FNAME, fname); + while (fileExists(fname)) { + if (cnt < 65536) + cnt++; + else { + displayWarning2F(STR_ERR_NO_FNAME); + while(1); + } + sprintf(fname, "%.12s.%i.sav", nds.gameTitle, cnt); + } + } + char fullpath[256]; + sprintf(fullpath, "%s/%s", path, fname); + displayMessage2F(STR_HW_WRITE_FILE, fullpath); + + FILE *file = fopen(fullpath, "wb"); + if (size < 8) + size_blocks = 1; + else + size_blocks = 1 << (size - 8); + // Slot 2 DLDI drivers don't seem to support writing big blocks! + u32 LEN = min(1 << size, 0x100); + for (u32 i = 0; i < size_blocks; i++) { + displayProgressBar(i+1, size_blocks); + auxspi_read_data(i << 8, data, LEN, type, ir); + fwrite(data, 1, LEN, file); + } + fclose(file); + + displayProgressBar(0,0); + displayMessageF(STR_EMPTY); +} + +void hwRestoreSlot2() +{ + // First, swap in a new game + swap_cart(); + bool ir = (slot_1_type == 1) ? true : false; + uint32 size = auxspi_save_size_log_2(ir); + uint8 type = auxspi_save_type(ir); + displayPrintUpper(); + + // second, select a save file + char path[256]; + char fname[256]; + memset(fname, 0, 256); + displayMessageF(STR_HW_SELECT_FILE); // lower screen is used for file browser + fileSelect("/", path, fname, 0, false, false); + char msg[256]; + // This does not have to be translated. + // FIXME: make this more meaningful! + sprintf(msg, "%s/%s", path, fname); + + FILE *file = fopen(msg, "rb"); + if (!file) { + iprintf("Error!"); + while (1); + } + + // 2a, format game if required + if (type == 3) { + displayMessage2F(STR_HW_FORMAT_GAME); + auxspi_erase(ir); + } + + // and third, write save + displayMessage2F(STR_HW_WRITE_GAME); + u32 LEN = 0, num_blocks = 0, shift = 0; + switch (type) { + case 1: + shift = 4; // 16 bytes + break; + case 2: + shift = 5; // 32 bytes + break; + case 3: + shift = 8; // 256 bytes + break; + default: + return; + } + LEN = 1 << shift; + num_blocks = 1 << (size - shift); + + for (unsigned int i = 0; i < num_blocks; i++) { + if (i % (num_blocks >> 6) == 0) + displayProgressBar(i+1, num_blocks); + fread(data, 1, LEN, file); + sysSetBusOwners(true, true); + auxspi_write_data(i << shift, data, LEN, type, ir); + } + fclose(file); + + displayProgressBar(0,0); + displayMessageF(STR_EMPTY); +} + // ------------------------------------------------------------ void hwBackupFTP(bool dlp) { diff --git a/arm9/source/hardware.h b/arm9/source/hardware.h index 5ade65b..4d4fcff 100644 --- a/arm9/source/hardware.h +++ b/arm9/source/hardware.h @@ -75,6 +75,9 @@ void hwBackupGBA(u8 type); void hwRestoreGBA(); void hwEraseGBA(); +void hwBackupSlot2(); +void hwRestoreSlot2(); + void hwFormatNor(uint32 page, uint32 count); uint32 hwGrab3in1(); diff --git a/arm9/source/main.cpp b/arm9/source/main.cpp index 87feeac..fe43cbf 100644 --- a/arm9/source/main.cpp +++ b/arm9/source/main.cpp @@ -101,8 +101,8 @@ void mode_slot2() displayPrintUpper(); displayPrintLower(); - displayWarning2F(STR_BOOT_MODE_UNSUPPORTED); - while(1); + //displayWarning2F(STR_BOOT_MODE_UNSUPPORTED); + //while(1); touchPosition touchXY; while(1) { @@ -111,20 +111,22 @@ void mode_slot2() // backup if ((touchXY.py > 8*0) && (touchXY.py < 8*8)) { - //displayPrintUpper(); - //hwBackupGBA(); + hwBackupSlot2(); + displayPrintLower(); } // restore if ((touchXY.py > 8*8) && (touchXY.py < 8*16)) { - //displayPrintUpper(); - //hwRestoreGBA(); + hwRestoreSlot2(); + displayPrintLower(); } // erase if ((touchXY.py > 8*16) && (touchXY.py < 8*24)) { - //displayPrintUpper(); - //hwEraseGBA(); + swap_cart(); + displayPrintUpper(); + hwErase(); + displayPrintLower(); } } } @@ -304,7 +306,8 @@ bool loadIniFile(char* path) ini = ini_open(inipath, "r", ""); } if (!ini) { - displayWarning2F(STR_BOOT_NO_INI); + //displayWarning2F(STR_BOOT_NO_INI); + iprintf("could not find ini file!"); while (1); } @@ -401,9 +404,11 @@ int main(int argc, char* argv[]) mode = hwDetect(); // Init DLDI (file system driver) + sysSetBusOwners(true, true); int fat = fatInitDefault(); if (fat == 0) { - displayWarning2F(STR_BOOT_DLDI_ERROR); + //displayWarning2F(STR_BOOT_DLDI_ERROR); + iprintf("DLDI error"); while (1); } @@ -416,6 +421,9 @@ int main(int argc, char* argv[]) loadIniFile(argv[0]); else loadIniFile(0); + + if (slot2) + mode = 4; // load strings // "txt" is used as a temp buffer for the language file name diff --git a/lang/template.ini b/lang/template.ini index 75c6120..c437d2b 100644 --- a/lang/template.ini +++ b/lang/template.ini @@ -8,9 +8,10 @@ # The strings "0" and "1" should never be used; they are internal stuff for "empty" and "untranslated" strings. # 2-5: These are boot-time messages. -2=DS savegame manager\nVersion 0.2.5 semi-stable\nBy Pokedoc +# You do not need to translate 2 and 3, they only appear *before* this file is read. Since the format is frozen, I leave these slots in. +#2=DS savegame manager\nVersion 0.2.5 semi-stable\nBy Pokedoc # This is an error message appearing when the ini file can not be found. -3=Unable to open ini file!\nPlease make sure that it is\n1. in this apps folder, or\n2. in the root folder\nIf 1. does not work, use 2. +#3=Unable to open ini file!\nPlease make sure that it is\n1. in this apps folder, or\n2. in the root folder\nIf 1. does not work, use 2. # Thsis is an error message called when the system tries to enter a mode that is not supported yet (e.g. DSi mode) 4=This mode is DISABLED.\nPlease restart the system. # This is an error called when the DLDI driver is not available. diff --git a/savegame_manager.odt b/savegame_manager.odt index 66260d4..f178cf5 100644 Binary files a/savegame_manager.odt and b/savegame_manager.odt differ