SWI 0x01 — RegisterRamReset¶
- Entry:
0x000009C2(THUMB; table lists0x000009C3with the THUMB low bit set) - Status: verified (hardware-checked 2026-07-08: fixture-driven runs on real GBA via the worker's no-blacklist opcode; see Hardware verification section)
Summary¶
Selectively clears blocks of RAM and resets groups of I/O registers to a known
state, chosen by an 8-bit flag mask in r0. RAM clears are done by zero-filling
via the BIOS CPU-fill routine (fixed zero source). Two things happen
unconditionally, regardless of the flags: the display is forced blank
(DISPCNT := 0x80) at entry, and a pair of serial-I/O register writes occur —
the source of the well-known RegisterRamReset SIO/register-corruption bug.
Parameters¶
| Reg | In | Meaning |
|---|---|---|
| r0 | reset flag mask | Bitmask selecting which regions/registers to reset (see table). |
Flag bits (each independently selectable):
| Bit | Value | Effect |
|-----|-------|--------|
| 0 | 0x01 | Zero-fill 256 KB external work RAM at 0x02000000 (0x40000 bytes) |
| 1 | 0x02 | Zero-fill on-chip work RAM at 0x03000000, 0x7E00 bytes — i.e. all 32 KB except the top 0x200 reserved for stacks/BIOS state |
| 2 | 0x04 | Zero-fill 1 KB palette RAM at 0x05000000 |
| 3 | 0x08 | Zero-fill 96 KB VRAM at 0x06000000 (0x18000 bytes) |
| 4 | 0x10 | Zero-fill 1 KB OAM at 0x07000000 |
| 5 | 0x20 | Reset serial I/O (SIO) registers |
| 6 | 0x40 | Reset sound registers |
| 7 | 0x80 | Reset "all other" registers (display, DMA, timers, IE/IF/IME, etc.) |
Returns¶
No return value; registers restored except scratch.
Clobbered registers¶
r0–r7, lr used internally (THUMB, saved/restored via the routine's
push/pop). Uses one stack word as the zero fill-source.
Algorithm¶
- Unconditionally write
0x80toDISPCNT(0x04000000), forcing the screen blank for the duration of the reset. - Prepare a zero word on the stack to use as the fixed fill source, and a
CPU-fill control value (
0x85000000OR'd with the word count) that drives a fixed-source 32-bit fill through the shared fill routine near CpuFastSet. - For each flag bit in
r0, if set, zero-fill the corresponding RAM block or reset the corresponding register group (see table). RAM sizes in words: EWRAM0x10000, IWRAM0x1F80, palette0x100, VRAM0x6000, OAM0x100. - Bit 7 zero-fills large runs of the display/DMA/timer register file
(
0x04000000–0x0400005Fregion) and the interrupt/system registers around0x04000200(IE/IF/WAITCNT/IME), plus a couple of undocumented slots (e.g.0x040001E2,0x04000410). - Bit 6 reprograms the sound registers (SOUNDCNT block at
0x04000080, master-enable, and masks SOUNDBIAS at0x04000088to its low bits) using the constant0x880E0000.
Real constants observed: DISPCNT 0x04000000 := 0x80; RAM bases
0x02000000/0x03000000/0x05000000/0x06000000/0x07000000; IWRAM clear size
0x7E00 bytes; fill control 0x85000000; sound reset word 0x880E0000;
IE/IF/IME block base 0x04000200.
Edge cases & known bugs¶
- Unconditional SIO/register corruption (the classic bug). Regardless of
which flags are passed, the routine performs two writes into the serial-I/O
register block: it stores the halfword
0x8000to0x04000114and the byte0x07to0x04000120(SIODATA32 area). These occur even if bit 5 (Reset SIO) is clear, so calling RegisterRamReset for an unrelated purpose (e.g. clearing VRAM) will silently disturb serial/SIO state. This matches the well-known GBATEK caveat that RegisterRamReset must be used with care around serial I/O. - DISPCNT is always forced blank on entry; callers relying on display state
must restore
DISPCNTafterward. - Bit 1 deliberately preserves the top
0x200bytes of IWRAM (stack pointers, IRQ handler pointer at0x03007FFC, IntrWait flag word at0x03007FF8, etc.), so it is safe to call from normal code without destroying BIOS state.
Hardware verification (2026-07-08)¶
Fixture-driven runs via the worker's no-blacklist opcode (swf), with
wake sources / handlers installed through CpuSet pokes. Raw data:
results/blacklist_fixtures1.csv.
Per-flag runs with seeded readable registers and palette/VRAM/OAM sentinels
(results/blacklist_rrr.csv):
| flags | raw cycles | observed effect |
|---|---|---|
| 0x00 | 198 | no observable register change; all seeds survived |
| 0x04 | 934 | palette cleared; nothing else |
| 0x08 | 64774 | VRAM cleared (0x6000-word fill dominates); nothing else |
| 0x10 | 678 | OAM cleared; nothing else |
| 0x20 | (response lost) | SIO register block reset killed the link permanently — remote recovery (nudge/sync) failed; physical power-cycle + re-multiboot required |
| 0x40 | 401 | sound only: SOUND1CNT_H→0, SOUNDCNT_L→0, SOUNDCNT_H readback 0x030E→0x000E (consistent with the static 0x880E write), SOUNDCNT_X→0; a SOUNDBIAS seed of 0x0155 survived |
| 0x80 | 431 | BG0/BG1CNT, WININ/WINOUT, BLDCNT/BLDALPHA, DMA0CNT_H, TM3CNT_H, KEYCNT, IE, WAITCNT all →0; sound registers untouched |
The unconditional 0x8000→0x04000114 / 0x07→0x04000120 writes are not
observable via readback (0x114 reads as 0; SIODATA32 is overwritten by the
link protocol immediately), so they remain a static-analysis finding. Bits
0/1 (EWRAM/IWRAM clear) were deliberately not run — they would erase the
worker itself.
Cycle count¶
flags=0: 198 cycles; palette 934; VRAM 64774; OAM 678; sound 401; other-regs 431 (raw). See the table above.
Open questions (need hardware verification)¶
- Confirm the exact register-level meaning and intent of the unconditional
writes to
0x04000114(0x8000) and0x04000120(0x07), and enumerate the full set of registers touched by bit 7 on real hardware. - Confirm the precise sound-register values left by bit 6.
GBATEK cross-reference¶
Flag semantics match GBATEK SWI 01h RegisterRamReset. This doc adds the concrete
IWRAM clear size (0x7E00), the forced DISPCNT := 0x80, the fill-control
constant, and the exact addresses/values of the unconditional SIO writes behind
the documented register-corruption bug.