summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author hap <happppp@users.noreply.github.com>2019-12-16 00:09:21 +0100
committer hap <happppp@users.noreply.github.com>2019-12-16 00:09:48 +0100
commit9c03fc73456877aa21ec8aaffe62f415ef6364bf (patch)
tree0d4a20389070d8242cb93d6cb99f2da3d4a8bd78
parentea878703face05e13a9c3c0cc967008fb77b367f (diff)
cgang: added stepper motors (nw)
-rw-r--r--src/devices/machine/ticket.cpp2
-rw-r--r--src/mame/drivers/cgang.cpp332
2 files changed, 248 insertions, 86 deletions
diff --git a/src/devices/machine/ticket.cpp b/src/devices/machine/ticket.cpp
index f18faa45aab..8063d4c41e5 100644
--- a/src/devices/machine/ticket.cpp
+++ b/src/devices/machine/ticket.cpp
@@ -51,7 +51,7 @@ ticket_dispenser_device::ticket_dispenser_device(const machine_config &mconfig,
, m_status(0)
, m_power(0)
, m_timer(nullptr)
- , m_output(*this, "led2") // TODO: probably shouldn't be hardcoded
+ , m_output(*this, "led2") // TODO: shouldn't be hardcoded
{
}
diff --git a/src/mame/drivers/cgang.cpp b/src/mame/drivers/cgang.cpp
index 1616795782d..8740040135e 100644
--- a/src/mame/drivers/cgang.cpp
+++ b/src/mame/drivers/cgang.cpp
@@ -5,14 +5,16 @@
『コズモギャングス』 (COSMOGANGS) by Namco, 1990. USA distribution was handled by
Data East, they titled it "Cosmo Gang".
-It is an electromechanical arcade lightgun game with ticket redemption.
-There is no screen, feedback is with motorized elements, lamps and 7segs,
-and of course sounds and music.
-
-The hardware has similarities with Gator Panic/Wacky Gator.
+It is an electromechanical arcade lightgun game. There is no screen, feedback
+is with motorized elements, lamps and 7segs, and of course sounds and music.
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:
@@ -33,12 +35,15 @@ Audio CPU side:
Cabinet:
- 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
- UFO with leds above cabinet
+- sliding door (only for Japan version?)
- 7segs for scorekeeping
- 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/pit8253.h"
#include "machine/ripple_counter.h"
+#include "machine/ticket.h"
#include "machine/timer.h"
#include "machine/watchdog.h"
#include "sound/upd7759.h"
@@ -60,8 +66,12 @@ Cabinet:
namespace {
-// length of the gate/door in msec (time it takes to open or close)
-static constexpr int GATE_MOTOR_LIMIT = 2500;
+// length of the sliding door in msec (time it takes to open or close)
+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
@@ -75,10 +85,12 @@ public:
m_latch(*this, "latch%u", 0),
m_pit(*this, "pit%u", 0),
m_ppi(*this, "ppi%u", 0),
+ m_ticket(*this, "ticket"),
m_adpcm(*this, "adpcm%u", 0),
m_ymsnd(*this, "ymsnd"),
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_gun_lamps(*this, "gun_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_sol(*this, "ufo_sol"),
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
@@ -94,6 +109,7 @@ public:
protected:
virtual void machine_start() override;
+ virtual void machine_reset() override;
private:
// devices/pointers
@@ -103,10 +119,12 @@ private:
required_device_array<generic_latch_8_device, 2> m_latch;
required_device_array<pit8253_device, 2> m_pit;
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<ym2151_device> m_ymsnd;
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;
output_finder<2> m_gun_lamps;
output_finder<8> m_spot_lamps;
@@ -115,6 +133,9 @@ private:
output_finder<> m_ufo_sol;
output_finder<5> m_en_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
void main_map(address_map &map);
@@ -123,10 +144,12 @@ private:
// I/O handlers
DECLARE_WRITE_LINE_MEMBER(main_irq_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_firq_clear_w) { m_maincpu->set_input_line(M6809_FIRQ_LINE, CLEAR_LINE); }
- TIMER_DEVICE_CALLBACK_MEMBER(gate_motor_tick);
+ DECLARE_WRITE8_MEMBER(main_irq_clear_w);
+ DECLARE_WRITE8_MEMBER(main_firq_clear_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_c_r);
@@ -136,6 +159,7 @@ private:
DECLARE_WRITE8_MEMBER(ppi3_a_w);
DECLARE_WRITE8_MEMBER(ppi3_b_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_b_w);
DECLARE_WRITE8_MEMBER(ppi4_c_w);
@@ -150,20 +174,23 @@ private:
int m_watchdog_clk = 0;
int m_main_irq = 0;
int m_main_firq = 0;
- u8 m_gate_motor_on = 0;
- int m_gate_motor_pos = 0;
+ u8 m_door_motor_on = 0;
+ int m_door_motor_pos = 0;
u8 m_cg_motor_on = 0;
u8 m_cg_motor_dir = 0;
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()
{
for (int i = 0; i < 5; i++)
- {
- m_cg_motor_clk[i] = 0;
- }
+ m_sol_filter[i] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(cgang_state::output_sol),this));
// resolve outputs
m_gun_lamps.resolve();
@@ -173,15 +200,42 @@ void cgang_state::machine_start()
m_ufo_sol.resolve();
m_en_sol.resolve();
m_cg_sol.resolve();
+ m_door_count.resolve();
+ m_en_count.resolve();
+ m_cg_count.resolve();
// register for savestates
save_item(NAME(m_watchdog_clk));
save_item(NAME(m_main_irq));
save_item(NAME(m_main_firq));
- save_item(NAME(m_gate_motor_on));
- save_item(NAME(m_gate_motor_pos));
+ save_item(NAME(m_door_motor_on));
+ save_item(NAME(m_door_motor_pos));
save_item(NAME(m_cg_motor_on));
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
******************************************************************************/
-// maincpu
+// maincpu (misc)
WRITE_LINE_MEMBER(cgang_state::main_irq_w)
{
@@ -210,76 +264,157 @@ WRITE_LINE_MEMBER(cgang_state::main_firq_w)
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_gate_motor_pos++;
- else if (m_gate_motor_on & 1 && m_gate_motor_pos > 0)
- m_gate_motor_pos--;
+ m_maincpu->set_input_line(M6809_IRQ_LINE, CLEAR_LINE);
+}
+
+WRITE8_MEMBER(cgang_state::main_firq_clear_w)
+{
+ m_maincpu->set_input_line(M6809_FIRQ_LINE, CLEAR_LINE);
}
template<int N>
WRITE_LINE_MEMBER(cgang_state::motor_clock_w)
{
- // clock stepper motor
- if (state && !m_cg_motor_clk[N])
+ // clock stepper motors
+ if (state && !m_cg_motor_clk[N] && BIT(m_cg_motor_on, N))
+ cg_motor_tick(N);
+
+ 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]++;
}
- m_cg_motor_clk[N] = state;
+ 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)
{
- 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;
}
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
data |= m_latch[1]->pending_r() ? 0 : 0x80;
- //data |= 0x7f;
-
return data;
}
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++)
{
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
- // PA6: gate up limit switch
- data |= 0x60;
- if (m_gate_motor_pos == 0)
+ // lightsensors masked with SW3
+ data |= ~m_dipsw[2]->read() & 0x1f;
+
+ // PA5: door down limit switch
+ // PA6: door up limit switch
+ if (m_door_motor_pos == 0)
data ^= 0x20;
- else if (m_gate_motor_pos == GATE_MOTOR_LIMIT)
+ else if (m_door_motor_pos == DOOR_MOTOR_LIMIT)
data ^= 0x40;
- //data |= 0x1e;
+ // force door limit switches low to disable
+ if (~m_conf->read() & 1)
+ data &= ~0x60;
return data;
}
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;
}
@@ -291,8 +426,8 @@ WRITE8_MEMBER(cgang_state::ppi2_c_w)
machine().bookkeeping().coin_counter_w(0, BIT(data, 0));
machine().bookkeeping().coin_lockout_w(0, BIT(~data, 1));
- // PC2: start button lamp (normal)
- // PC3: start button lamp (pro)
+ // PC2: start button lamp (easy)
+ // PC3: start button lamp (hard)
m_misc_lamps[0] = BIT(data, 2);
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]);
}
+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)
{
// PA2-PA4: round leds
for (int i = 0; i < 3; i++)
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++)
- m_en_sol[i] = BIT(data, i + 5);
+ set_en_sol(i, BIT(data, i + 5));
}
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++)
- m_en_sol[i + 3] = BIT(data, i);
+ set_en_sol(i + 3, BIT(data, i));
// 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);
// PB7: target lamp
@@ -360,9 +502,12 @@ WRITE8_MEMBER(cgang_state::ppi4_c_w)
for (int i = 0; i < 2; i++)
m_gun_lamps[i] = BIT(~data, i);
- // PC5: gate motor reverse
- // PC6: gate motor
- m_gate_motor_on = data >> 5 & 3;
+ // PC4: ticket motor
+ m_ticket->motor_w(BIT(data, 4));
+
+ // PC5: door motor reverse
+ // PC6: door motor
+ m_door_motor_on = data >> 5 & 3;
// PC7: watchdog P-RUN
int wd = BIT(data, 7);
@@ -488,20 +633,25 @@ static INPUT_PORTS_START( cgang )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON1 )
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( 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( 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_START("IN3") // "
+ PORT_START("FAKE2") // "
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( 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( 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_DIPUNKNOWN_DIPLOC( 0x01, 0x01, "SW1:1" )
PORT_DIPUNKNOWN_DIPLOC( 0x02, 0x02, "SW1:2" )
@@ -509,36 +659,46 @@ static INPUT_PORTS_START( cgang )
PORT_START("SW2")
PORT_DIPNAME( 0x03, 0x03, DEF_STR( Coinage ) ) PORT_DIPLOCATION("SW2:1,2")
- PORT_DIPSETTING( 0x00, DEF_STR( 3C_1C ) )
- PORT_DIPSETTING( 0x01, DEF_STR( 2C_1C ) )
- PORT_DIPSETTING( 0x03, DEF_STR( 1C_1C ) )
- PORT_DIPSETTING( 0x02, DEF_STR( 1C_2C ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( 3C_1C ) )
+ PORT_DIPSETTING( 0x01, DEF_STR( 2C_1C ) )
+ PORT_DIPSETTING( 0x03, DEF_STR( 1C_1C ) )
+ PORT_DIPSETTING( 0x02, DEF_STR( 1C_2C ) )
PORT_DIPNAME( 0x04, 0x04, "Attract Play" ) PORT_DIPLOCATION("SW2:3")
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
PORT_DIPSETTING( 0x04, DEF_STR( On ) )
- PORT_DIPNAME( 0x18, 0x18, "Ticket Points" ) PORT_DIPLOCATION("SW2:4,5") PORT_CONDITION("SW2", 0x20, EQUALS, 0x20)
- PORT_DIPSETTING( 0x18, "5" )
- PORT_DIPSETTING( 0x10, "10" )
- PORT_DIPSETTING( 0x08, "15" )
- PORT_DIPSETTING( 0x00, "20" )
- PORT_DIPNAME( 0x18, 0x18, "Prize Points" ) PORT_DIPLOCATION("SW2:4,5") PORT_CONDITION("SW2", 0x20, EQUALS, 0x00)
- PORT_DIPSETTING( 0x18, "20" )
- PORT_DIPSETTING( 0x10, "40" )
- PORT_DIPSETTING( 0x08, "60" )
- PORT_DIPSETTING( 0x00, "80" )
+ PORT_DIPNAME( 0x18, 0x18, "Points per Ticket" ) PORT_DIPLOCATION("SW2:4,5") PORT_CONDITION("SW2", 0x20, EQUALS, 0x20)
+ PORT_DIPSETTING( 0x18, "5" )
+ PORT_DIPSETTING( 0x10, "10" )
+ PORT_DIPSETTING( 0x08, "15" )
+ PORT_DIPSETTING( 0x00, "20" )
+ PORT_DIPNAME( 0x18, 0x18, "Points per Prize" ) PORT_DIPLOCATION("SW2:4,5") PORT_CONDITION("SW2", 0x20, EQUALS, 0x00)
+ PORT_DIPSETTING( 0x18, "20" )
+ PORT_DIPSETTING( 0x10, "40" )
+ PORT_DIPSETTING( 0x08, "60" )
+ PORT_DIPSETTING( 0x00, "80" )
PORT_DIPNAME( 0x20, 0x20, "Dispenser Mode" ) PORT_DIPLOCATION("SW2:6")
PORT_DIPSETTING( 0x20, "Ticket" )
PORT_DIPSETTING( 0x00, "Prize" )
PORT_DIPUNUSED_DIPLOC( 0x40, 0x40, "SW2:7" )
PORT_DIPUNUSED_DIPLOC( 0x80, 0x80, "SW2:8" )
- PORT_START("SW3")
- PORT_DIPUNKNOWN_DIPLOC( 0x01, 0x01, "SW3:1" )
- PORT_DIPUNKNOWN_DIPLOC( 0x02, 0x02, "SW3:2" )
- PORT_DIPUNKNOWN_DIPLOC( 0x04, 0x04, "SW3:3" )
- PORT_DIPUNKNOWN_DIPLOC( 0x08, 0x08, "SW3:4" )
- PORT_DIPUNKNOWN_DIPLOC( 0x10, 0x10, "SW3:5" )
- PORT_DIPUNUSED_DIPLOC( 0x20, 0x20, "SW3:6" )
+ PORT_START("SW3") // disables one of the lanes in case of hardware malfunction
+ PORT_DIPNAME( 0x01, 0x01, "Drive System 1" ) PORT_DIPLOCATION("SW3:1")
+ PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x01, DEF_STR( On ) )
+ PORT_DIPNAME( 0x02, 0x02, "Drive System 2" ) PORT_DIPLOCATION("SW3:2")
+ 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_START("SW4")
PORT_DIPNAME( 0x03, 0x02, DEF_STR( Difficulty ) ) PORT_DIPLOCATION("SW4:1,2")
@@ -624,7 +784,9 @@ void cgang_state::cgang(machine_config &config)
WATCHDOG_TIMER(config, m_watchdog); // HA1835P
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 */
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);
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);
- m_adpcm[1]->add_route(ALL_OUTPUTS, "mono", 0.65);
+ m_adpcm[1]->add_route(ALL_OUTPUTS, "mono", 0.75);
}