Skip to content

SWI 0x0D — GetBiosChecksum

  • Entry: 0x00000378 (ARM)
  • Status: verified (hardware-checked 2026-07-08: cycle counts and return values measured on real GBA via the worker ROM)

  • Computed value for this BIOS (gba_bios.bin, 16384 bytes): 0xBAAE187F

Summary

Returns a fixed 32-bit checksum of the BIOS ROM: the 32-bit wrap-around sum of all 4096 words (16 KiB) of the BIOS. It is a constant for a given BIOS image and is used by copy-protection / anti-piracy checks to confirm code is running on a genuine GBA BIOS. For the retail GBA BIOS this value is 0xBAAE187F.

Parameters

None.

Returns

Reg Out Meaning
r0 u32 BIOS checksum = sum of all 16 KiB of BIOS words (mod 2^32). 0xBAAE187F for retail GBA

Clobbered registers

r1, r2, r3, r12 (ip) are scratch. Side effect: the routine writes CPSR each iteration (see Algorithm) leaving the CPU in System mode with IRQ/FIQ disabled; the SWI return path is responsible for restoring the caller's mode/flags.

Hardware audit (2026-07-08, canary r4–r12 + CPSR snapshot): caller-visible clobbers: r0 = checksum, r1 = 1, r3 = 0x4000; r2 preserved. CPSR identical before/after — the internal System-mode window does not leak (checklist item resolved). r2, r4–r12, r13, and CPSR (flags and mode) came back bit-identical on every tested path. r11/r12 are explained by the SWI dispatcher (it pushes {r11, r12, lr} — see 10_irq_boot_and_iwram.md) and CPSR by the SPSR restore on return; r2 and r4–r10 must be preserved or restored by the routine itself — where a static note above claims r2 is destroyed, the hardware disagrees at the caller level. Raw data: results/clobber_audit_pass2.csv.

Algorithm

Accumulate r0 = 0, use r3 as a byte offset starting at 0. Loop: 1. ldm r3!, {r2} — load the next BIOS word and advance the offset by 4. 2. msr CPSR_fc, #0xDF — set control/flag byte of CPSR to 0xDF every iteration: mode = 0x1F (System), F=1 and I=1 (FIQ+IRQ disabled), T=0. This forces a fixed privileged, interrupt-free context while summing (a copy-protection hardening detail). 3. r0 = r0 + r2 — add the word. 4. lsrs r1, r3, #14 — test whether the offset has reached 0x4000 (16384). While r3 >> 14 == 0 (offset < 0x4000) the loop repeats.

So exactly 4096 words spanning the full 16 KiB BIOS are summed with 32-bit wrap-around. Directly computing this over gba_bios.bin gives 0xBAAE187F, confirming this is the genuine retail GBA BIOS image.

Edge cases & known bugs

  • The value is a hard constant per BIOS build; the NDS GBA-mode BIOS returns a different value (0xBAAE1880), which anti-piracy code uses to distinguish hardware.
  • The msr writing System mode with interrupts disabled is an intentional side effect; callers must not rely on CPSR mode being preserved across the raw routine (the SWI dispatcher restores state on movs pc, lr return).

Cycle count

Hardware-measured net CPU cycles (worker-ROM harness, TM0/TM1 cascade at F/1, 13-cycle baseline subtracted; identical across 3 runs — see 02_hardware_verification_checklist.md § Measurement setup).

41010 cycles, fully constant. r0 = 0xBAAE187F confirmed on hardware, matching the value computed from the dumped binary.

Open questions (need hardware verification)

  • Confirm on hardware that the checksum SWI returns exactly 0xBAAE187F and that the transient System-mode / interrupts-disabled window is invisible to callers after the SWI returns.

GBATEK cross-reference

Agrees with GBATEK: returns 0xBAAE187F (GBA) / 0xBAAE1880 (NDS). Adds the exact summation range (all 4096 words, loop bounded by offset reaching 0x4000) and documents the per-iteration msr CPSR_fc,#0xDF copy-protection side effect, which GBATEK does not detail.