Back to Page
Revision 9 (current)
Edited by Unknown on 1/1/2022 6:14 PM
%%TOC%%
!!!Text format
!! Overall file structure
The movie / savestate files are .zip archives with the following restictions
* Members must be each be uncompressed or compressed using deflate.
* Encryption must not be used.
* No patching or any other exotic stuff.
!! Savestate / SRAM / clean detection
* If file named "savestate" is present, it is a savestate, otherwise
* If file named "savestate.anchor" is present, it starts from savestate, otherwise
* If file with name starting with "moviesram." is present, it starts from SRAM, otherwise
* It starts from clean state
!! Members
The various standard members of the savestate.
! gametype
Type: One line%%%
If misisng: Load error%%%
Gives the type of system and region.
* snes_ntsc: NTSC SNES
* snes_pal: PAL SNES
* bsx: BS-X, non-slotted cartridge (always NTSC)
* bsxslotted: BS-X slotted cartridge (always NTSC)
* sufamiturbo: Sufami Turbo (always NTSC)
* sgb_ntsc: NTSC SGB
* sgb_pal: PAL SGB
* gdmg: Game Boy
* ggbc: Game Boy Color
* ggbca: Game Boy Color (GBA initial reg. values)
PAL framerate: 322445/6448 fps.%%%
NTSC framerate: 10738636/178683 fps.%%%
Game Boy framerate: 262144/4389 fps.
! port<n> (<n> is a number)
Type: One line%%%
If misisng: Set to default%%%
Gives the type of port <n> (1-based).
* none: No controller present
* gamepad: Standard Gamepad
* multitap: Multitap (4 gamepads). Note: Causes most games to not work or crash.
* mouse: Mouse
* superscope: Super Scope
* justifier: 1 justifier
* justifiers: 2 justifiers
Valid values depend on core type.
! setting.<name>
Type: One line%%%
If missing: Sett to default%%%
Gives value of a setting. Valid values depend on core type.
! gamename
Type: One line%%%
If missing: Game name will be blank.%%%
Name of the game. Purely for comment purposes
! authors
Type: Textual%%%
If missing: Authors list will be blank.%%%
Authors of the run, one per line. The part before '|' (if any) is real name, the part after is nickname.
! systemid
Type: One line%%%
If missing: Load error%%%
Must contain 'lsnes-rr1' (note: Even with rr0 and rr2 versions).
! controlsversion
Type: One line, mandatory%%%
If missing: Load error%%%
Must contain '0'.
! coreversion
Type: One line, mandatory%%%
If missing: Load error%%%
Bsnes core version string. Mismatch is error on loading savestate, warning on loading movie.
! projectid
Type: One line%%%
If missing: Load error%%%
Hexadecimal movie identifier. Used for recognizing movies.
! <slot>.sha256
Type one line%%%
If missing: Corresponding ROM is assumed absent%%%
SHA-256 hashes of ROM images. The <slot> may be either 'rom', 'romxml', 'slota'...'slotz' or 'slotaxml'...'slotzxml'.
The 'xml' slots are markup, and can be present only if corresponding non-'xml' slot is.
Valid slots vary depending on the system:
* SNES/GB/GBC: rom
* BS-X/SGB: rom, slota
* Sufami Turbo: rom, slota, slotb.
Hash failure is error on loading savestate, warning on loading movie.
! moviesram.<name>
Type: Raw binary%%%
If absent: Start with said SRAM clean.%%%
Contains initial contents of given SRAM.
As of bsnes v085, the following are used:
* moviesram.bss: SRAM on BS-X cartridge
* moviesram.bsp: PSRAM on BS-X cartridge
* moviesram.rtc: State of RTC on cartridge
* moviesram.nec: State of DSP ram on cartridge (if non-volatile)
* moviesram.slota.sts: State of Sufami Turbo slot A SRAM.
* moviesram.slotb.sts: State of Sufami Turbo slot B SRAM.
* moviesram.srm: SNES cartridge SRAM.
Gambatte uses the following:
* moviesram.main: Main SRAM.
* moviesram.rtc: RTC.
The cartridge may have only some of possible SRAMs or even none.
! saveframe
Type: One line%%%
If absent: Error if savestate, otherwise ignored%%%
Contains the number of frame game was saved on. Ignored if not loading savestate.
! lagcounter
Type: One line%%%
If absent: Error if savestate, otherwise ignored%%%
Contains the number of lag frames that have occured so far. Ignored if not loading savestate.
! pollcounters
Type: Text%%%
If absent: Error if savestate, otherwise ignored%%%
Contains the poll counters and data ready flags of (currently 100) controls.
! hostmemory
Type: Raw binary%%%
If absent: Resume with hostmemory clean%%%
Contains the Lua host memory. Ignored if not loading savestate.
! ramcontent.<name>
Type: Raw binary%%%
If absent: Fill with defaults%%%
Contains initial content of RAM memory block <name>.
! savestate
Type: Raw binary%%%
If absent: Load as movie%%%
Contains the bsnes core savestate.
The last 32 bytes are SHA-256 checksum of everything previous (the actual core savestate).
! savestate.anchor
Type: Raw binary%%%
If absent: Start from clean state or SRAM%%%
Contains the bsnes core savestate for initial state.
The last 32 bytes are SHA-256 checksum of everything previous (the actual core savestate).
! screenshot
Type: Raw binary%%%
If absent: Load error%%%
Contains screenshot of current screen.
! sram.<name>
Type: Raw binary%%%
If absent: Ignored%%%
Contains the contents of SRAM at the time of savestate. Ignored when loading.
! rerecords:
Type: One line%%%
If absent: Ignored%%%
Contains the rerecord count. Ignored when loading.
! rrdata
Type: Raw binary%%%
If absent: Load error%%%
Contains the data related to tracking rerecords. The rerecord count is computed from this.
The data compresses a set of IDs, each 32 bytes in length. Those are compressed into sequence of records (concatenated), each encoding starting ID and number of consequtive IDs (big-endian integers modulo 2^256 where next is increment by 1).
Each record consists of three parts:
* Opcode byte
* * Bits 0-4: The number of initial bytes omitted from the ID.
* * Bits 5-6: Number of bytes in sequence length.
* * Bit 7: Unused.
* First ID in sequence
* * The omitted bytes are taken from "next ID" field.
* Sequence length
* * If 0 bytes, the sequence length is 1.
* * If 1 byte, the sequence length minus 2.
* * If 2 bytes, big endian sequence length minus 258.
* * If 3 bytes, big endian sequence length minus 65794.
If more than 16,843,009 consequtive IDs are needed, multiple records are used to encode that.
After each record, the next ID field is set to the ID that comes after the last ID actually added. This field starts as all zeroes.
! starttime.second
Type: One line%%%
If absent: Default to 1,000,000,000.%%%
Contains the RTC starting time second part (since Unix epoch).
! starttime.subsecond
Type: One line%%%
If absent: Default to 0.%%%
Contains the RTC starting time subsecond part (in units of SMP cycles).
! savetime.second
Type: One line%%%
If absent: Default to 1,000,000,000.%%%
Contains the RTC current time second part (since Unix epoch).
! savetime.subsecond
Type: One line%%%
If absent: Default to 0.%%%
Contains the RTC current time subsecond part (in units of SMP cycles).
! input
Type: Textual%%%
If absent: Load error%%%
Contains the input, one subframe per line.
If line starts with <tab>, <CR>, <LF>, space, '.' or '|', it is part of previous frame, otherwise it starts a new frame (the first non-empty line must start a new frame).
Format:
F.|BYsSudlrAXLR
Where udlr are the directional buttons and LR are their respective buttons. If F is replaced with a '.' or whitespace, then this is a subframe instead of a frame. If the second character is not a '.' or whitespace, then this frame contains a reset. Certain resets are delayed resets, which have the following format:
FR X Y|BYsSudlrAXLR
Where 10000 * X + Y = the number of instructions to wait before resetting. When using LSMV's Gameboy (Gambatte) core, the format of a frame is as follows:
F.|ABsSrlud
! subtitles
Type: Textual%%%
If absent: Assume empty%%%
Contains subtitles, one per line in format <firstframe> <length> <text>
Backslash is written as \\, linefeed is written as \n
!!! Binary format
!! Types:
* Byte: 1 byte unsigned number.
* 32-bit: 4 byte unsigned big-endian number.
* varint: Variable-length number, all but the last byte have bit 7 set, last 7 bits of each byte form the number in __little endian__ order.
* string: Varint containing number of bytes in string, followed by UTF-8 value of that length.
* implicit-string: UTF-8 string taking remainder of block (these can only be inside blocks).
* implicit-blob: Binary data taking the remainder of block (these can only be inside blocks).
!! Overall file structure:
In order:
* Opaque: "lsmv" 0x1A
* string: Sysregion code (see gametype).
* Zero or more settings, for each:
* * Byte: 1
* * string: Name of setting.
* * string: Value of setting.
* Byte: 0
* Zero or more blocks, for each:
* * 32-bit: 0xaddb2d86
* * 32-bit: Block type.
* * Varint: Block payload length.
* * Opaque: Specified number of bytes making block payload.
!! Blocks
! Block type 0xf5e0fad7: ANCHOR_SAVE:
* implicit-blob: The savestate (last 32 bytes are SHA-256 checksum of previous).
! Block type 0xafff97b4: AUTHOR
* string: Real name
* implicit-string: Nickname
! Block type 0xe4344c7e: CORE_VERSION
* implicit-string: Core version string.
! Block type 0xe80d6970: GAMENAME
* implicit-string: Game name.
! Block type 0x3bf9d187: HOSTMEMORY
* implicit-blob: Lua Host memory contents.
! Block type 0xd261338f: MACRO
* varint: Frame number in macro
* implicit-string: Macro name.
! Block type 0xf3dca44b: MOVIE
* implicit-blob: Raw binary movie data
The frames are concatenated. Length of each frame and precise format depends on the core and settings.
! Block type 0xbbc824b7: MOVIE_SRAM
* string: Name of SRAM.
* implicit-blob: Initial contents for the SRAM.
! Block type 0x18c3a975: MOVIE_TIME
* varint: Seconds part of movie starting time.
* varint: Subseconds part of movie starting time.
! Block type 0x359bfbab: PROJECT_ID
* implicit-string: Project ID.
! Block type 0xd3ec3770: RAMCONTENT
* string: Name of memory area.
* implicit-blob: Initial contents of that memory area.
! Block type 0x0428acfc: ROMHASH
* byte: Number of slot
* * High 7 bits are slot number 0...26
* * Low bit is 0 for ROM slots, 1 for markup slots.
* implicit-string: Hash value
! Block type 0xa3a07f71: RRDATA
* implicit-blob: rrdata (see the textual file format).
! Block type 0xae9bfb2f: SAVE_SRAM
* string: Name of SRAM.
* implicit-blob: contents for the SRAM at time of savestate.
! Block type 0x2e5bc2ac: SAVESTATE
* Varint: Save frame
* Varint: Lag counter
* Varint: Current RTC second.
* Varint: Current RTC subsecond.
* 32-bit*n: Poll counters (Bit 31 is data ready bit). Number depends on the settings/core.
* Byte: Polled this frame flag.
* implicit-blob: Contents of the savestate.
! Block type 0xc6760d0e: SCREENSHOT
* implicit-blob: Screen contents.
! Block type 0x6a7054d3: SUBTITLE
* Varint: Starting frame
* Varint: Duration
* Implicit-string: Text (without escaping)