comparison genesis.c @ 1427:4e5797b3935a

WIP - New savestate format
author Michael Pavone <pavone@retrodev.com>
date Sun, 06 Aug 2017 00:06:36 -0700
parents 975b5b7eaa77
children 2540c05520f2
comparison
equal deleted inserted replaced
1426:957325c990d5 1427:4e5797b3935a
30 #define LINES_NTSC 262 30 #define LINES_NTSC 262
31 #define LINES_PAL 312 31 #define LINES_PAL 312
32 32
33 #define MAX_SOUND_CYCLES 100000 33 #define MAX_SOUND_CYCLES 100000
34 34
35 void genesis_serialize(genesis_context *gen, serialize_buffer *buf, uint32_t m68k_pc)
36 {
37 start_section(buf, SECTION_68000);
38 m68k_serialize(gen->m68k, m68k_pc, buf);
39 end_section(buf);
40
41 start_section(buf, SECTION_Z80);
42 z80_serialize(gen->z80, buf);
43 end_section(buf);
44
45 start_section(buf, SECTION_VDP);
46 vdp_serialize(gen->vdp, buf);
47 end_section(buf);
48
49 start_section(buf, SECTION_YM2612);
50 ym_serialize(gen->ym, buf);
51 end_section(buf);
52
53 start_section(buf, SECTION_PSG);
54 psg_serialize(gen->psg, buf);
55 end_section(buf);
56
57 //TODO: bus arbiter state
58
59 start_section(buf, SECTION_SEGA_IO_1);
60 io_serialize(gen->io.ports, buf);
61 end_section(buf);
62
63 start_section(buf, SECTION_SEGA_IO_2);
64 io_serialize(gen->io.ports + 1, buf);
65 end_section(buf);
66
67 start_section(buf, SECTION_SEGA_IO_EXT);
68 io_serialize(gen->io.ports + 2, buf);
69 end_section(buf);
70
71 start_section(buf, SECTION_MAIN_RAM);
72 save_int8(buf, RAM_WORDS * 2 / 1024);
73 save_buffer16(buf, gen->work_ram, RAM_WORDS);
74 end_section(buf);
75
76 start_section(buf, SECTION_SOUND_RAM);
77 save_int8(buf, Z80_RAM_BYTES / 1024);
78 save_buffer8(buf, gen->zram, Z80_RAM_BYTES);
79 end_section(buf);
80
81 //TODO: mapper state
82 }
83
84 static void ram_deserialize(deserialize_buffer *buf, void *vgen)
85 {
86 genesis_context *gen = vgen;
87 uint32_t ram_size = load_int8(buf) * 1024 / 2;
88 if (ram_size > RAM_WORDS) {
89 fatal_error("State has a RAM size of %d bytes", ram_size * 2);
90 }
91 load_buffer16(buf, gen->work_ram, ram_size);
92 }
93
94 static void zram_deserialize(deserialize_buffer *buf, void *vgen)
95 {
96 genesis_context *gen = vgen;
97 uint32_t ram_size = load_int8(buf) * 1024;
98 if (ram_size > Z80_RAM_BYTES) {
99 fatal_error("State has a Z80 RAM size of %d bytes", ram_size);
100 }
101 load_buffer8(buf, gen->zram, ram_size);
102 }
103
104 void genesis_deserialize(deserialize_buffer *buf, genesis_context *gen)
105 {
106 register_section_handler(buf, (section_handler){.fun = m68k_deserialize, .data = gen->m68k}, SECTION_68000);
107 register_section_handler(buf, (section_handler){.fun = z80_deserialize, .data = gen->z80}, SECTION_Z80);
108 register_section_handler(buf, (section_handler){.fun = vdp_deserialize, .data = gen->vdp}, SECTION_VDP);
109 register_section_handler(buf, (section_handler){.fun = ym_deserialize, .data = gen->ym}, SECTION_YM2612);
110 register_section_handler(buf, (section_handler){.fun = psg_deserialize, .data = gen->psg}, SECTION_PSG);
111 //TODO: bus arbiter
112 //HACK
113 gen->z80->reset = 0;
114 gen->z80->busreq = 0;
115 register_section_handler(buf, (section_handler){.fun = io_deserialize, .data = gen->io.ports}, SECTION_SEGA_IO_1);
116 register_section_handler(buf, (section_handler){.fun = io_deserialize, .data = gen->io.ports + 1}, SECTION_SEGA_IO_2);
117 register_section_handler(buf, (section_handler){.fun = io_deserialize, .data = gen->io.ports + 2}, SECTION_SEGA_IO_EXT);
118 register_section_handler(buf, (section_handler){.fun = ram_deserialize, .data = gen}, SECTION_MAIN_RAM);
119 register_section_handler(buf, (section_handler){.fun = zram_deserialize, .data = gen}, SECTION_SOUND_RAM);
120 //TODO: mapper state
121 while (buf->cur_pos < buf->size)
122 {
123 load_section(buf);
124 }
125 }
126
35 uint16_t read_dma_value(uint32_t address) 127 uint16_t read_dma_value(uint32_t address)
36 { 128 {
37 genesis_context *genesis = (genesis_context *)current_system; 129 genesis_context *genesis = (genesis_context *)current_system;
38 //TODO: Figure out what happens when you try to DMA from weird adresses like IO or banked Z80 area 130 //TODO: Figure out what happens when you try to DMA from weird adresses like IO or banked Z80 area
39 if ((address >= 0xA00000 && address < 0xB00000) || (address >= 0xC00000 && address <= 0xE00000)) { 131 if ((address >= 0xA00000 && address < 0xB00000) || (address >= 0xC00000 && address <= 0xE00000)) {
250 char slotname[] = "slot_0.gst"; 342 char slotname[] = "slot_0.gst";
251 slotname[5] = '0' + slot; 343 slotname[5] = '0' + slot;
252 char const *parts[] = {gen->header.save_dir, PATH_SEP, slotname}; 344 char const *parts[] = {gen->header.save_dir, PATH_SEP, slotname};
253 save_path = alloc_concat_m(3, parts); 345 save_path = alloc_concat_m(3, parts);
254 } 346 }
255 save_gst(gen, save_path, address); 347 serialize_buffer state;
348 init_serialize(&state);
349 genesis_serialize(gen, &state, address);;
350 FILE *statefile = fopen(save_path, "wb");
351 fwrite(state.data, 1, state.size, statefile);
352 fclose(statefile);
353 free(state.data);
354 //save_gst(gen, save_path, address);
256 printf("Saved state to %s\n", save_path); 355 printf("Saved state to %s\n", save_path);
257 if (slot != QUICK_SAVE_SLOT) { 356 if (slot != QUICK_SAVE_SLOT) {
258 free(save_path); 357 free(save_path);
259 } 358 }
260 } else if(gen->header.save_state) { 359 } else if(gen->header.save_state) {
904 { 1003 {
905 genesis_context *gen = (genesis_context *)system; 1004 genesis_context *gen = (genesis_context *)system;
906 set_keybindings(&gen->io); 1005 set_keybindings(&gen->io);
907 render_set_video_standard((gen->version_reg & HZ50) ? VID_PAL : VID_NTSC); 1006 render_set_video_standard((gen->version_reg & HZ50) ? VID_PAL : VID_NTSC);
908 if (statefile) { 1007 if (statefile) {
1008 //first try loading as a GST format savestate
909 uint32_t pc = load_gst(gen, statefile); 1009 uint32_t pc = load_gst(gen, statefile);
910 if (!pc) { 1010 if (!pc) {
911 fatal_error("Failed to load save state %s\n", statefile); 1011 //switch to native format if that fails
1012 FILE *f = fopen(statefile, "rb");
1013 if (!f) {
1014 goto state_error;
1015 }
1016 long statesize = file_size(f);
1017 deserialize_buffer state;
1018 void *statedata = malloc(statesize);
1019 if (statesize != fread(statedata, 1, statesize, f)) {
1020 goto state_error;
1021 }
1022 fclose(f);
1023 init_deserialize(&state, statedata, statesize);
1024 genesis_deserialize(&state, gen);
1025 free(statedata);
1026 //HACK
1027 pc = gen->m68k->last_prefetch_address;
912 } 1028 }
913 printf("Loaded %s\n", statefile); 1029 printf("Loaded %s\n", statefile);
914 if (gen->header.enter_debugger) { 1030 if (gen->header.enter_debugger) {
915 gen->header.enter_debugger = 0; 1031 gen->header.enter_debugger = 0;
916 insert_breakpoint(gen->m68k, pc, gen->header.debugger_type == DEBUGGER_NATIVE ? debugger : gdb_debug_enter); 1032 insert_breakpoint(gen->m68k, pc, gen->header.debugger_type == DEBUGGER_NATIVE ? debugger : gdb_debug_enter);
924 insert_breakpoint(gen->m68k, address, gen->header.debugger_type == DEBUGGER_NATIVE ? debugger : gdb_debug_enter); 1040 insert_breakpoint(gen->m68k, address, gen->header.debugger_type == DEBUGGER_NATIVE ? debugger : gdb_debug_enter);
925 } 1041 }
926 m68k_reset(gen->m68k); 1042 m68k_reset(gen->m68k);
927 } 1043 }
928 handle_reset_requests(gen); 1044 handle_reset_requests(gen);
1045 return;
1046 state_error:
1047 fatal_error("Failed to load save state %s\n", statefile);
929 } 1048 }
930 1049
931 static void resume_genesis(system_header *system) 1050 static void resume_genesis(system_header *system)
932 { 1051 {
933 genesis_context *gen = (genesis_context *)system; 1052 genesis_context *gen = (genesis_context *)system;