<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://preservation64.de/index.php?action=history&amp;feed=atom&amp;title=Cholo_GMA87</id>
	<title>Cholo GMA87 - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://preservation64.de/index.php?action=history&amp;feed=atom&amp;title=Cholo_GMA87"/>
	<link rel="alternate" type="text/html" href="https://preservation64.de/index.php?title=Cholo_GMA87&amp;action=history"/>
	<updated>2026-08-28T15:42:35Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.34.0-alpha</generator>
	<entry>
		<id>https://preservation64.de/index.php?title=Cholo_GMA87&amp;diff=75699&amp;oldid=prev</id>
		<title>Enigma at 22:22, 24 August 2026</title>
		<link rel="alternate" type="text/html" href="https://preservation64.de/index.php?title=Cholo_GMA87&amp;diff=75699&amp;oldid=prev"/>
		<updated>2026-08-24T22:22:15Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table class=&quot;diff diff-contentalign-left&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #222; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #222; text-align: center;&quot;&gt;Revision as of 22:22, 24 August 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l400&quot; &gt;Line 400:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 400:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   &amp;lt;code&amp;gt;$1000&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;$C000&amp;lt;/code&amp;gt;, decrypted range&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   &amp;lt;code&amp;gt;$1000&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;$C000&amp;lt;/code&amp;gt;, decrypted range&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   &amp;lt;code&amp;gt;$6400&amp;lt;/code&amp;gt;–&amp;lt;code&amp;gt;$CFFF&amp;lt;/code&amp;gt;)&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   &amp;lt;code&amp;gt;$6400&amp;lt;/code&amp;gt;–&amp;lt;code&amp;gt;$CFFF&amp;lt;/code&amp;gt;)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Starfox]] (&lt;del class=&quot;diffchange diffchange-inline&quot;&gt;two independently-dumped sources, &lt;/del&gt;keys agree &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;exactly&lt;/del&gt;)&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Starfox]] (keys agree &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;among sources&lt;/ins&gt;)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Jagd auf Roter Oktober]] (&lt;del class=&quot;diffchange diffchange-inline&quot;&gt;two independently-dumped sources, &lt;/del&gt;keys agree &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;exactly&lt;/del&gt;)&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Jagd auf Roter Oktober]] (keys agree &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;among sources&lt;/ins&gt;)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Enlightenment: Druid II]]&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Enlightenment: Druid II]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Delta]] (&lt;del class=&quot;diffchange diffchange-inline&quot;&gt;six independently-dumped sources, &lt;/del&gt;keys agree &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;exactly&lt;/del&gt;)&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Delta]] (keys agree &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;among sources&lt;/ins&gt;)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Kat Trap: Planet of the Cat-Men]]&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Kat Trap: Planet of the Cat-Men]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Cataball]] (via &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;''&lt;/del&gt;Hit Pak: Trio&lt;del class=&quot;diffchange diffchange-inline&quot;&gt;''&lt;/del&gt;)&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Cataball]] (via &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;[[&lt;/ins&gt;Hit Pak: Trio&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;]]&lt;/ins&gt;)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Bride of Frankenstein]]&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Bride of Frankenstein]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Bubble Bobble]] (three sources; two distinct physical pressings identified by&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Bubble Bobble]] (three sources; two distinct physical pressings identified by differing keys)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del class=&quot;diffchange diffchange-inline&quot;&gt;  &lt;/del&gt;differing keys)&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot;&gt; &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Flying Shark]]&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Flying Shark]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[James Bond 007&lt;del class=&quot;diffchange diffchange-inline&quot;&gt;: &lt;/del&gt;The Living Daylights]] / &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;''&lt;/del&gt;Der Hauch des Todes&lt;del class=&quot;diffchange diffchange-inline&quot;&gt;'' &lt;/del&gt;(same&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[James Bond 007 &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;in &lt;/ins&gt;The Living Daylights&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;: The Computer Game&lt;/ins&gt;]] / &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;[[James Bond 007 in &lt;/ins&gt;Der Hauch des Todes&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;: Das Computerspiel]] &lt;/ins&gt;(same release, listed separately under its German title on the wiki)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del class=&quot;diffchange diffchange-inline&quot;&gt;  &lt;/del&gt;release, listed separately under its German title on the wiki)&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Sidewize]] (keys agree &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;among sources&lt;/ins&gt;)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Sidewize]] (&lt;del class=&quot;diffchange diffchange-inline&quot;&gt;two sources, &lt;/del&gt;keys agree &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;exactly&lt;/del&gt;)&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot;&gt; &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Twin Tornado]]&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Twin Tornado]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Evening Star / Southern Belle]] &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;(independently matches a previously-published&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Evening Star / Southern Belle]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del class=&quot;diffchange diffchange-inline&quot;&gt;  key value on this game's own wiki page)&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot;&gt; &lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Revs+]]&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Revs+]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Zynaps]] (two sources, keys agree exactly)&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Zynaps]] (two sources, keys agree exactly)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Mystery of the Nile]]&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Mystery of the Nile]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Scary Monsters]]&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Scary Monsters]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Airwolf 2]] (via &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;''&lt;/del&gt;Hit Pak: Trio&lt;del class=&quot;diffchange diffchange-inline&quot;&gt;''&lt;/del&gt;) — same physical disk as Cataball, same key&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Airwolf 2]] (via &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;[[&lt;/ins&gt;Hit Pak: Trio&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;]]&lt;/ins&gt;) — same physical disk as Cataball, same key&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Great Gurianos]] (via &lt;del class=&quot;diffchange diffchange-inline&quot;&gt;''&lt;/del&gt;Hit Pak: Trio&lt;del class=&quot;diffchange diffchange-inline&quot;&gt;''&lt;/del&gt;) — same physical disk side as&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Great Gurianos]] (via &lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;[[&lt;/ins&gt;Hit Pak: Trio&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;]]&lt;/ins&gt;) — same physical disk side as&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del class=&quot;diffchange diffchange-inline&quot;&gt;  &lt;/del&gt;[[Airwolf 2]], same key&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;* &lt;/ins&gt;[[Airwolf 2]], same key&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;'''Not''' on this list: [[Eagles GMA87|Eagles]], which carries the same disk&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;'''Not''' on this list: [[Eagles GMA87|Eagles]], which carries the same disk&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Enigma</name></author>
		
	</entry>
	<entry>
		<id>https://preservation64.de/index.php?title=Cholo_GMA87&amp;diff=75698&amp;oldid=prev</id>
		<title>Enigma: Created page with &quot;= Cholo (C64) — GMA87 copy protection, full technical write-up =  This article documents, in full technical detail, the copy protection scheme used by the Commodore 64 relea...&quot;</title>
		<link rel="alternate" type="text/html" href="https://preservation64.de/index.php?title=Cholo_GMA87&amp;diff=75698&amp;oldid=prev"/>
		<updated>2026-08-24T22:18:34Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;= Cholo (C64) — GMA87 copy protection, full technical write-up =  This article documents, in full technical detail, the copy protection scheme used by the Commodore 64 relea...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;= Cholo (C64) — GMA87 copy protection, full technical write-up =&lt;br /&gt;
&lt;br /&gt;
This article documents, in full technical detail, the copy protection scheme&lt;br /&gt;
used by the Commodore 64 release of '''Cholo''' (1986/87). Cholo carries a&lt;br /&gt;
&amp;lt;code&amp;gt;GMA87&amp;lt;/code&amp;gt; disk label — named after a credit string embedded in the&lt;br /&gt;
loader itself, &amp;lt;code&amp;gt;&amp;quot;GMA WAS HERE 1986&amp;quot;&amp;lt;/code&amp;gt; — and its exact algorithm is&lt;br /&gt;
shared, byte-for-byte in structure, by at least twenty other C64 titles&lt;br /&gt;
linking to the [https://preservation64.de/index.php?title=GMA87 GMA87] wiki&lt;br /&gt;
page (full list at the end of this article). Every address below is&lt;br /&gt;
Cholo's own loader build (&amp;lt;code&amp;gt;gm1.prg&amp;lt;/code&amp;gt; at &amp;lt;code&amp;gt;$C000&amp;lt;/code&amp;gt;) unless&lt;br /&gt;
noted.&lt;br /&gt;
&lt;br /&gt;
== Summary ==&lt;br /&gt;
&lt;br /&gt;
* The protection does not simply check-and-refuse. It reads a physically&lt;br /&gt;
  unclonable property of the original disk — sync length variation in a&lt;br /&gt;
  deliberately malformed sync region on '''track 38''' — folds it into a&lt;br /&gt;
  single byte, and uses that byte as an XOR decryption key for essentially&lt;br /&gt;
  the entire game (~25.5 KB, &amp;lt;code&amp;gt;$4461&amp;lt;/code&amp;gt;–&amp;lt;code&amp;gt;$A7FF&amp;lt;/code&amp;gt;).&lt;br /&gt;
* A disk copy that doesn't reproduce the exact sync pattern doesn't get&lt;br /&gt;
  refused with an error — it decrypts the game into garbage and crashes&lt;br /&gt;
  when execution jumps into the decrypted region. '''There is no&lt;br /&gt;
  compare-and-branch to defeat by patching.'''&lt;br /&gt;
* Measured key for this disk capture: &amp;lt;code&amp;gt;$B1&amp;lt;/code&amp;gt; (177 decimal),&lt;br /&gt;
* This is the &amp;quot;standard&amp;quot; GMA87 mechanism — key measured on the drive, sent&lt;br /&gt;
  to the C64 as one byte, decrypted on the C64 in a single in-place pass.&lt;br /&gt;
  Compare this to [[Eagles GMA87|Eagles]], that&lt;br /&gt;
  moves the decryption step itself onto the drive's own 6502 instead.&lt;br /&gt;
&lt;br /&gt;
== Disk layout ==&lt;br /&gt;
&lt;br /&gt;
* Tracks 1–35 are a normal CBM DOS layout (verified: standard &amp;lt;code&amp;gt;$08&amp;lt;/code&amp;gt;&lt;br /&gt;
  header / &amp;lt;code&amp;gt;$07&amp;lt;/code&amp;gt; data blocks, correct track/sector/id checksums&lt;br /&gt;
  throughout).&lt;br /&gt;
* Tracks '''36–40''' are non-standard — outside the range a stock-formatted&lt;br /&gt;
  disk ever uses, reachable only by a loader that steps the drive head there&lt;br /&gt;
  directly. Decoded, each of these tracks (except track 38's third block)&lt;br /&gt;
  contains three near-identical repeating groups:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
sync 41 (or 40)&lt;br /&gt;
bits 0110100101&lt;br /&gt;
bytes &amp;lt;2-byte per-track &amp;quot;salt&amp;quot;&amp;gt; 8e 8d 55 55 ... 55 57&lt;br /&gt;
bits 111111&lt;br /&gt;
&lt;br /&gt;
sync 40&lt;br /&gt;
gcr 09                      &amp;lt;- non-standard block-ID; not $07 or $08&lt;br /&gt;
bytes 59 59 59 59 59 55 ... (mostly $55 filler)&lt;br /&gt;
bits 111111&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  The actual protection-check works on raw, byte-aligned reads straight off&lt;br /&gt;
  the drive's GCR shift register and it only ever looks at '''track 38'''.&lt;br /&gt;
* '''Track 38''' additionally has a distinctive tail after its third&lt;br /&gt;
  sync/data group: several short blocks with unusual, non-standard sync&lt;br /&gt;
  lengths ('''87''' and '''136''' &amp;quot;1&amp;quot;-bits, vs. the normal ~40), tagged&lt;br /&gt;
  &amp;lt;code&amp;gt;gcr 0f&amp;lt;/code&amp;gt;, ending in a long run of &amp;lt;code&amp;gt;$aa&amp;lt;/code&amp;gt; filler.&lt;br /&gt;
&lt;br /&gt;
== Loader chain ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;b&amp;lt;/code&amp;gt; (boot stub, relocates itself, loads &amp;lt;code&amp;gt;GM1&amp;lt;/code&amp;gt;) →&lt;br /&gt;
&amp;lt;code&amp;gt;gm1.prg&amp;lt;/code&amp;gt; (loaded to &amp;lt;code&amp;gt;$C000&amp;lt;/code&amp;gt;) →&lt;br /&gt;
&amp;lt;code&amp;gt;gma2.prg&amp;lt;/code&amp;gt; (loaded to &amp;lt;code&amp;gt;$C800&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;gm1.prg&amp;lt;/code&amp;gt;'s main entry:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$C000  4C 27 C0    JMP $C027          ; cold entry&lt;br /&gt;
$C003  4C 56 C0    JMP $C056          ; (alternate entry, not traced this pass)&lt;br /&gt;
...&lt;br /&gt;
$C027  A9 00       LDA #$00&lt;br /&gt;
$C029  20 90 FF    JSR $FF90          ; SETMSG (suppress KERNAL messages)&lt;br /&gt;
$C02C  A9 FF       LDA #$FF&lt;br /&gt;
$C02E  8D 29 03    STA $0329&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
then, continuing into the protection sequence itself:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$C030  ...&lt;br /&gt;
$C034  20 FD C2    JSR $C2FD          ; install the GETIN vector hijack (see below)&lt;br /&gt;
$C037  20 28 C3    JSR $C328          ; build the $0100 lookup table (see below)&lt;br /&gt;
$C03A  A9 02       LDA #$02&lt;br /&gt;
$C03C  20 89 C0    JSR $C089          ; (status/border helper, not traced)&lt;br /&gt;
$C03F  20 00 C8    JSR $C800          ; upload + execute the drive-side check,&lt;br /&gt;
                                       ;   collect the result byte in A&lt;br /&gt;
$C042  48          PHA                ; stash the measured key byte&lt;br /&gt;
$C043  A9 00       LDA #$00&lt;br /&gt;
$C045  8D 24 C0    STA $C024&lt;br /&gt;
$C048  A9 0D       LDA #$0D&lt;br /&gt;
$C04A  8D 25 C0    STA $C025&lt;br /&gt;
$C04D  20 89 C0    JSR $C089&lt;br /&gt;
$C050  20 00 0D    JSR $0D00          ; (fast-loader Y/N prompt lives around here)&lt;br /&gt;
$C053  4C 03 C1    JMP $C103          ; -&amp;gt; pull the key back and decrypt (see below)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== The GETIN vector hijack: the C64-side receiver ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;$C2FD&amp;lt;/code&amp;gt; repurposes the KERNAL &amp;lt;code&amp;gt;GETIN&amp;lt;/code&amp;gt; vector&lt;br /&gt;
(&amp;lt;code&amp;gt;$032A&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;$032B&amp;lt;/code&amp;gt;) to point at &amp;lt;code&amp;gt;$C308&amp;lt;/code&amp;gt;,&lt;br /&gt;
'''unconditionally''' — regardless of the separate &amp;quot;use fast loader?&amp;quot; Y/N&lt;br /&gt;
prompt shown during boot. &amp;lt;code&amp;gt;gma2.prg&amp;lt;/code&amp;gt;'s upload-and-execute routine&lt;br /&gt;
(&amp;lt;code&amp;gt;$C800&amp;lt;/code&amp;gt;, below) later calls the standard &amp;lt;code&amp;gt;GETIN&amp;lt;/code&amp;gt;&lt;br /&gt;
entry (&amp;lt;code&amp;gt;$FFE4&amp;lt;/code&amp;gt;) purely to trigger this hijacked path and collect&lt;br /&gt;
the drive's answer in &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$C308  08          PHP&lt;br /&gt;
$C309  78          SEI&lt;br /&gt;
$C30A  A5 01       LDA $01            ; processor port (memory config)&lt;br /&gt;
$C30C  48          PHA                ; save it&lt;br /&gt;
$C30D  29 FD       AND #$FD&lt;br /&gt;
$C30F  09 05       ORA #$05           ; bank out BASIC ROM, keep I/O visible&lt;br /&gt;
$C311  85 01       STA $01&lt;br /&gt;
$C313  AD 00 DD    LDA $DD00          ; read CIA2 port A once...&lt;br /&gt;
$C316  29 07       AND #$07&lt;br /&gt;
$C318  85 44       STA $44            ; ...build the &amp;quot;release&amp;quot; bit-pattern&lt;br /&gt;
$C31A  09 08       ORA #$08&lt;br /&gt;
$C31C  85 43       STA $43            ; ...and the &amp;quot;request&amp;quot; bit-pattern&lt;br /&gt;
$C31E  20 E3 C1    JSR $C1E3          ; do the actual raster-synced handshake+read&lt;br /&gt;
$C321  A8          TAY&lt;br /&gt;
$C322  68          PLA&lt;br /&gt;
$C323  85 01       STA $01            ; restore memory config&lt;br /&gt;
$C325  98          TYA&lt;br /&gt;
$C326  28          PLP&lt;br /&gt;
$C327  60          RTS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The real cycle-accurate handshake lives in the shared subroutine&lt;br /&gt;
&amp;lt;code&amp;gt;$C1E3&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$C1E3  A5 43       LDA $43&lt;br /&gt;
$C1E5  8D 00 DD    STA $DD00          ; write to CIA2 port A (drive-facing)&lt;br /&gt;
$C1E8  AD 00 DD    LDA $DD00&lt;br /&gt;
$C1EB  10 FB       BPL $C1E8          ; wait for bit 7 - a response from the drive&lt;br /&gt;
$C1ED  AD 12 D0    LDA $D012          ; raster line&lt;br /&gt;
$C1F0  C9 31       CMP #$31&lt;br /&gt;
$C1F2  90 06       BCC $C1FA&lt;br /&gt;
$C1F4  29 06       AND #$06&lt;br /&gt;
$C1F6  C9 02       CMP #$02&lt;br /&gt;
$C1F8  F0 F3       BEQ $C1ED          ; cycle-accurate raster-synced wait&lt;br /&gt;
$C1FA  A5 44       LDA $44&lt;br /&gt;
$C1FC  8D 00 DD    STA $DD00&lt;br /&gt;
$C1FF  EA (x9)     NOP                ; fixed-length timing pad&lt;br /&gt;
$C209  AE 00 DD    LDX $DD00          ; read the port value...&lt;br /&gt;
$C20C  BD 00 01    LDA $0100,X        ; ...as an INDEX into a lookup table&lt;br /&gt;
$C20F  AE 00 DD    LDX $DD00&lt;br /&gt;
       ...                            ; (three more reads, three more tables,&lt;br /&gt;
                                       ;  OR'd together - structurally identical&lt;br /&gt;
                                       ;  to Eagles' $05EB continuation)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This reads CIA2's &amp;lt;code&amp;gt;$DD00&amp;lt;/code&amp;gt; port with cycle-accurate raster-line&lt;br /&gt;
synchronization and decodes the drive's response into a byte using&lt;br /&gt;
four 256-entry lookup tables as a nibble/bit decoder. Those tables are&lt;br /&gt;
'''fixed, not disk-derived''' — built once by a plain tiling loop:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$C328  A2 00       LDX #$00&lt;br /&gt;
$C32A  A0 00       LDY #$00&lt;br /&gt;
$C32C  A9 08       LDA #$08&lt;br /&gt;
$C32E  8D 66 C3    STA $C366&lt;br /&gt;
$C331  BD 4A C3    LDA $C34A,X        ; fixed 28-byte source table at $C34A&lt;br /&gt;
$C334  99 00 01    STA $0100,Y&lt;br /&gt;
$C337  C8          INY&lt;br /&gt;
$C338  CE 66 C3    DEC $C366&lt;br /&gt;
$C33B  D0 F7       BNE $C334          ; each source byte repeated 8 times&lt;br /&gt;
$C33D  E8          INX&lt;br /&gt;
$C33E  E0 1C       CPX #$1C           ; 28 source bytes total&lt;br /&gt;
$C340  90 EA       BCC $C32C&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
They only gate ''whether'' the handshake can complete at all; they don't&lt;br /&gt;
encode a disk-specific value into the transferred byte.&lt;br /&gt;
&lt;br /&gt;
== The drive-side check: uploaded and executed on the 1541's own CPU ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;gma2.prg&amp;lt;/code&amp;gt;, from &amp;lt;code&amp;gt;$C86C&amp;lt;/code&amp;gt;, first opens the drive's&lt;br /&gt;
command channel and sends the &amp;lt;code&amp;gt;&amp;quot;M-&amp;quot;&amp;lt;/code&amp;gt; prefix of a standard 1541&lt;br /&gt;
DOS &amp;lt;code&amp;gt;M-W&amp;lt;/code&amp;gt; command, exactly the same KERNAL sequence documented&lt;br /&gt;
for Eagles' upload mechanism:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$C86C  A9 00       LDA #$00&lt;br /&gt;
$C86E  20 BD FF    JSR $FFBD          ; SETNAM (empty name)&lt;br /&gt;
$C871  A9 0F       LDA #$0F           ; A = 15&lt;br /&gt;
$C873  A8          TAY                ; Y = 15 (secondary address = command channel)&lt;br /&gt;
$C874  A2 08       LDX #$08           ; X = 8 (device 8)&lt;br /&gt;
$C876  20 BA FF    JSR $FFBA          ; SETLFS(LFN=15, dev=8, SA=15)&lt;br /&gt;
$C879  20 C0 FF    JSR $FFC0          ; OPEN&lt;br /&gt;
$C87C  A2 0F       LDX #$0F&lt;br /&gt;
$C87E  20 C9 FF    JSR $FFC9          ; CHKOUT(15)&lt;br /&gt;
$C881  A9 4D       LDA #$4D / JSR $FFD2   ; CHROUT 'M'&lt;br /&gt;
$C886  A9 2D       LDA #$2D / JSR $FFD2   ; CHROUT '-'&lt;br /&gt;
$C88B  60          RTS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Immediately following, at &amp;lt;code&amp;gt;$C88C&amp;lt;/code&amp;gt;–&amp;lt;code&amp;gt;$C93C&amp;lt;/code&amp;gt;, is the&lt;br /&gt;
'''177-byte payload''' of that &amp;lt;code&amp;gt;M-W&amp;lt;/code&amp;gt; command — which is, at the&lt;br /&gt;
same time, the literal source bytes of the drive-side program about to be&lt;br /&gt;
uploaded (this region disassembles identically to the live drive-RAM copy&lt;br /&gt;
at &amp;lt;code&amp;gt;$0300&amp;lt;/code&amp;gt; shown below, because it ''is'' that copy, still&lt;br /&gt;
sitting in C64 RAM before transmission):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$C88C  AD 00 1C    LDA $1C00&lt;br /&gt;
$C88F  29 9F       AND #$9F&lt;br /&gt;
$C891  8D 00 1C    STA $1C00&lt;br /&gt;
...                                    ; (identical to drive $0300 below)&lt;br /&gt;
$C91A  A9 01       LDA #$01&lt;br /&gt;
$C91C  4C 69 F9    JMP $F969&lt;br /&gt;
$C91F  A9 26       LDA #$26            ; $26 = 38 decimal - THE TARGET TRACK&lt;br /&gt;
$C921  85 06       STA $06&lt;br /&gt;
$C923  A9 01       LDA #$01&lt;br /&gt;
$C925  85 07       STA $07&lt;br /&gt;
$C927  20 18 C1    JSR $C118           ; (ROM call)&lt;br /&gt;
$C92A  A9 E0       LDA #$E0&lt;br /&gt;
$C92C  85 00       STA $00             ; submit EXECUTE job (buffer 0)&lt;br /&gt;
$C92E  A5 00       LDA $00&lt;br /&gt;
$C930  30 FC       BMI $C92E           ; wait for job completion&lt;br /&gt;
$C932  C9 02       CMP #$02&lt;br /&gt;
$C934  90 06       BCC $C93C           ; status &amp;lt; 2 (success) -&amp;gt; RTS normally&lt;br /&gt;
$C936  4C AA 03    JMP $03AA           ; status &amp;gt;= 2 (FAILURE) -&amp;gt; jump into the&lt;br /&gt;
                                       ;   just-uploaded drive copy's own hang loop&lt;br /&gt;
$C939  20 2C C1    JSR $C12C           ; (unreached in the traced path)&lt;br /&gt;
$C93C  60          RTS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After the &amp;lt;code&amp;gt;M-W&amp;lt;/code&amp;gt; data is sent, &amp;lt;code&amp;gt;gma2.prg&amp;lt;/code&amp;gt; issues an&lt;br /&gt;
&amp;lt;code&amp;gt;M-E $0393&amp;lt;/code&amp;gt; command — the standard 1541 DOS &amp;quot;memory-execute&amp;quot;&lt;br /&gt;
command — to actually run the freshly-uploaded code on the drive, starting&lt;br /&gt;
at its job-setup entry point (&amp;lt;code&amp;gt;$0393&amp;lt;/code&amp;gt;, see below).&lt;br /&gt;
&lt;br /&gt;
=== Full annotated disassembly: the uploaded drive routine (&amp;lt;code&amp;gt;$0300&amp;lt;/code&amp;gt;–&amp;lt;code&amp;gt;$03B0&amp;lt;/code&amp;gt;) ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
; ---- sync-marker search, 90-attempt retry budget ----&lt;br /&gt;
$0300  AD 00 1C    LDA $1C00&lt;br /&gt;
$0303  29 9F       AND #$9F&lt;br /&gt;
$0305  8D 00 1C    STA $1C00&lt;br /&gt;
$0308  A0 5A       LDY #$5A            ; Y = 90 - sync-retry budget&lt;br /&gt;
$030A  88          DEY                 ; &amp;lt;-- retry entry point&lt;br /&gt;
$030B  D0 05       BNE $0312&lt;br /&gt;
$030D  A9 02       LDA #$02            ; error $02 = HEADER NOT FOUND&lt;br /&gt;
$030F  4C 69 F9    JMP $F969           ; ERRR - retries exhausted, report failure&lt;br /&gt;
$0312  2C 00 1C    BIT $1C00&lt;br /&gt;
$0315  30 FB       BMI $0312           ; sync-wait poll&lt;br /&gt;
$0317  AD 01 1C    LDA $1C01           ; discard first raw byte after sync&lt;br /&gt;
$031A  B8          CLV&lt;br /&gt;
$031B  A2 04       LDX #$04&lt;br /&gt;
$031D  50 FE       BVC $031D           ; CLV/BVC byte-ready wait (classic 1541 trick)&lt;br /&gt;
$031F  B8          CLV&lt;br /&gt;
$0320  AD 01 1C    LDA $1C01           ; read raw GCR byte&lt;br /&gt;
$0323  9D 00 05    STA $0500,X         ; store into $0500-$0504 (5 bytes)&lt;br /&gt;
$0326  CA          DEX&lt;br /&gt;
$0327  10 F4       BPL $031D&lt;br /&gt;
$0329  C9 A9       CMP #$A9            ; last byte read must be $A9&lt;br /&gt;
$032B  D0 DD       BNE $030A           ; mismatch -&amp;gt; retry&lt;br /&gt;
$032D  AD 04 05    LDA $0504           ; first byte read (2nd overall)&lt;br /&gt;
$0330  C9 69       CMP #$69            ; must be $69&lt;br /&gt;
$0332  D0 D6       BNE $030A           ; mismatch -&amp;gt; retry&lt;br /&gt;
                                        ; signature &amp;quot;69 xx xx xx A9&amp;quot; confirmed&lt;br /&gt;
&lt;br /&gt;
; ---- 10-sample raw pulse-width (flux-jitter) measurement ----&lt;br /&gt;
$0334  A0 00       LDY #$00&lt;br /&gt;
$0336  2C 00 1C    BIT $1C00&lt;br /&gt;
$0339  30 FB       BMI $0336           ; wait for next sync&lt;br /&gt;
$033B  A2 00       LDX #$00&lt;br /&gt;
$033D  E8          INX                 ; &amp;lt;-- pulse-width measurement loop&lt;br /&gt;
$033E  2C 00 1C    BIT $1C00&lt;br /&gt;
$0341  10 FA       BPL $033D           ; count iterations (X) while bit7=0&lt;br /&gt;
$0343  8A          TXA&lt;br /&gt;
$0344  99 00 05    STA $0500,Y         ; store sample[Y]&lt;br /&gt;
$0347  C8          INY&lt;br /&gt;
$0348  C0 0A       CPY #$0A            ; 10 samples total&lt;br /&gt;
$034A  D0 EA       BNE $0336&lt;br /&gt;
&lt;br /&gt;
; ---- fold 10 samples into an 8-bit result via CMP/ROL ----&lt;br /&gt;
$034C  A2 02       LDX #$02            ; sample[0] discarded, sample[1] = reference&lt;br /&gt;
$034E  BD 00 05    LDA $0500,X&lt;br /&gt;
$0351  CD 01 05    CMP $0501           ; compare sample[X] to reference&lt;br /&gt;
$0354  2E 0A 05    ROL $050A           ; roll carry (&amp;gt;=ref-&amp;gt;1, &amp;lt;ref-&amp;gt;0) into result byte&lt;br /&gt;
$0357  E8          INX&lt;br /&gt;
$0358  E0 0A       CPX #$0A            ; samples[2..9], 8 comparisons -&amp;gt; 8-bit result&lt;br /&gt;
$035A  D0 F2       BNE $034E&lt;br /&gt;
$035C  AE 0A 05    LDX $050A           ; X = computed 8-bit result: $B1 for this disk&lt;br /&gt;
&lt;br /&gt;
; ---- send the result byte to the C64 via VIA1 $1800, nibble-out ----&lt;br /&gt;
$035F  2C 00 18    BIT $1800&lt;br /&gt;
$0362  10 FB       BPL $035F           ; wait for IEC bus ready&lt;br /&gt;
$0364  A9 10       LDA #$10&lt;br /&gt;
$0366  8D 00 18    STA $1800&lt;br /&gt;
$0369  2C 00 18    BIT $1800&lt;br /&gt;
$036C  30 FB       BMI $0369&lt;br /&gt;
$036E  8A          TXA                 ; A = result byte&lt;br /&gt;
$036F  4A          LSR A               ; \  send high nibble&lt;br /&gt;
$0370  4A          LSR A               ;  |&lt;br /&gt;
$0371  4A          LSR A               ;  |&lt;br /&gt;
$0372  4A          LSR A               ; /&lt;br /&gt;
$0373  8D 00 18    STA $1800&lt;br /&gt;
$0376  0A          ASL A&lt;br /&gt;
$0377  29 0F       AND #$0F&lt;br /&gt;
$0379  8D 00 18    STA $1800&lt;br /&gt;
$037C  8A          TXA&lt;br /&gt;
$037D  29 0F       AND #$0F            ; \  send low nibble&lt;br /&gt;
$037F  8D 00 18    STA $1800           ;  |&lt;br /&gt;
$0382  0A          ASL A               ;  |&lt;br /&gt;
$0383  29 0F       AND #$0F            ;  |&lt;br /&gt;
$0385  8D 00 18    STA $1800           ; /&lt;br /&gt;
$0388  A9 0F       LDA #$0F&lt;br /&gt;
$038A  EA          NOP&lt;br /&gt;
$038B  8D 00 18    STA $1800           ; final bus state&lt;br /&gt;
$038E  A9 01       LDA #$01            ; status $01 = SUCCESS&lt;br /&gt;
$0390  4C 69 F9    JMP $F969           ; ERRR (used generically as &amp;quot;set status, return&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
; ---- job setup: target track 38, submit EXECUTE job, check result (M-E entry point) ----&lt;br /&gt;
$0393  A9 26       LDA #$26            ; $26 = 38 decimal - THE TARGET TRACK&lt;br /&gt;
$0395  85 06       STA $06&lt;br /&gt;
$0397  A9 01       LDA #$01&lt;br /&gt;
$0399  85 07       STA $07&lt;br /&gt;
$039B  20 18 C1    JSR $C118           ; (ROM call)&lt;br /&gt;
$039E  A9 E0       LDA #$E0&lt;br /&gt;
$03A0  85 00       STA $00             ; submit EXECUTE job (buffer 0)&lt;br /&gt;
$03A2  A5 00       LDA $00&lt;br /&gt;
$03A4  30 FC       BMI $03A2           ; wait for job completion&lt;br /&gt;
$03A6  C9 02       CMP #$02&lt;br /&gt;
$03A8  90 06       BCC $03B0           ; status &amp;lt; 2 (success) -&amp;gt; RTS normally&lt;br /&gt;
$03AA  4C AA 03    JMP $03AA           ; status &amp;gt;= 2 (FAILURE) -&amp;gt; INFINITE SELF-LOOP&lt;br /&gt;
$03AD  20 2C C1    JSR $C12C           ; (unreached in the traced path)&lt;br /&gt;
$03B0  60          RTS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is '''instruction-for-instruction identical in structure''' to the&lt;br /&gt;
track-39 routine independently found and documented for&lt;br /&gt;
[[Eagles GMA87|Eagles]], down to the exact same offsets within the block —&lt;br /&gt;
only the target track differs (&amp;lt;code&amp;gt;$26&amp;lt;/code&amp;gt;/38 here vs. Eagles'&lt;br /&gt;
&amp;lt;code&amp;gt;$27&amp;lt;/code&amp;gt;/39). Both failure modes are deliberate, permanent hangs,&lt;br /&gt;
never wrong output: a marker mismatch retries up to 90 times before giving&lt;br /&gt;
up with error &amp;lt;code&amp;gt;$02&amp;lt;/code&amp;gt;; a failed job status falls into an infinite&lt;br /&gt;
self-loop at &amp;lt;code&amp;gt;$03AA&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Measured result byte for this disk capture: &amp;lt;code&amp;gt;$B1&amp;lt;/code&amp;gt; (177&lt;br /&gt;
decimal).'''&lt;br /&gt;
&lt;br /&gt;
== Decryption ==&lt;br /&gt;
&lt;br /&gt;
Back on the C64, the measured byte returned in &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt; from&lt;br /&gt;
&amp;lt;code&amp;gt;JSR $C800&amp;lt;/code&amp;gt; is stashed (&amp;lt;code&amp;gt;$C042: PHA&amp;lt;/code&amp;gt;), carried through&lt;br /&gt;
the fast-loader prompt handling, and pulled back at &amp;lt;code&amp;gt;$C103&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$C103  68          PLA&lt;br /&gt;
$C104  AA          TAX                ; X = the measured key byte ($B1 for this disk)&lt;br /&gt;
$C105  20 DC C0    JSR $C0DC          ; run the decrypt loop&lt;br /&gt;
$C108  20 6A C0    JSR $C06A          ; (post-decrypt cleanup, not traced this pass)&lt;br /&gt;
$C10B  4C 61 44    JMP $4461          ; jump straight into the freshly-decrypted code&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The decrypt loop itself is a '''single repeating-byte XOR key''' applied to&lt;br /&gt;
essentially the entire game, via a self-modifying pair of operands that walk&lt;br /&gt;
upward through memory:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$C0DC  A9 FE       ... (memory-config setup, banks out BASIC ROM)&lt;br /&gt;
$C0E1  85 01       STA $01&lt;br /&gt;
$C0E3  8A          TXA&lt;br /&gt;
$C0E4  4D 61 44    EOR $4461          ; self-modifying operand, walks $4461 -&amp;gt; ~$A7FF&lt;br /&gt;
$C0E7  8D 61 44    STA $4461&lt;br /&gt;
$C0EA  EE E5 C0    INC $C0E5          ; bump low byte of the EOR operand&lt;br /&gt;
$C0ED  EE E8 C0    INC $C0E8          ; bump low byte of the STA operand&lt;br /&gt;
$C0F0  D0 F1       BNE $C0E3&lt;br /&gt;
$C0F2  EE E6 C0    INC $C0E6          ; bump high byte&lt;br /&gt;
$C0F5  EE E9 C0    INC $C0E9&lt;br /&gt;
$C0F8  AD E9 C0    LDA $C0E9&lt;br /&gt;
$C0FB  C9 A8       CMP #$A8&lt;br /&gt;
$C0FD  D0 E4       BNE $C0E3&lt;br /&gt;
$C0FF  68          PLA&lt;br /&gt;
$C100  85 01       STA $01            ; restore memory config&lt;br /&gt;
$C102  60          RTS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Decrypting ~25.5 KB (&amp;lt;code&amp;gt;$4461&amp;lt;/code&amp;gt;–&amp;lt;code&amp;gt;$A7FF&amp;lt;/code&amp;gt;) in place, then&lt;br /&gt;
jumping directly into it. '''No comparison against a stored &amp;quot;correct&amp;quot; value&lt;br /&gt;
ever happens''' — a wrong key just produces garbage code and the machine&lt;br /&gt;
crashes on &amp;lt;code&amp;gt;JMP $4461&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Other games using this identical algorithm ==&lt;br /&gt;
&lt;br /&gt;
The following titles, all linking to the GMA87 wiki page, were independently&lt;br /&gt;
verified to use the '''exact same''' scheme&lt;br /&gt;
documented above: measurement on track 38, drive-side upload targeting&lt;br /&gt;
&amp;lt;code&amp;gt;$C800&amp;lt;/code&amp;gt; on the C64 / &amp;lt;code&amp;gt;$0300&amp;lt;/code&amp;gt; on the drive, and a&lt;br /&gt;
single repeating-byte C64-side XOR decrypt. Only the surrounding loader's&lt;br /&gt;
own memory layout (and, of course, each disk's measured key) differs between&lt;br /&gt;
them.&lt;br /&gt;
&lt;br /&gt;
* [[Triaxos]] — confirmed identical algorithm and fixed drive-upload target;&lt;br /&gt;
  only the loader's memory layout differs (&amp;lt;code&amp;gt;gm1.prg&amp;lt;/code&amp;gt; at&lt;br /&gt;
  &amp;lt;code&amp;gt;$1000&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;$C000&amp;lt;/code&amp;gt;, decrypted range&lt;br /&gt;
  &amp;lt;code&amp;gt;$6400&amp;lt;/code&amp;gt;–&amp;lt;code&amp;gt;$CFFF&amp;lt;/code&amp;gt;)&lt;br /&gt;
* [[Starfox]] (two independently-dumped sources, keys agree exactly)&lt;br /&gt;
* [[Jagd auf Roter Oktober]] (two independently-dumped sources, keys agree exactly)&lt;br /&gt;
* [[Enlightenment: Druid II]]&lt;br /&gt;
* [[Delta]] (six independently-dumped sources, keys agree exactly)&lt;br /&gt;
* [[Kat Trap: Planet of the Cat-Men]]&lt;br /&gt;
* [[Cataball]] (via ''Hit Pak: Trio'')&lt;br /&gt;
* [[Bride of Frankenstein]]&lt;br /&gt;
* [[Bubble Bobble]] (three sources; two distinct physical pressings identified by&lt;br /&gt;
  differing keys)&lt;br /&gt;
* [[Flying Shark]]&lt;br /&gt;
* [[James Bond 007: The Living Daylights]] / ''Der Hauch des Todes'' (same&lt;br /&gt;
  release, listed separately under its German title on the wiki)&lt;br /&gt;
* [[Sidewize]] (two sources, keys agree exactly)&lt;br /&gt;
* [[Twin Tornado]]&lt;br /&gt;
* [[Evening Star / Southern Belle]] (independently matches a previously-published&lt;br /&gt;
  key value on this game's own wiki page)&lt;br /&gt;
* [[Revs+]]&lt;br /&gt;
* [[Zynaps]] (two sources, keys agree exactly)&lt;br /&gt;
* [[Mystery of the Nile]]&lt;br /&gt;
* [[Scary Monsters]]&lt;br /&gt;
* [[Airwolf 2]] (via ''Hit Pak: Trio'') — same physical disk as Cataball, same key&lt;br /&gt;
* [[Great Gurianos]] (via ''Hit Pak: Trio'') — same physical disk side as&lt;br /&gt;
  [[Airwolf 2]], same key&lt;br /&gt;
&lt;br /&gt;
'''Not''' on this list: [[Eagles GMA87|Eagles]], which carries the same disk&lt;br /&gt;
label and measures its signature the same way, but moves the actual&lt;br /&gt;
decryption step onto the drive's own CPU instead of sending the key to the&lt;br /&gt;
C64 — see the dedicated Eagles article for the full mechanism.&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
&lt;br /&gt;
* [[GMA87]]&lt;br /&gt;
* [[Eagles GMA87|Eagles]]&lt;/div&gt;</summary>
		<author><name>Enigma</name></author>
		
	</entry>
</feed>