diff options
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 |
commit | 6d6a5b237d78ca39473e4291c1ed70d6b558f46d (patch) | |
tree | d9b69f44cdd7e65e8f69b1458b13bb71cf28897f | |
parent | 5817f03b73f4d77dc6381d4b4f110c6867a30e24 (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.c | 64 | ||||
-rw-r--r-- | src/emu/cpu/cop400/cop400.h | 48 | ||||
-rw-r--r-- | src/emu/cpu/cop400/cop410.c | 48 | ||||
-rw-r--r-- | src/emu/cpu/cop400/cop410ds.c | 4 | ||||
-rw-r--r-- | src/emu/cpu/cop400/cop420.c | 186 | ||||
-rw-r--r-- | src/mame/drivers/cidelsa.c | 10 | ||||
-rw-r--r-- | src/mame/drivers/looping.c | 9 | ||||
-rw-r--r-- | src/mame/drivers/thayers.c | 123 |
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 */ |