techno.cpp: WIP, added sound.

This commit is contained in:
Robbbert 2021-11-10 18:57:57 +11:00
parent 22a52e7875
commit 6f2242561d
2 changed files with 243 additions and 135 deletions

View File

@ -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)

View File

@ -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<cpu_device> m_maincpu;
required_ioport_array<8> m_switch;
required_device<m68000_device> m_maincpu;
required_device<tms7000_device> m_audiocpu;
required_device<dac_byte_interface> 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)