Basic save type detection based on code from GBARunner2 (thanks Gericom).
Note: Some EEPROM types are definitely broken right now.
This commit is contained in:
parent
aecbee03e7
commit
9002291e8a
|
@ -107,7 +107,7 @@ Result LGY_setGbaRtc(const GbaRtc rtc);
|
|||
Result LGY_getGbaRtc(GbaRtc *const out);
|
||||
Result LGY_backupGbaSave(void);
|
||||
#ifdef ARM11
|
||||
Result LGY_prepareGbaMode(bool gbaBios, u16 saveType, const char *const romPath, const char *const savePath);
|
||||
Result LGY_prepareGbaMode(bool gbaBios, const char *const romPath, const char *const savePath);
|
||||
void LGY_switchMode(void);
|
||||
void LGY_handleEvents(void);
|
||||
void LGY_deinit(void);
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
#include "arm11/hardware/pdn.h"
|
||||
#include "arm11/hardware/mcu.h"
|
||||
#include "arm11/hardware/lgyfb.h"
|
||||
#ifndef NDEBUG
|
||||
#include "arm11/fmt.h"
|
||||
#endif
|
||||
|
||||
|
||||
#define LGY_REGS_BASE (IO_MEM_ARM9_ARM11 + 0x41100)
|
||||
|
@ -38,7 +41,7 @@ static void lgySleepIrqHandler(u32 intSource)
|
|||
}
|
||||
}
|
||||
|
||||
static Result loadRom(const char *const path)
|
||||
static Result loadRom(const char *const path, u32 *const rsOut)
|
||||
{
|
||||
Result res;
|
||||
FHandle f;
|
||||
|
@ -54,6 +57,7 @@ static Result loadRom(const char *const path)
|
|||
|
||||
if(res == RES_OK)
|
||||
{
|
||||
*rsOut = romSize;
|
||||
// Pad ROM area with "open bus" value.
|
||||
memset((void*)(ROM_LOC + romSize), 0xFFFFFFFFu, romSize);
|
||||
}
|
||||
|
@ -66,6 +70,103 @@ static Result loadRom(const char *const path)
|
|||
return res;
|
||||
}
|
||||
|
||||
// Code based on: https://github.com/Gericom/GBARunner2/blob/master/arm9/source/save/Save.vram.cpp
|
||||
static void tryDetectSaveType(u32 romSize, u16 *const stOut)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
ee_puts("Trying to detect save type...");
|
||||
#endif
|
||||
|
||||
u8 saveChipKind = 0; // 0 = none, 1 = EEPROM, 2 = Flash, 3 = SRAM.
|
||||
const u32 *romPtr = (u32*)(ROM_LOC + 0xE4u); // Skip headers.
|
||||
for(; romPtr < (u32*)(ROM_LOC + romSize); romPtr++)
|
||||
{
|
||||
u32 tmp = *romPtr;
|
||||
|
||||
// "EEPR"
|
||||
if(tmp == 0x52504545u)
|
||||
{
|
||||
saveChipKind = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
// "FLAS"
|
||||
if(tmp == 0x53414C46u)
|
||||
{
|
||||
saveChipKind = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
// "SRAM"
|
||||
if(tmp == 0x4D415253u)
|
||||
{
|
||||
saveChipKind = 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(saveChipKind != 0)
|
||||
{
|
||||
static const struct
|
||||
{
|
||||
char *str;
|
||||
u16 saveType;
|
||||
} saveTypeLut[25] =
|
||||
{
|
||||
// EEPROM
|
||||
// TODO: Which ones are SAVE_TYPE_EEPROM_64k_2?
|
||||
{"EEPROM_V111", SAVE_TYPE_EEPROM_8k}, // 512 bytes.
|
||||
{"EEPROM_V120", SAVE_TYPE_EEPROM_64k},
|
||||
{"EEPROM_V121", SAVE_TYPE_EEPROM_64k},
|
||||
{"EEPROM_V122", SAVE_TYPE_EEPROM_64k},
|
||||
{"EEPROM_V124", SAVE_TYPE_EEPROM_64k},
|
||||
{"EEPROM_V125", SAVE_TYPE_EEPROM_64k},
|
||||
{"EEPROM_V126", SAVE_TYPE_EEPROM_64k},
|
||||
|
||||
// FLASH
|
||||
// Assume they all have RTC.
|
||||
{"FLASH_V120", SAVE_TYPE_FLASH_512k_PSC_RTC},
|
||||
{"FLASH_V121", SAVE_TYPE_FLASH_512k_PSC_RTC},
|
||||
{"FLASH_V123", SAVE_TYPE_FLASH_512k_PSC_RTC},
|
||||
{"FLASH_V124", SAVE_TYPE_FLASH_512k_PSC_RTC},
|
||||
{"FLASH_V125", SAVE_TYPE_FLASH_512k_PSC_RTC},
|
||||
{"FLASH_V126", SAVE_TYPE_FLASH_512k_PSC_RTC},
|
||||
{"FLASH512_V130", SAVE_TYPE_FLASH_512k_PSC_RTC},
|
||||
{"FLASH512_V131", SAVE_TYPE_FLASH_512k_PSC_RTC},
|
||||
{"FLASH512_V133", SAVE_TYPE_FLASH_512k_PSC_RTC},
|
||||
{"FLASH1M_V102", SAVE_TYPE_FLASH_1m_MRX_RTC},
|
||||
{"FLASH1M_V103", SAVE_TYPE_FLASH_1m_MRX_RTC},
|
||||
|
||||
// FRAM & SRAM
|
||||
{"SRAM_F_V100", SAVE_TYPE_SRAM_256k},
|
||||
{"SRAM_F_V102", SAVE_TYPE_SRAM_256k},
|
||||
{"SRAM_F_V103", SAVE_TYPE_SRAM_256k},
|
||||
|
||||
{"SRAM_V110", SAVE_TYPE_SRAM_256k},
|
||||
{"SRAM_V111", SAVE_TYPE_SRAM_256k},
|
||||
{"SRAM_V112", SAVE_TYPE_SRAM_256k},
|
||||
{"SRAM_V113", SAVE_TYPE_SRAM_256k}
|
||||
};
|
||||
|
||||
for(u32 i = 0; i < 25; i++)
|
||||
{
|
||||
const char *const str = saveTypeLut[i].str;
|
||||
const u16 saveType = saveTypeLut[i].saveType;
|
||||
|
||||
if(memcmp(romPtr, str, strlen(str)) == 0)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
ee_printf("Found save type %s.", str);
|
||||
#endif
|
||||
*stOut = saveType;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
else ee_puts("Could not identify save type. Using none.");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void setupFcramForGbaMode(void)
|
||||
{
|
||||
// FCRAM reset and clock disable.
|
||||
|
@ -78,12 +179,17 @@ static void setupFcramForGbaMode(void)
|
|||
while(REG_PDN_FCRAM_CNT & PDN_FCRAM_CNT_CLK_E_ACK); // Wait until clock is disabled.
|
||||
}
|
||||
|
||||
Result LGY_prepareGbaMode(bool gbaBios, u16 saveType, const char *const romPath, const char *const savePath)
|
||||
Result LGY_prepareGbaMode(bool gbaBios, const char *const romPath, const char *const savePath)
|
||||
{
|
||||
// Load the ROM image.
|
||||
Result res = loadRom(romPath);
|
||||
u32 romSize;
|
||||
Result res = loadRom(romPath, &romSize);
|
||||
if(res != RES_OK) return res;
|
||||
|
||||
// Try to detect the save type.
|
||||
u16 saveType = SAVE_TYPE_NONE;
|
||||
tryDetectSaveType(romSize, &saveType);
|
||||
|
||||
// Prepare ARM9 for GBA mode + settings and save loading.
|
||||
u32 cmdBuf[2];
|
||||
cmdBuf[0] = (u32)savePath;
|
||||
|
@ -132,7 +238,6 @@ void LGY_switchMode(void)
|
|||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
#include "arm11/fmt.h"
|
||||
void debugTests(void)
|
||||
{
|
||||
const u32 kDown = hidKeysDown();
|
||||
|
|
|
@ -39,7 +39,7 @@ int main(void)
|
|||
|
||||
ee_puts("Reading ROM and save...");
|
||||
Result res;
|
||||
if((res = LGY_prepareGbaMode(false, SAVE_TYPE_SRAM_256k, "sdmc:/rom.gba", "sdmc:/rom.sav")) == RES_OK)
|
||||
if((res = LGY_prepareGbaMode(false, "sdmc:/rom.gba", "sdmc:/rom.sav")) == RES_OK)
|
||||
{
|
||||
#ifdef NDEBUG
|
||||
GFX_setForceBlack(false, true);
|
||||
|
|
Loading…
Reference in New Issue