Difference between revisions of "GMA86"

From Software Archive
Jump to navigation Jump to search
Line 2: Line 2:
 
{{Special:Whatlinkshere/GMA86}}
 
{{Special:Whatlinkshere/GMA86}}
  
= Description =
+
= GMA86 =
An exception is [[Robin of the Wood]], that shows GMA86, but uses the same protection code as GMA85.
+
 
 +
'''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
 +
(<code>gma&lt;DDMMYY&gt;</code>, e.g. <code>gma140486</code> = 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 → <code>gm1</code>/<code>gma1</code>
 +
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 <code>M-W</code>/<code>M-E</code>
 +
commands), and has the '''drive itself''' seek an out-of-range track, search
 +
for the family's standard byte-aligned marker (<code>69 xx xx xx A9</code>,
 +
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 <code>CMP</code>/<code>ROL</code>
 +
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''' (<code>$26</code>) — '''C64-side bulk decrypt.''' The
 +
  measured byte is sent to the C64 over a raster-synced <code>$DD00</code>
 +
  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''' (<code>$27</code>) — '''drive-side per-sector decrypt.'''
 +
  The measured byte is instead baked as a literal <code>EOR #imm</code>
 +
  operand 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 <code>$035C</code>/<code>$035D</code>
 +
  key-injection address.
 +
# '''Track 37''' (<code>$25</code>) — '''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
 +
  (<code>gma140486</code>) 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.
 +
 
 +
== Signature measurement: the shared drive-side routine ==
 +
 
 +
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):
 +
 
 +
<pre>
 +
; ---- 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
 +
</pre>
 +
 
 +
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 <code>$DD00</code>, decoded through
 +
a small set of fixed lookup tables, landing in <code>A</code> at the return
 +
of a hijacked <code>GETIN</code> vector. The main loader stashes it
 +
(<code>PHA</code>) immediately after the upload-and-execute call, recovers
 +
it later (<code>PLA</code>/<code>TAX</code>), 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 <code>$26</code> = 38,
 +
confirmed directly) is the cleanest captured example:
 +
 
 +
<pre>
 +
$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
 +
</pre>
 +
 
 +
== 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 <code>GCRBIN</code>/<code>CHKBLK</code> header-verification
 +
calls, and — at the identical <code>$035C</code>/<code>$035D</code> address
 +
in every confirmed example — the measured byte baked directly in as an
 +
<code>EOR #imm</code> 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
 +
<code>$97</code>):
 +
 
 +
<pre>
 +
$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
 +
      ...
 +
</pre>
 +
 
 +
Because the key is injected directly into freshly-uploaded drive code
 +
rather than sent as data, a hunt for <code>EOR #&lt;key&gt;</code>
 +
(<code>49 xx</code>) 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 <code>$02</code>/<code>EOR #$97</code>
 +
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.
 +
 
 +
== See also ==
 +
 
 +
* [[GMA85]]
 +
* [[GMA87]]
 +
* [[Robin of the Wood]]

Revision as of 02:51, 28 August 2026

Pages that refer to this protection

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:

  1. 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.
  1. Track 39 ($27) — drive-side per-sector decrypt.
 The measured byte is instead baked as a literal EOR #imm
 operand 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/$035D
 key-injection address.
  1. 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.

Signature measurement: the shared drive-side routine

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.

See also