#if 0
//////////////////////////////////////////////////////////////////////////////
//
// Asura_PS2_GS_Redundant.cpp
//
// By: Kevin Lea, Richard Smith, Morgan Parry, Mike Healey.
//
// Contains code from Asura_PS2_GS.cpp which is no longer required / used
//
// Copyright (c) 2001 Rebellion. All rights reserved.
//
//////////////////////////////////////////////////////////////////////////////

// I N C L U D E S ///////////////////////////////////////////////////////////

// Standard independent.

// Standard platform-specific.
#include <devfont.h>                        // For sceDevCons...().
#include <libgraph.h>
#include <sifdev.h>
#include <sifrpc.h>

// Engine independent.
#include "Asura.h"                          // Global header.
#include "Asura_Assert.h"
#include "Asura_Camera.h"
#include "Asura_Render.h"
#include "Asura_TextureManagement.h"
#include "Asura_Timers.h"
#include "Asura_UserInput.h"
#include "Asura_Viewport.h"

// Engine platform-specific.
#include "Asura_PlatformBasics.h"
#include "Asura_PlatformRenderStates.h"
#include "Asura_PlatformTextureManagement.h"
#include "Asura_PS2_DMA.h"                  // For Asura_PS2_DMAFromSPR().
#include "Asura_PS2_GS.h"
#include "Asura_PS2_OS.h"
#include "Asura_PS2_VU1.h"                  // SetupMatrices()
#include "Asura_PS2_TV_Mode.h"              // PAL/NTSC

// hack
#include "Asura_PlatformInput.h"

// P R O T O T Y P E S   A N D   I N L I N E   F U N C T I O N S /////////////

//static void DrawFog( void );
static void DrawHelp( void );
static void DrawHud( void );
static void DrawLogo( void );
static void DrawPrompt( void );
static void DrawSunWhiteOutEffect( void );

//#include "WW2_Core.h"
static bool CanDrawHudStuff( void )
{
    // (MP - 04.02.2002) Hack for WW2 demo.
    //return( WW2_Core::GetGameState() == WW2_GAMESTATE_PLAYINGENV );
    return false;
}

DEBUGVAR float dbg_fHudAlphaFadeRate = 2.0f * 127.0f;

// The prompt and the logo depend on whether the help screen is on or not.
static float g_fHelpScreenAlphaValue = 0.0f;
/*static*/ bool g_bHelpScreenIsOn = false;
static bool g_bHelpScreenHasEverBeenOn = false;

static float g_fPromptAlphaValue = 0.0f;
static bool g_bPromptIsOn = false;
DEBUGVAR int dbg_iPromptWidth = 192;
DEBUGVAR int dbg_iPromptHeight = 96;
DEBUGVAR int dbg_iPromptInsetX = 16;
DEBUGVAR int dbg_iPromptInsetY = 2;

static float g_fLogoAlphaValue = 0.0f;
static bool g_bLogoIsOn = false;
DEBUGVAR int dbg_iLogoInsetX = -5;
DEBUGVAR int dbg_iLogoInsetY = -1;

//////////////////////////////////////////////////////////////////////////////
//
// FUNCTION     DrawPrompt().
// PARAMETERS   None.
// RETURNS      None.
// DESCRIPTION  
// AUTHOR       Morgan Parry - 31.10.2001.
//
//////////////////////////////////////////////////////////////////////////////
static void DrawPrompt( void )
{
    static int iPromptTextureID = -2;

    // Load texture if necessary.
    if( iPromptTextureID == -2 )
    {
        iPromptTextureID = Asura_Texture_Management::AddTexture( "\\hud\\help_hud.tm2" );
        Asura_Texture_Management::LoadTextures();
    }

    if( iPromptTextureID >= 0 )
    {
        // Update alpha value as necessary.
        if( g_bPromptIsOn )
        {
            if( !CanDrawHudStuff() || g_bHelpScreenIsOn )
            {
                g_bPromptIsOn = false;
            }
            else
            {
                if( g_fPromptAlphaValue < 127.0f )
                {
                    g_fPromptAlphaValue += dbg_fHudAlphaFadeRate * Asura_Timers::GetFrameTime();
                    if( g_fPromptAlphaValue > 127.0f )
                    {
                        g_fPromptAlphaValue = 127.0f;
                    }
                }
            }
        }
        else
        {
            if( CanDrawHudStuff() && !g_bHelpScreenIsOn && !g_bHelpScreenHasEverBeenOn )
            {
                g_bPromptIsOn = true;
            }
            else
            {
                if( g_fPromptAlphaValue > 0.0f )
                {
                    g_fPromptAlphaValue -= dbg_fHudAlphaFadeRate * Asura_Timers::GetFrameTime();
                    if( g_fPromptAlphaValue < 0.0f )
                    {
                        g_fPromptAlphaValue = 0.0f;
                    }
                }
            }
        }

        // Draw if not completely transparent.
        if( g_fPromptAlphaValue != 0.0f )
        {
            Asura_PS2_GS::Sprite xSprite;

            xSprite.iTexID  = iPromptTextureID;
            xSprite.iWidth  = dbg_iPromptWidth;
            xSprite.iHeight = dbg_iPromptHeight;
            xSprite.iScrX   = dbg_iPromptInsetX;
            xSprite.iScrY   = -xSprite.iHeight + dbg_iPromptInsetY;
            xSprite.uABGR   = Asura_PS2_GS::Sprite::WHITE;
            xSprite.uA      = static_cast<unsigned char>( g_fPromptAlphaValue );

            Asura_PS2_GS::DrawSprite( xSprite );
        }
    }
}
// End function DrawPrompt().

static void DrawHudThingy( const int iTextureID, const Asura_Vector_2* axCoords, const unsigned char uAlpha )
{
    // Setup renderer state.
    //Asura_PlatformRenderStates::SetAlphaBlend( 0, 2, 0, 1, 0 ); //( 0, 1, 0, 1, 0 );
    Asura_PlatformRenderStates::SetTranslucencyMode(ASURA_TRANSLUCENCY_GLOWING);
    Asura_PlatformRenderStates::SetDefaultAlphaValue( false );
	Asura_PlatformRenderStates::SetPixelTest( false, false );
	Asura_PlatformRenderStates::SetTextureClamp( true );
    Asura_Render::CurrentStates.RequestZBufferWriteEnabled( true );

    sceGifPacket xGifPacket;

    Asura_PS2_QW* pxScratchpad = Asura_PS2_SPR_Alloc( 0, 1024 );

    // Setup the GIF packet.
	sceGifPkInit( &xGifPacket, &(pxScratchpad->u128) );
	sceGifPkReset( &xGifPacket );
	sceGifPkAddGsData( &xGifPacket, SCE_GIF_SET_TAG(11, 1, NULL, NULL, SCE_GIF_PACKED, 1) );
	sceGifPkAddGsData( &xGifPacket, SCE_GIF_PACKED_AD );

    // Specify what texture we want.
	sceGifPkAddGsData( &xGifPacket, *GetTextureHandle(iTextureID) );
	sceGifPkAddGsData( &xGifPacket, SCE_GS_TEX0_1 );

    // Primitive specification.
	sceGifPkAddGsData(&xGifPacket, SCE_GS_SET_PRIM(	SCE_GS_PRIM_TRIFAN, // PRIM (Type)
													0,                  // IIP  (Shading 0 = Flat, 1 = Gouraud)
													1,                  // TME  (Texture Mapping On/Off)
													0,                  // FGE  (Fogging On.Off)
													1,                  // ABE  (Alpha Blending On/Off)
													0,                  // AA1  (Anti-Aliasing On/Off)
													1,                  // FST  (Texture Coord Format ST/UV)
													0,                  // CTXT (Context 0 or 1)
													0                   // FIX  (Fragment Value Control Off/On)
												) );
	sceGifPkAddGsData( &xGifPacket, SCE_GS_PRIM );


    // Colour.
    {
        const float fOne = 1.0f;
        const unsigned uHexOfOneFloat = *reinterpret_cast<const unsigned*>(&fOne);
        sceGifPkAddGsData( &xGifPacket, SCE_GS_SET_RGBAQ(127, 127, 127, uAlpha, uHexOfOneFloat) );
        sceGifPkAddGsData( &xGifPacket, SCE_GS_RGBAQ );
    }

    // UVs and positions.
    {
        const int iTextureWidth = GetTextureWidth(iTextureID) << 4;
        const int iTextureHeight = GetTextureHeight(iTextureID) << 4;
        const int aiUVs[4][2] =
        {
            { 0, 0 },
            { iTextureWidth, 0 },
            { iTextureWidth, iTextureHeight },
            { 0, iTextureHeight },
        };

        for( unsigned u = 0; u < 4; ++u )
        {
            sceGifPkAddGsData( &xGifPacket, SCE_GS_SET_UV(aiUVs[u][0], aiUVs[u][1]) );
            sceGifPkAddGsData( &xGifPacket, SCE_GS_UV );

            const int iX = static_cast<int>(axCoords[u].x) << 4;
            const int iY = static_cast<int>(axCoords[u].y) << 4;
            sceGifPkAddGsData( &xGifPacket, SCE_GS_SET_XYZ(iX, iY, 0) );
            sceGifPkAddGsData( &xGifPacket, SCE_GS_XYZ2 );
        }
    }

    // Close and send the GIF packet.
    sceGifPkTerminate( &xGifPacket );
    sceDmaSendN( Asura_PS2_GS::GetDmaChannel(), Asura_PS2_DMAFromSPR(xGifPacket.pBase), sceGifPkSize(&xGifPacket) );
    sceGsSyncPath( 0, 0 );

    Asura_PS2_SPR_Dealloc( pxScratchpad );
}

bool g_bDrawSniperHud = false;
float g_fHudRingRotation = 0.0f;

struct HudRing
{
    float fSize;
    unsigned char uAlpha;
};

DEBUGVAR HudRing dbg_axHudRings[2] =
{
// Rogue settings
//    {  70.0f, 20 }, // Inner.
//    { 350.0f, 10 }, // Outer.
    // GR settings
    {  0.0f, 0 }, // Inner.
    { 0.0f, 0}, // Outer.

};

DEBUGVAR unsigned dbg_uSniperDotRadius = 3;
DEBUGVAR unsigned dbg_uSniperDotABGR = 0x284f797b;

//////////////////////////////////////////////////////////////////////////////
//
// FUNCTION     DrawHud().
// PARAMETERS   None.
// RETURNS      None.
// DESCRIPTION  Draws the HUD.
// AUTHOR       Morgan Parry - 08.01.2002.
//
//////////////////////////////////////////////////////////////////////////////
static void DrawHud( void )
{
    static int iScopeTextureID = -2;
    static int iDotTextureID = -2;

    // Load the textures first time even if we're not drawing the HUD.
    if( iScopeTextureID == -2 )
    {
        Asura_Assert( iDotTextureID == -2, "" );

        iScopeTextureID = Asura_Texture_Management::AddTexture( "\\hud\\scope.tm2" );
        iDotTextureID = Asura_Texture_Management::AddTexture( "\\hud\\ScopeDot.tm2" );
        Asura_Texture_Management::LoadTextures();
    }

    if( !g_bDrawSniperHud || iScopeTextureID < 0 || iDotTextureID < 0 ) { return; }

    // Upload the scope texture.
    Asura_PS2_TextureManagement::UploadTexture( iScopeTextureID, ASURA_PS2_TEXTURE_BUFFER_0 );

    const float fCentreX = static_cast<float>( ASURA_PS2_SCREEN_CENTRE_X );
    const float fCentreY = static_cast<float>( ASURA_PS2_SCREEN_CENTRE_Y );

    extern float dbg_fAspectX;
    extern float dbg_fAspectY;

    // Draw the two rings.
    for( unsigned u = 0; u < 2; ++u )
    {
        const float fRotation = ( u == 0 ? g_fHudRingRotation : -g_fHudRingRotation );
        const float fCos = Asura_Maths::Cosine( fRotation );
        const float fSin = Asura_Maths::Sine( fRotation );

        const float axCoords[4][2] =
        {
            { -dbg_axHudRings[u].fSize * 0.5f, -dbg_axHudRings[u].fSize * 0.5f },
            {  dbg_axHudRings[u].fSize * 0.5f, -dbg_axHudRings[u].fSize * 0.5f },
            {  dbg_axHudRings[u].fSize * 0.5f,  dbg_axHudRings[u].fSize * 0.5f },
            { -dbg_axHudRings[u].fSize * 0.5f,  dbg_axHudRings[u].fSize * 0.5f },
        };

        // Transform.
        Asura_Vector_2 axTransformedCoords[4];
        for( unsigned v = 0; v < 4; ++v )
        {
            // Rotation.
            axTransformedCoords[v].x = axCoords[v][0] * fCos - axCoords[v][1] * fSin;
            axTransformedCoords[v].y = axCoords[v][0] * fSin + axCoords[v][1] * fCos;

            // Aspect correction.
            axTransformedCoords[v].x *= dbg_fAspectX;
            axTransformedCoords[v].y *= dbg_fAspectY;

            // Translation.
            axTransformedCoords[v].x += fCentreX;
            axTransformedCoords[v].y += fCentreY;
        }

        DrawHudThingy(
            iScopeTextureID,
            axTransformedCoords,
            dbg_axHudRings[u].uAlpha
        );
    }

    // Draw the dot.
    {
        float fHalfWidth = dbg_uSniperDotRadius * dbg_fAspectX;
        float fHalfHeight = dbg_uSniperDotRadius * dbg_fAspectY;

        Asura_PS2_GS::Sprite xSprite;

        xSprite.iScrX   = Asura_Maths::FloatToInt( (Asura_PS2_GS::GetScreenWidth() >> 1) - fHalfWidth );
        xSprite.iScrY   = Asura_Maths::FloatToInt( (Asura_PS2_GS::GetScreenHeight() >> 1) - fHalfHeight );
        xSprite.iWidth  = Asura_Maths::FloatToInt( 2.0f * fHalfWidth );
        xSprite.iHeight = Asura_Maths::FloatToInt( 2.0f * fHalfHeight );
        xSprite.iTexID  = iDotTextureID;
        xSprite.uABGR   = dbg_uSniperDotABGR;

        Asura_PS2_GS::DrawSprite( xSprite );
    }
}
// End function DrawHud().

//////////////////////////////////////////////////////////////////////////////
//
// FUNCTION     DrawLogo().
// PARAMETERS   None.
// RETURNS      None.
// DESCRIPTION  Draws Rebellion logo in the bottom right of the screen.
// AUTHOR       Morgan Parry.
//
//////////////////////////////////////////////////////////////////////////////
static void DrawLogo( void )
{
    static int iLogoID = -2;

    // Load texture if necessary.
    if( iLogoID == -2 )
    {
        iLogoID = Asura_Texture_Management::AddTexture( "\\hud\\reblogo.tm2" );
        Asura_Texture_Management::LoadTextures();
    }

    if( iLogoID >= 0 )
    {
        // Update alpha value as necessary.
        if( g_bLogoIsOn )
        {
            if( !CanDrawHudStuff() || g_bHelpScreenIsOn )
            {
                g_bLogoIsOn = false;
            }
            else
            {
                if( g_fLogoAlphaValue < 127.0f )
                {
                    g_fLogoAlphaValue += dbg_fHudAlphaFadeRate * Asura_Timers::GetFrameTime();
                    if( g_fLogoAlphaValue > 127.0f )
                    {
                        g_fLogoAlphaValue = 127.0f;
                    }
                }
            }
        }
        else
        {
            if( CanDrawHudStuff() && !g_bHelpScreenIsOn )
            {
                g_bLogoIsOn = true;
            }
            else
            {
                if( g_fLogoAlphaValue > 0.0f )
                {
                    g_fLogoAlphaValue -= dbg_fHudAlphaFadeRate * Asura_Timers::GetFrameTime();
                    if( g_fLogoAlphaValue < 0.0f )
                    {
                        g_fLogoAlphaValue = 0.0f;
                    }
                }
            }
        }

        // Draw if not completely transparent.
        if( g_fLogoAlphaValue != 0.0f )
        {
            Asura_PS2_GS::Sprite xSprite;

            xSprite.iTexID  = iLogoID;
            xSprite.iWidth  = GetTextureWidth( iLogoID );
            xSprite.iHeight = GetTextureHeight( iLogoID );
            xSprite.iScrX   = -xSprite.iWidth + dbg_iLogoInsetX;
            xSprite.iScrY   = -xSprite.iHeight + dbg_iLogoInsetY;
            xSprite.uABGR   = Asura_PS2_GS::Sprite::WHITE;
            xSprite.uA      = static_cast<unsigned char>( g_fLogoAlphaValue );

            Asura_PS2_GS::DrawSprite( xSprite );
        }
    }
}
// End function DrawLogo().

//////////////////////////////////////////////////////////////////////////////
//
// FUNCTION 	DrawHelp().
// PARAMETERS	None
// RETURNS		None
// DESCRIPTION	Draws an overlay texture providing key functionality info
// AUTHOR		Richard M. Smith (26 September 2001)
// MODIFIED     Morgan Parry.
//
//////////////////////////////////////////////////////////////////////////////
static void DrawHelp( void )
{
   static int iHelpID = -2;
    
    // Load texture if necessary.
    if( iHelpID == -2 )
    {
    	iHelpID = Asura_Texture_Management::AddTexture( "\\hud\\controls.tm2" );
        Asura_Texture_Management::LoadTextures();
    }

    // Don't draw anything if we don't have the texture.
    if( iHelpID >= 0 )
    {
        // Update alpha value if necessary.
        Asura_Assert( 0.0f <= g_fHelpScreenAlphaValue && g_fHelpScreenAlphaValue <= 127.0f, "" );
        if( g_bHelpScreenIsOn )
        {
            g_bHelpScreenHasEverBeenOn = true;
            if( !CanDrawHudStuff() || Asura_UserInput::DebouncedKeyPressed(ASURA_PS2_KEYID_PAD1_SELECT) )
            {
                g_bHelpScreenIsOn = false;
            }
            else if( g_fHelpScreenAlphaValue < 127.0f )
            {
                g_fHelpScreenAlphaValue += dbg_fHudAlphaFadeRate * Asura_Timers::GetFrameTime();
                if( g_fHelpScreenAlphaValue > 127.0f )
                {
                    g_fHelpScreenAlphaValue = 127.0f;
                }
            }
        }
        else
        {
            if( CanDrawHudStuff() && Asura_UserInput::DebouncedKeyPressed(ASURA_PS2_KEYID_PAD1_SELECT) )
            {
                g_bHelpScreenIsOn = true;
            }
            else if( g_fHelpScreenAlphaValue > 0.0f )
            {
                g_fHelpScreenAlphaValue -= dbg_fHudAlphaFadeRate * Asura_Timers::GetFrameTime();
                if( g_fHelpScreenAlphaValue < 0.0f )
                {
                    g_fHelpScreenAlphaValue = 0.0f;
                }
            }
        }

        // Draw if not completely transparent.
        if( g_fHelpScreenAlphaValue != 0.0f )
        {
            Asura_PS2_GS::Sprite xSprite;

            xSprite.iTexID  = iHelpID;
            xSprite.iScrX   = 0;
            xSprite.iScrY   = 0;
            xSprite.iWidth  = Asura_PS2_GS::GetScreenWidth();
            xSprite.iHeight = Asura_PS2_GS::GetScreenHeight();
            xSprite.uABGR   = Asura_PS2_GS::Sprite::WHITE;
            xSprite.uA      = static_cast<unsigned char>( g_fHelpScreenAlphaValue );

            Asura_PS2_GS::DrawSprite( xSprite );
        }
    }
}
// End function DrawHelp().

// (MP - 17.01.2002) For old method...
//DEBUGVAR Asura_Vector_3 dbg_xSunPos( 1333.8f, -15.2f, -1033.8f );

// In texture coordinates on the relevant side of the skybox.
DEBUGVAR Asura_Vector_2 dbg_axSunBoundingSquareCorners[2] =
{
    Asura_Vector_2( 0.876953125f, 0.3388671875f ), // Top-left.
    Asura_Vector_2( 0.984375f, 0.4638671875f ),    // Bottom-right.
};

//// Coordinates of top-left and bottom-right of relevant side of skybox, in
//// worldspace.
//DEBUGVAR Asura_Vector_3 dbg_axSunSkyboxSideCoords[2] =
//{
//    Asura_Vector_3( 1000.0f, -1.0f, 1000.0f ), // Top-left.
//    Asura_Vector_3( 1000.0f, 1.0f, -1000.0f ), // Bottom-right.
//};

DEBUGVAR float dbg_fSunHalfFOV = 45.0f * Asura_Maths::DegToRadConstant; // In radians.
DEBUGVAR float dbg_fSunCosOfHalfFOV = Asura_Maths::Cosine( dbg_fSunHalfFOV );

DEBUGVAR unsigned char dbg_uSunRed = 120;
DEBUGVAR unsigned char dbg_uSunGreen = 60;
DEBUGVAR unsigned char dbg_uSunBlue = 60;
DEBUGVAR float dbg_fSunAlphaMax = 70.0f; // In range [0, 128].
DEBUGVAR bool dbg_bSunUseAdditiveAlpha = true;

DEBUGVAR bool dbg_bEnableSunWhiteOutEffect = false;
DEBUGVAR bool dbg_bDrawSunBoundingSquare = false;

#include "Asura_Module.h"
#include "Asura_PlatformSkybox.h"

void DrawSunBoundingSquare( sceVu0IVECTOR xTopLeft, sceVu0IVECTOR xBottomRight );

static void ReadDataFromGS(
    u_long128* puDestBuffer,
    unsigned uSizeOfDestBuffer,
    unsigned uSrcAddr,
    unsigned uPixelStorageMode,
    unsigned uX, unsigned uY,
    unsigned uWidth, unsigned uHeight,
    unsigned uSrcBufferWidth
);

//////////////////////////////////////////////////////////////////////////////
//
// FUNCTION     DrawSunWhiteOutEffect().
// PARAMETERS   None.
// RETURNS      None.
// DESCRIPTION  
// AUTHOR       Morgan Parry - 15.01.2002.
//
//////////////////////////////////////////////////////////////////////////////
static void DrawSunWhiteOutEffect( void )
{
    if( !dbg_bEnableSunWhiteOutEffect ) { return; }

    float fVisibility; // In range [0, 1].
    float fCosOfAngleToSun;

    // Test visibility.
    {
        sceVu0IVECTOR axScreenCoords[2];

        // Calculate screen coordinates of sun bounding square. We'll just 
        // transform the bottom-left and top-right coordinates and then make
        // a square in screenspace using those. Also calculate angle from
        // view dir to dir to sun.
        {
            Asura_Vector_3 axCorners[2];
            GetCoordinatesOnSkybox( ASURA_PS2_SKYBOXFACES_XPOS, dbg_axSunBoundingSquareCorners, 2, axCorners );

            // Calculate angle.
            {
                // Calculate centre.
                Asura_Vector_3 xSunCentre = axCorners[0] + axCorners[1];
                xSunCentre *= 0.5f;

                const Asura_Vector_3 * const pxCamPos = Asura_Camera::GetPosition();

                // Get direction to sun.
                Asura_Vector_3 xToSun = xSunCentre - *pxCamPos;
                xToSun.Normalise();

                // Calculate dot product with camera direction.
                const Asura_Matrix_3x3 * const xCamOri = Asura_Camera::GetOrientation();
                const Asura_Vector_3 xCamDir( xCamOri->e13, xCamOri->e23, xCamOri->e33 );
                fCosOfAngleToSun = xCamDir * xToSun;

                // We don't need to do anything if this is outside the sun "FOV".
                if( fCosOfAngleToSun < dbg_fSunCosOfHalfFOV ) { return; }
            }

            // Transform to screen.
            {
                extern sceVu0FMATRIX g_xWorldToScreenMat;

                sceVu0FVECTOR axWorldCoords;
                for( unsigned u = 0; u < 2; ++u )
                {
                    axWorldCoords[0] = axCorners[u].x;
                    axWorldCoords[1] = axCorners[u].y;
                    axWorldCoords[2] = axCorners[u].z;
                    axWorldCoords[3] = 1.0f;

                    sceVu0RotTransPers( axScreenCoords[u], g_xWorldToScreenMat, axWorldCoords, 0 );
                }
            }
        }

        const unsigned uHalfScrW = Asura_PS2_GS::GetScreenWidth() >> 1;
        const unsigned uHalfScrH = Asura_PS2_GS::GetScreenHeight() >> 1;

        // Check if that's offscreen.
        {
            // Near Z plane.
            if( axScreenCoords[0][2] < 0 || axScreenCoords[1][2] < 0 ) { return; }

            // Left screen edge.
            if( axScreenCoords[1][0] < static_cast<int>((ASURA_PS2_SCREEN_CENTRE_X - uHalfScrW) << 4) ) { return; }

            // Right screen edge.
            if( axScreenCoords[0][0] > static_cast<int>((ASURA_PS2_SCREEN_CENTRE_X + uHalfScrW) << 4) ) { return; }

            // Top screen edge.
            if( axScreenCoords[1][1] < static_cast<int>((ASURA_PS2_SCREEN_CENTRE_Y - uHalfScrH) << 4) ) { return; }

            // Bottom screen edge.
            if( axScreenCoords[0][1] > static_cast<int>((ASURA_PS2_SCREEN_CENTRE_Y + uHalfScrH) << 4) ) { return; }
        }

        // Clip.
        {
            if( axScreenCoords[0][0] < static_cast<int>((ASURA_PS2_SCREEN_CENTRE_X - uHalfScrW) << 4) )
            {
                axScreenCoords[0][0] = (ASURA_PS2_SCREEN_CENTRE_X - uHalfScrW) << 4;
            }

            if( axScreenCoords[0][1] < static_cast<int>((ASURA_PS2_SCREEN_CENTRE_Y - uHalfScrH) << 4) )
            {
                axScreenCoords[0][1] = (ASURA_PS2_SCREEN_CENTRE_Y - uHalfScrH) << 4;
            }

            if( axScreenCoords[1][0] > static_cast<int>((ASURA_PS2_SCREEN_CENTRE_X + uHalfScrW) << 4) )
            {
                axScreenCoords[1][0] = (ASURA_PS2_SCREEN_CENTRE_X + uHalfScrW) << 4;
            }

            if( axScreenCoords[1][1] > static_cast<int>((ASURA_PS2_SCREEN_CENTRE_Y + uHalfScrH) << 4) )
            {
                axScreenCoords[1][1] = (ASURA_PS2_SCREEN_CENTRE_Y + uHalfScrH) << 4;
            }
        }

        u_long128* auBuffer = NULL;

        // The following code only supports a 16-bit Z buffer at the moment.
        Asura_Assert( Asura_PS2_GS::GetZBufferStorageFormat() == SCE_GS_PSMZ16 || 
            Asura_PS2_GS::GetZBufferStorageFormat() == SCE_GS_PSMZ16S, "" );

        Asura_Assert( axScreenCoords[0][0] >= 0, "" );
        Asura_Assert( axScreenCoords[0][1] >= 0, "" );
        Asura_Assert( axScreenCoords[1][0] >= 0, "" );
        Asura_Assert( axScreenCoords[1][1] >= 0, "" );
        Asura_Assert( axScreenCoords[0][0] <= axScreenCoords[1][0], "" );
        Asura_Assert( axScreenCoords[0][1] <= axScreenCoords[1][1], "" );
        unsigned uX = axScreenCoords[0][0] >> 4;
        unsigned uY = axScreenCoords[0][1] >> 4;
        unsigned uActualSunBSWidth = (axScreenCoords[1][0] >> 4) - uX;
        unsigned uActualSunBSHeight = (axScreenCoords[1][1] >> 4) - uY;

        if( uActualSunBSWidth == 0 || uActualSunBSHeight == 0 ) { return; }

        // We need uX and uY in terms of the viewport, rather than in terms
        // of the entire guardband.
        Asura_Assert( uX >= ASURA_PS2_SCREEN_CENTRE_X - uHalfScrW, "" );
        Asura_Assert( uY >= ASURA_PS2_SCREEN_CENTRE_Y - uHalfScrH, "" );
        uX -= ASURA_PS2_SCREEN_CENTRE_X - uHalfScrW;
        uY -= ASURA_PS2_SCREEN_CENTRE_Y - uHalfScrH;
        
        // We need width*height to be a multiple of 8, so that
        // width*height*bytes_per_pixel is a multiple of 16, as required by
        // sceGsSetDef...Image() and friends.
        unsigned uWidthOfAreaToGet = uActualSunBSWidth;
        unsigned uHeightOfAreaToGet = uActualSunBSHeight;
        unsigned uAdjustX = 0;
        unsigned uAdjustY = 0;
        if( ((uWidthOfAreaToGet * uHeightOfAreaToGet) & 7) != 0 )
        {
            unsigned uExtraX, uExtraY;

            // If we make the width and height both a multiple of 4, their
            // product will then be a multiple of 8, as required.
            uExtraX = ( (uWidthOfAreaToGet & 3) ? 4 - (uWidthOfAreaToGet & 3) : 0 );
            uExtraY = ( (uHeightOfAreaToGet & 3) ? 4 - (uHeightOfAreaToGet & 3) : 0 );

            // Increase the width and height by these amounts.
            uWidthOfAreaToGet += uExtraX;
            uHeightOfAreaToGet += uExtraY;

            // If that's taken us over the edge of the viewport, adjust the
            // X and Y coordinates.
            if( uX + uWidthOfAreaToGet >= (uHalfScrW << 1) )
            {
                uAdjustX = 1 + uX + uWidthOfAreaToGet - (uHalfScrW << 1);
                Asura_Assert( uX >= uAdjustX, "" );
                uX -= uAdjustX;
            }
            if( uY + uHeightOfAreaToGet >= (uHalfScrH << 1) )
            {
                uAdjustY = 1 + uY + uHeightOfAreaToGet - (uHalfScrH << 1);
                Asura_Assert( uY >= uAdjustY, "" );
                uY -= uAdjustY;
            }

            Asura_Assert( ((uWidthOfAreaToGet * uHeightOfAreaToGet) & 7) == 0, "" );
        }

        // Grab that area of VRAM from the GS.
        {
            const unsigned uBytesRequired = (uWidthOfAreaToGet * uHeightOfAreaToGet) << 1;
            Asura_Assert( (uBytesRequired & 15) == 0, "" );
            const unsigned uQWsRequired = uBytesRequired >> 4;

            auBuffer = new u_long128[uQWsRequired];
            if( !auBuffer ) { return; }

            ReadDataFromGS(
                auBuffer,
                uQWsRequired,
                ASURA_PS2_ZBFR_BASE_PTR * 32,
                Asura_PS2_GS::GetZBufferStorageFormat(),
                uX, uY,
                uWidthOfAreaToGet, uHeightOfAreaToGet,
                Asura_PS2_GS::GetScreenWidth()
            );
        }

        // Build an intensity modifier based upon what percentage of that
        // area remains unobstructed by world or character geometry.
        {
            const u_short* auZValues = reinterpret_cast<const u_short*>( auBuffer );

            unsigned uNumPixelsOfSun = 0;
            for( unsigned uRow = 0; uRow < uActualSunBSHeight; ++uRow )
            {
                for( unsigned uCol = 0; uCol < uActualSunBSWidth; ++uCol )
                {
                    if( auZValues[(uRow + uAdjustY) * uWidthOfAreaToGet + (uCol + uAdjustX)] == 0 )
                    {
                        ++uNumPixelsOfSun;
                    }
                }
            }

            fVisibility = static_cast<float>(uNumPixelsOfSun) / static_cast<float>(uActualSunBSWidth * uActualSunBSHeight);
        }

        // Debugging stuff.
        if( dbg_bDrawSunBoundingSquare )
        {
            DrawSunBoundingSquare( axScreenCoords[0], axScreenCoords[1] );
        }

        // Deallocate buffer.
        Asura_Assert( auBuffer, "" );
        delete[] auBuffer;
    }

    // Calculate intensity.
    const float fAngle = Asura_Maths::ArcCosine( fCosOfAngleToSun );
    const float fIntensity = fVisibility * (1.0f - fAngle / dbg_fSunHalfFOV);

    // Draw sprite.
    {
        // Setup renderer state.
        //Asura_PlatformRenderStates::SetAlphaBlend( 0, (dbg_bSunUseAdditiveAlpha ? 2 : 1), 0, 1, 0 );
        if (dbg_bSunUseAdditiveAlpha)
        {
            Asura_PlatformRenderStates::SetTranslucencyMode(ASURA_TRANSLUCENCY_GLOWING);
        }
        else
        {
            Asura_PlatformRenderStates::SetTranslucencyMode(ASURA_TRANSLUCENCY_NORMAL);
        }
//        Asura_PlatformRenderStates::SetDefaultAlphaValue( false );
        Asura_PlatformRenderStates::SetPixelTest( false, false );
//        Asura_PlatformRenderStates::SetTextureClamp( true );
        Asura_Render::CurrentStates.RequestZBufferWriteEnabled( false );

        const unsigned uNLOOP = 3; // One RGBAQ + two XYZ2s.

        // Get pointer to scratchpad.
        Asura_PS2_QW* const pxOutputStart = Asura_PS2_SPR_Alloc( 0, uNLOOP + 1 );
        Asura_PS2_QW* pxOut = pxOutputStart;

        // Write GIF tag.
        {
            Asura_PS2_GifTag* pxGifTag = reinterpret_cast<Asura_PS2_GifTag*>( pxOut );
            pxGifTag->Set(
                uNLOOP,                     // NLOOP.
                true,                       // EOP.
                true,                       // PRE.
                SCE_GS_SET_PRIM(            // PRIM.
                    SCE_GS_PRIM_SPRITE,         // PRIM.
                    1,                          // IIP.
                    0,                          // TME.
                    0,                          // FGE.
                    1,                          // ABE.
                    0,                          // AA1.
                    0,                          // FST.
                    0,                          // CTXT.
                    0                           // FIX.
                ),
                SCE_GIF_PACKED,             // FLG.
                1,                          // NREG.
                SCE_GIF_PACKED_AD           // REG1.
            );
        }
        ++pxOut;

        // Set RGBAQ.
        {
            const unsigned uAlpha = static_cast<unsigned>(static_cast<int>( dbg_fSunAlphaMax * fIntensity ));
            const float fOne = 1.0f;
            const unsigned uHexOfOneFloat = *reinterpret_cast<const unsigned*>( &fOne );
            pxOut->u64s[0] = SCE_GS_SET_RGBAQ( dbg_uSunRed, dbg_uSunGreen, dbg_uSunBlue, uAlpha, uHexOfOneFloat );
            pxOut->u64s[1] = SCE_GS_RGBAQ;
        }
        ++pxOut;

        const unsigned uScrWidth = Asura_PS2_GS::GetScreenWidth();
        const unsigned uScrHeight = Asura_PS2_GS::GetScreenHeight();

        // Set top-left XYZ.
        pxOut->u64s[0] = SCE_GS_SET_XYZ2(
            (ASURA_PS2_SCREEN_CENTRE_X - uScrWidth) << 4,
            (ASURA_PS2_SCREEN_CENTRE_Y - uScrHeight) << 4,
            0
        );
        pxOut->u64s[1] = SCE_GS_XYZ2;
        ++pxOut;

        // Set bottom-right XYZ.
        pxOut->u64s[0] = SCE_GS_SET_XYZ2(
            (ASURA_PS2_SCREEN_CENTRE_X + uScrWidth) << 4,
            (ASURA_PS2_SCREEN_CENTRE_Y + uScrHeight) << 4,
            0
        );
        pxOut->u64s[1] = SCE_GS_XYZ2;
        ++pxOut;

        // Check we wrote the amount of data we expect. Note that we also
        // wrote the GIF tag, which is not included in the NLOOP count.
        Asura_Assert( static_cast<unsigned>(pxOut - pxOutputStart) == uNLOOP + 1, "" );

        // Send to the GS using NORMAL DMA mode.
        {
            // Set the number of QWs to be transferred.
            *D2_QWC = uNLOOP + 1;

            // Set the start address.
            *D2_MADR = reinterpret_cast<unsigned>( Asura_PS2_DMAFromSPR(pxOutputStart) );

            // Ask for transfer completion to be reported on coprocessor.
            *D_PCR = 1 << D_PCR_CPC2_O;
            *D_STAT = 1 << D_STAT_CIS2_O;

            // Force those values to be written to the registers.
            asm( "sync.l" );

            // Setup channel control register.
            *D2_CHCR = (1 << D_CHCR_DIR_O)  // From memory.
                     | (0 << D_CHCR_MOD_O)  // Normal mode.
                     | (0 << D_CHCR_ASP_O)  // No address pushed by call tag.
                     | (0 << D_CHCR_TTE_O)  // Irrelevant in normal mode.
                     | (0 << D_CHCR_TIE_O)  // Irrelevant in normal mode (?).
                     | (1 << D_CHCR_STR_O); // Start DMA transfer.

            // Go go go.
            asm( "sync.l" );

            // Wait for completion.
            asm __volatile__( " _DrawSunWhiteOutEffect_WaitForDMA:         " );
            asm __volatile__( "     bc0f _DrawSunWhiteOutEffect_WaitForDMA " );
            asm __volatile__( "     nop                                    " );
        }

        Asura_PS2_SPR_Dealloc( pxOutputStart );
    }
    // End sprite drawing code.
}
// End function DrawSunWhiteOutEffect().

void DrawSunBoundingSquare( sceVu0IVECTOR __xTopLeft, sceVu0IVECTOR __xBottomRight )
{
    // Setup renderer state.
//    Asura_PlatformRenderStates::SetAlphaBlend( 0, (dbg_bSunUseAdditiveAlpha ? 2 : 1), 0, 1, 0 );
//    Asura_PlatformRenderStates::SetDefaultAlphaValue( false );
    Asura_PlatformRenderStates::SetPixelTest( false, false );
//    Asura_PlatformRenderStates::SetTextureClamp( true );
    Asura_Render::CurrentStates.RequestZBufferWriteEnabled( false );

    const unsigned uNLOOP = 6; // One RGBAQ + five XYZ2s.

    // Get pointer to scratchpad.
    Asura_PS2_QW* const pxOutputStart = Asura_PS2_SPR_Alloc( 0, uNLOOP + 1 );
    Asura_PS2_QW* pxOut = pxOutputStart;

    // Write GIF tag.
    {
        Asura_PS2_GifTag* pxGifTag = reinterpret_cast<Asura_PS2_GifTag*>( pxOut );
        pxGifTag->Set(
            uNLOOP,                     // NLOOP.
            true,                       // EOP.
            true,                       // PRE.
            SCE_GS_SET_PRIM(            // PRIM.
                SCE_GS_PRIM_LINESTRIP,      // PRIM.
                0,                          // IIP.
                0,                          // TME.
                0,                          // FGE.
                0,                          // ABE.
                0,                          // AA1.
                0,                          // FST.
                0,                          // CTXT.
                0                           // FIX.
            ),
            SCE_GIF_PACKED,             // FLG.
            1,                          // NREG.
            SCE_GIF_PACKED_AD           // REG1.
        );
    }
    ++pxOut;

    // Set RGBAQ.
    {
        const float fOne = 1.0f;
        const unsigned uHexOfOneFloat = *reinterpret_cast<const unsigned*>( &fOne );
        pxOut->u64s[0] = SCE_GS_SET_RGBAQ( 127, 127, 127, 127, uHexOfOneFloat );
        pxOut->u64s[1] = SCE_GS_RGBAQ;
    }
    ++pxOut;

    // Set top-left XYZ.
    pxOut->u64s[0] = SCE_GS_SET_XYZ2(
        __xTopLeft[0],
        __xTopLeft[1],
        0
    );
    pxOut->u64s[1] = SCE_GS_XYZ2;
    ++pxOut;

    // Set top-right XYZ.
    pxOut->u64s[0] = SCE_GS_SET_XYZ2(
        __xBottomRight[0],
        __xTopLeft[1],
        0
    );
    pxOut->u64s[1] = SCE_GS_XYZ2;
    ++pxOut;

    // Set bottom-right XYZ.
    pxOut->u64s[0] = SCE_GS_SET_XYZ2(
        __xBottomRight[0],
        __xBottomRight[1],
        0
    );
    pxOut->u64s[1] = SCE_GS_XYZ2;
    ++pxOut;

    // Set bottom-left XYZ.
    pxOut->u64s[0] = SCE_GS_SET_XYZ2(
        __xTopLeft[0],
        __xBottomRight[1],
        0
    );
    pxOut->u64s[1] = SCE_GS_XYZ2;
    ++pxOut;

    // Set top-left XYZ.
    pxOut->u64s[0] = SCE_GS_SET_XYZ2(
        __xTopLeft[0],
        __xTopLeft[1],
        0
    );
    pxOut->u64s[1] = SCE_GS_XYZ2;
    ++pxOut;

    // Check we wrote the amount of data we expect. Note that we also
    // wrote the GIF tag, which is not included in the NLOOP count.
    Asura_Assert( static_cast<unsigned>(pxOut - pxOutputStart) == uNLOOP + 1, "" );

    // Send to the GS using NORMAL DMA mode.
    {
        // Set the number of QWs to be transferred.
        *D2_QWC = uNLOOP + 1;

        // Set the start address.
        *D2_MADR = reinterpret_cast<unsigned>( Asura_PS2_DMAFromSPR(pxOutputStart) );

        // Ask for transfer completion to be reported on coprocessor.
        *D_PCR = 1 << D_PCR_CPC2_O;
        *D_STAT = 1 << D_STAT_CIS2_O;

        // Force those values to be written to the registers.
        asm( "sync.l" );

        // Setup channel control register.
        *D2_CHCR = (1 << D_CHCR_DIR_O)  // From memory.
                 | (0 << D_CHCR_MOD_O)  // Normal mode.
                 | (0 << D_CHCR_ASP_O)  // No address pushed by call tag.
                 | (0 << D_CHCR_TTE_O)  // Irrelevant in normal mode.
                 | (0 << D_CHCR_TIE_O)  // Irrelevant in normal mode (?).
                 | (1 << D_CHCR_STR_O); // Start DMA transfer.

        // Go go go.
        asm( "sync.l" );

        // Wait for completion.
        asm __volatile__( " _DrawSunBoundingSquare_WaitForDMA:         " );
        asm __volatile__( "     bc0f _DrawSunBoundingSquare_WaitForDMA " );
        asm __volatile__( "     nop                                    " );
    }

    Asura_PS2_SPR_Dealloc( pxOutputStart );
}

//////////////////////////////////////////////////////////////////////////////
//
// FUNCTION     ReadDataFromGS().
// PARAMETERS   
// RETURNS      None.
// DESCRIPTION  
// AUTHOR       Morgan Parry - 18.01.2002.
//
//////////////////////////////////////////////////////////////////////////////
static void ReadDataFromGS(
    u_long128* __puDestBuffer,
    unsigned __uSizeOfDestBuffer,          // In QWs.
    unsigned __uSrcAddr,                   // Word address / 64.
    unsigned __uPixelStorageMode,
    unsigned __uX, unsigned __uY,          // In pixels.
    unsigned __uWidth, unsigned __uHeight, // In pixels.
    unsigned __uSrcBufferWidth             // In pixels.
)
{
    sceGsSyncPath( 0, 0 );

    // Store the contents of the D1_CHCR register since sceGsExecStoreImage()
    // changes it.
    const unsigned uStoredD1CHCR = *D1_CHCR;

    // Divide src buffer width by 64; this is what sceGsExecStoreImage()
    // expects.
    __uSrcBufferWidth >>= 6;

    // (MP - 18.01.2002) Using these library functions is sloooooow. There
    // is a Sony sample available that provides much faster code.
    sceGsStoreImage xStoreImageInfo;
    sceGsSetDefStoreImage(
        &xStoreImageInfo,
        __uSrcAddr,
        __uSrcBufferWidth,
        __uPixelStorageMode,
        __uX, __uY,
        __uWidth, __uHeight
    );
    FlushCache( WRITEBACK_DCACHE );

    // Transfer.
    sceGsExecStoreImage( &xStoreImageInfo, __puDestBuffer );
    FlushCache( WRITEBACK_DCACHE );

    // Restore the contents of the D1_CHCR register
    *D1_CHCR = uStoredD1CHCR;
    asm( "sync.l" );
}
// End function ReadDataFromGS().


// (MP - 03.01.2002) Broken fog code. Can't get the MoveRGToBA() function to
// work.
//
//#define USE_SAMPLE_CODE_FOR_FOGGING (1)
//
//DEBUGVAR unsigned dbg_uFogSpriteAlpha = 128;
//
//#if !USE_SAMPLE_CODE_FOR_FOGGING
//
//static void MoveRGToBA( void )
//{
//    // This function assumes a 32-bit frame buffer.
//    #if ASURA_PS2_FRAMEBFR_BIT_DEPTH != 32
//        #error This function only works with a 32-bit frame buffer.
//    #endif
//
//    const unsigned uScreenWidth = Asura_PS2_GS::GetScreenWidth();
//    const unsigned uScreenHeight = Asura_PS2_GS::GetScreenHeight();
//
//    const unsigned uStripWidth = 8; // In pixels.
//    Asura_Assert( uScreenWidth % uStripWidth == 0, "" );
//    const unsigned uNumStrips = uScreenWidth / uStripWidth;
//    Asura_Assert( (uNumStrips & 1) == 0, "" );
//
//    // 11 QWs for setup plus 4 QWs per strip we draw. Note that we skip odd
//    // strips.
//    const unsigned uNLOOP = 11 + (uNumStrips / 2) * 4;
//
//    // Check the data will fit on the scratchpad. We'll write NLOOP QWs of
//    // register settings plus an extra QW for the GIF tag. The scratchpad has
//    // room for 1024 QWs.
//    Asura_Assert( uNLOOP + 1 <= 1024, "" );
//
//    Asura_PS2_QW* pxOut = Asura_PS2_SPR_Alloc( 0, uNLOOP + 1 );
//    Asura_PS2_QW* const pxBase = pxOut;
//
//    // Write GIF tag. We'll send data using A+D, ie. "address and data", mode,
//    // since we have to set various different registers.
//    {
//        Asura_PS2_GifTag* const pxGifTag = reinterpret_cast<Asura_PS2_GifTag*>( pxOut );
//        pxGifTag->Set(
//            uNLOOP,
//            true,
//            false,
//            0,
//            SCE_GIF_PACKED,
//            1,
//            SCE_GIF_PACKED_AD
//        );
//    }
//    ++pxOut;
//
//    // Setup frame buffer register. We want to restrict writes to the alpha
//    // channel, which is the upper 8 bits (as we're only writing the BA strips
//    // and skipping the RG ones.) The FBMSK value corresponds to the pixel
//    // value before format conversion, hence the strange 0x000038f8 value;
//    // see §3.9.5 of the GS User's Manual.
//    {
//        const unsigned uBaseAddr = ( Asura_PS2_GS::CurrentFrameBuffer ? ASURA_PS2_FRAMEBFR_0_BASE_PTR : ASURA_PS2_FRAMEBFR_1_BASE_PTR );
//        pxOut->u64s[0] = SCE_GS_SET_FRAME_1(
//            uBaseAddr,          // FBP   - Frame buffer base address.
//            uScreenWidth / 64,  // FBW   - Frame buffer width in units of pixels / 64.
//            SCE_GS_PSMCT16,     // PSM   - Frame buffer format.
//            0x000038f8          // FBMSK - Frame buffer write mask.
//        );
//        pxOut->u64s[1] = SCE_GS_FRAME_1;
//    }
//    ++pxOut;
//
//    // Disable writes to the Z buffer.
//    pxOut->u64s[0] = SCE_GS_SET_ZBUF(
//        ASURA_PS2_ZBFR_BASE_PTR,// ZBP   - Z buffer base address = word address / 2048.
//        ASURA_PS2_ZBFR_FMT,     // PSM   - Z buffer format.
//        1                       // ZMSK  - Write mask - write iff 0.
//    );
//    pxOut->u64s[1] = SCE_GS_ZBUF_1;
//    ++pxOut;
//
//    // Setup pixel test. We want to disable the depth test but there is a 
//    // known bug with setting ZTE to false; instead we set ZTE to true and
//    // set the method to be ALWAYS.
//    pxOut->u64s[0] = SCE_GS_SET_TEST_1(
//        false,                  // ATE   - Alpha test on iff true.
//        0,                      // ATST  - Alpha test method. Irrelevant if ATE is false.
//        0,                      // AREF  - Alpha reference value. Irrelevant if ATE is false.
//        0,                      // AFAIL - Behaviour when alpha test fails. Irrelevant if ATE is false.
//        false,                  // DATE  - Destination alpha test on iff true.
//        0,                      // DATM  - Destination alpha test method. Irrelevant if DATE is false.
//        true,                   // ZTE   - Depth test on iff true.
//        SCE_GS_ZALWAYS          // ZTST  - Depth test method.
//    );
//    pxOut->u64s[1] = SCE_GS_TEST_1;
//    ++pxOut;
//
//    // Scissor settings. Since we're pretending to the GS that we've got a
//    // 16-bit frame buffer (when really we're using 32), we need to double
//    // the height.
//    pxOut->u64s[0] = SCE_GS_SET_SCISSOR_1(
//        0,                      // SCAX0 - Upper-left X.
//        uScreenWidth - 1,       // SCAX1 - Bottom-right X.
//        0,                      // SCAY0 - Upper-left Y.
//        uScreenHeight * 2 - 1   // SCAY1 - Bottom-right Y.
//    );
//    pxOut->u64s[1] = SCE_GS_SCISSOR_1;
//    ++pxOut;
//        
//    // Flush texture cache to make sure all previous drawing has completed.
//    pxOut->u64s[0] = 0;
//    pxOut->u64s[1] = SCE_GS_TEXFLUSH;
//    ++pxOut;
//
//    // Setup texture alpha register, ie. the values that get used when the
//    // alpha value of a texture is not a full 8-bit value.
//    pxOut->u64s[0] = SCE_GS_SET_TEXA(
//        0,                      // TA0   - The alpha source value when alpha field is 0 in RGBA16 format or else format is RGB24.
//        false,                  // AEM   - Treat black textures as transparent iff true.
//        128                     // TA1   - Alpha source value when alpha field is 1 in RGBA16 format.
//    );
//    pxOut->u64s[1] = SCE_GS_TEXA;
//    ++pxOut;
//
//    // Setup texture filtering.
//    pxOut->u64s[0] = SCE_GS_SET_TEX1_1(
//        0,                      // LCM   - LOD calculation method.
//        0,                      // MXL   - Maximum MIP level.
//        SCE_GS_NEAREST,         // MMAG  - Filter when texture is expanded.
//        SCE_GS_NEAREST,         // MMIN  - Filter when texture is reduced.
//        0,                      // MTBA  - 
//        0,                      // L     - LOD parameter value L.
//        0                       // K     - LOD parameter value K.
//    );
//    pxOut->u64s[1] = SCE_GS_TEX1_1;
//    ++pxOut;
//
//    // Set texture information. Our texture is the Z buffer. We have the Z
//    // buffer address as (word addr / 2048) so we need to multiply by
//    // (2048 / 64) to get (word addr / 64).
//    {
//        const unsigned uBasePtr = ASURA_PS2_ZBFR_BASE_PTR << 5;
//
//        pxOut->u64s[0] = SCE_GS_SET_TEX0_1(
//            uBasePtr,           // TBP0  - Texture base pointer = word address / 64.
//            uScreenWidth / 64,  // TBW   - Texture buffer width in units of texels / 64.
//            SCE_GS_PSMZ16,      // PSM   - Texture pixel storage format.
//            10,                 // TW    - Texture width = log2 of width.
//            10,                 // TH    - Texture height = log2 of height.
//            1,                  // TCC   - Texture colour component. 1 => RGBA.
//            SCE_GS_DECAL,       // TFX   - Texture function.
//            0,                  // CBP   - CLUT buffer base pointer = word address / 64.
//            0,                  // CPSM  - CLUT pixel storage format.
//            0,                  // CSM   - CLUT storage mode.
//            0,                  // CSA   - CLUT entry offset.
//            0                   // CLD   - CLUT buffer load control.
//        );
//        pxOut->u64s[1] = SCE_GS_TEX0_1;
//    }
//    ++pxOut;
//
//    // Setup PRIM info.
//    pxOut->u64s[0] = SCE_GS_SET_PRIM(
//        SCE_GS_PRIM_SPRITE,     // PRIM  - Primitive type.
//        0,                      // IIP   - Shading method. 0 => flat shading.
//        true,                   // TME   - Texture mapping on iff true.
//        false,                  // FGE   - Fogging on iff true.
//        false,                  // ABE   - Alpha blending on iff true.
//        false,                  // AA1   - 1 pass antialiasing on iff true.
//        1,                      // FST   - Method of specifying texture coordinates. 1 => UVs.
//        0,                      // CTXT  - Context to use.
//        0                       // FIX.
//    );
//    pxOut->u64s[1] = SCE_GS_PRIM;
//    ++pxOut;
//
//    // Set RGBAQ of sprite.
//    {
//        const float fOne = 1.0f;
//        const unsigned* puHexOfOneFloat = reinterpret_cast<const unsigned*>( &fOne );
//
//        pxOut->u64s[0] = SCE_GS_SET_RGBAQ(
//            128,                // R.
//            128,                // G.
//            128,                // B.
//            128,                // A.
//            *puHexOfOneFloat    // Q.
//        );
//        pxOut->u64s[1] = SCE_GS_RGBAQ;
//    }
//    ++pxOut;
//
//    // Copy in 8-pixel wide strips.
//    const unsigned uTopLeftOffsetX = ASURA_PS2_SCREEN_CENTRE_X - uScreenWidth / 2;
//    const unsigned uTopLeftOffsetY = ASURA_PS2_SCREEN_CENTRE_Y - uScreenHeight / 2;
//    unsigned uSrcXOffset = 0;
//    unsigned uDestXOffset = uStripWidth;
//    for( unsigned u = 0; u < uNumStrips; u += 2 )
//    {
//        // Upper-left UV.
//        {
//            const unsigned uTLU = uSrcXOffset;
//            const unsigned uTLV = 0;
//            pxOut->u64s[0] = SCE_GS_SET_UV(
//                uTLU << 4,      // U     - U coordinate in 10:4 fixed point.
//                uTLV << 4       // V     - V coordinate in 10:4 fixed point.
//            );
//            pxOut->u64s[1] = SCE_GS_UV;
//            ++pxOut;
//        }
//
//        // Upper-left XYZ.
//        {
//            const unsigned uTLX = uTopLeftOffsetX + uDestXOffset;
//            const unsigned uTLY = uTopLeftOffsetY;
//            pxOut->u64s[0] = SCE_GS_SET_XYZ(
//                uTLX << 4,      // X     - X coordinate in 12:4 fixed point.
//                uTLY << 4,      // Y     - Y coordinate in 12:4 fixed point.
//                0               // Z     - Z coordinate in 12:4 fixed point.
//            );
//            pxOut->u64s[1] = SCE_GS_XYZ2;
//        }
//        ++pxOut;
//
//        // Bottom-right UV.
//        {
//            const unsigned uBRU = uSrcXOffset + uStripWidth;
//            const unsigned uBRV = uScreenHeight * 2;
//            pxOut->u64s[0] = SCE_GS_SET_UV(
//                uBRU << 4,
//                uBRV << 4
//            );
//            pxOut->u64s[1] = SCE_GS_UV;
//            ++pxOut;
//        }
//
//        // Bottom-right XYZ.
//        {
//            const unsigned uBRX = uTopLeftOffsetX + uDestXOffset + uStripWidth;
//            const unsigned uBRY = uTopLeftOffsetY + uScreenHeight * 2;
//            pxOut->u64s[0] = SCE_GS_SET_XYZ(
//                uBRX << 4,
//                uBRY << 4,
//                0
//            );
//            pxOut->u64s[1] = SCE_GS_XYZ2;
//        }
//        ++pxOut;
//
//        uSrcXOffset  += uStripWidth * 2;
//        uDestXOffset += uStripWidth * 2;
//    }
//
//    // Reset scissor settings.
//    pxOut->u64s[0] = SCE_GS_SET_SCISSOR_1(
//        0,                      // SCAX0 - Upper-left X.
//        uScreenWidth - 1,       // SCAX1 - Bottom-right X.
//        0,                      // SCAY0 - Upper-left Y.
//        uScreenHeight - 1       // SCAY1 - Bottom-right Y.
//    );
//    pxOut->u64s[1] = SCE_GS_SCISSOR_1;
//    ++pxOut;
//    
//    // Verify we output the expected amount of data. This means NLOOP QWs for
//    // all the register settings plus 1 QW for the GIF tag itself.
//    Asura_Assert( static_cast<unsigned>(pxOut - pxBase) == uNLOOP + 1, "" );
//
//    // Send to the GS using NORMAL DMA mode.
//    {
//        // Set the number of QWs to be transferred.
//        *D2_QWC = uNLOOP + 1;
//
//        // Set the start address.
//        *D2_MADR = reinterpret_cast<unsigned>( Asura_PS2_DMAFromSPR(pxBase) );
//
//        // Ask for transfer completion to be reported on coprocessor.
//        *D_PCR = 1 << D_PCR_CPC2_O;
//        *D_STAT = 1 << D_STAT_CIS2_O;
//
//        // Force those values to be written to the registers.
//        asm( "sync.l" );
//
//        // Setup channel control register.
//        *D2_CHCR = (1 << D_CHCR_DIR_O)  // From memory.
//                 | (0 << D_CHCR_MOD_O)  // Normal mode.
//                 | (0 << D_CHCR_ASP_O)  // No address pushed by call tag.
//                 | (0 << D_CHCR_TTE_O)  // Irrelevant in normal mode.
//                 | (0 << D_CHCR_TIE_O)  // Irrelevant in normal mode (?).
//                 | (1 << D_CHCR_STR_O); // Start DMA transfer.
//
//        // Go go go.
//        asm( "sync.l" );
//
//        // Wait for completion.
//        asm __volatile__( " _MoveRGToBA_WaitForDMA:         " );
//        asm __volatile__( "     bc0f _MoveRGToBA_WaitForDMA " );
//        asm __volatile__( "     nop                         " );
//    }
//
//    Asura_PS2_SPR_Dealloc( pxBase );
//}
//
//DEBUGVAR unsigned dbg_uFogSpriteZ = 32768;
//
//static void DrawFogSprite( void )
//{
//    const unsigned uScreenWidth = Asura_PS2_GS::GetScreenWidth();
//    const unsigned uScreenHeight = Asura_PS2_GS::GetScreenHeight();
//
//    const unsigned uStripWidth = 32; // In pixels.
//    const unsigned uNumStrips = uScreenWidth / uStripWidth;
//
//    const unsigned uNLOOP = 5 + (uNumStrips * 2);
//
//    // Check the data will fit on the scratchpad. We'll write NLOOP QWs of
//    // register settings plus an extra QW for the GIF tag. The scratchpad has
//    // room for 1024 QWs.
//    Asura_Assert( uNLOOP + 1 <= 1024, "" );
//
//    Asura_PS2_QW* pxOut = Asura_PS2_SPR_Alloc( 0, uNLOOP + 1 );
//    Asura_PS2_QW* const pxBase = pxOut;
//
//    // Write GIF tag. We'll send data using A+D, ie. "address and data", mode
//    // since we have to set various different registers.
//    {
//        Asura_PS2_GifTag* const pxGifTag = reinterpret_cast<Asura_PS2_GifTag*>( pxOut );
//        pxGifTag->Set(
//            uNLOOP,
//            true,
//            false,
//            0,
//            SCE_GIF_PACKED,
//            1,
//            SCE_GIF_PACKED_AD
//        );
//    }
//    ++pxOut;
//
//    // Setup frame buffer.
//    {
//        const unsigned uBaseAddr = ( Asura_PS2_GS::CurrentFrameBuffer ? ASURA_PS2_FRAMEBFR_0_BASE_PTR : ASURA_PS2_FRAMEBFR_1_BASE_PTR );
//        pxOut->u64s[0] = SCE_GS_SET_FRAME_1(
//            uBaseAddr,          // FBP   - Frame buffer base address.
//            uScreenWidth / 64,  // FBW   - Frame buffer width in units of pixels / 64.
//            SCE_GS_PSMCT32,     // PSM   - Frame buffer format.
//            0                   // FBMSK - Frame buffer write mask.
//        );
//        pxOut->u64s[1] = SCE_GS_FRAME_1;
//    }
//    ++pxOut;
//
//    // Setup pixel test.
//    pxOut->u64s[0] = SCE_GS_SET_TEST_1(
//        false,                  // ATE   - Alpha test on iff true.
//        0,                      // ATST  - Alpha test method. Irrelevant if ATE is false.
//        0,                      // AREF  - Alpha reference value. Irrelevant if ATE is false.
//        0,                      // AFAIL - Behaviour when alpha test fails. Irrelevant if ATE is false.
//        false,                  // DATE  - Destination alpha test on iff true.
//        0,                      // DATM  - Destination alpha test method. Irrelevant if DATE is false.
//        true,                   // ZTE   - Depth test on iff true.
//        SCE_GS_ZGREATER         // ZTST  - Depth test method.
//    );
//    pxOut->u64s[1] = SCE_GS_TEST_1;
//    ++pxOut;
//
//    // Setup alpha blend. This is RGBd * Ad + RGBs * (1 - Ad).
//    pxOut->u64s[0] = SCE_GS_SET_ALPHA(
//        1,                      // A     - 1 => dest RGB.
//        0,                      // B     - 0 => src RGB.
//        1,                      // C     - 1 => dest alpha.
//        0,                      // D     - 0 => src RGB.
//        0                       // FIX   - Irrelevant unless C is 2.
//    );
//    pxOut->u64s[1] = SCE_GS_ALPHA_1;
//    ++pxOut;
//
//    // Setup PRIM info.
//    pxOut->u64s[0] = SCE_GS_SET_PRIM(
//        SCE_GS_PRIM_SPRITE,     // PRIM  - Primitive type.
//        0,                      // IIP   - Shading method. 0 => flat shading.
//        false,                  // TME   - Texture mapping on iff true.
//        false,                  // FGE   - Fogging on iff true.
//        true,                   // ABE   - Alpha blending on iff true.
//        false,                  // AA1   - 1 pass antialiasing on iff true.
//        0,                      // FST   - Irrelevant since TME is false.
//        0,                      // CTXT  - Context to use.
//        0                       // FIX.
//    );
//    pxOut->u64s[1] = SCE_GS_PRIM;
//    ++pxOut;
//
//    // Set RGBAQ of sprite.
//    {
//        const float fOne = 1.0f;
//        const unsigned* puHexOfOneFloat = reinterpret_cast<const unsigned*>( &fOne );
//
//        pxOut->u64s[0] = SCE_GS_SET_RGBAQ(
//            32,                 // R.
//            32,                 // G.
//            32,                 // B.
//            dbg_uFogSpriteAlpha,// A.
//            *puHexOfOneFloat    // Q.
//        );
//        pxOut->u64s[1] = SCE_GS_RGBAQ;
//    }
//    ++pxOut;
//
//    // Write strip XYZs.
//    const unsigned uTopLeftOffsetX = ASURA_PS2_SCREEN_CENTRE_X - uScreenWidth / 2;
//    const unsigned uTopLeftOffsetY = ASURA_PS2_SCREEN_CENTRE_Y - uScreenHeight / 2;
//    const unsigned uZ = dbg_uFogSpriteZ;
//    unsigned uXOffset = 0;
//    for( unsigned u = 0; u < uNumStrips; ++u )
//    {
//        // Upper-left XYZ.
//        {
//            const unsigned uTLX = uTopLeftOffsetX + uXOffset;
//            const unsigned uTLY = uTopLeftOffsetY + 0;
//            pxOut->u64s[0] = SCE_GS_SET_XYZ(
//                uTLX << 4,      // X     - X coordinate in 12:4 fixed point.
//                uTLY << 4,      // Y     - Y coordinate in 12:4 fixed point.
//                uZ              // Z     - Z coordinate in 12:4 fixed point.
//            );
//            pxOut->u64s[1] = SCE_GS_XYZ2;
//        }
//        ++pxOut;
//
//        // Bottom-right XYZ.
//        {
//            const unsigned uBRX = uTopLeftOffsetX + uXOffset + uStripWidth;
//            const unsigned uBRY = uTopLeftOffsetY + uScreenHeight;
//            pxOut->u64s[0] = SCE_GS_SET_XYZ(
//                uBRX << 4,
//                uBRY << 4,
//                uZ
//            );
//            pxOut->u64s[1] = SCE_GS_XYZ2;
//        }
//        ++pxOut;
//
//        uXOffset += uStripWidth;
//    }
//
//    // Verify we output the expected amount of data. This means NLOOP QWs for
//    // all the register settings plus 1 QW for the GIF tag itself.
//    Asura_Assert( static_cast<unsigned>(pxOut - pxBase) == uNLOOP + 1, "" );
//    
//    // Send to the GS using NORMAL DMA mode.
//    {
//        // Set the number of QWs to be transferred.
//        *D2_QWC = uNLOOP + 1;
//
//        // Set the start address.
//        *D2_MADR = reinterpret_cast<unsigned>( Asura_PS2_DMAFromSPR(pxBase) );
//
//        // Ask for transfer completion to be reported on coprocessor.
//        *D_PCR = 1 << D_PCR_CPC2_O;
//        *D_STAT = 1 << D_STAT_CIS2_O;
//
//        // Force those values to be written to the registers.
//        asm( "sync.l" );
//
//        // Setup channel control register.
//        *D2_CHCR = (1 << D_CHCR_DIR_O)  // From memory.
//                 | (0 << D_CHCR_MOD_O)  // Normal mode.
//                 | (0 << D_CHCR_ASP_O)  // No address pushed by call tag.
//                 | (0 << D_CHCR_TTE_O)  // Irrelevant in normal mode.
//                 | (0 << D_CHCR_TIE_O)  // Irrelevant in normal mode (?).
//                 | (1 << D_CHCR_STR_O); // Start DMA transfer.
//
//        // Go go go.
//        asm( "sync.l" );
//
//        // Wait for completion.
//        asm __volatile__( " _DrawFogSprite_WaitForDMA:         " );
//        asm __volatile__( "     bc0f _DrawFogSprite_WaitForDMA " );
//        asm __volatile__( "     nop                            " );
//    }
//
//    Asura_PS2_SPR_Dealloc( pxBase );
//}
//
//#else // not !USE_SAMPLE_CODE_FOR_FOGGING
//
//struct FromSample_SPRITE {
//
//	int r,g,b,a;
//	int x0,y0;
//	int x1,y1;
//	int u0,v0; 
//	int u1,v1; 
//	int w;
//	int h;
//	int x;
//	int y; 
//
//};
//
//static FromSample_SPRITE FromSample_sprite;
//
//static void FromSample_SetSpriteRGBA( u_char r, u_char g, u_char b, u_char a )
//{
//	FromSample_sprite.r = r;
//	FromSample_sprite.g = g;
//	FromSample_sprite.b = b;
//	FromSample_sprite.a = a;
//}
//
//#define OFFX (ASURA_PS2_SCREEN_CENTRE_X - Asura_PS2_GS::GetScreenWidth()  / 2)
//#define OFFY (ASURA_PS2_SCREEN_CENTRE_Y - Asura_PS2_GS::GetScreenHeight() / 2)
//
//static void FromSample_SetSpriteCoords( short u0, short v0, short u1, short v1, int x, int y, int w, int h, short center )
//{
//	// source
//
//	FromSample_sprite.u0 = ( u0 << 4 );
//	FromSample_sprite.v0 = ( v0 << 4 );
//
//	FromSample_sprite.u1 = ( u1 << 4 );
//	FromSample_sprite.v1 = ( v1 << 4 );
//
//	if( center )
//	{
//		FromSample_sprite.u0 +=8;
//		FromSample_sprite.u1 +=8;
//		FromSample_sprite.v0 +=8;
//		FromSample_sprite.v1 +=8;
//	}	 
//
//	// destination
//
//	FromSample_sprite.x = ( x << 4 );
//	FromSample_sprite.y = ( y << 4 );
//
//	FromSample_sprite.w = w << 4;
//	FromSample_sprite.h = h << 4;
//
//	FromSample_sprite.x0 = OFFX + FromSample_sprite.x;
//	FromSample_sprite.y0 = OFFY + FromSample_sprite.y;
//
//	FromSample_sprite.x1 = FromSample_sprite.x0 + FromSample_sprite.w;
//	FromSample_sprite.y1 = FromSample_sprite.y0 + FromSample_sprite.h;
//
//
//	// set color
//
//	FromSample_sprite.r = 0x80;
//	FromSample_sprite.g = 0x80;
//	FromSample_sprite.b = 0x80;
//	FromSample_sprite.a = 0x80;
//}
//
//static void FromSample_FogSprite( void )
//{
//    const int iScreenWidth = Asura_PS2_GS::GetScreenWidth();
//    const int iScreenHeight = Asura_PS2_GS::GetScreenHeight();
//
//    const sceGsDBuff& xDblBfrInfo = Asura_PS2_GS::DoubleBuffer;
//    const int iCurBfr = Asura_PS2_GS::CurrentFrameBuffer;
//    const unsigned uBaseAddr = ( iCurBfr ? xDblBfrInfo.draw1.frame1.FBP : xDblBfrInfo.draw0.frame1.FBP );
//
//	sceGifPacket gif_pkt;
//	static u_long128 mem[50];
//	u_long128 *base_ptr=NULL;
//	int cnt=0;
//	int strip_width = 32;
//	int xoffset=0;
//    int num_strips = iScreenWidth / strip_width;
//	int zvert = 32768;
//
//	base_ptr = (u_long128*)( ( u_int )mem | ASURA_PS2_UNCACHED_MEM_FLAG );
//
//	sceGifPkInit(&gif_pkt, base_ptr );
//	sceGifPkReset(&gif_pkt);
//
//	// set GIF tag 
//	sceGifPkAddGsData( &gif_pkt, SCE_GIF_SET_TAG( 7+(num_strips*2), /*GIFTAG_EOP*/1, 0, 0, SCE_GIF_PACKED, 1 ) );
//	sceGifPkAddGsData( &gif_pkt, 0xEL ); 
//
//	// set frame buffer settings
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_SET_FRAME_1(uBaseAddr, iScreenWidth/64, SCE_GS_PSMCT32, 0));
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_FRAME_1);
//
//	sceGifPkAddGsData(&gif_pkt,	SCE_GS_SET_ZBUF( ASURA_PS2_ZBFR_BASE_PTR, SCE_GS_PSMZ24,1 )); // no Z write
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_ZBUF_1);
//
//	// pixel test control
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_SET_TEST_1(0,0,0,0,0,0,1,SCE_GS_ZGREATER));
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_TEST_1);			   
//
//	// offset value ( PRIM coord -> WIN coord )
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_SET_XYOFFSET_1( OFFX, OFFY ));
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_XYOFFSET_1);
//
//	// alpha blend settings A  B  C  D  FIX - (Cd-Cs)*Ad+Cs
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_SET_ALPHA(1, 0, 1, 0, 0) );
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_ALPHA_1);
//
//	// set PRIM info
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_SET_PRIM( SCE_GS_PRIM_SPRITE, 0, 0,
//		0,/*GS_PRIM_ALPHA*/1, 0,
//		0, 0, 0) );
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_PRIM);
//
//	// set RGBA of sprite
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_SET_RGBAQ(FromSample_sprite.r, FromSample_sprite.g, 
//		FromSample_sprite.b, FromSample_sprite.a, 0x3f800000));
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_RGBAQ);
//
//	// Screen size for this example is 640 x 448
//	// 20 sprites (32w x 448h size strips)
//
//	for( cnt=0; cnt< num_strips;cnt++)
//	{
//		// set upper-left position of sprite
//		sceGifPkAddGsData( &gif_pkt, SCE_GS_SET_XYZ( OFFX+(xoffset<<4), OFFY, zvert ) );
//		sceGifPkAddGsData( &gif_pkt, SCE_GS_XYZF2 );
//
//		// set lower-right position of sprite
//		sceGifPkAddGsData( &gif_pkt,
//			SCE_GS_SET_XYZ( OFFX + ( (xoffset+strip_width) << 4 ), OFFY + ( iScreenHeight << 4 ), zvert ) );
//		sceGifPkAddGsData( &gif_pkt, SCE_GS_XYZF2 );
//
//		xoffset+=strip_width;
//	}	
//
//
//	//sceGifPkDump(&gif_pkt);
//
//	// set packet size in quad words
//	sceGifPkTerminate(&gif_pkt);
//
//	//printf("size%d\n",sceGifPkSize(&gif_pkt));
//
//	// DMA send (Normal Mode) to GS via path 3
//    {
//	    sceGsSyncPath(0, 0);
//
//        sceDmaSendN(
//            Asura_PS2_GS::GetDmaChannel(),
//            (u_long128*)((u_int)gif_pkt.pBase & ASURA_PS2_DMA_MEM_MASK),
//            sceGifPkSize(&gif_pkt)
//        );
//    }
//}
//
//static void FromSample_MoveRG2BA( int src_buff, unsigned dest_buff )
//{
//    const int iScreenWidth = Asura_PS2_GS::GetScreenWidth();
//    const int iScreenHeight = Asura_PS2_GS::GetScreenHeight();
//
//	sceGifPacket gif_pkt;
//	static u_long128 mem[175];
//	u_long128 *base_ptr=NULL;
//	int cnt=0;
//	int dest_strip_width=8;
//	int src_strip_width=8;
//	int dest_h=iScreenHeight * 2;
//	int src_h=iScreenHeight * 2;
//	int src_xoffset=0;
//	int dest_xoffset=8;
//	int num_strips = iScreenWidth/src_strip_width;
//
//	base_ptr = (u_long128*)( ( u_int )mem | ASURA_PS2_UNCACHED_MEM_FLAG );
//
//	sceGifPkInit(&gif_pkt, base_ptr );
//	sceGifPkReset(&gif_pkt);
//
//	// GIF tag
//	sceGifPkAddGsData(&gif_pkt, SCE_GIF_SET_TAG(12+((num_strips/2)*4),/*GIFTAG_EOP*/1,0,0,SCE_GIF_PACKED,1) );
//	sceGifPkAddGsData(&gif_pkt, 0xEL ); 
//
//	// set frame buffer settings
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_SET_FRAME_1(dest_buff, iScreenWidth/64, SCE_GS_PSMCT16, 0x00003FFF));
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_FRAME_1);
//
//	sceGifPkAddGsData(&gif_pkt,	SCE_GS_SET_ZBUF( ASURA_PS2_ZBFR_BASE_PTR, SCE_GS_PSMZ24,1 )); // no Z writes
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_ZBUF_1);
//
//	// pixel test control
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_SET_TEST_1(0,0,0,0,0,0,1,SCE_GS_ZALWAYS));
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_TEST_1);
//
//	// offset value ( PRIM coord -> WIN coord )
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_SET_XYOFFSET_1( OFFX, OFFY ));
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_XYOFFSET_1);
//
//	// scissor settings ( WIN coordinates x0,x1,y0,y1 )
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_SET_SCISSOR_1(0,iScreenWidth-1,0,(iScreenHeight*2)-1));
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_SCISSOR_1);
//
//	// flush the texture cache
//	sceGifPkAddGsData(&gif_pkt, 0 );
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_TEXFLUSH );
//
//	// TA0, AE1, TA1
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_SET_TEXA(0x0,0x0,0x80) );
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_TEXA );
//
//	// set filtering
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_SET_TEX1_1(0, 0, 0, 0, 0, 0, 0));
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_TEX1_1);
//
//	// set texture information 
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_SET_TEX0_1(src_buff, iScreenWidth / 64, SCE_GS_PSMZ16, 
//		10, 10, 1, SCE_GS_DECAL, 
//		0, 0,
//		0, 0, 0 ) );  
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_TEX0_1);
//
//	// set PRIM info
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_SET_PRIM( SCE_GS_PRIM_SPRITE, 0, /*GS_PRIM_TEX*/1,
//		0,0,0,
//		/*GS_PRIM_UV*/1, 0, 0) );
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_PRIM);
//
//	// set RGBA of sprite
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_SET_RGBAQ(FromSample_sprite.r, FromSample_sprite.g, 
//		FromSample_sprite.b, FromSample_sprite.a, 0x3f800000));
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_RGBAQ);
//
//	// Screen size for this example is 640 x 896
//	// 40 sprites (8w x 896h size strips)
//
//	for( cnt=0; cnt<num_strips;cnt+=2 )
//	{
//
//		// SetSpriteCoords( 0, 0, 640, 896, 8, 0, 640, 896, 1 );
//
//		FromSample_SetSpriteCoords( src_xoffset, 0, src_xoffset+src_strip_width, src_h, 
//			dest_xoffset, 0, dest_strip_width, dest_h, 1 );
//
//		// set upper-left position of sprite
//		sceGifPkAddGsData(&gif_pkt, SCE_GS_SET_UV(FromSample_sprite.u0, FromSample_sprite.v0) );
//		sceGifPkAddGsData(&gif_pkt, SCE_GS_UV);
//
//		sceGifPkAddGsData(&gif_pkt, SCE_GS_SET_XYZ(FromSample_sprite.x0, FromSample_sprite.y0,0) );
//		sceGifPkAddGsData(&gif_pkt, SCE_GS_XYZ2);
//
//		// set lower-right position of sprite
//		sceGifPkAddGsData(&gif_pkt, SCE_GS_SET_UV(FromSample_sprite.u1, FromSample_sprite.v1) );
//		sceGifPkAddGsData(&gif_pkt, SCE_GS_UV);
//
//		sceGifPkAddGsData(&gif_pkt, SCE_GS_SET_XYZ(FromSample_sprite.x1, FromSample_sprite.y1,0) );
//		sceGifPkAddGsData(&gif_pkt, SCE_GS_XYZ2);	
//
//		src_xoffset += src_strip_width*2;
//		dest_xoffset += dest_strip_width*2;
//
//	}
//
//	// scissor settings ( WIN coordinates x0,x1,y0,y1 )
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_SET_SCISSOR_1(0,iScreenWidth-1,0,(iScreenHeight)-1));
//	sceGifPkAddGsData(&gif_pkt, SCE_GS_SCISSOR_1);
//
//	//sceGifPkDump(&gif_pkt);
//
//	// set packet size in quad words
//	sceGifPkTerminate(&gif_pkt);
//
//	//printf("size%d\n",sceGifPkSize(&gif_pkt));
//
//	// DMA send (Normal Mode) to GS via path 3		
//	sceGsSyncPath(0, 0);
//    sceDmaSendN(
//        Asura_PS2_GS::GetDmaChannel(),
//        (u_long128*)((u_int)gif_pkt.pBase&ASURA_PS2_DMA_MEM_MASK),
//        sceGifPkSize(&gif_pkt)
//    );
//}
//
//#endif // else not !USE_SAMPLE_CODE_FOR_FOGGING
//
////#include <libvifpk.h>
////// (MP - 18.12.2001) Borrowed from Sony sample "store_vram.zip". This
////// function stalls until the transfer is complete.
////static void ReadDataFromGS( u_long128* base_addr, short start_addr, short pixel_mode, short x,
////		       short y, short w, short h, short frame_width )
////{
////    int texture_qwc;
////    sceVif1Packet vif1_pkt;
////    u_long128 settup_base[10];
////    int buff_width;
////    u_long prev_imr = 0;
////    static u_int enable_path3[4] __attribute__ ( ( aligned( 16 ) ) ) = {
////    0x06000000,
////    0x00000000,
////    0x00000000,
////    0x00000000,
////    };
////
////    // get quad word count for image
////    if ( pixel_mode == SCE_GS_PSMCT32 )
////    texture_qwc = ( w * h * 32 ) >> 7;
////    else if ( pixel_mode == SCE_GS_PSMCT24 )
////    texture_qwc = ( w * h * 24 ) >> 7;
////    else if ( pixel_mode == SCE_GS_PSMCT16 )
////    texture_qwc = ( w * h * 16 ) >> 7;
////    else if ( pixel_mode == SCE_GS_PSMT8 )
////    texture_qwc = ( w * h * 8 ) >> 7;
////    else
////    texture_qwc = ( w * h * 4 ) >> 7;
////
////    // NLOOP is 15 bits => max value is 2^15.
////    Asura_Assert( texture_qwc <= (1 << 15), "" );
////
////    buff_width = frame_width >> 6;
////
////    if ( buff_width <= 0 )
////    buff_width = 1;
////
////    // set base address of GIF packet
////    sceVif1PkInit( &vif1_pkt, &settup_base[0] );
////    sceVif1PkReset( &vif1_pkt );
////
////    // will start transfer with VIF code and GS data will follow
////    sceVif1PkAddCode( &vif1_pkt, SCE_VIF1_SET_NOP( 0 ) );
////    // disable PATH 3 transfer
////    sceVif1PkAddCode( &vif1_pkt, SCE_VIF1_SET_MSKPATH3( 0x8000, 0 ) );
////    // wait for all 3 PATHS to GS to be complete
////    sceVif1PkAddCode( &vif1_pkt, SCE_VIF1_SET_FLUSHA( 0 ) );
////    // transfer 6 QW's to GS
////    sceVif1PkAddCode( &vif1_pkt, SCE_VIF1_SET_DIRECT( 6, 0 ) );
////
////    // GIF tag for texture settings         
////    sceVif1PkAddGsData( &vif1_pkt, SCE_GIF_SET_TAG( 5, 1, NULL, NULL, SCE_GIF_PACKED, 1 ) );
////    sceVif1PkAddGsData( &vif1_pkt, 0xEL ); // A+D
////
////    // set transmission between buffers
////    sceVif1PkAddGsData( &vif1_pkt, SCE_GS_SET_BITBLTBUF( start_addr, buff_width, pixel_mode,	// SRC
////						       NULL, NULL, NULL ) );	// DEST
////    sceVif1PkAddGsData( &vif1_pkt, SCE_GS_BITBLTBUF );
////
////    // set transmission area between buffers        ( source x,y  dest x,y  and direction )
////    sceVif1PkAddGsData( &vif1_pkt, SCE_GS_SET_TRXPOS( x, y, 0, 0, 0 ) );
////    sceVif1PkAddGsData( &vif1_pkt, SCE_GS_TRXPOS );
////
////    // set size of transmission area 
////    sceVif1PkAddGsData( &vif1_pkt, SCE_GS_SET_TRXREG( w, h ) );
////    sceVif1PkAddGsData( &vif1_pkt, SCE_GS_TRXREG );
////
////    // set FINISH event occurrence request
////    sceVif1PkAddGsData( &vif1_pkt, ( u_long ) ( 0x0 ) );
////    sceVif1PkAddGsData( &vif1_pkt, SCE_GS_FINISH );
////
////    // set transmission direction  ( LOCAL -> HOST Transmission )
////    sceVif1PkAddGsData( &vif1_pkt, SCE_GS_SET_TRXDIR( 1 ) );
////    sceVif1PkAddGsData( &vif1_pkt, SCE_GS_TRXDIR );
////
////    // get packet size in quad words        
////    sceVif1PkTerminate( &vif1_pkt );
////
////    // get current IMR status
////    prev_imr = sceGsPutIMR( sceGsGetIMR(  ) | 0x0200 );
////
////    // set the FINISH event
////    DPUT_GS_CSR( GS_CSR_FINISH_M );
////
////    // DMA from memory and start DMA transfer
////    FlushCache( WRITEBACK_DCACHE );
////
////    DPUT_D1_QWC( 0x7 );
////
////    DPUT_D1_MADR( (u_int)vif1_pkt.pBase & ASURA_PS2_DMA_MEM_MASK );
////
////    DPUT_D1_CHCR( 1 | ( 1 << 8 ) );
////
////    asm __volatile__( " sync.l " );
////
////    // check if DMA is complete (STR=0)
////    while( *D1_CHCR & 0x0100 ) { }
//////    printf( " 5 GS registers set\n" );
////
////    // check if FINISH event occured
////    while( !(*GS_CSR & GS_CSR_FINISH_M) ) { }
//////    printf( " Finish event complete\n" );
////
////    // change VIF1-FIFO transfer direction (VIF1 -> MAIN MEM or SPR)
////    *VIF1_STAT = 0x00800000;
////
////    // change GS bus direction (LOCAL->HOST)
////    DPUT_GS_BUSDIR( ( u_long ) 0x00000001 );
////
//////    printf( " Changed VIF1 and GS direction complete\n" );
////
////    // DMA to memory and start DMA transfer
////    FlushCache( WRITEBACK_DCACHE );
////
////    DPUT_D1_QWC( texture_qwc );
////
////    DPUT_D1_MADR( (u_int)base_addr & ASURA_PS2_DMA_MEM_MASK );
////
////    DPUT_D1_CHCR( 0 | ( 1 << 8 ) );
////
////    asm __volatile__( " sync.l " );
////
////    // check if DMA is complete (STR=0)
////    while( *D1_CHCR & 0x0100 ) { }
//////    printf( " Transferred:(%d) QW from GS -> MEM complete\n", texture_qwc );
////
////    // change VIF1-FIFO transfer direction (MAIN MEM or SPR -> VIF1)
////    *VIF1_STAT = 0;
////
////    // change GS bus direction (HOST->LOCAL)
////    DPUT_GS_BUSDIR( ( u_long ) 0 );
////
////    // restore previous IMR status
////    sceGsPutIMR( prev_imr );
////
////    // set the FINISH event
////    DPUT_GS_CSR( GS_CSR_FINISH_M );
//////    printf( " Restore VIF1 and GS direction complete\n" );
////
////    // MSKPATH3 is now enabled to allow transfer via PATH3
////    DPUT_VIF1_FIFO( *( u_long128 * ) enable_path3 );
//////    printf( " Restore PATH3 direction complete\n" );
////}
//
//static void ReadDataFromGS(
//    u_long128* puDestBuffer,
//    unsigned uSizeOfDestBuffer,         // In QWs.
//    unsigned uSrcAddr,                  // Word address / 64.
//    unsigned uPixelStorageMode,
//    unsigned uX, unsigned uY,           // In pixels.
//    unsigned uWidth, unsigned uHeight,  // In pixels.
//    unsigned uSrcBufferWidth            // In pixels.
//)
//{
//    // Store the contents of the D1_CHCR register since sceGsExecStoreImage()
//    // changes it.
//    const unsigned uStoredD1CHCR = *D1_CHCR;
//
//    // Divide src buffer width by 64; this is what sceGsExecStoreImage()
//    // expects.
//    uSrcBufferWidth >>= 6;
//
//    // Determine the number of bytes required per pixel.
//    unsigned uBytesPerPixel;
//    switch( uPixelStorageMode )
//    {
//        case SCE_GS_PSMCT32:
//        case SCE_GS_PSMZ32:
//            uBytesPerPixel = 4;
//            break;
//            
//        case SCE_GS_PSMCT24:
//        case SCE_GS_PSMZ24:
//            // (MP - 19.12.2001) Should this be 4?
//            uBytesPerPixel = 3;
//            break;
//
//        case SCE_GS_PSMCT16:
//        case SCE_GS_PSMZ16:
//            uBytesPerPixel = 2;
//            break;
//
//        default:
//            Asura_Assert( false, "Unsupported pixel storage mode." );
//            return;
//    }
//
//    // Calculate the number of QWs we'll be storing per line.
//    Asura_Assert( ((uWidth * uBytesPerPixel) & 15) == 0, "" );
//    const unsigned uQWsPerLine = (uWidth * uBytesPerPixel) >> 4;
//
//    sceGsStoreImage xStoreImageInfo;
//    unsigned uOut = 0;
//    for( unsigned u = 0; u < uHeight; ++u )
//    {
//        // Set the region of VRAM to be transferred.
//        sceGsSetDefStoreImage(
//            &xStoreImageInfo,
//            uSrcAddr,
//            uSrcBufferWidth,
//            uPixelStorageMode,
//            uX, uY + u,
//            uWidth, 1
//        );
//        FlushCache( WRITEBACK_DCACHE );
//
//        // Transfer.
//        Asura_Assert( uOut + uQWsPerLine <= uSizeOfDestBuffer, "Uh-oh - we're about to overrun the buffer." );
//        sceGsExecStoreImage( &xStoreImageInfo, puDestBuffer + uOut );
//        FlushCache( WRITEBACK_DCACHE );
//
//        // Update output counter.
//        uOut += uQWsPerLine;
//    }
//
//    // (MP - 19.12.2001) TEMP - Remove this condition if this function ever
//    // gets used for anything other than testing out the fog code.
//    Asura_Assert( uOut == uSizeOfDestBuffer, "" );
//
//    // Restore the contents of the D1_CHCR register
//    *D1_CHCR = uStoredD1CHCR;
//    asm( "sync.l" );
//}
//
//// Either this is broken or you can't do this.
//static void SendTexflush( void )
//{
//    // We're going to need to send 2 QWs: the GIF tag and the TEXFLUSH itself.
//    Asura_PS2_QW axPacketData[2];
//
//    // Write GIF tag.
//    {
//        Asura_PS2_GifTag* const pxGifTag = reinterpret_cast<Asura_PS2_GifTag*>( &axPacketData[0] );
//        pxGifTag->Set(
//            1,
//            true,
//            false,
//            0,
//            SCE_GIF_PACKED,
//            1,
//            SCE_GIF_PACKED_AD
//        );
//    }
//
//    // Write TEXFLUSH command.
//    axPacketData[1].u64s[0] = 0;
//    axPacketData[1].u64s[1] = SCE_GS_TEXFLUSH;
//
//    // Send to the GS using NORMAL DMA mode.
//    {
//        // Set the number of QWs to be transferred.
//        *D2_QWC = 2;
//
//        // Set the start address.
//        *D2_MADR = reinterpret_cast<unsigned>( &axPacketData[0] );
//
//        // Ask for transfer completion to be reported on coprocessor.
//        *D_PCR = 1 << D_PCR_CPC2_O;
//        *D_STAT = 1 << D_STAT_CIS2_O;
//
//        // Force those values to be written to the registers.
//        asm( "sync.l" );
//
//        // Setup channel control register.
//        *D2_CHCR = (1 << D_CHCR_DIR_O)  // From memory.
//                 | (0 << D_CHCR_MOD_O)  // Normal mode.
//                 | (0 << D_CHCR_ASP_O)  // No address pushed by call tag.
//                 | (0 << D_CHCR_TTE_O)  // Irrelevant in normal mode.
//                 | (0 << D_CHCR_TIE_O)  // Irrelevant in normal mode (?).
//                 | (1 << D_CHCR_STR_O); // Start DMA transfer.
//
//        // Go go go.
//        asm( "sync.l" );
//
//        // Wait for completion.
//        asm __volatile__( " _SendTexflush_WaitForDMA:         " );
//        asm __volatile__( "     bc0f _SendTexflush_WaitForDMA " );
//        asm __volatile__( "     nop                           " );
//    }
//}
//
//extern int Tim2GetLog2( int );
//#include "main.h"
//
//static void WriteGSDataToTimFile(
//    const char* szFilename,
//    const void* pvBuffer,
//    const unsigned uBufferSize,  // In bytes.
//    const unsigned uImgWidth,    // In pixels.
//    const unsigned uImgHeight,   //     "
//    const unsigned uImageFormat
//)
//{
//    Asura_String xTemp = ASURA_PS2_PCFILEROOT;
//    xTemp += szFilename;
//
//    const int iFileHandle = sceOpen( xTemp.GetString(), SCE_WRONLY | SCE_CREAT );
//    if( iFileHandle < 0 )
//    {
//        Asura_Assert( false, "Couldn't open file." );
//        return;
//    }
//
//    // Write file header.
//    {
//        TIM2_FILEHEADER xFileHdr;
//        xFileHdr.FileId[0]     = 'T';
//        xFileHdr.FileId[1]     = 'I';
//        xFileHdr.FileId[2]     = 'M';
//        xFileHdr.FileId[3]     = '2';
//        xFileHdr.FormatVersion = 3;
//        xFileHdr.FormatId      = 0;   // 16-byte alignment mode.
//        xFileHdr.Pictures      = 1;   // Num pictures in file.
//
//	    for( unsigned u = 0; u < 8; ++u )
//	    {
//		    xFileHdr.pad[u] = 0;
//	    }
//
//	    sceWrite( iFileHandle, &xFileHdr, sizeof(TIM2_FILEHEADER) );
//    }
//    
//    // Write picture header.
//    {
//        // Determine the TIM2 image type.
//        TIM2_gattr_type eImgType;
//        switch( uImageFormat )
//        {
//	        case SCE_GS_PSMCT32:
//		        eImgType = TIM2_RGB32;
//		        break;
//
//	        case SCE_GS_PSMCT24:
//		        eImgType = TIM2_RGB24;
//		        break;
//
//	        case SCE_GS_PSMCT16:
//		        eImgType = TIM2_RGB16;
//		        break;
//
//	        case SCE_GS_PSMCT16S:
//		        eImgType = TIM2_RGB16;
//		        break;
//
//	        default:
//		        Asura_Assert( false, "Invalid image format." );
//		        return;
//        }
//
//    	TIM2_PICTUREHEADER xPicHdr;
//        
//        xPicHdr.TotalSize      = sizeof(TIM2_PICTUREHEADER) + uBufferSize; // Total size in bytes.
//        xPicHdr.ClutSize       = 0;                                        // CLUT size in bytes.
//        xPicHdr.ImageSize      = uBufferSize;                              // Image data size in bytes.
//        xPicHdr.HeaderSize     = sizeof(TIM2_PICTUREHEADER);               // Header size in bytes.
//        xPicHdr.ClutColors     = 0;                                        // Number of CLUT colours.
//        xPicHdr.PictFormat     = 0;                                        // Picture format.
//        xPicHdr.MipMapTextures = 1;                                        // Number of MIPMAP textures.
//        xPicHdr.ClutType       = TIM2_NONE;                                // CLUT type.
//        xPicHdr.ImageType      = eImgType;                                 // Image type
//        xPicHdr.ImageWidth     = uImgWidth;                                // Image width
//        xPicHdr.ImageHeight    = uImgHeight;                               // Image height
//
//        {
//            xPicHdr.GsTex0     = 0;
//
//            sceGsTex0* pxTex0  = reinterpret_cast<sceGsTex0*>( &xPicHdr.GsTex0 );
//            pxTex0->TBW        = uImgWidth / 64;
//            pxTex0->PSM        = uImageFormat;
//            pxTex0->TW         = Tim2GetLog2( uImgWidth );
//            pxTex0->TH         = Tim2GetLog2( uImgHeight );
//        }
//
//        xPicHdr.GsTex1         = 0;
//        xPicHdr.GsTexaFbaPabe  = 0;
//        xPicHdr.GsTexClut      = 0;
//
//        sceWrite( iFileHandle, &xPicHdr, sizeof(TIM2_PICTUREHEADER) );
//    }
//
//    // Write image data.
//    sceWrite( iFileHandle, pvBuffer, uBufferSize );
//
//    // Close file.
//    sceClose( iFileHandle );
//}
//
//DEBUGVAR bool dbg_bEnableFog = false;
//DEBUGVAR bool dbg_bExtraSyncsInFogCode = false;
//DEBUGVAR bool dbg_bInspectDrawBufferBeforeFog = false;
//DEBUGVAR bool dbg_bInspectDrawBufferAfterFog = false;
//DEBUGVAR bool dbg_bInspectZBufferBeforeFog = false;
//DEBUGVAR bool dbg_bInspectZBufferAfterFog = false;
//DEBUGVAR bool dbg_bSaveSnapshotOfGSDataToTimFiles = false;
//DEBUGVAR bool dbg_bCopyZBufferToDrawBuffer = false;
//DEBUGVAR bool dbg_bCopyZBufferToDrawBuffer_Red = true;
//DEBUGVAR bool dbg_bCopyZBufferToDrawBuffer_Green = true;
//DEBUGVAR bool dbg_bCopyZBufferToDrawBuffer_Blue = true;
//DEBUGVAR bool dbg_bCopyZBufferToDrawBuffer_Alpha = true;
//static void DrawFog( void )
//{
//    #define DO_TONS_OF_SYNCS \
//    { \
//        sceGsSyncPath( 0, 0 ); \
//        FlushCache( WRITEBACK_DCACHE ); \
//    }
//
//    Asura_PS2_QW* axZBufferData_Before    = NULL;
//    Asura_PS2_QW* axZBufferData_After     = NULL;
//    Asura_PS2_QW* axDrawBufferData_Before = NULL;
//    Asura_PS2_QW* axDrawBufferData_After  = NULL;
//
//    DO_TONS_OF_SYNCS
//
//    if( dbg_bInspectDrawBufferBeforeFog )
//    {
//        Asura_Assert( (ASURA_PS2_FRAMEBFR_NUM_WORDS & 3) == 0, "" );
//        const unsigned uNumDrawBufferQWs = ASURA_PS2_FRAMEBFR_NUM_WORDS >> 2;
//        axDrawBufferData_Before = new Asura_PS2_QW[uNumDrawBufferQWs];
//        // (MP - 18.12.2001) Only for use on devkits so this'll succeed.
//
//        // Transfer draw buffer data from GS.
//        {
//            const unsigned uDrawBufferFmt =
//#if ASURA_PS2_FRAMEBFR_BIT_DEPTH == 32
//                SCE_GS_PSMCT32;
//#elif ASURA_PS2_FRAMEBFR_BIT_DEPTH == 24
//                SCE_GS_PSMCT24;
//#elif ASURA_PS2_FRAMEBFR_BIT_DEPTH == 16
//                SCE_GS_PSMCT16;
//#else
//                #error Invalid draw buffer bit depth.
//#endif
//
//            const unsigned uDrawBfrBaseAddr = ( Asura_PS2_GS::CurrentFrameBuffer ? ASURA_PS2_FRAMEBFR_0_BASE_PTR : ASURA_PS2_FRAMEBFR_1_BASE_PTR );
//            ReadDataFromGS(
//                &axDrawBufferData_Before[0].u128,
//                uNumDrawBufferQWs,
//                uDrawBfrBaseAddr * 32,
//                uDrawBufferFmt,
//                0,
//                0,
//                Asura_PS2_GS::GetScreenWidth(),
//                Asura_PS2_GS::GetScreenHeight(),
//                Asura_PS2_GS::GetScreenWidth()
//            );
//        }
//    }
//    // End if( dbg_bInspectDrawBufferBeforeFog ).
//
//    if( dbg_bInspectZBufferBeforeFog )
//    {
//        Asura_Assert( (ASURA_PS2_ZBFR_NUM_WORDS & 3) == 0, "" );
//        const unsigned uNumZBufferQWs = ASURA_PS2_ZBFR_NUM_WORDS >> 2; // This is unnecessarily large for 24-bit Z.
//        axZBufferData_Before = new Asura_PS2_QW[uNumZBufferQWs];
//        // (MP - 18.12.2001) Only for use on devkits so this'll succeed.
//
//        // Transfer Z buffer data from GS.
//        {
//            const unsigned uZBufferFmt =
//#if ASURA_PS2_ZBFR_BIT_DEPTH == 32
//                SCE_GS_PSMZ32;
//#elif ASURA_PS2_ZBFR_BIT_DEPTH == 24
//                SCE_GS_PSMZ24;
//#elif ASURA_PS2_ZBFR_BIT_DEPTH == 16
//                SCE_GS_PSMZ16;
//#else
//                #error Invalid Z buffer bit depth.
//#endif
//
//            ReadDataFromGS(
//                &axZBufferData_Before[0].u128,
//                uNumZBufferQWs,
//                ASURA_PS2_ZBFR_BASE_PTR * 32,
//                uZBufferFmt,
//                0,
//                0,
//                Asura_PS2_GS::GetScreenWidth(),
//                Asura_PS2_GS::GetScreenHeight(),
//                Asura_PS2_GS::GetScreenWidth()
//            );
//        }
//
//    }
//    // End if( dbg_bInspectZBufferBeforeFog ).
//
//    DO_TONS_OF_SYNCS
//
//    if( dbg_bEnableFog )
//    {
//#if USE_SAMPLE_CODE_FOR_FOGGING
//        if( dbg_bExtraSyncsInFogCode ) { sceGsSyncPath( 0, 0 ); }
//        const unsigned uDrawBfrBaseAddr = ( Asura_PS2_GS::CurrentFrameBuffer ? ASURA_PS2_FRAMEBFR_0_BASE_PTR : ASURA_PS2_FRAMEBFR_1_BASE_PTR );
//        FromSample_SetSpriteRGBA( 0x80, 0x80, 0x80, 0x80 );
//        FromSample_MoveRG2BA( ASURA_PS2_ZBFR_BASE_PTR * 32, uDrawBfrBaseAddr );  
//        FromSample_SetSpriteRGBA( 0x20, 0x20, 0x20, dbg_uFogSpriteAlpha );					
//        FromSample_FogSprite();
//        if( dbg_bExtraSyncsInFogCode ) { sceGsSyncPath( 0, 0 ); }
//#else
//        if( dbg_bExtraSyncsInFogCode ) { sceGsSyncPath( 0, 0 ); }
//        MoveRGToBA();
//
////        // Manual alpha setting.
////        {
////            Asura_Assert( dbg_bInspectDrawBufferBeforeFog && dbg_bInspectZBufferBeforeFog, "" );
////
////#if ASURA_PS2_ZBFR_BIT_DEPTH != 32
////#error !!!
////#endif
////#if ASURA_PS2_FRAMEBFR_BIT_DEPTH != 32
////#error !!!
////#endif
////
////            const unsigned uDrawBfrBaseAddr = ( Asura_PS2_GS::CurrentFrameBuffer ? ASURA_PS2_FRAMEBFR_0_BASE_PTR : ASURA_PS2_FRAMEBFR_1_BASE_PTR );
////
////            const unsigned uScrWidth = Asura_PS2_GS::GetScreenWidth();
////            const unsigned uScrHeight = Asura_PS2_GS::GetScreenHeight();
////
////            const unsigned uNumPixels = uScrWidth * uScrHeight;
////            unsigned* auTest = new unsigned[uNumPixels];
////
////            const unsigned* auOldDrawBfr = reinterpret_cast<const unsigned*>( axDrawBufferData_Before );
////            const unsigned* auZBuffer = reinterpret_cast<const unsigned*>( axZBufferData_Before );
////
////            for( unsigned u = 0; u < uNumPixels; ++u )
////            {
////                // Copy RGB from old draw buffer.
////                // NB: This is unnecessary - could just setup write mask
////                // instead and only change alpha.
////                auTest[u] = auOldDrawBfr[u] & 0x00ffffff;
////
////                // Adjust alpha.
////                const unsigned char uZGreen = (auZBuffer[u] & 0x0000ff00) >> 8;
////                auTest[u] |= uZGreen << 24;
////            }
////
////            FlushCache( WRITEBACK_DCACHE );
////
////            sceGsLoadImage xLoadImgInfo;
////
////            // Copy to draw buffer line by line.
////            const unsigned uNumWordsPerLine = uScrWidth;
////            for( unsigned u = 0; u < uScrHeight; ++u )
////            {
////                sceGsSetDefLoadImage(
////                    &xLoadImgInfo,
////                    uDrawBfrBaseAddr * 32,
////                    uScrWidth / 64,
////                    SCE_GS_PSMCT32,
////                    0,
////                    u,
////                    uScrWidth,
////                    1
////                );
////                FlushCache( WRITEBACK_DCACHE );
////
////                sceGsExecLoadImage( &xLoadImgInfo, reinterpret_cast<u_long128*>(auTest + u * uNumWordsPerLine) );
////            }
////            sceGsSyncPath( 0, 0 );
////
////            delete[] auTest;
////        }
////        // End manual alpha setting.
//
//        if( dbg_bExtraSyncsInFogCode ) { sceGsSyncPath( 0, 0 ); }
//        DrawFogSprite();
//        if( dbg_bExtraSyncsInFogCode ) { sceGsSyncPath( 0, 0 ); }
//#endif
//    }
//    // End if( dbg_bEnableFog ).
//
////    SendTexflush();
//    DO_TONS_OF_SYNCS
//
//    if( dbg_bInspectDrawBufferAfterFog )
//    {
//        Asura_Assert( (ASURA_PS2_FRAMEBFR_NUM_WORDS & 3) == 0, "" );
//        const unsigned uNumDrawBufferQWs = ASURA_PS2_FRAMEBFR_NUM_WORDS >> 2;
//        axDrawBufferData_After = new Asura_PS2_QW[uNumDrawBufferQWs];
//        // (MP - 18.12.2001) Only for use on devkits so this'll succeed.
//
//        // Transfer draw buffer data from GS.
//        {
//            const unsigned uDrawBufferFmt =
//#if ASURA_PS2_FRAMEBFR_BIT_DEPTH == 32
//                SCE_GS_PSMCT32;
//#elif ASURA_PS2_FRAMEBFR_BIT_DEPTH == 24
//                SCE_GS_PSMCT24;
//#elif ASURA_PS2_FRAMEBFR_BIT_DEPTH == 16
//                SCE_GS_PSMCT16;
//#else
//                #error Invalid draw buffer bit depth.
//#endif
//
//            const unsigned uDrawBfrBaseAddr = ( Asura_PS2_GS::CurrentFrameBuffer ? ASURA_PS2_FRAMEBFR_0_BASE_PTR : ASURA_PS2_FRAMEBFR_1_BASE_PTR );
//            ReadDataFromGS(
//                &axDrawBufferData_After[0].u128,
//                uNumDrawBufferQWs,
//                uDrawBfrBaseAddr * 32,
//                uDrawBufferFmt,
//                0,
//                0,
//                Asura_PS2_GS::GetScreenWidth(),
//                Asura_PS2_GS::GetScreenHeight(),
//                Asura_PS2_GS::GetScreenWidth()
//            );
//        }
//    }
//    // End if( dbg_bInspectDrawBufferAfterFog ).
//
//    if( dbg_bInspectZBufferAfterFog )
//    {
//        Asura_Assert( (ASURA_PS2_ZBFR_NUM_WORDS & 3) == 0, "" );
//        const unsigned uNumZBufferQWs = ASURA_PS2_ZBFR_NUM_WORDS >> 2; // This is unnecessarily large for 24-bit Z.
//        axZBufferData_After = new Asura_PS2_QW[uNumZBufferQWs];
//        // (MP - 18.12.2001) Only for use on devkits so this'll succeed.
//
//        // Transfer Z buffer data from GS.
//        {
//            const unsigned uZBufferFmt =
//#if ASURA_PS2_ZBFR_BIT_DEPTH == 32
//                SCE_GS_PSMZ32;
//#elif ASURA_PS2_ZBFR_BIT_DEPTH == 24
//                SCE_GS_PSMZ24;
//#elif ASURA_PS2_ZBFR_BIT_DEPTH == 16
//                SCE_GS_PSMZ16;
//#else
//                #error Invalid Z buffer bit depth.
//#endif
//
//            ReadDataFromGS(
//                &axZBufferData_After[0].u128,
//                uNumZBufferQWs,
//                ASURA_PS2_ZBFR_BASE_PTR * 32,
//                uZBufferFmt,
//                0,
//                0,
//                Asura_PS2_GS::GetScreenWidth(),
//                Asura_PS2_GS::GetScreenHeight(),
//                Asura_PS2_GS::GetScreenWidth()
//            );
//        }
//
//    }
//    // End if( dbg_bInspectZBufferAfterFog ).
//
//    DO_TONS_OF_SYNCS
//
//    // Some code to allow easy inspection of the draw buffer and Z buffer
//    // contents from before and after application of the fog code.
//    {
//        struct RGB32 { unsigned char r, g, b; };
//
//        // If we're using 24-bit formats, convert the buffers to arrays
//        // of 12-bit items.
//#if ASURA_PS2_FRAMEBFR_BIT_DEPTH == 24
//        RGB32* converted_draw_buffer_before_data = reinterpret_cast<RGB32*>( axDrawBufferData_Before );
//        RGB32* converted_draw_buffer_after_data = reinterpret_cast<RGB32*>( axDrawBufferData_After );
//#endif
//#if ASURA_PS2_ZBFR_BIT_DEPTH == 24
//        RGB32* converted_z_buffer_before_data = reinterpret_cast<RGB32*>( axZBufferData_Before );
//        RGB32* converted_z_buffer_after_data = reinterpret_cast<RGB32*>( axZBufferData_After );
//#endif
//
//        int breakpoint_me_baby = 1; ++breakpoint_me_baby;
//
//        if( dbg_bSaveSnapshotOfGSDataToTimFiles )
//        {
//            if( dbg_bInspectDrawBufferBeforeFog )
//            {
//                WriteGSDataToTimFile(
//                    "draw_buffer_before.tm2",
//                    axDrawBufferData_Before,
//                    ASURA_PS2_FRAMEBFR_NUM_WORDS * 4,
//                    Asura_PS2_GS::GetScreenWidth(),
//                    Asura_PS2_GS::GetScreenHeight(),
//                    SCE_GS_PSMCT32
//                );
//            }
//
//            if( dbg_bInspectDrawBufferAfterFog )
//            {
//                WriteGSDataToTimFile(
//                    "draw_buffer_after.tm2",
//                    axDrawBufferData_After,
//                    ASURA_PS2_FRAMEBFR_NUM_WORDS * 4,
//                    Asura_PS2_GS::GetScreenWidth(),
//                    Asura_PS2_GS::GetScreenHeight(),
//                    SCE_GS_PSMCT32
//                );
//            }
//
//            if( dbg_bInspectZBufferBeforeFog )
//            {
//                const unsigned uNumPixels = Asura_PS2_GS::GetScreenWidth() * Asura_PS2_GS::GetScreenHeight();
//
//#if ASURA_PS2_ZBFR_BIT_DEPTH == 32
//                WriteGSDataToTimFile(
//                    "z_buffer_before.tm2",
//                    axZBufferData_Before,
//                    uNumPixels * 4,
//                    Asura_PS2_GS::GetScreenWidth(),
//                    Asura_PS2_GS::GetScreenHeight(),
//                    SCE_GS_PSMCT32
//                );
//#elif ASURA_PS2_ZBFR_BIT_DEPTH == 24
//                WriteGSDataToTimFile(
//                    "z_buffer_before.tm2",
//                    axZBufferData_Before,
//                    uNumPixels * 3,
//                    Asura_PS2_GS::GetScreenWidth(),
//                    Asura_PS2_GS::GetScreenHeight(),
//                    SCE_GS_PSMCT24
//                );
//#else
//#error need code for other z buffer bit depths!
//#endif
//            }
//
//            if( dbg_bInspectZBufferAfterFog )
//            {
//                const unsigned uNumPixels = Asura_PS2_GS::GetScreenWidth() * Asura_PS2_GS::GetScreenHeight();
//#if ASURA_PS2_ZBFR_BIT_DEPTH == 32
//                WriteGSDataToTimFile(
//                    "z_buffer_after.tm2",
//                    axZBufferData_After,
//                    uNumPixels * 4,
//                    Asura_PS2_GS::GetScreenWidth(),
//                    Asura_PS2_GS::GetScreenHeight(),
//                    SCE_GS_PSMCT32
//                );
//#elif ASURA_PS2_ZBFR_BIT_DEPTH == 24
//                WriteGSDataToTimFile(
//                    "z_buffer_after.tm2",
//                    axZBufferData_After,
//                    uNumPixels * 3,
//                    Asura_PS2_GS::GetScreenWidth(),
//                    Asura_PS2_GS::GetScreenHeight(),
//                    SCE_GS_PSMCT24
//                );
//#else
//#error need code for other z buffer bit depths!
//#endif
//            }
//
//            dbg_bSaveSnapshotOfGSDataToTimFiles = false;
//        }
//        // End if( dbg_bSaveSnapshotOfGSDataToTimFiles ).
//    }
//
//    if( dbg_bCopyZBufferToDrawBuffer )
//    {
//        Asura_Assert( dbg_bInspectZBufferBeforeFog, "Need to get Z buffer contents too!" );
//
//        const unsigned uDrawBfrBaseAddr = ( Asura_PS2_GS::CurrentFrameBuffer ? ASURA_PS2_FRAMEBFR_0_BASE_PTR : ASURA_PS2_FRAMEBFR_1_BASE_PTR );
//        const unsigned uDrawBufferFmt =
//#if ASURA_PS2_FRAMEBFR_BIT_DEPTH == 32
//            SCE_GS_PSMCT32;
//#else
//            #error Invalid or unsupported draw buffer bit depth.
//#endif
//
//        unsigned* auToSend = new unsigned[ASURA_PS2_FRAMEBFR_NUM_WORDS];
//
//        const unsigned uScrWidth = Asura_PS2_GS::GetScreenWidth();
//        const unsigned uScrHeight = Asura_PS2_GS::GetScreenHeight();
//
//#if ASURA_PS2_ZBFR_BIT_DEPTH == 32
//        {
//            const unsigned char* auInput = reinterpret_cast<const unsigned char*>( axZBufferData_Before );
//            unsigned char* auOutput = reinterpret_cast<unsigned char*>( auToSend );
//
//            unsigned uIn = 0;
//            unsigned uOut = 0;
//
//            unsigned uNumPixels = uScrWidth * uScrHeight;
//            while( uNumPixels-- )
//            {
////                const unsigned uZValue = (auInput[uIn + 0] << 0) + (auInput[uIn + 1] << 8) + (auInput[uIn + 2] << 16);
////                const unsigned uColour = (uZValue * 128) / (1 << 24);
//
//                auOutput[uOut + 0] = ( dbg_bCopyZBufferToDrawBuffer_Red   ? auInput[uIn + 0] : 0 );
//                auOutput[uOut + 1] = ( dbg_bCopyZBufferToDrawBuffer_Green ? auInput[uIn + 1] : 0 );
//                auOutput[uOut + 2] = ( dbg_bCopyZBufferToDrawBuffer_Blue  ? auInput[uIn + 2] : 0 );
//                auOutput[uOut + 3] = ( dbg_bCopyZBufferToDrawBuffer_Alpha ? auInput[uIn + 3] : 0 );
//
//                uIn  += 4;
//                uOut += 4;
//            }
//
//            Asura_Assert( uOut == ASURA_PS2_FRAMEBFR_NUM_WORDS * 4, "" );
//        }
//#elif ASURA_PS2_ZBFR_BIT_DEPTH == 24
//        {
//            const unsigned char* auInput = reinterpret_cast<const unsigned char*>( axZBufferData_Before );
//            unsigned char* auOutput = reinterpret_cast<unsigned char*>( auToSend );
//
//            unsigned uIn = 0;
//            unsigned uOut = 0;
//
//            unsigned uNumPixels = uScrWidth * uScrHeight;
//            while( uNumPixels-- )
//            {
//                const unsigned uZValue = (auInput[uIn + 0] << 0) + (auInput[uIn + 1] << 8) + (auInput[uIn + 2] << 16);
//                const unsigned uColour = (uZValue * 128) / (1 << 24);
//
//                // R, G, B.
//                auOutput[uOut + 0] = uColour; //( dbg_bCopyZBufferToDrawBuffer_Red   ? auInput[uIn + 0] : 0 );
//                auOutput[uOut + 1] = uColour; //( dbg_bCopyZBufferToDrawBuffer_Green ? auInput[uIn + 1] : 0 );
//                auOutput[uOut + 2] = uColour; //( dbg_bCopyZBufferToDrawBuffer_Blue  ? auInput[uIn + 2] : 0 );
//
//                // A.
//                auOutput[uOut + 3] = 0; //128;
//
//                uIn  += 3;
//                uOut += 4;
//            }
//
//            Asura_Assert( uOut == ASURA_PS2_FRAMEBFR_NUM_WORDS * 4, "" );
//        }
//#else
//        #error Invalid or unsupported Z buffer bit depth.
//#endif
//        FlushCache( WRITEBACK_DCACHE );
//            
//        sceGsLoadImage xLoadImgInfo;
//
//        // Copy to draw buffer line by line.
//        const unsigned uHeight = Asura_PS2_GS::GetScreenHeight();
//        const unsigned uNumWordsPerLine = 
//#if ASURA_PS2_FRAMEBFR_BIT_DEPTH == 32
//            uScrWidth;
//#else
//            #error Invalid or unsupported draw buffer bit depth.
//#endif
//        for( unsigned u = 0; u < uHeight; ++u )
//        {
//            sceGsSetDefLoadImage(
//                &xLoadImgInfo,
//                uDrawBfrBaseAddr * 32,
//                uScrWidth / 64,
//                uDrawBufferFmt,
//                0,
//                u,
//                uScrWidth,
//                1
//            );
//            FlushCache( WRITEBACK_DCACHE );
//
//            sceGsExecLoadImage( &xLoadImgInfo, reinterpret_cast<u_long128*>(auToSend + u * uNumWordsPerLine) );
//            sceGsSyncPath( 0, 0 );
//        }
//
//        delete[] auToSend;
//    }
//    // End if( dbg_bCopyZBufferToDrawBuffer ).
//
//    // Clean up buffers as necessary.
//    if( axZBufferData_Before    ) { delete[] axZBufferData_Before;    }
//    if( axZBufferData_After     ) { delete[] axZBufferData_After;     }
//    if( axDrawBufferData_Before ) { delete[] axDrawBufferData_Before; }
//    if( axDrawBufferData_After  ) { delete[] axDrawBufferData_After;  }
//
//    #undef DO_TONS_OF_SYNCS
//}
#endif
