summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/msx/module/skw01.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/bus/msx/module/skw01.cpp')
-rw-r--r--src/devices/bus/msx/module/skw01.cpp176
1 files changed, 176 insertions, 0 deletions
diff --git a/src/devices/bus/msx/module/skw01.cpp b/src/devices/bus/msx/module/skw01.cpp
new file mode 100644
index 00000000000..cd7bf3d7f1c
--- /dev/null
+++ b/src/devices/bus/msx/module/skw01.cpp
@@ -0,0 +1,176 @@
+// license:BSD-3-Clause
+// copyright-holders:Wilbert Pol
+/**************************************************************************
+
+Yamaha SKW-01 emulation
+
+Word processor side slot module with Kanij ROM, 2KB SRAM, and a
+printer port.
+The PCB is labeled YMX-YWP.
+
+The software can be started from Basic by entering the command "CALL JWP"
+or "_JWP".
+
+**************************************************************************/
+
+#include "emu.h"
+#include "skw01.h"
+#include "bus/centronics/ctronics.h"
+#include "machine/buffer.h"
+#include "machine/nvram.h"
+
+namespace {
+
+class msx_cart_skw01_device : public device_t, public msx_cart_interface
+{
+public:
+ msx_cart_skw01_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ static constexpr u16 SRAM_SIZE = 2048;
+
+ required_device<nvram_device> m_nvram;
+ required_memory_region m_region_rom;
+ required_memory_region m_region_dict;
+ required_memory_region m_region_kanji;
+ u16 m_bank_address[5];
+ std::unique_ptr<u8[]> m_sram;
+ required_device<input_buffer_device> m_cent_status_in;
+ required_device<output_latch_device> m_cent_ctrl_out;
+ required_device<output_latch_device> m_cent_data_out;
+ required_device<centronics_device> m_centronics;
+
+ template<int Bank> void addr_lo_w(u8 data);
+ template<int Bank> void addr_hi_w(u8 data);
+ template<int Bank> u8 ready_r() const;
+ template<int Bank> u8 data_r() const;
+ void dictsram_w(u8 data);
+ u8 dictsram_r() const;
+};
+
+
+msx_cart_skw01_device::msx_cart_skw01_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, MSX_CART_SKW01, tag, owner, clock)
+ , msx_cart_interface(mconfig, *this)
+ , m_nvram(*this, "nvram")
+ , m_region_rom(*this, "rom")
+ , m_region_dict(*this, "dict")
+ , m_region_kanji(*this, "kanji")
+ , m_bank_address{0}
+ , m_cent_status_in(*this, "cent_status_in")
+ , m_cent_ctrl_out(*this, "cent_ctrl_out")
+ , m_cent_data_out(*this, "cent_data_out")
+ , m_centronics(*this, "centronics")
+{
+}
+
+void msx_cart_skw01_device::device_add_mconfig(machine_config &config)
+{
+ NVRAM(config, m_nvram, nvram_device::DEFAULT_ALL_0);
+
+ // printer port
+ CENTRONICS(config, m_centronics, centronics_devices, "printer");
+ m_centronics->busy_handler().set(m_cent_status_in, FUNC(input_buffer_device::write_bit1));
+
+ OUTPUT_LATCH(config, m_cent_data_out);
+ m_centronics->set_output_latch(*m_cent_data_out);
+ INPUT_BUFFER(config, m_cent_status_in);
+
+ OUTPUT_LATCH(config, m_cent_ctrl_out);
+ m_cent_ctrl_out->bit_handler<1>().set(m_centronics, FUNC(centronics_device::write_strobe));
+}
+
+ROM_START(msx_skw01)
+ ROM_REGION(0x8000, "rom", 0)
+ ROM_LOAD("skw-01.rom", 0x0000, 0x8000, CRC(9a7c9a26) SHA1(6a7f41d89f9d50f4ff648233670660cfb07a41ee))
+ ROM_REGION(0x8000, "dict", 0)
+ ROM_LOAD("skw-01p4.rom", 0x0000, 0x8000, CRC(41779e03) SHA1(82f2ecd9f3135a8602d54cc6322216b3b15ae8b3))
+ ROM_REGION(0x20000, "kanji", 0)
+ ROM_LOAD("skw-01kf.rom", 0x00000, 0x20000, CRC(9de1dc10) SHA1(f0901a63de6c95a42ce6ad82dd5e6bfba4bcf180))
+ROM_END
+
+const tiny_rom_entry *msx_cart_skw01_device::device_rom_region() const
+{
+ return ROM_NAME(msx_skw01);
+}
+
+void msx_cart_skw01_device::device_start()
+{
+ m_sram = std::make_unique<u8[]>(SRAM_SIZE);
+ m_nvram->set_base(m_sram.get(), SRAM_SIZE);
+ save_pointer(NAME(m_sram), SRAM_SIZE);
+ save_item(NAME(m_bank_address));
+
+ page(0)->install_rom(0x0000, 0x3fff, m_region_rom->base());
+ page(1)->install_rom(0x4000, 0x7fff, m_region_rom->base() + 0x4000);
+ page(1)->install_readwrite_handler(0x7fc0, 0x7fc0, emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::ready_r<0>)), emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::addr_lo_w<0>)));
+ page(1)->install_readwrite_handler(0x7fc1, 0x7fc1, emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::data_r<0>)), emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::addr_hi_w<0>)));
+ page(1)->install_readwrite_handler(0x7fc2, 0x7fc2, emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::ready_r<1>)), emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::addr_lo_w<1>)));
+ page(1)->install_readwrite_handler(0x7fc3, 0x7fc3, emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::data_r<1>)), emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::addr_hi_w<1>)));
+ page(1)->install_readwrite_handler(0x7fc4, 0x7fc4, emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::ready_r<2>)), emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::addr_lo_w<2>)));
+ page(1)->install_readwrite_handler(0x7fc5, 0x7fc5, emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::data_r<2>)), emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::addr_hi_w<2>)));
+ page(1)->install_readwrite_handler(0x7fc6, 0x7fc6, emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::ready_r<3>)), emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::addr_lo_w<3>)));
+ page(1)->install_readwrite_handler(0x7fc7, 0x7fc7, emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::data_r<3>)), emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::addr_hi_w<3>)));
+ page(1)->install_write_handler(0x7fc8, 0x7fc8, emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::addr_lo_w<4>)));
+ page(1)->install_write_handler(0x7fc9, 0x7fc9, emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::addr_hi_w<4>)));
+ page(1)->install_readwrite_handler(0x7fca, 0x7fcb, emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::dictsram_r)), emu::rw_delegate(*this, FUNC(msx_cart_skw01_device::dictsram_w)));
+ page(1)->install_readwrite_handler(0x7fcc, 0x7fcc, emu::rw_delegate(*m_cent_status_in, FUNC(input_buffer_device::read)), emu::rw_delegate(*m_cent_ctrl_out, FUNC(output_latch_device::write)));
+ page(1)->install_write_handler(0x7fce, 0x7fce, emu::rw_delegate(*m_cent_data_out, FUNC(output_latch_device::write)));
+}
+
+template<int Bank>
+void msx_cart_skw01_device::addr_lo_w(u8 data)
+{
+ m_bank_address[Bank] = (m_bank_address[Bank] & 0xff00) | data;
+}
+
+template<int Bank>
+void msx_cart_skw01_device::addr_hi_w(u8 data)
+{
+ m_bank_address[Bank] = (m_bank_address[Bank] & 0x00ff) | (u16(data) << 8);
+}
+
+template<int Bank>
+u8 msx_cart_skw01_device::ready_r() const
+{
+ // Unknown what the delay should be
+ // 0 - Not ready
+ // 1 - Data ready to read
+ return 1;
+}
+
+template<int Bank>
+u8 msx_cart_skw01_device::data_r() const
+{
+ return m_region_kanji->as_u8((Bank * 0x8000) | (m_bank_address[Bank] & 0x7fff));
+}
+
+void msx_cart_skw01_device::dictsram_w(u8 data)
+{
+ if (BIT(m_bank_address[4], 15))
+ {
+ m_sram[m_bank_address[4] & (SRAM_SIZE - 1)] = data;
+ }
+}
+
+u8 msx_cart_skw01_device::dictsram_r() const
+{
+ if (BIT(m_bank_address[4], 15))
+ {
+ return m_sram[m_bank_address[4] & (SRAM_SIZE - 1)];
+ }
+
+ return m_region_dict->as_u8(m_bank_address[4]);
+}
+
+} // anonymous namespace
+
+
+DEFINE_DEVICE_TYPE_PRIVATE(MSX_CART_SKW01, msx_cart_interface, msx_cart_skw01_device, "msx_cart_skw01", "Yamaha SKW-01")