Exemple #1
0
/*
==============
Render Polygon
==============
*/ 
void PS2Polygon::Render( void ) const {
	VIFDynamicDMA.StartDirect();
	/* Add the GIFTag */
	VIFDynamicDMA.Add128( GS_GIFTAG_BATCH(	mNumOfVerts,				    // NLOOP 
											1,							    // EOP
											1,							    // PRE
											GS_PRIM( PRIM_TRI_FAN, 	        // PRIM (TRIANGLE FAN)
												PRIM_IIP_GOURAUD,           // GOURAUD SHADING
												PRIM_TME_OFF,
												PRIM_FGE_OFF, 
												PRIM_ABE_OFF, 
												PRIM_AA1_OFF,               
												PRIM_FST_UV, 
												PRIM_CTXT_CONTEXT1, 
												PRIM_FIX_NOFIXDDA ),
											GIF_FLG_PACKED,				    // FLG
											GS_BATCH_2(	GIF_REG_RGBAQ, 
														GIF_REG_XYZ2 ) ) ); // BATCH	
	for( int i = 0; i < mNumOfVerts; i++ ) {
		/* Add the colour */ 
		VIFDynamicDMA.Add128( PACKED_RGBA( pVertColours[ i ].mR, pVertColours[ i ].mG, pVertColours[ i ].mB, pVertColours[ i ].mA ) );			
		/* Add the position */
		VIFDynamicDMA.Add128( PACKED_XYZ2( ( int )( ( 2048.0f + mX + pVerts[ i ].x ) * 16.0f ), 
										   ( int )( ( 2048.0f + mY + pVerts[ i ].y ) * 16.0f ),  
										   ( int )mZ, 
										   0 ) );
	}
	VIFDynamicDMA.EndDirect();
}
Exemple #2
0
/*
=============================
Textured Quad Render Function
=============================
*/
void PS2TexQuad::Render( void ) const {
	VIFDynamicDMA.StartDirect();
	/* Add the GIFTag */
	VIFDynamicDMA.Add128( GS_GIFTAG_BATCH(	mNumOfVerts,				    // NLOOP
											1,							    // EOP
											1,							    // PRE
											GS_PRIM( PRIM_TRI_STRIP, 	    // PRIM
												PRIM_IIP_FLAT, 
												PRIM_TME_ON,
												PRIM_FGE_OFF, 
												PRIM_ABE_ON, 
												PRIM_AA1_OFF, 
												PRIM_FST_UV, 
												PRIM_CTXT_CONTEXT1, 
												PRIM_FIX_NOFIXDDA ),
											GIF_FLG_PACKED,				    // FLG
											GS_BATCH_3(	GIF_REG_RGBAQ,
														GIF_REG_UV, 
														GIF_REG_XYZ2 ) ) ); // BATCH	
	for( int i = 0; i < mNumOfVerts; i++ ) {
		/* Add the colour */
		VIFDynamicDMA.Add128( PACKED_RGBA( pVertColours[ i ].mR, pVertColours[ i ].mG, pVertColours[ i ].mB, pVertColours[ i ].mA ) );
		/* Add UV texture coordinates */ 
		VIFDynamicDMA.Add128( PACKED_UV( ( ( ( int )pTexVerts[ i ].x ) << 4 ), ( ( ( int )pTexVerts[ i ] .y ) << 4 ) ) );
		/* Add the position */  
		VIFDynamicDMA.Add128( PACKED_XYZ2( ( int )( ( 2048.0f + mX + pVerts[ i ].x ) * 16.0f ), 
										   ( int )( ( 2048.0f + mY + pVerts[ i ].y ) * 16.0f ),  
										   ( int )mZ, 
										   0 ) );
	}
	VIFDynamicDMA.EndDirect();
}
Exemple #3
0
bool Image2D::Render()
{
	Debug ("Image2D::Render called.");
	
	if (!m_active) return true;
	
	// Place texture in buffer (as needed)
	AssetManager::GetSingleton().LoadTexture(m_texture);
	
	// Render the "model" in the correct location
	
	// Determine where to render the image
	int left		= m_x - m_width/2;
	int right		= m_x + m_width/2;
	int top			= m_y - m_height/2;
	int bottom		= m_y + m_height/2;

	// Start DIRECT mode transfer
	VIFDynamicDMA.StartDirect();
									
	// Add the GIFTag
	VIFDynamicDMA.Add128(GS_GIFTAG_BATCH(	1,							// NLOOP
											1,							// EOP
											1,							// PRE
											GS_PRIM(PRIM_SPRITE, 		//PRIM
													PRIM_IIP_FLAT, 
													PRIM_TME_ON,
													PRIM_FGE_OFF, 
													PRIM_ABE_ON, 
													PRIM_AA1_OFF, 
													PRIM_FST_UV, 
													PRIM_CTXT_CONTEXT1, 
													PRIM_FIX_NOFIXDDA),					
											GIF_FLG_PACKED,				//FLG
											GS_BATCH_5(	GIF_REG_RGBAQ, 	//BATCH
														GIF_REG_UV, 
														GIF_REG_XYZ2, 
														GIF_REG_UV, 
														GIF_REG_XYZ2)));				
	// Add Vertex data
	VIFDynamicDMA.Add128(PACKED_RGBA(m_r, m_g, m_b, m_a));
	VIFDynamicDMA.Add128(PACKED_UV(0<<4, 0<<4));
	VIFDynamicDMA.Add128(PACKED_XYZ2(	(left + 2048)<< 4, 
										(top + 2048)<< 4, 
										m_depth, 
										0));						
	VIFDynamicDMA.Add128(PACKED_UV((255<<4), (255<<4)));	
	VIFDynamicDMA.Add128(PACKED_XYZ2(	(right + 2048)<< 4, 
										(bottom + 2048)<< 4, 
										m_depth, 
										0));
			
	
	// End the direct mode
	VIFDynamicDMA.EndDirect();
	
	return true;
}
// Initialise the screen clear. With this class we clear the screen much faster than SPS2 would
// usually. This puts all of the screen clear DMA data into our static DMA buffer. This means it is
// only ever added once (very fast), and is then simply CALLed from the dynamic DMA buffer.
// Notice that instead of just using one big sprite to clear the screen we use 20 long tall strips.
// This is because the GS is optimised for polygons less than or equal to 32 pixels wide, and it
// "chokes" on ones that are larger.
void CSPS2Manager::InitScreenClear(int R, int G, int B)
{
	int x0 = (2048 - (sps2UScreenGetWidth() >> 1)) << 4;
	int y0 = (2048 - (sps2UScreenGetHeight() >> 1)) << 4;
	//int x1 = (2048 + (sps2UScreenGetWidth() >> 1)) << 4;
	int y1 = (2048 + (sps2UScreenGetHeight() >> 1)) << 4;

	// Get the address of the screen clear packet so we can CALL it
	// from the dynamic packet.
	iScreenClear = VIFStaticDMA.GetPointer();

	// Start the VIF direct mode.
	VIFStaticDMA.StartDirect();

	VIFStaticDMA.Add128(GS_GIFTAG_BATCH(4 + (20 * 2), 1, 0, 0, 
						GIF_FLG_PACKED, GS_BATCH_1(GIF_REG_A_D)));

	VIFStaticDMA.Add64(TEST_SET(0, 0, 0, 0, 0, 0, 1, 1));
	VIFStaticDMA.Add64(TEST_1);

	VIFStaticDMA.Add64(PRIM_SET(0x6, 0, 0, 0, 0, 0, 0, 0, 0));
	VIFStaticDMA.Add64(PRIM);

	VIFStaticDMA.Add64(RGBAQ_SET(R, G, B, 0x80, 0x3f800000));
	VIFStaticDMA.Add64(RGBAQ);

	for(int i = 0; i < 20; i++)
	{
		VIFStaticDMA.Add64(XYZ2_SET(x0, y0, 0));
		VIFStaticDMA.Add64(XYZ2);

		VIFStaticDMA.Add64(XYZ2_SET(x0 + (32 << 4), y1, 0));
		VIFStaticDMA.Add64(XYZ2);

		x0 += (32 << 4);
	}

	VIFStaticDMA.Add64(TEST_SET(0, 0, 0, 0, 0, 0, 1, 3));
	VIFStaticDMA.Add64(TEST_1);

	VIFStaticDMA.EndDirect();

	VIFStaticDMA.DMARet();
}
// Load the cube data into static DMA memory
void Cube::LoadCubeData(void)
{
	// Check if data already loaded - return if it is.
	// We only need the cube data loaded once.
	if(Cube::iStaticAddr)return;
	
	const int iDraw = 0;
	const int iDontDraw = 1;
		
	const float fDraw = *((float *)&iDraw);
	const float fDontDraw = *((float *)&iDontDraw);
		
	printf("Loading Cube Data\n");
	
	// Get the address of static data that we can call to later.
	Cube::iStaticAddr = VIFStaticDMA.GetPointer();
	
	VIFStaticDMA.Add32(FLUSH);			// Make sure VU1 isn't busy
	VIFStaticDMA.Add32(STCYCL(1,1));	// Unpack linearly, i.e. don't skip any spaces
	VIFStaticDMA.Add32(BASE(32));		// The double buffers start at VU1 address 32 (giving us 32 QW to store data that won't change)
	VIFStaticDMA.Add32(OFFSET(496));	// The size of each buffer.


	// The first face draws two triangle
	// Next faces draw four triangles
	// Five triangles needed for last face
	// Some triangles are "zero" area and will be culled by GS
	int iTriangles = 12;
	int iVerts = iTriangles * 3;
	
	// We want to unpack 3 quad words of misc data, and then 3QW per vertex starting at
	// VU mem location 32 (we will upload the matrices to the first 16QW per frame).
	VIFStaticDMA.AddUnpack(V4_32, 0, 2 + iVerts * 3, 1);
	
	// VU32 iVerts is in position "x" LSWord of the qword
	VIFStaticDMA.Add128(iVerts*3);
	
	// Add the GIFTag VU33
	VIFStaticDMA.Add128(GS_GIFTAG_BATCH(	iVerts,						// NLOOP
	 										1,							// EOP
	 										1,							// PRE
	 										GS_PRIM(PRIM_TRI,		 	// PRIM
													PRIM_IIP_GOURAUD, 
													PRIM_TME_ON,
													PRIM_FGE_OFF, 
													PRIM_ABE_ON, 
													PRIM_AA1_OFF, 
													PRIM_FST_STQ, 
													PRIM_CTXT_CONTEXT1, 
													PRIM_FIX_NOFIXDDA),					
	 										GIF_FLG_PACKED,				// FLG
	 										GS_BATCH_3(	GIF_REG_ST,
	 													GIF_REG_RGBAQ, 	// BATCH
	 													GIF_REG_XYZ2)));
	
	// Front face
	VIFStaticDMA.AddVector(Vector4(0, 0, 1, fDraw));			// TexCoord (STQ)	
	VIFStaticDMA.AddVector(Vector4( 0, 0, 1, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(-1.0f, 1.0f, 1.0f, 1.0f));	// Vert (xyzw)
	VIFStaticDMA.AddVector(Vector4(1, 0, 1, fDraw));			// TexCoord (STQ)
	VIFStaticDMA.AddVector(Vector4( 0, 0, 1, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(1.0f,  1.0f, 1.0f, 1.0f));	// Vert (xyzw)
	VIFStaticDMA.AddVector(Vector4(0, 1, 1, fDraw));			// TexCoord (STQ)
	VIFStaticDMA.AddVector(Vector4( 0, 0, 1, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(-1.0f,-1.0f, 1.0f, 1.0f));	// Vert (xyzw)
	VIFStaticDMA.AddVector(Vector4(0, 1, 1, fDraw));			// TexCoord (STQ)
	VIFStaticDMA.AddVector(Vector4( 0, 0, 1, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(-1.0f,-1.0f, 1.0f, 1.0f));	// Vert (xyzw)
	VIFStaticDMA.AddVector(Vector4(1, 0, 1, fDraw));			// TexCoord (STQ)
	VIFStaticDMA.AddVector(Vector4( 0, 0, 1, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(1.0f,  1.0f, 1.0f, 1.0f));	// Vert (xyzw)
	VIFStaticDMA.AddVector(Vector4(1 , 1, 1, fDraw));			// TexCoord (STQ)
	VIFStaticDMA.AddVector(Vector4( 0, 0, 1, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(1.0f, -1.0f, 1.0f, 1.0f));	// Vert (xyzw)

	// Right face
	VIFStaticDMA.AddVector(Vector4(0, 0, 1, fDraw));			// TexCoord (STQ)	
	VIFStaticDMA.AddVector(Vector4( 1, 0, 0, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(1.0f, 1.0f, 1.0f, 1.0f));	// Vert (xyzw)
	VIFStaticDMA.AddVector(Vector4(1, 0, 1, fDraw));			// TexCoord (STQ)
	VIFStaticDMA.AddVector(Vector4( 1, 0, 0, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(1.0f,  1.0f, -1.0f, 1.0f));	// Vert (xyzw)
	VIFStaticDMA.AddVector(Vector4(0, 1, 1, fDraw));			// TexCoord (STQ)
	VIFStaticDMA.AddVector(Vector4( 1, 0, 0, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(1.0f,-1.0f, 1.0f, 1.0f));	// Vert (xyzw)
	VIFStaticDMA.AddVector(Vector4(0, 1, 1, fDraw));			// TexCoord (STQ)
	VIFStaticDMA.AddVector(Vector4( 1, 0, 0, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(1.0f,-1.0f, 1.0f, 1.0f));	// Vert (xyzw)
	VIFStaticDMA.AddVector(Vector4(1, 0, 1, fDraw));			// TexCoord (STQ)
	VIFStaticDMA.AddVector(Vector4( 1, 0, 0, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(1.0f, 1.0f, -1.0f, 1.0f));	// Vert (xyzw)
	VIFStaticDMA.AddVector(Vector4(1 , 1, 1, fDraw));			// TexCoord (STQ)
	VIFStaticDMA.AddVector(Vector4( 1, 0, 0, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(1.0f, -1.0f, -1.0f, 1.0f));	// Vert (xyzw)

	// Back face
	VIFStaticDMA.AddVector(Vector4(1, 0, 1, fDraw));			// TexCoord (STQ)	
	VIFStaticDMA.AddVector(Vector4( 0, 0,-1, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(-1.0f, 1.0f, -1.0f, 1.0f));	// Vert (xyzw)
	VIFStaticDMA.AddVector(Vector4(1, 1, 1, 0));				// TexCoord (STQ)
	VIFStaticDMA.AddVector(Vector4( 0, 0,-1, fDraw));			// Normal
	VIFStaticDMA.AddVector(Vector4(-1.0f,-1.0f, -1.0f, 1.0f));	// Vert (xyzw)
	VIFStaticDMA.AddVector(Vector4(0, 0, 1, 0));				// TexCoord (STQ)
	VIFStaticDMA.AddVector(Vector4( 0, 0,-1, fDraw));			// Normal
	VIFStaticDMA.AddVector(Vector4(1.0f,  1.0f, -1.0f, 1.0f));	// Vert (xyzw)
	VIFStaticDMA.AddVector(Vector4(1, 1, 1, 0));				// TexCoord (STQ)
	VIFStaticDMA.AddVector(Vector4( 0, 0,-1, fDraw));			// Normal
	VIFStaticDMA.AddVector(Vector4(-1.0f,-1.0f, -1.0f, 1.0f));	// Vert (xyzw)
	VIFStaticDMA.AddVector(Vector4(0 , 1, 1, fDraw));			// TexCoord (STQ)
	VIFStaticDMA.AddVector(Vector4( 0, 0,-1, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(1.0f, -1.0f, -1.0f, 1.0f));	// Vert (xyzw)
	VIFStaticDMA.AddVector(Vector4(0, 0, 1, fDraw));			// TexCoord (STQ)
	VIFStaticDMA.AddVector(Vector4( 0, 0,-1, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(1.0f,  1.0f, -1.0f, 1.0f));	// Vert (xyzw)

	// Left face
	VIFStaticDMA.AddVector(Vector4(1, 0, 1, fDraw));			// TexCoord (STQ)	
	VIFStaticDMA.AddVector(Vector4(-1, 0, 0, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(-1.0f, 1.0f, 1.0f, 1.0f));	// Vert (xyzw)
	VIFStaticDMA.AddVector(Vector4(0, 0, 1, fDraw));			// TexCoord (STQ)
	VIFStaticDMA.AddVector(Vector4(-1, 0, 0, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(-1.0f,  1.0f, -1.0f, 1.0f));	// Vert (xyzw)
	VIFStaticDMA.AddVector(Vector4(1, 1, 1, fDraw));			// TexCoord (STQ)
	VIFStaticDMA.AddVector(Vector4(-1, 0, 0, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(-1.0f,-1.0f, 1.0f, 1.0f));	// Vert (xyzw)
	VIFStaticDMA.AddVector(Vector4(1, 1, 1, fDraw));			// TexCoord (STQ)
	VIFStaticDMA.AddVector(Vector4(-1, 0, 0, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(-1.0f,-1.0f, 1.0f, 1.0f));	// Vert (xyzw)
	VIFStaticDMA.AddVector(Vector4(0, 0, 1, fDraw));			// TexCoord (STQ)
	VIFStaticDMA.AddVector(Vector4(-1, 0, 0, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(-1.0f, 1.0f, -1.0f, 1.0f));	// Vert (xyzw)
	VIFStaticDMA.AddVector(Vector4(0 , 1, 1, fDraw));			// TexCoord (STQ)
	VIFStaticDMA.AddVector(Vector4(-1, 0, 0, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(-1.0f, -1.0f, -1.0f, 1.0f));	// Vert (xyzw)
	
	// Top face
	VIFStaticDMA.AddVector(Vector4(1, 0, 1, fDraw));			// TexCoord (STQ)	
	VIFStaticDMA.AddVector(Vector4(0, 1, 0, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(1.0f, 1.0f, 1.0f, 1.0f));	// Vert (xyzw)
	VIFStaticDMA.AddVector(Vector4(0, 0, 1, fDraw));			// TexCoord (STQ)
	VIFStaticDMA.AddVector(Vector4(0, 1, 0, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(1.0f,  1.0f, -1.0f, 1.0f));	// Vert (xyzw)
	VIFStaticDMA.AddVector(Vector4(1, 1, 1, fDraw));			// TexCoord (STQ)
	VIFStaticDMA.AddVector(Vector4(0, 1, 0, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(-1.0f, 1.0f, 1.0f, 1.0f));	// Vert (xyzw)
	VIFStaticDMA.AddVector(Vector4(1, 1, 1, fDraw));			// TexCoord (STQ)
	VIFStaticDMA.AddVector(Vector4(0, 1, 0, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(-1.0f, 1.0f, 1.0f, 1.0f));	// Vert (xyzw)
	VIFStaticDMA.AddVector(Vector4(0, 0, 1, fDraw));			// TexCoord (STQ)
	VIFStaticDMA.AddVector(Vector4(0, 1, 0, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(1.0f, 1.0f, -1.0f, 1.0f));	// Vert (xyzw)
	VIFStaticDMA.AddVector(Vector4(0 , 1, 1, fDraw));			// TexCoord (STQ)
	VIFStaticDMA.AddVector(Vector4(0, 1, 0, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(-1.0f,  1.0f, -1.0f, 1.0f));	// Vert (xyzw)
	
	// Bottom face
	VIFStaticDMA.AddVector(Vector4(0, 0, 1, fDraw));			// TexCoord (STQ)	
	VIFStaticDMA.AddVector(Vector4(0, -1, 0, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(1.0f, -1.0f, 1.0f, 1.0f));	// Vert (xyzw)
	VIFStaticDMA.AddVector(Vector4(1, 0, 1, fDraw));			// TexCoord (STQ)
	VIFStaticDMA.AddVector(Vector4(0, -1, 0, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(1.0f,  -1.0f, -1.0f, 1.0f));	// Vert (xyzw)
	VIFStaticDMA.AddVector(Vector4(0, 1, 1, fDraw));			// TexCoord (STQ)
	VIFStaticDMA.AddVector(Vector4(0, -1, 0, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(-1.0f,-1.0f, 1.0f, 1.0f));	// Vert (xyzw)
	VIFStaticDMA.AddVector(Vector4(0, 1, 1, fDraw));			// TexCoord (STQ)
	VIFStaticDMA.AddVector(Vector4(0, -1, 0, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(-1.0f,-1.0f, 1.0f, 1.0f));	// Vert (xyzw)
	VIFStaticDMA.AddVector(Vector4(1, 0, 1, fDraw));			// TexCoord (STQ)
	VIFStaticDMA.AddVector(Vector4(0, -1, 0, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(1.0f, -1.0f, -1.0f, 1.0f));	// Vert (xyzw)
	VIFStaticDMA.AddVector(Vector4(1 , 1, 1, fDraw));			// TexCoord (STQ)
	VIFStaticDMA.AddVector(Vector4(0, -1, 0, 0));				// Normal
	VIFStaticDMA.AddVector(Vector4(-1.0f, -1.0f, -1.0f, 1.0f));	// Vert (xyzw)

	
	// Flush to make sure VU1 isn't doing anything.
	VIFStaticDMA.Add32(FLUSH);
	// Then run the microcode.
	VIFStaticDMA.Add32(MSCALL(0));

	// Return back to the dynamic chain (note that we aren't aligned on a QWORD boundary, but
	// it doesn't matter because the packet class will sort that out for us).
	VIFStaticDMA.DMARet();
}
void CSPS2Manager::DownloadVram(CDMAMem & DMAChainMem, CDMAMem & SShotMem, 
								int addr, int bufw, int x, int y, int w, int h)
{
	// Pointer the memory for building the DMA chain
	uint32 * pDmaMem32 = (uint32 *)DMAChainMem.GetUncached();	

	uint32 uSrcPtr = addr;
	uint32 uQSize = (w*h*4)/16; // assuming 32bit framebuffer

	// Setup transfer texture back to memory
	pDmaMem32[0] = 0; //NOP;
	pDmaMem32[1] = 0x06008000; //MSKPATH3(0x8000);
	pDmaMem32[2] = 0x13000000; //FLUSHA;
	pDmaMem32[3] = 0x50000006; //DIRECT(6);

	// Add GifTag Data
	// Get pointer to GIFTag position
	uint128 * pGIFTag = (uint128 *)(pDmaMem32 + 4);
	
	// Store the GIFTag - The Giftag for A+D mode
	*pGIFTag = GS_GIFTAG_BATCH(	5,							// NLOOP
	 							1,							// EOP
	 							0,							// PRE
	 							0,							// PRIM				
	 							GIF_FLG_PACKED,				// FLG
	 							GS_BATCH_1(	GIF_REG_A_D));	// BATCH
	 
	// Get uint64 pointer to write the A_D data
	// [0] and [1] are the GIFTag									
	uint64 * pDmaMem64 = (uint64 *) (pGIFTag);

	pDmaMem64[2] = (BITBLTBUF_SET( uSrcPtr, bufw, 0, 0, 0, 0 ));
	pDmaMem64[3] = (GIF_A_D_REG_BITBLTBUF);

	pDmaMem64[4] = (TRXPOS_SET(x, y, 0, 0, 0)); // SSAX, SSAY, DSAX, DSAY, DIR
	pDmaMem64[5] = (GIF_A_D_REG_TRXPOS);

	pDmaMem64[6] = (TRXREG_SET(w, h)); // RRW, RRh
	pDmaMem64[7] = (GIF_A_D_REG_TRXREG);

	pDmaMem64[8] = (0);
	pDmaMem64[9] = (GIF_A_D_REG_FINISH);

	pDmaMem64[10] = (TRXDIR_SET(1)); // XDIR
	pDmaMem64[11] = (GIF_A_D_REG_TRXDIR);

	uint32 prev_chcr = *EE_D1_CHCR;
	
	// *_GS_IMR fetches the current setting of interrupt mask register (imr)
	// DPUT_GS_IMR() sets the current value of imr
	// Mark interrupts from the FINISH Event (GS Page 154)
	uint32 prev_imr = *_GS_IMR;
	DPUT_GS_IMR( prev_imr | 0x0200 );
	
	// vif1 must be available
	if ((*EE_D1_CHCR & 0x0100) != 0)
	{
		printf("VIF1 is not available for the Screen Shot\n");
		exit(-1);
	}	
	
	// Enable generation of the FINISH Event (GS Page 145)
	DPUT_GS_CSR( 2 ); 
	
	// Disable interrupts so we don't lose our finish event
	asm __volatile__ ("di");

	
	// Make sure all cache is writen to main memory
	FlushCache();
	
	// Setup and start DMA transfer to VIF1
	*EE_D1_QWC = 0x7;
	*EE_D1_MADR = DMAChainMem.GetPhysicalAddr();
	//             DIR      MOD       ASP     TTE       TIE      STR
	*EE_D1_CHCR = (1<<0) | (0<<2) | (0<<4) | (0<<6) | (0<<7) | (1<<8);

	// Wait till memory load is complete
	asm __volatile__( " sync.l " );
	
	// Wait till DMA is complete (STR=0)
	while ( *EE_D1_CHCR & 0x0100 );

	// Wait for the GS to finish loading the registers (FINISH EVENT)
	//while ( ((*GS_CSR_OFF(SPS2_GS_REGISTERS_START)) & 2) == 0 ); 
	while ( (*_GS_CSR & 2) == 0 );
	
	// Re-enable interrupts
	asm __volatile__ ("ei");
	
	
	// START! The actual download to memory 
	// wait for VIF1-FIFO to empty and become idle 
	while(*EE_VIF1_STAT & 0x1f000003); 
	
	// Change the VIF1 direction to VIF1->Memory
	*((volatile uint32 *) EE_VIF1_STAT) = (1<<23);
	
	// Change direction of VIF1 FIF0 Local->Host
	DPUT_GS_BUSDIR( ( uint64 ) 0x00000001 );
	
	// Setup and start DMA transfer from VIF1
	*EE_D1_QWC = uQSize;
	*EE_D1_MADR = SShotMem.GetPhysicalAddr();
	//          DIR    MOD       ASP     TTE       TIE      STR
	*EE_D1_CHCR = 0 | (0<<2) | (0<<4) | (0<<6) | (0<<7) | (1<<8);

	// Wait till memory load is complete
	asm __volatile__( " sync.l " );

	// check if DMA is complete (STR=0)
	while ( *EE_D1_CHCR & 0x0100 );
	
	// Restore CHCR and wait for it to complete
	*EE_D1_CHCR = prev_chcr;
	asm __volatile__( " sync.l " );
	
	// wait for VIF1-FIFO to empty and become idle 
	while ( *EE_VIF1_STAT & 0x1f000003 ); 

	
	// Change the VIF1 and VIF1 FIFO Direction back to normal
	*((volatile uint32 *) EE_VIF1_STAT) = 0;
	DPUT_GS_BUSDIR( ( uint64 ) 0 );
	
	
	// restore the setting of IMR
	DPUT_GS_IMR( prev_imr);
	// set the FINISH event to default
	//dput_gs_csr( GS_EE_CSR_FINISH_M );
	DPUT_GS_CSR( 2 ); 
	
	
	
	// Re-enable path3 transfers
	static uint32 enable_path3[4] ALIGN_QW = {
	0x06000000, //MSKPATH3(0),
	0,
	0,
	0};

	DPUT_EE_VIF1_FIFO( *( uint128 * ) enable_path3 );

	// Make sure data is written to main memory
	FlushCache();
}