From b325148544e0b93c1b75d2917fe91b25ccce97fb Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Wed, 14 Apr 2021 23:37:00 +0300 Subject: [PATCH] Update and clarify specification --- BESS.md | 17 +++++++++-------- Core/save_state.c | 9 +++++++-- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/BESS.md b/BESS.md index 03cb54c..9a4a10f 100644 --- a/BESS.md +++ b/BESS.md @@ -30,9 +30,16 @@ BESS uses a block format where each block contains the following header: Every block is followed by another blocked, until the END block is reached. If an implementation encounters an unsupported block, it should be completely ignored (Should not have any effect and should not trigger a failure). +#### NAME block + +The NAME block uses the `'NAME'` identifier, and is an optional block that contains the name of the emulator that created this save state. While optional, it is highly recommended to be included in every implementation – it allows the user to know which emulator and version is compatible with the native save state format contained in this file. When used, this block should come first. + +The length of the NAME block is variable, and it only contains the name and version of the originating emulator in ASCII. + + #### CORE block -The CORE block uses the `'CORE'` identifier, and is a required block that contains both core state information, as well as basic information about the BESS version used. This block must be the first block, except for the `NAME` block (But an implementation should allow unknown blocks to appear before it for future compatibility). +The CORE block uses the `'CORE'` identifier, and is a required block that contains both core state information, as well as basic information about the BESS version used. This block must be the first block, unless the `NAME` block exists then it must be second. An implementation should not enforce block order on blocks unknown to it for future compatibility. The length of the CORE block is 0xD0 bytes, but implementations are expected to ignore any excess bytes. Following the BESS block header, the structure is as follows: @@ -105,12 +112,6 @@ The contents of large buffers are stored outside of BESS structure so data from An implementation needs handle size mismatches gracefully. For example, if too large MBC RAM size is specified, the superfluous data should be ignored. On the other hand, if a too small VRAM size is specified (For example, if it's a save state from an emulator emulating a CGB in DMG mode, and it didn't save the second CGB VRAM bank), the implementation is expected to set that extra bank to all zeros. -#### NAME block - -The NAME block uses the `'NAME'` identifier, and is an optional block that contains the name of the emulator that created this save state. While optional, it is highly recommended to be included in every implementation – it allows the user to know which emulator and version is compatible with the native save state format contained in this file. When used, this block should come first. - -The length of the NAME block is variable, and it only contains the name and version of the originating emulator in ASCII. - #### XOAM block The XOAM block uses the `'XOAM'` identifier, and is an optional block that contains the data of extra OAM (addresses `0xFEA0-0xFEFF`). This block length must be `0x60`. Implementations that do not emulate this extra range are free to ignore the excess bytes, and to not create this block. @@ -172,7 +173,7 @@ The length of this block is 0x11 bytes long and it follows the following structu The SGB block uses the `'SGB '` identifier, and is an optional block that is only used while emulating an SGB or SGB2 *and* SGB commands enabled. Implementations must not save this block on other models or when SGB commands are disabled, and should assume SGB commands are disabled if this block is missing. -The length of this block is 0x39 bytes and it follows the following structure: +The length of this block is 0x39 bytes, but implementations should allow and ignore excess data in this block for extensions. The block follows the following structure: | Offset | Content | |--------|--------------------------------------------------------------------------------------------------------------------------| diff --git a/Core/save_state.c b/Core/save_state.c index 17932ee..980b791 100644 --- a/Core/save_state.c +++ b/Core/save_state.c @@ -988,8 +988,13 @@ static int load_bess_save(GB_gameboy_t *gb, virtual_file_t *file, bool is_samebo case BE32('SGB '): if (!found_core) goto parse_error; if (!gb->sgb) goto parse_error; - if (LE32(block.size) != sizeof(BESS_SGB_t) - sizeof(block)) goto parse_error; - file->read(file, &sgb.header + 1, sizeof(BESS_SGB_t) - sizeof(block)); + if (LE32(block.size) > sizeof(sgb) - sizeof(block)) { + if (file->read(file, &sgb.header + 1, sizeof(sgb) - sizeof(block)) != sizeof(sgb) - sizeof(block)) goto error; + file->seek(file, LE32(block.size) - (sizeof(sgb) - sizeof(block)), SEEK_CUR); + } + else { + if (file->read(file, &sgb.header + 1, LE32(block.size)) != LE32(block.size)) goto error; + } found_sgb = true; break; case BE32('END '):