Todas as páginas de formatos ↓
Gráficos e mídia

Smacker / ZRB: vídeo das cinemáticas

Fonte: coreprime/kbot @ 0ab97bf · Editar no GitHub

A abertura, os briefings das missões e as cinemáticas de encerramento do Total Annihilation são vídeos Smacker da RAD Game Tools. Eles são guardados com duas extensões diferentes:

Extensão Usada por Observações
.smk Ferramentas Smacker genéricas Formato padrão da RAD.
.zrb Os dados data/*.zrb do TA A Cavedog renomeou os arquivos Smacker para .zrb para desencorajar a extração casual. O conteúdo binário é idêntico byte a byte.

O FFmpeg decodifica Smacker nativamente, e o kbot o usa como mecanismo de conversão de Smacker → MP4. Nada converte no sentido contrário: o FFmpeg padrão não tem codificador nem muxer de Smacker, e o kbot não grava Smacker. Os filmes SMK2 para o TA são feitos com as ferramentas Smacker da RAD Game Tools.

Tip

Experimente você mesmo.

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

Em Go. Use 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")

O que há em uma instalação do TA

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

Cada arquivo numerado é uma cinemática: a sequência de abertura original "Arm vs Core", os briefings das missões etc. Os quadros são guardados em 640 × 240 com a flag entrelaçado ligada, então o jogo os mostra em 640 × 480, com uma linha preta a cada duas, a 30 fps. O kbot zrb to-mp4, a ferramenta MCP zrb_to_mp4 e o reprodutor de vídeo do studio (e suas miniaturas) os mostram do mesmo jeito.


Cabeçalho (no mínimo 104 bytes)

O cabeçalho Smacker traz uma assinatura, as dimensões, a contagem de quadros, a configuração de áudio e os tamanhos das tabelas de ponteiros. Lê-lo é simples, mas a decodificação do corpo usa árvores de Huffman em nível de bit, e é por isso que o kbot não decodifica o corpo e entrega o trabalho ao 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 de Flags: 0x01 quadro de anel (um quadro extra depois do último, para repetir o vídeo em loop), 0x02 entrelaçado (mostrado com o dobro da altura, com uma linha preta a cada duas), 0x04 dobrado (mostrado com o dobro da altura, com cada linha repetida). Com 0x02 e 0x04 ligados ao mesmo tempo, o filme é mostrado na altura em que foi guardado.

Como decodificar a taxa de quadros

O sinal de FrameRate escolhe entre duas codificações:

Valor Significado
> 0 Milissegundos por quadro: fps = 1000 / FrameRate.
< 0 Centésimos de milésimo de segundo por quadro: fps = 100_000 / abs(FrameRate).
0 Sem tempo definido; o kbot usa 15 fps.

Para 30 fps, o normal é ver -3333 (≈ -100000/30).

Variantes da assinatura

  • SMK2: o formato Smacker original. Quase todas as cinemáticas da Cavedog usam este.
  • SMK4: formato estendido com compressão melhor, das ferramentas mais novas da RAD. O TA 3.1c só reproduz SMK2.

O kbot lê os dois (e avisa quando o arquivo é SMK4); o FFmpeg decodifica os dois.

Faixas de áudio

Até 7 faixas de áudio. Cada palavra AudioRate[i] empacota a taxa de amostragem (bits 0–23) e as flags da faixa (bits 24–31): 0x80 comprimida, 0x40 presente, 0x20 16 bits (senão, 8 bits), 0x10 estéreo (senão, mono). O jogo só usa uma faixa quando o bit de presença está ligado, seja qual for a taxa. Não existe uma tabela de flags separada: as sete palavras depois do cabeçalho são a tabela de tamanhos dos quadros.

Note

Os arquivos ZRB da Cavedog têm uma única faixa, na posição 0: a palavra 0xD0005622, ou seja, presente, 22.050 Hz, estéreo, 8 bits, comprimida. As outras seis posições estão zeradas. O kbot zrb info e a ferramenta MCP zrb_info listam só as faixas presentes.


O mito de que "os dados são criptografados"

Muitos modders acreditam que os arquivos .zrb são uma variante criptografada do Smacker. Não são. Basta renomear 1.zrb para 1.smk para reproduzi-los em qualquer ferramenta que entenda Smacker (as ferramentas Bink/Smacker da RAD, FFmpeg, VLC). A única ofuscação da Cavedog foi a própria extensão.

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

Fluxos de conversão

O kbot zrb to-mp4 lê o cabeçalho e depois faz o FFmpeg decodificar o filme para H.264 (CRF 18) e AAC do jeito que o jogo o mostra: na altura de exibição (um filme entrelaçado de 640×240 vira 640×480 com uma linha preta a cada duas), com pixels quadrados, parando na contagem de quadros do cabeçalho (um quadro de anel não é mostrado).

Opção Efeito
--line-double Preenche as linhas extras de um filme entrelaçado repetindo cada linha guardada, em vez de preto.
--stored-height Mantém a altura do quadro como foi guardada (640×240).

O reprodutor de vídeo do studio usa a mesma conversão, e suas miniaturas mantêm a proporção de exibição 4:3 (128×96, linhas dobradas).

Important

Não existe caminho de MP4 → Smacker. O FFmpeg padrão não tem codificador (smackvid / smackaud) nem muxer de Smacker, e o kbot não grava Smacker. O kbot zrb from-mp4 e a ferramenta MCP zrb_from_mp4 informam exatamente isso (e só tentam o FFmpeg quando ele lista ao mesmo tempo um codificador smackvid e um muxer smk). Faça os filmes SMK2 para o TA com as ferramentas Smacker da RAD Game Tools.


Tamanhos típicos

Recurso Resolução Quadros Duração Tamanho do arquivo
Cinemática de abertura (data/1.zrb) 640 × 240 (mostrada em 640 × 480) 599 ~20 s ~7 MB
Outras cinemáticas (data/2.zrb–5.zrb) 640 × 240 (mostradas em 640 × 480) — — 10–41 MB

Armadilhas

Warning

AudioRate é uma palavra empacotada, não uma taxa. Lida como um número comum, a palavra 0xD0005622 da versão comercial dá 3.489.682.978 "Hz". Aplique uma máscara nos 24 bits baixos para obter a taxa e teste o bit 0x40000000 para saber se a faixa está presente. As ferramentas que leem mais sete palavras de "flags" depois do cabeçalho estão lendo a tabela de tamanhos dos quadros.

  • Smacker não é Bink. A RAD lançou primeiro o Smacker e depois o Bink, como seu sucessor. O TA só usa Smacker; o TA: Kingdoms passou para o Bink. Não carregue arquivos .bik com kbot zrb; use o kbot bik.
  • As árvores de Huffman do SMK4 não são compatíveis com decodificadores de SMK2. O FFmpeg lida com os dois, mas bibliotecas de terceiros mais antigas podem não lidar.
  • As cinemáticas originais guardam -3333 (100.000 / 3.333 ≈ 30,003 fps).
  • A altura guardada não é a altura mostrada. Confira as flags de entrelaçado e de dobrado; reproduzir os filmes da versão comercial em 640×240 os achata para metade da altura.
  • Renomear .zrb ↔ .smk não faz mal, mas o jogo espera .zrb no diretório data/. Não entregue ao motor arquivos com nome .smk.

Veja também

  • Bink: o codec sucessor que o TA: Kingdoms usa no lugar do Smacker.
  • HPI: o arquivo compactado que serve de invólucro e traz os arquivos ZRB.
  • Glossário: taxa de quadros, assinatura.