diff options
| author | 2026-04-16 03:01:50 +0900 | |
|---|---|---|
| committer | 2026-04-16 04:01:50 +1000 | |
| commit | 537f0a206c477889911f385be3e50f17185d6cfd (patch) | |
| tree | d15b5322b22fd1ccb5ac5ea8dd405799921be287 | |
| parent | 6d0d50b450a7e8307c6c5046bedc5dcd5fcb2185 (diff) | |
igs/igs023_video.cpp and related driver updates: (#15227)
* Reference: https://github.com/laoo/PGMTech
* Use BIT helper to extract single bits, use util::sext to sign extend values.
* Use logmacro.h for logging feature.
* Use address maps for RAM/video register area.
* Implemented additional features: sprite DMA, disable specific layer, ccanline counter (verified from hardware).
* Expanded palette area for fix possible out of bound text palette issue.
* igs/pgm.cpp: Added notes about Z80 control, reduced literal tag usage.
* igs/igs_68k_023vid.cpp: Added placeholder for IGS025.
| -rw-r--r-- | src/mame/igs/igs023_video.cpp | 501 | ||||
| -rw-r--r-- | src/mame/igs/igs023_video.h | 55 | ||||
| -rw-r--r-- | src/mame/igs/igs_68k_023vid.cpp | 19 | ||||
| -rw-r--r-- | src/mame/igs/igs_m027_023vid.cpp | 16 | ||||
| -rw-r--r-- | src/mame/igs/pgm.cpp | 31 |
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); |
