Behebung eines Fehlers in einem 2000er-Spiel auf Shockwave

Bild

Einzelbyte-Ersetzungsverlauf


Cartoon Cartoon Sommer Resort


Es war Sommer 2000. Ich wurde sechs, habe gerade die erste Klasse abgeschlossen und die Ferien begannen. Dies bedeutete, dass ich lange auf der Straße spielen, Cartoons anschauen und den Computer meines Vaters mit Windows 98 einschalten konnte, um in einem völlig neuen, unbekannten Land namens Internet nach Spielen zu suchen. Einer meiner Favoriten war die Cartoon Network-Website. Darauf fand ich viele faszinierende Flash-Spiele, die auf Fernseh-Cartoons basierten. In diesem Sommer veröffentlichten sie eine Reihe von Spielen namens Cartoon Cartoon Summer Resort.


Gameplay der ersten Folge von Cartoon Cartoon Summer Resort

Dieses Spiel war ein zweidimensionales Rollenspiel / Abenteuer mit einer Draufsicht von der Seite, bestehend aus vier Folgen. Der Spieler kontrollierte eine Zeichentrickfigur im Urlaub im Resort mit anderen Zeichentrickfiguren. In jeder Episode trat im Resort ein Problem auf, das gelöst werden musste. Der Spieler musste es lösen, indem er mit den Charakteren interagierte und Objekte fand oder sie austauschte.

Ich gehe 18 Jahre zurück


Während eines der jüngsten Nostalgie-Angriffe erinnerte ich mich an dieses Spiel und erkannte, dass ich es wieder spielen würde. Sie war fast zwei Jahrzehnte alt, daher war es schwierig, eine funktionierende Verbindung zu finden.

Außerdem würde kein moderner Browser den alten und anfälligen Shockwave-Player starten ... außer Internet Explorer. Ich war wahrscheinlich die erste Person, die 2018 einen legitimen Grund für die Verwendung von Internet Explorer gefunden hat.

Nachdem ich ein wenig gespielt hatte, bemerkte ich Momente, die nicht ignoriert werden konnten. Zum Beispiel monotone Hintergrundmusik, die in einer Endlosschleife abgespielt wird, und schlechte Erkennung von Kollisionen.

Der gleiche Fehler


Nach einiger Zeit fand ich einen Fehler im Spiel:

Wenn Sie sich durch Bereiche bewegen, in denen nichts passieren sollte, wird manchmal ein Dialogfeld angezeigt.

Wie aus der Animation hervorgeht, können Sie im Spiel ein Boot mieten, um sich im Wasser zu bewegen. Wenn Sie versuchen, ein anderes Boot zu mieten, wird die Meldung "Heute gibt es keine gemieteten Boote mehr!" Angezeigt. Wenn Sie nach Norden segeln und am rechten Rand der Insel entlang gehen, wird jedoch derselbe Text geöffnet, der am Bootsanleger erscheinen sollte.


Zu diesem Zeitpunkt würde jeder gesunde Mensch, der seine Zeit und Energie respektiert, den Fehler als geringfügiges Ärgernis betrachten und sich daran erinnern, dass es sich um ein mittelmäßiges Webspiel für Kinder handelt, das vor zwei Jahrzehnten erstellt wurde und weiterhin gespielt wird. Aber nicht ich.

Ich besaß bereits alle meine Programmierkenntnisse und sah mir das Spiel an. Ich empfand diesen Fehler als seltsam attraktiv. Es schien mir, als hätte ich ein uraltes Grab entdeckt und darin ein unberührtes Rätsel gefunden, das hätte verschwinden können und das von niemandem gelöst wurde. Für mich war dieser Fehler eine Gelegenheit, etwas Neues zu lernen und zu entdecken. Interessanterweise gab mir genau diese Möglichkeiten der Prozess des Spiels selbst in meiner Kindheit. Es ist fast poetisch, wie etwas versehentlich neue Herausforderungen darstellen kann, wenn man es aus einem anderen Blickwinkel betrachtet.

Dekonstruktionsspiel


Um den Fehler zu beheben, musste ich die internen Abläufe des Spiels verstehen. Nachdem ich das Problem untersucht hatte, stellte ich fest, dass das Spiel auf Shockwave in der Director- Anwendung erstellt wurde. Bei der Arbeit mit Director werden Projekte als .dir (Director) -Datei gespeichert. Diese Datei ähnelt der PSD-Datei für Photoshop. So wie eine PSD-Datei zerstörungsfreie Informationen zu Ebenen und Text enthält, speichert ein .dir Projekt alle Ressourcen, den .dir und andere Informationen, die im Entwicklungsprozess .dir sind. Der Regisseur verwendete die proprietäre Skriptsprache Lingo , um Szenen zu animieren.

Wenn das Spiel in einer .dir Datei gespeichert wäre, könnte ich es einfach in Director öffnen und leicht lernen, wie das Spiel funktioniert. Das Spiel wird jedoch als .dcr Datei veröffentlicht. Die .dcr Datei ist eine kompilierte Version des Director-Projekts. Das heißt, der gesamte Quellcode wird in Bytecode kompiliert, der auf der Shockwave-Plattform ausgeführt wird. Dieser Vorgang ähnelt der Vereinfachung einer PSD-Datei und wird zu einem PNG-Bild. Das PNG-Bild (in unserem Fall die DCR-Datei) ist kleiner, enthält jedoch keine Informationen zu Ebenen und Bearbeitungen und ist nur zur Verteilung vorgesehen.

Dies bedeutete, dass ich ein 500-KB-Binärobjekt ohne Dokumentation seiner Struktur hielt. Selbst wenn ich herausgefunden habe, wie man Bytecode auf niedriger Ebene findet, scheint niemand den Lingo-Bytecode rückentwickelt und das Prinzip der Shockwave-Plattform dokumentiert zu haben. Alle diese Informationen sind urheberrechtlich geschützt und gehören Adobe, das keinen Grund hat, sie zu veröffentlichen. Die Chancen, das Spiel zu verstehen, standen eher schlecht.

Dekompression


Ich fühlte mich besiegt, weil ich diesen Fehler höchstwahrscheinlich nicht beseitigen konnte, und beschloss herauszufinden, ob Ressourcen irgendwie aus dem Spiel extrahiert werden könnten. Ich nahm an, dass es wahrscheinlich einen Abschnitt komprimierter Daten oder ähnliches finden würde. Nach der Suche fand ich einige Programme namens offzip und packzip . Diese Tools können in beliebigen Binärdateien nach zlib-Daten suchen, Offsets anzeigen und in separate Dateien extrahieren.

Ich habe offzip mit einer DCR-Datei ausgeführt und zu meiner Überraschung hat es die Archive wirklich gefunden! 249 Stück, um genau zu sein.

$ ./offzip.exe -a 1.dcr

- open input file: 1.dcr
- zip data to check: 32 bytes
- zip windowBits: 15
- seek offset: 0x00000000 (0)
+------------+-----+----------------------------+----------------------+
| hex_offset | ... | zip -> unzip size / offset | spaces before | info |
+------------+-----+----------------------------+----------------------+
0x00000026 . 164 -> 214 / 0x000000ca _ 38 8:7:26:0:1:7b6349f6
0x000000d3 .. 3932 -> 9169 / 0x0000102f _ 9 8:7:26:0:1:c1079d84
...
0x00080490 . 265 -> 472 / 0x00080599 _ 0 8:7:26:0:1:04d6b43f
0x00080599 . 209 -> 366 / 0x0008066a _ 0 8:7:26:0:1:7da3ba08

- 249 valid compressed streams found
- 0x0004040d -> 0x001565c8 bytes covering the 50% of the file


Ich extrahierte alle diese Dateien in einen Ordner und begann, die Ergebnisse zu studieren. Es gab 206 .dat Dateien, 38 .fff Dateien, 4 .atn und eine einzelne .ini Datei.


Entdeckungen


Ich habe mit der INI-Datei begonnen, aber sie hat nichts gebracht. Es war eine einfache Schriftkonvertierungstabelle aus Directory 7.0 zwischen Windows und Mac. Dann ging ich zu den DAT-Dateien über. Die meisten von ihnen waren 1 KB groß, also habe ich mit riesigen 144 KB angefangen. Ich öffnete es in einem Hex-Editor und studierte. Meist waren es unleserliche Daten. Im Laufe der Zeit fand ich jedoch ein paar Wörter in ihnen, die Lingo-Identifikatoren zu sein schienen.


Die Analyse der großen DAT-Dateien gab mir einige Hinweise, sie enthielten einige interessante Nachrichten. Ich fand, dass Photoshop 3.0 höchstwahrscheinlich für Grafiken verwendet wurde. Ich habe auch erfahren, dass das Spiel ein internes Kartenbearbeitungswerkzeug namens Map-O-Matic v1 . Ich würde gerne sehen, wie es aussah und erstellt wurde.

Ich fand auch den Namen der Firma, die das Spiel entwickelt: Funny Garbage . Der Name des Hauptentwicklers war ebenfalls in der Datei, aber ich werde ihn nicht benennen. Es war großartig, den Autor des Spiels zu entdecken, das ich nach fast 20 Jahren hartnäckig zu reparieren versuchte, und schließlich das Gesicht der Person zu sehen, die zur wahrscheinlichen Ursache dieser Qual wurde. All diese Informationskrümel waren natürlich interessant, aber sie halfen nicht viel.

Durchbruch


Dann fing ich an, .fff Dateien in einem Hex-Editor zu studieren. Zu meiner großen Überraschung waren alle Daten in diesen Dateien lesbar und sahen aus wie Kartendaten:


Ich habe einige dieser Daten manuell extrahiert und in einem Texteditor bereinigt. Was ich getan habe, war einem JSON-Array sehr ähnlich:

[
#member: "block.104",
#type: #FLOR,
#location: [16, 9],
#width: 64,
#WSHIFT: 0,
#height: 32,
#HSHIFT: 0,
#data: [
#item: [
#name: "",
#type: #WALL,
#visi: [
#visiObj: "",
#visiAct: "",
#inviObj: "",
#inviAct: ""
],
#COND: [[#hasObj: "", #hasAct: "", #giveObj: "sunscreen", #giveAct: "gotscreen"], #none, #none, #none]
],
#move: [#U: 0, #d: 0, #L: 0, #R: 0, #COND: 1, #TIMEA: 0, #TIMEB: 0],
#message: [
[#text: "You bought the sun screen.", #plrObj: "", #plrAct: ""],
[#text: "No more sunscreen today!", #plrObj: "", #plrAct: "gotscreen"]
]
]
]


Es war sehr wichtig, weil ich viel über die Funktionsweise des Spiels gelernt habe.

  1. Das Spiel erwartet, dass sich Karten-, Text- und Ereignisdaten in JSON-ähnlichen Lingo-Objekten befinden
  2. Jeder #member Eintrag ist eine #member Kachel, ein Block oder ein Zeichen.
  3. Koordinaten und #member können bearbeitet werden.

Da ich wusste, dass die Dialoge des Spiels in diesen Dateien gespeichert wurden, schrieb ich eine kurze Zeile, um nur einen Dialog in eine Datei zu exportieren:

grep -a -o '#text: "[^"]*' Uncompressed/*.fff | awk '{print $0,"\r"}' > Dialogue.txt

Mit dieser Datei kann ich den fehlerhaften Text schnell finden und sehen, in welcher Datei er sich befand:


Der fehlerhafte Text ist entweder in 0004eda0.fff oder in 0004f396.fff . In unserem Fall erschien der Fehlertext in der ersten Datei. Wir wissen das, denn gleich danach erhalten wir eine Nachricht, wenn wir mit Og interagieren, einem Charakter auf derselben Karte wie die Kachel mit dem Fehler.

Fehlerbehebung


Jetzt konnte ich 0004eda0.fff öffnen und die Zeile über das Boot im Hex-Editor finden. Nachdem ich es gefunden hatte, konnte ich das damit verbundene #member Objekt finden. Ändern Sie dann die Eigenschaften und speichern Sie die Datei. Dann habe ich es erneut komprimiert und mit packzip in die DCR- packzip .


$ ./packzip -o 0x0004EDA0 Uncompressed/0004eda0.fff test.dcr

Wenn ich den Blocktyp von Block block.11 in Block block.11 block.13 und das Spiel block.11 , block.13 ich deutlich den Umriss der Fehlerkachel:


Durch Ändern der Kachel-ID können Sie die Grenzen des Problembereichs anzeigen

Die Fehlerbehebung selbst ist lächerlich einfach. Ich musste #message die Kennung #message für diese Fehlerkachel in #fessage :


Wenn wir nun die Änderungen patchen und in diesen Bereich zurückkehren, werden die Meldungen nicht mehr angezeigt!


Es wurde ein Fehler im Spiel behoben, durch den buchstäblich 1 Byte geändert wurde

Warum kann der Fehler behoben werden?


Ich kann nur davon ausgehen, dass die Spiel-Engine wahrscheinlich das Plättchen überprüft, auf dem sie steht, wenn sich der Spieler bewegt. Wenn eine Bedingung erfüllt ist, wird die dieser Kachel entsprechende Nachricht aus dem Array #message . Nach dem Ändern von #message in #fessage Link zum #message Array, nach dem der Code sucht, nicht mehr gefunden. Er betrachtet dies als leeres (oder undefiniertes?) Objekt und zeigt nichts an.

Betrachten Sie ein Beispiel für JS:

 function foo(bar) { if (bar["message"] !== undefined) { // display the message } } 

Angenommen, wir können die Funktion foo() nicht ändern, aber wir müssen das Ergebnis ändern. Wir haben Zugriff auf die ihr übermittelten Daten. Sie können die message des übergebenen Objekts umbenennen, und die Funktion glaubt, dass es nicht vorhanden war.

Wie ist dieser Fehler aufgetreten?


Ich nehme an, wegen der Faulheit. Die Entwickler verwendeten einen Karteneditor, um diesen Bereich zu erstellen. Höchstwahrscheinlich haben sie vergangene Karten in neue Bereiche kopiert und sie dann geändert. Dies ist einfacher als alles von Grund auf neu zu erstellen. Da die Ereignis- und Textdaten jedoch gemischt sind, werden sie höchstwahrscheinlich an einigen Stellen übersehen und vergessen, sie zu löschen oder zu ersetzen. Dies sieht am logischsten aus, da der fehlerhafte Dialog häufig von einer benachbarten Karte übernommen wurde, auf der er korrekt verwendet wurde.

Warum so viel Arbeit für etwas so Bedeutungsloses ausgeben?


Weiß nicht. Vielleicht wegen Nostalgie?

Source: https://habr.com/ru/post/de425601/


All Articles