Speedran Legend of Zelda durch Manipulation des Spielspeichers
Der erste Teil von Legend of Zelda ist ein unsterblicher Klassiker. Ein gewöhnlicher Spieler braucht ein paar Tage, um es zu beenden, aber für die erfahrensten Speedrunner ist dies eine halbstündige Frage. Der sehr verwirrende und komplexe Fehler, der von Sockfolder geöffnet wurde, ermöglicht es dem Benutzer jedoch, beliebigen Code direkt aus dem Spiel auszuführen, um das Spiel in weniger als drei Minuten abzuschließen.Kurz gesagt geschieht dies wie folgt:- Geben Sie den Code auf dem Bildschirm zur Namenseingabe ein.
- Wir betreten den zweiten Kerker und pfeifen.
- Wir gehen zum Friedhof, wir nennen zehn Geister.
- Wir warten auf die notwendigen Bedingungen, pausieren das Spiel, wenn sich die Kreaturen an bestimmten Orten befinden.
- Machen Sie eine Pause, drücken Sie gleichzeitig A und B und fertig!
Ja, das ist großartig. Schauen wir uns nun genauer an, was im Spiel passiert und wie dieser erstaunliche Legend of Zelda-Fehler ausgeführt wird.
So verursachen Sie einen Fehler
Also geben wir zuerst den Code auf dem Namenseingabebildschirm ein. Dateinamen werden im Speicher gespeichert, und jedes Zeichen entspricht einem bestimmten Byte im Speicher. Wir geben Dateien seltsame Namen, weil wir tatsächlich die erforderlichen Bytes in den Speicher schreiben, der dann zu Assembler-Code wird. Es gibt nur zwei Einschränkungen:- Wir können mit nur drei Dateien arbeiten, dh das Programm kann nur 3 * 8 Zeichen = 24 Bytes enthalten.
- Wir müssen als erste fünf Zeichen einer der ZELDA-Dateien eingeben, wenn wir mit der zweiten Quest beginnen möchten.
Wir müssen mit der zweiten Suche aus einem Grund beginnen, den ich später erläutern werde. Wir rufen die erste ZELDA-Datei auf, da dieser Name am besten geeignet ist. Jetzt starten wir das Spiel. Bevor wir zum Friedhof kommen, unterscheidet sich unser Verhalten praktisch nicht vom üblichen Spiel. Die Hauptsache, die wir tun müssen, ist zu versuchen, nicht zweimal zu sterben. Mit "sterben" ist sowohl der Tod selbst als auch der häufige Übergang zum Menü gemeint. Sie werden anhand weiterer Erklärungen verstehen, warum dies so ist.
Nachdem wir die Pfeife bekommen haben, gehen wir zu diesem Friedhofsbildschirm, um den Fehler zu beheben. Der Fehler wird hier ausgelöst, da bei Verwendung der Pfeife aus dem Grabstein ein Objekt erstellt wird, das eine versteckte Treppe öffnet. Dies ist für das Auftreten eines Fehlers erforderlich. Und das alles ist auf die Einschränkungen von Sprites zurückzuführen. In Legend of Zelda kann der Bildschirm bis zu 11 Sprites gleichzeitig enthalten. Wenn Sie versuchen, ein 12. Sprite zu erstellen, können Sie dies im Spiel nicht tun. Um den Fehler zu reproduzieren, brechen wir die Überlaufgrenze und erstellen das 12. Sprite.
Wenn Sie das Pfeifobjekt erstellen, vergisst das Spiel zu überprüfen, wie viele Sprites zuvor auf dem Bildschirm waren. Wenn wir die maximale Anzahl von Sprites erstellt haben, wird daher ein Sprite außerhalb der Sprite-Tabelle erstellt, der Speicher wird überschrieben und es tritt ein unerwarteter Status auf.Ab dem Offset 350 befindet sich ein kleines Fragment im Speicher, in dem die Kennungen von elf Sprites gespeichert sind. Beim Laden des Bildschirms wird ein Sprite erstellt, beginnend mit einer Position mit dem kleinstmöglichen Versatz des Sprites. Dies bedeutet, dass Sprites nach einer Position mit einem minimalen Versatz suchen, beginnend mit dem Versatz 350 und darüber hinaus. Wenn ein Sprite erstellt werden soll, sucht das Spiel nach einem leeren Wert in der Sprite-Tabelle, um ihn durch die Sprite-ID zu ersetzen, und erstellt ihn so. Im Gegensatz zum Erstellen von Sprites beim Laden des Bildschirms sucht das Spiel beim Erstellen eines Sprites nach einer Position mit einem maximalen Versatz für das Sprite. Dies bedeutet, dass sie zunächst prüft, ob es möglich ist, an Position 10 (0A) ein Sprite zu erstellen. Wenn nicht, überprüft sie Position 9 (09), d.h. Offset 359 und so weiter. Wenn alle Sprite-Positionen besetzt sind, gibt das Spiel auf und erstellt kein Sprite.
Die Entwickler vergaßen jedoch, Grenzprüfungen durchzuführen, damit das Spiel beim Versuch, ein "Pfeif" -Objekt zu erstellen, "aufgeben" konnte, und das Spiel sucht weiterhin nach Bytes mit dem Wert 00 an einer Stelle außerhalb der Sprite-Tabelle, um dort die Objektkennung aufzuschreiben. Aber wo sucht sie zuerst nach dieser Bedeutung? Tatsächlich ist diese Tabelle Teil eines größeren Arrays, in dem Informationen zu Sprites gespeichert sind. Wenn die Pfeife am Anfang der Tabelle einen Platz zum Erstellen findet, beginnt sie am Ende des Arrays mit der Suche nach Positionen mit dem Wert 00.Auf dem Friedhofsbildschirm enthält dieses Fragment des Arrays Informationen zum aktuellen Status von Geisteraktionen. Lassen Sie uns nun über die Zustände von Geisteraktionen sprechen. Die auf dem Friedhof geschaffenen Geister bewegen sich zufällig. Dies liegt daran, dass ihre Handlungen durch Verhalten gesteuert werden, das durch ihren Handlungszustand bestimmt wird. Diese Aktionszustände können abhängig von den Aktionen des Geistes einen beliebigen Wert von 0 (00) bis 5 (05) haben. Sie werden am Ende eines Arrays geschrieben, das Informationen zu Sprites enthält.Im Allgemeinen entsprechen alle diese Aktionszustände einer Position in der Funktionstabelle, die die Aktionen von Geistern definiert. Da Zustände nur 6 Werte haben können, hat die Tabelle die Größe, die zum Speichern aller sechs Aktionen erforderlich ist. Hier entspricht der Aktionszustand 0 (00) der Beschleunigung des Geistes. Dies ist wichtig, da die Pfeife, wenn sie nach einem Ort sucht, an dem sie ihr Sprite erstellen kann, die erste im Speicher gefundene Position mit dem Wert 00 ausfüllt. Die Geisterbeschleunigung entspricht der Aktion 0, die im Code mit dem Wert 00 aufgezeichnet ist. Das Spiel betrachtet sie daher als leere Position und schreibt die Kennung darauf pfeifen 5E.
Dann versucht das Spiel, den Code an Position 5E der Tabelle auszuführen. Da die Tabelle jedoch nur Werte bis 05 enthält, führt das Spiel Junk-Daten als Code weit über die Tabelle hinaus aus. Wenn Sie alles richtig machen, führen uns die Junk-Daten zu dem Code, den wir mit den Dateisymbolen aufgezeichnet haben. Das Spiel geht an Zelda und wir gehen das Spiel durch.Damit der Fehler funktioniert, müssen wir jedoch den dritten Status der Aktion in der Tabelle beschädigen. Der dritte erstellte Geist muss also beschleunigt werden, und alle nachfolgenden Geister müssen andere Aktionen ausführen (deren Code nicht gleich 00 ist). Dies ist eine wichtige Information. Nun wollen wir sehen, was passiert, wenn wir einen Fehler ausführen.Fehlerausführung
Wenn wir alles richtig gemacht haben, versucht das Spiel, die Daten auf Position 5E der Tabelle auszuführen. Es beginnt ab dem Offset 602 als Codedaten zu lesen. Informationen, die mit dem Status der Link-Aktion verknüpft sind, werden im Offset 602 und 603 gespeichert, damit wir sie steuern können. Wenn Link steht, sind die Werte an den Offsets 602 und 603 00. Wenn wir jedoch die Taste B drücken, um die Pfeife zu verwenden, ist der Wert bei 602 10, und wenn wir A drücken, um das Schwert zu verwenden, ist der Wert bei 603 01.
Wenn wir beide Tasten gleichzeitig drücken, sind die benachbarten Daten 10 01. Das Spiel interpretiert diese Daten als BPL-Verzweigungsbefehl, um zum Offset 605 zu gehen und die darin enthaltenen Daten als Code auszuführen. Die Werte 605 und 606 sind 00, wenn unsere Gesundheit nicht zu niedrig ist, und 40, wenn unsere Gesundheit niedrig ist. Um das Spiel schnell zu bestehen, müssen diese Werte gleich 00 sein. Sie müssen also versuchen, die Gesundheit aufrechtzuerhalten, bis der Fehler behoben ist. Der Wert 00 entspricht dem BRK-Befehl (break). Da es hier nichts tut, müssen die Werte 00 sein und das Spiel, um den Code weiter auszuführen.
Da wir das Schwert verwendet haben, führt das Spiel weiterhin Anweisungen im nächsten ungeraden Byte aus. Die nächste Anweisung, die nicht BRK ist, befindet sich am Offset 08, aber da wir das Schwert verwendet haben, springt das Spiel darüber und führt den Code bei 09 und 0A aus. Der Wert in Byte 09 ist immer 10, was bedeutet, dass wir uns wieder mit dem BPL-Verzweigungsbefehl befassen. Bytes am Offset 623 (62E) beziehen sich auf Musik. Sie versucht, das Abspielen von Musik zu beschleunigen, springt aber manchmal zu niedrigeren Werten.Dies bedeutet, dass wir den Fehler auf ein bestimmtes Musikstück anwenden müssen, um ihn zu beheben. Wenn der Wert klein ist, haben wir die Möglichkeit, im Speicher in einen Bereich mit sich erheblich ändernden Werten zu springen. Sie ändern sich so zufällig, dass wir sie nicht in Echtzeit steuern können, um Anweisungen zu erhalten, denen das Spiel folgen muss. Daher wird der Übergang hier wahrscheinlich zu einem Stillstand des Spiels führen.
Nach diesen chaotischen Daten gibt es jedoch einen Bereich sicherer Daten. Deshalb werden wir versuchen, dorthin zu springen. Wir benötigen mehr Daten im 60A, um den unsicheren Bereich genau zu überspringen und zu den permanenten, sicheren Daten zu gelangen. Wenn wir dorthin gingen, ist alles in Ordnung. Bei Offset 630 gibt es jedoch einen Zähler für Links Tod. Wenn Link zweimal gestorben ist, ist dieser Wert 02, was eine Anweisung bildet und das Spiel stoppt. Deshalb ist es wichtig, dass Sie nicht zweimal sterben. Infolgedessen fahren wir mit dem Offset 638 fort, dem Anfang der Tabelle, in der die Dateinamen gespeichert sind. Wenn wir hier ankommen, führt das Spiel den Code aus, den wir auf dem Dateibildschirm eingegeben haben. Und hier beginnt ...Code
Dateinamen werden der Reihe nach im Speicher gespeichert. Dies bedeutet, dass die ersten Bytes, die wir ausführen, eine Datei namens ZELDA sind. Glücklicherweise ist der von diesen Bytes ausgeführte Code sicher, so dass wir zum Rest übergehen können. Da der Name ZELDA nicht wichtig ist, schauen wir uns an, was der Rest des Codes tut. Zuerst führen wir drei PLP-Befehle aus (vom Stapel ziehen, vom Stapel ziehen). Wenn wir eine Funktion aufrufen, schreibt sie zwei Werte in den Stapel. Diese Werte entsprechen der Position, an der Sie sich im Code befanden, als Sie die Funktion ausgeführt haben. So kann das Spiel herausfinden, wo es nach Ausführung der Funktion zurückkehren kann.Wir beginnen mit dem Extrahieren von drei Werten aus dem Stapel und führen dann die Rückgabefunktion aus. Wir tun dies, um an den Ort zurückzukehren, an dem wir uns vor der Ausführung des Fehlers befanden. Andernfalls beendet das Spiel die Ausführung der Daten als Code nicht und friert infolgedessen ein. Bevor wir jedoch zu dem Code gelangen, der das Gedächtnis beschädigt und das Spiel beendet, müssen wir über einige weitere Werte sprechen.Die Werte am Speicheroffset 10 entsprechen der Nummer der Welt, in der wir uns befinden. Wenn wir uns in der oberirdischen Welt befinden, ist der Wert 00. Für den ersten Dungeon ist der Wert 01, für den zweiten - 02 und so weiter. Da sich Zelda im neunten Dungeon befindet, muss dieser Wert 09 sein. Wir machen jedoch einen Fehler in der oberirdischen Welt und der Wert ist 00. Wir müssen also einen Weg finden, ihn mit 09 gleichzusetzen. Der Wert bei Offset 11 entspricht einigen Daten über den Stand des Spiels. Wenn das Spiel geladen wird, ist der Wert 00, wenn das Spiel nicht geladen wird - 01. Wir müssen den neunten Dungeon laden, daher sollte dieser Wert 00 sein.Der Wert bei Offset 12 entspricht einem Teil des Zustands. Wenn der Bildschirm geladen wird, ist der Wert normalerweise 02, wenn er nicht geladen wird - normalerweise 05. Da wir den Dungeon laden möchten, sollte dieser Wert 02 sein.Der letzte Wert, den wir ändern möchten, entspricht der Quest, in der wir uns befinden. Der Wert bei Offset 62D entspricht der ersten oder zweiten Quest und hat den Wert 00 oder 01. Wir haben mit der zweiten Quest begonnen, möchten aber mit der ersten Quest enden, da wir das Spiel auf diese Weise verwirren. Daher müssen wir diesen Wert auf 00 ändern. Dies versetzt uns in eine seltsame Mischung aus erster und zweiter Quest. Wir benötigen diesen Hybridzustand, um Code für einen bestimmten Zweck auszuführen. Wir werden es uns ansehen, wenn wir erklären, was der Code tut.
Nun, wir setzen uns Ziele, gehen wir zum Code über. Erstens haben wir die LSR-Funktion (logische Verschiebung nach rechts) für Offset 11. Diese Funktion teilt den Wert in zwei Hälften und schreibt den Rest in den Übertrag. 11 ist eine Stelle im Speicher, die den Wert speichert, der dem Status des Spiels entspricht, und vor dieser Anweisung ist sein Wert 01. Wenn wir durch zwei teilen, erhalten wir 00 mit dem Rest 01, da die Division eine ganze Zahl ist. Bei Offset 11 wird der Wert 00 geschrieben und bei der Übertragung 01.Dann haben wir die ROX-Funktion zum Verschieben von 0D (links, links drehen) mit dem Index X. Da wir den Aktionsstatus des dritten von uns erstellten Geistes überschrieben haben, ist X gleich drei. 0D + X ist 0D + 03, was hexadezimal 10 ist. Daher dreht sich diese Funktion bei Offset 10 nach links. Diese Funktion multipliziert den Wert bei Offset 10 mit 2 und addiert die Silbentrennung. Der Wert beginnt bei 0. Null mal 2 ist gleich 0 und 0 + 1 ist gleich 1, daher wird der Wert auf Offset 10 geschrieben.Jetzt wird die ROX-Operation erneut wiederholt, um 0D mit Index X zu versetzen. Der Wert von X hat sich nicht geändert, er ist immer noch drei. Daher ist dies eine weitere Drehung nach links bei Offset 10. 1 * 2 = 2, und da wir die Übertragung bereits verwendet haben, ist ihr Wert 0. 2 + 0 = 2, sodass der Wert 2 in Offset 2 geschrieben wird.Als nächstes haben wir die dritte ROX-Operation für den Offset 0D. 2 * 2 = 4 und 4 + 0 = 4, also wird der Wert 4 bei Offset 10 geschrieben.Der nächste Befehl ist LSR bei Offset 12. Wir beginnen mit dem Wert 5, also ergibt das Teilen durch zwei den Rest 1. 2 wird bei Offset 12 geschrieben und 1 - in der Übertragung.Dann dreht sich der letzte ROX bei Offset 10 nach links. 4 * 2 = 8. Der Übertragungswert ist 1, wir addieren ihn zum Produkt und erhalten 9.Die letzte Anweisung vor der Rückkehr ist eine logische Rechtsverschiebung bei Offset 62D. Der Wert hier ist 1, weil wir uns in der zweiten Quest befinden. Und da wir durch 2 geteilt haben, ist der Wert gleich 0. Also sind wir in den Hybrid-Quest-Modus gekommen.Jetzt führen wir die Rückgabefunktion aus und das Spiel aktualisiert die Werte seines Status mit den in unserem Code aufgezeichneten Werten. Damit ist der Fehler behoben und wir betreten Zeldas Zimmer. Wir kommen dorthin, weil die Hybridquest das Spiel verwirrt. Sie weiß nicht genau, wo sie Link platzieren soll. Und so befinden wir uns in Zeldas Zimmer, nachdem wir das Spiel bestanden haben.
Ich hoffe, dies hilft Ihnen zu verstehen, was im Legend of Zelda-Spiel vor sich geht, wenn Sie beliebigen Code ausführen und einen schnellen Spielfehler ausführen.Source: https://habr.com/ru/post/de398171/
All Articles