TASVideos

Tool-assisted game movies
When human skills are just not enough

ZMV

zmv is the movie capture format of ZSNES, a SNES emulator.

ZMV file format description

ZMV file is structured as follows:
Header Fixed size, see below.
Beginning savestate Always present, but not always used, see below.
Stream Consists of the key input and chapter data for the movie.
Internal chapter index This is an array of pointers to all the chapters embedded in the "stream". The length of this array is described in the header.
External chapters Consists of a number of "external chapters". The length of this array is described next.
External chapter count Surprise, this field isn't in the header.
Author name Author name.

Header

    000 3-byte signature: 5A 4D 56 "ZMV"
    003 2-byte little-endian unsigned int: zsnes version number
    005 4-byte little-endian integer: CRC32 of the ROM
    009 4-byte little-endian unsigned int: number of frames
    00D 4-byte little-endian unsigned int: number of rerecords
    011 4-byte little-endian unsigned int: number of frames removed by rerecord
    015 4-byte little-endian unsigned int: number of frames advanced step by step
    019 1-byte: average recording frames per second
    01A 4-byte little-endian unsigned int: number of key combos
    01E 2-byte little-endian unsigned int: number of internal chapters
    020 2-byte little-endian unsigned int: length of the author name field in bytes
    022 3-byte little-endian unsigned int: size of an uncompressed save state in bytes
    025 1-byte: reserved
    026 1-byte flags: initial input configuration
       bit 7: first input enabled
       bit 6: second input enabled
       bit 5: third input enabled
       bit 4: fourth input enabled
       bit 3: fifth input enabled
       bit 2: mouse in first port
       bit 1: mouse in second port
       bit 0: super scope in second port
    027 1-byte flags:
       bits 7,6:
           if "00", movie begins from savestate
           if "10", movie begins from reset
           if "01", movie begins from power-on
           if "11", movie begins from power-on with SRAM clear
       bit 5: if "0", movie is NTSC (60 fps); if "1", movie is PAL (50 fps)
       other: reserved, set to 0
    028 3-byte little-endian unsigned int: initial save state size, highest bit specifies compression, next 23 specifies size

Savestate

Next follows a ZST format savestate. This save state is only loaded if the movie begins from savestate or the version of ZSNES used to make the movie is the different than the one playing it.

On reset or power on without SRAM clear where the version matches, only the SRAM is loaded from the Savestate.

Stream

After the optional savestate, comes the actual stream of movie data.
The number of events in the stream is equal to (number_of_frames + number_of_internal_chapters).
Each event is at least 1 byte long.

The first byte of the event has the following format:

    000 1-byte flags:
       bit 7: "1" if controller 1 changed, "0" otherwise
       bit 6: "1" if controller 2 changed, "0" otherwise
       bit 5: "1" if controller 3 changed, "0" otherwise
       bit 4: "1" if controller 4 changed, "0" otherwise
       bit 3: "1" if controller 5 changed, "0" otherwise
       bit 2: "1" if this is a "chapter" update, "0" if it's a "controller" update
       bit 1: "1" if this is RLE data instead of any of the above
       bit 0: "1" if this is command data instead any of the above
If the event is a command, the other seven bits define the command. The command could be "reset now" or similar things.

If the event is RLE data, next follows 4 bytes which is the frame to repeat current input until (inclusive).

If the event is a "chapter" update, the packet follows with a ZST format savestate. Using a header of:

    000 3-byte little endian unsigned int: save state size in format defined above
    001 above size: save state
    above size+001 4-byte little endian unsigned int: frame number save state loads to
    above size+005 2-byte: controller status bit field, see below
    above size+007 9-byte: previous controller input bits

If the event is a "controller" update, next comes the controller data for each changed controller, 12 bits per controller, or 20 bits in the case of the super scope, zeropadding up to full bytes. The minimum length of the controller data is 2 bytes, and the maximum length is 9 bytes. Controller format:

     bit 11: A
     bit 10: X
     bit 9:  L
     bit 8:  R
     bit 7:  B
     bit 6:  Y
     bit 5:  Select
     bit 4:  Start
     bit 3:  Up
     bit 2:  Down
     bit 1:  Left
     bit 0:  Right
For example, if this frame contained input for controllers 1 and 2:

     byte 1:
         bit 7:  P1 B
         bit 6:  P1 Y
         bit 5:  P1 Select
         bit 4:  P1 Start
         bit 3:  P1 Up
         bit 2:  P1 Down
         bit 1:  P1 Left
         bit 0:  P1 Right
     byte 2:
         bit 7:  P2 B
         bit 6:  P2 Y
         bit 5:  P2 Select
         bit 4:  P2 Start
         bit 3:  P1 A
         bit 2:  P1 X
         bit 1:  P1 L
         bit 0:  P1 R
     byte 3:
         bit 7:  P2 Up
         bit 6:  P2 Down
         bit 5:  P2 Left
         bit 4:  P2 Right
         bit 3:  P2 A
         bit 2:  P2 X
         bit 1:  P2 L
         bit 0:  P2 R
The number of "controller" update events in the stream should be equal to the "number of frames" field in the file header.
The number of "chapter" update events in the stream should be equal to the "number of internal chapters" field in the file header.

Internal chapter index

Position in file: (file_size - author_name_length - 2 - external_chapter_count * (zst_size + 4+2+9+4) - internal_chapter_count*4)

Internal chapters are "chapters" made during the movie recording.

The internal chapter index is an index for quickly finding all the internal chapters in the movie stream. Finding the internal chapter index is another story though...

Each item in the internal chapter index is 4 bytes long, and follows this format:

    000 4-byte little-endian unsigned int: offset of the chapter in the file
The offset is counted from the file beginning (zerobased), and points to the chapter data in the movie stream (after the flag byte).

External chapters

Position in file: ( file_size - author_name_length - 2 - external_chapter_count * (zst_size + 4+2+9+4) )

External chapters are "chapters" made during the movie playback.

Each item in the external chapter begins with a savestate, followed by this table:

     000 4-byte little-endian unsigned int: frame number
     004 2-byte: bit field of controller status
     006 9-byte array: previous input data (1 scope [20] + 4 regular [12*4] + 4 padded bits)
     00F 4-byte little-endian unsigned int: offset to movie stream from beginning of file
The size of an external chapter is therefore (zst_size + 4+2+9+4) bytes.

External chapter count.

Position in file: (file_size - author_name_length - 2)

This is a 2-byte field.

    000 2-byte little-endian unsigned int: number of external chapters

Author name

Position in file: (file_size - author_name_length)

Last in the file comes the author name field, which is an UTF-8 encoded text string, no zero terminator. The length of this field is described in the header.
The number of characters in this field can be calculated only by iterating it.

(Surprise, the length of this field is in the header, even though the number of external chapters isn't.)


See also: Emulator resources, frequently asked questions


Combined RSS Feed
ZMV last edited by Brandon on 2012-10-06 21:48:55
Page info and history | Latest diff | List referrers | View Source