# HG changeset patch # User Michael Pavone # Date 1460962241 25200 # Node ID 750995b587a076b612fd2a49eed1bfa8f6a6b46e # Parent 0abfecaaf5c8d963a6c2849c488c689238baaf3d Save State menu option is now fully functional. Load state sort of works, but is mostly broken. diff -r 0abfecaaf5c8 -r 750995b587a0 blastem.c --- a/blastem.c Sun Apr 17 20:31:22 2016 -0700 +++ b/blastem.c Sun Apr 17 23:50:41 2016 -0700 @@ -191,7 +191,6 @@ } int break_on_sync = 0; -int save_state = 0; char *save_state_path; //#define DO_DEBUG_PRINT @@ -294,7 +293,7 @@ vdp_int_ack(v_context); context->int_ack = 0; } - if (!address && (break_on_sync || save_state)) { + if (!address && (break_on_sync || gen->save_state)) { context->sync_cycle = context->current_cycle + 1; } adjust_int_cycle(context, v_context); @@ -303,16 +302,29 @@ break_on_sync = 0; debugger(context, address); } - if (save_state && (z_context->pc || (!z_context->reset && !z_context->busreq))) { - save_state = 0; + if (gen->save_state && (z_context->pc || (!z_context->reset && !z_context->busreq))) { + uint8_t slot = gen->save_state - 1; + gen->save_state = 0; //advance Z80 core to the start of an instruction while (!z_context->pc) { sync_z80(z_context, z_context->current_cycle + MCLKS_PER_Z80); } - save_gst(gen, save_state_path, address); - printf("Saved state to %s\n", save_state_path); - } else if(save_state) { + char *save_path; + if (slot == QUICK_SAVE_SLOT) { + save_path = save_state_path; + } else { + char slotname[] = "slot_0.gst"; + slotname[5] = '0' + slot; + char const *parts[] = {gen->save_dir, "/", slotname}; + save_path = alloc_concat_m(3, parts); + } + save_gst(gen, save_path, address); + printf("Saved state to %s\n", save_path); + if (slot != QUICK_SAVE_SLOT) { + free(save_path); + } + } else if(gen->save_state) { context->sync_cycle = context->current_cycle + 1; } } diff -r 0abfecaaf5c8 -r 750995b587a0 blastem.h --- a/blastem.h Sun Apr 17 20:31:22 2016 -0700 +++ b/blastem.h Sun Apr 17 23:50:41 2016 -0700 @@ -48,17 +48,18 @@ io_port ports[3]; uint8_t bus_busy; uint8_t should_exit; + uint8_t save_state; eeprom_state eeprom; }; extern genesis_context * genesis; extern int headless; extern int break_on_sync; -extern int save_state; extern tern_node * config; #define RAM_WORDS 32 * 1024 #define Z80_RAM_BYTES 8 * 1024 +#define QUICK_SAVE_SLOT 10 extern uint16_t *cart; extern uint16_t *ram; diff -r 0abfecaaf5c8 -r 750995b587a0 gst.c --- a/gst.c Sun Apr 17 20:31:22 2016 -0700 +++ b/gst.c Sun Apr 17 23:50:41 2016 -0700 @@ -95,6 +95,7 @@ } fseek(gstfile, GST_68K_RAM, SEEK_SET); for (int i = 0; i < (32*1024);) { + //FIXME: Need to deal with code in RAM that has potentially changed after this if (fread(buffer, 1, sizeof(buffer), gstfile) != sizeof(buffer)) { fputs("Failed to read 68K RAM from savestate\n", stderr); return 0; diff -r 0abfecaaf5c8 -r 750995b587a0 io.c --- a/io.c Sun Apr 17 20:31:22 2016 -0700 +++ b/io.c Sun Apr 17 23:50:41 2016 -0700 @@ -349,7 +349,7 @@ break_on_sync = 1; break; case UI_SAVE_STATE: - save_state = 1; + genesis->save_state = QUICK_SAVE_SLOT+1; break; case UI_NEXT_SPEED: current_speed++; diff -r 0abfecaaf5c8 -r 750995b587a0 menu.c --- a/menu.c Sun Apr 17 20:31:22 2016 -0700 +++ b/menu.c Sun Apr 17 23:50:41 2016 -0700 @@ -7,6 +7,8 @@ #include "menu.h" #include "backend.h" #include "util.h" +#include "gst.h" +#include "m68k_internal.h" //needed for get_native_address_trans, should be eliminated once handling of PC is cleaned up uint16_t menu_read_w(uint32_t address, void * context) @@ -273,6 +275,32 @@ } copy_to_guest(m68k, dst, buffer, cur-buffer); break; + case 5: + //save state + if (gen->next_context) { + gen->next_context->save_state = dst + 1; + } + m68k->should_return = 1; + break; + case 6: + //load state + if (gen->next_context && gen->next_context->save_dir) { + char numslotname[] = "slot_0.gst"; + char *slotname; + if (dst == QUICK_SAVE_SLOT) { + slotname = "quicksave.gst"; + } else { + numslotname[5] = '0' + dst; + slotname = numslotname; + } + char const *parts[] = {gen->next_context->save_dir, "/", slotname}; + char *gstpath = alloc_concat_m(3, parts); + uint32_t pc = load_gst(gen->next_context, gstpath); + free(gstpath); + gen->next_context->m68k->resume_pc = get_native_address_trans(gen->next_context->m68k, pc); + } + m68k->should_return = 1; + break; } default: fprintf(stderr, "WARNING: write to undefined menu port %X\n", address); diff -r 0abfecaaf5c8 -r 750995b587a0 menu.s68 --- a/menu.s68 Sun Apr 17 20:31:22 2016 -0700 +++ b/menu.s68 Sun Apr 17 23:50:41 2016 -0700 @@ -192,6 +192,7 @@ last_mbuttons rs.b 1 num_menu rs.b 1 num_slots rs.b 1 +port_off rs.b 1 int_6: @@ -353,6 +354,8 @@ add.w d0, d0 tst.b num_menu.w bne .select_menu_button + tst.b num_slots.w + bne .select_save_slot lea page_index.w, a2 move.l (0, a2, d0.w), a2 tst.b (-1, a2) @@ -368,6 +371,16 @@ move.l (0, a2, d0.w), a2 addq #6, a7 jmp (a2) +.select_save_slot: + lea menu_port, a3 + moveq #0, d0 + move.b port_off.w, d0 + add.w d0, a3 + move.b selected.w, d0 + move.l d0, (a3) + addq #6, a7 + jmp show_pause_menu + enter_dir: lea menu_port+4, a3 move.l a2, (a3) @@ -977,12 +990,14 @@ rts save_state: + move.b #(5*4), port_off.w bsr show_save_slots .wait stop #$2500 bra .wait load_state: + move.b #(6*4), port_off.w bsr show_save_slots .wait stop #$2500