hp85: support of opt. ROMs (#2604)

* hp85: added support for optional ROM cartridges. Started optional ROM
sw list (not finished).
* hp85: refactored mapping of opt. ROMs according to cuavas' comments
This commit is contained in:
fulivi 2017-08-29 13:45:36 +02:00 committed by Vas Crabb
parent 126ad62e7d
commit 05c792eee7
6 changed files with 324 additions and 19 deletions

70
hash/hp85_rom.xml Normal file
View File

@ -0,0 +1,70 @@
<?xml version="1.0"?>
<!DOCTYPE softwarelist SYSTEM "softwarelist.dtd">
<softwarelist name="hp85_rom" description="HP-85 Option ROMs">
<software name="service">
<description>Service ROM</description>
<year>198?</year>
<publisher>Hewlett-Packard</publisher>
<info name="serial" value="00085-60952"/>
<part name="rom" interface="hp80_rom">
<feature name="sc" value="0xe0"/>
<dataarea name="rom" size="0x2000">
<rom name="rom340.bin" size="0x2000" crc="41441333" sha1="6e166b7b0723da126021e2b2cd572660931e066d" offset="0"/>
</dataarea>
</part>
</software>
<software name="service_fix">
<description>Service ROM (fixed)</description>
<year>198?</year>
<publisher>Hewlett-Packard</publisher>
<info name="serial" value="00085-60952"/>
<part name="rom" interface="hp80_rom">
<feature name="sc" value="0xe0"/>
<dataarea name="rom" size="0x2000">
<rom name="rom340_fixed.bin" size="0x2000" crc="3ebdd60a" sha1="efa3d3cc9e593f6fe74b1189ea4c2dd0660ae698" offset="0"/>
</dataarea>
</part>
</software>
<software name="assembler">
<description>Assembler ROM</description>
<year>1980</year>
<publisher>Hewlett-Packard</publisher>
<info name="serial" value="00085-15007"/>
<part name="rom" interface="hp80_rom">
<feature name="sc" value="0x28"/>
<dataarea name="rom" size="0x2000">
<rom name="rom050.bin" size="0x2000" crc="9827cc3c" sha1="018d6a8df68a839b4e192da957f38a5db20f8bfc" offset="0"/>
</dataarea>
</part>
</software>
<software name="matrix">
<description>Matrix ROM</description>
<year>1979</year>
<publisher>Hewlett-Packard</publisher>
<info name="serial" value="00085-15004"/>
<part name="rom" interface="hp80_rom">
<feature name="sc" value="0xB0"/>
<dataarea name="rom" size="0x2000">
<rom name="rom260.bin" size="0x2000" crc="70f83074" sha1="3ef192ecff71b967ba747bea8df483e0596988b1" offset="0"/>
</dataarea>
</part>
</software>
<software name="io">
<description>I/O ROM</description>
<year>1979</year>
<publisher>Hewlett-Packard</publisher>
<info name="serial" value="00085-15003"/>
<part name="rom" interface="hp80_rom">
<feature name="sc" value="0xC0"/>
<dataarea name="rom" size="0x2000">
<rom name="rom300.bin" size="0x2000" crc="6f904a4c" sha1="6f90899fa983e2fd63088ce516c35d07e5942f2b" offset="0"/>
</dataarea>
</part>
</software>
</softwarelist>

View File

@ -3088,6 +3088,17 @@ if (BUSES["HP_OPTROM"]~=null) then
}
end
---------------------------------------------------
--
--@src/devices/bus/hp80_optroms/hp80_optrom.h,BUSES["HP80_OPTROM"] = true
---------------------------------------------------
if (BUSES["HP80_OPTROM"]~=null) then
files {
MAME_DIR .. "src/devices/bus/hp80_optroms/hp80_optrom.cpp",
}
end
---------------------------------------------------
--
--@src/devices/bus/hp9845_io/hp9845_io.h,BUSES["HP9845_IO"] = true

View File

@ -678,6 +678,7 @@ BUSES["IQ151"] = true
BUSES["ISA"] = true
BUSES["ISBX"] = true
BUSES["HP_OPTROM"] = true
BUSES["HP80_OPTROM"] = true
BUSES["HP9845_IO"] = true
BUSES["KC"] = true
BUSES["LPCI"] = true

View File

@ -0,0 +1,116 @@
// license:BSD-3-Clause
// copyright-holders: F. Ulivi
/*********************************************************************
hp80_optrom.cpp
Optional ROMs for HP80 systems
*********************************************************************/
#include "emu.h"
#include "hp80_optrom.h"
#include "softlist.h"
// Debugging
#define VERBOSE 1
#include "logmacro.h"
DEFINE_DEVICE_TYPE(HP80_OPTROM_CART, hp80_optrom_cart_device, "hp80_optrom_cart", "HP80 optional ROM cartridge")
DEFINE_DEVICE_TYPE(HP80_OPTROM_SLOT, hp80_optrom_slot_device, "hp80_optrom_slot", "HP80 optional ROM slot")
// +-----------------------+
// |hp80_optrom_cart_device|
// +-----------------------+
hp80_optrom_cart_device::hp80_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)
{
}
hp80_optrom_cart_device::hp80_optrom_cart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
hp80_optrom_cart_device(mconfig, HP80_OPTROM_CART, tag, owner, clock)
{
}
// +-----------------------+
// |hp80_optrom_slot_device|
// +-----------------------+
hp80_optrom_slot_device::hp80_optrom_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, HP80_OPTROM_SLOT, tag, owner, clock),
device_image_interface(mconfig, *this),
device_slot_interface(mconfig, *this),
m_cart(nullptr),
m_select_code(0)
{
}
hp80_optrom_slot_device::~hp80_optrom_slot_device()
{
}
void hp80_optrom_slot_device::install_read_handler(address_space& space)
{
if (loaded_through_softlist()) {
offs_t start = (offs_t)m_select_code * HP80_OPTROM_SIZE;
space.install_rom(start , start + HP80_OPTROM_SIZE - 1 , get_software_region("rom"));
}
}
void hp80_optrom_slot_device::device_start()
{
m_cart = dynamic_cast<hp80_optrom_cart_device *>(get_card_device());
}
image_init_result hp80_optrom_slot_device::call_load()
{
LOG("hp80_optrom: call_load\n");
if (m_cart == nullptr || !loaded_through_softlist()) {
LOG("hp80_optrom: must be loaded from sw list\n");
return image_init_result::FAIL;
}
const char *sc_feature = get_feature("sc");
if (sc_feature == nullptr) {
LOG("hp80_optrom: no 'sc' feature\n");
return image_init_result::FAIL;
}
unsigned sc;
if (sc_feature[ 0 ] != '0' || sc_feature[ 1 ] != 'x' || sscanf(&sc_feature[ 2 ] , "%x" , &sc) != 1) {
LOG("hp80_optrom: can't parse 'sc' feature\n");
return image_init_result::FAIL;
}
// Valid SC values: 0x01..0xff
if (sc < 1 || sc > 0xff) {
LOG("hp80_optrom: illegal select code (%x)\n" , sc);
return image_init_result::FAIL;
}
auto length = get_software_region_length("rom");
if (length != HP80_OPTROM_SIZE) {
LOG("hp80_optrom: illegal region length (%x)\n" , length);
return image_init_result::FAIL;
}
LOG("hp80_optrom: loaded SC=0x%02x\n" , sc);
m_select_code = sc;
return image_init_result::PASS;
}
void hp80_optrom_slot_device::call_unload()
{
LOG("hp80_optrom: call_unload\n");
machine().schedule_soft_reset();
}
std::string hp80_optrom_slot_device::get_default_card_software(get_default_card_software_hook &hook) const
{
return software_get_default_slot("rom");
}
SLOT_INTERFACE_START(hp80_optrom_slot_device)
SLOT_INTERFACE_INTERNAL("rom", HP80_OPTROM_CART)
SLOT_INTERFACE_END

View File

@ -0,0 +1,77 @@
// license:BSD-3-Clause
// copyright-holders: F. Ulivi
/*********************************************************************
hp80_optrom.h
Optional ROMs for HP80 systems
*********************************************************************/
#ifndef MAME_BUS_HP80_OPTROMS_HP80_OPTROM_H
#define MAME_BUS_HP80_OPTROMS_HP80_OPTROM_H
#pragma once
#include "softlist_dev.h"
// Size of optional ROMs (8k)
static constexpr offs_t HP80_OPTROM_SIZE = 0x2000;
class hp80_optrom_cart_device : public device_t,
public device_slot_card_interface
{
public:
// construction/destruction
hp80_optrom_cart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
protected:
hp80_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 hp80_optrom_slot_device : public device_t,
public device_image_interface,
public device_slot_interface
{
public:
// construction/destruction
hp80_optrom_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual ~hp80_optrom_slot_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 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 "hp80_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;
hp80_optrom_cart_device *m_cart;
uint8_t m_select_code;
};
// device type definition
DECLARE_DEVICE_TYPE(HP80_OPTROM_SLOT, hp80_optrom_slot_device)
DECLARE_DEVICE_TYPE(HP80_OPTROM_CART, hp80_optrom_cart_device)
SLOT_INTERFACE_EXTERN(hp80_optrom_slot_device);
#endif // MAME_BUS_HP80_OPTROMS_HP80_OPTROM_H

View File

@ -15,6 +15,9 @@
#include "sound/dac.h"
#include "sound/volt_reg.h"
#include "machine/1ma6.h"
#include "bus/hp80_optroms/hp80_optrom.h"
#include "softlist.h"
#include "machine/bankdev.h"
// Debugging
#define VERBOSE 1
@ -114,12 +117,12 @@ protected:
required_device<timer_device> m_clk_busy_timer;
required_device<beep_device> m_beep;
required_device<dac_1bit_device> m_dac;
required_region_ptr<uint8_t> m_rom00;
required_memory_bank m_rombank;
required_ioport m_io_key0;
required_ioport m_io_key1;
required_ioport m_io_key2;
required_ioport m_io_modkeys;
required_device_array<hp80_optrom_slot_device , 6> m_rom_drawers;
required_device<address_map_bank_device> m_rombank;
// Character generator
required_region_ptr<uint8_t> m_chargen;
@ -132,7 +135,6 @@ protected:
uint8_t m_crt_ctl;
uint8_t m_crt_read_byte;
uint8_t m_crt_write_byte;
uint8_t m_empty_bank[ 0x2000 ];
bool m_global_int_en;
uint16_t m_int_req;
uint16_t m_int_serv;
@ -183,12 +185,12 @@ hp85_state::hp85_state(const machine_config &mconfig, device_type type, const ch
m_clk_busy_timer(*this , "clk_busy_timer"),
m_beep(*this , "beeper"),
m_dac(*this , "dac"),
m_rom00(*this , "rom00"),
m_rombank(*this , "rombank"),
m_io_key0(*this , "KEY0"),
m_io_key1(*this , "KEY1"),
m_io_key2(*this , "KEY2"),
m_io_modkeys(*this, "MODKEYS"),
m_rom_drawers(*this , "drawer%u" , 1),
m_rombank(*this , "rombank"),
m_chargen(*this , "chargen")
{
}
@ -197,14 +199,6 @@ void hp85_state::machine_start()
{
machine().first_screen()->register_screen_bitmap(m_bitmap);
m_video_mem.resize(VIDEO_MEM_SIZE);
// ROM in bank 0 is always present (it's part of system ROMs)
m_rombank->configure_entry(0 , m_rom00);
memset(&m_empty_bank[ 0 ] , 0xff , sizeof(m_empty_bank));
// All other entries in rombank (01-FF) not present for now
m_rombank->configure_entries(1 , 255 , m_empty_bank , 0);
}
void hp85_state::machine_reset()
@ -215,9 +209,6 @@ void hp85_state::machine_reset()
m_crt_ctl = BIT_MASK(CRT_CTL_POWERDN_BIT) | BIT_MASK(CRT_CTL_WIPEOUT_BIT);
m_crt_read_byte = 0;
m_crt_write_byte = 0;
// Clear RSELEC
m_rombank->set_entry(0xff);
m_int_req = 0;
m_int_serv = 0;
m_top_pending = NO_IRQ;
@ -243,6 +234,16 @@ void hp85_state::machine_reset()
m_timer_idx = 0;
m_clk_busy = false;
update_irl();
// Load optional ROMs (if any)
// All entries in rombanks [01..FF] initially not present
m_rombank->space(AS_PROGRAM).unmap_read(HP80_OPTROM_SIZE * 1 , HP80_OPTROM_SIZE * 0x100 - 1);
for (auto& draw : m_rom_drawers) {
LOG("Loading opt ROM in drawer %s\n" , draw->tag());
draw->install_read_handler(m_rombank->space(AS_PROGRAM));
}
// Clear RSELEC
m_rombank->set_bank(0xff);
}
uint32_t hp85_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
@ -534,7 +535,7 @@ WRITE8_MEMBER(hp85_state::clkdat_w)
WRITE8_MEMBER(hp85_state::rselec_w)
{
m_rombank->set_entry(data);
m_rombank->set_bank(data);
}
// Outer index: key position [0..79] = r * 8 + c
@ -1011,7 +1012,7 @@ INPUT_PORTS_END
static ADDRESS_MAP_START(cpu_mem_map , AS_PROGRAM , 8 , hp85_state)
ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(0x0000 , 0x5fff) AM_ROM
AM_RANGE(0x6000 , 0x7fff) AM_ROMBANK("rombank")
AM_RANGE(0x6000 , 0x7fff) AM_DEVICE("rombank" , address_map_bank_device , amap8)
AM_RANGE(0x8000 , 0xbfff) AM_RAM
AM_RANGE(0xff00 , 0xff00) AM_WRITE(ginten_w)
AM_RANGE(0xff01 , 0xff01) AM_WRITE(gintdis_w)
@ -1024,11 +1025,24 @@ static ADDRESS_MAP_START(cpu_mem_map , AS_PROGRAM , 8 , hp85_state)
AM_RANGE(0xff18 , 0xff18) AM_WRITE(rselec_w)
ADDRESS_MAP_END
static ADDRESS_MAP_START(rombank_mem_map , AS_PROGRAM , 8 , hp85_state)
ADDRESS_MAP_UNMAP_HIGH
// ROM in bank 0 is always present (it's part of system ROMs)
AM_RANGE(0x0000 , 0x1fff) AM_ROM
ADDRESS_MAP_END
static MACHINE_CONFIG_START(hp85)
MCFG_CPU_ADD("cpu" , HP_CAPRICORN , MASTER_CLOCK / 16)
MCFG_CPU_PROGRAM_MAP(cpu_mem_map)
MCFG_CPU_IRQ_ACKNOWLEDGE_DRIVER(hp85_state , irq_callback)
MCFG_DEVICE_ADD("rombank", ADDRESS_MAP_BANK, 0)
MCFG_DEVICE_PROGRAM_MAP(rombank_mem_map)
MCFG_ADDRESS_MAP_BANK_ENDIANNESS(ENDIANNESS_LITTLE)
MCFG_ADDRESS_MAP_BANK_DATABUS_WIDTH(8)
MCFG_ADDRESS_MAP_BANK_ADDRBUS_WIDTH(21)
MCFG_ADDRESS_MAP_BANK_STRIDE(0x2000)
MCFG_SCREEN_ADD("screen" , RASTER)
MCFG_SCREEN_RAW_PARAMS(MASTER_CLOCK / 2 , 312 , 0 , 256 , 256 , 0 , 192)
MCFG_SCREEN_UPDATE_DRIVER(hp85_state , screen_update)
@ -1055,6 +1069,22 @@ static MACHINE_CONFIG_START(hp85)
// Tape drive
MCFG_DEVICE_ADD("tape" , HP_1MA6 , 0)
// Optional ROMs
MCFG_DEVICE_ADD("drawer1", HP80_OPTROM_SLOT, 0)
MCFG_DEVICE_SLOT_INTERFACE(hp80_optrom_slot_device, NULL, false)
MCFG_DEVICE_ADD("drawer2", HP80_OPTROM_SLOT, 0)
MCFG_DEVICE_SLOT_INTERFACE(hp80_optrom_slot_device, NULL, false)
MCFG_DEVICE_ADD("drawer3", HP80_OPTROM_SLOT, 0)
MCFG_DEVICE_SLOT_INTERFACE(hp80_optrom_slot_device, NULL, false)
MCFG_DEVICE_ADD("drawer4", HP80_OPTROM_SLOT, 0)
MCFG_DEVICE_SLOT_INTERFACE(hp80_optrom_slot_device, NULL, false)
MCFG_DEVICE_ADD("drawer5", HP80_OPTROM_SLOT, 0)
MCFG_DEVICE_SLOT_INTERFACE(hp80_optrom_slot_device, NULL, false)
MCFG_DEVICE_ADD("drawer6", HP80_OPTROM_SLOT, 0)
MCFG_DEVICE_SLOT_INTERFACE(hp80_optrom_slot_device, NULL, false)
MCFG_SOFTWARE_LIST_ADD("optrom_list" , "hp85_rom")
MACHINE_CONFIG_END
ROM_START(hp85)
@ -1063,7 +1093,7 @@ ROM_START(hp85)
ROM_LOAD("romsys2.bin" , 0x2000 , 0x2000 , CRC(50a85263) SHA1(3cf1d08749103ee245d572550ba1b053ffc7ef57))
ROM_LOAD("romsys3.bin" , 0x4000 , 0x2000 , CRC(0df385f0) SHA1(4c5ce5afd28f6d776f16cabbbbcc09769ff306b7))
ROM_REGION(0x2000 , "rom00" , 0)
ROM_REGION(0x2000 , "rombank" , 0)
ROM_LOAD("rom000.bin" , 0 , 0x2000 , CRC(e13b8ae3) SHA1(2374618d25d1a000ddb534ae4f55ebd98ce0fff3))
ROM_REGION(0x400 , "chargen" , 0)