1 // license:BSD-3-Clause
2 // copyright-holders:Nicola Salmoria, Aaron Giles
3 /*********************************************************************
4 
5     drawgfx.cpp
6 
7     Generic graphic functions.
8 
9 *********************************************************************/
10 
11 #include "emu.h"
12 #include "drawgfxt.ipp"
13 
14 
15 /***************************************************************************
16     INLINE FUNCTIONS
17 ***************************************************************************/
18 
19 /*-------------------------------------------------
20     readbit - read a single bit from a base
21     offset
22 -------------------------------------------------*/
23 
readbit(const u8 * src,unsigned int bitnum)24 static inline int readbit(const u8 *src, unsigned int bitnum)
25 {
26 	return src[bitnum / 8] & (0x80 >> (bitnum % 8));
27 }
28 
29 
30 /*-------------------------------------------------
31     normalize_xscroll - normalize an X scroll
32     value for a bitmap to be positive and less
33     than the width
34 -------------------------------------------------*/
35 
normalize_xscroll(const bitmap_t & bitmap,s32 xscroll)36 static inline s32 normalize_xscroll(const bitmap_t &bitmap, s32 xscroll)
37 {
38 	return (xscroll >= 0) ? xscroll % bitmap.width() : (bitmap.width() - (-xscroll) % bitmap.width());
39 }
40 
41 
42 /*-------------------------------------------------
43     normalize_yscroll - normalize a Y scroll
44     value for a bitmap to be positive and less
45     than the height
46 -------------------------------------------------*/
47 
normalize_yscroll(const bitmap_t & bitmap,s32 yscroll)48 static inline s32 normalize_yscroll(const bitmap_t &bitmap, s32 yscroll)
49 {
50 	return (yscroll >= 0) ? yscroll % bitmap.height() : (bitmap.height() - (-yscroll) % bitmap.height());
51 }
52 
53 
54 
55 //**************************************************************************
56 //  DEVICE DEFINITIONS
57 //**************************************************************************
58 
59 DEFINE_DEVICE_TYPE(GFXDECODE, gfxdecode_device, "gfxdecode", "gfxdecode")
60 
gfxdecode_device(const machine_config & mconfig,const char * tag,device_t * owner,u32 clock)61 gfxdecode_device::gfxdecode_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
62 	device_t(mconfig, GFXDECODE, tag, owner, clock),
63 	device_gfx_interface(mconfig, *this)
64 {
65 }
66 
67 
68 
69 
70 /***************************************************************************
71     GRAPHICS ELEMENTS
72 ***************************************************************************/
73 
74 
75 //-------------------------------------------------
76 //  gfx_element - constructor
77 //-------------------------------------------------
78 
gfx_element(device_palette_interface * palette,u8 * base,u16 width,u16 height,u32 rowbytes,u32 total_colors,u32 color_base,u32 color_granularity)79 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)
80 	: m_palette(palette),
81 		m_width(width),
82 		m_height(height),
83 		m_startx(0),
84 		m_starty(0),
85 		m_origwidth(width),
86 		m_origheight(height),
87 		m_total_elements(1),
88 		m_color_base(color_base),
89 		m_color_depth(color_granularity),
90 		m_color_granularity(color_granularity),
91 		m_total_colors((total_colors - color_base) / color_granularity),
92 		m_line_modulo(rowbytes),
93 		m_char_modulo(0),
94 		m_srcdata(base),
95 		m_dirtyseq(1),
96 		m_gfxdata(base),
97 		m_layout_is_raw(true),
98 		m_layout_planes(0),
99 		m_layout_xormask(0),
100 		m_layout_charincrement(0)
101 {
102 }
103 
gfx_element(device_palette_interface * palette,const gfx_layout & gl,const u8 * srcdata,u32 xormask,u32 total_colors,u32 color_base)104 gfx_element::gfx_element(device_palette_interface *palette, const gfx_layout &gl, const u8 *srcdata, u32 xormask, u32 total_colors, u32 color_base)
105 	: m_palette(palette),
106 		m_width(0),
107 		m_height(0),
108 		m_startx(0),
109 		m_starty(0),
110 		m_origwidth(0),
111 		m_origheight(0),
112 		m_total_elements(0),
113 		m_color_base(color_base),
114 		m_color_depth(0),
115 		m_color_granularity(0),
116 		m_total_colors(total_colors),
117 		m_line_modulo(0),
118 		m_char_modulo(0),
119 		m_srcdata(nullptr),
120 		m_dirtyseq(1),
121 		m_gfxdata(nullptr),
122 		m_layout_is_raw(false),
123 		m_layout_planes(0),
124 		m_layout_xormask(xormask),
125 		m_layout_charincrement(0)
126 {
127 	// set the layout
128 	set_layout(gl, srcdata);
129 }
130 
131 
132 //-------------------------------------------------
133 //  set_layout - set the layout for a gfx_element
134 //-------------------------------------------------
135 
set_layout(const gfx_layout & gl,const u8 * srcdata)136 void gfx_element::set_layout(const gfx_layout &gl, const u8 *srcdata)
137 {
138 	m_srcdata = srcdata;
139 
140 	// configure ourselves
141 	m_width = m_origwidth = gl.width;
142 	m_height = m_origheight = gl.height;
143 	m_startx = m_starty = 0;
144 	m_total_elements = gl.total;
145 	m_color_depth = m_color_granularity = 1 << gl.planes;
146 
147 	// copy data from the layout
148 	m_layout_is_raw = (gl.planeoffset[0] == GFX_RAW);
149 	m_layout_planes = gl.planes;
150 	m_layout_charincrement = gl.charincrement;
151 
152 	// raw graphics case
153 	if (m_layout_is_raw)
154 	{
155 		// RAW layouts don't need these arrays
156 		m_layout_planeoffset.clear();
157 		m_layout_xoffset.clear();
158 		m_layout_yoffset.clear();
159 		m_gfxdata_allocated.clear();
160 
161 		// modulos are determined for us by the layout
162 		m_line_modulo = gl.yoffs(0) / 8;
163 		m_char_modulo = gl.charincrement / 8;
164 
165 		// RAW graphics must have a pointer up front
166 		assert(srcdata != nullptr);
167 		m_gfxdata = const_cast<u8 *>(srcdata);
168 	}
169 
170 	// decoded graphics case
171 	else
172 	{
173 		// copy offsets
174 		m_layout_planeoffset.resize(m_layout_planes);
175 		m_layout_xoffset.resize(m_width);
176 		m_layout_yoffset.resize(m_height);
177 
178 		for (int p = 0; p < m_layout_planes; p++)
179 			m_layout_planeoffset[p] = gl.planeoffset[p];
180 		for (int y = 0; y < m_height; y++)
181 			m_layout_yoffset[y] = gl.yoffs(y);
182 		for (int x = 0; x < m_width; x++)
183 			m_layout_xoffset[x] = gl.xoffs(x);
184 
185 		// we get to pick our own modulos
186 		m_line_modulo = m_origwidth;
187 		m_char_modulo = m_line_modulo * m_origheight;
188 
189 		// allocate memory for the data
190 		m_gfxdata_allocated.resize(m_total_elements * m_char_modulo);
191 		m_gfxdata = &m_gfxdata_allocated[0];
192 	}
193 
194 	// mark everything dirty
195 	m_dirty.resize(m_total_elements);
196 	memset(&m_dirty[0], 1, m_total_elements);
197 
198 	// allocate a pen usage array for entries with 32 pens or less
199 	if (m_color_depth <= 32)
200 		m_pen_usage.resize(m_total_elements);
201 	else
202 		m_pen_usage.clear();
203 }
204 
205 
206 //-------------------------------------------------
207 //  set_raw_layout - set the layout for a gfx_element
208 //-------------------------------------------------
209 
set_raw_layout(const u8 * srcdata,u32 width,u32 height,u32 total,u32 linemod,u32 charmod)210 void gfx_element::set_raw_layout(const u8 *srcdata, u32 width, u32 height, u32 total, u32 linemod, u32 charmod)
211 {
212 	gfx_layout layout = { 0 };
213 	layout.width = width;
214 	layout.height = height;
215 	layout.total = total;
216 	layout.planes = 8;
217 	layout.planeoffset[0] = GFX_RAW;
218 	layout.yoffset[0] = linemod;
219 	layout.charincrement = charmod;
220 	set_layout(layout, srcdata);
221 }
222 
223 
224 //-------------------------------------------------
225 // set_source - set the source data for a gfx_element
226 //-------------------------------------------------
227 
set_source(const u8 * source)228 void gfx_element::set_source(const u8 *source)
229 {
230 	m_srcdata = source;
231 	memset(&m_dirty[0], 1, elements());
232 	if (m_layout_is_raw) m_gfxdata = const_cast<u8 *>(source);
233 }
234 
235 
236 //-------------------------------------------------
237 // set_source_and_total - set the source data
238 // and total elements for a gfx_element
239 //-------------------------------------------------
240 
set_source_and_total(const u8 * source,u32 total)241 void gfx_element::set_source_and_total(const u8 *source, u32 total)
242 {
243 	m_srcdata = source;
244 	m_total_elements = total;
245 
246 	// mark everything dirty
247 	m_dirty.resize(m_total_elements);
248 	memset(&m_dirty[0], 1, m_total_elements);
249 
250 	// allocate a pen usage array for entries with 32 pens or less
251 	if (m_color_depth <= 32)
252 		m_pen_usage.resize(m_total_elements);
253 
254 	if (m_layout_is_raw)
255 	{
256 		m_gfxdata = const_cast<u8 *>(source);
257 	}
258 	else
259 	{
260 		// allocate memory for the data
261 		m_gfxdata_allocated.resize(m_total_elements * m_char_modulo);
262 		m_gfxdata = &m_gfxdata_allocated[0];
263 	}
264 }
265 
266 
267 //-------------------------------------------------
268 //  set_source_clip - set a source clipping rect
269 //-------------------------------------------------
270 
set_source_clip(u32 xoffs,u32 width,u32 yoffs,u32 height)271 void gfx_element::set_source_clip(u32 xoffs, u32 width, u32 yoffs, u32 height)
272 {
273 	assert(xoffs < m_origwidth);
274 	assert(yoffs < m_origheight);
275 	assert(xoffs + width <= m_origwidth);
276 	assert(yoffs + height <= m_origheight);
277 
278 	m_width = width;
279 	m_height = height;
280 	m_startx = xoffs;
281 	m_starty = yoffs;
282 }
283 
284 
285 //-------------------------------------------------
286 //  decode - decode a single character
287 //-------------------------------------------------
288 
decode(u32 code)289 void gfx_element::decode(u32 code)
290 {
291 	// don't decode GFX_RAW
292 	if (!m_layout_is_raw)
293 	{
294 		// zap the data to 0
295 		u8 *decode_base = m_gfxdata + code * m_char_modulo;
296 		memset(decode_base, 0, m_char_modulo);
297 
298 		// iterate over planes
299 		int plane, planebit;
300 		for (plane = 0, planebit = 1 << (m_layout_planes - 1);
301 				plane < m_layout_planes;
302 				plane++, planebit >>= 1)
303 		{
304 			int planeoffs = code * m_layout_charincrement + m_layout_planeoffset[plane];
305 
306 			// iterate over rows
307 			for (int y = 0; y < m_origheight; y++)
308 			{
309 				int yoffs = planeoffs + m_layout_yoffset[y];
310 				u8 *dp = decode_base + y * m_line_modulo;
311 
312 				// iterate over columns
313 				for (int x = 0; x < m_origwidth; x++)
314 					if (readbit(m_srcdata, (yoffs + m_layout_xoffset[x]) ^ m_layout_xormask))
315 						dp[x] |= planebit;
316 			}
317 		}
318 	}
319 
320 	// (re)compute pen usage
321 	if (code < m_pen_usage.size())
322 	{
323 		// iterate over data, creating a bitmask of live pens
324 		const u8 *dp = m_gfxdata + code * m_char_modulo;
325 		u32 usage = 0;
326 		for (int y = 0; y < m_origheight; y++)
327 		{
328 			for (int x = 0; x < m_origwidth; x++)
329 				usage |= 1 << dp[x];
330 			dp += m_line_modulo;
331 		}
332 
333 		// store the final result
334 		m_pen_usage[code] = usage;
335 	}
336 
337 	// no longer dirty
338 	m_dirty[code] = 0;
339 }
340 
341 
342 
343 /***************************************************************************
344     DRAWGFX IMPLEMENTATIONS
345 ***************************************************************************/
346 
347 /*-------------------------------------------------
348     opaque - render a gfx element with
349     no transparency
350 -------------------------------------------------*/
351 
opaque(bitmap_ind16 & dest,const rectangle & cliprect,u32 code,u32 color,int flipx,int flipy,s32 destx,s32 desty)352 void gfx_element::opaque(bitmap_ind16 &dest, const rectangle &cliprect,
353 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty)
354 {
355 	color = colorbase() + granularity() * (color % colors());
356 	code %= elements();
357 	drawgfx_core(dest, cliprect, code, flipx, flipy, destx, desty, [color](u16 &destp, const u8 &srcp) { PIXEL_OP_REBASE_OPAQUE(destp, srcp); });
358 }
359 
opaque(bitmap_rgb32 & dest,const rectangle & cliprect,u32 code,u32 color,int flipx,int flipy,s32 destx,s32 desty)360 void gfx_element::opaque(bitmap_rgb32 &dest, const rectangle &cliprect,
361 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty)
362 {
363 	const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
364 	code %= elements();
365 	drawgfx_core(dest, cliprect, code, flipx, flipy, destx, desty, [paldata](u32 &destp, const u8 &srcp) { PIXEL_OP_REMAP_OPAQUE(destp, srcp); });
366 }
367 
368 
369 /*-------------------------------------------------
370     transpen - render a gfx element with
371     a single transparent pen
372 -------------------------------------------------*/
373 
transpen(bitmap_ind16 & dest,const rectangle & cliprect,u32 code,u32 color,int flipx,int flipy,s32 destx,s32 desty,u32 trans_pen)374 void gfx_element::transpen(bitmap_ind16 &dest, const rectangle &cliprect,
375 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
376 		u32 trans_pen)
377 {
378 	// special case invalid pens to opaque
379 	if (trans_pen > 0xff)
380 		return opaque(dest, cliprect, code, color, flipx, flipy, destx, desty);
381 
382 	// use pen usage to optimize
383 	code %= elements();
384 	if (has_pen_usage())
385 	{
386 		// fully transparent; do nothing
387 		u32 usage = pen_usage(code);
388 		if ((usage & ~(1 << trans_pen)) == 0)
389 			return;
390 
391 		// fully opaque; draw as such
392 		if ((usage & (1 << trans_pen)) == 0)
393 			return opaque(dest, cliprect, code, color, flipx, flipy, destx, desty);
394 	}
395 
396 	// render
397 	color = colorbase() + granularity() * (color % colors());
398 	drawgfx_core(dest, cliprect, code, flipx, flipy, destx, desty, [trans_pen, color](u16 &destp, const u8 &srcp) { PIXEL_OP_REBASE_TRANSPEN(destp, srcp); });
399 }
400 
transpen(bitmap_rgb32 & dest,const rectangle & cliprect,u32 code,u32 color,int flipx,int flipy,s32 destx,s32 desty,u32 trans_pen)401 void gfx_element::transpen(bitmap_rgb32 &dest, const rectangle &cliprect,
402 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
403 		u32 trans_pen)
404 {
405 	// special case invalid pens to opaque
406 	if (trans_pen > 0xff)
407 		return opaque(dest, cliprect, code, color, flipx, flipy, destx, desty);
408 
409 	// use pen usage to optimize
410 	code %= elements();
411 	if (has_pen_usage())
412 	{
413 		// fully transparent; do nothing
414 		u32 usage = pen_usage(code);
415 		if ((usage & ~(1 << trans_pen)) == 0)
416 			return;
417 
418 		// fully opaque; draw as such
419 		if ((usage & (1 << trans_pen)) == 0)
420 			return opaque(dest, cliprect, code, color, flipx, flipy, destx, desty);
421 	}
422 
423 	// render
424 	const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
425 	drawgfx_core(dest, cliprect, code, flipx, flipy, destx, desty, [trans_pen, paldata](u32 &destp, const u8 &srcp) { PIXEL_OP_REMAP_TRANSPEN(destp, srcp); });
426 }
427 
428 
429 /*-------------------------------------------------
430     transpen_raw - render a gfx element
431     with a single transparent pen and no color
432     lookups
433 -------------------------------------------------*/
434 
transpen_raw(bitmap_ind16 & dest,const rectangle & cliprect,u32 code,u32 color,int flipx,int flipy,s32 destx,s32 desty,u32 trans_pen)435 void gfx_element::transpen_raw(bitmap_ind16 &dest, const rectangle &cliprect,
436 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
437 		u32 trans_pen)
438 {
439 	// early out if completely transparent
440 	code %= elements();
441 	if (has_pen_usage() && (pen_usage(code) & ~(1 << trans_pen)) == 0)
442 		return;
443 
444 	// render
445 	drawgfx_core(dest, cliprect, code, flipx, flipy, destx, desty, [trans_pen, color](u16 &destp, const u8 &srcp) { PIXEL_OP_REBASE_TRANSPEN(destp, srcp); });
446 }
447 
transpen_raw(bitmap_rgb32 & dest,const rectangle & cliprect,u32 code,u32 color,int flipx,int flipy,s32 destx,s32 desty,u32 trans_pen)448 void gfx_element::transpen_raw(bitmap_rgb32 &dest, const rectangle &cliprect,
449 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
450 		u32 trans_pen)
451 {
452 	// early out if completely transparent
453 	code %= elements();
454 	if (has_pen_usage() && (pen_usage(code) & ~(1 << trans_pen)) == 0)
455 		return;
456 
457 	// render
458 	drawgfx_core(dest, cliprect, code, flipx, flipy, destx, desty, [trans_pen, color](u32 &destp, const u8 &srcp) { PIXEL_OP_REBASE_TRANSPEN(destp, srcp); });
459 }
460 
461 
462 /*-------------------------------------------------
463     transmask - render a gfx element
464     with a multiple transparent pens provided as
465     a mask
466 -------------------------------------------------*/
467 
transmask(bitmap_ind16 & dest,const rectangle & cliprect,u32 code,u32 color,int flipx,int flipy,s32 destx,s32 desty,u32 trans_mask)468 void gfx_element::transmask(bitmap_ind16 &dest, const rectangle &cliprect,
469 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
470 		u32 trans_mask)
471 {
472 	// special case 0 mask to opaque
473 	if (trans_mask == 0)
474 		return opaque(dest, cliprect, code, color, flipx, flipy, destx, desty);
475 
476 	// use pen usage to optimize
477 	code %= elements();
478 	if (has_pen_usage())
479 	{
480 		// fully transparent; do nothing
481 		u32 usage = pen_usage(code);
482 		if ((usage & ~trans_mask) == 0)
483 			return;
484 
485 		// fully opaque; draw as such
486 		if ((usage & trans_mask) == 0)
487 			return opaque(dest, cliprect, code, color, flipx, flipy, destx, desty);
488 	}
489 
490 	// render
491 	color = colorbase() + granularity() * (color % colors());
492 	drawgfx_core(dest, cliprect, code, flipx, flipy, destx, desty, [trans_mask, color](u16 &destp, const u8 &srcp) { PIXEL_OP_REBASE_TRANSMASK(destp, srcp); });
493 }
494 
transmask(bitmap_rgb32 & dest,const rectangle & cliprect,u32 code,u32 color,int flipx,int flipy,s32 destx,s32 desty,u32 trans_mask)495 void gfx_element::transmask(bitmap_rgb32 &dest, const rectangle &cliprect,
496 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
497 		u32 trans_mask)
498 {
499 	// special case 0 mask to opaque
500 	if (trans_mask == 0)
501 		return opaque(dest, cliprect, code, color, flipx, flipy, destx, desty);
502 
503 	// use pen usage to optimize
504 	code %= elements();
505 	if (has_pen_usage())
506 	{
507 		// fully transparent; do nothing
508 		u32 usage = pen_usage(code);
509 		if ((usage & ~trans_mask) == 0)
510 			return;
511 
512 		// fully opaque; draw as such
513 		if ((usage & trans_mask) == 0)
514 			return opaque(dest, cliprect, code, color, flipx, flipy, destx, desty);
515 	}
516 
517 	// render
518 	const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
519 	drawgfx_core(dest, cliprect, code, flipx, flipy, destx, desty, [trans_mask, paldata](u32 &destp, const u8 &srcp) { PIXEL_OP_REMAP_TRANSMASK(destp, srcp); });
520 }
521 
522 
523 /*-------------------------------------------------
524     transtable - render a gfx element
525     using a table to look up which pens are
526     transparent, opaque, or shadowing
527 -------------------------------------------------*/
528 
transtable(bitmap_ind16 & dest,const rectangle & cliprect,u32 code,u32 color,int flipx,int flipy,s32 destx,s32 desty,const u8 * pentable)529 void gfx_element::transtable(bitmap_ind16 &dest, const rectangle &cliprect,
530 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
531 		const u8 *pentable)
532 {
533 	assert(pentable != nullptr);
534 
535 	// render
536 	color = colorbase() + granularity() * (color % colors());
537 	const pen_t *shadowtable = m_palette->shadow_table();
538 	code %= elements();
539 	drawgfx_core(dest, cliprect, code, flipx, flipy, destx, desty, [pentable, color, shadowtable](u16 &destp, const u8 &srcp) { PIXEL_OP_REBASE_TRANSTABLE16(destp, srcp); });
540 }
541 
transtable(bitmap_rgb32 & dest,const rectangle & cliprect,u32 code,u32 color,int flipx,int flipy,s32 destx,s32 desty,const u8 * pentable)542 void gfx_element::transtable(bitmap_rgb32 &dest, const rectangle &cliprect,
543 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
544 		const u8 *pentable)
545 {
546 	assert(pentable != nullptr);
547 
548 	// render
549 	const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
550 	const pen_t *shadowtable = m_palette->shadow_table();
551 	code %= elements();
552 	drawgfx_core(dest, cliprect, code, flipx, flipy, destx, desty, [pentable, paldata, shadowtable](u32 &destp, const u8 &srcp) { PIXEL_OP_REMAP_TRANSTABLE32(destp, srcp); });
553 }
554 
555 
556 /*-------------------------------------------------
557     alpha - render a gfx element with
558     a single transparent pen, alpha blending the
559     remaining pixels with a fixed alpha value
560 -------------------------------------------------*/
561 
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)562 void gfx_element::alpha(bitmap_rgb32 &dest, const rectangle &cliprect,
563 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
564 		u32 trans_pen, u8 alpha_val)
565 {
566 	// special case alpha = 0xff
567 	if (alpha_val == 0xff)
568 		return transpen(dest, cliprect, code, color, flipx, flipy, destx, desty, trans_pen);
569 
570 	// early out if completely transparent
571 	code %= elements();
572 	if (has_pen_usage() && (pen_usage(code) & ~(1 << trans_pen)) == 0)
573 		return;
574 
575 	// get final code and color, and grab lookup tables
576 	const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
577 	drawgfx_core(dest, cliprect, code, flipx, flipy, destx, desty, [trans_pen, alpha_val, paldata](u32 &destp, const u8 &srcp) { PIXEL_OP_REMAP_TRANSPEN_ALPHA32(destp, srcp); });
578 }
579 
580 
581 
582 /***************************************************************************
583     DRAWGFXZOOM IMPLEMENTATIONS
584 ***************************************************************************/
585 
586 /*-------------------------------------------------
587     zoom_opaque - render a scaled gfx
588     element with no transparency
589 -------------------------------------------------*/
590 
zoom_opaque(bitmap_ind16 & dest,const rectangle & cliprect,u32 code,u32 color,int flipx,int flipy,s32 destx,s32 desty,u32 scalex,u32 scaley)591 void gfx_element::zoom_opaque(bitmap_ind16 &dest, const rectangle &cliprect,
592 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
593 		u32 scalex, u32 scaley)
594 {
595 	// non-zoom case
596 	if (scalex == 0x10000 && scaley == 0x10000)
597 		return opaque(dest, cliprect, code, color, flipx, flipy, destx, desty);
598 
599 	// render
600 	color = colorbase() + granularity() * (color % colors());
601 	code %= elements();
602 	drawgfxzoom_core(dest, cliprect, code, flipx, flipy, destx, desty, scalex, scaley, [color](u16 &destp, const u8 &srcp) { PIXEL_OP_REBASE_OPAQUE(destp, srcp); });
603 }
604 
zoom_opaque(bitmap_rgb32 & dest,const rectangle & cliprect,u32 code,u32 color,int flipx,int flipy,s32 destx,s32 desty,u32 scalex,u32 scaley)605 void gfx_element::zoom_opaque(bitmap_rgb32 &dest, const rectangle &cliprect,
606 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
607 		u32 scalex, u32 scaley)
608 {
609 	// non-zoom case
610 	if (scalex == 0x10000 && scaley == 0x10000)
611 		return opaque(dest, cliprect, code, color, flipx, flipy, destx, desty);
612 
613 	// render
614 	const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
615 	code %= elements();
616 	drawgfxzoom_core(dest, cliprect, code, flipx, flipy, destx, desty, scalex, scaley, [paldata](u32 &destp, const u8 &srcp) { PIXEL_OP_REMAP_OPAQUE(destp, srcp); });
617 }
618 
619 
620 /*-------------------------------------------------
621     zoom_transpen - render a scaled gfx
622     element with a single transparent pen
623 -------------------------------------------------*/
624 
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)625 void gfx_element::zoom_transpen(bitmap_ind16 &dest, const rectangle &cliprect,
626 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
627 		u32 scalex, u32 scaley, u32 trans_pen)
628 {
629 	// non-zoom case
630 	if (scalex == 0x10000 && scaley == 0x10000)
631 		return transpen(dest, cliprect, code, color, flipx, flipy, destx, desty, trans_pen);
632 
633 	// special case invalid pens to opaque
634 	if (trans_pen > 0xff)
635 		return zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley);
636 
637 	// use pen usage to optimize
638 	code %= elements();
639 	if (has_pen_usage())
640 	{
641 		// fully transparent; do nothing
642 		u32 usage = pen_usage(code);
643 		if ((usage & ~(1 << trans_pen)) == 0)
644 			return;
645 
646 		// fully opaque; draw as such
647 		if ((usage & (1 << trans_pen)) == 0)
648 			return zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley);
649 	}
650 
651 	// render
652 	color = colorbase() + granularity() * (color % colors());
653 	drawgfxzoom_core(dest, cliprect, code, flipx, flipy, destx, desty, scalex, scaley, [trans_pen, color](u16 &destp, const u8 &srcp) { PIXEL_OP_REBASE_TRANSPEN(destp, srcp); });
654 }
655 
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)656 void gfx_element::zoom_transpen(bitmap_rgb32 &dest, const rectangle &cliprect,
657 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
658 		u32 scalex, u32 scaley, u32 trans_pen)
659 {
660 	// non-zoom case
661 	if (scalex == 0x10000 && scaley == 0x10000)
662 		return transpen(dest, cliprect, code, color, flipx, flipy, destx, desty, trans_pen);
663 
664 	// special case invalid pens to opaque
665 	if (trans_pen > 0xff)
666 		return zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley);
667 
668 	// use pen usage to optimize
669 	code %= elements();
670 	if (has_pen_usage())
671 	{
672 		// fully transparent; do nothing
673 		u32 usage = pen_usage(code);
674 		if ((usage & ~(1 << trans_pen)) == 0)
675 			return;
676 
677 		// fully opaque; draw as such
678 		if ((usage & (1 << trans_pen)) == 0)
679 			return zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley);
680 	}
681 
682 	// render
683 	const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
684 	drawgfxzoom_core(dest, cliprect, code, flipx, flipy, destx, desty, scalex, scaley, [trans_pen, paldata](u32 &destp, const u8 &srcp) { PIXEL_OP_REMAP_TRANSPEN(destp, srcp); });
685 }
686 
687 
688 /*-------------------------------------------------
689     zoom_transpen_raw - render a scaled gfx
690     element with a single transparent pen and no
691     color lookups
692 -------------------------------------------------*/
693 
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)694 void gfx_element::zoom_transpen_raw(bitmap_ind16 &dest, const rectangle &cliprect,
695 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
696 		u32 scalex, u32 scaley, u32 trans_pen)
697 {
698 	// non-zoom case
699 	if (scalex == 0x10000 && scaley == 0x10000)
700 		return transpen_raw(dest, cliprect, code, color, flipx, flipy, destx, desty, trans_pen);
701 
702 	// early out if completely transparent
703 	code %= elements();
704 	if (has_pen_usage() && (pen_usage(code) & ~(1 << trans_pen)) == 0)
705 		return;
706 
707 	// render
708 	drawgfxzoom_core(dest, cliprect, code, flipx, flipy, destx, desty, scalex, scaley, [trans_pen, color](u16 &destp, const u8 &srcp) { PIXEL_OP_REBASE_TRANSPEN(destp, srcp); });
709 }
710 
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)711 void gfx_element::zoom_transpen_raw(bitmap_rgb32 &dest, const rectangle &cliprect,
712 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
713 		u32 scalex, u32 scaley, u32 trans_pen)
714 {
715 	// non-zoom case
716 	if (scalex == 0x10000 && scaley == 0x10000)
717 		return transpen_raw(dest, cliprect, code, color, flipx, flipy, destx, desty, trans_pen);
718 
719 	// early out if completely transparent
720 	code %= elements();
721 	if (has_pen_usage() && (pen_usage(code) & ~(1 << trans_pen)) == 0)
722 		return;
723 
724 	// render
725 	drawgfxzoom_core(dest, cliprect, code, flipx, flipy, destx, desty, scalex, scaley, [trans_pen, color](u32 &destp, const u8 &srcp) { PIXEL_OP_REBASE_TRANSPEN(destp, srcp); });
726 }
727 
728 
729 /*-------------------------------------------------
730     zoom_transmask - render a scaled gfx
731     element with a multiple transparent pens
732     provided as a mask
733 -------------------------------------------------*/
734 
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)735 void gfx_element::zoom_transmask(bitmap_ind16 &dest, const rectangle &cliprect,
736 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
737 		u32 scalex, u32 scaley, u32 trans_mask)
738 {
739 	// non-zoom case
740 	if (scalex == 0x10000 && scaley == 0x10000)
741 		return transmask(dest, cliprect, code, color, flipx, flipy, destx, desty, trans_mask);
742 
743 	// special case 0 mask to opaque
744 	if (trans_mask == 0)
745 		return zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley);
746 
747 	// use pen usage to optimize
748 	code %= elements();
749 	if (has_pen_usage())
750 	{
751 		// fully transparent; do nothing
752 		u32 usage = pen_usage(code);
753 		if ((usage & ~trans_mask) == 0)
754 			return;
755 
756 		// fully opaque; draw as such
757 		if ((usage & trans_mask) == 0)
758 			return zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley);
759 	}
760 
761 	// render
762 	color = colorbase() + granularity() * (color % colors());
763 	drawgfxzoom_core(dest, cliprect, code, flipx, flipy, destx, desty, scalex, scaley, [trans_mask, color](u16 &destp, const u8 &srcp) { PIXEL_OP_REBASE_TRANSMASK(destp, srcp); });
764 }
765 
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)766 void gfx_element::zoom_transmask(bitmap_rgb32 &dest, const rectangle &cliprect,
767 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
768 		u32 scalex, u32 scaley, u32 trans_mask)
769 {
770 	// non-zoom case
771 	if (scalex == 0x10000 && scaley == 0x10000)
772 		return transmask(dest, cliprect, code, color, flipx, flipy, destx, desty, trans_mask);
773 
774 	// special case 0 mask to opaque
775 	if (trans_mask == 0)
776 		return zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley);
777 
778 	// use pen usage to optimize
779 	code %= elements();
780 	if (has_pen_usage())
781 	{
782 		// fully transparent; do nothing
783 		u32 usage = pen_usage(code);
784 		if ((usage & ~trans_mask) == 0)
785 			return;
786 
787 		// fully opaque; draw as such
788 		if ((usage & trans_mask) == 0)
789 			return zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley);
790 	}
791 
792 	// render
793 	const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
794 	drawgfxzoom_core(dest, cliprect, code, flipx, flipy, destx, desty, scalex, scaley, [trans_mask, paldata](u32 &destp, const u8 &srcp) { PIXEL_OP_REMAP_TRANSMASK(destp, srcp); });
795 }
796 
797 
798 /*-------------------------------------------------
799     zoom_transtable - render a scaled gfx
800     element using a table to look up which pens
801     are transparent, opaque, or shadowing
802 -------------------------------------------------*/
803 
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)804 void gfx_element::zoom_transtable(bitmap_ind16 &dest, const rectangle &cliprect,
805 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
806 		u32 scalex, u32 scaley, const u8 *pentable)
807 {
808 	assert(pentable != nullptr);
809 
810 	// non-zoom case
811 	if (scalex == 0x10000 && scaley == 0x10000)
812 		return transtable(dest, cliprect, code, color, flipx, flipy, destx, desty, pentable);
813 
814 	// render
815 	color = colorbase() + granularity() * (color % colors());
816 	const pen_t *shadowtable = m_palette->shadow_table();
817 	code %= elements();
818 	drawgfxzoom_core(dest, cliprect, code, flipx, flipy, destx, desty, scalex, scaley, [pentable, color, shadowtable](u16 &destp, const u8 &srcp) { PIXEL_OP_REBASE_TRANSTABLE16(destp, srcp); });
819 }
820 
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)821 void gfx_element::zoom_transtable(bitmap_rgb32 &dest, const rectangle &cliprect,
822 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
823 		u32 scalex, u32 scaley, const u8 *pentable)
824 {
825 	assert(pentable != nullptr);
826 
827 	// non-zoom case
828 	if (scalex == 0x10000 && scaley == 0x10000)
829 		return transtable(dest, cliprect, code, color, flipx, flipy, destx, desty, pentable);
830 
831 	// render
832 	const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
833 	const pen_t *shadowtable = m_palette->shadow_table();
834 	code %= elements();
835 	drawgfxzoom_core(dest, cliprect, code, flipx, flipy, destx, desty, scalex, scaley, [pentable, paldata, shadowtable](u32 &destp, const u8 &srcp) { PIXEL_OP_REMAP_TRANSTABLE32(destp, srcp); });
836 }
837 
838 
839 /*-------------------------------------------------
840     zoom_alpha - render a scaled gfx element
841     with a single transparent pen, alpha blending
842     the remaining pixels with a fixed alpha value
843 -------------------------------------------------*/
844 
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)845 void gfx_element::zoom_alpha(bitmap_rgb32 &dest, const rectangle &cliprect,
846 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
847 		u32 scalex, u32 scaley, u32 trans_pen, u8 alpha_val)
848 {
849 	// non-zoom case
850 	if (scalex == 0x10000 && scaley == 0x10000)
851 		return alpha(dest, cliprect, code, color, flipx, flipy, destx, desty, trans_pen, alpha_val);
852 
853 	// special case alpha_val = 0xff
854 	if (alpha_val == 0xff)
855 		return zoom_transpen(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley, trans_pen);
856 
857 	// early out if completely transparent
858 	code %= elements();
859 	if (has_pen_usage() && (pen_usage(code) & ~(1 << trans_pen)) == 0)
860 		return;
861 
862 	// render
863 	const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
864 	drawgfxzoom_core(dest, cliprect, code, flipx, flipy, destx, desty, scalex, scaley, [trans_pen, alpha_val, paldata](u32 &destp, const u8 &srcp) { PIXEL_OP_REMAP_TRANSPEN_ALPHA32(destp, srcp); });
865 }
866 
867 
868 
869 /***************************************************************************
870     PDRAWGFX IMPLEMENTATIONS
871 ***************************************************************************/
872 
873 /*-------------------------------------------------
874     prio_opaque - render a gfx element with
875     no transparency, checking against the priority
876     bitmap
877 -------------------------------------------------*/
878 
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)879 void gfx_element::prio_opaque(bitmap_ind16 &dest, const rectangle &cliprect,
880 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
881 		bitmap_ind8 &priority, u32 pmask)
882 {
883 	// high bit of the mask is implicitly on
884 	pmask |= 1 << 31;
885 
886 	// render
887 	color = colorbase() + granularity() * (color % colors());
888 	code %= elements();
889 	drawgfx_core(dest, cliprect, code, flipx, flipy, destx, desty, priority, [pmask, color](u16 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_REBASE_OPAQUE_PRIORITY(destp, pri, srcp); });
890 }
891 
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)892 void gfx_element::prio_opaque(bitmap_rgb32 &dest, const rectangle &cliprect,
893 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
894 		bitmap_ind8 &priority, u32 pmask)
895 {
896 	// high bit of the mask is implicitly on
897 	pmask |= 1 << 31;
898 
899 	// render
900 	const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
901 	code %= elements();
902 	drawgfx_core(dest, cliprect, code, flipx, flipy, destx, desty, priority, [pmask, paldata](u32 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_REMAP_OPAQUE_PRIORITY(destp, pri, srcp); });
903 }
904 
905 
906 /*-------------------------------------------------
907     prio_transpen - render a gfx element with
908     a single transparent pen, checking against the
909     priority bitmap
910 -------------------------------------------------*/
911 
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)912 void gfx_element::prio_transpen(bitmap_ind16 &dest, const rectangle &cliprect,
913 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
914 		bitmap_ind8 &priority, u32 pmask, u32 trans_pen)
915 {
916 	// special case invalid pens to opaque
917 	if (trans_pen > 0xff)
918 		return prio_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask);
919 
920 	// use pen usage to optimize
921 	code %= elements();
922 	if (has_pen_usage())
923 	{
924 		// fully transparent; do nothing
925 		u32 usage = pen_usage(code);
926 		if ((usage & ~(1 << trans_pen)) == 0)
927 			return;
928 
929 		// fully opaque; draw as such
930 		if ((usage & (1 << trans_pen)) == 0)
931 			return prio_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask);
932 	}
933 
934 	// high bit of the mask is implicitly on
935 	pmask |= 1 << 31;
936 
937 	// render
938 	color = colorbase() + granularity() * (color % colors());
939 	drawgfx_core(dest, cliprect, code, flipx, flipy, destx, desty, priority, [pmask, trans_pen, color](u16 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_REBASE_TRANSPEN_PRIORITY(destp, pri, srcp); });
940 }
941 
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)942 void gfx_element::prio_transpen(bitmap_rgb32 &dest, const rectangle &cliprect,
943 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
944 		bitmap_ind8 &priority, u32 pmask, u32 trans_pen)
945 {
946 	// special case invalid pens to opaque
947 	if (trans_pen > 0xff)
948 		return prio_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask);
949 
950 	// use pen usage to optimize
951 	code %= elements();
952 	if (has_pen_usage())
953 	{
954 		// fully transparent; do nothing
955 		u32 usage = pen_usage(code);
956 		if ((usage & ~(1 << trans_pen)) == 0)
957 			return;
958 
959 		// fully opaque; draw as such
960 		if ((usage & (1 << trans_pen)) == 0)
961 			return prio_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask);
962 	}
963 
964 	// high bit of the mask is implicitly on
965 	pmask |= 1 << 31;
966 
967 	// render
968 	const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
969 	drawgfx_core(dest, cliprect, code, flipx, flipy, destx, desty, priority, [pmask, trans_pen, paldata](u32 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_REMAP_TRANSPEN_PRIORITY(destp, pri, srcp); });
970 }
971 
972 
973 /*-------------------------------------------------
974     priotranspen_raw - render a gfx element
975     with a single transparent pen and no color
976     lookups, checking against the priority bitmap
977 -------------------------------------------------*/
978 
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)979 void gfx_element::prio_transpen_raw(bitmap_ind16 &dest, const rectangle &cliprect,
980 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
981 		bitmap_ind8 &priority, u32 pmask, u32 trans_pen)
982 {
983 	// early out if completely transparent
984 	code %= elements();
985 	if (has_pen_usage() && (pen_usage(code) & ~(1 << trans_pen)) == 0)
986 		return;
987 
988 	// high bit of the mask is implicitly on
989 	pmask |= 1 << 31;
990 
991 	// render
992 	drawgfx_core(dest, cliprect, code, flipx, flipy, destx, desty, priority, [pmask, trans_pen, color](u16 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_REBASE_TRANSPEN_PRIORITY(destp, pri, srcp); });
993 }
994 
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)995 void gfx_element::prio_transpen_raw(bitmap_rgb32 &dest, const rectangle &cliprect,
996 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
997 		bitmap_ind8 &priority, u32 pmask, u32 trans_pen)
998 {
999 	// early out if completely transparent
1000 	code %= elements();
1001 	if (has_pen_usage() && (pen_usage(code) & ~(1 << trans_pen)) == 0)
1002 		return;
1003 
1004 	// high bit of the mask is implicitly on
1005 	pmask |= 1 << 31;
1006 
1007 	// render
1008 	drawgfx_core(dest, cliprect, code, flipx, flipy, destx, desty, priority, [pmask, trans_pen, color](u32 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_REBASE_TRANSPEN_PRIORITY(destp, pri, srcp); });
1009 }
1010 
1011 
1012 /*-------------------------------------------------
1013     prio_transmask - render a gfx element
1014     with a multiple transparent pens provided as
1015     a mask, checking against the priority bitmap
1016 -------------------------------------------------*/
1017 
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)1018 void gfx_element::prio_transmask(bitmap_ind16 &dest, const rectangle &cliprect,
1019 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
1020 		bitmap_ind8 &priority, u32 pmask, u32 trans_mask)
1021 {
1022 	// special case 0 mask to opaque
1023 	if (trans_mask == 0)
1024 		return prio_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask);
1025 
1026 	// use pen usage to optimize
1027 	code %= elements();
1028 	if (has_pen_usage())
1029 	{
1030 		// fully transparent; do nothing
1031 		u32 usage = pen_usage(code);
1032 		if ((usage & ~trans_mask) == 0)
1033 			return;
1034 
1035 		// fully opaque; draw as such
1036 		if ((usage & trans_mask) == 0)
1037 			return prio_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask);
1038 	}
1039 
1040 	// high bit of the mask is implicitly on
1041 	pmask |= 1 << 31;
1042 
1043 	// render
1044 	color = colorbase() + granularity() * (color % colors());
1045 	drawgfx_core(dest, cliprect, code, flipx, flipy, destx, desty, priority, [pmask, trans_mask, color](u16 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_REBASE_TRANSMASK_PRIORITY(destp, pri, srcp); });
1046 }
1047 
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)1048 void gfx_element::prio_transmask(bitmap_rgb32 &dest, const rectangle &cliprect,
1049 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
1050 		bitmap_ind8 &priority, u32 pmask, u32 trans_mask)
1051 {
1052 	// special case 0 mask to opaque
1053 	if (trans_mask == 0)
1054 		return prio_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask);
1055 
1056 	// use pen usage to optimize
1057 	code %= elements();
1058 	if (has_pen_usage())
1059 	{
1060 		// fully transparent; do nothing
1061 		u32 usage = pen_usage(code);
1062 		if ((usage & ~trans_mask) == 0)
1063 			return;
1064 
1065 		// fully opaque; draw as such
1066 		if ((usage & trans_mask) == 0)
1067 			return prio_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask);
1068 	}
1069 
1070 	// high bit of the mask is implicitly on
1071 	pmask |= 1 << 31;
1072 
1073 	// render
1074 	const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
1075 	drawgfx_core(dest, cliprect, code, flipx, flipy, destx, desty, priority, [pmask, trans_mask, paldata](u32 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_REMAP_TRANSMASK_PRIORITY(destp, pri, srcp); });
1076 }
1077 
1078 
1079 /*-------------------------------------------------
1080     prio_transtable - render a gfx element
1081     using a table to look up which pens are
1082     transparent, opaque, or shadowing, checking
1083     against the priority bitmap
1084 -------------------------------------------------*/
1085 
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)1086 void gfx_element::prio_transtable(bitmap_ind16 &dest, const rectangle &cliprect,
1087 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
1088 		bitmap_ind8 &priority, u32 pmask, const u8 *pentable)
1089 {
1090 	assert(pentable != nullptr);
1091 
1092 	// high bit of the mask is implicitly on
1093 	pmask |= 1 << 31;
1094 
1095 	// render
1096 	color = colorbase() + granularity() * (color % colors());
1097 	const pen_t *shadowtable = m_palette->shadow_table();
1098 	code %= elements();
1099 	drawgfx_core(dest, cliprect, code, flipx, flipy, destx, desty, priority, [pmask, pentable, color, shadowtable](u16 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_REBASE_TRANSTABLE16_PRIORITY(destp, pri, srcp); });
1100 }
1101 
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)1102 void gfx_element::prio_transtable(bitmap_rgb32 &dest, const rectangle &cliprect,
1103 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
1104 		bitmap_ind8 &priority, u32 pmask, const u8 *pentable)
1105 {
1106 	assert(pentable != nullptr);
1107 
1108 	// high bit of the mask is implicitly on
1109 	pmask |= 1 << 31;
1110 
1111 	// render
1112 	const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
1113 	const pen_t *shadowtable = m_palette->shadow_table();
1114 	code %= elements();
1115 	drawgfx_core(dest, cliprect, code, flipx, flipy, destx, desty, priority, [pmask, pentable, paldata, shadowtable](u32 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_REMAP_TRANSTABLE32_PRIORITY(destp, pri, srcp); });
1116 }
1117 
1118 
1119 /*-------------------------------------------------
1120     prio_alpha - render a gfx element with
1121     a single transparent pen, alpha blending the
1122     remaining pixels with a fixed alpha value,
1123     checking against the priority bitmap
1124 -------------------------------------------------*/
1125 
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)1126 void gfx_element::prio_alpha(bitmap_rgb32 &dest, const rectangle &cliprect,
1127 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
1128 		bitmap_ind8 &priority, u32 pmask, u32 trans_pen, u8 alpha_val)
1129 {
1130 	// special case alpha = 0xff
1131 	if (alpha_val == 0xff)
1132 		return prio_transpen(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask, trans_pen);
1133 
1134 	// early out if completely transparent
1135 	code %= elements();
1136 	if (has_pen_usage() && (pen_usage(code) & ~(1 << trans_pen)) == 0)
1137 		return;
1138 
1139 	// high bit of the mask is implicitly on
1140 	pmask |= 1 << 31;
1141 
1142 	// render
1143 	const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
1144 	drawgfx_core(dest, cliprect, code, flipx, flipy, destx, desty, priority, [pmask, trans_pen, alpha_val, paldata](u32 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_REMAP_TRANSPEN_ALPHA32_PRIORITY(destp, pri, srcp); });
1145 }
1146 
1147 
1148 
1149 /***************************************************************************
1150     PDRAWGFXZOOM IMPLEMENTATIONS
1151 ***************************************************************************/
1152 
1153 /*-------------------------------------------------
1154     prio_zoom_opaque - render a scaled gfx
1155     element with no transparency, checking against
1156     the priority bitmap
1157 -------------------------------------------------*/
1158 
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)1159 void gfx_element::prio_zoom_opaque(bitmap_ind16 &dest, const rectangle &cliprect,
1160 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
1161 		u32 scalex, u32 scaley, bitmap_ind8 &priority, u32 pmask)
1162 {
1163 	// non-zoom case
1164 	if (scalex == 0x10000 && scaley == 0x10000)
1165 		return prio_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask);
1166 
1167 	// high bit of the mask is implicitly on
1168 	pmask |= 1 << 31;
1169 
1170 	// render
1171 	color = colorbase() + granularity() * (color % colors());
1172 	code %= elements();
1173 	drawgfxzoom_core(dest, cliprect, code, flipx, flipy, destx, desty, scalex, scaley, priority, [pmask, color](u16 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_REBASE_OPAQUE_PRIORITY(destp, pri, srcp); });
1174 }
1175 
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)1176 void gfx_element::prio_zoom_opaque(bitmap_rgb32 &dest, const rectangle &cliprect,
1177 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
1178 		u32 scalex, u32 scaley, bitmap_ind8 &priority, u32 pmask)
1179 {
1180 	// non-zoom case
1181 	if (scalex == 0x10000 && scaley == 0x10000)
1182 		return prio_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask);
1183 
1184 	// high bit of the mask is implicitly on
1185 	pmask |= 1 << 31;
1186 
1187 	// render
1188 	const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
1189 	code %= elements();
1190 	drawgfxzoom_core(dest, cliprect, code, flipx, flipy, destx, desty, scalex, scaley, priority, [pmask, paldata](u32 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_REMAP_OPAQUE_PRIORITY(destp, pri, srcp); });
1191 }
1192 
1193 
1194 /*-------------------------------------------------
1195     prio_zoom_transpen - render a scaled gfx
1196     element with a single transparent pen,
1197     checking against the priority bitmap
1198 -------------------------------------------------*/
1199 
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)1200 void gfx_element::prio_zoom_transpen(bitmap_ind16 &dest, const rectangle &cliprect,
1201 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
1202 		u32 scalex, u32 scaley, bitmap_ind8 &priority, u32 pmask,
1203 		u32 trans_pen)
1204 {
1205 	// non-zoom case
1206 	if (scalex == 0x10000 && scaley == 0x10000)
1207 		return prio_transpen(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask, trans_pen);
1208 
1209 	// special case invalid pens to opaque
1210 	if (trans_pen > 0xff)
1211 		return prio_zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley, priority, pmask);
1212 
1213 	// use pen usage to optimize
1214 	code %= elements();
1215 	if (has_pen_usage())
1216 	{
1217 		// fully transparent; do nothing
1218 		u32 usage = pen_usage(code);
1219 		if ((usage & ~(1 << trans_pen)) == 0)
1220 			return;
1221 
1222 		// fully opaque; draw as such
1223 		if ((usage & (1 << trans_pen)) == 0)
1224 			return prio_zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley, priority, pmask);
1225 	}
1226 
1227 	// high bit of the mask is implicitly on
1228 	pmask |= 1 << 31;
1229 
1230 	// render
1231 	color = colorbase() + granularity() * (color % colors());
1232 	drawgfxzoom_core(dest, cliprect, code, flipx, flipy, destx, desty, scalex, scaley, priority, [pmask, trans_pen, color](u16 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_REBASE_TRANSPEN_PRIORITY(destp, pri, srcp); });
1233 }
1234 
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)1235 void gfx_element::prio_zoom_transpen(bitmap_rgb32 &dest, const rectangle &cliprect,
1236 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
1237 		u32 scalex, u32 scaley, bitmap_ind8 &priority, u32 pmask,
1238 		u32 trans_pen)
1239 {
1240 	// non-zoom case
1241 	if (scalex == 0x10000 && scaley == 0x10000)
1242 		return prio_transpen(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask, trans_pen);
1243 
1244 	// special case invalid pens to opaque
1245 	if (trans_pen > 0xff)
1246 		return prio_zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley, priority, pmask);
1247 
1248 	// use pen usage to optimize
1249 	code %= elements();
1250 	if (has_pen_usage())
1251 	{
1252 		// fully transparent; do nothing
1253 		u32 usage = pen_usage(code);
1254 		if ((usage & ~(1 << trans_pen)) == 0)
1255 			return;
1256 
1257 		// fully opaque; draw as such
1258 		if ((usage & (1 << trans_pen)) == 0)
1259 			return prio_zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley, priority, pmask);
1260 	}
1261 
1262 	// high bit of the mask is implicitly on
1263 	pmask |= 1 << 31;
1264 
1265 	// render
1266 	const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
1267 	drawgfxzoom_core(dest, cliprect, code, flipx, flipy, destx, desty, scalex, scaley, priority, [pmask, trans_pen, paldata](u32 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_REMAP_TRANSPEN_PRIORITY(destp, pri, srcp); });
1268 }
1269 
1270 
1271 /*-------------------------------------------------
1272     prio_zoom_transpen_raw - render a scaled gfx
1273     element with a single transparent pen and no
1274     color lookups, checking against the priority
1275     bitmap
1276 -------------------------------------------------*/
1277 
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)1278 void gfx_element::prio_zoom_transpen_raw(bitmap_ind16 &dest, const rectangle &cliprect,
1279 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
1280 		u32 scalex, u32 scaley, bitmap_ind8 &priority, u32 pmask,
1281 		u32 trans_pen)
1282 {
1283 	// non-zoom case
1284 	if (scalex == 0x10000 && scaley == 0x10000)
1285 		return prio_transpen_raw(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask, trans_pen);
1286 
1287 	// early out if completely transparent
1288 	code %= elements();
1289 	if (has_pen_usage() && (pen_usage(code) & ~(1 << trans_pen)) == 0)
1290 		return;
1291 
1292 	// high bit of the mask is implicitly on
1293 	pmask |= 1 << 31;
1294 
1295 	// render
1296 	drawgfxzoom_core(dest, cliprect, code, flipx, flipy, destx, desty, scalex, scaley, priority, [pmask, trans_pen, color](u16 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_REBASE_TRANSPEN_PRIORITY(destp, pri, srcp); });
1297 }
1298 
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)1299 void gfx_element::prio_zoom_transpen_raw(bitmap_rgb32 &dest, const rectangle &cliprect,
1300 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
1301 		u32 scalex, u32 scaley, bitmap_ind8 &priority, u32 pmask,
1302 		u32 trans_pen)
1303 {
1304 	// non-zoom case
1305 	if (scalex == 0x10000 && scaley == 0x10000)
1306 		return prio_transpen_raw(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask, trans_pen);
1307 
1308 	// early out if completely transparent
1309 	code %= elements();
1310 	if (has_pen_usage() && (pen_usage(code) & ~(1 << trans_pen)) == 0)
1311 		return;
1312 
1313 	// high bit of the mask is implicitly on
1314 	pmask |= 1 << 31;
1315 
1316 	// render
1317 	drawgfxzoom_core(dest, cliprect, code, flipx, flipy, destx, desty, scalex, scaley, priority, [pmask, trans_pen, color](u32 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_REBASE_TRANSPEN_PRIORITY(destp, pri, srcp); });
1318 }
1319 
1320 
1321 /*-------------------------------------------------
1322     prio_zoom_transmask - render a scaled gfx
1323     element with a multiple transparent pens
1324     provided as a mask, checking against the
1325     priority bitmap
1326 -------------------------------------------------*/
1327 
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)1328 void gfx_element::prio_zoom_transmask(bitmap_ind16 &dest, const rectangle &cliprect,
1329 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
1330 		u32 scalex, u32 scaley, bitmap_ind8 &priority, u32 pmask,
1331 		u32 trans_mask)
1332 {
1333 	// non-zoom case
1334 	if (scalex == 0x10000 && scaley == 0x10000)
1335 		return prio_transmask(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask, trans_mask);
1336 
1337 	// special case 0 mask to opaque
1338 	if (trans_mask == 0)
1339 		return prio_zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley, priority, pmask);
1340 
1341 	// use pen usage to optimize
1342 	code %= elements();
1343 	if (has_pen_usage())
1344 	{
1345 		// fully transparent; do nothing
1346 		u32 usage = pen_usage(code);
1347 		if ((usage & ~trans_mask) == 0)
1348 			return;
1349 
1350 		// fully opaque; draw as such
1351 		if ((usage & trans_mask) == 0)
1352 			return prio_zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley, priority, pmask);
1353 	}
1354 
1355 	// high bit of the mask is implicitly on
1356 	pmask |= 1 << 31;
1357 
1358 	// render
1359 	color = colorbase() + granularity() * (color % colors());
1360 	drawgfxzoom_core(dest, cliprect, code, flipx, flipy, destx, desty, scalex, scaley, priority, [pmask, trans_mask, color](u16 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_REBASE_TRANSMASK_PRIORITY(destp, pri, srcp); });
1361 }
1362 
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)1363 void gfx_element::prio_zoom_transmask(bitmap_rgb32 &dest, const rectangle &cliprect,
1364 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
1365 		u32 scalex, u32 scaley, bitmap_ind8 &priority, u32 pmask,
1366 		u32 trans_mask)
1367 {
1368 	// non-zoom case
1369 	if (scalex == 0x10000 && scaley == 0x10000)
1370 		return prio_transmask(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask, trans_mask);
1371 
1372 	// special case 0 mask to opaque
1373 	if (trans_mask == 0)
1374 		return prio_zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley, priority, pmask);
1375 
1376 	// use pen usage to optimize
1377 	code %= elements();
1378 	if (has_pen_usage())
1379 	{
1380 		// fully transparent; do nothing
1381 		u32 usage = pen_usage(code);
1382 		if ((usage & ~trans_mask) == 0)
1383 			return;
1384 
1385 		// fully opaque; draw as such
1386 		if ((usage & trans_mask) == 0)
1387 			return prio_zoom_opaque(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley, priority, pmask);
1388 	}
1389 
1390 	// high bit of the mask is implicitly on
1391 	pmask |= 1 << 31;
1392 
1393 	// render
1394 	const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
1395 	drawgfxzoom_core(dest, cliprect, code, flipx, flipy, destx, desty, scalex, scaley, priority, [pmask, trans_mask, paldata](u32 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_REMAP_TRANSMASK_PRIORITY(destp, pri, srcp); });
1396 }
1397 
1398 
1399 /*-------------------------------------------------
1400     prio_zoom_transtable - render a scaled gfx
1401     element using a table to look up which pens
1402     are transparent, opaque, or shadowing,
1403     checking against the priority bitmap
1404 -------------------------------------------------*/
1405 
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)1406 void gfx_element::prio_zoom_transtable(bitmap_ind16 &dest, const rectangle &cliprect,
1407 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
1408 		u32 scalex, u32 scaley, bitmap_ind8 &priority, u32 pmask,
1409 		const u8 *pentable)
1410 {
1411 	assert(pentable != nullptr);
1412 
1413 	// non-zoom case
1414 	if (scalex == 0x10000 && scaley == 0x10000)
1415 		return prio_transtable(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask, pentable);
1416 
1417 	// high bit of the mask is implicitly on
1418 	pmask |= 1 << 31;
1419 
1420 	// render
1421 	color = colorbase() + granularity() * (color % colors());
1422 	const pen_t *shadowtable = m_palette->shadow_table();
1423 	code %= elements();
1424 	drawgfxzoom_core(dest, cliprect, code, flipx, flipy, destx, desty, scalex, scaley, priority, [pmask, pentable, color, shadowtable](u16 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_REBASE_TRANSTABLE16_PRIORITY(destp, pri, srcp); });
1425 }
1426 
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)1427 void gfx_element::prio_zoom_transtable(bitmap_rgb32 &dest, const rectangle &cliprect,
1428 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
1429 		u32 scalex, u32 scaley, bitmap_ind8 &priority, u32 pmask,
1430 		const u8 *pentable)
1431 {
1432 	assert(pentable != nullptr);
1433 
1434 	// non-zoom case
1435 	if (scalex == 0x10000 && scaley == 0x10000)
1436 		return prio_transtable(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask, pentable);
1437 
1438 	// high bit of the mask is implicitly on
1439 	pmask |= 1 << 31;
1440 
1441 	// render
1442 	const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
1443 	const pen_t *shadowtable = m_palette->shadow_table();
1444 	code %= elements();
1445 	drawgfxzoom_core(dest, cliprect, code, flipx, flipy, destx, desty, scalex, scaley, priority, [pmask, pentable, paldata, shadowtable](u32 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_REMAP_TRANSTABLE32_PRIORITY(destp, pri, srcp); });
1446 }
1447 
1448 
1449 /*-------------------------------------------------
1450     prio_zoom_alpha - render a scaled gfx
1451     element with a single transparent pen, alpha
1452     blending the remaining pixels with a fixed
1453     alpha value, checking against the priority
1454     bitmap
1455 -------------------------------------------------*/
1456 
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)1457 void gfx_element::prio_zoom_alpha(bitmap_rgb32 &dest, const rectangle &cliprect,
1458 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
1459 		u32 scalex, u32 scaley, bitmap_ind8 &priority, u32 pmask,
1460 		u32 trans_pen, u8 alpha_val)
1461 {
1462 	// non-zoom case
1463 	if (scalex == 0x10000 && scaley == 0x10000)
1464 		return prio_alpha(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask, trans_pen, alpha_val);
1465 
1466 	// special case alpha_val = 0xff
1467 	if (alpha_val == 0xff)
1468 		return prio_zoom_transpen(dest, cliprect, code, color, flipx, flipy, destx, desty, scalex, scaley, priority, pmask, trans_pen);
1469 
1470 	// early out if completely transparent
1471 	code %= elements();
1472 	if (has_pen_usage() && (pen_usage(code) & ~(1 << trans_pen)) == 0)
1473 		return;
1474 
1475 	// high bit of the mask is implicitly on
1476 	pmask |= 1 << 31;
1477 
1478 	// render
1479 	const pen_t *paldata = m_palette->pens() + colorbase() + granularity() * (color % colors());
1480 	drawgfxzoom_core(dest, cliprect, code, flipx, flipy, destx, desty, scalex, scaley, priority, [pmask, trans_pen, alpha_val, paldata](u32 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_REMAP_TRANSPEN_ALPHA32_PRIORITY(destp, pri, srcp); });
1481 }
1482 
1483 
1484 #define PIXEL_OP_REMAP_TRANSPEN_PRIORITY_ADDIIVE32(DEST, PRIORITY, SOURCE)          \
1485 do                                                                                  \
1486 {                                                                                   \
1487 	u32 srcdata = (SOURCE);                                                         \
1488 	if (srcdata != trans_pen)                                                       \
1489 	{                                                                               \
1490 		if (((1 << ((PRIORITY) & 0x1f)) & pmask) == 0)                              \
1491 			(DEST) = add_blend_r32((DEST), paldata[srcdata]);                       \
1492 		(PRIORITY) = 31;                                                            \
1493 	}                                                                               \
1494 }                                                                                   \
1495 while (0)
1496 
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)1497 void gfx_element::prio_transpen_additive(bitmap_rgb32 &dest, const rectangle &cliprect,
1498 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
1499 		bitmap_ind8 &priority, u32 pmask, u32 trans_pen)
1500 {
1501 	const pen_t *paldata;
1502 
1503 	assert(dest.valid());
1504 	assert(dest.bpp() == 32);
1505 
1506 	/* get final code and color, and grab lookup tables */
1507 	code %= elements();
1508 	color %= colors();
1509 	paldata = m_palette->pens() + colorbase() + granularity() * color;
1510 
1511 	/* use pen usage to optimize */
1512 	if (has_pen_usage())
1513 	{
1514 		u32 usage = pen_usage(code);
1515 
1516 		/* fully transparent; do nothing */
1517 		if ((usage & ~(1 << trans_pen)) == 0)
1518 			return;
1519 	}
1520 
1521 	/* high bit of the mask is implicitly on */
1522 	pmask |= 1 << 31;
1523 
1524 	/* render based on dest bitmap depth */
1525 	drawgfx_core(dest, cliprect, code, flipx, flipy, destx, desty, priority, [pmask, trans_pen, paldata](u32 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_REMAP_TRANSPEN_PRIORITY_ADDIIVE32(destp, pri, srcp); });
1526 }
1527 
1528 
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)1529 void gfx_element::prio_zoom_transpen_additive(bitmap_rgb32 &dest, const rectangle &cliprect,
1530 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
1531 		u32 scalex, u32 scaley, bitmap_ind8 &priority, u32 pmask,
1532 		u32 trans_pen)
1533 {
1534 	const pen_t *paldata;
1535 
1536 	/* non-zoom case */
1537 
1538 	if (scalex == 0x10000 && scaley == 0x10000)
1539 	{
1540 		prio_transpen_additive(dest, cliprect, code, color, flipx, flipy, destx, desty, priority, pmask, trans_pen);
1541 		return;
1542 	}
1543 
1544 	assert(dest.valid());
1545 	assert(dest.bpp() == 32);
1546 
1547 	/* get final code and color, and grab lookup tables */
1548 	code %= elements();
1549 	color %= colors();
1550 	paldata = m_palette->pens() + colorbase() + granularity() * color;
1551 
1552 	/* use pen usage to optimize */
1553 	if (has_pen_usage())
1554 	{
1555 		u32 usage = pen_usage(code);
1556 
1557 		/* fully transparent; do nothing */
1558 		if ((usage & ~(1 << trans_pen)) == 0)
1559 			return;
1560 	}
1561 
1562 	/* high bit of the mask is implicitly on */
1563 	pmask |= 1 << 31;
1564 
1565 	drawgfxzoom_core(dest, cliprect, code, flipx, flipy, destx, desty, scalex, scaley, priority, [pmask, trans_pen, paldata](u32 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_REMAP_TRANSPEN_PRIORITY_ADDIIVE32(destp, pri, srcp); });
1566 }
1567 
1568 //#define MAKE_ARGB_RGB(a, rgb) rgb_t(a, rgb.r(), rgb.g(), rgb.b())
1569 #define MAKE_ARGB_RGB(a, rgb)   rgb_t(rgb).set_a(a)
1570 
1571 // combine in 'alpha' when copying to store in ARGB
1572 #define PIXEL_OP_REMAP_TRANS0_ALPHASTORE32(DEST, SOURCE)                                  \
1573 do                                                                                                  \
1574 {                                                                                                   \
1575 	u32 srcdata = (SOURCE);                                                                         \
1576 	if (srcdata != 0)                                                                               \
1577 		(DEST) = MAKE_ARGB_RGB(alpha,paldata[srcdata]);                                             \
1578 }                                                                                                   \
1579 while (0)
1580 // combine in 'alphatable' value to store in ARGB
1581 #define PIXEL_OP_REMAP_TRANS0_ALPHATABLESTORE32(DEST, SOURCE)                             \
1582 do                                                                                                  \
1583 {                                                                                                   \
1584 	u32 srcdata = (SOURCE);                                                                         \
1585 	if (srcdata != 0)                                                                               \
1586 		(DEST) = MAKE_ARGB_RGB(alphatable[srcdata], paldata[srcdata]);                              \
1587 }                                                                                                   \
1588 while (0)
1589 // drawgfxm.h macro to render alpha into 32-bit buffer
1590 #define PIXEL_OP_REMAP_TRANS0_ALPHATABLE32(DEST, SOURCE)                                  \
1591 do                                                                                                  \
1592 {                                                                                                   \
1593 	u32 srcdata = (SOURCE);                                                                         \
1594 	if (srcdata != 0)                                                                               \
1595 		(DEST) = alpha_blend_r32((DEST), paldata[srcdata], alphatable[srcdata]);                    \
1596 }                                                                                                   \
1597 while (0)
1598 
1599 /*-------------------------------------------------
1600     alphastore - render a gfx element with
1601     a single transparent pen, storing the alpha value
1602     in alpha field of ARGB32, negative alpha implies alphatable
1603 -------------------------------------------------*/
alphastore(bitmap_rgb32 & dest,const rectangle & cliprect,u32 code,u32 color,int flipx,int flipy,s32 destx,s32 desty,int fixedalpha,u8 * alphatable)1604 void gfx_element::alphastore(bitmap_rgb32 &dest, const rectangle &cliprect,
1605 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
1606 		int fixedalpha, u8 *alphatable)
1607 {
1608 	const pen_t *paldata;
1609 
1610 	assert(alphatable != nullptr);
1611 
1612 	/* if we have a fixed alpha, call the standard drawgfx_transpen */
1613 	if (fixedalpha == 0xff)
1614 	{
1615 		transpen(dest, cliprect, code, color, flipx, flipy, destx, desty, 0);
1616 		return;
1617 	}
1618 
1619 	/* get final code and color, and grab lookup tables */
1620 	code %= elements();
1621 	color %= colors();
1622 	paldata = m_palette->pens() + colorbase() + granularity() * color;
1623 
1624 	/* early out if completely transparent */
1625 	if (has_pen_usage() && (pen_usage(code) & ~(1 << 0)) == 0)
1626 		return;
1627 
1628 	if (fixedalpha >= 0)
1629 		drawgfx_core(dest, cliprect, code, flipx, flipy, destx, desty, [paldata, alpha = fixedalpha](u32 &destp, const u8 &srcp) { PIXEL_OP_REMAP_TRANS0_ALPHASTORE32(destp, srcp); });
1630 	else
1631 		drawgfx_core(dest, cliprect, code, flipx, flipy, destx, desty, [paldata, alphatable](u32 &destp, const u8 &srcp) { PIXEL_OP_REMAP_TRANS0_ALPHATABLESTORE32(destp, srcp); });
1632 }
1633 
1634 /*-------------------------------------------------
1635     alphatable - render a sprite with either
1636     a fixed alpha value, or if alpha==-1 then uses
1637     the per-pen alphatable[] array
1638  -------------------------------------------------*/
alphatable(bitmap_rgb32 & dest,const rectangle & cliprect,u32 code,u32 color,int flipx,int flipy,s32 destx,s32 desty,int fixedalpha,u8 * alphatable)1639 void gfx_element::alphatable(bitmap_rgb32 &dest, const rectangle &cliprect,
1640 		u32 code, u32 color, int flipx, int flipy, s32 destx, s32 desty,
1641 		int fixedalpha, u8 *alphatable)
1642 {
1643 	const pen_t *paldata;
1644 
1645 	/* if we have a fixed alpha, call the standard drawgfx_alpha */
1646 	if (fixedalpha >= 0)
1647 	{
1648 		alpha(dest, cliprect, code, color, flipx, flipy, destx, desty, 0, fixedalpha);
1649 		return;
1650 	}
1651 
1652 	assert(dest.bpp() == 32);
1653 	assert(alphatable != nullptr);
1654 
1655 	/* get final code and color, and grab lookup tables */
1656 	code %= elements();
1657 	color %= colors();
1658 	paldata = m_palette->pens() + colorbase() + granularity() * color;
1659 
1660 	/* early out if completely transparent */
1661 	if (has_pen_usage() && (pen_usage(code) & ~(1 << 0)) == 0)
1662 		return;
1663 
1664 	drawgfx_core(dest, cliprect, code, flipx, flipy, destx, desty, [paldata, alphatable](u32 &destp, const u8 &srcp) { PIXEL_OP_REMAP_TRANS0_ALPHATABLE32(destp, srcp); });
1665 }
1666 
1667 
1668 /***************************************************************************
1669     DRAW_SCANLINE IMPLEMENTATIONS
1670 ***************************************************************************/
1671 
1672 /*-------------------------------------------------
1673     draw_scanline8 - copy pixels from an 8bpp
1674     buffer to a single scanline of a bitmap
1675 -------------------------------------------------*/
1676 
draw_scanline8(bitmap_ind16 & bitmap,s32 destx,s32 desty,s32 length,const u8 * srcptr,const pen_t * paldata)1677 void draw_scanline8(bitmap_ind16 &bitmap, s32 destx, s32 desty, s32 length, const u8 *srcptr, const pen_t *paldata)
1678 {
1679 	// palette lookup case
1680 	if (paldata != nullptr)
1681 		drawscanline_core(bitmap, destx, desty, length, srcptr, [paldata](u16 &destp, const u8 &srcp) { PIXEL_OP_REMAP_OPAQUE(destp, srcp); });
1682 
1683 	// raw copy case
1684 	else
1685 		drawscanline_core(bitmap, destx, desty, length, srcptr, [](u16 &destp, const u8 &srcp) { PIXEL_OP_COPY_OPAQUE(destp, srcp); });
1686 }
1687 
draw_scanline8(bitmap_rgb32 & bitmap,s32 destx,s32 desty,s32 length,const u8 * srcptr,const pen_t * paldata)1688 void draw_scanline8(bitmap_rgb32 &bitmap, s32 destx, s32 desty, s32 length, const u8 *srcptr, const pen_t *paldata)
1689 {
1690 	// palette lookup case
1691 	if (paldata != nullptr)
1692 		drawscanline_core(bitmap, destx, desty, length, srcptr, [paldata](u32 &destp, const u8 &srcp) { PIXEL_OP_REMAP_OPAQUE(destp, srcp); });
1693 
1694 	// raw copy case
1695 	else
1696 		drawscanline_core(bitmap, destx, desty, length, srcptr, [](u32 &destp, const u8 &srcp) { PIXEL_OP_COPY_OPAQUE(destp, srcp); });
1697 }
1698 
prio_draw_scanline8(bitmap_ind16 & bitmap,s32 destx,s32 desty,s32 length,const u8 * srcptr,const pen_t * paldata,bitmap_ind8 & priority,u32 pmask)1699 void prio_draw_scanline8(bitmap_ind16 &bitmap, s32 destx, s32 desty, s32 length, const u8 *srcptr, const pen_t *paldata, bitmap_ind8 &priority, u32 pmask)
1700 {
1701 	// high bit of the mask is implicitly on
1702 	pmask |= 1 << 31;
1703 
1704 	// palette lookup case
1705 	if (paldata != nullptr)
1706 		drawscanline_core(bitmap, destx, desty, length, srcptr, priority, [paldata, pmask](u16 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_REMAP_OPAQUE_PRIORITY(destp, pri, srcp); });
1707 
1708 	// raw copy case
1709 	else
1710 		drawscanline_core(bitmap, destx, desty, length, srcptr, priority, [pmask](u16 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_COPY_OPAQUE_PRIORITY(destp, pri, srcp); });
1711 }
1712 
prio_draw_scanline8(bitmap_rgb32 & bitmap,s32 destx,s32 desty,s32 length,const u8 * srcptr,const pen_t * paldata,bitmap_ind8 & priority,u32 pmask)1713 void prio_draw_scanline8(bitmap_rgb32 &bitmap, s32 destx, s32 desty, s32 length, const u8 *srcptr, const pen_t *paldata, bitmap_ind8 &priority, u32 pmask)
1714 {
1715 	// high bit of the mask is implicitly on
1716 	pmask |= 1 << 31;
1717 
1718 	// palette lookup case
1719 	if (paldata != nullptr)
1720 		drawscanline_core(bitmap, destx, desty, length, srcptr, priority, [paldata, pmask](u32 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_REMAP_OPAQUE_PRIORITY(destp, pri, srcp); });
1721 
1722 	// raw copy case
1723 	else
1724 		drawscanline_core(bitmap, destx, desty, length, srcptr, priority, [pmask](u32 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_COPY_OPAQUE_PRIORITY(destp, pri, srcp); });
1725 }
1726 
primask_draw_scanline8(bitmap_ind16 & bitmap,s32 destx,s32 desty,s32 length,const u8 * srcptr,const pen_t * paldata,bitmap_ind8 & priority,u8 pcode,u8 pmask)1727 void primask_draw_scanline8(bitmap_ind16 &bitmap, s32 destx, s32 desty, s32 length, const u8 *srcptr, const pen_t *paldata, bitmap_ind8 &priority, u8 pcode, u8 pmask)
1728 {
1729 	if (pcode == 0 && pmask == 0xff)
1730 		return draw_scanline8(bitmap, destx, desty, length, srcptr, paldata);
1731 
1732 	// palette lookup case
1733 	if (paldata != nullptr)
1734 		drawscanline_core(bitmap, destx, desty, length, srcptr, priority, [paldata, pcode, pmask](u16 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_REMAP_OPAQUE_PRIMASK(destp, pri, srcp); });
1735 
1736 	// raw copy case
1737 	else
1738 		drawscanline_core(bitmap, destx, desty, length, srcptr, priority, [pcode, pmask](u16 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_COPY_OPAQUE_PRIMASK(destp, pri, srcp); });
1739 }
1740 
primask_draw_scanline8(bitmap_rgb32 & bitmap,s32 destx,s32 desty,s32 length,const u8 * srcptr,const pen_t * paldata,bitmap_ind8 & priority,u8 pcode,u8 pmask)1741 void primask_draw_scanline8(bitmap_rgb32 &bitmap, s32 destx, s32 desty, s32 length, const u8 *srcptr, const pen_t *paldata, bitmap_ind8 &priority, u8 pcode, u8 pmask)
1742 {
1743 	if (pcode == 0 && pmask == 0xff)
1744 		return draw_scanline8(bitmap, destx, desty, length, srcptr, paldata);
1745 
1746 	// palette lookup case
1747 	if (paldata != nullptr)
1748 		drawscanline_core(bitmap, destx, desty, length, srcptr, priority, [paldata, pcode, pmask](u32 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_REMAP_OPAQUE_PRIMASK(destp, pri, srcp); });
1749 
1750 	// raw copy case
1751 	else
1752 		drawscanline_core(bitmap, destx, desty, length, srcptr, priority, [pcode, pmask](u32 &destp, u8 &pri, const u8 &srcp) { PIXEL_OP_COPY_OPAQUE_PRIMASK(destp, pri, srcp); });
1753 }
1754 
1755 
1756 /*-------------------------------------------------
1757     draw_scanline16 - copy pixels from a 16bpp
1758     buffer to a single scanline of a bitmap
1759 -------------------------------------------------*/
1760 
draw_scanline16(bitmap_ind16 & bitmap,s32 destx,s32 desty,s32 length,const u16 * srcptr,const pen_t * paldata)1761 void draw_scanline16(bitmap_ind16 &bitmap, s32 destx, s32 desty, s32 length, const u16 *srcptr, const pen_t *paldata)
1762 {
1763 	// palette lookup case
1764 	if (paldata != nullptr)
1765 		drawscanline_core(bitmap, destx, desty, length, srcptr, [paldata](u16 &destp, const u16 &srcp) { PIXEL_OP_REMAP_OPAQUE(destp, srcp); });
1766 
1767 	// raw copy case
1768 	else
1769 		drawscanline_core(bitmap, destx, desty, length, srcptr, [](u16 &destp, const u16 &srcp) { PIXEL_OP_COPY_OPAQUE(destp, srcp); });
1770 }
1771 
draw_scanline16(bitmap_rgb32 & bitmap,s32 destx,s32 desty,s32 length,const u16 * srcptr,const pen_t * paldata)1772 void draw_scanline16(bitmap_rgb32 &bitmap, s32 destx, s32 desty, s32 length, const u16 *srcptr, const pen_t *paldata)
1773 {
1774 	// palette lookup case
1775 	if (paldata != nullptr)
1776 		drawscanline_core(bitmap, destx, desty, length, srcptr, [paldata](u32 &destp, const u16 &srcp) { PIXEL_OP_REMAP_OPAQUE(destp, srcp); });
1777 
1778 	// raw copy case
1779 	else
1780 		drawscanline_core(bitmap, destx, desty, length, srcptr, [](u32 &destp, const u16 &srcp) { PIXEL_OP_COPY_OPAQUE(destp, srcp); });
1781 }
1782 
prio_draw_scanline16(bitmap_ind16 & bitmap,s32 destx,s32 desty,s32 length,const u16 * srcptr,const pen_t * paldata,bitmap_ind8 & priority,u32 pmask)1783 void prio_draw_scanline16(bitmap_ind16 &bitmap, s32 destx, s32 desty, s32 length, const u16 *srcptr, const pen_t *paldata, bitmap_ind8 &priority, u32 pmask)
1784 {
1785 	// high bit of the mask is implicitly on
1786 	pmask |= 1 << 31;
1787 
1788 	// palette lookup case
1789 	if (paldata != nullptr)
1790 		drawscanline_core(bitmap, destx, desty, length, srcptr, priority, [paldata, pmask](u16 &destp, u8 &pri, const u16 &srcp) { PIXEL_OP_REMAP_OPAQUE_PRIORITY(destp, pri, srcp); });
1791 
1792 	// raw copy case
1793 	else
1794 		drawscanline_core(bitmap, destx, desty, length, srcptr, priority, [pmask](u16 &destp, u8 &pri, const u16 &srcp) { PIXEL_OP_COPY_OPAQUE_PRIORITY(destp, pri, srcp); });
1795 }
1796 
prio_draw_scanline16(bitmap_rgb32 & bitmap,s32 destx,s32 desty,s32 length,const u16 * srcptr,const pen_t * paldata,bitmap_ind8 & priority,u32 pmask)1797 void prio_draw_scanline16(bitmap_rgb32 &bitmap, s32 destx, s32 desty, s32 length, const u16 *srcptr, const pen_t *paldata, bitmap_ind8 &priority, u32 pmask)
1798 {
1799 	// high bit of the mask is implicitly on
1800 	pmask |= 1 << 31;
1801 
1802 	// palette lookup case
1803 	if (paldata != nullptr)
1804 		drawscanline_core(bitmap, destx, desty, length, srcptr, priority, [paldata, pmask](u32 &destp, u8 &pri, const u16 &srcp) { PIXEL_OP_REMAP_OPAQUE_PRIORITY(destp, pri, srcp); });
1805 
1806 	// raw copy case
1807 	else
1808 		drawscanline_core(bitmap, destx, desty, length, srcptr, priority, [pmask](u32 &destp, u8 &pri, const u16 &srcp) { PIXEL_OP_COPY_OPAQUE_PRIORITY(destp, pri, srcp); });
1809 }
1810 
primask_draw_scanline16(bitmap_ind16 & bitmap,s32 destx,s32 desty,s32 length,const u16 * srcptr,const pen_t * paldata,bitmap_ind8 & priority,u8 pcode,u8 pmask)1811 void primask_draw_scanline16(bitmap_ind16 &bitmap, s32 destx, s32 desty, s32 length, const u16 *srcptr, const pen_t *paldata, bitmap_ind8 &priority, u8 pcode, u8 pmask)
1812 {
1813 	if (pcode == 0 && pmask == 0xff)
1814 		return draw_scanline16(bitmap, destx, desty, length, srcptr, paldata);
1815 
1816 	// palette lookup case
1817 	if (paldata != nullptr)
1818 		drawscanline_core(bitmap, destx, desty, length, srcptr, priority, [paldata, pcode, pmask](u16 &destp, u8 &pri, const u16 &srcp) { PIXEL_OP_REMAP_OPAQUE_PRIMASK(destp, pri, srcp); });
1819 
1820 	// raw copy case
1821 	else
1822 		drawscanline_core(bitmap, destx, desty, length, srcptr, priority, [pcode, pmask](u16 &destp, u8 &pri, const u16 &srcp) { PIXEL_OP_COPY_OPAQUE_PRIMASK(destp, pri, srcp); });
1823 }
1824 
primask_draw_scanline16(bitmap_rgb32 & bitmap,s32 destx,s32 desty,s32 length,const u16 * srcptr,const pen_t * paldata,bitmap_ind8 & priority,u8 pcode,u8 pmask)1825 void primask_draw_scanline16(bitmap_rgb32 &bitmap, s32 destx, s32 desty, s32 length, const u16 *srcptr, const pen_t *paldata, bitmap_ind8 &priority, u8 pcode, u8 pmask)
1826 {
1827 	if (pcode == 0 && pmask == 0xff)
1828 		return draw_scanline16(bitmap, destx, desty, length, srcptr, paldata);
1829 
1830 	// palette lookup case
1831 	if (paldata != nullptr)
1832 		drawscanline_core(bitmap, destx, desty, length, srcptr, priority, [paldata, pcode, pmask](u32 &destp, u8 &pri, const u16 &srcp) { PIXEL_OP_REMAP_OPAQUE_PRIMASK(destp, pri, srcp); });
1833 
1834 	// raw copy case
1835 	else
1836 		drawscanline_core(bitmap, destx, desty, length, srcptr, priority, [pcode, pmask](u32 &destp, u8 &pri, const u16 &srcp) { PIXEL_OP_COPY_OPAQUE_PRIMASK(destp, pri, srcp); });
1837 }
1838 
1839 
1840 /*-------------------------------------------------
1841     draw_scanline32 - copy pixels from a 32bpp
1842     buffer to a single scanline of a bitmap
1843 -------------------------------------------------*/
1844 
draw_scanline32(bitmap_ind16 & bitmap,s32 destx,s32 desty,s32 length,const u32 * srcptr,const pen_t * paldata)1845 void draw_scanline32(bitmap_ind16 &bitmap, s32 destx, s32 desty, s32 length, const u32 *srcptr, const pen_t *paldata)
1846 {
1847 	// palette lookup case
1848 	if (paldata != nullptr)
1849 		drawscanline_core(bitmap, destx, desty, length, srcptr, [paldata](u16 &destp, const u32 &srcp) { PIXEL_OP_REMAP_OPAQUE(destp, srcp); });
1850 
1851 	// raw copy case
1852 	else
1853 		drawscanline_core(bitmap, destx, desty, length, srcptr, [](u16 &destp, const u32 &srcp) { PIXEL_OP_COPY_OPAQUE(destp, srcp); });
1854 }
1855 
draw_scanline32(bitmap_rgb32 & bitmap,s32 destx,s32 desty,s32 length,const u32 * srcptr,const pen_t * paldata)1856 void draw_scanline32(bitmap_rgb32 &bitmap, s32 destx, s32 desty, s32 length, const u32 *srcptr, const pen_t *paldata)
1857 {
1858 	// palette lookup case
1859 	if (paldata != nullptr)
1860 		drawscanline_core(bitmap, destx, desty, length, srcptr, [paldata](u32 &destp, const u32 &srcp) { PIXEL_OP_REMAP_OPAQUE(destp, srcp); });
1861 
1862 	// raw copy case
1863 	else
1864 		drawscanline_core(bitmap, destx, desty, length, srcptr, [](u32 &destp, const u32 &srcp) { PIXEL_OP_COPY_OPAQUE(destp, srcp); });
1865 }
1866 
prio_draw_scanline32(bitmap_ind16 & bitmap,s32 destx,s32 desty,s32 length,const u32 * srcptr,const pen_t * paldata,bitmap_ind8 & priority,u32 pmask)1867 void prio_draw_scanline32(bitmap_ind16 &bitmap, s32 destx, s32 desty, s32 length, const u32 *srcptr, const pen_t *paldata, bitmap_ind8 &priority, u32 pmask)
1868 {
1869 	// high bit of the mask is implicitly on
1870 	pmask |= 1 << 31;
1871 
1872 	// palette lookup case
1873 	if (paldata != nullptr)
1874 		drawscanline_core(bitmap, destx, desty, length, srcptr, priority, [paldata, pmask](u16 &destp, u8 &pri, const u32 &srcp) { PIXEL_OP_REMAP_OPAQUE_PRIORITY(destp, pri, srcp); });
1875 
1876 	// raw copy case
1877 	else
1878 		drawscanline_core(bitmap, destx, desty, length, srcptr, priority, [pmask](u16 &destp, u8 &pri, const u32 &srcp) { PIXEL_OP_COPY_OPAQUE_PRIORITY(destp, pri, srcp); });
1879 }
1880 
prio_draw_scanline32(bitmap_rgb32 & bitmap,s32 destx,s32 desty,s32 length,const u32 * srcptr,const pen_t * paldata,bitmap_ind8 & priority,u32 pmask)1881 void prio_draw_scanline32(bitmap_rgb32 &bitmap, s32 destx, s32 desty, s32 length, const u32 *srcptr, const pen_t *paldata, bitmap_ind8 &priority, u32 pmask)
1882 {
1883 	// high bit of the mask is implicitly on
1884 	pmask |= 1 << 31;
1885 
1886 	// palette lookup case
1887 	if (paldata != nullptr)
1888 		drawscanline_core(bitmap, destx, desty, length, srcptr, priority, [paldata, pmask](u32 &destp, u8 &pri, const u32 &srcp) { PIXEL_OP_REMAP_OPAQUE_PRIORITY(destp, pri, srcp); });
1889 
1890 	// raw copy case
1891 	else
1892 		drawscanline_core(bitmap, destx, desty, length, srcptr, priority, [pmask](u32 &destp, u8 &pri, const u32 &srcp) { PIXEL_OP_COPY_OPAQUE_PRIORITY(destp, pri, srcp); });
1893 }
1894 
primask_draw_scanline32(bitmap_ind16 & bitmap,s32 destx,s32 desty,s32 length,const u32 * srcptr,const pen_t * paldata,bitmap_ind8 & priority,u8 pcode,u8 pmask)1895 void primask_draw_scanline32(bitmap_ind16 &bitmap, s32 destx, s32 desty, s32 length, const u32 *srcptr, const pen_t *paldata, bitmap_ind8 &priority, u8 pcode, u8 pmask)
1896 {
1897 	if (pcode == 0 && pmask == 0xff)
1898 		return draw_scanline32(bitmap, destx, desty, length, srcptr, paldata);
1899 
1900 	// palette lookup case
1901 	if (paldata != nullptr)
1902 		drawscanline_core(bitmap, destx, desty, length, srcptr, priority, [paldata, pcode, pmask](u16 &destp, u8 &pri, const u32 &srcp) { PIXEL_OP_REMAP_OPAQUE_PRIMASK(destp, pri, srcp); });
1903 
1904 	// raw copy case
1905 	else
1906 		drawscanline_core(bitmap, destx, desty, length, srcptr, priority, [pcode, pmask](u16 &destp, u8 &pri, const u32 &srcp) { PIXEL_OP_COPY_OPAQUE_PRIMASK(destp, pri, srcp); });
1907 }
1908 
primask_draw_scanline32(bitmap_rgb32 & bitmap,s32 destx,s32 desty,s32 length,const u32 * srcptr,const pen_t * paldata,bitmap_ind8 & priority,u8 pcode,u8 pmask)1909 void primask_draw_scanline32(bitmap_rgb32 &bitmap, s32 destx, s32 desty, s32 length, const u32 *srcptr, const pen_t *paldata, bitmap_ind8 &priority, u8 pcode, u8 pmask)
1910 {
1911 	if (pcode == 0 && pmask == 0xff)
1912 		return draw_scanline32(bitmap, destx, desty, length, srcptr, paldata);
1913 
1914 	// palette lookup case
1915 	if (paldata != nullptr)
1916 		drawscanline_core(bitmap, destx, desty, length, srcptr, priority, [paldata, pcode, pmask](u32 &destp, u8 &pri, const u32 &srcp) { PIXEL_OP_REMAP_OPAQUE_PRIMASK(destp, pri, srcp); });
1917 
1918 	// raw copy case
1919 	else
1920 		drawscanline_core(bitmap, destx, desty, length, srcptr, priority, [pcode, pmask](u32 &destp, u8 &pri, const u32 &srcp) { PIXEL_OP_COPY_OPAQUE_PRIMASK(destp, pri, srcp); });
1921 }
1922 
1923 
1924 
1925 /***************************************************************************
1926     COPYBITMAP IMPLEMENTATIONS
1927 ***************************************************************************/
1928 
1929 /*-------------------------------------------------
1930     copybitmap - copy from one bitmap to another,
1931     copying all unclipped pixels
1932 -------------------------------------------------*/
1933 
copybitmap(bitmap_ind16 & dest,const bitmap_ind16 & src,int flipx,int flipy,s32 destx,s32 desty,const rectangle & cliprect)1934 void copybitmap(bitmap_ind16 &dest, const bitmap_ind16 &src, int flipx, int flipy, s32 destx, s32 desty, const rectangle &cliprect)
1935 {
1936 	copybitmap_core(dest, src, flipx, flipy, destx, desty, cliprect, [](u16 &destp, const u16 &srcp) { PIXEL_OP_COPY_OPAQUE(destp, srcp); });
1937 }
1938 
copybitmap(bitmap_rgb32 & dest,const bitmap_rgb32 & src,int flipx,int flipy,s32 destx,s32 desty,const rectangle & cliprect)1939 void copybitmap(bitmap_rgb32 &dest, const bitmap_rgb32 &src, int flipx, int flipy, s32 destx, s32 desty, const rectangle &cliprect)
1940 {
1941 	copybitmap_core(dest, src, flipx, flipy, destx, desty, cliprect, [](u32 &destp, const u32 &srcp) { PIXEL_OP_COPY_OPAQUE(destp, srcp); });
1942 }
1943 
prio_copybitmap(bitmap_ind16 & dest,const bitmap_ind16 & src,int flipx,int flipy,s32 destx,s32 desty,const rectangle & cliprect,bitmap_ind8 & priority,u32 pmask)1944 void prio_copybitmap(bitmap_ind16 &dest, const bitmap_ind16 &src, int flipx, int flipy, s32 destx, s32 desty, const rectangle &cliprect, bitmap_ind8 &priority, u32 pmask)
1945 {
1946 	// high bit of the mask is implicitly on
1947 	pmask |= 1 << 31;
1948 
1949 	copybitmap_core(dest, src, flipx, flipy, destx, desty, cliprect, priority, [pmask](u16 &destp, u8 &pri, const u16 &srcp) { PIXEL_OP_COPY_OPAQUE_PRIORITY(destp, pri, srcp); });
1950 }
1951 
prio_copybitmap(bitmap_rgb32 & dest,const bitmap_rgb32 & src,int flipx,int flipy,s32 destx,s32 desty,const rectangle & cliprect,bitmap_ind8 & priority,u32 pmask)1952 void prio_copybitmap(bitmap_rgb32 &dest, const bitmap_rgb32 &src, int flipx, int flipy, s32 destx, s32 desty, const rectangle &cliprect, bitmap_ind8 &priority, u32 pmask)
1953 {
1954 	// high bit of the mask is implicitly on
1955 	pmask |= 1 << 31;
1956 
1957 	copybitmap_core(dest, src, flipx, flipy, destx, desty, cliprect, priority, [pmask](u32 &destp, u8 &pri, const u32 &srcp) { PIXEL_OP_COPY_OPAQUE_PRIORITY(destp, pri, srcp); });
1958 }
1959 
primask_copybitmap(bitmap_ind16 & dest,const bitmap_ind16 & src,int flipx,int flipy,s32 destx,s32 desty,const rectangle & cliprect,bitmap_ind8 & priority,u8 pcode,u8 pmask)1960 void primask_copybitmap(bitmap_ind16 &dest, const bitmap_ind16 &src, int flipx, int flipy, s32 destx, s32 desty, const rectangle &cliprect, bitmap_ind8 &priority, u8 pcode, u8 pmask)
1961 {
1962 	if (pcode == 0 && pmask == 0xff)
1963 		copybitmap(dest, src, flipx, flipy, destx, desty, cliprect);
1964 	else
1965 		copybitmap_core(dest, src, flipx, flipy, destx, desty, cliprect, priority, [pcode, pmask](u16 &destp, u8 &pri, const u16 &srcp) { PIXEL_OP_COPY_OPAQUE_PRIMASK(destp, pri, srcp); });
1966 }
1967 
primask_copybitmap(bitmap_rgb32 & dest,const bitmap_rgb32 & src,int flipx,int flipy,s32 destx,s32 desty,const rectangle & cliprect,bitmap_ind8 & priority,u8 pcode,u8 pmask)1968 void primask_copybitmap(bitmap_rgb32 &dest, const bitmap_rgb32 &src, int flipx, int flipy, s32 destx, s32 desty, const rectangle &cliprect, bitmap_ind8 &priority, u8 pcode, u8 pmask)
1969 {
1970 	if (pcode == 0 && pmask == 0xff)
1971 		copybitmap(dest, src, flipx, flipy, destx, desty, cliprect);
1972 	else
1973 		copybitmap_core(dest, src, flipx, flipy, destx, desty, cliprect, priority, [pcode, pmask](u32 &destp, u8 &pri, const u32 &srcp) { PIXEL_OP_COPY_OPAQUE_PRIMASK(destp, pri, srcp); });
1974 }
1975 
1976 
1977 /*-------------------------------------------------
1978     copybitmap_trans - copy from one bitmap to
1979     another, copying all unclipped pixels except
1980     those that match transpen
1981 -------------------------------------------------*/
1982 
copybitmap_trans(bitmap_ind16 & dest,const bitmap_ind16 & src,int flipx,int flipy,s32 destx,s32 desty,const rectangle & cliprect,u32 trans_pen)1983 void copybitmap_trans(bitmap_ind16 &dest, const bitmap_ind16 &src, int flipx, int flipy, s32 destx, s32 desty, const rectangle &cliprect, u32 trans_pen)
1984 {
1985 	if (trans_pen > 0xffff)
1986 		copybitmap(dest, src, flipx, flipy, destx, desty, cliprect);
1987 	else
1988 		copybitmap_core(dest, src, flipx, flipy, destx, desty, cliprect, [trans_pen](u16 &destp, const u16 &srcp) { PIXEL_OP_COPY_TRANSPEN(destp, srcp); });
1989 }
1990 
copybitmap_trans(bitmap_rgb32 & dest,const bitmap_rgb32 & src,int flipx,int flipy,s32 destx,s32 desty,const rectangle & cliprect,u32 trans_pen)1991 void copybitmap_trans(bitmap_rgb32 &dest, const bitmap_rgb32 &src, int flipx, int flipy, s32 destx, s32 desty, const rectangle &cliprect, u32 trans_pen)
1992 {
1993 	if (trans_pen == 0xffffffff)
1994 		copybitmap(dest, src, flipx, flipy, destx, desty, cliprect);
1995 	else
1996 		copybitmap_core(dest, src, flipx, flipy, destx, desty, cliprect, [trans_pen](u32 &destp, const u32 &srcp) { PIXEL_OP_COPY_TRANSPEN(destp, srcp); });
1997 }
1998 
prio_copybitmap_trans(bitmap_ind16 & dest,const bitmap_ind16 & src,int flipx,int flipy,s32 destx,s32 desty,const rectangle & cliprect,bitmap_ind8 & priority,u32 pmask,u32 trans_pen)1999 void prio_copybitmap_trans(bitmap_ind16 &dest, const bitmap_ind16 &src, int flipx, int flipy, s32 destx, s32 desty, const rectangle &cliprect, bitmap_ind8 &priority, u32 pmask, u32 trans_pen)
2000 {
2001 	// high bit of the mask is implicitly on
2002 	pmask |= 1 << 31;
2003 
2004 	if (trans_pen > 0xffff)
2005 		prio_copybitmap(dest, src, flipx, flipy, destx, desty, cliprect, priority, pmask);
2006 	else
2007 		copybitmap_core(dest, src, flipx, flipy, destx, desty, cliprect, priority, [pmask, trans_pen](u16 &destp, u8 &pri, const u16 &srcp) { PIXEL_OP_COPY_TRANSPEN_PRIORITY(destp, pri, srcp); });
2008 }
2009 
prio_copybitmap_trans(bitmap_rgb32 & dest,const bitmap_rgb32 & src,int flipx,int flipy,s32 destx,s32 desty,const rectangle & cliprect,bitmap_ind8 & priority,u32 pmask,u32 trans_pen)2010 void prio_copybitmap_trans(bitmap_rgb32 &dest, const bitmap_rgb32 &src, int flipx, int flipy, s32 destx, s32 desty, const rectangle &cliprect, bitmap_ind8 &priority, u32 pmask, u32 trans_pen)
2011 {
2012 	// high bit of the mask is implicitly on
2013 	pmask |= 1 << 31;
2014 
2015 	if (trans_pen == 0xffffffff)
2016 		prio_copybitmap(dest, src, flipx, flipy, destx, desty, cliprect, priority, pmask);
2017 	else
2018 		copybitmap_core(dest, src, flipx, flipy, destx, desty, cliprect, priority, [pmask, trans_pen](u32 &destp, u8 &pri, const u32 &srcp) { PIXEL_OP_COPY_TRANSPEN_PRIORITY(destp, pri, srcp); });
2019 }
2020 
primask_copybitmap_trans(bitmap_ind16 & dest,const bitmap_ind16 & src,int flipx,int flipy,s32 destx,s32 desty,const rectangle & cliprect,u32 trans_pen,bitmap_ind8 & priority,u8 pcode,u8 pmask)2021 void primask_copybitmap_trans(bitmap_ind16 &dest, const bitmap_ind16 &src, int flipx, int flipy, s32 destx, s32 desty, const rectangle &cliprect, u32 trans_pen, bitmap_ind8 &priority, u8 pcode, u8 pmask)
2022 {
2023 	if (pcode == 0 && pmask == 0xff)
2024 		copybitmap_trans(dest, src, flipx, flipy, destx, desty, cliprect, trans_pen);
2025 	else if (trans_pen > 0xffff)
2026 		primask_copybitmap(dest, src, flipx, flipy, destx, desty, cliprect, priority, pcode, pmask);
2027 	else
2028 		copybitmap_core(dest, src, flipx, flipy, destx, desty, cliprect, priority, [trans_pen, pcode, pmask](u16 &destp, u8 &pri, const u16 &srcp) { PIXEL_OP_COPY_TRANSPEN_PRIMASK(destp, pri, srcp); });
2029 }
2030 
primask_copybitmap_trans(bitmap_rgb32 & dest,const bitmap_rgb32 & src,int flipx,int flipy,s32 destx,s32 desty,const rectangle & cliprect,u32 trans_pen,bitmap_ind8 & priority,u8 pcode,u8 pmask)2031 void primask_copybitmap_trans(bitmap_rgb32 &dest, const bitmap_rgb32 &src, int flipx, int flipy, s32 destx, s32 desty, const rectangle &cliprect, u32 trans_pen, bitmap_ind8 &priority, u8 pcode, u8 pmask)
2032 {
2033 	if (pcode == 0 && pmask == 0xff)
2034 		copybitmap_trans(dest, src, flipx, flipy, destx, desty, cliprect, trans_pen);
2035 	else if (trans_pen == 0xffffffff)
2036 		primask_copybitmap(dest, src, flipx, flipy, destx, desty, cliprect, priority, pcode, pmask);
2037 	else
2038 		copybitmap_core(dest, src, flipx, flipy, destx, desty, cliprect, priority, [trans_pen, pcode, pmask](u32 &destp, u8 &pri, const u32 &srcp) { PIXEL_OP_COPY_TRANSPEN_PRIMASK(destp, pri, srcp); });
2039 }
2040 
2041 
2042 /*-------------------------------------------------
2043     copybitmap_transalphpa - copy from one bitmap
2044     to another, copying all unclipped pixels except
2045     those with an alpha value of zero
2046 -------------------------------------------------*/
2047 
copybitmap_transalpha(bitmap_rgb32 & dest,const bitmap_rgb32 & src,int flipx,int flipy,s32 destx,s32 desty,const rectangle & cliprect)2048 void copybitmap_transalpha(bitmap_rgb32 &dest, const bitmap_rgb32 &src, int flipx, int flipy, s32 destx, s32 desty, const rectangle &cliprect)
2049 {
2050 	copybitmap_core(dest, src, flipx, flipy, destx, desty, cliprect, [](u32 &destp, const u32 &srcp) { PIXEL_OP_COPY_TRANSALPHA(destp, srcp); });
2051 }
2052 
prio_copybitmap_transalpha(bitmap_rgb32 & dest,const bitmap_rgb32 & src,int flipx,int flipy,s32 destx,s32 desty,const rectangle & cliprect,bitmap_ind8 & priority,u32 pmask)2053 void prio_copybitmap_transalpha(bitmap_rgb32 &dest, const bitmap_rgb32 &src, int flipx, int flipy, s32 destx, s32 desty, const rectangle &cliprect, bitmap_ind8 &priority, u32 pmask)
2054 {
2055 	// high bit of the mask is implicitly on
2056 	pmask |= 1 << 31;
2057 
2058 	copybitmap_core(dest, src, flipx, flipy, destx, desty, cliprect, priority, [pmask](u32 &destp, u8 &pri, const u32 &srcp) { PIXEL_OP_COPY_TRANSALPHA_PRIORITY(destp, pri, srcp); });
2059 }
2060 
primask_copybitmap_transalpha(bitmap_rgb32 & dest,const bitmap_rgb32 & src,int flipx,int flipy,s32 destx,s32 desty,const rectangle & cliprect,bitmap_ind8 & priority,u8 pcode,u8 pmask)2061 void primask_copybitmap_transalpha(bitmap_rgb32 &dest, const bitmap_rgb32 &src, int flipx, int flipy, s32 destx, s32 desty, const rectangle &cliprect, bitmap_ind8 &priority, u8 pcode, u8 pmask)
2062 {
2063 	if (pcode == 0 && pmask == 0xff)
2064 		copybitmap_transalpha(dest, src, flipx, flipy, destx, desty, cliprect);
2065 	else
2066 		copybitmap_core(dest, src, flipx, flipy, destx, desty, cliprect, priority, [pcode, pmask](u32 &destp, u8 &pri, const u32 &srcp) { PIXEL_OP_COPY_TRANSALPHA_PRIMASK(destp, pri, srcp); });
2067 }
2068 
2069 
2070 /***************************************************************************
2071     COPYSCROLLBITMAP IMPLEMENTATIONS
2072 ***************************************************************************/
2073 
2074 /*-------------------------------------------------
2075     copyscrollbitmap - copy from one bitmap to
2076     another, copying all unclipped pixels, and
2077     applying scrolling to one or more rows/columns
2078 -------------------------------------------------*/
2079 
copyscrollbitmap(bitmap_ind16 & dest,const bitmap_ind16 & src,u32 numrows,const s32 * rowscroll,u32 numcols,const s32 * colscroll,const rectangle & cliprect)2080 void copyscrollbitmap(bitmap_ind16 &dest, const bitmap_ind16 &src, u32 numrows, const s32 *rowscroll, u32 numcols, const s32 *colscroll, const rectangle &cliprect)
2081 {
2082 	// just call through to the transparent case as the underlying copybitmap will
2083 	// optimize for pen == 0xffffffff
2084 	copyscrollbitmap_trans(dest, src, numrows, rowscroll, numcols, colscroll, cliprect, 0xffffffff);
2085 }
2086 
copyscrollbitmap(bitmap_rgb32 & dest,const bitmap_rgb32 & src,u32 numrows,const s32 * rowscroll,u32 numcols,const s32 * colscroll,const rectangle & cliprect)2087 void copyscrollbitmap(bitmap_rgb32 &dest, const bitmap_rgb32 &src, u32 numrows, const s32 *rowscroll, u32 numcols, const s32 *colscroll, const rectangle &cliprect)
2088 {
2089 	// just call through to the transparent case as the underlying copybitmap will
2090 	// optimize for pen == 0xffffffff
2091 	copyscrollbitmap_trans(dest, src, numrows, rowscroll, numcols, colscroll, cliprect, 0xffffffff);
2092 }
2093 
prio_copyscrollbitmap(bitmap_ind16 & dest,const bitmap_ind16 & src,u32 numrows,const s32 * rowscroll,u32 numcols,const s32 * colscroll,const rectangle & cliprect,bitmap_ind8 & priority,u32 pmask)2094 void prio_copyscrollbitmap(bitmap_ind16 &dest, const bitmap_ind16 &src, u32 numrows, const s32 *rowscroll, u32 numcols, const s32 *colscroll, const rectangle &cliprect, bitmap_ind8 &priority, u32 pmask)
2095 {
2096 	// just call through to the transparent case as the underlying copybitmap will
2097 	// optimize for pen == 0xffffffff
2098 	prio_copyscrollbitmap_trans(dest, src, numrows, rowscroll, numcols, colscroll, cliprect, priority, pmask, 0xffffffff);
2099 }
2100 
prio_copyscrollbitmap(bitmap_rgb32 & dest,const bitmap_rgb32 & src,u32 numrows,const s32 * rowscroll,u32 numcols,const s32 * colscroll,const rectangle & cliprect,bitmap_ind8 & priority,u32 pmask)2101 void prio_copyscrollbitmap(bitmap_rgb32 &dest, const bitmap_rgb32 &src, u32 numrows, const s32 *rowscroll, u32 numcols, const s32 *colscroll, const rectangle &cliprect, bitmap_ind8 &priority, u32 pmask)
2102 {
2103 	// just call through to the transparent case as the underlying copybitmap will
2104 	// optimize for pen == 0xffffffff
2105 	prio_copyscrollbitmap_trans(dest, src, numrows, rowscroll, numcols, colscroll, cliprect, priority, pmask, 0xffffffff);
2106 }
2107 
primask_copyscrollbitmap(bitmap_ind16 & dest,const bitmap_ind16 & src,u32 numrows,const s32 * rowscroll,u32 numcols,const s32 * colscroll,const rectangle & cliprect,bitmap_ind8 & priority,u8 pcode,u8 pmask)2108 void primask_copyscrollbitmap(bitmap_ind16 &dest, const bitmap_ind16 &src, u32 numrows, const s32 *rowscroll, u32 numcols, const s32 *colscroll, const rectangle &cliprect, bitmap_ind8 &priority, u8 pcode, u8 pmask)
2109 {
2110 	// just call through to the transparent case as the underlying copybitmap will
2111 	// optimize for pen == 0xffffffff
2112 	if (pcode == 0 && pmask == 0xff)
2113 		copyscrollbitmap(dest, src, numrows, rowscroll, numcols, colscroll, cliprect);
2114 	else
2115 		primask_copyscrollbitmap_trans(dest, src, numrows, rowscroll, numcols, colscroll, cliprect, 0xffffffff, priority, pcode, pmask);
2116 }
2117 
primask_copyscrollbitmap(bitmap_rgb32 & dest,const bitmap_rgb32 & src,u32 numrows,const s32 * rowscroll,u32 numcols,const s32 * colscroll,const rectangle & cliprect,bitmap_ind8 & priority,u8 pcode,u8 pmask)2118 void primask_copyscrollbitmap(bitmap_rgb32 &dest, const bitmap_rgb32 &src, u32 numrows, const s32 *rowscroll, u32 numcols, const s32 *colscroll, const rectangle &cliprect, bitmap_ind8 &priority, u8 pcode, u8 pmask)
2119 {
2120 	// just call through to the transparent case as the underlying copybitmap will
2121 	// optimize for pen == 0xffffffff
2122 	if (pcode == 0 && pmask == 0xff)
2123 		copyscrollbitmap(dest, src, numrows, rowscroll, numcols, colscroll, cliprect);
2124 	else
2125 		primask_copyscrollbitmap_trans(dest, src, numrows, rowscroll, numcols, colscroll, cliprect, 0xffffffff, priority, pcode, pmask);
2126 }
2127 
2128 
2129 /*-------------------------------------------------
2130     copyscrollbitmap_trans - copy from one bitmap
2131     to another, copying all unclipped pixels
2132     except those that match transpen, and applying
2133     scrolling to one or more rows/columns
2134 -------------------------------------------------*/
2135 
2136 template<class BitmapClass>
copyscrollbitmap_trans_common(BitmapClass & dest,const BitmapClass & src,u32 numrows,const s32 * rowscroll,u32 numcols,const s32 * colscroll,const rectangle & cliprect,u32 trans_pen)2137 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)
2138 {
2139 	// no rowscroll and no colscroll means no scroll
2140 	if (numrows == 0 && numcols == 0)
2141 		return copybitmap_trans(dest, src, 0, 0, 0, 0, cliprect, trans_pen);
2142 
2143 	assert(numrows != 0 || rowscroll == nullptr);
2144 	assert(numrows == 0 || rowscroll != nullptr);
2145 	assert(numcols != 0 || colscroll == nullptr);
2146 	assert(numcols == 0 || colscroll != nullptr);
2147 
2148 	// fully scrolling X,Y playfield
2149 	if (numrows <= 1 && numcols <= 1)
2150 	{
2151 		s32 xscroll = normalize_xscroll(src, (numrows == 0) ? 0 : rowscroll[0]);
2152 		s32 yscroll = normalize_yscroll(src, (numcols == 0) ? 0 : colscroll[0]);
2153 
2154 		// iterate over all portions of the scroll that overlap the destination
2155 		for (s32 sx = xscroll - src.width(); sx < dest.width(); sx += src.width())
2156 			for (s32 sy = yscroll - src.height(); sy < dest.height(); sy += src.height())
2157 				copybitmap_trans(dest, src, 0, 0, sx, sy, cliprect, trans_pen);
2158 	}
2159 
2160 	// scrolling columns plus horizontal scroll
2161 	else if (numrows <= 1)
2162 	{
2163 		s32 xscroll = normalize_xscroll(src, (numrows == 0) ? 0 : rowscroll[0]);
2164 		rectangle subclip = cliprect;
2165 
2166 		// determine width of each column
2167 		int colwidth = src.width() / numcols;
2168 		assert(src.width() % colwidth == 0);
2169 
2170 		// iterate over each column
2171 		int groupcols;
2172 		for (int col = 0; col < numcols; col += groupcols)
2173 		{
2174 			s32 yscroll = colscroll[col];
2175 
2176 			// count consecutive columns scrolled by the same amount
2177 			for (groupcols = 1; col + groupcols < numcols; groupcols++)
2178 					if (colscroll[col + groupcols] != yscroll)
2179 					break;
2180 
2181 			// iterate over reps of the columns in question
2182 			yscroll = normalize_yscroll(src, yscroll);
2183 			for (s32 sx = xscroll - src.width(); sx < dest.width(); sx += src.width())
2184 			{
2185 				// compute the cliprect for this group
2186 				subclip.setx(col * colwidth + sx, (col + groupcols) * colwidth - 1 + sx);
2187 				subclip &= cliprect;
2188 
2189 				// iterate over all portions of the scroll that overlap the destination
2190 				for (s32 sy = yscroll - src.height(); sy < dest.height(); sy += src.height())
2191 					copybitmap_trans(dest, src, 0, 0, sx, sy, subclip, trans_pen);
2192 			}
2193 		}
2194 	}
2195 
2196 	// scrolling rows plus vertical scroll
2197 	else if (numcols <= 1)
2198 	{
2199 		s32 yscroll = normalize_yscroll(src, (numcols == 0) ? 0 : colscroll[0]);
2200 		rectangle subclip = cliprect;
2201 
2202 		// determine width of each rows
2203 		int rowheight = src.height() / numrows;
2204 		assert(src.height() % rowheight == 0);
2205 
2206 		// iterate over each row
2207 		int grouprows;
2208 		for (int row = 0; row < numrows; row += grouprows)
2209 		{
2210 			s32 xscroll = rowscroll[row];
2211 
2212 			// count consecutive rows scrolled by the same amount
2213 			for (grouprows = 1; row + grouprows < numrows; grouprows++)
2214 					if (rowscroll[row + grouprows] != xscroll)
2215 					break;
2216 
2217 			// iterate over reps of the rows in question
2218 			xscroll = normalize_xscroll(src, xscroll);
2219 			for (s32 sy = yscroll - src.height(); sy < dest.height(); sy += src.height())
2220 			{
2221 				// compute the cliprect for this group
2222 				subclip.sety(row * rowheight + sy, (row + grouprows) * rowheight - 1 + sy);
2223 				subclip &= cliprect;
2224 
2225 				// iterate over all portions of the scroll that overlap the destination
2226 				for (s32 sx = xscroll - src.width(); sx < dest.width(); sx += src.width())
2227 					copybitmap_trans(dest, src, 0, 0, sx, sy, subclip, trans_pen);
2228 			}
2229 		}
2230 	}
2231 }
2232 
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)2233 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)
2234 { copyscrollbitmap_trans_common(dest, src, numrows, rowscroll, numcols, colscroll, cliprect, trans_pen); }
2235 
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)2236 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)
2237 { copyscrollbitmap_trans_common(dest, src, numrows, rowscroll, numcols, colscroll, cliprect, trans_pen); }
2238 
2239 template<class BitmapClass>
prio_copyscrollbitmap_trans_common(BitmapClass & dest,const BitmapClass & src,u32 numrows,const s32 * rowscroll,u32 numcols,const s32 * colscroll,const rectangle & cliprect,bitmap_ind8 & priority,u32 pmask,u32 trans_pen)2240 static inline void prio_copyscrollbitmap_trans_common(BitmapClass &dest, const BitmapClass &src, u32 numrows, const s32 *rowscroll, u32 numcols, const s32 *colscroll, const rectangle &cliprect, bitmap_ind8 &priority, u32 pmask, u32 trans_pen)
2241 {
2242 	// no rowscroll and no colscroll means no scroll
2243 	if (numrows == 0 && numcols == 0)
2244 		return prio_copybitmap_trans(dest, src, 0, 0, 0, 0, cliprect, priority, pmask, trans_pen);
2245 
2246 	assert(numrows != 0 || rowscroll == nullptr);
2247 	assert(numrows == 0 || rowscroll != nullptr);
2248 	assert(numcols != 0 || colscroll == nullptr);
2249 	assert(numcols == 0 || colscroll != nullptr);
2250 
2251 	// fully scrolling X,Y playfield
2252 	if (numrows <= 1 && numcols <= 1)
2253 	{
2254 		s32 xscroll = normalize_xscroll(src, (numrows == 0) ? 0 : rowscroll[0]);
2255 		s32 yscroll = normalize_yscroll(src, (numcols == 0) ? 0 : colscroll[0]);
2256 
2257 		// iterate over all portions of the scroll that overlap the destination
2258 		for (s32 sx = xscroll - src.width(); sx < dest.width(); sx += src.width())
2259 			for (s32 sy = yscroll - src.height(); sy < dest.height(); sy += src.height())
2260 				prio_copybitmap_trans(dest, src, 0, 0, sx, sy, cliprect, priority, pmask, trans_pen);
2261 	}
2262 
2263 	// scrolling columns plus horizontal scroll
2264 	else if (numrows <= 1)
2265 	{
2266 		s32 xscroll = normalize_xscroll(src, (numrows == 0) ? 0 : rowscroll[0]);
2267 		rectangle subclip = cliprect;
2268 
2269 		// determine width of each column
2270 		int colwidth = src.width() / numcols;
2271 		assert(src.width() % colwidth == 0);
2272 
2273 		// iterate over each column
2274 		int groupcols;
2275 		for (int col = 0; col < numcols; col += groupcols)
2276 		{
2277 			s32 yscroll = colscroll[col];
2278 
2279 			// count consecutive columns scrolled by the same amount
2280 			for (groupcols = 1; col + groupcols < numcols; groupcols++)
2281 					if (colscroll[col + groupcols] != yscroll)
2282 					break;
2283 
2284 			// iterate over reps of the columns in question
2285 			yscroll = normalize_yscroll(src, yscroll);
2286 			for (s32 sx = xscroll - src.width(); sx < dest.width(); sx += src.width())
2287 			{
2288 				// compute the cliprect for this group
2289 				subclip.setx(col * colwidth + sx, (col + groupcols) * colwidth - 1 + sx);
2290 				subclip &= cliprect;
2291 
2292 				// iterate over all portions of the scroll that overlap the destination
2293 				for (s32 sy = yscroll - src.height(); sy < dest.height(); sy += src.height())
2294 					prio_copybitmap_trans(dest, src, 0, 0, sx, sy, subclip, priority, pmask, trans_pen);
2295 			}
2296 		}
2297 	}
2298 
2299 	// scrolling rows plus vertical scroll
2300 	else if (numcols <= 1)
2301 	{
2302 		s32 yscroll = normalize_yscroll(src, (numcols == 0) ? 0 : colscroll[0]);
2303 		rectangle subclip = cliprect;
2304 
2305 		// determine width of each rows
2306 		int rowheight = src.height() / numrows;
2307 		assert(src.height() % rowheight == 0);
2308 
2309 		// iterate over each row
2310 		int grouprows;
2311 		for (int row = 0; row < numrows; row += grouprows)
2312 		{
2313 			s32 xscroll = rowscroll[row];
2314 
2315 			// count consecutive rows scrolled by the same amount
2316 			for (grouprows = 1; row + grouprows < numrows; grouprows++)
2317 					if (rowscroll[row + grouprows] != xscroll)
2318 					break;
2319 
2320 			// iterate over reps of the rows in question
2321 			xscroll = normalize_xscroll(src, xscroll);
2322 			for (s32 sy = yscroll - src.height(); sy < dest.height(); sy += src.height())
2323 			{
2324 				// compute the cliprect for this group
2325 				subclip.sety(row * rowheight + sy, (row + grouprows) * rowheight - 1 + sy);
2326 				subclip &= cliprect;
2327 
2328 				// iterate over all portions of the scroll that overlap the destination
2329 				for (s32 sx = xscroll - src.width(); sx < dest.width(); sx += src.width())
2330 					prio_copybitmap_trans(dest, src, 0, 0, sx, sy, subclip, priority, pmask, trans_pen);
2331 			}
2332 		}
2333 	}
2334 }
2335 
prio_copyscrollbitmap_trans(bitmap_ind16 & dest,const bitmap_ind16 & src,u32 numrows,const s32 * rowscroll,u32 numcols,const s32 * colscroll,const rectangle & cliprect,bitmap_ind8 & priority,u32 pmask,u32 trans_pen)2336 void prio_copyscrollbitmap_trans(bitmap_ind16 &dest, const bitmap_ind16 &src, u32 numrows, const s32 *rowscroll, u32 numcols, const s32 *colscroll, const rectangle &cliprect, bitmap_ind8 &priority, u32 pmask, u32 trans_pen)
2337 { prio_copyscrollbitmap_trans_common(dest, src, numrows, rowscroll, numcols, colscroll, cliprect, priority, pmask, trans_pen); }
2338 
prio_copyscrollbitmap_trans(bitmap_rgb32 & dest,const bitmap_rgb32 & src,u32 numrows,const s32 * rowscroll,u32 numcols,const s32 * colscroll,const rectangle & cliprect,bitmap_ind8 & priority,u32 pmask,u32 trans_pen)2339 void prio_copyscrollbitmap_trans(bitmap_rgb32 &dest, const bitmap_rgb32 &src, u32 numrows, const s32 *rowscroll, u32 numcols, const s32 *colscroll, const rectangle &cliprect, bitmap_ind8 &priority, u32 pmask, u32 trans_pen)
2340 { prio_copyscrollbitmap_trans_common(dest, src, numrows, rowscroll, numcols, colscroll, cliprect, priority, pmask, trans_pen); }
2341 
2342 template<class BitmapClass>
primask_copyscrollbitmap_trans_common(BitmapClass & dest,const BitmapClass & src,u32 numrows,const s32 * rowscroll,u32 numcols,const s32 * colscroll,const rectangle & cliprect,u32 trans_pen,bitmap_ind8 & priority,u8 pcode=0,u8 pmask=0xff)2343 static inline void primask_copyscrollbitmap_trans_common(BitmapClass &dest, const BitmapClass &src, u32 numrows, const s32 *rowscroll, u32 numcols, const s32 *colscroll, const rectangle &cliprect, u32 trans_pen, bitmap_ind8 &priority, u8 pcode = 0, u8 pmask = 0xff)
2344 {
2345 	// no rowscroll and no colscroll means no scroll
2346 	if (pcode == 0 && pmask == 0xff)
2347 		return copyscrollbitmap_trans_common(dest, src, numrows, rowscroll, numcols, colscroll, cliprect, trans_pen);
2348 
2349 	if (numrows == 0 && numcols == 0)
2350 		return primask_copybitmap_trans(dest, src, 0, 0, 0, 0, cliprect, trans_pen, priority, pcode, pmask);
2351 
2352 	assert(numrows != 0 || rowscroll == nullptr);
2353 	assert(numrows == 0 || rowscroll != nullptr);
2354 	assert(numcols != 0 || colscroll == nullptr);
2355 	assert(numcols == 0 || colscroll != nullptr);
2356 
2357 	// fully scrolling X,Y playfield
2358 	if (numrows <= 1 && numcols <= 1)
2359 	{
2360 		s32 xscroll = normalize_xscroll(src, (numrows == 0) ? 0 : rowscroll[0]);
2361 		s32 yscroll = normalize_yscroll(src, (numcols == 0) ? 0 : colscroll[0]);
2362 
2363 		// iterate over all portions of the scroll that overlap the destination
2364 		for (s32 sx = xscroll - src.width(); sx < dest.width(); sx += src.width())
2365 			for (s32 sy = yscroll - src.height(); sy < dest.height(); sy += src.height())
2366 				primask_copybitmap_trans(dest, src, 0, 0, sx, sy, cliprect, trans_pen, priority, pcode, pmask);
2367 	}
2368 
2369 	// scrolling columns plus horizontal scroll
2370 	else if (numrows <= 1)
2371 	{
2372 		s32 xscroll = normalize_xscroll(src, (numrows == 0) ? 0 : rowscroll[0]);
2373 		rectangle subclip = cliprect;
2374 
2375 		// determine width of each column
2376 		int colwidth = src.width() / numcols;
2377 		assert(src.width() % colwidth == 0);
2378 
2379 		// iterate over each column
2380 		int groupcols;
2381 		for (int col = 0; col < numcols; col += groupcols)
2382 		{
2383 			s32 yscroll = colscroll[col];
2384 
2385 			// count consecutive columns scrolled by the same amount
2386 			for (groupcols = 1; col + groupcols < numcols; groupcols++)
2387 					if (colscroll[col + groupcols] != yscroll)
2388 					break;
2389 
2390 			// iterate over reps of the columns in question
2391 			yscroll = normalize_yscroll(src, yscroll);
2392 			for (s32 sx = xscroll - src.width(); sx < dest.width(); sx += src.width())
2393 			{
2394 				// compute the cliprect for this group
2395 				subclip.setx(col * colwidth + sx, (col + groupcols) * colwidth - 1 + sx);
2396 				subclip &= cliprect;
2397 
2398 				// iterate over all portions of the scroll that overlap the destination
2399 				for (s32 sy = yscroll - src.height(); sy < dest.height(); sy += src.height())
2400 					primask_copybitmap_trans(dest, src, 0, 0, sx, sy, subclip, trans_pen, priority, pcode, pmask);
2401 			}
2402 		}
2403 	}
2404 
2405 	// scrolling rows plus vertical scroll
2406 	else if (numcols <= 1)
2407 	{
2408 		s32 yscroll = normalize_yscroll(src, (numcols == 0) ? 0 : colscroll[0]);
2409 		rectangle subclip = cliprect;
2410 
2411 		// determine width of each rows
2412 		int rowheight = src.height() / numrows;
2413 		assert(src.height() % rowheight == 0);
2414 
2415 		// iterate over each row
2416 		int grouprows;
2417 		for (int row = 0; row < numrows; row += grouprows)
2418 		{
2419 			s32 xscroll = rowscroll[row];
2420 
2421 			// count consecutive rows scrolled by the same amount
2422 			for (grouprows = 1; row + grouprows < numrows; grouprows++)
2423 					if (rowscroll[row + grouprows] != xscroll)
2424 					break;
2425 
2426 			// iterate over reps of the rows in question
2427 			xscroll = normalize_xscroll(src, xscroll);
2428 			for (s32 sy = yscroll - src.height(); sy < dest.height(); sy += src.height())
2429 			{
2430 				// compute the cliprect for this group
2431 				subclip.sety(row * rowheight + sy, (row + grouprows) * rowheight - 1 + sy);
2432 				subclip &= cliprect;
2433 
2434 				// iterate over all portions of the scroll that overlap the destination
2435 				for (s32 sx = xscroll - src.width(); sx < dest.width(); sx += src.width())
2436 					primask_copybitmap_trans(dest, src, 0, 0, sx, sy, subclip, trans_pen, priority, pcode, pmask);
2437 			}
2438 		}
2439 	}
2440 }
2441 
primask_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,bitmap_ind8 & priority,u8 pcode,u8 pmask)2442 void primask_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, bitmap_ind8 &priority, u8 pcode, u8 pmask)
2443 { primask_copyscrollbitmap_trans_common(dest, src, numrows, rowscroll, numcols, colscroll, cliprect, trans_pen, priority, pcode, pmask); }
2444 
primask_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,bitmap_ind8 & priority,u8 pcode,u8 pmask)2445 void primask_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, bitmap_ind8 &priority, u8 pcode, u8 pmask)
2446 { primask_copyscrollbitmap_trans_common(dest, src, numrows, rowscroll, numcols, colscroll, cliprect, trans_pen, priority, pcode, pmask); }
2447 
2448 
2449 /***************************************************************************
2450     COPYROZBITMAP IMPLEMENTATIONS
2451 ***************************************************************************/
2452 
2453 /*-------------------------------------------------
2454     copyrozbitmap - copy from one bitmap to another,
2455     with zoom and rotation, copying all unclipped
2456     pixels
2457 -------------------------------------------------*/
2458 
copyrozbitmap(bitmap_ind16 & dest,const rectangle & cliprect,const bitmap_ind16 & src,s32 startx,s32 starty,s32 incxx,s32 incxy,s32 incyx,s32 incyy,bool wraparound)2459 void copyrozbitmap(bitmap_ind16 &dest, const rectangle &cliprect, const bitmap_ind16 &src, s32 startx, s32 starty, s32 incxx, s32 incxy, s32 incyx, s32 incyy, bool wraparound)
2460 {
2461 	copyrozbitmap_core(dest, cliprect, src, startx, starty, incxx, incxy, incyx, incyy, wraparound, [](u16 &destp, const u16 &srcp) { PIXEL_OP_COPY_OPAQUE(destp, srcp); });
2462 }
2463 
copyrozbitmap(bitmap_rgb32 & dest,const rectangle & cliprect,const bitmap_rgb32 & src,s32 startx,s32 starty,s32 incxx,s32 incxy,s32 incyx,s32 incyy,bool wraparound)2464 void copyrozbitmap(bitmap_rgb32 &dest, const rectangle &cliprect, const bitmap_rgb32 &src, s32 startx, s32 starty, s32 incxx, s32 incxy, s32 incyx, s32 incyy, bool wraparound)
2465 {
2466 	copyrozbitmap_core(dest, cliprect, src, startx, starty, incxx, incxy, incyx, incyy, wraparound, [](u32 &destp, const u32 &srcp) { PIXEL_OP_COPY_OPAQUE(destp, srcp); });
2467 }
2468 
prio_copyrozbitmap(bitmap_ind16 & dest,const rectangle & cliprect,const bitmap_ind16 & src,s32 startx,s32 starty,s32 incxx,s32 incxy,s32 incyx,s32 incyy,bool wraparound,bitmap_ind8 & priority,u32 pmask)2469 void prio_copyrozbitmap(bitmap_ind16 &dest, const rectangle &cliprect, const bitmap_ind16 &src, s32 startx, s32 starty, s32 incxx, s32 incxy, s32 incyx, s32 incyy, bool wraparound, bitmap_ind8 &priority, u32 pmask)
2470 {
2471 	// high bit of the mask is implicitly on
2472 	pmask |= 1 << 31;
2473 
2474 	copyrozbitmap_core(dest, cliprect, src, startx, starty, incxx, incxy, incyx, incyy, wraparound, priority, [pmask](u16 &destp, u8 &pri, const u16 &srcp) { PIXEL_OP_COPY_OPAQUE_PRIORITY(destp, pri, srcp); });
2475 }
2476 
prio_copyrozbitmap(bitmap_rgb32 & dest,const rectangle & cliprect,const bitmap_rgb32 & src,s32 startx,s32 starty,s32 incxx,s32 incxy,s32 incyx,s32 incyy,bool wraparound,bitmap_ind8 & priority,u32 pmask)2477 void prio_copyrozbitmap(bitmap_rgb32 &dest, const rectangle &cliprect, const bitmap_rgb32 &src, s32 startx, s32 starty, s32 incxx, s32 incxy, s32 incyx, s32 incyy, bool wraparound, bitmap_ind8 &priority, u32 pmask)
2478 {
2479 	// high bit of the mask is implicitly on
2480 	pmask |= 1 << 31;
2481 
2482 	copyrozbitmap_core(dest, cliprect, src, startx, starty, incxx, incxy, incyx, incyy, wraparound, priority, [pmask](u32 &destp, u8 &pri, const u32 &srcp) { PIXEL_OP_COPY_OPAQUE_PRIORITY(destp, pri, srcp); });
2483 }
2484 
primask_copyrozbitmap(bitmap_ind16 & dest,const rectangle & cliprect,const bitmap_ind16 & src,s32 startx,s32 starty,s32 incxx,s32 incxy,s32 incyx,s32 incyy,bool wraparound,bitmap_ind8 & priority,u8 pcode,u8 pmask)2485 void primask_copyrozbitmap(bitmap_ind16 &dest, const rectangle &cliprect, const bitmap_ind16 &src, s32 startx, s32 starty, s32 incxx, s32 incxy, s32 incyx, s32 incyy, bool wraparound, bitmap_ind8 &priority, u8 pcode, u8 pmask)
2486 {
2487 	if (pcode == 0 && pmask == 0xff)
2488 		copyrozbitmap(dest, cliprect, src, startx, starty, incxx, incxy, incyx, incyy, wraparound);
2489 	else
2490 		copyrozbitmap_core(dest, cliprect, src, startx, starty, incxx, incxy, incyx, incyy, wraparound, priority, [pcode, pmask](u16 &destp, u8 &pri, const u16 &srcp) { PIXEL_OP_COPY_OPAQUE_PRIMASK(destp, pri, srcp); });
2491 }
2492 
primask_copyrozbitmap(bitmap_rgb32 & dest,const rectangle & cliprect,const bitmap_rgb32 & src,s32 startx,s32 starty,s32 incxx,s32 incxy,s32 incyx,s32 incyy,bool wraparound,bitmap_ind8 & priority,u8 pcode,u8 pmask)2493 void primask_copyrozbitmap(bitmap_rgb32 &dest, const rectangle &cliprect, const bitmap_rgb32 &src, s32 startx, s32 starty, s32 incxx, s32 incxy, s32 incyx, s32 incyy, bool wraparound, bitmap_ind8 &priority, u8 pcode, u8 pmask)
2494 {
2495 	if (pcode == 0 && pmask == 0xff)
2496 		copyrozbitmap(dest, cliprect, src, startx, starty, incxx, incxy, incyx, incyy, wraparound);
2497 	else
2498 		copyrozbitmap_core(dest, cliprect, src, startx, starty, incxx, incxy, incyx, incyy, wraparound, priority, [pcode, pmask](u32 &destp, u8 &pri, const u32 &srcp) { PIXEL_OP_COPY_OPAQUE_PRIMASK(destp, pri, srcp); });
2499 }
2500 
2501 
2502 /*-------------------------------------------------
2503     copyrozbitmap_trans - copy from one bitmap to
2504     another, with zoom and rotation, copying all
2505     unclipped pixels whose values do not match
2506     transpen
2507 -------------------------------------------------*/
2508 
copyrozbitmap_trans(bitmap_ind16 & dest,const rectangle & cliprect,const bitmap_ind16 & src,s32 startx,s32 starty,s32 incxx,s32 incxy,s32 incyx,s32 incyy,bool wraparound,u32 trans_pen)2509 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, bool wraparound, u32 trans_pen)
2510 {
2511 	copyrozbitmap_core(dest, cliprect, src, startx, starty, incxx, incxy, incyx, incyy, wraparound, [trans_pen](u16 &destp, const u16 &srcp) { PIXEL_OP_COPY_TRANSPEN(destp, srcp); });
2512 }
2513 
copyrozbitmap_trans(bitmap_rgb32 & dest,const rectangle & cliprect,const bitmap_rgb32 & src,s32 startx,s32 starty,s32 incxx,s32 incxy,s32 incyx,s32 incyy,bool wraparound,u32 trans_pen)2514 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, bool wraparound, u32 trans_pen)
2515 {
2516 	copyrozbitmap_core(dest, cliprect, src, startx, starty, incxx, incxy, incyx, incyy, wraparound, [trans_pen](u32 &destp, const u32 &srcp) { PIXEL_OP_COPY_TRANSPEN(destp, srcp); });
2517 }
2518 
prio_copyrozbitmap_trans(bitmap_ind16 & dest,const rectangle & cliprect,const bitmap_ind16 & src,s32 startx,s32 starty,s32 incxx,s32 incxy,s32 incyx,s32 incyy,bool wraparound,bitmap_ind8 & priority,u32 pmask,u32 trans_pen)2519 void prio_copyrozbitmap_trans(bitmap_ind16 &dest, const rectangle &cliprect, const bitmap_ind16 &src, s32 startx, s32 starty, s32 incxx, s32 incxy, s32 incyx, s32 incyy, bool wraparound, bitmap_ind8 &priority, u32 pmask, u32 trans_pen)
2520 {
2521 	// high bit of the mask is implicitly on
2522 	pmask |= 1 << 31;
2523 
2524 	copyrozbitmap_core(dest, cliprect, src, startx, starty, incxx, incxy, incyx, incyy, wraparound, priority, [pmask, trans_pen](u16 &destp, u8 &pri, const u16 &srcp) { PIXEL_OP_COPY_TRANSPEN_PRIORITY(destp, pri, srcp); });
2525 }
2526 
prio_copyrozbitmap_trans(bitmap_rgb32 & dest,const rectangle & cliprect,const bitmap_rgb32 & src,s32 startx,s32 starty,s32 incxx,s32 incxy,s32 incyx,s32 incyy,bool wraparound,bitmap_ind8 & priority,u32 pmask,u32 trans_pen)2527 void prio_copyrozbitmap_trans(bitmap_rgb32 &dest, const rectangle &cliprect, const bitmap_rgb32 &src, s32 startx, s32 starty, s32 incxx, s32 incxy, s32 incyx, s32 incyy, bool wraparound, bitmap_ind8 &priority, u32 pmask, u32 trans_pen)
2528 {
2529 	// high bit of the mask is implicitly on
2530 	pmask |= 1 << 31;
2531 
2532 	copyrozbitmap_core(dest, cliprect, src, startx, starty, incxx, incxy, incyx, incyy, wraparound, priority, [pmask, trans_pen](u32 &destp, u8 &pri, const u32 &srcp) { PIXEL_OP_COPY_TRANSPEN_PRIORITY(destp, pri, srcp); });
2533 }
2534 
primask_copyrozbitmap_trans(bitmap_ind16 & dest,const rectangle & cliprect,const bitmap_ind16 & src,s32 startx,s32 starty,s32 incxx,s32 incxy,s32 incyx,s32 incyy,bool wraparound,u32 trans_pen,bitmap_ind8 & priority,u8 pcode,u8 pmask)2535 void primask_copyrozbitmap_trans(bitmap_ind16 &dest, const rectangle &cliprect, const bitmap_ind16 &src, s32 startx, s32 starty, s32 incxx, s32 incxy, s32 incyx, s32 incyy, bool wraparound, u32 trans_pen, bitmap_ind8 &priority, u8 pcode, u8 pmask)
2536 {
2537 	if (pcode == 0 && pmask == 0xff)
2538 		copyrozbitmap_trans(dest, cliprect, src, startx, starty, incxx, incxy, incyx, incyy, wraparound, trans_pen);
2539 	else
2540 		copyrozbitmap_core(dest, cliprect, src, startx, starty, incxx, incxy, incyx, incyy, wraparound, priority, [trans_pen, pcode, pmask](u16 &destp, u8 &pri, const u16 &srcp) { PIXEL_OP_COPY_TRANSPEN_PRIMASK(destp, pri, srcp); });
2541 }
2542 
primask_copyrozbitmap_trans(bitmap_rgb32 & dest,const rectangle & cliprect,const bitmap_rgb32 & src,s32 startx,s32 starty,s32 incxx,s32 incxy,s32 incyx,s32 incyy,bool wraparound,u32 trans_pen,bitmap_ind8 & priority,u8 pcode,u8 pmask)2543 void primask_copyrozbitmap_trans(bitmap_rgb32 &dest, const rectangle &cliprect, const bitmap_rgb32 &src, s32 startx, s32 starty, s32 incxx, s32 incxy, s32 incyx, s32 incyy, bool wraparound, u32 trans_pen, bitmap_ind8 &priority, u8 pcode, u8 pmask)
2544 {
2545 	if (pcode == 0 && pmask == 0xff)
2546 		copyrozbitmap_trans(dest, cliprect, src, startx, starty, incxx, incxy, incyx, incyy, wraparound, trans_pen);
2547 	else
2548 		copyrozbitmap_core(dest, cliprect, src, startx, starty, incxx, incxy, incyx, incyy, wraparound, priority, [trans_pen, pcode, pmask](u32 &destp, u8 &pri, const u32 &srcp) { PIXEL_OP_COPY_TRANSPEN_PRIMASK(destp, pri, srcp); });
2549 }
2550