/* ============== 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(); }
/* ============================= 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(); }
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(); }