From 6f2242561da182ab92b04a5f424740c2942b74ad Mon Sep 17 00:00:00 2001 From: Robbbert Date: Wed, 10 Nov 2021 18:57:57 +1100 Subject: [PATCH] techno.cpp: WIP, added sound. --- src/mame/drivers/ltd.cpp | 3 + src/mame/drivers/techno.cpp | 375 +++++++++++++++++++++++------------- 2 files changed, 243 insertions(+), 135 deletions(-) diff --git a/src/mame/drivers/ltd.cpp b/src/mame/drivers/ltd.cpp index fa2eaae2ce3..6085636c6ac 100644 --- a/src/mame/drivers/ltd.cpp +++ b/src/mame/drivers/ltd.cpp @@ -59,6 +59,7 @@ ToDo: #include "ltd.lh" +namespace { class ltd_state : public genpin_class { @@ -758,6 +759,8 @@ ROM_START(tricksht) ROM_LOAD("tricks-h.bin", 0x1000, 0x1000, CRC(2e4efb51) SHA1(3dd20addecf4b47bd68b05d557c378d1dbbbd892)) ROM_END +} // Anonymous namespace + // system 3, 2-player, with beep sounds, playable GAME(1981, arizona, 0, ltd3, ltd3, ltd_state, init_0, ROT0, "LTD", "Arizona", MACHINE_IS_SKELETON_MECHANICAL) GAME(1981, atla_ltd, 0, ltd3, ltd3, ltd_state, init_0, ROT0, "LTD", "Atlantis (LTD)", MACHINE_IS_SKELETON_MECHANICAL) diff --git a/src/mame/drivers/techno.cpp b/src/mame/drivers/techno.cpp index 252a30c25d6..1b0816791ab 100644 --- a/src/mame/drivers/techno.cpp +++ b/src/mame/drivers/techno.cpp @@ -2,14 +2,29 @@ // copyright-holders:Robbbert /********************************************************************************** - PINBALL - Technoplay "2-2C 8008 LS" (68000 CPU) - Schematic and PinMAME used as references +PINBALL +Technoplay "2-2C 8008 LS" (68000 CPU). Company also known as Tecnoplay. They still +exist, mainly as importer and reseller of amusement machines made by others. +Schematic and PinMAME used as references +Machines by this manufacturer: Devil King, Hi-Ball, Scramble, Space Team, X Force. +Scramble uses Zaccaria-2 system. + +Status: +- X-Force displays correctly, you can coin up and start a game, then no response. + Test mode works. ToDo: - Once you press the credit button, nothing responds (game requires 4 balls) -- Sliding display is too fast to read (much better if cpu xtal changed to 4MHz) -- No sound due to missing roms +- Sliding display is too fast to read (much better if cpu xtal changed to 4MHz). + DTACK needs to be hooked up but it is unsupported. Inserting waitstates doesn't + work either. +- Mechanical sounds +- Unemulated TKY2016-A and TKY2016-B pair of audio processor chips. + PinMAME thinks it might be a Y8950, but I'm not so sure. It's hooked up for now. +- Schematic shows sound rom banking, but no machine has those roms, so not coded. +- xforce: sound rom is missing +- spcteam: Bad display - can't tell if keys are doing anything. +- spcteam: randomly, lots of unmapped reads by the audiocpu from 0x20D8,9. ***********************************************************************************/ @@ -17,17 +32,25 @@ ToDo: #include "emu.h" #include "machine/genpin.h" #include "cpu/m68000/m68000.h" +#include "cpu/tms7000/tms7000.h" +#include "sound/dac.h" +#include "sound/ymopl.h" +#include "speaker.h" #include "techno.lh" +namespace { -class techno_state : public driver_device +class techno_state : public genpin_class { public: techno_state(const machine_config &mconfig, device_type type, const char *tag) - : driver_device(mconfig, type, tag) + : genpin_class(mconfig, type, tag) , m_maincpu(*this, "maincpu") - , m_switch(*this, "SWITCH.%u", 0) + , m_audiocpu(*this, "audiocpu") + , m_dac(*this, "dac") + , m_io_keyboard(*this, "X%u", 0) , m_digits(*this, "digit%u", 0U) + , m_io_outputs(*this, "out%u", 0U) { } void techno(machine_config &config); @@ -39,78 +62,94 @@ private: IRQ_ADVANCE_TIMER }; - uint16_t key_r(); - uint16_t rtrg_r(); - uint16_t sound_r(); - void disp1_w(uint16_t data); - void disp2_w(uint16_t data); - void lamp1_w(uint16_t data); - void lamp2_w(uint16_t data); - void setout_w(uint16_t data); - void sol1_w(uint16_t data); - void sol2_w(uint16_t data); - void sound_w(uint16_t data); + u16 key_r(); + u16 rtrg_r(); + u16 sound_r(); + void disp1_w(u16 data); + void disp2_w(u16 data); + void lamp1_w(u16 data); + void lamp2_w(u16 data); + void setout_w(u16 data); + void sol1_w(u16 data); + void sol2_w(u16 data); + void sound_w(u16 data); - uint8_t rd_r() { return 0; } - void wr_w(uint8_t data) {} + u8 pa_r(); + void pb_w(u8); - void techno_map(address_map &map); - void techno_sub_map(address_map &map); + void mem_map(address_map &map); + void audio_map(address_map &map); void cpu_space_map(address_map &map); virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; virtual void machine_start() override; virtual void machine_reset() override; - required_device m_maincpu; - required_ioport_array<8> m_switch; + required_device m_maincpu; + required_device m_audiocpu; + required_device m_dac; + required_ioport_array<8> m_io_keyboard; output_finder<48> m_digits; + output_finder<96> m_io_outputs; // 64 lamps + 32 solenoids emu_timer *m_irq_set_timer; emu_timer *m_irq_advance_timer; - bool m_digwait; - uint8_t m_keyrow; - uint16_t m_digit; - uint8_t m_vector; + bool m_digwait = 0; + u8 m_keyrow = 0; + u16 m_digit = 0; + u8 m_vector = 0; + u8 m_snd_cmd = 0; + bool m_snd_ack = 0; + u32 m_last_solenoid = 0; }; -void techno_state::techno_map(address_map &map) +void techno_state::mem_map(address_map &map) { map.global_mask(0x1ffff); map(0x00000, 0x03fff).rom(); map(0x04000, 0x04fff).ram().share("nvram"); // battery backed-up map(0x06000, 0x0ffff).rom(); map(0x14000, 0x147ff).rw(FUNC(techno_state::key_r), FUNC(techno_state::lamp1_w)); - map(0x14800, 0x14fff).rw(FUNC(techno_state::sound_r), FUNC(techno_state::lamp2_w)); + map(0x14800, 0x14fff).w(FUNC(techno_state::lamp2_w)); map(0x15000, 0x157ff).rw(FUNC(techno_state::rtrg_r), FUNC(techno_state::sol1_w)); - map(0x15800, 0x15fff).nopr().w(FUNC(techno_state::sol2_w)); // reads from 15800, but shown as not connected + map(0x15800, 0x15fff).rw(FUNC(techno_state::sound_r), FUNC(techno_state::sol2_w)); // sch has sound_r @14800 by mistake map(0x16000, 0x167ff).w(FUNC(techno_state::sound_w)); map(0x16800, 0x16fff).w(FUNC(techno_state::disp1_w)); map(0x17000, 0x177ff).w(FUNC(techno_state::disp2_w)); map(0x17800, 0x17fff).w(FUNC(techno_state::setout_w)); } -void techno_state::techno_sub_map(address_map &map) -{ // no ram here, must be internal to the cpu - map(0x0000, 0x3fff).r(FUNC(techno_state::rd_r)); // to TKY2016A audio processor which has its own 3.58MHz clock - map(0x4000, 0x7fff).w(FUNC(techno_state::wr_w)); // A11=LED;A12=WR2 (DAC) ;A13=WR1 (TKY2016A as above) - map(0x4000, 0xbfff).rom(); // 4000-7FFF is same as 8000-BFFF; 4x 16k ROMS bankswitched - map(0xc000, 0xffff).rom(); // another 16k ROM +void techno_state::cpu_space_map(address_map &map) +{ + map(0xfffff0, 0xffffff).m(m_maincpu, FUNC(m68000_base_device::autovectors_map)); + map(0xfffff2, 0xfffff3).lr16(NAME([this] () -> u16 { return m_vector; })); } -void techno_state::disp1_w(uint16_t data) +void techno_state::audio_map(address_map &map) +{ + map(0x3000, 0x3000).r("ym1", FUNC(y8950_device::read)); // TKY2016 + map(0x5800, 0x5801).w("ym1", FUNC(y8950_device::write)); // TKY2016 + map(0x6800, 0x6800).w(m_dac, FUNC(dac_byte_interface::write)); // DAC0808 + map(0x7000, 0x7000).nopw(); //w(FUNC(techno_state::led_w)); // LED (bit 0; rest unused) + map(0x4000, 0xbfff).rom().region("audiocpu", 0x4000); // ic8,9,10,11 - 4x 32k roms bankswitched (not used by any machine) + map(0xc000, 0xffff).rom().region("audiocpu", 0); // ic12, 1st half ignored, 2nd half used +} + +void techno_state::disp1_w(u16 data) { m_digits[m_digit] = bitswap<16>(data, 12, 10, 8, 14, 13, 9, 11, 15, 7, 6, 5, 4, 3, 2, 1, 0); + // need to hold DTACK here to momentarily slow the main cpu to half speed so that the displays can be read } -void techno_state::disp2_w(uint16_t data) +void techno_state::disp2_w(u16 data) { m_digits[m_digit+30] = bitswap<16>(data, 12, 10, 8, 14, 13, 9, 11, 15, 7, 6, 5, 4, 3, 2, 1, 0); + // need to hold DTACK here to momentarily slow the main cpu to half speed so that the displays can be read } -void techno_state::sound_w(uint16_t data) +void techno_state::sound_w(u16 data) { /* d0..d7 : to sound board @@ -120,6 +159,9 @@ d10 : data clock to display board d11-d15: AUX outputs */ + m_snd_cmd = data & 0xff; + m_audiocpu->set_input_line(TMS7000_INT3_LINE, HOLD_LINE); + // this code derived from PinMAME if (m_digwait) m_digit = (m_digit+1) % 16; @@ -131,134 +173,148 @@ d11-d15: AUX outputs } } -// lamps & keymatrix -void techno_state::lamp1_w(uint16_t data) +// lamp/keymatrix one line high +void techno_state::lamp1_w(u16 data) { // Work out key row - for (int i = 8; i < 16; i++) + for (int i = 0; i < 8; i++) if (BIT(data, i)) - m_keyrow = i-8; + m_keyrow = i; } -// more lamps -void techno_state::lamp2_w(uint16_t data) +// lamps - up to 8 lines high +// sch shows bits 0-7 going to aux outputs, but they are the same as bits 8-15, +// so probably do nothing or not exist. +void techno_state::lamp2_w(u16 data) { + for (u8 i = 0; i < 8; i++) + m_io_outputs[32+m_keyrow*8+i] = BIT(data ,i+8); } // solenoids -void techno_state::sol1_w(uint16_t data) +void techno_state::sol1_w(u16 data) { + for (u8 i = 0; i < 16; i++) + if (BIT(data, i) != BIT(m_last_solenoid, i)) + m_io_outputs[i] = BIT(data ,i); + m_last_solenoid = (m_last_solenoid & 0xffff0000) | data; } // more solenoids -void techno_state::sol2_w(uint16_t data) +void techno_state::sol2_w(u16 data) { + for (u8 i = 0; i < 16; i++) + if (BIT(data, i) != BIT(m_last_solenoid, i+16)) + m_io_outputs[i+16] = BIT(data ,i); + + if (BIT(data, 6) && !BIT(m_last_solenoid, 22)) + m_samples->start(0, 5); // outhole + + m_last_solenoid = (m_last_solenoid & 0xffff) | (data << 16); } -// unknown -void techno_state::setout_w(uint16_t data) +// blanking circuit +void techno_state::setout_w(u16 data) { + // data not used } // inputs -uint16_t techno_state::key_r() +u16 techno_state::key_r() { - return m_switch[m_keyrow]->read(); + u8 i = m_io_keyboard[m_keyrow]->read(); + return i | (i << 8); } -// unknown -uint16_t techno_state::rtrg_r() +// blanking circuit +u16 techno_state::rtrg_r() { + // data not used return 0xffff; } // feedback from sound board, and some AUX inputs -uint16_t techno_state::sound_r() +u16 techno_state::sound_r() { - return 0; + return 0xfe | u16(m_snd_ack); } +// These switch names are for xforce; it's the only manual we have static INPUT_PORTS_START( techno ) - PORT_START("SWITCH.0") - PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Letter select+") PORT_CODE(KEYCODE_F5) + PORT_START("X0") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_5_PAD) PORT_NAME("Letter select+") PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_COIN3 ) PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_COIN2 ) PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_COIN1 ) - PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_SERVICE ) - PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_TILT2 ) - PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Test-") PORT_CODE(KEYCODE_F7) - PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Test+") PORT_CODE(KEYCODE_F8) - PORT_START("SWITCH.1") - PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Fix top target right") - PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Horizontal rail right") + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_0_PAD) PORT_NAME("Setup") + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_0) PORT_NAME("Tilt2") + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_1_PAD) PORT_NAME("Test-") + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_2_PAD) PORT_NAME("Test+") + PORT_START("X1") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_A) PORT_NAME("Fix top target right") + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_B) PORT_NAME("Horizontal rail right") PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED ) - PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Mini Post") PORT_CODE(KEYCODE_I) + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_C) PORT_NAME("Mini Post") PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNUSED ) - PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_TILT ) + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_9) PORT_NAME("Tilt") PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_START ) - PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Letter select+") PORT_CODE(KEYCODE_F6) - PORT_START("SWITCH.2") + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_4_PAD) PORT_NAME("Letter select-") + PORT_START("X2") PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) - PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Inner Canal Left") PORT_CODE(KEYCODE_O) - PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Exit Canal Right") PORT_CODE(KEYCODE_OPENBRACE) - PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Ball 1") - PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Ball 2") - PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Ball 3") - PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Ball 4") - PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Out Hole") PORT_CODE(KEYCODE_X) - PORT_START("SWITCH.3") - PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Top Bumper") PORT_CODE(KEYCODE_Q) - PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Bottom Bumper") PORT_CODE(KEYCODE_W) - PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Top Right Kicker") PORT_CODE(KEYCODE_E) - PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Right Kicker") PORT_CODE(KEYCODE_R) - PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left Kicker") PORT_CODE(KEYCODE_Y) - PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Exit Canal Left") PORT_CODE(KEYCODE_U) - PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Inner Canal Right") PORT_CODE(KEYCODE_I) + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_D) PORT_NAME("Inner Canal Left") + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_E) PORT_NAME("Exit Canal Right") + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_3) PORT_NAME("Ball 1") + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_3) PORT_NAME("Ball 2") + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_3) PORT_NAME("Ball 3") + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_3) PORT_NAME("Ball 4") + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_X) PORT_NAME("Out Hole") PORT_CODE(KEYCODE_X) + PORT_START("X3") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_F) PORT_NAME("Top Bumper") + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_G) PORT_NAME("Bottom Bumper") + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_H) PORT_NAME("Top Right Kicker") + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_I) PORT_NAME("Right Kicker") + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_J) PORT_NAME("Left Kicker") + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_K) PORT_NAME("Exit Canal Left") + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_L) PORT_NAME("Inner Canal Right") PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNUSED ) - PORT_START("SWITCH.4") - PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Fix left target bottom") PORT_CODE(KEYCODE_A) - PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left rollover") PORT_CODE(KEYCODE_S) - PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Barrier 1 Target") PORT_CODE(KEYCODE_D) + PORT_START("X4") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_M) PORT_NAME("Fix left target bottom") + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_N) PORT_NAME("Left rollover") + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_O) PORT_NAME("Barrier 1 Target") PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED ) - PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Barrier 2 Target") PORT_CODE(KEYCODE_F) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_P) PORT_NAME("Barrier 2 Target") PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED ) - PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Barrier 3 Target") PORT_CODE(KEYCODE_G) - PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Left Bumper") PORT_CODE(KEYCODE_H) - PORT_START("SWITCH.5") - PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Fix right target top") PORT_CODE(KEYCODE_J) - PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Fix right target middle-top") PORT_CODE(KEYCODE_K) - PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Spinning Target") PORT_CODE(KEYCODE_L) - PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Fixed contact") PORT_CODE(KEYCODE_COLON) - PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Special Target") PORT_CODE(KEYCODE_QUOTE) + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_Q) PORT_NAME("Barrier 3 Target") + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_R) PORT_NAME("Left Bumper") + PORT_START("X5") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_S) PORT_NAME("Fix right target top") + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_T) PORT_NAME("Fix right target middle-top") + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_U) PORT_NAME("Spinning Target") + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_V) PORT_NAME("Fixed contact") + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_W) PORT_NAME("Special Target") PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED ) - PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Fix left target top") PORT_CODE(KEYCODE_CLOSEBRACE) - PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Fix left target centre") PORT_CODE(KEYCODE_BACKSLASH) - PORT_START("SWITCH.6") - PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Fix top left target left") PORT_CODE(KEYCODE_Z) - PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Ball 1 Bridge") - PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Ball 2 Bridge") - PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Ball 3 Bridge") - PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Ball 4 Bridge") + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_Y) PORT_NAME("Fix left target top") + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_Z) PORT_NAME("Fix left target centre") + PORT_START("X6") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_COMMA) PORT_NAME("Fix top left target left") + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_4) PORT_NAME("Ball 1 Bridge") + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_4) PORT_NAME("Ball 2 Bridge") + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_4) PORT_NAME("Ball 3 Bridge") + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_4) PORT_NAME("Ball 4 Bridge") PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNUSED ) - PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Fix right target middle-bottom") PORT_CODE(KEYCODE_C) - PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Fix right target bottom") PORT_CODE(KEYCODE_V) - PORT_START("SWITCH.7") - PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Fix top target middle-right") PORT_CODE(KEYCODE_B) - PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Fix top target middle-left") PORT_CODE(KEYCODE_N) - PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Fix top target Left") PORT_CODE(KEYCODE_M) - PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Horizontal Rail Left") PORT_CODE(KEYCODE_COMMA) - PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Chopper Exit") PORT_CODE(KEYCODE_STOP) - PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Chopper Entry") PORT_CODE(KEYCODE_SLASH) - PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Fix top left target right") PORT_CODE(KEYCODE_MINUS) - PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Fix top left target middle") PORT_CODE(KEYCODE_EQUALS) + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_STOP) PORT_NAME("Fix right target middle-bottom") + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_SLASH) PORT_NAME("Fix right target bottom") + PORT_START("X7") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_COLON) PORT_NAME("Fix top target middle-right") + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_QUOTE) PORT_NAME("Fix top target middle-left") + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_OPENBRACE) PORT_NAME("Fix top target Left") + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_NAME("Horizontal Rail Left") + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_BACKSLASH) PORT_NAME("Chopper Exit") + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_MINUS) PORT_NAME("Chopper Entry") + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_EQUALS) PORT_NAME("Fix top left target right") + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_KEYPAD ) PORT_CODE(KEYCODE_BACKSPACE) PORT_NAME("Fix top left target middle") INPUT_PORTS_END -void techno_state::cpu_space_map(address_map &map) -{ - map(0xfffff0, 0xffffff).m(m_maincpu, FUNC(m68000_base_device::autovectors_map)); - map(0xfffff2, 0xfffff3).lr16(NAME([this] () -> u16 { return m_vector; })); -} - void techno_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { if (id == IRQ_ADVANCE_TIMER) @@ -278,17 +334,54 @@ void techno_state::device_timer(emu_timer &timer, device_timer_id id, int param, } } +// E04C +u8 techno_state::pa_r() +{ + return m_snd_cmd; +} + +void techno_state::pb_w(u8 data) +{ + // d0: enable TKY2016 + // d1: ack back to maincpu + m_snd_ack = BIT(data, 1); + // d2,3 : bank + // d4: address/data - internal + // d5: r/w - internal + // d6: ena - internal + // d7: ck.oot - not used + // Banking of sound roms 4000-BFFF goes here, however no machine uses it + // m_bank->set_entry(BIT(data, 2, 2)); +} + void techno_state::machine_start() { + genpin_class::machine_start(); + + m_digits.resolve(); + m_io_outputs.resolve(); + + save_item(NAME(m_digwait)); + save_item(NAME(m_digit)); + save_item(NAME(m_keyrow)); + save_item(NAME(m_vector)); + save_item(NAME(m_snd_cmd)); + save_item(NAME(m_snd_ack)); + save_item(NAME(m_last_solenoid)); + m_irq_set_timer = timer_alloc(IRQ_SET_TIMER); m_irq_advance_timer = timer_alloc(IRQ_ADVANCE_TIMER); } void techno_state::machine_reset() { - m_digits.resolve(); + genpin_class::machine_reset(); + for (u8 i = 0; i < m_io_outputs.size(); i++) + m_io_outputs[i] = 0; + m_vector = 0x88; m_digit = 0; + m_last_solenoid = 0; attotime freq = attotime::from_hz(XTAL(8'000'000) / 256); // 31250Hz m_irq_set_timer->adjust(freq, 0, freq); @@ -299,16 +392,25 @@ void techno_state::techno(machine_config &config) { /* basic machine hardware */ M68000(config, m_maincpu, XTAL(8'000'000)); - m_maincpu->set_addrmap(AS_PROGRAM, &techno_state::techno_map); + m_maincpu->set_addrmap(AS_PROGRAM, &techno_state::mem_map); m_maincpu->set_addrmap(m68000_base_device::AS_CPU_SPACE, &techno_state::cpu_space_map); NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0); - //tms7000_device &cpu2(TMS7000(config, "cpu2", XTAL(4'000'000))); - //cpu2.set_addrmap(AS_PROGRAM, &techno_state::techno_sub_map); + TMS7000(config, m_audiocpu, 4_MHz_XTAL); + m_audiocpu->set_addrmap(AS_PROGRAM, &techno_state::audio_map); + m_audiocpu->in_porta().set(FUNC(techno_state::pa_r)); + m_audiocpu->out_portb().set(FUNC(techno_state::pb_w)); /* Video */ config.set_default_layout(layout_techno); + + // Sound + genpin_audio(config); + SPEAKER(config, "lspeaker").front_left(); + SPEAKER(config, "rspeaker").front_right(); + DAC_8BIT_R2R(config, m_dac, 0).add_route(ALL_OUTPUTS, "rspeaker", 0.5); // DAC0808 + Y8950(config, "ym1", 3580000).add_route(ALL_OUTPUTS, "lspeaker", 0.5); // TKY2016 - no crystal, just a random oscillator, sch says 3.58MHz } ROM_START(xforce) @@ -316,19 +418,22 @@ ROM_START(xforce) ROM_LOAD16_BYTE("ic15", 0x0001, 0x8000, CRC(fb8d2853) SHA1(0b0004abfe32edfd3ac15d66f90695d264c97eba)) ROM_LOAD16_BYTE("ic17", 0x0000, 0x8000, CRC(122ef649) SHA1(0b425f81869bc359841377a91c39f44395502bff)) - //ROM_REGION(0x20000, "cpu2", 0) - // 5 x 27256 roms are undumped + ROM_REGION(0xc000, "audiocpu", ROMREGION_ERASEFF) + // nothing dumped ROM_END ROM_START(spcteam) ROM_REGION(0x10000, "maincpu", 0) - ROM_LOAD16_BYTE("cpu_top.bin", 0x000001, 0x8000, CRC(b11dcf1f) SHA1(084eb98ee4c9f32d5518897a891ad1a601850d80)) - ROM_LOAD16_BYTE("cpu_bot.bin", 0x000000, 0x8000, CRC(892a5592) SHA1(c30dce37a5aae2834459179787f6c99353aadabb)) + ROM_LOAD16_BYTE("cpu_top.ic15", 0x0001, 0x8000, CRC(b11dcf1f) SHA1(084eb98ee4c9f32d5518897a891ad1a601850d80)) + ROM_LOAD16_BYTE("cpu_bot.ic17", 0x0000, 0x8000, CRC(892a5592) SHA1(c30dce37a5aae2834459179787f6c99353aadabb)) - ROM_REGION(0x10000, "cpu2", 0) - ROM_LOAD("sound.bin", 0x8000, 0x8000, CRC(6a87370f) SHA1(51e055dcf23a30e337ff439bba3c40e5c51c490a)) - ROM_RELOAD(0, 0x8000) + ROM_REGION(0xc000, "audiocpu", ROMREGION_ERASEFF) + // ic12 first half not used, inaccessible (all FF) + ROM_LOAD("sound.ic12", 0x0000, 0x4000, CRC(6a87370f) SHA1(51e055dcf23a30e337ff439bba3c40e5c51c490a)) + ROM_CONTINUE(0x0000, 0x4000) ROM_END +} // Anonymous namespace + GAME(1987, xforce, 0, techno, techno, techno_state, empty_init, ROT0, "Tecnoplay", "X Force", MACHINE_IS_SKELETON_MECHANICAL) -GAME(1988, spcteam, 0, techno, techno, techno_state, empty_init, ROT0, "Tecnoplay", "Space Team", MACHINE_IS_SKELETON_MECHANICAL) // needs correct layout +GAME(1988, spcteam, 0, techno, techno, techno_state, empty_init, ROT0, "Tecnoplay", "Space Team", MACHINE_IS_SKELETON_MECHANICAL)