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 |