diff --git a/desmume/src/gtk-glade/Makefile.am b/desmume/src/gtk-glade/Makefile.am
index c50a64314..f86952eda 100644
--- a/desmume/src/gtk-glade/Makefile.am
+++ b/desmume/src/gtk-glade/Makefile.am
@@ -4,7 +4,7 @@ desmume_glade_SOURCES = \
globals.h keyval_names.c main.c printscreen.c \
dTools/callbacks_1_ioregs.c dTools/callbacks_2_memview.c \
dTools/callbacks_3_palview.c dTools/callbacks_dtools.h \
- ../sndsdl.h ../sndsdl.c ../ctrlssdl.h ../ctrlssdl.c
+ ../sndsdl.h ../sndsdl.c ../ctrlssdl.h ../ctrlssdl.c
desmume_glade_LDADD = ../libdesmume.a $(SDL_LIBS) $(LIBGLADE_LIBS)
desmume_glade_CFLAGS = $(SDL_CFLAGS) $(LIBGLADE_CFLAGS)
desmume_glade_LDFLAGS = -rdynamic
diff --git a/desmume/src/gtk-glade/callbacks.c b/desmume/src/gtk-glade/callbacks.c
index 7b98e80a3..84e768513 100755
--- a/desmume/src/gtk-glade/callbacks.c
+++ b/desmume/src/gtk-glade/callbacks.c
@@ -28,7 +28,14 @@ gboolean ScreenGap=FALSE;
/* inline & protos */
+inline void SET_SENSITIVE(gchar *w, gboolean b) {
+ gtk_widget_set_sensitive(
+ glade_xml_get_widget(xml, w), TRUE);
+}
+
void enable_rom_features() {
+ scan_savestates();
+ update_savestates_menu();
SET_SENSITIVE("menu_exec", TRUE);
SET_SENSITIVE("menu_pause", TRUE);
SET_SENSITIVE("menu_reset", TRUE);
@@ -55,12 +62,6 @@ void MAINWINDOW_RESIZE() {
gtk_window_resize ((GtkWindow*)pWindow,1,1);
}
-void inline SET_SENSITIVE(gchar *w, gboolean b) {
- gtk_widget_set_sensitive(
- glade_xml_get_widget(xml, w), TRUE);
-}
-
-
/* MENU FILE ***** ***** ***** ***** */
void inline ADD_FILTER(GtkWidget * filech, const char * pattern, const char * name) {
GtkFileFilter *pFilter;
@@ -128,7 +129,6 @@ void on_menu_quit_activate (GtkMenuItem *menuitem, gpointer user_data) { gtk
/* MENU SAVES ***** ***** ***** ***** */
-
void on_loadstate1_activate (GtkMenuItem *m, gpointer d) { loadstate_slot(1); }
void on_loadstate2_activate (GtkMenuItem *m, gpointer d) { loadstate_slot(2); }
void on_loadstate3_activate (GtkMenuItem *m, gpointer d) { loadstate_slot(3); }
@@ -140,16 +140,16 @@ void on_loadstate8_activate (GtkMenuItem *m, gpointer d) { loadstate_slot(8); }
void on_loadstate9_activate (GtkMenuItem *m, gpointer d) { loadstate_slot(9); }
void on_loadstate10_activate(GtkMenuItem *m, gpointer d) { loadstate_slot(10); }
-void on_savestate1_activate (GtkMenuItem *m, gpointer d) { savestate_slot(1); }
-void on_savestate2_activate (GtkMenuItem *m, gpointer d) { savestate_slot(2); }
-void on_savestate3_activate (GtkMenuItem *m, gpointer d) { savestate_slot(3); }
-void on_savestate4_activate (GtkMenuItem *m, gpointer d) { savestate_slot(4); }
-void on_savestate5_activate (GtkMenuItem *m, gpointer d) { savestate_slot(5); }
-void on_savestate6_activate (GtkMenuItem *m, gpointer d) { savestate_slot(6); }
-void on_savestate7_activate (GtkMenuItem *m, gpointer d) { savestate_slot(7); }
-void on_savestate8_activate (GtkMenuItem *m, gpointer d) { savestate_slot(8); }
-void on_savestate9_activate (GtkMenuItem *m, gpointer d) { savestate_slot(9); }
-void on_savestate10_activate(GtkMenuItem *m, gpointer d) { savestate_slot(10); }
+void on_savestate1_activate (GtkMenuItem *m, gpointer d) { update_savestate(1); }
+void on_savestate2_activate (GtkMenuItem *m, gpointer d) { update_savestate(2); }
+void on_savestate3_activate (GtkMenuItem *m, gpointer d) { update_savestate(3); }
+void on_savestate4_activate (GtkMenuItem *m, gpointer d) { update_savestate(4); }
+void on_savestate5_activate (GtkMenuItem *m, gpointer d) { update_savestate(5); }
+void on_savestate6_activate (GtkMenuItem *m, gpointer d) { update_savestate(6); }
+void on_savestate7_activate (GtkMenuItem *m, gpointer d) { update_savestate(7); }
+void on_savestate8_activate (GtkMenuItem *m, gpointer d) { update_savestate(8); }
+void on_savestate9_activate (GtkMenuItem *m, gpointer d) { update_savestate(9); }
+void on_savestate10_activate(GtkMenuItem *m, gpointer d) { update_savestate(10); }
/* MENU EMULATION ***** ***** ***** ***** */
diff --git a/desmume/src/gtk-glade/desmume.c b/desmume/src/gtk-glade/desmume.c
index 2deef6fe7..fef44c4fd 100755
--- a/desmume/src/gtk-glade/desmume.c
+++ b/desmume/src/gtk-glade/desmume.c
@@ -50,8 +50,10 @@ void desmume_free()
int desmume_open(const char *filename)
{
- int i = NDS_LoadROM(filename, MC_TYPE_AUTODETECT, 1);
- return i;
+ int i;
+ clear_savestates();
+ i = NDS_LoadROM(filename, MC_TYPE_AUTODETECT, 1);
+ return i;
}
void desmume_pause()
@@ -61,12 +63,10 @@ void desmume_pause()
void desmume_resume()
{
+ execute = TRUE;
- execute = TRUE;
- if(!regMainLoop)
- {
- g_idle_add_full(EMULOOP_PRIO, &EmuLoop, NULL, NULL); regMainLoop = TRUE;
- }
+ if(!regMainLoop)
+ g_idle_add_full(EMULOOP_PRIO, &EmuLoop, NULL, NULL); regMainLoop = TRUE;
}
void desmume_reset()
diff --git a/desmume/src/gtk-glade/glade/DeSmuMe.glade b/desmume/src/gtk-glade/glade/DeSmuMe.glade
index 15afbb31f..453bac9f2 100755
--- a/desmume/src/gtk-glade/glade/DeSmuMe.glade
+++ b/desmume/src/gtk-glade/glade/DeSmuMe.glade
@@ -413,7 +413,7 @@
True
0
True
- False
+ True
@@ -511,7 +511,7 @@
True
9
True
- True
+ False
fs0
@@ -535,7 +535,7 @@
True
1x
True
- False
+ True
@@ -556,7 +556,7 @@
True
3x
True
- True
+ False
size1x
diff --git a/desmume/src/gtk-glade/globals.h b/desmume/src/gtk-glade/globals.h
index 1df79ccc1..e6b94158d 100755
--- a/desmume/src/gtk-glade/globals.h
+++ b/desmume/src/gtk-glade/globals.h
@@ -45,6 +45,7 @@
#include "../sndsdl.h"
#include "../ctrlssdl.h"
#include "../types.h"
+#include "../saves.h"
#include "desmume.h"
uint Frameskip;
diff --git a/desmume/src/gtk-glade/main.c b/desmume/src/gtk-glade/main.c
index a253a9621..d45b12c1f 100755
--- a/desmume/src/gtk-glade/main.c
+++ b/desmume/src/gtk-glade/main.c
@@ -122,10 +122,71 @@ int Write_ConfigFile()
return 0;
}
+/* ******** Savestate menu items handling ******** */
+void set_menuitem_label(GtkWidget * w, char * text )
+{
+ GtkLabel * child;
+ if ( GTK_BIN(w)->child )
+ {
+ child = GTK_BIN(w)->child;
+ gtk_label_set_text(child, text);
+ }
+}
+void clear_savestate_menu(char * cb_name, u8 num)
+{
+ GtkWidget * w;
+ char cb[40];
+ char text[40];
+ sprintf( cb, "%s%d", cb_name, num);
+ sprintf( text, "State %d (empty)", num);
+ w = glade_xml_get_widget(xml, cb);
+ set_menuitem_label( w, text );
+ gtk_check_menu_item_set_active((GtkCheckMenuItem*)w, FALSE);
+}
+
+void update_savestate_menu(char * cb_name, u8 num)
+{
+ GtkWidget * w;
+ char cb[40];
+
+ sprintf( cb, "%s%d", cb_name, num);
+ w = glade_xml_get_widget(xml, cb);
+ set_menuitem_label( w, savestates[num-1].date );
+ /* FIXME: Setting the menu item active makes DeSmuME go crazy!? */
+/* gtk_check_menu_item_set_active((GtkCheckMenuItem*)w, TRUE); */
+}
+
+void update_savestates_menu()
+{
+ char cb[15];
+ u8 i;
+ GtkWidget * w;
+
+ for( i = 1; i <= NB_STATES; i++ )
+ {
+ if( savestates[i-1].exists == TRUE )
+ {
+ update_savestate_menu("loadstate", i);
+ update_savestate_menu("savestate", i);
+ }
+ else
+ {
+ clear_savestate_menu("loadstate", i);
+ clear_savestate_menu("savestate", i);
+ }
+ }
+}
+
+void update_savestate(u8 num)
+{
+ savestate_slot(num);
+ update_savestate_menu("savestate", num);
+ update_savestate_menu("loadstate", num);
+}
/* ***** ***** MAIN ***** ***** */
diff --git a/desmume/src/saves.c b/desmume/src/saves.c
index d30b85df3..d6f807efe 100644
--- a/desmume/src/saves.c
+++ b/desmume/src/saves.c
@@ -26,6 +26,8 @@
#include "saves.h"
#include "MMU.h"
#include "NDSSystem.h"
+#include
+#include
#define SAVESTATE_VERSION 010
@@ -33,12 +35,58 @@
#define MAX_PATH 256
#endif
+/* Format time and convert to string */
+char * format_time(time_t cal_time)
+{
+ struct tm *time_struct;
+ static char string[30];
+
+ time_struct=localtime(&cal_time);
+ strftime(string, sizeof string, "%Y-%m-%d %H:%M", time_struct);
+
+ return(string);
+}
+
+void clear_savestates()
+{
+ u8 i;
+ for( i = 0; i < NB_STATES; i++ )
+ savestates[i].exists = FALSE;
+}
+
+/* Scan for existing savestates and update struct */
+void scan_savestates()
+{
+ struct stat sbuf;
+ char filename[MAX_PATH];
+ u8 i;
+
+ clear_savestates();
+
+ for( i = 1; i <= NB_STATES; i++ )
+ {
+ strcpy(filename, szRomBaseName);
+ sprintf(filename+strlen(filename), "%d.dst", i);
+ if( stat(filename,&sbuf) == -1 ) continue;
+ savestates[i-1].exists = TRUE;
+ strcpy(savestates[i-1].date, format_time(sbuf.st_mtime));
+ }
+
+ return 1;
+}
+
void savestate_slot(int num)
{
+ struct stat sbuf;
char filename[MAX_PATH];
+
strcpy(filename, szRomBaseName);
sprintf(filename+strlen(filename), "%d.dst", num);
savestate_save(filename);
+
+ savestates[num-1].exists = TRUE;
+ if( stat(filename,&sbuf) == -1 ) return;
+ strcpy(savestates[num-1].date, format_time(sbuf.st_mtime));
}
void loadstate_slot(int num)
diff --git a/desmume/src/saves.h b/desmume/src/saves.h
index d76a41824..9d31300ef 100644
--- a/desmume/src/saves.h
+++ b/desmume/src/saves.h
@@ -26,20 +26,30 @@ extern "C" {
#include "types.h"
- #define SRAM_ADDRESS 0x0A000000
- #define SRAM_SIZE 0x10000
+#define SRAM_ADDRESS 0x0A000000
+#define SRAM_SIZE 0x10000
+#define NB_STATES 10
- u8 sram_read (u32 address);
- void sram_write (u32 address, u8 value);
- int sram_load (const char *file_name);
- int sram_save (const char *file_name);
-
- int savestate_load (const char *file_name);
- int savestate_save (const char *file_name);
+typedef struct
+{
+ BOOL exists;
+ char date[40];
+} savestates_t;
+savestates_t savestates[NB_STATES];
- void savestate_slot(int num);
- void loadstate_slot(int num);
+void clear_savestates();
+void scan_savestates();
+u8 sram_read (u32 address);
+void sram_write (u32 address, u8 value);
+int sram_load (const char *file_name);
+int sram_save (const char *file_name);
+
+int savestate_load (const char *file_name);
+int savestate_save (const char *file_name);
+
+void savestate_slot(int num);
+void loadstate_slot(int num);
#ifdef __cplusplus
}