mirror of
https://github.com/rvtr/GodMode9i.git
synced 2025-11-02 00:11:07 -04:00
Add restoring DS saves on DS/DS Lite (#141)
This commit is contained in:
parent
4aa294b444
commit
ccf8d0200b
@ -469,7 +469,7 @@ bool driveRemoved(Drive drive) {
|
||||
case Drive::sdCard:
|
||||
return sdRemoved;
|
||||
case Drive::flashcard:
|
||||
return REG_SCFG_MC & BIT(0);
|
||||
return isDSiMode() ? REG_SCFG_MC & BIT(0) : !flashcardMounted;
|
||||
case Drive::ramDrive:
|
||||
return !ramdriveMounted;
|
||||
case Drive::nand:
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#include "font.h"
|
||||
#include "gba.h"
|
||||
#include "lzss.h"
|
||||
#include "main.h"
|
||||
#include "ndsheaderbanner.h"
|
||||
#include "read_card.h"
|
||||
#include "tonccpy.h"
|
||||
@ -151,7 +152,7 @@ void dumpFailMsg(std::string_view msg) {
|
||||
font->update(true);
|
||||
|
||||
scanKeys();
|
||||
pressed = keysDownRepeat();
|
||||
pressed = keysDown();
|
||||
swiWaitForVBlank();
|
||||
} while (!(pressed & KEY_A));
|
||||
}
|
||||
@ -574,8 +575,10 @@ void ndsCardSaveDump(const char* filename) {
|
||||
}
|
||||
|
||||
void ndsCardSaveRestore(const char *filename) {
|
||||
bool usingFlashcard = (io_dldi_data->ioInterface.features & FEATURE_SLOT_NDS) && flashcardMounted;
|
||||
|
||||
font->clear(false);
|
||||
font->print(0, 0, false, STR_RESTORE_SELECTED_SAVE_CARD);
|
||||
font->print(0, 0, false, (usingFlashcard ? STR_RESTORE_SELECTED_SAVE_CARD_FLASHCARD : STR_RESTORE_SELECTED_SAVE_CARD) + "\n\n" + STR_A_YES_B_NO);
|
||||
font->update(false);
|
||||
|
||||
// Power saving loop. Only poll the keys once per frame and sleep the CPU if there is nothing else to do
|
||||
@ -586,21 +589,16 @@ void ndsCardSaveRestore(const char *filename) {
|
||||
font->update(true);
|
||||
|
||||
scanKeys();
|
||||
pressed = keysDownRepeat();
|
||||
pressed = keysDown();
|
||||
swiWaitForVBlank();
|
||||
} while (!(pressed & (KEY_A | KEY_B)));
|
||||
|
||||
if(pressed & KEY_A) {
|
||||
int type = cardEepromGetTypeFixed();
|
||||
|
||||
if(type == -1) { // NAND
|
||||
if(type == -1 && !isRegularDS) { // NAND
|
||||
if (cardInit(&ndsCardHeader) != 0) {
|
||||
font->clear(false);
|
||||
font->print(0, 0, false, STR_UNABLE_TO_RESTORE_SAVE);
|
||||
font->update(false);
|
||||
for (int i = 0; i < 60 * 2; i++) {
|
||||
swiWaitForVBlank();
|
||||
}
|
||||
dumpFailMsg(STR_UNABLE_TO_RESTORE_SAVE);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -646,14 +644,47 @@ void ndsCardSaveRestore(const char *filename) {
|
||||
fclose(in);
|
||||
}
|
||||
} else { // SPI
|
||||
auxspi_extra card_type = auxspi_has_extra();
|
||||
bool auxspi = card_type == AUXSPI_INFRARED;
|
||||
FILE *in = fopen(filename, "rb");
|
||||
if(in) {
|
||||
unsigned char *buffer;
|
||||
unsigned char *buffer = nullptr;
|
||||
int size;
|
||||
int length;
|
||||
unsigned int num_blocks = 0, shift = 0, LEN = 0;
|
||||
|
||||
// Read save file length
|
||||
fseek(in, 0, SEEK_END);
|
||||
length = ftell(in);
|
||||
fseek(in, 0, SEEK_SET);
|
||||
|
||||
// If using flashcard, read the save and swap carts
|
||||
if(usingFlashcard) {
|
||||
buffer = new unsigned char[length];
|
||||
fread(buffer, 1, length, in);
|
||||
fclose(in);
|
||||
currentDrive = Drive::flashcard;
|
||||
chdir("fat:/");
|
||||
flashcardUnmount();
|
||||
|
||||
font->clear(false);
|
||||
font->print(0, 0, false, STR_EJECT_FLASHCARD_INSERT_GAME + "\n\n" + STR_A_CONTINUE);
|
||||
font->update(false);
|
||||
|
||||
// Power saving loop. Only poll the keys once per frame and sleep the CPU if there is nothing else to do
|
||||
do {
|
||||
// Print time
|
||||
font->print(-1, 0, true, RetTime(), Alignment::right, Palette::blackGreen);
|
||||
font->update(true);
|
||||
|
||||
scanKeys();
|
||||
pressed = keysDown();
|
||||
swiWaitForVBlank();
|
||||
} while (!(pressed & KEY_A));
|
||||
|
||||
type = cardEepromGetTypeFixed();
|
||||
}
|
||||
|
||||
auxspi_extra card_type = auxspi_has_extra();
|
||||
bool auxspi = card_type == AUXSPI_INFRARED;
|
||||
if(auxspi) {
|
||||
size = auxspi_save_size_log_2(card_type);
|
||||
type = auxspi_save_type(card_type);
|
||||
@ -675,11 +706,10 @@ void ndsCardSaveRestore(const char *filename) {
|
||||
} else {
|
||||
size = cardEepromGetSizeFixed();
|
||||
}
|
||||
fseek(in, 0, SEEK_END);
|
||||
length = ftell(in);
|
||||
fseek(in, 0, SEEK_SET);
|
||||
|
||||
if(length != (auxspi ? (int)(LEN * num_blocks) : size)) {
|
||||
fclose(in);
|
||||
if(!usingFlashcard)
|
||||
fclose(in);
|
||||
dumpFailMsg(STR_SAVE_SIZE_MISMATCH_CARD);
|
||||
return;
|
||||
}
|
||||
@ -696,8 +726,12 @@ void ndsCardSaveRestore(const char *filename) {
|
||||
else
|
||||
cardEepromChipEraseFixed();
|
||||
}
|
||||
|
||||
// If using flashcard restore from buffer,
|
||||
// otherwise from file so big saves can work
|
||||
if(auxspi){
|
||||
buffer = new unsigned char[LEN];
|
||||
if(!usingFlashcard)
|
||||
buffer = new unsigned char[LEN];
|
||||
font->print(0, 5, false, "[");
|
||||
font->print(-1, 5, false, "]");
|
||||
for(unsigned int i = 0; i < num_blocks; i++) {
|
||||
@ -705,13 +739,18 @@ void ndsCardSaveRestore(const char *filename) {
|
||||
font->printf(0, 6, false, Alignment::left, Palette::white, STR_N_OF_N_BYTES.c_str(), i * LEN, length);
|
||||
font->update(false);
|
||||
|
||||
fread(buffer, 1, LEN, in);
|
||||
auxspi_write_data(i << shift, buffer, LEN, type, card_type);
|
||||
if(usingFlashcard) {
|
||||
auxspi_write_data(i << shift, buffer + (LEN * i), LEN, type, card_type);
|
||||
} else {
|
||||
fread(buffer, 1, LEN, in);
|
||||
auxspi_write_data(i << shift, buffer, LEN, type, card_type);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int blocks = size / 32;
|
||||
int written = 0;
|
||||
buffer = new unsigned char[blocks];
|
||||
if(!usingFlashcard)
|
||||
buffer = new unsigned char[blocks];
|
||||
font->print(0, 5, false, "[");
|
||||
font->print(-1, 5, false, "]");
|
||||
for(unsigned int i = 0; i < 32; i++) {
|
||||
@ -719,13 +758,18 @@ void ndsCardSaveRestore(const char *filename) {
|
||||
font->printf(0, 6, false, Alignment::left, Palette::white, STR_N_OF_N_BYTES.c_str(), written, size);
|
||||
font->update(false);
|
||||
|
||||
fread(buffer, 1, blocks, in);
|
||||
cardWriteEeprom(written, buffer, blocks, type);
|
||||
if(usingFlashcard) {
|
||||
cardWriteEeprom(written, buffer + (blocks * i), blocks, type);
|
||||
} else {
|
||||
fread(buffer, 1, blocks, in);
|
||||
cardWriteEeprom(written, buffer, blocks, type);
|
||||
}
|
||||
written += blocks;
|
||||
}
|
||||
}
|
||||
delete[] buffer;
|
||||
fclose(in);
|
||||
if(!usingFlashcard)
|
||||
fclose(in);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -953,7 +997,7 @@ void gbaCartSaveDump(const char *filename) {
|
||||
|
||||
void gbaCartSaveRestore(const char *filename) {
|
||||
font->clear(false);
|
||||
font->print(0, 0, false, STR_RESTORE_SELECTED_SAVE_CART);
|
||||
font->print(0, 0, false, STR_RESTORE_SELECTED_SAVE_CART + "\n\n" + STR_A_YES_B_NO);
|
||||
font->update(false);
|
||||
|
||||
// Power saving loop. Only poll the keys once per frame and sleep the CPU if there is nothing else to do
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
#include <dirent.h>
|
||||
|
||||
#include <nds.h>
|
||||
#include <nds/arm9/dldi.h>
|
||||
#include <fat.h>
|
||||
|
||||
#include "main.h"
|
||||
@ -187,7 +188,10 @@ FileOperation fileBrowse_A(DirEntry* entry, char path[PATH_MAX]) {
|
||||
operations.push_back(FileOperation::trimNds);
|
||||
}
|
||||
if(extension(entry->name, {"sav", "sav1", "sav2", "sav3", "sav4", "sav5", "sav6", "sav7", "sav8", "sav9"})) {
|
||||
operations.push_back(FileOperation::restoreSave);
|
||||
if(!(io_dldi_data->ioInterface.features & FEATURE_SLOT_NDS) || entry->size <= (1 << 20))
|
||||
operations.push_back(FileOperation::restoreSaveNds);
|
||||
if(isRegularDS && (entry->size == 512 || entry->size == 8192 || entry->size == 32768 || entry->size == 65536 || entry->size == 131072))
|
||||
operations.push_back(FileOperation::restoreSaveGba);
|
||||
}
|
||||
if(currentDrive != Drive::fatImg && extension(entry->name, {"img", "sd", "sav", "pub", "pu1", "pu2", "pu3", "pu4", "pu5", "pu6", "pu7", "pu8", "pu9", "prv", "pr1", "pr2", "pr3", "pr4", "pr5", "pr6", "pr7", "pr8", "pr9"})) {
|
||||
operations.push_back(FileOperation::mountImg);
|
||||
@ -238,8 +242,14 @@ FileOperation fileBrowse_A(DirEntry* entry, char path[PATH_MAX]) {
|
||||
case FileOperation::trimNds:
|
||||
font->print(3, row++, false, STR_TRIM_NDS);
|
||||
break;
|
||||
case FileOperation::restoreSave:
|
||||
font->print(3, row++, false, STR_RESTORE_SAVE);
|
||||
case FileOperation::restoreSaveNds:
|
||||
if(!isRegularDS)
|
||||
font->print(3, row++, false, STR_RESTORE_SAVE);
|
||||
else
|
||||
font->print(3, row++, false, STR_RESTORE_SAVE_NDS);
|
||||
break;
|
||||
case FileOperation::restoreSaveGba:
|
||||
font->print(3, row++, false, STR_RESTORE_SAVE_GBA);
|
||||
break;
|
||||
case FileOperation::mountImg:
|
||||
font->print(3, row++, false, STR_MOUNT_FAT_IMG);
|
||||
@ -328,12 +338,11 @@ FileOperation fileBrowse_A(DirEntry* entry, char path[PATH_MAX]) {
|
||||
applaunch = true;
|
||||
return FileOperation::bootFile;
|
||||
break;
|
||||
} case FileOperation::restoreSave: {
|
||||
if(isDSiMode()) {
|
||||
ndsCardSaveRestore(entry->name.c_str());
|
||||
} else {
|
||||
gbaCartSaveRestore(entry->name.c_str());
|
||||
}
|
||||
} case FileOperation::restoreSaveNds: {
|
||||
ndsCardSaveRestore(entry->name.c_str());
|
||||
break;
|
||||
} case FileOperation::restoreSaveGba: {
|
||||
gbaCartSaveRestore(entry->name.c_str());
|
||||
break;
|
||||
} case FileOperation::copySdOut: {
|
||||
if (access("sd:/gm9i", F_OK) != 0) {
|
||||
|
||||
@ -44,7 +44,8 @@ enum class FileOperation {
|
||||
ndsInfo,
|
||||
trimNds,
|
||||
mountImg,
|
||||
restoreSave,
|
||||
restoreSaveNds,
|
||||
restoreSaveGba,
|
||||
showInfo,
|
||||
copySdOut,
|
||||
copyFatOut,
|
||||
|
||||
@ -96,6 +96,8 @@ STRING(MOUNT_NITROFS, "Mount NitroFS")
|
||||
STRING(SHOW_NDS_INFO, "Show NDS file info")
|
||||
STRING(TRIM_NDS, "Trim NDS file")
|
||||
STRING(RESTORE_SAVE, "Restore save")
|
||||
STRING(RESTORE_SAVE_NDS, "Restore save (Slot-1)")
|
||||
STRING(RESTORE_SAVE_GBA, "Restore save (Slot-2)")
|
||||
STRING(MOUNT_FAT_IMG, "Mount as FAT image")
|
||||
STRING(OPEN_HEX, "Open in hex editor")
|
||||
STRING(SHOW_DIRECTORY_INFO, "Show directory info")
|
||||
@ -150,8 +152,10 @@ STRING(FAILED_TO_RESTORE_SAVE, "Failed to restore the save.")
|
||||
STRING(UNABLE_TO_RESTORE_SAVE, "Unable to restore the save.")
|
||||
STRING(SAVE_SIZE_MISMATCH_CARD, "The size of this save doesn't match the size of the inserted game card.\n\nWrite cancelled!")
|
||||
STRING(SAVE_SIZE_MISMATCH_CART, "The size of this save doesn't match the size of the inserted game pak.\n\nWrite cancelled!")
|
||||
STRING(RESTORE_SELECTED_SAVE_CARD, "Restore the selected save to the inserted game card?\n\n(\\A yes, \\B no)")
|
||||
STRING(RESTORE_SELECTED_SAVE_CART, "Restore the selected save to the inserted game pak?\n\n(\\A yes, \\B no)")
|
||||
STRING(RESTORE_SELECTED_SAVE_CARD, "Restore the selected save to the inserted game card?")
|
||||
STRING(RESTORE_SELECTED_SAVE_CARD_FLASHCARD, "Unmount the flashcard and restore the selected save to a game card?")
|
||||
STRING(RESTORE_SELECTED_SAVE_CART, "Restore the selected save to the inserted game pak?")
|
||||
STRING(EJECT_FLASHCARD_INSERT_GAME, "Eject your flashcard and insert the game card to restore to.")
|
||||
STRING(PROGRESS, "Progress:")
|
||||
STRING(N_OF_N_BYTES, "%d/%d Bytes")
|
||||
STRING(NDS_IS_DUMPING, "%s.nds\nis dumping...")
|
||||
|
||||
@ -91,6 +91,8 @@ MOUNT_NITROFS=Mount NitroFS
|
||||
SHOW_NDS_INFO=Show NDS file info
|
||||
TRIM_NDS=Trim NDS file
|
||||
RESTORE_SAVE=Restore save
|
||||
RESTORE_SAVE_NDS=Restore save (Slot-1)
|
||||
RESTORE_SAVE_GBA=Restore save (Slot-2)
|
||||
MOUNT_FAT_IMG=Mount as FAT image
|
||||
OPEN_HEX=Open in hex editor
|
||||
SHOW_DIRECTORY_INFO=Show directory info
|
||||
@ -142,8 +144,10 @@ FAILED_TO_RESTORE_SAVE=Failed to restore the save.
|
||||
UNABLE_TO_RESTORE_SAVE=Unable to restore the save.
|
||||
SAVE_SIZE_MISMATCH_CARD=The size of this save doesn't match the size of the inserted game card.\n\nWrite cancelled!
|
||||
SAVE_SIZE_MISMATCH_CART=The size of this save doesn't match the size of the inserted game pak.\n\nWrite cancelled!
|
||||
RESTORE_SELECTED_SAVE_CARD=Restore the selected save to the inserted game card?\n\n(\A yes, \B no)
|
||||
RESTORE_SELECTED_SAVE_CART=Restore the selected save to the inserted game pak?\n\n(\A yes, \B no)
|
||||
RESTORE_SELECTED_SAVE_CARD=Restore the selected save to the inserted game card?
|
||||
RESTORE_SELECTED_SAVE_CARD_FLASHCARD=Unmount the flashcard and restore the selected save to a game card?
|
||||
RESTORE_SELECTED_SAVE_CART=Restore the selected save to the inserted game pak?
|
||||
EJECT_FLASHCARD_INSERT_GAME=Eject your flashcard and insert the game card to restore to.
|
||||
PROGRESS=Progress:
|
||||
N_OF_N_BYTES=%d/%d Bytes
|
||||
NDS_IS_DUMPING=%s.nds\nis dumping...
|
||||
|
||||
Loading…
Reference in New Issue
Block a user