zx spectrum: new slot devices, floating bus restore, big mface tidy-up (#7913)

This commit is contained in:
Tom 2022-01-25 12:45:31 +00:00 committed by GitHub
parent aafda14fb1
commit eb3c4e67da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
43 changed files with 1486 additions and 293 deletions

View File

@ -4114,6 +4114,8 @@ if (BUSES["SPECTRUM"]~=null) then
MAME_DIR .. "src/devices/bus/spectrum/mgt.h",
MAME_DIR .. "src/devices/bus/spectrum/mikroplus.cpp",
MAME_DIR .. "src/devices/bus/spectrum/mikroplus.h",
MAME_DIR .. "src/devices/bus/spectrum/mpoker.cpp",
MAME_DIR .. "src/devices/bus/spectrum/mpoker.h",
MAME_DIR .. "src/devices/bus/spectrum/opus.cpp",
MAME_DIR .. "src/devices/bus/spectrum/opus.h",
MAME_DIR .. "src/devices/bus/spectrum/plus2test.cpp",
@ -4128,6 +4130,8 @@ if (BUSES["SPECTRUM"]~=null) then
MAME_DIR .. "src/devices/bus/spectrum/speccydos.h",
MAME_DIR .. "src/devices/bus/spectrum/specdrum.cpp",
MAME_DIR .. "src/devices/bus/spectrum/specdrum.h",
MAME_DIR .. "src/devices/bus/spectrum/specmate.cpp",
MAME_DIR .. "src/devices/bus/spectrum/specmate.h",
MAME_DIR .. "src/devices/bus/spectrum/uslot.cpp",
MAME_DIR .. "src/devices/bus/spectrum/uslot.h",
MAME_DIR .. "src/devices/bus/spectrum/usource.cpp",

View File

@ -264,6 +264,7 @@ void spectrum_betav2_device::device_add_mconfig_base(machine_config& config)
SPECTRUM_EXPANSION_SLOT(config, m_exp, spectrum_expansion_devices, nullptr);
m_exp->irq_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::irq_w));
m_exp->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::nmi_w));
m_exp->fb_r_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::fb_r));
}
void spectrum_betav2_device::device_add_mconfig(machine_config &config)

View File

@ -114,6 +114,7 @@ void spectrum_beta128_device::device_add_mconfig(machine_config &config)
SPECTRUM_EXPANSION_SLOT(config, m_exp, spectrum_expansion_devices, nullptr);
m_exp->irq_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::irq_w));
m_exp->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::nmi_w));
m_exp->fb_r_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::fb_r));
}
const tiny_rom_entry *spectrum_beta128_device::device_rom_region() const

View File

@ -246,7 +246,7 @@ void spectrum_d40base_device::pre_opcode_fetch(offs_t offset)
uint8_t spectrum_d40base_device::iorq_r(offs_t offset)
{
uint8_t data = 0xff;
uint8_t data = offset & 1 ? m_slot->fb_r() : 0xff;
switch (offset & 0xf9)
{

View File

@ -45,7 +45,8 @@ spectrum_expansion_slot_device::spectrum_expansion_slot_device(const machine_con
device_single_card_slot_interface<device_spectrum_expansion_interface>(mconfig, *this),
m_card(nullptr),
m_irq_handler(*this),
m_nmi_handler(*this)
m_nmi_handler(*this),
m_fb_r_handler(*this)
{
}
@ -61,6 +62,7 @@ void spectrum_expansion_slot_device::device_start()
// resolve callbacks
m_irq_handler.resolve_safe();
m_nmi_handler.resolve_safe();
m_fb_r_handler.resolve_safe(0xff);
}
//-------------------------------------------------
@ -112,7 +114,7 @@ uint8_t spectrum_expansion_slot_device::iorq_r(offs_t offset)
if (m_card)
return m_card->iorq_r(offset);
else
return 0xff;
return offset & 1 ? fb_r() : 0xff;
}
//-------------------------------------------------
@ -169,6 +171,7 @@ void spectrum_expansion_slot_device::mreq_w(offs_t offset, uint8_t data)
#include "mface.h"
#include "mgt.h"
#include "mikroplus.h"
#include "mpoker.h"
#include "opus.h"
#include "plus2test.h"
#include "protek.h"
@ -176,6 +179,7 @@ void spectrum_expansion_slot_device::mreq_w(offs_t offset, uint8_t data)
#include "sixword.h"
#include "specdrum.h"
#include "speccydos.h"
#include "specmate.h"
#include "uslot.h"
#include "usource.h"
#include "uspeech.h"
@ -206,9 +210,14 @@ void spectrum_expansion_devices(device_slot_interface &device)
device.option_add("lprint", SPECTRUM_LPRINT);
device.option_add("lprint3", SPECTRUM_LPRINT3);
device.option_add("melodik", SPECTRUM_MELODIK);
device.option_add("mface1v1", SPECTRUM_MFACE1V1);
device.option_add("mface1v2", SPECTRUM_MFACE1V2);
device.option_add("mface1v3", SPECTRUM_MFACE1V3);
device.option_add("mface1", SPECTRUM_MFACE1);
device.option_add("mface128v1", SPECTRUM_MFACE128V1);
device.option_add("mface128", SPECTRUM_MFACE128);
device.option_add("mikroplus", SPECTRUM_MIKROPLUS);
device.option_add("mpoker", SPECTRUM_MPOKER);
device.option_add("mprint", SPECTRUM_MPRINT);
device.option_add("opus", SPECTRUM_OPUS);
device.option_add("plusd", SPECTRUM_PLUSD);
@ -218,6 +227,7 @@ void spectrum_expansion_devices(device_slot_interface &device)
device.option_add("speccydos", SPECTRUM_SPECCYDOS);
device.option_add("spdos", SPECTRUM_SPDOS);
device.option_add("specdrum", SPECTRUM_SPECDRUM);
device.option_add("specmate", SPECTRUM_SPECMATE);
device.option_add("swiftdisc", SPECTRUM_SWIFTDISC);
device.option_add("swiftdisc2", SPECTRUM_SWIFTDISC2);
device.option_add("uslot", SPECTRUM_USLOT);
@ -233,6 +243,7 @@ void spec128_expansion_devices(device_slot_interface &device)
device.option_add("intf1", SPECTRUM_INTF1);
device.option_add("intf2", SPECTRUM_INTF2);
device.option_add("kempjoy", SPECTRUM_KEMPJOY);
device.option_add("mface128v1", SPECTRUM_MFACE128V1);
device.option_add("mface128", SPECTRUM_MFACE128);
device.option_add("mikroplus", SPECTRUM_MIKROPLUS);
device.option_add("mprint", SPECTRUM_MPRINT);
@ -249,6 +260,7 @@ void spec128_expansion_devices(device_slot_interface &device)
void specpls3_expansion_devices(device_slot_interface &device)
{
device.option_add("kempjoy", SPECTRUM_KEMPJOY);
device.option_add("mface3", SPECTRUM_MFACE3);
}

View File

@ -76,6 +76,7 @@ public:
// callbacks
auto irq_handler() { return m_irq_handler.bind(); }
auto nmi_handler() { return m_nmi_handler.bind(); }
auto fb_r_handler() { return m_fb_r_handler.bind(); }
void pre_opcode_fetch(offs_t offset);
void post_opcode_fetch(offs_t offset);
@ -90,6 +91,7 @@ public:
DECLARE_WRITE_LINE_MEMBER( irq_w ) { m_irq_handler(state); }
DECLARE_WRITE_LINE_MEMBER( nmi_w ) { m_nmi_handler(state); }
uint8_t fb_r() { return m_fb_r_handler(); }
protected:
// device-level overrides
@ -100,6 +102,7 @@ protected:
private:
devcb_write_line m_irq_handler;
devcb_write_line m_nmi_handler;
devcb_read8 m_fb_r_handler;
};
@ -115,7 +118,7 @@ public:
virtual void post_data_fetch(offs_t offset) { };
virtual uint8_t mreq_r(offs_t offset) { return 0xff; }
virtual void mreq_w(offs_t offset, uint8_t data) { }
virtual uint8_t iorq_r(offs_t offset) { return 0xff; }
virtual uint8_t iorq_r(offs_t offset) { return offset & 1 ? m_slot->fb_r() : 0xff; }
virtual void iorq_w(offs_t offset, uint8_t data) { }
virtual DECLARE_READ_LINE_MEMBER(romcs) { return 0; }

View File

@ -131,6 +131,7 @@ void spectrum_flpone_device::device_add_mconfig(machine_config &config)
SPECTRUM_EXPANSION_SLOT(config, m_exp, spectrum_expansion_devices, nullptr);
m_exp->irq_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::irq_w));
m_exp->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::nmi_w));
m_exp->fb_r_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::fb_r));
}
const tiny_rom_entry *spectrum_flpone_device::device_rom_region() const

View File

@ -55,6 +55,7 @@ void spectrum_fuller_device::device_add_mconfig(machine_config &config)
SPECTRUM_EXPANSION_SLOT(config, m_exp, spectrum_expansion_devices, nullptr);
m_exp->irq_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::irq_w));
m_exp->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::nmi_w));
m_exp->fb_r_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::fb_r));
}
//**************************************************************************
@ -95,10 +96,10 @@ uint8_t spectrum_fuller_device::iorq_r(offs_t offset)
switch (offset & 0xff)
{
case 0x5f:
data &= m_psg->data_r();
data = m_psg->data_r();
break;
case 0x7f:
data &= m_joy->read() | (0xff ^ 0x8f);
data = m_joy->read() | (0xff ^ 0x8f);
break;
}
return data;

View File

@ -54,6 +54,7 @@ void spectrum_intf1_device::device_add_mconfig(machine_config &config)
SPECTRUM_EXPANSION_SLOT(config, m_exp, spectrum_expansion_devices, nullptr);
m_exp->irq_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::irq_w));
m_exp->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::nmi_w));
m_exp->fb_r_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::fb_r));
SOFTWARE_LIST(config, "microdrive_list").set_original("spectrum_microdrive");
}

View File

@ -128,7 +128,7 @@ uint8_t spectrum_intf2_device::mreq_r(offs_t offset)
uint8_t spectrum_intf2_device::iorq_r(offs_t offset)
{
uint8_t data = 0xff;
uint8_t data = offset & 1 ? m_slot->fb_r() : 0xff;
switch (offset & 0xff)
{

View File

@ -96,6 +96,7 @@ void spectrum_kempdisc_device::device_add_mconfig(machine_config &config)
SPECTRUM_EXPANSION_SLOT(config, m_exp, spectrum_expansion_devices, nullptr);
m_exp->irq_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::irq_w));
m_exp->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::nmi_w));
m_exp->fb_r_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::fb_r));
}
const tiny_rom_entry *spectrum_kempdisc_device::device_rom_region() const
@ -174,7 +175,7 @@ uint8_t spectrum_kempdisc_device::iorq_r(offs_t offset)
switch (offset & 0xff)
{
case 0xe5: case 0xe7: case 0xed: case 0xef:
data &= m_fdc->read(BIT(offset, 1) | (BIT(offset, 3) << 1));
data = m_fdc->read(BIT(offset, 1) | (BIT(offset, 3) << 1));
break;
}

View File

@ -71,9 +71,9 @@ void spectrum_kempjoy_device::device_start()
uint8_t spectrum_kempjoy_device::iorq_r(offs_t offset)
{
uint8_t data = 0xff;
uint8_t data = offset & 1 ? m_slot->fb_r() : 0xff;
if ((offset & 0x00ff) == 0x1f)
if ((offset & 0xe0) == 0) // 000- ---- uses 0x1f
{
data = m_joy->read() & 0x1f;
}

View File

@ -170,7 +170,7 @@ uint8_t spectrum_proceed_device::mreq_r(offs_t offset)
uint8_t spectrum_proceed_device::iorq_r(offs_t offset)
{
uint8_t data = 0xff;
uint8_t data = offset & 1 ? m_slot->fb_r() : 0xff;
if (!BIT(offset, 5))
data = m_z80pio->read((offset >> 6) & 3);

View File

@ -98,6 +98,7 @@ void spectrum_lprint3_device::device_add_mconfig(machine_config &config)
SPECTRUM_EXPANSION_SLOT(config, m_exp, spectrum_expansion_devices, nullptr);
m_exp->irq_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::irq_w));
m_exp->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::nmi_w));
m_exp->fb_r_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::fb_r));
}
void spectrum_kempcentrs_device::device_add_mconfig(machine_config &config)
@ -279,7 +280,7 @@ uint8_t spectrum_lprint_device::mreq_r(offs_t offset)
uint8_t spectrum_lprint_device::iorq_r(offs_t offset)
{
uint8_t data = 0xff;
uint8_t data = offset & 1 ? m_slot->fb_r() : 0xff;
if (!BIT(offset, 2))
{
@ -374,7 +375,7 @@ uint8_t spectrum_lprint3_device::mreq_r(offs_t offset)
uint8_t spectrum_kempcentrs_device::iorq_r(offs_t offset)
{
uint8_t data = 0xff;
uint8_t data = offset & 1 ? m_slot->fb_r() : 0xff;
switch (offset)
{
@ -432,7 +433,7 @@ void spectrum_kempcentre_device::pre_data_fetch(offs_t offset)
uint8_t spectrum_kempcentre_device::iorq_r(offs_t offset)
{
uint8_t data = 0xff;
uint8_t data = offset & 1 ? m_slot->fb_r() : 0xff;
if (!BIT(offset, 2)) // earlier version ? uses same paging as Lprint III
{
@ -506,7 +507,7 @@ void spectrum_kempcentreu_device::pre_opcode_fetch(offs_t offset)
uint8_t spectrum_kempcentreu_device::iorq_r(offs_t offset)
{
uint8_t data = 0xff;
uint8_t data = offset & 1 ? m_slot->fb_r() : 0xff;
if ((offset & 0xf0) == 0xb0) // BB or BF, actual address decode is not known
{

View File

@ -32,6 +32,7 @@ void spectrum_melodik_device::device_add_mconfig(machine_config &config)
SPECTRUM_EXPANSION_SLOT(config, m_exp, spectrum_expansion_devices, nullptr);
m_exp->irq_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::irq_w));
m_exp->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::nmi_w));
m_exp->fb_r_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::fb_r));
}
//**************************************************************************
@ -71,7 +72,7 @@ uint8_t spectrum_melodik_device::iorq_r(offs_t offset)
switch (offset & 0xc002)
{
case 0xc000:
data &= m_psg->data_r();
data = m_psg->data_r();
break;
}
return data;

View File

@ -17,16 +17,26 @@
© Romantic Robot UK Ltd 1985
Compatibility (real hardware)
-------------
mface1 models work with 48K, 128K/+2 (only in 48K mode), don't work with +2A/+3
mface128 models work with 48K/128K/+2, don't work with +2A/+3
mface3 works only with +2A/+3
mprint works with 48K/128K/+2, doesn't work with +2A/+3
incompatibility is due mainly to expansion slot pinout changes on last Amstrad built models.
Multiface One
-------------
Many versions exist, a very good source of info is: https://x128.speccy.cz/multiface/multiface.htm
Summary:
Earliest version has 2KB of RAM, composite video output, and no toolkit (pokes only).
Next version has 8KB of RAM, composite video output, and basic toolkit (including pokes).
Earliest version has 2KB of RAM, composite video output, and no pokes or toolkit.
Next version has 8KB of RAM, composite video output, and basic toolkit (just pokes).
Latest and most common version dropped the composite video output, added an enable/disable switch, and full-featured toolkit.
A special (and rare) version supports the Kempston Disc interface but drops Beta support. (not sold in stores, available only on request).
At some point during "early" revisions, the page out port changed from 0x5f to 0x1f.
At some point the page out port changed from 0x5f to 0x1f (rev 2.0 pcb?)
Three pcb revs are known: 1.2, 2.0, 2.1.
Various clone/hacked rom versions are known to exist as well.
Roms:
@ -34,12 +44,16 @@
The two hex digits are the rom checksum.
With the MF menu on-screen, press Symbol Shift + A (STOP) to see checksum, space to return.
The "joystick disable" jumper is required for use with Beta disk which would otherwise not work due to port clash.
Real world mf1/beta combo only works spectrum->mf1->beta, with jumper open, the user manual suggests Beta users may like to fit a switch instead.
Some confusion exactly how this works, as an original-looking schematic shows the jumper simply setting data bits 6,7 hi-z, with the actual joystick still operational.
This isn't enough to stop the clash so perhaps schematic is for some non-Beta-supporting version or has an error.
Assume for now the entire joystick is disabled as that's the only way Beta can work.
Beta support seems limited to Beta v3/plus (TR-DOS 3/4.xx) models, beta128 (TR-DOS 5.xx) doesn't work.
Bios rom "mu21e7" has issues with Betaplus, doesn't work with betav3,beta128,betacbi, perhaps it's for some other interface entirely...?
The enable/disable switch became necessary on later versions as games had started including checks to detect presence of the interface.
eg. Renegade ("The Hit Squad" re-release) whilst loading, reads from 0x9f specifically to cause the MF (if present) to page in and crash the machine.
Todo: confirm exact operation of disable switch.
As mentioned in the user instructions, there is a "joystick disable" jumper inside the unit which must be cut to allow Beta disk compatibility.
The joystick is not actually disabled but rather just data bus bits D6 + D7 are held hi-z for any reads of kempston range 0b000xxxxx.
rom maps to 0x0000
ram maps to 0x2000
@ -55,27 +69,51 @@
Multiface 128
-------------
128K/+2 support (also works with 48K)
DISCiPLE/Plus D disc support
Software enable/disable (in menu, press 'o' to toggle on/off)
Some new 128k-exclusive menu features when running in 128k mode (mode is auto-detected)
No joystick port
Software enable/disable
"Hypertape" recording (?)
No Beta support
Pass-through connector was optional
Original hardware version isn't compatible with DISCiPLE/+D (port clash), has "hypertape" high-speed tape recording
Second hardware version added DISCiPLE/+D compatibility and support as save device (uses different ports) but lost hypertape support
Todo ...
supported devices rom
-----+----------------------------------------+-------------
v1 Tape, Hypertape, Microdrive, Opus 87.1, 87.12
v2 Tape, Microdrive, Opus, DISCiPLE/+D 87.2
I/O R/W v1 v2
---------+-----+-----------+-----------
page in R 0x9f 0xbf
page out R 0x1f 0x3f
nmi reset W 0x9f 0xbf
hide W 0x1f 0x3f
Multiface 3
-----------
+2A/+2B/+3/3B support (doesn't work with 48K/128K/+2)
+2A/+2B/+3/+3B support (doesn't work with 48K/128K/+2)
+3 disk support
Todo ...
Pass-through connector was optional
No support for older external disk interfaces (Beta, Opus, +D etc.)
Pcb/logic is quite different to other models, has a PAL16L8 and 74LS670 4x4 register file.
A schematic created from the Hard Mirco clone pcb is available, used for various modern "re-creation" projects,
official version assumed to be very similar if not identical.
Hard Mirco clone has double size ROM (16K), but contains two identical 8K halves of data. Pcb does have ability to select rom half via software,
so perhaps an unused multi-bios feature? (unknown if unique to clone pcb or present on official pcb also).
Multiprint
----------
Version ? multiface with Centronics printer interface
Printer interface with some mface features
No backup/snapshot feature
Has all other usual mface features: cheat/poke, 8KB RAM, magic button etc.
Centronics parallel printer port
Kempston E and ZX Lprint compatible (LPRINT, LLIST, COPY etc.)
Unique "REM" command set (commands "hidden" in rem comments)
Pass-through connector was optional
Todo ...
Todo: find other print command hooks, only magic button triggered menu works for now...
*********************************************************************/
@ -88,7 +126,11 @@
DEVICE DEFINITIONS
***************************************************************************/
DEFINE_DEVICE_TYPE(SPECTRUM_MFACE1V1, spectrum_mface1v1_device, "spectrum_mface1v1", "Multiface One v1")
DEFINE_DEVICE_TYPE(SPECTRUM_MFACE1V2, spectrum_mface1v2_device, "spectrum_mface1v2", "Multiface One v2")
DEFINE_DEVICE_TYPE(SPECTRUM_MFACE1V3, spectrum_mface1v3_device, "spectrum_mface1v3", "Multiface One v3")
DEFINE_DEVICE_TYPE(SPECTRUM_MFACE1, spectrum_mface1_device, "spectrum_mface1", "Multiface One")
DEFINE_DEVICE_TYPE(SPECTRUM_MFACE128V1, spectrum_mface128v1_device, "spectrum_mface128v1", "Multiface 128 v1")
DEFINE_DEVICE_TYPE(SPECTRUM_MFACE128, spectrum_mface128_device, "spectrum_mface128", "Multiface 128")
DEFINE_DEVICE_TYPE(SPECTRUM_MFACE3, spectrum_mface3_device, "spectrum_mface3", "Multiface 3")
DEFINE_DEVICE_TYPE(SPECTRUM_MPRINT, spectrum_mprint_device, "spectrum_mprint", "MultiPrint")
@ -100,17 +142,17 @@ DEFINE_DEVICE_TYPE(SPECTRUM_MPRINT, spectrum_mprint_device, "spectrum_mprint", "
INPUT_PORTS_START( mface )
PORT_START("BUTTON")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Red Button") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHANGED_MEMBER(DEVICE_SELF, spectrum_mface_base_device, magic_button, 0)
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Red Button") PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, spectrum_mface_base_device, magic_button, 0)
INPUT_PORTS_END
INPUT_PORTS_START( mface1 )
INPUT_PORTS_START( mface1v2 )
PORT_INCLUDE( mface )
PORT_START("CONFIG")
PORT_CONFNAME(0x01, 0x00, "Joystick Enable Jumper")
PORT_CONFNAME(0x02, 0x00, "Joystick Enable Jumper")
PORT_CONFSETTING(0x00, "Closed")
PORT_CONFSETTING(0x01, "Open")
PORT_BIT(0xfe, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_CONFSETTING(0x02, "Open")
PORT_BIT(0xfd, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_START("JOY")
PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT) PORT_8WAY
@ -120,6 +162,16 @@ INPUT_PORTS_START( mface1 )
PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_BUTTON1)
INPUT_PORTS_END
INPUT_PORTS_START( mface1 )
PORT_INCLUDE( mface1v2 )
PORT_MODIFY("CONFIG")
PORT_CONFNAME(0x01, 0x00, "Interface Enable Switch")
PORT_CONFSETTING(0x00, "Enabled")
PORT_CONFSETTING(0x01, "Disabled")
PORT_BIT(0xfc, IP_ACTIVE_LOW, IPT_UNUSED)
INPUT_PORTS_END
//-------------------------------------------------
// input_ports - device-specific input ports
//-------------------------------------------------
@ -129,6 +181,11 @@ ioport_constructor spectrum_mface_base_device::device_input_ports() const
return INPUT_PORTS_NAME(mface);
}
ioport_constructor spectrum_mface1v2_device::device_input_ports() const
{
return INPUT_PORTS_NAME(mface1v2);
}
ioport_constructor spectrum_mface1_device::device_input_ports() const
{
return INPUT_PORTS_NAME(mface1);
@ -138,57 +195,75 @@ ioport_constructor spectrum_mface1_device::device_input_ports() const
// ROM( mface )
//-------------------------------------------------
ROM_START(mface1)
ROM_START(mface1v1) // pcb rev 1.2
ROM_REGION(0x2000, "rom", 0)
ROM_DEFAULT_BIOS("mu21e7")
ROM_SYSTEM_BIOS(0, "mu12cb", "MU12 CB") // Very early version, 2KB RAM, page out port 0x5F
ROM_DEFAULT_BIOS("mu12cb")
ROM_SYSTEM_BIOS(0, "mu12cb", "MU12 CB") // 2KB RAM, no pokes or toolkit, page out port 0x5f
ROMX_LOAD("mf1_12_cb.rom", 0x0000, 0x2000, CRC(c88fbf9f) SHA1(c3018d1b495b8bc0a135038db0987de7091c9d4c), ROM_BIOS(0))
ROM_SYSTEM_BIOS(1, "mu2023", "MU 2.0 23") // pokes only (no toolkit), page out port 0x5F
ROMX_LOAD("mf1_20_23.rom", 0x0000, 0x2000, CRC(d4ae8953) SHA1(b442eb634a72fb63f1ccbbd0021a7a581152888d), ROM_BIOS(1))
ROM_SYSTEM_BIOS(2, "mu20fe", "MU 2.0 FE") // pokes only (no toolkit)
ROMX_LOAD("mf1_20_fe.rom", 0x0000, 0x2000, CRC(fa1b8b0d) SHA1(20cd508b0143166558a7238c7a9ccfbe37b90b0d), ROM_BIOS(2))
ROM_SYSTEM_BIOS(3, "mu2167", "MU 2.1 67") // Kempston Disc support, no Beta support
ROMX_LOAD("mf1_21_67.rom", 0x0000, 0x2000, CRC(d720ec1b) SHA1(91a40d8f503ef825df3e2ed712897dbf4ca3671d), ROM_BIOS(3))
ROM_SYSTEM_BIOS(4, "mu21e4", "MU 2.1 E4") // the most common version
ROMX_LOAD("mf1_21_e4.rom", 0x0000, 0x2000, CRC(4b31a971) SHA1(ba28754a3cc31a4ca579829ed4310c313409cf5d), ROM_BIOS(4))
ROM_SYSTEM_BIOS(5, "mu21e7", "MU 2.1 E7") // last known version?
ROMX_LOAD("mf1_21_e7.rom", 0x0000, 0x2000, CRC(670f0ec2) SHA1(50fba2d628f3a2e9219f72980e4efd62fc9ec1f8), ROM_BIOS(5))
ROM_SYSTEM_BIOS(6, "bc96", "Brazilian clone 96") // Brazilian clone, unknown pcb version
ROMX_LOAD("mf1_bc_96.rom", 0x0000, 0x2000, CRC(e6fe4507) SHA1(a7e03e7fee3aa05ce1501072aab4534ea7bae257), ROM_BIOS(6))
ROM_END
/* Todo ...
ROM_SYSTEM_BIOS(?, "mu2090", "MU 2.0, 90") // pokes only or full toolkit? NO DUMP?
ROMX_LOAD("mf1_20_90.rom", 0x0000, 0x2000, CRC(2eaf8e41) SHA1(?), ROM_BIOS(?))
ROM_SYSTEM_BIOS(?, "bc93", "Brazilian clone 93") // NO DUMP?
ROMX_LOAD("mf1_bc_93.rom", 0x0000, 0x2000, CRC(8c17113b) SHA1(?), ROM_BIOS(?))
*/
ROM_START(mface128)
ROM_START(mface1v2) // unknown pcb rev (probably <2.0)
ROM_REGION(0x2000, "rom", 0)
ROM_DEFAULT_BIOS("v363c")
ROM_DEFAULT_BIOS("muxx23")
ROM_SYSTEM_BIOS(0, "muxx23", "MU x.x 23") // 8KB RAM, pokes only (no toolkit), page out port 0x5f
ROMX_LOAD("mf1_xx_23.rom", 0x0000, 0x2000, CRC(d4ae8953) SHA1(b442eb634a72fb63f1ccbbd0021a7a581152888d), ROM_BIOS(0))
ROM_END
ROM_START(mface1v3) // pcb rev 2.0
ROM_REGION(0x2000, "rom", 0)
ROM_DEFAULT_BIOS("mu20fe")
ROM_SYSTEM_BIOS(0, "mu20fe", "MU 2.0 FE") // pokes only (no toolkit)
ROMX_LOAD("mf1_20_fe.rom", 0x0000, 0x2000, CRC(fa1b8b0d) SHA1(20cd508b0143166558a7238c7a9ccfbe37b90b0d), ROM_BIOS(0))
// ROM_SYSTEM_BIOS(1, "mu2090", "MU 2.0, 90") // alt, unknown if earlier or later, no dump
// ROMX_LOAD("mf1_20_90.rom", 0x0000, 0x2000, CRC(2eaf8e41) SHA1(?), ROM_BIOS(1))
ROM_END
ROM_START(mface1) // pcb rev 2.1
ROM_REGION(0x2000, "rom", 0)
ROM_DEFAULT_BIOS("mu21e4")
ROM_SYSTEM_BIOS(0, "mu21e4", "MU 2.1 E4") // most common version
ROMX_LOAD("mf1_21_e4.rom", 0x0000, 0x2000, CRC(4b31a971) SHA1(ba28754a3cc31a4ca579829ed4310c313409cf5d), ROM_BIOS(0))
ROM_SYSTEM_BIOS(1, "mu21e7", "MU 2.1 E7") // alt, unknown if earlier or later, glitchy with Betaplus
ROMX_LOAD("mf1_21_e7.rom", 0x0000, 0x2000, CRC(670f0ec2) SHA1(50fba2d628f3a2e9219f72980e4efd62fc9ec1f8), ROM_BIOS(1))
ROM_SYSTEM_BIOS(2, "mu2167", "MU 2.1 67") // Kempston Disc support, no Beta support
ROMX_LOAD("mf1_21_67.rom", 0x0000, 0x2000, CRC(d720ec1b) SHA1(91a40d8f503ef825df3e2ed712897dbf4ca3671d), ROM_BIOS(2))
ROM_SYSTEM_BIOS(3, "bc96", "Brazilian clone 96") // Brazilian clone, unknown pcb version
ROMX_LOAD("mf1_bc_96.rom", 0x0000, 0x2000, CRC(e6fe4507) SHA1(a7e03e7fee3aa05ce1501072aab4534ea7bae257), ROM_BIOS(3))
// ROM_SYSTEM_BIOS(4, "bc93", "Brazilian clone 93") // another Brazilian clone, unknown pcb version, no dump
// ROMX_LOAD("mf1_bc_93.rom", 0x0000, 0x2000, CRC(8c17113b) SHA1(?), ROM_BIOS(4))
ROM_END
ROM_START(mface128v1)
ROM_REGION(0x2000, "rom", 0)
ROM_DEFAULT_BIOS("v350f")
ROM_SYSTEM_BIOS(0, "v340d", "87.1 V34 0D")
ROMX_LOAD("mf128_34_0d.rom", 0x0000, 0x2000, CRC(8d8cfd39) SHA1(2104962bb6097e58fcab63969bbaca424a872bb5), ROM_BIOS(0))
ROM_SYSTEM_BIOS(1, "v350d", "87.12 V35 0F")
ROM_SYSTEM_BIOS(1, "v350f", "87.12 V35 0F")
ROMX_LOAD("mf128_35_0f.rom", 0x0000, 0x2000, CRC(cfefd560) SHA1(6cd6fd2c0fbb40a989a568db9d08ba8eed49cbbd), ROM_BIOS(1))
ROM_SYSTEM_BIOS(2, "vxx0f", "87.2 Vxx 1D") // unknown PCB version
ROMX_LOAD("mf128_xx_1d.rom", 0x0000, 0x2000, CRC(f473991e) SHA1(f03f4ecbcf4a654f4775d16bda0d4cc47f884379), ROM_BIOS(2))
ROM_SYSTEM_BIOS(3, "v363c", "87.2 V36 3C")
ROMX_LOAD("mf128_36_3c.rom", 0x0000, 0x2000, CRC(78ec8cfd) SHA1(8df204ab490b87c389971ce0c7fb5f9cbd281f14), ROM_BIOS(3))
ROM_END
ROM_START(mface128) // DISCiPLE/+D compatible version
ROM_REGION(0x2000, "rom", 0)
ROM_DEFAULT_BIOS("v363c")
ROM_SYSTEM_BIOS(0, "vxx1d", "87.2 Vxx 1D") // unknown PCB version
ROMX_LOAD("mf128_xx_1d.rom", 0x0000, 0x2000, CRC(f473991e) SHA1(f03f4ecbcf4a654f4775d16bda0d4cc47f884379), ROM_BIOS(0))
ROM_SYSTEM_BIOS(1, "v363c", "87.2 V36 3C")
ROMX_LOAD("mf128_36_3c.rom", 0x0000, 0x2000, CRC(78ec8cfd) SHA1(8df204ab490b87c389971ce0c7fb5f9cbd281f14), ROM_BIOS(1))
ROM_END
ROM_START(mface3)
ROM_REGION(0x2000, "rom", 0)
ROM_DEFAULT_BIOS("v50fe")
ROM_SYSTEM_BIOS(0, "v5013", "V50 13")
ROMX_LOAD("mf3_50_13.rom", 0x0000, 0x2000, CRC(2d594640) SHA1(5d74d2e2e5a537639da92ff120f8a6d86f474495), ROM_BIOS(0))
ROM_SYSTEM_BIOS(1, "v50fe", "V50 FE")
ROMX_LOAD("mf3_50_fe.rom", 0x0000, 0x2000, CRC(b5c00f28) SHA1(983699a07665186f498f5827f9b35c442c2178ba), ROM_BIOS(1))
ROM_SYSTEM_BIOS(2, "vxx9a", "Hard Micro Multiface 3 clone Vxx 9a")
ROM_DEFAULT_BIOS("v5013")
ROM_SYSTEM_BIOS(0, "v50fe", "3.9 V50 FE") // doesn't have "lock 48K" option in save menu
ROMX_LOAD("mf3_50_fe.rom", 0x0000, 0x2000, CRC(b5c00f28) SHA1(983699a07665186f498f5827f9b35c442c2178ba), ROM_BIOS(0))
ROM_SYSTEM_BIOS(1, "v5013", "3.c V50 13")
ROMX_LOAD("mf3_50_13.rom", 0x0000, 0x2000, CRC(2d594640) SHA1(5d74d2e2e5a537639da92ff120f8a6d86f474495), ROM_BIOS(1))
ROM_SYSTEM_BIOS(2, "vxx9a", "Hard Micro Multiface 3 clone Vxx 9A")
ROMX_LOAD("mf3_hm_9a.rom", 0x0000, 0x2000, CRC(2ce53095) SHA1(5fa286f1552f26575a14ab32125d59c26ce95978), ROM_BIOS(2))
ROM_IGNORE(0x2000) // ROM is 16K, but contains two identical 8K halves
ROM_REGION( 0x200, "plds", 0 ) // pal from Hard Micro clone, probably the same for all
ROM_LOAD( "mf3_pal16l8a.icx", 0x000, 0x104, CRC(710186a1) SHA1(6573c2b8f55f66ef71ce3992f654080141e09739) )
ROM_END
ROM_START(mprint)
@ -210,6 +285,39 @@ void spectrum_mface_base_device::device_add_mconfig(machine_config &config)
SPECTRUM_EXPANSION_SLOT(config, m_exp, spectrum_expansion_devices, nullptr);
m_exp->irq_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::irq_w));
m_exp->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::nmi_w));
m_exp->fb_r_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::fb_r));
}
void spectrum_mface3_device::device_add_mconfig(machine_config &config)
{
spectrum_mface_base_device::device_add_mconfig(config);
/* passthru (+3 compatible devices only) */
SPECTRUM_EXPANSION_SLOT(config.replace(), m_exp, specpls3_expansion_devices, nullptr);
}
void spectrum_mprint_device::device_add_mconfig(machine_config &config)
{
spectrum_mface_base_device::device_add_mconfig(config);
/* printer port */
CENTRONICS(config, m_centronics, centronics_devices, "printer");
m_centronics->busy_handler().set(FUNC(spectrum_mprint_device::busy_w));
}
const tiny_rom_entry *spectrum_mface1v1_device::device_rom_region() const
{
return ROM_NAME(mface1v1);
}
const tiny_rom_entry *spectrum_mface1v2_device::device_rom_region() const
{
return ROM_NAME(mface1v2);
}
const tiny_rom_entry *spectrum_mface1v3_device::device_rom_region() const
{
return ROM_NAME(mface1v3);
}
const tiny_rom_entry *spectrum_mface1_device::device_rom_region() const
@ -217,6 +325,11 @@ const tiny_rom_entry *spectrum_mface1_device::device_rom_region() const
return ROM_NAME(mface1);
}
const tiny_rom_entry *spectrum_mface128v1_device::device_rom_region() const
{
return ROM_NAME(mface128v1);
}
const tiny_rom_entry *spectrum_mface128_device::device_rom_region() const
{
return ROM_NAME(mface128);
@ -249,25 +362,66 @@ spectrum_mface_base_device::spectrum_mface_base_device(const machine_config &mco
{
}
spectrum_mface1_device::spectrum_mface1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: spectrum_mface_base_device(mconfig, SPECTRUM_MFACE1, tag, owner, clock)
spectrum_mface1v2_device::spectrum_mface1v2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: spectrum_mface_base_device(mconfig, type, tag, owner, clock)
, m_joy(*this, "JOY")
, m_hwconfig(*this, "CONFIG")
{
}
spectrum_mface1v2_device::spectrum_mface1v2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: spectrum_mface1v2_device(mconfig, SPECTRUM_MFACE1V2, tag, owner, clock)
{
}
spectrum_mface1v1_device::spectrum_mface1v1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: spectrum_mface1v2_device(mconfig, SPECTRUM_MFACE1V1, tag, owner, clock)
{
}
spectrum_mface1v3_device::spectrum_mface1v3_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: spectrum_mface1v2_device(mconfig, type, tag, owner, clock)
{
}
spectrum_mface1v3_device::spectrum_mface1v3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: spectrum_mface1v3_device(mconfig, SPECTRUM_MFACE1V3, tag, owner, clock)
{
}
spectrum_mface1_device::spectrum_mface1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: spectrum_mface1v3_device(mconfig, SPECTRUM_MFACE1, tag, owner, clock)
{
}
spectrum_mface128_base_device::spectrum_mface128_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: spectrum_mface_base_device(mconfig, type, tag, owner, clock)
{
}
spectrum_mface128v1_device::spectrum_mface128v1_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: spectrum_mface128_base_device(mconfig, type, tag, owner, clock)
{
}
spectrum_mface128v1_device::spectrum_mface128v1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: spectrum_mface128v1_device(mconfig, SPECTRUM_MFACE128V1, tag, owner, clock)
{
}
spectrum_mface128_device::spectrum_mface128_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: spectrum_mface_base_device(mconfig, SPECTRUM_MFACE128, tag, owner, clock)
: spectrum_mface128v1_device(mconfig, SPECTRUM_MFACE128, tag, owner, clock)
{
}
spectrum_mface3_device::spectrum_mface3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: spectrum_mface_base_device(mconfig, SPECTRUM_MFACE3, tag, owner, clock)
: spectrum_mface128_base_device(mconfig, SPECTRUM_MFACE3, tag, owner, clock)
{
}
spectrum_mprint_device::spectrum_mprint_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: spectrum_mface_base_device(mconfig, SPECTRUM_MPRINT, tag, owner, clock)
: spectrum_mface128_base_device(mconfig, SPECTRUM_MPRINT, tag, owner, clock)
, m_centronics(*this, "centronics")
{
}
@ -278,6 +432,48 @@ spectrum_mprint_device::spectrum_mprint_device(const machine_config &mconfig, co
void spectrum_mface_base_device::device_start()
{
save_item(NAME(m_romcs));
save_item(NAME(m_nmi_pending));
}
void spectrum_mface1v2_device::device_start()
{
m_ram = std::make_unique<uint8_t[]>(8 * 1024);
save_pointer(NAME(m_ram), 8 * 1024);
spectrum_mface_base_device::device_start();
}
void spectrum_mface1v1_device::device_start()
{
m_ram = std::make_unique<uint8_t[]>(2 * 1024);
save_pointer(NAME(m_ram), 2 * 1024);
spectrum_mface_base_device::device_start();
}
void spectrum_mface128_base_device::device_start()
{
m_ram = std::make_unique<uint8_t[]>(8 * 1024);
save_pointer(NAME(m_ram), 8 * 1024);
save_item(NAME(m_hidden));
spectrum_mface_base_device::device_start();
}
void spectrum_mface128v1_device::device_start()
{
spectrum_mface128_base_device::device_start();
save_item(NAME(m_d3_ff));
}
void spectrum_mface3_device::device_start()
{
spectrum_mface128_base_device::device_start();
save_item(NAME(m_disable));
}
void spectrum_mprint_device::device_start()
{
spectrum_mface128_base_device::device_start();
m_busy = 0;
save_item(NAME(m_busy));
}
//-------------------------------------------------
@ -287,6 +483,25 @@ void spectrum_mface_base_device::device_start()
void spectrum_mface_base_device::device_reset()
{
m_romcs = 0;
m_nmi_pending = 0;
}
void spectrum_mface128_base_device::device_reset()
{
spectrum_mface_base_device::device_reset();
m_hidden = 1;
}
void spectrum_mface3_device::device_reset()
{
spectrum_mface128_base_device::device_reset();
m_disable = 0;
}
void spectrum_mprint_device::device_reset()
{
spectrum_mface128_base_device::device_reset();
m_centronics->write_strobe(1);
}
@ -305,25 +520,100 @@ void spectrum_mface_base_device::pre_opcode_fetch(offs_t offset)
if (!machine().side_effects_disabled())
{
if (offset == 0x0066)
if (offset == 0x0066 && m_nmi_pending)
m_romcs = 1;
}
}
void spectrum_mface128_device::pre_opcode_fetch(offs_t offset)
{
// pass-thru pin a15 is controlled by some extra logic on v2 pcb
m_exp->pre_opcode_fetch((m_nmi_pending || m_romcs) ? offset | 0x8000 : offset);
if (!machine().side_effects_disabled())
{
if (offset == 0x0066 && m_nmi_pending)
m_romcs = 1;
}
}
void spectrum_mprint_device::pre_opcode_fetch(offs_t offset)
{
m_exp->pre_opcode_fetch(offset);
if (!machine().side_effects_disabled())
{
if (offset == 0x0066 && m_nmi_pending)
m_romcs = 1;
// todo: must be some other hooks here...
// at least LPRINT, LLIST and COPY should be caught
// also unique REM xx commands
// menu should pop up for LPRINT and REM MP
}
}
uint8_t spectrum_mface1v2_device::iorq_r(offs_t offset)
{
uint8_t data = m_exp->iorq_r(offset);
if (!machine().side_effects_disabled())
{
switch (offset & 0xff) // real decodes tbc...
{
case 0x1f:
if (!(m_hwconfig->read() & 0x02))
data = m_joy->read() & 0x1f;
break;
case 0x5f:
m_romcs = 0;
break;
case 0x9f:
m_romcs = 1;
break;
}
}
return data;
}
uint8_t spectrum_mface1v3_device::iorq_r(offs_t offset)
{
uint8_t data = m_exp->iorq_r(offset);
if (!machine().side_effects_disabled())
{
switch (offset & 0xff) // real decodes tbc...
{
case 0x1f:
m_romcs = 0;
if (!(m_hwconfig->read() & 0x02))
data = m_joy->read() & 0x1f;
break;
case 0x9f:
m_romcs = 1;
break;
}
}
return data;
}
uint8_t spectrum_mface1_device::iorq_r(offs_t offset)
{
uint8_t data = m_exp->iorq_r(offset);
if (m_hwconfig->read() & 0x01) // disable switch
return data;
if (!machine().side_effects_disabled())
{
switch (offset & 0xff)
switch (offset & 0xf2) // -001 --1-
{
case 0x1f:
case 0x12: // 0001 --1- uses 0x1f
m_romcs = 0;
if (!(m_hwconfig->read() & 0x01)) // joystick disable jumper
if (!(m_hwconfig->read() & 0x02))
data = m_joy->read() & 0x1f;
break;
case 0x9f:
case 0x92: // 1001 --1- uses 0x9f
m_romcs = 1;
break;
}
@ -331,20 +621,47 @@ uint8_t spectrum_mface1_device::iorq_r(offs_t offset)
return data;
}
uint8_t spectrum_mface128v1_device::iorq_r(offs_t offset)
{
uint8_t data = m_exp->iorq_r(offset);
if (!machine().side_effects_disabled())
{
switch (offset & 0xf0) // -001 ----
{
case 0x10: // 0001 ---- uses 0x1f
m_romcs = 0;
break;
case 0x90: // 1001 ---- uses 0x9f
if (!m_hidden)
{
m_romcs = 1;
data = (data & 0x7f) | (m_d3_ff << 7);
}
break;
}
}
return data;
}
uint8_t spectrum_mface128_device::iorq_r(offs_t offset)
{
uint8_t data = m_exp->iorq_r(offset);
if (!machine().side_effects_disabled())
{
switch (offset & 0xff)
switch (offset & 0xf4) // -011 -1--
{
case 0xbf:
m_romcs = 1;
break;
case 0x3f:
case 0x34: // 0011 -1-- uses 0x3f
m_romcs = 0;
break;
case 0xb4: // 1011 -1-- uses 0xbf
if (!m_hidden)
{
m_romcs = 1;
data = (data & 0x7f) | (m_d3_ff << 7);
}
break;
}
}
return data;
@ -356,16 +673,26 @@ uint8_t spectrum_mface3_device::iorq_r(offs_t offset)
if (!machine().side_effects_disabled())
{
switch (offset & 0xff)
switch (offset & 0xff) // fully decoded by PAL16L8
{
case 0x3f:
m_romcs = 1;
if (!m_hidden)
m_romcs = 1;
break;
case 0xbf:
m_romcs = 0;
break;
}
}
// mface3 monitors writes to the +3 memory ctrl registers (ports 1ffd, 7ffd)
// keeps copies of the low nibbles in a 74LS670 4x4 register file
if ((offset & 0x7f) == 0x3f && !m_hidden)
{
data = 0xf0; // get stored copy of 1ffd, 7ffd
data |= m_reg_file[(offset >> 13) & 3] & 0xf;
}
return data;
}
@ -375,25 +702,141 @@ uint8_t spectrum_mprint_device::iorq_r(offs_t offset)
if (!machine().side_effects_disabled())
{
switch (offset & 0xff)
switch (offset & 0xff) // real decodes tbc...
{
case 0xbb:
m_romcs = 1;
break;
case 0xbf:
m_romcs = 0;
break;
case 0xbb:
if (!m_hidden)
m_romcs = 1;
data &= ~0x40;
data |= m_busy << 6;
break;
}
}
return data;
}
void spectrum_mface1v2_device::iorq_w(offs_t offset, uint8_t data)
{
if ((offset & 0xff) == 0x5f) // real decodes tbc...
nmi(CLEAR_LINE);
m_exp->iorq_w(offset, data);
}
void spectrum_mface1v3_device::iorq_w(offs_t offset, uint8_t data)
{
if ((offset & 0xff) == 0x1f) // real decodes tbc...
nmi(CLEAR_LINE);
m_exp->iorq_w(offset, data);
}
void spectrum_mface1_device::iorq_w(offs_t offset, uint8_t data)
{
switch (offset & 0xff)
if ((offset & 0xf2) == 0x12) // 0001 --1- uses 0x1f
nmi(CLEAR_LINE);
m_exp->iorq_w(offset, data);
}
void spectrum_mface128v1_device::iorq_w(offs_t offset, uint8_t data)
{
switch (offset & 0xf0) // -001 ----
{
case 0x1f:
m_slot->nmi_w(CLEAR_LINE);
case 0x10: // 0001 ---- uses 0x1f
m_hidden = 1;
[[fallthrough]];
case 0x90: // 1001 ---- uses 0x9f
nmi(CLEAR_LINE);
break;
}
// mface128 monitors writes to the 128K memory ctrl register (port 7ffd)
// keeps a copy of D3 (screen select bit) in a D flip-flop
if ((offset & 0x8002) == 0) // 0--- ---- ---- --0- uses 7ffd
m_d3_ff = (data >> 3) & 1;
m_exp->iorq_w(offset, data);
}
void spectrum_mface128_device::iorq_w(offs_t offset, uint8_t data)
{
switch (offset & 0xf4) // -011 -1--
{
case 0x34: // 0011 -1-- uses 0x3f
m_hidden = 1;
[[fallthrough]];
case 0xb4: // 1011 -1-- uses 0xbf
nmi(CLEAR_LINE);
break;
}
// mface128 monitors writes to the 128K memory ctrl register (port 7ffd)
// keeps a copy of D3 (screen select bit) in a D flip-flop
if ((offset & 0x8002) == 0) // 0--- ---- ---- --0- uses 7ffd
m_d3_ff = (data >> 3) & 1;
m_exp->iorq_w(offset, data);
}
void spectrum_mface3_device::iorq_w(offs_t offset, uint8_t data)
{
switch (offset & 0xff) // fully decoded by PAL16L8
{
case 0x3f:
m_hidden = 1; // also Hard Micro clone: D0 is 16KB rom msb (unused)
[[fallthrough]];
case 0xbf:
nmi(CLEAR_LINE);
break;
}
// mface3 monitors writes to the +3 memory ctrl registers (ports 1ffd, 7ffd)
// keeps copies of the low nibbles in a 74LS670 4x4 register file
if ((offset & 0x90fd) == 0x10fd)
m_reg_file[(offset >> 13) & 3] = data & 0x0f;
// also disables itself if special paging mode bit is set (CP/M)
if ((offset & 0xf0fd) == 0x10fd)
m_disable = data & 1;
m_exp->iorq_w(offset, data);
}
void spectrum_mprint_device::iorq_w(offs_t offset, uint8_t data)
{
// write_strobe is fired by wr seq: 0xbf, 0xbb, 0xbf
switch (offset & 0xff) // real decodes tbc...
{
case 0xbf:
m_centronics->write_data0(BIT(data, 0));
m_centronics->write_data1(BIT(data, 1));
m_centronics->write_data2(BIT(data, 2));
m_centronics->write_data3(BIT(data, 3));
m_centronics->write_data4(BIT(data, 4));
m_centronics->write_data5(BIT(data, 5));
m_centronics->write_data6(BIT(data, 6));
m_centronics->write_data7(BIT(data, 7));
m_centronics->write_strobe(1);
break;
case 0xbb:
m_centronics->write_strobe(0);
break;
}
switch (offset & 0x5ff)
{
case 0x4bf:
nmi(CLEAR_LINE);
break;
case 0x4fb: // not essential yet, for other hooks?
m_hidden = 0;
break;
case 0x5fb:
m_hidden = 1;
break;
}
@ -423,6 +866,29 @@ uint8_t spectrum_mface_base_device::mreq_r(offs_t offset)
return data;
}
uint8_t spectrum_mface1v1_device::mreq_r(offs_t offset)
{
uint8_t data = 0xff;
if (m_romcs)
{
switch (offset & 0xe000)
{
case 0x0000:
data = m_rom->base()[offset & 0x1fff];
break;
case 0x2000:
data = m_ram[offset & 0x7ff];
break;
}
}
if (m_exp->romcs())
data &= m_exp->mreq_r(offset);
return data;
}
void spectrum_mface_base_device::mreq_w(offs_t offset, uint8_t data)
{
if (m_romcs)
@ -439,26 +905,58 @@ void spectrum_mface_base_device::mreq_w(offs_t offset, uint8_t data)
m_exp->mreq_w(offset, data);
}
INPUT_CHANGED_MEMBER(spectrum_mface_base_device::magic_button)
void spectrum_mface1v1_device::mreq_w(offs_t offset, uint8_t data)
{
if (newval && !oldval)
if (m_romcs)
{
m_slot->nmi_w(ASSERT_LINE);
switch (offset & 0xe000)
{
case 0x2000:
m_ram[offset & 0x7ff] = data;
break;
}
}
else
if (m_exp->romcs())
m_exp->mreq_w(offset, data);
}
INPUT_CHANGED_MEMBER(spectrum_mface1v2_device::magic_button)
{
if (!newval)
{
m_slot->nmi_w(CLEAR_LINE);
nmi(ASSERT_LINE);
}
}
INPUT_CHANGED_MEMBER(spectrum_mface1_device::magic_button)
{
if (newval && !oldval) // key released
if (!newval)
{
}
else // key pressed
{
m_slot->nmi_w(ASSERT_LINE);
if (!(m_hwconfig->read() & 0x01))
{
nmi(ASSERT_LINE);
}
}
}
INPUT_CHANGED_MEMBER(spectrum_mface128_base_device::magic_button)
{
if (!newval)
{
m_hidden = 0;
nmi(ASSERT_LINE);
}
}
INPUT_CHANGED_MEMBER(spectrum_mface3_device::magic_button)
{
if (!newval)
{
if (!m_disable)
{
m_hidden = 0;
nmi(ASSERT_LINE);
}
}
}

View File

@ -9,7 +9,7 @@
#define MAME_BUS_SPECTRUM_MFACE_H
#include "exp.h"
#include "bus/centronics/ctronics.h"
//**************************************************************************
// TYPE DEFINITIONS
@ -18,13 +18,12 @@
class spectrum_mface_base_device :
public device_t,
public device_spectrum_expansion_interface
{
public:
// construction/destruction
spectrum_mface_base_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual DECLARE_INPUT_CHANGED_MEMBER(magic_button);
virtual DECLARE_INPUT_CHANGED_MEMBER(magic_button) { m_slot->nmi_w(newval ? CLEAR_LINE : ASSERT_LINE); };
protected:
spectrum_mface_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@ -49,14 +48,72 @@ protected:
virtual uint8_t iorq_r(offs_t offset) override { return m_exp->iorq_r(offset); }
virtual void iorq_w(offs_t offset, uint8_t data) override { m_exp->iorq_w(offset, data); }
void nmi(line_state state) { m_slot->nmi_w(state); m_nmi_pending = state; };
required_memory_region m_rom;
required_device<spectrum_expansion_slot_device> m_exp;
uint8_t m_ram[8 * 1024];
int m_romcs;
int m_nmi_pending;
std::unique_ptr<uint8_t[]> m_ram;
};
class spectrum_mface1_device : public spectrum_mface_base_device
class spectrum_mface1v2_device : public spectrum_mface_base_device
{
public:
spectrum_mface1v2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
DECLARE_INPUT_CHANGED_MEMBER(magic_button) override;
protected:
spectrum_mface1v2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
virtual void device_start() override;
// optional information overrides
virtual const tiny_rom_entry *device_rom_region() const override;
virtual ioport_constructor device_input_ports() const override;
virtual uint8_t iorq_r(offs_t offset) override;
virtual void iorq_w(offs_t offset, uint8_t data) override;
required_ioport m_joy;
required_ioport m_hwconfig;
};
class spectrum_mface1v1_device : public spectrum_mface1v2_device
{
public:
spectrum_mface1v1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
// device-level overrides
virtual void device_start() override;
// optional information overrides
virtual const tiny_rom_entry *device_rom_region() const override;
virtual uint8_t mreq_r(offs_t offset) override;
virtual void mreq_w(offs_t offset, uint8_t data) override;
};
class spectrum_mface1v3_device : public spectrum_mface1v2_device
{
public:
spectrum_mface1v3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
spectrum_mface1v3_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// optional information overrides
virtual const tiny_rom_entry *device_rom_region() const override;
virtual uint8_t iorq_r(offs_t offset) override;
virtual void iorq_w(offs_t offset, uint8_t data) override;
};
class spectrum_mface1_device : public spectrum_mface1v3_device
{
public:
spectrum_mface1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
@ -70,13 +127,46 @@ protected:
virtual uint8_t iorq_r(offs_t offset) override;
virtual void iorq_w(offs_t offset, uint8_t data) override;
private:
required_ioport m_joy;
required_ioport m_hwconfig;
};
class spectrum_mface128_device : public spectrum_mface_base_device
class spectrum_mface128_base_device : public spectrum_mface_base_device
{
public:
spectrum_mface128_base_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
DECLARE_INPUT_CHANGED_MEMBER(magic_button) override;
protected:
spectrum_mface128_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
int m_hidden;
};
class spectrum_mface128v1_device : public spectrum_mface128_base_device
{
public:
spectrum_mface128v1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
spectrum_mface128v1_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
virtual void device_start() override;
// optional information overrides
virtual const tiny_rom_entry *device_rom_region() const override;
virtual uint8_t iorq_r(offs_t offset) override;
virtual void iorq_w(offs_t offset, uint8_t data) override;
int m_d3_ff; // no initial state
};
class spectrum_mface128_device : public spectrum_mface128v1_device
{
public:
spectrum_mface128_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
@ -85,36 +175,68 @@ protected:
// optional information overrides
virtual const tiny_rom_entry *device_rom_region() const override;
virtual void pre_opcode_fetch(offs_t offset) override;
virtual uint8_t iorq_r(offs_t offset) override;
virtual void iorq_w(offs_t offset, uint8_t data) override;
};
class spectrum_mface3_device : public spectrum_mface_base_device
class spectrum_mface3_device : public spectrum_mface128_base_device
{
public:
spectrum_mface3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
DECLARE_INPUT_CHANGED_MEMBER(magic_button) override;
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
// optional information overrides
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
virtual uint8_t iorq_r(offs_t offset) override;
virtual void iorq_w(offs_t offset, uint8_t data) override;
private:
uint8_t m_reg_file[4]; // no initial state
int m_disable;
};
class spectrum_mprint_device : public spectrum_mface_base_device
class spectrum_mprint_device : public spectrum_mface128_base_device
{
public:
spectrum_mprint_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
// optional information overrides
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
virtual void pre_opcode_fetch(offs_t offset) override;
virtual uint8_t iorq_r(offs_t offset) override;
virtual void iorq_w(offs_t offset, uint8_t data) override;
private:
DECLARE_WRITE_LINE_MEMBER(busy_w) { m_busy = state; };
required_device<centronics_device> m_centronics;
int m_busy;
};
// device type definition
DECLARE_DEVICE_TYPE(SPECTRUM_MFACE1V1, spectrum_mface1v1_device)
DECLARE_DEVICE_TYPE(SPECTRUM_MFACE1V2, spectrum_mface1v2_device)
DECLARE_DEVICE_TYPE(SPECTRUM_MFACE1V3, spectrum_mface1v3_device)
DECLARE_DEVICE_TYPE(SPECTRUM_MFACE1, spectrum_mface1_device)
DECLARE_DEVICE_TYPE(SPECTRUM_MFACE128V1, spectrum_mface128v1_device)
DECLARE_DEVICE_TYPE(SPECTRUM_MFACE128, spectrum_mface128_device)
DECLARE_DEVICE_TYPE(SPECTRUM_MFACE3, spectrum_mface3_device)
DECLARE_DEVICE_TYPE(SPECTRUM_MPRINT, spectrum_mprint_device)

View File

@ -113,7 +113,7 @@
the PAL is a 16L6 rather than a 20L8 used in later version (only known dump is bruteforced and converted to gal20v8 target.)
details here: https://web.archive.org/web/20171118171054/http://trastero.speccy.org/cosas/JL/PlusD/PlusD-v1-0.html
from "pick-poke-it" user manual (reguarding v1.0 unit):
from "pick-poke-it" user manual (regarding v1.0 unit):
"A few PLUS D users are still using Version 1 of the ROM which was used in PLUS D's sold in December 1987-January 1988.
... check the serial number on the bottom of your PLUS D. If it's a 4-figure number commencing with 1,
then you have a PLUS D with the Version 1 ROM."
@ -170,7 +170,7 @@ DEFINE_DEVICE_TYPE(SPECTRUM_DISCIPLE, spectrum_disciple_device, "spectrum_discip
INPUT_PORTS_START(plusd)
PORT_START("BUTTON")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Snapshot Button") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHANGED_MEMBER(DEVICE_SELF, spectrum_plusd_device, snapshot_button, 0)
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Snapshot Button") PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, spectrum_plusd_device, snapshot_button, 0)
INPUT_PORTS_END
//-------------------------------------------------
@ -308,6 +308,7 @@ void spectrum_disciple_device::device_add_mconfig(machine_config &config)
SPECTRUM_EXPANSION_SLOT(config, m_exp, spectrum_expansion_devices, nullptr);
m_exp->irq_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::irq_w));
m_exp->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::nmi_w));
m_exp->fb_r_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::fb_r));
}
const tiny_rom_entry *spectrum_plusd_device::device_rom_region() const
@ -422,7 +423,7 @@ void spectrum_plusd_device::pre_opcode_fetch(offs_t offset)
uint8_t spectrum_plusd_device::iorq_r(offs_t offset)
{
uint8_t data = 0xff;
uint8_t data = offset & 1 ? m_slot->fb_r() : 0xff;
switch (offset & 0x7e) // address lines 0 and 7-15 ignored
{

View File

@ -91,7 +91,7 @@ void spectrum_mikroplus_device::device_start()
uint8_t spectrum_mikroplus_device::iorq_r(offs_t offset)
{
uint8_t data = 0xff;
uint8_t data = offset & 1 ? m_slot->fb_r() : 0xff;
if ((offset & 0xff) == 0xdf)
{

View File

@ -0,0 +1,168 @@
// license:BSD-3-Clause
// copyright-holders:TwistedTom
/*********************************************************************
MICRO-POKEer
(Micro-Studio, Hungary 1988-1989)
A back-up/snapshot type device similar to multiface.
Saves full ram or screen to tape (normal or high speed)
Cheat/poke and jump functions.
No pass-through slot.
Operation:
Press freeze button...
H: on-screen help
space: exit help
enter: return
r: total ram save
R: turbo total ram save
s: screen save
S: turbo screen save
l: turbo screen load
L: turbo total ram load
w: warm reset
m: micro-monitor (poke or jump)
micro-monitor:
black entry box appears...
move around with q/a/o/p, enter
input address (dec)
to jump: j, enter
to poke: p, input data (dec), enter (repeats)
to quit: q, enter
normal saves are useable independant of the interface,
"turbo" saves need the interface present, must use l or L options to load.
Lots of info including schematic and rom disassembly:
https://bitbandit.org/20141231/disassembling-the-micro-pokeer-rom-firmware/
*********************************************************************/
#include "emu.h"
#include "mpoker.h"
/***************************************************************************
DEVICE DEFINITIONS
***************************************************************************/
DEFINE_DEVICE_TYPE(SPECTRUM_MPOKER, spectrum_mpoker_device, "spectrum_mpoker", "MICRO-POKEer")
//-------------------------------------------------
// INPUT_PORTS( mpoker )
//-------------------------------------------------
INPUT_PORTS_START( mpoker )
PORT_START("BUTTON")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Freeze Button") PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, spectrum_mpoker_device, freeze_button, 0)
INPUT_PORTS_END
//-------------------------------------------------
// input_ports - device-specific input ports
//-------------------------------------------------
ioport_constructor spectrum_mpoker_device::device_input_ports() const
{
return INPUT_PORTS_NAME(mpoker);
}
//-------------------------------------------------
// ROM( mpoker )
//-------------------------------------------------
ROM_START(mpoker)
ROM_REGION(0x2000, "rom", 0) // v1.6
ROM_LOAD("mpoker.rom", 0x0000, 0x2000, CRC(11927434) SHA1(fd918519e4bd0eb8220d157a1c3f314669764657))
ROM_END
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
const tiny_rom_entry *spectrum_mpoker_device::device_rom_region() const
{
return ROM_NAME(mpoker);
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// spectrum_mpoker_device - constructor
//-------------------------------------------------
spectrum_mpoker_device::spectrum_mpoker_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, SPECTRUM_MPOKER, tag, owner, clock)
, device_spectrum_expansion_interface(mconfig, *this)
, m_rom(*this, "rom")
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void spectrum_mpoker_device::device_start()
{
save_item(NAME(m_romcs));
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void spectrum_mpoker_device::device_reset()
{
m_romcs = 0;
}
//**************************************************************************
// IMPLEMENTATION
//**************************************************************************
READ_LINE_MEMBER(spectrum_mpoker_device::romcs)
{
return m_romcs;
}
void spectrum_mpoker_device::iorq_w(offs_t offset, uint8_t data)
{
if ((offset & 0x80) == 0) // 0--- ---- uses 7f
{
m_romcs = BIT(data, 0);
}
}
uint8_t spectrum_mpoker_device::mreq_r(offs_t offset)
{
uint8_t data = 0xff;
if (m_romcs)
{
data = m_rom->base()[offset & 0x1fff];
}
return data;
}
INPUT_CHANGED_MEMBER(spectrum_mpoker_device::freeze_button)
{
if (newval)
{
m_slot->nmi_w(CLEAR_LINE);
}
else
{
m_romcs = 1;
m_slot->nmi_w(ASSERT_LINE);
}
}

View File

@ -0,0 +1,49 @@
// license:BSD-3-Clause
// copyright-holders:TwistedTom
/*********************************************************************
MICRO-POKEer
(Micro-Studio, Hungary 1988-1989)
*********************************************************************/
#ifndef MAME_BUS_SPECTRUM_MPOKER_H
#define MAME_BUS_SPECTRUM_MPOKER_H
#include "exp.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class spectrum_mpoker_device : public device_t, public device_spectrum_expansion_interface
{
public:
// construction/destruction
spectrum_mpoker_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
DECLARE_INPUT_CHANGED_MEMBER(freeze_button);
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
// optional information overrides
virtual const tiny_rom_entry *device_rom_region() const override;
virtual ioport_constructor device_input_ports() const override;
virtual uint8_t mreq_r(offs_t offset) override;
virtual void iorq_w(offs_t offset, uint8_t data) override;
virtual DECLARE_READ_LINE_MEMBER(romcs) override;
required_memory_region m_rom;
int m_romcs;
};
// device type definition
DECLARE_DEVICE_TYPE(SPECTRUM_MPOKER, spectrum_mpoker_device)
#endif // MAME_BUS_SPECTRUM_MPOKER_H

View File

@ -102,6 +102,7 @@ void spectrum_opus_device::device_add_mconfig(machine_config &config)
/* passthru without NMI */
SPECTRUM_EXPANSION_SLOT(config, m_exp, spectrum_expansion_devices, nullptr);
m_exp->irq_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::irq_w));
m_exp->fb_r_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::fb_r));
}
const tiny_rom_entry *spectrum_opus_device::device_rom_region() const
@ -188,7 +189,7 @@ uint8_t spectrum_opus_device::iorq_r(offs_t offset)
// PIA bit 7 is enable joystick and selected on A5 only
if (!BIT(m_pia->a_output(), 7) && (~offset & 0x20))
{
data &= m_joy->read() & 0x1f;
data = m_joy->read() & 0x1f;
}
return data;
}

View File

@ -74,7 +74,7 @@ void spectrum_protek_device::device_start()
uint8_t spectrum_protek_device::iorq_r(offs_t offset)
{
uint8_t data = 0xff;
uint8_t data = offset & 1 ? m_slot->fb_r() : 0xff;
switch (offset & 0xff)
{

View File

@ -127,7 +127,7 @@ uint8_t spectrum_sdi_device::mreq_r(offs_t offset)
uint8_t spectrum_sdi_device::iorq_r(offs_t offset)
{
uint8_t data = 0xff;
uint8_t data = offset & 1 ? m_slot->fb_r() : 0xff;
if ((offset & 0x9f) == 0x9f)
data = m_ppi->read((offset >> 5) & 3);

View File

@ -163,6 +163,7 @@ void spectrum_swiftdisc_device::device_add_mconfig(machine_config &config)
SPECTRUM_EXPANSION_SLOT(config, m_exp, spectrum_expansion_devices, nullptr);
m_exp->irq_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::irq_w));
m_exp->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::nmi_w));
m_exp->fb_r_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::fb_r));
}
void spectrum_swiftdisc2_device::device_add_mconfig(machine_config &config)
@ -376,7 +377,7 @@ uint8_t spectrum_swiftdisc_device::iorq_r(offs_t offset)
uint8_t data = m_exp->iorq_r(offset);
if (!BIT(offset, 5))
data &= m_joy->read();
data = m_joy->read() & 0x1f;
return data;
}
@ -484,10 +485,10 @@ uint8_t spectrum_swiftdisc2_device::iorq_r(offs_t offset)
uint8_t data = m_exp->iorq_r(offset);
if (m_romcs && (offset & 0xf890) == 0x3000)
data &= control_r();
data = control_r();
if (!BIT(offset, 5) && !BIT(m_control, 3))
data &= m_joy->read();
data = m_joy->read() & 0x1f;
if (m_conf->read())
{
@ -496,14 +497,14 @@ uint8_t spectrum_swiftdisc2_device::iorq_r(offs_t offset)
if (!BIT(offset, 3)) // port F7
{
// D7 - RS232 /RX
data &= ~(m_rs232->rxd_r() << 7);
data &= ~0x80;
data |= !m_rs232->rxd_r() << 7;
}
if (!BIT(offset, 4)) // port EF
{
data &= ~4;
data |= 0x0b;
// D3 - RS232 /DSR
data &= ~(m_rs232->dsr_r() << 3);
data &= ~0x8;
data |= !m_rs232->dsr_r() << 3;
}
}
}
@ -512,7 +513,8 @@ uint8_t spectrum_swiftdisc2_device::iorq_r(offs_t offset)
if (!BIT(offset, 3)) // port F7
{
// D7 - Centronics /BUSY
data &= ~(m_busy << 7);
data &= ~0x80;
data |= !m_busy << 7;
}
}

View File

@ -114,6 +114,7 @@ void spectrum_speccydos_device::device_add_mconfig(machine_config &config)
SPECTRUM_EXPANSION_SLOT(config, m_exp, spectrum_expansion_devices, nullptr);
m_exp->irq_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::irq_w));
m_exp->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::nmi_w));
m_exp->fb_r_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::fb_r));
}
const tiny_rom_entry *spectrum_speccydos_device::device_rom_region() const

View File

@ -0,0 +1,190 @@
// license:BSD-3-Clause
// copyright-holders:TwistedTom
/*********************************************************************
Spec-Mate back-up interface
(A, T & Y Computing Ltd.)
A back-up/snapshot type device similar to multiface.
No on-screen UI, feedback is given by border colour changes.
Supports saving to Beta-disk, Microdrive, Wafadrive, tape (normal & double-speed modes)
Only one rom is known, although magazine adverts stated:
"Opus users £2 extra, Opus & Sprint users contact us for details", suggesting other roms may exist.
(Sprint was a high-speed tape deck, x4 recording on a standard cassette)
Operation:
Press freeze button...
Black border mode: (select device)
t = save to tape
m = save to microdrive
d = save to Beta disk
w = save to wafadrive
f = save to tape, double-speed mode
0 = remove attributes *1
Red border mode: (save mode)
n = normal save
s = screenless save (game starts with blank screen!)
a = normal save with a 2nd screen (1st part of 2-part operation) *2
b = normal save with a 2nd screen (2nd part of 2-part operation) *2
Blue border mode: (select which part of vram is used as specmate working ram)
1 = use top 3rd of screen
2 = use middle 3rd of screen
3 = use bottom 3rd of screen
Magenta border mode: (enter filename)
Type a filename, press Enter to save
System should auto-unfreeze after successful save...
Notes:
*1 Removes colour from the frozen screen so that essential data "hidden" in vram can be seen (some games do this as a copy protection),
user can then avoid disturbing this data with choice made in blue-border mode.
*2 Saves a 2nd screen (eg. a nice loading screen) just for fun. 2-part operation, so load game, freeze, save 1st screen,
reset system, re-load game, freeze, save main game and 2nd screen.
* Saves are created with stand-alone loader code so are not dependant on the interface for reuse.
* Pokes can be added to the save loader: press BREAK as soon as the screen goes black, INK 9, POKE aaaaa,ddd
*********************************************************************/
#include "emu.h"
#include "specmate.h"
/***************************************************************************
DEVICE DEFINITIONS
***************************************************************************/
DEFINE_DEVICE_TYPE(SPECTRUM_SPECMATE, spectrum_specmate_device, "spectrum_specmate", "AT&Y Spec-Mate")
//-------------------------------------------------
// INPUT_PORTS( specmate )
//-------------------------------------------------
INPUT_PORTS_START( specmate )
PORT_START("BUTTON")
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Freeze Button") PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHANGED_MEMBER(DEVICE_SELF, spectrum_specmate_device, freeze_button, 0)
INPUT_PORTS_END
//-------------------------------------------------
// input_ports - device-specific input ports
//-------------------------------------------------
ioport_constructor spectrum_specmate_device::device_input_ports() const
{
return INPUT_PORTS_NAME(specmate);
}
//-------------------------------------------------
// ROM( specmate )
//-------------------------------------------------
ROM_START(specmate)
ROM_REGION(0x2000, "rom", 0) // unknown ver
ROM_LOAD("specmate.rom", 0x0000, 0x2000, CRC(8d74b19c) SHA1(c8f128610eeb5142d4d80f28e5dd07b7a5ab6b84))
ROM_END
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
void spectrum_specmate_device::device_add_mconfig(machine_config &config)
{
/* passthru */
SPECTRUM_EXPANSION_SLOT(config, m_exp, spectrum_expansion_devices, nullptr);
m_exp->irq_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::irq_w));
m_exp->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::nmi_w));
m_exp->fb_r_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::fb_r));
}
const tiny_rom_entry *spectrum_specmate_device::device_rom_region() const
{
return ROM_NAME(specmate);
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// spectrum_specmate_device - constructor
//-------------------------------------------------
spectrum_specmate_device::spectrum_specmate_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, SPECTRUM_SPECMATE, tag, owner, clock)
, device_spectrum_expansion_interface(mconfig, *this)
, m_rom(*this, "rom")
, m_exp(*this, "exp")
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void spectrum_specmate_device::device_start()
{
save_item(NAME(m_romcs));
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void spectrum_specmate_device::device_reset()
{
m_romcs = 0;
}
//**************************************************************************
// IMPLEMENTATION
//**************************************************************************
READ_LINE_MEMBER(spectrum_specmate_device::romcs)
{
return m_romcs | m_exp->romcs();
}
void spectrum_specmate_device::pre_opcode_fetch(offs_t offset)
{
m_exp->pre_opcode_fetch(offset);
if (!machine().side_effects_disabled())
{
switch (offset & 0xdfff) // a13 isn't used in the decoding
{
case 0x0066:
m_romcs = 1;
break;
case 0x0071:
m_romcs = 0;
break;
}
}
}
uint8_t spectrum_specmate_device::mreq_r(offs_t offset)
{
uint8_t data = 0xff;
if (m_romcs)
{
data = m_rom->base()[offset & 0x1fff];
}
if (m_exp->romcs())
data &= m_exp->mreq_r(offset);
return data;
}

View File

@ -0,0 +1,59 @@
// license:BSD-3-Clause
// copyright-holders:TwistedTom
/*********************************************************************
Spec-Mate back-up interface
(A, T & Y Computing Ltd.)
*********************************************************************/
#ifndef MAME_BUS_SPECTRUM_SPECMATE_H
#define MAME_BUS_SPECTRUM_SPECMATE_H
#include "exp.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class spectrum_specmate_device : public device_t, public device_spectrum_expansion_interface
{
public:
// construction/destruction
spectrum_specmate_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
DECLARE_INPUT_CHANGED_MEMBER(freeze_button) { m_slot->nmi_w(newval ? CLEAR_LINE : ASSERT_LINE); };
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
// optional information overrides
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
virtual ioport_constructor device_input_ports() const override;
virtual void pre_opcode_fetch(offs_t offset) override;
virtual uint8_t mreq_r(offs_t offset) override;
virtual DECLARE_READ_LINE_MEMBER(romcs) override;
// passthru
virtual void post_opcode_fetch(offs_t offset) override { m_exp->post_opcode_fetch(offset); };
virtual void pre_data_fetch(offs_t offset) override { m_exp->pre_data_fetch(offset); };
virtual void post_data_fetch(offs_t offset) override { m_exp->post_data_fetch(offset); };
virtual void mreq_w(offs_t offset, uint8_t data) override { if (m_exp->romcs()) m_exp->mreq_w(offset, data); }
virtual uint8_t iorq_r(offs_t offset) override { return m_exp->iorq_r(offset); }
virtual void iorq_w(offs_t offset, uint8_t data) override { m_exp->iorq_w(offset, data); }
required_memory_region m_rom;
required_device<spectrum_expansion_slot_device> m_exp;
int m_romcs;
};
// device type definition
DECLARE_DEVICE_TYPE(SPECTRUM_SPECMATE, spectrum_specmate_device)
#endif // MAME_BUS_SPECTRUM_SPECMATE_H

View File

@ -114,7 +114,7 @@ uint8_t spectrum_uspeech_device::iorq_r(offs_t offset)
m_romcs = !m_romcs;
}
return 0xff;
return offset & 1 ? m_slot->fb_r() : 0xff;
}
uint8_t spectrum_uspeech_device::mreq_r(offs_t offset)

View File

@ -53,6 +53,7 @@ void spectrum_wafa_device::device_add_mconfig(machine_config &config)
SPECTRUM_EXPANSION_SLOT(config, m_exp, spectrum_expansion_devices, nullptr);
m_exp->irq_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::irq_w));
m_exp->nmi_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::nmi_w));
m_exp->fb_r_handler().set(DEVICE_SELF_OWNER, FUNC(spectrum_expansion_slot_device::fb_r));
SOFTWARE_LIST(config, "wafadrive_list").set_original("spectrum_wafadrive");
}

View File

@ -131,7 +131,7 @@ void atm_state::atm_io(address_map &map)
map(0x003f, 0x003f).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::track_r), FUNC(beta_disk_device::track_w));
map(0x005f, 0x005f).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::sector_r), FUNC(beta_disk_device::sector_w));
map(0x007f, 0x007f).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::data_r), FUNC(beta_disk_device::data_w));
map(0x00fe, 0x00fe).select(0xff00).rw(FUNC(atm_state::spectrum_port_fe_r), FUNC(atm_state::spectrum_port_fe_w));
map(0x00fe, 0x00fe).select(0xff00).rw(FUNC(atm_state::spectrum_ula_r), FUNC(atm_state::spectrum_ula_w));
map(0x00ff, 0x00ff).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::state_r), FUNC(beta_disk_device::param_w));
map(0x4000, 0x4000).mirror(0x3ffd).w(FUNC(atm_state::atm_port_7ffd_w));
map(0x8000, 0x8000).mirror(0x3ffd).w("ay8912", FUNC(ay8910_device::data_w));

View File

@ -325,7 +325,7 @@ void elwro800_state::elwro800jr_io_w(offs_t offset, uint8_t data)
if (!BIT(cs,0))
{
// CFE
spectrum_port_fe_w(offset, data);
spectrum_ula_w(offset, data);
}
else if (!BIT(cs,1))
{

View File

@ -210,7 +210,7 @@ void pentagon_state::pentagon_io(address_map &map)
map(0x003f, 0x003f).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::track_r), FUNC(beta_disk_device::track_w));
map(0x005f, 0x005f).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::sector_r), FUNC(beta_disk_device::sector_w));
map(0x007f, 0x007f).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::data_r), FUNC(beta_disk_device::data_w));
map(0x00fe, 0x00fe).select(0xff00).rw(FUNC(pentagon_state::spectrum_port_fe_r), FUNC(pentagon_state::spectrum_port_fe_w));
map(0x00fe, 0x00fe).select(0xff00).rw(FUNC(pentagon_state::spectrum_ula_r), FUNC(pentagon_state::spectrum_ula_w));
map(0x00ff, 0x00ff).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::state_r), FUNC(beta_disk_device::param_w));
map(0x8000, 0x8000).mirror(0x3ffd).w("ay8912", FUNC(ay8910_device::data_w));
map(0xc000, 0xc000).mirror(0x3ffd).rw("ay8912", FUNC(ay8910_device::data_r), FUNC(ay8910_device::address_w));

View File

@ -197,7 +197,7 @@ void scorpion_state::scorpion_io(address_map &map)
map(0x003f, 0x003f).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::track_r), FUNC(beta_disk_device::track_w));
map(0x005f, 0x005f).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::sector_r), FUNC(beta_disk_device::sector_w));
map(0x007f, 0x007f).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::data_r), FUNC(beta_disk_device::data_w));
map(0x00fe, 0x00fe).select(0xff00).rw(FUNC(scorpion_state::spectrum_port_fe_r), FUNC(scorpion_state::spectrum_port_fe_w));
map(0x00fe, 0x00fe).select(0xff00).rw(FUNC(scorpion_state::spectrum_ula_r), FUNC(scorpion_state::spectrum_ula_w));
map(0x00ff, 0x00ff).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::state_r), FUNC(beta_disk_device::param_w));
map(0x4021, 0x4021).mirror(0x3fdc).w(FUNC(scorpion_state::scorpion_port_7ffd_w));
map(0x8021, 0x8021).mirror(0x3fdc).w("ay8912", FUNC(ay8910_device::data_w));

View File

@ -239,21 +239,35 @@ void spectrum_128_state::spectrum_128_update_memory()
m_screen_location = messram + (5<<14);
}
uint8_t spectrum_128_state::spectrum_128_ula_r()
uint8_t spectrum_128_state::spectrum_port_r(offs_t offset)
{
// Pass through to expansion device if present
if (m_exp->get_card_device())
return m_exp->iorq_r(offset | 1);
return floating_bus_r();
}
uint8_t spectrum_128_state::floating_bus_r()
{
// very basic "floating bus" implementation, see notes in spectrum.cpp
uint8_t data = 0xff;
int hpos = m_screen->hpos();
int vpos = m_screen->vpos();
return vpos<193 ? m_screen_location[0x1800|(vpos&0xf8)<<2]:0xff;
if ((hpos >= 48 && hpos < 304) && (vpos >= 48 && vpos < 240))
data = m_screen_location[0x1800 + (((vpos-48)/8)*32) + ((hpos-48)/8)];
return data;
}
void spectrum_128_state::spectrum_128_io(address_map &map)
{
map(0x0000, 0xffff).rw(m_exp, FUNC(spectrum_expansion_slot_device::iorq_r), FUNC(spectrum_expansion_slot_device::iorq_w));
map(0x0000, 0x0000).select(0xfffe).rw(FUNC(spectrum_128_state::spectrum_port_fe_r), FUNC(spectrum_128_state::spectrum_port_fe_w));
map(0x0000, 0x0000).select(0xfffe).rw(FUNC(spectrum_128_state::spectrum_ula_r), FUNC(spectrum_128_state::spectrum_ula_w));
map(0x0001, 0x0001).select(0xfffe).rw(FUNC(spectrum_128_state::spectrum_port_r), FUNC(spectrum_128_state::spectrum_port_w));
map(0x0001, 0x0001).select(0x7ffc).w(FUNC(spectrum_128_state::spectrum_128_port_7ffd_w)); // (A15 | A1) == 0, note: reading from this port does write to it by value from data bus
map(0x8000, 0x8000).mirror(0x3ffd).w("ay8912", FUNC(ay8910_device::data_w));
map(0xc000, 0xc000).mirror(0x3ffd).rw("ay8912", FUNC(ay8910_device::data_r), FUNC(ay8910_device::address_w));
map(0x0001, 0x0001).r(FUNC(spectrum_128_state::spectrum_128_ula_r)); // .mirror(0xfffe);
}
void spectrum_128_state::spectrum_128_mem(address_map &map)
@ -332,6 +346,7 @@ void spectrum_128_state::spectrum_128(machine_config &config)
SPECTRUM_EXPANSION_SLOT(config.replace(), m_exp, spec128_expansion_devices, nullptr);
m_exp->irq_handler().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
m_exp->nmi_handler().set_inputline(m_maincpu, INPUT_LINE_NMI);
m_exp->fb_r_handler().set(FUNC(spectrum_128_state::floating_bus_r));
/* internal ram */
m_ram->set_default_size("128K");
@ -375,24 +390,14 @@ ROM_START(specpls2)
ROMX_LOAD("pl2namco.rom",0x10000,0x8000, CRC(72a54e75) SHA1(311400157df689450dadc3620f4c4afa960b05ad), ROM_BIOS(4))
ROM_END
ROM_START(hc128)
ROM_START(hc128) // Romanian clone, "ICE Felix HC91+" (aka HC-128), AY-8910 was optional
ROM_REGION(0x18000,"maincpu",0)
ROM_LOAD("zx128_0.rom",0x10000,0x4000, CRC(e76799d2) SHA1(4f4b11ec22326280bdb96e3baf9db4b4cb1d02c5))
ROM_LOAD("hc128.rom", 0x14000,0x4000, CRC(0241e960) SHA1(cea0d14391b9e571460a816088a1c00ecb24afa3))
ROM_END
ROM_START(hc2000)
ROM_REGION(0x18000,"maincpu",0)
ROM_SYSTEM_BIOS( 0, "v1", "Version 1" )
ROMX_LOAD("zx128_0.rom",0x10000,0x4000, CRC(e76799d2) SHA1(4f4b11ec22326280bdb96e3baf9db4b4cb1d02c5), ROM_BIOS(0))
ROMX_LOAD("hc2000.v1", 0x14000,0x4000, CRC(453c1a5a) SHA1(f8139fc38478691cf44944dc83fd6e70b0f002fb), ROM_BIOS(0))
ROM_SYSTEM_BIOS( 1, "v2", "Version 2" )
ROMX_LOAD("zx128_0.rom",0x10000,0x4000, CRC(e76799d2) SHA1(4f4b11ec22326280bdb96e3baf9db4b4cb1d02c5), ROM_BIOS(1))
ROMX_LOAD("hc2000.v2", 0x14000,0x4000, CRC(65d90464) SHA1(5e2096e6460ff2120c8ada97579fdf82c1199c09), ROM_BIOS(1))
ROM_END
// YEAR NAME PARENT COMPAT MACHINE CLASS STATE INIT COMPANY FULLNAME FLAGS
// YEAR NAME PARENT COMPAT MACHINE INPUT STATE INIT COMPANY FULLNAME FLAGS
COMP( 1986, spec128, 0, 0, spectrum_128, spec128, spectrum_128_state, empty_init, "Sinclair Research Ltd", "ZX Spectrum 128", 0 )
COMP( 1986, specpls2, spec128, 0, spectrum_128, spec_plus, spectrum_128_state, empty_init, "Amstrad plc", "ZX Spectrum +2", 0 )
COMP( 1991, hc128, spec128, 0, spectrum_128, spec_plus, spectrum_128_state, empty_init, "ICE-Felix", "HC-128", 0 )
COMP( 1992, hc2000, spec128, 0, spectrum_128, spec_plus, spectrum_128_state, empty_init, "ICE-Felix", "HC-2000", MACHINE_NOT_WORKING )
COMP( 1991, hc128, spec128, 0, spectrum_128, spec_plus, spectrum_128_state, empty_init, "ICE-Felix", "HC-91+ (HC-128)", 0 )

View File

@ -173,10 +173,14 @@ static const int spectrum_plus3_memory_selections[]=
4,7,6,3
};
void specpls3_state::port_3ffd_w(uint8_t data)
void specpls3_state::port_3ffd_w(offs_t offset, uint8_t data)
{
if (m_upd765.found())
m_upd765->fifo_w(data);
/* mface3 needs to see this port */
if (m_exp)
m_exp->iorq_w(offset | 0x3000, data);
}
uint8_t specpls3_state::port_3ffd_r()
@ -291,14 +295,18 @@ uint8_t specpls3_state::bank1_r(offs_t offset)
return data;
}
void specpls3_state::port_7ffd_w(uint8_t data)
void specpls3_state::port_7ffd_w(offs_t offset, uint8_t data)
{
/* D0-D2: RAM page located at 0x0c000-0x0ffff */
/* D3 - Screen select (screen 0 in ram page 5, screen 1 in ram page 7 */
/* D4 - ROM select - which rom paged into 0x0000-0x03fff */
/* D5 - Disable paging */
/* D0-D2 - RAM page located at 0x0c000-0x0ffff */
/* D3 - Screen select (screen 0 in ram page 5, screen 1 in ram page 7 */
/* D4 - ROM select low bit - which rom paged into 0x0000-0x03fff */
/* D5 - Disable paging (permanent until reset) */
/* disable paging? */
/* mface3 needs to see this port */
if (m_exp)
m_exp->iorq_w(offset | 0x4000, data);
/* paging disabled? */
if (m_port_7ffd_data & 0x20)
return;
@ -309,12 +317,15 @@ void specpls3_state::port_7ffd_w(uint8_t data)
plus3_update_memory();
}
void specpls3_state::port_1ffd_w(uint8_t data)
void specpls3_state::port_1ffd_w(offs_t offset, uint8_t data)
{
/* D0-D1: ROM/RAM paging */
/* D2: Affects if d0-d1 work on ram/rom */
/* D3 - Disk motor on/off */
/* D4 - parallel port strobe */
/* D0=0 - Normal ROM/RAM paging mode */
/* D1 - Not used */
/* D2 - Rom select high bit */
/* D0=1 - Special RAM paging mode (all-RAM CP/M modes) */
/* D1-D2 - Special paging mode 0-3 */
/* D3 - Disk motor on/off */
/* D4 - Parallel port strobe */
if (m_upd765.found())
{
@ -323,14 +334,23 @@ void specpls3_state::port_1ffd_w(uint8_t data)
flop->get_device()->mon_w(!BIT(data, 3));
}
m_port_1ffd_data = data;
/* mface3 needs to see this port */
if (m_exp)
m_exp->iorq_w(offset | 0x1000, data);
/* disable paging? */
/* paging disabled? */
if ((m_port_7ffd_data & 0x20)==0)
{
/* no */
m_port_1ffd_data = data;
plus3_update_memory();
}
else
{
/* yes, update only non-memory related */
m_port_1ffd_data &= 0x7;
m_port_1ffd_data |= data & 0xf8;
}
}
/* ports are not decoded full.
@ -338,13 +358,13 @@ The function decodes the ports appropriately */
void specpls3_state::plus3_io(address_map &map)
{
map(0x0000, 0xffff).rw(m_exp, FUNC(spectrum_expansion_slot_device::iorq_r), FUNC(spectrum_expansion_slot_device::iorq_w));
map(0x0000, 0x0000).rw(FUNC(specpls3_state::spectrum_port_fe_r), FUNC(specpls3_state::spectrum_port_fe_w)).select(0xfffe);
map(0x4000, 0x4000).w(FUNC(specpls3_state::port_7ffd_w)).mirror(0x3ffd);
map(0x0000, 0x0000).rw(FUNC(specpls3_state::spectrum_ula_r), FUNC(specpls3_state::spectrum_ula_w)).select(0xfffe);
map(0x4000, 0x4000).w(FUNC(specpls3_state::port_7ffd_w)).select(0x3ffd);
map(0x8000, 0x8000).w("ay8912", FUNC(ay8910_device::data_w)).mirror(0x3ffd);
map(0xc000, 0xc000).rw("ay8912", FUNC(ay8910_device::data_r), FUNC(ay8910_device::address_w)).mirror(0x3ffd);
map(0x1000, 0x1000).w(FUNC(specpls3_state::port_1ffd_w)).mirror(0x0ffd);
map(0x1000, 0x1000).w(FUNC(specpls3_state::port_1ffd_w)).select(0x0ffd);
map(0x2000, 0x2000).r(FUNC(specpls3_state::port_2ffd_r)).mirror(0x0ffd);
map(0x3000, 0x3000).rw(FUNC(specpls3_state::port_3ffd_r), FUNC(specpls3_state::port_3ffd_w)).mirror(0x0ffd);
map(0x3000, 0x3000).rw(FUNC(specpls3_state::port_3ffd_r), FUNC(specpls3_state::port_3ffd_w)).select(0x0ffd);
}
void specpls3_state::plus3_mem(address_map &map)
@ -415,6 +435,8 @@ void specpls3_state::spectrum_plus2(machine_config &config)
SPECTRUM_EXPANSION_SLOT(config.replace(), m_exp, specpls3_expansion_devices, nullptr);
m_exp->irq_handler().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
m_exp->nmi_handler().set_inputline(m_maincpu, INPUT_LINE_NMI);
// these models don't have floating bus
m_exp->fb_r_handler().set([]() { return 0xff; });
}
void specpls3_state::spectrum_plus3(machine_config &config)
@ -435,34 +457,50 @@ void specpls3_state::spectrum_plus3(machine_config &config)
***************************************************************************/
/* Amstrad built +2A/+2B/+3/+3B models:
+2A/B has built-in tape "datacorder", +3/B has built-in 3" fdd
+2A/+3 use common z70830 pcb with v4.0 rom (fdc etc. unpopulated on +2A)
+2B/+3B use unique z70833/z70835 pcbs but use same v4.1 rom
Note, +2 (non-A/B, aka "grey case") although Amstrad built is essentially a re-cased Sinclair 128K, see spec128.cpp
*/
ROM_START(specpl2a)
ROM_REGION(0x20000,"maincpu",0)
ROM_LOAD("p2a41_0.rom",0x10000,0x4000, CRC(30c9f490) SHA1(62ec15a4af56cd1d206d0bd7011eac7c889a595d))
ROM_LOAD("p2a41_1.rom",0x14000,0x4000, CRC(a7916b3f) SHA1(1a7812c383a3701e90e88d1da086efb0c033ac72))
ROM_LOAD("p2a41_2.rom",0x18000,0x4000, CRC(c9a0b748) SHA1(8df145d10ff78f98138682ea15ebccb2874bf759))
ROM_LOAD("p2a41_3.rom",0x1c000,0x4000, CRC(b88fd6e3) SHA1(be365f331942ec7ec35456b641dac56a0dbfe1f0))
ROM_SYSTEM_BIOS( 0, "en", "English v4.0" ) // +2A
ROMX_LOAD("40092.ic7",0x10000,0x8000, CRC(9bc85686) SHA1(5992daf925f6e225fc0d01f7640282954d092ef4), ROM_BIOS(0))
ROMX_LOAD("40093.ic8",0x18000,0x8000, CRC(db551783) SHA1(a0432adcca03f849fb39b6dce6414740cf4aecd2), ROM_BIOS(0))
ROM_SYSTEM_BIOS( 1, "sp", "Spanish v4.0" )
ROMX_LOAD("40094.ic7",0x10000,0x8000, CRC(392242fb) SHA1(976ae88951f8d1beb5d107f048950118a7133823), ROM_BIOS(1))
ROMX_LOAD("40101.ic8",0x18000,0x8000, CRC(5daaae01) SHA1(09ca25b4dbec064a4964ab7a41d48404199afd77), ROM_BIOS(1))
ROM_SYSTEM_BIOS( 2, "enb", "English v4.1" ) // +2B
ROMX_LOAD("40092u.ic7",0x10000,0x8000, CRC(80808d82) SHA1(b9e88ec18f844ce42ecb7802d82c2bda65f9c4f2), ROM_BIOS(2))
ROMX_LOAD("40093u.ic8",0x18000,0x8000, CRC(61f2b50c) SHA1(d062765ceb1f3cd2c94ea51cb737cac7ad6151b4), ROM_BIOS(2))
ROM_SYSTEM_BIOS( 3, "spb", "Spanish v4.1" )
ROMX_LOAD("40094s.ic7",0x10000,0x8000, CRC(9d102acf) SHA1(c525bd23f79ca968d34a0efdcc47b2eb342007f5), ROM_BIOS(3))
ROMX_LOAD("40101s.ic8",0x18000,0x8000, CRC(1408ddce) SHA1(56eb124d44ee8c8daef130be4d7e735ec412c4ba), ROM_BIOS(3))
ROM_END
ROM_START(specpls3)
ROM_REGION(0x20000,"maincpu",0)
ROM_SYSTEM_BIOS( 0, "en", "English v4.0" )
ROMX_LOAD("pl3-0.rom",0x10000,0x4000, CRC(17373da2) SHA1(e319ed08b4d53a5e421a75ea00ea02039ba6555b), ROM_BIOS(0))
ROMX_LOAD("pl3-1.rom",0x14000,0x4000, CRC(f1d1d99e) SHA1(c9969fc36095a59787554026a9adc3b87678c794), ROM_BIOS(0))
ROMX_LOAD("pl3-2.rom",0x18000,0x4000, CRC(3dbf351d) SHA1(22e50c6ba4157a3f6a821bd9937cd26e292775c6), ROM_BIOS(0))
ROMX_LOAD("pl3-3.rom",0x1c000,0x4000, CRC(04448eaa) SHA1(65f031caa8148a5493afe42c41f4929deab26b4e), ROM_BIOS(0))
ROM_SYSTEM_BIOS( 1, "sp", "Spanish v.40" )
ROMX_LOAD("plus3sp0.rom",0x10000,0x4000, CRC(1f86147a) SHA1(e9b0a60a1a8def511d59090b945d175bdc646346), ROM_BIOS(1))
ROMX_LOAD("plus3sp1.rom",0x14000,0x4000, CRC(a8ac4966) SHA1(4e48f196427596c7990c175d135c15a039c274a4), ROM_BIOS(1))
ROMX_LOAD("plus3sp2.rom",0x18000,0x4000, CRC(f6bb0296) SHA1(09fc005625589ef5992515957ce7a3167dec24b2), ROM_BIOS(1))
ROMX_LOAD("plus3sp3.rom",0x1c000,0x4000, CRC(f6d25389) SHA1(ec8f644a81e2e9bcb58ace974103ea960361bad2), ROM_BIOS(1))
ROM_SYSTEM_BIOS( 2, "en41", "English v4.1" )
ROMX_LOAD("plus341.rom",0x10000,0x10000, CRC(be0d9ec4) SHA1(500c0945760abeefcbd08bc22c0d07b14b336cf0), ROM_BIOS(2))
ROM_SYSTEM_BIOS( 3, "4ms", "Customize 3.5\" 4ms" )
ROMX_LOAD("p3_01_4m.rom",0x10000,0x8000, CRC(ad99380a) SHA1(4e5d114b72d464cefdde0566457f52a3c0c1cae2), ROM_BIOS(3))
ROMX_LOAD("p3_23_4m.rom",0x18000,0x8000, CRC(07727895) SHA1(752cdd6a083ab9910348995e483541d60bb6372b), ROM_BIOS(3))
ROM_SYSTEM_BIOS( 4, "12ms", "Customize 3.5\" 12ms" )
ROMX_LOAD("p3_01_cm.rom",0x10000,0x8000, CRC(ad99380a) SHA1(4e5d114b72d464cefdde0566457f52a3c0c1cae2), ROM_BIOS(4))
ROMX_LOAD("p3_23_cm.rom",0x18000,0x8000, CRC(61f2b50c) SHA1(d062765ceb1f3cd2c94ea51cb737cac7ad6151b4), ROM_BIOS(4))
ROM_SYSTEM_BIOS( 0, "en", "English v4.0" ) // +3
ROMX_LOAD("40092.ic7",0x10000,0x8000, CRC(9bc85686) SHA1(5992daf925f6e225fc0d01f7640282954d092ef4), ROM_BIOS(0))
ROMX_LOAD("40093.ic8",0x18000,0x8000, CRC(db551783) SHA1(a0432adcca03f849fb39b6dce6414740cf4aecd2), ROM_BIOS(0))
ROM_SYSTEM_BIOS( 1, "sp", "Spanish v4.0" )
ROMX_LOAD("40094.ic7",0x10000,0x8000, CRC(392242fb) SHA1(976ae88951f8d1beb5d107f048950118a7133823), ROM_BIOS(1))
ROMX_LOAD("40101.ic8",0x18000,0x8000, CRC(5daaae01) SHA1(09ca25b4dbec064a4964ab7a41d48404199afd77), ROM_BIOS(1))
ROM_SYSTEM_BIOS( 2, "enb", "English v4.1" ) // +3B
ROMX_LOAD("40092u.ic7",0x10000,0x8000, CRC(80808d82) SHA1(b9e88ec18f844ce42ecb7802d82c2bda65f9c4f2), ROM_BIOS(2))
ROMX_LOAD("40093u.ic8",0x18000,0x8000, CRC(61f2b50c) SHA1(d062765ceb1f3cd2c94ea51cb737cac7ad6151b4), ROM_BIOS(2))
ROM_SYSTEM_BIOS( 3, "spb", "Spanish v4.1" )
ROMX_LOAD("40094s.ic7",0x10000,0x8000, CRC(9d102acf) SHA1(c525bd23f79ca968d34a0efdcc47b2eb342007f5), ROM_BIOS(3))
ROMX_LOAD("40101s.ic8",0x18000,0x8000, CRC(1408ddce) SHA1(56eb124d44ee8c8daef130be4d7e735ec412c4ba), ROM_BIOS(3))
ROM_SYSTEM_BIOS( 4, "4ms", "Customize 3.5\" 4ms" ) // unofficial 3.5" fdd hacks by Cristian Secară (v4.1 english)
ROMX_LOAD("p3_01_4m.rom",0x10000,0x8000, CRC(ad99380a) SHA1(4e5d114b72d464cefdde0566457f52a3c0c1cae2), ROM_BIOS(4))
ROMX_LOAD("p3_23_4m.rom",0x18000,0x8000, CRC(07727895) SHA1(752cdd6a083ab9910348995e483541d60bb6372b), ROM_BIOS(4))
ROM_SYSTEM_BIOS( 5, "12ms", "Customize 3.5\" 12ms" )
ROMX_LOAD("p3_01_cm.rom",0x10000,0x8000, CRC(ad99380a) SHA1(4e5d114b72d464cefdde0566457f52a3c0c1cae2), ROM_BIOS(5))
ROMX_LOAD("p3_23_cm.rom",0x18000,0x8000, CRC(61f2b50c) SHA1(d062765ceb1f3cd2c94ea51cb737cac7ad6151b4), ROM_BIOS(5))
ROM_END
ROM_START(specpl3e)
@ -499,10 +537,10 @@ ROM_START(sp3eata)
ROMX_LOAD("3ezxaes.rom",0x10000,0x10000, CRC(8f0ae91a) SHA1(71693e18b30c90914be58cba26682ca025c924ea), ROM_BIOS(1))
ROM_END
/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
COMP( 1987, specpl2a, spec128, 0, spectrum_plus2, spec_plus, specpls3_state, empty_init, "Amstrad plc", "ZX Spectrum +2a", 0 )
COMP( 1987, specpls3, spec128, 0, spectrum_plus3, spec_plus, specpls3_state, empty_init, "Amstrad plc", "ZX Spectrum +3", 0 )
COMP( 2000, specpl3e, spec128, 0, spectrum_plus3, spec_plus, specpls3_state, empty_init, "Amstrad plc", "ZX Spectrum +3e", MACHINE_UNOFFICIAL )
COMP( 2002, sp3e8bit, spec128, 0, spectrum_plus3, spec_plus, specpls3_state, empty_init, "Amstrad plc", "ZX Spectrum +3e 8bit IDE", MACHINE_UNOFFICIAL )
COMP( 2002, sp3eata, spec128, 0, spectrum_plus3, spec_plus, specpls3_state, empty_init, "Amstrad plc", "ZX Spectrum +3e 8bit ZXATASP" , MACHINE_UNOFFICIAL )
COMP( 2002, sp3ezcf, spec128, 0, spectrum_plus3, spec_plus, specpls3_state, empty_init, "Amstrad plc", "ZX Spectrum +3e 8bit ZXCF", MACHINE_UNOFFICIAL )
/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
COMP( 1987, specpl2a, 0, 0, spectrum_plus2, spec_plus, specpls3_state, empty_init, "Amstrad plc", "ZX Spectrum +2a", 0 )
COMP( 1987, specpls3, specpl2a, 0, spectrum_plus3, spec_plus, specpls3_state, empty_init, "Amstrad plc", "ZX Spectrum +3", 0 )
COMP( 2000, specpl3e, 0, 0, spectrum_plus3, spec_plus, specpls3_state, empty_init, "Amstrad plc", "ZX Spectrum +3e", MACHINE_UNOFFICIAL )
COMP( 2002, sp3e8bit, 0, 0, spectrum_plus3, spec_plus, specpls3_state, empty_init, "Amstrad plc", "ZX Spectrum +3e 8bit IDE", MACHINE_UNOFFICIAL )
COMP( 2002, sp3eata, 0, 0, spectrum_plus3, spec_plus, specpls3_state, empty_init, "Amstrad plc", "ZX Spectrum +3e 8bit ZXATASP", MACHINE_UNOFFICIAL )
COMP( 2002, sp3ezcf, 0, 0, spectrum_plus3, spec_plus, specpls3_state, empty_init, "Amstrad plc", "ZX Spectrum +3e 8bit ZXCF", MACHINE_UNOFFICIAL )

View File

@ -340,7 +340,7 @@ uint8_t spectrum_state::spectrum_rom_r(offs_t offset)
bit 2-0: border colour
*/
void spectrum_state::spectrum_port_fe_w(offs_t offset, uint8_t data)
void spectrum_state::spectrum_ula_w(offs_t offset, uint8_t data)
{
unsigned char Changed;
@ -364,6 +364,8 @@ void spectrum_state::spectrum_port_fe_w(offs_t offset, uint8_t data)
m_cassette->output((data & (1<<3)) ? -1.0 : +1.0);
}
// Some exp devices use ula port unused bits 5-7:
// Beta v2/3/plus use bit 7, Beta clones use bits 6 and 7
if (m_exp)
m_exp->iorq_w(offset, data);
@ -373,7 +375,7 @@ void spectrum_state::spectrum_port_fe_w(offs_t offset, uint8_t data)
/* KT: more accurate keyboard reading */
/* DJR: Spectrum+ keys added */
uint8_t spectrum_state::spectrum_port_fe_r(offs_t offset)
uint8_t spectrum_state::spectrum_ula_r(offs_t offset)
{
int lines = offset >> 8;
int data = 0xff;
@ -448,76 +450,30 @@ uint8_t spectrum_state::spectrum_port_fe_r(offs_t offset)
return data;
}
uint8_t spectrum_state::spectrum_port_ula_r(offs_t offset)
void spectrum_state::spectrum_port_w(offs_t offset, uint8_t data)
{
// known ports used for reading floating bus are:
// 0x28ff Arkanoid, Cobra, Renegade, Short Circuit, Terra Cresta
// 0x40ff Sidewize
// note, these games clash with Beta disk (status reg is R:xxff)
offset |= 1;
//logerror("fb: %04x\n", offset);
#if 0 // TODO make this expansion devices friendly
// Arkanoid, Cobra, Renegade, Short Circuit, Terra Cresta
if (offset == 0x28ff)
return floating_bus_r();
// Sidewize
if (offset == 0x40ff)
return floating_bus_r();
#endif
// Pass through to expansion device if present
if (m_exp->get_card_device())
return m_exp->iorq_r(offset);
m_exp->iorq_w(offset | 1, data);
}
uint8_t spectrum_state::spectrum_port_r(offs_t offset)
{
// Pass through to expansion device if present
if (m_exp->get_card_device())
return m_exp->iorq_r(offset | 1);
return floating_bus_r();
}
uint8_t spectrum_state::spectrum_clone_port_ula_r()
uint8_t spectrum_state::spectrum_clone_port_r(offs_t offset)
{
int vpos = m_screen->vpos();
// Pass through to expansion device if present
if (m_exp->get_card_device())
return m_exp->iorq_r(offset | 1);
return vpos<193 ? m_video_ram[(vpos&0xf8)<<2]:0xff;
}
/* Memory Maps */
void spectrum_state::spectrum_map(address_map &map)
{
map(0x0000, 0x3fff).rw(FUNC(spectrum_state::spectrum_rom_r), FUNC(spectrum_state::spectrum_rom_w));
map(0x4000, 0x5aff).ram().share("video_ram");
// installed later depending on ramsize
//map(0x5b00, 0x7fff).ram();
//map(0x8000, 0xffff).ram();
}
void spectrum_state::spectrum_opcodes(address_map &map)
{
map(0x0000, 0xffff).rw(FUNC(spectrum_state::spectrum_data_r), FUNC(spectrum_state::spectrum_data_w));
}
void spectrum_state::spectrum_data(address_map &map)
{
map(0x0000, 0xffff).r(FUNC(spectrum_state::pre_opcode_fetch_r));
}
/* ports are not decoded full.
The function decodes the ports appropriately */
void spectrum_state::spectrum_io(address_map &map)
{
map(0x0000, 0xffff).w(m_exp, FUNC(spectrum_expansion_slot_device::iorq_w));
map(0x00, 0x00).select(0xfffe).rw(FUNC(spectrum_state::spectrum_port_fe_r), FUNC(spectrum_state::spectrum_port_fe_w));
map(0x01, 0x01).select(0xfffe).r(FUNC(spectrum_state::spectrum_port_ula_r));
}
void spectrum_state::spectrum_clone_io(address_map &map)
{
map(0x0000, 0xffff).rw(m_exp, FUNC(spectrum_expansion_slot_device::iorq_r), FUNC(spectrum_expansion_slot_device::iorq_w));
map(0x00, 0x00).select(0xfffe).rw(FUNC(spectrum_state::spectrum_port_fe_r), FUNC(spectrum_state::spectrum_port_fe_w));
map(0x01, 0x01).r(FUNC(spectrum_state::spectrum_clone_port_ula_r)); // .mirror(0xfffe);
// no floating bus for clones
return 0xff;
}
uint8_t spectrum_state::floating_bus_r()
@ -540,6 +496,8 @@ uint8_t spectrum_state::floating_bus_r()
*
* ...others?
*
* (Sidewize uses port 0x40ff, others use 0x28ff)
*
* Note, some were later re-released as "fixed" +2A compatible versions with the floating bus code removed (Arkanoid, Cobra, others?).
*/
@ -557,6 +515,46 @@ uint8_t spectrum_state::floating_bus_r()
}
/* Memory Maps */
void spectrum_state::spectrum_map(address_map &map)
{
map(0x0000, 0x3fff).rw(FUNC(spectrum_state::spectrum_rom_r), FUNC(spectrum_state::spectrum_rom_w));
map(0x4000, 0x5aff).ram().share("video_ram");
// installed later depending on ramsize
//map(0x5b00, 0x7fff).ram();
//map(0x8000, 0xffff).ram();
}
void spectrum_state::spectrum_opcodes(address_map &map)
{
map(0x0000, 0xffff).rw(FUNC(spectrum_state::spectrum_data_r), FUNC(spectrum_state::spectrum_data_w));
}
void spectrum_state::spectrum_data(address_map &map)
{
map(0x0000, 0xffff).r(FUNC(spectrum_state::pre_opcode_fetch_r));
}
// The ula is usually accessed with port 0xfe but is only partially decoded with a single address line (A0),
// so actually responds to any even numbered port.
// Exp devices therefore shouldn't use any even numbered ports, but in fact some do:
// for write, some devices use bits 5-7 as they are not used by the ula (eg. Beta)
// for read, some devices (eg. Interface II and some other joystick interfaces) simply override the data lines to simulate key presses
// (series resistors between the ula and cpu/exp slot allow this)
void spectrum_state::spectrum_io(address_map &map)
{
map(0x00, 0x00).rw(FUNC(spectrum_state::spectrum_ula_r), FUNC(spectrum_state::spectrum_ula_w)).select(0xfffe);
map(0x01, 0x01).rw(FUNC(spectrum_state::spectrum_port_r), FUNC(spectrum_state::spectrum_port_w)).select(0xfffe);
}
void spectrum_state::spectrum_clone_io(address_map &map)
{
map(0x00, 0x00).rw(FUNC(spectrum_state::spectrum_ula_r), FUNC(spectrum_state::spectrum_ula_w)).select(0xfffe);
map(0x01, 0x01).rw(FUNC(spectrum_state::spectrum_clone_port_r), FUNC(spectrum_state::spectrum_port_w)).select(0xfffe);
}
/* Input ports */
/****************************************************************************************************/
@ -802,6 +800,7 @@ void spectrum_state::spectrum_common(machine_config &config)
SPECTRUM_EXPANSION_SLOT(config, m_exp, spectrum_expansion_devices, "kempjoy");
m_exp->irq_handler().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
m_exp->nmi_handler().set_inputline(m_maincpu, INPUT_LINE_NMI);
m_exp->fb_r_handler().set(FUNC(spectrum_state::floating_bus_r));
/* devices */
SNAPSHOT(config, "snapshot", "ach,frz,plusd,prg,sem,sit,sna,snp,snx,sp,z80,zx").set_load_callback(FUNC(spectrum_state::snapshot_cb));
@ -831,7 +830,10 @@ void spectrum_state::spectrum(machine_config &config)
void spectrum_state::spectrum_clone(machine_config &config)
{
spectrum(config);
// no floating bus
m_maincpu->set_addrmap(AS_IO, &spectrum_state::spectrum_clone_io);
m_exp->fb_r_handler().set([]() { return 0xff; });
}
/***************************************************************************
@ -913,6 +915,15 @@ ROM_START(spec80k)
ROM_LOAD("80-lec.rom", 0x0000, 0x4000, CRC(5b5c92b1) SHA1(bb7a77d66e95d2e28ebb610e543c065e0d428619))
ROM_END
/* Official Sinclair licensed Spanish clone */
ROM_START(inves)
ROM_REGION(0x10000,"maincpu",0)
ROM_LOAD("inves.rom",0x0000,0x4000, CRC(8ff7a4d1) SHA1(d020440638aff4d39467128413ef795677be9c23))
ROM_END
/* Brazilian clones */
ROM_START(tk90x)
ROM_REGION(0x10000,"maincpu",0)
ROM_LOAD("tk90x.rom",0x0000,0x4000, CRC(3e785f6f) SHA1(9a943a008be13194fb006bddffa7d22d2277813f))
@ -923,18 +934,14 @@ ROM_START(tk95)
ROM_LOAD("tk95.rom",0x0000,0x4000, CRC(17368e07) SHA1(94edc401d43b0e9a9cdc1d35de4b6462dc414ab3))
ROM_END
ROM_START(inves)
ROM_REGION(0x10000,"maincpu",0)
ROM_LOAD("inves.rom",0x0000,0x4000, CRC(8ff7a4d1) SHA1(d020440638aff4d39467128413ef795677be9c23))
ROM_END
/* Romanian clones */
ROM_START(hc85)
ROM_REGION(0x10000,"maincpu",0)
ROM_LOAD("hc85.rom",0x0000,0x4000, CRC(3ab60fb5) SHA1(a4189db0bcdf8b39ed782b398828efb408fc4817))
ROM_END
ROM_START( hc88 )
ROM_START(hc88)
ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASEFF )
ROM_LOAD( "hc88.bin", 0x0000, 0x0800, CRC(33be5134) SHA1(b15a6e7085710de8b818e42d329707cb737627e3))
ROM_END
@ -949,6 +956,27 @@ ROM_START(hc91)
ROM_LOAD("hc91.rom",0x0000,0x4000, CRC(8bf53761) SHA1(967d5179ba2823e9c8dd9ddfb0430465aaddb554))
ROM_END
ROM_START(hc2000)
// HC-91 with internal fdd, 64KB ram, dual-os (BASIC, CP/M), built-in Interface I
// user manual states "16KB BASIC rom, 16KB CP/M rom, 10KB Interface I rom"
// some pcb have 2x 27256 eproms, some have single 28-pin socket (27512?)
// for 2 eprom model, seems #1 is combined BASIC+CP/M, #2 is intf1
// BASIC should boot first, then optionally CP/M can be booted with RANDOMIZE USR 14446
// CP/M can use 56KB ram, fdc is UM8272A, disks are 3.5" 720KB
ROM_REGION(0x10000,"maincpu",0)
ROM_SYSTEM_BIOS( 0, "basicv1", "BASIC v1" )
ROMX_LOAD("hc2000.v1", 0x0000,0x4000, CRC(453c1a5a) SHA1(f8139fc38478691cf44944dc83fd6e70b0f002fb), ROM_BIOS(0))
ROM_SYSTEM_BIOS( 1, "basicv2", "BASIC v2" )
ROMX_LOAD("hc2000.v2", 0x0000,0x4000, CRC(65d90464) SHA1(5e2096e6460ff2120c8ada97579fdf82c1199c09), ROM_BIOS(1))
ROM_SYSTEM_BIOS( 2, "cpmv1", "CP/M v1" ) // not working
ROMX_LOAD("hc2000c.v1", 0x0000,0x4000, CRC(aaa373fe) SHA1(55a30d99c37c86c55ce6c8ecbe593b81d9819e90), ROM_BIOS(2))
ROM_SYSTEM_BIOS( 3, "cpmv2", "CP/M v2" ) // not working, data arranged differently to v1
ROMX_LOAD("hc2000c.v2", 0x0000,0x2000, CRC(69c757fe) SHA1(c2bcab2398fb493a31cf6c18ff1e4e9f55690d41), ROM_BIOS(3))
ROM_REGION(0x8000,"opt",0) // Interface 1 roms
ROM_LOAD_OPTIONAL("hc2000i.v12", 0x4000, 0x4000, CRC(182d5c0c) SHA1(b76d2bebcd938238f790e395859d0d237637d33e)) // 190892 v1, v2 pcb
ROM_LOAD_OPTIONAL("hc2000i.vx", 0x0000, 0x4000, CRC(39967a21) SHA1(e190001ae318982ed31f6c02b4201ca9126a739a)) // 221191 unknown pcb ver
ROM_END
ROM_START(cip03)
ROM_REGION(0x10000,"maincpu",0)
ROM_LOAD("cip03.rom",0x0000,0x4000, CRC(c7d0cd3c) SHA1(811055b44fc74076137e2bf8db206b2a70287cc2))
@ -964,7 +992,7 @@ ROM_START(jet)
ROM_LOAD("jet.rom",0x0000,0x4000, CRC(e56a7d11) SHA1(e76be9ee71bae6aa1c2ff969276fb599ed68cb50))
ROM_END
ROM_START( cobrasp )
ROM_START(cobrasp)
ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASEFF )
ROM_SYSTEM_BIOS(0, "v1", "V1")
ROMX_LOAD( "boot64k_v1.bin", 0x0000, 0x0800, CRC(a54aae6d) SHA1(8f5134ce24aea59065ed166ad79e864e17ce812f), ROM_BIOS(0))
@ -972,7 +1000,7 @@ ROM_START( cobrasp )
ROMX_LOAD( "boot64k_v2.bin", 0x0000, 0x0800, CRC(ee91cc89) SHA1(37dea7fe0734068adf99b91fdcbf3119095c350d), ROM_BIOS(1))
ROM_END
ROM_START( cobra80 )
ROM_START(cobra80)
ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASEFF )
ROM_SYSTEM_BIOS(0, "v1", "V1")
ROMX_LOAD( "boot80k_v1.bin", 0x0000, 0x0800, CRC(f42d2342) SHA1(8aa1b3b056e311674a051ffc6a49af60cae409f3), ROM_BIOS(0))
@ -1040,7 +1068,7 @@ ROM_END
/* Russian clones */
ROM_START( bk08 )
ROM_START(bk08)
ROM_REGION(0x10000,"maincpu",0)
ROM_LOAD( "right.bin", 0x0000, 0x2000, CRC(fb253544) SHA1(6b79487e3013d0acdea8d224b21c937e88105a2f) )
ROM_LOAD( "left.bin", 0x2000, 0x2000, CRC(a092b5f3) SHA1(06b8d98a398f61daf6604c68bcee4596c283c2cd) )
@ -1106,6 +1134,7 @@ COMP( 1985, hc85, spectrum, 0, spectrum_clone, spectrum, spectrum_stat
COMP( 1988, hc88, spectrum, 0, spectrum_clone, spectrum, spectrum_state, init_spectrum, "ICE-Felix", "HC-88", MACHINE_NOT_WORKING )
COMP( 1990, hc90, spectrum, 0, spectrum_clone, spectrum, spectrum_state, init_spectrum, "ICE-Felix", "HC-90", 0 )
COMP( 1991, hc91, spectrum, 0, spectrum_clone, spec_plus, spectrum_state, init_spectrum, "ICE-Felix", "HC-91", 0 )
COMP( 1992, hc2000, spectrum, 0, spectrum_clone, spec_plus, spectrum_state, init_spectrum, "ICE-Felix", "HC-2000", MACHINE_NOT_WORKING ) // dual-os, only BASIC roms working
COMP( 1988, cobrasp, spectrum, 0, spectrum_clone, spectrum, spectrum_state, init_spectrum, "ITCI", "Cobra (ITCI)", MACHINE_NOT_WORKING )
COMP( 1988, cobra80, spectrum, 0, spectrum_clone, spectrum, spectrum_state, init_spectrum, "ITCI", "Cobra 80K (ITCI)", MACHINE_NOT_WORKING )
COMP( 1987, cip01, spectrum, 0, spectrum_clone, spectrum, spectrum_state, init_spectrum, "Electronica", "CIP-01", 0 ) // keyboard should be spectrum, but image was not clear

View File

@ -530,7 +530,7 @@ void ts2068_state::ts2068_io(address_map &map)
map(0xf4, 0xf4).rw(FUNC(ts2068_state::port_f4_r), FUNC(ts2068_state::port_f4_w)).mirror(0xff00);
map(0xf5, 0xf5).w("ay8912", FUNC(ay8910_device::address_w)).mirror(0xff00);
map(0xf6, 0xf6).rw("ay8912", FUNC(ay8910_device::data_r), FUNC(ay8910_device::data_w)).mirror(0xff00);
map(0xfe, 0xfe).rw(FUNC(ts2068_state::spectrum_port_fe_r), FUNC(ts2068_state::spectrum_port_fe_w)).select(0xff00);
map(0xfe, 0xfe).rw(FUNC(ts2068_state::spectrum_ula_r), FUNC(ts2068_state::spectrum_ula_w)).select(0xff00);
map(0xff, 0xff).rw(FUNC(ts2068_state::port_ff_r), FUNC(ts2068_state::port_ff_w)).mirror(0xff00);
}
@ -573,7 +573,7 @@ void tc2048_state::port_ff_w(offs_t offset, uint8_t data)
void tc2048_state::tc2048_io(address_map &map)
{
map(0x00, 0x00).rw(FUNC(tc2048_state::spectrum_port_fe_r), FUNC(tc2048_state::spectrum_port_fe_w)).select(0xfffe);
map(0x00, 0x00).rw(FUNC(tc2048_state::spectrum_ula_r), FUNC(tc2048_state::spectrum_ula_w)).select(0xfffe);
map(0xff, 0xff).rw(FUNC(tc2048_state::port_ff_r), FUNC(tc2048_state::port_ff_w)).mirror(0xff00);
}

View File

@ -122,7 +122,7 @@ void tsconf_state::tsconf_io(address_map &map)
map(0x0077, 0x0077).mirror(0xff00).rw(FUNC(tsconf_state::tsconf_port_77_zctr_r), FUNC(tsconf_state::tsconf_port_77_zctr_w)); // spi data
map(0x005f, 0x005f).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::sector_r), FUNC(beta_disk_device::sector_w));
map(0x007f, 0x007f).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::data_r), FUNC(beta_disk_device::data_w));
map(0x00fe, 0x00fe).select(0xff00).rw(FUNC(tsconf_state::spectrum_port_fe_r), FUNC(tsconf_state::tsconf_port_fe_w));
map(0x00fe, 0x00fe).select(0xff00).rw(FUNC(tsconf_state::spectrum_ula_r), FUNC(tsconf_state::tsconf_port_fe_w));
map(0x00ff, 0x00ff).mirror(0xff00).rw(m_beta, FUNC(beta_disk_device::state_r), FUNC(beta_disk_device::param_w));
map(0x00af, 0x00af).select(0xff00).rw(FUNC(tsconf_state::tsconf_port_xxaf_r), FUNC(tsconf_state::tsconf_port_xxaf_w));
map(0x8ff7, 0x8ff7).select(0x7000).w(FUNC(tsconf_state::tsconf_port_f7_w)); // 3:bff7 5:dff7 6:eff7

View File

@ -36,11 +36,11 @@ protected:
private:
void bank1_w(offs_t offset, uint8_t data);
uint8_t bank1_r(offs_t offset);
void port_3ffd_w(uint8_t data);
void port_3ffd_w(offs_t offset, uint8_t data);
uint8_t port_3ffd_r();
uint8_t port_2ffd_r();
void port_7ffd_w(uint8_t data);
void port_1ffd_w(uint8_t data);
void port_7ffd_w(offs_t offset, uint8_t data);
void port_1ffd_w(offs_t offset, uint8_t data);
void plus3_us_w(uint8_t data);
void plus3_io(address_map &map);

View File

@ -153,10 +153,12 @@ protected:
uint8_t spectrum_data_r(offs_t offset);
void spectrum_data_w(offs_t offset, uint8_t data);
void spectrum_port_fe_w(offs_t offset, uint8_t data);
uint8_t spectrum_port_fe_r(offs_t offset);
uint8_t spectrum_port_ula_r(offs_t offset);
uint8_t spectrum_clone_port_ula_r();
void spectrum_ula_w(offs_t offset, uint8_t data);
uint8_t spectrum_ula_r(offs_t offset);
void spectrum_port_w(offs_t offset, uint8_t data);
virtual uint8_t spectrum_port_r(offs_t offset);
virtual uint8_t floating_bus_r();
uint8_t spectrum_clone_port_r(offs_t offset);
void spectrum_palette(palette_device &palette) const;
virtual uint32_t screen_update_spectrum(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
@ -238,8 +240,6 @@ protected:
void log_quickload(const char *type, uint32_t start, uint32_t length, uint32_t exec, const char *exec_format);
void setup_scr(uint8_t *quickdata, uint32_t quicksize);
void setup_raw(uint8_t *quickdata, uint32_t quicksize);
uint8_t floating_bus_r();
};
class spectrum_128_state : public spectrum_state
@ -262,7 +262,9 @@ private:
void spectrum_128_bank1_w(offs_t offset, uint8_t data);
uint8_t spectrum_128_bank1_r(offs_t offset);
void spectrum_128_port_7ffd_w(offs_t offset, uint8_t data);
uint8_t spectrum_128_ula_r();
virtual uint8_t spectrum_port_r(offs_t offset) override;
virtual uint8_t floating_bus_r() override;
//uint8_t spectrum_128_ula_r();
void spectrum_128_io(address_map &map);
void spectrum_128_mem(address_map &map);

View File

@ -336,7 +336,7 @@ void tsconf_state::tsconf_port_7ffd_w(u8 data)
void tsconf_state::tsconf_port_fe_w(offs_t offset, u8 data)
{
m_regs[BORDER] = (data & 0x07) | 0xf0;
spectrum_port_fe_w(offset, data);
spectrum_ula_w(offset, data);
}
u8 tsconf_state::tsconf_port_xxaf_r(offs_t port)

View File

@ -39196,7 +39196,6 @@ spdodgeb // TA-0022 (c) 1987
@source:spec128.cpp
hc128 // 1991 HC-128
hc2000 // 1992 HC-2000
spec128 // 1986 ZX Spectrum 128
specpls2 // 1986 ZX Spectrum +2
@ -39243,6 +39242,7 @@ didakm92 // 1992 Didaktik M 92
didakm93 // 1993 Didaktik M 93
didakt90 // 1990 Didaktik Skalica 90
didaktk // 1992 Didaktik Kompakt
hc2000 // 1992 HC-2000
hc85 // 1985 HC-85
hc88 // 1988 HC-88
hc90 // 1990 HC-90