kl5c80a12: Emulate interrupt controller

This commit is contained in:
AJR 2020-07-27 14:22:58 -04:00
parent f5191273ac
commit 4aae75d753
7 changed files with 611 additions and 64 deletions

View File

@ -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",
}

View File

@ -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);
}

View File

@ -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;
};

View 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());
}

View 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

View File

@ -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>));
}

View File

@ -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)