Partially rewrite uPD4701 device and hook it up to a few Sega games

This commit is contained in:
AJR 2017-05-21 01:31:52 -04:00
parent f09ba1e562
commit 02e787e3d3
6 changed files with 327 additions and 301 deletions

View File

@ -1,27 +1,38 @@
// license:BSD-3-Clause
// license:BSD-3-Clause,AJR
// copyright-holders:smf
/***************************************************************************
NEC uPD4701
Incremental Encoder Control
2009-06 Converted to be a device
NEC µPD4701A 2-Axis Incremental Encoder Counter
***************************************************************************/
#include "emu.h"
#include "upd4701.h"
#define MASK_SWITCHES ( 7 )
#define MASK_COUNTER ( 0xfff )
DEFINE_DEVICE_TYPE(UPD4701, upd4701_device, "upd4701", "uPD4701 Encoder")
DEFINE_DEVICE_TYPE(UPD4701A, upd4701_device, "upd4701a", "uPD4701A Incremental Encoder")
upd4701_device::upd4701_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, UPD4701, tag, owner, clock)
, m_cs(0), m_xy(0), m_ul(0), m_resetx(0), m_resety(0), m_latchx(0), m_latchy(0)
, m_startx(0), m_starty(0), m_x(0), m_y(0), m_switches(0), m_latchswitches(0), m_cf(0)
upd4701_device::upd4701_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, UPD4701A, tag, owner, clock)
, m_cs(true)
, m_xy(false)
, m_ul(false)
, m_resetx(false)
, m_resety(false)
, m_portx(*this, finder_base::DUMMY_TAG)
, m_porty(*this, finder_base::DUMMY_TAG)
, m_latchx(0)
, m_latchy(0)
, m_startx(0)
, m_starty(0)
, m_x(0)
, m_y(0)
, m_switches(0)
, m_latchswitches(0)
, m_cf(true)
, m_cf_cb(*this)
, m_sf_cb(*this)
{
}
@ -31,6 +42,11 @@ upd4701_device::upd4701_device(const machine_config &mconfig, const char *tag, d
void upd4701_device::device_start()
{
// resolve callbacks
m_cf_cb.resolve_safe();
m_sf_cb.resolve_safe();
// register state for saving
save_item(NAME(m_cs));
save_item(NAME(m_xy));
save_item(NAME(m_ul));
@ -45,54 +61,33 @@ void upd4701_device::device_start()
save_item(NAME(m_switches));
save_item(NAME(m_latchswitches));
save_item(NAME(m_cf));
// register special callback for analog inputs
if (m_portx.found() || m_porty.found())
machine().add_notifier(MACHINE_NOTIFY_FRAME, machine_notify_delegate(&upd4701_device::analog_update, this));
}
//-------------------------------------------------
// device_reset - device-specific reset
// ul_w - write to counter select line
//-------------------------------------------------
void upd4701_device::device_reset()
{
m_cs = 1;
m_xy = 0;
m_ul = 0;
m_resetx = 0;
m_resety = 0;
m_latchx = 0;
m_latchy = 0;
m_startx = 0;
m_starty = 0;
m_x = 0;
m_y = 0;
m_switches = 0;
m_latchswitches = 0;
m_cf = 1;
}
/* x,y increments can be 12bit (see MASK_COUNTER), hence we need a couple of
16bit handlers in the following */
/*-------------------------------------------------
ul_w
-------------------------------------------------*/
WRITE_LINE_MEMBER(upd4701_device::ul_w)
{
m_ul = state;
}
/*-------------------------------------------------
xy_w
-------------------------------------------------*/
//-------------------------------------------------
// xy_w - write to byte select line
//-------------------------------------------------
WRITE_LINE_MEMBER(upd4701_device::xy_w)
{
m_xy = state;
}
/*-------------------------------------------------
cs_w
-------------------------------------------------*/
//-------------------------------------------------
// cs_w - write to chip select line
//-------------------------------------------------
WRITE_LINE_MEMBER(upd4701_device::cs_w)
{
@ -105,20 +100,23 @@ WRITE_LINE_MEMBER( upd4701_device::cs_w )
m_latchx = (m_x - m_startx) & MASK_COUNTER;
m_latchy = (m_y - m_starty) & MASK_COUNTER;
m_latchswitches = (~m_switches) & MASK_SWITCHES;
if (m_latchswitches != 0)
{
m_latchswitches = m_switches;
if (m_switches != 0)
m_latchswitches |= 8;
}
m_cf = 1;
if (!m_cf)
{
// CF remains inactive while CS is low
m_cf = true;
m_cf_cb(1);
}
}
}
}
/*-------------------------------------------------
resetx_w
-------------------------------------------------*/
//-------------------------------------------------
// resetx_w - write to X counter reset line
//-------------------------------------------------
WRITE_LINE_MEMBER(upd4701_device::resetx_w)
{
@ -127,15 +125,13 @@ WRITE_LINE_MEMBER( upd4701_device::resetx_w )
m_resetx = state;
if (m_resetx)
{
m_startx = m_x;
}
}
}
/*-------------------------------------------------
resety_w
-------------------------------------------------*/
//-------------------------------------------------
// resety_w - write to Y counter reset line
//-------------------------------------------------
WRITE_LINE_MEMBER(upd4701_device::resety_w)
{
@ -144,106 +140,191 @@ WRITE_LINE_MEMBER( upd4701_device::resety_w )
m_resety = state;
if (m_resety)
{
m_starty = m_y;
}
}
//-------------------------------------------------
// reset_xy - pulse the counter reset lines
//-------------------------------------------------
WRITE8_MEMBER(upd4701_device::reset_xy)
{
resetx_w(1);
resety_w(1);
resetx_w(0);
resety_w(0);
}
/*-------------------------------------------------
x_add
-------------------------------------------------*/
//-------------------------------------------------
// analog_update - per-frame input update
//-------------------------------------------------
void upd4701_device::x_add( int16_t data )
void upd4701_device::analog_update()
{
if (m_portx.found())
x_add(m_portx->read() & MASK_COUNTER);
if (m_porty.found())
y_add(m_porty->read() & MASK_COUNTER);
}
//-------------------------------------------------
// x_add - count X-axis input
//-------------------------------------------------
void upd4701_device::x_add(s16 data)
{
if (!m_resetx && data != 0)
{
m_x += data;
if (m_cs)
if (m_cs && m_cf)
{
m_cf = 0;
m_cf = false;
m_cf_cb(0);
}
}
}
/*-------------------------------------------------
y_add
-------------------------------------------------*/
//-------------------------------------------------
// y_add - count Y-axis input
//-------------------------------------------------
void upd4701_device::y_add( int16_t data )
void upd4701_device::y_add(s16 data)
{
if (!m_resety && data != 0)
{
m_y += data;
if (m_cs && m_cf)
{
m_cf = false;
m_cf_cb(0);
}
}
}
//-------------------------------------------------
// switch_update - update one of three switches
//-------------------------------------------------
void upd4701_device::switch_update(u8 mask, bool state)
{
if (!state && (m_switches & mask) == 0)
{
// active low
m_switches |= mask;
// update SF output if other switches were not active
if ((m_switches & ~mask) == 0)
m_sf_cb(0);
}
else if (state && (m_switches & mask) == mask)
{
// inactive high
m_switches &= ~mask;
// update SF output if other switches are also inactive
if ((m_switches & ~mask) == 0)
m_sf_cb(1);
}
}
//-------------------------------------------------
// left_w - update left switch state
//-------------------------------------------------
WRITE_LINE_MEMBER(upd4701_device::left_w)
{
switch_update(4, state);
}
//-------------------------------------------------
// right_w - update right switch state
//-------------------------------------------------
WRITE_LINE_MEMBER(upd4701_device::right_w)
{
switch_update(2, state);
}
//-------------------------------------------------
// middle_w - update middle switch state
//-------------------------------------------------
WRITE_LINE_MEMBER(upd4701_device::middle_w)
{
switch_update(1, state);
}
//-------------------------------------------------
// d_r - read data lines directly
//-------------------------------------------------
READ8_MEMBER(upd4701_device::d_r)
{
if (m_cs)
{
m_cf = 0;
}
}
}
/*-------------------------------------------------
switches_set
-------------------------------------------------*/
void upd4701_device::switches_set( uint8_t data )
{
m_switches = data;
}
/*-------------------------------------------------
d_r
-------------------------------------------------*/
READ16_MEMBER( upd4701_device::d_r )
{
int data;
if (m_cs)
{
return 0xff;
}
if (m_xy)
{
data = m_latchy;
}
else
{
data = m_latchx;
logerror("Read while CS inactive\n");
return space.unmap();
}
u16 data = m_xy ? m_latchy : m_latchx;
data |= m_latchswitches << 12;
if (m_ul)
{
return data >> 8;
}
else
{
return data & 0xff;
}
//-------------------------------------------------
// read_x - read X axis through data/address bus
//-------------------------------------------------
READ8_MEMBER(upd4701_device::read_x)
{
return read_xy(space, (offset & 1) | 0);
}
/*-------------------------------------------------
sf_r
-------------------------------------------------*/
//-------------------------------------------------
// read_y - read Y axis through data/address bus
//-------------------------------------------------
READ8_MEMBER(upd4701_device::read_y)
{
return read_xy(space, (offset & 1) | 2);
}
//-------------------------------------------------
// read_xy - read either axis through bus
//-------------------------------------------------
READ8_MEMBER(upd4701_device::read_xy)
{
cs_w(0);
xy_w(BIT(offset, 1));
ul_w(BIT(offset, 0));
u8 result = d_r(space, 0);
cs_w(1);
return result;
}
//-------------------------------------------------
// sf_r - read switch flag
//-------------------------------------------------
READ_LINE_MEMBER(upd4701_device::sf_r)
{
if ((m_switches & MASK_SWITCHES) != MASK_SWITCHES)
{
if (m_switches != 0)
return 0;
}
return 1;
}
/*-------------------------------------------------
cf_r
-------------------------------------------------*/
//-------------------------------------------------
// cf_r - read counter flag
//-------------------------------------------------
READ_LINE_MEMBER(upd4701_device::cf_r)
{

View File

@ -1,10 +1,23 @@
// license:BSD-3-Clause
// copyright-holders:smf
// copyright-holders:smf,AJR
/***************************************************************************
NEC uPD4701
NEC µPD4701A 2-Axis Incremental Encoder Counter
Incremental Encoder Control
****************************************************************************
_____ _____
Xa 1 |* \_/ | 24 Vdd
Xb 2 | | 23 D7
RESET X 3 | | 22 D6
Ya 4 | | 21 D5
Yb 5 | uPD4701A | 20 D4
RESET Y 6 | | 19 D3
/RIGHT 7 | | 18 D2
/LEFT 8 | | 17 D1
/MIDDLE 9 | | 16 D0
/SF 10 | | 15 _CS
/CF 11 | | 14 _X/Y
Vss 12 |_____________| 13 U/_L
***************************************************************************/
@ -18,52 +31,86 @@
MACROS / CONSTANTS
***************************************************************************/
#define MCFG_UPD4701_PORTX(_tag) \
upd4701_device::set_portx_tag(*device, "^" _tag);
#define MCFG_UPD4701_PORTY(_tag) \
upd4701_device::set_porty_tag(*device, "^" _tag);
#define MCFG_UPD4701_CF_CALLBACK(_devcb) \
devcb = upd4701_device::set_cf_cb(*device, DEVCB_##_devcb);
#define MCFG_UPD4701_SF_CALLBACK(_devcb) \
devcb = upd4701_device::set_sf_cb(*device, DEVCB_##_devcb);
class upd4701_device : public device_t
{
public:
upd4701_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
upd4701_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
void x_add( int16_t data );
void y_add( int16_t data );
void switches_set( uint8_t data );
// static configuration
static void set_portx_tag(device_t &device, const char *tag) { downcast<upd4701_device &>(device).m_portx.set_tag(tag); }
static void set_porty_tag(device_t &device, const char *tag) { downcast<upd4701_device &>(device).m_porty.set_tag(tag); }
template<class Object>
static devcb_base &set_cf_cb(device_t &device, Object &&cb) { return downcast<upd4701_device &>(device).m_cf_cb.set_callback(std::forward<Object>(cb)); }
template<class Object>
static devcb_base &set_sf_cb(device_t &device, Object &&cb) { return downcast<upd4701_device &>(device).m_sf_cb.set_callback(std::forward<Object>(cb)); }
void x_add(s16 data);
void y_add(s16 data);
DECLARE_WRITE_LINE_MEMBER(cs_w);
DECLARE_WRITE_LINE_MEMBER(xy_w);
DECLARE_WRITE_LINE_MEMBER(ul_w);
DECLARE_WRITE_LINE_MEMBER(resetx_w);
DECLARE_WRITE_LINE_MEMBER(resety_w);
DECLARE_WRITE8_MEMBER(reset_xy);
DECLARE_READ8_MEMBER(d_r);
DECLARE_READ8_MEMBER(read_x);
DECLARE_READ8_MEMBER(read_y);
DECLARE_READ8_MEMBER(read_xy);
DECLARE_WRITE_LINE_MEMBER(left_w);
DECLARE_WRITE_LINE_MEMBER(right_w);
DECLARE_WRITE_LINE_MEMBER(middle_w);
DECLARE_READ16_MEMBER( d_r );
DECLARE_READ_LINE_MEMBER(cf_r);
DECLARE_READ_LINE_MEMBER(sf_r);
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
private:
// internal state
int m_cs;
int m_xy;
int m_ul;
int m_resetx;
int m_resety;
int m_latchx;
int m_latchy;
int m_startx;
int m_starty;
int m_x;
int m_y;
int m_switches;
int m_latchswitches;
int m_cf;
// internal helpers
void analog_update();
void switch_update(u8 mask, bool state);
// control lines
bool m_cs; // chip select (active low)
bool m_xy; // counter select (L = X, H = Y)
bool m_ul; // byte select (L = lower, H = upper)
bool m_resetx; // X-axis counter reset (active high)
bool m_resety; // Y-axis counter reset (active high)
// counter state
optional_ioport m_portx;
optional_ioport m_porty;
s16 m_latchx;
s16 m_latchy;
s16 m_startx;
s16 m_starty;
s16 m_x;
s16 m_y;
// switch state
u8 m_switches;
u8 m_latchswitches;
// flag outputs and callbacks
bool m_cf;
devcb_write_line m_cf_cb;
devcb_write_line m_sf_cb;
};
DECLARE_DEVICE_TYPE(UPD4701, upd4701_device)
#define MCFG_UPD4701_ADD(tag) \
MCFG_DEVICE_ADD((tag), UPD4701, 0)
DECLARE_DEVICE_TYPE(UPD4701A, upd4701_device)
#endif // MAME_MACHINE_UPD4701_H

View File

@ -392,8 +392,6 @@ public:
m_out2(*this, "OUT2" ),
m_cd(*this, "CD" ),
m_upd4701(*this, "upd4701" ),
m_upd4701_y(*this, "uPD4701_y" ),
m_upd4701_switches(*this, "uPD4701_switches" ),
m_stage(*this, "STAGE" ),
m_gunx(*this, "GUNX" ),
m_sensor(*this, "SENSOR" ),
@ -534,8 +532,6 @@ private:
required_ioport m_out2;
required_ioport m_cd;
optional_device<upd4701_device> m_upd4701;
optional_ioport m_upd4701_y;
optional_ioport m_upd4701_switches;
optional_ioport m_stage;
optional_ioport m_gunx;
optional_ioport m_sensor;
@ -842,38 +838,19 @@ todo:
READ16_MEMBER( ksys573_state::ge765pwbba_r )
{
uint32_t data = 0;
switch( offset )
{
case 0x4c:
case 0x4d:
m_upd4701->y_add( m_upd4701_y->read() );
m_upd4701->switches_set( m_upd4701_switches->read() );
m_upd4701->cs_w( 0 );
m_upd4701->xy_w( 1 );
if( offset == 0x4c )
{
m_upd4701->ul_w( 0 );
}
else
{
m_upd4701->ul_w( 1 );
}
data = m_upd4701->d_r( space, 0, 0xffff );
m_upd4701->cs_w( 1 );
break;
return m_upd4701->read_y(space, offset & 1);
default:
verboselog( 0, "ge765pwbba_r: unhandled offset %08x %08x\n", offset, mem_mask );
break;
}
verboselog( 2, "ge765pwbba_r( %08x, %08x ) %08x\n", offset, mem_mask, data );
return data;
verboselog( 2, "ge765pwbba_r( %08x, %08x )\n", offset, mem_mask );
return 0;
}
WRITE16_MEMBER( ksys573_state::ge765pwbba_w )
@ -2330,7 +2307,9 @@ static MACHINE_CONFIG_DERIVED( fbaitbc, konami573 )
MCFG_CPU_MODIFY( "maincpu" )
MCFG_CPU_PROGRAM_MAP( fbaitbc_map )
MCFG_UPD4701_ADD( "upd4701" )
MCFG_DEVICE_ADD("upd4701", UPD4701A, 0)
MCFG_UPD4701_PORTY("uPD4701_y")
MCFG_FRAGMENT_ADD( cassx )
MACHINE_CONFIG_END
@ -2528,9 +2507,9 @@ static INPUT_PORTS_START( fbaitbc )
PORT_BIT( 0x0fff, 0, IPT_MOUSE_Y ) PORT_MINMAX( 0, 0xfff ) PORT_SENSITIVITY( 15 ) PORT_KEYDELTA( 8 ) PORT_RESET
PORT_START( "uPD4701_switches" )
PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_PLAYER( 1 )
PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_PLAYER( 1 )
PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_PLAYER( 1 )
PORT_BIT( 0x1, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER("upd4701", upd4701_device, middle_w)
PORT_BIT( 0x2, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER("upd4701", upd4701_device, right_w)
PORT_BIT( 0x4, IP_ACTIVE_LOW, IPT_UNUSED ) PORT_PLAYER(1) PORT_WRITE_LINE_DEVICE_MEMBER("upd4701", upd4701_device, left_w)
INPUT_PORTS_END
static INPUT_PORTS_START( fbaitmc )

View File

@ -299,6 +299,7 @@ GND 8A 8B GND
#include "machine/i8255.h"
#include "machine/mc8123.h"
#include "machine/segacrp2_device.h"
#include "machine/upd4701.h"
#include "sound/sn76496.h"
#include "video/315_5124.h"
#include "speaker.h"
@ -324,8 +325,6 @@ public:
DECLARE_WRITE8_MEMBER(bank_write);
DECLARE_WRITE8_MEMBER(coin_counters_write);
DECLARE_READ8_MEMBER( ridleofp_port_f8_read );
DECLARE_WRITE8_MEMBER( ridleofp_port_fa_write );
DECLARE_READ8_MEMBER( hangonjr_port_f8_read );
DECLARE_WRITE8_MEMBER( hangonjr_port_fa_write );
@ -345,10 +344,6 @@ public:
// Analog input related
uint8_t m_port_select;
uint16_t m_last1;
uint16_t m_last2;
uint16_t m_diff1;
uint16_t m_diff2;
// Video RAM
uint8_t m_vram[2][0x4000 * 2];
@ -455,10 +450,6 @@ void systeme_state::machine_start()
}
save_item(NAME(m_port_select));
save_item(NAME(m_last1));
save_item(NAME(m_last2));
save_item(NAME(m_diff1));
save_item(NAME(m_diff2));
save_item(NAME(m_vram));
}
@ -485,41 +476,6 @@ WRITE8_MEMBER( systeme_state::hangonjr_port_fa_write)
m_port_select = data & 0x0f;
}
/*- Riddle of Pythagoras Specific -*/
READ8_MEMBER( systeme_state::ridleofp_port_f8_read )
{
switch (m_port_select)
{
default:
case 0: return m_diff1 & 0xff;
case 1: return m_diff1 >> 8;
case 2: return m_diff2 & 0xff;
case 3: return m_diff2 >> 8;
}
}
WRITE8_MEMBER( systeme_state::ridleofp_port_fa_write )
{
/* 0x10 is written before reading the dial (hold counters?) */
/* 0x03 is written after reading the dial (reset counters?) */
m_port_select = (data & 0x0c) >> 2;
if (data & 1)
{
int curr = ioport("IN2")->read();
m_diff1 = ((curr - m_last1) & 0x0fff) | (curr & 0xf000);
m_last1 = curr;
}
if (data & 2)
{
int curr = ioport("IN3")->read() & 0x0fff;
m_diff2 = ((curr - m_last2) & 0x0fff) | (curr & 0xf000);
m_last2 = curr;
}
}
/*******************************************************************************
Input Ports
@ -717,19 +673,16 @@ static INPUT_PORTS_START( segae_ridleofp_generic )
//PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED )
//PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("IN2") /* Read from Port 0xf8 */
PORT_BIT( 0x0fff, 0x0000, IPT_DIAL ) PORT_SENSITIVITY(60) PORT_KEYDELTA(125)
PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_BUTTON2 ) /* is this used in the game? */
PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_BUTTON1 )
PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_START("PAD1")
PORT_BIT( 0xfff, 0x000, IPT_DIAL ) PORT_SENSITIVITY(60) PORT_KEYDELTA(125) PORT_RESET
PORT_START("IN3") /* Read from Port 0xf8 */
PORT_BIT( 0x0fff, 0x0000, IPT_DIAL ) PORT_SENSITIVITY(60) PORT_KEYDELTA(125) PORT_COCKTAIL
PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_COCKTAIL
PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_COCKTAIL
PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_START("PAD2")
PORT_BIT( 0xfff, 0x000, IPT_DIAL ) PORT_SENSITIVITY(60) PORT_KEYDELTA(125) PORT_RESET PORT_COCKTAIL
PORT_START("BUTTONS")
PORT_BIT( 0x1, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_WRITE_LINE_DEVICE_MEMBER("upd4701", upd4701_device, middle_w) // is this used in the game?
PORT_BIT( 0x2, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_WRITE_LINE_DEVICE_MEMBER("upd4701", upd4701_device, right_w)
PORT_BIT( 0x4, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_WRITE_LINE_DEVICE_MEMBER("upd4701", upd4701_device, left_w)
INPUT_PORTS_END
@ -1044,9 +997,17 @@ static MACHINE_CONFIG_DERIVED( hangonjr, systeme )
MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( ridleofp, systeme )
MCFG_DEVICE_ADD("upd4701", UPD4701A, 0)
MCFG_UPD4701_PORTX("PAD1")
MCFG_UPD4701_PORTY("PAD2")
MCFG_DEVICE_MODIFY("ppi")
MCFG_I8255_IN_PORTA_CB(READ8(systeme_state, ridleofp_port_f8_read))
MCFG_I8255_OUT_PORTC_CB(WRITE8(systeme_state, ridleofp_port_fa_write))
MCFG_I8255_IN_PORTA_CB(DEVREAD8("upd4701", upd4701_device, d_r))
MCFG_I8255_OUT_PORTC_CB(DEVWRITELINE("upd4701", upd4701_device, cs_w)) MCFG_DEVCB_BIT(4)
MCFG_DEVCB_CHAIN_OUTPUT(DEVWRITELINE("upd4701", upd4701_device, xy_w)) MCFG_DEVCB_BIT(3)
MCFG_DEVCB_CHAIN_OUTPUT(DEVWRITELINE("upd4701", upd4701_device, ul_w)) MCFG_DEVCB_BIT(2)
MCFG_DEVCB_CHAIN_OUTPUT(DEVWRITELINE("upd4701", upd4701_device, resetx_w)) MCFG_DEVCB_BIT(1) // or possibly bit 0
MCFG_DEVCB_CHAIN_OUTPUT(DEVWRITELINE("upd4701", upd4701_device, resety_w)) MCFG_DEVCB_BIT(0) // or possibly bit 1
MACHINE_CONFIG_END

View File

@ -537,6 +537,7 @@ orunners: Interleaved with the dj and << >> buttons is the data the drives the
#include "machine/mb8421.h"
//#include "machine/mb89352.h"
#include "machine/msm6253.h"
#include "machine/upd4701.h"
#include "machine/315_5296.h"
#include "sound/2612intf.h"
#include "sound/rf5c68.h"
@ -903,56 +904,6 @@ WRITE_LINE_MEMBER(segas32_state::display_enable_1_w)
/*************************************
*
* I/O expansion range
*
*************************************/
/*************************************
*
* Game-specific custom I/O
*
*************************************/
READ8_MEMBER(segas32_trackball_state::sonic_custom_io_r)
{
switch (offset)
{
case 0x00/2:
case 0x04/2:
case 0x08/2:
case 0x0c/2:
case 0x10/2:
case 0x14/2:
return (uint8_t)(m_track_ports[offset/2]->read() - m_sonic_last[offset/2]);
}
logerror("%06X:unknown sonic_custom_io_r(%X) & %04X\n", space.device().safe_pc(), offset*2, mem_mask);
return 0xff;
}
WRITE8_MEMBER(segas32_trackball_state::sonic_custom_io_w)
{
switch (offset)
{
case 0x00/2:
case 0x08/2:
case 0x10/2:
m_sonic_last[offset/2 + 0] = m_track_ports[offset/2 + 0]->read();
m_sonic_last[offset/2 + 1] = m_track_ports[offset/2 + 1]->read();
return;
}
logerror("%06X:unknown sonic_custom_io_w(%X) = %04X & %04X\n", space.device().safe_pc(), offset*2, data, mem_mask);
}
/*************************************
*
* Random number generator
@ -2134,22 +2085,22 @@ static INPUT_PORTS_START( sonic )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START3 )
PORT_START("mainpcb:TRACKX1")
PORT_BIT( 0xff, 0, IPT_TRACKBALL_X ) PORT_SENSITIVITY(100) PORT_KEYDELTA(30) PORT_REVERSE PORT_PLAYER(1)
PORT_BIT( 0xfff, 0, IPT_TRACKBALL_X ) PORT_SENSITIVITY(100) PORT_KEYDELTA(30) PORT_RESET PORT_REVERSE PORT_PLAYER(1)
PORT_START("mainpcb:TRACKY1")
PORT_BIT( 0xff, 0, IPT_TRACKBALL_Y ) PORT_SENSITIVITY(100) PORT_KEYDELTA(30) PORT_PLAYER(1)
PORT_BIT( 0xfff, 0, IPT_TRACKBALL_Y ) PORT_SENSITIVITY(100) PORT_KEYDELTA(30) PORT_RESET PORT_PLAYER(1)
PORT_START("mainpcb:TRACKX2")
PORT_BIT( 0xff, 0, IPT_TRACKBALL_X ) PORT_SENSITIVITY(100) PORT_KEYDELTA(30) PORT_REVERSE PORT_PLAYER(2)
PORT_BIT( 0xfff, 0, IPT_TRACKBALL_X ) PORT_SENSITIVITY(100) PORT_KEYDELTA(30) PORT_RESET PORT_REVERSE PORT_PLAYER(2)
PORT_START("mainpcb:TRACKY2")
PORT_BIT( 0xff, 0, IPT_TRACKBALL_Y ) PORT_SENSITIVITY(100) PORT_KEYDELTA(30) PORT_PLAYER(2)
PORT_BIT( 0xfff, 0, IPT_TRACKBALL_Y ) PORT_SENSITIVITY(100) PORT_KEYDELTA(30) PORT_RESET PORT_PLAYER(2)
PORT_START("mainpcb:TRACKX3")
PORT_BIT( 0xff, 0, IPT_TRACKBALL_X ) PORT_SENSITIVITY(100) PORT_KEYDELTA(30) PORT_REVERSE PORT_PLAYER(3)
PORT_BIT( 0xfff, 0, IPT_TRACKBALL_X ) PORT_SENSITIVITY(100) PORT_KEYDELTA(30) PORT_RESET PORT_REVERSE PORT_PLAYER(3)
PORT_START("mainpcb:TRACKY3")
PORT_BIT( 0xff, 0, IPT_TRACKBALL_Y ) PORT_SENSITIVITY(100) PORT_KEYDELTA(30) PORT_PLAYER(3)
PORT_BIT( 0xfff, 0, IPT_TRACKBALL_Y ) PORT_SENSITIVITY(100) PORT_KEYDELTA(30) PORT_RESET PORT_PLAYER(3)
INPUT_PORTS_END
@ -2395,7 +2346,10 @@ machine_config_constructor segas32_analog_state::device_mconfig_additions() cons
static ADDRESS_MAP_START( system32_trackball_map, AS_PROGRAM, 16, segas32_trackball_state )
ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(0xc00040, 0xc0005f) AM_MIRROR(0x0fff80) AM_READWRITE8(sonic_custom_io_r, sonic_custom_io_w, 0x00ff)
//AM_RANGE(0xc00040, 0xc0005f) AM_MIRROR(0x0fff80) AM_READWRITE8(sonic_custom_io_r, sonic_custom_io_w, 0x00ff)
AM_RANGE(0xc00040, 0xc00047) AM_MIRROR(0x0fff80) AM_DEVREADWRITE8("upd1", upd4701_device, read_xy, reset_xy, 0x00ff)
AM_RANGE(0xc00048, 0xc0004f) AM_MIRROR(0x0fff80) AM_DEVREADWRITE8("upd2", upd4701_device, read_xy, reset_xy, 0x00ff)
AM_RANGE(0xc00050, 0xc00057) AM_MIRROR(0x0fff80) AM_DEVREADWRITE8("upd3", upd4701_device, read_xy, reset_xy, 0x00ff)
AM_IMPORT_FROM(system32_map)
ADDRESS_MAP_END
@ -2404,13 +2358,24 @@ static MACHINE_CONFIG_FRAGMENT( system32_trackball )
MCFG_DEVICE_MODIFY("maincpu")
MCFG_DEVICE_PROGRAM_MAP(system32_trackball_map)
MCFG_DEVICE_ADD("upd1", UPD4701A, 0)
MCFG_UPD4701_PORTX("TRACKX1")
MCFG_UPD4701_PORTY("TRACKY1")
MCFG_DEVICE_ADD("upd2", UPD4701A, 0)
MCFG_UPD4701_PORTX("TRACKX2")
MCFG_UPD4701_PORTY("TRACKY2")
MCFG_DEVICE_ADD("upd3", UPD4701A, 0)
MCFG_UPD4701_PORTX("TRACKX3")
MCFG_UPD4701_PORTY("TRACKY3")
MACHINE_CONFIG_END
DEFINE_DEVICE_TYPE(SEGA_S32_TRACKBALL_DEVICE, segas32_trackball_state, "segas32_pcb_trackball", "Sega System 32 trackball PCB")
segas32_trackball_state::segas32_trackball_state(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: segas32_state(mconfig, SEGA_S32_TRACKBALL_DEVICE, tag, owner, clock)
, m_track_ports(*this, {"TRACKX1", "TRACKY1", "TRACKX2", "TRACKY2", "TRACKX3", "TRACKY3"})
{
}

View File

@ -275,16 +275,9 @@ class segas32_trackball_state : public segas32_state
public:
segas32_trackball_state(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
DECLARE_READ8_MEMBER(sonic_custom_io_r);
DECLARE_WRITE8_MEMBER(sonic_custom_io_w);
protected:
virtual machine_config_constructor device_mconfig_additions() const override;
virtual void device_start() override;
private:
required_ioport_array<6> m_track_ports;
uint8_t m_sonic_last[6];
};
class segas32_4player_state : public segas32_state