bus/epson_qx, qx10.cpp: Added Epson QX-10 expansion bus. (#9241)

This commit is contained in:
Brian Johnson 2022-02-08 11:36:14 -05:00 committed by GitHub
parent 8f2247e1f2
commit 8b5307cee0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 579 additions and 23 deletions

View File

@ -3733,6 +3733,17 @@ if (BUSES["EPSON_SIO"]~=null) then
}
end
---------------------------------------------------
--
--@src/devices/bus/epson_qx/option.h,BUSES["EPSON_QX"] = true
---------------------------------------------------
if (BUSES["EPSON_QX"]~=null) then
files {
MAME_DIR .. "src/devices/bus/epson_qx/option.cpp",
MAME_DIR .. "src/devices/bus/epson_qx/option.h",
}
end
---------------------------------------------------
--
--@src/devices/bus/pce/pce_slot.h,BUSES["PCE"] = true

View File

@ -895,6 +895,7 @@ BUSES["ELECTRON_CART"] = true
BUSES["ELECTRON"] = true
BUSES["EP64"] = true
BUSES["EPSON_SIO"] = true
BUSES["EPSON_QX"] = true
BUSES["FMT_SCSI"] = true
BUSES["GAMATE"] = true
BUSES["GAMEBOY"] = true

View File

@ -0,0 +1,210 @@
// license:BSD-3-Clause
// copyright-holders:Brian Johnson
/*******************************************************************
*
* Epson QX-10 Expansion emulation
*
*******************************************************************/
#include "emu.h"
#include "option.h"
DEFINE_DEVICE_TYPE(EPSON_QX_OPTION_BUS_SLOT, bus::epson_qx::option_slot_device, "epson_qx_option_slot", "QX-10 Option slot")
DEFINE_DEVICE_TYPE(EPSON_QX_OPTION_BUS, bus::epson_qx::option_bus_device, "epson_qx_option_bus", "QX-10 Option Bus")
namespace bus::epson_qx {
//**************************************************************************
// EPSON SLOT DEVICE
//**************************************************************************
//-------------------------------------------------
// option_bus_slot_device - constructor
//-------------------------------------------------
option_slot_device::option_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, EPSON_QX_OPTION_BUS_SLOT, tag, owner, clock),
device_single_card_slot_interface<device_option_expansion_interface>(mconfig, *this),
m_bus(*this, finder_base::DUMMY_TAG),
m_dmas_w_cb(*this),
m_dmas_r_cb(*this),
m_dmaf_w_cb(*this),
m_dmaf_r_cb(*this),
m_eopf_cb(*this),
m_eops_cb(*this),
m_slot(-1)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void option_slot_device::device_start()
{
m_dmas_w_cb.resolve_safe();
m_dmas_r_cb.resolve_safe(0xff);
m_dmaf_w_cb.resolve();
m_dmaf_r_cb.resolve();
m_eopf_cb.resolve_safe();
m_eops_cb.resolve_safe();
device_option_expansion_interface *const intf(get_card_device());
if (intf) {
intf->set_option_bus(*m_bus, m_slot);
}
m_bus->add_slot(*this);
}
WRITE_LINE_MEMBER(option_slot_device::eopf) { m_eopf_cb(state); }
WRITE_LINE_MEMBER(option_slot_device::eops) { m_eops_cb(state); }
WRITE_LINE_MEMBER(option_slot_device::inth1_w) { (*m_bus).set_inth1_line(state, m_slot); }
WRITE_LINE_MEMBER(option_slot_device::inth2_w) { (*m_bus).set_inth2_line(state, m_slot); }
WRITE_LINE_MEMBER(option_slot_device::intl_w) { (*m_bus).set_intl_line(state, m_slot); }
WRITE_LINE_MEMBER(option_slot_device::drqf_w) { (*m_bus).set_drqf_line(state, m_slot); }
WRITE_LINE_MEMBER(option_slot_device::drqs_w) { (*m_bus).set_drqs_line(state, m_slot); }
WRITE_LINE_MEMBER(option_slot_device::rdyf_w) { (*m_bus).set_rdyf_line(state, m_slot); }
WRITE_LINE_MEMBER(option_slot_device::rdys_w) { (*m_bus).set_rdys_line(state, m_slot); }
//**************************************************************************
// EPSON OPTION BUS DEVICE
//**************************************************************************
//-------------------------------------------------
// option_bus_device - constructor
//-------------------------------------------------
option_bus_device::option_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, EPSON_QX_OPTION_BUS, tag, owner, clock),
m_iospace(*this, finder_base::DUMMY_TAG, -1),
m_inth1_cb(*this),
m_inth2_cb(*this),
m_intl_cb(*this),
m_drqf_cb(*this),
m_drqs_cb(*this),
m_rdyf_cb(*this),
m_rdys_cb(*this),
m_inth1(0),
m_inth2(0),
m_drqf(0),
m_rdyf(0),
m_rdys(0)
{
}
void option_bus_device::add_slot(option_slot_device &slot)
{
m_slot_list.push_back(&slot);
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void option_bus_device::device_start()
{
m_inth1_cb.resolve_safe();
m_inth2_cb.resolve_safe();
m_intl_cb.resolve_all_safe();
m_drqf_cb.resolve_safe();
m_drqs_cb.resolve_all_safe();
m_rdyf_cb.resolve_safe();
m_rdys_cb.resolve_safe();
}
//-------------------------------------------------
// device_reset - device-specific startup
//-------------------------------------------------
void option_bus_device::device_reset()
{
m_inth1 = 0;
m_inth2 = 0;
m_drqf = 0;
m_rdyf = 0;
m_rdys = 0;
}
void option_bus_device::dackf_w(uint8_t data)
{
for (int i = 0; i < m_slot_list.size(); ++i) {
if (!m_slot_list[i]->m_dmaf_w_cb.isnull()) {
m_slot_list[i]->m_dmaf_w_cb(data);
}
}
}
uint8_t option_bus_device::dackf_r()
{
uint8_t value = 0;
bool found = false;
for (int i = 0; i < m_slot_list.size(); ++i) {
if (!m_slot_list[i]->m_dmaf_r_cb.isnull()) {
found = true;
value |= m_slot_list[i]->m_dmaf_r_cb();
}
}
return (found ? value : 0xff);
}
void option_bus_device::set_inth1_line(uint8_t state, uint8_t slot)
{
m_inth1 = state ? (m_inth1 | (1 << (slot & 0x07))) : (m_inth1 & ~(1 << (slot & 0x07)));
m_inth1_cb(m_inth1 != 0);
}
void option_bus_device::set_inth2_line(uint8_t state, uint8_t slot)
{
m_inth2 = state ? (m_inth2 | (1 << (slot & 0x07))) : (m_inth2 & ~(1 << (slot & 0x07)));
m_inth2_cb(m_inth2 != 0);
}
void option_bus_device::set_drqf_line(uint8_t state, uint8_t slot)
{
m_drqf = !state ? (m_drqf | (1 << (slot & 0x07))) : (m_drqf & ~(1 << (slot & 0x07)));
m_drqf_cb(m_drqf == 0);
}
void option_bus_device::set_rdyf_line(uint8_t state, uint8_t slot)
{
m_rdyf = !state ? (m_rdyf | (1 << (slot & 0x07))) : (m_rdyf & ~(1 << (slot & 0x07)));
m_rdyf_cb(m_rdyf == 0);
}
void option_bus_device::set_rdys_line(uint8_t state, uint8_t slot)
{
m_rdys = !state ? (m_rdys | (1 << (slot & 0x07))) : (m_rdys & ~(1 << (slot & 0x07)));
m_rdys_cb(m_rdys == 0);
}
//**************************************************************************
// EPSON OPTION CARD INTERFACE
//**************************************************************************
//-------------------------------------------------
// option_device_expansion_interface - constructor
//-------------------------------------------------
device_option_expansion_interface::device_option_expansion_interface(const machine_config &mconfig, device_t &device) :
device_interface(device, "qx_option_bus"),
m_bus(nullptr),
m_slot(-1)
{
}
//---------------------------------------------------
// interface_pre_start - device-specific pre startup
//---------------------------------------------------
void device_option_expansion_interface::interface_pre_start()
{
if (!m_bus || m_slot == -1)
throw device_missing_dependencies();
}
//-------------------------------------------------
// SLOT_INTERFACE( option_bus_devices )
//-------------------------------------------------
void option_bus_devices(device_slot_interface &device)
{
}
} // namespace bus::epson_qx

View File

@ -0,0 +1,280 @@
// license:BSD-3-Clause
// copyright-holders:Brian Johnson
/*
QX-10 Option bus
1 GND 2 GND
3 DTB0 4 DTB1
5 DTB2 6 DTB3
7 DTB4 8 DTB5
9 DTB6 10 DTB7
11 -12V 12 -12V
13 ADR0 14 ADR1
15 ADR2 16 ADR3
17 ADR4 18 ADR5
19 ADR6 20 ADR7
21 ADR8 22 ADR9
23 ADR10 24 ADR11
25 ADR12 26 ADR13
27 ADR14 28 ADR15
29 GND 30 GND
31 CLK 32 GND
33 /BSAK 34 /MEMX
35 /IRD 36 /IWR
37 /MRD 38 /MWR
39 /RSIN 40 INTH1
41 INTH2 42 INTL
43 +5V 44 /RSET
45 +5V 46 +5V
47 /DRQF 48 /DRQS
49 /RDYF 50 /RDYS
51 /WAIT 52 /IWS
53 /DAKF 54 /DAKS
55 /EOPF 56 /EOPS
57 +12V 58 +12V
59 GND 60 GND
The INTH1 and INTH2 singals are the two hihg priority interrupts and are
global to the entire option bus. The INTL signal is the low priority interrupt
and is local to each of the 5 option slots.
5 4 3 2 1
|---| |---| |---| |---| |---|
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| *-|--|-*-|--|-*-|--|-*-|--|-*-|--------IRQH1 (Master IR2)
| | | | | | | | | |
| *-|--|-*-|--|-*-|--|-*-|--|-*-|--------IRQH2 (Master IR3)
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | *-|--------IRQL (Slave IR1)
| | | | | | | | | |
| | | | | | | *-|--|---|--------IRQL (Slave IR3)
| | | | | | | | | |
| | | | | *-|--|---|--|---|--------IRQL (Slave IR4)
| | | | | | | | | |
| | | *-|--|---|--|---|--|---|--------IRQL (Slave IR6)
| | | | | | | | | |
| *-|--|---|--|---|--|---|--|---|--------IRQL (Slave IR7)
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
|---| |---| |---| |---| |---|
The DREQ/DACK(F) signals are the high priorty DMA signals and are shared between all option slots.
The DREQ/DACK(S) signals are the lower priority DMA signals and are local to each slot, with the
exception of slot 5 which does not provide low priority DMA signals. The RDY/EOP(S) signals are
also connected to all 5 options slots since the DREQ(S) signals are all connected to the same
DMA controller.
5 4 3 2 1
|---| |---| |---| |---| |---|
| | | | | | | | | |
| *-|--|-*-|--|-*-|--|-*-|--|-*-|--------DREQF (Master CH3)
| *-|--|-*-|--|-*-|--|-*-|--|-*-|--------DACKF (Master Ch3)
| | | | | | | | | |
| *-|--|-*-|--|-*-|--|-*-|--|-*-|--------RDYF (Master RDY)
| *-|--|-*-|--|-*-|--|-*-|--|-*-|--------EOPF (Master EOP)
| | | | | | | | | |
| | | | | | | | | *-|--------DREQS (Slave CH0)
| | | | | | | | | *-|--------DACKS (Slave CH0)
| | | | | | | | | |
| | | | | | | *-|--|---|--------DREQS (Slave CH1)
| | | | | | | *-|--|---|--------DACKS (Slave CH1)
| | | | | | | | | |
| | | | | *-|--|---|--|---|--------DREQS (Slave CH2)
| | | | | *-|--|---|--|---|--------DACKS (Slave CH2)
| | | | | | | | | |
| | | *-|--|---|--|---|--|---|--------DREQS (Slave CH3)
| | | *-|--|---|--|---|--|---|--------DACKS (Slave CH3)
| | | | | | | | | |
| *-|--|-*-|--|-*-|--|-*-|--|-*-|--------RDYS (Slave RDY)
| *-|--|-*-|--|-*-|--|-*-|--|-*-|--------EOPS (Slave EOP)
| | | | | | | | | |
|---| |---| |---| |---| |---|
*/
#ifndef MAME_BUS_EPSON_QX_BUS_H
#define MAME_BUS_EPSON_QX_BUS_H
#pragma once
#include <vector>
namespace bus::epson_qx {
//**************************************************************************
// FORWARD DECLARATIONS
//**************************************************************************
class option_bus_device;
class device_option_expansion_interface;
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
/* Epson Slot Device */
class option_slot_device : public device_t, public device_single_card_slot_interface<device_option_expansion_interface>
{
public:
friend class option_bus_device;
// construction/destruction
template <typename T, typename U>
option_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&bus_tag, int slot, U &&opts, const char *dflt)
: option_slot_device(mconfig, tag, owner, bus_tag->clock())
{
option_reset();
opts(*this);
set_default_option(dflt);
set_fixed(false);
m_bus.set_tag(std::forward<T>(bus_tag));
m_slot = slot;
}
option_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
DECLARE_WRITE_LINE_MEMBER(inth1_w);
DECLARE_WRITE_LINE_MEMBER(inth2_w);
DECLARE_WRITE_LINE_MEMBER(intl_w);
DECLARE_WRITE_LINE_MEMBER(drqf_w);
DECLARE_WRITE_LINE_MEMBER(drqs_w);
DECLARE_WRITE_LINE_MEMBER(rdyf_w);
DECLARE_WRITE_LINE_MEMBER(rdys_w);
DECLARE_WRITE_LINE_MEMBER(eopf);
DECLARE_WRITE_LINE_MEMBER(eops);
auto dmas_w_callback() { m_dmas_w_cb.bind(); }
auto dmas_r_callback() { m_dmas_r_cb.bind(); }
auto dmaf_w_callback() { m_dmaf_w_cb.bind(); }
auto dmaf_r_callback() { m_dmaf_r_cb.bind(); }
auto in_eopf_callback() { return m_eopf_cb.bind(); }
auto in_eops_callback() { return m_eops_cb.bind(); }
protected:
// device-level overrides
virtual void device_start() override;
// configuration
required_device<option_bus_device> m_bus;
devcb_write8 m_dmas_w_cb;
devcb_read8 m_dmas_r_cb;
devcb_write8 m_dmaf_w_cb;
devcb_read8 m_dmaf_r_cb;
devcb_write_line m_eopf_cb;
devcb_write_line m_eops_cb;;
int m_slot;
};
/* Epson Bus Device */
class option_bus_device : public device_t
{
public:
// construction/destruction
option_bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
template <typename T> void set_iospace(T &&tag, int spacenum) { m_iospace.set_tag(std::forward<T>(tag), spacenum); }
void set_memview(memory_view::memory_view_entry &view) { m_view = &view; }
auto out_inth1_callback() { return m_inth1_cb.bind(); }
auto out_inth2_callback() { return m_inth2_cb.bind(); }
template <unsigned Slot> auto out_intl_callback() { return m_intl_cb[Slot].bind(); }
auto out_drqf_callback() { return m_drqf_cb.bind(); }
template <unsigned Slot> auto out_drqs_callback() { return m_drqs_cb[Slot].bind(); }
auto out_rdyf_callback() { return m_rdyf_cb.bind(); }
auto out_rdys_callback() { return m_rdys_cb.bind(); }
memory_view::memory_view_entry& memview() const { return *m_view; }
address_space &iospace() const { return *m_iospace; }
void dackf_w(uint8_t data);
uint8_t dackf_r();
template <unsigned Slot> void dacks_w(uint8_t data) { (*this)[Slot]->m_dmas_w_cb(data); }
template <unsigned Slot> uint8_t dacks_r() { return (*this)[Slot]->m_dmas_r_cb(); }
template <void (option_slot_device::*slot_callback)(int)> void slots_w(int state) {
for (option_slot_device *slot : m_slot_list) {
(slot->*slot_callback)(state);
}
}
void set_inth1_line(uint8_t state, uint8_t slot);
void set_inth2_line(uint8_t state, uint8_t slot);
void set_intl_line(uint8_t state, uint8_t slot) { m_intl_cb[slot](state); }
void set_drqf_line(uint8_t state, uint8_t slot);
void set_drqs_line(uint8_t state, uint8_t slot) { m_drqs_cb[slot](state); }
void set_rdyf_line(uint8_t state, uint8_t slot);
void set_rdys_line(uint8_t state, uint8_t slot);
void add_slot(option_slot_device &slot);
option_slot_device* operator[](int index) const {assert(index < m_slot_list.size()); return m_slot_list[index]; }
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
required_address_space m_iospace;
memory_view::memory_view_entry *m_view;
devcb_write_line m_inth1_cb;
devcb_write_line m_inth2_cb;
devcb_write_line::array<5> m_intl_cb;
devcb_write_line m_drqf_cb;
devcb_write_line::array<4> m_drqs_cb;
devcb_write_line m_rdyf_cb;
devcb_write_line m_rdys_cb;
std::vector<option_slot_device *> m_slot_list;
uint8_t m_inth1;
uint8_t m_inth2;
uint8_t m_drqf;
uint8_t m_rdyf;
uint8_t m_rdys;
};
/* Epson Option Card interface */
class device_option_expansion_interface : public device_interface
{
public:
void set_option_bus(option_bus_device &bus, int slot) { assert(!device().started()); m_bus = &bus; m_slot = slot; }
protected:
device_option_expansion_interface(const machine_config &mconfig, device_t &device);
virtual void interface_pre_start() override;
option_slot_device* get_slot() { return (*m_bus)[m_slot]; }
option_bus_device *m_bus;
int m_slot;
};
void option_bus_devices(device_slot_interface &device);
} // namespace bus::epson_qx
// device type definition
DECLARE_DEVICE_TYPE_NS(EPSON_QX_OPTION_BUS_SLOT, bus::epson_qx, option_slot_device)
DECLARE_DEVICE_TYPE_NS(EPSON_QX_OPTION_BUS, bus::epson_qx, option_bus_device)
#endif

View File

@ -1,5 +1,5 @@
// license:BSD-3-Clause
// copyright-holders:Mariusz Wojcieszek, Angelo Salese
// copyright-holders:Mariusz Wojcieszek, Angelo Salese, Brian Johnson
/***************************************************************************
QX-10
@ -35,6 +35,7 @@
#include "emu.h"
#include "bus/centronics/ctronics.h"
#include "bus/epson_qx/option.h"
#include "bus/rs232/rs232.h"
#include "cpu/z80/z80.h"
#include "imagedev/floppy.h"
@ -85,13 +86,15 @@ public:
m_rtc(*this, "rtc"),
m_kbd(*this, "kbd"),
m_centronics(*this, "centronics"),
m_bus(*this, "bus"),
m_speaker(*this, "speaker"),
m_vram_bank(0),
m_char_rom(*this, "chargen"),
m_maincpu(*this, "maincpu"),
m_screen(*this, "screen"),
m_ram(*this, RAM_TAG),
m_palette(*this, "palette")
m_palette(*this, "palette"),
m_ram_view(*this, "ramview")
{
}
@ -168,6 +171,7 @@ private:
required_device<mc146818_device> m_rtc;
required_device<rs232_port_device> m_kbd;
required_device<centronics_device> m_centronics;
required_device<bus::epson_qx::option_bus_device> m_bus;
required_device<speaker_sound_device> m_speaker;
uint8_t m_vram_bank;
//required_shared_ptr<uint8_t> m_video_ram;
@ -197,6 +201,8 @@ private:
/* memory */
memory_view m_ram_view;
int m_external_bank;
int m_membank;
int m_memprom;
int m_memcmos;
@ -323,7 +329,7 @@ void qx10_state::update_speaker()
*/
void qx10_state::update_memory_mapping()
{
int drambank = 0;
int drambank = -1;
if (m_membank & 1)
{
@ -342,6 +348,9 @@ void qx10_state::update_memory_mapping()
drambank = 3;
}
if (drambank >= 0 || !m_memprom || m_memcmos)
{
m_ram_view.select(0);
if (!m_memprom)
{
membank("bank1")->set_base(memregion("maincpu")->base());
@ -358,12 +367,26 @@ void qx10_state::update_memory_mapping()
{
membank("bank2")->set_base(m_ram->pointer() + drambank*64*1024 + 32*1024);
}
}
else
{
if (m_external_bank)
{
m_ram_view.select(1);;
}
else
{
m_ram_view.disable();
}
}
}
void qx10_state::qx10_18_w(uint8_t data)
{
m_membank = (data >> 4) & 0x0f;
m_spkr_enable = (data >> 2) & 0x01;
m_external_bank = (data >> 3) & 0x01;
m_pit_1->write_gate0(data & 1);
update_speaker();
update_memory_mapping();
@ -534,6 +557,7 @@ WRITE_LINE_MEMBER( qx10_state::tc_w )
{
/* floppy terminal count */
m_fdc->tc_w(!state);
m_bus->slots_w<&bus::epson_qx::option_slot_device::eopf>(state);
}
/*
@ -661,8 +685,10 @@ void qx10_state::vram_bank_w(uint8_t data)
void qx10_state::qx10_mem(address_map &map)
{
map.unmap_value_high();
map(0x0000, 0x7fff).bankrw("bank1");
map(0x8000, 0xdfff).bankrw("bank2");
map(0x0000, 0xdfff).view(m_ram_view);
m_ram_view[0](0x0000, 0x7fff).bankrw("bank1");
m_ram_view[0](0x8000, 0xdfff).bankrw("bank2");
m_ram_view[1](0x0000, 0xdfff).unmaprw();
map(0xe000, 0xffff).ram();
}
@ -688,7 +714,6 @@ void qx10_state::qx10_io(address_map &map)
map(0x3c, 0x3d).rw(FUNC(qx10_state::mc146818_r), FUNC(qx10_state::mc146818_w));
map(0x40, 0x4f).rw(m_dma_1, FUNC(am9517a_device::read), FUNC(am9517a_device::write));
map(0x50, 0x5f).rw(m_dma_2, FUNC(am9517a_device::read), FUNC(am9517a_device::write));
// map(0xfc, 0xfd) Multi-Font comms
}
/* Input ports */
@ -743,6 +768,7 @@ INPUT_PORTS_END
void qx10_state::machine_start()
{
m_bus->set_memview(m_ram_view[1]);
}
void qx10_state::machine_reset()
@ -755,6 +781,7 @@ void qx10_state::machine_reset()
m_zoom = 0;
m_external_bank = 0;
m_memprom = 0;
m_memcmos = 0;
m_membank = 0;
@ -965,6 +992,39 @@ void qx10_state::qx10(machine_config &config)
/* internal ram */
RAM(config, RAM_TAG).set_default_size("256K");
EPSON_QX_OPTION_BUS(config, m_bus, MAIN_CLK / 4);
m_dma_1->out_iow_callback<2>().set(m_bus, FUNC(bus::epson_qx::option_bus_device::dackf_w));
m_dma_1->in_ior_callback<2>().set(m_bus, FUNC(bus::epson_qx::option_bus_device::dackf_r));
m_dma_2->out_iow_callback<0>().set(m_bus, FUNC(bus::epson_qx::option_bus_device::dacks_w<0>));
m_dma_2->in_ior_callback<0>().set(m_bus, FUNC(bus::epson_qx::option_bus_device::dacks_r<0>));
m_dma_2->out_iow_callback<1>().set(m_bus, FUNC(bus::epson_qx::option_bus_device::dacks_w<1>));
m_dma_2->in_ior_callback<1>().set(m_bus, FUNC(bus::epson_qx::option_bus_device::dacks_r<1>));
m_dma_2->out_iow_callback<2>().set(m_bus, FUNC(bus::epson_qx::option_bus_device::dacks_w<2>));
m_dma_2->in_ior_callback<2>().set(m_bus, FUNC(bus::epson_qx::option_bus_device::dacks_r<2>));
m_dma_2->out_iow_callback<3>().set(m_bus, FUNC(bus::epson_qx::option_bus_device::dacks_w<3>));
m_dma_2->in_ior_callback<3>().set(m_bus, FUNC(bus::epson_qx::option_bus_device::dacks_r<3>));
m_dma_2->out_eop_callback().set(m_bus, FUNC(bus::epson_qx::option_bus_device::slots_w<&bus::epson_qx::option_slot_device::eops>));
m_bus->out_drqf_callback().set(m_dma_1, FUNC(am9517a_device::dreq2_w));
m_bus->out_rdyf_callback().set(m_dma_1, FUNC(am9517a_device::ready_w));
m_bus->out_drqs_callback<0>().set(m_dma_2, FUNC(am9517a_device::dreq0_w));
m_bus->out_drqs_callback<1>().set(m_dma_2, FUNC(am9517a_device::dreq1_w));
m_bus->out_drqs_callback<2>().set(m_dma_2, FUNC(am9517a_device::dreq2_w));
m_bus->out_drqs_callback<3>().set(m_dma_2, FUNC(am9517a_device::dreq3_w));
m_bus->out_rdys_callback().set(m_dma_2, FUNC(am9517a_device::ready_w));
m_bus->out_inth1_callback().set(m_pic_m, FUNC(pic8259_device::ir2_w));
m_bus->out_inth2_callback().set(m_pic_m, FUNC(pic8259_device::ir3_w));
m_bus->out_intl_callback<0>().set(m_pic_s, FUNC(pic8259_device::ir1_w));
m_bus->out_intl_callback<1>().set(m_pic_s, FUNC(pic8259_device::ir3_w));
m_bus->out_intl_callback<2>().set(m_pic_s, FUNC(pic8259_device::ir4_w));
m_bus->out_intl_callback<3>().set(m_pic_s, FUNC(pic8259_device::ir6_w));
m_bus->out_intl_callback<4>().set(m_pic_s, FUNC(pic8259_device::ir7_w));
m_bus->set_iospace(m_maincpu, AS_IO);
EPSON_QX_OPTION_BUS_SLOT(config, "option1", m_bus, 0, bus::epson_qx::option_bus_devices, nullptr);
EPSON_QX_OPTION_BUS_SLOT(config, "option2", m_bus, 1, bus::epson_qx::option_bus_devices, nullptr);
EPSON_QX_OPTION_BUS_SLOT(config, "option3", m_bus, 2, bus::epson_qx::option_bus_devices, nullptr);
EPSON_QX_OPTION_BUS_SLOT(config, "option4", m_bus, 3, bus::epson_qx::option_bus_devices, nullptr);
EPSON_QX_OPTION_BUS_SLOT(config, "option5", m_bus, 4, bus::epson_qx::option_bus_devices, nullptr);
// software lists
SOFTWARE_LIST(config, "flop_list").set_original("qx10_flop");
@ -979,12 +1039,6 @@ ROM_START( qx10 )
ROM_SYSTEM_BIOS(1, "v003", "v0.03")
ROMX_LOAD( "ipl003.bin", 0x0000, 0x0800, CRC(3cbc4008) SHA1(cc8c7d1aa0cca8f9753d40698b2dc6802fd5f890), ROM_BIOS(1))
/* This is probably the i8039 program ROM for the Q10MF Multifont card, and the actual font ROMs are missing (6 * HM43128) */
/* The first part of this rom looks like code for an embedded controller?
From 0300 on, is a keyboard lookup table */
ROM_REGION( 0x0800, "i8039", 0 )
ROM_LOAD( "m12020a.3e", 0x0000, 0x0800, CRC(fa27f333) SHA1(73d27084ca7b002d5f370220d8da6623a6e82132))
ROM_REGION( 0x1000, "chargen", 0 )
// ROM_LOAD( "qge.2e", 0x0000, 0x0800, BAD_DUMP CRC(ed93cb81) SHA1(579e68bde3f4184ded7d89b72c6936824f48d10b)) //this one contains special characters only
// ROM_LOAD( "qge.2e", 0x0000, 0x1000, BAD_DUMP CRC(eb31a2d5) SHA1(6dc581bf2854a07ae93b23b6dfc9c7abd3c0569e))