diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 77296e33..7172705c 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -165,7 +165,8 @@ snes9x_gtk_SOURCES += \ ../logger.cpp \ ../snapshot.cpp \ ../screenshot.cpp \ - ../movie.cpp + ../movie.cpp \ + ../statemanager.cpp # ASMCPU Doesn't exist anymore. snes9x_gtk_SOURCES += \ diff --git a/gtk/src/gtk_config.cpp b/gtk/src/gtk_config.cpp index c0f3bde5..5b8e0298 100644 --- a/gtk/src/gtk_config.cpp +++ b/gtk/src/gtk_config.cpp @@ -174,6 +174,9 @@ Snes9xConfig::load_defaults (void) netplay_last_host [0] = '\0'; netplay_last_port = 6096; modal_dialogs = 1; + + rewindGranularity = 5; + rewindBufferSize = 150; #ifdef USE_OPENGL sync_to_vblank = 1; diff --git a/gtk/src/gtk_config.h b/gtk/src/gtk_config.h index 9e8ec7c0..04363c5c 100644 --- a/gtk/src/gtk_config.h +++ b/gtk/src/gtk_config.h @@ -132,6 +132,9 @@ class Snes9xConfig int pointer_is_visible; struct timeval pointer_timestamp; + + unsigned int rewindGranularity; + unsigned int rewindBufferSize; #ifdef USE_XRANDR XRRScreenConfiguration *xrr_config; diff --git a/gtk/src/gtk_control.cpp b/gtk/src/gtk_control.cpp index 906a2846..1601cad0 100644 --- a/gtk/src/gtk_control.cpp +++ b/gtk/src/gtk_control.cpp @@ -89,6 +89,7 @@ const BindingLink b_links[] = { "b_load_movie", "LoadMovie" }, { "b_seek_to_frame", "GTK_seek_to_frame" }, { "b_swap_controllers", "GTK_swap_controllers" }, + { "b_rewind", "GTK_rewind" }, { NULL, NULL } }; @@ -193,6 +194,8 @@ S9xHandlePortCommand (s9xcommand_t cmd, int16 data1, int16 data2) { if (cmd.port[0] == PORT_QUIT) quit_binding_down = TRUE; + else if (cmd.port[0] == PORT_REWIND) + top_level->user_rewind = TRUE; } if (data1 == FALSE) /* Release */ @@ -225,6 +228,11 @@ S9xHandlePortCommand (s9xcommand_t cmd, int16 data1, int16 data2) top_level->unpause_from_user (); } + else if (cmd.port[0] == PORT_REWIND) + { + top_level->user_rewind = FALSE; + } + else if (cmd.port[0] == PORT_SEEK_TO_FRAME) { top_level->movie_seek_dialog (); @@ -307,6 +315,11 @@ S9xGetPortCommandT (const char *name) cmd.port[0] = PORT_SWAP_CONTROLLERS; } + else if (!strcasecmp (name, "GTK_rewind")) + { + cmd.port[0] = PORT_REWIND; + } + else { cmd = S9xGetCommandT (name); diff --git a/gtk/src/gtk_control.h b/gtk/src/gtk_control.h index 3afaa9e3..5ed09ac2 100644 --- a/gtk/src/gtk_control.h +++ b/gtk/src/gtk_control.h @@ -26,6 +26,7 @@ #define PORT_SEEK_TO_FRAME 5 #define PORT_QUIT 6 #define PORT_SWAP_CONTROLLERS 7 +#define PORT_REWIND 8 typedef struct BindingLink { @@ -37,7 +38,7 @@ typedef struct BindingLink extern const BindingLink b_links[]; extern const int b_breaks[]; #define NUM_JOYPAD_LINKS 24 -#define NUM_EMU_LINKS 52 +#define NUM_EMU_LINKS 53 typedef struct JoypadBinding { diff --git a/gtk/src/gtk_s9x.cpp b/gtk/src/gtk_s9x.cpp index 03e1c812..01595edf 100644 --- a/gtk/src/gtk_s9x.cpp +++ b/gtk/src/gtk_s9x.cpp @@ -9,6 +9,8 @@ #include "gtk_sound.h" #include "gtk_display.h" +#include "statemanager.h" + #ifdef NETPLAY_SUPPORT #include "gtk_netplay.h" #endif @@ -23,6 +25,7 @@ static gboolean S9xScreenSaverCheckFunc (gpointer data); Snes9xWindow *top_level; Snes9xConfig *gui_config; +StateManager stateMan; static struct timeval next_frame_time = { 0, 0 }; static struct timeval now; static int needs_fullscreening = FALSE; @@ -217,6 +220,12 @@ S9xOpenROM (const char *rom_filename) } CPU.Flags = flags; + + if (gui_config->rewindBufferSize) + { + printf("Setting buffer size to %u\n", gui_config->rewindBufferSize * 1024 * 1024); + stateMan.init(gui_config->rewindBufferSize * 1024 * 1024); + } S9xROMLoaded (); @@ -356,6 +365,12 @@ S9xIdleFunc (gpointer data) if (!S9xNetplayPush ()) { #endif + + if(top_level->user_rewind) + top_level->user_rewind = stateMan.pop(); + else if(IPPU.TotalEmulatedFrames % gui_config->rewindGranularity == 0) + stateMan.push(); + S9xMainLoop (); S9xMixSound (); diff --git a/gtk/src/gtk_s9xwindow.cpp b/gtk/src/gtk_s9xwindow.cpp index 7c275932..a6ade21e 100644 --- a/gtk/src/gtk_s9xwindow.cpp +++ b/gtk/src/gtk_s9xwindow.cpp @@ -589,6 +589,7 @@ Snes9xWindow::Snes9xWindow (Snes9xConfig *config) : }; user_pause = 0; + user_rewind = 0; sys_pause = 0; last_width = -1; last_height = -1; diff --git a/gtk/src/gtk_s9xwindow.h b/gtk/src/gtk_s9xwindow.h index d5350480..350e2abd 100644 --- a/gtk/src/gtk_s9xwindow.h +++ b/gtk/src/gtk_s9xwindow.h @@ -69,6 +69,7 @@ class Snes9xWindow : public GtkBuilderWindow Snes9xConfig *config; int user_pause, sys_pause; + int user_rewind; int last_width, last_height; int mouse_region_x, mouse_region_y; int mouse_region_width, mouse_region_height; diff --git a/gtk/src/snes9x.ui b/gtk/src/snes9x.ui index 051c2cd8..509128f4 100644 --- a/gtk/src/snes9x.ui +++ b/gtk/src/snes9x.ui @@ -8028,7 +8028,7 @@ False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 10 - 6 + 7 2 10 5 @@ -8224,6 +8224,37 @@ GTK_FILL + + + True + False + 0 + Rewind + + + 6 + 7 + GTK_FILL + + + + + + True + True + False + False + True + True + + + 1 + 2 + 6 + 7 + GTK_FILL + + 4