Cracking Super Trivia Master (1986)

Enerdyne's Super Trivia Master hid its questions in an LZ-style self-referential phrase table spread across eight banks, read through a single I/O port. Token decoder reverse-engineered from the Z80 firmware; 4447 questions recovered.

April 19, 2026 · crack, enerdyne, strvmstr, z80


← Archive

Super Trivia Master

Enerdyne Technologies / PGD Inc. · 1986 · ettrivia board · Z80 @ 4 MHz · 4447 records across 8 category banks


The Cabinet

Super Trivia Master1 shipped in 1986 from Enerdyne Technologies of El Cajon, California, published by PGD Inc. Enerdyne was a small West Coast outfit best remembered for producing cabinets distributed through PGD into bars and bowling alleys. The game ran on a Z80 @ 4 MHz with three AY-3-8910 sound chips and eight 32 KB question ROMs organized into four banks of paired hi/lo-byte chips. MAME tracks the hardware under its ettrivia driver.

Eight categories, one per chip pair:

The Data

All 4447 records browse at /browse?source=enerdyne_strvmstr . 8 categories, all multiple-choice, decoded straight from the ettrivia phrase tables. A sister cabinet, Progressive Music Trivia , shares the same decoder and adds 4199 more records.


How We Cracked It

The I/O Mapping

Unlike Merit’s 6221 (question ROMs in memory space) or GEI’s T3 (ROMs compressed to 5-bit packed words), Enerdyne’s board puts the question ROMs in the Z80’s I/O space. The Z80 selects a bank by writing bits 3-4 of memory port 0x9000 (control_w in MAME), then reads successive bytes by issuing IN A,(C) with C = 0x08. Bank offsets are kept by the program code, not by the hardware.

The Encoding

Each chip stores three things concatenated:

  1. A 12-byte pointer header at byte 0, six little-endian 16-bit words pointing to sub-regions of the chip:
    • W0, W1: secondary content pointers
    • W2: start of the phrase-length table (one byte per phrase, values 1-15)
    • W3: start of the phrase-text blob (concatenated uppercase ASCII, no separators)
    • W4, W5: repeated marker (unused)
  2. A 22-byte chip-name string followed by 0xFF padding to offset 0x30.
  3. The record stream starting at 0x30.

For the HI chips (loaded at bank offset 0x8000) the header offsets are chip-relative and need +0x8000 to become bank-absolute; for the LO chips they’re already absolute.

The Record Stream

At chip offset 0x30 the record stream begins. It’s a sequence of length-prefixed blocks, one per question: the first byte is the length of the whole block, counting itself, so the next block starts N bytes on. Inside each block the encoding interleaves ASCII characters with token references:

Byte rangeMeaning
0x01-0x17Two-byte phrase token, index = ((byte « 8) | next) − 0x60
0x18-0x1EField separator (between Q and answers, and between each answer; only 0x1E is ever used)
0x1FTune cue (consumes 2 trailing bytes, the tune to play)
0x20-0x5FLiteral ASCII, uppercase letters, digits, punctuation
0x60-0xFFSingle-byte phrase token, index = byte − 0x60

The Phrase Decoder

The Z80 decoder at program-ROM offset ~0x0ED0 takes a token byte (or token byte-pair), computes an index, and walks forward through the chip’s phrase-length table accumulating lengths to step over earlier phrases. When it reaches the target phrase’s slot it reads that phrase’s length, then issues that many IN A,(C) reads from the phrase-text blob. Each byte is decoded by subtracting 0x20 and the result is written directly as a tile index into video RAM at 0xC000/0xE000, the font tile ordering matches the ASCII ordering, so no separate character table is needed for phrase expansion. The earlier research notes claimed a 64-char ASCII lookup at 0x2B7A was used by the decoder; that table is actually for the name-entry / high-score path at 0x0F31, not for question rendering.

For two-byte tokens (first byte 0x01-0x17) the decoder initialises H = first_byte, L = 1 and iterates over ((L-1)*256 + H_init - 1) phrases. Phrase indices are per-chip, so a record’s tokens all resolve inside the same chip’s phrase table.

Splitting Records

Walk the blocks from 0x30, hopping by each length byte. That lands exactly on the phrase table (header word W2) on every chip, which is a nice check that the walk is right. Each block is one question: split it on 0x1E to get exactly four fields, question, correct answer, wrong answer 1, wrong answer 2.

We used to think the length byte didn’t count itself. That’s one byte off, and it meant every block swallowed the next block’s length byte. Questions got glued together (“What Is Merkin A Pubic Wig An Aphrodisiac A Courting Dance!how Did Mata Hari Meet Her Death”), the first one lost its answers, and bits of text went missing. Counting the length byte fixed all of it and more than doubled the yield.

Yield

Sports (sports_leisure)               702
Science Fiction (entertainment)       626
Rock and Pop (entertainment)          615
Entertainment (entertainment)         565
Movies & TV (entertainment)           514
Potpourri II (wild_card)              510
Cars, Boats and Planes (wild_card)    459
Sex II (wild_card)                    456
─────────────────────────────────────────
Total                                4447

What’s Unresolved

Almost nothing. We used to think some two-byte tokens pointed into a secondary table in another bank, and we dropped those records. That was the off-by-one again. With the blocks read correctly every token on every chip resolves in its own chip’s phrase table.

Three Sports records (the John Havlicek / Red Auerbach Hall of Fame block) are chopped into fixed 15-byte pieces in the ROM, so their fields come out rotated. The real cabinet shows them garbled too, so we leave them out.


References


More cracks

Cross-archive analyses


  1. Super Trivia Master (1986, Enerdyne Technologies) · Arcade-Museum · MAME romset: strvmstr ↩︎