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; 745 questions recovered.
April 19, 2026 · crack, enerdyne, strvmstr, z80
Super Trivia Master
Enerdyne Technologies / PGD Inc. · 1986 · ettrivia board · Z80 @ 4 MHz · 745 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:
- Sports (sports.hi0)
- Sex II (sex2.lo0)
- Movies & TV (movies.lo1)
- Rock and Pop (rock-pop.hi1)
- Cars, Boats and Planes (cars.hi2)
- Science Fiction (sci-fi.lo2)
- Entertainment (entrtn.hi3)
- Potpourri II (potprri.lo3)
The Data
All 745 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 852 more records.
- Extractor:
scripts/enerdyne/strvmstr.py - MAME driver:
mame/src/mame/misc/ettrivia.cpp
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:
- 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)
- A 22-byte chip-name string followed by 0xFF padding to offset
0x30. - 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: the first byte is the remaining byte
count, the next N bytes are the block body. Inside each block the
encoding interleaves ASCII characters with token references:
| Byte range | Meaning |
|---|---|
0x01-0x17 | Two-byte phrase token, index = ((byte « 8) | next) − 0x60 |
0x18-0x1D | New-question separator (renders as space, splits Q/A units) |
0x1E | Inline field separator (between Q and answers, and between each answer) |
0x1F | Section boundary (consumes 2 trailing pointer bytes) |
0x20-0x5F | Literal ASCII, uppercase letters, digits, punctuation |
0x60-0xFF | Single-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
Flatten all blocks end-to-end, then split on 0x18-0x1D to break the
stream into one logical record per “new-question” marker. Inside each
unit, split again on 0x1E to get exactly four fields: question,
correct answer, wrong answer 1, wrong answer 2.
Yield
Rock and Pop (entertainment) 121
Potpourri II (wild_card) 119
Movies & TV (entertainment) 116
Sports (sports_leisure) 98
Entertainment (entertainment) 82
Cars, Boats and Planes (wild_card) 79
Science Fiction (entertainment) 67
Sex II (wild_card) 63
─────────────────────────────────────────
Total 745
What’s Unresolved
Two-byte tokens whose prefix is >= 0x10 reference phrase-table
indices beyond each chip’s dictionary size (4,096+ entries into tables
of only 1,500-2,400 phrases). The Z80 counter arithmetic does compute
those indices, they are not truncated, but the actual lookup routes
through CALL 0x04A9 which pulls from a secondary table populated at
startup by a probe at 0x13F0 that reads magic bytes from port
0x0A/0x0B of each bank. Resolving those cross-bank tokens cleanly
requires either running the full Z80 init path in an emulator or
capturing the populated table via hardware trace. Records that
contained unresolved cross-bank tokens were dropped rather than
guessed, this costs ~20-30% potential yield per chip.
References
Related
More cracks
Cross-archive analyses
Super Trivia Master (1986, Enerdyne Technologies) · Arcade-Museum · MAME romset:
strvmstr↩︎