cgang: added stepper motors (nw)

This commit is contained in:
hap 2019-12-16 00:09:21 +01:00
parent ea878703fa
commit 9c03fc7345
2 changed files with 249 additions and 87 deletions

View File

@ -51,7 +51,7 @@ ticket_dispenser_device::ticket_dispenser_device(const machine_config &mconfig,
, m_status(0) , m_status(0)
, m_power(0) , m_power(0)
, m_timer(nullptr) , m_timer(nullptr)
, m_output(*this, "led2") // TODO: probably shouldn't be hardcoded , m_output(*this, "led2") // TODO: shouldn't be hardcoded
{ {
} }

View File

@ -5,14 +5,16 @@
(COSMOGANGS) by Namco, 1990. USA distribution was handled by (COSMOGANGS) by Namco, 1990. USA distribution was handled by
Data East, they titled it "Cosmo Gang". Data East, they titled it "Cosmo Gang".
It is an electromechanical arcade lightgun game with ticket redemption. It is an electromechanical arcade lightgun game. There is no screen, feedback
There is no screen, feedback is with motorized elements, lamps and 7segs, is with motorized elements, lamps and 7segs, and of course sounds and music.
and of course sounds and music.
The hardware has similarities with Gator Panic/Wacky Gator.
TODO: TODO:
- almost everything - internal artwork
- game can't really be played within MAME's constraints (mechanical stuff,
and the lightguns linked to it)
- ppi2_b_r cabinet center sensors, doesn't seem to affect the game at all
-------------------------------------------------------------------------------
Hardware notes: Hardware notes:
@ -33,12 +35,15 @@ Audio CPU side:
Cabinet: Cabinet:
- 5 lanes with movable aliens, lightsensor under mouth - 5 lanes with movable aliens, lightsensor under mouth
- 5 'energy containers', aliens will try to steal them - 5 'energy crates', aliens will try to steal them
- 2 lightguns - 2 lightguns
- UFO with leds above cabinet - UFO with leds above cabinet
- sliding door (only for Japan version?)
- 7segs for scorekeeping - 7segs for scorekeeping
- 2 speakers (but final mix is mono!) - 2 speakers (but final mix is mono!)
- ticket dispenser - optional ticket/prize dispenser
Overall, the hardware has similarities with Wacky Gator, see wacky_gator.cpp.
******************************************************************************/ ******************************************************************************/
@ -49,6 +54,7 @@ Cabinet:
#include "machine/i8255.h" #include "machine/i8255.h"
#include "machine/pit8253.h" #include "machine/pit8253.h"
#include "machine/ripple_counter.h" #include "machine/ripple_counter.h"
#include "machine/ticket.h"
#include "machine/timer.h" #include "machine/timer.h"
#include "machine/watchdog.h" #include "machine/watchdog.h"
#include "sound/upd7759.h" #include "sound/upd7759.h"
@ -60,8 +66,12 @@ Cabinet:
namespace { namespace {
// length of the gate/door in msec (time it takes to open or close) // length of the sliding door in msec (time it takes to open or close)
static constexpr int GATE_MOTOR_LIMIT = 2500; static constexpr int DOOR_MOTOR_LIMIT = 2000;
// length of each cosmogang lane, in motor steps
// at game start, one cosmo going forward takes around 6-7 seconds (compared to video recording)
static constexpr int CG_MOTOR_LIMIT = 850;
class cgang_state : public driver_device class cgang_state : public driver_device
@ -75,10 +85,12 @@ public:
m_latch(*this, "latch%u", 0), m_latch(*this, "latch%u", 0),
m_pit(*this, "pit%u", 0), m_pit(*this, "pit%u", 0),
m_ppi(*this, "ppi%u", 0), m_ppi(*this, "ppi%u", 0),
m_ticket(*this, "ticket"),
m_adpcm(*this, "adpcm%u", 0), m_adpcm(*this, "adpcm%u", 0),
m_ymsnd(*this, "ymsnd"), m_ymsnd(*this, "ymsnd"),
m_digits(*this, "digits"), m_digits(*this, "digits"),
m_inputs(*this, "IN%u", 1), m_fake(*this, "FAKE%u", 1),
m_conf(*this, "CONF1"),
m_dipsw(*this, "SW%u", 1), m_dipsw(*this, "SW%u", 1),
m_gun_lamps(*this, "gun_lamp%u", 0U), m_gun_lamps(*this, "gun_lamp%u", 0U),
m_spot_lamps(*this, "spot_lamp%u", 0U), m_spot_lamps(*this, "spot_lamp%u", 0U),
@ -86,7 +98,10 @@ public:
m_ufo_lamps(*this, "ufo_lamp%u", 0U), m_ufo_lamps(*this, "ufo_lamp%u", 0U),
m_ufo_sol(*this, "ufo_sol"), m_ufo_sol(*this, "ufo_sol"),
m_en_sol(*this, "en_sol%u", 0U), m_en_sol(*this, "en_sol%u", 0U),
m_cg_sol(*this, "cg_sol%u", 0U) m_cg_sol(*this, "cg_sol%u", 0U),
m_door_count(*this, "door_count"),
m_en_count(*this, "en_count%u", 0U),
m_cg_count(*this, "cg_count%u", 0U)
{ } { }
// machine drivers // machine drivers
@ -94,6 +109,7 @@ public:
protected: protected:
virtual void machine_start() override; virtual void machine_start() override;
virtual void machine_reset() override;
private: private:
// devices/pointers // devices/pointers
@ -103,10 +119,12 @@ private:
required_device_array<generic_latch_8_device, 2> m_latch; required_device_array<generic_latch_8_device, 2> m_latch;
required_device_array<pit8253_device, 2> m_pit; required_device_array<pit8253_device, 2> m_pit;
required_device_array<i8255_device, 5> m_ppi; required_device_array<i8255_device, 5> m_ppi;
required_device<ticket_dispenser_device> m_ticket;
required_device_array<upd7759_device, 2> m_adpcm; required_device_array<upd7759_device, 2> m_adpcm;
required_device<ym2151_device> m_ymsnd; required_device<ym2151_device> m_ymsnd;
required_device<pwm_display_device> m_digits; required_device<pwm_display_device> m_digits;
required_ioport_array<3> m_inputs; required_ioport_array<2> m_fake;
required_ioport m_conf;
required_ioport_array<4> m_dipsw; required_ioport_array<4> m_dipsw;
output_finder<2> m_gun_lamps; output_finder<2> m_gun_lamps;
output_finder<8> m_spot_lamps; output_finder<8> m_spot_lamps;
@ -115,6 +133,9 @@ private:
output_finder<> m_ufo_sol; output_finder<> m_ufo_sol;
output_finder<5> m_en_sol; output_finder<5> m_en_sol;
output_finder<5> m_cg_sol; output_finder<5> m_cg_sol;
output_finder<> m_door_count;
output_finder<5> m_en_count;
output_finder<5> m_cg_count;
// address maps // address maps
void main_map(address_map &map); void main_map(address_map &map);
@ -123,10 +144,12 @@ private:
// I/O handlers // I/O handlers
DECLARE_WRITE_LINE_MEMBER(main_irq_w); DECLARE_WRITE_LINE_MEMBER(main_irq_w);
DECLARE_WRITE_LINE_MEMBER(main_firq_w); DECLARE_WRITE_LINE_MEMBER(main_firq_w);
DECLARE_WRITE8_MEMBER(main_irq_clear_w) { m_maincpu->set_input_line(M6809_IRQ_LINE, CLEAR_LINE); } DECLARE_WRITE8_MEMBER(main_irq_clear_w);
DECLARE_WRITE8_MEMBER(main_firq_clear_w) { m_maincpu->set_input_line(M6809_FIRQ_LINE, CLEAR_LINE); } DECLARE_WRITE8_MEMBER(main_firq_clear_w);
TIMER_DEVICE_CALLBACK_MEMBER(gate_motor_tick);
template<int N> DECLARE_WRITE_LINE_MEMBER(motor_clock_w); template<int N> DECLARE_WRITE_LINE_MEMBER(motor_clock_w);
void cg_motor_tick(int i);
TIMER_DEVICE_CALLBACK_MEMBER(door_motor_tick);
void refresh_motor_output();
DECLARE_READ8_MEMBER(ppi1_b_r); DECLARE_READ8_MEMBER(ppi1_b_r);
DECLARE_READ8_MEMBER(ppi1_c_r); DECLARE_READ8_MEMBER(ppi1_c_r);
@ -136,6 +159,7 @@ private:
DECLARE_WRITE8_MEMBER(ppi3_a_w); DECLARE_WRITE8_MEMBER(ppi3_a_w);
DECLARE_WRITE8_MEMBER(ppi3_b_w); DECLARE_WRITE8_MEMBER(ppi3_b_w);
DECLARE_WRITE8_MEMBER(ppi3_c_w); DECLARE_WRITE8_MEMBER(ppi3_c_w);
void set_en_sol(int i, int state);
DECLARE_WRITE8_MEMBER(ppi4_a_w); DECLARE_WRITE8_MEMBER(ppi4_a_w);
DECLARE_WRITE8_MEMBER(ppi4_b_w); DECLARE_WRITE8_MEMBER(ppi4_b_w);
DECLARE_WRITE8_MEMBER(ppi4_c_w); DECLARE_WRITE8_MEMBER(ppi4_c_w);
@ -150,20 +174,23 @@ private:
int m_watchdog_clk = 0; int m_watchdog_clk = 0;
int m_main_irq = 0; int m_main_irq = 0;
int m_main_firq = 0; int m_main_firq = 0;
u8 m_gate_motor_on = 0; u8 m_door_motor_on = 0;
int m_gate_motor_pos = 0; int m_door_motor_pos = 0;
u8 m_cg_motor_on = 0; u8 m_cg_motor_on = 0;
u8 m_cg_motor_dir = 0; u8 m_cg_motor_dir = 0;
int m_cg_motor_clk[5]; int m_cg_motor_clk[5];
int m_cg_motor_pos[5];
int m_en_motor_pos[5];
emu_timer *m_sol_filter[5];
TIMER_CALLBACK_MEMBER(output_sol) { m_en_sol[param >> 1] = param & 1; }
}; };
void cgang_state::machine_start() void cgang_state::machine_start()
{ {
for (int i = 0; i < 5; i++) for (int i = 0; i < 5; i++)
{ m_sol_filter[i] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(cgang_state::output_sol),this));
m_cg_motor_clk[i] = 0;
}
// resolve outputs // resolve outputs
m_gun_lamps.resolve(); m_gun_lamps.resolve();
@ -173,15 +200,42 @@ void cgang_state::machine_start()
m_ufo_sol.resolve(); m_ufo_sol.resolve();
m_en_sol.resolve(); m_en_sol.resolve();
m_cg_sol.resolve(); m_cg_sol.resolve();
m_door_count.resolve();
m_en_count.resolve();
m_cg_count.resolve();
// register for savestates // register for savestates
save_item(NAME(m_watchdog_clk)); save_item(NAME(m_watchdog_clk));
save_item(NAME(m_main_irq)); save_item(NAME(m_main_irq));
save_item(NAME(m_main_firq)); save_item(NAME(m_main_firq));
save_item(NAME(m_gate_motor_on)); save_item(NAME(m_door_motor_on));
save_item(NAME(m_gate_motor_pos)); save_item(NAME(m_door_motor_pos));
save_item(NAME(m_cg_motor_on)); save_item(NAME(m_cg_motor_on));
save_item(NAME(m_cg_motor_dir)); save_item(NAME(m_cg_motor_dir));
save_item(NAME(m_cg_motor_clk));
save_item(NAME(m_cg_motor_pos));
save_item(NAME(m_en_motor_pos));
}
void cgang_state::machine_reset()
{
m_main_irq = 0;
m_main_firq = 0;
// initial motor positions
for (int i = 0; i < 5; i++)
{
m_cg_motor_clk[i] = 0;
m_cg_motor_pos[i] = 0;
m_en_motor_pos[i] = CG_MOTOR_LIMIT;
m_en_sol[i] = 0;
}
m_door_motor_pos = 0;
m_door_motor_on = 0;
m_cg_motor_on = 0;
refresh_motor_output();
} }
@ -190,7 +244,7 @@ void cgang_state::machine_start()
I/O I/O
******************************************************************************/ ******************************************************************************/
// maincpu // maincpu (misc)
WRITE_LINE_MEMBER(cgang_state::main_irq_w) WRITE_LINE_MEMBER(cgang_state::main_irq_w)
{ {
@ -210,76 +264,157 @@ WRITE_LINE_MEMBER(cgang_state::main_firq_w)
m_main_firq = state; m_main_firq = state;
} }
TIMER_DEVICE_CALLBACK_MEMBER(cgang_state::gate_motor_tick) WRITE8_MEMBER(cgang_state::main_irq_clear_w)
{ {
if (m_gate_motor_on & 2 && m_gate_motor_pos < GATE_MOTOR_LIMIT) m_maincpu->set_input_line(M6809_IRQ_LINE, CLEAR_LINE);
m_gate_motor_pos++; }
else if (m_gate_motor_on & 1 && m_gate_motor_pos > 0)
m_gate_motor_pos--; WRITE8_MEMBER(cgang_state::main_firq_clear_w)
{
m_maincpu->set_input_line(M6809_FIRQ_LINE, CLEAR_LINE);
} }
template<int N> template<int N>
WRITE_LINE_MEMBER(cgang_state::motor_clock_w) WRITE_LINE_MEMBER(cgang_state::motor_clock_w)
{ {
// clock stepper motor // clock stepper motors
if (state && !m_cg_motor_clk[N]) if (state && !m_cg_motor_clk[N] && BIT(m_cg_motor_on, N))
{ cg_motor_tick(N);
;
}
m_cg_motor_clk[N] = state; m_cg_motor_clk[N] = state;
} }
void cgang_state::cg_motor_tick(int i)
{
// note: the cosmogangs are stuck on the drive belts(5),
// and the energy crates can lock(or loosen) themselves from the belt
if (BIT(m_cg_motor_dir, i))
{
if (m_cg_motor_pos[i] > 0)
{
m_cg_motor_pos[i]--;
// 'pull' energy crate
if (m_en_sol[i])
m_en_motor_pos[i]--;
}
}
else
{
// 'push' energy crate
if (m_en_sol[i])
{
if (m_en_motor_pos[i] < CG_MOTOR_LIMIT)
{
m_en_motor_pos[i]++;
m_cg_motor_pos[i]++;
}
}
else if (m_cg_motor_pos[i] < m_en_motor_pos[i])
m_cg_motor_pos[i]++;
}
refresh_motor_output();
}
TIMER_DEVICE_CALLBACK_MEMBER(cgang_state::door_motor_tick)
{
if (m_door_motor_on & 2 && m_door_motor_pos < DOOR_MOTOR_LIMIT)
m_door_motor_pos++;
else if (m_door_motor_on & 1 && m_door_motor_pos > 0)
m_door_motor_pos--;
refresh_motor_output();
}
void cgang_state::refresh_motor_output()
{
// output motor positions in range 0-100
for (int i = 0; i < 5; i++)
{
m_cg_count[i] = int((m_cg_motor_pos[i] / float(CG_MOTOR_LIMIT)) * 100.0 + 0.5);
m_en_count[i] = int((m_en_motor_pos[i] / float(CG_MOTOR_LIMIT)) * 100.0 + 0.5);
}
m_door_count = int((m_door_motor_pos / float(DOOR_MOTOR_LIMIT)) * 100.0 + 0.5);
}
// maincpu (PPI1-PPI4)
READ8_MEMBER(cgang_state::ppi1_b_r) READ8_MEMBER(cgang_state::ppi1_b_r)
{ {
u8 data = 0; u8 data = 0xff;
//data |= 0xff; // PB0-PB4: cabinet front limit (CR1INI-CR5INI)
for (int i = 0; i < 5; i++)
if (m_en_motor_pos[i] == CG_MOTOR_LIMIT)
data ^= 1 << i;
// PB5-PB7: cabinet back limit (HST1-HST3)
for (int i = 0; i < 3; i++)
if (m_cg_motor_pos[i] == 0)
data ^= 1 << (i + 5);
return data; return data;
} }
READ8_MEMBER(cgang_state::ppi1_c_r) READ8_MEMBER(cgang_state::ppi1_c_r)
{ {
u8 data = 0; u8 data = 0x7f;
// PC0-PC1: cabinet back limit (HST4-HST5)
for (int i = 0; i < 2; i++)
if (m_cg_motor_pos[i + 3] == 0)
data ^= 1 << i;
// PC2-PC6: cosmogang-energy crate collision (CR1-CR5)
for (int i = 0; i < 5; i++)
if (m_cg_motor_pos[i] == m_en_motor_pos[i])
data ^= 1 << (i + 2);
// PC7: audiocpu mailbox status // PC7: audiocpu mailbox status
data |= m_latch[1]->pending_r() ? 0 : 0x80; data |= m_latch[1]->pending_r() ? 0 : 0x80;
//data |= 0x7f;
return data; return data;
} }
READ8_MEMBER(cgang_state::ppi2_a_r) READ8_MEMBER(cgang_state::ppi2_a_r)
{ {
u8 data = 0; u8 data = 0x60;
// PA0-PA4: character hit lightsensors // PA0-PA4: cosmogang hit lightsensors (G1HIT-G5HIT)
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
u8 mask = m_gun_lamps[i] ? 0x1f : 0; u8 mask = m_gun_lamps[i] ? 0x1f : 0;
data |= m_inputs[i + 1]->read() & mask; data |= m_fake[i]->read() & mask;
} }
// PA5: gate down limit switch // lightsensors masked with SW3
// PA6: gate up limit switch data |= ~m_dipsw[2]->read() & 0x1f;
data |= 0x60;
if (m_gate_motor_pos == 0) // PA5: door down limit switch
// PA6: door up limit switch
if (m_door_motor_pos == 0)
data ^= 0x20; data ^= 0x20;
else if (m_gate_motor_pos == GATE_MOTOR_LIMIT) else if (m_door_motor_pos == DOOR_MOTOR_LIMIT)
data ^= 0x40; data ^= 0x40;
//data |= 0x1e; // force door limit switches low to disable
if (~m_conf->read() & 1)
data &= ~0x60;
return data; return data;
} }
READ8_MEMBER(cgang_state::ppi2_b_r) READ8_MEMBER(cgang_state::ppi2_b_r)
{ {
u8 data = 0; u8 data = 0x1f;
//data |= 0xff; // PB0-PB4: cabinet center (G1POG-G5POG)
// how this is sensed?
return data; return data;
} }
@ -291,8 +426,8 @@ WRITE8_MEMBER(cgang_state::ppi2_c_w)
machine().bookkeeping().coin_counter_w(0, BIT(data, 0)); machine().bookkeeping().coin_counter_w(0, BIT(data, 0));
machine().bookkeeping().coin_lockout_w(0, BIT(~data, 1)); machine().bookkeeping().coin_lockout_w(0, BIT(~data, 1));
// PC2: start button lamp (normal) // PC2: start button lamp (easy)
// PC3: start button lamp (pro) // PC3: start button lamp (hard)
m_misc_lamps[0] = BIT(data, 2); m_misc_lamps[0] = BIT(data, 2);
m_misc_lamps[1] = BIT(data, 3); m_misc_lamps[1] = BIT(data, 3);
} }
@ -329,25 +464,32 @@ WRITE8_MEMBER(cgang_state::ppi3_c_w)
m_digits->matrix((1 << (data >> 4 & 0xf)) & 0x3ff, ls48_map[data & 0xf]); m_digits->matrix((1 << (data >> 4 & 0xf)) & 0x3ff, ls48_map[data & 0xf]);
} }
void cgang_state::set_en_sol(int i, int state)
{
// put a filter on energy crate solenoids, since game keeps strobing them
if (state != (m_sol_filter[i]->param() & 1))
m_sol_filter[i]->adjust(attotime::from_msec(1), i << 1 | state);
}
WRITE8_MEMBER(cgang_state::ppi4_a_w) WRITE8_MEMBER(cgang_state::ppi4_a_w)
{ {
// PA2-PA4: round leds // PA2-PA4: round leds
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
m_misc_lamps[i + 2] = BIT(data, i + 2); m_misc_lamps[i + 2] = BIT(data, i + 2);
// PA5-PA7: energy container solenoids (1-3) // PA5-PA7: energy crate solenoids (1-3)
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
m_en_sol[i] = BIT(data, i + 5); set_en_sol(i, BIT(data, i + 5));
} }
WRITE8_MEMBER(cgang_state::ppi4_b_w) WRITE8_MEMBER(cgang_state::ppi4_b_w)
{ {
// PB0,PB1: energy container solenoids (4-5) // PB0,PB1: energy crate solenoids (4-5)
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
m_en_sol[i + 3] = BIT(data, i); set_en_sol(i + 3, BIT(data, i));
// PB2-PB6: cosmogang solenoids // PB2-PB6: cosmogang solenoids
for (int i = 0; i < 2; i++) for (int i = 0; i < 5; i++)
m_cg_sol[i] = BIT(data, i + 2); m_cg_sol[i] = BIT(data, i + 2);
// PB7: target lamp // PB7: target lamp
@ -360,9 +502,12 @@ WRITE8_MEMBER(cgang_state::ppi4_c_w)
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
m_gun_lamps[i] = BIT(~data, i); m_gun_lamps[i] = BIT(~data, i);
// PC5: gate motor reverse // PC4: ticket motor
// PC6: gate motor m_ticket->motor_w(BIT(data, 4));
m_gate_motor_on = data >> 5 & 3;
// PC5: door motor reverse
// PC6: door motor
m_door_motor_on = data >> 5 & 3;
// PC7: watchdog P-RUN // PC7: watchdog P-RUN
int wd = BIT(data, 7); int wd = BIT(data, 7);
@ -488,20 +633,25 @@ static INPUT_PORTS_START( cgang )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON1 )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
PORT_START("IN2") // fake inputs, indicating gun is aimed at target PORT_START("FAKE1") // fake inputs, indicating gun is aimed at target
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 Aim Target 1") PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 Aim Target 1")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 Aim Target 2") PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 Aim Target 2")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 Aim Target 3") PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 Aim Target 3")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 Aim Target 4") PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 Aim Target 4")
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 Aim Target 5") PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P1 Aim Target 5")
PORT_START("IN3") // " PORT_START("FAKE2") // "
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 Aim Target 1") PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 Aim Target 1")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 Aim Target 2") PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 Aim Target 2")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 Aim Target 3") PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 Aim Target 3")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 Aim Target 4") PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 Aim Target 4")
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 Aim Target 5") PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("P2 Aim Target 5")
PORT_START("CONF1") // motorized sliding door in front of ufo entrance
PORT_CONFNAME( 0x01, 0x01, "Sliding Door System")
PORT_CONFSETTING( 0x00, DEF_STR( Off ) )
PORT_CONFSETTING( 0x01, DEF_STR( On ) )
PORT_START("SW1") PORT_START("SW1")
PORT_DIPUNKNOWN_DIPLOC( 0x01, 0x01, "SW1:1" ) PORT_DIPUNKNOWN_DIPLOC( 0x01, 0x01, "SW1:1" )
PORT_DIPUNKNOWN_DIPLOC( 0x02, 0x02, "SW1:2" ) PORT_DIPUNKNOWN_DIPLOC( 0x02, 0x02, "SW1:2" )
@ -516,12 +666,12 @@ static INPUT_PORTS_START( cgang )
PORT_DIPNAME( 0x04, 0x04, "Attract Play" ) PORT_DIPLOCATION("SW2:3") PORT_DIPNAME( 0x04, 0x04, "Attract Play" ) PORT_DIPLOCATION("SW2:3")
PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
PORT_DIPSETTING( 0x04, DEF_STR( On ) ) PORT_DIPSETTING( 0x04, DEF_STR( On ) )
PORT_DIPNAME( 0x18, 0x18, "Ticket Points" ) PORT_DIPLOCATION("SW2:4,5") PORT_CONDITION("SW2", 0x20, EQUALS, 0x20) PORT_DIPNAME( 0x18, 0x18, "Points per Ticket" ) PORT_DIPLOCATION("SW2:4,5") PORT_CONDITION("SW2", 0x20, EQUALS, 0x20)
PORT_DIPSETTING( 0x18, "5" ) PORT_DIPSETTING( 0x18, "5" )
PORT_DIPSETTING( 0x10, "10" ) PORT_DIPSETTING( 0x10, "10" )
PORT_DIPSETTING( 0x08, "15" ) PORT_DIPSETTING( 0x08, "15" )
PORT_DIPSETTING( 0x00, "20" ) PORT_DIPSETTING( 0x00, "20" )
PORT_DIPNAME( 0x18, 0x18, "Prize Points" ) PORT_DIPLOCATION("SW2:4,5") PORT_CONDITION("SW2", 0x20, EQUALS, 0x00) PORT_DIPNAME( 0x18, 0x18, "Points per Prize" ) PORT_DIPLOCATION("SW2:4,5") PORT_CONDITION("SW2", 0x20, EQUALS, 0x00)
PORT_DIPSETTING( 0x18, "20" ) PORT_DIPSETTING( 0x18, "20" )
PORT_DIPSETTING( 0x10, "40" ) PORT_DIPSETTING( 0x10, "40" )
PORT_DIPSETTING( 0x08, "60" ) PORT_DIPSETTING( 0x08, "60" )
@ -532,12 +682,22 @@ static INPUT_PORTS_START( cgang )
PORT_DIPUNUSED_DIPLOC( 0x40, 0x40, "SW2:7" ) PORT_DIPUNUSED_DIPLOC( 0x40, 0x40, "SW2:7" )
PORT_DIPUNUSED_DIPLOC( 0x80, 0x80, "SW2:8" ) PORT_DIPUNUSED_DIPLOC( 0x80, 0x80, "SW2:8" )
PORT_START("SW3") PORT_START("SW3") // disables one of the lanes in case of hardware malfunction
PORT_DIPUNKNOWN_DIPLOC( 0x01, 0x01, "SW3:1" ) PORT_DIPNAME( 0x01, 0x01, "Drive System 1" ) PORT_DIPLOCATION("SW3:1")
PORT_DIPUNKNOWN_DIPLOC( 0x02, 0x02, "SW3:2" ) PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
PORT_DIPUNKNOWN_DIPLOC( 0x04, 0x04, "SW3:3" ) PORT_DIPSETTING( 0x01, DEF_STR( On ) )
PORT_DIPUNKNOWN_DIPLOC( 0x08, 0x08, "SW3:4" ) PORT_DIPNAME( 0x02, 0x02, "Drive System 2" ) PORT_DIPLOCATION("SW3:2")
PORT_DIPUNKNOWN_DIPLOC( 0x10, 0x10, "SW3:5" ) PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
PORT_DIPSETTING( 0x02, DEF_STR( On ) )
PORT_DIPNAME( 0x04, 0x04, "Drive System 3" ) PORT_DIPLOCATION("SW3:3")
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
PORT_DIPSETTING( 0x04, DEF_STR( On ) )
PORT_DIPNAME( 0x08, 0x08, "Drive System 4" ) PORT_DIPLOCATION("SW3:4")
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
PORT_DIPSETTING( 0x08, DEF_STR( On ) )
PORT_DIPNAME( 0x10, 0x10, "Drive System 5" ) PORT_DIPLOCATION("SW3:5")
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
PORT_DIPSETTING( 0x10, DEF_STR( On ) )
PORT_DIPUNUSED_DIPLOC( 0x20, 0x20, "SW3:6" ) PORT_DIPUNUSED_DIPLOC( 0x20, 0x20, "SW3:6" )
PORT_START("SW4") PORT_START("SW4")
@ -624,7 +784,9 @@ void cgang_state::cgang(machine_config &config)
WATCHDOG_TIMER(config, m_watchdog); // HA1835P WATCHDOG_TIMER(config, m_watchdog); // HA1835P
m_watchdog->set_time(attotime::from_msec(100)); // approximation m_watchdog->set_time(attotime::from_msec(100)); // approximation
TIMER(config, "gate_motor").configure_periodic(FUNC(cgang_state::gate_motor_tick), attotime::from_msec(1)); TICKET_DISPENSER(config, m_ticket, attotime::from_msec(3000), TICKET_MOTOR_ACTIVE_HIGH, TICKET_STATUS_ACTIVE_HIGH);
TIMER(config, "door_motor").configure_periodic(FUNC(cgang_state::door_motor_tick), attotime::from_msec(1));
/* video hardware */ /* video hardware */
PWM_DISPLAY(config, m_digits).set_size(10, 7); PWM_DISPLAY(config, m_digits).set_size(10, 7);
@ -639,9 +801,9 @@ void cgang_state::cgang(machine_config &config)
m_ymsnd->add_route(ALL_OUTPUTS, "mono", 0.50); m_ymsnd->add_route(ALL_OUTPUTS, "mono", 0.50);
UPD7759(config, m_adpcm[0], 640_kHz_XTAL); UPD7759(config, m_adpcm[0], 640_kHz_XTAL);
m_adpcm[0]->add_route(ALL_OUTPUTS, "mono", 0.65); m_adpcm[0]->add_route(ALL_OUTPUTS, "mono", 0.75);
UPD7759(config, m_adpcm[1], 640_kHz_XTAL); UPD7759(config, m_adpcm[1], 640_kHz_XTAL);
m_adpcm[1]->add_route(ALL_OUTPUTS, "mono", 0.65); m_adpcm[1]->add_route(ALL_OUTPUTS, "mono", 0.75);
} }