mirror of
https://github.com/holub/mame
synced 2025-06-07 05:13:46 +03:00
2113 lines
68 KiB
C++
2113 lines
68 KiB
C++
// license:BSD-3-Clause
|
|
// copyright-holders:Nicola Salmoria, Aaron Giles
|
|
/*********************************************************************
|
|
|
|
drawgfx.c
|
|
|
|
Generic graphic functions.
|
|
*********************************************************************/
|
|
|
|
#include "emu.h"
|
|
#include "drawgfxm.h"
|
|
|
|
|
|
/***************************************************************************
|
|
GLOBAL VARIABLES
|
|
***************************************************************************/
|
|
|
|
// if this line errors during compile, the size of NO_PRIORITY is wrong and I need to use something else
|
|
u8 no_priority_size_is_wrong[2 * (sizeof(NO_PRIORITY) == 3) - 1];
|
|
|
|
bitmap_ind8 drawgfx_dummy_priority_bitmap;
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
INLINE FUNCTIONS
|
|
***************************************************************************/
|
|
|
|
/*-------------------------------------------------
|
|
readbit - read a single bit from a base
|
|
offset
|
|
-------------------------------------------------*/
|
|
|
|
static inline int readbit(const u8 *src, unsigned int bitnum)
|
|
{
|
|
return src[bitnum / 8] & (0x80 >> (bitnum % 8));
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
normalize_xscroll - normalize an X scroll
|
|
value for a bitmap to be positive and less
|
|
than the width
|
|
-------------------------------------------------*/
|
|
|
|
static inline s32 normalize_xscroll(const bitmap_t &bitmap, s32 xscroll)
|
|
{
|
|
return (xscroll >= 0) ? xscroll % bitmap.width() : (bitmap.width() - (-xscroll) % bitmap.width());
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
normalize_yscroll - normalize a Y scroll
|
|
value for a bitmap to be positive and less
|
|
than the height
|
|
-------------------------------------------------*/
|
|
|
|
static inline s32 normalize_yscroll(const bitmap_t &bitmap, s32 yscroll)
|
|
{
|
|
return (yscroll >= 0) ? yscroll % bitmap.height() : (bitmap.height() - (-yscroll) % bitmap.height());
|
|
}
|
|
|
|
|
|
|
|
//**************************************************************************
|
|
// DEVICE DEFINITIONS
|
|
//**************************************************************************
|
|
|
|
DEFINE_DEVICE_TYPE(GFXDECODE, gfxdecode_device, "gfxdecode", "gfxdecode")
|
|
|
|
gfxdecode_device::gfxdecode_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
|
|
device_t(mconfig, GFXDECODE, tag, owner, clock),
|
|
device_gfx_interface(mconfig, *this)
|
|
{
|
|
}
|
|
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
GRAPHICS ELEMENTS
|
|
***************************************************************************/
|
|
|
|
|
|
//-------------------------------------------------
|
|
// gfx_element - constructor
|
|
//-------------------------------------------------
|
|
|
|
gfx_element::gfx_element(device_palette_interface *palette, u8 *base, u16 width, u16 height, u32 rowbytes, u32 total_colors, u32 color_base, u32 color_granularity)
|
|
: m_palette(palette),
|
|
m_width(width),
|
|
m_height(height),
|
|
m_startx(0),
|
|
m_starty(0),
|
|
m_origwidth(width),
|
|
m_origheight(height),
|
|
m_total_elements(1),
|
|
m_color_base(color_base),
|
|
m_color_depth(color_granularity),
|
|
m_color_granularity(color_granularity),
|
|
m_total_colors((total_colors - color_base) / color_granularity),
|
|
m_line_modulo(rowbytes),
|
|
m_char_modulo(0),
|
|
m_srcdata(base),
|
|
m_dirtyseq(1),
|
|
m_gfxdata(base),
|
|
m_layout_is_raw(true),
|
|
m_layout_planes(0),
|
|
m_layout_xormask(0),
|
|
m_layout_charincrement(0)
|
|
{
|
|
}
|
|
|
|
gfx_element::gfx_element(device_palette_interface *palette, const gfx_layout &gl, const u8 *srcdata, u32 xormask, u32 total_colors, u32 color_base)
|
|
: m_palette(palette),
|
|
m_width(0),
|
|
m_height(0),
|
|
m_startx(0),
|
|
m_starty(0),
|
|
m_origwidth(0),
|
|
m_origheight(0),
|
|
m_total_elements(0),
|
|
m_color_base(color_base),
|
|
m_color_depth(0),
|
|
m_color_granularity(0),
|
|
m_total_colors(total_colors),
|
|
m_line_modulo(0),
|
|
m_char_modulo(0),
|
|
m_srcdata(nullptr),
|
|
m_dirtyseq(1),
|
|
m_gfxdata(nullptr),
|
|
m_layout_is_raw(false),
|
|
m_layout_planes(0),
|
|
m_layout_xormask(xormask),
|
|
m_layout_charincrement(0)
|
|
{
|
|
// set the layout
|
|
set_layout(gl, srcdata);
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// set_layout - set the layout for a gfx_element
|
|
//-------------------------------------------------
|
|
|
|
void gfx_element::set_layout(const gfx_layout &gl, const u8 *srcdata)
|
|
{
|
|
m_srcdata = srcdata;
|
|
|
|
// configure ourselves
|
|
m_width = m_origwidth = gl.width;
|
|
m_height = m_origheight = gl.height;
|
|
m_startx = m_starty = 0;
|
|
m_total_elements = gl.total;
|
|
m_color_depth = m_color_granularity = 1 << gl.planes;
|
|
|
|
// copy data from the layout
|
|
m_layout_is_raw = (gl.planeoffset[0] == GFX_RAW);
|
|
m_layout_planes = gl.planes;
|
|
m_layout_charincrement = gl.charincrement;
|
|
|
|
// raw graphics case
|
|
if (m_layout_is_raw)
|
|
{
|
|
// RAW layouts don't need these arrays
|
|
m_layout_planeoffset.clear();
|
|
m_layout_xoffset.clear();
|
|
m_layout_yoffset.clear();
|
|
m_gfxdata_allocated.clear();
|
|
|
|
// modulos are determined for us by the layout
|
|
m_line_modulo = gl.yoffs(0) / 8;
|
|
m_char_modulo = gl.charincrement / 8;
|
|
|
|
// RAW graphics must have a pointer up front
|
|
assert(srcdata != nullptr);
|
|
m_gfxdata = const_cast<u8 *>(srcdata);
|
|
}
|
|
|
|
// decoded graphics case
|
|
else
|
|
{
|
|
// copy offsets
|
|
m_layout_planeoffset.resize(m_layout_planes);
|
|
m_layout_xoffset.resize(m_width);
|
|
m_layout_yoffset.resize(m_height);
|
|
|
|
for (int p = 0; p < m_layout_planes; p++)
|
|
m_layout_planeoffset[p] = gl.planeoffset[p];
|
|
for (int y = 0; y < m_height; y++)
|
|
m_layout_yoffset[y] = gl.yoffs(y);
|
|
for (int x = 0; x < m_width; x++)
|
|
m_layout_xoffset[x] = gl.xoffs(x);
|
|
|
|
// we get to pick our own modulos
|
|
m_line_modulo = m_origwidth;
|
|
m_char_modulo = m_line_modulo * m_origheight;
|
|
|
|
// allocate memory for the data
|
|
m_gfxdata_allocated.resize(m_total_elements * m_char_modulo);
|
|
m_gfxdata = &m_gfxdata_allocated[0];
|
|
}
|
|
|
|
// mark everything dirty
|
|
m_dirty.resize(m_total_elements);
|
|
memset(&m_dirty[0], 1, m_total_elements);
|
|
|
|
// allocate a pen usage array for entries with 32 pens or less
|
|
if (m_color_depth <= 32)
|
|
m_pen_usage.resize(m_total_elements);
|
|
else
|
|
m_pen_usage.clear();
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// set_raw_layout - set the layout for a gfx_element
|
|
//-------------------------------------------------
|
|
|
|
void gfx_element::set_raw_layout(const u8 *srcdata, u32 width, u32 height, u32 total, u32 linemod, u32 charmod)
|
|
{
|
|
gfx_layout layout = { 0 };
|
|
layout.width = width;
|
|
layout.height = height;
|
|
layout.total = total;
|
|
layout.planes = 8;
|
|
layout.planeoffset[0] = GFX_RAW;
|
|
layout.yoffset[0] = linemod;
|
|
layout.charincrement = charmod;
|
|
set_layout(layout, srcdata);
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// set_source - set the source data for a gfx_element
|
|
//-------------------------------------------------
|
|
|
|
void gfx_element::set_source(const u8 *source)
|
|
{
|
|
m_srcdata = source;
|
|
memset(&m_dirty[0], 1, elements());
|
|
if (m_layout_is_raw) m_gfxdata = const_cast<u8 *>(source);
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// set_source_and_total - set the source data
|
|
// and total elements for a gfx_element
|
|
//-------------------------------------------------
|
|
|
|
void gfx_element::set_source_and_total(const u8 *source, u32 total)
|
|
{
|
|
m_srcdata = source;
|
|
m_total_elements = total;
|
|
|
|
// mark everything dirty
|
|
m_dirty.resize(m_total_elements);
|
|
memset(&m_dirty[0], 1, m_total_elements);
|
|
|
|
// allocate a pen usage array for entries with 32 pens or less
|
|
if (m_color_depth <= 32)
|
|
m_pen_usage.resize(m_total_elements);
|
|
|
|
if (m_layout_is_raw)
|
|
{
|
|
m_gfxdata = const_cast<u8 *>(source);
|
|
}
|
|
else
|
|
{
|
|
// allocate memory for the data
|
|
m_gfxdata_allocated.resize(m_total_elements * m_char_modulo);
|
|
m_gfxdata = &m_gfxdata_allocated[0];
|
|
}
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// set_source_clip - set a source clipping rect
|
|
//-------------------------------------------------
|
|
|
|
void gfx_element::set_source_clip(u32 xoffs, u32 width, u32 yoffs, u32 height)
|
|
{
|
|
assert(xoffs < m_origwidth);
|
|
assert(yoffs < m_origheight);
|
|
assert(xoffs + width <= m_origwidth);
|
|
assert(yoffs + height <= m_origheight);
|
|
|
|
m_width = width;
|
|
m_height = height;
|
|
m_startx = xoffs;
|
|
m_starty = yoffs;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------
|
|
// decode - decode a single character
|
|
//-------------------------------------------------
|
|
|
|
void gfx_element::decode(u32 code)
|
|
{
|
|
// don't decode GFX_RAW
|
|
if (!m_layout_is_raw)
|
|
{
|
|
// zap the data to 0
|
|
u8 *decode_base = m_gfxdata + code * m_char_modulo;
|
|
memset(decode_base, 0, m_char_modulo);
|
|
|
|
// iterate over planes
|
|
int plane, planebit;
|
|
for (plane = 0, planebit = 1 << (m_layout_planes - 1);
|
|
plane < m_layout_planes;
|
|
plane++, planebit >>= 1)
|
|
{
|
|
int planeoffs = code * m_layout_charincrement + m_layout_planeoffset[plane];
|
|
|
|
// iterate over rows
|
|
for (int y = 0; y < m_origheight; y++)
|
|
{
|
|
int yoffs = planeoffs + m_layout_yoffset[y];
|
|
u8 *dp = decode_base + y * m_line_modulo;
|
|
|
|
// iterate over columns
|
|
for (int x = 0; x < m_origwidth; x++)
|
|
if (readbit(m_srcdata, (yoffs + m_layout_xoffset[x]) ^ m_layout_xormask))
|
|
dp[x] |= planebit;
|
|
}
|
|
}
|
|
}
|
|
|
|
// (re)compute pen usage
|
|
if (code < m_pen_usage.size())
|
|
{
|
|
// iterate over data, creating a bitmask of live pens
|
|
const u8 *dp = m_gfxdata + code * m_char_modulo;
|
|
u32 usage = 0;
|
|
for (int y = 0; y < m_origheight; y++)
|
|
{
|
|
for (int x = 0; x < m_origwidth; x++)
|
|
usage |= 1 << dp[x];
|
|
dp += m_line_modulo;
|
|
}
|
|
|
|
// store the final result
|
|
m_pen_usage[code] = usage;
|
|
}
|
|
|
|
// no longer dirty
|
|
m_dirty[code] = 0;
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
DRAWGFX IMPLEMENTATIONS
|
|
***************************************************************************/
|
|
|
|
/*-------------------------------------------------
|
|
opaque - render a gfx element with
|
|
no transparency
|
|
-------------------------------------------------*/
|
|
|
|
void gfx_element::opaque(bitmap_ind16 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty)
|
|
{
|
|
color = colorbase() + granularity() * (color % colors());
|
|
code %= elements();
|
|
DECLARE_NO_PRIORITY;
|
|
DRAWGFX_CORE(u16, PIXEL_OP_REBASE_OPAQUE, NO_PRIORITY);
|
|
}
|
|
|
|
void gfx_element::opaque(bitmap_rgb32 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty)
|
|
{
|
|
const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
|
|
code %= elements();
|
|
DECLARE_NO_PRIORITY;
|
|
DRAWGFX_CORE(u32, PIXEL_OP_REMAP_OPAQUE, NO_PRIORITY);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
transpen - render a gfx element with
|
|
a single transparent pen
|
|
-------------------------------------------------*/
|
|
|
|
void gfx_element::transpen(bitmap_ind16 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
u32 trans_pen)
|
|
{
|
|
// special case invalid pens to opaque
|
|
if (trans_pen > 0xff)
|
|
return opaque(dest, cliprect, code, color, flipx, flipy, destx, desty);
|
|
|
|
// use pen usage to optimize
|
|
code %= elements();
|
|
if (has_pen_usage())
|
|
{
|
|
// fully transparent; do nothing
|
|
u32 usage = pen_usage(code);
|
|
if ((usage & ~(1 << trans_pen)) == 0)
|
|
return;
|
|
|
|
// fully opaque; draw as such
|
|
if ((usage & (1 << trans_pen)) == 0)
|
|
return opaque(dest, cliprect, code, color, flipx, flipy, destx, desty);
|
|
}
|
|
|
|
// render
|
|
color = colorbase() + granularity() * (color % colors());
|
|
DECLARE_NO_PRIORITY;
|
|
DRAWGFX_CORE(u16, PIXEL_OP_REBASE_TRANSPEN, NO_PRIORITY);
|
|
}
|
|
|
|
void gfx_element::transpen(bitmap_rgb32 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
u32 trans_pen)
|
|
{
|
|
// special case invalid pens to opaque
|
|
if (trans_pen > 0xff)
|
|
return opaque(dest, cliprect, code, color, flipx, flipy, destx, desty);
|
|
|
|
// use pen usage to optimize
|
|
code %= elements();
|
|
if (has_pen_usage())
|
|
{
|
|
// fully transparent; do nothing
|
|
u32 usage = pen_usage(code);
|
|
if ((usage & ~(1 << trans_pen)) == 0)
|
|
return;
|
|
|
|
// fully opaque; draw as such
|
|
if ((usage & (1 << trans_pen)) == 0)
|
|
return opaque(dest, cliprect, code, color, flipx, flipy, destx, desty);
|
|
}
|
|
|
|
// render
|
|
const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
|
|
DECLARE_NO_PRIORITY;
|
|
DRAWGFX_CORE(u32, PIXEL_OP_REMAP_TRANSPEN, NO_PRIORITY);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
transpen_raw - render a gfx element
|
|
with a single transparent pen and no color
|
|
lookups
|
|
-------------------------------------------------*/
|
|
|
|
void gfx_element::transpen_raw(bitmap_ind16 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
u32 trans_pen)
|
|
{
|
|
// early out if completely transparent
|
|
code %= elements();
|
|
if (has_pen_usage() && (pen_usage(code) & ~(1 << trans_pen)) == 0)
|
|
return;
|
|
|
|
// render
|
|
DECLARE_NO_PRIORITY;
|
|
DRAWGFX_CORE(u16, PIXEL_OP_REBASE_TRANSPEN, NO_PRIORITY);
|
|
}
|
|
|
|
void gfx_element::transpen_raw(bitmap_rgb32 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
u32 trans_pen)
|
|
{
|
|
// early out if completely transparent
|
|
code %= elements();
|
|
if (has_pen_usage() && (pen_usage(code) & ~(1 << trans_pen)) == 0)
|
|
return;
|
|
|
|
// render
|
|
DECLARE_NO_PRIORITY;
|
|
DRAWGFX_CORE(u32, PIXEL_OP_REBASE_TRANSPEN, NO_PRIORITY);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
transmask - render a gfx element
|
|
with a multiple transparent pens provided as
|
|
a mask
|
|
-------------------------------------------------*/
|
|
|
|
void gfx_element::transmask(bitmap_ind16 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
u32 trans_mask)
|
|
{
|
|
// special case 0 mask to opaque
|
|
if (trans_mask == 0)
|
|
return opaque(dest, cliprect, code, color, flipx, flipy, destx, desty);
|
|
|
|
// use pen usage to optimize
|
|
code %= elements();
|
|
if (has_pen_usage())
|
|
{
|
|
// fully transparent; do nothing
|
|
u32 usage = pen_usage(code);
|
|
if ((usage & ~trans_mask) == 0)
|
|
return;
|
|
|
|
// fully opaque; draw as such
|
|
if ((usage & trans_mask) == 0)
|
|
return opaque(dest, cliprect, code, color, flipx, flipy, destx, desty);
|
|
}
|
|
|
|
// render
|
|
color = colorbase() + granularity() * (color % colors());
|
|
DECLARE_NO_PRIORITY;
|
|
DRAWGFX_CORE(u16, PIXEL_OP_REBASE_TRANSMASK, NO_PRIORITY);
|
|
}
|
|
|
|
void gfx_element::transmask(bitmap_rgb32 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
u32 trans_mask)
|
|
{
|
|
// special case 0 mask to opaque
|
|
if (trans_mask == 0)
|
|
return opaque(dest, cliprect, code, color, flipx, flipy, destx, desty);
|
|
|
|
// use pen usage to optimize
|
|
code %= elements();
|
|
if (has_pen_usage())
|
|
{
|
|
// fully transparent; do nothing
|
|
u32 usage = pen_usage(code);
|
|
if ((usage & ~trans_mask) == 0)
|
|
return;
|
|
|
|
// fully opaque; draw as such
|
|
if ((usage & trans_mask) == 0)
|
|
return opaque(dest, cliprect, code, color, flipx, flipy, destx, desty);
|
|
}
|
|
|
|
// render
|
|
const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
|
|
DECLARE_NO_PRIORITY;
|
|
DRAWGFX_CORE(u32, PIXEL_OP_REMAP_TRANSMASK, NO_PRIORITY);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
transtable - render a gfx element
|
|
using a table to look up which pens are
|
|
transparent, opaque, or shadowing
|
|
-------------------------------------------------*/
|
|
|
|
void gfx_element::transtable(bitmap_ind16 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
const u8 *pentable)
|
|
{
|
|
assert(pentable != nullptr);
|
|
|
|
// render
|
|
color = colorbase() + granularity() * (color % colors());
|
|
const pen_t *shadowtable = m_palette->shadow_table();
|
|
code %= elements();
|
|
DECLARE_NO_PRIORITY;
|
|
DRAWGFX_CORE(u16, PIXEL_OP_REBASE_TRANSTABLE16, NO_PRIORITY);
|
|
}
|
|
|
|
void gfx_element::transtable(bitmap_rgb32 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
const u8 *pentable)
|
|
{
|
|
assert(pentable != nullptr);
|
|
|
|
// render
|
|
const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
|
|
const pen_t *shadowtable = m_palette->shadow_table();
|
|
code %= elements();
|
|
DECLARE_NO_PRIORITY;
|
|
DRAWGFX_CORE(u32, PIXEL_OP_REMAP_TRANSTABLE32, NO_PRIORITY);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
alpha - render a gfx element with
|
|
a single transparent pen, alpha blending the
|
|
remaining pixels with a fixed alpha value
|
|
-------------------------------------------------*/
|
|
|
|
void gfx_element::alpha(bitmap_rgb32 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
u32 trans_pen, u8 alpha_val)
|
|
{
|
|
// special case alpha = 0xff
|
|
if (alpha_val == 0xff)
|
|
return transpen(dest, cliprect, code, color, flipx, flipy, destx, desty, trans_pen);
|
|
|
|
// early out if completely transparent
|
|
code %= elements();
|
|
if (has_pen_usage() && (pen_usage(code) & ~(1 << trans_pen)) == 0)
|
|
return;
|
|
|
|
// get final code and color, and grab lookup tables
|
|
const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
|
|
DECLARE_NO_PRIORITY;
|
|
DRAWGFX_CORE(u32, PIXEL_OP_REMAP_TRANSPEN_ALPHA32, NO_PRIORITY);
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
DRAWGFXZOOM IMPLEMENTATIONS
|
|
***************************************************************************/
|
|
|
|
/*-------------------------------------------------
|
|
zoom_opaque - render a scaled gfx
|
|
element with no transparency
|
|
-------------------------------------------------*/
|
|
|
|
void gfx_element::zoom_opaque(bitmap_ind16 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
u32 scalex, u32 scaley)
|
|
{
|
|
// non-zoom case
|
|
if (scalex == 0x10000 && scaley == 0x10000)
|
|
return opaque(dest, cliprect, code, color, flipx, flipy, destx, desty);
|
|
|
|
// render
|
|
color = colorbase() + granularity() * (color % colors());
|
|
code %= elements();
|
|
DECLARE_NO_PRIORITY;
|
|
DRAWGFXZOOM_CORE(u16, PIXEL_OP_REBASE_OPAQUE, NO_PRIORITY);
|
|
}
|
|
|
|
void gfx_element::zoom_opaque(bitmap_rgb32 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
u32 scalex, u32 scaley)
|
|
{
|
|
// non-zoom case
|
|
if (scalex == 0x10000 && scaley == 0x10000)
|
|
return opaque(dest, cliprect, code, color, flipx, flipy, destx, desty);
|
|
|
|
// render
|
|
const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
|
|
code %= elements();
|
|
DECLARE_NO_PRIORITY;
|
|
DRAWGFXZOOM_CORE(u32, PIXEL_OP_REMAP_OPAQUE, NO_PRIORITY);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
zoom_transpen - render a scaled gfx
|
|
element with a single transparent pen
|
|
-------------------------------------------------*/
|
|
|
|
void gfx_element::zoom_transpen(bitmap_ind16 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
u32 scalex, u32 scaley, u32 trans_pen)
|
|
{
|
|
// non-zoom case
|
|
if (scalex == 0x10000 && scaley == 0x10000)
|
|
return transpen(dest, cliprect, code, color, flipx, flipy, destx, desty, trans_pen);
|
|
|
|
// special case invalid pens to opaque
|
|
if (trans_pen > 0xff)
|
|
return zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley);
|
|
|
|
// use pen usage to optimize
|
|
code %= elements();
|
|
if (has_pen_usage())
|
|
{
|
|
// fully transparent; do nothing
|
|
u32 usage = pen_usage(code);
|
|
if ((usage & ~(1 << trans_pen)) == 0)
|
|
return;
|
|
|
|
// fully opaque; draw as such
|
|
if ((usage & (1 << trans_pen)) == 0)
|
|
return zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley);
|
|
}
|
|
|
|
// render
|
|
color = colorbase() + granularity() * (color % colors());
|
|
DECLARE_NO_PRIORITY;
|
|
DRAWGFXZOOM_CORE(u16, PIXEL_OP_REBASE_TRANSPEN, NO_PRIORITY);
|
|
}
|
|
|
|
void gfx_element::zoom_transpen(bitmap_rgb32 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
u32 scalex, u32 scaley, u32 trans_pen)
|
|
{
|
|
// non-zoom case
|
|
if (scalex == 0x10000 && scaley == 0x10000)
|
|
return transpen(dest, cliprect, code, color, flipx, flipy, destx, desty, trans_pen);
|
|
|
|
// special case invalid pens to opaque
|
|
if (trans_pen > 0xff)
|
|
return zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley);
|
|
|
|
// use pen usage to optimize
|
|
code %= elements();
|
|
if (has_pen_usage())
|
|
{
|
|
// fully transparent; do nothing
|
|
u32 usage = pen_usage(code);
|
|
if ((usage & ~(1 << trans_pen)) == 0)
|
|
return;
|
|
|
|
// fully opaque; draw as such
|
|
if ((usage & (1 << trans_pen)) == 0)
|
|
return zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley);
|
|
}
|
|
|
|
// render
|
|
const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
|
|
DECLARE_NO_PRIORITY;
|
|
DRAWGFXZOOM_CORE(u32, PIXEL_OP_REMAP_TRANSPEN, NO_PRIORITY);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
zoom_transpen_raw - render a scaled gfx
|
|
element with a single transparent pen and no
|
|
color lookups
|
|
-------------------------------------------------*/
|
|
|
|
void gfx_element::zoom_transpen_raw(bitmap_ind16 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
u32 scalex, u32 scaley, u32 trans_pen)
|
|
{
|
|
// non-zoom case
|
|
if (scalex == 0x10000 && scaley == 0x10000)
|
|
return transpen_raw(dest, cliprect, code, color, flipx, flipy, destx, desty, trans_pen);
|
|
|
|
// early out if completely transparent
|
|
code %= elements();
|
|
if (has_pen_usage() && (pen_usage(code) & ~(1 << trans_pen)) == 0)
|
|
return;
|
|
|
|
// render
|
|
DECLARE_NO_PRIORITY;
|
|
DRAWGFXZOOM_CORE(u16, PIXEL_OP_REBASE_TRANSPEN, NO_PRIORITY);
|
|
}
|
|
|
|
void gfx_element::zoom_transpen_raw(bitmap_rgb32 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
u32 scalex, u32 scaley, u32 trans_pen)
|
|
{
|
|
// non-zoom case
|
|
if (scalex == 0x10000 && scaley == 0x10000)
|
|
return transpen_raw(dest, cliprect, code, color, flipx, flipy, destx, desty, trans_pen);
|
|
|
|
// early out if completely transparent
|
|
code %= elements();
|
|
if (has_pen_usage() && (pen_usage(code) & ~(1 << trans_pen)) == 0)
|
|
return;
|
|
|
|
// render
|
|
DECLARE_NO_PRIORITY;
|
|
DRAWGFXZOOM_CORE(u32, PIXEL_OP_REBASE_TRANSPEN, NO_PRIORITY);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
zoom_transmask - render a scaled gfx
|
|
element with a multiple transparent pens
|
|
provided as a mask
|
|
-------------------------------------------------*/
|
|
|
|
void gfx_element::zoom_transmask(bitmap_ind16 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
u32 scalex, u32 scaley, u32 trans_mask)
|
|
{
|
|
// non-zoom case
|
|
if (scalex == 0x10000 && scaley == 0x10000)
|
|
return transmask(dest, cliprect, code, color, flipx, flipy, destx, desty, trans_mask);
|
|
|
|
// special case 0 mask to opaque
|
|
if (trans_mask == 0)
|
|
return zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley);
|
|
|
|
// use pen usage to optimize
|
|
code %= elements();
|
|
if (has_pen_usage())
|
|
{
|
|
// fully transparent; do nothing
|
|
u32 usage = pen_usage(code);
|
|
if ((usage & ~trans_mask) == 0)
|
|
return;
|
|
|
|
// fully opaque; draw as such
|
|
if ((usage & trans_mask) == 0)
|
|
return zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley);
|
|
}
|
|
|
|
// render
|
|
color = colorbase() + granularity() * (color % colors());
|
|
DECLARE_NO_PRIORITY;
|
|
DRAWGFXZOOM_CORE(u16, PIXEL_OP_REBASE_TRANSMASK, NO_PRIORITY);
|
|
}
|
|
|
|
void gfx_element::zoom_transmask(bitmap_rgb32 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
u32 scalex, u32 scaley, u32 trans_mask)
|
|
{
|
|
// non-zoom case
|
|
if (scalex == 0x10000 && scaley == 0x10000)
|
|
return transmask(dest, cliprect, code, color, flipx, flipy, destx, desty, trans_mask);
|
|
|
|
// special case 0 mask to opaque
|
|
if (trans_mask == 0)
|
|
return zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley);
|
|
|
|
// use pen usage to optimize
|
|
code %= elements();
|
|
if (has_pen_usage())
|
|
{
|
|
// fully transparent; do nothing
|
|
u32 usage = pen_usage(code);
|
|
if ((usage & ~trans_mask) == 0)
|
|
return;
|
|
|
|
// fully opaque; draw as such
|
|
if ((usage & trans_mask) == 0)
|
|
return zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley);
|
|
}
|
|
|
|
// render
|
|
const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
|
|
DECLARE_NO_PRIORITY;
|
|
DRAWGFXZOOM_CORE(u32, PIXEL_OP_REMAP_TRANSMASK, NO_PRIORITY);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
zoom_transtable - render a scaled gfx
|
|
element using a table to look up which pens
|
|
are transparent, opaque, or shadowing
|
|
-------------------------------------------------*/
|
|
|
|
void gfx_element::zoom_transtable(bitmap_ind16 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
u32 scalex, u32 scaley, const u8 *pentable)
|
|
{
|
|
assert(pentable != nullptr);
|
|
|
|
// non-zoom case
|
|
if (scalex == 0x10000 && scaley == 0x10000)
|
|
return transtable(dest, cliprect, code, color, flipx, flipy, destx, desty, pentable);
|
|
|
|
// render
|
|
color = colorbase() + granularity() * (color % colors());
|
|
const pen_t *shadowtable = m_palette->shadow_table();
|
|
code %= elements();
|
|
DECLARE_NO_PRIORITY;
|
|
DRAWGFXZOOM_CORE(u16, PIXEL_OP_REBASE_TRANSTABLE16, NO_PRIORITY);
|
|
}
|
|
|
|
void gfx_element::zoom_transtable(bitmap_rgb32 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
u32 scalex, u32 scaley, const u8 *pentable)
|
|
{
|
|
assert(pentable != nullptr);
|
|
|
|
// non-zoom case
|
|
if (scalex == 0x10000 && scaley == 0x10000)
|
|
return transtable(dest, cliprect, code, color, flipx, flipy, destx, desty, pentable);
|
|
|
|
// render
|
|
const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
|
|
const pen_t *shadowtable = m_palette->shadow_table();
|
|
code %= elements();
|
|
DECLARE_NO_PRIORITY;
|
|
DRAWGFXZOOM_CORE(u32, PIXEL_OP_REMAP_TRANSTABLE32, NO_PRIORITY);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
zoom_alpha - render a scaled gfx element
|
|
with a single transparent pen, alpha blending
|
|
the remaining pixels with a fixed alpha value
|
|
-------------------------------------------------*/
|
|
|
|
void gfx_element::zoom_alpha(bitmap_rgb32 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
u32 scalex, u32 scaley, u32 trans_pen, u8 alpha_val)
|
|
{
|
|
// non-zoom case
|
|
if (scalex == 0x10000 && scaley == 0x10000)
|
|
return alpha(dest, cliprect, code, color, flipx, flipy, destx, desty, trans_pen, alpha_val);
|
|
|
|
// special case alpha_val = 0xff
|
|
if (alpha_val == 0xff)
|
|
return zoom_transpen(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley, trans_pen);
|
|
|
|
// early out if completely transparent
|
|
code %= elements();
|
|
if (has_pen_usage() && (pen_usage(code) & ~(1 << trans_pen)) == 0)
|
|
return;
|
|
|
|
// render
|
|
const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
|
|
DECLARE_NO_PRIORITY;
|
|
DRAWGFXZOOM_CORE(u32, PIXEL_OP_REMAP_TRANSPEN_ALPHA32, NO_PRIORITY);
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
PDRAWGFX IMPLEMENTATIONS
|
|
***************************************************************************/
|
|
|
|
/*-------------------------------------------------
|
|
prio_opaque - render a gfx element with
|
|
no transparency, checking against the priority
|
|
bitmap
|
|
-------------------------------------------------*/
|
|
|
|
void gfx_element::prio_opaque(bitmap_ind16 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
bitmap_ind8 &priority, u32 pmask)
|
|
{
|
|
// high bit of the mask is implicitly on
|
|
pmask |= 1 << 31;
|
|
|
|
// render
|
|
color = colorbase() + granularity() * (color % colors());
|
|
code %= elements();
|
|
DRAWGFX_CORE(u16, PIXEL_OP_REBASE_OPAQUE_PRIORITY, u8);
|
|
}
|
|
|
|
void gfx_element::prio_opaque(bitmap_rgb32 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
bitmap_ind8 &priority, u32 pmask)
|
|
{
|
|
// high bit of the mask is implicitly on
|
|
pmask |= 1 << 31;
|
|
|
|
// render
|
|
const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
|
|
code %= elements();
|
|
DRAWGFX_CORE(u32, PIXEL_OP_REMAP_OPAQUE_PRIORITY, u8);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
prio_transpen - render a gfx element with
|
|
a single transparent pen, checking against the
|
|
priority bitmap
|
|
-------------------------------------------------*/
|
|
|
|
void gfx_element::prio_transpen(bitmap_ind16 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
bitmap_ind8 &priority, u32 pmask, u32 trans_pen)
|
|
{
|
|
// special case invalid pens to opaque
|
|
if (trans_pen > 0xff)
|
|
return prio_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask);
|
|
|
|
// use pen usage to optimize
|
|
code %= elements();
|
|
if (has_pen_usage())
|
|
{
|
|
// fully transparent; do nothing
|
|
u32 usage = pen_usage(code);
|
|
if ((usage & ~(1 << trans_pen)) == 0)
|
|
return;
|
|
|
|
// fully opaque; draw as such
|
|
if ((usage & (1 << trans_pen)) == 0)
|
|
return prio_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask);
|
|
}
|
|
|
|
// high bit of the mask is implicitly on
|
|
pmask |= 1 << 31;
|
|
|
|
// render
|
|
color = colorbase() + granularity() * (color % colors());
|
|
DRAWGFX_CORE(u16, PIXEL_OP_REBASE_TRANSPEN_PRIORITY, u8);
|
|
}
|
|
|
|
void gfx_element::prio_transpen(bitmap_rgb32 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
bitmap_ind8 &priority, u32 pmask, u32 trans_pen)
|
|
{
|
|
// special case invalid pens to opaque
|
|
if (trans_pen > 0xff)
|
|
return prio_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask);
|
|
|
|
// use pen usage to optimize
|
|
code %= elements();
|
|
if (has_pen_usage())
|
|
{
|
|
// fully transparent; do nothing
|
|
u32 usage = pen_usage(code);
|
|
if ((usage & ~(1 << trans_pen)) == 0)
|
|
return;
|
|
|
|
// fully opaque; draw as such
|
|
if ((usage & (1 << trans_pen)) == 0)
|
|
return prio_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask);
|
|
}
|
|
|
|
// high bit of the mask is implicitly on
|
|
pmask |= 1 << 31;
|
|
|
|
// render
|
|
const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
|
|
DRAWGFX_CORE(u32, PIXEL_OP_REMAP_TRANSPEN_PRIORITY, u8);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
priotranspen_raw - render a gfx element
|
|
with a single transparent pen and no color
|
|
lookups, checking against the priority bitmap
|
|
-------------------------------------------------*/
|
|
|
|
void gfx_element::prio_transpen_raw(bitmap_ind16 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
bitmap_ind8 &priority, u32 pmask, u32 trans_pen)
|
|
{
|
|
// early out if completely transparent
|
|
code %= elements();
|
|
if (has_pen_usage() && (pen_usage(code) & ~(1 << trans_pen)) == 0)
|
|
return;
|
|
|
|
// high bit of the mask is implicitly on
|
|
pmask |= 1 << 31;
|
|
|
|
// render
|
|
DRAWGFX_CORE(u16, PIXEL_OP_REBASE_TRANSPEN_PRIORITY, u8);
|
|
}
|
|
|
|
void gfx_element::prio_transpen_raw(bitmap_rgb32 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
bitmap_ind8 &priority, u32 pmask, u32 trans_pen)
|
|
{
|
|
// early out if completely transparent
|
|
code %= elements();
|
|
if (has_pen_usage() && (pen_usage(code) & ~(1 << trans_pen)) == 0)
|
|
return;
|
|
|
|
// high bit of the mask is implicitly on
|
|
pmask |= 1 << 31;
|
|
|
|
// render
|
|
DRAWGFX_CORE(u32, PIXEL_OP_REBASE_TRANSPEN_PRIORITY, u8);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
prio_transmask - render a gfx element
|
|
with a multiple transparent pens provided as
|
|
a mask, checking against the priority bitmap
|
|
-------------------------------------------------*/
|
|
|
|
void gfx_element::prio_transmask(bitmap_ind16 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
bitmap_ind8 &priority, u32 pmask, u32 trans_mask)
|
|
{
|
|
// special case 0 mask to opaque
|
|
if (trans_mask == 0)
|
|
return prio_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask);
|
|
|
|
// use pen usage to optimize
|
|
code %= elements();
|
|
if (has_pen_usage())
|
|
{
|
|
// fully transparent; do nothing
|
|
u32 usage = pen_usage(code);
|
|
if ((usage & ~trans_mask) == 0)
|
|
return;
|
|
|
|
// fully opaque; draw as such
|
|
if ((usage & trans_mask) == 0)
|
|
return prio_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask);
|
|
}
|
|
|
|
// high bit of the mask is implicitly on
|
|
pmask |= 1 << 31;
|
|
|
|
// render
|
|
color = colorbase() + granularity() * (color % colors());
|
|
DRAWGFX_CORE(u16, PIXEL_OP_REBASE_TRANSMASK_PRIORITY, u8);
|
|
}
|
|
|
|
void gfx_element::prio_transmask(bitmap_rgb32 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
bitmap_ind8 &priority, u32 pmask, u32 trans_mask)
|
|
{
|
|
// special case 0 mask to opaque
|
|
if (trans_mask == 0)
|
|
return prio_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask);
|
|
|
|
// use pen usage to optimize
|
|
code %= elements();
|
|
if (has_pen_usage())
|
|
{
|
|
// fully transparent; do nothing
|
|
u32 usage = pen_usage(code);
|
|
if ((usage & ~trans_mask) == 0)
|
|
return;
|
|
|
|
// fully opaque; draw as such
|
|
if ((usage & trans_mask) == 0)
|
|
return prio_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask);
|
|
}
|
|
|
|
// high bit of the mask is implicitly on
|
|
pmask |= 1 << 31;
|
|
|
|
// render
|
|
const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
|
|
DRAWGFX_CORE(u32, PIXEL_OP_REMAP_TRANSMASK_PRIORITY, u8);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
prio_transtable - render a gfx element
|
|
using a table to look up which pens are
|
|
transparent, opaque, or shadowing, checking
|
|
against the priority bitmap
|
|
-------------------------------------------------*/
|
|
|
|
void gfx_element::prio_transtable(bitmap_ind16 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
bitmap_ind8 &priority, u32 pmask, const u8 *pentable)
|
|
{
|
|
assert(pentable != nullptr);
|
|
|
|
// high bit of the mask is implicitly on
|
|
pmask |= 1 << 31;
|
|
|
|
// render
|
|
color = colorbase() + granularity() * (color % colors());
|
|
const pen_t *shadowtable = m_palette->shadow_table();
|
|
code %= elements();
|
|
DRAWGFX_CORE(u16, PIXEL_OP_REBASE_TRANSTABLE16_PRIORITY, u8);
|
|
}
|
|
|
|
void gfx_element::prio_transtable(bitmap_rgb32 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
bitmap_ind8 &priority, u32 pmask, const u8 *pentable)
|
|
{
|
|
assert(pentable != nullptr);
|
|
|
|
// high bit of the mask is implicitly on
|
|
pmask |= 1 << 31;
|
|
|
|
// render
|
|
const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
|
|
const pen_t *shadowtable = m_palette->shadow_table();
|
|
code %= elements();
|
|
DRAWGFX_CORE(u32, PIXEL_OP_REMAP_TRANSTABLE32_PRIORITY, u8);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
prio_alpha - render a gfx element with
|
|
a single transparent pen, alpha blending the
|
|
remaining pixels with a fixed alpha value,
|
|
checking against the priority bitmap
|
|
-------------------------------------------------*/
|
|
|
|
void gfx_element::prio_alpha(bitmap_rgb32 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
bitmap_ind8 &priority, u32 pmask, u32 trans_pen, u8 alpha_val)
|
|
{
|
|
// special case alpha = 0xff
|
|
if (alpha_val == 0xff)
|
|
return prio_transpen(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask, trans_pen);
|
|
|
|
// early out if completely transparent
|
|
code %= elements();
|
|
if (has_pen_usage() && (pen_usage(code) & ~(1 << trans_pen)) == 0)
|
|
return;
|
|
|
|
// high bit of the mask is implicitly on
|
|
pmask |= 1 << 31;
|
|
|
|
// render
|
|
const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
|
|
DRAWGFX_CORE(u32, PIXEL_OP_REMAP_TRANSPEN_ALPHA32_PRIORITY, u8);
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
PDRAWGFXZOOM IMPLEMENTATIONS
|
|
***************************************************************************/
|
|
|
|
/*-------------------------------------------------
|
|
prio_zoom_opaque - render a scaled gfx
|
|
element with no transparency, checking against
|
|
the priority bitmap
|
|
-------------------------------------------------*/
|
|
|
|
void gfx_element::prio_zoom_opaque(bitmap_ind16 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
u32 scalex, u32 scaley, bitmap_ind8 &priority, u32 pmask)
|
|
{
|
|
// non-zoom case
|
|
if (scalex == 0x10000 && scaley == 0x10000)
|
|
return prio_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask);
|
|
|
|
// high bit of the mask is implicitly on
|
|
pmask |= 1 << 31;
|
|
|
|
// render
|
|
color = colorbase() + granularity() * (color % colors());
|
|
code %= elements();
|
|
DRAWGFXZOOM_CORE(u16, PIXEL_OP_REBASE_OPAQUE_PRIORITY, u8);
|
|
}
|
|
|
|
void gfx_element::prio_zoom_opaque(bitmap_rgb32 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
u32 scalex, u32 scaley, bitmap_ind8 &priority, u32 pmask)
|
|
{
|
|
// non-zoom case
|
|
if (scalex == 0x10000 && scaley == 0x10000)
|
|
return prio_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask);
|
|
|
|
// high bit of the mask is implicitly on
|
|
pmask |= 1 << 31;
|
|
|
|
// render
|
|
const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
|
|
code %= elements();
|
|
DRAWGFXZOOM_CORE(u32, PIXEL_OP_REMAP_OPAQUE_PRIORITY, u8);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
prio_zoom_transpen - render a scaled gfx
|
|
element with a single transparent pen,
|
|
checking against the priority bitmap
|
|
-------------------------------------------------*/
|
|
|
|
void gfx_element::prio_zoom_transpen(bitmap_ind16 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
u32 scalex, u32 scaley, bitmap_ind8 &priority, u32 pmask,
|
|
u32 trans_pen)
|
|
{
|
|
// non-zoom case
|
|
if (scalex == 0x10000 && scaley == 0x10000)
|
|
return prio_transpen(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask, trans_pen);
|
|
|
|
// special case invalid pens to opaque
|
|
if (trans_pen > 0xff)
|
|
return prio_zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley, priority, pmask);
|
|
|
|
// use pen usage to optimize
|
|
code %= elements();
|
|
if (has_pen_usage())
|
|
{
|
|
// fully transparent; do nothing
|
|
u32 usage = pen_usage(code);
|
|
if ((usage & ~(1 << trans_pen)) == 0)
|
|
return;
|
|
|
|
// fully opaque; draw as such
|
|
if ((usage & (1 << trans_pen)) == 0)
|
|
return prio_zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley, priority, pmask);
|
|
}
|
|
|
|
// high bit of the mask is implicitly on
|
|
pmask |= 1 << 31;
|
|
|
|
// render
|
|
color = colorbase() + granularity() * (color % colors());
|
|
DRAWGFXZOOM_CORE(u16, PIXEL_OP_REBASE_TRANSPEN_PRIORITY, u8);
|
|
}
|
|
|
|
void gfx_element::prio_zoom_transpen(bitmap_rgb32 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
u32 scalex, u32 scaley, bitmap_ind8 &priority, u32 pmask,
|
|
u32 trans_pen)
|
|
{
|
|
// non-zoom case
|
|
if (scalex == 0x10000 && scaley == 0x10000)
|
|
return prio_transpen(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask, trans_pen);
|
|
|
|
// special case invalid pens to opaque
|
|
if (trans_pen > 0xff)
|
|
return prio_zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley, priority, pmask);
|
|
|
|
// use pen usage to optimize
|
|
code %= elements();
|
|
if (has_pen_usage())
|
|
{
|
|
// fully transparent; do nothing
|
|
u32 usage = pen_usage(code);
|
|
if ((usage & ~(1 << trans_pen)) == 0)
|
|
return;
|
|
|
|
// fully opaque; draw as such
|
|
if ((usage & (1 << trans_pen)) == 0)
|
|
return prio_zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley, priority, pmask);
|
|
}
|
|
|
|
// high bit of the mask is implicitly on
|
|
pmask |= 1 << 31;
|
|
|
|
// render
|
|
const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
|
|
DRAWGFXZOOM_CORE(u32, PIXEL_OP_REMAP_TRANSPEN_PRIORITY, u8);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
prio_zoom_transpen_raw - render a scaled gfx
|
|
element with a single transparent pen and no
|
|
color lookups, checking against the priority
|
|
bitmap
|
|
-------------------------------------------------*/
|
|
|
|
void gfx_element::prio_zoom_transpen_raw(bitmap_ind16 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
u32 scalex, u32 scaley, bitmap_ind8 &priority, u32 pmask,
|
|
u32 trans_pen)
|
|
{
|
|
// non-zoom case
|
|
if (scalex == 0x10000 && scaley == 0x10000)
|
|
return prio_transpen_raw(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask, trans_pen);
|
|
|
|
// early out if completely transparent
|
|
code %= elements();
|
|
if (has_pen_usage() && (pen_usage(code) & ~(1 << trans_pen)) == 0)
|
|
return;
|
|
|
|
// high bit of the mask is implicitly on
|
|
pmask |= 1 << 31;
|
|
|
|
// render
|
|
DRAWGFXZOOM_CORE(u16, PIXEL_OP_REBASE_TRANSPEN_PRIORITY, u8);
|
|
}
|
|
|
|
void gfx_element::prio_zoom_transpen_raw(bitmap_rgb32 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
u32 scalex, u32 scaley, bitmap_ind8 &priority, u32 pmask,
|
|
u32 trans_pen)
|
|
{
|
|
// non-zoom case
|
|
if (scalex == 0x10000 && scaley == 0x10000)
|
|
return prio_transpen_raw(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask, trans_pen);
|
|
|
|
// early out if completely transparent
|
|
code %= elements();
|
|
if (has_pen_usage() && (pen_usage(code) & ~(1 << trans_pen)) == 0)
|
|
return;
|
|
|
|
// high bit of the mask is implicitly on
|
|
pmask |= 1 << 31;
|
|
|
|
// render
|
|
DRAWGFXZOOM_CORE(u32, PIXEL_OP_REBASE_TRANSPEN_PRIORITY, u8);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
prio_zoom_transmask - render a scaled gfx
|
|
element with a multiple transparent pens
|
|
provided as a mask, checking against the
|
|
priority bitmap
|
|
-------------------------------------------------*/
|
|
|
|
void gfx_element::prio_zoom_transmask(bitmap_ind16 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
u32 scalex, u32 scaley, bitmap_ind8 &priority, u32 pmask,
|
|
u32 trans_mask)
|
|
{
|
|
// non-zoom case
|
|
if (scalex == 0x10000 && scaley == 0x10000)
|
|
return prio_transmask(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask, trans_mask);
|
|
|
|
// special case 0 mask to opaque
|
|
if (trans_mask == 0)
|
|
return prio_zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley, priority, pmask);
|
|
|
|
// use pen usage to optimize
|
|
code %= elements();
|
|
if (has_pen_usage())
|
|
{
|
|
// fully transparent; do nothing
|
|
u32 usage = pen_usage(code);
|
|
if ((usage & ~trans_mask) == 0)
|
|
return;
|
|
|
|
// fully opaque; draw as such
|
|
if ((usage & trans_mask) == 0)
|
|
return prio_zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley, priority, pmask);
|
|
}
|
|
|
|
// high bit of the mask is implicitly on
|
|
pmask |= 1 << 31;
|
|
|
|
// render
|
|
color = colorbase() + granularity() * (color % colors());
|
|
DRAWGFXZOOM_CORE(u16, PIXEL_OP_REBASE_TRANSMASK_PRIORITY, u8);
|
|
}
|
|
|
|
void gfx_element::prio_zoom_transmask(bitmap_rgb32 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
u32 scalex, u32 scaley, bitmap_ind8 &priority, u32 pmask,
|
|
u32 trans_mask)
|
|
{
|
|
// non-zoom case
|
|
if (scalex == 0x10000 && scaley == 0x10000)
|
|
return prio_transmask(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask, trans_mask);
|
|
|
|
// special case 0 mask to opaque
|
|
if (trans_mask == 0)
|
|
return prio_zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley, priority, pmask);
|
|
|
|
// use pen usage to optimize
|
|
code %= elements();
|
|
if (has_pen_usage())
|
|
{
|
|
// fully transparent; do nothing
|
|
u32 usage = pen_usage(code);
|
|
if ((usage & ~trans_mask) == 0)
|
|
return;
|
|
|
|
// fully opaque; draw as such
|
|
if ((usage & trans_mask) == 0)
|
|
return prio_zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley, priority, pmask);
|
|
}
|
|
|
|
// high bit of the mask is implicitly on
|
|
pmask |= 1 << 31;
|
|
|
|
// render
|
|
const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
|
|
DRAWGFXZOOM_CORE(u32, PIXEL_OP_REMAP_TRANSMASK_PRIORITY, u8);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
prio_zoom_transtable - render a scaled gfx
|
|
element using a table to look up which pens
|
|
are transparent, opaque, or shadowing,
|
|
checking against the priority bitmap
|
|
-------------------------------------------------*/
|
|
|
|
void gfx_element::prio_zoom_transtable(bitmap_ind16 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
u32 scalex, u32 scaley, bitmap_ind8 &priority, u32 pmask,
|
|
const u8 *pentable)
|
|
{
|
|
assert(pentable != nullptr);
|
|
|
|
// non-zoom case
|
|
if (scalex == 0x10000 && scaley == 0x10000)
|
|
return prio_transtable(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask, pentable);
|
|
|
|
// high bit of the mask is implicitly on
|
|
pmask |= 1 << 31;
|
|
|
|
// render
|
|
color = colorbase() + granularity() * (color % colors());
|
|
const pen_t *shadowtable = m_palette->shadow_table();
|
|
code %= elements();
|
|
DRAWGFXZOOM_CORE(u16, PIXEL_OP_REBASE_TRANSTABLE16_PRIORITY, u8);
|
|
}
|
|
|
|
void gfx_element::prio_zoom_transtable(bitmap_rgb32 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
u32 scalex, u32 scaley, bitmap_ind8 &priority, u32 pmask,
|
|
const u8 *pentable)
|
|
{
|
|
assert(pentable != nullptr);
|
|
|
|
// non-zoom case
|
|
if (scalex == 0x10000 && scaley == 0x10000)
|
|
return prio_transtable(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask, pentable);
|
|
|
|
// high bit of the mask is implicitly on
|
|
pmask |= 1 << 31;
|
|
|
|
// render
|
|
const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
|
|
const pen_t *shadowtable = m_palette->shadow_table();
|
|
code %= elements();
|
|
DRAWGFXZOOM_CORE(u32, PIXEL_OP_REMAP_TRANSTABLE32_PRIORITY, u8);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
prio_zoom_alpha - render a scaled gfx
|
|
element with a single transparent pen, alpha
|
|
blending the remaining pixels with a fixed
|
|
alpha value, checking against the priority
|
|
bitmap
|
|
-------------------------------------------------*/
|
|
|
|
void gfx_element::prio_zoom_alpha(bitmap_rgb32 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
u32 scalex, u32 scaley, bitmap_ind8 &priority, u32 pmask,
|
|
u32 trans_pen, u8 alpha_val)
|
|
{
|
|
// non-zoom case
|
|
if (scalex == 0x10000 && scaley == 0x10000)
|
|
return prio_alpha(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask, trans_pen, alpha_val);
|
|
|
|
// special case alpha_val = 0xff
|
|
if (alpha_val == 0xff)
|
|
return prio_zoom_transpen(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley, priority, pmask, trans_pen);
|
|
|
|
// early out if completely transparent
|
|
code %= elements();
|
|
if (has_pen_usage() && (pen_usage(code) & ~(1 << trans_pen)) == 0)
|
|
return;
|
|
|
|
// high bit of the mask is implicitly on
|
|
pmask |= 1 << 31;
|
|
|
|
// render
|
|
const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
|
|
DRAWGFXZOOM_CORE(u32, PIXEL_OP_REMAP_TRANSPEN_ALPHA32_PRIORITY, u8);
|
|
}
|
|
|
|
|
|
#define PIXEL_OP_REMAP_TRANSPEN_PRIORITY_ADDIIVE32(DEST, PRIORITY, SOURCE) \
|
|
do \
|
|
{ \
|
|
u32 srcdata = (SOURCE); \
|
|
if (srcdata != trans_pen) \
|
|
{ \
|
|
if (((1 << ((PRIORITY) & 0x1f)) & pmask) == 0) \
|
|
{ \
|
|
u32 srcdata2 = paldata[srcdata]; \
|
|
\
|
|
u32 add; \
|
|
add = (srcdata2 & 0x00ff0000) + (DEST & 0x00ff0000); \
|
|
if (add & 0x01000000) DEST = (DEST & 0xff00ffff) | (0x00ff0000); \
|
|
else DEST = (DEST & 0xff00ffff) | (add & 0x00ff0000); \
|
|
add = (srcdata2 & 0x000000ff) + (DEST & 0x000000ff); \
|
|
if (add & 0x00000100) DEST = (DEST & 0xffffff00) | (0x000000ff); \
|
|
else DEST = (DEST & 0xffffff00) | (add & 0x000000ff); \
|
|
add = (srcdata2 & 0x0000ff00) + (DEST & 0x0000ff00); \
|
|
if (add & 0x00010000) DEST = (DEST & 0xffff00ff) | (0x0000ff00); \
|
|
else DEST = (DEST & 0xffff00ff) | (add & 0x0000ff00); \
|
|
} \
|
|
(PRIORITY) = 31; \
|
|
} \
|
|
} \
|
|
while (0)
|
|
|
|
void gfx_element::prio_transpen_additive(bitmap_rgb32 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
bitmap_ind8 &priority, u32 pmask, u32 trans_pen)
|
|
{
|
|
const pen_t *paldata;
|
|
|
|
assert(dest.valid());
|
|
assert(dest.bpp() == 32);
|
|
|
|
/* get final code and color, and grab lookup tables */
|
|
code %= elements();
|
|
color %= colors();
|
|
paldata = m_palette->pens() + colorbase() + granularity() * color;
|
|
|
|
/* use pen usage to optimize */
|
|
if (has_pen_usage())
|
|
{
|
|
u32 usage = pen_usage(code);
|
|
|
|
/* fully transparent; do nothing */
|
|
if ((usage & ~(1 << trans_pen)) == 0)
|
|
return;
|
|
}
|
|
|
|
/* high bit of the mask is implicitly on */
|
|
pmask |= 1 << 31;
|
|
|
|
/* render based on dest bitmap depth */
|
|
DRAWGFX_CORE(u32, PIXEL_OP_REMAP_TRANSPEN_PRIORITY_ADDIIVE32, u8);
|
|
}
|
|
|
|
|
|
void gfx_element::prio_zoom_transpen_additive(bitmap_rgb32 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
u32 scalex, u32 scaley, bitmap_ind8 &priority, u32 pmask,
|
|
u32 trans_pen)
|
|
{
|
|
const pen_t *paldata;
|
|
|
|
/* non-zoom case */
|
|
|
|
if (scalex == 0x10000 && scaley == 0x10000)
|
|
{
|
|
prio_transpen_additive(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask, trans_pen);
|
|
return;
|
|
}
|
|
|
|
assert(dest.valid());
|
|
assert(dest.bpp() == 32);
|
|
|
|
/* get final code and color, and grab lookup tables */
|
|
code %= elements();
|
|
color %= colors();
|
|
paldata = m_palette->pens() + colorbase() + granularity() * color;
|
|
|
|
/* use pen usage to optimize */
|
|
if (has_pen_usage())
|
|
{
|
|
u32 usage = pen_usage(code);
|
|
|
|
/* fully transparent; do nothing */
|
|
if ((usage & ~(1 << trans_pen)) == 0)
|
|
return;
|
|
}
|
|
|
|
/* high bit of the mask is implicitly on */
|
|
pmask |= 1 << 31;
|
|
|
|
DRAWGFXZOOM_CORE(u32, PIXEL_OP_REMAP_TRANSPEN_PRIORITY_ADDIIVE32, u8);
|
|
}
|
|
|
|
//#define MAKE_ARGB_RGB(a, rgb) rgb_t(a, rgb.r(), rgb.g(), rgb.b())
|
|
#define MAKE_ARGB_RGB(a, rgb) rgb_t(rgb).set_a(a)
|
|
|
|
// combine in 'alpha' when copying to store in ARGB
|
|
#define PIXEL_OP_REMAP_TRANS0_ALPHASTORE32(DEST, PRIORITY, SOURCE) \
|
|
do \
|
|
{ \
|
|
u32 srcdata = (SOURCE); \
|
|
if (srcdata != 0) \
|
|
(DEST) = MAKE_ARGB_RGB(alpha,paldata[srcdata]); \
|
|
} \
|
|
while (0)
|
|
// combine in 'alphatable' value to store in ARGB
|
|
#define PIXEL_OP_REMAP_TRANS0_ALPHATABLESTORE32(DEST, PRIORITY, SOURCE) \
|
|
do \
|
|
{ \
|
|
u32 srcdata = (SOURCE); \
|
|
if (srcdata != 0) \
|
|
(DEST) = MAKE_ARGB_RGB(alphatable[srcdata], paldata[srcdata]); \
|
|
} \
|
|
while (0)
|
|
// drawgfxm.h macro to render alpha into 32-bit buffer
|
|
#define PIXEL_OP_REMAP_TRANS0_ALPHATABLE32(DEST, PRIORITY, SOURCE) \
|
|
do \
|
|
{ \
|
|
u32 srcdata = (SOURCE); \
|
|
if (srcdata != 0) \
|
|
(DEST) = alpha_blend_r32((DEST), paldata[srcdata], alphatable[srcdata]); \
|
|
} \
|
|
while (0)
|
|
|
|
/*-------------------------------------------------
|
|
alphastore - render a gfx element with
|
|
a single transparent pen, storing the alpha value
|
|
in alpha field of ARGB32, negative alpha implies alphatable
|
|
-------------------------------------------------*/
|
|
void gfx_element::alphastore(bitmap_rgb32 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
int fixedalpha, u8 *alphatable)
|
|
{
|
|
DECLARE_NO_PRIORITY;
|
|
const pen_t *paldata;
|
|
|
|
assert(alphatable != nullptr);
|
|
|
|
/* if we have a fixed alpha, call the standard drawgfx_transpen */
|
|
if (fixedalpha == 0xff)
|
|
{
|
|
transpen(dest, cliprect, code, color, flipx, flipy, destx, desty, 0);
|
|
return;
|
|
}
|
|
|
|
/* get final code and color, and grab lookup tables */
|
|
code %= elements();
|
|
color %= colors();
|
|
paldata = m_palette->pens() + colorbase() + granularity() * color;
|
|
|
|
/* early out if completely transparent */
|
|
if (has_pen_usage() && (pen_usage(code) & ~(1 << 0)) == 0)
|
|
return;
|
|
|
|
if (fixedalpha >= 0)
|
|
{
|
|
u8 alpha = fixedalpha;
|
|
DRAWGFX_CORE(u32, PIXEL_OP_REMAP_TRANS0_ALPHASTORE32, NO_PRIORITY);
|
|
}
|
|
else
|
|
{
|
|
DRAWGFX_CORE(u32, PIXEL_OP_REMAP_TRANS0_ALPHATABLESTORE32, NO_PRIORITY);
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------------
|
|
alphatable - render a sprite with either
|
|
a fixed alpha value, or if alpha==-1 then uses
|
|
the per-pen alphatable[] array
|
|
-------------------------------------------------*/
|
|
void gfx_element::alphatable(bitmap_rgb32 &dest, const rectangle &cliprect,
|
|
u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
|
|
int fixedalpha ,u8 *alphatable)
|
|
{
|
|
DECLARE_NO_PRIORITY;
|
|
|
|
const pen_t *paldata;
|
|
|
|
/* if we have a fixed alpha, call the standard drawgfx_alpha */
|
|
if (fixedalpha >= 0)
|
|
{
|
|
alpha(dest, cliprect, code, color, flipx, flipy, destx, desty, 0, fixedalpha);
|
|
return;
|
|
}
|
|
|
|
assert(dest.bpp() == 32);
|
|
assert(alphatable != nullptr);
|
|
|
|
/* get final code and color, and grab lookup tables */
|
|
code %= elements();
|
|
color %= colors();
|
|
paldata = m_palette->pens() + colorbase() + granularity() * color;
|
|
|
|
/* early out if completely transparent */
|
|
if (has_pen_usage() && (pen_usage(code) & ~(1 << 0)) == 0)
|
|
return;
|
|
|
|
DRAWGFX_CORE(u32, PIXEL_OP_REMAP_TRANS0_ALPHATABLE32, NO_PRIORITY);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
DRAW_SCANLINE IMPLEMENTATIONS
|
|
***************************************************************************/
|
|
|
|
/*-------------------------------------------------
|
|
draw_scanline8 - copy pixels from an 8bpp
|
|
buffer to a single scanline of a bitmap
|
|
-------------------------------------------------*/
|
|
|
|
void draw_scanline8(bitmap_ind16 &bitmap, s32 destx, s32 desty, s32 length, const u8 *srcptr, const pen_t *paldata)
|
|
{
|
|
DECLARE_NO_PRIORITY;
|
|
|
|
// palette lookup case
|
|
if (paldata != nullptr)
|
|
DRAWSCANLINE_CORE(u16, PIXEL_OP_REMAP_OPAQUE, NO_PRIORITY);
|
|
|
|
// raw copy case
|
|
else
|
|
DRAWSCANLINE_CORE(u16, PIXEL_OP_COPY_OPAQUE, NO_PRIORITY);
|
|
}
|
|
|
|
void draw_scanline8(bitmap_rgb32 &bitmap, s32 destx, s32 desty, s32 length, const u8 *srcptr, const pen_t *paldata)
|
|
{
|
|
DECLARE_NO_PRIORITY;
|
|
|
|
// palette lookup case
|
|
if (paldata != nullptr)
|
|
DRAWSCANLINE_CORE(u32, PIXEL_OP_REMAP_OPAQUE, NO_PRIORITY);
|
|
|
|
// raw copy case
|
|
else
|
|
DRAWSCANLINE_CORE(u32, PIXEL_OP_COPY_OPAQUE, NO_PRIORITY);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
draw_scanline16 - copy pixels from a 16bpp
|
|
buffer to a single scanline of a bitmap
|
|
-------------------------------------------------*/
|
|
|
|
void draw_scanline16(bitmap_ind16 &bitmap, s32 destx, s32 desty, s32 length, const u16 *srcptr, const pen_t *paldata)
|
|
{
|
|
DECLARE_NO_PRIORITY;
|
|
|
|
// palette lookup case
|
|
if (paldata != nullptr)
|
|
DRAWSCANLINE_CORE(u16, PIXEL_OP_REMAP_OPAQUE, NO_PRIORITY);
|
|
|
|
// raw copy case
|
|
else
|
|
DRAWSCANLINE_CORE(u16, PIXEL_OP_COPY_OPAQUE, NO_PRIORITY);
|
|
}
|
|
|
|
void draw_scanline16(bitmap_rgb32 &bitmap, s32 destx, s32 desty, s32 length, const u16 *srcptr, const pen_t *paldata)
|
|
{
|
|
DECLARE_NO_PRIORITY;
|
|
|
|
// palette lookup case
|
|
if (paldata != nullptr)
|
|
DRAWSCANLINE_CORE(u32, PIXEL_OP_REMAP_OPAQUE, NO_PRIORITY);
|
|
|
|
// raw copy case
|
|
else
|
|
DRAWSCANLINE_CORE(u32, PIXEL_OP_COPY_OPAQUE, NO_PRIORITY);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
draw_scanline32 - copy pixels from a 32bpp
|
|
buffer to a single scanline of a bitmap
|
|
-------------------------------------------------*/
|
|
|
|
void draw_scanline32(bitmap_ind16 &bitmap, s32 destx, s32 desty, s32 length, const u32 *srcptr, const pen_t *paldata)
|
|
{
|
|
DECLARE_NO_PRIORITY;
|
|
|
|
// palette lookup case
|
|
if (paldata != nullptr)
|
|
DRAWSCANLINE_CORE(u16, PIXEL_OP_REMAP_OPAQUE, NO_PRIORITY);
|
|
|
|
// raw copy case
|
|
else
|
|
DRAWSCANLINE_CORE(u16, PIXEL_OP_COPY_OPAQUE, NO_PRIORITY);
|
|
}
|
|
|
|
void draw_scanline32(bitmap_rgb32 &bitmap, s32 destx, s32 desty, s32 length, const u32 *srcptr, const pen_t *paldata)
|
|
{
|
|
DECLARE_NO_PRIORITY;
|
|
|
|
// palette lookup case
|
|
if (paldata != nullptr)
|
|
DRAWSCANLINE_CORE(u32, PIXEL_OP_REMAP_OPAQUE, NO_PRIORITY);
|
|
|
|
// raw copy case
|
|
else
|
|
DRAWSCANLINE_CORE(u32, PIXEL_OP_COPY_OPAQUE, NO_PRIORITY);
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
EXTRACT_SCANLINE IMPLEMENTATIONS
|
|
***************************************************************************/
|
|
|
|
/*-------------------------------------------------
|
|
extract_scanline8 - copy pixels from a single
|
|
scanline of a bitmap to an 8bpp buffer
|
|
-------------------------------------------------*/
|
|
|
|
void extract_scanline8(const bitmap_ind16 &bitmap, s32 srcx, s32 srcy, s32 length, u8 *destptr)
|
|
{
|
|
EXTRACTSCANLINE_CORE(u16);
|
|
}
|
|
|
|
void extract_scanline8(const bitmap_rgb32 &bitmap, s32 srcx, s32 srcy, s32 length, u8 *destptr)
|
|
{
|
|
EXTRACTSCANLINE_CORE(u32);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
extract_scanline16 - copy pixels from a single
|
|
scanline of a bitmap to a 16bpp buffer
|
|
-------------------------------------------------*/
|
|
|
|
void extract_scanline16(const bitmap_ind16 &bitmap, s32 srcx, s32 srcy, s32 length, u16 *destptr)
|
|
{
|
|
EXTRACTSCANLINE_CORE(u16);
|
|
}
|
|
|
|
void extract_scanline16(const bitmap_rgb32 &bitmap, s32 srcx, s32 srcy, s32 length, u16 *destptr)
|
|
{
|
|
EXTRACTSCANLINE_CORE(u32);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
extract_scanline32 - copy pixels from a single
|
|
scanline of a bitmap to a 32bpp buffer
|
|
-------------------------------------------------*/
|
|
|
|
void extract_scanline32(const bitmap_ind16 &bitmap, s32 srcx, s32 srcy, s32 length, u32 *destptr)
|
|
{
|
|
EXTRACTSCANLINE_CORE(u16);
|
|
}
|
|
|
|
void extract_scanline32(const bitmap_rgb32 &bitmap, s32 srcx, s32 srcy, s32 length, u32 *destptr)
|
|
{
|
|
EXTRACTSCANLINE_CORE(u32);
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
COPYBITMAP IMPLEMENTATIONS
|
|
***************************************************************************/
|
|
|
|
/*-------------------------------------------------
|
|
copybitmap - copy from one bitmap to another,
|
|
copying all unclipped pixels
|
|
-------------------------------------------------*/
|
|
|
|
void copybitmap(bitmap_ind16 &dest, const bitmap_ind16 &src, int flipx, int flipy, s32 destx, s32 desty, const rectangle &cliprect)
|
|
{
|
|
DECLARE_NO_PRIORITY;
|
|
COPYBITMAP_CORE(u16, PIXEL_OP_COPY_OPAQUE, NO_PRIORITY);
|
|
}
|
|
|
|
void copybitmap(bitmap_rgb32 &dest, const bitmap_rgb32 &src, int flipx, int flipy, s32 destx, s32 desty, const rectangle &cliprect)
|
|
{
|
|
DECLARE_NO_PRIORITY;
|
|
COPYBITMAP_CORE(u32, PIXEL_OP_COPY_OPAQUE, NO_PRIORITY);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
copybitmap_trans - copy from one bitmap to
|
|
another, copying all unclipped pixels except
|
|
those that match transpen
|
|
-------------------------------------------------*/
|
|
|
|
void copybitmap_trans(bitmap_ind16 &dest, const bitmap_ind16 &src, int flipx, int flipy, s32 destx, s32 desty, const rectangle &cliprect, u32 trans_pen)
|
|
{
|
|
DECLARE_NO_PRIORITY;
|
|
if (trans_pen > 0xffff)
|
|
copybitmap(dest, src, flipx, flipy, destx, desty, cliprect);
|
|
else
|
|
COPYBITMAP_CORE(u16, PIXEL_OP_COPY_TRANSPEN, NO_PRIORITY);
|
|
}
|
|
|
|
void copybitmap_trans(bitmap_rgb32 &dest, const bitmap_rgb32 &src, int flipx, int flipy, s32 destx, s32 desty, const rectangle &cliprect, u32 trans_pen)
|
|
{
|
|
DECLARE_NO_PRIORITY;
|
|
if (trans_pen == 0xffffffff)
|
|
copybitmap(dest, src, flipx, flipy, destx, desty, cliprect);
|
|
else
|
|
COPYBITMAP_CORE(u32, PIXEL_OP_COPY_TRANSPEN, NO_PRIORITY);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
copybitmap_transalphpa - copy from one bitmap
|
|
to another, copying all unclipped pixels except
|
|
those with an alpha value of zero
|
|
-------------------------------------------------*/
|
|
|
|
void copybitmap_transalpha(bitmap_rgb32 &dest, const bitmap_rgb32 &src, int flipx, int flipy, s32 destx, s32 desty, const rectangle &cliprect)
|
|
{
|
|
DECLARE_NO_PRIORITY;
|
|
COPYBITMAP_CORE(u32, PIXEL_OP_COPY_TRANSALPHA, NO_PRIORITY);
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
COPYSCROLLBITMAP IMPLEMENTATIONS
|
|
***************************************************************************/
|
|
|
|
/*-------------------------------------------------
|
|
copyscrollbitmap - copy from one bitmap to
|
|
another, copying all unclipped pixels, and
|
|
applying scrolling to one or more rows/columns
|
|
-------------------------------------------------*/
|
|
|
|
void copyscrollbitmap(bitmap_ind16 &dest, const bitmap_ind16 &src, u32 numrows, const s32 *rowscroll, u32 numcols, const s32 *colscroll, const rectangle &cliprect)
|
|
{
|
|
// just call through to the transparent case as the underlying copybitmap will
|
|
// optimize for pen == 0xffffffff
|
|
copyscrollbitmap_trans(dest, src, numrows, rowscroll, numcols, colscroll, cliprect, 0xffffffff);
|
|
}
|
|
|
|
void copyscrollbitmap(bitmap_rgb32 &dest, const bitmap_rgb32 &src, u32 numrows, const s32 *rowscroll, u32 numcols, const s32 *colscroll, const rectangle &cliprect)
|
|
{
|
|
// just call through to the transparent case as the underlying copybitmap will
|
|
// optimize for pen == 0xffffffff
|
|
copyscrollbitmap_trans(dest, src, numrows, rowscroll, numcols, colscroll, cliprect, 0xffffffff);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
copyscrollbitmap_trans - copy from one bitmap
|
|
to another, copying all unclipped pixels
|
|
except those that match transpen, and applying
|
|
scrolling to one or more rows/columns
|
|
-------------------------------------------------*/
|
|
|
|
template<class _BitmapClass>
|
|
static inline void copyscrollbitmap_trans_common(_BitmapClass &dest, const _BitmapClass &src, u32 numrows, const s32 *rowscroll, u32 numcols, const s32 *colscroll, const rectangle &cliprect, u32 trans_pen)
|
|
{
|
|
// no rowscroll and no colscroll means no scroll
|
|
if (numrows == 0 && numcols == 0)
|
|
return copybitmap_trans(dest, src, 0, 0, 0, 0, cliprect, trans_pen);
|
|
|
|
assert(numrows != 0 || rowscroll == nullptr);
|
|
assert(numrows == 0 || rowscroll != nullptr);
|
|
assert(numcols != 0 || colscroll == nullptr);
|
|
assert(numcols == 0 || colscroll != nullptr);
|
|
|
|
// fully scrolling X,Y playfield
|
|
if (numrows <= 1 && numcols <= 1)
|
|
{
|
|
s32 xscroll = normalize_xscroll(src, (numrows == 0) ? 0 : rowscroll[0]);
|
|
s32 yscroll = normalize_yscroll(src, (numcols == 0) ? 0 : colscroll[0]);
|
|
|
|
// iterate over all portions of the scroll that overlap the destination
|
|
for (s32 sx = xscroll - src.width(); sx < dest.width(); sx += src.width())
|
|
for (s32 sy = yscroll - src.height(); sy < dest.height(); sy += src.height())
|
|
copybitmap_trans(dest, src, 0, 0, sx, sy, cliprect, trans_pen);
|
|
}
|
|
|
|
// scrolling columns plus horizontal scroll
|
|
else if (numrows <= 1)
|
|
{
|
|
s32 xscroll = normalize_xscroll(src, (numrows == 0) ? 0 : rowscroll[0]);
|
|
rectangle subclip = cliprect;
|
|
|
|
// determine width of each column
|
|
int colwidth = src.width() / numcols;
|
|
assert(src.width() % colwidth == 0);
|
|
|
|
// iterate over each column
|
|
int groupcols;
|
|
for (int col = 0; col < numcols; col += groupcols)
|
|
{
|
|
s32 yscroll = colscroll[col];
|
|
|
|
// count consecutive columns scrolled by the same amount
|
|
for (groupcols = 1; col + groupcols < numcols; groupcols++)
|
|
if (colscroll[col + groupcols] != yscroll)
|
|
break;
|
|
|
|
// iterate over reps of the columns in question
|
|
yscroll = normalize_yscroll(src, yscroll);
|
|
for (s32 sx = xscroll - src.width(); sx < dest.width(); sx += src.width())
|
|
{
|
|
// compute the cliprect for this group
|
|
subclip.setx(col * colwidth + sx, (col + groupcols) * colwidth - 1 + sx);
|
|
subclip &= cliprect;
|
|
|
|
// iterate over all portions of the scroll that overlap the destination
|
|
for (s32 sy = yscroll - src.height(); sy < dest.height(); sy += src.height())
|
|
copybitmap_trans(dest, src, 0, 0, sx, sy, subclip, trans_pen);
|
|
}
|
|
}
|
|
}
|
|
|
|
// scrolling rows plus vertical scroll
|
|
else if (numcols <= 1)
|
|
{
|
|
s32 yscroll = normalize_yscroll(src, (numcols == 0) ? 0 : colscroll[0]);
|
|
rectangle subclip = cliprect;
|
|
|
|
// determine width of each rows
|
|
int rowheight = src.height() / numrows;
|
|
assert(src.height() % rowheight == 0);
|
|
|
|
// iterate over each row
|
|
int grouprows;
|
|
for (int row = 0; row < numrows; row += grouprows)
|
|
{
|
|
s32 xscroll = rowscroll[row];
|
|
|
|
// count consecutive rows scrolled by the same amount
|
|
for (grouprows = 1; row + grouprows < numrows; grouprows++)
|
|
if (rowscroll[row + grouprows] != xscroll)
|
|
break;
|
|
|
|
// iterate over reps of the rows in question
|
|
xscroll = normalize_xscroll(src, xscroll);
|
|
for (s32 sy = yscroll - src.height(); sy < dest.height(); sy += src.height())
|
|
{
|
|
// compute the cliprect for this group
|
|
subclip.sety(row * rowheight + sy, (row + grouprows) * rowheight - 1 + sy);
|
|
subclip &= cliprect;
|
|
|
|
// iterate over all portions of the scroll that overlap the destination
|
|
for (s32 sx = xscroll - src.width(); sx < dest.width(); sx += src.width())
|
|
copybitmap_trans(dest, src, 0, 0, sx, sy, subclip, trans_pen);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void copyscrollbitmap_trans(bitmap_ind16 &dest, const bitmap_ind16 &src, u32 numrows, const s32 *rowscroll, u32 numcols, const s32 *colscroll, const rectangle &cliprect, u32 trans_pen)
|
|
{ copyscrollbitmap_trans_common(dest, src, numrows, rowscroll, numcols, colscroll, cliprect, trans_pen); }
|
|
|
|
void copyscrollbitmap_trans(bitmap_rgb32 &dest, const bitmap_rgb32 &src, u32 numrows, const s32 *rowscroll, u32 numcols, const s32 *colscroll, const rectangle &cliprect, u32 trans_pen)
|
|
{ copyscrollbitmap_trans_common(dest, src, numrows, rowscroll, numcols, colscroll, cliprect, trans_pen); }
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
COPYROZBITMAP IMPLEMENTATIONS
|
|
***************************************************************************/
|
|
|
|
/*-------------------------------------------------
|
|
copyrozbitmap - copy from one bitmap to another,
|
|
with zoom and rotation, copying all unclipped
|
|
pixels
|
|
-------------------------------------------------*/
|
|
|
|
void copyrozbitmap(bitmap_ind16 &dest, const rectangle &cliprect, const bitmap_ind16 &src, s32 startx, s32 starty, s32 incxx, s32 incxy, s32 incyx, s32 incyy, int wraparound)
|
|
{
|
|
DECLARE_NO_PRIORITY;
|
|
COPYROZBITMAP_CORE(u16, PIXEL_OP_COPY_OPAQUE, NO_PRIORITY);
|
|
}
|
|
|
|
void copyrozbitmap(bitmap_rgb32 &dest, const rectangle &cliprect, const bitmap_rgb32 &src, s32 startx, s32 starty, s32 incxx, s32 incxy, s32 incyx, s32 incyy, int wraparound)
|
|
{
|
|
DECLARE_NO_PRIORITY;
|
|
COPYROZBITMAP_CORE(u32, PIXEL_OP_COPY_OPAQUE, NO_PRIORITY);
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------
|
|
copyrozbitmap_trans - copy from one bitmap to
|
|
another, with zoom and rotation, copying all
|
|
unclipped pixels whose values do not match
|
|
transpen
|
|
-------------------------------------------------*/
|
|
|
|
void copyrozbitmap_trans(bitmap_ind16 &dest, const rectangle &cliprect, const bitmap_ind16 &src, s32 startx, s32 starty, s32 incxx, s32 incxy, s32 incyx, s32 incyy, int wraparound, u32 trans_pen)
|
|
{
|
|
DECLARE_NO_PRIORITY;
|
|
COPYROZBITMAP_CORE(u16, PIXEL_OP_COPY_TRANSPEN, NO_PRIORITY);
|
|
}
|
|
|
|
void copyrozbitmap_trans(bitmap_rgb32 &dest, const rectangle &cliprect, const bitmap_rgb32 &src, s32 startx, s32 starty, s32 incxx, s32 incxy, s32 incyx, s32 incyy, int wraparound, u32 trans_pen)
|
|
{
|
|
DECLARE_NO_PRIORITY;
|
|
COPYROZBITMAP_CORE(u32, PIXEL_OP_COPY_TRANSPEN, NO_PRIORITY);
|
|
}
|