SBSPSS/source/gfx/actor.cpp

834 lines
19 KiB
C++
Raw Normal View History

2001-04-01 09:22:30 +02:00
/******************/
/*** Actor Bank ***/
/******************/
#include "system\global.h"
#include "mem\memory.h"
#include "fileio\fileio.h"
#include "utils\utils.h"
2001-04-01 22:22:49 +02:00
#include "utils\pak.h"
#include "gfx\prim.h"
2001-04-01 23:38:59 +02:00
#include "gfx\actor.h"
2001-05-02 00:28:01 +02:00
#include "gfx\otpos.h"
2001-04-01 09:22:30 +02:00
#include <dstructs.h>
2001-04-09 23:27:21 +02:00
/*****************************************************************************/
2001-04-25 18:41:16 +02:00
CActorCache CActorPool::Cache;
sActorPool *CActorPool::ActorList,*CActorPool::LastActor;
2001-04-25 21:11:45 +02:00
u8 *CActorCache::UnpackBuffer;
2001-04-25 18:41:16 +02:00
/*****************************************************************************/
/*** Cache *******************************************************************/
/*****************************************************************************/
CActorCache::CActorCache()
{
for (int i=0;i<CACHE_TYPE_MAX; i++)
{
2001-04-25 21:11:45 +02:00
SlotList[i].ListMem=0;
2001-04-25 18:41:16 +02:00
}
2001-04-25 21:11:45 +02:00
UnpackBuffer=0;
2001-04-25 18:41:16 +02:00
}
/*****************************************************************************/
CActorCache::~CActorCache()
{
}
2001-04-09 23:27:21 +02:00
2001-04-04 18:51:04 +02:00
/*****************************************************************************/
2001-04-25 18:41:16 +02:00
int CActorCache::GetSizeType(int Size)
{
2001-04-27 22:28:47 +02:00
// if (Size<= 16) return(16);
// if (Size<= 32) return(32);
// if (Size<= 64) return(64);
// if (Size<=128) return(128);
// if (Size<=256) return(256);
2001-04-27 23:42:38 +02:00
return((Size+15)&-16);
2001-04-27 22:28:47 +02:00
// Size>>=4;
// Size<<=4;
2001-04-27 23:42:38 +02:00
// return(Size);
2001-04-25 18:41:16 +02:00
ASSERT(!"SPRITE SIZE NOT SUPPORTED");
return(-1);
}
2001-04-04 18:51:04 +02:00
2001-05-05 20:38:24 +02:00
/*****************************************************************************/
int CActorCache::ReAllocSlot(int W,int H)
{
int i;
int Slot=-1;
int SlotW=+32000,SlotH=+32000;
// Find best slot which fits in
// ASSERT(!"ReAlloc");
for (i=0;i<SlotCount; i++)
{
int ThisW=(SlotList[i].Width-W);
int ThisH=(SlotList[i].Height-H);
if (ThisW<SlotW || ThisH<SlotH)
{
Slot=i;
SlotW=ThisW;
SlotH=ThisH;
}
}
if (SlotList[Slot].Width<W)
{
// printf("Adjusted Slot Width from %i to %i\n",SlotList[Slot].Width,W);
SlotList[Slot].Width=W;
}
if (SlotList[Slot].Height<H)
{
// printf("Adjusted Slot Height from %i to %i\n",SlotList[Slot].Height,H);
SlotList[Slot].Height=H;
}
return(Slot);
}
2001-04-25 18:41:16 +02:00
/*****************************************************************************/
int CActorCache::GetSlot(int W,int H)
2001-04-04 18:51:04 +02:00
{
2001-04-25 18:41:16 +02:00
int i;
int Slot=0;
W=GetSizeType(W);
H=GetSizeType(H);
for (i=0; i<SlotCount && !Slot; i++)
{ // Slot exist?
if (SlotList[i].Width==W && SlotList[i].Height==H) Slot=i;
}
if (!Slot)
{ // Use New Slot
2001-05-05 20:38:24 +02:00
if (SlotCount>=CACHE_TYPE_MAX)
{ // No free slots, grab an existing one, and alter size to fit
Slot=ReAllocSlot(W,H);
}
else
{
2001-04-25 18:41:16 +02:00
Slot=SlotCount;
SlotList[Slot].Width=W;
SlotList[Slot].Height=H;
2001-05-05 18:34:58 +02:00
SlotCount++;
2001-05-05 20:38:24 +02:00
}
2001-04-25 18:41:16 +02:00
}
SlotList[Slot].RefCount++;
return(Slot);
}
/*****************************************************************************/
sPoolNode *CActorCache::RemoveHeadNode(sNodeList *Root)
{
2001-04-27 22:28:47 +02:00
sPoolNode *Node=Root->Head;
2001-04-25 18:41:16 +02:00
sPoolNode *Next=Node->Next;
2001-04-27 22:28:47 +02:00
Root->Head=Node->Next;
2001-04-25 18:41:16 +02:00
Next->Prev=0;
Node->Next=0;
return(Node);
}
/*****************************************************************************/
void CActorCache::RemoveNode(sPoolNode *Node,sNodeList *Root)
{
sPoolNode *Prev=Node->Prev;
sPoolNode *Next=Node->Next;
if (Prev)
{ // Not Head Node
Prev->Next=Node->Next;
}
if (Next)
{ // Not Tail Node
Next->Prev=Node->Prev;
}
}
/*****************************************************************************/
// Add node to end of list
void CActorCache::AddNode(sPoolNode *Node,sNodeList *Root)
2001-04-09 23:27:21 +02:00
{
2001-04-27 22:28:47 +02:00
sPoolNode *Prev=Root->Tail;
2001-04-25 18:41:16 +02:00
sPoolNode *Next=0;
if (Prev)
{ // Not Head Node
Prev->Next=Node;
}
else
2001-04-09 23:27:21 +02:00
{
2001-04-27 22:28:47 +02:00
Root->Head=Node;
2001-04-09 23:27:21 +02:00
}
2001-04-25 18:41:16 +02:00
Node->Prev=Prev;
Node->Next=0;
2001-04-27 22:28:47 +02:00
Root->Tail=Node;
}
/*****************************************************************************/
// Add node list to end of list
void CActorCache::AddNodeList(sNodeList *Src,sNodeList *Dst)
{
sPoolNode *SrcHead=Src->Head;
sPoolNode *SrcTail=Src->Tail;
sPoolNode *DstHead=Dst->Head;
sPoolNode *DstTail=Dst->Tail;
if (!SrcHead) return;
if (!DstTail)
{
Dst->Head=SrcHead;
SrcHead->Prev=0;
}
else
{
DstTail->Next=SrcHead;
SrcHead->Prev=DstTail;
}
SrcTail->Next=0;
Dst->Tail=SrcTail;
Src->Head=0;
Src->Tail=0;
2001-04-09 23:27:21 +02:00
}
2001-04-01 22:22:49 +02:00
/*****************************************************************************/
2001-04-25 18:41:16 +02:00
int CActorCache::ReserveSlot(int W,int H,int FrameCount)
2001-04-01 22:22:49 +02:00
{
2001-04-25 18:41:16 +02:00
int Slot=GetSlot(W,H);
SlotList[Slot].FrameCount+=FrameCount;
return(Slot);
}
2001-04-09 23:27:21 +02:00
2001-04-25 18:41:16 +02:00
/*****************************************************************************/
void CActorCache::AllocCache()
{
int TPW=CACHE_W/SlotCount;
2001-04-25 21:11:45 +02:00
int MaxW=0;
int MaxH=0;
2001-04-27 23:42:38 +02:00
/* if (TPW<1) */TPW=1;
2001-05-05 18:34:58 +02:00
2001-05-05 20:38:24 +02:00
ASSERT(SlotCount<=CACHE_W);
2001-04-27 23:42:38 +02:00
2001-04-25 18:41:16 +02:00
for (int i=0; i<SlotCount; i++)
2001-04-09 23:27:21 +02:00
{
2001-04-25 21:11:45 +02:00
if (MaxW<SlotList[i].Width) MaxW=SlotList[i].Width;
if (MaxH<SlotList[i].Height) MaxH=SlotList[i].Height;
2001-04-25 18:41:16 +02:00
InitCache(i,TPW);
}
2001-04-25 21:11:45 +02:00
UnpackBuffer=(u8*)MemAlloc(MaxW*MaxH,"UnpackBuffer");
2001-04-25 18:41:16 +02:00
}
/*****************************************************************************/
// This needs improving to 'grab' free areas left from bigger grabs (YIKES!)
void CActorCache::InitCache(int Slot,int TPW)
{
sPoolSlot *ThisSlot=&SlotList[Slot];
int W=(TPW*(TPAGE_W))/ThisSlot->Width;
int H=(TPAGE_H)/ThisSlot->Height;
int Total=W*H;
sPoolNode *List;
// Init List
2001-04-25 21:11:45 +02:00
ThisSlot->ListMem=(u8*)MemAlloc(Total*sizeof(sPoolNode),"CacheNodeList");
List=(sPoolNode*)ThisSlot->ListMem;
2001-04-25 18:41:16 +02:00
// Create List Entries
for (int Y=0; Y<H; Y++)
2001-04-09 23:27:21 +02:00
{
2001-04-25 18:41:16 +02:00
for (int X=0; X<W; X++)
2001-04-09 23:27:21 +02:00
{
2001-04-25 18:41:16 +02:00
int U=(X*ThisSlot->Width);
int V=Y*ThisSlot->Height;
int TexX=CACHE_X+CurrentTPX+(U>>2);
int TexY=CACHE_Y+V;
List->Actor=0;
List->TexX=TexX;
List->TexY=TexY;
List->U=U&255;
List->V=V&255;
2001-04-27 23:42:38 +02:00
List->TPage=getTPage(0,0,TexX,TexY);
2001-04-25 18:41:16 +02:00
AddNode(List,&ThisSlot->NodeList);
List++;
2001-04-09 23:27:21 +02:00
}
}
2001-04-25 18:41:16 +02:00
CurrentTPX+=(TPW*TPAGE_W)>>2;
2001-04-01 22:22:49 +02:00
}
2001-04-09 23:27:21 +02:00
/*****************************************************************************/
2001-04-25 18:41:16 +02:00
void CActorCache::Reset()
2001-04-09 23:27:21 +02:00
{
2001-04-25 18:41:16 +02:00
// Free and init lists
for (int i=0;i<CACHE_TYPE_MAX; i++)
{
2001-04-25 21:11:45 +02:00
if (SlotList[i].ListMem) MemFree(SlotList[i].ListMem);
SlotList[i].ListMem=0;
2001-04-27 22:28:47 +02:00
SlotList[i].NodeList.Head=0;
SlotList[i].NodeList.Tail=0;
2001-04-25 18:41:16 +02:00
SlotList[i].RefCount=0;
SlotList[i].FrameCount=0;
SlotList[i].Width=0;
SlotList[i].Height=0;
}
2001-04-25 21:11:45 +02:00
if (UnpackBuffer) MemFree(UnpackBuffer);
UnpackBuffer=0;
2001-04-25 18:41:16 +02:00
CurrentTPX=0;
CurrentPalette=0;
SlotCount=0;
// Clear VRam
2001-04-27 23:42:38 +02:00
RECT R={CACHE_X,CACHE_Y,TPAGE_W*CACHE_W,TPAGE_H*CACHE_H};
2001-04-25 18:41:16 +02:00
ClearImage(&R,0,255,0);
}
/*****************************************************************************/
void CActorCache::LoadPalette(sActorPool *Actor)
{
2001-04-26 23:15:36 +02:00
if (!Actor->ActorGfx->Clut)
{ // Cheap bodge at mo
RECT R;
int X=CurrentPalette%(((CACHE_W*TPAGE_W)/CACHE_PALW));
int Y=CurrentPalette/(((CACHE_W*TPAGE_W)/CACHE_PALW)-1);
2001-04-25 18:41:16 +02:00
2001-04-26 23:15:36 +02:00
if (Actor->Filename==ACTORS_SPONGEBOB_SBK)
{
R.x=512;
R.y=511;
}
else
{
R.x=CACHE_PALX+(CurrentPalette*CACHE_PALW);
R.y=CACHE_PALY-Y;
}
2001-04-25 18:41:16 +02:00
2001-04-26 23:15:36 +02:00
R.w=CACHE_PALW;
R.h=CACHE_PALH;
DrawSync(0);
LoadImage( &R, (u32*)Actor->ActorGfx->Palette);
Actor->ActorGfx->Clut=getClut(R.x,R.y);
CurrentPalette++;
}
2001-04-09 23:27:21 +02:00
}
2001-04-02 00:55:15 +02:00
2001-04-01 09:22:30 +02:00
/*****************************************************************************/
2001-04-09 23:27:21 +02:00
/*****************************************************************************/
/*****************************************************************************/
void CActorPool::Init()
2001-04-01 09:22:30 +02:00
{
2001-04-25 18:41:16 +02:00
ActorList=0;
2001-04-25 21:33:39 +02:00
Cache.Reset();
2001-04-25 18:41:16 +02:00
}
/*****************************************************************************/
void CActorPool::Reset()
{
sActorPool *List=ActorList;
while (List)
{
sActorPool *Next=List->Next;
if (List->Filename!=ACTORS_SPONGEBOB_SBK)
{
MemFree(List->ActorGfx);
delete List;
}
else
{
List->Next=0;
}
List=Next;
}
2001-04-25 21:33:39 +02:00
LastActor=ActorList;
2001-04-25 18:41:16 +02:00
Cache.Reset();
2001-04-09 23:27:21 +02:00
}
2001-04-02 00:55:15 +02:00
2001-04-09 23:27:21 +02:00
/*****************************************************************************/
2001-04-25 18:41:16 +02:00
void CActorPool::SetUpCache()
2001-04-09 23:27:21 +02:00
{
2001-04-25 18:41:16 +02:00
Cache.AllocCache();
// SetUp Actors
sActorPool *List=ActorList;
while (List)
{
2001-04-27 22:28:47 +02:00
List->PoolCache=Cache.GetSlotList(List->CacheSlot);
List->ActorCache.Head=0;
List->ActorCache.Tail=0;
2001-04-25 18:41:16 +02:00
List=List->Next;
}
}
/*****************************************************************************/
sActorPool *CActorPool::FindActor(FileEquate Filename)
{
sActorPool *List=ActorList;
while (List)
2001-04-09 23:27:21 +02:00
{
2001-04-25 18:41:16 +02:00
if (List->ActorGfx && List->Filename==Filename) return(List);
List=List->Next;
2001-04-09 23:27:21 +02:00
}
2001-04-25 18:41:16 +02:00
return(0);
2001-04-09 23:27:21 +02:00
}
2001-04-01 09:22:30 +02:00
2001-04-09 23:27:21 +02:00
/*****************************************************************************/
2001-04-25 18:41:16 +02:00
CActorGfx *CActorPool::GetActor(FileEquate Filename)
2001-04-09 23:27:21 +02:00
{
2001-04-25 18:41:16 +02:00
sActorPool *ThisActor;
CActorGfx *NewActor;
int TotalFrames=0;
bool NewFlag=false;
// Find Actor in Pool
ThisActor=FindActor(Filename);
if (!ThisActor)
2001-04-09 23:27:21 +02:00
{
2001-04-25 18:41:16 +02:00
ThisActor=LoadActor(Filename);
NewFlag=true;
2001-04-09 23:27:21 +02:00
}
2001-04-25 18:41:16 +02:00
NewActor=new ("CActorGfx") CActorGfx(ThisActor);
2001-04-30 23:49:54 +02:00
2001-04-25 18:41:16 +02:00
if (NewFlag)
{
TotalFrames=NewActor->GetTotalFrameCount();
}
ThisActor->CacheSlot=Cache.ReserveSlot(ThisActor->ActorGfx->MaxW,ThisActor->ActorGfx->MaxH,TotalFrames);
return(NewActor);
2001-04-09 23:27:21 +02:00
}
/*****************************************************************************/
2001-04-25 18:41:16 +02:00
sActorPool *CActorPool::LoadActor(FileEquate Filename)
2001-04-09 23:27:21 +02:00
{
int i;
2001-04-25 18:41:16 +02:00
int TotalFrames=0;
2001-04-09 23:27:21 +02:00
2001-04-25 21:11:45 +02:00
sSpriteAnimBank *Spr=(sSpriteAnimBank*)CFileIO::loadFile(Filename,"ActorGfx");
2001-04-09 23:27:21 +02:00
Spr->AnimList=(sSpriteAnim*) MakePtr(Spr,(int)Spr->AnimList);
Spr->FrameList=(sSpriteFrame*) MakePtr(Spr,(int)Spr->FrameList);
Spr->Palette=(u8*) MakePtr(Spr,(int)Spr->Palette);
2001-04-01 22:22:49 +02:00
// FixUp AnimList
2001-04-09 23:27:21 +02:00
for (i=0; i<Spr->AnimCount; i++)
2001-04-01 22:22:49 +02:00
{
2001-04-09 23:27:21 +02:00
sSpriteAnim *ThisAnim=&Spr->AnimList[i];
ThisAnim->Anim=(u16*) MakePtr(Spr,(int)ThisAnim->Anim);
2001-04-25 18:41:16 +02:00
TotalFrames+=ThisAnim->FrameCount;
2001-04-01 22:22:49 +02:00
}
2001-04-25 18:41:16 +02:00
2001-04-01 22:22:49 +02:00
// FixUp FrameList
2001-04-09 23:27:21 +02:00
for (i=0; i<Spr->FrameCount; i++)
2001-04-01 09:22:30 +02:00
{
2001-04-09 23:27:21 +02:00
sSpriteFrame *ThisFrame=&Spr->FrameList[i];
ThisFrame->PAKSpr=(u8*) MakePtr(Spr,(int)ThisFrame->PAKSpr);
2001-04-01 09:22:30 +02:00
}
2001-04-09 23:27:21 +02:00
// Store it
2001-04-25 18:41:16 +02:00
sActorPool *NewActor;
2001-04-02 00:55:15 +02:00
2001-04-25 18:41:16 +02:00
NewActor=new ("ActorPool") sActorPool();
NewActor->Filename=Filename;
NewActor->ActorGfx=Spr;
AddActor(NewActor);
2001-04-09 23:27:21 +02:00
2001-04-25 18:41:16 +02:00
return(NewActor);
2001-04-09 23:27:21 +02:00
}
/*****************************************************************************/
2001-04-25 18:41:16 +02:00
void CActorPool::AddActor(sActorPool *NewActor)
2001-04-09 23:27:21 +02:00
{
2001-04-25 18:41:16 +02:00
// Insert into list
2001-04-09 23:27:21 +02:00
2001-04-25 18:41:16 +02:00
if (!LastActor)
{ // Empty List
ActorList=NewActor;
2001-04-09 23:27:21 +02:00
}
2001-04-25 18:41:16 +02:00
else
{
LastActor->Next=NewActor;
}
NewActor->Next=0;
Cache.LoadPalette(NewActor);
LastActor=NewActor;
2001-04-09 23:27:21 +02:00
}
2001-04-27 22:28:47 +02:00
/*****************************************************************************/
void CActorPool::CleanUpCache()
{
sActorPool *Actor=ActorList;
while (Actor)
{
CActorCache::AddNodeList(&Actor->ActorCache ,Actor->PoolCache);
Actor=Actor->Next;
}
}
2001-04-09 23:27:21 +02:00
/*****************************************************************************/
/*****************************************************************************/
/*****************************************************************************/
/*****************************************************************************/
/*****************************************************************************/
/*****************************************************************************/
2001-04-25 18:41:16 +02:00
/*****************************************************************************/
CActorGfx::CActorGfx(sActorPool *ThisActor)
2001-04-09 23:27:21 +02:00
{
2001-04-25 18:41:16 +02:00
PoolEntry=ThisActor;
2001-04-30 23:49:54 +02:00
ShadowXOfs=DEF_SHADOW_OFS;
ShadowYOfs=DEF_SHADOW_OFS;
2001-05-01 20:21:59 +02:00
ShadowFlag=false;
2001-04-01 09:22:30 +02:00
}
/*****************************************************************************/
CActorGfx::~CActorGfx()
{
2001-04-09 23:27:21 +02:00
}
/*****************************************************************************/
2001-04-25 18:41:16 +02:00
sSpriteFrame *CActorGfx::GetFrame(int Anim,int Frame)
2001-04-09 23:27:21 +02:00
{
2001-04-25 18:41:16 +02:00
sSpriteAnim *ThisAnim=PoolEntry->ActorGfx->AnimList+Anim;
u16 ThisFrame=ThisAnim->Anim[Frame];
return(PoolEntry->ActorGfx->FrameList+ThisFrame);
2001-04-09 23:27:21 +02:00
}
2001-04-01 09:22:30 +02:00
/*****************************************************************************/
2001-05-02 00:28:01 +02:00
int ActorOT=OTPOS__ACTOR_POS;
2001-04-26 23:15:36 +02:00
2001-04-30 23:49:54 +02:00
POLY_FT4 *CActorGfx::Render(DVECTOR &Pos,int Anim,int Frame,bool XFlip,bool YFlip)
2001-04-01 09:22:30 +02:00
{
2001-04-26 15:00:44 +02:00
2001-04-25 18:41:16 +02:00
sPoolNode *ThisNode;;
POLY_FT4 *Ft4;
2001-04-09 23:27:21 +02:00
2001-04-26 15:00:44 +02:00
CurrentFrame=GetFrame(Anim,Frame);
2001-04-25 18:41:16 +02:00
// Is cached?
2001-04-27 22:28:47 +02:00
ThisNode=PoolEntry->ActorCache.Head;
2001-04-25 18:41:16 +02:00
while (ThisNode)
2001-04-27 22:28:47 +02:00
{ // Try local Cache (From Head forward)
2001-04-26 15:00:44 +02:00
if (ThisNode->Actor==PoolEntry->Filename && ThisNode->Anim==Anim && ThisNode->Frame==Frame) break;
2001-04-25 18:41:16 +02:00
ThisNode=ThisNode->Next;
}
2001-04-27 22:28:47 +02:00
/*
if (!ThisNode)
{ // Try main cache ( from tail back)
ThisNode=PoolEntry->PoolCache->Tail;
while (ThisNode)
{
if (ThisNode->Actor==PoolEntry->Filename && ThisNode->Anim==Anim && ThisNode->Frame==Frame) break;
if (ThisNode->Prev==PoolEntry->PoolCache->Tail) ThisNode->Prev=0;
ThisNode=ThisNode->Prev;
2001-04-10 01:29:26 +02:00
2001-04-27 22:28:47 +02:00
}
if (ThisNode)
{
CActorCache::RemoveNode(ThisNode,PoolEntry->PoolCache);
CActorCache::AddNode(ThisNode,&PoolEntry->ActorCache);
}
}
else
{
}
*/
2001-04-25 18:41:16 +02:00
if (!ThisNode)
{ // Not cached frame
2001-04-27 22:28:47 +02:00
ThisNode=CActorCache::RemoveHeadNode(PoolEntry->PoolCache);
2001-05-05 18:34:58 +02:00
if (ThisNode)
{
CActorCache::AddNode(ThisNode,&PoolEntry->ActorCache);
}
else
{
2001-05-05 23:18:12 +02:00
// printf("NO FREE NODES\n");
2001-05-05 18:34:58 +02:00
ThisNode=PoolEntry->ActorCache.Head;
}
2001-04-27 22:28:47 +02:00
ASSERT(ThisNode);
2001-05-05 18:34:58 +02:00
RECT R;
2001-04-25 18:41:16 +02:00
2001-04-26 15:00:44 +02:00
ThisNode->Actor=PoolEntry->Filename;
2001-04-25 18:41:16 +02:00
ThisNode->Anim=Anim;
ThisNode->Frame=Frame;
2001-04-26 15:00:44 +02:00
PAK_doUnpak(CActorCache::UnpackBuffer,CurrentFrame->PAKSpr);
2001-04-25 18:41:16 +02:00
R.x=ThisNode->TexX;
R.y=ThisNode->TexY;
2001-04-26 15:00:44 +02:00
R.w=CurrentFrame->W>>2; // div 4 cos 16 color
R.h=CurrentFrame->H;
2001-04-25 21:11:45 +02:00
LoadImage( &R, (u32*)CActorCache::UnpackBuffer);
2001-04-25 18:41:16 +02:00
}
2001-04-01 22:22:49 +02:00
2001-04-25 18:41:16 +02:00
Ft4=GetPrimFT4();
2001-04-26 15:00:44 +02:00
SetUpFT4(Ft4,CurrentFrame,ThisNode,Pos.vx,Pos.vy,XFlip,YFlip);
2001-04-01 23:38:59 +02:00
setRGB0(Ft4,128,128,128);
2001-04-25 18:41:16 +02:00
Ft4->tpage=ThisNode->TPage;
Ft4->clut=PoolEntry->ActorGfx->Clut;
2001-05-02 00:28:01 +02:00
addPrim(OtPtr+ActorOT,Ft4);
2001-04-01 22:22:49 +02:00
2001-04-30 23:49:54 +02:00
if (ShadowFlag)
2001-04-01 23:38:59 +02:00
{
POLY_FT4 *sFt4=GetPrimFT4();
*sFt4=*Ft4;
sFt4->x0-=ShadowXOfs;
sFt4->x1-=ShadowXOfs;
sFt4->y0+=ShadowYOfs;
sFt4->y1+=ShadowYOfs;
setSemiTrans(sFt4,1);
setRGB0(sFt4,0,0,0);
2001-05-02 00:28:01 +02:00
addPrim(OtPtr+ActorOT,sFt4);
2001-04-01 23:38:59 +02:00
}
2001-04-25 21:11:45 +02:00
// Set BBox
2001-04-26 15:00:44 +02:00
int HalfW=CurrentFrame->W>>1;
2001-04-25 21:11:45 +02:00
BBox.XMin=-HalfW;
BBox.XMax=+HalfW;
2001-04-26 15:00:44 +02:00
BBox.YMin=-CurrentFrame->H;
BBox.YMax=0;
2001-04-01 23:38:59 +02:00
return(Ft4);
}
2001-04-26 15:00:44 +02:00
/*****************************************************************************/
POLY_FT4 *CActorGfx::RotateScale(POLY_FT4 *Ft4,DVECTOR &Pos,int Angle,int XScale,int YScale)
{
int dX,dY;
int CosAngle,SinAngle;
int CosX,CosY,SinX,SinY;
sBBox SBox,CBox;
Angle&=4095;
dX=(CurrentFrame->W*XScale)>>(12+1); // +1 for half
dY=(CurrentFrame->H*YScale)>>(12);
CosAngle=mcos(Angle);
SinAngle=msin(Angle);
SBox.XMin=(SinAngle*-dX)>>12;
SBox.XMax=(SinAngle*+dX)>>12;
SBox.YMin=(SinAngle*-dY)>>12;
SBox.YMax=0;
CBox.XMin=(CosAngle*-dX)>>12;
CBox.XMax=(CosAngle*+dX)>>12;
CBox.YMin=(CosAngle*-dY)>>12;
CBox.YMax=0;
2001-04-26 16:36:30 +02:00
int x0,x1,x2,x3;
int y0,y1,y2,y3;
int XMin,XMax;
int YMin,YMax;
x0=CBox.XMin-SBox.YMin; y0=SBox.XMin+CBox.YMin;
x1=CBox.XMax-SBox.YMin; y1=SBox.XMax+CBox.YMin;
x2=CBox.XMin+SBox.YMax; y2=SBox.XMin-CBox.YMax;
x3=CBox.XMax+SBox.YMax; y3=SBox.XMax-CBox.YMax;
XMin=x0;
if (XMin>x1) XMin=x1;
if (XMin>x2) XMin=x2;
if (XMin>x3) XMin=x3;
XMax=x0;
if (XMax<x1) XMax=x1;
if (XMax<x2) XMax=x2;
if (XMax<x3) XMax=x3;
YMin=y0;
if (YMin>y1) YMin=y1;
if (YMin>y2) YMin=y2;
if (YMin>y3) YMin=y3;
YMax=y0;
if (YMax<y1) YMax=y1;
if (YMax<y2) YMax=y2;
if (YMax<y3) YMax=y3;
BBox.XMin=XMin;
BBox.XMax=XMax;
BBox.YMin=YMin;
BBox.YMax=YMax;
Ft4->x0=Pos.vx+x0; Ft4->y0=Pos.vy+y0;
Ft4->x1=Pos.vx+x1; Ft4->y1=Pos.vy+y1;
Ft4->x2=Pos.vx+x2; Ft4->y2=Pos.vy+y2;
Ft4->x3=Pos.vx+x3; Ft4->y3=Pos.vy+y3;
// Ft4->x0=Pos.vx+CBox.XMin-SBox.YMin; Ft4->y0=Pos.vy+SBox.XMin+CBox.YMin;
// Ft4->x1=Pos.vx+CBox.XMax-SBox.YMin; Ft4->y1=Pos.vy+SBox.XMax+CBox.YMin;
// Ft4->x2=Pos.vx+CBox.XMin+SBox.YMax; Ft4->y2=Pos.vy+SBox.XMin-CBox.YMax;
// Ft4->x3=Pos.vx+CBox.XMax+SBox.YMax; Ft4->y3=Pos.vy+SBox.XMax-CBox.YMax;
2001-04-26 15:00:44 +02:00
return(Ft4);
}
2001-04-01 23:38:59 +02:00
/*****************************************************************************/
2001-04-25 18:41:16 +02:00
void CActorGfx::SetUpFT4(POLY_FT4 *Ft4,sSpriteFrame *Frame,sPoolNode *Node,int X,int Y,bool XFlip,bool YFlip)
2001-04-01 23:38:59 +02:00
{
2001-04-09 23:27:21 +02:00
u8 W=Frame->W;
u8 H=Frame->H;
2001-04-25 18:41:16 +02:00
u8 U=Node->U;
u8 V=Node->V;
2001-04-01 09:22:30 +02:00
2001-04-01 23:38:59 +02:00
if (XFlip)
2001-04-04 17:54:27 +02:00
{
X-=Frame->XOfs;
X-=W;
2001-04-01 23:38:59 +02:00
Ft4->u0=U+W-1;
2001-04-04 17:54:27 +02:00
Ft4->u1=U;//-1;
2001-04-01 23:38:59 +02:00
Ft4->u2=U+W-1;
2001-04-04 17:54:27 +02:00
Ft4->u3=U;//-1;
}
2001-04-01 23:38:59 +02:00
else
{
2001-04-04 17:54:27 +02:00
X+=Frame->XOfs;
2001-04-01 23:38:59 +02:00
Ft4->u0=U;
2001-04-25 18:41:16 +02:00
Ft4->u1=U+W-1;
2001-04-01 23:38:59 +02:00
Ft4->u2=U;
2001-04-25 18:41:16 +02:00
Ft4->u3=U+W-1;
2001-04-04 17:54:27 +02:00
2001-04-01 23:38:59 +02:00
}
if (YFlip)
2001-04-04 17:54:27 +02:00
{
Y-=Frame->YOfs;
Y-=H;
2001-04-01 23:38:59 +02:00
Ft4->v0=V+H-1;
Ft4->v1=V+H-1;
2001-04-04 17:54:27 +02:00
Ft4->v2=V;//-1;
Ft4->v3=V;//-1;
}
2001-04-01 23:38:59 +02:00
else
{
2001-04-04 17:54:27 +02:00
Y+=Frame->YOfs;
2001-04-01 23:38:59 +02:00
Ft4->v0=V;
Ft4->v1=V;
2001-04-26 15:00:44 +02:00
Ft4->v2=V+H-1;
Ft4->v3=V+H-1;
2001-04-01 23:38:59 +02:00
}
setXYWH(Ft4,X,Y,W,H);
2001-04-01 09:22:30 +02:00
}
2001-04-21 00:20:58 +02:00
/*****************************************************************************/
/*****************************************************************************/
/*****************************************************************************/
sModel *CModelGfx::ModelTable;
sTri *CModelGfx::ModelTriList;
sQuad *CModelGfx::ModelQuadList;
sVtx *CModelGfx::ModelVtxList;
/*****************************************************************************/
void CModelGfx::SetData(sModel *Table,sTri *TList,sQuad *QList,sVtx *VList)
{
ModelTable=Table;
ModelTriList=TList;
ModelQuadList=QList;
ModelVtxList=VList;
2001-05-05 01:08:57 +02:00
2001-04-21 00:20:58 +02:00
}
/*****************************************************************************/
void CModelGfx::SetModel(int Type)
{
Model=&CModelGfx::ModelTable[Type];
}
/*****************************************************************************/
2001-05-05 18:34:58 +02:00
int PXOfs=-16;
int PYOfs=-8;
2001-04-27 22:28:47 +02:00
void CModelGfx::Render(DVECTOR &Pos,SVECTOR *Angle=0,VECTOR *Scale=0)
2001-04-21 00:20:58 +02:00
{
#define BLOCK_MULT 16
u8 *PrimPtr=GetPrimPtr();
POLY_FT3 *TPrimPtr=(POLY_FT3*)PrimPtr;
sVtx *P0,*P1,*P2;
u32 T0,T1,T2;
s32 ClipZ;
sOT *ThisOT;
DVECTOR MapXY;
VECTOR RenderPos;
int TriCount=Model->TriCount;
sTri *TList=&ModelTriList[Model->TriStart];
2001-04-27 22:28:47 +02:00
MATRIX Mtx;
SetIdentNoTrans(&Mtx);
if (Scale || Angle)
{
if (Angle) RotMatrix(Angle,&Mtx);
if (Scale) ScaleMatrix(&Mtx,Scale);
}
2001-04-21 00:20:58 +02:00
MapXY.vx=Pos.vx>>4;
MapXY.vy=Pos.vy>>4;
int ShiftX=(Pos.vx & 15);
int ShiftY=(Pos.vy & 15);
RenderPos.vx=(PXOfs*16)+((MapXY.vx*16)+ShiftX);
RenderPos.vy=(PYOfs*16)+((MapXY.vy*16)+ShiftY);
2001-04-27 22:28:47 +02:00
gte_SetRotMatrix(&Mtx);
2001-04-21 00:20:58 +02:00
CMX_SetTransMtxXY(&RenderPos);
while (TriCount--)
{
P0=&ModelVtxList[TList->P0]; P1=&ModelVtxList[TList->P1]; P2=&ModelVtxList[TList->P2];
gte_ldv3(P0,P1,P2);
setlen(TPrimPtr, GPU_PolyFT3Tag);
2001-05-02 20:40:41 +02:00
TPrimPtr->code=TList->PolyCode;
setRGB0(TPrimPtr,128,128,128);
2001-04-21 00:20:58 +02:00
gte_rtpt_b();
T0=*(u32*)&TList->uv0; // Get UV0 & TPage
T1=*(u32*)&TList->uv1; // Get UV1 & Clut
T2=*(u16*)&TList->uv2; // Get UV2
*(u32*)&TPrimPtr->u0=T0; // Set UV0
*(u32*)&TPrimPtr->u1=T1; // Set UV1
*(u16*)&TPrimPtr->u2=T2; // Set UV2
2001-05-02 00:28:01 +02:00
2001-05-05 01:08:57 +02:00
if (TList->OTOfs>ActorOT)
{
ThisOT=OtPtr+(ActorOT+1);
}
else
{
ThisOT=OtPtr+(ActorOT-1);
}
// ThisOT=OtPtr+TList->OTOfs;
2001-04-21 00:20:58 +02:00
TList++;
gte_nclip_b();
gte_stsxy3_ft3(TPrimPtr);
gte_stopz(&ClipZ);
if (ClipZ<=0)
{
addPrim(ThisOT,TPrimPtr);
TPrimPtr++;
}
}
SetPrimPtr((u8*)TPrimPtr);
}