summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine
diff options
context:
space:
mode:
author fulivi <fulivi@users.noreply.github.com>2019-11-08 03:42:09 +0100
committer Vas Crabb <cuavas@users.noreply.github.com>2019-11-08 13:42:09 +1100
commitc2a6ebd366e75e6d0644c93e4a1a60464b85b9db (patch)
tree762b03dc5ca851b713db619624fb684e1e046ff6 /src/mame/machine
parent143385e2f2b44ae4904f55bd30803c1f739bb503 (diff)
HP optional ROMs: address issue #5839 (#5873)
* hp80: refactored optional ROM device as requested in issue #5839 * hp9825: refactored optional ROM device as requested in issue #5839 * hp9845: refactored optional ROM device as requested in issue #5839
Diffstat (limited to 'src/mame/machine')
-rw-r--r--src/mame/machine/hp80_optrom.cpp89
-rw-r--r--src/mame/machine/hp80_optrom.h60
-rw-r--r--src/mame/machine/hp9825_optrom.cpp151
-rw-r--r--src/mame/machine/hp9825_optrom.h59
-rw-r--r--src/mame/machine/hp9845_optrom.cpp99
-rw-r--r--src/mame/machine/hp9845_optrom.h51
6 files changed, 509 insertions, 0 deletions
diff --git a/src/mame/machine/hp80_optrom.cpp b/src/mame/machine/hp80_optrom.cpp
new file mode 100644
index 00000000000..c61646515ba
--- /dev/null
+++ b/src/mame/machine/hp80_optrom.cpp
@@ -0,0 +1,89 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ hp80_optrom.cpp
+
+ Optional ROMs for HP80 systems
+
+*********************************************************************/
+
+#include "emu.h"
+#include "hp80_optrom.h"
+#include "softlist.h"
+
+// Debugging
+#define VERBOSE 1
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(HP80_OPTROM, hp80_optrom_device, "hp80_optrom", "HP80 optional ROM")
+
+// +------------------+
+// |hp80_optrom_device|
+// +------------------+
+hp80_optrom_device::hp80_optrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, HP80_OPTROM, tag, owner, clock),
+ device_image_interface(mconfig, *this),
+ m_select_code(0)
+{
+}
+
+hp80_optrom_device::~hp80_optrom_device()
+{
+}
+
+void hp80_optrom_device::install_read_handler(address_space& space)
+{
+ if (loaded_through_softlist()) {
+ offs_t start = (offs_t)m_select_code * HP80_OPTROM_SIZE;
+ space.install_rom(start , start + HP80_OPTROM_SIZE - 1 , get_software_region("rom"));
+ }
+}
+
+void hp80_optrom_device::device_start()
+{
+}
+
+image_init_result hp80_optrom_device::call_load()
+{
+ LOG("hp80_optrom: call_load\n");
+ if (!loaded_through_softlist()) {
+ LOG("hp80_optrom: must be loaded from sw list\n");
+ return image_init_result::FAIL;
+ }
+
+ const char *sc_feature = get_feature("sc");
+ if (sc_feature == nullptr) {
+ LOG("hp80_optrom: no 'sc' feature\n");
+ return image_init_result::FAIL;
+ }
+
+ unsigned sc;
+ if (sc_feature[ 0 ] != '0' || sc_feature[ 1 ] != 'x' || sscanf(&sc_feature[ 2 ] , "%x" , &sc) != 1) {
+ LOG("hp80_optrom: can't parse 'sc' feature\n");
+ return image_init_result::FAIL;
+ }
+
+ // Valid SC values: 0x01..0xff
+ if (sc < 1 || sc > 0xff) {
+ LOG("hp80_optrom: illegal select code (%x)\n" , sc);
+ return image_init_result::FAIL;
+ }
+
+ auto length = get_software_region_length("rom");
+
+ if (length != HP80_OPTROM_SIZE) {
+ LOG("hp80_optrom: illegal region length (%x)\n" , length);
+ return image_init_result::FAIL;
+ }
+
+ LOG("hp80_optrom: loaded SC=0x%02x\n" , sc);
+ m_select_code = sc;
+ return image_init_result::PASS;
+}
+
+void hp80_optrom_device::call_unload()
+{
+ LOG("hp80_optrom: call_unload\n");
+ machine().schedule_soft_reset();
+}
diff --git a/src/mame/machine/hp80_optrom.h b/src/mame/machine/hp80_optrom.h
new file mode 100644
index 00000000000..f0e272f60c8
--- /dev/null
+++ b/src/mame/machine/hp80_optrom.h
@@ -0,0 +1,60 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ hp80_optrom.h
+
+ Optional ROMs for HP80 systems
+
+*********************************************************************/
+
+#ifndef MAME_MACHINE_HP80_OPTROM_H
+#define MAME_MACHINE_HP80_OPTROM_H
+
+#pragma once
+
+#include "softlist_dev.h"
+
+// Size of optional ROMs (8k)
+static constexpr offs_t HP80_OPTROM_SIZE = 0x2000;
+
+class hp80_optrom_device : public device_t,
+ public device_image_interface
+{
+public:
+ // construction/destruction
+ hp80_optrom_device(machine_config const &mconfig, char const *tag, device_t *owner)
+ : hp80_optrom_device(mconfig, tag, owner, (uint32_t)0)
+ {
+ }
+
+ hp80_optrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~hp80_optrom_device();
+
+ void install_read_handler(address_space& space);
+
+protected:
+ // device-level overrides
+ 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 "hp80_rom"; }
+ virtual const char *file_extensions() const override { return "bin"; }
+
+ uint8_t m_select_code;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(HP80_OPTROM, hp80_optrom_device)
+
+#endif // MAME_MACHINE_HP80_OPTROM_H
diff --git a/src/mame/machine/hp9825_optrom.cpp b/src/mame/machine/hp9825_optrom.cpp
new file mode 100644
index 00000000000..b49ed6f4846
--- /dev/null
+++ b/src/mame/machine/hp9825_optrom.cpp
@@ -0,0 +1,151 @@
+// 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, hp9825_optrom_device, "hp9825_optrom", "HP9825 optional ROM")
+
+struct optrom_region {
+ offs_t m_start;
+ offs_t m_size;
+ const char *m_tag;
+};
+
+constexpr std::array<struct optrom_region , 8> 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_device|
+// +--------------------+
+hp9825_optrom_device::hp9825_optrom_device(machine_config const &mconfig, char const *tag, device_t *owner)
+ : hp9825_optrom_device(mconfig, tag, owner, (uint32_t)0)
+{
+}
+
+hp9825_optrom_device::hp9825_optrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, HP9825_OPTROM, tag, owner, clock)
+ , device_image_interface(mconfig, *this)
+ , m_rom_limit(0xffffU)
+ , m_loaded_regions(0)
+ , m_space_r(nullptr)
+ , m_bank(*this , "rombank")
+{
+}
+
+hp9825_optrom_device::~hp9825_optrom_device()
+{
+}
+
+void hp9825_optrom_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_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_device::device_start()
+{
+}
+
+image_init_result hp9825_optrom_device::call_load()
+{
+ LOG("hp9825_optrom: call_load\n");
+ if (!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_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();
+}
diff --git a/src/mame/machine/hp9825_optrom.h b/src/mame/machine/hp9825_optrom.h
new file mode 100644
index 00000000000..390c6a43eea
--- /dev/null
+++ b/src/mame/machine/hp9825_optrom.h
@@ -0,0 +1,59 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ hp9825_optrom.h
+
+ Optional ROMs for HP9825 systems
+
+*********************************************************************/
+#ifndef MAME_MACHINE_HP9825_OPTROM_H
+#define MAME_MACHINE_HP9825_OPTROM_H
+
+#pragma once
+
+#include "machine/bankdev.h"
+#include "softlist_dev.h"
+
+class hp9825_optrom_device : public device_t,
+ public device_image_interface
+{
+public:
+ // construction/destruction
+ hp9825_optrom_device(machine_config const &mconfig, char const *tag, device_t *owner);
+ hp9825_optrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~hp9825_optrom_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"; }
+
+ offs_t m_rom_limit;
+ unsigned m_loaded_regions;
+ address_space *m_space_r;
+ required_device<address_map_bank_device> m_bank;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(HP9825_OPTROM, hp9825_optrom_device)
+
+#endif /* MAME_MACHINE_HP9825_OPTROM_H */
diff --git a/src/mame/machine/hp9845_optrom.cpp b/src/mame/machine/hp9845_optrom.cpp
new file mode 100644
index 00000000000..26f5a41cf3b
--- /dev/null
+++ b/src/mame/machine/hp9845_optrom.cpp
@@ -0,0 +1,99 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ hp9845_optrom.cpp
+
+ Optional ROMs for HP9845 systems
+
+*********************************************************************/
+
+#include "emu.h"
+#include "hp9845_optrom.h"
+#include "softlist.h"
+#include "cpu/hphybrid/hphybrid.h"
+
+DEFINE_DEVICE_TYPE(HP9845_OPTROM, hp9845_optrom_device, "hp9845_optrom", "HP9845 optional ROM")
+
+// +--------------------+
+// |hp9845_optrom_device|
+// +--------------------+
+hp9845_optrom_device::hp9845_optrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, HP9845_OPTROM, tag, owner, clock),
+ device_image_interface(mconfig, *this),
+ m_base_addr(0),
+ m_end_addr(0)
+{
+}
+
+hp9845_optrom_device::~hp9845_optrom_device()
+{
+}
+
+void hp9845_optrom_device::device_start()
+{
+}
+
+image_init_result hp9845_optrom_device::call_load()
+{
+ logerror("hp9845_optrom: call_load\n");
+ if (!loaded_through_softlist()) {
+ logerror("hp9845_optrom: must be loaded from sw list\n");
+ return image_init_result::FAIL;
+ }
+
+ const char *base_feature = get_feature("base");
+ if (base_feature == nullptr) {
+ logerror("hp9845_optrom: no 'base' feature\n");
+ return image_init_result::FAIL;
+ }
+
+ offs_t base_addr;
+ if (base_feature[ 0 ] != '0' || base_feature[ 1 ] != 'x' || sscanf(&base_feature[ 2 ] , "%x" , &base_addr) != 1) {
+ logerror("hp9845_optrom: can't parse 'base' feature\n");
+ return image_init_result::FAIL;
+ }
+
+ // Valid BSC values for ROMs on LPU drawer: 0x07 0x0b .... 0x3b
+ // Valid BSC values for ROMs on PPU drawer: 0x09 0x0d .... 0x3d
+ // (BSC is field in bits 16..21 of base address)
+ // Bit 15 of base address must be 0
+ // Base address must be multiple of 0x1000
+ if ((base_addr & ~0x3f7000UL) != 0 || ((base_addr & 0x30000) != 0x10000 && (base_addr & 0x30000) != 0x30000) || base_addr < 0x70000) {
+ logerror("hp9845_optrom: illegal base address (%x)\n" , base_addr);
+ return image_init_result::FAIL;
+ }
+
+ auto length = get_software_region_length("rom") / 2;
+
+ if (length < 0x1000 || length > 0x8000 || (length & 0xfff) != 0 || ((base_addr & 0x7000) + length) > 0x8000) {
+ logerror("hp9845_optrom: illegal region length (%x)\n" , length);
+ return image_init_result::FAIL;
+ }
+
+ offs_t end_addr = base_addr + length - 1;
+ logerror("hp9845_optrom: base_addr = %06x end_addr = %06x\n" , base_addr , end_addr);
+
+ // Install ROM in address space of every CPU
+ for (hp_hybrid_cpu_device& cpu : device_interface_iterator<hp_hybrid_cpu_device>(machine().root_device())) {
+ logerror("hp9845_optrom: install in %s AS\n" , cpu.tag());
+ cpu.space(AS_PROGRAM).install_rom(base_addr , end_addr , get_software_region("rom"));
+ }
+
+ m_base_addr = base_addr;
+ m_end_addr = end_addr;
+
+ return image_init_result::PASS;
+}
+
+void hp9845_optrom_device::call_unload()
+{
+ logerror("hp9845_optrom: call_unload\n");
+ if (m_base_addr != 0 && m_end_addr != 0) {
+ for (hp_hybrid_cpu_device& cpu : device_interface_iterator<hp_hybrid_cpu_device>(machine().root_device())) {
+ cpu.space(AS_PROGRAM).unmap_read(m_base_addr , m_end_addr);
+ }
+ m_base_addr = 0;
+ m_end_addr = 0;
+ }
+}
diff --git a/src/mame/machine/hp9845_optrom.h b/src/mame/machine/hp9845_optrom.h
new file mode 100644
index 00000000000..289c3b2c7bc
--- /dev/null
+++ b/src/mame/machine/hp9845_optrom.h
@@ -0,0 +1,51 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ hp9845_optrom.h
+
+ Optional ROMs for HP9845 systems
+
+*********************************************************************/
+
+#ifndef MAME_MACHINE_HP9845_OPTROM_H
+#define MAME_MACHINE_HP9845_OPTROM_H
+
+#pragma once
+
+#include "softlist_dev.h"
+
+class hp9845_optrom_device : public device_t,
+ public device_image_interface
+{
+public:
+ // construction/destruction
+ hp9845_optrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~hp9845_optrom_device();
+
+protected:
+ // device-level overrides
+ 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 "hp9845b_rom"; }
+ virtual const char *file_extensions() const override { return "bin"; }
+
+ offs_t m_base_addr;
+ offs_t m_end_addr;
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(HP9845_OPTROM, hp9845_optrom_device)
+
+#endif // MAME_MACHINE_HP9845_OPTROM_H