From 5d05f2ff146f37f9ede1a083ae4275c7f50a7b22 Mon Sep 17 00:00:00 2001 From: Fabio Priuli Date: Fri, 7 Jun 2013 14:03:24 +0000 Subject: [PATCH] (MESS) snes: added skeleton SA-1 support. nw. --- .gitattributes | 2 + src/mess/drivers/snes.c | 100 +++++- src/mess/machine/sns_sa1.c | 628 +++++++++++++++++++++++++++++++++++++ src/mess/machine/sns_sa1.h | 70 +++++ src/mess/mess.mak | 1 + 5 files changed, 799 insertions(+), 2 deletions(-) create mode 100644 src/mess/machine/sns_sa1.c create mode 100644 src/mess/machine/sns_sa1.h diff --git a/.gitattributes b/.gitattributes index 9d5baf724b2..c9af8027333 100644 --- a/.gitattributes +++ b/.gitattributes @@ -7755,6 +7755,8 @@ src/mess/machine/sns_rom.c svneol=native#text/plain src/mess/machine/sns_rom.h svneol=native#text/plain src/mess/machine/sns_rom21.c svneol=native#text/plain src/mess/machine/sns_rom21.h svneol=native#text/plain +src/mess/machine/sns_sa1.c svneol=native#text/plain +src/mess/machine/sns_sa1.h svneol=native#text/plain src/mess/machine/sns_sdd1.c svneol=native#text/plain src/mess/machine/sns_sdd1.h svneol=native#text/plain src/mess/machine/sns_sfx.c svneol=native#text/plain diff --git a/src/mess/drivers/snes.c b/src/mess/drivers/snes.c index bbed04b6222..d43047ca42e 100644 --- a/src/mess/drivers/snes.c +++ b/src/mess/drivers/snes.c @@ -37,6 +37,7 @@ #include "machine/sns_rom.h" #include "machine/sns_rom21.h" #include "machine/sns_bsx.h" +#include "machine/sns_sa1.h" #include "machine/sns_sdd1.h" #include "machine/sns_sfx.h" #include "machine/sns_spc7110.h" @@ -70,6 +71,10 @@ public: DECLARE_READ8_MEMBER( snessfx_lo_r ); DECLARE_WRITE8_MEMBER( snessfx_hi_w ); DECLARE_WRITE8_MEMBER( snessfx_lo_w ); + DECLARE_READ8_MEMBER( snessa1_hi_r ); + DECLARE_READ8_MEMBER( snessa1_lo_r ); + DECLARE_WRITE8_MEMBER( snessa1_hi_w ); + DECLARE_WRITE8_MEMBER( snessa1_lo_w ); DECLARE_READ8_MEMBER( snes7110_hi_r ); DECLARE_READ8_MEMBER( snes7110_lo_r ); DECLARE_WRITE8_MEMBER( snes7110_hi_w ); @@ -514,6 +519,93 @@ WRITE8_MEMBER( snes_console_state::snessfx_lo_w ) snessfx_hi_w(space, offset, data, 0xff); } +//--------------------------------------------------------------------------------- +// LoROM + SA-1 +//--------------------------------------------------------------------------------- + +READ8_MEMBER( snes_console_state::snessa1_hi_r ) +{ + UINT16 address = offset & 0xffff; + + if (offset < 0x400000) + { + if (address < 0x2000) + return space.read_byte(0x7e0000 + address); + else if (address < 0x6000) + { + if (address >= 0x2200 && address < 0x2400) + return m_cartslot->chip_read(space, offset); // SA-1 Regs + else if (address >= 0x3000 && address < 0x3800) + return m_cartslot->chip_read(space, offset); // Internal SA-1 RAM (2K) + else + return snes_r_io(space, address); + } + else if (address < 0x8000) + return m_cartslot->chip_read(space, offset); // SA-1 BWRAM + else + return m_cartslot->read_h(space, offset); + } + else + return m_cartslot->read_h(space, offset); +} + +READ8_MEMBER( snes_console_state::snessa1_lo_r ) +{ + UINT16 address = offset & 0xffff; + + if (offset < 0x400000) + { + if (address < 0x2000) + return space.read_byte(0x7e0000 + address); + else if (address < 0x6000) + { + if (address >= 0x2200 && address < 0x2400) + return m_cartslot->chip_read(space, offset); // SA-1 Regs + else if (address >= 0x3000 && address < 0x3800) + return m_cartslot->chip_read(space, offset); // Internal SA-1 RAM (2K) + else + return snes_r_io(space, address); + } + else if (address < 0x8000) + return m_cartslot->chip_read(space, offset); // SA-1 BWRAM + else + return m_cartslot->read_l(space, offset); + } + else if (offset < 0x500000) + return m_cartslot->chip_read(space, offset); // SA-1 BWRAM (not mirrored above!) + else + return snes_r_io(space, address); // nothing mapped here! +} + +WRITE8_MEMBER( snes_console_state::snessa1_hi_w ) +{ + UINT16 address = offset & 0xffff; + if (offset < 0x400000) + { + if (address < 0x2000) + space.write_byte(0x7e0000 + address, data); + else if (address < 0x6000) + { + if (address >= 0x2200 && address < 0x2400) + m_cartslot->chip_write(space, offset, data); // SA-1 Regs + else if (address >= 0x3000 && address < 0x3800) + m_cartslot->chip_write(space, offset, data); // Internal SA-1 RAM (2K) + else + snes_w_io(space, address, data); + } + else if (address < 0x8000) + m_cartslot->chip_write(space, offset, data); // SA-1 BWRAM + } +} + +WRITE8_MEMBER( snes_console_state::snessa1_lo_w ) +{ + if (offset >= 0x400000 && offset < 0x500000) + m_cartslot->chip_write(space, offset, data); // SA-1 BWRAM (not mirrored above!) + else + snessfx_hi_w(space, offset, data, 0xff); +} + //--------------------------------------------------------------------------------- // HiROM + SPC-7110 //--------------------------------------------------------------------------------- @@ -1484,7 +1576,7 @@ static SLOT_INTERFACE_START(snes_cart) 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_sa1", SNS_LOROM_SA1) // 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 @@ -1535,10 +1627,14 @@ void snes_console_state::machine_start() case SNES_CX4: // this still uses the old simulation instead of emulating the CPU case SNES_ST010: // this requires two diff kinds of chip access, so we handle it in snes20_lo/hi_r/w case SNES_ST011: // this requires two diff kinds of chip access, so we handle it in snes20_lo/hi_r/w - case SNES_SA1: // still unemulated case SNES_ST018: // still unemulated case SNES_Z80GB: // still unemulated break; + case SNES_SA1: // skeleton support + m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8_delegate(FUNC(snes_console_state::snessa1_lo_r),this), write8_delegate(FUNC(snes_console_state::snessa1_lo_w),this)); + m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x800000, 0xffffff, read8_delegate(FUNC(snes_console_state::snessa1_hi_r),this), write8_delegate(FUNC(snes_console_state::snessa1_hi_w),this)); + set_5a22_map(m_maincpu); + break; case SNES_DSP: m_maincpu->space(AS_PROGRAM).install_read_handler(0x208000, 0x20ffff, 0, 0x9f0000, read8_delegate(FUNC(base_sns_cart_slot_device::chip_read),(base_sns_cart_slot_device*)m_cartslot)); m_maincpu->space(AS_PROGRAM).install_write_handler(0x208000, 0x20ffff, 0, 0x9f0000, write8_delegate(FUNC(base_sns_cart_slot_device::chip_write),(base_sns_cart_slot_device*)m_cartslot)); diff --git a/src/mess/machine/sns_sa1.c b/src/mess/machine/sns_sa1.c new file mode 100644 index 00000000000..b74127e1c78 --- /dev/null +++ b/src/mess/machine/sns_sa1.c @@ -0,0 +1,628 @@ +/*********************************************************************************************************** + + SA-1 add-on chip emulation (for SNES/SFC) + + Copyright MESS Team. + Visit http://mamedev.org for licensing and usage restrictions. + + Note: + - SA-1 register description below is based on no$cash docs. + - about bankswitch handling: no matter what is ROM size, at loading the ROM is mirrored up to 8MB and a + rom_bank_map[0x100] array is built as a lookup table for 256x32KB banks filling the 8MB accessible ROM + area; this allows to handle any 0-7 value written to CXB/DXB/EXB/FXB SA-1 registers without any masking! + - about BWRAM "bitmap mode": in 2bits mode + 600000h.Bit0-1 mirrors to 400000h.Bit0-1 + 600001h.Bit0-1 mirrors to 400000h.Bit2-3 + 600002h.Bit0-1 mirrors to 400000h.Bit4-5 + 600003h.Bit0-1 mirrors to 400000h.Bit6-7 + ... + in 4bits mode + 600000h.Bit0-3 mirrors to 400000h.Bit0-3 + 600001h.Bit0-3 mirrors to 400000h.Bit4-7 + 600002h.Bit0-3 mirrors to 400001h.Bit0-3 + 600003h.Bit0-3 mirrors to 400001h.Bit4-7 + ... + to handle the separate modes, bitmap accesses go to offset + 0x100000 + + TODO: + - test case for BWRAM & IRAM write protect (bsnes does not seem to ever protect either, so it's not implemented + for the moment) + - almost everything CPU related! + + ***********************************************************************************************************/ + + +#include "emu.h" +#include "machine/sns_sa1.h" + + +//------------------------------------------------- +// constructor +//------------------------------------------------- + +const device_type SNS_LOROM_SA1 = &device_creator; + + +sns_sa1_device::sns_sa1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, SNS_LOROM_SA1, "SNES Cart + SA-1", tag, owner, clock, "sns_rom_sa1", __FILE__), + device_sns_cart_interface( mconfig, *this ), + m_sa1(*this, "sa1cpu") +{ +} + + +void sns_sa1_device::device_start() +{ +} + +/*------------------------------------------------- + mapper specific handlers + -------------------------------------------------*/ + +/*------------------------------------------------- + RAM / SRAM / Registers + -------------------------------------------------*/ + +UINT8 sns_sa1_device::read_regs(UINT32 offset) +{ + UINT8 value = 0xff; + offset &= 0x1ff; // $2200 + offset gives the reg value to compare with docs + + switch (offset) + { + case 0x100: + // SNES SFR SNES CPU Flag Read (R) + break; + case 0x101: + // SA-1 CFR SA-1 CPU Flag Read (R) + break; + case 0x102: + // SA-1 HCR H-Count Read Lsb / Do Latching (R) + break; + case 0x103: + // SA-1 HCR H-Count Read Msb (R) + break; + case 0x104: + // SA-1 VCR V-Count Read Lsb (R) + break; + case 0x105: + // SA-1 VCR V-Count Read Msb (R) + break; + case 0x106: + // SA-1 MR Arithmetic Result, bit0-7 (Sum/Product/Quotient) (R) + break; + case 0x107: + // SA-1 MR Arithmetic Result, bit8-15 (Sum/Product/Quotient) (R) + break; + case 0x108: + // SA-1 MR Arithmetic Result, bit16-23 (Sum/Product/Remainder) (R) + break; + case 0x109: + // SA-1 MR Arithmetic Result, bit24-31 (Sum/Product/Remainder) (R) + break; + case 0x10a: + // SA-1 MR Arithmetic Result, bit32-39 (Sum) (R) + break; + case 0x10b: + // SA-1 OF Arithmetic Overflow Flag (R) + break; + case 0x10c: + // SA-1 VDP Variable-Length Data Read Port Lsb (R) + break; + case 0x10d: + // SA-1 VDP Variable-Length Data Read Port Msb (R) + break; + case 0x10e: + // SNES VC Version Code Register (R) + break; + default: + logerror("SA-1 Read access to an unmapped reg (%x)", offset); + break; + } + return value; +} + +void sns_sa1_device::write_regs(UINT32 offset, UINT8 data) +{ + offset &= 0x1ff; // $2200 + offset gives the reg value to compare with docs + + switch (offset) + { + case 0x000: + // SNES CCNT 20h SA-1 CPU Control (W) + break; + case 0x001: + // SNES SIE 00h SNES CPU Int Enable (W) + break; + case 0x002: + // SNES SIC 00h SNES CPU Int Clear (W) + break; + case 0x003: + // SNES CRV - SA-1 CPU Reset Vector Lsb (W) + break; + case 0x004: + // SNES CRV - SA-1 CPU Reset Vector Msb (W) + break; + case 0x005: + // SNES CNV - SA-1 CPU NMI Vector Lsb (W) + break; + case 0x006: + // SNES CNV - SA-1 CPU NMI Vector Msb (W) + break; + case 0x007: + // SNES CIV - SA-1 CPU IRQ Vector Lsb (W) + break; + case 0x008: + // SNES CIV - SA-1 CPU IRQ Vector Msb (W) + break; + case 0x009: + // SA-1 SCNT 00h SNES CPU Control (W) + break; + case 0x00a: + // SA-1 CIE 00h SA-1 CPU Int Enable (W) + break; + case 0x00b: + // SA-1 CIC 00h SA-1 CPU Int Clear (W) + break; + case 0x00c: + // SA-1 SNV - SNES CPU NMI Vector Lsb (W) + break; + case 0x00d: + // SA-1 SNV - SNES CPU NMI Vector Msb (W) + break; + case 0x00e: + // SA-1 SIV - SNES CPU IRQ Vector Lsb (W) + break; + case 0x00f: + // SA-1 SIV - SNES CPU IRQ Vector Msb (W) + break; + case 0x010: + // SA-1 TMC 00h H/V Timer Control (W) + break; + case 0x011: + // SA-1 CTR - SA-1 CPU Timer Restart (W) + break; + case 0x012: + // SA-1 HCNT - Set H-Count Lsb (W) + break; + case 0x013: + // SA-1 HCNT - Set H-Count Msb (W) + break; + case 0x014: + // SA-1 VCNT - Set V-Count Lsb (W) + break; + case 0x015: + // SA-1 VCNT - Set V-Count Msb (W) + break; + case 0x020: + // ROM 1MB bank for [c0-cf] + m_bank_c_hi = BIT(data, 7); + m_bank_c_rom = data & 0x07; + break; + case 0x021: + // ROM 1MB bank for [d0-df] + m_bank_d_hi = BIT(data, 7); + m_bank_d_rom = data & 0x07; + break; + case 0x022: + // ROM 1MB bank for [e0-ef] + m_bank_e_hi = BIT(data, 7); + m_bank_e_rom = data & 0x07; + break; + case 0x023: + // ROM 1MB bank for [f0-ff] + m_bank_f_hi = BIT(data, 7); + m_bank_f_rom = data & 0x07; + break; + case 0x024: + // BWRAM bank from SNES side + m_bwram_snes = data & 0x1f; // max 32x8K banks + break; + case 0x025: + // BWRAM bank & type from SA-1 side + m_bwram_sa1_source = BIT(data, 7); // 0 = normal, 1 = bitmap? + m_bwram_sa1 = data & 0x7f; // up to 128x8K banks here? + break; + case 0x026: + // enable writing to BWRAM from SNES + m_bwram_write_snes = BIT(data, 7); + break; + case 0x027: + // enable writing to BWRAM from SA-1 + m_bwram_write_sa1 = BIT(data, 7); + break; + case 0x028: + // write protected area at bottom of BWRAM + m_bwpa_sa1 = 0x100 * (data & 0x0f); + break; + case 0x029: + // enable writing to IRAM from SNES (1 bit for each 0x100 chunk) + m_iram_write_snes = data; + break; + case 0x02a: + // enable writing to IRAM from SA-1 (1 bit for each 0x100 chunk) + m_iram_write_sa1 = data; + break; + case 0x030: + // SA-1 DCNT 00h DMA Control (W) + break; + case 0x031: + // Both CDMA 00h Character Conversion DMA Parameters (W) + break; + case 0x032: + // Both SDA - DMA Source Device Start Address Lsb (W) + break; + case 0x033: + // Both SDA - DMA Source Device Start Address Mid (W) + break; + case 0x034: + // Both SDA - DMA Source Device Start Address Msb (W) + break; + case 0x035: + // Both DDA - DMA Dest Device Start Address Lsb (W) + break; + case 0x036: + // Both DDA - DMA Dest Device Start Address Mid (Start/I-RAM) (W) + break; + case 0x037: + // Both DDA - DMA Dest Device Start Address Msb (Start/BW-RAM)(W) + break; + case 0x038: + // SA-1 DTC - DMA Terminal Counter Lsb (W) + break; + case 0x039: + // SA-1 DTC - DMA Terminal Counter Msb (W) + break; + case 0x03f: + // Format for BWRAM when mapped to bitmap + m_bwram_sa1_format = BIT(data, 7); // 0 = 4bit, 1 = 2bit + break; + case 0x040: + case 0x041: + case 0x042: + case 0x043: + case 0x044: + case 0x045: + case 0x046: + case 0x047: + case 0x048: + case 0x049: + case 0x04a: + case 0x04b: + case 0x04c: + case 0x04d: + case 0x04e: + case 0x04f: + // SA-1 BRF - Bit Map Register File (2240h..224Fh) (W) + break; + case 0x050: + // SA-1 MCNT 00h Arithmetic Control (W) + break; + case 0x051: + // SA-1 MA - Arithmetic Param A Lsb (Multiplicand/Dividend) (W) + break; + case 0x052: + // SA-1 MA - Arithmetic Param A Msb (Multiplicand/Dividend) (W) + break; + case 0x053: + // SA-1 MB - Arithmetic Param B Lsb (Multiplier/Divisor) (W) + break; + case 0x054: + // SA-1 MB - Arithmetic Param B Msb (Multiplier/Divisor)/Start (W) + break; + case 0x058: + // SA-1 VBD - Variable-Length Bit Processing (W) + break; + case 0x059: + // SA-1 VDA - Var-Length Bit Game Pak ROM Start Address Lsb (W) + break; + case 0x05a: + // SA-1 VDA - Var-Length Bit Game Pak ROM Start Address Mid (W) + break; + case 0x05b: + // SA-1 VDA - Var-Length Bit Game Pak ROM Start Address Msb & Kick + break; + default: + logerror("SA-1 Write access to an unmapped reg (%x) with data %x", offset, data); + break; + } +} + +UINT8 sns_sa1_device::read_iram(UINT32 offset) +{ + return m_internal_ram[offset & 0x7ff]; +} + +void sns_sa1_device::write_iram(UINT32 offset, UINT8 data) +{ + m_internal_ram[offset & 0x7ff] = data; +} + +UINT8 sns_sa1_device::read_bwram(UINT32 offset) +{ + int shift = 0; + UINT8 mask = 0xff; + + if (!m_nvram) + return 0xff; // this should probably never happen, or are there SA-1 games with no BWRAM? + + if (offset < 0x100000) + return m_nvram[offset & (m_nvram_size - 1)]; + + // Bitmap BWRAM + if (m_bwram_sa1_format) + { + // 2bits mode + offset /= 4; + shift = ((offset % 4) * 2); + mask = 0x03; + } + else + { + // 4bits mode + offset /= 2; + shift = ((offset % 2) * 4); + mask = 0x0f; + } + + // only return the correct bits + return (m_nvram[offset & (m_nvram_size - 1)] >> shift) & mask; +} + +void sns_sa1_device::write_bwram(UINT32 offset, UINT8 data) +{ + UINT8 mask = 0xff; + + if (!m_nvram) + return; // this should probably never happen, or are there SA-1 games with no BWRAM? + + if (offset < 0x100000) + { + m_nvram[offset & (m_nvram_size - 1)] = data; + return; + } + + // Bitmap BWRAM + if (m_bwram_sa1_format) + { + // 2bits mode + offset /= 4; + data = (data & 0x03) << ((offset % 4) * 2); + mask = 0x03 << ((offset % 4) * 2); + } + else + { + // 4bits mode + offset /= 2; + data = (data & 0x0f) << ((offset % 2) * 4); + mask = 0x0f << ((offset % 2) * 4); + } + + // only change the correct bits, keeping the rest untouched + m_nvram[offset & (m_nvram_size - 1)] = (m_nvram[offset & (m_nvram_size - 1)] & ~mask) | data; +} + + + +/*------------------------------------------------- + Accesses from SNES CPU + -------------------------------------------------*/ + + +READ8_MEMBER(sns_sa1_device::read_l) +{ + int bank = 0; + + // ROM is mapped to [00-3f][8000-ffff] only here + if (offset < 0x200000) + { + if (!m_bank_c_hi) // when HiROM mapping is disabled, we always access first 1MB here + bank = (offset / 0x10000) + 0x00; + else // when HiROM mapping is enabled, we mirror [c0-cf][0000-ffff] bank + bank = (offset / 0x10000) + (m_bank_c_rom * 0x20); + + return m_rom[rom_bank_map[bank] * 0x8000 + (offset & 0x7fff)]; + } + else if (offset < 0x400000) + { + offset -= 0x200000; + if (!m_bank_d_hi) // when HiROM mapping is disabled, we always access second 1MB here + bank = (offset / 0x10000) + 0x20; + else // when HiROM mapping is enabled, we mirror [d0-df][0000-ffff] bank + bank = (offset / 0x10000) + (m_bank_d_rom * 0x20); + + return m_rom[rom_bank_map[bank] * 0x8000 + (offset & 0x7fff)]; + } + else + return 0; // this should not happen (the driver should only call read_l in the above case) +} + +READ8_MEMBER(sns_sa1_device::read_h) +{ + int bank = 0; + + // ROM is mapped to [80-bf][8000-ffff] & [c0-ff][0000-ffff] + if (offset < 0x200000) + { + if (!m_bank_e_hi) // when HiROM mapping is disabled, we always access third 1MB here + bank = (offset / 0x10000) + 0x40; + else // when HiROM mapping is enabled, we mirror [e0-ef][0000-ffff] bank + bank = (offset / 0x10000) + (m_bank_e_rom * 0x20); + + return m_rom[rom_bank_map[bank] * 0x8000 + (offset & 0x7fff)]; + } + else if (offset < 0x400000) + { + offset -= 0x200000; + if (!m_bank_f_hi) // when HiROM mapping is disabled, we always access fourth 1MB here + bank = (offset / 0x10000) + 0x60; + else // when HiROM mapping is enabled, we mirror [f0-ff][0000-ffff] bank + bank = (offset / 0x10000) + (m_bank_f_rom * 0x20); + + return m_rom[rom_bank_map[bank] * 0x8000 + (offset & 0x7fff)]; + } + else if (offset < 0x500000) + return m_rom[rom_bank_map[(m_bank_c_rom * 0x20) + (offset / 0x8000)] * 0x8000 + (offset & 0x7fff)]; + else if (offset < 0x600000) + return m_rom[rom_bank_map[(m_bank_d_rom * 0x20) + (offset / 0x8000)] * 0x8000 + (offset & 0x7fff)]; + else if (offset < 0x700000) + return m_rom[rom_bank_map[(m_bank_e_rom * 0x20) + (offset / 0x8000)] * 0x8000 + (offset & 0x7fff)]; + else + return m_rom[rom_bank_map[(m_bank_f_rom * 0x20) + (offset / 0x8000)] * 0x8000 + (offset & 0x7fff)]; +} + +WRITE8_MEMBER(sns_sa1_device::write_l) +{ +} + +WRITE8_MEMBER(sns_sa1_device::write_h) +{ +} + +READ8_MEMBER( sns_sa1_device::chip_read ) +{ + UINT16 address = offset & 0xffff; + + if (offset < 0x400000 && address >= 0x2200 && address < 0x2400) + return read_regs(address & 0x1ff); // SA-1 Regs + + if (offset < 0x400000 && address >= 0x3000 && address < 0x3800) + return read_iram(address & 0x7ff); // Internal SA-1 RAM (2K) + + if (offset < 0x400000 && address >= 0x6000 && address < 0x8000) + return read_bwram((m_bwram_snes * 0x2000) + (offset & 0x1fff)); // SA-1 BWRAM + + if (offset >= 0x400000 && offset < 0x500000) + return read_bwram(offset); // SA-1 BWRAM again (but not called for the [c0-cf] range, because it's not mirrored) + + return 0xff; +} + + +WRITE8_MEMBER( sns_sa1_device::chip_write ) +{ + UINT16 address = offset & 0xffff; + + if (offset < 0x400000 && address >= 0x2200 && address < 0x2400) + write_regs(address & 0x1ff, data); // SA-1 Regs + + if (offset < 0x400000 && address >= 0x3000 && address < 0x3800) + write_iram(address & 0x7ff, data); // Internal SA-1 RAM (2K) + + if (offset < 0x400000 && address >= 0x6000 && address < 0x8000) + write_bwram((m_bwram_snes * 0x2000) + (offset & 0x1fff), data); // SA-1 BWRAM + + if (offset >= 0x400000 && offset < 0x500000) + write_bwram(offset, data); // SA-1 BWRAM again (but not called for the [c0-cf] range, because it's not mirrored) +} + + +/*------------------------------------------------- + Accesses from SA-1 CPU + -------------------------------------------------*/ + +// These handlers basically match the SNES CPU ones, but there is no access to internal +// I/O regs or WRAM, and there are a few additional accesses to IRAM (in [00-3f][0000-07ff]) +// and to BWRAM (in [60-6f][0000-ffff], so-called bitmap mode) + +READ8_MEMBER( sns_sa1_device::sa1_hi_r ) +{ + UINT16 address = offset & 0xffff; + + if (offset < 0x400000) + { + if (address < 0x6000) + { + if (address < 0x0800) + return read_iram(offset); // Internal SA-1 RAM (2K) + else if (address >= 0x2200 && address < 0x2400) + return read_regs(offset & 0x1ff); // SA-1 Regs + else if (address >= 0x3000 && address < 0x3800) + return read_iram(offset); // Internal SA-1 RAM (2K) + } + else if (address < 0x8000) + return read_bwram((m_bwram_sa1 * 0x2000) + (offset & 0x1fff) + (m_bwram_sa1_source * 0x100000)); // SA-1 BWRAM + else + return read_h(space, offset); // ROM + + return 0xff; // maybe open bus? same as the main system one or diff? (currently not accessible from carts anyway...) + } + else + return read_h(space, offset); // ROM +} + +READ8_MEMBER( sns_sa1_device::sa1_lo_r ) +{ + UINT16 address = offset & 0xffff; + + if (offset < 0x400000) + { + if (address < 0x6000) + { + if (address < 0x0800) + return read_iram(offset); // Internal SA-1 RAM (2K) + else if (address >= 0x2200 && address < 0x2400) + return read_regs(offset & 0x1ff); // SA-1 Regs + else if (address >= 0x3000 && address < 0x3800) + return read_iram(offset); // Internal SA-1 RAM (2K) + } + else if (address < 0x8000) + return read_bwram((m_bwram_sa1 * 0x2000) + (offset & 0x1fff) + (m_bwram_sa1_source * 0x100000)); // SA-1 BWRAM + else + return read_l(space, offset); // ROM + + return 0xff; // maybe open bus? same as the main system one or diff? (currently not accessible from carts anyway...) + } + else if (offset < 0x500000) + return read_bwram(offset); // SA-1 BWRAM (not mirrored above!) + else if (offset >= 0x600000 && offset < 0x700000) + return read_bwram((offset & 0xfffff) + 0x100000); // SA-1 BWRAM Bitmap mode + else + return 0xff; // nothing should be mapped here, so maybe open bus? +} + +WRITE8_MEMBER( sns_sa1_device::sa1_hi_w ) +{ + UINT16 address = offset & 0xffff; + if (offset < 0x400000) + { + if (address < 0x6000) + { + if (address < 0x0800) + write_iram(offset, data); // Internal SA-1 RAM (2K) + else if (address >= 0x2200 && address < 0x2400) + write_regs(offset & 0x1ff, data); // SA-1 Regs + else if (address >= 0x3000 && address < 0x3800) + write_iram(offset, data); // Internal SA-1 RAM (2K) + } + else if (address < 0x8000) + write_bwram((m_bwram_sa1 * 0x2000) + (offset & 0x1fff) + (m_bwram_sa1_source * 0x100000), data); // SA-1 BWRAM + } +} + +WRITE8_MEMBER( sns_sa1_device::sa1_lo_w ) +{ + if (offset >= 0x400000 && offset < 0x500000) + write_bwram(offset & 0xfffff, data); // SA-1 BWRAM (not mirrored above!) + else if (offset >= 0x600000 && offset < 0x700000) + write_bwram((offset & 0xfffff) + 0x100000, data); // SA-1 BWRAM Bitmap mode + else + sa1_hi_w(space, offset, data); +} + +static ADDRESS_MAP_START( sa1_map, AS_PROGRAM, 8, sns_sa1_device ) + AM_RANGE(0x000000, 0x7dffff) AM_READWRITE(sa1_lo_r, sa1_lo_w) + AM_RANGE(0x7e0000, 0x7fffff) AM_NOP + AM_RANGE(0x800000, 0xffffff) AM_READWRITE(sa1_hi_r, sa1_hi_w) +ADDRESS_MAP_END + + +static MACHINE_CONFIG_FRAGMENT( snes_sa1 ) + MCFG_CPU_ADD("sa1cpu", _5A22, 10000000) + MCFG_CPU_PROGRAM_MAP(sa1_map) +MACHINE_CONFIG_END + +machine_config_constructor sns_sa1_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( snes_sa1 ); +} diff --git a/src/mess/machine/sns_sa1.h b/src/mess/machine/sns_sa1.h new file mode 100644 index 00000000000..664fa8c1022 --- /dev/null +++ b/src/mess/machine/sns_sa1.h @@ -0,0 +1,70 @@ +#ifndef __SNS_SA1_H +#define __SNS_SA1_H + +#include "machine/sns_slot.h" +#include "cpu/g65816/g65816.h" + + +// ======================> sns_sa1_device + +class sns_sa1_device : public device_t, + public device_sns_cart_interface +{ +public: + // construction/destruction + sns_sa1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + // device-level overrides + virtual void device_start(); + virtual machine_config_constructor device_mconfig_additions() const; + + // reading and writing + virtual DECLARE_READ8_MEMBER(read_l); + virtual DECLARE_READ8_MEMBER(read_h); + virtual DECLARE_WRITE8_MEMBER(write_l); + virtual DECLARE_WRITE8_MEMBER(write_h); + + // additional reading and writing + virtual DECLARE_READ8_MEMBER(chip_read); + virtual DECLARE_WRITE8_MEMBER(chip_write); + + DECLARE_READ8_MEMBER(sa1_lo_r); + DECLARE_READ8_MEMBER(sa1_hi_r); + DECLARE_WRITE8_MEMBER(sa1_lo_w); + DECLARE_WRITE8_MEMBER(sa1_hi_w); + +private: + + UINT8 read_regs(UINT32 offset); + UINT8 read_iram(UINT32 offset); + UINT8 read_bwram(UINT32 offset); + void write_regs(UINT32 offset, UINT8 data); + void write_iram(UINT32 offset, UINT8 data); + void write_bwram(UINT32 offset, UINT8 data); + + required_device<_5a22_device> m_sa1; + + UINT8 m_internal_ram[0x800]; + + // register related + // $2220-$2223 + int m_bank_c_hi, m_bank_c_rom; + int m_bank_d_hi, m_bank_d_rom; + int m_bank_e_hi, m_bank_e_rom; + int m_bank_f_hi, m_bank_f_rom; + // $2224-$2225 & $223f + UINT8 m_bwram_snes, m_bwram_sa1; + int m_bwram_sa1_source, m_bwram_sa1_format; + // $2226-$2227 + int m_bwram_write_snes, m_bwram_write_sa1; + // $2228 + UINT32 m_bwpa_sa1; + // $2229-$222a + UINT8 m_iram_write_snes, m_iram_write_sa1; +}; + + +// device type definition +extern const device_type SNS_LOROM_SA1; + +#endif diff --git a/src/mess/mess.mak b/src/mess/mess.mak index f32bdaf221d..ad74ed16e6e 100644 --- a/src/mess/mess.mak +++ b/src/mess/mess.mak @@ -1677,6 +1677,7 @@ $(MESSOBJ)/nintendo.a: \ $(MESS_MACHINE)/sns_rom.o \ $(MESS_MACHINE)/sns_rom21.o \ $(MESS_MACHINE)/sns_bsx.o \ + $(MESS_MACHINE)/sns_sa1.o \ $(MESS_MACHINE)/sns_sdd1.o \ $(MESS_MACHINE)/sns_sfx.o \ $(MESS_MACHINE)/sns_spc7110.o \