From d47d3ca4f7f87736de2fdb3a972e9f6be51aedca Mon Sep 17 00:00:00 2001 From: Nigel Barnes Date: Sun, 20 Jan 2019 11:24:51 +0000 Subject: sc3000: Added support for the SC-3000 Survivors Multicart and Megacart cartridges. --- src/devices/bus/sega8/rom.cpp | 112 +++++++++++++++++++++++++++++++++++ src/devices/bus/sega8/rom.h | 56 ++++++++++++++++++ src/devices/bus/sega8/sega8_slot.cpp | 30 +++++++++- src/devices/bus/sega8/sega8_slot.h | 9 ++- src/mame/drivers/sg1000.cpp | 4 +- 5 files changed, 207 insertions(+), 4 deletions(-) diff --git a/src/devices/bus/sega8/rom.cpp b/src/devices/bus/sega8/rom.cpp index 72017b5c795..1f039361a12 100644 --- a/src/devices/bus/sega8/rom.cpp +++ b/src/devices/bus/sega8/rom.cpp @@ -42,6 +42,9 @@ DEFINE_DEVICE_TYPE(SEGA8_ROM_KOREAN, sega8_korean_device, "sega8_kor DEFINE_DEVICE_TYPE(SEGA8_ROM_KOREAN_NB, sega8_korean_nb_device, "sega8_korean_nb", "SMS Korean No-Bank Mapper Carts") DEFINE_DEVICE_TYPE(SEGA8_ROM_SEOJIN, sega8_seojin_device, "sega8_seojin", "SMS Seo Jin Multi-cart") +// Specific SC-3000 cart types +DEFINE_DEVICE_TYPE(SEGA8_ROM_MULTICART, sega8_multicart_device, "sega8_multicart", "SC-3000 MkII Multicart Cart") +DEFINE_DEVICE_TYPE(SEGA8_ROM_MEGACART, sega8_megacart_device, "sega8_megacart", "SC-3000 Megacart Cart") sega8_rom_device::sega8_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) @@ -185,6 +188,18 @@ sega8_seojin_device::sega8_seojin_device(const machine_config &mconfig, const ch } +sega8_multicart_device::sega8_multicart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : sega8_rom_device(mconfig, SEGA8_ROM_MULTICART, tag, owner, clock) +{ +} + + +sega8_megacart_device::sega8_megacart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : sega8_rom_device(mconfig, SEGA8_ROM_MEGACART, tag, owner, clock) +{ +} + + void sega8_rom_device::device_start() { save_item(NAME(m_rom_bank_base)); @@ -268,6 +283,28 @@ void sega8_zemina_device::device_reset() } +void sega8_multicart_device::device_start() +{ + save_item(NAME(m_block)); +} + +void sega8_multicart_device::device_reset() +{ + m_block = 0xff; +} + + +void sega8_megacart_device::device_start() +{ + save_item(NAME(m_block)); +} + +void sega8_megacart_device::device_reset() +{ + m_block = 0xff; +} + + // initial bank setup needs to know how many 16K banks are available, so it needs to be called during cart loading... void sega8_rom_device::late_bank_setup() @@ -1023,3 +1060,78 @@ READ8_MEMBER(sega8_seojin_device::read_ram) return m_ram[offset & 0x3fff]; } +/*------------------------------------------------- + + SC-3000 Survivors MkII Multicart + +-------------------------------------------------*/ + +READ8_MEMBER(sega8_multicart_device::read_cart) +{ + // 16K of RAM sits in 0x8000-0xbfff + if (offset >= 0x8000) + return m_ram[offset & 0x3fff]; + + return m_rom[(offset & 0x7fff) | (m_block << 15) % m_rom_size]; +} + +WRITE8_MEMBER(sega8_multicart_device::write_cart) +{ + // 16K of RAM sits in 0x8000-0xbfff + if (offset >= 0x8000) + m_ram[offset & 0x3fff] = data; +} + +READ8_MEMBER(sega8_multicart_device::read_ram) +{ + return m_ram[0x4000 + (offset & 0x3fff)]; +} + +WRITE8_MEMBER(sega8_multicart_device::write_ram) +{ + m_ram[0x4000 + (offset & 0x3fff)] = data; +} + +WRITE8_MEMBER(sega8_multicart_device::write_io) +{ + if ((offset & 0xe0) == 0xe0) + m_block = (data & 0x80) ? ((data & 0x1f) | ((data & 0x40) ? 0x20 : 0x00)) : 0x3f; +} + +/*------------------------------------------------- + + SC-3000 Survivors Megacart + +-------------------------------------------------*/ + +READ8_MEMBER(sega8_megacart_device::read_cart) +{ + // 16K of RAM sits in 0x8000-0xbfff + if (offset >= 0x8000) + return m_ram[offset & 0x3fff]; + + return m_rom[(offset & 0x7fff) | (m_block << 15) % m_rom_size]; +} + +WRITE8_MEMBER(sega8_megacart_device::write_cart) +{ + // 16K of RAM sits in 0x8000-0xbfff + if (offset >= 0x8000) + m_ram[offset & 0x3fff] = data; +} + +READ8_MEMBER(sega8_megacart_device::read_ram) +{ + return m_ram[0x4000 + (offset & 0x3fff)]; +} + +WRITE8_MEMBER(sega8_megacart_device::write_ram) +{ + m_ram[0x4000 + (offset & 0x3fff)] = data; +} + +WRITE8_MEMBER(sega8_megacart_device::write_io) +{ + if ((offset & 0xe0) == 0xe0) + m_block = (data & 0x1f) | (data & 0xc0) >> 1; +} diff --git a/src/devices/bus/sega8/rom.h b/src/devices/bus/sega8/rom.h index c299ff261c5..4f9dc80d967 100644 --- a/src/devices/bus/sega8/rom.h +++ b/src/devices/bus/sega8/rom.h @@ -397,6 +397,60 @@ protected: }; +// ======================> sega8_multicart_device + +class sega8_multicart_device : public sega8_rom_device +{ +public: + // construction/destruction + sega8_multicart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // reading and writing + virtual DECLARE_READ8_MEMBER(read_cart) override; + virtual DECLARE_WRITE8_MEMBER(write_cart) override; + virtual DECLARE_WRITE8_MEMBER(write_io) override; + + // has internal RAM which overwrites the system one! + virtual DECLARE_READ8_MEMBER(read_ram) override; + virtual DECLARE_WRITE8_MEMBER(write_ram) override; + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + +private: + uint8_t m_block; +}; + + +// ======================> sega8_megacart_device + +class sega8_megacart_device : public sega8_rom_device +{ +public: + // construction/destruction + sega8_megacart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // reading and writing + virtual DECLARE_READ8_MEMBER(read_cart) override; + virtual DECLARE_WRITE8_MEMBER(write_cart) override; + virtual DECLARE_WRITE8_MEMBER(write_io) override; + + // has internal RAM which overwrites the system one! + virtual DECLARE_READ8_MEMBER(read_ram) override; + virtual DECLARE_WRITE8_MEMBER(write_ram) override; + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + +private: + uint8_t m_block; +}; + + // device type definition DECLARE_DEVICE_TYPE(SEGA8_ROM_STD, sega8_rom_device) DECLARE_DEVICE_TYPE(SEGA8_ROM_OTHELLO, sega8_othello_device) @@ -416,5 +470,7 @@ DECLARE_DEVICE_TYPE(SEGA8_ROM_HICOM, sega8_hicom_device) DECLARE_DEVICE_TYPE(SEGA8_ROM_KOREAN, sega8_korean_device) DECLARE_DEVICE_TYPE(SEGA8_ROM_KOREAN_NB, sega8_korean_nb_device) DECLARE_DEVICE_TYPE(SEGA8_ROM_SEOJIN, sega8_seojin_device) +DECLARE_DEVICE_TYPE(SEGA8_ROM_MULTICART, sega8_multicart_device) +DECLARE_DEVICE_TYPE(SEGA8_ROM_MEGACART, sega8_megacart_device) #endif // MAME_BUS_SEGA8_ROM_H diff --git a/src/devices/bus/sega8/sega8_slot.cpp b/src/devices/bus/sega8/sega8_slot.cpp index 3242654b829..0922a431cbf 100644 --- a/src/devices/bus/sega8/sega8_slot.cpp +++ b/src/devices/bus/sega8/sega8_slot.cpp @@ -178,7 +178,9 @@ static const sega8_slot slot_list[] = { SEGA8_MUSIC_EDITOR, "music_editor" }, { SEGA8_DAHJEE_TYPEA, "dahjee_typea" }, { SEGA8_DAHJEE_TYPEB, "dahjee_typeb" }, - { SEGA8_SEOJIN, "seojin" } + { SEGA8_SEOJIN, "seojin" }, + { SEGA8_MULTICART, "multicart" }, + { SEGA8_MEGACART, "megacart" } }; static int sega8_get_pcb_id(const char *slot) @@ -277,7 +279,7 @@ void sega8_cart_slot_device::setup_ram() m_cart->ram_alloc(0x800); m_cart->set_has_battery(false); } - else if (m_type == SEGA8_BASIC_L3) + else if (m_type == SEGA8_BASIC_L3 || m_type == SEGA8_MULTICART || m_type == SEGA8_MEGACART) { m_cart->ram_alloc(0x8000); m_cart->set_has_battery(false); @@ -584,6 +586,14 @@ int sega8_cart_slot_device::get_cart_type(const uint8_t *ROM, uint32_t len) cons type = SEGA8_MUSIC_EDITOR; } + // SC-3000 Survivors Multicart + if (len == 0x200000) + type = SEGA8_MULTICART; + + // SC-3000 Survivors Megacart + if (len == 0x400000) + type = SEGA8_MEGACART; + return type; } @@ -638,6 +648,14 @@ READ8_MEMBER(sega8_cart_slot_device::read_ram) return 0xff; } +READ8_MEMBER(sega8_cart_slot_device::read_io) +{ + if (m_cart) + return m_cart->read_io(space, offset); + else + return 0xff; +} + /*------------------------------------------------- write @@ -661,6 +679,12 @@ WRITE8_MEMBER(sega8_cart_slot_device::write_ram) m_cart->write_ram(space, offset, data); } +WRITE8_MEMBER(sega8_cart_slot_device::write_io) +{ + if (m_cart) + m_cart->write_io(space, offset, data); +} + /*------------------------------------------------- Internal header logging @@ -817,6 +841,8 @@ void sg1000_cart(device_slot_interface &device) device.option_add_internal("dahjee_typea", SEGA8_ROM_DAHJEE_TYPEA); device.option_add_internal("dahjee_typeb", SEGA8_ROM_DAHJEE_TYPEB); device.option_add_internal("cardcatcher", SEGA8_ROM_CARDCATCH); + device.option_add_internal("multicart", SEGA8_ROM_MULTICART); + device.option_add_internal("megacart", SEGA8_ROM_MEGACART); } void sg1000mk3_cart(device_slot_interface &device) diff --git a/src/devices/bus/sega8/sega8_slot.h b/src/devices/bus/sega8/sega8_slot.h index 9b653d4887b..829398b7ef4 100644 --- a/src/devices/bus/sega8/sega8_slot.h +++ b/src/devices/bus/sega8/sega8_slot.h @@ -32,7 +32,9 @@ enum SEGA8_MUSIC_EDITOR, SEGA8_DAHJEE_TYPEA, SEGA8_DAHJEE_TYPEB, - SEGA8_SEOJIN + SEGA8_SEOJIN, + SEGA8_MULTICART, + SEGA8_MEGACART }; @@ -56,6 +58,9 @@ public: // a few carts (for SG1000) acts as a RAM expansion, taking control of the system RAM in 0xc000-0xffff virtual DECLARE_READ8_MEMBER(read_ram) { return 0xff; } virtual DECLARE_WRITE8_MEMBER(write_ram) { } + // the SC3000 has I/OR, I/OW lines connected + virtual DECLARE_READ8_MEMBER(read_io) { return 0xff; } + virtual DECLARE_WRITE8_MEMBER(write_io) { } void rom_alloc(uint32_t size, const char *tag); void ram_alloc(uint32_t size); @@ -148,6 +153,8 @@ public: virtual DECLARE_WRITE8_MEMBER(write_mapper); virtual DECLARE_READ8_MEMBER(read_ram); virtual DECLARE_WRITE8_MEMBER(write_ram); + virtual DECLARE_READ8_MEMBER(read_io); + virtual DECLARE_WRITE8_MEMBER(write_io); int get_lphaser_xoffs() { return m_cart ? m_cart->get_lphaser_xoffs() : -1; } int get_sms_mode() { return m_cart->get_sms_mode(); } diff --git a/src/mame/drivers/sg1000.cpp b/src/mame/drivers/sg1000.cpp index ce1a99ab3f1..beb0c1d319a 100644 --- a/src/mame/drivers/sg1000.cpp +++ b/src/mame/drivers/sg1000.cpp @@ -187,6 +187,7 @@ void sg1000_state::sc3000_map(address_map &map) void sg1000_state::sc3000_io_map(address_map &map) { map.global_mask(0xff); + map(0x00, 0xff).rw(CARTSLOT_TAG, FUNC(sega8_cart_slot_device::read_io), FUNC(sega8_cart_slot_device::write_io)); map(0x7f, 0x7f).w(SN76489AN_TAG, FUNC(sn76489a_device::command_w)); map(0xbe, 0xbe).rw(TMS9918A_TAG, FUNC(tms9918a_device::vram_r), FUNC(tms9918a_device::vram_w)); map(0xbf, 0xbf).rw(TMS9918A_TAG, FUNC(tms9918a_device::register_r), FUNC(tms9918a_device::register_w)); @@ -485,7 +486,8 @@ void sc3000_state::machine_start() timer_set(attotime::zero, TIMER_LIGHTGUN_TICK); if (m_cart && m_cart->exists() && (m_cart->get_type() == SEGA8_BASIC_L3 || m_cart->get_type() == SEGA8_MUSIC_EDITOR - || m_cart->get_type() == SEGA8_DAHJEE_TYPEA || m_cart->get_type() == SEGA8_DAHJEE_TYPEB)) + || m_cart->get_type() == SEGA8_DAHJEE_TYPEA || m_cart->get_type() == SEGA8_DAHJEE_TYPEB + || m_cart->get_type() == SEGA8_MULTICART || m_cart->get_type() == SEGA8_MEGACART)) { m_maincpu->space(AS_PROGRAM).install_read_handler(0xc000, 0xffff, read8_delegate(FUNC(sega8_cart_slot_device::read_ram),(sega8_cart_slot_device*)m_cart)); m_maincpu->space(AS_PROGRAM).install_write_handler(0xc000, 0xffff, write8_delegate(FUNC(sega8_cart_slot_device::write_ram),(sega8_cart_slot_device*)m_cart)); -- cgit v1.2.3