SIDin #14 — Inside Hunter's Moon (Martin Walker's sound-effects engine, reverse-engineered, 2015)
Tognon reverse-engineers the sound-effects engine of hunters-moon (Thalamus, 1987) — code, graphics and effects by Martin Walker, music by matt-gray — because "the hives seems to be true living": the most realistic game effects he knows turn out to come from a tiny table-driven engine that uses up to all three voices per effect, which is also, he suggests, why no music plays during the game. Rights stay with Walker.
Key claims#
- Structure:
InitEngineclears the 25 SID registers, sets volume$0Fand zeroes the per-voice indexes; a sound is started by storing a table index intoindexInTable(+0, +7, +14 for the three voices) — "That's all."playSound, called once per frame, runssetUpSoundfor X = 0, 7, 14: a non-zero index triggersoutSidValue(load every register from the tables, then clear the index), thenmakeLoopandtestAndMakeEffectkeep the effect alive (sid-player-routine). - Thirteen tables of 32 entries, one column per effect index:
tableAD,tableSR,tableWave(pulse width packed asXY→$0YX0),tableFreqLo/Hi,tableControlReg(start),tableControlReg2(written when the loop counter runs out),tableLoopValue,tableFreqLoStep/HiStep,tableFreqEffect(1 add, 2 subtract, 3 looped add, 4 looped subtract, 5 add while looping then subtract, 6 subtract then add),tableWaveStep(pulse step, bouncing between$08xxand$0Exxlike Gray's player),tableFreqEffect2(1 swap the frequency low and high bytes, 2 subtract the step andEOR #$DF, 3 subtract andEOR #$12, 4 add$D41B AND $0F— the noise of oscillator 3 — to the high byte) (randomization-and-probability). - Sixteen effect routines dispatched through a PSID "song" number 1–16 (
lowTable/highTable): explosion, star cell, choose system, alternative choose, bell, short tick, long drill, plonk, fire, bell 2, bonus, launching, after bonus, stage start, middle, enemy explosion. Each just stores one to three indexes, e.g.soundBell=$16,$16,$17;soundFire=$12on voice 1 only;soundPlonk=$07and$04on voices 2–3. "You can so have the user that fire the enemy and at the same time other sound effects being played." - Long effects:
soundExplosion(indexes$0C/$0D/$0E) andsoundStarCellsetpreLongEffect; the next framelongEffect=$32(50 frames) during which voices 2–3 have their indexes cleared each frame, so nothing can interrupt the effect;flagExplosion/flagStarCelllet the game request them asynchronously. - Fire (
$12): AD$00, SR$30, control$11→$10, loop 6, frequency$E0F0, effect2 = 1 — "a triangle sound that change frequency from two fixed value" by swapping the bytes each frame. Plonk: voice 2 index$07with control$15(triangle + ring modulation), SR$98, frequency$F400, high-byte step$0D, effect 5 (add for 8 frames, then subtract) — "a vibrato like sound, but is uses ring modulation"; voice 3 index$04, silent triangle$10, frequency$2011, step$01, effect 6 — the modulator, "opposite to the one used into the other voice" (ring-modulation-and-sync). - The listing is wrapped as a PSID v2 ("Hunter's Moon / Martin Walker / 1987 Thalamus", 16 songs, init
initSongs, playplaySound, code at$0900, "extracted from original TAP"), so every effect can be auditioned in a SID player (sid-format). Tognon marks oddities in the voice-state block ("[Missing!!]", "[Voice 1!!]") and a "missing store????" inaddFreq(the low byte is written to the SID but not kept). - The game: "one of the best game ever", "128 levels", hard at first "but it has the right feeling".
Practical takeaways#
- A complete SFX engine in about 250 lines: per-effect columns for ADSR, waveform, pulse, pitch, a loop length and two effect selectors, plus a frame routine. The two-control-register trick (start waveform, then a second one — usually gate off — after N frames) is the same idea as an instrument's gate-off frame (instrument-design).
- Realism from register games rather than samples: byte-swapped frequencies,
EORscrambles of the high byte, oscillator-3 noise added to pitch, ring-modulated vibrato pairs. - Budget effects by voices: allow one-voice effects to overlap and reserve all three for the big ones — which may cost the in-game music (channel-interleaving).
Notable quotes#
"Before I reverse engineering the Martin code, I was sure it was a very complicated engine as the sound is the most realistic you can find into a game. But the engine is simple and the secret is just how the sid is manipulated in a convenient way :)"
"He uses even more SID voices for some effects … and maybe this is why music is not played during game play."
Relevance to the wiki#
Creates hunters-moon; a documented 1987 sound-effects engine next to the music drivers on sid-player-routine; ring-modulated and randomised effect recipes for ring-modulation-and-sync and randomization-and-probability; context for matt-gray's 1987 Thalamus credit (see also s-sidin15-serpent-demo-player, where Tognon finds leftovers of the Hunter's Moon tune in the Serpent Demo file).
To verify#
- Tognon states the fire effect alternates between "0Eh and 0Fh"; the table gives
$E0F0, so the swap alternates$E0F0and$F0E0— his figures look like the nibbles (unverified). - Whether Martin Walker's engine also drove the title-screen music is not discussed; the article says the music "is played using Matt Gray engine".
Pages touched#
hunters-moon · matt-gray · matt-gray-player · sid-player-routine · ring-modulation-and-sync · randomization-and-probability · instrument-design · channel-interleaving · sid-format · sidin · sound-effects