mirror of
https://github.com/rvtr/GodMode9i.git
synced 2025-11-02 00:11:07 -04:00
Fix NAND save writing and restoring
This commit is contained in:
parent
0bc622b3d5
commit
294c4bee1c
@ -30,6 +30,26 @@ void dumpFailMsg(bool save) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void saveWriteFailMsg(void) {
|
||||||
|
const std::string_view sizeError = "The size of this save doesn't match the size of the inserted game card.\n\nWrite cancelled!";
|
||||||
|
|
||||||
|
font->clear(false);
|
||||||
|
font->print(0, 0, false, sizeError, Alignment::left, Palette::red);
|
||||||
|
font->print(0, font->calcHeight(sizeError) + 1, false, "(<A> OK)");
|
||||||
|
font->update(false);
|
||||||
|
|
||||||
|
u16 pressed;
|
||||||
|
do {
|
||||||
|
// Print time
|
||||||
|
font->print(-1, 0, true, RetTime(), Alignment::right, Palette::blackGreen);
|
||||||
|
font->update(true);
|
||||||
|
|
||||||
|
scanKeys();
|
||||||
|
pressed = keysDownRepeat();
|
||||||
|
swiWaitForVBlank();
|
||||||
|
} while (!(pressed & KEY_A));
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
// https://github.com/devkitPro/libnds/blob/master/source/common/cardEeprom.c#L74
|
// https://github.com/devkitPro/libnds/blob/master/source/common/cardEeprom.c#L74
|
||||||
// with Pokémon Mystery Dungeon - Explorers of Sky (128 KiB EEPROM) fixed
|
// with Pokémon Mystery Dungeon - Explorers of Sky (128 KiB EEPROM) fixed
|
||||||
@ -215,7 +235,7 @@ void ndsCardSaveDump(const char* filename) {
|
|||||||
font->update(false);
|
font->update(false);
|
||||||
|
|
||||||
for (u32 i = 0; i < 0x8000; i += 0x200) {
|
for (u32 i = 0; i < 0x8000; i += 0x200) {
|
||||||
cardRead(ndsCardHeader.nandRwStart + src + i, copyBuf + i);
|
cardRead(cardNandRwStart + src + i, copyBuf + i, true);
|
||||||
}
|
}
|
||||||
if (fwrite(copyBuf, 1, (currentSize >= 0x8000 ? 0x8000 : currentSize), destinationFile) < 1) {
|
if (fwrite(copyBuf, 1, (currentSize >= 0x8000 ? 0x8000 : currentSize), destinationFile) < 1) {
|
||||||
dumpFailMsg(true);
|
dumpFailMsg(true);
|
||||||
@ -273,104 +293,144 @@ void ndsCardSaveRestore(const char *filename) {
|
|||||||
} while (!(pressed & (KEY_A | KEY_B)));
|
} while (!(pressed & (KEY_A | KEY_B)));
|
||||||
|
|
||||||
if(pressed & KEY_A) {
|
if(pressed & KEY_A) {
|
||||||
auxspi_extra card_type = auxspi_has_extra();
|
int type = cardEepromGetTypeFixed();
|
||||||
bool auxspi = card_type == AUXSPI_INFRARED;
|
|
||||||
FILE *in = fopen(filename, "rb");
|
if(type == -1) { // NAND
|
||||||
if(in) {
|
if (cardInit(&ndsCardHeader) != 0) {
|
||||||
unsigned char *buffer;
|
font->clear(false);
|
||||||
int size;
|
font->print(0, 0, false, "Unable to restore the save.");
|
||||||
int type;
|
font->update(false);
|
||||||
int length;
|
for (int i = 0; i < 60 * 2; i++) {
|
||||||
unsigned int num_blocks = 0, shift = 0, LEN = 0;
|
swiWaitForVBlank();
|
||||||
if(auxspi) {
|
|
||||||
size = auxspi_save_size_log_2(card_type);
|
|
||||||
type = auxspi_save_type(card_type);
|
|
||||||
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;
|
return;
|
||||||
num_blocks = 1 << (size - shift);
|
|
||||||
} else {
|
|
||||||
type = cardEepromGetTypeFixed();
|
|
||||||
size = cardEepromGetSizeFixed();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 saveSize = cardNandGetSaveSize();
|
||||||
|
|
||||||
|
if(saveSize == 0) {
|
||||||
|
dumpFailMsg(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE* in = fopen(filename, "rb");
|
||||||
|
|
||||||
fseek(in, 0, SEEK_END);
|
fseek(in, 0, SEEK_END);
|
||||||
length = ftell(in);
|
size_t length = ftell(in);
|
||||||
fseek(in, 0, SEEK_SET);
|
fseek(in, 0, SEEK_SET);
|
||||||
if(length != (auxspi ? (int)(LEN * num_blocks) : size)) {
|
if(length != saveSize) {
|
||||||
fclose(in);
|
fclose(in);
|
||||||
|
|
||||||
const std::string_view sizeError = "The size of this save doesn't match the size of the inserted game card.\n\nWrite cancelled!";
|
saveWriteFailMsg();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
font->clear(false);
|
u32 currentSize = saveSize;
|
||||||
font->print(0, 0, false, sizeError, Alignment::left, Palette::red);
|
if (in) {
|
||||||
font->print(0, font->calcHeight(sizeError) + 1, false, "(<A> OK)");
|
|
||||||
font->update(false);
|
|
||||||
|
|
||||||
do {
|
font->print(0, 4, false, "Progress:");
|
||||||
|
font->print(0, 5, false, "[");
|
||||||
|
font->print(-1, 5, false, "]");
|
||||||
|
for (u32 src = 0; src < saveSize; src += 0x8000) {
|
||||||
// Print time
|
// Print time
|
||||||
font->print(-1, 0, true, RetTime(), Alignment::right, Palette::blackGreen);
|
font->print(-1, 0, true, RetTime(), Alignment::right, Palette::blackGreen);
|
||||||
font->update(true);
|
font->update(true);
|
||||||
|
|
||||||
scanKeys();
|
font->print((src / (saveSize / (SCREEN_COLS - 2))) + 1, 5, false, "=");
|
||||||
pressed = keysDownRepeat();
|
font->printf(0, 6, false, Alignment::left, Palette::white, "%d/%d Bytes", src, saveSize);
|
||||||
swiWaitForVBlank();
|
|
||||||
} while (!(pressed & KEY_A));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
font->clear(false);
|
|
||||||
font->print(0, 0, false, "Restoring save...");
|
|
||||||
font->print(0, 1, false, "Do not remove the NDS card.");
|
|
||||||
font->print(0, 4, false, "Progress:");
|
|
||||||
font->update(false);
|
|
||||||
|
|
||||||
if(type == 3) {
|
|
||||||
if(auxspi)
|
|
||||||
auxspi_erase(card_type);
|
|
||||||
else
|
|
||||||
cardEepromChipEraseFixed();
|
|
||||||
}
|
|
||||||
if(auxspi){
|
|
||||||
buffer = new unsigned char[LEN];
|
|
||||||
font->print(0, 5, false, "[");
|
|
||||||
font->print(-1, 5, false, "]");
|
|
||||||
for(unsigned int i = 0; i < num_blocks; i++) {
|
|
||||||
font->print((i * (SCREEN_COLS - 2) / num_blocks) + 1, 5, false, "=");
|
|
||||||
font->printf(0, 6, false, Alignment::left, Palette::white, "%d/%d Bytes", i * LEN, length);
|
|
||||||
font->update(false);
|
font->update(false);
|
||||||
|
|
||||||
fread(buffer, 1, LEN, in);
|
fread(copyBuf, 1, 0x8000, in);
|
||||||
auxspi_write_data(i << shift, buffer, LEN, type, card_type);
|
for (u32 i = 0; i < 0x8000; i += 0x800) {
|
||||||
}
|
cardWriteNand(copyBuf + i, cardNandRwStart + src + i);
|
||||||
} else {
|
}
|
||||||
int blocks = size / 32;
|
currentSize -= 0x8000;
|
||||||
int written = 0;
|
|
||||||
buffer = new unsigned char[blocks];
|
|
||||||
font->print(0, 5, false, "[");
|
|
||||||
font->print(-1, 5, false, "]");
|
|
||||||
for(unsigned int i = 0; i < 32; i++) {
|
|
||||||
font->print((i * (SCREEN_COLS - 2) / 32) + 1, 5, false, "=");
|
|
||||||
font->printf(0, 6, false, Alignment::left, Palette::white, "%d/%d Bytes", written, size);
|
|
||||||
font->update(false);
|
|
||||||
|
|
||||||
fread(buffer, 1, blocks, in);
|
|
||||||
cardWriteEeprom(written, buffer, blocks, type);
|
|
||||||
written += blocks;
|
|
||||||
}
|
}
|
||||||
|
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;
|
||||||
|
int size;
|
||||||
|
int length;
|
||||||
|
unsigned int num_blocks = 0, shift = 0, LEN = 0;
|
||||||
|
if(auxspi) {
|
||||||
|
size = auxspi_save_size_log_2(card_type);
|
||||||
|
type = auxspi_save_type(card_type);
|
||||||
|
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);
|
||||||
|
} 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);
|
||||||
|
|
||||||
|
saveWriteFailMsg();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
font->clear(false);
|
||||||
|
font->print(0, 0, false, "Restoring save...");
|
||||||
|
font->print(0, 1, false, "Do not remove the NDS card.");
|
||||||
|
font->print(0, 4, false, "Progress:");
|
||||||
|
font->update(false);
|
||||||
|
|
||||||
|
if(type == 3) {
|
||||||
|
if(auxspi)
|
||||||
|
auxspi_erase(card_type);
|
||||||
|
else
|
||||||
|
cardEepromChipEraseFixed();
|
||||||
|
}
|
||||||
|
if(auxspi){
|
||||||
|
buffer = new unsigned char[LEN];
|
||||||
|
font->print(0, 5, false, "[");
|
||||||
|
font->print(-1, 5, false, "]");
|
||||||
|
for(unsigned int i = 0; i < num_blocks; i++) {
|
||||||
|
font->print((i * (SCREEN_COLS - 2) / num_blocks) + 1, 5, false, "=");
|
||||||
|
font->printf(0, 6, false, Alignment::left, Palette::white, "%d/%d Bytes", i * LEN, length);
|
||||||
|
font->update(false);
|
||||||
|
|
||||||
|
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];
|
||||||
|
font->print(0, 5, false, "[");
|
||||||
|
font->print(-1, 5, false, "]");
|
||||||
|
for(unsigned int i = 0; i < 32; i++) {
|
||||||
|
font->print((i * (SCREEN_COLS - 2) / 32) + 1, 5, false, "=");
|
||||||
|
font->printf(0, 6, false, Alignment::left, Palette::white, "%d/%d Bytes", written, size);
|
||||||
|
font->update(false);
|
||||||
|
|
||||||
|
fread(buffer, 1, blocks, in);
|
||||||
|
cardWriteEeprom(written, buffer, blocks, type);
|
||||||
|
written += blocks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete[] buffer;
|
||||||
|
fclose(in);
|
||||||
}
|
}
|
||||||
delete[] buffer;
|
|
||||||
fclose(in);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -604,7 +664,7 @@ void ndsCardDump(void) {
|
|||||||
iprintf ("\x1b[8;0H");
|
iprintf ("\x1b[8;0H");
|
||||||
iprintf ("Read:\n");
|
iprintf ("Read:\n");
|
||||||
iprintf ("%i/%i Bytes ", (int)src, (int)romSize);
|
iprintf ("%i/%i Bytes ", (int)src, (int)romSize);
|
||||||
cardRead (src, (void*)0x09000000+(src % 0x800000));
|
cardRead (src, (void*)0x09000000+(src % 0x800000), false);
|
||||||
}
|
}
|
||||||
iprintf("\x1b[15;0H");
|
iprintf("\x1b[15;0H");
|
||||||
iprintf("Please switch to the\nflashcard, then press A.\n");
|
iprintf("Please switch to the\nflashcard, then press A.\n");
|
||||||
@ -664,17 +724,12 @@ void ndsCardDump(void) {
|
|||||||
font->print(-1, 0, true, RetTime(), Alignment::right, Palette::blackGreen);
|
font->print(-1, 0, true, RetTime(), Alignment::right, Palette::blackGreen);
|
||||||
font->update(true);
|
font->update(true);
|
||||||
|
|
||||||
// TODO: Remove, just for testing
|
|
||||||
scanKeys();
|
|
||||||
if(keysDown() & KEY_B)
|
|
||||||
break;
|
|
||||||
|
|
||||||
font->print((src / (romSize / (SCREEN_COLS - 2))) + 1, 5, false, "=");
|
font->print((src / (romSize / (SCREEN_COLS - 2))) + 1, 5, false, "=");
|
||||||
font->printf(0, 6, false, Alignment::left, Palette::white, "%d/%d Bytes", src, romSize);
|
font->printf(0, 6, false, Alignment::left, Palette::white, "%d/%d Bytes", src, romSize);
|
||||||
font->update(false);
|
font->update(false);
|
||||||
|
|
||||||
for (u32 i = 0; i < 0x8000; i += 0x200) {
|
for (u32 i = 0; i < 0x8000; i += 0x200) {
|
||||||
cardRead (src+i, copyBuf+i);
|
cardRead (src+i, copyBuf+i, false);
|
||||||
}
|
}
|
||||||
if (fwrite(copyBuf, 1, (currentSize>=0x8000 ? 0x8000 : currentSize), destinationFile) < 1) {
|
if (fwrite(copyBuf, 1, (currentSize>=0x8000 ? 0x8000 : currentSize), destinationFile) < 1) {
|
||||||
dumpFailMsg(false);
|
dumpFailMsg(false);
|
||||||
@ -686,8 +741,7 @@ void ndsCardDump(void) {
|
|||||||
} else {
|
} else {
|
||||||
dumpFailMsg(false);
|
dumpFailMsg(false);
|
||||||
}
|
}
|
||||||
// TODO: Uncomment, just commented for testing
|
ndsCardSaveDump(destSavPath);
|
||||||
// ndsCardSaveDump(destSavPath);
|
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -45,7 +45,7 @@ enum {
|
|||||||
// NAND Card commands
|
// NAND Card commands
|
||||||
// https://problemkaputt.de/gbatek-ds-cartridge-nand.htm
|
// https://problemkaputt.de/gbatek-ds-cartridge-nand.htm
|
||||||
#define CARD_CMD_NAND_WRITE_BUFFER 0x81
|
#define CARD_CMD_NAND_WRITE_BUFFER 0x81
|
||||||
#define CARD_CMD_NAND_FLUSH_BUFFER 0x82
|
#define CARD_CMD_NAND_COMMIT_BUFFER 0x82
|
||||||
#define CARD_CMD_NAND_DISCARD_BUFFER 0x84
|
#define CARD_CMD_NAND_DISCARD_BUFFER 0x84
|
||||||
#define CARD_CMD_NAND_WRITE_ENABLE 0x85
|
#define CARD_CMD_NAND_WRITE_ENABLE 0x85
|
||||||
#define CARD_CMD_NAND_ROM_MODE 0x8B
|
#define CARD_CMD_NAND_ROM_MODE 0x8B
|
||||||
@ -63,18 +63,48 @@ typedef union
|
|||||||
static bool twlBlowfish = false;
|
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 bool normalChip = false; // As defined by GBAtek, normal chip secure area is accessed in blocks of 0x200, other chip in blocks of 0x1000
|
||||||
static bool nandChip = false;
|
|
||||||
static int nandRomMode = -1;
|
|
||||||
static u32 portFlags = 0;
|
static u32 portFlags = 0;
|
||||||
static u32 headerData[0x1000/sizeof(u32)] = {0};
|
static u32 headerData[0x1000/sizeof(u32)] = {0};
|
||||||
static u32 secureArea[CARD_SECURE_AREA_SIZE/sizeof(u32)] = {0};
|
static u32 secureArea[CARD_SECURE_AREA_SIZE/sizeof(u32)] = {0};
|
||||||
|
|
||||||
|
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) {
|
static u32 getRandomNumber(void) {
|
||||||
return rand();
|
return rand();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
// https://github.com/devkitPro/libnds/blob/105d4943dbac8f2bd99a47b22cd3ed48f96af083/source/common/card.c#L47-L62
|
||||||
|
// but modified to write if CARD_WR is set.
|
||||||
|
static void cardPolledTransferWrite(u32 flags, u32 *buffer, u32 length, const u8 *command) {
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
cardWriteCommand(command);
|
||||||
|
REG_ROMCTRL = flags | CARD_BUSY;
|
||||||
|
u32 * target = buffer + length;
|
||||||
|
do {
|
||||||
|
// Read/write data if available
|
||||||
|
if (REG_ROMCTRL & CARD_DATA_READY) {
|
||||||
|
if (flags & CARD_WR) { // Write
|
||||||
|
if (NULL != buffer && buffer < target)
|
||||||
|
REG_CARD_DATA_RD = *buffer++;
|
||||||
|
else
|
||||||
|
REG_CARD_DATA_RD = 0;
|
||||||
|
} else { // Read
|
||||||
|
u32 data = REG_CARD_DATA_RD;
|
||||||
|
if (NULL != buffer && buffer < target)
|
||||||
|
*buffer++ = REG_CARD_DATA_RD;
|
||||||
|
else
|
||||||
|
(void)data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} 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);
|
init_keycode (gameCode, 2, 8, iCardDevice);
|
||||||
@ -291,7 +321,7 @@ int cardInit (sNDSHeaderExt* ndsHeader)
|
|||||||
u32 portFlagsKey1, portFlagsSecRead;
|
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
|
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;
|
nandChip = false;
|
||||||
nandRomMode = -1;
|
nandSection = -1;
|
||||||
int secureBlockNumber;
|
int secureBlockNumber;
|
||||||
int i;
|
int i;
|
||||||
u8 cmdData[8] __attribute__ ((aligned));
|
u8 cmdData[8] __attribute__ ((aligned));
|
||||||
@ -313,9 +343,6 @@ int cardInit (sNDSHeaderExt* ndsHeader)
|
|||||||
NULL, 0);
|
NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: This was only done in DS mode, but fixes NAND in DSi mode
|
|
||||||
// see if only part of this is needed or if it causes problems to do
|
|
||||||
// all of it in DSi mode.
|
|
||||||
REG_ROMCTRL=0;
|
REG_ROMCTRL=0;
|
||||||
REG_AUXSPICNT=0;
|
REG_AUXSPICNT=0;
|
||||||
//ioDelay2(167550);
|
//ioDelay2(167550);
|
||||||
@ -467,10 +494,23 @@ int cardInit (sNDSHeaderExt* ndsHeader)
|
|||||||
//return normalChip ? ERR_SEC_NORM : ERR_SEC_OTHR;
|
//return normalChip ? ERR_SEC_NORM : ERR_SEC_OTHR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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;
|
return ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cardRead (u32 src, void* dest)
|
void cardRead (u32 src, void* dest, bool nandSave)
|
||||||
{
|
{
|
||||||
sNDSHeaderExt* ndsHeader = (sNDSHeaderExt*)headerData;
|
sNDSHeaderExt* ndsHeader = (sNDSHeaderExt*)headerData;
|
||||||
|
|
||||||
@ -491,15 +531,17 @@ void cardRead (u32 src, void* dest)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (nandChip) {
|
if (nandChip) {
|
||||||
// if (src < ndsHeader->nandRomEnd * 0x20000 /*dsi: 80000h?*/ && nandRomMode != CARD_CMD_NAND_ROM_MODE) {
|
if ((src < cardNandRomEnd || !nandSave) && nandSection != -1) {
|
||||||
// cardParamCommand(CARD_CMD_NAND_ROM_MODE, 0, CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW | CARD_DELAY1(0x1FFF) | CARD_DELAY2(0x3F), NULL, 0);
|
cardParamCommand(CARD_CMD_NAND_ROM_MODE, 0, portFlags | CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW, NULL, 0);
|
||||||
// nandRomMode = CARD_CMD_NAND_ROM_MODE;
|
nandSection = -1;
|
||||||
// } else if (src > ndsHeader->nandRwStart * 0x20000 /*dsi: 80000h?*/ && nandRomMode != CARD_CMD_NAND_RW_MODE) {
|
} else if (src >= cardNandRwStart && nandSection != (src - cardNandRwStart) / (128 << 10)) {
|
||||||
// cardParamCommand(CARD_CMD_NAND_RW_MODE, 0, CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW | CARD_DELAY1(0x1FFF) | CARD_DELAY2(0x3F), NULL, 0);
|
if(nandSection != -1) // Need to switch back to ROM mode before switching to another RW section
|
||||||
// nandRomMode = CARD_CMD_NAND_RW_MODE;
|
cardParamCommand(CARD_CMD_NAND_ROM_MODE, 0, portFlags | CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW, NULL, 0);
|
||||||
// }
|
cardParamCommand(CARD_CMD_NAND_RW_MODE, src, portFlags | CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW, NULL, 0);
|
||||||
// }
|
nandSection = (src - cardNandRwStart) / (128 << 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cardParamCommand (CARD_CMD_DATA_READ, src,
|
cardParamCommand (CARD_CMD_DATA_READ, src,
|
||||||
portFlags | CARD_ACTIVATE | CARD_nRESET | CARD_BLK_SIZE(1),
|
portFlags | CARD_ACTIVATE | CARD_nRESET | CARD_BLK_SIZE(1),
|
||||||
@ -510,3 +552,32 @@ void cardRead (u32 src, void* dest)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// src must be a 0x800 byte array
|
||||||
|
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
|
||||||
|
cardParamCommand(CARD_CMD_NAND_ROM_MODE, 0, portFlags | CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW, NULL, 0);
|
||||||
|
cardParamCommand(CARD_CMD_NAND_RW_MODE, dest, portFlags | CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW, NULL, 0);
|
||||||
|
nandSection = (dest - cardNandRwStart) / (128 << 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
cardParamCommand(CARD_CMD_NAND_WRITE_ENABLE, 0, portFlags | CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW, NULL, 0);
|
||||||
|
|
||||||
|
const u8 cmdData[8] = {0, 0, 0, dest, dest >> 8, dest >> 16, dest >> 24, CARD_CMD_NAND_WRITE_BUFFER};
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
cardPolledTransferWrite(portFlags | CARD_ACTIVATE | CARD_WR | CARD_nRESET | CARD_BLK_SIZE(1), src + (i * 0x200), 0x200 / sizeof(u32), cmdData);
|
||||||
|
}
|
||||||
|
|
||||||
|
cardParamCommand(CARD_CMD_NAND_COMMIT_BUFFER, 0, portFlags | CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW, NULL, 0);
|
||||||
|
|
||||||
|
u32 status;
|
||||||
|
do {
|
||||||
|
cardParamCommand(CARD_CMD_NAND_READ_STATUS, 0, portFlags | CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW | CARD_BLK_SIZE(7), &status, 1);
|
||||||
|
} while((status & BIT(5)) == 0);
|
||||||
|
|
||||||
|
cardParamCommand(CARD_CMD_NAND_DISCARD_BUFFER, 0, portFlags | CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW, NULL, 0);
|
||||||
|
}
|
||||||
|
|||||||
@ -36,9 +36,14 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern u32 cardNandRomEnd;
|
||||||
|
extern u32 cardNandRwStart;
|
||||||
|
|
||||||
int cardInit (sNDSHeaderExt* ndsHeader);
|
int cardInit (sNDSHeaderExt* ndsHeader);
|
||||||
|
|
||||||
void cardRead (u32 src, void* dest);
|
void cardRead (u32 src, void* dest, bool nandSave);
|
||||||
|
|
||||||
|
void cardWriteNand (void* src, u32 dest);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user