diff --git a/libretro.c b/libretro.c index a7255e7..f1be558 100644 --- a/libretro.c +++ b/libretro.c @@ -47,6 +47,14 @@ static int translation_caches_inited = 0; #define MAX_PATH (512) #endif +frameskip_type current_frameskip_type = no_frameskip; +u32 frameskip_value = 4; +u32 random_skip = 0; + +u32 skip_next_frame = 0; + +u32 frameskip_counter = 0; + static retro_log_printf_t log_cb; static retro_video_refresh_t video_cb; static retro_input_poll_t input_poll_cb; @@ -312,6 +320,9 @@ void retro_set_environment(retro_environment_t cb) #ifdef HAVE_DYNAREC { "gpsp_drc", "Dynamic recompiler (restart); enabled|disabled" }, #endif + { "gpsp_frameskip_type", "Frameskip type; off|manual" }, + { "gpsp_frameskip_value", "Frameskip value; 1|2|3|4|5|6|7|8|9|0" }, + { "gpsp_frameskip_variation", "Frameskip variation; uniform|random" }, { NULL, NULL }, }; @@ -422,9 +433,9 @@ static void extract_directory(char* buf, const char* path, size_t size) static void check_variables(int started_from_load) { -#ifdef HAVE_DYNAREC struct retro_variable var; +#ifdef HAVE_DYNAREC var.key = "gpsp_drc"; var.value = NULL; @@ -441,6 +452,31 @@ static void check_variables(int started_from_load) else dynarec_enable = 1; #endif + + var.key = "gpsp_frameskip_value"; + var.value = 0; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + frameskip_value = strtol(var.value, NULL, 10); + + var.key = "gpsp_frameskip_type"; + var.value = NULL; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "off")) + current_frameskip_type = no_frameskip; + else if (!strcmp(var.value, "manual")) + current_frameskip_type = manual_frameskip; + } + + var.key = "gpsp_frameskip_variation"; + var.value = NULL; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (!strcmp(var.value, "uniform")) + random_skip = 0; + else if (!strcmp(var.value, "random")) + random_skip = 1; + } } static void set_input_descriptors() @@ -490,7 +526,7 @@ bool retro_load_game(const struct retro_game_info* info) rom_translation_ptr = rom_translation_cache; ram_translation_ptr = ram_translation_cache; bios_translation_ptr = bios_translation_cache; -#elif defined(VITA) +#elif defined(PSP) || defined(VITA) dynarec_enable = 1; rom_translation_ptr = rom_translation_cache; ram_translation_ptr = ram_translation_cache; @@ -621,11 +657,33 @@ void retro_run(void) input_poll_cb(); + s32 used_frameskip = frameskip_value; + + skip_next_frame = 0; + + if(current_frameskip_type == manual_frameskip) + { + frameskip_counter = (frameskip_counter + 1) % + (used_frameskip + 1); + if(random_skip) + { + if(frameskip_counter != (rand() % (used_frameskip + 1))) + skip_next_frame = 1; + } + else + { + if(frameskip_counter) + skip_next_frame = 1; + } + } + switch_to_cpu_thread(); render_audio(); - video_run(); + /* Skip the video callback when skipping frames so the frontend can properly report FPS */ + if (!skip_next_frame) + video_run(); if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) check_variables(0); diff --git a/main.h b/main.h index 1f730c0..240c327 100644 --- a/main.h +++ b/main.h @@ -54,9 +54,20 @@ typedef struct timer_status_type status; } timer_type; +typedef enum +{ + auto_frameskip, + manual_frameskip, + no_frameskip +} frameskip_type; + extern u32 cpu_ticks; extern u32 execute_cycles; +extern frameskip_type current_frameskip_type; +extern u32 frameskip_value; +extern u32 random_skip; extern u32 global_cycles_per_instruction; +extern u32 skip_next_frame; extern u32 cycle_memory_access; extern u32 cycle_pc_relative_access; @@ -91,7 +102,6 @@ u32 file_length(const char *dummy, FILE *fp); extern u32 real_frame_count; extern u32 virtual_frame_count; -extern u32 max_frameskip; extern u32 num_skipped_frames; extern int dynarec_enable; diff --git a/video.c b/video.c index 48469e9..23cd368 100644 --- a/video.c +++ b/video.c @@ -4437,6 +4437,9 @@ void update_scanline(void) order_layers((dispcnt >> 8) & active_layers[video_mode]); + if(skip_next_frame) + return; + // If the screen is in in forced blank draw pure white. if(dispcnt & 0x80) {