20.11.2025, 16:42
|
Reverse Engineering der NLT II
|
|
hab gerade deinen String-Table Commit gesehen: https://github.com/Henne/BrightEyes/comm...6a30e3ba15
macht es nicht Sinn da mit einem array-typedef zu arbeiten um von den Magic-Values ganz weg zu kommen oder die Pointer-Size Probleme nur auf dem typedef zu haben, oder kann der Borland C++ 3.1 das nicht? Code: typedef char* string_table_t[1190]; // sizeof() = 9520ich verstehe nur nicht so ganz warum der Borland C teil nur Code: g_global_buffer_ptr = (HugePt)schick_alloc(g_buffersize);macht?
20.11.2025, 19:43
(Dieser Beitrag wurde zuletzt bearbeitet: 21.11.2025, 09:21 von siebenstreich.)
(20.11.2025, 14:46)NewProggie schrieb: Daneben bin ich einmal die seg-Dateien durch und hätte folgenden Vorschlag für die Umbenennung der Dateien: Vielen Dank! Die Liste können wir auf Alle Fälle mal aufheben für später. Ein wenig würde ich anpassen, z.B. seg002 -> main, bei seg053 bis 064 sollte entweder überall location dabeistehen oder nirgends, und die Kampf-Benennungen sind teilweise doch recht unspezifisch. Es wäre mir aber sehr recht, wenn die Benennung der Dateien von schick und schick_dos parallel bleibt, und solange der BCC noch im Rennen ist, müssen die Dateinamen vermutlich sowieso das Format 8.3 haben.
wie wollte ihr Unit-Tests machen?
die einfachste Variante wäre wohl eine statische Instanzierung einer Test-Structs welcher dann im ctor irgendwelche Tests macht also einfach mitten im Code drin z.B. Code: struct test_chr_finding_tganz lokal mit geringer Distanz zum zu testetenden Code für den Anfang wird dann vor dem Spiel-Start ausgeführt
Wie seht ihr den Einsatz von der C++/STL im nicht DOS-Teil?
z.B. std::string,std::vector, std::map, eben die ganz einfachen Container auch std::filesystem? man könnte einige von diesen globalen Puffern recht schnell unrelevant machen z.B. Code: signed int copy_chr_names(char* ptr, const signed int temple_id);durch Code: struct name_info_tersetzen ist nur ein Beispiel - aber da kommt schon einiges zusammen würde natürlich aber auch schon helfen diese char* ptr durch richtige Typen zu ersetzen Code: signed int menu_enter_delete(char* ptr, const signed int entries, const signed int mode)durch Code: struct name_info_t
Ich habe heute ein wenig an der STAR.DAT herumgerätselt:
Das, was z.B. im Wiki zu den Sternenschweif-Archiven steht (bzw. was nltpack macht), muss unvollständig sein: https://github.com/shihan42/BrightEyesWi...nenschweif Zumindest muss ich ziemlich heftige H*cks anwenden, um sie so modifizieren zu können, dass das Spiel sie fehlerfrei einliest. Bzw. ich verstehe aktuell einfach noch nicht, was genau schiefgeht. Vielleicht stehen an anderer Stelle irgendwo hardcodierte Dateilängen, oder das Spiel gleicht HDD- und CD-Variante auf eine mir unbekannte Weise ab. Im Moment scheint jedoch folgender Ansatz zu funktionieren: - Entferne alle Dateien aus dem HDD-Archiv und setze CD=0-Flag und Offset=0, außer a) für die Datei(en), die modifiziert werden sollen b) für die auf die letzte zu modifizierende Datei folgende Datei: Setze CD=0-Flag, aber setze den Offset auf das Ende der Datei: Dateilänge-(20 × Anzahl Einträge + 2). Andernfalls ist die allerletzte Datei (CD=1) kaputt. Hierbei konnte ich verifizieren, dass sowohl die modifizierten als auch die darauf folgende Datei vom Spiel gefunden werden. Vielleicht ist mein Ansatz auch komplett falsch. Er erklärt nicht, warum die unmodifizierten Spielarchive funktionieren, denn dort wird dieser „Hack“ ja nicht verwendet. Aber zumindest wäre er (bis wir verstehen, wie der originale Code funktioniert) am ungefährlichsten, da so alle unmodifizierten Dateien von CD gelesen werden. Ein anderer Ansatz, der in meinen Tests „funktioniert“ hat, war, die „vollständige“ STAR.DAT von der CD auf die HDD zu kopieren und diese zu modifizieren: Damit haben alle existierenden/relevanten Dateien dann CD=1-Flag und müssen daher nicht von CD gelesen werden. Allerdings verstehe ich auch hier nicht, wieso es funktioniert. Gegebenenfalls ist auch hier die letzte Datei kaputt, nur dass es eben eine andere ist, die in meinen Tests ggf. einfach nicht gelesen wurde. ---- Wollte das einfach mal kurz festhalten. Vielleicht finde ich die Ursache des Problems noch und komme ohne „Hack“ aus. Fürs Erste ist es für mich schon Erfolg genug, die Stern-Archive überhaupt irgendwie, ohne Absturz im Spiel, modifizieren zu können. Und: der Porträt-Exporter DSA1/Custom -> [DSA2, DSA3] ist damit fast fertig! Dazu mache ich im Lauf der kommenden Woche ein neues Thema auf. Kleiner Teaser im Anhang. Ich habe mich übrigens geirrt: Jedes Porträt aus der Schicksalsklinge hat ab DSA2 ein korrespondierendes erhalten, wurde aber teilweise deutlich verändert, z.B. mit anderen Augen- oder Haarfarben. Über den Exporter wird es dann deutlich einfacher sein, entweder mit den unveränderten Porträts aus DSA1 weiterzuspielen oder ein ganz eigenes Porträt zu importieren.
24.11.2025, 19:24
(24.11.2025, 18:25)cmfrydos schrieb: Und: der Porträt-Exporter DSA1/Custom -> [DSA2, DSA3] ist damit fast fertig! Dazu mache ich im Lauf der kommenden Woche ein neues Thema auf. Kleiner Teaser im Anhang. Das fänd ich super. Ich hab mich schon immer etwas geärgert, dass meine Truppe von DSA1 -> DSA2 anders aussieht und ich hätte viel lieber die möglichst originalen Köpfe wieder gehabt.
24.11.2025, 20:14
Ja, das sollte damit dann leicht möglich sein, mit den alten Köpfen weiterzuspielen.
Man kann damit auch Köpfe klassen-/typusübergreifend zuweisen, also z.B. einen Krieger mit Thorwalerkopf spielen. Ich überlege gerade, wie ich in der UI am geschicktesten auch intra-DSA2/DSA3-Porträtverschiebungen realisieren kann (vermutlich über einen weiteren Tab neben dem Dateiimport.) Ich finde manche der Köpfe eher seltener benutzter Klassen nämlich ganz schön, ohne dass sie direkt z.B. „Hexe“, „Streuner“ oder „Thorwaler“ schreien. Nur wenige Porträts sind aufgrund des Outfits (oder spitzer Ohren) klar einer Klasse zuzuordnen.
25.11.2025, 19:54
Das fände ich auch echt gut, wenn man die Heldenportraits auch noch nach DSA 1 nutzen könnte.
![]() Ich habe mir bislang damit beholfen, in jedem Teil die Gesichter auszuwählen (per HEX-Editor) die mir am besten gefallen, aber das funktionierte dann eben nur innerhalb von DSA 1 oder DSA 2 bzw. DSA 3 und nicht übergreifend von 1 nach 2 bzw. 3. Wäre denn eine Auswahl von DSA 2 / DSA 3 Portraits innerhalb von DSA 1 auch möglich?
"Alrik war durstig und hat getrunken."
25.11.2025, 22:05
(25.11.2025, 19:54)Alrik Alrikson schrieb: Wäre denn eine Auswahl von DSA 2 / DSA 3 Portraits innerhalb von DSA 1 auch möglich? Ja! Das habe ich gestern noch implementiert, ebenso eine weitere Möglichkeit des Palettenwechsels (mittels Markov-Ketten, um Kantenkontraste zu bewahren), die mir optisch noch besser zusagt! Allerdings gibt es in DSA1 leider weniger Farben zur Auswahl, sodass (noch) nicht alle Farben/Porträts gut funktionieren, aber die allermeisten, sodass man sich dann auch als Arva von Harben, Feylamia, oder Ork Thurazz auf die Suche nach der Schicksalsklinge machen kann! Die Tage dazu mehr; es gibt leider noch ein paar (wenige) Bugs von mir zu fixen.
26.11.2025, 10:29
Der Alpha aus dem rechten Bild hat Ähnlichkeit mit Edwin aus Baldurs Gate.
26.11.2025, 14:32
Ah, da hast du wohl die Vorlage für seinen Avatar gefunden!
Ich wollte gestern bloß mal Box-Downsampling ausprobieren und habe dafür ein paar der hier (für diesen Zweck) interessanteren Profilbilder genommen. Heute habe ich noch einmal etwas recherchiert und noch viele weitere klassische Non-KI-Techniken gefunden, die ich unbedingt ausprobieren, und integrieren möchte. Vermutlich mache ich den aktuellen Stand erst einmal release-reif und schiebe dann noch ein paar Techniken für den Custom-Bild-Import nach. Es gibt sicher auch gute Downsampling-Tools für genau diesen Zweck, aber nicht so schön integriert mit passendem Palettenwechsel für die NLT..
26.11.2025, 18:03
(25.11.2025, 22:05)cmfrydos schrieb:(25.11.2025, 19:54)Alrik Alrikson schrieb: Wäre denn eine Auswahl von DSA 2 / DSA 3 Portraits innerhalb von DSA 1 auch möglich? Ah, sehr cool! Sieht echt gut aus wie die DSA 2 bzw. DSA 3 Helden / NPC da in der Schicksalsklinge sind. Ja, die Portraits sehen farblich etwas anders aus, aber das verbinde ich auch mit dem ersten Teil der Trilogie und passt gut zu den anderen (originalen) Portraits.
"Alrik war durstig und hat getrunken."
30.11.2025, 16:12
Eine weitere sinnvolle Ergänzung, die man in der "neuen" Schick einbauen könnte, wäre die Würfelergebnisse anzuzeigen, so wie es derzeit bereits mit
Code: D1_INFO(...)
02.12.2025, 12:28
(Dieser Beitrag wurde zuletzt bearbeitet: 02.12.2025, 12:31 von siebenstreich.)
(30.11.2025, 16:12)NewProggie schrieb: Eine weitere sinnvolle Ergänzung, die man in der "neuen" Schick einbauen könnte, wäre die Würfelergebnisse anzuzeigen, so wie es derzeit bereits mit Ja, volle Zustimmung. Henne hatte in diesem Kontext mal von der Möglichkeit eines optional zuschaltbaren "Debug"-Fensters gesprochen. Eine Aufgabe wäre dann, mal den Quellcode komplett durchzugehen und konsequent solche Ausgaben nachzurüsten. Denn bisher gibt es diese D1_INFO-Stellen nur dort, wo sie aus Neugier oder Debug-Erfordernissen heraus mal jemand implementiert hat. Ich wollte z.B. mal die Logik hinter den Schiffsreisen genauer verstehen und habe Ausgaben für ein paar damit in Zusammenhang stehende Dinge eingebaut, die sonst nur "hinter den Kulissen" ablaufen. Eine davon "Heutige Wetter-Anpassung der Schiffs-Geschwindigkeiten..." durfte ich neulich in einem Screenshot entdecken ![]() Bei den Überland-Reisen ist manches ähnlich, aber D1_INFO-Ausgaben gibt es bisher nicht. Was ich mir auch gut vorstellen könnte, wäre eine aufgebohrte Ausgabe im Kampf, anstelle der farbigen Sterne, die ja nur ein schemenhaftes Abbild der im Hintergrund ablaufenden DSA3-Mechanismen liefern. Vielleicht könnte man hier die AT- und PA-Würfe explizit ausgeben, evtl. als W20-Grafik, wo das Ergebnis als Zahl in die obenliegende Seite eingetragen wird. Aber das sind Zukunfts-Spinnereien, vorher gibt es noch viele dringendere Dinge zu tun.
als Gamestate/Debug-Feature könnte "Dear ImGui" vielleicht auch ganz interessant sein: https://github.com/ocornut/imgui
ist ein sogenanntes Immediate UI (https://github.com/ocornut/imgui/blob/ma...i-toolkits) - also ohne Queue/Events usw. sondern der State des UIs und das UI selbst wird unmittelbar aus dem Code verändert d.h. man kann UI Änderungen mitten in den Code im Algorithmen-Fluss machen - besonder gut geeignet für Aktual-Anzeigen/Game-State-Debugger etc. Es ist das meist verwendete Immediate GUI und in vielen kommerziellen Spielen, Applikations eingebaut: https://github.com/ocornut/imgui/wiki/So...dear-imgui
05.12.2025, 12:32
(Dieser Beitrag wurde zuletzt bearbeitet: 05.12.2025, 13:56 von siebenstreich.)
Um euch ein wenig auf dem Laufenden zu halten:
Es gibt für die Schicksalsklinge folgenden Exploit, erste mir bekannte Erwähnung von JackyD vom 14.8.2006. Man kann manches schwierige Reiseereignis wie z.B. einen Sumpf wie folgt umgehen: Bei der Ankunft gibt es die Option, umzudrehen. Das macht man, und danach dreht man gleich nochmal um (hierzu muss man zuerst ein Lager aufzuschlagen). Das Reiseereignis tritt nicht mehr auf. Mir ist die Ursache dieses Exploits über den Weg gelaufen und ich habe es in BrightEyes repariert (als Original-Bug 51). Der Fix ist unauffällig, aber es hat mich doch einige Zeit gekostet. Das Hauptproblem war, die Bedeutung eines gewissen Arrays zu verstehen. Zuerst hatte ich es so halb treffend mit g_journey_tevent_accessibility benannt. Schließlich ist der Groschen gefallen und ich habe es in g_journey_tevent_relative_position umgetauft. In diesem Array wird für jedes Reiseereignis auf der aktuellen Route die Information abgelegt, ob es sich (vom Startort aus gesehen) vor oder hinter der Gruppe befindet. Im Verlauf der Reise werden die Einträge entsprechend aktualisiert. Und beim Richtungswechsel der Gruppe wird dubioserweise der Eintrag für das zuletzt aufgetretene Reiseereignis umgedreht. Gut möglich, dass dieses Verhalten bereits das Resultat einer letztlich unvollständigen Fehlerkorrektur von Attic ist. Der berühmte dirty hack, der auch oft funktioniert, dessen Auswirkungen sich aber schwer überblicken lassen und der dann in komplizierteren Situationen gerne doch nicht das tut, was er soll. Noch genauer: Die Grundlogik von Überlandreisen findet in der Funktion trv_do_journey (in der Datei seg094.cpp) statt. Tritt ein Reiseereignis ein, so wird dort die zugehörige handler-Funktion aufgerufen, die das Reiseereignis gewissermaßen autark abarbeitet. Danach muss die äußere Funktion trv_do_journey den zugehörigen Eintrag in g_journey_tevent_relative_position aktualisieren. Hierzu muss sie wissen, ob die Gruppe die Position des Reiseereignisses letztlich passiert hat oder nicht. Das Grundproblem: Das ist nicht so ganz klar. Meistens trifft ersteres zu, aber es gibt Reiseereignisse, in deren Handler die Möglichkeit des Umdrehens angeboten wird, und in diesem Fall hat man das Reiseereignis eben nicht passiert. Attic geht mit der Situation so um: Man geht standardmäßig davon aus, dass das Reiseereignis passiert wurde. Wird jedoch eine Richtungsänderung durchgeführt (die an der entsprechenden Stelle vom handler eines Reiseereignisses, aber auch von einer Umkehr nach dem Abbrechen eines Lagers herkommen kann), wird das letzte Reiseereignis dahingehend korrigiert, dass die Gruppe doch nicht daran vorbegekommen ist. Damit geht man gewissermaßen auf Nummer sicher, denn in der Situation der Reiseereignis-Umkehr tut man das richtige, und in den anderen Fällen verhindert man, dass das letzte Reiseereignis nicht ein zweites Mal hintereinander ausgeführt wird (nicht ganz logisch, aber noch irgendwie vertretbar). Ändert man jetzt aber früh genug nochmal die Richtung, so ist das letzte Reiseereignis immer noch das letzte Reiseereignis, dessen Ausführung nach der erneuten Umkehr abermals unterbunden wird. Und das ist in keinem Fall richtig... In meinem Fix wird jetzt einfach unmittelbar nach Beenden der handler-Funktion des Reiseereignisses nachgeschaut, ob eine Änderung der Richtung stattfinden soll. Falls ja, so dürfte das in (hoffentlich) allen Fällen bedeuten, dass die Gruppe sich zum Umdrehen entschieden und folglich das Reiseereignis nicht passiert hat. Die oben angesprochene dubiose Aktualisierung habe ich deaktiviert (der bloße Richtungswechsel teleportiert mich ja nicht an einem Reiseereignis vorbei). |
Benutzer, die gerade dieses Thema anschauen: 5 Gast/Gäste


