diff options
author | 2008-06-12 17:20:08 +0000 | |
---|---|---|
committer | 2008-06-12 17:20:08 +0000 | |
commit | f8912e4a2d3f7b0817b20ffa62d3e15f00d0bbeb (patch) | |
tree | 573407b85f7652108da21011878b025182188f1c /src | |
parent | c10b238896a3e2a78ae8a2b4e44f986dbc375801 (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.c | 22 | ||||
-rw-r--r-- | src/emu/cpu/cop400/cop400.h | 5 | ||||
-rw-r--r-- | src/emu/cpu/cop400/cop420.c | 45 | ||||
-rw-r--r-- | src/emu/cpu/cpu.mak | 3 | ||||
-rw-r--r-- | src/emu/cpuexec.h | 1 | ||||
-rw-r--r-- | src/emu/cpuintrf.c | 4 | ||||
-rw-r--r-- | src/mame/drivers/thayers.c | 148 | ||||
-rw-r--r-- | src/mame/mame.mak | 1 |
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 |