diff --git a/hash/hp_ipc_rom.xml b/hash/hp_ipc_rom.xml new file mode 100644 index 00000000000..b2fe442e907 --- /dev/null +++ b/hash/hp_ipc_rom.xml @@ -0,0 +1,22 @@ + + + + + + + Software Engineering ROM + 1986 + Hewlett-Packard + + + + + + + + + + + diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua index a3ce421a8c3..8dd3c92a5ff 100644 --- a/scripts/target/mame/mess.lua +++ b/scripts/target/mame/mess.lua @@ -2603,6 +2603,8 @@ files { MAME_DIR .. "src/mame/machine/hp9845_printer.h", MAME_DIR .. "src/mame/machine/hp98x5_io_sys.cpp", MAME_DIR .. "src/mame/machine/hp98x5_io_sys.h", + MAME_DIR .. "src/mame/machine/hp_ipc_optrom.cpp", + MAME_DIR .. "src/mame/machine/hp_ipc_optrom.h", MAME_DIR .. "src/mame/video/hp48.cpp", MAME_DIR .. "src/mame/drivers/hp49gp.cpp", MAME_DIR .. "src/mame/drivers/hp9845.cpp", diff --git a/src/mame/drivers/hp_ipc.cpp b/src/mame/drivers/hp_ipc.cpp index c963b061497..74e05e364de 100644 --- a/src/mame/drivers/hp_ipc.cpp +++ b/src/mame/drivers/hp_ipc.cpp @@ -374,6 +374,7 @@ Software to look for #include "sound/dac.h" #include "machine/input_merger.h" #include "bus/hp_ipc_io/hp_ipc_io.h" +#include "machine/hp_ipc_optrom.h" #include "emupal.h" #include "screen.h" @@ -398,6 +399,7 @@ public: , m_irq6_merger(*this , "merge_irq6") , m_io_slot_a(*this , "slot_a") , m_io_slot_b(*this , "slot_b") + , m_rom_slots(*this , "rom%u" , 0) { } void hp_ipc_base(machine_config &config); @@ -452,6 +454,7 @@ private: required_device m_irq6_merger; required_device m_io_slot_a; required_device m_io_slot_b; + required_device_array m_rom_slots; uint32_t m_mmu[4], m_lowest_ram_addr; uint16_t *m_internal_ram; @@ -744,6 +747,15 @@ void hp_ipc_state::machine_reset() m_spkr->cs_w(1); m_spkr->sk_w(0); m_spkr->di_w(0); + + // Load optional ROMs (if any) + // But first unload anything in opt ROM range + m_bankdev->space().unmap_read(0x100000 , 0x4fffff); + m_bankdev->space().unmap_read(0x100000 + 0x1800000, 0x4fffff + 0x1800000); + + for (auto& slot : m_rom_slots) { + slot->install_read_handler(m_bankdev->space()); + } } @@ -781,6 +793,7 @@ void hp_ipc_state::hp_ipc_base(machine_config &config) FLOPPY_CONNECTOR(config, "fdc:0", hp_ipc_floppies, "35dd", hp_ipc_state::floppy_formats); SOFTWARE_LIST(config, "flop_list").set_original("hp_ipc"); + SOFTWARE_LIST(config, "rom_list").set_original("hp_ipc_rom"); mm58167_device &rtc(MM58167(config, "rtc", 32.768_kHz_XTAL)); rtc.irq().set(FUNC(hp_ipc_state::irq_1)); @@ -841,6 +854,11 @@ void hp_ipc_state::hp_ipc_base(machine_config &config) m_io_slot_b->irq5_cb().set(m_irq5_merger , FUNC(input_merger_any_high_device::in_w<2>)); m_io_slot_b->irq6_cb().set(m_irq6_merger , FUNC(input_merger_any_high_device::in_w<2>)); + // Optional ROMs + for (auto& finder : m_rom_slots) { + HP_IPC_OPTROM(config, finder); + } + RAM(config, RAM_TAG).set_default_size("512K").set_extra_options("768K,1M,1576K,2M,3M,4M,5M,6M,7M,7680K"); } diff --git a/src/mame/machine/hp_ipc_optrom.cpp b/src/mame/machine/hp_ipc_optrom.cpp new file mode 100644 index 00000000000..75b66ec7a67 --- /dev/null +++ b/src/mame/machine/hp_ipc_optrom.cpp @@ -0,0 +1,84 @@ +// license:BSD-3-Clause +// copyright-holders: F. Ulivi +/********************************************************************* + + hp_ipc_optrom.cpp + + Optional ROMs for HP Integral PC + +*********************************************************************/ + +#include "emu.h" +#include "hp_ipc_optrom.h" +#include "softlist.h" + +// Debugging +#define VERBOSE 1 +#include "logmacro.h" + +DEFINE_DEVICE_TYPE(HP_IPC_OPTROM, hp_ipc_optrom_device, "hp_ipc_optrom", "HP IPC optional ROM") + +// +--------------------+ +// |hp_ipc_optrom_device| +// +--------------------+ +hp_ipc_optrom_device::hp_ipc_optrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, HP_IPC_OPTROM, tag, owner, clock) + , device_image_interface(mconfig, *this) + , m_base(0) +{ +} + +hp_ipc_optrom_device::~hp_ipc_optrom_device() +{ +} + +void hp_ipc_optrom_device::install_read_handler(address_space& space) +{ + if (loaded_through_softlist()) { + auto region = get_software_region("rom"); + auto len = get_software_region_length("rom"); + + // Supervisor mode + space.install_rom(m_base , m_base + len - 1 , region); + // User mode + space.install_rom(m_base + 0x1800000 , m_base + 0x1800000 + len - 1 , region); + } +} + +void hp_ipc_optrom_device::device_start() +{ +} + +image_init_result hp_ipc_optrom_device::call_load() +{ + LOG("hp_ipc_optrom: call_load\n"); + if (!loaded_through_softlist()) { + LOG("hp_ipc_optrom: must be loaded from sw list\n"); + return image_init_result::FAIL; + } + + const char *base_feature = get_feature("base"); + if (base_feature == nullptr) { + LOG("hp_ipc_optrom: no 'base' feature\n"); + return image_init_result::FAIL; + } + + if (base_feature[ 0 ] != '0' || base_feature[ 1 ] != 'x' || sscanf(&base_feature[ 2 ] , "%x" , &m_base) != 1) { + LOG("hp_ipc_optrom: can't parse 'base' feature\n"); + return image_init_result::FAIL; + } + + // Valid base values: multiple of 1M, [0x100000..0x4fffff] + if ((m_base & 0xfffffU) != 0 || m_base < 0x100000U || m_base > 0x400000U) { + LOG("hp_ipc_optrom: illegal base (%x)\n" , m_base); + return image_init_result::FAIL; + } + + LOG("hp_ipc_optrom: loaded base=0x%06x\n" , m_base); + return image_init_result::PASS; +} + +void hp_ipc_optrom_device::call_unload() +{ + LOG("hp_ipc_optrom: call_unload\n"); +} diff --git a/src/mame/machine/hp_ipc_optrom.h b/src/mame/machine/hp_ipc_optrom.h new file mode 100644 index 00000000000..93872a0a5b8 --- /dev/null +++ b/src/mame/machine/hp_ipc_optrom.h @@ -0,0 +1,58 @@ +// license:BSD-3-Clause +// copyright-holders: F. Ulivi +/********************************************************************* + + hp_ipc_optrom.h + + Optional ROMs for HP Integral PC + +*********************************************************************/ + +#ifndef MAME_MACHINE_HP_IPC_OPTROM_H +#define MAME_MACHINE_HP_IPC_OPTROM_H + +#pragma once + +#include "softlist_dev.h" + +class hp_ipc_optrom_device : public device_t, + public device_image_interface +{ +public: + // construction/destruction + hp_ipc_optrom_device(machine_config const &mconfig, char const *tag, device_t *owner) + : hp_ipc_optrom_device(mconfig, tag, owner, (uint32_t)0) + { + } + + hp_ipc_optrom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + virtual ~hp_ipc_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 noexcept override { return IO_ROM; } + virtual bool is_readable() const noexcept override { return true; } + virtual bool is_writeable() const noexcept override { return false; } + virtual bool is_creatable() const noexcept override { return false; } + virtual bool must_be_loaded() const noexcept override { return false; } + virtual bool is_reset_on_load() const noexcept override { return true; } + virtual const char *image_interface() const noexcept override { return "hp_ipc_rom"; } + virtual const char *file_extensions() const noexcept override { return "bin"; } + +private: + offs_t m_base; +}; + +// device type definition +DECLARE_DEVICE_TYPE(HP_IPC_OPTROM, hp_ipc_optrom_device) + +#endif // MAME_MACHINE_HP_IPC_OPTROM_H