Mercurial > repos > blastem
comparison genesis.c @ 2043:804954731e3f mame_interp
Add cycle checks to deal with 68K core differences to the new refresh emulation blocks merged from default
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Thu, 05 Aug 2021 23:48:41 -0700 |
parents | 638eb2d25696 |
children |
comparison
equal
deleted
inserted
replaced
2042:3142602d21d8 | 2043:804954731e3f |
---|---|
36 #define LINES_PAL 313 | 36 #define LINES_PAL 313 |
37 | 37 |
38 #ifdef IS_LIB | 38 #ifdef IS_LIB |
39 #define MAX_SOUND_CYCLES (MCLKS_PER_YM*NUM_OPERATORS*6*4) | 39 #define MAX_SOUND_CYCLES (MCLKS_PER_YM*NUM_OPERATORS*6*4) |
40 #else | 40 #else |
41 #define MAX_SOUND_CYCLES 100000 | 41 #define MAX_SOUND_CYCLES 100000 |
42 #endif | 42 #endif |
43 | 43 |
44 #ifdef NEW_CORE | 44 #ifdef NEW_CORE |
45 #define Z80_CYCLE cycles | 45 #define Z80_CYCLE cycles |
46 #define Z80_OPTS opts | 46 #define Z80_OPTS opts |
55 { | 55 { |
56 if (all) { | 56 if (all) { |
57 start_section(buf, SECTION_68000); | 57 start_section(buf, SECTION_68000); |
58 m68k_serialize(gen->m68k, m68k_pc, buf); | 58 m68k_serialize(gen->m68k, m68k_pc, buf); |
59 end_section(buf); | 59 end_section(buf); |
60 | 60 |
61 start_section(buf, SECTION_Z80); | 61 start_section(buf, SECTION_Z80); |
62 z80_serialize(gen->z80, buf); | 62 z80_serialize(gen->z80, buf); |
63 end_section(buf); | 63 end_section(buf); |
64 } | 64 } |
65 | 65 |
66 start_section(buf, SECTION_VDP); | 66 start_section(buf, SECTION_VDP); |
67 vdp_serialize(gen->vdp, buf); | 67 vdp_serialize(gen->vdp, buf); |
68 end_section(buf); | 68 end_section(buf); |
69 | 69 |
70 start_section(buf, SECTION_YM2612); | 70 start_section(buf, SECTION_YM2612); |
71 ym_serialize(gen->ym, buf); | 71 ym_serialize(gen->ym, buf); |
72 end_section(buf); | 72 end_section(buf); |
73 | 73 |
74 start_section(buf, SECTION_PSG); | 74 start_section(buf, SECTION_PSG); |
75 psg_serialize(gen->psg, buf); | 75 psg_serialize(gen->psg, buf); |
76 end_section(buf); | 76 end_section(buf); |
77 | 77 |
78 if (all) { | 78 if (all) { |
79 start_section(buf, SECTION_GEN_BUS_ARBITER); | 79 start_section(buf, SECTION_GEN_BUS_ARBITER); |
80 save_int8(buf, gen->z80->reset); | 80 save_int8(buf, gen->z80->reset); |
81 save_int8(buf, gen->z80->busreq); | 81 save_int8(buf, gen->z80->busreq); |
82 save_int16(buf, gen->z80_bank_reg); | 82 save_int16(buf, gen->z80_bank_reg); |
83 end_section(buf); | 83 end_section(buf); |
84 | 84 |
85 start_section(buf, SECTION_SEGA_IO_1); | 85 start_section(buf, SECTION_SEGA_IO_1); |
86 io_serialize(gen->io.ports, buf); | 86 io_serialize(gen->io.ports, buf); |
87 end_section(buf); | 87 end_section(buf); |
88 | 88 |
89 start_section(buf, SECTION_SEGA_IO_2); | 89 start_section(buf, SECTION_SEGA_IO_2); |
90 io_serialize(gen->io.ports + 1, buf); | 90 io_serialize(gen->io.ports + 1, buf); |
91 end_section(buf); | 91 end_section(buf); |
92 | 92 |
93 start_section(buf, SECTION_SEGA_IO_EXT); | 93 start_section(buf, SECTION_SEGA_IO_EXT); |
94 io_serialize(gen->io.ports + 2, buf); | 94 io_serialize(gen->io.ports + 2, buf); |
95 end_section(buf); | 95 end_section(buf); |
96 | 96 |
97 start_section(buf, SECTION_MAIN_RAM); | 97 start_section(buf, SECTION_MAIN_RAM); |
98 save_int8(buf, RAM_WORDS * 2 / 1024); | 98 save_int8(buf, RAM_WORDS * 2 / 1024); |
99 save_buffer16(buf, gen->work_ram, RAM_WORDS); | 99 save_buffer16(buf, gen->work_ram, RAM_WORDS); |
100 end_section(buf); | 100 end_section(buf); |
101 | 101 |
102 start_section(buf, SECTION_SOUND_RAM); | 102 start_section(buf, SECTION_SOUND_RAM); |
103 save_int8(buf, Z80_RAM_BYTES / 1024); | 103 save_int8(buf, Z80_RAM_BYTES / 1024); |
104 save_buffer8(buf, gen->zram, Z80_RAM_BYTES); | 104 save_buffer8(buf, gen->zram, Z80_RAM_BYTES); |
105 end_section(buf); | 105 end_section(buf); |
106 | 106 |
107 if (gen->version_reg & 0xF) { | 107 if (gen->version_reg & 0xF) { |
108 //only save TMSS info if it's present | 108 //only save TMSS info if it's present |
109 //that will allow a state saved on a model lacking TMSS | 109 //that will allow a state saved on a model lacking TMSS |
110 //to be loaded on a model that has it | 110 //to be loaded on a model that has it |
111 start_section(buf, SECTION_TMSS); | 111 start_section(buf, SECTION_TMSS); |
112 save_int8(buf, gen->tmss); | 112 save_int8(buf, gen->tmss); |
113 save_buffer16(buf, gen->tmss_lock, 2); | 113 save_buffer16(buf, gen->tmss_lock, 2); |
114 end_section(buf); | 114 end_section(buf); |
115 } | 115 } |
116 | 116 |
117 cart_serialize(&gen->header, buf); | 117 cart_serialize(&gen->header, buf); |
118 } | 118 } |
119 } | 119 } |
120 | 120 |
121 static uint8_t *serialize(system_header *sys, size_t *size_out) | 121 static uint8_t *serialize(system_header *sys, size_t *size_out) |
251 genesis_context *genesis = (genesis_context *)current_system; | 251 genesis_context *genesis = (genesis_context *)current_system; |
252 //TODO: Figure out what happens when you try to DMA from weird adresses like IO or banked Z80 area | 252 //TODO: Figure out what happens when you try to DMA from weird adresses like IO or banked Z80 area |
253 if ((address >= 0xA00000 && address < 0xB00000) || (address >= 0xC00000 && address <= 0xE00000)) { | 253 if ((address >= 0xA00000 && address < 0xB00000) || (address >= 0xC00000 && address <= 0xE00000)) { |
254 return 0; | 254 return 0; |
255 } | 255 } |
256 | 256 |
257 //addresses here are word addresses (i.e. bit 0 corresponds to A1), so no need to do multiply by 2 | 257 //addresses here are word addresses (i.e. bit 0 corresponds to A1), so no need to do multiply by 2 |
258 return read_word(address * 2, (void **)genesis->m68k->mem_pointers, &genesis->m68k->options->gen, genesis->m68k); | 258 return read_word(address * 2, (void **)genesis->m68k->mem_pointers, &genesis->m68k->options->gen, genesis->m68k); |
259 } | 259 } |
260 | 260 |
261 static uint16_t get_open_bus_value(system_header *system) | 261 static uint16_t get_open_bus_value(system_header *system) |
296 } | 296 } |
297 if (mask < 2 && (v_context->regs[REG_MODE_3] & BIT_EINT_EN)) { | 297 if (mask < 2 && (v_context->regs[REG_MODE_3] & BIT_EINT_EN)) { |
298 uint32_t next_eint_port0 = io_next_interrupt(gen->io.ports, context->current_cycle); | 298 uint32_t next_eint_port0 = io_next_interrupt(gen->io.ports, context->current_cycle); |
299 uint32_t next_eint_port1 = io_next_interrupt(gen->io.ports + 1, context->current_cycle); | 299 uint32_t next_eint_port1 = io_next_interrupt(gen->io.ports + 1, context->current_cycle); |
300 uint32_t next_eint_port2 = io_next_interrupt(gen->io.ports + 2, context->current_cycle); | 300 uint32_t next_eint_port2 = io_next_interrupt(gen->io.ports + 2, context->current_cycle); |
301 uint32_t next_eint = next_eint_port0 < next_eint_port1 | 301 uint32_t next_eint = next_eint_port0 < next_eint_port1 |
302 ? (next_eint_port0 < next_eint_port2 ? next_eint_port0 : next_eint_port2) | 302 ? (next_eint_port0 < next_eint_port2 ? next_eint_port0 : next_eint_port2) |
303 : (next_eint_port1 < next_eint_port2 ? next_eint_port1 : next_eint_port2); | 303 : (next_eint_port1 < next_eint_port2 ? next_eint_port1 : next_eint_port2); |
304 if (next_eint != CYCLE_NEVER) { | 304 if (next_eint != CYCLE_NEVER) { |
305 next_eint = next_eint < context->current_cycle ? context->current_cycle : next_eint; | 305 next_eint = next_eint < context->current_cycle ? context->current_cycle : next_eint; |
306 if (next_eint < context->int_cycle) { | 306 if (next_eint < context->int_cycle) { |
316 } | 316 } |
317 /*if (context->int_cycle != old_int_cycle) { | 317 /*if (context->int_cycle != old_int_cycle) { |
318 printf("int cycle changed to: %d, level: %d @ %d(%d), frame: %d, vcounter: %d, hslot: %d, mask: %d, hint_counter: %d\n", context->int_cycle, context->int_num, v_context->cycles, context->current_cycle, v_context->frame, v_context->vcounter, v_context->hslot, context->status & 0x7, v_context->hint_counter); | 318 printf("int cycle changed to: %d, level: %d @ %d(%d), frame: %d, vcounter: %d, hslot: %d, mask: %d, hint_counter: %d\n", context->int_cycle, context->int_num, v_context->cycles, context->current_cycle, v_context->frame, v_context->vcounter, v_context->hslot, context->status & 0x7, v_context->hint_counter); |
319 old_int_cycle = context->int_cycle; | 319 old_int_cycle = context->int_cycle; |
320 }*/ | 320 }*/ |
321 | 321 |
322 if (context->status & M68K_STATUS_TRACE || context->trace_pending) { | 322 if (context->status & M68K_STATUS_TRACE || context->trace_pending) { |
323 context->target_cycle = context->current_cycle; | 323 context->target_cycle = context->current_cycle; |
324 return; | 324 return; |
325 } | 325 } |
326 | 326 |
341 } else if ((context->target_cycle - context->current_cycle) > gen->int_latency_prev2) { | 341 } else if ((context->target_cycle - context->current_cycle) > gen->int_latency_prev2) { |
342 context->target_cycle = context->sync_cycle = context->int_cycle - gen->int_latency_prev2; | 342 context->target_cycle = context->sync_cycle = context->int_cycle - gen->int_latency_prev2; |
343 } else { | 343 } else { |
344 context->target_cycle = context->sync_cycle = context->current_cycle; | 344 context->target_cycle = context->sync_cycle = context->current_cycle; |
345 } | 345 } |
346 | 346 |
347 } | 347 } |
348 /*printf("Cyc: %d, Trgt: %d, Int Cyc: %d, Int: %d, Mask: %X, V: %d, H: %d, HICount: %d, HReg: %d, Line: %d\n", | 348 /*printf("Cyc: %d, Trgt: %d, Int Cyc: %d, Int: %d, Mask: %X, V: %d, H: %d, HICount: %d, HReg: %d, Line: %d\n", |
349 context->current_cycle, context->target_cycle, context->int_cycle, context->int_num, (context->status & 0x7), | 349 context->current_cycle, context->target_cycle, context->int_cycle, context->int_num, (context->status & 0x7), |
350 v_context->regs[REG_MODE_2] & 0x20, v_context->regs[REG_MODE_1] & 0x10, v_context->hint_counter, v_context->regs[REG_HINT], v_context->cycles / MCLKS_LINE);*/ | 350 v_context->regs[REG_MODE_2] & 0x20, v_context->regs[REG_MODE_1] & 0x10, v_context->hint_counter, v_context->regs[REG_HINT], v_context->cycles / MCLKS_LINE);*/ |
351 } | 351 } |
626 gen->bus_busy = 1; | 626 gen->bus_busy = 1; |
627 sync_components(context, 0); | 627 sync_components(context, 0); |
628 gen->bus_busy = 0; | 628 gen->bus_busy = 0; |
629 } | 629 } |
630 } | 630 } |
631 | 631 |
632 if (blocked < 0) { | 632 if (blocked < 0) { |
633 blocked = vdp_control_port_write(v_context, value); | 633 blocked = vdp_control_port_write(v_context, value); |
634 } else { | 634 } else { |
635 blocked = 0; | 635 blocked = 0; |
636 } | 636 } |
817 static m68k_context * io_write(uint32_t location, m68k_context * context, uint8_t value) | 817 static m68k_context * io_write(uint32_t location, m68k_context * context, uint8_t value) |
818 { | 818 { |
819 genesis_context * gen = context->system; | 819 genesis_context * gen = context->system; |
820 #ifdef REFRESH_EMULATION | 820 #ifdef REFRESH_EMULATION |
821 //do refresh check here so we can avoid adding a penalty for a refresh that happens during an IO area access | 821 //do refresh check here so we can avoid adding a penalty for a refresh that happens during an IO area access |
822 if (context->current_cycle - 4*MCLKS_PER_68K > last_sync_cycle) { | |
822 refresh_counter += context->current_cycle - 4*MCLKS_PER_68K - last_sync_cycle; | 823 refresh_counter += context->current_cycle - 4*MCLKS_PER_68K - last_sync_cycle; |
823 context->current_cycle += REFRESH_DELAY * MCLKS_PER_68K * (refresh_counter / (MCLKS_PER_68K * REFRESH_INTERVAL)); | 824 context->current_cycle += REFRESH_DELAY * MCLKS_PER_68K * (refresh_counter / (MCLKS_PER_68K * REFRESH_INTERVAL)); |
824 refresh_counter = refresh_counter % (MCLKS_PER_68K * REFRESH_INTERVAL); | 825 refresh_counter = refresh_counter % (MCLKS_PER_68K * REFRESH_INTERVAL); |
825 last_sync_cycle = context->current_cycle - 4*MCLKS_PER_68K; | 826 last_sync_cycle = context->current_cycle - 4*MCLKS_PER_68K; |
827 } | |
826 #endif | 828 #endif |
827 if (location < 0x10000) { | 829 if (location < 0x10000) { |
828 //Access to Z80 memory incurs a one 68K cycle wait state | 830 //Access to Z80 memory incurs a one 68K cycle wait state |
829 context->current_cycle += MCLKS_PER_68K; | 831 context->current_cycle += MCLKS_PER_68K; |
830 if (!z80_enabled || z80_get_busack(gen->z80, context->current_cycle)) { | 832 if (!z80_enabled || z80_get_busack(gen->z80, context->current_cycle)) { |
977 { | 979 { |
978 uint8_t value; | 980 uint8_t value; |
979 genesis_context *gen = context->system; | 981 genesis_context *gen = context->system; |
980 #ifdef REFRESH_EMULATION | 982 #ifdef REFRESH_EMULATION |
981 //do refresh check here so we can avoid adding a penalty for a refresh that happens during an IO area access | 983 //do refresh check here so we can avoid adding a penalty for a refresh that happens during an IO area access |
984 if (context->current_cycle - 4*MCLKS_PER_68K > last_sync_cycle) { | |
982 refresh_counter += context->current_cycle - 4*MCLKS_PER_68K - last_sync_cycle; | 985 refresh_counter += context->current_cycle - 4*MCLKS_PER_68K - last_sync_cycle; |
983 context->current_cycle += REFRESH_DELAY * MCLKS_PER_68K * (refresh_counter / (MCLKS_PER_68K * REFRESH_INTERVAL)); | 986 context->current_cycle += REFRESH_DELAY * MCLKS_PER_68K * (refresh_counter / (MCLKS_PER_68K * REFRESH_INTERVAL)); |
984 refresh_counter = refresh_counter % (MCLKS_PER_68K * REFRESH_INTERVAL); | 987 refresh_counter = refresh_counter % (MCLKS_PER_68K * REFRESH_INTERVAL); |
985 last_sync_cycle = context->current_cycle - 4*MCLKS_PER_68K; | 988 last_sync_cycle = context->current_cycle - 4*MCLKS_PER_68K; |
989 } | |
986 #endif | 990 #endif |
987 if (location < 0x10000) { | 991 if (location < 0x10000) { |
988 //Access to Z80 memory incurs a one 68K cycle wait state | 992 //Access to Z80 memory incurs a one 68K cycle wait state |
989 context->current_cycle += MCLKS_PER_68K; | 993 context->current_cycle += MCLKS_PER_68K; |
990 if (!z80_enabled || z80_get_busack(gen->z80, context->current_cycle)) { | 994 if (!z80_enabled || z80_get_busack(gen->z80, context->current_cycle)) { |
1326 } else if (region & REGION_J) { | 1330 } else if (region & REGION_J) { |
1327 gen->version_reg = NO_DISK | JAP; | 1331 gen->version_reg = NO_DISK | JAP; |
1328 } else { | 1332 } else { |
1329 gen->version_reg = NO_DISK | USA; | 1333 gen->version_reg = NO_DISK | USA; |
1330 } | 1334 } |
1331 | 1335 |
1332 if (region & HZ50) { | 1336 if (region & HZ50) { |
1333 gen->normal_clock = MCLKS_PAL; | 1337 gen->normal_clock = MCLKS_PAL; |
1334 gen->soft_flush_cycles = MCLKS_LINE * 262 / 3 + 2; | 1338 gen->soft_flush_cycles = MCLKS_LINE * 262 / 3 + 2; |
1335 } else { | 1339 } else { |
1336 gen->normal_clock = MCLKS_NTSC; | 1340 gen->normal_clock = MCLKS_NTSC; |
1610 char *config_gain; | 1614 char *config_gain; |
1611 config_gain = tern_find_path(config, "audio\0psg_gain\0", TVAL_PTR).ptrval; | 1615 config_gain = tern_find_path(config, "audio\0psg_gain\0", TVAL_PTR).ptrval; |
1612 render_audio_source_gaindb(gen->psg->audio, config_gain ? atof(config_gain) : 0.0f); | 1616 render_audio_source_gaindb(gen->psg->audio, config_gain ? atof(config_gain) : 0.0f); |
1613 config_gain = tern_find_path(config, "audio\0fm_gain\0", TVAL_PTR).ptrval; | 1617 config_gain = tern_find_path(config, "audio\0fm_gain\0", TVAL_PTR).ptrval; |
1614 render_audio_source_gaindb(gen->ym->audio, config_gain ? atof(config_gain) : 0.0f); | 1618 render_audio_source_gaindb(gen->ym->audio, config_gain ? atof(config_gain) : 0.0f); |
1615 | 1619 |
1616 char *config_dac = tern_find_path_default(config, "audio\0fm_dac\0", (tern_val){.ptrval="zero_offset"}, TVAL_PTR).ptrval; | 1620 char *config_dac = tern_find_path_default(config, "audio\0fm_dac\0", (tern_val){.ptrval="zero_offset"}, TVAL_PTR).ptrval; |
1617 ym_enable_zero_offset(gen->ym, !strcmp(config_dac, "zero_offset")); | 1621 ym_enable_zero_offset(gen->ym, !strcmp(config_dac, "zero_offset")); |
1618 } | 1622 } |
1619 | 1623 |
1620 static void config_updated(system_header *system) | 1624 static void config_updated(system_header *system) |
1653 m68k_context *m68k = context; | 1657 m68k_context *m68k = context; |
1654 genesis_context *gen = m68k->system; | 1658 genesis_context *gen = m68k->system; |
1655 if (gen->tmss) { | 1659 if (gen->tmss) { |
1656 return gen->tmss_write_16(address, context, value); | 1660 return gen->tmss_write_16(address, context, value); |
1657 } | 1661 } |
1658 | 1662 |
1659 return context; | 1663 return context; |
1660 } | 1664 } |
1661 | 1665 |
1662 static void *tmss_rom_write_8(uint32_t address, void *context, uint8_t value) | 1666 static void *tmss_rom_write_8(uint32_t address, void *context, uint8_t value) |
1663 { | 1667 { |
1664 m68k_context *m68k = context; | 1668 m68k_context *m68k = context; |
1665 genesis_context *gen = m68k->system; | 1669 genesis_context *gen = m68k->system; |
1666 if (gen->tmss) { | 1670 if (gen->tmss) { |
1667 return gen->tmss_write_8(address, context, value); | 1671 return gen->tmss_write_8(address, context, value); |
1668 } | 1672 } |
1669 | 1673 |
1670 return context; | 1674 return context; |
1671 } | 1675 } |
1672 | 1676 |
1673 static uint16_t tmss_rom_read_16(uint32_t address, void *context) | 1677 static uint16_t tmss_rom_read_16(uint32_t address, void *context) |
1674 { | 1678 { |
1702 address += gen->tmss_write_offset; | 1706 address += gen->tmss_write_offset; |
1703 uint16_t *dest = get_native_pointer(address, (void **)m68k->mem_pointers, &m68k->options->gen); | 1707 uint16_t *dest = get_native_pointer(address, (void **)m68k->mem_pointers, &m68k->options->gen); |
1704 *dest = value; | 1708 *dest = value; |
1705 m68k_handle_code_write(address, m68k); | 1709 m68k_handle_code_write(address, m68k); |
1706 } | 1710 } |
1707 | 1711 |
1708 return context; | 1712 return context; |
1709 } | 1713 } |
1710 | 1714 |
1711 static void *tmss_word_write_8(uint32_t address, void *context, uint8_t value) | 1715 static void *tmss_word_write_8(uint32_t address, void *context, uint8_t value) |
1712 { | 1716 { |
1720 #else | 1724 #else |
1721 dest[address & 1 ^ 1] = value; | 1725 dest[address & 1 ^ 1] = value; |
1722 #endif | 1726 #endif |
1723 m68k_handle_code_write(address & ~1, m68k); | 1727 m68k_handle_code_write(address & ~1, m68k); |
1724 } | 1728 } |
1725 | 1729 |
1726 return context; | 1730 return context; |
1727 } | 1731 } |
1728 | 1732 |
1729 static void *tmss_odd_write_16(uint32_t address, void *context, uint16_t value) | 1733 static void *tmss_odd_write_16(uint32_t address, void *context, uint16_t value) |
1730 { | 1734 { |
1829 gen->frame_end = vdp_cycles_to_frame_end(gen->vdp); | 1833 gen->frame_end = vdp_cycles_to_frame_end(gen->vdp); |
1830 char * config_cycles = tern_find_path(config, "clocks\0max_cycles\0", TVAL_PTR).ptrval; | 1834 char * config_cycles = tern_find_path(config, "clocks\0max_cycles\0", TVAL_PTR).ptrval; |
1831 gen->max_cycles = config_cycles ? atoi(config_cycles) : DEFAULT_SYNC_INTERVAL; | 1835 gen->max_cycles = config_cycles ? atoi(config_cycles) : DEFAULT_SYNC_INTERVAL; |
1832 gen->int_latency_prev1 = MCLKS_PER_68K * 32; | 1836 gen->int_latency_prev1 = MCLKS_PER_68K * 32; |
1833 gen->int_latency_prev2 = MCLKS_PER_68K * 16; | 1837 gen->int_latency_prev2 = MCLKS_PER_68K * 16; |
1834 | 1838 |
1835 render_set_video_standard((gen->version_reg & HZ50) ? VID_PAL : VID_NTSC); | 1839 render_set_video_standard((gen->version_reg & HZ50) ? VID_PAL : VID_NTSC); |
1836 event_system_start(SYSTEM_GENESIS, (gen->version_reg & HZ50) ? VID_PAL : VID_NTSC, rom->name); | 1840 event_system_start(SYSTEM_GENESIS, (gen->version_reg & HZ50) ? VID_PAL : VID_NTSC, rom->name); |
1837 | 1841 |
1838 gen->ym = malloc(sizeof(ym2612_context)); | 1842 gen->ym = malloc(sizeof(ym2612_context)); |
1839 char *fm = tern_find_ptr_default(model, "fm", "discrete 2612"); | 1843 char *fm = tern_find_ptr_default(model, "fm", "discrete 2612"); |
1840 if (!strcmp(fm + strlen(fm) -4, "3834")) { | 1844 if (!strcmp(fm + strlen(fm) -4, "3834")) { |
1841 system_opts |= YM_OPT_3834; | 1845 system_opts |= YM_OPT_3834; |
1842 } | 1846 } |
1843 ym_init(gen->ym, gen->master_clock, MCLKS_PER_YM, system_opts); | 1847 ym_init(gen->ym, gen->master_clock, MCLKS_PER_YM, system_opts); |
1844 | 1848 |
1845 gen->psg = malloc(sizeof(psg_context)); | 1849 gen->psg = malloc(sizeof(psg_context)); |
1846 psg_init(gen->psg, gen->master_clock, MCLKS_PER_PSG); | 1850 psg_init(gen->psg, gen->master_clock, MCLKS_PER_PSG); |
1847 | 1851 |
1848 set_audio_config(gen); | 1852 set_audio_config(gen); |
1849 | 1853 |
1850 z80_map[0].buffer = gen->zram = calloc(1, Z80_RAM_BYTES); | 1854 z80_map[0].buffer = gen->zram = calloc(1, Z80_RAM_BYTES); |
1851 #ifndef NO_Z80 | 1855 #ifndef NO_Z80 |
1852 z80_options *z_opts = malloc(sizeof(z80_options)); | 1856 z80_options *z_opts = malloc(sizeof(z80_options)); |
1913 //nor_flash_init(&gen->nor, gen->save_storage, gen->save_size, rom->save_page_size, rom->save_product_id, rom->save_bus); | 1917 //nor_flash_init(&gen->nor, gen->save_storage, gen->save_size, rom->save_page_size, rom->save_product_id, rom->save_bus); |
1914 } | 1918 } |
1915 } else { | 1919 } else { |
1916 gen->save_storage = NULL; | 1920 gen->save_storage = NULL; |
1917 } | 1921 } |
1918 | 1922 |
1919 gen->mapper_start_index = rom->mapper_start_index; | 1923 gen->mapper_start_index = rom->mapper_start_index; |
1920 | 1924 |
1921 //This must happen before we generate memory access functions in init_m68k_opts | 1925 //This must happen before we generate memory access functions in init_m68k_opts |
1922 uint8_t next_ptr_index = 0; | 1926 uint8_t next_ptr_index = 0; |
1923 uint32_t tmss_min_alloc = 16 * 1024; | 1927 uint32_t tmss_min_alloc = 16 * 1024; |
1924 for (int i = 0; i < rom->map_chunks; i++) | 1928 for (int i = 0; i < rom->map_chunks; i++) |
1925 { | 1929 { |
2063 opts->gen.flags |= M68K_OPT_BROKEN_READ_MODIFY; | 2067 opts->gen.flags |= M68K_OPT_BROKEN_READ_MODIFY; |
2064 } | 2068 } |
2065 gen->m68k = init_68k_context(opts, NULL); | 2069 gen->m68k = init_68k_context(opts, NULL); |
2066 gen->m68k->system = gen; | 2070 gen->m68k->system = gen; |
2067 opts->address_log = (system_opts & OPT_ADDRESS_LOG) ? fopen("address.log", "w") : NULL; | 2071 opts->address_log = (system_opts & OPT_ADDRESS_LOG) ? fopen("address.log", "w") : NULL; |
2068 | 2072 |
2069 //This must happen after the 68K context has been allocated | 2073 //This must happen after the 68K context has been allocated |
2070 for (int i = 0; i < rom->map_chunks; i++) | 2074 for (int i = 0; i < rom->map_chunks; i++) |
2071 { | 2075 { |
2072 if (rom->map[i].flags & MMAP_PTR_IDX) { | 2076 if (rom->map[i].flags & MMAP_PTR_IDX) { |
2073 gen->m68k->mem_pointers[rom->map[i].ptr_index] = rom->map[i].buffer; | 2077 gen->m68k->mem_pointers[rom->map[i].ptr_index] = rom->map[i].buffer; |
2074 } | 2078 } |
2075 } | 2079 } |
2076 | 2080 |
2077 if (gen->mapper_type == MAPPER_SEGA) { | 2081 if (gen->mapper_type == MAPPER_SEGA) { |
2078 //initialize bank registers | 2082 //initialize bank registers |
2079 for (int i = 1; i < sizeof(gen->bank_regs); i++) | 2083 for (int i = 1; i < sizeof(gen->bank_regs); i++) |
2080 { | 2084 { |
2081 gen->bank_regs[i] = i; | 2085 gen->bank_regs[i] = i; |