roybaer / mdcii-engine

Plattformunabhängiger Nachbau der Grafikengine von Anno 1602 – Platform independent remake of the graphics engine of Anno 1602/1602 AD
GNU General Public License v2.0
25 stars 5 forks source link

grafiken.txt und bebauung.txt #8

Open siredmar opened 5 years ago

siredmar commented 5 years ago

Es gibt die Dateien grafiken.txt und bebauung.txt, welche Informationen zum mapping zu den Original spieldateien enthalten. Fragen:

  1. Wie wurden diese files erzeugt?
  2. Sind sie bereits komplett?
  3. Der Unterschied zwischen grafiken.txt und grafiken_1602.txt ist NINA vs. Vanilla 1602. Bekommt man den Unterschied anhand der bsh Dateien zur Laufzeit heraus?

Ziel: Ein self contained Binary ohne andere Abhängigkeiten als das original Spiel. D. H. Pflege der bisherigen txt Dateien im Quellcode mit einer Erkennung, welche Variante von Anno (NINA A, Vanilla) installiert ist bzw. mit Kommandozeileparameter zum auswählen.

roybaer commented 5 years ago
  1. Die Dateien wurden manuell durch optischen Abgleich der Ausgabe von inselbmp mit Screenshots erzeugt.
  2. Sie sollten vollständig sein, garantieren kann ich das aber nicht.
  3. Stadtfld.bsh enthält unterschiedlich viele Bilder. Das sollte sich jetzt mit Bsh_leser::anzahl() leicht überprüfen lassen. Bloß gab es die Funktion nicht von Anfang an, weil die Anzahl in der Datei nicht explizit gespeichert ist.

Auf lange Sicht müsste man diese Informationen sowieso aus Haeuser.cod auslesen. Das sind „verschlüsselte“ Textdateien (Zweierkomplement jedes Bytes), die mit mdcii-codcat „entschlüsselt“ werden können. Vielleicht kann man da einen Boost-Spirit-Parser für bauen.

Green-Sky commented 5 years ago

Ich hab vor Ewigkeiten mal einen ".cod" Interpreter grbaut, der hat aber eine mieserable Code-Quallität. Ich könnte bei Bedarf den Code in eine private Repo hochladen. Den Code hab ich dann auch noch benutzt um die Daten in eine SQLite DB zu packen. Dazu kommen noch Listen die aus der EXE direkt entnommen wurden. Jene DB könnt ich auch zur verfügung stellen, hier bin ich mir aber nicht sicher ob das erlaubt ist.

roybaer commented 5 years ago

Die Listen aus der EXE-Datei will ich schon aus rechtlichen Gründen definitiv nicht sehen. SQLite halte ich in dem Kontext auch für eher mäßig sinnvoll. Es dürfte dann wohl besser sein, den Parser neu zu schreiben. Die notwendigen Indizes der Grafiken in den BSH-Dateien könnte man dann von grafiken.txt ableiten.

Green-Sky commented 5 years ago

Die Listen aus der EXE-Datei will ich schon aus rechtlichen Gründen definitiv nicht sehen.

Ok, aber ich werde die Offsets zu den Listen (Gebäude IDs) in der EXE irgendwann irgendwo veröffentlichen.

SQLite halte ich in dem Kontext auch für eher mäßig sinnvoll.

Ich hab mich aus analyse Zwecken damals dafür entschieden. Die Daten sind relational, warum also nicht. Ob das für die Engine dann Sinn macht bin ich mir auch nicht sicher.

Es dürfte dann wohl besser sein, den Parser neu zu schreiben.

Hab ich seit Damals vor, komm aber nie dazu. :see_no_evil:

Die notwendigen Indizes der Grafiken in den BSH-Dateien könnte man dann von grafiken.txt ableiten.

Die sind in der haeuser.cod zu finden.

Aber meine Absicht mit meinem Kommentar war eigentlich zu sagen, dass ich eine grafiken.txt Datei erzeugen könnte.

siredmar commented 5 years ago

Ich bin gerade dabei einen COD Parser unter Verwendung von Protobuf zu implementieren. Protobuf deswegen, weil damit die ausgerollte Struktur der COD Dateien ueber sich wiederholende und rekursive Objekte ganz gut darstellen laesst, und es so wie C++ start typisiert ist. D.h. der Umgang damit fuehlt sich wesentlich nativer an als z.b. mit JSON zu arbeiten. Wie dem auch sei, ich habe mich bei der Implementierung anfangs an die von @cmfcmf aus Anno2018-godot gehalten, bin dann aber startk abgewichen. Die Grundiee, die Zeilen per Regex zu parsen, ist aber bstehen geblieben. Nun hab ich quasi meine Objekte auf der Hand, der vollstaendig geparsten COD Datein. Alle relativen Variablen sind berechnet, Wo Konstanten definiert sind, werden diese verwendet, der Objekt Fill fuegt die Variablen des eingefuegten Objekts hinzu. Das Ergebnis sieht dann zumindest von den Dateninhalten der einzelnen Objekte ziemlich aehnlich zu der JSON Variente von @cmfcmf aus. Die Frage ist nun: wir haben z.B. grafiken.txt Wenn ich mir mein erzeugtes Objekt fuer den Galgen mal so ansehe, dann finde ich die die Variable "Gfx" mit Wert 5372 wieder. Dasselbe finde ich auch in z.b. grafiken.txt wieder.

Protobuf Galgen Objekt:

objects {
    name: "474"
    variables {
      variable {
        name: "Id"
        value_int: 20841
      }
      variable {
        name: "Gfx"
        value_int: 5372
      }
      variable {
        name: "Baugfx"
        value_int: 376
      }
      variable {
        name: "Kind"
        value_string: "GEBAEUDE"
      }
      variable {
        name: "Size"
        value_array {
          value {
            value_int: 1
          }
          value {
            value_int: 1
          }
        }
      }
      variable {
        name: "Rotate"
        value_int: 1
      }
      variable {
        name: "Tuerflg"
        value_int: 1
      }
      variable {
        name: "AnimAdd"
        value_int: 4
      }
      variable {
        name: "AnimAnz"
        value_int: 6
      }
      variable {
        name: "AnimTime"
        value_int: 220
      }
    }
    objects {
      name: "HAUS_PRODTYP"
      variables {
        variable {
          name: "Kind"
          value_string: "GALGEN"
        }
        variable {
          name: "Radius"
          value_int: 16
        }
        variable {
          name: "Kosten"
          value_int: 20
        }
        variable {
          name: "Bauinfra"
          value_string: "INFRA_GALGEN"
        }
      }
    }
    objects {
      name: "HAUS_BAUKOST"
      variables {
        variable {
          name: "Werkzeug"
          value_int: 1
        }
        variable {
          name: "Holz"
          value_int: 2
        }
        variable {
          name: "Money"
          value_int: 100
        }
      }
    }
  }

Auszug aus grafiken.txt

841 5372 galgen

Selbe Frage fuer bebauung.txt

Dieselbe Nummer 841 ist hier fuer den Galgen benutzt.

Auszug aus bebauung.txt

841 1 1 4 6 1 1 1 0 galgen

Jezt die Frage: Woher kommt die Zahlen z.b. 841? Sind diese frei gewaehlt um eine Zuordnung treffen zu koennen oder hat das irgendeine tiefere Bedeutung?

Green-Sky commented 5 years ago

Jezt die Frage: Woher kommt die Zahlen z.b. 841? Sind diese frei gewaehlt um eine Zuordnung treffen zu koennen oder hat das irgendeine tiefere Bedeutung?

So fern ich mich richtig erinnere, werden alle IDs +20k gerechnet. Nur in dem Insel Datei Format sind die Zahlen so klein. Die IDs in den GAD dateien müssten übrigens irgendwo bei +35k liegen.

edit: Um mehr auf deine Frage einzugehn: Die IDs sind in den COD/GAD Dateien definiert. Allerdings sind die nicht frei wählbar, weil in der EXE statische Arrays mit den IDs zwegs Kathegorie sind. (unsauber programmiert)

siredmar commented 5 years ago

Ah... Ein Wald mit vielen Bäumen... 🙂 Ok, das reicht mir erstmal um die Grafiken.txt und Bebauung.txt Dateien loszuwerden und die Sachen aus den geparsten cod Dateien zu generieren.

roybaer commented 5 years ago

Ich bin gerade dabei einen COD Parser unter Verwendung von Protobuf zu implementieren. Protobuf deswegen, weil damit die ausgerollte Struktur der COD Dateien ueber sich wiederholende und rekursive Objekte ganz gut darstellen laesst, und es so wie C++ start typisiert ist. D.h. der Umgang damit fuehlt sich wesentlich nativer an als z.b. mit JSON zu arbeiten.

Das klingt doch sehr gut! Wenn es statisch typisiert ist, ist es wahrscheinlich auch deutlich effizienter.

Ah... Ein Wald mit vielen Bäumen... slightly_smiling_face Ok, das reicht mir erstmal um die Grafiken.txt und Bebauung.txt Dateien loszuwerden und die Sachen aus den geparsten cod Dateien zu generieren.

Loswerden im Sinne von „nicht brauchen“. Die beiden Dateien sollten trotzdem im Repo bleiben.

siredmar commented 5 years ago

Hab noch ein paar Fragen am Beispiel fuer den Galgen:

;           _________ ID
;          / ________ Breite (d.h. Breite des Gebäudes)
;         / / _______ Höhe (d.h. Länge des Gebäudes)
;        / / / ______ Richtungen (1 oder 4)
;       / / / / _____ Animationsschritte
;      / / / / / ____ Grundhöhe (0 oder 1)
;     / / / / / / ___ Bauhöhe (0 oder 1)
;    / / / / / / / __ Anzahl optisch unterscheidbarer Lagerstände
;   / / / / / / / / _ Kategorie (0=keine, 1=Land, 2=Feld, 3=Haus, 4=Betrieb)
;  / / / / / / / / /
841 1 1 4 6 1 1 1 0 galgen

Ich kann aus dem Objekt die Breite, Hoehe (Size Array), Richtungen (Rotate), Animationsschritte (AnimAnz), und evtl. die Kategorie (Kind) rausholen. Die Information Grundhoehe, Bauhoehe und Anzahl optisch unterscheidbarer Lagerstaend kann ich nicht zuordnen. Kann mir jemand sagen, ob die ueberhaupt in haeuser.cod zu finden sind? Wie bist du auf diese Namensgebung gekommen?

Auszug bebauung.hpp

struct Bebauungsinfo
{
  uint8_t breite;
  uint8_t hoehe;
  uint8_t richtungen;
  uint8_t ani_schritte;
  uint8_t grundhoehe;
  uint8_t bauhoehe;
  uint8_t lagerstaende;
  uint8_t kategorie;
};
roybaer commented 5 years ago

Also dass der Galgen keinen sichtbaren Lagerstand hat, überrascht mich eher weniger. Die Grundhöhe dient der Berechnung des Y-Versatzes der Grafik auf dem Bildschirm. Es kann gut sein, dass dieser Versatz in den COD-Dateien direkt gespeichert ist. Die Bauhöhe gibt nur an, ob z.B. ein Soldat darauf oder dahinter gezeichnet wird, d.h. ob es Boden oder etwas anderes ist. Als ich mir das ausgedacht hatte, wusste ich noch überhaupt nicht, dass die Verschlüsselung der COD-Dateien so extrem primitiv ist und hatte die folglich noch nie gesehen.

Green-Sky commented 5 years ago

Die Information Grundhoehe, Bauhoehe und Anzahl optisch unterscheidbarer Lagerstaend kann ich nicht zuordnen. Kann mir jemand sagen, ob die ueberhaupt in haeuser.cod zu finden sind?

Hast du ObjFill schon implementiert? Schau dir mal das erste Objekt (Nummer: 0) im HAUS Objekt Array an. Da sind die ganzen Defaults drin, die dann mittels ObjFill: 0,MAXHAUS angewendet werden.

siredmar commented 5 years ago

Als ich mir das ausgedacht hatte, wusste ich noch überhaupt nicht, dass die Verschlüsselung der COD-Dateien so extrem primitiv ist und hatte die folglich noch nie gesehen.

Primitiv ist gut. Das Dateiformat ist gelinde gesagt gefühltes Chaos mit inkonsistent in der Benutzung zwischen verschiedenen cod Dateien. Da haben sich die Entwickler damals echt ein hartes Brett überlegt. Ich würde gerne mal den original source zum cod parsing sehen! 🙂

siredmar commented 5 years ago

Die Information Grundhoehe, Bauhoehe und Anzahl optisch unterscheidbarer Lagerstaend kann ich nicht zuordnen. Kann mir jemand sagen, ob die ueberhaupt in haeuser.cod zu finden sind?

Hast du ObjFill schon implementiert? Schau dir mal das erste Objekt (Nummer: 0) im HAUS Objekt Array an. Da sind die ganzen Defaults drin, die dann mittels ObjFill: 0,MAXHAUS angewendet werden.

Ja, den objfill hab ich implementiert. Mit genau dieser objfill Zeile konnte ich bis dato aber nix anfangen. Ich vermute mal, dass dieses base Objekt in jedes nachfolgende kopiert wird. Also alle Objekte mit ID 0 bis MAXHAUS. Stichwort inkonsistenz: MAXHAUS ist nirgends definiert 🤮 Meine objfill Implementierung kann quasi sich ein Objekt aktiv holen und einbauen. Der oben genannte objfill unterscheidet sich hier ja grundlegend. Muss ich noch einbauen. Wenn das drin ist, dann könnte es sein, dass die fehlenden Parameter in meiner Frage von oben drin sind. Also nochmal ran 👍

siredmar commented 4 years ago

Die Dateien im Rahmen von #15 entfernt worden, da es jetzt einen COD Parser gibt.