saitek_osa: added sparc module emulation [Ryan Holtz, hap]

This commit is contained in:
hap 2021-11-24 02:36:24 +01:00
parent 4518f0eade
commit 63f8d3da21
8 changed files with 115 additions and 33 deletions

View File

@ -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) 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;
} }

View File

@ -113,7 +113,7 @@ public:
virtual void ack_w(int state) { } virtual void ack_w(int state) { }
virtual void pw_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: protected:
device_saitekosa_expansion_interface(const machine_config &mconfig, device_t &device); device_saitekosa_expansion_interface(const machine_config &mconfig, device_t &device);

View File

@ -8,7 +8,7 @@ Saitek OSA Module: Kasparov Sparc (1993)
The chess engine is by the Spracklen's. Their last, and also their strongest. The chess engine is by the Spracklen's. Their last, and also their strongest.
Hardware notes: Hardware notes:
- Fujitsu MB86930 SPARClite @ 20MHz - Fujitsu MB86930-20 SPARClite @ 20MHz
- 256KB ROM (4*AMD AM27C512) - 256KB ROM (4*AMD AM27C512)
- 1MB DRAM (8*NEC 424256-60), expandable to 4MB - 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. at the front part, and a heatsink on the CPU.
TODO: 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) : 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_t(mconfig, OSA_SPARC, tag, owner, clock),
device_saitekosa_expansion_interface(mconfig, *this), 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() 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() 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 // 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) void saitekosa_sparc_device::device_add_mconfig(machine_config &config)
{ {
// basic machine hardware // basic machine hardware
#if 0 MB86930(config, m_maincpu, 20_MHz_XTAL);
SPARCV8(config, m_maincpu, 20_MHz_XTAL); m_maincpu->set_addrmap(0x00, &saitekosa_sparc_device::debugger_map);
m_maincpu->set_addrmap(0, &saitekosa_sparc_device::main_map); m_maincpu->cs0_read_cb().set(FUNC(saitekosa_sparc_device::rom_r));
m_maincpu->set_mmu(nullptr); m_maincpu->cs2_read_cb().set(FUNC(saitekosa_sparc_device::ram_r));
#endif 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 // 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() 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));
} }

View File

@ -24,21 +24,37 @@ public:
// construction/destruction // construction/destruction
saitekosa_sparc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); 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 // from host
virtual u8 data_r() override; virtual u8 data_r() override;
virtual void nmi_w(int state) override;
virtual void ack_w(int state) override;
protected: protected:
virtual const tiny_rom_entry *device_rom_region() const override; 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_add_mconfig(machine_config &config) override;
virtual void device_start() override; virtual void device_start() override;
virtual void device_reset() override; virtual void device_reset() override;
private: private:
optional_device<sparcv8_device> m_maincpu; required_device<mb86930_device> m_maincpu;
required_region_ptr<u32> m_rom;
required_shared_ptr<u32> m_ram;
void main_map(address_map &map); 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; }
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 #endif // MAME_BUS_SAITEKOSA_SPARC_H

View File

@ -1005,12 +1005,12 @@ void mb86930_device::wait_specifier_w(offs_t offset, uint32_t data, uint32_t mem
COMBINE_DATA(&m_wssr[offset]); COMBINE_DATA(&m_wssr[offset]);
const uint32_t wait_idx = (offset << 1); const uint32_t wait_idx = (offset << 1);
const bool wait_en0 = BIT(m_wssr[offset], 21) && !BIT(m_wssr[offset], 20); const bool wait_en0 = BIT(m_wssr[offset], 8) && !BIT(m_wssr[offset], 7);
const bool wait_en1 = 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_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] >> 9) & 0x1f) + 1) : 0;
m_same_page_waits[wait_idx] = wait_en0 ? (((m_wssr[offset] >> 22) & 0x1f) + 1) : 0; m_other_page_waits[wait_idx] = wait_en0 ? (((m_wssr[offset] >> 14) & 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] >> 22) & 0x1f) + 1) : 0;
m_same_page_waits[wait_idx + 1] = wait_en1 ? (((m_wssr[offset] >> 9) & 0x1f) + 1) : 0; m_other_page_waits[wait_idx + 1] = wait_en1 ? (((m_wssr[offset] >> 27) & 0x1f) + 1) : 0;
} }

View File

@ -176,7 +176,7 @@ void leo_state::unk_w(u8 data)
void leo_state::exp_rts_w(int state) void leo_state::exp_rts_w(int state)
{ {
// NAND with ACK-P (not used by module) // NAND with ACK-P (not used by chesscomputer?)
} }

View File

@ -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. pushed in to hide the chessboard display.
TODO: 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 - make it a subdriver of saitek_leonardo.cpp? or too many differences
- same TODO list as saitek_leonardo.cpp - same TODO list as saitek_leonardo.cpp
@ -199,7 +199,7 @@ u8 ren_state::control_r()
void ren_state::exp_rts_w(int state) void ren_state::exp_rts_w(int state)
{ {
// NAND with ACK-P (not used by module) // NAND with ACK-P (not used by chesscomputer?)
} }

View File

@ -561,14 +561,15 @@ static const dasm_table_entry dasm_table[] =
{ "sm590", le, 0, []() -> util::disasm_interface * { return new sm590_disassembler; } }, { "sm590", le, 0, []() -> util::disasm_interface * { return new sm590_disassembler; } },
{ "sm5a", le, 0, []() -> util::disasm_interface * { return new sm5a_disassembler; } }, { "sm5a", le, 0, []() -> util::disasm_interface * { return new sm5a_disassembler; } },
{ "sm8500", le, 0, []() -> util::disasm_interface * { return new sm8500_disassembler; } }, { "sm8500", le, 0, []() -> util::disasm_interface * { return new sm8500_disassembler; } },
{ "sparcv7", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, 7); } }, { "sparclite", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, sparc_disassembler::sparclite); } },
{ "sparcv8", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, 8); } }, { "sparcv7", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, sparc_disassembler::v7); } },
{ "sparcv9", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, 9); } }, { "sparcv8", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, sparc_disassembler::v8); } },
{ "sparcv9vis1", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, 9, sparc_disassembler::vis_1); } }, { "sparcv9", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, sparc_disassembler::v9); } },
{ "sparcv9vis2", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, 9, sparc_disassembler::vis_2); } }, { "sparcv9vis1", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, sparc_disassembler::v9, sparc_disassembler::vis_1); } },
{ "sparcv9vis2p", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, 9, sparc_disassembler::vis_2p); } }, { "sparcv9vis2", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, sparc_disassembler::v9, sparc_disassembler::vis_2); } },
{ "sparcv9vis3", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, 9, sparc_disassembler::vis_3); } }, { "sparcv9vis2p", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, sparc_disassembler::v9, sparc_disassembler::vis_2p); } },
{ "sparcv9vis3b", be, 0, []() -> util::disasm_interface * { return new sparc_disassembler(nullptr, 9, sparc_disassembler::vis_3b); } }, { "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; } }, { "spc700", le, 0, []() -> util::disasm_interface * { return new spc700_disassembler; } },
{ "ssem", le, 0, []() -> util::disasm_interface * { return new ssem_disassembler; } }, { "ssem", le, 0, []() -> util::disasm_interface * { return new ssem_disassembler; } },
{ "ssp1601", be, -1, []() -> util::disasm_interface * { return new ssp1601_disassembler; } }, { "ssp1601", be, -1, []() -> util::disasm_interface * { return new ssp1601_disassembler; } },