Themabewertung:
  • 2 Bewertung(en) - 3 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
Reverse Engineering der NLT II
Sagen wir es mal so: Ich konvergiere gegen eine native 64-Bit Version der SCHICKM.EXE.

"kurz" ist der relative Begriff für den Arbeitsaufwand, welchen ich hierfür betreiben muss.
Es wird erst released wenn es fertig ist.

Der Plan sieht folgendermaßen aus:
* Behilfsweise Zugriffe auf das Datensegment mittels globaler Variablen nativ machen. (Beendet, wenn die Werte von p_datseg, ds_read und ds_write 0 sind)
* Unstimmigkeiten an den Spielständen (Pointer) so hinbiegen, dass sie zukunftstauglich sind.
* ONLY-DOS-Code auskommentieren z.B. EMS, AUDIO-CD
* Grafik mit SDL2 einbinden (kann von GEN.EXE übernommen werden)
* Tastatur- / Maus mit SDL2 einbinden (kann von GEN.EXE übernommen werden)
* Dateieingabe portabel gestalten (SCHICK.DAT, *.CHR und Savegames)
* Dateiausgabe portabel gestalten (Savegames und TEMP/*)
* Binäräquivalenzcodedifferenz weiter gegen 0 gehen lassen, sodass ein binäräquivalentes DOS-Binary mit SDL-Anbau für moderne OS vorhanden ist.
* Musikausgabe wie bei GEN.EXE

Ab diesem Punkt sollte ein lauffähiges Programm vorhanden sein,
welches mit Sicherheit sehr häufig wegen mittlerweile erkennbaren Speicherzugriffsfehlern abstürzt.

Dann wird wie bei gen und gen_dos geforkt, d.h. es gibt einen Ordner schick_dos,
in welchem ich versuchen werde andere Versionen der SCHICKM.EXE/BLADEM.EXE nachzubauen um die Unterschiede der anderen Versionen in die Weiterentwicklung zu integrieren.
Dadurch wird die neue SCHICKM.EXE flexibler und kann hoffentlich mit verschiedenen Versionen der SCHICK.DAT betrieben werden.
Zitieren
Für Riva haben wir jetzt einen funktionierenden Tracer, der Stackframes und aktive Interrupt-Handler anzeigt und Aufrufe in Intervallen aufzeichnen sowie z. B. für Speedscope exportieren kann. Das macht die Arbeit so viel leichter :jippie: ! Allein in den letzten zwei Stunden konnte ich so über 40 Spielfunktionen identifizieren und annotieren.
Zitieren
@cmfrydos: Großartig! Bei größeren Projekten manchmal Abstand und neu justieren notwendig.
So kommen neue Ideen, man verhindert das frustrierende "sich in irgendetwas verrennen" und auf einmal läuft es.
Wie die alten Hasen hier im Forum wissen gab es bei Bright-Eyes/BrightEyes immer mal größere Pausen, was meinem RL geschuldet war.
Diese Zeiten waren notwendig um neu zu denken und zu überlegen, was das Beste für mich und dieses Projekt ist.

Zwischenstand:
* Binäräquivalenzcodedifferenz = 3778 Bytes
* auskommentierte Zeilen in der symbols.h = 95.2 %
* es kompilieren auch schon einige Dateien (105 / 110) mit dem GCC

Weitere Fortschrittswerte welche definitiv gegen Null gehen:
Code:
# p_datseg   : 87
# ds_read    : 63
# ds_write   : 43
# host_read  : 2561
# host_write : 607
# _ptr_      : 393
Zitieren
:thx: :jippie: :thx:
--------
Warnung! Geschichte kann zu Einsichten führen und verursacht Bewusstsein!
Avatar by: Keven Law (CC BY-SA 2.0)
Zitieren
Es gibt etwas zu feiern: Die direkten Lese- und Schreibzugriffe auf das "Datensegment" sind jetzt eliminert.

Die indirekten Zugriffe mittels dem Zeiger/Pointer p_datseg, werden anschließend mit dem Umsortieren der globalen Variablen entfernt.

@siebenstreich: Den Schiffsreise-Bug, welchen du mal bearbeitet hast, habe ich heute etwas untersucht.
Es gibt Schiffe mit einer Geschwindigkeit von 150 km/h.
Dieser Wert wird in einer Bit8s Variable gespeichert, welche fälschlicherweise den Wert -106 haben sollte.
Das ergibt im Sinne des Spiels keinen Sinn, muss aber erstmal wegen der Binäraquivalenzcodedifferenz so bleiben,
genauso wie alle anderen Fehler, welche der GCC und Clang anmeckern.


Zwischenstand:
* Binäräquivalenzcodedifferenz = 3708 Bytes
* auskommentierte Zeilen in der symbols.h = 96.1 %
* es kompilieren schon einige Dateien (108 / 110) mit dem GCC

Weitere Fortschrittswerte welche definitiv gegen Null gehen:
Code:
# p_datseg   : 62
# ds_read    : 0
# ds_write   : 0
# host_read  : 2527
# host_write : 596
# _ptr_      : 393
Zitieren
Zitat:Es gibt etwas zu feiern: Die direkten Lese- und Schreibzugriffe auf das "Datensegment" sind jetzt eliminert.

ein grosser Sprung!
Zitieren
(11.09.2025, 07:07)llm schrieb:
Zitat:Es gibt etwas zu feiern: Die direkten Lese- und Schreibzugriffe auf das "Datensegment" sind jetzt eliminert.

ein grosser Sprung!

Aber nur ein kleiner Schritt für Henne ;-)
Zitieren
Ohne Proben ganz nach oben! :jippie: :D :jippie:
Zitieren
(10.09.2025, 20:24)HenneNWH schrieb: Es gibt etwas zu feiern: Die direkten Lese- und Schreibzugriffe auf das "Datensegment" sind jetzt eliminert.

Bravo!

Ohnehin ist es sehr befriedigend zu sehen, wie die höheren Datenstrukturen jetzt sukzessive Gestalt annehmen und der ganze vorherige Ballast dadurch unnötig wird und verschwindet.

(10.09.2025, 20:24)HenneNWH schrieb: @siebenstreich: Den Schiffsreise-Bug, welchen du mal bearbeitet hast, habe ich heute etwas untersucht.
Es gibt Schiffe mit einer Geschwindigkeit von 150 km/h.
Dieser Wert wird in einer Bit8s Variable gespeichert, welche fälschlicherweise den Wert -106 haben sollte.
Das ergibt im Sinne des Spiels keinen Sinn, muss aber erstmal wegen der Binäraquivalenzcodedifferenz so bleiben, genauso wie alle anderen Fehler, welche der GCC und Clang anmeckern.

Sehr gut. Eine Fehlerursache im Umfeld "typecast signed-vs-unsigned" hatte ich auch vermutet bzw. die Sache durch trial-and-error auch irgendwie repariert, aber ohne zu verstehen was genau passiert. Die Schiffe mit 150 km/h sind übrigens Schnellsegler, gibt es in der Variante Begleitschutzfahrt (kostenlos) und Luxuspassage (vergleichsweise teuer). Mich wundert jetzt nur, dass ich den Bug damals in Zusammenhang mit einem Langschiff (Geschwindigkeit 120, passt noch in 7 Bit) notiert hatte. Ist da noch mehr? (Das ist mir öfter passiert: Man sucht nach einem Bug und findet drei davon. Oder fünf.)
Zitieren
Das Umsortieren der globalen Variablen und das Entfernen von p_datseg sind zwei verschiedene Punkte, die hoffentlich bald abgeschlossen sind.
Der hohe Wert der Binäräaquivalenzcodedifferenz hängt direkt mit dem Umsortieren zusammen.
Im Datensegment meiner Version sind 6 Bytes, die dort nicht hingehören und noch dafür sorgen,
dass die Offsets vieler Variablen um 6 Byte verschoben sind. Das wird sich sicher noch klären.

Meiner Erfahrung nach sollte Fehler, wie der Schiffsreisebug, erst behoben werden, wenn die Problematik vollständig verstanden wurde.
Ist der Code in einem lesbaren Zustand, wird es wesentlich einfacher die Unstimmigkeiten endgültig zu beheben.

Mit Sicherheit wird es noch ein paar Tage dauern. ;-)

Zwischenstand:
* Binäräquivalenzcodedifferenz = 3666 Bytes
* auskommentierte Zeilen in der symbols.h = 97.7 %
* es kompilieren schon einige Dateien (108 / 110) mit dem GCC

Weitere Fortschrittswerte welche definitiv gegen Null gehen:
Code:
# p_datseg   :36
# host_read  : 2527
# host_write : 596
# _ptr_      : 393
Zitieren
(13.09.2025, 14:07)HenneNWH schrieb: Meiner Erfahrung nach sollte Fehler, wie der Schiffsreisebug, erst behoben werden, wenn die Problematik vollständig verstanden wurde.
Ist der Code in einem lesbaren Zustand, wird es wesentlich einfacher die Unstimmigkeiten endgültig zu beheben.

Ja, stimmt schon. Aber wessen Leben verläuft schon perfekt linear? :evil: 

Warum treibt mich dieser Schiffsreise-Bug so um?

Es ist nicht der Bug an sich. Von dieser Coleur gibt es viele in der Schicksalsklinge.

Sondern: An dieser Stelle produziert der GCC einen anderes Programmverhalten als der BCC, wohlgemerkt aus demselben C-Code. Anders formuliert: Trotz Binäräquivalenz (selbes Resultat mit dem BCC) liefert der GCC ein Programm, das sich anders verhält als das Original. Das finde ich etwas verstörend, und es ist die einzige mir bekannte Stelle, wo das passiert. Und deswegen fände ich es wichtig, genau zu verstehen, was hier abläuft.
Zitieren
:jippie: :jippie: :jippie:

Heute gibt es wieder gute Neuigkeiten:
* Der Pointer/Zeiger p_datseg wurde komplett entfernt :wave:
* Das Datensegment hat durch das Umsortieren der Variablen die richtige Größe bekommen.
* Dadurch ist der Wert der Binäräquivalenzcodedifferenz drastisch gefallen (um ca. 1341 Bytes).

Zwischenstand:
* Binäräquivalenzcodedifferenz = 2325 Bytes
* auskommentierte Zeilen in der symbols.h = 100 %
* es kompilieren schon einige Dateien (108 / 110) mit dem GCC

Weitere Fortschrittswerte welche definitiv gegen Null gehen:
Code:
# p_datseg  : 0
# host_read  : 2521
# host_write : 596
# _ptr_      : 393
Zitieren
Das Datensegment mit BCC hat jetzt wirklich genau dieselbe Größe! :jippie:

Zwischenstand:
* Binäräquivalenzcodedifferenz = 555 Bytes
* es kompilieren schon einige Dateien (108 / 110) mit dem GCC

Weitere Fortschrittswerte welche definitiv gegen Null gehen:
Code:
# host_read  : 2434
# host_write : 562
# _ptr_      : 389
Zitieren
Nice! Das ist cool!

Da werd ich ganz neidisch :D
Zitieren
Super! Das (Zwischen-)Ziel ist sooo nah!
--------
Warnung! Geschichte kann zu Einsichten führen und verursacht Bewusstsein!
Avatar by: Keven Law (CC BY-SA 2.0)
Zitieren
Kleine Zwischenstandsmeldung (Achtung technisch!)

Hab heute das Tool: exe_comp um Overlays erweitert.
Bei der GEN.EXE wurden damit die Binaries in 3 Teile zerlegt: Header, Code und DATA.
Bei der SCHICKM.EXE ist noch ein großer nachladbarer Codeteil nach DATA, welcher mit diesem Tool seit heute separat extrahiert wird
um so besser analysiert werden zu können. Dabei handelt es sich um den Code aus den Dateien seg024-seg122.cpp.
Die gehe ich jetzt gerade einzeln durch und behebe die Fehler,
welche zum Teil von mir in den Anfangstagen von Bright-Eyes gemacht wurden,
oder auch jetzt manchmal durch falsch gesetzte Klammern entstanden sind.

Wo gehobelt wird, fallen Späne.

Im Großen und ganzen sieht es bisher ganz gut aus.
Der Overlay-Teil von BrightEyes ist aktuell 32 Byte länger als im Original.
Wenn dieser Missstand von mir behoben wurde, wird es auch dort eine Zahl
geben um meinen Fortschritt anzuzeigen.

Das Datensegment konnte heute von mir auf dieselbe Länge gebracht werden. :jippie:
Dort ist eine Differenz von 108 Byte vorhanden, eine Abweichung von 0.0017 %.
Diese hängt mit dort gespeicherten Funktionszeigern auf den Overlay-Teil zusammen,
welche vom Linker noch nicht die richtigen Adressen zugewiesen bekommen haben.
Das ist auf aktuellen Systemen jedoch irrelevant.

Das Tool exe_comp findet jetzt auch die Variable _stklen und kann deren Wert auslesen. :up:


Zwischenstand:
* Binäräquivalenzcodedifferenz = 576 Bytes (unausgelagerter Code)
* es kompilieren schon einige Dateien (108 / 110) mit dem GCC

Code:
# host_read  : 2414
# host_write : 554
# _ptr_      : 373
Zitieren
(17.09.2025, 21:44)HenneNWH schrieb: Dabei handelt es sich um den Code aus den Dateien seg024-seg122.cpp.
Die gehe ich jetzt gerade einzeln durch und behebe die Fehler,
welche zum Teil von mir in den Anfangstagen von Bright-Eyes gemacht wurden,
oder auch jetzt manchmal durch falsch gesetzte Klammern entstanden sind.

Zum Verständnis, weil es mich interessiert: Wie konntest du dort Fehler machen, die offenbar nicht bemerkt wurden? Es wurde doch schon lange auf Binäräquivalenz getestet. Kannst du ein Beispiel für einen solchen Fehler nennen?
Zitieren
Die Struktur der GEN.EXE ist vereinfacht : | Header | CODE | DATA | .
Die Struktur der SCHICKM.EXE ist vereinfacht | Header | CODE | DATA | Overlay-Code | .

Bei Bright-Eyes wurden als Testobjekte die OBJ-Dateien benutzt.
Mit dem Wechsel zu BrightEyes und dem Ersetzen der Symbole durch globale Variablen hat dieses Testverfahren nicht mehr ausgereicht.
Daher habe ich exe_comp für derartige BCC-Binaries entwickelt.
Dieses Programm habe ich gestern um den Overlay-Bereich erweitert, da dieser bisher unbeaufsichtigt war.
Jetzt gehe ich den Code nochmal von seg024 -> seg122 durch und versuche die dortigen Differenzen zu beseitigen.

Bsp:
Commit seg028
In den Zeilen 93, 372 und 400 musste nochmal nachgebessert werden.

Commit seg024
ist komplett so ein Fall.

Aber dafür gibt es ja Softwaretests!
Zitieren
Danke für die Erklärung!

Ich habe die genannten Änderungen ein wenig angeschaut und mein Eindruck ist, dass das fast alles Dinge sind, die in Bright-Eyes noch gepasst haben (allerdings in sperrigerer Ausdrucksweise) und im Rahmen deiner kürzlichen Umbauten passiert sind.
(Ein weiterer Beleg, wie mächtig dein Binäräquivalenz-Test ist!)

Ausnahme: seg028, Zeile 400. Den von dir eingefügten Typecast (unsigned short) gab es auch in Bright-Eyes nicht.
Mir ist jedoch nicht klar, wie diese Stelle in Bright-Eyes den Binäräquivalenztest bestehen konnte. Auf Ebene der OBJ-Datei sollte dieser fehlende Typecast doch auch auffallen, denke ich mir. Hast du eine Erklärung?

Ich frage mich jetzt auch, ob in Zusammenhang mit dem Schiffsreise-Bug evtl. etwas ähnliches abläuft: Ein Typecast fehlt (oder ist zu viel), der beim Vergleich der OBJ-Dateien aber nicht auffällt (warum auch immer), dann aber für ein unterschiedliches Programmverhalten sorgt.
Zitieren
In Bright-Eyes wurde die Typisierung der Variablen durch Makros wie ds_readbs() oder ds_readb() an sehr vielen Stellen separat festgelegt.

In BrightEyes hat der BCC jetzt diese Information zentral festgelegt bekommen, trifft andere Entscheidungen und generiert an einigen Stellen anderen Code.
Aktuell stecke ich in seg032.cpp an einem Ausdruck,
welcher den richtigen Code mit einer falschen Adresse generiert. Schreibe ich ihn so wie er sein sollte um, kommt ein ganz anderer Code raus, der möglicherweise korrekt funktionieren würde.

Eine andere Sache ist, dass die Offsets der Spungadressen in die Overlay-Segmente anders sind.
Das ist dann die nächste Baustelle.
Zitieren




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