summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/video/imagetek_i4100.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/video/imagetek_i4100.cpp')
-rw-r--r--src/devices/video/imagetek_i4100.cpp140
1 files changed, 134 insertions, 6 deletions
diff --git a/src/devices/video/imagetek_i4100.cpp b/src/devices/video/imagetek_i4100.cpp
index cba8a4b4034..f760f148254 100644
--- a/src/devices/video/imagetek_i4100.cpp
+++ b/src/devices/video/imagetek_i4100.cpp
@@ -71,6 +71,12 @@
#include <algorithm>
+#define LOG_INT (1 << 1U)
+//#define VERBOSE (LOG_INT)
+#include "logmacro.h"
+
+#define LOGINT(...) LOGMASKED(LOG_INT, __VA_ARGS__)
+
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
@@ -156,6 +162,8 @@ void imagetek_i4100_device::map(address_map &map)
map(0x78880, 0x78881).w(FUNC(imagetek_i4100_device::crtc_vert_w));
map(0x78890, 0x78891).w(FUNC(imagetek_i4100_device::crtc_horz_w));
map(0x788a0, 0x788a1).w(FUNC(imagetek_i4100_device::crtc_unlock_w));
+ map(0x788a3, 0x788a3).rw(FUNC(imagetek_i4100_device::irq_cause_r), FUNC(imagetek_i4100_device::irq_cause_w));
+ map(0x788a5, 0x788a5).w(FUNC(imagetek_i4100_device::irq_enable_w));
map(0x788aa, 0x788ab).w(FUNC(imagetek_i4100_device::rombank_w));
map(0x788ac, 0x788ad).w(FUNC(imagetek_i4100_device::screen_ctrl_w));
}
@@ -184,6 +192,8 @@ void imagetek_i4220_device::v2_map(address_map &map)
map(0x78880, 0x78881).w(FUNC(imagetek_i4220_device::crtc_vert_w));
map(0x78890, 0x78891).w(FUNC(imagetek_i4220_device::crtc_horz_w));
map(0x788a0, 0x788a1).w(FUNC(imagetek_i4220_device::crtc_unlock_w));
+ map(0x788a3, 0x788a3).rw(FUNC(imagetek_i4220_device::irq_cause_r), FUNC(imagetek_i4220_device::irq_cause_w));
+ map(0x788a5, 0x788a5).w(FUNC(imagetek_i4220_device::irq_enable_w));
map(0x788aa, 0x788ab).w(FUNC(imagetek_i4220_device::rombank_w));
map(0x788ac, 0x788ad).w(FUNC(imagetek_i4220_device::screen_ctrl_w));
@@ -228,6 +238,11 @@ void imagetek_i4300_device::v3_map(address_map &map)
map(0x78802, 0x78803).w(FUNC(imagetek_i4300_device::crtc_horz_w));
map(0x78804, 0x78805).w(FUNC(imagetek_i4300_device::crtc_vert_w));
+ map(0x78810, 0x7881f).w(FUNC(imagetek_i4300_device::irq_level_w)).umask16(0x00ff);
+ map(0x78820, 0x7882f).w(FUNC(imagetek_i4300_device::irq_vector_w)).umask16(0x00ff);
+ map(0x78831, 0x78831).w(FUNC(imagetek_i4300_device::irq_enable_w));
+ map(0x78833, 0x78833).rw(FUNC(imagetek_i4300_device::irq_cause_r), FUNC(imagetek_i4300_device::irq_cause_w));
+
map(0x78840, 0x7884d).w(FUNC(imagetek_i4300_device::blitter_w)).share("blitter_regs");
map(0x78850, 0x7885b).rw(FUNC(imagetek_i4300_device::scroll_r), FUNC(imagetek_i4300_device::scroll_w)).share("scrollregs");
map(0x78860, 0x7886b).rw(FUNC(imagetek_i4300_device::window_r), FUNC(imagetek_i4300_device::window_w)).share("windowregs");
@@ -266,7 +281,9 @@ imagetek_i4100_device::imagetek_i4100_device(const machine_config &mconfig, devi
, m_scroll(*this, "scrollregs")
, m_palette(*this, "palette")
, m_gfxrom(*this, DEVICE_SELF)
- , m_blit_irq_cb(*this)
+ , m_irq_cb(*this)
+ , m_vblank_irq_level(-1)
+ , m_blit_irq_level(-1)
, m_support_8bpp(has_ext_tiles)
, m_support_16x16(has_ext_tiles)
, m_tilemap_scrolldx{0, 0, 0}
@@ -291,6 +308,8 @@ imagetek_i4220_device::imagetek_i4220_device(const machine_config &mconfig, cons
imagetek_i4300_device::imagetek_i4300_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: imagetek_i4100_device(mconfig, I4300, tag, owner, clock, true)
{
+ std::fill(std::begin(m_irq_levels), std::end(m_irq_levels), 0);
+ std::fill(std::begin(m_irq_vectors), std::end(m_irq_vectors), 0);
}
//-------------------------------------------------
@@ -335,6 +354,8 @@ void imagetek_i4100_device::device_start()
m_screen_blank = false;
m_screen_flip = false;
+ save_item(NAME(m_requested_int));
+ save_item(NAME(m_irq_enable));
save_item(NAME(m_rombank));
save_item(NAME(m_crtc_unlock));
save_item(NAME(m_sprite_count));
@@ -357,13 +378,21 @@ void imagetek_i4100_device::device_start()
m_gfxrom_size = m_gfxrom.bytes();
- m_blit_irq_cb.resolve_safe();
+ m_irq_cb.resolve_safe();
m_blit_done_timer = timer_alloc(TIMER_BLIT_END);
m_spritelist = std::make_unique<sprite_t []>(0x1000 / 8);
m_sprite_end = m_spritelist.get();
}
+void imagetek_i4300_device::device_start()
+{
+ imagetek_i4100_device::device_start();
+
+ save_item(NAME(m_irq_levels));
+ save_item(NAME(m_irq_vectors));
+}
+
//-------------------------------------------------
// device_reset - device-specific reset
@@ -371,6 +400,8 @@ void imagetek_i4100_device::device_start()
void imagetek_i4100_device::device_reset()
{
+ m_requested_int = 0;
+ m_irq_enable = 0xff;
m_rombank = 0;
m_crtc_unlock = false;
m_sprite_count = 0;
@@ -378,6 +409,7 @@ void imagetek_i4100_device::device_reset()
m_sprite_xoffset = 0;
m_sprite_yoffset = 0;
m_sprite_color_code = 0;
+ update_irq_state();
for(int i=0; i != 3; i++) {
m_layer_priority[i] = 0;
@@ -393,13 +425,108 @@ void imagetek_i4100_device::device_reset()
expand_gfx1();
}
+//**************************************************************************
+// INTERRUPTS
+//**************************************************************************
+
+u8 imagetek_i4100_device::irq_cause_r()
+{
+ /* interrupt cause, used by
+
+ int[0] vblank
+ int[1] hblank (bangball for faster intermission skip,
+ puzzli for gameplay water effect,
+ blzntrnd title screen scroll (enabled all the time then?),
+ unused/empty in balcube, daitoride, karatour,
+ unchecked mouja & other i4300 games )
+ int[2] blitter
+ int[3] ? KARATOUR
+ int[4] ?
+ int[5] ? KARATOUR, BLZNTRND
+ int[6] unused
+ int[7] unused
+
+ */
+
+ return m_requested_int;
+}
+
+void imagetek_i4100_device::irq_cause_w(u8 data)
+{
+ if ((m_requested_int & data) == 0)
+ return;
+
+ LOGINT("%s: Interrupts acknowledged (%02X)\n", machine().describe_context(), data);
+ m_requested_int &= ~data;
+ update_irq_state();
+}
+
+void imagetek_i4100_device::set_irq(int level)
+{
+ if (!BIT(m_requested_int, level))
+ {
+ LOGINT("IRQ %d set\n", level);
+ m_requested_int |= 1 << level;
+ update_irq_state();
+ }
+}
+
+void imagetek_i4100_device::clear_irq(int level)
+{
+ if (BIT(m_requested_int, level))
+ {
+ LOGINT("IRQ %d cleared\n", level);
+ m_requested_int &= ~(1 << level);
+ update_irq_state();
+ }
+}
+
+void imagetek_i4100_device::update_irq_state()
+{
+ m_irq_cb((m_requested_int & ~m_irq_enable) ? ASSERT_LINE : CLEAR_LINE);
+}
+
+void imagetek_i4100_device::irq_enable_w(u8 data)
+{
+ LOGINT("%s: IRQ enable register = %02X\n", machine().describe_context(), data);
+ m_irq_enable = data;
+ update_irq_state();
+}
+
+void imagetek_i4300_device::irq_level_w(offs_t offset, u8 data)
+{
+ m_irq_levels[offset] = data;
+}
+
+void imagetek_i4300_device::irq_vector_w(offs_t offset, u8 data)
+{
+ m_irq_vectors[offset] = data;
+}
+
+u8 imagetek_i4300_device::irq_vector_r(offs_t offset)
+{
+ return m_irq_vectors[offset];
+}
+
+void imagetek_i4300_device::update_irq_state()
+{
+ u8 irqs = m_requested_int & ~m_irq_enable;
+
+ int level = 0;
+ for (int i = 0; i < 8; i++)
+ if (BIT(irqs, i))
+ level = std::max(level, m_irq_levels[i] & 7);
+
+ m_irq_cb(level);
+}
void imagetek_i4100_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
switch (id)
{
case TIMER_BLIT_END:
- m_blit_irq_cb(ASSERT_LINE);
+ if (m_blit_irq_level != -1)
+ set_irq(m_blit_irq_level);
break;
}
}
@@ -1295,9 +1422,10 @@ WRITE_LINE_MEMBER(imagetek_i4100_device::screen_eof)
{
if (state)
{
- if (!m_spriteram_buffered)
- return;
+ if (m_vblank_irq_level != -1)
+ set_irq(m_vblank_irq_level);
- m_spriteram->copy();
+ if (m_spriteram_buffered)
+ m_spriteram->copy();
}
}