summaryrefslogtreecommitdiffstatshomepage
path: root/src/mess/machine/c128.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mess/machine/c128.c')
-rw-r--r--src/mess/machine/c128.c1307
1 files changed, 1307 insertions, 0 deletions
diff --git a/src/mess/machine/c128.c b/src/mess/machine/c128.c
new file mode 100644
index 00000000000..8299ba56a03
--- /dev/null
+++ b/src/mess/machine/c128.c
@@ -0,0 +1,1307 @@
+/***************************************************************************
+
+ commodore c128 home computer
+
+ peter.trauner@jk.uni-linz.ac.at
+ documentation:
+ iDOC (http://www.softwolves.pp.se/idoc)
+ Christian Janoff mepk@c64.org
+
+***************************************************************************/
+
+#include "emu.h"
+#include "includes/c128.h"
+#include "includes/c64_legacy.h"
+#include "includes/cbm.h"
+#include "machine/cbmiec.h"
+#include "cpu/m6502/m6502.h"
+#include "imagedev/cassette.h"
+#include "machine/6526cia.h"
+#include "sound/sid6581.h"
+#include "video/vic6567.h"
+#include "video/vdc8563.h"
+
+#define MMU_PAGE1 ((((state->m_mmu[10]&0xf)<<8)|state->m_mmu[9])<<8)
+#define MMU_PAGE0 ((((state->m_mmu[8]&0xf)<<8)|state->m_mmu[7])<<8)
+#define MMU_VIC_ADDR ((state->m_mmu[6]&0xc0)<<10)
+#define MMU_RAM_RCR_ADDR ((state->m_mmu[6]&0x30)<<14)
+#define MMU_SIZE (c128_mmu_helper[state->m_mmu[6]&3])
+#define MMU_BOTTOM (state->m_mmu[6]&4)
+#define MMU_TOP (state->m_mmu[6]&8)
+#define MMU_CPU8502 (state->m_mmu[5]&1) /* else z80 */
+/* fastio output (c128_mmu[5]&8) else input */
+#define MMU_FSDIR(s) ((s)->m_mmu[5]&0x08)
+#define MMU_GAME_IN (state->m_mmu[5]&0x10)
+#define MMU_EXROM_IN (state->m_mmu[5]&0x20)
+#define MMU_64MODE (state->m_mmu[5]&0x40)
+#define MMU_40_IN (state->m_mmu[5]&0x80)
+
+#define MMU_RAM_CR_ADDR ((state->m_mmu[0]&0xc0)<<10)
+#define MMU_RAM_LO (state->m_mmu[0]&2) /* else rom at 0x4000 */
+#define MMU_RAM_MID ((state->m_mmu[0]&0xc)==0xc) /* 0x8000 - 0xbfff */
+#define MMU_ROM_MID ((state->m_mmu[0]&0xc)==0)
+#define MMU_EXTERNAL_ROM_MID ((state->m_mmu[0]&0xc)==8)
+#define MMU_INTERNAL_ROM_MID ((state->m_mmu[0]&0xc)==4)
+
+#define MMU_IO_ON (!(state->m_mmu[0]&1)) /* io window at 0xd000 */
+#define MMU_ROM_HI ((state->m_mmu[0]&0x30)==0) /* rom at 0xc000 */
+#define MMU_EXTERNAL_ROM_HI ((state->m_mmu[0]&0x30)==0x20)
+#define MMU_INTERNAL_ROM_HI ((state->m_mmu[0]&0x30)==0x10)
+#define MMU_RAM_HI ((state->m_mmu[0]&0x30)==0x30)
+
+#define MMU_RAM_ADDR (MMU_RAM_RCR_ADDR|MMU_RAM_CR_ADDR)
+
+static const int c128_mmu_helper[4] =
+{0x400, 0x1000, 0x2000, 0x4000};
+
+#define VERBOSE_LEVEL 0
+#define DBG_LOG( MACHINE, N, M, A ) \
+ do { \
+ if(VERBOSE_LEVEL >= N) \
+ { \
+ if( M ) \
+ logerror("%11.6f: %-24s", MACHINE.time().as_double(), (char*) M ); \
+ logerror A; \
+ } \
+ } while (0)
+
+/*
+ two cpus share 1 memory system, only 1 cpu can run
+ controller is the mmu
+
+ mame has different memory subsystems for each cpu
+*/
+
+
+/* m8502 port
+ in c128 mode
+ bit 0 color
+ bit 1 lores
+ bit 2 hires
+ 3 textmode
+ 5 graphics (turned on ram at 0x1000 for video chip
+*/
+
+
+
+
+
+
+
+static void c128_nmi( running_machine &machine )
+{
+ c128_state *state = machine.driver_data<c128_state>();
+ device_t *cia_1 = machine.device("cia_1");
+ int cia1irq = mos6526_irq_r(cia_1);
+
+ if (state->m_nmilevel != (machine.root_device().ioport("SPECIAL")->read() & 0x80) || cia1irq) /* KEY_RESTORE */
+ {
+ if (1) // this was never valid, there is no active CPU during a timer firing! cpu_getactivecpu() == 0)
+ {
+ /* z80 */
+ cputag_set_input_line(machine, "maincpu", INPUT_LINE_NMI, (machine.root_device().ioport("SPECIAL")->read() & 0x80) || cia1irq);
+ }
+ else
+ {
+ cputag_set_input_line(machine, "m8502", INPUT_LINE_NMI, (machine.root_device().ioport("SPECIAL")->read() & 0x80) || cia1irq);
+ }
+
+ state->m_nmilevel = (machine.root_device().ioport("SPECIAL")->read() & 0x80) || cia1irq;
+ }
+}
+
+/***********************************************
+
+ CIA Interfaces
+
+***********************************************/
+
+/*
+ * CIA 0 - Port A keyboard line select
+ * CIA 0 - Port B keyboard line read
+ *
+ * flag cassette read input, serial request in
+ * irq to irq connected
+ *
+ * see machine/cbm.c
+ */
+
+static READ8_DEVICE_HANDLER( c128_cia0_port_a_r )
+{
+ UINT8 cia0portb = mos6526_pb_r(device->machine().device("cia_0"), 0);
+
+ return cbm_common_cia0_port_a_r(device, cia0portb);
+}
+
+static READ8_DEVICE_HANDLER( c128_cia0_port_b_r )
+{
+ c128_state *state = device->machine().driver_data<c128_state>();
+ UINT8 value = 0xff;
+ UINT8 cia0porta = mos6526_pa_r(device->machine().device("cia_0"), 0);
+ device_t *vic2e = device->machine().device("vic2e");
+
+ value &= cbm_common_cia0_port_b_r(device, cia0porta);
+
+ if (!vic2e_k0_r(vic2e))
+ value &= state->m_keyline[0];
+ if (!vic2e_k1_r(vic2e))
+ value &= state->m_keyline[1];
+ if (!vic2e_k2_r(vic2e))
+ value &= state->m_keyline[2];
+
+ return value;
+}
+
+static WRITE8_DEVICE_HANDLER( c128_cia0_port_b_w )
+{
+ device_t *vic2e = device->machine().device("vic2e");
+ vic2_lightpen_write(vic2e, data & 0x10);
+}
+
+static void c128_irq( running_machine &machine, int level )
+{
+ c128_state *state = machine.driver_data<c128_state>();
+ if (level != state->m_old_level)
+ {
+ DBG_LOG(machine, 3, "mos6510", ("irq %s\n", level ? "start" : "end"));
+
+ if (0) // && (cpu_getactivecpu() == 0))
+ {
+ cputag_set_input_line(machine, "maincpu", 0, level);
+ }
+ else
+ {
+ cputag_set_input_line(machine, "m8502", M6510_IRQ_LINE, level);
+ }
+
+ state->m_old_level = level;
+ }
+}
+
+static void c128_cia0_interrupt( device_t *device, int level )
+{
+ c128_state *state = device->machine().driver_data<c128_state>();
+ c128_irq(device->machine(), level || state->m_vicirq);
+}
+
+WRITE_LINE_MEMBER( c128_state::vic_interrupt )
+{
+ device_t *cia_0 = machine().device("cia_0");
+#if 1
+ if (state != m_vicirq)
+ {
+ c128_irq (machine(), state || mos6526_irq_r(cia_0));
+ m_vicirq = state;
+ }
+#endif
+}
+
+static void c128_iec_data_out_w(running_machine &machine)
+{
+ c128_state *state = machine.driver_data<c128_state>();
+ int data = !state->m_data_out;
+
+ /* fast serial data */
+ if (MMU_FSDIR(state)) data &= state->m_sp1;
+
+ state->m_iec->data_w(data);
+}
+
+static void c128_iec_srq_out_w(running_machine &machine)
+{
+ c128_state *state = machine.driver_data<c128_state>();
+ int srq = 1;
+
+ /* fast serial clock */
+ if (MMU_FSDIR(state)) srq &= state->m_cnt1;
+
+ state->m_iec->srq_w(srq);
+}
+
+static WRITE_LINE_DEVICE_HANDLER( cia0_cnt_w )
+{
+ c128_state *drvstate = device->machine().driver_data<c128_state>();
+ /* fast clock out */
+ drvstate->m_cnt1 = state;
+ c128_iec_srq_out_w(device->machine());
+}
+
+static WRITE_LINE_DEVICE_HANDLER( cia0_sp_w )
+{
+ c128_state *drvstate = device->machine().driver_data<c128_state>();
+ /* fast data out */
+ drvstate->m_sp1 = state;
+ c128_iec_data_out_w(device->machine());
+}
+
+const mos6526_interface c128_ntsc_cia0 =
+{
+ 60,
+ DEVCB_LINE(c128_cia0_interrupt),
+ DEVCB_NULL, /* pc_func */
+ DEVCB_LINE(cia0_cnt_w),
+ DEVCB_LINE(cia0_sp_w),
+ DEVCB_HANDLER(c128_cia0_port_a_r),
+ DEVCB_NULL,
+ DEVCB_HANDLER(c128_cia0_port_b_r),
+ DEVCB_HANDLER(c128_cia0_port_b_w)
+};
+
+const mos6526_interface c128_pal_cia0 =
+{
+ 50,
+ DEVCB_LINE(c128_cia0_interrupt),
+ DEVCB_NULL, /* pc_func */
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_HANDLER(c128_cia0_port_a_r),
+ DEVCB_NULL,
+ DEVCB_HANDLER(c128_cia0_port_b_r),
+ DEVCB_HANDLER(c128_cia0_port_b_w)
+};
+
+WRITE_LINE_DEVICE_HANDLER( c128_iec_srq_w )
+{
+ c128_state *drvstate = device->machine().driver_data<c128_state>();
+
+ if (!MMU_FSDIR(drvstate))
+ {
+ mos6526_flag_w(device, state);
+ mos6526_cnt_w(device, state);
+ }
+}
+
+WRITE_LINE_DEVICE_HANDLER( c128_iec_data_w )
+{
+ c128_state *drvstate = device->machine().driver_data<c128_state>();
+
+ if (!MMU_FSDIR(drvstate))
+ {
+ mos6526_sp_w(device, state);
+ }
+}
+
+/*
+ * CIA 1 - Port A
+ * bit 7 serial bus data input
+ * bit 6 serial bus clock input
+ * bit 5 serial bus data output
+ * bit 4 serial bus clock output
+ * bit 3 serial bus atn output
+ * bit 2 rs232 data output
+ * bits 1-0 vic-chip system memory bank select
+ *
+ * CIA 1 - Port B
+ * bit 7 user rs232 data set ready
+ * bit 6 user rs232 clear to send
+ * bit 5 user
+ * bit 4 user rs232 carrier detect
+ * bit 3 user rs232 ring indicator
+ * bit 2 user rs232 data terminal ready
+ * bit 1 user rs232 request to send
+ * bit 0 user rs232 received data
+ *
+ * flag restore key or rs232 received data input
+ * irq to nmi connected ?
+ */
+static READ8_DEVICE_HANDLER( c128_cia1_port_a_r )
+{
+ c128_state *state = device->machine().driver_data<c128_state>();
+ UINT8 value = 0xff;
+
+ if (!state->m_iec->clk_r())
+ value &= ~0x40;
+
+ if (!state->m_iec->data_r())
+ value &= ~0x80;
+
+ return value;
+}
+
+static WRITE8_DEVICE_HANDLER( c128_cia1_port_a_w )
+{
+ c128_state *state = device->machine().driver_data<c128_state>();
+ static const int helper[4] = {0xc000, 0x8000, 0x4000, 0x0000};
+
+ state->m_data_out = BIT(data, 5);
+ c128_iec_data_out_w(device->machine());
+
+ state->m_iec->clk_w(!BIT(data, 4));
+
+ state->m_iec->atn_w(!BIT(data, 3));
+
+ state->m_vicaddr = state->m_memory + helper[data & 0x03];
+ state->m_c128_vicaddr = state->m_memory + helper[data & 0x03] + state->m_va1617;
+}
+
+static void c128_cia1_interrupt( device_t *device, int level )
+{
+ c128_nmi(device->machine());
+}
+
+const mos6526_interface c128_ntsc_cia1 =
+{
+ 60,
+ DEVCB_LINE(c128_cia1_interrupt),
+ DEVCB_NULL, /* pc_func */
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_HANDLER(c128_cia1_port_a_r),
+ DEVCB_HANDLER(c128_cia1_port_a_w),
+ DEVCB_NULL,
+ DEVCB_NULL
+};
+
+const mos6526_interface c128_pal_cia1 =
+{
+ 50,
+ DEVCB_LINE(c128_cia1_interrupt),
+ DEVCB_NULL, /* pc_func */
+ DEVCB_NULL,
+ DEVCB_NULL,
+ DEVCB_HANDLER(c128_cia1_port_a_r),
+ DEVCB_HANDLER(c128_cia1_port_a_w),
+ DEVCB_NULL,
+ DEVCB_NULL
+};
+
+/***********************************************
+
+ Memory Handlers
+
+***********************************************/
+static WRITE8_HANDLER( c128_dma8726_port_w )
+{
+ DBG_LOG(space->machine(), 1, "dma write", ("%.3x %.2x\n",offset,data));
+}
+
+static READ8_HANDLER( c128_dma8726_port_r )
+{
+ DBG_LOG(space->machine(), 1, "dma read", ("%.3x\n",offset));
+ return 0xff;
+}
+
+WRITE8_HANDLER( c128_write_d000 )
+{
+ c128_state *state = space->machine().driver_data<c128_state>();
+ device_t *cia_0 = space->machine().device("cia_0");
+ device_t *cia_1 = space->machine().device("cia_1");
+ device_t *sid = space->machine().device("sid6581");
+ device_t *vic2e = space->machine().device("vic2e");
+ device_t *vdc8563 = space->machine().device("vdc8563");
+
+ UINT8 c64_port6510 = m6510_get_port(space->machine().device<legacy_cpu_device>("m8502"));
+
+ if (!state->m_write_io)
+ {
+ if (offset + 0xd000 >= state->m_ram_top)
+ state->m_memory[0xd000 + offset] = data;
+ else
+ state->m_ram[0xd000 + offset] = data;
+ }
+ else
+ {
+ switch ((offset&0xf00)>>8)
+ {
+ case 0:case 1: case 2: case 3:
+ vic2_port_w(vic2e, offset & 0x3ff, data);
+ break;
+ case 4:
+ sid6581_w(sid, offset & 0x3f, data);
+ break;
+ case 5:
+ c128_mmu8722_port_w(space, offset & 0xff, data);
+ break;
+ case 6:case 7:
+ vdc8563_port_w(vdc8563, offset & 0xff, data);
+ break;
+ case 8: case 9: case 0xa: case 0xb:
+ if (state->m_c64mode)
+ state->m_colorram[(offset & 0x3ff)] = data | 0xf0;
+ else
+ state->m_colorram[(offset & 0x3ff)|((c64_port6510&3)<<10)] = data | 0xf0; // maybe all 8 bit connected!
+ break;
+ case 0xc:
+ mos6526_w(cia_0, offset, data);
+ break;
+ case 0xd:
+ mos6526_w(cia_1, offset, data);
+ break;
+ case 0xf:
+ c128_dma8726_port_w(space, offset&0xff,data);
+ break;
+ case 0xe:
+ DBG_LOG(space->machine(), 1, "io write", ("%.3x %.2x\n", offset, data));
+ break;
+ }
+ }
+}
+
+
+
+static READ8_HANDLER( c128_read_io )
+{
+ c128_state *state = space->machine().driver_data<c128_state>();
+ device_t *cia_0 = space->machine().device("cia_0");
+ device_t *cia_1 = space->machine().device("cia_1");
+ device_t *sid = space->machine().device("sid6581");
+ device_t *vic2e= space->machine().device("vic2e");
+ device_t *vdc8563 = space->machine().device("vdc8563");
+
+ if (offset < 0x400)
+ return vic2_port_r(vic2e, offset & 0x3ff);
+ else if (offset < 0x500)
+ return sid6581_r(sid, offset & 0xff);
+ else if (offset < 0x600)
+ return c128_mmu8722_port_r(space, offset & 0xff);
+ else if (offset < 0x800)
+ return vdc8563_port_r(vdc8563, offset & 0xff);
+ else if (offset < 0xc00)
+ return state->m_colorram[offset & 0x3ff];
+ else if (offset == 0xc00)
+ {
+ cia_set_port_mask_value(cia_0, 0, state->ioport("CTRLSEL")->read() & 0x80 ? c64_keyline[8] : c64_keyline[9] );
+ return mos6526_r(cia_0, offset);
+ }
+ else if (offset == 0xc01)
+ {
+ cia_set_port_mask_value(cia_0, 1, space->machine().root_device().ioport("CTRLSEL")->read() & 0x80 ? c64_keyline[9] : c64_keyline[8] );
+ return mos6526_r(cia_0, offset);
+ }
+ else if (offset < 0xd00)
+ return mos6526_r(cia_0, offset);
+ else if (offset < 0xe00)
+ return mos6526_r(cia_1, offset);
+ else if ((offset >= 0xf00) & (offset <= 0xfff))
+ return c128_dma8726_port_r(space, offset&0xff);
+ DBG_LOG(space->machine(), 1, "io read", ("%.3x\n", offset));
+ return 0xff;
+}
+
+void c128_bankswitch_64( running_machine &machine, int reset )
+{
+ c128_state *state = machine.driver_data<c128_state>();
+ int data, loram, hiram, charen;
+
+ if (!state->m_c64mode)
+ return;
+
+ data = m6510_get_port(machine.device<legacy_cpu_device>("m8502")) & 0x07;
+ if ((state->m_old_data == data) && (state->m_old_exrom == state->m_exrom) && (state->m_old_game == state->m_game) && !reset)
+ return;
+
+ DBG_LOG(machine, 1, "bankswitch", ("%d\n", data & 7));
+ loram = (data & 1) ? 1 : 0;
+ hiram = (data & 2) ? 1 : 0;
+ charen = (data & 4) ? 1 : 0;
+
+ if ((!state->m_game && state->m_exrom) || (loram && hiram && !state->m_exrom))
+ state->membank("bank8")->set_base(state->m_roml);
+ else
+ state->membank("bank8")->set_base(state->m_memory + 0x8000);
+
+ if ((!state->m_game && state->m_exrom && hiram) || (!state->m_exrom))
+ state->membank("bank9")->set_base(state->m_romh);
+ else if (loram && hiram)
+ state->membank("bank9")->set_base(state->m_basic);
+ else
+ state->membank("bank9")->set_base(state->m_memory + 0xa000);
+
+ if ((!state->m_game && state->m_exrom) || (charen && (loram || hiram)))
+ {
+ machine.device("m8502")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0xd000, 0xdfff, FUNC(c128_read_io));
+ state->m_write_io = 1;
+ }
+ else
+ {
+ machine.device("m8502")->memory().space(AS_PROGRAM)->install_read_bank(0xd000, 0xdfff, "bank5");
+ state->m_write_io = 0;
+ if ((!charen && (loram || hiram)))
+ state->membank("bank13")->set_base(state->m_chargen);
+ else
+ state->membank("bank13")->set_base(state->m_memory + 0xd000);
+ }
+
+ if (!state->m_game && state->m_exrom)
+ {
+ state->membank("bank14")->set_base(state->m_romh);
+ state->membank("bank15")->set_base(state->m_romh+0x1f00);
+ state->membank("bank16")->set_base(state->m_romh+0x1f05);
+ }
+ else
+ {
+ if (hiram)
+ {
+ state->membank("bank14")->set_base(state->m_kernal);
+ state->membank("bank15")->set_base(state->m_kernal+0x1f00);
+ state->membank("bank16")->set_base(state->m_kernal+0x1f05);
+ }
+ else
+ {
+ state->membank("bank14")->set_base(state->m_memory + 0xe000);
+ state->membank("bank15")->set_base(state->m_memory + 0xff00);
+ state->membank("bank16")->set_base(state->m_memory + 0xff05);
+ }
+ }
+ state->m_old_data = data;
+ state->m_old_exrom = state->m_exrom;
+ state->m_old_game =state->m_game;
+}
+
+/* typical z80 configuration
+ 0x3f 0x3f 0x7f 0x3e 0x7e 0xb0 0x0b 0x00 0x00 0x01 0x00 */
+static void c128_bankswitch_z80( running_machine &machine )
+{
+ c128_state *state = machine.driver_data<c128_state>();
+ state->m_ram = state->m_memory + MMU_RAM_ADDR;
+ state->m_va1617 = MMU_VIC_ADDR;
+#if 1
+ state->membank("bank10")->set_base(state->m_z80);
+ state->membank("bank11")->set_base(state->m_ram + 0x1000);
+ if ( (( (machine.root_device().ioport("SPECIAL")->read() & 0x06) == 0x02 ) && (MMU_RAM_ADDR >= 0x40000))
+ || (( (machine.root_device().ioport("SPECIAL")->read() & 0x06) == 0x00) && (MMU_RAM_ADDR >= 0x20000)) )
+ state->m_ram = NULL;
+#else
+ if (MMU_BOTTOM)
+ state->m_ram_bottom = MMU_SIZE;
+ else
+ state->m_ram_bottom = 0;
+
+ if (MMU_RAM_ADDR==0) { /* this is used in z80 mode for rom on/off switching !*/
+ state->membank("bank10")->set_base(state->m_z80);
+ state->membank("bank11")->set_base(state->m_z80 + 0x400);
+ }
+ else
+ {
+ state->membank("bank10")->set_base((state->m_ram_bottom > 0 ? state->m_memory : state->m_ram));
+ state->membank("bank11")->set_base((state->m_ram_bottom > 0x400 ? state->m_memory : state->m_ram) + 0x400);
+ }
+
+ state->membank("bank1")->set_base((state->m_ram_bottom > 0 ? state->m_memory : state->m_ram));
+ state->membank("bank2")->set_base((state->m_ram_bottom > 0x400 ? state->m_memory : state->m_ram) + 0x400);
+
+ state->membank("bank3")->set_base((state->m_ram_bottom > 0x1000 ? state->m_memory : state->m_ram) + 0x1000);
+ state->membank("bank4")->set_base((state->m_ram_bottom > 0x2000 ? state->m_memory : state->m_ram) + 0x2000);
+ state->membank("bank5")->set_base(state->m_ram + 0x4000);
+
+ if (MMU_TOP)
+ state->m_ram_top = 0x10000 - MMU_SIZE;
+ else
+ state->m_ram_top = 0x10000;
+
+ if (state->m_ram_top > 0xc000)
+ state->membank("bank6")->set_base(state->m_ram + 0xc000);
+ else
+ state->membank("bank6")->set_base(state->m_memory + 0xc000);
+
+ if (state->m_ram_top > 0xe000)
+ state->membank("bank7")->set_base(state->m_ram + 0xe000);
+ else
+ state->membank("bank7")->set_base(state->m_memory + 0xd000);
+
+ if (state->m_ram_top > 0xf000)
+ state->membank("bank8")->set_base(state->m_ram + 0xf000);
+ else
+ state->membank("bank8")->set_base(state->m_memory + 0xe000);
+
+ if (state->m_ram_top > 0xff05)
+ state->membank("bank9")->set_base(state->m_ram + 0xff05);
+ else
+ state->membank("bank9")->set_base(state->m_memory + 0xff05);
+
+ if ( (( (machine.root_device().ioport("SPECIAL")->read() & 0x06) == 0x02 ) && (MMU_RAM_ADDR >= 0x40000))
+ || (( (machine.root_device().ioport("SPECIAL")->read() & 0x06) == 0x00) && (MMU_RAM_ADDR >= 0x20000)) )
+ state->m_ram = NULL;
+#endif
+}
+
+static void c128_bankswitch_128( running_machine &machine, int reset )
+{
+ c128_state *state = machine.driver_data<c128_state>();
+ state->m_c64mode = MMU_64MODE;
+ if (state->m_c64mode)
+ {
+ /* mmu works also in c64 mode, but this can wait */
+ state->m_ram = state->m_memory;
+ state->m_va1617 = 0;
+ state->m_ram_bottom = 0;
+ state->m_ram_top = 0x10000;
+
+ state->membank("bank1")->set_base(state->m_memory);
+ state->membank("bank2")->set_base(state->m_memory + 0x100);
+
+ state->membank("bank3")->set_base(state->m_memory + 0x200);
+ state->membank("bank4")->set_base(state->m_memory + 0x400);
+ state->membank("bank5")->set_base(state->m_memory + 0x1000);
+ state->membank("bank6")->set_base(state->m_memory + 0x2000);
+
+ state->membank("bank7")->set_base(state->m_memory + 0x4000);
+
+ state->membank("bank12")->set_base(state->m_memory + 0xc000);
+
+ c128_bankswitch_64(machine, reset);
+ }
+ else
+ {
+ state->m_ram = state->m_memory + MMU_RAM_ADDR;
+ state->m_va1617 = MMU_VIC_ADDR;
+ state->membank("bank1")->set_base(state->m_memory + state->m_mmu_page0);
+ state->membank("bank2")->set_base(state->m_memory + state->m_mmu_page1);
+ if (MMU_BOTTOM)
+ {
+ state->m_ram_bottom = MMU_SIZE;
+ }
+ else
+ state->m_ram_bottom = 0;
+ state->membank("bank3")->set_base((state->m_ram_bottom > 0x200 ? state->m_memory : state->m_ram) + 0x200);
+ state->membank("bank4")->set_base((state->m_ram_bottom > 0x400 ? state->m_memory : state->m_ram) + 0x400);
+ state->membank("bank5")->set_base((state->m_ram_bottom > 0x1000 ? state->m_memory : state->m_ram) + 0x1000);
+ state->membank("bank6")->set_base((state->m_ram_bottom > 0x2000 ? state->m_memory : state->m_ram) + 0x2000);
+
+ if (MMU_RAM_LO)
+ {
+ state->membank("bank7")->set_base(state->m_ram + 0x4000);
+ }
+ else
+ {
+ state->membank("bank7")->set_base(state->m_c128_basic);
+ }
+
+ if (MMU_RAM_MID)
+ {
+ state->membank("bank8")->set_base(state->m_ram + 0x8000);
+ state->membank("bank9")->set_base(state->m_ram + 0xa000);
+ }
+ else if (MMU_ROM_MID)
+ {
+ state->membank("bank8")->set_base(state->m_c128_basic + 0x4000);
+ state->membank("bank9")->set_base(state->m_c128_basic + 0x6000);
+ }
+ else if (MMU_INTERNAL_ROM_MID)
+ {
+ state->membank("bank8")->set_base(state->m_internal_function);
+ state->membank("bank9")->set_base(state->m_internal_function + 0x2000);
+ }
+ else
+ {
+ state->membank("bank8")->set_base(state->m_external_function);
+ state->membank("bank9")->set_base(state->m_external_function + 0x2000);
+ }
+
+ if (MMU_TOP)
+ {
+ state->m_ram_top = 0x10000 - MMU_SIZE;
+ }
+ else
+ state->m_ram_top = 0x10000;
+
+ machine.device("m8502")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0xff00, 0xff04, FUNC(c128_mmu8722_ff00_r));
+
+ if (MMU_IO_ON)
+ {
+ state->m_write_io = 1;
+ machine.device("m8502")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0xd000, 0xdfff, FUNC(c128_read_io));
+ }
+ else
+ {
+ state->m_write_io = 0;
+ machine.device("m8502")->memory().space(AS_PROGRAM)->install_read_bank(0xd000, 0xdfff, "bank13");
+ }
+
+
+ if (MMU_RAM_HI)
+ {
+ if (state->m_ram_top > 0xc000)
+ {
+ state->membank("bank12")->set_base(state->m_ram + 0xc000);
+ }
+ else
+ {
+ state->membank("bank12")->set_base(state->m_memory + 0xc000);
+ }
+ if (!MMU_IO_ON)
+ {
+ if (state->m_ram_top > 0xd000)
+ {
+ state->membank("bank13")->set_base(state->m_ram + 0xd000);
+ }
+ else
+ {
+ state->membank("bank13")->set_base(state->m_memory + 0xd000);
+ }
+ }
+ if (state->m_ram_top > 0xe000)
+ {
+ state->membank("bank14")->set_base(state->m_ram + 0xe000);
+ }
+ else
+ {
+ state->membank("bank14")->set_base(state->m_memory + 0xe000);
+ }
+ if (state->m_ram_top > 0xff05)
+ {
+ state->membank("bank16")->set_base(state->m_ram + 0xff05);
+ }
+ else
+ {
+ state->membank("bank16")->set_base(state->m_memory + 0xff05);
+ }
+ }
+ else if (MMU_ROM_HI)
+ {
+ state->membank("bank12")->set_base(state->m_editor);
+ if (!MMU_IO_ON) {
+ state->membank("bank13")->set_base(state->m_c128_chargen);
+ }
+ state->membank("bank14")->set_base(state->m_c128_kernal);
+ state->membank("bank16")->set_base(state->m_c128_kernal + 0x1f05);
+ }
+ else if (MMU_INTERNAL_ROM_HI)
+ {
+ state->membank("bank12")->set_base(state->m_internal_function);
+ if (!MMU_IO_ON) {
+ state->membank("bank13")->set_base(state->m_internal_function + 0x1000);
+ }
+ state->membank("bank14")->set_base(state->m_internal_function + 0x2000);
+ state->membank("bank16")->set_base(state->m_internal_function + 0x3f05);
+ }
+ else /*if (MMU_EXTERNAL_ROM_HI) */
+ {
+ state->membank("bank12")->set_base(state->m_external_function);
+ if (!MMU_IO_ON) {
+ state->membank("bank13")->set_base(state->m_external_function + 0x1000);
+ }
+ state->membank("bank14")->set_base(state->m_external_function + 0x2000);
+ state->membank("bank16")->set_base(state->m_external_function + 0x3f05);
+ }
+
+ if ( (( (machine.root_device().ioport("SPECIAL")->read() & 0x06) == 0x02 ) && (MMU_RAM_ADDR >= 0x40000))
+ || (( (machine.root_device().ioport("SPECIAL")->read() & 0x06) == 0x00) && (MMU_RAM_ADDR >= 0x20000)) )
+ state->m_ram = NULL;
+ }
+}
+
+// 128u4
+// FIX-ME: are the bankswitch functions working in the expected way without the memory_set_context?
+static void c128_bankswitch( running_machine &machine, int reset )
+{
+ c128_state *state = machine.driver_data<c128_state>();
+ if (state->m_mmu_cpu != MMU_CPU8502)
+ {
+ if (!MMU_CPU8502)
+ {
+// DBG_LOG(machine, 1, "switching to z80", ("active %d\n",cpu_getactivecpu()) );
+// memory_set_context(machine, 0);
+ c128_bankswitch_z80(machine);
+// memory_set_context(machine, 1);
+ cputag_set_input_line(machine, "maincpu", INPUT_LINE_HALT, CLEAR_LINE);
+ cputag_set_input_line(machine, "m8502", INPUT_LINE_HALT, ASSERT_LINE);
+ }
+ else
+ {
+// DBG_LOG(machine, 1, "switching to m6502", ("active %d\n",cpu_getactivecpu()) );
+// memory_set_context(machine, 1);
+ c128_bankswitch_128(machine, reset);
+// memory_set_context(machine, 0);
+ cputag_set_input_line(machine, "maincpu", INPUT_LINE_HALT, ASSERT_LINE);
+ cputag_set_input_line(machine, "m8502", INPUT_LINE_HALT, CLEAR_LINE);
+
+ /* NPW 19-Nov-2005 - In the C128, CPU #0 starts out and hands over
+ * control to CPU #1. CPU #1 seems to execute garbage from 0x0000
+ * up to 0x1100, at which point it finally hits some code
+ * (presumably set up by CPU #1.) This always worked, but when I
+ * changed the m8502 CPU core to use an internal memory map, it
+ * started BRK-ing forever when trying to execute 0x0000.
+ *
+ * I am not sure whether the C128 actually executes this invalid
+ * memory or if this is a bug in the C128 driver. In any case, the
+ * driver used to work with this behavior, so I am doing this hack
+ * where I set CPU #1's PC to 0x1100 on reset.
+ */
+ if (cpu_get_reg(machine.device("m8502"), STATE_GENPC) == 0x0000)
+ cpu_set_reg(machine.device("m8502"), STATE_GENPC, 0x1100);
+ }
+ state->m_mmu_cpu = MMU_CPU8502;
+ return;
+ }
+ if (!MMU_CPU8502)
+ c128_bankswitch_z80(machine);
+ else
+ c128_bankswitch_128(machine, reset);
+}
+
+static void c128_mmu8722_reset( running_machine &machine )
+{
+ c128_state *state = machine.driver_data<c128_state>();
+ memset(state->m_mmu, 0, sizeof (state->m_mmu));
+ state->m_mmu[5] |= 0x38;
+ state->m_mmu[10] = 1;
+ state->m_mmu_cpu = 0;
+ state->m_mmu_page0 = 0;
+ state->m_mmu_page1 = 0x0100;
+ c128_bankswitch (machine, 1);
+}
+
+WRITE8_HANDLER( c128_mmu8722_port_w )
+{
+ c128_state *state = space->machine().driver_data<c128_state>();
+ offset &= 0xf;
+ switch (offset)
+ {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 8:
+ case 10:
+ state->m_mmu[offset] = data;
+ break;
+ case 5:
+ state->m_mmu[offset] = data;
+ c128_bankswitch (space->machine(), 0);
+ c128_iec_srq_out_w(space->machine());
+ c128_iec_data_out_w(space->machine());
+ break;
+ case 0:
+ case 6:
+ state->m_mmu[offset] = data;
+ c128_bankswitch (space->machine(), 0);
+ break;
+ case 7:
+ state->m_mmu[offset] = data;
+ state->m_mmu_page0=MMU_PAGE0;
+ break;
+ case 9:
+ state->m_mmu[offset] = data;
+ state->m_mmu_page1=MMU_PAGE1;
+ c128_bankswitch (space->machine(), 0);
+ break;
+ case 0xb:
+ break;
+ case 0xc:
+ case 0xd:
+ case 0xe:
+ case 0xf:
+ break;
+ }
+}
+
+READ8_HANDLER( c128_mmu8722_port_r )
+{
+ c128_state *state = space->machine().driver_data<c128_state>();
+ int data;
+
+ offset &= 0x0f;
+ switch (offset)
+ {
+ case 5:
+ data = state->m_mmu[offset] | 6;
+ if ( /*disk enable signal */ 0)
+ data &= ~8;
+ if (!state->m_game)
+ data &= ~0x10;
+ if (!state->m_exrom)
+ data &= ~0x20;
+ if (space->machine().root_device().ioport("SPECIAL")->read() & 0x10)
+ data &= ~0x80;
+ break;
+ case 0xb:
+ /* hinybble number of 64 kb memory blocks */
+ if ((space->machine().root_device().ioport("SPECIAL")->read() & 0x06) == 0x02) // 256KB RAM
+ data = 0x4f;
+ else if ((state->ioport("SPECIAL")->read() & 0x06) == 0x04) // 1MB
+ data = 0xf;
+ else
+ data = 0x2f;
+ break;
+ case 0xc:
+ case 0xd:
+ case 0xe:
+ case 0xf:
+ data=0xff;
+ break;
+ default:
+ data=state->m_mmu[offset];
+ }
+ return data;
+}
+
+WRITE8_HANDLER( c128_mmu8722_ff00_w )
+{
+ c128_state *state = space->machine().driver_data<c128_state>();
+ switch (offset)
+ {
+ case 0:
+ state->m_mmu[offset] = data;
+ c128_bankswitch (space->machine(), 0);
+ break;
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+#if 1
+ state->m_mmu[0]= state->m_mmu[offset];
+#else
+ state->m_mmu[0]|= state->m_mmu[offset];
+#endif
+ c128_bankswitch (space->machine(), 0);
+ break;
+ }
+}
+
+ READ8_HANDLER( c128_mmu8722_ff00_r )
+{
+ c128_state *state = space->machine().driver_data<c128_state>();
+ return state->m_mmu[offset];
+}
+
+WRITE8_HANDLER( c128_write_0000 )
+{
+ c128_state *state = space->machine().driver_data<c128_state>();
+ if (state->m_ram != NULL)
+ state->m_ram[0x0000 + offset] = data;
+}
+
+WRITE8_HANDLER( c128_write_1000 )
+{
+ c128_state *state = space->machine().driver_data<c128_state>();
+ if (state->m_ram != NULL)
+ state->m_ram[0x1000 + offset] = data;
+}
+
+WRITE8_HANDLER( c128_write_4000 )
+{
+ c128_state *state = space->machine().driver_data<c128_state>();
+ if (state->m_ram != NULL)
+ state->m_ram[0x4000 + offset] = data;
+}
+
+WRITE8_HANDLER( c128_write_8000 )
+{
+ c128_state *state = space->machine().driver_data<c128_state>();
+ if (state->m_ram != NULL)
+ state->m_ram[0x8000 + offset] = data;
+}
+
+WRITE8_HANDLER( c128_write_a000 )
+{
+ c128_state *state = space->machine().driver_data<c128_state>();
+ if (state->m_ram != NULL)
+ state->m_ram[0xa000 + offset] = data;
+}
+
+WRITE8_HANDLER( c128_write_c000 )
+{
+ c128_state *state = space->machine().driver_data<c128_state>();
+ if (state->m_ram != NULL)
+ state->m_ram[0xc000 + offset] = data;
+}
+
+WRITE8_HANDLER( c128_write_e000 )
+{
+ c128_state *state = space->machine().driver_data<c128_state>();
+ if (offset + 0xe000 >= state->m_ram_top)
+ state->m_memory[0xe000 + offset] = data;
+ else if (state->m_ram != NULL)
+ state->m_ram[0xe000 + offset] = data;
+}
+
+WRITE8_HANDLER( c128_write_ff00 )
+{
+ c128_state *state = space->machine().driver_data<c128_state>();
+ if (!state->m_c64mode)
+ c128_mmu8722_ff00_w(space, offset, data);
+ else if (state->m_ram!=NULL)
+ state->m_memory[0xff00 + offset] = data;
+}
+
+WRITE8_HANDLER( c128_write_ff05 )
+{
+ c128_state *state = space->machine().driver_data<c128_state>();
+ if (offset + 0xff05 >= state->m_ram_top)
+ state->m_memory[0xff05 + offset] = data;
+ else if (state->m_ram!=NULL)
+ state->m_ram[0xff05 + offset] = data;
+}
+
+/*
+ * only 14 address lines
+ * a15 and a14 portlines
+ * 0x1000-0x1fff, 0x9000-0x9fff char rom
+ */
+READ8_MEMBER( c128_state::vic_dma_read )
+{
+ UINT8 c64_port6510 = m6510_get_port(machine().device<legacy_cpu_device>("m8502"));
+
+ /* main memory configuration to include */
+ if (m_c64mode)
+ {
+ if (!m_game && m_exrom)
+ {
+ if (offset < 0x3000)
+ return m_memory[offset];
+ return m_romh[offset & 0x1fff];
+ }
+ if (((m_vicaddr - m_memory + offset) & 0x7000) == 0x1000)
+ return m_chargen[offset & 0xfff];
+ return m_vicaddr[offset];
+ }
+ if (!(c64_port6510 & 4) && (((m_c128_vicaddr - m_memory + offset) & 0x7000) == 0x1000))
+ return m_c128_chargen[offset & 0xfff];
+ return m_c128_vicaddr[offset];
+}
+
+READ8_MEMBER( c128_state::vic_dma_read_color )
+{
+ UINT8 c64_port6510 = m6510_get_port(machine().device<legacy_cpu_device>("m8502"));
+
+ if (m_c64mode)
+ return m_colorram[offset & 0x3ff] & 0xf;
+ else
+ return m_colorram[(offset & 0x3ff)|((c64_port6510 & 0x3) << 10)] & 0xf;
+}
+
+/* 2008-09-01
+ We need here the m6510 port handlers from c64, otherwise c128_common_driver_init
+ seems unable to use correctly the timer.
+ This will be probably fixed in a future clean up.
+*/
+
+
+WRITE8_DEVICE_HANDLER(c128_m6510_port_write)
+{
+ c128_state *state = device->machine().driver_data<c128_state>();
+
+ UINT8 direction = offset; // HACK ALERT!
+
+ /* if line is marked as input then keep current value */
+ data = (state->m_c64_port_data & ~direction) | (data & direction);
+
+ /* resistors make P0,P1,P2 go high when respective line is changed to input */
+ if (!(direction & 0x04))
+ data |= 0x04;
+
+ if (!(direction & 0x02))
+ data |= 0x02;
+
+ if (!(direction & 0x01))
+ data |= 0x01;
+
+ state->m_c64_port_data = data;
+
+ if (state->m_tape_on)
+ {
+ if (direction & 0x08)
+ {
+ device->machine().device<cassette_image_device>(CASSETTE_TAG)->output((data & 0x08) ? -(0x5a9e >> 1) : +(0x5a9e >> 1));
+ }
+
+ if (direction & 0x20)
+ {
+ if (!(data & 0x20))
+ {
+ device->machine().device<cassette_image_device>(CASSETTE_TAG)->change_state(CASSETTE_MOTOR_ENABLED,CASSETTE_MASK_MOTOR);
+ state->m_datasette_timer->adjust(attotime::zero, 0, attotime::from_hz(44100));
+ }
+ else
+ {
+ device->machine().device<cassette_image_device>(CASSETTE_TAG)->change_state(CASSETTE_MOTOR_DISABLED ,CASSETTE_MASK_MOTOR);
+ state->m_datasette_timer->reset();
+ }
+ }
+ }
+
+ c128_bankswitch_64(device->machine(), 0);
+
+ state->m_memory[0x000] = device->memory().space(AS_PROGRAM)->read_byte(0);
+ state->m_memory[0x001] = device->memory().space(AS_PROGRAM)->read_byte(1);
+
+}
+
+READ8_DEVICE_HANDLER(c128_m6510_port_read)
+{
+ c128_state *state = device->machine().driver_data<c128_state>();
+ UINT8 data = state->m_c64_port_data;
+
+ if ((device->machine().device<cassette_image_device>(CASSETTE_TAG)->get_state() & CASSETTE_MASK_UISTATE) != CASSETTE_STOPPED)
+ data &= ~0x10;
+ else
+ data |= 0x10;
+
+ if (state->ioport("SPECIAL")->read() & 0x20) /* Check Caps Lock */
+ data &= ~0x40;
+ else
+ data |= 0x40;
+
+ return data;
+}
+
+static void c128_common_driver_init( running_machine &machine )
+{
+ c128_state *state = machine.driver_data<c128_state>();
+ UINT8 *gfx=machine.root_device().memregion("gfx1")->base();
+ UINT8 *ram = state->memregion("maincpu")->base();
+ int i;
+
+ state->m_memory = ram;
+
+ state->m_c128_basic = ram + 0x100000;
+ state->m_basic = ram + 0x108000;
+ state->m_kernal = ram + 0x10a000;
+ state->m_editor = ram + 0x10c000;
+ state->m_z80 = ram + 0x10d000;
+ state->m_c128_kernal = ram + 0x10e000;
+ state->m_internal_function = ram + 0x110000;
+ state->m_external_function = ram + 0x118000;
+ state->m_chargen = ram + 0x120000;
+ state->m_c128_chargen = ram + 0x121000;
+ state->m_colorram = ram + 0x122000;
+ state->m_vdcram = ram + 0x122800;
+ state->m_c64_roml = auto_alloc_array(machine, UINT8, 0x2000);
+ state->m_c64_romh = auto_alloc_array(machine, UINT8, 0x2000);
+
+ state->m_tape_on = 1;
+ state->m_game = 1;
+ state->m_exrom = 1;
+ state->m_pal = 0;
+ state->m_c64mode = 0;
+ state->m_vicirq = 0;
+
+ state->m_monitor = -1;
+ state->m_cnt1 = 1;
+ state->m_sp1 = 1;
+ cbm_common_init();
+ state->m_keyline[0] = state->m_keyline[1] = state->m_keyline[2] = 0xff;
+
+ for (i = 0; i < 0x100; i++)
+ gfx[i] = i;
+
+ if (state->m_tape_on)
+ state->m_datasette_timer = machine.scheduler().timer_alloc(FUNC(c64_tape_timer));
+}
+
+DRIVER_INIT_MEMBER(c128_state,c128)
+{
+ device_t *vic2e = machine().device("vic2e");
+ device_t *vdc8563 = machine().device("vdc8563");
+
+ c128_common_driver_init(machine());
+
+ vic2_set_rastering(vic2e, 0);
+ vdc8563_set_rastering(vdc8563, 1);
+}
+
+DRIVER_INIT_MEMBER(c128_state,c128pal)
+{
+ device_t *vic2e = machine().device("vic2e");
+ device_t *vdc8563 = machine().device("vdc8563");
+
+ c128_common_driver_init(machine());
+ m_pal = 1;
+
+ vic2_set_rastering(vic2e, 1);
+ vdc8563_set_rastering(vdc8563, 0);
+}
+
+DRIVER_INIT_MEMBER(c128_state,c128d)
+{
+ DRIVER_INIT_CALL( c128 );
+}
+
+DRIVER_INIT_MEMBER(c128_state,c128dpal)
+{
+ DRIVER_INIT_CALL( c128pal );
+}
+
+DRIVER_INIT_MEMBER(c128_state,c128dcr)
+{
+ DRIVER_INIT_CALL( c128 );
+}
+
+DRIVER_INIT_MEMBER(c128_state,c128dcrp)
+{
+ DRIVER_INIT_CALL( c128pal );
+}
+
+DRIVER_INIT_MEMBER(c128_state,c128d81)
+{
+ DRIVER_INIT_CALL( c128 );
+}
+
+MACHINE_START( c128 )
+{
+ c128_state *state = machine.driver_data<c128_state>();
+// This was in MACHINE_START( c64 ), but never called
+// TO DO: find its correct use, when fixing c64 mode
+ if (state->m_c64mode)
+ c128_bankswitch_64(machine, 1);
+}
+
+MACHINE_RESET( c128 )
+{
+ c128_state *state = machine.driver_data<c128_state>();
+ state->m_c128_vicaddr = state->m_vicaddr = state->m_memory;
+ state->m_c64mode = 0;
+ c128_mmu8722_reset(machine);
+ cputag_set_input_line(machine, "maincpu", INPUT_LINE_HALT, CLEAR_LINE);
+ cputag_set_input_line(machine, "m8502", INPUT_LINE_HALT, ASSERT_LINE);
+}
+
+
+INTERRUPT_GEN( c128_frame_interrupt )
+{
+ c128_state *state = device->machine().driver_data<c128_state>();
+ static const char *const c128ports[] = { "KP0", "KP1", "KP2" };
+ int i, value;
+ device_t *vic2e = device->machine().device("vic2e");
+ device_t *vdc8563 = device->machine().device("vdc8563");
+
+ c128_nmi(device->machine());
+
+ if ((device->machine().root_device().ioport("SPECIAL")->read() & 0x08) != state->m_monitor)
+ {
+ if (device->machine().root_device().ioport("SPECIAL")->read() & 0x08)
+ {
+ vic2_set_rastering(vic2e, 0);
+ vdc8563_set_rastering(vdc8563, 1);
+ device->machine().primary_screen->set_visible_area(0, 655, 0, 215);
+ }
+ else
+ {
+ vic2_set_rastering(vic2e, 1);
+ vdc8563_set_rastering(vdc8563, 0);
+ if (state->m_pal)
+ device->machine().primary_screen->set_visible_area(0, VIC6569_VISIBLECOLUMNS - 1, 0, VIC6569_VISIBLELINES - 1);
+ else
+ device->machine().primary_screen->set_visible_area(0, VIC6567_VISIBLECOLUMNS - 1, 0, VIC6567_VISIBLELINES - 1);
+ }
+ state->m_monitor = device->machine().root_device().ioport("SPECIAL")->read() & 0x08;
+ }
+
+
+ /* common keys input ports */
+ cbm_common_interrupt(device);
+
+ /* Fix Me! Currently, neither left Shift nor Shift Lock work in c128, but reading the correspondent input produces a bug!
+ Hence, we overwrite the actual reading as it never happens */
+ if ((device->machine().root_device().ioport("SPECIAL")->read() & 0x40)) //
+ c64_keyline[1] |= 0x80;
+
+ /* c128 specific: keypad input ports */
+ for (i = 0; i < 3; i++)
+ {
+ value = 0xff;
+ value &= ~device->machine().root_device().ioport(c128ports[i])->read();
+ state->m_keyline[i] = value;
+ }
+}
+
+SCREEN_UPDATE_IND16( c128 )
+{
+ device_t *vic2e = screen.machine().device("vic2e");
+ device_t *vdc8563 = screen.machine().device("vdc8563");
+
+ vdc8563_video_update(vdc8563, bitmap, cliprect);
+ vic2_video_update(vic2e, bitmap, cliprect);
+ return 0;
+}