Vendored 86Box EMU8000 core (GPL-2, emu8k.cpp/.h + shim) plus vweawe.cpp: two cards at the production addresses (0x620/0x640 register triplets), rear-card DSP/mixer stub at 0x240, synthesis on an autonomous render thread with direct winmm output so sustained voices ride through emulation-thread stalls (RIO staging retries) like the real silicon did. WC sample-counter interpolation between render chunks keeps HMI SOS busy-waits fast. VWE_AWE32/VWE_AWE_ROM/VWE_AWE_RAM_KB/VWE_AWE_SHIFT/ VWE_AWE_LEAD_MS/VWE_AWE_DUMP/VWE_AWE_LOG env knobs. emulator/roms: the AWE32 1MGM GM ROM dumped from our own pod card (SF2) plus the reconstructed raw image the emulated EMU8000 loads. The HMI driver refuses the AUDIO*.RES SoundFont upload without it (banks declare irom=1MGM) -- that was the root cause of the first silent runs; full debug chain in SOUND-NOTES.md. Repo serves the pod-owner community only. .gitignore: drop the ROM excludes and un-ignore ALPHA_1/ and sda4/ (committed separately). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
9.7 KiB
Sound subsystem — recon & plan
Goal: bring the pod's audio up in the DOSBox-X fork, faithful to the production hardware: two AWE32 ISA cards driving four cockpit speakers (front pair + rear pair).
What the production system actually was (recon 2026-07-04)
-
Cards (
REL410/BT/SETENV.BAT:158,VGL_LABS/PARAMETR.BAT:172):AWE_FRONT = A220 I5 D1 H5 P330 T6AWE_REAR = A240 I7 D3 H6 P300 T6Sound is enabled by SETENV arg 3 =s(n= NOSOUND — our current emulator confs runcall setenv.bat r s n g, i.e. sound explicitly OFF). Mixer preset viac:\sb16\sb16set+audio\ctmix.cfg(not in the ALPHA_1 image — lived on the pod's local C:);icom.cfgvariant opens line-in on the front card whenL4INTERCOM=ON(analog intercom mix).AWE_MASTER_VOLUME/c:\setvol.bat= per-pod volume.
-
The game does NOT stream PCM through the SB16 DSP. The audio engine (
CODE/RP/MUNGA_L4/L4AUD*.CPP|HPP, shared MUNGA "Audio Manager" brick, 1995) is MIDI-only wavetable synthesis:- HMI Sound Operating System MIDI layer (
sosm.h,sosMIDISendMIDIData),_MIDI_DRIVER_TYPE _MIDI_AWE32, driver linked into BTL4OPT.EXE (sosMIDIInitDriverstring present; no external .MDI). - Each
AudioCardparses its BLASTER-style env var (AWE_FRONT/AWE_REAR-> srcAddx/irq/dma/mpuAddx/emuAddx) and drives the card's EMU8000 sampler: note on/off, program change, pitch bend, and the AWE NRPNs (pitch 16, filter cutoff 21, vol attack 11). 32 voices, 16 channels per card.LoadSBK()uploads SoundFont banks into card sample DRAM. AudioHardware=frontCard+rearCard.
- HMI Sound Operating System MIDI layer (
-
All sound content is SoundFont banks:
REL410/BT/AUDIO/AUDIO1.RES(3.7MB) andAUDIO2.RES(3.4MB) are RIFFsfbk(SBK/SF1,isng= EMU8000) — renamed SoundFonts.AUDIO.INI [AudioResources]loads BOTH into EACH card. Both banks per card ⇒ >7MB samples ⇒ the pod AWE32s had DRAM upgrades (stock is 512KB); emulate with 8MB. -
3D audio is computed in software by the game's AudioRenderer (
AUDIO.INI [AudioRenderer]): amplitude + HF rolloff with knees, doppler (speed_of_sound 250), ITD 1.5ms, source compression, reverb scale — rendered by steering wavetable voices per ear across the front/rear cards. Quad positional audio, 1995. -
HARDWARE CONFIRMED (Cyd, 2026-07-04): pulled a card from a cockpit — they are indeed AWE32s, each with 2× 30-pin memory SIMMs fitted (the predicted DRAM upgrade; both banks per card ⇒ likely 2×4MB SIMMs = 8MB). Also confirmed: the intercom hardware was removed from the cockpits at some point — the intercom path (line-in mix,
icom.cfg,L4INTERCOM) is documented here for the record but will NOT be restored; plan item 8 is closed as won't-do (mic/comms, if ever wanted, would be a new host-side feature, not a restoration). -
Period test suite exists:
VWETEST/VGLTEST/— TEST.BAT, SETENV1-9, and diagnostic SBKs (PINKNOIS pink noise, SPKPLACE/SPKBASE placement, QCHNTSTF/QCHNTSTB quad front/back, phase tests) + PINKNOIS.TXT procedure. This is VWE's own speaker validation battery — use it to validate the emulation before the game.
The gap
DOSBox-X emulates one SB16 (DSP/mixer/OPL) and an MPU-401 — but no
EMU8000, and no second card. The game's entire audio path is EMU8000
register programming at base+0x400/+0x800/+0xC00 (0x620/0xA20/0xE20 and
0x640/0xA40/0xE40). Nothing will sound until the EMU8000 exists.
Plan
- EMU8000 core in the fork (the big rock). Port the emu8k core from
86Box (GPL-2, same license as DOSBox-X; mature implementation incl.
sample-RAM read/write via SMALR/SMALW, 32 voices, filters, envelopes,
chorus/reverb). Two instances (front/rear), I/O hooks at both cards'
EMU8000 port triplets, 8MB sample DRAM each, each mixed into its own
DOSBox mixer channel (
AWEFRONT,AWEREAR) at 44.1kHz. Config via env or conf section, following the vpxlog device pattern. - Second-card detection plumbing. Keep DOSBox-X's native SB16 as the
front card — conf
[sblaster] sbtype=sb16 irq=5 dma=1 hdma=5to matchI5. Add a minimal stub at 0x240 (DSP reset/version 4.xx + mixer register file) so probes/sb16set succeed for the rear card. No DMA audio needed anywhere (MIDI-only engine; SB IRQ/DMA unused — I5/I7 conflicts are a non-issue in emulation). - Source verification pass (before/while coding): read
L4AUDIO.CPP/L4AUDRND.CPP/L4AUDRES.CPPfor the SOS init sequence (timer rate, card detection order, failure modes), the exact SBK load path, and whatInitMIDIReceive/GetMIDIByte(MPU input!) is used for in pod mode — open question. - Enable sound: gauge confs arg3
n→s. sb16set calls will error harmlessly (not in image) — emulated mixer defaults stand in; optionally add period SB16 utils to aSB16/dir later for authenticity. Do NOT flip the flag before step 1 lands (unknown hang risk probing absent EMU8000 — or do one throwaway run first to record the failure mode). - Validate with VGLTEST in the emulator: pink noise per speaker, quad front/back tests — the way VWE techs did it.
- In-mission validation: arena1 — engine pitch vs throttle (NRPN), weapons, front/rear pan while turning past sources. Archive captures via DOSBox-X mixer WAV record.
- Quad host output (cockpit build): start with front+rear summed to stereo; then map to a 4.0 SDL output or send the rear card's channel to a second host audio device for the physical rear pair.
Intercom— closed, won't-do: the intercom hardware was removed from the cockpits (confirmed 2026-07-04). Remaining deferred items: MPU MIDI-receive consumer, AUDIOMR.INI (mission-review audio profile) differences.
STATUS 2026-07-04: FIRST SOUND ACHIEVED (steps 1-4 done)
Implemented in the fork: vendored 86Box EMU8000 core (emu8k.cpp/.h, GPL-2)
vweawe.cppglue (two cards at 0x620/0x640 triplets, per-card mixer channels AWE32F/AWE32R, 0x240 DSP/mixer stub,VWEAWE_Initfrom sdlmain, env: VWE_AWE32=1, VWE_AWE_RAM_KB, VWE_AWE_ROM, VWE_AWE_SHIFT, VWE_AWE_DUMP (s16 stream dump), VWE_AWE_LOG=1 (port trace + 10s activity reports incl. smldW upload counter + active voices + peak)).
Debug chain that got to sound, for the record:
- Game run: SOS driver alive, EMU8000 detected, DRAM probe PASSES (FFFF/AAAA/5555 bank scan verified in the SM trace), notes played (voices>0) but smldW=99 -- SoundFont upload never ran, voices played zeroed DRAM = silence.
- AWEUTIL /S (production boot runs it per card, PARAMETR.BAT:181-186) hung polling WC: first lead. WC itself verified good after adding block-interpolation (emu8k_shim_wc_extra; killed the 268M-poll storm).
- Root cause: the banks declare
irom=1MGMand the HMI AWE32 driver (and AWEUTIL) verify the GM ROM before accepting SBKs. Emulated cards had a zeroed ROM -> silent rejection. - Fix: reconstructed a 1MB ROM image from a user-supplied 1MGM.SF2 (smpl
chunk 1,047,588 B end-aligned into 1MB + ID words 0x314D/0x474D at word
offsets 2/3) ->
VWE_AWE_ROM=<path>-> both cards uploaded 3,513,581 sample words (full 7MB) and the mission plays real audio on both channels (front peak 11.8k, rear hit full-scale 32768).
Architecture rev 2 (same day): autonomous synth thread. User feedback: sound great, but RIO stalls (staging-phase drops pre-date sound; the game can't service the board while loading — button-press resync is the player ritual) made audio chop, because DOSBox's mixer renders on the emulation thread. Fix: synthesis moved to a dedicated render thread with its OWN winmm output (10ms slots, VWE_AWE_LEAD_MS queue, default 80ms), EMU8000 state guarded by one critical section against guest port I/O. Like the real silicon, sustained voices keep sounding through emulation-thread stalls. Both cards sum to one stereo stream for now (user runs a headset); per-card devices for the 4-speaker cockpit later. Note: our audio no longer routes through the DOSBox mixer (its volume controls don't affect it). Also: first render-path rev needlessly memset 64KB/card/ms — fixed (clear only consumed region) before the thread move; both changes reduce emulation-thread load vs the first-sound build.
Follow-ups:
- ROM provenance settled:
emulator/roms/1mgm.sf2was dumped from one of OUR OWN pod AWE32 cards; the repo serves the pod-owner community only, so it is committed along with the reconstructedemulator/roms/awe32.raw(recipe: SF2 smpl chunk end-aligned into 1MB + ID words 314D/474D at word offsets 2-3). PointVWE_AWE_ROMatemulator\roms\awe32.raw. The reconstruction may misalign ROM-resident GM presets (VWE banks are RAM samples, unaffected) -- a raw linear re-dump of the ROM chips would perfect it if GM playback ever matters. - Rear card hit peak 32768 = clipping; consider VWE_AWE_SHIFT=1 or mixer channel trim once real gameplay levels are assessed.
- Upload pacing is ~32K words/s (driver polls between words) -> adds ~2min per card to boot. Optimization candidate later.
- Re-enable
aweutil /sin the boot sequence now that a ROM exists (currently skipped in the scratch conf) -- production authenticity. - Promote the scratch gauge_sound.conf changes into the repo gauge confs
once validated: [sblaster] irq=5, production DIAGNOSE(+AWEUTIL) init
block, setenv arg3
s.
Risks / notes
- emu8k port: integration surface is small (ISA I/O + mixer callback), but verify the driver's DRAM size probe and chip ID/revision reads pass.
- HMI SOS hooks the PIT for MIDI timing — routine under DOSBox.
- Ran fine under 32RTM/DPMI on real pods, so no new protected-mode risk.
- RP (Red Planet) uses the same MUNGA audio brick and its own AUDIO*.RES — everything here carries over.