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