-
Notifications
You must be signed in to change notification settings - Fork 0
ANM TV Format
Vairn edited this page Jun 1, 2026
·
7 revisions
This documents the custom MM2 animation format used by files like 54.anm..74.anm.
It is based on:
- Binary inspection of
EXTRACTED/*.anm - Runtime string/use evidence in
EXTRACTED/mm2.asm(00.anmtemplate) - Legacy decode code from your older
gfxToolproject
All samples start with file magic:
-
00 00 54 56("TV"marker at bytes 2..3)
Then:
-
Prelude frame descriptors (fixed 11 slots, 4 bytes each) at
0x04..0x2F- Unused slots are
FF FF FF FF - Used slot (current best model):
u8 x_offsetu8 y_offsetu8 widthu8 height
- Working composition model from file behavior:
- frame
0= base sprite - frame
N>0= patch sprite drawn atprelude[N-1].(x_offset,y_offset) -
width/heightcan act as patch crop bounds
- frame
- Unused slots are
-
Sequence header bytes at
0x30..0x32-
seq_header_b & 0x7F~= sequence-count hint (can under-report) - high bit in
seq_header_bis often set (unknown flag)
-
-
Sequence stream at
0x33...- Sequence blocks are delimited by
0xFF - Payload is typically
(frame_index, delay)byte pairs - Parse until image marker (
FF 00 ...), do not hard-stop on header hint
- Sequence blocks are delimited by
-
Image chunk marker + header
- Located by scanning for
FF 00then interpreting big-endian words at the next byte - Header words:
u16 frame_count-
u16 depth_or_mode(observed3)
- Located by scanning for
-
Per-frame image metadata (
frame_countentries):u16 widthu16 height-
u16 flags(observed mostly0)
-
Palette: 32 words (
u16) - Frame pixel stream: packed nibble RLE/literal stream, decoded sequentially per frame
Each command byte:
- If high nibble is
0x0or0xF:- Emit nibble value (
0or15) repeated(low_nibble + 1)times
- Emit nibble value (
- Else:
- Literal byte: emit two nibbles (high, then low)
Nibbles are packed to bytes in order (n0,n1 -> byte (n0<<4)|n1).
Decoded output for one frame is:
-
5 * RASSIZE(width, height)bytes RASSIZE(w,h) = h * ((((w) + 15) >> 3) & 0xFFFE)- Payload is 5 planar bitplanes concatenated (
plane0..plane4)
Because some control fields are still partially unknown, the safest saver strategy is:
- Parse and keep all known fields structurally.
- Preserve unknown bytes/flags exactly.
- Re-emit sequence section and prelude table byte-identically unless intentionally edited.
- Only recompute frame payload and any lengths/offsets that are explicitly required.
Use the reference implementation in:
EXTRACTED/decomp/mm2_anm_codec.hEXTRACTED/decomp/mm2_anm_codec.c
Core API:
-
mm2_anm_load_file()parses container + frame metadata and decodes frame planes. -
mm2_anm_save_file()writes parsed structure back. -
mm2_anm_free()releases owned buffers.
The saver currently targets roundtrip/preservation semantics; if you want canonical rebuild (re-encode stream from raw planes), add a dedicated encoder pass.
tools/decode_anm.py now parses this format and writes:
EXTRACTED/anm_decoded/<name>/meta.jsonEXTRACTED/anm_decoded/<name>/frame_###/plane{0..4}.bin
Example:
python tools\decode_anm.py EXTRACTED\54.anm EXTRACTED\74.anm- Docs Wiki Hub ← full doc index
- Getting Started ← read this first
- Overview
- Workspace Notes
- Open Questions
- Full Analysis
- Game Remake
- Startup and Init
- Runtime Memory Map
- Main Loop and Map
- Exploration Input and Options
- Party and Session
- Game State Struct
- Data Hunk mm2 data 00
- Time Era Calendar
- GFX Loading
- ANM TV Format
- PC DOS graphics
- SNES graphics
- 3D View and Game Screen
- Amiga 3D Render Process
- Scripted Scene Graphics
- Event Graphics Opcodes
- Title Screen Assets
- Title Screen Animation
- Format inventory
- items.dat
- monsters.dat
- roster.dat
- attrib.dat
- map.dat
- spells & item use
- event.dat
- Events by location ← 71 maps
- Events hub (numbered)
- Event Script Opcodes
-
Event Script DSL ←
.mm2evtauthoring - Event Text Rendering
- Event Graphics Opcodes
- Combat Overview
- Combat System
- Encounter Tables
- Spell Cast ASM
- monsters.dat abilities
- Spells and item use
- Amiga audio in exe ← Paula / DATA / remake
- Controls: Sounds / Walk Beep
- MM2 music format (superseded)
- Title/death audio paths (superseded)
- Known songs catalog (superseded)
- Town Services
- Spell Sources
- Character Mechanics
- Skills and Hirelings
- Commerce Formulas
- Commerce World Services
- Mount Farview Class Quest
- Class Quest HP Bug
- Event Runtime
- Event to String Path
- Embedded Exe Strings
- Copy Protection
- Time Era Calendar
- Game State Struct
- MM1 Overview ← hub + decode status
- MM1 MAZEDATA format
- MM1 to MM2 outdoor
- MM1 WALLPIX by sector
- MM1 art & graphics
- MM1 items / monsters (status)
- MM1 map walker ↗
- MM1 2D maps gallery
- MM1 WALLPIX gallery