모든 형식 페이지 ↓
그래픽·미디어

Smacker / ZRB — 컷신 영상

출처: coreprime/kbot @ 0ab97bf · GitHub에서 편집

Total Annihilation의 인트로, 미션 브리핑, 아웃트로 영상은 RAD Game Tools Smacker 영상입니다. 두 가지 확장자로 저장되어 있습니다.

확장자 사용처 비고
.smk 일반 Smacker 도구 표준 RAD 형식.
.zrb TA의 data/*.zrb 페이로드 Cavedog이 손쉬운 추출을 막으려고 Smacker 파일의 확장자를 .zrb로 바꿨습니다. 바이너리 내용은 바이트 단위로 동일합니다.

FFmpeg은 Smacker를 기본으로 디코딩할 수 있으며, kbot은 Smacker → MP4 변환 엔진으로 FFmpeg을 씁니다. 반대 방향으로 변환하는 것은 없습니다: 기본 FFmpeg에는 Smacker 인코더도 먹서도 없고, kbot에도 Smacker 라이터가 없습니다. TA용 SMK2 영상은 RAD Game Tools의 Smacker 도구로 만듭니다.

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 vs 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 프레임당 10만분의 1초 단위: 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

Cavedog의 ZRB 파일에는 슬롯 0에 트랙이 하나만 있습니다: 워드 0xD0005622 — 있음, 22,050 Hz, 스테레오, 8비트, 압축됨. 나머지 여섯 슬롯은 0입니다. 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 먹서를 모두 내놓을 때만 FFmpeg을 시도합니다). TA용 SMK2 영상은 RAD Game Tools의 Smacker 도구로 만드세요.


일반적인 크기

에셋 해상도 프레임 길이 파일 크기
인트로 영상(data/1.zrb) 640 × 240(표시 640 × 480) 599 약 20초 약 7 MB
그 밖의 영상(data/2.zrb–5.zrb) 640 × 240(표시 640 × 480) — — 10–41 MB

주의할 점

Warning

AudioRate는 레이트가 아니라 여러 값을 담은 워드입니다. 평범한 숫자로 읽으면 정식판의 워드 0xD0005622는 3,489,682,978 "Hz"가 됩니다. 레이트는 하위 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로 이름을 바꾸는 것은 무해하지만, 게임은 data/ 디렉터리에서 .zrb를 찾습니다. 엔진에는 .smk 이름의 파일을 배포하지 마세요.

함께 보기

  • Bink — TA: Kingdoms가 Smacker 대신 쓰는 후속 코덱.
  • HPI — ZRB 파일을 담아 배포하는 컨테이너 아카이브.
  • 용어집 — frame rate, signature.