Mercurial > repos > blastem
comparison genesis.c @ 1692:5dacaef602a7 segacd
Merge from default
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 05 Jan 2019 00:58:08 -0800 |
parents | a763523dadf4 6909c5d0bbb5 |
children | 3414a4423de1 |
comparison
equal
deleted
inserted
replaced
1504:95b3a1a8b26c | 1692:5dacaef602a7 |
---|---|
14 #include "render.h" | 14 #include "render.h" |
15 #include "gst.h" | 15 #include "gst.h" |
16 #include "util.h" | 16 #include "util.h" |
17 #include "debug.h" | 17 #include "debug.h" |
18 #include "gdb_remote.h" | 18 #include "gdb_remote.h" |
19 #include "saves.h" | |
20 #include "bindings.h" | |
21 #include "jcart.h" | |
19 #define MCLKS_NTSC 53693175 | 22 #define MCLKS_NTSC 53693175 |
20 #define MCLKS_PAL 53203395 | 23 #define MCLKS_PAL 53203395 |
21 | 24 |
22 uint32_t MCLKS_PER_68K; | 25 uint32_t MCLKS_PER_68K; |
23 #define MCLKS_PER_YM 7 | 26 #define MCLKS_PER_YM 7 |
27 #define DEFAULT_SYNC_INTERVAL MCLKS_LINE | 30 #define DEFAULT_SYNC_INTERVAL MCLKS_LINE |
28 #define DEFAULT_LOWPASS_CUTOFF 3390 | 31 #define DEFAULT_LOWPASS_CUTOFF 3390 |
29 | 32 |
30 //TODO: Figure out the exact value for this | 33 //TODO: Figure out the exact value for this |
31 #define LINES_NTSC 262 | 34 #define LINES_NTSC 262 |
32 #define LINES_PAL 312 | 35 #define LINES_PAL 313 |
33 | 36 |
34 #define MAX_SOUND_CYCLES 100000 | 37 #define MAX_SOUND_CYCLES 100000 |
35 | 38 |
36 void genesis_serialize(genesis_context *gen, serialize_buffer *buf, uint32_t m68k_pc) | 39 void genesis_serialize(genesis_context *gen, serialize_buffer *buf, uint32_t m68k_pc) |
37 { | 40 { |
108 z80_invalidate_code_range(gen->z80, 0, 0x4000); | 111 z80_invalidate_code_range(gen->z80, 0, 0x4000); |
109 } | 112 } |
110 | 113 |
111 static void update_z80_bank_pointer(genesis_context *gen) | 114 static void update_z80_bank_pointer(genesis_context *gen) |
112 { | 115 { |
113 if (gen->z80->bank_reg < 0x100) { | 116 if (gen->z80->bank_reg < 0x140) { |
114 gen->z80->mem_pointers[1] = get_native_pointer(gen->z80->bank_reg << 15, (void **)gen->m68k->mem_pointers, &gen->m68k->options->gen); | 117 gen->z80->mem_pointers[1] = get_native_pointer(gen->z80->bank_reg << 15, (void **)gen->m68k->mem_pointers, &gen->m68k->options->gen); |
115 } else { | 118 } else { |
116 gen->z80->mem_pointers[1] = NULL; | 119 gen->z80->mem_pointers[1] = NULL; |
117 } | 120 } |
118 } | 121 } |
123 gen->z80->reset = load_int8(buf); | 126 gen->z80->reset = load_int8(buf); |
124 gen->z80->busreq = load_int8(buf); | 127 gen->z80->busreq = load_int8(buf); |
125 gen->z80->bank_reg = load_int16(buf) & 0x1FF; | 128 gen->z80->bank_reg = load_int16(buf) & 0x1FF; |
126 } | 129 } |
127 | 130 |
131 static void adjust_int_cycle(m68k_context * context, vdp_context * v_context); | |
128 void genesis_deserialize(deserialize_buffer *buf, genesis_context *gen) | 132 void genesis_deserialize(deserialize_buffer *buf, genesis_context *gen) |
129 { | 133 { |
130 register_section_handler(buf, (section_handler){.fun = m68k_deserialize, .data = gen->m68k}, SECTION_68000); | 134 register_section_handler(buf, (section_handler){.fun = m68k_deserialize, .data = gen->m68k}, SECTION_68000); |
131 register_section_handler(buf, (section_handler){.fun = z80_deserialize, .data = gen->z80}, SECTION_Z80); | 135 register_section_handler(buf, (section_handler){.fun = z80_deserialize, .data = gen->z80}, SECTION_Z80); |
132 register_section_handler(buf, (section_handler){.fun = vdp_deserialize, .data = gen->vdp}, SECTION_VDP); | 136 register_section_handler(buf, (section_handler){.fun = vdp_deserialize, .data = gen->vdp}, SECTION_VDP); |
142 while (buf->cur_pos < buf->size) | 146 while (buf->cur_pos < buf->size) |
143 { | 147 { |
144 load_section(buf); | 148 load_section(buf); |
145 } | 149 } |
146 update_z80_bank_pointer(gen); | 150 update_z80_bank_pointer(gen); |
151 adjust_int_cycle(gen->m68k, gen->vdp); | |
147 } | 152 } |
148 | 153 |
149 uint16_t read_dma_value(uint32_t address) | 154 uint16_t read_dma_value(uint32_t address) |
150 { | 155 { |
151 genesis_context *genesis = (genesis_context *)current_system; | 156 genesis_context *genesis = (genesis_context *)current_system; |
241 static void z80_next_int_pulse(z80_context * z_context) | 246 static void z80_next_int_pulse(z80_context * z_context) |
242 { | 247 { |
243 genesis_context * gen = z_context->system; | 248 genesis_context * gen = z_context->system; |
244 z_context->int_pulse_start = vdp_next_vint_z80(gen->vdp); | 249 z_context->int_pulse_start = vdp_next_vint_z80(gen->vdp); |
245 z_context->int_pulse_end = z_context->int_pulse_start + Z80_INT_PULSE_MCLKS; | 250 z_context->int_pulse_end = z_context->int_pulse_start + Z80_INT_PULSE_MCLKS; |
251 z_context->im2_vector = 0xFF; | |
246 } | 252 } |
247 | 253 |
248 static void sync_z80(z80_context * z_context, uint32_t mclks) | 254 static void sync_z80(z80_context * z_context, uint32_t mclks) |
249 { | 255 { |
250 #ifndef NO_Z80 | 256 #ifndef NO_Z80 |
305 | 311 |
306 uint32_t mclks = context->current_cycle; | 312 uint32_t mclks = context->current_cycle; |
307 sync_z80(z_context, mclks); | 313 sync_z80(z_context, mclks); |
308 sync_sound(gen, mclks); | 314 sync_sound(gen, mclks); |
309 vdp_run_context(v_context, mclks); | 315 vdp_run_context(v_context, mclks); |
316 if (mclks >= gen->reset_cycle) { | |
317 gen->reset_requested = 1; | |
318 context->should_return = 1; | |
319 gen->reset_cycle = CYCLE_NEVER; | |
320 } | |
310 if (v_context->frame != last_frame_num) { | 321 if (v_context->frame != last_frame_num) { |
311 //printf("reached frame end %d | MCLK Cycles: %d, Target: %d, VDP cycles: %d, vcounter: %d, hslot: %d\n", last_frame_num, mclks, gen->frame_end, v_context->cycles, v_context->vcounter, v_context->hslot); | 322 //printf("reached frame end %d | MCLK Cycles: %d, Target: %d, VDP cycles: %d, vcounter: %d, hslot: %d\n", last_frame_num, mclks, gen->frame_end, v_context->cycles, v_context->vcounter, v_context->hslot); |
312 last_frame_num = v_context->frame; | 323 last_frame_num = v_context->frame; |
313 | 324 |
314 if(exit_after){ | 325 if(exit_after){ |
321 uint32_t deduction = mclks - ADJUST_BUFFER; | 332 uint32_t deduction = mclks - ADJUST_BUFFER; |
322 vdp_adjust_cycles(v_context, deduction); | 333 vdp_adjust_cycles(v_context, deduction); |
323 io_adjust_cycles(gen->io.ports, context->current_cycle, deduction); | 334 io_adjust_cycles(gen->io.ports, context->current_cycle, deduction); |
324 io_adjust_cycles(gen->io.ports+1, context->current_cycle, deduction); | 335 io_adjust_cycles(gen->io.ports+1, context->current_cycle, deduction); |
325 io_adjust_cycles(gen->io.ports+2, context->current_cycle, deduction); | 336 io_adjust_cycles(gen->io.ports+2, context->current_cycle, deduction); |
337 if (gen->mapper_type == MAPPER_JCART) { | |
338 jcart_adjust_cycles(gen, deduction); | |
339 } | |
326 context->current_cycle -= deduction; | 340 context->current_cycle -= deduction; |
327 z80_adjust_cycles(z_context, deduction); | 341 z80_adjust_cycles(z_context, deduction); |
328 gen->ym->current_cycle -= deduction; | 342 gen->ym->current_cycle -= deduction; |
329 gen->psg->cycles -= deduction; | 343 gen->psg->cycles -= deduction; |
330 if (gen->ym->write_cycle != CYCLE_NEVER) { | 344 if (gen->ym->write_cycle != CYCLE_NEVER) { |
331 gen->ym->write_cycle = gen->ym->write_cycle >= deduction ? gen->ym->write_cycle - deduction : 0; | 345 gen->ym->write_cycle = gen->ym->write_cycle >= deduction ? gen->ym->write_cycle - deduction : 0; |
346 } | |
347 if (gen->reset_cycle != CYCLE_NEVER) { | |
348 gen->reset_cycle -= deduction; | |
332 } | 349 } |
333 } | 350 } |
334 } | 351 } |
335 gen->frame_end = vdp_cycles_to_frame_end(v_context); | 352 gen->frame_end = vdp_cycles_to_frame_end(v_context); |
336 context->sync_cycle = gen->frame_end; | 353 context->sync_cycle = gen->frame_end; |
342 } | 359 } |
343 if (!address && (gen->header.enter_debugger || gen->header.save_state)) { | 360 if (!address && (gen->header.enter_debugger || gen->header.save_state)) { |
344 context->sync_cycle = context->current_cycle + 1; | 361 context->sync_cycle = context->current_cycle + 1; |
345 } | 362 } |
346 adjust_int_cycle(context, v_context); | 363 adjust_int_cycle(context, v_context); |
364 if (gen->reset_cycle < context->target_cycle) { | |
365 context->target_cycle = gen->reset_cycle; | |
366 } | |
347 if (address) { | 367 if (address) { |
348 if (gen->header.enter_debugger) { | 368 if (gen->header.enter_debugger) { |
349 gen->header.enter_debugger = 0; | 369 gen->header.enter_debugger = 0; |
350 debugger(context, address); | 370 debugger(context, address); |
351 } | 371 } |
357 while (!z_context->pc) | 377 while (!z_context->pc) |
358 { | 378 { |
359 sync_z80(z_context, z_context->current_cycle + MCLKS_PER_Z80); | 379 sync_z80(z_context, z_context->current_cycle + MCLKS_PER_Z80); |
360 } | 380 } |
361 } | 381 } |
362 char *save_path; | 382 char *save_path = get_slot_name(&gen->header, slot, use_native_states ? "state" : "gst"); |
363 if (slot == QUICK_SAVE_SLOT) { | |
364 save_path = save_state_path; | |
365 } else { | |
366 char slotname[] = "slot_0.state"; | |
367 slotname[5] = '0' + slot; | |
368 if (!use_native_states) { | |
369 strcpy(slotname + 7, "gst"); | |
370 } | |
371 char const *parts[] = {gen->header.save_dir, PATH_SEP, slotname}; | |
372 save_path = alloc_concat_m(3, parts); | |
373 } | |
374 if (use_native_states) { | 383 if (use_native_states) { |
375 serialize_buffer state; | 384 serialize_buffer state; |
376 init_serialize(&state); | 385 init_serialize(&state); |
377 genesis_serialize(gen, &state, address); | 386 genesis_serialize(gen, &state, address); |
378 save_to_file(&state, save_path); | 387 save_to_file(&state, save_path); |
379 free(state.data); | 388 free(state.data); |
380 } else { | 389 } else { |
381 save_gst(gen, save_path, address); | 390 save_gst(gen, save_path, address); |
382 } | 391 } |
383 printf("Saved state to %s\n", save_path); | 392 printf("Saved state to %s\n", save_path); |
384 if (slot != QUICK_SAVE_SLOT) { | 393 free(save_path); |
385 free(save_path); | |
386 } | |
387 } else if(gen->header.save_state) { | 394 } else if(gen->header.save_state) { |
388 context->sync_cycle = context->current_cycle + 1; | 395 context->sync_cycle = context->current_cycle + 1; |
389 } | 396 } |
390 } | 397 } |
391 #ifdef REFRESH_EMULATION | 398 #ifdef REFRESH_EMULATION |
1006 gen->normal_clock = MCLKS_NTSC; | 1013 gen->normal_clock = MCLKS_NTSC; |
1007 } | 1014 } |
1008 gen->master_clock = gen->normal_clock; | 1015 gen->master_clock = gen->normal_clock; |
1009 } | 1016 } |
1010 | 1017 |
1011 static void handle_reset_requests(genesis_context *gen) | |
1012 { | |
1013 while (gen->reset_requested) | |
1014 { | |
1015 gen->reset_requested = 0; | |
1016 z80_assert_reset(gen->z80, gen->m68k->current_cycle); | |
1017 z80_clear_busreq(gen->z80, gen->m68k->current_cycle); | |
1018 ym_reset(gen->ym); | |
1019 //Is there any sort of VDP reset? | |
1020 m68k_reset(gen->m68k); | |
1021 } | |
1022 vdp_release_framebuffer(gen->vdp); | |
1023 } | |
1024 | |
1025 #include "m68k_internal.h" //needed for get_native_address_trans, should be eliminated once handling of PC is cleaned up | 1018 #include "m68k_internal.h" //needed for get_native_address_trans, should be eliminated once handling of PC is cleaned up |
1026 static uint8_t load_state(system_header *system, uint8_t slot) | 1019 static uint8_t load_state(system_header *system, uint8_t slot) |
1027 { | 1020 { |
1028 genesis_context *gen = (genesis_context *)system; | 1021 genesis_context *gen = (genesis_context *)system; |
1029 char numslotname[] = "slot_0.state"; | 1022 char *statepath = get_slot_name(system, slot, "state"); |
1030 char *slotname; | |
1031 if (slot == QUICK_SAVE_SLOT) { | |
1032 slotname = "quicksave.state"; | |
1033 } else { | |
1034 numslotname[5] = '0' + slot; | |
1035 slotname = numslotname; | |
1036 } | |
1037 char const *parts[] = {gen->header.save_dir, PATH_SEP, slotname}; | |
1038 char *statepath = alloc_concat_m(3, parts); | |
1039 deserialize_buffer state; | 1023 deserialize_buffer state; |
1040 uint32_t pc = 0; | 1024 uint32_t pc = 0; |
1041 uint8_t ret; | 1025 uint8_t ret; |
1026 if (!gen->m68k->resume_pc) { | |
1027 system->delayed_load_slot = slot + 1; | |
1028 gen->m68k->should_return = 1; | |
1029 ret = get_modification_time(statepath) != 0; | |
1030 if (!ret) { | |
1031 strcpy(statepath + strlen(statepath)-strlen("state"), "gst"); | |
1032 ret = get_modification_time(statepath) != 0; | |
1033 } | |
1034 goto done; | |
1035 } | |
1042 if (load_from_file(&state, statepath)) { | 1036 if (load_from_file(&state, statepath)) { |
1043 genesis_deserialize(&state, gen); | 1037 genesis_deserialize(&state, gen); |
1044 free(state.data); | 1038 free(state.data); |
1045 //HACK | 1039 //HACK |
1046 pc = gen->m68k->last_prefetch_address; | 1040 pc = gen->m68k->last_prefetch_address; |
1051 ret = pc != 0; | 1045 ret = pc != 0; |
1052 } | 1046 } |
1053 if (ret) { | 1047 if (ret) { |
1054 gen->m68k->resume_pc = get_native_address_trans(gen->m68k, pc); | 1048 gen->m68k->resume_pc = get_native_address_trans(gen->m68k, pc); |
1055 } | 1049 } |
1050 done: | |
1056 free(statepath); | 1051 free(statepath); |
1057 return ret; | 1052 return ret; |
1058 } | 1053 } |
1059 | 1054 |
1055 static void handle_reset_requests(genesis_context *gen) | |
1056 { | |
1057 while (gen->reset_requested || gen->header.delayed_load_slot) | |
1058 { | |
1059 if (gen->reset_requested) { | |
1060 gen->reset_requested = 0; | |
1061 gen->m68k->should_return = 0; | |
1062 z80_assert_reset(gen->z80, gen->m68k->current_cycle); | |
1063 z80_clear_busreq(gen->z80, gen->m68k->current_cycle); | |
1064 ym_reset(gen->ym); | |
1065 //Is there any sort of VDP reset? | |
1066 m68k_reset(gen->m68k); | |
1067 } | |
1068 if (gen->header.delayed_load_slot) { | |
1069 load_state(&gen->header, gen->header.delayed_load_slot - 1); | |
1070 gen->header.delayed_load_slot = 0; | |
1071 resume_68k(gen->m68k); | |
1072 } | |
1073 } | |
1074 bindings_release_capture(); | |
1075 vdp_release_framebuffer(gen->vdp); | |
1076 render_pause_source(gen->ym->audio); | |
1077 render_pause_source(gen->psg->audio); | |
1078 } | |
1079 | |
1060 static void start_genesis(system_header *system, char *statefile) | 1080 static void start_genesis(system_header *system, char *statefile) |
1061 { | 1081 { |
1062 genesis_context *gen = (genesis_context *)system; | 1082 genesis_context *gen = (genesis_context *)system; |
1063 set_keybindings(&gen->io); | |
1064 render_set_video_standard((gen->version_reg & HZ50) ? VID_PAL : VID_NTSC); | |
1065 if (statefile) { | 1083 if (statefile) { |
1066 //first try loading as a native format savestate | 1084 //first try loading as a native format savestate |
1067 deserialize_buffer state; | 1085 deserialize_buffer state; |
1068 uint32_t pc; | 1086 uint32_t pc; |
1069 if (load_from_file(&state, statefile)) { | 1087 if (load_from_file(&state, statefile)) { |
1098 } | 1116 } |
1099 | 1117 |
1100 static void resume_genesis(system_header *system) | 1118 static void resume_genesis(system_header *system) |
1101 { | 1119 { |
1102 genesis_context *gen = (genesis_context *)system; | 1120 genesis_context *gen = (genesis_context *)system; |
1103 map_all_bindings(&gen->io); | |
1104 render_set_video_standard((gen->version_reg & HZ50) ? VID_PAL : VID_NTSC); | 1121 render_set_video_standard((gen->version_reg & HZ50) ? VID_PAL : VID_NTSC); |
1122 bindings_reacquire_capture(); | |
1105 vdp_reacquire_framebuffer(gen->vdp); | 1123 vdp_reacquire_framebuffer(gen->vdp); |
1124 render_resume_source(gen->ym->audio); | |
1125 render_resume_source(gen->psg->audio); | |
1106 resume_68k(gen->m68k); | 1126 resume_68k(gen->m68k); |
1107 handle_reset_requests(gen); | 1127 handle_reset_requests(gen); |
1108 } | 1128 } |
1109 | 1129 |
1110 static void inc_debug_mode(system_header *system) | 1130 static void inc_debug_mode(system_header *system) |
1111 { | 1131 { |
1112 genesis_context *gen = (genesis_context *)system; | 1132 genesis_context *gen = (genesis_context *)system; |
1113 gen->vdp->debug++; | 1133 vdp_inc_debug_mode(gen->vdp); |
1114 if (gen->vdp->debug == 7) { | |
1115 gen->vdp->debug = 0; | |
1116 } | |
1117 } | |
1118 | |
1119 static void inc_debug_pal(system_header *system) | |
1120 { | |
1121 genesis_context *gen = (genesis_context *)system; | |
1122 gen->vdp->debug_pal++; | |
1123 if (gen->vdp->debug_pal == 4) { | |
1124 gen->vdp->debug_pal = 0; | |
1125 } | |
1126 } | 1134 } |
1127 | 1135 |
1128 static void request_exit(system_header *system) | 1136 static void request_exit(system_header *system) |
1129 { | 1137 { |
1130 genesis_context *gen = (genesis_context *)system; | 1138 genesis_context *gen = (genesis_context *)system; |
1161 } | 1169 } |
1162 | 1170 |
1163 static void soft_reset(system_header *system) | 1171 static void soft_reset(system_header *system) |
1164 { | 1172 { |
1165 genesis_context *gen = (genesis_context *)system; | 1173 genesis_context *gen = (genesis_context *)system; |
1166 gen->m68k->should_return = 1; | 1174 if (gen->reset_cycle == CYCLE_NEVER) { |
1167 gen->reset_requested = 1; | 1175 double random = (double)rand()/(double)RAND_MAX; |
1176 gen->reset_cycle = gen->m68k->current_cycle + random * MCLKS_LINE * (gen->version_reg & HZ50 ? LINES_PAL : LINES_NTSC); | |
1177 if (gen->reset_cycle < gen->m68k->target_cycle) { | |
1178 gen->m68k->target_cycle = gen->reset_cycle; | |
1179 } | |
1180 } | |
1168 } | 1181 } |
1169 | 1182 |
1170 static void free_genesis(system_header *system) | 1183 static void free_genesis(system_header *system) |
1171 { | 1184 { |
1172 genesis_context *gen = (genesis_context *)system; | 1185 genesis_context *gen = (genesis_context *)system; |
1173 vdp_free(gen->vdp); | 1186 vdp_free(gen->vdp); |
1187 memmap_chunk *map = (memmap_chunk *)gen->m68k->options->gen.memmap; | |
1174 m68k_options_free(gen->m68k->options); | 1188 m68k_options_free(gen->m68k->options); |
1175 free(gen->cart); | 1189 free(gen->cart); |
1176 free(gen->m68k); | 1190 free(gen->m68k); |
1177 free(gen->work_ram); | 1191 free(gen->work_ram); |
1178 z80_options_free(gen->z80->options); | 1192 z80_options_free(gen->z80->options); |
1179 free(gen->z80); | 1193 free(gen->z80); |
1180 free(gen->zram); | 1194 free(gen->zram); |
1181 ym_free(gen->ym); | 1195 ym_free(gen->ym); |
1182 psg_free(gen->psg); | 1196 psg_free(gen->psg); |
1183 free(gen->save_storage); | |
1184 free(gen->header.save_dir); | 1197 free(gen->header.save_dir); |
1198 free_rom_info(&gen->header.info); | |
1185 free(gen->lock_on); | 1199 free(gen->lock_on); |
1186 free(gen); | 1200 free(gen); |
1201 } | |
1202 | |
1203 static void gamepad_down(system_header *system, uint8_t gamepad_num, uint8_t button) | |
1204 { | |
1205 genesis_context *gen = (genesis_context *)system; | |
1206 io_gamepad_down(&gen->io, gamepad_num, button); | |
1207 if (gen->mapper_type == MAPPER_JCART) { | |
1208 jcart_gamepad_down(gen, gamepad_num, button); | |
1209 } | |
1210 } | |
1211 | |
1212 static void gamepad_up(system_header *system, uint8_t gamepad_num, uint8_t button) | |
1213 { | |
1214 genesis_context *gen = (genesis_context *)system; | |
1215 io_gamepad_up(&gen->io, gamepad_num, button); | |
1216 if (gen->mapper_type == MAPPER_JCART) { | |
1217 jcart_gamepad_up(gen, gamepad_num, button); | |
1218 } | |
1219 } | |
1220 | |
1221 static void mouse_down(system_header *system, uint8_t mouse_num, uint8_t button) | |
1222 { | |
1223 genesis_context *gen = (genesis_context *)system; | |
1224 io_mouse_down(&gen->io, mouse_num, button); | |
1225 } | |
1226 | |
1227 static void mouse_up(system_header *system, uint8_t mouse_num, uint8_t button) | |
1228 { | |
1229 genesis_context *gen = (genesis_context *)system; | |
1230 io_mouse_up(&gen->io, mouse_num, button); | |
1231 } | |
1232 | |
1233 static void mouse_motion_absolute(system_header *system, uint8_t mouse_num, uint16_t x, uint16_t y) | |
1234 { | |
1235 genesis_context *gen = (genesis_context *)system; | |
1236 io_mouse_motion_absolute(&gen->io, mouse_num, x, y); | |
1237 } | |
1238 | |
1239 static void mouse_motion_relative(system_header *system, uint8_t mouse_num, int32_t x, int32_t y) | |
1240 { | |
1241 genesis_context *gen = (genesis_context *)system; | |
1242 io_mouse_motion_relative(&gen->io, mouse_num, x, y); | |
1243 } | |
1244 | |
1245 static void keyboard_down(system_header *system, uint8_t scancode) | |
1246 { | |
1247 genesis_context *gen = (genesis_context *)system; | |
1248 io_keyboard_down(&gen->io, scancode); | |
1249 } | |
1250 | |
1251 static void keyboard_up(system_header *system, uint8_t scancode) | |
1252 { | |
1253 genesis_context *gen = (genesis_context *)system; | |
1254 io_keyboard_up(&gen->io, scancode); | |
1255 } | |
1256 | |
1257 static void config_updated(system_header *system) | |
1258 { | |
1259 genesis_context *gen = (genesis_context *)system; | |
1260 setup_io_devices(config, &system->info, &gen->io); | |
1187 } | 1261 } |
1188 | 1262 |
1189 static genesis_context *shared_init(uint32_t system_opts, rom_info *rom, uint8_t force_region) | 1263 static genesis_context *shared_init(uint32_t system_opts, rom_info *rom, uint8_t force_region) |
1190 { | 1264 { |
1191 static memmap_chunk z80_map[] = { | 1265 static memmap_chunk z80_map[] = { |
1215 gen->header.soft_reset = soft_reset; | 1289 gen->header.soft_reset = soft_reset; |
1216 gen->header.free_context = free_genesis; | 1290 gen->header.free_context = free_genesis; |
1217 gen->header.get_open_bus_value = get_open_bus_value; | 1291 gen->header.get_open_bus_value = get_open_bus_value; |
1218 gen->header.request_exit = request_exit; | 1292 gen->header.request_exit = request_exit; |
1219 gen->header.inc_debug_mode = inc_debug_mode; | 1293 gen->header.inc_debug_mode = inc_debug_mode; |
1220 gen->header.inc_debug_pal = inc_debug_pal; | 1294 gen->header.gamepad_down = gamepad_down; |
1295 gen->header.gamepad_up = gamepad_up; | |
1296 gen->header.mouse_down = mouse_down; | |
1297 gen->header.mouse_up = mouse_up; | |
1298 gen->header.mouse_motion_absolute = mouse_motion_absolute; | |
1299 gen->header.mouse_motion_relative = mouse_motion_relative; | |
1300 gen->header.keyboard_down = keyboard_down; | |
1301 gen->header.keyboard_up = keyboard_up; | |
1302 gen->header.config_updated = config_updated; | |
1221 gen->header.type = SYSTEM_GENESIS; | 1303 gen->header.type = SYSTEM_GENESIS; |
1222 | 1304 gen->header.info = *rom; |
1223 set_region(gen, rom, force_region); | 1305 set_region(gen, rom, force_region); |
1224 | 1306 |
1225 gen->vdp = malloc(sizeof(vdp_context)); | 1307 gen->vdp = init_vdp_context(gen->version_reg & 0x40); |
1226 init_vdp_context(gen->vdp, gen->version_reg & 0x40); | |
1227 gen->vdp->system = &gen->header; | 1308 gen->vdp->system = &gen->header; |
1228 gen->frame_end = vdp_cycles_to_frame_end(gen->vdp); | 1309 gen->frame_end = vdp_cycles_to_frame_end(gen->vdp); |
1229 char * config_cycles = tern_find_path(config, "clocks\0max_cycles\0", TVAL_PTR).ptrval; | 1310 char * config_cycles = tern_find_path(config, "clocks\0max_cycles\0", TVAL_PTR).ptrval; |
1230 gen->max_cycles = config_cycles ? atoi(config_cycles) : DEFAULT_SYNC_INTERVAL; | 1311 gen->max_cycles = config_cycles ? atoi(config_cycles) : DEFAULT_SYNC_INTERVAL; |
1231 gen->int_latency_prev1 = MCLKS_PER_68K * 32; | 1312 gen->int_latency_prev1 = MCLKS_PER_68K * 32; |
1232 gen->int_latency_prev2 = MCLKS_PER_68K * 16; | 1313 gen->int_latency_prev2 = MCLKS_PER_68K * 16; |
1233 | 1314 |
1234 char * lowpass_cutoff_str = tern_find_path(config, "audio\0lowpass_cutoff\0", TVAL_PTR).ptrval; | 1315 render_set_video_standard((gen->version_reg & HZ50) ? VID_PAL : VID_NTSC); |
1235 uint32_t lowpass_cutoff = lowpass_cutoff_str ? atoi(lowpass_cutoff_str) : DEFAULT_LOWPASS_CUTOFF; | |
1236 | 1316 |
1237 gen->ym = malloc(sizeof(ym2612_context)); | 1317 gen->ym = malloc(sizeof(ym2612_context)); |
1238 ym_init(gen->ym, render_sample_rate(), gen->master_clock, MCLKS_PER_YM, render_audio_buffer(), system_opts, lowpass_cutoff); | 1318 ym_init(gen->ym, gen->master_clock, MCLKS_PER_YM, system_opts); |
1239 | 1319 |
1240 gen->psg = malloc(sizeof(psg_context)); | 1320 gen->psg = malloc(sizeof(psg_context)); |
1241 psg_init(gen->psg, render_sample_rate(), gen->master_clock, MCLKS_PER_PSG, render_audio_buffer(), lowpass_cutoff); | 1321 psg_init(gen->psg, gen->master_clock, MCLKS_PER_PSG); |
1242 | 1322 |
1243 gen->zram = calloc(1, Z80_RAM_BYTES); | |
1244 z80_map[0].buffer = gen->zram = calloc(1, Z80_RAM_BYTES); | 1323 z80_map[0].buffer = gen->zram = calloc(1, Z80_RAM_BYTES); |
1245 #ifndef NO_Z80 | 1324 #ifndef NO_Z80 |
1246 z80_options *z_opts = malloc(sizeof(z80_options)); | 1325 z80_options *z_opts = malloc(sizeof(z80_options)); |
1247 init_z80_opts(z_opts, z80_map, 5, NULL, 0, MCLKS_PER_Z80, 0xFFFF); | 1326 init_z80_opts(z_opts, z80_map, 5, NULL, 0, MCLKS_PER_Z80, 0xFFFF); |
1248 gen->z80 = init_z80_context(z_opts); | 1327 gen->z80 = init_z80_context(z_opts); |
1296 | 1375 |
1297 gen->cart = main_rom; | 1376 gen->cart = main_rom; |
1298 gen->lock_on = lock_on; | 1377 gen->lock_on = lock_on; |
1299 | 1378 |
1300 setup_io_devices(config, rom, &gen->io); | 1379 setup_io_devices(config, rom, &gen->io); |
1380 gen->header.has_keyboard = io_has_keyboard(&gen->io); | |
1301 gen->mapper_type = rom->mapper_type; | 1381 gen->mapper_type = rom->mapper_type; |
1302 gen->save_type = rom->save_type; | 1382 gen->save_type = rom->save_type; |
1303 if (gen->save_type != SAVE_NONE) { | 1383 if (gen->save_type != SAVE_NONE) { |
1304 gen->save_ram_mask = rom->save_mask; | 1384 gen->save_ram_mask = rom->save_mask; |
1305 gen->save_size = rom->save_size; | 1385 gen->save_size = rom->save_size; |
1307 gen->eeprom_map = rom->eeprom_map; | 1387 gen->eeprom_map = rom->eeprom_map; |
1308 gen->num_eeprom = rom->num_eeprom; | 1388 gen->num_eeprom = rom->num_eeprom; |
1309 if (gen->save_type == SAVE_I2C) { | 1389 if (gen->save_type == SAVE_I2C) { |
1310 eeprom_init(&gen->eeprom, gen->save_storage, gen->save_size); | 1390 eeprom_init(&gen->eeprom, gen->save_storage, gen->save_size); |
1311 } else if (gen->save_type == SAVE_NOR) { | 1391 } else if (gen->save_type == SAVE_NOR) { |
1312 nor_flash_init(&gen->nor, gen->save_storage, gen->save_size, rom->save_page_size, rom->save_product_id, rom->save_bus); | 1392 memcpy(&gen->nor, rom->nor, sizeof(gen->nor)); |
1393 //nor_flash_init(&gen->nor, gen->save_storage, gen->save_size, rom->save_page_size, rom->save_product_id, rom->save_bus); | |
1313 } | 1394 } |
1314 } else { | 1395 } else { |
1315 gen->save_storage = NULL; | 1396 gen->save_storage = NULL; |
1316 } | 1397 } |
1317 | 1398 |
1361 (read_16_fun)io_read_w, (write_16_fun)io_write_w, | 1442 (read_16_fun)io_read_w, (write_16_fun)io_write_w, |
1362 (read_8_fun)io_read, (write_8_fun)io_write} | 1443 (read_8_fun)io_read, (write_8_fun)io_write} |
1363 }; | 1444 }; |
1364 const size_t base_chunks = sizeof(base_map)/sizeof(*base_map); | 1445 const size_t base_chunks = sizeof(base_map)/sizeof(*base_map); |
1365 | 1446 |
1366 genesis_context *alloc_config_genesis(void *rom, uint32_t rom_size, void *lock_on, uint32_t lock_on_size, uint32_t ym_opts, uint8_t force_region, rom_info *info_out) | 1447 genesis_context *alloc_config_genesis(void *rom, uint32_t rom_size, void *lock_on, uint32_t lock_on_size, uint32_t ym_opts, uint8_t force_region) |
1367 { | 1448 { |
1368 tern_node *rom_db = get_rom_db(); | 1449 tern_node *rom_db = get_rom_db(); |
1369 *info_out = configure_rom(rom_db, rom, rom_size, lock_on, lock_on_size, base_map, base_chunks); | 1450 rom_info info = configure_rom(rom_db, rom, rom_size, lock_on, lock_on_size, base_map, base_chunks); |
1370 rom = info_out->rom; | 1451 rom = info.rom; |
1371 rom_size = info_out->rom_size; | 1452 rom_size = info.rom_size; |
1372 #ifndef BLASTEM_BIG_ENDIAN | 1453 #ifndef BLASTEM_BIG_ENDIAN |
1373 byteswap_rom(rom_size, rom); | 1454 byteswap_rom(rom_size, rom); |
1374 if (lock_on) { | 1455 if (lock_on) { |
1375 byteswap_rom(lock_on_size, lock_on); | 1456 byteswap_rom(lock_on_size, lock_on); |
1376 } | 1457 } |
1377 #endif | 1458 #endif |
1378 return alloc_init_genesis(info_out, rom, lock_on, ym_opts, force_region); | 1459 char *m68k_divider = tern_find_path(config, "clocks\0m68k_divider\0", TVAL_PTR).ptrval; |
1379 } | 1460 if (!m68k_divider) { |
1380 | 1461 m68k_divider = "7"; |
1381 genesis_context *alloc_config_genesis_cdboot(system_media *media, uint32_t system_opts, uint8_t force_region, rom_info *info_out) | 1462 } |
1382 { | 1463 MCLKS_PER_68K = atoi(m68k_divider); |
1383 segacd_context *cd = alloc_configure_segacd(media, system_opts, force_region, info_out); | 1464 if (!MCLKS_PER_68K) { |
1384 genesis_context *gen = shared_init(system_opts, info_out, force_region); | 1465 MCLKS_PER_68K = 7; |
1466 } | |
1467 return alloc_init_genesis(&info, rom, lock_on, ym_opts, force_region); | |
1468 } | |
1469 | |
1470 genesis_context *alloc_config_genesis_cdboot(system_media *media, uint32_t system_opts, uint8_t force_region) | |
1471 { | |
1472 tern_node *rom_db = get_rom_db(); | |
1473 rom_info info = configure_rom(rom_db, media->buffer, media->size, NULL, 0, base_map, base_chunks); | |
1474 | |
1475 segacd_context *cd = alloc_configure_segacd(media, system_opts, force_region, &info); | |
1476 genesis_context *gen = shared_init(system_opts, &info, force_region); | |
1385 gen->cart = gen->lock_on = NULL; | 1477 gen->cart = gen->lock_on = NULL; |
1386 gen->save_storage = NULL; | 1478 gen->save_storage = NULL; |
1387 gen->save_type = SAVE_NONE; | 1479 gen->save_type = SAVE_NONE; |
1388 gen->version_reg &= ~NO_DISK; | 1480 gen->version_reg &= ~NO_DISK; |
1389 | 1481 |
1390 gen->expansion = cd; | 1482 gen->expansion = cd; |
1391 setup_io_devices(config, info_out, &gen->io); | 1483 setup_io_devices(config, &info, &gen->io); |
1392 | 1484 |
1393 uint32_t cd_chunks; | 1485 uint32_t cd_chunks; |
1394 memmap_chunk *cd_map = segacd_main_cpu_map(gen->expansion, &cd_chunks); | 1486 memmap_chunk *cd_map = segacd_main_cpu_map(gen->expansion, &cd_chunks); |
1395 memmap_chunk *map = malloc(sizeof(memmap_chunk) * (cd_chunks + base_chunks)); | 1487 memmap_chunk *map = malloc(sizeof(memmap_chunk) * (cd_chunks + base_chunks)); |
1396 memcpy(map, cd_map, sizeof(memmap_chunk) * cd_chunks); | 1488 memcpy(map, cd_map, sizeof(memmap_chunk) * cd_chunks); |