diff options
Diffstat (limited to 'src/mame/hp/hp9845_optrom.cpp')
-rw-r--r-- | src/mame/hp/hp9845_optrom.cpp | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/src/mame/hp/hp9845_optrom.cpp b/src/mame/hp/hp9845_optrom.cpp new file mode 100644 index 00000000000..74dc12ebf51 --- /dev/null +++ b/src/mame/hp/hp9845_optrom.cpp @@ -0,0 +1,98 @@ +// 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_rom_image_interface(mconfig, *this), + m_base_addr(0), + m_end_addr(0) +{ +} + +hp9845_optrom_device::~hp9845_optrom_device() +{ +} + +void hp9845_optrom_device::device_start() +{ +} + +std::pair<std::error_condition, std::string> hp9845_optrom_device::call_load() +{ + logerror("hp9845_optrom: call_load\n"); + if (!loaded_through_softlist()) { + return std::make_pair(image_error::UNSUPPORTED, "Option ROMs must be loaded from software list"); + } + + const char *base_feature = get_feature("base"); + if (base_feature == nullptr) { + return std::make_pair(image_error::BADSOFTWARE, "Software item is missing 'base' feature"); + } + + offs_t base_addr; + if (base_feature[ 0 ] != '0' || base_feature[ 1 ] != 'x' || sscanf(&base_feature[ 2 ] , "%x" , &base_addr) != 1) { + return std::make_pair(image_error::BADSOFTWARE, "Can't parse software item 'base' feature"); + } + + // 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) { + return std::make_pair( + image_error::BADSOFTWARE, + util::string_format("Illegal base address (%x)", base_addr)); + } + + auto length = get_software_region_length("rom") / 2; + + if (length < 0x1000 || length > 0x8000 || (length & 0xfff) != 0 || ((base_addr & 0x7000) + length) > 0x8000) { + return std::make_pair( + image_error::INVALIDLENGTH, + util::string_format("Illegal 'rom' data area size (%u)", length)); + } + + 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_enumerator<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 std::make_pair(std::error_condition(), std::string()); +} + +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_enumerator<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; + } +} |