mirror of
https://github.com/holub/mame
synced 2025-04-19 23:12:11 +03:00
Holtek HT1130 CPU core, and preliminary driver for a brick game using it (#11872)
new machines marked as NOT WORKING -------------------------- Brick Game 96 in 1 (E-23 Plus Mark II) [azya52, David Haywood]
This commit is contained in:
parent
70ebbc384b
commit
6222175a22
@ -3932,3 +3932,20 @@ if opt_tool(CPUS, "XTENSA") then
|
||||
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/xtensa/xtensa_helper.cpp")
|
||||
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/xtensa/xtensa_helper.h")
|
||||
end
|
||||
|
||||
--------------------------------------------------
|
||||
-- Holtek HT1130
|
||||
--@src/devices/cpu/ht1130/ht1130.h,CPUS["HT1130"] = true
|
||||
--------------------------------------------------
|
||||
|
||||
if CPUS["HT1130"] then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/cpu/ht1130/ht1130.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/ht1130/ht1130.h",
|
||||
}
|
||||
end
|
||||
|
||||
if opt_tool(CPUS, "HT1130") then
|
||||
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/ht1130/ht1130d.cpp")
|
||||
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/ht1130/ht1130d.h")
|
||||
end
|
||||
|
1059
src/devices/cpu/ht1130/ht1130.cpp
Normal file
1059
src/devices/cpu/ht1130/ht1130.cpp
Normal file
File diff suppressed because it is too large
Load Diff
126
src/devices/cpu/ht1130/ht1130.h
Normal file
126
src/devices/cpu/ht1130/ht1130.h
Normal file
@ -0,0 +1,126 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:David Haywood
|
||||
|
||||
#ifndef MAME_CPU_HT1130_HT1130_H
|
||||
#define MAME_CPU_HT1130_HT1130_H
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
class ht1130_device : public cpu_device
|
||||
{
|
||||
public:
|
||||
ht1130_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
enum {
|
||||
HT1130_PC,
|
||||
HT1130_R0,
|
||||
HT1130_R1,
|
||||
HT1130_R2,
|
||||
HT1130_R3,
|
||||
HT1130_R4,
|
||||
HT1130_ACC,
|
||||
HT1130_TIMER_EN,
|
||||
HT1130_TIMER,
|
||||
};
|
||||
|
||||
auto pm_in_cb() { return m_port_in_pm.bind(); }
|
||||
auto ps_in_cb() { return m_port_in_ps.bind(); }
|
||||
auto pp_in_cb() { return m_port_in_pp.bind(); }
|
||||
|
||||
auto pa_out_cb() { return m_port_out_pa.bind(); }
|
||||
|
||||
auto display_data_out_cb() { return m_display_data_out.bind(); }
|
||||
|
||||
protected:
|
||||
ht1130_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor data);
|
||||
|
||||
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
virtual void execute_run() override;
|
||||
virtual void execute_set_input(int inputnum, int state) override;
|
||||
virtual uint32_t execute_max_cycles() const noexcept override { return 2; }
|
||||
|
||||
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
|
||||
|
||||
virtual space_config_vector memory_space_config() const override;
|
||||
|
||||
void internal_map(address_map &map);
|
||||
void internal_data_map(address_map &map);
|
||||
|
||||
void tempram_w(offs_t offset, u8 data);
|
||||
void displayram_w(offs_t offset, u8 data);
|
||||
|
||||
required_shared_ptr<u8> m_tempram;
|
||||
required_shared_ptr<u8> m_displayram;
|
||||
|
||||
private:
|
||||
address_space_config m_space_config;
|
||||
address_space_config m_data_config;
|
||||
|
||||
memory_access<8, 0, 0, ENDIANNESS_LITTLE>::specific m_space;
|
||||
memory_access<8, 0, 0, ENDIANNESS_LITTLE>::specific m_data;
|
||||
|
||||
void setreg(u8 which, u8 data);
|
||||
u8 getreg(u8 which);
|
||||
void setacc(u8 data);
|
||||
u8 getacc();
|
||||
void setcarry();
|
||||
void clearcarry();
|
||||
u8 getcarry();
|
||||
u8 getr1r0();
|
||||
u8 getr1r0_data();
|
||||
void setr1r0_data(u8 data);
|
||||
u8 getr3r2();
|
||||
u8 getr3r2_data();
|
||||
void setr3r2_data(u8 data);
|
||||
void settimer(u8 data);
|
||||
void settimer_upper(u8 data);
|
||||
void settimer_lower(u8 data);
|
||||
u8 gettimer_upper();
|
||||
u8 gettimer_lower();
|
||||
|
||||
void cycle();
|
||||
u8 fetch();
|
||||
void do_op();
|
||||
|
||||
u32 m_pc;
|
||||
s32 m_icount;
|
||||
|
||||
u8 m_regs[5];
|
||||
u8 m_acc;
|
||||
u8 m_carry;
|
||||
u8 m_irqen;
|
||||
u8 m_timer_en;
|
||||
u8 m_inhalt;
|
||||
u8 m_timerover;
|
||||
u16 m_timer;
|
||||
|
||||
u16 m_stackaddr;
|
||||
u8 m_stackcarry;
|
||||
|
||||
devcb_read8 m_port_in_pm;
|
||||
devcb_read8 m_port_in_ps;
|
||||
devcb_read8 m_port_in_pp;
|
||||
|
||||
devcb_write8 m_port_out_pa;
|
||||
|
||||
devcb_write8 m_display_data_out;
|
||||
};
|
||||
|
||||
class ht1190_device : public ht1130_device
|
||||
{
|
||||
public:
|
||||
ht1190_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
|
||||
private:
|
||||
void internal_data_map_ht1190(address_map &map);
|
||||
};
|
||||
|
||||
|
||||
DECLARE_DEVICE_TYPE(HT1130, ht1130_device)
|
||||
DECLARE_DEVICE_TYPE(HT1190, ht1190_device)
|
||||
|
||||
#endif // MAME_CPU_HT1130_HT1130_H
|
668
src/devices/cpu/ht1130/ht1130d.cpp
Normal file
668
src/devices/cpu/ht1130/ht1130d.cpp
Normal file
@ -0,0 +1,668 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:David Haywood
|
||||
|
||||
#include "emu.h"
|
||||
#include "ht1130d.h"
|
||||
|
||||
ht1130_disassembler::ht1130_disassembler()
|
||||
: util::disasm_interface()
|
||||
{
|
||||
}
|
||||
|
||||
u32 ht1130_disassembler::opcode_alignment() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
offs_t ht1130_disassembler::disassemble(std::ostream &stream, offs_t pc, const ht1130_disassembler::data_buffer &opcodes, const ht1130_disassembler::data_buffer ¶ms)
|
||||
{
|
||||
u8 inst = opcodes.r8(pc);
|
||||
|
||||
switch (inst)
|
||||
{
|
||||
case 0b00001000: // ADC A,[R1R0] : Add data memory contents and carry to the accumulator
|
||||
{
|
||||
stream << "ADC A,[R1R0]";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00001001: // ADD A,[R1R0] : Add data memory contents to the accumulator
|
||||
{
|
||||
stream << "ADD A,[R1R0]";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00011010: // AND A,[R1R0] : Logical AND accumulator with data memory
|
||||
{
|
||||
stream << "AND A,[R1R0]";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00011101: // AND [R1R0],A : Logical AND data memory with accumulator
|
||||
{
|
||||
stream << "AND [R1R0],A";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00101010: // CLC : Clear carry flag
|
||||
{
|
||||
stream << "CLC";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00110110: // DAA : Decimal-Adjust accumulator
|
||||
{
|
||||
stream << "DAA";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00111111: // DEC A : Decrement accumulator
|
||||
{
|
||||
stream << "DEC A";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00001101: // DEC [R1R0] : Decrement data memory
|
||||
{
|
||||
stream << "DEC [R1R0]";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00001111: // DEC [R3R2] : Decrement data memory
|
||||
{
|
||||
stream << "DEC [R3R2]";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00101101: // DI : Disable interrupt
|
||||
{
|
||||
stream << "DI";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00101100: // EI : Enable interrupt
|
||||
{
|
||||
stream << "EI";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00110010: // IN A,PM : Input port to accumulator
|
||||
{
|
||||
stream << "IN A,PM";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00110011: // IN A,PS : Input port to accumulator
|
||||
{
|
||||
stream << "IN A,PS";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00110100: // IN A,PP : Input port to accumulator
|
||||
{
|
||||
stream << "IN A,PP";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00110001: // INC A : Increment accumulator
|
||||
{
|
||||
stream << "INC A";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00001100: // INC [R1R0] : Increment data memory
|
||||
{
|
||||
stream << "INC [R1R0]";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00001110: // INC [R3R2] : Increment data memory
|
||||
{
|
||||
stream << "INC [R3R2]";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00111011: // MOV A,TMRH : Move timer high nibble to accumulator
|
||||
{
|
||||
stream << "MOV A,TMRH";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00111010: // MOV A,TMRL : Move timer low nibble to accumulator
|
||||
{
|
||||
stream << "MOV A,TMRL";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00000100: // MOV A,[R1R0] : Move data memory to accumulator
|
||||
{
|
||||
stream << "MOV A,[R1R0]";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00000110: // MOV A,[R3R2] : Move data memory to accumulator
|
||||
{
|
||||
stream << "MOV A,[R3R2]";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00111101: // MOV TMRH,A : Move accumulator to timer high nibble
|
||||
{
|
||||
stream << "MOV TMRH,A";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00111100: // MOV TMRL,A : Move accumulator to timer low nibble
|
||||
{
|
||||
stream << "MOV TMRL,A";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00000101: // MOV [R1R0],A : Move accumulator to data memory
|
||||
{
|
||||
stream << "MOV [R1R0],A";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00000111: // MOV [R3R2],A : Move accumulator to data memory
|
||||
{
|
||||
stream << "MOV [R3R2],A";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00111110: // NOP : No operation
|
||||
{
|
||||
stream << "NOP";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00011100: // OR A,[R1R0] : Logical OR accumulator with data memory
|
||||
{
|
||||
stream << "OR A,[R1R0]";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00011111: // OR [R1R0],A : Logically OR data memory with accumulator
|
||||
{
|
||||
stream << "OR [R1R0],A";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00110000: // OUT PA,A : Output accumulator data to port A
|
||||
{
|
||||
stream << "OUT PA,A";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b01001110: // READ MR0A : Read ROM code of current page to M(R1,R0) and ACC
|
||||
{
|
||||
stream << "READ MR0A";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b01001100: // READ R4A : Read ROM code of current page to R4 and accumulator
|
||||
{
|
||||
stream << "READ R4A";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b01001111: // READF MR0A : Read ROM Code of page F to M(R1,R0) and ACC
|
||||
{
|
||||
stream << "READF MR0A";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b01001101: // READF R4A : Read ROM code of page F to R4 and accumulator
|
||||
{
|
||||
stream << "READF R4A";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00101110: // RET : Return from subroutine or interrupt
|
||||
{
|
||||
stream << "RET";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00101111: // RETI : Return from interrupt subroutine
|
||||
{
|
||||
stream << "RETI";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00000001: // RL A : Rotate accumulator left
|
||||
{
|
||||
stream << "RL A";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00000011: // RLC A : Rotate accumulator left through carry
|
||||
{
|
||||
stream << "RLC A";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00000000: // RR A : Rotate accumulator right
|
||||
{
|
||||
stream << "RR A";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00000010: // RRC A : Rotate accumulator right through carry
|
||||
{
|
||||
stream << "RRC A";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00001010: // SBC A,[R1R0] : Subtract data memory contents and carry from ACC
|
||||
{
|
||||
stream << "SBC A,[R1R0]";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b01001011: // SOUND A : Activate SOUND channel with accumulator
|
||||
{
|
||||
stream << "SOUND A";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b01001001: // SOUND LOOP : Turn on sound repeat cycle
|
||||
{
|
||||
stream << "SOUND LOOP";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b01001010: // SOUND OFF : Turn off sound
|
||||
{
|
||||
stream << "SOUND OFF";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b01001000: // SOUND ONE : Turn on sound 1 cycle
|
||||
{
|
||||
stream << "SOUND ONE";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00101011: // STC : Set carry flag
|
||||
{
|
||||
stream << "STC";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00001011: // SUB A,[R1R0] : Subtract data memory contents from accumulator
|
||||
{
|
||||
stream << "SUB A,[R1R0]";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00111001: // TIMER OFF : Set timer to stop counting
|
||||
{
|
||||
stream << "TIMER OFF";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00111000: // TIMER ON : Set timer to start counting
|
||||
{
|
||||
stream << "TIMER ON";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00011011: // XOR A,[R1R0] : Logical XOR accumulator with data memory
|
||||
{
|
||||
stream << "XOR A,[R1R0]";
|
||||
return 1;
|
||||
}
|
||||
|
||||
case 0b00011110: // XOR [R1R0],A : Logical XOR data memory with accumulator
|
||||
{
|
||||
stream << "XOR [R1R0],A";
|
||||
return 1;
|
||||
}
|
||||
|
||||
//// Opcodes with XH Immediates
|
||||
|
||||
case 0b01000000: // (with 4-bit immediate) : ADD A,XH : Add immediate data to the accumulator
|
||||
{
|
||||
u8 operand = opcodes.r8(pc + 1);
|
||||
if (!(operand & 0xf0))
|
||||
{
|
||||
util::stream_format(stream, "ADD A,0x%02x", operand);
|
||||
}
|
||||
else
|
||||
{
|
||||
util::stream_format(stream, "<ill %02x %02x>", inst, operand);
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
case 0b01000010: // (with 4-bit immediate) : AND A,XH : Logical AND immediate data to accumulator
|
||||
{
|
||||
u8 operand = opcodes.r8(pc + 1);
|
||||
if (!(operand & 0xf0))
|
||||
{
|
||||
util::stream_format(stream, "AND A,0x%02x", operand);
|
||||
}
|
||||
else
|
||||
{
|
||||
util::stream_format(stream, "<ill %02x %02x>", inst, operand);
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
case 0b01000110: // (with 4-bit immediate) : MOV R4,XH : Move immediate data to R4
|
||||
{
|
||||
u8 operand = opcodes.r8(pc + 1);
|
||||
if (!(operand & 0xf0))
|
||||
{
|
||||
util::stream_format(stream, "MOV R4,0x%02x", operand);
|
||||
}
|
||||
else
|
||||
{
|
||||
util::stream_format(stream, "<ill %02x %02x>", inst, operand);
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
case 0b01000100: // (with 4-bit immediate) : OR A,XH : Logical OR immediate data to accumulator
|
||||
{
|
||||
u8 operand = opcodes.r8(pc + 1);
|
||||
if (!(operand & 0xf0))
|
||||
{
|
||||
util::stream_format(stream, "OR A,0x%02x", operand);
|
||||
}
|
||||
else
|
||||
{
|
||||
util::stream_format(stream, "<ill %02x %02x>", inst, operand);
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
case 0b01000001: // (with 4-bit immediate) : SUB A,XH : Subtract immediate data from accumulator0
|
||||
{
|
||||
u8 operand = opcodes.r8(pc + 1);
|
||||
if (!(operand & 0xf0))
|
||||
{
|
||||
util::stream_format(stream, "SUB A,0x%02x", operand);
|
||||
}
|
||||
else
|
||||
{
|
||||
util::stream_format(stream, "<ill %02x %02x>", inst, operand);
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
case 0b01000011: // (with 4-bit immediate) : XOR A,XH : Logical XOR immediate data to accumulator
|
||||
{
|
||||
u8 operand = opcodes.r8(pc + 1);
|
||||
if (!(operand & 0xf0))
|
||||
{
|
||||
util::stream_format(stream, "XOR A,0x%02x", operand);
|
||||
}
|
||||
else
|
||||
{
|
||||
util::stream_format(stream, "<ill %02x %02x>", inst, operand);
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
//case 0b0111dddd: // MOV A,XH : Move immediate data to accumulator
|
||||
case 0b01110000: case 0b01110001: case 0b01110010: case 0b01110011:
|
||||
case 0b01110100: case 0b01110101: case 0b01110110: case 0b01110111:
|
||||
case 0b01111000: case 0b01111001: case 0b01111010: case 0b01111011:
|
||||
case 0b01111100: case 0b01111101: case 0b01111110: case 0b01111111:
|
||||
{
|
||||
u8 operand = inst & 0x0f;
|
||||
util::stream_format(stream, "MOV A,0x%02x", operand);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Ops using registers
|
||||
|
||||
// case 0b0001nnn1: DEC Rn : Decrement register (R0-R4)
|
||||
case 0b00010001: case 0b00010011: case 0b00010101: case 0b00010111:
|
||||
case 0b00011001:
|
||||
{
|
||||
u8 reg = (inst & 0x0e) >> 1;
|
||||
util::stream_format(stream, "DEC R%d", reg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// case 0b0001nnn0: INC Rn : Increment register
|
||||
case 0b00010000: case 0b00010010: case 0b00010100: case 0b00010110:
|
||||
case 0b00011000:
|
||||
{
|
||||
u8 reg = (inst & 0x0e) >> 1;
|
||||
util::stream_format(stream, "INC R%d", reg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// case 0b0010nnn1: MOV A,Rn : Move register to accumulator
|
||||
case 0b00100001: case 0b00100011: case 0b00100101: case 0b00100111:
|
||||
case 0b00101001:
|
||||
{
|
||||
u8 reg = (inst & 0x0e) >> 1;
|
||||
util::stream_format(stream, "MOV A,R%d", reg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
//case 0b0010nnn0: MOV Rn,A : Move accumulator to register
|
||||
case 0b00100000: case 0b00100010: case 0b00100100: case 0b00100110:
|
||||
case 0b00101000:
|
||||
{
|
||||
u8 reg = (inst & 0x0e) >> 1;
|
||||
util::stream_format(stream, "MOV R%d, A", reg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// dual move ops
|
||||
|
||||
//case 0b0101dddd: // (with 4-bit immediate) : MOV R1R0,XXH : Move immediate data to R1 and R0
|
||||
case 0b01010000: case 0b01010001: case 0b01010010: case 0b01010011:
|
||||
case 0b01010100: case 0b01010101: case 0b01010110: case 0b01010111:
|
||||
case 0b01011000: case 0b01011001: case 0b01011010: case 0b01011011:
|
||||
case 0b01011100: case 0b01011101: case 0b01011110: case 0b01011111:
|
||||
{
|
||||
u8 operand = opcodes.r8(pc + 1);
|
||||
if (!(operand & 0xf0))
|
||||
{
|
||||
uint8_t fulldata = (inst & 0x0f) | (operand << 4);
|
||||
util::stream_format(stream, "MOV R1R0,0x%02x", fulldata);
|
||||
}
|
||||
else
|
||||
{
|
||||
util::stream_format(stream, "<ill %02x %02x>", inst, operand);
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
//case 0b0110dddd: // (with 4-bit immediate) : MOV R3R2,XXH : Move immediate data to R3 and R2
|
||||
case 0b01100000: case 0b01100001: case 0b01100010: case 0b01100011:
|
||||
case 0b01100100: case 0b01100101: case 0b01100110: case 0b01100111:
|
||||
case 0b01101000: case 0b01101001: case 0b01101010: case 0b01101011:
|
||||
case 0b01101100: case 0b01101101: case 0b01101110: case 0b01101111:
|
||||
{
|
||||
u8 operand = opcodes.r8(pc + 1);
|
||||
if (!(operand & 0xf0))
|
||||
{
|
||||
uint8_t fulldata = (inst & 0x0f) | (operand << 4);
|
||||
util::stream_format(stream, "MOV R3R2,0x%02x", fulldata);
|
||||
}
|
||||
else
|
||||
{
|
||||
util::stream_format(stream, "<ill %02x %02x>", inst, operand);
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
// Jump / Call opcodes with full addresses
|
||||
|
||||
// case 0b1111aaaa: // (with 8-bit immediate) : CALL address : Subroutine call
|
||||
case 0b11110000: case 0b11110001: case 0b11110010: case 0b11110011:
|
||||
case 0b11110100: case 0b11110101: case 0b11110110: case 0b11110111:
|
||||
case 0b11111000: case 0b11111001: case 0b11111010: case 0b11111011:
|
||||
case 0b11111100: case 0b11111101: case 0b11111110: case 0b11111111:
|
||||
{
|
||||
u8 operand = opcodes.r8(pc + 1);
|
||||
uint16_t fulladdr = ((inst & 0x0f) << 8) | operand;
|
||||
util::stream_format(stream, "CALL %03x", fulladdr);
|
||||
return 2;
|
||||
}
|
||||
|
||||
// case 0b1110aaaa: // (with 8-bit immediate) : JMP address : Direct jump
|
||||
case 0b11100000: case 0b11100001: case 0b11100010: case 0b11100011:
|
||||
case 0b11100100: case 0b11100101: case 0b11100110: case 0b11100111:
|
||||
case 0b11101000: case 0b11101001: case 0b11101010: case 0b11101011:
|
||||
case 0b11101100: case 0b11101101: case 0b11101110: case 0b11101111:
|
||||
{
|
||||
u8 operand = opcodes.r8(pc + 1);
|
||||
uint16_t fulladdr = ((inst & 0x0f) << 8) | operand;
|
||||
util::stream_format(stream, "JMP %03x", fulladdr);
|
||||
return 2;
|
||||
}
|
||||
|
||||
// Jump / Call opcodes with partial address
|
||||
|
||||
// case 0b11000aaa: (with 8-bit immediate) : JC address : Jump if carry is set
|
||||
case 0b11000000: case 0b11000001: case 0b11000010: case 0b11000011:
|
||||
case 0b11000100: case 0b11000101: case 0b11000110: case 0b11000111:
|
||||
{
|
||||
u8 operand = opcodes.r8(pc + 1);
|
||||
uint16_t fulladdr = ((inst & 0x07) << 8) | operand | (pc & 0x800);
|
||||
util::stream_format(stream, "JC %03x", fulladdr);
|
||||
return 2;
|
||||
}
|
||||
|
||||
// case 0b11001aaa: (with 8-bit immediate) : JNC address : Jump if carry is not set
|
||||
case 0b11001000: case 0b11001001: case 0b11001010: case 0b11001011:
|
||||
case 0b11001100: case 0b11001101: case 0b11001110: case 0b11001111:
|
||||
{
|
||||
u8 operand = opcodes.r8(pc + 1);
|
||||
uint16_t fulladdr = ((inst & 0x07) << 8) | operand | (pc & 0x800);
|
||||
util::stream_format(stream, "JNC %03x", fulladdr);
|
||||
return 2;
|
||||
}
|
||||
|
||||
// case 0b10111aaa: (with 8-bit immediate) : JNZ A,address : Jump if accumulator is not 0
|
||||
case 0b10111000: case 0b10111001: case 0b10111010: case 0b10111011:
|
||||
case 0b10111100: case 0b10111101: case 0b10111110: case 0b10111111:
|
||||
{
|
||||
u8 operand = opcodes.r8(pc + 1);
|
||||
uint16_t fulladdr = ((inst & 0x07) << 8) | operand | (pc & 0x800);
|
||||
util::stream_format(stream, "JNZ A,%03x", fulladdr);
|
||||
return 2;
|
||||
}
|
||||
|
||||
// case 0b10100aaa: (with 8-bit immediate) : JNZ R0,address : Jump if register is not 0
|
||||
case 0b10100000: case 0b10100001: case 0b10100010: case 0b10100011:
|
||||
case 0b10100100: case 0b10100101: case 0b10100110: case 0b10100111:
|
||||
{
|
||||
u8 operand = opcodes.r8(pc + 1);
|
||||
uint16_t fulladdr = ((inst & 0x07) << 8) | operand | (pc & 0x800);
|
||||
util::stream_format(stream, "JNZ R0,%03x", fulladdr);
|
||||
return 2;
|
||||
}
|
||||
|
||||
// case 0b10101aaa: (with 8-bit immediate) : JNZ R1,address : Jump if register is not 0
|
||||
case 0b10101000: case 0b10101001: case 0b10101010: case 0b10101011:
|
||||
case 0b10101100: case 0b10101101: case 0b10101110: case 0b10101111:
|
||||
{
|
||||
u8 operand = opcodes.r8(pc + 1);
|
||||
uint16_t fulladdr = ((inst & 0x07) << 8) | operand | (pc & 0x800);
|
||||
util::stream_format(stream, "JNZ R1,%03x", fulladdr);
|
||||
return 2;
|
||||
}
|
||||
|
||||
// case 0b11011aaa: (with 8-bit immediate) : JNZ R4,address : Jump if register is not 0
|
||||
case 0b11011000: case 0b11011001: case 0b11011010: case 0b11011011:
|
||||
case 0b11011100: case 0b11011101: case 0b11011110: case 0b11011111:
|
||||
{
|
||||
u8 operand = opcodes.r8(pc + 1);
|
||||
uint16_t fulladdr = ((inst & 0x07) << 8) | operand | (pc & 0x800);
|
||||
util::stream_format(stream, "JNZ R4,%03x", fulladdr);
|
||||
return 2;
|
||||
}
|
||||
|
||||
// case 0b11010aaa: (with 8-bit immediate) : JTMR address : Jump if time-out
|
||||
case 0b11010000: case 0b11010001: case 0b11010010: case 0b11010011:
|
||||
case 0b11010100: case 0b11010101: case 0b11010110: case 0b11010111:
|
||||
{
|
||||
u8 operand = opcodes.r8(pc + 1);
|
||||
uint16_t fulladdr = ((inst & 0x07) << 8) | operand | (pc & 0x800);
|
||||
util::stream_format(stream, "JTMR %03x", fulladdr);
|
||||
return 2;
|
||||
}
|
||||
|
||||
// case 0b10110aaa: (with 8-bit immediate) : JZ A,address : Jump if accumulator is 0
|
||||
case 0b10110000: case 0b10110001: case 0b10110010: case 0b10110011:
|
||||
case 0b10110100: case 0b10110101: case 0b10110110: case 0b10110111:
|
||||
{
|
||||
u8 operand = opcodes.r8(pc + 1);
|
||||
uint16_t fulladdr = ((inst & 0x07) << 8) | operand | (pc & 0x800);
|
||||
util::stream_format(stream, "JZ A,%03x", fulladdr);
|
||||
return 2;
|
||||
}
|
||||
|
||||
//case 0b100nnaaa: // (with 8-bit immediate) : JAn address : Jump if accumulator bit n is set
|
||||
case 0b10000000: case 0b10000001: case 0b10000010: case 0b10000011:
|
||||
case 0b10000100: case 0b10000101: case 0b10000110: case 0b10000111:
|
||||
case 0b10001000: case 0b10001001: case 0b10001010: case 0b10001011:
|
||||
case 0b10001100: case 0b10001101: case 0b10001110: case 0b10001111:
|
||||
case 0b10010000: case 0b10010001: case 0b10010010: case 0b10010011:
|
||||
case 0b10010100: case 0b10010101: case 0b10010110: case 0b10010111:
|
||||
case 0b10011000: case 0b10011001: case 0b10011010: case 0b10011011:
|
||||
case 0b10011100: case 0b10011101: case 0b10011110: case 0b10011111:
|
||||
{
|
||||
u8 operand = opcodes.r8(pc + 1);
|
||||
uint16_t fulladdr = ((inst & 0x07) << 8) | operand | (pc & 0x800);
|
||||
uint8_t bit = (inst & 0x18)>>3;
|
||||
util::stream_format(stream, "JA%d %03x", bit, fulladdr);
|
||||
return 2;
|
||||
}
|
||||
|
||||
// other Ops
|
||||
case 0b01000101: // (with 4 bit immediate) : SOUND n : Activate SOUND channel n
|
||||
{
|
||||
u8 operand = opcodes.r8(pc + 1);
|
||||
if (!(operand & 0xf0))
|
||||
{
|
||||
util::stream_format(stream, "SOUND %d", operand);
|
||||
}
|
||||
else
|
||||
{
|
||||
util::stream_format(stream, "<ill %02x %02x>", inst, operand);
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
case 0b00110111: // (with 00111110) : HALT Halt system clock
|
||||
{
|
||||
u8 operand = opcodes.r8(pc + 1);
|
||||
if (operand == 0b00111110)
|
||||
{
|
||||
stream << "HALT";
|
||||
}
|
||||
else
|
||||
{
|
||||
util::stream_format(stream, "<ill %02x %02x>", inst, operand);
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
case 0b01000111: // (with 8-bit immediate) : TIMER XXH : Set immediate data to timer counter
|
||||
{
|
||||
u8 operand = opcodes.r8(pc + 1);
|
||||
util::stream_format(stream, "TIMER %02x", operand);
|
||||
return 2;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
util::stream_format(stream, "<ill %02x>", inst);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
22
src/devices/cpu/ht1130/ht1130d.h
Normal file
22
src/devices/cpu/ht1130/ht1130d.h
Normal file
@ -0,0 +1,22 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:David Haywood
|
||||
|
||||
#ifndef MAME_CPU_HT1130_HT1130D_H
|
||||
#define MAME_CPU_HT1130_HT1130D_H
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
class ht1130_disassembler : public util::disasm_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
ht1130_disassembler();
|
||||
|
||||
protected:
|
||||
// disassembler overrides
|
||||
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;
|
||||
};
|
||||
|
||||
#endif // MAME_CPU_HT1130_HT1130D_H
|
108
src/mame/handheld/hh_ht11xx.cpp
Normal file
108
src/mame/handheld/hh_ht11xx.cpp
Normal file
@ -0,0 +1,108 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:David Haywood
|
||||
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
#include "cpu/ht1130/ht1130.h"
|
||||
|
||||
#include "screen.h"
|
||||
#include "speaker.h"
|
||||
|
||||
#define VERBOSE (0)
|
||||
#include "logmacro.h"
|
||||
|
||||
namespace {
|
||||
|
||||
class ht11xx_brickgame_state : public driver_device
|
||||
{
|
||||
public:
|
||||
ht11xx_brickgame_state(const machine_config &mconfig, device_type type, const char *tag) :
|
||||
driver_device(mconfig, type, tag),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_out_x(*this, "seg%u_%u", 0U, 0U),
|
||||
m_in1(*this, "IN1"),
|
||||
m_in2(*this, "IN2")
|
||||
{ }
|
||||
|
||||
void ht11xx_brickgame(machine_config &config);
|
||||
|
||||
protected:
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
|
||||
private:
|
||||
void mcfg_svg_screen(machine_config &config, u16 width, u16 height, const char *tag = "screen");
|
||||
|
||||
void display_data_w(offs_t offset, u8 data);
|
||||
|
||||
required_device<ht1130_device> m_maincpu;
|
||||
output_finder<256, 4> m_out_x;
|
||||
required_ioport m_in1;
|
||||
required_ioport m_in2;
|
||||
};
|
||||
|
||||
void ht11xx_brickgame_state::machine_start()
|
||||
{
|
||||
m_out_x.resolve();
|
||||
}
|
||||
|
||||
void ht11xx_brickgame_state::machine_reset()
|
||||
{
|
||||
}
|
||||
|
||||
static INPUT_PORTS_START( ht11xx_brickgame )
|
||||
PORT_START("IN1")
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_START1 )
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("Mute")
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("Power")
|
||||
|
||||
PORT_START("IN2") // not a joystick, but buttons are used for directional inputs in the snake game etc.
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("Up / Rotate")
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("Down / Drop")
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("Right")
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("Left")
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
void ht11xx_brickgame_state::display_data_w(offs_t offset, u8 data)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
m_out_x[offset+0xb0][i] = (data >> i) & 1;
|
||||
}
|
||||
}
|
||||
|
||||
void ht11xx_brickgame_state::mcfg_svg_screen(machine_config &config, u16 width, u16 height, const char *tag)
|
||||
{
|
||||
screen_device &screen(SCREEN(config, tag, SCREEN_TYPE_SVG));
|
||||
screen.set_refresh_hz(60);
|
||||
screen.set_size(width, height);
|
||||
screen.set_visarea_full();
|
||||
}
|
||||
|
||||
void ht11xx_brickgame_state::ht11xx_brickgame(machine_config &config)
|
||||
{
|
||||
HT1190(config, m_maincpu, 1000000/8); // frequency?
|
||||
m_maincpu->display_data_out_cb().set(FUNC(ht11xx_brickgame_state::display_data_w));
|
||||
|
||||
m_maincpu->ps_in_cb().set_ioport(m_in1);
|
||||
m_maincpu->pp_in_cb().set_ioport(m_in2);
|
||||
|
||||
SPEAKER(config, "speaker").front_center();
|
||||
|
||||
mcfg_svg_screen(config, 768, 1080);
|
||||
}
|
||||
|
||||
ROM_START( brke23p2 )
|
||||
ROM_REGION( 0x1000, "maincpu", 0 )
|
||||
ROM_LOAD( "e23plusmarkii96in1.bin", 0x0000, 0x1000, CRC(8045fac4) SHA1(a36213309e6add31f31e4248f02f17de9914a5c1) ) // visual decap
|
||||
|
||||
ROM_REGION( 139648, "screen", 0)
|
||||
ROM_LOAD( "brke23p2.svg", 0, 139648, CRC(f29ea936) SHA1(d80a37aa4e5647b31454a6d6de5a59c770ef0322) )
|
||||
ROM_END
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// some other dieshots have 1996 on them, it is also possible the software is from Holtek
|
||||
CONS( 1993, brke23p2, 0, 0, ht11xx_brickgame, ht11xx_brickgame, ht11xx_brickgame_state, empty_init, "E-Star", "Brick Game 96 in 1 (E-23 Plus Mark II)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) // needs SVG screen
|
@ -18807,6 +18807,9 @@ vinvader // VTech
|
||||
wantgman // Actronics / Hanzawa
|
||||
zackman // Bandai
|
||||
|
||||
@source:handheld/hh_ht11xx.cpp
|
||||
brke23p2
|
||||
|
||||
@source:handheld/hh_melps4.cpp
|
||||
cfrogger // Coleco
|
||||
gjungler // Gakken
|
||||
|
@ -70,6 +70,7 @@ using util::BIT;
|
||||
#include "cpu/hp2100/hp2100d.h"
|
||||
#include "cpu/hpc/hpcdasm.h"
|
||||
#include "cpu/hphybrid/hphybrid_dasm.h"
|
||||
#include "cpu/ht1130/ht1130d.h"
|
||||
#include "cpu/i386/i386dasm.h"
|
||||
#include "cpu/i8008/8008dasm.h"
|
||||
#include "cpu/i8085/8085dasm.h"
|
||||
@ -475,6 +476,7 @@ static const dasm_table_entry dasm_table[] =
|
||||
{ "hpc16083", le, 0, []() -> util::disasm_interface * { return new hpc16083_disassembler; } },
|
||||
{ "hpc16164", le, 0, []() -> util::disasm_interface * { return new hpc16164_disassembler; } },
|
||||
{ "hyperstone", be, 0, []() -> util::disasm_interface * { return new hyperstone_disassembler(&hyperstone_unidasm); } },
|
||||
{ "ht1130", le, 0, []() -> util::disasm_interface * { return new ht1130_disassembler; } },
|
||||
{ "i4004", le, 0, []() -> util::disasm_interface * { return new i4004_disassembler; } },
|
||||
{ "i4040", le, 0, []() -> util::disasm_interface * { return new i4040_disassembler; } },
|
||||
{ "i8008", le, 0, []() -> util::disasm_interface * { return new i8008_disassembler; } },
|
||||
|
Loading…
Reference in New Issue
Block a user