comparison genesis.c @ 2052:3748a2a8a4b7

Support Sega mapper without 'SEGA SSF' in header or ROM DB entry and implement a subset of the extended Sega mapper implemented in the Mega Everdrive when 'SEGA SSF' is present
author Michael Pavone <pavone@retrodev.com>
date Sat, 01 Jan 2022 18:54:46 -0800
parents 3b8e29ef1145
children 3414a4423de1
comparison
equal deleted inserted replaced
2051:97bfb6089274 2052:3748a2a8a4b7
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
54 { 54 {
55 if (all) { 55 if (all) {
56 start_section(buf, SECTION_68000); 56 start_section(buf, SECTION_68000);
57 m68k_serialize(gen->m68k, m68k_pc, buf); 57 m68k_serialize(gen->m68k, m68k_pc, buf);
58 end_section(buf); 58 end_section(buf);
59 59
60 start_section(buf, SECTION_Z80); 60 start_section(buf, SECTION_Z80);
61 z80_serialize(gen->z80, buf); 61 z80_serialize(gen->z80, buf);
62 end_section(buf); 62 end_section(buf);
63 } 63 }
64 64
65 start_section(buf, SECTION_VDP); 65 start_section(buf, SECTION_VDP);
66 vdp_serialize(gen->vdp, buf); 66 vdp_serialize(gen->vdp, buf);
67 end_section(buf); 67 end_section(buf);
68 68
69 start_section(buf, SECTION_YM2612); 69 start_section(buf, SECTION_YM2612);
70 ym_serialize(gen->ym, buf); 70 ym_serialize(gen->ym, buf);
71 end_section(buf); 71 end_section(buf);
72 72
73 start_section(buf, SECTION_PSG); 73 start_section(buf, SECTION_PSG);
74 psg_serialize(gen->psg, buf); 74 psg_serialize(gen->psg, buf);
75 end_section(buf); 75 end_section(buf);
76 76
77 if (all) { 77 if (all) {
78 start_section(buf, SECTION_GEN_BUS_ARBITER); 78 start_section(buf, SECTION_GEN_BUS_ARBITER);
79 save_int8(buf, gen->z80->reset); 79 save_int8(buf, gen->z80->reset);
80 save_int8(buf, gen->z80->busreq); 80 save_int8(buf, gen->z80->busreq);
81 save_int16(buf, gen->z80_bank_reg); 81 save_int16(buf, gen->z80_bank_reg);
82 end_section(buf); 82 end_section(buf);
83 83
84 start_section(buf, SECTION_SEGA_IO_1); 84 start_section(buf, SECTION_SEGA_IO_1);
85 io_serialize(gen->io.ports, buf); 85 io_serialize(gen->io.ports, buf);
86 end_section(buf); 86 end_section(buf);
87 87
88 start_section(buf, SECTION_SEGA_IO_2); 88 start_section(buf, SECTION_SEGA_IO_2);
89 io_serialize(gen->io.ports + 1, buf); 89 io_serialize(gen->io.ports + 1, buf);
90 end_section(buf); 90 end_section(buf);
91 91
92 start_section(buf, SECTION_SEGA_IO_EXT); 92 start_section(buf, SECTION_SEGA_IO_EXT);
93 io_serialize(gen->io.ports + 2, buf); 93 io_serialize(gen->io.ports + 2, buf);
94 end_section(buf); 94 end_section(buf);
95 95
96 start_section(buf, SECTION_MAIN_RAM); 96 start_section(buf, SECTION_MAIN_RAM);
97 save_int8(buf, RAM_WORDS * 2 / 1024); 97 save_int8(buf, RAM_WORDS * 2 / 1024);
98 save_buffer16(buf, gen->work_ram, RAM_WORDS); 98 save_buffer16(buf, gen->work_ram, RAM_WORDS);
99 end_section(buf); 99 end_section(buf);
100 100
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) { 106 if (gen->version_reg & 0xF) {
107 //only save TMSS info if it's present 107 //only save TMSS info if it's present
108 //that will allow a state saved on a model lacking TMSS 108 //that will allow a state saved on a model lacking TMSS
109 //to be loaded on a model that has it 109 //to be loaded on a model that has it
110 start_section(buf, SECTION_TMSS); 110 start_section(buf, SECTION_TMSS);
111 save_int8(buf, gen->tmss); 111 save_int8(buf, gen->tmss);
112 save_buffer16(buf, gen->tmss_lock, 2); 112 save_buffer16(buf, gen->tmss_lock, 2);
113 end_section(buf); 113 end_section(buf);
114 } 114 }
115 115
116 cart_serialize(&gen->header, buf); 116 cart_serialize(&gen->header, buf);
117 } 117 }
118 } 118 }
119 119
120 static uint8_t *serialize(system_header *sys, size_t *size_out) 120 static uint8_t *serialize(system_header *sys, size_t *size_out)
248 genesis_context *genesis = (genesis_context *)current_system; 248 genesis_context *genesis = (genesis_context *)current_system;
249 //TODO: Figure out what happens when you try to DMA from weird adresses like IO or banked Z80 area 249 //TODO: Figure out what happens when you try to DMA from weird adresses like IO or banked Z80 area
250 if ((address >= 0xA00000 && address < 0xB00000) || (address >= 0xC00000 && address <= 0xE00000)) { 250 if ((address >= 0xA00000 && address < 0xB00000) || (address >= 0xC00000 && address <= 0xE00000)) {
251 return 0; 251 return 0;
252 } 252 }
253 253
254 //addresses here are word addresses (i.e. bit 0 corresponds to A1), so no need to do multiply by 2 254 //addresses here are word addresses (i.e. bit 0 corresponds to A1), so no need to do multiply by 2
255 return read_word(address * 2, (void **)genesis->m68k->mem_pointers, &genesis->m68k->options->gen, genesis->m68k); 255 return read_word(address * 2, (void **)genesis->m68k->mem_pointers, &genesis->m68k->options->gen, genesis->m68k);
256 } 256 }
257 257
258 static uint16_t get_open_bus_value(system_header *system) 258 static uint16_t get_open_bus_value(system_header *system)
288 } 288 }
289 if (mask < 2 && (v_context->regs[REG_MODE_3] & BIT_EINT_EN)) { 289 if (mask < 2 && (v_context->regs[REG_MODE_3] & BIT_EINT_EN)) {
290 uint32_t next_eint_port0 = io_next_interrupt(gen->io.ports, context->current_cycle); 290 uint32_t next_eint_port0 = io_next_interrupt(gen->io.ports, context->current_cycle);
291 uint32_t next_eint_port1 = io_next_interrupt(gen->io.ports + 1, context->current_cycle); 291 uint32_t next_eint_port1 = io_next_interrupt(gen->io.ports + 1, context->current_cycle);
292 uint32_t next_eint_port2 = io_next_interrupt(gen->io.ports + 2, context->current_cycle); 292 uint32_t next_eint_port2 = io_next_interrupt(gen->io.ports + 2, context->current_cycle);
293 uint32_t next_eint = next_eint_port0 < next_eint_port1 293 uint32_t next_eint = next_eint_port0 < next_eint_port1
294 ? (next_eint_port0 < next_eint_port2 ? next_eint_port0 : next_eint_port2) 294 ? (next_eint_port0 < next_eint_port2 ? next_eint_port0 : next_eint_port2)
295 : (next_eint_port1 < next_eint_port2 ? next_eint_port1 : next_eint_port2); 295 : (next_eint_port1 < next_eint_port2 ? next_eint_port1 : next_eint_port2);
296 if (next_eint != CYCLE_NEVER) { 296 if (next_eint != CYCLE_NEVER) {
297 next_eint = next_eint < context->current_cycle ? context->current_cycle : next_eint; 297 next_eint = next_eint < context->current_cycle ? context->current_cycle : next_eint;
298 if (next_eint < context->int_cycle) { 298 if (next_eint < context->int_cycle) {
308 } 308 }
309 /*if (context->int_cycle != old_int_cycle) { 309 /*if (context->int_cycle != old_int_cycle) {
310 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); 310 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);
311 old_int_cycle = context->int_cycle; 311 old_int_cycle = context->int_cycle;
312 }*/ 312 }*/
313 313
314 if (context->status & M68K_STATUS_TRACE || context->trace_pending) { 314 if (context->status & M68K_STATUS_TRACE || context->trace_pending) {
315 context->target_cycle = context->current_cycle; 315 context->target_cycle = context->current_cycle;
316 return; 316 return;
317 } 317 }
318 318
333 } else if ((context->target_cycle - context->current_cycle) > gen->int_latency_prev2) { 333 } else if ((context->target_cycle - context->current_cycle) > gen->int_latency_prev2) {
334 context->target_cycle = context->sync_cycle = context->int_cycle - gen->int_latency_prev2; 334 context->target_cycle = context->sync_cycle = context->int_cycle - gen->int_latency_prev2;
335 } else { 335 } else {
336 context->target_cycle = context->sync_cycle = context->current_cycle; 336 context->target_cycle = context->sync_cycle = context->current_cycle;
337 } 337 }
338 338
339 } 339 }
340 /*printf("Cyc: %d, Trgt: %d, Int Cyc: %d, Int: %d, Mask: %X, V: %d, H: %d, HICount: %d, HReg: %d, Line: %d\n", 340 /*printf("Cyc: %d, Trgt: %d, Int Cyc: %d, Int: %d, Mask: %X, V: %d, H: %d, HICount: %d, HReg: %d, Line: %d\n",
341 context->current_cycle, context->target_cycle, context->int_cycle, context->int_num, (context->status & 0x7), 341 context->current_cycle, context->target_cycle, context->int_cycle, context->int_num, (context->status & 0x7),
342 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);*/ 342 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);*/
343 } 343 }
608 gen->bus_busy = 1; 608 gen->bus_busy = 1;
609 sync_components(context, 0); 609 sync_components(context, 0);
610 gen->bus_busy = 0; 610 gen->bus_busy = 0;
611 } 611 }
612 } 612 }
613 613
614 if (blocked < 0) { 614 if (blocked < 0) {
615 blocked = vdp_control_port_write(v_context, value); 615 blocked = vdp_control_port_write(v_context, value);
616 } else { 616 } else {
617 blocked = 0; 617 blocked = 0;
618 } 618 }
1306 } else if (region & REGION_J) { 1306 } else if (region & REGION_J) {
1307 gen->version_reg = NO_DISK | JAP; 1307 gen->version_reg = NO_DISK | JAP;
1308 } else { 1308 } else {
1309 gen->version_reg = NO_DISK | USA; 1309 gen->version_reg = NO_DISK | USA;
1310 } 1310 }
1311 1311
1312 if (region & HZ50) { 1312 if (region & HZ50) {
1313 gen->normal_clock = MCLKS_PAL; 1313 gen->normal_clock = MCLKS_PAL;
1314 gen->soft_flush_cycles = MCLKS_LINE * 262 / 3 + 2; 1314 gen->soft_flush_cycles = MCLKS_LINE * 262 / 3 + 2;
1315 } else { 1315 } else {
1316 gen->normal_clock = MCLKS_NTSC; 1316 gen->normal_clock = MCLKS_NTSC;
1512 ym_free(gen->ym); 1512 ym_free(gen->ym);
1513 psg_free(gen->psg); 1513 psg_free(gen->psg);
1514 free(gen->header.save_dir); 1514 free(gen->header.save_dir);
1515 free_rom_info(&gen->header.info); 1515 free_rom_info(&gen->header.info);
1516 free(gen->lock_on); 1516 free(gen->lock_on);
1517 if (gen->save_type != SAVE_NONE && gen->mapper_type != MAPPER_SEGA_MED_V2) {
1518 free(gen->save_storage);
1519 }
1517 free(gen); 1520 free(gen);
1518 } 1521 }
1519 1522
1520 static void gamepad_down(system_header *system, uint8_t gamepad_num, uint8_t button) 1523 static void gamepad_down(system_header *system, uint8_t gamepad_num, uint8_t button)
1521 { 1524 {
1576 char *config_gain; 1579 char *config_gain;
1577 config_gain = tern_find_path(config, "audio\0psg_gain\0", TVAL_PTR).ptrval; 1580 config_gain = tern_find_path(config, "audio\0psg_gain\0", TVAL_PTR).ptrval;
1578 render_audio_source_gaindb(gen->psg->audio, config_gain ? atof(config_gain) : 0.0f); 1581 render_audio_source_gaindb(gen->psg->audio, config_gain ? atof(config_gain) : 0.0f);
1579 config_gain = tern_find_path(config, "audio\0fm_gain\0", TVAL_PTR).ptrval; 1582 config_gain = tern_find_path(config, "audio\0fm_gain\0", TVAL_PTR).ptrval;
1580 render_audio_source_gaindb(gen->ym->audio, config_gain ? atof(config_gain) : 0.0f); 1583 render_audio_source_gaindb(gen->ym->audio, config_gain ? atof(config_gain) : 0.0f);
1581 1584
1582 char *config_dac = tern_find_path_default(config, "audio\0fm_dac\0", (tern_val){.ptrval="zero_offset"}, TVAL_PTR).ptrval; 1585 char *config_dac = tern_find_path_default(config, "audio\0fm_dac\0", (tern_val){.ptrval="zero_offset"}, TVAL_PTR).ptrval;
1583 ym_enable_zero_offset(gen->ym, !strcmp(config_dac, "zero_offset")); 1586 ym_enable_zero_offset(gen->ym, !strcmp(config_dac, "zero_offset"));
1584 } 1587 }
1585 1588
1586 static void config_updated(system_header *system) 1589 static void config_updated(system_header *system)
1619 m68k_context *m68k = context; 1622 m68k_context *m68k = context;
1620 genesis_context *gen = m68k->system; 1623 genesis_context *gen = m68k->system;
1621 if (gen->tmss) { 1624 if (gen->tmss) {
1622 return gen->tmss_write_16(address, context, value); 1625 return gen->tmss_write_16(address, context, value);
1623 } 1626 }
1624 1627
1625 return context; 1628 return context;
1626 } 1629 }
1627 1630
1628 static void *tmss_rom_write_8(uint32_t address, void *context, uint8_t value) 1631 static void *tmss_rom_write_8(uint32_t address, void *context, uint8_t value)
1629 { 1632 {
1630 m68k_context *m68k = context; 1633 m68k_context *m68k = context;
1631 genesis_context *gen = m68k->system; 1634 genesis_context *gen = m68k->system;
1632 if (gen->tmss) { 1635 if (gen->tmss) {
1633 return gen->tmss_write_8(address, context, value); 1636 return gen->tmss_write_8(address, context, value);
1634 } 1637 }
1635 1638
1636 return context; 1639 return context;
1637 } 1640 }
1638 1641
1639 static uint16_t tmss_rom_read_16(uint32_t address, void *context) 1642 static uint16_t tmss_rom_read_16(uint32_t address, void *context)
1640 { 1643 {
1668 address += gen->tmss_write_offset; 1671 address += gen->tmss_write_offset;
1669 uint16_t *dest = get_native_pointer(address, (void **)m68k->mem_pointers, &m68k->options->gen); 1672 uint16_t *dest = get_native_pointer(address, (void **)m68k->mem_pointers, &m68k->options->gen);
1670 *dest = value; 1673 *dest = value;
1671 m68k_handle_code_write(address, m68k); 1674 m68k_handle_code_write(address, m68k);
1672 } 1675 }
1673 1676
1674 return context; 1677 return context;
1675 } 1678 }
1676 1679
1677 static void *tmss_word_write_8(uint32_t address, void *context, uint8_t value) 1680 static void *tmss_word_write_8(uint32_t address, void *context, uint8_t value)
1678 { 1681 {
1686 #else 1689 #else
1687 dest[address & 1 ^ 1] = value; 1690 dest[address & 1 ^ 1] = value;
1688 #endif 1691 #endif
1689 m68k_handle_code_write(address & ~1, m68k); 1692 m68k_handle_code_write(address & ~1, m68k);
1690 } 1693 }
1691 1694
1692 return context; 1695 return context;
1693 } 1696 }
1694 1697
1695 static void *tmss_odd_write_16(uint32_t address, void *context, uint16_t value) 1698 static void *tmss_odd_write_16(uint32_t address, void *context, uint16_t value)
1696 { 1699 {
1795 gen->frame_end = vdp_cycles_to_frame_end(gen->vdp); 1798 gen->frame_end = vdp_cycles_to_frame_end(gen->vdp);
1796 char * config_cycles = tern_find_path(config, "clocks\0max_cycles\0", TVAL_PTR).ptrval; 1799 char * config_cycles = tern_find_path(config, "clocks\0max_cycles\0", TVAL_PTR).ptrval;
1797 gen->max_cycles = config_cycles ? atoi(config_cycles) : DEFAULT_SYNC_INTERVAL; 1800 gen->max_cycles = config_cycles ? atoi(config_cycles) : DEFAULT_SYNC_INTERVAL;
1798 gen->int_latency_prev1 = MCLKS_PER_68K * 32; 1801 gen->int_latency_prev1 = MCLKS_PER_68K * 32;
1799 gen->int_latency_prev2 = MCLKS_PER_68K * 16; 1802 gen->int_latency_prev2 = MCLKS_PER_68K * 16;
1800 1803
1801 render_set_video_standard((gen->version_reg & HZ50) ? VID_PAL : VID_NTSC); 1804 render_set_video_standard((gen->version_reg & HZ50) ? VID_PAL : VID_NTSC);
1802 event_system_start(SYSTEM_GENESIS, (gen->version_reg & HZ50) ? VID_PAL : VID_NTSC, rom->name); 1805 event_system_start(SYSTEM_GENESIS, (gen->version_reg & HZ50) ? VID_PAL : VID_NTSC, rom->name);
1803 1806
1804 gen->ym = malloc(sizeof(ym2612_context)); 1807 gen->ym = malloc(sizeof(ym2612_context));
1805 char *fm = tern_find_ptr_default(model, "fm", "discrete 2612"); 1808 char *fm = tern_find_ptr_default(model, "fm", "discrete 2612");
1806 if (!strcmp(fm + strlen(fm) -4, "3834")) { 1809 if (!strcmp(fm + strlen(fm) -4, "3834")) {
1807 system_opts |= YM_OPT_3834; 1810 system_opts |= YM_OPT_3834;
1808 } 1811 }
1809 ym_init(gen->ym, gen->master_clock, MCLKS_PER_YM, system_opts); 1812 ym_init(gen->ym, gen->master_clock, MCLKS_PER_YM, system_opts);
1810 1813
1811 gen->psg = malloc(sizeof(psg_context)); 1814 gen->psg = malloc(sizeof(psg_context));
1812 psg_init(gen->psg, gen->master_clock, MCLKS_PER_PSG); 1815 psg_init(gen->psg, gen->master_clock, MCLKS_PER_PSG);
1813 1816
1814 set_audio_config(gen); 1817 set_audio_config(gen);
1815 1818
1816 z80_map[0].buffer = gen->zram = calloc(1, Z80_RAM_BYTES); 1819 z80_map[0].buffer = gen->zram = calloc(1, Z80_RAM_BYTES);
1817 #ifndef NO_Z80 1820 #ifndef NO_Z80
1818 z80_options *z_opts = malloc(sizeof(z80_options)); 1821 z80_options *z_opts = malloc(sizeof(z80_options));
1879 //nor_flash_init(&gen->nor, gen->save_storage, gen->save_size, rom->save_page_size, rom->save_product_id, rom->save_bus); 1882 //nor_flash_init(&gen->nor, gen->save_storage, gen->save_size, rom->save_page_size, rom->save_product_id, rom->save_bus);
1880 } 1883 }
1881 } else { 1884 } else {
1882 gen->save_storage = NULL; 1885 gen->save_storage = NULL;
1883 } 1886 }
1884 1887
1885 gen->mapper_start_index = rom->mapper_start_index; 1888 gen->mapper_start_index = rom->mapper_start_index;
1886 1889
1887 //This must happen before we generate memory access functions in init_m68k_opts 1890 //This must happen before we generate memory access functions in init_m68k_opts
1888 uint8_t next_ptr_index = 0; 1891 uint8_t next_ptr_index = 0;
1889 uint32_t tmss_min_alloc = 16 * 1024; 1892 uint32_t tmss_min_alloc = 16 * 1024;
1890 for (int i = 0; i < rom->map_chunks; i++) 1893 for (int i = 0; i < rom->map_chunks; i++)
1891 { 1894 {
2029 opts->gen.flags |= M68K_OPT_BROKEN_READ_MODIFY; 2032 opts->gen.flags |= M68K_OPT_BROKEN_READ_MODIFY;
2030 } 2033 }
2031 gen->m68k = init_68k_context(opts, NULL); 2034 gen->m68k = init_68k_context(opts, NULL);
2032 gen->m68k->system = gen; 2035 gen->m68k->system = gen;
2033 opts->address_log = (system_opts & OPT_ADDRESS_LOG) ? fopen("address.log", "w") : NULL; 2036 opts->address_log = (system_opts & OPT_ADDRESS_LOG) ? fopen("address.log", "w") : NULL;
2034 2037
2035 //This must happen after the 68K context has been allocated 2038 //This must happen after the 68K context has been allocated
2036 for (int i = 0; i < rom->map_chunks; i++) 2039 for (int i = 0; i < rom->map_chunks; i++)
2037 { 2040 {
2038 if (rom->map[i].flags & MMAP_PTR_IDX) { 2041 if (rom->map[i].flags & MMAP_PTR_IDX) {
2039 gen->m68k->mem_pointers[rom->map[i].ptr_index] = rom->map[i].buffer; 2042 gen->m68k->mem_pointers[rom->map[i].ptr_index] = rom->map[i].buffer;
2040 } 2043 }
2041 } 2044 }
2042 2045
2043 if (gen->mapper_type == MAPPER_SEGA) { 2046 if (gen->mapper_type == MAPPER_SEGA) {
2044 //initialize bank registers 2047 //initialize bank registers
2045 for (int i = 1; i < sizeof(gen->bank_regs); i++) 2048 for (int i = 1; i < sizeof(gen->bank_regs); i++)
2046 { 2049 {
2047 gen->bank_regs[i] = i; 2050 gen->bank_regs[i] = i;