mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
mtu130: Add support for the datamover (68k board)
This commit is contained in:
parent
39aa2cd864
commit
2da17be127
@ -4950,3 +4950,18 @@ if (BUSES["PC8801"]~=null) then
|
||||
MAME_DIR .. "src/devices/bus/pc8801/jmbx1.h",
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/bus/mtu130/board.h,BUSES["MTU130"] = true
|
||||
---------------------------------------------------
|
||||
|
||||
if (BUSES["MTU130"]~=null) then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/bus/mtu130/board.cpp",
|
||||
MAME_DIR .. "src/devices/bus/mtu130/board.h",
|
||||
MAME_DIR .. "src/devices/bus/mtu130/datamover.cpp",
|
||||
MAME_DIR .. "src/devices/bus/mtu130/datamover.h",
|
||||
}
|
||||
end
|
||||
|
||||
|
37
src/devices/bus/mtu130/board.cpp
Normal file
37
src/devices/bus/mtu130/board.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Olivier Galibert
|
||||
|
||||
// MTU-130 extension board
|
||||
|
||||
#include "emu.h"
|
||||
#include "board.h"
|
||||
|
||||
DEFINE_DEVICE_TYPE(MTU130_EXTENSION, mtu130_extension_device, "mtu130_extension", "MTU130 extension board slot")
|
||||
|
||||
mtu130_extension_device::mtu130_extension_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
|
||||
device_t(mconfig, MTU130_EXTENSION, tag, owner, clock),
|
||||
device_single_card_slot_interface<mtu130_extension_interface>(mconfig, *this),
|
||||
m_irq_merger(*this, finder_base::DUMMY_TAG)
|
||||
{
|
||||
}
|
||||
|
||||
void mtu130_extension_device::map_io(address_space_installer &space)
|
||||
{
|
||||
auto dev = get_card_device();
|
||||
if(dev)
|
||||
dev->map_io(space);
|
||||
}
|
||||
|
||||
void mtu130_extension_device::device_start()
|
||||
{
|
||||
}
|
||||
|
||||
mtu130_extension_interface::mtu130_extension_interface(const machine_config &mconfig, device_t &device) :
|
||||
device_interface(device, "extension_board")
|
||||
{
|
||||
}
|
||||
|
||||
void mtu130_extension_interface::set_irq(bool state) const
|
||||
{
|
||||
downcast<mtu130_extension_device *>(device().owner())->set_irq(state);
|
||||
}
|
69
src/devices/bus/mtu130/board.h
Normal file
69
src/devices/bus/mtu130/board.h
Normal file
@ -0,0 +1,69 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Olivier Galibert
|
||||
|
||||
// MTU-130 extension board
|
||||
|
||||
#ifndef MAME_BUS_MTU130_EXTENSION_H
|
||||
#define MAME_BUS_MTU130_EXTENSION_H
|
||||
|
||||
#include "machine/input_merger.h"
|
||||
|
||||
class mtu130_extension_interface : public device_interface
|
||||
{
|
||||
public:
|
||||
mtu130_extension_interface(const machine_config &mconfig, device_t &device);
|
||||
virtual ~mtu130_extension_interface() = default;
|
||||
|
||||
// Read/write on banks 2/3
|
||||
virtual void write23(offs_t offset, u8 data) = 0;
|
||||
virtual u8 read23(offs_t offset) = 0;
|
||||
|
||||
// Map i/o in the bfxx area.
|
||||
virtual void map_io(address_space_installer &space) = 0;
|
||||
|
||||
void set_irq(bool state) const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class mtu130_extension_device : public device_t, public device_single_card_slot_interface<mtu130_extension_interface>
|
||||
{
|
||||
public:
|
||||
mtu130_extension_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
|
||||
virtual ~mtu130_extension_device() = default;
|
||||
|
||||
// Configuration
|
||||
void set_slot_id(u8 slot_id) { m_slot_id = slot_id; }
|
||||
template<class T> void set_irq_merger(T &&tag) { m_irq_merger.set_tag(std::forward<T>(tag)); }
|
||||
|
||||
// Read/write on banks 2/3, read return 0xff if not driven
|
||||
void write23(offs_t offset, u8 data) {
|
||||
auto dev = get_card_device();
|
||||
if(dev)
|
||||
dev->write23(offset, data);
|
||||
}
|
||||
|
||||
u8 read23(offs_t offset) {
|
||||
auto dev = get_card_device();
|
||||
return dev ? dev->read23(offset) : 0xff;
|
||||
}
|
||||
|
||||
void map_io(address_space_installer &space);
|
||||
|
||||
void set_irq(bool state) const {
|
||||
switch(m_slot_id) {
|
||||
case 0: m_irq_merger->in_w<10>(state); break;
|
||||
case 1: m_irq_merger->in_w<11>(state); break;
|
||||
case 2: m_irq_merger->in_w<12>(state); break;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
required_device<input_merger_device> m_irq_merger;
|
||||
u8 m_slot_id;
|
||||
virtual void device_start() override;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(MTU130_EXTENSION, mtu130_extension_device)
|
||||
|
||||
#endif
|
171
src/devices/bus/mtu130/datamover.cpp
Normal file
171
src/devices/bus/mtu130/datamover.cpp
Normal file
@ -0,0 +1,171 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Olivier Galibert
|
||||
|
||||
// Datamover - 68K-based extension board
|
||||
|
||||
#include "datamover.h"
|
||||
|
||||
DEFINE_DEVICE_TYPE(MTU130_DATAMOVER0, mtu130_datamover0_device, "datamover0", "Datamover")
|
||||
DEFINE_DEVICE_TYPE(MTU130_DATAMOVER1, mtu130_datamover1_device, "datamover1", "Datamover (alt address)")
|
||||
|
||||
mtu130_datamover0_device::mtu130_datamover0_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
|
||||
mtu130_datamover_base_device(mconfig, MTU130_DATAMOVER0, tag, owner, 0xbfbe, clock)
|
||||
{
|
||||
}
|
||||
|
||||
mtu130_datamover1_device::mtu130_datamover1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
|
||||
mtu130_datamover_base_device(mconfig, MTU130_DATAMOVER1, tag, owner, 0xbfbc, clock)
|
||||
{
|
||||
}
|
||||
|
||||
mtu130_datamover_base_device::mtu130_datamover_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t base_address, uint32_t clock) :
|
||||
device_t(mconfig, type, tag, owner, clock),
|
||||
mtu130_extension_interface(mconfig, *this),
|
||||
m_cpu(*this, "cpu"),
|
||||
m_ram(*this, "ram"),
|
||||
m_base_address(base_address)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void mtu130_datamover_base_device::write23(offs_t offset, u8 data)
|
||||
{
|
||||
if(!m_ram_visible)
|
||||
return;
|
||||
if(m_ram_xor)
|
||||
offset ^= 1;
|
||||
offset |= m_ram_bank << 17;
|
||||
if(offset & 1)
|
||||
m_ram[offset >> 1] = (m_ram[offset >> 1] & 0xff00) | data;
|
||||
else
|
||||
m_ram[offset >> 1] = (m_ram[offset >> 1] & 0x00ff) | (data << 8);
|
||||
}
|
||||
|
||||
u8 mtu130_datamover_base_device::read23(offs_t offset)
|
||||
{
|
||||
if(!m_ram_visible)
|
||||
return 0xff;
|
||||
if(m_ram_xor)
|
||||
offset ^= 1;
|
||||
offset |= m_ram_bank << 17;
|
||||
if(offset & 1)
|
||||
return m_ram[offset >> 1];
|
||||
else
|
||||
return m_ram[offset >> 1] >> 8;
|
||||
|
||||
}
|
||||
|
||||
void mtu130_datamover_base_device::map_io(address_space_installer &space)
|
||||
{
|
||||
space.install_device(m_base_address, m_base_address+1, *this, &mtu130_datamover_base_device::m6502_map);
|
||||
}
|
||||
|
||||
void mtu130_datamover_base_device::device_start()
|
||||
{
|
||||
save_item(NAME(m_ram_visible));
|
||||
save_item(NAME(m_ram_xor));
|
||||
save_item(NAME(m_ram_bank));
|
||||
save_item(NAME(m_irq4_req));
|
||||
save_item(NAME(m_irq7_req));
|
||||
save_item(NAME(m_irq6502_req));
|
||||
save_item(NAME(m_irq6502_en));
|
||||
}
|
||||
|
||||
void mtu130_datamover_base_device::device_reset()
|
||||
{
|
||||
m_cpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
|
||||
m_cpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
|
||||
|
||||
m_ram_visible = true;
|
||||
m_ram_xor = false;
|
||||
m_ram_bank = 0;
|
||||
m_irq4_req = false;
|
||||
m_irq7_req = false;
|
||||
m_irq6502_req = false;
|
||||
m_irq6502_en = false;
|
||||
}
|
||||
|
||||
|
||||
void mtu130_datamover_base_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
M68000(config, m_cpu, 10_MHz_XTAL/10*8);
|
||||
m_cpu->set_addrmap(AS_PROGRAM, &mtu130_datamover_base_device::m68k_map);
|
||||
m_cpu->set_addrmap(m68000_device::AS_CPU_SPACE, &mtu130_datamover_base_device::m68k_cs_map);
|
||||
}
|
||||
|
||||
void mtu130_datamover_base_device::m6502_map(address_map &map)
|
||||
{
|
||||
map(0, 0).r(FUNC(mtu130_datamover_base_device::status_r)).w(FUNC(mtu130_datamover_base_device::control_w));
|
||||
map(1, 1).w(FUNC(mtu130_datamover_base_device::enable_w));
|
||||
}
|
||||
|
||||
void mtu130_datamover_base_device::m68k_map(address_map &map)
|
||||
{
|
||||
map(0x000000, 0x0fffff).ram().share(m_ram);
|
||||
map(0x100001, 0x100001).rw(FUNC(mtu130_datamover_base_device::irq_req_r), FUNC(mtu130_datamover_base_device::irq_req_w));
|
||||
}
|
||||
|
||||
void mtu130_datamover_base_device::m68k_cs_map(address_map &map)
|
||||
{
|
||||
map(0xfffff3, 0xfffff3).lr8(NAME([] () -> u8 { return 0x19; }));
|
||||
map(0xfffff5, 0xfffff5).lr8(NAME([] () -> u8 { return 0x1a; }));
|
||||
map(0xfffff7, 0xfffff7).lr8(NAME([] () -> u8 { return 0x1b; }));
|
||||
map(0xfffff9, 0xfffff9).lr8(NAME([this] () -> u8 { m_irq4_req = false; m_cpu->set_input_line(4, CLEAR_LINE); return 0x1c; }));
|
||||
map(0xfffffb, 0xfffffb).lr8(NAME([] () -> u8 { return 0x1d; }));
|
||||
map(0xfffffd, 0xfffffd).lr8(NAME([] () -> u8 { return 0x1e; }));
|
||||
map(0xffffff, 0xffffff).lr8(NAME([this] () -> u8 { m_irq7_req = false; m_cpu->set_input_line(7, CLEAR_LINE); return 0x1f; }));
|
||||
}
|
||||
|
||||
void mtu130_datamover_base_device::control_w(u8 data)
|
||||
{
|
||||
if(data & 0x80)
|
||||
m_irq6502_req = false;
|
||||
|
||||
if(data & 0x40)
|
||||
m_irq4_req = true;
|
||||
|
||||
m_irq6502_en = data & 0x20;
|
||||
|
||||
if(data & 0x10)
|
||||
m_irq7_req = true;
|
||||
|
||||
m_cpu->set_input_line(INPUT_LINE_HALT, data & 0x08 ? CLEAR_LINE : ASSERT_LINE);
|
||||
m_cpu->set_input_line(INPUT_LINE_RESET, data & 0x04 ? CLEAR_LINE : ASSERT_LINE);
|
||||
|
||||
if(!(data & 0x04))
|
||||
m_irq4_req = m_irq7_req = m_irq6502_req = false;
|
||||
|
||||
m_ram_xor = data & 0x02;
|
||||
|
||||
set_irq(m_irq6502_req && m_irq6502_en);
|
||||
m_cpu->set_input_line(4, m_irq4_req ? ASSERT_LINE : CLEAR_LINE);
|
||||
m_cpu->set_input_line(7, m_irq7_req ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
|
||||
void mtu130_datamover_base_device::irq_req_w(u8 data)
|
||||
{
|
||||
m_irq6502_req = data & 0x01;
|
||||
set_irq(m_irq6502_req && m_irq6502_en);
|
||||
}
|
||||
|
||||
u8 mtu130_datamover_base_device::irq_req_r()
|
||||
{
|
||||
return m_irq6502_req;
|
||||
}
|
||||
|
||||
void mtu130_datamover_base_device::enable_w(u8 data)
|
||||
{
|
||||
m_ram_visible = !(data & 8);
|
||||
m_ram_bank = data & 7;
|
||||
}
|
||||
|
||||
u8 mtu130_datamover_base_device::status_r()
|
||||
{
|
||||
return
|
||||
(m_irq6502_req ? 0x80 : 0x00) |
|
||||
(m_irq4_req ? 0x40 : 0x00) |
|
||||
(m_irq6502_en ? 0x20 : 0x00) |
|
||||
(m_cpu->input_state(INPUT_LINE_HALT) ? 0x00 : 0x10) |
|
||||
(m_ram_visible ? 0x00 : 0x08) |
|
||||
m_ram_bank;
|
||||
}
|
72
src/devices/bus/mtu130/datamover.h
Normal file
72
src/devices/bus/mtu130/datamover.h
Normal file
@ -0,0 +1,72 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Olivier Galibert
|
||||
|
||||
// Datamover - 68K-based extension board
|
||||
|
||||
#ifndef MAME_BUS_MTU130_DATAMOVER_H
|
||||
#define MAME_BUS_MTU130_DATAMOVER_H
|
||||
|
||||
#include "board.h"
|
||||
#include "cpu/m68000/m68000.h"
|
||||
|
||||
class mtu130_datamover_base_device : public device_t, public mtu130_extension_interface
|
||||
{
|
||||
public:
|
||||
mtu130_datamover_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t base_address, uint32_t clock = 0);
|
||||
virtual ~mtu130_datamover_base_device() = default;
|
||||
|
||||
virtual void write23(offs_t offset, u8 data) override;
|
||||
virtual u8 read23(offs_t offset) override;
|
||||
|
||||
virtual void map_io(address_space_installer &space) override;
|
||||
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
protected:
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
|
||||
private:
|
||||
required_device<m68000_device> m_cpu;
|
||||
required_shared_ptr<u16> m_ram;
|
||||
|
||||
bool m_ram_visible;
|
||||
bool m_ram_xor;
|
||||
u8 m_ram_bank;
|
||||
bool m_irq4_req;
|
||||
bool m_irq7_req;
|
||||
bool m_irq6502_req;
|
||||
bool m_irq6502_en;
|
||||
|
||||
uint32_t m_base_address;
|
||||
|
||||
void m6502_map(address_map &map);
|
||||
void m68k_map(address_map &map);
|
||||
void m68k_cs_map(address_map &map);
|
||||
|
||||
void control_w(u8 data);
|
||||
void enable_w(u8 data);
|
||||
u8 status_r();
|
||||
|
||||
void irq_req_w(u8 data);
|
||||
u8 irq_req_r();
|
||||
};
|
||||
|
||||
class mtu130_datamover0_device : public mtu130_datamover_base_device
|
||||
{
|
||||
public:
|
||||
mtu130_datamover0_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
|
||||
virtual ~mtu130_datamover0_device() = default;
|
||||
};
|
||||
|
||||
class mtu130_datamover1_device : public mtu130_datamover_base_device
|
||||
{
|
||||
public:
|
||||
mtu130_datamover1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
|
||||
virtual ~mtu130_datamover1_device() = default;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(MTU130_DATAMOVER0, mtu130_datamover0_device)
|
||||
DECLARE_DEVICE_TYPE(MTU130_DATAMOVER1, mtu130_datamover1_device)
|
||||
|
||||
#endif
|
@ -6,6 +6,9 @@
|
||||
// Silently boots to floppy, so nothing will happen if you don't have
|
||||
// a bootable disk in the drive.
|
||||
|
||||
// The backplane has 5 slots, one if which is used by the main cpu
|
||||
// card, the Monomeg, and one by the FDC card.
|
||||
|
||||
// Unimplemented:
|
||||
// - MTUTAPE, a kind of digital tape?
|
||||
// - MTUNET, some proprietary network
|
||||
@ -13,15 +16,15 @@
|
||||
// - Sound on user via cb2, it's weird
|
||||
// - Light pen, need working demo code
|
||||
|
||||
// Unimplemented extension boards:
|
||||
// Implemented extension boards:
|
||||
// - DATAMOVER, a 68k-based board, used by BASIC 1.5 to accelerate floating point operations
|
||||
|
||||
// Unimplemented extension boards:
|
||||
// - PROGRAMMOVER, a z80-based board
|
||||
// - MultI-O, an i/o board
|
||||
|
||||
// Need to add the extra PROMs once they're dumped.
|
||||
|
||||
// Note that we hardcoded the ram in bank 3 BASIC 1.5 needs, it should
|
||||
// be added by DATAMOVER (or PROGRAMMOVER after some reconfiguration).
|
||||
|
||||
// Probable bug somewhere making the BASIC (light pen, game) demos
|
||||
// fail in the demonstration disk, possibly in the customized 6502
|
||||
// core.
|
||||
@ -34,6 +37,8 @@
|
||||
#include "machine/mos6551.h"
|
||||
#include "machine/upd765.h"
|
||||
#include "bus/rs232/rs232.h"
|
||||
#include "bus/mtu130/board.h"
|
||||
#include "bus/mtu130/datamover.h"
|
||||
#include "sound/dac.h"
|
||||
#include "emupal.h"
|
||||
#include "screen.h"
|
||||
@ -53,6 +58,7 @@ public:
|
||||
m_rs232(*this, "rs232"),
|
||||
m_fdc(*this, "fdc"),
|
||||
m_floppy(*this, "fdc:%d", 0U),
|
||||
m_ext(*this, "ext%d", 0U),
|
||||
m_screen(*this, "screen"),
|
||||
m_palette(*this, "palette"),
|
||||
m_dac(*this, "dac"),
|
||||
@ -88,6 +94,7 @@ private:
|
||||
required_device<rs232_port_device> m_rs232;
|
||||
required_device<upd765a_device> m_fdc;
|
||||
required_device_array<floppy_connector, 4> m_floppy;
|
||||
required_device_array<mtu130_extension_device, 3> m_ext;
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<palette_device> m_palette;
|
||||
required_device<dac_byte_interface> m_dac;
|
||||
@ -115,6 +122,7 @@ private:
|
||||
|
||||
static void floppies(device_slot_interface &device);
|
||||
void map(address_map &map);
|
||||
void extension_board(machine_config &config, int slot_id, const char *tag, const char *def);
|
||||
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
|
||||
u8 fdc_ctrl_r();
|
||||
@ -162,6 +170,9 @@ void mtu130_state::machine_start()
|
||||
m_se_view.select(0);
|
||||
m_rom_view.disable();
|
||||
m_rof_view.disable();
|
||||
|
||||
for(auto e : m_ext)
|
||||
e->map_io(m_io_view[1]);
|
||||
}
|
||||
|
||||
void mtu130_state::video_start()
|
||||
@ -382,7 +393,8 @@ void mtu130_state::map(address_map &map)
|
||||
|
||||
map(0x1c000, 0x1ffff).ram().share(m_videoram); // 16k of video ram
|
||||
|
||||
map(0x30000, 0x3ffff).ram(); // Basic 1.5 wants more ram, comes from an extension board
|
||||
map(0x20000, 0x3ffff).lrw8(NAME([this](offs_t offset) -> u8 { return m_ext[0]->read23(offset) & m_ext[1]->read23(offset) & m_ext[2]->read23(offset); }),
|
||||
NAME([this](offs_t offset, u8 data) { m_ext[0]->write23(offset, data); m_ext[1]->write23(offset, data); m_ext[2]->write23(offset, data); }));
|
||||
}
|
||||
|
||||
void mtu130_state::floppies(device_slot_interface &device)
|
||||
@ -391,8 +403,22 @@ void mtu130_state::floppies(device_slot_interface &device)
|
||||
device.option_add("8dsdd", FLOPPY_8_DSDD);
|
||||
}
|
||||
|
||||
void mtu130_state::extension_board(machine_config &config, int slot_id, const char *tag, const char *def)
|
||||
{
|
||||
MTU130_EXTENSION(config, m_ext[slot_id]);
|
||||
m_ext[slot_id]->set_slot_id(slot_id);
|
||||
m_ext[slot_id]->set_irq_merger(m_irq_merger);
|
||||
if(def)
|
||||
m_ext[slot_id]->set_default_option(def);
|
||||
|
||||
m_ext[slot_id]->option_add("datamover", MTU130_DATAMOVER0);
|
||||
m_ext[slot_id]->option_add("datamover_sec", MTU130_DATAMOVER1); // Datamover using secondary i/o addresses
|
||||
}
|
||||
|
||||
void mtu130_state::mtu130(machine_config &config)
|
||||
{
|
||||
config.set_perfect_quantum(m_maincpu); // Needs tight sync with the 68000 in the datamover
|
||||
|
||||
M6502MTU(config, m_maincpu, 10_MHz_XTAL/10);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &mtu130_state::map);
|
||||
|
||||
@ -442,6 +468,10 @@ void mtu130_state::mtu130(machine_config &config)
|
||||
|
||||
DAC_8BIT_R2R(config, m_dac, 0).add_route(ALL_OUTPUTS, m_speaker, 1.0);
|
||||
SPEAKER(config, m_speaker).front_center();
|
||||
|
||||
extension_board(config, 0, "ext0", "datamover");
|
||||
extension_board(config, 1, "ext1", nullptr);
|
||||
extension_board(config, 2, "ext2", nullptr);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user