mirror of
https://github.com/holub/mame
synced 2025-05-22 13:48:55 +03:00
2452 lines
86 KiB
C
2452 lines
86 KiB
C
/***************************************************************************
|
|
|
|
snes.c
|
|
|
|
Driver file to handle emulation of the Nintendo Super NES.
|
|
|
|
R. Belmont
|
|
Anthony Kruize
|
|
Angelo Salese
|
|
Fabio Priuli
|
|
byuu
|
|
Based on the original MESS driver by Lee Hammerton (aka Savoury Snax)
|
|
|
|
Driver is preliminary right now.
|
|
|
|
The memory map included below is setup in a way to make it easier to handle
|
|
Mode 20 and Mode 21 ROMs.
|
|
|
|
Todo (in no particular order):
|
|
- Fix additional sound bugs
|
|
- Emulate extra chips - superfx, dsp2, sa-1 etc.
|
|
- Add horizontal mosaic, hi-res. interlaced etc to video emulation.
|
|
- Fix support for Mode 7. (In Progress)
|
|
- Handle interleaved roms (maybe even multi-part roms, but how?)
|
|
- Add support for running at 3.58 MHz at the appropriate time.
|
|
- I'm sure there's lots more ...
|
|
|
|
***************************************************************************/
|
|
|
|
#include "emu.h"
|
|
#include "audio/snes_snd.h"
|
|
#include "cpu/spc700/spc700.h"
|
|
#include "cpu/superfx/superfx.h"
|
|
#include "cpu/g65816/g65816.h"
|
|
#include "cpu/upd7725/upd7725.h"
|
|
#include "includes/snes.h"
|
|
#include "machine/snescart.h"
|
|
|
|
#include "crsshair.h"
|
|
|
|
#define MAX_SNES_CART_SIZE 0x600000
|
|
|
|
class snes_console_state : public snes_state
|
|
{
|
|
public:
|
|
snes_console_state(const machine_config &mconfig, device_type type, const char *tag)
|
|
: snes_state(mconfig, type, tag)
|
|
{ }
|
|
|
|
DECLARE_READ8_MEMBER( spc_ram_100_r );
|
|
DECLARE_WRITE8_MEMBER( spc_ram_100_w );
|
|
UINT8 st010_read_ram(UINT16 addr);
|
|
void st010_write_ram(UINT16 addr, UINT8 data);
|
|
DECLARE_READ8_MEMBER( snes_lo_r );
|
|
DECLARE_READ8_MEMBER( snes_hi_r );
|
|
DECLARE_WRITE8_MEMBER( snes_lo_w );
|
|
DECLARE_WRITE8_MEMBER( snes_hi_w );
|
|
DECLARE_READ8_MEMBER( superfx_r_bank1 );
|
|
DECLARE_READ8_MEMBER( superfx_r_bank2 );
|
|
DECLARE_READ8_MEMBER( superfx_r_bank3 );
|
|
DECLARE_WRITE8_MEMBER( superfx_w_bank3 );
|
|
CUSTOM_INPUT_MEMBER( snes_mouse_speed_input );
|
|
CUSTOM_INPUT_MEMBER( snes_superscope_offscreen_input );
|
|
TIMER_CALLBACK_MEMBER( lightgun_tick );
|
|
void snes_gun_latch( INT16 x, INT16 y );
|
|
void snes_input_read_joy( int port );
|
|
void snes_input_read_mouse( int port );
|
|
void snes_input_read_superscope( int port );
|
|
DECLARE_WRITE8_MEMBER(snes_input_read);
|
|
DECLARE_READ8_MEMBER(snes_oldjoy1_read);
|
|
DECLARE_READ8_MEMBER(snes_oldjoy2_read);
|
|
};
|
|
|
|
/*************************************
|
|
*
|
|
* Memory handlers
|
|
*
|
|
*************************************/
|
|
|
|
READ8_MEMBER(snes_console_state::spc_ram_100_r )
|
|
{
|
|
return spc_ram_r(machine().device("spc700"), space, offset + 0x100);
|
|
}
|
|
|
|
WRITE8_MEMBER(snes_console_state::spc_ram_100_w )
|
|
{
|
|
spc_ram_w(machine().device("spc700"), space, offset + 0x100, data);
|
|
}
|
|
|
|
// DSP accessors
|
|
#define dsp_get_sr() m_upd7725->snesdsp_read(false)
|
|
#define dsp_get_dr() m_upd7725->snesdsp_read(true)
|
|
#define dsp_set_sr(data) m_upd7725->snesdsp_write(false, data)
|
|
#define dsp_set_dr(data) m_upd7725->snesdsp_write(true, data)
|
|
|
|
#define st010_get_sr() m_upd96050->snesdsp_read(false)
|
|
#define st010_get_dr() m_upd96050->snesdsp_read(true)
|
|
#define st010_set_sr(data) m_upd96050->snesdsp_write(false, data)
|
|
#define st010_set_dr(data) m_upd96050->snesdsp_write(true, data)
|
|
|
|
// ST-010 and ST-011 RAM interface
|
|
UINT8 snes_console_state::st010_read_ram(UINT16 addr)
|
|
{
|
|
UINT16 temp = m_upd96050->dataram_r(addr/2);
|
|
UINT8 res;
|
|
|
|
if (addr & 1)
|
|
{
|
|
res = temp>>8;
|
|
}
|
|
else
|
|
{
|
|
res = temp & 0xff;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
void snes_console_state::st010_write_ram(UINT16 addr, UINT8 data)
|
|
{
|
|
UINT16 temp = m_upd96050->dataram_r(addr/2);
|
|
|
|
if (addr & 1)
|
|
{
|
|
temp &= 0xff;
|
|
temp |= data<<8;
|
|
}
|
|
else
|
|
{
|
|
temp &= 0xff00;
|
|
temp |= data;
|
|
}
|
|
|
|
m_upd96050->dataram_w(addr/2, temp);
|
|
}
|
|
|
|
|
|
READ8_MEMBER( snes_console_state::snes_lo_r )
|
|
{
|
|
UINT16 address = offset & 0xffff;
|
|
|
|
// take care of add-on chip access
|
|
if (m_has_addon_chip == HAS_OBC1
|
|
&& (offset < 0x400000 && address >= 0x6000 && address < 0x8000))
|
|
return obc1_read(space, offset, mem_mask);
|
|
if (m_has_addon_chip == HAS_CX4
|
|
&& (offset < 0x400000 && address >= 0x6000 && address < 0x8000))
|
|
return CX4_read(address - 0x6000);
|
|
if (m_has_addon_chip == HAS_RTC
|
|
&& (offset < 0x400000 && (address == 0x2800 || address == 0x2801)))
|
|
return srtc_read(space, offset);
|
|
if (m_has_addon_chip == HAS_ST010 || m_has_addon_chip == HAS_ST011)
|
|
{
|
|
if (offset >= 0x680000 && offset < 0x700000 && address < 0x1000)
|
|
return st010_read_ram(address);
|
|
if (offset == 0x600000 || offset == 0x600001)
|
|
return (offset & 1) ? st010_get_sr() : st010_get_dr();
|
|
}
|
|
if (m_cart[0].mode == SNES_MODE_21 && m_has_addon_chip == HAS_DSP1
|
|
&& (offset < 0x200000 && address >= 0x6000 && address < 0x8000))
|
|
return (address < 0x7000) ? dsp_get_dr() : dsp_get_sr();
|
|
if (m_cart[0].mode == SNES_MODE_20 && m_has_addon_chip == HAS_DSP1)
|
|
{
|
|
if (offset >= 0x200000 && offset < 0x400000 && (offset & 0x8000) == 0x8000)
|
|
return (address < 0xc000) ? dsp_get_dr() : dsp_get_sr();
|
|
if (offset >= 0x600000 && offset < 0x700000 && (offset & 0x8000) == 0x0000)
|
|
return (address < 0x4000) ? dsp_get_dr() : dsp_get_sr();
|
|
}
|
|
if ((m_has_addon_chip == HAS_DSP2 || m_has_addon_chip == HAS_DSP3)
|
|
&& (offset >= 0x200000 && offset < 0x400000 && (offset & 0x8000) == 0x8000))
|
|
return (address < 0xc000) ? dsp_get_dr() : dsp_get_sr();
|
|
if (m_has_addon_chip == HAS_DSP4
|
|
&& (offset >= 0x300000 && offset < 0x400000 && (offset & 0x8000) == 0x8000))
|
|
return (address < 0xc000) ? dsp_get_dr() : dsp_get_sr();
|
|
if (m_has_addon_chip == HAS_SDD1
|
|
&& (offset < 0x400000 && address >= 0x4800 && address < 0x4808))
|
|
return sdd1_mmio_read(space, (UINT32)address);
|
|
if ((m_has_addon_chip == HAS_SPC7110 || m_has_addon_chip == HAS_SPC7110_RTC)
|
|
&& offset < 0x400000)
|
|
{
|
|
UINT16 limit = (m_has_addon_chip == HAS_SPC7110_RTC) ? 0x4842 : 0x483f;
|
|
if (address >= 0x4800 && address <= limit)
|
|
return spc7110_mmio_read(space, (UINT32)address);
|
|
if (offset < 0x10000 && address >= 0x6000 && address < 0x8000)
|
|
return snes_ram[0x306000 + (address & 0x1fff)];
|
|
if (offset >= 0x300000 && offset < 0x310000 && address >= 0x6000 && address < 0x8000)
|
|
return snes_ram[0x306000 + (address & 0x1fff)];
|
|
}
|
|
if ((m_has_addon_chip == HAS_SPC7110 || m_has_addon_chip == HAS_SPC7110_RTC)
|
|
&& offset >= 0x500000 && offset < 0x510000)
|
|
return spc7110_mmio_read(space, 0x4800);
|
|
if (m_has_addon_chip == HAS_SUPERFX && m_superfx != NULL
|
|
&& offset < 0x400000)
|
|
{
|
|
if (address >= 0x3000 && address < 0x3300)
|
|
return superfx_mmio_read(m_superfx, address);
|
|
if (address >= 0x6000 && address < 0x8000) // here it should be snes_ram[0xe00000+...] but there are mirroring issues
|
|
return superfx_access_ram(m_superfx) ? snes_ram[0xf00000 + (offset & 0x1fff)] : snes_open_bus_r(space, 0);
|
|
}
|
|
if (m_has_addon_chip == HAS_SUPERFX && m_superfx != NULL
|
|
&& offset >= 0x400000 && offset < 0x600000)
|
|
{
|
|
if (superfx_access_rom(m_superfx))
|
|
return snes_ram[offset];
|
|
else
|
|
{
|
|
static const UINT8 sfx_data[16] = {
|
|
0x00, 0x01, 0x00, 0x01, 0x04, 0x01, 0x00, 0x01,
|
|
0x00, 0x01, 0x08, 0x01, 0x00, 0x01, 0x0c, 0x01,
|
|
};
|
|
return sfx_data[offset & 0x0f];
|
|
}
|
|
}
|
|
if (m_has_addon_chip == HAS_SUPERFX && m_superfx != NULL
|
|
&& offset >= 0x600000)
|
|
return superfx_access_ram(m_superfx) ? snes_ram[0x800000 + offset] : snes_open_bus_r(space, 0);
|
|
|
|
// base cart access
|
|
if (offset < 0x300000)
|
|
return snes_r_bank1(space, offset, 0xff);
|
|
else if (offset < 0x400000)
|
|
return snes_r_bank2(space, offset - 0x300000, 0xff);
|
|
else if (offset < 0x600000)
|
|
return snes_r_bank3(space, offset - 0x400000, 0xff);
|
|
else if (offset < 0x700000)
|
|
return snes_r_bank4(space, offset - 0x600000, 0xff);
|
|
else
|
|
return snes_r_bank5(space, offset - 0x700000, 0xff);
|
|
}
|
|
|
|
READ8_MEMBER( snes_console_state::snes_hi_r )
|
|
{
|
|
UINT16 address = offset & 0xffff;
|
|
|
|
// take care of add-on chip access
|
|
if (m_has_addon_chip == HAS_OBC1
|
|
&& (offset < 0x400000 && address >= 0x6000 && address < 0x8000))
|
|
return obc1_read(space, offset, mem_mask);
|
|
if (m_has_addon_chip == HAS_CX4
|
|
&& (offset < 0x400000 && address >= 0x6000 && address < 0x8000))
|
|
return CX4_read(address - 0x6000);
|
|
if (m_has_addon_chip == HAS_RTC
|
|
&& (offset < 0x400000 && (address == 0x2800 || address == 0x2801)))
|
|
return srtc_read(space, offset);
|
|
if (m_has_addon_chip == HAS_ST010 || m_has_addon_chip == HAS_ST011)
|
|
{
|
|
if (offset >= 0x680000 && offset < 0x700000 && address < 0x1000)
|
|
return st010_read_ram(address);
|
|
if (offset == 0x600000 || offset == 0x600001)
|
|
return (offset & 1) ? st010_get_sr() : st010_get_dr();
|
|
}
|
|
if (m_cart[0].mode == SNES_MODE_21 && m_has_addon_chip == HAS_DSP1
|
|
&& (offset < 0x200000 && address >= 0x6000 && address < 0x8000))
|
|
return (address < 0x7000) ? dsp_get_dr() : dsp_get_sr();
|
|
if (m_cart[0].mode == SNES_MODE_20 && m_has_addon_chip == HAS_DSP1)
|
|
{
|
|
if (offset >= 0x200000 && offset < 0x400000 && (offset & 0x8000) == 0x8000)
|
|
return (address < 0xc000) ? dsp_get_dr() : dsp_get_sr();
|
|
if (offset >= 0x600000 && offset < 0x700000 && (offset & 0x8000) == 0x0000)
|
|
return (address < 0x4000) ? dsp_get_dr() : dsp_get_sr();
|
|
}
|
|
if ((m_has_addon_chip == HAS_DSP2 || m_has_addon_chip == HAS_DSP3)
|
|
&& (offset >= 0x200000 && offset < 0x400000 && (offset & 0x8000) == 0x8000))
|
|
return (address < 0xc000) ? dsp_get_dr() : dsp_get_sr();
|
|
if (m_has_addon_chip == HAS_DSP4
|
|
&& (offset >= 0x300000 && offset < 0x400000 && (offset & 0x8000) == 0x8000))
|
|
return (address < 0xc000) ? dsp_get_dr() : dsp_get_sr();
|
|
if (m_has_addon_chip == HAS_SDD1
|
|
&& (offset < 0x400000 && address >= 0x4800 && address < 0x4808))
|
|
return sdd1_mmio_read(space, (UINT32)address);
|
|
if (m_has_addon_chip == HAS_SDD1 && offset >= 0x400000)
|
|
return sdd1_read(space.machine(), offset - 0x400000);
|
|
if ((m_has_addon_chip == HAS_SPC7110 || m_has_addon_chip == HAS_SPC7110_RTC)
|
|
&& offset < 0x400000)
|
|
{
|
|
UINT16 limit = (m_has_addon_chip == HAS_SPC7110_RTC) ? 0x4842 : 0x483f;
|
|
if (address >= 0x4800 && address <= limit)
|
|
return spc7110_mmio_read(space, (UINT32)address);
|
|
if (offset < 0x10000 && address >= 0x6000 && address < 0x8000)
|
|
return snes_ram[0x306000 + (address & 0x1fff)];
|
|
if (offset >= 0x300000 && offset < 0x310000 && address >= 0x6000 && address < 0x8000)
|
|
return snes_ram[0x306000 + (address & 0x1fff)];
|
|
}
|
|
if ((m_has_addon_chip == HAS_SPC7110 || m_has_addon_chip == HAS_SPC7110_RTC)
|
|
&& offset >= 0x500000)
|
|
return spc7110_bank7_read(space, offset - 0x400000);
|
|
if (m_has_addon_chip == HAS_SUPERFX && m_superfx != NULL)
|
|
return space.read_byte(offset); // [80-ff] same as [00-7f]
|
|
|
|
// base cart access
|
|
if (offset < 0x400000)
|
|
return snes_r_bank6(space, offset, 0xff);
|
|
else
|
|
return snes_r_bank7(space, offset - 0x400000, 0xff);
|
|
}
|
|
|
|
WRITE8_MEMBER( snes_console_state::snes_lo_w )
|
|
{
|
|
UINT16 address = offset & 0xffff;
|
|
|
|
// take care of add-on chip access
|
|
if (m_has_addon_chip == HAS_OBC1
|
|
&& (offset < 0x400000 && address >= 0x6000 && address < 0x8000))
|
|
{ obc1_write(space, offset, data, mem_mask); return; }
|
|
if (m_has_addon_chip == HAS_CX4
|
|
&& (offset < 0x400000 && address >= 0x6000 && address < 0x8000))
|
|
{ CX4_write(space.machine(), address - 0x6000, data); return; }
|
|
if (m_has_addon_chip == HAS_RTC
|
|
&& (offset < 0x400000 && (address == 0x2800 || address == 0x2801)))
|
|
{ srtc_write(space.machine(), offset, data); return; }
|
|
if (m_has_addon_chip == HAS_ST010 || m_has_addon_chip == HAS_ST011)
|
|
{
|
|
if (offset >= 0x680000 && offset < 0x700000 && address < 0x1000)
|
|
{ st010_write_ram(address, data); return; }
|
|
if (offset == 0x600000)
|
|
{ st010_set_dr(data); return; }
|
|
if (offset == 0x600001)
|
|
{ st010_set_sr(data); return; }
|
|
}
|
|
if (m_cart[0].mode == SNES_MODE_21 && m_has_addon_chip == HAS_DSP1
|
|
&& (offset < 0x200000 && address >= 0x6000 && address < 0x8000))
|
|
{ dsp_set_dr(data); return; }
|
|
if (m_cart[0].mode == SNES_MODE_20 && m_has_addon_chip == HAS_DSP1)
|
|
{
|
|
if (offset >= 0x200000 && offset < 0x400000 && (offset & 0x8000) == 0x8000)
|
|
{ dsp_set_dr(data); return; }
|
|
if (offset >= 0x600000 && offset < 0x700000 && (offset & 0x8000) == 0x0000)
|
|
{ dsp_set_dr(data); return; }
|
|
}
|
|
if ((m_has_addon_chip == HAS_DSP2 || m_has_addon_chip == HAS_DSP3)
|
|
&& (offset >= 0x200000 && offset < 0x400000 && (offset & 0x8000) == 0x8000))
|
|
{
|
|
if (address < 0xc000)
|
|
{ dsp_set_dr(data); return; }
|
|
else
|
|
{ dsp_set_sr(data); return; }
|
|
}
|
|
if (m_has_addon_chip == HAS_DSP4
|
|
&& (offset >= 0x300000 && offset < 0x400000 && (offset & 0x8000) == 0x8000))
|
|
{
|
|
if (address < 0xc000)
|
|
{ dsp_set_dr(data); return; }
|
|
else
|
|
{ dsp_set_sr(data); return; }
|
|
}
|
|
if (m_has_addon_chip == HAS_SDD1 && offset < 0x400000)
|
|
{
|
|
if ((address >= 0x4300 && address < 0x4380) || (address >= 0x4800 && address < 0x4808))
|
|
{
|
|
sdd1_mmio_write(space, (UINT32)address, data);
|
|
// here we don't return, but we let the w_io happen...
|
|
}
|
|
}
|
|
if ((m_has_addon_chip == HAS_SPC7110 || m_has_addon_chip == HAS_SPC7110_RTC) && offset < 0x400000)
|
|
{
|
|
UINT16 limit = (m_has_addon_chip == HAS_SPC7110_RTC) ? 0x4842 : 0x483f;
|
|
if (address >= 0x4800 && address <= limit)
|
|
{ spc7110_mmio_write(space.machine(), (UINT32)address, data); return; }
|
|
if (offset < 0x10000 && address >= 0x6000 && address < 0x8000)
|
|
{ snes_ram[0x306000 + (address & 0x1fff)] = data; return; }
|
|
if (offset >= 0x300000 && offset < 0x310000 && address >= 0x6000 && address < 0x8000)
|
|
{ snes_ram[0x306000 + (address & 0x1fff)] = data; return; }
|
|
}
|
|
if (m_has_addon_chip == HAS_SUPERFX && m_superfx != NULL
|
|
&& offset < 0x400000)
|
|
{
|
|
if (address >= 0x3000 && address < 0x3300)
|
|
{ superfx_mmio_write(m_superfx, address, data); return; }
|
|
if (address >= 0x6000 && address < 0x8000) // here it should be snes_ram[0xe00000+...] but there are mirroring issues
|
|
{ snes_ram[0xf00000 + (offset & 0x1fff)] = data; return; }
|
|
}
|
|
if (m_has_addon_chip == HAS_SUPERFX && m_superfx != NULL
|
|
&& offset >= 0x600000)
|
|
{ snes_ram[0x800000 + offset] = data; return; }
|
|
|
|
// base cart access
|
|
if (offset < 0x300000)
|
|
snes_w_bank1(space, offset, data, 0xff);
|
|
else if (offset < 0x400000)
|
|
snes_w_bank2(space, offset - 0x300000, data, 0xff);
|
|
else if (offset < 0x600000)
|
|
return;
|
|
else if (offset < 0x700000)
|
|
snes_w_bank4(space, offset - 0x600000, data, 0xff);
|
|
else
|
|
snes_w_bank5(space, offset - 0x700000, data, 0xff);
|
|
}
|
|
|
|
WRITE8_MEMBER( snes_console_state::snes_hi_w )
|
|
{
|
|
UINT16 address = offset & 0xffff;
|
|
|
|
// take care of add-on chip access
|
|
if (m_has_addon_chip == HAS_OBC1
|
|
&& (offset < 0x400000 && address >= 0x6000 && address < 0x8000))
|
|
{ obc1_write(space, offset, data, mem_mask); return; }
|
|
if (m_has_addon_chip == HAS_CX4
|
|
&& (offset < 0x400000 && address >= 0x6000 && address < 0x8000))
|
|
{ CX4_write(space.machine(), address - 0x6000, data); return; }
|
|
if (m_has_addon_chip == HAS_RTC
|
|
&& (offset < 0x400000 && (address == 0x2800 || address == 0x2801)))
|
|
{ srtc_write(space.machine(), offset, data); return; }
|
|
if (m_has_addon_chip == HAS_ST010 || m_has_addon_chip == HAS_ST011)
|
|
{
|
|
if (offset >= 0x680000 && offset < 0x700000 && address < 0x1000)
|
|
{ st010_write_ram(address, data); return; }
|
|
if (offset == 0x600000)
|
|
{ st010_set_dr(data); return; }
|
|
if (offset == 0x600001)
|
|
{ st010_set_sr(data); return; }
|
|
}
|
|
if (m_cart[0].mode == SNES_MODE_21 && m_has_addon_chip == HAS_DSP1
|
|
&& (offset < 0x200000 && address >= 0x6000 && address < 0x8000))
|
|
{ dsp_set_dr(data); return; }
|
|
if (m_cart[0].mode == SNES_MODE_20 && m_has_addon_chip == HAS_DSP1)
|
|
{
|
|
if (offset >= 0x200000 && offset < 0x400000 && (offset & 0x8000) == 0x8000)
|
|
{ dsp_set_dr(data); return; }
|
|
if (offset >= 0x600000 && offset < 0x700000 && (offset & 0x8000) == 0x0000)
|
|
{ dsp_set_dr(data); return; }
|
|
}
|
|
if ((m_has_addon_chip == HAS_DSP2 || m_has_addon_chip == HAS_DSP3)
|
|
&& (offset >= 0x200000 && offset < 0x400000 && (offset & 0x8000) == 0x8000))
|
|
{
|
|
if (address < 0xc000)
|
|
{ dsp_set_dr(data); return; }
|
|
else
|
|
{ dsp_set_sr(data); return; }
|
|
}
|
|
if (m_has_addon_chip == HAS_DSP4
|
|
&& (offset >= 0x300000 && offset < 0x400000 && (offset & 0x8000) == 0x8000))
|
|
{
|
|
if (address < 0xc000)
|
|
{ dsp_set_dr(data); return; }
|
|
else
|
|
{ dsp_set_sr(data); return; }
|
|
}
|
|
if (m_has_addon_chip == HAS_SDD1 && offset < 0x400000)
|
|
{
|
|
if ((address >= 0x4300 && address < 0x4380) || (address >= 0x4800 && address < 0x4808))
|
|
{
|
|
sdd1_mmio_write(space, (UINT32)address, data);
|
|
// here we don't return, but we let the w_io happen...
|
|
}
|
|
}
|
|
if ((m_has_addon_chip == HAS_SPC7110 || m_has_addon_chip == HAS_SPC7110_RTC) && offset < 0x400000)
|
|
{
|
|
UINT16 limit = (m_has_addon_chip == HAS_SPC7110_RTC) ? 0x4842 : 0x483f;
|
|
if (address >= 0x4800 && address <= limit)
|
|
{ spc7110_mmio_write(space.machine(), (UINT32)address, data); return; }
|
|
if (offset < 0x10000 && address >= 0x6000 && address < 0x8000)
|
|
{ snes_ram[0x306000 + (address & 0x1fff)] = data; return; }
|
|
if (offset >= 0x300000 && offset < 0x310000 && address >= 0x6000 && address < 0x8000)
|
|
{ snes_ram[0x306000 + (address & 0x1fff)] = data; return; }
|
|
}
|
|
if (m_has_addon_chip == HAS_SUPERFX && m_superfx != NULL)
|
|
{ space.write_byte(offset, data); return; } // [80-ff] same as [00-7f]
|
|
|
|
// base cart access
|
|
if (offset < 0x400000)
|
|
snes_w_bank6(space, offset, data, 0xff);
|
|
else
|
|
snes_w_bank7(space, offset, data - 0x400000, 0xff);
|
|
}
|
|
|
|
READ8_MEMBER( snes_console_state::superfx_r_bank1 )
|
|
{
|
|
return snes_ram[offset | 0x8000];
|
|
}
|
|
|
|
READ8_MEMBER( snes_console_state::superfx_r_bank2 )
|
|
{
|
|
return snes_ram[0x400000 + offset];
|
|
}
|
|
|
|
READ8_MEMBER( snes_console_state::superfx_r_bank3 )
|
|
{
|
|
/* IMPORTANT: SFX RAM sits in 0x600000-0x7fffff, and it's mirrored in 0xe00000-0xffffff. However, SNES
|
|
has only access to 0x600000-0x7dffff (because there is WRAM after that), hence we directly use the mirror
|
|
as the place where to write & read SFX RAM. SNES handlers have been setup accordingly. */
|
|
//printf("superfx_r_bank3: %08x = %02x\n", offset, snes_ram[0xe00000 + offset]);
|
|
return snes_ram[0xe00000 + offset];
|
|
}
|
|
|
|
WRITE8_MEMBER( snes_console_state::superfx_w_bank3 )
|
|
{
|
|
/* IMPORTANT: SFX RAM sits in 0x600000-0x7fffff, and it's mirrored in 0xe00000-0xffffff. However, SNES
|
|
has only access to 0x600000-0x7dffff (because there is WRAM after that), hence we directly use the mirror
|
|
as the place where to write & read SFX RAM. SNES handlers have been setup accordingly. */
|
|
//printf("superfx_w_bank3: %08x = %02x\n", offset, data);
|
|
snes_ram[0xe00000 + offset] = data;
|
|
}
|
|
|
|
/*************************************
|
|
*
|
|
* Address maps
|
|
*
|
|
*************************************/
|
|
|
|
static ADDRESS_MAP_START( snes_map, AS_PROGRAM, 8, snes_console_state )
|
|
AM_RANGE(0x000000, 0x7dffff) AM_READWRITE(snes_lo_r, snes_lo_w)
|
|
AM_RANGE(0x7e0000, 0x7fffff) AM_RAM /* 8KB Low RAM, 24KB High RAM, 96KB Expanded RAM */
|
|
AM_RANGE(0x800000, 0xffffff) AM_READWRITE(snes_hi_r, snes_hi_w)
|
|
ADDRESS_MAP_END
|
|
|
|
static ADDRESS_MAP_START( superfx_map, AS_PROGRAM, 8, snes_console_state )
|
|
AM_RANGE(0x000000, 0x3fffff) AM_READ(superfx_r_bank1)
|
|
AM_RANGE(0x400000, 0x5fffff) AM_READ(superfx_r_bank2)
|
|
AM_RANGE(0x600000, 0x7dffff) AM_READWRITE(superfx_r_bank3, superfx_w_bank3)
|
|
AM_RANGE(0x800000, 0xbfffff) AM_READ(superfx_r_bank1)
|
|
AM_RANGE(0xc00000, 0xdfffff) AM_READ(superfx_r_bank2)
|
|
AM_RANGE(0xe00000, 0xffffff) AM_READWRITE(superfx_r_bank3, superfx_w_bank3)
|
|
ADDRESS_MAP_END
|
|
|
|
static ADDRESS_MAP_START( spc_map, AS_PROGRAM, 8, snes_console_state )
|
|
AM_RANGE(0x0000, 0x00ef) AM_DEVREADWRITE_LEGACY("spc700", spc_ram_r, spc_ram_w) /* lower 32k ram */
|
|
AM_RANGE(0x00f0, 0x00ff) AM_DEVREADWRITE_LEGACY("spc700", spc_io_r, spc_io_w) /* spc io */
|
|
AM_RANGE(0x0100, 0xffff) AM_READWRITE(spc_ram_100_r, spc_ram_100_w)
|
|
ADDRESS_MAP_END
|
|
|
|
static ADDRESS_MAP_START( dsp_prg_map, AS_PROGRAM, 32, snes_console_state )
|
|
AM_RANGE(0x0000, 0x07ff) AM_ROM AM_REGION("dspprg", 0)
|
|
ADDRESS_MAP_END
|
|
|
|
static ADDRESS_MAP_START( dsp_data_map, AS_DATA, 16, snes_console_state )
|
|
AM_RANGE(0x0000, 0x03ff) AM_ROM AM_REGION("dspdata", 0)
|
|
ADDRESS_MAP_END
|
|
|
|
static ADDRESS_MAP_START( setadsp_prg_map, AS_PROGRAM, 32, snes_console_state )
|
|
AM_RANGE(0x0000, 0x3fff) AM_ROM AM_REGION("dspprg", 0)
|
|
ADDRESS_MAP_END
|
|
|
|
static ADDRESS_MAP_START( setadsp_data_map, AS_DATA, 16, snes_console_state )
|
|
AM_RANGE(0x0000, 0x07ff) AM_ROM AM_REGION("dspdata", 0)
|
|
ADDRESS_MAP_END
|
|
|
|
/*************************************
|
|
*
|
|
* Input ports
|
|
*
|
|
*************************************/
|
|
|
|
CUSTOM_INPUT_MEMBER( snes_console_state::snes_mouse_speed_input )
|
|
{
|
|
int port = (FPTR)param;
|
|
|
|
if (m_oldjoy1_latch & 0x1)
|
|
{
|
|
m_mouse[port].speed++;
|
|
if ((m_mouse[port].speed & 0x03) == 0x03)
|
|
m_mouse[port].speed = 0;
|
|
}
|
|
|
|
return m_mouse[port].speed;
|
|
}
|
|
|
|
CUSTOM_INPUT_MEMBER( snes_console_state::snes_superscope_offscreen_input )
|
|
{
|
|
int port = (FPTR)param;
|
|
static const char *const portnames[2][3] =
|
|
{
|
|
{ "SUPERSCOPE1", "SUPERSCOPE1_X", "SUPERSCOPE1_Y" },
|
|
{ "SUPERSCOPE2", "SUPERSCOPE2_X", "SUPERSCOPE2_Y" },
|
|
};
|
|
|
|
INT16 x = ioport(portnames[port][1])->read();
|
|
INT16 y = ioport(portnames[port][2])->read();
|
|
|
|
/* these are the theoretical boundaries, but we currently are always onscreen... */
|
|
if (x < 0 || x >= SNES_SCR_WIDTH || y < 0 || y >= m_ppu.m_beam.last_visible_line)
|
|
m_scope[port].offscreen = 1;
|
|
else
|
|
m_scope[port].offscreen = 0;
|
|
|
|
return m_scope[port].offscreen;
|
|
}
|
|
|
|
TIMER_CALLBACK_MEMBER( snes_console_state::lightgun_tick )
|
|
{
|
|
if ((ioport("CTRLSEL")->read() & 0x0f) == 0x03 || (ioport("CTRLSEL")->read() & 0x0f) == 0x04) {
|
|
/* enable lightpen crosshair */
|
|
crosshair_set_screen(machine(), 0, CROSSHAIR_SCREEN_ALL);
|
|
}
|
|
else
|
|
{
|
|
/* disable lightpen crosshair */
|
|
crosshair_set_screen(machine(), 0, CROSSHAIR_SCREEN_NONE);
|
|
}
|
|
|
|
if ((ioport("CTRLSEL")->read() & 0xf0) == 0x30 || (ioport("CTRLSEL")->read() & 0xf0) == 0x40)
|
|
{
|
|
/* enable lightpen crosshair */
|
|
crosshair_set_screen(machine(), 1, CROSSHAIR_SCREEN_ALL);
|
|
}
|
|
else
|
|
{
|
|
/* disable lightpen crosshair */
|
|
crosshair_set_screen(machine(), 1, CROSSHAIR_SCREEN_NONE);
|
|
}
|
|
}
|
|
|
|
|
|
static INPUT_PORTS_START( snes_joypads )
|
|
PORT_START("SERIAL1_DATA1_L")
|
|
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("P1 Button A") PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01)
|
|
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("P1 Button X") PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01)
|
|
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("P1 Button L") PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01)
|
|
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_NAME("P1 Button R") PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01)
|
|
PORT_START("SERIAL1_DATA1_H")
|
|
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P1 Button B") PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01)
|
|
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P1 Button Y") PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01)
|
|
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_NAME("P1 Select") PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01)
|
|
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_START1 ) PORT_NAME("P1 Start") PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01)
|
|
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01)
|
|
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01)
|
|
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01)
|
|
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x01)
|
|
|
|
PORT_START("SERIAL2_DATA1_L")
|
|
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("P2 Button A") PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10)
|
|
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("P2 Button X") PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10)
|
|
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("P2 Button L") PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10)
|
|
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_NAME("P2 Button R") PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10)
|
|
PORT_START("SERIAL2_DATA1_H")
|
|
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P2 Button B") PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10)
|
|
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P2 Button Y") PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10)
|
|
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_SELECT ) PORT_NAME("P2 Select") PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10)
|
|
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_START2 ) PORT_NAME("P2 Start") PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10)
|
|
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10)
|
|
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10)
|
|
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10)
|
|
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x10)
|
|
|
|
PORT_START("SERIAL1_DATA2_L")
|
|
PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED )
|
|
PORT_START("SERIAL1_DATA2_H")
|
|
PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED )
|
|
|
|
PORT_START("SERIAL2_DATA2_L")
|
|
PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED )
|
|
PORT_START("SERIAL2_DATA2_H")
|
|
PORT_BIT( 0xff, IP_ACTIVE_HIGH, IPT_UNUSED )
|
|
INPUT_PORTS_END
|
|
|
|
static INPUT_PORTS_START( snes_mouse )
|
|
PORT_START("MOUSE1")
|
|
/* bits 0,3 = mouse signature (must be 1) */
|
|
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
|
|
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED )
|
|
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED )
|
|
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED )
|
|
/* bits 4,5 = mouse speed: 0 = slow, 1 = normal, 2 = fast, 3 = unused */
|
|
PORT_BIT( 0x30, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, snes_console_state, snes_mouse_speed_input, (void *)0)
|
|
/* bits 6,7 = mouse buttons */
|
|
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P1 Mouse Button Left") PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x02)
|
|
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P1 Mouse Button Right") PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x02)
|
|
|
|
PORT_START("MOUSE1_X")
|
|
PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x02)
|
|
|
|
PORT_START("MOUSE1_Y")
|
|
PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x02)
|
|
|
|
PORT_START("MOUSE2")
|
|
/* bits 0,3 = mouse signature (must be 1) */
|
|
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
|
|
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_UNUSED )
|
|
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED )
|
|
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED )
|
|
/* bits 4,5 = mouse speed: 0 = slow, 1 = normal, 2 = fast, 3 = unused */
|
|
PORT_BIT( 0x30, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, snes_console_state, snes_mouse_speed_input, (void *)1)
|
|
/* bits 6,7 = mouse buttons */
|
|
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P2 Mouse Button Left") PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x20)
|
|
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P2 Mouse Button Right") PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x20)
|
|
|
|
PORT_START("MOUSE2_X")
|
|
PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x20)
|
|
|
|
PORT_START("MOUSE2_Y")
|
|
PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x20)
|
|
INPUT_PORTS_END
|
|
|
|
static INPUT_PORTS_START( snes_superscope )
|
|
PORT_START("SUPERSCOPE1")
|
|
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) // Noise
|
|
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, snes_console_state, snes_superscope_offscreen_input, (void *)0)
|
|
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED )
|
|
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED )
|
|
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("Port1 Superscope Pause") PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x03)
|
|
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("Port1 Superscope Turbo") PORT_TOGGLE PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x03)
|
|
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Port1 Superscope Cursor") PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x03)
|
|
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Port1 Superscope Fire") PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x03)
|
|
|
|
PORT_START("SUPERSCOPE1_X")
|
|
PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X ) PORT_NAME("Port1 Superscope X Axis") PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(25) PORT_KEYDELTA(15) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x03)
|
|
|
|
PORT_START("SUPERSCOPE1_Y")
|
|
PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y) PORT_NAME("Port1 Superscope Y Axis") PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(25) PORT_KEYDELTA(15) PORT_PLAYER(1) PORT_CONDITION("CTRLSEL", 0x0f, EQUALS, 0x03)
|
|
|
|
PORT_START("SUPERSCOPE2")
|
|
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_UNUSED ) // Noise
|
|
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, snes_console_state, snes_superscope_offscreen_input, (void *)1)
|
|
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_UNUSED )
|
|
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNUSED )
|
|
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("Port2 Superscope Pause") PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x30)
|
|
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("Port2 Superscope Turbo") PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x30)
|
|
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("Port2 Superscope Cursor") PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x30)
|
|
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("Port2 Superscope Fire") PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x30)
|
|
|
|
PORT_START("SUPERSCOPE2_X")
|
|
PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X ) PORT_NAME("Port2 Superscope X Axis") PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(25) PORT_KEYDELTA(15) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x30)
|
|
|
|
PORT_START("SUPERSCOPE2_Y")
|
|
PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y) PORT_NAME("Port2 Superscope Y Axis") PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(25) PORT_KEYDELTA(15) PORT_PLAYER(2) PORT_CONDITION("CTRLSEL", 0xf0, EQUALS, 0x30)
|
|
INPUT_PORTS_END
|
|
|
|
static INPUT_PORTS_START( snes )
|
|
PORT_START("CTRLSEL") /* Select Controller Type */
|
|
PORT_CONFNAME( 0x0f, 0x01, "P1 Controller")
|
|
PORT_CONFSETTING( 0x00, "Unconnected" )
|
|
PORT_CONFSETTING( 0x01, "Gamepad" )
|
|
PORT_CONFSETTING( 0x02, "Mouse" )
|
|
PORT_CONFSETTING( 0x03, "Superscope" )
|
|
// PORT_CONFSETTING( 0x04, "Justfier" )
|
|
// PORT_CONFSETTING( 0x05, "Multitap" )
|
|
PORT_CONFNAME( 0xf0, 0x10, "P2 Controller")
|
|
PORT_CONFSETTING( 0x00, "Unconnected" )
|
|
PORT_CONFSETTING( 0x10, "Gamepad" )
|
|
PORT_CONFSETTING( 0x20, "Mouse" )
|
|
PORT_CONFSETTING( 0x30, "Superscope" )
|
|
// PORT_CONFSETTING( 0x40, "Justfier" )
|
|
// PORT_CONFSETTING( 0x50, "Multitap" )
|
|
|
|
PORT_INCLUDE(snes_joypads)
|
|
PORT_INCLUDE(snes_mouse)
|
|
PORT_INCLUDE(snes_superscope)
|
|
|
|
PORT_START("OPTIONS")
|
|
PORT_CONFNAME( 0x01, 0x00, "Hi-Res pixels blurring (TV effect)")
|
|
PORT_CONFSETTING( 0x00, DEF_STR( Off ) )
|
|
PORT_CONFSETTING( 0x01, DEF_STR( On ) )
|
|
|
|
#if SNES_LAYER_DEBUG
|
|
PORT_START("DEBUG1")
|
|
PORT_CONFNAME( 0x03, 0x00, "Select BG1 priority" )
|
|
PORT_CONFSETTING( 0x00, "All" )
|
|
PORT_CONFSETTING( 0x01, "BG1B (lower) only" )
|
|
PORT_CONFSETTING( 0x02, "BG1A (higher) only" )
|
|
PORT_CONFNAME( 0x0c, 0x00, "Select BG2 priority" )
|
|
PORT_CONFSETTING( 0x00, "All" )
|
|
PORT_CONFSETTING( 0x04, "BG2B (lower) only" )
|
|
PORT_CONFSETTING( 0x08, "BG2A (higher) only" )
|
|
PORT_CONFNAME( 0x30, 0x00, "Select BG3 priority" )
|
|
PORT_CONFSETTING( 0x00, "All" )
|
|
PORT_CONFSETTING( 0x10, "BG3B (lower) only" )
|
|
PORT_CONFSETTING( 0x20, "BG3A (higher) only" )
|
|
PORT_CONFNAME( 0xc0, 0x00, "Select BG4 priority" )
|
|
PORT_CONFSETTING( 0x00, "All" )
|
|
PORT_CONFSETTING( 0x40, "BG4B (lower) only" )
|
|
PORT_CONFSETTING( 0x80, "BG4A (higher) only" )
|
|
|
|
PORT_START("DEBUG2")
|
|
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle BG 1") PORT_CODE(KEYCODE_1_PAD) PORT_TOGGLE
|
|
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle BG 2") PORT_CODE(KEYCODE_2_PAD) PORT_TOGGLE
|
|
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle BG 3") PORT_CODE(KEYCODE_3_PAD) PORT_TOGGLE
|
|
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle BG 4") PORT_CODE(KEYCODE_4_PAD) PORT_TOGGLE
|
|
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Objects") PORT_CODE(KEYCODE_5_PAD) PORT_TOGGLE
|
|
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Main/Sub") PORT_CODE(KEYCODE_6_PAD) PORT_TOGGLE
|
|
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Color Math") PORT_CODE(KEYCODE_7_PAD) PORT_TOGGLE
|
|
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Windows") PORT_CODE(KEYCODE_8_PAD) PORT_TOGGLE
|
|
|
|
PORT_START("DEBUG3")
|
|
PORT_BIT( 0x4, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Mosaic") PORT_CODE(KEYCODE_9_PAD) PORT_TOGGLE
|
|
PORT_CONFNAME( 0x70, 0x00, "Select OAM priority" )
|
|
PORT_CONFSETTING( 0x00, "All" )
|
|
PORT_CONFSETTING( 0x10, "OAM0 only" )
|
|
PORT_CONFSETTING( 0x20, "OAM1 only" )
|
|
PORT_CONFSETTING( 0x30, "OAM2 only" )
|
|
PORT_CONFSETTING( 0x40, "OAM3 only" )
|
|
PORT_CONFNAME( 0x80, 0x00, "Draw sprite in reverse order" )
|
|
PORT_CONFSETTING( 0x00, DEF_STR( Off ) )
|
|
PORT_CONFSETTING( 0x80, DEF_STR( On ) )
|
|
|
|
PORT_START("DEBUG4")
|
|
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Mode 0 draw") PORT_TOGGLE
|
|
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Mode 1 draw") PORT_TOGGLE
|
|
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Mode 2 draw") PORT_TOGGLE
|
|
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Mode 3 draw") PORT_TOGGLE
|
|
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Mode 4 draw") PORT_TOGGLE
|
|
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Mode 5 draw") PORT_TOGGLE
|
|
PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Mode 6 draw") PORT_TOGGLE
|
|
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("Toggle Mode 7 draw") PORT_TOGGLE
|
|
#endif
|
|
INPUT_PORTS_END
|
|
|
|
|
|
/*************************************
|
|
*
|
|
* Input callbacks
|
|
*
|
|
*************************************/
|
|
|
|
void snes_console_state::snes_gun_latch( INT16 x, INT16 y )
|
|
{
|
|
/* these are the theoretical boundaries */
|
|
if (x < 0)
|
|
x = 0;
|
|
if (x > (SNES_SCR_WIDTH - 1))
|
|
x = SNES_SCR_WIDTH - 1;
|
|
|
|
if (y < 0)
|
|
y = 0;
|
|
if (y > (m_ppu.m_beam.last_visible_line - 1))
|
|
y = m_ppu.m_beam.last_visible_line - 1;
|
|
|
|
m_ppu.m_beam.latch_horz = x;
|
|
m_ppu.m_beam.latch_vert = y;
|
|
m_ppu.m_stat78 |= 0x40;
|
|
}
|
|
|
|
void snes_console_state::snes_input_read_joy( int port )
|
|
{
|
|
static const char *const portnames[2][4] =
|
|
{
|
|
{ "SERIAL1_DATA1_L", "SERIAL1_DATA1_H", "SERIAL1_DATA2_L", "SERIAL1_DATA2_H" },
|
|
{ "SERIAL2_DATA1_L", "SERIAL2_DATA1_H", "SERIAL2_DATA2_L", "SERIAL2_DATA2_H" },
|
|
};
|
|
|
|
m_data1[port] = ioport(portnames[port][0])->read() | (ioport(portnames[port][1])->read() << 8);
|
|
m_data2[port] = ioport(portnames[port][2])->read() | (ioport(portnames[port][3])->read() << 8);
|
|
|
|
// avoid sending signals that could crash games
|
|
// if left, no right
|
|
if (m_data1[port] & 0x200)
|
|
m_data1[port] &= ~0x100;
|
|
// if up, no down
|
|
if (m_data1[port] & 0x800)
|
|
m_data1[port] &= ~0x400;
|
|
|
|
m_joypad[port].buttons = m_data1[port];
|
|
}
|
|
|
|
void snes_console_state::snes_input_read_mouse( int port )
|
|
{
|
|
INT16 var;
|
|
static const char *const portnames[2][3] =
|
|
{
|
|
{ "MOUSE1", "MOUSE1_X", "MOUSE1_Y" },
|
|
{ "MOUSE2", "MOUSE2_X", "MOUSE2_Y" },
|
|
};
|
|
|
|
m_mouse[port].buttons = ioport(portnames[port][0])->read();
|
|
m_mouse[port].x = ioport(portnames[port][1])->read();
|
|
m_mouse[port].y = ioport(portnames[port][2])->read();
|
|
var = m_mouse[port].x - m_mouse[port].oldx;
|
|
|
|
if (var < -127)
|
|
{
|
|
m_mouse[port].deltax = 0xff;
|
|
m_mouse[port].oldx -= 127;
|
|
}
|
|
else if (var < 0)
|
|
{
|
|
m_mouse[port].deltax = 0x80 | (-var);
|
|
m_mouse[port].oldx = m_mouse[port].x;
|
|
}
|
|
else if (var > 127)
|
|
{
|
|
m_mouse[port].deltax = 0x7f;
|
|
m_mouse[port].oldx += 127;
|
|
}
|
|
else
|
|
{
|
|
m_mouse[port].deltax = var & 0xff;
|
|
m_mouse[port].oldx = m_mouse[port].x;
|
|
}
|
|
|
|
var = m_mouse[port].y - m_mouse[port].oldy;
|
|
|
|
if (var < -127)
|
|
{
|
|
m_mouse[port].deltay = 0xff;
|
|
m_mouse[port].oldy -= 127;
|
|
}
|
|
else if (var < 0)
|
|
{
|
|
m_mouse[port].deltay = 0x80 | (-var);
|
|
m_mouse[port].oldy = m_mouse[port].y;
|
|
}
|
|
else if (var > 127)
|
|
{
|
|
m_mouse[port].deltay = 0x7f;
|
|
m_mouse[port].oldy += 127;
|
|
}
|
|
else
|
|
{
|
|
m_mouse[port].deltay = var & 0xff;
|
|
m_mouse[port].oldy = m_mouse[port].y;
|
|
}
|
|
|
|
m_data1[port] = m_mouse[port].buttons | (0x00 << 8);
|
|
m_data2[port] = 0;
|
|
}
|
|
|
|
void snes_console_state::snes_input_read_superscope( int port )
|
|
{
|
|
static const char *const portnames[2][3] =
|
|
{
|
|
{ "SUPERSCOPE1", "SUPERSCOPE1_X", "SUPERSCOPE1_Y" },
|
|
{ "SUPERSCOPE2", "SUPERSCOPE2_X", "SUPERSCOPE2_Y" },
|
|
};
|
|
UINT8 input;
|
|
|
|
/* first read input bits */
|
|
m_scope[port].x = ioport(portnames[port][1])->read();
|
|
m_scope[port].y = ioport(portnames[port][2])->read();
|
|
input = ioport(portnames[port][0])->read();
|
|
|
|
/* then start elaborating input bits: only keep old turbo value */
|
|
m_scope[port].buttons &= 0x20;
|
|
|
|
/* set onscreen/offscreen */
|
|
m_scope[port].buttons |= BIT(input, 1);
|
|
|
|
/* turbo is a switch; toggle is edge sensitive */
|
|
if (BIT(input, 5) && !m_scope[port].turbo_lock)
|
|
{
|
|
m_scope[port].buttons ^= 0x20;
|
|
m_scope[port].turbo_lock = 1;
|
|
}
|
|
else if (!BIT(input, 5))
|
|
m_scope[port].turbo_lock = 0;
|
|
|
|
/* fire is a button; if turbo is active, trigger is level sensitive; otherwise it is edge sensitive */
|
|
if (BIT(input, 7) && (BIT(m_scope[port].buttons, 5) || !m_scope[port].fire_lock))
|
|
{
|
|
m_scope[port].buttons |= 0x80;
|
|
m_scope[port].fire_lock = 1;
|
|
}
|
|
else if (!BIT(input, 7))
|
|
m_scope[port].fire_lock = 0;
|
|
|
|
/* cursor is a button; it is always level sensitive */
|
|
m_scope[port].buttons |= BIT(input, 6);
|
|
|
|
/* pause is a button; it is always edge sensitive */
|
|
if (BIT(input, 4) && !m_scope[port].pause_lock)
|
|
{
|
|
m_scope[port].buttons |= 0x10;
|
|
m_scope[port].pause_lock = 1;
|
|
}
|
|
else if (!BIT(input, 4))
|
|
m_scope[port].pause_lock = 0;
|
|
|
|
/* If we have pressed fire or cursor and we are on-screen and SuperScope is in Port2, then latch video signal.
|
|
Notice that we only latch Port2 because its IOBit pin is connected to bit7 of the IO Port, while Port1 has
|
|
IOBit pin connected to bit6 of the IO Port, and the latter is not detected by the H/V Counters. In other
|
|
words, you can connect SuperScope to Port1, but there is no way SNES could detect its on-screen position */
|
|
if ((m_scope[port].buttons & 0xc0) && !(m_scope[port].buttons & 0x02) && port == 1)
|
|
snes_gun_latch(m_scope[port].x, m_scope[port].y);
|
|
|
|
m_data1[port] = 0xff | (m_scope[port].buttons << 8);
|
|
m_data2[port] = 0;
|
|
}
|
|
|
|
WRITE8_MEMBER(snes_console_state::snes_input_read)
|
|
{
|
|
UINT8 ctrl1 = ioport("CTRLSEL")->read() & 0x0f;
|
|
UINT8 ctrl2 = (ioport("CTRLSEL")->read() & 0xf0) >> 4;
|
|
|
|
/* Check if lightgun has been chosen as input: if so, enable crosshair */
|
|
machine().scheduler().timer_set(attotime::zero, timer_expired_delegate(FUNC(snes_console_state::lightgun_tick),this));
|
|
|
|
switch (ctrl1)
|
|
{
|
|
case 1: /* SNES joypad */
|
|
snes_input_read_joy(0);
|
|
break;
|
|
case 2: /* SNES Mouse */
|
|
snes_input_read_mouse(0);
|
|
break;
|
|
case 3: /* SNES Superscope */
|
|
snes_input_read_superscope(0);
|
|
break;
|
|
case 0: /* no controller in port1 */
|
|
default:
|
|
m_data1[0] = 0;
|
|
m_data2[0] = 0;
|
|
break;
|
|
}
|
|
|
|
switch (ctrl2)
|
|
{
|
|
case 1: /* SNES joypad */
|
|
snes_input_read_joy(1);
|
|
break;
|
|
case 2: /* SNES Mouse */
|
|
snes_input_read_mouse(1);
|
|
break;
|
|
case 3: /* SNES Superscope */
|
|
snes_input_read_superscope(1);
|
|
break;
|
|
case 0: /* no controller in port2 */
|
|
default:
|
|
m_data1[1] = 0;
|
|
m_data2[1] = 0;
|
|
break;
|
|
}
|
|
|
|
// is automatic reading on? if so, copy port data1/data2 to joy1l->joy4h
|
|
// this actually works like reading the first 16bits from oldjoy1/2 in reverse order
|
|
if (SNES_CPU_REG(NMITIMEN) & 1)
|
|
{
|
|
SNES_CPU_REG(JOY1L) = (m_data1[0] & 0x00ff) >> 0;
|
|
SNES_CPU_REG(JOY1H) = (m_data1[0] & 0xff00) >> 8;
|
|
SNES_CPU_REG(JOY2L) = (m_data1[1] & 0x00ff) >> 0;
|
|
SNES_CPU_REG(JOY2H) = (m_data1[1] & 0xff00) >> 8;
|
|
SNES_CPU_REG(JOY3L) = (m_data2[0] & 0x00ff) >> 0;
|
|
SNES_CPU_REG(JOY3H) = (m_data2[0] & 0xff00) >> 8;
|
|
SNES_CPU_REG(JOY4L) = (m_data2[1] & 0x00ff) >> 0;
|
|
SNES_CPU_REG(JOY4H) = (m_data2[1] & 0xff00) >> 8;
|
|
|
|
// make sure read_idx starts returning all 1s because the auto-read reads it :-)
|
|
m_read_idx[0] = 16;
|
|
m_read_idx[1] = 16;
|
|
}
|
|
|
|
}
|
|
|
|
READ8_MEMBER(snes_console_state::snes_oldjoy1_read)
|
|
{
|
|
UINT8 ctrl1 = ioport("CTRLSEL")->read() & 0x0f;
|
|
UINT8 res = 0;
|
|
|
|
switch (ctrl1)
|
|
{
|
|
case 1: /* SNES joypad */
|
|
if (m_read_idx[0] >= 16)
|
|
res = 0x01;
|
|
else
|
|
res = (m_joypad[0].buttons >> (15 - m_read_idx[0]++)) & 0x01;
|
|
break;
|
|
case 2: /* SNES Mouse */
|
|
if (m_read_idx[0] >= 32)
|
|
res = 0x01;
|
|
else if (m_read_idx[0] >= 24)
|
|
res = (m_mouse[0].deltax >> (31 - m_read_idx[0]++)) & 0x01;
|
|
else if (m_read_idx[0] >= 16)
|
|
res = (m_mouse[0].deltay >> (23 - m_read_idx[0]++)) & 0x01;
|
|
else if (m_read_idx[0] >= 8)
|
|
res = (m_mouse[0].buttons >> (15 - m_read_idx[0]++)) & 0x01;
|
|
else
|
|
res = 0;
|
|
break;
|
|
case 3: /* SNES Superscope */
|
|
if (m_read_idx[0] >= 8)
|
|
res = 0x01;
|
|
else
|
|
res = (m_scope[0].buttons >> (7 - m_read_idx[0]++)) & 0x01;
|
|
break;
|
|
case 0: /* no controller in port2 */
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
READ8_MEMBER(snes_console_state::snes_oldjoy2_read)
|
|
{
|
|
UINT8 ctrl2 = (ioport("CTRLSEL")->read() & 0xf0) >> 4;
|
|
UINT8 res = 0;
|
|
|
|
switch (ctrl2)
|
|
{
|
|
case 1: /* SNES joypad */
|
|
if (m_read_idx[1] >= 16)
|
|
res = 0x01;
|
|
else
|
|
res = (m_joypad[1].buttons >> (15 - m_read_idx[1]++)) & 0x01;
|
|
break;
|
|
case 2: /* SNES Mouse */
|
|
if (m_read_idx[1] >= 32)
|
|
res = 0x01;
|
|
else if (m_read_idx[1] >= 24)
|
|
res = (m_mouse[1].deltax >> (31 - m_read_idx[1]++)) & 0x01;
|
|
else if (m_read_idx[1] >= 16)
|
|
res = (m_mouse[1].deltay >> (23 - m_read_idx[1]++)) & 0x01;
|
|
else if (m_read_idx[1] >= 8)
|
|
res = (m_mouse[1].buttons >> (15 - m_read_idx[1]++)) & 0x01;
|
|
else
|
|
res = 0;
|
|
break;
|
|
case 3: /* SNES Superscope */
|
|
if (m_read_idx[1] >= 8)
|
|
res = 0x01;
|
|
else
|
|
res = (m_scope[1].buttons >> (7 - m_read_idx[1]++)) & 0x01;
|
|
break;
|
|
case 0: /* no controller in port2 */
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
/*************************************
|
|
*
|
|
* Machine driver
|
|
*
|
|
*************************************/
|
|
|
|
static MACHINE_START( snes_mess )
|
|
{
|
|
snes_console_state *state = machine.driver_data<snes_console_state>();
|
|
|
|
machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(snes_machine_stop),&machine));
|
|
MACHINE_START_CALL(snes);
|
|
|
|
switch (state->m_has_addon_chip)
|
|
{
|
|
case HAS_SDD1:
|
|
sdd1_init(machine);
|
|
break;
|
|
case HAS_SPC7110:
|
|
spc7110_init(machine);
|
|
break;
|
|
case HAS_SPC7110_RTC:
|
|
spc7110rtc_init(machine);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static MACHINE_START( snesst )
|
|
{
|
|
machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(sufami_machine_stop),&machine));
|
|
MACHINE_START_CALL(snes);
|
|
}
|
|
|
|
static MACHINE_RESET( snes_mess )
|
|
{
|
|
snes_console_state *state = machine.driver_data<snes_console_state>();
|
|
|
|
MACHINE_RESET_CALL(snes);
|
|
|
|
state->m_io_read = write8_delegate(FUNC(snes_console_state::snes_input_read),state);
|
|
state->m_oldjoy1_read = read8_delegate(FUNC(snes_console_state::snes_oldjoy1_read),state);
|
|
state->m_oldjoy2_read = read8_delegate(FUNC(snes_console_state::snes_oldjoy2_read),state);
|
|
|
|
// see if there's a uPD7725 DSP in the machine config
|
|
state->m_upd7725 = machine.device<upd7725_device>("dsp");
|
|
|
|
// if we have a DSP, halt it for the moment
|
|
if (state->m_upd7725)
|
|
machine.device("dsp")->execute().set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
|
|
|
|
// ditto for a uPD96050 (Seta ST-010 or ST-011)
|
|
state->m_upd96050 = machine.device<upd96050_device>("setadsp");
|
|
if (state->m_upd96050)
|
|
machine.device("setadsp")->execute().set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
|
|
|
|
switch (state->m_has_addon_chip)
|
|
{
|
|
case HAS_DSP1:
|
|
case HAS_DSP2:
|
|
case HAS_DSP3:
|
|
case HAS_DSP4:
|
|
// cartridge uses the DSP, let 'er rip
|
|
if (state->m_upd7725)
|
|
machine.device("dsp")->execute().set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
|
|
else
|
|
{
|
|
logerror("SNES: Game uses a DSP, but the machine driver is missing the uPD7725!\n");
|
|
state->m_has_addon_chip = HAS_NONE; // prevent crash trying to access NULL device
|
|
}
|
|
break;
|
|
|
|
case HAS_RTC:
|
|
srtc_init(machine);
|
|
break;
|
|
|
|
case HAS_OBC1:
|
|
obc1_init(machine);
|
|
break;
|
|
|
|
case HAS_ST010:
|
|
case HAS_ST011:
|
|
// cartridge uses the DSP, let 'er rip
|
|
if (state->m_upd96050)
|
|
machine.device("setadsp")->execute().set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
|
|
else
|
|
{
|
|
logerror("SNES: Game uses a Seta DSP, but the machine driver is missing the uPD96050!\n");
|
|
state->m_has_addon_chip = HAS_NONE; // prevent crash trying to access NULL device
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static MACHINE_CONFIG_START( snes_base, snes_console_state )
|
|
|
|
/* basic machine hardware */
|
|
MCFG_CPU_ADD("maincpu", _5A22, MCLK_NTSC) /* 2.68 MHz, also 3.58 MHz */
|
|
MCFG_CPU_PROGRAM_MAP(snes_map)
|
|
|
|
MCFG_CPU_ADD("soundcpu", SPC700, 1024000) /* 1.024 MHz */
|
|
MCFG_CPU_PROGRAM_MAP(spc_map)
|
|
|
|
//MCFG_QUANTUM_TIME(attotime::from_hz(48000))
|
|
MCFG_QUANTUM_PERFECT_CPU("maincpu")
|
|
|
|
MCFG_MACHINE_START(snes_mess)
|
|
MCFG_MACHINE_RESET(snes_mess)
|
|
|
|
/* video hardware */
|
|
MCFG_VIDEO_START(snes)
|
|
|
|
MCFG_SCREEN_ADD("screen", RASTER)
|
|
MCFG_SCREEN_RAW_PARAMS(DOTCLK_NTSC * 2, SNES_HTOTAL * 2, 0, SNES_SCR_WIDTH * 2, SNES_VTOTAL_NTSC, 0, SNES_SCR_HEIGHT_NTSC)
|
|
MCFG_SCREEN_UPDATE_DRIVER( snes_state, screen_update )
|
|
|
|
/* sound hardware */
|
|
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
|
|
MCFG_SOUND_ADD("spc700", SNES, 0)
|
|
MCFG_SOUND_ROUTE(0, "lspeaker", 1.00)
|
|
MCFG_SOUND_ROUTE(1, "rspeaker", 1.00)
|
|
MACHINE_CONFIG_END
|
|
|
|
static MACHINE_CONFIG_DERIVED( snes, snes_base )
|
|
|
|
MCFG_FRAGMENT_ADD(snes_cartslot)
|
|
MACHINE_CONFIG_END
|
|
|
|
|
|
static SUPERFX_CONFIG( snes_superfx_config )
|
|
{
|
|
DEVCB_DRIVER_LINE_MEMBER(snes_state,snes_extern_irq_w) /* IRQ line from cart */
|
|
};
|
|
|
|
static MACHINE_CONFIG_DERIVED( snessfx, snes )
|
|
|
|
MCFG_CPU_ADD("superfx", SUPERFX, 21480000) /* 21.48MHz */
|
|
MCFG_CPU_PROGRAM_MAP(superfx_map)
|
|
MCFG_CPU_CONFIG(snes_superfx_config)
|
|
MACHINE_CONFIG_END
|
|
|
|
static MACHINE_CONFIG_DERIVED( snesdsp, snes )
|
|
|
|
MCFG_CPU_ADD("dsp", UPD7725, 8000000)
|
|
MCFG_CPU_PROGRAM_MAP(dsp_prg_map)
|
|
MCFG_CPU_DATA_MAP(dsp_data_map)
|
|
MACHINE_CONFIG_END
|
|
|
|
static MACHINE_CONFIG_DERIVED( snesst10, snes )
|
|
|
|
MCFG_CPU_ADD("setadsp", UPD96050, 10000000)
|
|
MCFG_CPU_PROGRAM_MAP(setadsp_prg_map)
|
|
MCFG_CPU_DATA_MAP(setadsp_data_map)
|
|
MACHINE_CONFIG_END
|
|
|
|
static MACHINE_CONFIG_DERIVED( snesst11, snes )
|
|
|
|
MCFG_CPU_ADD("setadsp", UPD96050, 15000000)
|
|
MCFG_CPU_PROGRAM_MAP(setadsp_prg_map)
|
|
MCFG_CPU_DATA_MAP(setadsp_data_map)
|
|
MACHINE_CONFIG_END
|
|
|
|
static MACHINE_CONFIG_DERIVED( snespal, snes_base )
|
|
MCFG_CPU_MODIFY( "maincpu" )
|
|
MCFG_CPU_CLOCK( MCLK_PAL )
|
|
|
|
MCFG_SCREEN_MODIFY("screen")
|
|
MCFG_SCREEN_RAW_PARAMS(DOTCLK_PAL, SNES_HTOTAL, 0, SNES_SCR_WIDTH, SNES_VTOTAL_PAL, 0, SNES_SCR_HEIGHT_PAL)
|
|
|
|
MCFG_FRAGMENT_ADD(snesp_cartslot)
|
|
MACHINE_CONFIG_END
|
|
|
|
static MACHINE_CONFIG_DERIVED( snespsfx, snespal )
|
|
|
|
MCFG_CPU_ADD("superfx", SUPERFX, 21480000) /* 21.48MHz */
|
|
MCFG_CPU_PROGRAM_MAP(superfx_map)
|
|
MCFG_CPU_CONFIG(snes_superfx_config)
|
|
MACHINE_CONFIG_END
|
|
|
|
static MACHINE_CONFIG_DERIVED( snespdsp, snespal )
|
|
|
|
MCFG_CPU_ADD("dsp", UPD7725, 8000000)
|
|
MCFG_CPU_PROGRAM_MAP(dsp_prg_map)
|
|
MCFG_CPU_DATA_MAP(dsp_data_map)
|
|
MACHINE_CONFIG_END
|
|
|
|
static MACHINE_CONFIG_DERIVED( snesst, snes_base )
|
|
|
|
MCFG_MACHINE_START(snesst)
|
|
|
|
MCFG_FRAGMENT_ADD(sufami_cartslot)
|
|
MACHINE_CONFIG_END
|
|
|
|
|
|
/*************************************
|
|
*
|
|
* ROM definition(s)
|
|
*
|
|
*************************************/
|
|
|
|
ROM_START( snes )
|
|
ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
|
|
|
|
ROM_REGION( 0x100, "sound_ipl", 0 ) /* IPL ROM */
|
|
ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) ) /* boot rom */
|
|
|
|
ROM_REGION( 0x10000, "addons", ROMREGION_ERASE00 ) /* add-on chip ROMs (DSP, SFX, etc) */
|
|
|
|
ROM_REGION( MAX_SNES_CART_SIZE, "cart", ROMREGION_ERASE00 )
|
|
ROM_REGION( 0x2000, "dspprg", ROMREGION_ERASEFF)
|
|
ROM_REGION( 0x800, "dspdata", ROMREGION_ERASEFF)
|
|
ROM_END
|
|
|
|
ROM_START( snesdsp )
|
|
ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
|
|
|
|
ROM_REGION( 0x100, "sound_ipl", 0 ) /* IPL ROM */
|
|
ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) ) /* boot rom */
|
|
|
|
ROM_REGION( 0x10000, "addons", 0 ) /* add-on chip ROMs (DSP, SFX, etc) */
|
|
ROM_LOAD( "dsp1b.bin", SNES_DSP1B_OFFSET, 0x002800, CRC(453557e0) SHA1(3a218b0e4572a8eba6d0121b17fdac9529609220) )
|
|
ROM_LOAD( "dsp1.bin", SNES_DSP1_OFFSET, 0x002800, CRC(2838f9f5) SHA1(0a03ccb1fd2bea91151c745a4d1f217ae784f889) )
|
|
ROM_LOAD( "dsp2.bin", SNES_DSP2_OFFSET, 0x002800, CRC(8e9fbd9b) SHA1(06dd9fcb118d18f6bbe234e013cb8780e06d6e63) )
|
|
ROM_LOAD( "dsp3.bin", SNES_DSP3_OFFSET, 0x002800, CRC(6b86728a) SHA1(1b133741fad810eb7320c21ecfdd427d25a46da1) )
|
|
ROM_LOAD( "dsp4.bin", SNES_DSP4_OFFSET, 0x002800, CRC(ce0c7783) SHA1(76fd25f7dc26c3b3f7868a3aa78c7684068713e5) )
|
|
|
|
ROM_REGION( MAX_SNES_CART_SIZE, "cart", ROMREGION_ERASE00 )
|
|
ROM_REGION( 0x2000, "dspprg", ROMREGION_ERASEFF)
|
|
ROM_REGION( 0x800, "dspdata", ROMREGION_ERASEFF)
|
|
ROM_END
|
|
|
|
ROM_START( snesst10 )
|
|
ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
|
|
|
|
ROM_REGION( 0x100, "sound_ipl", 0 ) /* IPL ROM */
|
|
ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) ) /* boot rom */
|
|
|
|
ROM_REGION( 0x11000, "addons", 0 ) /* add-on chip ROMs (DSP, SFX, etc) */
|
|
ROM_LOAD( "st010.bin", 0x000000, 0x011000, CRC(aa11ee2d) SHA1(cc1984e989cb94e3dcbb5f99e085b5414e18a017) )
|
|
|
|
ROM_REGION( MAX_SNES_CART_SIZE, "cart", ROMREGION_ERASE00 )
|
|
ROM_REGION( 0x10000, "dspprg", ROMREGION_ERASEFF)
|
|
ROM_REGION( 0x1000, "dspdata", ROMREGION_ERASEFF)
|
|
ROM_END
|
|
|
|
ROM_START( snesst11 )
|
|
ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
|
|
|
|
ROM_REGION( 0x100, "sound_ipl", 0 ) /* IPL ROM */
|
|
ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) ) /* boot rom */
|
|
|
|
ROM_REGION( 0x11000, "addons", 0 ) /* add-on chip ROMs (DSP, SFX, etc) */
|
|
ROM_LOAD( "st011.bin", 0x000000, 0x011000, CRC(34d2952c) SHA1(1375b8c1efc8cae4962b57dfe22f6b78e1ddacc8) )
|
|
|
|
ROM_REGION( MAX_SNES_CART_SIZE, "cart", ROMREGION_ERASE00 )
|
|
ROM_REGION( 0x10000, "dspprg", ROMREGION_ERASEFF)
|
|
ROM_REGION( 0x1000, "dspdata", ROMREGION_ERASEFF)
|
|
ROM_END
|
|
|
|
ROM_START( snessfx )
|
|
ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
|
|
|
|
ROM_REGION( 0x100, "sound_ipl", 0 ) /* IPL ROM */
|
|
ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) ) /* boot rom */
|
|
|
|
ROM_REGION( 0x10000, "addons", ROMREGION_ERASE00 ) /* add-on chip ROMs (DSP, SFX, etc) */
|
|
|
|
ROM_REGION( MAX_SNES_CART_SIZE, "cart", ROMREGION_ERASE00 )
|
|
ROM_REGION( 0x2000, "dspprg", ROMREGION_ERASEFF)
|
|
ROM_REGION( 0x800, "dspdata", ROMREGION_ERASEFF)
|
|
ROM_END
|
|
|
|
ROM_START( snespal )
|
|
ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
|
|
|
|
ROM_REGION( 0x100, "sound_ipl", 0 ) /* IPL ROM */
|
|
ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) ) /* boot rom */
|
|
|
|
ROM_REGION( 0x10000, "addons", ROMREGION_ERASE00 ) /* add-on chip ROMs (DSP, SFX, etc) */
|
|
|
|
ROM_REGION( MAX_SNES_CART_SIZE, "cart", ROMREGION_ERASE00 )
|
|
ROM_REGION( 0x2000, "dspprg", ROMREGION_ERASEFF)
|
|
ROM_REGION( 0x800, "dspdata", ROMREGION_ERASEFF)
|
|
ROM_END
|
|
|
|
ROM_START( snespdsp )
|
|
ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
|
|
|
|
ROM_REGION( 0x100, "sound_ipl", 0 ) /* IPL ROM */
|
|
ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) ) /* boot rom */
|
|
|
|
ROM_REGION( 0x10000, "addons", 0 ) /* add-on chip ROMs (DSP, SFX, etc) */
|
|
ROM_LOAD( "dsp1b.bin", SNES_DSP1B_OFFSET, 0x002800, CRC(453557e0) SHA1(3a218b0e4572a8eba6d0121b17fdac9529609220) )
|
|
ROM_LOAD( "dsp1.bin", SNES_DSP1_OFFSET, 0x002800, CRC(2838f9f5) SHA1(0a03ccb1fd2bea91151c745a4d1f217ae784f889) )
|
|
ROM_LOAD( "dsp2.bin", SNES_DSP2_OFFSET, 0x002800, CRC(8e9fbd9b) SHA1(06dd9fcb118d18f6bbe234e013cb8780e06d6e63) )
|
|
ROM_LOAD( "dsp3.bin", SNES_DSP3_OFFSET, 0x002800, CRC(6b86728a) SHA1(1b133741fad810eb7320c21ecfdd427d25a46da1) )
|
|
ROM_LOAD( "dsp4.bin", SNES_DSP4_OFFSET, 0x002800, CRC(ce0c7783) SHA1(76fd25f7dc26c3b3f7868a3aa78c7684068713e5) )
|
|
|
|
ROM_REGION( MAX_SNES_CART_SIZE, "cart", ROMREGION_ERASE00 )
|
|
ROM_REGION( 0x2000, "dspprg", ROMREGION_ERASEFF)
|
|
ROM_REGION( 0x800, "dspdata", ROMREGION_ERASEFF)
|
|
ROM_END
|
|
|
|
ROM_START( snespsfx )
|
|
ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
|
|
|
|
ROM_REGION( 0x100, "sound_ipl", 0 ) /* IPL ROM */
|
|
ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) ) /* boot rom */
|
|
|
|
ROM_REGION( 0x10000, "addons", ROMREGION_ERASE00 ) /* add-on chip ROMs (DSP, SFX, etc) */
|
|
|
|
ROM_REGION( MAX_SNES_CART_SIZE, "cart", ROMREGION_ERASE00 )
|
|
ROM_REGION( 0x2000, "dspprg", ROMREGION_ERASEFF)
|
|
ROM_REGION( 0x800, "dspdata", ROMREGION_ERASEFF)
|
|
ROM_END
|
|
|
|
ROM_START( snesst )
|
|
ROM_REGION( 0x1000000, "maincpu", ROMREGION_ERASE00 )
|
|
|
|
ROM_REGION( 0x100, "sound_ipl", 0 ) /* IPL ROM */
|
|
ROM_LOAD( "spc700.rom", 0, 0x40, CRC(44bb3a40) SHA1(97e352553e94242ae823547cd853eecda55c20f0) ) /* boot rom */
|
|
|
|
ROM_REGION( 0x10000, "addons", ROMREGION_ERASE00 ) /* add-on chip ROMs (DSP, SFX, etc) */
|
|
|
|
ROM_REGION( 0x40000, "sufami", 0 ) /* add-on chip ROMs (DSP, SFX, etc) */
|
|
ROM_LOAD( "shvc-qh-0.bin", 0, 0x40000, CRC(9b4ca911) SHA1(ef86ea192eed03d5c413fdbbfd46043be1d7a127) )
|
|
|
|
ROM_REGION( MAX_SNES_CART_SIZE, "slot_a", ROMREGION_ERASE00 )
|
|
ROM_REGION( MAX_SNES_CART_SIZE, "slot_b", ROMREGION_ERASE00 )
|
|
ROM_REGION( 0x2000, "dspprg", ROMREGION_ERASEFF)
|
|
ROM_REGION( 0x800, "dspdata", ROMREGION_ERASEFF)
|
|
ROM_END
|
|
|
|
|
|
|
|
/*************************************
|
|
*
|
|
* Game driver(s)
|
|
*
|
|
*************************************/
|
|
|
|
/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS */
|
|
CONS( 1989, snes, 0, 0, snes, snes, snes_state, snes_mess, "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
|
|
CONS( 1991, snespal, snes, 0, snespal, snes, snes_state, snes_mess, "Nintendo", "Super Nintendo Entertainment System (PAL)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
|
|
|
|
// FIXME: the "hacked" drivers below, currently needed due to limitations in the core device design, should eventually be removed
|
|
|
|
// These would require CPU to be added/removed depending on the cart which is loaded
|
|
CONS( 1989, snesdsp, snes, 0, snesdsp, snes, snes_state, snes_mess, "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC, w/DSP-x)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
|
|
CONS( 1991, snespdsp, snes, 0, snespdsp, snes, snes_state, snes_mess, "Nintendo", "Super Nintendo Entertainment System (PAL, w/DSP-x)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
|
|
CONS( 1989, snessfx, snes, 0, snessfx, snes, snes_state, snes_mess, "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC, w/SuperFX)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
|
|
CONS( 1991, snespsfx, snes, 0, snespsfx, snes, snes_state, snes_mess, "Nintendo", "Super Nintendo Entertainment System (PAL, w/SuperFX)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
|
|
CONS( 1989, snesst10, snes, 0, snesst10, snes, snes_state, snes_mess, "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC, w/ST-010)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
|
|
CONS( 1989, snesst11, snes, 0, snesst11, snes, snes_state, snes_mess, "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC, w/ST-011)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
|
|
//CONS( 1989, snessa1, snes, 0, snessa1, snes, XXX_CLASS, snes_mess, "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC, w/SA-1)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
|
|
//CONS( 1991, snespsa1, snes, 0, snespsa1, snes, XXX_CLASS, snes_mess, "Nintendo", "Super Nintendo Entertainment System (PAL, w/SA-1)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND )
|
|
|
|
// These would require cartslot to be added/removed depending on the cart which is loaded
|
|
CONS( 1989, snesst, snes, 0, snesst, snes, snes_state, snesst, "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC, w/Sufami Turbo)", GAME_NOT_WORKING )
|
|
|
|
|
|
|
|
// WIP for slot-ified cart devices
|
|
|
|
#include "machine/sns_slot.h"
|
|
#include "machine/sns_rom.h"
|
|
#include "machine/sns_rom21.h"
|
|
#include "machine/sns_bsx.h"
|
|
#include "machine/sns_sdd1.h"
|
|
#include "machine/sns_sfx.h"
|
|
#include "machine/sns_spc7110.h"
|
|
#include "machine/sns_sufami.h"
|
|
#include "machine/sns_upd.h"
|
|
|
|
class snsnew_state : public snes_console_state
|
|
{
|
|
public:
|
|
snsnew_state(const machine_config &mconfig, device_type type, const char *tag)
|
|
: snes_console_state(mconfig, type, tag),
|
|
m_slotcart(*this, "snsslot")
|
|
{ }
|
|
|
|
DECLARE_READ8_MEMBER( snes20_hi_r );
|
|
DECLARE_WRITE8_MEMBER( snes20_hi_w );
|
|
DECLARE_READ8_MEMBER( snes20_lo_r );
|
|
DECLARE_WRITE8_MEMBER( snes20_lo_w );
|
|
DECLARE_READ8_MEMBER( snes21_lo_r );
|
|
DECLARE_WRITE8_MEMBER( snes21_lo_w );
|
|
DECLARE_READ8_MEMBER( snes21_hi_r );
|
|
DECLARE_WRITE8_MEMBER( snes21_hi_w );
|
|
DECLARE_READ8_MEMBER( snesfx_hi_r );
|
|
DECLARE_READ8_MEMBER( snesfx_lo_r );
|
|
DECLARE_WRITE8_MEMBER( snesfx_hi_w );
|
|
DECLARE_WRITE8_MEMBER( snesfx_lo_w );
|
|
DECLARE_READ8_MEMBER( snespc7110_hi_r );
|
|
DECLARE_READ8_MEMBER( snespc7110_lo_r );
|
|
DECLARE_WRITE8_MEMBER( snespc7110_hi_w );
|
|
DECLARE_WRITE8_MEMBER( snespc7110_lo_w );
|
|
DECLARE_READ8_MEMBER( snesdd1_lo_r );
|
|
DECLARE_WRITE8_MEMBER( snesdd1_lo_w );
|
|
DECLARE_READ8_MEMBER( snesdd1_hi_r );
|
|
DECLARE_WRITE8_MEMBER( snesdd1_hi_w );
|
|
DECLARE_READ8_MEMBER( snesbsx_hi_r );
|
|
DECLARE_WRITE8_MEMBER( snesbsx_hi_w );
|
|
DECLARE_READ8_MEMBER( snesbsx_lo_r );
|
|
DECLARE_WRITE8_MEMBER( snesbsx_lo_w );
|
|
DECLARE_READ8_MEMBER( snesnew_lo_r );
|
|
DECLARE_READ8_MEMBER( snesnew_hi_r );
|
|
DECLARE_WRITE8_MEMBER( snesnew_lo_w );
|
|
DECLARE_WRITE8_MEMBER( snesnew_hi_w );
|
|
|
|
optional_device<sns_cart_slot_device> m_slotcart;
|
|
int m_type;
|
|
};
|
|
|
|
|
|
// FIXME: merge these add-on specific maps into something more sane!
|
|
|
|
// In general LoROM games have perfect mirror between 0x00-0x7d and 0x80-0xff
|
|
// But BSX+LoROM games use different read handlers (to access ROM beyond 2MB)
|
|
// so we use two different set of handlers...
|
|
|
|
// LoROM
|
|
|
|
READ8_MEMBER( snsnew_state::snes20_hi_r )
|
|
{
|
|
UINT16 address = offset & 0xffff;
|
|
|
|
if (offset < 0x400000)
|
|
{
|
|
if (address < 0x2000)
|
|
return space.read_byte(0x7e0000 + address);
|
|
if (address >= 0x2000 && address < 0x6000)
|
|
return snes_r_io(space, address);
|
|
if (address >= 0x6000 && address < 0x8000)
|
|
return snes_open_bus_r(space, 0);
|
|
if (address >= 0x8000)
|
|
return m_slotcart->m_cart->read_h(space, offset);
|
|
}
|
|
else if (offset < 0x700000)
|
|
{
|
|
if (address < 0x8000)
|
|
return snes_open_bus_r(space, 0);
|
|
else
|
|
return m_slotcart->m_cart->read_h(space, offset);
|
|
}
|
|
|
|
// ROM & NVRAM access
|
|
return m_slotcart->m_cart->read_h(space, offset);
|
|
}
|
|
|
|
WRITE8_MEMBER( snsnew_state::snes20_hi_w )
|
|
{
|
|
UINT16 address = offset & 0xffff;
|
|
if (offset < 0x400000)
|
|
{
|
|
if (address < 0x2000)
|
|
space.write_byte(0x7e0000 + address, data);
|
|
if (address >= 0x2000 && address < 0x6000)
|
|
snes_w_io(space, address, data);
|
|
}
|
|
else if (offset >= 0x700000) // NVRAM access
|
|
{
|
|
m_slotcart->m_cart->write_h(space, offset, data);
|
|
}
|
|
}
|
|
|
|
READ8_MEMBER( snsnew_state::snes20_lo_r )
|
|
{
|
|
UINT16 address = offset & 0xffff;
|
|
|
|
if (offset < 0x400000)
|
|
{
|
|
if (address < 0x2000)
|
|
return space.read_byte(0x7e0000 + address);
|
|
if (address >= 0x2000 && address < 0x6000)
|
|
return snes_r_io(space, address);
|
|
if (address >= 0x6000 && address < 0x8000)
|
|
return snes_open_bus_r(space, 0);
|
|
if (address >= 0x8000)
|
|
return m_slotcart->m_cart->read_l(space, offset);
|
|
}
|
|
else if (offset < 0x700000)
|
|
{
|
|
if (address < 0x8000)
|
|
return snes_open_bus_r(space, 0);
|
|
else
|
|
return m_slotcart->m_cart->read_l(space, offset);
|
|
}
|
|
|
|
// ROM & NVRAM access
|
|
return m_slotcart->m_cart->read_l(space, offset);
|
|
}
|
|
|
|
WRITE8_MEMBER( snsnew_state::snes20_lo_w )
|
|
{
|
|
snes20_hi_w(space, offset, data, 0xff);
|
|
}
|
|
|
|
|
|
// HiROM
|
|
|
|
READ8_MEMBER( snsnew_state::snes21_lo_r )
|
|
{
|
|
UINT16 address = offset & 0xffff;
|
|
|
|
if (offset < 0x400000)
|
|
{
|
|
if (address < 0x2000)
|
|
return space.read_byte(0x7e0000 + address);
|
|
if (address >= 0x2000 && address < 0x6000)
|
|
return snes_r_io(space, address);
|
|
if (address >= 0x6000 && address < 0x8000)
|
|
{
|
|
if (m_slotcart->m_cart->get_nvram_size())
|
|
{
|
|
// read NVRAM, instead
|
|
if (offset >= 0x300000)
|
|
return m_slotcart->m_cart->read_l(space, offset);
|
|
}
|
|
return snes_open_bus_r(space, 0);
|
|
}
|
|
if (address >= 0x8000)
|
|
return m_slotcart->m_cart->read_l(space, offset);
|
|
}
|
|
|
|
// ROM & NVRAM access
|
|
return m_slotcart->m_cart->read_l(space, offset);
|
|
}
|
|
|
|
WRITE8_MEMBER( snsnew_state::snes21_lo_w )
|
|
{
|
|
UINT16 address = offset & 0xffff;
|
|
if (offset < 0x400000)
|
|
{
|
|
if (address < 0x2000)
|
|
space.write_byte(0x7e0000 + address, data);
|
|
if (address >= 0x2000 && address < 0x6000)
|
|
snes_w_io(space, address, data);
|
|
if (address >= 0x6000 && address < 0x8000)
|
|
{
|
|
if (m_slotcart->m_cart->get_nvram_size())
|
|
{
|
|
// write to NVRAM, in this case
|
|
if (offset >= 0x300000)
|
|
m_slotcart->m_cart->write_l(space, offset, data);
|
|
}
|
|
}
|
|
}
|
|
else if (offset >= 0x700000) // NVRAM access
|
|
m_slotcart->m_cart->write_l(space, offset, data);
|
|
}
|
|
|
|
READ8_MEMBER( snsnew_state::snes21_hi_r )
|
|
{
|
|
UINT16 address = offset & 0xffff;
|
|
|
|
if (offset < 0x400000)
|
|
{
|
|
if (address < 0x2000)
|
|
return space.read_byte(0x7e0000 + address);
|
|
if (address >= 0x2000 && address < 0x6000)
|
|
return snes_r_io(space, address);
|
|
if (address >= 0x6000 && address < 0x8000)
|
|
{
|
|
if (m_slotcart->m_cart->get_nvram_size())
|
|
{
|
|
// read NVRAM, instead
|
|
if (offset >= 0x300000)
|
|
return m_slotcart->m_cart->read_h(space, offset);
|
|
}
|
|
return snes_open_bus_r(space, 0);
|
|
}
|
|
if (address >= 0x8000)
|
|
return m_slotcart->m_cart->read_h(space, offset);
|
|
}
|
|
|
|
// ROM & NVRAM access
|
|
return m_slotcart->m_cart->read_h(space, offset);
|
|
}
|
|
|
|
WRITE8_MEMBER( snsnew_state::snes21_hi_w )
|
|
{
|
|
UINT16 address = offset & 0xffff;
|
|
if (offset < 0x400000)
|
|
{
|
|
if (address < 0x2000)
|
|
space.write_byte(0x7e0000 + address, data);
|
|
if (address >= 0x2000 && address < 0x6000)
|
|
snes_w_io(space, address, data);
|
|
if (address >= 0x6000 && address < 0x8000)
|
|
{
|
|
if (m_slotcart->m_cart->get_nvram_size())
|
|
{
|
|
// write to NVRAM, in this case
|
|
if (offset >= 0x300000)
|
|
m_slotcart->m_cart->write_h(space, offset, data);
|
|
}
|
|
}
|
|
}
|
|
else if (offset >= 0x700000) // NVRAM access
|
|
m_slotcart->m_cart->write_h(space, offset, data);
|
|
}
|
|
|
|
// SuperFX / GSU
|
|
|
|
READ8_MEMBER( snsnew_state::snesfx_hi_r )
|
|
{
|
|
UINT16 address = offset & 0xffff;
|
|
|
|
if (offset < 0x400000)
|
|
{
|
|
if (address < 0x2000)
|
|
return space.read_byte(0x7e0000 + address);
|
|
if (address >= 0x2000 && address < 0x6000)
|
|
{
|
|
if (address >= 0x3000 && address < 0x3300)
|
|
return m_slotcart->m_cart->chip_read(space, offset);
|
|
else
|
|
return snes_r_io(space, address);
|
|
}
|
|
if (address >= 0x6000 && address < 0x8000)
|
|
{
|
|
return m_slotcart->m_cart->read_h(space, offset); //RAM
|
|
}
|
|
if (address >= 0x8000)
|
|
return m_slotcart->m_cart->read_h(space, offset); //ROM
|
|
}
|
|
else if (offset < 0x600000)
|
|
return m_slotcart->m_cart->read_h(space, offset); //ROM
|
|
|
|
return m_slotcart->m_cart->read_h(space, offset); //RAM
|
|
}
|
|
|
|
READ8_MEMBER( snsnew_state::snesfx_lo_r )
|
|
{
|
|
UINT16 address = offset & 0xffff;
|
|
|
|
if (offset < 0x400000)
|
|
{
|
|
if (address < 0x2000)
|
|
return space.read_byte(0x7e0000 + address);
|
|
if (address >= 0x2000 && address < 0x6000)
|
|
{
|
|
if (address >= 0x3000 && address < 0x3300)
|
|
return m_slotcart->m_cart->chip_read(space, offset);
|
|
else
|
|
return snes_r_io(space, address);
|
|
}
|
|
if (address >= 0x6000 && address < 0x8000)
|
|
{
|
|
return m_slotcart->m_cart->read_l(space, offset); //RAM
|
|
}
|
|
if (address >= 0x8000)
|
|
return m_slotcart->m_cart->read_l(space, offset); //ROM
|
|
}
|
|
else if (offset < 0x600000)
|
|
return m_slotcart->m_cart->read_l(space, offset); //ROM
|
|
|
|
return m_slotcart->m_cart->read_l(space, offset); //RAM
|
|
}
|
|
|
|
WRITE8_MEMBER( snsnew_state::snesfx_hi_w )
|
|
{
|
|
UINT16 address = offset & 0xffff;
|
|
if (offset < 0x400000)
|
|
{
|
|
if (address < 0x2000)
|
|
space.write_byte(0x7e0000 + address, data);
|
|
if (address >= 0x2000 && address < 0x6000)
|
|
{
|
|
if (address >= 0x3000 && address < 0x3300)
|
|
m_slotcart->m_cart->chip_write(space, offset, data);
|
|
else
|
|
snes_w_io(space, address, data);
|
|
}
|
|
if (address >= 0x6000 && address < 0x8000)
|
|
m_slotcart->m_cart->write_h(space, offset, data);
|
|
}
|
|
else
|
|
m_slotcart->m_cart->write_h(space, offset, data);
|
|
}
|
|
|
|
WRITE8_MEMBER( snsnew_state::snesfx_lo_w )
|
|
{
|
|
UINT16 address = offset & 0xffff;
|
|
if (offset < 0x400000)
|
|
{
|
|
if (address < 0x2000)
|
|
space.write_byte(0x7e0000 + address, data);
|
|
if (address >= 0x2000 && address < 0x6000)
|
|
{
|
|
if (address >= 0x3000 && address < 0x3300)
|
|
m_slotcart->m_cart->chip_write(space, offset, data);
|
|
else
|
|
snes_w_io(space, address, data);
|
|
}
|
|
if (address >= 0x6000 && address < 0x8000)
|
|
m_slotcart->m_cart->write_l(space, offset, data);
|
|
}
|
|
else
|
|
m_slotcart->m_cart->write_l(space, offset, data);
|
|
}
|
|
|
|
// SPC-7110
|
|
|
|
READ8_MEMBER( snsnew_state::snespc7110_hi_r )
|
|
{
|
|
UINT16 address = offset & 0xffff;
|
|
|
|
if (offset < 0x400000)
|
|
{
|
|
if (address < 0x2000)
|
|
return space.read_byte(0x7e0000 + address);
|
|
if (address >= 0x2000 && address < 0x6000)
|
|
{
|
|
UINT16 limit = (m_slotcart->get_type() == SNES_SPC7110_RTC) ? 0x4843 : 0x4840;
|
|
if (address >= 0x4800 && address < limit)
|
|
return m_slotcart->m_cart->chip_read(space, address);
|
|
|
|
return snes_r_io(space, address);
|
|
}
|
|
if (address >= 0x6000 && address < 0x8000)
|
|
{
|
|
if (offset < 0x10000)
|
|
return m_slotcart->m_cart->read_h(space, offset);
|
|
if (offset >= 0x300000 && offset < 0x310000)
|
|
return m_slotcart->m_cart->read_h(space, offset);
|
|
}
|
|
if (address >= 0x8000)
|
|
return m_slotcart->m_cart->read_h(space, offset);
|
|
}
|
|
return m_slotcart->m_cart->read_h(space, offset);
|
|
}
|
|
|
|
READ8_MEMBER( snsnew_state::snespc7110_lo_r )
|
|
{
|
|
UINT16 address = offset & 0xffff;
|
|
|
|
if (offset < 0x400000)
|
|
{
|
|
if (address < 0x2000)
|
|
return space.read_byte(0x7e0000 + address);
|
|
if (address >= 0x2000 && address < 0x6000)
|
|
{
|
|
UINT16 limit = (m_slotcart->get_type() == SNES_SPC7110_RTC) ? 0x4843 : 0x4840;
|
|
if (address >= 0x4800 && address < limit)
|
|
return m_slotcart->m_cart->chip_read(space, address);
|
|
|
|
return snes_r_io(space, address);
|
|
}
|
|
if (address >= 0x6000 && address < 0x8000)
|
|
{
|
|
if (offset < 0x10000)
|
|
return m_slotcart->m_cart->read_l(space, offset);
|
|
if (offset >= 0x300000 && offset < 0x310000)
|
|
return m_slotcart->m_cart->read_l(space, offset);
|
|
}
|
|
if (address >= 0x8000)
|
|
return m_slotcart->m_cart->read_l(space, offset);
|
|
}
|
|
if (offset >= 0x500000 && offset < 0x510000)
|
|
return m_slotcart->m_cart->chip_read(space, 0x4800);
|
|
|
|
return snes_open_bus_r(space, 0);
|
|
}
|
|
|
|
WRITE8_MEMBER( snsnew_state::snespc7110_hi_w )
|
|
{
|
|
UINT16 address = offset & 0xffff;
|
|
if (offset < 0x400000)
|
|
{
|
|
if (address < 0x2000)
|
|
space.write_byte(0x7e0000 + address, data);
|
|
if (address >= 0x2000 && address < 0x6000)
|
|
{
|
|
UINT16 limit = (m_slotcart->get_type() == SNES_SPC7110_RTC) ? 0x4843 : 0x4840;
|
|
if (address >= 0x4800 && address < limit)
|
|
{
|
|
m_slotcart->m_cart->chip_write(space, address, data);
|
|
return;
|
|
}
|
|
snes_w_io(space, address, data);
|
|
}
|
|
if (address >= 0x6000 && address < 0x8000)
|
|
{
|
|
if (offset < 0x10000)
|
|
m_slotcart->m_cart->write_l(space, offset, data);
|
|
if (offset >= 0x300000 && offset < 0x310000)
|
|
m_slotcart->m_cart->write_l(space, offset, data);
|
|
}
|
|
}
|
|
}
|
|
|
|
WRITE8_MEMBER( snsnew_state::snespc7110_lo_w )
|
|
{
|
|
UINT16 address = offset & 0xffff;
|
|
if (offset < 0x400000)
|
|
{
|
|
if (address < 0x2000)
|
|
space.write_byte(0x7e0000 + address, data);
|
|
if (address >= 0x2000 && address < 0x6000)
|
|
{
|
|
UINT16 limit = (m_slotcart->get_type() == SNES_SPC7110_RTC) ? 0x4843 : 0x4840;
|
|
if (address >= 0x4800 && address < limit)
|
|
{
|
|
m_slotcart->m_cart->chip_write(space, address, data);
|
|
return;
|
|
}
|
|
snes_w_io(space, address, data);
|
|
}
|
|
if (address >= 0x6000 && address < 0x8000)
|
|
{
|
|
if (offset < 0x10000)
|
|
m_slotcart->m_cart->write_l(space, offset, data);
|
|
if (offset >= 0x300000 && offset < 0x310000)
|
|
m_slotcart->m_cart->write_l(space, offset, data);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// S-DD1
|
|
|
|
READ8_MEMBER( snsnew_state::snesdd1_lo_r )
|
|
{
|
|
UINT16 address = offset & 0xffff;
|
|
|
|
if (offset < 0x400000)
|
|
{
|
|
if (address < 0x2000)
|
|
return space.read_byte(0x7e0000 + address);
|
|
if (address >= 0x2000 && address < 0x6000)
|
|
{
|
|
if (address >= 0x4800 && address < 0x4808)
|
|
return m_slotcart->m_cart->chip_read(space, address);
|
|
|
|
return snes_r_io(space, address);
|
|
}
|
|
if (address >= 0x6000 && address < 0x8000)
|
|
return snes_open_bus_r(space, 0);
|
|
if (address >= 0x8000)
|
|
return m_slotcart->m_cart->read_l(space, offset);
|
|
}
|
|
|
|
// ROM & NVRAM access
|
|
return m_slotcart->m_cart->read_l(space, offset);
|
|
}
|
|
|
|
WRITE8_MEMBER( snsnew_state::snesdd1_lo_w )
|
|
{
|
|
UINT16 address = offset & 0xffff;
|
|
if (offset < 0x400000)
|
|
{
|
|
if (address < 0x2000)
|
|
space.write_byte(0x7e0000 + address, data);
|
|
if (address >= 0x2000 && address < 0x6000)
|
|
{
|
|
if (address >= 0x4300 && address < 0x4380)
|
|
{
|
|
m_slotcart->m_cart->chip_write(space, address, data);
|
|
// here we don't return, but we let the w_io happen...
|
|
}
|
|
if (address >= 0x4800 && address < 0x4808)
|
|
{
|
|
m_slotcart->m_cart->chip_write(space, address, data);
|
|
return;
|
|
}
|
|
snes_w_io(space, address, data);
|
|
}
|
|
}
|
|
if (offset >= 0x700000 && address < 0x8000 && m_slotcart->m_cart->get_nvram_size())
|
|
return m_slotcart->m_cart->write_l(space, offset, data);
|
|
}
|
|
|
|
READ8_MEMBER( snsnew_state::snesdd1_hi_r )
|
|
{
|
|
if (offset >= 0x400000)
|
|
return m_slotcart->m_cart->read_h(space, offset);
|
|
else
|
|
return snesdd1_lo_r(space, offset, 0xff);
|
|
}
|
|
|
|
WRITE8_MEMBER( snsnew_state::snesdd1_hi_w )
|
|
{
|
|
snesdd1_lo_w(space, offset, data, 0xff);
|
|
}
|
|
|
|
|
|
// BS-X
|
|
|
|
READ8_MEMBER( snsnew_state::snesbsx_hi_r )
|
|
{
|
|
UINT16 address = offset & 0xffff;
|
|
|
|
if (offset < 0x400000)
|
|
{
|
|
if (address < 0x2000)
|
|
return space.read_byte(0x7e0000 + address);
|
|
if (address >= 0x2000 && address < 0x6000)
|
|
{
|
|
if (address >= 0x2188 && address < 0x21a0)
|
|
return m_slotcart->m_cart->chip_read(space, offset);
|
|
if (address >= 0x5000)
|
|
return m_slotcart->m_cart->chip_read(space, offset);
|
|
return snes_r_io(space, address);
|
|
}
|
|
if (address >= 0x6000 && address < 0x8000)
|
|
{
|
|
if (offset >= 0x200000)
|
|
return m_slotcart->m_cart->read_l(space, offset);
|
|
else
|
|
return snes_open_bus_r(space, 0);
|
|
}
|
|
if (address >= 0x8000)
|
|
return m_slotcart->m_cart->read_l(space, offset);
|
|
}
|
|
return m_slotcart->m_cart->read_l(space, offset);
|
|
}
|
|
|
|
WRITE8_MEMBER( snsnew_state::snesbsx_hi_w )
|
|
{
|
|
UINT16 address = offset & 0xffff;
|
|
if (offset < 0x400000)
|
|
{
|
|
if (address < 0x2000)
|
|
space.write_byte(0x7e0000 + address, data);
|
|
if (address >= 0x2000 && address < 0x6000)
|
|
{
|
|
if (address >= 0x2188 && address < 0x21a0)
|
|
{
|
|
m_slotcart->m_cart->chip_write(space, offset, data);
|
|
return;
|
|
}
|
|
if (address >= 0x5000)
|
|
{
|
|
m_slotcart->m_cart->chip_write(space, offset, data);
|
|
return;
|
|
}
|
|
snes_w_io(space, address, data);
|
|
}
|
|
if (address >= 0x6000 && address < 0x8000)
|
|
{
|
|
if (offset >= 0x200000)
|
|
return m_slotcart->m_cart->write_l(space, offset, data);
|
|
}
|
|
if (address >= 0x8000)
|
|
return m_slotcart->m_cart->write_l(space, offset, data);
|
|
}
|
|
return m_slotcart->m_cart->write_l(space, offset, data);
|
|
}
|
|
|
|
READ8_MEMBER( snsnew_state::snesbsx_lo_r )
|
|
{
|
|
return snesbsx_hi_r(space, offset, 0xff);
|
|
}
|
|
|
|
WRITE8_MEMBER( snsnew_state::snesbsx_lo_w )
|
|
{
|
|
snesbsx_hi_w(space, offset, data, 0xff);
|
|
}
|
|
|
|
|
|
READ8_MEMBER( snsnew_state::snesnew_lo_r )
|
|
{
|
|
// take care of add-on IO
|
|
if (m_slotcart->get_type() == SNES_DSP
|
|
&& (offset >= 0x200000 && offset < 0x400000 && (offset & 0x8000) == 0x8000))
|
|
return m_slotcart->m_cart->chip_read(space, offset & 0x7fff);
|
|
else if (m_slotcart->get_type() == SNES_DSP_MODE21
|
|
&& (offset < 0x200000 && (offset & 0xffff) >= 0x6000 && (offset & 0xffff) < 0x8000))
|
|
return m_slotcart->m_cart->chip_read(space, offset & 0x1fff);
|
|
else if (m_slotcart->get_type() == SNES_DSP4
|
|
&& (offset >= 0x300000 && offset < 0x400000 && (offset & 0x8000) == 0x8000))
|
|
return m_slotcart->m_cart->chip_read(space, offset & 0x7fff);
|
|
else if (m_slotcart->get_type() == SNES_OBC1
|
|
&& (offset < 0x400000 && (offset & 0xffff) >= 0x6000 && (offset & 0xffff) < 0x8000))
|
|
return m_slotcart->m_cart->chip_read(space, offset);
|
|
else if ((m_slotcart->get_type() == SNES_ST010 || m_slotcart->get_type() == SNES_ST011)
|
|
&& (offset >= 0x680000 && offset < 0x700000 && (offset & 0xffff) < 0x1000))
|
|
return m_slotcart->m_cart->chip_read(space, offset);
|
|
else if ((m_slotcart->get_type() == SNES_ST010 /*|| m_slotcart->get_type() == SNES_ST011*/) // why does this freeze moritash?
|
|
&& (offset == 0x600000 || offset == 0x600001))
|
|
return m_slotcart->m_cart->chip_read(space, offset);
|
|
else if (m_slotcart->get_type() == SNES_SRTC
|
|
&& (offset < 0x400000 && (offset & 0xffff) == 0x2800))
|
|
return m_slotcart->m_cart->chip_read(space, offset & 0xffff);
|
|
else
|
|
{
|
|
switch (m_type)
|
|
{
|
|
case SNES_MODE20:
|
|
case SNES_ST010:
|
|
case SNES_ST011:
|
|
case SNES_DSP:
|
|
case SNES_DSP4:
|
|
case SNES_OBC1:
|
|
case SNES_SUFAMITURBO:
|
|
case SNES_STROM:
|
|
case SNES_BSXLO:
|
|
case SNES_POKEMON:
|
|
case SNES_BANANA:
|
|
return snes20_lo_r(space, offset, 0xff);
|
|
|
|
case SNES_MODE21:
|
|
case SNES_DSP_MODE21:
|
|
case SNES_SRTC:
|
|
case SNES_BSXHI:
|
|
return snes21_lo_r(space, offset, 0xff);
|
|
|
|
case SNES_SFX:
|
|
return snesfx_lo_r(space, offset, 0xff);
|
|
|
|
case SNES_SPC7110:
|
|
case SNES_SPC7110_RTC:
|
|
return snespc7110_lo_r(space, offset, 0xff);
|
|
|
|
case SNES_SDD1:
|
|
return snesdd1_lo_r(space, offset, 0xff);
|
|
|
|
case SNES_BSX:
|
|
return snesbsx_lo_r(space, offset, 0xff);
|
|
}
|
|
}
|
|
return snes_open_bus_r(space, 0);
|
|
}
|
|
|
|
READ8_MEMBER( snsnew_state::snesnew_hi_r )
|
|
{
|
|
// take care of add-on IO
|
|
if (m_slotcart->get_type() == SNES_DSP
|
|
&& (offset >= 0x200000 && offset < 0x400000 && (offset & 0x8000) == 0x8000))
|
|
return m_slotcart->m_cart->chip_read(space, offset & 0x7fff);
|
|
else if (m_slotcart->get_type() == SNES_DSP_MODE21
|
|
&& (offset < 0x200000 && (offset & 0xffff) >= 0x6000 && (offset & 0xffff) < 0x8000))
|
|
return m_slotcart->m_cart->chip_read(space, offset & 0x1fff);
|
|
else if (m_slotcart->get_type() == SNES_DSP4
|
|
&& (offset >= 0x300000 && offset < 0x400000 && (offset & 0x8000) == 0x8000))
|
|
return m_slotcart->m_cart->chip_read(space, offset & 0x7fff);
|
|
else if (m_slotcart->get_type() == SNES_OBC1
|
|
&& (offset < 0x400000 && (offset & 0xffff) >= 0x6000 && (offset & 0xffff) < 0x8000))
|
|
return m_slotcart->m_cart->chip_read(space, offset);
|
|
else if ((m_slotcart->get_type() == SNES_ST010 || m_slotcart->get_type() == SNES_ST011)
|
|
&& (offset >= 0x680000 && offset < 0x700000 && (offset & 0xffff) < 0x1000))
|
|
return m_slotcart->m_cart->chip_read(space, offset);
|
|
else if ((m_slotcart->get_type() == SNES_ST010 || m_slotcart->get_type() == SNES_ST011)
|
|
&& (offset == 0x600000 || offset == 0x600001))
|
|
return m_slotcart->m_cart->chip_read(space, offset);
|
|
else if (m_slotcart->get_type() == SNES_SRTC
|
|
&& (offset < 0x400000 && (offset & 0xffff) == 0x2800))
|
|
return m_slotcart->m_cart->chip_read(space, offset & 0xffff);
|
|
else if ((m_slotcart->get_type() == SNES_POKEMON || m_slotcart->get_type() == SNES_BANANA)
|
|
&& (offset & 0x70000) == 0x0000)
|
|
{
|
|
// printf("hi read %x\n", offset);
|
|
return m_slotcart->m_cart->chip_read(space, offset);
|
|
}
|
|
else
|
|
{
|
|
switch (m_type)
|
|
{
|
|
case SNES_MODE20:
|
|
case SNES_ST010:
|
|
case SNES_ST011:
|
|
case SNES_DSP:
|
|
case SNES_DSP4:
|
|
case SNES_OBC1:
|
|
case SNES_SUFAMITURBO:
|
|
case SNES_STROM:
|
|
case SNES_BSXLO:
|
|
case SNES_POKEMON:
|
|
case SNES_BANANA:
|
|
return snes20_hi_r(space, offset, 0xff);
|
|
|
|
case SNES_MODE21:
|
|
case SNES_DSP_MODE21:
|
|
case SNES_SRTC:
|
|
case SNES_BSXHI:
|
|
return snes21_hi_r(space, offset, 0xff);
|
|
|
|
case SNES_SFX:
|
|
return snesfx_hi_r(space, offset, 0xff);
|
|
|
|
case SNES_SPC7110:
|
|
case SNES_SPC7110_RTC:
|
|
return snespc7110_hi_r(space, offset, 0xff);
|
|
|
|
case SNES_SDD1:
|
|
return snesdd1_hi_r(space, offset, 0xff);
|
|
|
|
case SNES_BSX:
|
|
return snesbsx_hi_r(space, offset, 0xff);
|
|
}
|
|
}
|
|
return snes_open_bus_r(space, 0);
|
|
}
|
|
|
|
WRITE8_MEMBER( snsnew_state::snesnew_lo_w )
|
|
{
|
|
// take care of add-on IO
|
|
if (m_slotcart->get_type() == SNES_DSP
|
|
&& (offset >= 0x200000 && offset < 0x400000 && (offset & 0x8000) == 0x8000))
|
|
m_slotcart->m_cart->chip_write(space, offset & 0x7fff, data);
|
|
else if (m_slotcart->get_type() == SNES_DSP_MODE21
|
|
&& (offset < 0x200000 && (offset & 0xffff) >= 0x6000 && (offset & 0xffff) < 0x8000))
|
|
m_slotcart->m_cart->chip_write(space, offset & 0x1fff, data);
|
|
else if (m_slotcart->get_type() == SNES_DSP4
|
|
&& (offset >= 0x300000 && offset < 0x400000 && (offset & 0x8000) == 0x8000))
|
|
m_slotcart->m_cart->chip_write(space, offset & 0x7fff, data);
|
|
else if (m_slotcart->get_type() == SNES_OBC1
|
|
&& (offset < 0x400000 && (offset & 0xffff) >= 0x6000 && (offset & 0xffff) < 0x8000))
|
|
m_slotcart->m_cart->chip_write(space, offset, data);
|
|
else if ((m_slotcart->get_type() == SNES_ST010 || m_slotcart->get_type() == SNES_ST011)
|
|
&& (offset >= 0x680000 && offset < 0x700000 && (offset & 0xffff) < 0x1000))
|
|
m_slotcart->m_cart->chip_write(space, offset, data);
|
|
else if ((m_slotcart->get_type() == SNES_ST010 || m_slotcart->get_type() == SNES_ST011)
|
|
&& (offset == 0x600000 || offset == 0x600001))
|
|
m_slotcart->m_cart->chip_write(space, offset, data);
|
|
else if (m_slotcart->get_type() == SNES_SRTC
|
|
&& (offset < 0x400000 && (offset & 0xffff) == 0x2801))
|
|
m_slotcart->m_cart->chip_write(space, offset & 0xffff, data);
|
|
else if (m_slotcart->get_type() == SNES_BANANA
|
|
&& (offset & 0x78000) == 0x8000)
|
|
{
|
|
// printf("lo write %x\n", offset);
|
|
m_slotcart->m_cart->chip_write(space, offset, data);
|
|
}
|
|
else
|
|
{
|
|
switch (m_type)
|
|
{
|
|
case SNES_MODE20:
|
|
case SNES_ST010:
|
|
case SNES_ST011:
|
|
case SNES_DSP:
|
|
case SNES_DSP4:
|
|
case SNES_OBC1:
|
|
case SNES_SUFAMITURBO:
|
|
case SNES_STROM:
|
|
case SNES_BSXLO:
|
|
case SNES_POKEMON:
|
|
case SNES_BANANA:
|
|
snes20_lo_w(space, offset, data, 0xff);
|
|
break;
|
|
|
|
case SNES_MODE21:
|
|
case SNES_DSP_MODE21:
|
|
case SNES_SRTC:
|
|
case SNES_BSXHI:
|
|
snes21_lo_w(space, offset, data, 0xff);
|
|
break;
|
|
|
|
case SNES_SFX:
|
|
snesfx_lo_w(space, offset, data, 0xff);
|
|
break;
|
|
|
|
case SNES_SPC7110:
|
|
case SNES_SPC7110_RTC:
|
|
snespc7110_lo_w(space, offset, data, 0xff);
|
|
break;
|
|
|
|
case SNES_SDD1:
|
|
snesdd1_lo_w(space, offset, data, 0xff);
|
|
break;
|
|
|
|
case SNES_BSX:
|
|
snesbsx_lo_w(space, offset, data, 0xff);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
WRITE8_MEMBER( snsnew_state::snesnew_hi_w )
|
|
{
|
|
// take care of add-on IO
|
|
if (m_slotcart->get_type() == SNES_DSP
|
|
&& (offset >= 0x200000 && offset < 0x400000 && (offset & 0x8000) == 0x8000))
|
|
m_slotcart->m_cart->chip_write(space, offset & 0x7fff, data);
|
|
else if (m_slotcart->get_type() == SNES_DSP_MODE21
|
|
&& (offset < 0x200000 && (offset & 0xffff) >= 0x6000 && (offset & 0xffff) < 0x8000))
|
|
m_slotcart->m_cart->chip_write(space, offset & 0x1fff, data);
|
|
else if (m_slotcart->get_type() == SNES_DSP4
|
|
&& (offset >= 0x300000 && offset < 0x400000 && (offset & 0x8000) == 0x8000))
|
|
m_slotcart->m_cart->chip_write(space, offset & 0x7fff, data);
|
|
else if (m_slotcart->get_type() == SNES_OBC1
|
|
&& (offset < 0x400000 && (offset & 0xffff) >= 0x6000 && (offset & 0xffff) < 0x8000))
|
|
return m_slotcart->m_cart->chip_write(space, offset, data);
|
|
else if ((m_slotcart->get_type() == SNES_ST010 || m_slotcart->get_type() == SNES_ST011)
|
|
&& (offset >= 0x680000 && offset < 0x700000 && (offset & 0xffff) < 0x1000))
|
|
m_slotcart->m_cart->chip_write(space, offset, data);
|
|
else if ((m_slotcart->get_type() == SNES_ST010 || m_slotcart->get_type() == SNES_ST011)
|
|
&& (offset == 0x600000 || offset == 0x600001))
|
|
m_slotcart->m_cart->chip_write(space, offset, data);
|
|
else if (m_slotcart->get_type() == SNES_SRTC
|
|
&& (offset < 0x400000 && (offset & 0xffff) == 0x2801))
|
|
m_slotcart->m_cart->chip_write(space, offset & 0xffff, data);
|
|
else if ((m_slotcart->get_type() == SNES_POKEMON)
|
|
&& (offset & 0x70000) == 0x0000)
|
|
{
|
|
// printf("hi write %x\n", offset);
|
|
m_slotcart->m_cart->chip_write(space, offset, data);
|
|
}
|
|
else
|
|
{
|
|
switch (m_type)
|
|
{
|
|
case SNES_MODE20:
|
|
case SNES_ST010:
|
|
case SNES_ST011:
|
|
case SNES_DSP:
|
|
case SNES_DSP4:
|
|
case SNES_OBC1:
|
|
case SNES_SUFAMITURBO:
|
|
case SNES_STROM:
|
|
case SNES_BSXLO:
|
|
case SNES_POKEMON:
|
|
case SNES_BANANA:
|
|
snes20_hi_w(space, offset, data, 0xff);
|
|
break;
|
|
|
|
case SNES_MODE21:
|
|
case SNES_DSP_MODE21:
|
|
case SNES_SRTC:
|
|
case SNES_BSXHI:
|
|
snes21_hi_w(space, offset, data, 0xff);
|
|
break;
|
|
|
|
case SNES_SFX:
|
|
snesfx_hi_w(space, offset, data, 0xff);
|
|
break;
|
|
|
|
case SNES_SPC7110:
|
|
case SNES_SPC7110_RTC:
|
|
snespc7110_hi_w(space, offset, data, 0xff);
|
|
break;
|
|
|
|
case SNES_SDD1:
|
|
snesdd1_hi_w(space, offset, data, 0xff);
|
|
break;
|
|
|
|
case SNES_BSX:
|
|
snesbsx_hi_w(space, offset, data, 0xff);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static ADDRESS_MAP_START( snesnew_map, AS_PROGRAM, 8, snsnew_state )
|
|
AM_RANGE(0x000000, 0x7dffff) AM_READWRITE(snesnew_lo_r, snesnew_lo_w)
|
|
AM_RANGE(0x7e0000, 0x7fffff) AM_RAM /* 8KB Low RAM, 24KB High RAM, 96KB Expanded RAM */
|
|
AM_RANGE(0x800000, 0xffffff) AM_READWRITE(snesnew_hi_r, snesnew_hi_w)
|
|
ADDRESS_MAP_END
|
|
|
|
static SLOT_INTERFACE_START(snes_cart)
|
|
SLOT_INTERFACE_INTERNAL("lorom", SNS_LOROM)
|
|
SLOT_INTERFACE_INTERNAL("lorom_bsx", SNS_LOROM_BSX) // LoROM + BS-X slot - unsupported
|
|
SLOT_INTERFACE_INTERNAL("lorom_cx4", SNS_LOROM) // Cart + CX4 - unsupported
|
|
SLOT_INTERFACE_INTERNAL("lorom_dsp", SNS_LOROM_NECDSP)
|
|
SLOT_INTERFACE_INTERNAL("lorom_dsp4", SNS_LOROM_NECDSP)
|
|
SLOT_INTERFACE_INTERNAL("lorom_obc1", SNS_LOROM_OBC1)
|
|
SLOT_INTERFACE_INTERNAL("lorom_sa1", SNS_LOROM) // Cart + SA1 - unsupported
|
|
SLOT_INTERFACE_INTERNAL("lorom_sdd1", SNS_LOROM_SDD1)
|
|
SLOT_INTERFACE_INTERNAL("lorom_sfx", SNS_LOROM_SUPERFX)
|
|
SLOT_INTERFACE_INTERNAL("lorom_sgb", SNS_LOROM) // SuperGB base cart - unsupported
|
|
SLOT_INTERFACE_INTERNAL("lorom_st010", SNS_LOROM_SETA10)
|
|
SLOT_INTERFACE_INTERNAL("lorom_st011", SNS_LOROM_SETA11)
|
|
SLOT_INTERFACE_INTERNAL("lorom_st018", SNS_LOROM) // Cart + ST018 - unsupported
|
|
SLOT_INTERFACE_INTERNAL("lorom_sufami", SNS_LOROM_SUFAMI) // Sufami Turbo base cart
|
|
SLOT_INTERFACE_INTERNAL("hirom", SNS_HIROM)
|
|
SLOT_INTERFACE_INTERNAL("hirom_bsx", SNS_HIROM_BSX) // HiROM + BS-X slot - unsupported
|
|
SLOT_INTERFACE_INTERNAL("hirom_dsp", SNS_HIROM_NECDSP)
|
|
SLOT_INTERFACE_INTERNAL("hirom_spc7110", SNS_HIROM_SPC7110)
|
|
SLOT_INTERFACE_INTERNAL("hirom_spcrtc", SNS_HIROM_SPC7110_RTC)
|
|
SLOT_INTERFACE_INTERNAL("hirom_srtc", SNS_HIROM_SRTC)
|
|
SLOT_INTERFACE_INTERNAL("bsxrom", SNS_ROM_BSX) // BS-X base cart - partial support only
|
|
// pirate carts
|
|
SLOT_INTERFACE_INTERNAL("lorom_poke", SNS_LOROM_POKEMON)
|
|
SLOT_INTERFACE_END
|
|
|
|
|
|
static MACHINE_START( snesnew )
|
|
{
|
|
snsnew_state *state = machine.driver_data<snsnew_state>();
|
|
|
|
state->m_type = state->m_slotcart->get_type();
|
|
|
|
MACHINE_START_CALL(snes_mess);
|
|
|
|
// in progress...
|
|
switch (state->m_type)
|
|
{
|
|
case SNES_MODE21:
|
|
machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snsnew_state::snes21_lo_r),state), write8_delegate(FUNC(snsnew_state::snes21_lo_w),state));
|
|
machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snsnew_state::snes21_hi_r),state), write8_delegate(FUNC(snsnew_state::snes21_hi_w),state));
|
|
set_5a22_map(*state->m_maincpu);
|
|
break;
|
|
case SNES_DSP_MODE21:
|
|
// machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snsnew_state::snes21_lo_r),state), write8_delegate(FUNC(snsnew_state::snes21_lo_w),state));
|
|
// machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snsnew_state::snes21_hi_r),state), write8_delegate(FUNC(snsnew_state::snes21_hi_w),state));
|
|
// machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x006000, 0x007fff, 0x9f0000, 0, read8_delegate(FUNC(device_sns_cart_interface::chip_read),state->m_slotcart->m_cart));
|
|
// machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x006000, 0x007fff, 0x9f0000, 0, write8_delegate(FUNC(device_sns_cart_interface::chip_write),state->m_slotcart->m_cart));
|
|
// set_5a22_map(*state->m_maincpu);
|
|
break;
|
|
case SNES_SRTC:
|
|
// machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snsnew_state::snes21_lo_r),state), write8_delegate(FUNC(snsnew_state::snes21_lo_w),state));
|
|
// machine.device("maincpu")->memory().space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snsnew_state::snes21_hi_r),state), write8_delegate(FUNC(snsnew_state::snes21_hi_w),state));
|
|
// machine.device("maincpu")->memory().space(AS_PROGRAM).install_read_handler(0x002800, 0x002800, 0xbf0000, 0, read8_delegate(FUNC(device_sns_cart_interface::chip_read),state->m_slotcart->m_cart));
|
|
// machine.device("maincpu")->memory().space(AS_PROGRAM).install_write_handler(0x002801, 0x002801, 0xbf0000, 0, write8_delegate(FUNC(device_sns_cart_interface::chip_write),state->m_slotcart->m_cart));
|
|
// set_5a22_map(*state->m_maincpu);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static MACHINE_CONFIG_START( snesnew, snsnew_state )
|
|
MCFG_FRAGMENT_ADD( snes_base )
|
|
|
|
MCFG_CPU_MODIFY("maincpu")
|
|
MCFG_CPU_PROGRAM_MAP(snesnew_map)
|
|
|
|
MCFG_MACHINE_START(snesnew)
|
|
|
|
MCFG_SNS_CARTRIDGE_ADD("snsslot", snes_cart, NULL, NULL)
|
|
MCFG_SOFTWARE_LIST_ADD("cart_list","snes")
|
|
MCFG_SOFTWARE_LIST_ADD("bsx_list","snes_bspack")
|
|
MCFG_SOFTWARE_LIST_ADD("st_list","snes_strom")
|
|
MACHINE_CONFIG_END
|
|
|
|
static MACHINE_CONFIG_DERIVED( snespnew, snesnew )
|
|
MCFG_CPU_MODIFY( "maincpu" )
|
|
MCFG_CPU_CLOCK( MCLK_PAL )
|
|
|
|
MCFG_SCREEN_MODIFY("screen")
|
|
MCFG_SCREEN_RAW_PARAMS(DOTCLK_PAL, SNES_HTOTAL, 0, SNES_SCR_WIDTH, SNES_VTOTAL_PAL, 0, SNES_SCR_HEIGHT_PAL)
|
|
MACHINE_CONFIG_END
|
|
|
|
|
|
#define rom_snesnew rom_snes
|
|
#define rom_snespnew rom_snespal
|
|
|
|
CONS( 1989, snesnew, snes, 0, snesnew, snes, snes_state, snes_mess, "Nintendo", "Super Nintendo Entertainment System / Super Famicom (NTSC, Test)", GAME_NOT_WORKING )
|
|
CONS( 1989, snespnew, snes, 0, snespnew, snes, snes_state, snes_mess, "Nintendo", "Super Nintendo Entertainment System (PAL, Test)", GAME_NOT_WORKING )
|