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)
This commit is contained in:
fulivi 2019-10-23 16:23:12 +02:00 committed by R. Belmont
parent 23a05f7e85
commit 430bd2d508
9 changed files with 472 additions and 39 deletions

55
hash/hp9825b_rom.xml Normal file
View File

@ -0,0 +1,55 @@
<?xml version="1.0"?>
<!DOCTYPE softwarelist SYSTEM "softwarelist.dtd">
<!-- HP9825B/T option ROMs -->
<!-- Compiled by F.Ulivi with data from http://www.hpmuseum.net/ (mostly) -->
<softwarelist name="hp9825b_rom" description="HP 9825B Option ROMs">
<software name="mass">
<description>9885 ROM for 9825</description>
<year>1976</year>
<publisher>Hewlett-Packard</publisher>
<info name="serial" value="98217A" />
<part name="rom" interface="hp9825_rom">
<dataarea name="rom3000" size="0x800" width="16" endianness="big">
<rom name="98217a.bin" size="0x800" crc="ee41c924" sha1="eac268523c09291a9939bc2dac201e4285185b51"/>
</dataarea>
</part>
</software>
<software name="mass2">
<description>9885/9895 ROM for 9825</description>
<year>1980</year>
<publisher>Hewlett-Packard</publisher>
<info name="serial" value="98228A" />
<part name="rom" interface="hp9825_rom">
<dataarea name="rom5c00" size="0x4000" width="16" endianness="big">
<rom name="98228a.bin" size="0x4000" crc="31ce695e" sha1="b61273356c421102ff2bbd6aa7277200ee778097"/>
</dataarea>
</part>
</software>
<software name="sssmass">
<description>SSS mass storage ROM</description>
<year>1984</year>
<publisher>Structured Software Systems</publisher>
<part name="rom" interface="hp9825_rom">
<dataarea name="rom5c00" size="0x4000" width="16" endianness="big">
<rom name="sssmass.bin" size="0x4000" crc="95d36297" sha1="5e1777c894f6507a461c4a12f12ae5ac2c7a4385"/>
</dataarea>
</part>
</software>
<software name="matrix">
<description>Matrix ROM for 9825</description>
<year>1976</year>
<publisher>Hewlett-Packard</publisher>
<info name="serial" value="98211A" />
<part name="rom" interface="hp9825_rom">
<dataarea name="rom3c00" size="0x800" width="16" endianness="big">
<rom name="98211a.bin" size="0x800" crc="2cec553f" sha1="95c8d8becae6948accb342d23bc7072f0adb2c67"/>
</dataarea>
</part>
</software>
</softwarelist>

View File

@ -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

View File

@ -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

View File

@ -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<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_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<hp9825_optrom_cart_device *>(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");
}

View File

@ -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<address_map_bank_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 */

View File

@ -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));

View File

@ -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();

View File

@ -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

View File

@ -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<hp_09825_67907_cpu_device> m_cpu;
required_device_array<hp9825_optrom_slot_device , 4> m_rom_drawers;
private:
required_device<hp98x5_io_sys_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<uint16_t[]> 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<uint16_t[]>(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))