507 lines
12 KiB
C++
507 lines
12 KiB
C++
/******************/
|
|
/*** Actor Bank ***/
|
|
/******************/
|
|
|
|
#include "system\global.h"
|
|
#include "mem\memory.h"
|
|
#include "fileio\fileio.h"
|
|
#include "utils\utils.h"
|
|
#include "utils\pak.h"
|
|
#include "gfx\prim.h"
|
|
#include "gfx\actor.h"
|
|
|
|
#include <dstructs.h>
|
|
|
|
/*****************************************************************************/
|
|
int ShadowXOfs=32;
|
|
int ShadowYOfs=32;
|
|
|
|
/*****************************************************************************/
|
|
|
|
CActorPool::ACTOR_TYPE CActorPool::actorType[39] =
|
|
{
|
|
ACTOR_PLAYER, //SpongeBob=0
|
|
ACTOR_FRIEND_NPC, //BarnacleBoy=1
|
|
ACTOR_FRIEND_NPC, //Gary=2
|
|
ACTOR_FRIEND_NPC, //Krusty=3
|
|
ACTOR_FRIEND_NPC, //MermaidMan=4
|
|
ACTOR_FRIEND_NPC, //Patrick=5
|
|
ACTOR_FRIEND_NPC, //Sandy=6
|
|
ACTOR_FRIEND_NPC, //Squidward=7
|
|
ACTOR_FRIEND_NPC, //Plankton=8
|
|
ACTOR_UNKNOWN,
|
|
ACTOR_ENEMY_NPC, //SmallJellyfish-Level1=10
|
|
ACTOR_ENEMY_NPC, //SmallJellyfish-Level2=11
|
|
ACTOR_ENEMY_NPC, //Motherjellyfish=12
|
|
ACTOR_ENEMY_NPC, //Anenome-Level1=13
|
|
ACTOR_ENEMY_NPC, //SpikeyAnenome=14
|
|
ACTOR_ENEMY_NPC, //Anenome-Level3=15
|
|
ACTOR_ENEMY_NPC, //BabyOctopus=16
|
|
ACTOR_ENEMY_NPC, //Ballblob=17
|
|
ACTOR_ENEMY_NPC, //Boogermonster=18
|
|
ACTOR_ENEMY_NPC, //Caterpillar=19
|
|
ACTOR_ENEMY_NPC, //Clam-Level1=20
|
|
ACTOR_ENEMY_NPC, //Clam-Level2=21
|
|
ACTOR_ENEMY_NPC, //Eyeball=22
|
|
ACTOR_ENEMY_NPC, //Flamingskull=23
|
|
ACTOR_ENEMY_NPC, //FlyingDutchman=24
|
|
ACTOR_ENEMY_NPC, //Ghost=25
|
|
ACTOR_ENEMY_NPC, //GiantWorm=26
|
|
ACTOR_ENEMY_NPC, //HermitCrab=27
|
|
ACTOR_ENEMY_NPC, //IronDogFish=28
|
|
ACTOR_ENEMY_NPC, //PuffaFish=29
|
|
ACTOR_ENEMY_NPC, //SeaSnake=30
|
|
ACTOR_ENEMY_NPC, //Sharkman=31
|
|
ACTOR_ENEMY_NPC, //SharkSub=32
|
|
ACTOR_ENEMY_NPC, //Skeletalfish=33
|
|
ACTOR_ENEMY_NPC, //SpiderCrab=34
|
|
ACTOR_ENEMY_NPC, //Squiddart=35
|
|
ACTOR_ENEMY_NPC, //Stomper=36
|
|
ACTOR_ENEMY_NPC, //DustDevil=37
|
|
ACTOR_ENEMY_NPC, //SiderCrabSpawner=38
|
|
};
|
|
|
|
/*****************************************************************************/
|
|
sActorPool CActorPool::ActorPool[MAX_ACTORS];
|
|
|
|
CSlotCache CActorGfx::SlotCache;
|
|
u8 CActorGfx::UnpackBuffer[CActorPool::MAX_ACTOR_SIZE];
|
|
|
|
/*****************************************************************************/
|
|
/*** Slot Cache **************************************************************/
|
|
/*****************************************************************************/
|
|
void CSlotCache::Init()
|
|
{
|
|
for (int Y=0; Y<DYN_SLOTH; Y++)
|
|
{
|
|
for (int X=0; X<DYN_SLOTW; X++)
|
|
{
|
|
Cache[X][Y].W=0;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
bool CSlotCache::FindSlot(int SprW,int SprH,u16 &TexX,u16 &TexY,u8 &u,u8 &v)
|
|
{
|
|
int W=(SprW+(DYN_W-1))/DYN_W;
|
|
int H=(SprH+(DYN_H-1))/DYN_H;
|
|
|
|
for (int Y=0; Y<DYN_SLOTH; Y++)
|
|
{
|
|
for (int X=0; X<DYN_SLOTW; X++)
|
|
{
|
|
if (TakeSlot(X,Y,W,H))
|
|
{
|
|
printf("TakeSlot %i %i\n",X,Y);
|
|
TexX=DYN_SLOTX+(X*DYN_W/4);
|
|
TexY=DYN_SLOTY+(Y*DYN_H);
|
|
u=(X&3)*64;
|
|
v=(Y&3)*64;
|
|
return(true);
|
|
}
|
|
|
|
}
|
|
}
|
|
return(false);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
bool CSlotCache::TakeSlot(int SX,int SY,int SW,int SH)
|
|
{
|
|
int W,H;
|
|
if (SX+SW>DYN_SLOTW) return(false);
|
|
if (SY+SH>DYN_SLOTH) return(false);
|
|
if ((SX&3)==3 && SW>1) return(false);
|
|
|
|
for (H=0; H<SH; H++)
|
|
{
|
|
for (W=0; W<SW; W++)
|
|
{
|
|
if (Cache[SX+W][SY+H].W) return(false);
|
|
}
|
|
}
|
|
// Slot good
|
|
for (H=0; H<SH; H++)
|
|
{
|
|
for (W=0; W<SW; W++)
|
|
{
|
|
Cache[SX+W][SY+H].W=SW;
|
|
Cache[SX+W][SY+H].H=SH;
|
|
}
|
|
}
|
|
|
|
return(true);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/*****************************************************************************/
|
|
/*****************************************************************************/
|
|
void CActorPool::Init()
|
|
{
|
|
int i;
|
|
for (i=0; i<MAX_ACTORS; i++)
|
|
{
|
|
ActorPool[i].SpriteBank=0;
|
|
}
|
|
CActorGfx::ResetCache();
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
int CActorPool::FindActorInPool(FileEquate Filename)
|
|
{
|
|
for (int i=0; i<MAX_ACTORS; i++)
|
|
{
|
|
if (ActorPool[i].SpriteBank && ActorPool[i].Filename==Filename) return(i);
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
int CActorPool::FindFreeActor()
|
|
{
|
|
for (int i=0; i<MAX_ACTORS; i++)
|
|
{
|
|
if (ActorPool[i].SpriteBank==0) return(i);
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
int CActorPool::LoadActor(FileEquate Filename)
|
|
{
|
|
int i;
|
|
|
|
sSpriteAnimBank *Spr=(sSpriteAnimBank*)CFileIO::loadFile(Filename);
|
|
|
|
Spr->AnimList=(sSpriteAnim*) MakePtr(Spr,(int)Spr->AnimList);
|
|
Spr->FrameList=(sSpriteFrame*) MakePtr(Spr,(int)Spr->FrameList);
|
|
Spr->Palette=(u8*) MakePtr(Spr,(int)Spr->Palette);
|
|
|
|
// FixUp AnimList
|
|
DAVE_DBGMSG("Anims %i\n",Spr->AnimCount);
|
|
for (i=0; i<Spr->AnimCount; i++)
|
|
{
|
|
sSpriteAnim *ThisAnim=&Spr->AnimList[i];
|
|
ThisAnim->Anim=(u16*) MakePtr(Spr,(int)ThisAnim->Anim);
|
|
}
|
|
// FixUp FrameList
|
|
DAVE_DBGMSG("Anims %i\n",Spr->FrameCount);
|
|
for (i=0; i<Spr->FrameCount; i++)
|
|
{
|
|
sSpriteFrame *ThisFrame=&Spr->FrameList[i];
|
|
ThisFrame->PAKSpr=(u8*) MakePtr(Spr,(int)ThisFrame->PAKSpr);
|
|
}
|
|
|
|
// Store it
|
|
int Idx=FindFreeActor();
|
|
ASSERT(Idx!=-1);
|
|
|
|
sActorPool &ThisActor=ActorPool[Idx];
|
|
|
|
ThisActor.Filename=Filename;
|
|
ThisActor.SpriteBank=Spr;
|
|
ThisActor.RefCount=1;
|
|
ThisActor.Clut=LoadPalette(ThisActor,Idx);
|
|
|
|
return(Idx);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
#define DYN_PALW 64
|
|
#define DYN_PALH 1
|
|
#define DYN_PALX 512
|
|
#define DYN_PALY 511
|
|
|
|
u16 CActorPool::LoadPalette(sActorPool &ThisActor,int Idx)
|
|
{
|
|
RECT R;
|
|
int X=Idx&31;
|
|
int Y=Idx%31;
|
|
|
|
R.x=DYN_PALX+(Idx*DYN_PALW);
|
|
R.y=DYN_PALY-Y;
|
|
R.w=DYN_PALW;
|
|
R.h=DYN_PALH;
|
|
// DrawSync(0);
|
|
LoadImage( &R, (u32*)ThisActor.SpriteBank->Palette);
|
|
|
|
int Clut=getClut(R.x,R.y);
|
|
return(Clut);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
CActorGfx *CActorPool::GetActor(FileEquate Filename)
|
|
{
|
|
CActorGfx *Actor;
|
|
int Idx;
|
|
|
|
// Find Actor in Pool
|
|
Idx=FindActorInPool(Filename);
|
|
if (Idx==-1)
|
|
{
|
|
Idx=LoadActor(Filename);
|
|
}
|
|
|
|
sActorPool &ThisActor=ActorPool[Idx];
|
|
Actor=new ("CActorGfx") CActorGfx;
|
|
Actor->SetData(Filename,ThisActor.SpriteBank,ThisActor.Clut);
|
|
ThisActor.RefCount++;
|
|
return(Actor);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/*** Dump ********************************************************************/
|
|
/*****************************************************************************/
|
|
// Dumps all apart from spongeybob
|
|
void CActorPool::DumpActors()
|
|
{
|
|
printf("DumpActors\n");
|
|
for (int i=0; i<MAX_ACTORS; i++)
|
|
{
|
|
if (ActorPool[i].SpriteBank && ActorPool[i].Filename!=ACTORS_SPONGEBOB_SBK)
|
|
{
|
|
if (ActorPool[i].SpriteBank) MemFree(ActorPool[i].SpriteBank);
|
|
ActorPool[i].SpriteBank=0;
|
|
}
|
|
}
|
|
printf("DumpActorsDone\n");
|
|
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/*****************************************************************************/
|
|
/*****************************************************************************/
|
|
/*****************************************************************************/
|
|
/*****************************************************************************/
|
|
/*****************************************************************************/
|
|
CActorGfx::CActorGfx()
|
|
{
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
CActorGfx::~CActorGfx()
|
|
{
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
void CActorGfx::SetData(FileEquate Filename,sSpriteAnimBank *_SpriteBank,u16 _Clut)
|
|
{
|
|
SpriteBank=_SpriteBank;
|
|
Clut=_Clut;
|
|
|
|
if (Filename!=ACTORS_SPONGEBOB_SBK)
|
|
{
|
|
bool SlotStatus=SlotCache.FindSlot(_SpriteBank->MaxW,_SpriteBank->MaxH,TexX,TexY,U,V);
|
|
ASSERT(SlotStatus);
|
|
}
|
|
else
|
|
{
|
|
TexX=512;
|
|
TexY=256;
|
|
U=0;
|
|
V=0;
|
|
}
|
|
TPage=getTPage(0,0,TexX,TexY);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
void CActorGfx::ResetCache()
|
|
{
|
|
RECT R;
|
|
SlotCache.Init();
|
|
R.x=512;
|
|
R.y=256;
|
|
R.w=512;
|
|
R.h=250;
|
|
ClearImage(&R,0,255,0);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
sSpriteFrame *CActorGfx::GetFrame(int Anim,int Frame)
|
|
{
|
|
sSpriteAnim *ThisAnim=SpriteBank->AnimList+Anim;
|
|
u16 ThisFrame=ThisAnim->Anim[Frame];
|
|
|
|
return(SpriteBank->FrameList+ThisFrame);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
int ActorOT=10;
|
|
POLY_FT4 *CActorGfx::Render(DVECTOR &Pos,int Anim,int Frame,bool XFlip,bool YFlip,bool Shadow)
|
|
{
|
|
sSpriteFrame *FrameGfx=GetFrame(Anim,Frame);
|
|
|
|
PAK_doUnpak(UnpackBuffer,FrameGfx->PAKSpr);
|
|
// Gfx
|
|
|
|
RECT Rect;
|
|
Rect.x=TexX;
|
|
Rect.y=TexY;
|
|
Rect.w=FrameGfx->W/4;
|
|
Rect.h=FrameGfx->H;
|
|
|
|
LoadImage( &Rect, (u32*)UnpackBuffer);
|
|
|
|
POLY_FT4 *Ft4=GetPrimFT4();
|
|
SetUpFT4(Ft4,FrameGfx,Pos.vx,Pos.vy,XFlip,YFlip);
|
|
setRGB0(Ft4,128,128,128);
|
|
Ft4->tpage=TPage;
|
|
Ft4->clut=Clut;
|
|
AddPrimToList(Ft4,ActorOT);
|
|
|
|
if (Shadow)
|
|
{
|
|
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);
|
|
AddPrimToList(sFt4,ActorOT);
|
|
}
|
|
|
|
return(Ft4);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
void CActorGfx::SetUpFT4(POLY_FT4 *Ft4,sSpriteFrame *Frame,int X,int Y,bool XFlip,bool YFlip)
|
|
{
|
|
u8 W=Frame->W;
|
|
u8 H=Frame->H;
|
|
|
|
if (XFlip)
|
|
{
|
|
X-=Frame->XOfs;
|
|
X-=W;
|
|
Ft4->u0=U+W-1;
|
|
Ft4->u1=U;//-1;
|
|
Ft4->u2=U+W-1;
|
|
Ft4->u3=U;//-1;
|
|
|
|
}
|
|
else
|
|
{
|
|
X+=Frame->XOfs;
|
|
Ft4->u0=U;
|
|
Ft4->u1=U+W;
|
|
Ft4->u2=U;
|
|
Ft4->u3=U+W;
|
|
|
|
}
|
|
|
|
if (YFlip)
|
|
{
|
|
Y-=Frame->YOfs;
|
|
Y-=H;
|
|
Ft4->v0=V+H-1;
|
|
Ft4->v1=V+H-1;
|
|
Ft4->v2=V;//-1;
|
|
Ft4->v3=V;//-1;
|
|
}
|
|
else
|
|
{
|
|
Y+=Frame->YOfs;
|
|
Ft4->v0=V;
|
|
Ft4->v1=V;
|
|
Ft4->v2=V+H;
|
|
Ft4->v3=V+H;
|
|
}
|
|
|
|
setXYWH(Ft4,X,Y,W,H);
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
/*****************************************************************************/
|
|
/*****************************************************************************/
|
|
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;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
void CModelGfx::SetModel(int Type)
|
|
{
|
|
Model=&CModelGfx::ModelTable[Type];
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
int DX=1;
|
|
int DY=1;
|
|
int PXOfs=-16;
|
|
int PYOfs=-6;
|
|
void CModelGfx::Render(DVECTOR &Pos)
|
|
{
|
|
#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];
|
|
|
|
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);
|
|
|
|
CMX_SetTransMtxXY(&RenderPos);
|
|
|
|
while (TriCount--)
|
|
{
|
|
P0=&ModelVtxList[TList->P0]; P1=&ModelVtxList[TList->P1]; P2=&ModelVtxList[TList->P2];
|
|
gte_ldv3(P0,P1,P2);
|
|
setPolyFT3(TPrimPtr);
|
|
setShadeTex(TPrimPtr,1);
|
|
setlen(TPrimPtr, GPU_PolyFT3Tag);
|
|
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
|
|
if (TList->OTOfs>MAX_OT-1) TList->OTOfs=MAX_OT-1;
|
|
ThisOT=OtPtr+TList->OTOfs;
|
|
|
|
TList++;
|
|
gte_nclip_b();
|
|
gte_stsxy3_ft3(TPrimPtr);
|
|
// if (TriCount==1)
|
|
// {
|
|
// printf("%i,%i\n",TPrimPtr->x0,TPrimPtr->y0);
|
|
//
|
|
// }
|
|
|
|
gte_stopz(&ClipZ);
|
|
if (ClipZ<=0)
|
|
{
|
|
addPrim(ThisOT,TPrimPtr);
|
|
TPrimPtr++;
|
|
}
|
|
}
|
|
|
|
SetPrimPtr((u8*)TPrimPtr);
|
|
}
|