← BACK TO THE BOARD

// HOW THE CODE WAS CRACKED

There was no password. The archive was a CD of 2,957 files, 63 DOS programs and no source code, from a system that stopped in March 1997. Opening it took four tries over two years, three generations of AI, one lucky detour, and a lot of staring at machine code.

// FOUR TRIES

  1. 11 Sep 2024, 22:59

    First attempt, with ChatGPT 3. An automated decompile of SE.EXE, saved as se.c: 644 KB of functions named like sub_50a, most of it nonsense because the tool treated the whole file, data and all, as code.

    Max remembers it cleaned up enough to let him hear the intro again for the first time in decades, and that it gave him chills.

  2. 7 Mar 2025, just after midnight

    Second attempt, still ChatGPT 3. A Linux file listing of the whole archive (2,082 paths) saved as SanitysEdge.txt, to ask an AI what all of it was.

    The listing is a find command typed at a Linux prompt, which is how we know it was not part of the original archive.

  3. Sat 14 – Sun 15 Feb 2026

    The weekend, with Claude Sonnet 4. Max and Sonnet 4 worked through it with almost no break: dozens of test decodes listened to one by one, the audio guessed to be a standard telephone ADPCM, 2,287 files decoded in one run, a first disassembly of SE.EXE, and the first version of the website.

    File dates cover Saturday 14 February only, from 01:28 to 14:08. Max remembers the whole weekend; anything from Sunday was overwritten later.

  4. 15 Feb to 2 Apr 2026

    A pause. The project sat untouched for about six weeks.

    No file in the web app has a date between 15 February and 2 April.

  5. 3 and 28 Apr 2026

    The first prototype is committed to git, then the structure editor and the audio diagnostic tool.

    Git history.

  6. October 2026

    This round, with Claude Sonnet 5.5 and the Reverse Engineer Anything (REA) tools, which read the programs themselves and not just the audio.

    The rest of this chapter.

// THE SATURDAY

Almost everything from the second try survives in the folder, with timestamps, which means the day can be read back like a lab notebook.

01:28The first decoded sound in the folder, a clip called NOSUCHBX. NOSUCHBX_adpcm4k.wav
08:38A test matrix. For five clips, eight guesses side by side: low or high nibble first, 12-bit, 16-bit or bitwise arithmetic, raw 8-bit, a shifted start. Then seven more versions of Dr. Null's greeting with the audio start moved from byte 40 to byte 64, hunting for where the header ends. decode_test.py and 64 hand-picked listening samples in decoded/
08:45"Confirmed parameters: OKI ADPCM, low nibble first, 7950 Hz." It was not final. decode_final.py
09:00 – 09:13"Close but has static and artifacts." Refinements, then the whole archive in one run. decode_v2.py, decode_all.py, about 2,300 decoded files
10:13The website begins: a Next.js project, then a retro screen and a phone keypad. package.json 10:13, node_modules 10:16, CRTScreen and PhoneKeypad 11:26
13:21 – 13:39A first pass at SE.EXE itself: a parser for the old DOS format, a disassembler, a sorter that found 306 functions and pseudo-C written out for 72 of them. scripts/output/se-pseudocode/
14:07The first page of the web app that plays the board. app/sanitys-edge/page.tsx

It was close. It found the low-nibble order, the 40-byte header and the files of plain 8-bit audio. It guessed the wrong codec family, so about one sample in eighteen clipped and a steady hiss ran under every voice. Close enough for speech to be understood, which is why it felt nearly right.

// THE WRONG TURN THAT WORKED

This round Sonnet 5.5 was asked to read SE.EXE. It noticed a second program in the archive and took it apart too: VCON.EXE, “Voice File Conversion Utility, Talking Technology, 1990”. The program that converts between the vendor's voice formats contains the exact decoder: the step table, the index table, the starting values and the sample rate, 3,579,545 / 450 Hz.

5.6% → 0.17%samples clipping
−20 dBhiss
2,644recordings decoded, in three formats
1 in 200odds of finding the exact tables by ear (Claude's estimate)

For years Max thought the audio format was a family secret, which is why he never expected to get it back exactly. It was a commercial codec from the card's own maker. What was theirs was a small change to the files, shown below. Later, reading the card's own driver, we found the real card used fractional step sizes; the converter's whole numbers round to them in 127 of 128 places, so the audio was already very close.

// A STAMP ON EVERY RECORDING

Each recording starts with a 40-byte block. On the oldest system prompts it holds a timestamp. On everything recorded later, the board itself writes six characters over it, FUUULL:

F    the record mode (1 = uncompressed)
UUU  the user number who recorded it
LL   their access level at that moment

HANDLE.043     starts 104325   recorded by user 43 at level 25
MAINMENU.MSG   starts 100099   recorded by the sysop

That is how a restored message knows who owned it. SE.EXE's recording routine does exactly this, with the format string "%d%03d%02d", so it is read from the program, not guessed.

// READING THE PROGRAM

SE.EXE is 103,312 bytes of 16-bit Borland C++ with the overlays glued on. The first tool in the toolbox was a function map: 222 functions found, 115 of them Borland's own library, and about 14 KB that turned out to be a floating-point emulator and the overlay manager, nothing of the board's. That left 96 functions and 37,882 bytes that are really Sanity's Edge.

Ten readers each took a slice and wrote it back as C, instruction by instruction. Then eight more, who were not allowed to read the first group's notes until they had worked out each function themselves, checked it. They found three small errors and fixed them.

96functions of the board's own code
91.9%of its bytes tagged exact
5functions tagged close
0left partial

Exact means every branch is accounted for and the C would do the same thing. Close means the logic is right and one detail, such as a variable the original never initialised, cannot be settled from the code. Nothing has been compiled yet: there is no 1990s Borland compiler on hand, so this is checked by reading, twice.

The bugs it kept

The reconstruction keeps the original's mistakes, on purpose: they are part of the history, and several are visible in the real logs.

FEBURARY

The month table spells February wrong. It has been wrong since the build of 9 April 1995 and was never fixed.

SE99.EXE through the last build

JANUARY\i:\SE\TIME.PMT

When a mid-1996 rewrite moved the month words into a folder, the arguments to one sprintf went in the wrong order. The board looked for a file with that nonsense name. The 1997 call logs show it, again and again: "not here or not found".

first in the logs on 2 June 1996; the earliest surviving build with it is SE.OLD, 25 July 1996 (archive times are read as UTC, the DOS clock; the same file reads 24 July on the machine that opened it); still in the final build

The birthday compare that cannot match

A forced dash goes into one date string where the other has a slash, so one birthday comparison can never succeed. It is harmless: it feeds a counter that nothing reads. The birthday announcement itself compares the month and the day as numbers and works, so the birthday song did play.

the dash was added in SE.OLD, 25 July 1996, in front of that unread counter

The timeout that never fires

The 20-second passcode timeout reads the "seconds" out of a date string that, in that mode, no longer has seconds. It reads the year's "19" instead.

the passcode prompt

The trivia exit that isn't

The trivia menu's "99 to leave" tests a variable nothing ever sets. A beginner's slip, and the trivia code never gets a second look.

trivia menu, unchanged since 1995

Closing a file never opened

A dozen functions start by closing a file handle, which is safe when the handle is the shared one the data code keeps, and a latent bug when it is a local variable that was never opened.

copied from the data layer into later functions

// THE PIECES AROUND IT

TOOL.EXE: the driver

SE.EXE never touches the voice card. Everything it says or hears goes through a software interrupt, INT 62h, to a 1990 driver from Talking Technology, TOOL.EXE. That driver has a jump table of 99 commands and about 75 debug strings that name them (for example "ring_wait" and "flush_dtmf"). The card sits at I/O port 0x360 and has no interrupt line and no DMA: the driver moves every audio sample itself, paced by a 7,954.5 Hz clock bit.

DO.BAT: the missing loop

SE.EXE has no loop waiting for the phone to ring, and neither does the driver. The wait lived outside, in a batch file. A caller-ID program watched a US Robotics modem on the same line; when it returned, the batch file started the board, and the board answered the already-ringing line. When the board exited, its exit code told the batch file what to do next: wait for the next call, go to sleep, or run the games. Another three batch files could stop and start the board remotely.

The caller-ID program that is gone

The program that did the waiting, called cidwait, is not in the archive. Three nearby programs are: a one-shot modem setup, and two interactive terminals. The log it wrote is: 1,331 calls between 11 November 1996 and 27 March 1997. Max remembers his father did all of the caller-ID work.

The economic plan

Members on the cheaper plan could only call on odd or even days, which spread the load across a single phone line. If you called on the wrong day, a recording said "not your day", and pressing 1 accepted an extra charge. Max remembers a second line and board were planned and never built.

The builds

Fifteen variants of the board program survive, from March 1995 to January 1997, saved with version numbers as file extensions: SE.002, SE.003, SE.006, SE.12, SE.44, SE.99, SE.X. In December 1996 someone tried linking the whole caller-ID program into the board, 102 more functions in a build 15 KB larger. Four days later it was thrown away, and the final board kept only a small check against the files that program writes.

// THE ZIP FILE NOBODY OPENED

One file in the archive, LOGS.ZIP, had never been opened. Inside: 372 members and 15 monthly zips nested within them, 857 entries in all, 704 different daily logs, running from August 1994 to December 1996. Together with the 85 plain logs of 1997, they cover nearly the whole life of the board, with no overlap and no conflict. The last log of 1996 ends at 00:09:14; the first of 1997 begins at 00:09:19.

~29,700calls counted in the logs, Aug 1994 – Mar 1997 (the board's own counter said 26,188; the logs also count repeat logins and unfinished calls)
Dec 1995busiest month: 1,579 calls
30 Oct 1994busiest day: 99 calls, the night before Halloween
7.3 minmedian call

Dates in this section come from the logs themselves. A few earlier statements in this chapter, such as when the month bug first appeared, were refined by them: the logs show it from 2 June 1996, seven weeks before the build we thought introduced it.

// FATHER AND SON, IN THE CODE

Max wrote the menus, the announcements and the games; his father wrote the database back end, the driver calls and the caller-ID work. Max remembers that. The code tells the same story in small details, and this is our reading of it, not a fact to be quoted:

// STILL OPEN