Mercurial > repos > blastem
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; |