SBSPSS/source/gfx/tpage.cpp
2001-06-13 18:32:53 +00:00

316 lines
8.4 KiB
C++

/**********************/
/*** PSX Vram Stuff ***/
/**********************/
#include "System\global.h"
#include "Gfx\TPage.h"
#include "Gfx\AnimTex.h"
#include "Gfx\Prim.h"
#include "System\vid.h"
#include "FileIO/FileIO.h"
#include "Mem\Memory.h"
#include "utils\utils.h"
enum TPAGE_ENUMS
{
TPAGE_HALF0 = 0,
TPAGE_HALF1 = 1,
TPAGE_FULL = 0,
TPAGE_DYN_START = (24),
TPAGE_DYN_END = (26),
MAX_TPAGES = 32,
};
//#define INVALIDATE_CACHE 1
const int TPRawW=64;
const int TPRawH=256;
struct sAnimTexInfo
{
int Frame;
sFrameHdr FrameHdr;
};
struct sTPageInfo
{
s16 RefCount;
FileEquate TPageName;
s16 XOfs,YOfs;
u16 AnimTexCount;
sAnimTexInfo AnimTexFrame[TPAGE_MAX_ANIM_TEX];
};
struct sTPageCache
{
sTPageInfo Info[2];
};
static sTPageCache s_TPCache[MAX_TPAGES];
// Theory!!
// Filenames stored so IF tpage is set to load, AND is found within table (free or not) then use that
// Will only work if people are good with the tpage allocation (due to no checks on width)
// Will write a InvalidDate routine
/*****************************************************************************/
void TPInit()
{
// Likes to be a multiple of 65536, dunno why, Im shit like that
for (int i=0; i<MAX_TPAGES ;i++)
{
s_TPCache[i].Info[0].RefCount=s_TPCache[i].Info[1].RefCount=0;
s_TPCache[i].Info[0].TPageName=s_TPCache[i].Info[1].TPageName=(FileEquate)0;
s_TPCache[i].Info[0].AnimTexCount=s_TPCache[i].Info[1].AnimTexCount=0;
}
}
/*****************************************************************************/
void TPFree( const TPAGE_DESC & desc,int Invalidate)
{
#if defined(INVALIDATE_CACHE)
RECT R;
setRECT(&R,(desc.tpage&0xf)*TPRawW,(desc.tpage>15)*TPRawH,64,128);
Invalidate=1;
#endif
s_TPCache[desc.tpage].Info[desc.Half].RefCount--;
if (!s_TPCache[desc.tpage].Info[desc.Half].RefCount)
{
if (Invalidate) s_TPCache[desc.tpage].Info[desc.Half].TPageName=(FileEquate)0;
if (desc.Half==0 && s_TPCache[desc.tpage].Info[1].RefCount==-1) // Check for full tpage
{
s_TPCache[desc.tpage].Info[1].RefCount=0;
#if defined(INVALIDATE_CACHE)
R.h=256;
#endif
}
CAnimTex::DumpThisTPage(s_TPCache[desc.tpage].Info[desc.Half].TPageName);
#if defined(INVALIDATE_CACHE)
R.y+=desc.Half*128;
ClearImage(&R,0,255,0);
#endif
}
}
/*****************************************************************************/
void IsTPageInCache(FileEquate Filename,int &TPage,int &Half)
{
TPage=0;
for (int Loop=0; Loop<MAX_TPAGES && !TPage; Loop++)
{
if (s_TPCache[Loop].Info[0].TPageName==Filename)
{
Half=0;
TPage=Loop;
}
else
if (s_TPCache[Loop].Info[1].TPageName==Filename)
{
Half=1;
TPage=Loop;
}
}
}
/*****************************************************************************/
sTPageInfo *FindSpareTPage(FileEquate Filename, int &TPage,int &Half,sTPageHdr *TPHdr)
{
TPage=TPHdr->TPageStart;
Half=0;
if (TPage>=TPAGE_DYN_START && TPage<=TPAGE_DYN_END) // Its a dynamic TPage!
{
// Find spare VRam
if (TPHdr->TPageHeightInPixels <= 128) // Half TPage
{
// Find spare half
while(s_TPCache[TPage].Info[0].RefCount && s_TPCache[TPage].Info[1].RefCount)
{
TPage++;
ASSERT(TPage <= TPAGE_DYN_END);// ASSERT(!"VRAM FULL");
}
if (!s_TPCache[TPage].Info[0].RefCount)
Half = TPAGE_HALF0;
else
Half=TPAGE_HALF1;
}
else
{ // Full TPage
while(s_TPCache[TPage].Info[0].RefCount || s_TPCache[TPage].Info[1].RefCount)
{
TPage++;
if (TPage >= MAX_TPAGES) ASSERT(!"VRAM FULL");
}
Half = TPAGE_FULL;
s_TPCache[TPage].Info[1].TPageName=(FileEquate)0;
s_TPCache[TPage].Info[1].RefCount=-1; // lock 2nd half
}
}
sTPageInfo *Cache=&s_TPCache[TPage].Info[Half];
Cache->RefCount++;
Cache->TPageName=Filename;
Cache->XOfs=TPage-TPHdr->TPageStart;
Cache->YOfs=Half*128;
Cache->AnimTexCount=0;
return(Cache);
}
/*****************************************************************************/
void TPLoadVRam(sTPageHdr *TPHdr, int TPage, int Half, u32 *VRamData)
{
RECT Rect;
// Read and DMA TP to VRam
Rect.x=(TPage%16)*TPRawW;
Rect.y=((TPage>>4)*TPRawH)+(Half*128);
Rect.w=TPHdr->TPageWidth*TPRawW;
Rect.h=TPHdr->TPageHeightInPixels;
DrawSync( 0 );
LoadImage( &Rect, VRamData);
}
/*****************************************************************************/
void AddAnimTexToList(sTPageInfo *Cache,sFrameHdr *FramePtr,int Frm,int TPage,int Half)
{
MCmemcpy(&Cache->AnimTexFrame[Cache->AnimTexCount].FrameHdr,FramePtr,sizeof(sFrameHdr));
Cache->AnimTexFrame[Cache->AnimTexCount].Frame=Frm;
Cache->AnimTexCount++;
}
/*****************************************************************************/
TPAGE_DESC TPLoadTex(FileEquate Filename)
{
TPAGE_DESC Desc;
sTPageHdr *TPHdr;
sFrameHdr *FramePtr;
u32 *VRAMData;
int TPage,Half;
sTPageInfo *Cache;
// Is it already loaded in TCache?
IsTPageInCache(Filename,TPage,Half);
if (TPage) // Is in cache, no need to load it again :o)
{
// DBG_MSG2("TPLoadTex Cached (%i,%i)",TPage,Half);
s_TPCache[TPage].Info[Half].RefCount++;
Cache=&s_TPCache[TPage].Info[Half];
}
else
{ // Better load it then
// DBG_MSG0("TPLoadTex");
TPHdr=(sTPageHdr*)CFileIO::loadFile(Filename,"TPLoadTEX");
ASSERT(!TPHdr->NumOfSpareBoxes);
FramePtr=(sFrameHdr*) MakePtr(TPHdr,sizeof(sTPageHdr));
VRAMData=(u32*) MakePtr(FramePtr,TPHdr->NoOfFrames*sizeof(sFrameHdr));
Cache=FindSpareTPage(Filename,TPage,Half,TPHdr);
for (int Frm=0;Frm<TPHdr->NoOfFrames; Frm++) // Add Animated Texture references
{
if (FramePtr->Cycle) AddAnimTexToList(Cache,FramePtr,Frm,TPage,Half);
FramePtr++;
}
TPLoadVRam(TPHdr, TPage,Half,VRAMData);
MemFree(TPHdr);
}
// If first instance, add animated textures
if (Cache->RefCount==1)
{
sAnimTexInfo *ATexPtr=Cache->AnimTexFrame;
for (int Frm=0; Frm<Cache->AnimTexCount; Frm++) CAnimTex::AddAnimTex(&ATexPtr[Frm].FrameHdr,ATexPtr[Frm].Frame,Filename);
}
Desc.Half= Half;
Desc.tpage = TPage;
Desc.xoffset = Cache->XOfs;
Desc.yoffset = Cache->YOfs;
return (Desc);
}
/*****************************************************************************/
// These are NEVER dynamic, but need to store the frame headers
// Plus, this should only happen at system startup now :o)
TPAGE_DESC TPLoadTexWithHeaders(FileEquate Filename, sFrameHdr **hdrs )
{
TPAGE_DESC Desc;
sTPageHdr TPHdr;
sFrameHdr *FramePtr;
u32 *VRAMData;
int TPage,Half=0;
sTPageInfo *Cache;
int ReadLeft;
// Is it already loaded in TCache?
IsTPageInCache(Filename,TPage,Half);
if (TPage) // Found one!!
{
// DBG_MSG2("TPLoadTexWithHeaders Cached (%i,%i)",TPage,Half);
s_TPCache[TPage].Info[Half].RefCount++;
Cache=&s_TPCache[TPage].Info[Half];
// Reload headers (PKG)
CFileIO::OpenFile(Filename);
CFileIO::ReadFile((void*)&TPHdr,sizeof(sTPageHdr));
*hdrs=(sFrameHdr*)MemAlloc(sizeof(sFrameHdr)*TPHdr.NoOfFrames,"TpFh(from cache)");
ReadLeft=CFileIO::GetReadLeft();
FramePtr=(sFrameHdr*)MemAlloc(ReadLeft,"TPLoadTemp");
CFileIO::ReadFile(FramePtr,ReadLeft);
CFileIO::CloseFile();
MCmemcpy(*hdrs,FramePtr,TPHdr.NoOfFrames*sizeof(sFrameHdr));
MemFree(FramePtr);
}
else
{
// DBG_MSG0("TPLoadTexWithHeaders");
CFileIO::OpenFile(Filename);
// Load Main Header
CFileIO::ReadFile((void*)&TPHdr,sizeof(sTPageHdr));
ASSERT(!TPHdr.NumOfSpareBoxes);
TPage=TPHdr.TPageStart;
// Load Rest
*hdrs=(sFrameHdr*)MemAlloc(sizeof(sFrameHdr)*TPHdr.NoOfFrames,"TpFh");
ReadLeft=CFileIO::GetReadLeft();
FramePtr=(sFrameHdr*)MemAlloc(ReadLeft,"TPLoadTemp");
CFileIO::ReadFile(FramePtr,ReadLeft);
CFileIO::CloseFile();
VRAMData=(u32*) MakePtr(FramePtr,TPHdr.NoOfFrames*sizeof(sFrameHdr));
MCmemcpy(*hdrs,FramePtr,TPHdr.NoOfFrames*sizeof(sFrameHdr));
TPLoadVRam(&TPHdr, TPage,Half,VRAMData);
Cache=&s_TPCache[TPage].Info[Half];
MemFree(FramePtr);
FramePtr=*hdrs;
for (int Frm=0;Frm<TPHdr.NoOfFrames; Frm++) // Add Animated Texture references
{
if (FramePtr->Cycle) AddAnimTexToList(Cache,FramePtr++,Frm,TPage,Half);
}
Cache->RefCount=1;
Cache->TPageName=Filename;
Cache->XOfs=0;
Cache->YOfs=0;
Cache->AnimTexCount=0;
s_TPCache[TPage].Info[1].RefCount=-1;
}
// If first instance, add animated textures
if (Cache->RefCount==1)
{
sAnimTexInfo *ATexPtr=Cache->AnimTexFrame;
for (int Frm=0; Frm<Cache->AnimTexCount; Frm++) CAnimTex::AddAnimTex(&ATexPtr[Frm].FrameHdr,ATexPtr[Frm].Frame,Filename);
}
Desc.Half= Half;
Desc.tpage = TPage;
Desc.xoffset = Cache->XOfs;
Desc.yoffset = Cache->YOfs;
return (Desc);
}