Crystals-DSA-Foren

Normale Version: Reverse Engineering der NLT
Sie sehen gerade eine vereinfachte Darstellung unserer Inhalte. Normale Ansicht mit richtiger Formatierung.
Leider bin ich im Moment etwas Verhindert beim Testen von BrightEyes. Ich habe mein Windows 7 auf Windows 10 geupgraded und leider zickt Windows 10 an allen Ecken und Enden rum, so auch bei Dosbox. Ich kann BrightEyes zwar starten, komme aber nicht über das Intro hinaus. :(
Also ich hab nach dem Upgrade direkt eine neu installation gemacht ;) Hab aber schon öfters gehört, dass viele die "nur" ein Upgrade gemacht hatten hier und da Probleme haben...

@Henne
erstmal ein großes lob von mir, wie du die Entwicklung von Brighteyes in letzter Zeit vorangetrieben hast. Ich habe im moment leider nicht mehr so viel Zeit um wirklich aktiv mitzuhelfen. Durch die Arbeit bin ich im Moment gut ausgelastet und hab da leider wenig Zeit für anderes...
Naja auf jeden Fall hab ich mir gerade ein paar Zeilen code angesehen und ich muss dochmal ein wenig meckern ;) Du hast eindeutig noch unter jemanden gelernt, der mit alten C kompilern zu tun hatte. Dieses deklarieren von Variablen am Funktionsanfang ohne sie unmittelbar zu definieren hat unter neueren C compilern (neuer als ANSI-C (C89/C90)) nichts und in C++ noch viel weniger zu suchen!!!
Ich habe schon zu oft gesehen, dass im nachhinein code geändert wurde und deswege in einer besonderen if/switch Anweisung eine bestimmte Variable nicht mehr initialisiert wurde, womit es ein bischen Glückssache wurde, dass im Speicher zufällig ein halbwegs passender Wert drin stand...Auf jeden Fall ist es eine schlechte Angewonheit, die man sich schnellsten Abgewöhnen sollte ;)
Und als zwites noch ein kleiner Tip von mir. Seit der C++ 11 Standard draußen ist, haben sich einige verbesserungen in Sachen Speicherhändling ergeben. So kann ich z.B. den std::Array anstellen von normalen Arrays empfehlen, da diese ihre eigene größe kennen und wenn man mittels ".at" auf sie zugreift, sogar ihre speichergrenzen überwachen können. Und nicht zu vergessen auch die neuen smart Pointer sind einen anblick wert....aber ich vermute mal da du immer Testweise gegen den alten Borland compiler compellierst, werden dir diese Neuerungen wohl entgehen....
Auf jeden Fall mach weiter so, ist echt tolle Arbeit die du bisher geleistet hast :)
(02.08.2015, 20:56)tommy schrieb: [ -> ]Also ich hab nach dem Upgrade direkt eine neu installation gemacht ;) Hab aber schon öfters gehört, dass viele die "nur" ein Upgrade gemacht hatten hier und da Probleme haben...

@Henne
erstmal ein großes lob von mir, wie du die Entwicklung von Brighteyes in letzter Zeit vorangetrieben hast. Ich habe im moment leider nicht mehr so viel Zeit um wirklich aktiv mitzuhelfen. Durch die Arbeit bin ich im Moment gut ausgelastet und hab da leider wenig Zeit für anderes...
Naja auf jeden Fall hab ich mir gerade ein paar Zeilen code angesehen und ich muss dochmal ein wenig meckern ;) Du hast eindeutig noch unter jemanden gelernt, der mit alten C kompilern zu tun hatte. Dieses deklarieren von Variablen am Funktionsanfang ohne sie unmittelbar zu definieren hat unter neueren C compilern (neuer als ANSI-C (C89/C90)) nichts und in C++ noch viel weniger zu suchen!!!
Ich habe schon zu oft gesehen, dass im nachhinein code geändert wurde und deswege in einer besonderen if/switch Anweisung eine bestimmte Variable nicht mehr initialisiert wurde, womit es ein bischen Glückssache wurde, dass im Speicher zufällig ein halbwegs passender Wert drin stand...Auf jeden Fall ist es eine schlechte Angewonheit, die man sich schnellsten Abgewöhnen sollte ;)
Und als zwites noch ein kleiner Tip von mir. Seit der C++ 11 Standard draußen ist, haben sich einige verbesserungen in Sachen Speicherhändling ergeben. So kann ich z.B. den std::Array anstellen von normalen Arrays empfehlen, da diese ihre eigene größe kennen und wenn man mittels ".at" auf sie zugreift, sogar ihre speichergrenzen überwachen können. Und nicht zu vergessen auch die neuen smart Pointer sind einen anblick wert....aber ich vermute mal da du immer Testweise gegen den alten Borland compiler compellierst, werden dir diese Neuerungen wohl entgehen....
Auf jeden Fall mach weiter so, ist echt tolle Arbeit die du bisher geleistet hast :)

Der C89 Standard schreibt explizit vor, dass Variablen zu Beginn eines Scopes deklariert werden müssen. Im Hinblick auf den alten Compiler, den er verwendet, muss er das vermutlich so machen.
Außerdem ist der bisherige Code in C geschrieben. Ich habe noch nichts gesehen, was explizit C++ voraussetzt.
std::array überwacht zudem nicht seine Speichergrenzen, sondern wirft eine std::out_of_range Exception, falls du mit .at() auf eine ungültige Stelle im Array zugreifst.

Soweit ich mich erinnern kann, ist der eigentliche "Rewrite" sowieso erst in der zweiten Entwicklungsstufe vorgesehen, d.h. nachdem alle Funktionen entsprechend nachgebaut wurden.
Ich muss zugeben ich habe noch nie mit einen solchen alten kompiler gearbeitet. Aber so wie ich das sehe sind die Funktionen kein echtes C sondern nur eine c like mit einem C++ Compiler. Das ist schon nen Unterschied.

(03.08.2015, 11:06)NewProggie schrieb: [ -> ]std::array überwacht zudem nicht seine Speichergrenzen, sondern wirft eine std::out_of_range Exception, falls du mit .at() auf eine ungültige Stelle im Array zugreifst.
genau das ist überwachen von Speichergrenzen ;). Es geht ja gerade darum, dass es in C, C++ erlaubt ist über die reservierten Speichergrenzen hinaus zuzugreifen und unterliegende Daten zu verändern, was sich häufig in sehr willkürlichen verhalten im Programm äußert. Der std::Array unterbindet das durch das werfen einer exception, wodurch das Programm sofern nicht abgefangen, genau an der Stelle abstürzt. Was aber viel wichtiger ist, man erhält eine Aussagekräftige Fehlermeldung und im Debugmodus sogar die genaue Position des Auftretens, was ein beheben des Fehlers sehr vereinfacht.

Ich habe die letzten Jahren in sachen C, C++ einen wirklich guten Mentor gehabt, der sauch immer auf nächsten Stand ist. Ich habe da auf jeden Fall eine menge über die Tücken und vorallem die Neuerungen gelernt, man sollte sich denen auf keinen Fall verschließen....auch wenn visual studio bei der Umsetzung von Standards sehr zurückhängt. Achja und wäre das echter C Code, hätte man den garnicht ohne weiteres mit vissual Studio 2012 Compellieren können ;)

(03.08.2015, 11:06)NewProggie schrieb: [ -> ]Soweit ich mich erinnern kann, ist der eigentliche "Rewrite" sowieso erst in der zweiten Entwicklungsstufe vorgesehen, d.h. nachdem alle Funktionen entsprechend nachgebaut wurden.
Da hast du natürlich recht, ich weiß nicht in wieweit das nötig ist um den direkten Codevergleich zu erhalten.........aber....dieser Stil ist trotzdem furchtbar und man sollte es vermeiden wo es geht. Auf lange sicht macht es das leben auch leichter^^
Der Quelltext ist mehr oder weniger das, was der Disassembler ausgibt. Deshalb der merkwürdige Stil. Irgend etwas C++-typisches habe ich noch nicht gesehen. Statt ganz auf Klassen aus Boost umzusteigen, könnte man auch assertions einsetzen. Die kann man per Präprozessor einfach ausschalten.
std::Array entstammt nicht Boost sondern gehört zur STL :)
Hallo zusammen.

Ich habe mal wieder eine kleine hoffnungsvolle Frage in die Expertenrunde:

(Wie) ist es einem interessierten Laien möglich, die .exe oder .dat- Dateien so zu vergrößern, also Inhalte einzufügen, ohne dass man gleich alles komplett zerschießt?

Läßt sich das mit überschaubarem Aufwand und technischem Verständnis machen, oder ist das schon ...fortgeschritten... komplex?

Gruß und vielen Dank, Jandor.
Das geht mit Hendriks nltpack. Und die exe kannst Du z.B. mit Lua modden.
(30.07.2015, 18:02)adtbm schrieb: [ -> ]Nachdem ich dann raus in den Tempel bin, zum speichern und den Spielstand wieder
neu geladen habe, hat wieder ein Held gefehlt...

Im Moment arbeite ich an einer Lösung für diesen Bug und möchte meine Erkenntnisse loswerden:

Der Bug tritt beim speichern auf, aber nicht immer.

Die für diesen Bug beim speichern wichtigen Schritte sind:
  • Alle aktiven Helden werden im TEMP-Verzeichnis gespeichert.
  • Der komplette Spielstand wird gespeichert.
  • Alle CHR-Dateien im TEMP-Verzeichnis werden an den Spielstand angehängt.

Welche CHR-Dateien das sind wird mit den Funktionen findfirst("TEMP\\*.CHR", &blk, 0) und findnext(&blk) ermittelt.

Das Problem ist nun, dass einige CHR-Dateien manchmal (noch) nicht im TEMP-Verzeichnis angekommen sind, und findnext() sie nicht findet was dazu führt, dass diese Helden nicht im Spielstand landen.

Ich habe einiges ausprobiert (fflush(), flushall(), sync(), warten) aber war damit leider erfolglos. :wall:

Aktuell habe ich den Laufwerkscache von DOSBox (dos/drive_cache.cpp) unter Verdacht,
welcher die Datei- und Verzeichnisnamen speichert um Laufwerkszugriffe zu vermeiden.
Dort stöbere ich gerade herum und lese mich in den Code ein.

...ah, in der Entwicklerversion von DOSBox wurde nach v0.74 nochmal an drive_cache.cpp herumgeschraubt...


(02.08.2015, 20:56)tommy schrieb: [ -> ]Naja auf jeden Fall hab ich mir gerade ein paar Zeilen code angesehen und ich muss dochmal ein wenig meckern ;) Du hast eindeutig noch unter jemanden gelernt, der mit alten C kompilern zu tun hatte. Dieses deklarieren von Variablen am Funktionsanfang ohne sie unmittelbar zu definieren hat unter neueren C compilern (neuer als ANSI-C (C89/C90)) nichts und in C++ noch viel weniger zu suchen!!!
Ich habe schon zu oft gesehen, dass im nachhinein code geändert wurde und deswege in einer besonderen if/switch Anweisung eine bestimmte Variable nicht mehr initialisiert wurde, womit es ein bischen Glückssache wurde, dass im Speicher zufällig ein halbwegs passender Wert drin stand...Auf jeden Fall ist es eine schlechte Angewonheit, die man sich schnellsten Abgewöhnen sollte ;)

Danke sowohl für das Lob als auch die Kritik. :thx:

Im Moment ist meine Hauptpriorität den Borland C++ 3.1 Compiler (von 1992) dazu zu bringen genau den gleichen Binärcode wie er in der SCHICKM.EXE ist auszugeben. Das bedeutet, dass ich auch so programmieren muss wie die ATTIC-Programmier es damals getan haben.
Bei SCHICK war das einzige was mit C++ etwas zu tun hatte die Dateiendungen *.cpp
(*.c erzeugt in seltenen Fällen leicht anderen Code).
Der Programmcode wurde ausschließlich in C, inline Assembler(BASM) und Assembler geschrieben.

Aber um auf deine Frage zu Antworten: ich hatte meine erste Begegnung mit C 1998 (Borland Turbo C ???) und habe das so gelernt.
In meinem Studium (2011) wurden wir in "Algorithmen und Programmierung" aber trotzdem dazu angehalten "ANSI-C" zu programmieren, da es für manche Plattformen nichts anderes gibt.
(22.08.2015, 21:26)HenneNWH schrieb: [ -> ]Das bedeutet, dass ich auch so programmieren muss wie die ATTIC-Programmier es damals getan haben.

Hoffentlich kriegt das Guido nicht in den falschen Hals. :ironie:
Hallo Henne,

erstmal Hut ab, dass du weiterhin so kontinuierlich und akribisch dran bist. Das ganze Thema verfolge ich seit Anbeginn an sehr interessiert mit der Brille eines unbedarften Endanwenders/Spielers. Ich kann nur schwer erahnen wie viel Mühe und Zeit es kostet, die Programme in kleinster Detailarbeit nachzuvollziehen. Dafür, dass du hier seit Jahren unbeiirt deine Arbeit - behaupte mal ohne großen Zuspruch - fortsetzt, gebührt dir mein vollster Respekt. Auf mich wirkt das hier regelrecht wie ein Lebenswerk.

Frage für den Laien: Wo soll die Reise denn hingehen?
Angenommen 100% wurden "nachgebaut" (lt. der von dir angeführten Statistik) - was heißt das?
Heißt das, du hast das Coding, das von den Programmierern damals verbrochen wurde, verstanden, und wenn ja, liegt es nun in einer Form vor, dass auch andere es verstehen können?
Hast du schon Ideen/Wünsche, wie es danach weitergehen soll?

Ansonsten bleibt mir nur zu sagen: Weitermachen! :-)

Viele Grüße
GZ
@Gaddezwerch:
Vielen Dank für das Lob.
100% bedeuten, dass ich den Programmcode 1:1 nachgebaut habe. Verstanden hab ich ihn desswegen noch nicht,
aber es fällt auf jeden Fall leichter.
Anschließend müssen die globalen Variablen, auf welche z.Z. mit z.B. ds_readbs() usw. zugegriffen wird, durch richtige Variablen ersetzt werden.
Anschließend muss noch die gesamte Ein-/Ausgabe portiert werden, z.B. mit SDL, die Dokumentation vervollständigt werden, sämtliche Fehler behoben werden und ich wäre mit meiner eigentlichen Arbeit endlich am Ende.
Ein paar klein Änderungen würde ich schon noch vornehmen, aber die sind eher algorithmischer Natur (z.B. alternative Kampf-KI) oder Talentproben nach DSA3-Regeln .

Mein persönliches Anliegen ist der Erhalt des Originals (wie es meiner Meinung nach von den Entwicklern gemeint war).
Modding steht für mich nicht auf der Wunschliste, aber wenn der Zwischencode so klein bleibt,
dann kann ich mich auch passiv darum kümmern. Es sollte blos nicht mehr in Arbeit ausarten. :)
Hast Du einen Überblick, ob im noch nicht disassemblierten Code noch auf die Hardwareregister zugegriffen wird?
Maschinencode arbeitet doch (fast) immer mit HW-Registern. => Ja.
Oder meinst Du etwas anderes?
Oh, das war missverständlich formuliert. Ich meinte, ob der verbliebene Code noch oft auf Grafikkarte, Soundkarte usw. zugreift.
Nein, das halte ich für sehr unwahrscheinlich, da es für diese Zugriffe spezielle Funktionen gibt.

Es kann sein, dass zum Löschen des GraKa-Speichers die memset()-Funktion genommen wird,
aber das kann ich heute Abend genauer sagen.
Dann werde ich mir bei Gelegenheit mal die Doku von SDL vornehmen. :)
(17.07.2014, 15:00)Shihan schrieb: [ -> ]Hihi, ich hatte gerade eine Eingebung bezgl. der Faces. Und habe dann gemerkt, dass ich doof bin. Im Wiki hatte ich schon einige Dinge eingetragen, die mir wieder eingefallen sind. Und zwar hatte ich im Objekt-Header einige Stellen mit "Unbekanntes Offset im Objekt-Eintrag" bezeichnet. Kurz geprüft, eines von denen ist die Face-Liste!

Habe mir dann eben Zeit genommen und meinen Exporter angepasst (der bisher nur Vertices konnte). Nun kann ich also auch Faces exportieren, d.h. damit ein komplettes 3D-Mesh.

Habe das dann fünf mal gemacht, hier sind die Ergebnisse:
Boronsacker
[Bild: blender_export_boronsacker.png]

Boronsacker-Dungeon
[Bild: blender_export_boronsacker_dun.png]

Umland
[Bild: blender_export_env02.png]

Mine, 1. Ebene
[Bild: blender_export_mine01.png]

Riva
[Bild: blender_export_riva.png]

Der Exporter ist noch ein wenig fehlerträchtig, insb. bei Riva oder dem Umland sieht man noch verdammt viele Lücken. Da muss ich nochmal reinsehen, woher das Problem jetzt kommt. Aber das wird auch noch werden ;)


Als nächstes (nach der Fehlerbehebung) also dann Texturen.... OpenGL-Renderer, wir kommen! :cool:
PAL/PIX Format
Fast alle PAL/PIX Dateien sind BoPa komprimiert in DUNGEON.ALF gespeichert, aber nicht alle.

PAL/PIX Header:
Code:
Offset  Länge
0x0     4 Byte             unbekannt, immer 0x00000012
0x4     4 Byte             unbekannt, immer 0x00000008
0x8     4 Byte             unbekannt, immer 0x00000002
0xC     4 Byte             unbekannt, immer 0x00000002
0x10    4 Byte             unbekannt, immer 0x00000003
0x14    4 Byte             eine unbekannte Größe oder ein Offset (dies + 40 = Offset der Daten (Pixel/Farben); dies - 12 = Länge des Herkunftpfadstring)
0x18    1 Byte             PAL/PIX-Typ: bei PIX-Texturen immer 0x03, bei PAL-Paletten immer 0x07
0x1B    2 Byte             bei PAL/PIX-Typ = 0x03: Breite der Textur
0x1D    2 Byte             bei PAL/PIX-Typ = 0x03: Höhe der Textur
0x23    variabel (s.o.)    Herkunftpfadstring
Daten bei PAL/PIX-Typ = 0x03:
Ein Breite * Höhe langer Array von 1 Byte Integern der Indexe der Farbe des Pixels aus der Farbpalette. Das erste Byte entspricht der oberen linken Ecke, das letzte Byte der unteren rechten.

Daten bei PAL/PIX-Typ = 0x07:
Ein Array von 256 Farben, wobei eine Farbe in vier Byte gespeichert ist:
Code:
1. Byte    immer = 0x00
2. Byte    RGB-Wert für Rot
3. Byte    RGB-Wert für Grün
4. Byte    RGB-Wert für Blau
By the way: FE_PINUP.PIX is NSFW!
Hat FE_PINUP.PIX auch eine Funktion, oder ist das nur eine Belohnung für eifrige Disassemblierer? :D
(06.09.2015, 17:27)Rabenaas schrieb: [ -> ]Hat FE_PINUP.PIX auch eine Funktion, oder ist das nur eine Belohnung für eifrige Disassemblierer? :D
Das ist das Easter Egg in der Feste, das nur gesehen werden kann wenn ein Zwerg der Partyanführer ist.