Skip to content

About

File-format documentation for Sargon V: World Class Chess (Mediagenic, 1991, MS-DOS): one LSB-first-LZW container behind five extensions, one 8-bit asset set driving VGA/EGA/Tandy via a 256-to-16 dither table, a hand-written Tandy 1000 SL/TL driver, the 512-byte position record, the tutorial decision trees - and the hamster in the About box.

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pc-sargon5-doc

Reverse-engineering notes on Sargon V: World Class Chess (Mediagenic, 1991) — the last of the line Dan and Kathe Spracklen started in 1978 with a Z80 program written for a computer chess tournament, and the only one whose PC front end this repository is about.

The About box splits the credit itself:

Chess Engine: Dan & Kathe Spracklen
P.C. Engine: Kevin E. Leavelle

Everything here is the second half — the container, the codec, the display layer, the position records, the tutorial system. The search itself is a black box this project has not opened.

Documentation only. No game assets, no extracted art, no audio, no executable code is committed here. The tools in tools/ reproduce every figure, table and image from your own legally obtained copy.

What is documented

Doc Contents
00-overview.md The release, the two disagreeing copyright lines, the eight shipped files
01-executable.md SARGON5.EXE: the LZEXE wrapper, the 32-copy copyright fence, the data segment, the command line, EMS, the build
02-container-and-codec.md The 16-byte directory and the LSB-first LZW that five of the eight files share
03-graphics.md SCREENE.HUH: eight frames, 182 sprites, the bottom-centre anchor, the piece-set loader
04-palettes-and-16-colour.md The VGA palette and the 768-byte table that lets one asset set serve four displays
05-fonts.md FONTS.FNT: six proportional faces, and the tail of the character range
06-display-drivers.md WAZZOO.DRV: VGA, EGA, Tandy — and a register-level Tandy 1000 SL/TL driver
07-audio.md Six standard MIDI files, seven device records, and the card with no switch
08-opening-book.md OPENE.BOK: 338 opening names, and what can be said about the tree
09-position-records.md The 512-byte record every game, lesson and puzzle uses; the move stream
10-annotated-lessons.md .ANN coaching trees, and the .ANT sources that shipped by accident
11-text-board-format.md The plain-text board importer nothing in the release uses
12-easter-eggs-and-leftovers.md Dr. Destructo, Hamster Gone Bad Productions, and what happens to the white king
13-open-questions.md Everything unresolved, with the measurements behind it
notes/resource-inventory.md All 219 blocks across the five containers, grouped and sized
notes/tutorial-inventory.md 335 lessons and games, the two numbering gaps, the census
notes/string-inventory.md The credits, the messages, the file names, the device names

Highlights

Five files with four different extensions are one format. SCREENE.HUH, SMORE.HUH, FONTS.FNT, WAZZOO.DRV and OPENE.BOK share a directory of 16-byte entries with no magic number, no signature and no entry count — the first entry's data offset is the directory length, so the count is that offset divided by sixteen. All 219 blocks across the five files are contiguous, and every one decodes to exactly its declared size.

The codec is LZW read backwards. Nine to twelve bits, 256 clear, 257 end — and packed least-significant bit first, where GIF, TIFF and Unix compress all pack MSB-first. Attacking the first block the usual way is not obviously wrong: it runs, and produces 955 plausible bytes before the dictionary walks off. Read the same bytes LSB-first and it lands on exactly 64,000 — one 320×200 frame. On an 8086 the LSB-first accumulator is a shift and a mask; MSB-first needs a rotate through a width that changes under you.

One asset set serves four displays. There is no EGA art and no Tandy art in the release. Every sprite and every screen is 8-bit indexed, and each palette block carries 768 bytes of VGA DAC values plus 768 more — three bytes, six nibbles per colour — that express the same 256 colours for the 16-colour drivers. Substitute any one of those six nibble planes for the whole image and the picture stays legible. That single decision is why the sprites are chunky rather than planar and why the EGA driver is the biggest of the four.

WAZZOO.DRV is video, not audio. Four blocks, thirty entry points each — one interface, four implementations. Driver 1 is the one worth reading: it never calls the BIOS, and instead writes nineteen 6845 CRTC registers, five video-array registers through 0x3DA/0x3DE, and a page register at 0x3DF before clearing 64,000 bytes at A000. That is Tandy 1000 SL/TL 640×200 in 16 colours, programmed by hand, as a separate driver from the ordinary Tandy one. Somebody on the team had the machine.

Every game, lesson, puzzle and endgame is the same 512-byte record. Four extensions — .SAR, .ILL, .CMB, .ENG — and one format: a 256-byte move stream, then a 32-slot piece list of types and 0x88 squares that is never compacted, so a captured man keeps its slot and gets square 0x80. The trailer's one interesting byte is a cursor, not a length: class013.sar has a 63-byte stream with the cursor at 16, so 47 bytes of that game are recorded but not yet played. The shipped saved games are recordings wound back, not truncated.

The move stream is one byte per half-move, and the opening statistics decode it. Bit 7 is the side; the low seven bits are a 1-based index into the move list the engine generates. 113 records start from the initial position, and their first byte takes exactly four values — 12 (80 times), 14 (26), 1 (4), 16 (3). Those are 1.e4, 1.d4, 1.Nf3 and 1.c4, in the right proportions. The second byte takes nine values, which come out as e5, c5, Nf6, d5, e6, d6, c6, f5 and Nh6 — the Sicilian, the Indian defences, the Queen's Gambit, the French, the Pirc, the Caro-Kann and the Dutch, again in the right proportions. The generator emits knight moves first, king's knight before queen's, then pawns from the h-file to the a-file, one-square push before two. Where it stops is in chapter 13, stated with the number: a replay gets 2,290 of 4,631 half-moves.

A tutorial lesson is a decision tree, not a recording. sicw.ann carries 318 move entries for a twenty-turn game. Twenty are the correct moves, twenty the machine's replies, twenty a catch-all — and the other 258 are anticipated mistakes, each with its own sentence. Turn 1 of frenchb.ann names four rival openings by the first move that gives them away; turn 3 enumerates twenty-six wrong moves, including every pawn advance on the board under one message, "A waste of a precious move".

The lessons' source code shipped, and the game cannot see it. WHITE.ANT and BLACK.ANT are the plain-text authoring format the .ANN files were compiled from — move lines, wildcards, XXX as a section break. The file dialog filters on *.ANN. Two authoring files, in the retail game directory, invisible to the program that shipped them. The typo in "a sample black anotated game" is in the retail file.

There is a plain-text board importer nobody used. A routine at 0x16CED accepts a file that begins with a plus sign, reads a two-character piece code every five bytes and every 86 bytes a new rank, matching against WPWRWBWNWKWQBPBRBBBNBKBQ plus two spaces for empty. Every constant in it resolves to an ASCII board drawn with +----+ separators and | BR | cells, CRLF throughout. No .TXT ships, nothing demonstrates it, and it is strict enough that one character out of place rejects the file.

The programmer is credited as "Dr. Destructo". Four of the thirteen job titles in the About box are jokes — Interloper, Cool Boss, Grunt-work — but only one replaces a person's name, on the line directly under Dan and Kathe Spracklen.

Hold h while the About box is open. A sprite appears at (210, 163) and two lines of text at (154, 87): Hamster Gone Bad / Productions! The routine is the About dialog's own draw procedure, it checks the keyboard state array for ASCII h, and each time it fires it increments a counter. Do it three times, then hold q in two further dialogs, and a hook inside the piece-set loader comes alive: on the fifth of the twelve sprites it loads — the white king — it substitutes block 192 or block 193 instead. Which one is decided by a sixteen-bit LFSR with taps 0xB400, one time in four. Block 193 is a digitised bespectacled human face. Block 192 is a hamster holding something that has nothing to do with chess. Either of them then plays the game as White's king.

A card with a driver and no switch. The executable carries seven audio device records: AdLib, IBM PS/1, Roland MT-32, Internal Speaker, Tandy 1000, Null Device — and Game Blaster PC Music Board, Creative's 1987 CMS card, which no command-line switch selects and the help box never lists. Conversely there is no "Sound Blaster" string anywhere in the image: /S reaches the AdLib record, because a Sound Blaster's music side is an OPL2.

Two numbering gaps ship in the retail data. end22.eng is missing from an otherwise unbroken 1–58, and opngs007 through opngs010 from 1–69. The surrounding files are present and intact.

Tools

Pure Python 3. pillow is needed for the rendering paths and capstone only for the driver disassembler.

tools/s5lib.py       the container, the LZW, sprites, palettes
tools/s5res.py       list, verify and extract any container
tools/s5gfx.py       screens, sprite sheets, piece sets, the 16-colour test
tools/s5font.py      FONTS.FNT
tools/s5drv.py       the four display drivers
tools/s5music.py     the six MIDI files
tools/s5book.py      OPENE.BOK and its 338 opening names
tools/s5pos.py       positions from .SAR, .ILL, .CMB and .ENG, as diagrams and FEN
tools/s5ann.py       .ANN lessons, as readable coaching transcripts
tools/s5unpack.py    the LZEXE 0.91 wrapper
tools/s5strings.py   text out of the unpacked image
tools/s5export.py    one shot: all of the above into one directory
python tools/s5export.py "<install>" ./out

or piecemeal:

python tools/s5res.py    "<install>" verify
python tools/s5res.py    "<install>" list SCREENE.HUH
python tools/s5gfx.py    "<install>" screens ./screens
python tools/s5gfx.py    "<install>" pieces piece-sets.png
python tools/s5gfx.py    "<install>" ega 20 title-16.png
python tools/s5font.py   "<install>" sheet fonts.png
python tools/s5drv.py    "<install>" info
python tools/s5music.py  "<install>" dump ./music
python tools/s5book.py   "<install>" names
python tools/s5pos.py    board "<install>/tutorial/bg01.cmb"
python tools/s5ann.py    text  "<install>/tutorial/frenchb.ann"
python tools/s5unpack.py "<install>" s5.bin
python tools/s5strings.py s5.bin

<install> is the directory holding SARGON5.EXE, with games/ and tutorial/ beside it.

Status

The container and its codec are solved and verified block by block — all 219 of them, across all five files. SCREENE.HUH, FONTS.FNT, SMORE.HUH and WAZZOO.DRV are decoded end to end. The 512-byte position record is solved except for the move stream's generator ordering, which is decoded far enough to read every opening move in the corpus and no further. The opening book's tree is not decoded. Chapter 13 lists all of it, with the numbers.

About

File-format documentation for Sargon V: World Class Chess (Mediagenic, 1991, MS-DOS): one LSB-first-LZW container behind five extensions, one 8-bit asset set driving VGA/EGA/Tandy via a 256-to-16 dither table, a hand-written Tandy 1000 SL/TL driver, the 512-byte position record, the tutorial decision trees - and the hamster in the About box.

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages