Skip to content

Instantly share code, notes, and snippets.

@leiradel
Last active January 23, 2021 17:48
Show Gist options
  • Save leiradel/3eeb240acab8d0fd5e0d70889ec9caeb to your computer and use it in GitHub Desktop.
Save leiradel/3eeb240acab8d0fd5e0d70889ec9caeb to your computer and use it in GitHub Desktop.

Save states

Despite having an API that creates save state data into an user-provided buffer, some Libretro cores still create additional data as files. Additionally, Libretro save states don't feature a screenshot of the video frame buffer at the time the save state is created, making it impossible to preview the save state or restore the frame buffer when the save state is loaded back.

We also want to save data to completely restore the emulation state, like the core name and version, core options values, and any other data needed by the application.

To make it easier to put all this data into a single file, we'll use the RIFF format. RIFF is a chunked format, allowing us to save everything we need in an organized way.

All integers and float-point numbers are written in little-endian, and strings are null-terminated.

Chunks

Save states will have one main chunk, HCSV, with the following subchunks to hold the data:

  • HC :
    • HASH: The git commit hash when the app was built
    • OPTS: A chunk with the application options, each option is serialized as:
      • A string with an application option key
      • A string with an application option value that was selected at the time the save state was created
      • The list terminates with an empty option key (length is 0)
  • TIME: ISO-8601 data and time when the file was created
  • REM : A string with any notes that the user wanted to save along with the save state
  • FRMB: Frame buffer contents
    • AVNF: A copy of the retro_system_av_info structure contents at the time the save state was created. All values must be serialized in little-endian, without any padding, in the same order as they appear in the structure.
    • PXFM: A 32-bit unsigned integer with the pixel format as specified with the retro_pixel_format enumeration
    • PIXL: Pixel data using the format specified in the PXFM chunk and dimensions specified in AVNF, compressed with zlib
  • SAVE: The data obtained with a call to retro_serialize
  • FILE: If the core creates files to persist additional data, they are added to this chunk, which is repeated for each file
    • PATH: A 32-bit unsigned integer specifying where the file must be put in the file system so the core can find it
      • 0: System folder
      • 1: Same folder as the core
      • 2: Core assets folder
      • 3: Save folder
    • NAME: a string with the file name, without the path
    • UNSZ: A 32-bit unsigned integer with the size of DATA when uncompressed
    • DATA: The contents of the file compressed with zlib
  • CORE: A chunk with core information
    • NAME: A string with the library name from retro_system_info
    • VERS: A string with the library version also from retro_system_info
    • OPTS: A chunk with the core options, same format as the application options
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment