SWI 0x2A — SoundGetJumpList¶
- Entry:
0x00002692(THUMB; SWI table stores0x00002693) - Status: verified (hardware-checked 2026-07-08: cycle counts and return registers measured on real GBA; struct layouts remain from static analysis)
Summary¶
Copies the BIOS sound driver's internal jump list — a table of 36 function
pointers — into a caller-supplied buffer, sanitizing each entry so that any value
that is not a valid in-BIOS code pointer is written as 0. Music-player/sequencer
code uses this vector to call the BIOS's sequencer command handlers and driver
entry points without hard-coding their addresses.
Parameters¶
| Reg | In | Meaning |
|---|---|---|
| r0 | ptr | Destination buffer for 36 words (144 bytes) |
Returns¶
| Reg | Out | Meaning |
|---|---|---|
| r0 | ptr | Advanced past the written table (buffer filled) |
Clobbered registers¶
r1, r2, r3, ip (r12).
Hardware audit (2026-07-08, canary r4–r12 + CPSR snapshot): caller-visible clobbers: r0 advanced past the 36 written words, r1 = 0, r3 = 0x23B1 leftover. 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¶
- Iterate 36 (
0x24) entries. The source table is at0x00003738. - For each source word, run a validity filter: an entry is kept only if it looks
like a legal BIOS code pointer (within the BIOS address range / low bits clear);
otherwise it is replaced with
0. - Store the (possibly zeroed) value into the destination buffer and advance both pointers.
Jump list contents (source @ 0x3738)¶
The 36 entries are the sequencer command handlers plus driver hooks. Recognisable
targets include the MIDI-track command interpreters (byte-fetch / relocation
handlers around 0x2665–0x271D), the note/velocity processors, and driver
routines such as the frequency-setup helper (0x170A), a channel-init helper
(0x159C), and internal mixer support functions (0x23B1, 0x23C7, 0x23E7).
Many slots point at a common default/unknown-command handler (0x2665), acting as
no-op stubs for unused command bytes. This is the table also referenced from
SoundArea+0x34 (installed by SoundDriverInit).
Edge cases & known bugs¶
- Entries failing the pointer-validity check become
0; a caller that blindly calls a zeroed slot would branch to0. The intent is that only defined command bytes index valid slots. - No bounds/validity check on the destination buffer (must be ≥ 144 bytes).
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).
1421 cycles (writes 36 words).
Open questions (need hardware verification)¶
- Precise semantics of the pointer-validity filter (exact address bounds accepted).
- The exact command-byte → slot mapping and the role of each of the 36 entries.
GBATEK cross-reference¶
GBATEK lists SWI 2Ah with little detail; this documents that it returns a 36-entry
sanitized function-pointer table sourced from 0x3738 (the sequencer command jump
table).