Audio extraction: first playable exports
2026-09-18. Open the listening gallery.
For later work, see the hardware and Roland investigation, including custom instruments, missing percussion, independent loop timing and hand-corrected FLAC references.
Six Roland SCC-1 arrangements now export as standard MIDI, with Ogg Vorbis listening previews. The gallery offers both plus source event/loop metadata. These are the six music groups' SCC-1 variants, not 30 distinct songs. Their original song titles remain unknown. Scene assignments and chained briefing selections are now listed in the scene and music catalogue. Group 1 is startup and menu music (see below).
The Ogg files are now rendered by FluidSynth with FluidR3 GM, not recordings of Darker or emulation of the SCC-1's exact instrument set. Their purpose is to hear the recovered arrangements. The preview provenance records the soundfont hash, sample rate and encoding. Original hardware timbre, game volume/fades, interrupt quantisation and repeated playback are not claimed.
Correction: DC saturation in the first preview render
Listening to the startup preview showed that it deteriorated around 11 seconds and provided an Audacity screenshot showing its left channel driven up to full scale. Decoded Ogg measurements confirmed this. By the latter part of the old render, the output was almost entirely positive full-scale DC. Smaller drifting offsets were also present in several other tracks.
Controlled rerenders of the same MIDI and soundfont reproduced the problem with TiMidity even with reverb and chorus disabled. FluidSynth did not reproduce the saturation. This isolates a preview-synthesis-path problem; the precise TiMidity failure is not yet diagnosed. The music decoder was not changed to reinterpret volume as pitch or vice versa: the original driver's command 95 emits MIDI pitch bend and command 96 emits controller 7 (volume), as already checked against its instruction output.
All six listening copies were regenerated with FluidSynth and encoded directly
to Ogg Vorbis, with no DC blocker or other corrective filtering. MIDI and
source-event metadata remain unchanged. The synthesis settings and absence of
filtering are recorded in variants/previews.json.
The individual variants/group-N-scc1-check.json reports contain both source PCM
and final Ogg measurements, per channel in five-second windows. Checks guard
against large DC offsets and clipping; small residual synthesis offsets are
retained. These checks detect this failure class; they do not validate musical
interpretation or original hardware timbre.
The gallery includes a content-hash query on each audio URL to avoid stale
cached previews after regeneration.
Other hardware variants
All thirty native sequences and their five drivers now have a dedicated export and comparison page, including source command inventories. See hardware differences and conversion limits. Only the SCC-1 versions currently have verified standard MIDI conversions. The other four hardware variants now have provisional MIDI/GM auditions, selectable in the gallery; their hardware-specific command mappings remain unverified.
What the executable establishes
The game selects driver resource 33 + driver_index at 9C66–9C74. Music loader
0AAE–0AC1 selects 38 + 5*music_group + driver_index, appends it to the loaded
driver and invokes driver API function 4 with song number 1 (0AC4–0AC7).
Thus the five-way grouping is established by code, not merely similar headers.
| Group | SCC-1 resource | Sequence tracks | Initial BPM | Division | Loop-end tick |
|---|---|---|---|---|---|
| 1 | 00/39 | 15 | 98 | 96 | 12,672 |
| 2 | 00/44 | 15 | 90 | 96 | 4,704 |
| 3 | 00/49 | 9 | 92 | 96 | 4,704 |
| 4 | 00/54 | 13 | 90 | 96 | 4,704 |
| 5 | 00/59 | 11 | 90 | 96 | 4,704 |
| 6 | 00/64 | 12 | 100 | 96 | 6,144 |
Within each arrangement, every track reaches its loop at the same tick. The MIDI exports contain one initial traversal of each track, then added all-notes-off messages so a finite audition can end cleanly. Source loop targets are preserved in JSON: repetition may start after introductory setup, not at the file beginning. No scene names have been invented for these tracks.
Startup music identification
The opening music is group 0 in the engine's zero-based selector: group 1 in
our gallery, SCC-1 resource 00/39 (Sound Blaster variant 00/38).
Startup 9CBD–9CBF calls D8D6 with AL=1, selecting stored record 1 from
resource 04/15. Its scene script contains the music command 40 00; opcode 40
routes through C067 to 0A99, selecting music group zero. The return-to-menu
path independently does XOR AL,AL; CALL 0A99 at 3F47–3F49.
The original song title remains unknown; “Startup music” is a functional label.
Container and sequence format
Offsets here are within resource 00/34, the SCC-1 driver, unless stated otherwise.
Its public entry at 0000 dispatches by AH through the table at 026A.
Function 3 services the player at 02A3; function 4 selects the song.
Music resource layout recovered from 03C0–046E:
- Byte 0: song count (one in each supplied music resource).
- Word at 1: offset of the song-pointer table, relative to the resource base.
- A selected table word points to the song descriptor, also base-relative.
- Descriptor bytes: division, initial tempo, track count, followed by a u16 resource-relative stream offset for each track.
- Events consist of a variable-length delta followed by an event and its operands.
Deltas use high-bit continuation and seven payload bits per byte, most
significant group first.
05FE–0667is the original decoder; a five-byte unterminated value becomes FFFFFFFF, used as a long/infinite delay sentinel.
The driver keeps 16 track states of 23 bytes each at 008A. The first word is
the stream cursor; +2/+4 is the countdown, +6 the loop cursor, +8 the selected
channel, +9 the last note, and +A the activity/mode byte.
| Event | SCC-1 handler meaning |
|---|---|
00–7F |
Note-on; event byte is note, following byte is velocity |
80–8F |
Select channel; no MIDI event by itself |
90 nn |
Note-off represented as note-on nn with zero velocity |
91 |
Stop track and silence channel |
92 pp |
Program change |
93 tt |
Change tempo |
94 |
No-op in this driver |
95 bb |
Pitch bend, low seven bits zero, high seven bits bb |
96 vv |
Channel volume, scaled by master volume |
97 xx |
Update driver track field +14; retained in command metadata |
98 |
Return to saved loop cursor |
99 |
Release last note on channels 0–11; channels 12–15 use the driver's digital-voice stop branch |
9A |
Park stream at the driver's sentinel delay |
9B pp |
Pan controller |
9C |
Save loop cursor at the following delta |
9D cc vv |
MIDI controller/value pair |
FF |
No event; proceed to the next delta |
The extracted songs exercise channel selection, notes, explicit/last-note release, instrument changes, volume, pan, pitch bend, controller commands and loops. The less common terminal/tempo/park cases above are identified statically; they are not all exercised by these six arrangements.
0668 computes sequence progress from the timer divisor and the two tempo bytes:
the constant 0444:6390 is 71,590,800 (1,193,180 × 60). This establishes the
musical division/tempo interpretation. Conversion to MIDI retains musical tick
time; it does not reproduce the driver's quantised interrupt delivery. The game
sets the driver's timer-divisor parameter to 5D24 at 9CA4–9CA9.
Original-code verification
verify_audio.py executes each exported event through
031A and each preceding delta through 05FE, in the original SCC-1 driver.
It intercepts MIDI output at 0796/079F before hardware polling, retaining full
status bytes instead of the hardware path's running-status suppression. Driver
state persists across events in a track, and master volume is set to unity.
20,545 event commands and 20,545 delta decodes match, including stream cursor positions and first-loop destinations, across all 75 tracks. See scc1-verification.json.
The check does not run hardware initialization, the full periodic scheduler, MIDI synthesis or the complete game. The driver has digital-voice branches for some commands; those are not converted into fabricated MIDI notes or sample assets. Exact source command records remain available for subsequent work.
Sound effects are a separate investigation
The main executable itself contains a direct FM register-write path:
1185 sends a register index to port 0388, and the following code sends its
value to 0389, using PIT reads for delays. 113E–1181 programs operator and
channel registers. 0EDB onward maintains effect voice state, and 0E82 has a
special interaction with the Sound Blaster music driver's internal tables.
This is evidence for a procedural FM effects path, not a bank of ordinary WAV files waiting to be renamed. The music drivers also contain digital-audio support; that does not by itself establish sample payloads used by this game. The next step is to recover the effect definitions and their evolving register writes, then render them through an appropriate OPL implementation with verified timing. A subsequent effects extraction pass now exports the embedded FM definitions and playable isolated auditions. Full live modulation remains separate from those previews.
Reproduction
python3 tools/extract_audio.py
PYTHONPATH=/tmp/darker-python python3 tools/verify_audio.py
python3 tools/render_audio_previews.py
Extraction uses Python's standard library. Verification requires Unicorn. Preview rendering requires libfluidsynth.so.3, ffmpeg and the locally installed FluidR3 GM soundfont; it does not bundle the soundfont with the extracted assets.
Earlier Sound Images investigation
2026-09-18. We examined the Aminet Sound Images EaglePlayer package. The downloaded LHA contains an Amiga executable replayer and ripper, plus readmes; no source code. Its readme says version 2 adds Sound Images Generation 2 support and exposes sample-saving through EaglePlayer 2. This is useful prior work, but not evidence that it directly accepts Darker's DOS resource format. “PC relative” in this Amiga context means program-counter-relative, not PC/DOS.
The ripper contains the attribution Tony 'Tiny' Williams, adapted by Wanted Team.
Darker's resources 00/39–41, 44–46, 49–51, 54–56, 59–61 and 64–66 contain
Tiny at byte offset 4. The sound drivers already explicitly identify Tony
Williams / Sound Images Generation 2 v1.11x. These are consistent provenance
clues, not proof of binary compatibility between Amiga and DOS songs.
Resources 00/38–67 show six repeating groups of five related stream variants,
consistent with the five extracted hardware drivers. Headers start with 01
and a little-endian word, followed by command-like bytes. Neither raw PCM nor
standard MIDI/WAV framing is established. The exact length/table semantics,
timing, command set and instrument/sample banks still need tracing through the
DOS drivers. Do not rename these resources .mid or .wav and expect playback.
All thirty candidate streams and five drivers have already been losslessly
extracted into analysis/resources/. At that stage there was no playable audio export.
The next useful step is tracing one driver's event decoder, then separating
sequence conversion from sample-bank extraction. Emulator recording is another
route to a listening copy, but would not by itself explain the format.