From 430bd2d50852737282a51b88fa26acbdd0f2c44d Mon Sep 17 00:00:00 2001 From: fulivi Date: Wed, 23 Oct 2019 16:23:12 +0200 Subject: [PATCH] Hp9825: support for external ROM cartridges added (#5761) * hp9825: optional ROM cartridges added (9825b only, ATM) * hp9825: optional ROMs added to 9825t, added support for banked ROMs @5c00, separated RAM & ROM spaces in 9825t * hp9885: added missing post-amble when writing sectors on disk * hp9825: added acknowledgments to comments (nw) * hp9825: changes requested by V.Crabb (nw) --- hash/hp9825b_rom.xml | 55 ++++++ scripts/src/bus.lua | 12 ++ scripts/target/mame/mess.lua | 1 + .../bus/hp9825_optroms/hp9825_optrom.cpp | 179 ++++++++++++++++++ .../bus/hp9825_optroms/hp9825_optrom.h | 79 ++++++++ src/devices/bus/hp9845_io/98034.cpp | 69 +++++-- src/devices/bus/hp9845_io/98034.h | 3 +- src/devices/bus/hp9845_io/hp9885.cpp | 12 +- src/mame/drivers/hp9825.cpp | 101 ++++++++-- 9 files changed, 472 insertions(+), 39 deletions(-) create mode 100644 hash/hp9825b_rom.xml create mode 100644 src/devices/bus/hp9825_optroms/hp9825_optrom.cpp create mode 100644 src/devices/bus/hp9825_optroms/hp9825_optrom.h 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))