diff --git a/config.def.h b/config.def.h index 1e158e4171..54ae55ae89 100644 --- a/config.def.h +++ b/config.def.h @@ -271,6 +271,9 @@ static const bool block_sram_overwrite = false; // When the ROM is loaded, state index will be set to the highest existing value. static const bool savestate_auto_index = false; +// Slowmotion ratio. +static const float slowmotion_ratio = 3.0; + //////////////////// // Keybinds, Joypad @@ -323,6 +326,7 @@ static const struct snes_keybind snes_keybinds_1[] = { { true, SSNES_DSP_CONFIG, SK_c, NO_BTN, AXIS_NONE }, { true, SSNES_MUTE, SK_F9, NO_BTN, AXIS_NONE }, { true, SSNES_NETPLAY_FLIP, SK_i, NO_BTN, AXIS_NONE }, + { true, SSNES_SLOWMOTION, SK_e, NO_BTN, AXIS_NONE }, }; // Player 2-5 diff --git a/driver.c b/driver.c index ac67e6c970..2d02b4bf0a 100644 --- a/driver.c +++ b/driver.c @@ -333,7 +333,7 @@ void init_audio(void) g_extern.audio_data.data_ptr = 0; ssnes_assert(g_settings.audio.out_rate < g_settings.audio.in_rate * AUDIO_MAX_RATIO); - ssnes_assert(g_extern.audio_data.outsamples = (float*)malloc(max_bufsamples * sizeof(float) * AUDIO_MAX_RATIO)); + ssnes_assert(g_extern.audio_data.outsamples = (float*)malloc(max_bufsamples * sizeof(float) * AUDIO_MAX_RATIO * g_settings.slowmotion_ratio)); g_extern.audio_data.orig_src_ratio = g_extern.audio_data.src_ratio = diff --git a/driver.h b/driver.h index c9ce3bcac1..77a10d9ad1 100644 --- a/driver.h +++ b/driver.h @@ -58,6 +58,7 @@ enum SSNES_DSP_CONFIG, SSNES_MUTE, SSNES_NETPLAY_FLIP, + SSNES_SLOWMOTION, #ifdef SSNES_CONSOLE SSNES_CHEAT_INPUT, diff --git a/general.h b/general.h index a7af7788a5..3e6cf1324f 100644 --- a/general.h +++ b/general.h @@ -167,6 +167,8 @@ struct settings size_t rewind_buffer_size; unsigned rewind_granularity; + float slowmotion_ratio; + bool pause_nonactive; unsigned autosave_interval; @@ -373,6 +375,7 @@ struct global // Pausing support bool is_paused; bool is_oneshot; + bool is_slowmotion; // Autosave support. autosave_t *autosave[2]; diff --git a/settings.c b/settings.c index c4e76d15fb..c92871682b 100644 --- a/settings.c +++ b/settings.c @@ -202,6 +202,7 @@ void config_set_defaults(void) g_settings.rewind_enable = rewind_enable; g_settings.rewind_buffer_size = rewind_buffer_size; g_settings.rewind_granularity = rewind_granularity; + g_settings.slowmotion_ratio = slowmotion_ratio; g_settings.pause_nonactive = pause_nonactive; g_settings.autosave_interval = autosave_interval; @@ -458,6 +459,9 @@ bool config_load_file(const char *path) g_settings.rewind_buffer_size = buffer_size * UINT64_C(1000000); CONFIG_GET_INT(rewind_granularity, "rewind_granularity"); + CONFIG_GET_FLOAT(slowmotion_ratio, "slowmotion_ratio"); + if (g_settings.slowmotion_ratio < 1.0f) + g_settings.slowmotion_ratio = 1.0f; CONFIG_GET_BOOL(pause_nonactive, "pause_nonactive"); CONFIG_GET_INT(autosave_interval, "autosave_interval"); @@ -573,6 +577,7 @@ static const struct bind_map bind_maps[MAX_PLAYERS][SSNES_BIND_LIST_END] = { DECLARE_BIND(dsp_config, SSNES_DSP_CONFIG), DECLARE_BIND(audio_mute, SSNES_MUTE), DECLARE_BIND(netplay_flip_players, SSNES_NETPLAY_FLIP), + DECLARE_BIND(slowmotion, SSNES_SLOWMOTION), }, DECL_PLAYER(2), diff --git a/ssnes.c b/ssnes.c index f7678f44b1..84f029ed28 100644 --- a/ssnes.c +++ b/ssnes.c @@ -307,6 +307,8 @@ static bool audio_flush(const int16_t *data, size_t samples) readjust_audio_input_rate(); src_data.ratio = g_extern.audio_data.src_ratio; + if (g_extern.is_slowmotion) + src_data.ratio *= g_settings.slowmotion_ratio; resampler_process(g_extern.audio_data.source, &src_data); @@ -1750,6 +1752,16 @@ static void check_rewind(void) psnes_set_audio_sample(g_extern.frame_is_reverse ? audio_sample_rewind : audio_sample); } +static void check_slowmotion(void) +{ + g_extern.is_slowmotion = driver.input->key_pressed(driver.input_data, SSNES_SLOWMOTION); + if (g_extern.is_slowmotion) + { + msg_queue_clear(g_extern.msg_queue); + msg_queue_push(g_extern.msg_queue, g_extern.frame_is_reverse ? "Slow motion rewind." : "Slow motion.", 0, 30); + } +} + static void check_movie_record(void) { static bool old_button = false; @@ -2070,6 +2082,7 @@ static void do_state_checks(void) } check_rewind(); + check_slowmotion(); if (g_extern.bsv.movie_playback) check_movie_playback(); diff --git a/ssnes.cfg b/ssnes.cfg index 1d94b34b03..bed6579de6 100644 --- a/ssnes.cfg +++ b/ssnes.cfg @@ -278,6 +278,9 @@ # Netplay flip players. # input_netplay_flip_players = i +# Hold for slowmotion. +# input_slowmotion = e + #### Misc # Enable rewinding. This will take a performance hit when playing, so it is disabled by default. @@ -331,3 +334,6 @@ # There is no upper bound on the index. # savestate_auto_index = false +# Slowmotion ratio. When slowmotion, game will slow down by factor. +# slowmotion_ratio = 3.0 +