// license:BSD-3-Clause // copyright-holders:Luca Elia, David Haywood /* */ #include "emu.h" #include "fuukifg.h" #include "screen.h" DEFINE_DEVICE_TYPE(FUUKI_VIDEO, fuukivid_device, "fuukivid", "Fuuki Video") fuukivid_device::fuukivid_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : device_t(mconfig, FUUKI_VIDEO, tag, owner, clock) , device_gfx_interface(mconfig, *this, nullptr) , device_video_interface(mconfig, *this) , m_tile_cb(*this) , m_colpri_cb(*this) , m_gfx_region(*this, DEVICE_SELF) , m_colbase(0) , m_colnum(0x100) { } void fuukivid_device::device_start() { /* 16x16x4 */ gfx_layout layout_16x16x4 = { 16,16, 0, 4, { STEP4(0,1) }, { STEP16(0,4) }, { STEP16(0,16*4) }, 16*16*4 }; layout_16x16x4.total = m_gfx_region->bytes() / ((16*16*4) / 8); m_tile_cb.resolve(); m_colpri_cb.resolve(); set_gfx(0, std::make_unique(&palette(), layout_16x16x4, m_gfx_region->base(), 0, m_colnum, m_colbase)); } void fuukivid_device::device_reset() { } /*************************************************************************** Sprites Drawing Offset: Bits: Value: 0.w fedc ---- ---- ---- Number Of Tiles Along X - 1 ---- b--- ---- ---- Flip X ---- -a-- ---- ---- 1 = Don't Draw This Sprite ---- --98 7654 3210 X (Signed) 2.w fedc ---- ---- ---- Number Of Tiles Along Y - 1 ---- b--- ---- ---- Flip Y ---- -a-- ---- ---- ---- --98 7654 3210 Y (Signed) 4.w fedc ---- ---- ---- Zoom X ($0 = Full Size, $F = Half Size) ---- ba98 ---- ---- Zoom Y "" ---- ---- 76-- ---- Priority ---- ---- --54 3210 Color 6.w Tile Code for FG3 hardware 6.w fe-- ---- ---- ---- Tile Bank --dc ba98 7654 3210 Tile Code ***************************************************************************/ void fuukivid_device::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, bool flip_screen, u16 *spriteram, u32 size) { // as we're likely framebuffered (sprites are delayed by 2-3 frames, at least on FG3, and doing rasters on sprites causes glitches) we // only draw the sprites when MAME wants to draw the final screen line. Ideally we should framebuffer them instead. if (cliprect.max_y != screen.visible_area().max_y) return; const bool tilebank = !m_tile_cb.isnull(); const bool priority = !m_colpri_cb.isnull(); const rectangle spriteclip = screen.visible_area(); const int max_x = spriteclip.max_x + 1; const int max_y = spriteclip.max_y + 1; int start, end, inc; if (priority) { start = size - 4; end = -4; inc = -4; } else { start = 0; end = size; inc = +4; } /* Draw them backwards, for pdrawgfx */ for (int offs = start; offs != end; offs += inc) { const u16 data0 = spriteram[offs + 0]; const u16 data1 = spriteram[offs + 1]; const u16 attr = spriteram[offs + 2]; u32 code = spriteram[offs + 3]; if (tilebank) m_tile_cb(code); if (data0 & 0x400) continue; int flipx = data0 & 0x0800; int flipy = data1 & 0x0800; const int xnum = ((data0 >> 12) & 0xf) + 1; const int ynum = ((data1 >> 12) & 0xf) + 1; const int xzoom = 16 * 8 - (8 * ((attr >> 12) & 0xf)) / 2; const int yzoom = 16 * 8 - (8 * ((attr >> 8) & 0xf)) / 2; u32 pri_mask = 0; u32 colour = attr & 0xff; if (priority) m_colpri_cb(colour, pri_mask); int sx = (data0 & 0x1ff) - (data0 & 0x200); int sy = (data1 & 0x1ff) - (data1 & 0x200); if (flip_screen) { flipx = !flipx; sx = max_x - sx - xnum * 16; flipy = !flipy; sy = max_y - sy - ynum * 16; } int xstart, ystart, xend, yend, xinc, yinc; if (flipx) { xstart = xnum-1; xend = -1; xinc = -1; } else { xstart = 0; xend = xnum; xinc = +1; } if (flipy) { ystart = ynum-1; yend = -1; yinc = -1; } else { ystart = 0; yend = ynum; yinc = +1; } for (int y = ystart; y != yend; y += yinc) { for (int x = xstart; x != xend; x += xinc) { if (priority) { if (xzoom == (16*8) && yzoom == (16*8)) gfx(0)->prio_transpen(bitmap,spriteclip, code++, colour, flipx, flipy, sx + x * 16, sy + y * 16, screen.priority(), pri_mask, 15); else gfx(0)->prio_zoom_transpen(bitmap,spriteclip, code++, colour, flipx, flipy, sx + (x * xzoom) / 8, sy + (y * yzoom) / 8, (0x10000/0x10/8) * (xzoom + 8), (0x10000/0x10/8) * (yzoom + 8),// nearest greater integer value to avoid holes screen.priority(), pri_mask, 15); } else { if (xzoom == (16*8) && yzoom == (16*8)) gfx(0)->transpen(bitmap,spriteclip, code++, colour, flipx, flipy, sx + x * 16, sy + y * 16, 15); else gfx(0)->zoom_transpen(bitmap,spriteclip, code++, colour, flipx, flipy, sx + (x * xzoom) / 8, sy + (y * yzoom) / 8, (0x10000/0x10/8) * (xzoom + 8), (0x10000/0x10/8) * (yzoom + 8),// nearest greater integer value to avoid holes 15); } } } } }