changeset 957:1618d3676a35

Save state menu WIP
author Michael Pavone <pavone@retrodev.com>
date Fri, 15 Apr 2016 23:57:50 -0700
parents f5550cdffe49
children 83532f944e3b
files blastem.c blastem.h menu.c menu.s68 util.c util.h
diffstat 6 files changed, 120 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/blastem.c	Fri Apr 15 20:39:26 2016 -0700
+++ b/blastem.c	Fri Apr 15 23:57:50 2016 -0700
@@ -1220,6 +1220,8 @@
 			}
 			//allocate new genesis context
 			game_context = alloc_init_genesis(&info, fps, ym_log ? YM_OPT_WAVE_LOG : 0);
+			menu_context->next_context = game_context;
+			game_context->next_context = menu_context;
 			setup_saves(menu_context->next_rom, &info, game_context);
 			free(menu_context->next_rom);
 			menu_context->next_rom = NULL;
--- a/blastem.h	Fri Apr 15 20:39:26 2016 -0700
+++ b/blastem.h	Fri Apr 15 23:57:50 2016 -0700
@@ -17,36 +17,39 @@
 #include "romdb.h"
 #include "arena.h"
 
-typedef struct {
-	m68k_context   *m68k;
-	z80_context    *z80;
-	vdp_context    *vdp;
-	ym2612_context *ym;
-	psg_context    *psg;
-	uint16_t       *cart;
-	uint16_t       *work_ram;
-	uint8_t        *zram;
-	void           *extra;
-	arena          *arena;
-	char           *next_rom;
-	char           *save_dir;
-	uint8_t        *save_storage;
-	eeprom_map     *eeprom_map;
-	uint32_t       num_eeprom;
-	uint32_t       save_size;
-	uint32_t       save_ram_mask;
-	uint32_t       master_clock; //Current master clock value
-	uint32_t       normal_clock; //Normal master clock (used to restore master clock after turbo mode)
-	uint32_t       frame_end;
-	uint32_t       max_cycles;
-	uint8_t        bank_regs[8];
-	uint16_t       mapper_start_index;
-	uint8_t        save_type;
-	io_port        ports[3];
-	uint8_t        bus_busy;
-	uint8_t        should_exit;
-	eeprom_state   eeprom;
-} genesis_context;
+typedef struct genesis_context genesis_context;
+
+struct genesis_context {
+	m68k_context    *m68k;
+	z80_context     *z80;
+	vdp_context     *vdp;
+	ym2612_context  *ym;
+	psg_context     *psg;
+	genesis_context *next_context;
+	uint16_t        *cart;
+	uint16_t        *work_ram;
+	uint8_t         *zram;
+	void            *extra;
+	arena           *arena;
+	char            *next_rom;
+	char            *save_dir;
+	uint8_t         *save_storage;
+	eeprom_map      *eeprom_map;
+	uint32_t        num_eeprom;
+	uint32_t        save_size;
+	uint32_t        save_ram_mask;
+	uint32_t        master_clock; //Current master clock value
+	uint32_t        normal_clock; //Normal master clock (used to restore master clock after turbo mode)
+	uint32_t        frame_end;
+	uint32_t        max_cycles;
+	uint8_t         bank_regs[8];
+	uint16_t        mapper_start_index;
+	uint8_t         save_type;
+	io_port         ports[3];
+	uint8_t         bus_busy;
+	uint8_t         should_exit;
+	eeprom_state    eeprom;
+};
 
 extern genesis_context * genesis;
 extern int headless;
--- a/menu.c	Fri Apr 15 20:39:26 2016 -0700
+++ b/menu.c	Fri Apr 15 23:57:50 2016 -0700
@@ -52,6 +52,25 @@
 	buf[maxchars-1] = 0;
 }
 
+void copy_to_guest(m68k_context *m68k, uint32_t guest_addr, char *src, size_t tocopy)
+{
+	char *dst = NULL;
+	for (char *cur = src; cur < src+tocopy; cur+=2, guest_addr+=2, dst+=2)
+	{
+		if (!dst || !(guest_addr & 0xFFFF)) {
+			//we may have walked off the end of a memory block, get a fresh native pointer
+			dst = get_native_pointer(guest_addr, (void **)m68k->mem_pointers, &m68k->options->gen);
+			if (!dst) {
+				break;
+			}
+		}
+		src[1] = *cur;
+		*src = cur[1];
+	}
+}
+
+#define SAVE_INFO_BUFFER_SIZE (11*40)
+
 #ifdef __ANDROID__
 #include <SDL.h>
 #include <jni.h>
@@ -190,6 +209,7 @@
 			gen->next_rom = alloc_concat_m(3, pieces);
 			m68k->should_return = 1;
 			break;
+		}
 		case 3: {
 			switch (dst)
 			{
@@ -204,6 +224,55 @@
 			
 			break;
 		}
+		case 4: {
+			char *buffer = malloc(SAVE_INFO_BUFFER_SIZE);
+			char *cur = buffer;
+			if (gen->next_context && gen->next_context->save_dir) {
+				char *end = buffer + SAVE_INFO_BUFFER_SIZE;
+				char slotfile[] = "slot_0.gst";
+				char const * parts[3] = {gen->next_context->save_dir, "/", slotfile};
+				struct tm ltime;
+				char *fname;
+				time_t modtime;
+				for (int i = 0; i < 10 && cur < end; i++)
+				{
+					slotfile[5] = i + '0';
+					fname = alloc_concat_m(3, parts);
+					modtime = get_modification_time(fname);
+					free(fname);
+					if (modtime) {
+						cur += snprintf(cur, end-cur, "Slot %d - ", i);
+						cur += strftime(cur, end-cur, "%c", localtime_r(&modtime, &ltime));
+						
+					} else {
+						cur += snprintf(cur, end-cur, "Slot %d - EMPTY", i);
+					}
+					//advance past the null terminator for this entry
+					cur++;
+				}
+				if (cur < end) {
+					parts[2] = "quicksave.gst";
+					fname = alloc_concat_m(3, parts);
+					modtime = get_modification_time(fname);
+					free(fname);
+					if (modtime) {
+						cur += strftime(cur, end-cur, "Quick   - %c", localtime_r(&modtime, &ltime));
+					} else if ((end-cur) > strlen("Quick   - EMPTY")){
+						cur += strlen(strcpy(cur, "Quick   - EMPTY"));
+					}
+					//advance past the null terminator for this entry
+					cur++;
+					if (cur < end) {
+						//terminate the list
+						*cur = 0;
+					}
+				}
+			} else {
+				*(cur++) = 0;
+				*(cur++) = 0;
+			}
+			copy_to_guest(m68k, dst, buffer, cur-buffer);
+			break;
 		}
 		default:
 			fprintf(stderr, "WARNING: write to undefined menu port %X\n", address);
--- a/menu.s68	Fri Apr 15 20:39:26 2016 -0700
+++ b/menu.s68	Fri Apr 15 23:57:50 2016 -0700
@@ -935,10 +935,13 @@
 	
 save_state:
 	;TODO: Implement me
-	bra save_state
+	move.l #0, menu_port+16
+.forever
+	bra .forever
 	
 load_state:
 	;TODO: Implement me
+	move.l #0, menu_port+16
 	bra save_state
 	
 about_text:
--- a/util.c	Fri Apr 15 20:39:26 2016 -0700
+++ b/util.c	Fri Apr 15 23:57:50 2016 -0700
@@ -366,6 +366,15 @@
 	free(list);
 }
 
+time_t get_modification_time(char *path)
+{
+	struct stat st;
+	if (stat(path, &st)) {
+		return 0;
+	}
+	return st.st_mtim.tv_sec;
+}
+
 int ensure_dir_exists(char *path)
 {
 	struct stat st;
--- a/util.h	Fri Apr 15 20:39:26 2016 -0700
+++ b/util.h	Fri Apr 15 23:57:50 2016 -0700
@@ -2,6 +2,7 @@
 #define UTIL_H_
 
 #include <stdio.h>
+#include <time.h>
 
 typedef struct {
 	char    *name;
@@ -40,6 +41,8 @@
 dir_entry *get_dir_list(char *path, size_t *numret);
 //Frees a dir list returned by get_dir_list
 void free_dir_list(dir_entry *list, size_t numentries);
+//Gets the modification time of a file
+time_t get_modification_time(char *path);
 //Recusrively creates a directory if it does not exist
 int ensure_dir_exists(char *path);
 //Returns the contents of a symlink in a newly allocated string