Mercurial > repos > blastem
comparison genesis.c @ 2039:3b8e29ef1145
Add TMSS state to save states
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 07 Mar 2021 23:13:19 -0800 |
parents | b0b0c31338c3 |
children | 638eb2d25696 3748a2a8a4b7 |
comparison
equal
deleted
inserted
replaced
2038:5b51f03b2227 | 2039:3b8e29ef1145 |
---|---|
101 start_section(buf, SECTION_SOUND_RAM); | 101 start_section(buf, SECTION_SOUND_RAM); |
102 save_int8(buf, Z80_RAM_BYTES / 1024); | 102 save_int8(buf, Z80_RAM_BYTES / 1024); |
103 save_buffer8(buf, gen->zram, Z80_RAM_BYTES); | 103 save_buffer8(buf, gen->zram, Z80_RAM_BYTES); |
104 end_section(buf); | 104 end_section(buf); |
105 | 105 |
106 if (gen->version_reg & 0xF) { | |
107 //only save TMSS info if it's present | |
108 //that will allow a state saved on a model lacking TMSS | |
109 //to be loaded on a model that has it | |
110 start_section(buf, SECTION_TMSS); | |
111 save_int8(buf, gen->tmss); | |
112 save_buffer16(buf, gen->tmss_lock, 2); | |
113 end_section(buf); | |
114 } | |
115 | |
106 cart_serialize(&gen->header, buf); | 116 cart_serialize(&gen->header, buf); |
107 } | 117 } |
108 } | 118 } |
109 | 119 |
110 static uint8_t *serialize(system_header *sys, size_t *size_out) | 120 static uint8_t *serialize(system_header *sys, size_t *size_out) |
170 gen->z80->reset = load_int8(buf); | 180 gen->z80->reset = load_int8(buf); |
171 gen->z80->busreq = load_int8(buf); | 181 gen->z80->busreq = load_int8(buf); |
172 gen->z80_bank_reg = load_int16(buf) & 0x1FF; | 182 gen->z80_bank_reg = load_int16(buf) & 0x1FF; |
173 } | 183 } |
174 | 184 |
185 static void tmss_deserialize(deserialize_buffer *buf, void *vgen) | |
186 { | |
187 genesis_context *gen = vgen; | |
188 gen->tmss = load_int8(buf); | |
189 load_buffer16(buf, gen->tmss_lock, 2); | |
190 } | |
191 | |
175 static void adjust_int_cycle(m68k_context * context, vdp_context * v_context); | 192 static void adjust_int_cycle(m68k_context * context, vdp_context * v_context); |
193 static void check_tmss_lock(genesis_context *gen); | |
194 static void toggle_tmss_rom(genesis_context *gen); | |
176 void genesis_deserialize(deserialize_buffer *buf, genesis_context *gen) | 195 void genesis_deserialize(deserialize_buffer *buf, genesis_context *gen) |
177 { | 196 { |
178 register_section_handler(buf, (section_handler){.fun = m68k_deserialize, .data = gen->m68k}, SECTION_68000); | 197 register_section_handler(buf, (section_handler){.fun = m68k_deserialize, .data = gen->m68k}, SECTION_68000); |
179 register_section_handler(buf, (section_handler){.fun = z80_deserialize, .data = gen->z80}, SECTION_Z80); | 198 register_section_handler(buf, (section_handler){.fun = z80_deserialize, .data = gen->z80}, SECTION_Z80); |
180 register_section_handler(buf, (section_handler){.fun = vdp_deserialize, .data = gen->vdp}, SECTION_VDP); | 199 register_section_handler(buf, (section_handler){.fun = vdp_deserialize, .data = gen->vdp}, SECTION_VDP); |
185 register_section_handler(buf, (section_handler){.fun = io_deserialize, .data = gen->io.ports + 1}, SECTION_SEGA_IO_2); | 204 register_section_handler(buf, (section_handler){.fun = io_deserialize, .data = gen->io.ports + 1}, SECTION_SEGA_IO_2); |
186 register_section_handler(buf, (section_handler){.fun = io_deserialize, .data = gen->io.ports + 2}, SECTION_SEGA_IO_EXT); | 205 register_section_handler(buf, (section_handler){.fun = io_deserialize, .data = gen->io.ports + 2}, SECTION_SEGA_IO_EXT); |
187 register_section_handler(buf, (section_handler){.fun = ram_deserialize, .data = gen}, SECTION_MAIN_RAM); | 206 register_section_handler(buf, (section_handler){.fun = ram_deserialize, .data = gen}, SECTION_MAIN_RAM); |
188 register_section_handler(buf, (section_handler){.fun = zram_deserialize, .data = gen}, SECTION_SOUND_RAM); | 207 register_section_handler(buf, (section_handler){.fun = zram_deserialize, .data = gen}, SECTION_SOUND_RAM); |
189 register_section_handler(buf, (section_handler){.fun = cart_deserialize, .data = gen}, SECTION_MAPPER); | 208 register_section_handler(buf, (section_handler){.fun = cart_deserialize, .data = gen}, SECTION_MAPPER); |
209 register_section_handler(buf, (section_handler){.fun = tmss_deserialize, .data = gen}, SECTION_TMSS); | |
210 uint8_t tmss_old = gen->tmss; | |
211 gen->tmss = 0xFF; | |
190 while (buf->cur_pos < buf->size) | 212 while (buf->cur_pos < buf->size) |
191 { | 213 { |
192 load_section(buf); | 214 load_section(buf); |
215 } | |
216 if (gen->version_reg & 0xF) { | |
217 if (gen->tmss == 0xFF) { | |
218 //state lacked a TMSS section, assume that the game ROM is mapped in | |
219 //and that the VDP is unlocked | |
220 gen->tmss_lock[0] = 0x5345; | |
221 gen->tmss_lock[1] = 0x4741; | |
222 gen->tmss = 1; | |
223 } | |
224 if (gen->tmss != tmss_old) { | |
225 toggle_tmss_rom(gen); | |
226 } | |
227 check_tmss_lock(gen); | |
193 } | 228 } |
194 update_z80_bank_pointer(gen); | 229 update_z80_bank_pointer(gen); |
195 adjust_int_cycle(gen->m68k, gen->vdp); | 230 adjust_int_cycle(gen->m68k, gen->vdp); |
196 free(buf->handlers); | 231 free(buf->handlers); |
197 buf->handlers = NULL; | 232 buf->handlers = NULL; |
1174 } | 1209 } |
1175 } | 1210 } |
1176 | 1211 |
1177 static void check_tmss_lock(genesis_context *gen) | 1212 static void check_tmss_lock(genesis_context *gen) |
1178 { | 1213 { |
1179 gen->vdp_unlocked = gen->tmss_lock[0] == 'SE' && gen->tmss_lock[1] == 'GA'; | 1214 gen->vdp_unlocked = gen->tmss_lock[0] == 0x5345 && gen->tmss_lock[1] == 0x4741; |
1215 } | |
1216 | |
1217 static void toggle_tmss_rom(genesis_context *gen) | |
1218 { | |
1219 m68k_context *context = gen->m68k; | |
1220 for (int i = 0; i < NUM_MEM_AREAS; i++) | |
1221 { | |
1222 uint16_t *tmp = context->mem_pointers[i]; | |
1223 context->mem_pointers[i] = gen->tmss_pointers[i]; | |
1224 gen->tmss_pointers[i] = tmp; | |
1225 } | |
1226 m68k_invalidate_code_range(context, 0, 0x400000); | |
1180 } | 1227 } |
1181 | 1228 |
1182 static void *unused_write(uint32_t location, void *vcontext, uint16_t value) | 1229 static void *unused_write(uint32_t location, void *vcontext, uint16_t value) |
1183 { | 1230 { |
1184 m68k_context *context = vcontext; | 1231 m68k_context *context = vcontext; |
1189 check_tmss_lock(gen); | 1236 check_tmss_lock(gen); |
1190 } else if (has_tmss && location == 0xA14100) { | 1237 } else if (has_tmss && location == 0xA14100) { |
1191 value &= 1; | 1238 value &= 1; |
1192 if (gen->tmss != value) { | 1239 if (gen->tmss != value) { |
1193 gen->tmss = value; | 1240 gen->tmss = value; |
1194 for (int i = 0; i < NUM_MEM_AREAS; i++) | 1241 toggle_tmss_rom(gen); |
1195 { | |
1196 uint16_t *tmp = context->mem_pointers[i]; | |
1197 context->mem_pointers[i] = gen->tmss_pointers[i]; | |
1198 gen->tmss_pointers[i] = tmp; | |
1199 } | |
1200 m68k_invalidate_code_range(context, 0, 0x400000); | |
1201 } | 1242 } |
1202 } else if (location < 0x800000 || (location >= 0xA13000 && location < 0xA13100) || (location >= 0xA12000 && location < 0xA12100)) { | 1243 } else if (location < 0x800000 || (location >= 0xA13000 && location < 0xA13100) || (location >= 0xA12000 && location < 0xA12100)) { |
1203 //these writes are ignored when no relevant hardware is present | 1244 //these writes are ignored when no relevant hardware is present |
1204 } else { | 1245 } else { |
1205 fatal_error("Machine freeze due to unmapped write to %X\n", location); | 1246 fatal_error("Machine freeze due to unmapped write to %X\n", location); |
1225 } else if (has_tmss && (location == 0xA14100 || location == 0xA14101)) { | 1266 } else if (has_tmss && (location == 0xA14100 || location == 0xA14101)) { |
1226 if (location & 1) { | 1267 if (location & 1) { |
1227 value &= 1; | 1268 value &= 1; |
1228 if (gen->tmss != value) { | 1269 if (gen->tmss != value) { |
1229 gen->tmss = value; | 1270 gen->tmss = value; |
1230 for (int i = 0; i < NUM_MEM_AREAS; i++) | 1271 toggle_tmss_rom(gen); |
1231 { | |
1232 uint16_t *tmp = context->mem_pointers[i]; | |
1233 context->mem_pointers[i] = gen->tmss_pointers[i]; | |
1234 gen->tmss_pointers[i] = tmp; | |
1235 } | |
1236 m68k_invalidate_code_range(context, 0, 0x400000); | |
1237 } | 1272 } |
1238 } | 1273 } |
1239 } else if (location < 0x800000 || (location >= 0xA13000 && location < 0xA13100) || (location >= 0xA12000 && location < 0xA12100)) { | 1274 } else if (location < 0x800000 || (location >= 0xA13000 && location < 0xA13100) || (location >= 0xA12000 && location < 0xA12100)) { |
1240 //these writes are ignored when no relevant hardware is present | 1275 //these writes are ignored when no relevant hardware is present |
1241 } else { | 1276 } else { |