Fix libretro SGB1 FPS, fix un/serialization memory corruptions in libretro

This commit is contained in:
Lior Halphon 2019-06-19 23:49:43 +03:00
parent 91b0e491c5
commit 50a6a3e35c
4 changed files with 53 additions and 39 deletions

View File

@ -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; 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;
}

View File

@ -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_width(GB_gameboy_t *gb);
unsigned GB_get_screen_height(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); unsigned GB_get_player_count(GB_gameboy_t *gb);
#endif /* GB_h */ #endif /* GB_h */

View File

@ -466,7 +466,7 @@ static void render_jingle(GB_gameboy_t *gb, size_t count);
void GB_sgb_render(GB_gameboy_t *gb) void GB_sgb_render(GB_gameboy_t *gb)
{ {
if (gb->apu_output.sample_rate) { 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++; if (gb->sgb->intro_animation < INTRO_ANIMATION_LENGTH) gb->sgb->intro_animation++;

View File

@ -14,8 +14,6 @@
#define AUDIO_FREQUENCY 48000 #define AUDIO_FREQUENCY 48000
#endif #endif
#define FRAME_RATE (0x400000 / 70224.0)
#ifdef _WIN32 #ifdef _WIN32
#include <direct.h> #include <direct.h>
#include <windows.h> #include <windows.h>
@ -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) void retro_get_system_av_info(struct retro_system_av_info *info)
{ {
struct retro_game_geometry geom; 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) 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); environ_cb(RETRO_ENVIRONMENT_SET_VARIABLES, (void *)vars_dual);
check_variables(); check_variables();
frame_buf = (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 * 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, 0, emulated_devices * SGB_VIDEO_PIXELS * sizeof(uint32_t));
memset(frame_buf_copy, 0, emulated_devices * 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; enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_XRGB8888;
if (!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt)) if (!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt))
@ -987,56 +985,67 @@ bool retro_load_game_special(unsigned type, const struct retro_game_info *info,
size_t retro_serialize_size(void) size_t retro_serialize_size(void)
{ {
if (emulated_devices == 2) static size_t maximum_save_size = 0;
return GB_get_save_state_size(&gameboy[0]) + GB_get_save_state_size(&gameboy[1]); if (maximum_save_size) {
else return maximum_save_size * 2;
return GB_get_save_state_size(&gameboy[0]); }
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) bool retro_serialize(void *data, size_t size)
{ {
if (!initialized) if (!initialized || !data)
return false; return false;
void* save_data[2];
size_t state_size[2];
size_t offset = 0; size_t offset = 0;
for (int i = 0; i < emulated_devices; i++) for (int i = 0; i < emulated_devices; i++) {
{ size_t state_size = GB_get_save_state_size(&gameboy[i]);
state_size[i] = GB_get_save_state_size(&gameboy[i]); if (state_size > size) {
save_data[i] = (uint8_t*)malloc(state_size[i]); return false;
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]; GB_save_state_to_buffer(&gameboy[i], ((uint8_t *) data) + offset);
free(save_data[i]); offset += state_size;
size -= state_size;
} }
if (data)
return true; return true;
else
return false;
} }
bool retro_unserialize(const void *data, size_t size) 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++) for (int i = 0; i < emulated_devices; i++)
{ {
state_size[i] = GB_get_save_state_size(&gameboy[i]); size_t state_size = GB_get_save_state_size(&gameboy[i]);
save_data[i] = (uint8_t*)malloc(state_size[i]); if (state_size > size) {
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)
return false; 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; return true;
} }