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)
{
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 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);

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

View File

@ -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<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

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

View File

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

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.
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?)
}

View File

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