diff --git a/hash/snes.xml b/hash/snes.xml index 61385ea032f..ca64b570696 100644 --- a/hash/snes.xml +++ b/hash/snes.xml @@ -15397,7 +15397,7 @@ more investigation needed... - + diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 1ef192b9890..1b5484abf58 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -3675,6 +3675,8 @@ if (BUSES["SNES"]~=null) then MAME_DIR .. "src/devices/bus/snes/sgb.h", MAME_DIR .. "src/devices/bus/snes/spc7110.cpp", MAME_DIR .. "src/devices/bus/snes/spc7110.h", + MAME_DIR .. "src/devices/bus/snes/st018.cpp", + MAME_DIR .. "src/devices/bus/snes/st018.h", MAME_DIR .. "src/devices/bus/snes/sufami.cpp", MAME_DIR .. "src/devices/bus/snes/sufami.h", MAME_DIR .. "src/devices/bus/snes/upd.cpp", diff --git a/src/devices/bus/snes/snes_carts.cpp b/src/devices/bus/snes/snes_carts.cpp index 228c340fac4..f29610c20e2 100644 --- a/src/devices/bus/snes/snes_carts.cpp +++ b/src/devices/bus/snes/snes_carts.cpp @@ -20,6 +20,7 @@ #include "sfx.h" #include "sgb.h" #include "spc7110.h" +#include "st018.h" #include "sufami.h" #include "upd.h" @@ -40,7 +41,7 @@ void snes_cart(device_slot_interface &device) device.option_add_internal("lorom_sgb2", SNS_LOROM_SUPERGB2); // SuperGB2 base cart - unsupported device.option_add_internal("lorom_st010", SNS_LOROM_SETA10); device.option_add_internal("lorom_st011", SNS_LOROM_SETA11); - device.option_add_internal("lorom_st018", SNS_LOROM); // Cart + ST018 - unsupported + device.option_add_internal("lorom_st018", SNS_LOROM_ST018); device.option_add_internal("lorom_sufami", SNS_LOROM_SUFAMI); // Sufami Turbo base cart device.option_add_internal("hirom", SNS_HIROM); device.option_add_internal("hirom_bsx", SNS_HIROM_BSX); // HiROM + BS-X slot - unsupported diff --git a/src/devices/bus/snes/st018.cpp b/src/devices/bus/snes/st018.cpp new file mode 100644 index 00000000000..adc15a921d0 --- /dev/null +++ b/src/devices/bus/snes/st018.cpp @@ -0,0 +1,161 @@ +// license:BSD-3-Clause +// copyright-holders:cam900 +/*********************************************************************************************************** + + ARMv3 add-on chip emulation (for SNES/SFC) + used in carts with ST-018 add-on chips + + ***********************************************************************************************************/ + + +#include "emu.h" +#include "st018.h" + + +// helpers +inline uint32_t get_prg(uint8_t *CPU, uint32_t addr) +{ + return (CPU[addr * 4] | (CPU[addr * 4 + 1] << 8) | (CPU[addr * 4 + 2] << 16) | (CPU[addr * 4 + 3] << 24)); +} + +//------------------------------------------------- +// constructor +//------------------------------------------------- + +DEFINE_DEVICE_TYPE(SNS_LOROM_ST018, sns_rom_st018_device, "sns_rom_st018", "SNES Cart (LoROM) + Seta ST018") + + +sns_rom_st018_device::sns_rom_st018_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : sns_rom_device(mconfig, SNS_LOROM_ST018, tag, owner, clock) + , m_copro(*this, "copro") + , m_cpu2copro(*this, "cpu2copro") + , m_copro2cpu(*this, "copro2cpu") + , m_signal(false) + , m_copro_reset(false) +{ +} + +void sns_rom_st018_device::device_start() +{ + m_copro_prg.resize(0x20000/sizeof(uint32_t)); + m_copro_data.resize(0x8000/sizeof(uint32_t)); + + save_item(NAME(m_signal)); + save_item(NAME(m_copro_reset)); +} + +void sns_rom_st018_device::device_reset() +{ + m_signal = false; + m_copro_reset = false; + m_copro->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); +} + +/*------------------------------------------------- + mapper specific handlers + -------------------------------------------------*/ + +//------------------------------------------------- +// Seta ST018 +//------------------------------------------------- + +// ST018 dump contains prg at offset 0 and data at offset 0x20000 +uint32_t sns_rom_st018_device::copro_prg_r(offs_t offset) +{ + return get_prg(&m_bios[0], offset); +} + +uint32_t sns_rom_st018_device::copro_data_r(offs_t offset) +{ + return get_prg(&m_bios[0], offset + 0x20000/4); +} + +uint8_t sns_rom_st018_device::status_r() +{ + return (m_copro2cpu->pending_r() ? 0x01 : 0) | + (m_signal ? 0x04 : 0) | + (m_cpu2copro->pending_r() ? 0x08 : 0) | + (m_copro_reset ? 0 : 0x80); +} + +void sns_rom_st018_device::signal_w(uint8_t data) +{ + m_signal = true; +} + +//------------------------------------------------- +// copro_map +//------------------------------------------------- + +void sns_rom_st018_device::copro_map(address_map &map) +{ + map(0x0000'0000, 0x0001'ffff).r(FUNC(sns_rom_st018_device::copro_prg_r)); + map(0x4000'0000, 0x4000'0000).w(m_copro2cpu, FUNC(generic_latch_8_device::write)); + map(0x4000'0010, 0x4000'0010).r(m_cpu2copro, FUNC(generic_latch_8_device::read)).w(FUNC(sns_rom_st018_device::signal_w)); + map(0x4000'0020, 0x4000'0020).r(FUNC(sns_rom_st018_device::status_r)); + map(0x4000'0020, 0x4000'002f).nopw(); // Unknown write + map(0xa000'0000, 0xa000'7fff).r(FUNC(sns_rom_st018_device::copro_data_r)); + map(0xe000'0000, 0xe000'3fff).ram(); +} + + +//------------------------------------------------- +// device_add_mconfig - add device configuration +//------------------------------------------------- + +void sns_rom_st018_device::device_add_mconfig(machine_config &config) +{ + ARM7(config, m_copro, 21440000); // TODO: ARMv3 + m_copro->set_addrmap(AS_PROGRAM, &sns_rom_st018_device::copro_map); + + GENERIC_LATCH_8(config, m_cpu2copro); + GENERIC_LATCH_8(config, m_copro2cpu); +} + +uint8_t sns_rom_st018_device::chip_read(offs_t offset) +{ + uint8_t ret = 0xff; + switch (offset & 0x06) + { + case 0x00: + ret = m_copro2cpu->read(); + break; + case 0x02: + if (!machine().side_effects_disabled()) + m_signal = false; + break; + case 0x04: + ret = status_r(); + break; + } + return ret; +} + + +void sns_rom_st018_device::chip_write(offs_t offset, uint8_t data) +{ + switch (offset & 0x06) + { + case 0x02: + m_cpu2copro->write(data); + break; + case 0x04: + m_copro_reset = BIT(data, 0); + m_copro->set_input_line(INPUT_LINE_RESET, m_copro_reset ? ASSERT_LINE : CLEAR_LINE); + break; + } +} + + +// To make faster DSP access to its internal rom, let's install read banks and map m_bios there with correct byte order + +void sns_rom_st018_device::speedup_addon_bios_access() +{ + m_copro->space(AS_PROGRAM).install_rom(0x0000'0000, 0x0001'ffff, &m_copro_prg[0]); + m_copro->space(AS_PROGRAM).install_rom(0xa000'0000, 0xa000'7fff, &m_copro_data[0]); + // copy data in the correct format + for (int x = 0; x < 0x8000; x++) + m_copro_prg[x] = m_bios[x * 4] | (m_bios[x * 4 + 1] << 8) | (m_bios[x * 4 + 2] << 16) | (m_bios[x * 4 + 3] << 24); + for (int x = 0; x < 0x2000; x++) + m_copro_data[x] = m_bios[0x20000 + x * 4] | (m_bios[0x20000 + x * 4 + 1] << 8) | (m_bios[0x20000 + x * 4 + 2] << 16) | (m_bios[0x20000 + x * 4 + 3] << 24); +} diff --git a/src/devices/bus/snes/st018.h b/src/devices/bus/snes/st018.h new file mode 100644 index 00000000000..1621c7598d7 --- /dev/null +++ b/src/devices/bus/snes/st018.h @@ -0,0 +1,56 @@ +// license:BSD-3-Clause +// copyright-holders:cam900 +#ifndef MAME_BUS_SNES_ST018_H +#define MAME_BUS_SNES_ST018_H + +#pragma once + +#include "snes_slot.h" +#include "rom.h" +#include "cpu/arm7/arm7.h" +#include "machine/gen_latch.h" + +// ======================> sns_rom_st018_device + +class sns_rom_st018_device : public sns_rom_device +{ +public: + // construction/destruction + sns_rom_st018_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + // device-level overrides + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; + + virtual void speedup_addon_bios_access() override; + + // additional reading and writing + virtual uint8_t chip_read(offs_t offset) override; + virtual void chip_write(offs_t offset, uint8_t data) override; + +private: + uint32_t copro_prg_r(offs_t offset); + uint32_t copro_data_r(offs_t offset); + + uint8_t status_r(); + void signal_w(uint8_t data); + + void copro_map(address_map &map) ATTR_COLD; + + required_device m_copro; + required_device m_cpu2copro; + required_device m_copro2cpu; + + std::vector m_copro_prg; + std::vector m_copro_data; + + bool m_signal; + bool m_copro_reset; +}; + +// device type definition +DECLARE_DEVICE_TYPE(SNS_LOROM_ST018, sns_rom_st018_device) + +#endif // MAME_BUS_SNES_ST018_H diff --git a/src/mame/nintendo/snes.cpp b/src/mame/nintendo/snes.cpp index 93ad4be6e64..27e32acabb2 100644 --- a/src/mame/nintendo/snes.cpp +++ b/src/mame/nintendo/snes.cpp @@ -1200,7 +1200,10 @@ 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_ST018: // still unemulated + break; + case SNES_ST018: + m_maincpu->space(AS_PROGRAM).install_read_handler(0x003800, 0x0038ff, 0, 0xbf0000, 0, read8sm_delegate(*m_cartslot, FUNC(base_sns_cart_slot_device::chip_read))); + m_maincpu->space(AS_PROGRAM).install_write_handler(0x003800, 0x0038ff, 0, 0xbf0000, 0, write8sm_delegate(*m_cartslot, FUNC(base_sns_cart_slot_device::chip_write))); break; case SNES_Z80GB: // skeleton support m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x000000, 0x7dffff, read8m_delegate(*this, FUNC(snes_console_state::snessgb_lo_r)), write8m_delegate(*this, FUNC(snes_console_state::snessgb_lo_w)));