diff options
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 |
commit | c2a6ebd366e75e6d0644c93e4a1a60464b85b9db (patch) | |
tree | 762b03dc5ca851b713db619624fb684e1e046ff6 /src/mame/machine | |
parent | 143385e2f2b44ae4904f55bd30803c1f739bb503 (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.cpp | 89 | ||||
-rw-r--r-- | src/mame/machine/hp80_optrom.h | 60 | ||||
-rw-r--r-- | src/mame/machine/hp9825_optrom.cpp | 151 | ||||
-rw-r--r-- | src/mame/machine/hp9825_optrom.h | 59 | ||||
-rw-r--r-- | src/mame/machine/hp9845_optrom.cpp | 99 | ||||
-rw-r--r-- | src/mame/machine/hp9845_optrom.h | 51 |
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 |