GMA86
Contents
Pages that refer to this protection
- Descriptions of old disk copy protections (← links)
- Iridis Alpha (← links)
- GMA87 (← links)
- Sanxion (← links)
- The Sentry (← links)
- Uridium (← links)
- The Graphic Adventure Creator (← links)
- GMA85 (← links)
- Split Personalities (← links)
- Robin of the Wood (← links)
- Pub Games (← links)
- Cyrus II Chess (← links)
- Firelord (← links)
- Filemaster 64 (← links)
GMA86
GMA86 is a Commodore 64 disk copy protection scheme spanning a run of
1986 releases from Firebird, Domark, Alligata, Hewson, Robtek, Thalamus and
others, and the middle generation of the "GMA" protection family — successor
to GMA85, predecessor to GMA87. It shares that family's naming
convention: each disk's BAM label carries a build-date stamp
(gma<DDMMYY>, e.g. gma140486 = 14 Apr 1986 for
Robin of the Wood), and the loader chain keeps the same file-naming
pattern used throughout the family (a boot stub → gm1/gma1
second-stage loader → game data files).
Where GMA85 never derives a key at all, and GMA87's surveyed titles converge on one architecture (a C64-side bulk decrypt, with Eagles as a single confirmed drive-side exception), GMA86 is the generation where a real, disk-specific decryption key first becomes the norm — but it is not architecturally uniform. Of eleven surveyed titles, seven use a C64-side bulk decrypt, three use a drive-side per-sector decrypt otherwise thought unique to Eagles, and one carries the ancestral GMA85 presence-only check forward unchanged, with no key at all. All three mechanisms share the exact same underlying drive-upload plumbing and sync-length measurement primitive; what differs is only what happens to the measured byte afterward, and which out-of-range track it's read from.
Mechanism
Every GMA86 title uploads a short machine-code program to the 1541's own
drive RAM over the serial bus (the standard DOS M-W/M-E
commands), and has the drive itself seek an out-of-range track, search
for the family's standard byte-aligned marker (69 xx xx xx A9,
not decoded to the usual 5-bit GCR nibble boundaries), and — for two of the
three mechanisms below — measure ten raw sync-to-sync pulse-width samples
there, folding them into a single byte via the same CMP/ROL
technique documented for GMA87's Cholo and Triaxos. Which out-of-range track
is targeted correlates exactly with which of the three mechanisms a given
title uses:
- Track 38 (
$26) — C64-side bulk decrypt.
The measured byte is sent to the C64 over a raster-synced $DD00
handshake and used as a single repeating-byte XOR key over almost the
entire game, decrypted in place in one pass before jumping straight into
the result. Seven of eleven surveyed titles: Sanxion, Split Personalities,
Cyrus II Chess, The Sentry, Filemaster 64, Pub Games, and The Graphic
Adventure Creator.
- Track 39 (
$27) — drive-side per-sector decrypt.
The measured byte is instead baked as a literalEOR #immoperand into a second, freshly-uploaded drive-resident program, and the 1541's own 6502 decrypts every subsequent sector before it ever reaches the C64, streaming the result out over a bit-banged serial link one byte at a time. Three of eleven surveyed titles, all Hewson-published: Firelord, Uridium, and Iridis Alpha — matching GMA87's Eagles almost byte-for-byte, including the identical$035C/$035Dkey-injection address.
- Track 37 (
$25) — presence-only, no key. The
drive reads two raw 256-byte blocks off the track and reports success
unconditionally; nothing is ever folded, compared, or sent. This is the
ancestral GMA85 mechanism, carried forward unmodified. One of eleven
surveyed titles: Robin of the Wood, whose disk-label date
(gma140486) places it firmly within the GMA86 era despite
running GMA85-generation drive code.
On any genuine failure — marker not found within the retry budget, or a failed job status — the drive hangs permanently in an infinite self-loop rather than reporting an error the C64 could act on, the same "hang, never produce wrong output" convention used throughout the whole GMA family.
Confirmed byte-for-byte identical (Firelord, Uridium, Iridis Alpha) or structurally identical down to the exact same offsets (the C64-side titles, confirmed point-by-point against Cholo's own upload routine) to the mechanism already documented in detail for GMA87. The only things that vary between tracks 38 and 39 are the literal target-track constant and, for the drive-side variant, what happens to the result afterward (see below):
; ---- sync-marker search, 90-attempt retry budget ----
$0300 AD 00 1C LDA $1C00
$0303 29 9F AND #$9F
$0305 8D 00 1C STA $1C00
$0308 A0 5A LDY #$5A ; Y = 90 - sync-retry budget
$030A 88 DEY ; <-- retry entry point
$030B D0 05 BNE $0312
$030D A9 02 LDA #$02 ; error $02 = HEADER NOT FOUND
$030F 4C 69 F9 JMP $F969 ; ERRR - retries exhausted, report failure
$0312 2C 00 1C BIT $1C00
$0315 30 FB BMI $0312 ; sync-wait poll
$0317 AD 01 1C LDA $1C01 ; discard first raw byte after sync
$031A B8 CLV
$031B A2 04 LDX #$04
$031D 50 FE BVC $031D ; CLV/BVC byte-ready wait (classic 1541 trick)
$031F B8 CLV
$0320 AD 01 1C LDA $1C01 ; read raw GCR byte
$0323 9D 00 05 STA $0500,X ; store into $0500-$0504 (5 bytes)
$0326 CA DEX
$0327 10 F4 BPL $031D
$0329 C9 A9 CMP #$A9 ; last byte read must be $A9
$032B D0 DD BNE $030A ; mismatch -> retry
$032D AD 04 05 LDA $0504 ; first byte read (2nd overall)
$0330 C9 69 CMP #$69 ; must be $69
$0332 D0 D6 BNE $030A ; mismatch -> retry
; signature "69 xx xx xx A9" confirmed
; ---- 10-sample raw pulse-width (sync-length) measurement ----
$0334 A0 00 LDY #$00
$0336 2C 00 1C BIT $1C00
$0339 30 FB BMI $0336 ; wait for next sync
$033B A2 00 LDX #$00
$033D E8 INX ; <-- pulse-width measurement loop
$033E 2C 00 1C BIT $1C00
$0341 10 FA BPL $033D ; count iterations (X) while bit7=0
$0343 8A TXA
$0344 99 00 05 STA $0500,Y ; store sample[Y]
$0347 C8 INY
$0348 C0 0A CPY #$0A ; 10 samples total
$034A D0 EA BNE $0336
; ---- fold 10 samples into an 8-bit result via CMP/ROL ----
$034C A2 02 LDX #$02 ; sample[0] discarded, sample[1] = reference
$034E BD 00 05 LDA $0500,X
$0351 CD 01 05 CMP $0501 ; compare sample[X] to reference
$0354 2E 0A 05 ROL $050A ; roll carry (>=ref->1, <ref->0) into result byte
$0357 E8 INX
$0358 E0 0A CPX #$0A ; samples[2..9], 8 comparisons -> 8-bit result
$035A D0 F2 BNE $034E
$035C AE 0A 05 LDX $050A ; X = computed 8-bit sync-length result
; ---- job setup: target track, submit EXECUTE job, check result ----
LDA #<track> ; $26 (38) for the C64-side variant,
STA $06 ; $27 (39) for the drive-side variant
...
JMP <infinite self-loop> ; on failure status - hang forever
The remainder — how the result byte is used — is where the three GMA86 mechanisms diverge.
Variant A: C64-side bulk decrypt
The measured byte is sent to the C64 the same way GMA87's Cholo/Triaxos do
it: a raster-line-synced read of CIA2's $DD00, decoded through
a small set of fixed lookup tables, landing in A at the return
of a hijacked GETIN vector. The main loader stashes it
(PHA) immediately after the upload-and-execute call, recovers
it later (PLA/TAX), and feeds it into a
self-modifying XOR loop that walks upward through memory decrypting the
game in place before jumping straight into the result — confirmed
byte-for-byte structurally identical (just different target addresses and
end-page constants) across all seven C64-side titles.
The Graphic Adventure Creator's build (target track $26 = 38,
confirmed directly) is the cleanest captured example:
$401F JSR $C800 ; the fixed drive-upload-and-execute trigger
$4022 PHA ; stash the measured key
$4023 LDA #$00 / JSR $42AB
$4028 PLA ; recover it
$4029 TAX ; X = $C3 (this disk's measured key)
$402A LDA $01 / PHA / AND #$FE / STA $01 ; bank out BASIC ROM
$4031 TXA / EOR $C900 / STA $C900 ; self-modifying decrypt
$4038 INC $4033 / INC $4036 / BNE $4031
$4040 INC $4034 / INC $4037
LDA $4034 / CMP #$C9 / BNE $4031
$404D PLA / STA $01 ; restore memory config
$4050 ... ; standard KERNAL cold-start-ish sequence
Variant B: drive-side per-sector decrypt
Firelord, Uridium, and Iridis Alpha instead move the decrypt onto the 1541
itself, matching GMA87's Eagles almost line-for-line: once the signature
measurement above completes, a second program is uploaded into drive
RAM, overwriting the first. It contains a GCR sector-read loop, the standard
DOS ROM's own GCRBIN/CHKBLK header-verification
calls, and — at the identical $035C/$035D address
in every confirmed example — the measured byte baked directly in as an
EOR #imm immediate operand, decrypting each data byte as it's
read and streaming the already-decrypted result to the C64 over the
bit-banged serial link. Confirmed live for Uridium (measured key
$97):
$0359 BD 00 06 LDA $0600,Y ; raw (still-encrypted) byte off the sector buffer
$035C 49 97 EOR #$97 ; the measured sync-length byte, baked in as a
; literal immediate operand at upload time
$035E AA TAX ; decrypted byte ready to send/store
...
Because the key is injected directly into freshly-uploaded drive code
rather than sent as data, a hunt for EOR #<key>
(49 xx) across drive RAM after the upload reliably locates this
instruction — the same technique used to confirm all three drive-side
titles here and Eagles in GMA87. All three drive-side GMA86 titles are
Hewson-published, matching Eagles' own publisher; the C64-side titles found
in this survey are Domark, Alligata, Firebird, Ariolasoft, Robtek, and
Thalamus releases — a suggestive publisher-level correlation, though not
established as a rule (Firelord's own publisher wasn't independently
confirmed, and no non-Hewson drive-side counterexample was specifically
sought).
Variant C: presence-only, no key
Robin of the Wood's disk-label date places it within the GMA86 era, but its
drive-side program is confirmed byte-for-byte identical to the GMA85
generation's: target track 37, two raw 256-byte blocks read and discarded,
success reported unconditionally. Confirmed experimentally by corrupting the
track's surrounding "salt" bytes while preserving the marker — no change in
behavior. No sync-length measurement of any kind occurs on this title's
out-of-range track. See GMA85 for the full annotated disassembly of this
mechanism, including the C64-side loader's $02/EOR #$97
check some (but not all) titles of that generation carry — a plausible
code-integrity tripwire against a patched-out upload call, not a
disk-content validation, and not specific to Robin of the Wood; it belongs
to the inherited GMA85 loader, not to anything introduced in GMA86.
Relationship to GMA85 and GMA87
GMA86 sits directly between the two: it inherits GMA85's presence-only mechanism wholesale (still shipping on at least one GMA86-labeled title), and it establishes — a full year before GMA87 — both real-key architectures GMA87 titles use, including the drive-side variant later found in Eagles and, until this survey, thought to be an isolated architectural outlier within the whole GMA family. It isn't: the drive-side decrypt is an established technique in this author's toolkit that predates Eagles by at least a year, reused essentially unchanged.