mirror of
https://github.com/holub/mame
synced 2025-07-05 09:57:47 +03:00
kl5c80a12: Emulate interrupt controller
This commit is contained in:
parent
f5191273ac
commit
4aae75d753
@ -2616,6 +2616,8 @@ if (CPUS["Z80"]~=null) then
|
||||
MAME_DIR .. "src/devices/cpu/z80/tmpz84c015.h",
|
||||
MAME_DIR .. "src/devices/cpu/z80/kl5c80a12.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/z80/kl5c80a12.h",
|
||||
MAME_DIR .. "src/devices/cpu/z80/kp69.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/z80/kp69.h",
|
||||
MAME_DIR .. "src/devices/cpu/z80/lz8420m.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/z80/lz8420m.h",
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
— MMU
|
||||
— USART (KP51) (unemulated)
|
||||
— 16-bit timer/counters (KP64, KP63) (unemulated)
|
||||
— 16-level interrupt controller (KP69) (unemulated)
|
||||
— 16-level interrupt controller (KP69)
|
||||
— Parallel ports (KP65, KP66) (unemulated)
|
||||
— 512-byte high-speed RAM
|
||||
— External bus interface unit (unemulated)
|
||||
@ -25,12 +25,19 @@
|
||||
|
||||
DEFINE_DEVICE_TYPE(KL5C80A12, kl5c80a12_device, "kl5c80a12", "Kawasaki Steel KL5C80A12")
|
||||
|
||||
static const z80_daisy_config fake_daisy_config[] = { { "kp69" }, { nullptr } };
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// kl5c80a12 - device type constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
kl5c80a12_device::kl5c80a12_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
: z80_device(mconfig, KL5C80A12, tag, owner, clock)
|
||||
, m_program_config("program", ENDIANNESS_LITTLE, 8, 20, 0, 16, 10, address_map_constructor(FUNC(kl5c80a12_device::internal_ram), this))
|
||||
, m_opcodes_config("opcodes", ENDIANNESS_LITTLE, 8, 20, 0, 16, 10, address_map_constructor(FUNC(kl5c80a12_device::internal_ram), this))
|
||||
, m_io_config("io", ENDIANNESS_LITTLE, 8, 16, 0, address_map_constructor(FUNC(kl5c80a12_device::internal_io), this))
|
||||
, m_kp69(*this, "kp69")
|
||||
{
|
||||
std::fill_n(&m_mmu_a[0], 4, 0);
|
||||
std::fill_n(&m_mmu_b[0], 5, 0);
|
||||
@ -55,6 +62,10 @@ void kl5c80a12_device::internal_ram(address_map &map)
|
||||
void kl5c80a12_device::internal_io(address_map &map)
|
||||
{
|
||||
map(0x00, 0x07).mirror(0xff00).rw(FUNC(kl5c80a12_device::mmu_r), FUNC(kl5c80a12_device::mmu_w));
|
||||
map(0x34, 0x34).mirror(0xff00).rw(m_kp69, FUNC(kp69_device::isrl_r), FUNC(kp69_device::lerl_pgrl_w));
|
||||
map(0x35, 0x35).mirror(0xff00).rw(m_kp69, FUNC(kp69_device::isrh_r), FUNC(kp69_device::lerh_pgrh_w));
|
||||
map(0x36, 0x36).mirror(0xff00).rw(m_kp69, FUNC(kp69_device::imrl_r), FUNC(kp69_device::imrl_w));
|
||||
map(0x37, 0x37).mirror(0xff00).rw(m_kp69, FUNC(kp69_device::imrh_r), FUNC(kp69_device::ivr_imrh_w));
|
||||
}
|
||||
|
||||
|
||||
@ -104,6 +115,8 @@ void kl5c80a12_device::device_start()
|
||||
).mask(0x3ff);
|
||||
}
|
||||
|
||||
m_kp69->add_to_state(*this, KP69_IRR);
|
||||
|
||||
save_item(NAME(m_mmu_a));
|
||||
save_item(NAME(m_mmu_b));
|
||||
}
|
||||
@ -136,9 +149,27 @@ void kl5c80a12_device::device_post_load()
|
||||
}
|
||||
|
||||
|
||||
/* CPU interface */
|
||||
//-------------------------------------------------
|
||||
// device_add_mconfig - add device-specific
|
||||
// machine configuration
|
||||
//-------------------------------------------------
|
||||
|
||||
void kl5c80a12_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
KP69(config, m_kp69);
|
||||
m_kp69->int_callback().set_inputline(*this, INPUT_LINE_IRQ0);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_config_complete - perform any
|
||||
// operations now that the configuration is
|
||||
// complete
|
||||
//-------------------------------------------------
|
||||
|
||||
void kl5c80a12_device::device_config_complete()
|
||||
{
|
||||
set_daisy_config(fake_daisy_config);
|
||||
}
|
||||
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "z80.h"
|
||||
#include "kp69.h"
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
@ -24,7 +25,8 @@ public:
|
||||
enum
|
||||
{
|
||||
KC82_B1 = Z80_WZ + 1, KC82_B2, KC82_B3, KC82_B4,
|
||||
KC82_A1, KC82_A2, KC82_A3
|
||||
KC82_A1, KC82_A2, KC82_A3,
|
||||
KP69_IRR, KP69_ISR, KP69_IVR, KP69_LER, KP69_PGR, KP69_IMR
|
||||
};
|
||||
|
||||
kl5c80a12_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
|
||||
@ -32,6 +34,7 @@ public:
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
virtual void device_config_complete() override;
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual void device_post_load() override;
|
||||
@ -68,6 +71,8 @@ private:
|
||||
u16 m_mmu_a[4];
|
||||
u8 m_mmu_b[5];
|
||||
u32 m_mmu_base[0x40];
|
||||
|
||||
required_device<kp69_device> m_kp69;
|
||||
};
|
||||
|
||||
|
||||
|
453
src/devices/cpu/z80/kp69.cpp
Normal file
453
src/devices/cpu/z80/kp69.cpp
Normal file
@ -0,0 +1,453 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:AJR
|
||||
/***************************************************************************
|
||||
|
||||
Kawasaki Steel (Kawatetsu) KP69 Interrupt Controller
|
||||
|
||||
This macro cell is the sole provider of maskable interrupts for
|
||||
KC80/KC82-based microcontrollers. It responds to the CPU's internal
|
||||
IACK and EOI outputs (the latter associated with the RETI instruction)
|
||||
with prioritized Mode 2 vectors and nested in-service lockouts. It
|
||||
offers no support for polled operation or daisy-chaining other
|
||||
interrupt controllers, but it does allow code to recognize spurious
|
||||
interrupts.
|
||||
|
||||
Each of the 16 interrupt sources may be programmed either as level-
|
||||
triggered or edge-triggered, though the latter is required for
|
||||
interrupts that are internal timer/counter outputs. These and the
|
||||
interrupt vector register must be written first after a reset before
|
||||
the mask and priority group registers can be defined, with no way of
|
||||
returning to the initial mode once the vector has been set.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "kp69.h"
|
||||
|
||||
#define VERBOSE 0
|
||||
#include "logmacro.h"
|
||||
|
||||
// device type definition
|
||||
DEFINE_DEVICE_TYPE(KP69, kp69_device, "kp69", "Kawasaki Steel KP69 Interrupt Controller")
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// kp69_device - device type constructor
|
||||
//-------------------------------------------------
|
||||
|
||||
kp69_device::kp69_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
|
||||
: device_t(mconfig, KP69, tag, owner, clock)
|
||||
, device_z80daisy_interface(mconfig, *this)
|
||||
, m_int_callback(*this)
|
||||
, m_input_levels(0)
|
||||
, m_irr(0)
|
||||
, m_isr(0)
|
||||
, m_illegal_state(false)
|
||||
, m_ivr(0)
|
||||
, m_ivr_written(false)
|
||||
, m_imr(0xffff)
|
||||
, m_ler(0)
|
||||
, m_pgr(0)
|
||||
, m_int_active(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_resolve_objects - resolve objects that
|
||||
// may be needed for other devices to set
|
||||
// initial conditions at start time
|
||||
//-------------------------------------------------
|
||||
|
||||
void kp69_device::device_resolve_objects()
|
||||
{
|
||||
// Resolve output callback
|
||||
m_int_callback.resolve_safe();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void kp69_device::device_start()
|
||||
{
|
||||
// Register state for saving
|
||||
save_item(NAME(m_input_levels));
|
||||
save_item(NAME(m_irr));
|
||||
save_item(NAME(m_isr));
|
||||
save_item(NAME(m_illegal_state));
|
||||
save_item(NAME(m_ivr));
|
||||
save_item(NAME(m_ivr_written));
|
||||
save_item(NAME(m_imr));
|
||||
save_item(NAME(m_ler));
|
||||
save_item(NAME(m_pgr));
|
||||
save_item(NAME(m_int_active));
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// add_to_state - debug state interface for MCU
|
||||
//-------------------------------------------------
|
||||
|
||||
void kp69_device::add_to_state(device_state_interface &state, int index)
|
||||
{
|
||||
state.state_add<u16>(index, "IRR", [this]() { return m_irr; }, [this](u16 data) { set_irr(data); });
|
||||
state.state_add<u16>(index + 1, "ISR", [this]() { return m_isr; }, [this](u16 data) { set_isr(data); });
|
||||
state.state_add(index + 2, "IVR", m_ivr).mask(0xe0);
|
||||
state.state_add<u16>(index + 3, "LER", [this]() { return m_ler; }, [this](u16 data) { set_ler(data); });
|
||||
state.state_add<u16>(index + 4, "PGR", [this]() { return m_pgr; }, [this](u16 data) { set_pgr(data); });
|
||||
state.state_add<u16>(index + 5, "IMR", [this]() { return m_imr; }, [this](u16 data) { set_imr(data); });
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
|
||||
void kp69_device::device_reset()
|
||||
{
|
||||
// Reset inputs to level mode
|
||||
m_irr = m_input_levels;
|
||||
m_ler = 0;
|
||||
|
||||
// Mask all interrupts and end service
|
||||
m_isr = 0;
|
||||
m_imr = 0xffff;
|
||||
m_illegal_state = false;
|
||||
|
||||
// Reset priority groups
|
||||
m_pgr = 0;
|
||||
|
||||
// Allow LER and IVR to be written first
|
||||
m_ivr_written = false;
|
||||
|
||||
// Deassert interrupt output
|
||||
set_int(false);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// isrl_r - read lower 8 bits of ISR
|
||||
//-------------------------------------------------
|
||||
|
||||
u8 kp69_device::isrl_r()
|
||||
{
|
||||
return m_isr & 0x00ff;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// isrh_r - read upper 8 bits of ISR
|
||||
//-------------------------------------------------
|
||||
|
||||
u8 kp69_device::isrh_r()
|
||||
{
|
||||
return (m_isr & 0xff00) >> 8;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// imrl_r - read lower 8 bits of IMR
|
||||
//-------------------------------------------------
|
||||
|
||||
u8 kp69_device::imrl_r()
|
||||
{
|
||||
return m_imr & 0x00ff;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// imrh_r - read upper 8 bits of IMR
|
||||
//-------------------------------------------------
|
||||
|
||||
u8 kp69_device::imrh_r()
|
||||
{
|
||||
return (m_imr & 0xff00) >> 8;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// lerl_pgrl_w - write lower 8 bits of LER or PGR
|
||||
//-------------------------------------------------
|
||||
|
||||
void kp69_device::lerl_pgrl_w(u8 data)
|
||||
{
|
||||
if (m_ivr_written)
|
||||
set_pgr((m_pgr & 0xff00) | data);
|
||||
else
|
||||
set_ler((m_ler & 0xff00) | data);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// lerh_pgrh_w - write upper 8 bits of LER or PGR
|
||||
//-------------------------------------------------
|
||||
|
||||
void kp69_device::lerh_pgrh_w(u8 data)
|
||||
{
|
||||
if (m_ivr_written)
|
||||
set_pgr(u16(data) << 8 | (m_pgr & 0x00ff));
|
||||
else
|
||||
set_ler(u16(data) << 8 | (m_ler & 0x00ff));
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// imrl_w - write lower 8 bits of IMR
|
||||
//-------------------------------------------------
|
||||
|
||||
void kp69_device::imrl_w(u8 data)
|
||||
{
|
||||
if (!m_ivr_written)
|
||||
logerror("%s: IMRL written before IVR\n", machine().describe_context());
|
||||
|
||||
set_imr((m_imr & 0xff00) | data);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// ivr_imrh_w - write IVR or upper 8 bits of IMR
|
||||
//-------------------------------------------------
|
||||
|
||||
void kp69_device::ivr_imrh_w(u8 data)
|
||||
{
|
||||
if (m_ivr_written)
|
||||
set_imr(u16(data) << 8 | (m_imr & 0x00ff));
|
||||
else
|
||||
{
|
||||
m_ivr = data & 0xe0;
|
||||
m_ivr_written = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// int_active - determine whether or not the INT
|
||||
// output is currently active
|
||||
//-------------------------------------------------
|
||||
|
||||
bool kp69_device::int_active() const
|
||||
{
|
||||
if (m_illegal_state)
|
||||
return false;
|
||||
|
||||
// Compare priority of pending interrupt request with any being serviced
|
||||
u16 requested = m_irr & ~m_imr;
|
||||
if ((requested & m_pgr) != 0 || (m_isr & m_pgr) != 0)
|
||||
return count_leading_zeros(u32(requested & m_pgr)) < count_leading_zeros(u32(m_isr & m_pgr));
|
||||
else if (requested != 0)
|
||||
return count_leading_zeros(u32(requested)) < count_leading_zeros(u32(m_isr));
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// set_int - update the INT output state
|
||||
//-------------------------------------------------
|
||||
|
||||
void kp69_device::set_int(bool active)
|
||||
{
|
||||
if (m_int_active != active)
|
||||
{
|
||||
m_int_active = active;
|
||||
m_int_callback(m_int_active ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// set_input_level - set the level state of one
|
||||
// out of 16 interrupt inputs
|
||||
//-------------------------------------------------
|
||||
|
||||
void kp69_device::set_input_level(int level, bool state)
|
||||
{
|
||||
if (!BIT(m_input_levels, level) && state)
|
||||
{
|
||||
m_input_levels |= 1 << level;
|
||||
if (!BIT(m_irr, level))
|
||||
{
|
||||
u16 old_ints = m_irr | m_isr;
|
||||
m_irr |= 1 << level;
|
||||
LOG("IRR[%d] asserted\n", level);
|
||||
if (!m_illegal_state && !BIT(m_imr, level) && (1 << level) > (BIT(m_pgr, level) ? old_ints & m_pgr : old_ints))
|
||||
set_int(true);
|
||||
}
|
||||
}
|
||||
else if (BIT(m_input_levels, level) && !state)
|
||||
{
|
||||
m_input_levels &= ~(1 << level);
|
||||
if (!BIT(m_ler, level) && BIT(m_irr, level))
|
||||
{
|
||||
m_irr &= ~(1 << level);
|
||||
LOG("IRR[%d] cleared\n", level);
|
||||
if (!m_illegal_state && !BIT(m_imr, level))
|
||||
set_int(int_active());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// set_irr - write a new value to the Interrupt
|
||||
// Request Register (not accessible by software)
|
||||
//-------------------------------------------------
|
||||
|
||||
void kp69_device::set_irr(u16 data)
|
||||
{
|
||||
bool update = !m_illegal_state && ((m_irr ^ data) & m_ler & ~m_imr) != 0;
|
||||
m_irr = (data & m_ler) | (m_input_levels & ~m_ler);
|
||||
if (update)
|
||||
set_int(int_active());
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// set_isr - write a new value to the In Service
|
||||
// Register (not writable by software)
|
||||
//-------------------------------------------------
|
||||
|
||||
void kp69_device::set_isr(u16 data)
|
||||
{
|
||||
m_isr = data;
|
||||
set_int(int_active());
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// set_imr - write a new value to the Interrupt
|
||||
// Mask Register
|
||||
//-------------------------------------------------
|
||||
|
||||
void kp69_device::set_imr(u16 data)
|
||||
{
|
||||
bool update = !m_illegal_state && (m_irr & ~(m_imr ^ data)) != 0;
|
||||
m_imr = data;
|
||||
if (update)
|
||||
set_int(int_active());
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// set_ler - write a new value to the Level/Edge
|
||||
// Register
|
||||
//-------------------------------------------------
|
||||
|
||||
void kp69_device::set_ler(u16 data)
|
||||
{
|
||||
u16 requested = m_irr & ~m_imr;
|
||||
m_irr = (m_input_levels & ~data) | (m_irr & m_ler & data);
|
||||
m_ler = data;
|
||||
if (requested != (m_irr & ~m_imr))
|
||||
set_int(int_active());
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// set_pgr - write a new value to the Priority
|
||||
// Group Register
|
||||
//-------------------------------------------------
|
||||
|
||||
void kp69_device::set_pgr(u16 data)
|
||||
{
|
||||
if (m_pgr != data)
|
||||
{
|
||||
m_pgr = data;
|
||||
if (!m_illegal_state && m_isr != 0)
|
||||
set_int(int_active());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// z80daisy_irq_state - return the overall IRQ
|
||||
// state for this device
|
||||
//-------------------------------------------------
|
||||
|
||||
int kp69_device::z80daisy_irq_state()
|
||||
{
|
||||
return m_int_active ? (Z80_DAISY_INT | Z80_DAISY_IEO) : Z80_DAISY_IEO;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// z80daisy_irq_ack - acknowledge an IRQ and
|
||||
// return the appropriate vector
|
||||
//-------------------------------------------------
|
||||
|
||||
int kp69_device::z80daisy_irq_ack()
|
||||
{
|
||||
u16 requested = m_irr & ~m_imr;
|
||||
int level = -1;
|
||||
|
||||
// Restrict to high-priority interrupts if any of those are pending
|
||||
if ((requested & m_pgr) != 0)
|
||||
{
|
||||
level = 31 - count_leading_zeros(u32(requested & m_pgr));
|
||||
assert(level >= 0 && level < 16);
|
||||
if ((1 << level) < (m_isr & m_pgr))
|
||||
level = -1;
|
||||
}
|
||||
else if (requested != 0 && (m_isr & m_pgr) == 0)
|
||||
{
|
||||
level = 31 - count_leading_zeros(u32(requested));
|
||||
assert(level >= 0 && level < 16);
|
||||
if ((1 << level) < m_isr)
|
||||
level = -1;
|
||||
}
|
||||
|
||||
if (level != -1)
|
||||
{
|
||||
u8 vector = m_ivr | (level << 1);
|
||||
if (BIT(m_ler, level))
|
||||
{
|
||||
LOG("%s: IRR[%d] acknowledged and cleared (vector = %02X)\n", machine().describe_context(), level, vector);
|
||||
m_irr &= ~(1 << level);
|
||||
}
|
||||
else
|
||||
LOG("%s: IR[%d] acknowledged (vector = %02X)\n", machine().describe_context(), level, vector);
|
||||
|
||||
m_isr |= 1 << level;
|
||||
set_int(false);
|
||||
|
||||
return vector;
|
||||
}
|
||||
|
||||
// Illegal interrupt operation: same vector as IR[0] but ISR[0] not set
|
||||
LOG("%s: Illegal interrupt at IACK (vector = %02X)\n", machine().describe_context(), m_ivr);
|
||||
m_illegal_state = true;
|
||||
set_int(false);
|
||||
return m_ivr;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// z80daisy_irq_reti - clear the interrupt
|
||||
// pending state to allow other interrupts through
|
||||
//-------------------------------------------------
|
||||
|
||||
void kp69_device::z80daisy_irq_reti()
|
||||
{
|
||||
if (m_illegal_state)
|
||||
{
|
||||
LOG("%s: End of illegal interrupt\n", machine().describe_context());
|
||||
m_illegal_state = false;
|
||||
}
|
||||
else if (m_isr != 0)
|
||||
{
|
||||
int level = 31 - count_leading_zeros(u32((m_isr & m_pgr) != 0 ? (m_isr & m_pgr) : m_isr));
|
||||
assert(level >= 0 && level < 16);
|
||||
|
||||
m_isr &= ~(1 << level);
|
||||
LOG("%s: EOI for ISR[%d]\n", machine().describe_context(), level);
|
||||
}
|
||||
else
|
||||
{
|
||||
logerror("%s: RETI before interrupt acknowledged\n", machine().describe_context());
|
||||
return;
|
||||
}
|
||||
|
||||
set_int(int_active());
|
||||
}
|
92
src/devices/cpu/z80/kp69.h
Normal file
92
src/devices/cpu/z80/kp69.h
Normal file
@ -0,0 +1,92 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:AJR
|
||||
/***************************************************************************
|
||||
|
||||
Kawasaki Steel (Kawatetsu) KP69 Interrupt Controller
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MAME_CPU_Z80_KP69_H
|
||||
#define MAME_CPU_Z80_KP69_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "machine/z80daisy.h"
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
class kp69_device : public device_t, public device_z80daisy_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
kp69_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0);
|
||||
|
||||
// callback to CPU
|
||||
auto int_callback() { return m_int_callback.bind(); }
|
||||
|
||||
// read handlers
|
||||
u8 isrl_r();
|
||||
u8 isrh_r();
|
||||
u8 imrl_r();
|
||||
u8 imrh_r();
|
||||
|
||||
// write handlers
|
||||
void lerl_pgrl_w(u8 data);
|
||||
void lerh_pgrh_w(u8 data);
|
||||
void imrl_w(u8 data);
|
||||
void ivr_imrh_w(u8 data);
|
||||
|
||||
// interrupt inputs
|
||||
template <int N> DECLARE_WRITE_LINE_MEMBER(ir_w)
|
||||
{
|
||||
static_assert(N >= 0 && N < 16, "Invalid level");
|
||||
set_input_level(N, state);
|
||||
}
|
||||
|
||||
void add_to_state(device_state_interface &state, int index);
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_resolve_objects() override;
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
// device_z80daisy_interface overrides
|
||||
virtual int z80daisy_irq_state() override;
|
||||
virtual int z80daisy_irq_ack() override;
|
||||
virtual void z80daisy_irq_reti() override;
|
||||
|
||||
private:
|
||||
// internal helpers
|
||||
bool int_active() const;
|
||||
void set_int(bool active);
|
||||
void set_input_level(int level, bool state);
|
||||
void set_irr(u16 data);
|
||||
void set_isr(u16 data);
|
||||
void set_imr(u16 data);
|
||||
void set_ler(u16 data);
|
||||
void set_pgr(u16 data);
|
||||
|
||||
// callback object
|
||||
devcb_write_line m_int_callback;
|
||||
|
||||
// internal state
|
||||
u16 m_input_levels;
|
||||
u16 m_irr;
|
||||
u16 m_isr;
|
||||
bool m_illegal_state;
|
||||
u8 m_ivr;
|
||||
bool m_ivr_written;
|
||||
u16 m_imr;
|
||||
u16 m_ler;
|
||||
u16 m_pgr;
|
||||
bool m_int_active;
|
||||
};
|
||||
|
||||
// device type declaration
|
||||
DECLARE_DEVICE_TYPE(KP69, kp69_device)
|
||||
|
||||
#endif // MAME_CPU_Z80_KP69_H
|
@ -254,10 +254,8 @@ private:
|
||||
DECLARE_WRITE_LINE_MEMBER(ddenlovr_irq);
|
||||
DECLARE_WRITE_LINE_MEMBER(mmpanic_irq);
|
||||
DECLARE_WRITE_LINE_MEMBER(mmpanic_rtc_irq);
|
||||
DECLARE_WRITE_LINE_MEMBER(hanakanz_irq);
|
||||
DECLARE_WRITE_LINE_MEMBER(funkyfig_sound_irq);
|
||||
DECLARE_WRITE_LINE_MEMBER(mjflove_irq);
|
||||
DECLARE_WRITE_LINE_MEMBER(hanakanz_rtc_irq);
|
||||
DECLARE_WRITE_LINE_MEMBER(mjflove_rtc_irq);
|
||||
|
||||
void ddenlovr_bgcolor_w(uint8_t data);
|
||||
@ -9992,34 +9990,6 @@ void ddenlovr_state::mmpanic(machine_config &config)
|
||||
0xe2 is from the 6242RTC
|
||||
*/
|
||||
|
||||
WRITE_LINE_MEMBER(ddenlovr_state::hanakanz_irq)
|
||||
{
|
||||
if (!state)
|
||||
return;
|
||||
|
||||
/* I haven't found a irq ack register, so I need this kludge to
|
||||
make sure I don't lose any interrupt generated by the blitter,
|
||||
otherwise quizchq would lock up. */
|
||||
//if (downcast<cpu_device *>(m_maincpu)->input_state(0))
|
||||
// return;
|
||||
|
||||
m_maincpu->set_input_line_and_vector(0, HOLD_LINE, 0xe0); // Z80
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(ddenlovr_state::hanakanz_rtc_irq)
|
||||
{
|
||||
if (!state)
|
||||
return;
|
||||
|
||||
/* I haven't found a irq ack register, so I need this kludge to
|
||||
make sure I don't lose any interrupt generated by the blitter,
|
||||
otherwise quizchq would lock up. */
|
||||
//if (downcast<cpu_device *>(drvm_maincpu)->input_state(0))
|
||||
// return;
|
||||
|
||||
m_maincpu->set_input_line_and_vector(0, HOLD_LINE, 0xe2); // Z80
|
||||
}
|
||||
|
||||
void ddenlovr_state::hanakanz(machine_config &config)
|
||||
{
|
||||
/* basic machine hardware */
|
||||
@ -10038,7 +10008,7 @@ void ddenlovr_state::hanakanz(machine_config &config)
|
||||
m_screen->set_visarea(0, 336-1, 5, 256-11-1);
|
||||
m_screen->set_screen_update(FUNC(ddenlovr_state::screen_update_ddenlovr));
|
||||
m_screen->set_video_attributes(VIDEO_ALWAYS_UPDATE);
|
||||
m_screen->screen_vblank().set(FUNC(ddenlovr_state::hanakanz_irq));
|
||||
m_screen->screen_vblank().set("maincpu:kp69", FUNC(kp69_device::ir_w<0>));
|
||||
|
||||
PALETTE(config, m_palette, palette_device::BLACK).set_entries(0x200);
|
||||
|
||||
@ -10054,7 +10024,7 @@ void ddenlovr_state::hanakanz(machine_config &config)
|
||||
|
||||
/* devices */
|
||||
msm6242_device &rtc(MSM6242(config, "rtc", XTAL(32'768)));
|
||||
rtc.out_int_handler().set(FUNC(ddenlovr_state::hanakanz_rtc_irq));
|
||||
rtc.out_int_handler().set("maincpu:kp69", FUNC(kp69_device::ir_w<1>));
|
||||
}
|
||||
|
||||
void ddenlovr_state::hkagerou(machine_config &config)
|
||||
@ -10083,7 +10053,7 @@ void ddenlovr_state::kotbinyo(machine_config &config)
|
||||
m_screen->set_visarea(0, 336-1-1, 1+4, 256-15-1+4);
|
||||
m_screen->set_screen_update(FUNC(ddenlovr_state::screen_update_ddenlovr));
|
||||
m_screen->set_video_attributes(VIDEO_ALWAYS_UPDATE);
|
||||
m_screen->screen_vblank().set(FUNC(ddenlovr_state::hanakanz_irq));
|
||||
m_screen->screen_vblank().set("maincpu:kp69", FUNC(kp69_device::ir_w<0>));
|
||||
|
||||
PALETTE(config, m_palette, palette_device::BLACK).set_entries(0x200);
|
||||
|
||||
@ -10098,7 +10068,7 @@ void ddenlovr_state::kotbinyo(machine_config &config)
|
||||
m_oki->add_route(ALL_OUTPUTS, "mono", 0.80);
|
||||
|
||||
/* devices */
|
||||
// MSM6242(config, "rtc", XTAL(32'768)).out_int_handler().set(FUNC(ddenlovr_state::hanakanz_rtc_irq));
|
||||
// MSM6242(config, "rtc", XTAL(32'768)).out_int_handler().set("maincpu:kp69", FUNC(kp69_device::ir_w<1>));
|
||||
}
|
||||
|
||||
void ddenlovr_state::kotbinsp(machine_config &config)
|
||||
@ -10486,7 +10456,7 @@ void ddenlovr_state::jongtei(machine_config &config)
|
||||
m_screen->set_visarea(0, 336-1, 5, 256-11-1);
|
||||
m_screen->set_screen_update(FUNC(ddenlovr_state::screen_update_ddenlovr));
|
||||
m_screen->set_video_attributes(VIDEO_ALWAYS_UPDATE);
|
||||
m_screen->screen_vblank().set(FUNC(ddenlovr_state::hanakanz_irq));
|
||||
m_screen->screen_vblank().set("maincpu:kp69", FUNC(kp69_device::ir_w<0>));
|
||||
|
||||
PALETTE(config, m_palette, palette_device::BLACK).set_entries(0x200);
|
||||
|
||||
@ -10502,7 +10472,7 @@ void ddenlovr_state::jongtei(machine_config &config)
|
||||
OKIM6295(config, m_oki, XTAL(28'636'363) / 28, okim6295_device::PIN7_HIGH).add_route(ALL_OUTPUTS, "mono", 0.80);
|
||||
|
||||
/* devices */
|
||||
MSM6242(config, "rtc", XTAL(32'768)).out_int_handler().set(FUNC(ddenlovr_state::hanakanz_rtc_irq));
|
||||
MSM6242(config, "rtc", XTAL(32'768)).out_int_handler().set("maincpu:kp69", FUNC(kp69_device::ir_w<1>));
|
||||
}
|
||||
|
||||
void ddenlovr_state::mjgnight(machine_config &config)
|
||||
@ -10700,7 +10670,7 @@ void ddenlovr_state::daimyojn(machine_config &config)
|
||||
m_screen->set_visarea(0, 336-1-1, 1, 256-15-1);
|
||||
m_screen->set_screen_update(FUNC(ddenlovr_state::screen_update_ddenlovr));
|
||||
m_screen->set_video_attributes(VIDEO_ALWAYS_UPDATE);
|
||||
m_screen->screen_vblank().set(FUNC(ddenlovr_state::hanakanz_irq));
|
||||
m_screen->screen_vblank().set("maincpu:kp69", FUNC(kp69_device::ir_w<0>));
|
||||
|
||||
PALETTE(config, m_palette, palette_device::BLACK).set_entries(0x200);
|
||||
|
||||
@ -10714,7 +10684,7 @@ void ddenlovr_state::daimyojn(machine_config &config)
|
||||
OKIM6295(config, m_oki, XTAL(28'636'363) / 28, okim6295_device::PIN7_HIGH).add_route(ALL_OUTPUTS, "mono", 0.80);
|
||||
|
||||
/* devices */
|
||||
MSM6242(config, "rtc", XTAL(32'768)).out_int_handler().set(FUNC(ddenlovr_state::hanakanz_rtc_irq));
|
||||
MSM6242(config, "rtc", XTAL(32'768)).out_int_handler().set("maincpu:kp69", FUNC(kp69_device::ir_w<1>));
|
||||
}
|
||||
|
||||
|
||||
|
@ -190,9 +190,9 @@ public:
|
||||
sigmab98_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: sigmab98_base_state(mconfig, type, tag)
|
||||
, m_maincpu(*this, "maincpu")
|
||||
, m_hopper(*this, "hopper")
|
||||
, m_nvramdev(*this, "nvram")
|
||||
, m_eeprom(*this, "eeprom")
|
||||
, m_hopper(*this, "hopper")
|
||||
, m_nvram(*this, "nvram")
|
||||
, m_leds(*this, "led%u", 0U)
|
||||
{ }
|
||||
@ -211,6 +211,8 @@ public:
|
||||
void init_ucytokyu();
|
||||
|
||||
protected:
|
||||
virtual void machine_reset() override;
|
||||
|
||||
void gegege_regs_w(offs_t offset, uint8_t data);
|
||||
uint8_t gegege_regs_r(offs_t offset);
|
||||
void gegege_regs2_w(offs_t offset, uint8_t data);
|
||||
@ -231,8 +233,6 @@ protected:
|
||||
void show_outputs();
|
||||
void eeprom_w(uint8_t data);
|
||||
|
||||
DECLARE_MACHINE_RESET(sigmab98);
|
||||
|
||||
INTERRUPT_GEN_MEMBER(sigmab98_vblank_interrupt);
|
||||
|
||||
void dashhero_io_map(address_map &map);
|
||||
@ -245,11 +245,11 @@ protected:
|
||||
|
||||
// Required devices
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<ticket_dispenser_device> m_hopper;
|
||||
|
||||
// Optional devices
|
||||
optional_device<nvram_device> m_nvramdev; // battery backed RAM (should be required, but dashhero breaks with it)
|
||||
optional_device<eeprom_serial_93cxx_device> m_eeprom;
|
||||
optional_device<ticket_dispenser_device> m_hopper;
|
||||
|
||||
// Shared pointers
|
||||
required_shared_ptr<uint8_t> m_nvram;
|
||||
@ -287,6 +287,9 @@ public:
|
||||
void init_lufykzku();
|
||||
void lufykzku(machine_config &config);
|
||||
|
||||
protected:
|
||||
virtual void machine_reset() override;
|
||||
|
||||
private:
|
||||
required_device<mb3773_device> m_watchdog;
|
||||
required_device_array<ttl165_device, 2> m_dsw_shifter;
|
||||
@ -302,8 +305,6 @@ private:
|
||||
void lufykzku_c8_w(uint8_t data);
|
||||
void lufykzku_watchdog_w(uint8_t data);
|
||||
|
||||
DECLARE_MACHINE_RESET(lufykzku);
|
||||
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(lufykzku_irq);
|
||||
|
||||
void lufykzku_io_map(address_map &map);
|
||||
@ -343,7 +344,6 @@ protected:
|
||||
private:
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(sammymdl_irq);
|
||||
|
||||
uint8_t unk_34_r();
|
||||
uint8_t coin_counter_r();
|
||||
void coin_counter_w(uint8_t data);
|
||||
uint8_t leds_r();
|
||||
@ -1323,12 +1323,6 @@ void sammymdl_state::eeprom_w(uint8_t data)
|
||||
logerror("%s: unknown eeeprom bits written %02x\n", machine().describe_context(), data);
|
||||
}
|
||||
|
||||
uint8_t sammymdl_state::unk_34_r()
|
||||
{
|
||||
// mask 0x01?
|
||||
return 0x01;
|
||||
}
|
||||
|
||||
uint8_t sigmab98_base_state::vblank_r()
|
||||
{
|
||||
// mask 0x04 must be set before writing sprite list
|
||||
@ -1433,7 +1427,6 @@ void sammymdl_state::animalc_io(address_map &map)
|
||||
map(0x30, 0x30).portr("BUTTON");
|
||||
map(0x31, 0x31).rw(FUNC(sammymdl_state::coin_counter_r), FUNC(sammymdl_state::coin_counter_w));
|
||||
map(0x32, 0x32).rw(FUNC(sammymdl_state::leds_r), FUNC(sammymdl_state::leds_w));
|
||||
map(0x34, 0x34).r(FUNC(sammymdl_state::unk_34_r));
|
||||
map(0x90, 0x90).w("oki", FUNC(okim9810_device::write));
|
||||
map(0x91, 0x91).w("oki", FUNC(okim9810_device::tmp_register_w));
|
||||
map(0x92, 0x92).r("oki", FUNC(okim9810_device::read));
|
||||
@ -1905,7 +1898,7 @@ INPUT_PORTS_END
|
||||
Sigma B-98 Games
|
||||
***************************************************************************/
|
||||
|
||||
MACHINE_RESET_MEMBER(sigmab98_state,sigmab98)
|
||||
void sigmab98_state::machine_reset()
|
||||
{
|
||||
m_rombank = 0;
|
||||
membank("rombank")->set_entry(0);
|
||||
@ -1926,8 +1919,6 @@ void sigmab98_state::sigmab98(machine_config &config)
|
||||
m_maincpu->set_addrmap(AS_IO, &sigmab98_state::gegege_io_map);
|
||||
m_maincpu->set_vblank_int("screen", FUNC(sigmab98_state::sigmab98_vblank_interrupt));
|
||||
|
||||
MCFG_MACHINE_RESET_OVERRIDE(sigmab98_state, sigmab98)
|
||||
|
||||
NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
|
||||
EEPROM_93C46_16BIT(config, "eeprom");
|
||||
|
||||
@ -1988,7 +1979,7 @@ void sigmab98_state::dashhero(machine_config &config)
|
||||
Banpresto Medal Games
|
||||
***************************************************************************/
|
||||
|
||||
MACHINE_RESET_MEMBER(lufykzku_state,lufykzku)
|
||||
void lufykzku_state::machine_reset()
|
||||
{
|
||||
m_rombank = 0;
|
||||
membank("romrambank")->set_entry(0);
|
||||
@ -2013,8 +2004,6 @@ void lufykzku_state::lufykzku(machine_config &config)
|
||||
m_maincpu->set_addrmap(AS_IO, &lufykzku_state::lufykzku_io_map);
|
||||
TIMER(config, "scantimer").configure_scanline(FUNC(lufykzku_state::lufykzku_irq), "screen", 0, 1);
|
||||
|
||||
MCFG_MACHINE_RESET_OVERRIDE(lufykzku_state, lufykzku)
|
||||
|
||||
NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0); // battery backed RAM
|
||||
// No EEPROM
|
||||
|
||||
@ -2061,15 +2050,20 @@ void lufykzku_state::lufykzku(machine_config &config)
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(sammymdl_state::sammymdl_irq)
|
||||
{
|
||||
int scanline = param;
|
||||
uint16_t irqs = 0;
|
||||
|
||||
if (scanline == 240)
|
||||
m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_vblank_vector); // Z80
|
||||
irqs |= 1 << ((m_vblank_vector & 0x1e) >> 1);
|
||||
|
||||
if (scanline == 128)
|
||||
m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_timer0_vector); // Z80
|
||||
irqs |= 1 << ((m_timer0_vector & 0x1e) >> 1);
|
||||
|
||||
if (scanline == 32)
|
||||
m_maincpu->set_input_line_and_vector(0, HOLD_LINE, m_timer1_vector); // Z80
|
||||
irqs |= 1 << ((m_timer1_vector & 0x1e) >> 1);
|
||||
|
||||
// FIXME: this is not much less of a hack than HOLD_LINE
|
||||
if (irqs != 0)
|
||||
m_maincpu->set_state_int(kl5c80a12_device::KP69_IRR, m_maincpu->state_int(kl5c80a12_device::KP69_IRR) | irqs);
|
||||
}
|
||||
|
||||
void sammymdl_state::sammymdl(machine_config &config)
|
||||
|
Loading…
Reference in New Issue
Block a user