summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus
diff options
context:
space:
mode:
author Angelo Salese <angelosa@users.noreply.github.com>2021-08-24 10:22:03 +0200
committer GitHub <noreply@github.com>2021-08-24 10:22:03 +0200
commit0e4ba6d49ad68d13966dc2cd14adbe68a7b3b684 (patch)
treef44d329f0185cb67a7ff5babafa1b264ac6273ce /src/devices/bus
parentc471fad8e019703bb3323682f662249e251414f4 (diff)
Major state refactoring of pc98 based HW (#8475)
First major step in splitting up machine classes in NEC PC98 family tree: * Splits up derivative HWs into own state machine and files (pc98ha.cpp, pc9821.cpp and pc9801_epson.cpp); * Adds a preliminary uPD4991a parallel RTC, used by pc98ha; * Fix -26, -86, -118 C-bus sound board dips or jumper settings; * Fix default sound card for pc9821 (-86) and pc9821ce2 / pc9821cx3 (-118); * Adds preliminary MAD Factory Otomichan-kai C-bus sound board; * Adds boilerplate code for C-bus installing board I/Os, avoiding the possible inconvenience of board(s) getting silently unmapped by other installed boards; * Major refactoring of HW dip switches readouts, using required_ioports instead of scattering things around in PPI hooks; * Extensive QA rundown, including research on missing features and undumped machines. pc9801.cpp: Don't passthrough mouse irq frequency when cycle setting is setup too, fixes jastrike mouse input on options menu. pc9801.cpp: Fix kanji RAM window LR readback, makes telenetm to properly display 8x16 chars on RS and derivative machines. pc8801.cpp: fixed OPNA RAM readback, allowing SWs to playback ADPCMs properly. New machines marked as NOT_WORKING ---------------------------------- PC-98LT [anonymous] PC-98HA "Handy98" [anonymous] PC-9821Nr15 (98NOTE Lavie) [flyingharuka] PC-9821Nr166 (98NOTE Lavie) [flyingharuka] PC-9821Nw150 (98NOTE Lavie) [flyingharuka] PC-9821Ra266 (98MATE R) [flyingharuka] PC-9821Cx3 (98MULTi CanBe) [flyingharuka] PC-9801VX [qazmko1029] PC-9801US [CoolMod]
Diffstat (limited to 'src/devices/bus')
-rw-r--r--src/devices/bus/cbus/mpu_pc98.cpp2
-rw-r--r--src/devices/bus/cbus/pc9801_118.cpp120
-rw-r--r--src/devices/bus/cbus/pc9801_118.h3
-rw-r--r--src/devices/bus/cbus/pc9801_26.cpp90
-rw-r--r--src/devices/bus/cbus/pc9801_26.h4
-rw-r--r--src/devices/bus/cbus/pc9801_55.cpp253
-rw-r--r--src/devices/bus/cbus/pc9801_55.h80
-rw-r--r--src/devices/bus/cbus/pc9801_86.cpp259
-rw-r--r--src/devices/bus/cbus/pc9801_86.h59
-rw-r--r--src/devices/bus/cbus/pc9801_amd98.cpp18
-rw-r--r--src/devices/bus/cbus/pc9801_amd98.h12
-rw-r--r--src/devices/bus/cbus/pc9801_cbus.cpp44
-rw-r--r--src/devices/bus/cbus/pc9801_cbus.h2
-rw-r--r--src/devices/bus/cbus/pc9801_snd.cpp8
-rw-r--r--src/devices/bus/cbus/pc9801_snd.h8
15 files changed, 814 insertions, 148 deletions
diff --git a/src/devices/bus/cbus/mpu_pc98.cpp b/src/devices/bus/cbus/mpu_pc98.cpp
index 2230e966fda..2ba192d4b0d 100644
--- a/src/devices/bus/cbus/mpu_pc98.cpp
+++ b/src/devices/bus/cbus/mpu_pc98.cpp
@@ -38,7 +38,7 @@ WRITE_LINE_MEMBER( mpu_pc98_device::mpu_irq_out )
// GLOBAL VARIABLES
//**************************************************************************
-DEFINE_DEVICE_TYPE(MPU_PC98, mpu_pc98_device, "mpu_pc98", "Roland MPU-401 MIDI Interface (CBUS)")
+DEFINE_DEVICE_TYPE(MPU_PC98, mpu_pc98_device, "mpu_pc98", "Roland MPU-401 MIDI Interface (C-bus)")
//-------------------------------------------------
// device_add_mconfig - add device configuration
diff --git a/src/devices/bus/cbus/pc9801_118.cpp b/src/devices/bus/cbus/pc9801_118.cpp
index 7f45cdf5d5e..403a23b4658 100644
--- a/src/devices/bus/cbus/pc9801_118.cpp
+++ b/src/devices/bus/cbus/pc9801_118.cpp
@@ -1,16 +1,24 @@
// license:BSD-3-Clause
// copyright-holders:Angelo Salese
-/***************************************************************************
+/**************************************************************************************************
- NEC PC-9801-118 sound card
+ NEC PC-9801-118 sound card "CanBe Sound 2"
- YMF297 + some extra ports
+ YMF297 + some extra ports, apparently derived from -86.
+ Introduced around the same time as Windows 95 release, it has various compatibility issues
+ under DOS (especially when PnP is enabled).
+ Doesn't have a sound ROM, it also cannot be installed with an environment also sporting a -86.
TODO:
- - preliminary, presumably needs CS-4232 too, it's an extended clone of the already emulated AD1848 used on the Windows Sound System
+ - Fix sound chip type (YMF297-F);
+ - Add CS-4232 support, it's an extended clone of the already emulated AD1848 used on the
+ Windows Sound System;
+ - Understand what the obfuscated NEC "ANCHOR" and "MAZE" chips really are;
+ - PnP interface (missing BIOS);
- verify sound irq;
+ - test if driver can be installed under Windows 95;
-***************************************************************************/
+**************************************************************************************************/
#include "emu.h"
#include "bus/cbus/pc9801_118.h"
@@ -27,11 +35,11 @@
//**************************************************************************
// device type definition
-DEFINE_DEVICE_TYPE(PC9801_118, pc9801_118_device, "pc9801_118", "pc9801_118")
+DEFINE_DEVICE_TYPE(PC9801_118, pc9801_118_device, "pc9801_118", "NEC PC-9801-118")
WRITE_LINE_MEMBER(pc9801_118_device::sound_irq)
{
- /* TODO: seems to die very often */
+ // TODO: sometimes misfired irq causes sound or even host hang
m_bus->int_w<5>(state);
}
@@ -41,9 +49,15 @@ WRITE_LINE_MEMBER(pc9801_118_device::sound_irq)
void pc9801_118_device::device_add_mconfig(machine_config &config)
{
+ // TODO: "ANCHOR" & "MAZE" custom NEC chips
+ // sourced by 5D clock
+
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
- YM2608(config, m_opn3, XTAL_5B * 2 / 5); // actually YMF297-F, unknown clock / divider, more likely uses 5D clock
+
+ // actually YMF297-F (YMF288 + OPL3 compatible FM sources), unknown clock / divider
+ // 5B is near both CS-4232 and this
+ YM2608(config, m_opn3, XTAL_5B * 2 / 5);
m_opn3->irq_handler().set(FUNC(pc9801_118_device::sound_irq));
m_opn3->port_a_read_callback().set(FUNC(pc9801_118_device::opn_porta_r));
//m_opn3->port_b_read_callback().set(FUNC(pc8801_state::opn_portb_r));
@@ -61,10 +75,48 @@ void pc9801_118_device::device_add_mconfig(machine_config &config)
static INPUT_PORTS_START( pc9801_118 )
PORT_INCLUDE( pc9801_joy_port )
- PORT_START("OPN3_DSW")
- PORT_CONFNAME( 0x01, 0x00, "PC-9801-118: Port Base" )
- PORT_CONFSETTING( 0x00, "0x088" )
- PORT_CONFSETTING( 0x01, "0x188" )
+ // 12 line Jumper settings @ 8F
+ // documented at https://sammargh.github.io/pc98/ext_card_doc/9801-118.txt
+ // TODO: understand how SW can read these
+ PORT_START("OPN3_JP_8F")
+ PORT_CONFNAME( 0x001, 0x000, "PC-9801-118: Enable Plug and Play" ) // [1]
+ PORT_CONFSETTING( 0x000, DEF_STR( No ) )
+ PORT_CONFSETTING( 0x001, DEF_STR( Yes ) )
+ // "group" is basically a obnoxious machine ID
+ // details are in the aforementioned link, in a nutshell should be:
+ // Group 1: later CanBe (Cb onward)
+ // Group 2: early CanBe (Ce, Ce2, Cs2), 9821 MATE A
+ // Group 4: several ValueStar models
+ // Group 5: 9821 MATE B, Notebooks, 9801 BX, some H98 models
+ // Group 3: anything not covered above (link also mentions BX4 here?)
+ // In practice this should really be tested on field ...
+ PORT_CONFNAME( 0x406, 0x000, "PC-9801-118: PCM Group select") // [2, 3, 11]
+ PORT_CONFSETTING( 0x000, "Groups 2, 3, 4, 5" ) // uses -118 PCM
+ PORT_CONFSETTING( 0x404, "Group 3" ) // uses PCM host
+ PORT_CONFSETTING( 0x002, "Group 1" ) // ?
+ // all other settings "prohibited"
+ PORT_CONFNAME( 0x008, 0x008, "PC-9801-118: unknown [4]" ) // [4] "prohibited", always ON
+ PORT_CONFSETTING( 0x000, DEF_STR( Off ) )
+ PORT_CONFSETTING( 0x008, DEF_STR( On ) )
+ PORT_CONFNAME( 0x030, 0x000, "PC-9801-118: FM Interrupt setting" ) // [5,6]
+ PORT_CONFSETTING( 0x000, "INT5 (IRQ12)" )
+ PORT_CONFSETTING( 0x010, "INT6 (IRQ13)" )
+ PORT_CONFSETTING( 0x020, "INT41 (IRQ10)" )
+ PORT_CONFSETTING( 0x030, "INT0 (IRQ3)")
+ PORT_CONFNAME( 0x040, 0x000, "PC-9801-118: DMA channel" ) // [7]
+ PORT_CONFSETTING( 0x000, "1" )
+ PORT_CONFSETTING( 0x040, "2" )
+ PORT_CONFNAME( 0x180, 0x000, "PC-9801-118: PCM Interrupt setting" ) // [8,9]
+ PORT_CONFSETTING( 0x000, "INT5 (IRQ12)" )
+ PORT_CONFSETTING( 0x080, "INT1 (IRQ5)" )
+ PORT_CONFSETTING( 0x100, "INT41 (IRQ10)" )
+ PORT_CONFSETTING( 0x180, "INT0 (IRQ3)" )
+ PORT_CONFNAME( 0x200, 0x000, "PC-9801-118: enable MIDI Interrupt" ) // [10]
+ PORT_CONFSETTING( 0x000, DEF_STR( No ) )
+ PORT_CONFSETTING( 0x200, DEF_STR( Yes ) ) // auto for PnP, INT41 for non-PnP
+ PORT_CONFNAME( 0x800, 0x000, "PC-9801-118: unknown [12]" ) // [12] "prohibited", always OFF
+ PORT_CONFSETTING( 0x000, DEF_STR( Off ) )
+ PORT_CONFSETTING( 0x800, DEF_STR( On ) )
INPUT_PORTS_END
ioport_constructor pc9801_118_device::device_input_ports() const
@@ -72,8 +124,14 @@ ioport_constructor pc9801_118_device::device_input_ports() const
return INPUT_PORTS_NAME( pc9801_118 );
}
-// RAM
ROM_START( pc9801_118 )
+ ROM_REGION( 0x20000, "pnp_bios", ROMREGION_ERASE00 )
+ // NB: either socket is exclusively populated, earlier models populates 1E while later populates 2E.
+ // Most likely contains same data or slight revision bump.
+ // μPD27c1024 socket
+ ROM_LOAD( "118 e316.1e", 0x00000, 0x20000, NO_DUMP )
+ // LH531024N socket at .2e (unreadable label)
+
ROM_REGION( 0x100000, "opn3", ROMREGION_ERASE00 )
ROM_END
@@ -111,11 +169,24 @@ void pc9801_118_device::device_validity_check(validity_checker &valid) const
// device_start - device-specific startup
//-------------------------------------------------
+u16 pc9801_118_device::read_io_base()
+{
+ // hardwired on this board
+ return 0x0188;
+}
void pc9801_118_device::device_start()
{
+ m_io_base = read_io_base();
m_bus->install_io(0xa460, 0xa463, read8sm_delegate(*this, FUNC(pc9801_118_device::id_r)), write8sm_delegate(*this, FUNC(pc9801_118_device::ext_w)));
+ m_bus->install_io(
+ m_io_base,
+ m_io_base + 7,
+ read8sm_delegate(*this, FUNC(pc9801_118_device::opn3_r)),
+ write8sm_delegate(*this, FUNC(pc9801_118_device::opn3_w))
+ );
+
save_item(NAME(m_ext_reg));
}
@@ -126,10 +197,8 @@ void pc9801_118_device::device_start()
void pc9801_118_device::device_reset()
{
- uint16_t port_base = (ioport("OPN3_DSW")->read() & 1) << 8;
- m_bus->io_space().unmap_readwrite(0x0088, 0x008b, 0x100);
- m_bus->install_io(port_base + 0x0088, port_base + 0x008f, read8sm_delegate(*this, FUNC(pc9801_118_device::opn3_r)), write8sm_delegate(*this, FUNC(pc9801_118_device::opn3_w)));
- m_ext_reg = 1; // TODO: enabled or disabled?
+ // TODO: is this enabled or disabled at boot?
+ m_ext_reg = 1;
}
@@ -140,7 +209,7 @@ void pc9801_118_device::device_reset()
uint8_t pc9801_118_device::opn3_r(offs_t offset)
{
- if(((offset & 5) == 0) || m_ext_reg)
+ if(((offset & 5) == 0) || m_ext_reg )
return m_opn3->read(offset >> 1);
else // odd
{
@@ -152,7 +221,7 @@ uint8_t pc9801_118_device::opn3_r(offs_t offset)
void pc9801_118_device::opn3_w(offs_t offset, uint8_t data)
{
- if(((offset & 5) == 0) || m_ext_reg)
+ if( ((offset & 5) == 0) || m_ext_reg )
m_opn3->write(offset >> 1,data);
//else // odd
// printf("PC9801-118: Write to undefined port [%02x] %02x\n",offset+0x188,data);
@@ -162,11 +231,13 @@ uint8_t pc9801_118_device::id_r(offs_t offset)
{
if(offset == 0)
{
- printf("OPN3 EXT read ID [%02x]\n",offset);
+ logerror("OPN3 EXT read ID [%02x]\n",offset);
+ // TODO: confirm ID
+ // by assumption we make this same as later CanBe releases, may or may not be right
return 0x80 | (m_ext_reg & 1);
}
- printf("OPN3 EXT read unk [%02x]\n",offset);
+ logerror("OPN3 EXT read unk [%02x]\n", offset);
return 0xff;
}
@@ -175,11 +246,10 @@ void pc9801_118_device::ext_w(offs_t offset, uint8_t data)
if(offset == 0)
{
m_ext_reg = data & 1;
- /* TODO: apparently writing a 1 doubles the available channels (and presumably enables CS-4231 too) */
- if(data)
- printf("PC-9801-118: extended register %02x write\n",data);
+ if(data & 2)
+ logerror("%s: extended register %02x write\n", machine().describe_context(), data);
return;
}
- printf("OPN3 EXT write unk %02x -> [%02x]\n",data,offset);
+ logerror("%s: EXT write unk %02x -> [%02x]\n", machine().describe_context(), data, offset);
}
diff --git a/src/devices/bus/cbus/pc9801_118.h b/src/devices/bus/cbus/pc9801_118.h
index 0984a9c880c..94ac3bfe24c 100644
--- a/src/devices/bus/cbus/pc9801_118.h
+++ b/src/devices/bus/cbus/pc9801_118.h
@@ -28,6 +28,8 @@ public:
// construction/destruction
pc9801_118_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ static constexpr feature_type imperfect_features() { return feature::SOUND; }
+
uint8_t opn3_r(offs_t offset);
void opn3_w(offs_t offset, uint8_t data);
uint8_t id_r(offs_t offset);
@@ -42,6 +44,7 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual ioport_constructor device_input_ports() const override;
virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual u16 read_io_base() override;
private:
required_device<pc9801_slot_device> m_bus;
diff --git a/src/devices/bus/cbus/pc9801_26.cpp b/src/devices/bus/cbus/pc9801_26.cpp
index e9b9498c6ac..8f8b15740bd 100644
--- a/src/devices/bus/cbus/pc9801_26.cpp
+++ b/src/devices/bus/cbus/pc9801_26.cpp
@@ -1,6 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Angelo Salese
-/***************************************************************************
+/**************************************************************************************************
NEC PC-9801-26 sound card
@@ -8,8 +8,10 @@
TODO:
- verify sound irq;
+ - understand if dips can be read by SW;
+ - configurable irq level needs a binding flush in C-bus handling;
-***************************************************************************/
+**************************************************************************************************/
#include "emu.h"
#include "bus/cbus/pc9801_26.h"
@@ -23,11 +25,11 @@
//**************************************************************************
// device type definition
-DEFINE_DEVICE_TYPE(PC9801_26, pc9801_26_device, "pc9801_26", "pc9801_26")
+DEFINE_DEVICE_TYPE(PC9801_26, pc9801_26_device, "pc9801_26", "NEC PC-9801-26")
WRITE_LINE_MEMBER(pc9801_26_device::sound_irq)
{
- /* TODO: seems to die very often */
+ // TODO: sometimes misfired irq causes sound or even host hang
m_bus->int_w<5>(state);
}
@@ -77,10 +79,27 @@ const tiny_rom_entry *pc9801_26_device::device_rom_region() const
static INPUT_PORTS_START( pc9801_26 )
PORT_INCLUDE( pc9801_joy_port )
- PORT_START("OPN_DSW")
+ // On-board jumpers
+ // TODO: any way to actually read these from HW?
+ PORT_START("OPN_JP6A1_JP6A3")
+ PORT_CONFNAME( 0x03, 0x02, "PC-9801-26: Interrupt level")
+ PORT_CONFSETTING( 0x00, "IRQ 0" ) // 2-3, 2-3
+ PORT_CONFSETTING( 0x01, "IRQ 4" ) // 2-3, 1-2
+ PORT_CONFSETTING( 0x02, "IRQ 5" ) // 1-2, 1-2
+ PORT_CONFSETTING( 0x03, "IRQ 6" ) // 1-2, 2-3
+
+ PORT_START("OPN_JP6A2")
+ PORT_CONFNAME( 0x07, 0x01, "PC-9801-26: Sound ROM address")
+ PORT_CONFSETTING( 0x00, "0xc8000" ) // 1-10
+ PORT_CONFSETTING( 0x01, "0xcc000" ) // 2-9
+ PORT_CONFSETTING( 0x02, "0xd0000" ) // 3-8
+ PORT_CONFSETTING( 0x03, "0xd4000" ) // 4-7
+ PORT_CONFSETTING( 0x04, "Disable ROM") // 5-6
+
+ PORT_START("OPN_JP6A4")
PORT_CONFNAME( 0x01, 0x01, "PC-9801-26: Port Base" )
- PORT_CONFSETTING( 0x00, "0x088" )
- PORT_CONFSETTING( 0x01, "0x188" )
+ PORT_CONFSETTING( 0x00, "0x088" ) // 1-4
+ PORT_CONFSETTING( 0x01, "0x188" ) // 2-3
INPUT_PORTS_END
ioport_constructor pc9801_26_device::device_input_ports() const
@@ -97,9 +116,9 @@ ioport_constructor pc9801_26_device::device_input_ports() const
//-------------------------------------------------
pc9801_26_device::pc9801_26_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : pc9801_snd_device(mconfig, PC9801_26, tag, owner, clock),
- m_bus(*this, DEVICE_SELF_OWNER),
- m_opn(*this, "opn")
+ : pc9801_snd_device(mconfig, PC9801_26, tag, owner, clock)
+ , m_bus(*this, DEVICE_SELF_OWNER)
+ , m_opn(*this, "opn")
{
}
@@ -117,10 +136,15 @@ void pc9801_26_device::device_validity_check(validity_checker &valid) const
// device_start - device-specific startup
//-------------------------------------------------
+u16 pc9801_26_device::read_io_base()
+{
+ return ((ioport("OPN_JP6A4")->read() & 1) << 8) + 0x0088;
+}
void pc9801_26_device::device_start()
{
- m_bus->program_space().install_rom(0xcc000,0xcffff,memregion(this->subtag("sound_bios").c_str())->base());
+ m_rom_base = 0;
+ m_io_base = 0;
}
@@ -130,10 +154,48 @@ void pc9801_26_device::device_start()
void pc9801_26_device::device_reset()
{
- uint16_t port_base = (ioport("OPN_DSW")->read() & 1) << 8;
+ // install the ROM to the physical program space
+ u8 rom_setting = ioport("OPN_JP6A2")->read() & 7;
+ static const u32 rom_addresses[8] = { 0xc8000, 0xcc000, 0xd0000, 0xd4000, 0, 0, 0, 0 };
+ u32 current_rom = rom_addresses[rom_setting & 7];
+ memory_region *rom_region = memregion(this->subtag("sound_bios").c_str());
+ const u32 rom_size = rom_region->bytes() - 1;
- m_bus->io_space().unmap_readwrite(0x0088, 0x008b, 0x100);
- m_bus->install_io(port_base + 0x0088, port_base + 0x008b, read8sm_delegate(*this, FUNC(pc9801_26_device::opn_r)), write8sm_delegate(*this, FUNC(pc9801_26_device::opn_w)));
+ if (m_rom_base == 0)
+ m_rom_base = current_rom;
+
+ if (m_rom_base != 0)
+ {
+ logerror("%s: uninstall ROM at %08x-%08x\n", machine().describe_context(), m_rom_base, m_rom_base + rom_size);
+ m_bus->program_space().unmap_readwrite(m_rom_base, m_rom_base + rom_size);
+ }
+ if (current_rom != 0)
+ {
+ logerror("%s: install ROM at %08x-%08x\n", machine().describe_context(), current_rom, current_rom + rom_size);
+ m_bus->program_space().unmap_readwrite(current_rom, current_rom + rom_size);
+ m_bus->program_space().install_rom(
+ current_rom,
+ current_rom + rom_size,
+ rom_region->base()
+ );
+ }
+ m_rom_base = current_rom;
+
+ // install I/O ports
+ u16 current_io = read_io_base();
+ m_bus->flush_install_io(
+ this->tag(),
+ m_io_base,
+ current_io,
+ 3,
+ read8sm_delegate(*this, FUNC(pc9801_26_device::opn_r)),
+ write8sm_delegate(*this, FUNC(pc9801_26_device::opn_w))
+ );
+ m_io_base = current_io;
+
+ // install IRQ line
+// static const u8 irq_levels[4] = {0, 4, 5, 6};
+// m_irq_level = irq_levels[ioport("OPN_JP6A1_JP6A3")->read() & 3];
}
diff --git a/src/devices/bus/cbus/pc9801_26.h b/src/devices/bus/cbus/pc9801_26.h
index 84eeaab31d4..80cd57a20cd 100644
--- a/src/devices/bus/cbus/pc9801_26.h
+++ b/src/devices/bus/cbus/pc9801_26.h
@@ -2,7 +2,7 @@
// copyright-holders:Angelo Salese
/***************************************************************************
-Template for skeleton device
+ NEC PC-9801-26 sound card
***************************************************************************/
@@ -39,12 +39,14 @@ protected:
virtual void device_add_mconfig(machine_config &config) override;
virtual ioport_constructor device_input_ports() const override;
virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual u16 read_io_base() override;
private:
required_device<pc9801_slot_device> m_bus;
required_device<ym2203_device> m_opn;
DECLARE_WRITE_LINE_MEMBER(sound_irq);
+ u32 m_rom_base;
};
diff --git a/src/devices/bus/cbus/pc9801_55.cpp b/src/devices/bus/cbus/pc9801_55.cpp
new file mode 100644
index 00000000000..879ad2f1a66
--- /dev/null
+++ b/src/devices/bus/cbus/pc9801_55.cpp
@@ -0,0 +1,253 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+/**************************************************************************************************
+
+ NEC PC-9801-55/-55U/-55L
+
+ SCSI interface, running on WD33C93A
+
+ TODO:
+ - Is PC-9801-55 also running on this except with WD33C93 instead?
+ Will see once we obtain a dump of that;
+ - DIP is never taken (definitely lies at vector 0x2c -> PC=0xdc01e);
+ - DRQ
+ - All roms seems to be misdumped (too generous sizes), is it intentional?
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "bus/cbus/pc9801_55.h"
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// device type definition
+DEFINE_DEVICE_TYPE(PC9801_55U, pc9801_55u_device, "pc9801_55u", "NEC PC-9801-55U")
+DEFINE_DEVICE_TYPE(PC9801_55L, pc9801_55l_device, "pc9801_55l", "NEC PC-9801-55L")
+
+ROM_START( pc9801_55u )
+ ROM_REGION16_LE( 0x10000, "scsi_bios", ROMREGION_ERASEFF )
+ // JNC2B_00.BIN BADADDR ---xxxxxxxxxxxx
+ // JNC3B_00.BIN BADADDR ---xxxxxxxxxxxx
+ ROM_LOAD16_BYTE( "jnc2b_00.bin", 0x000000, 0x008000, CRC(ddace1b7) SHA1(614569be28a90bd385cf8abc193e629e568125b7) )
+ ROM_LOAD16_BYTE( "jnc3b_00.bin", 0x000001, 0x008000, CRC(b8a8a49e) SHA1(7781dab492df889148e070a7da7ead207e18ed04) )
+ROM_END
+
+const tiny_rom_entry *pc9801_55u_device::device_rom_region() const
+{
+ return ROM_NAME( pc9801_55u );
+}
+
+ROM_START( pc9801_55l )
+ ROM_REGION16_LE( 0x10000, "scsi_bios", ROMREGION_ERASEFF )
+ // ETA1B_00.BIN BADADDR ---xxxxxxxxxxxx
+ // ETA3B_00.BIN BADADDR ---xxxxxxxxxxxx
+ ROM_LOAD16_BYTE( "eta1b_00.bin", 0x000000, 0x008000, CRC(300ff6c1) SHA1(6cdee535b77535fe6c4dda4427aeb803fcdea0b8) )
+ ROM_LOAD16_BYTE( "eta3b_00.bin", 0x000001, 0x008000, CRC(44477512) SHA1(182bb45ba0da7a4f9113e268e04ffca8403cf164) )
+ROM_END
+
+const tiny_rom_entry *pc9801_55l_device::device_rom_region() const
+{
+ return ROM_NAME( pc9801_55l );
+}
+
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
+
+WRITE_LINE_MEMBER(pc9801_55_device::scsi_irq_w)
+{
+ // TODO: should be INT3, but BIOS configures as INT0 somewhere (unhandled dip reading?)
+ m_bus->int_w<0>(state);
+}
+
+void pc9801_55_device::device_add_mconfig(machine_config &config)
+{
+ NSCSI_BUS(config, m_scsi_bus);
+ // TODO: currently returning default_scsi_devices, checkout if true for PC-98
+ NSCSI_CONNECTOR(config, "scsi:0", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:1", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:2", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:3", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:4", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:5", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:6", default_scsi_devices, nullptr);
+ NSCSI_CONNECTOR(config, "scsi:7").option_set("wdc", WD33C93A).machine_config(
+ [this](device_t *device)
+ {
+ wd33c9x_base_device &adapter = downcast<wd33c9x_base_device &>(*device);
+
+ // TODO: unknown clock
+ adapter.set_clock(10'000'000);
+ adapter.irq_cb().set(*this, FUNC(pc9801_55_device::scsi_irq_w));
+ // TODO: DRQ on C-bus
+ //adapter.drq_cb().set(*this, FUNC(pc9801_55_device::scsi_drq));
+ }
+ );
+}
+
+static INPUT_PORTS_START( pc9801_55 )
+ PORT_START("SCSI_DSW1")
+ PORT_DIPNAME( 0x07, 0x07, "PC-9801-55: SCSI board ID") PORT_DIPLOCATION("SCSI_SW1:!1,!2,!3")
+ PORT_DIPSETTING( 0x00, "0" )
+ PORT_DIPSETTING( 0x01, "1" )
+ PORT_DIPSETTING( 0x02, "2" )
+ PORT_DIPSETTING( 0x03, "3" )
+ PORT_DIPSETTING( 0x04, "4" )
+ PORT_DIPSETTING( 0x05, "5" )
+ PORT_DIPSETTING( 0x06, "6" )
+ PORT_DIPSETTING( 0x07, "7" )
+ PORT_DIPNAME( 0x38, 0x18, "PC-9801-55: Interrupt level") PORT_DIPLOCATION("SCSI_SW1:!4,!5,!6")
+ PORT_DIPSETTING( 0x00, "INT0" )
+ PORT_DIPSETTING( 0x08, "INT1" )
+ PORT_DIPSETTING( 0x10, "INT2" )
+ PORT_DIPSETTING( 0x18, "INT3" )
+ PORT_DIPSETTING( 0x20, "INT5" )
+ PORT_DIPSETTING( 0x28, "INT6" )
+ PORT_DIPSETTING( 0x30, DEF_STR( Unknown ) )
+ PORT_DIPSETTING( 0x38, DEF_STR( Unknown ) )
+ PORT_DIPNAME( 0xc0, 0x00, "PC-9801-55: DMA channel") PORT_DIPLOCATION("SCSI_SW1:!7,!8")
+ PORT_DIPSETTING( 0x00, "0" )
+ PORT_DIPSETTING( 0x40, "1 (prohibited)" )
+ PORT_DIPSETTING( 0x80, "2" )
+ PORT_DIPSETTING( 0xc0, "3" )
+
+ PORT_START("SCSI_DSW2")
+ // TODO: understand all valid possible settings of this
+ PORT_DIPNAME( 0x7f, 0x66, "PC-9801-55: machine ID and ROM base address") PORT_DIPLOCATION("SCSI_SW2:!1,!2,!3,!4,!5,!6,!7")
+ PORT_DIPSETTING( 0x66, "i386, 0xdc000-0xddfff")
+ // ...
+ PORT_DIPNAME( 0x80, 0x80, "PC-9801-55: ROM accessibility at Power-On") PORT_DIPLOCATION("SCSI_SW2:!8")
+ PORT_DIPSETTING( 0x80, DEF_STR( Yes ))
+ PORT_DIPSETTING( 0x00, DEF_STR( No ))
+
+ PORT_START("SCSI_JP")
+ // SW3 and SW4 Jumper settings
+ PORT_CONFNAME( 0x03, 0x00, "PC-9801-55: I/O base address")
+ PORT_CONFSETTING( 0x00, "0xcc0") // 01-02 01 02
+ PORT_CONFSETTING( 0x01, "0xcd0")
+ PORT_CONFSETTING( 0x02, "0xce0")
+ PORT_CONFSETTING( 0x03, "0xcf0")
+INPUT_PORTS_END
+
+ioport_constructor pc9801_55_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( pc9801_55 );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// pc9801_55u_device - constructor
+//-------------------------------------------------
+
+pc9801_55_device::pc9801_55_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , m_bus(*this, DEVICE_SELF_OWNER)
+ , m_scsi_bus(*this, "scsi")
+ , m_wdc(*this, "scsi:7:wdc")
+{
+}
+
+pc9801_55u_device::pc9801_55u_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : pc9801_55_device(mconfig, PC9801_55U, tag, owner, clock)
+{
+
+}
+
+pc9801_55l_device::pc9801_55l_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : pc9801_55_device(mconfig, PC9801_55L, tag, owner, clock)
+{
+
+}
+
+
+//-------------------------------------------------
+// device_validity_check - perform validity checks
+// on this device
+//-------------------------------------------------
+
+void pc9801_55_device::device_validity_check(validity_checker &valid) const
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void pc9801_55_device::device_start()
+{
+ m_bus->program_space().install_rom(
+ 0xdc000,
+ 0xddfff,
+ memregion(this->subtag("scsi_bios").c_str())->base()
+ );
+
+ // TODO: docs hints that this has mirrors at 0xcd*, 0xce*, 0xcf*
+ m_bus->install_io(
+ 0xcc0,
+ 0xcc5,
+ read8sm_delegate(*this, FUNC(pc9801_55_device::comms_r)),
+ write8sm_delegate(*this, FUNC(pc9801_55_device::comms_w))
+ );
+
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void pc9801_55_device::device_reset()
+{
+
+}
+
+
+//**************************************************************************
+// READ/WRITE HANDLERS
+//**************************************************************************
+
+u8 pc9801_55_device::comms_r(offs_t offset)
+{
+ if((offset & 1) == 0)
+ {
+ offs_t addr = offset >> 1;
+ if (addr & 2)
+ {
+ logerror("%s: Read to status port [%02x]\n", machine().describe_context(), offset + 0xcc0);
+
+ return 0;
+ }
+
+ return m_wdc->indir_r(addr);
+ }
+ // odd
+
+ logerror("%s: Read to undefined port [%02x]\n", machine().describe_context(), offset + 0xcc0);
+
+ return 0xff;
+}
+
+void pc9801_55_device::comms_w(offs_t offset, u8 data)
+{
+ if((offset & 1) == 0)
+ {
+ offs_t addr = offset >> 1;
+ if (addr & 2)
+ {
+ logerror("%s: Write to command port [%02x] %02x\n", machine().describe_context(), offset + 0xcc0, data);
+
+ return;
+ }
+
+ m_wdc->indir_w(addr, data);
+ return;
+ }
+
+ // odd
+ logerror("%s: Write to undefined port [%02x] %02x\n", machine().describe_context(), offset + 0xcc0, data);
+}
diff --git a/src/devices/bus/cbus/pc9801_55.h b/src/devices/bus/cbus/pc9801_55.h
new file mode 100644
index 00000000000..b74c754c2b8
--- /dev/null
+++ b/src/devices/bus/cbus/pc9801_55.h
@@ -0,0 +1,80 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+/***************************************************************************
+
+ NEC PC-9801-55/-55U/-55L
+
+***************************************************************************/
+
+#ifndef MAME_BUS_CBUS_PC9801_55_H
+#define MAME_BUS_CBUS_PC9801_55_H
+
+#pragma once
+
+#include "bus/cbus/pc9801_cbus.h"
+#include "bus/nscsi/devices.h"
+#include "machine/nscsi_bus.h"
+#include "machine/wd33c9x.h"
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> pc9801_118_device
+
+class pc9801_55_device : public device_t
+{
+public:
+ // construction/destruction
+ //pc9801_55_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ pc9801_55_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ static constexpr feature_type unemulated_features() { return feature::DISK; }
+
+ DECLARE_WRITE_LINE_MEMBER(scsi_irq_w);
+
+protected:
+ // device-level overrides
+ virtual void device_validity_check(validity_checker &valid) const override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ // optional information overrides
+// virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+
+private:
+ required_device<pc9801_slot_device> m_bus;
+ required_device<nscsi_bus_device> m_scsi_bus;
+ required_device<wd33c9x_base_device> m_wdc;
+
+ u8 comms_r(offs_t offset);
+ void comms_w(offs_t offset, u8 data);
+};
+
+class pc9801_55u_device : public pc9801_55_device
+{
+public:
+ pc9801_55u_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+private:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+};
+
+class pc9801_55l_device : public pc9801_55_device
+{
+public:
+ pc9801_55l_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+private:
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+};
+
+// device type definition
+//DECLARE_DEVICE_TYPE(PC9801_55, pc9801_55_device)
+DECLARE_DEVICE_TYPE(PC9801_55U, pc9801_55u_device)
+DECLARE_DEVICE_TYPE(PC9801_55L, pc9801_55l_device)
+
+#endif // MAME_BUS_CBUS_PC9801_55_H
diff --git a/src/devices/bus/cbus/pc9801_86.cpp b/src/devices/bus/cbus/pc9801_86.cpp
index 2b8b9c8d1af..6fcc789e27e 100644
--- a/src/devices/bus/cbus/pc9801_86.cpp
+++ b/src/devices/bus/cbus/pc9801_86.cpp
@@ -1,25 +1,35 @@
// license:BSD-3-Clause
// copyright-holders:Angelo Salese
-/***************************************************************************
+/**************************************************************************************************
NEC PC-9801-86 sound card
NEC PC-9801-SpeakBoard sound card
+ Mad Factory Otomi-chan Kai sound card
Similar to PC-9801-26, this one has YM2608 instead of YM2203 and an
additional DAC port
+
SpeakBoard sound card seems to be derived design from -86, with an additional
OPNA mapped at 0x58*
+ Otomi-chan Kai is a doujinshi sound card based off SpeakBoard design.
+ It uses YM3438 OPL2C mapped at 0x78*, and anything that uses the nax.exe sound driver
+ expects this to be installed as default (cfr. datsumj).
+ To fallback to a regular -26/-86 board user needs to add parameter switches "-2" or "-3"
+ respectively, cfr. "nax -?" for additional details.
+
TODO:
- - Test all pcm modes
- - Make volume work
- - Recording
+ - Test all pcm modes;
+ - Make volume work;
+ - Recording;
- SpeakBoard: no idea about software that uses this, also board shows a single YM2608B?
- "-86 only supports ADPCM instead of PCM, while SpeakBoard has OPNA + 256 Kbit RAM"
- Sounds like a sound core flaw since OPNA requires a rom region in any case;
+ "-86 only supports ADPCM instead of PCM, while SpeakBoard has OPNA + 256 Kbit RAM";
+ - Otomi-chan Kai: find a manual (マニュアル), it's mentioned with nax usage.
+ Very low-res scan of the PCB sports a 4-bit dip-sw bank at very least;
+ - Otomi-chan Kai: unknown ID port readback;
- verify sound irq;
-***************************************************************************/
+**************************************************************************************************/
#include "emu.h"
#include "bus/cbus/pc9801_86.h"
@@ -32,15 +42,22 @@
//**************************************************************************
// device type definition
-DEFINE_DEVICE_TYPE(PC9801_86, pc9801_86_device, "pc9801_86", "pc9801_86")
+DEFINE_DEVICE_TYPE(PC9801_86, pc9801_86_device, "pc9801_86", "NEC PC-9801-86")
WRITE_LINE_MEMBER(pc9801_86_device::sound_irq)
{
m_fmirq = state ? true : false;
- /* TODO: seems to die very often */
+ // TODO: sometimes misfired irq causes sound or even host hang
m_bus->int_w<5>(state || (m_pcmirq ? ASSERT_LINE : CLEAR_LINE));
}
+// only for derived designs?
+void pc9801_86_device::opna_map(address_map &map)
+{
+ // TODO: confirm it really is ROMless
+ // TODO: confirm size
+ map(0x000000, 0x1fffff).ram();
+}
//-------------------------------------------------
// device_add_mconfig - add device configuration
@@ -60,6 +77,8 @@ void pc9801_86_device::pc9801_86_config(machine_config &config)
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
YM2608(config, m_opna, 7.987_MHz_XTAL); // actually YM2608B
+ // shouldn't have one
+// m_opna->set_addrmap(0, &pc9801_86_device::opna_map);
m_opna->irq_handler().set(FUNC(pc9801_86_device::sound_irq));
m_opna->port_a_read_callback().set(FUNC(pc9801_86_device::opn_porta_r));
//m_opna->port_b_read_callback().set(FUNC(pc8801_state::opn_portb_r));
@@ -79,6 +98,16 @@ void pc9801_86_device::device_add_mconfig(machine_config &config)
pc9801_86_config(config);
}
+// helper for derived devices to account for the different master OPNA sound mixing
+void pc9801_86_device::opna_reset_routes_config(machine_config &config)
+{
+ m_opna->reset_routes();
+ m_opna->add_route(0, "lspeaker", 0.50);
+ m_opna->add_route(0, "rspeaker", 0.50);
+ m_opna->add_route(1, "lspeaker", 0.50);
+ m_opna->add_route(2, "rspeaker", 0.50);
+}
+
// to load a different bios for slots:
// -cbusX pc9801_86,bios=N
ROM_START( pc9801_86 )
@@ -87,13 +116,12 @@ ROM_START( pc9801_86 )
// we currently mark bios names based off where they originally belonged to, lacking of a better info
// supposedly these are -86 roms according to eikanwa2 sound card detection,
// loading a -26 rom in a -86 environment causes an hang there.
+ // TODO: several later machines (i.e. CanBe) really has an internal -86 with sound BIOS data coming directly from the machine ROM
+ // it also sports different ID mapping at $a460
ROM_SYSTEM_BIOS( 0, "86rx", "nec86rx" )
ROMX_LOAD( "sound_rx.rom", 0x0000, 0x4000, BAD_DUMP CRC(fe9f57f2) SHA1(d5dbc4fea3b8367024d363f5351baecd6adcd8ef), ROM_BIOS(0) )
- ROM_SYSTEM_BIOS( 1, "86mu", "nec86mu" )
+ ROM_SYSTEM_BIOS( 1, "86mu", "epson86mu" )
ROMX_LOAD( "sound_486mu.rom", 0x0000, 0x4000, BAD_DUMP CRC(6cdfa793) SHA1(4b8250f9b9db66548b79f961d61010558d6d6e1c), ROM_BIOS(1) )
-
- // RAM
- ROM_REGION( 0x100000, "opna", ROMREGION_ERASE00 )
ROM_END
const tiny_rom_entry *pc9801_86_device::device_rom_region() const
@@ -109,10 +137,32 @@ const tiny_rom_entry *pc9801_86_device::device_rom_region() const
static INPUT_PORTS_START( pc9801_86 )
PORT_INCLUDE( pc9801_joy_port )
+ // Single 8-bit DSW bank
+ // TODO: how HW really reads these?
PORT_START("OPNA_DSW")
- PORT_CONFNAME( 0x01, 0x01, "PC-9801-86: Port Base" )
- PORT_CONFSETTING( 0x00, "0x088" )
- PORT_CONFSETTING( 0x01, "0x188" )
+ PORT_DIPNAME( 0x01, 0x00, "PC-9801-86: Port Base" ) PORT_DIPLOCATION("OPNA_SW:!1")
+ PORT_DIPSETTING( 0x00, "0x188" )
+ PORT_DIPSETTING( 0x01, "0x288" )
+ PORT_DIPNAME( 0x02, 0x00, "PC-9801-86: Enable sound ROM") PORT_DIPLOCATION("OPNA_SW:!2")
+ PORT_DIPSETTING( 0x00, DEF_STR( Yes ) ) // hardwired at 0xcc000
+ PORT_DIPSETTING( 0x02, DEF_STR( No ) )
+ PORT_DIPNAME( 0x0c, 0x00, "PC-9801-86: Interrupt level") PORT_DIPLOCATION("OPNA_SW:!3,!4")
+ PORT_DIPSETTING( 0x0c, "IRQ 0" )
+ PORT_DIPSETTING( 0x08, "IRQ 4" )
+ PORT_DIPSETTING( 0x00, "IRQ 5" )
+ PORT_DIPSETTING( 0x04, "IRQ 6" )
+ PORT_DIPNAME( 0x10, 0x00, "PC-9801-86: Interrupt enable") PORT_DIPLOCATION("OPNA_SW:!5")
+ PORT_DIPSETTING( 0x00, DEF_STR( Yes ) )
+ PORT_DIPSETTING( 0x10, DEF_STR( No ) )
+ PORT_DIPNAME( 0xe0, 0x80, "PC-9801-86: ID number") PORT_DIPLOCATION("OPNA_SW:!6,!7,!8")
+ PORT_DIPSETTING( 0x00, "0" )
+ PORT_DIPSETTING( 0x20, "1" )
+ PORT_DIPSETTING( 0x40, "2" )
+ PORT_DIPSETTING( 0x60, "3" )
+ PORT_DIPSETTING( 0x80, "4" )
+ PORT_DIPSETTING( 0xa0, "5" )
+ PORT_DIPSETTING( 0xc0, "6" )
+ PORT_DIPSETTING( 0xe0, "7" )
INPUT_PORTS_END
ioport_constructor pc9801_86_device::device_input_ports() const
@@ -129,12 +179,12 @@ ioport_constructor pc9801_86_device::device_input_ports() const
//-------------------------------------------------
pc9801_86_device::pc9801_86_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : pc9801_snd_device(mconfig, type, tag, owner, clock),
- m_bus(*this, DEVICE_SELF_OWNER),
- m_opna(*this, "opna"),
- m_ldac(*this, "ldac"),
- m_rdac(*this, "rdac"),
- m_queue(QUEUE_SIZE)
+ : pc9801_snd_device(mconfig, type, tag, owner, clock)
+ , m_bus(*this, DEVICE_SELF_OWNER)
+ , m_opna(*this, "opna")
+ , m_ldac(*this, "ldac")
+ , m_rdac(*this, "rdac")
+ , m_queue(QUEUE_SIZE)
{
}
@@ -154,6 +204,11 @@ void pc9801_86_device::device_validity_check(validity_checker &valid) const
{
}
+u16 pc9801_86_device::read_io_base()
+{
+ return ((ioport("OPNA_DSW")->read() & 1) << 8) + 0x188;
+}
+
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
@@ -161,12 +216,19 @@ void pc9801_86_device::device_validity_check(validity_checker &valid) const
void pc9801_86_device::device_start()
{
- m_bus->program_space().install_rom(0xcc000,0xcffff,memregion(this->subtag("sound_bios").c_str())->base());
+ // TODO: uninstall option from dip
+ m_bus->program_space().install_rom(
+ 0xcc000,
+ 0xcffff,
+ memregion(this->subtag("sound_bios").c_str())->base()
+ );
m_bus->install_io(0xa460, 0xa463, read8smo_delegate(*this, FUNC(pc9801_86_device::id_r)), write8smo_delegate(*this, FUNC(pc9801_86_device::mask_w)));
m_bus->install_io(0xa464, 0xa46f, read8sm_delegate(*this, FUNC(pc9801_86_device::pcm_r)), write8sm_delegate(*this, FUNC(pc9801_86_device::pcm_w)));
m_bus->install_io(0xa66c, 0xa66f, read8sm_delegate(*this, [this](offs_t o){ return o == 2 ? m_pcm_mute : 0xff; }, "pc9801_86_mute_r"),
write8sm_delegate(*this, [this](offs_t o, u8 d){ if(o == 2) m_pcm_mute = d; }, "pc9801_86_mute_w"));
+ m_io_base = 0;
+
m_dac_timer = timer_alloc();
save_item(NAME(m_count));
save_item(NAME(m_queue));
@@ -180,9 +242,16 @@ void pc9801_86_device::device_start()
void pc9801_86_device::device_reset()
{
- uint16_t port_base = (ioport("OPNA_DSW")->read() & 1) << 8;
- m_bus->io_space().unmap_readwrite(0x0088, 0x008f, 0x100);
- m_bus->install_io(port_base + 0x0088, port_base + 0x008f, read8sm_delegate(*this, FUNC(pc9801_86_device::opna_r)), write8sm_delegate(*this, FUNC(pc9801_86_device::opna_w)));
+ u16 current_io = read_io_base();
+ m_bus->flush_install_io(
+ this->tag(),
+ m_io_base,
+ current_io,
+ 7,
+ read8sm_delegate(*this, FUNC(pc9801_86_device::opna_r)),
+ write8sm_delegate(*this, FUNC(pc9801_86_device::opna_w))
+ );
+ m_io_base = current_io;
m_mask = 0;
m_head = m_tail = m_count = 0;
@@ -200,36 +269,40 @@ void pc9801_86_device::device_reset()
//**************************************************************************
-uint8_t pc9801_86_device::opna_r(offs_t offset)
+u8 pc9801_86_device::opna_r(offs_t offset)
{
if((offset & 1) == 0)
return m_opna->read(offset >> 1);
else // odd
{
- logerror("PC9801-86: Read to undefined port [%02x]\n",offset+0x188);
+ logerror("%s: Read to undefined port [%02x]\n", machine().describe_context(), offset + m_io_base);
return 0xff;
}
}
-void pc9801_86_device::opna_w(offs_t offset, uint8_t data)
+void pc9801_86_device::opna_w(offs_t offset, u8 data)
{
if((offset & 1) == 0)
m_opna->write(offset >> 1,data);
else // odd
- logerror("PC9801-86: Write to undefined port [%02x] %02x\n",offset+0x188,data);
+ logerror("%s: Write to undefined port [%02x] %02x\n", machine().describe_context(), offset + m_io_base, data);
}
-uint8_t pc9801_86_device::id_r()
+u8 pc9801_86_device::id_r()
{
- return 0x40 | m_mask;
+ // either a -86 or 9821 MATE A uses this id (built-in)
+ const u8 id_port = ((ioport("OPNA_DSW")->read() & 1) << 4) | 0x40;
+ return id_port | m_mask;
}
-void pc9801_86_device::mask_w(uint8_t data)
+void pc9801_86_device::mask_w(u8 data)
{
m_mask = data & 1;
+ // TODO: bit 1 totally cuts off OPNA output
+ logerror("%s: OPNA mask setting %02x\n", machine().describe_context(), data);
}
-uint8_t pc9801_86_device::pcm_r(offs_t offset)
+u8 pc9801_86_device::pcm_r(offs_t offset)
{
if((offset & 1) == 0)
{
@@ -251,7 +324,7 @@ uint8_t pc9801_86_device::pcm_r(offs_t offset)
return 0xff;
}
-void pc9801_86_device::pcm_w(offs_t offset, uint8_t data)
+void pc9801_86_device::pcm_w(offs_t offset, u8 data)
{
const u32 rate = (25.4_MHz_XTAL).value() / 16;
const int divs[8] = {36, 48, 72, 96, 144, 192, 288, 384};
@@ -301,9 +374,9 @@ int pc9801_86_device::queue_count()
return m_count;
}
-uint8_t pc9801_86_device::queue_pop()
+u8 pc9801_86_device::queue_pop()
{
- uint8_t ret = m_queue[m_tail++];
+ u8 ret = m_queue[m_tail++];
m_tail %= QUEUE_SIZE;
m_count = (m_count - 1) % QUEUE_SIZE; // dangel resets the fifo after filling it completely so maybe it expects an underflow
return ret;
@@ -356,7 +429,9 @@ void pc9801_86_device::device_timer(emu_timer& timer, device_timer_id id, int pa
}
//**************************************************************************
+//
// SpeakBoard device section
+//
//**************************************************************************
DEFINE_DEVICE_TYPE(PC9801_SPEAKBOARD, pc9801_speakboard_device, "pc9801_spb", "NEC PC9801 SpeakBoard")
@@ -365,11 +440,6 @@ ROM_START( pc9801_spb )
ROM_REGION( 0x4000, "sound_bios", ROMREGION_ERASEFF )
ROM_LOAD16_BYTE( "spb lh5764 ic21_pink.bin", 0x0001, 0x2000, CRC(5bcefa1f) SHA1(ae88e45d411bf5de1cb42689b12b6fca0146c586) )
ROM_LOAD16_BYTE( "spb lh5764 ic22_green.bin", 0x0000, 0x2000, CRC(a7925ced) SHA1(3def9ee386ab6c31436888261bded042cd64a0eb) )
-
- // RAM
- ROM_REGION( 0x100000, "opna", ROMREGION_ERASE00 )
-
- ROM_REGION( 0x100000, "opna_slave", ROMREGION_ERASE00 )
ROM_END
const tiny_rom_entry *pc9801_speakboard_device::device_rom_region() const
@@ -377,32 +447,21 @@ const tiny_rom_entry *pc9801_speakboard_device::device_rom_region() const
return ROM_NAME( pc9801_spb );
}
-
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// pc9801_speakboard_device - constructor
-//-------------------------------------------------
-
pc9801_speakboard_device::pc9801_speakboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : pc9801_86_device(mconfig, PC9801_SPEAKBOARD, tag, owner, clock),
- m_opna_slave(*this, "opna_slave")
+ : pc9801_86_device(mconfig, PC9801_SPEAKBOARD, tag, owner, clock)
+ , m_opna_slave(*this, "opna_slave")
{
}
void pc9801_speakboard_device::device_add_mconfig(machine_config &config)
{
pc9801_86_config(config);
-
- m_opna->reset_routes();
- m_opna->add_route(0, "lspeaker", 0.50);
- m_opna->add_route(0, "rspeaker", 0.50);
- m_opna->add_route(1, "lspeaker", 0.50);
- m_opna->add_route(2, "rspeaker", 0.50);
+ opna_reset_routes_config(config);
+ // TODO: confirm RAM mapping configuration (shared? not present on either chip? misc?)
+ m_opna->set_addrmap(0, &pc9801_speakboard_device::opna_map);
YM2608(config, m_opna_slave, 7.987_MHz_XTAL);
+ m_opna_slave->set_addrmap(0, &pc9801_speakboard_device::opna_map);
m_opna_slave->add_route(0, "lspeaker", 0.50);
m_opna_slave->add_route(0, "rspeaker", 0.50);
m_opna_slave->add_route(1, "lspeaker", 0.50);
@@ -421,22 +480,96 @@ void pc9801_speakboard_device::device_reset()
pc9801_86_device::device_reset();
}
-uint8_t pc9801_speakboard_device::opna_slave_r(offs_t offset)
+u8 pc9801_speakboard_device::opna_slave_r(offs_t offset)
{
if((offset & 1) == 0)
return m_opna_slave->read(offset >> 1);
else // odd
{
- logerror("PC9801-SPB: Read to undefined port [%02x]\n",offset+0x588);
+ logerror("%s: Read to undefined port [%02x]\n", machine().describe_context(), offset + 0x588);
return 0xff;
}
}
-void pc9801_speakboard_device::opna_slave_w(offs_t offset, uint8_t data)
+void pc9801_speakboard_device::opna_slave_w(offs_t offset, u8 data)
{
if((offset & 1) == 0)
m_opna_slave->write(offset >> 1,data);
else // odd
- logerror("PC9801-SPB: Write to undefined port [%02x] %02x\n",offset+0x588,data);
+ logerror("%s: Write to undefined port [%02x] %02x\n", machine().describe_context(), offset + 0x588, data);
}
+//**************************************************************************
+//
+// Otomi-chan Kai device section
+//
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE(OTOMICHAN_KAI, otomichan_kai_device, "pc98_otomichan_kai", "MAD Factory Otomi-chan Kai") // 音美(おとみ)ちゃん改
+
+otomichan_kai_device::otomichan_kai_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : pc9801_86_device(mconfig, OTOMICHAN_KAI, tag, owner, clock)
+ , m_opn2c(*this, "opn2c")
+{
+}
+
+ROM_START( pc98_otomichan_kai )
+ ROM_REGION( 0x4000, "sound_bios", ROMREGION_ERASEFF )
+ // TODO: "compatible" with SpeakBoard, does it even uses a ROM altogether? low-res PCB pic doesn't help at all.
+ ROM_LOAD16_BYTE( "spb lh5764 ic21_pink.bin", 0x0001, 0x2000, BAD_DUMP CRC(5bcefa1f) SHA1(ae88e45d411bf5de1cb42689b12b6fca0146c586) )
+ ROM_LOAD16_BYTE( "spb lh5764 ic22_green.bin", 0x0000, 0x2000, BAD_DUMP CRC(a7925ced) SHA1(3def9ee386ab6c31436888261bded042cd64a0eb) )
+ROM_END
+
+const tiny_rom_entry *otomichan_kai_device::device_rom_region() const
+{
+ return ROM_NAME( pc98_otomichan_kai );
+}
+
+void otomichan_kai_device::device_add_mconfig(machine_config &config)
+{
+ pc9801_86_config(config);
+ opna_reset_routes_config(config);
+ // TODO: confirm if this has OPNA RAM
+ m_opna->set_addrmap(0, &otomichan_kai_device::opna_map);
+
+ YM3438(config, m_opn2c, 7.987_MHz_XTAL);
+ m_opn2c->add_route(0, "lspeaker", 0.50);
+ m_opn2c->add_route(1, "rspeaker", 0.50);
+}
+
+u8 otomichan_kai_device::id_r()
+{
+ // no ID, unconfirmed if it has mask
+ return 0xf0 | m_mask;
+}
+
+void otomichan_kai_device::device_start()
+{
+ pc9801_86_device::device_start();
+
+ m_bus->install_io(0x0788, 0x078f, read8sm_delegate(*this, FUNC(otomichan_kai_device::opn2c_r)), write8sm_delegate(*this, FUNC(otomichan_kai_device::opn2c_w)));
+}
+
+void otomichan_kai_device::device_reset()
+{
+ pc9801_86_device::device_reset();
+}
+
+u8 otomichan_kai_device::opn2c_r(offs_t offset)
+{
+ if((offset & 1) == 0)
+ return m_opn2c->read(offset >> 1);
+ else // odd
+ {
+ logerror("%s: Read to undefined port [%02x]\n", machine().describe_context(), offset + 0x788);
+ return 0xff;
+ }
+}
+
+void otomichan_kai_device::opn2c_w(offs_t offset, u8 data)
+{
+ if((offset & 1) == 0)
+ m_opn2c->write(offset >> 1, data);
+ else // odd
+ logerror("%s: Write to undefined port [%02x] %02x\n", machine().describe_context(), offset + 0x788, data);
+}
diff --git a/src/devices/bus/cbus/pc9801_86.h b/src/devices/bus/cbus/pc9801_86.h
index 21de4102f01..5dda6681f6b 100644
--- a/src/devices/bus/cbus/pc9801_86.h
+++ b/src/devices/bus/cbus/pc9801_86.h
@@ -29,13 +29,6 @@ public:
pc9801_86_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
pc9801_86_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
- uint8_t opna_r(offs_t offset);
- void opna_w(offs_t offset, uint8_t data);
- uint8_t id_r();
- void mask_w(uint8_t data);
- uint8_t pcm_r(offs_t offset);
- void pcm_w(offs_t offset, uint8_t data);
-
DECLARE_WRITE_LINE_MEMBER(sound_irq);
protected:
@@ -45,25 +38,37 @@ protected:
virtual void device_reset() override;
// optional information overrides
virtual void device_add_mconfig(machine_config &config) override;
+ void opna_reset_routes_config(machine_config &config);
virtual ioport_constructor device_input_ports() const override;
virtual const tiny_rom_entry *device_rom_region() const override;
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
void pc9801_86_config(machine_config &config);
+ virtual u16 read_io_base() override;
required_device<pc9801_slot_device> m_bus;
required_device<ym2608_device> m_opna;
+ void opna_map(address_map &map);
+
+ u8 opna_r(offs_t offset);
+ void opna_w(offs_t offset, u8 data);
+ virtual u8 id_r();
+ void mask_w(u8 data);
+ u8 pcm_r(offs_t offset);
+ void pcm_w(offs_t offset, u8 data);
+
+ u8 m_mask;
+
private:
int queue_count();
- uint8_t queue_pop();
-
+ u8 queue_pop();
- uint8_t m_mask, m_pcm_mode, m_vol[7], m_pcm_ctrl, m_pcm_mute;
+ u8 m_pcm_mode, m_vol[7], m_pcm_ctrl, m_pcm_mute;
uint16_t m_head, m_tail, m_count, m_irq_rate;
bool m_pcmirq, m_fmirq, m_pcm_clk, m_init;
required_device<dac_word_interface> m_ldac;
required_device<dac_word_interface> m_rdac;
- std::vector<uint8_t> m_queue;
+ std::vector<u8> m_queue;
emu_timer *m_dac_timer;
};
@@ -73,8 +78,10 @@ public:
// construction/destruction
pc9801_speakboard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- uint8_t opna_slave_r(offs_t offset);
- void opna_slave_w(offs_t offset, uint8_t data);
+ static constexpr feature_type imperfect_features() { return feature::SOUND; }
+
+ u8 opna_slave_r(offs_t offset);
+ void opna_slave_w(offs_t offset, u8 data);
protected:
virtual void device_add_mconfig(machine_config &config) override;
@@ -86,13 +93,33 @@ private:
required_device<ym2608_device> m_opna_slave;
};
+class otomichan_kai_device : public pc9801_86_device
+{
+public:
+ // construction/destruction
+ otomichan_kai_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-// device type definition
-DECLARE_DEVICE_TYPE(PC9801_86, pc9801_86_device)
-DECLARE_DEVICE_TYPE(PC9801_SPEAKBOARD, pc9801_speakboard_device)
+ static constexpr feature_type imperfect_features() { return feature::SOUND; }
+ u8 opn2c_r(offs_t offset);
+ void opn2c_w(offs_t offset, u8 data);
+protected:
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+
+private:
+ required_device<ym3438_device> m_opn2c;
+
+ virtual u8 id_r() override;
+};
+// device type definition
+DECLARE_DEVICE_TYPE(PC9801_86, pc9801_86_device)
+DECLARE_DEVICE_TYPE(PC9801_SPEAKBOARD, pc9801_speakboard_device)
+DECLARE_DEVICE_TYPE(OTOMICHAN_KAI, otomichan_kai_device)
#endif // MAME_BUS_CBUS_PC9801_86_H
diff --git a/src/devices/bus/cbus/pc9801_amd98.cpp b/src/devices/bus/cbus/pc9801_amd98.cpp
index a6eeb015c4c..5b4d66bbdff 100644
--- a/src/devices/bus/cbus/pc9801_amd98.cpp
+++ b/src/devices/bus/cbus/pc9801_amd98.cpp
@@ -1,6 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Angelo Salese
-/***************************************************************************
+/**************************************************************************************************
System Sacom AMD-98 (AmuseMent boarD)
@@ -13,7 +13,7 @@
- PIT control;
- PCM section;
-=============================================================================
+===================================================================================================
- Known games with AMD-98 support
Brown's Run (System Sacom)
@@ -25,7 +25,7 @@
Relics (Bothtec)
Thexder (Game Arts)
-***************************************************************************/
+**************************************************************************************************/
#include "emu.h"
#include "bus/cbus/pc9801_amd98.h"
@@ -37,7 +37,7 @@
//**************************************************************************
// device type definition
-DEFINE_DEVICE_TYPE(PC9801_AMD98, pc9801_amd98_device, "pc9801_amd98", "pc9801_amd98")
+DEFINE_DEVICE_TYPE(PC9801_AMD98, pc9801_amd98_device, "pc9801_amd98", "System Sacom AMD-98")
//-------------------------------------------------
// device_add_mconfig - add device configuration
@@ -101,11 +101,11 @@ ioport_constructor pc9801_amd98_device::device_input_ports() const
//-------------------------------------------------
pc9801_amd98_device::pc9801_amd98_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, PC9801_AMD98, tag, owner, clock),
- m_bus(*this, DEVICE_SELF_OWNER),
- m_ay1(*this, "ay1"),
- m_ay2(*this, "ay2"),
- m_ay3(*this, "ay3")
+ : device_t(mconfig, PC9801_AMD98, tag, owner, clock)
+ , m_bus(*this, DEVICE_SELF_OWNER)
+ , m_ay1(*this, "ay1")
+ , m_ay2(*this, "ay2")
+ , m_ay3(*this, "ay3")
{
}
diff --git a/src/devices/bus/cbus/pc9801_amd98.h b/src/devices/bus/cbus/pc9801_amd98.h
index fa031edbe1b..f26246c768b 100644
--- a/src/devices/bus/cbus/pc9801_amd98.h
+++ b/src/devices/bus/cbus/pc9801_amd98.h
@@ -2,7 +2,7 @@
// copyright-holders:Angelo Salese
/***************************************************************************
- NEC PC-9801-118
+ System Sacom AMD-98 (AmuseMent boarD)
***************************************************************************/
@@ -14,12 +14,11 @@
#include "bus/cbus/pc9801_cbus.h"
#include "sound/ay8910.h"
-
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
-// ======================> pc9801_118_device
+// ======================> pc9801_amd98_device
class pc9801_amd98_device : public device_t
{
@@ -54,12 +53,7 @@ private:
};
-
// device type definition
DECLARE_DEVICE_TYPE(PC9801_AMD98, pc9801_amd98_device)
-
-
-
-
-#endif // MAME_BUS_CBUS_PC9801_118_H
+#endif // MAME_BUS_CBUS_PC9801_AMD98_H
diff --git a/src/devices/bus/cbus/pc9801_cbus.cpp b/src/devices/bus/cbus/pc9801_cbus.cpp
index 649676d31f1..9077d8cc4ea 100644
--- a/src/devices/bus/cbus/pc9801_cbus.cpp
+++ b/src/devices/bus/cbus/pc9801_cbus.cpp
@@ -1,15 +1,23 @@
// license:BSD-3-Clause
// copyright-holders:Angelo Salese
-/**********************************************************************
+/**************************************************************************************************
C-bus slot interface for PC-98xx family
a.k.a. NEC version of the ISA bus.
+ C-bus -> Card Bus
TODO:
- stub interface, checkout what actually belongs here.
+ Speculation is that C-bus has ROM / RAM slots always in the 0xc0000-0xdffff region,
+ and some opacity can be added if true.
+ - move pc9801_cbus_devices declaration from pc9801 driver in here;
+ - 8-bit I/O smearing should be handled here;
+ - INT# should be handled here too;
+ - Best way to inform user when it tries to install incompatible boards?
+ - Support for PCI bridging on later machines (cfr. pc9801cx3);
-**********************************************************************/
+**************************************************************************************************/
#include "emu.h"
#include "pc9801_cbus.h"
@@ -123,3 +131,35 @@ template void pc9801_slot_device::install_io<read8_delegate, write8_delegate
template void pc9801_slot_device::install_io<read8s_delegate, write8s_delegate >(offs_t start, offs_t end, read8s_delegate rhandler, write8s_delegate whandler);
template void pc9801_slot_device::install_io<read8sm_delegate, write8sm_delegate >(offs_t start, offs_t end, read8sm_delegate rhandler, write8sm_delegate whandler);
template void pc9801_slot_device::install_io<read8smo_delegate, write8smo_delegate>(offs_t start, offs_t end, read8smo_delegate rhandler, write8smo_delegate whandler);
+
+// boilerplate code for boards that has configurable I/O with either Jumpers or Dip-Switches
+// NB: client must have a mechanism to remember what port has been used before and after calling this,
+// in order to avoid "last instantiated wins" issues with overlapping board full configs.
+void pc9801_slot_device::flush_install_io(const char *client_tag, u16 old_io, u16 new_io, u16 size, read8sm_delegate rhandler, write8sm_delegate whandler)
+{
+ // initialize if client have this unmapped (such as first boot)
+ // device_start fns cannot read input ports ...
+ if (old_io == 0)
+ old_io = new_io;
+
+ logerror("%s: %s uninstall I/O at %04x-%04x\n",
+ this->tag(),
+ client_tag,
+ old_io,
+ old_io + size
+ );
+ this->io_space().unmap_readwrite(old_io, old_io + size);
+
+ logerror("%s: %s install I/O at %04x-%04x\n",
+ this->tag(),
+ client_tag,
+ new_io,
+ new_io + size
+ );
+ this->install_io(
+ new_io,
+ new_io + size,
+ rhandler,
+ whandler
+ );
+}
diff --git a/src/devices/bus/cbus/pc9801_cbus.h b/src/devices/bus/cbus/pc9801_cbus.h
index 728aca3e692..ab7085dfa86 100644
--- a/src/devices/bus/cbus/pc9801_cbus.h
+++ b/src/devices/bus/cbus/pc9801_cbus.h
@@ -113,6 +113,8 @@ public:
template<int I> void int_w(bool state) { m_int_callback[I](state); }
template<typename R, typename W> void install_io(offs_t start, offs_t end, R rhandler, W whandler);
+ void flush_install_io(const char *client_tag, u16 old_io, u16 new_io, u16 size, read8sm_delegate rhandler, write8sm_delegate whandler);
+
protected:
// device-level overrides
virtual void device_start() override;
diff --git a/src/devices/bus/cbus/pc9801_snd.cpp b/src/devices/bus/cbus/pc9801_snd.cpp
index 6a611d77e78..3a33cfe6757 100644
--- a/src/devices/bus/cbus/pc9801_snd.cpp
+++ b/src/devices/bus/cbus/pc9801_snd.cpp
@@ -3,21 +3,19 @@
/***************************************************************************
NEC PC-9801
- common functions for CBUS sound boards -26, -86, -118
+ common functions for C-bus sound boards -26, -86, -118
***************************************************************************/
#include "emu.h"
#include "pc9801_snd.h"
-//DEFINE_DEVICE_TYPE(PC9801_SND, pc9801_snd_device, "pc9801_snd", "PC9801 CBUS Sound")
-
pc9801_snd_device::pc9801_snd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, type, tag, owner, clock)
{
}
-uint8_t pc9801_snd_device::opn_porta_r()
+u8 pc9801_snd_device::opn_porta_r()
{
if(m_joy_sel & 0x80)
return ioport(m_joy_sel & 0x40 ? "PA2" : "PA1")->read();
@@ -25,7 +23,7 @@ uint8_t pc9801_snd_device::opn_porta_r()
return 0xff;
}
-void pc9801_snd_device::opn_portb_w(uint8_t data) { m_joy_sel = data; }
+void pc9801_snd_device::opn_portb_w(u8 data) { m_joy_sel = data; }
INPUT_PORTS_START(pc9801_joy_port)
PORT_START("PA1")
diff --git a/src/devices/bus/cbus/pc9801_snd.h b/src/devices/bus/cbus/pc9801_snd.h
index c7408c09383..0c9c694a4e3 100644
--- a/src/devices/bus/cbus/pc9801_snd.h
+++ b/src/devices/bus/cbus/pc9801_snd.h
@@ -18,11 +18,13 @@ public:
pc9801_snd_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
protected:
- uint8_t opn_porta_r();
- void opn_portb_w(uint8_t data);
+ u8 opn_porta_r();
+ void opn_portb_w(u8 data);
+ u16 m_io_base;
+ virtual u16 read_io_base() = 0;
private:
- uint8_t m_joy_sel;
+ u8 m_joy_sel;
};
//DECLARE_DEVICE_TYPE(PC9801_SND, pc9801_snd_device)