Alle Formatseiten ↓
Grafik und Medien

GAF – Graphics Animation Format

Aus coreprime/kbot @ 0ab97bf · Auf GitHub bearbeiten

GAF speichert Sprite-Animationen mit indizierten Farben. Fast jedes animierte 2D-Element in Total Annihilation ist ein GAF: Cursor, Mauszeiger, Explosionen, Einheitenteile, schwankende Bäume, Waffensymbole, Lavablasen, einfach alles. TA: Kingdoms verwendet denselben Container unter der Endung .taf für seine Animationen mit Palette wieder (die Palette kommt aus einer Begleitdatei). TA:K liefert außerdem eine Truecolor-Variante von .taf aus, die statt Indizes 16-Bit-ARGB-Pixel speichert – sie hat eine eigene Seite, TAF / TSF.

Sequenz cursormove aus cursors.gaf    einzelner Frame aus cursorselect

Tip

Probier es selbst.

kbot gaf list   anims/cursors.gaf                                      # sequences, frame counts, loop flag
kbot gaf export anims/cursors.gaf --format gif --sequence 0 --target cursor.gif
kbot gaf dump   anims/cursors.gaf --target ./cursors                   # one PNG per frame

Alle Flags stehen in der kbot gaf-Referenz der CLI.

Aus Go heraus. Verwende formats/gaf:

import "github.com/coreprime/kbot/formats/gaf"

r, _ := gaf.LoadFromFile("anims/cursors.gaf")
defer r.Close()
sequences, _ := r.ReadSequences()
for _, seq := range sequences {
    fmt.Println(seq.Name, len(seq.Frames))
}

Auf einen Blick

┌─ Header (12B) ─┐
│ ver  N  pad    │
└────────┬───────┘
         ▼
┌─ Sequence offset table ─┐  N × uint32 absolute offsets
└───┬─────────────────────┘
    ▼
┌─ SequenceHeader (40B) ─┐
│ frameCount, loop word, │
│ +4 word, name[32]      │
└─────────┬──────────────┘
          ▼
┌─ FrameListItem (8B) × frameCount ─┐  ptr + tick duration
└───┬───────────────────────────────┘
    ▼
┌─ FrameInfo (24B) ─┐
│ size, origin,     │
│ transparency,     │
│ compressed?,      │
│ layers, +11 byte  │
│ ptrPixelData      │
└─────┬─────────────┘
      ▼
┌─ Pixel data: raw or run-encoded ─┐
└──────────────────────────────────┘

Ein GAF ist ein flaches Array aus Sequenzen; jede Sequenz ist ein Array aus Frames; jeder Frame ist eine Bitmap aus Palettenindizes der Größe Breite × Höhe mit einem Ursprungspunkt und (optional) RLE-artigen Transparenzläufen. Frames können „Unter-Frames“ enthalten, sodass ein logischer Animationsschritt aus mehreren übereinandergelegten Ebenen zusammengesetzt ist.


Header (12 Byte)

typedef struct {
    uint32 Version;        // 0x00010100 (or 0 for a handful of stock GAFs)
    uint32 SequenceCount;  // Number of animations in the file
    uint32 Unknown1;       // Always 0
} GAFHeader;
Feld Anmerkungen
Version 0x00010100 bei allen Werkzeugen von Drittanbietern. Cavedogs anims/terrain.gaf und anims/vismasks.gaf werden mit Version == 0 ausgeliefert. Das Spiel prüft das Wort nicht; kbot liest jeden Wert (ein unbekannter wird als Warnung gemeldet) und schreibt 0x00010100.
SequenceCount Direkt dahinter folgen SequenceCount × uint32 absolute Datei-Offsets, von denen jeder auf einen SequenceHeader zeigt. Das Spiel verwendet nur die unteren 16 Bit, gelesen als vorzeichenbehafteter Wert: 1–32.767 Sequenzen, keine bei null oder einem negativen Wert.
Unknown1 Immer null; beim Schreiben null ausgeben.

Sequenz (40 Byte)

typedef struct {
    uint16 FrameCount;
    uint16 LoopFlags;      // +2: low byte non-zero = the sequence loops
    uint32 Unknown4;       // +4: not used by the game; stock files store 0
    char   Name[32];       // NUL-padded, case-preserved
} GAFSequence;

Das Spiel wiederholt eine Sequenz in einer Schleife, wenn das untere Byte von LoopFlags gesetzt ist, und spielt sie einmal ab (und bleibt dann auf dem letzten Frame stehen), wenn es 0 ist. Jede Sequenz der Originaldateien speichert 1. kbot behält beide Wörter bei, wenn es eine Datei neu schreibt, und kbot gaf build gibt einer Sequenz ohne sequence.csv den Originalwert 1.

Darauf folgen FrameCount × FrameListItem:

typedef struct {
    uint32 PtrFrameInfo;   // → FrameInfo
    uint32 Duration;       // Game ticks (30 ticks = 1 second); low 16 bits used
} FrameListItem;

Das Spiel liest nur die unteren 16 Bit von Duration und zeigt einen Frame für max(Duration, 1) Ticks seines 30-Hz-Animationstakts.

Sequenznamen sind wichtig – das Spiel sucht Animationen über ihren Namen (z. B. verweist UnitInfo auf corpyro_smoke aus dem Skript corpyro.gaf). Behandle sie beim Abgleichen als ASCII ohne Unterscheidung von Groß- und Kleinschreibung.


Frame (24 Byte Info + Nutzdaten)

typedef struct {
    uint16 Width;
    uint16 Height;
    int16  OriginX;            // Render anchor, may be negative
    int16  OriginY;
    uint8  TransparencyIndex;  // Key: transparent in raw frames
    uint8  Compressed;         // 0 = raw bitmap, non-zero = run-encoded
    uint8  LayerCount;         // +10: 0 = simple frame, >0 = composite of layers
    uint8  Blend;              // +11: set on a layer = drawn translucently
    uint32 Unknown2;           // +12: editor scratch, not used by the game
    uint32 PtrFrameData;       // → pixel bytes OR layer pointer table
    uint32 Unknown3;           // Always 0
} FrameInfo;

OriginX / OriginY beschreiben den Ankerpunkt, an dem der Frame in die Welt geblittet wird. Bei einem Explosions-Sprite ist der Ursprung meist der Mittelpunkt der Explosion; bei einem Cursor ist es das Hotspot-Pixel.

Frames mit Ebenen

Ist LayerCount > 0, ist PtrFrameData ein Array aus LayerCount × uint32 Zeigern auf verschachtelte FrameInfos, keine Pixeldaten. Jede Ebene wird in Array-Reihenfolge (von hinten nach vorn) gezeichnet, mit ihrem Hotspot auf dem Hotspot des äußeren Frames. Eine Ebene, deren Byte +11 gesetzt ist, wird über die Transluzenztabelle gezeichnet, statt kopiert zu werden (keine Originaldatei setzt es). Byte +10 und Byte +11 sind getrennte Felder: Liest man sie als eine 16-Bit-Anzahl, wird ein gesetztes Byte +11 zu 256 Ebenen.

Pixeldaten

TransparencyIndex gilt pro Frame, nicht für die ganze Datei – das Cursor-GAF etwa verwendet bei manchen Frames Index 9 (das Systempink) und bei anderen Index 0.

Unkomprimiert (Compressed == 0)

Width × Height Bytes, von oben nach unten, von links nach rechts. Das Spiel zeichnet jedes Pixel außer denen, die gleich TransparencyIndex sind. Einheitentexturen (textures/*.gaf) und die Sichtmasken (anims/vismasks.gaf) werden als einfache Pixel-Arrays gelesen, ihre Frames müssen also roh sein; alle Originalframes dort sind es auch.

Komprimiert (Compressed != 0) – Lauflängenkodierung von TA

Die Pixeldaten sind eine Folge von Height unabhängigen Zeilen. Jede Zeile beginnt mit einem uint16 lineLength, gefolgt von einem lauflängenkodierten Bytestrom von genau lineLength Bytes. Innerhalb dieses Stroms beginnt jeder Chunk mit einer 1-Byte-Maske, deren untere zwei Bits die Art des Chunks auswählen:

Maskentest Chunk-Art Länge (Pixel) Folgende Bytes
mask & 0x01 Transparenter Lauf count = mask >> 1 (keine – die Pixel werden übersprungen)
mask & 0x02 Wiederholungslauf count = (mask >> 2) + 1 1 Byte – der zu wiederholende Farbindex
keiner von beiden Literale Kopie count = (mask >> 2) + 1 count Bytes – die literalen Pixel

Die maximalen Lauflängen sind also 127 transparente Pixel, 64 Wiederholungspixel und 64 literale Pixel pro Chunk. Nur übersprungene Pixel sind transparent: Ein wiederholtes oder literales Pixel wird auch dann gezeichnet, wenn sein Wert gleich TransparencyIndex ist, und Palettenindex 0 ist gewöhnliches deckendes Schwarz. Endet die kodierte Zeile vor Width, füllt kbot sie mit transparenten Pixeln auf und meldet das; das Spiel würde in die folgenden Bytes hinein weiterlesen. Ebenen können kleiner als der äußere Frame sein und werden über ihr eigenes OriginX/Y positioniert.

Referenz: formats/gaf/gaf.go readCompressed und formats/gaf/writer.go compressRow.

Important

GAF hat keine Palette. Die Datei speichert nur 8-Bit-Indizes. Um in Farbe zu rendern, brauchst du entweder die globale TA-Palette (palettes/palette.pal) oder, bei TA: Kingdoms, eine Palette pro Asset, die außerhalb des GAF liegt. Die TAK-spezifische Mechanik beschreiben [Palettenauflösung in TA: Kingdoms] (#ta-kingdoms--palette-resolution) und Transparenz-Eigenheit von TA: Kingdoms. kbot gaf export verwendet standardmäßig die eingebettete TA-Palette und die Transparenzregel des Spiels; beides lässt sich überschreiben.


TA: Kingdoms – Palettenauflösung

Note

Dieser Abschnitt beschreibt nur, was in TA:K anders ist. Der Renderer von TA verwendet immer palettes/palette.pal; der Byte-Aufbau von GAF ist in TA und TAK identisch, aber TAK hat stattdessen eine Paletten-Pipeline pro Asset eingebaut.

TA: Kingdoms liefert denselben .gaf-Container (manchmal als .taf) wie TA aus, holt die Palette aber aus einer Begleitdatei pro Asset. Die TAK-Installation der Verkaufsversion folgt drei dokumentierten Konventionen, in absteigender Priorität:

  1. Gleichnamige .pcx neben der .gaf. Oberflächen- und Animations-Assets werden mit einer 1×1-PCX-Datei ausgeliefert, in deren PLTE-Chunk die gewünschte Palette eingebettet ist. anims/actionbuttons.gaf wird mit anims/actionbuttons.pcx gerendert. Etwa 38 % der anims/*.gaf-Dateien von TAK haben eine solche Begleitdatei.

  2. .pal mit gleichem Basisnamen in palettes/. Selten; betrifft eine Handvoll Original-Assets, für die Cavedog eine rohe 1.024-Byte-Palette exportiert hat.

  3. Seitenspezifische Palette nach Präfix des Dateinamens. GAFs von Einheiten und Kartenobjekten tragen ein dreibuchstabiges Seitenpräfix und verwenden die passende Palette der Seite:

    Präfix Seite Palettendatei
    ara* Aramon palettes/aramon.pcx
    tar* Taros palettes/taros.pcx
    ver* Veruna palettes/veruna.pcx
    zon* Zhon palettes/zhon.pcx
    aid* Aiden (Iron Plague) palettes/aiden.pcx
    cre* Creon (Iron Plague) palettes/creon.pcx

Lässt sich keine davon auflösen, fällt der Resolver auf palettes/palette.pal und schließlich auf die eingebettete TA-Palette zurück – beide sind in der TAK-Verkaufsversion bytegleich, untereinander und mit der Palette von TA. Bei GAFs von Einheiten oder Kartenobjekten, die zu keinem Seitenpräfix passen, sind die Farben ohne ausdrückliche Überschreibung also falsch.

Der Resolver von kbot

internal/palettepick setzt die obige Kette um. Jeder Einstiegspunkt, der ein GAF rendert, reicht sie durch:

  • Web-Explorer. Die Routen /png/… und /apng/… erkennen die Palette standardmäßig automatisch; der GAF-Viewer bietet ein Dropdown mit jedem Kandidaten, den der Resolver findet, plus einem Eintrag auto. Übergib ?palette=<vfs-path>, um eine bestimmte zu erzwingen (das Dropdown erledigt das für dich).
  • kbot gaf export / kbot gaf dump. Übergib --palette <path.pcx|path.pal> zum Überschreiben; andernfalls wird die eingebettete TA-Palette verwendet (die CLI führt den VFS-Resolver nicht aus, weil sie keinen VFS-Kontext hat, solange du sie nicht über kbot mount aufrufst).
  • MCP-Tool gaf_export. Akzeptiert ein optionales Argument palette (ein Pfad innerhalb des konfigurierten Ordners game-data); lässt man es weg, läuft der vollständige Resolver.

Ein TA-GAF nach TA: Kingdoms portieren

Der Byte-Aufbau von GAF ist in TA und TAK identisch – nur die Quelle der Palette unterscheidet sich. So portierst du eine vorhandene TA-.gaf:

  1. Erstelle eine 1×1-PCX mit eingebetteter TA-Palette.
  2. Speichere sie mit demselben Basisnamen neben dem GAF (z. B. MyGaf.gaf + MyGaf.pcx).

Das genügt, damit TAK es mit den ursprünglichen TA-Farben rendert.


TA: Kingdoms – Transparenz-Eigenheit

Note

Dieser Abschnitt beschreibt nur, was in TA:K anders ist. Das Byte TransparencyIndex im Abschnitt Frame ist für den Renderer von TA maßgeblich, aber die Content-Autoren von TAK haben es bei unkomprimierten Frames nicht mit den tatsächlichen Pixeldaten abgeglichen.

Viele Texturatlas-GAFs von TAK (alles unter textures/*.gaf und ein Teil von anims/*.gaf) enthalten einen unkomprimierten Frame, dessen TransparencyIndex in den Metadaten eine Konstante angibt (typischerweise 9), die in den tatsächlichen Pixeldaten nie vorkommt – den „transparenten“ Rand hat der Grafiker dagegen mit einem anderen Palettenindex gefüllt (häufig 5). Wer die Metadaten wörtlich nimmt, rendert einen deckenden farbigen Hintergrund, wo der Renderer von TA Transparenz erzeugt hätte.

Der Renderer von TA rät nie: Er verwendet bei rohen Frames den gespeicherten Transparenzschlüssel und bei komprimierten die Überspringbefehle. Für TAK-Atlanten bietet kbot eine optionale Ecken-Heuristik an (TransparencyModeHeuristic, siehe EffectiveTransparencyIndex in formats/gaf von kbot-io), die nur für rohe Frames gilt:

  1. Kommt TransparencyIndex irgendwo im Pixelpuffer vor, gelten die Metadaten.
  2. Andernfalls werden die vier Ecken abgetastet. Stimmen alle vier in einem Wert überein, wird dieser Wert als effektiver Transparenzindex verwendet. Das rettet unkomprimierte TAK-Frames, bei denen der Grafiker einen einheitlichen Rand gezeichnet hat.
  3. Andernfalls wird auf den gespeicherten TransparencyIndex zurückgegriffen (was die Darstellung randloser Texturen wie dungwormB1 erhält, deren Ecken Einheitenpixel sind – die automatische Erkennung verzichtet hier zu Recht auf das Überschreiben).

Komprimierte und zusammengesetzte Frames verwenden immer ihre übersprungenen Pixel. Das Byte auf der Platte wird nie überschrieben – Writer, die einen Round-Trip machen, sehen den ursprünglichen Wert. Ein vollständig deckender TA-Frame mit einheitlichem Rand würde diesen Rand unter der Heuristik verlieren, deshalb wird sie beim Rendern von TA nie verwendet.

Transparenz beim Rendern überschreiben

gaf.RenderOptions bietet diese Modi:

Modus Verhalten Einsatzzweck
TransparencyModeAuto / TransparencyModeMetadata Die Regel des Spiels: Die Schlüsselpixel eines rohen Frames und die übersprungenen Pixel eines komprimierten Frames sind transparent; Index 0 ist deckendes Schwarz (der Nullwert und überall in kbot der Standard für TA). Anzeige, Dumps, Round-Trips.
TransparencyModeHeuristic Ecken-Schätzung für rohe Frames (siehe oben), sonst die Regel des Spiels. Diesen Modus verwendet das Studio für Sprites von TA: Kingdoms. Texturatlanten von TAK.
TransparencyModeNone Jedes Pixel ist deckend. Die Schlüsselfarbe untersuchen.
TransparencyModeIndex Einen vom Aufrufer angegebenen Index verwenden. Überschreiben in der Oberfläche; Debugging.

Jeder exportierte Paletteneintrag ist deckend, bis auf einen transparenten Platz pro Export, normalerweise den Transparenzschlüssel des Frames. Zeichnet ein Frame Pixel, deren Wert seinem Schlüssel entspricht (oder verwenden die Frames einer Animation die Schlüssel der jeweils anderen als Farben), wird stattdessen ein Index, den kein gezeichnetes Pixel verwendet, zu diesem Platz, sodass das Bild jeden Palettenindex behält.

Der GAF-Viewer des Asset-Explorers bietet neben der Palettenauswahl ein Dropdown Default / Game rule / Corner guess / None und reicht die Wahl als ?transparency=game|heuristic|none|<N> an jede PNG-/GIF-/APNG-Anfrage weiter. Standard ist die Regel des Spiels bei TA und die Ecken-Schätzung bei Installationen von TA: Kingdoms. Der Cache-Schlüssel enthält die Transparenzangabe; ein Moduswechsel liefert also keine veralteten Renderings aus.

Das MCP-Tool gaf_export folgt demselben Standard: der Regel des Spiels, außer dass ein als TA: Kingdoms registrierter Spieldatenordner (ein kbot-Kontext takingdoms) die Ecken-Schätzung bekommt; sein Ergebnis nennt den verwendeten Modus. kbot gaf export liest eine einfache Datei ohne Spielkontext und verwendet daher standardmäßig die Regel des Spiels; übergib für Atlanten von TA: Kingdoms --transparency heuristic. kbot gaf dump verwendet immer die Regel des Spiels, weil kbot gaf build die gespeicherten Schlüssel aus den Bildern zurückliest.


Beispiel im Detail – cursors.gaf

$ kbot gaf list anims/cursors.gaf
GAF: 22 sequence(s), version 0x00010100

#   Name             Frames  Loops  Duration (ticks)  Duration (sec)
─   ────             ──────  ─────  ────────────────  ──────────────
0   cursormove       8       yes    64                2.13
1   cursorgrn        1       yes    10                0.33
2   cursorselect     2       yes    12                0.40
...

Ein typischer Frame von cursormove:

Width:       32
Height:      32
OriginX:     16        ← hotspot in the middle of the cursor
OriginY:     16
Transparency: 0        ← this frame's key (compressed, so only skips are transparent)
Compressed:  1         ← run-encoded
LayerCount:  0         ← flat (no sub-frames)

Ein GAF bauen

kbot gaf dump schreibt einen Verzeichnisaufbau, den kbot gaf build wieder einliest:

cursors/
├── cursormove/
│   ├── sequence.csv    ← index,name,loop_flags,unknown4
│   ├── frames.csv      ← frame,width,height,origin_x,origin_y,transparency,
│   │                     duration_ticks,duration_sec,storage,blend
│   ├── animated.png    ← preview only; not read back
│   ├── 0.png
│   ├── 1.png
│   └── ...
└── ...
kbot gaf dump  anims/cursors.gaf --target ./cursors
# edit some PNGs / tweak frames.csv or sequence.csv
kbot gaf build ./cursors --target ./cursors-rebuilt.gaf
kbot gaf roundtrip anims/                     # check dump/build keeps what the game reads

Die Frame-Bilder sind indizierte PNGs (oder GIFs mit --format gif), die nach der Regel des Spiels gezeichnet werden, sodass jedes Pixel seinen Palettenindex behält und nur die transparenten Pixel markiert sind. Der Build-Schritt kopiert diese Indizes zurück und macht aus transparenten Pixeln den Transparenzschlüssel des Frames; RGBA-Bilder werden stattdessen der nächstgelegenen Palettenfarbe zugeordnet, wobei der Schlüssel vermieden wird.

  • sequence.csv stellt die Reihenfolge der Sequenzen, ihren genauen Namen, ihr Schleifenwort und ihr Wort +4 wieder her. Fehlt sie, ist der Ordnername der Sequenzname, und die Sequenz läuft in einer Schleife, wie jede Originalsequenz.
  • storage (raw oder compressed) und blend (das Byte +11) stellen den Header jedes Frames wieder her. Frames ohne storage werden komprimiert; nur Frames, die in textures/*.gaf oder anims/vismasks.gaf geschrieben werden, sind immer roh, weil das Spiel diese als einfache Pixel-Arrays liest. --storage raw|compressed überschreibt beides.
  • Zusammengesetzte Frames (mit Ebenen) werden als ein einziges zusammengeführtes Bild ausgegeben und als einfache Frames zurückgebaut; kbot gaf roundtrip meldet, wie viele.
  • Ein Frame ohne Pixel (Breite oder Höhe 0) hat kein Bild; seine Zeile in frames.csv allein baut ihn wieder auf.
  • Ein Unterordner ohne frames.csv und ohne sequence.csv wird mit einer Warnung übersprungen. Jeder andere Unterordner, der sich nicht bauen lässt (ein fehlendes oder unlesbares Bild, ein ungültiger CSV-Wert), bricht den Build ab, damit nie stillschweigend eine Sequenz fehlt.

Note

GAFs von TA und TA:K sind bytegleich. Der Container ist identisch; nur die Paletten-Pipeline unterscheidet sich. Die vollständige Kette und die Anleitung zum Portieren eines GAF nach TAK stehen oben unter Palettenauflösung in TA: Kingdoms.


Stolperfallen

Warning

Eine Sequenz, deren Schleifenbyte 0 ist, läuft einmal ab und bleibt stehen. Werkzeuge, die das Wort +2 als null schreiben, frieren jedes animierte Kartenobjekt ein, das sie anfassen. kbot behält das Wort bei, und neue Sequenzen, die kbot baut, laufen in einer Schleife.

  • Manche Sequenzen werden mit Frame-Dauern von 0 ausgeliefert. Das Spiel zeigt einen solchen Frame einen Tick lang, wie bei einer Dauer von 1. Setz sie nicht auf einen Standardwert, um sie zu „reparieren“.
  • Komprimierte Pixelzeilen können kürzer als Width sein. Das Spiel liest die nächsten Bytes als Befehle weiter; kbot füllt die Zeile mit transparenten Pixeln auf und meldet das. Keine Originaldatei hat solche Zeilen.
  • Ursprünge von Ebenen sind Hotspots: Jede Ebene wird so platziert, dass ihr Ursprung auf dem Ursprung des äußeren Frames liegt.
  • Die .taf von TA: Kingdoms gibt es in zwei Varianten. kbot liest eine .taf mit Palette wie ein gewöhnliches GAF, aber TA:K liefert auch Truecolor-.taf-Dateien aus (16-Bit-ARGB-Pixel, keine Palette). Unterscheide sie am Format-Byte des Frames; die Truecolor-Variante beschreibt TAF / TSF.
  • anims/terrain.gaf und anims/vismasks.gaf haben Version == 0. Das Spiel ignoriert das Versionswort.
  • Die Anzahl der Frames pro Sequenz ist nicht begrenzt – cursorteleport hat 46 Frames. Geh beim Bemessen von Puffern nicht von einer festen Obergrenze aus.

Typische Größen

Asset Beobachteter Bereich in Cavedogs GAFs
anims/cursors.gaf ~30 KB, 22 Sequenzen, je 1–46 Frames
Einheitenteil (z. B. Mündungsfeuer) 5–20 KB, 1 Sequenz, 4–12 Frames
Explosion (Familie anims/explosions.gaf) 50–250 KB pro Datei
anims/textures.gaf (das Haupt-Texturblatt) ~12 MB (größtes GAF in TA)
anims/terrain.gaf ~1,5 MB
Daten pro Frame Typischerweise <1 KB; große Frames (Explosionen mit 256×256) erreichen über 10 KB

Echte Beispiele im Referenzkatalog

Bemerkenswerte GAFs in der TA-Installation – jedes davon lässt sich mit kbot hpi extract entpacken und dann mit kbot gaf list / kbot gaf export untersuchen:

  • anims/cursors.gaf – 22 Sequenzen, jede eine Cursor-Animation der Oberfläche. Die kleinsten Sequenzen (cursorgrn, cursorred) sind einzelne Frames; die größte (cursorteleport) hat 46 Frames über 460 Ticks. Siehe das Beispiel im Detail oben.
  • anims/textures.gaf – ~12 MB, das Haupt-Kachelblatt, auf das die OffsetToTextureName-Strings jedes 3DO-Modells verweisen. Durchstöbern mit kbot gaf list anims/textures.gaf | head.
  • Familie anims/explosions.gaf – typische Effekt-GAFs: lasersht.gaf, acid.gaf, bigexpls.gaf – jedes enthält mehrere benannte Explosionssequenzen.
  • anims/armcom.gaf / corcom.gaf – Commander-Teile pro Seite (Auswahlkreis, Baulaser).
  • anims/terrain.gaf + anims/vismasks.gaf – die einzigen Original-GAFs mit Version == 0 im Header (gut zu wissen, wenn man einen Parser schreibt).

Siehe auch

  • TAF / TSF – die Truecolor-Variante .taf von TA: Kingdoms, die auf demselben Container aufbaut, samt ihrer bearbeitbaren Textform.
  • PAL – die Farbtabelle, die man zum Rendern von GAF-Frames braucht.
  • PCX – wie TA:K einer .taf mit Palette eine Palette liefert.
  • 3DO – wenn ein „Sprite“ in Wirklichkeit ein texturiertes 3D-Modell ist (die meisten Explosionen sind GAF; die meisten Projektile sind 3DO + GAF-Mündungsfeuer).
  • Glossar – sub-frame, origin, tick.