From 5a9eea849961702e484682678ae0cc3102f3eab2 Mon Sep 17 00:00:00 2001 From: wilbertpol Date: Thu, 20 Jun 2024 03:33:57 +0100 Subject: bus/msx/cart/ram.cpp: Add support for Tecnobytes Double RAM. (#12481) --- src/devices/bus/msx/cart/ram.cpp | 166 ++++++++++++++++++++++++++++--- src/devices/bus/msx/cart/slotoptions.cpp | 1 + src/devices/bus/msx/cart/slotoptions.h | 1 + 3 files changed, 156 insertions(+), 12 deletions(-) diff --git a/src/devices/bus/msx/cart/ram.cpp b/src/devices/bus/msx/cart/ram.cpp index b745a28ae08..fe1b52cc2ce 100644 --- a/src/devices/bus/msx/cart/ram.cpp +++ b/src/devices/bus/msx/cart/ram.cpp @@ -78,7 +78,16 @@ Not supported: - MSX Club Gouda Memory Mapper 4MB - Padial LPE-4MB-V42KP - T.N.S. Addram -- Tecnobytes Double RAM (MegaRam not supported) +- Tecnobytes Double RAM + +Known issues/problems: +- Switching Tecnobytes Double RAM from Memory Mapper to MegaRAM mode will cause + the emulation to look up when the system is using the Double RAM as main + memory. It is unknown if this also happens on a real system. + +TODO: +- Unknown which parts of memory are used for the MegaRAM 8KB pages. + Not supported memory mappers: - 8bits4ever SD-512 @@ -114,22 +123,24 @@ DECLARE_DEVICE_TYPE(MSX_CART_768K_MM_RAM, msx_cart_interface) DECLARE_DEVICE_TYPE(MSX_CART_1024K_MM_RAM, msx_cart_interface) DECLARE_DEVICE_TYPE(MSX_CART_2048K_MM_RAM, msx_cart_interface) DECLARE_DEVICE_TYPE(MSX_CART_4096K_MM_RAM, msx_cart_interface) +DECLARE_DEVICE_TYPE(MSX_CART_DOUBLE_RAM, msx_cart_interface) DECLARE_DEVICE_TYPE(MSX_CART_MMM, msx_cart_interface) void msx_cart_ram_register_options(device_slot_interface &device) { using namespace bus::msx::cart; - device.option_add(slotoptions::RAM16K, MSX_CART_16K_RAM); - device.option_add(slotoptions::RAM32K, MSX_CART_32K_RAM); - device.option_add(slotoptions::RAM48K, MSX_CART_48K_RAM); - device.option_add(slotoptions::RAM64K, MSX_CART_64K_RAM); - device.option_add(slotoptions::MM256K, MSX_CART_256K_MM_RAM); - device.option_add(slotoptions::MM512K, MSX_CART_512K_MM_RAM); - device.option_add(slotoptions::MM768K, MSX_CART_768K_MM_RAM); - device.option_add(slotoptions::MM1024K, MSX_CART_1024K_MM_RAM); - device.option_add(slotoptions::MM2048K, MSX_CART_2048K_MM_RAM); - device.option_add(slotoptions::MM4096K, MSX_CART_4096K_MM_RAM); - device.option_add(slotoptions::MMM, MSX_CART_MMM); + device.option_add(slotoptions::RAM16K, MSX_CART_16K_RAM); + device.option_add(slotoptions::RAM32K, MSX_CART_32K_RAM); + device.option_add(slotoptions::RAM48K, MSX_CART_48K_RAM); + device.option_add(slotoptions::RAM64K, MSX_CART_64K_RAM); + device.option_add(slotoptions::MM256K, MSX_CART_256K_MM_RAM); + device.option_add(slotoptions::MM512K, MSX_CART_512K_MM_RAM); + device.option_add(slotoptions::MM768K, MSX_CART_768K_MM_RAM); + device.option_add(slotoptions::MM1024K, MSX_CART_1024K_MM_RAM); + device.option_add(slotoptions::MM2048K, MSX_CART_2048K_MM_RAM); + device.option_add(slotoptions::MM4096K, MSX_CART_4096K_MM_RAM); + device.option_add(slotoptions::DOUBLE_RAM, MSX_CART_DOUBLE_RAM); + device.option_add(slotoptions::MMM, MSX_CART_MMM); } namespace { @@ -386,6 +397,136 @@ void msx_cart_mmm_device::device_add_mconfig(machine_config &config) m_sn76489a->add_route(ALL_OUTPUTS, soundin(), 0.8); } + + +class msx_cart_double_ram_device : public msx_cart_base_mm_ram_device +{ +public: + msx_cart_double_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : msx_cart_base_mm_ram_device(mconfig, MSX_CART_DOUBLE_RAM, tag, owner, clock, 4 * 1024 * 1024) + , m_mode_switch(*this, "MODE") + , m_view{ {*this, "view0"}, {*this, "view1"}, {*this, "view2"}, {*this, "view3"} } + , m_mrview{ {*this, "mrview0"}, {*this, "mrview1"}, {*this, "mrview2"}, {*this, "mrview3"} } + , m_megaram(false) + { } + + DECLARE_INPUT_CHANGED_MEMBER(mode_callback); + +protected: + virtual void device_start() override; + virtual void device_reset() override; + virtual ioport_constructor device_input_ports() const override; + +private: + static constexpr u8 MODE_RO = 0; + static constexpr u8 MODE_RW = 1; + static constexpr u8 MODE_MM = 0; + static constexpr u8 MODE_MR = 1; + + required_ioport m_mode_switch; + memory_view m_view[4]; + memory_view m_mrview[4]; + bool m_megaram; + + void set_page_views(); +}; + +static INPUT_PORTS_START(double_ram_mode_switch) + PORT_START("MODE") + PORT_CONFNAME(0x01, 0x01, "Mode") PORT_CHANGED_MEMBER(DEVICE_SELF, msx_cart_double_ram_device, mode_callback, 0) + PORT_CONFSETTING(0x00, "Memory Mapper") + PORT_CONFSETTING(0x01, "MegaRAM") +INPUT_PORTS_END + +ioport_constructor msx_cart_double_ram_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(double_ram_mode_switch); +} + +void msx_cart_double_ram_device::device_start() +{ + msx_cart_base_ram_device::device_start(); + + m_bank_mask = device_generic_cart_interface::map_non_power_of_two( + unsigned(get_ram_size() / 0x4000), + [this] (unsigned entry, unsigned page) + { + for (int i = 0; i < 4; i++) + m_rambank[i]->configure_entry(entry, ram_data() + 0x4000 * page); + } + ); + + page(0)->install_view(0x0000, 0x3fff, m_view[0]); + page(1)->install_view(0x4000, 0x7fff, m_view[1]); + page(2)->install_view(0x8000, 0xbfff, m_view[2]); + page(3)->install_view(0xc000, 0xffff, m_view[3]); + + m_view[0][MODE_MM].install_readwrite_bank(0x0000, 0x3fff, m_rambank[0]); + m_view[0][MODE_MR]; + + m_view[1][MODE_MM].install_readwrite_bank(0x4000, 0x7fff, m_rambank[1]); + m_view[1][MODE_MR].install_view(0x4000, 0x5fff, m_mrview[0]); + m_view[1][MODE_MR].install_view(0x6000, 0x7fff, m_mrview[1]); + + m_view[2][MODE_MM].install_readwrite_bank(0x8000, 0xbfff, m_rambank[2]); + m_view[2][MODE_MR].install_view(0x8000, 0x9fff, m_mrview[2]); + m_view[2][MODE_MR].install_view(0xa000, 0xbfff, m_mrview[3]); + + m_view[3][MODE_MM].install_readwrite_bank(0xc000, 0xffff, m_rambank[3]); + m_view[3][MODE_MR]; + + m_mrview[0][MODE_RO].install_read_bank(0x4000, 0x5fff, m_rambank[0]); + m_mrview[0][MODE_RO].install_write_handler(0x4000, 0x4000, write8smo_delegate(*this, [this] (u8 data) { this->m_rambank[0]->set_entry(data); }, "bank_4000")); + m_mrview[0][MODE_RW].install_readwrite_bank(0x4000, 0x5fff, m_rambank[0]); + + m_mrview[1][MODE_RO].install_read_bank(0x6000, 0x7fff, m_rambank[1]); + m_mrview[1][MODE_RO].install_write_handler(0x6000, 0x6000, write8smo_delegate(*this, [this] (u8 data) { this->m_rambank[1]->set_entry(data); }, "bank_6000")); + m_mrview[1][MODE_RW].install_readwrite_bank(0x6000, 0x7fff, m_rambank[1]); + + m_mrview[2][MODE_RO].install_read_bank(0x8000, 0x9fff, m_rambank[2]); + m_mrview[2][MODE_RO].install_write_handler(0x8000, 0x8000, write8smo_delegate(*this, [this] (u8 data) { this->m_rambank[2]->set_entry(data); }, "bank_8000")); + m_mrview[2][MODE_RW].install_readwrite_bank(0x8000, 0x9fff, m_rambank[2]); + + m_mrview[3][MODE_RO].install_read_bank(0xa000, 0xbfff, m_rambank[3]); + m_mrview[3][MODE_RO].install_write_handler(0xa000, 0xa000, write8smo_delegate(*this, [this] (u8 data) { this->m_rambank[3]->set_entry(data); }, "bank_a000")); + m_mrview[3][MODE_RW].install_readwrite_bank(0xa000, 0xbfff, m_rambank[3]); + + io_space().install_read_tap(0x8e, 0x8e, "megaram_w", [this] (offs_t, u8&, u8) { if (m_megaram) for (int i = 0; i < 4; i++) m_mrview[i].select(MODE_RW); } ); + io_space().install_write_tap(0x8e, 0x8e, "megaram_r", [this] (offs_t, u8&, u8) { if (m_megaram) for (int i = 0; i < 4; i++) m_mrview[i].select(MODE_RO); } ); + + // The MSX system allows multiple devices to react to I/O, so we use taps. + io_space().install_write_tap(0xfc, 0xfc, "bank0", [this] (offs_t, u8& data, u8){ if (!m_megaram) this->bank_w<0>(data); }); + io_space().install_write_tap(0xfd, 0xfd, "bank1", [this] (offs_t, u8& data, u8){ if (!m_megaram) this->bank_w<1>(data); }); + io_space().install_write_tap(0xfe, 0xfe, "bank2", [this] (offs_t, u8& data, u8){ if (!m_megaram) this->bank_w<2>(data); }); + io_space().install_write_tap(0xff, 0xff, "bank3", [this] (offs_t, u8& data, u8){ if (!m_megaram) this->bank_w<3>(data); }); + + save_item(NAME(m_megaram)); + + for (int i = 0; i < 4; i++) + { + m_mrview[i].select(MODE_RO); + m_rambank[i]->set_entry(i); + } +} + +void msx_cart_double_ram_device::device_reset() +{ + m_megaram = BIT(m_mode_switch->read(), 0); + set_page_views(); +} + +INPUT_CHANGED_MEMBER(msx_cart_double_ram_device::mode_callback) +{ + m_megaram = BIT(newval, 0); + set_page_views(); +} + +void msx_cart_double_ram_device::set_page_views() +{ + for (int i = 0; i < 4; i++) + m_view[i].select(m_megaram ? MODE_MR : MODE_MM); +} + } // anonymous namespace @@ -399,4 +540,5 @@ DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_768K_MM_RAM, msx_cart_interface, msx_cart_7 DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_1024K_MM_RAM, msx_cart_interface, msx_cart_1024k_mm_ram_device, "msx_cart_1024k_mm_ram", "Generic MSX 1024K MM RAM Expansion") DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_2048K_MM_RAM, msx_cart_interface, msx_cart_2048k_mm_ram_device, "msx_cart_2048k_mm_ram", "Generic MSX 2048K MM RAM Expansion") DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_4096K_MM_RAM, msx_cart_interface, msx_cart_4096k_mm_ram_device, "msx_cart_4096k_mm_ram", "Generic MSX 4096K MM RAM Expansion") +DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_DOUBLE_RAM, msx_cart_interface, msx_cart_double_ram_device, "msx_cart_double_ram", "Tecnobytes Double RAM") DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_MMM, msx_cart_interface, msx_cart_mmm_device, "msx_cart_mmm", "Popolon Musical Memory Mapper") diff --git a/src/devices/bus/msx/cart/slotoptions.cpp b/src/devices/bus/msx/cart/slotoptions.cpp index 046a164ddbe..a99a1750bf3 100644 --- a/src/devices/bus/msx/cart/slotoptions.cpp +++ b/src/devices/bus/msx/cart/slotoptions.cpp @@ -31,6 +31,7 @@ char const *const DISK_NMS1200 = "disk_nms1200"; char const *const DISK_TADPF550 = "disk_tadpf550"; char const *const DISK_VY0010 = "disk_vy0010"; char const *const DOOLY = "dooly"; +char const *const DOUBLE_RAM = "double_ram"; char const *const EASISPEECH = "easispeech"; char const *const EC701 = "ec701"; char const *const FMPAC = "fmpac"; diff --git a/src/devices/bus/msx/cart/slotoptions.h b/src/devices/bus/msx/cart/slotoptions.h index 9ea5cc31d87..3333ca62165 100644 --- a/src/devices/bus/msx/cart/slotoptions.h +++ b/src/devices/bus/msx/cart/slotoptions.h @@ -33,6 +33,7 @@ extern char const *const DISK_ML30DC; extern char const *const DISK_NMS1200; extern char const *const DISK_TADPF550; extern char const *const DISK_VY0010; +extern char const *const DOUBLE_RAM; extern char const *const DOOLY; extern char const *const EASISPEECH; extern char const *const EC701; -- cgit v1.2.3