diff --git a/include/arm11/hardware/lgy.h b/include/arm11/hardware/lgy.h index 4cb8aac..54bbf7f 100644 --- a/include/arm11/hardware/lgy.h +++ b/include/arm11/hardware/lgy.h @@ -4,6 +4,26 @@ #include "error_codes.h" +enum +{ + SAVE_TYPE_EEPROM_8k = 0x0u, // "[save] in upper 16Mbyte of ROM area" + SAVE_TYPE_EEPROM_8k_2 = 0x1u, // "[save] in upper 100h byte of ROM area" + SAVE_TYPE_EEPROM_64k = 0x2u, // "[save] in upper 16Mbyte of ROM area" + SAVE_TYPE_EEPROM_64k_2 = 0x3u, // "[save] in upper 100h byte of ROM area" + SAVE_TYPE_FLASH_512k_AML_RTC = 0x4u, // "FLASH ID=3D1Fh, Atmel" + SAVE_TYPE_FLASH_512k_AML = 0x5u, // "FLASH ID=3D1Fh, Atmel" + SAVE_TYPE_FLASH_512k_SST_RTC = 0x6u, // "FLASH ID=D4BFh, SST" + SAVE_TYPE_FLASH_512k_SST = 0x7u, // "FLASH ID=D4BFh, SST" + SAVE_TYPE_FLASH_512k_PSC_RTC = 0x8u, // "FLASH ID=1B32h, Panasonic" + SAVE_TYPE_FLASH_512k_PSC = 0x9u, // "FLASH ID=1B32h, Panasonic" + SAVE_TYPE_FLASH_1m_MRX_RTC = 0xAu, // "FLASH ID=09C2h, Macronix" + SAVE_TYPE_FLASH_1m_MRX = 0xBu, // "FLASH ID=09C2h, Macronix" + SAVE_TYPE_FLASH_1m_SNO_RTC = 0xCu, // "FLASH ID=1362h, Sanyo" + SAVE_TYPE_FLASH_1m_SNO = 0xDu, // "FLASH ID=1362h, Sanyo" + SAVE_TYPE_SRAM_256k = 0xEu, + SAVE_TYPE_NONE = 0xFu +}; + // All values in BCD. typedef struct { @@ -33,7 +53,7 @@ typedef struct -Result LGY_prepareLegacyMode(bool gbaBios); +Result LGY_prepareGbaMode(bool gbaBios, u16 saveType); Result LGY_setGbaRtc(GbaRtc rtc); Result LGY_getGbaRtc(GbaRtc *out); void LGY_switchMode(void); diff --git a/include/arm9/hardware/lgy.h b/include/arm9/hardware/lgy.h index 9167194..2eda59c 100644 --- a/include/arm9/hardware/lgy.h +++ b/include/arm9/hardware/lgy.h @@ -93,7 +93,7 @@ typedef struct -Result LGY_prepareLegacyMode(bool gbaBios); +Result LGY_prepareGbaMode(bool gbaBios, u16 saveType); Result LGY_setGbaRtc(GbaRtc rtc); Result LGY_getGbaRtc(GbaRtc *out); Result LGY_backupGbaSave(void); diff --git a/include/ipc_handler.h b/include/ipc_handler.h index 72269b3..3d3cdff 100644 --- a/include/ipc_handler.h +++ b/include/ipc_handler.h @@ -33,7 +33,7 @@ typedef enum { - IPC_CMD9_PREPARE_AGB = MAKE_CMD(0, 0, 0, 1), + IPC_CMD9_PREPARE_GBA = MAKE_CMD(0, 0, 0, 2), IPC_CMD9_SET_GBA_RTC = MAKE_CMD(1, 0, 0, 2), IPC_CMD9_GET_GBA_RTC = MAKE_CMD(2, 0, 1, 0), IPC_CMD9_PREPARE_POWER = MAKE_CMD(3, 0, 0, 0) diff --git a/source/arm11/hardware/lgy.c b/source/arm11/hardware/lgy.c index fc49ca0..a9280eb 100644 --- a/source/arm11/hardware/lgy.c +++ b/source/arm11/hardware/lgy.c @@ -34,10 +34,10 @@ static void lgySleepIrqHandler(u32 intSource) } } -Result LGY_prepareLegacyMode(bool gbaBios) +Result LGY_prepareGbaMode(bool gbaBios, u16 saveType) { - const u32 cmdBuf = gbaBios; - Result res = PXI_sendCmd(IPC_CMD9_PREPARE_AGB, &cmdBuf, 1); + const u32 cmdBuf[2] = {gbaBios, saveType}; + Result res = PXI_sendCmd(IPC_CMD9_PREPARE_GBA, cmdBuf, 2); if(res != RES_OK) return res; GbaRtc rtc; diff --git a/source/arm11/main.c b/source/arm11/main.c index 432cc9c..04937bb 100644 --- a/source/arm11/main.c +++ b/source/arm11/main.c @@ -37,7 +37,7 @@ int main(void) ee_puts("Reading ROM and save..."); Result res; - if((res = LGY_prepareLegacyMode(false)) == RES_OK) + if((res = LGY_prepareGbaMode(false, SAVE_TYPE_SRAM_256k)) == RES_OK) { GFX_setForceBlack(false, true); GFX_setBrightness(DEFAULT_BRIGHTNESS, 0); diff --git a/source/arm9/hardware/lgy.c b/source/arm9/hardware/lgy.c index f6c5746..8420ae3 100644 --- a/source/arm9/hardware/lgy.c +++ b/source/arm9/hardware/lgy.c @@ -38,21 +38,52 @@ static u32 g_saveHash[8] = {0}; -Result LGY_prepareLegacyMode(bool gbaBios) +#define STRINGIFY(s) #s +#define STR(s) STRINGIFY(s) +NAKED static void _overlayStub(void) { - REG_LGY_MODE = 2; // GBA mode + __asm__("mov r0, #0x4000000\n\t" + "mov r1, #1\n\t" + "strb r1, [r0, #0x300]\n\t" // "POSTFLG" + "ldr pc, _overlayStubJmp\n\t" + "_overlayStubJmp: .4byte " STR(ARM7_STUB_LOC) "\n\t" : : : ); +} + +static void setupBiosOverlay(bool gbaBios) +{ + iomemcpy(REGs_LGY_A7_VECTOR, (u32*)_overlayStub, 20); - // BIOS overlay - REGs_LGY_A7_VECTOR[0] = 0xE51FF004; //ldr pc, [pc, #-4] - REGs_LGY_A7_VECTOR[1] = ARM7_STUB_LOC; NDMA_copy((u32*)ARM7_STUB_LOC9, _arm7_stub_start, (u32)_arm7_stub_end - (u32)_arm7_stub_start); - //iomemcpy((u32*)ARM7_STUB_LOC9, _arm7_stub_start, (u32)_arm7_stub_end - (u32)_arm7_stub_start); // Patch swi 0x10 (RegisterRamReset) to swi 0x26 (HardReset). if(gbaBios) *((u8*)(ARM7_STUB_LOC9 + ((u32)_arm7_stub_swi - (u32)_arm7_stub_start))) = 0x26; +} - REG_LGY_GBA_SAVE_TYPE = SAVE_TYPE_SRAM_256k; - static const u32 saveStuff[4] = {0x27C886, 0x8CE35, 0x184, 0x31170}; - iomemcpy(REGs_LGY_GBA_SAVE_TIMING, saveStuff, 16); +static void setupSaveType(u16 saveType) +{ + REG_LGY_GBA_SAVE_TYPE = saveType; + static const u8 saveSizeLut[16] = {1, 1, 8, 8, 64, 64, 64, 64, 64, 64, 128, 128, 128, 128, 32, 0}; + g_saveSize = 1024u * saveSizeLut[saveType & 0xFu]; + + // Flash chip erase, flash sector erase, flash program, EEPROM write. + static const u32 saveTm512k4k[4] = {0x27C886, 0x8CE35, 0x184, 0x31170}; // Timing 512k/4k. + static const u32 saveTm1m64k[4] = {0x17D43E, 0x26206, 0x86, 0x2DD13}; // Timing 1m/64k. + const u32 *saveTm; + if(saveType < SAVE_TYPE_EEPROM_64k || + (saveType > SAVE_TYPE_EEPROM_64k_2 && saveType < SAVE_TYPE_FLASH_1m_MRX_RTC) || + saveType == SAVE_TYPE_SRAM_256k) + { + saveTm = saveTm512k4k; + } + else saveTm = saveTm1m64k; // Don't care about save type none. + iomemcpy(REGs_LGY_GBA_SAVE_TIMING, saveTm, 16); +} + +Result LGY_prepareGbaMode(bool gbaBios, u16 saveType) +{ + REG_LGY_MODE = LGY_MODE_AGB; + + setupBiosOverlay(gbaBios); + setupSaveType(saveType); Result res = RES_OK; do @@ -90,23 +121,25 @@ Result LGY_prepareLegacyMode(bool gbaBios) break; } - g_saveSize = 1024 * 32; - if(f_open(&f, "sdmc:/rom.sav", FA_OPEN_EXISTING | FA_READ) == FR_OK) + if(g_saveSize != 0) { - UINT read; - FRESULT fres = f_read(&f, (void*)SAVE_LOC, MAX_SAVE_SIZE, &read); - - f_close(&f); - - if(fres != FR_OK) + if(f_open(&f, "sdmc:/rom.sav", FA_OPEN_EXISTING | FA_READ) == FR_OK) { - res = RES_FILE_READ_ERR; - break; - } + UINT read; + FRESULT fres = f_read(&f, (void*)SAVE_LOC, MAX_SAVE_SIZE, &read); - sha((u32*)SAVE_LOC, g_saveSize, g_saveHash, SHA_INPUT_BIG | SHA_MODE_256, SHA_OUTPUT_BIG); + f_close(&f); + + if(fres != FR_OK) + { + res = RES_FILE_READ_ERR; + break; + } + + sha((u32*)SAVE_LOC, g_saveSize, g_saveHash, SHA_INPUT_BIG | SHA_MODE_256, SHA_OUTPUT_BIG); + } + else NDMA_fill((u32*)SAVE_LOC, 0xFFFFFFFFu, g_saveSize); } - else NDMA_fill((u32*)SAVE_LOC, 0xFFFFFFFFu, g_saveSize); } else { diff --git a/source/arm9/ipc_handler.c b/source/arm9/ipc_handler.c index 3a219d5..1148766 100644 --- a/source/arm9/ipc_handler.c +++ b/source/arm9/ipc_handler.c @@ -35,8 +35,8 @@ u32 IPC_handleCmd(u8 cmdId, u32 inBufs, u32 outBufs, const u32 *const buf) u32 result = 0; switch(cmdId) { - case IPC_CMD_ID_MASK(IPC_CMD9_PREPARE_AGB): - result = LGY_prepareLegacyMode(*buf); + case IPC_CMD_ID_MASK(IPC_CMD9_PREPARE_GBA): + result = LGY_prepareGbaMode(buf[0], buf[1]); break; case IPC_CMD_ID_MASK(IPC_CMD9_SET_GBA_RTC): result = LGY_setGbaRtc(*((GbaRtc*)buf));