Created
July 3, 2020 19:20
-
-
Save exelotl/f990968d530c89bd14b65648a8892a7f to your computer and use it in GitHub Desktop.
GBA program that detects its own save type by searching for magic strings in ROM
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
asm """ | |
.balign 4 | |
.string \"SRAM_Vnnn\" | |
""" | |
import natu | |
irqInit() | |
irqEnable(II_VBLANK) | |
dispcnt = initDispCnt(bg0 = true) | |
# initialise text | |
tteInitChr4cDefault(bgnr = 0, initBgCnt(cbb = 0, sbb = 31)) | |
tteSetPos(20, 20) | |
tteWrite("ROM SAVE TYPE DETECTOR\n") | |
tteWrite("Press (A) to start\n\n") | |
template hword(a,b:char): uint16 = | |
ord(a).uint16 or ord(b).uint16 shl 8 | |
template word(a,b,c,d:char): uint32 = | |
(ord(a).uint32) or | |
(ord(b).uint32 shl 8) or | |
(ord(c).uint32 shl 16) or | |
(ord(d).uint32 shl 24) | |
const sram1 = word('S','R','A','M') | |
const sram2 = hword('_','V') | |
const eeprom1 = word('E','E','P','R') | |
const eeprom2 = hword('O','M') | |
const eeprom3 = hword('_','V') | |
const flash1 = word('F','L','A','S') | |
const flash2a = hword('H','_') | |
const flash3a = byte('V') | |
const flash2b = word('H','5','1','2') | |
const flash3b = hword('_','V') | |
const flash2c = word('H','1','M','_') | |
const flash3c = byte('V') | |
while not keyHit(KEY_A).bool: | |
keyPoll() | |
VBlankIntrWait() | |
tteWrite("Searching...\n") | |
const romSearchSize = 0x8000 # 8 KB | |
var romMem8 {.importc:"((u8*)(0x08000000))", nodecl.}: array[romSearchSize, uint8] | |
var romMem16 {.importc:"((u16*)(0x08000000))", nodecl.}: array[romSearchSize div sizeof(uint16), uint16] | |
var romMem32 {.importc:"((u32*)(0x08000000))", nodecl.}: array[romSearchSize div sizeof(uint32), uint32] | |
var saveKind = 0 | |
for i,w in pairs(romMem32): | |
if w == sram1: | |
if romMem16[i*2+2] == sram2: | |
saveKind = 1 | |
break | |
if w == eeprom1: | |
if romMem16[i*2+2] == eeprom2 and romMem16[i*2+3] == eeprom3: | |
saveKind = 2 | |
break | |
if w == flash1: | |
if romMem16[i*2+2] == flash2a and romMem8[i*4+6] == flash3a: | |
saveKind = 3 | |
break | |
if romMem32[i+1] == flash2b and romMem16[i*2+4] == flash3b: | |
saveKind = 3 | |
break | |
if romMem32[i+1] == flash2c and romMem8[i*4+8] == flash3c: | |
saveKind = 4 | |
break | |
tteWrite("DONE!\n") | |
case saveKind | |
of 1: tteWrite("Save type = SRAM\n") | |
of 2: tteWrite("Save type = EEPROM\n") | |
of 3: tteWrite("Save type = FLASH512\n") | |
of 4: tteWrite("Save type = FLASH1M\n") | |
else: tteWrite("Save type = None\n") | |
while true: | |
VBlankIntrWait() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Note: this program isn't particularly useful - it's just a proof-of-concept to see how long it would take to detect the save type on hardware, by searching for the magic strings as outlined in GBATEK - GBA Cart Backup IDs.
If we search the entire possible ROM space, it takes far too long (30 seconds or more), but by restricting the search to only the first 8kb, we can determine the save type in just a few milliseconds, which is barely noticeable.