From 9faa7d113828b288add781d736742946a82cc646 Mon Sep 17 00:00:00 2001 From: wilbertpol Date: Tue, 14 Feb 2023 18:29:14 +0000 Subject: bus/msx/cart/msxdos2.cpp: Added full MSX-DOS2 support. (#10893) New working software list items (msx1_cart.xml) ------------------------------ Japanese MSX-DOS 2.20 (Japan, 256KB) Japanese MSX-DOS 2.20 (Japan, 256KB, alt) Japanese MSX-DOS 2.20 (Japan, 256KB, alt 2) Japanese MSX-DOS 2.20 (Japan, 128KB) Japanese MSX-DOS 2.20 (Japan) MSX-DOS 2.20 (Europe) --- hash/msx2_cart.xml | 159 +++++++++++++++++++++++ src/devices/bus/msx/cart/cartridge.cpp | 3 +- src/devices/bus/msx/cart/msxdos2.cpp | 227 ++++++++++++++++++++++++++++++--- src/devices/bus/msx/cart/msxdos2.h | 24 +--- 4 files changed, 371 insertions(+), 42 deletions(-) diff --git a/hash/msx2_cart.xml b/hash/msx2_cart.xml index 25d692c8168..4925c79553d 100644 --- a/hash/msx2_cart.xml +++ b/hash/msx2_cart.xml @@ -3156,4 +3156,163 @@ LZ93A13 (32 pin) - 8KB banks + + Japanese MSX-DOS 2.20 (Japan, 256KB) + 1989 + ASCII + + + + + + + + + + + + + + + + + + + + + + + + + + Japanese MSX-DOS 2.20 (Japan, 256KB, alt) + 1989 + ASCII + + + + + + + + + + + + + + + + + + + + + + + + + + Japanese MSX-DOS 2.20 (Japan, 256KB, alt 2) + 1989 + ASCII + + + + + + + + + + + + + + + + + + + + + + + + + + Japanese MSX-DOS 2.20 (Japan, 128KB) + 1988 + ASCII + + + + + + + + + + + + + + + + + + + + + + + + + + + Japanese MSX-DOS 2.20 (Japan) + 1988 + ASCII + + + + + + + + + + + + + + + + + + + + + + + + + MSX-DOS 2.20 (Europe) + 1989 + H.S.H. + + + + + + + + + + + + + + + diff --git a/src/devices/bus/msx/cart/cartridge.cpp b/src/devices/bus/msx/cart/cartridge.cpp index 089740e0a8d..1bc8b482d57 100644 --- a/src/devices/bus/msx/cart/cartridge.cpp +++ b/src/devices/bus/msx/cart/cartridge.cpp @@ -65,7 +65,8 @@ void msx_cart(device_slot_interface &device) device.option_add_internal("msxaud_fsca1", MSX_CART_MSX_AUDIO_FSCA1); device.option_add_internal("msxaud_hxmu900", MSX_CART_MSX_AUDIO_HXMU900); device.option_add_internal("msxaud_nms1205", MSX_CART_MSX_AUDIO_NMS1205); - device.option_add_internal("msxdos2", MSX_CART_MSXDOS2); + device.option_add_internal("msxdos2j", MSX_CART_MSXDOS2J); + device.option_add_internal("msxdos2e", MSX_CART_MSXDOS2E); device.option_add_internal("msxwrite", MSX_CART_MSXWRITE); device.option_add_internal("nomapper", MSX_CART_NOMAPPER); device.option_add_internal("rtype", MSX_CART_RTYPE); diff --git a/src/devices/bus/msx/cart/msxdos2.cpp b/src/devices/bus/msx/cart/msxdos2.cpp index 10d92918eb3..e747be583e4 100644 --- a/src/devices/bus/msx/cart/msxdos2.cpp +++ b/src/devices/bus/msx/cart/msxdos2.cpp @@ -3,49 +3,238 @@ #include "emu.h" #include "msxdos2.h" -// This is the bare minimum to get a msx-dos 2 rom working in a system -// TODO: -// - Add subslots for regular rom and kanji driver rom -// - Add support for 128KB and 256KB memory mapper versions +#include "bus/generic/slot.h" -DEFINE_DEVICE_TYPE(MSX_CART_MSXDOS2, msx_cart_msxdos2_device, "msx_cart_msxdos2", "MSX Cartridge - MSXDOS2") +/* +Emulation of MSX-DOS2 cartridges. -msx_cart_msxdos2_device::msx_cart_msxdos2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) - : device_t(mconfig, MSX_CART_MSXDOS2, tag, owner, clock) - , msx_cart_interface(mconfig, *this) - , m_rombank(*this, "rombank") +Japanese MSX-DOS2 uses an expanded slot model: +- Subslot 1 - Memory mapper with no, 128KB, or 256KB RAM +- Subslot 2 - Kanji Basic ROM +- Subslot 3 - MSX-DOS2 banked ROM + +European MSX-DOS2 releases only contain MSX-DOS2 banked ROM. + +The rom banking address is either $6000 or $7ffe depending on the +version of the hardware. + +*/ + +namespace { + +class msx_cart_msxdos2_base_device : public device_t, public msx_cart_interface { -} +protected: + msx_cart_msxdos2_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, type, tag, owner, clock) + , msx_cart_interface(mconfig, *this) + , m_rombank(*this, "rombank") + , m_bank_address(0) + { } + + virtual void device_start() override { } + virtual void device_reset() override; + virtual image_init_result initialize_cartridge(std::string &message) override; + + void bank_w(u8 data); + + static inline constexpr unsigned PAGE_SIZE = 0x4000; -void msx_cart_msxdos2_device::device_reset() + memory_bank_creator m_rombank; + u16 m_bank_address; +}; + +void msx_cart_msxdos2_base_device::device_reset() { - m_rombank->set_entry(1); + m_rombank->set_entry(0); } -image_init_result msx_cart_msxdos2_device::initialize_cartridge(std::string &message) +image_init_result msx_cart_msxdos2_base_device::initialize_cartridge(std::string &message) { if (!cart_rom_region()) { - message = "msx_cart_msxdos2_device: Required region 'rom' was not found."; + message = "msx_cart_msxdos2: Required region 'rom' was not found."; return image_init_result::FAIL; } if (cart_rom_region()->bytes() != 0x10000) { - message = "msx_cart_msxdos2_device: Region 'rom' has unsupported size."; + message = "msx_cart_msxdos2: Region 'rom' has unsupported size."; return image_init_result::FAIL; } - m_rombank->configure_entries(0, 4, cart_rom_region()->base(), 0x4000); + const char *bank_address_str = get_feature("bank_address"); + if (!bank_address_str) + { + message = "msx_cart_msxdos2: Feature 'bank_address' was not found."; + return image_init_result::FAIL; + } + m_bank_address = strtol(bank_address_str, nullptr, 0); + if (m_bank_address < 0x4000 || m_bank_address > 0x7fff) + { + message = "msx_cart_msxdos2: bank_address must be between 0x4000 and 0x7fff."; + return image_init_result::FAIL; + } - page(1)->install_read_bank(0x4000, 0x7fff, m_rombank); - page(1)->install_write_handler(0x7ffe, 0x7ffe, write8smo_delegate(*this, FUNC(msx_cart_msxdos2_device::bank_w))); + m_rombank->configure_entries(0, 4, cart_rom_region()->base(), PAGE_SIZE); return image_init_result::PASS; } -void msx_cart_msxdos2_device::bank_w(u8 data) +void msx_cart_msxdos2_base_device::bank_w(u8 data) { m_rombank->set_entry(data & 0x03); } + + + +class msx_cart_msxdos2j_device : public msx_cart_msxdos2_base_device +{ +public: + msx_cart_msxdos2j_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : msx_cart_msxdos2_base_device(mconfig, MSX_CART_MSXDOS2J, tag, owner, clock) + , m_rambank(*this, "rambank%u", 0) + , m_view_page0(*this, "view_page0") + , m_view_page1(*this, "view_page1") + , m_view_page2(*this, "view_page2") + , m_view_page3(*this, "view_page3") + , m_secondary_slot(0) + , m_bank_mask(0) + { } + + virtual image_init_result initialize_cartridge(std::string &message) override; + +protected: + virtual void device_start() override; + +private: + u8 secondary_slot_r(); + void secondary_slot_w(u8 data); + template void mm_bank_w(u8 data); + + memory_bank_array_creator<4> m_rambank; + memory_view m_view_page0; + memory_view m_view_page1; + memory_view m_view_page2; + memory_view m_view_page3; + u8 m_secondary_slot; + u8 m_bank_mask; +}; + + +void msx_cart_msxdos2j_device::device_start() +{ + msx_cart_msxdos2_base_device::device_start(); + save_item(NAME(m_secondary_slot)); +} + +image_init_result msx_cart_msxdos2j_device::initialize_cartridge(std::string &message) +{ + image_init_result result = msx_cart_msxdos2_base_device::initialize_cartridge(message); + if (result != image_init_result::PASS) + return result; + + u32 ram_size = cart_ram_region() ? cart_ram_region()->bytes() : 0; + if (ram_size > 256 * PAGE_SIZE || (ram_size & (PAGE_SIZE - 1)) != 0) + { + message = "msx_cart_msxdos2: Region 'ram' size must be a multiple of 0x4000 and at most 0x400000."; + return image_init_result::FAIL; + } + + page(0)->install_view(0x0000, 0x3fff, m_view_page0); + page(1)->install_view(0x4000, 0x7fff, m_view_page1); + page(2)->install_view(0x8000, 0xbfff, m_view_page2); + page(3)->install_view(0xc000, 0xffff, m_view_page3); + page(3)->install_readwrite_handler(0xffff, 0xffff, read8smo_delegate(*this, FUNC(msx_cart_msxdos2j_device::secondary_slot_r)), write8smo_delegate(*this, FUNC(msx_cart_msxdos2j_device::secondary_slot_w))); + + // Make sure all views we can select do exist. + for (int subslot = 0; subslot < 4; subslot++) + { + m_view_page0[subslot]; + m_view_page1[subslot]; + m_view_page2[subslot]; + m_view_page3[subslot]; + } + + // Kanji driver + m_view_page1[2].install_rom(0x4000, 0x7fff, cart_rom_region()->base() + 0xc000); + + // MSX-DOS2 rom + m_view_page1[3].install_read_bank(0x4000, 0x7fff, m_rombank); + m_view_page1[3].install_write_handler(m_bank_address, m_bank_address, write8smo_delegate(*this, FUNC(msx_cart_msxdos2j_device::bank_w))); + + // On-cartridge memory mapper RAM + if (ram_size) + { + m_bank_mask = device_generic_cart_interface::map_non_power_of_two( + unsigned(ram_size / PAGE_SIZE), + [this] (unsigned entry, unsigned page) + { + for (int i = 0; i < 4; i++) + m_rambank[i]->configure_entry(entry, cart_ram_region()->base() + PAGE_SIZE * page); + } + ); + + m_view_page0[1].install_readwrite_bank(0x0000, 0x3fff, m_rambank[0]); + m_view_page1[1].install_readwrite_bank(0x4000, 0x7fff, m_rambank[1]); + m_view_page2[1].install_readwrite_bank(0x8000, 0xbfff, m_rambank[2]); + m_view_page3[1].install_readwrite_bank(0xc000, 0xffff, m_rambank[3]); + + io_space().install_write_tap(0xfc, 0xfc, "bank0", [this] (offs_t, u8& data, u8){ this->mm_bank_w<0>(data); }); + io_space().install_write_tap(0xfd, 0xfd, "bank1", [this] (offs_t, u8& data, u8){ this->mm_bank_w<1>(data); }); + io_space().install_write_tap(0xfe, 0xfe, "bank2", [this] (offs_t, u8& data, u8){ this->mm_bank_w<2>(data); }); + io_space().install_write_tap(0xff, 0xff, "bank3", [this] (offs_t, u8& data, u8){ this->mm_bank_w<3>(data); }); + } + + return image_init_result::PASS; +} + +u8 msx_cart_msxdos2j_device::secondary_slot_r() +{ + return ~m_secondary_slot; +} + +void msx_cart_msxdos2j_device::secondary_slot_w(u8 data) +{ + m_view_page0.select((data >> 0) & 0x03); + m_view_page1.select((data >> 2) & 0x03); + m_view_page2.select((data >> 4) & 0x03); + m_view_page3.select((data >> 6) & 0x03); + m_secondary_slot = data; +} + +template +void msx_cart_msxdos2j_device::mm_bank_w(u8 data) +{ + m_rambank[Bank]->set_entry(data & m_bank_mask); +} + + + +class msx_cart_msxdos2e_device : public msx_cart_msxdos2_base_device +{ +public: + msx_cart_msxdos2e_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : msx_cart_msxdos2_base_device(mconfig, MSX_CART_MSXDOS2E, tag, owner, clock) + { } + + virtual image_init_result initialize_cartridge(std::string &message) override; +}; + +image_init_result msx_cart_msxdos2e_device::initialize_cartridge(std::string &message) +{ + image_init_result result = msx_cart_msxdos2_base_device::initialize_cartridge(message); + if (result != image_init_result::PASS) + return result; + + page(1)->install_read_bank(0x4000, 0x7fff, m_rombank); + page(1)->install_write_handler(m_bank_address, m_bank_address, write8smo_delegate(*this, FUNC(msx_cart_msxdos2e_device::bank_w))); + + return image_init_result::PASS; +} + +} // anonymous namespace + +DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_MSXDOS2J, msx_cart_interface, msx_cart_msxdos2j_device, "msx_cart_msxdos2j", "MSX Cartridge - MSXDOS2 Japan") +DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_MSXDOS2E, msx_cart_interface, msx_cart_msxdos2e_device, "msx_cart_msxdos2e", "MSX Cartridge - MSXDOS2 Europe") diff --git a/src/devices/bus/msx/cart/msxdos2.h b/src/devices/bus/msx/cart/msxdos2.h index 6f0212a3da8..826d2638ee7 100644 --- a/src/devices/bus/msx/cart/msxdos2.h +++ b/src/devices/bus/msx/cart/msxdos2.h @@ -7,27 +7,7 @@ #include "bus/msx/slot/cartridge.h" - -DECLARE_DEVICE_TYPE(MSX_CART_MSXDOS2, msx_cart_msxdos2_device) - - -class msx_cart_msxdos2_device : public device_t, public msx_cart_interface -{ -public: - msx_cart_msxdos2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); - - virtual image_init_result initialize_cartridge(std::string &message) override; - -protected: - // device-level overrides - virtual void device_start() override { } - virtual void device_reset() override; - -private: - void bank_w(u8 data); - - memory_bank_creator m_rombank; -}; - +DECLARE_DEVICE_TYPE(MSX_CART_MSXDOS2J, msx_cart_interface) +DECLARE_DEVICE_TYPE(MSX_CART_MSXDOS2E, msx_cart_interface) #endif // MAME_BUS_MSX_CART_MSXDOS2_H -- cgit v1.2.3