summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Curt Coder <curtcoder@mail.com>2008-06-04 20:15:15 +0000
committer Curt Coder <curtcoder@mail.com>2008-06-04 20:15:15 +0000
commit6d6a5b237d78ca39473e4291c1ed70d6b558f46d (patch)
treed9b69f44cdd7e65e8f69b1458b13bb71cf28897f
parent5817f03b73f4d77dc6381d4b4f110c6867a30e24 (diff)
- Added HALT opcode and halt mode to the COP410
- Added Microbus support, clock divisor selection, and CKO mode selection to the COP420 - Changed Thayer's Quest keyboard interface to at least slightly resemble the schematics
-rw-r--r--src/emu/cpu/cop400/410ops.c64
-rw-r--r--src/emu/cpu/cop400/cop400.h48
-rw-r--r--src/emu/cpu/cop400/cop410.c48
-rw-r--r--src/emu/cpu/cop400/cop410ds.c4
-rw-r--r--src/emu/cpu/cop400/cop420.c186
-rw-r--r--src/mame/drivers/cidelsa.c10
-rw-r--r--src/mame/drivers/looping.c9
-rw-r--r--src/mame/drivers/thayers.c123
8 files changed, 443 insertions, 49 deletions
diff --git a/src/emu/cpu/cop400/410ops.c b/src/emu/cpu/cop400/410ops.c
index 4ac4ab71dc9..8c5ebf5a457 100644
--- a/src/emu/cpu/cop400/410ops.c
+++ b/src/emu/cpu/cop400/410ops.c
@@ -141,7 +141,13 @@ INLINE void WRITE_Q(UINT8 data)
INLINE void WRITE_G(UINT8 data)
{
+ if (R.intf->microbus == COP400_MICROBUS_ENABLED)
+ {
+ data = (data & 0x0e) | R.microbus_int;
+ }
+
G = data;
+
OUT_G(G);
}
@@ -484,6 +490,24 @@ INSTRUCTION(retsk)
skip = 1;
}
+/*
+
+ Processor: COP410C/COP411C
+
+ Mnemonic: HALT
+
+ Hex Code: 33 38
+ Binary: 0 0 1 1 0 0 1 1 0 0 1 1 1 0 0 0
+
+ Description: Halt processor
+
+*/
+
+INSTRUCTION(halt)
+{
+ R.halt = 1;
+}
+
/* Memory Reference Instructions */
/*
@@ -502,7 +526,45 @@ INSTRUCTION(retsk)
INSTRUCTION(camq)
{
- WRITE_Q((A << 4) | RAM_R(B));
+ /*
+
+ Excerpt from the COP410L data sheet:
+
+ False states may be generated on L0-L7 during the execution of the CAMQ instruction.
+ The L-ports should not be used as clocks for edge sensitive devices such as flip-flops,
+ counters, shift registers, etc. the following short program that illustrates this situation.
+
+ START:
+ CLRA ;ENABLE THE Q
+ LEI 4 ;REGISTER TO L LINES
+ LBI TEST
+ STII 3
+ AISC 12
+ LOOP:
+ LBI TEST ;LOAD Q WITH X'C3
+ CAMQ
+ JP LOOP
+
+ In this program the internal Q register is enabled onto the L lines and a steady bit
+ pattern of logic highs is output on L0, L1, L6, L7, and logic lows on L2-L5 via the
+ two-byte CAMQ instruction. Timing constraints on the device are such that the Q
+ register may be temporarily loaded with the second byte of the CAMQ opcode (3C) prior
+ to receiving the valid data pattern. If this occurs, the opcode will ripple onto the L
+ lines and cause negative-going glitches on L0, L1, L6, L7, and positive glitches on
+ L2-L5. Glitch durations are under 2 ms, although the exact value may vary due to data
+ patterns, processing parameters, and L line loading. These false states are peculiar
+ only to the CAMQ instruction and the L lines.
+
+ */
+
+ UINT8 data = (A << 4) | RAM_R(B);
+
+ WRITE_Q(data);
+
+#ifdef CAMQ_BUG
+ WRITE_Q(0x3c);
+ WRITE_Q(data);
+#endif
}
/*
diff --git a/src/emu/cpu/cop400/cop400.h b/src/emu/cpu/cop400/cop400.h
index e460cb2ede5..7b4f2592dce 100644
--- a/src/emu/cpu/cop400/cop400.h
+++ b/src/emu/cpu/cop400/cop400.h
@@ -2,7 +2,7 @@
cop400.h
- National Semiconductor COP400 Emulator.
+ National Semiconductor COPS Emulator.
Copyright Nicola Salmoria and the MAME Team.
Visit http://mamedev.org for licensing and usage restrictions.
@@ -35,16 +35,62 @@ enum {
COP400_SKL
};
+typedef enum _cop400_cki_bond cop400_cki_bond;
+enum _cop400_cki_bond {
+ COP400_CKI_DIVISOR_4 = 4,
+ COP400_CKI_DIVISOR_8 = 8,
+ COP400_CKI_DIVISOR_16 = 16
+};
+
+typedef enum _cop400_cko_bond cop400_cko_bond;
+enum _cop400_cko_bond {
+ COP400_CKO_OSCILLATOR_OUTPUT = 0,
+ COP400_CKO_HALT_IO_PORT,
+ COP400_CKO_GENERAL_PURPOSE_INPUT
+};
+
+typedef enum _cop400_microbus cop400_microbus;
+enum _cop400_microbus {
+ COP400_MICROBUS_DISABLED = 0,
+ COP400_MICROBUS_ENABLED
+};
+
+/* interface */
+typedef struct _cop400_interface cop400_interface;
+struct _cop400_interface
+{
+ cop400_cki_bond cki; /* CKI bonding option */
+ cop400_cko_bond cko; /* CKO bonding option */
+ cop400_microbus microbus; /* microbus option */
+};
+#define COP400_INTERFACE(name) const cop400_interface (name) =
+
+/*
+
+ Prefix Temperature Range
+
+ COP4xx 0C to 70C
+ COP3xx -40C to +85C
+ COP2xx -55C to +125C
+
+*/
+
+/* COP 41x */
extern void cop401_get_info(UINT32 state, cpuinfo *info);
extern void cop410_get_info(UINT32 state, cpuinfo *info);
extern void cop411_get_info(UINT32 state, cpuinfo *info);
+/* COP 42x */
extern void cop402_get_info(UINT32 state, cpuinfo *info);
extern void cop420_get_info(UINT32 state, cpuinfo *info);
extern void cop421_get_info(UINT32 state, cpuinfo *info);
extern void cop422_get_info(UINT32 state, cpuinfo *info);
+/* COP 44x */
extern void cop404_get_info(UINT32 state, cpuinfo *info);
+extern void cop424_get_info(UINT32 state, cpuinfo *info);
+extern void cop425_get_info(UINT32 state, cpuinfo *info);
+extern void cop426_get_info(UINT32 state, cpuinfo *info);
extern void cop444_get_info(UINT32 state, cpuinfo *info);
extern void cop445_get_info(UINT32 state, cpuinfo *info);
diff --git a/src/emu/cpu/cop400/cop410.c b/src/emu/cpu/cop400/cop410.c
index 292fcfe7264..cbf3dfa97b9 100644
--- a/src/emu/cpu/cop400/cop410.c
+++ b/src/emu/cpu/cop400/cop410.c
@@ -13,8 +13,10 @@
TODO:
+ - run interrupt test suite
+ - run production test suite
+ - run microbus test suite
- remove LBIops
- - run all test suites
*/
@@ -35,6 +37,8 @@ typedef struct {
typedef struct
{
+ const cop400_interface *intf;
+
UINT9 PC;
UINT9 PREVPC;
UINT4 A;
@@ -50,6 +54,8 @@ typedef struct
UINT8 G_mask;
UINT8 D_mask;
UINT8 si;
+ int microbus_int;
+ int halt;
} COP410_Regs;
static COP410_Regs R;
@@ -119,7 +125,7 @@ static const s_opcode opcode_33_map[256]=
{1, illegal },{1, skgz },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
{1, illegal },{1, illegal },{1, ing },{1, illegal },{1, illegal },{1, illegal },{1, inl },{1, illegal },
{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
- {1, illegal },{1, illegal },{1, omg },{1, illegal },{1, camq },{1, illegal },{1, obd },{1, illegal },
+ {1, halt },{1, illegal },{1, omg },{1, illegal },{1, camq },{1, illegal },{1, obd },{1, illegal },
{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },{1, illegal },
@@ -197,7 +203,7 @@ static const s_opcode opcode_map[256]=
/* Memory Maps */
-static ADDRESS_MAP_START( cop410_internal_rom, ADDRESS_SPACE_DATA, 8 )
+static ADDRESS_MAP_START( cop410_internal_rom, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x000, 0x1ff) AM_ROM
ADDRESS_MAP_END
@@ -213,22 +219,41 @@ static void cop410_init(int index, int clock, const void *config, int (*irqcallb
int i;
memset(&R, 0, sizeof(R));
- R.G_mask = 0x0F;
- R.D_mask = 0x0F;
+
+ R.intf = (cop400_interface *) config;
+
+ assert(R.intf != NULL);
+
+ /* set output pin masks */
+
+ R.G_mask = 0x0f;
+ R.D_mask = 0x0f;
+
+ /* set clock divider */
+
+ activecpu_set_info_int(CPUINFO_INT_CLOCK_DIVIDER, R.intf->cki);
+
+ /* allocate serial timer */
cop410_serial_timer = timer_alloc(cop410_serial_tick, NULL);
timer_adjust_periodic(cop410_serial_timer, attotime_zero, index, ATTOTIME_IN_HZ(clock));
+ /* initialize instruction length array */
+
for (i=0; i<256; i++) InstLen[i]=1;
InstLen[0x60] = InstLen[0x61] = InstLen[0x68] = InstLen[0x69] = InstLen[0x33] = InstLen[0x23] = 2;
+ /* initialize LBI opcode array */
+
for (i=0; i<256; i++) LBIops[i] = 0;
for (i=0x08; i<0x10; i++) LBIops[i] = 1;
for (i=0x18; i<0x20; i++) LBIops[i] = 1;
for (i=0x28; i<0x30; i++) LBIops[i] = 1;
for (i=0x38; i<0x40; i++) LBIops[i] = 1;
+ /* register for state saving */
+
state_save_register_item("cop410", index, PC);
state_save_register_item("cop410", index, R.PREVPC);
state_save_register_item("cop410", index, A);
@@ -246,6 +271,8 @@ static void cop410_init(int index, int clock, const void *config, int (*irqcallb
state_save_register_item("cop410", index, R.G_mask);
state_save_register_item("cop410", index, R.D_mask);
state_save_register_item("cop410", index, R.si);
+ state_save_register_item("cop410", index, R.microbus_int);
+ state_save_register_item("cop410", index, R.halt);
}
static void cop411_init(int index, int clock, const void *config, int (*irqcallback)(int))
@@ -269,6 +296,8 @@ static void cop410_reset(void)
OUT_D(0);
EN = 0;
WRITE_G(0);
+
+ R.halt = 0;
}
/****************************************************************************
@@ -286,6 +315,13 @@ static int cop410_execute(int cycles)
CALL_DEBUGGER(PC);
+ if (R.intf->cko == COP400_CKO_HALT_IO_PORT)
+ {
+ R.halt = IN_CKO();
+ }
+
+ if (R.halt) continue;
+
opcode = ROM(PC);
if (skipLBI == 1)
@@ -470,7 +506,7 @@ void cop410_get_info(UINT32 state, cpuinfo *info)
void cop411_get_info(UINT32 state, cpuinfo *info)
{
- // COP411 is a 20-pin package version of the COP410, lacking some ports
+ // COP411 is a 20-pin package version of the COP410, missing D2/D3/G3/CKO
switch (state)
{
diff --git a/src/emu/cpu/cop400/cop410ds.c b/src/emu/cpu/cop400/cop410ds.c
index 39494a221e3..d08cdc37220 100644
--- a/src/emu/cpu/cop400/cop410ds.c
+++ b/src/emu/cpu/cop400/cop410ds.c
@@ -231,6 +231,10 @@ offs_t cop410_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opr
sprintf(buffer, "INL");
break;
+ case 0x38:
+ sprintf(buffer, "HALT");
+ break;
+
case 0x3A:
sprintf(buffer, "OMG");
break;
diff --git a/src/emu/cpu/cop400/cop420.c b/src/emu/cpu/cop400/cop420.c
index 7eaa58c16ec..aa0094968a2 100644
--- a/src/emu/cpu/cop400/cop420.c
+++ b/src/emu/cpu/cop400/cop420.c
@@ -13,9 +13,12 @@
TODO:
+ - when is the microbus int cleared?
- run interrupt test suite
- run production test suite
+ - run microbus test suite
- remove LBIops
+ - move cop440 stuff to cop440.c
*/
@@ -36,6 +39,8 @@ typedef struct {
typedef struct
{
+ const cop400_interface *intf;
+
UINT10 PC;
UINT10 PREVPC;
UINT4 A;
@@ -56,6 +61,8 @@ typedef struct
UINT4 in[4];
UINT8 si;
int last_skip;
+ int microbus_int;
+ int halt;
} COP420_Regs;
static COP420_Regs R;
@@ -68,6 +75,7 @@ static int LBIops33[256];
static emu_timer *cop420_serial_timer;
static emu_timer *cop420_counter_timer;
static emu_timer *cop420_inil_timer;
+static emu_timer *cop420_microbus_timer;
#include "420ops.c"
@@ -206,7 +214,7 @@ static const s_opcode opcode_map[256]=
/* Memory Maps */
-static ADDRESS_MAP_START( cop420_internal_rom, ADDRESS_SPACE_DATA, 8 )
+static ADDRESS_MAP_START( cop420_internal_rom, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x000, 0x3ff) AM_ROM
ADDRESS_MAP_END
@@ -214,14 +222,6 @@ static ADDRESS_MAP_START( cop420_internal_ram, ADDRESS_SPACE_DATA, 8 )
AM_RANGE(0x00, 0x3f) AM_RAM
ADDRESS_MAP_END
-static ADDRESS_MAP_START( cop444_internal_rom, ADDRESS_SPACE_DATA, 8 )
- AM_RANGE(0x000, 0x7ff) AM_ROM
-ADDRESS_MAP_END
-
-static ADDRESS_MAP_START( cop444_internal_ram, ADDRESS_SPACE_DATA, 8 )
- AM_RANGE(0x00, 0x7f) AM_RAM
-ADDRESS_MAP_END
-
/* Binary Counter */
static TIMER_CALLBACK(cop420_counter_tick)
@@ -253,6 +253,35 @@ static TIMER_CALLBACK(cop420_inil_tick)
}
}
+/* Microbus */
+
+static TIMER_CALLBACK(cop420_microbus_tick)
+{
+ UINT8 in = IN_IN();
+
+ if (!BIT(in, 2))
+ {
+ // chip select
+
+ if (!BIT(in, 1))
+ {
+ // read strobe
+
+ OUT_L(Q);
+
+ R.microbus_int = 1;
+ }
+ else if (!BIT(in, 3))
+ {
+ // write strobe
+
+ Q = IN_L();
+
+ R.microbus_int = 0;
+ }
+ }
+}
+
/****************************************************************************
* Initialize emulation
****************************************************************************/
@@ -261,24 +290,53 @@ static void cop420_init(int index, int clock, const void *config, int (*irqcallb
int i;
memset(&R, 0, sizeof(R));
- R.G_mask = 0x0F;
- R.D_mask = 0x0F;
+
+ R.intf = (cop400_interface *) config;
+
+ assert(R.intf != NULL);
+
+ /* set output pin masks */
+
+ R.G_mask = 0x0f;
+ R.D_mask = 0x0f;
+
+ /* set clock divider */
+
+ activecpu_set_info_int(CPUINFO_INT_CLOCK_DIVIDER, R.intf->cki);
+
+ /* allocate serial timer */
cop420_serial_timer = timer_alloc(cop410_serial_tick, NULL);
timer_adjust_periodic(cop420_serial_timer, attotime_zero, index, ATTOTIME_IN_HZ(clock));
+ /* allocate counter timer */
+
cop420_counter_timer = timer_alloc(cop420_counter_tick, NULL);
timer_adjust_periodic(cop420_counter_timer, attotime_zero, index, ATTOTIME_IN_HZ(clock));
+ /* allocate IN latch timer */
+
cop420_inil_timer = timer_alloc(cop420_inil_tick, NULL);
timer_adjust_periodic(cop420_inil_timer, attotime_zero, index, ATTOTIME_IN_HZ(clock));
+ /* allocate Microbus timer */
+
+ if (R.intf->microbus == COP400_MICROBUS_ENABLED)
+ {
+ cop420_microbus_timer = timer_alloc(cop420_microbus_tick, NULL);
+ timer_adjust_periodic(cop420_microbus_timer, attotime_zero, index, ATTOTIME_IN_HZ(clock));
+ }
+
+ /* initialize instruction length array */
+
for (i=0; i<256; i++) InstLen[i]=1;
InstLen[0x60] = InstLen[0x61] = InstLen[0x62] = InstLen[0x63] =
InstLen[0x68] = InstLen[0x69] = InstLen[0x6a] = InstLen[0x6b] =
InstLen[0x33] = InstLen[0x23] = 2;
+ /* initialize LBI opcode array */
+
for (i=0; i<256; i++) LBIops[i] = 0;
for (i=0x08; i<0x10; i++) LBIops[i] = 1;
for (i=0x18; i<0x20; i++) LBIops[i] = 1;
@@ -288,6 +346,8 @@ static void cop420_init(int index, int clock, const void *config, int (*irqcallb
for (i=0; i<256; i++) LBIops33[i] = 0;
for (i=0x80; i<0xc0; i++) LBIops33[i] = 1;
+ /* register for state saving */
+
state_save_register_item("cop420", index, PC);
state_save_register_item("cop420", index, R.PREVPC);
state_save_register_item("cop420", index, A);
@@ -310,6 +370,8 @@ static void cop420_init(int index, int clock, const void *config, int (*irqcallb
state_save_register_item("cop420", index, R.si);
state_save_register_item("cop420", index, R.last_skip);
state_save_register_item_array("cop420", index, R.in);
+ state_save_register_item("cop420", index, R.microbus_int);
+ state_save_register_item("cop420", index, R.halt);
}
static void cop422_init(int index, int clock, const void *config, int (*irqcallback)(int))
@@ -320,14 +382,6 @@ static void cop422_init(int index, int clock, const void *config, int (*irqcallb
R.D_mask = 0x0e; // only D2, D3 available
}
-static void cop445_init(int index, int clock, const void *config, int (*irqcallback)(int))
-{
- cop420_init(index, clock, config, irqcallback);
-
- R.G_mask = 0x07;
- R.D_mask = 0x03;
-}
-
/****************************************************************************
* Reset registers to their initial values
****************************************************************************/
@@ -340,6 +394,9 @@ static void cop420_reset(void)
OUT_D(0);
EN = 0;
WRITE_G(0);
+
+ R.counter = 0;
+ R.timerlatch = 1;
}
/****************************************************************************
@@ -406,7 +463,7 @@ static int cop420_execute(int cycles)
skip = 0;
// push next PC
- PUSH(PC + 1);
+ PUSH(PC);
// jump to interrupt service routine
PC = 0x0ff;
@@ -630,10 +687,42 @@ void cop402_get_info(UINT32 state, cpuinfo *info)
}
}
-void cop444_get_info(UINT32 state, cpuinfo *info)
+/* COP44x */
+
+static void cop426_init(int index, int clock, const void *config, int (*irqcallback)(int))
{
- // COP444 is functionally equivalent to COP420, but with twice the RAM/ROM
+ cop420_init(index, clock, config, irqcallback);
+ R.G_mask = 0x0e; // only G2, G3 available
+ R.D_mask = 0x0e; // only D2, D3 available
+}
+
+static void cop445_init(int index, int clock, const void *config, int (*irqcallback)(int))
+{
+ cop420_init(index, clock, config, irqcallback);
+
+ R.G_mask = 0x07;
+ R.D_mask = 0x03;
+}
+
+static ADDRESS_MAP_START( cop424_internal_rom, ADDRESS_SPACE_PROGRAM, 8 )
+ AM_RANGE(0x000, 0x3ff) AM_ROM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( cop424_internal_ram, ADDRESS_SPACE_DATA, 8 )
+ AM_RANGE(0x00, 0x3f) AM_RAM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( cop444_internal_rom, ADDRESS_SPACE_PROGRAM, 8 )
+ AM_RANGE(0x000, 0x7ff) AM_ROM
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( cop444_internal_ram, ADDRESS_SPACE_DATA, 8 )
+ AM_RANGE(0x00, 0x7f) AM_RAM
+ADDRESS_MAP_END
+
+void cop444_get_info(UINT32 state, cpuinfo *info)
+{
switch (state)
{
/* --- the following bits of info are returned as pointers to data or functions --- */
@@ -667,9 +756,60 @@ void cop445_get_info(UINT32 state, cpuinfo *info)
}
}
+void cop424_get_info(UINT32 state, cpuinfo *info)
+{
+ // COP424 is functionally equivalent to COP444, with only 1K ROM and 64x4 bytes RAM
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM:
+ info->internal_map8 = address_map_cop424_internal_rom; break;
+ case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_DATA:
+ info->internal_map8 = address_map_cop424_internal_ram; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "COP424"); break;
+ case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "National Semiconductor COPS"); break;
+
+ default: cop444_get_info(state, info); break;
+ }
+}
+
+void cop425_get_info(UINT32 state, cpuinfo *info)
+{
+ // COP425 is a 24-pin package version of the COP424, lacking the IN ports
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "COP425"); break;
+ case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "National Semiconductor COPS"); break;
+
+ default: cop444_get_info(state, info); break;
+ }
+}
+
+void cop426_get_info(UINT32 state, cpuinfo *info)
+{
+ // COP426 is a 20-pin package version of the COP424, with only L0-L7, G2-G3, D2-D3 ports
+
+ switch (state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_INIT: info->init = cop426_init; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "COP426"); break;
+ case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "National Semiconductor COPS"); break;
+
+ default: cop444_get_info(state, info); break;
+ }
+}
+
void cop404_get_info(UINT32 state, cpuinfo *info)
{
- // COP404 is a ROMless version of the COP444
+ // COP404 is a ROMless version of the COP444, which can emulate a COP410 or a COP424
switch (state)
{
diff --git a/src/mame/drivers/cidelsa.c b/src/mame/drivers/cidelsa.c
index 90caefe2ffd..179fc6e1c0b 100644
--- a/src/mame/drivers/cidelsa.c
+++ b/src/mame/drivers/cidelsa.c
@@ -289,6 +289,15 @@ static CDP1852_INTERFACE( draco_cdp1852_out1_intf )
NULL
};
+/* COP400 Interface */
+
+static COP400_INTERFACE( draco_cop_intf )
+{
+ COP400_CKI_DIVISOR_16, // ???
+ COP400_CKO_OSCILLATOR_OUTPUT, // ???
+ COP400_MICROBUS_DISABLED
+};
+
/* Memory Maps */
// Destroyer
@@ -683,6 +692,7 @@ static MACHINE_DRIVER_START( draco )
MDRV_CPU_ADD(COP420, DRACO_SND_CHR1) // COP402N
MDRV_CPU_PROGRAM_MAP(draco_sound_map, 0)
MDRV_CPU_IO_MAP(draco_sound_io_map, 0)
+ MDRV_CPU_CONFIG(draco_cop_intf)
// input/output hardware
diff --git a/src/mame/drivers/looping.c b/src/mame/drivers/looping.c
index dab1edc3b84..2901921e0e3 100644
--- a/src/mame/drivers/looping.c
+++ b/src/mame/drivers/looping.c
@@ -56,6 +56,7 @@ L056-6 9A " " VLI-8-4 7A "
#include "sound/dac.h"
#include "sound/5220intf.h"
#include "video/resnet.h"
+#include "cpu/cop400/cop400.h"
/*************************************
@@ -570,7 +571,12 @@ static const struct AY8910interface ay8910_interface =
NULL
};
-
+static COP400_INTERFACE( looping_cop_intf )
+{
+ COP400_CKI_DIVISOR_16, // ???
+ COP400_CKO_OSCILLATOR_OUTPUT, // ???
+ COP400_MICROBUS_DISABLED
+};
/*************************************
*
@@ -594,6 +600,7 @@ static MACHINE_DRIVER_START( looping )
MDRV_CPU_ADD(COP420, COP_CLOCK)
MDRV_CPU_PROGRAM_MAP(looping_cop_map,0)
MDRV_CPU_DATA_MAP(looping_cop_data_map,0)
+ MDRV_CPU_CONFIG(looping_cop_intf)
MDRV_MACHINE_START(looping)
diff --git a/src/mame/drivers/thayers.c b/src/mame/drivers/thayers.c
index 50ffb3a03c0..f592642d307 100644
--- a/src/mame/drivers/thayers.c
+++ b/src/mame/drivers/thayers.c
@@ -7,7 +7,6 @@ Notes:
a COP404L - A ROMless COP420 with 1k of RAM. I wonder which one is correct?
Todo:
- Add SIO to the cop420 core.
Fix up my poor interpretation of the hard-to-read schematics.
Write a real SC-01 (SSI-263) emulator for MAME.
Convert to tilemaps.
@@ -293,18 +292,46 @@ static WRITE8_HANDLER(cop_d_write)
}
}
-static WRITE8_HANDLER(cop_sk_write)
-{
- /* I think this data falls off into a black hole - the pins aren't hooked up.
- The COP400 XAS instruction writes to both SK and SIO, that's why the CPU writes data here at all. */
-}
+static int kb_bit;
-static WRITE8_HANDLER(cop_sio_write)
+static READ8_HANDLER(cop_si_r)
{
- /* This data is sent to the CLK pin of the keyboard handling logic. We don't need to emulate it here. */
+ UINT8 data;
+ char port[4];
+ int row = kb_bit / 8;
+ int col = kb_bit % 8;
+
+ sprintf(port, "R%d", row);
+
+ switch (col)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ data = input_port_read(machine, port);
+ return BIT(data, col);
+
+ case 4:
+ return (row == 9);
+
+ default:
+ return 1;
+ }
}
+static WRITE8_HANDLER(cop_so_w)
+{
+ if (data)
+ {
+ kb_bit++;
+ if (kb_bit == 80)
+ {
+ kb_bit = 0;
+ }
+ }
+}
/* PROGRAM MAPS */
static ADDRESS_MAP_START( mainmem, ADDRESS_SPACE_PROGRAM, 8 )
@@ -342,10 +369,9 @@ static ADDRESS_MAP_START( copio, ADDRESS_SPACE_IO, 8 )
AM_RANGE(COP400_PORT_L, COP400_PORT_L) AM_READWRITE(cop_l_read,cop_l_write)
AM_RANGE(COP400_PORT_G, COP400_PORT_G) AM_READWRITE(cop_g_read,cop_g_write)
AM_RANGE(COP400_PORT_D, COP400_PORT_D) AM_WRITE(cop_d_write)
- AM_RANGE(COP400_PORT_SK, COP400_PORT_SK) AM_WRITE(cop_sk_write)
- AM_RANGE(COP400_PORT_SIO,COP400_PORT_SIO) AM_READ_PORT("THAYERS_LETTERS") AM_WRITE(cop_sio_write) /* Unemulated in COP40x core, so nothing happens ATM */
-ADDRESS_MAP_END /* This is also very wrong. The keyboard interface needs to
- be understood much better than what I have here */
+ AM_RANGE(COP400_PORT_SK, COP400_PORT_SK) AM_WRITENOP
+ AM_RANGE(COP400_PORT_SIO,COP400_PORT_SIO) AM_READ(cop_si_r) AM_WRITE(cop_so_w)
+ADDRESS_MAP_END
/* PORTS */
static INPUT_PORTS_START( thayers )
@@ -388,10 +414,8 @@ static INPUT_PORTS_START( thayers )
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(laserdisc_command_r, 0 ) /* Enter pin on LD player */
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(laserdisc_status_r, 0 ) /* Ready pin on LD player */
- /* The following 3 port definitions can be combined into one (thus making this scheme work) if the port bit limit is raised from 32 to 64 */
- /* But maybe there's a better way to do it than what I have here? */
- /* Or maybe this doesn't even work at all :) */
/* "Scan codes" heisted from Daphne - need to be tested! */
+/*
PORT_START_TAG("THAYERS_ACTIONS")
PORT_BIT( 0x30, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME( DEF_STR( No ) ) PORT_CODE( KEYCODE_DEL_PAD )
PORT_BIT( 0x31, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME( DEF_STR( Yes ) ) PORT_CODE( KEYCODE_0_PAD )
@@ -437,13 +461,71 @@ static INPUT_PORTS_START( thayers )
PORT_BIT( 0x81, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME( "2" ) PORT_CODE( KEYCODE_RCONTROL )
PORT_BIT( 0x82, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME( "3 - Enter" ) PORT_CODE( KEYCODE_ENTER )
PORT_BIT( 0x83, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME( "4 - Space" ) PORT_CODE( KEYCODE_SPACE )
+*/
+ PORT_START_TAG("R0")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_OTHER )
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_OTHER )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_OTHER )
+
+ PORT_START_TAG("R1")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_OTHER )
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_OTHER )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_OTHER )
+
+ PORT_START_TAG("R2")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_OTHER )
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_OTHER )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_OTHER )
+
+ PORT_START_TAG("R3")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_OTHER )
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_OTHER )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_OTHER )
+
+ PORT_START_TAG("R4")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_OTHER )
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_OTHER )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_OTHER )
+
+ PORT_START_TAG("R5")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_OTHER )
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_OTHER )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_OTHER )
+
+ PORT_START_TAG("R6")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_OTHER )
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_OTHER )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_OTHER )
+
+ PORT_START_TAG("R7")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_OTHER )
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_OTHER )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_OTHER )
+
+ PORT_START_TAG("R8")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_OTHER )
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_OTHER )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_OTHER )
+
+ PORT_START_TAG("R9")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_OTHER )
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_OTHER )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_OTHER )
INPUT_PORTS_END
-
static MACHINE_START( thayers )
{
discinfo = laserdisc_init(LASERDISC_TYPE_LDV1000, get_disk_handle(0), 0);
- return;
}
static INTERRUPT_GEN( vblank_callback_thayers )
@@ -451,6 +533,12 @@ static INTERRUPT_GEN( vblank_callback_thayers )
laserdisc_vsync(discinfo);
}
+static COP400_INTERFACE( thayers_cop_intf )
+{
+ COP400_CKI_DIVISOR_16, // ???
+ COP400_CKO_OSCILLATOR_OUTPUT, // ???
+ COP400_MICROBUS_DISABLED
+};
/* DRIVER */
static MACHINE_DRIVER_START( thayers )
@@ -466,6 +554,7 @@ static MACHINE_DRIVER_START( thayers )
MDRV_CPU_ADD(COP420, SCHEMATIC_CLOCK/2/8) /* Can't read the schematics, but this is what daphne says */
MDRV_CPU_PROGRAM_MAP(copmem,0)
MDRV_CPU_IO_MAP(copio,0)
+ MDRV_CPU_CONFIG(thayers_cop_intf)
/* video */