diff options
author | Michael Pavone <pavone@retrodev.com> | 2016-04-15 23:57:50 -0700 |
---|---|---|
committer | Michael Pavone <pavone@retrodev.com> | 2016-04-15 23:57:50 -0700 |
commit | f76ba81c317fdca5f549bcb044d62861609fe6d1 (patch) | |
tree | 0dc9bed8def723181a9655c27886fcc27dccb5d3 | |
parent | e913f115a678bf2eb0da3a0c6b2ab45830f79028 (diff) |
Save state menu WIP
-rw-r--r-- | blastem.c | 2 | ||||
-rw-r--r-- | blastem.h | 63 | ||||
-rw-r--r-- | menu.c | 69 | ||||
-rw-r--r-- | menu.s68 | 5 | ||||
-rw-r--r-- | util.c | 9 | ||||
-rw-r--r-- | util.h | 3 |
6 files changed, 120 insertions, 31 deletions
@@ -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; @@ -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; @@ -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, <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); @@ -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: @@ -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; @@ -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 |