Пример #1
0
		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);
		}
Пример #2
0
	//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;
	}
Пример #3
0
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;
			}
		}
	}
}
Пример #4
0
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;
			}
		}
	}
}
Пример #5
0
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;
}
Пример #6
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;
}
Пример #7
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;
}
Пример #8
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;
         }
     }
 }
Пример #9
0
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];
				}
			}
		}
	}
}
Пример #10
0
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;
	}
}
Пример #11
0
// 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];
				}
			}
		}
	}
}
Пример #12
0
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;
}
Пример #13
0
long bottom(const rectangle& r) { return r.bottom(); }
Пример #14
0
////////////////////////////////////////////////////////////
/// 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 );
    }
}
Пример #15
0
////////////////////////////////////////////////////////////
/// 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 );
    }

}
Пример #16
0
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];
						}
					}
				}
			}
		}
	}
}
Пример #17
0
/*
    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);
					}
				}
			}
		}
	}
Пример #18
0
	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;
	}