Im Gegensatz zu modernen Computern war das Konzept eines Dateisystems in den Spektren nicht so. Dies bedeutet, dass für das Herunterladen von jedem Medientyp eine separate Implementierung erforderlich war und das Programm in den meisten Fällen nicht einfach vom Band auf die Festplatte kopiert werden konnte. In Fällen, in denen der Programmlader in BASIC geschrieben wurde, konnte er mit einer relativ einfachen Überarbeitung an TR-DOS angepasst werden. Die Situation wurde jedoch durch die Tatsache kompliziert, dass in vielen Spielen (sowohl mit Marken als auch mit Hacking) die Lader in Maschinencodes geschrieben waren und manchmal einen Kopierschutz enthielten.

Trotz des Vorhandenseins eines „magischen Knopfes“, der lediglich den Speicher des Computers vollständig entleerte und es ermöglichte, das Programm auf einer Diskette zu speichern, wurde von Experten in Betracht gezogen, Diskettenversionen von Spielen zu erstellen, wobei das ursprüngliche Startabbild und andere Attribute beibehalten wurden.
In diesem Artikel werde ich Ihnen erklären , wie Sie eine solche Anpassung am Beispiel des Pac-Man- Spiels durchführen, nämlich am Originalbild von Pac-Man.tzx .
Die Werkzeuge
Trotz der Tatsache, dass früher alle diese Arbeiten direkt auf dem ZX Spectrum ausgeführt wurden (ohne andere Optionen), werde ich das Spiel mithilfe des Emulators und der Befehlszeilenprogramme anpassen. Der Hauptgrund ist, dass der Anpassungsprozess insbesondere zunächst aus einer großen Anzahl von Versuchen und Irrtümern besteht und bei Automatisierung viel weniger schmerzhaft verläuft. Gleiches kann direkt auf dem Spektrum erfolgen.
Im ersten Teil werden wir die folgenden Werkzeuge verwenden:
- Sicherungsemulator zum Debuggen und Testen.
- SkoolKit zum Zerlegen.
Deaktivieren des Starts im Bootloader
Da die Bild- und Datendatei ohne Headerblock heruntergeladen wird (17 Byte mit Name und Dateityp), bedeutet dies, dass der Loader in Maschinencodes geschrieben ist. Sie müssen herausfinden, wo sich diese Codes befinden und von welcher Adresse aus sie gestartet werden.
Es gibt verschiedene Möglichkeiten, den Bootloader-Code anzuzeigen:
Am einfachsten ist es, das Programm herunterzuladen, auf den Start des Bootloaders zu warten und es durch Drücken der Leertaste zu stoppen. In vielen Fällen funktioniert dies, aber im Fall von Pacman führt dies wie in vielen anderen Fällen zu einem Zurücksetzen.
Der nächste Weg ist das Laden des Programms mit MERGE ""
anstelle von LOAD ""
. Im Gegensatz zu LOAD
ignoriert MERGE
die Programmautorun. Im Fall von Pac-Man führt das Booten über MERGE
dass der Computer mit einer charakteristischen Verschiebung des linken Bildschirms einfriert. Dies liegt daran, dass MERGE
das Programm nicht zeilenweise ausführt, sondern versucht, es vollständig zu analysieren und mit dem bereits geladenen Programm zusammenzuführen. Wenn das Programm jedoch einen Block mit Maschinencodes hat, der gegen die Syntax des Programms verstößt, führt dies zu einem Absturz.
Wenn Sie sich nicht den listbasic
zerbrechen möchten, können Sie das Bandabbild von TZX in TAP konvertieren und das mit Fuse listbasic
Dienstprogramm verwenden:
$ tzx2tap Pac-Man.tzx $ listbasic Pac-Man.tap 1 RANDOMIZE USR (PEEK 23635+256*PEEK 23636+91)
Die Adresse 23635
( $5C53
) entspricht der PROG
Systemvariablen, die die Startadresse des BASIC-Bereichs enthält. Somit ist der Einstiegspunkt zum Bootloader gegenüber dem BASIC-Bereich um 91 Bytes versetzt.
Eine andere Möglichkeit, den Bootloader zu betrachten, ist im Artikel Desativando a autoexecução de um programa BASIC beschrieben . Im Fuse-Debugger müssen Sie einen Haltepunkt br 2053
festlegen, das Programm laden und nach Abschluss des Downloads und Beendigung der Codeausführung den set 23619 128
ausführen. Dadurch wird verhindert, dass das Programm gestartet wird, und Sie können BASIC beenden.
Demontage des Bootloaders
Wenn Sie die Verschiebung des Einstiegspunkts relativ zum BASIC-Bereich kennen, können Sie seine absolute Adresse berechnen. Beim ZX Spectrum 48K ohne geladenes TR-DOS beginnt der BASIC-Bereich bei 23755
( $5CCB
). Folglich startet der Bootloader bei 23755 + 91 = 23846
( $5D26
).
Um zu beginnen, setzen Sie einfach einen Haltepunkt an die Startadresse und sehen Sie sich die Maschinencodes an. In Fuse können Sie br 23846
und mit dem Herunterladen des Programms beginnen. Sobald der Bootloader ausgeführt wird, stoppt der Emulator:

Wenn der Loader sehr einfach ist, sehen Sie sich einfach den zerlegten Code im mittleren Bereich an und verstehen Sie, was geladen wird. Normalerweise sieht der Download-Code für eine Datei ohne Header ungefähr so aus:
LD IX, $8000 ; LD DE, $4000 ; LD A, $FF ; CALL $0556 ; LD-BYTES JP $8000 ;
In einem komplexeren Fall mit Codeausführung müssen Sie die Schritte verstehen und Notizen machen. Die SkoolKit Utility Suite ist dafür gut geeignet. Wenn Sie sich ein Ziel setzen, kann das Spiel mit seiner Hilfe bis zur letzten Schraube (Nachricht, Sprite, Sound) analysiert werden. Wie dies gemacht wird, wird in der Dokumentation ausführlich beschrieben.
Kurz gesagt, gehen Sie wie folgt vor:
Pac-Man.z80
mit tap2sna.py
oder den Emulatorfunktionen einen Schnappschuss des Pac-Man.z80
Computerspeichers.- Erstellen Sie eine
Pac-Man.ctl
Steuerdatei mit einer ersten Anleitung zum Zerlegen:
i 16384 Ignore for now c $5D26 Loader
- Führen Sie die Demontage aus:
sna2skool.py -H -c Pac-Man.ctl Pac-Man.z80 > Pac-Man.skool
. - Fügen Sie der Lerndatei neue Anweisungen und Kommentare hinzu, während Sie den Code studieren.
- Wiederholen, bis alles vollständig erleuchtet ist.
Als Ergebnis erhalten wir nach dem ersten Durchgang Folgendes (meine Kommentare, Adressen werden weggelassen):
ORG $5D26 ; 23846, ; DI IM 1 ; LD D, IYh ; LD E, IYl ; LD B, $25 ; EX DE, HL ; LD DE, $0019 ; ADD HL, DE ; HL $5C53 ( PROG) LD E, (HL) ; PROG DE IX INC HL ; LD D, (HL) ; LD IXh, D ; LD IXl, E ; LD A, (IX+$7F) ; ( $7F- ; PROG) LD HL, $0035 ; ($35 PROG) ADD HL, DE ; PUSH HL ; XOR (HL) ; LD (HL), A ; INC HL ; DJNZ $5D43 ; AND (HL) ; RET NZ ; ; DEFB $77
Bootloader-Entschlüsselung
Alles, was wirklich wichtig ist, ist, dass sich der entschlüsselte Bootloader bei PROG + $35
. Dies bedeutet, dass, wenn wir einen Haltepunkt auf br 23808
, zu diesem Zeitpunkt die Entschlüsselung abgeschlossen ist, wir den entschlüsselten Bootloader sehen:

Dieses Programm ist dem oben erwähnten typischen Fall bereits viel ähnlicher. Der Wert $4000
( 16384
) wird in die Register IX
und DE
geladen, etwas anderes wird getan und die Steuerung wird bei $055A
an die ROM-Routine $055A
(dies ist einige Bytes niedriger als der Standardeintrittspunkt in LD-BYTES
). Es scheint, dass dieser Ansatz eine Art Kopierschutz implementiert, weil Die Standardprozedur lädt diese Datei nicht und einige Kopisten verstehen sie nicht.
Programmeinstiegspunkt
Es bleibt abzuwarten, wie das Programm nach dem Laden aufgerufen wird. Anstelle der üblichen CALL LD-BYTES
und JP
werden hier LD SP, XXXX
und JP LD-BYTES
verwendet. Die erste (übliche) Option funktioniert wie folgt:
CALL
schiebt den aktuellen Wert des Software-Zählers ( PC
) auf den Stapel.- Die Steuerung wird an die aufgerufene Routine übergeben.
- Bei der Rückkehr von einem Unterprogramm (
RET
) wird der Wert vom Stapel entfernt und es erfolgt ein Übergang zum aufrufenden Programm.
Warum wird es hier anders gemacht? Tatsache ist, dass Pac-Man mit dem ZX Spectrum 16K kompatibel ist und absolut den gesamten RAM belegt (siehe Dateigröße oben). Daher überschreibt sich das Programm beim Laden sowohl den Loader als auch den Stack, wo immer sie sich befinden. Wenn wir mithilfe des Stacks vom ROM zum Bootloader wechseln und dann das heruntergeladene Programm über JP
aufrufen möchten, gibt es zum Zeitpunkt des Downloads weder eine Speicheradresse, in der sich JP
befindet, noch die Anweisung selbst.
Stattdessen bewegt sich der Stapelzeiger in den Speicherbereich, in dem nach dem Laden die Adresse des Einstiegspunkts in das Programm angezeigt wird, und der Prozessor, der das Spoofing nicht bemerkt, entfernt es mit dem neuen Zeiger vom Stapel und wechselt zur angegebenen Adresse.
Das vollständige Demontageergebnis kann im Projekt-Repository auf dem Github angezeigt werden.
Insgesamt
Als Ergebnis des Studiums des Bootloaders haben wir Folgendes herausgefunden:
- Eine Datei ohne Header mit einer Länge von 16384 Bytes wird bei 16384 heruntergeladen (im Bildschirmbereich, der im Allgemeinen während des Downloadvorgangs offensichtlich ist).
- Am Ende des Downloads befindet sich der Stapelzeiger bei
$5D7C
, wo die Steuerung übertragen wird.
In den folgenden Abschnitten werde ich darüber sprechen, wie Sie Dateien für das Schreiben auf die Festplatte vorbereiten und einen Monoblock-Datei-Loader in Assembler schreiben.
Verwandte Links:
- Profil "TRUB Spectrumist".
- Reverse Engineering von ZX Spectrum (Z80) -Spielen .
- Adaptação de jogos de fita für Beta 48 .