Smacker / ZRB — vídeo das cinemáticas
Fonte: coreprime/kbot @ 0ab97bf · Editar no GitHub
A introdução, os briefings das missões e as cinemáticas finais do Total Annihilation são vídeos Smacker da RAD Game Tools. Estão guardados com duas extensões diferentes:
Extensão Usada por Notas .smkFerramentas Smacker genéricas Formato RAD normal. .zrbO payload data/*.zrbdo TAA Cavedog mudou a extensão dos ficheiros Smacker para .zrbpara desencorajar a extração casual. O conteúdo binário é idêntico byte a byte.O FFmpeg descodifica Smacker nativamente, e o kbot usa-o como motor de conversão de Smacker → MP4. Nada converte no sentido inverso: o FFmpeg normal não tem codificador nem multiplexador (muxer) de Smacker, e o kbot não tem escritor de Smacker. Os filmes SMK2 para o TA fazem-se com as ferramentas Smacker da RAD Game Tools.
Tip
Experimente por si.
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
A partir de 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 encontra numa instalação do TA
$ ls $(kbot ctx path)/data/*.zrb
1.zrb 2.zrb 3.zrb 4.zrb 5.zrb
Cada ficheiro numerado é uma cinemática: a sequência de introdução
original "Arm vs Core", os briefings das missões, etc. Os fotogramas
estão guardados a 640 × 240 com a flag de entrelaçado definida,
por isso o jogo mostra-os a 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 leitor de vídeo do estúdio (e as suas miniaturas) mostram-nos da mesma
forma.
Cabeçalho (104 bytes no mínimo)
O cabeçalho Smacker contém uma assinatura, a geometria, as contagens de fotogramas, a configuração do áudio e os tamanhos das tabelas de ponteiros. Lê-lo é simples, mas a descodificação do corpo assenta em árvores de Huffman ao nível do bit, e é por isso que o kbot não trata do corpo e recorre 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 fotograma de anel (um fotograma extra depois do
último, para a repetição em ciclo), 0x02 entrelaçado (mostrado com o
dobro da altura, com uma linha preta a cada duas), 0x04 duplicado
(mostrado com o dobro da altura, com cada linha repetida). Com 0x02 e
0x04 definidos ao mesmo tempo, o filme é mostrado com a altura
guardada.
Descodificar a taxa de fotogramas
O sinal de FrameRate escolhe entre duas codificações:
| Valor | Significado |
|---|---|
> 0 |
Milissegundos por fotograma: fps = 1000 / FrameRate. |
< 0 |
Cem-milésimos de segundo por fotograma: fps = 100_000 / abs(FrameRate). |
0 |
Sem temporização definida: o kbot usa 15 fps. |
Para 30 fps, vê-se normalmente -3333 (≈ -100000/30).
Variantes da assinatura
SMK2— o formato Smacker original. Quase todas as cinemáticas da Cavedog o usam.SMK4— formato alargado com melhor compressão, das ferramentas mais recentes da RAD. O TA 3.1c só reproduz SMK2.
O kbot lê os dois (e assinala um ficheiro SMK4); o FFmpeg descodifica os dois.
Faixas de áudio
Até 7 faixas de áudio. Cada palavra AudioRate[i] junta a frequência 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 seu bit de
presença está definido, seja qual for a frequência. Não há uma tabela
de flags separada: as sete palavras a seguir ao cabeçalho são a tabela
de tamanhos dos fotogramas.
Note
Os ficheiros 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 a zero. O kbot zrb info e a
ferramenta MCP zrb_info só listam as faixas presentes.
O mito dos "dados cifrados"
Muitos modders acreditam que os ficheiros .zrb são uma variante cifrada
do Smacker. Não são. Mudar o nome de 1.zrb para 1.smk torna-os
reproduzíveis em qualquer ferramenta que conheça o Smacker (as
ferramentas Bink/Smacker da RAD, o FFmpeg, o 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
Processos de conversão
O kbot zrb to-mp4 lê o cabeçalho e depois põe o FFmpeg a descodificar o
filme para H.264 (CRF 18) e AAC tal como o jogo o mostra: com a
altura de apresentação (um filme entrelaçado de 640×240 passa a 640×480,
com uma linha preta a cada duas), com píxeis quadrados e parando na
contagem de fotogramas do cabeçalho (o fotograma de anel não é
mostrado).
| Opção | Efeito |
|---|---|
--line-double |
Preenche as linhas extra de um filme entrelaçado repetindo cada linha guardada, em vez de as deixar pretas. |
--stored-height |
Mantém a altura guardada dos fotogramas (640×240). |
O leitor de vídeo do estúdio usa a mesma conversão, e as suas miniaturas mantêm a forma de apresentação 4:3 (128×96, linhas duplicadas).
Important
Não há caminho de MP4 → Smacker. O FFmpeg normal não tem
codificador de Smacker (smackvid / smackaud) nem muxer, e o kbot não
tem escritor de Smacker. O kbot zrb from-mp4 e a ferramenta MCP
zrb_from_mp4 dizem exatamente isso (e só tentam o FFmpeg quando este
lista tanto um codificador smackvid como 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 | Fotogramas | Duração | Tamanho do ficheiro |
|---|---|---|---|---|
Cinemática de introdução (data/1.zrb) |
640 × 240 (mostrada a 640 × 480) | 599 | ~20 s | ~7 MB |
Outras cinemáticas (data/2.zrb–5.zrb) |
640 × 240 (mostradas a 640 × 480) | — | — | 10–41 MB |
Armadilhas
Warning
AudioRate é uma palavra compactada, não uma frequência. Lida como
um número simples, a palavra dos ficheiros comerciais, 0xD0005622, dá
3 489 682 978 "Hz". Aplique uma máscara aos 24 bits inferiores para
obter a frequência 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 a ler a tabela de tamanhos dos fotogramas.
- 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 ficheiros
.bikcomkbot zrb: use antes okbot bik. - As árvores de Huffman do
SMK4não são retrocompatíveis com os descodificadores deSMK2. O FFmpeg trata os dois, mas as bibliotecas de terceiros mais antigas podem não tratar. - As cinemáticas distribuídas guardam
-3333(100 000 / 3333 ≈ 30.003 fps). - A altura guardada não é a altura mostrada. Verifique as flags de entrelaçado e de duplicado; reproduzir os filmes comerciais a 640×240 achata-os para metade da altura.
- Mudar a extensão
.zrb↔.smké inofensivo, mas o jogo espera.zrbna pastadata/. Não entregue ao motor ficheiros com nomes.smk.