aboutsummaryrefslogtreecommitdiff
path: root/patches/mame2000/0002-add-frameskip.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patches/mame2000/0002-add-frameskip.patch')
-rw-r--r--patches/mame2000/0002-add-frameskip.patch276
1 files changed, 276 insertions, 0 deletions
diff --git a/patches/mame2000/0002-add-frameskip.patch b/patches/mame2000/0002-add-frameskip.patch
new file mode 100644
index 0000000..a07582e
--- /dev/null
+++ b/patches/mame2000/0002-add-frameskip.patch
@@ -0,0 +1,276 @@
+diff --git a/src/libretro/libretro.c b/src/libretro/libretro.c
+index 521a561..514e335 100644
+--- a/src/libretro/libretro.c
++++ b/src/libretro/libretro.c
+@@ -51,6 +51,20 @@ static scond_t *libretro_cond = NULL;
+ static slock_t *libretro_mutex = NULL;
+ #endif
+
++unsigned frameskip_type = 0;
++unsigned frameskip_threshold = 0;
++unsigned frameskip_counter = 0;
++unsigned frameskip_interval = 0;
++
++int retro_audio_buff_active = false;
++unsigned retro_audio_buff_occupancy = 0;
++int retro_audio_buff_underrun = false;
++
++unsigned retro_audio_latency = 0;
++int update_audio_latency = false;
++
++int should_skip_frame = 0;
++
+ int game_index = -1;
+ unsigned short *gp2x_screen15;
+ int thread_done = 0;
+@@ -151,10 +165,87 @@ static bool libretro_supports_bitmasks = false;
+
+ unsigned skip_disclaimer = 0;
+
+-static void update_variables(void)
++static void retro_audio_buff_status_cb(
++ bool active, unsigned occupancy, bool underrun_likely)
++{
++ retro_audio_buff_active = active;
++ retro_audio_buff_occupancy = occupancy;
++ retro_audio_buff_underrun = underrun_likely;
++}
++
++static void retro_set_audio_buff_status_cb(void)
++{
++ if (frameskip_type > 0)
++ {
++ struct retro_audio_buffer_status_callback buf_status_cb;
++
++ buf_status_cb.callback = retro_audio_buff_status_cb;
++ if (!environ_cb(RETRO_ENVIRONMENT_SET_AUDIO_BUFFER_STATUS_CALLBACK,
++ &buf_status_cb))
++ {
++ retro_audio_buff_active = false;
++ retro_audio_buff_occupancy = 0;
++ retro_audio_buff_underrun = false;
++ retro_audio_latency = 0;
++ }
++ else
++ {
++ /* Frameskip is enabled - increase frontend
++ * audio latency to minimise potential
++ * buffer underruns */
++ uint32_t frame_time_usec = 1000000.0 / Machine->drv->frames_per_second;
++
++ /* Set latency to 6x current frame time... */
++ retro_audio_latency = (unsigned)(6 * frame_time_usec / 1000);
++
++ /* ...then round up to nearest multiple of 32 */
++ retro_audio_latency = (retro_audio_latency + 0x1F) & ~0x1F;
++ }
++ }
++ else
++ {
++ environ_cb(RETRO_ENVIRONMENT_SET_AUDIO_BUFFER_STATUS_CALLBACK, NULL);
++ retro_audio_latency = 0;
++ }
++
++ update_audio_latency = true;
++}
++
++static void update_variables(bool first_run)
+ {
+ struct retro_variable var;
+-
++ bool prev_frameskip_type;
++
++ var.key = "mame2000-frameskip";
++ var.value = NULL;
++
++ prev_frameskip_type = frameskip_type;
++ frameskip_type = 0;
++
++ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
++ {
++ if (strcmp(var.value, "auto") == 0)
++ frameskip_type = 1;
++ if (strcmp(var.value, "threshold") == 0)
++ frameskip_type = 2;
++ }
++
++ var.key = "mame2000-frameskip_threshold";
++ var.value = NULL;
++
++ frameskip_threshold = 30;
++
++ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
++ frameskip_threshold = strtol(var.value, NULL, 10);
++
++ var.key = "mame2000-frameskip_interval";
++ var.value = NULL;
++
++ frameskip_interval = 1;
++
++ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
++ frameskip_interval = strtol(var.value, NULL, 10);
++
+ var.value = NULL;
+ var.key = "mame2000-skip_disclaimer";
+
+@@ -180,11 +271,19 @@ static void update_variables(void)
+ }
+ else
+ global_showinfo = 0;
++
++ /* Reinitialise frameskipping, if required */
++ if (!first_run &&
++ ((frameskip_type != prev_frameskip_type)))
++ retro_set_audio_buff_status_cb();
+ }
+
+ void retro_set_environment(retro_environment_t cb)
+ {
+ static const struct retro_variable vars[] = {
++ { "mame2000-frameskip", "Frameskip ; disabled|auto|threshold" },
++ { "mame2000-frameskip_threshold", "Frameskip Threshold (%); 30|40|50|60" },
++ { "mame2000-frameskip_interval", "Frameskip Interval; 1|2|3|4|5|6|7|8|9" },
+ { "mame2000-skip_disclaimer", "Skip Disclaimer; enabled|disabled" },
+ { "mame2000-show_gameinfo", "Show Game Information; disabled|enabled" },
+ { NULL, NULL },
+@@ -475,7 +574,7 @@ void retro_init(void)
+ libretro_mutex = slock_new();
+ #endif
+ init_joy_list();
+- update_variables();
++ update_variables(true);
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_INPUT_BITMASKS, NULL))
+ libretro_supports_bitmasks = true;
+@@ -496,6 +595,14 @@ void retro_deinit(void)
+ #endif
+
+ libretro_supports_bitmasks = false;
++ frameskip_type = 0;
++ frameskip_threshold = 0;
++ frameskip_counter = 0;
++ retro_audio_buff_active = false;
++ retro_audio_buff_occupancy = 0;
++ retro_audio_buff_underrun = false;
++ retro_audio_latency = 0;
++ update_audio_latency = false;
+ }
+
+ unsigned retro_api_version(void)
+@@ -560,9 +667,13 @@ void retro_run(void)
+ update_input();
+
+ if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated)
+- update_variables();
++ update_variables(false);
++
++ if (should_skip_frame)
++ video_cb(NULL, gfx_width, gfx_height, gfx_width * 2);
++ else
++ video_cb(gp2x_screen15, gfx_width, gfx_height, gfx_width * 2);
+
+- video_cb(gp2x_screen15, gfx_width, gfx_height, gfx_width * 2);
+ if (samples_per_frame)
+ {
+ if (usestereo)
+@@ -584,6 +695,19 @@ void retro_run(void)
+ #ifndef WANT_LIBCO
+ unlock_mame();
+ #endif
++
++ /* If frameskip/timing settings have changed,
++ * update frontend audio latency
++ * > Can do this before or after the frameskip
++ * check, but doing it after means we at least
++ * retain the current frame's audio output */
++ if (update_audio_latency)
++ {
++ environ_cb(RETRO_ENVIRONMENT_SET_MINIMUM_AUDIO_LATENCY,
++ &retro_audio_latency);
++ update_audio_latency = false;
++ }
++
+ }
+
+ bool retro_load_game(const struct retro_game_info *info)
+@@ -895,6 +1019,7 @@ bool retro_load_game(const struct retro_game_info *info)
+ run_thread = sthread_create(run_thread_proc, NULL);
+ #endif
+
++ retro_set_audio_buff_status_cb();
+ return true;
+ }
+
+diff --git a/src/libretro/video.c b/src/libretro/video.c
+index ce13ea0..f97ac05 100644
+--- a/src/libretro/video.c
++++ b/src/libretro/video.c
+@@ -8,6 +8,17 @@ extern int isIpad;
+ extern int emulated_width;
+ extern int emulated_height;
+ extern int safe_render_path;
++
++extern unsigned frameskip_type;
++extern unsigned frameskip_threshold;
++extern unsigned frameskip_counter;
++extern unsigned frameskip_interval;
++
++extern int retro_audio_buff_active;
++extern unsigned retro_audio_buff_occupancy;
++extern int retro_audio_buff_underrun;
++extern int should_skip_frame;
++
+ int iOS_exitPause = 0;
+ int iOS_cropVideo = 0;
+ int iOS_aspectRatio = 0;
+@@ -793,7 +804,7 @@ static INLINE void pan_display(void)
+
+ int osd_skip_this_frame(void)
+ {
+- return 0;
++ return should_skip_frame;
+ }
+
+ /* Update the display. */
+@@ -902,6 +913,41 @@ void osd_update_video_and_audio(struct osd_bitmap *bitmap)
+ /* Check for PGUP, PGDN and pan screen */
+ pan_display();
+
++ should_skip_frame = 0;
++ /* Check whether current frame should
++ * be skipped */
++ if ((frameskip_type > 0) &&
++ retro_audio_buff_active)
++ {
++ int skip_frame;
++
++ switch (frameskip_type)
++ {
++ case 1: /* auto */
++ skip_frame = retro_audio_buff_underrun;
++ break;
++ case 2: /* threshold */
++ skip_frame = (retro_audio_buff_occupancy < frameskip_threshold);
++ break;
++ default:
++ skip_frame = 0;
++ break;
++ }
++
++ if (skip_frame)
++ {
++ if(frameskip_counter < frameskip_interval)
++ {
++ should_skip_frame = 1;
++ frameskip_counter++;
++ }
++ else
++ frameskip_counter = 0;
++ }
++ else
++ frameskip_counter = 0;
++ }
++
+ hook_video_done();
+ }
+