Skip to content

Instantly share code, notes, and snippets.

@exelotl
Created July 3, 2020 19:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save exelotl/f990968d530c89bd14b65648a8892a7f to your computer and use it in GitHub Desktop.
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
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()
@exelotl
Copy link
Author

exelotl commented Jul 10, 2020

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment