Alle Formatseiten ↓
Grafik und Medien

Smacker / ZRB – Zwischensequenz-Video

Aus coreprime/kbot @ 0ab97bf · Auf GitHub bearbeiten

Intro, Missionsbriefings und Abspann von Total Annihilation sind Videos im Format Smacker von RAD Game Tools. Sie liegen unter zwei verschiedenen Endungen vor:

Endung Verwendet von Anmerkungen
.smk allgemeinen Smacker-Werkzeugen Das Standardformat von RAD.
.zrb den Nutzdaten data/*.zrb von TA Cavedog hat Smacker-Dateien in .zrb umbenannt, um beiläufiges Extrahieren zu erschweren. Der binäre Inhalt ist byte-identisch.

FFmpeg dekodiert Smacker von Haus aus, und kbot verwendet es als Konvertierungs-Engine für Smacker → MP4. In die andere Richtung konvertiert nichts: Das Standard-FFmpeg hat weder einen Smacker-Encoder noch einen Muxer, und kbot hat keinen Smacker-Writer. SMK2-Videos für TA erstellst du mit den Smacker-Werkzeugen von RAD Game Tools.

Tip

Probier es selbst.

kbot zrb info     data/1.zrb               # header summary
kbot zrb to-mp4   data/1.zrb intro.mp4     # decode to a 640x480 MP4 (requires ffmpeg)
kbot zrb from-mp4 intro.mp4 out.zrb        # reports that no Smacker encoder exists

Aus Go heraus. Verwende formats/smacker:

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

r, _ := smacker.OpenReader("data/1.zrb")
defer r.Close()
fmt.Println(r.Width(), r.Height(), r.FrameCount(), r.FrameRate())
_ = smacker.ConvertToMP4("data/1.zrb", "intro.mp4")

Was du in einer TA-Installation findest

$ ls $(kbot ctx path)/data/*.zrb
1.zrb  2.zrb  3.zrb  4.zrb  5.zrb

Jede nummerierte Datei ist eine Zwischensequenz – die ursprüngliche Intro-Sequenz „Arm vs Core“, Missionsbriefings usw. Die Frames sind mit 640 × 240 gespeichert und haben das Flag interlaced gesetzt, daher zeigt das Spiel sie mit 640 × 480 an, jede zweite Zeile schwarz, mit 30 fps. kbot zrb to-mp4, das MCP-Werkzeug zrb_to_mp4 und der Videoplayer des Studios (samt seiner Vorschaubilder) zeigen sie genauso.


Header (mindestens 104 Byte)

Der Smacker-Header enthält eine Signatur, die Geometrie, Frame-Anzahlen, die Audiokonfiguration und die Größen der Zeigertabellen. Ihn zu lesen ist einfach, aber das Dekodieren des Rumpfs läuft über Huffman-Bäume auf Bitebene, und deshalb überlässt kbot den Rumpf FFmpeg.

typedef struct {
    uint32 Signature;        // 'SMK2' = 0x324B4D53 or 'SMK4' = 0x344B4D53
    uint32 Width;
    uint32 Height;
    uint32 Frames;
    int32  FrameRate;        // See below — sign-encoded
    uint32 Flags;
    uint32 AudioSize[7];
    uint32 TreesSize;        // Huffman tree section length
    uint32 MMapSize;
    uint32 MClrSize;
    uint32 FullSize;
    uint32 TypeSize;
    uint32 AudioRate[7];     // packed: rate in bits 0-23, flags in bits 24-31
    uint32 dummy;            // 4-byte reserved; the header ends here (104 bytes)
    // …followed by one entry per frame, plus one for the ring frame
    // when Flags bit 0 is set:
    uint32 FrameSizes[Frames (+1)];
    uint8  FrameTypes[Frames (+1)];
    uint8  HuffmanTrees[TreesSize];
} SmackerHeader;

Bits von Flags: 0x01 Ring-Frame (ein zusätzlicher Frame nach dem letzten, für Schleifen), 0x02 interlaced (in doppelter Höhe angezeigt, jede zweite Zeile schwarz), 0x04 verdoppelt (in doppelter Höhe angezeigt, jede Zeile wiederholt). Sind 0x02 und 0x04 beide gesetzt, wird das Video in seiner gespeicherten Höhe angezeigt.

Die Bildrate dekodieren

Das Vorzeichen von FrameRate wählt zwischen zwei Kodierungen:

Wert Bedeutung
> 0 Millisekunden pro Frame: fps = 1000 / FrameRate.
< 0 Hunderttausendstel Sekunden pro Frame: fps = 100_000 / abs(FrameRate).
0 Kein festgelegtes Timing – kbot verwendet 15 fps.

Für 30 fps siehst du meist -3333 (≈ -100000/30).

Varianten der Signatur

  • SMK2 – das ursprüngliche Smacker-Format. Fast alle Zwischensequenzen von Cavedog verwenden es.
  • SMK4 – erweitertes Format mit besserer Kompression, aus neueren Werkzeugen von RAD. TA 3.1c spielt nur SMK2 ab.

kbot liest beide (und weist auf eine SMK4-Datei hin); FFmpeg dekodiert beide.

Audiospuren

Bis zu 7 Audiospuren. Jedes Wort AudioRate[i] packt die Abtastrate (Bits 0–23) und die Flags der Spur (Bits 24–31): 0x80 komprimiert, 0x40 vorhanden, 0x20 16 Bit (sonst 8 Bit), 0x10 Stereo (sonst Mono). Das Spiel verwendet eine Spur nur, wenn ihr Vorhanden-Bit gesetzt ist, unabhängig von ihrer Rate. Eine eigene Flag-Tabelle gibt es nicht: Die sieben Wörter nach dem Header sind die Tabelle der Frame-Größen.

Note

Cavedogs ZRB-Dateien haben eine einzige Spur auf Platz 0: das Wort 0xD0005622 – vorhanden, 22.050 Hz, Stereo, 8 Bit, komprimiert. Die anderen sechs Plätze sind genullt. kbot zrb info und das MCP-Werkzeug zrb_info listen nur die vorhandenen Spuren auf.


Der Mythos „Die Daten sind verschlüsselt“

Unter Moddern hält sich hartnäckig die Annahme, .zrb-Dateien seien eine verschlüsselte Variante von Smacker. Das sind sie nicht. Benennt man 1.zrb in 1.smk um, lassen sie sich in jedem Werkzeug abspielen, das Smacker kennt (die Bink/Smacker-Werkzeuge von RAD, FFmpeg, VLC). Cavedogs einzige Verschleierung war die Endung selbst.

# Equivalent — try both
ffplay data/1.zrb
cp data/1.zrb /tmp/intro.smk && ffplay /tmp/intro.smk

Konvertierungspipelines

kbot zrb to-mp4 liest den Header und lässt FFmpeg das Video dann so, wie das Spiel es zeigt, nach H.264 (CRF 18) und AAC dekodieren: in der Anzeigehöhe (ein interlaced Video in 640×240 wird zu 640×480 mit jeder zweiten Zeile schwarz), mit quadratischen Pixeln, und mit Halt bei der Frame-Anzahl aus dem Header (ein Ring-Frame wird nicht angezeigt).

Flag Wirkung
--line-double Füllt die zusätzlichen Zeilen eines interlaced Videos, indem jede gespeicherte Zeile wiederholt wird, statt mit Schwarz.
--stored-height Behält die gespeicherte Frame-Höhe bei (640×240).

Der Videoplayer des Studios verwendet dieselbe Konvertierung, und seine Vorschaubilder behalten das Anzeigeformat 4:3 bei (128×96, Zeilen verdoppelt).

Important

Es gibt keinen Weg von MP4 → Smacker. Das Standard-FFmpeg hat weder einen Smacker-Encoder (smackvid / smackaud) noch einen Muxer, und kbot hat keinen Smacker-Writer. kbot zrb from-mp4 und das MCP-Werkzeug zrb_from_mp4 melden genau das (und versuchen FFmpeg nur, wenn es sowohl einen Encoder smackvid als auch einen Muxer smk aufführt). Erstelle SMK2-Videos für TA mit den Smacker-Werkzeugen von RAD Game Tools.


Typische Größen

Asset Auflösung Frames Dauer Dateigröße
Intro (data/1.zrb) 640 × 240 (angezeigt 640 × 480) 599 ~20 s ~7 MB
Andere Zwischensequenzen (data/2.zrb–5.zrb) 640 × 240 (angezeigt 640 × 480) – – 10–41 MB

Stolperfallen

Warning

AudioRate ist ein gepacktes Wort, keine Rate. Als einfache Zahl gelesen ergibt das Wort 0xD0005622 der Verkaufsversion 3.489.682.978 „Hz“. Maskiere die unteren 24 Bit für die Rate und prüfe Bit 0x40000000 auf Vorhandensein. Werkzeuge, die nach dem Header sieben weitere „Flag“-Wörter lesen, lesen in Wahrheit die Tabelle der Frame-Größen.

  • Smacker ist nicht Bink. RAD hat zuerst Smacker herausgebracht und dann Bink als Nachfolger. TA verwendet nur Smacker; TA: Kingdoms ist auf Bink umgestiegen. Lade .bik-Dateien nicht mit kbot zrb – nimm stattdessen kbot bik.
  • Die Huffman-Bäume von SMK4 sind nicht abwärtskompatibel zu SMK2-Decodern. FFmpeg kommt mit beiden zurecht, ältere Bibliotheken von Drittanbietern unter Umständen nicht.
  • Die ausgelieferten Zwischensequenzen speichern -3333 (100.000 / 3.333 ≈ 30,003 fps).
  • Die gespeicherte Höhe ist nicht die angezeigte Höhe. Prüfe die Flags interlaced und verdoppelt; spielt man die Videos der Verkaufsversion in 640×240 ab, werden sie auf halbe Höhe gestaucht.
  • .zrb ↔ .smk umzubenennen ist harmlos, aber das Spiel erwartet im Verzeichnis data/ die Endung .zrb. Liefere der Engine keine Dateien mit der Endung .smk aus.

Siehe auch

  • Bink – der Nachfolge-Codec, den TA: Kingdoms anstelle von Smacker verwendet.
  • HPI – das Hüllarchiv, in dem die ZRB-Dateien ausgeliefert werden.
  • Glossar – frame rate, signature.