Cracking Exidy Fax (1983)
How we decoded 3,584 trivia questions from a binary tree compressed into 22 ROM chips
April 5, 2026 · crack, exidy, 6502
Exidy Fax
Exidy · 1983 · 6502 CPU · 22 ROM chips · 3,584 records across History, Sports, Entertainment, Grab Bag
The Game
Exidy Fax hit bar tops in 1983, one of the first coin-op trivia machines ever shipped to American drinking establishments, years before Greyhound Electronics, NTN, or the Merit bar-top boom. The cabinet was a table-format unit with a small color monitor under glass, four answer buttons (A/B/C/D), and a coin slot that accepted quarters (later tokens, as operators wised up to the all-night-stamina player). You’d drop in a coin, pick a category from History, Sports, Entertainment, or “Grab Bag”, pick a difficulty from easy/medium/hard, and answer ten questions per credit.
Exidy, the company, was a California outfit born in 1973 that shipped Crash (the first hit-and-killer driving game), Mouse Trap, and Venture. They were not a trivia company, they were a mainstream arcade manufacturer with a hit in Chiller and a steady output of dedicated cabinets. Fax was their attempt to capture the bar market before the format had a name. It shipped with an astonishing 4,800 questions packed into 176 KB across 22 separate ROM chips, a volume that required compression techniques nobody else in 1983 was using.
The Data
All 3,584 cracked records browse at /browse?source=exidy_fax . filterable by category and difficulty (easy / medium / hard). Cross-checked against 97 MAME-captured questions: 100% match.
How We Cracked It
The Question
And that’s why Fax sat un-extracted for forty years. Unlike every other trivia game of the era (plaintext ASCII, sometimes with a light XOR), Fax used a binary-tree Huffman-like compression with an XOR’d dictionary. The data in the ROMs looks like random bytes. The 6502 program ROM actively decompresses each question at play time by walking a tree. To read the questions, we had to reverse the decompression routine. That’s four layers deep.
Layer 1: XOR Encryption
The first barrier. Every byte in the dictionary ROM (fxd-1c.64, “bank 0”) is
XOR’d with 0x56. This was discovered by disassembling the 6502
program ROM and finding the instruction at $FA12:
$FA0E: INX
$FA0F: JSR $F9BA ; read raw byte from bank 0
$FA12: EOR #$56 ; ← XOR with 0x56
$FA14: STA $85,X ; store decoded byte
$FA16: BPL $FA0E ; loop until high bit set
After XOR decoding, the first bytes of the ROM spell out HISTORY,
SPORTS, ENTERTAINMENT, GRAB BAG, the
four category headers. Each terminated by a byte with the high bit set (bit 7 = 1),
a convention from the 6502 era where RAM was precious and a single bit could
serve as both data and delimiter.
Layer 2: The 194-Word Dictionary
After the four category headers and 48 bytes of metadata, a single byte announces
the dictionary size: 0xC2 (194 in decimal). What follows are 194
strings, common trivia words, each terminated by a high-bit byte:
Raw ROM: 3C 25 21 F2 (4 bytes)
XOR 0x56: 6A 73 77 A4
Masked: 'y' 'e' 'a' 'r'|0x80
Result: "year" (high bit on 'r' marks end)
Dictionary sample (194 words):
[0] year [1] yards [2] wrote [3] world
[4] won [5] with [6] which [7] what
...
[88] first [99] did [114] and [172] In
[194] Black [196] Battle [201] Baseball [204] Adams
The words are sorted roughly reverse-alphabetically: lowercase common words first (year, yards, wrote, world), then proper nouns (York, World, William, Washington), then numbers (100, 10, 000). These 194 words cover the most common vocabulary in 1983 bar trivia.
Layer 3: The Binary Tree
After the dictionary, at offset 0x0439 in bank 0, sits the
compression engine: a binary decision tree. Every two bytes form
one node:
Node format (2 bytes, raw, no XOR):
If byte0 < 0xFE: Internal node
byte0 = left child offset (relative, in 2-byte units)
byte1 = right child offset
If byte0 == 0xFE: Dictionary leaf
byte1 = word index (0-193)
→ emit dictionary word
If byte0 == 0xFF: Literal/control leaf
byte1 = ASCII character code → emit single character
byte1 = 0x7C → difficulty separator
byte1 = 0x5C → end/continuation marker
The tree root is at offset 0x0439. Here are the first nodes:
0439: 02 01 internal node (left=2, right=1)
043B: 03 02 internal node (left=3, right=2)
043D: 05 04 internal node (left=5, right=4)
043F: 06 05 internal node
0441: 01 06 internal node
0443: FF 20 ← literal SPACE (0x20)
0445: 08 06 internal node
...
044F: FF 0D ← literal CR (carriage return)
0453: FF 65 ← literal 'e'
0457: FF 61 ← literal 'a'
045D: FF 72 ← literal 'r'
Space and e are the most common symbols, they live closest to the
root, reached in the fewest bits. Rare proper nouns are deeper.
Layer 4: The Bitstream
The actual question data is a compressed bitstream spread across all 22 ROM banks (176KB). Each bit selects left (0) or right (1) at each tree node. When a leaf is reached, the symbol is emitted and the walk restarts from the root.
Category metadata (48 bytes, 4 categories × 3 difficulties):
HISTORY easy: bank 0, $28AF, 7 bits
HISTORY medium: bank 1, $3798, 1 bit
HISTORY hard: bank 3, $30EE, 4 bits
SPORTS easy: bank 5, $317A, 3 bits
...
GRAB BAG hard: bank 19, $3DFD, 6 bits
The "bits" value is the starting bit position within the
first byte (consumed MSB-first: 7→6→5→...→0).
The $F9E5 routine auto-advances through banks:
when the address crosses $3FFF, it wraps to $2000
and increments the bank number.
Layer 5: Difficulty Interleaving
Each question position in the bitstream contains data for all three
difficulty levels, separated by FF 7C markers. The game selects
one randomly and skips the others:
[easy question + answers] FF 7C
[medium question + answers] FF 7C
[hard question + answers] FF 5C (end)
This means 3× more data per position. A question like “Alaska was purchased from what country?” at easy difficulty shares a bitstream position with a harder variant at the same topic.
Putting It Together
To decode one question, the 6502 CPU:
- Selects a bank and starting address from the category metadata
- Reads one byte from the data bank → 8 bits of navigation
- For each bit, follows left or right child in the tree (in bank 0)
- On reaching a leaf: emits a dictionary word or literal character
- When bits exhaust, reads the next byte (auto-advancing through banks)
- On
FF 7C: decrements difficulty counter, skips if non-zero - On
FF 5C: question complete
Results
3,584 unique questions extracted across 4 categories and 3 difficulty levels. Cross-checked against 97 MAME-captured questions, 100% match.
HISTORY easy: 252 medium: 313 hard: 308
SPORTS easy: 286 medium: 299 hard: 293
ENTERTAINMENT easy: 276 medium: 345 hard: 295
GRAB BAG easy: 279 medium: 316 hard: 322
Sample:
[HISTORY/easy] Alaska was purchased from what country
✓ Russia ✗ China / Canada / Germany
[SPORTS/medium] Which boxer retired undefeated
✓ Gene Tunney ✗ Floyd Patterson / Joe Walcott / Joe Louis
[ENTERTAINMENT/hard] What movie star was known as "The Mellin's Baby"
✓ Humphrey Bogart ✗ Paul Newman / Mickey Rooney / Clint Eastwood
The compression ratio is impressive for 1983: 194 dictionary words + a binary tree + bitstream packing achieved roughly 5:1 compression on trivia text. The same approach , Huffman-like tree coding with a domain dictionary, would not be out of place in a modern compression library.
The difficulty tier is preserved in our extraction, you can filter by easy, medium, and hard on the browse page, alongside the four categories.
Arcade Trivia Archive, data extracted from MAME ROM dumps using a custom Python decoder.
Extractor: scripts/fax/fax_tree_decode.py
References
Related
Cross-archive analyses
Fax1 (1983, Exidy, Inc. (Sunnyvale, CA)) · Arcade-Museum · Flyer · MAME romset:
fax↩︎