mirror of
https://github.com/holub/mame
synced 2025-04-18 22:49:58 +03:00
HP9825 emulation added (#4018)
* hphybrid: major overhaul to add the 09825-67907 variant * hphybrid: adapted hp64k & hp9845 to revised hphybrid CPUs * hp9825: first release of HP9825B emulator * hphybrid: added 09825-67907 to unidasm * hp9825: improved appearance of blinking cursor * hphybrid: minor changes
This commit is contained in:
parent
e1a3c9fbea
commit
7fdb72d7a2
@ -2246,6 +2246,7 @@ files {
|
||||
MAME_DIR .. "src/mame/drivers/hp2620.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/hp700.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/hp2640.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/hp9825.cpp",
|
||||
}
|
||||
|
||||
createMESSProjects(_target, _subtarget, "hec2hrp")
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -8,15 +8,25 @@
|
||||
// The HP hybrid processor series is composed of a few different models with different
|
||||
// capabilities. The series was derived from HP's own 2116 processor by translating a
|
||||
// discrete implementation of the 1960s into a multi-chip module (hence the "hybrid" name).
|
||||
// This emulator currently supports both the 5061-3001 & the 5061-3011 versions.
|
||||
// This emulator currently supports the 5061-3001, 5061-3011 and 09825-67907 versions.
|
||||
//
|
||||
// | *CPU* | *Addr bits* | *Multi-indirect* | *BPC* | *IOC* | *EMC* | *AEC* | *Used in* |
|
||||
// |-------------+-------------+------------------+-------+-------+-------+-------+-----------|
|
||||
// | 09825-67907 | 15 | Y | Y | Y | Y | N | HP 9825 |
|
||||
// | 5061-3001 | 16 (+ext) | N | Y | Y | Y | Y | HP 9845 |
|
||||
// | 5061-3011 | 16 | N | Y | Y | N | N | HP 64000 |
|
||||
//
|
||||
// For this emulator I mainly relied on these sources:
|
||||
// - "The how they do dat manual": this manual has way more than you will ever want to know
|
||||
// about the hybrid processors. It often gets to the single transistor detail level..
|
||||
// - "Reference manual for the CPD N-MOS II Processor": this is an internal HP manual that
|
||||
// was targeted at the hw/sw user of the processors.
|
||||
// - http://www.hp9845.net/ website
|
||||
// - HP manual "Assembly development ROM manual for the HP9845": this is the most precious
|
||||
// and "enabling" resource of all
|
||||
// - HP manual "Assembly development ROM manual for the HP9845"
|
||||
// - US Patent 4,075,679 describing the HP9825 system
|
||||
// - US Patent 4,180,854 describing the HP9845 system
|
||||
// - Study of disassembly of firmware of HP64000 & HP9845 systems
|
||||
// - hp9800e emulator for inspiration on implementing EMC instructions
|
||||
// - hp9800e emulator (now go9800) for inspiration on implementing EMC instructions
|
||||
// - A lot of "educated" guessing
|
||||
|
||||
#ifndef MAME_CPU_HPHYBRID_HPHYBRID_H
|
||||
@ -37,15 +47,7 @@
|
||||
#define HP_IOADDR_IC_SHIFT 0
|
||||
|
||||
// Compose an I/O address from PA & IC
|
||||
#define HP_MAKE_IOADDR(pa , ic) (((pa) << HP_IOADDR_PA_SHIFT) | ((ic) << HP_IOADDR_IC_SHIFT))
|
||||
|
||||
// Set boot mode of 5061-3001: either normal (false) or as in HP9845 system (true)
|
||||
#define MCFG_HPHYBRID_SET_9845_BOOT(_mode) \
|
||||
downcast<hp_5061_3001_cpu_device &>(*device).set_boot_mode(_mode);
|
||||
|
||||
// PA changed callback
|
||||
#define MCFG_HPHYBRID_PA_CHANGED(_devcb) \
|
||||
downcast<hp_hybrid_cpu_device &>(*device).set_pa_changed_func(DEVCB_##_devcb);
|
||||
inline constexpr unsigned HP_MAKE_IOADDR(unsigned pa , unsigned ic) { return ((pa << HP_IOADDR_PA_SHIFT) | (ic << HP_IOADDR_IC_SHIFT)); }
|
||||
|
||||
class hp_hybrid_cpu_device : public cpu_device
|
||||
{
|
||||
@ -57,7 +59,10 @@ public:
|
||||
|
||||
uint8_t pa_r() const;
|
||||
|
||||
template <class Object> devcb_base &set_pa_changed_func(Object &&cb) { return m_pa_changed_func.set_callback(std::forward<Object>(cb)); }
|
||||
auto pa_changed_cb() { return m_pa_changed_func.bind(); }
|
||||
|
||||
void set_relative_mode(bool rela) { m_relative_mode = rela; }
|
||||
void set_rw_cycles(unsigned read_cycles , unsigned write_cycles) { m_r_cycles = read_cycles; m_w_cycles = write_cycles; }
|
||||
|
||||
protected:
|
||||
hp_hybrid_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint8_t addrwidth);
|
||||
@ -67,16 +72,22 @@ protected:
|
||||
virtual void device_reset() override;
|
||||
|
||||
// device_execute_interface overrides
|
||||
virtual uint32_t execute_min_cycles() const override { return 6; }
|
||||
virtual uint32_t execute_min_cycles() const override { return m_r_cycles; }
|
||||
virtual uint32_t execute_input_lines() const override { return 2; }
|
||||
virtual uint32_t execute_default_irq_vector(int inputnum) const override { return 0xff; }
|
||||
virtual void execute_run() override;
|
||||
virtual void execute_set_input(int inputnum, int state) override;
|
||||
|
||||
uint16_t execute_one(uint16_t opcode);
|
||||
uint16_t execute_one_sub(uint16_t opcode);
|
||||
// Execute an instruction that doesn't belong to either BPC or IOC
|
||||
virtual uint16_t execute_no_bpc_ioc(uint16_t opcode) = 0;
|
||||
bool execute_one_bpc(uint16_t opcode , uint16_t& next_pc);
|
||||
// Execute an instruction that doesn't belong to BPC
|
||||
virtual bool execute_no_bpc(uint16_t opcode , uint16_t& next_pc) = 0;
|
||||
|
||||
// Add EMC state
|
||||
void emc_start();
|
||||
|
||||
// Execute EMC instructions
|
||||
bool execute_emc(uint16_t opcode , uint16_t& next_pc);
|
||||
|
||||
// device_memory_interface overrides
|
||||
virtual space_config_vector memory_space_config() const override;
|
||||
@ -84,9 +95,6 @@ protected:
|
||||
// device_state_interface overrides
|
||||
virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
|
||||
|
||||
// device_disasm_interface overrides
|
||||
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
|
||||
|
||||
// Different cases of memory access
|
||||
// See patent @ pg 361
|
||||
typedef enum {
|
||||
@ -97,25 +105,42 @@ protected:
|
||||
} aec_cases_t;
|
||||
|
||||
// do memory address extension
|
||||
virtual uint32_t add_mae(aec_cases_t aec_case , uint16_t addr) = 0;
|
||||
virtual uint32_t add_mae(aec_cases_t aec_case , uint16_t addr);
|
||||
|
||||
uint16_t remove_mae(uint32_t addr);
|
||||
static uint16_t remove_mae(uint32_t addr);
|
||||
|
||||
uint16_t RM(aec_cases_t aec_case , uint16_t addr);
|
||||
uint16_t RM(uint32_t addr);
|
||||
virtual uint16_t read_non_common_reg(uint16_t addr) = 0;
|
||||
virtual bool read_non_common_reg(uint16_t addr , uint16_t& v) = 0;
|
||||
bool read_emc_reg(uint16_t addr , uint16_t& v);
|
||||
|
||||
void WM(aec_cases_t aec_case , uint16_t addr , uint16_t v);
|
||||
void WM(uint32_t addr , uint16_t v);
|
||||
virtual void write_non_common_reg(uint16_t addr , uint16_t v) = 0;
|
||||
virtual bool write_non_common_reg(uint16_t addr , uint16_t v) = 0;
|
||||
bool write_emc_reg(uint16_t addr , uint16_t v);
|
||||
|
||||
uint16_t RIO(uint8_t pa , uint8_t ic);
|
||||
void WIO(uint8_t pa , uint8_t ic , uint16_t v);
|
||||
|
||||
uint16_t fetch();
|
||||
virtual uint16_t get_indirect_target(uint32_t addr);
|
||||
virtual void enter_isr();
|
||||
virtual void handle_dma() = 0;
|
||||
|
||||
uint16_t get_skip_addr(uint16_t opcode , bool condition) const;
|
||||
|
||||
void update_pa();
|
||||
|
||||
devcb_write8 m_pa_changed_func;
|
||||
uint8_t m_last_pa;
|
||||
|
||||
int m_icount;
|
||||
uint32_t m_addr_mask;
|
||||
uint16_t m_addr_mask_low16;
|
||||
bool m_relative_mode;
|
||||
unsigned m_r_cycles;
|
||||
unsigned m_w_cycles;
|
||||
bool m_boot_mode;
|
||||
bool m_forced_bsc_25;
|
||||
|
||||
// State of processor
|
||||
@ -134,39 +159,26 @@ protected:
|
||||
uint16_t m_dmac; // DMA counter
|
||||
uint16_t m_reg_I; // Instruction register
|
||||
uint32_t m_genpc; // Full PC
|
||||
// EMC registers
|
||||
uint16_t m_reg_ar2[ 4 ]; // AR2 register
|
||||
uint16_t m_reg_se; // SE register (4 bits)
|
||||
uint16_t m_reg_r25; // R25 register
|
||||
uint16_t m_reg_r26; // R26 register
|
||||
uint16_t m_reg_r27; // R27 register
|
||||
|
||||
address_space *m_program;
|
||||
|
||||
private:
|
||||
address_space_config m_program_config;
|
||||
address_space_config m_io_config;
|
||||
|
||||
address_space *m_program;
|
||||
memory_access_cache<1, -1, ENDIANNESS_BIG> *m_cache;
|
||||
address_space *m_io;
|
||||
|
||||
uint32_t get_ea(uint16_t opcode);
|
||||
void do_add(uint16_t& addend1 , uint16_t addend2);
|
||||
uint16_t get_skip_addr_sc(uint16_t opcode , uint16_t& v , unsigned n);
|
||||
uint16_t get_skip_addr_sc(uint16_t opcode , uint32_t& v , unsigned n);
|
||||
void do_pw(uint16_t opcode);
|
||||
template<typename T> uint16_t get_skip_addr_sc(uint16_t opcode , T& v , unsigned n);
|
||||
void check_for_interrupts();
|
||||
virtual void enter_isr();
|
||||
void handle_dma();
|
||||
|
||||
uint16_t RIO(uint8_t pa , uint8_t ic);
|
||||
void WIO(uint8_t pa , uint8_t ic , uint16_t v);
|
||||
};
|
||||
|
||||
class hp_5061_3001_cpu_device : public hp_hybrid_cpu_device
|
||||
{
|
||||
public:
|
||||
hp_5061_3001_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
void set_boot_mode(bool mode) { m_boot_mode = mode; }
|
||||
|
||||
protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual uint32_t execute_max_cycles() const override { return 237; } // FMP 15
|
||||
|
||||
static uint8_t do_dec_shift_r(uint8_t d1 , uint64_t& mantissa);
|
||||
static uint8_t do_dec_shift_l(uint8_t d12 , uint64_t& mantissa);
|
||||
@ -177,25 +189,6 @@ protected:
|
||||
uint64_t do_mrxy(uint64_t ar);
|
||||
bool do_dec_add(bool carry_in , uint64_t& a , uint64_t b);
|
||||
void do_mpy();
|
||||
|
||||
virtual uint16_t execute_no_bpc_ioc(uint16_t opcode) override;
|
||||
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
|
||||
virtual uint32_t add_mae(aec_cases_t aec_case, uint16_t addr) override;
|
||||
virtual uint16_t read_non_common_reg(uint16_t addr) override;
|
||||
virtual void write_non_common_reg(uint16_t addr , uint16_t v) override;
|
||||
|
||||
private:
|
||||
bool m_boot_mode;
|
||||
|
||||
// Additional state of processor
|
||||
uint16_t m_reg_ar2[ 4 ]; // AR2 register
|
||||
uint16_t m_reg_se; // SE register (4 bits)
|
||||
uint16_t m_reg_r25; // R25 register
|
||||
uint16_t m_reg_r26; // R26 register
|
||||
uint16_t m_reg_r27; // R27 register
|
||||
uint16_t m_reg_aec[ 37 - 32 + 1 ]; // AEC registers R32-R37
|
||||
|
||||
virtual void enter_isr() override;
|
||||
};
|
||||
|
||||
class hp_5061_3011_cpu_device : public hp_hybrid_cpu_device
|
||||
@ -204,15 +197,74 @@ public:
|
||||
hp_5061_3011_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
protected:
|
||||
hp_5061_3011_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint8_t addrwidth);
|
||||
// TODO: fix
|
||||
virtual uint32_t execute_max_cycles() const override { return 25; }
|
||||
virtual uint16_t execute_no_bpc_ioc(uint16_t opcode) override;
|
||||
virtual uint32_t add_mae(aec_cases_t aec_case , uint16_t addr) override;
|
||||
virtual uint16_t read_non_common_reg(uint16_t addr) override;
|
||||
virtual void write_non_common_reg(uint16_t addr , uint16_t v) override;
|
||||
virtual bool execute_no_bpc(uint16_t opcode , uint16_t& next_pc) override;
|
||||
virtual bool read_non_common_reg(uint16_t addr , uint16_t& v) override;
|
||||
virtual bool write_non_common_reg(uint16_t addr , uint16_t v) override;
|
||||
virtual void handle_dma() override;
|
||||
|
||||
// device_disasm_interface overrides
|
||||
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
|
||||
};
|
||||
|
||||
class hp_5061_3001_cpu_device : public hp_5061_3011_cpu_device
|
||||
{
|
||||
public:
|
||||
hp_5061_3001_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
// Set boot mode of 5061-3001: either normal (false) or as in HP9845 system (true)
|
||||
void set_9845_boot_mode(bool mode) { m_boot_mode = mode; }
|
||||
|
||||
protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
// TODO: fix
|
||||
virtual uint32_t execute_max_cycles() const override { return 237; } // FMP 15
|
||||
|
||||
virtual bool execute_no_bpc(uint16_t opcode , uint16_t& next_pc) override;
|
||||
virtual uint32_t add_mae(aec_cases_t aec_case, uint16_t addr) override;
|
||||
virtual bool read_non_common_reg(uint16_t addr , uint16_t& v) override;
|
||||
virtual bool write_non_common_reg(uint16_t addr , uint16_t v) override;
|
||||
virtual void enter_isr() override;
|
||||
|
||||
// device_disasm_interface overrides
|
||||
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
|
||||
private:
|
||||
// Additional state of processor
|
||||
uint16_t m_reg_aec[ 37 - 32 + 1 ]; // AEC registers R32-R37
|
||||
};
|
||||
|
||||
class hp_09825_67907_cpu_device : public hp_hybrid_cpu_device
|
||||
{
|
||||
public:
|
||||
hp_09825_67907_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
|
||||
// device_execute_interface overrides
|
||||
// TODO: fix
|
||||
virtual uint32_t execute_max_cycles() const override { return 237; } // FMP 15
|
||||
|
||||
virtual bool execute_no_bpc(uint16_t opcode , uint16_t& next_pc) override;
|
||||
|
||||
// device_disasm_interface overrides
|
||||
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
|
||||
|
||||
virtual bool read_non_common_reg(uint16_t addr , uint16_t& v) override;
|
||||
virtual bool write_non_common_reg(uint16_t addr , uint16_t v) override;
|
||||
virtual uint16_t get_indirect_target(uint32_t addr) override;
|
||||
virtual void handle_dma() override;
|
||||
|
||||
private:
|
||||
void inc_dec_cd(uint16_t& cd_reg , bool increment , bool byte);
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(HP_5061_3001, hp_5061_3001_cpu_device)
|
||||
DECLARE_DEVICE_TYPE(HP_5061_3011, hp_5061_3011_cpu_device)
|
||||
DECLARE_DEVICE_TYPE(HP_09825_67907 , hp_09825_67907_cpu_device)
|
||||
|
||||
#endif // MAME_CPU_HPHYBRID_HPHYBRID_H
|
||||
|
@ -8,86 +8,15 @@
|
||||
#include "hphybrid_dasm.h"
|
||||
#include "hphybrid_defs.h"
|
||||
|
||||
void hp_hybrid_disassembler::addr_2_str(std::ostream &stream, uint16_t addr , bool indirect , bool is_3001)
|
||||
void hp_hybrid_disassembler::addr_2_str(std::ostream &stream, uint16_t addr , bool indirect)
|
||||
{
|
||||
util::stream_format(stream, "$%04x" , addr);
|
||||
|
||||
if (is_3001) {
|
||||
switch (addr) {
|
||||
case HP_REG_AR1_ADDR:
|
||||
stream << "(Ar1)";
|
||||
break;
|
||||
|
||||
case HP_REG_AR1_ADDR + 1:
|
||||
stream << "(Ar1_2)";
|
||||
break;
|
||||
|
||||
case HP_REG_AR1_ADDR + 2:
|
||||
stream << "(Ar1_3)";
|
||||
break;
|
||||
|
||||
case HP_REG_AR1_ADDR + 3:
|
||||
stream << "(Ar1_4)";
|
||||
break;
|
||||
|
||||
case HP_REG_AR2_ADDR:
|
||||
stream << "(Ar2)";
|
||||
break;
|
||||
|
||||
case HP_REG_AR2_ADDR + 1:
|
||||
stream << "(Ar2_2)";
|
||||
break;
|
||||
|
||||
case HP_REG_AR2_ADDR + 2:
|
||||
stream << "(Ar2_3)";
|
||||
break;
|
||||
|
||||
case HP_REG_AR2_ADDR + 3:
|
||||
stream << "(Ar2_4)";
|
||||
break;
|
||||
|
||||
case HP_REG_SE_ADDR:
|
||||
stream << "(SE)";
|
||||
break;
|
||||
|
||||
case HP_REG_R25_ADDR:
|
||||
stream << "(R25)";
|
||||
break;
|
||||
|
||||
case HP_REG_R26_ADDR:
|
||||
stream << "(R26)";
|
||||
break;
|
||||
|
||||
case HP_REG_R27_ADDR:
|
||||
stream << "(R27)";
|
||||
break;
|
||||
|
||||
case HP_REG_R32_ADDR:
|
||||
stream << "(R32)";
|
||||
break;
|
||||
|
||||
case HP_REG_R33_ADDR:
|
||||
stream << "(R33)";
|
||||
break;
|
||||
|
||||
case HP_REG_R34_ADDR:
|
||||
stream << "(R34)";
|
||||
break;
|
||||
|
||||
case HP_REG_R35_ADDR:
|
||||
stream << "(R35)";
|
||||
break;
|
||||
|
||||
case HP_REG_R36_ADDR:
|
||||
stream << "(R36)";
|
||||
break;
|
||||
|
||||
case HP_REG_R37_ADDR:
|
||||
stream << "(R37)";
|
||||
break;
|
||||
}
|
||||
if (m_flags & HP_HYBRID_DASM_HAS_15BITS) {
|
||||
addr &= 0x7fff;
|
||||
}
|
||||
|
||||
util::stream_format(stream, "$%04x" , addr);
|
||||
|
||||
// Common registers
|
||||
switch (addr) {
|
||||
case HP_REG_A_ADDR:
|
||||
stream << "(A)";
|
||||
@ -148,6 +77,116 @@ void hp_hybrid_disassembler::addr_2_str(std::ostream &stream, uint16_t addr , bo
|
||||
case HP_REG_D_ADDR:
|
||||
stream << "(D)";
|
||||
break;
|
||||
|
||||
default:
|
||||
// EMC registers
|
||||
if (m_flags & HP_HYBRID_DASM_HAS_EMC) {
|
||||
if (m_flags & HP_HYBRID_DASM_HAS_15BITS) {
|
||||
switch (addr) {
|
||||
case HP_REG_AR1_ADDR & 0x7fff:
|
||||
stream << "(Ar1)";
|
||||
break;
|
||||
|
||||
case (HP_REG_AR1_ADDR & 0x7fff) + 1:
|
||||
stream << "(Ar1_2)";
|
||||
break;
|
||||
|
||||
case (HP_REG_AR1_ADDR & 0x7fff) + 2:
|
||||
stream << "(Ar1_3)";
|
||||
break;
|
||||
|
||||
case (HP_REG_AR1_ADDR & 0x7fff) + 3:
|
||||
stream << "(Ar1_4)";
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (addr) {
|
||||
case HP_REG_AR1_ADDR:
|
||||
stream << "(Ar1)";
|
||||
break;
|
||||
|
||||
case HP_REG_AR1_ADDR + 1:
|
||||
stream << "(Ar1_2)";
|
||||
break;
|
||||
|
||||
case HP_REG_AR1_ADDR + 2:
|
||||
stream << "(Ar1_3)";
|
||||
break;
|
||||
|
||||
case HP_REG_AR1_ADDR + 3:
|
||||
stream << "(Ar1_4)";
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (addr) {
|
||||
case HP_REG_AR2_ADDR:
|
||||
stream << "(Ar2)";
|
||||
break;
|
||||
|
||||
case HP_REG_AR2_ADDR + 1:
|
||||
stream << "(Ar2_2)";
|
||||
break;
|
||||
|
||||
case HP_REG_AR2_ADDR + 2:
|
||||
stream << "(Ar2_3)";
|
||||
break;
|
||||
|
||||
case HP_REG_AR2_ADDR + 3:
|
||||
stream << "(Ar2_4)";
|
||||
break;
|
||||
|
||||
case HP_REG_SE_ADDR:
|
||||
stream << "(SE)";
|
||||
break;
|
||||
|
||||
case HP_REG_R25_ADDR:
|
||||
stream << "(R25)";
|
||||
break;
|
||||
|
||||
case HP_REG_R26_ADDR:
|
||||
stream << "(R26)";
|
||||
break;
|
||||
|
||||
case HP_REG_R27_ADDR:
|
||||
stream << "(R27)";
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
// AEC registers
|
||||
if (m_flags & HP_HYBRID_DASM_HAS_AEC) {
|
||||
switch (addr) {
|
||||
case HP_REG_R32_ADDR:
|
||||
stream << "(R32)";
|
||||
break;
|
||||
|
||||
case HP_REG_R33_ADDR:
|
||||
stream << "(R33)";
|
||||
break;
|
||||
|
||||
case HP_REG_R34_ADDR:
|
||||
stream << "(R34)";
|
||||
break;
|
||||
|
||||
case HP_REG_R35_ADDR:
|
||||
stream << "(R35)";
|
||||
break;
|
||||
|
||||
case HP_REG_R36_ADDR:
|
||||
stream << "(R36)";
|
||||
break;
|
||||
|
||||
case HP_REG_R37_ADDR:
|
||||
stream << "(R37)";
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (indirect) {
|
||||
@ -155,18 +194,23 @@ void hp_hybrid_disassembler::addr_2_str(std::ostream &stream, uint16_t addr , bo
|
||||
}
|
||||
}
|
||||
|
||||
void hp_hybrid_disassembler::param_none(std::ostream &stream, offs_t pc , uint16_t opcode , bool is_3001)
|
||||
void hp_hybrid_disassembler::param_none(std::ostream &stream, offs_t pc , uint16_t opcode)
|
||||
{
|
||||
}
|
||||
|
||||
void hp_hybrid_disassembler::param_loc(std::ostream &stream, offs_t pc , uint16_t opcode , bool is_3001)
|
||||
void hp_hybrid_disassembler::param_loc(std::ostream &stream, offs_t pc , uint16_t opcode)
|
||||
{
|
||||
uint16_t base;
|
||||
uint16_t off;
|
||||
|
||||
if (opcode & 0x0400) {
|
||||
// Current page
|
||||
base = pc;
|
||||
if (m_flags & HP_HYBRID_DASM_ABS_MODE) {
|
||||
// Current page, absolute mode
|
||||
base = (pc & 0xfc00) | 0x200;
|
||||
} else {
|
||||
// Current page, relative mode
|
||||
base = pc;
|
||||
}
|
||||
} else {
|
||||
// Base page
|
||||
base = 0;
|
||||
@ -177,26 +221,26 @@ void hp_hybrid_disassembler::param_loc(std::ostream &stream, offs_t pc , uint16_
|
||||
off -= 0x400;
|
||||
}
|
||||
|
||||
addr_2_str(stream, base + off , (opcode & 0x8000) != 0 , is_3001);
|
||||
addr_2_str(stream, base + off , (opcode & 0x8000) != 0);
|
||||
}
|
||||
|
||||
void hp_hybrid_disassembler::param_addr32(std::ostream &stream, offs_t pc , uint16_t opcode , bool is_3001)
|
||||
void hp_hybrid_disassembler::param_addr32(std::ostream &stream, offs_t pc , uint16_t opcode)
|
||||
{
|
||||
addr_2_str(stream, opcode & 0x1f , (opcode & 0x8000) != 0 , is_3001);
|
||||
addr_2_str(stream, opcode & 0x1f , (opcode & 0x8000) != 0);
|
||||
}
|
||||
|
||||
void hp_hybrid_disassembler::param_skip(std::ostream &stream, offs_t pc , uint16_t opcode , bool is_3001)
|
||||
void hp_hybrid_disassembler::param_skip(std::ostream &stream, offs_t pc , uint16_t opcode)
|
||||
{
|
||||
uint16_t off = opcode & 0x3f;
|
||||
if (off & 0x20) {
|
||||
off -= 0x40;
|
||||
}
|
||||
addr_2_str(stream , pc + off , false , is_3001);
|
||||
addr_2_str(stream , pc + off , false);
|
||||
}
|
||||
|
||||
void hp_hybrid_disassembler::param_skip_sc(std::ostream &stream, offs_t pc , uint16_t opcode , bool is_3001)
|
||||
void hp_hybrid_disassembler::param_skip_sc(std::ostream &stream, offs_t pc , uint16_t opcode)
|
||||
{
|
||||
param_skip(stream, pc, opcode , is_3001);
|
||||
param_skip(stream, pc, opcode);
|
||||
|
||||
if (opcode & 0x80) {
|
||||
if (opcode & 0x40) {
|
||||
@ -207,7 +251,7 @@ void hp_hybrid_disassembler::param_skip_sc(std::ostream &stream, offs_t pc , uin
|
||||
}
|
||||
}
|
||||
|
||||
void hp_hybrid_disassembler::param_ret(std::ostream &stream, offs_t pc , uint16_t opcode , bool is_3001)
|
||||
void hp_hybrid_disassembler::param_ret(std::ostream &stream, offs_t pc , uint16_t opcode)
|
||||
{
|
||||
int off = opcode & 0x3f;
|
||||
|
||||
@ -221,14 +265,14 @@ void hp_hybrid_disassembler::param_ret(std::ostream &stream, offs_t pc , uint16_
|
||||
}
|
||||
}
|
||||
|
||||
void hp_hybrid_disassembler::param_n16(std::ostream &stream, offs_t pc , uint16_t opcode , bool is_3001)
|
||||
void hp_hybrid_disassembler::param_n16(std::ostream &stream, offs_t pc , uint16_t opcode)
|
||||
{
|
||||
util::stream_format(stream , "%u" , (opcode & 0xf) + 1);
|
||||
}
|
||||
|
||||
void hp_hybrid_disassembler::param_reg_id(std::ostream &stream, offs_t pc , uint16_t opcode , bool is_3001)
|
||||
void hp_hybrid_disassembler::param_reg_id(std::ostream &stream, offs_t pc , uint16_t opcode)
|
||||
{
|
||||
addr_2_str(stream, opcode & 7, false , is_3001);
|
||||
addr_2_str(stream, opcode & 7, false);
|
||||
|
||||
if (opcode & 0x80) {
|
||||
stream << ",D";
|
||||
@ -237,123 +281,131 @@ void hp_hybrid_disassembler::param_reg_id(std::ostream &stream, offs_t pc , uint
|
||||
}
|
||||
}
|
||||
|
||||
const hp_hybrid_disassembler::dis_entry_t hp_hybrid_disassembler::dis_table[] = {
|
||||
// *** BPC Instructions ***
|
||||
{0xffff , 0x0000 , "NOP" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0x7800 , 0x0000 , "LDA" , &hp_hybrid_disassembler::param_loc , 0 },
|
||||
{0x7800 , 0x0800 , "LDB" , &hp_hybrid_disassembler::param_loc , 0 },
|
||||
{0x7800 , 0x1000 , "CPA" , &hp_hybrid_disassembler::param_loc , 0 },
|
||||
{0x7800 , 0x1800 , "CPB" , &hp_hybrid_disassembler::param_loc , 0 },
|
||||
{0x7800 , 0x2000 , "ADA" , &hp_hybrid_disassembler::param_loc , 0 },
|
||||
{0x7800 , 0x2800 , "ADB" , &hp_hybrid_disassembler::param_loc , 0 },
|
||||
{0x7800 , 0x3000 , "STA" , &hp_hybrid_disassembler::param_loc , 0 },
|
||||
{0x7800 , 0x3800 , "STB" , &hp_hybrid_disassembler::param_loc , 0 },
|
||||
{0x7800 , 0x4000 , "JSM" , &hp_hybrid_disassembler::param_loc , STEP_OVER },
|
||||
{0x7800 , 0x4800 , "ISZ" , &hp_hybrid_disassembler::param_loc , 0 },
|
||||
{0x7800 , 0x5000 , "AND" , &hp_hybrid_disassembler::param_loc , 0 },
|
||||
{0x7800 , 0x5800 , "DSZ" , &hp_hybrid_disassembler::param_loc , 0 },
|
||||
{0x7800 , 0x6000 , "IOR" , &hp_hybrid_disassembler::param_loc , 0 },
|
||||
{0x7800 , 0x6800 , "JMP" , &hp_hybrid_disassembler::param_loc , 0 },
|
||||
{0x7fe0 , 0x7000 , "EXE" , &hp_hybrid_disassembler::param_addr32 , 0 },
|
||||
{0xffc0 , 0x7400 , "RZA" , &hp_hybrid_disassembler::param_skip , 0 },
|
||||
{0xffc0 , 0x7C00 , "RZB" , &hp_hybrid_disassembler::param_skip , 0 },
|
||||
{0xffc0 , 0x7440 , "RIA" , &hp_hybrid_disassembler::param_skip , 0 },
|
||||
{0xffc0 , 0x7C40 , "RIB" , &hp_hybrid_disassembler::param_skip , 0 },
|
||||
{0xffc0 , 0x7500 , "SZA" , &hp_hybrid_disassembler::param_skip , 0 },
|
||||
{0xffc0 , 0x7D00 , "SZB" , &hp_hybrid_disassembler::param_skip , 0 },
|
||||
{0xffc0 , 0x7540 , "SIA" , &hp_hybrid_disassembler::param_skip , 0 },
|
||||
{0xffc0 , 0x7D40 , "SIB" , &hp_hybrid_disassembler::param_skip , 0 },
|
||||
{0xffc0 , 0x7480 , "SFS" , &hp_hybrid_disassembler::param_skip , 0 },
|
||||
{0xffc0 , 0x7580 , "SFC" , &hp_hybrid_disassembler::param_skip , 0 },
|
||||
{0xffc0 , 0x7c80 , "SSS" , &hp_hybrid_disassembler::param_skip , 0 },
|
||||
{0xffc0 , 0x7d80 , "SSC" , &hp_hybrid_disassembler::param_skip , 0 },
|
||||
{0xffc0 , 0x7cc0 , "SHS" , &hp_hybrid_disassembler::param_skip , 0 },
|
||||
{0xffc0 , 0x7dc0 , "SHC" , &hp_hybrid_disassembler::param_skip , 0 },
|
||||
{0xff00 , 0x7600 , "SLA" , &hp_hybrid_disassembler::param_skip_sc , 0 },
|
||||
{0xff00 , 0x7e00 , "SLB" , &hp_hybrid_disassembler::param_skip_sc , 0 },
|
||||
{0xff00 , 0x7700 , "RLA" , &hp_hybrid_disassembler::param_skip_sc , 0 },
|
||||
{0xff00 , 0x7f00 , "RLB" , &hp_hybrid_disassembler::param_skip_sc , 0 },
|
||||
{0xff00 , 0xf400 , "SAP" , &hp_hybrid_disassembler::param_skip_sc , 0 },
|
||||
{0xff00 , 0xfc00 , "SBP" , &hp_hybrid_disassembler::param_skip_sc , 0 },
|
||||
{0xff00 , 0xf500 , "SAM" , &hp_hybrid_disassembler::param_skip_sc , 0 },
|
||||
{0xff00 , 0xfd00 , "SBM" , &hp_hybrid_disassembler::param_skip_sc , 0 },
|
||||
{0xff00 , 0xf600 , "SOC" , &hp_hybrid_disassembler::param_skip_sc , 0 },
|
||||
{0xff00 , 0xf700 , "SOS" , &hp_hybrid_disassembler::param_skip_sc , 0 },
|
||||
{0xff00 , 0xfe00 , "SEC" , &hp_hybrid_disassembler::param_skip_sc , 0 },
|
||||
{0xff00 , 0xff00 , "SES" , &hp_hybrid_disassembler::param_skip_sc , 0 },
|
||||
{0xffff , 0xf020 , "TCA" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xffff , 0xf820 , "TCB" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xffff , 0xf060 , "CMA" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xffff , 0xf860 , "CMB" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xff80 , 0xf080 , "RET" , &hp_hybrid_disassembler::param_ret , STEP_OUT },
|
||||
{0xfff0 , 0xf100 , "AAR" , &hp_hybrid_disassembler::param_n16 , 0 },
|
||||
{0xfff0 , 0xf900 , "ABR" , &hp_hybrid_disassembler::param_n16 , 0 },
|
||||
{0xffff , 0xf14f , "CLA" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xfff0 , 0xf140 , "SAR" , &hp_hybrid_disassembler::param_n16 , 0 },
|
||||
{0xffff , 0xf94f , "CLB" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xfff0 , 0xf940 , "SBR" , &hp_hybrid_disassembler::param_n16 , 0 },
|
||||
{0xfff0 , 0xf180 , "SAL" , &hp_hybrid_disassembler::param_n16 , 0 },
|
||||
{0xfff0 , 0xf980 , "SBL" , &hp_hybrid_disassembler::param_n16 , 0 },
|
||||
{0xfff0 , 0xf1c0 , "RAR" , &hp_hybrid_disassembler::param_n16 , 0 },
|
||||
{0xfff0 , 0xf9c0 , "RBR" , &hp_hybrid_disassembler::param_n16 , 0 },
|
||||
// *** IOC Instructions ***
|
||||
{0xffff , 0x7100 , "SDO" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7108 , "SDI" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7110 , "EIR" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7118 , "DIR" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7120 , "DMA" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7128 , "PCM" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7138 , "DDR" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7140 , "DBL" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7148 , "CBL" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7150 , "DBU" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7158 , "CBU" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xff78 , 0x7160 , "PWC" , &hp_hybrid_disassembler::param_reg_id , 0 },
|
||||
{0xff78 , 0x7168 , "PWD" , &hp_hybrid_disassembler::param_reg_id , 0 },
|
||||
{0xff78 , 0x7960 , "PBC" , &hp_hybrid_disassembler::param_reg_id , 0 },
|
||||
{0xff78 , 0x7968 , "PBD" , &hp_hybrid_disassembler::param_reg_id , 0 },
|
||||
{0xff78 , 0x7170 , "WWC" , &hp_hybrid_disassembler::param_reg_id , 0 },
|
||||
{0xff78 , 0x7178 , "WWD" , &hp_hybrid_disassembler::param_reg_id , 0 },
|
||||
{0xff78 , 0x7970 , "WBC" , &hp_hybrid_disassembler::param_reg_id , 0 },
|
||||
{0xff78 , 0x7978 , "WBD" , &hp_hybrid_disassembler::param_reg_id , 0 },
|
||||
// *** END ***
|
||||
{0 , 0 , nullptr , nullptr , 0 }
|
||||
const hp_hybrid_disassembler::dis_entry_t hp_hybrid_disassembler::dis_table_common[] = {
|
||||
// *** BPC Instructions ***
|
||||
{0xffff , 0x0000 , "NOP" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0x7800 , 0x0000 , "LDA" , &hp_hybrid_disassembler::param_loc , 0 },
|
||||
{0x7800 , 0x0800 , "LDB" , &hp_hybrid_disassembler::param_loc , 0 },
|
||||
{0x7800 , 0x1000 , "CPA" , &hp_hybrid_disassembler::param_loc , 0 },
|
||||
{0x7800 , 0x1800 , "CPB" , &hp_hybrid_disassembler::param_loc , 0 },
|
||||
{0x7800 , 0x2000 , "ADA" , &hp_hybrid_disassembler::param_loc , 0 },
|
||||
{0x7800 , 0x2800 , "ADB" , &hp_hybrid_disassembler::param_loc , 0 },
|
||||
{0x7800 , 0x3000 , "STA" , &hp_hybrid_disassembler::param_loc , 0 },
|
||||
{0x7800 , 0x3800 , "STB" , &hp_hybrid_disassembler::param_loc , 0 },
|
||||
{0x7800 , 0x4000 , "JSM" , &hp_hybrid_disassembler::param_loc , STEP_OVER },
|
||||
{0x7800 , 0x4800 , "ISZ" , &hp_hybrid_disassembler::param_loc , 0 },
|
||||
{0x7800 , 0x5000 , "AND" , &hp_hybrid_disassembler::param_loc , 0 },
|
||||
{0x7800 , 0x5800 , "DSZ" , &hp_hybrid_disassembler::param_loc , 0 },
|
||||
{0x7800 , 0x6000 , "IOR" , &hp_hybrid_disassembler::param_loc , 0 },
|
||||
{0x7800 , 0x6800 , "JMP" , &hp_hybrid_disassembler::param_loc , 0 },
|
||||
{0x7fe0 , 0x7000 , "EXE" , &hp_hybrid_disassembler::param_addr32 , 0 },
|
||||
{0xffc0 , 0x7400 , "RZA" , &hp_hybrid_disassembler::param_skip , 0 },
|
||||
{0xffc0 , 0x7C00 , "RZB" , &hp_hybrid_disassembler::param_skip , 0 },
|
||||
{0xffc0 , 0x7440 , "RIA" , &hp_hybrid_disassembler::param_skip , 0 },
|
||||
{0xffc0 , 0x7C40 , "RIB" , &hp_hybrid_disassembler::param_skip , 0 },
|
||||
{0xffc0 , 0x74c0 , "SDS" , &hp_hybrid_disassembler::param_skip , 0 },
|
||||
{0xffc0 , 0x7500 , "SZA" , &hp_hybrid_disassembler::param_skip , 0 },
|
||||
{0xffc0 , 0x7D00 , "SZB" , &hp_hybrid_disassembler::param_skip , 0 },
|
||||
{0xffc0 , 0x7540 , "SIA" , &hp_hybrid_disassembler::param_skip , 0 },
|
||||
{0xffc0 , 0x7D40 , "SIB" , &hp_hybrid_disassembler::param_skip , 0 },
|
||||
{0xffc0 , 0x7480 , "SFS" , &hp_hybrid_disassembler::param_skip , 0 },
|
||||
{0xffc0 , 0x7580 , "SFC" , &hp_hybrid_disassembler::param_skip , 0 },
|
||||
{0xffc0 , 0x75c0 , "SDC" , &hp_hybrid_disassembler::param_skip , 0 },
|
||||
{0xffc0 , 0x7c80 , "SSS" , &hp_hybrid_disassembler::param_skip , 0 },
|
||||
{0xffc0 , 0x7d80 , "SSC" , &hp_hybrid_disassembler::param_skip , 0 },
|
||||
{0xffc0 , 0x7cc0 , "SHS" , &hp_hybrid_disassembler::param_skip , 0 },
|
||||
{0xffc0 , 0x7dc0 , "SHC" , &hp_hybrid_disassembler::param_skip , 0 },
|
||||
{0xff00 , 0x7600 , "SLA" , &hp_hybrid_disassembler::param_skip_sc , 0 },
|
||||
{0xff00 , 0x7e00 , "SLB" , &hp_hybrid_disassembler::param_skip_sc , 0 },
|
||||
{0xff00 , 0x7700 , "RLA" , &hp_hybrid_disassembler::param_skip_sc , 0 },
|
||||
{0xff00 , 0x7f00 , "RLB" , &hp_hybrid_disassembler::param_skip_sc , 0 },
|
||||
{0xff00 , 0xf400 , "SAP" , &hp_hybrid_disassembler::param_skip_sc , 0 },
|
||||
{0xff00 , 0xfc00 , "SBP" , &hp_hybrid_disassembler::param_skip_sc , 0 },
|
||||
{0xff00 , 0xf500 , "SAM" , &hp_hybrid_disassembler::param_skip_sc , 0 },
|
||||
{0xff00 , 0xfd00 , "SBM" , &hp_hybrid_disassembler::param_skip_sc , 0 },
|
||||
{0xff00 , 0xf600 , "SOC" , &hp_hybrid_disassembler::param_skip_sc , 0 },
|
||||
{0xff00 , 0xf700 , "SOS" , &hp_hybrid_disassembler::param_skip_sc , 0 },
|
||||
{0xff00 , 0xfe00 , "SEC" , &hp_hybrid_disassembler::param_skip_sc , 0 },
|
||||
{0xff00 , 0xff00 , "SES" , &hp_hybrid_disassembler::param_skip_sc , 0 },
|
||||
{0xffff , 0xf020 , "TCA" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xffff , 0xf820 , "TCB" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xffff , 0xf060 , "CMA" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xffff , 0xf860 , "CMB" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xff80 , 0xf080 , "RET" , &hp_hybrid_disassembler::param_ret , STEP_OUT },
|
||||
{0xfff0 , 0xf100 , "AAR" , &hp_hybrid_disassembler::param_n16 , 0 },
|
||||
{0xfff0 , 0xf900 , "ABR" , &hp_hybrid_disassembler::param_n16 , 0 },
|
||||
{0xffff , 0xf14f , "CLA" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xfff0 , 0xf140 , "SAR" , &hp_hybrid_disassembler::param_n16 , 0 },
|
||||
{0xffff , 0xf94f , "CLB" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xfff0 , 0xf940 , "SBR" , &hp_hybrid_disassembler::param_n16 , 0 },
|
||||
{0xfff0 , 0xf180 , "SAL" , &hp_hybrid_disassembler::param_n16 , 0 },
|
||||
{0xfff0 , 0xf980 , "SBL" , &hp_hybrid_disassembler::param_n16 , 0 },
|
||||
{0xfff0 , 0xf1c0 , "RAR" , &hp_hybrid_disassembler::param_n16 , 0 },
|
||||
{0xfff0 , 0xf9c0 , "RBR" , &hp_hybrid_disassembler::param_n16 , 0 },
|
||||
// *** IOC Instructions ***
|
||||
{0xffff , 0x7110 , "EIR" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7118 , "DIR" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7120 , "DMA" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7128 , "PCM" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7138 , "DDR" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xff78 , 0x7160 , "PWC" , &hp_hybrid_disassembler::param_reg_id , 0 },
|
||||
{0xff78 , 0x7168 , "PWD" , &hp_hybrid_disassembler::param_reg_id , 0 },
|
||||
{0xff78 , 0x7960 , "PBC" , &hp_hybrid_disassembler::param_reg_id , 0 },
|
||||
{0xff78 , 0x7968 , "PBD" , &hp_hybrid_disassembler::param_reg_id , 0 },
|
||||
{0xff78 , 0x7170 , "WWC" , &hp_hybrid_disassembler::param_reg_id , 0 },
|
||||
{0xff78 , 0x7178 , "WWD" , &hp_hybrid_disassembler::param_reg_id , 0 },
|
||||
{0xff78 , 0x7970 , "WBC" , &hp_hybrid_disassembler::param_reg_id , 0 },
|
||||
{0xff78 , 0x7978 , "WBD" , &hp_hybrid_disassembler::param_reg_id , 0 },
|
||||
// *** END ***
|
||||
{0 , 0 , nullptr , nullptr , 0 }
|
||||
};
|
||||
const hp_hybrid_disassembler::dis_entry_t hp_hybrid_disassembler::dis_table_ioc16[] = {
|
||||
// *** IOC-16 instructions ***
|
||||
{0xffff , 0x7100 , "SDO" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7108 , "SDI" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7140 , "DBL" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7148 , "CBL" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7150 , "DBU" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7158 , "CBU" , &hp_hybrid_disassembler::param_none , 0 },
|
||||
// *** END ***
|
||||
{0 , 0 , nullptr , nullptr , 0 }
|
||||
};
|
||||
const hp_hybrid_disassembler::dis_entry_t hp_hybrid_disassembler::dis_table_emc[] = {
|
||||
// *** EMC Instructions ***
|
||||
{0xffff , 0x7200 , "MWA" , &hp_5061_3001_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7220 , "CMY" , &hp_5061_3001_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7260 , "CMX" , &hp_5061_3001_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7280 , "FXA" , &hp_5061_3001_disassembler::param_none , 0 },
|
||||
{0xfff0 , 0x7300 , "XFR" , &hp_5061_3001_disassembler::param_n16 , 0 },
|
||||
{0xffff , 0x7340 , "NRM" , &hp_5061_3001_disassembler::param_none , 0 },
|
||||
{0xfff0 , 0x7380 , "CLR" , &hp_5061_3001_disassembler::param_n16 , 0 },
|
||||
{0xffff , 0x73c0 , "CDC" , &hp_5061_3001_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7a00 , "FMP" , &hp_5061_3001_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7a21 , "FDV" , &hp_5061_3001_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7b00 , "MRX" , &hp_5061_3001_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7b21 , "DRS" , &hp_5061_3001_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7b40 , "MRY" , &hp_5061_3001_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7b61 , "MLY" , &hp_5061_3001_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7b8f , "MPY" , &hp_5061_3001_disassembler::param_none , 0 },
|
||||
// *** END ***
|
||||
{0 , 0 , nullptr , nullptr , 0 }
|
||||
};
|
||||
const hp_hybrid_disassembler::dis_entry_t hp_hybrid_disassembler::dis_table_aec[] = {
|
||||
// *** Undocumented AEC instructions of 5061-3001 ***
|
||||
{0xffff , 0x7026 , "CIM" , &hp_5061_3001_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7027 , "SIM" , &hp_5061_3001_disassembler::param_none , 0 },
|
||||
// *** END ***
|
||||
{0 , 0 , nullptr , nullptr , 0 }
|
||||
};
|
||||
|
||||
const hp_hybrid_disassembler::dis_entry_t hp_5061_3001_disassembler::dis_table_emc[] = {
|
||||
// *** EMC Instructions ***
|
||||
{0xffff , 0x7200 , "MWA" , &hp_5061_3001_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7220 , "CMY" , &hp_5061_3001_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7260 , "CMX" , &hp_5061_3001_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7280 , "FXA" , &hp_5061_3001_disassembler::param_none , 0 },
|
||||
{0xfff0 , 0x7300 , "XFR" , &hp_5061_3001_disassembler::param_n16 , 0 },
|
||||
{0xffff , 0x7340 , "NRM" , &hp_5061_3001_disassembler::param_none , 0 },
|
||||
{0xfff0 , 0x7380 , "CLR" , &hp_5061_3001_disassembler::param_n16 , 0 },
|
||||
{0xffff , 0x73c0 , "CDC" , &hp_5061_3001_disassembler::param_none , 0 },
|
||||
{0xffc0 , 0x74c0 , "SDS" , &hp_5061_3001_disassembler::param_skip , 0 },
|
||||
{0xffc0 , 0x75c0 , "SDC" , &hp_5061_3001_disassembler::param_skip , 0 },
|
||||
{0xffff , 0x7a00 , "FMP" , &hp_5061_3001_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7a21 , "FDV" , &hp_5061_3001_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7b00 , "MRX" , &hp_5061_3001_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7b21 , "DRS" , &hp_5061_3001_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7b40 , "MRY" , &hp_5061_3001_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7b61 , "MLY" , &hp_5061_3001_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7b8f , "MPY" , &hp_5061_3001_disassembler::param_none , 0 },
|
||||
// *** Undocumented instructions of 5061-3001 ***
|
||||
{0xffff , 0x7026 , "CIM" , &hp_5061_3001_disassembler::param_none , 0 },
|
||||
{0xffff , 0x7027 , "SIM" , &hp_5061_3001_disassembler::param_none , 0 },
|
||||
// *** END ***
|
||||
{0 , 0 , nullptr , nullptr , 0 }
|
||||
};
|
||||
|
||||
offs_t hp_hybrid_disassembler::disassemble_table(uint16_t opcode , offs_t pc , const dis_entry_t *table , bool is_3001 , std::ostream &stream)
|
||||
offs_t hp_hybrid_disassembler::disassemble_table(uint16_t opcode , offs_t pc , const dis_entry_t *table , std::ostream &stream)
|
||||
{
|
||||
const dis_entry_t *p;
|
||||
|
||||
for (p = table; p->m_op_mask; p++) {
|
||||
if ((opcode & p->m_op_mask) == p->m_opcode) {
|
||||
stream << p->m_mnemonic << " ";
|
||||
(this->*(p->m_param_fn))(stream , pc , opcode , is_3001);
|
||||
(this->*(p->m_param_fn))(stream , pc , opcode);
|
||||
return 1 | p->m_dasm_flags | SUPPORTED;
|
||||
}
|
||||
}
|
||||
@ -366,10 +418,19 @@ offs_t hp_hybrid_disassembler::disassemble(std::ostream &stream, offs_t pc, cons
|
||||
uint16_t opcode = opcodes.r16(pc);
|
||||
offs_t res;
|
||||
|
||||
res = disassemble_table(opcode, pc, dis_table, false, stream);
|
||||
res = disassemble_table(opcode, pc, dis_table_common, stream);
|
||||
|
||||
if (res == 0)
|
||||
{
|
||||
if (res == 0 && (m_flags & HP_HYBRID_DASM_HAS_15BITS) == 0) {
|
||||
res = disassemble_table(opcode, pc, dis_table_ioc16, stream);
|
||||
}
|
||||
if (res == 0 && (m_flags & HP_HYBRID_DASM_HAS_EMC) != 0) {
|
||||
res = disassemble_table(opcode, pc, dis_table_emc, stream);
|
||||
}
|
||||
if (res == 0 && (m_flags & HP_HYBRID_DASM_HAS_AEC) != 0) {
|
||||
res = disassemble_table(opcode, pc, dis_table_aec, stream);
|
||||
}
|
||||
|
||||
if (res == 0) {
|
||||
// Unknown opcode
|
||||
stream << "???";
|
||||
res = 1 | SUPPORTED;
|
||||
@ -378,26 +439,28 @@ offs_t hp_hybrid_disassembler::disassemble(std::ostream &stream, offs_t pc, cons
|
||||
return res;
|
||||
}
|
||||
|
||||
offs_t hp_5061_3001_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms)
|
||||
hp_hybrid_disassembler::hp_hybrid_disassembler(unsigned flags)
|
||||
: m_flags(flags)
|
||||
{
|
||||
uint16_t opcode = opcodes.r16(pc);
|
||||
offs_t res;
|
||||
}
|
||||
|
||||
res = disassemble_table(opcode, pc, dis_table_emc, true, stream);
|
||||
hp_5061_3011_disassembler::hp_5061_3011_disassembler(bool relative_mode)
|
||||
: hp_hybrid_disassembler(relative_mode ? 0 : HP_HYBRID_DASM_ABS_MODE)
|
||||
{
|
||||
}
|
||||
|
||||
if (res == 0)
|
||||
{
|
||||
res = disassemble_table(opcode, pc, dis_table, true, stream);
|
||||
}
|
||||
hp_5061_3001_disassembler::hp_5061_3001_disassembler(bool relative_mode)
|
||||
: hp_hybrid_disassembler(HP_HYBRID_DASM_HAS_EMC |
|
||||
HP_HYBRID_DASM_HAS_AEC |
|
||||
(relative_mode ? 0 : HP_HYBRID_DASM_ABS_MODE))
|
||||
{
|
||||
}
|
||||
|
||||
if (res == 0)
|
||||
{
|
||||
// Unknown opcode
|
||||
stream << "???";
|
||||
res = 1 | SUPPORTED;
|
||||
}
|
||||
|
||||
return res;
|
||||
hp_09825_67907_disassembler::hp_09825_67907_disassembler(bool relative_mode)
|
||||
: hp_hybrid_disassembler(HP_HYBRID_DASM_HAS_15BITS |
|
||||
HP_HYBRID_DASM_HAS_EMC |
|
||||
(relative_mode ? 0 : HP_HYBRID_DASM_ABS_MODE))
|
||||
{
|
||||
}
|
||||
|
||||
u32 hp_hybrid_disassembler::opcode_alignment() const
|
||||
|
@ -9,17 +9,24 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
enum : unsigned {
|
||||
HP_HYBRID_DASM_HAS_15BITS = 1,
|
||||
HP_HYBRID_DASM_HAS_EMC = 2,
|
||||
HP_HYBRID_DASM_HAS_AEC = 4,
|
||||
HP_HYBRID_DASM_ABS_MODE = 8
|
||||
};
|
||||
|
||||
class hp_hybrid_disassembler : public util::disasm_interface
|
||||
{
|
||||
public:
|
||||
hp_hybrid_disassembler() = default;
|
||||
hp_hybrid_disassembler(unsigned flags);
|
||||
virtual ~hp_hybrid_disassembler() = default;
|
||||
|
||||
virtual u32 opcode_alignment() const override;
|
||||
virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) override;
|
||||
|
||||
protected:
|
||||
typedef void (hp_hybrid_disassembler::*fn_dis_param)(std::ostream &stream , offs_t pc , uint16_t opcode , bool is_3001);
|
||||
typedef void (hp_hybrid_disassembler::*fn_dis_param)(std::ostream &stream , offs_t pc , uint16_t opcode);
|
||||
|
||||
typedef struct {
|
||||
uint16_t m_op_mask;
|
||||
@ -29,31 +36,44 @@ protected:
|
||||
uint32_t m_dasm_flags;
|
||||
} dis_entry_t;
|
||||
|
||||
static const dis_entry_t dis_table[];
|
||||
unsigned m_flags;
|
||||
static const dis_entry_t dis_table_common[];
|
||||
static const dis_entry_t dis_table_ioc16[];
|
||||
static const dis_entry_t dis_table_emc[];
|
||||
static const dis_entry_t dis_table_aec[];
|
||||
|
||||
void addr_2_str(std::ostream &stream, uint16_t addr , bool indirect , bool is_3001);
|
||||
void param_none(std::ostream &stream, offs_t pc , uint16_t opcode , bool is_3001);
|
||||
void param_loc(std::ostream &stream, offs_t pc , uint16_t opcode , bool is_3001);
|
||||
void param_addr32(std::ostream &stream, offs_t pc , uint16_t opcode , bool is_3001);
|
||||
void param_skip(std::ostream &stream, offs_t pc , uint16_t opcode , bool is_3001);
|
||||
void param_skip_sc(std::ostream &stream, offs_t pc , uint16_t opcode , bool is_3001);
|
||||
void param_ret(std::ostream &stream, offs_t pc , uint16_t opcode , bool is_3001);
|
||||
void param_n16(std::ostream &stream, offs_t pc , uint16_t opcode , bool is_3001);
|
||||
void param_reg_id(std::ostream &stream, offs_t pc , uint16_t opcode , bool is_3001);
|
||||
void addr_2_str(std::ostream &stream, uint16_t addr , bool indirect);
|
||||
void param_none(std::ostream &stream, offs_t pc , uint16_t opcode);
|
||||
void param_loc(std::ostream &stream, offs_t pc , uint16_t opcode);
|
||||
void param_addr32(std::ostream &stream, offs_t pc , uint16_t opcode);
|
||||
void param_skip(std::ostream &stream, offs_t pc , uint16_t opcode);
|
||||
void param_skip_sc(std::ostream &stream, offs_t pc , uint16_t opcode);
|
||||
void param_ret(std::ostream &stream, offs_t pc , uint16_t opcode);
|
||||
void param_n16(std::ostream &stream, offs_t pc , uint16_t opcode);
|
||||
void param_reg_id(std::ostream &stream, offs_t pc , uint16_t opcode);
|
||||
|
||||
offs_t disassemble_table(uint16_t opcode , offs_t pc , const dis_entry_t *table , bool is_3001 , std::ostream &stream);
|
||||
offs_t disassemble_table(uint16_t opcode , offs_t pc , const dis_entry_t *table , std::ostream &stream);
|
||||
};
|
||||
|
||||
class hp_5061_3001_disassembler : public hp_hybrid_disassembler
|
||||
{
|
||||
public:
|
||||
hp_5061_3001_disassembler() = default;
|
||||
hp_5061_3001_disassembler(bool relative_mode = true);
|
||||
virtual ~hp_5061_3001_disassembler() = default;
|
||||
};
|
||||
|
||||
virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) override;
|
||||
class hp_5061_3011_disassembler : public hp_hybrid_disassembler
|
||||
{
|
||||
public:
|
||||
hp_5061_3011_disassembler(bool relative_mode = true);
|
||||
virtual ~hp_5061_3011_disassembler() = default;
|
||||
};
|
||||
|
||||
protected:
|
||||
static const dis_entry_t dis_table_emc[];
|
||||
class hp_09825_67907_disassembler : public hp_hybrid_disassembler
|
||||
{
|
||||
public:
|
||||
hp_09825_67907_disassembler(bool relative_mode = false);
|
||||
virtual ~hp_09825_67907_disassembler() = default;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -2,37 +2,36 @@
|
||||
#define MAME_CPU_HPHYBRID_HPHYBRID_DEFS_H
|
||||
|
||||
// Addresses of memory mapped registers
|
||||
#define HP_REG_A_ADDR 0x0000
|
||||
#define HP_REG_B_ADDR 0x0001
|
||||
#define HP_REG_P_ADDR 0x0002
|
||||
#define HP_REG_R_ADDR 0x0003
|
||||
#define HP_REG_R4_ADDR 0x0004
|
||||
#define HP_REG_R5_ADDR 0x0005
|
||||
#define HP_REG_R6_ADDR 0x0006
|
||||
#define HP_REG_R7_ADDR 0x0007
|
||||
#define HP_REG_IV_ADDR 0x0008
|
||||
#define HP_REG_PA_ADDR 0x0009
|
||||
#define HP_REG_W_ADDR 0x000A
|
||||
#define HP_REG_DMAPA_ADDR 0x000B
|
||||
#define HP_REG_DMAMA_ADDR 0x000C
|
||||
#define HP_REG_DMAC_ADDR 0x000D
|
||||
#define HP_REG_C_ADDR 0x000e
|
||||
#define HP_REG_D_ADDR 0x000f
|
||||
#define HP_REG_AR2_ADDR 0x0010
|
||||
#define HP_REG_SE_ADDR 0x0014
|
||||
#define HP_REG_R25_ADDR 0x0015
|
||||
#define HP_REG_R26_ADDR 0x0016
|
||||
#define HP_REG_R27_ADDR 0x0017
|
||||
#define HP_REG_R32_ADDR 0x001a
|
||||
#define HP_REG_R33_ADDR 0x001b
|
||||
#define HP_REG_R34_ADDR 0x001c
|
||||
#define HP_REG_R35_ADDR 0x001d
|
||||
#define HP_REG_R36_ADDR 0x001e
|
||||
#define HP_REG_R37_ADDR 0x001f
|
||||
#define HP_REG_LAST_ADDR 0x001f
|
||||
#define HP_REG_AR1_ADDR 0xfff8
|
||||
|
||||
#define HP_REG_IV_MASK 0xfff0
|
||||
#define HP_REG_PA_MASK 0x000f
|
||||
enum : uint16_t {
|
||||
HP_REG_A_ADDR = 0x0000,
|
||||
HP_REG_B_ADDR = 0x0001,
|
||||
HP_REG_P_ADDR = 0x0002,
|
||||
HP_REG_R_ADDR = 0x0003,
|
||||
HP_REG_R4_ADDR = 0x0004,
|
||||
HP_REG_R5_ADDR = 0x0005,
|
||||
HP_REG_R6_ADDR = 0x0006,
|
||||
HP_REG_R7_ADDR = 0x0007,
|
||||
HP_REG_IV_ADDR = 0x0008,
|
||||
HP_REG_PA_ADDR = 0x0009,
|
||||
HP_REG_W_ADDR = 0x000A,
|
||||
HP_REG_DMAPA_ADDR = 0x000B,
|
||||
HP_REG_DMAMA_ADDR = 0x000C,
|
||||
HP_REG_DMAC_ADDR = 0x000D,
|
||||
HP_REG_C_ADDR = 0x000e,
|
||||
HP_REG_D_ADDR = 0x000f,
|
||||
HP_REG_AR2_ADDR = 0x0010,
|
||||
HP_REG_SE_ADDR = 0x0014,
|
||||
HP_REG_R25_ADDR = 0x0015,
|
||||
HP_REG_R26_ADDR = 0x0016,
|
||||
HP_REG_R27_ADDR = 0x0017,
|
||||
HP_REG_R32_ADDR = 0x001a,
|
||||
HP_REG_R33_ADDR = 0x001b,
|
||||
HP_REG_R34_ADDR = 0x001c,
|
||||
HP_REG_R35_ADDR = 0x001d,
|
||||
HP_REG_R36_ADDR = 0x001e,
|
||||
HP_REG_R37_ADDR = 0x001f,
|
||||
HP_REG_LAST_ADDR = 0x001f,
|
||||
HP_REG_AR1_ADDR = 0xfff8
|
||||
};
|
||||
|
||||
#endif // MAME_CPU_HPHYBRID_HPHYBRID_DEFS_H
|
||||
|
@ -1375,11 +1375,12 @@ static void hp64k_floppies(device_slot_interface &device)
|
||||
}
|
||||
|
||||
MACHINE_CONFIG_START(hp64k_state::hp64k)
|
||||
MCFG_DEVICE_ADD("cpu" , HP_5061_3011 , 6250000)
|
||||
MCFG_DEVICE_PROGRAM_MAP(cpu_mem_map)
|
||||
MCFG_DEVICE_IO_MAP(cpu_io_map)
|
||||
MCFG_DEVICE_IRQ_ACKNOWLEDGE_DRIVER(hp64k_state , hp64k_irq_callback)
|
||||
MCFG_QUANTUM_TIME(attotime::from_hz(100))
|
||||
HP_5061_3011(config , m_cpu , 6250000);
|
||||
m_cpu->set_rw_cycles(6 , 6);
|
||||
m_cpu->set_relative_mode(true);
|
||||
m_cpu->set_addrmap(AS_PROGRAM , &hp64k_state::cpu_mem_map);
|
||||
m_cpu->set_addrmap(AS_IO , &hp64k_state::cpu_io_map);
|
||||
m_cpu->set_irq_acknowledge_callback(FUNC(hp64k_state::hp64k_irq_callback));
|
||||
|
||||
// Actual keyboard refresh rate should be between 1 and 2 kHz
|
||||
MCFG_TIMER_DRIVER_ADD_PERIODIC("kb_timer", hp64k_state, hp64k_kb_scan, attotime::from_hz(100))
|
||||
|
668
src/mame/drivers/hp9825.cpp
Normal file
668
src/mame/drivers/hp9825.cpp
Normal file
@ -0,0 +1,668 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:F. Ulivi
|
||||
|
||||
// **************************
|
||||
// Driver for HP 9825 systems
|
||||
// **************************
|
||||
//
|
||||
// **** Temporary header, will hopefully evolve into proper doc ****
|
||||
//
|
||||
// What's in:
|
||||
// - Emulation of 9825B system
|
||||
// - 12 kw of RAMs
|
||||
// - 12 kw of system ROM
|
||||
// - Keyboard (SHIFT LOCK & RESET not implemented)
|
||||
// - Display & run light
|
||||
// What's not yet in:
|
||||
// - Internal & external expansion ROMs
|
||||
// - Configurable RAM size
|
||||
// - Printer
|
||||
// - DC100 tape drive
|
||||
// - I/O expansion slots: 98034 & 98035 modules from hp9845 emulation can be used here, too
|
||||
// - Beeper
|
||||
//
|
||||
// 9825A & 9825T can also be emulated. At the moment I haven't all the necessary
|
||||
// ROM dumps, though.
|
||||
|
||||
#include "emu.h"
|
||||
#include "cpu/hphybrid/hphybrid.h"
|
||||
#include "machine/timer.h"
|
||||
#include "hp9825.lh"
|
||||
|
||||
// CPU clock (generated by a trimmered RC oscillator)
|
||||
constexpr unsigned MAIN_CLOCK = 6000000;
|
||||
|
||||
// KDP chip clock
|
||||
constexpr unsigned KDP_CLOCK = MAIN_CLOCK / 4;
|
||||
|
||||
// Bit manipulation
|
||||
namespace {
|
||||
template<typename T> constexpr T BIT_MASK(unsigned n)
|
||||
{
|
||||
return (T)1U << n;
|
||||
}
|
||||
|
||||
template<typename T> void BIT_CLR(T& w , unsigned n)
|
||||
{
|
||||
w &= ~BIT_MASK<T>(n);
|
||||
}
|
||||
|
||||
template<typename T> void BIT_SET(T& w , unsigned n)
|
||||
{
|
||||
w |= BIT_MASK<T>(n);
|
||||
}
|
||||
}
|
||||
|
||||
class hp9825_state : public driver_device
|
||||
{
|
||||
public:
|
||||
hp9825_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_cpu(*this , "cpu")
|
||||
, m_cursor_timer(*this , "cursor_timer")
|
||||
, m_io_key(*this , "KEY%u" , 0)
|
||||
, m_shift_key(*this , "KEY_SHIFT")
|
||||
, m_display(*this , "char_%u_%u" , 0U , 0U)
|
||||
, m_run_light(*this , "run_light")
|
||||
{
|
||||
}
|
||||
|
||||
void hp9825b(machine_config &config);
|
||||
|
||||
private:
|
||||
required_device<hp_09825_67907_cpu_device> m_cpu;
|
||||
required_device<timer_device> m_cursor_timer;
|
||||
required_ioport_array<4> m_io_key;
|
||||
required_ioport m_shift_key;
|
||||
output_finder<32 , 7> m_display;
|
||||
output_finder<> m_run_light;
|
||||
|
||||
bool m_display_on;
|
||||
uint8_t m_display_mem[ 32 ];
|
||||
uint8_t m_display_idx;
|
||||
bool m_rpl_cursor;
|
||||
bool m_cursor_blink;
|
||||
bool m_any_cursor;
|
||||
uint8_t m_scancode;
|
||||
bool m_key_pressed;
|
||||
bool m_autorepeating;
|
||||
unsigned m_autorepeat_cnt;
|
||||
uint8_t m_irl_pending;
|
||||
uint8_t m_irh_pending;
|
||||
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
|
||||
void cpu_io_map(address_map &map);
|
||||
void cpu_mem_map(address_map &map);
|
||||
|
||||
DECLARE_READ16_MEMBER(kb_scancode_r);
|
||||
DECLARE_WRITE16_MEMBER(disp_w);
|
||||
DECLARE_READ16_MEMBER(kdp_status_r);
|
||||
DECLARE_WRITE16_MEMBER(kdp_control_w);
|
||||
|
||||
void update_display();
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(cursor_blink);
|
||||
void kb_scan_ioport(ioport_value pressed , ioport_port &port , unsigned idx_base , int& max_seq_len , unsigned& max_seq_idx);
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(kb_scan);
|
||||
|
||||
IRQ_CALLBACK_MEMBER(irq_callback);
|
||||
void update_irq();
|
||||
void set_irq(uint8_t sc , int state);
|
||||
};
|
||||
|
||||
void hp9825_state::machine_start()
|
||||
{
|
||||
m_display.resolve();
|
||||
m_run_light.resolve();
|
||||
|
||||
save_item(NAME(m_display_on));
|
||||
save_item(NAME(m_display_mem));
|
||||
save_item(NAME(m_display_idx));
|
||||
save_item(NAME(m_scancode));
|
||||
save_item(NAME(m_irl_pending));
|
||||
save_item(NAME(m_irh_pending));
|
||||
}
|
||||
|
||||
void hp9825_state::machine_reset()
|
||||
{
|
||||
m_display_on = false;
|
||||
m_display_idx = 0;
|
||||
m_rpl_cursor = false;
|
||||
m_cursor_timer->reset();
|
||||
m_cursor_blink = true;
|
||||
update_display();
|
||||
m_scancode = 0;
|
||||
m_key_pressed = false;
|
||||
m_autorepeating = false;
|
||||
m_autorepeat_cnt = 0;
|
||||
m_irl_pending = 0;
|
||||
m_irh_pending = 0;
|
||||
update_irq();
|
||||
}
|
||||
|
||||
void hp9825_state::cpu_io_map(address_map &map)
|
||||
{
|
||||
map.unmap_value_low();
|
||||
map(HP_MAKE_IOADDR(0 , 0) , HP_MAKE_IOADDR(0 , 0)).rw(FUNC(hp9825_state::kb_scancode_r) , FUNC(hp9825_state::disp_w));
|
||||
map(HP_MAKE_IOADDR(0 , 1) , HP_MAKE_IOADDR(0 , 1)).rw(FUNC(hp9825_state::kdp_status_r) , FUNC(hp9825_state::kdp_control_w));
|
||||
// TODO:
|
||||
}
|
||||
|
||||
void hp9825_state::cpu_mem_map(address_map &map)
|
||||
{
|
||||
map.unmap_value_low();
|
||||
map(0x0000 , 0x2fff).rom();
|
||||
map(0x5000 , 0x7fff).ram();
|
||||
}
|
||||
|
||||
READ16_MEMBER(hp9825_state::kb_scancode_r)
|
||||
{
|
||||
// TODO:
|
||||
uint8_t res = m_scancode;
|
||||
if (m_shift_key->read()) {
|
||||
BIT_SET(res , 7);
|
||||
}
|
||||
set_irq(0 , false);
|
||||
return res;
|
||||
}
|
||||
|
||||
WRITE16_MEMBER(hp9825_state::disp_w)
|
||||
{
|
||||
// TODO:
|
||||
if (m_display_on) {
|
||||
m_display_on = false;
|
||||
m_cursor_timer->reset();
|
||||
m_cursor_blink = true;
|
||||
m_display_idx = 0;
|
||||
update_display();
|
||||
}
|
||||
m_display_mem[ m_display_idx++ ] = uint8_t(data);
|
||||
}
|
||||
|
||||
READ16_MEMBER(hp9825_state::kdp_status_r)
|
||||
{
|
||||
// TODO:
|
||||
return 8;
|
||||
}
|
||||
|
||||
WRITE16_MEMBER(hp9825_state::kdp_control_w)
|
||||
{
|
||||
// TODO:
|
||||
bool regen_display = false;
|
||||
if (BIT(data , 1) && !m_display_on) {
|
||||
m_display_on = true;
|
||||
// Cursor should blink at 2^-19 the KDP clock
|
||||
attotime cursor_half_period{ attotime::from_ticks(262144 , KDP_CLOCK) };
|
||||
m_cursor_timer->adjust(cursor_half_period , 0 , cursor_half_period);
|
||||
regen_display = true;
|
||||
}
|
||||
if (BIT(data , 6) && !m_rpl_cursor) {
|
||||
m_rpl_cursor = true;
|
||||
regen_display = true;
|
||||
}
|
||||
if (BIT(data , 5) && m_rpl_cursor) {
|
||||
m_rpl_cursor = false;
|
||||
regen_display = true;
|
||||
}
|
||||
if (BIT(data , 4)) {
|
||||
if (BIT(data , 3)) {
|
||||
m_run_light = !m_run_light;
|
||||
} else {
|
||||
m_run_light = false;
|
||||
}
|
||||
} else if (BIT(data , 3)) {
|
||||
m_run_light = true;
|
||||
}
|
||||
if (regen_display) {
|
||||
update_display();
|
||||
}
|
||||
}
|
||||
|
||||
// The character generator was reverse engineered from images of printer & display test patterns.
|
||||
// It is not guaranteed to be pixel-accurate though it looks quite close to the original.
|
||||
static const uint8_t chargen[ 128 ][ 5 ] = {
|
||||
{ 0x08,0x1c,0x3e,0x7f,0x00 }, // 00
|
||||
{ 0x30,0x48,0x45,0x40,0x30 }, // 01
|
||||
{ 0x45,0x29,0x11,0x29,0x45 }, // 02
|
||||
{ 0x7d,0x09,0x11,0x21,0x7d }, // 03
|
||||
{ 0x38,0x44,0x44,0x38,0x44 }, // 04
|
||||
{ 0x7c,0x2a,0x4a,0x4a,0x34 }, // 05
|
||||
{ 0x7f,0x01,0x01,0x01,0x03 }, // 06
|
||||
{ 0x7d,0x09,0x05,0x05,0x79 }, // 07
|
||||
{ 0x60,0x58,0x46,0x58,0x60 }, // 08
|
||||
{ 0x38,0x44,0x44,0x3c,0x04 }, // 09
|
||||
{ 0x10,0x20,0x7f,0x20,0x10 }, // 0a
|
||||
{ 0x62,0x14,0x08,0x10,0x60 }, // 0b
|
||||
{ 0x40,0x3c,0x20,0x20,0x1c }, // 0c
|
||||
{ 0x08,0x1c,0x2a,0x08,0x08 }, // 0d
|
||||
{ 0x10,0x08,0x78,0x08,0x04 }, // 0e
|
||||
{ 0x08,0x55,0x7f,0x55,0x08 }, // 0f
|
||||
{ 0x3e,0x49,0x49,0x49,0x3e }, // 10
|
||||
{ 0x5e,0x61,0x01,0x61,0x5e }, // 11
|
||||
{ 0x30,0x4a,0x4d,0x49,0x30 }, // 12
|
||||
{ 0x78,0x14,0x15,0x14,0x78 }, // 13
|
||||
{ 0x38,0x44,0x45,0x3c,0x40 }, // 14
|
||||
{ 0x78,0x15,0x14,0x15,0x78 }, // 15
|
||||
{ 0x38,0x45,0x44,0x3d,0x40 }, // 16
|
||||
{ 0x3c,0x43,0x42,0x43,0x3c }, // 17
|
||||
{ 0x38,0x45,0x44,0x45,0x38 }, // 18
|
||||
{ 0x3e,0x41,0x40,0x41,0x3e }, // 19
|
||||
{ 0x3c,0x41,0x40,0x41,0x3c }, // 1a
|
||||
{ 0x7e,0x09,0x7f,0x49,0x49 }, // 1b
|
||||
{ 0x38,0x44,0x38,0x54,0x58 }, // 1c
|
||||
{ 0x12,0x19,0x15,0x12,0x00 }, // 1d
|
||||
{ 0x48,0x7e,0x49,0x41,0x42 }, // 1e
|
||||
{ 0x55,0x2a,0x55,0x2a,0x55 }, // 1f
|
||||
{ 0x00,0x00,0x00,0x00,0x00 }, // 20
|
||||
{ 0x00,0x5f,0x00,0x00,0x00 }, // 21
|
||||
{ 0x00,0x03,0x00,0x03,0x00 }, // 22
|
||||
{ 0x14,0x7f,0x14,0x7f,0x14 }, // 23
|
||||
{ 0x24,0x2a,0x7f,0x2a,0x12 }, // 24
|
||||
{ 0x23,0x13,0x08,0x64,0x62 }, // 25
|
||||
{ 0x36,0x49,0x56,0x20,0x50 }, // 26
|
||||
{ 0x00,0x0b,0x07,0x00,0x00 }, // 27
|
||||
{ 0x00,0x00,0x3e,0x41,0x00 }, // 28
|
||||
{ 0x00,0x41,0x3e,0x00,0x00 }, // 29
|
||||
{ 0x08,0x2a,0x1c,0x2a,0x08 }, // 2a
|
||||
{ 0x08,0x08,0x3e,0x08,0x08 }, // 2b
|
||||
{ 0x00,0x58,0x38,0x00,0x00 }, // 2c
|
||||
{ 0x08,0x08,0x08,0x08,0x08 }, // 2d
|
||||
{ 0x00,0x60,0x60,0x00,0x00 }, // 2e
|
||||
{ 0x20,0x10,0x08,0x04,0x02 }, // 2f
|
||||
{ 0x3e,0x51,0x49,0x45,0x3e }, // 30
|
||||
{ 0x00,0x42,0x7f,0x40,0x00 }, // 31
|
||||
{ 0x62,0x51,0x49,0x49,0x46 }, // 32
|
||||
{ 0x22,0x41,0x49,0x49,0x36 }, // 33
|
||||
{ 0x18,0x14,0x12,0x7f,0x10 }, // 34
|
||||
{ 0x27,0x45,0x45,0x45,0x39 }, // 35
|
||||
{ 0x3c,0x4a,0x49,0x49,0x30 }, // 36
|
||||
{ 0x01,0x71,0x09,0x05,0x03 }, // 37
|
||||
{ 0x36,0x49,0x49,0x49,0x36 }, // 38
|
||||
{ 0x06,0x49,0x49,0x29,0x1e }, // 39
|
||||
{ 0x00,0x36,0x36,0x00,0x00 }, // 3a
|
||||
{ 0x00,0x5b,0x3b,0x00,0x00 }, // 3b
|
||||
{ 0x00,0x08,0x14,0x22,0x41 }, // 3c
|
||||
{ 0x14,0x14,0x14,0x14,0x14 }, // 3d
|
||||
{ 0x41,0x22,0x14,0x08,0x00 }, // 3e
|
||||
{ 0x06,0x01,0x51,0x09,0x06 }, // 3f
|
||||
{ 0x3e,0x41,0x5d,0x55,0x1e }, // 40
|
||||
{ 0x7e,0x09,0x09,0x09,0x7e }, // 41
|
||||
{ 0x7f,0x49,0x49,0x49,0x36 }, // 42
|
||||
{ 0x3e,0x41,0x41,0x41,0x22 }, // 43
|
||||
{ 0x7f,0x41,0x41,0x41,0x3e }, // 44
|
||||
{ 0x7f,0x49,0x49,0x49,0x41 }, // 45
|
||||
{ 0x7f,0x09,0x09,0x09,0x01 }, // 46
|
||||
{ 0x3e,0x41,0x41,0x51,0x72 }, // 47
|
||||
{ 0x7f,0x08,0x08,0x08,0x7f }, // 48
|
||||
{ 0x00,0x41,0x7f,0x41,0x00 }, // 49
|
||||
{ 0x20,0x40,0x40,0x40,0x3f }, // 4a
|
||||
{ 0x7f,0x08,0x14,0x22,0x41 }, // 4b
|
||||
{ 0x7f,0x40,0x40,0x40,0x40 }, // 4c
|
||||
{ 0x7f,0x02,0x0c,0x02,0x7f }, // 4d
|
||||
{ 0x7f,0x04,0x08,0x10,0x7f }, // 4e
|
||||
{ 0x3e,0x41,0x41,0x41,0x3e }, // 4f
|
||||
{ 0x7f,0x09,0x09,0x09,0x06 }, // 50
|
||||
{ 0x3e,0x41,0x51,0x21,0x5e }, // 51
|
||||
{ 0x7f,0x09,0x19,0x29,0x46 }, // 52
|
||||
{ 0x26,0x49,0x49,0x49,0x32 }, // 53
|
||||
{ 0x01,0x01,0x7f,0x01,0x01 }, // 54
|
||||
{ 0x3f,0x40,0x40,0x40,0x3f }, // 55
|
||||
{ 0x07,0x18,0x60,0x18,0x07 }, // 56
|
||||
{ 0x7f,0x20,0x10,0x20,0x7f }, // 57
|
||||
{ 0x63,0x14,0x08,0x14,0x63 }, // 58
|
||||
{ 0x03,0x04,0x78,0x04,0x03 }, // 59
|
||||
{ 0x61,0x51,0x49,0x45,0x43 }, // 5a
|
||||
{ 0x00,0x00,0x7f,0x41,0x41 }, // 5b
|
||||
{ 0x20,0x7f,0x01,0x01,0x01 }, // 5c
|
||||
{ 0x41,0x41,0x7f,0x00,0x00 }, // 5d
|
||||
{ 0x04,0x02,0x7f,0x02,0x04 }, // 5e
|
||||
{ 0x40,0x40,0x40,0x40,0x40 }, // 5f
|
||||
{ 0x00,0x07,0x0b,0x00,0x00 }, // 60
|
||||
{ 0x38,0x44,0x44,0x3c,0x40 }, // 61
|
||||
{ 0x7f,0x48,0x44,0x44,0x38 }, // 62
|
||||
{ 0x38,0x44,0x44,0x44,0x20 }, // 63
|
||||
{ 0x38,0x44,0x44,0x48,0x7f }, // 64
|
||||
{ 0x38,0x54,0x54,0x54,0x08 }, // 65
|
||||
{ 0x08,0x7e,0x09,0x02,0x00 }, // 66
|
||||
{ 0x08,0x14,0x54,0x54,0x3c }, // 67
|
||||
{ 0x7f,0x08,0x04,0x04,0x78 }, // 68
|
||||
{ 0x00,0x44,0x7d,0x40,0x00 }, // 69
|
||||
{ 0x20,0x40,0x44,0x3d,0x00 }, // 6a
|
||||
{ 0x7f,0x10,0x28,0x44,0x00 }, // 6b
|
||||
{ 0x00,0x41,0x7f,0x40,0x00 }, // 6c
|
||||
{ 0x78,0x04,0x18,0x04,0x78 }, // 6d
|
||||
{ 0x7c,0x08,0x04,0x04,0x78 }, // 6e
|
||||
{ 0x38,0x44,0x44,0x44,0x38 }, // 6f
|
||||
{ 0x7c,0x14,0x24,0x24,0x18 }, // 70
|
||||
{ 0x18,0x24,0x14,0x7c,0x40 }, // 71
|
||||
{ 0x7c,0x08,0x04,0x04,0x00 }, // 72
|
||||
{ 0x48,0x54,0x54,0x54,0x20 }, // 73
|
||||
{ 0x04,0x3e,0x44,0x20,0x00 }, // 74
|
||||
{ 0x3c,0x40,0x40,0x20,0x7c }, // 75
|
||||
{ 0x1c,0x20,0x40,0x20,0x1c }, // 76
|
||||
{ 0x3c,0x40,0x30,0x40,0x3c }, // 77
|
||||
{ 0x44,0x28,0x10,0x28,0x44 }, // 78
|
||||
{ 0x04,0x48,0x30,0x08,0x04 }, // 79
|
||||
{ 0x44,0x64,0x54,0x4c,0x44 }, // 7a
|
||||
{ 0x08,0x7c,0x04,0x7c,0x02 }, // 7b
|
||||
{ 0x00,0x00,0x7f,0x00,0x00 }, // 7c
|
||||
{ 0x08,0x08,0x2a,0x1c,0x08 }, // 7d
|
||||
{ 0x41,0x63,0x55,0x49,0x63 }, // 7e
|
||||
{ 0x7f,0x08,0x08,0x08,0x08 } // 7f
|
||||
};
|
||||
|
||||
void hp9825_state::update_display()
|
||||
{
|
||||
m_any_cursor = false;
|
||||
for (unsigned i = 0; i < 32; ++i) {
|
||||
bool cursor_here = BIT(m_display_mem[ i ] , 7);
|
||||
if (cursor_here) {
|
||||
m_any_cursor = true;
|
||||
}
|
||||
bool show_cursor = m_cursor_blink && cursor_here;
|
||||
uint8_t char_code = m_display_mem[ i ] & 0x7f;
|
||||
for (unsigned j = 0; j < 7; ++j) {
|
||||
uint8_t five_dots = 0;
|
||||
if (m_display_on) {
|
||||
for (unsigned col = 0; col < 5; col++) {
|
||||
uint8_t char_col;
|
||||
if (show_cursor) {
|
||||
if (m_rpl_cursor) {
|
||||
// Replace cursor: all pixels lit
|
||||
char_col = ~0;
|
||||
} else {
|
||||
// Insert cursor: character code 0
|
||||
char_col = chargen[ 0 ][ col ];
|
||||
}
|
||||
} else {
|
||||
char_col = chargen[ char_code ][ col ];
|
||||
}
|
||||
if (BIT(char_col , j)) {
|
||||
BIT_SET(five_dots , col);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_display[ i ][ j ] = five_dots;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(hp9825_state::cursor_blink)
|
||||
{
|
||||
m_cursor_blink = !m_cursor_blink;
|
||||
if (m_any_cursor) {
|
||||
update_display();
|
||||
}
|
||||
}
|
||||
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(hp9825_state::kb_scan)
|
||||
{
|
||||
ioport_value input[ 4 ]
|
||||
{ m_io_key[ 0 ]->read(),
|
||||
m_io_key[ 1 ]->read(),
|
||||
m_io_key[ 2 ]->read(),
|
||||
m_io_key[ 3 ]->read()
|
||||
};
|
||||
|
||||
if (m_key_pressed) {
|
||||
// Still pressed ?
|
||||
m_key_pressed = BIT(input[ m_scancode / 32 ] , m_scancode % 32);
|
||||
} else {
|
||||
int max_seq_len = 0;
|
||||
unsigned max_seq_idx = 0;
|
||||
for (unsigned i = 0; i < 4; i++) {
|
||||
kb_scan_ioport(input[ i ] , *m_io_key[ i ] , i << 5 , max_seq_len , max_seq_idx);
|
||||
}
|
||||
if (max_seq_len) {
|
||||
m_scancode = max_seq_idx;
|
||||
m_key_pressed = true;
|
||||
set_irq(0 , true);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_key_pressed) {
|
||||
auto prev_cnt = m_autorepeat_cnt;
|
||||
m_autorepeat_cnt++;
|
||||
// Auto-repeat initial delay & frequency are entirely guessed..
|
||||
if (BIT(m_autorepeat_cnt , 5)) {
|
||||
// Initial delay passed
|
||||
m_autorepeating = true;
|
||||
}
|
||||
if (m_autorepeating && BIT(~prev_cnt & m_autorepeat_cnt , 3)) {
|
||||
// Repeat key every time bit 3 of autorepeat counter goes 0->1
|
||||
set_irq(0 , true);
|
||||
}
|
||||
} else {
|
||||
m_autorepeating = false;
|
||||
m_autorepeat_cnt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void hp9825_state::kb_scan_ioport(ioport_value pressed , ioport_port &port , unsigned idx_base , int& max_seq_len , unsigned& max_seq_idx)
|
||||
{
|
||||
while (pressed) {
|
||||
unsigned bit_no = 31 - count_leading_zeros(pressed);
|
||||
ioport_value mask = BIT_MASK<ioport_value>(bit_no);
|
||||
int seq_len = port.field(mask)->seq().length();
|
||||
if (seq_len > max_seq_len) {
|
||||
max_seq_len = seq_len;
|
||||
max_seq_idx = bit_no + idx_base;
|
||||
}
|
||||
pressed &= ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
IRQ_CALLBACK_MEMBER(hp9825_state::irq_callback)
|
||||
{
|
||||
if (irqline == HPHYBRID_IRL) {
|
||||
return m_irl_pending;
|
||||
} else {
|
||||
return m_irh_pending;
|
||||
}
|
||||
}
|
||||
|
||||
void hp9825_state::update_irq()
|
||||
{
|
||||
m_cpu->set_input_line(HPHYBRID_IRL , m_irl_pending != 0);
|
||||
m_cpu->set_input_line(HPHYBRID_IRH , m_irh_pending != 0);
|
||||
}
|
||||
|
||||
void hp9825_state::set_irq(uint8_t sc , int state)
|
||||
{
|
||||
unsigned bit_n = sc % 8;
|
||||
|
||||
if (sc < 8) {
|
||||
if (state) {
|
||||
BIT_SET(m_irl_pending, bit_n);
|
||||
} else {
|
||||
BIT_CLR(m_irl_pending, bit_n);
|
||||
}
|
||||
} else {
|
||||
if (state) {
|
||||
BIT_SET(m_irh_pending, bit_n);
|
||||
} else {
|
||||
BIT_CLR(m_irh_pending, bit_n);
|
||||
}
|
||||
}
|
||||
update_irq();
|
||||
}
|
||||
|
||||
MACHINE_CONFIG_START(hp9825_state::hp9825b)
|
||||
HP_09825_67907(config , m_cpu , MAIN_CLOCK);
|
||||
// Just guessing... settings borrowed from hp9845
|
||||
m_cpu->set_rw_cycles(6 , 6);
|
||||
m_cpu->set_relative_mode(false);
|
||||
m_cpu->set_addrmap(AS_PROGRAM , &hp9825_state::cpu_mem_map);
|
||||
m_cpu->set_addrmap(AS_IO , &hp9825_state::cpu_io_map);
|
||||
m_cpu->set_irq_acknowledge_callback(FUNC(hp9825_state::irq_callback));
|
||||
|
||||
TIMER(config , m_cursor_timer , 0).configure_generic(timer_device::expired_delegate(FUNC(hp9825_state::cursor_blink) , this));
|
||||
|
||||
// Keyboard scan timer. A scan of the whole keyboard should take 2^14 KDP clocks.
|
||||
TIMER(config , "kb_timer" , 0).configure_periodic(timer_device::expired_delegate(FUNC(hp9825_state::kb_scan) , this) , attotime::from_ticks(16384 , KDP_CLOCK));
|
||||
|
||||
config.set_default_layout(layout_hp9825);
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
#define IOP_MASK(x) BIT_MASK<ioport_value>((x))
|
||||
|
||||
static INPUT_PORTS_START(hp9825)
|
||||
// Keyboard is arranged in a 8 x 16 matrix. Of the 128 possible positions, 102 are used.
|
||||
// Keys are mapped on bit b of KEYn
|
||||
// where b = (row & 1) << 4 + column, n = row >> 1
|
||||
// column = [0..15]
|
||||
// row = [0..7]
|
||||
// 4 more keys are not in the matrix: 2 SHIFTs, 1 SHIFT LOCK and RESET key.
|
||||
// Fun fact: alphanumeric keys are arranged in the matrix so that their scancode (row/column number)
|
||||
// equals the lower case ASCII code. The person in charge of routing the keyboard PCB
|
||||
// must have loved this arrangement...
|
||||
PORT_START("KEY0")
|
||||
PORT_BIT(IOP_MASK(0) , IP_ACTIVE_HIGH , IPT_UNUSED) // 0,0: N/U
|
||||
PORT_BIT(IOP_MASK(1) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC)) PORT_NAME("Stop") // 0,1: Stop
|
||||
PORT_BIT(IOP_MASK(2) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Rewind") // 0,2: Rewind
|
||||
PORT_BIT(IOP_MASK(3) , IP_ACTIVE_HIGH , IPT_UNUSED) // 0,3: N/U
|
||||
PORT_BIT(IOP_MASK(4) , IP_ACTIVE_HIGH , IPT_UNUSED) // 0,4: N/U
|
||||
PORT_BIT(IOP_MASK(5) , IP_ACTIVE_HIGH , IPT_UNUSED) // 0,5: N/U
|
||||
PORT_BIT(IOP_MASK(6) , IP_ACTIVE_HIGH , IPT_UNUSED) // 0,6: N/U
|
||||
PORT_BIT(IOP_MASK(7) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Result") // 0,7: Result
|
||||
PORT_BIT(IOP_MASK(8) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Line insert") // 0,8: Line insert
|
||||
PORT_BIT(IOP_MASK(9) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Line delete") // 0,9: Line delete
|
||||
PORT_BIT(IOP_MASK(10) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) PORT_NAME("Execute") // 0,10: Execute
|
||||
PORT_BIT(IOP_MASK(11) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Line recall") // 0,11: Line recall
|
||||
PORT_BIT(IOP_MASK(12) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Run") // 0,12: Run
|
||||
PORT_BIT(IOP_MASK(13) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Store") // 0,13: Store
|
||||
PORT_BIT(IOP_MASK(14) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Display left") // 0,14: Display left
|
||||
PORT_BIT(IOP_MASK(15) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Display right") // 0,15: Display right
|
||||
PORT_BIT(IOP_MASK(16) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) PORT_NAME("Display down") // 1,0: Display down
|
||||
PORT_BIT(IOP_MASK(17) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) PORT_NAME("Display up") // 1,1: Display up
|
||||
PORT_BIT(IOP_MASK(18) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_HOME) PORT_NAME("Clear") // 1,2: Clear
|
||||
PORT_BIT(IOP_MASK(19) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Print all") // 1,3: Print all
|
||||
PORT_BIT(IOP_MASK(20) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_LEFT) PORT_NAME("Char back") // 1,4: Char back
|
||||
PORT_BIT(IOP_MASK(21) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_RIGHT) PORT_NAME("Char forward") // 1,5: Char forward
|
||||
PORT_BIT(IOP_MASK(22) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_INSERT) PORT_NAME("Char ins/rpl") // 1,6: Char ins/rpl
|
||||
PORT_BIT(IOP_MASK(23) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_DEL) PORT_NAME("Char delete") // 1,7: Char delete
|
||||
PORT_BIT(IOP_MASK(24) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Step") // 1,8: Step
|
||||
PORT_BIT(IOP_MASK(25) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_NAME("Continue") PORT_CHAR(13) // 1,9: Continue
|
||||
PORT_BIT(IOP_MASK(26) , IP_ACTIVE_HIGH , IPT_UNUSED) // 1,10: N/U
|
||||
PORT_BIT(IOP_MASK(27) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("List") // 1,11: List
|
||||
PORT_BIT(IOP_MASK(28) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Line fetch") // 1,12: Line fetch
|
||||
PORT_BIT(IOP_MASK(29) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Erase") // 1,13: Erase
|
||||
PORT_BIT(IOP_MASK(30) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Record") // 1,14: Record
|
||||
PORT_BIT(IOP_MASK(31) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Load") // 1,15: Load
|
||||
|
||||
PORT_START("KEY1")
|
||||
PORT_BIT(IOP_MASK(0) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') // 2,0: Space
|
||||
PORT_BIT(IOP_MASK(1) , IP_ACTIVE_HIGH , IPT_UNUSED) // 2,1: N/U
|
||||
PORT_BIT(IOP_MASK(2) , IP_ACTIVE_HIGH , IPT_UNUSED) // 2,2: N/U
|
||||
PORT_BIT(IOP_MASK(3) , IP_ACTIVE_HIGH , IPT_UNUSED) // 2,3: N/U
|
||||
PORT_BIT(IOP_MASK(4) , IP_ACTIVE_HIGH , IPT_UNUSED) // 2,4: N/U
|
||||
PORT_BIT(IOP_MASK(5) , IP_ACTIVE_HIGH , IPT_UNUSED) // 2,5: N/U
|
||||
PORT_BIT(IOP_MASK(6) , IP_ACTIVE_HIGH , IPT_UNUSED) // 2,6: N/U
|
||||
PORT_BIT(IOP_MASK(7) , IP_ACTIVE_HIGH , IPT_UNUSED) // 2,7: N/U
|
||||
PORT_BIT(IOP_MASK(8) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('(') PORT_NAME("Keypad (") // 2,8: KP (
|
||||
PORT_BIT(IOP_MASK(9) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(')') PORT_NAME("Keypad )") // 2,9: KP )
|
||||
PORT_BIT(IOP_MASK(10) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_ASTERISK) PORT_CHAR(UCHAR_MAMEKEY(ASTERISK)) // 2,10: KP *
|
||||
PORT_BIT(IOP_MASK(11) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(PLUS_PAD)) // 2,11: KP +
|
||||
PORT_BIT(IOP_MASK(12) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') // 2,12: ,
|
||||
PORT_BIT(IOP_MASK(13) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS_PAD) PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD)) // 2,13: KP -
|
||||
PORT_BIT(IOP_MASK(14) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') // 2,14: .
|
||||
PORT_BIT(IOP_MASK(15) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH_PAD) PORT_CHAR(UCHAR_MAMEKEY(SLASH_PAD)) // 2,15: KP /
|
||||
PORT_BIT(IOP_MASK(16) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') PORT_CHAR('\'') // 3,0: 0
|
||||
PORT_BIT(IOP_MASK(17) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') // 3,1: 1
|
||||
PORT_BIT(IOP_MASK(18) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') // 3,2: 2
|
||||
PORT_BIT(IOP_MASK(19) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') // 3,3: 3
|
||||
PORT_BIT(IOP_MASK(20) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') // 3,4: 4
|
||||
PORT_BIT(IOP_MASK(21) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') // 3,5: 5
|
||||
PORT_BIT(IOP_MASK(22) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') // 3,6: 6
|
||||
PORT_BIT(IOP_MASK(23) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('@') // 3,7: 7
|
||||
PORT_BIT(IOP_MASK(24) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('[') // 3,8: 8
|
||||
PORT_BIT(IOP_MASK(25) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(']') // 3,9: 9
|
||||
PORT_BIT(IOP_MASK(26) , IP_ACTIVE_HIGH , IPT_UNUSED) // 3,10: N/U
|
||||
PORT_BIT(IOP_MASK(27) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') // 3,11: ;
|
||||
PORT_BIT(IOP_MASK(28) , IP_ACTIVE_HIGH , IPT_UNUSED) // 3,12: N/U
|
||||
PORT_BIT(IOP_MASK(29) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS_PAD) PORT_CHAR(UCHAR_MAMEKEY(EQUALS_PAD)) // 3,13: =
|
||||
PORT_BIT(IOP_MASK(30) , IP_ACTIVE_HIGH , IPT_UNUSED) // 3,14: N/U
|
||||
PORT_BIT(IOP_MASK(31) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('?') PORT_CHAR(':') // 3,15: ?
|
||||
|
||||
PORT_START("KEY2")
|
||||
PORT_BIT(IOP_MASK(0) , IP_ACTIVE_HIGH , IPT_UNUSED) // 4,0: N/U
|
||||
PORT_BIT(IOP_MASK(1) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("f0") // 4,1: f0
|
||||
PORT_BIT(IOP_MASK(2) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1)) PORT_NAME("f1") // 4,2: f1
|
||||
PORT_BIT(IOP_MASK(3) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2)) PORT_NAME("f2") // 4,3: f2
|
||||
PORT_BIT(IOP_MASK(4) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3)) PORT_NAME("f3") // 4,4: f3
|
||||
PORT_BIT(IOP_MASK(5) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4)) PORT_NAME("f4") // 4,5: f4
|
||||
PORT_BIT(IOP_MASK(6) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5)) PORT_NAME("f5") // 4,6: f5
|
||||
PORT_BIT(IOP_MASK(7) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6)) PORT_NAME("f6") // 4,7: f6
|
||||
PORT_BIT(IOP_MASK(8) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7)) PORT_NAME("f7") // 4,8: f7
|
||||
PORT_BIT(IOP_MASK(9) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8)) PORT_NAME("f8") // 4,9: f8
|
||||
PORT_BIT(IOP_MASK(10) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F9) PORT_CHAR(UCHAR_MAMEKEY(F9)) PORT_NAME("f9") // 4,10: f9
|
||||
PORT_BIT(IOP_MASK(11) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F10) PORT_CHAR(UCHAR_MAMEKEY(F10)) PORT_NAME("f10") // 4,11: f10
|
||||
PORT_BIT(IOP_MASK(12) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F11) PORT_CHAR(UCHAR_MAMEKEY(F11)) PORT_NAME("f11") // 4,12: f11
|
||||
PORT_BIT(IOP_MASK(13) , IP_ACTIVE_HIGH , IPT_UNUSED) // 4,13: N/U
|
||||
PORT_BIT(IOP_MASK(14) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_0_PAD) PORT_CHAR(UCHAR_MAMEKEY(0_PAD)) // 4,14: KP 0
|
||||
PORT_BIT(IOP_MASK(15) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_1_PAD) PORT_CHAR(UCHAR_MAMEKEY(1_PAD)) // 4,15: KP 1
|
||||
PORT_BIT(IOP_MASK(16) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_2_PAD) PORT_CHAR(UCHAR_MAMEKEY(2_PAD)) // 5,0: KP 2
|
||||
PORT_BIT(IOP_MASK(17) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_3_PAD) PORT_CHAR(UCHAR_MAMEKEY(3_PAD)) // 5,1: KP 3
|
||||
PORT_BIT(IOP_MASK(18) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_4_PAD) PORT_CHAR(UCHAR_MAMEKEY(4_PAD)) // 5,2: KP 4
|
||||
PORT_BIT(IOP_MASK(19) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_5_PAD) PORT_CHAR(UCHAR_MAMEKEY(5_PAD)) // 5,3: KP 5
|
||||
PORT_BIT(IOP_MASK(20) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_6_PAD) PORT_CHAR(UCHAR_MAMEKEY(6_PAD)) // 5,4: KP 6
|
||||
PORT_BIT(IOP_MASK(21) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_7_PAD) PORT_CHAR(UCHAR_MAMEKEY(7_PAD)) // 5,5: KP 7
|
||||
PORT_BIT(IOP_MASK(22) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_8_PAD) PORT_CHAR(UCHAR_MAMEKEY(8_PAD)) // 5,6: KP 8
|
||||
PORT_BIT(IOP_MASK(23) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_9_PAD) PORT_CHAR(UCHAR_MAMEKEY(9_PAD)) // 5,7: KP 9
|
||||
PORT_BIT(IOP_MASK(24) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) // 5,8: KP .
|
||||
PORT_BIT(IOP_MASK(25) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA_PAD) PORT_CHAR(UCHAR_MAMEKEY(COMMA_PAD)) // 5,9: KP ,
|
||||
PORT_BIT(IOP_MASK(26) , IP_ACTIVE_HIGH , IPT_UNUSED) // 5,10: N/U
|
||||
PORT_BIT(IOP_MASK(27) , IP_ACTIVE_HIGH , IPT_UNUSED) // 5,11: N/U
|
||||
PORT_BIT(IOP_MASK(28) , IP_ACTIVE_HIGH , IPT_UNUSED) // 5,12: N/U
|
||||
PORT_BIT(IOP_MASK(29) , IP_ACTIVE_HIGH , IPT_UNUSED) // 5,13: N/U
|
||||
PORT_BIT(IOP_MASK(30) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_NAME("↑ √") // 5,14: ^
|
||||
PORT_BIT(IOP_MASK(31) , IP_ACTIVE_HIGH , IPT_UNUSED) // 5,15: N/U
|
||||
|
||||
PORT_START("KEY3")
|
||||
PORT_BIT(IOP_MASK(0) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("Enter exp _") // 6,0: Enter exp
|
||||
PORT_BIT(IOP_MASK(1) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') // 6,1: A
|
||||
PORT_BIT(IOP_MASK(2) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') // 6,2: B
|
||||
PORT_BIT(IOP_MASK(3) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') // 6,3: C
|
||||
PORT_BIT(IOP_MASK(4) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') // 6,4: D
|
||||
PORT_BIT(IOP_MASK(5) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') // 6,5: E
|
||||
PORT_BIT(IOP_MASK(6) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') // 6,6: F
|
||||
PORT_BIT(IOP_MASK(7) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') // 6,7: G
|
||||
PORT_BIT(IOP_MASK(8) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') // 6,8: H
|
||||
PORT_BIT(IOP_MASK(9) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') // 6,9: I
|
||||
PORT_BIT(IOP_MASK(10) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') // 6,10: J
|
||||
PORT_BIT(IOP_MASK(11) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') // 6,11: K
|
||||
PORT_BIT(IOP_MASK(12) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') // 6,12: L
|
||||
PORT_BIT(IOP_MASK(13) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') // 6,13: M
|
||||
PORT_BIT(IOP_MASK(14) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') // 6,14: N
|
||||
PORT_BIT(IOP_MASK(15) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') // 6,15: O
|
||||
PORT_BIT(IOP_MASK(16) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') // 7,0: P
|
||||
PORT_BIT(IOP_MASK(17) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') // 7,1: Q
|
||||
PORT_BIT(IOP_MASK(18) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') // 7,2: R
|
||||
PORT_BIT(IOP_MASK(19) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') // 7,3: S
|
||||
PORT_BIT(IOP_MASK(20) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') // 7,4: T
|
||||
PORT_BIT(IOP_MASK(21) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') // 7,5: U
|
||||
PORT_BIT(IOP_MASK(22) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') // 7,6: V
|
||||
PORT_BIT(IOP_MASK(23) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') // 7,7: W
|
||||
PORT_BIT(IOP_MASK(24) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') // 7,8: X
|
||||
PORT_BIT(IOP_MASK(25) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') // 7,9: Y
|
||||
PORT_BIT(IOP_MASK(26) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') // 7,10: Z
|
||||
PORT_BIT(IOP_MASK(27) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_NAME("π |") // 7,11: Pi
|
||||
PORT_BIT(IOP_MASK(28) , IP_ACTIVE_HIGH , IPT_UNUSED) // 7,12: N/U
|
||||
PORT_BIT(IOP_MASK(29) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_END) PORT_NAME("→") // 7,13: Gazinta
|
||||
PORT_BIT(IOP_MASK(30) , IP_ACTIVE_HIGH , IPT_UNUSED) // 7,14: N/U
|
||||
PORT_BIT(IOP_MASK(31) , IP_ACTIVE_HIGH , IPT_UNUSED) // 7,15: N/U
|
||||
|
||||
PORT_START("KEY_SHIFT")
|
||||
PORT_BIT(IOP_MASK(0) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1) // Shift
|
||||
INPUT_PORTS_END
|
||||
|
||||
ROM_START(hp9825b)
|
||||
ROM_REGION(0x6000 , "cpu" , ROMREGION_16BIT | ROMREGION_BE)
|
||||
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_END
|
||||
|
||||
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
|
||||
COMP(1980, hp9825b, 0, 0, hp9825b, hp9825, hp9825_state, empty_init, "Hewlett-Packard", "HP 9825B", MACHINE_NO_SOUND)
|
@ -3737,15 +3737,19 @@ void hp9845_base_state::ppu_io_map(address_map &map)
|
||||
}
|
||||
|
||||
MACHINE_CONFIG_START(hp9845_base_state::hp9845_base)
|
||||
MCFG_DEVICE_ADD("lpu", HP_5061_3001, 5700000)
|
||||
MCFG_DEVICE_PROGRAM_MAP(global_mem_map)
|
||||
MCFG_HPHYBRID_SET_9845_BOOT(true)
|
||||
MCFG_DEVICE_ADD("ppu", HP_5061_3001, 5700000)
|
||||
MCFG_DEVICE_PROGRAM_MAP(global_mem_map)
|
||||
MCFG_DEVICE_IO_MAP(ppu_io_map)
|
||||
MCFG_HPHYBRID_SET_9845_BOOT(true)
|
||||
MCFG_DEVICE_IRQ_ACKNOWLEDGE_DRIVER(hp9845_base_state , irq_callback)
|
||||
MCFG_HPHYBRID_PA_CHANGED(WRITE8(*this, hp9845_base_state , pa_w))
|
||||
HP_5061_3001(config , m_lpu , 5700000);
|
||||
m_lpu->set_addrmap(AS_PROGRAM , &hp9845_base_state::global_mem_map);
|
||||
m_lpu->set_9845_boot_mode(true);
|
||||
m_lpu->set_rw_cycles(6 , 6);
|
||||
m_lpu->set_relative_mode(true);
|
||||
HP_5061_3001(config , m_ppu , 5700000);
|
||||
m_ppu->set_addrmap(AS_PROGRAM , &hp9845_base_state::global_mem_map);
|
||||
m_ppu->set_addrmap(AS_IO , &hp9845_base_state::ppu_io_map);
|
||||
m_ppu->set_9845_boot_mode(true);
|
||||
m_ppu->set_rw_cycles(6 , 6);
|
||||
m_ppu->set_relative_mode(true);
|
||||
m_ppu->set_irq_acknowledge_callback(FUNC(hp9845_base_state::irq_callback));
|
||||
m_ppu->pa_changed_cb().set(FUNC(hp9845_base_state::pa_w));
|
||||
|
||||
// video hardware
|
||||
MCFG_SCREEN_ADD("screen", RASTER)
|
||||
|
34
src/mame/layout/hp9825.lay
Normal file
34
src/mame/layout/hp9825.lay
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0"?>
|
||||
<mamelayout version="2">
|
||||
<element name="dotmatrix5dot">
|
||||
<dotmatrix5dot>
|
||||
<color red="1.0" green="0" blue="0" />
|
||||
</dotmatrix5dot>
|
||||
</element>
|
||||
<element name="run_light" defstate="0">
|
||||
<disk state="0">
|
||||
<color red="0.25" green="0" blue="0" />
|
||||
</disk>
|
||||
<disk state="1">
|
||||
<color red="1.0" green="0" blue="0" />
|
||||
</disk>
|
||||
</element>
|
||||
<view name="32-char display">
|
||||
<bounds x="-5" y="0" width="289" height="7"/>
|
||||
<bezel name="run_light" element="run_light">
|
||||
<bounds x="-5" y="2" width="2" height="2"/>
|
||||
</bezel>
|
||||
<!-- 32 5x7 characters -->
|
||||
<repeat count="32">
|
||||
<param name="digitidx" start="0" increment="1" />
|
||||
<param name="digit_x" start="0.0" increment="9"/>
|
||||
<!-- Each of the 7 rows in a character -->
|
||||
<repeat count="7">
|
||||
<param name="rowidx" start="0" increment="1" />
|
||||
<bezel name="char_~digitidx~_~rowidx~" element="dotmatrix5dot" state="0">
|
||||
<bounds x="~digit_x~" y="~rowidx~" width="5" height="1" />
|
||||
</bezel>
|
||||
</repeat>
|
||||
</repeat>
|
||||
</view>
|
||||
</mamelayout>
|
@ -15286,6 +15286,9 @@ hp64k //
|
||||
@source:hp700.cpp
|
||||
hp700_92 //
|
||||
|
||||
@source:hp9825.cpp
|
||||
hp9825b // HP 9825B
|
||||
|
||||
@source:hp9845.cpp
|
||||
hp9835a //
|
||||
hp9835b //
|
||||
|
@ -291,6 +291,7 @@ hp48.cpp
|
||||
hp49gp.cpp
|
||||
hp64k.cpp
|
||||
hp700.cpp
|
||||
hp9825.cpp
|
||||
hp9845.cpp
|
||||
hp9k.cpp
|
||||
hp9k_3xx.cpp
|
||||
|
@ -349,8 +349,9 @@ static const dasm_table_entry dasm_table[] =
|
||||
{ "hd6309", be, 0, []() -> util::disasm_interface * { return new hd6309_disassembler; } },
|
||||
{ "hd63701", be, 0, []() -> util::disasm_interface * { return new m680x_disassembler(63701); } },
|
||||
{ "hmcs40", le, -1, []() -> util::disasm_interface * { return new hmcs40_disassembler; } },
|
||||
{ "hp_hybrid", be, -1, []() -> util::disasm_interface * { return new hp_hybrid_disassembler; } },
|
||||
{ "hp_5061_3001", be, -1, []() -> util::disasm_interface * { return new hp_5061_3001_disassembler; } },
|
||||
{ "hp_5061_3011", be, -1, []() -> util::disasm_interface * { return new hp_5061_3011_disassembler; } },
|
||||
{ "hp_09825_67907", be, -1, []() -> util::disasm_interface * { return new hp_09825_67907_disassembler; } },
|
||||
{ "hyperstone", be, 0, []() -> util::disasm_interface * { return new hyperstone_disassembler(&hyperstone_unidasm); } },
|
||||
{ "i4004", le, 0, []() -> util::disasm_interface * { return new i4004_disassembler; } },
|
||||
{ "i4040", le, 0, []() -> util::disasm_interface * { return new i4040_disassembler; } },
|
||||
|
Loading…
Reference in New Issue
Block a user