From 1cdd1948ee33363212150c70ac865dc97b5bfce7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Banaan=20Ananas?= Date: Thu, 9 Oct 2014 23:39:27 +0000 Subject: [PATCH] added 315-5296 device --- .gitattributes | 2 + src/emu/machine/7200fifo.c | 24 ++-- src/emu/sound/upd7759.c | 14 +-- src/emu/sound/upd7759.h | 14 +-- src/mame/drivers/segac2.c | 214 ++++++++++++------------------------ src/mame/machine/315-5296.c | 178 ++++++++++++++++++++++++++++++ src/mame/machine/315-5296.h | 145 ++++++++++++++++++++++++ src/mame/mame.mak | 1 + 8 files changed, 420 insertions(+), 172 deletions(-) create mode 100644 src/mame/machine/315-5296.c create mode 100644 src/mame/machine/315-5296.h diff --git a/.gitattributes b/.gitattributes index e5848af7f54..9a0b3bafa8f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -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 diff --git a/src/emu/machine/7200fifo.c b/src/emu/machine/7200fifo.c index 728fc5c8563..f4a6cb758b3 100644 --- a/src/emu/machine/7200fifo.c +++ b/src/emu/machine/7200fifo.c @@ -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; diff --git a/src/emu/sound/upd7759.c b/src/emu/sound/upd7759.c index 72157e51f73..942c1aad28e 100644 --- a/src/emu/sound/upd7759.c +++ b/src/emu/sound/upd7759.c @@ -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); diff --git a/src/emu/sound/upd7759.h b/src/emu/sound/upd7759.h index 10d0df4a8f8..948f7224927 100644 --- a/src/emu/sound/upd7759.h +++ b/src/emu/sound/upd7759.h @@ -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; diff --git a/src/mame/drivers/segac2.c b/src/mame/drivers/segac2.c index 6cde903f3e1..2f9729935bd 100644 --- a/src/mame/drivers/segac2.c +++ b/src/mame/drivers/segac2.c @@ -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) diff --git a/src/mame/machine/315-5296.c b/src/mame/machine/315-5296.c new file mode 100644 index 00000000000..6104df5bf38 --- /dev/null +++ b/src/mame/machine/315-5296.c @@ -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 - 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; + } +} diff --git a/src/mame/machine/315-5296.h b/src/mame/machine/315-5296.h new file mode 100644 index 00000000000..a3882475db6 --- /dev/null +++ b/src/mame/machine/315-5296.h @@ -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 static devcb_base &set_in_pa_callback(device_t &device, _Object object) { return downcast(device).m_in_pa_cb.set_callback(object); } + template static devcb_base &set_in_pb_callback(device_t &device, _Object object) { return downcast(device).m_in_pb_cb.set_callback(object); } + template static devcb_base &set_in_pc_callback(device_t &device, _Object object) { return downcast(device).m_in_pc_cb.set_callback(object); } + template static devcb_base &set_in_pd_callback(device_t &device, _Object object) { return downcast(device).m_in_pd_cb.set_callback(object); } + template static devcb_base &set_in_pe_callback(device_t &device, _Object object) { return downcast(device).m_in_pe_cb.set_callback(object); } + template static devcb_base &set_in_pf_callback(device_t &device, _Object object) { return downcast(device).m_in_pf_cb.set_callback(object); } + template static devcb_base &set_in_pg_callback(device_t &device, _Object object) { return downcast(device).m_in_pg_cb.set_callback(object); } + template static devcb_base &set_in_ph_callback(device_t &device, _Object object) { return downcast(device).m_in_ph_cb.set_callback(object); } + + template static devcb_base &set_out_pa_callback(device_t &device, _Object object) { return downcast(device).m_out_pa_cb.set_callback(object); } + template static devcb_base &set_out_pb_callback(device_t &device, _Object object) { return downcast(device).m_out_pb_cb.set_callback(object); } + template static devcb_base &set_out_pc_callback(device_t &device, _Object object) { return downcast(device).m_out_pc_cb.set_callback(object); } + template static devcb_base &set_out_pd_callback(device_t &device, _Object object) { return downcast(device).m_out_pd_cb.set_callback(object); } + template static devcb_base &set_out_pe_callback(device_t &device, _Object object) { return downcast(device).m_out_pe_cb.set_callback(object); } + template static devcb_base &set_out_pf_callback(device_t &device, _Object object) { return downcast(device).m_out_pf_cb.set_callback(object); } + template static devcb_base &set_out_pg_callback(device_t &device, _Object object) { return downcast(device).m_out_pg_cb.set_callback(object); } + template static devcb_base &set_out_ph_callback(device_t &device, _Object object) { return downcast(device).m_out_ph_cb.set_callback(object); } + + template static devcb_base &set_out_cnt0_callback(device_t &device, _Object object) { return downcast(device).m_out_cnt0_cb.set_callback(object); } + template static devcb_base &set_out_cnt1_callback(device_t &device, _Object object) { return downcast(device).m_out_cnt1_cb.set_callback(object); } + template static devcb_base &set_out_cnt2_callback(device_t &device, _Object object) { return downcast(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 */ diff --git a/src/mame/mame.mak b/src/mame/mame.mak index ecaa2675fe2..200131b3832 100644 --- a/src/mame/mame.mak +++ b/src/mame/mame.mak @@ -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 \