void k053247_device::zdrawgfxzoom32GP( bitmap_rgb32 &bitmap, const rectangle &cliprect, uint32_t code, uint32_t color, int flipx, int flipy, int sx, int sy, int scalex, int scaley, int alpha, int drawmode, int zcode, int pri, uint8_t* gx_objzbuf, uint8_t* gx_shdzbuf) { #define FP 19 #define FPONE (1<<FP) #define FPHALF (1<<(FP-1)) #define FPENT 0 // inner loop const uint8_t *src_ptr; int src_x; int eax, ecx; int src_fx, src_fdx; int shdpen; uint8_t z8 = 0, p8 = 0; uint8_t *ozbuf_ptr; uint8_t *szbuf_ptr; const pen_t *pal_base; const pen_t *shd_base; uint32_t *dst_ptr; // outter loop int src_fby, src_fdy, src_fbx; const uint8_t *src_base; int dst_w, dst_h; // one-time int nozoom, granularity; int src_fw, src_fh; int dst_minx, dst_maxx, dst_miny, dst_maxy; int dst_skipx, dst_skipy, dst_x, dst_y, dst_lastx, dst_lasty; int src_pitch, dst_pitch; // cull illegal and transparent objects if (!scalex || !scaley) return; // find shadow pens and cull invisible shadows granularity = shdpen = m_gfx->granularity(); shdpen--; if (zcode >= 0) { if (drawmode == 5) { drawmode = 4; shdpen = 1; } } else if (drawmode >= 4) return; // alpha blend necessary? if (drawmode & 2) { if (alpha <= 0) return; if (alpha >= 255) drawmode &= ~2; } // fill internal data structure with default values ozbuf_ptr = gx_objzbuf; szbuf_ptr = gx_shdzbuf; src_pitch = 16; src_fw = 16; src_fh = 16; src_base = m_gfx->get_data(code % m_gfx->elements()); pal_base = palette().pens() + m_gfx->colorbase() + (color % m_gfx->colors()) * granularity; shd_base = palette().shadow_table(); dst_ptr = &bitmap.pix32(0); dst_pitch = bitmap.rowpixels(); dst_minx = cliprect.min_x; dst_maxx = cliprect.max_x; dst_miny = cliprect.min_y; dst_maxy = cliprect.max_y; dst_x = sx; dst_y = sy; // cull off-screen objects if (dst_x > dst_maxx || dst_y > dst_maxy) return; nozoom = (scalex == 0x10000 && scaley == 0x10000); if (nozoom) { dst_h = dst_w = 16; src_fdy = src_fdx = 1; } else { dst_w = ((scalex<<4)+0x8000)>>16; dst_h = ((scaley<<4)+0x8000)>>16; if (!dst_w || !dst_h) return; src_fw <<= FP; src_fh <<= FP; src_fdx = src_fw / dst_w; src_fdy = src_fh / dst_h; } dst_lastx = dst_x + dst_w - 1; if (dst_lastx < dst_minx) return; dst_lasty = dst_y + dst_h - 1; if (dst_lasty < dst_miny) return; // clip destination dst_skipx = 0; eax = dst_minx; if ((eax -= dst_x) > 0) { dst_skipx = eax; dst_w -= eax; dst_x = dst_minx; } eax = dst_lastx; if ((eax -= dst_maxx) > 0) dst_w -= eax; dst_skipy = 0; eax = dst_miny; if ((eax -= dst_y) > 0) { dst_skipy = eax; dst_h -= eax; dst_y = dst_miny; } eax = dst_lasty; if ((eax -= dst_maxy) > 0) dst_h -= eax; // calculate zoom factors and clip source if (nozoom) { if (!flipx) src_fbx = 0; else { src_fbx = src_fw - 1; src_fdx = -src_fdx; } if (!flipy) src_fby = 0; else { src_fby = src_fh - 1; src_fdy = -src_fdy; src_pitch = -src_pitch; } } else { if (!flipx) src_fbx = FPENT; else { src_fbx = src_fw - FPENT - 1; src_fdx = -src_fdx; } if (!flipy) src_fby = FPENT; else { src_fby = src_fh - FPENT - 1; src_fdy = -src_fdy; } } src_fbx += dst_skipx * src_fdx; src_fby += dst_skipy * src_fdy; // adjust insertion points and pre-entry constants eax = (dst_y - dst_miny) * GX_ZBUFW + (dst_x - dst_minx) + dst_w; z8 = (uint8_t)zcode; p8 = (uint8_t)pri; ozbuf_ptr += eax; szbuf_ptr += eax << 1; dst_ptr += dst_y * dst_pitch + dst_x + dst_w; dst_w = -dst_w; if (!nozoom) { ecx = src_fby; src_fby += src_fdy; ecx >>= FP; src_fx = src_fbx; src_x = src_fbx; src_fx += src_fdx; ecx <<= 4; src_ptr = src_base; src_x >>= FP; src_ptr += ecx; ecx = dst_w; if (zcode < 0) // no shadow and z-buffering { do { do { eax = src_ptr[src_x]; src_x = src_fx; src_fx += src_fdx; src_x >>= FP; if (!eax || eax >= shdpen) continue; dst_ptr [ecx] = pal_base[eax]; } while (++ecx); ecx = src_fby; src_fby += src_fdy; dst_ptr += dst_pitch; ecx >>= FP; src_fx = src_fbx; src_x = src_fbx; src_fx += src_fdx; ecx <<= 4; src_ptr = src_base; src_x >>= FP; src_ptr += ecx; ecx = dst_w; } while (--dst_h); } else { switch (drawmode)
static inline void K053936GP_copyroz32clip( running_machine &machine, bitmap_rgb32 &dst_bitmap, bitmap_ind16 &src_bitmap, const rectangle &dst_cliprect, const rectangle &src_cliprect, UINT32 _startx,UINT32 _starty,int _incxx,int _incxy,int _incyx,int _incyy, int tilebpp, int blend, int alpha, int clip, int pixeldouble_output, palette_device *palette ) { static const int colormask[8]={1,3,7,0xf,0x1f,0x3f,0x7f,0xff}; int cy, cx; int ecx; int src_pitch, incxy, incxx; int src_minx, src_maxx, src_miny, src_maxy, cmask; UINT16 *src_base; size_t src_size; const pen_t *pal_base; int dst_ptr; int dst_size; int dst_base2; int tx, dst_pitch; UINT32 *dst_base; int starty, incyy, startx, incyx, ty, sx, sy; incxy = _incxy; incxx = _incxx; incyy = _incyy; incyx = _incyx; starty = _starty; startx = _startx; if (clip) // set source clip range to some extreme values when disabled { src_minx = src_cliprect.min_x; src_maxx = src_cliprect.max_x; src_miny = src_cliprect.min_y; src_maxy = src_cliprect.max_y; } // this simply isn't safe to do! else { src_minx = src_miny = -0x10000; src_maxx = src_maxy = 0x10000; } // set target clip range sx = dst_cliprect.min_x; tx = dst_cliprect.max_x - sx + 1; sy = dst_cliprect.min_y; ty = dst_cliprect.max_y - sy + 1; startx += sx * incxx + sy * incyx; starty += sx * incxy + sy * incyy; // adjust entry points and other loop constants dst_pitch = dst_bitmap.rowpixels(); dst_base = &dst_bitmap.pix32(0); dst_base2 = sy * dst_pitch + sx + tx; ecx = tx = -tx; tilebpp = (tilebpp-1) & 7; pal_base = palette->pens(); cmask = colormask[tilebpp]; src_pitch = src_bitmap.rowpixels(); src_base = &src_bitmap.pix16(0); src_size = src_bitmap.width() * src_bitmap.height(); dst_size = dst_bitmap.width() * dst_bitmap.height(); dst_ptr = 0;//dst_base; cy = starty; cx = startx; if (blend > 0) { dst_ptr += dst_pitch; // draw blended starty += incyy; startx += incyx; do { do { int srcx = (cx >> 16) & 0x1fff; int srcy = (cy >> 16) & 0x1fff; int pixel; UINT32 offs; offs = srcy * src_pitch + srcx; cx += incxx; cy += incxy; if (offs>=src_size) continue; if (srcx < src_minx || srcx > src_maxx || srcy < src_miny || srcy > src_maxy) continue; pixel = src_base[offs]; if (!(pixel & cmask)) continue; if ((dst_ptr+ecx+dst_base2)<dst_size) dst_base[dst_ptr+ecx+dst_base2] = alpha_blend_r32(pal_base[pixel], dst_base[dst_ptr+ecx+dst_base2], alpha); if (pixeldouble_output) { ecx++; if ((dst_ptr+ecx+dst_base2)<dst_size) dst_base[dst_ptr+ecx+dst_base2] = alpha_blend_r32(pal_base[pixel], dst_base[dst_ptr+ecx+dst_base2], alpha); } } while (++ecx < 0); ecx = tx; dst_ptr += dst_pitch; cy = starty; starty += incyy; cx = startx; startx += incyx; } while (--ty); }
// utility function to render a clipped scanline vertically or horizontally inline void k053250_device::pdraw_scanline32(bitmap_rgb32 &bitmap, const pen_t *palette, UINT8 *source, const rectangle &cliprect, int linepos, int scroll, int zoom, UINT32 clipmask, UINT32 wrapmask, UINT32 orientation, bitmap_ind8 &priority, UINT8 pri) { // a sixteen-bit fixed point resolution should be adequate to our application #define FIXPOINT_PRECISION 16 #define FIXPOINT_PRECISION_HALF (1<<(FIXPOINT_PRECISION-1)) int end_pixel, flip, dst_min, dst_max, dst_start, dst_length; UINT32 src_wrapmask; UINT8 *src_base; int src_fx, src_fdx; int pix_data, dst_offset; const pen_t *pal_base; UINT8 *pri_base; UINT32 *dst_base; int dst_adv; // flip X and flip Y also switch role when the X Y coordinates are swapped if (!(orientation & ORIENTATION_SWAP_XY)) { flip = orientation & ORIENTATION_FLIP_X; dst_min = cliprect.min_x; dst_max = cliprect.max_x; } else { flip = orientation & ORIENTATION_FLIP_Y; dst_min = cliprect.min_y; dst_max = cliprect.max_y; } if (clipmask) { // reject scanlines that are outside of the target bitmap's right(bottom) clip boundary dst_start = -scroll; if (dst_start > dst_max) return; // calculate target length dst_length = clipmask + 1; if (zoom) dst_length = (dst_length << 6) / zoom; // reject scanlines that are outside of the target bitmap's left(top) clip boundary end_pixel = dst_start + dst_length - 1; if (end_pixel < dst_min) return; // clip scanline tail if ((end_pixel -= dst_max) > 0) dst_length -= end_pixel; // reject 0-length scanlines if (dst_length <= 0) return; // calculate zoom factor src_fdx = zoom << (FIXPOINT_PRECISION-6); // clip scanline head end_pixel = dst_min; if ((end_pixel -= dst_start) > 0) { // chop scanline to the correct length and move target start location to the left(top) clip boundary dst_length -= end_pixel; dst_start = dst_min; // and skip the source for the left(top) clip region src_fx = end_pixel * src_fdx + FIXPOINT_PRECISION_HALF; } else // the point five bias is to ensure even distribution of stretched or shrinked pixels src_fx = FIXPOINT_PRECISION_HALF; // adjust flipped source if (flip) { // start from the target's clipped end if the scanline is flipped dst_start = dst_max + dst_min - dst_start - (dst_length-1); // and move source start location to the opposite end src_fx += (dst_length-1) * src_fdx - 1; src_fdx = -src_fdx; } } else { // draw wrapped scanline at virtual bitmap boundary when source clipping is off dst_start = dst_min; dst_length = dst_max - dst_min + 1; // target scanline spans the entire visible area src_fdx = zoom << (FIXPOINT_PRECISION-6); // pre-advance source for the clipped region if (!flip) src_fx = (scroll + dst_min) * src_fdx + FIXPOINT_PRECISION_HALF; else { src_fx = (scroll + dst_max) * src_fdx + FIXPOINT_PRECISION_HALF-1; src_fdx = -src_fdx; } } if (!(orientation & ORIENTATION_SWAP_XY)) { // calculate target increment for horizontal scanlines which is exactly one dst_adv = 1; dst_offset = dst_length; pri_base = &priority.pix8(linepos, dst_start + dst_offset); dst_base = &bitmap.pix32(linepos, dst_start + dst_length); } else { // calculate target increment for vertical scanlines which is the bitmap's pitch value dst_adv = bitmap.rowpixels(); dst_offset= dst_length * dst_adv; pri_base = &priority.pix8(dst_start, linepos + dst_offset); dst_base = &bitmap.pix32(dst_start, linepos + dst_offset); } // generalized src_base = source; // there is no need to wrap source offsets along with source clipping // so we set all bits of the wrapmask to one src_wrapmask = (clipmask) ? ~0 : wrapmask; pal_base = palette; dst_offset = -dst_offset; // negate target offset in order to terminated draw loop at 0 condition if (pri) { // draw scanline and update priority bitmap do { pix_data = src_base[(src_fx>>FIXPOINT_PRECISION) & src_wrapmask]; src_fx += src_fdx; if (pix_data) { pix_data = pal_base[pix_data]; pri_base[dst_offset] = pri; dst_base[dst_offset] = pix_data; } } while (dst_offset += dst_adv); } else { // draw scanline but do not update priority bitmap do {
/* mix & blend the paletted 16-bit tile and sprite bitmaps into an RGB 32-bit bitmap */ static void blendbitmaps(running_machine &machine, bitmap_rgb32 &dest,bitmap_ind16 &src1,bitmap_ind16 &src2,bitmap_ind16 &src3, int sx,int sy,const rectangle &clip) { int ox; int oy; int ex; int ey; /* check bounds */ ox = sx; oy = sy; ex = sx + src1.width() - 1; if (sx < 0) sx = 0; if (sx < clip.min_x) sx = clip.min_x; if (ex >= dest.width()) ex = dest.width() - 1; if (ex > clip.max_x) ex = clip.max_x; if (sx > ex) return; ey = sy + src1.height() - 1; if (sy < 0) sy = 0; if (sy < clip.min_y) sy = clip.min_y; if (ey >= dest.height()) ey = dest.height() - 1; if (ey > clip.max_y) ey = clip.max_y; if (sy > ey) return; { const pen_t *paldata = machine.pens; UINT32 *end; UINT16 *sd1 = &src1.pix16(0); UINT16 *sd2 = &src2.pix16(0); UINT16 *sd3 = &src3.pix16(0); int sw = ex-sx+1; /* source width */ int sh = ey-sy+1; /* source height */ int sm = src1.rowpixels(); /* source modulo */ UINT32 *dd = &dest.pix32(sy, sx); /* dest data */ int dm = dest.rowpixels(); /* dest modulo */ sd1 += (sx-ox); sd1 += sm * (sy-oy); sd2 += (sx-ox); sd2 += sm * (sy-oy); sd3 += (sx-ox); sd3 += sm * (sy-oy); sm -= sw; dm -= sw; while (sh) { #define BLENDPIXEL(x) if (sd3[x]) { \ if (sd2[x]) { \ dd[x] = paldata[sd2[x] | 0x0400] + paldata[sd3[x]]; \ } else { \ dd[x] = paldata[sd1[x] | 0x0400] + paldata[sd3[x]]; \ } \ } else { \ if (sd2[x]) { \ if (sd2[x] & 0x0800) { \ dd[x] = paldata[sd1[x] | 0x0400] + paldata[sd2[x]]; \ } else { \ dd[x] = paldata[sd2[x]]; \ } \ } else { \ dd[x] = paldata[sd1[x]]; \ } \ } end = dd + sw; while (dd <= end - 8) { BLENDPIXEL(0); BLENDPIXEL(1); BLENDPIXEL(2); BLENDPIXEL(3); BLENDPIXEL(4); BLENDPIXEL(5); BLENDPIXEL(6); BLENDPIXEL(7); dd += 8; sd1 += 8; sd2 += 8; sd3 += 8; } while (dd < end) { BLENDPIXEL(0); dd++; sd1++; sd2++; sd3++; } dd += dm; sd1 += sm; sd2 += sm; sd3 += sm; sh--; #undef BLENDPIXEL } } }