diff --git a/hash/hp9825b_rom.xml b/hash/hp9825b_rom.xml
new file mode 100644
index 00000000000..0daca82ecae
--- /dev/null
+++ b/hash/hp9825b_rom.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+ 9885 ROM for 9825
+ 1976
+ Hewlett-Packard
+
+
+
+
+
+
+
+
+
+ 9885/9895 ROM for 9825
+ 1980
+ Hewlett-Packard
+
+
+
+
+
+
+
+
+
+ SSS mass storage ROM
+ 1984
+ Structured Software Systems
+
+
+
+
+
+
+
+
+
+ Matrix ROM for 9825
+ 1976
+ Hewlett-Packard
+
+
+
+
+
+
+
+
diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua
index 5d57448facb..da475f25379 100644
--- a/scripts/src/bus.lua
+++ b/scripts/src/bus.lua
@@ -3832,6 +3832,18 @@ if (BUSES["HP80_IO"]~=null) then
}
end
+---------------------------------------------------
+--
+--@src/devices/bus/hp_optroms/hp_optrom.h,BUSES["HP_OPTROM"] = true
+---------------------------------------------------
+
+if (BUSES["HP9825_OPTROM"]~=null) then
+ files {
+ MAME_DIR .. "src/devices/bus/hp9825_optroms/hp9825_optrom.cpp",
+ MAME_DIR .. "src/devices/bus/hp9825_optroms/hp9825_optrom.h",
+ }
+end
+
---------------------------------------------------
--
--@src/devices/bus/hp9845_io/hp9845_io.h,BUSES["HP9845_IO"] = true
diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua
index 79313910ef1..8ce66040e49 100644
--- a/scripts/target/mame/mess.lua
+++ b/scripts/target/mame/mess.lua
@@ -806,6 +806,7 @@ BUSES["JAKKS_GAMEKEY"] = true
BUSES["HP_OPTROM"] = true
BUSES["HP80_OPTROM"] = true
BUSES["HP80_IO"] = true
+BUSES["HP9825_OPTROM"] = true
BUSES["HP9845_IO"] = true
BUSES["KC"] = true
BUSES["LPCI"] = true
diff --git a/src/devices/bus/hp9825_optroms/hp9825_optrom.cpp b/src/devices/bus/hp9825_optroms/hp9825_optrom.cpp
new file mode 100644
index 00000000000..56e1758ebe0
--- /dev/null
+++ b/src/devices/bus/hp9825_optroms/hp9825_optrom.cpp
@@ -0,0 +1,179 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ hp9825_optrom.cpp
+
+ Optional ROMs for HP9825 systems
+
+*********************************************************************/
+
+#include "emu.h"
+#include "hp9825_optrom.h"
+#include "softlist.h"
+
+// Debugging
+//#define VERBOSE 1
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(HP9825_OPTROM_CART, hp9825_optrom_cart_device, "hp9825_optrom_cart", "HP9825 optional ROM cartridge")
+DEFINE_DEVICE_TYPE(HP9825_OPTROM_SLOT, hp9825_optrom_slot_device, "hp9825_optrom_slot", "HP9825 optional ROM slot")
+
+struct optrom_region {
+ offs_t m_start;
+ offs_t m_size;
+ const char *m_tag;
+};
+
+constexpr std::array region_tab =
+ {{
+ { 0x3000 , 0x400 , "rom3000" },
+ { 0x3400 , 0x400 , "rom3400" },
+ { 0x3800 , 0x400 , "rom3800" },
+ { 0x3c00 , 0x400 , "rom3c00" },
+ { 0x4000 , 0x400 , "rom4000" },
+ { 0x4400 , 0x800 , "rom4400" },
+ { 0x4c00 , 0x400 , "rom4c00" },
+ { 0x5c00 ,0x2000 , "rom5c00" }
+ }};
+
+// +-------------------------+
+// |hp9825_optrom_cart_device|
+// +-------------------------+
+hp9825_optrom_cart_device::hp9825_optrom_cart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : hp9825_optrom_cart_device(mconfig , HP9825_OPTROM_CART , tag , owner , clock)
+{
+}
+
+hp9825_optrom_cart_device::hp9825_optrom_cart_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_slot_card_interface(mconfig, *this)
+{
+}
+
+// +-------------------------+
+// |hp9825_optrom_slot_device|
+// +-------------------------+
+hp9825_optrom_slot_device::hp9825_optrom_slot_device(machine_config const &mconfig, char const *tag, device_t *owner)
+ : hp9825_optrom_slot_device(mconfig, tag, owner, (uint32_t)0)
+{
+}
+
+hp9825_optrom_slot_device::hp9825_optrom_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, HP9825_OPTROM_SLOT, tag, owner, clock)
+ , device_image_interface(mconfig, *this)
+ , device_slot_interface(mconfig, *this)
+ , m_cart(nullptr)
+ , m_rom_limit(0xffffU)
+ , m_loaded_regions(0)
+ , m_space_r(nullptr)
+ , m_bank(*this , "rombank")
+{
+ option_reset();
+ option_add_internal("rom", HP9825_OPTROM_CART);
+ set_default_option(nullptr);
+ set_fixed(false);
+}
+
+hp9825_optrom_slot_device::~hp9825_optrom_slot_device()
+{
+}
+
+void hp9825_optrom_slot_device::install_rw_handlers(address_space *space_r , address_space *space_w)
+{
+ LOG("limit=%04x\n" , m_rom_limit);
+ m_loaded_regions = 0;
+ m_space_r = space_r;
+
+ unsigned mask = 1;
+
+ for (const struct optrom_region& reg : region_tab) {
+ uint8_t *ptr = get_software_region(reg.m_tag);
+ if (ptr != nullptr) {
+ LOG("%s loaded\n" , reg.m_tag);
+ if (reg.m_start == 0x5c00) {
+ space_r->install_rom(0x3000 , 0x33ff , ptr);
+ space_r->install_device(0x5c00 , 0x5fff , *m_bank , &address_map_bank_device::amap16);
+ m_bank->space(AS_PROGRAM).install_rom(0 , 0x1fff , ptr);
+ } else {
+ space_r->install_rom(reg.m_start , reg.m_start + reg.m_size - 1 , ptr);
+ }
+ m_loaded_regions |= mask;
+ }
+ mask <<= 1;
+ }
+ if (space_w != nullptr) {
+ space_w->install_write_tap(0 , 0x3ff , "bank_switch" ,
+ [this](offs_t offset, u16 &data, u16 mem_mask) {
+ if (BIT(offset , 5)) {
+ LOG("bank = %u\n" , offset & 7);
+ m_bank->set_bank(offset & 7);
+ }
+ });
+ }
+}
+
+void hp9825_optrom_slot_device::device_add_mconfig(machine_config &config)
+{
+ ADDRESS_MAP_BANK(config , m_bank).set_options(ENDIANNESS_BIG , 16 , 13 , 0x400).set_shift(-1);
+}
+
+void hp9825_optrom_slot_device::device_start()
+{
+ m_cart = dynamic_cast(get_card_device());
+}
+
+image_init_result hp9825_optrom_slot_device::call_load()
+{
+ LOG("hp9825_optrom: call_load\n");
+ if (m_cart == nullptr || !loaded_through_softlist()) {
+ LOG("hp9825_optrom: must be loaded from sw list\n");
+ return image_init_result::FAIL;
+ }
+
+ for (const struct optrom_region& reg : region_tab) {
+ auto len = get_software_region_length(reg.m_tag) / 2;
+ if (len != 0) {
+ if (len != reg.m_size) {
+ LOG("Region %s: wrong size (%u should be %u)\n" , reg.m_tag , len , reg.m_size);
+ return image_init_result::FAIL;
+ }
+ if (reg.m_start >= m_rom_limit) {
+ LOG("Region %s beyond ROM limit (start=%04x , limit=%04x)\n" , reg.m_tag , reg.m_start , m_rom_limit);
+ return image_init_result::FAIL;
+ }
+ }
+ }
+
+ return image_init_result::PASS;
+}
+
+void hp9825_optrom_slot_device::call_unload()
+{
+ LOG("hp9825_optrom: call_unload\n");
+ if (m_space_r != nullptr && m_loaded_regions) {
+ unsigned mask = 1;
+
+ for (const struct optrom_region& reg : region_tab) {
+ if (m_loaded_regions & mask) {
+ if (reg.m_start == 0x5c00) {
+ m_space_r->unmap_read(0x3000 , 0x33ff);
+ m_space_r->unmap_read(0x5c00 , 0x5fff);
+ m_bank->space(AS_PROGRAM).unmap_read(0 , 0x1fff);
+ } else {
+ m_space_r->unmap_read(reg.m_start , reg.m_start + reg.m_size - 1);
+ }
+ LOG("%s unloaded\n" , reg.m_tag);
+ }
+ mask <<= 1;
+ }
+ m_loaded_regions = 0;
+ }
+ machine().schedule_soft_reset();
+}
+
+std::string hp9825_optrom_slot_device::get_default_card_software(get_default_card_software_hook &hook) const
+{
+ return software_get_default_slot("rom");
+}
+
diff --git a/src/devices/bus/hp9825_optroms/hp9825_optrom.h b/src/devices/bus/hp9825_optroms/hp9825_optrom.h
new file mode 100644
index 00000000000..127710c8340
--- /dev/null
+++ b/src/devices/bus/hp9825_optroms/hp9825_optrom.h
@@ -0,0 +1,79 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ hp9825_optrom.h
+
+ Optional ROMs for HP9825 systems
+
+*********************************************************************/
+#ifndef MAME_BUS_HP9825_OPTROMS_HP9825_OPTROM_H
+#define MAME_BUS_HP9825_OPTROMS_HP9825_OPTROM_H
+
+#pragma once
+
+#include "softlist_dev.h"
+#include "machine/bankdev.h"
+
+class hp9825_optrom_cart_device : public device_t,
+ public device_slot_card_interface
+{
+public:
+ // construction/destruction
+ hp9825_optrom_cart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ hp9825_optrom_cart_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ // device-level overrides
+ virtual void device_start() override { }
+};
+
+class hp9825_optrom_slot_device : public device_t,
+ public device_image_interface,
+ public device_slot_interface
+{
+public:
+ // construction/destruction
+ hp9825_optrom_slot_device(machine_config const &mconfig, char const *tag, device_t *owner);
+ hp9825_optrom_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~hp9825_optrom_slot_device();
+
+ void set_rom_limit(offs_t rom_limit) { m_rom_limit = rom_limit; }
+
+ void install_rw_handlers(address_space *space_r , address_space *space_w);
+
+protected:
+ // device-level overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_start() override;
+
+ // image-level overrides
+ virtual image_init_result call_load() override;
+ virtual void call_unload() override;
+ virtual const software_list_loader &get_software_list_loader() const override { return rom_software_list_loader::instance(); }
+
+ virtual iodevice_t image_type() const override { return IO_ROM; }
+ virtual bool is_readable() const override { return true; }
+ virtual bool is_writeable() const override { return false; }
+ virtual bool is_creatable() const override { return false; }
+ virtual bool must_be_loaded() const override { return false; }
+ virtual bool is_reset_on_load() const override { return true; }
+ virtual const char *image_interface() const override { return "hp9825_rom"; }
+ virtual const char *file_extensions() const override { return "bin"; }
+
+ // slot interface overrides
+ virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override;
+
+ hp9825_optrom_cart_device *m_cart;
+ offs_t m_rom_limit;
+ unsigned m_loaded_regions;
+ address_space *m_space_r;
+ required_device m_bank;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(HP9825_OPTROM_SLOT, hp9825_optrom_slot_device)
+DECLARE_DEVICE_TYPE(HP9825_OPTROM_CART, hp9825_optrom_cart_device)
+
+#endif /* MAME_BUS_HP9825_OPTROMS_HP9825_OPTROM_H */
diff --git a/src/devices/bus/hp9845_io/98034.cpp b/src/devices/bus/hp9845_io/98034.cpp
index 9f016eaa3d8..388e10c469f 100644
--- a/src/devices/bus/hp9845_io/98034.cpp
+++ b/src/devices/bus/hp9845_io/98034.cpp
@@ -107,6 +107,7 @@ void hp98034_io_card_device::device_reset()
m_idr = 0;
m_odr = 0;
m_force_flg = false;
+ m_flg = true;
m_mode_reg = 0xff;
m_clr_hpib = false;
m_ctrl_out = 0;
@@ -133,14 +134,24 @@ READ16_MEMBER(hp98034_io_card_device::reg_r)
m_force_flg = true;
update_flg();
- // PPU pauses for an instant to let NP see FLG=0 immediately
- // There's a bug in Mass Memory opt. ROM because the PPU
- // doesn't wait for FLG from 98034 in a few (common) cases.
- // A magic combination of relative speeds between PPU and
- // NP always hides this bug in the real hw.
- space.device().execute().spin_until_time(attotime::from_usec(5));
- LOG("read R%u=%04x\n" , offset + 4 , res);
+ // This and the following scheduler acrobatics are meant
+ // to work around a lot of race conditions between hybrid
+ // CPU and Nanoprocessor. Apparently HP people cut a few
+ // cornerns for the sake of transfer speed (such as avoiding
+ // to wait for FLG in selected places) but didn't fully
+ // realize how tight the speed margins were.
+ // The goals of the scheduler manipulation are:
+ // - Quick propagation between processors of FLG setting &
+ // clearing
+ // - Delay the scheduling of hybrid CPU when FLG is set by NP.
+ // This is meant to gain some margin to NP in the race with
+ // CPU (in real hw the margin was probably no more than a
+ // couple of µs).
+ machine().scheduler().boost_interleave(attotime::from_usec(5) , attotime::from_usec(100));
+ space.device().execute().spin();
+ machine().scheduler().synchronize();
+ LOG("%.06f RD R%u=%04x %s\n" , machine().time().as_double() , offset + 4 , res , machine().describe_context());
return res;
}
@@ -159,16 +170,17 @@ WRITE16_MEMBER(hp98034_io_card_device::reg_w)
m_force_flg = true;
update_flg();
- // PPU pauses for an instant to let NP see FLG=0 immediately
- // (see above)
- space.device().execute().spin_until_time(attotime::from_usec(5));
- LOG("write R%u=%04x\n" , offset + 4 , data);
+ // See reg_r above
+ machine().scheduler().boost_interleave(attotime::from_usec(5) , attotime::from_usec(100));
+ space.device().execute().spin();
+ machine().scheduler().synchronize();
+ LOG("%.06f WR R%u=%04x %s\n" , machine().time().as_double() , offset + 4 , data , machine().describe_context());
}
WRITE8_MEMBER(hp98034_io_card_device::dc_w)
{
if (data != m_dc) {
- //LOG("DC=%02x\n" , data);
+ LOG("%.06f DC=%02x\n" , machine().time().as_double() , data);
m_dc = data;
update_dc();
}
@@ -228,7 +240,7 @@ READ8_MEMBER(hp98034_io_card_device::hpib_ctrl_r)
if (!m_ieee488->eoi_r()) {
BIT_SET(res , 7);
}
-
+ LOG("%.06f DS2=%02x\n" , machine().time().as_double() , res);
return res;
}
@@ -249,14 +261,20 @@ WRITE8_MEMBER(hp98034_io_card_device::odr_w)
READ8_MEMBER(hp98034_io_card_device::mode_reg_r)
{
+ LOG("%.06f MR=%02x\n" , machine().time().as_double() , m_mode_reg);
return m_mode_reg;
}
WRITE8_MEMBER(hp98034_io_card_device::mode_reg_clear_w)
{
+ LOG("%.06f clear_w\n" , machine().time().as_double());
m_mode_reg = 0xff;
m_force_flg = false;
- update_flg();
+ if (update_flg()) {
+ // See reg_r above
+ machine().scheduler().boost_interleave(attotime::zero , attotime::from_usec(100));
+ machine().scheduler().synchronize();
+ }
}
READ8_MEMBER(hp98034_io_card_device::switch_r)
@@ -284,13 +302,24 @@ void hp98034_io_card_device::update_dc()
{
irq_w(!BIT(m_dc , 0));
sts_w(BIT(m_dc , 4));
- update_flg();
+ if (update_flg()) {
+ // See reg_r above
+ machine().scheduler().boost_interleave(attotime::zero , attotime::from_usec(100));
+ machine().scheduler().synchronize();
+ }
update_clr_hpib();
}
-void hp98034_io_card_device::update_flg()
+bool hp98034_io_card_device::update_flg()
{
- flg_w(BIT(m_dc , 3) && !m_force_flg);
+ bool new_flg = BIT(m_dc , 3) && !m_force_flg;
+ if (new_flg != m_flg) {
+ m_flg = new_flg;
+ flg_w(m_flg);
+ return true;
+ } else {
+ return false;
+ }
}
void hp98034_io_card_device::update_np_irq()
@@ -331,7 +360,6 @@ void hp98034_io_card_device::update_clr_hpib()
update_data_out();
update_ctrl_out();
update_np_irq();
- LOG("clr_hpib %d\n" , m_clr_hpib);
}
ROM_START(hp98034)
@@ -366,8 +394,9 @@ const tiny_rom_entry *hp98034_io_card_device::device_rom_region() const
void hp98034_io_card_device::device_add_mconfig(machine_config &config)
{
// Clock for NP is generated by a RC oscillator. Manual says its typical frequency
- // is around 2 MHz.
- HP_NANOPROCESSOR(config, m_cpu, 2000000);
+ // is around 2 MHz. A quick simulation of the oscillator gives the following data though:
+ // 2.5 MHz frequency, 33% duty cycle.
+ HP_NANOPROCESSOR(config, m_cpu, 2500000);
m_cpu->set_addrmap(AS_PROGRAM, &hp98034_io_card_device::np_program_map);
m_cpu->set_addrmap(AS_IO, &hp98034_io_card_device::np_io_map);
m_cpu->dc_changed().set(FUNC(hp98034_io_card_device::dc_w));
diff --git a/src/devices/bus/hp9845_io/98034.h b/src/devices/bus/hp9845_io/98034.h
index 45efc059a3a..16cf334894b 100644
--- a/src/devices/bus/hp9845_io/98034.h
+++ b/src/devices/bus/hp9845_io/98034.h
@@ -69,6 +69,7 @@ private:
uint8_t m_odr; // Output Data Register
bool m_force_flg;
uint8_t m_mode_reg;
+ bool m_flg;
// 488 bus state
bool m_clr_hpib;
@@ -76,7 +77,7 @@ private:
uint8_t m_data_out;
void update_dc();
- void update_flg();
+ bool update_flg();
void update_np_irq();
void update_data_out();
void update_ctrl_out();
diff --git a/src/devices/bus/hp9845_io/hp9885.cpp b/src/devices/bus/hp9845_io/hp9885.cpp
index e4a2fc9f33c..e3b407d2976 100644
--- a/src/devices/bus/hp9845_io/hp9885.cpp
+++ b/src/devices/bus/hp9845_io/hp9885.cpp
@@ -415,10 +415,11 @@ void hp9885_device::device_timer(emu_timer &timer, device_timer_id id, int param
return;
} else {
preset_crc();
- m_word_cnt = 129;
if (m_op == OP_READ) {
+ m_word_cnt = 129;
set_state(FSM_RD_DATA);
} else {
+ m_word_cnt = 130;
set_state(FSM_WR_DATA);
m_pll.start_writing(m_pll.ctime);
m_had_transition = false;
@@ -484,17 +485,20 @@ void hp9885_device::device_timer(emu_timer &timer, device_timer_id id, int param
case FSM_WR_DATA:
{
m_word_cnt--;
- if (m_word_cnt > 1) {
+ if (m_word_cnt > 2) {
if (BIT(m_status , STS_XFER_COMPLETE)) {
wr_word(0);
} else {
wr_word(m_input);
- if (m_word_cnt > 2) {
+ if (m_word_cnt > 3) {
set_ibf(false);
}
}
- } else if (m_word_cnt == 1) {
+ } else if (m_word_cnt == 2) {
wr_word(m_crc);
+ } else if (m_word_cnt == 1) {
+ // Post-amble
+ wr_word(0);
} else {
m_pll.stop_writing(m_drive , m_pll.ctime);
// Move to next sector
diff --git a/src/mame/drivers/hp9825.cpp b/src/mame/drivers/hp9825.cpp
index 39c92bbe7cc..d1512fa31c8 100644
--- a/src/mame/drivers/hp9825.cpp
+++ b/src/mame/drivers/hp9825.cpp
@@ -20,8 +20,8 @@
// - I/O expansion slots: 98032, 98034 & 98035 modules can be connected
// - For 9825T: the so-called SKOAL mechanism that transparently overlays RAM & ROM
// in the same address space
-// What's not yet in:
// - External expansion ROMs
+// What's not yet in:
// - Configurable RAM size
//
// Thanks to Dyke Shaffer for publishing (on https://groups.io/g/VintHPcom)
@@ -32,6 +32,8 @@
// For what regards the 9825T, I'd like to thank again Dyke Shaffer for
// publishing a lot of internal HP docs about the SKOAL card. I recovered the
// content of SKOAL ROM from its printed & scanned dump.
+// I'd also like to thank Paul Berger for providing the images of the optional
+// mass storage ROMs (see http://www.hpmuseum.net).
//
// 9825A can also be emulated. At the moment I haven't all the necessary
// ROM dumps, though.
@@ -41,11 +43,13 @@
#include "machine/timer.h"
#include "machine/hp9825_tape.h"
#include "machine/hp98x5_io_sys.h"
+#include "bus/hp9825_optroms/hp9825_optrom.h"
#include "bus/hp9845_io/hp9845_io.h"
#include "imagedev/bitbngr.h"
#include "speaker.h"
#include "sound/beep.h"
#include "hp9825.lh"
+#include "softlist.h"
// Debugging
#define VERBOSE 0
@@ -99,6 +103,7 @@ public:
hp9825_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_cpu(*this , "cpu")
+ , m_rom_drawers(*this , "drawer%u" , 0U)
, m_io_sys(*this , "io_sys")
, m_cursor_timer(*this , "cursor_timer")
, m_tape(*this , "tape")
@@ -123,6 +128,7 @@ protected:
virtual void machine_reset() override;
required_device m_cpu;
+ required_device_array m_rom_drawers;
private:
required_device m_io_sys;
@@ -673,6 +679,11 @@ void hp9825_state::hp9825_base(machine_config &config)
tmp.dmar().set([this , slot](int state) { set_dmar_slot(slot , state); });
}
+ // Optional ROM slots
+ for (auto& finder : m_rom_drawers) {
+ HP9825_OPTROM_SLOT(config , finder);
+ }
+
config.set_default_layout(layout_hp9825);
}
@@ -841,6 +852,9 @@ public:
void hp9825b(machine_config &config);
+protected:
+ virtual void device_reset() override;
+
private:
void cpu_mem_map(address_map &map);
};
@@ -849,12 +863,30 @@ void hp9825b_state::hp9825b(machine_config &config)
{
hp9825_base(config);
m_cpu->set_addrmap(AS_PROGRAM , &hp9825b_state::cpu_mem_map);
+
+ for (auto& finder : m_rom_drawers) {
+ finder->set_rom_limit(0x5000);
+ }
+
+ SOFTWARE_LIST(config, "optrom_list").set_original("hp9825b_rom");
+}
+
+void hp9825b_state::device_reset()
+{
+ hp9825_state::device_reset();
+
+ auto space = &m_cpu->space(AS_PROGRAM);
+
+ for (auto& finder : m_rom_drawers) {
+ finder->install_rw_handlers(space , nullptr);
+ }
}
void hp9825b_state::cpu_mem_map(address_map &map)
{
map.unmap_value_low();
- map(0x0000 , 0x3bff).rom();
+ map(0x0000 , 0x2fff).rom();
+ map(0x3400 , 0x3bff).rom();
map(0x4000 , 0x4fff).rom();
map(0x5000 , 0x7fff).ram();
}
@@ -862,13 +894,16 @@ void hp9825b_state::cpu_mem_map(address_map &map)
// +---------------+
// | hp9825t_state |
// +---------------+
-class hp9825t_state : public hp9825_state
+class hp9825t_state : public hp9825_state,
+ public device_memory_interface
{
public:
hp9825t_state(const machine_config &mconfig, device_type type, const char *tag)
: hp9825_state(mconfig , type , tag)
- , m_rom_region(*this , "rom")
+ , device_memory_interface(mconfig , *this)
, m_skoalrom(*this , "skoalrom")
+ , m_ram_space_config("ram" , ENDIANNESS_BIG , 16 , 15 , -1)
+ , m_rom_space_config("rom" , ENDIANNESS_BIG , 16 , 15 , -1)
{
}
@@ -878,10 +913,15 @@ protected:
virtual void machine_start() override;
virtual void device_reset() override;
+ // device_memory_interface overrides
+ virtual space_config_vector memory_space_config() const override;
+
private:
- required_memory_region m_rom_region;
required_memory_region m_skoalrom;
- std::unique_ptr m_ram;
+ address_space_config m_ram_space_config;
+ address_space *m_ram_space;
+ address_space_config m_rom_space_config;
+ address_space *m_rom_space;
uint8_t m_cycle_type;
@@ -894,6 +934,8 @@ private:
uint16_t m_fetch_addr;
void cpu_mem_map(address_map &map);
+ void ram_mem_map(address_map &map);
+ void rom_mem_map(address_map &map);
DECLARE_READ16_MEMBER(cpu_mem_r);
DECLARE_WRITE16_MEMBER(cpu_mem_w);
void stm(uint8_t cycle_type);
@@ -909,32 +951,65 @@ void hp9825t_state::hp9825t(machine_config &config)
m_cpu->set_addrmap(AS_PROGRAM , &hp9825t_state::cpu_mem_map);
m_cpu->stm_cb().set(FUNC(hp9825t_state::stm));
m_cpu->opcode_cb().set(FUNC(hp9825t_state::opcode_fetch));
+ set_addrmap(0 , &hp9825t_state::ram_mem_map);
+ set_addrmap(1 , &hp9825t_state::rom_mem_map);
+
+ for (auto& finder : m_rom_drawers) {
+ finder->set_rom_limit(0x6000);
+ }
+
+ SOFTWARE_LIST(config, "optrom_list").set_original("hp9825b_rom");
}
void hp9825t_state::machine_start()
{
hp9825_state::machine_start();
- // 32kw of RAM (the 1st kw is not accessible in normal operation)
- m_ram = std::make_unique(32768);
- save_pointer(NAME(m_ram) , 32768);
+ m_ram_space = &space(0);
+ m_rom_space = &space(1);
}
void hp9825t_state::device_reset()
{
hp9825_state::device_reset();
+ for (auto& finder : m_rom_drawers) {
+ finder->install_rw_handlers(m_rom_space , m_ram_space);
+ }
+
// This has to be done before CPU reset or first instruction won't be fetched correctly
m_cycle_type = 0;
m_special_opt = 0xf;
}
+device_memory_interface::space_config_vector hp9825t_state::memory_space_config() const
+{
+ return space_config_vector {
+ std::make_pair(0 , &m_ram_space_config),
+ std::make_pair(1 , &m_rom_space_config)
+ };
+}
+
void hp9825t_state::cpu_mem_map(address_map &map)
{
map.unmap_value_low();
map(0x0000 , 0x7fff).rw(FUNC(hp9825t_state::cpu_mem_r) , FUNC(hp9825t_state::cpu_mem_w));
}
+void hp9825t_state::ram_mem_map(address_map &map)
+{
+ // 32 kw of RAM covering the whole address space (1st kw not accessible)
+ map(0x0000 , 0x7fff).ram();
+}
+
+void hp9825t_state::rom_mem_map(address_map &map)
+{
+ map.unmap_value_low();
+ map(0x0000 , 0x2fff).rom().region(":rom" , 0);
+ map(0x3400 , 0x3bff).rom().region(":rom" , 0x6800);
+ map(0x4000 , 0x53ff).rom().region(":rom" , 0x8000);
+}
+
READ16_MEMBER(hp9825t_state::cpu_mem_r)
{
bool from_rom;
@@ -955,7 +1030,7 @@ READ16_MEMBER(hp9825t_state::cpu_mem_r)
from_rom = is_rom(offset , hp_hybrid_cpu_device::CYCLE_IFETCH_MASK);
}
- return from_rom ? m_rom_region->as_u16(offset) : m_ram[ offset ];
+ return from_rom ? m_rom_space->read_word(offset , mem_mask) : m_ram_space->read_word(offset , mem_mask);
}
WRITE16_MEMBER(hp9825t_state::cpu_mem_w)
@@ -967,7 +1042,7 @@ WRITE16_MEMBER(hp9825t_state::cpu_mem_w)
m_cycle_type = 0;
}
// All write cycles go to RAM
- m_ram[ offset ] = (m_ram[ offset ] & ~mem_mask) | (data & mem_mask);
+ m_ram_space->write_word(offset , data , mem_mask);
}
void hp9825t_state::stm(uint8_t cycle_type)
@@ -1080,7 +1155,6 @@ ROM_START(hp9825b)
ROM_LOAD("sysrom1.bin" , 0x0000 , 0x2000 , CRC(fe429268) SHA1(f2fe7c5abca92bd13f81b4385fc4fce0cafb0da0))
ROM_LOAD("sysrom2.bin" , 0x2000 , 0x2000 , CRC(96093b5d) SHA1(c6ec4cafd019887df0fa849b3c7070bb74faee54))
ROM_LOAD("sysrom3.bin" , 0x4000 , 0x2000 , CRC(f9470f67) SHA1(b80cb4a366d93bd7acc3508ce987bb11c5986b2a))
- ROM_LOAD("98217.bin" , 0x6000 , 0x0800 , BAD_DUMP CRC(ea1fcf63) SHA1(e535c82897210a1c67c1ca16f44f936d4c470463))
ROM_LOAD("genio_t.bin" , 0x6800 , 0x0800 , CRC(ade1d1ed) SHA1(9af74a65b29ef1885f74164238ecf8d16ac995d6))
ROM_LOAD("plot72.bin" , 0x7000 , 0x0800 , CRC(0a9cb8db) SHA1(d0d126fca108f2715e1e408cb31b09ba69385ac4))
ROM_LOAD("advpgm_t.bin", 0x8000 , 0x0800 , CRC(965b5e5a) SHA1(ff44dd15f8fa4ca03dfd970ed8b200e8a071ec13))
@@ -1089,11 +1163,10 @@ ROM_START(hp9825b)
ROM_END
ROM_START(hp9825t)
- ROM_REGION(0xc000 , "rom" , ROMREGION_16BIT | ROMREGION_BE | ROMREGION_ERASE | ROMREGION_ERASE00)
+ ROM_REGION(0xa800 , ":rom" , ROMREGION_16BIT | ROMREGION_BE | ROMREGION_ERASE | ROMREGION_ERASE00)
ROM_LOAD("sysrom1.bin" , 0x0000 , 0x2000 , CRC(fe429268) SHA1(f2fe7c5abca92bd13f81b4385fc4fce0cafb0da0))
ROM_LOAD("sysrom2.bin" , 0x2000 , 0x2000 , CRC(96093b5d) SHA1(c6ec4cafd019887df0fa849b3c7070bb74faee54))
ROM_LOAD("sysrom3.bin" , 0x4000 , 0x2000 , CRC(f9470f67) SHA1(b80cb4a366d93bd7acc3508ce987bb11c5986b2a))
- ROM_LOAD("98217.bin" , 0x6000 , 0x0800 , BAD_DUMP CRC(ea1fcf63) SHA1(e535c82897210a1c67c1ca16f44f936d4c470463))
ROM_LOAD("genio_t.bin" , 0x6800 , 0x0800 , CRC(ade1d1ed) SHA1(9af74a65b29ef1885f74164238ecf8d16ac995d6))
ROM_LOAD("plot72.bin" , 0x7000 , 0x0800 , CRC(0a9cb8db) SHA1(d0d126fca108f2715e1e408cb31b09ba69385ac4))
ROM_LOAD("advpgm_t.bin", 0x8000 , 0x0800 , CRC(965b5e5a) SHA1(ff44dd15f8fa4ca03dfd970ed8b200e8a071ec13))