26.01.2017, 14:33
Reverse Engineering der NLT
|
26.01.2017, 17:20
(25.01.2017, 23:31)HenneNWH schrieb: Hallo Alrik, Hallo Henne, danke für Deine Erklärungen. Dann bleibe ich weiterhin gespannt, wie das fertige Produkt aussehen wird.
"Alrik war durstig und hat getrunken."
26.01.2017, 21:23
Wo findet man die Texte, die von get_tx() usw. ausgegeben werden? In der EXE?
26.01.2017, 21:41
Ah, zu get_tx usw kann ich etwas sagen. Die Texte stammen sämtlich aus der SCHICK.DAT - je nach Spielsituation aus unterschiedlichen Dateien (mit Endungen *.DTX odr *.LTX). In meinem neulich hier vorgestellten Tool sind diese Dateien gelb eingefärbt.
get_ttx bezieht sich immer auf die TEXT.LTX. Die ist nämlich ständig geladen. get_tx und get_tx2 beziehen sich auf wechselnde Text-Dateien aus der SCHICK.DAT, die in den Variablen TX_INDEX und TX2_INDEX indiziert sind und mit load_tx bzw. load_tx2 nachgeladen werden. Die Hex-Angaben im Argument von get_tx(...) beziehen sich auf die Offsets in den Index-Tabellen TX_INDEX, TX2_INDEX usw. und können in mein Python-Tool bei den jeweiligen Dateien direkt eingegeben werden.
26.01.2017, 21:52
Ich wollte die Offsets durch geeignete Label ersetzen. Meinst Du, so eine Liste kann man auch automatisiert erstellen?
26.01.2017, 21:54
Meinst du echt, das ist nötig? Das ist echt viel Zeug und man müsste wahnsinnig lange Bezeichner verwenden um damit überhaupt etwas anfangen zu können. Wie wäre es stattdessen, an den jeweiligen Stellen im Code die entscheidenden Strings in Kommentaren anzuführen?
26.01.2017, 22:14
Ich mag keine physikalischen Konstanten im Code. Das ist barbarisch. Hinterher wollen wir vielleicht mal Unicode oder sonstwas. Meine ursprüngliche Idee war z.B. #define TX_A1 0xa1, und dann nach und nach A1 etc. von Hand durch etwas sinnvolles zu ersetzen. Und schon haben wir kostenlos eine Stufe Indirektion. Sowas wie der %S-%s-Fehler würde dann im Header und nicht mehr im eigentlichen Code erledigt.
26.01.2017, 22:17
Ihr gebt dann Bescheid, wenn ihr mit eurem Dekompilier- und Datensegment-Variablenbennennungs-Gedöns so weit seid, dass ich die Programmcode-Änderungen aus meinem umfassenden Patch einpflegen kann?
(26.01.2017, 22:14)Rabenaas schrieb: Ich mag keine physikalischen Konstanten im Code.Physikalische Konstanten sind das nicht. Da sind einfach alle Strings durchnummeriert. Das gleiche Problem hat man übrigens auch bei moderner internationaler Software, die sowas wie GNU gettext verwendet, siehe beispielsweise die Diskussion hier: https://stackoverflow.com/questions/2164...glish-text Da scheiden sich die Geister, ob man die (englischen) Strings direkt im Code verwendet, ob man die Strings durchnummeriert (wofür man sich bei der Schicksalsklinge vermutlich entschieden hatte) oder ob man irgendwelche abkürzenden Bezeichnungen verwendet. Als ersten Schritt könnte man vielleicht die Hexzahlen durch Dezimalzahlen ersetzen. Statt get_tx(0x0c) sollte man get_tx(3) (Faktor 4 kann man immer rauskürzen, der ist immer drin) verwenden. Das würde dann demnächst zu tx_index[3]. Dann könnte man noch sowas machen wie tx_index[msg0273] oder tx_index[tx_ottarje_003] oder tx_index[TX_thorgun_the_strong] (weil der vierte String in der OTTARJE.LTX eben "THORGUN DER STARKE" ist). Oder was schwebt dir aktuell konkret vor, wie es am Ende aussehen könnte? Nachtrag: Wenn du eindeutige Identifikatoren definieren willst, die nicht einfach nur durchnummerieren, dann hier ein Vorgeschmack, welche Art von Strings du da voneinander unterscheiden musst (direkt aufeinanderfolgend in FEATURE4.LTX): Code: SCHRITT FÜR SCHRITT SCHAUFELT IHR EUCH VORWÄRTS. ES IST BITTERKALT. DER ATEM Code: STUNDE UM STUNDE MARSCHIERT IHR, EURE AUGEN GEBLENDET VON DER ENDLOSEN Code: STUNDE UM STUNDE MARSCHIERT IHR DURCH DIE ENDLOSE SCHNEEWÜSTE, EURE AUGEN
26.01.2017, 23:24
Na, tx_ottarje_003 wäre doch schon ziemlich aufgeräumt. Man könnte auch gleich das ganze get_tx(0x..) durch je so ein Makro zu ersetzen.
Es wäre schön, wenn wir von so etwas wie Code: strcat((char*)Real2Host(ds_readd(DTP2)), Code: strcat(STR_AT(DTP2), TX_029); (26.01.2017, 23:24)Rabenaas schrieb: Es wäre schön, wenn wir [...]Woran wir momentan arbeiten, ist die Wiederherstellung dessen, was vermutlich im Original-Code stand. Und das ist in diesem Fall sehr wahrscheinlich eine dieser Varianten: Code: strcat(&dtp2, tx_index[29]); Natürlich kannst du auch das get_tx(...) in die Definition der Makros hineinnehmen, sodass da steht Code: strcat(&dtp2, TX_spelltxt_029); Code: get_tx(random_schick(4) + 19) Nebenbei: Wenn du wirklich die LTX-Datei (also OTTARJE.LTX oder SPELLTXT.LTX usw.) in den Variablennamen hineinnehmen willst, wirst du eine Menge Arbeit vor dir haben. Du müsstest bei jedem der 2500 Aufrufe von get_tx bzw. get_tx2 herausfinden, auf welche Datei sich der Offset jeweils bezieht. Die kryptischen Hex-Werte der INDEX-Offsets habe ich jetzt durch die etwas brauchbareren Dezimalwerte der String-Nummern ersetzt. Also ein get_tx(0x0c) wird zu get_tx(3) usw. Hier der pull request dazu: https://github.com/Henne/Bright-Eyes/pull/37 Wenn du also etwas in der Richtung machen willst, Rabenaas, schließt du vielleicht am besten daran an. Edit: Beitrag nochmal umgeschrieben und Infos ergänzt.
27.01.2017, 12:27
Ach, dann verstehe ich jetzt auch das hier.
(25.01.2017, 16:16)HenneNWH schrieb: Phase 2 ist folgendermaßen untergliedert: Wie gehst Du vor? Variablen deklarieren und hoffen, dass es passt?
27.01.2017, 12:54
Ich bin momentan noch nicht so ganz sicher, an welcher Stelle im Code ich globale Variablen am Ende deklarieren muss, damit auch die Reihenfolge passt. Aber prinzipiell ist die Idee, bei den Einträgen in symbols.h einen Eintrag der Form...
Code: #define HERBS_TOXIC (0x08e7) /* signed short[5]; { SHURINKNOLLE (0x7a), ALRAUNE (0x7e), LOTUSBLUTE (0x84), EITRIGER KROTENSCHEMEL (0x3e), 0xff } */ Code: signed short herbs_toxic[5] = { ITEM_SHURINKNOLLE, ITEM_ALRAUNE, ITEM_LOTUSBLUTE, ITEM_EITRIGER_KROTENSCHEMEL, 0xff };
27.01.2017, 13:14
Wäre es ggf. eine Möglichkeit, die Variablen als extern zu deklarieren, in einer eigenen c-Datei zu definieren? Diese c-Datei müsste man per pragma in ein beliebiges Segment einordnen lassen können.
27.01.2017, 14:16
(27.01.2017, 12:27)Rabenaas schrieb: Ach, dann verstehe ich jetzt auch das hier. Im Wesentlichen ja. Das kann ich allerdings erst machen wenn der komplette Code an der richtigen Stelle ist. Wie der Linker (TLINK) von BCC die Daten anordnet habe ich schon herausgefunden, bzw. kann man sich beim Linken eine MAP-Datei erstellen, in welcher alle Positionen der globalen Variablen stehen. Zuerst kommen die initialisierten Variablen in der Reihenfolge, in der die Objektdateien an den Linker übergeben werden. Also erst die CLIB, dann seg001, seg002,...,seg122. Typisierte Konstanten (const) sind initialisierte Daten. Danach kommen die uninitialisierten Daten (BSS) in derselben Reihenfolge. Wie es aber am realisiert werden soll, weiß ich noch nicht. Ich glaube aber, dass eine große C-Datei mit Daten erstmal am besten funktioniert. Im Original sind die Daten teilweise auf die C-Dateien verteilt worden, die Beschreibungen der Schatztruhen in den Dungeons, in denen sie vorkommen, Tabellen für Händler bei den Händlern, etc. Bei dem Speicherbereich für den Spielstand und den Tabellen würde ich vielleicht eine Ausnahme (eigene Datei) machen.
02.02.2017, 01:22
So, die symbols.h ist jetzt im Wesentlichen vollständig und die globalen Variablen könnten also deklariert werden: https://github.com/Henne/Bright-Eyes/pull/41
Übrigens habe ich noch ein bisschen mit meinem Tool herumgespielt. Man kann jetzt auch die Karten von Dungeons und Städten anschauen - inkl. Kämpfen, Türen, Treppen und Gebäuden:
12.02.2017, 17:30
Ich könnte jetzt das Datensegment über die datseg.cpp füllen. Der Code ist hier: http://pastebin.com/sSgNjd13 Es fehlen nur noch etwa 270 Zeilen - das wäre schnell durchgecheckt. Aber der BCC beschwert sich:
Code: Error datseg.cpp 1595: Group overflowed maximum size: DGROUP Jemand eine Ahnung, was man dagegen macht?
Wäre es eigentlich möglich, den Download auf github auszulagern? Dafür müsste für jeden Download releases festgelegt werden und jemand (ich) könnte dann die binaries beisteuern. Habe ich schon bei mehreren Softwareprojekten gesehen.
https://github.com/blog/1547-release-your-software Ein Vorteil wäre, dass ich hier nicht mehr mit den Anhängen hantieren müsste. Außerdem würde das Forum/Crystal aus dem Fokus genommen, was vor allem aus rechtlicher Sicht so langsam immer bedenkenswerter wird. Das Download-Thema würde ich weiterhin pflegen, aber mit externem Download. Viel wird das Binary eh nicht heruntergeladen....
--------
Warnung! Geschichte kann zu Einsichten führen und verursacht Bewusstsein! Avatar by: Keven Law (CC BY-SA 2.0) (12.02.2017, 17:30)gaor schrieb: Ich könnte jetzt das Datensegment über die datseg.cpp füllen. Der Code ist hier: http://pastebin.com/sSgNjd13 Es fehlen nur noch etwa 270 Zeilen - das wäre schnell durchgecheckt. Aber der BCC beschwert sich: Der Fehler kommt wenn dein Segment > 64k ist laut https://github.com/Henne/Bright-Eyes/blo...e/datseg.h ist das Datensegment (0xf7af - 0x936 - 2) = 0xEE77 = 61047 Bytes - also noch unter 64k ich würde aber (wenn nicht 100% klar ist wo was liegt) vorsichtig vorgehen: 1. einen Struct mit den ds-Variablen definieren - und mit static_assert/offsetof dauerhaft Offset und komplette Größe prüfen 2. gehörig auf das Alignment achten (könnte sich bei BCC zu gcc usw. unterscheiden - was tödlich wäre) siehe #pragma pack(1) (https://msdn.microsoft.com/de-de/library/2e70t5y1.aspx) Code: #pragma pack(push,1) 3. die ds-Variable auf den Struct-casten - und damit arbeiten - dann bleiben die Initalwerte erstmal wo sie sind ... 4. eine weitere instanz von ds_structur erzeugen - die members einzeln fuellen und pruefen ob das dem Inhalt von ds entspricht - dauerhaft Code: ds_structur fuell_test; und wenn alles passt kannst du die char ds[...] durch ds_structur ds; ersetzen am einfachsten ist es wohl wenn du eine Liste der Variablen, Typen und Offsets hast dann kannst du dir den ganzen Code mit Python oder sonstwas einfach generieren |
Benutzer, die gerade dieses Thema anschauen: 27 Gast/Gäste