summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--blastem.c2
-rw-r--r--blastem.h63
-rw-r--r--menu.c69
-rw-r--r--menu.s685
-rw-r--r--util.c9
-rw-r--r--util.h3
6 files changed, 120 insertions, 31 deletions
diff --git a/blastem.c b/blastem.c
index d772ae2..4bc841d 100644
--- a/blastem.c
+++ b/blastem.c
@@ -1220,6 +1220,8 @@ int main(int argc, char ** argv)
}
//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;
diff --git a/blastem.h b/blastem.h
index 738de7f..eaf56cc 100644
--- a/blastem.h
+++ b/blastem.h
@@ -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;
diff --git a/menu.c b/menu.c
index 6dbbd12..e24d986 100644
--- a/menu.c
+++ b/menu.c
@@ -52,6 +52,25 @@ void copy_string_from_guest(m68k_context *m68k, uint32_t guest_addr, char *buf,
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 @@ void * menu_write_w(uint32_t address, void * context, uint16_t value)
gen->next_rom = alloc_concat_m(3, pieces);
m68k->should_return = 1;
break;
+ }
case 3: {
switch (dst)
{
@@ -204,6 +224,55 @@ void * menu_write_w(uint32_t address, void * context, uint16_t value)
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);
diff --git a/menu.s68 b/menu.s68
index 92a4eb5..602da07 100644
--- a/menu.s68
+++ b/menu.s68
@@ -935,10 +935,13 @@ resume:
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:
diff --git a/util.c b/util.c
index 9094223..1e3cfe8 100644
--- a/util.c
+++ b/util.c
@@ -366,6 +366,15 @@ void free_dir_list(dir_entry *list, size_t numentries)
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;
diff --git a/util.h b/util.h
index b9d271e..7fd26b6 100644
--- a/util.h
+++ b/util.h
@@ -2,6 +2,7 @@
#define UTIL_H_
#include <stdio.h>
+#include <time.h>
typedef struct {
char *name;
@@ -40,6 +41,8 @@ char *read_bundled_file(char *name, long *sizeret);
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