Als erstes will ich mal erklären was das überhaupt ist.

Es handelt sich um eine .dll zur freien Verwendung, die das Managment über Ressourcen wie Grafiken, Sounds und sonstigen Content ungemein vereinfacht und nette Feature bietet. Genannt hab ich das ganze "Thorium Ressource Manager", auch wenn es im Augenblick eher nur ein Loader ist.
Eigentlich habe ich den Manager für ein Spielprojekt von mir entwickelt aber nachdem ich immer mehr Einfälle hatte ihn zu verbessern, denke ich das ihn auch andere gebrauchen können.
Kernpunkt ist das die Ressourcen asynchron geladen werden. Das ermöglicht das Laden der Ressourcen im Hintergrund während der Spieler spielt oder während ein Intro-Video läuft.
Das war auch recht schnell umgesetzt. Das ganze läuft über 2 eigene Threads, einer zum laden von der HDD und der andere zum dekomprimieren der Ressourcen. Das heisst während der erste Thread die nächste Ressource von der HDD liest, ist der zweite schon mit dekomprimieren der vorherrigen Ressource beschäftigt. Dadurch ist das laden extrem schnell. Dabei können vom Programm soviele Ressourcen wie gewünscht angefordert werden, also es muss nicht gewartet werden bis eine fertig geladen ist. Das währe sogar ziemlich ungut, da in diesem Falle das gleichzeitige Laden und Dekomprimieren nicht zum Zuge kommen würde. Das Programm bekommt über einen Callback mitgeteilt wenn die Ressource fertig geladen und dekomprimiert wurde.
Dann dachte ich mir, hey warum nicht mal was neues einbauen: vollautomatischer Multilanguage-Support. Zu diesem Zwecke habe ich ein eigenes Container/Archiv Format entwickelt, dessen Spezifikationen ich offen lege. Das Format unterstützt verschiedene Sprachversionen von ein und der selben Ressource. Das heisst ihr müsst euch keine Gedanken mehr darum machen, welche Datei ihr bei welcher Sprache laded. Darum kümmert sich der Ressource Manager. Ihr müsst nur beim initialisieren einen Sprachcode angeben.
Das zweite Nebenfeature, welches ich eingebaut habe, ist Versionierung der Ressourcen. Man kann Ressourcen, die in einem Container liegen eine Versionsnummer verpassen. Das heisst wenn mehrere Archive mit Ressourcen im Ressourcen-Verzeichnis liegen und diese teilweise gleiche Ressourcen beinhalten, wird automatisch immer die aktuelleste Ressource geladen.
Ausserdem dient das ganze auch als Art Abstraktion des Ressourcenzugriffs. Nutzt ihr meinen Manager braucht ihr euch keine Gedanken mehr darum machen wo und wie die Ressourcen liegen. Aus Performancegründen für ultra-schnellen Zugriff auf die Ressourcen werden alle Container in einem Verzeichnis eurer wahl indiziert. Das heisst alle Informationen ermittelt und die Container "offen gehalten". So kann, wenn eine Ressource angefordert wird, direkt die Ressource aus dem jeweiligen Container geladen werden ohne das noch Header oder Directorys ausgelesen werden müssen. Zudem erfolg die Identifizierung der Ressourcen intern nicht primär über ihren Namen sondern über einen Hash ihres Namens. Dadurch ist der Zugriff wirklich extrem schnell. Viel schneller als wenn man auf eine einzelne Datei auf der HDD zugreift.
Also ihr könnt so viele Container erstellen wie ihr wollt. Der Ressourcen Manager wird die Ressourcen immer finden. So können auch Patches ganz simpel (wie bei vielen kommerziellen Spielen) einfach als eine einzelne Ressourcendatei einfach mit ins Ressourcenverzeichnis gelegt werden. Dank der Versionisierung werden immer nur die neusten Ressourcen indiziert.
Für Entwicklungs- und Debuggingzwecke indiziert der Ressource Manager auch alle einzelnen Dateien im Ressourcenverzeichnis. Dabei ersetzen einzelne Dateien mit gleichem Namen wie Ressourcen in Containern diese.
Der Zugriff auf einzelne Dateien ist allerdings generell langsamer und alle Feature wie Komprimierung und multilinguale Ressourcen fallen weg.
Ganz fertig ist das Teil noch nicht aber aber es liegen schon ein kleines Beispiel und ein Tool um ThorReCo Ressource Container/Archive zu bauen bei.
Am wichtigsten neben der ThoriumRessourceManager.dll ist die ThReCoWriter.exe. Dieses Tool baut euch Ressource Container nach den unten genannten Spezifikationen zusammen. Es werden noch nicht alle Feature unterstützt aber multilinguale Ressourcen sowie Versionierung sind drinnen. Das Teil ist nur ein kleines Konsolenprogramm, welches als Parameter den Dateinamen einer Textdatei mit Informationen zu den Ressourcen erwartet. Eine Beispieldatei sammt Beispielressourcen in deutsch und englisch liegt bei. Auch schon ein fertig gebautes ThReCo und eine "make test.trc.bat" mit der ihr ohne die Konsole zu öffnen bauen könnt. Die test.txt sollte selbsterklärend sein, das ist die Beschreibungsdatei für die Ressourcen.
Den ThReCoWriter.exe will ich in nächster Zeit weitestgehend durch ein Total Commander Plugin ersetzen. Dann wirds schön komfortabel, zumindest für Total Commander Nutzer.

Eine Example.pb ist auch dabei. Wobei die nicht so schön ist. Die Ressourcen kann man natürlich viel schöner über strukturierte Linked Lists handeln und ich habe auch weitestgehend auf Fehlerprüfung verzichtet. Soll ja nur ein kleines übersichtliches Beispiel sein. Es extrahiert 2 Ressourcen aus dem beiliegenden test.trc.
Besonders interessieren würde mich, welche Komprimierungen ihr den gerne hättet. Im Augenblick ist nur JCalG1 (über PB interne Lib) integriert. Das Container Format sieht aber auch schon bzip2 vor. Wird aber noch nicht vom Manager unterstützt. Also was hättet ihr gerne noch an Komprimierungen? Aber denkt drann, es ist für Games, das heisst es geht um Speed. Der Festplattenspeicher ist unerheblich, es geht darum das Laden der Ressourcen zu beschleunigen. Ausserdem sollte die Komprimierung idealerweise als freie DLL verfügbar sein.
So, hier nun erstmal der Download:
Es handelt sich hier um einen Debug-Build, der langsamer ist als der Master-Build und eine Logdatei im Anwendungsverzeichnis erstellt. Die brauche ich, wenn es Probleme gibt.
Thorium Ressource Manager v0.02
Es gibt nur sehr wenige Prozeduren über die das alles gehandelt wird. Also im Prinzip sehr einfach einzubinden die DLL. Ist allerdings etwas komplizierter zu benutzen als einfache linieare Loader.
Hier die Proceduren:
Code: Alles auswählen
ResInitManager(RessourcePath.s, Language.i, CallbackAddr.i)
RessourcePath gibt den Pfad des Ressourcenverzeichnises an.
Language ist ein Sprachcode. Sprachcodes gehen von 1-255 und sind im Augenblick noch nicht festgelegt. Was ich aber später aus Kompatiblitätsgründen noch tuen werde. Im Augenblick ist nur drauf zu achten das der Sprachcode im Programm dem Sprachcode in den Ressourcencontainern entspricht. Welche Codes ihr dabei verwendet bleibt erstmal noch euch überlassen.
CallbackAddr ist die Adresse für den Callback der angibt das die Ressourcen geladen wurden.
Code: Alles auswählen
;callback procedure format: ProcedureName(ResIndex.i, Addr.i, Size.i, Error.i)
;Errorcodes: 1 = Could not load ressource from HDD.
; 2 = Could not decompress ressource.
ResIndex ist praktisch Handle auf die Ressource, den bekommt ihr wenn ihr die Ressource anfordert und könnt ihn hier verwenden um zu identifiezieren welche Ressource geladen wurde.
Addr ist die Speicheradresse an die die Ressource geladen wurde.
Size ist die Größe der Ressource im Speicher.
Wollt ihr eine Ressource wieder freigeben einfach den Speicher mittels PB's FreeMemory freigeben.
Code: Alles auswählen
ResLoad(ResName.s)
Der Rückgabewert ist der ResIndex, den ihr im Callback prüfen könnt.
Code: Alles auswählen
ResChangeLang(Language.i)
Tut ihr dies aber werden alle Ressourcen neu indiziert. Wichtig! Alle ResIndex Handles werden damit ungültig. Führt einen Sprachwechsel nur durch wenn der Manager gerade nicht beschäftigt ist, also keine Ressourcen läd. Die bereits geladenen Ressourcen bleiben selbstverständlich gültig.
Code: Alles auswählen
ResGetLastError()
Tritt ein Fehler auf gibt eine Prozedur 0 zurück. Ist eine Prozedur erfolgreich gibt sie einen Rückgabewert oder 1 zurück.
Die Fehlercodes sind wie folgt:
Code: Alles auswählen
#ResError_NoAccessFile = 1 ;kein Zugriff auf Datei
#ResError_WrongOrDmgArchiv = 2 ;Archiv ist kein ThReCo oder beschädigt
#ResError_UnsupArchivFormat = 3 ;nicht unterstütztes Archivformat
#ResError_UnsupArchivFotmatVersion = 4 ;nicht unterstütze Version des Archivformats
#ResError_UnsupCompInArchiv = 5 ;nicht unterstützte Kompression wird im Archiv genutzt
#ResError_ArchivIsBig = 6 ;Archiv ist größer als 2GB und dies wird nicht unterstützt
#ResError_ArchivIsHuge = 7 ;Archiv ist größer als 4GB und dies wird nicht unterstützt
#ResError_UnsupDirComp = 8 ;Directory des Archivs ist mit nicht unterstützter Kompression komprimiert
#ResError_AllocMem = 9 ;Speicher konnte nicht alloziert werden
#ResError_ReadFile = 10 ;konnte Datei nicht auslesen
#ResError_Decomp = 11 ;konnte nicht dekomprimieren
#ResError_NoAccessDir = 12 ;kein Zugriff auf Verzeichnis
#ResError_OutOfIndex = 13 ;ausserhalb des gültigen Bereichs
#ResError_ResNotFound = 14 ;Ressource konnte nicht gefunden werden

Zum Abschluß noch das eigene Containerformat ich habe es ThReCo (Thorium Ressource Container) genannt. Dateitypenendung: .trc
Das Format ist noch nicht Final. Es kann passieren das ich noch Änderungen vornehme ohne den Versionszähler des Formats zu erhöhen. Erst wenn ich die Final veröffentliche ist auf die Formatspezifikation 100% verlass.
Auch enthält die Formatspezifikation bereits Dinge die noch nicht unterstützt werden, z.b. bzip2 Komprimierung oder Big- und Huge-File support für Container größer 2GB bzw größer 4GB.
Ich habe die Datentypen einfach in Byteanzahl angegeben. Ist finde ich einfach damit rummzurechnen. Es handelt sich immer um unsignt Ganzzahlen. Esseiden bei der Signatur und dem Ressourcennamen.
Code: Alles auswählen
;ThorReCo (Thorium Ressource Container) format structure
;------
;header
;------
;8 byte signature = ThorReCo
;1 byte format version = 1
;1 byte used compressions (flags)
;1 byte flags
;2 byte alignment
;1 byte compression of directory
;2 byte compressed size of directory (4 byte on huge file)
;2 byte uncompressed size of directory (4 byte on huge file)
;4 byte offset of directory (8 byte on huge file)
;---------
;directory
;---------
;2 byte count of ressources (4 byte on huge file)
;x byte ressource entries
;---------------
;ressource entry
;---------------
;1 byte lengh descriptor for ressource name
;x byte ressource name
;2 byte version of ressource
;1 byte compression
;1 byte count of language entries
;x byte language entries
;--------------
;language entry
;--------------
;1 byte language
;4 byte compressed size of ressource (8 byte on huge file)
;4 byte uncompressed size of ressource (8 byte on huge file)
;4 byte offset of ressource (8 byte on huge file)
;
;------------
;header flags
;------------
;bit0 = ressource versioning
;bit1 = multilingual
;bit2 = big file (file > 2GB)
;bit3 = huge file (file > 4GB)
;bit4 = unused
;bit5 = unused
;bit6 = unused
;bit7 = unused
;
;-----------------------
;compression enumaration
;-----------------------
;00 = none (uncompressed)
;01 = JCalG1
;02 = bzip2
;03 = BriefLZ
;04 = zlib
;
;-----------------
;compression flags
;-----------------
;bit0 = JCalG1
;bit1 = bzip2
;bit2 = BriefLZ
;bit3 = zlib
;bit4 = unused
;bit5 = unused
;bit6 = unused
;bit7 = unused
Hoffe auf Feedback.
