From b6e1d3d986cdceaabcfae73250c49e617dfb32eb Mon Sep 17 00:00:00 2001 From: hap Date: Wed, 5 Aug 2015 17:54:26 +0200 Subject: [PATCH] New game added ----------------- Castle Toy Tactix [hap, Sean Riddle, Kevin Horton] --- src/emu/cpu/ucom4/ucom4.c | 89 +++++++++++++++++++++ src/emu/cpu/ucom4/ucom4.h | 17 +++- src/emu/cpu/ucom4/ucom4op.c | 44 +---------- src/mame/mess.lst | 1 + src/mess/drivers/hh_ucom4.c | 135 ++++++++++++++++++++++++++++++++ src/mess/layout/tactix.lay | 152 ++++++++++++++++++++++++++++++++++++ 6 files changed, 393 insertions(+), 45 deletions(-) create mode 100644 src/mess/layout/tactix.lay diff --git a/src/emu/cpu/ucom4/ucom4.c b/src/emu/cpu/ucom4/ucom4.c index 569047e9bf0..1d3da737b77 100644 --- a/src/emu/cpu/ucom4/ucom4.c +++ b/src/emu/cpu/ucom4/ucom4.c @@ -26,6 +26,7 @@ // uCOM-43 products: 2000x8 ROM, RAM size custom, supports full instruction set const device_type NEC_D553 = &device_creator; // 42-pin PMOS, 35 pins for I/O, Open Drain output, 96x4 RAM +const device_type NEC_D557L = &device_creator; // 28-pin PMOS, 21 pins for I/O, Open Drain output, 96x4 RAM const device_type NEC_D650 = &device_creator; // 42-pin CMOS, 35 pins for I/O, push-pull output, 96x4 RAM // uCOM-44 products: 1000x8 ROM, 64x4 RAM, does not support external interrupt @@ -61,6 +62,10 @@ upd553_cpu_device::upd553_cpu_device(const machine_config &mconfig, const char * : ucom4_cpu_device(mconfig, NEC_D553, "uPD553", tag, owner, clock, NEC_UCOM43, 3 /* stack levels */, 11 /* prg width */, ADDRESS_MAP_NAME(program_2k), 7 /* data width */, ADDRESS_MAP_NAME(data_96x4), "upd553", __FILE__) { } +upd557l_cpu_device::upd557l_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : ucom4_cpu_device(mconfig, NEC_D557L, "uPD557L", tag, owner, clock, NEC_UCOM43, 3, 11, ADDRESS_MAP_NAME(program_2k), 7, ADDRESS_MAP_NAME(data_96x4), "upd557l", __FILE__) +{ } + upd650_cpu_device::upd650_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : ucom4_cpu_device(mconfig, NEC_D650, "uPD650", tag, owner, clock, NEC_UCOM43, 3, 11, ADDRESS_MAP_NAME(program_2k), 7, ADDRESS_MAP_NAME(data_96x4), "upd650", __FILE__) { } @@ -207,6 +212,90 @@ void ucom4_cpu_device::device_reset() +//------------------------------------------------- +// i/o handling +//------------------------------------------------- + +// default: +// A,B are inputs, C,D are input/output, E,F,G,H,I are output + +UINT8 ucom4_cpu_device::input_r(int index) +{ + index &= 0xf; + UINT8 inp = 0; + + switch (index) + { + case NEC_UCOM4_PORTA: inp = m_read_a(index, 0xff); break; + case NEC_UCOM4_PORTB: inp = m_read_b(index, 0xff); break; + case NEC_UCOM4_PORTC: inp = m_read_c(index, 0xff) | m_port_out[index]; break; + case NEC_UCOM4_PORTD: inp = m_read_d(index, 0xff) | m_port_out[index]; break; + + default: + logerror("%s read from unknown port %c at $%03X\n", tag(), 'A' + index, m_prev_pc); + break; + } + + return inp & 0xf; +} + +void ucom4_cpu_device::output_w(int index, UINT8 data) +{ + index &= 0xf; + data &= 0xf; + + switch (index) + { + case NEC_UCOM4_PORTC: m_write_c(index, data, 0xff); break; + case NEC_UCOM4_PORTD: m_write_d(index, data, 0xff); break; + case NEC_UCOM4_PORTE: m_write_e(index, data, 0xff); break; + case NEC_UCOM4_PORTF: m_write_f(index, data, 0xff); break; + case NEC_UCOM4_PORTG: m_write_g(index, data, 0xff); break; + case NEC_UCOM4_PORTH: m_write_h(index, data, 0xff); break; + case NEC_UCOM4_PORTI: m_write_i(index, data & 7, 0xff); break; + + default: + logerror("%s write to unknown port %c = $%X at $%03X\n", tag(), 'A' + index, data, m_prev_pc); + break; + } + + m_port_out[index] = data; +} + +// uPD557L: +// ports B,H,I are stripped, port G is reduced to 1 pin + +UINT8 upd557l_cpu_device::input_r(int index) +{ + index &= 0xf; + + if (index == NEC_UCOM4_PORTB) + logerror("%s read from unknown port %c at $%03X\n", tag(), 'A' + index, m_prev_pc); + else + return ucom4_cpu_device::input_r(index); + + return 0; +} + +void upd557l_cpu_device::output_w(int index, UINT8 data) +{ + index &= 0xf; + data &= 0xf; + + if (index == NEC_UCOM4_PORTH || index == NEC_UCOM4_PORTI) + logerror("%s write to unknown port %c = $%X at $%03X\n", tag(), 'A' + index, data, m_prev_pc); + else + { + // only G0 for port G + if (index == NEC_UCOM4_PORTG) + data &= 1; + + ucom4_cpu_device::output_w(index, data); + } +} + + + //------------------------------------------------- // interrupt //------------------------------------------------- diff --git a/src/emu/cpu/ucom4/ucom4.h b/src/emu/cpu/ucom4/ucom4.h index 5a2105bd4bc..9b0651b6703 100644 --- a/src/emu/cpu/ucom4/ucom4.h +++ b/src/emu/cpu/ucom4/ucom4.h @@ -207,6 +207,9 @@ protected: devcb_write8 m_write_h; devcb_write8 m_write_i; + virtual UINT8 input_r(int index); + virtual void output_w(int index, UINT8 data); + // misc internal helpers void increment_pc(); void fetch_arg(); @@ -216,8 +219,6 @@ protected: void ram_w(UINT8 data); void pop_stack(); void push_stack(); - virtual UINT8 input_r(int index); - virtual void output_w(int index, UINT8 data); bool check_op_43(); TIMER_CALLBACK_MEMBER( simple_timer_cb ); @@ -318,6 +319,17 @@ public: }; +class upd557l_cpu_device : public ucom4_cpu_device +{ +public: + upd557l_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + +protected: + virtual UINT8 input_r(int index); + virtual void output_w(int index, UINT8 data); +}; + + class upd650_cpu_device : public ucom4_cpu_device { public: @@ -334,6 +346,7 @@ public: extern const device_type NEC_D553; +extern const device_type NEC_D557L; extern const device_type NEC_D650; extern const device_type NEC_D552; diff --git a/src/emu/cpu/ucom4/ucom4op.c b/src/emu/cpu/ucom4/ucom4op.c index 6fad00fe20b..a9c5c0fe892 100644 --- a/src/emu/cpu/ucom4/ucom4op.c +++ b/src/emu/cpu/ucom4/ucom4op.c @@ -34,48 +34,9 @@ void ucom4_cpu_device::push_stack() m_stack[0] = m_pc; } -UINT8 ucom4_cpu_device::input_r(int index) -{ - index &= 0xf; - UINT8 inp = 0xf; - switch (index) - { - case NEC_UCOM4_PORTA: inp = m_read_a(index, 0xff); break; - case NEC_UCOM4_PORTB: inp = m_read_b(index, 0xff); break; - case NEC_UCOM4_PORTC: inp = m_read_c(index, 0xff) | m_port_out[index]; break; - case NEC_UCOM4_PORTD: inp = m_read_d(index, 0xff) | m_port_out[index]; break; - default: - logerror("%s read from unknown port %c at $%03X\n", tag(), 'A' + index, m_prev_pc); - break; - } - - return inp & 0xf; -} - -void ucom4_cpu_device::output_w(int index, UINT8 data) -{ - index &= 0xf; - data &= 0xf; - - switch (index) - { - case NEC_UCOM4_PORTC: m_write_c(index, data, 0xff); break; - case NEC_UCOM4_PORTD: m_write_d(index, data, 0xff); break; - case NEC_UCOM4_PORTE: m_write_e(index, data, 0xff); break; - case NEC_UCOM4_PORTF: m_write_f(index, data, 0xff); break; - case NEC_UCOM4_PORTG: m_write_g(index, data, 0xff); break; - case NEC_UCOM4_PORTH: m_write_h(index, data, 0xff); break; - case NEC_UCOM4_PORTI: m_write_i(index, data & 7, 0xff); break; - - default: - logerror("%s write to unknown port %c = $%X at $%03X\n", tag(), 'A' + index, data & 0xf, m_prev_pc); - break; - } - - m_port_out[index] = data; -} +// basic instruction set void ucom4_cpu_device::op_illegal() { @@ -83,9 +44,6 @@ void ucom4_cpu_device::op_illegal() } - -// basic instruction set - // Load void ucom4_cpu_device::op_li() diff --git a/src/mame/mess.lst b/src/mame/mess.lst index 8bd4d8fdea2..786b9213b64 100644 --- a/src/mame/mess.lst +++ b/src/mame/mess.lst @@ -2263,6 +2263,7 @@ bmsoccer // Bambino bmsafari // Bambino splasfgt // Bambino bcclimbr // Bandai +tactix // Castle Toy invspace // Epoch efball // Epoch galaxy2 // Epoch diff --git a/src/mess/drivers/hh_ucom4.c b/src/mess/drivers/hh_ucom4.c index b1f016fa194..2f32abac1c4 100644 --- a/src/mess/drivers/hh_ucom4.c +++ b/src/mess/drivers/hh_ucom4.c @@ -44,6 +44,8 @@ @209 uPD553C 1982, Tomy Caveman (TN-12) @258 uPD553C 1984, Tomy Alien Chase (TN-16) + @512 uPD557LC 1980, Castle Toy Tactix + *060 uPD650C 1979, Mattel Computer Gin *085 uPD650C 1980, Roland TR-808 *127 uPD650C 198?, Sony OA-S1100 Typecorder (subcpu, have dump) @@ -52,6 +54,11 @@ (* denotes not yet emulated by MAME, @ denotes it's in this driver) + +TODO: + - games that rely on the fact that faster/longer strobed elements appear brighter: + tactix(player 2) + ***************************************************************************/ #include "includes/hh_ucom4.h" @@ -59,6 +66,7 @@ // internal artwork #include "efball.lh" #include "mvbfree.lh" +#include "tactix.lh" // clickable #include "hh_ucom4_test.lh" // common test-layout - use external artwork @@ -956,6 +964,125 @@ MACHINE_CONFIG_END +/*************************************************************************** + + Castle Toy Tactix + * NEC uCOM-43 MCU, labeled D557LC 512 + * 16 LEDs behind buttons + + Tactix is similar to Merlin, for 1 or 2 players. In 2-player mode, simply + don't press the Comp Turn button. The four included minigames are: + 1: Capture (reversi) + 2: Jump-Off (peg solitaire) + 3: Triple Play (3 in a row) + 4: Concentration (memory) + + note: MAME external artwork is not needed for this game + +***************************************************************************/ + +class tactix_state : public hh_ucom4_state +{ +public: + tactix_state(const machine_config &mconfig, device_type type, const char *tag) + : hh_ucom4_state(mconfig, type, tag) + { } + + DECLARE_WRITE8_MEMBER(leds_w); + DECLARE_WRITE8_MEMBER(speaker_w); + DECLARE_WRITE8_MEMBER(input_w); + DECLARE_READ8_MEMBER(input_r); +}; + +// handlers + +WRITE8_MEMBER(tactix_state::leds_w) +{ + // D,F: 4*4 led matrix + m_port[offset] = data; + display_matrix(4, 4, m_port[NEC_UCOM4_PORTD], m_port[NEC_UCOM4_PORTF]); +} + +WRITE8_MEMBER(tactix_state::speaker_w) +{ + // G0: speaker out + m_speaker->level_w(data & 1); +} + +WRITE8_MEMBER(tactix_state::input_w) +{ + // C,E0: input mux + m_port[offset] = data; + m_inp_mux = (m_port[NEC_UCOM4_PORTE] << 4 & 0x10) | m_port[NEC_UCOM4_PORTC]; +} + +READ8_MEMBER(tactix_state::input_r) +{ + // A: multiplexed inputs + return read_inputs(5); +} + + +// config + +static INPUT_PORTS_START( tactix ) + PORT_START("IN.0") // C0 port A + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_1) PORT_NAME("Button 1") + PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_Q) PORT_NAME("Button 5") + PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_A) PORT_NAME("Button 9") + PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_Z) PORT_NAME("Button 13") + + PORT_START("IN.1") // C1 port A + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_2) PORT_NAME("Button 2") + PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_W) PORT_NAME("Button 6") + PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_S) PORT_NAME("Button 10") + PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_X) PORT_NAME("Button 14") + + PORT_START("IN.2") // C2 port A + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_3) PORT_NAME("Button 3") + PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_E) PORT_NAME("Button 7") + PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_D) PORT_NAME("Button 11") + PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_C) PORT_NAME("Button 15") + + PORT_START("IN.3") // C3 port A + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_4) PORT_NAME("Button 4") + PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_R) PORT_NAME("Button 8") + PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_F) PORT_NAME("Button 12") + PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_V) PORT_NAME("Button 16") + + PORT_START("IN.4") // E0 port A + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_5) //todo.. + PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_6) + PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_7) + PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYPAD) PORT_CODE(KEYCODE_8) +INPUT_PORTS_END + +static MACHINE_CONFIG_START( tactix, tactix_state ) + + /* basic machine hardware */ + MCFG_CPU_ADD("maincpu", NEC_D557L, 400000) // approximation + MCFG_UCOM4_READ_A_CB(READ8(tactix_state, input_r)) + MCFG_UCOM4_WRITE_C_CB(WRITE8(tactix_state, input_w)) + MCFG_UCOM4_WRITE_D_CB(WRITE8(tactix_state, leds_w)) + MCFG_UCOM4_WRITE_E_CB(WRITE8(tactix_state, input_w)) + MCFG_UCOM4_WRITE_F_CB(WRITE8(tactix_state, leds_w)) + MCFG_UCOM4_WRITE_G_CB(WRITE8(tactix_state, speaker_w)) + + MCFG_TIMER_DRIVER_ADD_PERIODIC("display_decay", hh_ucom4_state, display_decay_tick, attotime::from_msec(1)) + MCFG_DEFAULT_LAYOUT(layout_tactix) + + /* no video! */ + + /* sound hardware */ + MCFG_SPEAKER_STANDARD_MONO("mono") + MCFG_SOUND_ADD("speaker", SPEAKER_SOUND, 0) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) +MACHINE_CONFIG_END + + + + + /*************************************************************************** Epoch Invader From Space (manufactured in Japan) @@ -2319,6 +2446,12 @@ ROM_START( bcclimbr ) ROM_END +ROM_START( tactix ) + ROM_REGION( 0x0800, "maincpu", 0 ) + ROM_LOAD( "d557lc-512", 0x0000, 0x0800, CRC(1df738cb) SHA1(15a5de28a3c03e6894d29c56b5b424983569ccf2) ) +ROM_END + + ROM_START( invspace ) ROM_REGION( 0x0400, "maincpu", 0 ) ROM_LOAD( "d552c-054", 0x0000, 0x0400, CRC(913d9c13) SHA1(f20edb5458e54d2f6d4e45e5d59efd87e05a6f3f) ) @@ -2401,6 +2534,8 @@ CONS( 1980, splasfgt, 0, 0, splasfgt, splasfgt, driver_device, 0, "Bambin CONS( 1982, bcclimbr, 0, 0, bcclimbr, bcclimbr, driver_device, 0, "Bandai", "Crazy Climber (Bandai)", MACHINE_SUPPORTS_SAVE | MACHINE_REQUIRES_ARTWORK ) +CONS( 1980, tactix, 0, 0, tactix, tactix, driver_device, 0, "Castle Toy", "Tactix", MACHINE_SUPPORTS_SAVE ) + CONS( 1980, invspace, 0, 0, invspace, invspace, driver_device, 0, "Epoch", "Invader From Space", MACHINE_SUPPORTS_SAVE | MACHINE_REQUIRES_ARTWORK ) CONS( 1980, efball, 0, 0, efball, efball, driver_device, 0, "Epoch", "Electronic Football (Epoch)", MACHINE_SUPPORTS_SAVE ) CONS( 1981, galaxy2, 0, 0, galaxy2, galaxy2, driver_device, 0, "Epoch", "Galaxy II", MACHINE_SUPPORTS_SAVE | MACHINE_REQUIRES_ARTWORK ) diff --git a/src/mess/layout/tactix.lay b/src/mess/layout/tactix.lay new file mode 100644 index 00000000000..0f6bfad4928 --- /dev/null +++ b/src/mess/layout/tactix.lay @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +