diff --git a/Makefile.win b/Makefile.win index 05db70577d..407562ae04 100644 --- a/Makefile.win +++ b/Makefile.win @@ -166,10 +166,10 @@ clean: rm -f tools/*.o dist_x86: all - zip -r ssnes-win32-0.9-rc3.zip $(TARGET) $(JTARGET) ssnes.cfg snes.dll SDL.dll + zip -r ssnes-win32-0.9-rc4.zip $(TARGET) $(JTARGET) ssnes.cfg snes.dll SDL.dll dist_x86_64: all - zip -r ssnes-win64-0.9-rc3.zip $(TARGET) $(JTARGET) ssnes.cfg snes.dll SDL.dll + zip -r ssnes-win64-0.9-rc4.zip $(TARGET) $(JTARGET) ssnes.cfg snes.dll SDL.dll libs_x86: wget https://github.com/downloads/Themaister/SSNES/SSNES-win32-libs.zip --no-check-certificate diff --git a/general.h b/general.h index 58d45a287d..a137a38232 100644 --- a/general.h +++ b/general.h @@ -41,6 +41,9 @@ #ifndef _WIN32 #include // MAXPATHLEN +#else +#define WIN32_LEAN_AND_MEAN +#include #endif #ifndef MAXPATHLEN @@ -282,6 +285,13 @@ struct global unsigned record_height; #endif + struct + { + const uint16_t *data; + unsigned width; + unsigned height; + } frame_cache; + char title_buf[64]; struct diff --git a/gfx/gl.c b/gfx/gl.c index ebdd04ec2b..f0d775d932 100644 --- a/gfx/gl.c +++ b/gfx/gl.c @@ -842,19 +842,14 @@ static void check_window(gl_t *gl) gl->frame_count); if (quit) - { gl->quitting = true; - } else if (resize) - { gl->should_resize = true; - } } static bool gl_frame(void *data, const void* frame, unsigned width, unsigned height, unsigned pitch, const char *msg) { gl_t *gl = data; - check_window(gl); gl_shader_use(1); gl->frame_count++; @@ -1336,6 +1331,7 @@ static void* gl_init(const video_info_t *video, const input_driver_t **input, vo static bool gl_alive(void *data) { gl_t *gl = data; + check_window(gl); return !gl->quitting; } diff --git a/gfx/sdl.c b/gfx/sdl.c index dd94d43c7c..bee4d82e91 100644 --- a/gfx/sdl.c +++ b/gfx/sdl.c @@ -465,7 +465,6 @@ static void check_window(sdl_video_t *vid) static bool sdl_gfx_frame(void *data, const void* frame, unsigned width, unsigned height, unsigned pitch, const char *msg) { sdl_video_t *vid = data; - check_window(vid); if (SDL_MUSTLOCK(vid->buffer)) SDL_LockSurface(vid->buffer); @@ -537,6 +536,7 @@ static void sdl_gfx_set_nonblock_state(void *data, bool state) static bool sdl_gfx_alive(void *data) { sdl_video_t *vid = data; + check_window(vid); return !vid->quitting; } diff --git a/netplay.c b/netplay.c index 86efc46dd8..2522b6de81 100644 --- a/netplay.c +++ b/netplay.c @@ -15,6 +15,25 @@ * If not, see . */ +#ifdef _WIN32 +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0501 +#endif +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#else +#include +#include +#include +#include +#include +#include +#include +#include +#endif + #include "netplay.h" #include "general.h" #include "autosave.h" @@ -25,32 +44,17 @@ #include #include + #ifdef _WIN32 -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0501 -#endif -#define WIN32_LEAN_AND_MEAN -#include -#include -#include // Woohoo, Winsock has headers from the STONE AGE! :D #define close(x) closesocket(x) #define CONST_CAST (const char*) #define NONCONST_CAST (char*) #else -#include -#include -#include -#include -#include -#include -#include -#include #define CONST_CAST #define NONCONST_CAST #endif - #define PREV_PTR(x) ((x) == 0 ? handle->buffer_size - 1 : (x) - 1) #define NEXT_PTR(x) ((x + 1) % handle->buffer_size) diff --git a/qb/config.params.sh b/qb/config.params.sh index 4860cce882..36ca395a24 100644 --- a/qb/config.params.sh +++ b/qb/config.params.sh @@ -1,7 +1,7 @@ . qb/qb.params.sh PACKAGE_NAME=ssnes -PACKAGE_VERSION=0.9-rc3 +PACKAGE_VERSION=0.9-rc4 # Adds a command line opt to ./configure --help # $1: Variable (HAVE_ALSA, HAVE_OSS, etc) diff --git a/ssnes.c b/ssnes.c index b304933b9a..0e54d07610 100644 --- a/ssnes.c +++ b/ssnes.c @@ -181,6 +181,33 @@ static void video_frame(const uint16_t *data, unsigned width, unsigned height) if (!driver.video->frame(driver.video_data, data, width, height, (height == 448 || height == 478) ? 1024 : 2048, msg)) g_extern.video_active = false; #endif + + g_extern.frame_cache.data = data; + g_extern.frame_cache.width = width; + g_extern.frame_cache.height = height; +} + +static void video_cached_frame(void) +{ +#ifdef HAVE_FFMPEG + // Cannot allow FFmpeg recording when pushing duped frames. + bool recording = g_extern.recording; + g_extern.recording = false; +#endif + + // Not 100% safe, since the library might have + // freed the memory, but no known implementations do this :D + // It would be really stupid at any rate ... + if (g_extern.frame_cache.data) + { + video_frame(g_extern.frame_cache.data, + g_extern.frame_cache.width, + g_extern.frame_cache.height); + } + +#ifdef HAVE_FFMPEG + g_extern.recording = recording; +#endif } static bool audio_flush(const int16_t *data, unsigned samples) @@ -332,7 +359,7 @@ static int16_t input_state(bool port, unsigned device, unsigned index, unsigned #endif #ifdef _WIN32 -#define PACKAGE_VERSION "0.9-rc3" +#define PACKAGE_VERSION "0.9-rc4" #endif #include "config.features.h" @@ -1267,19 +1294,25 @@ static void check_savestates(void) old_should_loadstate = should_loadstate; } -static void check_fullscreen(void) +static bool check_fullscreen(void) { - static bool was_pressed = false; - bool pressed; // If we go fullscreen we drop all drivers and reinit to be safe. - if ((pressed = driver.input->key_pressed(driver.input_data, SSNES_FULLSCREEN_TOGGLE_KEY)) && !was_pressed) + static bool was_pressed = false; + bool pressed = driver.input->key_pressed(driver.input_data, SSNES_FULLSCREEN_TOGGLE_KEY); + bool toggle = pressed && !was_pressed; + if (toggle) { g_settings.video.fullscreen = !g_settings.video.fullscreen; uninit_drivers(); init_drivers(); + + // Poll input to avoid possibly stale data to corrupt things. + if (driver.input) + driver.input->poll(driver.input_data); } was_pressed = pressed; + return toggle; } static void check_stateslots(void) @@ -1390,7 +1423,7 @@ static void check_rewind(void) g_extern.frame_is_reverse = true; setup_rewind_audio(); - msg_queue_push(g_extern.msg_queue, "Rewinding!", 0, 30); + msg_queue_push(g_extern.msg_queue, "Rewinding!", 0, g_extern.is_paused ? 1 : 30); psnes_unserialize(buf, psnes_serialize_size()); if (g_extern.bsv_movie) @@ -1455,6 +1488,9 @@ static void check_pause(void) static bool old_state = false; bool new_state = driver.input->key_pressed(driver.input_data, SSNES_PAUSE_TOGGLE); + // FRAMEADVANCE will set us into pause mode. + new_state |= !g_extern.is_paused && driver.input->key_pressed(driver.input_data, SSNES_FRAMEADVANCE); + static bool old_focus = true; bool focus = true; @@ -1513,9 +1549,14 @@ static void check_oneshot(void) { static bool old_state = false; bool new_state = driver.input->key_pressed(driver.input_data, SSNES_FRAMEADVANCE); - - g_extern.is_oneshot = new_state && !old_state; + g_extern.is_oneshot = (new_state && !old_state); old_state = new_state; + + // Rewind buttons works like FRAMEREWIND when paused. We will one-shot in that case. + static bool old_rewind_state = false; + bool new_rewind_state = driver.input->key_pressed(driver.input_data, SSNES_REWIND); + g_extern.is_oneshot |= new_rewind_state && !old_rewind_state; + old_rewind_state = new_rewind_state; } static void check_reset(void) @@ -1630,17 +1671,14 @@ static void do_state_checks(void) { if (!g_extern.netplay) { - check_reset(); -#ifdef HAVE_XML - check_cheats(); -#endif check_pause(); check_oneshot(); + + if (check_fullscreen() && g_extern.is_paused) + video_cached_frame(); + if (g_extern.is_paused && !g_extern.is_oneshot) - { - check_fullscreen(); return; - } set_fast_forward_button( driver.input->key_pressed(driver.input_data, SSNES_FAST_FORWARD_KEY), @@ -1651,21 +1689,23 @@ static void do_state_checks(void) check_stateslots(); check_savestates(); } - check_rewind(); + check_rewind(); if (!g_extern.bsv_movie_playback) check_movie_record(); - + #ifdef HAVE_XML check_shader_dir(); + check_cheats(); #endif #ifdef HAVE_DYLIB check_dsp_config(); #endif + check_reset(); } - - check_fullscreen(); + else + check_fullscreen(); #ifdef HAVE_DYLIB // DSP plugin doesn't use variable input rate.