void draw_corner_point(::nana::paint::graphics& graph, const rectangle& r) { graph.set_pixel(r.x, r.y); graph.set_pixel(r.right() - 1, r.y); graph.set_pixel(r.right() - 1, r.bottom() - 1); graph.set_pixel(r.x, r.bottom() - 1); }
//covered test if r2 covers r1. bool covered(const rectangle& r1, //Rectangle 1 is must under rectangle 2 const rectangle& r2) //Rectangle 2 { if(r1.x < r2.x || r1.right() > r2.right()) return false; if(r1.y < r2.y || r1.bottom() > r2.bottom()) return false; return true; }
void madalien_state::draw_headlight(bitmap_ind16 &bitmap, const rectangle &cliprect, int flip) { if (BIT(*m_video_flags, 0)) { uint8_t y; for (y = 0; y < 0x80; y++) { uint8_t x; uint8_t hy = y - *m_headlight_pos; if (flip) hy = ~hy; if ((hy < cliprect.top()) || (hy > cliprect.bottom())) continue; for (x = 0; x < 0x80; x++) { uint8_t hx = x; if (flip) hx = ~hx; if ((hx < cliprect.left()) || (hx > cliprect.right())) continue; if (m_headlight_bitmap->pix16(y, x) != 0) bitmap.pix16(hy, hx) |= 8; } } } }
void namcos21_state::winrun_bitmap_draw(bitmap_ind16 &bitmap, const rectangle &cliprect) { uint8_t *videoram = m_gpu_videoram.get(); //printf("%d %d (%d %d) - %04x %04x %04x|%04x %04x\n",cliprect.top(),cliprect.bottom(),m_screen->vpos(),m_gpu_intc->get_posirq_line(),m_winrun_gpu_register[0],m_winrun_gpu_register[2/2],m_winrun_gpu_register[4/2],m_winrun_gpu_register[0xa/2],m_winrun_gpu_register[0xc/2]); int yscroll = -cliprect.top()+(int16_t)m_winrun_gpu_register[0x2/2]; int xscroll = 0;//m_winrun_gpu_register[0xc/2] >> 7; int base = 0x1000+0x100*(m_winrun_color&0xf); int sx,sy; for( sy=cliprect.top(); sy<=cliprect.bottom(); sy++ ) { const uint8_t *pSource = &videoram[((yscroll+sy)&0x3ff)*0x200]; uint16_t *pDest = &bitmap.pix16(sy); for( sx=cliprect.left(); sx<=cliprect.right(); sx++ ) { int pen = pSource[(sx+xscroll) & 0x1ff]; switch( pen ) { case 0xff: break; // TODO: additive blending? winrun car select uses register [0xc] for a xscroll value case 0x00: pDest[sx] = (pDest[sx]&0x1fff)+0x4000; break; case 0x01: pDest[sx] = (pDest[sx]&0x1fff)+0x6000; break; default: pDest[sx] = base|pen; break; } } } }
uint32_t dragngun_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { screen.priority().fill(0, cliprect); bitmap.fill(m_palette->pen(0x400), cliprect); // Palette index not confirmed m_deco_tilegen[0]->pf_update(m_pf_rowscroll[0].get(), m_pf_rowscroll[1].get()); m_deco_tilegen[1]->pf_update(m_pf_rowscroll[2].get(), m_pf_rowscroll[3].get()); m_deco_tilegen[1]->tilemap_2_draw(screen, bitmap, cliprect, 0, 1); // it uses pf3 in 8bpp mode instead, like captaven m_deco_tilegen[1]->tilemap_1_draw(screen, bitmap, cliprect, 0, 2); m_deco_tilegen[0]->tilemap_2_draw(screen, bitmap, cliprect, 0, 4); m_deco_tilegen[0]->tilemap_1_draw(screen, bitmap, cliprect, 0, 8); // zooming sprite draw is very slow, and sprites are buffered.. however, one of the levels attempts to use // partial updates for every line, which causes things to be very slow... the sprites appear to support // multiple layers of alpha, so rendering to a buffer for layer isn't easy (maybe there are multiple sprite // chips at work?) // // really, it needs optimizing .. // so for now we only draw these 2 layers on the last update call if (cliprect.bottom() == 247) { rectangle clip(cliprect.left(), cliprect.right(), 8, 247); m_sprgenzoom->dragngun_draw_sprites(bitmap,clip,m_spriteram->buffer(), m_sprite_layout_ram[0], m_sprite_layout_ram[1], m_sprite_lookup_ram[0], m_sprite_lookup_ram[1], m_sprite_ctrl, screen.priority(), m_temp_render_bitmap ); } return 0; }
uint32_t casloopy_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { gfx_element *gfx = m_gfxdecode->gfx(m_gfx_index); int x,y; int count; static int test; if(machine().input().code_pressed(KEYCODE_Z)) test+=0x100; if(machine().input().code_pressed(KEYCODE_X)) test-=0x100; //popmessage("%08x",test); #if 0 int r,g,b; r = pal5bit((m_vregs[0x4/4] >> 10) & 0x1f); g = pal5bit((m_vregs[0x4/4] >> 5) & 0x1f); b = pal5bit((m_vregs[0x4/4] >> 0) & 0x1f); m_palette->set_pen_color(0x100,rgb_t(r^0xff,g^0xff,b^0xff)); bitmap.fill( 0x100 ,cliprect); #endif count = test; for (y=0;y<32;y++) { for (x=0;x<32;x++) { uint16_t tile = (m_vram[count+1])|(m_vram[count]<<8); tile &= 0x7ff; //??? gfx->transpen(bitmap,cliprect,tile,7,0,0,x*8,y*8,0xffffffff); count+=2; } } count = test; for (y=cliprect.top(); y<cliprect.bottom(); y++) // FIXME: off-by-one? { for(x=0;x<256;x++) { uint8_t pix; pix = m_bitmap_vram[count]; if(pix) bitmap.pix16(y, x) = pix + 0x100; count++; } } return 0; }
uint32_t madalien_state::screen_update_madalien(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { int flip = BIT(ioport("DSW")->read(), 6) && BIT(*m_video_control, 0); // bits #0 and #1 define scrolling mode // // mode 0 - cycle over map section A // mode 1 - cycle over map section B // // mode 2 - transition from B to A // mode 3 - transition from A to B int scroll_mode = *m_scroll & 3; bitmap.fill(0, cliprect); draw_edges(screen, bitmap, cliprect, flip, scroll_mode); draw_foreground(screen, bitmap, cliprect, flip); /* highlight section A (outside of tunnels). * also, bit 1 of the video_flags register (6A) is * combined with the headlight signal through NOR gate 1A, * which is used to light up the tunnel when an alien explodes */ if (scroll_mode != 1 || *m_video_flags & 2) { int x; int y; int min_x = 0; int max_x = 0xff; if (!(*m_video_flags & 2)) { if (scroll_mode == 2) min_x = (*m_scroll & 0xfc); else if (scroll_mode == 3) max_x = (*m_scroll & 0xfc) - 1; } if (flip) { int max_x_save = max_x; max_x = 0xff - min_x; min_x = 0xff - max_x_save; } for (y = cliprect.top(); y <= cliprect.bottom(); y++) for (x = min_x; x <= max_x; x++) if ((x >= cliprect.left()) && (x <= cliprect.right())) bitmap.pix16(y, x) |= 8; } draw_headlight(bitmap, cliprect, flip); return 0; }
void dc::fill_or(unsigned int color, const rectangle<int> & rt) { int x2 = rt.right(); int y2 = rt.bottom(); for (int y = rt.top(); y < y2; y++) { for (int x = rt.left(); x < x2; x++) { (*this)[y][x] |= color; } } }
void dassault_state::mixdassaultlayer(bitmap_rgb32 &bitmap, bitmap_ind16* sprite_bitmap, const rectangle &cliprect, uint16_t pri, uint16_t primask, uint16_t penbase, uint8_t alpha) { int y, x; const pen_t *paldata = &m_palette->pen(0); uint16_t* srcline; uint32_t* dstline; for (y=cliprect.top();y<=cliprect.bottom();y++) { srcline=&sprite_bitmap->pix16(y,0); dstline=&bitmap.pix32(y,0); for (x=cliprect.left();x<=cliprect.right();x++) { uint16_t pix = srcline[x]; if ((pix & primask) != pri) continue; if (pix&0xf) { uint16_t pen = pix&0x1ff; if (pix & 0x800) pen += 0x200; if (alpha!=0xff) { if (pix&0x400) // TODO, Additive/Subtractive Blending? { uint32_t base = dstline[x]; dstline[x] = alpha_blend_r32(base, paldata[pen+penbase], alpha); } else if (pix&0x200) { uint32_t base = dstline[x]; dstline[x] = alpha_blend_r32(base, paldata[pen+penbase], alpha); } else { dstline[x] = paldata[pen+penbase]; } } else { dstline[x] = paldata[pen+penbase]; } } } } }
void tc0100scn_device::tilemap_draw_fg( screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, tilemap_t* tmap, int flags, u8 priority, u8 pmask ) { const bitmap_ind16 &src_bitmap = tmap->pixmap(); int width_mask, height_mask, x, y, p; int column_offset, src_x = 0, src_y = 0; int scrollx_delta = - tmap->scrolldx(); int scrolly_delta = - tmap->scrolldy(); width_mask = src_bitmap.width() - 1; height_mask = src_bitmap.height() - 1; src_y = (m_fgscrolly + scrolly_delta) & height_mask; if (m_ctrl[0x7] & 1) // Flipscreen src_y = (256 - src_y) & height_mask; //We use cliprect.max_y and cliprect.max_x to support games which use more than 1 screen src_y += cliprect.top(); // Row offsets are 'screen space' 0-255 regardless of Y scroll for (y = cliprect.top(); y <= cliprect.bottom(); y++) { src_x = (m_fgscrollx - m_fgscroll_ram[(y + scrolly_delta) & 0x1ff] + scrollx_delta + cliprect.min_x) & width_mask; if (m_ctrl[0x7] & 1) // Flipscreen src_x = (256 - 64 - src_x) & width_mask; // Col offsets are 'tilemap' space 0-511, and apply to blocks of 8 pixels at once for (x = 0; x < cliprect.width(); x++) { column_offset = m_colscroll_ram[(src_x & 0x3ff) / 8]; p = src_bitmap.pix16((src_y - column_offset) & height_mask, src_x); if ((p & 0xf)!= 0 || (flags & TILEMAP_DRAW_OPAQUE)) { bitmap.pix16(y, x + cliprect.min_x) = p; if (screen.priority().valid()) { u8 *pri = &screen.priority().pix8(y); pri[x + cliprect.min_x] = (pri[x + cliprect.min_x] & pmask) | priority; } } src_x = (src_x + 1) & width_mask; } src_y = (src_y + 1) & height_mask; } }
// not amazingly efficient, called multiple times to pull a layer out of the sprite bitmaps, but keeps correct sprite<->sprite priorities void rohga_state::mixwizdfirelayer(bitmap_rgb32 &bitmap, const rectangle &cliprect, uint16_t pri, uint16_t primask) { int y, x; const pen_t *paldata = m_palette->pens(); bitmap_ind16* sprite_bitmap; int penbase; sprite_bitmap = &m_sprgen[1]->get_sprite_temp_bitmap(); penbase = 0x600; uint16_t* srcline; uint32_t* dstline; for (y=cliprect.top();y<=cliprect.bottom();y++) { srcline=&sprite_bitmap->pix16(y,0); dstline=&bitmap.pix32(y,0); for (x=cliprect.left();x<=cliprect.right();x++) { uint16_t pix = srcline[x]; if ((pix & primask) != pri) continue; if (pix&0xf) { uint16_t pen = pix&0x1ff; if (pen&0x100) { uint32_t base = dstline[x]; pen &=0xff; dstline[x] = alpha_blend_r32(base, paldata[pen+penbase], 0x80); } else { dstline[x] = paldata[pen+penbase]; } } } } }
uint8_t mermaid_state::collision_check( rectangle& rect ) { uint8_t data = 0; int x; int y; for (y = rect.top(); y <= rect.bottom(); y++) for (x = rect.left(); x <= rect.right(); x++) { uint16_t a = m_palette->pen_indirect(m_helper.pix16(y, x)) & 0x3f; uint16_t b = m_palette->pen_indirect(m_helper2.pix16(y, x)) & 0x3f; if (b) if (a) data |= 0x01; } return data; }
long bottom(const rectangle& r) { return r.bottom(); }
//////////////////////////////////////////////////////////// /// Toogle button style //////////////////////////////////////////////////////////// void TBtStyle::draw_toggle_button( const canvas& c, const rectangle& rect, const bool enabled, const font& mfont, const long lastx, const long lasty, const ustring& name, const bool is_depressed, const bool is_checked ) const { rectangle area = rect.intersect( c ); if ( area.is_empty() ) return; unsigned char red, green, blue; if ( enabled ) { red = 0; green = 0; blue = 0; } else { red = 128; green = 128; blue = 128; } // compute the name length if it hasn't already been computed if ( name_width == 0 ) { unsigned long height; mfont.compute_size( name, name_width, height ); } // figure out where the name string should appear rectangle name_rect; const unsigned long width = name_width; const unsigned long height = mfont.height(); name_rect.set_left(( rect.right() + rect.left() - width ) / 2 ); name_rect.set_top(( rect.bottom() + rect.top() - height ) / 2 + 1 ); name_rect.set_right( name_rect.left() + width - 1 ); name_rect.set_bottom( name_rect.top() + height ); long d = 0; if ( is_checked ) d = 1; if ( is_depressed ) d = 2; name_rect.set_left( name_rect.left() + d ); name_rect.set_right( name_rect.right() + d ); name_rect.set_top( name_rect.top() + d ); name_rect.set_bottom( name_rect.bottom() + d ); // now draw the edge of the button if ( is_checked || is_depressed ) { fill_rect_with_vertical_gradient( c, rect, rgb_pixel( 233, 241, 246 ), rgb_pixel( 197, 220, 232 ) ); mfont.draw_string( c, name_rect, name, rgb_pixel( red, green, blue ) ); draw_button_down( c, rect ); } else { fill_rect_with_vertical_gradient( c, rect, rgb_pixel( 241, 241, 241 ), rgb_pixel( 210, 210, 210 ) ); mfont.draw_string( c, name_rect, name, rgb_pixel( red, green, blue ) ); draw_button_up( c, rect ); } }
//////////////////////////////////////////////////////////// /// ButtonArrow style //////////////////////////////////////////////////////////// void arrowBtStyle::draw_button( const canvas& c, const rectangle& rect, const bool enabled, const font& mfont, const long lastx, const long lasty, const ustring& name, const bool is_depressed ) const { rectangle area = rect.intersect( c ); if ( area.is_empty() ) return; const long height = rect.height(); const long width = rect.width(); const long smallest = ( width < height ) ? width : height; const long rows = ( smallest + 3 ) / 4; const long start = rows + rows / 2 - 1; long dep; long tip_x = 0; long tip_y = 0; long wy = 0; long hy = 0; long wx = 0; long hx = 0; if ( is_depressed ) { dep = 0; fill_rect_with_vertical_gradient( c, rect, rgb_pixel( 164, 213, 239 ), rgb_pixel( 232, 246, 253 ) ); // draw the button's border draw_button_down( c, rect ); } else { dep = -1; fill_rect_with_vertical_gradient( c, rect, rgb_pixel( 199, 199, 203 ), rgb_pixel( 242, 242, 242 ) ); // draw the button's border draw_button_up( c, rect ); } switch ( dir ) { case UP: tip_x = width / 2 + rect.left() + dep; tip_y = ( height - start ) / 2 + rect.top() + dep + 1; wy = 0; hy = 1; wx = 1; hx = 0; break; case DOWN: tip_x = width / 2 + rect.left() + dep; tip_y = rect.bottom() - ( height - start ) / 2 + dep; wy = 0; hy = -1; wx = 1; hx = 0; break; case LEFT: tip_x = rect.left() + ( width - start ) / 2 + dep + 1; tip_y = height / 2 + rect.top() + dep; wy = 1; hy = 0; wx = 0; hx = 1; break; case RIGHT: tip_x = rect.right() - ( width - start ) / 2 + dep; tip_y = height / 2 + rect.top() + dep; wy = 1; hy = 0; wx = 0; hx = -1; break; } rgb_pixel color; if ( enabled ) { color.red = 60; color.green = 60; color.blue = 60; } else { color.red = 128; color.green = 128; color.blue = 128; } for ( long i = 0; i < rows; ++i ) { draw_line( c, point( tip_x + wx*i + hx*i, tip_y + wy*i + hy*i ), point( tip_x + wx*i* -1 + hx*i, tip_y + wy*i* -1 + hy*i ), color ); } }
void rohga_state::mixnitroballlayer(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { int y, x; const pen_t *paldata = &m_palette->pen(0); bitmap_ind16 *sprite_bitmap1, *sprite_bitmap2; bitmap_ind8* priority_bitmap; uint16_t priority = m_decocomn->priority_r(); sprite_bitmap1 = &m_sprgen[0]->get_sprite_temp_bitmap(); sprite_bitmap2 = &m_sprgen[1]->get_sprite_temp_bitmap(); priority_bitmap = &screen.priority(); uint32_t* dstline; uint16_t *srcline1, *srcline2; uint8_t *srcpriline; for (y=cliprect.top();y<=cliprect.bottom();y++) { srcline1=&sprite_bitmap1->pix16(y,0); srcline2=&sprite_bitmap2->pix16(y,0); srcpriline=&priority_bitmap->pix8(y,0); dstline=&bitmap.pix32(y,0); for (x=cliprect.left();x<=cliprect.right();x++) { uint16_t pix1 = srcline1[x]; uint16_t pix2 = srcline2[x]; /* Here we have pix1 - raw pixel / colour / priority data from first 1st chip pix2 - raw pixel / colour / priority data from first 2nd chip */ int pri1, pri2; // pix1 sprite vs playfield switch (priority) // TODO : Verify this from real pcb { case 0x00: default: { switch (pix1 & 0xe00) { case 0x000: default: pri1 = 0x200; break; case 0x200: pri1 = 0x020; break; case 0x400: pri1 = 0x008; break; case 0x600: pri1 = 0x002; break; case 0x800: pri1 = 0x100; break; case 0xa00: pri1 = 0x040; break; case 0xc00: pri1 = 0x004; break; case 0xe00: pri1 = 0x001; break; } } break; case 0x20: { switch (pix1 & 0xe00) { case 0x000: default: pri1 = 0x080; break; case 0x200: pri1 = 0x004; break; case 0x400: pri1 = 0x002; break; case 0x600: pri1 = 0x001; break; case 0x800: pri1 = 0x100; break; case 0xa00: pri1 = 0x020; break; case 0xc00: pri1 = 0x008; break; case 0xe00: pri1 = 0x200; break; } } break; } // pix2 sprite vs pix1 sprite pri2 = 0x080; switch (priority) { case 0x00: default: pri2 = 0x080; break; case 0x20: pri2 = 0x010; break; } uint8_t bgpri = srcpriline[x]; /* once we get here we have pri1 - 0x001/0x002/0x004/0x008/0x010/0x020/0x040/0x080/0x100/0x200 (sprite chip 1 pixel priority relative to bg) pri2 - 0x080/0x010 (sprite chip 2 pixel priority relative to bg) bgpri - 0x008/0x040 (from drawing tilemaps earlier, to compare above pri1/pri2 priorities against) pix1 - same as before (ready to extract just colour data from) pix2 - same as before ^^ */ int drawnpixe1 = 0; if (pix1 & 0xf) { if (pri1 > bgpri) { dstline[x] = paldata[(pix1&0x1ff)+0x400]; drawnpixe1 = 1; } } if (pix2 & 0xf) { if (pri2 > bgpri) { if ((!drawnpixe1) || (pri2 > pri1)) { if (pix2 & 0x100) { uint32_t base = dstline[x]; dstline[x] = alpha_blend_r32(base, paldata[(pix2&0xff)+0x600], 0x80); } else { dstline[x] = paldata[(pix2&0xff)+0x600]; } } } } } } }
/* This function mimics the priority PROM/circuit on the pcb. It takes the tilemaps & sprite bitmaps as inputs, and outputs a final pixel based on alpha & priority values. Rendering sprites to temporary bitmaps is the only reasonable way to implement proper priority & blending support - it can't be done in-place on the final framebuffer without a lot of support bitmaps. */ void nslasher_state::mixDualAlphaSprites(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, gfx_element *gfx0, gfx_element *gfx1, int mixAlphaTilemap) { const pen_t *pens = m_deco_ace->pens(); const pen_t *pal0 = &pens[gfx0->colorbase()]; const pen_t *pal1 = &pens[gfx1->colorbase()]; const pen_t *pal2 = &pens[m_gfxdecode->gfx((m_pri & 1) ? 1 : 2)->colorbase()]; bitmap_ind16& sprite0_mix_bitmap = m_sprgen[0]->get_sprite_temp_bitmap(); bitmap_ind16& sprite1_mix_bitmap = m_sprgen[1]->get_sprite_temp_bitmap(); /* Mix sprites into main bitmap, based on priority & alpha */ for (int y = cliprect.top(); y <= cliprect.bottom(); y++) { uint8_t* tilemapPri = &screen.priority().pix8(y); uint16_t* sprite0 = &sprite0_mix_bitmap.pix16(y); uint16_t* sprite1 = &sprite1_mix_bitmap.pix16(y); uint32_t* destLine = &bitmap.pix32(y); uint16_t* alphaTilemap = &m_tilemap_alpha_bitmap->pix16(y); for (int x = cliprect.left(); x <= cliprect.right(); x++) { uint16_t const priColAlphaPal0 = sprite0[x]; uint16_t const priColAlphaPal1 = sprite1[x]; uint16_t const pri0 = (priColAlphaPal0 & 0x6000) >> 13; uint16_t const pri1 = (priColAlphaPal1 & 0x6000) >> 13; uint16_t const col0 = (((priColAlphaPal0 & 0x1f00) >> 8) % gfx0->colors()) * gfx0->granularity(); uint16_t const col1 = (((priColAlphaPal1 & 0x0f00) >> 8) % gfx1->colors()) * gfx1->granularity(); uint16_t const alpha1 = priColAlphaPal1 & 0x8000; // Apply sprite bitmap 0 according to priority rules if ((priColAlphaPal0 & 0xff) != 0) { /* Sprite 0 priority rules: 0 = Sprite above all layers 1 = Sprite under top playfield 2 = Sprite under top two playfields 3 = Sprite under all playfields */ if ((pri0 & 0x3) == 0 || (pri0 & 0x3) == 1 || ((pri0 & 0x3) == 2 && mixAlphaTilemap)) // Spri0 on top of everything, or under alpha playfield { destLine[x] = pal0[(priColAlphaPal0 & 0xff) + col0]; } else if ((pri0 & 0x3) == 2) // Spri0 under top playfield { if (tilemapPri[x] < 4) destLine[x] = pal0[(priColAlphaPal0 & 0xff) + col0]; } else // Spri0 under top & middle playfields { if (tilemapPri[x] < 2) destLine[x] = pal0[(priColAlphaPal0 & 0xff) + col0]; } } // Apply sprite bitmap 1 according to priority rules if ((priColAlphaPal1 & 0xff) != 0) { // Apply alpha for this pixel based on Ace setting if (alpha1) { /* Alpha rules: Pri 0 - Over all tilemaps, but under sprite 0 pri 0, pri 1, pri 2 Pri 1 - Pri 2 - Pri 3 - */ /* Alpha values are tied to ACE ram... */ //int alpha = m_deco_ace->get_alpha(((priColAlphaPal1 & 0xf0) >> 4) / 2); //if (alpha < 0) // alpha = 0; /* I don't really understand how object ACE ram is really hooked up, the only obvious place in Night Slashers is the stagecoach in level 2 */ if (pri1 == 0 && (((priColAlphaPal0 & 0xff) == 0 || ((pri0 & 0x3) != 0 && (pri0 & 0x3) != 1 && (pri0 & 0x3) != 2)))) { if ((m_pri & 1) == 0 || ((m_pri & 1) == 1 && tilemapPri[x] < 4) || ((m_pri & 1) == 1 && mixAlphaTilemap)) destLine[x] = alpha_blend_r32(destLine[x], pal1[(priColAlphaPal1 & 0xff) + col1], 0x80); } else if (pri1 == 1 && ((priColAlphaPal0 & 0xff) == 0 || ((pri0 & 0x3) != 0 && (pri0 & 0x3) != 1 && (pri0 & 0x3) != 2))) destLine[x] = alpha_blend_r32(destLine[x], pal1[(priColAlphaPal1 & 0xff) + col1], 0x80); else if (pri1 == 2) // TOdo destLine[x] = alpha_blend_r32(destLine[x], pal1[(priColAlphaPal1 & 0xff) + col1], 0x80); else if (pri1 == 3) // TOdo destLine[x] = alpha_blend_r32(destLine[x], pal1[(priColAlphaPal1 & 0xff) + col1], 0x80); } else { /* Non alpha rules: Pri 0 - Under sprite 0 pri 0, over all tilemaps */ if (pri1 == 0 && ((priColAlphaPal0 & 0xff) == 0 || ((pri0 & 0x3) != 0))) destLine[x] = pal1[(priColAlphaPal1 & 0xff) + col1]; else if (pri1 == 1) // todo destLine[x] = pal1[(priColAlphaPal1 & 0xff) + col1]; else if (pri1 == 2) // todo destLine[x] = pal1[(priColAlphaPal1 & 0xff) + col1]; else if (pri1 == 3) // todo destLine[x] = pal1[(priColAlphaPal1 & 0xff) + col1]; } } /* Optionally mix in alpha tilemap */ if (mixAlphaTilemap) { uint16_t p = alphaTilemap[x]; if (p & 0xf) { /* Alpha tilemap under top two sprite 0 priorities */ if (((priColAlphaPal0 & 0xff) == 0 || (pri0 & 0x3) == 2 || (pri0 & 0x3) == 3) && ((priColAlphaPal1 & 0xff) == 0 || (pri1 & 0x3) == 2 || (pri1 & 0x3) == 3 || alpha1)) { /* Alpha values are tied to ACE ram */ int alpha = m_deco_ace->get_alpha(0x17 + (((p & 0xf0) >> 4) / 2)); if (alpha < 0) alpha = 0; destLine[x] = alpha_blend_r32(destLine[x], pal2[p], alpha); } } } } }
bool intersection(const rectangle & r, point pos_beg, point pos_end, point& good_pos_beg, point& good_pos_end) { const int right = r.right(); const int bottom = r.bottom(); if(pos_beg.x > pos_end.x) std::swap(pos_beg, pos_end); bool good_beg = (0 <= pos_beg.x && pos_beg.x < right && 0 <= pos_beg.y && pos_beg.y < bottom); bool good_end = (0 <= pos_end.x && pos_end.x < right && 0 <= pos_end.y && pos_end.y < bottom); if(good_beg && good_end) { good_pos_beg = pos_beg; good_pos_end = pos_end; return true; } else if(pos_beg.x == pos_end.x) { if(r.x <= pos_beg.x && pos_beg.x < right) { if(pos_beg.y < r.y) { if(pos_end.y < r.y) return false; good_pos_beg.y = r.y; good_pos_end.y = (pos_end.y < bottom ? pos_end.y : bottom - 1); } else if(pos_beg.y >= bottom) { if(pos_end.y >= bottom) return false; good_pos_beg.y = bottom - 1; good_pos_end.y = (pos_end.y < r.y ? r.y : pos_end.y); } good_pos_beg.x = good_pos_end.x = r.x; return true; } return false; } else if(pos_beg.y == pos_end.y) { if(r.y <= pos_beg.y && pos_beg.y < bottom) { if(pos_beg.x < r.x) { if(pos_end.x < r.x) return false; good_pos_beg.x = r.x; good_pos_end.x = (pos_end.x < right ? pos_end.x : right - 1); } else if(pos_beg.x >= right) { if(pos_end.x >= right) return false; good_pos_beg.x = right - 1; good_pos_end.x = (pos_end.x < r.x ? r.x : pos_end.x); } good_pos_beg.y = good_pos_end.y = r.y; return true; } return false; } double m = (pos_end.y - pos_beg.y ) / double(pos_end.x - pos_beg.x); bool is_nw_to_se = (m >= 0.0); //The formulas for the line. //y = m * (x - pos_beg.x) + pos_beg.y //x = (y - pos_beg.y) / m + pos_beg.x if(!good_beg) { good_pos_beg.y = static_cast<int>(m * (r.x - pos_beg.x)) + pos_beg.y; if(r.y <= good_pos_beg.y && good_pos_beg.y < bottom) { good_pos_beg.x = r.x; } else { bool cond; int y; if(is_nw_to_se) { y = r.y; cond = good_pos_beg.y < y; } else { y = bottom - 1; cond = good_pos_beg.y > y; } if(cond) { good_pos_beg.x = static_cast<int>((y - pos_beg.y) / m) + pos_beg.x; if(r.x <= good_pos_beg.x && good_pos_beg.x < right) good_pos_beg.y = y; else return false; } else return false; } if(good_pos_beg.x < pos_beg.x) return false; } else good_pos_beg = pos_beg; if(!good_end) { good_pos_end.y = static_cast<int>(m * (right - 1 - pos_beg.x)) + pos_beg.y; if(r.y <= good_pos_end.y && good_pos_end.y < bottom) { good_pos_end.x = right - 1; } else { bool cond; int y; if(is_nw_to_se) { y = bottom - 1; cond = good_pos_end.y > y; } else { y = r.y; cond = good_pos_end.y < y; } if(cond) { good_pos_end.x = static_cast<int>((y - pos_beg.y) / m) + pos_beg.x; if(r.x <= good_pos_end.x && good_pos_end.x < right) good_pos_end.y = y; else return false; } else return false; } if(good_pos_end.x > pos_end.x) return false; } else good_pos_end = pos_end; return true; }