Skip to content

SWI 0x1A — SoundDriverInit

  • Entry: 0x00001664 (THUMB; SWI table stores 0x00001665)
  • Status: verified (hardware-checked 2026-07-08: cycle counts and return registers measured on real GBA; struct layouts remain from static analysis)

Summary

Initializes the BIOS software sound mixer ("Direct Sound" PCM engine). The caller supplies a pointer to a SoundArea work buffer (a large zero-able RAM struct, ≈ 0xFB0 bytes). The routine: - stores the SoundArea pointer at fixed IWRAM address 0x03007FF0 (all later sound SWIs find the work area through this pointer), - zero-fills the work area, - programs the APU registers and the two sound-FIFO DMA channels (DMA1 → FIFO A, DMA2 → FIFO B) to stream the mixer's PCM output buffers, - installs default function-pointer hooks (mostly no-op stubs) and the sequencer command jump-table pointer, - writes the SoundArea identity word and calls the internal mode/frequency setup with a default sampling rate, - resynchronises the FIFO DMA to the scanline/V-count timing before returning.

Parameters

Reg In Meaning
r0 ptr Pointer to the SoundArea work buffer to initialize (WRAM, ~0xFB0 bytes)

Returns

Reg Out Meaning
SoundArea initialized; global sound pointer set at 0x03007FF0

Register/DMA programming performed

  • SOUNDCNT_X (0x04000084) ← 0x008F : master sound enable (bit7) set.
  • SOUNDCNT_H (0x04000082) ← 0xA90E : PSG master volume 100%, Direct Sound A & B at 100%, DS-A routed right + FIFO-A reset, DS-B routed left + FIFO-B reset, both Direct Sound timers = Timer 0.
  • SOUNDBIAS+1 (0x04000089) : bit 6 (SOUNDBIAS bit 14, amplitude-resolution / sampling-cycle) set, low bits preserved.
  • DMA1: DMA1SAD (0x040000BC) ← SoundArea + 0x350 (PCM mix buffer A); DMA1DAD (0x040000C0) ← 0x040000A0 (FIFO A); DMA1CNT_H cleared then later enabled by the VSync routines.
  • DMA2: DMA2SAD (0x040000C8) ← SoundArea + 0x980 (PCM mix buffer B); DMA2DAD (0x040000CC) ← 0x040000A4 (FIFO B); DMA2CNT_H cleared.
  • Work-area pointer written to 0x03007FF0 (offset +0x30 of the block based at 0x03007FC0).

Inferred SoundArea struct layout

Base = SoundArea pointer. Identity word 0x68736d53 ("Smsh") marks a valid/ready area and doubles as a re-entrancy lock (sound SWIs bump it by 1 while running and restore it on exit; a mismatch makes the SWI a no-op).

Offset Size Field (inferred) Notes
0x00 u32 ident / lock set to 0x68736d53; used as busy guard
0x04 u8 pcmDmaCounter V-blank countdown, reload from +0x0B
0x05 u8 reverb set by SoundDriverMode (0..0x7F)
0x06 u8 maxChans / active PCM channel count init = 8
0x07 u8 masterVolume init = 15 (0x0F)
0x08 u8 freq (sample-rate index) set by mode helper
0x09 u8 mode/misc bits
0x0B u8 pcmDmaPeriod frames per DMA buffer cycle; reload for +0x04
0x10 s32 pcmSamplesPerVBlank from freq table (96..704)
0x14 s32 pcmFreq / derived rate
0x18 s32 divFreq / derived
0x1C ptr CGB(PSG) channel array (4 × 0x40) used by SoundChannelClear
0x20 u32 MPlayMain-hook enable flag 0 by default
0x24 ptr MPlayMain hook function 0 by default
0x28 ptr main-update hook init = no-op stub (0x1708)
0x2C ptr hook init = stub
0x30 ptr hook init = stub
0x34 ptr sequencer command jump table init = 0x3738 (BIOS table)
0x38 ptr VSync/aux hook function init = 0x2424
0x3C ptr hook init = stub
0x50 + i*0x40 0x40 PCM channel[i], i = 0..11 12 mixer voices; status byte at +0
0x350 ~0x630 PCM mix buffer A (→ FIFO A via DMA1)
0x980 ~0x630 PCM mix buffer B (→ FIFO B via DMA2)

The 12 PCM channels occupy 0x50..0x350 (12 × 0x40). "Direct Sound channels" here means software mixer voices, not the two hardware FIFOs; SoundDriverMain mixes all active voices down into the two PCM buffers each frame.

Algorithm

  1. Save the SoundArea pointer; disable DMA1/DMA2 control high halfwords.
  2. Program SOUNDCNT_X, SOUNDCNT_H, SOUNDBIAS resolution bit, and DMA source/dest as listed above; store the mix-buffer-A address into DMA1SAD.
  3. Store the SoundArea pointer to 0x03007FF0.
  4. Zero-fill the work area via CpuSet (memfill of ~4016 bytes / 1004 words).
  5. Set defaults: maxChans = 8, masterVolume = 15, hook slots to stubs, jump-table pointer = 0x3738, VSync hook = 0x2424.
  6. Call the internal mode/frequency helper (0x170A) with default frequency index (bits 16–19 = 4 ⇒ ~13379 Hz), which fills pcmSamplesPerVBlank/pcmFreq and derived timer/period fields, waits for a safe V-count window, and enables the FIFO DMA.
  7. Write the identity word 0x68736d53 to offset 0 and return.

Edge cases & known bugs

  • The work area must be at least 0xFB0 bytes and word-aligned; the fill and the buffer offsets assume this.
  • The routine does not check the caller pointer for validity.

Clobbered registers

Hardware audit (2026-07-08, canary r4–r12 + CPSR snapshot): caller-visible clobbers: r0 = 0x68736D53 ('Smsh' ident), r1 = 0x9F, r3 = 0x170 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.

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).

64325 cycles, constant across runs (work-area clear dominates).

Open questions (need hardware verification)

  • Exact meaning of offsets 0x14/0x18 (pcmFreq vs. divFreq) and the derived timer reload written by the 0x170A helper.
  • Precise per-channel (0x40-byte) field layout — see SoundDriverMain.
  • Whether maxChans default 8 is later overridden by SoundDriverMode.

GBATEK cross-reference

Fills in the SoundArea/"SoundInfo"/work-area layout that GBATEK leaves largely undocumented, plus the exact SOUNDCNT/DMA programming and the 0x03007FF0 global pointer convention.