segaufo: assume nmi enable is on IO2 CNT1, fix regression with debug popmessage, small cleanups,

misc: update some notes
This commit is contained in:
hap 2024-07-14 14:20:24 +02:00
parent 74b0ef1a99
commit 97fb89fbe2
9 changed files with 317 additions and 337 deletions

View File

@ -8,14 +8,12 @@ Excalibur Igor (model 711E)
This is the newer version of Ivan, see ivanto.cpp for the first version. It's This is the newer version of Ivan, see ivanto.cpp for the first version. It's
on very different hardware. Manufacturing was moved to Ewig. Ivan's model number on very different hardware. Manufacturing was moved to Ewig. Ivan's model number
is the same as the first version, but it's easy to distinguish them. is the same as the first version, but it's easy to distinguish between them.
The chess engine is by Ron Nelson, similar to the one in Excalibur Mirage. It The chess engine is by Ron Nelson, similar to the one in Excalibur Mirage. It
has speech, and also sound effects that are reminiscent of Battle Chess. has speech, and also sound effects that are reminiscent of Battle Chess.
Hardware notes: Hardware notes:
Ivan The Terrible:
- PCB label: EXCALIBUR ELECTRONICS, INC. 4/18/97, IVANT2, 00-33352-000 - PCB label: EXCALIBUR ELECTRONICS, INC. 4/18/97, IVANT2, 00-33352-000
- Hitachi H8/3216 MCU (only 32KB out of 48KB internal ROM used), 12MHz XTAL - Hitachi H8/3216 MCU (only 32KB out of 48KB internal ROM used), 12MHz XTAL
- small daughterboard (27C080 pinout) with an 1MB ROM under epoxy, contents is - small daughterboard (27C080 pinout) with an 1MB ROM under epoxy, contents is
@ -24,11 +22,9 @@ Ivan The Terrible:
- LCD with 5 7segs and custom segments - LCD with 5 7segs and custom segments
- no LEDs, button sensors chessboard - no LEDs, button sensors chessboard
Igor: Igor is on the same base hardware. The PCB (label: EXCALIBUR ELECTRONICS, INC.
- PCB label: EXCALIBUR ELECTRONICS, INC. 510-1005A01, 5/28/97 IGOR 510-1005A01, 5/28/97 IGOR) looks a bit different, but the connections are the
- Hitachi H8/3214 MCU, 12MHz XTAL same as Ivan. It has a H8/3214 MCU and the sound ROM is 128KB instead of 1MB.
- sound ROM under epoxy 128KB instead of 1MB
- rest is same as Ivan
There's also a newer version of Igor from 2000 (model 711E-2) on much weaker There's also a newer version of Igor from 2000 (model 711E-2) on much weaker
hardware, it has a Samsung KS57C2308 MCU instead. hardware, it has a Samsung KS57C2308 MCU instead.

View File

@ -129,7 +129,6 @@ authors:hap
</element> </element>
<!-- control panel --> <!-- control panel -->
<element ref="static_pink"> <element ref="static_pink">
<bounds x="0" y="60" width="200" height="30" /> <bounds x="0" y="60" width="200" height="30" />
</element> </element>
@ -162,9 +161,7 @@ authors:hap
<bounds x="129" y="71" width="10" height="15" /> <bounds x="129" y="71" width="10" height="15" />
</element> </element>
<!-- left ufo info --> <!-- left ufo info -->
<element ref="text_x"> <element ref="text_x">
<bounds x="5" y="5" width="10" height="4" /> <bounds x="5" y="5" width="10" height="4" />
</element> </element>
@ -215,7 +212,6 @@ authors:hap
</element> </element>
<!-- right ufo info --> <!-- right ufo info -->
<element ref="text_x"> <element ref="text_x">
<bounds x="105" y="5" width="10" height="4" /> <bounds x="105" y="5" width="10" height="4" />
</element> </element>
@ -265,6 +261,5 @@ authors:hap
<bounds x="166" y="44" width="3" height="3" /> <bounds x="166" y="44" width="3" height="3" />
</element> </element>
</view> </view>
</mamelayout> </mamelayout>

View File

@ -5,7 +5,6 @@ authors:hap
--> -->
<mamelayout version="2"> <mamelayout version="2">
<!-- define elements --> <!-- define elements -->
<element name="static_black"><rect><color red="0.0" green="0.0" blue="0.0" /></rect></element> <element name="static_black"><rect><color red="0.0" green="0.0" blue="0.0" /></rect></element>
@ -110,7 +109,6 @@ authors:hap
</element> </element>
<!-- control panel --> <!-- control panel -->
<element ref="static_pink"> <element ref="static_pink">
<bounds x="0" y="60" width="200" height="30" /> <bounds x="0" y="60" width="200" height="30" />
</element> </element>
@ -122,10 +120,10 @@ authors:hap
<bounds x="43" y="70" width="10" height="10"/> <bounds x="43" y="70" width="10" height="10"/>
</element> </element>
<element name="lamp2" ref="lamp_b1" inputtag="IN2" inputmask="0x10" > <element name="lamp3" ref="lamp_b2" inputtag="IN2" inputmask="0x20" >
<bounds x="147" y="70" width="10" height="10"/> <bounds x="147" y="70" width="10" height="10"/>
</element> </element>
<element name="lamp3" ref="lamp_b2" inputtag="IN2" inputmask="0x20" > <element name="lamp2" ref="lamp_b1" inputtag="IN2" inputmask="0x10" >
<bounds x="160" y="70" width="10" height="10"/> <bounds x="160" y="70" width="10" height="10"/>
</element> </element>
@ -143,9 +141,7 @@ authors:hap
<bounds x="129" y="71" width="10" height="15" /> <bounds x="129" y="71" width="10" height="15" />
</element> </element>
<!-- left ufo info --> <!-- left ufo info -->
<element ref="text_x"> <element ref="text_x">
<bounds x="5" y="5" width="10" height="4" /> <bounds x="5" y="5" width="10" height="4" />
</element> </element>
@ -196,7 +192,6 @@ authors:hap
</element> </element>
<!-- right ufo info --> <!-- right ufo info -->
<element ref="text_x"> <element ref="text_x">
<bounds x="105" y="5" width="10" height="4" /> <bounds x="105" y="5" width="10" height="4" />
</element> </element>
@ -246,6 +241,5 @@ authors:hap
<bounds x="166" y="44" width="3" height="3" /> <bounds x="166" y="44" width="3" height="3" />
</element> </element>
</view> </view>
</mamelayout> </mamelayout>

View File

@ -5,7 +5,6 @@ authors:hap
--> -->
<mamelayout version="2"> <mamelayout version="2">
<!-- define elements --> <!-- define elements -->
<element name="static_black"><rect><color red="0.0" green="0.0" blue="0.0" /></rect></element> <element name="static_black"><rect><color red="0.0" green="0.0" blue="0.0" /></rect></element>
@ -106,7 +105,6 @@ authors:hap
</element> </element>
<!-- control panel --> <!-- control panel -->
<element ref="static_pink"> <element ref="static_pink">
<bounds x="0" y="60" width="100" height="30" /> <bounds x="0" y="60" width="100" height="30" />
</element> </element>
@ -125,9 +123,7 @@ authors:hap
<bounds x="61" y="71" width="10" height="15" /> <bounds x="61" y="71" width="10" height="15" />
</element> </element>
<!-- left ufo info --> <!-- left ufo info -->
<element ref="text_x"> <element ref="text_x">
<bounds x="5" y="5" width="10" height="4" /> <bounds x="5" y="5" width="10" height="4" />
</element> </element>
@ -174,6 +170,5 @@ authors:hap
<bounds x="62" y="44" width="3" height="3" /> <bounds x="62" y="44" width="3" height="3" />
</element> </element>
</view> </view>
</mamelayout> </mamelayout>

View File

@ -5,7 +5,6 @@ authors:hap
--> -->
<mamelayout version="2"> <mamelayout version="2">
<!-- define elements --> <!-- define elements -->
<element name="static_black"><rect><color red="0.0" green="0.0" blue="0.0" /></rect></element> <element name="static_black"><rect><color red="0.0" green="0.0" blue="0.0" /></rect></element>
@ -126,7 +125,6 @@ authors:hap
</element> </element>
<!-- control panel --> <!-- control panel -->
<element ref="static_pink"> <element ref="static_pink">
<bounds x="0" y="60" width="100" height="30" /> <bounds x="0" y="60" width="100" height="30" />
</element> </element>
@ -145,9 +143,7 @@ authors:hap
<bounds x="61" y="71" width="10" height="15" /> <bounds x="61" y="71" width="10" height="15" />
</element> </element>
<!-- left ufo info --> <!-- left ufo info -->
<element ref="text_x"> <element ref="text_x">
<bounds x="5" y="5" width="10" height="4" /> <bounds x="5" y="5" width="10" height="4" />
</element> </element>
@ -197,6 +193,5 @@ authors:hap
<bounds x="66" y="44" width="3" height="3" /> <bounds x="66" y="44" width="3" height="3" />
</element> </element>
</view> </view>
</mamelayout> </mamelayout>

View File

@ -61,7 +61,6 @@ Overall, the hardware has similarities with Wacky Gator, see wacky_gator.cpp.
#include "machine/pit8253.h" #include "machine/pit8253.h"
#include "machine/ripple_counter.h" #include "machine/ripple_counter.h"
#include "machine/ticket.h" #include "machine/ticket.h"
#include "machine/timer.h"
#include "machine/watchdog.h" #include "machine/watchdog.h"
#include "sound/upd7759.h" #include "sound/upd7759.h"
#include "sound/ymopm.h" #include "sound/ymopm.h"
@ -115,7 +114,6 @@ public:
m_cg_count(*this, "cg_count%u", 0U) m_cg_count(*this, "cg_count%u", 0U)
{ } { }
// machine configs
void cgang(machine_config &config); void cgang(machine_config &config);
protected: protected:
@ -149,6 +147,23 @@ private:
output_finder<5> m_en_count; output_finder<5> m_en_count;
output_finder<5> m_cg_count; output_finder<5> m_cg_count;
int m_watchdog_clk = 0;
int m_main_irq = 0;
int m_main_firq = 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_pos[5] = { };
emu_timer *m_door_timer;
emu_timer *m_sol_filter[5];
TIMER_CALLBACK_MEMBER(output_sol) { m_en_sol[param >> 1] = param & 1; }
// address maps // address maps
void main_map(address_map &map); void main_map(address_map &map);
void sound_map(address_map &map); void sound_map(address_map &map);
@ -160,7 +175,7 @@ private:
void main_firq_clear_w(u8 data); void main_firq_clear_w(u8 data);
template<int N> void motor_clock_w(int state); template<int N> void motor_clock_w(int state);
void cg_motor_tick(int i); void cg_motor_tick(int i);
TIMER_DEVICE_CALLBACK_MEMBER(door_motor_tick); TIMER_CALLBACK_MEMBER(door_motor_tick);
void refresh_motor_output(); void refresh_motor_output();
u8 ppi1_b_r(); u8 ppi1_b_r();
@ -183,21 +198,6 @@ private:
void ppi5_a_w(u8 data); void ppi5_a_w(u8 data);
void ppi5_b_w(u8 data); void ppi5_b_w(u8 data);
u8 ppi5_c_r(); u8 ppi5_c_r();
int m_watchdog_clk = 0;
int m_main_irq = 0;
int m_main_firq = 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_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()
@ -205,6 +205,9 @@ void cgang_state::machine_start()
for (int i = 0; i < 5; i++) for (int i = 0; i < 5; i++)
m_sol_filter[i] = timer_alloc(FUNC(cgang_state::output_sol), this); m_sol_filter[i] = timer_alloc(FUNC(cgang_state::output_sol), this);
m_door_timer = timer_alloc(FUNC(cgang_state::door_motor_tick), this);
m_door_timer->adjust(attotime::from_msec(1), 0, attotime::from_msec(1));
// resolve outputs // resolve outputs
m_gun_lamps.resolve(); m_gun_lamps.resolve();
m_spot_lamps.resolve(); m_spot_lamps.resolve();
@ -332,7 +335,7 @@ void cgang_state::cg_motor_tick(int i)
refresh_motor_output(); refresh_motor_output();
} }
TIMER_DEVICE_CALLBACK_MEMBER(cgang_state::door_motor_tick) TIMER_CALLBACK_MEMBER(cgang_state::door_motor_tick)
{ {
if (m_door_motor_on & 2 && m_door_motor_pos < DOOR_MOTOR_LIMIT) if (m_door_motor_on & 2 && m_door_motor_pos < DOOR_MOTOR_LIMIT)
m_door_motor_pos++; m_door_motor_pos++;
@ -808,8 +811,6 @@ void cgang_state::cgang(machine_config &config)
TICKET_DISPENSER(config, m_ticket, attotime::from_msec(3000), TICKET_MOTOR_ACTIVE_HIGH, TICKET_STATUS_ACTIVE_HIGH); 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);
m_digits->set_segmask(0x3ff, 0x7f); m_digits->set_segmask(0x3ff, 0x7f);
@ -860,5 +861,5 @@ ROM_END
Drivers Drivers
*******************************************************************************/ *******************************************************************************/
// YEAR NAME PARENT MACHINE INPUT CLASS INIT MONITOR COMPANY, FULLNAME, FLAGS // YEAR NAME PARENT MACHINE INPUT CLASS INIT MNTR COMPANY, FULLNAME, FLAGS
GAME( 1990, cgang, 0, cgang, cgang, cgang_state, empty_init, ROT0, "Namco (Data East license)", "Cosmo Gang (US)", MACHINE_SUPPORTS_SAVE | MACHINE_MECHANICAL | MACHINE_IMPERFECT_CONTROLS ) GAME( 1990, cgang, 0, cgang, cgang, cgang_state, empty_init, ROT0, "Namco (Data East license)", "Cosmo Gang (US)", MACHINE_SUPPORTS_SAVE | MACHINE_MECHANICAL | MACHINE_IMPERFECT_CONTROLS )

View File

@ -10,8 +10,8 @@ properly.
TODO: TODO:
- if/when MAME supports an exit callback, hook up power-off switch to that - if/when MAME supports an exit callback, hook up power-off switch to that
- super system peripherals don't work on nsnova due to serial clock drift, baud - Novag Super System peripherals don't work on nsnova due to serial clock drift,
rate differs a bit between host and client, m6801 serial emulation issue baud rate differs a bit between host and client, m6801 serial emulation issue
- unmapped reads from 0x3c/0x3d (primo/supremo) or 0x33/0x34 (nsnova) - unmapped reads from 0x3c/0x3d (primo/supremo) or 0x33/0x34 (nsnova)
- supremo unmapped writes to 0x2000/0x6000, always 0? - supremo unmapped writes to 0x2000/0x6000, always 0?
- is the 1st version of supremo(black plastic) the same ROM? - is the 1st version of supremo(black plastic) the same ROM?

View File

@ -5,8 +5,8 @@
Novag Sapphire (model 9304) Novag Sapphire (model 9304)
It's the successor to Novag VIP / Super VIP, the chess engine is again by Handheld chess computer. It's the successor to Novag Super VIP, whereas Ruby is
David Kittinger. the successor to Novag VIP. The chess engine is by David Kittinger again.
Hardware notes: Hardware notes:
- PCB label: 100168 REV A - PCB label: 100168 REV A
@ -17,7 +17,9 @@ Hardware notes:
- 24 buttons, piezo - 24 buttons, piezo
TODO: TODO:
- rs232 nss_tvi (Novag TV Interface) doesn't work - Novag Super System peripherals don't work due to serial clock drift, baud rate
differs a bit between host and client, m6801 serial emulation issue (to work
around it, underclock sapphire to exactly 26.4192MHz)
- it does a cold boot at every reset, so nvram won't work properly unless MAME - it does a cold boot at every reset, so nvram won't work properly unless MAME
adds some kind of auxillary autosave state feature at power-off adds some kind of auxillary autosave state feature at power-off

View File

@ -1,6 +1,6 @@
// license:BSD-3-Clause // license:BSD-3-Clause
// copyright-holders:hap // copyright-holders:hap
/*************************************************************************** /*******************************************************************************
Sega UFO Catcher, Z80 type hardware Sega UFO Catcher, Z80 type hardware
The list underneath is not complete. A # before the name means it's not dumped yet. The list underneath is not complete. A # before the name means it's not dumped yet.
@ -23,12 +23,12 @@
- # School Kids (1993) - # School Kids (1993)
4th gen - EX brd 4th gen - EX brd
* Z80 Z0840008PSC, 8MHz XTAL, 32MHz XTAL, 2 Sega 315-5296(I/O), 315-5338A, YM3438, * Z80 Z0840008PSC, 8MHz XTAL, 32MHz XTAL, 2 Sega 315-5296(I/O), YM3438, NEC uPD71054C,
NEC uPD71054C, optional NEC uPD7759C optional 315-5338A, optional NEC uPD7759C
- # Dream Palace (1992) - # Dream Palace (1992)
- # Dream Kitchen (1994) - # Dream Kitchen (1994)
- # UFO Catcher Excellent (1994) - # UFO Catcher Excellent (1994)
- # UFO A La Carte (1996) - # UFO A La Carte (1996) (2P)
- UFO Catcher 21 (1996) (2P) - UFO Catcher 21 (1996) (2P)
- UFO Catcher 800 (1998) (1P) - UFO Catcher 800 (1998) (1P)
- # Baby UFO (1998) - # Baby UFO (1998)
@ -40,7 +40,7 @@
- add dipswitches - add dipswitches
- prize sensor for ufo21/ufo800 - prize sensor for ufo21/ufo800
***************************************************************************/ *******************************************************************************/
#include "emu.h" #include "emu.h"
@ -49,7 +49,6 @@
#include "cpu/z80/z80.h" #include "cpu/z80/z80.h"
#include "machine/pit8253.h" #include "machine/pit8253.h"
#include "machine/timer.h"
#include "sound/upd7759.h" #include "sound/upd7759.h"
#include "sound/ymopn.h" #include "sound/ymopn.h"
@ -67,7 +66,8 @@
namespace { namespace {
/* simulation parameters */ // simulation parameters
// x/y/z cabinet dimensions per player (motor range) // x/y/z cabinet dimensions per player (motor range)
#define CABINET_WIDTH 400 #define CABINET_WIDTH 400
#define CABINET_DEPTH 400 #define CABINET_DEPTH 400
@ -81,83 +81,132 @@ namespace {
#define CRANE_SIZE 350 #define CRANE_SIZE 350
class ufo_state : public driver_device class ufo_state : public driver_device
{ {
public: public:
ufo_state(const machine_config &mconfig, device_type type, const char *tag) : ufo_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag), driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"), m_maincpu(*this, "maincpu"),
m_io1(*this, "io1"), m_io(*this, "io%u", 1),
m_io2(*this, "io2"),
m_upd(*this, "upd"), m_upd(*this, "upd"),
m_inputs(*this, "IN%u", 1),
m_counters(*this, "counter%u", 0U), m_counters(*this, "counter%u", 0U),
m_digits(*this, "digit%u", 0U), m_digits(*this, "digit%u", 0U),
m_lamps(*this, "lamp%u", 0U) m_lamps(*this, "lamp%u", 0U)
{ } { }
// machine configs
void ufomini(machine_config &config); void ufomini(machine_config &config);
void ufo21(machine_config &config); void ufo21(machine_config &config);
void newufo(machine_config &config); void newufo(machine_config &config);
void ufo800(machine_config &config); void ufo800(machine_config &config);
private: protected:
void motor_tick(int p, int m);
void pit_out0(int state);
void pit_out1(int state);
void pit_out2(int state);
uint8_t crane_limits_r(offs_t offset);
void stepper_w(uint8_t data);
void cp_lamps_w(uint8_t data);
void cp_digits_w(offs_t offset, uint8_t data);
void crane_xyz_w(offs_t offset, uint8_t data);
void ufo_lamps_w(uint8_t data);
uint8_t ex_crane_limits_r(offs_t offset);
uint8_t ex_crane_open_r();
void ex_stepper_w(uint8_t data);
void ex_cp_lamps_w(uint8_t data);
void ex_crane_xyz_w(offs_t offset, uint8_t data);
void ex_ufo21_lamps1_w(uint8_t data);
void ex_ufo21_lamps2_w(uint8_t data);
void ex_ufo800_lamps_w(uint8_t data);
uint8_t ex_upd_busy_r();
void ex_upd_start_w(uint8_t data);
virtual void machine_reset() override;
virtual void machine_start() override; virtual void machine_start() override;
TIMER_DEVICE_CALLBACK_MEMBER(simulate_xyz); virtual void machine_reset() override { m_nmi_enable = false; }
TIMER_DEVICE_CALLBACK_MEMBER(update_info);
void ufo_map(address_map &map); private:
void ufo_portmap(address_map &map); // devices/pointers
void ex_ufo21_portmap(address_map &map); required_device<cpu_device> m_maincpu;
void ex_ufo800_portmap(address_map &map); required_device_array<sega_315_5296_device, 2> m_io;
optional_device<upd7759_device> m_upd;
optional_ioport_array<2> m_inputs;
output_finder<2 * 4> m_counters;
output_finder<2> m_digits;
output_finder<28> m_lamps;
struct Player struct Player
{ {
struct Motor struct Motor
{ {
uint8_t running = 0; u8 running = 0;
uint8_t direction = 0; u8 direction = 0;
float position = 0; float position = 0.5f;
float speed = 0; float speed = 0.0f;
} motor[4]; } motor[4];
} m_player[2]; } m_player[2];
uint8_t m_stepper = 0; bool m_nmi_enable = false;
u8 m_stepper = 0;
required_device<cpu_device> m_maincpu; emu_timer *m_motor_timer;
required_device<sega_315_5296_device> m_io1;
required_device<sega_315_5296_device> m_io2; void init_motors();
optional_device<upd7759_device> m_upd; void motor_tick(int p, int m);
output_finder<2 * 4> m_counters; TIMER_CALLBACK_MEMBER(simulate_xyz);
output_finder<2> m_digits;
output_finder<28> m_lamps; // address maps
void ufo_map(address_map &map);
void ufo_portmap(address_map &map);
void ex_ufo21_portmap(address_map &map);
// I/O handlers
void pit_out0(int state);
void pit_out1(int state);
void pit_out2(int state);
void nmi_enable_w(int state) { m_nmi_enable = bool(state); }
template<int P> u8 crane_limits_r();
void stepper_w(u8 data);
void cp_lamps_w(u8 data);
template<int P> void cp_digits_w(u8 data);
template<int P> void crane_xyz_w(u8 data);
void ufo_lamps_w(u8 data);
template<int P> u8 ex_crane_limits_r();
u8 ex_crane_open_r();
void ex_stepper_w(u8 data);
void ex_cp_lamps_w(u8 data);
template<int P> void ex_crane_xyz_w(u8 data);
void ex_ufo21_lamps1_w(u8 data);
void ex_ufo21_lamps2_w(u8 data);
void ex_ufo800_lamps_w(u8 data);
u8 ex_upd_busy_r();
void ex_upd_start_w(u8 data);
}; };
void ufo_state::machine_start()
{
// resolve outputs
m_counters.resolve();
m_digits.resolve();
m_lamps.resolve();
// register for savestates
save_item(NAME(m_stepper));
save_item(NAME(m_nmi_enable));
init_motors();
}
/*******************************************************************************
Motors
*******************************************************************************/
void ufo_state::init_motors()
{
m_motor_timer = timer_alloc(FUNC(ufo_state::simulate_xyz), this);
m_motor_timer->adjust(attotime::from_hz(MOTOR_SPEED), 0, attotime::from_hz(MOTOR_SPEED));
static const float motor_speeds[4] =
{ 1.0f/CABINET_WIDTH, 1.0f/CABINET_DEPTH, 1.0f/CABINET_HEIGHT, 1.0f/CRANE_SIZE };
for (int m = 0; m < 4; m++)
{
for (auto & elem : m_player)
elem.motor[m].speed = motor_speeds[m];
save_item(NAME(m_player[0].motor[m].running), m);
save_item(NAME(m_player[0].motor[m].direction), m);
save_item(NAME(m_player[0].motor[m].position), m);
save_item(NAME(m_player[1].motor[m].running), m);
save_item(NAME(m_player[1].motor[m].direction), m);
save_item(NAME(m_player[1].motor[m].position), m);
}
}
void ufo_state::motor_tick(int p, int m) void ufo_state::motor_tick(int p, int m)
{ {
@ -174,16 +223,12 @@ void ufo_state::motor_tick(int p, int m)
m_player[p].motor[m].position = 1; m_player[p].motor[m].position = 1;
} }
TIMER_DEVICE_CALLBACK_MEMBER(ufo_state::simulate_xyz) TIMER_CALLBACK_MEMBER(ufo_state::simulate_xyz)
{ {
for (int p = 0; p < 2; p++) for (int p = 0; p < 2; p++)
for (int m = 0; m < 3; m++) for (int m = 0; m < 3; m++)
motor_tick(p, m); motor_tick(p, m);
}
TIMER_DEVICE_CALLBACK_MEMBER(ufo_state::update_info)
{
// output ufo motor positions // output ufo motor positions
// 0 X: 000 = right, 100 = left (player 1) // 0 X: 000 = right, 100 = left (player 1)
// 1 Y: 000 = front, 100 = back // 1 Y: 000 = front, 100 = back
@ -192,25 +237,26 @@ TIMER_DEVICE_CALLBACK_MEMBER(ufo_state::update_info)
for (int p = 0; p < 2; p++) for (int p = 0; p < 2; p++)
{ {
for (int m = 0; m < 4; m++) for (int m = 0; m < 4; m++)
m_counters[(p << 2) | m] = uint8_t(m_player[p].motor[m].position * 100); m_counters[(p << 2) | m] = u8(m_player[p].motor[m].position * 100);
} }
#if 0 #if 0
// show io2 outputs
std::ostringstream msg; std::ostringstream msg;
msg << std::hex << std::setfill('0');
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
msg << std::setw(2) << m_io2->debug_peek_output(i); {
msg << std::uppercase << std::hex << std::setw(2) << std::setfill('0') << +m_io[1]->debug_peek_output(i);
if (i != 7) msg << " ";
}
popmessage("%s", std::move(msg).str()); popmessage("%s", std::move(msg).str());
#endif #endif
} }
/*************************************************************************** /*******************************************************************************
I/O I/O
*******************************************************************************/
***************************************************************************/
void ufo_state::pit_out0(int state) void ufo_state::pit_out0(int state)
{ {
@ -220,7 +266,7 @@ void ufo_state::pit_out0(int state)
void ufo_state::pit_out1(int state) void ufo_state::pit_out1(int state)
{ {
// NMI? // NMI?
if (state) if (state && m_nmi_enable)
m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero); m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero);
} }
@ -230,14 +276,14 @@ void ufo_state::pit_out2(int state)
} }
/* generic / UFO board handlers */ // generic / UFO board handlers
/* io1 */ // 315-5296 #1
uint8_t ufo_state::crane_limits_r(offs_t offset) template<int P>
u8 ufo_state::crane_limits_r()
{ {
int p = offset & 1; u8 ret = 0x7f;
uint8_t ret = 0x7f;
// d0: left limit sw (right for p2) // d0: left limit sw (right for p2)
// d1: right limit sw (left for p2) // d1: right limit sw (left for p2)
@ -247,23 +293,24 @@ uint8_t ufo_state::crane_limits_r(offs_t offset)
// d5: up limit sw // d5: up limit sw
for (int m = 0; m < 3; m++) for (int m = 0; m < 3; m++)
{ {
ret ^= (m_player[p].motor[m].position >= 1) << (m*2 + 0); ret ^= (m_player[P].motor[m].position >= 1) << (m*2 + 0);
ret ^= (m_player[p].motor[m].position <= 0) << (m*2 + 1); ret ^= (m_player[P].motor[m].position <= 0) << (m*2 + 1);
} }
// d6: crane open sensor (reflective sticker on the stepper motor rotation disc) // d6: crane open sensor (reflective sticker on the stepper motor rotation disc)
if (m_player[p].motor[3].position >= 0.97f) if (m_player[P].motor[3].position >= 0.97f)
ret ^= 0x40; ret ^= 0x40;
// d7: prize sensor (mirror?) // d7: prize sensor (mirror?)
ret |= (ioport(p ? "IN2" : "IN1")->read() & 0x80); ret |= m_inputs[P]->read() & 0x80;
return ret; return ret;
} }
/* io2 */
void ufo_state::stepper_w(uint8_t data) // 315-5296 #2
void ufo_state::stepper_w(u8 data)
{ {
for (int p = 0; p < 2; p++) for (int p = 0; p < 2; p++)
{ {
@ -271,12 +318,12 @@ void ufo_state::stepper_w(uint8_t data)
// controlled with 4 output bits connected to a Toshiba TB6560AHQ motor driver. // controlled with 4 output bits connected to a Toshiba TB6560AHQ motor driver.
// I don't know which bits connect to which pins specifically. // I don't know which bits connect to which pins specifically.
// To run it, the game writes a continuous sequence of $5, $9, $a, $6, .. // To run it, the game writes a continuous sequence of $5, $9, $a, $6, ..
static const uint8_t sequence[4] = static const u8 sequence[4] =
{ 0x5, 0x9, 0xa, 0x6 }; { 0x5, 0x9, 0xa, 0x6 };
// d0-d3: p1, d4-d7: p2 // d0-d3: p1, d4-d7: p2
uint8_t cur = data >> (p*4) & 0xf; u8 cur = data >> (p*4) & 0xf;
uint8_t prev = m_stepper >> (p*4) & 0xf; u8 prev = m_stepper >> (p*4) & 0xf;
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
@ -297,7 +344,7 @@ void ufo_state::stepper_w(uint8_t data)
m_stepper = data; m_stepper = data;
} }
void ufo_state::cp_lamps_w(uint8_t data) void ufo_state::cp_lamps_w(u8 data)
{ {
// d0-d3: p1/p2 button lamps // d0-d3: p1/p2 button lamps
// other bits: ? // other bits: ?
@ -305,35 +352,35 @@ void ufo_state::cp_lamps_w(uint8_t data)
m_lamps[i] = BIT(~data, i); m_lamps[i] = BIT(~data, i);
} }
void ufo_state::cp_digits_w(offs_t offset, uint8_t data) template<int P>
void ufo_state::cp_digits_w(u8 data)
{ {
static constexpr uint8_t lut_7448[0x10] = static constexpr u8 lut_7448[0x10] =
{ 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7c,0x07,0x7f,0x67,0x58,0x4c,0x62,0x69,0x78,0x00 }; { 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7c,0x07,0x7f,0x67,0x58,0x4c,0x62,0x69,0x78,0x00 };
// d0-d3: cpanel digit // d0-d3: cpanel digit
// other bits: ? // other bits: ?
m_digits[offset & 1] = lut_7448[data & 0xf]; m_digits[P] = lut_7448[data & 0xf];
} }
void ufo_state::crane_xyz_w(offs_t offset, uint8_t data) template<int P>
void ufo_state::crane_xyz_w(u8 data)
{ {
int p = offset & 1;
// d0: x/z axis (0:x, 1:z + halt x/y) // d0: x/z axis (0:x, 1:z + halt x/y)
// d1: x/z direction // d1: x/z direction
// d2: y direction // d2: y direction
// d3: x/z running // d3: x/z running
// d4: y running // d4: y running
// other bits: ? // other bits: ?
m_player[p].motor[0].running = (data & 9) == 8; m_player[P].motor[0].running = (data & 9) == 8;
m_player[p].motor[0].direction = data & 2; m_player[P].motor[0].direction = data & 2;
m_player[p].motor[1].running = (data & 0x11) == 0x10; m_player[P].motor[1].running = (data & 0x11) == 0x10;
m_player[p].motor[1].direction = data & 4; m_player[P].motor[1].direction = data & 4;
m_player[p].motor[2].running = (data & 9) == 9; m_player[P].motor[2].running = (data & 9) == 9;
m_player[p].motor[2].direction = data & 2; m_player[P].motor[2].direction = data & 2;
} }
void ufo_state::ufo_lamps_w(uint8_t data) void ufo_state::ufo_lamps_w(u8 data)
{ {
// d0-d3: ufo leds (2 bits per player) // d0-d3: ufo leds (2 bits per player)
// 3 sets of two red/green leds, each set is wired to the same control 2 bits // 3 sets of two red/green leds, each set is wired to the same control 2 bits
@ -351,14 +398,14 @@ void ufo_state::ufo_lamps_w(uint8_t data)
} }
/* EX board specific handlers */ // EX board specific handlers
/* io1 */ // 315-5296 #1
uint8_t ufo_state::ex_crane_limits_r(offs_t offset) template<int P>
u8 ufo_state::ex_crane_limits_r()
{ {
int p = offset & 1; u8 ret = 0xf0;
uint8_t ret = 0xf0;
// d0: left limit sw (invert) // d0: left limit sw (invert)
// d1: right limit sw (invert) // d1: right limit sw (invert)
@ -371,17 +418,17 @@ uint8_t ufo_state::ex_crane_limits_r(offs_t offset)
for (int m = 0; m < 3; m++) for (int m = 0; m < 3; m++)
{ {
int shift = (m*2) + (m == 2); int shift = (m*2) + (m == 2);
ret ^= (m_player[p].motor[m].position >= 1) << shift; ret ^= (m_player[P].motor[m].position >= 1) << shift;
ret ^= (m_player[p].motor[m].position <= 0) << (shift+1); ret ^= (m_player[P].motor[m].position <= 0) << (shift+1);
} }
return ret; return ret;
} }
uint8_t ufo_state::ex_crane_open_r() u8 ufo_state::ex_crane_open_r()
{ {
// d0-d3: p1, d4-d7: p2 // d0-d3: p1, d4-d7: p2
uint8_t ret = 0xff; u8 ret = 0xff;
for (int p = 0; p < 2; p++) for (int p = 0; p < 2; p++)
{ {
@ -396,16 +443,17 @@ uint8_t ufo_state::ex_crane_open_r()
return ret; return ret;
} }
/* io2 */
void ufo_state::ex_stepper_w(uint8_t data) // 315-5296 #2
void ufo_state::ex_stepper_w(u8 data)
{ {
// stepper motor sequence is: 6 c 9 3 6 c 9 3.. // stepper motor sequence is: 6 c 9 3 6 c 9 3..
// which means d0 and d3 are swapped when compared with UFO board hardware // which means d0 and d3 are swapped when compared with UFO board hardware
stepper_w(bitswap<8>(data,4,6,5,7,0,2,1,3)); stepper_w(bitswap<8>(data,4,6,5,7,0,2,1,3));
} }
void ufo_state::ex_cp_lamps_w(uint8_t data) void ufo_state::ex_cp_lamps_w(u8 data)
{ {
// d0,d1,d4,d5: p1/p2 button lamps // d0,d1,d4,d5: p1/p2 button lamps
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
@ -416,10 +464,9 @@ void ufo_state::ex_cp_lamps_w(uint8_t data)
machine().bookkeeping().coin_counter_w(i, data >> (2 + (i&1) + (i&2) * 2) & 1); machine().bookkeeping().coin_counter_w(i, data >> (2 + (i&1) + (i&2) * 2) & 1);
} }
void ufo_state::ex_crane_xyz_w(offs_t offset, uint8_t data) template<int P>
void ufo_state::ex_crane_xyz_w(u8 data)
{ {
int p = offset & 1;
// more straightforward setup than on UFO board hardware // more straightforward setup than on UFO board hardware
// d0: move left // d0: move left
// d1: move right // d1: move right
@ -430,12 +477,12 @@ void ufo_state::ex_crane_xyz_w(offs_t offset, uint8_t data)
for (int m = 0; m < 3; m++) for (int m = 0; m < 3; m++)
{ {
int bits = data >> (m*2) & 3; int bits = data >> (m*2) & 3;
m_player[p].motor[m].running = (bits == 1 || bits == 2) ? 1 : 0; m_player[P].motor[m].running = (bits == 1 || bits == 2) ? 1 : 0;
m_player[p].motor[m].direction = bits & 2; m_player[P].motor[m].direction = bits & 2;
} }
} }
void ufo_state::ex_ufo800_lamps_w(uint8_t data) void ufo_state::ex_ufo800_lamps_w(u8 data)
{ {
// d0-d4: 5 red leds on ufo // d0-d4: 5 red leds on ufo
// other bits: ? // other bits: ?
@ -443,9 +490,10 @@ void ufo_state::ex_ufo800_lamps_w(uint8_t data)
m_lamps[10 + i] = BIT(data, i); m_lamps[10 + i] = BIT(data, i);
} }
/* 315-5338A */
void ufo_state::ex_ufo21_lamps1_w(uint8_t data) // 315-5338A
void ufo_state::ex_ufo21_lamps1_w(u8 data)
{ {
// d0: ? (ufo21 reads from it too, but value is discarded) // d0: ? (ufo21 reads from it too, but value is discarded)
// d1-d6 are the 6 red leds on each ufo // d1-d6 are the 6 red leds on each ufo
@ -454,20 +502,20 @@ void ufo_state::ex_ufo21_lamps1_w(uint8_t data)
m_lamps[10 + i] = BIT(data, i); m_lamps[10 + i] = BIT(data, i);
} }
void ufo_state::ex_ufo21_lamps2_w(uint8_t data) void ufo_state::ex_ufo21_lamps2_w(u8 data)
{ {
for (int i = 1; i < 7; i++) for (int i = 1; i < 7; i++)
m_lamps[20 + i] = BIT(data, i); m_lamps[20 + i] = BIT(data, i);
} }
void ufo_state::ex_upd_start_w(uint8_t data) void ufo_state::ex_upd_start_w(u8 data)
{ {
// d0: upd7759c start sample // d0: upd7759c start sample
// other bits: unused? // other bits: unused?
m_upd->start_w(~data & 1); m_upd->start_w(~data & 1);
} }
uint8_t ufo_state::ex_upd_busy_r() u8 ufo_state::ex_upd_busy_r()
{ {
// d0: upd7759c busy // d0: upd7759c busy
// other bits: unused? // other bits: unused?
@ -476,7 +524,10 @@ uint8_t ufo_state::ex_upd_busy_r()
} }
/* Memory maps */
/*******************************************************************************
Address Maps
*******************************************************************************/
void ufo_state::ufo_map(address_map &map) void ufo_state::ufo_map(address_map &map)
{ {
@ -490,8 +541,8 @@ void ufo_state::ufo_portmap(address_map &map)
map.global_mask(0xff); map.global_mask(0xff);
map(0x00, 0x03).rw("pit", FUNC(pit8254_device::read), FUNC(pit8254_device::write)); map(0x00, 0x03).rw("pit", FUNC(pit8254_device::read), FUNC(pit8254_device::write));
map(0x40, 0x43).rw("ym", FUNC(ym3438_device::read), FUNC(ym3438_device::write)); map(0x40, 0x43).rw("ym", FUNC(ym3438_device::read), FUNC(ym3438_device::write));
map(0x80, 0xbf).rw(m_io1, FUNC(sega_315_5296_device::read), FUNC(sega_315_5296_device::write)); map(0x80, 0xbf).rw(m_io[0], FUNC(sega_315_5296_device::read), FUNC(sega_315_5296_device::write));
map(0xc0, 0xff).rw(m_io2, FUNC(sega_315_5296_device::read), FUNC(sega_315_5296_device::write)); map(0xc0, 0xff).rw(m_io[1], FUNC(sega_315_5296_device::read), FUNC(sega_315_5296_device::write));
} }
void ufo_state::ex_ufo21_portmap(address_map &map) void ufo_state::ex_ufo21_portmap(address_map &map)
@ -501,20 +552,11 @@ void ufo_state::ex_ufo21_portmap(address_map &map)
map(0x60, 0x6f).rw("io3", FUNC(sega_315_5338a_device::read), FUNC(sega_315_5338a_device::write)); map(0x60, 0x6f).rw("io3", FUNC(sega_315_5338a_device::read), FUNC(sega_315_5338a_device::write));
} }
void ufo_state::ex_ufo800_portmap(address_map &map)
{
ufo_portmap(map);
// map(0x60, 0x67).noprw(); // unused?
// map(0x68, 0x68).nopw(); // ?
}
/*******************************************************************************
/*************************************************************************** Input Ports
*******************************************************************************/
Inputs
***************************************************************************/
static INPUT_PORTS_START( newufo ) static INPUT_PORTS_START( newufo )
PORT_START("IN1") PORT_START("IN1")
@ -622,7 +664,8 @@ static INPUT_PORTS_START( newufo )
PORT_DIPSETTING( 0x08, "Setting 1" ) PORT_DIPSETTING( 0x08, "Setting 1" )
PORT_DIPSETTING( 0x00, "Setting 2" ) PORT_DIPSETTING( 0x00, "Setting 2" )
// Manual states "5 ~ 8 must be set OFF." // Manual states "5 ~ 8 must be set OFF."
PORT_DIPNAME( 0x10, 0x10, "Ignore Prize Sensor" ) PORT_DIPLOCATION("SW2:5") // "When DIP SW 2 #5 is set to ON, the game can be played normally without error even if the prize sensor is malfunctioning." // "When DIP SW 2 #5 is set to ON, the game can be played normally without error even if the prize sensor is malfunctioning."
PORT_DIPNAME( 0x10, 0x10, "Ignore Prize Sensor" ) PORT_DIPLOCATION("SW2:5")
PORT_DIPSETTING( 0x10, DEF_STR( Off ) ) PORT_DIPSETTING( 0x10, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) ) // Manual states "Fanfare and CPanel Digit will not work though." PORT_DIPSETTING( 0x00, DEF_STR( On ) ) // Manual states "Fanfare and CPanel Digit will not work though."
PORT_DIPUNKNOWN( 0x20, IP_ACTIVE_LOW ) PORT_DIPLOCATION("SW2:6") PORT_DIPUNKNOWN( 0x20, IP_ACTIVE_LOW ) PORT_DIPLOCATION("SW2:6")
@ -782,92 +825,47 @@ INPUT_PORTS_END
/*************************************************************************** /*******************************************************************************
Machine Configs
Machine Config *******************************************************************************/
***************************************************************************/
void ufo_state::machine_reset()
{
}
void ufo_state::machine_start()
{
m_counters.resolve();
m_digits.resolve();
m_lamps.resolve();
// init/zerofill/register for savestates
static const float motor_speeds[4] =
{ 1.0f/CABINET_WIDTH, 1.0f/CABINET_DEPTH, 1.0f/CABINET_HEIGHT, 1.0f/CRANE_SIZE };
for (int m = 0; m < 4; m++)
{
for (auto & elem : m_player)
{
elem.motor[m].running = 0;
elem.motor[m].direction = 0;
elem.motor[m].position = 0.5;
elem.motor[m].speed = motor_speeds[m];
}
save_item(NAME(m_player[0].motor[m].running), m);
save_item(NAME(m_player[0].motor[m].direction), m);
save_item(NAME(m_player[0].motor[m].position), m);
save_item(NAME(m_player[1].motor[m].running), m);
save_item(NAME(m_player[1].motor[m].direction), m);
save_item(NAME(m_player[1].motor[m].position), m);
}
m_stepper = 0;
save_item(NAME(m_stepper));
}
void ufo_state::newufo(machine_config &config) void ufo_state::newufo(machine_config &config)
{ {
/* basic machine hardware */ // basic machine hardware
Z80(config, m_maincpu, XTAL(16'000'000)/2); Z80(config, m_maincpu, 16_MHz_XTAL/2);
m_maincpu->set_addrmap(AS_PROGRAM, &ufo_state::ufo_map); m_maincpu->set_addrmap(AS_PROGRAM, &ufo_state::ufo_map);
m_maincpu->set_addrmap(AS_IO, &ufo_state::ufo_portmap); m_maincpu->set_addrmap(AS_IO, &ufo_state::ufo_portmap);
TIMER(config, "motor_timer").configure_periodic(FUNC(ufo_state::simulate_xyz), attotime::from_hz(MOTOR_SPEED)); SEGA_315_5296(config, m_io[0], 16_MHz_XTAL); // all ports set to input
TIMER(config, "update_timer").configure_periodic(FUNC(ufo_state::update_info), attotime::from_hz(60)); m_io[0]->in_pa_callback().set(FUNC(ufo_state::crane_limits_r<0>));
m_io[0]->in_pb_callback().set(FUNC(ufo_state::crane_limits_r<1>));
m_io[0]->in_pe_callback().set_ioport("IN1");
m_io[0]->in_pf_callback().set_ioport("DSW1");
m_io[0]->in_pg_callback().set_ioport("DSW2");
m_io[0]->in_ph_callback().set_ioport("IN2");
SEGA_315_5296(config, m_io1, XTAL(16'000'000)); SEGA_315_5296(config, m_io[1], 16_MHz_XTAL); // all ports set to output
// all ports set to input m_io[1]->out_pa_callback().set(FUNC(ufo_state::stepper_w));
m_io1->in_pa_callback().set(FUNC(ufo_state::crane_limits_r)); m_io[1]->out_pb_callback().set(FUNC(ufo_state::cp_lamps_w));
m_io1->in_pb_callback().set(FUNC(ufo_state::crane_limits_r)); m_io[1]->out_pc_callback().set(FUNC(ufo_state::cp_digits_w<0>));
m_io1->in_pe_callback().set_ioport("IN1"); m_io[1]->out_pd_callback().set(FUNC(ufo_state::cp_digits_w<1>));
m_io1->in_pf_callback().set_ioport("DSW1"); m_io[1]->out_pe_callback().set(FUNC(ufo_state::crane_xyz_w<0>));
m_io1->in_pg_callback().set_ioport("DSW2"); m_io[1]->out_pf_callback().set(FUNC(ufo_state::crane_xyz_w<1>));
m_io1->in_ph_callback().set_ioport("IN2"); m_io[1]->out_pg_callback().set(FUNC(ufo_state::ufo_lamps_w));
m_io[1]->out_cnt1_callback().set(FUNC(ufo_state::nmi_enable_w));
SEGA_315_5296(config, m_io2, XTAL(16'000'000)); pit8254_device &pit(PIT8254(config, "pit", 16_MHz_XTAL/2)); // uPD71054C, configuration is unknown
// all ports set to output pit.set_clk<0>(16_MHz_XTAL/2/256);
m_io2->out_pa_callback().set(FUNC(ufo_state::stepper_w));
m_io2->out_pb_callback().set(FUNC(ufo_state::cp_lamps_w));
m_io2->out_pc_callback().set(FUNC(ufo_state::cp_digits_w));
m_io2->out_pd_callback().set(FUNC(ufo_state::cp_digits_w));
m_io2->out_pe_callback().set(FUNC(ufo_state::crane_xyz_w));
m_io2->out_pf_callback().set(FUNC(ufo_state::crane_xyz_w));
m_io2->out_pg_callback().set(FUNC(ufo_state::ufo_lamps_w));
pit8254_device &pit(PIT8254(config, "pit", XTAL(16'000'000)/2)); // uPD71054C, configuration is unknown
pit.set_clk<0>(XTAL(16'000'000)/2/256);
pit.out_handler<0>().set(FUNC(ufo_state::pit_out0)); pit.out_handler<0>().set(FUNC(ufo_state::pit_out0));
pit.set_clk<1>(XTAL(16'000'000)/2/256); pit.set_clk<1>(16_MHz_XTAL/2/256);
pit.out_handler<1>().set(FUNC(ufo_state::pit_out1)); pit.out_handler<1>().set(FUNC(ufo_state::pit_out1));
pit.set_clk<2>(XTAL(16'000'000)/2/256); pit.set_clk<2>(16_MHz_XTAL/2/256);
pit.out_handler<2>().set(FUNC(ufo_state::pit_out2)); pit.out_handler<2>().set(FUNC(ufo_state::pit_out2));
/* no video! */ // sound hardware
/* sound hardware */
SPEAKER(config, "mono").front_center(); SPEAKER(config, "mono").front_center();
ym3438_device &ym(YM3438(config, "ym", XTAL(16'000'000)/2)); ym3438_device &ym(YM3438(config, "ym", 16_MHz_XTAL/2));
ym.irq_handler().set_inputline("maincpu", 0); ym.irq_handler().set_inputline("maincpu", 0);
ym.add_route(0, "mono", 0.40); ym.add_route(0, "mono", 0.40);
ym.add_route(1, "mono", 0.40); ym.add_route(1, "mono", 0.40);
@ -877,10 +875,10 @@ void ufo_state::ufomini(machine_config &config)
{ {
newufo(config); newufo(config);
/* basic machine hardware */ // basic machine hardware
m_io1->in_pc_callback().set_ioport("IN1"); m_io[0]->in_pc_callback().set_ioport("IN1");
m_io1->in_pe_callback().set_constant(0); m_io[0]->in_pe_callback().set_constant(0);
m_io1->in_ph_callback().set_constant(0); m_io[0]->in_ph_callback().set_constant(0);
} }
@ -888,18 +886,18 @@ void ufo_state::ufo21(machine_config &config)
{ {
newufo(config); newufo(config);
/* basic machine hardware */ // basic machine hardware
m_maincpu->set_addrmap(AS_IO, &ufo_state::ex_ufo21_portmap); m_maincpu->set_addrmap(AS_IO, &ufo_state::ex_ufo21_portmap);
m_io1->in_pa_callback().set(FUNC(ufo_state::ex_crane_limits_r)); m_io[0]->in_pa_callback().set(FUNC(ufo_state::ex_crane_limits_r<0>));
m_io1->in_pb_callback().set(FUNC(ufo_state::ex_crane_limits_r)); m_io[0]->in_pb_callback().set(FUNC(ufo_state::ex_crane_limits_r<1>));
m_io1->in_pc_callback().set(FUNC(ufo_state::ex_crane_open_r)); m_io[0]->in_pc_callback().set(FUNC(ufo_state::ex_crane_open_r));
m_io2->out_pa_callback().set(FUNC(ufo_state::ex_stepper_w)); m_io[1]->out_pa_callback().set(FUNC(ufo_state::ex_stepper_w));
m_io2->out_pb_callback().set(FUNC(ufo_state::ex_cp_lamps_w)); m_io[1]->out_pb_callback().set(FUNC(ufo_state::ex_cp_lamps_w));
m_io2->out_pe_callback().set(FUNC(ufo_state::ex_crane_xyz_w)); m_io[1]->out_pe_callback().set(FUNC(ufo_state::ex_crane_xyz_w<0>));
m_io2->out_pf_callback().set(FUNC(ufo_state::ex_crane_xyz_w)); m_io[1]->out_pf_callback().set(FUNC(ufo_state::ex_crane_xyz_w<1>));
m_io2->out_pg_callback().set_nop(); m_io[1]->out_pg_callback().set_nop();
sega_315_5338a_device &io3(SEGA_315_5338A(config, "io3", 0)); sega_315_5338a_device &io3(SEGA_315_5338A(config, "io3", 0));
io3.out_pa_callback().set(FUNC(ufo_state::ex_upd_start_w)); io3.out_pa_callback().set(FUNC(ufo_state::ex_upd_start_w));
@ -907,7 +905,7 @@ void ufo_state::ufo21(machine_config &config)
io3.out_pe_callback().set(FUNC(ufo_state::ex_ufo21_lamps1_w)); io3.out_pe_callback().set(FUNC(ufo_state::ex_ufo21_lamps1_w));
io3.out_pf_callback().set(FUNC(ufo_state::ex_ufo21_lamps2_w)); io3.out_pf_callback().set(FUNC(ufo_state::ex_ufo21_lamps2_w));
/* sound hardware */ // sound hardware
UPD7759(config, m_upd); UPD7759(config, m_upd);
m_upd->add_route(ALL_OUTPUTS, "mono", 0.75); m_upd->add_route(ALL_OUTPUTS, "mono", 0.75);
} }
@ -916,30 +914,26 @@ void ufo_state::ufo800(machine_config &config)
{ {
newufo(config); newufo(config);
/* basic machine hardware */ // basic machine hardware
m_maincpu->set_addrmap(AS_IO, &ufo_state::ex_ufo800_portmap); m_io[0]->in_pa_callback().set(FUNC(ufo_state::ex_crane_limits_r<0>));
m_io[0]->in_pb_callback().set_ioport("IN2");
m_io[0]->in_pc_callback().set(FUNC(ufo_state::ex_crane_open_r));
m_io[0]->in_pd_callback().set_ioport("IN1");
m_io[0]->in_pe_callback().set_constant(0);
m_io[0]->in_ph_callback().set_constant(0);
m_io1->in_pa_callback().set(FUNC(ufo_state::ex_crane_limits_r)); m_io[1]->out_pa_callback().set(FUNC(ufo_state::ex_stepper_w));
m_io1->in_pb_callback().set_ioport("IN2"); m_io[1]->out_pb_callback().set(FUNC(ufo_state::ex_cp_lamps_w));
m_io1->in_pc_callback().set(FUNC(ufo_state::ex_crane_open_r)); m_io[1]->out_pe_callback().set(FUNC(ufo_state::ex_crane_xyz_w<0>));
m_io1->in_pd_callback().set_ioport("IN1"); m_io[1]->out_pf_callback().set(FUNC(ufo_state::ex_ufo800_lamps_w));
m_io1->in_pe_callback().set_constant(0); m_io[1]->out_pg_callback().set_nop();
m_io1->in_ph_callback().set_constant(0);
m_io2->out_pa_callback().set(FUNC(ufo_state::ex_stepper_w));
m_io2->out_pb_callback().set(FUNC(ufo_state::ex_cp_lamps_w));
m_io2->out_pe_callback().set(FUNC(ufo_state::ex_crane_xyz_w));
m_io2->out_pf_callback().set(FUNC(ufo_state::ex_ufo800_lamps_w));
m_io2->out_pg_callback().set_nop();
} }
/*************************************************************************** /*******************************************************************************
ROM Definitions
Game drivers *******************************************************************************/
***************************************************************************/
ROM_START( newufo ) ROM_START( newufo )
ROM_REGION( 0x10000, "maincpu", 0 ) ROM_REGION( 0x10000, "maincpu", 0 )
@ -987,10 +981,18 @@ ROM_END
} // anonymous namespace } // anonymous namespace
/*******************************************************************************
Drivers
*******************************************************************************/
// YEAR NAME PARENT MACHINE INPUT CLASS INIT MNTR COMPANY, FULLNAME, FLAGS, LAYOUT
GAMEL( 1991, newufo, 0, newufo, newufo, ufo_state, empty_init, ROT0, "Sega", "New UFO Catcher (standard)", MACHINE_MECHANICAL | MACHINE_SUPPORTS_SAVE, layout_newufo ) GAMEL( 1991, newufo, 0, newufo, newufo, ufo_state, empty_init, ROT0, "Sega", "New UFO Catcher (standard)", MACHINE_MECHANICAL | MACHINE_SUPPORTS_SAVE, layout_newufo )
GAMEL( 1991, newufo_sonic, newufo, newufo, newufo, ufo_state, empty_init, ROT0, "Sega", "New UFO Catcher (Sonic The Hedgehog)", MACHINE_MECHANICAL | MACHINE_SUPPORTS_SAVE, layout_newufo ) GAMEL( 1991, newufo_sonic, newufo, newufo, newufo, ufo_state, empty_init, ROT0, "Sega", "New UFO Catcher (Sonic The Hedgehog)", MACHINE_MECHANICAL | MACHINE_SUPPORTS_SAVE, layout_newufo )
GAMEL( 1991, newufo_nfl, newufo, newufo, newufo, ufo_state, empty_init, ROT0, "Sega", "New UFO Catcher (Team NFL)", MACHINE_MECHANICAL | MACHINE_SUPPORTS_SAVE, layout_newufo ) GAMEL( 1991, newufo_nfl, newufo, newufo, newufo, ufo_state, empty_init, ROT0, "Sega", "New UFO Catcher (Team NFL)", MACHINE_MECHANICAL | MACHINE_SUPPORTS_SAVE, layout_newufo )
GAMEL( 1991, newufo_xmas, newufo, newufo, newufo, ufo_state, empty_init, ROT0, "Sega", "New UFO Catcher (Christmas season ROM kit)", MACHINE_MECHANICAL | MACHINE_SUPPORTS_SAVE, layout_newufo ) GAMEL( 1991, newufo_xmas, newufo, newufo, newufo, ufo_state, empty_init, ROT0, "Sega", "New UFO Catcher (Christmas season ROM kit)", MACHINE_MECHANICAL | MACHINE_SUPPORTS_SAVE, layout_newufo )
GAMEL( 1991, ufomini, 0, ufomini, ufomini, ufo_state, empty_init, ROT0, "Sega", "UFO Catcher Mini", MACHINE_MECHANICAL | MACHINE_SUPPORTS_SAVE, layout_ufomini ) GAMEL( 1991, ufomini, 0, ufomini, ufomini, ufo_state, empty_init, ROT0, "Sega", "UFO Catcher Mini", MACHINE_MECHANICAL | MACHINE_SUPPORTS_SAVE, layout_ufomini )
GAMEL( 1996, ufo21, 0, ufo21, ufo21, ufo_state, empty_init, ROT0, "Sega", "UFO Catcher 21", MACHINE_MECHANICAL | MACHINE_SUPPORTS_SAVE, layout_ufo21 ) GAMEL( 1996, ufo21, 0, ufo21, ufo21, ufo_state, empty_init, ROT0, "Sega", "UFO Catcher 21", MACHINE_MECHANICAL | MACHINE_SUPPORTS_SAVE, layout_ufo21 )
GAMEL( 1998, ufo800, 0, ufo800, ufo800, ufo_state, empty_init, ROT0, "Sega", "UFO Catcher 800", MACHINE_MECHANICAL | MACHINE_SUPPORTS_SAVE, layout_ufo800 ) GAMEL( 1998, ufo800, 0, ufo800, ufo800, ufo_state, empty_init, ROT0, "Sega", "UFO Catcher 800", MACHINE_MECHANICAL | MACHINE_SUPPORTS_SAVE, layout_ufo800 )