mirror of
https://github.com/thug1src/thug.git
synced 2025-01-22 05:43:47 +00:00
1136 lines
29 KiB
C++
1136 lines
29 KiB
C++
|
#include <string.h>
|
||
|
#include <core/defines.h>
|
||
|
#include <core/debug.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <libgraph.h>
|
||
|
#include "texture.h"
|
||
|
#include "texturemem.h"
|
||
|
#include "dma.h"
|
||
|
#include "vif.h"
|
||
|
#include "gif.h"
|
||
|
#include "gs.h"
|
||
|
#include "group.h"
|
||
|
#include "scene.h"
|
||
|
#include "switches.h"
|
||
|
#include <sys\file\filesys.h>
|
||
|
#include <core\crc.h>
|
||
|
|
||
|
|
||
|
// K: I put this back to 0 for the moment because Conv4to32 is corrupting memory
|
||
|
// by writing past the end of the temporary swizzle buffer, which causes a hang
|
||
|
// when switching themes in the park editor.
|
||
|
// Garrett: Should be fixed now.
|
||
|
#define SWIZZLE_IN_LOAD 1
|
||
|
|
||
|
namespace NxPs2
|
||
|
{
|
||
|
|
||
|
// static array of pointers to sGroup
|
||
|
// (so that we can pre-allocate our sGroups
|
||
|
// to avoid memory fragmentation)
|
||
|
const int vMAX_TEX_GROUPS = 32;
|
||
|
static sGroup* sp_temp_groups[vMAX_TEX_GROUPS];
|
||
|
|
||
|
extern TextureMemoryLayout TexMemLayout;
|
||
|
|
||
|
//------------------------------------------------------------------------------------
|
||
|
// L O A D T E X T U R E S
|
||
|
//------------------------------------------------------------------------------------
|
||
|
//
|
||
|
// Performs 2 tasks - it adds texture register settings to the array Textures for all
|
||
|
// textures in the texture file buffer (increasing NumTextures accordingly), and it
|
||
|
// creates a dma subroutine to upload all the textures in the file buffer to vram.
|
||
|
// Currently it handles all the packing (poorly!), but this will eventually be done by
|
||
|
// a preprocess in the tools pipeline.
|
||
|
|
||
|
bool load_textures(sScene* pScene, uint8* pTexBuffer, bool IsSkin, bool IsInstanceable, bool UsesPip, uint32 texDictOffset)
|
||
|
{
|
||
|
Dbg_MsgAssert( pScene, ( "No scene pointer" ) );
|
||
|
Dbg_MsgAssert( pTexBuffer, ( "No tex buffer pointer" ) );
|
||
|
|
||
|
int total_num_textures=0;
|
||
|
|
||
|
#if 0
|
||
|
// make sure there's no dma list running
|
||
|
sceGsSyncPath(0,0);
|
||
|
#else
|
||
|
// GJ: Calling "sceGsSyncPath()" instead
|
||
|
// of "WaitForRendering()" will cause the boardshop
|
||
|
// to crash when going into the "Change Deck" menu.
|
||
|
// Neither Mick nor Mike seem to know why this
|
||
|
// would be the case, so it's probably worth
|
||
|
// investigating at some point
|
||
|
void WaitForRendering();
|
||
|
WaitForRendering();
|
||
|
#endif
|
||
|
|
||
|
// Dbg_Message("loading textures from file %s\n", Filename);
|
||
|
|
||
|
// initialise members
|
||
|
pScene->NumTextures = 0;
|
||
|
pScene->NumMeshes = 0;
|
||
|
pScene->pMeshes = NULL;
|
||
|
pScene->Flags = 0;
|
||
|
pScene->pInstances = NULL;
|
||
|
|
||
|
// link it in
|
||
|
pScene->pNext = sScene::pHead;
|
||
|
sScene::pHead = pScene;
|
||
|
|
||
|
// set flags
|
||
|
if (UsesPip)
|
||
|
{
|
||
|
pScene->Flags |= SCENEFLAG_USESPIP;
|
||
|
}
|
||
|
|
||
|
// set the tex buffer pointer
|
||
|
pScene->pTexBuffer = pTexBuffer;
|
||
|
|
||
|
// set data pointer
|
||
|
sScene::pData = pScene->pTexBuffer;
|
||
|
|
||
|
// version number
|
||
|
sTexture::sVersion = *(uint32 *)sScene::pData, sScene::pData+=4;
|
||
|
// printf("Texture version %d\n", sTexture::sVersion);
|
||
|
|
||
|
// get number of texture groups
|
||
|
pScene->NumGroups = *(uint32 *)sScene::pData, sScene::pData+=4;
|
||
|
|
||
|
// get total number of textures, version >= 3
|
||
|
if (sTexture::sVersion >= 3)
|
||
|
{
|
||
|
total_num_textures = *(int *)sScene::pData, sScene::pData+=4;
|
||
|
}
|
||
|
|
||
|
|
||
|
// allocate storage for textures
|
||
|
if (sTexture::sVersion >= 3)
|
||
|
{
|
||
|
// if there are no textures, it will assert in Mem::Malloc
|
||
|
// so catch this assert earlier here.....
|
||
|
// really there should be some more elegant handling of scenes with no textures, but they are sufficently rare.
|
||
|
//Dbg_MsgAssert(total_num_textures>0,("Need at least one texture in %s (it has none)\n",Filename));
|
||
|
if( total_num_textures > 0 )
|
||
|
{
|
||
|
pScene->pTextures = (sTexture *)Mem::Malloc(total_num_textures*sizeof(sTexture));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pScene->pTextures = NULL;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pScene->pTextures = (sTexture *)Mem::Malloc(2000*sizeof(sTexture));
|
||
|
}
|
||
|
|
||
|
if ( !((total_num_textures == 0 ) || ( pScene->pTextures )) )
|
||
|
{
|
||
|
Dbg_Message( "couldn't allocate memory for textures" );
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
Dbg_MsgAssert( pScene->NumGroups < vMAX_TEX_GROUPS, ( "Too many tex groups for static array of sGroup pointers (increase vMAX_TEX_GROUPS from %d)", vMAX_TEX_GROUPS ) );
|
||
|
for (int i=0; i<pScene->NumGroups; i++)
|
||
|
{
|
||
|
// pre-allocate space for texture groups...
|
||
|
sp_temp_groups[i] = (sGroup *)Mem::Malloc(sizeof(sGroup));
|
||
|
memset(sp_temp_groups[i],0,sizeof(sGroup));
|
||
|
}
|
||
|
|
||
|
// allocate prebuilt dma buffer for textures
|
||
|
#if 0
|
||
|
int available = Mem::Available()-128; // -128 is needed otherwise it fails trying to allocate all free mem in a region
|
||
|
if (available > 500000)
|
||
|
{
|
||
|
available = 500000; // clamp to 500k if we have loads of memory. No sure why, maybe just to speed up loading when in debug mode
|
||
|
}
|
||
|
#else
|
||
|
// We don't want to allocate all memory as it messes with memory debugging
|
||
|
// so
|
||
|
// only seem to need T*256 + G*48
|
||
|
// hmm, somethings seems to be T*512 for some reason....
|
||
|
// but upped it a bit to be safe
|
||
|
// These only get used for peds and stuff now
|
||
|
int available = total_num_textures * 512 + pScene->NumGroups * 128 + 512; // bumped up multipliers, and added 512 byte extra
|
||
|
#endif
|
||
|
|
||
|
|
||
|
pScene->pTexDma = (uint8 *)Mem::Malloc(available); // Allocate all available memeory on current context
|
||
|
|
||
|
// set dma pointer to new buffer
|
||
|
dma::pLoc = pScene->pTexDma;
|
||
|
|
||
|
// test
|
||
|
sGroup::VramBufferBase = 0x2BC0;
|
||
|
|
||
|
// iterate over groups
|
||
|
for (int i=0; i<pScene->NumGroups; i++)
|
||
|
{
|
||
|
LoadTextureGroup(NULL, pScene, sp_temp_groups[i], IsSkin, IsInstanceable, UsesPip, texDictOffset);
|
||
|
sp_temp_groups[i] = NULL;
|
||
|
}
|
||
|
|
||
|
//Dbg_Message( "Dma usage = %d Textures = %d, Groups = %d", (int)(dma::pLoc-pScene->pTexDma), total_num_textures, pScene->NumGroups );
|
||
|
|
||
|
if ( (int)(dma::pLoc-pScene->pTexDma) >= available )
|
||
|
{
|
||
|
Dbg_Message( "Texture dictionary used more memory (%d) than available (%d)", (int)(dma::pLoc-pScene->pTexDma), available );
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// resize dma buffer so it just fits
|
||
|
pScene->pTexDma = (uint8 *)Mem::ReallocateShrink(dma::pLoc-pScene->pTexDma, pScene->pTexDma);
|
||
|
|
||
|
// success!
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// load textures from a file
|
||
|
sScene *LoadTextures(const char *Filename, bool IsSkin, bool IsInstanceable, bool UsesPip, uint32 texDictOffset, uint32 *p_size)
|
||
|
{
|
||
|
// Dbg_Message( "LoadTextures: file = %s", Filename );
|
||
|
|
||
|
sScene* pScene = (sScene*)Mem::Malloc(sizeof(sScene));
|
||
|
Dbg_MsgAssert(pScene, ("couldn't allocate scene"));
|
||
|
|
||
|
uint8* pTexBuffer = (uint8*)File::LoadAlloc( Filename, (int*) p_size );
|
||
|
|
||
|
bool success = load_textures(pScene, pTexBuffer, IsSkin, IsInstanceable, UsesPip, texDictOffset);
|
||
|
if ( !success )
|
||
|
{
|
||
|
Dbg_MsgAssert( 0, ( "Load textures from file %s failed", Filename ) );
|
||
|
}
|
||
|
|
||
|
return pScene;
|
||
|
}
|
||
|
|
||
|
// load textures from a data buffer, rather than opening a file
|
||
|
sScene *LoadTextures(uint32* pData, int dataSize, bool IsSkin, bool IsInstanceable, bool UsesPip, uint32 texDictOffset)
|
||
|
{
|
||
|
// Dbg_Message( "LoadTextures: data = %p size = %d", pData, dataSize );
|
||
|
|
||
|
sScene* pScene = (sScene*)Mem::Malloc(sizeof(sScene));
|
||
|
Dbg_MsgAssert(pScene, ("couldn't allocate scene"));
|
||
|
|
||
|
uint8* pTexBuffer = (uint8*)Mem::Malloc(dataSize);
|
||
|
Dbg_MsgAssert(pTexBuffer, ("couldn't allocate tex buffer"));
|
||
|
|
||
|
// copy over the data
|
||
|
memcpy( pTexBuffer, pData, dataSize );
|
||
|
|
||
|
bool success = load_textures(pScene, pTexBuffer, IsSkin, IsInstanceable, UsesPip, texDictOffset);
|
||
|
if ( !success )
|
||
|
{
|
||
|
Dbg_MsgAssert( 0, ( "Load textures from data buffer failed" ) );
|
||
|
}
|
||
|
|
||
|
return pScene;
|
||
|
}
|
||
|
|
||
|
void LoadTextureGroup(void *pFile, sScene *pScene, sGroup *pGroup, bool IsSkin, bool IsInstanceable, bool UsesPip, uint32 texDictOffset)
|
||
|
{
|
||
|
sTexture *pTex, *pOriginalTexture=NULL;
|
||
|
uint32 TW, TH, PSM, CPSM;
|
||
|
uint TBP[7], TBW[7], CBP;
|
||
|
uint Width[7], Height[7], NumTexBytes[7], NumTexQWords[7], NumClutBytes, NumClutQWords, NumVramBytes[7];
|
||
|
uint BitsPerTexel, BitsPerClutEntry, PaletteSize, AdjustedWidth[7], AdjustedHeight[7];
|
||
|
uint PageWidth, PageHeight, AdjustedBitsPerTexel, TexCount=0;
|
||
|
int i,j,k,NumTexturesThisGroup,MXL;
|
||
|
uint NextTBP, LastCBP;
|
||
|
uint8 *pTextureSource;
|
||
|
static int Shit=0;
|
||
|
|
||
|
Dbg_MsgAssert( pScene, ( "No pScene" ) );
|
||
|
Dbg_MsgAssert( pGroup, ( "No pre-allocated pGroup was specified" ) );
|
||
|
|
||
|
// set the scene it belongs to
|
||
|
pGroup->pScene = pScene;
|
||
|
|
||
|
pGroup->profile_color = 0x00c000; // green = static group (world, cars)
|
||
|
if (IsInstanceable)
|
||
|
{
|
||
|
pGroup->profile_color = 0x808000; // cyan = instancable static group (cars, gameobjs)
|
||
|
}
|
||
|
if (IsSkin)
|
||
|
{
|
||
|
pGroup->profile_color = 0x000080; // red = skin group
|
||
|
if (IsInstanceable)
|
||
|
{
|
||
|
pGroup->profile_color = 0x800080; // magenta = instancable skinned group
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// zero the mesh pointer in case no meshes get loaded
|
||
|
pGroup->pMeshes = NULL;
|
||
|
pGroup->NumMeshes = 0;
|
||
|
|
||
|
// prepare to build dma info for this group
|
||
|
dma::Align(0,16);
|
||
|
pGroup->pUpload[0] = pGroup->pUpload[1] = dma::pLoc;
|
||
|
|
||
|
// get group checksum
|
||
|
pGroup->Checksum = *(uint32 *)sScene::pData;
|
||
|
pGroup->Checksum += texDictOffset;
|
||
|
sScene::pData+=4;
|
||
|
|
||
|
// get group flags if present
|
||
|
if (sTexture::sVersion >= 2)
|
||
|
{
|
||
|
pGroup->flags = *(uint32 *)sScene::pData, sScene::pData+=4;
|
||
|
}
|
||
|
else if (pGroup->Checksum>=1000 & pGroup->Checksum<2000)
|
||
|
{
|
||
|
pGroup->flags = GROUPFLAG_SKY;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pGroup->flags = 0;
|
||
|
}
|
||
|
|
||
|
// get group priority if present
|
||
|
if (sTexture::sVersion >= 4)
|
||
|
{
|
||
|
pGroup->Priority = *(float *)sScene::pData, sScene::pData+=4;
|
||
|
}
|
||
|
|
||
|
else
|
||
|
{
|
||
|
// set its priority manually
|
||
|
if (UsesPip)
|
||
|
{
|
||
|
switch (pGroup->flags & (GROUPFLAG_SKY|GROUPFLAG_TRANSPARENT))
|
||
|
{
|
||
|
case 0:
|
||
|
pGroup->Priority = 0;
|
||
|
break;
|
||
|
case GROUPFLAG_SKY:
|
||
|
pGroup->Priority = -100;
|
||
|
break;
|
||
|
case GROUPFLAG_TRANSPARENT:
|
||
|
pGroup->Priority = 7500;
|
||
|
break;
|
||
|
case GROUPFLAG_TRANSPARENT|GROUPFLAG_SKY:
|
||
|
pGroup->Priority = -99;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (IsSkin)
|
||
|
{
|
||
|
pGroup->Priority = 5000+Shit;
|
||
|
}
|
||
|
if (IsInstanceable)
|
||
|
{
|
||
|
pGroup->Priority = 2500+Shit;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// if it has the lowest priority, make a new head
|
||
|
if (sGroup::pHead==NULL || pGroup->Priority < sGroup::pHead->Priority)
|
||
|
{
|
||
|
pGroup->pNext = sGroup::pHead;
|
||
|
pGroup->pPrev = NULL;
|
||
|
sGroup::pHead = pGroup;
|
||
|
|
||
|
if (pGroup->pNext)
|
||
|
pGroup->pNext->pPrev = pGroup;
|
||
|
else
|
||
|
sGroup::pTail = pGroup;
|
||
|
}
|
||
|
|
||
|
// othwerwise if it has the highest priority, make a new tail
|
||
|
else if (pGroup->Priority >= sGroup::pTail->Priority)
|
||
|
{
|
||
|
pGroup->pPrev = sGroup::pTail;
|
||
|
pGroup->pNext = NULL;
|
||
|
sGroup::pTail->pNext = pGroup;
|
||
|
sGroup::pTail = pGroup;
|
||
|
}
|
||
|
|
||
|
// otherwise find its immediate superior, priority-wise, in the group list
|
||
|
else
|
||
|
{
|
||
|
sGroup *pSup;
|
||
|
for (pSup=sGroup::pHead; pSup; pSup=pSup->pNext)
|
||
|
{
|
||
|
if (pGroup->Priority < pSup->Priority)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
Dbg_MsgAssert(pSup, ("error inserting into group list\n"));
|
||
|
|
||
|
pGroup->pNext = pSup;
|
||
|
pGroup->pPrev = pSup->pPrev;
|
||
|
pSup->pPrev->pNext = pGroup;
|
||
|
pSup->pPrev = pGroup;
|
||
|
}
|
||
|
|
||
|
// get number of textures
|
||
|
NumTexturesThisGroup = *(uint32 *)sScene::pData, sScene::pData+=4;
|
||
|
|
||
|
// set vram usage for this group
|
||
|
pGroup->VramStart = sGroup::VramBufferBase;
|
||
|
pGroup->VramEnd = sGroup::VramBufferBase+0x0A20;
|
||
|
|
||
|
// advance buffer for next group
|
||
|
sGroup::VramBufferBase ^= 0x1E20;
|
||
|
|
||
|
// initialise base pointers
|
||
|
NextTBP = pGroup->VramStart;
|
||
|
LastCBP = pGroup->VramEnd;
|
||
|
|
||
|
// loop over textures
|
||
|
for (i=0,pTex=pScene->pTextures+pScene->NumTextures; i<NumTexturesThisGroup; i++,pTex++)
|
||
|
{
|
||
|
// get texture flags
|
||
|
if (sTexture::sVersion >= 5)
|
||
|
{
|
||
|
pTex->Flags = *(uint32 *)sScene::pData, sScene::pData+=4;
|
||
|
}
|
||
|
|
||
|
// get texture checksum
|
||
|
pTex->Checksum = *(uint32 *)sScene::pData, sScene::pData+=4;
|
||
|
|
||
|
// set group checksum
|
||
|
pTex->GroupChecksum = pGroup->Checksum;
|
||
|
|
||
|
// get dimensions
|
||
|
TW = *(uint32 *)sScene::pData, sScene::pData+=4;
|
||
|
TH = *(uint32 *)sScene::pData, sScene::pData+=4;
|
||
|
|
||
|
// get pixel storage modes
|
||
|
PSM = *(uint32 *)sScene::pData, sScene::pData+=4; // for texels
|
||
|
CPSM = *(uint32 *)sScene::pData, sScene::pData+=4; // for clut
|
||
|
|
||
|
// get maximum mipmap level
|
||
|
MXL = *(uint32 *)sScene::pData, sScene::pData+=4;
|
||
|
|
||
|
// clear buffer pointers
|
||
|
pTex->mp_texture_buffer = NULL;
|
||
|
pTex->mp_clut_buffer = NULL;
|
||
|
pTex->m_texture_buffer_size = 0;
|
||
|
pTex->m_clut_buffer_size = 0;
|
||
|
|
||
|
// bail if it's a non-texture
|
||
|
if (TW == 0xFFFFFFFF)
|
||
|
{
|
||
|
printf("non-texture at number %d\n", i);
|
||
|
// there won't be any more data for this texture
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// detect duplicated texture, signalled by MXL of -1
|
||
|
if (MXL<0)
|
||
|
{
|
||
|
// find the original texture
|
||
|
pOriginalTexture = ResolveTextureChecksum(pTex->Checksum);
|
||
|
|
||
|
// adjust MXL
|
||
|
MXL &= 0x7FFFFFFF;
|
||
|
|
||
|
// signal duplicate
|
||
|
pTex->Flags &= ~TEXFLAG_ORIGINAL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// not a duplicate, must be the original
|
||
|
pTex->Flags |= TEXFLAG_ORIGINAL;
|
||
|
}
|
||
|
|
||
|
// quadword-align (original only)
|
||
|
if (pTex->Flags & TEXFLAG_ORIGINAL)
|
||
|
{
|
||
|
sScene::pData = (uint8 *)(((uint)(sScene::pData+15)) & 0xFFFFFFF0);
|
||
|
}
|
||
|
|
||
|
// bits per texel and palette size
|
||
|
switch (PSM)
|
||
|
{
|
||
|
case PSMCT32:
|
||
|
BitsPerTexel = 32;
|
||
|
PaletteSize = 0;
|
||
|
break;
|
||
|
case PSMCT24:
|
||
|
BitsPerTexel = 24;
|
||
|
PaletteSize = 0;
|
||
|
break;
|
||
|
case PSMCT16:
|
||
|
BitsPerTexel = 16;
|
||
|
PaletteSize = 0;
|
||
|
break;
|
||
|
case PSMT8:
|
||
|
BitsPerTexel = 8;
|
||
|
PaletteSize = 256;
|
||
|
break;
|
||
|
case PSMT4:
|
||
|
BitsPerTexel = 4;
|
||
|
PaletteSize = 16;
|
||
|
break;
|
||
|
default:
|
||
|
printf("Unknown PSM %d at index %d in texture file\n", PSM, i);
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
// adjust bits per texel for 24-bit
|
||
|
AdjustedBitsPerTexel = BitsPerTexel;
|
||
|
if (BitsPerTexel == 24)
|
||
|
{
|
||
|
AdjustedBitsPerTexel = 32;
|
||
|
}
|
||
|
|
||
|
// bits per clut entry
|
||
|
if (BitsPerTexel < 16)
|
||
|
switch (CPSM)
|
||
|
{
|
||
|
case PSMCT32:
|
||
|
BitsPerClutEntry = 32;
|
||
|
break;
|
||
|
case PSMCT16:
|
||
|
BitsPerClutEntry = 16;
|
||
|
break;
|
||
|
default:
|
||
|
printf("Unknown CPSM %d in texture file\n", PSM);
|
||
|
exit(1);
|
||
|
}
|
||
|
else
|
||
|
BitsPerClutEntry = 0;
|
||
|
|
||
|
// rearrange original 256-colour cluts according to requirements of CSM1
|
||
|
if (PSM==PSMT8 && (pTex->Flags & TEXFLAG_ORIGINAL))
|
||
|
{
|
||
|
uint32 temp32;
|
||
|
uint16 temp16;
|
||
|
for (j=0; j<256; j+=32)
|
||
|
for (k=0; k<8; k++)
|
||
|
if (CPSM==PSMCT32)
|
||
|
{
|
||
|
temp32 = ((uint32 *)sScene::pData)[j+k+8];
|
||
|
((uint32 *)sScene::pData)[j+k+8] = ((uint32 *)sScene::pData)[j+k+16];
|
||
|
((uint32 *)sScene::pData)[j+k+16] = temp32;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
temp16 = ((uint16 *)sScene::pData)[j+k+8];
|
||
|
((uint16 *)sScene::pData)[j+k+8] = ((uint16 *)sScene::pData)[j+k+16];
|
||
|
((uint16 *)sScene::pData)[j+k+16] = temp16;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// calculate texture dimensions
|
||
|
for (j=0; j<=MXL; j++)
|
||
|
{
|
||
|
Width[j] = (TW>=0 ? 1<<TW : 0) >> j;
|
||
|
Height[j] = (TH>=0 ? 1<<TH : 0) >> j;
|
||
|
TBW[j] = (Width[j]+63) >> 6;
|
||
|
if (BitsPerTexel<16 && TBW[j]<2)
|
||
|
TBW[j] = 2;
|
||
|
}
|
||
|
|
||
|
// get page size
|
||
|
switch (PSM)
|
||
|
{
|
||
|
case PSMCT32:
|
||
|
case PSMCT24:
|
||
|
PageWidth = 64;
|
||
|
PageHeight = 32;
|
||
|
break;
|
||
|
case PSMCT16:
|
||
|
PageWidth = 64;
|
||
|
PageHeight = 64;
|
||
|
break;
|
||
|
case PSMT8:
|
||
|
PageWidth = 128;
|
||
|
PageHeight = 64;
|
||
|
break;
|
||
|
case PSMT4:
|
||
|
PageWidth = 128;
|
||
|
PageHeight = 128;
|
||
|
break;
|
||
|
default:
|
||
|
printf("Unknown PSM %d at index %d in texture file\n", PSM, i);
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
// calculate adjusted dimensions based on vram page size
|
||
|
for (j=0; j<=MXL; j++)
|
||
|
{
|
||
|
AdjustedWidth[j] = Width[j];
|
||
|
AdjustedHeight[j] = Height[j];
|
||
|
|
||
|
if (AdjustedWidth[j] < PageWidth && AdjustedHeight[j] > PageHeight)
|
||
|
{
|
||
|
AdjustedWidth[j] = PageWidth;
|
||
|
}
|
||
|
|
||
|
if (AdjustedWidth[j] > PageWidth && AdjustedHeight[j] < PageHeight)
|
||
|
{
|
||
|
AdjustedHeight[j] = PageHeight;
|
||
|
}
|
||
|
|
||
|
if (TBW[j]<<6 > AdjustedWidth[j])
|
||
|
{
|
||
|
AdjustedWidth[j] = TBW[j]<<6;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// calculate sizes within file
|
||
|
NumClutBytes = PaletteSize * BitsPerClutEntry >> 3;
|
||
|
NumClutQWords = NumClutBytes >> 4;
|
||
|
for (j=0; j<=MXL; j++)
|
||
|
{
|
||
|
NumTexBytes[j] = Width[j] * Height[j] * BitsPerTexel >> 3;
|
||
|
NumVramBytes[j] = AdjustedWidth[j] * AdjustedHeight[j] * AdjustedBitsPerTexel >> 3;
|
||
|
NumTexQWords[j] = (NumTexBytes[j]+15) >> 4;
|
||
|
}
|
||
|
|
||
|
// calculate TBP
|
||
|
TBP[0] = NextTBP;
|
||
|
for (j=1; j<=MXL; j++)
|
||
|
TBP[j] = (((TBP[j-1]<<8)+NumVramBytes[j-1]+0x1FFF) & 0xFFFFE000) >> 8;
|
||
|
|
||
|
// calculate CBP
|
||
|
if (BitsPerTexel >= 16)
|
||
|
CBP = LastCBP;
|
||
|
else if (BitsPerTexel == 4)
|
||
|
CBP = LastCBP - 1;
|
||
|
else
|
||
|
CBP = LastCBP - (CPSM==PSMCT32 ? 4 : 2);
|
||
|
|
||
|
// calculate next TBP
|
||
|
NextTBP = (((TBP[MXL]<<8)+NumVramBytes[MXL]+0x1FFF) & 0xFFFFE000) >> 8;
|
||
|
|
||
|
// bail if VRAM would become over-packed
|
||
|
if (NextTBP > CBP)
|
||
|
{
|
||
|
printf("no room for texture %d\n", i);
|
||
|
if (pTex->Flags & TEXFLAG_ORIGINAL)
|
||
|
{
|
||
|
sScene::pData += NumClutBytes;
|
||
|
for (j=0; j<=MXL; j++)
|
||
|
{
|
||
|
sScene::pData = (uint8 *)(((uint)(sScene::pData+NumTexBytes[j]+15)) & 0xFFFFFFF0);
|
||
|
}
|
||
|
}
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// add clut upload to dma list if necessary
|
||
|
if (BitsPerTexel < 16)
|
||
|
{
|
||
|
// source
|
||
|
if (pTex->Flags & TEXFLAG_ORIGINAL)
|
||
|
{
|
||
|
pTextureSource = sScene::pData;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pTextureSource = pOriginalTexture->mp_clut_buffer;
|
||
|
}
|
||
|
|
||
|
// save buffer pointer
|
||
|
pTex->mp_clut_buffer = pTextureSource;
|
||
|
pTex->m_clut_buffer_size = NumClutBytes;
|
||
|
|
||
|
// add dma
|
||
|
dma::BeginTag(dma::cnt,0);
|
||
|
vif::NOP();
|
||
|
vif::NOP();
|
||
|
gif::Tag2(gs::A_D,1,PACKED,0,0,0,4);
|
||
|
gs::Reg2(gs::BITBLTBUF,PackBITBLTBUF(0,0,0,CBP,1,CPSM));
|
||
|
gs::Reg2(gs::TRXPOS, PackTRXPOS(0,0,0,0,0));
|
||
|
if (PSM==PSMT4)
|
||
|
gs::Reg2(gs::TRXREG,PackTRXREG(8,2));
|
||
|
else
|
||
|
gs::Reg2(gs::TRXREG,PackTRXREG(16,16));
|
||
|
gs::Reg2(gs::TRXDIR, 0);
|
||
|
gif::Tag2(0,0,IMAGE,0,0,0,NumClutQWords);
|
||
|
dma::EndTag();
|
||
|
dma::Tag(dma::ref, NumClutQWords, (uint)pTextureSource);
|
||
|
vif::NOP();
|
||
|
vif::NOP();
|
||
|
}
|
||
|
|
||
|
if (pTex->Flags & TEXFLAG_ORIGINAL)
|
||
|
{
|
||
|
// step past clut data, and quadword-align
|
||
|
sScene::pData = (uint8 *)(((uint)(sScene::pData+NumClutBytes+15)) & 0xFFFFFFF0);
|
||
|
|
||
|
// save buffer pointer
|
||
|
pTex->mp_texture_buffer = sScene::pData;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pTex->mp_texture_buffer = pOriginalTexture->mp_texture_buffer;
|
||
|
}
|
||
|
pTextureSource = pTex->mp_texture_buffer;
|
||
|
|
||
|
|
||
|
// offset to improve caching
|
||
|
for (j=0; j<=MXL; j++)
|
||
|
{
|
||
|
if (TexCount & 1)
|
||
|
{
|
||
|
if ((BitsPerTexel==32 || BitsPerTexel==8)
|
||
|
&& (Width[j] <= (PageWidth>>1))
|
||
|
&& (Height[j] <= PageHeight)
|
||
|
||
|
||
|
(BitsPerTexel==16 || BitsPerTexel==4)
|
||
|
&& (Width[j] <= PageWidth)
|
||
|
&& (Height[j] <= (PageHeight>>1)))
|
||
|
{
|
||
|
TBP[j] += 16;
|
||
|
//printf("better caching!\n");
|
||
|
}
|
||
|
}
|
||
|
TexCount++;
|
||
|
}
|
||
|
|
||
|
#if SWIZZLE_IN_LOAD
|
||
|
bool swizzleTex = BitsPerTexel <= 8;
|
||
|
#endif // SWIZZLE_IN_LOAD
|
||
|
|
||
|
// loop over mipmaps
|
||
|
for (j=0; j<=MXL; j++)
|
||
|
{
|
||
|
#if SWIZZLE_IN_LOAD
|
||
|
int swizzle_tbw = TBW[j];
|
||
|
int swizzle_width = Width[j];
|
||
|
int swizzle_height = Height[j];
|
||
|
uint32 swizzlePSM = PSM;
|
||
|
bool swizzleMip = false;
|
||
|
|
||
|
if (swizzleTex)
|
||
|
{
|
||
|
switch (PSM)
|
||
|
{
|
||
|
case PSMT8:
|
||
|
{
|
||
|
if (TexMemLayout.CanConv8to32(Width[j], Height[j]))
|
||
|
{
|
||
|
if (pTex->Flags & TEXFLAG_ORIGINAL)
|
||
|
{
|
||
|
Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());
|
||
|
uint8 *pTextureSwizzle = (uint8 *) Mem::Malloc(Width[j] * Height[j]);
|
||
|
Mem::Manager::sHandle().PopContext();
|
||
|
|
||
|
TexMemLayout.Conv8to32(Width[j], Height[j], pTextureSource, pTextureSwizzle);
|
||
|
memcpy(pTextureSource, pTextureSwizzle, Width[j] * Height[j]);
|
||
|
|
||
|
Mem::Free(pTextureSwizzle);
|
||
|
}
|
||
|
|
||
|
// Change size to 32-bit version
|
||
|
swizzle_width /= 2;
|
||
|
swizzle_height /= 2;
|
||
|
|
||
|
// Recalculate Buffer Width since 8-bit version can be artificially high
|
||
|
swizzle_tbw = swizzle_width / 64;
|
||
|
if (swizzle_tbw == 0)
|
||
|
swizzle_tbw = 1;
|
||
|
|
||
|
swizzleMip = true;
|
||
|
swizzlePSM=PSMCT32; // swizzle
|
||
|
pTex->Flags |= TEXFLAG_MIP_SWIZZLE_32BIT(j);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
case PSMT4:
|
||
|
{
|
||
|
if (TexMemLayout.CanConv4to32(Width[j], Height[j]))
|
||
|
{
|
||
|
//Dbg_Message("Swizzling texture checksum %x", pTex->Checksum);
|
||
|
|
||
|
if (pTex->Flags & TEXFLAG_ORIGINAL)
|
||
|
{
|
||
|
Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());
|
||
|
uint8 *pTextureSwizzle = (uint8 *) Mem::Malloc(Width[j] * Height[j] / 2);
|
||
|
Mem::Manager::sHandle().PopContext();
|
||
|
|
||
|
TexMemLayout.Conv4to32(Width[j], Height[j], pTextureSource, pTextureSwizzle);
|
||
|
memcpy(pTextureSource, pTextureSwizzle, Width[j] * Height[j] / 2);
|
||
|
|
||
|
Mem::Free(pTextureSwizzle);
|
||
|
}
|
||
|
|
||
|
// Change size to 32-bit version
|
||
|
swizzle_width /= 2;
|
||
|
swizzle_height /= 4;
|
||
|
|
||
|
// Recalculate Buffer Width since 4-bit version can be artificially high
|
||
|
swizzle_tbw = swizzle_width / 64;
|
||
|
if (swizzle_tbw == 0)
|
||
|
swizzle_tbw = 1;
|
||
|
|
||
|
swizzleMip = true;
|
||
|
swizzlePSM=PSMCT32; // swizzle
|
||
|
pTex->Flags |= TEXFLAG_MIP_SWIZZLE_32BIT(j);
|
||
|
}
|
||
|
else if (TexMemLayout.CanConv4to16(Width[j], Height[j]))
|
||
|
{
|
||
|
if (pTex->Flags & TEXFLAG_ORIGINAL)
|
||
|
{
|
||
|
Mem::Manager::sHandle().PushContext(Mem::Manager::sHandle().TopDownHeap());
|
||
|
uint8 *pTextureSwizzle = (uint8 *) Mem::Malloc(Width[j] * Height[j] / 2);
|
||
|
Mem::Manager::sHandle().PopContext();
|
||
|
|
||
|
TexMemLayout.Conv4to16(Width[j], Height[j], pTextureSource, pTextureSwizzle);
|
||
|
memcpy(pTextureSource, pTextureSwizzle, Width[j] * Height[j] / 2);
|
||
|
|
||
|
Mem::Free(pTextureSwizzle);
|
||
|
}
|
||
|
|
||
|
// Change size to 16-bit version
|
||
|
swizzle_width /= 2;
|
||
|
swizzle_height /= 2;
|
||
|
|
||
|
// Recalculate Buffer Width since 4-bit version can be artificially high
|
||
|
swizzle_tbw = swizzle_width / 64;
|
||
|
if (swizzle_tbw == 0)
|
||
|
swizzle_tbw = 1;
|
||
|
|
||
|
swizzleMip = true;
|
||
|
swizzlePSM=PSMCT16; // swizzle
|
||
|
pTex->Flags |= TEXFLAG_MIP_SWIZZLE_16BIT(j);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
#endif // SWIZZLE_IN_LOAD
|
||
|
|
||
|
|
||
|
// add texture upload to dma list for this mipmap level
|
||
|
dma::BeginTag(dma::cnt,0);
|
||
|
vif::NOP();
|
||
|
vif::NOP();
|
||
|
gif::Tag2(gs::A_D,1,PACKED,0,0,0,4);
|
||
|
#if SWIZZLE_IN_LOAD
|
||
|
gs::Reg2(gs::BITBLTBUF,PackBITBLTBUF(0,0,0,TBP[j],swizzle_tbw,swizzlePSM));
|
||
|
gs::Reg2(gs::TRXPOS, PackTRXPOS(0,0,0,0,0));
|
||
|
gs::Reg2(gs::TRXREG, PackTRXREG(swizzle_width,swizzle_height));
|
||
|
#else
|
||
|
gs::Reg2(gs::BITBLTBUF,PackBITBLTBUF(0,0,0,TBP[j],TBW[j],PSM));
|
||
|
gs::Reg2(gs::TRXPOS, PackTRXPOS(0,0,0,0,0));
|
||
|
gs::Reg2(gs::TRXREG, PackTRXREG(Width[j],Height[j]));
|
||
|
#endif // SWIZZLE_IN_LOAD
|
||
|
gs::Reg2(gs::TRXDIR, 0);
|
||
|
|
||
|
if (j==0)
|
||
|
{
|
||
|
pTex->mp_dma = dma::pLoc;
|
||
|
pTex->m_quad_words = NumTexQWords[j];
|
||
|
pTex->m_render_count = 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
gif::Tag2(0, 0, IMAGE, 0, 0, 0, NumTexQWords[j]); // 0..3 words, NumTexQWords is in the lower 15 bits of the first word [0]
|
||
|
dma::EndTag(); // Just Aligns upo to QW boundry
|
||
|
dma::Tag(dma::ref, NumTexQWords[j], (uint)pTextureSource); // 0..1 (after alignment) NumTexQWords goes in word 1
|
||
|
vif::NOP();
|
||
|
vif::NOP();
|
||
|
|
||
|
// step past tex data for this level
|
||
|
pTextureSource += NumTexBytes[j];
|
||
|
}
|
||
|
|
||
|
pTex->m_texture_buffer_size = (uint32) pTextureSource - (uint32) pTex->mp_texture_buffer;
|
||
|
|
||
|
if (pTex->Flags & TEXFLAG_ORIGINAL)
|
||
|
{
|
||
|
sScene::pData = pTextureSource;
|
||
|
}
|
||
|
|
||
|
// make entry in texture table
|
||
|
pTex->MXL = MXL;
|
||
|
pTex->RegTEX0 = PackTEX0(TBP[0],TBW[0],PSM,TW,TH,(PSM!=PSMCT24),MODULATE,CBP,CPSM,0,0,1);
|
||
|
pTex->RegMIPTBP1 = PackMIPTBP1(TBP[1],TBW[1],TBP[2],TBW[2],TBP[3],TBW[3]);
|
||
|
pTex->RegMIPTBP2 = PackMIPTBP2(TBP[4],TBW[4],TBP[5],TBW[5],TBP[6],TBW[6]);
|
||
|
|
||
|
// advance texture base pointer to 1st page after texture
|
||
|
// and reduce clut base pointer to 1st page before clut (if there was one)
|
||
|
TBP[0] = NextTBP;
|
||
|
LastCBP = CBP;
|
||
|
|
||
|
}
|
||
|
|
||
|
// add to total for the scene
|
||
|
pScene->NumTextures += NumTexturesThisGroup;
|
||
|
|
||
|
// texflush so we can use textures
|
||
|
dma::BeginTag(dma::end, 0);
|
||
|
vif::NOP();
|
||
|
vif::NOP();
|
||
|
gif::Tag2(gs::A_D,1,PACKED,0,0,1,1);
|
||
|
gs::Reg2(gs::TEXFLUSH, 0);
|
||
|
dma::EndTag();
|
||
|
|
||
|
if (UsesPip==false)
|
||
|
{
|
||
|
Shit++;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
void DeleteTextures(sScene *pScene)
|
||
|
{
|
||
|
sScene *pPrev;
|
||
|
sGroup *pGroup, *pDead;
|
||
|
|
||
|
// deallocate assets
|
||
|
Mem::Free(pScene->pTexBuffer);
|
||
|
Mem::Free(pScene->pTexDma);
|
||
|
if( pScene->pTextures != NULL )
|
||
|
{
|
||
|
Mem::Free(pScene->pTextures);
|
||
|
}
|
||
|
|
||
|
// deallocate groups
|
||
|
pGroup = sGroup::pHead;
|
||
|
while (pGroup)
|
||
|
{
|
||
|
if (pGroup->pScene == pScene)
|
||
|
{
|
||
|
if (pGroup == sGroup::pHead)
|
||
|
{
|
||
|
pGroup->pNext->pPrev = NULL;
|
||
|
sGroup::pHead = pGroup->pNext;
|
||
|
}
|
||
|
else if (pGroup == sGroup::pTail)
|
||
|
{
|
||
|
pGroup->pPrev->pNext = NULL;
|
||
|
sGroup::pTail = pGroup->pPrev;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pGroup->pNext->pPrev = pGroup->pPrev;
|
||
|
pGroup->pPrev->pNext = pGroup->pNext;
|
||
|
}
|
||
|
pDead = pGroup;
|
||
|
pGroup = pGroup->pNext;
|
||
|
Mem::Free(pDead);
|
||
|
}
|
||
|
else
|
||
|
pGroup = pGroup->pNext;
|
||
|
}
|
||
|
|
||
|
// unlink
|
||
|
if (pScene==sScene::pHead)
|
||
|
sScene::pHead = pScene->pNext;
|
||
|
else
|
||
|
{
|
||
|
for (pPrev=sScene::pHead; pPrev; pPrev=pPrev->pNext)
|
||
|
if (pPrev->pNext == pScene)
|
||
|
break;
|
||
|
Dbg_MsgAssert(pPrev, ("couldn't find scene to delete\n"));
|
||
|
|
||
|
pPrev->pNext = pScene->pNext;
|
||
|
}
|
||
|
|
||
|
// free
|
||
|
Mem::Free(pScene);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
sTexture *ResolveTextureChecksum(uint32 TextureChecksum)
|
||
|
{
|
||
|
sScene *pScene;
|
||
|
sTexture *pTex=NULL;
|
||
|
int i;
|
||
|
|
||
|
for (pScene=sScene::pHead; pScene; pScene=pScene->pNext)
|
||
|
{
|
||
|
for (i=0,pTex=pScene->pTextures; i<pScene->NumTextures; i++,pTex++)
|
||
|
if ((pTex->Checksum == TextureChecksum) && (pTex->Flags & TEXFLAG_ORIGINAL))
|
||
|
return pTex;
|
||
|
}
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
sTexture *ResolveTextureChecksum(uint32 TextureChecksum, uint32 GroupChecksum)
|
||
|
{
|
||
|
sScene *pScene;
|
||
|
sTexture *pTex=NULL;
|
||
|
int i;
|
||
|
|
||
|
for (pScene=sScene::pHead; pScene; pScene=pScene->pNext)
|
||
|
{
|
||
|
for (i=0,pTex=pScene->pTextures; i<pScene->NumTextures; i++,pTex++)
|
||
|
if ((pTex->Checksum == TextureChecksum) && (pTex->GroupChecksum == GroupChecksum))
|
||
|
return pTex;
|
||
|
}
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
uint32 sTexture::sVersion;
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// The following Get() calls are very inefficient. They should only be
|
||
|
// used when necessary (i.e. initialization).
|
||
|
//
|
||
|
uint16 sTexture::GetWidth() const
|
||
|
{
|
||
|
sceGsTex0 tex0 = *((sceGsTex0 *) &RegTEX0);
|
||
|
uint16 TW = tex0.TW;
|
||
|
//uint16 TW = (uint16) ((RegTEX0 >> 26) & M04);
|
||
|
|
||
|
return 1 << TW;
|
||
|
}
|
||
|
|
||
|
uint16 sTexture::GetHeight() const
|
||
|
{
|
||
|
sceGsTex0 tex0 = *((sceGsTex0 *) &RegTEX0);
|
||
|
uint16 TH = tex0.TH;
|
||
|
//uint16 TH = (uint16) ((RegTEX0 >> 30) & M04);
|
||
|
|
||
|
return 1 << TH;
|
||
|
}
|
||
|
|
||
|
uint8 sTexture::GetBitdepth() const
|
||
|
{
|
||
|
sceGsTex0 tex0 = *((sceGsTex0 *) &RegTEX0);
|
||
|
uint PSM = tex0.PSM;
|
||
|
|
||
|
switch (PSM)
|
||
|
{
|
||
|
case PSMCT32:
|
||
|
return 32;
|
||
|
break;
|
||
|
case PSMCT24:
|
||
|
return 24;
|
||
|
break;
|
||
|
case PSMCT16:
|
||
|
return 16;
|
||
|
break;
|
||
|
case PSMT8:
|
||
|
return 8;
|
||
|
break;
|
||
|
case PSMT4:
|
||
|
return 4;
|
||
|
break;
|
||
|
default:
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
uint8 sTexture::GetClutBitdepth() const
|
||
|
{
|
||
|
sceGsTex0 tex0 = *((sceGsTex0 *) &RegTEX0);
|
||
|
uint CPSM = tex0.CPSM;
|
||
|
|
||
|
switch (CPSM)
|
||
|
{
|
||
|
case PSMCT32:
|
||
|
return 32;
|
||
|
break;
|
||
|
case PSMCT24:
|
||
|
return 24;
|
||
|
break;
|
||
|
case PSMCT16:
|
||
|
return 16;
|
||
|
break;
|
||
|
default:
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
uint8 sTexture::GetNumMipmaps() const
|
||
|
{
|
||
|
return MXL + 1;
|
||
|
}
|
||
|
|
||
|
bool sTexture::HasSwizzleMip() const
|
||
|
{
|
||
|
for (uint mip_idx = 0; mip_idx <= MXL; mip_idx++)
|
||
|
{
|
||
|
if (Flags & TEXFLAG_MIP_SWIZZLE(mip_idx))
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
void sTexture::ReplaceTextureData(uint8 *p_texture_data)
|
||
|
{
|
||
|
uint mip_width, mip_height, mip_NumTexBytes;
|
||
|
|
||
|
int bitdepth = GetBitdepth();
|
||
|
int width = GetWidth();
|
||
|
int height = GetHeight();
|
||
|
|
||
|
uint8 *pTextureSource = mp_texture_buffer;
|
||
|
|
||
|
// calculate texture dimensions
|
||
|
for (uint j=0; j<=MXL; j++)
|
||
|
{
|
||
|
mip_width = width >> j;
|
||
|
mip_height = height >> j;
|
||
|
mip_NumTexBytes = mip_width * mip_height * bitdepth >> 3;
|
||
|
|
||
|
// Do the actual copies, swizzling if necessary
|
||
|
if (Flags & TEXFLAG_MIP_SWIZZLE_16BIT(j))
|
||
|
{
|
||
|
switch (bitdepth)
|
||
|
{
|
||
|
case 4:
|
||
|
TexMemLayout.Conv4to16(mip_width, mip_height, p_texture_data, pTextureSource);
|
||
|
break;
|
||
|
case 8:
|
||
|
default:
|
||
|
Dbg_MsgAssert(0, ("Can't swizzle a texture of bitdepth %d to 16-bit", bitdepth));
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else if (Flags & TEXFLAG_MIP_SWIZZLE_32BIT(j))
|
||
|
{
|
||
|
switch (bitdepth)
|
||
|
{
|
||
|
case 8:
|
||
|
TexMemLayout.Conv8to32(mip_width, mip_height, p_texture_data, pTextureSource);
|
||
|
break;
|
||
|
case 4:
|
||
|
TexMemLayout.Conv4to32(mip_width, mip_height, p_texture_data, pTextureSource);
|
||
|
break;
|
||
|
default:
|
||
|
Dbg_MsgAssert(0, ("Can't swizzle a texture of bitdepth %d to 32-bit", bitdepth));
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
memcpy(pTextureSource, p_texture_data, mip_NumTexBytes);
|
||
|
}
|
||
|
|
||
|
// step past tex data for this level
|
||
|
pTextureSource += mip_NumTexBytes;
|
||
|
p_texture_data += mip_NumTexBytes;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
} // namespace NxPs2
|
||
|
|