trunk/src/mess/machine/c64.c
| r18259 | r18260 | |
| 41 | 41 | |
| 42 | 42 | #define log_cart 0 |
| 43 | 43 | |
| 44 | | /* expansion port lines input */ |
| 45 | | |
| 46 | | /* cpu port */ |
| 47 | | |
| 48 | | |
| 49 | | |
| 50 | | static void c64_nmi( running_machine &machine ) |
| 51 | | { |
| 52 | | legacy_c64_state *state = machine.driver_data<legacy_c64_state>(); |
| 53 | | device_t *cia_1 = machine.device("cia_1"); |
| 54 | | int cia1irq = mos6526_irq_r(cia_1); |
| 55 | | |
| 56 | | if (state->m_nmilevel != (machine.root_device().ioport("SPECIAL")->read() & 0x80) || cia1irq) /* KEY_RESTORE */ |
| 57 | | { |
| 58 | | machine.device("maincpu")->execute().set_input_line(INPUT_LINE_NMI, (machine.root_device().ioport("SPECIAL")->read() & 0x80) || cia1irq); |
| 59 | | |
| 60 | | state->m_nmilevel = (machine.root_device().ioport("SPECIAL")->read() & 0x80) || cia1irq; |
| 61 | | } |
| 62 | | } |
| 63 | | |
| 64 | | |
| 65 | | /*********************************************** |
| 66 | | |
| 67 | | CIA Interfaces |
| 68 | | |
| 69 | | ***********************************************/ |
| 70 | | |
| 71 | | /* |
| 72 | | * CIA 0 - Port A keyboard line select |
| 73 | | * CIA 0 - Port B keyboard line read |
| 74 | | * |
| 75 | | * flag cassette read input, serial request in |
| 76 | | * irq to irq connected |
| 77 | | * |
| 78 | | * see machine/cbm.c |
| 79 | | */ |
| 80 | | |
| 81 | | READ8_MEMBER(legacy_c64_state::c64_cia0_port_a_r) |
| 82 | | { |
| 83 | | UINT8 cia0portb = mos6526_pb_r(machine().device("cia_0"), space, 0); |
| 84 | | |
| 85 | | return cbm_common_cia0_port_a_r(machine().device("cia_0"), cia0portb); |
| 86 | | } |
| 87 | | |
| 88 | | READ8_MEMBER(legacy_c64_state::c64_cia0_port_b_r) |
| 89 | | { |
| 90 | | UINT8 cia0porta = mos6526_pa_r(machine().device("cia_0"), space, 0); |
| 91 | | |
| 92 | | return cbm_common_cia0_port_b_r(machine().device("cia_0"), cia0porta); |
| 93 | | } |
| 94 | | |
| 95 | | WRITE8_MEMBER(legacy_c64_state::c64_cia0_port_b_w) |
| 96 | | { |
| 97 | | device_t *vic2 = machine().device("vic2"); |
| 98 | | vic2_lightpen_write(vic2, data & 0x10); |
| 99 | | } |
| 100 | | |
| 101 | | static void c64_irq( running_machine &machine, int level ) |
| 102 | | { |
| 103 | | legacy_c64_state *state = machine.driver_data<legacy_c64_state>(); |
| 104 | | if (level != state->m_old_level) |
| 105 | | { |
| 106 | | DBG_LOG(machine, 3, "mos6510", ("irq %s\n", level ? "start" : "end")); |
| 107 | | machine.device("maincpu")->execute().set_input_line(M6510_IRQ_LINE, level); |
| 108 | | state->m_old_level = level; |
| 109 | | } |
| 110 | | } |
| 111 | | |
| 112 | | static void c64_cia0_interrupt( device_t *device, int level ) |
| 113 | | { |
| 114 | | legacy_c64_state *state = device->machine().driver_data<legacy_c64_state>(); |
| 115 | | c64_irq (device->machine(), level || state->m_vicirq); |
| 116 | | } |
| 117 | | |
| 118 | | WRITE_LINE_MEMBER( legacy_c64_state::c64_vic_interrupt ) |
| 119 | | { |
| 120 | | device_t *cia_0 = machine().device("cia_0"); |
| 121 | | #if 1 |
| 122 | | if (state != m_vicirq) |
| 123 | | { |
| 124 | | c64_irq(machine(), state || mos6526_irq_r(cia_0)); |
| 125 | | m_vicirq = state; |
| 126 | | } |
| 127 | | #endif |
| 128 | | } |
| 129 | | |
| 130 | | const mos6526_interface c64_ntsc_cia0 = |
| 131 | | { |
| 132 | | DEVCB_LINE(c64_cia0_interrupt), |
| 133 | | DEVCB_NULL, /* pc_func */ |
| 134 | | DEVCB_NULL, |
| 135 | | DEVCB_NULL, |
| 136 | | DEVCB_DRIVER_MEMBER(legacy_c64_state,c64_cia0_port_a_r), |
| 137 | | DEVCB_NULL, |
| 138 | | DEVCB_DRIVER_MEMBER(legacy_c64_state,c64_cia0_port_b_r), |
| 139 | | DEVCB_DRIVER_MEMBER(legacy_c64_state,c64_cia0_port_b_w) |
| 140 | | }; |
| 141 | | |
| 142 | | const mos6526_interface c64_pal_cia0 = |
| 143 | | { |
| 144 | | DEVCB_LINE(c64_cia0_interrupt), |
| 145 | | DEVCB_NULL, /* pc_func */ |
| 146 | | DEVCB_NULL, |
| 147 | | DEVCB_NULL, |
| 148 | | DEVCB_DRIVER_MEMBER(legacy_c64_state,c64_cia0_port_a_r), |
| 149 | | DEVCB_NULL, |
| 150 | | DEVCB_DRIVER_MEMBER(legacy_c64_state,c64_cia0_port_b_r), |
| 151 | | DEVCB_DRIVER_MEMBER(legacy_c64_state,c64_cia0_port_b_w) |
| 152 | | }; |
| 153 | | |
| 154 | | |
| 155 | | /* |
| 156 | | * CIA 1 - Port A |
| 157 | | * bit 7 serial bus data input |
| 158 | | * bit 6 serial bus clock input |
| 159 | | * bit 5 serial bus data output |
| 160 | | * bit 4 serial bus clock output |
| 161 | | * bit 3 serial bus atn output |
| 162 | | * bit 2 rs232 data output |
| 163 | | * bits 1-0 vic-chip system memory bank select |
| 164 | | * |
| 165 | | * CIA 1 - Port B |
| 166 | | * bit 7 user rs232 data set ready |
| 167 | | * bit 6 user rs232 clear to send |
| 168 | | * bit 5 user |
| 169 | | * bit 4 user rs232 carrier detect |
| 170 | | * bit 3 user rs232 ring indicator |
| 171 | | * bit 2 user rs232 data terminal ready |
| 172 | | * bit 1 user rs232 request to send |
| 173 | | * bit 0 user rs232 received data |
| 174 | | * |
| 175 | | * flag restore key or rs232 received data input |
| 176 | | * irq to nmi connected ? |
| 177 | | */ |
| 178 | | READ8_MEMBER(legacy_c64_state::c64_cia1_port_a_r) |
| 179 | | { |
| 180 | | UINT8 value = 0xff; |
| 181 | | |
| 182 | | if (!m_iec->clk_r()) |
| 183 | | value &= ~0x40; |
| 184 | | |
| 185 | | if (!m_iec->data_r()) |
| 186 | | value &= ~0x80; |
| 187 | | |
| 188 | | return value; |
| 189 | | } |
| 190 | | |
| 191 | | WRITE8_MEMBER(legacy_c64_state::c64_cia1_port_a_w) |
| 192 | | { |
| 193 | | static const int helper[4] = {0xc000, 0x8000, 0x4000, 0x0000}; |
| 194 | | |
| 195 | | m_iec->clk_w(!(data & 0x10)); |
| 196 | | m_iec->data_w(!(data & 0x20)); |
| 197 | | m_iec->atn_w(!(data & 0x08)); |
| 198 | | m_vicaddr = m_memory + helper[data & 0x03]; |
| 199 | | } |
| 200 | | |
| 201 | | static void c64_cia1_interrupt( device_t *device, int level ) |
| 202 | | { |
| 203 | | c64_nmi(device->machine()); |
| 204 | | } |
| 205 | | |
| 206 | | const mos6526_interface c64_ntsc_cia1 = |
| 207 | | { |
| 208 | | DEVCB_LINE(c64_cia1_interrupt), |
| 209 | | DEVCB_NULL, /* pc_func */ |
| 210 | | DEVCB_NULL, |
| 211 | | DEVCB_NULL, |
| 212 | | DEVCB_DRIVER_MEMBER(legacy_c64_state,c64_cia1_port_a_r), |
| 213 | | DEVCB_DRIVER_MEMBER(legacy_c64_state,c64_cia1_port_a_w), |
| 214 | | DEVCB_NULL, |
| 215 | | DEVCB_NULL |
| 216 | | }; |
| 217 | | |
| 218 | | const mos6526_interface c64_pal_cia1 = |
| 219 | | { |
| 220 | | DEVCB_LINE(c64_cia1_interrupt), |
| 221 | | DEVCB_NULL, /* pc_func */ |
| 222 | | DEVCB_NULL, |
| 223 | | DEVCB_NULL, |
| 224 | | DEVCB_DRIVER_MEMBER(legacy_c64_state,c64_cia1_port_a_r), |
| 225 | | DEVCB_DRIVER_MEMBER(legacy_c64_state,c64_cia1_port_a_w), |
| 226 | | DEVCB_NULL, |
| 227 | | DEVCB_NULL |
| 228 | | }; |
| 229 | | |
| 230 | | /*********************************************** |
| 231 | | |
| 232 | | Memory Handlers |
| 233 | | |
| 234 | | ***********************************************/ |
| 235 | | |
| 236 | | WRITE8_HANDLER( c64_roml_w ) |
| 237 | | { |
| 238 | | legacy_c64_state *state = space.machine().driver_data<legacy_c64_state>(); |
| 239 | | |
| 240 | | state->m_memory[offset + 0x8000] = data; |
| 241 | | |
| 242 | | if (state->m_roml_writable) |
| 243 | | state->m_roml[offset] = data; |
| 244 | | } |
| 245 | | |
| 246 | | WRITE8_HANDLER( c64_write_io ) |
| 247 | | { |
| 248 | | legacy_c64_state *state = space.machine().driver_data<legacy_c64_state>(); |
| 249 | | device_t *cia_0 = space.machine().device("cia_0"); |
| 250 | | device_t *cia_1 = space.machine().device("cia_1"); |
| 251 | | sid6581_device *sid = space.machine().device<sid6581_device>("sid6581"); |
| 252 | | device_t *vic2 = space.machine().device("vic2"); |
| 253 | | |
| 254 | | state->m_io_mirror[offset] = data; |
| 255 | | if (offset < 0x400) |
| 256 | | vic2_port_w(vic2, space, offset & 0x3ff, data); |
| 257 | | else if (offset < 0x800) |
| 258 | | sid->write(space, offset & 0x3ff, data); |
| 259 | | else if (offset < 0xc00) |
| 260 | | state->m_colorram[offset & 0x3ff] = data | 0xf0; |
| 261 | | else if (offset < 0xd00) |
| 262 | | mos6526_w(cia_0, space, offset, data); |
| 263 | | else if (offset < 0xe00) |
| 264 | | { |
| 265 | | if (state->m_cia1_on) |
| 266 | | mos6526_w(cia_1, space, offset, data); |
| 267 | | else |
| 268 | | DBG_LOG(space.machine(), 1, "io write", ("%.3x %.2x\n", offset, data)); |
| 269 | | } |
| 270 | | else if (offset < 0xf00) |
| 271 | | DBG_LOG(space.machine(), 1, "io write", ("%.3x %.2x\n", offset, data)); /* i/o 1 */ |
| 272 | | else |
| 273 | | DBG_LOG(space.machine(), 1, "io write", ("%.3x %.2x\n", offset, data)); /* i/o 2 */ |
| 274 | | } |
| 275 | | |
| 276 | | WRITE8_HANDLER( c64_ioarea_w ) |
| 277 | | { |
| 278 | | legacy_c64_state *state = space.machine().driver_data<legacy_c64_state>(); |
| 279 | | if (state->m_io_enabled) |
| 280 | | c64_write_io(space, offset, data); |
| 281 | | else |
| 282 | | state->m_io_ram_w_ptr[offset] = data; |
| 283 | | } |
| 284 | | |
| 285 | | READ8_HANDLER( c64_read_io ) |
| 286 | | { |
| 287 | | legacy_c64_state *state = space.machine().driver_data<legacy_c64_state>(); |
| 288 | | device_t *cia_0 = space.machine().device("cia_0"); |
| 289 | | device_t *cia_1 = space.machine().device("cia_1"); |
| 290 | | sid6581_device *sid = space.machine().device<sid6581_device>("sid6581"); |
| 291 | | device_t *vic2 = space.machine().device("vic2"); |
| 292 | | |
| 293 | | if (offset < 0x400) |
| 294 | | return vic2_port_r(vic2, space, offset & 0x3ff); |
| 295 | | |
| 296 | | else if (offset < 0x800) |
| 297 | | return sid->read(space, offset & 0x3ff); |
| 298 | | |
| 299 | | else if (offset < 0xc00) |
| 300 | | return state->m_colorram[offset & 0x3ff]; |
| 301 | | |
| 302 | | else if (offset < 0xd00) |
| 303 | | { |
| 304 | | if (offset & 1) |
| 305 | | cia_set_port_mask_value(cia_0, 1, space.machine().root_device().ioport("CTRLSEL")->read() & 0x80 ? c64_keyline[9] : c64_keyline[8] ); |
| 306 | | else |
| 307 | | cia_set_port_mask_value(cia_0, 0, state->ioport("CTRLSEL")->read() & 0x80 ? c64_keyline[8] : c64_keyline[9] ); |
| 308 | | |
| 309 | | return mos6526_r(cia_0, space, offset); |
| 310 | | } |
| 311 | | |
| 312 | | else if (state->m_cia1_on && (offset < 0xe00)) |
| 313 | | return mos6526_r(cia_1, space, offset); |
| 314 | | |
| 315 | | DBG_LOG(space.machine(), 1, "io read", ("%.3x\n", offset)); |
| 316 | | |
| 317 | | return 0xff; |
| 318 | | } |
| 319 | | |
| 320 | | READ8_HANDLER( c64_ioarea_r ) |
| 321 | | { |
| 322 | | legacy_c64_state *state = space.machine().driver_data<legacy_c64_state>(); |
| 323 | | return state->m_io_enabled ? c64_read_io(space, offset) : state->m_io_ram_r_ptr[offset]; |
| 324 | | } |
| 325 | | |
| 326 | | |
| 327 | 44 | /* Info from http://unusedino.de/ec64/technical/misc/c64/64doc.html */ |
| 328 | 45 | /* |
| 329 | 46 | |
| r18259 | r18260 | |
| 653 | 370 | state->m_colorram[offset & 0x3ff] = data | 0xf0; |
| 654 | 371 | } |
| 655 | 372 | |
| 656 | | TIMER_CALLBACK( c64_tape_timer ) |
| 657 | | { |
| 658 | | double tmp = machine.device<cassette_image_device>(CASSETTE_TAG)->input(); |
| 659 | | device_t *cia_0 = machine.device("cia_0"); |
| 660 | | |
| 661 | | mos6526_flag_w(cia_0, tmp > +0.0); |
| 662 | | } |
| 663 | | |
| 664 | | static void c64_common_driver_init( running_machine &machine ) |
| 665 | | { |
| 666 | | legacy_c64_state *state = machine.driver_data<legacy_c64_state>(); |
| 667 | | cbm_common_init(); |
| 668 | | state->m_game = 1; |
| 669 | | state->m_exrom = 1; |
| 670 | | state->m_old_data = -1; |
| 671 | | |
| 672 | | if (!state->m_ultimax) |
| 673 | | { |
| 674 | | UINT8 *mem = state->memregion("maincpu")->base(); |
| 675 | | state->m_basic = mem + 0x10000; |
| 676 | | state->m_kernal = mem + 0x12000; |
| 677 | | state->m_chargen = mem + 0x14000; |
| 678 | | state->m_colorram = mem + 0x15000; |
| 679 | | state->m_c64_roml = mem + 0x15400; |
| 680 | | state->m_c64_romh = mem + 0x17400; |
| 681 | | } |
| 682 | | |
| 683 | | if (state->m_tape_on) |
| 684 | | state->m_datasette_timer = machine.scheduler().timer_alloc(FUNC(c64_tape_timer)); |
| 685 | | |
| 686 | | // "cyberload" tape loader check the e000-ffff ram; the init ram need to return different value |
| 687 | | { |
| 688 | | int i; |
| 689 | | for (i = 0; i < 0x2000; i += 0x40) |
| 690 | | memset(state->m_memory + (0xe000 + i), ((i & 0x40) >> 6) * 0xff, 0x40); |
| 691 | | } |
| 692 | | } |
| 693 | | |
| 694 | | DRIVER_INIT_MEMBER(legacy_c64_state,c64) |
| 695 | | { |
| 696 | | m_ultimax = 0; |
| 697 | | m_is_sx64 = 0; |
| 698 | | m_pal = 0; |
| 699 | | m_cia1_on = 1; |
| 700 | | m_tape_on = 1; |
| 701 | | c64_common_driver_init(machine()); |
| 702 | | } |
| 703 | | |
| 704 | | DRIVER_INIT_MEMBER(legacy_c64_state,c64pal) |
| 705 | | { |
| 706 | | m_ultimax = 0; |
| 707 | | m_is_sx64 = 0; |
| 708 | | m_pal = 1; |
| 709 | | m_cia1_on = 1; |
| 710 | | m_tape_on = 1; |
| 711 | | c64_common_driver_init(machine()); |
| 712 | | } |
| 713 | | |
| 714 | | DRIVER_INIT_MEMBER(legacy_c64_state,ultimax) |
| 715 | | { |
| 716 | | m_ultimax = 1; |
| 717 | | m_is_sx64 = 0; |
| 718 | | m_pal = 0; |
| 719 | | m_cia1_on = 0; |
| 720 | | m_tape_on = 1; |
| 721 | | c64_common_driver_init(machine()); |
| 722 | | } |
| 723 | | |
| 724 | | DRIVER_INIT_MEMBER(legacy_c64_state,c64gs) |
| 725 | | { |
| 726 | | m_ultimax = 0; |
| 727 | | m_is_sx64 = 0; |
| 728 | | m_pal = 1; |
| 729 | | m_cia1_on = 1; |
| 730 | | m_tape_on = 0; |
| 731 | | c64_common_driver_init(machine()); |
| 732 | | } |
| 733 | | |
| 734 | | DRIVER_INIT_MEMBER(legacy_c64_state,sx64) |
| 735 | | { |
| 736 | | m_ultimax = 0; |
| 737 | | m_is_sx64 = 1; |
| 738 | | m_pal = 1; |
| 739 | | m_cia1_on = 1; |
| 740 | | m_tape_on = 0; |
| 741 | | c64_common_driver_init(machine()); |
| 742 | | } |
| 743 | | |
| 744 | | MACHINE_START( c64 ) |
| 745 | | { |
| 746 | | legacy_c64_state *state = machine.driver_data<legacy_c64_state>(); |
| 747 | | state->m_port_data = 0x17; |
| 748 | | |
| 749 | | state->m_io_mirror = auto_alloc_array(machine, UINT8, 0x1000); |
| 750 | | state->m_io_enabled = 0; |
| 751 | | |
| 752 | | state->m_vicaddr = state->m_memory; |
| 753 | | state->m_vicirq = 0; |
| 754 | | |
| 755 | | if (!state->m_ultimax) |
| 756 | | c64_bankswitch(machine, 1); |
| 757 | | } |
| 758 | | |
| 759 | | INTERRUPT_GEN_MEMBER(legacy_c64_state::c64_frame_interrupt) |
| 760 | | { |
| 761 | | c64_nmi(machine()); |
| 762 | | cbm_common_interrupt(&device); |
| 763 | | } |
| 764 | | |
| 765 | | |
| 766 | 373 | /*********************************************** |
| 767 | 374 | |
| 768 | 375 | C64 Cartridges |
| r18259 | r18260 | |
| 1573 | 1180 | |
| 1574 | 1181 | return result; |
| 1575 | 1182 | } |
| 1576 | | |
| 1577 | | static DEVICE_IMAGE_LOAD( max_cart ) |
| 1578 | | { |
| 1579 | | legacy_c64_state *state = image.device().machine().driver_data<legacy_c64_state>(); |
| 1580 | | int result = IMAGE_INIT_PASS; |
| 1581 | | |
| 1582 | | if (image.software_entry() != NULL) |
| 1583 | | { |
| 1584 | | UINT32 size; |
| 1585 | | |
| 1586 | | // setup Ultimax mode |
| 1587 | | state->m_exrom = 1; |
| 1588 | | state->m_game = 0; |
| 1589 | | |
| 1590 | | state->m_roml = state->m_c64_roml; |
| 1591 | | state->m_romh = state->m_c64_romh; |
| 1592 | | |
| 1593 | | memset(state->m_roml, 0, 0x2000); |
| 1594 | | memset(state->m_romh, 0, 0x2000); |
| 1595 | | |
| 1596 | | // is there anything to load at 0x8000? |
| 1597 | | size = image.get_software_region_length("roml"); |
| 1598 | | if (size) |
| 1599 | | memcpy(state->m_roml, image.get_software_region("roml"), size); |
| 1600 | | |
| 1601 | | // is there anything to load at 0xe000? |
| 1602 | | size = image.get_software_region_length("romh"); |
| 1603 | | if (size) |
| 1604 | | memcpy(state->m_romh, image.get_software_region("romh"), size); |
| 1605 | | } |
| 1606 | | else |
| 1607 | | result = c64_crt_load(image); |
| 1608 | | |
| 1609 | | return result; |
| 1610 | | } |
| 1611 | | |
| 1612 | | |
| 1613 | | /*************************************************************************** |
| 1614 | | *.CRT CARTRIDGE HANDLING |
| 1615 | | ***************************************************************************/ |
| 1616 | | |
| 1617 | | static WRITE8_HANDLER( fc3_bank_w ) |
| 1618 | | { |
| 1619 | | legacy_c64_state *state = space.machine().driver_data<legacy_c64_state>(); |
| 1620 | | // Type # 3 |
| 1621 | | // working: |
| 1622 | | // not working: |
| 1623 | | |
| 1624 | | UINT8 bank = data & 0x3f; |
| 1625 | | UINT8 *cart = state->memregion("user1")->base(); |
| 1626 | | |
| 1627 | | if (data & 0x40) |
| 1628 | | { |
| 1629 | | if (bank > 3) |
| 1630 | | logerror("Warning: This cart type should have at most 4 banks and the cart looked for bank %d... Something strange is going on!\n", bank); |
| 1631 | | else |
| 1632 | | { |
| 1633 | | memcpy(state->m_roml, cart + bank * 0x4000, 0x2000); |
| 1634 | | memcpy(state->m_romh, cart + bank * 0x4000 + 0x2000, 0x2000); |
| 1635 | | /* |
| 1636 | | if (log_cart) |
| 1637 | | { |
| 1638 | | logerror("bank %d of size %d successfully loaded at %d!\n", bank, state->m_cart.bank[bank].size, state->m_cart.bank[bank].addr); |
| 1639 | | if (state->m_cart.bank[bank].index != bank) |
| 1640 | | logerror("Warning: According to the CHIP info this should be bank %d, but we are loading it as bank %d!\n", state->m_cart.bank[bank].index, bank); |
| 1641 | | } |
| 1642 | | */ |
| 1643 | | } |
| 1644 | | } |
| 1645 | | } |
| 1646 | | |
| 1647 | | static WRITE8_HANDLER( ocean1_bank_w ) |
| 1648 | | { |
| 1649 | | legacy_c64_state *state = space.machine().driver_data<legacy_c64_state>(); |
| 1650 | | // Type # 5 |
| 1651 | | // working: Double Dragon, Ghostbusters, Terminator 2 |
| 1652 | | // not working: Pang, Robocop 2, Toki |
| 1653 | | |
| 1654 | | UINT8 bank = data & 0x3f; |
| 1655 | | UINT8 *cart = state->memregion("user1")->base(); |
| 1656 | | |
| 1657 | | switch (state->m_cart.bank[bank].addr) |
| 1658 | | { |
| 1659 | | case 0x8000: |
| 1660 | | memcpy(state->m_roml, cart + bank * 0x2000, state->m_cart.bank[bank].size); |
| 1661 | | break; |
| 1662 | | case 0xa000: |
| 1663 | | memcpy(state->m_roml + 0x2000, cart + bank * 0x2000, state->m_cart.bank[bank].size); |
| 1664 | | break; |
| 1665 | | case 0xe000: |
| 1666 | | memcpy(state->m_romh, cart + bank * 0x2000, state->m_cart.bank[bank].size); |
| 1667 | | break; |
| 1668 | | default: |
| 1669 | | logerror("Unexpected loading address (%x) for bank %x\n", state->m_cart.bank[bank].addr, bank); |
| 1670 | | break; |
| 1671 | | } |
| 1672 | | /* |
| 1673 | | if (log_cart) |
| 1674 | | { |
| 1675 | | logerror("bank %d of size %d successfully loaded at %d!\n", bank, state->m_cart.bank[bank].size, state->m_cart.bank[bank].addr); |
| 1676 | | if (state->m_cart.bank[bank].index != bank) |
| 1677 | | logerror("Warning: According to the CHIP info this should be bank %d, but we are loading it as bank %d!\n", state->m_cart.bank[bank].index, bank); |
| 1678 | | } |
| 1679 | | */ |
| 1680 | | } |
| 1681 | | |
| 1682 | | static WRITE8_HANDLER( funplay_bank_w ) |
| 1683 | | { |
| 1684 | | legacy_c64_state *state = space.machine().driver_data<legacy_c64_state>(); |
| 1685 | | // Type # 7 |
| 1686 | | // working: |
| 1687 | | // not working: |
| 1688 | | |
| 1689 | | UINT8 bank = data & 0x39, real_bank = 0; |
| 1690 | | UINT8 *cart = state->memregion("user1")->base(); |
| 1691 | | |
| 1692 | | /* This should be written after the bankswitch has happened. We log it to see if it is really working */ |
| 1693 | | if (data == 0x86) |
| 1694 | | logerror("Reserved value written\n"); |
| 1695 | | else |
| 1696 | | { |
| 1697 | | /* bank number is not the value written, but state->m_cart.bank[bank].index IS the value written! */ |
| 1698 | | real_bank = ((bank & 0x01) << 3) + ((bank & 0x38) >> 3); |
| 1699 | | |
| 1700 | | memcpy(state->m_roml, cart + real_bank * 0x2000, 0x2000); |
| 1701 | | /* |
| 1702 | | if (log_cart) |
| 1703 | | { |
| 1704 | | logerror("bank %d of size %d successfully loaded at %d!\n", bank, state->m_cart.bank[bank].size, state->m_cart.bank[bank].addr); |
| 1705 | | if (state->m_cart.bank[bank].index != bank) |
| 1706 | | logerror("Warning: According to the CHIP info this should be bank %d, but we are loading it as bank %d!\n", state->m_cart.bank[bank].index, bank); |
| 1707 | | } |
| 1708 | | */ |
| 1709 | | } |
| 1710 | | } |
| 1711 | | |
| 1712 | | static WRITE8_HANDLER( supergames_bank_w ) |
| 1713 | | { |
| 1714 | | legacy_c64_state *state = space.machine().driver_data<legacy_c64_state>(); |
| 1715 | | // Type # 8 |
| 1716 | | // working: |
| 1717 | | // not working: |
| 1718 | | |
| 1719 | | UINT8 bank = data & 0x03, bit2 = data & 0x04; |
| 1720 | | UINT8 *cart = state->memregion("user1")->base(); |
| 1721 | | |
| 1722 | | if (data & 0x04) |
| 1723 | | { |
| 1724 | | state->m_game = 0; |
| 1725 | | state->m_exrom = 0; |
| 1726 | | } |
| 1727 | | else |
| 1728 | | { |
| 1729 | | state->m_game = 0; |
| 1730 | | state->m_exrom = 0; |
| 1731 | | } |
| 1732 | | |
| 1733 | | if (data == 0xc) |
| 1734 | | { |
| 1735 | | state->m_game = 1; |
| 1736 | | state->m_exrom = 1; |
| 1737 | | } |
| 1738 | | |
| 1739 | | if (bit2) |
| 1740 | | { |
| 1741 | | memcpy(state->m_roml, cart + bank * 0x4000, 0x2000); |
| 1742 | | memcpy(state->m_romh, cart + bank * 0x4000 + 0x2000, 0x2000); |
| 1743 | | } |
| 1744 | | else |
| 1745 | | { |
| 1746 | | memcpy(state->m_roml, cart + bank * 0x4000, 0x2000); |
| 1747 | | memcpy(state->m_romh, cart + bank * 0x4000 + 0x2000, 0x2000); |
| 1748 | | } |
| 1749 | | } |
| 1750 | | |
| 1751 | | static WRITE8_HANDLER( c64gs_bank_w ) |
| 1752 | | { |
| 1753 | | legacy_c64_state *state = space.machine().driver_data<legacy_c64_state>(); |
| 1754 | | // Type # 15 |
| 1755 | | // working: |
| 1756 | | // not working: The Last Ninja Remix |
| 1757 | | |
| 1758 | | UINT8 bank = offset & 0xff; |
| 1759 | | UINT8 *cart = state->memregion("user1")->base(); |
| 1760 | | |
| 1761 | | if (bank > 0x3f) |
| 1762 | | logerror("Warning: This cart type should have at most 64 banks and the cart looked for bank %d... Something strange is going on!\n", bank); |
| 1763 | | |
| 1764 | | memcpy(state->m_roml, cart + bank * 0x2000, 0x2000); |
| 1765 | | /* |
| 1766 | | if (log_cart) |
| 1767 | | { |
| 1768 | | logerror("bank %d of size %d successfully loaded at %d!\n", bank, state->m_cart.bank[bank].size, state->m_cart.bank[bank].addr); |
| 1769 | | if (state->m_cart.bank[bank].index != bank) |
| 1770 | | logerror("Warning: According to the CHIP info this should be bank %d, but we are loading it as bank %d!\n", state->m_cart.bank[bank].index, bank); |
| 1771 | | } |
| 1772 | | */ |
| 1773 | | } |
| 1774 | | |
| 1775 | | static READ8_HANDLER( dinamic_bank_r ) |
| 1776 | | { |
| 1777 | | legacy_c64_state *state = space.machine().driver_data<legacy_c64_state>(); |
| 1778 | | // Type # 17 |
| 1779 | | // working: Satan |
| 1780 | | // not working: |
| 1781 | | |
| 1782 | | UINT8 bank = offset & 0xff; |
| 1783 | | UINT8 *cart = state->memregion("user1")->base(); |
| 1784 | | |
| 1785 | | if (bank > 0xf) |
| 1786 | | logerror("Warning: This cart type should have 16 banks and the cart looked for bank %d... Something strange is going on!\n", bank); |
| 1787 | | |
| 1788 | | memcpy(state->m_roml, cart + bank * 0x2000, 0x2000); |
| 1789 | | /* |
| 1790 | | if (log_cart) |
| 1791 | | { |
| 1792 | | logerror("bank %d of size %d successfully loaded at %d!\n", bank, state->m_cart.bank[bank].size, state->m_cart.bank[bank].addr); |
| 1793 | | if (state->m_cart.bank[bank].index != bank) |
| 1794 | | logerror("Warning: According to the CHIP info this should be bank %d, but we are loading it as bank %d!\n", state->m_cart.bank[bank].index, bank); |
| 1795 | | } |
| 1796 | | */ |
| 1797 | | return 0; |
| 1798 | | } |
| 1799 | | |
| 1800 | | static READ8_HANDLER( zaxxon_bank_r ) |
| 1801 | | { |
| 1802 | | legacy_c64_state *state = space.machine().driver_data<legacy_c64_state>(); |
| 1803 | | // Type # 18 |
| 1804 | | // working: |
| 1805 | | // not working: |
| 1806 | | |
| 1807 | | UINT8 bank; |
| 1808 | | UINT8 *cart = state->memregion("user1")->base(); |
| 1809 | | |
| 1810 | | if (offset < 0x1000) |
| 1811 | | bank = 0; |
| 1812 | | else |
| 1813 | | bank = 1; |
| 1814 | | |
| 1815 | | // state->m_game = 0; |
| 1816 | | // state->m_exrom = 0; |
| 1817 | | |
| 1818 | | memcpy(state->m_romh, cart + bank * 0x2000 + 0x1000, 0x2000); |
| 1819 | | |
| 1820 | | return cart[offset & 0x0fff]; |
| 1821 | | } |
| 1822 | | |
| 1823 | | static WRITE8_HANDLER( domark_bank_w ) |
| 1824 | | { |
| 1825 | | legacy_c64_state *state = space.machine().driver_data<legacy_c64_state>(); |
| 1826 | | // Type # 19 |
| 1827 | | // working: |
| 1828 | | // not working: |
| 1829 | | |
| 1830 | | UINT8 bank = data & 0x7f; |
| 1831 | | UINT8 *cart = state->memregion("user1")->base(); |
| 1832 | | |
| 1833 | | if (data & 0x80) |
| 1834 | | { |
| 1835 | | state->m_game = 1; |
| 1836 | | state->m_exrom = 1; |
| 1837 | | } |
| 1838 | | else |
| 1839 | | { |
| 1840 | | state->m_game = 1; |
| 1841 | | state->m_exrom = 0; |
| 1842 | | memcpy(state->m_roml, cart + bank * 0x2000, 0x2000); |
| 1843 | | } |
| 1844 | | } |
| 1845 | | |
| 1846 | | static WRITE8_HANDLER( comal80_bank_w ) |
| 1847 | | { |
| 1848 | | legacy_c64_state *state = space.machine().driver_data<legacy_c64_state>(); |
| 1849 | | // Type # 21 |
| 1850 | | // working: Comal 80 |
| 1851 | | // not working: |
| 1852 | | |
| 1853 | | UINT8 bank = data & 0x83; |
| 1854 | | UINT8 *cart = state->memregion("user1")->base(); |
| 1855 | | |
| 1856 | | /* only valid values 0x80, 0x81, 0x82, 0x83 */ |
| 1857 | | if (!(bank & 0x80)) |
| 1858 | | logerror("Warning: we are writing an invalid bank value %d\n", bank); |
| 1859 | | else |
| 1860 | | { |
| 1861 | | bank &= 0x03; |
| 1862 | | |
| 1863 | | memcpy(state->m_roml, cart + bank * 0x4000, 0x4000); |
| 1864 | | /* |
| 1865 | | if (log_cart) |
| 1866 | | { |
| 1867 | | logerror("bank %d of size %d successfully loaded at %d!\n", bank, state->m_cart.bank[bank].size, state->m_cart.bank[bank].addr); |
| 1868 | | if (state->m_cart.bank[bank].index != bank) |
| 1869 | | logerror("Warning: According to the CHIP info this should be bank %d, but we are loading it as bank %d!\n", state->m_cart.bank[bank].index, bank); |
| 1870 | | } |
| 1871 | | */ |
| 1872 | | } |
| 1873 | | } |
| 1874 | | |
| 1875 | | static void setup_c64_custom_mappers(running_machine &machine) |
| 1876 | | { |
| 1877 | | legacy_c64_state *state = machine.driver_data<legacy_c64_state>(); |
| 1878 | | address_space &space = machine.device( "maincpu")->memory().space( AS_PROGRAM ); |
| 1879 | | |
| 1880 | | switch (state->m_cart.mapper) |
| 1881 | | { |
| 1882 | | case ACTION_REPLAY: /* Type # 1 not working */ |
| 1883 | | break; |
| 1884 | | case KCS_PC: /* Type # 2 not working */ |
| 1885 | | break; |
| 1886 | | case FINAL_CART_III: /* Type # 3 not working - 4 16k banks, loaded at 0x8000, banks chosen by writing to 0xdfff */ |
| 1887 | | space.install_legacy_write_handler( 0xdfff, 0xdfff, FUNC(fc3_bank_w) ); |
| 1888 | | break; |
| 1889 | | case SIMONS_BASIC: /* Type # 4 not working */ |
| 1890 | | break; |
| 1891 | | case OCEAN_1: /* Type # 5 - up to 64 8k banks, loaded at 0x8000 or 0xa000, banks chosen by writing to 0xde00 */ |
| 1892 | | space.install_legacy_write_handler( 0xde00, 0xde00, FUNC(ocean1_bank_w) ); |
| 1893 | | break; |
| 1894 | | case EXPERT: /* Type # 6 not working */ |
| 1895 | | break; |
| 1896 | | case FUN_PLAY: /* Type # 7 - 16 8k banks, loaded at 0x8000, banks chosen by writing to 0xde00 */ |
| 1897 | | space.install_legacy_write_handler( 0xde00, 0xde00, FUNC(funplay_bank_w) ); |
| 1898 | | break; |
| 1899 | | case SUPER_GAMES: /* Type # 8 not working */ |
| 1900 | | space.install_legacy_write_handler( 0xdf00, 0xdf00, FUNC(supergames_bank_w) ); |
| 1901 | | break; |
| 1902 | | case ATOMIC_POWER: /* Type # 9 not working */ |
| 1903 | | break; |
| 1904 | | case EPYX_FASTLOAD: /* Type # 10 not working */ |
| 1905 | | break; |
| 1906 | | case WESTERMANN: /* Type # 11 not working */ |
| 1907 | | break; |
| 1908 | | case REX: /* Type # 12 working */ |
| 1909 | | break; |
| 1910 | | case FINAL_CART_I: /* Type # 13 not working */ |
| 1911 | | break; |
| 1912 | | case MAGIC_FORMEL: /* Type # 14 not working */ |
| 1913 | | break; |
| 1914 | | case C64GS: /* Type # 15 - up to 64 8k banks, loaded at 0x8000, banks chosen by writing to 0xde00 + bank */ |
| 1915 | | space.install_legacy_write_handler( 0xde00, 0xdeff, FUNC(c64gs_bank_w) ); |
| 1916 | | break; |
| 1917 | | case DINAMIC: /* Type # 17 - 16 8k banks, loaded at 0x8000, banks chosen by reading to 0xde00 + bank */ |
| 1918 | | space.install_legacy_read_handler( 0xde00, 0xdeff, FUNC(dinamic_bank_r) ); |
| 1919 | | break; |
| 1920 | | case ZAXXON: /* Type # 18 */ |
| 1921 | | space.install_legacy_read_handler( 0x8000, 0x9fff, FUNC(zaxxon_bank_r) ); |
| 1922 | | break; |
| 1923 | | case DOMARK: /* Type # 19 */ |
| 1924 | | space.install_legacy_write_handler( 0xde00, 0xde00, FUNC(domark_bank_w) ); |
| 1925 | | break; |
| 1926 | | case SUPER_SNAP_5: /* Type # 20 not working */ |
| 1927 | | break; |
| 1928 | | case COMAL_80: /* Type # 21 - 4 16k banks, loaded at 0x8000, banks chosen by writing to 0xde00 */ |
| 1929 | | space.install_legacy_write_handler( 0xde00, 0xde00, FUNC(comal80_bank_w) ); |
| 1930 | | break; |
| 1931 | | case GENERIC_CRT: /* Type # 0 - single bank, no bankswitch, loaded at start with correct size and place */ |
| 1932 | | default: |
| 1933 | | break; |
| 1934 | | } |
| 1935 | | } |
| 1936 | | |
| 1937 | | |
| 1938 | | MACHINE_RESET( c64 ) |
| 1939 | | { |
| 1940 | | legacy_c64_state *state = machine.driver_data<legacy_c64_state>(); |
| 1941 | | if (state->m_cart.n_banks) |
| 1942 | | setup_c64_custom_mappers(machine); |
| 1943 | | } |
| 1944 | | |
| 1945 | | |
| 1946 | 1183 | MACHINE_CONFIG_FRAGMENT( c64_cartslot ) |
| 1947 | 1184 | MCFG_CARTSLOT_ADD("cart1") |
| 1948 | 1185 | MCFG_CARTSLOT_EXTENSION_LIST("crt,80") |
| r18259 | r18260 | |
| 1962 | 1199 | MCFG_SOFTWARE_LIST_ADD("cart_list_c64", "c64_cart") |
| 1963 | 1200 | MACHINE_CONFIG_END |
| 1964 | 1201 | |
| 1965 | | MACHINE_CONFIG_FRAGMENT( ultimax_cartslot ) |
| 1966 | | MCFG_CARTSLOT_ADD("cart") |
| 1967 | | MCFG_CARTSLOT_EXTENSION_LIST("crt,e0,f0") |
| 1968 | | MCFG_CARTSLOT_MANDATORY |
| 1969 | | MCFG_CARTSLOT_INTERFACE("ultimax_cart") |
| 1970 | | MCFG_CARTSLOT_START(c64_cart) |
| 1971 | | MCFG_CARTSLOT_LOAD(max_cart) |
| 1972 | | MCFG_CARTSLOT_UNLOAD(c64_cart) |
| 1973 | | |
| 1974 | | /* software lists */ |
| 1975 | | MCFG_SOFTWARE_LIST_ADD("cart_list","max") |
| 1976 | | MACHINE_CONFIG_END |