summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author angelosa <lordkale4@gmail.com>2025-04-15 00:18:01 +0200
committer angelosa <lordkale4@gmail.com>2025-04-15 00:18:01 +0200
commitf6d743b937814e95df449e8657d55ceef8bd3d2d (patch)
tree8272ae9326b26aa33ced3a212447284c3a0a28a0
parent0855f614ed5bdd8de70af532121fb11d2ee88c16 (diff)
nec/pc98: convert SDIP to device
-rw-r--r--src/mame/nec/pc9801.cpp61
-rw-r--r--src/mame/nec/pc9801.h9
-rw-r--r--src/mame/nec/pc9821.cpp15
-rw-r--r--src/mame/nec/pc98_kbd.cpp27
-rw-r--r--src/mame/nec/pc98_kbd.h4
-rw-r--r--src/mame/nec/pc98_memsw.cpp39
-rw-r--r--src/mame/nec/pc98_memsw.h23
-rw-r--r--src/mame/nec/pc98_sdip.cpp99
-rw-r--r--src/mame/nec/pc98_sdip.h39
-rw-r--r--src/mame/nec/pc98ha.cpp2
10 files changed, 183 insertions, 135 deletions
diff --git a/src/mame/nec/pc9801.cpp b/src/mame/nec/pc9801.cpp
index 1b6ebd923b2..cf751f06e5f 100644
--- a/src/mame/nec/pc9801.cpp
+++ b/src/mame/nec/pc9801.cpp
@@ -656,7 +656,7 @@ void pc9801_state::pc9801_common_io(address_map &map)
// map.unmap_value_high();
map(0x0000, 0x001f).rw(m_dmac, FUNC(am9517a_device::read), FUNC(am9517a_device::write)).umask16(0xff00);
map(0x0000, 0x001f).rw(FUNC(pc9801_state::pic_r), FUNC(pc9801_state::pic_w)).umask16(0x00ff); // i8259 PIC (bit 3 ON slave / master) / i8237 DMA
- map(0x0020, 0x002f).w(FUNC(pc9801_state::rtc_w)).umask16(0x00ff);
+ map(0x0020, 0x0020).w(FUNC(pc9801_state::rtc_w));
map(0x0030, 0x0037).rw(m_ppi_sys, FUNC(i8255_device::read), FUNC(i8255_device::write)).umask16(0xff00);
map(0x0030, 0x0033).rw(m_sio_rs, FUNC(i8251_device::read), FUNC(i8251_device::write)).umask16(0x00ff); //i8251 RS232c / i8255 system port
map(0x0040, 0x0047).rw(m_ppi_prn, FUNC(i8255_device::read), FUNC(i8255_device::write)).umask16(0x00ff);
@@ -1248,47 +1248,23 @@ void pc9801vm_state::pc9801rs_io(address_map &map)
map(0xe0d0, 0xe0d3).r(FUNC(pc9801vm_state::midi_r));
}
-// SDIP handling
-// TODO: move to device
-
-template<unsigned port> u8 pc9801us_state::sdip_r(offs_t offset)
-{
- u8 sdip_offset = port + (m_sdip_bank * 12);
-
- return m_sdip[sdip_offset];
-}
-
-template<unsigned port> void pc9801us_state::sdip_w(offs_t offset, u8 data)
-{
- u8 sdip_offset = port + (m_sdip_bank * 12);
-
- m_sdip[sdip_offset] = data;
-}
-
-void pc9801us_state::sdip_bank_w(offs_t offset, u8 data)
-{
- // TODO: depending on model type this is hooked up differently
- // (or be not hooked up at all like in 9801US case)
- m_sdip_bank = (data & 0x40) >> 6;
-}
-
void pc9801us_state::pc9801us_io(address_map &map)
{
pc9801rs_io(map);
map(0x0430, 0x0433).rw(FUNC(pc9801us_state::ide_ctrl_r), FUNC(pc9801us_state::ide_ctrl_w)).umask16(0x00ff);
- map(0x841e, 0x841e).rw(FUNC(pc9801us_state::sdip_r<0x0>), FUNC(pc9801us_state::sdip_w<0x0>));
- map(0x851e, 0x851e).rw(FUNC(pc9801us_state::sdip_r<0x1>), FUNC(pc9801us_state::sdip_w<0x1>));
- map(0x861e, 0x861e).rw(FUNC(pc9801us_state::sdip_r<0x2>), FUNC(pc9801us_state::sdip_w<0x2>));
- map(0x871e, 0x871e).rw(FUNC(pc9801us_state::sdip_r<0x3>), FUNC(pc9801us_state::sdip_w<0x3>));
- map(0x881e, 0x881e).rw(FUNC(pc9801us_state::sdip_r<0x4>), FUNC(pc9801us_state::sdip_w<0x4>));
- map(0x891e, 0x891e).rw(FUNC(pc9801us_state::sdip_r<0x5>), FUNC(pc9801us_state::sdip_w<0x5>));
- map(0x8a1e, 0x8a1e).rw(FUNC(pc9801us_state::sdip_r<0x6>), FUNC(pc9801us_state::sdip_w<0x6>));
- map(0x8b1e, 0x8b1e).rw(FUNC(pc9801us_state::sdip_r<0x7>), FUNC(pc9801us_state::sdip_w<0x7>));
- map(0x8c1e, 0x8c1e).rw(FUNC(pc9801us_state::sdip_r<0x8>), FUNC(pc9801us_state::sdip_w<0x8>));
- map(0x8d1e, 0x8d1e).rw(FUNC(pc9801us_state::sdip_r<0x9>), FUNC(pc9801us_state::sdip_w<0x9>));
- map(0x8e1e, 0x8e1e).rw(FUNC(pc9801us_state::sdip_r<0xa>), FUNC(pc9801us_state::sdip_w<0xa>));
- map(0x8f1e, 0x8f1e).rw(FUNC(pc9801us_state::sdip_r<0xb>), FUNC(pc9801us_state::sdip_w<0xb>));
- map(0x8f1f, 0x8f1f).w(FUNC(pc9801us_state::sdip_bank_w));
+ map(0x841e, 0x841e).rw(m_sdip, FUNC(pc98_sdip_device::read<0x0>), FUNC(pc98_sdip_device::write<0x0>));
+ map(0x851e, 0x851e).rw(m_sdip, FUNC(pc98_sdip_device::read<0x1>), FUNC(pc98_sdip_device::write<0x1>));
+ map(0x861e, 0x861e).rw(m_sdip, FUNC(pc98_sdip_device::read<0x2>), FUNC(pc98_sdip_device::write<0x2>));
+ map(0x871e, 0x871e).rw(m_sdip, FUNC(pc98_sdip_device::read<0x3>), FUNC(pc98_sdip_device::write<0x3>));
+ map(0x881e, 0x881e).rw(m_sdip, FUNC(pc98_sdip_device::read<0x4>), FUNC(pc98_sdip_device::write<0x4>));
+ map(0x891e, 0x891e).rw(m_sdip, FUNC(pc98_sdip_device::read<0x5>), FUNC(pc98_sdip_device::write<0x5>));
+ map(0x8a1e, 0x8a1e).rw(m_sdip, FUNC(pc98_sdip_device::read<0x6>), FUNC(pc98_sdip_device::write<0x6>));
+ map(0x8b1e, 0x8b1e).rw(m_sdip, FUNC(pc98_sdip_device::read<0x7>), FUNC(pc98_sdip_device::write<0x7>));
+ map(0x8c1e, 0x8c1e).rw(m_sdip, FUNC(pc98_sdip_device::read<0x8>), FUNC(pc98_sdip_device::write<0x8>));
+ map(0x8d1e, 0x8d1e).rw(m_sdip, FUNC(pc98_sdip_device::read<0x9>), FUNC(pc98_sdip_device::write<0x9>));
+ map(0x8e1e, 0x8e1e).rw(m_sdip, FUNC(pc98_sdip_device::read<0xa>), FUNC(pc98_sdip_device::write<0xa>));
+ map(0x8f1e, 0x8f1e).rw(m_sdip, FUNC(pc98_sdip_device::read<0xb>), FUNC(pc98_sdip_device::write<0xb>));
+ map(0x8f1f, 0x8f1f).w(m_sdip, FUNC(pc98_sdip_device::bank_w));
}
void pc9801bx_state::pc9801bx2_map(address_map &map)
@@ -2137,8 +2113,6 @@ MACHINE_START_MEMBER(pc9801vm_state,pc9801rs)
MACHINE_START_MEMBER(pc9801us_state,pc9801us)
{
MACHINE_START_CALL_MEMBER(pc9801rs);
-
- save_pointer(NAME(m_sdip), 24);
}
MACHINE_START_MEMBER(pc9801bx_state,pc9801bx2)
@@ -2630,6 +2604,8 @@ void pc9801us_state::pc9801us(machine_config &config)
m_maincpu->set_irq_acknowledge_callback("pic8259_master", FUNC(pic8259_device::inta_cb));
config_floppy_35hd(config);
+
+ PC98_SDIP(config, "sdip", 0);
}
void pc9801us_state::pc9801fs(machine_config &config)
@@ -2641,13 +2617,14 @@ void pc9801us_state::pc9801fs(machine_config &config)
m_maincpu->set_addrmap(AS_IO, &pc9801us_state::pc9801us_io);
m_maincpu->set_irq_acknowledge_callback("pic8259_master", FUNC(pic8259_device::inta_cb));
-
// optional 3'5 floppies x2
config_floppy_525hd(config);
// optional SCSI HDD
pit_clock_config(config, xtal / 4);
+
+ PC98_SDIP(config, "sdip", 0);
}
void pc9801bx_state::pc9801bx2(machine_config &config)
@@ -2664,6 +2641,8 @@ void pc9801bx_state::pc9801bx2(machine_config &config)
pit_clock_config(config, xtal / 4); // unknown, fixes timer error at POST, /4 ~ /7
+ PC98_SDIP(config, "sdip", 0);
+
// minimum RAM: 1.8 / 3.6 MB (?)
// maximum RAM: 19.6 MB
// GDC & EGC, DAC1BIT built-in
diff --git a/src/mame/nec/pc9801.h b/src/mame/nec/pc9801.h
index 84ecb504f88..a09837a39e4 100644
--- a/src/mame/nec/pc9801.h
+++ b/src/mame/nec/pc9801.h
@@ -57,6 +57,7 @@
#include "pc98_cd.h"
#include "pc98_kbd.h"
#include "pc98_memsw.h"
+#include "pc98_sdip.h"
#include "bus/ata/atadev.h"
#include "bus/ata/ataintf.h"
@@ -538,6 +539,7 @@ class pc9801us_state : public pc9801vm_state
public:
pc9801us_state(const machine_config &mconfig, device_type type, const char *tag)
: pc9801vm_state(mconfig, type, tag)
+ , m_sdip(*this, "sdip")
{
}
void pc9801us(machine_config &config);
@@ -551,12 +553,7 @@ protected:
// SDIP, PC9801DA onward
protected:
- u8 m_sdip[24];
-private:
- u8 m_sdip_bank;
- template<unsigned port> u8 sdip_r(offs_t offset);
- template<unsigned port> void sdip_w(offs_t offset, u8 data);
- void sdip_bank_w(offs_t offset, u8 data);
+ required_device<pc98_sdip_device> m_sdip;
};
/**********************************************************
diff --git a/src/mame/nec/pc9821.cpp b/src/mame/nec/pc9821.cpp
index 332750036c5..3cf162285ad 100644
--- a/src/mame/nec/pc9821.cpp
+++ b/src/mame/nec/pc9821.cpp
@@ -446,7 +446,13 @@ void pc9821_state::pc9821_io(address_map &map)
map(0x0000, 0x001f).rw(m_dmac, FUNC(am9517a_device::read), FUNC(am9517a_device::write)).umask32(0xff00ff00);
map(0x0000, 0x001f).lr8(NAME([this] (offs_t o) { return BIT(o, 1) ? 0xff : pic_r(o); })).umask32(0x00ff00ff);
map(0x0000, 0x001f).w(FUNC(pc9821_state::pic_w)).umask32(0x00ff00ff); // i8259 PIC (bit 3 ON slave / master) / i8237 DMA
- map(0x0020, 0x002f).w(FUNC(pc9821_state::rtc_w)).umask32(0x000000ff);
+ map(0x0020, 0x0020).w(FUNC(pc9821_state::rtc_w));
+ map(0x0022, 0x0022).lw8(NAME([this] (offs_t offset, u8 data) {
+ // TODO: r/w to both ports, superset of uPD4990A
+ // Reportedly buggy with DOS/Win95 off the bat, can use HRTIMER.SYS/BCKWHEAT.SYS as fallback
+ if (BIT(data, 4))
+ popmessage("rtc_w: extended uPD4993(A) mode enable %02x", data);
+ }));
map(0x0020, 0x002f).w(FUNC(pc9821_state::dmapg8_w)).umask32(0xff00ff00);
map(0x0030, 0x0037).rw(m_ppi_sys, FUNC(i8255_device::read), FUNC(i8255_device::write)).umask32(0xff00ff00); //i8251 RS232c / i8255 system port
map(0x0040, 0x0047).rw(m_ppi_prn, FUNC(i8255_device::read), FUNC(i8255_device::write)).umask32(0x00ff00ff);
@@ -497,7 +503,7 @@ void pc9821_state::pc9821_io(address_map &map)
map(0x0ca0, 0x0ca0).lr8(NAME([] () { return 0xff; })); // high reso detection
// map(0x0cc0, 0x0cc7) SCSI interface / <undefined>
// map(0x0cfc, 0x0cff) PCI bus
- map(0x1e8c, 0x1e8f).noprw(); // IDE RAM switch
+ map(0x1e8c, 0x1e8f).noprw(); // TODO: IDE RAM switch
map(0x2ed0, 0x2edf).lr8(NAME([] (address_space &s, offs_t o, u8 mm) { return 0xff; })).umask32(0xffffffff); // unknown sound related
map(0x3fd8, 0x3fdf).r(m_pit, FUNC(pit8253_device::read)).umask16(0xff00);
map(0x3fd8, 0x3fdf).w(FUNC(pc9821_state::pit_latch_delay)).umask16(0xff00);
@@ -846,6 +852,8 @@ void pc9821_state::pc9821(machine_config &config)
PALETTE(config.replace(), m_palette, FUNC(pc9821_state::pc9801_palette), 16 + 16 + 256);
// m_hgdc[1]->set_display_pixels(FUNC(pc9821_state::pegc_display_pixels));
+
+ PC98_SDIP(config, "sdip", 0);
}
void pc9821_mate_a_state::pc9821as(machine_config &config)
@@ -1224,7 +1232,8 @@ ROM_END
ROM_START( pc9821ce2 )
ROM_REGION16_LE( 0x30000, "ipl", ROMREGION_ERASEFF )
- ROM_LOAD( "itf_ce2.rom", 0x10000, 0x008000, CRC(273e9e88) SHA1(9bca7d5116788776ed0f297bccb4dfc485379b41) )
+ // baddump: missing setup menu bank
+ ROM_LOAD( "itf_ce2.rom", 0x10000, 0x008000, BAD_DUMP CRC(273e9e88) SHA1(9bca7d5116788776ed0f297bccb4dfc485379b41) )
ROM_LOAD( "bios_ce2.rom", 0x18000, 0x018000, BAD_DUMP CRC(76affd90) SHA1(910fae6763c0cd59b3957b6cde479c72e21f33c1) )
ROM_REGION( 0x80000, "chargen", 0 )
diff --git a/src/mame/nec/pc98_kbd.cpp b/src/mame/nec/pc98_kbd.cpp
index aee77b00b96..36b0ef7b35f 100644
--- a/src/mame/nec/pc98_kbd.cpp
+++ b/src/mame/nec/pc98_kbd.cpp
@@ -28,22 +28,8 @@ TODO:
#include "pc98_kbd.h"
#include "machine/keyboard.ipp"
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-
-// device type definition
DEFINE_DEVICE_TYPE(PC98_KBD, pc98_kbd_device, "pc98_kbd", "NEC PC-98 Keyboard")
-
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// pc98_kbd_device - constructor
-//-------------------------------------------------
-
pc98_kbd_device::pc98_kbd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, PC98_KBD, tag, owner, clock)
, device_buffered_serial_interface(mconfig, *this)
@@ -54,30 +40,17 @@ pc98_kbd_device::pc98_kbd_device(const machine_config &mconfig, const char *tag,
{
}
-//-------------------------------------------------
-// device_validity_check - perform validity checks
-// on this device
-//-------------------------------------------------
-
void pc98_kbd_device::device_validity_check(validity_checker &valid) const
{
}
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
void pc98_kbd_device::device_start()
{
// ...
}
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
void pc98_kbd_device::device_reset()
{
clear_fifo();
diff --git a/src/mame/nec/pc98_kbd.h b/src/mame/nec/pc98_kbd.h
index 69c3a8f65f6..acf4904a3d8 100644
--- a/src/mame/nec/pc98_kbd.h
+++ b/src/mame/nec/pc98_kbd.h
@@ -1,10 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Angelo Salese
-/***************************************************************************
- PC-9801 Keyboard simulation
-
-***************************************************************************/
#ifndef MAME_NEC_PC98_KBD_H
#define MAME_NEC_PC98_KBD_H
diff --git a/src/mame/nec/pc98_memsw.cpp b/src/mame/nec/pc98_memsw.cpp
index fa78efe8329..dccfda0df89 100644
--- a/src/mame/nec/pc98_memsw.cpp
+++ b/src/mame/nec/pc98_memsw.cpp
@@ -1,6 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:Angelo Salese
-/***************************************************************************
+/**************************************************************************************************
PC-9801 MEMSW interface
@@ -74,51 +74,27 @@
- Is the mapping truly aligned to 2 bytes? Looks more like 4, needs real
HW verification.
-***************************************************************************/
+**************************************************************************************************/
#include "emu.h"
#include "pc98_memsw.h"
#include "coreutil.h"
-//**************************************************************************
-// GLOBAL VARIABLES
-//**************************************************************************
-
-// device type definition
DEFINE_DEVICE_TYPE(PC98_MEMSW, pc98_memsw_device, "pc98_memsw", "NEC PC-98 Memory Switch device")
-
-//**************************************************************************
-// LIVE DEVICE
-//**************************************************************************
-
-//-------------------------------------------------
-// pc98_memsw_device - constructor
-//-------------------------------------------------
-
pc98_memsw_device::pc98_memsw_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, PC98_MEMSW, tag, owner, clock),
- device_nvram_interface(mconfig, *this)
+ : device_t(mconfig, PC98_MEMSW, tag, owner, clock)
+ , device_nvram_interface(mconfig, *this)
{
}
-
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
void pc98_memsw_device::device_start()
{
save_pointer(NAME(m_bram), m_bram_size);
}
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
void pc98_memsw_device::device_reset()
{
}
@@ -154,16 +130,13 @@ bool pc98_memsw_device::nvram_write(util::write_stream &file)
return !err;
}
-//**************************************************************************
-// READ/WRITE HANDLERS
-//**************************************************************************
-uint8_t pc98_memsw_device::read(uint8_t offset)
+uint8_t pc98_memsw_device::read(offs_t offset)
{
return m_bram[offset];
}
-void pc98_memsw_device::write( uint8_t offset, uint8_t data )
+void pc98_memsw_device::write(offs_t offset, uint8_t data )
{
m_bram[offset] = data;
}
diff --git a/src/mame/nec/pc98_memsw.h b/src/mame/nec/pc98_memsw.h
index 37f2d69be25..da818235cb7 100644
--- a/src/mame/nec/pc98_memsw.h
+++ b/src/mame/nec/pc98_memsw.h
@@ -1,10 +1,5 @@
// license:BSD-3-Clause
// copyright-holders:Angelo Salese
-/***************************************************************************
-
-Template for skeleton device
-
-***************************************************************************/
#ifndef MAME_NEC_PC98_MEMSW_H
#define MAME_NEC_PC98_MEMSW_H
@@ -14,26 +9,14 @@ Template for skeleton device
#include "machine/nvram.h"
-//**************************************************************************
-// INTERFACE CONFIGURATION MACROS
-//**************************************************************************
-
-
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// ======================> pc98_memsw_device
-
class pc98_memsw_device : public device_t,
- public device_nvram_interface
+ public device_nvram_interface
{
public:
pc98_memsw_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- uint8_t read(uint8_t offset);
- void write(uint8_t offset, uint8_t data);
+ uint8_t read(offs_t offset);
+ void write(offs_t offset, uint8_t data);
protected:
virtual void device_start() override ATTR_COLD;
diff --git a/src/mame/nec/pc98_sdip.cpp b/src/mame/nec/pc98_sdip.cpp
new file mode 100644
index 00000000000..8ad0ecf2c88
--- /dev/null
+++ b/src/mame/nec/pc98_sdip.cpp
@@ -0,0 +1,99 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+/**************************************************************************************************
+
+PC-9801 S[oftware]DIP interface
+
+TODO:
+- Discards saved settings;
+
+**************************************************************************************************/
+
+#include "emu.h"
+#include "pc98_sdip.h"
+
+DEFINE_DEVICE_TYPE(PC98_SDIP, pc98_sdip_device, "pc98_sdip", "NEC PC-98 SDIP device")
+
+pc98_sdip_device::pc98_sdip_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, PC98_SDIP, tag, owner, clock)
+ , device_nvram_interface(mconfig, *this)
+{
+}
+
+void pc98_sdip_device::device_start()
+{
+ save_pointer(NAME(m_sdip_ram), m_sdip_size);
+ save_item(NAME(m_bank));
+}
+
+
+void pc98_sdip_device::device_reset()
+{
+ m_bank = 0;
+}
+
+
+void pc98_sdip_device::nvram_default()
+{
+ std::fill(std::begin(m_sdip_ram), std::end(m_sdip_ram), 0xff);
+}
+
+bool pc98_sdip_device::nvram_read(util::read_stream &file)
+{
+ auto const [err, actual_size] = util::read(file, m_sdip_ram, m_sdip_size);
+ return !err && (actual_size == m_sdip_size);
+}
+
+bool pc98_sdip_device::nvram_write(util::write_stream &file)
+{
+ auto const [err, actual_size] = util::write(file, m_sdip_ram, m_sdip_size);
+ return !err;
+}
+
+
+template<unsigned port> u8 pc98_sdip_device::read(offs_t offset)
+{
+ u8 sdip_offset = port + (m_bank * 12);
+
+ return m_sdip_ram[sdip_offset];
+}
+
+template<unsigned port> void pc98_sdip_device::write(offs_t offset, u8 data)
+{
+ u8 sdip_offset = port + (m_bank * 12);
+
+ m_sdip_ram[sdip_offset] = data;
+}
+
+void pc98_sdip_device::bank_w(offs_t offset, u8 data)
+{
+ // TODO: depending on model type this is hooked up differently
+ // (or be not hooked up at all like in 9801US case)
+ m_bank = !!(BIT(data, 6));
+}
+
+template u8 pc98_sdip_device::read<0>(offs_t offset);
+template u8 pc98_sdip_device::read<1>(offs_t offset);
+template u8 pc98_sdip_device::read<2>(offs_t offset);
+template u8 pc98_sdip_device::read<3>(offs_t offset);
+template u8 pc98_sdip_device::read<4>(offs_t offset);
+template u8 pc98_sdip_device::read<5>(offs_t offset);
+template u8 pc98_sdip_device::read<6>(offs_t offset);
+template u8 pc98_sdip_device::read<7>(offs_t offset);
+template u8 pc98_sdip_device::read<8>(offs_t offset);
+template u8 pc98_sdip_device::read<9>(offs_t offset);
+template u8 pc98_sdip_device::read<10>(offs_t offset);
+template u8 pc98_sdip_device::read<11>(offs_t offset);
+
+template void pc98_sdip_device::write<0>(offs_t offset, u8 data);
+template void pc98_sdip_device::write<1>(offs_t offset, u8 data);
+template void pc98_sdip_device::write<2>(offs_t offset, u8 data);
+template void pc98_sdip_device::write<3>(offs_t offset, u8 data);
+template void pc98_sdip_device::write<4>(offs_t offset, u8 data);
+template void pc98_sdip_device::write<5>(offs_t offset, u8 data);
+template void pc98_sdip_device::write<6>(offs_t offset, u8 data);
+template void pc98_sdip_device::write<7>(offs_t offset, u8 data);
+template void pc98_sdip_device::write<8>(offs_t offset, u8 data);
+template void pc98_sdip_device::write<9>(offs_t offset, u8 data);
+template void pc98_sdip_device::write<10>(offs_t offset, u8 data);
+template void pc98_sdip_device::write<11>(offs_t offset, u8 data);
diff --git a/src/mame/nec/pc98_sdip.h b/src/mame/nec/pc98_sdip.h
new file mode 100644
index 00000000000..8dff5d391f5
--- /dev/null
+++ b/src/mame/nec/pc98_sdip.h
@@ -0,0 +1,39 @@
+// license:BSD-3-Clause
+// copyright-holders:Angelo Salese
+
+#ifndef MAME_NEC_PC98_SDIP_H
+#define MAME_NEC_PC98_SDIP_H
+
+#pragma once
+
+#include "machine/nvram.h"
+
+
+class pc98_sdip_device : public device_t,
+ public device_nvram_interface
+{
+public:
+ pc98_sdip_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ template <unsigned port> u8 read(offs_t offset);
+ template <unsigned port> void write(offs_t offset, u8 data);
+ void bank_w(offs_t offset, u8 data);
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void nvram_default() override;
+ virtual bool nvram_read(util::read_stream &file) override;
+ virtual bool nvram_write(util::write_stream &file) override;
+
+private:
+ u8 m_sdip_ram[24];
+ const u8 m_sdip_size = 24;
+ bool m_bank = 0;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(PC98_SDIP, pc98_sdip_device)
+
+#endif // MAME_NEC_PC98_SDIP_H
diff --git a/src/mame/nec/pc98ha.cpp b/src/mame/nec/pc98ha.cpp
index 9a1d7acd9d2..8d44315b249 100644
--- a/src/mame/nec/pc98ha.cpp
+++ b/src/mame/nec/pc98ha.cpp
@@ -150,7 +150,7 @@ void pc98lt_state::lt_io(address_map &map)
{
map.unmap_value_high();
// map(0x0000, 0x001f) // PIC (bit 3 ON slave / master), V50 internal / <undefined>
- map(0x0020, 0x002f).w(FUNC(pc98lt_state::rtc_w)).umask16(0x00ff);
+ map(0x0020, 0x0020).w(FUNC(pc98lt_state::rtc_w));
map(0x0030, 0x0037).rw(m_ppi_sys, FUNC(i8255_device::read), FUNC(i8255_device::write)).umask16(0xff00);
map(0x0030, 0x0033).rw(m_sio_rs, FUNC(i8251_device::read), FUNC(i8251_device::write)).umask16(0x00ff); //i8251 RS232c / i8255 system port
map(0x0040, 0x0047).rw(m_ppi_prn, FUNC(i8255_device::read), FUNC(i8255_device::write)).umask16(0x00ff);