From 97fb89fbe2045ea263f2d5cb8e85b62a881ae5a0 Mon Sep 17 00:00:00 2001 From: hap Date: Sun, 14 Jul 2024 14:20:24 +0200 Subject: segaufo: assume nmi enable is on IO2 CNT1, fix regression with debug popmessage, small cleanups, misc: update some notes --- src/mame/excalibur/ivant.cpp | 12 +- src/mame/layout/newufo.lay | 11 +- src/mame/layout/ufo21.lay | 16 +- src/mame/layout/ufo800.lay | 9 +- src/mame/layout/ufomini.lay | 9 +- src/mame/namco/cgang.cpp | 47 ++-- src/mame/novag/primo.cpp | 4 +- src/mame/novag/sapphire.cpp | 8 +- src/mame/sega/segaufo.cpp | 560 ++++++++++++++++++++++--------------------- 9 files changed, 328 insertions(+), 348 deletions(-) diff --git a/src/mame/excalibur/ivant.cpp b/src/mame/excalibur/ivant.cpp index 247f9a095ca..20a86d75ba2 100644 --- a/src/mame/excalibur/ivant.cpp +++ b/src/mame/excalibur/ivant.cpp @@ -8,14 +8,12 @@ Excalibur Igor (model 711E) 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 -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 has speech, and also sound effects that are reminiscent of Battle Chess. Hardware notes: - -Ivan The Terrible: - 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 - 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 - no LEDs, button sensors chessboard -Igor: -- PCB label: EXCALIBUR ELECTRONICS, INC. 510-1005A01, 5/28/97 IGOR -- Hitachi H8/3214 MCU, 12MHz XTAL -- sound ROM under epoxy 128KB instead of 1MB -- rest is same as Ivan +Igor is on the same base hardware. The PCB (label: EXCALIBUR ELECTRONICS, INC. +510-1005A01, 5/28/97 IGOR) looks a bit different, but the connections are the +same as Ivan. It has a H8/3214 MCU and the sound ROM is 128KB instead of 1MB. There's also a newer version of Igor from 2000 (model 711E-2) on much weaker hardware, it has a Samsung KS57C2308 MCU instead. diff --git a/src/mame/layout/newufo.lay b/src/mame/layout/newufo.lay index 7cb861a8f7e..8d955652254 100644 --- a/src/mame/layout/newufo.lay +++ b/src/mame/layout/newufo.lay @@ -128,8 +128,7 @@ authors:hap - - + @@ -162,9 +161,7 @@ authors:hap - - - + @@ -214,8 +211,7 @@ authors:hap - - + @@ -265,6 +261,5 @@ authors:hap - diff --git a/src/mame/layout/ufo21.lay b/src/mame/layout/ufo21.lay index a4e8470ee5f..dae829e7b8d 100644 --- a/src/mame/layout/ufo21.lay +++ b/src/mame/layout/ufo21.lay @@ -5,7 +5,6 @@ authors:hap --> - @@ -109,8 +108,7 @@ authors:hap - - + @@ -122,10 +120,10 @@ authors:hap - + - + @@ -143,9 +141,7 @@ authors:hap - - - + @@ -195,8 +191,7 @@ authors:hap - - + @@ -246,6 +241,5 @@ authors:hap - diff --git a/src/mame/layout/ufo800.lay b/src/mame/layout/ufo800.lay index 161e983faf4..ea3fedf7828 100644 --- a/src/mame/layout/ufo800.lay +++ b/src/mame/layout/ufo800.lay @@ -5,7 +5,6 @@ authors:hap --> - @@ -105,8 +104,7 @@ authors:hap - - + @@ -125,9 +123,7 @@ authors:hap - - - + @@ -174,6 +170,5 @@ authors:hap - diff --git a/src/mame/layout/ufomini.lay b/src/mame/layout/ufomini.lay index 5c7feb85c53..2460392428f 100644 --- a/src/mame/layout/ufomini.lay +++ b/src/mame/layout/ufomini.lay @@ -5,7 +5,6 @@ authors:hap --> - @@ -125,8 +124,7 @@ authors:hap - - + @@ -145,9 +143,7 @@ authors:hap - - - + @@ -197,6 +193,5 @@ authors:hap - diff --git a/src/mame/namco/cgang.cpp b/src/mame/namco/cgang.cpp index d5bb39e71bf..b5f4f070913 100644 --- a/src/mame/namco/cgang.cpp +++ b/src/mame/namco/cgang.cpp @@ -61,7 +61,6 @@ Overall, the hardware has similarities with Wacky Gator, see wacky_gator.cpp. #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" #include "sound/ymopm.h" @@ -115,7 +114,6 @@ public: m_cg_count(*this, "cg_count%u", 0U) { } - // machine configs void cgang(machine_config &config); protected: @@ -149,6 +147,23 @@ private: output_finder<5> m_en_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 void main_map(address_map &map); void sound_map(address_map &map); @@ -160,7 +175,7 @@ private: void main_firq_clear_w(u8 data); template void motor_clock_w(int state); void cg_motor_tick(int i); - TIMER_DEVICE_CALLBACK_MEMBER(door_motor_tick); + TIMER_CALLBACK_MEMBER(door_motor_tick); void refresh_motor_output(); u8 ppi1_b_r(); @@ -183,21 +198,6 @@ private: void ppi5_a_w(u8 data); void ppi5_b_w(u8 data); 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() @@ -205,6 +205,9 @@ void cgang_state::machine_start() for (int i = 0; i < 5; i++) 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 m_gun_lamps.resolve(); m_spot_lamps.resolve(); @@ -332,7 +335,7 @@ void cgang_state::cg_motor_tick(int i) 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) 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); - 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); m_digits->set_segmask(0x3ff, 0x7f); @@ -860,5 +861,5 @@ ROM_END Drivers *******************************************************************************/ -// YEAR NAME PARENT MACHINE INPUT CLASS INIT MONITOR 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 ) +// 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 ) diff --git a/src/mame/novag/primo.cpp b/src/mame/novag/primo.cpp index fe5433b6673..dbdf45169a6 100644 --- a/src/mame/novag/primo.cpp +++ b/src/mame/novag/primo.cpp @@ -10,8 +10,8 @@ properly. TODO: - 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 - rate differs a bit between host and client, m6801 serial emulation issue +- Novag Super System peripherals don't work on nsnova due to serial clock drift, + baud rate differs a bit between host and client, m6801 serial emulation issue - unmapped reads from 0x3c/0x3d (primo/supremo) or 0x33/0x34 (nsnova) - supremo unmapped writes to 0x2000/0x6000, always 0? - is the 1st version of supremo(black plastic) the same ROM? diff --git a/src/mame/novag/sapphire.cpp b/src/mame/novag/sapphire.cpp index bc37e8d02b8..e251a33fc1c 100644 --- a/src/mame/novag/sapphire.cpp +++ b/src/mame/novag/sapphire.cpp @@ -5,8 +5,8 @@ Novag Sapphire (model 9304) -It's the successor to Novag VIP / Super VIP, the chess engine is again by -David Kittinger. +Handheld chess computer. It's the successor to Novag Super VIP, whereas Ruby is +the successor to Novag VIP. The chess engine is by David Kittinger again. Hardware notes: - PCB label: 100168 REV A @@ -17,7 +17,9 @@ Hardware notes: - 24 buttons, piezo 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 adds some kind of auxillary autosave state feature at power-off diff --git a/src/mame/sega/segaufo.cpp b/src/mame/sega/segaufo.cpp index 90e8f20aa90..d5bc15f6150 100644 --- a/src/mame/sega/segaufo.cpp +++ b/src/mame/sega/segaufo.cpp @@ -1,46 +1,46 @@ // license:BSD-3-Clause // copyright-holders:hap -/*************************************************************************** - - Sega UFO Catcher, Z80 type hardware - The list underneath is not complete. A # before the name means it's not dumped yet. - - 1st gen - * ? - - # UFO Catcher (1985) - - 2nd gen: - * ? - - # UFO Catcher DX (1987) - - # UFO Catcher DX II (1987) - - 3rd gen - UFO brd - * Z80 (sticker obscures label), 16MHz XTAL, 2 Sega 315-5296(I/O), YM3438, NEC uPD71054C - - # Dream Town (1990) - - New UFO Catcher (1991) (2P) - probably the most popular cabinet of all UFO Catcher series - - UFO Catcher Mini (1991) (1P) - - # UFO Catcher Sega Sonic (1991) - - # School Kids (1993) - - 4th gen - EX brd - * Z80 Z0840008PSC, 8MHz XTAL, 32MHz XTAL, 2 Sega 315-5296(I/O), 315-5338A, YM3438, - NEC uPD71054C, optional NEC uPD7759C - - # Dream Palace (1992) - - # Dream Kitchen (1994) - - # UFO Catcher Excellent (1994) - - # UFO A La Carte (1996) - - UFO Catcher 21 (1996) (2P) - - UFO Catcher 800 (1998) (1P) - - # Baby UFO (1998) - - # Prize Sensor (1998) - - More games were released after 2000, assumed to be on more modern hardware. - - TODO: - - add dipswitches - - prize sensor for ufo21/ufo800 - -***************************************************************************/ +/******************************************************************************* + +Sega UFO Catcher, Z80 type hardware +The list underneath is not complete. A # before the name means it's not dumped yet. + +1st gen +* ? +- # UFO Catcher (1985) + +2nd gen: +* ? +- # UFO Catcher DX (1987) +- # UFO Catcher DX II (1987) + +3rd gen - UFO brd +* Z80 (sticker obscures label), 16MHz XTAL, 2 Sega 315-5296(I/O), YM3438, NEC uPD71054C +- # Dream Town (1990) +- New UFO Catcher (1991) (2P) - probably the most popular cabinet of all UFO Catcher series +- UFO Catcher Mini (1991) (1P) +- # UFO Catcher Sega Sonic (1991) +- # School Kids (1993) + +4th gen - EX brd +* Z80 Z0840008PSC, 8MHz XTAL, 32MHz XTAL, 2 Sega 315-5296(I/O), YM3438, NEC uPD71054C, + optional 315-5338A, optional NEC uPD7759C +- # Dream Palace (1992) +- # Dream Kitchen (1994) +- # UFO Catcher Excellent (1994) +- # UFO A La Carte (1996) (2P) +- UFO Catcher 21 (1996) (2P) +- UFO Catcher 800 (1998) (1P) +- # Baby UFO (1998) +- # Prize Sensor (1998) + +More games were released after 2000, assumed to be on more modern hardware. + +TODO: +- add dipswitches +- prize sensor for ufo21/ufo800 + +*******************************************************************************/ #include "emu.h" @@ -49,7 +49,6 @@ #include "cpu/z80/z80.h" #include "machine/pit8253.h" -#include "machine/timer.h" #include "sound/upd7759.h" #include "sound/ymopn.h" @@ -67,7 +66,8 @@ namespace { -/* simulation parameters */ +// simulation parameters + // x/y/z cabinet dimensions per player (motor range) #define CABINET_WIDTH 400 #define CABINET_DEPTH 400 @@ -81,83 +81,132 @@ namespace { #define CRANE_SIZE 350 - class ufo_state : public driver_device { public: ufo_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag), m_maincpu(*this, "maincpu"), - m_io1(*this, "io1"), - m_io2(*this, "io2"), + m_io(*this, "io%u", 1), m_upd(*this, "upd"), + m_inputs(*this, "IN%u", 1), m_counters(*this, "counter%u", 0U), m_digits(*this, "digit%u", 0U), m_lamps(*this, "lamp%u", 0U) { } + // machine configs void ufomini(machine_config &config); void ufo21(machine_config &config); void newufo(machine_config &config); void ufo800(machine_config &config); -private: - 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; +protected: virtual void machine_start() override; - TIMER_DEVICE_CALLBACK_MEMBER(simulate_xyz); - TIMER_DEVICE_CALLBACK_MEMBER(update_info); + virtual void machine_reset() override { m_nmi_enable = false; } - void ufo_map(address_map &map); - void ufo_portmap(address_map &map); - void ex_ufo21_portmap(address_map &map); - void ex_ufo800_portmap(address_map &map); +private: + // devices/pointers + required_device m_maincpu; + required_device_array m_io; + optional_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 Motor { - uint8_t running = 0; - uint8_t direction = 0; - float position = 0; - float speed = 0; + u8 running = 0; + u8 direction = 0; + float position = 0.5f; + float speed = 0.0f; } motor[4]; } m_player[2]; - uint8_t m_stepper = 0; + bool m_nmi_enable = false; + u8 m_stepper = 0; - required_device m_maincpu; - required_device m_io1; - required_device m_io2; - optional_device m_upd; - output_finder<2 * 4> m_counters; - output_finder<2> m_digits; - output_finder<28> m_lamps; + emu_timer *m_motor_timer; + + void init_motors(); + void motor_tick(int p, int m); + TIMER_CALLBACK_MEMBER(simulate_xyz); + + // 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 u8 crane_limits_r(); + void stepper_w(u8 data); + void cp_lamps_w(u8 data); + template void cp_digits_w(u8 data); + template void crane_xyz_w(u8 data); + void ufo_lamps_w(u8 data); + + template u8 ex_crane_limits_r(); + u8 ex_crane_open_r(); + void ex_stepper_w(u8 data); + void ex_cp_lamps_w(u8 data); + template 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) { @@ -174,16 +223,12 @@ void ufo_state::motor_tick(int p, int m) 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 m = 0; m < 3; m++) motor_tick(p, m); -} - -TIMER_DEVICE_CALLBACK_MEMBER(ufo_state::update_info) -{ // output ufo motor positions // 0 X: 000 = right, 100 = left (player 1) // 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 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 + // show io2 outputs std::ostringstream msg; - msg << std::hex << std::setfill('0'); 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()); #endif } -/*************************************************************************** - - I/O - -***************************************************************************/ +/******************************************************************************* + I/O +*******************************************************************************/ 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) { // NMI? - if (state) + if (state && m_nmi_enable) 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 +u8 ufo_state::crane_limits_r() { - int p = offset & 1; - uint8_t ret = 0x7f; + u8 ret = 0x7f; // d0: left limit sw (right 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 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 <= 0) << (m*2 + 1); + ret ^= (m_player[P].motor[m].position >= 1) << (m*2 + 0); + ret ^= (m_player[P].motor[m].position <= 0) << (m*2 + 1); } // 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; // d7: prize sensor (mirror?) - ret |= (ioport(p ? "IN2" : "IN1")->read() & 0x80); + ret |= m_inputs[P]->read() & 0x80; 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++) { @@ -271,12 +318,12 @@ void ufo_state::stepper_w(uint8_t data) // controlled with 4 output bits connected to a Toshiba TB6560AHQ motor driver. // 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, .. - static const uint8_t sequence[4] = + static const u8 sequence[4] = { 0x5, 0x9, 0xa, 0x6 }; // d0-d3: p1, d4-d7: p2 - uint8_t cur = data >> (p*4) & 0xf; - uint8_t prev = m_stepper >> (p*4) & 0xf; + u8 cur = data >> (p*4) & 0xf; + u8 prev = m_stepper >> (p*4) & 0xf; for (int i = 0; i < 4; i++) { @@ -297,7 +344,7 @@ void ufo_state::stepper_w(uint8_t 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 // other bits: ? @@ -305,35 +352,35 @@ void ufo_state::cp_lamps_w(uint8_t data) m_lamps[i] = BIT(~data, i); } -void ufo_state::cp_digits_w(offs_t offset, uint8_t data) +template +void ufo_state::cp_digits_w(u8 data) { - static constexpr uint8_t lut_7448[0x10] = - { 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7c,0x07,0x7f,0x67,0x58,0x4c,0x62,0x69,0x78,0x00 }; + static constexpr u8 lut_7448[0x10] = + { 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7c,0x07,0x7f,0x67,0x58,0x4c,0x62,0x69,0x78,0x00 }; // d0-d3: cpanel digit // 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 +void ufo_state::crane_xyz_w(u8 data) { - int p = offset & 1; - // d0: x/z axis (0:x, 1:z + halt x/y) // d1: x/z direction // d2: y direction // d3: x/z running // d4: y running // other bits: ? - m_player[p].motor[0].running = (data & 9) == 8; - m_player[p].motor[0].direction = data & 2; - m_player[p].motor[1].running = (data & 0x11) == 0x10; - m_player[p].motor[1].direction = data & 4; - m_player[p].motor[2].running = (data & 9) == 9; - m_player[p].motor[2].direction = data & 2; + m_player[P].motor[0].running = (data & 9) == 8; + m_player[P].motor[0].direction = data & 2; + m_player[P].motor[1].running = (data & 0x11) == 0x10; + m_player[P].motor[1].direction = data & 4; + m_player[P].motor[2].running = (data & 9) == 9; + 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) // 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 +u8 ufo_state::ex_crane_limits_r() { - int p = offset & 1; - uint8_t ret = 0xf0; + u8 ret = 0xf0; // d0: left 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++) { int shift = (m*2) + (m == 2); - 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 >= 1) << shift; + ret ^= (m_player[P].motor[m].position <= 0) << (shift+1); } return ret; } -uint8_t ufo_state::ex_crane_open_r() +u8 ufo_state::ex_crane_open_r() { // d0-d3: p1, d4-d7: p2 - uint8_t ret = 0xff; + u8 ret = 0xff; for (int p = 0; p < 2; p++) { @@ -396,16 +443,17 @@ uint8_t ufo_state::ex_crane_open_r() 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.. // 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)); } -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 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); } -void ufo_state::ex_crane_xyz_w(offs_t offset, uint8_t data) +template +void ufo_state::ex_crane_xyz_w(u8 data) { - int p = offset & 1; - // more straightforward setup than on UFO board hardware // d0: move left // 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++) { int bits = data >> (m*2) & 3; - 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].running = (bits == 1 || bits == 2) ? 1 : 0; + 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 // other bits: ? @@ -443,9 +490,10 @@ void ufo_state::ex_ufo800_lamps_w(uint8_t data) 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) // 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); } -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++) 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 // other bits: unused? m_upd->start_w(~data & 1); } -uint8_t ufo_state::ex_upd_busy_r() +u8 ufo_state::ex_upd_busy_r() { // d0: upd7759c busy // 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) { @@ -490,8 +541,8 @@ void ufo_state::ufo_portmap(address_map &map) map.global_mask(0xff); 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(0x80, 0xbf).rw(m_io1, 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(0x80, 0xbf).rw(m_io[0], 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) @@ -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)); } -void ufo_state::ex_ufo800_portmap(address_map &map) -{ - ufo_portmap(map); -// map(0x60, 0x67).noprw(); // unused? -// map(0x68, 0x68).nopw(); // ? -} - - -/*************************************************************************** - Inputs - -***************************************************************************/ +/******************************************************************************* + Input Ports +*******************************************************************************/ static INPUT_PORTS_START( newufo ) PORT_START("IN1") @@ -622,7 +664,8 @@ static INPUT_PORTS_START( newufo ) PORT_DIPSETTING( 0x08, "Setting 1" ) PORT_DIPSETTING( 0x00, "Setting 2" ) // 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( 0x00, DEF_STR( On ) ) // Manual states "Fanfare and CPanel Digit will not work though." PORT_DIPUNKNOWN( 0x20, IP_ACTIVE_LOW ) PORT_DIPLOCATION("SW2:6") @@ -782,92 +825,47 @@ INPUT_PORTS_END -/*************************************************************************** - - 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)); -} +/******************************************************************************* + Machine Configs +*******************************************************************************/ void ufo_state::newufo(machine_config &config) { - /* basic machine hardware */ - Z80(config, m_maincpu, XTAL(16'000'000)/2); + // basic machine hardware + Z80(config, m_maincpu, 16_MHz_XTAL/2); m_maincpu->set_addrmap(AS_PROGRAM, &ufo_state::ufo_map); 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)); - TIMER(config, "update_timer").configure_periodic(FUNC(ufo_state::update_info), attotime::from_hz(60)); - - SEGA_315_5296(config, m_io1, XTAL(16'000'000)); - // all ports set to input - m_io1->in_pa_callback().set(FUNC(ufo_state::crane_limits_r)); - m_io1->in_pb_callback().set(FUNC(ufo_state::crane_limits_r)); - m_io1->in_pe_callback().set_ioport("IN1"); - m_io1->in_pf_callback().set_ioport("DSW1"); - m_io1->in_pg_callback().set_ioport("DSW2"); - m_io1->in_ph_callback().set_ioport("IN2"); - - SEGA_315_5296(config, m_io2, XTAL(16'000'000)); - // all ports set to output - 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); + SEGA_315_5296(config, m_io[0], 16_MHz_XTAL); // all ports set to input + 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_io[1], 16_MHz_XTAL); // all ports set to output + m_io[1]->out_pa_callback().set(FUNC(ufo_state::stepper_w)); + m_io[1]->out_pb_callback().set(FUNC(ufo_state::cp_lamps_w)); + m_io[1]->out_pc_callback().set(FUNC(ufo_state::cp_digits_w<0>)); + m_io[1]->out_pd_callback().set(FUNC(ufo_state::cp_digits_w<1>)); + m_io[1]->out_pe_callback().set(FUNC(ufo_state::crane_xyz_w<0>)); + m_io[1]->out_pf_callback().set(FUNC(ufo_state::crane_xyz_w<1>)); + 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)); + + pit8254_device &pit(PIT8254(config, "pit", 16_MHz_XTAL/2)); // uPD71054C, configuration is unknown + pit.set_clk<0>(16_MHz_XTAL/2/256); 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.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)); - /* no video! */ - - /* sound hardware */ + // sound hardware 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.add_route(0, "mono", 0.40); ym.add_route(1, "mono", 0.40); @@ -877,10 +875,10 @@ void ufo_state::ufomini(machine_config &config) { newufo(config); - /* basic machine hardware */ - m_io1->in_pc_callback().set_ioport("IN1"); - m_io1->in_pe_callback().set_constant(0); - m_io1->in_ph_callback().set_constant(0); + // basic machine hardware + m_io[0]->in_pc_callback().set_ioport("IN1"); + m_io[0]->in_pe_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); - /* basic machine hardware */ + // basic machine hardware 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_io1->in_pb_callback().set(FUNC(ufo_state::ex_crane_limits_r)); - m_io1->in_pc_callback().set(FUNC(ufo_state::ex_crane_open_r)); + m_io[0]->in_pa_callback().set(FUNC(ufo_state::ex_crane_limits_r<0>)); + m_io[0]->in_pb_callback().set(FUNC(ufo_state::ex_crane_limits_r<1>)); + 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_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_crane_xyz_w)); - m_io2->out_pg_callback().set_nop(); + m_io[1]->out_pa_callback().set(FUNC(ufo_state::ex_stepper_w)); + m_io[1]->out_pb_callback().set(FUNC(ufo_state::ex_cp_lamps_w)); + m_io[1]->out_pe_callback().set(FUNC(ufo_state::ex_crane_xyz_w<0>)); + m_io[1]->out_pf_callback().set(FUNC(ufo_state::ex_crane_xyz_w<1>)); + m_io[1]->out_pg_callback().set_nop(); sega_315_5338a_device &io3(SEGA_315_5338A(config, "io3", 0)); 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_pf_callback().set(FUNC(ufo_state::ex_ufo21_lamps2_w)); - /* sound hardware */ + // sound hardware UPD7759(config, m_upd); m_upd->add_route(ALL_OUTPUTS, "mono", 0.75); } @@ -916,30 +914,26 @@ void ufo_state::ufo800(machine_config &config) { newufo(config); - /* basic machine hardware */ - m_maincpu->set_addrmap(AS_IO, &ufo_state::ex_ufo800_portmap); - - m_io1->in_pa_callback().set(FUNC(ufo_state::ex_crane_limits_r)); - m_io1->in_pb_callback().set_ioport("IN2"); - m_io1->in_pc_callback().set(FUNC(ufo_state::ex_crane_open_r)); - m_io1->in_pd_callback().set_ioport("IN1"); - m_io1->in_pe_callback().set_constant(0); - 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(); -} - + // basic machine hardware + 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_io[1]->out_pa_callback().set(FUNC(ufo_state::ex_stepper_w)); + m_io[1]->out_pb_callback().set(FUNC(ufo_state::ex_cp_lamps_w)); + m_io[1]->out_pe_callback().set(FUNC(ufo_state::ex_crane_xyz_w<0>)); + m_io[1]->out_pf_callback().set(FUNC(ufo_state::ex_ufo800_lamps_w)); + m_io[1]->out_pg_callback().set_nop(); +} -/*************************************************************************** - Game drivers -***************************************************************************/ +/******************************************************************************* + ROM Definitions +*******************************************************************************/ ROM_START( newufo ) ROM_REGION( 0x10000, "maincpu", 0 ) @@ -987,10 +981,18 @@ ROM_END } // 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_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_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( 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 ) -- cgit v1.2.3