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:
profi200 2020-06-13 16:13:58 +02:00
parent aecbee03e7
commit 9002291e8a
No known key found for this signature in database
GPG Key ID: 17B42AE5911139F3
3 changed files with 111 additions and 6 deletions

View File

@ -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);

View File

@ -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();

View File

@ -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);