Skip to main content
Back to articles
2026 / 01
| 2 min read

A Small Day That Mattered

Nine small bugs in the CRT, modem, and BBS paths, cleared before they had a chance to compound.

emulator bbs modem debugging

Nine bugs, no features. Nine things that were slightly wrong and needed to stop being wrong before I built anything on top of them.

They were small and unglamorous. The power light came on at the wrong point in the boot sequence. BBS output bypassed the UART and wrote straight to the terminal, so the RX LED never flashed. The scrollback buffer fought with the CRT rendering. None of it crashes anything. It just makes the machine feel wrong.

The ones I care about most are the state-transition bugs: disconnect mid-session, reconnect quickly, and the system believes it is in two conversations at once. Those only get more expensive the longer the surrounding code grows.

So I swept the seams instead of building new features. The changes:

  • Fixed power light initialization timing (moved to setupTerminal)
  • Removed direct terminal writes and deleted renderTerminal entirely; all output now flows through CharacterUART
  • Set terminal to 80×40 at 18px font, disabled scrollback, added cursor blink
  • Added V.92 56k handshake audio as an option (defaults to 300 baud Bell 103)

Every fix exposed another assumption about where a boundary was. Removing the UART bypass changed the BBS screen display flow: it now appears after the dial sequence, routed through the UART, with the RX LED flashing in step. That is the behaviour I wanted, but getting there meant tracing three files to work out which one was supposed to be the source of truth.

The browser’s timing constraints keep showing up. The JavaScript modem path is deeper than I first modelled, and it keeps nudging me toward a tighter core (possibly Rust/WASM) for the parts that care about clocks.

Tomorrow: the repo structure needs to match the dependency graph. I want cargo test in a CPU core directory to stop being a full-repo compile.