/*---------------------------------------------------------------------------*
  Project:  THP Simple Player
  File:     THPDraw.c

  Copyright (C)2002-2006 Nintendo  All Rights Reserved.

  These coded instructions, statements, and computer programs contain
  proprietary information of Nintendo of America Inc. and/or Nintendo
  Company Ltd., and are protected by Federal copyright law.  They may
  not be disclosed to third parties or copied or duplicated in any form,
  in whole or in part, without the prior written consent of Nintendo.

  $Log: THPDraw.c,v $
  Revision 1.1  02/03/2006 10:01:13  aka
  Imported from Dolphin tree.

    
    2     03/11/25 11:24 Dante
    Japanese to English translation of comments and text strings
    
    1     02/01/16 10:54a Akagi
    Initial revision made by Suzuki-san (IRD).
    
  $NoKeywords: $  

 *---------------------------------------------------------------------------*/

#include <demo.h>
#include "THPDraw.h"

/*---------------------------------------------------------------------------*
    Name:           THPGXRestore

    Description:    Restore used swap table data to original state

    Arguments:      None

    Returns:        None
 *---------------------------------------------------------------------------*/
 
void THPGXRestore( void )
{
    GXSetZMode(GX_ENABLE, GX_ALWAYS, GX_DISABLE);
    GXSetBlendMode(GX_BM_NONE, GX_BL_ONE, GX_BL_ZERO, GX_LO_SET);
    
    GXSetNumTexGens(1);
    GXSetNumChans(0);
    GXSetNumTevStages(1);
    GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
    GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE);        

    // Swap mode settings
    GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0);
    GXSetTevSwapMode(GX_TEVSTAGE1, GX_TEV_SWAP0, GX_TEV_SWAP0);
    GXSetTevSwapMode(GX_TEVSTAGE2, GX_TEV_SWAP0, GX_TEV_SWAP0);
    GXSetTevSwapMode(GX_TEVSTAGE3, GX_TEV_SWAP0, GX_TEV_SWAP0);

    GXSetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED,   GX_CH_GREEN,
                                        GX_CH_BLUE,  GX_CH_ALPHA); // RGBA
    GXSetTevSwapModeTable(GX_TEV_SWAP1, GX_CH_RED,   GX_CH_RED,
                                        GX_CH_RED,   GX_CH_ALPHA); // RRRA
    GXSetTevSwapModeTable(GX_TEV_SWAP2, GX_CH_GREEN, GX_CH_GREEN,
                                        GX_CH_GREEN, GX_CH_ALPHA); // GGGA
    GXSetTevSwapModeTable(GX_TEV_SWAP3, GX_CH_BLUE,  GX_CH_BLUE,
                                        GX_CH_BLUE,  GX_CH_ALPHA); // BBBA

}



/*---------------------------------------------------------------------------*
    Name:           THPGXYuv2RgbSetup

    Description:    Required setup routine for movie rendering

    Arguments:      rmode:	Pointer for currently set GXRenderModeObj

    Returns:        None
 *---------------------------------------------------------------------------*/

void THPGXYuv2RgbSetup( const GXRenderModeObj *rmode )
{
    s32         scrWidth;
    s32         scrHeight;
    Mtx44       pMtx;
    Mtx         mMtx;
    
    scrWidth  = rmode->fbWidth;
    scrHeight = rmode->efbHeight;

    GXSetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR);

    // Geometry
    MTXOrtho(pMtx, 0.0f, (f32)scrHeight, 0.0f, (f32)scrWidth, 0.0f, -1.0F);
    GXSetProjection(pMtx, GX_ORTHOGRAPHIC);
    GXSetViewport(0.0F, 0.0F, (f32)scrWidth, (f32)scrHeight, 0.0F, 1.0F);
    GXSetScissor(0, 0, (u32)scrWidth, (u32)scrHeight);

    MTXIdentity(mMtx);
    GXLoadPosMtxImm(mMtx, GX_PNMTX0);
    GXSetCurrentMtx(GX_PNMTX0);
    
    // Framebuffer
    GXSetZMode(GX_ENABLE, GX_ALWAYS, GX_DISABLE);
    GXSetBlendMode(GX_BM_NONE, GX_BL_ONE, GX_BL_ZERO, GX_LO_CLEAR);
    GXSetColorUpdate(GX_TRUE);
    GXSetAlphaUpdate(GX_FALSE);
    GXSetDispCopyGamma(GX_GM_1_0);

    // Color channels
    GXSetNumChans(0);
    
    // Texture coord generation
    GXSetNumTexGens(2);
    GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
    GXSetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);

    // Texture cache
    GXInvalidateTexAll();

    // Vertex formats
    GXClearVtxDesc();
    GXSetVtxDesc(GX_VA_POS,  GX_DIRECT);
    GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
    GXSetVtxAttrFmt(GX_VTXFMT7, GX_VA_POS,  GX_POS_XYZ, GX_S16, 0);
    GXSetVtxAttrFmt(GX_VTXFMT7, GX_VA_TEX0, GX_TEX_ST,  GX_U16, 0);

    // *******************************************************
    //    TEV settings to perform YUV->RGB conversion
    // *******************************************************
    GXSetNumTevStages(4);
    
    // Stage 0 (Cb texture)
    //    R = -90, B = -114+226Cb, A = 135-88Cb
    GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD1, GX_TEXMAP1, GX_COLOR_NULL);
    GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC,
                    GX_CC_KONST, GX_CC_C0);
    GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO,
                    GX_CS_SCALE_1, GX_FALSE, GX_TEVPREV);
    GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_TEXA,
                    GX_CA_KONST, GX_CA_A0);
    GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_SUB, GX_TB_ZERO,
                    GX_CS_SCALE_1, GX_FALSE, GX_TEVPREV);
    GXSetTevKColorSel(GX_TEVSTAGE0, GX_TEV_KCSEL_K0);
    GXSetTevKAlphaSel(GX_TEVSTAGE0, GX_TEV_KASEL_K0_A);
    GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0);
    
    // Stage 1 (Cr texture)
    //    R = 2*(R+179Cr), B = 2*B, A = A-182Cr
    GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1, GX_TEXMAP2, GX_COLOR_NULL);
    GXSetTevColorIn(GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_TEXC,
                    GX_CC_KONST, GX_CC_CPREV);
    GXSetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO,
                    GX_CS_SCALE_2, GX_FALSE, GX_TEVPREV);
    GXSetTevAlphaIn(GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_TEXA,
                    GX_CA_KONST, GX_CA_APREV);
    GXSetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_SUB, GX_TB_ZERO,
                    GX_CS_SCALE_1, GX_FALSE, GX_TEVPREV);
    GXSetTevKColorSel(GX_TEVSTAGE1, GX_TEV_KCSEL_K1);
    GXSetTevKAlphaSel(GX_TEVSTAGE1, GX_TEV_KASEL_K1_A);
    GXSetTevSwapMode(GX_TEVSTAGE1, GX_TEV_SWAP0, GX_TEV_SWAP0);
    
    // Stage 2 (Y texture)
    //    R += 255Y, B += 255Y, A += 255Y [do clamp]
    GXSetTevOrder(GX_TEVSTAGE2, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL);
    GXSetTevColorIn(GX_TEVSTAGE2, GX_CC_ZERO, GX_CC_TEXC,
                    GX_CC_ONE, GX_CC_CPREV);
    GXSetTevColorOp(GX_TEVSTAGE2, GX_TEV_ADD, GX_TB_ZERO,
                    GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
    GXSetTevAlphaIn(GX_TEVSTAGE2, GX_CA_TEXA, GX_CA_ZERO,
                    GX_CA_ZERO, GX_CA_APREV);
    GXSetTevAlphaOp(GX_TEVSTAGE2, GX_TEV_ADD, GX_TB_ZERO,
                    GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
    GXSetTevSwapMode(GX_TEVSTAGE2, GX_TEV_SWAP0, GX_TEV_SWAP0);

    // Stage 3
    //    Merge Alpha into the Green channel
    GXSetTevOrder(GX_TEVSTAGE3, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);
    GXSetTevColorIn(GX_TEVSTAGE3, GX_CC_APREV, GX_CC_CPREV,
                    GX_CC_KONST, GX_CC_ZERO);
    GXSetTevColorOp(GX_TEVSTAGE3, GX_TEV_ADD, GX_TB_ZERO,
                    GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
    GXSetTevAlphaIn(GX_TEVSTAGE3, GX_CA_ZERO, GX_CA_ZERO,
                    GX_CA_ZERO, GX_CA_ZERO);
    GXSetTevAlphaOp(GX_TEVSTAGE3, GX_TEV_ADD, GX_TB_ZERO,
                    GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
    GXSetTevSwapMode(GX_TEVSTAGE3, GX_TEV_SWAP0, GX_TEV_SWAP0);
    GXSetTevKColorSel(GX_TEVSTAGE3, GX_TEV_KCSEL_K2);
    
    // Constant colors
    GXSetTevColorS10(GX_TEVREG0, (GXColorS10){ -90, 0, -114, 135 });
    GXSetTevKColor(GX_KCOLOR0, (GXColor){   0,   0, 226,  88 });
    GXSetTevKColor(GX_KCOLOR1, (GXColor){ 179,   0,   0, 182 });
    GXSetTevKColor(GX_KCOLOR2, (GXColor){ 255,   0, 255, 128 });

    // Swap mode tables
    GXSetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED,   GX_CH_GREEN,
                                        GX_CH_BLUE,  GX_CH_ALPHA); // RGBA
}


/*---------------------------------------------------------------------------*
    Name:           THPGXYuv2RgbDraw

    Description:    Draw movie texture with polygon attached

    Arguments:      y_data         Pointer for y texture
                    u_data         Pointer for u texture
                    v_data         Pointer for v texture
                    x              Upper left x coordinate of TV screen for 
                                    display of polygon.
                    y              Upper left y coordinate of TV screen for 
                                    display of polygon.
                    textureWidth   Width of texture
                    textureHeight  Height of texture
                    polygonWidth   Width of polygon
                    polygonHeight  Height of polygon

    Returns:        None
 *---------------------------------------------------------------------------*/

void 
THPGXYuv2RgbDraw
( 
    u8* y_data, 
    u8* u_data, 
    u8* v_data, 
    s16 x, 
    s16 y, 
    s16 textureWidth, 
    s16 textureHeight,
    s16 polygonWidth,
    s16 polygonHeight
    
 )
{
    GXTexObj    tobj0, tobj1, tobj2;

    // Y Texture
    GXInitTexObj(&tobj0, y_data, (u16)textureWidth, (u16)textureHeight, 
                 GX_TF_I8, GX_CLAMP, GX_CLAMP, GX_FALSE);
    GXInitTexObjLOD(&tobj0, GX_NEAR, GX_NEAR, 0, 0, 0, 0, 0, GX_ANISO_1);
    GXLoadTexObj(&tobj0, GX_TEXMAP0);

    // Cb Texture
    GXInitTexObj(&tobj1, u_data, (u16)(textureWidth>>1), (u16)(textureHeight>>1),
                 GX_TF_I8, GX_CLAMP, GX_CLAMP, GX_FALSE);
    GXInitTexObjLOD(&tobj1, GX_NEAR, GX_NEAR, 0, 0, 0, 0, 0, GX_ANISO_1);
    GXLoadTexObj(&tobj1, GX_TEXMAP1);

    // Cr Texture
    GXInitTexObj(&tobj2, v_data, (u16)(textureWidth>>1), (u16)(textureHeight>>1),
                 GX_TF_I8, GX_CLAMP, GX_CLAMP, GX_FALSE);
    GXInitTexObjLOD(&tobj2, GX_NEAR, GX_NEAR, 0, 0, 0, 0, 0, GX_ANISO_1);
    GXLoadTexObj(&tobj2, GX_TEXMAP2);

    // Draw a quad
    GXBegin(GX_QUADS, GX_VTXFMT7, 4);
        GXPosition3s16(x, y, 0);
        GXTexCoord2u16(0, 0);
        GXPosition3s16((s16)(x+polygonWidth), y, 0);
        GXTexCoord2u16(1, 0);
        GXPosition3s16((s16)(x+polygonWidth), (s16)(y+polygonHeight), 0);
        GXTexCoord2u16(1, 1);
        GXPosition3s16(x, (s16)(y+polygonHeight), 0);
        GXTexCoord2u16(0, 1);
    GXEnd();
}
