From 233a5e82799b4e5fc47bee9efe788a9595738190 Mon Sep 17 00:00:00 2001 From: wilbertpol Date: Sun, 15 Sep 2024 17:36:42 +0100 Subject: msx/msx_s1990.cpp, msx/msxtr.cpp: Added preliminary MSX-Engine S1990 device and started implementing MSX turbo R. (#12753) Moved fsa1st and fsa1gt (Panasonic FSA-1 systems) to the new msx/msxtr.cpp source file. --- src/mame/layout/msx_turbor.lay | 91 ++++++++ src/mame/mame.lst | 6 +- src/mame/msx/msx2p.cpp | 96 --------- src/mame/msx/msx_s1990.cpp | 268 ++++++++++++++++++++++++ src/mame/msx/msx_s1990.h | 93 +++++++++ src/mame/msx/msxtr.cpp | 463 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 919 insertions(+), 98 deletions(-) create mode 100644 src/mame/layout/msx_turbor.lay create mode 100644 src/mame/msx/msx_s1990.cpp create mode 100644 src/mame/msx/msx_s1990.h create mode 100644 src/mame/msx/msxtr.cpp diff --git a/src/mame/layout/msx_turbor.lay b/src/mame/layout/msx_turbor.lay new file mode 100644 index 00000000000..6f66af755e6 --- /dev/null +++ b/src/mame/layout/msx_turbor.lay @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/mame/mame.lst b/src/mame/mame.lst index fc433641d81..2174e417874 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -32760,8 +32760,6 @@ expert3t // expertac // expertdx // fsa1fx // 1988 MSX2+ Japan -fsa1gt // -fsa1st // fsa1wsx // 1989 MSX2+ Japan fsa1wx // 1988 MSX2+ Japan fsa1wxa // 1988 MSX2+ Japan @@ -32771,6 +32769,10 @@ phc35j // 1989 MSX2+ Japan phc70fd // 1988 MSX2+ Japan phc70fd2 // 1988 MSX2+ Japan +@source:msx/msxtr.cpp +fsa1gt // +fsa1st // + @source:msx/pengadvb.cpp pengadvb // (c) 1988 Screen pengadvb2 // (c) 1988 Comet diff --git a/src/mame/msx/msx2p.cpp b/src/mame/msx/msx2p.cpp index 7cf6cf8cbd0..6458918768b 100644 --- a/src/mame/msx/msx2p.cpp +++ b/src/mame/msx/msx2p.cpp @@ -53,9 +53,6 @@ public: void phc35j(machine_config &config); void hbf1xdj(machine_config &config); void hbf1xv(machine_config &config); - - void fsa1gt(machine_config &config); - void fsa1st(machine_config &config); }; /******************************** MSX 2+ **********************************/ @@ -638,94 +635,6 @@ void msx2p_state::hbf1xv(machine_config &config) msx2plus(SND_YM2149, config, layout_msx_jp_1fdd); } -/* MSX Turbo-R - Panasonic FS-A1GT */ - -ROM_START(fsa1gt) - ROM_REGION(0x46c000, "maincpu", 0) - ROM_LOAD("a1gtbios.rom", 0x0000, 0x8000, CRC(937c8dbb) SHA1(242e73d8284a012b275c0a266844ebbc4269d787)) - ROM_LOAD("a1gtext.rom", 0x8000, 0x4000, CRC(70aea0fe) SHA1(018d7a5222f28514908fb1b1513286a6558a6d05)) - ROM_LOAD("a1gtdos.rom", 0xc000, 0x10000, CRC(bb2a0eae) SHA1(4880bf34f1c86fff5456ec2b4cf70d02339e2caa)) - ROM_LOAD("a1gtkdr.rom", 0x1c000, 0x8000, CRC(eaf0d125) SHA1(5b39c1ccd3a213b78e02927f56a9abc72cd8c28d)) - ROM_LOAD("a1gtmus.rom", 0x24000, 0x4000, CRC(f5f93437) SHA1(6aea1aef5ec31c1826c22edf580525f93baad425)) - ROM_LOAD("a1gtopt.rom", 0x28000, 0x4000, CRC(50d11f60) SHA1(b4433a3975c57dd440d6bf12dbd28b2ac1b90ef4)) - ROM_LOAD("a1gtkfn.rom", 0x2c000, 0x40000, CRC(1f6406fb) SHA1(5aff2d9b6efc723bc395b0f96f0adfa83cc54a49)) - ROM_LOAD("a1gtfirm.rom", 0x6c000, 0x400000, CRC(feefeadc) SHA1(e779c338eb91a7dea3ff75f3fde76b8af22c4a3a)) -ROM_END - -void msx2p_state::fsa1gt(machine_config &config) -{ - // AY8910 (in T9769) - // FDC: tc8566af, 1 3.5" DSDD drive - // 2 Cartridge slots - // T9769C + S1990 - // FM built-in - // Microphone - // MIDI-in - // MIDI-out - // firmware switch - // pause button - // ren-sha turbo slider - - add_internal_slot(config, MSX_SLOT_ROM, "bios", 0, 0, 0, 2, "maincpu"); - add_internal_slot(config, MSX_SLOT_MUSIC, "mus", 0, 2, 1, 1, "maincpu", 0x24000).set_ym2413_tag(m_ym2413); - add_internal_slot(config, MSX_SLOT_ROM, "opt", 0, 3, 1, 1, "maincpu", 0x28000); - add_cartridge_slot<1>(config, 1); - add_cartridge_slot<2>(config, 2); - add_internal_slot(config, MSX_SLOT_RAM_MM, "ram_mm", 3, 0, 0, 4).set_total_size(0x20000); // 128KB?? Mapper RAM - add_internal_slot(config, MSX_SLOT_ROM, "ext", 3, 1, 0, 1, "maincpu", 0x8000); - add_internal_slot(config, MSX_SLOT_ROM, "kdr", 3, 1, 1, 2, "maincpu", 0x1c000); - add_internal_disk(config, MSX_SLOT_DISK4_TC8566, "dos", 3, 2, 1, 3, "maincpu", 0xc000); - add_internal_slot(config, MSX_SLOT_ROM, "firm", 3, 3, 0, 4, "maincpu", 0x6c000); - MSX_SYSTEMFLAGS(config, "sysflags", m_maincpu, 0x00); - - msx_ym2413(config); - - turbor(SND_AY8910, config, layout_msx_jp_1fdd); -} - -/* MSX Turbo-R - Panasonic FS-A1ST */ - -ROM_START(fsa1st) - ROM_REGION(0x46c000, "maincpu", 0) - ROM_LOAD("a1stbios.rom", 0x0000, 0x8000, CRC(77b94ae0) SHA1(f078b5ec56884bfb81481d45c7151418770bff5a)) - ROM_LOAD("a1stext.rom", 0x8000, 0x4000, CRC(2c2c77a4) SHA1(373412f9c32762de1c3a7e27fc3d80614e0a0c8e)) - ROM_LOAD("a1stdos.rom", 0xc000, 0x10000, CRC(1fc71407) SHA1(5d2186658adcf4ce0c2d3232384b5712341108e5)) - ROM_LOAD("a1stkdr.rom", 0x1c000, 0x8000, CRC(eaf0d125) SHA1(5b39c1ccd3a213b78e02927f56a9abc72cd8c28d)) - ROM_LOAD("a1stmus.rom", 0x24000, 0x4000, CRC(fd7dec41) SHA1(e002a9b426732e6c2d31e548c40cf7c122348ce3)) - ROM_LOAD("a1stopt.rom", 0x28000, 0x4000, CRC(c6a4a2a1) SHA1(cb06dea7b025745f9d2b87dcf03ded615287ead3)) - ROM_LOAD("a1stkfn.rom", 0x2c000, 0x40000, CRC(1f6406fb) SHA1(5aff2d9b6efc723bc395b0f96f0adfa83cc54a49)) - ROM_LOAD("a1stfirm.rom", 0x6c000, 0x400000, CRC(139ac99c) SHA1(c212b11fda13f83dafed688c54d098e7e47ab225)) -ROM_END - -void msx2p_state::fsa1st(machine_config &config) -{ - // AY8910 (in T9769) - // FDC: tc8566af, 1 3.5" DSDD drive - // T9769C + S1990 - // 2 Cartridge slots - // FM built-in - // microphone - // firmware switch - // pause button - // ren-sha turbo slider - - add_internal_slot(config, MSX_SLOT_ROM, "bios", 0, 0, 0, 2, "maincpu"); - add_internal_slot(config, MSX_SLOT_MUSIC, "mus", 0, 2, 1, 1, "maincpu", 0x24000).set_ym2413_tag(m_ym2413); - add_internal_slot(config, MSX_SLOT_ROM, "opt", 0, 3, 1, 1, "maincpu", 0x28000); - add_cartridge_slot<1>(config, 1); - add_cartridge_slot<2>(config, 2); - add_internal_slot(config, MSX_SLOT_RAM_MM, "ram_mm", 3, 0, 0, 4).set_total_size(0x20000); // 128KB?? Mapper RAM - add_internal_slot(config, MSX_SLOT_ROM, "ext", 3, 1, 0, 1, "maincpu", 0x8000); - add_internal_slot(config, MSX_SLOT_ROM, "kdr", 3, 1, 1, 2, "maincpu", 0x1c000); - add_internal_disk(config, MSX_SLOT_DISK4_TC8566, "dos", 3, 2, 1, 3, "maincpu", 0xc000); - add_internal_slot(config, MSX_SLOT_ROM, "firm", 3, 3, 0, 4, "maincpu", 0x6c000); - MSX_SYSTEMFLAGS(config, "sysflags", m_maincpu, 0x00); - - msx_ym2413(config); - - turbor(SND_AY8910, config, layout_msx_jp_1fdd); -} - } // anonymous namespace COMP(19??, expert3i, 0, 0, expert3i, msx2, msx2p_state, empty_init, "Ciel", "Expert 3 IDE (MSX2+, Brazil)", MACHINE_NOT_WORKING) // Some hardware not emulated @@ -741,8 +650,3 @@ COMP(1989, phc70fd2, 0, 0, phc70fd2, msx2jp, msx2p_state, empty COMP(1989, phc35j, 0, 0, phc35j, msx2jp, msx2p_state, empty_init, "Sanyo", "PHC-35J / Wavy35 (MSX2+, Japan)", 0) COMP(1988, hbf1xdj, 0, 0, hbf1xdj, msx2jp, msx2p_state, empty_init, "Sony", "HB-F1XDJ (MSX2+, Japan)", 0) COMP(1989, hbf1xv, 0, 0, hbf1xv, msx2jp, msx2p_state, empty_init, "Sony", "HB-F1XV (MSX2+, Japan)", 0) - -/* MSX Turbo-R */ -/* Temporary placeholders, Turbo-R hardware is not supported yet */ -COMP(1991, fsa1gt, 0, 0, fsa1gt, msx2jp, msx2p_state, empty_init, "Panasonic", "FS-A1GT (MSX Turbo-R, Japan)", MACHINE_NOT_WORKING) -COMP(1991, fsa1st, 0, 0, fsa1st, msx2jp, msx2p_state, empty_init, "Panasonic", "FS-A1ST (MSX Turbo-R, Japan)", MACHINE_NOT_WORKING) diff --git a/src/mame/msx/msx_s1990.cpp b/src/mame/msx/msx_s1990.cpp new file mode 100644 index 00000000000..abc443cdf33 --- /dev/null +++ b/src/mame/msx/msx_s1990.cpp @@ -0,0 +1,268 @@ +// license:BSD-3-Clause +// copyright-holders:Wilbert Pol +#include "emu.h" +#include "msx_s1990.h" + + +#define LOG_CPU (1U << 1) +#define LOG_PCM (1U << 2) +//#define VERBOSE (LOG_CPU | LOG_PCM) +#include "logmacro.h" + +/*************************************************************************** + + ASCII S1990 MSX-Engine + +TODO: +- Injection of wait states when accessing VDP when Z80 is active. +- Injection of wait states when accessing VDP when R800 is active. +- Injection of wait state to align 7MHz R800 bus with 3.5MHz MSX bus. +- Unknown what the other internal registers do + +Internal registers: +- 0x00 +- 0x01 +- 0x02 +- 0x03 +- 0x04 +- 0x05 - Read only? + Read + 7------- Unknown + -6------ 1 - Firmware enabled + --543210 Unknown +- 0x06 - R/W - CPU Control + Write + 76------ Unknown + --5----- 0 - R800 active, 1 - Z80 active + ---43210 Unknown +- 0x07 +- 0x08 +- 0x09 +- 0x0a +- 0x0b +- 0x0c +- 0x0d +- 0x0e - Byte before last byte written - read only? +- 0x0f - Last byte written - read only? + +***************************************************************************/ + + +DEFINE_DEVICE_TYPE(MSX_S1990, msx_s1990_device, "msx_s1990", "MSX-Engine S1990") + + +msx_s1990_device::msx_s1990_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, MSX_S1990, tag, owner, clock) + , device_memory_interface(mconfig, *this) + , m_program_config("program", ENDIANNESS_LITTLE, 8, 16, 0) + , m_io_config("io", ENDIANNESS_LITTLE, 8, 16, 0) + , m_firmware_switch_cb(*this, 0) + , m_pause_led_cb(*this) + , m_r800_led_cb(*this) + , m_dac_write_cb(*this) + , m_sample_hold_cb(*this) + , m_select_cb(*this) + , m_filter_cb(*this) + , m_muting_cb(*this) + , m_comp_cb(*this, 0) + , m_z80(*this, finder_base::DUMMY_TAG) + , m_r800(*this, finder_base::DUMMY_TAG) + , m_reg_index(0) + , m_last_counter_reset(attotime::zero) + , m_last_pcm_write_ticks(0) + , m_pcm_control(0) + , m_pcm_data(0x80) + , m_dac_timer(nullptr) + , m_z80_halt_enabled(false) +{ +} + + +device_memory_interface::space_config_vector msx_s1990_device::memory_space_config() const +{ + return space_config_vector { + std::make_pair(AS_PROGRAM, &m_program_config), + std::make_pair(AS_IO, &m_io_config) + }; +} + + +void msx_s1990_device::device_start() +{ + space(AS_PROGRAM).specific(m_data); + space(AS_IO).specific(m_io); + + save_item(NAME(m_regs)); + save_item(NAME(m_reg_index)); + save_item(NAME(m_last_counter_reset)); + save_item(NAME(m_last_pcm_write_ticks)); + save_item(NAME(m_pcm_control)); + save_item(NAME(m_pcm_data)); + + m_dac_timer = timer_alloc(FUNC(msx_s1990_device::dac_write), this); +} + + +void msx_s1990_device::device_reset() +{ + m_regs[6] = 0x20; // Z80 active + m_last_counter_reset = attotime::zero; + m_last_pcm_write_ticks = 0; + m_z80->resume(SUSPEND_REASON_HALT); + m_r800->suspend(SUSPEND_REASON_HALT, true); +} + + +INPUT_CHANGED_MEMBER(msx_s1990_device::pause_callback) +{ + if (m_z80_halt_enabled && BIT(m_regs[0x06], 5)) + m_z80->set_input_line(Z80_INPUT_LINE_WAIT, BIT(newval, 0) ? ASSERT_LINE : CLEAR_LINE); +} + + +void msx_s1990_device::pause_w(u8 data) +{ + m_pause_led_cb(BIT(data, 0)); + m_z80_halt_enabled = BIT(data, 1); + m_r800_led_cb(BIT(data, 7)); +} + + +void msx_s1990_device::reg_index_write(u8 data) +{ + m_reg_index = data; +} + + +u8 msx_s1990_device::regs_read() +{ + if ((m_reg_index & 0x0f) == 0x05) + return (m_firmware_switch_cb()) ? 0x40 : 0x00; + return m_regs[m_reg_index & 0x0f]; +} + + +void msx_s1990_device::regs_write(u8 data) +{ + if ((m_reg_index & 0x0f) == 0x06) + { + if (BIT(data, 5)) + { + LOGMASKED(LOG_CPU, "Enable Z80, disable R800\n"); + m_z80->resume(SUSPEND_REASON_HALT); + m_r800->suspend(SUSPEND_REASON_HALT, true); + } + else + { + LOGMASKED(LOG_CPU, "Disable Z80, enable R800\n"); + m_z80->suspend(SUSPEND_REASON_HALT, true); + m_r800->resume(SUSPEND_REASON_HALT); + } + } + + m_regs[m_reg_index & 0x0f] = data; +} + + +void msx_s1990_device::mem_write(offs_t offset, u8 data) +{ + // TODO Clock syncing when in R800 mode + m_regs[0x0e] = m_regs[0x0f]; + m_regs[0x0f] = data; + m_data.write_byte(offset, data); +} + + +u8 msx_s1990_device::mem_read(offs_t offset) +{ + // TODO Clock syncing when in R800 mode + return m_data.read_byte(offset); +} + + +void msx_s1990_device::io_write(offs_t offset, u8 data) +{ + // TODO Clock syncing/extra wait cycles + // TODO Injection of wait states when accessing VDP + m_io.write_byte(offset, data); +} + + +u8 msx_s1990_device::io_read(offs_t offset) +{ + // TODO Clock syncing/extra wait cycles + return m_io.read_byte(offset); +} + + +void msx_s1990_device::counter_write(u8 data) +{ + // TODO: Round to last counter tick? + m_last_counter_reset = machine().time(); +} + + +u8 msx_s1990_device::counter_read(offs_t offset) +{ + u64 counter = attotime_to_clocks(machine().time() - m_last_counter_reset) / 28; + return (counter >> (8 * BIT(offset, 0))) & 0xff; +} + + +TIMER_CALLBACK_MEMBER(msx_s1990_device::dac_write) +{ + m_dac_write_cb(m_pcm_data); +} + + +void msx_s1990_device::pmdac(u8 data) +{ + m_pcm_data = data; + if (!BIT(m_pcm_control, 1)) + { + // Round to last counter tick and schedule next dac write? + m_last_pcm_write_ticks = machine().time().as_ticks(PCM_FREQUENCY); + m_dac_timer->adjust(attotime::from_ticks(m_last_pcm_write_ticks + 1, PCM_FREQUENCY)); + } +} + + +u8 msx_s1990_device::pmcnt() +{ + return (machine().time().as_ticks(PCM_FREQUENCY) - m_last_pcm_write_ticks) & 0x03; +} + + +void msx_s1990_device::pmcntl(u8 data) +{ + // 7------- 0 + // -6------ 0 + // --5----- 0 + // ---4---- SMPL + // ----3--- SEL + // -----2-- FILT + // ------1- MUTE + // -------0 ADDA ?? + + LOGMASKED(LOG_PCM, "pmcntl: %02x\n", data); + m_pcm_control = data & 0x1f; + m_sample_hold_cb(BIT(m_pcm_control, 4)); + m_select_cb(BIT(m_pcm_control, 3)); + m_filter_cb(BIT(m_pcm_control, 2)); + m_muting_cb(BIT(m_pcm_control, 1)); +} + + +u8 msx_s1990_device::pmstat() +{ + // 7------- COMP + // -6------ 0 + // --5----- 0 + // ---4---- SMPL + // ----3--- SEL + // -----2-- FILT + // ------1- MUTE + // -------0 BUFF ?? + + return (m_pcm_control & 0x1f) | (m_comp_cb() ? 0x80 : 0x00); +} diff --git a/src/mame/msx/msx_s1990.h b/src/mame/msx/msx_s1990.h new file mode 100644 index 00000000000..3a8c7587d35 --- /dev/null +++ b/src/mame/msx/msx_s1990.h @@ -0,0 +1,93 @@ +// license:BSD-3-Clause +// copyright-holders:Wilbert Pol +#ifndef MAME_MSX_MSX_S1990_H +#define MAME_MSX_MSX_S1990_H + +#pragma once + +#include "cpu/z80/r800.h" +#include "cpu/z80/z80.h" + +DECLARE_DEVICE_TYPE(MSX_S1990, msx_s1990_device) + +class msx_s1990_device : public device_t, + public device_memory_interface +{ +public: + msx_s1990_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + static constexpr feature_type imperfect_features() { return feature::TIMING; } + + // configuration + template void set_z80_tag(T &&tag) { m_z80.set_tag(std::forward(tag)); } + template void set_r800_tag(T &&tag) { m_r800.set_tag(std::forward(tag)); } + auto firmware_switch_callback() { return m_firmware_switch_cb.bind(); } + auto pause_led_callback() { return m_pause_led_cb.bind(); } + auto r800_led_callback() { return m_r800_led_cb.bind(); } + auto dac_write_callback() { return m_dac_write_cb.bind(); } + auto sample_hold_callback() { return m_sample_hold_cb.bind(); } + auto select_callback() { return m_select_cb.bind(); } + auto filter_callback() { return m_filter_cb.bind(); } + auto muting_callback() { return m_muting_cb.bind(); } + auto comp_callback() { return m_comp_cb.bind(); } + + void pause_w(u8 data); + + void reg_index_write(u8 data); + u8 regs_read(); + void regs_write(u8 data); + + void mem_write(offs_t offset, u8 data); + u8 mem_read(offs_t offset); + void io_write(offs_t offset, u8 data); + u8 io_read(offs_t offset); + + void counter_write(u8 data); + u8 counter_read(offs_t offset); + + void pmdac(u8 data); + u8 pmcnt(); + void pmcntl(u8 data); + u8 pmstat(); + + DECLARE_INPUT_CHANGED_MEMBER(pause_callback); + +protected: + virtual void device_start() override; + virtual void device_reset() override; + + // device_memory_interface implementation + virtual space_config_vector memory_space_config() const override; + virtual u32 translate_memory_address(u16 address) { return address; } + +private: + TIMER_CALLBACK_MEMBER(dac_write); + + static constexpr u32 PCM_FREQUENCY = 15750; + const address_space_config m_program_config; + const address_space_config m_io_config; + memory_access<16, 0, 0, ENDIANNESS_LITTLE>::specific m_data; + memory_access<16, 0, 0, ENDIANNESS_LITTLE>::specific m_io; + devcb_read_line m_firmware_switch_cb; + devcb_write_line m_pause_led_cb; + devcb_write_line m_r800_led_cb; + devcb_write8 m_dac_write_cb; + devcb_write_line m_sample_hold_cb; + devcb_write_line m_select_cb; + devcb_write_line m_filter_cb; + devcb_write_line m_muting_cb; + devcb_read_line m_comp_cb; + required_device m_z80; + required_device m_r800; + + u8 m_regs[16]; + u8 m_reg_index; + attotime m_last_counter_reset; + u64 m_last_pcm_write_ticks; + u8 m_pcm_control; + u8 m_pcm_data; + emu_timer *m_dac_timer; + bool m_z80_halt_enabled; +}; + +#endif // MAME_MSX_MSX_S1990_H diff --git a/src/mame/msx/msxtr.cpp b/src/mame/msx/msxtr.cpp new file mode 100644 index 00000000000..eb684081dbb --- /dev/null +++ b/src/mame/msx/msxtr.cpp @@ -0,0 +1,463 @@ +// license:BSD-3-Clause +// copyright-holders:Wilbert Pol + +#include "emu.h" +#include "msx.h" +#include "msx_keyboard.h" +#include "msx_s1990.h" +#include "msx_systemflags.h" +#include "bus/midi/midi.h" +#include "bus/msx/slot/disk.h" +#include "bus/msx/slot/music.h" +#include "bus/msx/slot/panasonic08r.h" +#include "bus/msx/slot/ram_mm.h" +#include "bus/msx/slot/rom.h" +#include "machine/i8251.h" +#include "machine/pit8253.h" +#include "softlist_dev.h" + +#include "msx_turbor.lh" + +using namespace msx_keyboard; + + +/*************************************************************************** + + MSX Turbo-R machine drivers + +The R800 and Z80 see exactly the same memory layouts, only one of the two CPUs +is active at any one time. The S1990 controls which CPU is active and can inject +wait states depending on which cpu is active. + +TODO: +- sfg extensions may not work due to irq callbacks being registered with the Z80 only. +- v9958 commands seem to execute too fast. Several software items hang because of this. +- verify midi interface operation on fsa1gt. +- Implement DAC/PCM related hardware/filter and hook it up to the S1990. +- Microphone input. + +***************************************************************************/ + +namespace { + +class msxtr_state : public msx2p_base_state +{ +public: + msxtr_state(const machine_config &mconfig, device_type type, const char *tag) + : msx2p_base_state(mconfig, type, tag, 21.477272_MHz_XTAL, 6) + , m_r800(*this, "r800") + , m_s1990(*this, "s1990") + , m_pause_switch(*this, "PAUSE") + , m_firmware_switch(*this, "FIRMWARE") + , m_pause_led(*this, "pause_led") + , m_r800_led(*this, "r800_led") + , m_pcmdac(*this, "pcmdac") + { + } + + void fsa1st(machine_config &config); + +protected: + virtual void machine_start() override; + virtual void machine_reset() override; + + void turbor(ay8910_type ay8910_type, machine_config &config, const internal_layout &layout); + void turbor_add_softlists(machine_config &config); + void s1990_mem_map(address_map &map); + void s1990_io_map(address_map &map); + void cpu_mem_map(address_map &map); + void cpu_io_map(address_map &map); + + virtual void setup_slot_spaces(msx_internal_slot_interface &device) override; + virtual address_space& get_io_space() override; + + void pause_led_w(int state); + void r800_led_w(int state); + void pcm_dac_w(u8 data); + void pcm_sample_hold_w(int state); + void pcm_select_w(int state); + void pcm_filter_w(int state); + void muting_w(int state); + int pcm_comp_r(); + + required_device m_r800; + required_device m_s1990; + required_ioport m_pause_switch; + required_ioport m_firmware_switch; + output_finder<> m_pause_led; + output_finder<> m_r800_led; + required_device m_pcmdac; + u8 m_pcm_last_sample; + u8 m_pcm_held_sample; + u8 m_pcm_sample_hold; +}; + +class fsa1gt_state : public msxtr_state +{ +public: + fsa1gt_state(const machine_config &mconfig, device_type type, const char *tag) + : msxtr_state(mconfig, type, tag) + , m_i8251(*this, "i8251") + , m_i8254(*this, "i8254") + , m_midiin(*this, "midiin_port") + , m_midiout(*this, "midiout_port") + , m_dtr(false) + , m_rts(false) + , m_rxrdy(false) + , m_timer2_ff(false) + { + } + + void fsa1gt(machine_config &config); + +private: + required_device m_i8251; + required_device m_i8254; + required_device m_midiin; + required_device m_midiout; + bool m_dtr; + bool m_rts; + bool m_rxrdy; + bool m_timer2_ff; + + void s1990_io_map(address_map &map); + void dtr_w(int state); + void rts_w(int state); + void rxrdy_w(int state); + void timer0_w(int state); + void timer2_w(int state); + void update_midi_int_state(); + void clear_timer2_ff(u8 data); +}; + + +address_space& msxtr_state::get_io_space() +{ + return m_s1990->space(AS_IO); +} + +void msxtr_state::setup_slot_spaces(msx_internal_slot_interface &device) +{ + device.set_memory_space(m_s1990, AS_PROGRAM); + device.set_io_space(m_s1990, AS_IO); + // TODO: This is used for signalling irq vectors. But that should go to the currently active cpu not just the z80. + device.set_maincpu(m_maincpu); +} + +void msxtr_state::machine_start() +{ + msx2p_base_state::machine_start(); + m_pause_led.resolve(); + m_r800_led.resolve(); + + save_item(NAME(m_pcm_last_sample)); + save_item(NAME(m_pcm_held_sample)); + save_item(NAME(m_pcm_sample_hold)); +} + +void msxtr_state::machine_reset() +{ + msx2p_base_state::machine_reset(); + m_pause_led = 0; + m_r800_led = 0; +} + +void msxtr_state::s1990_mem_map(address_map &map) +{ + memory_map(map); +} + +void msxtr_state::s1990_io_map(address_map &map) +{ + msx2plus_io_map(map); + map(0xa4, 0xa4).rw(m_s1990, FUNC(msx_s1990_device::pmcnt), FUNC(msx_s1990_device::pmdac)); + map(0xa5, 0xa5).rw(m_s1990, FUNC(msx_s1990_device::pmstat), FUNC(msx_s1990_device::pmcntl)); + map(0xa7, 0xa7).portr(m_pause_switch.finder_tag()); + map(0xa7, 0xa7).w(m_s1990, FUNC(msx_s1990_device::pause_w)); + map(0xe4, 0xe4).w(m_s1990, FUNC(msx_s1990_device::reg_index_write)); + map(0xe5, 0xe5).rw(m_s1990, FUNC(msx_s1990_device::regs_read), FUNC(msx_s1990_device::regs_write)); + map(0xe6, 0xe6).w(m_s1990, FUNC(msx_s1990_device::counter_write)); + map(0xe6, 0xe7).r(m_s1990, FUNC(msx_s1990_device::counter_read)); +} + +void msxtr_state::cpu_mem_map(address_map &map) +{ + map(0x0000, 0xffff).rw(m_s1990, FUNC(msx_s1990_device::mem_read), FUNC(msx_s1990_device::mem_write)); +} + +void msxtr_state::cpu_io_map(address_map &map) +{ + map.global_mask(0xff); + map(0x00, 0xff).rw(m_s1990, FUNC(msx_s1990_device::io_read), FUNC(msx_s1990_device::io_write)); +} + +void msxtr_state::pause_led_w(int state) +{ + m_pause_led = state; +} + +void msxtr_state::r800_led_w(int state) +{ + m_r800_led = state; +} + +void msxtr_state::turbor(ay8910_type ay8910_type, machine_config &config, const internal_layout &layout) +{ + msx2plus_base(ay8910_type, config, layout); + + m_maincpu->set_addrmap(AS_PROGRAM, &msxtr_state::cpu_mem_map); + m_maincpu->set_addrmap(AS_IO, &msxtr_state::cpu_io_map); + + R800(config, m_r800, 28.636363_MHz_XTAL); + m_r800->set_addrmap(AS_PROGRAM, &msxtr_state::cpu_mem_map); + m_r800->set_addrmap(AS_IO, &msxtr_state::cpu_io_map); + + MSX_S1990(config, m_s1990, 28.636363_MHz_XTAL / 4); + m_s1990->set_addrmap(AS_PROGRAM, &msxtr_state::s1990_mem_map); + m_s1990->set_addrmap(AS_IO, &msxtr_state::s1990_io_map); + m_s1990->set_z80_tag(m_maincpu); + m_s1990->set_r800_tag(m_r800); + m_s1990->pause_led_callback().set(FUNC(msxtr_state::pause_led_w)); + m_s1990->r800_led_callback().set(FUNC(msxtr_state::r800_led_w)); + m_s1990->firmware_switch_callback().set_ioport(m_firmware_switch); + m_s1990->dac_write_callback().set(FUNC(msxtr_state::pcm_dac_w)); + m_s1990->sample_hold_callback().set(FUNC(msxtr_state::pcm_sample_hold_w)); + m_s1990->select_callback().set(FUNC(msxtr_state::pcm_select_w)); + m_s1990->filter_callback().set(FUNC(msxtr_state::pcm_filter_w)); + m_s1990->muting_callback().set(FUNC(msxtr_state::muting_w)); + m_s1990->comp_callback().set(FUNC(msxtr_state::pcm_comp_r)); + + // TODO: Do IRQ requests go to both cpus (only to be ignored by the inactive cpu) or only to the currently active cpu? + m_mainirq->output_handler().append_inputline(m_r800, INPUT_LINE_IRQ0); + + DAC_8BIT_R2R(config, m_pcmdac).add_route(ALL_OUTPUTS, m_speaker, 1.0); // Unknown DAC type + + // Software lists + turbor_add_softlists(config); +} + +void msxtr_state::pcm_dac_w(u8 data) +{ + m_pcmdac->write(data); + m_pcm_last_sample = data; +} + +void msxtr_state::pcm_sample_hold_w(int state) +{ + if (!m_pcm_sample_hold && state) + m_pcm_held_sample = m_pcm_last_sample; + m_pcm_sample_hold = state; +} + +void msxtr_state::pcm_select_w(int state) +{ + // TODO pcm select +} + +void msxtr_state::pcm_filter_w(int state) +{ + // TODO enable pcm filter +} + +int msxtr_state::pcm_comp_r() +{ + // TODO pcm output compare + return 0; +} + +void msxtr_state::muting_w(int state) +{ + // TODO mute all sound +} + +void msxtr_state::turbor_add_softlists(machine_config &config) +{ + if (m_hw_def.has_cartslot()) + { + SOFTWARE_LIST(config, "cart_list").set_original("msxr_cart"); + SOFTWARE_LIST(config, "msx2p_cart_list").set_compatible("msx2p_cart"); + SOFTWARE_LIST(config, "msx2_cart_list").set_compatible("msx2_cart"); + SOFTWARE_LIST(config, "msx1_cart_list").set_compatible("msx1_cart"); + } + + if (m_hw_def.has_fdc()) + { + SOFTWARE_LIST(config, "flop_list").set_original("msxr_flop"); + SOFTWARE_LIST(config, "msx2p_flop_list").set_compatible("msx2p_flop"); + SOFTWARE_LIST(config, "msx2_flop_list").set_compatible("msx2_flop"); + SOFTWARE_LIST(config, "msx1_flop_list").set_compatible("msx1_flop"); + } +} + +/* MSX Turbo-R - Panasonic FS-A1GT */ + +ROM_START(fsa1gt) + ROM_REGION(0x400000, "firmware", 0) + // This should be 2 1MB roms at locations IC20 and IC23. + ROM_LOAD("a1gtfirm.rom", 0, 0x400000, CRC(feefeadc) SHA1(e779c338eb91a7dea3ff75f3fde76b8af22c4a3a) BAD_DUMP) + + ROM_REGION(0x40000, "kanji", 0) + ROM_LOAD("a1gtkfn.rom", 0, 0x40000, CRC(1f6406fb) SHA1(5aff2d9b6efc723bc395b0f96f0adfa83cc54a49)) +ROM_END + +void fsa1gt_state::s1990_io_map(address_map &map) +{ + msxtr_state::s1990_io_map(map); + map(0xe8, 0xe9).rw(m_i8251, FUNC(i8251_device::read), FUNC(i8251_device::write)); + map(0xea, 0xea).w(FUNC(fsa1gt_state::clear_timer2_ff)); + map(0xec, 0xef).rw(m_i8254, FUNC(pit8254_device::read), FUNC(pit8254_device::write)); +} + +void fsa1gt_state::fsa1gt(machine_config &config) +{ + // AY8910 (in T9769) + // FDC: tc8566af, 1 3.5" DSDD drive + // 2 Cartridge slots + // T9769C + S1990 + // FM built-in + // Microphone + // MIDI-in + // MIDI-out + // firmware switch + // pause button + // ren-sha turbo slider + + add_internal_slot(config, MSX_SLOT_ROM, "bios", 0, 0, 0, 2, "firmware", 0x050000); + add_internal_slot(config, MSX_SLOT_MUSIC, "msxmusic", 0, 2, 1, 1, "firmware", 0x07c000).set_ym2413_tag(m_ym2413); + add_internal_slot(config, MSX_SLOT_ROM, "opt", 0, 3, 1, 1, "firmware", 0x048000); + add_cartridge_slot<1>(config, 1); + add_cartridge_slot<2>(config, 2); + add_internal_slot(config, MSX_SLOT_RAM_MM, "ram_mm", 3, 0, 0, 4).set_total_size(0x80000); // 512KB Mapper RAM + add_internal_slot(config, MSX_SLOT_ROM, "ext", 3, 1, 0, 1, "firmware", 0x070000); + add_internal_slot(config, MSX_SLOT_ROM, "kdr", 3, 1, 1, 2, "firmware", 0x074000); + add_internal_disk(config, MSX_SLOT_DISK4_TC8566, "dos", 3, 2, 1, 3, "firmware", 0x060000); + add_internal_slot(config, MSX_SLOT_PANASONIC08R, "firmware", 3, 3, 0, 4, "firmware").set_sram_size(0x8000).set_mm_tag("ram_mm"); + + MSX_SYSTEMFLAGS(config, "sysflags", m_maincpu, 0x00); + + msx_ym2413(config); + + m_hw_def.has_cassette(false); + turbor(SND_AY8910, config, layout_msx_turbor); + m_s1990->set_addrmap(AS_IO, &fsa1gt_state::s1990_io_map); + + I8251(config, m_i8251, 16_MHz_XTAL / 4); // Not sure about this + m_i8251->txd_handler().set(m_midiout, FUNC(midi_port_device::write_txd)); + m_i8251->dtr_handler().set(*this, FUNC(fsa1gt_state::dtr_w)); + m_i8251->rts_handler().set(*this, FUNC(fsa1gt_state::rts_w)); + m_i8251->rxrdy_handler().set(*this, FUNC(fsa1gt_state::rxrdy_w)); + + PIT8254(config, m_i8254); + m_i8254->set_clk<0>(16_MHz_XTAL / 4); + m_i8254->set_clk<2>(16_MHz_XTAL/ 4); + m_i8254->out_handler<0>().set(*this, FUNC(fsa1gt_state::timer0_w)); + m_i8254->out_handler<2>().set(*this, FUNC(fsa1gt_state::timer2_w)); + + MIDI_PORT(config, m_midiin, midiin_slot, "midiin").rxd_handler().set(m_i8251, FUNC(i8251_device::rx_w)); + MIDI_PORT(config, m_midiout, midiout_slot, "midiout"); +} + +void fsa1gt_state::rts_w(int state) +{ + m_rts = state; + update_midi_int_state(); +} + +void fsa1gt_state::rxrdy_w(int state) +{ + m_rxrdy = state; + update_midi_int_state(); +} + +void fsa1gt_state::dtr_w(int state) +{ + m_dtr = state; + update_midi_int_state(); +} + +void fsa1gt_state::timer0_w(int state) +{ + m_i8251->tx_clock_w(state); + m_i8251->rx_clock_w(state); +} + +void fsa1gt_state::timer2_w(int state) +{ + m_timer2_ff = m_timer2_ff | state; + m_i8254->write_clk1(state); + update_midi_int_state(); +} + +void fsa1gt_state::clear_timer2_ff(u8 data) +{ + m_timer2_ff = false; + update_midi_int_state(); +} + +void fsa1gt_state::update_midi_int_state() +{ + m_i8251->write_dsr(m_timer2_ff && m_dtr); + m_mainirq->in_w<3>(!((m_timer2_ff && m_dtr) || (m_rts && m_rxrdy))); +} + +/* MSX Turbo-R - Panasonic FS-A1ST */ + +ROM_START(fsa1st) + ROM_REGION(0x400000, "firmware", 0) + // This should be either 3 512KB roms or 1 1MB and 1 512KB rom (at IC12 and IC18?). Both variants are known to exist. + ROM_LOAD("a1stfirm.rom", 0, 0x400000, CRC(139ac99c) SHA1(c212b11fda13f83dafed688c54d098e7e47ab225) BAD_DUMP) + + ROM_REGION(0x40000, "kanji", 0) + ROM_LOAD("a1stkfn.rom", 0, 0x40000, CRC(1f6406fb) SHA1(5aff2d9b6efc723bc395b0f96f0adfa83cc54a49)) +ROM_END + +void msxtr_state::fsa1st(machine_config &config) +{ + // AY8910 (in T9769) + // FDC: tc8566af, 1 3.5" DSDD drive + // T9769C + S1990 + // 2 Cartridge slots + // FM built-in + // microphone + // firmware switch + // pause button + // ren-sha turbo slider + + add_internal_slot(config, MSX_SLOT_ROM, "bios", 0, 0, 0, 2, "firmware", 0x050000); + add_internal_slot(config, MSX_SLOT_MUSIC, "msxmusic", 0, 2, 1, 1, "firmware", 0x07c000).set_ym2413_tag(m_ym2413); + add_internal_slot(config, MSX_SLOT_ROM, "opt", 0, 3, 1, 1, "firmware", 0x048000); + add_cartridge_slot<1>(config, 1); + add_cartridge_slot<2>(config, 2); + add_internal_slot(config, MSX_SLOT_RAM_MM, "ram_mm", 3, 0, 0, 4).set_total_size(0x40000); // 256KB Mapper RAM + add_internal_slot(config, MSX_SLOT_ROM, "ext", 3, 1, 0, 1, "firmware", 0x070000); + add_internal_slot(config, MSX_SLOT_ROM, "kdr", 3, 1, 1, 2, "firmware", 0x074000); + add_internal_disk(config, MSX_SLOT_DISK4_TC8566, "dos", 3, 2, 1, 3, "firmware", 0x060000); + add_internal_slot(config, MSX_SLOT_PANASONIC08R, "firmware", 3, 3, 0, 4, "firmware").set_sram_size(0x4000).set_mm_tag("ram_mm"); + + MSX_SYSTEMFLAGS(config, "sysflags", m_maincpu, 0x00); + + msx_ym2413(config); + + m_hw_def.has_cassette(false); + turbor(SND_AY8910, config, layout_msx_turbor); +} + +INPUT_PORTS_START(msxtr) + PORT_INCLUDE(msx2jp) + + PORT_START("PAUSE") + PORT_CONFNAME(0x01, 0x00, "Pause") PORT_CHANGED_MEMBER("s1990", msx_s1990_device, pause_callback, 0) + PORT_CONFSETTING(0x00, "off") + PORT_CONFSETTING(0x01, "on") + + PORT_START("FIRMWARE") + PORT_CONFNAME(0x01, 0x01, "Firmware") + PORT_CONFSETTING(0x01, "enabled") + PORT_CONFSETTING(0x00, "disabled") +INPUT_PORTS_END + +} // anonymous namespace + +/* MSX Turbo-R */ +COMP(1991, fsa1gt, 0, 0, fsa1gt, msxtr, fsa1gt_state, empty_init, "Panasonic", "FS-A1GT (MSX Turbo-R, Japan)", MACHINE_NOT_WORKING) +COMP(1991, fsa1st, 0, 0, fsa1st, msxtr, msxtr_state, empty_init, "Panasonic", "FS-A1ST (MSX Turbo-R, Japan)", MACHINE_NOT_WORKING) -- cgit v1.2.3