/*
 * Skin plug-in
 */

/****************************************************************************
 *                                                                          *
 *  Module  :   skinEnvPipe.c                                               *
 *                                                                          *
 *  Purpose :   Skin Environment mapping pipeline for PS2                   *
 *                                                                          *
 ****************************************************************************/


/****************************************************************************
 Includes
 */
#include <rpdbgerr.h>
#include <archive/rpmatfx310.h>
/* #include <rpskin.h> */
#include <archive/rpskin310.h>

#include "../../driver/sky2/baasm.h"

#include "rpplugin.h"
#include "effectPipes.h"
#include "effectPipesSky.h"

#include "SKY2_SkinGlosEnvMap/stddata.h"
#include "SKY2_SkinGlosEnvMap/skinEnvPipe.h"

#if (!defined(DOXYGEN))
static const char rcsid[] __RWUNUSED__ = 
    "@@@@(#)$Id: skinEnvPipe.c,v 1.12 2001/09/26 10:48:12 johns Exp $";
#endif /* (!defined(DOXYGEN)) */

/*----------------------------------------------------------------------*/
/*-                                Definition                          -*/
/*----------------------------------------------------------------------*/

#define RWALIGN_skySkinEnvMapTransforms \
        RWALIGN(skySkinEnvMapTransforms, rpMATFXALIGNMENT)

matFXVUcode 
RWALIGN_skySkinEnvMapTransforms =
{
    &SkinGlosEnvMapPRS, &vu1nullTrans,
    &SkinGlosEnvMapPRL, &vu1nullTrans,
    &vu1nullTrans, &vu1nullTrans, &vu1nullTrans, &vu1nullTrans,
    &vu1nullTrans, &vu1nullTrans, &vu1nullTrans, &vu1nullTrans,
    &vu1nullTrans, &vu1nullTrans, &vu1nullTrans, &vu1nullTrans,
    &vu1nullTrans, &vu1nullTrans, &vu1nullTrans, &vu1nullTrans,
    &vu1nullTrans, &vu1nullTrans, &vu1nullTrans, &vu1nullTrans,
    &vu1nullTrans, &vu1nullTrans, &vu1nullTrans, &vu1nullTrans,
    &vu1nullTrans, &vu1nullTrans, &vu1nullTrans, &vu1nullTrans
};

/*----------------------------------------------------------------------*/
/*-                                Functions                           -*/
/*----------------------------------------------------------------------*/
RwBool
_rpMatFXSkinEnvMapInstanceCallBack( void **clusterData,
                                    RwUInt32 __RWUNUSED__ numClusters )
{
    /* --------------- Pipe --------------------------------------*/
    RxPS2Mesh                      *mesh = (RxPS2Mesh *)clusterData[0];
    RxPS2DMASessionRecord *dmaSessionRec = (RxPS2DMASessionRecord *)clusterData[1];
    rpMatFXMaterialData *materialData    =
        (rpMatFXMaterialData *)*MATFXMATERIALGETDATA(mesh->mesh->material);
    /* --------------- Skin --------------------------------------*/
    RpAtomic  *atomic     = dmaSessionRec->sourceObject.atomic;
    RpSkin    *skin       = *MatFXSkinAtomicGetData(atomic);
    RwUInt32  numMatrices = MatFXSkinGetNumBones(skin);
    RwReal    *destMBI    = (RwReal *)(clusterData[2]);
    RwInt32   DMAstorage  = 0;
    RwMatrix  *pMBA       = (RwMatrix *)NULL;
    /*---------------- Env ---------------------------------------*/
    RwTexture *basetex       = (RwTexture *) NULL;   
    RwTexture *envMapTexture = (RwTexture *) NULL;
    RwReal     envMapCoef    = 0.0f;
    RwBool     blendmode;

    RWFUNCTION(RWSTRING("_rpMatFXSkinEnvMapInstanceCallBack"));

    RWASSERT(NULL != mesh);
    RWASSERT(NULL != dmaSessionRec);
    RWASSERT(NULL != destMBI);
    RWASSERT(NULL != atomic);
    RWASSERT(NULL != skin);
    RWASSERT(NULL != materialData);

    /*------------ Skin weights and indices instancing -----------*/
    if (dmaSessionRec->serialNum != ((RwUInt32 *) (*(mesh->cacheEntryRef) + 1))[3])
    {
        MatFXSkinWeightsInstancing(mesh->mesh, skin, destMBI);
    }

    /*----------------- Bones matrices uploading -----------------*/
    if(0 == mesh->meshNum)
    {
        pMBA           = MatFXSkinMatrixUpdating(atomic, skin);
        RWASSERT(NULL != pMBA);
        DMAstorage     = numMatrices * 4;
    }

    /*----------------- Env mapping ------------------------------*/
    blendmode  = materialData->data[rpSECONDPASS].data.envMap.useFrameBufferAlpha;
    envMapCoef = materialData->data[rpSECONDPASS].data.envMap.coef;
    envMapTexture = materialData->data[rpSECONDPASS].data.envMap.texture;
    RWASSERT(envMapTexture);

    /*----------------- DMA data Upload --------------------------*/
    {
        RwUInt128 ltmp        = 0;    
        RwUInt64  prim        = 0x0l;
        RwUInt64  primSwitch  = 0x4l;
        RwUInt64  fogSwitch   = 0x0l;
        RwUInt64  rastex1     = 0;
        RwUInt64  rastex2     = 0;
        RwUInt32  val1, val2;
        RwUInt64  tmp, tmp1;

        /*--------------- set the prim type -----------------*/
        if (dmaSessionRec->transType & 4)
        {
            primSwitch = 0x3l;
        }
        /*--------------- set the fog -----------------------*/
        if (dmaSessionRec->transType & 1)
        {
            fogSwitch = 0x1l;
        }
  
  		/*--- Need to upload the base texture ---*/
		basetex = mesh->mesh->material->texture;
        if (NULL != basetex)
        {
	        _rpMatFXUploadTexture(basetex, dmaSessionRec, mesh);
	        skyTexGetTex0(basetex->raster, &val1, &val2); 
	        rastex1 = ((RwUInt64) val1 << 32) | val2; 
	    }

        /*--- Now upload the envMap texture -----*/
        if (NULL != envMapTexture)
        {
	        skyTexCacheAccessRaster(envMapTexture->raster, TRUE);
  	        skyTexGetTex0(envMapTexture->raster, &val1, &val2);
    	    rastex2 = ((RwUInt64) val1 << 32) | val2;            

            if ((envMapTexture->raster->depth <= 8) && (basetex)
                && (basetex->raster->depth <= 8))
            {
                skyTextureRaster = (RwRaster*)-1;
            }
        }
        
        /*---------------- DMA packet -----------------------*/
        sweFinaliseOpenLocalPkt((int) (SWE_PKT_DMA_MODE_CHAIN_TTE |
                                       SWE_PKT_LOCAL |
                                       SWE_PKT_VU1 |
                                       SWE_PKT_CIRCALLOC),
                                       /**/ -(18 + DMAstorage) /**/);
        if (!sweLocalPacket)
        {
            RWRETURN(FALSE);
        }
        tmp  = ((1l << 28)      |  (/**/ DMAstorage + 16 /**/));
        tmp1 = ((((0x6cl << 24) | ((/**/ DMAstorage + 11 /**/) << 16) |
               ((long) (pipeASymbSkinStaticEnvDataStart))) << 32)     |
               ((1l << 24) | (4 << 8) | (4)));
        MAKE128(ltmp, tmp1, tmp);
        SWEADDCONTFAST(ltmp);
        /*---------------------------------------------------*/

        /*---------- Dark Fog Tag / Tex0-2 Info -------------*/
        tmp  = /* NLOOP */ 2l
             | /* EOP   */ (1l << 15)
             | /* PRE   */ (0l << 46)
             | /* FLG   */ (0l << 58)
             | /* NREG  */ (1l << 60);
        MAKE128(ltmp, 0xel, tmp);
        SWEADDCONTFAST(ltmp);
        MAKE128(ltmp, GS_FOGCOL, 0x000000l);
        SWEADDCONTFAST(ltmp);
        MAKE128(ltmp, GS_TEX0_2, rastex2);
        SWEADDCONTFAST(ltmp);

        /*-------Real Fog Tag / Tex0-1 Info -----------------*/
        tmp  = /* NLOOP */ 2l
             | /* EOP   */ (1l << 15)
             | /* PRE   */ (0l << 46)
             | /* FLG   */ (0l << 58)
             | /* NREG  */ (1l << 60);
        MAKE128(ltmp, 0xel, tmp);
        SWEADDCONTFAST(ltmp);
        MAKE128(ltmp, GS_FOGCOL, skyFogcol);
        SWEADDCONTFAST(ltmp);
        MAKE128(ltmp, GS_TEX0_1, rastex1);
        SWEADDCONTFAST(ltmp);

        /*----------- Context 2 Env-Map GifTag --------------*/
        prim = ( /* fix  */ 0x0l << 10        |
                 /* ctxt */ 0x1l << 9         |
                 /* fst  */ 0x0l << 8         |
                 /* aa1  */ 0x0l << 7         |
                 /* abe  */ 0x1l << 6         | 
                 /* fge  */ fogSwitch << 5    |
                 /* tme  */ 0x1l << 4         |
                 /* iip  */ 0x1l << 3         |
                 /* prim */ primSwitch << 0);
        tmp = (  /* regs */ 0x3l << (60 - 32) |
                 /* flg  */ 0x0l << (58 - 32) |
                 /* prim */ prim << (47 - 32) |
                 /* pre  */ 0x1l << (46 - 32)) << 32;
        MAKE128(ltmp, 0x412l, tmp);
        SWEADDCONTFAST(ltmp);

        /*------------ Env Map matrix -----------------------*/
        ltmp = *((u_long128 *) & (matFXEnvMatrix.right));
        SWEADDCONTFAST(ltmp);
        ltmp = *((u_long128 *) & (matFXEnvMatrix.up));
        SWEADDCONTFAST(ltmp);
        tmp  = *(const RwUInt64 *) & (matFXEnvMatrix.at.x);
        tmp1 = *(const RwUInt32 *) & (envMapCoef);
        tmp1 = ((tmp1 << 32) | (*(const RwUInt32 *) & (matFXEnvMatrix.at.z)));
        MAKE128(ltmp, tmp1, tmp);
        SWEADDCONTFAST(ltmp);

        /*------------ Environment Map Datas ----------------*/
        tmp  = *(const RwUInt64 *) (matFXEnvParams);
        tmp1 = *(const RwUInt64 *) (matFXEnvParams + 2);
        MAKE128(ltmp, tmp1, tmp);
        SWEADDCONTFAST(ltmp);

        /*-------- Upload Skin matrices ---------------------*/
        if(DMAstorage)
        {
            RwUInt32  i;
            for (i = 0; i < numMatrices; i++)
            {
                ltmp = *((u_long128 *) & pMBA->right.x);
                SWEADDCONTFAST(ltmp);
                ltmp = *((u_long128 *) & pMBA->up.x);
                SWEADDCONTFAST(ltmp);
                ltmp = *((u_long128 *) & pMBA->at.x);
                SWEADDCONTFAST(ltmp);
                ltmp = *((u_long128 *) & pMBA->pos.x);
                SWEADDCONTFAST(ltmp);
                pMBA++;
            }
        }
        /*---------------------------------------------------*/

        /*------------ Padding ------------------------------*/
        tmp  = VIFCMD_NOP   | (VIFCMD_NOP << 32);
        tmp1 = (VIFCMD_NOP) | ((VIFCMD_DIRECT | /**/ 4 /**/) << 32);
        MAKE128(ltmp, tmp1, tmp);
        SWEADDCONTFAST(ltmp);

        /*------------- Second Context Registers ------------*/
        tmp  = /* NLOOP */ 3l
             | /* EOP   */ (1l << 15)
             | /* PRE   */ (0l << 46)
             | /* FLG   */ (0l << 58)
             | /* NREG  */ (1l << 60);
        MAKE128(ltmp, 0xel, tmp);
        SWEADDCONTFAST(ltmp);
        MAKE128(ltmp, GS_ALPHA_2, 0x8000000048l | (0x20 >> blendmode));
        SWEADDCONTFAST(ltmp);
        MAKE128(ltmp, GS_CLAMP_2, 0x0);
        SWEADDCONTFAST(ltmp);
        MAKE128(ltmp, GS_TEST_2,  0x50002l);
        SWEADDCONTFAST(ltmp);

        /*------- Terminate the DMA with an interrupt -------*/
        MAKE128(ltmp, 0l, (0xfl << 28));
        SWEADDCONTFAST(ltmp);
        /*---------------------------------------------------*/

        sweFinaliseOpenLocalPkt(SWE_LPS_CONT, 0);
    }

    RWRETURN(TRUE);
}
