View Page Source

Revision (current)
Last Updated by feos on 7/25/2015 2:19 PM
Back to Page

{{zmv}} is the movie capture format of [OtherEmulators|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
[http://www.php.net/utf8_encode|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], [FAQ|frequently asked questions]