# HG changeset patch # User Michael Pavone # Date 1460789870 25200 # Node ID 1618d3676a3500a9f5993d546186bcbe474be5d8 # Parent f5550cdffe4925bb1fedd77ee2a25c9ae47520fa Save state menu WIP diff -r f5550cdffe49 -r 1618d3676a35 blastem.c --- 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; diff -r f5550cdffe49 -r 1618d3676a35 blastem.h --- 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; diff -r f5550cdffe49 -r 1618d3676a35 menu.c --- 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 #include @@ -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, <ime)); + + } 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, <ime)); + } 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 -r f5550cdffe49 -r 1618d3676a35 menu.s68 --- 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: diff -r f5550cdffe49 -r 1618d3676a35 util.c --- 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; diff -r f5550cdffe49 -r 1618d3676a35 util.h --- 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 +#include 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