static void draw_vdp(mame_bitmap *bitmap, const rectangle *cliprect, int priority) { int x, y; for (y = cliprect->min_y; y <= cliprect->max_y; y++) { UINT16 *src = BITMAP_ADDR16(tempbitmap, y, 0); UINT16 *dst = BITMAP_ADDR16(bitmap, y, 0); UINT8 *pri = BITMAP_ADDR8(priority_bitmap, y, 0); for (x = cliprect->min_x; x <= cliprect->max_x; x++) { UINT16 pix = src[x]; if (pix != 0xffff) { dst[x] = pix; pri[x] |= priority; } } } }
static void draw_vdp(const device_config *screen, bitmap_t *bitmap, const rectangle *cliprect, int priority) { int x, y; bitmap_t *priority_bitmap = screen->machine->priority_bitmap; for (y = cliprect->min_y; y <= cliprect->max_y; y++) { UINT16 *src = BITMAP_ADDR16(tempbitmap, y, 0); UINT16 *dst = BITMAP_ADDR16(bitmap, y, 0); UINT8 *pri = BITMAP_ADDR8(priority_bitmap, y, 0); for (x = cliprect->min_x; x <= cliprect->max_x; x++) { UINT16 pix = src[x]; if (pix != 0xffff) { dst[x] = pix; pri[x] |= priority; } } } }
static void draw_vdp(device_t *screen, bitmap_t *bitmap, const rectangle *cliprect, int priority) { segas1x_state *state = screen->machine().driver_data<segas1x_state>(); int x, y; bitmap_t *priority_bitmap = screen->machine().priority_bitmap; for (y = cliprect->min_y; y <= cliprect->max_y; y++) { UINT16 *src = BITMAP_ADDR16(state->m_tmp_bitmap, y, 0); UINT16 *dst = BITMAP_ADDR16(bitmap, y, 0); UINT8 *pri = BITMAP_ADDR8(priority_bitmap, y, 0); for (x = cliprect->min_x; x <= cliprect->max_x; x++) { UINT16 pix = src[x]; if (pix != 0xffff) { dst[x] = pix; pri[x] |= priority; } } } }
static void draw_sprites( running_machine *machine, bitmap_t *bitmap, const rectangle *cliprect ) { UINT16 *source = spriteram_old; UINT16 *finish = source + (spriteram_size/2)/2; int global_x = mcatadv_vidregs[0]-0x184; int global_y = mcatadv_vidregs[1]-0x1f1; UINT16 *destline; UINT8 *priline; UINT8 *sprdata = memory_region ( machine, "gfx1" ); int xstart, xend, xinc; int ystart, yend, yinc; if( vidregs_old[2] == 0x0001 ) /* Double Buffered */ { source += (spriteram_size/2)/2; finish += (spriteram_size/2)/2; } else if( vidregs_old[2] ) /* I suppose it's possible that there is 4 banks, haven't seen it used though */ { logerror("Spritebank != 0/1\n"); } while ( source<finish ) { int pen = (source[0]&0x3f00)>>8; int tileno = source[1]&0xffff; int pri = (source[0]&0xc000)>>14; int x = source[2]&0x3ff; int y = source[3]&0x3ff; int flipy = source[0] & 0x0040; int flipx = source[0] & 0x0080; int height = ((source[3]&0xf000)>>12)*16; int width = ((source[2]&0xf000)>>12)*16; int offset = tileno * 256; int drawxpos, drawypos; int xcnt,ycnt; int pix; if (x & 0x200) x-=0x400; if (y & 0x200) y-=0x400; #if 0 // For Flipscreen/Cocktail if(mcatadv_vidregs[0]&0x8000) { flipx = !flipx; } if(mcatadv_vidregs[1]&0x8000) { flipy = !flipy; } #endif if (source[3] != source[0]) // 'hack' don't draw sprites while its testing the ram! { if(!flipx) { xstart = 0; xend = width; xinc = 1; } else { xstart = width-1; xend = -1; xinc = -1; } if(!flipy) { ystart = 0; yend = height; yinc = 1; } else { ystart = height-1; yend = -1; yinc = -1; } for (ycnt = ystart; ycnt != yend; ycnt += yinc) { drawypos = y+ycnt-global_y; if ((drawypos >= cliprect->min_y) && (drawypos <= cliprect->max_y)) { destline = BITMAP_ADDR16(bitmap, drawypos, 0); priline = BITMAP_ADDR8(machine->priority_bitmap, drawypos, 0); for (xcnt = xstart; xcnt != xend; xcnt += xinc) { drawxpos = x+xcnt-global_x; if((priline[drawxpos] < pri)) { if (offset >= 0x500000*2) offset = 0; pix = sprdata[offset/2]; if (offset & 1) pix = pix >> 4; pix &= 0x0f; if ((drawxpos >= cliprect->min_x) && (drawxpos <= cliprect->max_x) && pix) destline[drawxpos] = (pix + (pen << 4)); } offset++; } } else { offset += width; } } }
static void draw_sprite(running_machine *machine, mame_bitmap *bitmap, const rectangle *cliprect, const UINT8 *addr, int pitch, const pen_t *paldata, int x0, int y0, int screen_width, int screen_height, int width, int height, int flipx, int flipy, int priority, int shadow, int shadow_pen, int eos ) { const pen_t *shadow_base = machine->remapped_colortable + machine->gfx[0]->color_base + (machine->drv->total_colors/2); const UINT8 *source; int full_shadow=shadow&SYS16_SPR_SHADOW; int partial_shadow=shadow&SYS16_SPR_PARTIAL_SHADOW; int shadow_mask=(machine->drv->total_colors/2)-1; int sx, x, xcount; int sy, y, ycount = 0; int dx,dy; UINT16 *dest; UINT8 *pri; unsigned pen, data; priority = 1<<priority; if( flipy ){ dy = -1; y0 += screen_height-1; } else { dy = 1; } if( flipx ){ dx = -1; x0 += screen_width-1; } else { dx = 1; } if (!eos) { sy = y0; for( y=height; y; y-- ){ ycount += screen_height; while( ycount>=height ){ if( sy>=cliprect->min_y && sy<=cliprect->max_y ){ source = addr; dest = BITMAP_ADDR16(bitmap, sy, 0); pri = BITMAP_ADDR8(priority_bitmap, sy, 0); sx = x0; xcount = 0; for( x=width; x; x-=2 ){ data = (unsigned)*source++; /* next 2 pixels */ pen = data>>4; xcount += screen_width; while( xcount>=width ) { if( pen && pen!=0xf && sx>=cliprect->min_x && sx<=cliprect->max_x ){ if(!(pri[sx]&priority)){ if (full_shadow) dest[sx] = shadow_base[dest[sx]&shadow_mask]; else if (partial_shadow && pen==shadow_pen) dest[sx] = shadow_base[dest[sx]&shadow_mask]; else dest[sx] = paldata[pen]; } } xcount -= width; sx+=dx; } pen = data&0xf; xcount += screen_width; while( xcount>=width ) { if( pen && pen!=0xf && sx>=cliprect->min_x && sx<=cliprect->max_x ){ if(!(pri[sx]&priority)){ if (full_shadow) dest[sx] = shadow_base[dest[sx]&shadow_mask]; else if (partial_shadow && pen==shadow_pen) dest[sx] = shadow_base[dest[sx]&shadow_mask]; else dest[sx] = paldata[pen]; } } xcount -= width; sx+=dx; } } } ycount -= height; sy+=dy; } addr += pitch; }
static void taito_f2_tc360_spritemixdraw( running_machine *machine, bitmap_t *dest_bmp, const rectangle *clip, const gfx_element *gfx, UINT32 code, UINT32 color, int flipx, int flipy, int sx, int sy, int scalex, int scaley ) { taitof2_state *state = machine->driver_data<taitof2_state>(); int pal_base = gfx->color_base + gfx->color_granularity * (color % gfx->total_colors); const UINT8 *source_base = gfx_element_get_data(gfx, code % gfx->total_elements); bitmap_t *priority_bitmap = gfx->machine->priority_bitmap; int sprite_screen_height = (scaley * gfx->height + 0x8000) >> 16; int sprite_screen_width = (scalex * gfx->width + 0x8000) >> 16; if (!scalex || !scaley) return; 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 (clip) { 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; for (y = sy; y < ey; y++) { const UINT8 *source = source_base + (y_index >> 16) * gfx->line_modulo; UINT16 *dest = BITMAP_ADDR16(dest_bmp, y, 0); UINT8 *pri = BITMAP_ADDR8(priority_bitmap, y, 0); int x, x_index = x_index_base; for (x = sx; x < ex; x++) { int c = source[x_index >> 16]; if (c && (pri[x] & 0x80) == 0) { UINT8 tilemap_priority = 0, sprite_priority = 0; // Get tilemap priority (0 - 0xf) for this destination pixel if (pri[x] & 0x10) tilemap_priority = state->tilepri[4]; else if (pri[x] & 0x8) tilemap_priority = state->tilepri[3]; else if (pri[x] & 0x4) tilemap_priority = state->tilepri[2]; else if (pri[x] & 0x2) tilemap_priority = state->tilepri[1]; else if (pri[x] & 0x1) tilemap_priority = state->tilepri[0]; // Get sprite priority (0 - 0xf) for this source pixel if ((color & 0xc0) == 0xc0) sprite_priority = state->spritepri[3]; else if ((color & 0xc0) == 0x80) sprite_priority = state->spritepri[2]; else if ((color & 0xc0) == 0x40) sprite_priority = state->spritepri[1]; else if ((color & 0xc0) == 0x00) sprite_priority = state->spritepri[0]; // Blend mode 1 - Sprite under tilemap, use sprite palette with tilemap data if ((state->spriteblendmode & 0xc0) == 0xc0 && sprite_priority == (tilemap_priority - 1)) { dest[x] = ((pal_base + c) & 0xfff0) | (dest[x] & 0xf); } // Blend mode 1 - Sprite over tilemap, use sprite data with tilemap palette else if ((state->spriteblendmode & 0xc0) == 0xc0 && sprite_priority == (tilemap_priority + 1)) { if (dest[x] & 0xf) dest[x] = (dest[x] & 0xfff0) | ((pal_base + c) & 0xf); else dest[x] = pal_base + c; } // Blend mode 2 - Sprite under tilemap, use sprite data with tilemap palette else if ((state->spriteblendmode & 0xc0) == 0x80 && sprite_priority == (tilemap_priority - 1)) { dest[x] = (dest[x] & 0xffef); } // Blend mode 2 - Sprite over tilemap, alternate sprite palette, confirmed in Pulirula level 2 else if ((state->spriteblendmode & 0xc0) == 0x80 && sprite_priority == (tilemap_priority + 1)) { dest[x] = ((pal_base + c) & 0xffef); // Pulirula level 2, Liquid Kids attract mode } // No blending else { if (sprite_priority > tilemap_priority) // Ninja Kids confirms tilemap takes priority in equal value case dest[x] = pal_base + c; } pri[x] |= 0x80; } x_index += dx; } y_index += dy; } }
// utility function to render a clipped scanline vertically or horizontally inline void k053250_t::pdraw_scanline32(bitmap_t *bitmap, const pen_t *palette, UINT8 *source, const rectangle *cliprect, int linepos, int scroll, int zoom, UINT32 clipmask, UINT32 wrapmask, UINT32 orientation, bitmap_t *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 zero-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 = BITMAP_ADDR8(priority, linepos, dst_start + dst_offset); dst_base = BITMAP_ADDR32(bitmap, 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 = BITMAP_ADDR8(priority, dst_start, linepos + dst_offset); dst_base = BITMAP_ADDR32(bitmap, 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 zero 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 {
void deco_bac06_device::custom_tilemap_draw(running_machine &machine, bitmap_t *bitmap, const rectangle *cliprect, tilemap_t *tilemap_ptr, const UINT16 *rowscroll_ptr, const UINT16 *colscroll_ptr, const UINT16 *control0, const UINT16 *control1, int flags, UINT16 penmask, UINT16 pencondition, UINT16 colprimask, UINT16 colpricondition ) { const bitmap_t *src_bitmap = tilemap_get_pixmap(tilemap_ptr); const bitmap_t *flags_bitmap = tilemap_get_flagsmap(tilemap_ptr); int x, y, p, colpri; int column_offset=0, src_x=0, src_y=0; UINT32 scrollx = 0; UINT32 scrolly = 0; if (control1) { scrollx = control1[0]; scrolly = control1[1]; } int width_mask; int height_mask; int row_scroll_enabled = 0; int col_scroll_enabled = 0; if (control0) { row_scroll_enabled = (rowscroll_ptr && (control0[0]&0x4)); col_scroll_enabled = (colscroll_ptr && (control0[0]&0x8)); } if (!src_bitmap) return; width_mask = src_bitmap->width - 1; height_mask = src_bitmap->height - 1; /* Column scroll & row scroll may per applied per pixel, there are shift registers for each which control the granularity of the row/col offset (down to per line level for row, and per 8 lines for column). Nb: The row & col selectors are _not_ affected by the shape of the playfield (ie, 256*1024, 512*512 or 1024*256). So even if the tilemap width is only 256, 'src_x' should not wrap at 256 in the code below (to do so would mean the top half of row RAM would never be accessed which is incorrect). Nb2: Real hardware exhibits a strange bug with column scroll on 'mode 2' (256*1024) - the first column has a strange additional offset, but curiously the first 'wrap' (at scroll offset 256) does not have this offset, it is displayed as expected. The bug is confimed to only affect this mode, the other two modes work as expected. This bug is not emulated, as it doesn't affect any games. */ if (flip_screen_get(machine)) src_y = (src_bitmap->height - 256) - scrolly; else src_y = scrolly; for (y=0; y<=cliprect->max_y; y++) { if (row_scroll_enabled) src_x=scrollx + rowscroll_ptr[(src_y >> (control1[3]&0xf))&(0x1ff>>(control1[3]&0xf))]; else src_x=scrollx; if (flip_screen_get(machine)) src_x=(src_bitmap->width - 256) - src_x; for (x=0; x<=cliprect->max_x; x++) { if (col_scroll_enabled) column_offset=colscroll_ptr[((src_x >> 3) >> (control1[2]&0xf))&(0x3f>>(control1[2]&0xf))]; p = *BITMAP_ADDR16(src_bitmap, (src_y + column_offset)&height_mask, src_x&width_mask); colpri = *BITMAP_ADDR8(flags_bitmap, (src_y + column_offset)&height_mask, src_x&width_mask)&0xf; src_x++; if ((flags&TILEMAP_DRAW_OPAQUE) || (p&m_bppmask)) { if ((p&penmask)==pencondition) if((colpri&colprimask)==colpricondition) *BITMAP_ADDR16(bitmap, y, x) = p+(colpri&m_gfxcolmask)*m_bppmult; } } src_y++; }