GEOS-Kopierschutz

Aus C64-Wiki
Zur Navigation springenZur Suche springen
GEOS Bootvorgang mit ungültigen GEOS-Lückendaten

Der Kopierschutz von GEOS ist eine Maßnahme zur Verhinderung der Vervielfältigung von Daten. Das Besondere am Kopierschutz von GEOS ist, dass dieser aus zwei separat zu betrachtenden Kopierschutzmaßnahmen besteht, welche verschiedene Teile des Betriebssystems auf unterschiedliche Art und Weise schützen. Auf der einen Seite ist da der Kopierschutz an sich, welcher in diesem Artikel behandelt wird und auf der anderen Seite das GEOS-Seriennummernsystem. Da sich der Kopierschutz in den einzelnen GEOS-Versionen etwas unterscheidet, bezieht sich dieser Artikel vorwiegend auf die Versionen 2.0 in der Sprache Deutsch für C64 und C128. Im Abschnitt Geschichte wird auf andere Versionen eingegangen.


Motivation und Abgrenzung[Bearbeiten | Quelltext bearbeiten]

Was will der Kopierschutz erreichen?[Bearbeiten | Quelltext bearbeiten]

  • Die Weitergabe von nicht installierten und installierten Systemdisketten soll verhindert werden.
  • Das Anfertigen von Sicherheitskopien von nicht installierten und installierten Systemdisketten soll verhindert werden. Die Sicherheitskopien wurden deshalb gleich mit ausgeliefert. Die Diskette "Sicherheitssystem" enthält, bis auf den Diskettennamen, die gleichen Daten wie die Diskette "System".
  • Das Anfertigen von Raubkopien von nicht installierten und installierten Systemdisketten soll verhindert werden.
  • Die Weitergabe von nicht installierten Applikationsdisketten soll verhindert werden.
  • Das Anfertigen von Sicherheitskopien von nicht installierten Applikationsdisketten soll verhindert werden.
  • Das Anfertigen von Raubkopien von nicht installierten Applikationsdisketten soll verhindert werden.

Was wird durch den Kopierschutz nicht verhindert?[Bearbeiten | Quelltext bearbeiten]

  • Die Weitergabe von installierten Applikationsdisketten wird durch den Kopierschutz nicht verhindert.
  • Das Anfertigen von Sicherheitskopien von installierten Applikationsdisketten, wird durch den Kopierschutz nicht verhindert.
  • Das GEOS Seriennummernsystem hat nichts mit dem GEOS-Kopierschutz zu tun und bildet einen vollständigen separaten parallel existierenden Schutzmechanismus.

Kopiergeschützte Disketten[Bearbeiten | Quelltext bearbeiten]

GEOS 2.0 für C64 und 128 besteht jeweils aus 4 doppelseitigen Disketten. Hinzu kommen 2 doppelseitige Disketten für die GEORAM Versionen von GEOS 2.0 für C64 und C128. Es sind also 20 einzelne Diskettenseiten bzw. 20 einzelne Diskettenimages.

Die folgende Tabelle zeigt, welche Disketten einen Kopierschutz besitzen und welche nicht.

Nr. Diskette Disk.Nr. Seite Name Kopierschutz
1 GEOS 64 2.0 1 A "System" ja
2 GEOS 64 2.0 1 B "Applikations" ja ("GEOWRITE")
3 GEOS 64 2.0 2 A "Sicherheitsystem" ja
4 GEOS 64 2.0 2 B "Write Utilities" ja(Anmerkung 1) ("GEOMERGE")
5 GEOS 64 2.0 3 A "GeoSpell deutsch" nein
6 GEOS 64 2.0 3 B "GeoSpell engl." nein
7 GEOS 64 2.0 4 A "Druckertreiber" nein
8 GEOS 64 2.0 4 B "Neue GEOS-Trei." nein
9 GEOS 128 2.0 1 A "System" ja
10 GEOS 128 2.0 1 B "Applikations" ja ("GEOWRITE")
11 GEOS 128 2.0 2 A "Sicherheitsystem" ja
12 GEOS 128 2.0 2 B "Write Utilities" ja(Anmerkung 1) ("GEOMERGE")
13 GEOS 128 2.0 3 A "GeoSpell deutsch" nein
14 GEOS 128 2.0 3 B "GeoSpell engl." nein
15 GEOS 128 2.0 4 A "Druckertreiber" nein
16 GEOS 128 2.0 4 B "weitere Treiber" nein
17 GEOS 2.0r GEORAM 64 1 A "System" ja
18 GEOS 2.0r GEORAM 128 1 B "System" ja
19 GEOS 2.0r GEORAM 64 2 A "Sicherheitsystem" ja
20 GEOS 2.0r GEORAM 128 2 B "Sicherheitsystem" ja

Anmerkung 1:

Von den "Write Utilities" mit der Applikation "GEOMERGE" gibt es verschiedene Versionen. Die Versionen vor April 1992 wurden mit dem Kopierschutz ausgeliefert. Die Versionen, welche nach April 1992 ausgeliefert wurden, besaßen keinen Kopierschutz mehr. Der Kopierschutz wurde durch den Hersteller selbst entfernt, da es wohl Probleme mit der Installationsroutine mit bestimmten Laufwerken gegeben hat.

Auch andere GEOS-Applikationen sind mit demselben Kopierschutz ausgeliefert worden.

Bestandteile[Bearbeiten | Quelltext bearbeiten]

Der Kopierschutz besteht aus zwei Teilen.

  • Teil 1: Daten, welche an speziellen Stellen der Systemdisketten bzw. Applikationsdisketten gespeichert sind. Dieser Teil wird im Weiteren als "GEOS-Lückendaten" bezeichnet.
  • Teil 2: Programmcode, welcher diese Daten überprüft und entscheidet, ob die vorhandenen Daten gültig sind. Dieser Teil wird im Weiteren als "Kopierschutzprüfung" bezeichnet.

Hintergrundwissen zum Aufbau einer Diskette[Bearbeiten | Quelltext bearbeiten]

Der Aufbau einer Diskettenspur

Sektor[Bearbeiten | Quelltext bearbeiten]

Der Aufbau eines Diskettensektors
  • Eine Diskette im 1541-Format unterteilt sich in Spuren und Sektoren.
  • Jeder Sektor enthält einen Datenblock (hier sind die reinen Nutzdaten gemeint) von 254 Bytes an Daten. Zwei zusätzliche Bytes bilden einen Zeiger zum nächsten Block. Dadurch wird es möglich, mit Files zu arbeiten, die länger als ein Block sind. Eine 1541-Diskette enthält 35 Spuren (Ringe), die von 1 bis 35 durchnummeriert sind. Da die Spuren verschieden lang sind, enthalten sie eine verschiedene Anzahl von Sektoren. Die Nummerierung von Sektoren beginnt mit Sektor 0.
  • Die Abbildung "Der Aufbau eines Diskettensektors" zeigt den Aufbau eines Diskettensektors. Die Abbildung ist einer Abbildung aus dem 1541 Floppy Disk Bedienungshandbuch nachempfunden. Auch diese Abbildung zeigt die Lücken vor (Lücke1) und nach (Lücke2) dem Datenblock.

Sektor Vorspannblock (Header-Block)[Bearbeiten | Quelltext bearbeiten]

  • Jeder Sektor besitzt einen Vorspannblock, der sogenannte Header-Block.
  • Der Vorspannblock eines Sektors ermöglicht es dem Commodore-DOS, die Spur und den Sektor zu identifizieren. Er besteht aus einer Synchronisierungsmarkierung (SYNC), acht Bytes identifizierenden Informationen und einer Vorspannblocklücke.
  • Ein Vorspannblock wird nur während der Formatierung geschrieben. Danach wird er niemals neu geschrieben.
  • Nach einer Formatierung besteht jede Vorspannblocklücke aus acht Bytes mit dem Wert $55.
  • Das Commodore-DOS liest die Daten der Vorspannblocklücke niemals.

Sektor Datenblock[Bearbeiten | Quelltext bearbeiten]

  • Jeder Sektor besitzt einen Datenblock.
  • Ein Datenblock eines Sektor speichert die 256 Datenbytes für diesen Sektor. Er besteht aus einer Synchronisationsmarkierung, einer Datenblock-ID, den 256 Bytes Daten, eine Datenblockprüfsumme, zwei aus $00-Bytes und eine Datenblocklücke.
  • Die Länge der Datenblocklücke variiert von in der Regel 4 bis 12 Bytes.
  • Die Datenblocklücke zwischen dem letzten Sektor einer Spur und dem Sektor 0 ist meist länger; sie kann bis zu 100 Bytes lang sein.
  • Nach einer Formatierung besitzen alle Bytes der Datenblocklücken den Wert $55.
  • Das Commodore-DOS liest die Daten der Datenblocklücken niemals.
  • Sollen Daten auf einer Diskette gespeichert werden, dann werden immer gesamte Datenblöcke (einschließlich der vorhergehenden Synchronisationsmarkierung) neu geschrieben.
  • Das Commodore-DOS beginnt immer erst nach den 8 Bytes der Vorspannblocklücke mit dem Schreiben eines Datenblocks.

SYNC-Markierung[Bearbeiten | Quelltext bearbeiten]

  • Jeder Vorspannblock (Header-Block) und jeder Datenblock beginnt mit einer SYNC-Markierung.
  • Eine SYNC-Markierung ist eine ganz besondere Kennzeichnung innerhalb einer Spur.
  • Eine SYNC-Markierung besteht aus 10 oder mehr aufeinander folgenden 1-Bits (das Commodore-DOS verwendet normalerweise 40 dieser 1-Bits).
  • Dieses besondere Muster von Bits kennzeichnet den Anfang eines Vorspannblocks (Header-Blocks) oder eines Datenblocks.
  • Die Hardware in einem Commodore-Laufwerk kann diese Kennzeichnung erkennen und dem Commodore-DOS signalisieren, dass ein neuer Daten- oder Vorspannblock (Header-Block) kommt (siehe Artikel Hardware-Aufbau der 1541).

Nutzen der Lücken vor und nach dem Datenblock[Bearbeiten | Quelltext bearbeiten]

  • Beim Schreiben eines Datenblocks kann nicht sichergestellt werden, dass die Daten genau an die richtige Stelle auf der Diskette geschrieben werden.
  • Dadurch kann der Anfang aber auch das Ende eines Datenblocks etwas verschoben auf die Diskette geschrieben werden.
  • Damit dabei keine Daten der Vorspannblöcke überschrieben werden, wurden die Lücken vor und nach dem Datenblock eingefügt.
  • Die Lücken sind also der Spielraum für die Position eines Datenblocks.
  • Da die SYNC-Markierung eines Datenblocks beim Schreiben immer neu geschrieben wird, kann das Commodore-DOS den Anfang des Datenblocks auch dann finden, wenn sich dieser etwas weiter vorn oder etwas weiter hinten befindet.

GEOS-Lückendaten[Bearbeiten | Quelltext bearbeiten]

Folgen von ungültigen oder nicht vorhanden GEOS-Lückendaten[Bearbeiten | Quelltext bearbeiten]

Was passiert, wenn die GEOS-Lückendaten ungültig oder nicht vorhanden sind?

Installation einer Applikation mit ungültigen GEOS-Lückendaten
  • Beim Booten von einer Systemdiskette mit ungültigen oder nicht vorhanden GEOS-Lückendaten wird durch die Kopierschutzprüfung ein Reset ausgelöst und der Rechner somit zurückgesetzt.
  • Beim Installieren einer Applikation mit ungültigen oder nicht vorhanden GEOS-Lückendaten wird eine Fehlermeldung ausgeben und die Installation abgebrochen.

Position der GEOS-Lückendaten[Bearbeiten | Quelltext bearbeiten]

Wo genau befinden sich die GEOS-Lückendaten auf den kopiergeschützten Disketten?

  • Das Commodore-DOS[1] sieht vor und nach einem Datenblock eine kleine Lücke von ein paar Bytes vor.
  • Diese Bytes werden nur durch das Formatieren einer Diskette durch das Commodore-DOS geschrieben.
  • Das Commodore-DOS setzt alle Lücken-Byte auf den Wert $55.
  • Die GEOS-Lückendaten hingegen enden immer mit den Werten $55 $67 $55 $55 $67 vor der nächsten SYNC-Markierung.
  • In Anhang C ist der Sektor 0 (Spur 21) einer GEOS-Systemdiskette einmal schematisch dargestellt.
  • Bis auf die GEOS-Lückendaten entsprechen die kopiergeschützten GEOS-Disketten dem Commodore-DOS-Format.

Kopierschutzprüfung[Bearbeiten | Quelltext bearbeiten]

Wann wird eine Kopierschutzprüfung durchgeführt?[Bearbeiten | Quelltext bearbeiten]

  • Beim Booten des GEOS-Systems werden die GEOS-Lückendaten überprüft, es wird also die Kopierschutzprüfung durchgeführt.
  • Eine Kopierschutzprüfung erfolgt sowohl auf nicht installierten als auch auf installierten Systemdisketten.
  • Beim Installieren einer nicht installierten Applikation werden die GEOS-Lückendaten überprüft, es wird also die Kopierschutzprüfung durchgeführt.
  • Beim Starten von installierten Applikationen erfolgt keine Kopierschutzprüfung.

Welche Lücken werden von der Kopierschutzprüfung geprüft (Systemdisketten)?[Bearbeiten | Quelltext bearbeiten]

  • Auf der Spur 21 sind 19 Sektoren vorhanden, was dem Commodore-DOS-Standard entspricht.
  • Die Kopierschutzprüfung prüft alle 19 Sektor Vorspannlücken von Spur 21.
  • Die Kopierschutzprüfung prüft die ersten 18 Sektor Datenlücken von Spur 21.
  • Die Lücke zwischen dem letzten Sektor und dem Sektor 0 wird nicht geprüft.
  • Die Kopierschutzprüfung prüft also insgesamt 37 mal (19 + 18 = 37). Siehe dazu Anhang A

Welche Werte akzeptiert die Kopierschutzprüfung in den Lücken?[Bearbeiten | Quelltext bearbeiten]

  • Die Kopierschutzprüfung akzeptiert in den Lücken nur Bytes mit dem Werte $55 oder $67.

Warum muss jede Lücke mit einem Byte mit dem Wert $67 enden?[Bearbeiten | Quelltext bearbeiten]

In diesem Abschnitt soll die Frage beantwortet werden, warum jede Lücke mit einem Byte mit dem Wert $67 enden muss, damit die Kopierschutzprüfung bestanden wird.

  • Die Kopierschutzprüfung prüft alle Byte der Vorspannlücken und der Datenblocklücken.
  • Diese Bytes müssen entweder den Wert $55 oder $67 aufweisen, ansonsten ist die Kopierschutzprüfung nicht bestanden.
  • Die Kopierschutzprüfung prüft alle Bytes bis zum Ende der jeweiligen Lücke.
  • Um das Ende einer Lücke zu erkennen, prüft die Kopierschutzprüfung vor dem Lesen des nächsten Bytes, ob das Laufwerk schon die nächste SYNC-Markierung erkannt hat.
  • Die SYNC-Markierung kennzeichnet das Ende jeder Lücke bzw. den Anfang des nächsten Blocks (Daten- oder Vorspannblock bzw. Header-Block).
  • Steht ein Byte mit dem Wert $55 vor der nächsten SYNC-Markierung (also am Ende einer Lücke), so ist dies zunächst in Ordnung. Die Kopierschutzprüfung prüft das Byte, und da es den zulässigen Wert $55 aufweist, wird die Prüfung vorgesetzt. Jetzt wird geprüft, ob schon die nächste SYNC-Markierung erkannt wurde. Dies ist nicht der Fall, da noch keine 10 aufeinander folgenden 1-Bits gelesen wurden. Zu diesem Zeitpunkt wurde erst ein 1-Bit gelesen, da der Wert $55 (1010101) mit 01 endet. Dann wird das nächste Byte gelesen, welches den Wert $FF (11111111) aufweist. Anschließend wird wieder geprüft, ob das Laufwerk schon die nächste SYNC-Markierung erkannt hat. Dies ist immer noch nicht der Fall, da erst das letzte 1-Bit des Werts $55 und die acht 1-Bits des Werts $FF also genau neun 1-Bits gelesen worden sind. Jetzt prüft die Kopierschutzprüfung den Wert $FF, welcher leider nicht dem Wert $55 und auch nicht dem Wert $67 entspricht. Somit ist die Kopierschutzprüfung nicht bestanden! Siehe dazu auch Anhang B, wo auch dieser Fall dargestellt ist.
  • Steht ein Byte mit dem Wert $67 vor der nächsten SYNC-Markierung (also am Ende einer Lücke), so ist dies in Ordnung. Die Kopierschutzprüfung prüft das Byte und da es den zulässigen Wert $67 aufweist, wird die Prüfung vorgesetzt. Jetzt wird geprüft, ob schon die nächste SYNC-Markierung erkannt wurde. Dies ist nicht der Fall, da noch keine 10 aufeinander folgenden 1-Bits gelesen wurden. Zu diesem Zeitpunkt wurden erst drei 1-Bits gelesen, da der Wert $67 (1100111) mit 0111 endet. Dann wird das nächste Byte gelesen, welches den Wert $FF (11111111) aufweist. Anschließend wird wieder geprüft, ob das Laufwerk schon die nächste SYNC-Markierung erkannt hat. Dies ist der Fall da schon elf (3 + 8) 1-Bits gelesen worden sind. Die Kopierschutzprüfung dieser Lücke ist damit bestanden.
  • Es kann also kein Byte mit dem Wert $55 (1010101) vor der SYNC-Markierung stehen, da die Bit-Folge 1010101 des Werts $55 nur ein 1-Bit am Ende aufweist und so nach dem Lesen eines nachfolgenden Bytes mit dem Wert $FF noch keine SYNC-Markierung erkannt wird.
  • So muss also zwingend ein Byte mit dem Wert $67 (1100111) vor jeder SYNC-Markierung stehen, da die Bit-Folge 1100111 des Werts $67 drei 1-Bits am Ende aufweist und so nach dem Lesen eines nachfolgenden Bytes mit dem Wert $FF eine SYNC-Markierung erkannt wird.

Kopierschutzprüfung im Detail[Bearbeiten | Quelltext bearbeiten]

Wo wird die Kopierschutzprüfung ausgeführt?[Bearbeiten | Quelltext bearbeiten]

Die Kopierschutzprüfung wird im Speicher des Diskettenlaufwerks von dessen Prozessor ausgeführt.

Wie gelangt die Kopierschutzprüfung in den Speicher des Diskettenlaufwerks?[Bearbeiten | Quelltext bearbeiten]

Um die Frage, wie die Kopierschutzprüfung in den Speicher des Diskettenlaufwerks gelangt, beantworten zu können, muss der Bootvorgang von GEOS sehr genau unter die Lupe genommen werden. Die Entwickler von GEOS haben sich große Mühe gegeben, die Kopierschutzprüfung, genauer gesagt die Kopierschutzprüfungen, zu verstecken. Beim Bootvorgang von GEOS werden die Dateien "GEOS", "GEOS BOOT" und "GEOS KERNAL" von der Systemdiskette verwendet. In den weiteren Abschnitten werden diese Programmen bzw. Dateien genau unter die Lupe genommen.

Hier nur mal ein Überblick über den Bootvorgang von GEOS:

  1. Das Programm GEOS wird vom Benutzer geladen und gestartet.
  2. Das Programm GEOS lädt das Programm "GEOS BOOT" mittels Kernal-Routinen in den Speicher und startet es.
  3. Das Programm "GEOS BOOT" ist zum Teil kodiert auf der Diskette gespeichert und wird auch so in den Speicher geladen.
  4. Der Aufruf der Dekodierroutine von "GEOS BOOT" wird über eine Veränderung des Stapelspeichers durchgeführt, um diesen zu verschleiern.
  5. Das Programm "GEOS BOOT" sendet eine Schnellladeroutine (Stufe 1) an das Diskettenlaufwerk.
  6. Die Schnellladeroutine (Stufe 1) liegt im Speicher des Rechners in 32 Byte langen Blöcken in umgekehrter Byte-Reihenfolge vor und wird erst durch die Übertragung, im Speicher des Diskettenlaufwerks, in die richtige Reihenfolge gebracht.
  7. Die Schnellladeroutine (Stufe 1) enthält die Kopierschutzprüfung (I).
  8. Die Schnellladeroutine (Stufe 1) wird durch das Programm "GEOS BOOT" im Diskettenlaufwerk gestartet.
  9. Die Schnellladeroutine (Stufe 1) überträgt 3 Sektorketten, welche den 3 Datensätzen der GEOS-VLIR-Datei "GEOS KERNAL" entsprechen.
  10. Die Schnellladeroutine (Stufe 1) führt die Kopierschutzprüfung (I) zwischen der Übertragung des 2. und 3. Datensatzes durch.
  11. Die Datensätze 2 und 3 sind kodiert auf der Diskette abgelegt und werden bei der Übertragung dekodiert. Ein Teil der Schnellladeroutine selbst, dient dabei als Dekodierschlüssel.
  12. Der letzte geladene Sektor (Sektor 12 von Spur 29), enthält nur 59 Datenbyte, welche von der Schnellladeroutine (Stufe 1) übertragen werden. Der Rest des Sektors, welcher eigentlich nie benutzt wird, befindet sich aber auch nach der Beendigung der Schnellladeroutine (Stufe 1) noch im Speicher des Diskettenlaufwerks und enthält eine weitere Kopierschutzprüfung (II).
  13. Das Programm "GEOS BOOT" startet den GEOS-Kernal.
  14. Während des Starts des GEOS-Kernal wird die Kernal-Routine GetDirHead aufgerufen, diese Routine geht nahtlos in die Kernal Routine GetBlock über.
  15. Die GEOS-Kernal-Routine GetBlock ruft die Kernal-Routine EnterTurbo auf.
  16. Die GEOS-Kernal-Routine EnterTurbo sendet, mit Hilfe von ein paar Unterroutinen, eine weitere Schnelladeroutine (Stufe 2) an das Diskettenlaufwerk und startet diese.
  17. Die Schnelladeroutine (Stufe 2) vereinigt sich im Speicher des Diskettenlaufwerks mit der dort schon vorhandenen Kopierschutzprüfung (II).

GEOS[Bearbeiten | Quelltext bearbeiten]

Die Datei GEOS ist ein sehr kurzes Programm, welches 2 Aufgaben hat. Zum Einen soll es dem Benutzer den Start mittels eines Autostartmechanismus erleichtern. Zum Anderen soll es die Datei "GEOS BOOT" in den Speicher laden und ausführen. Dieses Programm soll durch den Benutzer mittels

LOAD "GEOS",8,1

geladen und anschließend automatisch gestartet werden. Dabei kommt ein sogenannter Stapel-Autostart zum Einsatz, welcher sehr genau im "Das Anti-Cracker-Buch" Kapitel 3.15 beschrieben ist. Kurz zusammengefasst, das Programm GEOS wird an die Speicherstelle $0110 geladen, was der gespeicherten Ladeadresse (den ersten 2 Byte der Programmdatei) entspricht. Dieser Speicherbereich ist Teil des Prozessor-Stack, welcher durch die Programmdatei am Ende mit 165 $02 Werten überschrieben wird. Dadurch werden die Rücksprungadressen des Stapels so geändert, dass das RTS, welches am Ende des LOAD-Befehls ausgeführt wird, zur Adresse $0202 + $01, also zu $0203 verzweigt. Und genau an dieser Stelle hat das Programm GEOS ein JMP $0123, welches zur eigentlichen Laderoutine springt.

Falls das Programm GEOS versehentlich ohne Angabe der Sekundäradresse mittels

LOAD "GEOS",8

geladen wird, ist das auch kein Problem. Die Entwickler haben für diesen Fall eine kleines BASIC-Programm in die Datei GEOS integriert, welches nach dem Start mit

RUN

die korrekte LOAD-Anweisung mit der Sekundäradresse ausführt. Dazu muss man wissen, dass der Befehl LOAD Programme immer an den BASIC-Anfang (beim C64 i.d.R. die Speicherstelle 2049 bzw. $0801) lädt, wenn keine Sekundäradresse angeben wird. Dabei werden die ersten beiden Bytes der Programmdatei, welche die Startadresse im Speicher angeben, ignoriert. Das BASIC-Programm muss sich also am Anfang der Programmdatei "GEOS" befinden, damit das Laden als Basisprogramm funktioniert.

Im folgenden sind die ersten 21 Byte der Datei GEOS einmal dargestellt.

Offset(dec): Speicheradr. Inhalt Beschreibung
         00:              $10    Startadresse Low-Byte, welches vom LOAD "GEOS",8 ignoriert wird und durch 01 ersetzt wird
         01:              $01    Startadresse High-Byte, welches vom LOAD "GEOS",8 ignoriert wird und durch 08 ersetzt wird
         02: $0801        $12    Zeiger auf die nächste BASIC-Zeile Low-Byte $0812
         03: $0802        $08    Zeiger auf die nächste BASIC-Zeile High-Byte $0812
         04: $0803        $0a    BASIC-Zeilennummer Low-Byte 10 
         05: $0804        $00    BASIC-Zeilennummer High-Byte
         06: $0805        $93    Token für den BASIC-Befehl LOAD
         07: $0806        $20    Leerzeichen
         08: $0807        $22 "
         09: $0808        $47 G
         10: $0809        $45 E
         11: $080a        $4f O
         12: $080b        $53 S
         13: $080c        $22 "
         14: $080d        $2c ,
         15: $080e        $38 8
         16: $080f        $2c ,
         17: $0810        $31 1
         18: $0811        $00    1 Nullbyte markiert das Ende der BASIC-Zeile 
         19: $0812        $00    2 Nullbytes an Stelle eines Zeigers auf die nächste BASIC-Zeile zeigt das Ende des BASIC-Programms an
         20: $0813        $00

Daraus ergibt sich das folgende kleine BASIC-Programm.

10 LOAD "GEOS",8,1

Die Hauptaufgabe des Programms GEOS ist, die Datei "GEOS BOOT" mittels der Standard-Kernal-Routinen zu laden und zu starten. Die Datei "GEOS BOOT" wird dabei an dessen gespeicherte Ladeadresse (ersten 2 Bytes der Programmdatei) $6000 geladen und ausgeführt.

$0110:                     .BYTE $12,$08,$0A,$00,$93,$20  ;BASIC-Programm
$0116:                     .TEXT ""GEOS",8,1"             ;BASIC-Programm
$0120:                     .BYTE $00,$00,$00              ;BASIC-Programm
$0123: A9 0E       j0123┌─►LDA #$0E
$0125: 8D 20 D0         │  STA $D020      ;Farbe des Bildschirmrands (0..15) 
$0128: A0 06            │  LDY #$06
$012A: 8C 21 D0         │  STY $D021      ;Bildschirmhintergrundfarbe (0..15)
$012D: A9 00            │  LDA #$00
$012F: 20 90 FF         │  JSR ROM_SETMSG ;$FF90 - SETMSG: Steuerung von KERNAL-Meldungen   
$0132: A9 09            │  LDA #$09
$0134: A2 55            │  LDX #$55
$0136: A0 01            │  LDY #$01
$0138: 20 BD FF         │  JSR ROM_SETNAM ;$FFBD - SETNAM: Festlegen des Dateinamens                     
$013B: A9 50            │  LDA #$50
$013D: A6 BA            │  LDX aBA
$013F: A0 01            │  LDY #$01
$0141: 20 BA FF         │  JSR ROM_SETLFS ;$FFBA - Setzen der Geräteadressen (logische, Primär- und Sekundäradresse)            
$0144: A9 00            │  LDA #$00
$0146: A2 FF            │  LDX #$FF
$0148: A0 FF            │  LDY #$FF
$014A: 20 D5 FF         │  JSR ROM_LOAD   ;$FFD5 - LOAD: Daten ins RAM laden von Peripheriegeräten    
$014D: 90 03            │┌─BCC b0152
$014F: 6C 02 03         ││ JMP (p0302)    ;Vektor: BASIC-Warmstart
                        ││
$0152: 4C 00 60    b0152│└►JMP e6000      ;Start des Programms "GEOS BOOT"
                        │
$0155:                  │  .TEXT "GEOS BOOT"
$015E:                  │  .BYTE $02,$02,$02,$02,$02,$02,$02,$02
$0166:                  │  .BYTE $02,$02,$02,$02,$02,$02,$02,$02
$016E:                  │  .BYTE $02,$02,$02,$02,$02,$02,$02,$02
$0176:                  │  .BYTE $02,$02,$02,$02,$02,$02,$02,$02
$017E:                  │  .BYTE $02,$02,$02,$02,$02,$02,$02,$02
$0186:                  │  .BYTE $02,$02,$02,$02,$02,$02,$02,$02
$018E:                  │  .BYTE $02,$02,$02,$02,$02,$02,$02,$02
$0196:                  │  .BYTE $02,$02,$02,$02,$02,$02,$02,$02
$019E:                  │  .BYTE $02,$02,$02,$02,$02,$02,$02,$02
$01A6:                  │  .BYTE $02,$02,$02,$02,$02,$02,$02,$02
$01AE:                  │  .BYTE $02,$02,$02,$02,$02,$02,$02,$02
$01B6:                  │  .BYTE $02,$02,$02,$02,$02,$02,$02,$02
$01BE:                  │  .BYTE $02,$02,$02,$02,$02,$02,$02,$02
$01C6:                  │  .BYTE $02,$02,$02,$02,$02,$02,$02,$02
$01CE:                  │  .BYTE $02,$02,$02,$02,$02,$02,$02,$02
$01D6:                  │  .BYTE $02,$02,$02,$02,$02,$02,$02,$02
$01DE:                  │  .BYTE $02,$02,$02,$02,$02,$02,$02,$02
$01E6:                  │  .BYTE $02,$02,$02,$02,$02,$02,$02,$02
$01EE:                  │  .BYTE $02,$02,$02,$02,$02,$02,$02,$02
$01F6:                  │  .BYTE $02,$02,$02,$02,$02,$02,$02,$02
$01FE:                  │  .BYTE $02,$02,$02,$02,$02
$0203: 4C 23 01         └──JMP j0123

GEOS BOOT[Bearbeiten | Quelltext bearbeiten]

Das Programm "GEOS BOOT" hat verschiedene Aufgaben. Die Hauptaufgabe ist eine Schnellladeroutine (Stufe 1) im Diskettenlaufwerk zu installieren, um dann den GEOS KERNAL mit einer ca. 6-fachen gesteigerten Geschwindigkeit zu laden und dann zu starten. Das Programm "GEOS BOOT" wird vom Programm GEOS mit den gewöhnlichen Kernal-Routinen geladen. Das bedeutet, dass die Programmdaten, welche in den Speicher geladen werden, auch auf der Diskette in gleicher Form gespeichert vorliegen. Damit die Kopierschutzprüfung (I), welche in diesen Programmdaten enthalten ist, nicht einfach auf der Diskette erkennbar ist, sind Teile des Programms "GEOS BOOT" kodiert worden. Der Bereich $613F bis $643E ist kodiert und wird vom Programm "GEOS BOOT" selbst dekodiert. Der Aufruf der Dekodierroutine ist dabei raffiniert verschleiert worden.

Hauptaufgabe:

  • Laden und Starten des GEOS KERNAL mittels Schnellladeroutine (Stufe 1)

Nebenaufgaben:

  • Ausgabe des Textes "GEOS BOOTET ..."
  • Die Schnellladeroutine (Stufe 1) mit der Kopierschutzprüfung (I) verstecken (sowohl auf der Diskette als auch im Speicher das Rechners).
    • Teile des Programms sind dazu kodiert worden.
    • Die Schnellladeroutine (Stufe 1) an sich ist im Speicher des Rechners in Blöcken zu jeweils 32 Byte rückwärts abgelegt, so dass dieser Programmcode wirklich erst in dem Speicher des Diskettenlaufwerks lesbar wird.
    • Der Aufruf der Decodierroutine ist raffiniert verschleiert.
  • Bereitstellung einer zufälligen Zahl (2 Byte), welche gegebenenfalls von der Installationsroutine als neue Seriennummer verwendet werden kann. Die Zufallszahl wird dabei durch die Abfrage der zufälligen Position des Rasterstrahls ermittelt.

Im Folgendem werden die einzelnen Teilbereiche des Programms "GEOS BOOT" einmal genauer betrachtet.

Bereich von $60A7 bis $60E8[Bearbeiten | Quelltext bearbeiten]

In diesem Abschnitt wird der Bereich von $60A7 bis $60E8 behandelt. Zusätzlich sind der Einsprung $6000 bis $6002, der Text "GEOS BOOTET ..." $6003 bis $6012 und die Interruptroutine $64A2 bis $64A7 enthalten. Dieser Bereich wird über den Einsprung an Adresse $6000 als erstes ausgeführt. Zunächst wird das System ein wenig vorbereitet, indem die Speicherbelegung festgelegt und nicht-maskierbare Interrupt-Vektoren initialisiert werden. Dann wird der Bildschirmspeicher geleert und alle Sprites abgeschaltet. Als letzten Schritt wird noch der Text "GEOS BOOTET ..." auf den Bildschirm ausgegeben.

$6000: 4C A7 60           ┌─JMP j60A7
$6003:             a6003  │ .BYTE $0E                              ;Anzahl der zu kopierenden Zeichen vom Text "GEOS BOOTET ..."
$6004:             f6004  │ .BYTE $07,$05,$0F,$13,$20,$02,$0F,$0F  ;Bildschirmcode GEOS BOO
$600C:                    │ .BYTE $14,$05,$14,$20,$2E,$2E,$2E      ;Bildschirmcode TET ...
.                         │ 
.                         │ 
.                         │   
$60A7: 78          j60A7  └►SEI          ;setzt das Interrupt-Flag und unterbindet alle Interrupts (IRQ) bis auf den NMI
$60A8: A9 36                LDA #$36     ;das gesamte BASIC abschalten, um das darunterliegende RAM nutzbar zu machen (durchgehender RAM-Speicher von $0800 bis $CFFF)
$60AA: 85 01                STA a01      ;Prozessorport
$60AC: A9 64                LDA #>p64A7
$60AE: 8D 19 03             STA a0319    ;Vektor: nicht maskierter Interrupt (NMI)
$60B1: A9 A7                LDA #<p64A7
$60B3: 8D 18 03             STA a0318    ;Vektor: nicht maskierter Interrupt (NMI)
$60B6: A9 64                LDA #>p64A2
$60B8: 8D 15 03             STA a0315    ;Vektor: Hardware Interrupt (IRQ)
$60BB: A9 A2                LDA #<p64A2
$60BD: 8D 14 03             STA a0314    ;Vektor: Hardware Interrupt (IRQ)
$60C0: A2 10                LDX #$10
$60C2: A9 04                LDA #$04
$60C4: 85 09                STA a09      ;Speicher der Zeropage, welcher als Puffer verwendet wird
$60C6: A0 00                LDY #$00
$60C8: 8C 15 D0             STY $D015    ;Sprite-Schalter, Bit = 1: Sprite n an (0..255)
$60CB: 84 08                STY a08      ;Zeropage-Adresse $08 wird als Puffer verwendet
$60CD: A9 20       b60CD┌►┌►LDA #$20
$60CF: 91 08            │ │ STA (p08),Y
$60D1: C8               │ │ INY 
$60D2: D0 F9            │ └─BNE b60CD
$60D4: E6 09            │   INC a09
$60D6: CA               │   DEX 
$60D7: D0 F4            └───BNE b60CD
$60D9: AC 03 60             LDY a6003
$60DC: A9 0E       b60DC  ┌►LDA #$0E      ;Farbwert für die Farbe "Hellblau"
$60DE: 99 4C D9           │ STA fD94C,Y   ;FARB-RAM mit $0E füllen
$60E1: B9 04 60           │ LDA f6004,Y
$60E4: 99 4C 05           │ STA f054C,Y   ;Bildschirmspeicher
$60E7: 88                 │ DEY 
$60E8: 10 F2              └─BPL b60DC
.
.
.
$64A2: 68          p64A2    PLA            ;Start der Interruptroutine (IRQ)
$64A3: A8                   TAY 
$64A4: 68                   PLA 
$64A5: AA                   TAX 
$64A6: 68                   PLA 
$64A7: 40          p64A7    RTI            ;Start der Interruptroutine (NMI)

Legende:
   C-64 KERNAL System und nicht-maskierbare Interrupt Vektoren initialisieren
   Bildschirmspeicher leeren
   Alle Sprites abschalten
   Den Text "GEOS BOOTET ..." direkt in den Bildschirmspeicher schreiben
   Farbspeicher füllen
Bildschirmcode (hex): $07 $05 $0F $13 $20 $02 $0F $0F $14 $05 $14 $20 $2E $2E $2E
Bildschirmcode (dec): 7 5 15 19 32 2 15 15 20 5 20 32 46 46 46
Ausgabe: C64-Font1-7.png C64-Font1-5.png C64-Font1-15.png C64-Font1-19.png C64-Font1-32.png C64-Font1-2.png C64-Font1-15.png C64-Font1-15.png C64-Font1-20.png C64-Font1-5.png C64-Font1-20.png C64-Font1-32.png C64-Font1-46.png C64-Font1-46.png C64-Font1-46.png
Bereich von $60EA bis $6128[Bearbeiten | Quelltext bearbeiten]
$60EA: A0 00                LDY #$00
$60EC: B9 00 C0    b60EC  ┌►LDA fC000,Y
$60EF: 99 00 5F           │ STA f5F00,Y
$60F2: C8                 │ INY 
$60F3: D0 F7              └─BNE b60EC
$60F5: A0 01                LDY #$01
$60F7: 8D 04 DD             STA $DD04    ;CIA2: Timer A: Low-Byte
$60FA: 88                   DEY 
$60FB: 8C 05 DD             STY $DD05    ;CIA2: Timer A: High-Byte
$60FE: 8C 1A D0             STY $D01A    ;VIC: Interrupt Request: Maske(IMR)
$6101: A9 7F                LDA #$7F
$6103: 8D 19 D0             STA $D019    ;VIC: Interrupt Request (IRR)
$6106: 8D 0D DC             STA $DC0D    ;CIA1: Interrupt Control und Status
$6109: 8D 0D DD             STA $DD0D    ;CIA2: Interrupt Control und Status
$610C: A9 3F                LDA #$3F
$610E: 8D 02 DD             STA $DD02    ;CIA2: Datenrichtung Port A
$6111: A9 81                LDA #$81
$6113: 8D 0D DD             STA $DD0D    ;CIA2: Interrupt Control und Status
$6116: A9 09                LDA #$09
$6118: 8D 0E DD             STA $DD0E    ;CIA2: Control Timer A
$611B: A0 2C                LDY #$2C
$611D: AD 12 D0    b611D┌►┌►LDA $D012    ;Lesen: Aktuelle Rasterzeile
$6120: C5 10            │ │ CMP a10
$6122: F0 F9            │ └─BEQ b611D
$6124: 85 10            │   STA a10
$6126: 88               │   DEY 
$6127: D0 F4            └───BNE b611D
Bereich von $6129 bis $613F[Bearbeiten | Quelltext bearbeiten]

In diesem Abschnitt wird der Bereich von $6129 bis $613F behandelt. Zusätzlich sind der kodierter Bereich $613F bis $643E, der Bereich $6080 bis $60A6 und der Bereich $6482 bis $64A1 enthalten. In diesem Bereich wird zunächst ein INITIALIZE des Diskettenlaufwerks ausgeführt. Die dabei verwendete Unterroutine ab der Adresse $6080 verändert den Stapelzeiger so, dass die Ausführung des RTS an der Adresse $613F die Dekodierroutine ab der Adresse $6482 aufruft. Somit ist der Aufruf der Dekodierroutine sehr schlecht erkennbar. Die Dekodierroutine führt ein EOR mit dem Wert $C9 auf den gesamten kodierten Bereich von $613F bis $643E aus. Nach dem Dekodieren wird wieder zur Adresse $613F gesprungen. Interessant ist an dieser Stelle, dass der Befehl RTS, an der Adresse $613F, zum kodierten Bereich gehört. Der Befehl RTS hat den Opcode $60, welcher durch die Dekodierung (EOR mit dem Wert $C9) zu dem Wert $A9 wird. Und $A9 ist der Opcode für den Befehl LDA, welcher nach der Dekodierung an der Adresse $613F steht.

$6080: BA          s6080  ┌─►TSX            ;kopiert den Stapelzeiger in das X-Register
$6081: A9 64              │  LDA #$64
$6083: 9D 04 01           │  STA f0104,X
$6086: A9 81              │  LDA #$81
$6088: 9D 03 01           │  STA f0103,X
$608B: A5 BA              │  LDA aBA
$608D: 20 B1 FF           │  JSR ROM_LISTEN ;$FFB1 - LISTEN: Befehl LISTEN für Geräte am seriellen Bus (Start Datenempfang bei Peripheriegeräten)         
$6090: A9 FF              │  LDA #$FF
$6092: 20 93 FF           │  JSR ROM_SECOND ;$FF93 - SECOND: Übertragung der Sekundäradresse nach LISTEN-Befehl 
$6095: A0 00              │  LDY #$00
$6097: B1 02       b6097  │┌►LDA (p02),Y
$6099: 20 A8 FF           ││ JSR ROM_CIOUT  ;$FFA8 - CIOUT: Byte-Ausgabe (serieller Bus)            
$609C: C8                 ││ INY 
$609D: C0 05              ││ CPY #$05
$609F: 90 F6              │└─BCC b6097
$60A1: 60                 │  RTS
$60A2:             p60A2  │  .TEXT "I:0"
$60A5:                    │  .BYTE $20,$20
.                         │
.                         │
.                         │
$6129: A9 37                LDA #$37
$612B: 85 10                STA a10
$612D: A9 07                LDA #$07
$612F: 85 0F                STA a0F
$6131: A9 60              │  LDA #>p60A2
$6133: 85 03              │  STA a03
$6135: A9 A2              │  LDA #<p60A2
$6137: 85 02              │  STA a02
$6139: 20 80 60           └──JSR s6080
$613C: 20 AE FF              JSR ROM_UNLSN ;$FFAE - UNLSN: Senden des UNLISTEN-Befehls für seriellen Bus zur Beendigung der Datenübertragung      
$613F: 60          p613F┌► ┌─RTS           ;nach dem Dekodieren: $613F: A9 62       p613F   LDA #$62
. kodierte Daten        │  │ 
. bis $643E             │  │
.                       │  │ 
$6482: A9 61            │  └►LDA #>p613F
$6484: 85 03            │    STA a03
$6486: A9 3F            │    LDA #<p613F   ;bei $613f
$6488: 85 02            │    STA a02
$648A: A2 03            │    LDX #$03      ;4 Pages
$648C: A0 00            │    LDY #$00
$648E: B1 02       b648E│┌►┌►LDA (p02),Y
$6490: 49 C9            ││ │ EOR #$C9      ;EOR-verknüpfen
$6492: 91 02            ││ │ STA (p02),Y
$6494: 99 00 01    b6494││ │ STA f0100,Y   ;zusätzlich bei $100 ablegen
$6497: 88               ││ │ DEY 
$6498: D0 F4            ││ └─BNE b648E     ;alle 256 Bytes?
$649A: E6 03            ││   INC a03       ;nächste Page
$649C: CA               ││   DEX           ;Page-Zähler
$649D: D0 EF            │└───BNE b648E     ;alle Pages?
$649F: 4C 3F 61    b649F└────JMP p613F

Legende:
   Setzen von 2 Byte der Zeropage (der Wert $37 in Adresse $10 und der Wert $07 in Adresse $0F)
   INITIALIZE des Dikettenlaufwerks
   Floppy-Befehle senden
   Prozessorstapel manipulieren
   Start der Dekodierroutine
   Dekodierroutine
(kodierter) Bereich $613F bis $643E kodiert und dekodiert[Bearbeiten | Quelltext bearbeiten]

Im Folgendem ist einem der gesamte Bereich von $613F bis $643E kodiert und dekodiert dargestellt. Es ist gut zu erkennen, dass aus dem Wert $60 (Opcode für ein RTS) in der Adresse $613F nach dem Dekodieren der Wert $A9 (Opcode für ein LDA) wird. Die Dekodierung erfolgt durch ein EOR mit dem Wert $C9.

$613F:             p613F   .BYTE $60,$AB                          ;dekodiert:$A9,$62
$6141:                     .BYTE $4C,$C2,$60,$F1,$4C,$C3,$60,$C9  ;dekodiert:$85,$0B,$A9,$38,$85,$0A,$A9,$00
$6149:                     .BYTE $4C,$C4,$60,$DB,$4C,$C5,$60,$A8  ;dekodiert:$85,$0D,$A9,$12,$85,$0C,$A9,$61
$6151:                     .BYTE $4C,$CA,$60,$36,$4C,$CB,$E9,$49  ;dekodiert:$85,$03,$A9,$FF,$85,$02,$20,$80
$6159:                     .BYTE $A9,$60,$E9,$E9,$61,$36,$69,$D6  ;dekodiert:$60,$A9,$20,$20,$A8,$FF,$A0,$1F
$6161:                     .BYTE $78,$C3,$E9,$61,$36,$41,$D9,$31  ;dekodiert:$B1,$0A,$20,$A8,$FF,$88,$10,$F8
$6169:                     .BYTE $E9,$67,$36,$D1,$60,$E9,$AC,$C3  ;dekodiert:$20,$AE,$FF,$18,$A9,$20,$65,$0A
$6171:                     .BYTE $4C,$C3,$59,$CB,$2F,$C2,$D1,$60  ;dekodiert:$85,$0A,$90,$02,$E6,$0B,$18,$A9
$6179:                     .BYTE $E9,$A4,$CB,$AB,$44,$CB,$AB,$59  ;dekodiert:$20,$6D,$02,$62,$8D,$02,$62,$90
$6181:                     .BYTE $CA,$27,$CA,$AB,$0F,$C5,$19,$0F  ;dekodiert:$03,$EE,$03,$62,$C6,$0C,$D0,$C6
$6189:                     .BYTE $60,$A8,$4C,$CA,$60,$33,$4C,$CB  ;dekodiert:$A9,$61,$85,$03,$A9,$FA,$85,$02
$6191:                     .BYTE $E9,$49,$A9,$E9,$67,$36,$B1,$69  ;dekodiert:$20,$80,$60,$20,$AE,$FF,$78,$A0
$6199:                     .BYTE $E8,$41,$19,$34,$E9,$B0,$A9,$E5  ;dekodiert:$21,$88,$D0,$FD,$20,$79,$60,$2C
$61A1:                     .BYTE $C9,$14,$F9,$32,$60,$59,$4C,$CC  ;dekodiert:$00,$DD,$30,$FB,$A9,$90,$85,$05
$61A9:                     .BYTE $60,$C9,$4C,$CD,$E9,$CD,$AB,$64  ;dekodiert:$A9,$00,$85,$04,$20,$04,$62,$AD
$61B1:                     .BYTE $DB,$19,$44,$37,$CB,$60,$99,$4C  ;dekodiert:$12,$D0,$8D,$FE,$02,$A9,$50,$85
$61B9:                     .BYTE $CC,$60,$C9,$4C,$CD,$E9,$CD,$AB  ;dekodiert:$05,$A9,$00,$85,$04,$20,$04,$62
$61C1:                     .BYTE $60,$76,$4C,$CC,$60,$89,$4C,$CD  ;dekodiert:$A9,$BF,$85,$05,$A9,$40,$85,$04
$61C9:                     .BYTE $E9,$CD,$AB,$6C,$CC,$00,$76,$19  ;dekodiert:$20,$04,$62,$A5,$05,$C9,$BF,$D0
$61D1:                     .BYTE $CA,$85,$2B,$35,$64,$DB,$19,$39  ;dekodiert:$03,$4C,$E2,$FC,$AD,$12,$D0,$F0
$61D9:                     .BYTE $32,$44,$36,$CB,$6C,$C6,$44,$C9  ;dekodiert:$FB,$8D,$FF,$02,$A5,$0F,$8D,$00
$61E1:                     .BYTE $14,$60,$B6,$44,$C4,$14,$64,$C4  ;dekodiert:$DD,$A9,$7F,$8D,$0D,$DD,$AD,$0D
$61E9:                     .BYTE $14,$6C,$73,$E9,$78,$36,$60,$26  ;dekodiert:$DD,$A5,$BA,$20,$B1,$FF,$A9,$EF
$61F1:                     .BYTE $E9,$5A,$36,$E9,$67,$36,$85,$CA  ;dekodiert:$20,$93,$FF,$20,$AE,$FF,$4C,$03
$61F9:                     .BYTE $09,$84,$E4,$8C,$9E,$CD,$84,$E4  ;dekodiert:$C0,$4D,$2D,$45,$57,$04,$4D,$2D
$6201:                     .BYTE $9E,$C9,$CA,$60,$AD,$4C,$CA,$60  ;dekodiert:$57,$00,$03,$A9,$64,$85,$03,$A9
$6209:                     .BYTE $61,$4C,$CB,$69,$C8,$E9,$EF,$A9  ;dekodiert:$A8,$85,$02,$A0,$01,$20,$26,$60
$6211:                     .BYTE $61,$39,$EA,$81,$E9,$EF,$A9,$A1  ;dekodiert:$A8,$F0,$23,$48,$20,$26,$60,$68
$6219:                     .BYTE $81,$61,$60,$F9,$4C,$C8,$41,$78  ;dekodiert:$48,$A8,$A9,$30,$85,$01,$88,$B1
$6221:                     .BYTE $CB,$58,$CD,$51,$19,$31,$60,$FF  ;dekodiert:$02,$91,$04,$98,$D0,$F8,$A9,$36
$6229:                     .BYTE $4C,$C8,$A1,$D1,$AC,$CD,$4C,$CD  ;dekodiert:$85,$01,$68,$18,$65,$04,$85,$04
$6231:                     .BYTE $59,$10,$2F,$CC,$19,$1C,$A9,$A9  ;dekodiert:$90,$D9,$E6,$05,$D0,$D5,$60,$60
$6239:                     .BYTE $D1,$C9,$44,$C9,$60,$30,$19,$D1  ;dekodiert:$18,$00,$8D,$00,$A9,$F9,$D0,$18
$6241:                     .BYTE $C9,$E5,$CD,$60,$A9,$89,$E9,$C9  ;dekodiert:$00,$2C,$04,$A9,$60,$40,$20,$00
$6249:                     .BYTE $C1,$CB,$C3,$CD,$C5,$CF,$C7,$C8  ;dekodiert:$08,$02,$0A,$04,$0C,$06,$0E,$01
$6251:                     .BYTE $C0,$CA,$C2,$CC,$C4,$CE,$C6,$CF  ;dekodiert:$09,$03,$0B,$05,$0D,$07,$0F,$06
$6259:                     .BYTE $60,$FB,$4C,$E1,$60,$FA,$4C,$CC  ;dekodiert:$A9,$32,$85,$28,$A9,$33,$85,$05
$6261:                     .BYTE $60,$8C,$4C,$C9,$60,$A9,$C8,$39  ;dekodiert:$A9,$45,$85,$00,$A9,$60,$01,$F0
$6269:                     .BYTE $03,$C9,$6F,$CA,$91,$E9,$C2,$19  ;dekodiert:$CA,$00,$A6,$03,$58,$20,$0B,$D0
$6271:                     .BYTE $F9,$60,$D5,$C5,$44,$27,$60,$39  ;dekodiert:$30,$A9,$1C,$0C,$8D,$EE,$A9,$F0
$6279:                     .BYTE $03,$C9,$6F,$CC,$39,$EB,$6F,$3A  ;dekodiert:$CA,$00,$A6,$05,$F0,$22,$A6,$F3
$6281:                     .BYTE $78,$85,$3D,$03,$85,$CA,$39,$F9  ;dekodiert:$B1,$4C,$F4,$CA,$4C,$03,$F0,$30
$6289:                     .BYTE $00,$8C,$6C,$F6,$4F,$03,$C9,$4F  ;dekodiert:$C9,$45,$A5,$3F,$86,$CA,$00,$86
$6291:                     .BYTE $C8,$6B,$80,$4F,$73,$F8,$4C,$E1  ;dekodiert:$01,$A2,$49,$86,$BA,$31,$85,$28
$6299:                     .BYTE $64,$CA,$45,$E9,$C8,$6B,$C8,$A0  ;dekodiert:$AD,$03,$8C,$20,$01,$A2,$01,$69
$62A1:                     .BYTE $36,$80,$CF,$79,$DA,$39,$CC,$E1  ;dekodiert:$FF,$49,$06,$B0,$13,$F0,$05,$28
$62A9:                     .BYTE $24,$F1,$36,$6B,$EB,$6C,$EB,$19  ;dekodiert:$ED,$38,$FF,$A2,$22,$A5,$22,$D0
$62B1:                     .BYTE $03,$C9,$6F,$CA,$73,$E9,$C1,$CA  ;dekodiert:$CA,$00,$A6,$03,$BA,$20,$08,$03
$62B9:                     .BYTE $E0,$B9,$8C,$83,$AC,$D1,$B9,$6C  ;dekodiert:$29,$70,$45,$4A,$65,$18,$70,$A5
$62C1:                     .BYTE $B9,$4C,$37,$E0,$D5,$C9,$64,$61  ;dekodiert:$70,$85,$FE,$29,$1C,$00,$AD,$A8
$62C9:                     .BYTE $C3,$83,$4F,$A9,$D5,$C5,$44,$27  ;dekodiert:$0A,$4A,$86,$60,$1C,$0C,$8D,$EE
$62D1:                     .BYTE $60,$CA,$27,$E9,$EB,$4C,$CC,$45  ;dekodiert:$A9,$03,$EE,$20,$22,$85,$05,$8C
$62D9:                     .BYTE $E9,$C8,$60,$36,$6B,$A9,$32,$19  ;dekodiert:$20,$01,$A9,$FF,$A2,$60,$FB,$D0
$62E1:                     .BYTE $D1,$CC,$64,$D1,$CC,$44,$82,$60  ;dekodiert:$18,$05,$AD,$18,$05,$8D,$4B,$A9
$62E9:                     .BYTE $21,$19,$41,$CA,$78,$E9,$D7,$60  ;dekodiert:$E8,$D0,$88,$03,$B1,$20,$1E,$A9
$62F1:                     .BYTE $D5,$C9,$44,$B9,$4C,$B9,$8C,$C1  ;dekodiert:$1C,$00,$8D,$70,$85,$70,$45,$08
$62F9:                     .BYTE $F9,$B9,$0F,$D8,$39,$41,$C9,$6D  ;dekodiert:$30,$70,$C6,$11,$F0,$88,$00,$A4
$6301:                     .BYTE $EB,$4F,$D1,$6F,$CA,$E9,$E9,$B9  ;dekodiert:$22,$86,$18,$A6,$03,$20,$20,$70
$6309:                     .BYTE $4C,$CD,$60,$CA,$78,$E9,$36,$60  ;dekodiert:$85,$04,$A9,$03,$B1,$20,$FF,$A9
$6311:                     .BYTE $CA,$45,$E9,$43,$C8,$6B,$CA,$4D  ;dekodiert:$03,$8C,$20,$8A,$01,$A2,$03,$84
$6319:                     .BYTE $A9,$D5,$C9,$44,$CA,$C6,$D4,$56  ;dekodiert:$60,$1C,$00,$8D,$03,$0F,$1D,$9F
$6321:                     .BYTE $E0,$D5,$C9,$64,$8A,$4C,$3B,$82  ;dekodiert:$29,$1C,$00,$AD,$43,$85,$F2,$4B
$6329:                     .BYTE $E9,$43,$A9,$EB,$4C,$C9,$60,$21  ;dekodiert:$20,$8A,$60,$22,$85,$00,$A9,$E8
$6331:                     .BYTE $79,$F1,$CA,$3A,$E9,$B9,$6F,$C6  ;dekodiert:$B0,$38,$03,$F3,$20,$70,$A6,$0F
$6339:                     .BYTE $E0,$43,$B9,$4C,$83,$83,$83,$83  ;dekodiert:$29,$8A,$70,$85,$4A,$4A,$4A,$4A
$6341:                     .BYTE $63,$CD,$E3,$E5,$BA,$78,$41,$CA  ;dekodiert:$AA,$04,$2A,$2C,$73,$B1,$88,$03
$6349:                     .BYTE $DA,$E9,$B8,$6D,$CD,$DF,$E9,$B8  ;dekodiert:$13,$20,$71,$A4,$04,$16,$20,$71
$6351:                     .BYTE $6C,$CA,$DA,$E9,$C9,$69,$B8,$C9  ;dekodiert:$A5,$03,$13,$20,$00,$A0,$71,$00
$6359:                     .BYTE $74,$B9,$6F,$D1,$C9,$44,$C6,$E0  ;dekodiert:$BD,$70,$A6,$18,$00,$8D,$0F,$29
$6361:                     .BYTE $E3,$43,$D1,$C9,$47,$C9,$19,$C9  ;dekodiert:$2A,$8A,$18,$00,$8E,$00,$D0,$00
$6369:                     .BYTE $19,$D1,$C9,$E5,$32,$39,$D1,$C9  ;dekodiert:$D0,$18,$00,$2C,$FB,$F0,$18,$00
$6371:                     .BYTE $E5,$D1,$C9,$44,$CD,$60,$63,$60  ;dekodiert:$2C,$18,$00,$8D,$04,$A9,$AA,$A9
$6379:                     .BYTE $CD,$98,$E9,$81,$80,$6C,$B1,$C1  ;dekodiert:$04,$51,$20,$48,$49,$A5,$78,$08
$6381:                     .BYTE $A9,$D1,$C9,$47,$CB,$6B,$C9,$39  ;dekodiert:$60,$18,$00,$8E,$02,$A2,$00,$F0
$6389:                     .BYTE $08,$19,$D1,$C9,$44,$C9,$09,$C6  ;dekodiert:$C1,$D0,$18,$00,$8D,$00,$C0,$0F
$6391:                     .BYTE $E0,$E3,$23,$D1,$C9,$44,$CA,$4C  ;dekodiert:$29,$2A,$EA,$18,$00,$8D,$03,$85
$6399:                     .BYTE $A1,$D5,$C5,$44,$25,$60,$30,$46  ;dekodiert:$68,$1C,$0C,$8D,$EC,$A9,$F9,$8F
$63A1:                     .BYTE $E9,$FA,$4D,$D1,$C9,$45,$D5,$C9  ;dekodiert:$20,$33,$84,$18,$00,$8C,$1C,$00
$63A9:                     .BYTE $44,$3E,$E0,$D5,$C9,$64,$CD,$4A  ;dekodiert:$8D,$F7,$29,$1C,$00,$AD,$04,$83
$63B1:                     .BYTE $E9,$32,$39,$D1,$C9,$E5,$CD,$60  ;dekodiert:$20,$FB,$F0,$18,$00,$2C,$04,$A9
$63B9:                     .BYTE $CD,$06,$E9,$DD,$60,$CC,$E0,$44  ;dekodiert:$04,$CF,$20,$14,$A9,$05,$29,$8D
$63C1:                     .BYTE $C6,$60,$CD,$DA,$44,$90,$60,$CD  ;dekodiert:$0F,$A9,$04,$13,$8D,$59,$A9,$04
$63C9:                     .BYTE $06,$E9,$DA,$60,$BA,$4C,$CB,$60  ;dekodiert:$CF,$20,$13,$A9,$73,$85,$02,$A9
$63D1:                     .BYTE $BD,$4C,$CF,$60,$A9,$E1,$80,$E9  ;dekodiert:$74,$85,$06,$A9,$60,$28,$49,$20
$63D9:                     .BYTE $C3,$69,$CC,$CB,$E9,$CD,$3A,$E9  ;dekodiert:$0A,$A0,$05,$02,$20,$04,$F3,$20
$63E1:                     .BYTE $8C,$69,$CD,$3A,$E9,$C9,$69,$DB  ;dekodiert:$45,$A0,$04,$F3,$20,$00,$A0,$12
$63E9:                     .BYTE $19,$DA,$6B,$CD,$3A,$E9,$CB,$69  ;dekodiert:$D0,$13,$A2,$04,$F3,$20,$02,$A0
$63F1:                     .BYTE $3C,$D9,$E9,$CC,$E0,$44,$C9,$CC  ;dekodiert:$F5,$10,$20,$05,$29,$8D,$00,$05
$63F9:                     .BYTE $E0,$45,$CF,$C8,$65,$31,$19,$03  ;dekodiert:$29,$8C,$06,$01,$AC,$F8,$D0,$CA
$6401:                     .BYTE $C9,$6F,$CA,$E0,$E9,$CC,$E1,$44  ;dekodiert:$00,$A6,$03,$29,$20,$05,$28,$8D
$6409:                     .BYTE $DD,$60,$CC,$E0,$44,$D8,$60,$21  ;dekodiert:$14,$A9,$05,$29,$8D,$11,$A9,$E8
$6411:                     .BYTE $19,$03,$CC,$CB,$E9,$CD,$3A,$D5  ;dekodiert:$D0,$CA,$05,$02,$20,$04,$F3,$1C
$6419:                     .BYTE $C8,$64,$A9,$3E,$19,$41,$D5,$C8  ;dekodiert:$01,$AD,$60,$F7,$D0,$88,$1C,$01
$6421:                     .BYTE $64,$71,$37,$99,$EF,$19,$DC,$60  ;dekodiert:$AD,$B8,$FE,$50,$26,$D0,$15,$A9
$6429:                     .BYTE $29,$19,$A1,$CA,$36,$E9,$37,$69  ;dekodiert:$E0,$D0,$68,$03,$FF,$20,$FE,$A0
$6431:                     .BYTE $CB,$39,$81,$CF,$C9,$64,$41,$E9  ;dekodiert:$02,$F0,$48,$06,$00,$AD,$88,$20
$6439:                     .BYTE $CA,$91,$E9,$CC,$E1,$44          ;dekodiert:$03,$58,$20,$05,$28,$8D
Bereich von $613F bis $6193[Bearbeiten | Quelltext bearbeiten]

In diesem Abschnitt wird der Bereich von $613F bis $6193 behandelt. Zusätzlich sind der Bereich von $61FA bis $6203 und der Bereich $6238 bis $6238 enthalten. In diesem Bereich wird die Schnellladeroutine (Stufe 1) an das Diskettenlaufwerk gesendet und startet. Der Programmcode der Schnellladeroutine (Stufe 1) ist im Speicher des Rechners nicht lesbar, da dieser in jeweils 32 Byte Blöcken rückwärts gespeichert abgelegt ist. Erst im Speicher des Diskettenlaufwerks ist der Programmcode lesbar. Die Schnellladeroutine (Stufe 1) befindet sich nach der Übertragung im Speicherbereich $0300 bis $053F des Diskettenlaufwerks. Die Kopierschutzprüfung (I) ist ein Teil dieser Schnellladeroutine (Stufe 1), welche sich zu diesem Zeitpunkt im Speicher des Diskettenlaufwerks befindet. Anschließend erfolgt noch der Start der Schnellladeroutine (Stufe 1), welcher an der Adresse $0457 im Speicher des Diskettenlaufwerks erfolgt.

$613F: A9 62       p613F   LDA #>p6238   ;$62
$6141: 85 0B               STA a0B
$6143: A9 38               LDA #<p6238   ;$38
$6145: 85 0A               STA a0A
$6147: A9 00               LDA #$00
$6149: 85 0D               STA a0D       ;Zeropage-Adresse $0D wird als Puffer verwendet
$614B: A9 12               LDA #$12      ;$12=18
$614D: 85 0C               STA a0C       ;Zeropage-Adresse $0C wird als Puffer verwendet
$614F: A9 61       b614F┌─►LDA #>p61FF
$6151: 85 03            │  STA a03
$6153: A9 FF            │  LDA #<p61FF
$6155: 85 02            │  STA a02
$6157: 20 80 60         │  JSR s6080 ─►
$615A: A9 20            │  LDA #$20     
$615C: 20 A8 FF         │  JSR ROM_CIOUT ;$FFA8 - CIOUT: Byte-Ausgabe (serieller Bus)
$615F: A0 1F            │  LDY #$1F      ;$1F=31
$6161: B1 0A       b6161│┌►LDA (p0A),Y   ;lädt den Akkumulator mit dem Inhalt der Speicheradresse (LSB= $ll ; MSB= $ll+1)+Y
$6163: 20 A8 FF         ││ JSR ROM_CIOUT ;$FFA8 - CIOUT: Byte-Ausgabe (serieller Bus)
$6166: 88               ││ DEY           ;vermindert den Inhalt des Y-Registers um 1
$6167: 10 F8            │└─BPL b6161     ;verzweigt zur Adresse $hhll, wenn das Ergebnis der letzten Operation positiv ist, was mit Negative-Flag = 0 angezeigt wird
$6169: 20 AE FF         │  JSR ROM_UNLSN ;$FFAE - UNLSN: Senden des UNLISTEN-Befehls für seriellen Bus zur Beendigung der Datenübertragung
$616C: 18               │  CLC           ;löscht das Carry-Flag
$616D: A9 20            │  LDA #$20      ;$20=32
$616F: 65 0A            │  ADC a0A       ;addiert zum Inhalt des Akkumulators den Inhalt der Zeropage-Adresse $ll
$6171: 85 0A            │  STA a0A
$6173: 90 02            │┌─BCC b6177     ;verzweigt zur Adresse $hhll, wenn das Carry-Flag = 0 ist
$6175: E6 0B            ││ INC a0B
$6177: 18          b6177│└►CLC 
$6178: A9 20            │  LDA #$20      ;$20=32
$617A: 6D 02 62         │  ADC a6202     ;addiert zum Inhalt des Akkumulators den Inhalt der Zeropage-Adresse $ll
$617D: 8D 02 62         │  STA a6202
$6180: 90 03            │┌─BCC b6185
$6182: EE 03 62         ││ INC a6203     ;Übertrag High-Byte
$6185: C6 0C       b6185│└►DEC a0C       ;Zeropage-Adresse $0C wird als Puffer verwendet
$6187: D0 C6            └──BNE b614F
$6189: A9 61               LDA #>p61FA
$618B: 85 03               STA a03
$618D: A9 FA               LDA #<p61FA
$618F: 85 02               STA a02
$6191: 20 80 60            JSR s6080 ─►
.
.
.
$61FA:             p61FA   .TEXT "M-E"
$61FD:                     .BYTE $57,$04
$61FF:             p61FF   .TEXT "M-W"
$6202:             a6202   .BYTE $00
$6203:             a6203   .BYTE $03
.
.
.
;               ┌──────────────────────────────────────────────────────────────────────────────────────────────┐
;               │                              ┌────────────────────────────────┐                              │
;Block 1        │                              │                                ▼                              │
$6238:   .BYTE $60,$18,$00,$8D,$00,$A9,$F9,$D0 │   ;Floppy-RAM: $0300:   .BYTE $0F,$07,$0D,$05,$0B,$03,$09,$01 │
$6240:   .BYTE $18,$00,$2C,$04,$A9,$60,$40,$20 │   ;Floppy-RAM: $0308:   .BYTE $0E,$06,$0C,$04,$0A,$02,$08,$00 │
$6248:   .BYTE $00,$08,$02,$0A,$04,$0C,$06,$0E │   ;Floppy-RAM: $0310:   .BYTE $20,$40,$60,$A9,$04,$2C,$00,$18 │
$6250:   .BYTE $01,$09,$03,$0B,$05,$0D,$07,$0F─┘   ;Floppy-RAM: $0318:   .BYTE $D0,$F9,$A9,$00,$8D,$00,$18,$60◄┘
;Block 2                                                                                                        
$6258:   .BYTE $06,$A9,$32,$85,$28,$A9,$33,$85     ;Floppy-RAM: $0320:   .BYTE $A9,$EE,$8D,$0C,$1C,$A9,$30,$D0  
$6260:   .BYTE $05,$A9,$45,$85,$00,$A9,$60,$01     ;Floppy-RAM: $0328:   .BYTE $0B,$20,$58,$03,$A6,$00,$CA,$F0  
$6268:   .BYTE $F0,$CA,$00,$A6,$03,$58,$20,$0B     ;Floppy-RAM: $0330:   .BYTE $01,$60,$A9,$00,$85,$45,$A9,$05  
$6270:   .BYTE $D0,$30,$A9,$1C,$0C,$8D,$EE,$A9     ;Floppy-RAM: $0338:   .BYTE $85,$33,$A9,$28,$85,$32,$A9,$06  
;Block 3                                                                                                        
$6278:   .BYTE $F0,$CA,$00,$A6,$05,$F0,$22,$A6     ;Floppy-RAM: $0340:   .BYTE $85,$31,$BA,$86,$49,$A2,$01,$86  
$6280:   .BYTE $F3,$B1,$4C,$F4,$CA,$4C,$03,$F0     ;Floppy-RAM: $0348:   .BYTE $00,$CA,$86,$3F,$A5,$45,$C9,$30  
$6288:   .BYTE $30,$C9,$45,$A5,$3F,$86,$CA,$00     ;Floppy-RAM: $0350:   .BYTE $F0,$03,$4C,$CA,$F4,$4C,$B1,$F3  
$6290:   .BYTE $86,$01,$A2,$49,$86,$BA,$31,$85     ;Floppy-RAM: $0358:   .BYTE $A6,$22,$F0,$05,$A6,$00,$CA,$F0  
;Block 4                                                                                                        
$6298:   .BYTE $28,$AD,$03,$8C,$20,$01,$A2,$01     ;Floppy-RAM: $0360:   .BYTE $08,$20,$BA,$03,$A6,$00,$CA,$D0  
$62A0:   .BYTE $69,$FF,$49,$06,$B0,$13,$F0,$05     ;Floppy-RAM: $0368:   .BYTE $22,$A5,$22,$A2,$FF,$38,$ED,$28  
$62A8:   .BYTE $28,$ED,$38,$FF,$A2,$22,$A5,$22     ;Floppy-RAM: $0370:   .BYTE $05,$F0,$13,$B0,$06,$49,$FF,$69  
$62B0:   .BYTE $D0,$CA,$00,$A6,$03,$BA,$20,$08     ;Floppy-RAM: $0378:   .BYTE $01,$A2,$01,$20,$8C,$03,$AD,$28  
;Block 5                                                                                                        
$62B8:   .BYTE $03,$29,$70,$45,$4A,$65,$18,$70     ;Floppy-RAM: $0380:   .BYTE $05,$85,$22,$20,$EE,$03,$A9,$EE  
$62C0:   .BYTE $A5,$70,$85,$FE,$29,$1C,$00,$AD     ;Floppy-RAM: $0388:   .BYTE $8D,$0C,$1C,$60,$86,$4A,$0A,$A8  
$62C8:   .BYTE $A8,$0A,$4A,$86,$60,$1C,$0C,$8D     ;Floppy-RAM: $0390:   .BYTE $AD,$00,$1C,$29,$FE,$85,$70,$A5  
$62D0:   .BYTE $EE,$A9,$03,$EE,$20,$22,$85,$05     ;Floppy-RAM: $0398:   .BYTE $70,$18,$65,$4A,$45,$70,$29,$03  
;Block 6                                                                                                        
$62D8:   .BYTE $8C,$20,$01,$A9,$FF,$A2,$60,$FB     ;Floppy-RAM: $03A0:   .BYTE $45,$70,$85,$70,$8D,$00,$1C,$A9  
$62E0:   .BYTE $D0,$18,$05,$AD,$18,$05,$8D,$4B     ;Floppy-RAM: $03A8:   .BYTE $1E,$20,$B1,$03,$88,$D0,$E8,$A9  
$62E8:   .BYTE $A9,$E8,$D0,$88,$03,$B1,$20,$1E     ;Floppy-RAM: $03B0:   .BYTE $4B,$8D,$05,$18,$AD,$05,$18,$D0  
$62F0:   .BYTE $A9,$1C,$00,$8D,$70,$85,$70,$45     ;Floppy-RAM: $03B8:   .BYTE $FB,$60,$A2,$FF,$A9,$01,$20,$8C  
;Block 7                                                                                                        
$62F8:   .BYTE $08,$30,$70,$C6,$11,$F0,$88,$00     ;Floppy-RAM: $03C0:   .BYTE $03,$A2,$01,$8A,$20,$8C,$03,$A9  
$6300:   .BYTE $A4,$22,$86,$18,$A6,$03,$20,$20     ;Floppy-RAM: $03C8:   .BYTE $FF,$20,$B1,$03,$A9,$04,$85,$70  
$6308:   .BYTE $70,$85,$04,$A9,$03,$B1,$20,$FF     ;Floppy-RAM: $03D0:   .BYTE $20,$20,$03,$A6,$18,$86,$22,$A4  
$6310:   .BYTE $A9,$03,$8C,$20,$8A,$01,$A2,$03     ;Floppy-RAM: $03D8:   .BYTE $00,$88,$F0,$11,$C6,$70,$30,$08  
;Block 8                                                                                                        
$6318:   .BYTE $84,$60,$1C,$00,$8D,$03,$0F,$1D     ;Floppy-RAM: $03E0:   .BYTE $A6,$70,$20,$F3,$03,$38,$B0,$E8  
$6320:   .BYTE $9F,$29,$1C,$00,$AD,$43,$85,$F2     ;Floppy-RAM: $03E8:   .BYTE $A9,$00,$85,$22,$60,$8A,$20,$4B  
$6328:   .BYTE $4B,$20,$8A,$60,$22,$85,$00,$A9     ;Floppy-RAM: $03F0:   .BYTE $F2,$85,$43,$AD,$00,$1C,$29,$9F  
$6330:   .BYTE $E8,$B0,$38,$03,$F3,$20,$70,$A6     ;Floppy-RAM: $03F8:   .BYTE $1D,$0F,$03,$8D,$00,$1C,$60,$84  
;Block 9                                                                                                        
$6338:   .BYTE $0F,$29,$8A,$70,$85,$4A,$4A,$4A     ;Floppy-RAM: $0400:   .BYTE $71,$A0,$00,$20,$13,$03,$A5,$71  
$6340:   .BYTE $4A,$AA,$04,$2A,$2C,$73,$B1,$88     ;Floppy-RAM: $0408:   .BYTE $20,$16,$04,$A4,$71,$20,$13,$03  
$6348:   .BYTE $03,$13,$20,$71,$A4,$04,$16,$20     ;Floppy-RAM: $0410:   .BYTE $88,$B1,$73,$2C,$2A,$04,$AA,$4A  
$6350:   .BYTE $71,$A5,$03,$13,$20,$00,$A0,$71     ;Floppy-RAM: $0418:   .BYTE $4A,$4A,$4A,$85,$70,$8A,$29,$0F  
;Block 10                                                                                                       
$6358:   .BYTE $00,$BD,$70,$A6,$18,$00,$8D,$0F     ;Floppy-RAM: $0420:   .BYTE $AA,$A9,$04,$8D,$00,$18,$2C,$00  
$6360:   .BYTE $29,$2A,$8A,$18,$00,$8E,$00,$D0     ;Floppy-RAM: $0428:   .BYTE $18,$F0,$FB,$2C,$00,$18,$D0,$00  
$6368:   .BYTE $00,$D0,$18,$00,$2C,$FB,$F0,$18     ;Floppy-RAM: $0430:   .BYTE $D0,$00,$8E,$00,$18,$8A,$2A,$29  
$6370:   .BYTE $00,$2C,$18,$00,$8D,$04,$A9,$AA     ;Floppy-RAM: $0438:   .BYTE $0F,$8D,$00,$18,$A6,$70,$BD,$00  
;Block 11                                                                                                       
$6378:   .BYTE $A9,$04,$51,$20,$48,$49,$A5,$78     ;Floppy-RAM: $0440:   .BYTE $03,$8D,$00,$18,$EA,$2A,$29,$0F  
$6380:   .BYTE $08,$60,$18,$00,$8E,$02,$A2,$00     ;Floppy-RAM: $0448:   .BYTE $C0,$00,$8D,$00,$18,$D0,$C1,$F0  
$6388:   .BYTE $F0,$C1,$D0,$18,$00,$8D,$00,$C0     ;Floppy-RAM: $0450:   .BYTE $00,$A2,$02,$8E,$00,$18,$60,$08  
$6390:   .BYTE $0F,$29,$2A,$EA,$18,$00,$8D,$03     ;Floppy-RAM: $0458:   .BYTE $78,$A5,$49,$48,$20,$51,$04,$A9  
;Block 12                                                                                                       
$6398:   .BYTE $85,$68,$1C,$0C,$8D,$EC,$A9,$F9     ;Floppy-RAM: $0460:   .BYTE $04,$2C,$00,$18,$F0,$FB,$20,$83  
$63A0:   .BYTE $8F,$20,$33,$84,$18,$00,$8C,$1C     ;Floppy-RAM: $0468:   .BYTE $04,$AD,$00,$1C,$29,$F7,$8D,$00  
$63A8:   .BYTE $00,$8D,$F7,$29,$1C,$00,$AD,$04     ;Floppy-RAM: $0470:   .BYTE $1C,$8C,$00,$18,$84,$33,$20,$8F  
$63B0:   .BYTE $83,$20,$FB,$F0,$18,$00,$2C,$04     ;Floppy-RAM: $0478:   .BYTE $F9,$A9,$EC,$8D,$0C,$1C,$68,$85  
;Block 13                                                                                                       
$63B8:   .BYTE $A9,$04,$CF,$20,$14,$A9,$05,$29     ;Floppy-RAM: $0480:   .BYTE $49,$28,$60,$A9,$06,$85,$74,$A9  
$63C0:   .BYTE $8D,$0F,$A9,$04,$13,$8D,$59,$A9     ;Floppy-RAM: $0488:   .BYTE $02,$85,$73,$A9,$13,$20,$CF,$04  
$63C8:   .BYTE $04,$CF,$20,$13,$A9,$73,$85,$02     ;Floppy-RAM: $0490:   .BYTE $A9,$59,$8D,$13,$04,$A9,$0F,$8D  
$63D0:   .BYTE $A9,$74,$85,$06,$A9,$60,$28,$49     ;Floppy-RAM: $0498:   .BYTE $29,$05,$A9,$14,$20,$CF,$04,$A9  
;Block 14                                                                                                       
$63D8:   .BYTE $20,$0A,$A0,$05,$02,$20,$04,$F3     ;Floppy-RAM: $04A0:   .BYTE $00,$8D,$29,$05,$20,$10,$F5,$A0  
$63E0:   .BYTE $20,$45,$A0,$04,$F3,$20,$00,$A0     ;Floppy-RAM: $04A8:   .BYTE $02,$20,$F3,$04,$A2,$13,$D0,$12  
$63E8:   .BYTE $12,$D0,$13,$A2,$04,$F3,$20,$02     ;Floppy-RAM: $04B0:   .BYTE $A0,$00,$20,$F3,$04,$A0,$45,$20  
$63F0:   .BYTE $A0,$F5,$10,$20,$05,$29,$8D,$00     ;Floppy-RAM: $04B8:   .BYTE $F3,$04,$20,$02,$05,$A0,$0A,$20  
;Block 15                                                                                                       
$63F8:   .BYTE $05,$29,$8C,$06,$01,$AC,$F8,$D0     ;Floppy-RAM: $04C0:   .BYTE $F3,$04,$20,$02,$05,$CA,$D0,$E8  
$6400:   .BYTE $CA,$00,$A6,$03,$29,$20,$05,$28     ;Floppy-RAM: $04C8:   .BYTE $A9,$11,$8D,$29,$05,$A9,$14,$8D  
$6408:   .BYTE $8D,$14,$A9,$05,$29,$8D,$11,$A9     ;Floppy-RAM: $04D0:   .BYTE $28,$05,$20,$29,$03,$A6,$00,$CA  
$6410:   .BYTE $E8,$D0,$CA,$05,$02,$20,$04,$F3     ;Floppy-RAM: $04D8:   .BYTE $D0,$F8,$AC,$01,$06,$8C,$29,$05  
;Block 16                                                                                                       
$6418:   .BYTE $1C,$01,$AD,$60,$F7,$D0,$88,$1C     ;Floppy-RAM: $04E0:   .BYTE $88,$AD,$00,$06,$48,$F0,$02,$A0  
$6420:   .BYTE $01,$AD,$B8,$FE,$50,$26,$D0,$15     ;Floppy-RAM: $04E8:   .BYTE $FE,$20,$FF,$03,$68,$D0,$E0,$A9  
$6428:   .BYTE $A9,$E0,$D0,$68,$03,$FF,$20,$FE     ;Floppy-RAM: $04F0:   .BYTE $15,$D0,$26,$50,$FE,$B8,$AD,$01  
$6430:   .BYTE $A0,$02,$F0,$48,$06,$00,$AD,$88     ;Floppy-RAM: $04F8:   .BYTE $1C,$88,$D0,$F7,$60,$AD,$01,$1C  
;Block 17                                                                                                       
$6438:   .BYTE $20,$03,$58,$20,$05,$28,$8D,$12     ;Floppy-RAM: $0500:   .BYTE $B8,$60,$AC,$00,$1C,$10,$F6,$50  
$6440:   .BYTE $A9,$68,$68,$ED,$F0,$67,$C9,$F1     ;Floppy-RAM: $0508:   .BYTE $F9,$B8,$AD,$01,$1C,$C9,$55,$F0  
$6448:   .BYTE $F0,$55,$C9,$1C,$01,$AD,$B8,$F9     ;Floppy-RAM: $0510:   .BYTE $F1,$C9,$67,$F0,$ED,$68,$68,$A9  
$6450:   .BYTE $50,$F6,$10,$1C,$00,$AC,$60,$B8     ;Floppy-RAM: $0518:   .BYTE $12,$8D,$28,$05,$20,$58,$03,$20  
;Block 18                                                                                                       
$6458:   .BYTE $00,$00,$00,$00,$00,$00,$00,$00     ;Floppy-RAM: $0520:   .BYTE $13,$03,$A9,$00,$A8,$4C,$16,$04  
$6460:   .BYTE $00,$00,$00,$00,$00,$00,$00,$00     ;Floppy-RAM: $0528:   .BYTE $00,$0D,$00,$00,$00,$AE,$77,$00  
$6468:   .BYTE $00,$77,$AE,$00,$00,$00,$0D,$00     ;Floppy-RAM: $0530:   .BYTE $00,$00,$00,$00,$00,$00,$00,$00  
$6470:   .BYTE $04,$16,$4C,$A8,$00,$A9,$03,$13     ;Floppy-RAM: $0538:   .BYTE $00,$00,$00,$00,$00,$00,$00,$00  

Legende:
   Kopiert den Speicher von $6238 bis $6477 in den Speicher des Diskettenlaufwerks von $0300 bis $053F
   - Es werden immer Blöcke von 32 Byte an das Diskettenlaufwerks gesendet.
   - Jeder Block wird dabei von Hinten nach Vorn (also Rückwerts) an das Diskettenlaufwerk gesendet.
   - Der Programmcode ist also im Speicher des Rechners nicht lesbar, erst im Speicher des Diskettenlaufwerks stimmt die Reihenfolge der Bytes und der Programmcode wird lesbar
   Die Schnellladeroutine (Stufe 1) im Speicher des Diskettenlaufwerks wird gestartet
Bereich von $6194 bis $61D4[Bearbeiten | Quelltext bearbeiten]

In diesem Abschnitt wird der Bereich von $6194 bis $61D4 behandelt. Zusätzlich sind der Bereich $6204 bis $6237 und der Bereich $6016 bis $607F enthalten. In diesem Bereich wird die Schnellladeroutine (Stufe 1) im Diskettenlaufwerk benutzt, um den GEOS KERNAL zu laden. Die Übertragung der Daten mit der Schnellladeroutine (Stufe 1) ist für die Betrachtung des Kopierschutzschutzes relativ unwichtig. Vielleicht nur mal soviel, die Schnellladeroutine (Stufe 1) überträgt immer 2 Bits auf einmal, dafür wird die CLOCK-IN- und DATA-IN-Leitung des CIA2 verwendet. Dabei werden 4 2-Bit-Grupen ohne Handshake übertragen. Es wird sich dabei darauf verlassen, dass der Rechner und das Diskettenlaufwerk zeitlich synchron arbeiten, dadurch können auch Daten auf der CLK-Leitung übertragen werden und der zeitliche Aufwand für die Synchronisation wird drastisch minimiert.

Die Schnellladeroutine (Stufe 1) im Diskettenlaufwerk wird in diesem Bereich 3 mal benutzt, um Daten von der Diskette einzulesen. Dabei übermittelt die Schnellladeroutine (Stufe 1) jeweils eine Sektorkette, welche jeweils durch einen fest kodierten Startsektor definiert ist. Die 3 Sektorketten entsprechen dabei aber genau den 3 Datensätzen der GEOS KERNAL Datei, welche im GEOS-VLIR-Format gespeichert vorliegt. Die erste Sektorkette, welche dem Datensatz 1 entspricht, wird nach $9000 geladen. Die zweite Sektorkette, welche dem Datensatz 3 entspricht wird nach $5000 geladen. Und die dritte Sektorkette, welche dem Datensatz 2 entspricht, wird nach $BF40 geladen. Somit werden die Daten der GEOS KERNAL Datei komplett in den Speicher des Rechners geladen.

$6016:              f6016       .BYTE $0F,$07,$0D,$05,$0B,$03,$09,$01
$601E:                          .BYTE $0E,$06,$0C,$04,$0A,$02,$08,$00
$6026: 78       ┌►┌►s6026       SEI 
$6027: A5 0F    │ │             LDA a0F          ;$07 = %00000111
$6029: 8D 00 DD │ │             STA $DD00        ;CIA2: Daten Port A
                │ │                              ;$07 = %00000111
                │ │                              ;       ││││││││  Bit 0..1: Auswahl der Position des VIC-Speichers
                │ │                              ;       ││││││││    %00, 0: Bank 3: $C000-$FFFF, 49152-65535
                │ │                              ;       ││││││││    %01, 1: Bank 2: $8000-$BFFF, 32768-49151
                │ │                              ;       ││││││││    %10, 2: Bank 1: $4000-$7FFF, 16384-32767
                │ │                              ;       ││││││└└───►%11, 3: Bank 0: $0000-$3FFF, 0-16383 (Standard)
                │ │                              ;       │││││└───►Bit 2: RS-232: TXD Ausgang, Userport: Daten PA 2 (Pin M)
                │ │                              ;       │││││     Bit 3..5: Serielle Schnittstelle Ausgang (0=High/Inactive, 1=Low/Active)
                │ │                              ;       ││││└──────►Bit 3: ATN OUT
                │ │                              ;       │││└───────►Bit 4: CLOCK OUT
                │ │                              ;       ││└────────►Bit 5: DATA OUT
                │ │                              ;       ││        Bit 6..7: Serielle Schnittstelle Eingang (0=Low/Active, 1=High/Inactive)
                │ │                              ;       │└─────────►Bit 6: CLOCK IN
                │ │                              ;       └──────────►Bit 7: DATA IN 
$602C: 2C 00 DD │ │ b602C     ┌►BIT $DD00        ;CIA2: Daten Port A
$602F: 10 FB    │ │           └─BPL b602C        ;warten bis Bit 7 (DATA IN) = 1 ist 
$6031: 48       │ │             PHA 
$6032: 68       │ │             PLA 
$6033: 48       │ │             PHA 
$6034: 68       │ │             PLA 
$6035: 48       │ │             PHA 
$6036: 68       │ │             PLA 
$6037: EA       │ │             NOP 
$6038: 84 0E    │ │             STY a0E
$603A: 38       │ │ b603A  ┌───►SEC 
$603B: AD 12 D0 │ │ b603B  │  ┌►LDA $D012        ;Lesen: Aktuelle Rasterzeile
$603E: E9 31    │ │        │  │ SBC #$31
$6040: 90 04    │ │        │ ┌│─BCC b6046
$6042: 29 06    │ │        │ ││ AND #$06
$6044: F0 F5    │ │        │ │└─BEQ b603B
$6046: A5 10    │ │ b6046  │ └─►LDA a10          ;$37 = %00110111
$6048: 8D 00 DD │ │        │    STA $DD00        ;CIA2: Daten Port A
                │ │        │                     ;$37 = %00110111
                │ │        │                     ;       │││││││  Bit 0..1: Auswahl der Position des VIC-Speichers
                │ │        │                     ;       │││││││    %00, 0: Bank 3: $C000-$FFFF, 49152-65535
                │ │        │                     ;       │││││││    %01, 1: Bank 2: $8000-$BFFF, 32768-49151
                │ │        │                     ;       │││││││    %10, 2: Bank 1: $4000-$7FFF, 16384-32767
                │ │        │                     ;       │││││└└───►%11, 3: Bank 0: $0000-$3FFF, 0-16383 (Standard)
                │ │        │                     ;       ││││└───►Bit 2: RS-232: TXD Ausgang, Userport: Daten PA 2 (Pin M)
                │ │        │                     ;       │││││     Bit 3..5: Serielle Schnittstelle Ausgang (0=High/Inactive, 1=Low/Active)
                │ │        │                     ;       ││││└──────►Bit 3: ATN OUT
                │ │        │                     ;       │││└───────►Bit 4: CLOCK OUT
                │ │        │                     ;       ││└────────►Bit 5: DATA OUT
                │ │        │                     ;       ││        Bit 6..7: Serielle Schnittstelle Eingang (0=Low/Active, 1=High/Inactive)
                │ │        │                     ;       │└─────────►Bit 6: CLOCK IN
                │ │        │                     ;       └──────────►Bit 7: DATA IN 
$604B: A5 02    │ │        │    LDA a02
$604D: A5 0F    │ │        │    LDA a0F          ;$07 = %00000111
$604F: 8D 00 DD │ │        │    STA $DD00        ;CIA2: Daten Port A
                │ │        │                     ;$07 = %00000111
                │ │        │                     ;       ││││││││  Bit 0..1: Auswahl der Position des VIC-Speichers
                │ │        │                     ;       ││││││││    %00, 0: Bank 3: $C000-$FFFF, 49152-65535
                │ │        │                     ;       ││││││││    %01, 1: Bank 2: $8000-$BFFF, 32768-49151
                │ │        │                     ;       ││││││││    %10, 2: Bank 1: $4000-$7FFF, 16384-32767
                │ │        │                     ;       ││││││└└───►%11, 3: Bank 0: $0000-$3FFF, 0-16383 (Standard)
                │ │        │                     ;       │││││└───►Bit 2: RS-232: TXD Ausgang, Userport: Daten PA 2 (Pin M)
                │ │        │                     ;       │││││     Bit 3..5: Serielle Schnittstelle Ausgang (0=High/Inactive, 1=Low/Active)
                │ │        │                     ;       ││││└──────►Bit 3: ATN OUT
                │ │        │                     ;       │││└───────►Bit 4: CLOCK OUT
                │ │        │                     ;       ││└────────►Bit 5: DATA OUT
                │ │        │                     ;       ││        Bit 6..7: Serielle Schnittstelle Eingang (0=Low/Active, 1=High/Inactive)
                │ │        │                     ;       │└─────────►Bit 6: CLOCK IN
                │ │        │                     ;       └──────────►Bit 7: DATA IN 
$6052: C6 0E    │ │        │    DEC a0E
$6054: EA       │ │        │    NOP 
$6055: EA       │ │        │    NOP 
$6056: EA       │ │        │    NOP 
$6057: AD 00 DD │ │        │    LDA $DD00        ;CIA2: Daten Port A
$605A: 4A       │ │        │    LSR              ;die acht Bit des Akkumulators werden um eine Stelle nach rechts verschoben
$605B: 4A       │ │        │    LSR 
$605C: EA       │ │        │    NOP 
$605D: 0D 00 DD │ │        │    ORA $DD00        ;CIA2: Daten Port A
                │ │        │                     ;bitweise ODER-Verknüpfung mit dem Akkumulator und der Speicheradresse $hhll
                │ │        │                     ;Das Ergebnis wird im Akkumulator gespeichert.
$6060: 4A       │ │        │    LSR 
$6061: 4A       │ │        │    LSR 
$6062: 4A       │ │        │    LSR 
$6063: 4A       │ │        │    LSR 
$6064: AC 00 DD │ │        │    LDY $DD00        ;CIA2: Daten Port A
$6067: AA       │ │        │    TAX              ;kopiert den Inhalt des Akkumulators in das X-Register
$6068: 98       │ │        │    TYA       ┌──────────────────────────────────────────────────────┘ ;kopiert das Y-Register in den Akkumulator
$6069: 4A       │ │        │    LSR       │
$606A: 4A       │ │        │    LSR       │
$606B: 0D 00 DD │ │        │    ORA $DD00 │      ;CIA2: Daten Port A
                │ │        │              │      ;bitweise ODER-Verknüpfung mit dem Akkumulator und der Speicheradresse $hhll
                │ │        │              │      ;Das Ergebnis wird im Akkumulator gespeichert.
$606E: 29 F0    │ │        │    AND #$F0  ▼ 
$6070: 1D 16 60 │ │        │    ORA f6016,X      ;bitweise ODER-Verknüpfung mit dem Akkumulator und der Speicheradresse ($hhll+X)
                │ │        │                     ;Das Ergebnis wird im Akkumulator gespeichert.
$6073: A4 0E    │ │        │    LDY a0E          ;lädt das Y-Register mit dem Inhalt der Zeropage-Adresse $0E und beeinflussen das Zero-Flag 
$6075: 91 02    │ │        │    STA (p02),Y
$6077: D0 C1    │ │        └────BNE b603A        ;verzweigt zur Adresse $603A, wenn das  Ergebnis der letzten Operation ungleich $00 ist (wenn Zero-Flag = 0 ist)
$6079: EA       │ │ s6079    ┌─►NOP 
$607A: A2 17    │ │          │  LDX #$17         ;$17 = %00010111
$607C: 8E 00 DD │ │          │  STX $DD00        ;CIA2: Daten Port A
                │ │          │                   ;$17 = %00010111
                │ │          │                   ;       ││││││  Bit 0..1: Auswahl der Position des VIC-Speichers
                │ │          │                   ;       ││││││    %00, 0: Bank 3: $C000-$FFFF, 49152-65535
                │ │          │                   ;       ││││││    %01, 1: Bank 2: $8000-$BFFF, 32768-49151
                │ │          │                   ;       ││││││    %10, 2: Bank 1: $4000-$7FFF, 16384-32767
                │ │          │                   ;       ││││└└───►%11, 3: Bank 0: $0000-$3FFF, 0-16383 (Standard)
                │ │          │                   ;       │││└───►Bit 2: RS-232: TXD Ausgang, Userport: Daten PA 2 (Pin M)
                │ │          │                   ;       ││││     Bit 3..5: Serielle Schnittstelle Ausgang (0=High/Inactive, 1=Low/Active)
                │ │          │                   ;       │││└──────►Bit 3: ATN OUT
                │ │          │                   ;       │││└───────►Bit 4: CLOCK OUT
                │ │          │                   ;       ││└────────►Bit 5: DATA OUT
                │ │          │                   ;       ││        Bit 6..7: Serielle Schnittstelle Eingang (0=Low/Active, 1=High/Inactive)
                │ │          │                   ;       │└─────────►Bit 6: CLOCK IN
                │ │          │                   ;       └──────────►Bit 7: DATA IN 
$607F: 60       │ │          │  RTS
.               │ │          │
.               │ │          │
.               │ │          │
$6194: 20 AE FF │ │          │  JSR ROM_UNLSN    ;$FFAE - UNLSN: Senden des UNLISTEN-Befehls für seriellen Bus zur Beendigung der Datenübertragung  
$6197: 78       │ │          │  SEI 
$6198: A0 21    │ │          │  LDY #$21
$619A: 88       │ │ b619A    │┌►DEY 
$619B: D0 FD    │ │          │└─BNE b619A
$619D: 20 79 60 │ │          └──JSR s6079
$61A0: 2C 00 DD │ │ b61A0     ┌►BIT $DD00        ;CIA2: Daten Port A
$61A3: 30 FB    │ │           └─BMI b61A0
$61A5: A9 90    │ │             LDA #>p9000
$61A7: 85 05    │ │             STA a05
$61A9: A9 00    │ │             LDA #<p9000
$61AB: 85 04    │ │             STA a04
$61AD: 20 04 62 │ │      ┌──────JSR s6204
$61B0: AD 12 D0 │ │      │      LDA $D012        ;Lesen: Aktuelle Rasterzeile
$61B3: 8D FE 02 │ │      │      STA a02FE
$61B6: A9 50    │ │      │      LDA #>p5000
$61B8: 85 05    │ │      │      STA a05
$61BA: A9 00    │ │      │      LDA #<p5000
$61BC: 85 04    │ │      │      STA a04
$61BE: 20 04 62 │ │      │ ┌────JSR s6204
$61C1: A9 BF    │ │      │ │    LDA #>pBF40
$61C3: 85 05    │ │      │ │    STA a05
$61C5: A9 40    │ │      │ │    LDA #<pBF40
$61C7: 85 04    │ │      │ │    STA a04
$61C9: 20 04 62 │ │      │ │ ┌──JSR s6204
$61CC: A5 05    │ │      │ │ │  LDA a05
$61CE: C9 BF    │ │      │ │ │  CMP #$BF         ;vergleicht den Akkumulator mit dem konstanten Wert $BF
$61D0: D0 03    │ │      │ │ │┌─BNE b61D5        ;verzweigt, wenn der Akkumulator <> $BF
$61D2: 4C E2 FC │ │      │ │ ││ JMP RESET_VECTOR ;Kopierschutzprüfung nicht bestanden! 
.               │ │      │ │ │└►                 ;Kopierschutzprüfung bestanden! 
.               │ │      │ │ │
.               │ │      │ │ │
$6204: A9 64    │ │ s6204└►└►└─►LDA #>p64A8      ;Der Speicher direkt nach dem Programm "GEOS BOOT" wird als Puffer verwendet.
$6206: 85 03    │ │             STA a03
$6208: A9 A8    │ │             LDA #<p64A8
$620A: 85 02    │ │             STA a02
$620C: A0 01    │ │ b620C  ┌►┌─►LDY #$01
$620E: 20 26 60 │ └────────│─│──JSR s6026
$6211: A8       │          │ │  TAY              ;kopiert den Inhalt des Akkumulators in das Y-Register
$6212: F0 23    │        ┌─│─│──BEQ b6237        ;verzweigt zur Adresse $6237, wenn das  Ergebnis der letzten Operation gleich $00 ist, was mit Zero-Flag = 1 angezeigt wird
$6214: 48       │        │ │ │  PHA              ;legt den Inhalt des Akkumulators auf dem Stapel ab. Danach wird der Stapelzeiger um 1 verringert.
$6215: 20 26 60 └────────│─│─│──JSR s6026
$6218: 68                │ │ │  PLA              ;erhöht den Stapelzeiger um 1 und danach wird der Akkumulator mit dem Inhalt der Speicherzelle, auf die der Stapelzeiger zeigt, geladen
$6219: 48                │ │ │  PHA              ;legt den Inhalt des Akkumulators auf dem Stapel ab. Danach wird der Stapelzeiger um 1 verringert.
$621A: A8                │ │ │  TAY              ;kopiert den Inhalt des Akkumulators in das Y-Register
$621B: A9 30             │ │ │  LDA #$30
$621D: 85 01             │ │ │  STA a01
$621F: 88           b621F│ │ │┌►DEY
$6220: B1 02             │ │ ││ LDA (p02),Y
$6222: 91 04             │ │ ││ STA (p04),Y
$6224: 98                │ │ ││ TYA              ;kopiert das Y-Register in den Akkumulator
$6225: D0 F8             │ │ │└─BNE b621F
$6227: A9 36             │ │ │  LDA #$36
$6229: 85 01             │ │ │  STA a01
$622B: 68                │ │ │  PLA              ;erhöht den Stapelzeiger um 1 und danach wird der Akkumulator mit dem Inhalt der Speicherzelle, auf die der Stapelzeiger zeigt, geladen
$622C: 18                │ │ │  CLC              ;löscht das Carry-Flag
$622D: 65 04             │ │ │  ADC a04          ;addiert zum Inhalt des Akkumulators den Inhalt der Zeropage-Adresse $04
$622F: 85 04             │ │ │  STA a04
$6231: 90 D9             │ │ └──BCC b620C        ;verzweigt zur Adresse $620C, wenn das Carry-Flag = 0 ist
$6233: E6 05             │ │    INC a05          ;erhöht den Inhalt der Zeropage-Adresse $05 um 1
$6235: D0 D5             │ └────BNE b620C        ;verzweigt zur Adresse $620C, wenn das  Ergebnis der letzten Operation ungleich $00 ist, was mit Zero-Flag = 0 angezeigt wird
$6237: 60           b6237└─────►RTS

Legende:
   Vorbereitungen für das Empfangen der Daten von dem Diskettenlaufwerk
   Sektorkette 1/Datensatz 1 wird nach $9000 geladen
   eine Zufallszahl (aktuelle Rasterzeile) ermitteln und in $02FE speichern
   Sektorkette 2/Datensatz 3 wird nach $5000 geladen
   Sektorkette 3/Datensatz 2 wird nach $BF40 geladen
   Prüfung, ob die Kopierschutzprüfung (I) im Diskettenlaufwerk bestanden wurde
Beispiel - Empfangen von Daten von der Schnellladeroutine[Bearbeiten | Quelltext bearbeiten]

In diesem Abschnitt soll der Empfangen von einem Byte (in diesem Fall der Wert $FE) von der Schnellladeroutine (Stufe 1) behandelt werden. In dem folgendem Beispiel ist der Bereich des Programmcode von Adresse $6057 bis $6077 dargestellt, welcher die Daten von der Schnelladerroutine in Empfang nehmen soll. Zu jeder Programmzeile ist der Inhalt des Akkumulators, des X- und des Y-Registers angegeben.

                               ;A:07 X:17 Y:01
$6057: AD 00 DD   LDA $DD00    ;A:07 X:17 Y:01 $07=%00000111 Daten Port A wird gelesen das Bit 7=0 und das Bit 6=0
$605A: 4A         LSR          ;A:03 X:17 Y:01 $03=%00000011 Die gelesen Bit 7 und 6 werden um eine Stelle nach rechts verschoben 
$605B: 4A         LSR          ;A:01 X:17 Y:01 $01=%00000001 Die gelesen Bit 7 und 6 werden um eine Stelle nach rechts verschoben, damit sind die Bit 7 und 6 wieder frei
$605C: EA         NOP          ;A:01 X:17 Y:01 
$605D: 0D 00 DD   ORA $DD00    ;A:87 X:17 Y:01 $87=%10000111 Daten Port A wird gelesen das Bit 7=1 und das Bit 6=0
                               ;                             Die Bit 5 (DATA OUT) und 4 (CLOCK OUT) dürfen im Daten Port A nicht gesetzt sein,
                               ;                             da sonst die 2 bereits übertragen Bit beeinflusst werden 
$6060: 4A         LSR          ;A:43 X:17 Y:01 $43=%01000011 Die gelesenen Bit 7 und 6 und die zu vorgelesenen Bit werden um eine Stelle nach rechts verschoben
$6061: 4A         LSR          ;A:21 X:17 Y:01 $21=%00100001 Die gelesenen Bit 7 und 6 und die zu vorgelesenen Bit werden um eine Stelle nach rechts verschoben
$6062: 4A         LSR          ;A:10 X:17 Y:01 $10=%00010000 Die gelesenen Bit 7 und 6 und die zu vorgelesenen Bit werden um eine Stelle nach rechts verschoben
$6063: 4A         LSR          ;A:08 X:17 Y:01 $08=%00001000 Die gelesenen Bit 7 und 6 und die zu vorgelesenen Bit werden um eine Stelle nach rechts verschoben
                               ;                             jetzt befinden sich die gelesenen 4 Bit an den an den Bit Positionen 3,2,1 und 0 und die Bit 7,6,5 und 4 sind Null
                               ;                             Die gelesenen 4 Bit entsprechen aber nicht direkt den unteren 4 Bit des zu empfangenen Byte!
                               ;                             Die gelesenen 4 Bit bestimmen nur die Position in der Wertetabelle ab der Adresse $6016.
                               ;                             Aus dieser Wertetabelle werden dann erst die richtigen 4 Bit des zu lesenden Byte ermittelt. 
$6064: AC 00 DD   LDY $DD00    ;A:08 X:17 Y:C7 $C7=%11000111 Daten Port A wird gelesen das Bit 7=1 und das Bit 6=1, diesmal wird der Wert in das Y-Register geschrieben
$6067: AA         TAX          ;A:08 X:08 Y:C7               Die zuerst gelesenen 4 Bit, welche sich noch im Akkumulator befinden, werden in das X-Register übertragen
$6068: 98         TYA          ;A:C7 X:08 Y:C7               Der Wert des Y-Registern, welcher die gerade gelesenen 2 Bit enthält, wird in den Akkumulator übertragen.
$6069: 4A         LSR          ;A:63 X:08 Y:C7 $63=%01100001 Die gelesen Bit 7 und 6 werden um eine Stelle nach rechts verschoben
$606A: 4A         LSR          ;A:31 X:08 Y:C7 $31=%00110001 Die gelesen Bit 7 und 6 werden um eine Stelle nach rechts verschoben
$606B: 0D 00 DD   ORA $DD00    ;A:F7 X:08 Y:C7 $F7=%11110111 Daten Port A wird gelesen das Bit 7=1 und das Bit 6=1
                               ;                             Die Bit 5 (DATA OUT) und 4 (CLOCK OUT) dürfen im Daten Port A nicht gesetzt sein,
                               ;                             da sonst die 2 bereits übertragen Bit beeinflusst werden 
$606E: 29 F0      AND #$F0     ;A:F0 X:08 Y:C7 $F7=%11110111 Durch das AND mit $F0 werden die Bit 3,2,1 und 0 auf Null gesetzt, die gelesenen Bit 7,6,5 und 4 bleiben erhalten
                               ;           AND $F0=%11110000
                               ;               -------------
                               ;             = $F0=%11110000
$6070: 1D 16 60   ORA f6016,X  ;A:FE X:08 Y:C7               Durch das ORA werden die Bit 3,2,1 und 0 des zu übertragenen Bytes aus der Wertetabelle
                               ;                             mit den zuletzt gelesen 4 Bit, welche sich schon an den Bit-Position 7,6,5 und 4 befinden, zusammengefügt.
                               ;                             Dabei bestimmen die zuerst übertragenen 4 Bit, welchen in diesem Fall den Wert $08 erben und sich momentan
                               ;                             im X-Register befinden, die Position in der Wertetabelle ab der Adresse $6016.        
                               ;                             In der Wertetabelle an der Position $6016+$08(entspricht %00001000)=$601E befindet sich
                               ;                             der Wert $0E (entspricht %00001110).
                               ;               $F0=%11110000
                               ;           ORA $0E=%00001110
                               ;               -------------
                               ;             = $FE=%11111110 Das empfangene Byte $FE steht nun endgültig im Akkumulator.                                    
$6073: A4 0E      LDY a0E      ;A:FE X:08 Y:00
$6075: 91 02      STA (p02),Y  ;A:FE X:08 Y:00               Speichern des empfangen Byte $FE im Pufferspeicher
$6077: D0 C1      BNE b603A    ;                             Schleifende
┌Wertetabelle──────────────────────────────────────────┐ 
│$6016:           .BYTE $0F,$07,$0D,$05,$0B,$03,$09,$01│
│$601E:           .BYTE $0E,$06,$0C,$04,$0A,$02,$08,$00│
└──────────────────────────────────────────────────────┘
Bereich von $61D5 bis $61F9[Bearbeiten | Quelltext bearbeiten]

Wenn der Programmcode dieses Bereiches ausgeführt wird, muss die Kopierschutzprüfung (I) bestanden worden sein. In diesem Bereich werden nur noch die offenen Floppy-Kanäle geschlossen und es erfolgt der Start des GEOS KERNAL.

$61D5: AD 12 D0    b61D5 ┌►LDA $D012      ;Lesen: Aktuelle Rasterzeile
$61D8: F0 FB             └─BEQ b61D5
$61DA: 8D FF 02            STA a02FF
$61DD: A5 0F               LDA a0F        ;$07 = %00000111
$61DF: 8D 00 DD            STA $DD00      ;CIA2: Daten Port A 
                                          ;Bit 0..1: Auswahl der Position des VIC-Speichers %11, 3: Bank 0: $0000-$3FFF, 0-16383 (Standard)
                                          ;Bit 2: RS-232: TXD Ausgang, Userport: Daten PA 2 (Pin M))
$61E2: A9 7F               LDA #$7F
$61E4: 8D 0D DD            STA $DD0D      ;CIA2: Interrupt Control und Status ; Turn off CIAs Timer interrupts ($7f = %01111111)
$61E7: AD 0D DD            LDA $DD0D      ;CIA2: Interrupt Control und Status ; by reading $dd0d we cancel all CIA-IRQs in queue/unprocessed
$61EA: A5 BA               LDA aBA        ;aktuelle Gerätenummer
$61EC: 20 B1 FF            JSR ROM_LISTEN ;$FFB1 - LISTEN: Befehl LISTEN für Geräte am seriellen Bus (Start Datenempfang bei Peripheriegeräten)
$61EF: A9 EF               LDA #$EF
$61F1: 20 93 FF            JSR ROM_SECOND ;$FF93 - SECOND: Übertragung der Sekundäradresse nach LISTEN-Befehl  
$61F4: 20 AE FF            JSR ROM_UNLSN  ;$FFAE - UNLSN: Senden des UNLISTEN-Befehls für seriellen Bus zur Beendigung der Datenübertragung
$61F7: 4C 03 C0            JMP eC003

Legende:
   Es wird eine weitere Zufallszahl (aktuelle Rasterzeile) ermittelt und in $02FF geschrieben.
   Einige offene Floppy-Kanäle werden geschlossen.
   Der GEOS Kernal wird gestartet durch einen Sprung zur Adresse $C003, an welcher sich ein Sprung zur Adresse $5000 befindet.
Alle Bereiche im Überblick ($6000 bis $64A7)[Bearbeiten | Quelltext bearbeiten]

Wenn alle Bereiche des Programms "GEOS BOOT" betrachtet werden, fällt ganz deutlich auf, dass der Programmcode der Schnellladeroutine (Stufe 1), welcher die Kopierschutzprüfung (I) enthält, sehr gut verschleiert wurde. Zum einen ist ein Teil (und nur ein Teil) des Programmcodes der Schnellladeroutine (Stufe 1) kodiert. Zum anderen ist der Programmcode der Schnellladeroutine (Stufe 1) in 32-Byte-Blöcken rückwärts im Speicher des Rechners abgelegt und wird erst bei der Übertragung zum Diskettenlaufwerk in die richtige Byte-Reihenfolge gebracht.

┌──────────────────────────────────────────────────────────────────────────────────────┐
│$6000                                                                                 │
│        JMP j60A7                                                                     │ 
│$6002                                                                                 │ 
└──────────────────────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────────────────────┐
│$6003                                                                                 │
│        Bildschirmcodes "GEOS BOOTET ..."                                             │
│$6012                                                                                 │
└──────────────────────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────────────────────┐
│$6013                                                                                 │
│        3 NULL-Bytes                                                                  │
│$6015                                                                                 │
└──────────────────────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────────────────────┐
│$6016                                                                                 │
│        Daten von der Schnellladeroutine (Stufe 1) empfangen                          │
│$607F                                                                                 │
└──────────────────────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────────────────────┐
│$6080                                                                                 │
│        Prozessorstapel manipulieren                                                  │
│        Byte-Ausgabe (serieller Bus) immer genau 5 Byte                               │
│$60A1                                                                                 │
└──────────────────────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────────────────────┐
│$60A2                                                                                 │
│        TEXT "I:0  "                                                                  │
│$60A6                                                                                 │
└──────────────────────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────────────────────┐
│$60A7                                                                                 │
│        C-64 KERNAL System und nicht-maskierbare Interrupt Vektoren initialisieren    │
│        Bildschirmspeicher leeren                                                     │
│        Alle Sprites abschalten                                                       │
│        Den Text "GEOS BOOTET ..." direkt in den Bildschirmspeicher schreiben         │
│        Farbspeicher füllen                                                           │
│$60E8                                                                                 │
└──────────────────────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────────────────────┐
│$60EA                                                                                 │
│        ???                                                                           │
│$6128                                                                                 │
└──────────────────────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────────────────────┐
│$6129                                                                                 │
│        den TEXT "I:0  " an das Laufwerk senden                                       │
│        die Dekodier-Routine mittels RTS über den manipulieren Prozessorstapel rufen  │
│$613F                                                                                 │
└──────────────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────┐┌───────────────────────────────────────────────────────────┐
│$613F                    ││$613F                                                      │
│        kodierte Daten   ││        Schnellladerroutine ans Diskettenlaufwerk senden   │
│                         ││        Schnellladerroutine im Diskettenlaufwerk starten   │
│                         ││$6193                                                      │
│                         │└───────────────────────────────────────────────────────────┘
│                         │┌───────────────────────────────────────────────────────────┐
│                         ││$6194                                                      │
│                         ││        Vorbereitungen für das Empfangen der Daten         │
│                         ││        Sektorkette 1/Datensatz 1 wird nach $9000 geladen  │
│                         ││        Es wird eine Zufallszahl ermittelt                 │
│                         ││        Sektorkette 2/Datensatz 3 wird nach $5000 geladen  │
│                         ││        Sektorkette 3/Datensatz 2 wird nach $BF40 geladen  │
│                         ││        Prüfung der Kopierschutzprüfung (I)                │
│                         ││$61D4                                                      │ 
│                         │└───────────────────────────────────────────────────────────┘
│                         │┌───────────────────────────────────────────────────────────┐
│                         ││$61D5                                                      │
│                         ││       es wird eine weitere Zufallszahl ermittelt          │
│                         ││       offene Floppy-Kanäle werden geschlossen             │
│                         ││       GEOS Kernal wird gestartet                          │
│                         ││$61F9                                                      │ 
│                         │└───────────────────────────────────────────────────────────┘
│                         │┌───────────────────────────────────────────────────────────┐
│                         ││$61FA                                                      │
│                         ││        TEXT "M-E" & TEXT "M-W"                            │
│                         ││$6203                                                      │
│                         │└───────────────────────────────────────────────────────────┘
│                         │┌───────────────────────────────────────────────────────────┐
│                         ││$6204                                                      │
│                         ││        empfangene Daten an die Zieladresse kopieren       │
│                         ││$6237                                                      │
│                         │└───────────────────────────────────────────────────────────┘
│                         │┌───────────────────────────────────────────────────────────┐
│                         ││$6238                                                      │ 
│$643E                    ││        Programmcode für das Diskettenlaufwerk             │
│                         ││        in 32 Byte Blöcken rückwärts gespeichert,          │
└─────────────────────────┘│        welcher die Kopierschutzprüfung (I) enthält        │
┌──────────────────────────┘                                                           │  
│$6477                                                                                 │
└──────────────────────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────────────────────┐
│$6478                                                                                 │
│        10 NULL-Bytes                                                                 │
│$6481                                                                                 │
└──────────────────────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────────────────────┐
│$6482                                                                                 │
│        Dekodier-Routine                                                              │
│$64A1                                                                                 │
└──────────────────────────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────────────────────────┐
│$64A2                                                                                 │
│        Interrupt Routine                                                             │
│$64A7                                                                                 │
└──────────────────────────────────────────────────────────────────────────────────────┘
Die Schnellladeroutine (Stufe 1)[Bearbeiten | Quelltext bearbeiten]

Diese Schnellladeroutine (Stufe 1) lädt und überträgt nacheinander 3 Ketten von Sektoren an den Rechner. Der jeweilige Start-Sektor ist fest im Programm vorgegeben (hart kodiert). Die 1. Kette beginnt mit dem Sektor 13 auf Spur 19, die 2. Kette beginnt mit Sektor 15 auf Spur 20 und die 3. Kette beginnt mit Sektor 17 auf Spur 20. Die Sektoren der 1. Kette sind dabei nicht kodiert gespeichert worden. Die Sektoren der 2. und 3. Kette sind kodiert auf der Diskette abgelegt worden und werden nach dem Einlesen dekodiert. Zum Dekodieren wird nicht ein fester Wert sondern ein Teil des Programmcodes wird zum Dekodieren verwendet. Der Bereich von $042A bis $0527 wird für die Dekodierung benutzt, was Änderungen an diesem Programmcode verhindern soll. In diesem Bereich befindet sich natürlich auch die Kopierschutzprüfung (I). Der letzte Sektor, welcher durch die Schnellladeroutine (Stufe 1) geladen wird, ist der Sektor 12 von Spur 29. Dieser Sektor befindet sich nach dem Beenden der Schnellladeroutine (Stufe 1) noch im Datenpuffer des Diskettenlaufwerks ab der Adresse $0600.

Sektorkette Sektoren (Spur.Sektor) Anzahl der Sektoren Byte wird geladen nach Kodiert Datensatz in der Datei GEOS KERNAL
Sektorkette 1 19.13, 19.02, 19.14, 19.03, 19.16, 19.05, 19.18, 19.06, 20.14, 20.03, 20.11, 20.00, 20.08, 20.16, 20.05, 20.13, 20.02 17 16 (komplette Sektoren) * 254 Byte + 32 Byte (vom letzten Sektor) = 4096 Byte $9000-$9FFF NEIN 1
Sektorkette 2 20.15, 20.04, 20.12, 21.14, 21.03, 21.11 6 5 (komplette Sektoren) * 254 Byte + 201 Byte (vom letzten Sektor) = 1471 Byte $5000-$55BE JA 3
Sektorkette 3 20.17, 21.15, 21.04, 21.12, 21.01, 21.09, 21.17, 21.06, 21.16, 21.05, 21.13, 21.02, 21.10, 21.18, 21.07, 21.00, 21.08, 22.14, 22.03, 22.11, 22.00, 22.08, 22.16, 22.05, 22.13, 22.02, 22.10, 22.18, 22.07, 22.15, 22.04, 22.12, 22.01, 22.09, 22.17, 22.06, 23.14, 23.03, 23.11, 23.00, 23.08, 23.16, 23.05, 23.13, 23.02, 23.10, 23.18, 23.07, 23.15, 23.04, 23.12, 23.01, 23.09, 23.17, 23.06, 24.14, 24.03, 24.11, 24.00, 24.08, 26.16, 29.00, 29.07, 29.15, 29.05, 29.12 66 65 (komplette Sektoren) * 254 Byte + 60 Byte (vom letzten Sektor) = 16570 Byte $BF40-$FFF9 JA 2

Der Sektor 12 von Spur 29 enthält nach den eigentlichen Daten noch weiter Daten, welche nicht zum Speicher des Rechners übertragen werden. In diesen zusätzlichen Daten befindet sich die Kopierschutzprüfung (II), welche unbemerkt, durch das Laden des letzten Sektors, in den Speicher des Diskettenlaufwerks gelangt. Das DOS des Diskettenlaufwerks lädt immer ganze Sektoren in den Speicher des Diskettenlaufwerks, auch wenn diese nur zum Teil gefüllt sind.

Spur 29 Sektor 12
   00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00 00 3D FF 91 EA E7 55 06 6D F2 71 48 BA 8E 8A 2B
10 2F ED C1 BA A0 50 DD C1 6B C5 10 1D 48 2E 09 7D
20 01 68 A4 40 E8 D5 63 F6 20 D0 C3 EE FF AD 60 BD
30 87 10 49 FD DF E4 04 E9 44 EC 80 98 F0 FB 35 FB
40 88 D0 FA 84 3E A9 FF 4C 4E 06 00 00 00 00 85 48
50 A9 EE 8D 0C 1C A2 32 CA F0 62 2C 00 1C 30 FB AD
60 01 1C B8 A0 00 50 FE B8 AD 01 1C D9 D5 06 D0 E7
70 C8 C0 08 D0 F0 A0 02 20 98 06 A2 13 D0 12 A0 00
80 20 98 06 A0 45 20 98 06 20 A7 06 A0 0A 20 98 06
90 20 A7 06 CA D0 E8 F0 29 50 FE B8 AD 01 1C 88 D0
A0 F7 60 AD 01 1C B8 60 AC 00 1C 10 F6 50 F9 B8 AD
B0 01 1C C9 55 F0 F1 C9 67 F0 ED 68 68 A9 FE 8D 39
C0 04 A9 60 8D 50 06 A2 79 A0 00 59 51 06 99 51 06
D0 C8 CA D0 F6 60 52 57 35 29 6F 76 9C D5 00 03 00
E0 00 80 00 00 00 00 6B 55 00 00 00 00 00 00 00 00
F0 00 00 00 00 00 00 3C 03 00 00 00 00 00 00 08 00

Legende:
   Ein $00-Byte kennzeichnet den letzten
   Sektor in der Sektorkette.
   Position des letzten Datenbyte als 
   Offset vom Beginn des Sektors, d.h.
   der Wert $FB an Position $3D ist das
   letzte Datenbyte.
   Datenbyte
   Normalerweise Datenmüll, welcher niemals
   an den Rechner übertragen wird, da die
   Datei an Position $3D endet.
$0300:          f0300             .BYTE $0F,$07,$0D,$05,$0B,$03,$09,$01 ;Übertragungstabelle für oberes Nibble
$0308:                            .BYTE $0E,$06,$0C,$04,$0A,$02,$08     ;
$030F:          f030F             .BYTE $00,$20,$40,$60                 ;Dichte-Tabelle, überlappt mit der Nibble-Tabelle
                                                                        ;Warten, bis CLOCK gesetzt ist, CLOCK/DATA gesetzt ist
$0313: A9 04    b0313           ┌►LDA #$04     ◄┐◄┐          ◄┐         ; Werte maskieren
$0315: 2C 00 18                 BIT a1800                       ; Bus überprüfen
$0318: D0 F9                    BNE b0313                       ; verzweigen bis CLOCK gesetzt ist 
$031A: A9 00                      LDA #$00                        ; setze CLOCK/DATA
$031C: 8D 00 18                   STA a1800                       ;
$031F: 60                         RTS                             ;
                                                                  ;Suchauftrag ausführen (wird von $03d0 aufgerufen)
$0320: A9 EE    s0320             LDA #$EE   ◄┐                   ;
$0322: 8D 0C 1C                   STA a1C0C                     ; Lesemodus, Ready-Byte aktivieren
$0325: A9 30                      LDA #$30                      ; Suchauftragscode maskieren
$0327: D0 0B                  ┌   BNE b0334                     ; (Springe immer)
$0329: 20 58 03 s0329       │   JSR s0358        ◄┐           ; Sektor suchen und lesen (0528/29)
$032C: A6 00                │   LDX a00                     ; überprüfen, ob erfolgreich
$032E: CA                   │   DEX                         ;
$032F: F0 01                │ ┌ BEQ b0332                   ; wenn ja, Leseauftrag ausführen
$0331: 60                   │ │ RTS                         ;
                            │ │                             ;Auftragsvorverarbeitung
$0332: A9 00    b0332       │ └►LDA #$00                    ; Leseauftragscode maskieren
$0334: 85 45    b0334       └►  STA a45                     ; maskierten Auftragscode setzen
$0336: A9 05                    LDA #>p0528                 ; verwenden von 0528/29 als aktuelle Auftrags t/s Adressen
$0338: 85 33                    STA a33                     ;
$033A: A9 28                    LDA #<p0528                 ;
$033C: 85 32                    STA a32                     ;
$033E: A9 06                    LDA #$06                    ; Setzen Sie den aktuellen Puffer auf 0600
$0340: 85 31                    STA a31                     ;
$0342: BA                       TSX                         ;
$0343: 86 49                    STX a49                     ; den aktuellen Stapelzeiger merken
$0345: A2 01                    LDX #$01                    ;
$0347: 86 00                    STX a00                     ; den Auftragscode 0 setzten, als "ok" Ergebnis
$0349: CA                       DEX                         ;
$034A: 86 3F                    STX a3F                     ; Controller auf Puffer 0 setzen
$034C: A5 45                    LDA a45                     ; prüfen, ob der maskierte Auftragscode LESEN ist
$034E: C9 30                    CMP #$30                    ;
$0350: F0 03                  ┌ BEQ b0355                   ;
$0352: 4C CA F4               │ JMP eF4CA                   ; weiter im ROM-Auftragscode-Handler
                                             ;
$0355: 4C B1 F3 b0355         └►JMP eF3B1                   ; Sektor suchen
                                                            ;Suchen der Spur in $0528
$0358: A6 22    s0358       └►    LDX a22          ◄┐         ; aktuelle Spur
$035A: F0 05                    ┌ BEQ b0361                 ; auf Gültigkeit prüfen
$035C: A6 00                    │ LDX a00                   ; Auftragscode Ergebnis überprüfen
$035E: CA                       │ DEX                       ;
$035F: F0 08                  ┌ │ BEQ b0369                 ;
$0361: 20 BA 03 b0361   ┌     │ └►JSR s03BA                 ; Fehlerbehebung versuchen
$0364: A6 00            │     │   LDX a00                   ; überprüfen, ob erfolgreich
$0366: CA               │     │   DEX                       ;
$0367: D0 22            │ ┌   │   BNE b038B                 ; springen, wenn nicht
$0369: A5 22    b0369   │ │   └►  LDA a22                   ; kein Fehler - aktuelle Spur lesen
$036B: A2 FF            │ │       LDX #$FF                  ;
$036D: 38               │ │       SEC                       ;
$036E: ED 28 05         │ │       SBC p0528                 ; prüfen, ob sie mit der angeforderten Spur übereinstimmt
$0371: F0 13            │ │ ┌     BEQ b0386                 ; zurückkehren, wenn ok
$0373: B0 06            │ │ │   ┌ BCS b037B                 ; springen, wenn aktuelle Spur > angeforderter Spur
$0375: 49 FF            │ │ │   │ EOR #$FF                  ; Differenz negieren
$0377: 69 01            │ │ │   │ ADC #$01                  ; 
$0379: A2 01            │ │ │   │ LDX #$01                  ; 
$037B: 20 8C 03 b037B   │ │ │ └►JSR s038C                 ; suchen der gewünschten Spur
$037E: AD 28 05         │ │ │   LDA p0528                 ; annehmen, dass es funktionierte
$0381: 85 22            │ │ │   STA a22                   ; 
$0383: 20 EE 03       │ │ │   JSR s03EE                 ; aktualisieren Sektoren in Spur und Dichte
$0386: A9 EE    b0386 │ │ └►  LDA #$EE                  ; Kopf in den Lesemodus versetzen, Ready Byte aktiviert
$0388: 8D 0C 1C       │ │     STA a1C0C                 ; 
$038B: 60       b038B │ └►    RTS                       ; 
                                                  ;Kopf in Richtung X bewegen (X=$ff:hoch? X=$01:runter?)
$038C: 86 4A    s038C ┌►┌►└►  STX a4A                   ; Schrittzähler für Kopftransport setzen
$038E: 0A                 ASL                       ; Umwandlung der Spurenanzahl in die Schrittanzahl
$038F: A8                 TAY                       ; 
$0390: AD 00 1C           LDA a1C00                 ; HW-Steuerungsport lesen
$0393: 29 FE              AND #$FE                  ; STP1 maskieren
$0395: 85 70              STA a70                   ; temporär speichern
$0397: A5 70    b0397 ┌►  LDA a70                   ; lesen des maskierten Portwertes
$0399: 18             │   CLC                       ; 
$039A: 65 4A          │   ADC a4A                   ; Richtung hinzuaddieren ($ff oder $01)
$039C: 45 70          │   EOR a70                   ; neue Schrittbits berechnen
$039E: 29 03          │   AND #$03                  ; 
$03A0: 45 70          │   EOR a70                   ; 
$03A2: 85 70          │   STA a70                   ; 
$03A4: 8D 00 1C       │   STA a1C00                 ; Kopf bewegen
$03A7: A9 1E          │   LDA #$1E                  ; konstante Verzögerung
$03A9: 20 B1 03       │ ┌ JSR s03B1                 ; 
$03AC: 88             │ │ DEY                       ; dekrementieren des Halben-Spur Zählers
$03AD: D0 E8          └ │ BNE b0397                 ; weiter Schritte ausführen, wenn erforderlich
$03AF: A9 4B            │ LDA #$4B                  ; Abschlussverzögerung
$03B1: 8D 05 18 s03B1 ┌►└►STA a1805                 ; warten für ca. 256 * A Zyklen
$03B4: AD 05 18 b03B4 │ ┌►LDA a1805                 ; 
$03B7: D0 FB          │ └ BNE b03B4                 ; 
$03B9: 60             │   RTS                       ; 
                                     ;Fehlerbehebung: nach oben / unten suchen
$03BA: A2 FF    s03BA └►│   LDX #$FF                  ; Schritt-Richtung
$03BC: A9 01            │   LDA #$01                  ; eine Spur
$03BE: 20 8C 03         │   JSR s038C                 ; bewegen des Kopfes
$03C1: A2 01              │   LDX #$01                  ; Schritt-Richtung
$03C3: 8A                 │   TXA                       ; eine Spur
$03C4: 20 8C 03           │   JSR s038C                 ; den Kopf wieder zurück bewegen
$03C7: A9 FF                │   LDA #$FF                  ; ~65000 Zyklen warten
$03C9: 20 B1 03             └   JSR s03B1                 ; 
$03CC: A9 04                    LDA #$04                  ; 5 Versuche
$03CE: 85 70                    STA a70                   ; 
$03D0: 20 20 03 b03D0   ┌►      JSR s0320                 ; suchen
$03D3: A6 18            │       LDX a18                     ; Spur des letzten gelesenen Sektorvorspanns
$03D5: 86 22            │       STX a22                     ; zur Spur des aktuellen Auftrags
$03D7: A4 00            │       LDY a00                     ; Auftragsergebnis lesen
$03D9: 88               │       DEY                         ; 
$03DA: F0 11            │ ┌     BEQ b03ED                   ; springen, wenn erfolgreich
$03DC: C6 70            │ │     DEC a70                     ; Wiederholungszähler dekrimieren
$03DE: 30 08            │ │   ┌ BMI b03E8                   ; 
$03E0: A6 70            │ │   │ LDX a70                     ; lesen des Wiederholungszähler
$03E2: 20 F3 03         │ │ ┌ │ JSR s03F3                   ; Kopfdichte setzen
$03E5: 38               │ │ │ │ SEC                         ; 
$03E6: B0 E8            └ │ │ │ BCS b03D0                   ; (immer springen) erneut suchen
$03E8: A9 00    b03E8     │ │ └►LDA #$00                    ; löschen der Spur vom aktuellen Auftrag
$03EA: 85 22              │ │   STA a22                     ; 
$03EC: 60                 │ │   RTS                         ; 
                          │ │                               ; 
$03ED: 8A       b03ED     └►│   TXA                         ; aktuelle Spur in den Akkumulator speichern
$03EE: 20 4B F2 s03EE └►      │   JSR eF24B                   ; die Anzahl der Sektoren der Spur ermitteln
$03F1: 85 43                  │   STA a43                     ; Variable für die Anzahl der Sektoren der Spur aktualisieren
$03F3: AD 00 1C s03F3         └►  LDA a1C00                   ; lesen des aktuellen Portinhalts
$03F6: 29 9F                      AND #$9F                    ; alles außer Dichtebits bewahren
$03F8: 1D 0F 03                   ORA f030F,X                 ; ausgewählte Dichtebits zusammenführen
$03FB: 8D 00 1C                   STA a1C00                   ; Wert im Steuersport speichern
$03FE: 60                         RTS                         ; zurückkehren
                                                              ;Übertragen eines Datenbausteins
$03FF: 84 71    s03FF             STY a71        ◄┐           ; Anzahl der Bytes speichern
$0401: A0 00                      LDY #$00                  ; ein Byte
$0403: 20 13 03                   JSR b0313                 ; warten bis CLOCK gesetzt ist
$0406: A5 71                      LDA a71                     ; Bytesanzahl abrufen
$0408: 20 16 04                 JSR s0416                   ; übertragen
$040B: A4 71                    LDY a71                     ; Byteanzahl lesen
$040D: 20 13 03                 JSR b0313                   ; Warten bis CLOCK gesetzt ist
$0410: 88       b0410       ┌►  DEY                           ; Byteanzahl dekrementieren
$0411: B1 73                │   LDA (p73),Y                   ; Datenbyte lesen
$0413: 2C 2A 04 a0413       │   BIT a042A                     ; Befehl geändert zu EOR $042A,Y (Anmerkung: Entschlüsselungsschlüssel endet kurz vor den t/s Bytes bei $0528)
$0416: AA       s0416       │   └►TAX                ◄┐         ; Byte merken
$0417: 4A                   │     LSR                         ; Bit des oberen Nibble nach unten schieben
$0418: 4A                   │     LSR                         ; 
$0419: 4A                   │     LSR                         ; 
$041A: 4A                   │     LSR                         ; 
$041B: 85 70                │     STA a70                     ; oberen Nibble merken
$041D: 8A                   │     TXA                         ; 
$041E: 29 0F                │     AND #$0F                    ; unteres Nibble maskieren
$0420: AA                   │     TAX                         ; 
$0421: A9 04                │     LDA #$04                    ; CLOCK/DATA setzen
$0423: 8D 00 18             │     STA a1800                   ; 
$0426: 2C 00 18 b0426       │   ┌►BIT a1800                   ; warten bis CLOCK nicht gesetzt ist
                a042A       │   │ =*+$01                      ; Befehlsparameter aufgerufen
$0429: F0 FB                │   └ BEQ b0426                   ; 
$042B: 2C 00 18             │     BIT a1800                   ; Bus überprüfen
$042E: D0 00                │   ┌ BNE b0430                   ; 2/3 - wegwerfen 2 zusätzliche Zyklen addieren, wenn CLOCK nicht gesetzt war
$0430: D0 00    b0430       │ ┌ └►BNE b0432                   ; 2/3
$0432: 8E 00 18 b0432       │ └►  STX a1800                   ; 4 - sende! (31) auf (CD)
$0435: 8A                   │     TXA                         ; 2
$0436: 2A                   │     ROL                         ; 2 - das nächste Bitpaar in Position bringen
$0437: 29 0F                │     AND #$0F                    ; 2 - maskieren
$0439: 8D 00 18             │     STA a1800                   ; 4 - sende! (20) auf (CD)
$043C: A6 70                │     LDX a70                     ; 3 - gespeichertes oberes Nibble lesen
$043E: BD 00 03             │     LDA f0300,X                 ; 4 - Nibble umwandeln
$0441: 8D 00 18             │     STA a1800                   ; 4 - sende (01) auf (CD)
$0444: EA                   │     NOP                         ; 2
$0445: 2A                   │     ROL                         ; 2
$0446: 29 0F                │     AND #$0F                    ; 2
$0448: C0 00                │     CPY #$00                    ; 2 - Bytezähler prüfen
$044A: 8D 00 18             │     STA a1800                   ; 4 - sende (23) auf (CD)
$044D: D0 C1                └     BNE b0410                   ; Fortsetzen der Schleife, wenn Bytes verbleiben
$044F: F0 00                    ┌ BEQ b0451                   ; Abfall-Zyklen?
$0451: A2 02    b0451         ┌►└►LDX #$02                    ; DATA auf nicht gesetzt setzen
$0453: 8E 00 18               │   STX a1800                   ; 
$0456: 60                     │   RTS                         ; 
                              │                               ;---- Einstiegspunkt ----
$0457: 08                     │   PHP                         ; speicherte Flags
$0458: 78                     │   SEI                         ; 
$0459: A5 49                  │   LDA a49                     ; speichern des temporären Stapelzeiger
$045B: 48                     │   PHA                         ; 
$045C: 20 51 04               └   JSR b0451                   ; DATA auf nicht gesetzt setzen
$045F: A9 04                      LDA #$04                    ; 
$0461: 2C 00 18 b0461           ┌►BIT a1800                   ; warten, bis CLOCK nicht gesetzt ist
$0464: F0 FB                    └ BEQ b0461                   ; 
$0466: 20 83 04                 ┌ JSR s0483                   ; übertragen der hartkodierten Sektorenketten und durchführen der Kopierschutzprüfung
$0469: AD 00 1C                 │ LDA a1C00                   ; LED ausschalten
$046C: 29 F7                    │ AND #$F7                    ; 
$046E: 8D 00 1C                 │ STA a1C00                   ; 
$0471: 8C 00 18                 │ STY a1800                   ; Y=0 immer - CLOCK/DATA setzen
$0474: 84 33                    │ STY a33                     ; High-Byte des Auftrags t/s Zeigers leeren
$0476: 20 8F F9                 │ JSR eF98F                   ; Motor ausschalten
$0479: A9 EC                    │ LDA #$EC                    ; Lesemodus, Ready-Byte deaktivieren
$047B: 8D 0C 1C                 │ STA a1C0C                   ; 
$047E: 68                       │ PLA                         ; wiederherstellen des temporären Stapelzeigers
$047F: 85 49                    │ STA a49                     ; 
$0481: 28                       │ PLP                         ; Flags wiederherstellen
$0482: 60                       │ RTS                         ; zurückkehren zum DOS ROM
                                │                             ;Übertragen von ein paar hartkodierte Sektorenketten und durchführen der Kopierschutzprüfung
$0483: A9 06    s0483           └►LDA #>p0602                 ; Zieladresse auf $0602 setzen
$0485: 85 74                      STA a74                     ; 
$0487: A9 02                      LDA #<p0602                 ; 
$0489: 85 73                      STA a73                     ; 
$048B: A9 13                      LDA #$13                    ; Spur 19 (Anfangssektor $0d von M-W)
$048D: 20 CF 04                 JSR s04CF                   ; lese und übertragen des Sektors
$0490: A9 59                    LDA #$59                    ; ändern der Übertragungsschleife mit Entschlüsselung
$0492: 8D 13 04                 STA a0413                   ; "BIT" zu "EOR, Y" ändern
$0495: A9 0F                    LDA #$0F                    ; Sektor auf 15 setzen
$0497: 8D 29 05                 STA a0529                   ; 
$049A: A9 14                    LDA #$14                    ; Spur 20
$049C: 20 CF 04               JSR s04CF                   ; lesen und übertragen des (entschlüsselten) Sektors
$049F: A9 00                  LDA #$00                    ; Sektor auf 0 setzen (die Spur ist 21, nach der Rückkehr von $04cf)
$04A1: 8D 29 05               STA a0529                   ; 
$04A4: 20 10 F5               JSR eF510                   ; nach dem Blockvorspann suchen
$04A7: A0 02                  LDY #$02                    ; lesen und wegwerfen von 2 Byte
$04A9: 20 F3 04               JSR s04F3                 ; 
$04AC: A2 13                  LDX #$13                  ; Anzahl der zu prüfenden Sektoren
$04AE: D0 12                ┌ BNE b04C2                 ;(Springe immer)
$04B0: A0 00    b04B0     ┌►│ LDY #$00                  ; Kopierschutzprüfung (Einsprung bei $l4c2) / wegwerfen von 256 Byte
$04B2: 20 F3 04           │ │ JSR s04F3               ; 
$04B5: A0 45              │ │ LDY #$45                ; wegwerfen von $45 Bytes
$04B7: 20 F3 04         │ │ JSR s04F3               ; 
$04BA: 20 02 05         │ │ JSR s0502             ; prüfe die Byte vor dem SYNC (kurz vor dem Sektor-Vorspannblock)
$04BD: A0 0A            │ │ LDY #$0A              ; wegwerfen von $0a Byte
$04BF: 20 F3 04       │ │ JSR s04F3             ; 
$04C2: 20 02 05 b04C2 │ └►JSR s0502           ; prüfe die Byte vor dem SYNC (kurz vor dem Datenblock)
$04C5: CA             │   DEX                 ; 
$04C6: D0 E8          └   BNE b04B0           ; Schleife, bis alle Sektoren geprüft wurden
$04C8: A9 11              LDA #$11            ; Sektor 17 setzen
$04CA: 8D 29 05           STA a0529           ; 
$04CD: A9 14              LDA #$14            ; Spur 20 einstellen
$04CF: 8D 28 05 s04CF └►└►┌►  STA p0528           ; Spur setzen
$04D2: 20 29 03 b04D2     ┌►JSR s0329           ; Sektor lesen
$04D5: A6 00              │ LDX a00               ; prüfen, ob erfolgreich
$04D7: CA                 │ DEX                   ; 
$04D8: D0 F8              └ BNE b04D2             ; springen, wenn nicht (unbegrenzte Wiederholungen)
$04DA: AC 01 06             LDY a0601             ; Sektornummer von $0601 einstellen (Linksektor)
$04DD: 8C 29 05             STY a0529             ; als aktuellen Sektor für die Operation
$04E0: 88                   DEY                   ; ändern der Anzahl der Bytes
$04E1: AD 00 06             LDA a0600             ; lesen der Linkspur
$04E4: 48                   PHA                   ; 
$04E5: F0 02              ┌ BEQ b04E9             ; springe, wenn der letzte Sektor in der Kette erreicht wurde
$04E7: A0 FE              │ LDY #$FE              ; Anzahl der Byte im Sektor setzen
$04E9: 20 FF 03 b04E9     └►JSR s03FF             ; übertragen der Sektoreninhalte
$04EC: 68                   PLA                     ; die Linkspur wiederherstellen
$04ED: D0 E0                BNE s04CF               ; die Übertragung weiterführen bis zum Kettenende
$04EF: A9 15                  LDA #$15                ; Spur auf 21 setzen
$04F1: D0 26                BNE b0519               ; (springe immer)
$04F3: 50 FE    s04F3 └►└►    ┌►BVC s04F3  ◄┘◄┘             ; warten bis das Byte fertig ist
$04F5: B8               │       CLV                         ; 
$04F6: AD 01 1C         │       LDA a1C01                   ; Byte lesen
$04F9: 88               │       DEY                         ; Zähler deprimieren
$04FA: D0 F7            │       BNE s04F3                   ; Schleife, bis alle Byte weggeworfen wurden
$04FC: 60               │         RTS                         ; 
                        │                                     ;Ein Byte lesen (ohne zu warten)
$04FD: AD 01 1C b04FD   │     ┌►  LDA a1C01                   ; Byte lesen (letztes Byte vor dem SYNC)
$0500: B8               │     │   CLV                         ; 
$0501: 60               │     │   RTS                         ; 
                        │     │                               ;Liest rohe Bytes und beendet, wenn ein SYNC gefunden wurde
$0502: AC 00 1C s0502   │ ┌►┌►┌►LDY a1C00      ◄┘◄┘             ; auf SYNC prüfen
$0505: 10 F6            │ BPL b04FD                       ; Byte lesen und zurückgeben, wenn SYNC gefunden wurde
$0507: 50 F9            │   BVC s0502                       ; schleife, bis Byte gelesen werden darf
$0509: B8               │     CLV                             ; 
$050A: AD 01 1C         │     LDA a1C01                       ; Byte lesen
$050D: C9 55            │     CMP #$55                        ; 
$050F: F0 F1            │     BEQ s0502                       ; Schleife, wenn $55
$0511: C9 67            │       CMP #$67                        ; 
$0513: F0 ED            │       BEQ s0502                       ; Schleife, wenn $67
$0515: 68               │         PLA                             ; Kopierschutzprüfung fehlgeschlagen / Rücksprungadresse entfernen
$0516: 68               │         PLA                             ; neue Rücksprungadresse wird $0469 sein
$0517: A9 12            │         LDA #$12                        ; Spur auf 18 setzen
$0519: 8D 28 05 b0519   └►        STA p0528                       ; aktuelle Spur einstellen
$051C: 20 58 03                   JSR s0358                       ; suchen
$051F: 20 13 03                   JSR b0313                         ; warten, bis CLOCK gesetzt ist
$0522: A9 00                      LDA #$00                            ; senden von einem 0x00 Byte und zurückkehren
$0524: A8                         TAY                                 ; 
$0525: 4C 16 04                   JMP s0416                           ; senden!
                                                                        ; 
$0528:          p0528             .BYTE $00                             ;Fast, aber nicht ganz Müll:
$0529:          a0529             .BYTE $0D,$00,$00,$00,$AE,$77,$00,$00 ;0529 ist der erste Sektor (Sektor $0D=13)
$0531:                            .BYTE $00,$00,$00,$00,$00,$00,$00,$00 ;
$0539:                            .BYTE $00,$00,$00,$00,$00,$00,$00     ;

Legende:
   Kopierschutzprüfung (I)
Speicherbelegung nach dem Laden des GEOS Kernal[Bearbeiten | Quelltext bearbeiten]

Der Speicherinhalt nach dem Laden des GEOS Kernal, also wenn sich das Programm an der Adresse $61F7 (JMP $C003) befindet, ist sehr interessant. Zu diesem Zeitpunkt befinden sich gleich zwei Kopierschutzprüfungsroutinen im Speicher des Diskettenlaufwerks. Die Kopierschutzprüfung (I) ist ein Bestandteil der Schnellladeroutine (Stufe 1), welche sich noch im Speicherbereich $0300 bis $053F befindet. Im Speicherbereich $0600 bis $06FF befinden sich die Daten des zuletzt gelesenen Sektors (Spur 29 Sektor 12), welche die Kopierschutzprüfung (II) enthalten. Im Speicher des Rechners befindet sich noch das Programm "GEOS BOOT", welches die Schnellladeroutine (Stufe 1) mit der Kopierschutzprüfung (I) beinhaltet. Die Schnellladeroutine (Stufe 1) ist in 32 Byte Blöcken in umgekehrter Bytereihenfolge im Speicher abgelegt. Die Schnellladeroutine (Stufe 2), als Teil des GEOS KERNAL, befindet sich auch schon im Speicher des Rechners. Beim Start des GEOS KERNAL wird die Schnellladeroutine (Stufe 2) an das Diskettenlaufwerk übertragen und ersetzt dort die Schnellladeroutine (Stufe 1). Während der Ausführung der Schnellladeroutine (Stufe 2) wird eine Unterroutine aufgerufen, welche eigentlich kein korrektes Ende besitzt. Diese Unterroutine geht nahtlos in die Kopierschutzprüfung (II) über, welche sich in den Daten aus Spur 29 Sektor 12 versteckt, welche wiederum noch immer im Speicher des Diskettenlaufwerks vorhanden sind.

                 Rechner                                                                                 Diskettenlaufwerk
─────────── ┌───────────────┐ $0000-$03FF Zeropage und Erweiterte Zeropage                  ─────────── ┌───────────────┐ ── ───────────
$0000-$0FFF │      RAM      │ $0400-$07e7 Bildschirmspeicher                                $0000-$07FF │      RAM      │    $0000-$00FF ┐
─────────── ├───────────────┤                                                               ─────────── ├───────────────┤ ┐  ─────────── │
$1000-$1FFF │               │                                                                           │               │ │  $0100-$01FF │ $0000-$02FF Zeropage
─────────── │               │                                                                           │               │ │  ─────────── │
$2000-$2FFF │               │                                                                           │               │ │  $0200-$02FF ┘
─────────── │               │                                                                           │               │ │  ─────────── 
$3000-$3FFF │               │                                                                           │               │ │  $0300-$03FF ┐
─────────── │      RAM      │                                                                           │               │ │  ─────────── │ $0300-$053F Schnellladeroutine (Stufe 1)
$4000-$4FFF │               │                                                                           │               │ │  $0400-$04FF │             beinhaltet die Kopierschutzprüfung (I)
─────────── │               │                                                                           │               │ │  ─────────── │ 
$5000-$5FFF │               │ $5000-$55BE Sektorkette 2/Datensatz 3 (GEOS Kaltstartroutine)             │               │ │  $0500-$05FF ┘
─────────── │               │                                                                           │               │ │  ─────────── 
$6000-$6FFF │               │ $6000-$64A7 "GEOS BOOT" enthält                                           │               │ │  $0600-$06FF   $0600-$06FF Daten von Spur 29 Sektor 12,
─────────── │               │             die Schnellladeroutine (Stufe 1), welche                      │               │ │  ───────────               das ist der letzte gelesene Sektor
$7000-$7FFF │               │             die Kopierschutzprüfung (I) beinhaltet                        │               │ │  $0700-$07FF               und beinhaltet die Kopierschutzprüfung (II)
─────────── ├───────────────┤                                                                           │               │ └─ ───────────
$8000-$8FFF │               │                                                                           │               │
─────────── │      RAM      │                                                                           │               │
$9000-$9FFF │               │ $9000-$9FFF Sektorkette 1/Datensatz 1 (GEOS Kernal Teil 1)                │               │
─────────── ├───────────────┤             Im Bereich $9609-$9948 befindet sich schon die                │               │
$A000-$AFFF │               │             Schnellladeroutine (Stufe 2)                                  │               │
─────────── │      RAM      │                                                                           │               │
$B000-$BFFF │               │ $BF40─────┐                                                               │               │
─────────── ├───────────────┤           │                                                   ─────────── ├───────────────┤           
$C000-$CFFF │      RAM      │           │                                                   $C000-$CFFF │               │
─────────── ├───────────────┤           │                                                   ─────────── │               │
$D000-$DFFF │      RAM      │           │ Sektorkette 3/Datensatz 2 (GEOS Kernal Teil 2)    $D000-$DFFF │               │
─────────── ├───────────────┤           │                                                   ─────────── │    DOS ROM    │
$E000-$EFFF │               │           │                                                   $E000-$EFFF │               │
─────────── │      RAM      │           │                                                   ─────────── │               │
$F000-$FFFF │               │ $FFF9─────┘                                                   $F000-$FFFF │               │
─────────── └───────────────┘                                                               ─────────── └───────────────┘

GEOS KERNAL[Bearbeiten | Quelltext bearbeiten]

Die Datei "GEOS KERNAL" ist eine USR-Datei im GEOS-VLIR-Format (Variable Length Index Record). Diese Datei besteht aus 3 Datensätzen. Die Startsektoren dieser 3 Datensätze entsprechen genau den fest kodierten Startsektoren im Programmcode der Schnellladeroutine (Stufe 1). Durch die Schnellladeroutine (Stufe 1) werden die 3 Datensätze komplett in den Speicher des Rechners geladen. Die Datei "GEOS KERNAL" belegt die komplette Spur 21 (alle 19 Sektoren), welche die gültigen GEOS-Lückendaten besitzen muss, da diese von der Kopierschutzprüfung (I und II) abgefragt werden.

  • alle Sektoren von Spur 21
Merkmal der Datei "GEOS KERNAL" Bemerkung
Sektoren/Blöcke 91 (17 für Datensatz 1 + 66 für Datensatz 2 + 6 für Datensatz 3 + 1 RECORD-Block + 1 GEOS-Info-Block)
Commodore DOS Dateiart USR ($83 im Directory)
Startsektor (RECORD-Block) Spur 19 Sektor 0
GEOS Dateistruktur VLIR ($01 im Directory)
GEOS Dateiart System Boot File ($0C im Directory)
GEOS Info Block Spur 19 Sektor 11
Datensätze 3
Datensatz 1 Startsektor Spur 19 Sektor 13
Datensatz 1 Sektoren (Spur.Sektor) 19.13, 19.02, 19.14, 19.03, 19.16, 19.05, 19.18, 19.06, 20.14, 20.03, 20.11, 20.00, 20.08, 20.16, 20.05, 20.13, 20.02
Datensatz 2 Startsektor Spur 20 Sektor 17
Datensatz 2 Sektoren (Spur.Sektor) 20.17, 21.15, 21.04, 21.12, 21.01, 21.09, 21.17, 21.06, 21.16, 21.05, 21.13, 21.02, 21.10, 21.18, 21.07, 21.00, 21.08, 22.14, 22.03, 22.11, 22.00, 22.08, 22.16, 22.05, 22.13, 22.02, 22.10, 22.18, 22.07, 22.15, 22.04, 22.12, 22.01, 22.09, 22.17, 22.06, 23.14, 23.03, 23.11, 23.00, 23.08, 23.16, 23.05, 23.13, 23.02, 23.10, 23.18, 23.07, 23.15, 23.04, 23.12, 23.01, 23.09, 23.17, 23.06, 24.14, 24.03, 24.11, 24.00, 24.08, 26.16, 29.00, 29.07, 29.15, 29.05, 29.12
Datensatz 3 Startsektor Spur 20 Sektor 15
Datensatz 3 Sektoren (Spur.Sektor) 20.15, 20.04, 20.12, 21.14, 21.03, 21.11
Bereich von $5000 bis $510E - GEOS-Kernal-Routine BootGEOS (Auszug)[Bearbeiten | Quelltext bearbeiten]

Das Programm "GEOS BOOT" startet mittels JMP $C003 die GEOS-Kernal-Routine BootGEOS. Die GEOS-Kernal-Routine BootGEOS ist für den eigentlichen Kopierschutzmechanismus nebensächlich. Interessant ist hingegen die GEOS-Kernal-Routine EnterTurbo, welche eine weitere Schnelladerroutine (II) an das Diskettenlaufwerk sendet und auch startet. Um den ersten Aufruf der GEOS-Kernal-Routine EnterTurbo zu finden, ist jedoch ein Blick auf die GEOS-Kernal-Routine BootGEOS unabdingbar. Die GEOS-Kernal-Routine BootGEOS ruft die GEOS-Kernal-Routine GetDirHead auf.

$5000: 78          p5000      SEI 
$5001: EA                     NOP 
$5002: D8                     CLD 
$5003: A2 FF                  LDX #$FF
$5005: 9A                     TXS 
$5006: A9 30                  LDA #$30
$5008: 85 01                  STA a01
$500A: A9 35                  LDA #$35
$500C: 8D FA FF               STA aFFFA    ;NMI
$500F: 8D FC FF               STA aFFFC    ;Hardware Reset
$5012: 8D FE FF               STA aFFFE    ;IRQ
$5015: A9 FB                  LDA #$FB
$5017: 8D FB FF               STA aFFFB    ;NMI
$501A: 8D FD FF               STA aFFFD    ;Hardware Reset
$501D: 8D FF FF               STA aFFFF    ;IRQ
$5020: 20 9C C4               JSR eC49C
$5023: 20 B4 C1               JSR eC1B4    ;GEOS Kernal Routine i_FillRam
$5026: 00 05                  BRK #$05
$5028: 00 84                  BRK #$84
$502A: 00 20                  BRK #$20
$502C: 71 C2                  ADC (pC2),Y
$502E: 20 80 FE               JSR eFE80
$5031: A9 08                  LDA #$08
$5033: 8D 8C 84               STA a848C
$5036: A9 01                  LDA #$01
$5038: 8D 4F 92               STA a924F
$503B: A4 BA                  LDY aBA
$503D: A9 01                  LDA #$01
$503F: 99 86 84               STA f8486,Y
$5042: 8C 89 84               STY a8489
$5045: A2 00                  LDX #$00
$5047: AD 0F 5F               LDA a5F0F
$504A: C9 13                  CMP #$13
$504C: D0 0F             ┌────BNE b505D
$504E: A0 03             │    LDY #$03
$5050: B9 06 5F    b5050 │  ┌►LDA f5F06,Y
$5053: D9 95 51          │  │ CMP f5195,Y
$5056: D0 05             │ ┌│─BNE b505D
$5058: 88                │ ││ DEY 
$5059: 10 F5             │ │└─BPL b5050
$505B: A2 80             │ │  LDX #$80
$505D: 8A          b505D └►└─►TXA 
$505E: 8D C5 88               STA a88C5
$5061: F0 14               ┌──BEQ b5077
$5063: A0 02               │  LDY #$02
$5065: B9 18 5F    b5065   │┌►LDA f5F18,Y
$5068: 99 16 85            ││ STA f8516,Y
$506B: 88                  ││ DEY 
$506C: 10 F7               │└─BPL b5065
$506E: AD 12 5F            │  LDA a5F12
$5071: 8D C4 88            │  STA a88C4
$5074: B8                  │  CLV 
$5075: 50 3F              ┌│──BVC b50B6
$5077: A9 35       b5077  │└─►LDA #$35
$5079: 85 01              │   STA a01
$507B: AD 0F DC           │   LDA $DC0F    ;CIA1: CIA Control Register B
$507E: 29 7F              │   AND #$7F
$5080: 8D 0F DC           │   STA $DC0F    ;CIA1: CIA Control Register B
$5083: A9 81              │   LDA #$81
$5085: 8D 0B DC           │   STA $DC0B    ;CIA1: Time-of-Day Clock: Hours + AM/PM Flag
$5088: A9 00              │   LDA #$00
$508A: 8D 0A DC           │   STA $DC0A    ;CIA1: Time-of-Day Clock: Minutes
$508D: 8D 09 DC           │   STA $DC09    ;CIA1: Time-of-Day Clock: Seconds
$5090: 8D 08 DC           │   STA $DC08    ;CIA1: Time-of-Day Clock: 1/10 Seconds
$5093: A9 30              │   LDA #$30
$5095: 85 01              │   STA a01
$5097: A9 58              │   LDA #<p0758
$5099: 8D 16 85           │   STA f8516
$509C: A9 07              │   LDA #>p0758
$509E: 8D 17 85           │   STA a8517
$50A1: A9 06              │   LDA #$06
$50A3: 8D 18 85           │   STA a8518
$50A6: A2 07              │   LDX #$07
$50A8: A9 BB              │   LDA #$BB
$50AA: 9D E8 8F    b50AA  │ ┌►STA f8FE8,X
$50AD: CA                 │ │ DEX 
$50AE: 10 FA              │ └─BPL b50AA
$50B0: A9 BF              │   LDA #$BF
$50B2: 8D F0 8F           │   STA a8FF0
$50B5: EA                 │   NOP 
$50B6: A9 FA       b50B6  └──►LDA #>pFAB3
$50B8: 8D FF FF               STA aFFFF    ;IRQ
$50BB: A9 B3                  LDA #<pFAB3
$50BD: 8D FE FF               STA aFFFE    ;IRQ
$50C0: 20 47 C2               JSR eC247    ;GEOS Kernal Routine GetDirHead
$50C3: 8A                     TXA 
$50C4: D0 0D              ┌───BNE b50D3
$50C6: A9 42              │   LDA #$42
$50C8: CD BD 82           │   CMP a82BD
$50CB: F0 06              │ ┌─BEQ b50D3
$50CD: 8D BD 82           │ │ STA a82BD
$50D0: 20 4A C2           │ │ JSR eC24A    ;GEOS Kernal Routine PutDirHead
$50D3: 20 99 51    b50D3  └►└►JSR s5199
$50D6: 4C D9 50             ┌─JMP j50D9
                            │
$50D9: AD 91 51    j50D9    └►LDA a5191
$50DC: 85 05                  STA a05
$50DE: AD 90 51               LDA a5190
$50E1: 85 04                  STA a04
$50E3: AD 94 51               LDA a5194
$50E6: 18                     CLC 
$50E7: 69 20                  ADC #$20
$50E9: 8D 94 51               STA a5194
$50EC: D0 21              ┌───BNE b510F
$50EE: AD 93 51    b50EE  │   LDA a5193
$50F1: 85 05              │   STA a05
$50F3: AD 92 51           │   LDA a5192
$50F6: 85 04              ▼   STA a04
$50F8: D0 15              ┌───BNE b510F
$50FA: AD 8D 84           │   LDA a848D    ;numDrives: Anzahl von Laufwerken im System
$50FD: D0 03              │ ┌─BNE b5102
$50FF: EE 8D 84           │ │ INC a848D
$5102: A9 C3       b5102  │ └►LDA #>pC326
$5104: 8D 2E C2           │   STA aC22E
$5107: A9 26              │   LDA #<pC326
$5109: 8D 2D C2           │   STA aC22D
$510C: 4C 26 C3           ▼   JMP pC326

Eintrag in der Sprungtabelle zur GEOS-Kernal-Routine GetDirHead

$901A:                        .BYTE $DF,$94
.
.
.
$C247: 6C 1A 90    eC247      JMP ($901A)
Bereich von $94DF bis $94FB - GEOS-Kernal-Routine GetDirHead (GetBlock)[Bearbeiten | Quelltext bearbeiten]

Die GEOS-Kernal-Routine GetDirHead geht Nahtlos in die GEOS-Kernal-Routine GetBlock über. An der Adresse $94EC beginnt die GEOS-Kernal-Routine GetBlock. Die GEOS-Kernal-Routine GetBlock wiederum ruft die GEOS-Kernal-Routine EnterTurbo auf.

$94DF: 20 EF 92               JSR s92EF
$94E2: D0 08                ┌─BNE b94EC
$94E4: A9 80       j94E4    │ LDA #>p8000
$94E6: 85 0B                │ STA a0B
$94E8: A9 00                │ LDA #<p8000
$94EA: 85 0A                │ STA a0A
$94EC: 20 14 C2    b94EC    └►JSR eC214    ;GEOS Kernal Routine EnterTurbo
$94EF: 8A                     TXA 
$94F0: D0 09                ┌─BNE b94FB
$94F2: 20 5C C2             │ JSR eC25C    ;GEOS Kernal Routine InitForIO
$94F5: 20 1A C2             │ JSR eC21A    ;GEOS Kernal Routine ReadBlock
$94F8: 20 5F C2             │ JSR eC25F    ;GEOS Kernal Routine DoneWithIO
$94FB: 60          b94FB    └►RTS

Eintrag in der Sprungtabelle zur GEOS-Kernal-Routine EnterTurbo

$9008:                        .BYTE $C3,$93
.
.
.
$C214:  6C 08 90   eC214      JMP ($9008)
Bereich von $93C3 bis $9416 - GEOS-Kernal-Routine EnterTurbo[Bearbeiten | Quelltext bearbeiten]

Die GEOS-Kernal-Routine EnterTurbo benutzt ein paar Unterroutinen, um die Schnellladeroutine (Stufe 2) an das Diskettenlaufwerk zu senden und diese zu starten.

$93C3: AD 89 84                   LDA a8489
$93C6: 20 B0 C2                   JSR eC2B0     ;GEOS Kernal Routine SetDevice
$93C9: 2C C6 88                   BIT a88C6
$93CC: 30 46            ┌─────────BMI b9414
$93CE: AE 89 84         │         LDX a8489
$93D1: BD 8A 84         │         LDA f848A,X
$93D4: 30 0E            │       ┌─BMI b93E4
$93D6: 20 3B 94         │       │ JSR s943B
$93D9: 8A               │       │ TXA 
$93DA: D0 3A            │      ┌│─BNE b9416
$93DC: AE 89 84         │      ││ LDX a8489
$93DF: A9 80            │      ││ LDA #$80
$93E1: 9D 8A 84         │      ││ STA f848A,X
$93E4: 29 40       b93E4│      │└►AND #$40
$93E6: D0 2C            │ ┌────│──BNE b9414
$93E8: 20 5C C2         │ │    │  JSR eC25C     ;GEOS Kernal Routine InitForIO
$93EB: A2 94            │ │    │  LDX #$94
$93ED: A9 17            │ │    │  LDA #$17
$93EF: 20 EA 90         │ │    │  JSR s90EA
$93F2: 8A               │ │    │  TXA 
$93F3: D0 21            │ │  ┌─│──BNE b9416
$93F5: 20 AE FF         │ │  │ │  JSR ROM_UNLSN ;$FFAE - unlisten all SERIAL devices      
$93F8: 78               │ │  │ │  SEI 
$93F9: A0 21            │ │  │ │  LDY #$21
$93FB: 88          b93FB│ │  │ │┌►DEY 
$93FC: D0 FD            │ │  │ │└─BNE b93FB
$93FE: 20 95 91         │ │  │ │  JSR b9195
$9401: 2C 00 DD    b9401│ │  │ │┌►BIT $DD00     ;CIA2: Data Port Register A
$9404: 30 FB            │ │  │ │└─BMI b9401
$9406: 20 5F C2         │ │  │ │  JSR eC25F     ;GEOS Kernal Routine DoneWithIO
$9409: AE 89 84         │ │  │ │  LDX a8489
$940C: BD 8A 84         │ │  │ │  LDA f848A,X
$940F: 09 40            │ │  │ │  ORA #$40
$9411: 9D 8A 84         │ │  │ │  STA f848A,X
$9414: A2 00       b9414└►└──│─│─►LDX #$00
$9416: 60          b9416     └►└─►RTS

$9417:                           .TEXT "M-E"
$941A:                           .BYTE $DC,$03
Bereich von $943B bis $9479 - Übertragen der Schnellladeroutine (Stufe 2)[Bearbeiten | Quelltext bearbeiten]

In diesem Abschnitt wird der Bereich von $943B bis $9479 behandelt, welcher das Übertragen der Schnellladeroutine (Stufe 2) vom Rechner zum Diskettenlaufwerk beinhaltet. Die Routine in diesem Bereich überträgt die Schnellladeroutine (Stufe 2) vom Rechner zum Speicher des Diskettenlaufwerks. Die Schnellladeroutine (Stufe 2) befindet sich ab der Adresse $9609 im Speicher des Rechners und soll zum Speicher des Diskettenlaufwerks ab der Adresse $0300 übertragen werden. Die Übertragung erfolgt durch die Unterroutine im Bereich von $947A bis $94A1, welche bei jedem Aufruf genau 32 Byte überträgt. Da diese Unterroutine 27 mal aufgerufen wird müssten eigentlich 864 Byte übertragen werden. Da beim Start von GEOS die Anzahl der Laufwerke im System gleich 0 ist, überträgt die Unterroutine im Bereich von $947A bis $94A1 für den Schleifendurchlauf (Schleifenzähler gleich 0) keine Daten. So werden also für die 27 Schleifendurchläufe nur 832 Datenbyte an das Diskettenlaufwerk übertragen. Es wird also der Speicherbereich von $9609 bis $9948 ($9609 + 832 - 1 = $9948) des Rechners in den Speicherbereich das Diskettenlaufwerks von $0300 bis $063F ($0300 + 832 - 1 = $063F) übertragen. Der Bereich vom $640 bis $6FF des Speichers des Diskettenlaufwerks bleibt bei der Übertragung des Schnellladeroutine (Stufe 2) unangetastet. In dem Bereich vom $640 bis $6FF befinden sich zu diesem Zeitpunkt immer noch die Daten des Sektors 12 von Spur 29. Dies ist der letzten Sektor, welcher mit der Schnellladeroutine (Stufe 1) geladen wurde.

$943B: 20 5C C2    s943B    JSR eC25C     ;GEOS Kernal Routine InitForIO
$943E: A9 96                LDA #>p9609
$9440: 85 8E                STA a8E       ;die Zeropageadresse $8E wird als Zeiger verwendet
$9442: A9 09                LDA #<p9609
$9444: 85 8D                STA a8D       ;die Zeropageadresse $8D wird als Zeiger verwendet
$9446: A9 03                LDA #>p0300
$9448: 8D A6 94             STA a94A6     ;ändert die Zieladresse des Direktzugriffsbefehls (M-W), welcher an der Adresse $94A2 beginnt 
$944B: A9 00                LDA #<p0300
$944D: 8D A5 94             STA a94A5     ;ändert die Zieladresse des Direktzugriffsbefehls (M-W), welcher an der Adresse $94A2 beginnt 
$9450: A9 1A                LDA #$1A      ;$1A=26 entspricht 27 Schleifendurchläufen
$9452: 85 8F                STA a8F       ;die Zeropageadresse $8F wird als Schleifenzähler verwendet
$9454: 20 7A 94    b9454 ┌─►JSR s947A     ;senden der nächsten 32 Byte an das Diskettenlaufwerk
$9457: 8A                │  TXA           ;Fehlerprüfung,
$9458: D0 1D            ┌│──BNE b9477     ;bei Fehler verzweigen
$945A: 18               ││  CLC           ;löscht das Carry-Flag
$945B: A9 20            ││  LDA #$20      ; \
$945D: 65 8D            ││  ADC a8D       ;  \
$945F: 85 8D            ││  STA a8D       ;   Die Adresse (Quelle), welche in $8D/$8E gespeichert ist, wird um 32 erhöhen
$9461: 90 02            ││┌─BCC b9465     ;  /
$9463: E6 8E            │││ INC a8E       ; /
$9465: 18          b9465││└►CLC           ;löscht das Carry-Flag
$9466: A9 20            ││  LDA #$20      ; \
$9468: 6D A5 94         ││  ADC a94A5     ;  \
$946B: 8D A5 94         ││  STA a94A5     ;   Die Adresse (Ziel), welche in $94A5/$94A6 gespeichert ist, wird um 32 erhöhen
$946E: 90 03            ││┌─BCC b9473     ;  /
$9470: EE A6 94         │││ INC a94A6     ; /
$9473: C6 8F       b9473││└►DEC a8F       ;der Schleifenzähler wird um 1 vermindert
$9475: 10 DD            │└──BPL b9454     ;solange der Schleifenzähler >= 0 ist wird verzweigt
$9477: 4C 5F C2    b9477└──►JMP eC25F     ;GEOS Kernal Routine DoneWithIO

$94A2:                      .TEXT "M-W"
$94A5:             a94A5    .BYTE $60
$94A6:             a94A6    .BYTE $06
Bereich von $947A bis $94A1 - Übertragen von 32 Datenbyte[Bearbeiten | Quelltext bearbeiten]

In diesem Abschnitt wird der Bereich von $947A bis $94A1 behandelt, welcher die Übertragung von 32 Datenbyte zum Speicher des Diskettenlaufwerks durchführt. Diese Unterroutine sendet 32 Datenbyte zum Speicher des Diskettenlaufwerks. Falls der aktuelle Schleifenzähler der äußeren Schleife gleich $00 ist und die Anzahl der Laufwerke im System auch gleich 0 ist, dann werden keine Datenbyte übertragen. Um den Direktzugriffsbefehl an das Diskettenlaufwerk zu senden wird die Unterroutine im Bereich $90EA bis $9119 verwendet.

$947A: A5 8F       s947A     LDA a8F       ;lädt den aktuellen Schleifenzähler der äußeren Schleife in den Akkumulator
$947C: 0D 8D 84              ORA a848D     ;numDrives: Anzahl von Laufwerken im System (die Anzahl ist bei Start von GEOS gleich 0)
$947F: F0 1E              ┌──BEQ b949F     ;verzweigt, wenn das Ergebnis der letzten Operation gleich $00 ist, also noch kein Laufwerk im System ist
$9481: A2 94              │  LDX #$94      ;Startadresse des Direktzugriffsbefehl (M-W) in das X-Register laden
$9483: A9 A2              │  LDA #$A2      ;Startadresse des Direktzugriffsbefehl (M-W) in den Akkumulator laden
$9485: 20 EA 90           │  JSR s90EA     ;Unterroutine Direktzugriffsbefehl an das Diskettenlaufwerk senden aufrufen
$9488: 8A                 │  TXA           ;Fehlerprüfung,  
$9489: D0 16             ┌│──BNE b94A1     ;bei Fehler verzweigen
$948B: A9 20             ││  LDA #$20      ;vor den eigentlichen Daten wird der Wert $20, was einem Leerzeichen entspricht, gesendet
$948D: 20 A8 FF          ││  JSR ROM_CIOUT ;$FFA8 - CIOUT: Byte-Ausgabe (serieller Bus)             
$9490: A0 00             ││  LDY #$00
$9492: B1 8D       b9492 ││┌►LDA (p8D),Y
$9494: 20 A8 FF          │││ JSR ROM_CIOUT ;$FFA8 - CIOUT: Byte-Ausgabe (serieller Bus)             
$9497: C8                │││ INY 
$9498: C0 20             │││ CPY #$20
$949A: 90 F6             ││└─BCC b9492
$949C: 20 AE FF          ││  JSR ROM_UNLSN ;$FFAE - UNLSN: Senden des UNLISTEN-Befehls für seriellen Bus zur Beendigung der Datenübertragung      
$949F: A2 00       b949F │└─►LDX #$00
$94A1: 60          b94A1 └──►RTS

$94A2:                       .TEXT "M-W"
$94A5:             a94A5     .BYTE $60
$94A6:             a94A6     .BYTE $06
Bereich von $90EA bis $9119 - Direktzugriffsbefehl senden[Bearbeiten | Quelltext bearbeiten]

In diesem Abschnitt wird der Bereich von $90EA bis $9119 behandeltet, welcher das Senden von Direktzugriffsbefehl an das Diskettenlaufwerk durchführt. Diese Unterroutine sendet einen Direktzugriffsbefehl an das Diskettenlaufwerk. Die Adresse an dem sich der Befehl befindet wird mittels Akkumulator und Y-Register übergeben. Als Rückgabeparameter wird das X-Register verwendet, welches im positiven Fall den Wert $00 aufweist. Im Fehlerfall enthält das X-Register den Wert $0D. Ein Direktzugriffsbefehl besteht dabei aus 5 Byte z.B. "M-W" als Text und die Byte $00,$06.

$90EA: 86 8C       s90EA      STX a8C        ;Adresse welche auf den Direktzugriffsbefehl zeig in das Zeropageadresse $8C speichern
$90EC: 85 8B                  STA a8B        ;Adresse welche auf den Direktzugriffsbefehl zeig in das Zeropageadresse $8B speichern
$90EE: A9 00                  LDA #$00
$90F0: 85 90                  STA a90        ;Zeropageadresse $90 auf den Wert $00 setzten, um diesen für die Fehlerprüfung verwenden zu können
$90F2: AD 89 84               LDA a8489      ;$8489 curDrive: aktuelle Laufwerksnummer
$90F5: 20 B1 FF               JSR ROM_LISTEN ;$FFB1 - LISTEN: Befehl LISTEN für Geräte am seriellen Bus (Start Datenempfang bei Peripheriegeräten)        
$90F8: 24 90                  BIT a90        ;Fehlerprüfung
$90FA: 30 18            ┌─────BMI b9114      ;verzweigen im Fehlerfall
$90FC: A9 FF            │     LDA #$FF
$90FE: 20 93 FF         │     JSR ROM_SECOND ;$FF93 - SECOND: Übertragung der Sekundäradresse nach LISTEN-Befehl  
$9101: 24 90            │     BIT a90        ;Fehlerprüfung
$9103: 30 0F            │ ┌───BMI b9114      ;verzweigen im Fehlerfall
$9105: A0 00            │ │   LDY #$00
$9107: B1 8B       b9107│ │ ┌►LDA (p8B),Y    ;das nächste Byte des Direktzugriffsbefehl in den Akkumulator laden
$9109: 20 A8 FF         │ │ │ JSR ROM_CIOUT  ;$FFA8 - CIOUT: Byte-Ausgabe (serieller Bus)            
$910C: C8               │ │ │ INY            ;erhöht den Inhalt des Y-Registers um 1
$910D: C0 05            │ │ │ CPY #$05       ;prüfen ob schon 5 Byte übertragen wurden
$910F: 90 F6            │ │ └─BCC b9107      ;verzweigen bis das 5. Byte übertragen wurde
$9111: A2 00            │ │   LDX #$00       ;das X-Register wird als Rückgabewert auf den Wert $00 für OK gesetzt
$9113: 60               │ │   RTS 
                        │ │
$9114: 20 AE FF    b9114└►└──►JSR ROM_UNLSN  ;$FFAE - UNLSN: Senden des UNLISTEN-Befehls für seriellen Bus zur Beendigung der Datenübertragung       
$9117: A2 0D                  LDX #$0D       ;das X-Register wird als Rückgabewert auf den Wert $0D für Fehler gesetzt
$9119: 60                     RTS
Schnellladeroutine (Stufe 2)[Bearbeiten | Quelltext bearbeiten]

Von der Schnellladeroutine (Stufe 2) wurden nur die Byte von $0300 bis $063F vom Rechner an das Diskettenlaufwerk übertragen. Die restlichen Byte bis zur Adresse $06FF stammen immer noch von Spur 29 Sektor 12, welcher als letzter Sektor von der Schnellladeroutine (Stufe 1) gelesen wurde. Der Programmcode der Schnellladeroutine (Stufe 2) geht also nahtlos in den Programmcode der Kopierschutzprüfung (II) über. Wenn die Kopierschutzprüfung (II) durchlaufen wurde und auch bestanden wurde, so schaltet sich die Prüfung selbstständig aus und kodiert einen Teil ihres Programmcodes. Bei jedem weiteren Aufruf wird also keine weitere Kopierschutzprüfung mehr durchgeführt und die Kopierschutzprüfung ist auch nicht mehr als solche erkennbar.

$0300:          f0300             .BYTE $0F,$07,$0D,$05,$0B,$03,$09,$01 ;
$0308:                            .BYTE $0E,$06,$0C,$04,$0A,$02,$08     ;
$030F:          f030F             .BYTE $00,$80                         ;
$0311: 20 A0 40                   JSR e40A0                             ;
$0314: C0 60                      CPY #$60                              ;
$0316: E0 10                      CPX #$10                              ;
$0318: 90 30                  ┌   BCC b034A                             ;
$031A: B0 50              ┌   │   BCS b036C                             ;
$031C: D0 70          ┌   │   │   BNE b038E                             ;
                j031F │   │   │   =*+$01               ◄┐               ;
$031E: F0 A0          │   │   │   BEQ e02C0             │               ;
$0320:                │   │   │   .BYTE $00             │               ;
$0321: 84 73          │   │   │   STY a73               │               ;
$0323: 84 74          │   │   │   STY a74               │               ;
$0325: C8             │   │   │   INY                   │               ;
$0326: 84 71    j0326 │   │   │   STY a71            ◄┐ │               ;
$0328: A0 00          │   │   │   LDY #$00            │ │               ;
$032A: 20 C5 03       │   │   │   JSR s03C5         │ │               ;
$032D: A5 71          │   │   │   LDA a71           │ │               ;
$032F: 20 3A 03       │   │   │ ┌ JSR s033A         │ │               ;
$0332: A4 71          │   │   │ │ LDY a71           │ │               ;
$0334: 20 C5 03       │   │   │ │ JSR s03C5       │ │               ;
$0337: 88       b0337 │   │ ┌►│ │ DEY             │ │               ;
$0338: B1 73          │   │ │ │ │ LDA (p73),Y     │ │               ;
$033A: AA       s033A │   │ │ │ └►TAX             │ │               ;
$033B: 4A             │   │ │ │   LSR             │ │               ;
$033C: 4A             │   │ │ │   LSR             │ │               ;
$033D: 4A             │   │ │ │   LSR             │ │               ;
$033E: 4A             │   │ │ │   LSR             │ │               ;
$033F: 85 70          │   │ │ │   STA a70         │ │               ;
$0341: 8A             │   │ │ │   TXA             │ │               ;
$0342: 29 0F          │   │ │ │   AND #$0F        │ │               ;
$0344: AA             │   │ │ │   TAX             │ │               ;
$0345: A9 04          │   │ │ │   LDA #$04        │ │               ;
$0347: 8D 00 18       │   │ │ │   STA a1800       │ │               ;
$034A: 2C 00 18 b034A │   │ │ └►┌►BIT a1800       │ │               ;
$034D: F0 FB          │   │ │   └ BEQ b034A       │ │               ;
$034F: 2C 00 18       │   │ │     BIT a1800       │ │               ;
$0352: D0 00          │   │ │   ┌ BNE b0354       │ │               ;
$0354: D0 00    b0354 │   │ │ ┌ └►BNE b0356       │ │               ;
$0356: 8E 00 18 b0356 │   │ │ └►  STX a1800       │ │               ;
$0359: 8A             │   │ │     TXA             │ │               ;
$035A: 2A             │   │ │     ROL             │ │               ;
$035B: 29 0F          │   │ │     AND #$0F        │ │               ;
$035D: 8D 00 18       │   │ │     STA a1800       │ │               ;
$0360: A6 70          │   │ │     LDX a70         │ │               ;
$0362: BD 00 03       │   │ │     LDA f0300,X     │ │               ;
$0365: 8D 00 18       │   │ │     STA a1800       │ │               ;
$0368: EA             │   │ │     NOP             │ │               ;
$0369: 2A             │   │ │     ROL             │ │               ;
$036A: 29 0F          │   │ │     AND #$0F        │ │               ;
$036C: C0 00    b036C │   └►│     CPY #$00        │ │               ;
$036E: 8D 00 18       │     │     STA a1800       │ │               ;
$0371: D0 C4          │     └     BNE b0337       │ │               ;
$0373: F0 43          │ ┌         BEQ b03B8       │ │               ;
$0375: A0 01    s0375 │ │         LDY #$01     ◄┐ │ │        ◄┐     ;
$0377: 20 83 03       │ │     ┌   JSR s0383     │ │ │         │     ;
$037A: 85 71          │ │     │   STA a71       │ │ │         │     ;
$037C: A8             │ │     │   TAY           │ │ │         │     ;
$037D: 20 83 03       │ │     │ ┌ JSR s0383     │ │ │         │     ;
$0380: A4 71          │ │     │ │ LDY a71       │ │ │         │     ;
$0382: 60             │ │     │ │ RTS           │ │ │         │     ;
                      │ │     │ │               │ │ │         │     ;
$0383: 20 C5 03 s0383 │ │   └►└►JSR s03C5     │ │ │         │     ;
$0386: 48       b0386 │ │   ┌►  PHA           │ │ │         │     ;
$0387: 68             │ │   │   PLA           │ │ │         │     ;
$0388: A9 04          │ │   │   LDA #$04      │ │ │         │     ;
$038A: 2C 00 18 b038A │ │   │ ┌►BIT a1800     │ │ │         │     ;
                b038E └►│   │ │ =*+$01        │ │ │         │     ;
$038D: F0 FB            │   │ └ BEQ b038A     │ │ │         │     ;
$038F: EA               │   │   NOP           │ │ │         │     ;
$0390: EA               │   │   NOP           │ │ │         │     ;
$0391: EA               │   │   NOP           │ │ │         │     ;
$0392: AD 00 18         │   │   LDA a1800     │ │ │         │     ;
$0395: 0A               │   │   ASL           │ │ │         │     ;
$0396: EA               │   │   NOP           │ │ │         │     ;
$0397: EA               │   │   NOP           │ │ │         │     ;
$0398: EA               │   │   NOP           │ │ │         │     ;
$0399: EA               │   │   NOP           │ │ │         │     ;
$039A: 0D 00 18         │   │   ORA a1800     │ │ │         │     ;
$039D: 29 0F            │   │   AND #$0F      │ │ │         │     ;
$039F: AA               │   │   TAX           │ │ │         │     ;
$03A0: EA               │   │   NOP           │ │ │         │     ;
$03A1: EA               │   │   NOP           │ │ │         │     ;
$03A2: EA               │   │   NOP           │ │ │         │     ;
$03A3: AD 00 18         │   │   LDA a1800     │ │ │         │     ;
$03A6: 0A               │   │   ASL           │ │ │         │     ;
$03A7: 48               │   │   PHA           │ │ │         │     ;
$03A8: A5 70            │   │   LDA a70       │ │ │         │     ;
$03AA: 68               │   │   PLA           │ │ │         │     ;
$03AB: 0D 00 18         │   │   ORA a1800     │ │ │         │     ;
$03AE: 29 0F            │   │   AND #$0F      │ │ │         │     ;
$03B0: 1D 0F 03         │   │   ORA f030F,X   │ │ │         │     ;
$03B3: 88               │   │   DEY           │ │ │         │     ;
$03B4: 91 73            │   │   STA (p73),Y   │ │ │         │     ;
$03B6: D0 CE            │   └   BNE b0386     │ │ │         │     ;
$03B8: A2 02    b03B8   └►┌►    LDX #$02      │ │ │         │     ;
$03BA: 8E 00 18           │     STX a1800     │ │ │         │     ;
$03BD: 60                 │     RTS           │ │ │         │     ;
                          │                   │ │ │         │     ;
$03BE: C6 48    b03BE     │ ┌►  DEC a48       │ │ │         │     ;
$03C0: D0 03              │ │ BNE s03C5     │ │ │         │     ;
$03C2: 20 4B 04         ┌ │ │ JSR s044B     │ │ │         │     ;
$03C5: A9 C0    s03C5   │ └►│ │ └►LDA #$C0      │◄┘◄┘ │ │         │     ;
$03C7: 8D 05 18         │   │ │   STA a1805     │     │ │         │     ;
$03CA: 2C 05 18 b03CA   │   │ │ ┌►BIT a1805     │     │ │         │     ;
$03CD: 10 EF            │   │ └ │ BPL b03BE     │     │ │         │     ;
$03CF: A9 04            │   │   │ LDA #$04      │     │ │         │     ;
$03D1: 2C 00 18         │   │   │ BIT a1800     │     │ │         │     ;
$03D4: D0 F4            │   │   └ BNE b03CA     │     │ │         │     ;
$03D6: A9 00            │   │     LDA #$00      │     │ │         │     ;
$03D8: 8D 00 18         │   │     STA a1800     │     │ │         │     ;
$03DB: 60               │   │     RTS           │     │ │         │     ;
                        │   │                   │     │ │         │     ;
$03DC: 08               │   │     PHP           │     │ │         │     ;---- Einstiegspunkt ----
$03DD: 78               │   │     SEI           │     │ │         │     ;
$03DE: A5 49            │   │     LDA a49       │     │ │         │     ;
$03E0: 48               │   │     PHA           │     │ │         │     ;
$03E1: A0 00            │   │     LDY #$00      │     │ │         │     ;
$03E3: 88       b03E3   │   │   ┌►DEY           │     │ │         │     ;
$03E4: D0 FD            │   │   └ BNE b03E3     │     │ │         │     ;
$03E6: 20 B8 03         │   └     JSR b03B8     │     │ │         │     ;
$03E9: A9 04            │         LDA #$04      │     │ │         │     ;
$03EB: 2C 00 18 b03EB   │       ┌►BIT a1800     │     │ │         │     ;
$03EE: F0 FB            │       └ BEQ b03EB     │     │ │         │     ;
$03F0: 20 40 04         │   ┌     JSR s0440     │     │ │         │     ;
$03F3: A9 06            │   │     LDA #>p064A   │     │ │         │     ;
$03F5: 85 74            │   │     STA a74       │     │ │         │     ;
$03F7: A9 4A            │   │     LDA #<p064A   │     │ │         │     ;
$03F9: 85 73            │   │     STA a73       │     │ │         │     ;
$03FB: 20 75 03         │   │     JSR s0375     ┘     │ │         │     ;
$03FE: 20 44 04         │   │ ┌   JSR s0444           │ │         │     ;
$0401: A9 07            │   │ │   LDA #>p0700         │ │         │     ;
$0403: 85 74            │   │ │   STA a74             │ │         │     ;
$0405: A9 00            │   │ │   LDA #<p0700         │ │         │     ;
$0407: 85 73            │   │ │   STA a73             │ │         │     ;
$0409: A9 03            │   │ │   LDA #$03            │ │         │     ;
$040B: 48               │   │ │   PHA                 │ │         │     ;
$040C: A9 EF            │   │ │   LDA #$EF            │ │         │     ;
$040E: 48               │   │ │   PHA                 │ │         │     ;
$040F: 6C 4A 06         │   │ │   JMP (p064A)         │ │         │     ;
                        │   │ │                       │ │         │     ;
$0412: 20 8F F9         │   │ │   JSR eF98F           │ │         │     ;
$0415: A9 00            │   │ │   LDA #$00            │ │         │     ;
$0417: 8D 00 18         │   │ │   STA a1800           │ │         │     ;
$041A: 85 33            │   │ │   STA a33             │ │         │     ;
$041C: A9 EC            │   │ │   LDA #$EC            │ │         │     ;
$041E: 8D 0C 1C         │   │ │   STA a1C0C           │ │         │     ;
$0421: 68               │   │ │   PLA                 │ │         │     ;
$0422: 68               │   │ │   PLA                 │ │         │     ;
$0423: 68               │   │ │   PLA                 │ │         │     ;
$0424: 85 49            │   │ │   STA a49             │ │         │     ;
$0426: 28               │   │ │   PLP                 │ │         │     ;
$0427: 60               │   │ │   RTS                 │ │         │     ;
                        │   │ │                       │ │         │     ;
$0428: AD 4C 06         │   │ │   LDA a064C           │ │         │     ;
$042B: 85 77            │   │ │   STA a77             │ │         │     ;
$042D: 49 60            │   │ │   EOR #$60            │ │         │     ;
$042F: 85 78            │   │ │   STA a78             │ │         │     ;
$0431: 60               │   │ │   RTS                 │ │         │     ;
                        │   │ │                       │ │         │     ;
$0432: A5 00            │   │ │   LDA a00             │ │         │     ;
$0434: C9 01            │   │ │   CMP #$01            │ │         │     ;
$0436: D0 05            │   │ │ ┌ BNE b043D           │ │         │     ;
                a0439   │   │ │ │ =*+$01              │ │         │     ;
$0438: A0 00            │   │ │ │ LDY #$00            │ │         │     ;
$043A: 4C 26 03         │   │ │ │ JMP j0326           ┘ │         │     ;
                        │   │ │ │                       │         │     ;
$043D: 4C 1F 03 b043D   │   │ │ └►JMP j031F             ┘         │     ;
                        │   │ │                                   │     ;
$0440: A9 F7    s0440   │   └►│   LDA #$F7                        │     ;
$0442: D0 11            │     │ ┌ BNE b0455                       │     ;
$0444: A9 08    s0444   │     └►│ LDA #$08                        │     ;
$0446: 0D 00 1C         │       │ ORA a1C00                       │     ;
$0449: D0 18            │     ┌ │ BNE b0463                       │     ;
$044B: A9 00    s044B   └►    │ │ LDA #$00                        │     ;
$044D: 85 20                  │ │ STA a20                         │     ;
$044F: A9 FF                  │ │ LDA #$FF                        │     ;
$0451: 85 3E                  │ │ STA a3E                         │     ;
$0453: A9 FB                  │ │ LDA #$FB                        │     ;
$0455: 2D 00 1C b0455         │ └►AND a1C00                       │     ;
$0458: 4C 63 04               │ ┌ JMP b0463                       │     ;
                              │ │                                 │     ;
$045B: AD 00 1C s045B         │ │ LDA a1C00          ◄┐◄┐         │     ;
$045E: 29 9F                  │ │ AND #$9F                    │     ;
$0460: 1D 67 04               │ │ ORA f0467,X                 │     ;
$0463: 8D 00 1C b0463         └►└►STA a1C00                   │     ;
$0466: 60                         RTS                         │     ;
                                                              │     ;
$0467:          f0467             .BYTE $00                   │     ;
$0468: 20 40 60                   JSR e6040                   │     ;
$046B: 20 32 06 s046B             JSR s0632          ◄┐◄┐   │     ;Dieser Aufruf führt zur Durchführung der Kopierschutzprüfung
$046E: A5 22                      LDA a22               │     ;
$0470: F0 05                    ┌ BEQ b0477             │     ;
$0472: A6 00                    │ LDX a00               │     ;
$0474: CA                       │ DEX                   │     ;
$0475: F0 20                  ┌ │ BEQ b0497             │     ;
$0477: A5 12    b0477         │ └►LDA a12               │     ;
$0479: 48                     │   PHA                   │     ;
$047A: A5 13                  │   LDA a13               │     ;
$047C: 48                     │   PHA                   │     ;
$047D: 20 07 05               │   JSR s0507       ┐     │     ;
$0480: 68                     │   PLA             │     │     ;
$0481: 85 13                  │   STA a13         │     │     ;
$0483: AA                     │   TAX             │     │     ;
$0484: 68                     │   PLA             │     │     ;
$0485: 85 12                  │   STA a12         │     │     ;
$0487: A4 00                  │   LDY a00         │     │     ;
$0489: C0 01                  │   CPY #$01        │     │     ;
$048B: D0 29            ┌     │   BNE b04B6       │     │     ;
$048D: E4 17            │     │   CPX a17         │     │     ;
$048F: D0 26          ┌ │     │   BNE b04B7       │     │     ;
$0491: C5 16          │ │     │   CMP a16         │     │     ;
$0493: D0 22          │ │ ┌   │   BNE b04B7       │     │     ;
$0495: A9 00          │ │ │   │   LDA #$00        │     │     ;
$0497: 48       b0497 │ │ │   └►  PHA             │     │     ;
$0498: A5 22          │ │ │       LDA a22         │     │     ;
$049A: A2 FF          │ │ │       LDX #$FF        │     │     ;
$049C: 38             │ │ │       SEC             │     │     ;
$049D: ED 4C 06       │ │ │       SBC a064C       │     │     ;
$04A0: F0 13          │ │ │   ┌   BEQ b04B5       │     │     ;
$04A2: B0 06          │ │ │   │ ┌ BCS b04AA       │     │     ;
$04A4: 49 FF          │ │ │   │ │ EOR #$FF        │     │     ;
$04A6: 69 01          │ │ │   │ │ ADC #$01        │     │     ;
$04A8: A2 01          │ │ │   │ │ LDX #$01        │     │     ;
$04AA: 20 BC 04 b04AA │ │ │ │ └►JSR s04BC       │     │     ;
$04AD: AD 4C 06       │ │ │ │   LDA a064C       │     │     ;
$04B0: 85 22          │ │ │ │   STA a22         │     │     ;
$04B2: 20 40 05       │ │ │ │   JSR s0540       │ ┐   │     ;
$04B5: 68       b04B5 │ │ │ └►  PLA             │ │   │     ;
$04B6: 60       b04B6 │ └►│     RTS             │ │   │     ;
                      │   │                     │ │   │     ;
$04B7: A9 0B    b04B7 └►  └►    LDA #$0B        │ │   │     ;
$04B9: 85 00                    STA a00         │ │   │     ;
$04BB: 60                       RTS             │ │   │     ;
                                                │ │   │     ;
$04BC: 86 4A    s04BC ┌►    └►    STX a4A      ◄┐ │ │   │     ;
$04BE: 0A                       ASL           │ │   │     ;
$04BF: A8                       TAY           │ │   │     ;
$04C0: AD 00 1C                 LDA a1C00     │ │   │     ;
$04C3: 29 FE                    AND #$FE      │ │   │     ;
$04C5: 85 70                    STA a70       │ │   │     ;
$04C7: A9 1E                    LDA #$1E      │ │   │     ;
$04C9: 85 71                    STA a71       │ │   │     ;
$04CB: A5 70    b04CB ┌►        LDA a70       │ │   │     ;
$04CD: 18             │         CLC           │ │   │     ;
$04CE: 65 4A          │         ADC a4A       │ │   │     ;
$04D0: 45 70          │         EOR a70       │ │   │     ;
$04D2: 29 03          │         AND #$03      │ │   │     ;
$04D4: 45 70          │         EOR a70       │ │   │     ;
$04D6: 85 70          │         STA a70       │ │   │     ;
$04D8: 8D 00 1C       │         STA a1C00     │ │   │     ;
$04DB: A5 71          │         LDA a71       │ │   │     ;
$04DD: 20 FB 04       │ ┌       JSR s04FB     │ │   │     ;
$04E0: A5 71          │ │       LDA a71       │ │   │     ;
$04E2: C0 05          │ │       CPY #$05      │ │   │     ;
$04E4: 90 08          │ │     ┌ BCC b04EE     │ │   │     ;
$04E6: C9 11          │ │     │ CMP #$11      │ │   │     ;
$04E8: 90 0A          │ │ ┌   │ BCC b04F4     │ │   │     ;
$04EA: E9 02          │ │ │   │ SBC #$02      │ │   │     ;
$04EC: D0 06          │ │ │ ┌ │ BNE b04F4     │ │   │     ;
$04EE: C9 1C    b04EE │ │ │ │ └►CMP #$1C      │ │   │     ;
$04F0: B0 02          │ │ │ │ ┌ BCS b04F4     │ │   │     ;
$04F2: 69 04          │ │ │ │ │ ADC #$04      │ │   │     ;
$04F4: 85 71    b04F4 │ │ └►└►└►STA a71       │ │   │     ;
$04F6: 88             │ │       DEY           │ │   │     ;
$04F7: D0 D2          └ │       BNE b04CB     │ │   │     ;
$04F9: A9 4B            │       LDA #$4B      │ │   │     ;
$04FB: 8D 05 18 s04FB   └►  ┌►  STA a1805     │ │   │     ;
$04FE: AD 05 18 b04FE       │ ┌►LDA a1805     │ │   │     ;
$0501: D0 FB                │ └ BNE b04FE     │ │   │     ;
$0503: 60                   │   RTS           │ │   │     ;
                       │ │   │     ;
$0504: 20 32 06             │   JSR s0632     │ │ │     ;Bei diesem Aufruf ist die Kopierschutzprüfung entschärft
$0507: A6 00    s0507       │   LDX a00      ◄┘ │ │     ;
$0509: CA                   │   DEX           │     ;
$050A: F0 12                │ ┌ BEQ b051E     │     ;
$050C: A2 FF                │ │ LDX #$FF      │     ;
$050E: A9 01                │ │ LDA #$01      │     ;
$0510: 20 BC 04             │ │ JSR s04BC     │     ;
$0513: A2 01                  │ │ LDX #$01      │     ;
$0515: 8A                     │ │ TXA           │     ;
$0516: 20 BC 04               │ │ JSR s04BC     │     ;
$0519: A9 FF                  │ │ LDA #$FF          │ │     ;
$051B: 20 FB 04               └ │ JSR s04FB         │ │     ;
$051E: A9 04    b051E     ┌►    └►LDA #$04          │ │     ;
$0520: 85 70              │       STA a70           │ │     ;
$0522: 20 99 05 b0522 ┌   │ ┌►    JSR s0599         │ │     ;
$0525: A6 18          │   │ │     LDX a18           │ │     ;
$0527: 86 22          │   │ │     STX a22           │ │     ;
$0529: A4 00          │   │ │     LDY a00           │ │     ;
$052B: 88             │   │ │     DEY               │ │     ;
$052C: F0 11          │   │ │ ┌   BEQ b053F         │ │     ;
$052E: C6 70          │   │ │ │   DEC a70           │ │     ;
$0530: 30 08          │   │ │ │ ┌ BMI b053A         │ │     ;
$0532: A6 70          │   │ │ │ │ LDX a70           │ │     ;
$0534: 20 5B 04       │   │ │ │ │ JSR s045B         │ │     ;
$0537: 38             │   │ │ │ │ SEC               │   │     ;
$0538: B0 E8          │   │ └ │ │ BCS b0522         │   │     ;
$053A: A9 00    b053A │   │   │ └►LDA #$00          │   │     ;
$053C: 85 22          │   │   │   STA a22           │   │     ;
$053E: 60             │   │   │   RTS               │   │     ;
                      │   │   │                     │   │     ;
$053F: 8A       b053F │   │   └►  TXA               │   │     ;
$0540: 20 4B F2 s0540 │   │       JSR eF24B        ◄┘   │     ;
$0543: 85 43          │   │       STA a43               │     ;
$0545: 4C 5B 04       │   │       JMP s045B             │     ;
                      │   │                               │     ;
$0548: AA       s0548 │ ┌►│       TAX                     │     ;
$0549: 24 20          │ │ │       BIT a20                 │     ;
$054B: 10 09          │ │ │     ┌ BPL b0556               │     ;
$054D: 20 3B 06       │ │ │     │ JSR s063B             │     ;Bei diesem Aufruf ist die Kopierschutzprüfung schon entschärft
$0550: A9 20          │ │ │     │ LDA #$20              │     ;
$0552: 85 20          │ │ │     │ STA a20               │     ;
$0554: A2 00          │ │ │     │ LDX #$00              │     ;
$0556: E4 22    b0556 │ │ │     └►CPX a22               │     ;
$0558: F0 21          │ │ │ ┌     BEQ b057B             │     ;
$055A: 20 1E 05       │ │ └ │     JSR b051E             │     ;
$055D: C9 01          │ │   │     CMP #$01              │     ;
$055F: D0 1A          │ │   │ ┌   BNE b057B             │     ;
$0561: A4 19          │ │   │ │   LDY a19               │     ;
$0563: C8             │ │   │ │   INY                   │     ;
$0564: C4 43          │ │   │ │   CPY a43               │     ;
$0566: 90 02          │ │   │ │ ┌ BCC b056A             │     ;
$0568: A0 00          │ │   │ │ │ LDY #$00              │     ;
$056A: 84 19    b056A │ │   │ │ └►STY a19               │     ;
$056C: A9 00          │ │   │ │   LDA #$00              │     ;
$056E: 85 45          │ │   │ │   STA a45               │     ;
$0570: A9 00          │ │   │ │   LDA #>p18             │     ;
$0572: 85 33          │ │   │ │   STA a33               │     ;
$0574: A9 18          │ │   │ │   LDA #<p18             │     ;
$0576: 85 32          │ │   │ │   STA a32               │     ;
$0578: 20 A5 05       │ │ ┌ │ │   JSR s05A5             │     ;
$057B: 60       b057B │ │ │ └►└►  RTS                   │     ;
                      │ │ │                             │     ;
$057C: 20 6B 04       │ │ │       JSR s046B             │     ;
$057F: A6 00          │ │ │       LDX a00                 │     ;
$0581: CA             │ │ │       DEX                     │     ;
$0582: D0 03          │ │ │     ┌ BNE b0587               │     ;
$0584: 20 48 05       │ └ │     │ JSR s0548               │     ;
$0587: 20 75 03 b0587 │   │     └►JSR s0375               ┘     ;
$058A: A9 10          │   │       LDA #$10                      ;
$058C: D0 05          │   │     ┌ BNE b0593                     ;
$058E: 20 6B 04       │   │     │ JSR s046B                     ;
$0591: A9 00          │   │     │ LDA #$00                        ;
$0593: A6 00    b0593 │   │     └►LDX a00                         ;
$0595: CA             │   │       DEX                             ;
$0596: F0 03          │   │     ┌ BEQ b059B                       ;
$0598: 60             │   │     │ RTS                             ;
                      │   │     │                                 ;
$0599: A9 30    s0599 └►  │     │ LDA #$30                        ;
$059B: 85 45    b059B     │     └►STA a45                         ;
$059D: A9 06              │       LDA #>a064C                     ;
$059F: 85 33              │       STA a33                         ;
$05A1: A9 4C              │       LDA #<a064C                     ;
$05A3: 85 32              │       STA a32                         ;
$05A5: A9 07    s05A5     └►      LDA #$07                        ;
$05A7: 85 31                      STA a31                         ;
$05A9: BA                         TSX                             ;
$05AA: 86 49                      STX a49                         ;
$05AC: A2 01                      LDX #$01                        ;
$05AE: 86 00                      STX a00                         ;
$05B0: CA                         DEX                             ;
$05B1: 86 3F                      STX a3F                         ;
$05B3: A9 EE                      LDA #$EE                        ;
$05B5: 8D 0C 1C                   STA a1C0C                       ;
$05B8: A5 45                      LDA a45                         ;
$05BA: C9 10                      CMP #$10                        ;
$05BC: F0 0A                  ┌   BEQ b05C8                       ;
$05BE: C9 30                  │   CMP #$30                        ;
$05C0: F0 03                  │ ┌ BEQ b05C5                       ;
$05C2: 4C CA F4               │ │ JMP eF4CA                       ;
                              │ │                                 ;
$05C5: 4C B1 F3 b05C5         │ └►JMP eF3B1                       ;
                              │                                   ;
$05C8: 20 E9 F5 b05C8         └►  JSR eF5E9                       ;
$05CB: 85 3A                      STA a3A                         ;
$05CD: AD 00 1C                   LDA a1C00                       ;
$05D0: 29 10                      AND #$10                        ;
$05D2: D0 04                    ┌ BNE b05D8                       ;
$05D4: A9 08                    │ LDA #$08                        ;
$05D6: D0 57                  ┌ │ BNE b062F                       ;
$05D8: 20 8F F7 b05D8         │ └►JSR eF78F                       ;
$05DB: 20 10 F5               │   JSR eF510                       ;
$05DE: A2 09                  │   LDX #$09                        ;
$05E0: 50 FE    b05E0         │ ┌►BVC b05E0                       ;
$05E2: B8                     │ │ CLV                             ;
$05E3: CA                     │ │ DEX                             ;
$05E4: D0 FA                  │ └ BNE b05E0                       ;
$05E6: A9 FF                  │   LDA #$FF                        ;
$05E8: 8D 03 1C               │   STA a1C03                       ;
$05EB: AD 0C 1C               │   LDA a1C0C                       ;
$05EE: 29 1F                  │   AND #$1F                        ;
$05F0: 09 C0                  │   ORA #$C0                        ;
$05F2: 8D 0C 1C               │   STA a1C0C                       ;
$05F5: A9 FF                  │   LDA #$FF                        ;
$05F7: A2 05                  │   LDX #$05                        ;
$05F9: 8D 01 1C               │   STA a1C01                       ;
$05FC: B8                     │   CLV                             ;
$05FD: 50 FE    b05FD         │ ┌►BVC b05FD                       ;
$05FF: B8                     │ │ CLV                             ;
$0600: CA                     │ │ DEX                             ;
$0601: D0 FA                  │ └ BNE b05FD                       ;
$0603: A0 BB                  │   LDY #$BB                        ;
$0605: B9 00 01 b0605         │ ┌►LDA f0100,Y                     ;
$0608: 50 FE    b0608         │ │ BVC b0608                       ;
$060A: B8                     │ │ CLV                             ;
$060B: 8D 01 1C               │ │ STA a1C01                       ;
$060E: C8                     │ │ INY                             ;
$060F: D0 F4                  │ └ BNE b0605                       ;
$0611: B1 30    b0611         │ ┌►LDA (p30),Y                     ;
$0613: 50 FE    b0613         │ │ BVC b0613                       ;
$0615: B8                     │ │ CLV                             ;
$0616: 8D 01 1C               │ │ STA a1C01                       ;
$0619: C8                     │ │ INY                             ;
$061A: D0 F5                  │ └ BNE b0611                       ;
$061C: 50 FE    b061C         │   BVC b061C                       ;
$061E: AD 0C 1C               │   LDA a1C0C                       ;
$0621: 09 E0                  │   ORA #$E0                        ;
$0623: 8D 0C 1C               │   STA a1C0C                       ;
$0626: A9 00                  │   LDA #$00                        ;
$0628: 8D 03 1C               │   STA a1C03                       ;
$062B: 85 50                  │   STA a50                         ;
$062D: A9 01                  │   LDA #$01                        ;
$062F: 85 00    b062F         └►  STA a00                         ;
$0631: 60                         RTS                             ;
                                                                  ;
$0632: A5 20    s0632             LDA a20                  ◄┘◄┘       ; prüfen, ob der Motor eingeschaltet ist
$0634: 29 20                      AND #$20                            ;
$0636: D0 0D                ┌     BNE b0645                           ;
$0638: 20 7E F9             │     JSR eF97E                           ; Motor einschalten
$063B: A0 80    s063B       │     LDY #$80     ◄┘                       ; Verzögerungsschleife
$063D: CA       b063D       │ ┌►┌►DEX                                   ;
$063E: D0 FD                │ │ └ BNE b063D                             ;
$0640: 88                   │ │   DEY                                   ;
$0641: D0 FA                │ └   BNE b063D                             ;
$0643: 84 3E                │     STY a3E                               ; Setzen des aktiven Laufwerks auf 0
$0645: A9 FF    b0645       └►    LDA #$FF                              ;
$0647: 4C 4E 06                 ┌ JMP j064E                             ; Befehls-Puffer überspringen
                                │                                       ;
$064A:          p064A           │ .BYTE $00,$00                         ; Befehls-Puffer
$064C:          a064C           │ .BYTE $00,$00                         ;
$064E: 85 48    j064E           └►STA a48                               ; die Ausschaltverzögerung auf das Maximum setzen
                f0651             =*+$01                                ; Befehlscode aufgerufen.
$0650: A9 EE    a0650             LDA #$EE                              ; wird später zu einem RTS (60) geändert
$0652: 8D 0C 1C                   STA a1C0C                             ; Lesemodus, Ready-Byte aktivieren
$0655: A2 32                      LDX #$32                              ; 50 Versuche
$0657: CA       b0657         ┌►  DEX                                   ;
$0658: F0 62                  │   BEQ b06BC                           ; Sprung zu "Kopierschutzprüfung fehlgeschlagen"
$065A: 2C 00 1C b065A         │ ┌►BIT a1C00                           ; auf SYNC warten
$065D: 30 FB                  │ └ BMI b065A                           ;
$065F: AD 01 1C               │   LDA a1C01                           ; Datenbyte lesen und verwerfen, damit das 8-Bit-Register wieder zur Datenaufnahme bereit ist​
$0662: B8                     │   CLV                                 ;
$0663: A0 00                  │   LDY #$00                            ;
$0665: 50 FE    b0665         │ ┌►BVC b0665                           ; auf Byte warten
$0667: B8                     │ │ CLV                                 ;
$0668: AD 01 1C               │ │ LDA a1C01                           ; Datenbyte lesen
$066B: D9 D5 06               │ │ CMP f06D5,Y                         ; Byte vergleichen mit der Vergleichsdatentabelle
$066E: D0 E7                  └ │ BNE b0657                           ; verzweigen, wenn es nicht übereinstimmt
$0670: C8                       │ INY                                 ; Inkrement-Tabellenzeiger
$0671: C0 08                    │ CPY #$08                            ;
$0673: D0 F0                    └ BNE b0665                           ; verzeweigen, bis 8 Byte erfolgreich verglichen wurden
$0675: A0 02                      LDY #$02                            ; 2 Bytes (Rest des Sektorkopfes)
$0677: 20 98 06                 JSR s0698                           ; überspringen
$067A: A2 13                    LDX #$13                            ; 19 Sektoren auf der Spur 21
$067C: D0 12                  ┌ BNE b0690                           ; (immer verzweigen)
$067E: A0 00    b067E   ┌►    │ LDY #$00                            ; überspringen von 256 Byte
$0680: 20 98 06       │     │ JSR s0698                           ;
$0683: A0 45          │     │ LDY #$45                            ; überspringen von 69 Byte
$0685: 20 98 06         │ JSR s0698                           ; (kompletten Datenbaustein, danach überspringen)
$0688: 20 A7 06         │ JSR s06A7                         ; prüfen der GEOS Lückendaten (kehrt nicht zurück, wenn die Prüfung fehlschlägt)
$068B: A0 0A            │ LDY #$0A                          ; Überspringen von 10 Byte (kodierter Sektor-Vorspann)
$068D: 20 98 06       │ JSR s0698                         ;
$0690: 20 A7 06 b0690 └►JSR s06A7                       ; prüfen der GEOS Lückendaten (kehrt nicht zurück, wenn die Prüfung fehlschlägt)
$0693: CA               DEX                             ; der Sektorzähler wird dekrementiert
$0694: D0 E8            BNE b067E                       ; verzeigen, wenn noch Sektoren übrig sind
$0696: F0 29              BEQ b06C1                     ; (immer verzweiegen) Kopierschutzprüfung wurde bestanden
$0698: 50 FE    s0698 └►└►  └►└►┌►BVC s0698                     ; auf Byte warten
$069A: B8                       CLV                           ;
$069B: AD 01 1C                 LDA a1C01                     ; Datenbyte lesen
$069E: 88                       DEY                           ;
$069F: D0 F7                    BNE s0698                     ; verzeigen, bis genug Bytes übersprungen wurden
$06A1: 60                         RTS                           ;
                                                                ;
$06A2: AD 01 1C b06A2         ┌►  LDA a1C01                     ; Datenbyte lesen und verwerfen, damit das 8-Bit-Register wieder zur Datenaufnahme bereit ist​
$06A5: B8                     │   CLV                           ;
$06A6: 60                     │   RTS                           ; Zurückkehren (Schutz noch nicht gefunden)
                              │                                 ;Das Prüfbyte vor dem SYNC, muss $55 oder $67 sein (gleiche Prüfbyte wie im Schnellladeroutine (Stufe 1)
$06A7: AC 00 1C s06A7     ┌►┌►┌►LDY a1C00    ◄┘◄┘                 ; auf SYNC prüfen
$06AA: 10 F6              BPL b06A2         │                 ; verzweigen, wenn SYNC gefunden
$06AC: 50 F9                BVC s06A7         │                 ; auf Byte warten
$06AE: B8                     CLV               │                 ;
$06AF: AD 01 1C               LDA a1C01         │                 ; Datenbyte lesen
$06B2: C9 55                  CMP #$55          │                 ;
$06B4: F0 F1                  BEQ s06A7         │                 ; verzweige, wenn $55
$06B6: C9 67                    CMP #$67          │                 ;
$06B8: F0 ED                    BEQ s06A7         │                 ; verzweige, wenn $67
                                                    │                 ;wenn das Byte nicht $55 oder $67 entspricht, dann ist die Kopierschutzprüfung fehlgeschlagen
$06BA: 68                         PLA               │                 ; Rücksprungadresse vom Stapel entfernen
$06BB: 68                         PLA               │                 ;
                                                    │                 ;Kopierschutzprüfung ist fehlgeschlagen, die Übertragungslänge wird geändert, um das Laden zu sabotieren
$06BC: A9 FE    b06BC             LDA #$FE          │◄┘                 ;
$06BE: 8D 39 04                   STA a0439         │                   ;
                                                    │                   ;Die Kopierschutzprüfung wurde bestanden, der Code der Kopierschutzprüfung wird "entfernt"
$06C1: A9 60    b06C1             LDA #$60         ◄┘                   ; den Anfang der Kopierschutzprüfung wird geändert zu einem RTS ($60)
$06C3: 8D 50 06                   STA a0650                             ;
$06C6: A2 79                      LDX #$79                              ; Zerstören der Beweise
$06C8: A0 00                      LDY #$00                              ; d.h. EOR aller Code Byte von $0651 bis $06C9 durchführen, um diese unkentlich zu machen
$06CA: 59 51 06 b06CA           ┌►EOR f0651,Y                           ;
$06CD: 99 51 06                 │ STA f0651,Y                           ;
$06D0: C8                       │ INY                                   ;
$06D1: CA                       │ DEX                                   ;
$06D2: D0 F6                    └ BNE b06CA                             ;
$06D4: 60                         RTS                                   ;
                                                                        ;
$06D5:          f06D5             .BYTE $52,$57,$35,$29,$6F,$76,$9C,$D5 ;Vergleichsdatentabelle
$06DD:                            .BYTE $00,$03,$00,$00,$80,$00,$00,$00 ; GCR-decodiert: 08 13 00 15 4A 45
$06E5:                            .BYTE $00,$6B,$55,$00,$00,$00,$00,$00 ; (Sektorvorspann für Spur 21 Sektor 0)
$06ED:                            .BYTE $00,$00,$00,$00,$00,$00,$00,$00 ;
$06F5:                            .BYTE $00,$3C,$03,$00,$00,$00,$00,$00 ;
$06FD:                            .BYTE $00,$08,$00                     ;

Legende:
   Daten von Spur 29 Sektor 12
Vereinigung der Schnellladeroutine (Stufe 2) mit der Kopierschutzprüfung (II)[Bearbeiten | Quelltext bearbeiten]

Die Schnellladeroutine (Stufe 2) wird von der GEOS-Kernal-Routine EnterTurbo an das Diskettenlaufwerk übertragen und gestartet. Dabei entscheidet die Anzahl der Laufwerke im System darüber, ob die gesamte Schnellladeroutine (Stufe 2) (27 mal 32 Byte=864 Byte) oder nur ein Teil (26 mal 32 Byte=832 Byte) übertragen wird. Die Anzahl der Laufwerke im System speichert Geos in der Adresse $848D (numDrives). Wenn Geos gestartet wird, ist die Anzahl der Laufwerke im System natürlich Null und in dem Fall wird nur ein Teil (26 mal 32 Byte=832 Byte) der Schnellladeroutine (Stufe 2) an das Diskettenlaufwerk übertragen. Zu diesem Zeitpunkt befinden sich noch die Schnellladeroutine (Stufe 1) und der letzte geladene Sektor (Spur 29 Sektor 12) im Speicher des Diskettenlaufwerks. Durch die Übertragung der Schnellladeroutine (Stufe 2) wird die Schnellladeroutine (Stufe 1) komplett und die Daten des letzten geladenen Sektors zum Teil überschrieben. Wenn nur ein Teil (26 mal 32 Byte=832 Byte) der Schnellladeroutine (Stufe 2) übertragen wird, benötigt die Schnellladeroutine (Stufe 2) unbedingt die Daten des letzten geladenen Sektors. Erst durch die Vereinigung der Schnellladeroutine (Stufe 2) mit den Daten des letzten geladenen Sektors, entsteht eine vollständige Routine. Die Daten des letzten geladenen Sektors entsprechen dabei der Kopierschutzprüfung (II). Nach dem Start der Schnellladeroutine (Stufe 2) durch die GEOS-Kernal-Routine EnterTurbo wird die Kopierschutzprüfung (II) durchgeführt. Wird diese Prüfung bestanden, so wird ein Teil des Programmcodes der Kopierschutzprüfung (II) kodiert, um dessen Existenz zu verbergen. Die Kopierschutzprüfung (II) deaktiviert sich auch nach dem einmaligen Bestehen durch eine Änderung des eigenen Programmcodes (es wird ein RTS an Adresse $0650 geschrieben). Im weiteren Verlauf des Starts von Geos wird die Anzahl der Laufwerke im System (numDrives) erhöht. Das bedeutet, dass bei jedem weiteren Aufruf der GEOS-Kernal-Routine EnterTurbo, die gesamte (27 mal 32 Byte=864 Byte) Schnellladeroutine (Stufe 2) an das Diskettenlaufwerk übertragen wird. Wenn die gesamte Schnellladeroutine (Stufe 2) übertragen wird, werden die Daten des letzten Sektors nicht benötigt, da die Schnellladeroutine (Stufe 2) dann schon eine komplette Routine darstellt. Eine Kopierschutzprüfung ist dann im Speicher des Diskettenlaufwerks nicht mehr vorhanden.

Schnellladeroutine (Stufe 2)        Schnellladeroutine (Stufe 1)             832 Byte der                    Schnellladeroutine (Stufe 2)    Die komplette (864 Byte)
im Speicher des Rechners            und der letzte geladene Sektor           Schnellladeroutine (Stufe 2)    nach bestandener                Schnellladeroutine (Stufe 2)
                                    (Spur 29 Sektor 12)                      im Speicher der Floppy          Kopierschutzprüfung             im Speicher der Floppy
                                           Übertragung von        
                                 ┌─────────────────────────────────┐
                                       26 mal 32 Byte=832 Byte                                               │
$9609: 0F 07 0D 05 0B 03 09 01┐─┐│  $0300: 0F 07 0D 05 0B 03 09 01 │┌►$0300: 0F 07 0D 05 0B 03 09 01  $0300: 0F 07 0D 05 0B 03 09 01  $0300: 0F 07 0D 05 0B 03 09 01◄┐ 
$9611: 0E 06 0C 04 0A 02 08 00│ ││  $0308: 0E 06 0C 04 0A 02 08 00 ││ $0308: 0E 06 0C 04 0A 02 08 00  $0308: 0E 06 0C 04 0A 02 08 00  $0308: 0E 06 0C 04 0A 02 08 00 │ 
.        Schnellladeroutine   │ ││  .        Schnellladeroutine    ││ .        Schnellladeroutine     .        Schnellladeroutine     .        Schnellladeroutine    │ 
.            (Stufe 2)        │ ├┘  .            (Stufe 1)         └┤ .            (Stufe 2)          .            (Stufe 2)          .            (Stufe 2)         │ 
.                             │ │   $0530: 00 00 00 00 00 00 00 00  │ .                               .                               .                              │ 
.                             │ │   $0538: 00 00 00 00 00 00 00 00  │ .                               .                               .                              │ 
.                             │ │                                   │ .                               .                               .                              │  
$98F9: 09 C0 8D 0C 1C A9 FF A2│ │                                   │ $05F0: 09 C0 8D 0C 1C A9 FF A2  $05F0: 09 C0 8D 0C 1C A9 FF A2  $05F0: 09 C0 8D 0C 1C A9 FF A2 │ 
$9901: 05 8D 01 1C B8 50 FE B8│ │                                   │ $05F8: 05 8D 01 1C B8 50 FE B8  $05F8: 05 8D 01 1C B8 50 FE B8  $05F8: 05 8D 01 1C B8 50 FE B8 │ 
$9909: CA D0 FA A0 BB B9 00 01│ │   $0600: 00 3D FF 91 EA E7 55 06  │ $0600: CA D0 FA A0 BB B9 00 01  $0600: CA D0 FA A0 BB B9 00 01  $0600: CA D0 FA A0 BB B9 00 01 │ 
$9911: 50 FE B8 8D 01 1C C8 D0│ │   $0608: 6D F2 71 48 BA 8E 8A 2B  │ $0608: 50 FE B8 8D 01 1C C8 D0  $0608: 50 FE B8 8D 01 1C C8 D0  $0608: 50 FE B8 8D 01 1C C8 D0 │ 
$9919: F4 B1 30 50 FE B8 8D 01│ │   $0610: 2F ED C1 BA A0 50 DD C1  │ $0610: F4 B1 30 50 FE B8 8D 01  $0610: F4 B1 30 50 FE B8 8D 01  $0610: F4 B1 30 50 FE B8 8D 01 │ 
$9921: 1C C8 D0 F5 50 FE AD 0C│ │   $0618: 6B C5 10 1D 48 2E 09 7D  │ $0618: 1C C8 D0 F5 50 FE AD 0C  $0618: 1C C8 D0 F5 50 FE AD 0C  $0618: 1C C8 D0 F5 50 FE AD 0C │ 
$9929: 1C 09 E0 8D 0C 1C A9 00│ │   $0620: 01 68 A4 40 E8 D5 63 F6  │ $0620: 1C 09 E0 8D 0C 1C A9 00  $0620: 1C 09 E0 8D 0C 1C A9 00  $0620: 1C 09 E0 8D 0C 1C A9 00 │ 
$9931: 8D 03 1C 85 50 A9 01 85│ │   $0628: 20 D0 C3 EE FF AD 60 BD  │ $0628: 8D 03 1C 85 50 A9 01 85  $0628: 8D 03 1C 85 50 A9 01 85  $0628: 8D 03 1C 85 50 A9 01 85 │ 
$9939: 00 60 A5 20 29 20 D0 0D│ │   $0630: 87 10 49 FD DF E4 04 E9  │ $0630: 00 60 A5 20 29 20 D0 0D  $0630: 00 60 A5 20 29 20 D0 0D  $0630: 00 60 A5 20 29 20 D0 0D │ 
$9941: 20 7E F9 A0 80 CA D0 FD│─┘   $0638: 44 EC 80 98 F0 FB 35 FB  └►$0638: 20 7E F9 A0 80 CA D0 FD  $0638: 20 7E F9 A0 80 CA D0 FD  $0638: 20 7E F9 A0 80 CA D0 FD │ 
$9949: 88 D0 FA 84 3E A9 FF 85│     $0640: 88 D0 FA 84 3E A9 FF 4C    $0640: 88 D0 FA 84 3E A9 FF 4C  $0640: 88 D0 FA 84 3E A9 FF 4C  $0640: 88 D0 FA 84 3E A9 FF 85 │ 
$9951: 48 60 00 00 00 00 AC 89├┐    $0648: 4E 06 00 00 00 00 85 48    $0648: 4E 06 00 00 00 00 85 48  $0648: 4E 06 8E 05 12 00 85 48  $0648: 48 60 00 00 00 00 AC 89 ├┐
$9959: 84 B9 86 84 8D B1 99 29││    $0650: A9 EE 8D 0C 1C A2 32 CA    $0650: A9 EE 8D 0C 1C A2 32 CA  $0650: 60 8E 03 0F 13 B1 83 49  $0650: 84 B9 86 84 8D B1 99 29 ││
$9961: BF 99 86 84 20 E1 C1 8A┘│    $0658: F0 62 2C 00 1C 30 FB AD    $0658: F0 62 2C 00 1C 30 FB AD  $0658: B9 DB F7 F7 EB DB 20 8D  $0658: BF 99 86 84 20 E1 C1 8A◄┘│
                               │    $0660: 01 1C B8 A0 00 50 FE B8    $0660: 01 1C B8 A0 00 50 FE B8  $0660: 8C 90 28 88 88 D8 26 9E  $0660:                                                │    $0668: AD 01 1C D9 D5 06 D0 E7    $0668: AD 01 1C D9 D5 06 D0 E7  $0668: 33 32 2E F7 22 24 F4 13  $0668:                                                │    $0670: C8 C0 08 D0 F0 A0 02 20    $0670: C8 C0 08 D0 F0 A0 02 20  $0670: DB 1B 13 C3 33 93 91 B1  $0670:                                                │    $0678: 98 06 A2 13 D0 12 A0 00    $0678: 98 06 A2 13 D0 12 A0 00  $0678: 29 2F 8D 9E 4E 5C FC FC  $0678:                                                │    $0680: 20 98 06 A0 45 20 98 06    $0680: 20 98 06 A0 45 20 98 06  $0680: DC 44 42 E2 A7 87 1F 19  $0680:                                                │    $0688: 20 A7 06 A0 0A 20 98 06    $0688: 20 A7 06 A0 0A 20 98 06  $0688: 39 9E 98 38 32 12 8A 8C  $0688:                                                │    $0690: 20 A7 06 CA D0 E8 F0 29    $0690: 20 A7 06 CA D0 E8 F0 29  $0690: AC 0B 0D C7 17 FF 0F 26  $0690:                                                │    $0698: 50 FE B8 AD 01 1C 88 D0    $0698: 50 FE B8 AD 01 1C 88 D0  $0698: 76 88 30 9D 9C 80 08 D8  $0698:                                                │    $06A0: F7 60 AD 01 1C B8 60 AC    $06A0: F7 60 AD 01 1C B8 60 AC  $06A0: 2F 4F E2 E3 FF 47 27 8B  $06A0:                                                │    $06A8: 00 1C 10 F6 50 F9 B8 AD    $06A8: 00 1C 10 F6 50 F9 B8 AD  $06A8: 8B 97 87 71 21 D8 60 CD  $06A8:                                                │    $06B0: 01 1C C9 55 F0 F1 C9 67    $06B0: 01 1C C9 55 F0 F1 C9 67  $06B0: CC D0 19 4C BC 4D 84 E3  $06B0:                                                │    $06B8: F0 ED 68 68 A9 FE 8D 39    $06B8: F0 ED 68 68 A9 FE 8D 39  $06B8: 13 FE 96 FE 57 A9 24 1D  $06B8:                                                │    $06C0: 04 A9 60 8D 50 06 A2 79    $06C0: 04 A9 60 8D 50 06 A2 79  $06C0: 19 B0 D0 5D 0D 0B A9 D0  $06C0:                                                │    $06C8: A0 00 59 51 06 99 51 06    $06C8: A0 00 59 51 06 99 51 06  $06C8: 70 70 59 51 06 99 51 06  $06C8:                                                │    $06D0: C8 CA D0 F6 60 52 57 35    $06D0: C8 CA D0 F6 60 52 57 35  $06D0: C8 CA D0 F6 60 52 57 35  $06D0:                                                │    $06D8: 29 6F 76 9C D5 00 03 00    $06D8: 29 6F 76 9C D5 00 03 00  $06D8: 29 6F 76 9C D5 00 03 00  $06D8:                                                │    $06E0: 00 80 00 00 00 00 6B 55    $06E0: 00 80 00 00 00 00 6B 55  $06E0: 00 80 00 00 00 00 6B 55  $06E0:                                                │    $06E8: 00 00 00 00 00 00 00 00    $06E8: 00 00 00 00 00 00 00 00  $06E8: 00 00 00 00 00 00 00 00  $06E8:                                                │    $06F0: 00 00 00 00 00 00 3C 03    $06F0: 00 00 00 00 00 00 3C 03  $06F0: 00 00 00 00 00 00 3C 03  $06F0:                                                │    $06F8: 00 00 00 00 00 00 08 00    $06F8: 00 00 00 00 00 00 08 00  $06F8: 00 00 00 00 00 00 08 00  $06F8:                                                                                                                                                 Übertragung von                                └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
                                                                                                                                             27 mal 32 Byte=864 Byte
                                                                                                                                    
                                                                      $0638: 20 7E F9  JSR $F97E      $0638: 20 7E F9  JSR $F97E      $0638: 20 7E F9  JSR $F97E    
                                                                      $063B: A0 80     LDY #$80       $063B: A0 80     LDY #$80       $063B: A0 80     LDY #$80     
                                                                      $063D: CA        DEX            $063D: CA        DEX            $063D: CA        DEX          
                                                                      $063E: D0 FD     BNE $063D      $063E: D0 FD     BNE $063D      $063E: D0 FD     BNE $063D    
                                                                      $0640: 88        DEY            $0640: 88        DEY            $0640: 88        DEY          
                                                                      $0641: D0 FA     BNE $063D      $0641: D0 FA     BNE $063D      $0641: D0 FA     BNE $063D    
                                                                      $0643: 84 3E     STY $3E        $0643: 84 3E     STY $3E        $0643: 84 3E     STY $3E      
                                                                      $0645: A9 FF     LDA #$FF       $0645: A9 FF     LDA #$FF       $0645: A9 FF     LDA #$FF     
                                                                      $0647: 4C 4E 06  JMP $064E      $0647: 4C 4E 06  JMP $064E      $0647: 85 48     STA $48      
                                                                      $064A:           .BYTE $00      $064A:           .BYTE $8E      $0649: 60        RTS          
                                                                      $064B:           .BYTE $00      $064B:           .BYTE $05      $064A:           .BYTE $00    
                                                                      $064C:           .BYTE $00      $064C:           .BYTE $12      $064B:           .BYTE $00    
                                                                      $064D:           .BYTE $00      $064D:           .BYTE $00      $064C:           .BYTE $00    
                                                                      $064E: 85 48     STA $48        $064E: 85 48     STA $48        $064D:           .BYTE $00    
                                                                      $0650: A9 EE     LDA #$EE       $0650: 60        RTS            $064E: AC 89 84  LDY $8489    
                                                                      $0652: 8D 0C 1C  STA $1C0C      $0651: 8E 03 0F  STX $0F03      $0651: B9 86 84  LDA $8486,Y  
                                                                      $0655: A2 32     LDX #$32       $0654: 13 B1     SLO ($B1),Y    $0654: 8D B1 99  STA $99B1    
                                                                      $0657: CA        DEX            $0656: 83 49     SAX ($49,X)    $0657: 29 BF     AND #$BF     
                                                                      $0658: F0 62     BEQ $06BC      $0658: B9 DB F7  LDA $F7DB,Y    $0659: 99 86 84  STA $8486,Y  
                                                                      $065A: 2C 00 1C  BIT $1C00      $065B: F7 EB     ISC $EB,X      $065C: 20 E1 C1  JSR $C1E1    
                                                                      $065D: 30 FB     BMI $065A      $065D: DB 20 8D  DCP $8D20,Y    $065F: 8A        TXA          
                                                                      $065F: AD 01 1C  LDA $1C01                                                                    

Legende:
   Schnellladeroutine (Stufe 1)
   832 Byte der Schnellladeroutine (Stufe 2)
   32 weitere Byte der Schnellladeroutine (Stufe 2)
   oberer Teil der Daten von Spur 29 Sektor 12
   unterer Teil der Daten von Spur 29 Sektor 12
   60 = RTS welches die Kopierschutzprüfung (II) deaktiviert
   Kommando Puffer welcher das letzte Kommando der Schnellladeroutine (Stufe 2) enthält
   Bereich welcher nach dem bestehen der Kopierschutzprüfung (II) kodiert wurde

Geschichte[Bearbeiten | Quelltext bearbeiten]

  • Bis Version 1.2 befinden sich die GEOS-Kopierschutzdaten auf der Spur 36, welche keine SYNC-Markierungen besitzt. Dort wird auf die Bytefolge $2f $53 $77 als Signatur geprüft. Der Programmcode dieser Prüfroutine befindet sich in der Datei "GEOS BOOT" und wird somit nur einmalig beim GEOS-Start ausgeführt. Ein einfacher Patch dieser Datei kann diesen Schutz aushebeln.
  • GEOS 1.3 besitzt zusätzlich zu diesem Kopierschutz ein sogenanntes "Trojanisches Pferd". Es ist ein Mechanismus, welcher sich im "DESKTOP" befindet. Dieser Mechanismus prüft in zufälligen Abständen die Prüfsumme der Datei "GEOS BOOT", um unerlaubte Veränderungen festzustellen. Wenn diese Prüfsumme falsch ist, werden die Directory Einträge der Dateien "GEOS", "GEOS BOOT", "KERNAL" und "DESKTOP" überschrieben, womit die GEOS-Diskette unbrauchbar wird.
  • Von den „Write Utilities“ mit der Applikation „GEOMERGE“ gibt es verschiedene Versionen. Die Versionen vor April 1992 wurden mit dem Kopierschutz ausgeliefert. Die nach April 1992 ausgelieferten Versionen besaßen keinen Kopierschutz mehr. Der Kopierschutz wurde durch den Hersteller selbst entfernt, da es wohl Probleme mit der Installationsroutine mit bestimmten Laufwerken gegeben hat.
  • Seit ca. Februar 2004 kann die Version 2.0 von GEOS im Web[2] bezogen werden. Diese Version besitzt keinen Kopierschutz mehr. Leider liegt diese Version nur in englischer Sprache vor.

Kopieren des Kopierschutzes[Bearbeiten | Quelltext bearbeiten]

Warum kann der Kopierschutz nicht kopiert werden?[Bearbeiten | Quelltext bearbeiten]

  • Die Commodore-Laufwerke, wie 1541, 1570, 1571, können eine Spur mit Nutzdaten nicht in einem Schreibdurchgang schreiben.
  • Die betroffenen Spuren (Spur 21) der kopiergeschützten GEOS-Disketten besitzen Nutzdaten, welche unbedingt benötigt werden.
  • Die Commodore-Laufwerke besitzen nur 2 KByte RAM-Speicher.
  • Eine gesamte Spur inklusive Nutzdaten benötigt mehr als 2 KByte RAM-Speicher.
  • Der RAM-Speicher des Rechners (C64/C128) kann nicht als Zwischenspeicher dienen, da die serielle Übertragung zu langsam ist, um eine Spur in einem Schreibdurchgang schreiben zu können.
  • Das Kopieren einer Diskette mit einem Commodore-Laufwerk kann also nur sektorweise erfolgen.

Warum zerstört das sektorweise Kopieren die GEOS-Lückendaten?[Bearbeiten | Quelltext bearbeiten]

  • Beim sektorweisen Kopieren werden die einzelnen Sektoren von einer Diskette gelesen und auf eine andere Diskette geschrieben.
  • Normalerweise wird dabei jede Spur, vor dem Kopieren der Sektoren, auf der Zieldiskette neu formatiert.
  • Durch das Formatieren werden normalerweise alle Lücken-Bytes auf den Wert $55 gesetzt.
  • Dann werden die einzelnen Sektoren nacheinander auf die formatierte Spur geschrieben.
  • Da sich dabei die Position der Daten-Blöcke immer etwas verschiebt, werden die Lücken-Bytes mit den Werten $55 vor und hinter dem Datenblock verändert.
  • Die GEOS-Lückendaten gehen beim sektorweisen Kopieren auf jeden Fall verloren.
  • In Anhang B ist dargestellt, dass schon eine Verschiebung um ein Bit nach vorn oder nach hinten die Lückendaten verändert.

Beispiel für das Zerstören der GEOS-Lückendaten durch sektorweises Kopieren[Bearbeiten | Quelltext bearbeiten]

Fabrikneue unformatierte Zieldiskette[Bearbeiten | Quelltext bearbeiten]

Zieldiskette
  • keine Struktur
GEOSTrack21Random1.png
GEOSTrack21Random2.png

Eine neue unformatierte Diskette besitzt keinerlei Struktur.

Formatieren der Zieldiskette[Bearbeiten | Quelltext bearbeiten]

Zieldiskette
  • Vorspannblock
  • Lücke
  • Datenblock
  • Lücke
  • usw.
GEOSTrack21FormattedByBASIC1.png
GEOSTrack21FormattedByBASIC2.png

Das Formatieren legt die organisatorischen Strukturen wie Spuren und Sektoren an. Die Zieldiskette kann mit folgenden BASIC Befehlen mit der Disketten-ID "LJ" und dem Diskettennamen "System" formatiert werden. Die Eingabe sollte im Groß-/Kleinschrift (Zeichensatz 2) Modus erfolgen.

open 1,8,15,"n:sYSTEM,lj": close 1

Durch das Formatieren mit der korrekten Disketten-ID "LJ" entstehen auf der Zieldiskette gültige Vorspannblöcke auf Spur 21. Aber auch auf allen anderen Spuren entstehen so korrekte Vorspannblöcke. Dies ist wichtig, damit nicht die Fehlermeldung READ ERROR (DISK ID MISMATCH) auftritt.

Spezielle Formatroutine[Bearbeiten | Quelltext bearbeiten]

Zieldiskette
  • Vorspannblock
  • Lücke
  • Datenblock
  • Lücke
  • usw.
GEOSTrack21FormattedBySpecialRoutine1.png
GEOSTrack21FormattedBySpecialRoutine2.png
Quelldiskette
(GEOS 64 2.0 Deutsch)
  • Vorspannblock
  • Lücke
  • Datenblock
  • Lücke
  • usw.
GEOSTrack21Original1.png
GEOSTrack21Original2.png

Die folgende spezielle Formatroutine formatiert die Spur 21 der eingelegten Diskette mit folgenden Eigenschaften:

  • Disketten-ID = "LJ"
  • Lücken vor den Datenblöcken 55 55 55 55 55 67 55 55 67
  • Lücken nach den Datenblöcken 55 55 55 55 67 55 55 67

Somit stimmen die Vorspannblöcke und die Lücken vor und nach den Datenblöcken auf der Zieldiskette mit der Quelldiskette überein.

Das folgende BASIC-Programm ist aus Teilen des Programms GEOSKONVERT 64 von Hans-Juergen Ziethmann entstanden.

100 POKE 53280,0: POKE 53281,0: POKE 646,15: REM Farben setzen
110 PRINT "{clear}{home}{ctrl+n}{weiß}"
120 PRINT "Dieses Programm formatiert die Spur 21"
130 PRINT "der eingelegten Diskette."
140 PRINT "Dabei werden spezielle Daten in den"
150 PRINT "Luecken vor und nach den Daten-" 
160 PRINT "Bloecken erzeugt."
170 PRINT "{violett}{cursor unten}Disketten ID:LJ"
180 PRINT "Luecke vor  :55 55 55 55 55 67 55 55 67"
190 PRINT "Luecke nach :   55 55 55 55 67 55 55 67"
200 PRINT "{gelb}{cursor down}Bitte Zieldiskette in das Laufwerk 8"
210 PRINT "einlegen und eine beliebige Taste"
220 PRINT "druecken.": WAIT 203,64,64
230 PRINT "{weiß}{cursor down}Uebertrage die Programmdaten"
240 PRINT "zum Laufwerk 8:";
250 OPEN15,8,15
260 LBYTE=237: REM lo-byte of the memory address 237 = ED
270 HBYTE=4: REM hi-byte of the memory address 4 = 04
280 B=1
290 FOR A=0 TO 327
300 B=B+1: IF B=20 THEN PRINT ".";: B=1
310 LBYTE=LBYTE+1
320 READ BYTE 
330 IF LBYTE>255 THEN HBYTE=HBYTE+1: LBYTE=0
340 PRINT#15,"m-w"CHR$(LBYTE)CHR$(HBYTE)CHR$(1)CHR$(BYTE)
350 NEXT A
360 PRINT "{grün}OK"
370 PRINT "{weiß}{down}Starte das Programm"
380 PRINT "im Laufwerk 8:";
390 PRINT#15,"m-e"CHR$(238)CHR$(4): REM $04EE
400 CLOSE 1: CLOSE 15
410 PRINT "{grün}OK" 
420 PRINT "{rot}{cursor down}Fertig!"
500 DATA 169,26,141,5,28,162,21,134
510 DATA 10,169,224,133,2,165,2,48
520 DATA 250,96,169,19,133,67,169,0
530 DATA 133,27,160,0,162,0,165,57
540 DATA 153,0,3,200,200,165,27,153
550 DATA 0,3,200,165,10,153,0,3
560 DATA 200,169,74,153,0,3,200,169
570 DATA 76,153,0,3,200,169,15,153
580 DATA 0,3,200,153,0,3,200,169
590 DATA 0,89,250,2,89,251,2,89
600 DATA 252,2,89,253,2,153,249,2
610 DATA 230,27,165,27,197,67,144,190
620 DATA 169,3,133,49,152,72,169,75
630 DATA 141,0,7,162,1,138,157,0
640 DATA 7,232,208,250,32,48,254,104
650 DATA 168,136,32,229,253,32,245,253
660 DATA 169,7,133,49,32,233,245,133
670 DATA 58,32,143,247,169,0,133,50
680 DATA 32,14,254,169,255,141,1,28
690 DATA 162,5,80,254,184,202,208,250
700 DATA 162,10,164,50,80,254,184,185
710 DATA 0,3,141,1,28,200,202,208
720 DATA 243,162,5,80,254,184,169,85
730 DATA 141,1,28,202,208,245,80,254
740 DATA 184,169,103,141,1,28,162,2
750 DATA 80,254,184,169,85,141,1,28
760 DATA 202,208,245,80,254,184,169,103
770 DATA 141,1,28,169,255,162,5,80
780 DATA 254,184,141,1,28,202,208,247
790 DATA 162,187,80,254,184,189,0,1
800 DATA 141,1,28,232,208,244,160,0
810 DATA 80,254,184,177,48,141,1,28
820 DATA 200,208,245,169,85,162,4,80
830 DATA 254,184,141,1,28,202,208,247
840 DATA 80,254,184,169,103,141,1,28
850 DATA 169,85,162,2,80,254,184,141
860 DATA 1,28,202,208,247,80,254,184
870 DATA 169,103,141,1,28,165,50,24
880 DATA 105,10,133,50,198,27,208,13
890 DATA 80,254,184,80,254,184,32,0
900 DATA 254,76,158,253,0,76,129,5

Im Anhang D findet sich der Assemblercode des Maschinenprogramms, das in den DATA-Zeilen des obigen BASIC-Programms abgelegt ist.

Sektorweises Kopieren[Bearbeiten | Quelltext bearbeiten]

Zieldiskette
  • Vorspannblock
  • Lücke
  • Datenblock
  • Lücke
  • usw.
GEOSTrack21FormattedBySpecialRoutineData1.png
GEOSTrack21FormattedBySpecialRoutineData2.png

Die Zieldiskette ist nun gut präpariert:

  • Alle Sektoren und deren Vorspannblöcke auf allen Spuren besitzen die Disketten-ID "LJ".
  • Die Spur 21 besitzt die korrekten Lücken vor und nach den Datenblöcken.

Der Zieldiskette fehlen nur noch die Datenblöcke der Quelldiskette. Um die vorbereiteten Daten auf der Zieldiskette nicht zu zerstören, wird für das Kopieren ein Kopierprogramm verwendet, welches die Spuren nicht formatiert. Hier kommt z.B. das Kopierprogramm "52.master-copy" in Frage. Das Kopierprogramm überträgt die Datenblöcke sektorweise von der Quelldiskette auf die Zieldiskette, ohne die Spuren neu zu formatieren. Dadurch bleiben die korrekten Vorspannblöcke erhalten und die Datenblöcke werden auch korrekt von der Quelldiskette übernommen. Leider werden die Datenblöcke nicht exakt an die „richtige“ Stelle geschrieben. Dadurch werden die vorbereiteten korrekten Lücken vor und nach den Datenblöcken auf Spur 21 zerstört.

Das Kopierprogramm "52.master-copy" kopiert leider nur 324 der 325 (GCR-codierten) Bytes der Datenblöcke. Dies ist normalerweise auch kein Problem, da die letzten 2 Bytes jedes Standarddatenblocks immer den Wert $00 besitzen und somit keine Information beinhalten. Wenn diese 2 Bytes in GCR codiert werden, entstehen 2,5 Bytes also 5 Nibbles mit den Werten $5 $29 $4A. Somit endet jeder Standarddatenblock mit den GCR-codierten Werten $5 $29 $4A. Da sowohl auf der Quelldiskette als auch auf der Zieldiskette die Datenblöcke mit diesen Werten enden, ist das Fehlverhalten von „52.master-copy“ auch hier zu vernachlässigen. Der Wert $4A, welcher nicht kopiert wird, gehört also somit ausnahmsweise mit zur Lücke.

Kopierprogramm "52.master-copy"


Warum scheitern auch Nibbler beim Kopieren der GEOS-Lückendaten?[Bearbeiten | Quelltext bearbeiten]

  • Ein Nibbler arbeitet zwar nicht sektorweise und versucht die Vorspannblocklücken und auch die Datenblocklücken 1 zu 1; Byte für Byte zu übertragen.
  • Nibbler haben aber dennoch das Problem, dass sie eine Spur nicht in einem Schreibvorgang schreiben können.
  • Somit muss auch ein Nibbler eine Spur in mehreren Durchgängen schreiben, was wiederum zur Zerstörung einiger Lückendaten-Bytes führt.
  • Ein sehr guter Vertreter der Nibbler ist der Turbo Nibbler[3].

Wie kann die Kopierschutzprüfung ausgetrickst werden (ohne diese zu entfernen)?[Bearbeiten | Quelltext bearbeiten]

Gelöschter Directory-Eintrag vom Programm "GEORAMKONV.128" auf der Heftdiskette zur "64'er Extra 1/94"
  • Die Nutzdaten von der Spur 21 werden auf andere Spuren verschoben und das Directory dementsprechend geändert.
  • Die Spur 21 wird in der Block Availability Map als belegt markiert.
  • So können die Daten nach wie vor von der Diskette gelesen werden.
  • Nun müssen noch die GEOS-Lückendaten auf die Spur 21 aufgebracht werden.
  • Durch eine spezielle Formatierungsroutine ist es möglich, die GEOS-Lückendaten auf die Spur 21 zu schreiben.
  • Die spezielle Formatierungsroutine kommt dabei mit den 2 KByte RAM-Speicher der Commodore-Laufwerke aus, da keine Nutzdaten auf die Spuren geschrieben werden müssen.
  • Genau dieses Vorgehen verwenden die folgenden Programme:
    • "GEOSKONVERT 64" für GEOS 64 2.0 aus der Programmsammlung "First Aid for GEOS" (Seite B)
    • "GEORAMKONV.64" für GEOS 2.0r GEORAM 64 aus der Programmsammlung "First Aid for GEOS" (Seite B)
    • "GEOSKONVERT 128" für GEOS 128 2.0 aus der Programmsammlung "First Aid for GEOS" (Seite B)
    • Ein "GEORAMKONV.128" für GEOS 2.0r GEORAM 128 ist nie veröffentlicht worden. Es gibt jedoch auf der Diskette zum 64'er Heft "64'er Extra 1/94" einen gelöschten Directory-Eintrag für dieses Programm.

Wie kann der Kopierschutz mit originaler Hardware dennoch kopiert werden?[Bearbeiten | Quelltext bearbeiten]

  • Das Kopieren des Kopierschutzes am C64 oder C128 ist nur mit zusätzlicher Hardware möglich.
  • Mit einem parallel angeschlossenen Commodore-Laufwerk kann der Rechner (C64/C128) als Zwischenspeicher genutzt werden, da die parallele Übertragung schnell genug ist, um eine Spur mit einem Schreibdurchgang auf die Zieldiskette zu schreiben.
  • Mit dem Burst Nibbler[4][5] ist es möglich, GEOS mit einem parallel angeschlossenen Commodore-Laufwerk zu kopieren.
  • Mit einer Erweiterung des Laufwerk-RAM-Speichers (z.B. RAMBOard) kann eine gesamte Spur in dem Laufwerk zwischengespeichert werden, um diese mit einem Schreibdurchgang auf die Zieldiskette zu schreiben.
  • Mit dem Maverick RAMBoard Nibbler[6] und einem RAMBOard ist es möglich, GEOS zu kopieren.

Wie kann der Kopierschutz mit moderner Hardware kopiert werden?[Bearbeiten | Quelltext bearbeiten]

  • Mit der Kombination aus PC, ZoomFloppy und Commodore 1571 ist es schon mit nur serieller Übertragung möglich, eine gesamte Spur in einem Durchgang auf die Diskette zu schreiben. Hierbei wird keine Modifikation der 1571 benötigt. Am PC wird dazu das "nibtools"-Software[7] mit den Befehlen "nibread" und "nibwrite" verwendet.
  • Mit diversen Parallelkabeln kann ein umgebautes Commodore-Laufwerk an einen PC angeschlossen und eine gesamte Spur in einem Durchgang auf eine Diskette geschrieben werden.

Abbildung des Kopierschutzes mittels Disketten-Image[Bearbeiten | Quelltext bearbeiten]

Um den GEOS-Kopierschutz abbilden zu können, wird ein Disketten-Image-Formate benötigt, welches Disketten auf GCR-Ebene abbilden kann. Die GEOS-Lückendaten benötigen zwingend eine Abbildung auf GCR-Ebene. Die Abbildung mittels D64-Datei ist nicht ausreichend, da dieses Format nur die reinen Daten und nicht die GCR-Ebene abbildet. Bei der Erstellung einer D64-Datei von einer kopiergeschützten GEOS Diskette gehen die GEOS-Lückendaten verloren. Die verlorenen GEOS-Lückendaten können jedoch rekonstruiert werden.

Das G64-Dateiformat, welches eine Diskette auf GCR-Ebene abbildet, ist absolut ausreichend, um den GEOS-Kopierschutz vollständig abzubilden. Selbst das Zurückschreiben auf eine reale Diskette ist ohne Verlust der GEOS-Lückendaten möglich.

Weitere Formate, welche den GEOS-Kopierschutz abbilden können:

  • P64
  • FDI
  • CT RAW
  • IPF
  • NIB
  • DFI image format (DFI)
  • SuperCard Pro image file format (SCP)
  • KryoFlux stream files

Rekonstruieren der GEOS-Lückendaten[Bearbeiten | Quelltext bearbeiten]

Eine kopiergeschützte GEOS-Diskette entspricht, bis auf die GEOS-Lückendaten, dem Commodore-DOS-Standard. Somit enthält eine einfache Kopie einer kopiergeschützen GEOS-Diskette bzw. ein erstelltes D64-Image einer kopiergeschützen GEOS-Diskette, bis auf die GEOS-Lückendaten, alle benötigten Informationen. Dabei spielt es auch keine Rolle, wann die Kopie bzw. das D64-Image erstellt wurde. Es ist somit möglich, auch von uralten Kopien bzw. D64-Images lauffähige Disketten bzw. G64-Images zu erstellen. Die GEOS-Lückendaten können nachträglich wieder angelegt werden. Die Diskette muss dazu im D64-Dateiformat vorliegen.

Methoden zum Hinzufügen von GEOS-Lückendaten zu einer D64-Image-Datei[Bearbeiten | Quelltext bearbeiten]

  1. Suchen und Ersetzen im G64-Image (alias "Holzhammermethode")
    • Das D64-Image wird mit einem entsprechenden Programm (z.B. 64copy[8]) in ein G64-Image umgewandelt.
    • Mit einem Hex-Editor (z.B. Notepad++ mit dem Plugin Hex-Editor) wird in der entstandenen G64-Image-Datei nach "55 FF FF FF FF" gesucht und dies durch "67 FF FF FF FF" ersetzt.
    • Da in einem G64-Image die Daten GCR-codiert vorliegen, werden in der Regel durch diese Methode immer die richtigen Stellen gefunden und ersetzt.
  2. Verwenden von nibconv67[9] von ZAK256
    • Dieses Tool fügt bei der Konvertierung von D64 zu G64 die GEOS-Lückendaten hinzu.
  3. Verwenden von nibconv+[10] von markusC64
    • Dieses Tool fügt bei der Konvertierung von D64 zu G64 die GEOS-Lückendaten hinzu. Dazu ist die Option "-7" bei der Konvertierung zu verwenden.
  4. Verwenden von g64conv[11] von markusC64
    • Dieses Tool fügt bei der Konvertierung von D64 zu G64 die GEOS-Lückendaten hinzu, wenn ein entsprechendes Template verwendet wird.

Anhang A - 37 Kopierschutzprüfungen (19 Header-Lücken und 18 Data-Lücken)[Bearbeiten | Quelltext bearbeiten]

Sektor Block/Cap Prüfung ldx #$13 19 19 sectors on track 21
Sektor 0 Header Block
Header Cap Prüfung 1 dex 18 decrement sector counter
Data Block
Data Cap Prüfung 2
Sektor 1 Header Block
Header Cap Prüfung 3 dex 17 decrement sector counter
Data Block
Data Cap Prüfung 4
Sektor 2 Header Block
Header Cap Prüfung 5 dex 16 decrement sector counter
Data Block
Data Cap Prüfung 6
Sektor 3 Header Block
Header Cap Prüfung 7 dex 15 decrement sector counter
Data Block
Data Cap Prüfung 8
Sektor 4 Header Block
Header Cap Prüfung 9 dex 14 decrement sector counter
Data Block
Data Cap Prüfung 10
Sektor 5 Header Block
Header Cap Prüfung 11 dex 13 decrement sector counter
Data Block
Data Cap Prüfung 12
Sektor 6 Header Block
Header Cap Prüfung 13 dex 12 decrement sector counter
Data Block
Data Cap Prüfung 14
Sektor 7 Header Block
Header Cap Prüfung 15 dex 11 decrement sector counter
Data Block
Data Cap Prüfung 16
Sektor 8 Header Block
Header Cap Prüfung 17 dex 10 decrement sector counter
Data Block
Data Cap Prüfung 18
Sektor 9 Header Block
Header Cap Prüfung 19 dex 9 decrement sector counter
Data Block
Data Cap Prüfung 20
Sektor 10 Header Block
Header Cap Prüfung 21 dex 8 decrement sector counter
Data Block
Data Cap Prüfung 22
Sektor 11 Header Block
Header Cap Prüfung 23 dex 7 decrement sector counter
Data Block
Data Cap Prüfung 24
Sektor 12 Header Block
Header Cap Prüfung 25 dex 6 decrement sector counter
Data Block
Data Cap Prüfung 26
Sektor 13 Header Block
Header Cap Prüfung 27 dex 5 decrement sector counter
Data Block
Data Cap Prüfung 28
Sektor 14 Header Block
Header Cap Prüfung 29 dex 4 decrement sector counter
Data Block
Data Cap Prüfung 30
Sektor 15 Header Block
Header Cap Prüfung 31 dex 3 decrement sector counter
Data Block
Data Cap Prüfung 32
Sektor 16 Header Block
Header Cap Prüfung 33 dex 2 decrement sector counter
Data Block
Data Cap Prüfung 34
Sektor 17 Header Block
Header Cap Prüfung 35 dex 1 decrement sector counter
Data Block
Data Cap Prüfung 36
Sektor 18 Header Block
Header Cap Prüfung 37 dex 0 decrement sector counter
Data Block
Data Cap Keine Prüfung!


Anhang B - Probleme beim sektorweisen Kopieren[Bearbeiten | Quelltext bearbeiten]

Probleme beim sektorweisen Kopieren


Anhang C - Der Sektor 0 (Spur 21) einer GEOS-Systemdiskette[Bearbeiten | Quelltext bearbeiten]

Der Sektor 0 (Spur 21) einer GEOS Systemdiskette


Anhang D - Assemblercode der speziellen Formatroutine[Bearbeiten | Quelltext bearbeiten]

*=$04EE



    LDA #$1A
    STA $1C05     ; TIMER 1 HIGH COUNTER
    LDX #$15      ; $15 = 21 für Spur 21
    STX $0A       ; Spur für Aufgabe in $0002 (Puffer 2)
    LDA #$E0      ; Aufgabencode = $E0 (224) => EXECUTE
L01 STA $02       ; benutze Puffer #2 ($0500+) für die Aufgabe EXECUTE -> $0500
    LDA $02
    BMI L01
    RTS
;-------------------------------------------------------------------------------
;$0500 Start von Puffer #2
    LDA #$13      ; $13 = 19 ist Anzahl der Sektoren auf Spur 21
    STA $43       ; $42 enthält die Sektorenanzahl, welche von der
                  ; Formatroutine verwendet wird
    LDA #$00      ; Akkumulator = $00
    STA $1B       ; $1B wird als Sektorzähler verwendet
    LDY #$00      ; Y = $00
    LDX #$00      ; X = $00
L02 LDA $39       ; Vorspannblock ID Zeichen ($08) 
                  ; ab $300 werden die Vorspannblöcke aufgebaut                  
    STA $0300,Y   ; Vorspannblock ID Zeichen ($08)
                  ; in den aktuellen Vorspannblock schreiben
    INY           ; Y + 1
    INY           ; Y + 1
    LDA $1B       ; Sektorzähler
    STA $0300,Y   ; Sektorzähler in den aktuellen Vorspannblock schreiben
    INY           ; Y + 1
    LDA $0A       ; Spurnummer
                  ; Track/Sector for job in $0002 (buffer 2)
    STA $0300,Y   ; Spurnummer in den aktuellen Vorspannblock schreiben
;-------------------------------------------------------------------------------
    INY           ; Y + 1
;    LDA $13      ; 2. Zeichen der Disketten ID
    LDA #$4A      ; "J"
    STA $0300,Y   ; 2. Zeichen der Disketten ID "J"
                  ; in den aktuellen Vorspannblock schreiben
;-------------------------------------------------------------------------------
    INY           ; Y + 1
;    LDA $12      ; 1. Zeichen der Disketten ID
    LDA #$4C      ; "L"
    STA $0300,Y   ; 1. Zeichen der Disketten ID "L"
                  ; in den aktuellen Vorspannblock schreiben
;-------------------------------------------------------------------------------
    INY           ; Y + 1
    LDA #$0F      ; Akkumulator = $0F
    STA $0300,Y   ; $0F in den aktuellen Vorspannblock schreiben
    INY           ; Y + 1
    STA $0300,Y   ; $0F in den aktuellen Vorspannblock schreiben
    INY           ; Y + 1
;-------------------------------------------------------------------------------
; Anfang - Prüfsumme berechnen
;-------------------------------------------------------------------------------
    LDA #$00      ; Akkumulator = $00
    EOR $02FA,Y   ;
    EOR $02FB,Y   ;
    EOR $02FC,Y   ;
    EOR $02FD,Y   ;
    STA $02F9,Y   ;
;-------------------------------------------------------------------------------
; Ende - Prüfsumme berechnen 
;-------------------------------------------------------------------------------
    INC $1B       ; Sektorzähler + 1
    LDA $1B       ; Akkumulator = Sektorzähler
    CMP $43       ; Sektorzähler mit Sektorenanzahl ($13 = 19) vergleichen
    BCC L02       ; Verzweige bis alle 19 Vorspannblöcke angelegt wurden
;-------------------------------------------------------------------------------
    LDA #$03      ; Akkumulator = $03
    STA $31       ; Pointer to currently active buffer
                  ; $0300
    TYA           ; Akkumulator = Y
    PHA           ; Lege Akkumulatorinhalt auf den Stack
;-------------------------------------------------------------------------------
;    TXA          ; Akkumulator = X (X ist immer noch 0)
    LDA #$4B      ; 1541 FORMAT
    STA $0700     ; 
    LDX #$01      ; 1541 FORMAT
    TXA           ; Akkumulator = X
;-------------------------------------------------------------------------------
L03 STA $0700,X   ;
    INX           ; X + 1
    BNE L03       ;
    JSR $FE30     ; Convert header images in buffer #0 into
                  ; GCR form without the header ID code.
                  ; Data buffer #0 ($0300-03FF)
    PLA           ; Hole Akkumulatorwert vom Stack 
    TAY           ; Y = Akkumulator
    DEY           ; Y - 1
    JSR $FDE5     ; Loop to move .Y characters in buffer #0
                  ; ($0300+) up 69 memory locations in RAM.
    JSR $FDF5     ; Load .Y with $44 (68)
    LDA #$07      ;
    STA $31       ; 31 = 07 (30 = 00) => $0700             
                  ; Pointer to currently active buffer
    JSR $F5E9     ; Calculate data block checksum
                  ; EOR the 256 data bytes. Return with the
                  ; checksum in .A
    STA $3A       ; Storage of data or header checksum
    JSR $F78F     ; Convert entire data buffer into GCR write image.
    LDA #$00      ; Akkumulator = $00
    STA $32       ; Zeiger zu den aktiven Werten in der Vorspanntabelle
    JSR $FE0E     ; Clear (zero) bit 5 of the 6522's PCR2
                  ; ($1C0C). This forces CB2 low.
;-------------------------------------------------------------------------------
; Anfang - SYNC für Vorspannblock
;-------------------------------------------------------------------------------
L04 LDA #$FF
    STA $1C01
    LDX #$05
L05 BVC L05
    CLV
    DEX           ; X - 1
    BNE L05
;-------------------------------------------------------------------------------
; Ende - SYNC für Vorspannblock
;-------------------------------------------------------------------------------

;-------------------------------------------------------------------------------
; Anfang - Vorspannblock
;-------------------------------------------------------------------------------
    LDX #$0A
    LDY $32
L06 BVC L06
    CLV
    LDA $0300,Y   ; Daten ab $0300+
    STA $1C01
    INY           ; Y + 1
    DEX           ; X - 1
    BNE L06
;-------------------------------------------------------------------------------
; Ende - Vorspannblock
;-------------------------------------------------------------------------------

;-------------------------------------------------------------------------------
; Anfag - Lücke 1 (9 Bytes $55 $55 $55 $55 $55 $67 $55 $55 $67)
;-------------------------------------------------------------------------------
    LDX #$05
L07 BVC L07
    CLV
    LDA #$55      ; 5x $55 schreiben
    STA $1C01
    DEX           ; X - 1
    BNE L07
;-------------------------------------------------------------------------------
L08 BVC L08
    CLV
    LDA #$67      ; 1x $67 schreiben
    STA $1C01
;-------------------------------------------------------------------------------
    LDX #$02
L09 BVC L09
    CLV
    LDA #$55      ; 2x $55 schreiben
    STA $1C01
    DEX           ; X - 1
    BNE L09
;-------------------------------------------------------------------------------
L10 BVC L10
    CLV
    LDA #$67      ; 1x $67 schreiben
    STA $1C01
;-------------------------------------------------------------------------------
; Ende - Lücke 1
;-------------------------------------------------------------------------------

;-------------------------------------------------------------------------------
; Anfang - SYNC Datenblock
;-------------------------------------------------------------------------------
    LDA #$FF
    LDX #$05
L11 BVC L11
    CLV
    STA $1C01
    DEX           ; X - 1
    BNE L11
;-------------------------------------------------------------------------------
; Ende - SYNC Datenblock
;-------------------------------------------------------------------------------
    LDX #$BB      ; 255 - 187 = 68 mal
L12 BVC L12
    CLV
    LDA $0100,X   ; Daten ab $0100 + $BB = $01BB
    STA $1C01
    INX           ; X + 1
    BNE L12
;-------------------------------------------------------------------------------
    LDY #$00
L13 BVC L13
    CLV
    LDA ($30),Y    ; LDA ($30), Y lädt den Akkumulator mit dem Inhalt der
                   ; Speicheradresse (LSB= $30 ; MSB= $30+1)+Y. 
                   ; $30 $31 = $00 $07 => $0700
    STA $1C01
    INY            ; Y + 1
    BNE L13
;-------------------------------------------------------------------------------
; Anfag - Lücke 2 (8 Bytes $55 $55 $55 $55 $67 $55 $55 $67)
;-------------------------------------------------------------------------------
    LDA #$55
    LDX #$04      ; 4x $55 schreiben
L14 BVC L14
    CLV
    STA $1C01
    DEX           ; X - 1
    BNE L14
;-------------------------------------------------------------------------------
L15 BVC L15
    CLV
    LDA #$67      ; 1x $67 schreiben
    STA $1C01
;-------------------------------------------------------------------------------
    LDA #$55
    LDX #$02      ; 2x $55 schreiben
L16 BVC L16
    CLV
    STA $1C01
    DEX           ; X - 1
    BNE L16
;-------------------------------------------------------------------------------
L17 BVC L17
    CLV
    LDA #$67      ; 1x $67 schreiben
    STA $1C01
;-------------------------------------------------------------------------------
; Ende - Lücke 2
;-------------------------------------------------------------------------------
    LDA $32       ; Zeiger zu den aktiven Werten in der Vorspanntabelle
    CLC           ; Carry-Flag löschen
    ADC #$0A      ; Akkumulator + 10 
                  ; 10 Byte entspricht der Länge des Vorspanns
                  ; der Zeiger wird auf den nächsten Vorspann gesetzt
    STA $32       ; Wert wieder in $32 schreiben
    DEC $1B       ; Sektorzähler - 1
    BNE L20       ; Verzweigen bis alle 19 Sektoren geschrieben wurden
L18 BVC L18
    CLV
L19 BVC L19
    CLV
    JSR $FE00     ; Schreibmodus verlassen
    JMP $FD9E
    BRK

L20 JMP L04


Literatur[Bearbeiten | Quelltext bearbeiten]

Weblinks[Bearbeiten | Quelltext bearbeiten]

WP-W11.png Wikipedia: Kopierschutz
WP-W11.png Wikipedia: GEOS (8-Bit-Betriebssystem)

Quellen[Bearbeiten | Quelltext bearbeiten]



Artikel des Monats.gif Dieser Artikel wurde Artikel des Monats.
Mustread 32.gif Dieser Artikel wurde in die Liste der Lesenswerten Artikel aufgenommen.

C64-Wiki-Pokal2016.png
Dieser Artikel wurde Artikel des Jahres 2016.