Schlagwort-Archive: PAC-Datei

Exemplarisch wie ich mein SPACOLA-Remake entwickle, eine kleine Anekdote aus meinem Leben als Softwareentwickler: Bei meinen ziellosen Recherchen zur Historie des Atari ST und seiner erstaunlichen, reichhaltigen Public-Domain-Welt stolperte ich über eine kurze Spezifikation des Dateiformats für Bilddateien aus dem sehr beliebten Zeichenprogramm STAD. Der Name ist ein Akronym und steht für ST-aided Design. Das Programm wurde 1986 von Peter Melzer bei den Application Systems Heidelberg veröffentlicht und eröffnete den Nutzern ungeahnte Möglichkeiten – selbst 3D-Modellierung war damit machbar, wenn auch äußerst sperrig und unbequem. Auch meine Wenigkeit verbrachte in den 80ern und 90ern sehr viele Kindheitstage mit dem Malen von lustigen Bildern und Animationen in STAD. Achja, bevor ich darauf angesprochen werde: Ja, rein theoretisch war STAD keine PD-Software, aber wir wissen doch alle wie das damals so lief. Wer kennt nicht die berüchtigte Diskettenwanderung.

Die Bilder konnten in mehreren verschiedenen Formaten abgespeichert werden, darunter unkomprimiert als Doodle, gepackt, oder als DEGAS-Bild (ein weiteres zeitgenössisches und sehr bekanntes ST-Zeichenprogramm). Dabei entwickelte Melzer mit den gepackten .PAC-Bilddateien sein eigenes Bildformat, das die Bildinformationen relativ unspektakulär mittels RLE kodiert und so platzsparend auf der Diskette ablegen kann. Nun, meine Programmierkenntnisse in GFA-BASIC in den 90ern waren leider sehr begrenzt, und so konnte ich seinerzeit nur unkomprimierte Bilder in meine Progrämmchen einlesen, da ich dafür Codebeispiele in meinen Programmierbüchern fand. Im Traum hätte ich nicht daran gedacht, gepackte STAD-Bilder zu laden oder noch verrücktere Bildformate. Ich hatte schlicht keinen Code dafür, und wie andere Entwickler solche Formate in ihren Quellcode einbinden, das war für mich eher schwarze Magie.

Bekanntes Beispielbild „KRUSCH.PAC“ aus STAD. Die einzelnen Fortschritte während der Entwicklung des STAD-PAC-Konverters von oben nach unten. (Rote Bereiche sind nur Hintergrund, wo noch nichts gezeichnet wurde.)

Doch kein Problem ist für einen Haudegen wie mich alt genug um es nicht doch noch zu lösen: Kaum 30 Jahre später will ich es mir beweisen. Ich kann einen STAD-PAC-Konverter entwickeln. Vielleicht nicht mehr unbedingt in GFA-BASIC, aber zumindest in Java, und diesen damit theoretisch für mein Remake-Projekt nutzbar machen. Wofür genau? Das ist mir noch vollkommen unklar, aber wen kümmert es schon. Um eins klarzustellen: Es gibt funktionierenden Cross-Platform-Code in der Wildnis um STAD-Dateien zu laden. Unter anderem der beliebte Bildbetrachter “XnView MP” lädt alle STAD-PAC-Dateien erfolgreich, was mich anfangs extrem überrascht hat, da es doch heutzutage ein mindestens äußerst exotisches und rares Dateiformat ist. Scheint so als wolle der Entwickler dem Anspruch gerecht werden, möglichst viele Dateiformate zu beherrschen. Leider ist ausgerechnet die Software dieses Entwicklers natürlich nicht quelloffen, und daher für Studien nicht verfügbar, doch mit Hilfe der im Internet frei verfügbaren Spezifikationen wollte ich es auf jeden Fall selbst versuchen.

Und so setzte ich mich daran und begann die Spezifikation zu implementieren. Aus meiner Kindheit besitze ich unzählige eigene PAC-Dateien mit Bildchen, ich konnte aber zusätzlich sehr viele Beispieldateien im Netz finden und bei der Entwicklung zum Testen nutzen. Wie die Spezifikation beschreibt, gibt es zwei Sorten von STAD-PAC-Dateien: Die vertikal gepackten, und die horizontal gepackten. Die Implementierung der RLE-Dekodierung war dann auch tatsächlich nicht so schwer, vieles an Vorarbeit zum Bytestream-Handling hatte ich bereits früher erledigt bei der Entwicklung an meinem Shapelist- und Dongleware-PAC-Konverter. Schwierig wird es, wenn man zusätzlich Quellen im Internet findet, die zwar ebenfalls das Bildformat beschreiben, aber leider Fehler enthalten, wie einen falschen Runcount zu verwenden. Merke: Man sollte nicht alles glauben, was im Netz steht.

Schon relativ schnell erkannte ich die erste größere Schwierigkeit: Alle Internetquellen haben die Tatsache gemeinsam, dass sie die RLE-Dekodierung genau dokumentieren, aber bei den unkomprimierten Bilddaten nur noch ganz abstrakt von “use bytes” die Rede ist. Es wird tatsächlich nirgends beschrieben, wie das Bild damit genau gezeichnet werden soll. Der Teil fehlt einfach, so als wäre er entweder unnötig oder komplett trivial. Und selbst wenn die Bezeichnung “vertically packed” es so darstellt, die Pixel fortlaufend von oben nach unten zu zeichnen, ist leider nicht des Rätsels Lösung. Und so verbrachte ich noch eine Handvoll weiterer Stunden damit, die Zeichenroutinen zu debuggen, zu reverse engineeren und inkrementelle Fortschritte zu feiern, bis ich endlich eine fehlerfreie Implementierung in den Händen hielt. Gerne möchte ich das Internet mit meinen mühsam selbst gesammelten Erkenntnissen bereichern und die Spezifikationen um die überall fehlenden Informationen ergänzen:

Die vertikal gepackten Bilder (mit dem Header “pM86”) werden in Blöcken von je 8×8 Pixeln gezeichnet, wobei die Pixel innerhalb des Blocks zuerst von links nach rechts und von oben nach unten gezeichnet werden, während die Blöcke zuerst von oben nach unten und von links nach rechts gezeichnet werden. Am Ende erhält man ein binäres Vollbild mit (mehr oder weniger) 640×400 Bildpunkten. Die horizontal gepackten Bilder (mit dem Header “pM85”) werden als fortlaufende Pixelsequenz von links nach rechts und von oben nach unten gezeichnet. Vertikal gepackte Bilder sind dabei in einer erstaunlichen Mehrheit vorzufinden, während das horizontal gepackte Format vermutlich älter ist und seltener vorkommt. Immerhin ist das STAD-PAC-Format um mehrere Größenordnungen weniger komplex als das Dongleware-PAC-Format, aber selbst hier musste ich ein wenig experimentieren und basteln.

Das ebenfalls bekannte STAD-Beispielbild „ESCHER1.SEQ“, dargestellt im STAD-PAC-Konverter

Aufgefallen ist mir außerdem, dass viele STAD-PAC-Dateien mehr Zeichenanweisungen im Bytestream enthalten als es zu zeichnende Pixel auf dem Bildschirm gibt. Aus diesem Grund muss meine Implementierung überzählige Runcounts und überflüssige Bytes am Ende der Datei verwerfen, wenn das Bild vorzeitig fertig ist. Das fand ich durchaus ein wenig seltsam und unnötig. Ebenfalls bemerkenswert, dass besagter Bildbetrachter XnView MP die wenigen horizontal gepackten STAD-Dateien zwar korrekt entpackt, aber aus irgendeinem Grund falsch darstellt: Es wird ein Bild erzeugt, das 640×400 Pixel enthält, doch es wird vertikal gestreckt auf 440 Pixel. Und selbst wenn man dieses Bild direkt nach PNG konvertiert, wird es mit diesem seltsamen Streckfaktor (DPI bzw. Pixels per Unit unterschiedlich in Y-Richtung) in den Metadaten der PNG-Datei gespeichert.

Da kann ich doch glatt stolz darauf sein, dass meine Implementierung einen Fehler weniger hat als einer der bekanntesten Bildbetrachter überhaupt. Alles in allem wieder einmal ein schönes, erfolgreiches, produktives Wochenende, an dem ich eine kleine historische Software-Knobelaufgabe lösen konnte. Das SPACOLA-Remake kann nun gepackte STAD-Bilder laden, falls es mal nötig wäre. Zusätzlich habe ich auch wieder die Arbeit an einigen kleineren Aspekten an dem Spiel aufgenommen. Wie das eben so ist, ich muss mich mal wieder in das Thema reinfinden, und dafür eignen sich am besten die einfacheren Aufwärm-Themen.

Ich will jetzt nicht unbedingt behaupten, dass ich fleißig bin, aber wenn ich mal ausnahmsweise nicht faul bin, dann bin ich so richtig nicht faul. Nach einer längeren Abwesenheit und gleichzeitigen Arbeitspause an meinem Spiele-Remake, bin ich nun endlich wieder dran. Mich hat aus irgendeinem mysteriösen Grund plötzlich wieder die Motivation eingeholt, und sofort konnte ich zumindest wieder etliche Kleinigkeiten angehen und Fehler korrigieren. Allerdings habe ich durch Zufall ganz unerwartet einen weiteren Meilenstein bei der Entwicklung erreicht; einen Punkt auf meiner To-Do-Liste, den ich definitiv irgendwann umsetzen wollte, selbst wenn dies einen Nutzen nur theoretischer Natur auf dem Papier bringt.

Was bisher geschah: Einem unfassbar mäßig begabten Entwickler eines Spiele-Remakes, der zwar nicht vom Erfolg seines Projektes überzeugt, aber dafür wenigstens nicht von seinem Ziel abzubringen ist, war es gelungen, die Original-Dateien des Atari ST-Spiels SPACOLA mit Hilfe eines Debuggers zu entpacken und anschließend sogar das undokumentierte Format der Sprite-Dateien zu dechiffrieren und einen eigenen Konverter zu schreiben. Dies sollte ihm endlich einen wichtigen Einblick in die Hintergründe der Unterhaltungssoftware einer längst vergessenen Zivilisation geben. Wie hatten unsere Vorfahren einst Spiele entwickelt? Wurden die Quellcodes damals noch in Keilschrift verfasst? Mussten Benutzer an einer Kurbel drehen, wenn sie ihren Heimcomputer starten wollten? Waren antike Computerprogramme auch nur in schwarzweiß? (In diesem Fall, ja!). Unermüdlich arbeitete der selbsternannte Software-Archäologe weiter an den historischen Dokumenten, um vielleicht irgendwann einmal das perfekte Remake zu erschaffen.

Teil 3 meines fortlaufenden Hintergrundberichts: Es war eigentlich reiner Zufall als ich im Internet auf die Reverse-Engineering-Erkenntnisse von Jeremy Sawicki aus dem Jahr 2003 stieß. Der hatte diverse OXYD-Spiele in ihren Farbversionen für den IBM-PC erfolgreich analysiert und deren Formatspezifikationen offengelegt, darunter das Levelformat, die Grafik- und Sounddateien. Seine Dokumentation war unter anderem nützlich bei der Entwicklung des freien OXYD-Klons Enigma. Als ich mir die Angaben zum Grafikformat genauer ansah, erkannte ich plötzlich viele Gemeinsamkeiten zu den PAC-Dateien, die in den alten Monochromversionen der frühen Dongleware-Klassiker Verwendung fanden. Diese Dateien enthielten binäre Vollbildgrafiken für die Spiele seit Esprit (1989) und bis mindestens OXYD2 (1991).

Ich hatte mich natürlich längst selbst mehrfach daran versucht, das seltsame Dateiformat zu dekodieren, zuletzt auf Grund meiner Erfolge beim Konvertieren der Sprite-Dateien, doch das PAC-Format widersetzte sich meinen Annäherungsversuchen konsequent. Bis auf einige sehr offensichtliche Headerinformationen konnte ich kaum sinnvolle Werte herauslesen, und meine einzigen Erkenntnisse über das Kompressionsverfahren bestanden darin, dass das Bild in Blöcke unterteilt wird, und die Pixelinformationen grundsätzlich durch ein XOR-Verfahren invertiert von oben nach unten beschrieben werden. Durch Manipulieren der Dateien im Hexeditor und anschließendem Beobachten der Auswirkungen in OXYD, stellte ich erstaunt fest, dass die Dateistruktur eine sehr eigenwillige sein musste, weil oft komplett unvorhersehbare und unintuitive Artefakte im Bild dadurch enstanden. Als ich keinerlei Gesetzmäßigkeiten ausmachen konnte, gab ich mein Vorhaben desillusioniert auf.

Seit heute weiß ich endlich sehr genau, was das große Problem war. Von Sawickis Arbeit angespornt, begann ich endlich an der Entwicklung eines eigenen Konverters, den ich letztlich in mein Remake einbauen wollte, so wie bereits getan beim Konverter für Sprite-Dateien. Ich studierte die Formatspezifikationen und implementierte die Dekompressions- und Zeichenroutinen. Ohne nun zu sehr ins Detail zu gehen (wer alles wissen möchte, kann die Originalseite lesen), besteht jede Packed-Bitplane-Datei aus einem Header, einem Bitstream und einem Bytestream. Der Bitstream beschreibt dabei die gesamte Struktur des Bildes, sowie Angaben über die Kompressionsmethodik, und der Bytestream enthält die tatsächlichen Pixeldaten, die entsprechend gezeichnet werden müssen.

Jedes Bild hat die Auflösung von 640×400 Bildpunkten und ist in Blöcken von je 16×16 Pixeln aufgeteilt. Der Bitstream beschreibt dabei, wie das Bild nacheinander in Reihen von Blöcken, Blöcken, Blockquadranten und Reihen von Pixeln in immer kleinere Häppchen aufgespalten wird, wobei jedes Element entweder übersprungen oder gezeichnet werden kann. Müssen Pixel gezeichnet werden, so wird ein Byte aus dem Bytestream gelesen und dessen Bits als Pixel interpretiert, abhängig von einer der Pixelreihen darüber, die miteinander XOR-verknüpft werden, also je nachdem ob ein Bit gekippt wird oder nicht. Die Formatspezifikation von Sawicki ist dabei technisch betrachtet soweit korrekt, aber leider an mehreren Stellen etwas unpräzise formuliert, so dass ich mehrere Fehler machte, deren Behebung mich viel Zeit gekostet hat.

Das Titelbild „TITLE.PAC“: Die einzelnen Fortschritte während der Entwicklung des PAC-Konverters von oben nach unten. (Rote Bereiche sind nur Hintergrund, wo noch nichts gezeichnet wurde.)

Während der Entwicklung fiel mir jedoch auf, dass Sawicki eines der Features des proprietären Dongleware-Formats definitiv nicht kannte: Neben dem Invert-Flag, das festlegt, ob das fertige Bild noch invertiert werden muss, gab es in meinem Archiv eine einzelne Datei, die ein undokumentiertes Flag setzt. Zum Glück konnte ich am Output des Konverters bereits erkennen, was dem Bild fehlte: Es musste ein Dithered Pattern („Schachbrettmuster“) mittels XOR über das gesamte fertige Bild gezeichnet werden, um die ursprüngliche Grafik wiederherzustellen. Dieser Modus wird wohl zwar nur sehr selten angewandt, aber mein Konverter unterstützt dieses Feature nun ebenfalls. Im Endeffekt war es mir in geschätzt sechs bis sieben Stunden gelungen, eine Implementierung abzuliefern, die sämtliche 16 PAC-Dateien, die ich aus vier Spielen gesammelt hatte, fehlerfrei einzulesen und anzuzeigen vermochte.

Ohne das hilfreiche Dokument wäre ich immer noch nicht schlauer, und sonst einen Konverter zu schreiben, hätte ich wahrscheinlich nur geschafft wenn ich viele Wochen und Monate in mühsames Debugging der Spiele investiert hätte. Ob ich mir diese Zeit jemals hätte nehmen wollen, sei mal dahingestellt. Nun bin ich umso glücklicher über diese angenehme Abkürzung, die ich nehmen konnte. Der Konverter ist fertig und bereits ins Remake eingebaut. Dadurch bin ich jetzt endlich in der Lage, auch die originalen Grafikdateien in unveränderter Form im Remake einzulesen und zu verwenden. Das macht – wie eingangs im Absatz beschrieben – für den Spieler absolut keinen Unterschied, für mich als Entwickler mit Perfektionsdrang aber einen gewaltigen.

Mein SPACOLA-Remake kann nun die ursprünglichen Sounddateien, die Sprites und die Grafikdateien korrekt lesen. An der Interpretation der originalen Leveldaten arbeite ich mich weiterhin Schritt für Schritt voran, sie werden aber immerhin schon komplett eingelesen. Alles was jetzt noch vollständig fehlt: Die Musikdaten im SMS Synthesizer-Format von Jürgen Piscol. Ob ich dieses Kapitel jemals abschließen werde, lässt sich im Moment noch nicht einmal sagen. Andererseits, wer weiß schon, ob sich nicht doch wieder jemand findet, der zufällig eine detaillierte Analyse des Formats in Schriftform für mich zur Einsicht hat. Dann könnte nämlich alles ganz schnell gehen.

Das „Boss Is Coming“-Bild aus OXYD2, dargestellt im PAC-Konverter, zeigt den Datenbank-Manager „Phoenix“ von den Application Systems Heidelberg

Und falls sich nun jemand fragt, wieviele PAC-Dateien in SPACOLA Eclipse denn nun eingelesen und angezeigt werden können: Es sind ganze vier Dateien! Erstens, das Titelbild beim Laden des Spiels. Zweitens, das typische HUD mit dem Radar auf der rechten Seite. Drittens, der Rentenbescheid zum Ausdrucken nach Abschluss des letzten Levels. Die vierte und letzte PAC-Datei ist tatsächlich ein ungenutztes Bild, das die Kontaktadresse des Dongleware-Verlages enthält. Vermutlich wurde es in einer früheren Version des Spiels verwendet, und dann durch ganz normalen Text in der Dongleware-Schriftart ersetzt. Alle diese vier Originaldateien werde ich nun ins Remake einbauen und in irgendeiner Weise nutzen, damit sich der ganze Entwicklungsaufwand auch gelohnt hat.