summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/drawgfx.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/drawgfx.c')
-rw-r--r--trunk/src/emu/drawgfx.c1995
1 files changed, 1995 insertions, 0 deletions
diff --git a/trunk/src/emu/drawgfx.c b/trunk/src/emu/drawgfx.c
new file mode 100644
index 00000000000..3d23dcbbad5
--- /dev/null
+++ b/trunk/src/emu/drawgfx.c
@@ -0,0 +1,1995 @@
+/*********************************************************************
+
+ drawgfx.c
+
+ Generic graphic functions.
+
+ Copyright Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+*********************************************************************/
+
+#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
+UINT8 no_priority_size_is_wrong[2 * (sizeof(NO_PRIORITY) == 3) - 1];
+
+bitmap_ind8 drawgfx_dummy_priority_bitmap;
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void decodechar(const gfx_element *gfx, UINT32 code, const UINT8 *src);
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ readbit - read a single bit from a base
+ offset
+-------------------------------------------------*/
+
+static inline int readbit(const UINT8 *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 INT32 normalize_xscroll(bitmap_t &bitmap, INT32 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 INT32 normalize_yscroll(bitmap_t &bitmap, INT32 yscroll)
+{
+ return (yscroll >= 0) ? yscroll % bitmap.height() : (bitmap.height() - (-yscroll) % bitmap.height());
+}
+
+
+
+/***************************************************************************
+ GRAPHICS ELEMENTS
+***************************************************************************/
+
+/*-------------------------------------------------
+ gfx_init - allocate memory for the graphics
+ elements referenced by a machine
+-------------------------------------------------*/
+
+void gfx_init(running_machine &machine)
+{
+ const gfx_decode_entry *gfxdecodeinfo = machine.config().m_gfxdecodeinfo;
+ int curgfx;
+
+ // skip if nothing to do
+ if (gfxdecodeinfo == NULL)
+ return;
+
+ // loop over all elements
+ for (curgfx = 0; curgfx < MAX_GFX_ELEMENTS && gfxdecodeinfo[curgfx].gfxlayout != NULL; curgfx++)
+ {
+ const gfx_decode_entry *gfxdecode = &gfxdecodeinfo[curgfx];
+ memory_region *region = (gfxdecode->memory_region != NULL) ? machine.root_device().memregion(gfxdecode->memory_region) : NULL;
+ UINT32 region_length = (region != NULL) ? (8 * region->bytes()) : 0;
+ const UINT8 *region_base = (region != NULL) ? region->base() : NULL;
+ UINT32 xscale = (gfxdecode->xscale == 0) ? 1 : gfxdecode->xscale;
+ UINT32 yscale = (gfxdecode->yscale == 0) ? 1 : gfxdecode->yscale;
+ UINT32 *extpoffs, extxoffs[MAX_ABS_GFX_SIZE], extyoffs[MAX_ABS_GFX_SIZE];
+ const gfx_layout *gl = gfxdecode->gfxlayout;
+ int israw = (gl->planeoffset[0] == GFX_RAW);
+ int planes = gl->planes;
+ UINT32 width = gl->width;
+ UINT32 height = gl->height;
+ UINT32 total = gl->total;
+ UINT32 charincrement = gl->charincrement;
+ gfx_layout glcopy;
+ int j;
+
+ // make a copy of the layout
+ glcopy = *gfxdecode->gfxlayout;
+
+ // copy the X and Y offsets into temporary arrays
+ memcpy(extxoffs, glcopy.xoffset, sizeof(glcopy.xoffset));
+ memcpy(extyoffs, glcopy.yoffset, sizeof(glcopy.yoffset));
+
+ // if there are extended offsets, copy them over top
+ if (glcopy.extxoffs != NULL)
+ memcpy(extxoffs, glcopy.extxoffs, glcopy.width * sizeof(extxoffs[0]));
+ if (glcopy.extyoffs != NULL)
+ memcpy(extyoffs, glcopy.extyoffs, glcopy.height * sizeof(extyoffs[0]));
+
+ // always use the extended offsets here
+ glcopy.extxoffs = extxoffs;
+ glcopy.extyoffs = extyoffs;
+
+ extpoffs = glcopy.planeoffset;
+
+ // expand X and Y by the scale factors
+ if (xscale > 1)
+ {
+ width *= xscale;
+ for (j = width - 1; j >= 0; j--)
+ extxoffs[j] = extxoffs[j / xscale];
+ }
+ if (yscale > 1)
+ {
+ height *= yscale;
+ for (j = height - 1; j >= 0; j--)
+ extyoffs[j] = extyoffs[j / yscale];
+ }
+
+ // if the character count is a region fraction, compute the effective total
+ if (IS_FRAC(total))
+ {
+ assert(region_length != 0);
+ total = region_length / charincrement * FRAC_NUM(total) / FRAC_DEN(total);
+ }
+
+ // for non-raw graphics, decode the X and Y offsets
+ if (!israw)
+ {
+ // loop over all the planes, converting fractions
+ for (j = 0; j < planes; j++)
+ {
+ UINT32 value1 = extpoffs[j];
+ if (IS_FRAC(value1))
+ {
+ assert(region_length != 0);
+ extpoffs[j] = FRAC_OFFSET(value1) + region_length * FRAC_NUM(value1) / FRAC_DEN(value1);
+ }
+ }
+
+ // loop over all the X/Y offsets, converting fractions
+ for (j = 0; j < width; j++)
+ {
+ UINT32 value2 = extxoffs[j];
+ if (IS_FRAC(value2))
+ {
+ assert(region_length != 0);
+ extxoffs[j] = FRAC_OFFSET(value2) + region_length * FRAC_NUM(value2) / FRAC_DEN(value2);
+ }
+ }
+
+ for (j = 0; j < height; j++)
+ {
+ UINT32 value3 = extyoffs[j];
+ if (IS_FRAC(value3))
+ {
+ assert(region_length != 0);
+ extyoffs[j] = FRAC_OFFSET(value3) + region_length * FRAC_NUM(value3) / FRAC_DEN(value3);
+ }
+ }
+ }
+
+ // otherwise, just use the line modulo
+ else
+ {
+ int base = gfxdecode->start;
+ int end = region_length/8;
+ int linemod = gl->yoffset[0];
+ while (total > 0)
+ {
+ int elementbase = base + (total - 1) * charincrement / 8;
+ int lastpixelbase = elementbase + height * linemod / 8 - 1;
+ if (lastpixelbase < end)
+ break;
+ total--;
+ }
+ }
+
+ // update glcopy
+ glcopy.width = width;
+ glcopy.height = height;
+ glcopy.total = total;
+
+ // allocate the graphics
+ machine.gfx[curgfx] = gfx_element_alloc(machine, &glcopy, (region_base != NULL) ? region_base + gfxdecode->start : NULL, gfxdecode->total_color_codes, gfxdecode->color_codes_start);
+ }
+}
+
+
+
+/*-------------------------------------------------
+ gfx_element_alloc - allocate a gfx_element structure
+ based on a given layout
+-------------------------------------------------*/
+
+gfx_element *gfx_element_alloc(running_machine &machine, const gfx_layout *gl, const UINT8 *srcdata, UINT32 total_colors, UINT32 color_base)
+{
+ int israw = (gl->planeoffset[0] == GFX_RAW);
+ int planes = gl->planes;
+ UINT16 width = gl->width;
+ UINT16 height = gl->height;
+ UINT32 total = gl->total;
+ gfx_element *gfx;
+
+ // allocate memory for the gfx_element structure
+ gfx = auto_alloc_clear(machine, gfx_element(machine));
+
+ // fill in the data
+ gfx->width = width;
+ gfx->height = height;
+
+ gfx->origwidth = width;
+ gfx->origheight = height;
+ gfx->total_elements = total;
+
+ gfx->color_base = color_base;
+ gfx->color_depth = 1 << planes;
+ gfx->color_granularity = 1 << planes;
+ gfx->total_colors = total_colors;
+
+ gfx->srcdata = srcdata;
+
+ // copy the layout
+ gfx->layout = *gl;
+ if (gfx->layout.extxoffs != NULL)
+ {
+ if (gfx->layout.width < ARRAY_LENGTH(gfx->layout.xoffset))
+ {
+ memcpy(gfx->layout.xoffset, gfx->layout.extxoffs, sizeof(gfx->layout.xoffset[0]) * gfx->layout.width);
+ gfx->layout.extxoffs = NULL;
+ }
+ else
+ {
+ UINT32 *buffer = auto_alloc_array(machine, UINT32, gfx->layout.width);
+ memcpy(buffer, gfx->layout.extxoffs, sizeof(gfx->layout.extxoffs[0]) * gfx->layout.width);
+ gfx->layout.extxoffs = buffer;
+ }
+ }
+
+ if (gfx->layout.extyoffs != NULL)
+ {
+ if (gfx->layout.height < ARRAY_LENGTH(gfx->layout.yoffset))
+ {
+ memcpy(gfx->layout.yoffset, gfx->layout.extyoffs, sizeof(gfx->layout.yoffset[0]) * gfx->layout.height);
+ gfx->layout.extyoffs = NULL;
+ }
+ else
+ {
+ UINT32 *buffer = auto_alloc_array(machine, UINT32, gfx->layout.height);
+ memcpy(buffer, gfx->layout.extyoffs, sizeof(gfx->layout.extyoffs[0]) * gfx->layout.height);
+ gfx->layout.extyoffs = buffer;
+ }
+ }
+
+ // allocate a pen usage array for entries with 32 pens or less
+ if (gfx->color_depth <= 32)
+ gfx->pen_usage = auto_alloc_array(machine, UINT32, gfx->total_elements);
+
+ // allocate a dirty array
+ gfx->dirty = auto_alloc_array(machine, UINT8, gfx->total_elements);
+ memset(gfx->dirty, 1, gfx->total_elements * sizeof(*gfx->dirty));
+
+ // raw graphics case
+ if (israw)
+ {
+ // modulos are determined for us by the layout
+ gfx->line_modulo = (gl->extyoffs ? gl->extyoffs[0] : gl->yoffset[0]) / 8;
+ gfx->char_modulo = gl->charincrement / 8;
+
+ // don't free the data because we will get a pointer at decode time
+ gfx->flags |= GFX_ELEMENT_DONT_FREE;
+
+ // RAW graphics must have a pointer up front
+ gfx->gfxdata = (UINT8 *)gfx->srcdata;
+ }
+
+ // decoded graphics case
+ else
+ {
+ // we get to pick our own modulos
+ gfx->line_modulo = gfx->origwidth;
+ gfx->char_modulo = gfx->line_modulo * gfx->origheight;
+
+ // allocate memory for the data
+ gfx->gfxdata = auto_alloc_array(machine, UINT8, gfx->total_elements * gfx->char_modulo);
+ }
+
+ return gfx;
+}
+
+
+/*-------------------------------------------------
+ gfx_element_decode - update a single code in
+ a gfx_element
+-------------------------------------------------*/
+
+void gfx_element_decode(const gfx_element *gfx, UINT32 code)
+{
+ decodechar(gfx, code, gfx->srcdata);
+}
+
+
+/*-------------------------------------------------
+ gfx_element_free - free a gfx_element
+-------------------------------------------------*/
+
+void gfx_element_free(gfx_element *gfx)
+{
+ // ignore NULL frees
+ if (gfx == NULL)
+ return;
+
+ // free our data
+ auto_free(gfx->machine(), gfx->layout.extyoffs);
+ auto_free(gfx->machine(), gfx->layout.extxoffs);
+ auto_free(gfx->machine(), gfx->pen_usage);
+ auto_free(gfx->machine(), gfx->dirty);
+ auto_free(gfx->machine(), gfx->gfxdata);
+ auto_free(gfx->machine(), gfx);
+}
+
+
+/*-------------------------------------------------
+ gfx_element_build_temporary - create a
+ temporary one-off gfx_element
+-------------------------------------------------*/
+
+void gfx_element_build_temporary(gfx_element *gfx, running_machine &machine, UINT8 *base, UINT32 width, UINT32 height, UINT32 rowbytes, UINT32 color_base, UINT32 color_granularity, UINT32 flags)
+{
+ static UINT8 not_dirty = 0;
+
+ gfx->width = width;
+ gfx->height = height;
+ gfx->startx = 0;
+ gfx->starty = 0;
+
+ gfx->origwidth = width;
+ gfx->origheight = height;
+ gfx->flags = flags;
+ gfx->total_elements = 1;
+
+ gfx->color_base = color_base;
+ gfx->color_depth = color_granularity;
+ gfx->color_granularity = color_granularity;
+ gfx->total_colors = (machine.total_colors() - color_base) / color_granularity;
+
+ gfx->pen_usage = NULL;
+
+ gfx->gfxdata = base;
+ gfx->line_modulo = rowbytes;
+ gfx->char_modulo = 0;
+ gfx->srcdata = base;
+ gfx->dirty = &not_dirty;
+ gfx->dirtyseq = 0;
+}
+
+
+/*-------------------------------------------------
+ calc_penusage - calculate the pen usage for
+ a given graphics tile
+-------------------------------------------------*/
+
+static void calc_penusage(const gfx_element *gfx, UINT32 code)
+{
+ const UINT8 *dp = gfx->gfxdata + code * gfx->char_modulo;
+ UINT32 usage = 0;
+ int x, y;
+
+ // if nothing allocated, don't do it
+ if (gfx->pen_usage == NULL)
+ return;
+
+ for (y = 0; y < gfx->origheight; y++)
+ {
+ for (x = 0; x < gfx->origwidth; x++)
+ usage |= 1 << dp[x];
+
+ dp += gfx->line_modulo;
+ }
+
+ // store the final result
+ gfx->pen_usage[code] = usage;
+}
+
+
+/*-------------------------------------------------
+ decodechar - decode a single character based
+ on a specified layout
+-------------------------------------------------*/
+
+static void decodechar(const gfx_element *gfx, UINT32 code, const UINT8 *src)
+{
+ const gfx_layout *gl = &gfx->layout;
+ int israw = (gl->planeoffset[0] == GFX_RAW);
+ int planes = gl->planes;
+ UINT32 charincrement = gl->charincrement;
+ const UINT32 *poffset = gl->planeoffset;
+ const UINT32 *xoffset = gl->extxoffs ? gl->extxoffs : gl->xoffset;
+ const UINT32 *yoffset = gl->extyoffs ? gl->extyoffs : gl->yoffset;
+ UINT8 *dp = gfx->gfxdata + code * gfx->char_modulo;
+ int plane, x, y;
+
+ if (!israw)
+ {
+ // zap the data to 0
+ memset(dp, 0, gfx->char_modulo);
+ for (plane = 0; plane < planes; plane++)
+ {
+ int planebit = 1 << (planes - 1 - plane);
+ int planeoffs = code * charincrement + poffset[plane];
+
+ for (y = 0; y < gfx->origheight; y++)
+ {
+ int yoffs = planeoffs + yoffset[y];
+
+ dp = gfx->gfxdata + code * gfx->char_modulo + y * gfx->line_modulo;
+ for (x = 0; x < gfx->origwidth; x++)
+ if (readbit(src, yoffs + xoffset[x]))
+ dp[x] |= planebit;
+ }
+ }
+ }
+
+ // compute pen usage
+ calc_penusage(gfx, code);
+
+ // no longer dirty
+ gfx->dirty[code] = 0;
+}
+
+
+/***************************************************************************
+ DRAWGFX IMPLEMENTATIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ drawgfx_opaque - render a gfx element with
+ no transparency
+-------------------------------------------------*/
+
+void drawgfx_opaque(bitmap_ind16 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty)
+{
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ code %= gfx->total_elements;
+ DECLARE_NO_PRIORITY;
+ DRAWGFX_CORE(UINT16, PIXEL_OP_REMAP_OPAQUE, NO_PRIORITY);
+}
+
+void drawgfx_opaque(bitmap_rgb32 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty)
+{
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ code %= gfx->total_elements;
+ DECLARE_NO_PRIORITY;
+ DRAWGFX_CORE(UINT32, PIXEL_OP_REMAP_OPAQUE, NO_PRIORITY);
+}
+
+
+/*-------------------------------------------------
+ drawgfx_transpen - render a gfx element with
+ a single transparent pen
+-------------------------------------------------*/
+
+void drawgfx_transpen(bitmap_ind16 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 transpen)
+{
+ // special case invalid pens to opaque
+ if (transpen > 0xff)
+ return drawgfx_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty);
+
+ // use pen usage to optimize
+ code %= gfx->total_elements;
+ if (gfx->pen_usage != NULL && !gfx->dirty[code])
+ {
+ // fully transparent; do nothing
+ UINT32 usage = gfx->pen_usage[code];
+ if ((usage & ~(1 << transpen)) == 0)
+ return;
+
+ // fully opaque; draw as such
+ if ((usage & (1 << transpen)) == 0)
+ return drawgfx_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty);
+ }
+
+ // render
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ DECLARE_NO_PRIORITY;
+ DRAWGFX_CORE(UINT16, PIXEL_OP_REMAP_TRANSPEN, NO_PRIORITY);
+}
+
+void drawgfx_transpen(bitmap_rgb32 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 transpen)
+{
+ // special case invalid pens to opaque
+ if (transpen > 0xff)
+ return drawgfx_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty);
+
+ // use pen usage to optimize
+ code %= gfx->total_elements;
+ if (gfx->pen_usage != NULL && !gfx->dirty[code])
+ {
+ // fully transparent; do nothing
+ UINT32 usage = gfx->pen_usage[code];
+ if ((usage & ~(1 << transpen)) == 0)
+ return;
+
+ // fully opaque; draw as such
+ if ((usage & (1 << transpen)) == 0)
+ return drawgfx_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty);
+ }
+
+ // render
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ DECLARE_NO_PRIORITY;
+ DRAWGFX_CORE(UINT32, PIXEL_OP_REMAP_TRANSPEN, NO_PRIORITY);
+}
+
+
+/*-------------------------------------------------
+ drawgfx_transpen_raw - render a gfx element
+ with a single transparent pen and no color
+ lookups
+-------------------------------------------------*/
+
+void drawgfx_transpen_raw(bitmap_ind16 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 transpen)
+{
+ // early out if completely transparent
+ code %= gfx->total_elements;
+ if (gfx->pen_usage != NULL && !gfx->dirty[code] && (gfx->pen_usage[code] & ~(1 << transpen)) == 0)
+ return;
+
+ // render
+ DECLARE_NO_PRIORITY;
+ DRAWGFX_CORE(UINT16, PIXEL_OP_REBASE_TRANSPEN, NO_PRIORITY);
+}
+
+void drawgfx_transpen_raw(bitmap_rgb32 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 transpen)
+{
+ // early out if completely transparent
+ code %= gfx->total_elements;
+ if (gfx->pen_usage != NULL && !gfx->dirty[code] && (gfx->pen_usage[code] & ~(1 << transpen)) == 0)
+ return;
+
+ // render
+ DECLARE_NO_PRIORITY;
+ DRAWGFX_CORE(UINT32, PIXEL_OP_REBASE_TRANSPEN, NO_PRIORITY);
+}
+
+
+/*-------------------------------------------------
+ drawgfx_transmask - render a gfx element
+ with a multiple transparent pens provided as
+ a mask
+-------------------------------------------------*/
+
+void drawgfx_transmask(bitmap_ind16 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 transmask)
+{
+ // special case 0 mask to opaque
+ if (transmask == 0)
+ return drawgfx_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty);
+
+ // use pen usage to optimize
+ code %= gfx->total_elements;
+ if (gfx->pen_usage != NULL && !gfx->dirty[code])
+ {
+ // fully transparent; do nothing
+ UINT32 usage = gfx->pen_usage[code];
+ if ((usage & ~transmask) == 0)
+ return;
+
+ // fully opaque; draw as such
+ if ((usage & transmask) == 0)
+ return drawgfx_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty);
+ }
+
+ // render
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ DECLARE_NO_PRIORITY;
+ DRAWGFX_CORE(UINT16, PIXEL_OP_REMAP_TRANSMASK, NO_PRIORITY);
+}
+
+void drawgfx_transmask(bitmap_rgb32 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 transmask)
+{
+ // special case 0 mask to opaque
+ if (transmask == 0)
+ return drawgfx_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty);
+
+ // use pen usage to optimize
+ code %= gfx->total_elements;
+ if (gfx->pen_usage != NULL && !gfx->dirty[code])
+ {
+ // fully transparent; do nothing
+ UINT32 usage = gfx->pen_usage[code];
+ if ((usage & ~transmask) == 0)
+ return;
+
+ // fully opaque; draw as such
+ if ((usage & transmask) == 0)
+ return drawgfx_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty);
+ }
+
+ // render
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ DECLARE_NO_PRIORITY;
+ DRAWGFX_CORE(UINT32, PIXEL_OP_REMAP_TRANSMASK, NO_PRIORITY);
+}
+
+
+/*-------------------------------------------------
+ drawgfx_transtable - render a gfx element
+ using a table to look up which pens are
+ transparent, opaque, or shadowing
+-------------------------------------------------*/
+
+void drawgfx_transtable(bitmap_ind16 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ const UINT8 *pentable, const pen_t *shadowtable)
+{
+ assert(pentable != NULL);
+
+ // render
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ code %= gfx->total_elements;
+ DECLARE_NO_PRIORITY;
+ DRAWGFX_CORE(UINT16, PIXEL_OP_REMAP_TRANSTABLE16, NO_PRIORITY);
+}
+
+void drawgfx_transtable(bitmap_rgb32 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ const UINT8 *pentable, const pen_t *shadowtable)
+{
+ assert(pentable != NULL);
+
+ // render
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ code %= gfx->total_elements;
+ DECLARE_NO_PRIORITY;
+ DRAWGFX_CORE(UINT32, PIXEL_OP_REMAP_TRANSTABLE32, NO_PRIORITY);
+}
+
+
+/*-------------------------------------------------
+ drawgfx_alpha - render a gfx element with
+ a single transparent pen, alpha blending the
+ remaining pixels with a fixed alpha value
+-------------------------------------------------*/
+
+void drawgfx_alpha(bitmap_rgb32 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 transpen, UINT8 alpha)
+{
+ // special case alpha = 0xff
+ if (alpha == 0xff)
+ return drawgfx_transpen(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, transpen);
+
+ // early out if completely transparent
+ code %= gfx->total_elements;
+ if (gfx->pen_usage != NULL && !gfx->dirty[code] && (gfx->pen_usage[code] & ~(1 << transpen)) == 0)
+ return;
+
+ // get final code and color, and grab lookup tables
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ DECLARE_NO_PRIORITY;
+ DRAWGFX_CORE(UINT32, PIXEL_OP_REMAP_TRANSPEN_ALPHA32, NO_PRIORITY);
+}
+
+
+
+/***************************************************************************
+ DRAWGFXZOOM IMPLEMENTATIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ drawgfxzoom_opaque - render a scaled gfx
+ element with no transparency
+-------------------------------------------------*/
+
+void drawgfxzoom_opaque(bitmap_ind16 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley)
+{
+ // non-zoom case
+ if (scalex == 0x10000 && scaley == 0x10000)
+ return drawgfx_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty);
+
+ // render
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ code %= gfx->total_elements;
+ DECLARE_NO_PRIORITY;
+ DRAWGFXZOOM_CORE(UINT16, PIXEL_OP_REMAP_OPAQUE, NO_PRIORITY);
+}
+
+void drawgfxzoom_opaque(bitmap_rgb32 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley)
+{
+ // non-zoom case
+ if (scalex == 0x10000 && scaley == 0x10000)
+ return drawgfx_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty);
+
+ // render
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ code %= gfx->total_elements;
+ DECLARE_NO_PRIORITY;
+ DRAWGFXZOOM_CORE(UINT32, PIXEL_OP_REMAP_OPAQUE, NO_PRIORITY);
+}
+
+
+/*-------------------------------------------------
+ drawgfxzoom_transpen - render a scaled gfx
+ element with a single transparent pen
+-------------------------------------------------*/
+
+void drawgfxzoom_transpen(bitmap_ind16 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley, UINT32 transpen)
+{
+ // non-zoom case
+ if (scalex == 0x10000 && scaley == 0x10000)
+ return drawgfx_transpen(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, transpen);
+
+ // special case invalid pens to opaque
+ if (transpen > 0xff)
+ return drawgfxzoom_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, scalex, scaley);
+
+ // use pen usage to optimize
+ code %= gfx->total_elements;
+ if (gfx->pen_usage != NULL && !gfx->dirty[code])
+ {
+ // fully transparent; do nothing
+ UINT32 usage = gfx->pen_usage[code];
+ if ((usage & ~(1 << transpen)) == 0)
+ return;
+
+ // fully opaque; draw as such
+ if ((usage & (1 << transpen)) == 0)
+ return drawgfxzoom_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, scalex, scaley);
+ }
+
+ // render
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ DECLARE_NO_PRIORITY;
+ DRAWGFXZOOM_CORE(UINT16, PIXEL_OP_REMAP_TRANSPEN, NO_PRIORITY);
+}
+
+void drawgfxzoom_transpen(bitmap_rgb32 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley, UINT32 transpen)
+{
+ // non-zoom case
+ if (scalex == 0x10000 && scaley == 0x10000)
+ return drawgfx_transpen(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, transpen);
+
+ // special case invalid pens to opaque
+ if (transpen > 0xff)
+ return drawgfxzoom_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, scalex, scaley);
+
+ // use pen usage to optimize
+ code %= gfx->total_elements;
+ if (gfx->pen_usage != NULL && !gfx->dirty[code])
+ {
+ // fully transparent; do nothing
+ UINT32 usage = gfx->pen_usage[code];
+ if ((usage & ~(1 << transpen)) == 0)
+ return;
+
+ // fully opaque; draw as such
+ if ((usage & (1 << transpen)) == 0)
+ return drawgfxzoom_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, scalex, scaley);
+ }
+
+ // render
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ DECLARE_NO_PRIORITY;
+ DRAWGFXZOOM_CORE(UINT32, PIXEL_OP_REMAP_TRANSPEN, NO_PRIORITY);
+}
+
+
+/*-------------------------------------------------
+ drawgfxzoom_transpen_raw - render a scaled gfx
+ element with a single transparent pen and no
+ color lookups
+-------------------------------------------------*/
+
+void drawgfxzoom_transpen_raw(bitmap_ind16 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley, UINT32 transpen)
+{
+ // non-zoom case
+ if (scalex == 0x10000 && scaley == 0x10000)
+ return drawgfx_transpen_raw(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, transpen);
+
+ // early out if completely transparent
+ code %= gfx->total_elements;
+ if (gfx->pen_usage != NULL && !gfx->dirty[code] && (gfx->pen_usage[code] & ~(1 << transpen)) == 0)
+ return;
+
+ // render
+ DECLARE_NO_PRIORITY;
+ DRAWGFXZOOM_CORE(UINT16, PIXEL_OP_REBASE_TRANSPEN, NO_PRIORITY);
+}
+
+void drawgfxzoom_transpen_raw(bitmap_rgb32 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley, UINT32 transpen)
+{
+ // non-zoom case
+ if (scalex == 0x10000 && scaley == 0x10000)
+ return drawgfx_transpen_raw(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, transpen);
+
+ // early out if completely transparent
+ code %= gfx->total_elements;
+ if (gfx->pen_usage != NULL && !gfx->dirty[code] && (gfx->pen_usage[code] & ~(1 << transpen)) == 0)
+ return;
+
+ // render
+ DECLARE_NO_PRIORITY;
+ DRAWGFXZOOM_CORE(UINT32, PIXEL_OP_REBASE_TRANSPEN, NO_PRIORITY);
+}
+
+
+/*-------------------------------------------------
+ drawgfxzoom_transmask - render a scaled gfx
+ element with a multiple transparent pens
+ provided as a mask
+-------------------------------------------------*/
+
+void drawgfxzoom_transmask(bitmap_ind16 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley, UINT32 transmask)
+{
+ // non-zoom case
+ if (scalex == 0x10000 && scaley == 0x10000)
+ return drawgfx_transmask(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, transmask);
+
+ // special case 0 mask to opaque
+ if (transmask == 0)
+ return drawgfxzoom_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, scalex, scaley);
+
+ // use pen usage to optimize
+ code %= gfx->total_elements;
+ if (gfx->pen_usage != NULL && !gfx->dirty[code])
+ {
+ // fully transparent; do nothing
+ UINT32 usage = gfx->pen_usage[code];
+ if ((usage & ~transmask) == 0)
+ return;
+
+ // fully opaque; draw as such
+ if ((usage & transmask) == 0)
+ return drawgfxzoom_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, scalex, scaley);
+ }
+
+ // render
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ DECLARE_NO_PRIORITY;
+ DRAWGFXZOOM_CORE(UINT16, PIXEL_OP_REMAP_TRANSMASK, NO_PRIORITY);
+}
+
+void drawgfxzoom_transmask(bitmap_rgb32 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley, UINT32 transmask)
+{
+ // non-zoom case
+ if (scalex == 0x10000 && scaley == 0x10000)
+ return drawgfx_transmask(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, transmask);
+
+ // special case 0 mask to opaque
+ if (transmask == 0)
+ return drawgfxzoom_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, scalex, scaley);
+
+ // use pen usage to optimize
+ code %= gfx->total_elements;
+ if (gfx->pen_usage != NULL && !gfx->dirty[code])
+ {
+ // fully transparent; do nothing
+ UINT32 usage = gfx->pen_usage[code];
+ if ((usage & ~transmask) == 0)
+ return;
+
+ // fully opaque; draw as such
+ if ((usage & transmask) == 0)
+ return drawgfxzoom_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, scalex, scaley);
+ }
+
+ // render
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ DECLARE_NO_PRIORITY;
+ DRAWGFXZOOM_CORE(UINT32, PIXEL_OP_REMAP_TRANSMASK, NO_PRIORITY);
+}
+
+
+/*-------------------------------------------------
+ drawgfxzoom_transtable - render a scaled gfx
+ element using a table to look up which pens
+ are transparent, opaque, or shadowing
+-------------------------------------------------*/
+
+void drawgfxzoom_transtable(bitmap_ind16 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley, const UINT8 *pentable, const pen_t *shadowtable)
+{
+ assert(pentable != NULL);
+
+ // non-zoom case
+ if (scalex == 0x10000 && scaley == 0x10000)
+ return drawgfx_transtable(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, pentable, shadowtable);
+
+ // render
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ code %= gfx->total_elements;
+ DECLARE_NO_PRIORITY;
+ DRAWGFXZOOM_CORE(UINT16, PIXEL_OP_REMAP_TRANSTABLE16, NO_PRIORITY);
+}
+
+void drawgfxzoom_transtable(bitmap_rgb32 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley, const UINT8 *pentable, const pen_t *shadowtable)
+{
+ assert(pentable != NULL);
+
+ // non-zoom case
+ if (scalex == 0x10000 && scaley == 0x10000)
+ return drawgfx_transtable(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, pentable, shadowtable);
+
+ // render
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ code %= gfx->total_elements;
+ DECLARE_NO_PRIORITY;
+ DRAWGFXZOOM_CORE(UINT32, PIXEL_OP_REMAP_TRANSTABLE32, NO_PRIORITY);
+}
+
+
+/*-------------------------------------------------
+ drawgfxzoom_alpha - render a scaled gfx element
+ with a single transparent pen, alpha blending
+ the remaining pixels with a fixed alpha value
+-------------------------------------------------*/
+
+void drawgfxzoom_alpha(bitmap_rgb32 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley, UINT32 transpen, UINT8 alpha)
+{
+ // non-zoom case
+ if (scalex == 0x10000 && scaley == 0x10000)
+ return drawgfx_alpha(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, transpen, alpha);
+
+ // special case alpha = 0xff
+ if (alpha == 0xff)
+ return drawgfxzoom_transpen(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, scalex, scaley, transpen);
+
+ // early out if completely transparent
+ code %= gfx->total_elements;
+ if (gfx->pen_usage != NULL && !gfx->dirty[code] && (gfx->pen_usage[code] & ~(1 << transpen)) == 0)
+ return;
+
+ // render
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ DECLARE_NO_PRIORITY;
+ DRAWGFXZOOM_CORE(UINT32, PIXEL_OP_REMAP_TRANSPEN_ALPHA32, NO_PRIORITY);
+}
+
+
+
+/***************************************************************************
+ PDRAWGFX IMPLEMENTATIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ pdrawgfx_opaque - render a gfx element with
+ no transparency, checking against the priority
+ bitmap
+-------------------------------------------------*/
+
+void pdrawgfx_opaque(bitmap_ind16 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ bitmap_ind8 &priority, UINT32 pmask)
+{
+ // high bit of the mask is implicitly on
+ pmask |= 1 << 31;
+
+ // render
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ code %= gfx->total_elements;
+ DRAWGFX_CORE(UINT16, PIXEL_OP_REMAP_OPAQUE_PRIORITY, UINT8);
+}
+
+void pdrawgfx_opaque(bitmap_rgb32 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ bitmap_ind8 &priority, UINT32 pmask)
+{
+ // high bit of the mask is implicitly on
+ pmask |= 1 << 31;
+
+ // render
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ code %= gfx->total_elements;
+ DRAWGFX_CORE(UINT32, PIXEL_OP_REMAP_OPAQUE_PRIORITY, UINT8);
+}
+
+
+/*-------------------------------------------------
+ pdrawgfx_transpen - render a gfx element with
+ a single transparent pen, checking against the
+ priority bitmap
+-------------------------------------------------*/
+
+void pdrawgfx_transpen(bitmap_ind16 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ bitmap_ind8 &priority, UINT32 pmask, UINT32 transpen)
+{
+ // special case invalid pens to opaque
+ if (transpen > 0xff)
+ return pdrawgfx_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, priority, pmask);
+
+ // use pen usage to optimize
+ code %= gfx->total_elements;
+ if (gfx->pen_usage != NULL && !gfx->dirty[code])
+ {
+ // fully transparent; do nothing
+ UINT32 usage = gfx->pen_usage[code];
+ if ((usage & ~(1 << transpen)) == 0)
+ return;
+
+ // fully opaque; draw as such
+ if ((usage & (1 << transpen)) == 0)
+ return pdrawgfx_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, priority, pmask);
+ }
+
+ // high bit of the mask is implicitly on
+ pmask |= 1 << 31;
+
+ // render
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ DRAWGFX_CORE(UINT16, PIXEL_OP_REMAP_TRANSPEN_PRIORITY, UINT8);
+}
+
+void pdrawgfx_transpen(bitmap_rgb32 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ bitmap_ind8 &priority, UINT32 pmask, UINT32 transpen)
+{
+ // special case invalid pens to opaque
+ if (transpen > 0xff)
+ return pdrawgfx_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, priority, pmask);
+
+ // use pen usage to optimize
+ code %= gfx->total_elements;
+ if (gfx->pen_usage != NULL && !gfx->dirty[code])
+ {
+ // fully transparent; do nothing
+ UINT32 usage = gfx->pen_usage[code];
+ if ((usage & ~(1 << transpen)) == 0)
+ return;
+
+ // fully opaque; draw as such
+ if ((usage & (1 << transpen)) == 0)
+ return pdrawgfx_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, priority, pmask);
+ }
+
+ // high bit of the mask is implicitly on
+ pmask |= 1 << 31;
+
+ // render
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ DRAWGFX_CORE(UINT32, PIXEL_OP_REMAP_TRANSPEN_PRIORITY, UINT8);
+}
+
+
+/*-------------------------------------------------
+ pdrawgfx_transpen_raw - render a gfx element
+ with a single transparent pen and no color
+ lookups, checking against the priority bitmap
+-------------------------------------------------*/
+
+void pdrawgfx_transpen_raw(bitmap_ind16 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ bitmap_ind8 &priority, UINT32 pmask, UINT32 transpen)
+{
+ // early out if completely transparent
+ code %= gfx->total_elements;
+ if (gfx->pen_usage != NULL && !gfx->dirty[code] && (gfx->pen_usage[code] & ~(1 << transpen)) == 0)
+ return;
+
+ // high bit of the mask is implicitly on
+ pmask |= 1 << 31;
+
+ // render
+ DRAWGFX_CORE(UINT16, PIXEL_OP_REBASE_TRANSPEN_PRIORITY, UINT8);
+}
+
+void pdrawgfx_transpen_raw(bitmap_rgb32 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ bitmap_ind8 &priority, UINT32 pmask, UINT32 transpen)
+{
+ // early out if completely transparent
+ code %= gfx->total_elements;
+ if (gfx->pen_usage != NULL && !gfx->dirty[code] && (gfx->pen_usage[code] & ~(1 << transpen)) == 0)
+ return;
+
+ // high bit of the mask is implicitly on
+ pmask |= 1 << 31;
+
+ // render
+ DRAWGFX_CORE(UINT32, PIXEL_OP_REBASE_TRANSPEN_PRIORITY, UINT8);
+}
+
+
+/*-------------------------------------------------
+ pdrawgfx_transmask - render a gfx element
+ with a multiple transparent pens provided as
+ a mask, checking against the priority bitmap
+-------------------------------------------------*/
+
+void pdrawgfx_transmask(bitmap_ind16 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ bitmap_ind8 &priority, UINT32 pmask, UINT32 transmask)
+{
+ // special case 0 mask to opaque
+ if (transmask == 0)
+ return pdrawgfx_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, priority, pmask);
+
+ // use pen usage to optimize
+ code %= gfx->total_elements;
+ if (gfx->pen_usage != NULL && !gfx->dirty[code])
+ {
+ // fully transparent; do nothing
+ UINT32 usage = gfx->pen_usage[code];
+ if ((usage & ~transmask) == 0)
+ return;
+
+ // fully opaque; draw as such
+ if ((usage & transmask) == 0)
+ return pdrawgfx_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, priority, pmask);
+ }
+
+ // high bit of the mask is implicitly on
+ pmask |= 1 << 31;
+
+ // render
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ DRAWGFX_CORE(UINT16, PIXEL_OP_REMAP_TRANSMASK_PRIORITY, UINT8);
+}
+
+void pdrawgfx_transmask(bitmap_rgb32 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ bitmap_ind8 &priority, UINT32 pmask, UINT32 transmask)
+{
+ // special case 0 mask to opaque
+ if (transmask == 0)
+ return pdrawgfx_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, priority, pmask);
+
+ // use pen usage to optimize
+ code %= gfx->total_elements;
+ if (gfx->pen_usage != NULL && !gfx->dirty[code])
+ {
+ // fully transparent; do nothing
+ UINT32 usage = gfx->pen_usage[code];
+ if ((usage & ~transmask) == 0)
+ return;
+
+ // fully opaque; draw as such
+ if ((usage & transmask) == 0)
+ return pdrawgfx_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, priority, pmask);
+ }
+
+ // high bit of the mask is implicitly on
+ pmask |= 1 << 31;
+
+ // render
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ DRAWGFX_CORE(UINT32, PIXEL_OP_REMAP_TRANSMASK_PRIORITY, UINT8);
+}
+
+
+/*-------------------------------------------------
+ pdrawgfx_transtable - render a gfx element
+ using a table to look up which pens are
+ transparent, opaque, or shadowing, checking
+ against the priority bitmap
+-------------------------------------------------*/
+
+void pdrawgfx_transtable(bitmap_ind16 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ bitmap_ind8 &priority, UINT32 pmask, const UINT8 *pentable, const pen_t *shadowtable)
+{
+ assert(pentable != NULL);
+
+ // high bit of the mask is implicitly on
+ pmask |= 1 << 31;
+
+ // render
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ code %= gfx->total_elements;
+ DRAWGFX_CORE(UINT16, PIXEL_OP_REMAP_TRANSTABLE16_PRIORITY, UINT8);
+}
+
+void pdrawgfx_transtable(bitmap_rgb32 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ bitmap_ind8 &priority, UINT32 pmask, const UINT8 *pentable, const pen_t *shadowtable)
+{
+ assert(pentable != NULL);
+
+ // high bit of the mask is implicitly on
+ pmask |= 1 << 31;
+
+ // render
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ code %= gfx->total_elements;
+ DRAWGFX_CORE(UINT32, PIXEL_OP_REMAP_TRANSTABLE32_PRIORITY, UINT8);
+}
+
+
+/*-------------------------------------------------
+ pdrawgfx_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 pdrawgfx_alpha(bitmap_rgb32 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ bitmap_ind8 &priority, UINT32 pmask, UINT32 transpen, UINT8 alpha)
+{
+ // special case alpha = 0xff
+ if (alpha == 0xff)
+ return pdrawgfx_transpen(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, priority, pmask, transpen);
+
+ // early out if completely transparent
+ code %= gfx->total_elements;
+ if (gfx->pen_usage != NULL && !gfx->dirty[code] && (gfx->pen_usage[code] & ~(1 << transpen)) == 0)
+ return;
+
+ // high bit of the mask is implicitly on
+ pmask |= 1 << 31;
+
+ // render
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ DRAWGFX_CORE(UINT32, PIXEL_OP_REMAP_TRANSPEN_ALPHA32_PRIORITY, UINT8);
+}
+
+
+
+/***************************************************************************
+ PDRAWGFXZOOM IMPLEMENTATIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ pdrawgfxzoom_opaque - render a scaled gfx
+ element with no transparency, checking against
+ the priority bitmap
+-------------------------------------------------*/
+
+void pdrawgfxzoom_opaque(bitmap_ind16 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley, bitmap_ind8 &priority, UINT32 pmask)
+{
+ // non-zoom case
+ if (scalex == 0x10000 && scaley == 0x10000)
+ return pdrawgfx_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, priority, pmask);
+
+ // high bit of the mask is implicitly on
+ pmask |= 1 << 31;
+
+ // render
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ code %= gfx->total_elements;
+ DRAWGFXZOOM_CORE(UINT16, PIXEL_OP_REMAP_OPAQUE_PRIORITY, UINT8);
+}
+
+void pdrawgfxzoom_opaque(bitmap_rgb32 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley, bitmap_ind8 &priority, UINT32 pmask)
+{
+ // non-zoom case
+ if (scalex == 0x10000 && scaley == 0x10000)
+ return pdrawgfx_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, priority, pmask);
+
+ // high bit of the mask is implicitly on
+ pmask |= 1 << 31;
+
+ // render
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ code %= gfx->total_elements;
+ DRAWGFXZOOM_CORE(UINT32, PIXEL_OP_REMAP_OPAQUE_PRIORITY, UINT8);
+}
+
+
+/*-------------------------------------------------
+ pdrawgfxzoom_transpen - render a scaled gfx
+ element with a single transparent pen,
+ checking against the priority bitmap
+-------------------------------------------------*/
+
+void pdrawgfxzoom_transpen(bitmap_ind16 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley, bitmap_ind8 &priority, UINT32 pmask,
+ UINT32 transpen)
+{
+ // non-zoom case
+ if (scalex == 0x10000 && scaley == 0x10000)
+ return pdrawgfx_transpen(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, priority, pmask, transpen);
+
+ // special case invalid pens to opaque
+ if (transpen > 0xff)
+ return pdrawgfxzoom_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, scalex, scaley, priority, pmask);
+
+ // use pen usage to optimize
+ code %= gfx->total_elements;
+ if (gfx->pen_usage != NULL && !gfx->dirty[code])
+ {
+ // fully transparent; do nothing
+ UINT32 usage = gfx->pen_usage[code];
+ if ((usage & ~(1 << transpen)) == 0)
+ return;
+
+ // fully opaque; draw as such
+ if ((usage & (1 << transpen)) == 0)
+ return pdrawgfxzoom_opaque(dest, cliprect, gfx, 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 = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ DRAWGFXZOOM_CORE(UINT16, PIXEL_OP_REMAP_TRANSPEN_PRIORITY, UINT8);
+}
+
+void pdrawgfxzoom_transpen(bitmap_rgb32 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley, bitmap_ind8 &priority, UINT32 pmask,
+ UINT32 transpen)
+{
+ // non-zoom case
+ if (scalex == 0x10000 && scaley == 0x10000)
+ return pdrawgfx_transpen(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, priority, pmask, transpen);
+
+ // special case invalid pens to opaque
+ if (transpen > 0xff)
+ return pdrawgfxzoom_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, scalex, scaley, priority, pmask);
+
+ // use pen usage to optimize
+ code %= gfx->total_elements;
+ if (gfx->pen_usage != NULL && !gfx->dirty[code])
+ {
+ // fully transparent; do nothing
+ UINT32 usage = gfx->pen_usage[code];
+ if ((usage & ~(1 << transpen)) == 0)
+ return;
+
+ // fully opaque; draw as such
+ if ((usage & (1 << transpen)) == 0)
+ return pdrawgfxzoom_opaque(dest, cliprect, gfx, 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 = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ DRAWGFXZOOM_CORE(UINT32, PIXEL_OP_REMAP_TRANSPEN_PRIORITY, UINT8);
+}
+
+
+/*-------------------------------------------------
+ pdrawgfxzoom_transpen_raw - render a scaled gfx
+ element with a single transparent pen and no
+ color lookups, checking against the priority
+ bitmap
+-------------------------------------------------*/
+
+void pdrawgfxzoom_transpen_raw(bitmap_ind16 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley, bitmap_ind8 &priority, UINT32 pmask,
+ UINT32 transpen)
+{
+ // non-zoom case
+ if (scalex == 0x10000 && scaley == 0x10000)
+ return pdrawgfx_transpen_raw(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, priority, pmask, transpen);
+
+ // early out if completely transparent
+ code %= gfx->total_elements;
+ if (gfx->pen_usage != NULL && !gfx->dirty[code] && (gfx->pen_usage[code] & ~(1 << transpen)) == 0)
+ return;
+
+ // high bit of the mask is implicitly on
+ pmask |= 1 << 31;
+
+ // render
+ DRAWGFXZOOM_CORE(UINT16, PIXEL_OP_REBASE_TRANSPEN_PRIORITY, UINT8);
+}
+
+void pdrawgfxzoom_transpen_raw(bitmap_rgb32 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley, bitmap_ind8 &priority, UINT32 pmask,
+ UINT32 transpen)
+{
+ // non-zoom case
+ if (scalex == 0x10000 && scaley == 0x10000)
+ return pdrawgfx_transpen_raw(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, priority, pmask, transpen);
+
+ // early out if completely transparent
+ code %= gfx->total_elements;
+ if (gfx->pen_usage != NULL && !gfx->dirty[code] && (gfx->pen_usage[code] & ~(1 << transpen)) == 0)
+ return;
+
+ // high bit of the mask is implicitly on
+ pmask |= 1 << 31;
+
+ // render
+ DRAWGFXZOOM_CORE(UINT32, PIXEL_OP_REBASE_TRANSPEN_PRIORITY, UINT8);
+}
+
+
+/*-------------------------------------------------
+ pdrawgfxzoom_transmask - render a scaled gfx
+ element with a multiple transparent pens
+ provided as a mask, checking against the
+ priority bitmap
+-------------------------------------------------*/
+
+void pdrawgfxzoom_transmask(bitmap_ind16 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley, bitmap_ind8 &priority, UINT32 pmask,
+ UINT32 transmask)
+{
+ // non-zoom case
+ if (scalex == 0x10000 && scaley == 0x10000)
+ return pdrawgfx_transmask(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, priority, pmask, transmask);
+
+ // special case 0 mask to opaque
+ if (transmask == 0)
+ return pdrawgfxzoom_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, scalex, scaley, priority, pmask);
+
+ // use pen usage to optimize
+ code %= gfx->total_elements;
+ if (gfx->pen_usage != NULL && !gfx->dirty[code])
+ {
+ // fully transparent; do nothing
+ UINT32 usage = gfx->pen_usage[code];
+ if ((usage & ~transmask) == 0)
+ return;
+
+ // fully opaque; draw as such
+ if ((usage & transmask) == 0)
+ return pdrawgfxzoom_opaque(dest, cliprect, gfx, 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 = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ DRAWGFXZOOM_CORE(UINT16, PIXEL_OP_REMAP_TRANSMASK_PRIORITY, UINT8);
+}
+
+void pdrawgfxzoom_transmask(bitmap_rgb32 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley, bitmap_ind8 &priority, UINT32 pmask,
+ UINT32 transmask)
+{
+ // non-zoom case
+ if (scalex == 0x10000 && scaley == 0x10000)
+ return pdrawgfx_transmask(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, priority, pmask, transmask);
+
+ // special case 0 mask to opaque
+ if (transmask == 0)
+ return pdrawgfxzoom_opaque(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, scalex, scaley, priority, pmask);
+
+ // use pen usage to optimize
+ code %= gfx->total_elements;
+ if (gfx->pen_usage != NULL && !gfx->dirty[code])
+ {
+ // fully transparent; do nothing
+ UINT32 usage = gfx->pen_usage[code];
+ if ((usage & ~transmask) == 0)
+ return;
+
+ // fully opaque; draw as such
+ if ((usage & transmask) == 0)
+ return pdrawgfxzoom_opaque(dest, cliprect, gfx, 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 = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ DRAWGFXZOOM_CORE(UINT32, PIXEL_OP_REMAP_TRANSMASK_PRIORITY, UINT8);
+}
+
+
+/*-------------------------------------------------
+ pdrawgfxzoom_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 pdrawgfxzoom_transtable(bitmap_ind16 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley, bitmap_ind8 &priority, UINT32 pmask,
+ const UINT8 *pentable, const pen_t *shadowtable)
+{
+ assert(pentable != NULL);
+
+ // non-zoom case
+ if (scalex == 0x10000 && scaley == 0x10000)
+ return pdrawgfx_transtable(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, priority, pmask, pentable, shadowtable);
+
+ // high bit of the mask is implicitly on
+ pmask |= 1 << 31;
+
+ // render
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ code %= gfx->total_elements;
+ DRAWGFXZOOM_CORE(UINT16, PIXEL_OP_REMAP_TRANSTABLE16_PRIORITY, UINT8);
+}
+
+void pdrawgfxzoom_transtable(bitmap_rgb32 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley, bitmap_ind8 &priority, UINT32 pmask,
+ const UINT8 *pentable, const pen_t *shadowtable)
+{
+ assert(pentable != NULL);
+
+ // non-zoom case
+ if (scalex == 0x10000 && scaley == 0x10000)
+ return pdrawgfx_transtable(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, priority, pmask, pentable, shadowtable);
+
+ // high bit of the mask is implicitly on
+ pmask |= 1 << 31;
+
+ // render
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ code %= gfx->total_elements;
+ DRAWGFXZOOM_CORE(UINT32, PIXEL_OP_REMAP_TRANSTABLE32_PRIORITY, UINT8);
+}
+
+
+/*-------------------------------------------------
+ pdrawgfxzoom_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 pdrawgfxzoom_alpha(bitmap_rgb32 &dest, const rectangle &cliprect, const gfx_element *gfx,
+ UINT32 code, UINT32 color, int flipx, int flipy, INT32 destx, INT32 desty,
+ UINT32 scalex, UINT32 scaley, bitmap_ind8 &priority, UINT32 pmask,
+ UINT32 transpen, UINT8 alpha)
+{
+ // non-zoom case
+ if (scalex == 0x10000 && scaley == 0x10000)
+ return pdrawgfx_alpha(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, priority, pmask, transpen, alpha);
+
+ // special case alpha = 0xff
+ if (alpha == 0xff)
+ return pdrawgfxzoom_transpen(dest, cliprect, gfx, code, color, flipx, flipy, destx, desty, scalex, scaley, priority, pmask, transpen);
+
+ // early out if completely transparent
+ code %= gfx->total_elements;
+ if (gfx->pen_usage != NULL && !gfx->dirty[code] && (gfx->pen_usage[code] & ~(1 << transpen)) == 0)
+ return;
+
+ // high bit of the mask is implicitly on
+ pmask |= 1 << 31;
+
+ // render
+ const pen_t *paldata = &gfx->machine().pens[gfx->color_base + gfx->color_granularity * (color % gfx->total_colors)];
+ DRAWGFXZOOM_CORE(UINT32, PIXEL_OP_REMAP_TRANSPEN_ALPHA32_PRIORITY, UINT8);
+}
+
+
+
+/***************************************************************************
+ DRAW_SCANLINE IMPLEMENTATIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ draw_scanline8 - copy pixels from an 8bpp
+ buffer to a single scanline of a bitmap
+-------------------------------------------------*/
+
+void draw_scanline8(bitmap_ind16 &bitmap, INT32 destx, INT32 desty, INT32 length, const UINT8 *srcptr, const pen_t *paldata)
+{
+ DECLARE_NO_PRIORITY;
+
+ // palette lookup case
+ if (paldata != NULL)
+ DRAWSCANLINE_CORE(UINT16, PIXEL_OP_REMAP_OPAQUE, NO_PRIORITY);
+
+ // raw copy case
+ else
+ DRAWSCANLINE_CORE(UINT16, PIXEL_OP_COPY_OPAQUE, NO_PRIORITY);
+}
+
+void draw_scanline8(bitmap_rgb32 &bitmap, INT32 destx, INT32 desty, INT32 length, const UINT8 *srcptr, const pen_t *paldata)
+{
+ DECLARE_NO_PRIORITY;
+
+ // palette lookup case
+ if (paldata != NULL)
+ DRAWSCANLINE_CORE(UINT32, PIXEL_OP_REMAP_OPAQUE, NO_PRIORITY);
+
+ // raw copy case
+ else
+ DRAWSCANLINE_CORE(UINT32, 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, INT32 destx, INT32 desty, INT32 length, const UINT16 *srcptr, const pen_t *paldata)
+{
+ DECLARE_NO_PRIORITY;
+
+ // palette lookup case
+ if (paldata != NULL)
+ DRAWSCANLINE_CORE(UINT16, PIXEL_OP_REMAP_OPAQUE, NO_PRIORITY);
+
+ // raw copy case
+ else
+ DRAWSCANLINE_CORE(UINT16, PIXEL_OP_COPY_OPAQUE, NO_PRIORITY);
+}
+
+void draw_scanline16(bitmap_rgb32 &bitmap, INT32 destx, INT32 desty, INT32 length, const UINT16 *srcptr, const pen_t *paldata)
+{
+ DECLARE_NO_PRIORITY;
+
+ // palette lookup case
+ if (paldata != NULL)
+ DRAWSCANLINE_CORE(UINT32, PIXEL_OP_REMAP_OPAQUE, NO_PRIORITY);
+
+ // raw copy case
+ else
+ DRAWSCANLINE_CORE(UINT32, 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, INT32 destx, INT32 desty, INT32 length, const UINT32 *srcptr, const pen_t *paldata)
+{
+ DECLARE_NO_PRIORITY;
+
+ // palette lookup case
+ if (paldata != NULL)
+ DRAWSCANLINE_CORE(UINT16, PIXEL_OP_REMAP_OPAQUE, NO_PRIORITY);
+
+ // raw copy case
+ else
+ DRAWSCANLINE_CORE(UINT16, PIXEL_OP_COPY_OPAQUE, NO_PRIORITY);
+}
+
+void draw_scanline32(bitmap_rgb32 &bitmap, INT32 destx, INT32 desty, INT32 length, const UINT32 *srcptr, const pen_t *paldata)
+{
+ DECLARE_NO_PRIORITY;
+
+ // palette lookup case
+ if (paldata != NULL)
+ DRAWSCANLINE_CORE(UINT32, PIXEL_OP_REMAP_OPAQUE, NO_PRIORITY);
+
+ // raw copy case
+ else
+ DRAWSCANLINE_CORE(UINT32, 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(bitmap_ind16 &bitmap, INT32 srcx, INT32 srcy, INT32 length, UINT8 *destptr)
+{
+ EXTRACTSCANLINE_CORE(UINT16);
+}
+
+void extract_scanline8(bitmap_rgb32 &bitmap, INT32 srcx, INT32 srcy, INT32 length, UINT8 *destptr)
+{
+ EXTRACTSCANLINE_CORE(UINT32);
+}
+
+
+/*-------------------------------------------------
+ extract_scanline16 - copy pixels from a single
+ scanline of a bitmap to a 16bpp buffer
+-------------------------------------------------*/
+
+void extract_scanline16(bitmap_ind16 &bitmap, INT32 srcx, INT32 srcy, INT32 length, UINT16 *destptr)
+{
+ EXTRACTSCANLINE_CORE(UINT16);
+}
+
+void extract_scanline16(bitmap_rgb32 &bitmap, INT32 srcx, INT32 srcy, INT32 length, UINT16 *destptr)
+{
+ EXTRACTSCANLINE_CORE(UINT32);
+}
+
+
+/*-------------------------------------------------
+ extract_scanline32 - copy pixels from a single
+ scanline of a bitmap to a 32bpp buffer
+-------------------------------------------------*/
+
+void extract_scanline32(bitmap_ind16 &bitmap, INT32 srcx, INT32 srcy, INT32 length, UINT32 *destptr)
+{
+ EXTRACTSCANLINE_CORE(UINT16);
+}
+
+void extract_scanline32(bitmap_rgb32 &bitmap, INT32 srcx, INT32 srcy, INT32 length, UINT32 *destptr)
+{
+ EXTRACTSCANLINE_CORE(UINT32);
+}
+
+
+
+/***************************************************************************
+ COPYBITMAP IMPLEMENTATIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ copybitmap - copy from one bitmap to another,
+ copying all unclipped pixels
+-------------------------------------------------*/
+
+void copybitmap(bitmap_ind16 &dest, bitmap_ind16 &src, int flipx, int flipy, INT32 destx, INT32 desty, const rectangle &cliprect)
+{
+ DECLARE_NO_PRIORITY;
+ COPYBITMAP_CORE(UINT16, PIXEL_OP_COPY_OPAQUE, NO_PRIORITY);
+}
+
+void copybitmap(bitmap_rgb32 &dest, bitmap_rgb32 &src, int flipx, int flipy, INT32 destx, INT32 desty, const rectangle &cliprect)
+{
+ DECLARE_NO_PRIORITY;
+ COPYBITMAP_CORE(UINT32, 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, bitmap_ind16 &src, int flipx, int flipy, INT32 destx, INT32 desty, const rectangle &cliprect, UINT32 transpen)
+{
+ DECLARE_NO_PRIORITY;
+ if (transpen > 0xffff)
+ copybitmap(dest, src, flipx, flipy, destx, desty, cliprect);
+ else
+ COPYBITMAP_CORE(UINT16, PIXEL_OP_COPY_TRANSPEN, NO_PRIORITY);
+}
+
+void copybitmap_trans(bitmap_rgb32 &dest, bitmap_rgb32 &src, int flipx, int flipy, INT32 destx, INT32 desty, const rectangle &cliprect, UINT32 transpen)
+{
+ DECLARE_NO_PRIORITY;
+ if (transpen == 0xffffffff)
+ copybitmap(dest, src, flipx, flipy, destx, desty, cliprect);
+ else
+ COPYBITMAP_CORE(UINT32, PIXEL_OP_COPY_TRANSPEN, 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, bitmap_ind16 &src, UINT32 numrows, const INT32 *rowscroll, UINT32 numcols, const INT32 *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, bitmap_rgb32 &src, UINT32 numrows, const INT32 *rowscroll, UINT32 numcols, const INT32 *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, _BitmapClass &src, UINT32 numrows, const INT32 *rowscroll, UINT32 numcols, const INT32 *colscroll, const rectangle &cliprect, UINT32 transpen)
+{
+ // no rowscroll and no colscroll means no scroll
+ if (numrows == 0 && numcols == 0)
+ return copybitmap_trans(dest, src, 0, 0, 0, 0, cliprect, transpen);
+
+ assert(numrows != 0 || rowscroll == NULL);
+ assert(numrows == 0 || rowscroll != NULL);
+ assert(numcols != 0 || colscroll == NULL);
+ assert(numcols == 0 || colscroll != NULL);
+
+ // fully scrolling X,Y playfield
+ if (numrows <= 1 && numcols <= 1)
+ {
+ INT32 xscroll = normalize_xscroll(src, (numrows == 0) ? 0 : rowscroll[0]);
+ INT32 yscroll = normalize_yscroll(src, (numcols == 0) ? 0 : colscroll[0]);
+
+ // iterate over all portions of the scroll that overlap the destination
+ for (INT32 sx = xscroll - src.width(); sx < dest.width(); sx += src.width())
+ for (INT32 sy = yscroll - src.height(); sy < dest.height(); sy += src.height())
+ copybitmap_trans(dest, src, 0, 0, sx, sy, cliprect, transpen);
+ }
+
+ // scrolling columns plus horizontal scroll
+ else if (numrows <= 1)
+ {
+ INT32 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)
+ {
+ INT32 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 (INT32 sx = xscroll - src.width(); sx < dest.width(); sx += src.width())
+ {
+ // compute the cliprect for this group
+ subclip.min_x = col * colwidth + sx;
+ subclip.max_x = (col + groupcols) * colwidth - 1 + sx;
+ subclip &= cliprect;
+
+ // iterate over all portions of the scroll that overlap the destination
+ for (INT32 sy = yscroll - src.height(); sy < dest.height(); sy += src.height())
+ copybitmap_trans(dest, src, 0, 0, sx, sy, subclip, transpen);
+ }
+ }
+ }
+
+ // scrolling rows plus vertical scroll
+ else if (numcols <= 1)
+ {
+ INT32 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)
+ {
+ INT32 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 (INT32 sy = yscroll - src.height(); sy < dest.height(); sy += src.height())
+ {
+ // compute the cliprect for this group
+ subclip.min_y = row * rowheight + sy;
+ subclip.max_y = (row + grouprows) * rowheight - 1 + sy;
+ subclip &= cliprect;
+
+ // iterate over all portions of the scroll that overlap the destination
+ for (INT32 sx = xscroll - src.width(); sx < dest.width(); sx += src.width())
+ copybitmap_trans(dest, src, 0, 0, sx, sy, subclip, transpen);
+ }
+ }
+ }
+}
+
+void copyscrollbitmap_trans(bitmap_ind16 &dest, bitmap_ind16 &src, UINT32 numrows, const INT32 *rowscroll, UINT32 numcols, const INT32 *colscroll, const rectangle &cliprect, UINT32 transpen)
+{ copyscrollbitmap_trans_common(dest, src, numrows, rowscroll, numcols, colscroll, cliprect, transpen); }
+
+void copyscrollbitmap_trans(bitmap_rgb32 &dest, bitmap_rgb32 &src, UINT32 numrows, const INT32 *rowscroll, UINT32 numcols, const INT32 *colscroll, const rectangle &cliprect, UINT32 transpen)
+{ copyscrollbitmap_trans_common(dest, src, numrows, rowscroll, numcols, colscroll, cliprect, transpen); }
+
+
+
+/***************************************************************************
+ 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, bitmap_ind16 &src, INT32 startx, INT32 starty, INT32 incxx, INT32 incxy, INT32 incyx, INT32 incyy, int wraparound)
+{
+ DECLARE_NO_PRIORITY;
+ COPYROZBITMAP_CORE(UINT16, PIXEL_OP_COPY_OPAQUE, NO_PRIORITY);
+}
+
+void copyrozbitmap(bitmap_rgb32 &dest, const rectangle &cliprect, bitmap_rgb32 &src, INT32 startx, INT32 starty, INT32 incxx, INT32 incxy, INT32 incyx, INT32 incyy, int wraparound)
+{
+ DECLARE_NO_PRIORITY;
+ COPYROZBITMAP_CORE(UINT32, 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, bitmap_ind16 &src, INT32 startx, INT32 starty, INT32 incxx, INT32 incxy, INT32 incyx, INT32 incyy, int wraparound, UINT32 transpen)
+{
+ DECLARE_NO_PRIORITY;
+ COPYROZBITMAP_CORE(UINT16, PIXEL_OP_COPY_TRANSPEN, NO_PRIORITY);
+}
+
+void copyrozbitmap_trans(bitmap_rgb32 &dest, const rectangle &cliprect, bitmap_rgb32 &src, INT32 startx, INT32 starty, INT32 incxx, INT32 incxy, INT32 incyx, INT32 incyy, int wraparound, UINT32 transpen)
+{
+ DECLARE_NO_PRIORITY;
+ COPYROZBITMAP_CORE(UINT32, PIXEL_OP_COPY_TRANSPEN, NO_PRIORITY);
+}