HEARO

> Music player for vintage DOS PCs.

NetISA suite app. 286 minimum. 24 audio devices, MDA through SVGA. Trackers, MIDI, WAV, and chiptunes play on the host. Compressed formats and streaming go through the NetISA card’s ESP32 in v1.1.

HEARO v1.4 main UI in DOSBox-X. Four-pane text-mode layout: top-left file browser showing C:\DATA contents (TONE.MOD highlighted), top-right Now Playing pane reading 'no track loaded', bottom-left Playlist pane (empty), bottom-right Spectrum visualizer showing the dim default sweep. Top status bar shows menu items File / Playback / View / Settings / Help. Bottom status bar shows Space:Play/Pause N:Next P:Prev Tab:Focus F2:Settings F10:Hall F12:Exit.
HEARO v1.4 main UI on a 486DX2 + SB16 + VESA SVGA Workstation tier. Four panes, menu bar, status bar with F-key shortcuts. Captured automated via DOSBox-X with HEARO.CFG-controlled state and DEBUG.EXE keyboard-buffer prefill.

v1.5.1 release — 2026-05-02

Tagged at v1.5.1. v1.5.0 plus the three deferred follow-ups its release notes flagged as v1.6 work, brought forward into a same-day patch.

LHA depacker for YM5 / YM6. Every YM file in the Atari ST chiptune corpus ships LHA-compressed (typically -lh5-); v1.5.0 only accepted the rare uncompressed YM3 form. v1.5.1 adds a from-scratch implementation of the LHA level-0 / level-1 header parser and the LH5 algorithm (8 KB sliding-window LZSS with static Huffman codes for both the literal/length and offset alphabets). Wraps the existing AY synth, so YM5 / YM6 streams (which have a richer header and 16 registers per frame versus YM3’s 14, with column-major OR row-major layout depending on the A_STREAMINTERLEAVED attr bit) load and play through the same code path as YM3. Validated end-to-end on 86Box via two new wav-matrix cells: an LH0 (stored) wrap of a real YM3 file, and an LH5 (literal-only encoded) wrap of a synthetic YM5 stream. The LZ back-reference path of the LH5 decoder is verified with an additional ABABA round-trip fixture decoded by a Python port of the C decoder. Implementation in src/decode/lha.c + lha.h, ~370 LOC. Read from the Yoshizaki LHA spec; lhasa (ISC) was consulted only for the LH5 constants (DICBIT=13, NC=510, NP=14). MIT-clean, no GPL contamination.

FX:N counter coverage extended. v1.5.0 wired the FX:N activity badge on the now-playing pane only for the post-v1.4 trackers (STM / FAR / ULT) where the per-channel modulator state was already memorized for the per-tick effects pump. v1.5.1 adds *_active_fx accessors to the older trackers (MOD, S3M, XM, IT, MTM, 669) so the badge surfaces wherever the engine actually pumps a continuous effect. MOD reports tone porta, vibrato, tremolo, arpeggio, and note-delay countdowns; S3M reports tone porta (G), vibrato (H), tremor (I), retrig (Q), arpeggio (J); IT reports tone porta + vibrato. XM and 669 surface only what their MVP engines currently model (XM = Axx volume slide; 669 = no per-tick effects yet) so the badge is honest rather than misleading.

Tone-porta-without-instrument fallback fixtures. v1.5.0 implemented the “Gxx with note column populated but instrument column empty → slide using whatever sample is currently playing” semantics for STM / FAR / ULT (the convention real-world S3M/STM/FAR/ULT music routinely writes), but didn’t ship regression coverage. v1.5.1 adds three new fixtures — FXSTM5, FXFAR5, FXULT6 — each exercising the fallback path with a control row (porta with instrument) followed by two fallback rows (porta without instrument, sliding both up and down). All three pass deterministic on 86Box.

33 wav-matrix cells now PASS deterministic (was 30 in v1.5.0); HEARO.EXE grew from 231 KB to 235 KB (+4 KB for LHA + the older-tracker FX accessors).

v1.5.0 release — 2026-05-02

Tagged at v1.5.0. Six new decoders, AY chip music with streaming synth, full per-tick effects pump on STM / FAR / ULT, animated splash intro with OPL2 fanfare, four phases of UI catch-up, three new themes, and a 320CDT YMF715 research dossier with both a documented user workaround and a staged native EEPROMless wake path. Three-round pre-release quality gate caught 22 issues (3 Critical + 19 Important) before tag. 30/30 wav-matrix cells PASS deterministic.

v1.5 development log — 2026-05-01

Six new decoders shipped on top of v1.4. CMF (Creative Music File, OPL2 + embedded MIDI track), HSC (HSC AdLib Composer, pattern-based OPL2), STM (Scream Tracker 2, 4-channel PCM), RAD v1 (Reality AdLib Tracker, OPL2 with a 32-pattern offset table), FAR (Farandole Composer, 16-channel PCM, C5 reference at 16726 Hz), and ULT (UltraTracker V004 with column-major RLE patterns). Plus an AY-3-8910 / YM3 register-stream player covering the ZX Spectrum 128 / Amstrad CPC / Atari ST chip-music corpus: 3 tone channels at 12-bit period precision, 17-bit Galois LFSR noise, all 8 functional envelope shapes, per-channel envelope-follow, and a streaming synth that lifts the initial pre-render cap so songs of any length play.

Total decoder count is now 16, all covered by an end-to-end audio regression. A per-format TESTPLAY plus fixture packs into an 86Box VM, the /W render path drives the decoder and mixer with FPU forced off and writes a deterministic byte stream, then the harness mounts the VHD and hashes the rendered WAV against per-cell baselines. PCM trackers hash the mixer output directly; OPL formats route through Nuked-OPL3 host synthesis so the hash captures chip-write ordering instead of just the raw register stream; AY uses HEARO’s own software synth. A peak-amplitude floor was added after a real regression where a baseline regenerated against silence still hashed deterministically and looked healthy.

LHA-packed YM5 is the next AY follow-up. Every YM file in the wild ships LH5-compressed; the recognizer accepts raw YM3 today. Adding the LHA depacker is its own ~600 LOC chunk plus corpus-fixture sourcing, so it sits in its own session.

Effect coverage on STM, FAR, and ULT expanded into a full per-tick effects pump. STM honors Axx (set speed), Bxx (position jump), Cxx (pattern break), Dxx (volume slide), Exx / Fxx (pitch slides), Gxx (tone portamento), Hxx (vibrato), Jxx (arpeggio), and Oxx (sample offset). FAR honors Fxx (set tempo), Dxx / Exx (fine tempo deltas), 6xx / 7xx (volume slide up / down), 3xx (tone porta), and 5xx / 8xx (vibrato — FAR splits vibrato across two effect codes). ULT honors 1xx / 2xx (portamento up / down), 3xx (tone porta), 4xx (vibrato), 7xx (tremolo), 9xx (sample offset), Axx (volume slide), Bxx (position jump), Cxx (set volume in either effect column), Dxx (pattern break), and Fxx (set speed). The wav-matrix grew from 19 to 30 cells with one new fixture per format-effect-group, plus an AY-3-8910 envelope-shape regression cell that cycles all 8 functional shapes against a baseline that AYFULL (which only exercises shape 0x0A) doesn’t catch.

UI catch-up — 2026-05-01

After the post-v1.4 feature blitz the UI needed to catch up so users could see and reach what was actually shipping. Four passes landed today: Phase 1 visibility added live indicators to the bottom status bar ([EQ], [REV:Cathedral], [Wide]/[Karaoke] separation modes, [V:Plasma] for the current visualizer) plus a format badge in the now-playing pane ([STM], [AY/YM3]) that brightens when the active format has effect coverage. Discovery was previously by reading the README; now it’s by glancing at the screen.

Phase 2 promoted env-var features into the UI. The stereo-separation knob was previously reachable only by setting HEARO_SEPARATION=narrow before launch; it now lives at Settings → Stereo mode with a live picker for Full / Narrow / Mono / Wide / Karaoke. Reverb and EQ presets already had pickers; the status bar now confirms what’s active.

Phase 3 tightened discoverability. The boot screen got a “Try: Alt-S Settings, V cycles visualizers, F2 Unlock matrix, Alt-H Help” tip line below the unlock count, so first-time users have a concrete first action. The browser’s empty state replaced “(no music files in this directory)” with actionable hints (Backspace to parent, Alt-F to open by path, or filter status when an extension filter is active). The now-playing pane’s stopped state replaced the empty artist / album lines with “ENTER in browser to play. Alt-F: open by path. V: cycle viz.”

Phase 4 added curated themes. Three new built-in palettes joined the existing six: Borland Blue (Turbo Pascal IDE blue / yellow / cyan), Norton Commander (black-on-cyan with the file-manager bones), and Tokyo Night (modern dark purple with soft accents). The theme picker already had live preview, so cycling through the new palettes is instant. Total built-in count is now 9 plus the user-defined slot.

Animated splash intro — 2026-05-01

The post-v1.4 launches needed a moment of theatre, in the spirit of the old Apogee / Sierra studio splashes. HEARO now plays a brief animated intro before the diagnostic boot screen lands.

Four phases in roughly 3.5 seconds. Reveal: a column-by-column wipe walks left-to-right across the HEARO logo with a CGA-snow flicker zone behind the wavefront, evoking the CRT-warm-up feel without needing per-pixel work in Mode 13h. Fanfare: a three-note OPL2 ascending arpeggio (C5, G5, C6) keys on at 25%, 50%, and 75% through the reveal so the music and the visual land together. Hold: full-intensity logo with a "NetISA Music Player" subtitle for one second. Dissolve: the VGA palette fades to black across ten vsync-gated steps, then control returns to the boot screen.

Any keypress skips. --no-intro, HEARO_INTRO=off, or --safe on the command line opts out entirely so first-time problem diagnosis isn’t gated behind theatre. On hardware with no OPL chip the visual still plays, just silently. Implementation is text-mode + INT 10h palette tricks, ~250 lines, integrates with HEARO’s existing theme_apply for state restore. Lives in src/ui/intro.c.

HEARO splash intro animation looping: HEARO logo wipes in left-to-right with a CGA-snow flicker zone, settles to the full logo with 'NetISA Music Player' subtitle, then dissolves into the boot screen.
The intro animation captured via scripts/capture-intro-gif.ps1 (ffmpeg gdigrab into DOSBox-X, palette-quantised to GIF). The OPL2 fanfare doesn’t survive the GIF; for the audio, reach for the binary on real iron or a DOSBox-X build.

The architectural piece behind this is a process_tick() per-format that runs on every non-row tick, pushing volume and frequency deltas through the mixer in the same scaling space the row processor uses. ULT cells widened to 7 bytes to carry both effect columns natively; STM cells stayed at 5; FAR cells stayed at 4 because FAR’s effect parameter is already 4 bits, so cmd<<4 | param packs into a single byte. Tone portamento, vibrato, and tremolo are deferred — they need memorized per-channel target state (Gxx remembers a target note, Hxx remembers depth and speed) that the dispatch path doesn’t yet carry. Twenty-five-of-twenty-five cells PASS deterministic across reruns.

v1.4.0 release — 2026-04-30

Tagged at v1.4.0. The polish-and-visuals milestone: 2-pole resonant IT filter, five FPU-gated text-mode visualizers, Mode 13h fullscreen plasma, 3-band parametric EQ, light Schroeder reverb, S3M effect-set expansion (with an S/T/U dispatch bug fix that had been silent since v1.0), GENMIDI bank loader path expansion, M3U save/load, EQ + reverb preset libraries, browser extension filter, theming Layer 5 (custom palette editor + per-role override picker + .THM hot-reload + theme exporter), and a five-round red-team review campaign that caught seven real bugs that smoke tests missed.

Visualizers

Eight modes. V cycles. Spectrum, VU, Bars work on any iron; Plasma, Tunnel, Fire, Particle, Wireframe are FPU-gated and skipped on FPU-less hardware. Audio keeps playing through the cycle — the spectrum-style modes pick up the live sample feed; the demoscene-style modes self-animate from frame counters.

HEARO frequency bars visualizer running while TONE.MOD plays. Spectrum bars in tri-color zones (green for low, yellow for mid, red for high) showing real audio data with peak-hold caps.
Frequency bars with peak-hold and tri-color zones. Real audio data from TONE.MOD.
HEARO plasma visualizer in the bottom-right pane. Three CORDIC sine fields summed per cell, color-cycled through 8-step ASCII glyph ramp.
Plasma: three CORDIC sine fields summed per cell, FPU-gated, ~3 cycles/cell on 386+.
HEARO tunnel visualizer. Squared-distance depth plus angular twist gives rotating-rings pattern that reads as a tunnel without atan2 or sqrt.
Tunnel: squared-distance “depth” plus dx*dy angular twist. No atan2 or sqrt.
HEARO fire visualizer. Heat propagates upward from a randomly-seeded bottom row through ASCII glyphs in red/orange/yellow.
Fire: heat propagation from a fresh PRNG-seeded bottom row, decay per-row above.
HEARO particle fountain. 24 particles with Q8.8 fixed-point position and velocity, gravity affecting vy.
Particle fountain: 24 particles, Q8.8 position+velocity, gravity vy+=16/frame.
HEARO wireframe rotating cube. 8 vertices, 12 edges, double rotation around Y then X via CORDIC sin/cos, perspective projection plus Bresenham line drawing to ASCII.
Wireframe cube: 8 verts × 12 edges. CORDIC rotation + Bresenham ASCII lines.

Plus a fullscreen Mode 13h plasma at 320×200×256 (View → Graphical viz). Pre-computed sine table + per-frame phase tables make the inner loop three array lookups per pixel; comfortably 30+ fps on a 486.

Theming

Layer 5 of the theming system shipped with v1.4: 7 palettes × 7 schemes × 6 bundles = 294 baseline combinations, plus per-role overrides for the 28 named roles, plus an in-app palette editor with live VGA DAC preview, plus .THM extension files. Two examples below.

HEARO with Amber CRT palette + Norton Classic role scheme. The whole UI is amber-on-brown, mimicking a 1980s amber phosphor monitor running Norton Commander.
Amber CRT palette + Norton Classic scheme — the 1992 NC vibe in amber phosphor.
HEARO with Synthwave palette + High Contrast role scheme. Magenta, cyan, yellow against black, very loud and modern.
Synthwave palette + High Contrast scheme — magenta / cyan / yellow.

Settings + Hall

HEARO Settings: Feature Unlock Matrix. Lists each unlock and whether it's enabled. Visualizers section shows 256-bin FFT, 64-bin bipartite FFT, Plasma, Tunnel, Particle system, Fire, Wireframe 3D all unlocked; Stochastic particles is FPU-less only and locked. Audio section shows RealSound PWM unlocked, Tandy/PCjr PSG / Covox / Disney Sound Source / OPL2 MIDI listed with their requirements.
F2 Settings: feature unlock matrix. 32 of 67 unlocked on this 486+FPU.
HEARO Hall of Recognition. Machine fingerprint 7A00CFEB, first boot 2026-04-30, boot count 38. Hardware timeline showing CPU Intel 80486SX, FPU 80487, Memory 640K conv + 64512K XMS, Video VESA generic 2048KB VRAM, Audio PC Speaker. Lifetime statistics: 0 hours played, 0 tracks played, 32 features unlocked, 9 hardware events.
F10 Hall of Recognition: machine fingerprint, first-boot date, hardware timeline, lifetime stats.

Boot screen

HEARO v1.4 boot screen in DOSBox-X. Big CP437 box-drawing HEARO logo at top with NetISA Music Player v1.3.0 / MIT License subtitle. CPU Intel 80486SX 8 MHz detected; 80487 ENABLED listing 256-bin FFT, sinc resampling, exact mixing, plasma, tunnel, particle system, fire, wireframe 3D, karaoke vocal removal, parametric EQ, stereo widening, gamma-correct dither, adaptive CORDIC, log-domain effects, 16+ channel mixing in green. Memory 640K + 64512K extended detected with full library index and visualizer preload unlocked. Video VESA generic 2048KB VRAM ENABLED. Bottom: Your machine has unlocked 32 features. Press any key to begin.
v1.4 boot screen on the same Workstation tier. 32 features unlocked. Captured automated via DOSBox-X with PrintWindow / WM_PRINT.

The capture pipeline that produced these shots is fully automated: per-shot HEARO.CFG sets the visualizer / palette / scheme target, per-shot DOSBox-X autoexec runs DEBUG.EXE to pre-fill the BIOS keyboard buffer at 0040:001A with a navigation key sequence (Enter dismiss boot, 7 Down keys, Enter to play TONE.MOD). HEARO consumes the buffer naturally via INT 16h AH=10h. The trick bypasses DOSBox-X SDL2’s input filter that silently drops SendKeys / SendInput from PowerShell. Source at scripts/capture-v14-shots.ps1.

What shipped in v1.4, in commit order:

v1.4 quality — the red-team campaign

After v1.4 shipped, a five-round red-team review campaign across all chunks (audio engine, mixer DSP, visualizers, tracker decoders, theming) caught seven real bugs that the smoke tests missed:

Every one of these passed the smoke test (frame counts correct, no crashes) but produced wrong audible / visual output. The smoke test verifies frame counts and crash-freedom; the red-team campaign verifies what the smoke test can’t. Each fix shipped as its own commit per round and is on origin/main.

v1.3.0 release — 2026-04-28

Tagged at v1.3.0. The demoscene-polish milestone: engine fidelity for XM and IT, three visualizer modes, real now-playing metadata, plus a same-day v1.0 hardening pass that closed 12 review findings and imported five auplay-inspired SB/DMA improvements.

What shipped, in commit order:

Same-day hardening: 12 issues closed from external code reviews (mixer loop-bound clamping, safe_fmalloc 64K policy, irq_save/irq_restore helpers, MOD per-pattern allocation, S3M out-of-bounds note guard, XM short-header zero-init, mixer frequency overflow fix, modal UI audio pump, browser extension sync, nowplay_advance wiring, S3M packed/stereo flag rejection); five auplay-inspired SB/DMA improvements (DSP4 IRQ self-detection, INTSTAT-driven IRQ ack with ack-both fallback, DSP_END_DMA + 0xD9/0xDA bug fix, audio_callback returns u16 + EOF wiring, unified DMA register tables).

Three rounds of iterative code review closed clean: 5 → 1 → 0 Critical+Important findings. The Round 2 finding was a u32 overflow in IT pitch-envelope frequency multiplication on high notes (~250 kHz base_freq times max-positive envelope multiplier exceeded u32); fixed via a split-shift form. Source & commits.

Status

2026-04-30, v1.4.0 released. Compiles clean under Open Watcom V2. HEARO.EXE is 189 KB; the seven test programs build alongside it. DOSBox-X SB16 sentinels match across every commit (WAV 90112 / MOD 90112 / IT 90112 / MIDI 133120 / VGM 90112 at /T4 and /T6). Real-iron PC Speaker validation passed on the Toshiba 320CDT (8 formats decode + play, no crashes); the OPL3-SA path is hardware-blocked behind a Toshiba-specific power gate documented in 320cdt-test-methodology.md. Primary real-iron audio target is the 486 DX-2 + Vibra 16S box.

What is in the tree:

Boot screen

One line per detected component, status word right justified, unlocked features indented under the component that enabled them. Last line: feature count.

Unlock matrix

Each detected expansion enables specific features. Around 70 rules. Each rule is one row in a table: name, description, requirement string, pure-function check against hw_profile_t. Adding a feature is one line.

Detection

Eight modules, each one self-contained so a misbehaving probe can be turned off in one place.

Per-device probe protocols: docs/hearo-soundcard-reference.md.

Video tiers

WorkstationSVGA 1024x768x256
EnhancedSVGA 800x600x256
StandardSVGA 640x480x256
ClassicVGA 320x200x256
LegacyEGA 640x350x16
MinimalMDA / Hercules text

Text-mode tier (Minimal) is what shipped in v1.0. Graphical tiers are scaffolded only; real Mode 13h / VESA framebuffer code is v1.3.

Hall of Recognition

Plain text file (HEARO.HAL). Hardware first-seen dates, lifetime stats. Editable with any text editor.

Install an FPU, the next boot says it is new. A year later the boot screen says so on the same calendar day. No achievements or scores.

Format support

Host: WAV (PCM 8/16, mono/stereo), MOD (4/6/8 ch), S3M, XM, IT (envelopes + NNAs + 2-pole filter), MTM, 669, STM, FAR, ULT, MIDI (SMF), VGM (SN76489 + OPL2/3 + YM2612), CMF, HSC, RAD v1, AY/YM3.

ESP32 (v1.1+): MP3, FLAC, Opus, Vorbis, AAC, WMA, ALAC.

Streaming (v1.1+): Icecast/SHOUTcast, Bandcamp, SomaFM, Internet Archive, Nectarine Demoscene Radio, ModArchive.

Compressed formats decode on the ESP32 because real-time MP3 decode below a fast 486 does not work. Without the NetISA card those extensions are greyed out in the file browser.

Math

Roadmap

Suite

HEARO is one of nine NetISA suite apps. Shared INI config grammar, Hall file format, boot-screen layout, command-line conventions (/SAFE, /REDETECT, /STUBNET).

CATHODEWeb browser
DISCORDChat client
CLAUDELLM client
COURIEREmail (OAuth2)
CRATECloud filesystem
KIOSKPackage manager
CHIMETime sync
HEAROMusic player
RADIOXT streaming

Hardware

Floor286 + 1MB + MDA
Standard386 + 4MB + VGA + AdLib
Workstation486 + 8MB + SVGA + SB16
Maximum486DX2+ 16MB + 1024 + GUS
DOS3.3+
LicenseMIT

286 is the floor. V20 + 8087 + 640K + CGA/EGA + AdLib/SB gets a degraded path that still plays trackers and MIDI. RADIO is the lighter sibling for true XT-class machines.

Technical

PlatformMS-DOS (real + DPMI)
BinariesHEARO.EXE + HEAROXM.EXE
ToolchainOpenWatcom V2
StandardC89/C90
Source~10K lines, 35 modules
LicenseMIT

HEARO.EXE: real mode, large model, 286+. HEAROXM.EXE: 32-bit flat, DOS/4GW, 386+. Both ship together; 32-bit preferred when available, 16-bit is the universal fallback.

Layout: docs/hearo-design.md, docs/hearo-soundcard-reference.md. hearo/src/ (35 modules: detect, unlock, ui, math, config, platform, stub). hearo/test/ (six test programs). hearo/data/unlocks.def. hearo/scripts/ (DOSBox-X screenshot toolkit). hearo/Makefile.

FAQ

Will it run on my 286?
Yes. 286 + 1 MB + MDA + PC Speaker is the floor. Text-mode UI works on every adapter from MDA up.
What audio devices are supported?
Twenty-four. PC Speaker, Tandy/PCjr PSG, Covox, Disney Sound Source, AdLib (OPL2), AdLib Gold (OPL3 + 12-bit DAC), Sound Blaster 1.x / 2.0 / Pro / Pro 2 / 16 / 16 ASP / AWE32 / AWE64, Gravis UltraSound Classic / MAX / ACE / PnP, MPU-401 with SysEx-identified MT-32 / CM-32L / SC-55 / SC-55mkII / SC-88 / SC-88 Pro / DB50XG / SCB-55, Ensoniq SoundScape, Pro Audio Spectrum 16, ESS AudioDrive, Turtle Beach MultiSound. Probe protocols in the soundcard reference.
Does HEARO play MP3 / FLAC / Opus?
Yes, on the ESP32. Compressed formats decode on the NetISA card and arrive at the host as PCM. Native formats decode on the host. Without a NetISA card, compressed extensions are greyed out. v1.0 ships native-only; v1.1 turns on the ESP32 path.
How does the Hall of Recognition work?
Plain text file. Each boot, HEARO compares detection against the previous fingerprint and appends new components with their first-seen date. Stats accumulate (hours played, tracks, boot count, peak features). Just a record.
What unlocks the FFT spectrum analyzer?
Any FPU. Without an FPU, you get a 64-bin bipartite-table FFT. Fast enough for a 286.
What does the NetISA card do for HEARO?
Streaming and compressed-format decode. v1.0 native-only; v1.1 turns on Internet radio (Icecast/SHOUTcast), Bandcamp, SomaFM, Internet Archive, ModArchive, plus MP3/FLAC/Opus/Vorbis/AAC.
Does it work in DOSBox-X, 86Box, PCem?
Yes. Standard BIOS calls + direct VRAM. Audio detection works in DOSBox-X with the standard SB + GUS emulation.
License?
MIT. Same as the rest of the suite.
Where is the source?
BarelyBooting/netisa/hearo

Links