summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--src/mame/igs/igs023_video.cpp501
-rw-r--r--src/mame/igs/igs023_video.h55
-rw-r--r--src/mame/igs/igs_68k_023vid.cpp19
-rw-r--r--src/mame/igs/igs_m027_023vid.cpp16
-rw-r--r--src/mame/igs/pgm.cpp31
5 files changed, 349 insertions, 273 deletions
diff --git a/src/mame/igs/igs023_video.cpp b/src/mame/igs/igs023_video.cpp
index db7bb50290c..8aa99b3e98a 100644
--- a/src/mame/igs/igs023_video.cpp
+++ b/src/mame/igs/igs023_video.cpp
@@ -1,8 +1,19 @@
// license:BSD-3-Clause
// copyright-holders:David Haywood
-// IGS023 (PGM) style video
+/*
+IGS023 (PGM) style video
+
+Used by:
+- igs/pgm.cpp
+- igs/igs_68k_023vid.cpp
+- igs/igs_m027_023vid.cpp
+
+TODO:
+- Interrupt handling and background scaling are not implemented
+- Is video register area mirrored?
+*/
#include "emu.h"
#include "igs023_video.h"
@@ -10,6 +21,15 @@
#include "screen.h"
+#define LOG_UNK (1U << 1)
+
+#define LOG_ALL (LOG_UNK)
+
+#define VERBOSE (0)
+#include "logmacro.h"
+
+#define LOGUNK(...) LOGMASKED(LOG_UNK, __VA_ARGS__)
+
namespace {
const gfx_layout pgm32_charlayout =
@@ -28,15 +48,40 @@ constexpr bool get_flipx(u8 flip) { return BIT(flip, 0); }
} // anonymous namespace
+void igs023_video_device::videoram_map(address_map &map)
+{
+ map(0x0000, 0x0fff).mirror(0x3000).rw(FUNC(igs023_video_device::bg_videoram_r), FUNC(igs023_video_device::bg_videoram_w));
+ map(0x4000, 0x5fff).mirror(0x2000).rw(FUNC(igs023_video_device::tx_videoram_r), FUNC(igs023_video_device::tx_videoram_w));
+ map(0x7000, 0x7fff).rw(FUNC(igs023_video_device::rowscrollram_r), FUNC(igs023_video_device::rowscrollram_w));
+}
+
+void igs023_video_device::videoregs_map(address_map &map)
+{
+ map(0x0000, 0x0fff).rw(FUNC(igs023_video_device::spritebuffer_r), FUNC(igs023_video_device::spritebuffer_w)); // read only?
+ map(0x1000, 0x103f).w(FUNC(igs023_video_device::zoomram_w));
+ map(0x2000, 0x2001).rw(FUNC(igs023_video_device::bg_yscroll_r), FUNC(igs023_video_device::bg_yscroll_w));
+ map(0x3000, 0x3001).rw(FUNC(igs023_video_device::bg_xscroll_r), FUNC(igs023_video_device::bg_xscroll_w));
+ map(0x4000, 0x4001).rw(FUNC(igs023_video_device::bg_scale_r), FUNC(igs023_video_device::bg_scale_w));
+ map(0x5000, 0x5001).rw(FUNC(igs023_video_device::tx_yscroll_r), FUNC(igs023_video_device::tx_yscroll_w));
+ map(0x6000, 0x6001).rw(FUNC(igs023_video_device::tx_xscroll_r), FUNC(igs023_video_device::tx_xscroll_w));
+ map(0x7000, 0x7001).lr16(NAME([this]() -> u16 { return screen().vpos(); }));
+ map(0xe000, 0xe001).rw(FUNC(igs023_video_device::ctrl_r), FUNC(igs023_video_device::ctrl_w));
+}
DEFINE_DEVICE_TYPE(IGS023_VIDEO, igs023_video_device, "igs023", "IGS023 Video System")
igs023_video_device::igs023_video_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, IGS023_VIDEO, tag, owner, clock)
, device_gfx_interface(mconfig, *this, gfxinfo)
+ , device_video_interface(mconfig, *this)
, m_gfx_region(*this, DEVICE_SELF)
, m_adata(*this, "sprcol")
, m_bdata(*this, "sprmask")
+ , m_bg_videoram(*this, "bg_videoram", 0x1000, ENDIANNESS_BIG) // or 0x4000?
+ , m_tx_videoram(*this, "tx_videoram", 0x2000, ENDIANNESS_BIG)
+ , m_rowscrollram(*this, "rowscrollram", 0x1000, ENDIANNESS_BIG)
+ , m_spritebuffer(*this, "spritebuffer", 0x1000, ENDIANNESS_BIG)
+ , m_zoomram(*this, "zoomram", 0x40, ENDIANNESS_BIG)
, m_readspriteram_cb(*this, 0)
, m_sprite_ptr_pre(nullptr)
, m_bg_tilemap(nullptr)
@@ -44,9 +89,12 @@ igs023_video_device::igs023_video_device(const machine_config &mconfig, const ch
, m_aoffset(0)
, m_abit(0)
, m_boffset(0)
- , m_bg_videoram(nullptr)
- , m_tx_videoram(nullptr)
- , m_rowscrollram(nullptr)
+ , m_bg_yscroll(0)
+ , m_bg_xscroll(0)
+ , m_bg_scale(0)
+ , m_tx_yscroll(0)
+ , m_tx_xscroll(0)
+ , m_ctrl(0)
{
}
@@ -56,38 +104,147 @@ GFXDECODE_MEMBER( igs023_video_device::gfxinfo )
GFXDECODE_END
+// video RAM
+u16 igs023_video_device::bg_videoram_r(offs_t offset)
+{
+ return m_bg_videoram[offset];
+}
+
+void igs023_video_device::bg_videoram_w(offs_t offset, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_bg_videoram[offset]);
+ m_bg_tilemap->mark_tile_dirty(offset / 2);
+}
-u16 igs023_video_device::videoregs_r(offs_t offset)
+u16 igs023_video_device::tx_videoram_r(offs_t offset)
{
- return m_videoregs[offset];
+ return m_tx_videoram[offset];
}
-void igs023_video_device::videoregs_w(offs_t offset, u16 data, u16 mem_mask)
+void igs023_video_device::tx_videoram_w(offs_t offset, u16 data, u16 mem_mask)
{
- COMBINE_DATA(&m_videoregs[offset]);
+ COMBINE_DATA(&m_tx_videoram[offset]);
+ m_tx_tilemap->mark_tile_dirty(offset / 2);
}
-u16 igs023_video_device::videoram_r(offs_t offset)
+u16 igs023_video_device::rowscrollram_r(offs_t offset)
{
- if (offset < 0x4000 / 2)
- return m_bg_videoram[offset & 0x7ff];
- else if (offset < 0x7000 / 2)
- return m_tx_videoram[offset & 0xfff];
- else
- return m_videoram[offset];
+ return m_rowscrollram[offset];
}
-void igs023_video_device::videoram_w(offs_t offset, u16 data, u16 mem_mask)
+void igs023_video_device::rowscrollram_w(offs_t offset, u16 data, u16 mem_mask)
{
- if (offset < 0x4000 / 2)
- bg_videoram_w(offset & 0x7ff, data, mem_mask);
- else if (offset < 0x7000 / 2)
- tx_videoram_w(offset & 0xfff, data, mem_mask);
- else
- COMBINE_DATA(&m_videoram[offset]);
+ COMBINE_DATA(&m_rowscrollram[offset]);
+}
+
+// video registers
+u16 igs023_video_device::spritebuffer_r(offs_t offset)
+{
+ return m_spritebuffer[offset];
+}
+
+void igs023_video_device::spritebuffer_w(offs_t offset, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_spritebuffer[offset]);
+}
+
+void igs023_video_device::zoomram_w(offs_t offset, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_zoomram[offset]);
+}
+
+u16 igs023_video_device::bg_yscroll_r()
+{
+ return m_bg_yscroll;
+}
+
+void igs023_video_device::bg_yscroll_w(offs_t offset, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_bg_yscroll);
+}
+
+u16 igs023_video_device::bg_xscroll_r()
+{
+ return m_bg_xscroll;
+}
+
+void igs023_video_device::bg_xscroll_w(offs_t offset, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_bg_xscroll);
+}
+
+u16 igs023_video_device::bg_scale_r()
+{
+ return m_bg_scale;
+}
+
+void igs023_video_device::bg_scale_w(offs_t offset, u16 data, u16 mem_mask)
+{
+ /*
+ Background scale register format
+
+ Bit Description
+ fedc ba98 7654 3210
+ ---- --xx xxx- ---- Vertical scale
+ ---- ---- ---x xxxx Horizontal scale
+
+ * Scale range is 50% to 200%, 0b10000 being 100%
+ * Unmarked bits are can be set but unknown and/or unused
+ TODO: not implemented, unknown algorithm
+ */
+ COMBINE_DATA(&m_bg_scale);
+ if (m_bg_scale != 0x210)
+ LOGUNK("%s: Unknown bg_scale_w write %04x & %04x", machine().describe_context(), data, mem_mask);
+}
+
+u16 igs023_video_device::tx_yscroll_r()
+{
+ return m_tx_yscroll;
+}
+
+void igs023_video_device::tx_yscroll_w(offs_t offset, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_tx_yscroll);
+ m_tx_tilemap->set_scrolly(0, m_tx_yscroll);
+}
+
+u16 igs023_video_device::tx_xscroll_r()
+{
+ return m_tx_xscroll;
+}
+
+void igs023_video_device::tx_xscroll_w(offs_t offset, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_tx_xscroll);
+ m_tx_tilemap->set_scrollx(0, m_tx_xscroll);
}
+u16 igs023_video_device::ctrl_r()
+{
+ return m_ctrl;
+}
+void igs023_video_device::ctrl_w(offs_t offset, u16 data, u16 mem_mask)
+{
+ const u16 prev = m_ctrl;
+ /*
+ Control register format
+
+ Bit Description
+ fedc ba98 7654 3210
+ --x- ---- ---- ---- Disable high priority sprites
+ ---x ---- ---- ---- Disable background layer
+ ---- x--- ---- ---- Disable text layer
+ ---- ---- ---- x--- enable interrupt triggered each VBlank
+ ---- ---- ---- -x-- enable interrupt triggered every 62 scanlines (Not synced with VBlank)
+ ---- ---- ---- ---x Sprite DMA enable
+
+ * Unmarked bits are can be set but unknown and/or unused
+ */
+ COMBINE_DATA(&m_ctrl);
+ if ((prev ^ m_ctrl) & 0xc7f2)
+ LOGUNK("%s: Unknown ctrl_w write %04x & %04x", machine().describe_context(), data, mem_mask);
+}
/******************************************************************************
@@ -108,50 +265,14 @@ inline void igs023_video_device::pgm_draw_pix(int xdrawpos, int pri, u16 *dest,
{
if (!(destpri[xdrawpos] & 1))
{
- if (!pri)
- {
+ if ((!pri) || (!(destpri[xdrawpos] & 2)))
dest[xdrawpos] = srcdat;
- }
- else
- {
- if (!(destpri[xdrawpos] & 2))
- {
- dest[xdrawpos] = srcdat;
- }
- }
}
destpri[xdrawpos] |= 1;
}
}
-inline void igs023_video_device::pgm_draw_pix_nopri(int xdrawpos, u16 *dest, u8 *destpri, const rectangle &cliprect, u16 srcdat)
-{
- if ((xdrawpos >= cliprect.min_x) && (xdrawpos <= cliprect.max_x))
- {
- if (!(destpri[xdrawpos] & 1))
- {
- dest[xdrawpos] = srcdat;
- }
- destpri[xdrawpos] |= 1;
- }
-}
-
-inline void igs023_video_device::pgm_draw_pix_pri(int xdrawpos, u16 *dest, u8 *destpri, const rectangle &cliprect, u16 srcdat)
-{
- if ((xdrawpos >= cliprect.min_x) && (xdrawpos <= cliprect.max_x))
- {
- if (!(destpri[xdrawpos] & 1))
- {
- if (!(destpri[xdrawpos] & 2))
- {
- dest[xdrawpos] = srcdat;
- }
- }
- destpri[xdrawpos] |= 1;
- }
-}
-
inline u8 igs023_video_device::get_sprite_pix()
{
const u8 srcdat = ((m_adata[m_aoffset & (m_adata.length() - 1)] >> m_abit) & 0x1f);
@@ -169,6 +290,18 @@ inline u8 igs023_video_device::get_sprite_pix()
for complex zoomed cases
*************************************************************************/
+inline void igs023_video_device::draw_sprite_pixel(int &xdrawpos, int &xcntdraw, u16 *dest, u8 *destpri, const rectangle &cliprect, int xpos, int flip, int pri, int realxsize, u16 srcdat)
+{
+ if (!get_flipx(flip))
+ xdrawpos = xpos + xcntdraw;
+ else
+ xdrawpos = xpos + realxsize - xcntdraw;
+
+ pgm_draw_pix(xdrawpos, pri, dest, destpri, cliprect, srcdat);
+
+ xcntdraw++;
+}
+
void igs023_video_device::draw_sprite_line(int wide, u16 *dest, u8 *destpri, const rectangle &cliprect, int xzoom, bool xgrow, int flip, int xpos, int pri, int realxsize, int palt, bool draw)
{
int xoffset = 0;
@@ -181,61 +314,29 @@ void igs023_video_device::draw_sprite_line(int wide, u16 *dest, u8 *destpri, con
for (int x = 0; x < 16; x++)
{
+ const bool xzoombit = BIT(xzoom, xoffset & 0x1f);
+ xoffset++;
+
if (!(BIT(msk, 0)))
{
const u16 srcdat = get_sprite_pix() + palt * 32;
if (draw)
{
- const bool xzoombit = BIT(xzoom, xoffset & 0x1f);
- xoffset++;
-
- if (xzoombit && xgrow)
- { // double this column
-
- if (!get_flipx(flip))
- xdrawpos = xpos + xcntdraw;
- else
- xdrawpos = xpos + realxsize - xcntdraw;
-
- pgm_draw_pix(xdrawpos, pri, dest, destpri, cliprect, srcdat);
-
- xcntdraw++;
-
- if (!get_flipx(flip))
- xdrawpos = xpos + xcntdraw;
- else
- xdrawpos = xpos + realxsize - xcntdraw;
-
- pgm_draw_pix(xdrawpos, pri, dest, destpri, cliprect, srcdat);
-
- xcntdraw++;
- }
- else if (xzoombit && (!xgrow))
+ if (xgrow || (!xzoombit))
{
- /* skip this column */
- }
- else //normal column
- {
- if (!get_flipx(flip))
- xdrawpos = xpos + xcntdraw;
- else
- xdrawpos = xpos + realxsize - xcntdraw;
-
- pgm_draw_pix(xdrawpos, pri, dest, destpri, cliprect, srcdat);
-
- xcntdraw++;
+ const int pixel_column = xzoombit ? 2 : 1;
+ for (int i = 0; i < pixel_column; i++)
+ {
+ draw_sprite_pixel(xdrawpos, xcntdraw, dest, destpri, cliprect, xpos, flip, pri, realxsize, srcdat);
+ }
}
}
-
}
else
{
- const bool xzoombit = BIT(xzoom, xoffset & 0x1f);
- xoffset++;
- if (xzoombit && xgrow) { xcntdraw += 2; }
- else if (xzoombit && (!xgrow)) { }
- else { xcntdraw++; }
+ if (xgrow || (!xzoombit))
+ xcntdraw += xzoombit ? 2 : 1;
}
msk >>= 1;
@@ -267,9 +368,8 @@ void igs023_video_device::draw_sprite_new_zoomed(int wide, int high, int xpos, i
while (ycnt < high)
{
const bool yzoombit = BIT(yzoom, ycnt & 0x1f);
- if (yzoombit && ygrow) { realysize += 2; }
- else if (yzoombit && (!ygrow)) { }
- else { realysize++; };
+ if (ygrow || (!yzoombit))
+ realysize += yzoombit ? 2 : 1;
ycnt++;
}
@@ -280,9 +380,8 @@ void igs023_video_device::draw_sprite_new_zoomed(int wide, int high, int xpos, i
while (xcnt < wide * 16)
{
const bool xzoombit = BIT(xzoom, xcnt & 0x1f);
- if (xzoombit && xgrow) { realxsize += 2; }
- else if (xzoombit && (!xgrow)) { }
- else { realxsize++; };
+ if (xgrow || (!xzoombit))
+ realxsize += xzoombit ? 2 : 1;
xcnt++;
}
@@ -403,77 +502,26 @@ void igs023_video_device::draw_sprite_line_basic(int wide, u16 *dest, u8 *destpr
int xdrawpos = 0;
int xcntdraw = 0;
- if (!pri)
+ for (int xcnt = 0; xcnt < wide; xcnt++)
{
- for (int xcnt = 0; xcnt < wide; xcnt++)
- {
- u16 msk = m_bdata[m_boffset & (m_bdata.length() - 1)];
-
- for (int x = 0; x < 16; x++)
- {
- if (!(BIT(msk, 0)))
- {
- const u16 srcdat = get_sprite_pix() + palt * 32;
-
- if (draw)
- {
- if (!get_flipx(flip))
- xdrawpos = xpos + xcntdraw;
- else
- xdrawpos = xpos + realxsize - xcntdraw;
-
- pgm_draw_pix_nopri(xdrawpos, dest, destpri, cliprect, srcdat);
-
- xcntdraw++;
- }
-
- }
- else
- {
- xcntdraw++;
- }
-
- msk >>= 1;
- }
+ u16 msk = m_bdata[m_boffset & (m_bdata.length() - 1)];
- m_boffset++;
- }
- }
- else
- {
- for (int xcnt = 0; xcnt < wide; xcnt++)
+ for (int x = 0; x < 16; x++)
{
- u16 msk = m_bdata[m_boffset & (m_bdata.length() - 1)];
-
- for (int x = 0; x < 16; x++)
+ if (!(BIT(msk, 0)))
{
- if (!(BIT(msk, 0)))
- {
- const u16 srcdat = get_sprite_pix() + palt * 32;
-
- if (draw)
- {
- if (!get_flipx(flip))
- xdrawpos = xpos + xcntdraw;
- else
- xdrawpos = xpos + realxsize - xcntdraw;
-
- pgm_draw_pix_pri(xdrawpos, dest, destpri, cliprect, srcdat);
-
- xcntdraw++;
- }
-
- }
- else
- {
- xcntdraw++;
- }
+ const u16 srcdat = get_sprite_pix() + palt * 32;
- msk >>= 1;
+ if (draw)
+ draw_sprite_pixel(xdrawpos, xcntdraw, dest, destpri, cliprect, xpos, flip, pri, realxsize, srcdat);
}
+ else
+ xcntdraw++;
- m_boffset++;
+ msk >>= 1;
}
+
+ m_boffset++;
}
}
@@ -541,6 +589,9 @@ void igs023_video_device::draw_sprites(bitmap_ind16& spritebitmap, const rectang
{
sprite_ptr--;
+ if (BIT(m_ctrl, 13) && (!sprite_ptr->pri))
+ continue;
+
m_boffset = sprite_ptr->offs;
if ((!sprite_ptr->xzoom) && (!sprite_ptr->yzoom))
{
@@ -572,7 +623,7 @@ void igs023_video_device::draw_sprites(bitmap_ind16& spritebitmap, const rectang
02 x------- -------- Vertical Zoom/Shrink mode select
-xxxx--- -------- Vertical Zoom/Shrink table select
- -----xxx xxxxxxxx Y position (10 bit signed)
+ ------xx xxxxxxxx Y position (10 bit signed)
04 -x------ -------- Flip Y
--x----- -------- Flip X
@@ -588,33 +639,34 @@ void igs023_video_device::draw_sprites(bitmap_ind16& spritebitmap, const rectang
*/
void igs023_video_device::get_sprites()
{
- m_sprite_ptr_pre = m_spritelist.get();
+ if (!sprite_dma())
+ return;
- u16 const *const sprite_zoomtable = &m_videoregs[0x1000 / 2];
+ m_sprite_ptr_pre = m_spritelist.get();
int sprite_num = 0;
- while (sprite_num < 0xa00/2)
+ while (sprite_num < 0x1000/2)
{
- const u16 spr4 = m_readspriteram_cb(sprite_num + 4);
- if (!spr4) break; /* is this right? */
+ const u16 spr4 = m_spritebuffer[sprite_num + 4];
+ if ((spr4 & 0x7fff) == 0) break; // verified on hardware
- const u16 spr0 = m_readspriteram_cb(sprite_num + 0);
+ const u16 spr0 = m_spritebuffer[sprite_num + 0];
+ const bool xgrow = BIT(spr0, 15);
int xzom = (spr0 & 0x7800) >> 11;
- const bool xgrow = (spr0 & 0x8000) >> 15;
- m_sprite_ptr_pre->x = (spr0 & 0x03ff) - (spr0 & 0x0400);
+ m_sprite_ptr_pre->x = util::sext(spr0 & 0x07ff, 11);
- const u16 spr1 = m_readspriteram_cb(sprite_num + 1);
+ const u16 spr1 = m_spritebuffer[sprite_num + 1];
+ const bool ygrow = BIT(spr1, 15);
int yzom = (spr1 & 0x7800) >> 11;
- const bool ygrow = (spr1 & 0x8000) >> 15;
- m_sprite_ptr_pre->y = (spr1 & 0x01ff) - (spr1 & 0x0200);
+ m_sprite_ptr_pre->y = util::sext(spr1 & 0x03ff, 10);
- const u16 spr2 = m_readspriteram_cb(sprite_num + 2);
- const u16 spr3 = m_readspriteram_cb(sprite_num + 3);
+ const u16 spr2 = m_spritebuffer[sprite_num + 2];
+ const u16 spr3 = m_spritebuffer[sprite_num + 3];
m_sprite_ptr_pre->flip = (spr2 & 0x6000) >> 13;
m_sprite_ptr_pre->color = (spr2 & 0x1f00) >> 8;
- m_sprite_ptr_pre->pri = (spr2 & 0x0080) >> 7;
+ m_sprite_ptr_pre->pri = BIT(spr2, 7);
m_sprite_ptr_pre->offs = ((spr2 & 0x007f) << 16) | (spr3 & 0xffff);
m_sprite_ptr_pre->width = (spr4 & 0x7e00) >> 9;
@@ -634,29 +686,23 @@ void igs023_video_device::get_sprites()
// some games (e.g. ddp3) have zero in last zoom table entry but expect 1
// is the last entry hard-coded to 1, or does zero have the same effect as 1?
- m_sprite_ptr_pre->xzoom = (xzom == 0xf) ? 1 : ((u32(sprite_zoomtable[xzom * 2]) << 16) | sprite_zoomtable[xzom * 2 + 1]);
- m_sprite_ptr_pre->yzoom = (yzom == 0xf) ? 1 : ((u32(sprite_zoomtable[yzom * 2]) << 16) | sprite_zoomtable[yzom * 2 + 1]);
+ m_sprite_ptr_pre->xzoom = (xzom < 0x10) ? (xzom == 0xf) ? 1 : ((u32(m_zoomram[xzom * 2]) << 16) | m_zoomram[xzom * 2 + 1]) : 0;
+ m_sprite_ptr_pre->yzoom = (yzom < 0x10) ? (yzom == 0xf) ? 1 : ((u32(m_zoomram[yzom * 2]) << 16) | m_zoomram[yzom * 2 + 1]) : 0;
m_sprite_ptr_pre->xgrow = xgrow;
m_sprite_ptr_pre->ygrow = ygrow;
m_sprite_ptr_pre++;
- sprite_num += 5;
+ sprite_num += 8;
}
}
/* TX Layer */
-void igs023_video_device::tx_videoram_w(offs_t offset, u16 data, u16 mem_mask)
-{
- m_tx_videoram[offset] = data;
- m_tx_tilemap->mark_tile_dirty(offset / 2);
-}
-
TILE_GET_INFO_MEMBER(igs023_video_device::get_tx_tile_info)
{
/* 0x904000 - 0x90ffff is the Text Overlay Ram (pgm_tx_videoram)
each tile uses 4 bytes, the tilemap is 64x128?
the layer uses 4bpp 8x8 tiles from the 'T' roms
- colours from 0xA01000 - 0xA017FF
+ colours from 0xA01000 - 0xA013FF
scroll registers are at 0xB05000 (Y) and 0xB06000 (X)
@@ -670,17 +716,11 @@ TILE_GET_INFO_MEMBER(igs023_video_device::get_tx_tile_info)
const u32 colour = (m_tx_videoram[tile_index * 2 + 1] & 0x3e) >> 1;
const u8 flipyx = (m_tx_videoram[tile_index * 2 + 1] & 0xc0) >> 6;
- tileinfo.set(0,tileno,colour,TILE_FLIPYX(flipyx));
+ tileinfo.set(0, tileno, colour, TILE_FLIPYX(flipyx));
}
/* BG Layer */
-void igs023_video_device::bg_videoram_w(offs_t offset, u16 data, u16 mem_mask)
-{
- m_bg_videoram[offset] = data;
- m_bg_tilemap->mark_tile_dirty(offset / 2);
-}
-
TILE_GET_INFO_MEMBER(igs023_video_device::get_bg_tile_info)
{
/* pretty much the same as tx layer */
@@ -689,23 +729,13 @@ TILE_GET_INFO_MEMBER(igs023_video_device::get_bg_tile_info)
const u32 colour = (m_bg_videoram[tile_index * 2 + 1] & 0x3e) >> 1;
const u8 flipyx = (m_bg_videoram[tile_index * 2 + 1] & 0xc0) >> 6;
- tileinfo.set(1,tileno,colour,TILE_FLIPYX(flipyx));
+ tileinfo.set(1, tileno, colour, TILE_FLIPYX(flipyx));
}
void igs023_video_device::device_start()
{
- m_videoram = make_unique_clear<uint16_t []>(0x8000/2);
- m_videoregs = make_unique_clear<uint16_t []>(0x10000/2);
-
- save_pointer(NAME(m_videoram), 0x8000/2);
- save_pointer(NAME(m_videoregs), 0x10000/2);
-
- m_bg_videoram = &m_videoram[0];
- m_tx_videoram = &m_videoram[0x4000/2];
- m_rowscrollram = &m_videoram[0x7000/2];
-
// assumes it can make an address mask with .length() - 1 on these
assert(!(m_adata.length() & (m_adata.length() - 1)));
assert(!(m_bdata.length() & (m_bdata.length() - 1)));
@@ -723,6 +753,13 @@ void igs023_video_device::device_start()
m_bg_tilemap = &machine().tilemap().create(*this, tilemap_get_info_delegate(*this, FUNC(igs023_video_device::get_bg_tile_info)), TILEMAP_SCAN_ROWS, 32, 32, 64, 16);
m_bg_tilemap->set_transparent_pen(31);
m_bg_tilemap->set_scroll_rows(16 * 32);
+
+ save_item(NAME(m_bg_yscroll));
+ save_item(NAME(m_bg_xscroll));
+ save_item(NAME(m_bg_scale));
+ save_item(NAME(m_tx_yscroll));
+ save_item(NAME(m_tx_xscroll));
+ save_item(NAME(m_ctrl));
}
void igs023_video_device::device_reset()
@@ -736,19 +773,39 @@ u32 igs023_video_device::screen_update(screen_device &screen, bitmap_ind16 &bitm
screen.priority().fill(0, cliprect);
- m_bg_tilemap->set_scrolly(0, m_videoregs[0x2000/2]);
+ if (BIT(~m_ctrl, 12))
+ {
+ m_bg_tilemap->set_scrolly(0, m_bg_yscroll);
- for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
- m_bg_tilemap->set_scrollx((y + m_videoregs[0x2000 / 2]) & 0x1ff, m_videoregs[0x3000 / 2] + m_rowscrollram[y]);
+ for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
+ m_bg_tilemap->set_scrollx((y + m_bg_yscroll) & 0x1ff, m_bg_xscroll + m_rowscrollram[y]);
- m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 2);
+ m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 2);
+ }
draw_sprites(bitmap, cliprect, screen.priority());
- m_tx_tilemap->set_scrolly(0, m_videoregs[0x5000/2]);
- m_tx_tilemap->set_scrollx(0, m_videoregs[0x6000/2]); // Check
-
- m_tx_tilemap->draw(screen, bitmap, cliprect, 0, 0);
+ if (BIT(~m_ctrl, 11))
+ m_tx_tilemap->draw(screen, bitmap, cliprect, 0, 0);
return 0;
}
+
+bool igs023_video_device::sprite_dma()
+{
+ // verified on hardware
+ constexpr u16 ram_mask[5] = { 0xffff, 0xfbff, 0x7fff, 0xffff, 0xffff };
+ if (BIT(~m_ctrl, 0))
+ return false;
+
+ for (int i = 0, dst = 0, offs = 0; i < 256; i++, dst += 8)
+ {
+ for (int src = 0; src < 5; src++)
+ {
+ m_spritebuffer[dst + src] = m_readspriteram_cb(offs++) & ram_mask[src];
+ }
+ if ((m_spritebuffer[dst + 4] & 0x7fff) == 0)
+ return true;
+ }
+ return true;
+}
diff --git a/src/mame/igs/igs023_video.h b/src/mame/igs/igs023_video.h
index fb38572d813..bd185e5b9c3 100644
--- a/src/mame/igs/igs023_video.h
+++ b/src/mame/igs/igs023_video.h
@@ -7,22 +7,20 @@
#include "tilemap.h"
-class igs023_video_device : public device_t, public device_gfx_interface
+class igs023_video_device : public device_t, public device_gfx_interface, public device_video_interface
{
public:
igs023_video_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
auto read_spriteram_callback() { return m_readspriteram_cb.bind(); }
- u16 videoram_r(offs_t offset);
- void videoram_w(offs_t offset, u16 data, u16 mem_mask = ~0);
- u16 videoregs_r(offs_t offset);
- void videoregs_w(offs_t offset, u16 data, u16 mem_mask);
-
u32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void get_sprites();
+ void videoram_map(address_map &map) ATTR_COLD;
+ void videoregs_map(address_map &map) ATTR_COLD;
+
protected:
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
@@ -43,6 +41,12 @@ private:
required_region_ptr<u16> m_adata;
required_region_ptr<u16> m_bdata;
+ memory_share_creator<u16> m_bg_videoram;
+ memory_share_creator<u16> m_tx_videoram;
+ memory_share_creator<u16> m_rowscrollram;
+ memory_share_creator<u16> m_spritebuffer;
+ memory_share_creator<u16> m_zoomram;
+
devcb_read16 m_readspriteram_cb; // for reading spritelist from mainram
std::unique_ptr<sprite_t[]> m_spritelist;
@@ -54,26 +58,47 @@ private:
u8 m_abit;
u32 m_boffset;
- std::unique_ptr<uint16_t []> m_videoregs;
- std::unique_ptr<uint16_t []> m_videoram;
-
- // working variables, don't need saving
- u16 *m_bg_videoram = nullptr;
- u16 *m_tx_videoram = nullptr;
- u16 *m_rowscrollram = nullptr;
+ // video register
+ u16 m_bg_yscroll;
+ u16 m_bg_xscroll;
+ u16 m_bg_scale;
+ u16 m_tx_yscroll;
+ u16 m_tx_xscroll;
+ u16 m_ctrl;
void pgm_draw_pix(int xdrawpos, int pri, u16 *dest, u8 *destpri, const rectangle &cliprect, u16 srcdat);
- void pgm_draw_pix_nopri(int xdrawpos, u16 *dest, u8 *destpri, const rectangle &cliprect, u16 srcdat);
- void pgm_draw_pix_pri(int xdrawpos, u16 *dest, u8 *destpri, const rectangle &cliprect, u16 srcdat);
u8 get_sprite_pix();
+ void draw_sprite_pixel(int &xdrawpos, int &xcntdraw, u16 *dest, u8 *destpri, const rectangle &cliprect, int xpos, int flip, int pri, int realxsize, u16 srcdat);
void draw_sprite_line(int wide, u16 *dest, u8 *destpri, const rectangle &cliprect, int xzoom, bool xgrow, int flip, int xpos, int pri, int realxsize, int palt, bool draw);
void draw_sprite_new_zoomed(int wide, int high, int xpos, int ypos, int palt, int flip, bitmap_ind16 &bitmap, const rectangle &cliprect, bitmap_ind8 &priority_bitmap, u32 xzoom, bool xgrow, u32 yzoom, bool ygrow, int pri);
void draw_sprite_line_basic(int wide, u16 *dest, u8 *destpri, const rectangle &cliprect, int flip, int xpos, int pri, int realxsize, int palt, bool draw);
void draw_sprite_new_basic(int wide, int high, int xpos, int ypos, int palt, int flip, bitmap_ind16 &bitmap, const rectangle &cliprect, bitmap_ind8 &priority_bitmap, int pri);
void draw_sprites(bitmap_ind16& spritebitmap, const rectangle &cliprect, bitmap_ind8& priority_bitmap);
+ u16 tx_videoram_r(offs_t offset);
void tx_videoram_w(offs_t offset, u16 data, u16 mem_mask = ~0);
+ u16 bg_videoram_r(offs_t offset);
void bg_videoram_w(offs_t offset, u16 data, u16 mem_mask = ~0);
+ u16 rowscrollram_r(offs_t offset);
+ void rowscrollram_w(offs_t offset, u16 data, u16 mem_mask = ~0);
+
+ u16 spritebuffer_r(offs_t offset);
+ void spritebuffer_w(offs_t offset, u16 data, u16 mem_mask = ~0);
+ void zoomram_w(offs_t offset, u16 data, u16 mem_mask = ~0);
+ u16 bg_yscroll_r();
+ void bg_yscroll_w(offs_t offset, u16 data, u16 mem_mask = ~0);
+ u16 bg_xscroll_r();
+ void bg_xscroll_w(offs_t offset, u16 data, u16 mem_mask = ~0);
+ u16 bg_scale_r();
+ void bg_scale_w(offs_t offset, u16 data, u16 mem_mask = ~0);
+ u16 tx_yscroll_r();
+ void tx_yscroll_w(offs_t offset, u16 data, u16 mem_mask = ~0);
+ u16 tx_xscroll_r();
+ void tx_xscroll_w(offs_t offset, u16 data, u16 mem_mask = ~0);
+ u16 ctrl_r();
+ void ctrl_w(offs_t offset, u16 data, u16 mem_mask = ~0);
+
+ bool sprite_dma();
TILE_GET_INFO_MEMBER(get_tx_tile_info);
TILE_GET_INFO_MEMBER(get_bg_tile_info);
diff --git a/src/mame/igs/igs_68k_023vid.cpp b/src/mame/igs/igs_68k_023vid.cpp
index e38bc9fd97c..a35ac07f3e4 100644
--- a/src/mame/igs/igs_68k_023vid.cpp
+++ b/src/mame/igs/igs_68k_023vid.cpp
@@ -16,6 +16,7 @@ TODO:
#include "emu.h"
#include "igs023_video.h"
+//#include "igs025.h"
#include "cpu/m6502/m6502.h"
#include "cpu/m68000/m68000.h"
@@ -130,10 +131,10 @@ void igs_68k_023vid_state::main_program_base_map(address_map &map)
map(0x000000, 0x07ffff).rom();
map(0x800000, 0x81ffff).ram().share(m_mainram); // RAM test tests the full 0x20000, while in game it only seems to use 0x10000
- map(0x900000, 0x907fff).mirror(0x0f8000).rw(m_video, FUNC(igs023_video_device::videoram_r), FUNC(igs023_video_device::videoram_w));
- map(0xa00000, 0xa011ff).ram().w("palette", FUNC(palette_device::write16)).share("palette");
- map(0xa01200, 0xa023ff).ram(); // palette RAM test fails otherwise
- map(0xb00000, 0xb0ffff).rw(m_video, FUNC(igs023_video_device::videoregs_r), FUNC(igs023_video_device::videoregs_w));
+ map(0x900000, 0x907fff).mirror(0x0f8000).m(m_video, FUNC(igs023_video_device::videoram_map));
+ map(0xa00000, 0xa013ff).ram().w("palette", FUNC(palette_device::write16)).share("palette");
+ map(0xa01400, 0xa023ff).ram(); // palette RAM test fails otherwise
+ map(0xb00000, 0xb0ffff).m(m_video, FUNC(igs023_video_device::videoregs_map));
}
void igs_68k_023vid_state::main_program_xypmd_map(address_map &map)
@@ -236,20 +237,20 @@ void igs_68k_023vid_state::xypmd(machine_config &config)
m6502_device &subcpu(M6502(config, "subcpu", 8_MHz_XTAL)); // TODO: something M6502 derived (data.u13 is M6502 derived code)
subcpu.set_addrmap(AS_PROGRAM, &igs_68k_023vid_state::sub_program_map);
+ //IGS025(config, "igs025", 0);
+
// video hardware
SCREEN(config, m_screen, SCREEN_TYPE_RASTER); // TODO: verify everything once emulation works
- m_screen->set_refresh_hz(60);
- m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(1000));
- m_screen->set_size(512, 256);
- m_screen->set_visarea(0, 448-1, 0, 224-1);
+ m_screen->set_raw(50_MHz_XTAL/5, 640, 0, 448, 264, 0, 224); // copied from igs/pgm.cpp, correct?
m_screen->set_screen_update("igs023", FUNC(igs023_video_device::screen_update));
m_screen->screen_vblank().set(FUNC(igs_68k_023vid_state::screen_vblank));
m_screen->set_palette("palette");
- PALETTE(config, "palette").set_format(palette_device::xRGB_555, 0x1200 / 2);
+ PALETTE(config, "palette").set_format(palette_device::xRGB_555, 0x1400 / 2);
IGS023_VIDEO(config, m_video, 0);
m_video->set_palette("palette");
+ m_video->set_screen(m_screen);
m_video->read_spriteram_callback().set([this](offs_t offset) { return m_mainram[offset]; });
// sound hardware
diff --git a/src/mame/igs/igs_m027_023vid.cpp b/src/mame/igs/igs_m027_023vid.cpp
index 6af607b8d51..b2bf88960ee 100644
--- a/src/mame/igs/igs_m027_023vid.cpp
+++ b/src/mame/igs/igs_m027_023vid.cpp
@@ -187,9 +187,9 @@ void igs_m027_023vid_state::m027_map(address_map &map)
map(0x2800'0000, 0x2800'0fff).ram();
- map(0x3890'0000, 0x3890'7fff).rw(m_video, FUNC(igs023_video_device::videoram_r), FUNC(igs023_video_device::videoram_w)).umask32(0xffffffff);
- map(0x38a0'0000, 0x38a0'11ff).ram().w(m_palette, FUNC(palette_device::write32)).share("palette");
- map(0x38b0'0000, 0x38b0'ffff).rw(m_video, FUNC(igs023_video_device::videoregs_r), FUNC(igs023_video_device::videoregs_w)).umask32(0xffffffff);
+ map(0x3890'0000, 0x3890'7fff).m(m_video, FUNC(igs023_video_device::videoram_map)).umask32(0xffffffff);
+ map(0x38a0'0000, 0x38a0'13ff).ram().w(m_palette, FUNC(palette_device::write32)).share("palette");
+ map(0x38b0'0000, 0x38b0'ffff).m(m_video, FUNC(igs023_video_device::videoregs_map)).umask32(0xffffffff);
map(0x4800'0000, 0x4800'0001).r(FUNC(igs_m027_023vid_state::in_r<0>));
map(0x4800'0002, 0x4800'0003).r(FUNC(igs_m027_023vid_state::in_r<1>));
@@ -394,19 +394,17 @@ void igs_m027_023vid_state::m027_023vid(machine_config &config)
NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
- m_screen->set_refresh_hz(60);
- m_screen->set_vblank_time(ATTOSECONDS_IN_USEC(1000));
- m_screen->set_size(512, 256);
- m_screen->set_visarea(0, 448-1, 0, 224-1);
+ m_screen->set_raw(50_MHz_XTAL/5, 640, 0, 448, 264, 0, 224); // copied from igs/pgm.cpp, correct?
m_screen->set_screen_update(m_video, FUNC(igs023_video_device::screen_update));
- m_screen->set_palette(m_palette);
m_screen->screen_vblank().set(FUNC(igs_m027_023vid_state::screen_vblank));
+ m_screen->set_palette(m_palette);
- PALETTE(config, m_palette).set_format(palette_device::xRGB_555, 0x1200/2);
+ PALETTE(config, m_palette).set_format(palette_device::xRGB_555, 0x1400/2);
// PGM video
IGS023_VIDEO(config, m_video, 0);
m_video->set_palette(m_palette);
+ m_video->set_screen(m_screen);
m_video->read_spriteram_callback().set(FUNC(igs_m027_023vid_state::sprites_r));
// sound hardware
diff --git a/src/mame/igs/pgm.cpp b/src/mame/igs/pgm.cpp
index 6572d6cdb55..1acc04cdd89 100644
--- a/src/mame/igs/pgm.cpp
+++ b/src/mame/igs/pgm.cpp
@@ -220,10 +220,10 @@ Notes:
void pgm_state::coin_counter_w(u16 data)
{
- machine().bookkeeping().coin_counter_w(0, data & 0x0001);
- machine().bookkeeping().coin_counter_w(1, data & 0x0002);
- machine().bookkeeping().coin_counter_w(2, data & 0x0004);
- machine().bookkeeping().coin_counter_w(3, data & 0x0008);
+ machine().bookkeeping().coin_counter_w(0, BIT(data, 0));
+ machine().bookkeeping().coin_counter_w(1, BIT(data, 1));
+ machine().bookkeeping().coin_counter_w(2, BIT(data, 2));
+ machine().bookkeeping().coin_counter_w(3, BIT(data, 3));
}
bool pgm_state::z80_sync(int which)
@@ -269,7 +269,7 @@ void pgm_state::z80_reset_w(offs_t offset, u16 data, u16 mem_mask)
m_soundcpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
m_soundcpu->pulse_input_line(INPUT_LINE_RESET, attotime::zero);
}
- else
+ else // if (data == 0xa659)
{
/* this might not be 100% correct, but several of the games (ddp2, puzzli2 etc.) expect the z80 to be turned
off during data uploads, they write here before the upload */
@@ -280,6 +280,7 @@ void pgm_state::z80_reset_w(offs_t offset, u16 data, u16 mem_mask)
void pgm_state::z80_ctrl_w(offs_t offset, u16 data, u16 mem_mask)
{
LOGZ80("Z80: ctrl %04x @ %04x (%06x)\n", data, mem_mask, m_maincpu->pc());
+ // TODO: hook up Z80 bus request: 68K writes 0x45d3 before access, then 0x0a0a after access
}
template<int N>
@@ -308,7 +309,7 @@ void pgm_state::z80_latch3_w(u8 data)
void pgm_state::pgm_z80_mem(address_map &map)
{
- map(0x0000, 0xffff).ram().share("z80_mainram");
+ map(0x0000, 0xffff).ram().share(m_z80_mainram);
}
void pgm_state::pgm_z80_io(address_map &map)
@@ -325,18 +326,11 @@ void pgm_state::pgm_base_mem(address_map &map)
{
map(0x700006, 0x700007).nopw(); // Watchdog?
- map(0x800000, 0x81ffff).ram().mirror(0x0e0000).share("sram"); /* Main Ram */
+ map(0x800000, 0x81ffff).ram().mirror(0x0e0000).share(m_mainram); /* Main RAM */
- map(0x900000, 0x907fff).mirror(0x0f8000).rw(m_video, FUNC(igs023_video_device::videoram_r), FUNC(igs023_video_device::videoram_w)); /* IGS023 VIDEO CHIP */
- map(0xa00000, 0xa011ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette");
- map(0xb00000, 0xb0ffff).rw(m_video, FUNC(igs023_video_device::videoregs_r), FUNC(igs023_video_device::videoregs_w)); /* Video Regs inc. Zoom Table */
- //map(0xb01000, 0xb0103f) Zoom/Shrink table for sprites
- //map(0xb02000, 0xb02001) Background scroll Y
- //map(0xb03000, 0xb03001) Background scroll X
- //map(0xb04000, 0xb04001) Unknown #0
- //map(0xb05000, 0xb05001) Foreground scroll Y
- //map(0xb06000, 0xb06001) Foreground scroll X?
- //map(0xb0e000, 0xb0e001) Unknown #1
+ map(0x900000, 0x907fff).mirror(0x0f8000).m(m_video, FUNC(igs023_video_device::videoram_map)); /* IGS023 VIDEO CHIP */
+ map(0xa00000, 0xa013ff).ram().w(m_palette, FUNC(palette_device::write16)).share("palette");
+ map(0xb00000, 0xb0ffff).m(m_video, FUNC(igs023_video_device::videoregs_map));
map(0xc00003, 0xc00003).rw(FUNC(pgm_state::m68k_latch_r<0>), FUNC(pgm_state::m68k_latch1_w));
map(0xc00005, 0xc00005).r(FUNC(pgm_state::m68k_latch_r<1>)).w(m_soundlatch[1], FUNC(generic_latch_8_device::write));
@@ -522,7 +516,7 @@ void pgm_state::pgmbase(machine_config &config)
screen.screen_vblank().set(FUNC(pgm_state::screen_vblank));
screen.set_palette(m_palette);
- PALETTE(config, m_palette, palette_device::BLACK).set_format(palette_device::xRGB_555, 0x1200/2);
+ PALETTE(config, m_palette, palette_device::BLACK).set_format(palette_device::xRGB_555, 0x1400/2);
/*sound hardware */
SPEAKER(config, "mono").front_center();
@@ -533,6 +527,7 @@ void pgm_state::pgmbase(machine_config &config)
IGS023_VIDEO(config, m_video, 0);
m_video->set_palette(m_palette);
+ m_video->set_screen("screen");
m_video->read_spriteram_callback().set(FUNC(pgm_state::sprites_r));
ICS2115(config, m_ics, 33.8688_MHz_XTAL);