Example #1
0
/**
 * Adds velocities and creates clipping rectangles for all the
 * objects that have moved on the specified object list.
 * @param pObjList			Playfield display list to draw
 * @param pWin				Playfield window top left position
 * @param pClip				Playfield clipping rectangle
 * @param bNoVelocity		When reset, objects pos is updated with velocity
 * @param bScrolled)		When set, playfield has scrolled
 */
void FindMovingObjects(OBJECT **pObjList, Common::Point *pWin, Common::Rect *pClip, bool bNoVelocity, bool bScrolled) {
	OBJECT *pObj;			// object list traversal pointer

	for (pObj = *pObjList; pObj != NULL; pObj = pObj->pNext) {
		if (!bNoVelocity) {
			// we want to add velocities to objects position

			if (bScrolled) {
				// this playfield has scrolled

				// indicate change
				pObj->flags |= DMA_CHANGED;
			}
		}

		if ((pObj->flags & DMA_CHANGED) ||	// object changed
			HasPalMoved(pObj->pPal)) {	// or palette moved
			// object has changed in some way

			Common::Rect rcClip;	// objects clipped bounding rectangle
			Common::Rect rcObj;	// objects bounding rectangle

			// calc intersection of objects previous bounding rectangle
			// NOTE: previous position is in screen co-ords
			if (IntersectRectangle(rcClip, pObj->rcPrev, *pClip)) {
				// previous position is within clipping rect
				AddClipRect(rcClip);
			}

			// calc objects current bounding rectangle
			if (pObj->flags & DMA_ABS) {
				// object position is absolute
				rcObj.left = fracToInt(pObj->xPos);
				rcObj.top  = fracToInt(pObj->yPos);
			} else {
				// object position is relative to window
				rcObj.left = fracToInt(pObj->xPos) - pWin->x;
				rcObj.top  = fracToInt(pObj->yPos) - pWin->y;
			}
			rcObj.right  = rcObj.left + pObj->width;
			rcObj.bottom = rcObj.top  + pObj->height;

			// calc intersection of object with clipping rect
			if (IntersectRectangle(rcClip, rcObj, *pClip)) {
				// current position is within clipping rect
				AddClipRect(rcClip);

				// update previous position
				pObj->rcPrev = rcClip;
			} else {
				// clear previous position
				pObj->rcPrev = Common::Rect();
			}

			// clear changed flag
			pObj->flags &= ~DMA_CHANGED;
		}
	}
}
Example #2
0
/**
 * Deletes an object from the specified object list and places it
 * on the free list.
 * @param pObjList			List to delete object from
 * @param pDelObj			Object to delete
 */
void DelObject(OBJECT *pObjList, OBJECT *pDelObj) {
	OBJECT *pPrev, *pObj;	// object list traversal pointers
	const Common::Rect rcScreen(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);

	// validate object pointer
	assert(isValidObject(pDelObj));

#ifdef DEBUG
	// one less object in use
	--numObj;
	assert(numObj >= 0);
#endif

	for (pPrev = pObjList, pObj = pObjList->pNext; pObj != NULL; pPrev = pObj, pObj = pObj->pNext) {
		if (pObj == pDelObj) {
			// found object to delete

			if (IntersectRectangle(pDelObj->rcPrev, pDelObj->rcPrev, rcScreen)) {
				// allocate a clipping rect for objects previous pos
				AddClipRect(pDelObj->rcPrev);
			}

			// make PREV next = OBJ next - removes OBJ from list
			pPrev->pNext = pObj->pNext;

			// place free list in OBJ next
			pObj->pNext = pFreeObjects;

			// add OBJ to top of free list
			pFreeObjects = pObj;

			// delete objects palette
			if (pObj->pPal)
				FreePalette(pObj->pPal);

			// quit
			return;
		}
	}

	// if we get to here - object has not been found on the list
	// This can be triggered in Act 3 in DW1 while talking to the guard,
	// so this has been turned to a warning instead of an error
	warning("DelObject(): formally 'assert(0)!'");
}
Example #3
0
void DrawBackgnd() {
	int i;			// playfield counter
	PLAYFIELD *pPlay;	// playfield pointer
	int prevX, prevY;	// save interger part of position
	Common::Point ptWin;	// window top left

	if (pCurBgnd == NULL)
		return;		// no current background

	// scroll each background playfield
	for (i = 0; i < pCurBgnd->numPlayfields; i++) {
		// get pointer to correct playfield
		pPlay = pCurBgnd->fieldArray + i;

		// save integer part of position
		prevX = fracToInt(pPlay->fieldX);
		prevY = fracToInt(pPlay->fieldY);

		// update scrolling
		pPlay->fieldX += pPlay->fieldXvel;
		pPlay->fieldY += pPlay->fieldYvel;

		// convert fixed point window pos to a int
		ptWin.x = fracToInt(pPlay->fieldX);
		ptWin.y = fracToInt(pPlay->fieldY);

		// set the moved flag if the playfield has moved
		if (prevX != ptWin.x || prevY != ptWin.y)
			pPlay->bMoved = true;

		// sort the display list for this background - just in case somebody has changed object Z positions
		SortObjectList((OBJECT *)&pPlay->pDispList);

		// generate clipping rects for all objects that have moved etc.
		FindMovingObjects((OBJECT *)&pPlay->pDispList, &ptWin,
			&pPlay->rcClip,	false, pPlay->bMoved);

		// clear playfield moved flag
		pPlay->bMoved = false;
	}

	// merge the clipping rectangles
	MergeClipRect();

	// redraw all playfields within the clipping rectangles
	const RectList &clipRects = GetClipRects();
	for (RectList::const_iterator r = clipRects.begin(); r != clipRects.end(); ++r) {
		// clear the clip rectangle on the virtual screen
		// for each background playfield
		for (i = 0; i < pCurBgnd->numPlayfields; i++) {
			Common::Rect rcPlayClip;	// clip rect for this playfield

			// get pointer to correct playfield
			pPlay = pCurBgnd->fieldArray + i;

			// convert fixed point window pos to a int
			ptWin.x = fracToInt(pPlay->fieldX);
			ptWin.y = fracToInt(pPlay->fieldY);

			if (IntersectRectangle(rcPlayClip, pPlay->rcClip, *r))
				// redraw all objects within this clipping rect
				UpdateClipRect((OBJECT *)&pPlay->pDispList,
						&ptWin,	&rcPlayClip);
		}
	}

	// transfer any new palettes to the video DAC
	PalettesToVideoDAC();

	// update the screen within the clipping rectangles
	for (RectList::const_iterator r = clipRects.begin(); r != clipRects.end(); ++r) {
		UpdateScreenRect(*r);
	}

	g_system->updateScreen();

	// delete all the clipping rectangles
	ResetClipRect();
}
Example #4
0
//---------------------------------------------------------------------------
// x, y is position
// xs, ys is starting position on source bitmap (x, y is upper left) + xs, ys )
// w, h is height and width of the image to use.
// default behavior is to omit copying 0 pixels for transparency
// overlays....
 void  BlotImageSizedEx ( ImageFile *pifDest, ImageFile *pifSrc
                              , int32_t xd, int32_t yd
                              , int32_t xs, int32_t ys
                              , uint32_t ws, uint32_t hs
                              , uint32_t nTransparent
                              , uint32_t method
                              , ... )
{
#define BROKEN_CODE
	PCDATA po, pi;
	//int  hd, wd;
	uint32_t oo, oi; // treated as an adder... it is unsigned by math, but still results correct offset?
	static uint32_t lock;
	va_list colors;
	va_start( colors, method );
	if( nTransparent > ALPHA_TRANSPARENT_MAX )
		return;

	if(  !pifSrc
		|| !pifSrc->image
		|| !pifDest
		//|| !pifDest->image

	  )
	{
		// this will happen when mixing modes...
		lprintf( WIDE( "sanity check failed %p %p %p" ), pifSrc, pifDest, pifSrc?pifSrc->image:NULL );
		return;
	}
	//lprintf( WIDE( "BlotImageSized %d,%d to %d,%d by %d,%d" ), xs, ys, xd, yd, ws, hs );

	{
		IMAGE_RECTANGLE r1;
		IMAGE_RECTANGLE r2;
		IMAGE_RECTANGLE rs;
		IMAGE_RECTANGLE rd;
		int tmp;
		//IMAGE_RECTANGLE r3;
		r1.x = xd;
		r1.y = yd;
		r1.width = ws;
		r1.height = hs;
		r2.x = pifDest->eff_x;
		r2.y = pifDest->eff_y;
		tmp = (pifDest->eff_maxx - pifDest->eff_x) + 1;
		if( tmp < 0 )
			r2.width = 0;
		else
			r2.width = (IMAGE_SIZE_COORDINATE)tmp;
		tmp = (pifDest->eff_maxy - pifDest->eff_y) + 1;
		if( tmp < 0 )
			r2.height = 0;
		else
			r2.height = (IMAGE_SIZE_COORDINATE)tmp;
		if( !IntersectRectangle( &rd, &r1, &r2 ) )
		{
			//lprintf( WIDE( "Images do not overlap. %d,%d %d,%d vs %d,%d %d,%d" ), r1.x,r1.y,r1.width,r1.height
			//		 , r2.x,r2.y,r2.width,r2.height);
			return;
		}

		//lprintf( WIDE( "Correcting coordinates by %d,%d" )
		//		 , rd.x - xd
		//		 , rd.y - yd
		//		 );

		xs += rd.x - xd;
		ys += rd.y - yd;
		tmp = rd.x - xd;
		if( tmp > 0 && (unsigned)tmp > ws )
			ws = 0;
		else
		{
			if( tmp < 0 )
				ws += (unsigned)-tmp;
			else
				ws -= (unsigned)tmp;
		}
		tmp = rd.y - yd;
		if( tmp > 0 && (unsigned)tmp > hs )
			hs = 0;
		else
		{
			if( tmp < 0 )
				hs += (unsigned)-tmp;
			else
				hs -= (unsigned)tmp;
		}
		//lprintf( WIDE( "Resulting dest is %d,%d %d,%d" ), rd.x,rd.y,rd.width,rd.height );
		xd = rd.x;
		yd = rd.y;
		r1.x = xs;
		r1.y = ys;
		r1.width = ws;
		r1.height = hs;
		r2.x = pifSrc->eff_x;
		r2.y = pifSrc->eff_y;
		tmp = (pifSrc->eff_maxx - pifSrc->eff_x) + 1;
		if( tmp < 0 )
			r2.width = 0;
		else
			r2.width = (IMAGE_SIZE_COORDINATE)tmp;
		tmp = (pifSrc->eff_maxy - pifSrc->eff_y) + 1;
		if( tmp < 0 )
			r2.height = 0;
		else
			r2.height = (IMAGE_SIZE_COORDINATE)tmp;
		if( !IntersectRectangle( &rs, &r1, &r2 ) )
		{
			lprintf( WIDE( "Desired Output does not overlap..." ) );
			return;
		}
		//lprintf( WIDE( "Resulting dest is %d,%d %d,%d" ), rs.x,rs.y,rs.width,rs.height );
		ws = rs.width<rd.width?rs.width:rd.width;
		hs = rs.height<rd.height?rs.height:rd.height;
		xs = rs.x;
		ys = rs.y;
		//lprintf( WIDE( "Resulting rect is %d,%d to %d,%d dim: %d,%d" ), rs.x, rs.y, rd.x, rd.y, rs.width, rs.height );
		//lprintf( WIDE( "Resulting rect is %d,%d to %d,%d dim: %d,%d" ), xs, ys, xd, yd, ws, hs );
	}
		//lprintf( WIDE(WIDE( "Doing image (%d,%d)-(%d,%d) (%d,%d)-(%d,%d)" )), xs, ys, ws, hs, xd, yd, wd, hd );
	if( (int32_t)ws <= 0 ||
        (int32_t)hs <= 0 /*||
        (int32_t)wd <= 0 ||
		(int32_t)hd <= 0 */ )
	{
		lprintf( WIDE( "out of bounds" ) );
		return;
	}
#ifdef _INVERT_IMAGE
	// set pointer in to the starting x pixel
	// on the last line of the image to be copied
	//pi = IMG_ADDRESS( pifSrc, xs, ys );
	//po = IMG_ADDRESS( pifDest, xd, yd );
	pi = IMG_ADDRESS( pifSrc, xs, ys );
	po = IMG_ADDRESS( pifDest, xd, yd );
//cpg 19 Jan 2007 2>c:\work\sack\src\imglib\blotdirect.c(492) : warning C4146: unary minus operator applied to unsigned type, result still unsigned
//cpg 19 Jan 2007 2>c:\work\sack\src\imglib\blotdirect.c(493) : warning C4146: unary minus operator applied to unsigned type, result still unsigned
	oo = 4*-(int)(ws+pifDest->pwidth);     // w is how much we can copy...
	oi = 4*-(int)(ws+pifSrc->pwidth); // adding remaining width...
#else
	// set pointer in to the starting x pixel
	// on the first line of the image to be copied...
	pi = IMG_ADDRESS( pifSrc, xs, ys );
	po = IMG_ADDRESS( pifDest, xd, yd );
	oo = 4*(pifDest->pwidth - ws);     // w is how much we can copy...
	oi = 4*(pifSrc->pwidth - ws); // adding remaining width...
#endif
	//lprintf( WIDE("Doing image (%d,%d)-(%d,%d) (%d,%d)-(%d,%d)"), xs, ys, ws, hs, xd, yd, wd, hd );
	//oo = 4*(pifDest->pwidth - ws);     // w is how much we can copy...
	//oi = 4*(pifSrc->pwidth - ws); // adding remaining width...
	while( LockedExchange( &lock, 1 ) )
		Relinquish();

	if( ( pifDest->flags & IF_FLAG_FINAL_RENDER )
		&& !( pifDest->flags & IF_FLAG_IN_MEMORY ) )
	{
		Image topmost_parent;

		ReloadOpenGlTexture( pifSrc, 0 );
		if( !pifSrc->glActiveSurface )
		{
	        //lprintf( WIDE( "gl texture hasn't updated or went away?" ) );
		    lock = 0;
			return;
		}
		//lprintf( WIDE( "use regular texture %p (%d,%d)" ), pifSrc, pifSrc->width, pifSrc->height );
      //DebugBreak();        g

		// closed loop to get the top imgae size.
		for( topmost_parent = pifSrc; topmost_parent->pParent; topmost_parent = topmost_parent->pParent );

		/*
		 * only a portion of the image is actually used, the rest is filled with blank space
		 *
		 */
		TranslateCoord( pifDest, &xd, &yd );
		TranslateCoord( pifSrc, &xs, &ys );
		{
			int glDepth = 1;
			double x_size, x_size2, y_size, y_size2;
			VECTOR v1[2], v3[2],v4[2],v2[2];
			int v = 0;

			v1[v][0] = xd;
			v1[v][1] = yd;
			v1[v][2] = 0.0;

			v2[v][0] = xd;
			v2[v][1] = yd+hs;
			v2[v][2] = 0.0;

			v3[v][0] = xd+ws;
			v3[v][1] = yd+hs;
			v3[v][2] = 0.0;

			v4[v][0] = xd+ws;
			v4[v][1] = yd;
			v4[v][2] = 0.0;

			x_size = (double) xs/ (double)topmost_parent->width;
			x_size2 = (double) (xs+ws)/ (double)topmost_parent->width;
			y_size = (double) ys/ (double)topmost_parent->height;
			y_size2 = (double) (ys+hs)/ (double)topmost_parent->height;
			// Front Face
			//glColor4ub( 255,120,32,192 );
			//lprintf( WIDE( "Texture size is %g,%g to %g,%g" ), x_size, y_size, x_size2, y_size2 );
			while( pifDest && pifDest->pParent )
			{
				glDepth = 0;
				if( pifDest->transform )
				{
					Apply( pifDest->transform, v1[1-v], v1[v] );
					Apply( pifDest->transform, v2[1-v], v2[v] );
					Apply( pifDest->transform, v3[1-v], v3[v] );
					Apply( pifDest->transform, v4[1-v], v4[v] );
					v = 1-v;
				}
				pifDest = pifDest->pParent;
			}
			if( pifDest->transform )
			{
				Apply( pifDest->transform, v1[1-v], v1[v] );
				Apply( pifDest->transform, v2[1-v], v2[v] );
				Apply( pifDest->transform, v3[1-v], v3[v] );
				Apply( pifDest->transform, v4[1-v], v4[v] );
				v = 1-v;
			}
#if 0
			if( glDepth )
			{
				//lprintf( WIDE( "enqable depth..." ) );
				glEnable( GL_DEPTH_TEST );
			}
			else
			{
				//lprintf( WIDE( "disable depth..." ) );
				glDisable( GL_DEPTH_TEST );
			}
#endif
			glBindTexture(GL_TEXTURE_2D, pifSrc->glActiveSurface);				// Select Our Texture
			if( method == BLOT_COPY )
				glColor4ub( 255,255,255,255 );
			else if( method == BLOT_SHADED )
			{
				CDATA tmp = va_arg( colors, CDATA );
				glColor4ubv( (GLubyte*)&tmp );
			}
			else if( method == BLOT_MULTISHADE )
			{
#if !defined( __ANDROID__ )
				InitShader();
				if( glUseProgram && l.glActiveSurface->shader.multi_shader )
				{
					int err;
					CDATA r = va_arg( colors, CDATA );
					CDATA g = va_arg( colors, CDATA );
					CDATA b = va_arg( colors, CDATA );
		 			glEnable(GL_FRAGMENT_PROGRAM_ARB);
					glUseProgram( l.glActiveSurface->shader.multi_shader );
					err = glGetError();
					glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, 0, (float)GetRedValue( r )/255.0f, (float)GetGreenValue( r )/255.0f, (float)GetBlueValue( r )/255.0f, (float)GetAlphaValue( r )/255.0f );
					err = glGetError();
					glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, 1, (float)GetRedValue( g )/255.0f, (float)GetGreenValue( g )/255.0f, (float)GetBlueValue( g )/255.0f, (float)GetAlphaValue( g )/255.0f );
					err = glGetError();
					glProgramLocalParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, 2, (float)GetRedValue( b )/255.0f, (float)GetGreenValue( b )/255.0f, (float)GetBlueValue( b )/255.0f, (float)GetAlphaValue( b )/255.0f );					
					err = glGetError();
				}
				else
#endif
				{
					Image output_image;
					CDATA r = va_arg( colors, CDATA );
					CDATA g = va_arg( colors, CDATA );
					CDATA b = va_arg( colors, CDATA );
					output_image = GetShadedImage( pifSrc, r, g, b );
					glBindTexture( GL_TEXTURE_2D, output_image->glActiveSurface );
					glColor4ub( 255,255,255,255 );
				}
			}
			else if( method == BLOT_INVERTED )
			{
#if !defined( __ANDROID__ )
				InitShader();
				if( l.glActiveSurface->shader.inverse_shader )
				{
					int err;
		 			glEnable(GL_FRAGMENT_PROGRAM_ARB);
					glUseProgram( l.glActiveSurface->shader.inverse_shader );
					err = glGetError();
				}
				else
#endif
				{
					Image output_image;
					output_image = GetInvertedImage( pifSrc );
					glBindTexture( GL_TEXTURE_2D, output_image->glActiveSurface );
					glColor4ub( 255,255,255,255 );
				}
			}
			glBegin(GL_TRIANGLE_STRIP);
			//glBegin(GL_QUADS);
			scale( v1[v], v1[v], l.scale );
			scale( v2[v], v2[v], l.scale );
			scale( v3[v], v3[v], l.scale );
			scale( v4[v], v4[v], l.scale );
			glTexCoord2f(x_size, y_size); glVertex3fv(v1[v]);	// Bottom Left Of The Texture and Quad
			glTexCoord2f(x_size, y_size2); glVertex3fv(v2[v]);	// Top Left Of The Texture and Quad
			glTexCoord2f(x_size2, y_size); glVertex3fv(v4[v]);	// Bottom Right Of The Texture and Quad
			glTexCoord2f(x_size2, y_size2); glVertex3fv(v3[v]);	// Top Right Of The Texture and Quad
			// Back Face
			glEnd();
#if !defined( __ANDROID__ )
			if( method == BLOT_MULTISHADE )
			{
				if( l.glActiveSurface->shader.multi_shader )
				{
 					glDisable(GL_FRAGMENT_PROGRAM_ARB);
				}
			}
			else if( method == BLOT_INVERTED )
			{
				if( l.glActiveSurface->shader.inverse_shader )
				{
 					glDisable(GL_FRAGMENT_PROGRAM_ARB);
				}
			}
#endif
			glBindTexture(GL_TEXTURE_2D, 0);				// Select Our Texture
		}
	}
	else
	{
		switch( method )
		{
		case BLOT_COPY:
			if( !nTransparent )
				CopyPixelsT0( po, pi, oo, oi, ws, hs );
			else if( nTransparent == 1 )
				CopyPixelsT1( po, pi, oo, oi, ws, hs );
			else if( nTransparent & ALPHA_TRANSPARENT )
				CopyPixelsTImgA( po, pi, oo, oi, ws, hs, nTransparent & 0xFF);
			else if( nTransparent & ALPHA_TRANSPARENT_INVERT )
				CopyPixelsTImgAI( po, pi, oo, oi, ws, hs, nTransparent & 0xFF );
			else
				CopyPixelsTA( po, pi, oo, oi, ws, hs, nTransparent );
			break;
		case BLOT_SHADED:
			if( !nTransparent )
				CopyPixelsShadedT0( po, pi, oo, oi, ws, hs
                           , va_arg( colors, CDATA ) );
			else if( nTransparent == 1 )
				CopyPixelsShadedT1( po, pi, oo, oi, ws, hs
                           , va_arg( colors, CDATA ) );
			else if( nTransparent & ALPHA_TRANSPARENT )
				CopyPixelsShadedTImgA( po, pi, oo, oi, ws, hs, nTransparent & 0xFF
                           , va_arg( colors, CDATA ) );
			else if( nTransparent & ALPHA_TRANSPARENT_INVERT )
				CopyPixelsShadedTImgAI( po, pi, oo, oi, ws, hs, nTransparent & 0xFF
                           , va_arg( colors, CDATA ) );
			else
				CopyPixelsShadedTA( po, pi, oo, oi, ws, hs, nTransparent
                           , va_arg( colors, CDATA ) );
			break;
		case BLOT_MULTISHADE:
			{
				CDATA r,g,b;
				r = va_arg( colors, CDATA );
				g = va_arg( colors, CDATA );
				b = va_arg( colors, CDATA );
				//lprintf( WIDE( "r g b %08x %08x %08x" ), r,g, b );
				if( !nTransparent )
					CopyPixelsMultiT0( po, pi, oo, oi, ws, hs
										  , r, g, b );
				else if( nTransparent == 1 )
					CopyPixelsMultiT1( po, pi, oo, oi, ws, hs
										  , r, g, b );
				else if( nTransparent & ALPHA_TRANSPARENT )
					CopyPixelsMultiTImgA( po, pi, oo, oi, ws, hs, nTransparent & 0xFF
											  , r, g, b );
				else if( nTransparent & ALPHA_TRANSPARENT_INVERT )
					CopyPixelsMultiTImgAI( po, pi, oo, oi, ws, hs, nTransparent & 0xFF
												, r, g, b );
				else
					CopyPixelsMultiTA( po, pi, oo, oi, ws, hs, nTransparent
										  , r, g, b );
			}
			break;
		}
		MarkImageUpdated( pifDest );
	}
	lock = 0;
	//lprintf( WIDE( "Image done.." ) );
}