inline void deco_zoomspr_device::dragngun_drawgfxzoom( bitmap_rgb32 &dest_bmp,const rectangle &clip,gfx_element *gfx, UINT32 code,UINT32 color,int flipx,int flipy,int sx,int sy, int transparent_color, int scalex, int scaley,bitmap_ind8 *pri_buffer,UINT32 pri_mask, int sprite_screen_width, int sprite_screen_height, UINT8 alpha, bitmap_ind8 &pri_bitmap, bitmap_rgb32 &temp_bitmap, int priority) { rectangle myclip; if (!scalex || !scaley) return; /* scalex and scaley are 16.16 fixed point numbers 1<<15 : shrink to 50% 1<<16 : uniform scale 1<<17 : double to 200% */ /* KW 991012 -- Added code to force clip to bitmap boundary */ myclip = clip; myclip &= temp_bitmap.cliprect(); { if( gfx ) { const pen_t *pal = &m_palette->pen(gfx->colorbase() + gfx->granularity() * (color % gfx->colors())); const UINT8 *code_base = gfx->get_data(code % gfx->elements()); if (sprite_screen_width && sprite_screen_height) { /* compute sprite increment per screen pixel */ int dx = (gfx->width()<<16)/sprite_screen_width; int dy = (gfx->height()<<16)/sprite_screen_height; int ex = sx+sprite_screen_width; int ey = sy+sprite_screen_height; int x_index_base; int y_index; if( flipx ) { x_index_base = (sprite_screen_width-1)*dx; dx = -dx; } else { x_index_base = 0; } if( flipy ) { y_index = (sprite_screen_height-1)*dy; dy = -dy; } else { y_index = 0; } if( sx < clip.min_x) { /* clip left */ int pixels = clip.min_x-sx; sx += pixels; x_index_base += pixels*dx; } if( sy < clip.min_y ) { /* clip top */ int pixels = clip.min_y-sy; sy += pixels; y_index += pixels*dy; } /* NS 980211 - fixed incorrect clipping */ if( ex > clip.max_x+1 ) { /* clip right */ int pixels = ex-clip.max_x-1; ex -= pixels; } if( ey > clip.max_y+1 ) { /* clip bottom */ int pixels = ey-clip.max_y-1; ey -= pixels; } if( ex>sx ) { /* skip if inner loop doesn't draw anything */ int y; /* case 1: no alpha */ if (alpha == 0xff) { { for( y=sy; y<ey; y++ ) { const UINT8 *source = code_base + (y_index>>16) * gfx->rowbytes(); UINT32 *dest = &temp_bitmap.pix32(y); UINT8 *pri = &pri_bitmap.pix8(y); int x, x_index = x_index_base; for( x=sx; x<ex; x++ ) { int c = source[x_index>>16]; if (c != transparent_color) { if (priority >= pri[x]) { dest[x] = pal[c]; dest[x] |= 0xff000000; } else // sprites can have a 'masking' effect on other sprites { dest[x] = 0x00000000; } } x_index += dx; } y_index += dy; } } } /* alpha-blended */ else { { for( y=sy; y<ey; y++ ) { const UINT8 *source = code_base + (y_index>>16) * gfx->rowbytes(); UINT32 *dest = &temp_bitmap.pix32(y); UINT8 *pri = &pri_bitmap.pix8(y); UINT32 *tmapcolor = &dest_bmp.pix32(y); int x, x_index = x_index_base; for( x=sx; x<ex; x++ ) { int c = source[x_index>>16]; if (c != transparent_color) { if (priority >= pri[x]) { // this logic doesn't seem correct. Sprites CAN blend other sprites (needed in many places) but based on videos of the character select screen it appears that sprites can't blend already blended sprites // I'm not sure which colour gets used but the video shows a single shade of yellow rather than the yellow blending the yellow) if ((dest[x] & 0xff000000) == 0x00000000) dest[x] = alpha_blend_r32(tmapcolor[x] & 0x00ffffff, pal[c] & 0x00ffffff, alpha); // if nothing has been drawn pull the pixel from the tilemap to blend with else dest[x] = alpha_blend_r32(dest[x] & 0x00ffffff, pal[c] & 0x00ffffff, alpha); // otherwise blend with what was previously drawn dest[x] |= 0xff000000; } else // sprites can have a 'masking' effect on other sprites { dest[x] = 0x00000000; } } x_index += dx; } y_index += dy; } } } }
// utility function to render a clipped scanline vertically or horizontally inline void k053250_device::pdraw_scanline32(bitmap_rgb32 &bitmap, const pen_t *pal_base, 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; 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; 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 {