Willkommen im cgboard - classic games Forum! Deine gemütliche Retro Gaming Community. Besuche uns auch im Discord Chat.

[DOSBox] Monkey Island 2 - The Secrets of Disassembling
#1
Information 
7
Hallo zusammen,
bei meinem neuesten Projekt hatte ich eine spannende Reise in die Vergangenheit und wollte euch nun, nachdem ich es geschafft habe, darauf mitnehmen.
Es kann hier und da ein bisschen trocken werden aber das liegt in der Natur der Sache Smile

Worum geht es eigentlich
Nun, viele von euch dürften ja das hervorragende "Monkey Island 2 Ultimate Talkie" Projekt von u.A. @Andi kennen. Er schrieb mich eines Tages in Discord an und fragte mich, ob ich da nicht so ein paar Dinge für ihn bei dem Projekt "beheben" könnte die schon lange auf seiner Agenda stehen. Unter anderem:

In der DOS-Version:
  • Ein paar Texte bspw. wenn man die Lautstärke erhöht oder verringert sind unübersetzt
  • Beim Start hört man nur die Sprache und muss zuerst STRG+T drücken um das ganze auf deutsche Untertitel + Sprache zu stellen
  • Der Cursor blinkt zu schnell
"Klingt interessant" dachte ich mir, "Challenge Accepted!" und die Reise ging los.

Akt 1: Die Fühler ausstrecken
Da die ganze Sache mit Disassembling noch ziemlich neu für mich ist, musste ich mich an die Tools und das Prozedere erstmal gewöhnen und Informationen sowie Tools sammeln.
Also einfach erstmal die "MONKEY2.EXE" in Ghidra (ein ziemlich guter OpenSource Disassembler von der NSA) geworfen - Ernüchterung.

[Bild: mi14lczw.jpg]

Nur eine Funktion, ganz viel Daten - die Datei ist gepackt! Durch Zufall stieß ich auf ein Programm namens "SOURCER" welches einen generischen Unpacker mitbringt und die Datei entpacken konnte, sodass ich danach die echte EXE-Datei erhielt.


[Bild: mi2_unpwddik.jpg]

Ganz viel Code, ganz viele Funktionen und die gesuchten unübersetzten Texte. Punkt 1 kann man dann schon mal erledigen:
[Bild: mi3_unp2ibi85.jpg]

Danach machte ich mich auf die Suche nach Punkt 2.

Akt 2 - Die Suche nach Big Whoop ähh. der Stelle wo der Textmodus gesetzt wird
Der Punkt sollte sich als sehr schwierig herausstellen - ich wusste nämlich nicht wo ich anfangen soll. Erstmal zur Theorie.
  • Im Spiel kann man zwischen "Nur Sprache", "Sprache und Text" sowie "Nur Text" umstellen
  • Das Spiel startet immer im Modus "Nur Sprache"
Das Video zeigt wie das Spiel sich in der Ursprungsversion verhält:


So, wo fange ich an. Schon seit je her arbeitete ich mit Cheat Engine für diverse Dinge und dachte, versuch ich es einfach mal. Also habe ich DosBox-X (wegen integriertem Debugger) angeworfen und einfach mal den Speicher der DosBox nach Veränderungen durchsucht.




Was kann man in dem Video sehen?
  • Die Theorie dass der Textmodus im Speicher liegt war richtig, und der Wert dafür ist 0 (=Sprache), 1 (=Text und Sprache) oder 2 (= Nur Text) (die Suche danach hat aber wesentlich länger gedauert in der Praxis Big Grin )
  • Danach habe ich gesucht welcher Code an diese Stelle im Speicher schreibt
  • Wichtiges Learning hierbei: Der CPU Core muss auf "normal" stehen sonst ist das ganze Suchen und Debuggen sinnlos
  • Nach ein wenig try and error (das Video zeigt nur letztendlich die richtige Stelle) hab ich gesehen dass zweimal an die Stelle beim Start geschrieben wird
  • Zuerst die 2 (= nur Text) und danach die 0 (= nur Sprache)
  • Ich habe dann einen Breakpoint an die Stelle gesetzt damit die Ausführung pausiert und zusätzlich noch eine Bedingung gesetzt dass der Breakpoint nur halten soll wenn das SI-Register den Wert 0x2743C enthält (das ist ein Zeiger auf den Speicher wohin der Wert geschrieben werden soll)
  • Die Methode die ich gefunden hatte stammt nämlich von DosBox und ist nicht der echte Code, dazu später mehr
  • Beim zweiten Halten an der Stelle (wo er 0 gerne in den Speicher schreiben möchte) habe ich ihm den Wert "1" untergejubelt und siehe da: Das Spiel startet mit Text + Sprache!
Also war ich auf einem guten Weg... so dachte ich. Das lief bisher zu reibungslos und die Probleme fingen später erst richtig an.

Akt 3: Debuggen per DosBox

Nun ging es darum die Stelle im Code zu finden die dafür verantwortlich ist, den Text-Modus auf "Nur Sprache" zu setzen. Hierfür nutze ich den Debugger von DosBox-X und steppe so lange durch den Code bis der andere Debugger (von Cheat Engine) den Breakpoint auslöst.

Wie der Debugger aussieht, seht ihr hier:



Ich hatte nun die Stelle gefunden, der Code sieht wie folgt aus:

CALLF      FUN_28e0_0002  -> Initialisiert den SoundBlaster (ich konnte die Werte 220, 7 und 1 erkennen was die Adresse des SoundBlasters in DosBox ist)
ADD        SP,0x2 -> Unwichtig
OR        AX,AX -> Unwichtig, aber: AX enthält den Wert 0 wenn der SoundBlaster erfolgreich initialisiert wird
JNZ        LAB_26a4_031f -> Wenn AX den Wert > 0 enthält, springt er weg (dann war irgendwas kaputt)
MOV        word ptr [0x23f2],0x1 -> Unwichtig
MOV        [0x414c],AX -> Bingo - hier wird 0 in den Speicher geschrieben Yeah

So nun muss man das ganze noch irgendwie patchen.

Akt 4 - DOS und seine Tücken
Der schwierigste Part überhaupt ist das Speichermodell von DOS. Bei Windows haben wir durchgängig einen riesigen Block Speicher, wir können überall hinspringen, alles tutti. In Zeiten von 16GB+ Ram auch kein Problem.

Aber damals musste man sich was überlegen (wie ihr ja bestimmt alle wisst) da ein Programm häufig nicht ganz in den Speicher passt. Also gibt es unter DOS "Segmente" sodass man das Programm häppchenweise laden kann.

Das große Problem hierbei ist dass eine Adresse wie 19FE:2345 sich nicht so leicht auf eine phyische Adresse in der EXE-Datei übertragen lässt. Und am Ende des Tages muss ich ja die Bits und Bytes in der MONKEY2.EXE verändern.

Der Punkt hat mitunter am meisten Zeit gekostet und so ganz verstanden habe ich es immernoch nicht Big Grin

Akt 5 - Assembler und seine Tücken
Kurzer Exkurs: Ein sogenannter OpCode hat eine feste Länge, manche sind 2 Byte, manche 4, manche 6 oder gar 12 Byte lang.
Möchte man das Programm verändern muss man penibel darauf achten dass man das einhält. Wenn man irgendwo Bytes einfügt (und das Programm vergrößert) verschieben sich alle Bytes dahinter und das ist eine Katastrophe da die ganzen Adressen nicht mehr stimmen.

Nun der Code den ich verändern will ist dieser:
MOV        [0x414c],AX

Was ich brauche wäre sowas:
MOV        AX,0x1 <- Schreib 1 in das Register (= Text + Sprache)
MOV        [0x414c],AX <- Schreib 1 vom Register in den Speicher

Das blöde ist nur: Was ich benötige ist länger (6+6 Byte) als das was vorher da war (6 Byte). Also muss ich einen Trick anwenden. Dieser nennt sich: Code Cave.

Was ist ein Code Cave? Ein Code Cave ist "freier" (sprich leerer) Speicherbereich in den ich munter schreiben kann. Dort kann auch wesentlich mehr Code stehen als vorher da war. Viele Loader/Trainer etc. benutzen diese Technik.

Das Programm springt dann kurz mal woanders hin, tut Dinge die ich möchte, und springt dann wieder zurück:

[Bild: codecave200fmo.png]

Als ich dann eine passende Stelle gefunden und das mit der Sprungadresse korrekt gemacht hatte (siehe oben) funktionierte das mit Text + Sprache auch vom Start weg:



Akt 6 - Lessons learned
Das Speichermanagement unter DOS ist nach heutigen Maßstäben bestenfalls überholt, schlimmstenfalls eine Katastrophe aber mit den damaligen Mitteln ging es halt nicht anders.
Es war auf jeden Fall spannend sich da hinein zu fuchsen, zu sehen was die Interrupts machen (z.B. ganz am Anfang wird die DOS-Version überprüft), und und und.

Ich hoffe der Beitrag war nicht allzu trocken und ich habe viele Details rausgekürzt die vieeeeeeeeel zu theoretisch wären.

Jetzt gilt es den Patch zu testen und reifen zu lassen. Nur weil es in einer DosBox läuft heißt es nicht dass es überall funktioniert.

Akt 7 - Appendix
- Zum Cursor-Problem: Ich habe hierfür auch mal den Code von ScummVM angeschaut und es sieht so aus dass es eine Endlosschleife gibt die sich um die Aktualisierung des Cursor-States kümmert. Die Blinkrate hängt von der Geschwindigkeit des PCs ab, das lässt sich leider nur schwer beheben. Würde man es verlangsamen (das habe ich getestet) laufen die Animationen auch langsamer ab.

- Warum schreibt er erst "2" in den Speicher und danach "0": 2 (= nur Text) ist der Default und wenn keine Soundkarte vorhanden ist, wird eben nur Text angezeigt. Ganz einfach Smile

Euer GBuster Elefant
Zitieren
#2
0
Ich fand es sehr spannend, den Text zu lesen. Cheat Engine und Code Cave sind zwei interessante Konzepte, die ich mir merken werde.
Ich habe nach dem Lesen trotzdem noch das Gefühl, dass ich meilenweit davon weg bin, selbst mal so etwas hinzubekommen. Aber ich verstehe auch, dass man für eine ganz spezifische Fehlersuche nur schwierig ein Schritt-für-Schritt-Tutorial aufbauen kann. Dann wäre der Text jetzt 300 Seiten lang.

Vielen Dank für das Teilen der Schritte, lieber GBuster.
Zitieren
#3
0
Ich kann schon verstehen, daß einem der Ehrgeiz packt, auch die letzten Fragmente zu übersetzen, die sich wohl tief im Programmcode verbergen, nur erschließt sich mir der Sinn nicht so richtig.

Die Talkieversion von MI2 funktioniert einwandfrei. Das man in ScummVM im Menü einmal etwas umstellen muss  um die deutschen Texte zu bekommen (oder STRG+T in der Dosversion), ist kein Aufwand und der englische Text beim Lautstärke erhöhen/verringern stört doch nicht, weil nicht spielrelevant.

Also Aufwand/Nutzen steht eigentlich in keinem Verhältnis. Aber ich bin trotzdem beeindruckt von Deinem Ehrgeiz gBuster. ....und Deinem technischen Verständnis.
Zitieren
#4
1
(02.07.2023, 07:11)Commodus schrieb: Ich kann schon verstehen, daß einem der Ehrgeiz packt, auch die letzten Fragmente zu übersetzen, die sich wohl tief im Programmcode verbergen, nur erschließt sich mir der Sinn nicht so richtig.

Die Talkieversion von MI2 funktioniert einwandfrei. Das man in ScummVM im Menü einmal etwas umstellen muss  um die deutschen Texte zu bekommen (oder STRG+T in der Dosversion), ist kein Aufwand und der englische Text beim Lautstärke erhöhen/verringern stört doch nicht, weil nicht spielrelevant.

Also Aufwand/Nutzen steht eigentlich in keinem Verhältnis. Aber ich bin trotzdem beeindruckt von Deinem Ehrgeiz gBuster. ....und Deinem technischen Verständnis.

Kann ich verstehen. Ich selbst hatte mir eine Timebox gesetzt dass wenn ich keine wesentlichen Fortschritte erziele dann auch irgendwann abgebrochen hätte.
Aber:

Das grundsätzliche Wissen daraus kann man auf alles Mögliche anwenden, sei es zum Knacken eines Kopierschutzes, zum Übersetzen, um einen Entpacker für Ressourcen zu erstellen etc. Im Grunde genommen ging es mir um die Machbarkeit ansich Smile Natürlich verstehe ich (und das habe ich Andi auch zu denken gegeben) dass sicher 98% der Leute ScummVM zum spielen benutzen.

Auf der anderen Seite ist es meine Art Andi und wer auch immer daran mitgearbeitet hat meinen Dank auszusprechen - Monkey Island 2 war mein Einstieg in die Adventure-Welt, mein Aller-Aller-Allererstes Adventure und nicht nur das - das allererste Computerspiel an das ich Hand anlegen durfte Smile

Insofern haben ich und das Spiel eine ganz besondere Beziehung.
Zitieren
#5
0
Wow, das war wirklich interessant, GBuster! Bei mir ist es ohnehin so, dass ich total gerne den monatlichen Progress Report vom Emulator Dolphin lese und das hier schlägt in die gleiche Kerbe – ich liebe so etwas. Ich würde echt gerne auch in Zukunft mehr von deinen Projekten in dieser Weise erfahren (wenn Zeit und Lust da ist, versteht sich). Fröhlich

Dass wenige DOSBox/MS-DOS für die LucasArts-Klassiker verwenden ist mir bewusst (selbst Speedrunner benutzen für Monkey Island ScummVM), aber es gibt auch noch genug Puristen, die die Oldschool-Variante vorziehen und für die ist das hier ganz großes Kino. ^^

Vielen lieben Dank noch einmal dafür, dass du dir das näher angesehen hast. Ich weiß das wirklich zu schätzen – vor allem da ich weiß, wie viele Stunden du daran gearbeitet hast. <3

Das Testen übernehme dann ich. Ich bin gerade auch an MI1 dran und da ich gerne beide Teile perfekt aufeinander abstimmen möchte (und auf Return to Monkey Island ebenfalls, da gibt es nämlich auch einige Anspielungen), wird das Spiel noch sehr oft von mir durchgespielt (per ScummVM, DOSBox, PCem, 86Box, etc.).
Zitieren
#6
1
Kleines Update: Die Lösung mit dem Code Cave klang in der Theorie gut, funktionierte in DosBox-X auch ... aber dann leider in DosBox Staging nicht.

Der Hintergrund: Die Segmente (wie oben beschrieben) sind nie an der gleichen Stelle und es war mir jetzt zu hoch irgendwie in Erfahrung zu bringen wie ich das mit den Offsets hinbekomme. Vielleicht mal wann anders Smile

Ich hab es jetzt so gelöst dass der Modus IMMER auf Text+Sprache gestellt wird. Das scheint offenbar auch keine Probleme zu machen.
Zitieren
#7
0
Interessanter Beitrag
Zitieren
#8
0
Das mit der Code Cave klingt so einfach, wie genial. Aber ich selbst habe überhaupt keinen Durchblick bei sowas, ich verstehe da nur die von dir erklärte Theorie Smile
[Bild: gogc8jon.png] [Bild: switchi4j98.png] [Bild: opel29k8i.png]
In ewigem Gedenken an SonataFanatica... R.I.P., mein alter Freund  Sad
Zitieren


Möglicherweise verwandte Themen…
Thema Verfasser Antworten Ansichten Letzter Beitrag
  Tales of Monkey Island (TOMI) - Launcher uwecr 5 1.276 22.03.2022, 18:15
Letzter Beitrag: Heinrich Reich
  [ScummVM] ScummVM mitm Handy und Curse Of Monkey Island 3 DJ_Biohazard 5 3.062 12.12.2007, 19:17
Letzter Beitrag: DJ_Biohazard
  [Problem] Monkey Island 2 -=hilfe=- talisac 8 3.357 09.06.2005, 22:05
Letzter Beitrag: Anathos
  [Info] holiday island nachfolger? nurich 4 2.551 29.08.2004, 18:02
Letzter Beitrag: Scuzzlbutt
  Monkey Island 4 um 5 €, Media Markt AUT macidonni 2 1.532 03.06.2004, 18:53
Letzter Beitrag: Chris

Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 1 Gast/Gäste