mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 13:42:47 +00:00
Some groundwork for CARD2 save support
This commit is contained in:
parent
1cb72a87e1
commit
dfb2dff352
@ -101,12 +101,12 @@ const CardSPITypeData * const FLASH_1MB_CTR = flashTypes + 8;
|
|||||||
#define REG_CFG9_CARDCTL *((vu16*)0x1000000C)
|
#define REG_CFG9_CARDCTL *((vu16*)0x1000000C)
|
||||||
#define CARDCTL_SPICARD (1u<<8)
|
#define CARDCTL_SPICARD (1u<<8)
|
||||||
|
|
||||||
int CardSPIWriteRead(CardSPIType type, const void* cmd, u32 cmdSize, void* answer, u32 answerSize, const void* data, u32 dataSize) {
|
int CardSPIWriteRead(bool infrared, const void* cmd, u32 cmdSize, void* answer, u32 answerSize, const void* data, u32 dataSize) {
|
||||||
u32 headerFooterVal = 0;
|
u32 headerFooterVal = 0;
|
||||||
|
|
||||||
REG_CFG9_CARDCTL |= CARDCTL_SPICARD;
|
REG_CFG9_CARDCTL |= CARDCTL_SPICARD;
|
||||||
|
|
||||||
if (type.infrared) {
|
if (infrared) {
|
||||||
SPI_XferInfo irXfer = { &headerFooterVal, 1, false };
|
SPI_XferInfo irXfer = { &headerFooterVal, 1, false };
|
||||||
SPI_DoXfer(SPI_DEV_CART_IR, &irXfer, 1, false);
|
SPI_DoXfer(SPI_DEV_CART_IR, &irXfer, 1, false);
|
||||||
}
|
}
|
||||||
@ -123,13 +123,13 @@ int CardSPIWriteRead(CardSPIType type, const void* cmd, u32 cmdSize, void* answe
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CardSPIWaitWriteEnd(CardSPIType type, u32 timeout) {
|
int CardSPIWaitWriteEnd(bool infrared, u32 timeout) {
|
||||||
u8 cmd = SPI_CMD_RDSR, statusReg = 0;
|
u8 cmd = SPI_CMD_RDSR, statusReg = 0;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
u64 time_start = timer_start();
|
u64 time_start = timer_start();
|
||||||
|
|
||||||
do {
|
do {
|
||||||
res = CardSPIWriteRead(type, &cmd, 1, &statusReg, 1, 0, 0);
|
res = CardSPIWriteRead(infrared, &cmd, 1, &statusReg, 1, 0, 0);
|
||||||
if (res) return res;
|
if (res) return res;
|
||||||
if (timer_msec(time_start) > timeout) return 1;
|
if (timer_msec(time_start) > timeout) return 1;
|
||||||
} while(statusReg & SPI_FLG_WIP);
|
} while(statusReg & SPI_FLG_WIP);
|
||||||
@ -139,18 +139,18 @@ int CardSPIWaitWriteEnd(CardSPIType type, u32 timeout) {
|
|||||||
|
|
||||||
int CardSPIEnableWriting_512B(CardSPIType type) {
|
int CardSPIEnableWriting_512B(CardSPIType type) {
|
||||||
u8 cmd = SPI_CMD_WREN;
|
u8 cmd = SPI_CMD_WREN;
|
||||||
return CardSPIWriteRead(type, &cmd, 1, NULL, 0, 0, 0);
|
return CardSPIWriteRead(type.infrared, &cmd, 1, NULL, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CardSPIEnableWriting_regular(CardSPIType type) {
|
int CardSPIEnableWriting_regular(CardSPIType type) {
|
||||||
u8 cmd = SPI_CMD_WREN, statusReg = 0;
|
u8 cmd = SPI_CMD_WREN, statusReg = 0;
|
||||||
int res = CardSPIWriteRead(type, &cmd, 1, NULL, 0, 0, 0);
|
int res = CardSPIWriteRead(type.infrared, &cmd, 1, NULL, 0, 0, 0);
|
||||||
|
|
||||||
if (res) return res;
|
if (res) return res;
|
||||||
cmd = SPI_CMD_RDSR;
|
cmd = SPI_CMD_RDSR;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
res = CardSPIWriteRead(type, &cmd, 1, &statusReg, 1, 0, 0);
|
res = CardSPIWriteRead(type.infrared, &cmd, 1, &statusReg, 1, 0, 0);
|
||||||
if (res) return res;
|
if (res) return res;
|
||||||
} while(statusReg & ~SPI_FLG_WEL);
|
} while(statusReg & ~SPI_FLG_WEL);
|
||||||
|
|
||||||
@ -165,24 +165,24 @@ int CardSPIEnableWriting(CardSPIType type) {
|
|||||||
int _SPIWriteTransaction(CardSPIType type, void* cmd, u32 cmdSize, const void* data, u32 dataSize) {
|
int _SPIWriteTransaction(CardSPIType type, void* cmd, u32 cmdSize, const void* data, u32 dataSize) {
|
||||||
int res;
|
int res;
|
||||||
if ((res = CardSPIEnableWriting(type))) return res;
|
if ((res = CardSPIEnableWriting(type))) return res;
|
||||||
if ((res = CardSPIWriteRead(type, cmd, cmdSize, NULL, 0, (void*) ((u8*) data), dataSize))) return res;
|
if ((res = CardSPIWriteRead(type.infrared, cmd, cmdSize, NULL, 0, (void*) ((u8*) data), dataSize))) return res;
|
||||||
return CardSPIWaitWriteEnd(type, 1000);
|
return CardSPIWaitWriteEnd(type.infrared, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CardSPIReadJEDECIDAndStatusReg(CardSPIType type, u32* id, u8* statusReg) {
|
int CardSPIReadJEDECIDAndStatusReg(bool infrared, u32* id, u8* statusReg) {
|
||||||
u8 cmd = SPI_FLASH_CMD_RDID;
|
u8 cmd = SPI_FLASH_CMD_RDID;
|
||||||
u8 reg = 0;
|
u8 reg = 0;
|
||||||
u8 idbuf[3] = { 0 };
|
u8 idbuf[3] = { 0 };
|
||||||
u32 id_ = 0;
|
u32 id_ = 0;
|
||||||
int res = CardSPIWaitWriteEnd(type, 0);
|
int res = CardSPIWaitWriteEnd(infrared, 0);
|
||||||
if (res) return res;
|
if (res) return res;
|
||||||
|
|
||||||
if ((res = CardSPIWriteRead(type, &cmd, 1, idbuf, 3, 0, 0))) return res;
|
if ((res = CardSPIWriteRead(infrared, &cmd, 1, idbuf, 3, 0, 0))) return res;
|
||||||
|
|
||||||
id_ = (idbuf[0] << 16) | (idbuf[1] << 8) | idbuf[2];
|
id_ = (idbuf[0] << 16) | (idbuf[1] << 8) | idbuf[2];
|
||||||
cmd = SPI_CMD_RDSR;
|
cmd = SPI_CMD_RDSR;
|
||||||
|
|
||||||
if ((res = CardSPIWriteRead(type, &cmd, 1, ®, 1, 0, 0))) return res;
|
if ((res = CardSPIWriteRead(infrared, &cmd, 1, ®, 1, 0, 0))) return res;
|
||||||
|
|
||||||
if (id) *id = id_;
|
if (id) *id = id_;
|
||||||
if (statusReg) *statusReg = reg;
|
if (statusReg) *statusReg = reg;
|
||||||
@ -256,7 +256,7 @@ int CardSPIWriteSaveData_24bit_erase_program(CardSPIType type, u32 offset, const
|
|||||||
if (!(res = _SPIWriteTransaction(type, cmd, 4, (void*) ((u8*) data - offset + pos), pageSize))) {
|
if (!(res = _SPIWriteTransaction(type, cmd, 4, (void*) ((u8*) data - offset + pos), pageSize))) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
CardSPIWriteRead(type, "\x04", 1, NULL, 0, NULL, 0);
|
CardSPIWriteRead(type.infrared, "\x04", 1, NULL, 0, NULL, 0);
|
||||||
}
|
}
|
||||||
if(res) {
|
if(res) {
|
||||||
free(newData);
|
free(newData);
|
||||||
@ -278,7 +278,7 @@ int CardSPIWriteSaveData(CardSPIType type, u32 offset, const void* data, u32 siz
|
|||||||
u32 writeSize = type.chip->writeSize;
|
u32 writeSize = type.chip->writeSize;
|
||||||
if (writeSize == 0) return 0xC8E13404;
|
if (writeSize == 0) return 0xC8E13404;
|
||||||
|
|
||||||
int res = CardSPIWaitWriteEnd(type, 1000);
|
int res = CardSPIWaitWriteEnd(type.infrared, 1000);
|
||||||
if (res) return res;
|
if (res) return res;
|
||||||
|
|
||||||
while(pos < end) {
|
while(pos < end) {
|
||||||
@ -307,7 +307,7 @@ int CardSPIReadSaveData_9bit(CardSPIType type, u32 pos, void* data, u32 size) {
|
|||||||
cmd[0] = SPI_512B_EEPROM_CMD_RDLO;
|
cmd[0] = SPI_512B_EEPROM_CMD_RDLO;
|
||||||
cmd[1] = (u8) pos;
|
cmd[1] = (u8) pos;
|
||||||
|
|
||||||
int res = CardSPIWriteRead(type, cmd, cmdSize, data, len, NULL, 0);
|
int res = CardSPIWriteRead(type.infrared, cmd, cmdSize, data, len, NULL, 0);
|
||||||
if (res) return res;
|
if (res) return res;
|
||||||
|
|
||||||
read += len;
|
read += len;
|
||||||
@ -319,7 +319,7 @@ int CardSPIReadSaveData_9bit(CardSPIType type, u32 pos, void* data, u32 size) {
|
|||||||
cmd[0] = SPI_512B_EEPROM_CMD_RDHI;
|
cmd[0] = SPI_512B_EEPROM_CMD_RDHI;
|
||||||
cmd[1] = (u8)(pos + read);
|
cmd[1] = (u8)(pos + read);
|
||||||
|
|
||||||
int res = CardSPIWriteRead(type, cmd, cmdSize, (void*)((u8*)data + read), len, NULL, 0);
|
int res = CardSPIWriteRead(type.infrared, cmd, cmdSize, (void*)((u8*)data + read), len, NULL, 0);
|
||||||
|
|
||||||
if (res) return res;
|
if (res) return res;
|
||||||
}
|
}
|
||||||
@ -330,13 +330,13 @@ int CardSPIReadSaveData_9bit(CardSPIType type, u32 pos, void* data, u32 size) {
|
|||||||
int CardSPIReadSaveData_16bit(CardSPIType type, u32 offset, void* data, u32 size) {
|
int CardSPIReadSaveData_16bit(CardSPIType type, u32 offset, void* data, u32 size) {
|
||||||
u8 cmd[3] = { SPI_CMD_READ, (u8)(offset >> 8), (u8) offset };
|
u8 cmd[3] = { SPI_CMD_READ, (u8)(offset >> 8), (u8) offset };
|
||||||
|
|
||||||
return CardSPIWriteRead(type, cmd, 3, data, size, NULL, 0);
|
return CardSPIWriteRead(type.infrared, cmd, 3, data, size, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CardSPIReadSaveData_24bit(CardSPIType type, u32 offset, void* data, u32 size) {
|
int CardSPIReadSaveData_24bit(CardSPIType type, u32 offset, void* data, u32 size) {
|
||||||
u8 cmd[4] = { SPI_CMD_READ, (u8)(offset >> 16), (u8)(offset >> 8), (u8) offset };
|
u8 cmd[4] = { SPI_CMD_READ, (u8)(offset >> 16), (u8)(offset >> 8), (u8) offset };
|
||||||
|
|
||||||
return CardSPIWriteRead(type, cmd, 4, data, size, NULL, 0);
|
return CardSPIWriteRead(type.infrared, cmd, 4, data, size, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CardSPIReadSaveData(CardSPIType type, u32 offset, void* data, u32 size) {
|
int CardSPIReadSaveData(CardSPIType type, u32 offset, void* data, u32 size) {
|
||||||
@ -344,7 +344,7 @@ int CardSPIReadSaveData(CardSPIType type, u32 offset, void* data, u32 size) {
|
|||||||
|
|
||||||
if (size == 0) return 0;
|
if (size == 0) return 0;
|
||||||
|
|
||||||
int res = CardSPIWaitWriteEnd(type, 1000);
|
int res = CardSPIWaitWriteEnd(type.infrared, 1000);
|
||||||
if (res) return res;
|
if (res) return res;
|
||||||
|
|
||||||
size = (size <= CardSPIGetCapacity(type) - offset) ? size : CardSPIGetCapacity(type) - offset;
|
size = (size <= CardSPIGetCapacity(type) - offset) ? size : CardSPIGetCapacity(type) - offset;
|
||||||
@ -367,7 +367,7 @@ int CardSPIEraseSector_emulated(CardSPIType type, u32 offset) {
|
|||||||
int CardSPIEraseSector_real(CardSPIType type, u32 offset) {
|
int CardSPIEraseSector_real(CardSPIType type, u32 offset) {
|
||||||
u8 cmd[4] = { type.chip->eraseCommand, (u8)(offset >> 16), (u8)(offset >> 8), (u8) offset };
|
u8 cmd[4] = { type.chip->eraseCommand, (u8)(offset >> 16), (u8)(offset >> 8), (u8) offset };
|
||||||
|
|
||||||
int res = CardSPIWaitWriteEnd(type, 10000);
|
int res = CardSPIWaitWriteEnd(type.infrared, 10000);
|
||||||
if (res) return res;
|
if (res) return res;
|
||||||
|
|
||||||
return _SPIWriteTransaction(type, cmd, 4, NULL, 0);
|
return _SPIWriteTransaction(type, cmd, 4, NULL, 0);
|
||||||
@ -438,7 +438,7 @@ int _SPIIsDataMirrored(CardSPIType type, int size, bool* mirrored) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CardSPIGetCardSPIType(CardSPIType* type, bool infrared) {
|
CardSPIType CardSPIGetCardSPIType(bool infrared) {
|
||||||
u8 sr = 0;
|
u8 sr = 0;
|
||||||
u32 jedec = 0;
|
u32 jedec = 0;
|
||||||
CardSPIType t = {NO_CHIP, infrared};
|
CardSPIType t = {NO_CHIP, infrared};
|
||||||
@ -446,20 +446,18 @@ int CardSPIGetCardSPIType(CardSPIType* type, bool infrared) {
|
|||||||
|
|
||||||
if(infrared) {
|
if(infrared) {
|
||||||
// Infrared carts currently not supported, need additional handling!
|
// Infrared carts currently not supported, need additional handling!
|
||||||
*type = (CardSPIType) {NO_CHIP, true};
|
return (CardSPIType) {NO_CHIP, true};
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
res = CardSPIReadJEDECIDAndStatusReg(t, &jedec, &sr);
|
res = CardSPIReadJEDECIDAndStatusReg(infrared, &jedec, &sr);
|
||||||
if (res) return res;
|
if (res) return (CardSPIType) {NO_CHIP, false};
|
||||||
|
|
||||||
if ((sr & 0xfd) == 0x00 && (jedec != 0x00ffffff)) { t.chip = &FLASH_DUMMY; }
|
if ((sr & 0xfd) == 0x00 && (jedec != 0x00ffffff)) { t.chip = &FLASH_DUMMY; }
|
||||||
if ((sr & 0xfd) == 0xF0 && (jedec == 0x00ffffff)) { *type = (CardSPIType) { EEPROM_512B, false }; return 0; }
|
if ((sr & 0xfd) == 0xF0 && (jedec == 0x00ffffff)) { return (CardSPIType) { EEPROM_512B, false }; }
|
||||||
if ((sr & 0xfd) == 0x00 && (jedec == 0x00ffffff)) { t = (CardSPIType) { &EEPROM_DUMMY, false }; }
|
if ((sr & 0xfd) == 0x00 && (jedec == 0x00ffffff)) { t = (CardSPIType) { &EEPROM_DUMMY, false }; }
|
||||||
|
|
||||||
if(t.chip == NO_CHIP) {
|
if(t.chip == NO_CHIP) {
|
||||||
*type = (CardSPIType) {NO_CHIP, false};
|
return (CardSPIType) {NO_CHIP, false};
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t.chip == &EEPROM_DUMMY) {
|
if (t.chip == &EEPROM_DUMMY) {
|
||||||
@ -467,24 +465,20 @@ int CardSPIGetCardSPIType(CardSPIType* type, bool infrared) {
|
|||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
for(i = 0; i < sizeof(EEPROMTypes) / sizeof(CardSPITypeData) - 1; i++) {
|
for(i = 0; i < sizeof(EEPROMTypes) / sizeof(CardSPITypeData) - 1; i++) {
|
||||||
if ((res = _SPIIsDataMirrored(t, CardSPIGetCapacity((CardSPIType) {EEPROMTypes + i, false}), &mirrored))) return res;
|
if ((res = _SPIIsDataMirrored(t, CardSPIGetCapacity((CardSPIType) {EEPROMTypes + i, false}), &mirrored))) return (CardSPIType) {NO_CHIP, false};
|
||||||
if (mirrored) {
|
if (mirrored) {
|
||||||
*type = (CardSPIType) {EEPROMTypes + i, false};
|
return (CardSPIType) {EEPROMTypes + i, false};
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*type = (CardSPIType) { EEPROMTypes + i, false };
|
return (CardSPIType) { EEPROMTypes + i, false };
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for(size_t i = 0; i < sizeof(flashTypes) / sizeof(CardSPITypeData); i++) {
|
for(size_t i = 0; i < sizeof(flashTypes) / sizeof(CardSPITypeData); i++) {
|
||||||
if (flashTypes[i].jedecId == jedec) {
|
if (flashTypes[i].jedecId == jedec) {
|
||||||
*type = (CardSPIType) { flashTypes + i, infrared };
|
return (CardSPIType) { flashTypes + i, infrared };
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*type = (CardSPIType) { NO_CHIP, infrared };
|
return (CardSPIType) { NO_CHIP, infrared };
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -66,11 +66,11 @@ extern const CardSPITypeData * const FLASH_128KB_CTR; // Most common, including
|
|||||||
extern const CardSPITypeData * const FLASH_512KB_CTR; // Also common, including Detective Pikachu
|
extern const CardSPITypeData * const FLASH_512KB_CTR; // Also common, including Detective Pikachu
|
||||||
extern const CardSPITypeData * const FLASH_1MB_CTR; // For example Pokemon Ultra Sun
|
extern const CardSPITypeData * const FLASH_1MB_CTR; // For example Pokemon Ultra Sun
|
||||||
|
|
||||||
int CardSPIWriteRead(CardSPIType type, const void* cmd, u32 cmdSize, void* answer, u32 answerSize, const void* data, u32 dataSize);
|
int CardSPIWriteRead(bool infrared, const void* cmd, u32 cmdSize, void* answer, u32 answerSize, const void* data, u32 dataSize);
|
||||||
int CardSPIWaitWriteEnd(CardSPIType type, u32 timeout);
|
int CardSPIWaitWriteEnd(bool infrared, u32 timeout);
|
||||||
int CardSPIEnableWriting(CardSPIType type);
|
int CardSPIEnableWriting(CardSPIType type);
|
||||||
int CardSPIReadJEDECIDAndStatusReg(CardSPIType type, u32* id, u8* statusReg);
|
int CardSPIReadJEDECIDAndStatusReg(bool infrared, u32* id, u8* statusReg);
|
||||||
int CardSPIGetCardSPIType(CardSPIType* type, bool infrared);
|
CardSPIType CardSPIGetCardSPIType(bool infrared);
|
||||||
u32 CardSPIGetPageSize(CardSPIType type);
|
u32 CardSPIGetPageSize(CardSPIType type);
|
||||||
u32 CardSPIGetCapacity(CardSPIType type);
|
u32 CardSPIGetCapacity(CardSPIType type);
|
||||||
u32 CardSPIGetEraseSize(CardSPIType type);
|
u32 CardSPIGetEraseSize(CardSPIType type);
|
||||||
|
@ -152,10 +152,18 @@ u32 InitCartRead(CartData* cdata) {
|
|||||||
|
|
||||||
// save data
|
// save data
|
||||||
u32 card2_offset = getle32(cdata->header + 0x200);
|
u32 card2_offset = getle32(cdata->header + 0x200);
|
||||||
if ((card2_offset != 0xFFFFFFFF) || (CardSPIGetCardSPIType(&(cdata->save_type), 0) != 0)) {
|
if (card2_offset != 0xFFFFFFFF) {
|
||||||
cdata->save_type = (CardSPIType) { NO_CHIP, false };
|
cdata->save_type = CARD_SAVE_CARD2;
|
||||||
|
cdata->save_size = cdata->cart_size - card2_offset * NCSD_MEDIA_UNIT;
|
||||||
|
} else {
|
||||||
|
cdata->spi_save_type = CardSPIGetCardSPIType(false);
|
||||||
|
if (cdata->spi_save_type.chip == NO_CHIP) {
|
||||||
|
cdata->save_type = CARD_SAVE_NONE;
|
||||||
|
} else {
|
||||||
|
cdata->save_type = CARD_SAVE_SPI;
|
||||||
|
cdata->save_size = CardSPIGetCapacity(cdata->spi_save_type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cdata->save_size = CardSPIGetCapacity(cdata->save_type);
|
|
||||||
} else { // NTR/TWL cartridges
|
} else { // NTR/TWL cartridges
|
||||||
// NTR header
|
// NTR header
|
||||||
TwlHeader* nds_header = (void*)cdata->header;
|
TwlHeader* nds_header = (void*)cdata->header;
|
||||||
@ -198,10 +206,13 @@ u32 InitCartRead(CartData* cdata) {
|
|||||||
|
|
||||||
// save data
|
// save data
|
||||||
bool infrared = *(nds_header->game_code) == 'I';
|
bool infrared = *(nds_header->game_code) == 'I';
|
||||||
if (CardSPIGetCardSPIType(&(cdata->save_type), infrared) != 0) {
|
cdata->spi_save_type = CardSPIGetCardSPIType(infrared);
|
||||||
cdata->save_type = (CardSPIType) { NO_CHIP, false };
|
if (cdata->spi_save_type.chip == NO_CHIP) {
|
||||||
|
cdata->save_type = CARD_SAVE_NONE;
|
||||||
|
} else {
|
||||||
|
cdata->save_type = CARD_SAVE_SPI;
|
||||||
|
cdata->save_size = CardSPIGetCapacity(cdata->spi_save_type);
|
||||||
}
|
}
|
||||||
cdata->save_size = CardSPIGetCapacity(cdata->save_type);
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -336,27 +347,11 @@ u32 ReadCartInfo(u8* buffer, u64 offset, u64 count, CartData* cdata) {
|
|||||||
u32 ReadCartSave(u8* buffer, u64 offset, u64 count, CartData* cdata) {
|
u32 ReadCartSave(u8* buffer, u64 offset, u64 count, CartData* cdata) {
|
||||||
if (offset >= cdata->save_size) return 1;
|
if (offset >= cdata->save_size) return 1;
|
||||||
if (offset + count > cdata->save_size) count = cdata->save_size - offset;
|
if (offset + count > cdata->save_size) count = cdata->save_size - offset;
|
||||||
return (CardSPIReadSaveData(cdata->save_type, offset, buffer, count) == 0) ? 0 : 1;
|
return (CardSPIReadSaveData(cdata->spi_save_type, offset, buffer, count) == 0) ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 WriteCartSave(const u8* buffer, u64 offset, u64 count, CartData* cdata) {
|
u32 WriteCartSave(const u8* buffer, u64 offset, u64 count, CartData* cdata) {
|
||||||
if (offset >= cdata->save_size) return 1;
|
if (offset >= cdata->save_size) return 1;
|
||||||
if (offset + count > cdata->save_size) count = cdata->save_size - offset;
|
if (offset + count > cdata->save_size) count = cdata->save_size - offset;
|
||||||
return (CardSPIWriteSaveData(cdata->save_type, offset, buffer, count) == 0) ? 0 : 1;
|
return (CardSPIWriteSaveData(cdata->spi_save_type, offset, buffer, count) == 0) ? 0 : 1;
|
||||||
}
|
|
||||||
|
|
||||||
u32 ReadCartSaveJedecId(u8* buffer, u64 offset, u64 count, CartData* cdata) {
|
|
||||||
u8 ownBuf[JEDECID_AND_SREG_SIZE] = { 0 };
|
|
||||||
u32 id;
|
|
||||||
u8 sReg;
|
|
||||||
if (offset >= JEDECID_AND_SREG_SIZE) return 1;
|
|
||||||
if (offset + count > JEDECID_AND_SREG_SIZE) count = JEDECID_AND_SREG_SIZE - offset;
|
|
||||||
int res = CardSPIReadJEDECIDAndStatusReg(cdata->save_type, &id, &sReg);
|
|
||||||
if (res) return res;
|
|
||||||
ownBuf[0] = (id >> 16) & 0xff;
|
|
||||||
ownBuf[1] = (id >> 8) & 0xff;
|
|
||||||
ownBuf[2] = id & 0xff;
|
|
||||||
ownBuf[JEDECID_AND_SREG_SIZE - 1] = sReg;
|
|
||||||
memcpy(buffer, ownBuf + offset, count);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,13 @@
|
|||||||
#define PRIV_HDR_SIZE 0x50
|
#define PRIV_HDR_SIZE 0x50
|
||||||
#define JEDECID_AND_SREG_SIZE 0x4
|
#define JEDECID_AND_SREG_SIZE 0x4
|
||||||
|
|
||||||
|
typedef enum CardSaveType {
|
||||||
|
CARD_SAVE_NONE,
|
||||||
|
CARD_SAVE_SPI,
|
||||||
|
CARD_SAVE_CARD2,
|
||||||
|
CARD_SAVE_RETAIL_NAND,
|
||||||
|
} CardSaveType;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u8 header[0x8000]; // NTR header + secure area / CTR header + private header
|
u8 header[0x8000]; // NTR header + secure area / CTR header + private header
|
||||||
u8 storage[0x8000]; // encrypted secure area + modcrypt area / unused
|
u8 storage[0x8000]; // encrypted secure area + modcrypt area / unused
|
||||||
@ -20,7 +27,8 @@ typedef struct {
|
|||||||
u64 cart_size;
|
u64 cart_size;
|
||||||
u64 data_size;
|
u64 data_size;
|
||||||
u32 save_size;
|
u32 save_size;
|
||||||
CardSPIType save_type;
|
CardSaveType save_type;
|
||||||
|
CardSPIType spi_save_type; // Specific data for SPI save
|
||||||
u32 arm9i_rom_offset; // TWL specific
|
u32 arm9i_rom_offset; // TWL specific
|
||||||
} PACKED_ALIGN(16) CartData;
|
} PACKED_ALIGN(16) CartData;
|
||||||
|
|
||||||
@ -34,4 +42,3 @@ u32 ReadCartPrivateHeader(void* buffer, u64 offset, u64 count, CartData* cdata);
|
|||||||
u32 ReadCartInfo(u8* buffer, u64 offset, u64 count, CartData* cdata);
|
u32 ReadCartInfo(u8* buffer, u64 offset, u64 count, CartData* cdata);
|
||||||
u32 ReadCartSave(u8* buffer, u64 offset, u64 count, CartData* cdata);
|
u32 ReadCartSave(u8* buffer, u64 offset, u64 count, CartData* cdata);
|
||||||
u32 WriteCartSave(const u8* buffer, u64 offset, u64 count, CartData* cdata);
|
u32 WriteCartSave(const u8* buffer, u64 offset, u64 count, CartData* cdata);
|
||||||
u32 ReadCartSaveJedecId(u8* buffer, u64 offset, u64 count, CartData* cdata);
|
|
||||||
|
@ -2,9 +2,8 @@
|
|||||||
#include "gamecart.h"
|
#include "gamecart.h"
|
||||||
|
|
||||||
#define FAT_LIMIT 0x100000000
|
#define FAT_LIMIT 0x100000000
|
||||||
#define VFLAG_SECURE_AREA_ENC (1UL<<27)
|
#define VFLAG_SECURE_AREA_ENC (1UL<<28)
|
||||||
#define VFLAG_GAMECART_NFO (1UL<<28)
|
#define VFLAG_GAMECART_NFO (1UL<<29)
|
||||||
#define VFLAG_JEDECID_AND_SRFG (1UL<<29)
|
|
||||||
#define VFLAG_SAVEGAME (1UL<<30)
|
#define VFLAG_SAVEGAME (1UL<<30)
|
||||||
#define VFLAG_PRIV_HDR (1UL<<31)
|
#define VFLAG_PRIV_HDR (1UL<<31)
|
||||||
|
|
||||||
@ -66,7 +65,7 @@ bool ReadVCartDir(VirtualFile* vfile, VirtualDir* vdir) {
|
|||||||
vfile->size = PRIV_HDR_SIZE;
|
vfile->size = PRIV_HDR_SIZE;
|
||||||
vfile->flags |= VFLAG_PRIV_HDR;
|
vfile->flags |= VFLAG_PRIV_HDR;
|
||||||
return true;
|
return true;
|
||||||
} else if ((vdir->index == 7) && (cdata->save_size > 0)) { // savegame
|
} else if ((vdir->index == 7) && (cdata->save_type != CARD_SAVE_NONE)) { // savegame
|
||||||
snprintf(vfile->name, 32, "%s.sav", name);
|
snprintf(vfile->name, 32, "%s.sav", name);
|
||||||
vfile->size = cdata->save_size;
|
vfile->size = cdata->save_size;
|
||||||
vfile->flags = VFLAG_SAVEGAME;
|
vfile->flags = VFLAG_SAVEGAME;
|
||||||
@ -78,11 +77,6 @@ bool ReadVCartDir(VirtualFile* vfile, VirtualDir* vdir) {
|
|||||||
vfile->size = strnlen(info, 255);
|
vfile->size = strnlen(info, 255);
|
||||||
vfile->flags |= VFLAG_GAMECART_NFO;
|
vfile->flags |= VFLAG_GAMECART_NFO;
|
||||||
return true;
|
return true;
|
||||||
} else if ((vdir->index == 9) && cdata->save_type.chip) { // JEDEC id and status register
|
|
||||||
strcpy(vfile->name, "jedecid_and_sreg.bin");
|
|
||||||
vfile->size = JEDECID_AND_SREG_SIZE;
|
|
||||||
vfile->flags |= VFLAG_JEDECID_AND_SRFG;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,8 +93,6 @@ int ReadVCartFile(const VirtualFile* vfile, void* buffer, u64 offset, u64 count)
|
|||||||
return ReadCartSave(buffer, foffset, count, cdata);
|
return ReadCartSave(buffer, foffset, count, cdata);
|
||||||
else if (vfile->flags & VFLAG_GAMECART_NFO)
|
else if (vfile->flags & VFLAG_GAMECART_NFO)
|
||||||
return ReadCartInfo(buffer, foffset, count, cdata);
|
return ReadCartInfo(buffer, foffset, count, cdata);
|
||||||
else if (vfile->flags & VFLAG_JEDECID_AND_SRFG)
|
|
||||||
return ReadCartSaveJedecId(buffer, foffset, count, cdata);
|
|
||||||
|
|
||||||
SetSecureAreaEncryption(vfile->flags & VFLAG_SECURE_AREA_ENC);
|
SetSecureAreaEncryption(vfile->flags & VFLAG_SECURE_AREA_ENC);
|
||||||
return ReadCartBytes(buffer, foffset, count, cdata);
|
return ReadCartBytes(buffer, foffset, count, cdata);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user