Skip to content

SWI 0x2A — SoundGetJumpList

  • Entry: 0x00002692 (THUMB; SWI table stores 0x00002693)
  • 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

  1. Iterate 36 (0x24) entries. The source table is at 0x00003738.
  2. 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.
  3. 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 0x26650x271D), 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 to 0. 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).