diff options
Diffstat (limited to 'src/mame/msx/msx.h')
-rw-r--r-- | src/mame/msx/msx.h | 374 |
1 files changed, 374 insertions, 0 deletions
diff --git a/src/mame/msx/msx.h b/src/mame/msx/msx.h new file mode 100644 index 00000000000..19f1dc8fd1c --- /dev/null +++ b/src/mame/msx/msx.h @@ -0,0 +1,374 @@ +// license:BSD-3-Clause +// copyright-holders:Wilbert Pol +#ifndef MAME_MSX_MSX_H +#define MAME_MSX_MSX_H + +#pragma once + +#include "bus/centronics/ctronics.h" +#include "bus/msx/ctrl/ctrl.h" +#include "bus/msx/slot/cartridge.h" +#include "bus/msx/cart/cartridge.h" +#include "bus/msx/minicart/minicart.h" +#include "bus/msx/module/module.h" +#include "cpu/z80/z80.h" +#include "imagedev/cassette.h" +#include "machine/buffer.h" +#include "machine/i8255.h" +#include "machine/input_merger.h" +#include "machine/rp5c01.h" +#include "msx_switched.h" +#include "sound/ay8910.h" +#include "sound/dac.h" +#include "sound/ymopl.h" +#include "speaker.h" +#include "video/v9938.h" +#include "video/tms9928a.h" + + +class msx_hw_def +{ +public: + msx_hw_def() {} + bool has_cassette() const { return m_has_cassette; } + bool has_printer_port() const { return m_has_printer_port; } + bool has_cartslot() const { return m_has_cartslot; } + bool has_fdc() const { return m_has_fdc; } + msx_hw_def &has_cassette(bool has_cassette) { m_has_cassette = has_cassette; return *this;} + msx_hw_def &has_printer_port(bool has_printer_port) { m_has_printer_port = has_printer_port; return *this; } + msx_hw_def &has_cartslot(bool has_cartslot) { m_has_cartslot = has_cartslot; return *this; } + msx_hw_def &has_fdc(bool has_fdc) { m_has_fdc = has_fdc; return *this; } + +private: + bool m_has_cassette = true; + bool m_has_printer_port = true; + bool m_has_cartslot = false; + bool m_has_fdc = false; +}; + +class msx_state : public driver_device +{ +protected: + msx_state(const machine_config &mconfig, device_type type, const char *tag, XTAL main_xtal, int cpu_xtal_divider); + + enum ay8910_type + { + SND_AY8910, + SND_YM2149 + }; + + enum vdp_type + { + VDP_TMS9118, + VDP_TMS9128, + VDP_TMS9129, + VDP_TMS9918, + VDP_TMS9918A, + VDP_TMS9928A, + VDP_TMS9929A + }; + + void msx_base(ay8910_type ay8910_type, machine_config &config, const internal_layout &layout); + void msx1(vdp_type vdp_type, ay8910_type ay8910_type, machine_config &config, const internal_layout &layout); + void msx1_add_softlists(machine_config &config); + + // configuration helpers + template <typename T, typename U> + auto &add_internal_slot(machine_config &config, T &&type, U &&tag, u8 prim, u8 sec, u8 page, u8 numpages) + { + return add_internal_slot(config, std::forward<T>(type), std::forward<U>(tag), prim, true, sec, page, numpages); + } + template <typename T, typename U> + auto &add_internal_slot(machine_config &config, T &&type, U &&tag, u8 prim, u8 page, u8 numpages) + { + return add_internal_slot(config, std::forward<T>(type), std::forward<U>(tag), prim, false, 0, page, numpages); + } + template <typename T, typename U> + auto &add_internal_slot(machine_config &config, T &&type, U &&tag, u8 prim, u8 sec, u8 page, u8 numpages, const char *region, u32 offset = 0) + { + return add_internal_slot(config, std::forward<T>(type), std::forward<U>(tag), prim, true, sec, page, numpages, region, offset); + } + template <typename T, typename U> + auto &add_internal_slot(machine_config &config, T &&type, U &&tag, u8 prim, u8 page, u8 numpages, const char *region, u32 offset = 0) + { + return add_internal_slot(config, std::forward<T>(type), std::forward<U>(tag), prim, false, 0, page, numpages, region, offset); + } + template <typename T, typename U> + auto &add_internal_disk(machine_config &config, T &&type, U &&tag, u8 prim, u8 sec, u8 page, u8 numpages, const char *region, u32 offset = 0) + { + return add_internal_disk(config, std::forward<T>(type), std::forward<U>(tag), prim, true, sec, page, numpages, region, offset); + } + template <typename T, typename U> + auto &add_internal_disk(machine_config &config, T &&type, U &&tag, u8 prim, u8 page, u8 numpages, const char *region, u32 offset = 0) + { + return add_internal_disk(config, std::forward<T>(type), std::forward<U>(tag), prim, false, 0, page, numpages, region, offset); + } + template <int N, typename T, typename U> + auto &add_internal_slot_irq(machine_config &config, T &&type, U &&tag, u8 prim, u8 sec, u8 page, u8 numpages, const char *region, u32 offset = 0) + { + return add_internal_slot_irq<N>(config, std::forward<T>(type), std::forward<U>(tag), prim, true, sec, page, numpages, region, offset); + } + template <int N, typename T, typename U> + auto &add_internal_slot_irq(machine_config &config, T &&type, U &&tag, u8 prim, u8 page, u8 numpages, const char *region, u32 offset = 0) + { + return add_internal_slot_irq<N>(config, std::forward<T>(type), std::forward<U>(tag), prim, false, 0, page, numpages, region, offset); + } + template <int N, typename T, typename U> + auto &add_internal_slot_irq_mirrored(machine_config &config, T &&type, U &&tag, u8 prim, u8 sec, u8 page, u8 numpages, const char *region, u32 offset = 0) + { + auto &device = add_internal_slot_irq<N>(config, std::forward<T>(type), std::forward<U>(tag), prim, sec, page, numpages, region, offset); + device.set_size(0x4000); + return device; + } + template <typename T, typename U> + auto &add_internal_disk_mirrored(machine_config &config, T &&type, U &&tag, u8 prim, u8 sec, u8 page, u8 numpages, const char *region, u32 offset = 0) + { + return add_internal_disk_mirrored(config, std::forward<T>(type), std::forward<U>(tag), prim, true, sec, page, numpages, region, offset); + } + template <typename T, typename U> + auto &add_internal_disk_mirrored(machine_config &config, T &&type, U &&tag, u8 prim, u8 page, u8 numpages, const char *region, u32 offset = 0) + { + return add_internal_disk_mirrored(config, std::forward<T>(type), std::forward<U>(tag), prim, false, 0, page, numpages, region, offset); + } + template <int N, typename T, typename U, typename V> + auto &add_cartridge_slot(machine_config &config, T &&type, U &&tag, u8 prim, u8 sec, V &&intf, const char *deft) + { + return add_cartridge_slot<N>(config, std::forward<T>(type), std::forward<U>(tag), prim, true, sec, intf, deft); + } + template <int N, typename T, typename U, typename V> + auto &add_cartridge_slot(machine_config &config, T &&type, U &&tag, u8 prim, V &&intf, const char *deft) + { + return add_cartridge_slot<N>(config, std::forward<T>(type), std::forward<U>(tag), prim, false, 0, intf, deft); + } + template <int N> + auto &add_cartridge_slot(machine_config &config, u8 prim, u8 sec) + { + return add_cartridge_slot<N>(config, prim, true, sec); + } + template <int N> + auto &add_cartridge_slot(machine_config &config, u8 prim) + { + return add_cartridge_slot<N>(config, prim, false, 0); + } + template <int N> + auto &add_cartridge_slot(machine_config &config, u8 prim, XTAL xtal) + { + return add_cartridge_slot<N>(config, prim, false, 0, xtal); + } + virtual void driver_start() override; + virtual void machine_start() override; + virtual void machine_reset() override; + + void expanded_slot_w(u8 data); + u8 expanded_slot_r(); + u8 kanji_r(offs_t offset); + void kanji_w(offs_t offset, u8 data); + void ppi_port_a_w(u8 data); + void ppi_port_c_w(u8 data); + u8 ppi_port_b_r(); + u8 psg_port_a_r(); + u8 psg_port_b_r(); + void psg_port_a_w(u8 data); + void psg_port_b_w(u8 data); + + void msx_base_io_map(address_map &map); + void msx1_io_map(address_map &map); + void memory_map(address_map &map); + void memory_expand_slot(int slot); + memory_view::memory_view_entry *get_view(int page, int prim, int sec); + + required_device<z80_device> m_maincpu; + optional_device<cassette_image_device> m_cassette; + required_device<ay8910_device> m_ay8910; + required_device<dac_1bit_device> m_dac; + required_device<i8255_device> m_ppi; + optional_device<tms9928a_device> m_tms9928a; + optional_device<input_buffer_device> m_cent_status_in; + optional_device<output_latch_device> m_cent_ctrl_out; + optional_device<output_latch_device> m_cent_data_out; + optional_device<centronics_device> m_centronics; + required_device<speaker_device> m_speaker; + required_device<input_merger_any_high_device> m_mainirq; + required_device<screen_device> m_screen; + optional_memory_region m_region_kanji; + required_device<msx_general_purpose_port_device> m_gen_port1; + required_device<msx_general_purpose_port_device> m_gen_port2; + required_ioport_array<11> m_io_key; + msx_hw_def m_hw_def; + // This is here until more direct rom dumps from kanji font roms become available. + bool m_kanji_fsa1fx = false; + memory_view m_view_page0; + memory_view m_view_page1; + memory_view m_view_page2; + memory_view m_view_page3; + memory_view *m_view[4]; + // There must be a better way to do this + memory_view m_view_slot0_page0; + memory_view m_view_slot0_page1; + memory_view m_view_slot0_page2; + memory_view m_view_slot0_page3; + memory_view m_view_slot1_page0; + memory_view m_view_slot1_page1; + memory_view m_view_slot1_page2; + memory_view m_view_slot1_page3; + memory_view m_view_slot2_page0; + memory_view m_view_slot2_page1; + memory_view m_view_slot2_page2; + memory_view m_view_slot2_page3; + memory_view m_view_slot3_page0; + memory_view m_view_slot3_page1; + memory_view m_view_slot3_page2; + memory_view m_view_slot3_page3; + memory_view *m_exp_view[4][4]; + struct internal_slot + { + int prim; + bool is_expanded; + int sec; + int page; + int numpages; + msx_internal_slot_interface *internal_slot; + }; + std::vector<internal_slot> m_internal_slots; + + // PSG + u8 m_psg_b; + // kanji + u32 m_kanji_latch; + // memory + bool m_slot_expanded[4]; + u8 m_primary_slot; + u8 m_secondary_slot[4]; + u8 m_port_c_old; + u8 m_keylatch; + output_finder<> m_caps_led; + output_finder<> m_code_led; + const XTAL m_main_xtal; + const int m_cpu_xtal_divider; + +private: + // configuration helpers + template <typename T, typename U> + auto &add_base_slot(machine_config &config, T &&type, U &&tag, u8 prim, bool expanded, u8 sec, u8 page, u8 numpages, u32 clock = 0) + { + auto &device(std::forward<T>(type)(config, std::forward<U>(tag), clock)); + device.set_memory_space(m_maincpu, AS_PROGRAM); + device.set_io_space(m_maincpu, AS_IO); + device.set_maincpu(m_maincpu); + m_internal_slots.push_back({prim, expanded, sec, page, numpages, &device}); + return device; + } + template <typename T, typename U> + auto &add_internal_slot(machine_config &config, T &&type, U &&tag, u8 prim, bool expanded, u8 sec, u8 page, u8 numpages) + { + auto &device = add_base_slot(config, std::forward<T>(type), std::forward<U>(tag), prim, expanded, sec, page, numpages); + device.set_start_address(page * 0x4000); + device.set_size(numpages * 0x4000); + return device; + } + template <typename T, typename U> + auto &add_internal_slot(machine_config &config, T &&type, U &&tag, u8 prim, bool expanded, u8 sec, u8 page, u8 numpages, const char *region, u32 offset = 0) + { + auto &device = add_internal_slot(config, std::forward<T>(type), std::forward<U>(tag), prim, expanded, sec, page, numpages); + device.set_rom_start(region, offset); + return device; + } + template <typename T, typename U> + auto &add_internal_disk(machine_config &config, T &&type, U &&tag, u8 prim, bool expanded, u8 sec, u8 page, u8 numpages, const char *region, u32 offset = 0) + { + auto &device = add_internal_slot(config, std::forward<T>(type), std::forward<U>(tag), prim, true, sec, page, numpages, region, offset); + m_hw_def.has_fdc(true); + return device; + } + template <int N, typename T, typename U> + auto &add_internal_slot_irq(machine_config &config, T &&type, U &&tag, u8 prim, bool expanded, u8 sec, u8 page, u8 numpages, const char *region, u32 offset = 0) + { + auto &device = add_internal_slot(config, std::forward<T>(type), std::forward<U>(tag), prim, expanded, sec, page, numpages, region, offset); + device.irq_handler().set(m_mainirq, FUNC(input_merger_device::in_w<N>)); + return device; + } + template <typename T, typename U> + auto &add_internal_disk_mirrored(machine_config &config, T &&type, U &&tag, u8 prim, bool expanded, u8 sec, u8 page, u8 numpages, const char *region, u32 offset = 0) + { + // Memory mapped FDC registers are also accessible through page 2 + auto &device = add_internal_disk(config, std::forward<T>(type), std::forward<U>(tag), prim, expanded, sec, page, numpages, region, offset); + device.set_size(0x4000); + return device; + } + template <int N, typename T, typename U, typename V> + auto &add_cartridge_slot(machine_config &config, T &&type, U &&tag, u8 prim, bool expanded, u8 sec, V &&intf, const char *deft, u32 clock) + { + auto &device = add_base_slot(config, std::forward<T>(type), std::forward<U>(tag), prim, expanded, sec, 0, 4, clock); + device.option_reset(); + intf(device, expanded); + device.set_default_option(deft); + device.set_fixed(false); + device.irq_handler().set(m_mainirq, FUNC(input_merger_device::in_w<N>)); + device.add_route(ALL_OUTPUTS, m_speaker, 1.0); + return device; + } + template <int N, typename T, typename U, typename V> + auto &add_cartridge_slot(machine_config &config, T &&type, U &&tag, u8 prim, bool expanded, u8 sec, V &&intf, const char *deft) + { + return add_cartridge_slot<N>(config, std::forward<T>(type), std::forward<U>(tag), prim, expanded, sec, std::forward<V>(intf), deft, (m_main_xtal / m_cpu_xtal_divider).value()); + } + template <int N> + auto &add_cartridge_slot(machine_config &config, u8 prim, bool expanded, u8 sec) + { + static const char *tags[4] = { + "cartslot1", "cartslot2", "cartslot3", "cartslot4" + }; + static_assert(N >= 1 && N <= 4, "Invalid cartridge slot number"); + m_hw_def.has_cartslot(true); + return add_cartridge_slot<N>(config, MSX_SLOT_CARTRIDGE, tags[N-1], prim, expanded, sec, msx_cart, nullptr, (m_main_xtal / m_cpu_xtal_divider).value()); + } +}; + + +class msx2_base_state : public msx_state +{ +protected: + msx2_base_state(const machine_config &mconfig, device_type type, const char *tag, XTAL main_xtal, int cpu_xtal_divider) + : msx_state(mconfig, type, tag, main_xtal, cpu_xtal_divider) + , m_v9938(*this, "v9938") + , m_v9958(*this, "v9958") + , m_rtc(*this, "rtc") + , m_rtc_latch(0) + { + } + + virtual void machine_start() override; + + void msx2_base(ay8910_type ay8910_type, machine_config &config, const internal_layout &layout); + void msx2(ay8910_type ay8910_type, machine_config &config, const internal_layout &layout); + void msx2_pal(ay8910_type ay8910_type, machine_config &config, const internal_layout &layout); + void msx2plus_base(ay8910_type ay8910_type, machine_config &config, const internal_layout &layout); + void msx2plus(ay8910_type ay8910_type, machine_config &config, const internal_layout &layout); + void msx2plus_pal(ay8910_type ay8910_type, machine_config &config, const internal_layout &layout); + void turbor(ay8910_type ay8910_type, machine_config &config, const internal_layout &layout); + void msx2_add_softlists(machine_config &config); + void msx2plus_add_softlists(machine_config &config); + void turbor_add_softlists(machine_config &config); + void msx_ym2413(machine_config &config); + void msx2_64kb_vram(machine_config &config); + u8 rtc_reg_r(); + void rtc_reg_w(u8 data); + void rtc_latch_w(u8 data); + u8 switched_r(offs_t offset); + void switched_w(offs_t offset, u8 data); + void turbo_w(int state); + void msx2_base_io_map(address_map &map); + void msx2_io_map(address_map &map); + void msx2plus_io_map(address_map &map); + + std::vector<msx_switched_interface *> m_switched; + + optional_device<v9938_device> m_v9938; + optional_device<v9958_device> m_v9958; + required_device<rp5c01_device> m_rtc; + + // rtc + u8 m_rtc_latch = 0; +}; + +#endif // MAME_MSX_MSX_H |