diff --git a/Core/gb.c b/Core/gb.c index cbd295c..dec32a9 100644 --- a/Core/gb.c +++ b/Core/gb.c @@ -896,3 +896,8 @@ void GB_set_update_input_hint_callback(GB_gameboy_t *gb, GB_update_input_hint_ca { gb->update_input_hint_callback = callback; } + +double GB_get_usual_frame_rate(GB_gameboy_t *gb) +{ + return GB_get_clock_rate(gb) / (double)LCDC_PERIOD; +} diff --git a/Core/gb.h b/Core/gb.h index 2d7d599..b943d85 100644 --- a/Core/gb.h +++ b/Core/gb.h @@ -695,7 +695,7 @@ void GB_set_clock_multiplier(GB_gameboy_t *gb, double multiplier); unsigned GB_get_screen_width(GB_gameboy_t *gb); unsigned GB_get_screen_height(GB_gameboy_t *gb); - +double GB_get_usual_frame_rate(GB_gameboy_t *gb); unsigned GB_get_player_count(GB_gameboy_t *gb); #endif /* GB_h */ diff --git a/Core/sgb.c b/Core/sgb.c index 89218ab..5bcb72d 100644 --- a/Core/sgb.c +++ b/Core/sgb.c @@ -466,7 +466,7 @@ static void render_jingle(GB_gameboy_t *gb, size_t count); void GB_sgb_render(GB_gameboy_t *gb) { if (gb->apu_output.sample_rate) { - render_jingle(gb, gb->apu_output.sample_rate / (GB_get_clock_rate(gb) / (double)LCDC_PERIOD)); + render_jingle(gb, gb->apu_output.sample_rate / GB_get_usual_frame_rate(gb)); } if (gb->sgb->intro_animation < INTRO_ANIMATION_LENGTH) gb->sgb->intro_animation++; diff --git a/libretro/libretro.c b/libretro/libretro.c index cec93f8..1dd411c 100644 --- a/libretro/libretro.c +++ b/libretro/libretro.c @@ -14,8 +14,6 @@ #define AUDIO_FREQUENCY 48000 #endif -#define FRAME_RATE (0x400000 / 70224.0) - #ifdef _WIN32 #include #include @@ -727,7 +725,7 @@ void retro_get_system_info(struct retro_system_info *info) void retro_get_system_av_info(struct retro_system_av_info *info) { struct retro_game_geometry geom; - struct retro_system_timing timing = { FRAME_RATE, AUDIO_FREQUENCY }; + struct retro_system_timing timing = { GB_get_usual_frame_rate(&gameboy[0]), AUDIO_FREQUENCY }; if (emulated_devices == 2) { @@ -947,11 +945,11 @@ bool retro_load_game_special(unsigned type, const struct retro_game_info *info, environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void *)vars_dual); check_variables(); - frame_buf = (uint32_t*)malloc(emulated_devices * VIDEO_PIXELS * sizeof(uint32_t)); - frame_buf_copy = (uint32_t*)malloc(emulated_devices * VIDEO_PIXELS * sizeof(uint32_t)); + frame_buf = (uint32_t*)malloc(emulated_devices * SGB_VIDEO_PIXELS * sizeof(uint32_t)); + frame_buf_copy = (uint32_t*)malloc(emulated_devices * SGB_VIDEO_PIXELS * sizeof(uint32_t)); - memset(frame_buf, 0, emulated_devices * VIDEO_PIXELS * sizeof(uint32_t)); - memset(frame_buf_copy, 0, emulated_devices * VIDEO_PIXELS * sizeof(uint32_t)); + memset(frame_buf, 0, emulated_devices * SGB_VIDEO_PIXELS * sizeof(uint32_t)); + memset(frame_buf_copy, 0, emulated_devices * SGB_VIDEO_PIXELS * sizeof(uint32_t)); enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_XRGB8888; if (!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt)) @@ -987,54 +985,65 @@ bool retro_load_game_special(unsigned type, const struct retro_game_info *info, size_t retro_serialize_size(void) { - if (emulated_devices == 2) - return GB_get_save_state_size(&gameboy[0]) + GB_get_save_state_size(&gameboy[1]); - else - return GB_get_save_state_size(&gameboy[0]); + static size_t maximum_save_size = 0; + if (maximum_save_size) { + return maximum_save_size * 2; + } + + GB_gameboy_t temp; + + GB_init(&temp, GB_MODEL_DMG_B); + maximum_save_size = GB_get_save_state_size(&temp); + GB_free(&temp); + + GB_init(&temp, GB_MODEL_CGB_E); + maximum_save_size = MAX(maximum_save_size, GB_get_save_state_size(&temp)); + GB_free(&temp); + + GB_init(&temp, GB_MODEL_SGB2); + maximum_save_size = MAX(maximum_save_size, GB_get_save_state_size(&temp)); + GB_free(&temp); + + return maximum_save_size * 2; } bool retro_serialize(void *data, size_t size) { - if (!initialized) + if (!initialized || !data) return false; - void* save_data[2]; - size_t state_size[2]; size_t offset = 0; - for (int i = 0; i < emulated_devices; i++) - { - state_size[i] = GB_get_save_state_size(&gameboy[i]); - save_data[i] = (uint8_t*)malloc(state_size[i]); - GB_save_state_to_buffer(&gameboy[i], (uint8_t*) save_data[i]); - memcpy(data + offset, save_data[i], state_size[i]); - offset += state_size[i]; - free(save_data[i]); + for (int i = 0; i < emulated_devices; i++) { + size_t state_size = GB_get_save_state_size(&gameboy[i]); + if (state_size > size) { + return false; + } + + GB_save_state_to_buffer(&gameboy[i], ((uint8_t *) data) + offset); + offset += state_size; + size -= state_size; } - if (data) - return true; - else - return false; + return true; } bool retro_unserialize(const void *data, size_t size) { - void* save_data[2]; - size_t state_size[2]; - int ret; - for (int i = 0; i < emulated_devices; i++) { - state_size[i] = GB_get_save_state_size(&gameboy[i]); - save_data[i] = (uint8_t*)malloc(state_size[i]); - memcpy (save_data[i], data + (state_size[i] * i), state_size[i]); - ret = GB_load_state_from_buffer(&gameboy[i], save_data[i], state_size[i]); - free(save_data[i]); - - if (ret != 0) + size_t state_size = GB_get_save_state_size(&gameboy[i]); + if (state_size > size) { return false; + } + + if (GB_load_state_from_buffer(&gameboy[i], data, state_size)) { + return false; + } + + size -= state_size; + data = ((uint8_t *)data) + state_size; } return true;