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 .smkFerramentas Smacker genéricas Formato padrão da RAD. .zrbOs dados data/*.zrbdo TAA Cavedog renomeou os arquivos Smacker para .zrbpara 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
.bikcomkbot zrb; use okbot bik. - As árvores de Huffman do
SMK4não são compatíveis com decodificadores deSMK2. 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↔.smknão faz mal, mas o jogo espera.zrbno diretóriodata/. Não entregue ao motor arquivos com nome.smk.