Don't use BESS for internal in-memory saves

This commit is contained in:
Lior Halphon 2021-04-13 20:35:07 +03:00
parent dfdbff7304
commit fada772cb1
4 changed files with 47 additions and 19 deletions

View File

@ -1899,7 +1899,7 @@ static bool undo(GB_gameboy_t *gb, char *arguments, char *modifiers, const debug
return true; return true;
} }
uint16_t pc = gb->pc; uint16_t pc = gb->pc;
GB_load_state_from_buffer(gb, gb->undo_state, GB_get_save_state_size(gb)); GB_load_state_from_buffer(gb, gb->undo_state, GB_get_save_state_size_no_bess(gb));
GB_log(gb, "Reverted a \"%s\" command.\n", gb->undo_label); GB_log(gb, "Reverted a \"%s\" command.\n", gb->undo_label);
if (pc != gb->pc) { if (pc != gb->pc) {
GB_cpu_disassemble(gb, gb->pc, 5); GB_cpu_disassemble(gb, gb->pc, 5);
@ -2205,8 +2205,8 @@ bool GB_debugger_execute_command(GB_gameboy_t *gb, char *input)
const debugger_command_t *command = find_command(command_string); const debugger_command_t *command = find_command(command_string);
if (command) { if (command) {
uint8_t *old_state = malloc(GB_get_save_state_size(gb)); uint8_t *old_state = malloc(GB_get_save_state_size_no_bess(gb));
GB_save_state_to_buffer(gb, old_state); GB_save_state_to_buffer_no_bess(gb, old_state);
bool ret = command->implementation(gb, arguments, modifiers, command); bool ret = command->implementation(gb, arguments, modifiers, command);
if (!ret) { // Command continues, save state in any case if (!ret) { // Command continues, save state in any case
free(gb->undo_state); free(gb->undo_state);
@ -2214,9 +2214,9 @@ bool GB_debugger_execute_command(GB_gameboy_t *gb, char *input)
gb->undo_label = command->command; gb->undo_label = command->command;
} }
else { else {
uint8_t *new_state = malloc(GB_get_save_state_size(gb)); uint8_t *new_state = malloc(GB_get_save_state_size_no_bess(gb));
GB_save_state_to_buffer(gb, new_state); GB_save_state_to_buffer_no_bess(gb, new_state);
if (memcmp(new_state, old_state, GB_get_save_state_size(gb)) != 0) { if (memcmp(new_state, old_state, GB_get_save_state_size_no_bess(gb)) != 0) {
// State changed, save the old state as the new undo state // State changed, save the old state as the new undo state
free(gb->undo_state); free(gb->undo_state);
gb->undo_state = old_state; gb->undo_state = old_state;
@ -2306,8 +2306,8 @@ void GB_debugger_run(GB_gameboy_t *gb)
if (gb->debug_disable) return; if (gb->debug_disable) return;
if (!gb->undo_state) { if (!gb->undo_state) {
gb->undo_state = malloc(GB_get_save_state_size(gb)); gb->undo_state = malloc(GB_get_save_state_size_no_bess(gb));
GB_save_state_to_buffer(gb, gb->undo_state); GB_save_state_to_buffer_no_bess(gb, gb->undo_state);
} }
char *input = NULL; char *input = NULL;
@ -2355,9 +2355,9 @@ next_command:
} }
else if (jump_to_result == JUMP_TO_NONTRIVIAL) { else if (jump_to_result == JUMP_TO_NONTRIVIAL) {
if (!gb->nontrivial_jump_state) { if (!gb->nontrivial_jump_state) {
gb->nontrivial_jump_state = malloc(GB_get_save_state_size(gb)); gb->nontrivial_jump_state = malloc(GB_get_save_state_size_no_bess(gb));
} }
GB_save_state_to_buffer(gb, gb->nontrivial_jump_state); GB_save_state_to_buffer_no_bess(gb, gb->nontrivial_jump_state);
gb->non_trivial_jump_breakpoint_occured = false; gb->non_trivial_jump_breakpoint_occured = false;
should_delete_state = false; should_delete_state = false;
} }

View File

@ -108,7 +108,7 @@ static void state_decompress(const uint8_t *prev, uint8_t *data, uint8_t *dest,
void GB_rewind_push(GB_gameboy_t *gb) void GB_rewind_push(GB_gameboy_t *gb)
{ {
const size_t save_size = GB_get_save_state_size(gb); const size_t save_size = GB_get_save_state_size_no_bess(gb);
if (!gb->rewind_sequences) { if (!gb->rewind_sequences) {
if (gb->rewind_buffer_length) { if (gb->rewind_buffer_length) {
gb->rewind_sequences = malloc(sizeof(*gb->rewind_sequences) * gb->rewind_buffer_length); gb->rewind_sequences = malloc(sizeof(*gb->rewind_sequences) * gb->rewind_buffer_length);
@ -140,11 +140,11 @@ void GB_rewind_push(GB_gameboy_t *gb)
if (!gb->rewind_sequences[gb->rewind_pos].key_state) { if (!gb->rewind_sequences[gb->rewind_pos].key_state) {
gb->rewind_sequences[gb->rewind_pos].key_state = malloc(save_size); gb->rewind_sequences[gb->rewind_pos].key_state = malloc(save_size);
GB_save_state_to_buffer(gb, gb->rewind_sequences[gb->rewind_pos].key_state); GB_save_state_to_buffer_no_bess(gb, gb->rewind_sequences[gb->rewind_pos].key_state);
} }
else { else {
uint8_t *save_state = malloc(save_size); uint8_t *save_state = malloc(save_size);
GB_save_state_to_buffer(gb, save_state); GB_save_state_to_buffer_no_bess(gb, save_state);
gb->rewind_sequences[gb->rewind_pos].compressed_states[gb->rewind_sequences[gb->rewind_pos].pos++] = gb->rewind_sequences[gb->rewind_pos].compressed_states[gb->rewind_sequences[gb->rewind_pos].pos++] =
state_compress(gb->rewind_sequences[gb->rewind_pos].key_state, save_state, save_size); state_compress(gb->rewind_sequences[gb->rewind_pos].key_state, save_state, save_size);
free(save_state); free(save_state);
@ -158,7 +158,7 @@ bool GB_rewind_pop(GB_gameboy_t *gb)
return false; return false;
} }
const size_t save_size = GB_get_save_state_size(gb); const size_t save_size = GB_get_save_state_size_no_bess(gb);
if (gb->rewind_sequences[gb->rewind_pos].pos == 0) { if (gb->rewind_sequences[gb->rewind_pos].pos == 0) {
GB_load_state_from_buffer(gb, gb->rewind_sequences[gb->rewind_pos].key_state, save_size); GB_load_state_from_buffer(gb, gb->rewind_sequences[gb->rewind_pos].key_state, save_size);
free(gb->rewind_sequences[gb->rewind_pos].key_state); free(gb->rewind_sequences[gb->rewind_pos].key_state);

View File

@ -218,7 +218,7 @@ static size_t bess_size_for_cartridge(const GB_cartridge_t *cart)
} }
} }
size_t GB_get_save_state_size(GB_gameboy_t *gb) size_t GB_get_save_state_size_no_bess(GB_gameboy_t *gb)
{ {
return GB_SECTION_SIZE(header) return GB_SECTION_SIZE(header)
+ GB_SECTION_SIZE(core_state) + sizeof(uint32_t) + GB_SECTION_SIZE(core_state) + sizeof(uint32_t)
@ -232,7 +232,12 @@ size_t GB_get_save_state_size(GB_gameboy_t *gb)
+ (GB_is_hle_sgb(gb)? sizeof(*gb->sgb) + sizeof(uint32_t) : 0) + (GB_is_hle_sgb(gb)? sizeof(*gb->sgb) + sizeof(uint32_t) : 0)
+ gb->mbc_ram_size + gb->mbc_ram_size
+ gb->ram_size + gb->ram_size
+ gb->vram_size + gb->vram_size;
}
size_t GB_get_save_state_size(GB_gameboy_t *gb)
{
return GB_get_save_state_size_no_bess(gb) +
// BESS // BESS
+ sizeof(BESS_CORE_t) + sizeof(BESS_CORE_t)
+ sizeof(BESS_block_t) // NAME + sizeof(BESS_block_t) // NAME
@ -453,7 +458,7 @@ static int save_bess_mbc_block(GB_gameboy_t *gb, virtual_file_t *file)
return 0; return 0;
} }
static int save_state_internal(GB_gameboy_t *gb, virtual_file_t *file) static int save_state_internal(GB_gameboy_t *gb, virtual_file_t *file, bool append_bess)
{ {
if (file->write(file, GB_GET_SECTION(gb, header), GB_SECTION_SIZE(header)) != GB_SECTION_SIZE(header)) goto error; if (file->write(file, GB_GET_SECTION(gb, header), GB_SECTION_SIZE(header)) != GB_SECTION_SIZE(header)) goto error;
if (!DUMP_SECTION(gb, file, core_state)) goto error; if (!DUMP_SECTION(gb, file, core_state)) goto error;
@ -475,6 +480,7 @@ static int save_state_internal(GB_gameboy_t *gb, virtual_file_t *file)
if (!dump_section(file, gb->sgb, sizeof(*gb->sgb))) goto error; if (!dump_section(file, gb->sgb, sizeof(*gb->sgb))) goto error;
} }
BESS_CORE_t bess_core = {0,}; BESS_CORE_t bess_core = {0,};
bess_core.mbc_ram.offset = LE32(file->tell(file)); bess_core.mbc_ram.offset = LE32(file->tell(file));
@ -495,6 +501,8 @@ static int save_state_internal(GB_gameboy_t *gb, virtual_file_t *file)
goto error; goto error;
} }
if (!append_bess) return 0;
BESS_footer_t bess_footer = { BESS_footer_t bess_footer = {
.start_offset = LE32(file->tell(file)), .start_offset = LE32(file->tell(file)),
.magic = BE32('BESS'), .magic = BE32('BESS'),
@ -694,7 +702,7 @@ int GB_save_state(GB_gameboy_t *gb, const char *path)
.tell = file_tell, .tell = file_tell,
.file = f, .file = f,
}; };
int ret = save_state_internal(gb, &file); int ret = save_state_internal(gb, &file, true);
fclose(f); fclose(f);
return ret; return ret;
} }
@ -709,10 +717,23 @@ void GB_save_state_to_buffer(GB_gameboy_t *gb, uint8_t *buffer)
.position = 0, .position = 0,
}; };
save_state_internal(gb, &file); save_state_internal(gb, &file, true);
assert(file.position == GB_get_save_state_size(gb)); assert(file.position == GB_get_save_state_size(gb));
} }
void GB_save_state_to_buffer_no_bess(GB_gameboy_t *gb, uint8_t *buffer)
{
virtual_file_t file = {
.write = buffer_write,
.seek = buffer_seek,
.tell = buffer_tell,
.buffer = (uint8_t *)buffer,
.position = 0,
};
save_state_internal(gb, &file, false);
assert(file.position == GB_get_save_state_size_no_bess(gb));
}
static bool read_section(virtual_file_t *file, void *dest, uint32_t size, bool fix_broken_windows_saves) static bool read_section(virtual_file_t *file, void *dest, uint32_t size, bool fix_broken_windows_saves)
{ {

View File

@ -27,4 +27,11 @@ void GB_save_state_to_buffer(GB_gameboy_t *gb, uint8_t *buffer);
int GB_load_state(GB_gameboy_t *gb, const char *path); int GB_load_state(GB_gameboy_t *gb, const char *path);
int GB_load_state_from_buffer(GB_gameboy_t *gb, const uint8_t *buffer, size_t length); int GB_load_state_from_buffer(GB_gameboy_t *gb, const uint8_t *buffer, size_t length);
#ifdef GB_INTERNAL
/* For internal in-memory save states (rewind, debugger) that do not need BESS */
size_t GB_get_save_state_size_no_bess(GB_gameboy_t *gb);
void GB_save_state_to_buffer_no_bess(GB_gameboy_t *gb, uint8_t *buffer);
#endif
#endif /* save_state_h */ #endif /* save_state_h */