Smacker / ZRB — видеоролики
Источник: coreprime/kbot @ 0ab97bf · Редактировать на GitHub
Вступительный ролик, брифинги миссий и финальные ролики Total Annihilation — это видео RAD Game Tools Smacker. Они хранятся под двумя разными расширениями:
Расширение Где используется Примечания .smkОбычные инструменты Smacker Стандартный формат RAD. .zrbПолезная нагрузка TA в data/*.zrbCavedog переименовала файлы Smacker в .zrb, чтобы отбить охоту к случайному извлечению. Двоичное содержимое побайтно идентично.FFmpeg декодирует Smacker сам, и kbot использует его как движок преобразования Smacker → MP4. В обратную сторону не преобразует ничто: в стандартном FFmpeg нет ни кодировщика, ни мультиплексора Smacker, а в kbot нет модуля записи Smacker. Ролики SMK2 для TA делают инструментами Smacker от RAD Game Tools.
Tip
Попробуйте сами.
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
Из Go. Используйте 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")
Что лежит в установке TA
$ ls $(kbot ctx path)/data/*.zrb
1.zrb 2.zrb 3.zrb 4.zrb 5.zrb
Каждый пронумерованный файл — это ролик: оригинальная вступительная
сцена «ARM против CORE», брифинги миссий и т. д. Кадры хранятся в
разрешении 640 × 240 с установленным флагом чересстрочности,
поэтому игра показывает их в разрешении 640 × 480, где каждая вторая
строка чёрная, с частотой 30 fps. kbot zrb to-mp4, инструмент MCP
zrb_to_mp4 и видеоплеер студии (а также его миниатюры) показывают их
точно так же.
Заголовок (не меньше 104 байт)
Заголовок Smacker содержит сигнатуру, геометрию, число кадров, параметры звука и размеры таблиц указателей. Прочитать его несложно, но тело декодируется через деревья Хаффмана на уровне битов, поэтому kbot не берётся за тело и использует 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;
Биты Flags: 0x01 — кольцевой кадр (один дополнительный кадр после
последнего, для зацикливания), 0x02 — чересстрочность (показывается с
удвоенной высотой, каждая вторая строка чёрная), 0x04 — удвоение
(показывается с удвоенной высотой, каждая строка повторяется). Если
установлены и 0x02, и 0x04, ролик показывается с той высотой, с
которой хранится.
Как декодировать частоту кадров
Знак FrameRate выбирает одну из двух кодировок:
| Значение | Смысл |
|---|---|
> 0 |
Миллисекунды на кадр: fps = 1000 / FrameRate. |
< 0 |
Стотысячные доли секунды на кадр: fps = 100_000 / abs(FrameRate). |
0 |
Частота не задана — kbot использует 15 fps. |
Для 30 fps обычно встречается -3333 (≈ -100000/30).
Варианты сигнатуры
SMK2— исходный формат Smacker. Его используют почти все ролики Cavedog.SMK4— расширенный формат с улучшенным сжатием из более новых инструментов RAD. TA 3.1c воспроизводит только SMK2.
kbot читает оба (и отмечает файл SMK4), FFmpeg декодирует оба.
Звуковые дорожки
До 7 звуковых дорожек. Каждое слово AudioRate[i] упаковывает частоту
дискретизации (биты 0–23) и флаги дорожки (биты 24–31): 0x80 — сжатая,
0x40 — присутствует, 0x20 — 16 бит (иначе 8 бит), 0x10 — стерео
(иначе моно). Игра использует дорожку, только если установлен её бит
присутствия, какой бы ни была её частота. Отдельной таблицы флагов нет:
семь слов после заголовка — это таблица размеров кадров.
Note
В файлах ZRB от Cavedog одна дорожка, в слоте 0: слово
0xD0005622 — присутствует, 22 050 Гц, стерео, 8 бит, сжатая.
Остальные шесть слотов обнулены. kbot zrb info и инструмент MCP
zrb_info выводят только присутствующие дорожки.
Миф о «зашифрованных данных»
Среди моддеров распространено мнение, что файлы .zrb — зашифрованный
вариант Smacker. Это не так. Если переименовать 1.zrb в 1.smk,
файл воспроизводится в любом инструменте, который понимает Smacker
(инструменты RAD Bink/Smacker, FFmpeg, VLC). Единственной маскировкой
Cavedog было само расширение.
# Equivalent — try both
ffplay data/1.zrb
cp data/1.zrb /tmp/intro.smk && ffplay /tmp/intro.smk
Цепочки преобразования
kbot zrb to-mp4 читает заголовок, а затем FFmpeg декодирует ролик в
H.264 (CRF 18) и AAC так, как его показывает игра: с высотой
отображения (чересстрочный ролик 640×240 превращается в 640×480, где
каждая вторая строка чёрная), с квадратными пикселями, и останавливается
на числе кадров из заголовка (кольцевой кадр не показывается).
| Флаг | Действие |
|---|---|
--line-double |
Заполнять дополнительные строки чересстрочного ролика повтором каждой сохранённой строки, а не чёрным. |
--stored-height |
Сохранить высоту кадра, с которой он хранится (640×240). |
Видеоплеер студии использует то же преобразование, а его миниатюры сохраняют пропорции экрана 4:3 (128×96, строки удвоены).
Important
Пути MP4 → Smacker нет. В стандартном FFmpeg нет кодировщика
Smacker (smackvid / smackaud) и мультиплексора, а в kbot нет модуля
записи Smacker. Именно об этом и сообщают kbot zrb from-mp4 и
инструмент MCP zrb_from_mp4 (FFmpeg они пробуют, только если тот
перечисляет и кодировщик smackvid, и мультиплексор smk). Ролики
SMK2 для TA делайте инструментами Smacker от RAD Game Tools.
Типичные размеры
| Ресурс | Разрешение | Кадров | Длительность | Размер файла |
|---|---|---|---|---|
Вступительный ролик (data/1.zrb) |
640 × 240 (показывается 640 × 480) | 599 | ~20 с | ~7 МБ |
Остальные ролики (data/2.zrb–5.zrb) |
640 × 240 (показывается 640 × 480) | — | — | 10–41 МБ |
Подводные камни
Warning
AudioRate — упакованное слово, а не частота. Если прочитать
слово из оригинальных файлов 0xD0005622 как обычное число, получится
3 489 682 978 «Гц». Для частоты маскируйте младшие 24 бита, а
присутствие проверяйте по биту 0x40000000. Инструменты, которые
читают после заголовка ещё семь слов «флагов», на самом деле читают
таблицу размеров кадров.
- Smacker — это не Bink. RAD сначала выпустила Smacker, а потом Bink
как его преемника. TA использует только Smacker, TA: Kingdoms перешла
на Bink. Не открывайте файлы
.bikчерезkbot zrb— используйтеkbot bik. - Деревья Хаффмана
SMK4несовместимы с декодерамиSMK2. FFmpeg справляется с обоими, но старые сторонние библиотеки могут и не справиться. - В роликах из комплекта игры хранится
-3333(100 000 / 3 333 ≈ 30,003 fps). - Высота хранения — не высота показа. Проверяйте флаги чересстрочности и удвоения: оригинальные ролики, воспроизведённые в 640×240, сплющены до половины высоты.
- Переименование
.zrb↔.smkбезвредно, но игра ожидает.zrbв каталогеdata/. Не отдавайте движку файлы с именами.smk.