Frage

Ich brauche große Modelle und andere strukturierte Binärdaten auf einer älteren CD-basierte Spielkonsole so effizient wie möglich zu laden. Was ist der beste Weg, es zu tun? Die Daten werden von einer Python-Anwendung exportiert werden. Dies ist ein ziemlich aufwendiges Hobby-Projekt.

requierements:

  • keine Abhängigkeit von vollständig standardkonforme STL -. Ich könnte USTL verwenden obwohl
  • so wenig Aufwand wie möglich. Ziel für eine Lösung so gut. dass es auf dem ursprünglichen Playstation, und doch so modern und elegant wie möglich verwendet werden könnte.
  • keine rückwärts / vorwärts Kompatibilität erforderlich.
  • kein Kopieren von großen Brocken um - vorzugsweise Dateien in dem Arbeitsspeicher im Hintergrund geladen werden, und alle großen Brocken zugegriffen direkt von dort später
  • .
  • sollte nicht auf das Ziel verlassen, um die gleiche endianness und Ausrichtung aufweisen, das heißt ein C-Plug-in Python, die ihre Strukturen auf der Disc-Dumps würde nicht eine sehr gute Idee.
  • sollte die geladenen Daten ermöglicht, mich zu bewegen, wie mit einzelnen Dateien 1/3 die RAM-Größe, die Fragmentierung ein Problem sein könnte. Keine MMU zu Missbrauch.
  • Robustheit ist ein großer Bonus, da meine Aufmerksamkeitsspanne ist sehr kurz, das heißt i ändern Teil des Codes Speicher würde und vergessen, das Laden einer oder vice versa, so dass zumindest ein stummer Schutz wäre schön.
  • Austauschbarkeit zwischen geladenen Daten und zur Laufzeit generierte Daten ohne Laufzeitaufwand und ohne schwere Speicherverwaltung wäre ein schöner Bonus.

ich irgendwie einen halb Plan in Python trivial zu parsen, beschränkt-Syntax C Header, die Strukturen mit Offsets anstelle von Zeigern und Convenience-Wrapper structs / Klassen in der Hauptanwendung mit Getter verwenden würde, die Offsets richtig umwandeln würde typisierte Zeiger / Referenzen, aber ich möchte Ihre Vorschläge hören.

Zur Verdeutlichung:. Die Anforderung in erster Linie um Datenladerahmen und Speicherverwaltung

War es hilfreich?

Lösung

Dies ist eine gemeinsame Entwicklung von Spielen Muster.

Die übliche Vorgehensweise ist, die Daten in einem Offline-Vorprozess Schritt zu kochen. Die resultierenden Blobs können mit minimalem Aufwand strömte werden. Die Blobs sind plattformabhängig und sollte die richtige Ausrichtung und Bytereihenfolge der Zielplattform enthalten.

Zur Laufzeit können Sie werfen einfach einen Zeiger auf die In-Memory-Blob-Datei. Sie können auch mit verschachtelten Strukturen beschäftigen. Wenn Sie ein Inhaltsverzeichnis mit Offsets für alle die Zeigerwerte innerhalb des Blob halten, können Sie dann fix-up die Zeiger auf Punkt an die richtige Adresse. Dies ist ähnlich wie DLL-Laden funktioniert.

Ich habe auf einer Ruby-Bibliothek gearbeitet, bbq , dass ich verwenden, um Daten zu kochen mein iphone Spiel.

Hier ist das Speicherlayout ich für die Blob-Header verwenden:

// Memory layout
//
// p begining of file in memory.
// p + 0 : num_pointers
// p + 4 : offset 0
// p + 8 : offset 1
// ...
// p + ((num_pointers - 1) * 4) : offset n-1
// p + (num_pointers * 4) : num_pointers   // again so we can figure out 
//                                            what memory to free.
// p + ((num_pointers + 1) * 4) : start of cooked data
//

Hier ist, wie ich ein Binär-Blob-Datei laden und reparieren Zeiger:

void* bbq_load(const char* filename)
{
    unsigned char* p;
    int size = LoadFileToMemory(filename, &p);
    if(size <= 0)
        return 0;

    // get the start of the pointer table
    unsigned int* ptr_table = (unsigned int*)p;
    unsigned int num_ptrs = *ptr_table;
    ptr_table++;

    // get the start of the actual data
    // the 2 is to skip past both num_pointer values
    unsigned char* base = p + ((num_ptrs + 2) * sizeof(unsigned int));

    // fix up the pointers
    while ((ptr_table + 1) < (unsigned int*)base)
    {
        unsigned int* ptr = (unsigned int*)(base + *ptr_table);
        *ptr = (unsigned int)((unsigned char*)ptr + *ptr);
        ptr_table++;
    }

    return base;
}

bbq Bibliothek ist nicht ganz bereit für die Prime Zeit, aber es könnte Ihnen einige Ideen auf, wie man sich in python schreiben.

Good Luck!

Andere Tipps

Auf Plattformen wie der Nintendo GameCube und DS, 3D-Modelle sind in der Regel in ein sehr einfachen benutzerdefinierten Format gespeichert:

  • Ein kurzer Header, eine magische Zahl enthält die Datei zu identifizieren, die Anzahl der Ecken, Normale usw. und optional eine Prüfsumme der Daten nach dem Header (Adler-32, CRC-16, etc).
  • A möglicherweise komprimierte Liste der 32-Bit-Floating-Point-3-Tupel für jeden Vektor und normal.
  • Eine eventuell komprimierte Liste von Kanten oder Flächen.
  • Alle Daten im nativen Endian-Format der Zielplattform.
  • Das Komprimierungsformat ist oft trivial (Huffman), einfache (Arithmetic) oder Standard (gzip). Alle diese erfordern sehr wenig Speicher oder Rechenleistung.

Sie Formate wie das als Stichwort nehmen könnten. Es ist eine recht kompakte Darstellung

ist mein Vorschlag ein Format am ähnlichsten Ihre In-Memory-Datenstrukturen zu verwenden, die Nachbearbeitung und das Kopieren zu minimieren. Wenn das bedeutet, das Format selbst erstellen, soll es so sein. Sie haben extreme Anforderungen, so extreme Maßnahmen erforderlich sind.

Ich stelle fest, dass nirgendwo in Ihrer Beschreibung fragen Sie für „einfache Programmierung“. : -)

So, hier ist was für mich den Sinn kommt, als eine Möglichkeit, dies zu schaffen:

  • Die Daten in dem gleichen On-Disk-Format sein sollten, wie es in dem Zielspeicher wäre, so dass es einfach Blobs von der Festplatte in dem Speicher ohne Neuformatierung ziehen kann. Je nachdem, wie viel Freiheit, die Sie wollen in die Dinge in Erinnerung setzen, die „Blobs“ könnte die ganze Datei sein, oder könnten kleinere Bits in ihm sein; Ich verstehe Ihre Daten nicht gut genug, um empfehlen, wie es zu unterteilen, aber vermutlich kann man. Weil wir nicht auf dem gleichen Endian und Ausrichtung auf dem Host verlassen können, müssen Sie ein wenig schlau sein, über Dinge zu übersetzen, wenn die Dateien auf der Host-Seite zu schreiben, aber zumindest diese Weise müssen Sie nur die Klugheit auf einer Seite die Übertragung und nicht auf beiden.

  • Um ein wenig Sicherheit zu gewährleisten, dass die Zielseite und hostseitigen Code übereinstimmt, können Sie dies in einer Form schreiben sollen, wenn Sie eine einzelne Datenbeschreibung zur Verfügung stellen und eine Generation Code hat, der sowohl die generieren C Code Zielseite und der hostseitigen Python Code davon. Man könnte sogar hat Ihren Generator eine kleine zufällige „Version“ Nummer im Prozess erzeugen, und hat die Host-seitige Code schreiben, um diese in die Datei-Header und der zielseitigen es überprüfen, und Sie einen Fehler, wenn sie nicht übereinstimmen . (Der Punkt einen zufälligen Wert ist, dass die einzige Information, biss Sie interessiert, ist, ob sie übereinstimmen, und Sie wollen nicht, es müssen manuell erhöhen.)

Betrachten Sie Ihre Daten als BLOBs in einer SQLite-DB speichern. SQLite ist sehr leicht zu transportieren und lighweight, ANSI C, verfügt sowohl über C ++ und Python-Schnittstellen. Dies wird von großen Dateien kümmern, keine Fragmentierung, mit variabler Länge Datensätze mit dem schnellen Zugriff, und so weiter. Der Rest ist nur Serialisierung von structs auf diese BLOBs.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top