summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author Curt Coder <curtcoder@mail.com>2008-06-12 17:20:08 +0000
committer Curt Coder <curtcoder@mail.com>2008-06-12 17:20:08 +0000
commitf8912e4a2d3f7b0817b20ffa62d3e15f00d0bbeb (patch)
tree573407b85f7652108da21011878b025182188f1c /src
parentc10b238896a3e2a78ae8a2b4e44f986dbc375801 (diff)
COP4xx:
- Added COP421 variant Thayer's Quest: - Fixed SSI-263 timings, service mode works now - Changed to use COP421
Diffstat (limited to 'src')
-rw-r--r--src/emu/cpu/cop400/420ops.c22
-rw-r--r--src/emu/cpu/cop400/cop400.h5
-rw-r--r--src/emu/cpu/cop400/cop420.c45
-rw-r--r--src/emu/cpu/cpu.mak3
-rw-r--r--src/emu/cpuexec.h1
-rw-r--r--src/emu/cpuintrf.c4
-rw-r--r--src/mame/drivers/thayers.c148
-rw-r--r--src/mame/mame.mak1
8 files changed, 149 insertions, 80 deletions
diff --git a/src/emu/cpu/cop400/420ops.c b/src/emu/cpu/cop400/420ops.c
index 3633e5e3843..d65f68484eb 100644
--- a/src/emu/cpu/cop400/420ops.c
+++ b/src/emu/cpu/cop400/420ops.c
@@ -17,7 +17,7 @@
#include "410ops.c"
-#define IN_IN() IN(COP400_PORT_IN)
+#define IN_IN() (R.IN_mask ? IN(COP400_PORT_IN) : 0)
/* Arithmetic Instructions */
@@ -245,26 +245,6 @@ INSTRUCTION(inil)
/*
- Processor: COP421
-
- Mnemonic: INIL
-
- Hex Code: 33 29
- Binary:
-
- Data Flow: "0",CKO,"0","0" -> A
-
- Description: Input CKO to A
-
-*/
-
-INSTRUCTION(cop421_inil)
-{
- A = IN_CKO() << 2;
-}
-
-/*
-
Mnemonic: OGI
Operand: y
diff --git a/src/emu/cpu/cop400/cop400.h b/src/emu/cpu/cop400/cop400.h
index 3427b040d30..a12dbd3bde2 100644
--- a/src/emu/cpu/cop400/cop400.h
+++ b/src/emu/cpu/cop400/cop400.h
@@ -39,13 +39,16 @@ 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
+ COP400_CKI_DIVISOR_16 = 16,
+ COP400_CKI_DIVISOR_32 = 32
};
typedef enum _cop400_cko_bond cop400_cko_bond;
enum _cop400_cko_bond {
COP400_CKO_OSCILLATOR_OUTPUT = 0,
+ COP400_CKO_RAM_POWER_SUPPLY,
COP400_CKO_HALT_IO_PORT,
+ COP400_CKO_SYNC_INPUT,
COP400_CKO_GENERAL_PURPOSE_INPUT
};
diff --git a/src/emu/cpu/cop400/cop420.c b/src/emu/cpu/cop400/cop420.c
index 23510320cd3..b9e6ffec0ea 100644
--- a/src/emu/cpu/cop400/cop420.c
+++ b/src/emu/cpu/cop400/cop420.c
@@ -14,6 +14,8 @@
TODO:
- when is the microbus int cleared?
+ - CKO sync input
+ - save internal RAM when CKO is RAM power supply pin
- run interrupt test suite
- run production test suite
- run microbus test suite
@@ -57,6 +59,7 @@ typedef struct
UINT16 counter;
UINT8 G_mask;
UINT8 D_mask;
+ UINT8 IN_mask;
UINT4 IL;
UINT4 in[4];
UINT8 si;
@@ -227,6 +230,7 @@ ADDRESS_MAP_END
static TIMER_CALLBACK(cop420_counter_tick)
{
cpuintrf_push_context(param);
+
R.counter++;
if (R.counter == 1024)
@@ -234,6 +238,7 @@ static TIMER_CALLBACK(cop420_counter_tick)
R.counter = 0;
R.timerlatch = 1;
}
+
cpuintrf_pop_context();
}
@@ -245,6 +250,7 @@ static TIMER_CALLBACK(cop420_inil_tick)
int i;
cpuintrf_push_context(param);
+
in = IN_IN();
for (i = 0; i < 4; i++)
{
@@ -255,6 +261,7 @@ static TIMER_CALLBACK(cop420_inil_tick)
IL |= (1 << i);
}
}
+
cpuintrf_pop_context();
}
@@ -265,7 +272,9 @@ static TIMER_CALLBACK(cop420_microbus_tick)
UINT8 in;
cpuintrf_push_context(param);
+
in = IN_IN();
+
if (!BIT(in, 2))
{
// chip select
@@ -287,6 +296,7 @@ static TIMER_CALLBACK(cop420_microbus_tick)
R.microbus_int = 0;
}
}
+
cpuintrf_pop_context();
}
@@ -305,8 +315,9 @@ static void cop420_init(int index, int clock, const void *config, int (*irqcallb
/* set output pin masks */
- R.G_mask = 0x0f;
- R.D_mask = 0x0f;
+ R.G_mask = 0x0f; // G0-G3 available
+ R.D_mask = 0x0f; // D0-D3 available
+ R.IN_mask = 0x0f; // IN0-IN3 available
/* set clock divider */
@@ -375,6 +386,7 @@ static void cop420_init(int index, int clock, const void *config, int (*irqcallb
state_save_register_item("cop420", index, R.counter);
state_save_register_item("cop420", index, R.G_mask);
state_save_register_item("cop420", index, R.D_mask);
+ state_save_register_item("cop420", index, R.IN_mask);
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);
@@ -382,12 +394,32 @@ static void cop420_init(int index, int clock, const void *config, int (*irqcallb
state_save_register_item("cop420", index, R.halt);
}
+static void cop421_init(int index, int clock, const void *config, int (*irqcallback)(int))
+{
+ cop420_init(index, clock, config, irqcallback);
+
+ /* microbus option is not available */
+
+ assert(R.intf->microbus != COP400_MICROBUS_ENABLED);
+
+ /* set output pin masks */
+
+ R.IN_mask = 0; // IN lines not available
+}
+
static void cop422_init(int index, int clock, const void *config, int (*irqcallback)(int))
{
cop420_init(index, clock, config, irqcallback);
+ /* microbus option is not available */
+
+ assert(R.intf->microbus != COP400_MICROBUS_ENABLED);
+
+ /* set output pin masks */
+
R.G_mask = 0x0e; // only G2, G3 available
R.D_mask = 0x0e; // only D2, D3 available
+ R.IN_mask = 0; // IN lines not available
}
/****************************************************************************
@@ -652,17 +684,20 @@ void cop421_get_info(UINT32 state, cpuinfo *info)
switch (state)
{
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_INIT: info->init = cop421_init; break;
+
/* --- the following bits of info are returned as NULL-terminated strings --- */
case CPUINFO_STR_NAME: strcpy(info->s, "COP421"); break;
case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "National Semiconductor COPS"); break;
- default: cop410_get_info(state, info); break;
+ default: cop420_get_info(state, info); break;
}
}
void cop422_get_info(UINT32 state, cpuinfo *info)
{
- // COP422 is a 20-pin package version of the COP420, lacking the IN ports
+ // COP422 is a 20-pin package version of the COP420, lacking G0/G1, D0/D1, and the IN ports
switch (state)
{
@@ -673,7 +708,7 @@ void cop422_get_info(UINT32 state, cpuinfo *info)
case CPUINFO_STR_NAME: strcpy(info->s, "COP422"); break;
case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "National Semiconductor COPS"); break;
- default: cop410_get_info(state, info); break;
+ default: cop420_get_info(state, info); break;
}
}
diff --git a/src/emu/cpu/cpu.mak b/src/emu/cpu/cpu.mak
index 49b387a5236..8a0cb72fc38 100644
--- a/src/emu/cpu/cpu.mak
+++ b/src/emu/cpu/cpu.mak
@@ -268,6 +268,7 @@ $(CPUOBJ)/cdp1802/cdp1802.o: $(CPUSRC)/cdp1802/cdp1802.c \
CPUDEFS += -DHAS_COP410=$(if $(filter COP410,$(CPUS)),1,0)
CPUDEFS += -DHAS_COP411=$(if $(filter COP411,$(CPUS)),1,0)
CPUDEFS += -DHAS_COP420=$(if $(filter COP420,$(CPUS)),1,0)
+CPUDEFS += -DHAS_COP421=$(if $(filter COP421,$(CPUS)),1,0)
ifneq ($(filter COP410 COP411,$(CPUS)),)
OBJDIRS += $(CPUOBJ)/cop400
@@ -275,7 +276,7 @@ CPUOBJS += $(CPUOBJ)/cop400/cop410.o
DBGOBJS += $(CPUOBJ)/cop400/cop410ds.o
endif
-ifneq ($(filter COP420,$(CPUS)),)
+ifneq ($(filter COP420 COP421,$(CPUS)),)
OBJDIRS += $(CPUOBJ)/cop400
CPUOBJS += $(CPUOBJ)/cop400/cop420.o
DBGOBJS += $(CPUOBJ)/cop400/cop420ds.o
diff --git a/src/emu/cpuexec.h b/src/emu/cpuexec.h
index dbc608f391e..1670e993386 100644
--- a/src/emu/cpuexec.h
+++ b/src/emu/cpuexec.h
@@ -218,6 +218,7 @@ enum _cpu_type
CPU_ALPHA8301,
CPU_CDP1802,
CPU_COP420,
+ CPU_COP421,
CPU_COP410,
CPU_COP411,
CPU_TMP90840,
diff --git a/src/emu/cpuintrf.c b/src/emu/cpuintrf.c
index dd5094db184..c72c5cba199 100644
--- a/src/emu/cpuintrf.c
+++ b/src/emu/cpuintrf.c
@@ -190,6 +190,7 @@ void alpha8201_get_info(UINT32 state, cpuinfo *info);
void alpha8301_get_info(UINT32 state, cpuinfo *info);
void cdp1802_get_info(UINT32 state, cpuinfo *info);
void cop420_get_info(UINT32 state, cpuinfo *info);
+void cop421_get_info(UINT32 state, cpuinfo *info);
void cop410_get_info(UINT32 state, cpuinfo *info);
void cop411_get_info(UINT32 state, cpuinfo *info);
void tmp90840_get_info(UINT32 state, cpuinfo *info);
@@ -766,6 +767,9 @@ static const struct
#if (HAS_COP420)
{ CPU_COP420, cop420_get_info },
#endif
+#if (HAS_COP421)
+ { CPU_COP421, cop421_get_info },
+#endif
#if (HAS_COP410)
{ CPU_COP410, cop410_get_info },
#endif
diff --git a/src/mame/drivers/thayers.c b/src/mame/drivers/thayers.c
index d3de8547f47..e4336a3b842 100644
--- a/src/mame/drivers/thayers.c
+++ b/src/mame/drivers/thayers.c
@@ -2,9 +2,11 @@
TODO:
- - game gets stuck in a loop at 2224
- - SSI263 sound
- - laserdisc
+ - LDV1000 mode
+ - PR7820 INT/_EXT line
+ - coin counter
+ - convert SSI-263 to a sound device
+ - dump laserdisc
*/
@@ -13,6 +15,7 @@
#include "machine/laserdsc.h"
#include "cpu/cop400/cop400.h"
//#include "dlair.lh"
+
extern const char layout_dlair[];
static laserdisc_info *discinfo;
@@ -32,9 +35,9 @@ static int data_rdy_int = 1;
static int ssi_data_request = 1;
static int cart_present;
+static int pr7820_enter;
-static const UINT8 led_map[16] =
- { 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7c,0x07,0x7f,0x67,0x77,0x7c,0x39,0x5e,0x79,0x00 };
+static const UINT8 led_map[16] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7c, 0x07, 0x7f, 0x67, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x00 };
/* Video */
@@ -83,7 +86,7 @@ static READ8_HANDLER( irqstate_r )
0
1
- 2 SSI263 data request
+ 2 SSI263 A/_R
3 tied to +5V
4 _TIMER INT
5 _DATA RDY INT
@@ -329,7 +332,7 @@ static WRITE8_HANDLER( laserdsc_data_w )
laserdisc_data = data;
}
-static WRITE8_HANDLER( counter_w )
+static WRITE8_HANDLER( laserdsc_control_w )
{
/*
@@ -342,41 +345,31 @@ static WRITE8_HANDLER( counter_w )
4 coin counter
5 U16 output enable
6 ENTER if switch B5 closed
- 7
+ 7 INT/_EXT
*/
- coin_counter_w(0, !BIT(data, 4));
+ coin_counter_w(0, BIT(data, 4));
if (BIT(data, 5))
{
laserdisc_data_w(discinfo, laserdisc_data);
}
- if (laserdisc_type == LASERDISC_TYPE_PR7820)
+ switch (laserdisc_type)
{
- laserdisc_line_w(discinfo, LASERDISC_LINE_ENTER, BIT(data, 6) ? CLEAR_LINE : ASSERT_LINE);
- }
-}
-
-static READ8_HANDLER( laserdsc_status_r )
-{
- /*
+ case LASERDISC_TYPE_PR7820:
+ pr7820_enter = BIT(data, 6) ? CLEAR_LINE : ASSERT_LINE;
- bit description
+ laserdisc_line_w(discinfo, LASERDISC_LINE_ENTER, pr7820_enter);
- 0
- 1
- 2
- 3
- 4
- 5
- 6
- 7 INT/_EXT
-
- */
+ // BIT(data, 7) is INT/_EXT, but there is no such input line in laserdsc.h
+ break;
- return 0;
+ case LASERDISC_TYPE_LDV1000:
+ laserdisc_line_w(discinfo, LASERDISC_LINE_ENTER, BIT(data, 7) ? CLEAR_LINE : ASSERT_LINE);
+ break;
+ }
}
static WRITE8_HANDLER( den1_w )
@@ -419,7 +412,17 @@ static WRITE8_HANDLER( den2_w )
output_set_digit_value(8 + (data >> 4), led_map[data & 0x0f]);
}
-/* SSI 263 */
+/* SSI-263 */
+
+/*
+
+ The following information is from the SSI-263A data sheet.
+
+ Thayer's Quest uses an SSI-263, so this might be inaccurate, but it works for now
+
+*/
+
+#define SSI263_CLOCK (XTAL_4MHz/2)
static const char SSI263_PHONEMES[0x40][5] =
{
@@ -437,29 +440,57 @@ static struct SSI263
UINT8 c;
UINT8 a;
UINT8 f;
+ UINT8 mode;
} ssi263;
+static TIMER_CALLBACK( ssi263_phoneme_tick )
+{
+ ssi_data_request = 0;
+ check_interrupt(machine);
+}
+
static WRITE8_HANDLER( ssi263_register_w )
{
switch (offset)
{
case 0:
+ {
+ int frame_time = ((4096 * (16 - ssi263.r)) / 2); // us, /2 should actually be /SSI263_CLOCK, but this way we get microseconds directly
+ int phoneme_time = frame_time * (4 - ssi263.dr); // us
+
// duration/phoneme register
- ssi263.dr = data >> 5;
+ ssi263.dr = (data >> 5) & 0x03;
ssi263.p = data & 0x3f;
ssi_data_request = 1;
check_interrupt(machine);
- logerror("SSI263 Phoneme Duration: %u\n", ssi263.dr);
- logerror("SSI263 Phoneme: %02x %s\n", ssi263.p, SSI263_PHONEMES[ssi263.p]);
+ switch (ssi263.mode)
+ {
+ case 0:
+ case 1:
+ // phoneme timing response
+ timer_set(ATTOTIME_IN_USEC(phoneme_time), NULL, 0, ssi263_phoneme_tick);
+ break;
+ case 2:
+ // frame timing response
+ timer_set(ATTOTIME_IN_USEC(frame_time), NULL, 0, ssi263_phoneme_tick);
+ break;
+ case 3:
+ // disable A/_R output
+ break;
+ }
+
+ //logerror("SSI263 Phoneme Duration: %u\n", ssi263.dr);
+ //logerror("SSI263 Phoneme: %02x %s\n", ssi263.p, SSI263_PHONEMES[ssi263.p]);
+ }
break;
case 1:
// inflection register
ssi263.i = (data << 3) | (ssi263.i & 0x403);
- logerror("SSI263 Inflection: %u\n", ssi263.i);
+ //logerror("SSI263 Inflection: %u\n", ssi263.i);
break;
case 2:
@@ -467,24 +498,34 @@ static WRITE8_HANDLER( ssi263_register_w )
ssi263.i = (BIT(data, 4) << 11) | (ssi263.i & 0x7f8) | (data & 0x07);
ssi263.r = data >> 4;
- logerror("SSI263 Inflection: %u\n", ssi263.i);
- logerror("SSI263 Rate: %u\n", ssi263.r);
+ //logerror("SSI263 Inflection: %u\n", ssi263.i);
+ //logerror("SSI263 Rate: %u\n", ssi263.r);
break;
case 3:
// control/articulation/amplitude register
if (ssi263.c && !BIT(data, 7))
{
- switch (ssi263.dr)
+ ssi263.mode = ssi263.dr;
+
+ switch (ssi263.mode)
{
case 0:
+ //logerror("SSI263 Phoneme Timing Response, Transitioned Inflection\n");
+ break;
+
case 1:
+ //logerror("SSI263 Phoneme Timing Response, Immediate Inflection\n");
+ break;
+
case 2:
- ssi_data_request = 0;
- check_interrupt(machine);
+ // activate A/_R
+ //logerror("SSI263 Frame Timing Response, Immediate Inflection\n");
break;
+
case 3:
// disable A/_R output
+ //logerror("SSI263 A/R Output Disabled\n");
break;
}
}
@@ -493,9 +534,9 @@ static WRITE8_HANDLER( ssi263_register_w )
ssi263.t = (data >> 4) & 0x07;
ssi263.a = data & 0x0f;
- logerror("SSI263 Control: %u\n", ssi263.c);
- logerror("SSI263 Articulation: %u\n", ssi263.t);
- logerror("SSI263 Amplitude: %u\n", ssi263.a);
+ //logerror("SSI263 Control: %u\n", ssi263.c);
+ //logerror("SSI263 Articulation: %u\n", ssi263.t);
+ //logerror("SSI263 Amplitude: %u\n", ssi263.a);
break;
case 4:
@@ -504,13 +545,15 @@ static WRITE8_HANDLER( ssi263_register_w )
case 7:
// filter frequency register
ssi263.f = data;
- logerror("SSI263 Filter Frequency: %u\n", ssi263.f);
+ //logerror("SSI263 Filter Frequency: %u\n", ssi263.f);
break;
}
}
static READ8_HANDLER( ssi263_register_r )
{
+ // D7 becomes an output, as the inverted state of A/_R. The register address bits are ignored.
+
return !ssi_data_request << 7;
}
@@ -535,7 +578,7 @@ static ADDRESS_MAP_START( thayers_io_map, ADDRESS_SPACE_IO, 8 )
AM_RANGE(0xf2, 0xf2) AM_READ_PORT("DSWA")
AM_RANGE(0xf3, 0xf3) AM_WRITE(intrq_w)
AM_RANGE(0xf4, 0xf4) AM_WRITE(laserdsc_data_w)
- AM_RANGE(0xf5, 0xf5) AM_READWRITE(laserdsc_status_r, counter_w)
+ AM_RANGE(0xf5, 0xf5) AM_WRITE(laserdsc_control_w)
AM_RANGE(0xf6, 0xf6) AM_WRITE(den1_w)
AM_RANGE(0xf7, 0xf7) AM_WRITE(den2_w)
ADDRESS_MAP_END
@@ -548,14 +591,13 @@ static ADDRESS_MAP_START( thayers_cop_io_map, ADDRESS_SPACE_IO, 8 )
AM_RANGE(COP400_PORT_L, COP400_PORT_L) AM_READWRITE(cop_l_r, cop_l_w)
AM_RANGE(COP400_PORT_G, COP400_PORT_G) AM_READWRITE(cop_g_r, cop_g_w)
AM_RANGE(COP400_PORT_D, COP400_PORT_D) AM_WRITE(cop_d_w)
- AM_RANGE(COP400_PORT_IN, COP400_PORT_IN) AM_READNOP
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
/* Input Ports */
-static CUSTOM_INPUT( laserdisc_status_r )
+static CUSTOM_INPUT( laserdisc_enter_r )
{
if (discinfo == NULL)
return 0;
@@ -563,7 +605,7 @@ static CUSTOM_INPUT( laserdisc_status_r )
switch (laserdisc_type)
{
case LASERDISC_TYPE_PR7820:
- return 0;
+ return pr7820_enter;
case LASERDISC_TYPE_LDV1000:
return (laserdisc_line_r(discinfo, LASERDISC_LINE_STATUS) == ASSERT_LINE) ? 0 : 1;
@@ -572,7 +614,7 @@ static CUSTOM_INPUT( laserdisc_status_r )
return 0;
}
-static CUSTOM_INPUT( laserdisc_command_r )
+static CUSTOM_INPUT( laserdisc_ready_r )
{
if (discinfo == NULL)
return 0;
@@ -618,7 +660,7 @@ static INPUT_PORTS_START( thayers )
PORT_SERVICE_DIPLOC( 0x01, 0x01, "B:1" )
PORT_DIPUNUSED_DIPLOC( 0x02, IP_ACTIVE_LOW, "B:2" )
PORT_DIPUNUSED_DIPLOC( 0x04, IP_ACTIVE_LOW, "B:3" )
- PORT_DIPNAME( 0x18, 0x18, "LD Player" ) PORT_DIPLOCATION( "B:5,4" )
+ PORT_DIPNAME( 0x18, 0x00, "LD Player" ) PORT_DIPLOCATION( "B:5,4" )
PORT_DIPSETTING( 0x18, "LDV-1000" )
PORT_DIPSETTING( 0x00, "PR-7820" )
PORT_DIPUNUSED_DIPLOC( 0xe0, IP_ACTIVE_LOW, "B:8,7,6" )
@@ -626,8 +668,8 @@ static INPUT_PORTS_START( thayers )
PORT_START_TAG("COIN")
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_COIN1 )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_COIN2 )
- 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 */
+ PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(laserdisc_enter_r, 0 )
+ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM(laserdisc_ready_r, 0 )
PORT_START_TAG("R0")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME( "2" ) PORT_CODE( KEYCODE_F2 )
@@ -697,6 +739,8 @@ static MACHINE_START( thayers )
laserdisc_type = LASERDISC_TYPE_LDV1000;
discinfo = laserdisc_init(laserdisc_type, get_disk_handle(0), 0);
+
+ memset(&ssi263, 0, sizeof(ssi263));
}
static MACHINE_RESET( thayers )
@@ -732,7 +776,7 @@ static MACHINE_DRIVER_START( thayers )
MDRV_MACHINE_START(thayers)
MDRV_MACHINE_RESET(thayers)
- MDRV_CPU_ADD(COP420, XTAL_4MHz/2) // COP421L-PCA/N
+ MDRV_CPU_ADD(COP421, XTAL_4MHz/2) // COP421L-PCA/N
MDRV_CPU_PROGRAM_MAP(thayers_cop_map, 0)
MDRV_CPU_IO_MAP(thayers_cop_io_map, 0)
MDRV_CPU_CONFIG(thayers_cop_intf)
diff --git a/src/mame/mame.mak b/src/mame/mame.mak
index 79226a43668..691f92d92c5 100644
--- a/src/mame/mame.mak
+++ b/src/mame/mame.mak
@@ -185,6 +185,7 @@ CPUS += ALPHA8201
CPUS += ALPHA8301
CPUS += CDP1802
CPUS += COP420
+CPUS += COP421
CPUS += COP410
CPUS += TLCS90
CPUS += MB8841