added 315-5296 device

This commit is contained in:
Michaël Banaan Ananas 2014-10-09 23:39:27 +00:00
parent e9aea92d1a
commit 1cdd1948ee
8 changed files with 420 additions and 172 deletions

2
.gitattributes vendored
View File

@ -6865,6 +6865,8 @@ src/mame/layout/wpc_an.lay svneol=native#text/xml
src/mame/layout/zac_1.lay svneol=native#text/xml
src/mame/layout/zac_2.lay svneol=native#text/xml
src/mame/layout/zac_proto.lay svneol=native#text/xml
src/mame/machine/315-5296.c svneol=native#text/plain
src/mame/machine/315-5296.h svneol=native#text/plain
src/mame/machine/3do.c svneol=native#text/plain
src/mame/machine/acitya.c svneol=native#text/plain
src/mame/machine/ajax.c svneol=native#text/plain

View File

@ -38,9 +38,9 @@ void fifo7200_device::device_start()
m_buffer.resize(m_ram_size);
// resolve callbacks
m_ef_handler.resolve();
m_ff_handler.resolve();
m_hf_handler.resolve();
m_ef_handler.resolve_safe();
m_ff_handler.resolve_safe();
m_hf_handler.resolve_safe();
// state save
save_item(NAME(m_read_ptr));
@ -65,9 +65,9 @@ void fifo7200_device::device_reset()
m_ff = 0;
m_hf = 0;
if (!m_ef_handler.isnull()) m_ef_handler(!m_ef);
if (!m_ff_handler.isnull()) m_ff_handler(!m_ff);
if (!m_hf_handler.isnull()) m_hf_handler(!m_hf);
m_ef_handler(!m_ef);
m_ff_handler(!m_ff);
m_hf_handler(!m_hf);
}
@ -87,19 +87,19 @@ void fifo7200_device::fifo_write(UINT16 data)
if (m_ef)
{
m_ef = 0;
if (!m_ef_handler.isnull()) m_ef_handler(!m_ef);
m_ef_handler(!m_ef);
}
else if (m_read_ptr == m_write_ptr)
{
m_ff = 1;
if (!m_ff_handler.isnull()) m_ff_handler(!m_ff);
m_ff_handler(!m_ff);
}
else if (((m_read_ptr + 1 + m_ram_size / 2) % m_ram_size) == m_write_ptr)
{
m_hf = 1;
if (!m_hf_handler.isnull()) m_hf_handler(!m_hf);
m_hf_handler(!m_hf);
}
}
@ -118,19 +118,19 @@ UINT16 fifo7200_device::fifo_read()
if (m_ff)
{
m_ff = 0;
if (!m_ff_handler.isnull()) m_ff_handler(!m_ff);
m_ff_handler(!m_ff);
}
else if (m_read_ptr == m_write_ptr)
{
m_ef = 1;
if (!m_ef_handler.isnull()) m_ef_handler(!m_ef);
m_ef_handler(!m_ef);
}
else if (((m_read_ptr + m_ram_size / 2) % m_ram_size) == m_write_ptr)
{
m_hf = 0;
if (!m_hf_handler.isnull()) m_hf_handler(!m_hf);
m_hf_handler(!m_hf);
}
return ret;

View File

@ -736,11 +736,11 @@ void upd775x_device::postload()
*************************************************************/
void upd775x_device::reset_w(UINT8 data)
WRITE_LINE_MEMBER( upd775x_device::reset_w )
{
/* update the reset value */
UINT8 oldreset = m_reset;
m_reset = (data != 0);
m_reset = (state != 0);
/* update the stream first */
m_channel->update();
@ -750,11 +750,11 @@ void upd775x_device::reset_w(UINT8 data)
device_reset();
}
void upd7759_device::start_w(UINT8 data)
WRITE_LINE_MEMBER( upd7759_device::start_w )
{
/* update the start value */
UINT8 oldstart = m_start;
m_start = (data != 0);
m_start = (state != 0);
logerror("upd7759_start_w: %d->%d\n", oldstart, m_start);
@ -772,11 +772,11 @@ void upd7759_device::start_w(UINT8 data)
}
}
void upd7756_device::start_w(UINT8 data)
WRITE_LINE_MEMBER( upd7756_device::start_w )
{
/* update the start value */
UINT8 oldstart = m_start;
m_start = (data != 0);
m_start = (state != 0);
logerror("upd7759_start_w: %d->%d\n", oldstart, m_start);
@ -798,7 +798,7 @@ WRITE8_MEMBER( upd775x_device::port_w )
}
int upd775x_device::busy_r()
READ_LINE_MEMBER( upd775x_device::busy_r )
{
/* return /BUSY */
return (m_state == STATE_IDLE);

View File

@ -25,8 +25,8 @@ public:
void set_bank_base(offs_t base);
void reset_w(UINT8 data);
int busy_r();
DECLARE_WRITE_LINE_MEMBER( reset_w );
DECLARE_READ_LINE_MEMBER( busy_r );
DECLARE_WRITE8_MEMBER( port_w );
void postload();
@ -93,9 +93,9 @@ public:
upd7759_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
enum
{
TIMER_SLAVE_UPDATE
};
{
TIMER_SLAVE_UPDATE
};
virtual void device_start();
virtual void device_reset();
@ -104,7 +104,7 @@ public:
emu_timer *m_timer; /* timer */
void start_w(UINT8 data);
DECLARE_WRITE_LINE_MEMBER( start_w );
};
class upd7756_device : public upd775x_device
@ -116,7 +116,7 @@ public:
virtual void device_reset();
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
void start_w(UINT8 data);
DECLARE_WRITE_LINE_MEMBER( start_w );
};
extern const device_type UPD7759;

View File

@ -70,6 +70,7 @@
#include "emu.h"
#include "cpu/m68000/m68000.h"
#include "machine/nvram.h"
#include "machine/315-5296.h"
#include "sound/okim6295.h"
#include "sound/sn76496.h"
#include "sound/2612intf.h"
@ -162,11 +163,13 @@ public:
DECLARE_WRITE_LINE_MEMBER(vdp_lv6irqline_callback_c2);
DECLARE_WRITE_LINE_MEMBER(vdp_lv4irqline_callback_c2);
DECLARE_READ8_MEMBER(io_portc_r);
DECLARE_WRITE8_MEMBER(io_portd_w);
DECLARE_WRITE8_MEMBER(io_porth_w);
DECLARE_WRITE16_MEMBER( segac2_upd7759_w );
DECLARE_READ16_MEMBER( palette_r );
DECLARE_WRITE16_MEMBER( palette_w );
DECLARE_READ16_MEMBER( io_chip_r );
DECLARE_WRITE16_MEMBER( io_chip_w );
DECLARE_WRITE16_MEMBER( control_w );
DECLARE_READ16_MEMBER( prot_r );
DECLARE_WRITE16_MEMBER( prot_w );
@ -201,7 +204,6 @@ public:
int prot_func_pclubjv2(int in);
int prot_func_pclubjv4(int in);
int prot_func_pclubjv5(int in);
};
@ -255,7 +257,6 @@ MACHINE_RESET_MEMBER(segac2_state,segac2)
m_sp_palbase = 0;
recompute_palette_tables();
}
@ -273,10 +274,10 @@ MACHINE_RESET_MEMBER(segac2_state,segac2)
******************************************************************************/
/* handle writes to the UPD7759 */
WRITE16_MEMBER(segac2_state::segac2_upd7759_w )
WRITE16_MEMBER(segac2_state::segac2_upd7759_w)
{
/* make sure we have a UPD chip */
if (!m_sound_banks)
if (m_upd7759 == NULL)
return;
/* only works if we're accessing the low byte */
@ -307,7 +308,7 @@ WRITE16_MEMBER(segac2_state::segac2_upd7759_w )
******************************************************************************/
/* handle reads from the paletteram */
READ16_MEMBER(segac2_state::palette_r )
READ16_MEMBER(segac2_state::palette_r)
{
offset &= 0x1ff;
if (m_segac2_alt_palette_mode)
@ -317,7 +318,7 @@ READ16_MEMBER(segac2_state::palette_r )
}
/* handle writes to the paletteram */
WRITE16_MEMBER(segac2_state::palette_w )
WRITE16_MEMBER(segac2_state::palette_w)
{
int r, g, b, newword;
int tmpr, tmpg, tmpb;
@ -403,143 +404,63 @@ void segac2_state::recompute_palette_tables()
m_segac2_sp_pal_lookup[i] = 0x200 * m_palbank + ((~sppal << 2) & 0x100) + ((sppal << 2) & 0x80) + ((~sppal >> 2) & 0x40) + ((sppal >> 2) & 0x20) + (sppal & 0x10);
}
}
}
/******************************************************************************
I/O Read & Write Handlers
*******************************************************************************
Controls, and Poto Poto reads 'S' 'E' 'G' and 'A' (SEGA) from this area
as a form of protection.
Lots of unknown writes however offset 0E certainly seems to be banking,
both colours and sound sample banks.
Sega 315-5296 I/O chip
******************************************************************************/
READ16_MEMBER(segac2_state::io_chip_r )
READ8_MEMBER(segac2_state::io_portc_r)
{
static const char *const portnames[] = { "P1", "P2", "PORTC", "PORTD", "SERVICE", "COINAGE", "DSW", "PORTH" };
offset &= 0x1f/2;
switch (offset)
{
/* I/O ports */
case 0x00/2:
case 0x02/2:
case 0x04/2:
case 0x06/2:
case 0x08/2:
case 0x0a/2:
case 0x0c/2:
case 0x0e/2:
/* if the port is configured as an output, return the last thing written */
if (m_misc_io_data[0x1e/2] & (1 << offset))
return m_misc_io_data[offset];
/* otherwise, return an input port */
if (offset == 0x04/2 && m_sound_banks)
return (ioport(portnames[offset])->read() & 0xbf) | (m_upd7759->busy_r() << 6);
return ioport(portnames[offset])->read();
/* 'SEGA' protection */
case 0x10/2:
return 'S';
case 0x12/2:
return 'E';
case 0x14/2:
return 'G';
case 0x16/2:
return 'A';
/* CNT register & mirror */
case 0x18/2:
case 0x1c/2:
return m_misc_io_data[0x1c/2];
/* port direction register & mirror */
case 0x1a/2:
case 0x1e/2:
return m_misc_io_data[0x1e/2];
}
return 0xffff;
// D7 : From MB3773P pin 1. (/RESET output)
// D6 : From uPD7759 pin 18. (/BUSY output)
int busy = (m_upd7759 != NULL) ? (m_upd7759->busy_r() << 6) : 0x40;
return 0xbf | busy;
}
WRITE16_MEMBER(segac2_state::io_chip_w )
WRITE8_MEMBER(segac2_state::io_portd_w)
{
UINT8 newbank;
// UINT8 old;
/*
D7 : To pin 3 of JP15. (Watchdog clock control)
D6 : To MUTE input pin on TDA1518BQ amplifier.
D5 : To CN2 pin 10. (Unknown purpose)
D4 : To CN2 pin 11. (Unknown purpose)
D3 : To CN1 pin K. (Coin lockout 2)
D2 : To CN1 pin 9. (Coin lockout 1)
D1 : To CN1 pin J. (Coin meter 2)
D0 : To CN1 pin 8. (Coin meter 1)
*/
//coin_lockout_w(space.machine(), 1, data & 0x08);
//coin_lockout_w(space.machine(), 0, data & 0x04);
coin_counter_w(space.machine(), 1, data & 0x02);
coin_counter_w(space.machine(), 0, data & 0x01);
}
/* generic implementation */
offset &= 0x1f/2;
// old = m_misc_io_data[offset];
m_misc_io_data[offset] = data;
switch (offset)
WRITE8_MEMBER(segac2_state::io_porth_w)
{
/*
D7 : To pin A19 of CN4
D6 : To pin B19 of CN4
D5 : ?
D4 : ?
D3 : To pin 31 of uPD7759 sample ROM (A18 on a 27C040)
D2 : To pin 30 of uPD7759 sample ROM (A17 on a 27C040)
D1 : To A10 of color RAM
D0 : To A9 of color RAM
*/
int newbank = data & 3;
if (newbank != m_palbank)
{
/* I/O ports */
case 0x00/2:
case 0x02/2:
case 0x04/2:
case 0x08/2:
case 0x0a/2:
case 0x0c/2:
break;
/* miscellaneous output */
case 0x06/2:
/*
D7 : To pin 3 of JP15. (Watchdog clock control)
D6 : To MUTE input pin on TDA1518BQ amplifier.
D5 : To CN2 pin 10. (Unknown purpose)
D4 : To CN2 pin 11. (Unknown purpose)
D3 : To CN1 pin K. (Coin lockout 2)
D2 : To CN1 pin 9. (Coin lockout 1)
D1 : To CN1 pin J. (Coin meter 2)
D0 : To CN1 pin 8. (Coin meter 1)
*/
/* coin_lockout_w(space.machine(), 1, data & 0x08);
coin_lockout_w(space.machine(), 0, data & 0x04); */
coin_counter_w(space.machine(), 1, data & 0x02);
coin_counter_w(space.machine(), 0, data & 0x01);
break;
/* banking */
case 0x0e/2:
/*
D7 : To pin A19 of CN4
D6 : To pin B19 of CN4
D5 : ?
D4 : ?
D3 : To pin 31 of uPD7759 sample ROM (A18 on a 27C040)
D2 : To pin 30 of uPD7759 sample ROM (A17 on a 27C040)
D1 : To A10 of color RAM
D0 : To A9 of color RAM
*/
newbank = data & 3;
if (newbank != m_palbank)
{
//m_screen->update_partial(m_screen->vpos() + 1);
m_palbank = newbank;
recompute_palette_tables();
}
if (m_sound_banks > 1)
{
newbank = (data >> 2) & (m_sound_banks - 1);
m_upd7759->set_bank_base(newbank * 0x20000);
}
break;
/* CNT register */
case 0x1c/2:
if (m_sound_banks > 1)
{
m_upd7759->reset_w((data >> 1) & 1);
}
break;
//m_screen->update_partial(m_screen->vpos() + 1);
m_palbank = newbank;
recompute_palette_tables();
}
if (m_sound_banks > 1)
{
newbank = (data >> 2) & (m_sound_banks - 1);
m_upd7759->set_bank_base(newbank * 0x20000);
}
}
@ -713,7 +634,7 @@ static ADDRESS_MAP_START( main_map, AS_PROGRAM, 16, segac2_state )
AM_RANGE(0x000000, 0x1fffff) AM_ROM
AM_RANGE(0x800000, 0x800001) AM_MIRROR(0x13fdfe) AM_READWRITE(prot_r, prot_w)
AM_RANGE(0x800200, 0x800201) AM_MIRROR(0x13fdfe) AM_WRITE(control_w)
AM_RANGE(0x840000, 0x84001f) AM_MIRROR(0x13fee0) AM_READWRITE(io_chip_r, io_chip_w)
AM_RANGE(0x840000, 0x84001f) AM_MIRROR(0x13fee0) AM_DEVREADWRITE8("io", sega_315_5296_device, read, write, 0x00ff)
AM_RANGE(0x840100, 0x840107) AM_MIRROR(0x13fef8) AM_DEVREADWRITE8("ymsnd", ym3438_device, read, write, 0x00ff)
AM_RANGE(0x880100, 0x880101) AM_MIRROR(0x13fefe) AM_WRITE(counter_timer_w)
AM_RANGE(0x8c0000, 0x8c0fff) AM_MIRROR(0x13f000) AM_READWRITE(palette_r, palette_w) AM_SHARE("paletteram")
@ -758,14 +679,6 @@ static INPUT_PORTS_START( systemc_generic )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2)
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2)
PORT_START("PORTC")
PORT_BIT( 0x3f, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_SPECIAL ) /* From uPD7759 pin 18. (/BUSY output) */
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_SPECIAL ) /* From MB3773P pin 1. (/RESET output) */
PORT_START("PORTD")
PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("SERVICE")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 )
@ -788,9 +701,6 @@ static INPUT_PORTS_START( systemc_generic )
PORT_DIPUNUSED_DIPLOC( 0x20, IP_ACTIVE_LOW, "SW2:6" )
PORT_DIPUNUSED_DIPLOC( 0x40, IP_ACTIVE_LOW, "SW2:7" )
PORT_DIPUNUSED_DIPLOC( 0x80, IP_ACTIVE_LOW, "SW2:8" )
PORT_START("PORTH")
PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
INPUT_PORTS_END
@ -1465,6 +1375,17 @@ static MACHINE_CONFIG_START( segac, segac2_state )
MCFG_MACHINE_RESET_OVERRIDE(segac2_state,segac2)
MCFG_NVRAM_ADD_1FILL("nvram") // borencha requires 0xff fill or there is no sound (it lacks some of the init code of the borench set)
MCFG_DEVICE_ADD("io", SEGA_315_5296, 0)
MCFG_315_5296_IN_PORTA_CB(IOPORT("P1"))
MCFG_315_5296_IN_PORTB_CB(IOPORT("P2"))
MCFG_315_5296_IN_PORTC_CB(READ8(segac2_state, io_portc_r))
MCFG_315_5296_OUT_PORTD_CB(WRITE8(segac2_state, io_portd_w))
MCFG_315_5296_IN_PORTE_CB(IOPORT("SERVICE"))
MCFG_315_5296_IN_PORTF_CB(IOPORT("COINAGE"))
MCFG_315_5296_IN_PORTG_CB(IOPORT("DSW"))
MCFG_315_5296_OUT_PORTH_CB(WRITE8(segac2_state, io_porth_w))
/* video hardware */
MCFG_DEVICE_ADD("gen_vdp", SEGA315_5313, 0)
MCFG_SEGA315_5313_IS_PAL(false)
MCFG_SEGA315_5313_SND_IRQ_CALLBACK(WRITELINE(segac2_state, vdp_sndirqline_callback_c2));
@ -1475,7 +1396,6 @@ static MACHINE_CONFIG_START( segac, segac2_state )
MCFG_TIMER_DEVICE_ADD_SCANLINE("scantimer", "gen_vdp", sega315_5313_device, megadriv_scanline_timer_callback_alt_timing, "megadriv", 0, 1)
MCFG_SCREEN_ADD("megadriv", RASTER)
MCFG_SCREEN_REFRESH_RATE(60)
MCFG_SCREEN_SIZE(512, 262)
@ -1503,6 +1423,8 @@ MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( segac2, segac )
/* basic machine hardware */
MCFG_DEVICE_MODIFY("io")
MCFG_315_5296_OUT_CNT1_CB(DEVWRITELINE("upd", upd7759_device, reset_w))
/* sound hardware */
MCFG_SOUND_ADD("upd", UPD7759, XL1_CLOCK)

178
src/mame/machine/315-5296.c Normal file
View File

@ -0,0 +1,178 @@
/**********************************************************************
Sega 315-5296 I/O chip
Sega 100-pin QFP, with 8 bidirectional I/O ports, and 3 output pins.
Commonly used from the late 80s up until Sega Model 2.
**********************************************************************/
#include "machine/315-5296.h"
const device_type SEGA_315_5296 = &device_creator<sega_315_5296_device>;
//-------------------------------------------------
// sega_315_5296_device - constructor
//-------------------------------------------------
sega_315_5296_device::sega_315_5296_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, SEGA_315_5296, "Sega 315-5296", tag, owner, clock, "315-5296", __FILE__),
m_in_pa_cb(*this),
m_in_pb_cb(*this),
m_in_pc_cb(*this),
m_in_pd_cb(*this),
m_in_pe_cb(*this),
m_in_pf_cb(*this),
m_in_pg_cb(*this),
m_in_ph_cb(*this),
m_out_pa_cb(*this),
m_out_pb_cb(*this),
m_out_pc_cb(*this),
m_out_pd_cb(*this),
m_out_pe_cb(*this),
m_out_pf_cb(*this),
m_out_pg_cb(*this),
m_out_ph_cb(*this),
m_out_cnt0_cb(*this),
m_out_cnt1_cb(*this),
m_out_cnt2_cb(*this)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void sega_315_5296_device::device_start()
{
// resolve callbacks
m_in_pa_cb.resolve_safe(0xff); m_in_port_cb[0] = &m_in_pa_cb;
m_in_pb_cb.resolve_safe(0xff); m_in_port_cb[1] = &m_in_pb_cb;
m_in_pc_cb.resolve_safe(0xff); m_in_port_cb[2] = &m_in_pc_cb;
m_in_pd_cb.resolve_safe(0xff); m_in_port_cb[3] = &m_in_pd_cb;
m_in_pe_cb.resolve_safe(0xff); m_in_port_cb[4] = &m_in_pe_cb;
m_in_pf_cb.resolve_safe(0xff); m_in_port_cb[5] = &m_in_pf_cb;
m_in_pg_cb.resolve_safe(0xff); m_in_port_cb[6] = &m_in_pg_cb;
m_in_ph_cb.resolve_safe(0xff); m_in_port_cb[7] = &m_in_ph_cb;
m_out_pa_cb.resolve_safe(); m_out_port_cb[0] = &m_out_pa_cb;
m_out_pb_cb.resolve_safe(); m_out_port_cb[1] = &m_out_pb_cb;
m_out_pc_cb.resolve_safe(); m_out_port_cb[2] = &m_out_pc_cb;
m_out_pd_cb.resolve_safe(); m_out_port_cb[3] = &m_out_pd_cb;
m_out_pe_cb.resolve_safe(); m_out_port_cb[4] = &m_out_pe_cb;
m_out_pf_cb.resolve_safe(); m_out_port_cb[5] = &m_out_pf_cb;
m_out_pg_cb.resolve_safe(); m_out_port_cb[6] = &m_out_pg_cb;
m_out_ph_cb.resolve_safe(); m_out_port_cb[7] = &m_out_ph_cb;
m_out_cnt0_cb.resolve_safe(); m_out_cnt_cb[0] = &m_out_cnt0_cb;
m_out_cnt1_cb.resolve_safe(); m_out_cnt_cb[1] = &m_out_cnt1_cb;
m_out_cnt2_cb.resolve_safe(); m_out_cnt_cb[2] = &m_out_cnt2_cb;
// register for savestates
save_item(NAME(m_output_latch));
save_item(NAME(m_cnt));
save_item(NAME(m_dir));
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void sega_315_5296_device::device_reset()
{
// all ports are set to input
m_dir = 0;
// clear output ports
memset(m_output_latch, 0, sizeof(m_output_latch));
m_cnt = 0;
for (int i = 0; i < 8; i++)
(*m_out_port_cb[i])((offs_t)i, 0);
for (int i = 0; i < 3; i++)
(*m_out_cnt_cb[i])(0);
}
//-------------------------------------------------
READ8_MEMBER( sega_315_5296_device::read )
{
offset &= 0xf;
switch (offset)
{
// port A to H
case 0x0: case 0x1: case 0x2: case 0x3: case 0x4: case 0x5: case 0x6: case 0x7:
// if the port is configured as an output, return the last thing written
if (m_dir & 1 << offset)
return m_output_latch[offset];
// otherwise, return an input port
return (*m_in_port_cb[offset])(offset);
// 'SEGA' protection
case 0x8:
return 'S';
case 0x9:
return 'E';
case 0xa:
return 'G';
case 0xb:
return 'A';
// CNT register & mirror
case 0xc: case 0xe:
return m_cnt;
// port direction register & mirror
case 0xd: case 0xf:
return m_dir;
}
return 0xff;
}
WRITE8_MEMBER( sega_315_5296_device::write )
{
offset &= 0xf;
switch (offset)
{
// port A to H
case 0x0: case 0x1: case 0x2: case 0x3: case 0x4: case 0x5: case 0x6: case 0x7:
// if the port is configured as an output, write it
if (m_dir & 1 << offset)
(*m_out_port_cb[offset])(offset, data);
m_output_latch[offset] = data;
break;
// CNT register
case 0xe:
// d0-2: CNT0-2, other bits: ?
for (int i = 0; i < 3; i++)
(*m_out_cnt_cb[i])(data >> i & 1);
m_cnt = data;
break;
// port direction register
case 0xf:
// refresh output ports if the direction changed
for (int i = 0; i < 8; i++)
{
if ((m_dir ^ data) & (1 << i))
(*m_out_port_cb[i])((offs_t)i, (data & 1 << i) ? m_output_latch[i] : 0);
}
m_dir = data;
break;
default:
break;
}
}

145
src/mame/machine/315-5296.h Normal file
View File

@ -0,0 +1,145 @@
/**********************************************************************
Sega 315-5296 I/O chip
Copyright MAME Team.
Visit http://mamedev.org for licensing and usage restrictions.
**********************************************************************/
#pragma once
#ifndef _SEGA_315_5296_H
#define _SEGA_315_5296_H
#include "emu.h"
//**************************************************************************
// INTERFACE CONFIGURATION MACROS
//**************************************************************************
// A to H 8-bit input ports
#define MCFG_315_5296_IN_PORTA_CB(_devcb) \
devcb = &sega_315_5296_device::set_in_pa_callback(*device, DEVCB_##_devcb);
#define MCFG_315_5296_IN_PORTB_CB(_devcb) \
devcb = &sega_315_5296_device::set_in_pb_callback(*device, DEVCB_##_devcb);
#define MCFG_315_5296_IN_PORTC_CB(_devcb) \
devcb = &sega_315_5296_device::set_in_pc_callback(*device, DEVCB_##_devcb);
#define MCFG_315_5296_IN_PORTD_CB(_devcb) \
devcb = &sega_315_5296_device::set_in_pd_callback(*device, DEVCB_##_devcb);
#define MCFG_315_5296_IN_PORTE_CB(_devcb) \
devcb = &sega_315_5296_device::set_in_pe_callback(*device, DEVCB_##_devcb);
#define MCFG_315_5296_IN_PORTF_CB(_devcb) \
devcb = &sega_315_5296_device::set_in_pf_callback(*device, DEVCB_##_devcb);
#define MCFG_315_5296_IN_PORTG_CB(_devcb) \
devcb = &sega_315_5296_device::set_in_pg_callback(*device, DEVCB_##_devcb);
#define MCFG_315_5296_IN_PORTH_CB(_devcb) \
devcb = &sega_315_5296_device::set_in_ph_callback(*device, DEVCB_##_devcb);
// A to H 8-bit output ports
#define MCFG_315_5296_OUT_PORTA_CB(_devcb) \
devcb = &sega_315_5296_device::set_out_pa_callback(*device, DEVCB_##_devcb);
#define MCFG_315_5296_OUT_PORTB_CB(_devcb) \
devcb = &sega_315_5296_device::set_out_pb_callback(*device, DEVCB_##_devcb);
#define MCFG_315_5296_OUT_PORTC_CB(_devcb) \
devcb = &sega_315_5296_device::set_out_pc_callback(*device, DEVCB_##_devcb);
#define MCFG_315_5296_OUT_PORTD_CB(_devcb) \
devcb = &sega_315_5296_device::set_out_pd_callback(*device, DEVCB_##_devcb);
#define MCFG_315_5296_OUT_PORTE_CB(_devcb) \
devcb = &sega_315_5296_device::set_out_pe_callback(*device, DEVCB_##_devcb);
#define MCFG_315_5296_OUT_PORTF_CB(_devcb) \
devcb = &sega_315_5296_device::set_out_pf_callback(*device, DEVCB_##_devcb);
#define MCFG_315_5296_OUT_PORTG_CB(_devcb) \
devcb = &sega_315_5296_device::set_out_pg_callback(*device, DEVCB_##_devcb);
#define MCFG_315_5296_OUT_PORTH_CB(_devcb) \
devcb = &sega_315_5296_device::set_out_ph_callback(*device, DEVCB_##_devcb);
// CNT output pins
#define MCFG_315_5296_OUT_CNT0_CB(_devcb) \
devcb = &sega_315_5296_device::set_out_cnt0_callback(*device, DEVCB_##_devcb);
#define MCFG_315_5296_OUT_CNT1_CB(_devcb) \
devcb = &sega_315_5296_device::set_out_cnt1_callback(*device, DEVCB_##_devcb);
#define MCFG_315_5296_OUT_CNT2_CB(_devcb) \
devcb = &sega_315_5296_device::set_out_cnt2_callback(*device, DEVCB_##_devcb);
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// ======================> sega_315_5296_device
class sega_315_5296_device : public device_t
{
public:
sega_315_5296_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// static configuration helpers
template<class _Object> static devcb_base &set_in_pa_callback(device_t &device, _Object object) { return downcast<sega_315_5296_device &>(device).m_in_pa_cb.set_callback(object); }
template<class _Object> static devcb_base &set_in_pb_callback(device_t &device, _Object object) { return downcast<sega_315_5296_device &>(device).m_in_pb_cb.set_callback(object); }
template<class _Object> static devcb_base &set_in_pc_callback(device_t &device, _Object object) { return downcast<sega_315_5296_device &>(device).m_in_pc_cb.set_callback(object); }
template<class _Object> static devcb_base &set_in_pd_callback(device_t &device, _Object object) { return downcast<sega_315_5296_device &>(device).m_in_pd_cb.set_callback(object); }
template<class _Object> static devcb_base &set_in_pe_callback(device_t &device, _Object object) { return downcast<sega_315_5296_device &>(device).m_in_pe_cb.set_callback(object); }
template<class _Object> static devcb_base &set_in_pf_callback(device_t &device, _Object object) { return downcast<sega_315_5296_device &>(device).m_in_pf_cb.set_callback(object); }
template<class _Object> static devcb_base &set_in_pg_callback(device_t &device, _Object object) { return downcast<sega_315_5296_device &>(device).m_in_pg_cb.set_callback(object); }
template<class _Object> static devcb_base &set_in_ph_callback(device_t &device, _Object object) { return downcast<sega_315_5296_device &>(device).m_in_ph_cb.set_callback(object); }
template<class _Object> static devcb_base &set_out_pa_callback(device_t &device, _Object object) { return downcast<sega_315_5296_device &>(device).m_out_pa_cb.set_callback(object); }
template<class _Object> static devcb_base &set_out_pb_callback(device_t &device, _Object object) { return downcast<sega_315_5296_device &>(device).m_out_pb_cb.set_callback(object); }
template<class _Object> static devcb_base &set_out_pc_callback(device_t &device, _Object object) { return downcast<sega_315_5296_device &>(device).m_out_pc_cb.set_callback(object); }
template<class _Object> static devcb_base &set_out_pd_callback(device_t &device, _Object object) { return downcast<sega_315_5296_device &>(device).m_out_pd_cb.set_callback(object); }
template<class _Object> static devcb_base &set_out_pe_callback(device_t &device, _Object object) { return downcast<sega_315_5296_device &>(device).m_out_pe_cb.set_callback(object); }
template<class _Object> static devcb_base &set_out_pf_callback(device_t &device, _Object object) { return downcast<sega_315_5296_device &>(device).m_out_pf_cb.set_callback(object); }
template<class _Object> static devcb_base &set_out_pg_callback(device_t &device, _Object object) { return downcast<sega_315_5296_device &>(device).m_out_pg_cb.set_callback(object); }
template<class _Object> static devcb_base &set_out_ph_callback(device_t &device, _Object object) { return downcast<sega_315_5296_device &>(device).m_out_ph_cb.set_callback(object); }
template<class _Object> static devcb_base &set_out_cnt0_callback(device_t &device, _Object object) { return downcast<sega_315_5296_device &>(device).m_out_cnt0_cb.set_callback(object); }
template<class _Object> static devcb_base &set_out_cnt1_callback(device_t &device, _Object object) { return downcast<sega_315_5296_device &>(device).m_out_cnt1_cb.set_callback(object); }
template<class _Object> static devcb_base &set_out_cnt2_callback(device_t &device, _Object object) { return downcast<sega_315_5296_device &>(device).m_out_cnt2_cb.set_callback(object); }
DECLARE_READ8_MEMBER( read );
DECLARE_WRITE8_MEMBER( write );
protected:
// device-level overrides
virtual void device_start();
virtual void device_reset();
private:
devcb_read8 m_in_pa_cb;
devcb_read8 m_in_pb_cb;
devcb_read8 m_in_pc_cb;
devcb_read8 m_in_pd_cb;
devcb_read8 m_in_pe_cb;
devcb_read8 m_in_pf_cb;
devcb_read8 m_in_pg_cb;
devcb_read8 m_in_ph_cb;
devcb_write8 m_out_pa_cb;
devcb_write8 m_out_pb_cb;
devcb_write8 m_out_pc_cb;
devcb_write8 m_out_pd_cb;
devcb_write8 m_out_pe_cb;
devcb_write8 m_out_pf_cb;
devcb_write8 m_out_pg_cb;
devcb_write8 m_out_ph_cb;
devcb_write_line m_out_cnt0_cb;
devcb_write_line m_out_cnt1_cb;
devcb_write_line m_out_cnt2_cb;
devcb_read8 *m_in_port_cb[8];
devcb_write8 *m_out_port_cb[8];
devcb_write_line *m_out_cnt_cb[3];
UINT8 m_output_latch[8];
UINT8 m_cnt;
UINT8 m_dir;
};
// device type definition
extern const device_type SEGA_315_5296;
#endif /* _SEGA_315_5296_H */

View File

@ -1727,6 +1727,7 @@ $(MAMEOBJ)/sega.a: \
$(DRIVERS)/turbo.o $(AUDIO)/turbo.o $(VIDEO)/turbo.o \
$(DRIVERS)/vicdual.o $(AUDIO)/vicdual.o $(VIDEO)/vicdual.o $(AUDIO)/carnival.o $(AUDIO)/depthch.o $(AUDIO)/invinco.o $(AUDIO)/pulsar.o \
$(DRIVERS)/zaxxon.o $(AUDIO)/zaxxon.o $(VIDEO)/zaxxon.o \
$(MACHINE)/315-5296.o \
$(MACHINE)/fd1089.o \
$(MACHINE)/fd1094.o \
$(MACHINE)/fddebug.o \