Crystals-DSA-Foren
Reverse Engineering der NLT II - Druckversion

+- Crystals-DSA-Foren (https://www.crystals-dsa-foren.de)
+-- Forum: Allgemeines zur Nordlandtrilogie DOS (https://www.crystals-dsa-foren.de/forumdisplay.php?fid=20)
+--- Forum: Technische Werkstatt (https://www.crystals-dsa-foren.de/forumdisplay.php?fid=34)
+--- Thema: Reverse Engineering der NLT II (/showthread.php?tid=5383)

Seiten: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16


RE: Reverse Engineering der NLT II - gaor - 17.01.2021

Ich würde eigentlich davon ausgehen, dass Henne von GitHub per Mail über deinen PR benachrichtigt wird. Er hat sich hier im Forum und dort auf GitHub länger nicht mehr blicken lassen, was ja auch irgendwie okay ist, denke ich. Das schöne an git sind ja die Forks, deshalb kannst du zum Glück einfach erstmal ohne Einschränkungen an deinem Fork weiterarbeiten.

Vielleicht findet ja Henne doch nochmal irgendwann die Zeit, deine Änderungen zu übernehmen, oder vielleicht entscheidet er sich ja auch an irgendeinem Punkt, dir oder jemand anderem Schreibrechte für das Repository zu übertragen.

Könntest du vielleicht zu dem Compiler-Problem ein Issue auf GitHub eröffnen? Ich finde, dort kann man leichter Referenzen zum Code einbinden und mit dem GitHub-Markdown übersichtlicher über solche Dinge sprechen. Dazu wäre interessant zu wissen, welcher Commit genau das Problem auslöst und welche Umgebung (Compiler-Version etc.) du benutzt.


RE: Reverse Engineering der NLT II - cmfrydos - 17.01.2021

Fände es auch interesaant zu wissen, wie es mit dem Projekt weitergeht.
Habe selbst mal etwas mit dem Code gespielt, aber es wäre hilfreich jemanden zu haben, der ein paar ToDo's für den Einstieg vorschlagen kann, um sinnvoll dem Projekt beizutragen.

Zu dem Abbruch im Makefile habe ich nur die Idee, da zuvor nur Warnungen ausgespuckt wurden, dass hier evtl Warnungen als Fehler gewertet werden, um den Code sauber zu halten? Nur so als Idee, weil normalerweise syntaxfehler o ä vom Compiler mit Zeilennummer angegeben werden.


RE: Reverse Engineering der NLT II - gaor - 17.01.2021

Hennes letzter Stand zur Roadmap ist schon etwas veraltet: https://www.crystals-dsa-foren.de/showthread.php?tid=700&pid=151240#pid151240

Ich hatte seitdem in mehreren Posts versucht zusammenzufassen, wo wir stehen und wo wir hin wollen oder könnten:
https://www.crystals-dsa-foren.de/showthread.php?tid=5383&pid=156661#pid156661
https://www.crystals-dsa-foren.de/showthread.php?tid=5383&pid=156683#pid156683
https://www.crystals-dsa-foren.de/showthread.php?tid=5383&pid=156702#pid156702
https://www.crystals-dsa-foren.de/showthread.php?tid=5383&pid=156719#pid156719
https://www.crystals-dsa-foren.de/showthread.php?tid=5383&pid=156801#pid156801
https://www.crystals-dsa-foren.de/showthread.php?tid=5383&pid=160895#pid160895
https://www.crystals-dsa-foren.de/showthread.php?tid=5383&pid=160898#pid160898


RE: Reverse Engineering der NLT II - siebenstreich - 18.01.2021

Vielen Dank für eure Antworten.

Ich bin noch neu bei git und habe in meinem Fork sukzessive immer größeren Mist gebaut.
Deswegen die Reißleine gezogen und alles nochmal neu gemacht. Damit ist das Compiler-Problem jetzt weg! Und die Commits sehen nicht mehr so chaotisch aus.

Hier der Link zum neuen Pull-Request.


RE: Reverse Engineering der NLT II - siebenstreich - 18.01.2021

Ich habe jetzt endlich mal BrightEyes ausprobiert. Der Geschwindigkeitsunterschied verglichen zur normalen Dosbox ist schon beeindruckend. Das Laufen mit den Pfeiltasten fühlt sich viel flüssiger an. Und die Logging-Ausgabe auf der Konsole ist natürlich der Wahnsinn. Wobei ich mich frage, warum beim Verlassen des Zeughauses die Meldung "Gegner (0x52) zum ersten mal besiegt" kommt.

Ein Problem habe ich allerdings: Ich kann die Maus in der BrightEyes-Dosbox nicht zur Mitarbeit bewegen. Wenn ich innerhalb des Fensters klicke, dann wird ja normalerweise die Maussteuerung an die Dosbox übergeben; mit Ctrl+F10 kriegt man den Mauszeiger wieder frei. Aber mit der BrightEyes-Dosbox klappt das nicht. Ein wenig habe ich mitt der Tastatur gespielt. Aber damit komme ich nicht mehr weiter, sobald ich in einem Laden was einkaufen will. Zur Auswahl der Waren braucht man offenbar zwingend die Maus.

Kennt jemand das Problem mit der Maus und kann mir weiterhelfen? Ich bin ja immer noch auf der Fehlersuche und würde gerne die Logging-Ausgabe zum Debuggen hernehmen (mir also an gewissen kritischen Stellen einige Werte aus dem Speicher ausgeben lassen, die ich gerne wüsste).


RE: Reverse Engineering der NLT II - Alpha Zen - 19.01.2021

Man kommt garantiert auch ohne Maus in die Händlermenüs, allerdings weiß ich nicht aus dem Kopf, mit welcher Taste. Schon die F-Tasten durchprobiert?


RE: Reverse Engineering der NLT II - Alrik Alrikson - 19.01.2021

In der "normalen" DOS-Version wird das jeweilige Menü mit Ziffernblock "9" geöffnet.


RE: Reverse Engineering der NLT II - siebenstreich - 22.01.2021

Es geht nicht um das Öffnen der Menüs, sondern um die Auswahl der Waren, die ge- oder verkauft werden sollen. Das kriege ich ohne Maus nicht hin.


RE: Reverse Engineering der NLT II - Alrik Alrikson - 22.01.2021

Mit + und - (nicht Ziffernblock) kann man die Anzahl der Waren bestimmen, die jeweilige Ware aber auszuwählen ohne Maus habe ich auch nicht geschafft, trotz aller möglichen Tastenkombinationen. Vielleicht ist es tatsächlich nicht ohne Maus spielbar. Was aber seltsam wäre, denn ansonsten funktioniert alles ohne Maus - im Helden-Inventar kann man mit den Pfeiltasten und Enter die Gegenstände platzieren.


RE: Reverse Engineering der NLT II - gaor - 22.01.2021

Schick findet irgendwie beim Spielstart heraus, ob eine Maus angeschlossen ist oder nicht, und merkt sich das. Manche Tastatur-Funktionen sind nur aktiviert, wenn keine Maus angeschlossen ist. Dazu gehört auch die Warenauswahl beim Einkauf (select_with_keyboard in seg002).


RE: Reverse Engineering der NLT II - siebenstreich - 22.01.2021

ok, danke. Dann ist es bei mir (SCHICK.EXE via BrightEyes aus meinem Fork) wohl so, dass er zwar die Maus erkennt, diese dann aber nicht richtig funktioniert.
Ich sehe auch einen Mauszeiger, aber ich kann ihn nicht verschieben.

gaor, du bist doch ein BrightEyes Veteran: Hattest du schonmal solche Probleme mit BrightEyes? Liegt es irgendwie an der mittlerweile nicht mehr ganz aktuellen DosBox, die zugrunde liegt?


RE: Reverse Engineering der NLT II - gaor - 23.01.2021

Ich hatte solche Probleme bisher nicht, habe es aber auch länger nicht mehr probiert. Meine Vermutung würde jetzt auch dahin gehen, dass die alte DosBox-Version vielleicht nicht mehr so gut mit modernen Bibliotheken zusammenspielt. Aber eigentlich habe ich keine Ahnung.

Nachtrag: Ich habe es gerade mal wieder probiert: Die Maus wird nicht gefangen, aber wenn ich "autolock=false" in der dosbox-Konfigurationsdatei setze, funktioniert die Mausbedienung trotzdem. Habe jetzt das Problem auch in der DosBox-Community gefunden: https://www.vogons.org/viewtopic.php?f=31&t=62703 Hier gibt es auch einen Patch, damit es auch mit "autolock=true" funktioniert: https://sourceforge.net/p/dosbox/code-0/4177/ Hab den Patch auf Bright-Eyes angewandt und kann bestätigen, dass er funktioniert. Nach ein paar anderen Problemchen meinerseits funktioniert jetzt auch alles andere bei mir wieder, wie es soll. Finde toll, dass du die Arbeit an Bright-Eyes wieder aufnimmst :)


RE: Reverse Engineering der NLT II - siebenstreich - 23.01.2021

Danke, so schaut eine perfekte Antwort aus!

ich hatte ironischerweise 'autolock=true' ausprobiert, aber nicht 'autolock=false'. Mit letzterem geht die Maus tatsächlich, allerdings halt ohne "lock".
Den Patch habe ich eingebaut und damit geht wieder alles wie gewohnt.

So eine richtige Idee zu deinem Problem habe ich leider nicht.
SCHICK.EXE und SCHICK.DAT sind vermutlich an der richtigen Stelle? Nach dem Intro kommt bei mir die Frage, woher die Musik kommen soll, CD oder MIDI. Also etwas, was es im Original nicht gibt und in BrightEyes neu eingebaut wurde, in die Funktion read_sound_cfg() in seg002.cpp. D.h. im Umfeld davon müsste bei dir irgenwas hängen bleiben.


RE: Reverse Engineering der NLT II - wiese.hano - 24.01.2021

Ohne den Diskussionfaden über die Mausbedienung hier abbrechen zu wollen, ich habe mal eine Frage zu einem anderen Thema.
(22.03.2018, 20:38)Rabenaas schrieb: Das letzte mal, das Henne eine Statistik gepostet hat, fehlten 5 Funktionen für Binärkompatibilität. Außerdem schließt sich die komplette Phase 2 an, bevor es an die Portierung geht. Jedenfalls ist das mein Eindruck. :think:

Stimmt es, dass die Binärkompatibilität inzwischen hergestellt ist? Was muss/musste getan werden, um diese zu erreichen? Über eine kurze Erklärung würde ich mich freuen, weil ich mir das nicht so richtig vorstellen kann.

Was Binärkompatibilität bedeutet, weiß ich im Prinzip. Aber wie erreicht man sie?


RE: Reverse Engineering der NLT II - siebenstreich - 24.01.2021

Am Anfang ist die SCHICK.EXE, also das von Attic ausgelieferte Spiel in Maschinencode (aka Binärcode). Das ist der Code, in dem der Prozessor denkt, aber für Menschen ist er sehr kompliziert zu lesen und zu verstehen. Henne und andere haben die unglaubliche Leistung vollbracht, diesen Maschinencode in Quellcode in der Programmiersprache C zurückzuübersetzen. Außerdem hat Henne den originalen Compiler von Borland aufgetrieben, mit dem er (wie Attic damals) den C-Quellcode wieder in Maschinencode übersetzen kann.

Das Ziel ist nun, dass dabei genau die originale SCHICK.EXE wieder rauskommt. Das ist dann der "ultimative Beweis" (Worte von Henne) dafür, dass der erarbeitete C-Code äquivalent ist zum originalen. Der Programmcode ist in Funktionen unterteilt, so dass man die Äquivalenz Funktion für Funktion durchtesten kann. Und dabei gibt es wohl noch 5 Funktionen, wo noch nicht exakt der originale Binärcode rauskommt.

Das ist aber wohl unerheblich, weil es sich nur um eine verdrehte Reihenfolge von ein paar Befehlen handelt, auf die es eigentlich nicht ankommt. So habe ich das zumindest verstanden. D.h. wir haben jetzt im Wesentlichen einen korrekten Programmcode in C. Dieser sieht aber noch unnötig kompliziert aus und viele Bezeichner haben nichtssagende Namen. Die weitere Aufgabe besteht also u.a. erstmal darin, den Code zu verstehen und zu kommentieren, und den Bezeichnern treffende Namen zu geben. Daran versuche ich mich momentan ein wenig.


RE: Reverse Engineering der NLT II - wiese.hano - 24.01.2021

(24.01.2021, 12:45)siebenstreich schrieb: Henne und andere haben die unglaubliche Leistung vollbracht, diesen Maschinencode in Quellcode in der Programmiersprache C zurückzuübersetzen.

Wo ist das Problem? Wurde der Code in C-Code übersetzt, müsste sich doch ohne Weiteres (durch Compilieren) der Binärcode wieder herstellen lassen.

(24.01.2021, 12:45)siebenstreich schrieb: Der Programmcode ist in Funktionen unterteilt, so dass man die Äquivalenz Funktion für Funktion durchtesten kann.

Wie sieht so ein "Durchtesten" aus? Kann man denn einzelne Bereiche des Binärcodes isolieren, einzelne Bereiche des C-Codes übersetzen und dann beides miteinander vergleichen? Braucht man vielleicht BrightEyes dafür?

(24.01.2021, 12:45)siebenstreich schrieb: Die weitere Aufgabe besteht also u.a. erstmal darin, den Code zu verstehen und zu kommentieren, und den Bezeichnern treffende Namen zu geben.
Wenn du Lust hast, kannst du ja mal beschreiben, wie du dabei vorgehst, bzw. welche Handlungen notwendig waren/sind, um dich dazu in die Lage zu versetzen, das zu tun. Ich kann mir das nur schwer vorstellen.


RE: Reverse Engineering der NLT II - gaor - 24.01.2021

(24.01.2021, 13:26)wiese.hano schrieb: Wo ist das Problem? Wurde der Code in C-Code übersetzt, müsste sich doch ohne Weiteres (durch Compilieren) der Binärcode wieder herstellen lassen.
So einfach ist das nicht. Nur weil zwei C-Quellcodes exakt das gleiche tun, heißt es nicht, dass der Compiler sie auch in den gleichen Maschinencode übersetzt. Und umgekehrt gibt es auch mehrere verschiedene C-Quellcodes, die beim Kompilieren den gleichen Maschinencode ergeben. Fakt ist, dass wir C-Code haben, der exakt das tut, was die SCHICK.EXE tut. Aber wenn man kompiliert, kommt etwas heraus, das im Maschinencode leicht vom Original abweicht (tut aber effektiv das gleiche), weil der Compiler irgendwelche "Optimierungen" vornimmt. Glücklicherweise sind das aktuell nur noch 5 Funktionen, die solche Abweichungen aufweisen.



(24.01.2021, 13:26)wiese.hano schrieb: Wie sieht so ein "Durchtesten" aus? Kann man denn einzelne Bereiche des Binärcodes isolieren, einzelne Bereiche des C-Codes übersetzen und dann beides miteinander vergleichen? Braucht man vielleicht BrightEyes dafür?
Genau, man kann einzelne C-Quellcode-Dateien getrennt voneinander kompilieren. In Bright-Eyes sind die nötigen Befehle bzw. Skripte dafür enthalten. Aber der Compiler selbst (BCC.EXE) ist nicht in Bright-Eyes enthalten, weil er proprietär lizensiert ist.


RE: Reverse Engineering der NLT II - wiese.hano - 24.01.2021

Nehmen wir an, wir haben eine Datei, die compiliert wird, wie vergleicht ihr die dann mit dem original Code, der ja sicherlich nicht in Bruchstücken, je nach Datei, vorliegt, sondern monolithisch als Ganzes. Wie lassen sich dort Teile isolieren und mit dem compilierten Code vergleichen? Kann man einzelne Bereiche des originalen Binärcodes getrennt vom Rest auswerten?


RE: Reverse Engineering der NLT II - gaor - 24.01.2021

Zum Vergleich wird der Maschinencode der kompilierten Dateien mit einem Disassembler (ndisasm) in Assembler-Instruktionen übersetzt. Hier ist das Skript, das kompiliert und vergleicht: https://github.com/Henne/Bright-Eyes/blob/bright_eyes/src/custom/schick/rewrite_m302de/tools/bc_ready.sh

Achso die original SCHICKM.EXE muss vor der Ausführung des Vergeichskripts einmalig dekompiliert werden. Hier ist das Skript, das sich darum kümmert und noch ein paar Pointer ersetzt: https://github.com/Henne/Bright-Eyes/blob/bright_eyes/src/custom/schick/rewrite_m302de/tools/disassemble.sh


RE: Reverse Engineering der NLT II - siebenstreich - 25.01.2021

(24.01.2021, 13:26)wiese.hano schrieb:
(24.01.2021, 12:45)siebenstreich schrieb: Die weitere Aufgabe besteht also u.a. erstmal darin, den Code zu verstehen und zu kommentieren, und den Bezeichnern treffende Namen zu geben.

Wenn du Lust hast, kannst du ja mal beschreiben, wie du dabei vorgehst, bzw. welche Handlungen notwendig waren/sind, um dich dazu in die Lage zu versetzen, das zu tun. Ich kann mir das nur schwer vorstellen.

Ich habe den C-Quellcode von BrightEyes auf meiner Festplatte, schaue mir die einzelnen Dateien an und versuche zu verstehen. Angefangen hatte ich auf der Suche nach der Ursache eines Bug (eingefrorener Kampfbildschirm) mit der Datei seg038.cpp, in der der Algorithmus zur Wegberechnung im Kampf steht. Das wahr sehr mühselig. Man reimt sich langsam so sukzessive zusammen, was da wohl passiert, verwirft Theorien, stellt neue auf. Inzwischen ist schon eine gewisse Kenntnis von Querbeziehungen vorhanden (von einem Überblick will ich nicht sprechen), so dass es etwas leichter geht.

Ein ganz konkretes Beispiel:
Heute bin ich irgendwie im Quellcode zur Alchimie gelandet. Dort steht

Code:
if ((test_skill(hero, 0x20, host_readbs(r_ptr + 0x1a)) > 0)

Schlaue Menschen haben bereits die Bezeichner 'test_skill' und 'hero' vergeben (vorher dürften da zwei nichtssagende kryptische Bezeichner gewesen sein), so dass die Vermutung naheliegt, dass der in 'held' gespeicherte Held eine Talentprobe ablegt, wahrscheinlich (aufgrund des Kontexts) in Alchimie. Nachdem ich mittlerweile weiß, dass die Talente in der Datei 'commons.h' drinstehen, habe ich dort nachgeschaut und den Eintrag "TA_ALCHIMIE = 32" gefunden. Also steht 0x20 (das ist die Zahl 32 in Hexadezimal) tatsächlich wie vermutet für das Alchimie-Talent, und ich kann die Zeile wie folgt abändern:

Code:
if ((test_skill(hero, TA_ALCHIMIE, host_readbs(r_ptr + 0x1a)) > 0)

Das ist jetzt schon etwas besser lesbar. Und es ist letztlich genau das gleiche wie oben, weil TA_ALCHIMIE ja nur wieder für 32 steht. Die Frage ist, was soll das 0x1a (=26 in Dezimal) weiter hinten? r_ptr ist ein Zeiger auf das zu brauende Rezept. Ein Blick in die Funktion test_skill(...) zeigt, dass dort die Erschwernis/Erleichterung der Talentprobe angegeben wird. Also steht wohl 26 Positionen nach dem Beginn des Rezept-Blocks die Schwierigkeit des Rezepts. Weil ich nichts entsprechendes finden konnte, habe ich in der commons.c den Entrag "RECIPE_DIFFICULTY = 26" ergänzt, womit die Zeile jetzt als 

Code:
if ((test_skill(hero, TA_ALCHIMIE, host_readbs(r_ptr + RECIPE_DIFFICULTY)) > 0)

schreiben kann.