From 63f8d3da216d40d3d05b0fbd4982099089f55697 Mon Sep 17 00:00:00 2001 From: hap Date: Wed, 24 Nov 2021 02:36:24 +0100 Subject: saitek_osa: added sparc module emulation [Ryan Holtz, hap] --- src/devices/bus/saitek_osa/expansion.cpp | 2 +- src/devices/bus/saitek_osa/expansion.h | 2 +- src/devices/bus/saitek_osa/sparc.cpp | 85 ++++++++++++++++++++++++++++---- src/devices/bus/saitek_osa/sparc.h | 24 +++++++-- src/devices/cpu/sparc/sparc.cpp | 12 ++--- src/mame/drivers/saitek_leonardo.cpp | 2 +- src/mame/drivers/saitek_renaissance.cpp | 4 +- src/tools/unidasm.cpp | 17 ++++--- 8 files changed, 115 insertions(+), 33 deletions(-) diff --git a/src/devices/bus/saitek_osa/expansion.cpp b/src/devices/bus/saitek_osa/expansion.cpp index 0c7e6be78bc..ba2dc790422 100644 --- a/src/devices/bus/saitek_osa/expansion.cpp +++ b/src/devices/bus/saitek_osa/expansion.cpp @@ -132,7 +132,7 @@ void saitekosa_expansion_device::pw_w(int state) u32 saitekosa_expansion_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { - return (m_module) ? m_module->screen_update(screen, bitmap, cliprect) : UPDATE_HAS_NOT_CHANGED; + return (m_module) ? m_module->screen_update(screen, bitmap, cliprect) : 0; } diff --git a/src/devices/bus/saitek_osa/expansion.h b/src/devices/bus/saitek_osa/expansion.h index f155754cea4..47364d492ec 100644 --- a/src/devices/bus/saitek_osa/expansion.h +++ b/src/devices/bus/saitek_osa/expansion.h @@ -113,7 +113,7 @@ public: virtual void ack_w(int state) { } virtual void pw_w(int state) { } - virtual u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { return UPDATE_HAS_NOT_CHANGED; } + virtual u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { return 0; } protected: device_saitekosa_expansion_interface(const machine_config &mconfig, device_t &device); diff --git a/src/devices/bus/saitek_osa/sparc.cpp b/src/devices/bus/saitek_osa/sparc.cpp index 3b3a4222665..0517b158686 100644 --- a/src/devices/bus/saitek_osa/sparc.cpp +++ b/src/devices/bus/saitek_osa/sparc.cpp @@ -8,7 +8,7 @@ Saitek OSA Module: Kasparov Sparc (1993) The chess engine is by the Spracklen's. Their last, and also their strongest. Hardware notes: -- Fujitsu MB86930 SPARClite @ 20MHz +- Fujitsu MB86930-20 SPARClite @ 20MHz - 256KB ROM (4*AMD AM27C512) - 1MB DRAM (8*NEC 424256-60), expandable to 4MB @@ -16,7 +16,8 @@ The module doesn't have its own LCD screen. It has a grill+fan underneath at the front part, and a heatsink on the CPU. TODO: -- skeleton device, missing SPARClite emulation, maybe only needs the MMU? +- runs too slow? opening book moves take around 3 seconds, but on the real + device less than 1 second ***************************************************************************/ @@ -34,15 +35,31 @@ DEFINE_DEVICE_TYPE(OSA_SPARC, saitekosa_sparc_device, "osa_sparc", "Sparc") saitekosa_sparc_device::saitekosa_sparc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : device_t(mconfig, OSA_SPARC, tag, owner, clock), device_saitekosa_expansion_interface(mconfig, *this), - m_maincpu(*this, "maincpu") + m_maincpu(*this, "maincpu"), + m_rom(*this, "maincpu"), + m_ram(*this, "ram") { } void saitekosa_sparc_device::device_start() { + m_rom_mask = m_rom.length() - 1; + set_ram_mask(20); // 1MB default + + // register for savestates + save_item(NAME(m_data_out)); + save_item(NAME(m_rom_mask)); + save_item(NAME(m_ram_mask)); + save_item(NAME(m_installed)); } void saitekosa_sparc_device::device_reset() { + if (!m_installed) + { + // MAME doesn't allow reading ioport at device_start + set_ram_mask(ioport("RAM")->read() ? 22 : 20); + m_installed = true; + } } @@ -81,6 +98,23 @@ const tiny_rom_entry *saitekosa_sparc_device::device_rom_region() const } +//------------------------------------------------- +// input_ports - device-specific input ports +//------------------------------------------------- + +static INPUT_PORTS_START( sparc ) + PORT_START("RAM") + PORT_CONFNAME( 0x01, 0x00, "RAM Size" ) + PORT_CONFSETTING( 0x00, "1MB" ) + PORT_CONFSETTING( 0x01, "4MB" ) +INPUT_PORTS_END + +ioport_constructor saitekosa_sparc_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(sparc); +} + + //------------------------------------------------- // device_add_mconfig - add device configuration //------------------------------------------------- @@ -88,11 +122,13 @@ const tiny_rom_entry *saitekosa_sparc_device::device_rom_region() const void saitekosa_sparc_device::device_add_mconfig(machine_config &config) { // basic machine hardware -#if 0 - SPARCV8(config, m_maincpu, 20_MHz_XTAL); - m_maincpu->set_addrmap(0, &saitekosa_sparc_device::main_map); - m_maincpu->set_mmu(nullptr); -#endif + MB86930(config, m_maincpu, 20_MHz_XTAL); + m_maincpu->set_addrmap(0x00, &saitekosa_sparc_device::debugger_map); + m_maincpu->cs0_read_cb().set(FUNC(saitekosa_sparc_device::rom_r)); + m_maincpu->cs2_read_cb().set(FUNC(saitekosa_sparc_device::ram_r)); + m_maincpu->cs2_write_cb().set(FUNC(saitekosa_sparc_device::ram_w)); + m_maincpu->cs3_read_cb().set(FUNC(saitekosa_sparc_device::host_io_r)); + m_maincpu->cs3_write_cb().set(FUNC(saitekosa_sparc_device::host_io_w)); } @@ -100,8 +136,26 @@ void saitekosa_sparc_device::device_add_mconfig(machine_config &config) // internal i/o //------------------------------------------------- -void saitekosa_sparc_device::main_map(address_map &map) +u32 saitekosa_sparc_device::host_io_r(offs_t offset, u32 mem_mask) { + // d0-d7: data input latch, d8: ACK-P + return m_expansion->data_state() | (m_expansion->ack_state() ? 0 : 0x100); +} + +void saitekosa_sparc_device::host_io_w(offs_t offset, u32 data, u32 mem_mask) +{ + // d0-d7: data output latch, d10: output latch enable + COMBINE_DATA(&m_data_out); + + // d8: STB-P, d9: RTS-P + m_expansion->stb_w(BIT(m_data_out, 8)); + m_expansion->rts_w(BIT(~m_data_out, 9)); +} + +void saitekosa_sparc_device::debugger_map(address_map &map) +{ + map(0x00000000, 0x0003ffff).rom().region("maincpu", 0); + map(0x01000000, 0x013fffff).ram().share("ram"); // 4MB } @@ -111,5 +165,16 @@ void saitekosa_sparc_device::main_map(address_map &map) u8 saitekosa_sparc_device::data_r() { - return 0xff; + return (m_data_out & 0x400) ? 0xff : (u8)m_data_out; +} + +void saitekosa_sparc_device::nmi_w(int state) +{ + m_maincpu->set_input_line(SPARC_IRQ1, !state ? ASSERT_LINE : CLEAR_LINE); +} + +void saitekosa_sparc_device::ack_w(int state) +{ + if (state != m_expansion->ack_state()) + machine().scheduler().boost_interleave(attotime::zero, attotime::from_usec(100)); } diff --git a/src/devices/bus/saitek_osa/sparc.h b/src/devices/bus/saitek_osa/sparc.h index 63855ff0a63..ffdda735502 100644 --- a/src/devices/bus/saitek_osa/sparc.h +++ b/src/devices/bus/saitek_osa/sparc.h @@ -24,21 +24,37 @@ public: // construction/destruction saitekosa_sparc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); - static constexpr feature_type unemulated_features() { return feature::COMMS; } - // from host virtual u8 data_r() override; + virtual void nmi_w(int state) override; + virtual void ack_w(int state) override; protected: virtual const tiny_rom_entry *device_rom_region() const override; + virtual ioport_constructor device_input_ports() const override; virtual void device_add_mconfig(machine_config &config) override; virtual void device_start() override; virtual void device_reset() override; private: - optional_device m_maincpu; + required_device m_maincpu; + required_region_ptr m_rom; + required_shared_ptr m_ram; + + void debugger_map(address_map &map); + + u32 rom_r(offs_t offset, u32 mem_mask) { return m_rom[offset & m_rom_mask]; } + u32 ram_r(offs_t offset, u32 mem_mask) { return m_ram[offset & m_ram_mask]; } + void ram_w(offs_t offset, u32 data, u32 mem_mask) { COMBINE_DATA(&m_ram[offset & m_ram_mask]); } + u32 host_io_r(offs_t offset, u32 mem_mask = ~0U); + void host_io_w(offs_t offset, u32 data, u32 mem_mask = ~0U); + + void set_ram_mask(u8 n) { m_ram_mask = ((1 << n) / 4) - 1; } - void main_map(address_map &map); + u32 m_data_out = 0; + u32 m_rom_mask = 0; + u32 m_ram_mask = 0; + bool m_installed = false; }; #endif // MAME_BUS_SAITEKOSA_SPARC_H diff --git a/src/devices/cpu/sparc/sparc.cpp b/src/devices/cpu/sparc/sparc.cpp index 3312bd236b3..d4ac48b6a33 100644 --- a/src/devices/cpu/sparc/sparc.cpp +++ b/src/devices/cpu/sparc/sparc.cpp @@ -1005,12 +1005,12 @@ void mb86930_device::wait_specifier_w(offs_t offset, uint32_t data, uint32_t mem COMBINE_DATA(&m_wssr[offset]); const uint32_t wait_idx = (offset << 1); - const bool wait_en0 = BIT(m_wssr[offset], 21) && !BIT(m_wssr[offset], 20); - const bool wait_en1 = BIT(m_wssr[offset], 8) && !BIT(m_wssr[offset], 7); - m_other_page_waits[wait_idx] = wait_en0 ? (((m_wssr[offset] >> 27) & 0x1f) + 1) : 0; - m_same_page_waits[wait_idx] = wait_en0 ? (((m_wssr[offset] >> 22) & 0x1f) + 1) : 0; - m_other_page_waits[wait_idx + 1] = wait_en1 ? (((m_wssr[offset] >> 14) & 0x1f) + 1) : 0; - m_same_page_waits[wait_idx + 1] = wait_en1 ? (((m_wssr[offset] >> 9) & 0x1f) + 1) : 0; + const bool wait_en0 = BIT(m_wssr[offset], 8) && !BIT(m_wssr[offset], 7); + const bool wait_en1 = BIT(m_wssr[offset], 21) && !BIT(m_wssr[offset], 20); + m_same_page_waits[wait_idx] = wait_en0 ? (((m_wssr[offset] >> 9) & 0x1f) + 1) : 0; + m_other_page_waits[wait_idx] = wait_en0 ? (((m_wssr[offset] >> 14) & 0x1f) + 1) : 0; + m_same_page_waits[wait_idx + 1] = wait_en1 ? (((m_wssr[offset] >> 22) & 0x1f) + 1) : 0; + m_other_page_waits[wait_idx + 1] = wait_en1 ? (((m_wssr[offset] >> 27) & 0x1f) + 1) : 0; } diff --git a/src/mame/drivers/saitek_leonardo.cpp b/src/mame/drivers/saitek_leonardo.cpp index 915e03d61a9..70597d181bb 100644 --- a/src/mame/drivers/saitek_leonardo.cpp +++ b/src/mame/drivers/saitek_leonardo.cpp @@ -176,7 +176,7 @@ void leo_state::unk_w(u8 data) void leo_state::exp_rts_w(int state) { - // NAND with ACK-P (not used by module) + // NAND with ACK-P (not used by chesscomputer?) } diff --git a/src/mame/drivers/saitek_renaissance.cpp b/src/mame/drivers/saitek_renaissance.cpp index 8838ffc46ff..b749b9131b8 100644 --- a/src/mame/drivers/saitek_renaissance.cpp +++ b/src/mame/drivers/saitek_renaissance.cpp @@ -23,7 +23,7 @@ so a chessboard display + 7seg info. It's on a small drawer that can be pushed in to hide the chessboard display. TODO: -- fart noise at boot if maestroa module is inserted +- fart noise at boot if maestroa or sparc module is inserted - make it a subdriver of saitek_leonardo.cpp? or too many differences - same TODO list as saitek_leonardo.cpp @@ -199,7 +199,7 @@ u8 ren_state::control_r() void ren_state::exp_rts_w(int state) { - // NAND with ACK-P (not used by module) + // NAND with ACK-P (not used by chesscomputer?) } diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp index 64610c3ba21..c691149945a 100644 --- a/src/tools/unidasm.cpp +++ b/src/tools/unidasm.cpp @@ -561,14 +561,15 @@ static const dasm_table_entry dasm_table[] = { "sm590", le, 0, []() -> util::disasm_interface * { return new sm590_disassembler; } }, { "sm5a", le, 0, []() -> util::disasm_interface * { return new sm5a_disassembler; } }, { "sm8500", le, 0, []() -> util::disasm_interface * { return new sm8500_disassembler; } }, - { "sparcv7", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, 7); } }, - { "sparcv8", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, 8); } }, - { "sparcv9", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, 9); } }, - { "sparcv9vis1", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, 9, sparc_disassembler::vis_1); } }, - { "sparcv9vis2", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, 9, sparc_disassembler::vis_2); } }, - { "sparcv9vis2p", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, 9, sparc_disassembler::vis_2p); } }, - { "sparcv9vis3", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, 9, sparc_disassembler::vis_3); } }, - { "sparcv9vis3b", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, 9, sparc_disassembler::vis_3b); } }, + { "sparclite", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, sparc_disassembler::sparclite); } }, + { "sparcv7", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, sparc_disassembler::v7); } }, + { "sparcv8", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, sparc_disassembler::v8); } }, + { "sparcv9", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, sparc_disassembler::v9); } }, + { "sparcv9vis1", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, sparc_disassembler::v9, sparc_disassembler::vis_1); } }, + { "sparcv9vis2", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, sparc_disassembler::v9, sparc_disassembler::vis_2); } }, + { "sparcv9vis2p", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, sparc_disassembler::v9, sparc_disassembler::vis_2p); } }, + { "sparcv9vis3", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, sparc_disassembler::v9, sparc_disassembler::vis_3); } }, + { "sparcv9vis3b", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, sparc_disassembler::v9, sparc_disassembler::vis_3b); } }, { "spc700", le, 0, []() -> util::disasm_interface * { return new spc700_disassembler; } }, { "ssem", le, 0, []() -> util::disasm_interface * { return new ssem_disassembler; } }, { "ssp1601", be, -1, []() -> util::disasm_interface * { return new ssp1601_disassembler; } }, -- cgit v1.2.3