mirror of
https://github.com/holub/mame
synced 2025-04-19 23:12:11 +03:00
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:
parent
23a05f7e85
commit
430bd2d508
55
hash/hp9825b_rom.xml
Normal file
55
hash/hp9825b_rom.xml
Normal 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>
|
@ -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
|
||||
|
@ -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
|
||||
|
179
src/devices/bus/hp9825_optroms/hp9825_optrom.cpp
Normal file
179
src/devices/bus/hp9825_optroms/hp9825_optrom.cpp
Normal 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");
|
||||
}
|
||||
|
79
src/devices/bus/hp9825_optroms/hp9825_optrom.h
Normal file
79
src/devices/bus/hp9825_optroms/hp9825_optrom.h
Normal 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 */
|
@ -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));
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
Loading…
Reference in New Issue
Block a user