mtx: Added expansion bus with SDX floppy controller.

- 80 column card with SDX in CP/M mode.
- ROM/RAM banking fixed for CP/M, and MTX500 now correctly detected.
- Support for Type 03 and Type 07 .mfloppy images.
- Added alternate MTX2 romset (German).
- Keyboard ROM now selected in Configuration.
- Quickload .RUN files.
This commit is contained in:
Nigel Barnes 2019-03-10 17:23:39 +00:00
parent f9ae1fd408
commit 5511ce41e2
12 changed files with 1025 additions and 128 deletions

View File

@ -1404,6 +1404,21 @@ if (BUSES["MSX_SLOT"]~=null) then
end
---------------------------------------------------
--
--@src/devices/bus/mtx/exp.h,BUSES["MTX"] = true
---------------------------------------------------
if (BUSES["MTX"]~=null) then
files {
MAME_DIR .. "src/devices/bus/mtx/exp.cpp",
MAME_DIR .. "src/devices/bus/mtx/exp.h",
MAME_DIR .. "src/devices/bus/mtx/sdx.cpp",
MAME_DIR .. "src/devices/bus/mtx/sdx.h",
}
end
---------------------------------------------------
--
--@src/devices/bus/kc/kc.h,BUSES["KC"] = true

View File

@ -1145,6 +1145,18 @@ if (FORMATS["MSX_DSK"]~=null or _OPTIONS["with-tools"]) then
}
end
--------------------------------------------------
--
--@src/lib/formats/mtx_dsk.h,FORMATS["MTX_DSK"] = true
--------------------------------------------------
if (FORMATS["MTX_DSK"]~=null or _OPTIONS["with-tools"]) then
files {
MAME_DIR.. "src/lib/formats/mtx_dsk.cpp",
MAME_DIR.. "src/lib/formats/mtx_dsk.h",
}
end
--------------------------------------------------
--
--@src/lib/formats/mz_cas.h,FORMATS["MZ_CAS"] = true

View File

@ -772,6 +772,7 @@ BUSES["MACPDS"] = true
BUSES["MIDI"] = true
BUSES["MEGADRIVE"] = true
BUSES["MSX_SLOT"] = true
BUSES["MTX"] = true
BUSES["NASBUS"] = true
BUSES["NEOGEO"] = true
BUSES["NEOGEO_CTRL"] = true
@ -933,6 +934,7 @@ FORMATS["MFM_HD"] = true
FORMATS["MM_DSK"] = true
FORMATS["MS0515_DSK"] = true
FORMATS["MSX_DSK"] = true
FORMATS["MTX_DSK"] = true
FORMATS["MZ_CAS"] = true
FORMATS["NANOS_DSK"] = true
FORMATS["NASCOM_DSK"] = true

126
src/devices/bus/mtx/exp.cpp Normal file
View File

@ -0,0 +1,126 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************
MTX expansion emulation
**********************************************************************/
#include "emu.h"
#include "exp.h"
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
DEFINE_DEVICE_TYPE(MTX_EXP_SLOT, mtx_exp_slot_device, "mtx_exp_slot", "MTX expansion slot")
//**************************************************************************
// DEVICE MTX_BUS PORT INTERFACE
//**************************************************************************
//-------------------------------------------------
// device_mtx_exp_interface - constructor
//-------------------------------------------------
device_mtx_exp_interface::device_mtx_exp_interface(const machine_config &mconfig, device_t &device)
: device_slot_card_interface(mconfig, device)
{
m_slot = dynamic_cast<mtx_exp_slot_device *>(device.owner());
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// mtx_exp_slot_device - constructor
//-------------------------------------------------
mtx_exp_slot_device::mtx_exp_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, MTX_EXP_SLOT, tag, owner, clock)
, device_slot_interface(mconfig, *this)
, m_io(nullptr)
, m_card(nullptr)
, m_busreq_handler(*this)
, m_int_handler(*this)
, m_nmi_handler(*this)
{
}
//-------------------------------------------------
// device_validity_check -
//-------------------------------------------------
void mtx_exp_slot_device::device_validity_check(validity_checker &valid) const
{
device_t *const carddev = get_card_device();
if (carddev && !dynamic_cast<device_mtx_exp_interface *>(carddev))
osd_printf_error("Card device %s (%s) does not implement device_mtx_exp_interface\n", carddev->tag(), carddev->name());
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void mtx_exp_slot_device::device_start()
{
device_t *const carddev = get_card_device();
if (carddev && !dynamic_cast<device_mtx_exp_interface *>(carddev))
osd_printf_error("Card device %s (%s) does not implement device_mtx_exp_interface\n", carddev->tag(), carddev->name());
// resolve callbacks
m_busreq_handler.resolve_safe();
m_int_handler.resolve_safe();
m_nmi_handler.resolve_safe();
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void mtx_exp_slot_device::device_reset()
{
}
//-------------------------------------------------
// set_program_space - set address space we are attached to
//-------------------------------------------------
void mtx_exp_slot_device::set_program_space(address_space *program)
{
m_program = program;
}
//-------------------------------------------------
// set_io_space - set address space we are attached to
//-------------------------------------------------
void mtx_exp_slot_device::set_io_space(address_space *io)
{
m_io = io;
}
//-------------------------------------------------
// SLOT_INTERFACE( mtx_exp_devices )
//-------------------------------------------------
// slot devices
//#include "fdx.h"
#include "sdx.h"
void mtx_expansion_devices(device_slot_interface &device)
{
//device.option_add("fdx", MTX_FDX); /* FDX Floppy Disc System */
device.option_add("sdxbas", MTX_SDXBAS); /* SDX Floppy Disc System (SDX ROM)*/
device.option_add("sdxcpm", MTX_SDXCPM); /* SDX Floppy Disc System (CP/M ROM and 80 column card) */
}

92
src/devices/bus/mtx/exp.h Normal file
View File

@ -0,0 +1,92 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************
MTX expansion emulation
**********************************************************************/
#ifndef MAME_BUS_MTX_EXP_H
#define MAME_BUS_MTX_EXP_H
#pragma once
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// ======================> mtx_exp_slot_device
class device_mtx_exp_interface;
class mtx_exp_slot_device : public device_t, public device_slot_interface
{
public:
// construction/destruction
template <typename T>
mtx_exp_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&slot_options, const char *default_option)
: mtx_exp_slot_device(mconfig, tag, owner)
{
option_reset();
slot_options(*this);
set_default_option(default_option);
set_fixed(false);
}
mtx_exp_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock = 0);
void set_program_space(address_space *program);
void set_io_space(address_space *io);
// callbacks
auto busreq_handler() { return m_busreq_handler.bind(); }
auto int_handler() { return m_int_handler.bind(); }
auto nmi_handler() { return m_nmi_handler.bind(); }
DECLARE_WRITE_LINE_MEMBER( busreq_w ) { m_busreq_handler(state); }
DECLARE_WRITE_LINE_MEMBER( int_w ) { m_int_handler(state); }
DECLARE_WRITE_LINE_MEMBER( nmi_w ) { m_nmi_handler(state); }
address_space *m_program;
address_space *m_io;
protected:
// device-level overrides
virtual void device_validity_check(validity_checker &valid) const override;
virtual void device_start() override;
virtual void device_reset() override;
device_mtx_exp_interface *m_card;
private:
devcb_write_line m_busreq_handler;
devcb_write_line m_int_handler;
devcb_write_line m_nmi_handler;
};
// ======================> device_mtx_exp_interface
class device_mtx_exp_interface : public device_slot_card_interface
{
public:
// construction/destruction
device_mtx_exp_interface(const machine_config &mconfig, device_t &device);
protected:
address_space &program_space() { return *m_slot->m_program; }
address_space &io_space() { return *m_slot->m_io; }
mtx_exp_slot_device *m_slot;
};
// device type definition
DECLARE_DEVICE_TYPE(MTX_EXP_SLOT, mtx_exp_slot_device)
void mtx_expansion_devices(device_slot_interface &device);
#endif // MAME_BUS_MTX_EXP_H

425
src/devices/bus/mtx/sdx.cpp Normal file
View File

@ -0,0 +1,425 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************
MTX SDX Controller
**********************************************************************/
#include "emu.h"
#include "sdx.h"
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
DEFINE_DEVICE_TYPE(MTX_SDXBAS, mtx_sdxbas_device, "mtx_sdxbas", "MTX SDX Controller (BASIC)")
DEFINE_DEVICE_TYPE(MTX_SDXCPM, mtx_sdxcpm_device, "mtx_sdxcpm", "MTX SDX Controller (CP/M)")
//-------------------------------------------------
// SLOT_INTERFACE( sdx_floppies )
//-------------------------------------------------
static void sdx_floppies(device_slot_interface &device)
{
device.option_add("35dd", FLOPPY_35_DD);
device.option_add("525qd", FLOPPY_525_QD);
}
FLOPPY_FORMATS_MEMBER(mtx_sdx_device::floppy_formats)
FLOPPY_MTX_FORMAT
FLOPPY_FORMATS_END
//-------------------------------------------------
// ROM( sdx )
//-------------------------------------------------
ROM_START( sdxbas )
ROM_REGION(0x2000, "sdx_rom", ROMREGION_ERASE00)
ROM_DEFAULT_BIOS("sdx07")
ROM_SYSTEM_BIOS(0, "sdx07", "Type 07")
ROMX_LOAD("sdxbas07.rom", 0x0000, 0x2000, CRC(db88b245) SHA1(05c89db8e39ec3165b4620432f48e1d59abe10dd), ROM_BIOS(0))
ROM_SYSTEM_BIOS(1, "sdx03", "Type 03")
ROMX_LOAD("sdxbas03.rom", 0x0000, 0x2000, CRC(2fc46a46) SHA1(f08e6a8cffbb3ca39633be6e9958bec85d1e5981), ROM_BIOS(1))
ROM_END
ROM_START( sdxcpm )
ROM_REGION(0x2000, "sdx_rom", ROMREGION_ERASE00)
ROM_DEFAULT_BIOS("sdx07")
ROM_SYSTEM_BIOS(0, "sdx07", "SDX07 CP/M")
ROMX_LOAD("sdxcpm07.rom", 0x0000, 0x2000, CRC(622a04ea) SHA1(c633ce1054b45afda53116e0c6e272a1ae6a2155), ROM_BIOS(0))
ROM_REGION(0x2000, "chargen", 0)
ROM_LOAD("80z_7a.bin", 0x0000, 0x1000, CRC(ea6fe865) SHA1(f84883f79bed34501e5828336894fad929bddbb5)) // alpha
ROM_LOAD("80z_9a.bin", 0x1000, 0x1000, NO_DUMP) // graphic
ROM_END
//-------------------------------------------------
// INPUT_PORTS( sdx )
//-------------------------------------------------
INPUT_PORTS_START( sdx )
PORT_START("DSW0")
PORT_DIPNAME(0x01, 0x00, "Drive A: Head-load solenoid present") PORT_DIPLOCATION("SW1:1")
PORT_DIPSETTING(0x00, DEF_STR(Yes))
PORT_DIPSETTING(0x01, DEF_STR(No))
PORT_DIPNAME(0x02, 0x00, "Drive A: Double-sided drive") PORT_DIPLOCATION("SW1:2")
PORT_DIPSETTING(0x00, DEF_STR(Yes))
PORT_DIPSETTING(0x02, DEF_STR(No))
PORT_DIPNAME(0x04, 0x00, "Drive A: 96 TPI drive") PORT_DIPLOCATION("SW1:3")
PORT_DIPSETTING(0x00, DEF_STR(Yes))
PORT_DIPSETTING(0x04, DEF_STR(No))
PORT_DIPNAME(0x08, 0x00, "Drive A: Stepping rate") PORT_DIPLOCATION("SW1:4")
PORT_DIPSETTING(0x00, "Stepping rate 6ms")
PORT_DIPSETTING(0x08, "Stepping rate 12ms")
PORT_START("DSW1")
PORT_DIPNAME(0x01, 0x00, "Drive B: Head-load solenoid present") PORT_DIPLOCATION("SW2:1")
PORT_DIPSETTING(0x00, DEF_STR(Yes))
PORT_DIPSETTING(0x01, DEF_STR(No))
PORT_DIPNAME(0x02, 0x00, "Drive B: Double-sided drive") PORT_DIPLOCATION("SW2:2")
PORT_DIPSETTING(0x00, DEF_STR(Yes))
PORT_DIPSETTING(0x02, DEF_STR(No))
PORT_DIPNAME(0x04, 0x00, "Drive B: 96 TPI drive") PORT_DIPLOCATION("SW2:3")
PORT_DIPSETTING(0x00, DEF_STR(Yes))
PORT_DIPSETTING(0x04, DEF_STR(No))
PORT_DIPNAME(0x08, 0x00, "Drive B: Stepping rate") PORT_DIPLOCATION("SW2:4")
PORT_DIPSETTING(0x00, "Stepping rate 6ms")
PORT_DIPSETTING(0x08, "Stepping rate 12ms")
INPUT_PORTS_END
//-------------------------------------------------
// input_ports - device-specific input ports
//-------------------------------------------------
ioport_constructor mtx_sdx_device::device_input_ports() const
{
return INPUT_PORTS_NAME(sdx);
}
//-------------------------------------------------
// gfx_layout mtx_sdx_charlayout
//-------------------------------------------------
static const gfx_layout mtx_sdx_charlayout =
{
8, 10, /* 8 x 10 characters */
256, /* 256 characters */
1, /* 1 bits per pixel */
{ 0 }, /* no bitplanes */
/* x offsets */
{ 0, 1, 2, 3, 4, 5, 6, 7 },
/* y offsets */
{ 0 * 8, 1 * 8, 2 * 8, 3 * 8, 4 * 8, 5 * 8, 6 * 8, 7 * 8, 8 * 8, 9 * 8 },
8 * 16 /* every char takes 16 bytes */
};
//-------------------------------------------------
// GFXDECODE( gfx_mtx_sdx )
//-------------------------------------------------
static GFXDECODE_START(gfx_mtx_sdx)
GFXDECODE_ENTRY("chargen", 0, mtx_sdx_charlayout, 0, 8)
GFXDECODE_END
//-------------------------------------------------
// device_add_mconfig - add device configuration
//-------------------------------------------------
void mtx_sdxbas_device::device_add_mconfig(machine_config &config)
{
/* fdc */
MB8877(config, m_fdc, 8_MHz_XTAL / 8);
m_fdc->hld_wr_callback().set(FUNC(mtx_sdx_device::motor_w));
FLOPPY_CONNECTOR(config, "fdc:0", sdx_floppies, "525qd", mtx_sdx_device::floppy_formats).enable_sound(true);
FLOPPY_CONNECTOR(config, "fdc:1", sdx_floppies, "525qd", mtx_sdx_device::floppy_formats).enable_sound(true);
}
void mtx_sdxcpm_device::device_add_mconfig(machine_config &config)
{
/* fdc */
MB8877(config, m_fdc, 8_MHz_XTAL / 8);
m_fdc->hld_wr_callback().set(FUNC(mtx_sdx_device::motor_w));
FLOPPY_CONNECTOR(config, "fdc:0", sdx_floppies, "525qd", mtx_sdx_device::floppy_formats).enable_sound(true);
FLOPPY_CONNECTOR(config, "fdc:1", sdx_floppies, "525qd", mtx_sdx_device::floppy_formats).enable_sound(true);
/* 80 column video card - required to be installed in MTX internally */
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */
m_screen->set_refresh_hz(50);
m_screen->set_size(960, 313);
m_screen->set_visarea(00, 640 - 1, 0, 240 - 1);
m_screen->set_screen_update("crtc", FUNC(hd6845_device::screen_update));
GFXDECODE(config, "gfxdecode", "palette", gfx_mtx_sdx);
PALETTE(config, "palette", palette_device::RGB_3BIT);
HD6845(config, m_crtc, 15_MHz_XTAL / 8);
m_crtc->set_screen("screen");
m_crtc->set_show_border_area(false);
m_crtc->set_char_width(8);
m_crtc->set_update_row_callback(FUNC(mtx_sdxcpm_device::crtc_update_row), this);
}
const tiny_rom_entry *mtx_sdxbas_device::device_rom_region() const
{
return ROM_NAME( sdxbas );
}
const tiny_rom_entry *mtx_sdxcpm_device::device_rom_region() const
{
return ROM_NAME( sdxcpm );
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// mtx_sdx_device - constructor
//-------------------------------------------------
mtx_sdx_device::mtx_sdx_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, type, tag, owner, clock)
, device_mtx_exp_interface(mconfig, *this)
, m_sdx_rom(*this, "sdx_rom")
, m_fdc(*this, "fdc")
, m_floppy0(*this, "fdc:0")
, m_floppy1(*this, "fdc:1")
, m_dsw(*this, "DSW%u", 0)
{
}
mtx_sdxbas_device::mtx_sdxbas_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: mtx_sdx_device(mconfig, MTX_SDXBAS, tag, owner, clock)
{
}
mtx_sdxcpm_device::mtx_sdxcpm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: mtx_sdx_device(mconfig, MTX_SDXCPM, tag, owner, clock)
, m_screen(*this, "screen")
, m_palette(*this, "palette")
, m_crtc(*this, "crtc")
, m_char_rom(*this, "chargen")
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void mtx_sdxbas_device::device_start()
{
save_item(NAME(m_control));
}
void mtx_sdxcpm_device::device_start()
{
save_item(NAME(m_control));
save_item(NAME(m_80col_ascii));
save_item(NAME(m_80col_attr));
save_item(NAME(m_80col_addr));
save_item(NAME(m_80col_char_ram));
save_item(NAME(m_80col_attr_ram));
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void mtx_sdxbas_device::device_reset()
{
machine().root_device().membank("rommap_bank1")->configure_entry(3, m_sdx_rom->base());
/* SDX FDC */
io_space().install_readwrite_handler(0x10, 0x13, read8sm_delegate(FUNC(mb8877_device::read), m_fdc.target()), write8sm_delegate(FUNC(mb8877_device::write), m_fdc.target()));
io_space().install_readwrite_handler(0x14, 0x14, read8_delegate(FUNC(mtx_sdx_device::sdx_status_r), this), write8_delegate(FUNC(mtx_sdx_device::sdx_control_w), this));
}
void mtx_sdxcpm_device::device_reset()
{
machine().root_device().membank("rommap_bank1")->configure_entry(3, m_sdx_rom->base());
/* SDX FDC */
io_space().install_readwrite_handler(0x10, 0x13, read8sm_delegate(FUNC(mb8877_device::read), m_fdc.target()), write8sm_delegate(FUNC(mb8877_device::write), m_fdc.target()));
io_space().install_readwrite_handler(0x14, 0x14, read8_delegate(FUNC(mtx_sdx_device::sdx_status_r), this), write8_delegate(FUNC(mtx_sdx_device::sdx_control_w), this));
/* 80 column */
io_space().install_readwrite_handler(0x30, 0x33, read8_delegate(FUNC(mtx_sdxcpm_device::mtx_80col_r), this), write8_delegate(FUNC(mtx_sdxcpm_device::mtx_80col_w), this));
io_space().install_readwrite_handler(0x38, 0x38, read8smo_delegate(FUNC(mc6845_device::status_r), m_crtc.target()), write8smo_delegate(FUNC(mc6845_device::address_w), m_crtc.target()));
io_space().install_readwrite_handler(0x39, 0x39, read8smo_delegate(FUNC(mc6845_device::register_r), m_crtc.target()), write8smo_delegate(FUNC(mc6845_device::register_w), m_crtc.target()));
memset(m_80col_char_ram, 0, sizeof(m_80col_char_ram));
memset(m_80col_attr_ram, 0, sizeof(m_80col_attr_ram));
}
//**************************************************************************
// IMPLEMENTATION
//**************************************************************************
READ8_MEMBER(mtx_sdx_device::sdx_status_r)
{
/*
bit description
0 Head load: 1 - head load on drive
1 Double-sided: 1 if drive double-sided
2 TPI: 0 - 48 TPI drive. 1 - 96 TPI drive
3 Track stepping rate: 0 - 12ms, 1 - 6ms
4 No. of drives: 0 - 1 drive, 1 - 2 drives
5 Ready: 1 - drive ready
6 Interrupt: 1 - FDC interrupt request
7 Data request: 1 - FDC data request
*/
uint8_t data = 0x00;
data |= m_dsw[BIT(m_control, 0)].read_safe(0x0f) & 0x0f;
data |= (m_floppy0->get_device() && m_floppy1->get_device()) ? 0x10 : 0x00;
if (m_floppy)
data |= m_floppy->ready_r() ? 0x00 : 0x20;
data |= m_fdc->intrq_r() ? 0x40 : 0x00;
data |= m_fdc->drq_r() ? 0x80 : 0x00;
return data;
}
WRITE8_MEMBER(mtx_sdx_device::sdx_control_w)
{
/*
bit description
0 Drive select: 0 - drive A, 1 - drive B
1 Side select: 0 - side 0, 1 - side 1
2 Motor on: 1 - turns drive motor on
3 Motor ready: 1 - drive motor ready
4 Density: 0 - FM, 1 - MFM
*/
m_control = data;
/* bit 0: drive select */
m_floppy = BIT(data, 0) ? m_floppy1->get_device() : m_floppy0->get_device();
m_fdc->set_floppy(m_floppy);
if (m_floppy)
{
/* bit 1: side select */
m_floppy->ss_w(BIT(data, 1));
logerror("motor on %d\n", BIT(data, 2));
/* bit 2: motor on */
m_floppy->mon_w(!(BIT(data, 2) || m_fdc->hld_r()));
logerror("head load %d\n", m_fdc->hld_r());
/* bit 3: motor ready */
//if (BIT(data, 3))
//m_floppy->mon_w(!BIT(data, 2));
//m_floppy->mon_w(!BIT(data, 3));
logerror("motor ready %d\n", BIT(data, 3));
}
/* bit 4: density */
m_fdc->dden_w(!BIT(data, 4));
}
WRITE_LINE_MEMBER(mtx_sdx_device::motor_w)
{
if (m_floppy0->get_device()) m_floppy0->get_device()->mon_w(0);
if (m_floppy1->get_device()) m_floppy1->get_device()->mon_w(0);
}
//-------------------------------------------------
// 80 column video board
//-------------------------------------------------
READ8_MEMBER(mtx_sdxcpm_device::mtx_80col_r)
{
uint8_t data = 0xff;
switch (offset)
{
case 0:
/* ring the bell */
break;
case 2:
if (!BIT(m_80col_addr, 15))
data = m_80col_char_ram[m_80col_addr & 0x07ff];
break;
case 3:
if (!BIT(m_80col_addr, 15))
data = m_80col_attr_ram[m_80col_addr & 0x07ff];
break;
}
return data;
}
WRITE8_MEMBER(mtx_sdxcpm_device::mtx_80col_w)
{
switch (offset)
{
case 0:
m_80col_addr = (m_80col_addr & 0xff00) | data;
/* write to ram */
if (BIT(m_80col_addr, 15))
{
/* write enable ascii ram */
if (BIT(m_80col_addr, 14))
m_80col_char_ram[m_80col_addr & 0x07ff] = m_80col_ascii;
/* write enable attribute ram */
if (BIT(m_80col_addr, 13))
m_80col_attr_ram[m_80col_addr & 0x07ff] = m_80col_attr;
}
break;
case 1:
m_80col_addr = (data << 8) | (m_80col_addr & 0x00ff);
break;
case 2:
m_80col_ascii = data;
break;
case 3:
m_80col_attr = data;
break;
}
}
MC6845_UPDATE_ROW(mtx_sdxcpm_device::crtc_update_row)
{
const pen_t *pen = m_palette->pens();
for (int column = 0; column < x_count; column++)
{
uint8_t code = m_80col_char_ram[(ma + column) & 0x7ff];
uint8_t attr = m_80col_attr_ram[(ma + column) & 0x7ff];
offs_t addr = (code << 4) | (ra & 0x0f);
uint8_t data = m_char_rom->base()[addr];
if (column == cursor_x)
{
data = 0xff;
attr = 0x07;
}
for (int bit = 0; bit < 8; bit++)
{
int x = (column * 8) + bit;
int fg = attr & 0x07;
int bg = attr & 0x38;
int color = BIT(data, 7) ? fg : bg;
bitmap.pix32(y, x) = pen[de ? color : 0];
data <<= 1;
}
}
}

105
src/devices/bus/mtx/sdx.h Normal file
View File

@ -0,0 +1,105 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/**********************************************************************
MTX SDX Controller
**********************************************************************/
#ifndef MAME_BUS_MTX_EXP_SDX_H
#define MAME_BUS_MTX_EXP_SDX_H
#include "exp.h"
#include "imagedev/floppy.h"
#include "machine/wd_fdc.h"
#include "video/mc6845.h"
#include "formats/mtx_dsk.h"
#include "emupal.h"
#include "screen.h"
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class mtx_sdx_device :
public device_t,
public device_mtx_exp_interface
{
public:
DECLARE_FLOPPY_FORMATS(floppy_formats);
// optional information overrides
virtual ioport_constructor device_input_ports() const override;
DECLARE_READ8_MEMBER(sdx_status_r);
DECLARE_WRITE8_MEMBER(sdx_control_w);
DECLARE_WRITE_LINE_MEMBER(motor_w);
protected:
// construction/destruction
mtx_sdx_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
required_memory_region m_sdx_rom;
required_device<mb8877_device> m_fdc;
required_device<floppy_connector> m_floppy0;
required_device<floppy_connector> m_floppy1;
required_ioport_array<2> m_dsw;
floppy_image_device *m_floppy;
uint8_t m_control;
};
class mtx_sdxbas_device : public mtx_sdx_device
{
public:
// construction/destruction
mtx_sdxbas_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
// optional information overrides
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
};
class mtx_sdxcpm_device : public mtx_sdx_device
{
public:
// construction/destruction
mtx_sdxcpm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
// optional information overrides
virtual void device_add_mconfig(machine_config &config) override;
virtual const tiny_rom_entry *device_rom_region() const override;
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
private:
DECLARE_READ8_MEMBER(mtx_80col_r);
DECLARE_WRITE8_MEMBER(mtx_80col_w);
MC6845_UPDATE_ROW(crtc_update_row);
required_device<screen_device> m_screen;
required_device<palette_device> m_palette;
required_device<mc6845_device> m_crtc;
required_memory_region m_char_rom;
uint8_t m_80col_char_ram[0x800];
uint8_t m_80col_attr_ram[0x800];
uint8_t m_80col_ascii, m_80col_attr;
uint16_t m_80col_addr;
};
// device type definition
DECLARE_DEVICE_TYPE(MTX_SDXBAS, mtx_sdxbas_device)
DECLARE_DEVICE_TYPE(MTX_SDXCPM, mtx_sdxcpm_device)
#endif // MAME_BUS_MTX_EXP_SDX_H

View File

@ -0,0 +1,53 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/***************************************************************************
Memotech MTX
Disk image format
***************************************************************************/
#include "mtx_dsk.h"
mtx_format::mtx_format() : wd177x_format(formats)
{
}
const char *mtx_format::name() const
{
return "mtx";
}
const char *mtx_format::description() const
{
return "Memotech MTX disk image";
}
const char *mtx_format::extensions() const
{
return "mfloppy";
}
const mtx_format::format mtx_format::formats[] =
{
{ // 320k 5 1/4 inch double density single sided (Type 03)
floppy_image::FF_525, floppy_image::DSDD, floppy_image::MFM,
2000, 16, 40, 2, 256, {}, 1, {}, 32, 22, 54
},
{ // 640k 5 1/4 inch double density double sided (Type 07)
floppy_image::FF_525, floppy_image::DSQD, floppy_image::MFM,
2000, 16, 80, 2, 256, {}, 1, {}, 32, 22, 54
},
{ // 320k 3 1/2 inch double density single sided (Type 03)
floppy_image::FF_35, floppy_image::DSDD, floppy_image::MFM,
2000, 16, 40, 2, 256, {}, 1, {}, 32, 22, 54
},
{ // 640k 3 1/2 inch double density double sided (Type 07)
floppy_image::FF_35, floppy_image::DSQD, floppy_image::MFM,
2000, 16, 80, 2, 256, {}, 1, {}, 32, 22, 54
},
{}
};
const floppy_format_type FLOPPY_MTX_FORMAT = &floppy_image_format_creator<mtx_format>;

33
src/lib/formats/mtx_dsk.h Normal file
View File

@ -0,0 +1,33 @@
// license:BSD-3-Clause
// copyright-holders:Nigel Barnes
/***************************************************************************
Memotech MTX
Disk image format
***************************************************************************/
#pragma once
#ifndef __MTX_DSK_H__
#define __MTX_DSK_H__
#include "wd177x_dsk.h"
class mtx_format : public wd177x_format
{
public:
mtx_format();
virtual const char *name() const override;
virtual const char *description() const override;
virtual const char *extensions() const override;
private:
static const format formats[];
};
extern const floppy_format_type FLOPPY_MTX_FORMAT;
#endif // __MTX_DSK_H__

View File

@ -11,8 +11,7 @@
TODO:
- cassette
- cartridges
- SDX/FDX floppy
- FDX floppy
- HDX hard disk
- HRX high resolution graphics
- "Silicon" disks
@ -24,14 +23,8 @@
#include "includes/mtx.h"
#include "bus/centronics/ctronics.h"
#include "cpu/z80/z80.h"
#include "machine/z80daisy.h"
#include "imagedev/cassette.h"
#include "imagedev/snapquik.h"
#include "machine/ram.h"
#include "machine/z80ctc.h"
#include "machine/z80dart.h"
#include "sound/sn76496.h"
#include "video/tms9928a.h"
#include "softlist.h"
@ -64,7 +57,7 @@ void mtx_state::mtx_io(address_map &map)
map(0x04, 0x04).r(FUNC(mtx_state::mtx_prt_r)).w("cent_data_out", FUNC(output_latch_device::bus_w));
map(0x05, 0x05).rw(FUNC(mtx_state::mtx_key_lo_r), FUNC(mtx_state::mtx_sense_w));
map(0x06, 0x06).rw(FUNC(mtx_state::mtx_key_hi_r), FUNC(mtx_state::mtx_sound_latch_w));
// map(0x07, 0x07) PIO
// map(0x07, 0x07) PIO
map(0x08, 0x0b).rw(m_z80ctc, FUNC(z80ctc_device::read), FUNC(z80ctc_device::write));
map(0x1f, 0x1f).w(FUNC(mtx_state::mtx_cst_motor_w));
map(0x30, 0x31).w(FUNC(mtx_state::hrx_address_w));
@ -202,6 +195,12 @@ static INPUT_PORTS_START( mtx512 )
PORT_DIPSETTING(0x08, DEF_STR(Off) )
PORT_DIPSETTING(0x00, DEF_STR(On) )
PORT_BIT( 0xf3, IP_ACTIVE_LOW, IPT_UNUSED)
PORT_START("keyboard_rom")
PORT_CONFNAME(0x03, 0x00, "Keyboard ROM")
PORT_CONFSETTING(0x00, "None")
PORT_CONFSETTING(0x01, "Denmark")
PORT_CONFSETTING(0x02, "Finland")
INPUT_PORTS_END
/***************************************************************************
@ -243,7 +242,7 @@ WRITE_LINE_MEMBER(mtx_state::ctc_trg2_w)
static const z80_daisy_config mtx_daisy_chain[] =
{
{ Z80CTC_TAG },
{ "z80ctc" },
{ nullptr }
};
@ -253,8 +252,8 @@ static const z80_daisy_config mtx_daisy_chain[] =
static const z80_daisy_config rs128_daisy_chain[] =
{
{ Z80CTC_TAG },
{ Z80DART_TAG },
{ "z80ctc" },
{ "z80dart" },
{ nullptr }
};
@ -283,19 +282,16 @@ WRITE_LINE_MEMBER(mtx_state::mtx_tms9929a_interrupt)
machine_config( mtx512 )
-------------------------------------------------*/
MACHINE_CONFIG_START(mtx_state::mtx512)
void mtx_state::mtx512(machine_config &config)
{
/* basic machine hardware */
Z80(config, m_maincpu, XTAL(4'000'000));
Z80(config, m_maincpu, 4_MHz_XTAL);
m_maincpu->set_addrmap(AS_PROGRAM, &mtx_state::mtx_mem);
m_maincpu->set_addrmap(AS_IO, &mtx_state::mtx_io);
m_maincpu->set_daisy_config(mtx_daisy_chain);
MCFG_MACHINE_START_OVERRIDE(mtx_state,mtx512)
MCFG_MACHINE_RESET_OVERRIDE(mtx_state,mtx512)
/* video hardware */
tms9929a_device &vdp(TMS9929A(config, "tms9929a", XTAL(10'738'635)));
tms9929a_device &vdp(TMS9929A(config, "tms9929a", 10.6875_MHz_XTAL));
vdp.set_screen("screen");
vdp.set_vram_size(0x4000);
vdp.int_callback().set(FUNC(mtx_state::mtx_tms9929a_interrupt));
@ -303,15 +299,15 @@ MACHINE_CONFIG_START(mtx_state::mtx512)
/* sound hardware */
SPEAKER(config, "mono").front_center();
SN76489A(config, SN76489A_TAG, XTAL(4'000'000)).add_route(ALL_OUTPUTS, "mono", 1.00);
SN76489A(config, m_sn, 4_MHz_XTAL).add_route(ALL_OUTPUTS, "mono", 1.00);
/* devices */
Z80CTC(config, m_z80ctc, XTAL(4'000'000));
Z80CTC(config, m_z80ctc, 4_MHz_XTAL);
m_z80ctc->intr_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
m_z80ctc->zc_callback<1>().set(FUNC(mtx_state::ctc_trg1_w));
m_z80ctc->zc_callback<2>().set(FUNC(mtx_state::ctc_trg2_w));
TIMER(config, "z80ctc_timer").configure_periodic(FUNC(mtx_state::ctc_tick), attotime::from_hz(XTAL(4'000'000)/13));
TIMER(config, "z80ctc_timer").configure_periodic(FUNC(mtx_state::ctc_tick), attotime::from_hz(4_MHz_XTAL/13));
CENTRONICS(config, m_centronics, centronics_devices, "printer");
m_centronics->busy_handler().set(FUNC(mtx_state::write_centronics_busy));
@ -322,7 +318,11 @@ MACHINE_CONFIG_START(mtx_state::mtx512)
output_latch_device &cent_data_out(OUTPUT_LATCH(config, "cent_data_out"));
m_centronics->set_output_latch(cent_data_out);
MCFG_SNAPSHOT_ADD("snapshot", mtx_state, mtx, "mtx", attotime::from_seconds(1))
snapshot_image_device &snapshot(SNAPSHOT(config, "snapshot"));
snapshot.set_handler(snapquick_load_delegate(&SNAPSHOT_LOAD_NAME(mtx_state, mtx), this), "mtx", attotime::from_seconds(1));
quickload_image_device &quickload(QUICKLOAD(config, "quickload"));
quickload.set_handler(snapquick_load_delegate(&QUICKLOAD_LOAD_NAME(mtx_state, mtx), this), "run", attotime::from_seconds(1));
CASSETTE(config, m_cassette);
m_cassette->set_default_state(CASSETTE_PLAY | CASSETTE_MOTOR_DISABLED | CASSETTE_SPEAKER_MUTED);
m_cassette->set_interface("mtx_cass");
@ -333,20 +333,25 @@ MACHINE_CONFIG_START(mtx_state::mtx512)
RAM(config, m_ram).set_default_size("64K").set_extra_options("96K,128K,192K,320K,448K,512K");
/* rom extension board */
MCFG_GENERIC_SOCKET_ADD("extrom", generic_plain_slot, "mtx_rom")
MCFG_GENERIC_EXTENSIONS("bin,rom")
MCFG_GENERIC_LOAD(mtx_state, extrom_load)
GENERIC_SOCKET(config, m_extrom, generic_plain_slot, "mtx_rom", "bin,rom");
m_extrom->set_device_load(device_image_load_delegate(&mtx_state::device_image_load_extrom_load, this));
/* rs232 board with disk drive bus */
MTX_EXP_SLOT(config, m_exp, mtx_expansion_devices, nullptr);
m_exp->int_handler().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
m_exp->nmi_handler().set_inputline(m_maincpu, INPUT_LINE_NMI);
m_exp->busreq_handler().set_inputline(m_maincpu, Z80_INPUT_LINE_BUSRQ);
/* cartridge slot */
MCFG_GENERIC_SOCKET_ADD("rompak", generic_plain_slot, "mtx_cart")
MCFG_GENERIC_EXTENSIONS("bin,rom")
MCFG_GENERIC_LOAD(mtx_state, rompak_load)
GENERIC_CARTSLOT(config, m_rompak, generic_plain_slot, "mtx_cart", "bin,rom");
m_rompak->set_device_load(device_image_load_delegate(&mtx_state::device_image_load_rompak_load, this));
/* software lists */
SOFTWARE_LIST(config, "cass_list").set_original("mtx_cass");
SOFTWARE_LIST(config, "flop_list").set_original("mtx_flop");
SOFTWARE_LIST(config, "cart_list").set_original("mtx_cart");
SOFTWARE_LIST(config, "rom_list").set_original("mtx_rom");
MACHINE_CONFIG_END
}
void mtx_state::mtx500(machine_config &config)
{
@ -369,7 +374,7 @@ void mtx_state::rs128(machine_config &config)
m_maincpu->set_daisy_config(rs128_daisy_chain);
/* devices */
Z80DART(config, m_z80dart, XTAL(4'000'000));
Z80DART(config, m_z80dart, 4_MHz_XTAL);
m_z80dart->out_int_callback().set_inputline(m_maincpu, INPUT_LINE_IRQ0);
/* internal ram */
@ -382,30 +387,23 @@ void mtx_state::rs128(machine_config &config)
ROM_START( mtx512 )
ROM_REGION( 0x02000, "user1", 0 )
ROM_LOAD( "osrom", 0x0000, 0x2000, CRC(9ca858cc) SHA1(3804503a58f0bcdea96bb6488833782ebd03976d) )
ROM_SYSTEM_BIOS( 0, "uk", "UK" )
ROMX_LOAD( "mtx1a.9h", 0x0000, 0x2000, CRC(9ca858cc) SHA1(3804503a58f0bcdea96bb6488833782ebd03976d), ROM_BIOS(0) ) /* OS */
ROM_SYSTEM_BIOS( 1, "de", "German" )
ROMX_LOAD( "mtx2a.9h", 0x0000, 0x2000, CRC(1c7bbe98) SHA1(8c950051b830e5e0c41072d6bd893151acd3839d), ROM_BIOS(1) ) /* OS */
ROM_REGION( 0x10000, "user2", ROMREGION_ERASEFF )
ROM_LOAD( "basicrom", 0x0000, 0x2000, CRC(87b4e59c) SHA1(c49782a82a7f068c1195cd967882ba9edd546eaf) )
ROM_LOAD( "assemrom", 0x2000, 0x2000, CRC(9d7538c3) SHA1(d1882c4ea61a68b1715bd634ded5603e18a99c5f) )
ROMX_LOAD( "mtx1b.8h", 0x0000, 0x2000, CRC(87b4e59c) SHA1(c49782a82a7f068c1195cd967882ba9edd546eaf), ROM_BIOS(0) ) /* BASIC */
ROMX_LOAD( "mtx1c.10h", 0x2000, 0x2000, CRC(9d7538c3) SHA1(d1882c4ea61a68b1715bd634ded5603e18a99c5f), ROM_BIOS(0) ) /* ASSEM */
ROMX_LOAD( "mtx2b.8h", 0x0000, 0x2000, CRC(599d5b6b) SHA1(3ec1f7f476a21ca3206012ded22198c020b47f7d), ROM_BIOS(1) ) /* BASIC */
ROMX_LOAD( "mtx1c.10h", 0x2000, 0x2000, CRC(9d7538c3) SHA1(d1882c4ea61a68b1715bd634ded5603e18a99c5f), ROM_BIOS(1) ) /* ASSEM */
/* Keyboard ROMs are piggy-backed on top of the OS ROM, wired to be selected as ROM 7 */
/* Keyboard PROMs (N82S181N) are piggy-backed on top of the OS ROM, wired to be selected as ROM 7 */
/* Country character sets documented in the Operators Manual are:
U.S.A, France, Germany, England, Denmark, Sweden, Italy, Spain */
ROM_DEFAULT_BIOS("us")
ROM_SYSTEM_BIOS( 0, "us", "U.S.A." )
ROM_SYSTEM_BIOS( 1, "dk", "Denmark" )
ROMX_LOAD( "danish.rom", 0xe000, 0x2000, CRC(9c1b3fae) SHA1(82bc021660d88eebcf0c4d3856558ee9acc1c348), ROM_BIOS(1) )
ROM_SYSTEM_BIOS( 2, "fi", "Finland" )
ROMX_LOAD( "finnish.rom", 0xe000, 0x2000, CRC(9b96cf72) SHA1(b46d1a733e0e635ccdaf4752cc370d793c3b5c55), ROM_BIOS(2) )
ROM_REGION( 0x2000, "sdx", 0 )
ROM_LOAD( "sdx", 0x0000, 0x2000, NO_DUMP )
ROM_REGION( 0x2000, "mtx", 0 )
ROM_LOAD( "sm2 fdcx1 v03", 0x0000, 0x2000, NO_DUMP )
ROM_REGION( 0x1000, MC6845_TAG, 0 )
ROM_LOAD( "80z.bin", 0x0000, 0x1000, CRC(ea6fe865) SHA1(f84883f79bed34501e5828336894fad929bddbb5) )
ROM_REGION( 0x4000, "keyboard_rom", 0 )
ROM_LOAD( "danish.rom", 0x0000, 0x2000, CRC(9c1b3fae) SHA1(82bc021660d88eebcf0c4d3856558ee9acc1c348) )
ROM_LOAD( "finnish.rom", 0x2000, 0x2000, CRC(9b96cf72) SHA1(b46d1a733e0e635ccdaf4752cc370d793c3b5c55) )
/* Device GAL16V8 converted from PAL14L4 JEDEC map */
ROM_REGION( 0x117, "plds", 0 )

View File

@ -14,35 +14,29 @@
#include "bus/centronics/ctronics.h"
#include "bus/generic/slot.h"
#include "bus/generic/carts.h"
#include "bus/mtx/exp.h"
#include "cpu/z80/z80.h"
#include "machine/z80daisy.h"
#include "machine/z80dart.h"
#include "machine/z80ctc.h"
#include "sound/sn76496.h"
#include "machine/ram.h"
#include "machine/timer.h"
#define Z80_TAG "z80"
#define Z80CTC_TAG "z80ctc"
#define Z80DART_TAG "z80dart"
#define FD1793_TAG "fd1793" // SDX
#define FD1791_TAG "fd1791" // FDX
#define SN76489A_TAG "sn76489a"
#define MC6845_TAG "mc6845"
#define SCREEN_TAG "screen"
#define CENTRONICS_TAG "centronics"
class mtx_state : public driver_device
{
public:
mtx_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_maincpu(*this, Z80_TAG)
, m_sn(*this, SN76489A_TAG)
, m_z80ctc(*this, Z80CTC_TAG)
, m_z80dart(*this, Z80DART_TAG)
, m_maincpu(*this, "z80")
, m_sn(*this, "sn76489a")
, m_z80ctc(*this, "z80ctc")
, m_z80dart(*this, "z80dart")
, m_cassette(*this, "cassette")
, m_centronics(*this, CENTRONICS_TAG)
, m_centronics(*this, "centronics")
, m_ram(*this, RAM_TAG)
, m_exp(*this, "exp")
, m_extrom(*this, "extrom")
, m_rompak(*this, "rompak")
{ }
@ -51,6 +45,10 @@ public:
void mtx500(machine_config &config);
void mtx512(machine_config &config);
protected:
virtual void machine_start() override;
virtual void machine_reset() override;
private:
required_device<z80_device> m_maincpu;
required_device<sn76489a_device> m_sn;
@ -59,6 +57,7 @@ private:
required_device<cassette_image_device> m_cassette;
required_device<centronics_device> m_centronics;
required_device<ram_device> m_ram;
required_device<mtx_exp_slot_device> m_exp;
required_device<generic_slot_device> m_extrom;
required_device<generic_slot_device> m_rompak;
@ -91,8 +90,6 @@ private:
DECLARE_WRITE8_MEMBER(hrx_data_w);
DECLARE_READ8_MEMBER(hrx_attr_r);
DECLARE_WRITE8_MEMBER(hrx_attr_w);
DECLARE_MACHINE_START(mtx512);
DECLARE_MACHINE_RESET(mtx512);
TIMER_DEVICE_CALLBACK_MEMBER(ctc_tick);
TIMER_DEVICE_CALLBACK_MEMBER(cassette_tick);
DECLARE_WRITE_LINE_MEMBER(ctc_trg1_w);
@ -110,7 +107,9 @@ private:
void bankswitch(uint8_t data);
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(extrom_load);
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(rompak_load);
DECLARE_QUICKLOAD_LOAD_MEMBER(mtx);
DECLARE_SNAPSHOT_LOAD_MEMBER(mtx);
void mtx_io(address_map &map);
void mtx_mem(address_map &map);
void rs128_io(address_map &map);

View File

@ -111,38 +111,20 @@ void mtx_state::bankswitch(uint8_t data)
program.install_readwrite_bank(0x8000, 0xbfff, "rammap_bank3");
/* set ram bank, for invalid pages a nop-handler will be installed */
switch (ram_page)
{
case 0:
if (ram_page * 0xc000 + 0x10000 <= m_ram->size())
membank("rammap_bank1")->set_entry(ram_page);
else
program.nop_readwrite(0x0000, 0x3fff);
if (ram_page * 0xc000 + 0xc000 <= m_ram->size())
membank("rammap_bank2")->set_entry(ram_page);
else
program.nop_readwrite(0x4000, 0x7fff);
if (ram_page * 0xc000 + 0x8000 <= m_ram->size())
membank("rammap_bank3")->set_entry(ram_page);
else
program.nop_readwrite(0x8000, 0xbfff);
break;
if ((ram_page == 0 && m_ram->size() > 0xc000) || (ram_page > 0 && m_ram->size() > 0x10000 + ram_page * 0xc000))
membank("rammap_bank1")->set_entry(ram_page);
else
program.nop_readwrite(0x0000, 0x3fff);
if ((ram_page == 0 && m_ram->size() > 0x8000) || (ram_page > 0 && m_ram->size() > 0x14000 + ram_page * 0xc000))
default:
if (ram_page * 0xc000 + 0x8000 <= m_ram->size())
membank("rammap_bank1")->set_entry(ram_page);
else
program.nop_readwrite(0x0000, 0x3fff);
if (ram_page * 0xc000 + 0xc000 <= m_ram->size())
membank("rammap_bank2")->set_entry(ram_page);
else
program.nop_readwrite(0x4000, 0x7fff);
if (ram_page * 0xc000 + 0x10000 <= m_ram->size())
membank("rammap_bank3")->set_entry(ram_page);
else
program.nop_readwrite(0x8000, 0xbfff);
break;
}
membank("rammap_bank2")->set_entry(ram_page);
else
program.nop_readwrite(0x4000, 0x7fff);
if ((ram_page == 0 && m_ram->size() > 0x4000) || (ram_page > 0 && m_ram->size() > 0x18000 + ram_page * 0xc000))
membank("rammap_bank3")->set_entry(ram_page);
else
program.nop_readwrite(0x8000, 0xbfff);
}
else
{
@ -158,11 +140,11 @@ void mtx_state::bankswitch(uint8_t data)
membank("rommap_bank1")->set_entry(rom_page);
/* set ram bank, for invalid pages a nop-handler will be installed */
if (ram_page * 0x8000 + 0xc000 <= m_ram->size())
if ((ram_page == 0 && m_ram->size() > 0x8000) || (ram_page > 0 && m_ram->size() > 0x10000 + ram_page * 0x8000))
membank("rommap_bank2")->set_entry(ram_page);
else
program.nop_readwrite(0x4000, 0x7fff);
if (ram_page * 0x8000 + 0x8000 <= m_ram->size())
if ((ram_page == 0 && m_ram->size() > 0x4000) || (ram_page == 1 && m_ram->size() > 0xc000) || (ram_page > 1 && m_ram->size() > 0x14000 + ram_page * 0x8000))
membank("rommap_bank3")->set_entry(ram_page);
else
program.nop_readwrite(0x8000, 0xbfff);
@ -208,7 +190,16 @@ WRITE8_MEMBER(mtx_state::mtx_cst_w)
WRITE8_MEMBER(mtx_state::mtx_cst_motor_w)
{
m_cassette->change_state(data ? CASSETTE_MOTOR_ENABLED : CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR);
/* supported in the MTX ROM */
switch (data)
{
case 0xaa:
m_cassette->change_state(CASSETTE_MOTOR_ENABLED, CASSETTE_MASK_MOTOR);
break;
case 0x55:
m_cassette->change_state(CASSETTE_MOTOR_DISABLED, CASSETTE_MASK_MOTOR);
break;
}
}
/*-------------------------------------------------
@ -453,14 +444,10 @@ DEVICE_IMAGE_LOAD_MEMBER( mtx_state, rompak_load )
SNAPSHOT_LOAD_MEMBER( mtx_state, mtx )
{
address_space &program = m_maincpu->space(AS_PROGRAM);
void *ptr;
uint8_t header[18];
// read header
image.fread(&header, sizeof(header));
uint8_t *data = (uint8_t*)image.ptr();
// verify first byte
if (header[0] != 0xff)
if (data[0] != 0xff)
{
image.seterror(IMAGE_ERROR_INVALIDIMAGE, nullptr);
return image_init_result::FAIL;
@ -468,41 +455,78 @@ SNAPSHOT_LOAD_MEMBER( mtx_state, mtx )
// get tape name
char tape_name[16];
memcpy(&tape_name, &header[1], 15);
memcpy(&tape_name, &data[1], 15);
tape_name[15] = '\0';
image.message("Loading '%s'", tape_name);
// reset memory map
bankswitch(0);
// start of system variables area
uint16_t system_variables_base = pick_integer_le(header, 16, 2);
uint16_t system_variables_base = pick_integer_le(data, 16, 2);
// write system variables
uint16_t system_variables_size = 0;
if (system_variables_base != 0)
{
ptr = program.get_write_ptr(system_variables_base);
system_variables_size = 0xfb4b - system_variables_base;
image.fread(ptr, system_variables_size);
for (int i = 0; i < system_variables_size; i++)
program.write_byte(system_variables_base + i, data[18 + i]);
}
// write actual image data
uint16_t data_size = snapshot_size - 18 - system_variables_size;
ptr = program.get_write_ptr(0x4000);
image.fread(ptr, 0x4000);
// if we cross the page boundary, get a new write pointer and write the rest
if (data_size > 0x4000)
{
ptr = program.get_write_ptr(0x8000);
image.fread(ptr, 0x4000);
}
for (int i = 0; i < data_size; i++)
program.write_byte(0x4000 + i, data[18 + system_variables_size + i]);
logerror("snapshot name = '%s', system_size = 0x%04x, data_size = 0x%04x\n", tape_name, system_variables_size, data_size);
return image_init_result::PASS;
}
/***************************************************************************
QUICKLOAD
***************************************************************************/
QUICKLOAD_LOAD_MEMBER(mtx_state, mtx)
{
address_space &program = m_maincpu->space(AS_PROGRAM);
uint8_t *data = (uint8_t*)image.ptr();
if (quickload_size < 4)
{
image.seterror(IMAGE_ERROR_INVALIDIMAGE, "File too short");
return image_init_result::FAIL;
}
uint16_t code_base = pick_integer_le(data, 0, 2);
uint16_t code_length = pick_integer_le(data, 2, 2);
if (quickload_size < code_length)
{
image.seterror(IMAGE_ERROR_INVALIDIMAGE, "File too short");
return image_init_result::FAIL;
}
if (code_base < 0x4000 || (code_base + code_length) >= 0x10000)
{
image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Invalid code base and length");
return image_init_result::FAIL;
}
// reset memory map
bankswitch(0);
// write image data
for (int i = 0; i < code_length; i++)
program.write_byte(code_base + i, data[4 + i]);
m_maincpu->set_pc(code_base);
return image_init_result::PASS;
}
/***************************************************************************
MACHINE INITIALIZATION
***************************************************************************/
@ -511,7 +535,7 @@ SNAPSHOT_LOAD_MEMBER( mtx_state, mtx )
MACHINE_START( mtx512 )
-------------------------------------------------*/
MACHINE_START_MEMBER(mtx_state, mtx512)
void mtx_state::machine_start()
{
address_space &program = m_maincpu->space(AS_PROGRAM);
@ -521,12 +545,11 @@ MACHINE_START_MEMBER(mtx_state, mtx512)
program.install_readwrite_bank(0x8000, 0xbfff, "rommap_bank3");
membank("rommap_bank1")->configure_entries(0, 8, memregion("user2")->base(), 0x2000);
if (m_extrom->exists())
membank("rommap_bank1")->configure_entry(2, m_extrom->get_rom_base());
if (m_rompak->exists())
membank("rommap_bank1")->configure_entry(7, m_rompak->get_rom_base());
membank("rommap_bank2")->configure_entries(0, 16, m_ram->pointer() + 0x8000, 0x8000);
membank("rommap_bank3")->configure_entries(0, 16, m_ram->pointer() + 0x4000, 0x8000);
membank("rommap_bank2")->configure_entry(0, m_ram->pointer() + 0x8000);
membank("rommap_bank2")->configure_entries(1, 15, m_ram->pointer() + 0x10000, 0x8000);
membank("rommap_bank3")->configure_entry(0, m_ram->pointer() + 0x4000);
membank("rommap_bank3")->configure_entry(1, m_ram->pointer() + 0xc000);
membank("rommap_bank3")->configure_entries(2, 14, m_ram->pointer() + 0x14000, 0x8000);
/* setup banks for ram based memory map */
program.install_readwrite_bank(0x0000, 0x3fff, "rammap_bank1");
@ -542,10 +565,24 @@ MACHINE_START_MEMBER(mtx_state, mtx512)
/* install 4000h bytes common block */
program.install_ram(0xc000, 0xffff, m_ram->pointer());
/* setup expansion slot */
m_exp->set_program_space(&m_maincpu->space(AS_PROGRAM));
m_exp->set_io_space(&m_maincpu->space(AS_IO));
}
MACHINE_RESET_MEMBER(mtx_state, mtx512)
void mtx_state::machine_reset()
{
/* extension board ROMs */
if (m_extrom->exists())
membank("rommap_bank1")->configure_entry(2, m_extrom->get_rom_base());
/* keyboard ROMs */
if (ioport("keyboard_rom")->read())
membank("rommap_bank1")->configure_entry(7, memregion("keyboard_rom")->base() + (ioport("keyboard_rom")->read() - 1) * 0x2000);
/* rompak ROMs */
if (m_rompak->exists())
membank("rommap_bank1")->configure_entry(7, m_rompak->get_rom_base());
/* bank switching */
bankswitch(0);
}