more PS2 stuff; memory movement done

This commit is contained in:
aap 2020-12-03 16:04:59 +01:00
parent 3c24505990
commit 13cefd3293
7 changed files with 294 additions and 29 deletions

View file

@ -40,7 +40,7 @@ CTempColModels::Initialise(void)
colmodel.numSpheres = ARRAY_SIZE(sphrs);\
colmodel.spheres = sphrs;\
colmodel.level = LEVEL_GENERIC;\
colmodel.ownsCollisionVolumes = false;\
colmodel.ownsCollisionVolumes = false;
int i;

View file

@ -1032,17 +1032,261 @@ void CGame::Process(void)
int32 gNumMemMoved;
bool
MoveMem(void **ptr)
{
if(*ptr){
gNumMemMoved++;
void *newPtr = gMainHeap.MoveMemory(*ptr);
if(*ptr != newPtr){
*ptr = newPtr;
return true;
}
}
return false;
}
typedef struct _SkyRasterExt _SkyRasterExt;
struct _SkyRasterExt
{
RwInt32 dmaRefCount; /**< Internal use */
RwInt32 dmaClrCount; /**< Internal use */
/* General texture setup register */
RwUInt32 lsb; /**< Internal use */
RwUInt32 msb; /**< Internal use */
RwUInt32 palOffset; /**< Internal use */
/* K: a 12 bit 8.4 value in bottom bits */
/* L: a 2 bit value in 12,13 */
RwUInt16 mipmapKL; /**< Internal use */
/* NOTE: This is left shifted two */
RwUInt8 maxMipLevel; /**< Internal use */
/* Is this texture to stay in the cache? */
RwUInt8 bLocked; /**< Internal use */
/* Mipmap addresses */
RwUInt32 miptbp1Lsb; /**< Internal use */
RwUInt32 miptbp1Msb; /**< Internal use */
RwUInt32 miptbp2Lsb; /**< Internal use */
RwUInt32 miptbp2Msb; /**< Internal use */
/* Size in bytes in system memory for pixels */
RwUInt32 sysMemSize; /**< Internal use */
/* Size in bytes in system memory for palette */
RwUInt32 sysMemPalSize; /**< Internal use */
/* Size in words in video memory for pixels + palette */
RwUInt32 nTexCacheSize; /**< Internal use */
/* Should we cache packets for this raster */
RwUInt8 cachePkts; /**< Internal use */
RwUInt8 lockedMipLevel; /**< Currently locked mip level */
RwUInt8 flags; /**< Bit 0 new format texture */
/**< Bit 1 twiddled (->32) */
/**< Bit 2 twiddled (->16) */
RwUInt8 pad[1]; /**< Internal use */
#if defined(GSB) && defined(GSPLUS)
RwUInt32 lsb3; /**< Internal use */
RwUInt32 msb3; /**< Internal use */
RwUInt32 miptbp3Lsb, miptbp3Msb; /**< Internal use */
RwUInt32 miptbp4Lsb, miptbp4Msb; /**< Internal use */
#endif /* defined(GSB) && defined(GSPLUS) */
};
uint32 skyRasterExt;
#define RASTEREXTFROMRASTER(raster) \
((_SkyRasterExt *)(((RwUInt8 *)(raster)) + skyRasterExt))
// Some convenience structs
struct SkyDataPrefix
{
uint32 pktSize1;
uint32 data; // pointer to data as read from TXD
uint32 pktSize2;
uint32 unused;
};
struct DMAGIFUpload
{
uint32 tag1_qwc, tag1_addr; // dmaref
uint32 nop1, vif_direct1;
uint32 giftag[4];
uint32 gs_bitbltbuf[4];
uint32 tag2_qwc, tag2_addr; // dmaref
uint32 nop2, vif_direct2;
};
// This is very scary. it depends on the exact memory layout of the DMA chains and whatnot
RwTexture *
MoveTextureMemoryCB(RwTexture *texture, void *pData)
{
// TODO
#ifdef GTA_PS2
bool *pRet = (bool*)pData;
RwRaster *raster = RwTextureGetRaster(texture);
_SkyRasterExt *rasterExt = RASTEREXTFROMRASTER(raster);
if(raster->originalPixels == nil || // the raw data
raster->cpPixels == raster->originalPixels || // old format, can't handle it
rasterExt->dmaRefCount != 0 && rasterExt->dmaClrCount != 0)
return texture;
// this is the allocated pointer we will move
SkyDataPrefix *prefix = (SkyDataPrefix*)raster->originalPixels;
DMAGIFUpload *uploads = (DMAGIFUpload*)(prefix+1);
// We have 4qw for each upload,
// i.e. for each buffer width of mip levels,
// and the palette if there is one.
// NB: this code does NOT support mipmaps!
// so we assume two uploads (pixels and palette)
//
// each upload looks like this:
// (DMAcnt; NOP; VIF DIRECT(2))
// giftag (1, A+D)
// GS_BITBLTBUF
// (DMAref->pixel data; NOP; VIF DIRECT(5))
// the DMArefs are what we have to adjust
uintptr dataDiff, upload1Diff, upload2Diff, pixelDiff, paletteDiff;
dataDiff = prefix->data - (uintptr)raster->originalPixels;
upload1Diff = uploads[0].tag2_addr - (uintptr)raster->originalPixels;
if(raster->palette)
upload2Diff = uploads[1].tag2_addr - (uintptr)raster->originalPixels;
pixelDiff = (uintptr)raster->cpPixels - (uintptr)raster->originalPixels;
if(raster->palette)
paletteDiff = (uintptr)raster->palette - (uintptr)raster->originalPixels;
uint8 *newptr = (uint8*)gMainHeap.MoveMemory(raster->originalPixels);
if(newptr != raster->originalPixels){
// adjust everything
prefix->data = (uintptr)newptr + dataDiff;
uploads[0].tag2_addr = (uintptr)newptr + upload1Diff;
if(raster->palette)
uploads[1].tag2_addr = (uintptr)newptr + upload2Diff;
raster->originalPixels = newptr;
raster->cpPixels = newptr + pixelDiff;
if(raster->palette)
raster->palette = newptr + paletteDiff;
if(pRet){
*pRet = true;
return nil;
}
}
#else
// nothing to do here really, everything should be in videomemory
#endif
return texture;
}
bool
TidyUpModelInfo(CBaseModelInfo *,bool)
MoveAtomicMemory(RpAtomic *atomic, bool onlyOne)
{
// TODO
RpGeometry *geo = RpAtomicGetGeometry(atomic);
#if THIS_IS_COMPATIBLE_WITH_GTA3_RW31
if(MoveMem((void**)&geo->triangles) && onlyOne)
return true;
if(MoveMem((void**)&geo->matList.materials) && onlyOne)
return true;
if(MoveMem((void**)&geo->preLitLum) && onlyOne)
return true;
if(MoveMem((void**)&geo->texCoords[0]) && onlyOne)
return true;
if(MoveMem((void**)&geo->texCoords[1]) && onlyOne)
return true;
// verts and normals of morph target are allocated together
int vertDiff;
if(geo->morphTarget->normals)
vertDiff = geo->morphTarget->normals - geo->morphTarget->verts;
if(MoveMem((void**)&geo->morphTarget->verts)){
if(geo->morphTarget->normals)
geo->morphTarget->normals = geo->morphTarget->verts + vertDiff;
if(onlyOne)
return true;
}
RpMeshHeader *oldmesh = geo->mesh;
if(MoveMem((void**)&geo->mesh)){
// index pointers are allocated together with meshes,
// have to relocate those too
RpMesh *mesh = (RpMesh*)(geo->mesh+1);
uintptr reloc = (uintptr)geo->mesh - (uintptr)oldmesh;
for(int i = 0; i < geo->mesh->numMeshes; i++)
mesh[i].indices = (RxVertexIndex*)((uintptr)mesh[i].indices + reloc);
if(onlyOne)
return true;
}
#else
// we could do something in librw here
#endif
return false;
}
bool
MoveColModelMemory(CColModel &colModel, bool onlyOne)
{
#if GTA_VERSION >= GTA3_PS2_160
// hm...should probably only do this if ownsCollisionVolumes
// but it doesn't exist on PS2...
if(!colModel.ownsCollisionVolumes)
return false;
#endif
if(MoveMem((void**)&colModel.spheres) && onlyOne)
return true;
if(MoveMem((void**)&colModel.lines) && onlyOne)
return true;
if(MoveMem((void**)&colModel.boxes) && onlyOne)
return true;
if(MoveMem((void**)&colModel.vertices) && onlyOne)
return true;
if(MoveMem((void**)&colModel.triangles) && onlyOne)
return true;
if(MoveMem((void**)&colModel.trianglePlanes) && onlyOne)
return true;
return false;
}
RpAtomic*
MoveAtomicMemoryCB(RpAtomic *atomic, void *pData)
{
bool *pRet = (bool*)pData;
if(pRet == nil)
MoveAtomicMemory(atomic, false);
else if(MoveAtomicMemory(atomic, true)){
*pRet = true;
return nil;
}
return atomic;
}
bool
TidyUpModelInfo(CBaseModelInfo *modelInfo, bool onlyone)
{
if(modelInfo->GetColModel() && modelInfo->DoesOwnColModel())
if(MoveColModelMemory(*modelInfo->GetColModel(), onlyone))
return true;
RwObject *rwobj = modelInfo->GetRwObject();
if(RwObjectGetType(rwobj) == rpATOMIC)
if(MoveAtomicMemory((RpAtomic*)rwobj, onlyone))
return true;
if(RwObjectGetType(rwobj) == rpCLUMP){
bool ret = false;
if(onlyone)
RpClumpForAllAtomics((RpClump*)rwobj, MoveAtomicMemoryCB, &ret);
else
RpClumpForAllAtomics((RpClump*)rwobj, MoveAtomicMemoryCB, nil);
if(ret)
return true;
}
if(modelInfo->GetModelType() == MITYPE_PED && ((CPedModelInfo*)modelInfo)->m_hitColModel)
if(MoveColModelMemory(*((CPedModelInfo*)modelInfo)->m_hitColModel, onlyone))
return true;
return false;
}

View file

@ -922,24 +922,24 @@ CEntity *
CWorld::TestSphereAgainstSectorList(CPtrList &list, CVector spherePos, float radius, CEntity *entityToIgnore,
bool ignoreSomeObjects)
{
static CColModel sphereCol;
static CColModel OurColModel;
sphereCol.boundingSphere.center.x = 0.0f;
sphereCol.boundingSphere.center.y = 0.0f;
sphereCol.boundingSphere.center.z = 0.0f;
sphereCol.boundingSphere.radius = radius;
sphereCol.boundingBox.min.x = -radius;
sphereCol.boundingBox.min.y = -radius;
sphereCol.boundingBox.min.z = -radius;
sphereCol.boundingBox.max.x = radius;
sphereCol.boundingBox.max.y = radius;
sphereCol.boundingBox.max.z = radius;
sphereCol.numSpheres = 1;
sphereCol.spheres = &sphereCol.boundingSphere;
sphereCol.numLines = 0;
sphereCol.numBoxes = 0;
sphereCol.numTriangles = 0;
sphereCol.ownsCollisionVolumes = false;
OurColModel.boundingSphere.center.x = 0.0f;
OurColModel.boundingSphere.center.y = 0.0f;
OurColModel.boundingSphere.center.z = 0.0f;
OurColModel.boundingSphere.radius = radius;
OurColModel.boundingBox.min.x = -radius;
OurColModel.boundingBox.min.y = -radius;
OurColModel.boundingBox.min.z = -radius;
OurColModel.boundingBox.max.x = radius;
OurColModel.boundingBox.max.y = radius;
OurColModel.boundingBox.max.z = radius;
OurColModel.numSpheres = 1;
OurColModel.spheres = &OurColModel.boundingSphere;
OurColModel.numLines = 0;
OurColModel.numBoxes = 0;
OurColModel.numTriangles = 0;
OurColModel.ownsCollisionVolumes = false;
CMatrix sphereMat;
sphereMat.SetTranslate(spherePos);
@ -962,7 +962,7 @@ CWorld::TestSphereAgainstSectorList(CPtrList &list, CVector spherePos, float rad
if(e->GetBoundRadius() + radius > distance) {
CColModel *eCol = CModelInfo::GetModelInfo(e->GetModelIndex())->GetColModel();
int collidedSpheres =
CCollision::ProcessColModels(sphereMat, sphereCol, e->GetMatrix(), *eCol,
CCollision::ProcessColModels(sphereMat, OurColModel, e->GetMatrix(), *eCol,
gaTempSphereColPoints, nil, nil);
if(collidedSpheres != 0 ||

View file

@ -1,27 +1,27 @@
#pragma once
enum Config {
NUMPLAYERS = 1,
NUMPLAYERS = 1, // 4 on PS2
NUMCDIMAGES = 12, // gta3.img duplicates (not used on PC)
MAX_CDIMAGES = 8, // additional cdimages
MAX_CDCHANNELS = 5,
MODELINFOSIZE = 5500,
MODELINFOSIZE = 5500, // 3150 on PS2
// TXDSTORESIZE = 850,
TXDSTORESIZE = 1024, // for Xbox map
EXTRADIRSIZE = 128,
CUTSCENEDIRSIZE = 512,
SIMPLEMODELSIZE = 5000,
SIMPLEMODELSIZE = 5000, // 2910 on PS2
MLOMODELSIZE = 1,
MLOINSTANCESIZE = 1,
TIMEMODELSIZE = 30,
CLUMPMODELSIZE = 5,
PEDMODELSIZE = 90,
VEHICLEMODELSIZE = 120,
VEHICLEMODELSIZE = 120, // 70 on PS2
XTRACOMPSMODELSIZE = 2,
TWODFXSIZE = 2000,
TWODFXSIZE = 2000, // 1210 on PS2
MAXVEHICLESLOADED = 50, // 70 on mobile

View file

@ -63,9 +63,9 @@ public:
bool DoesOwnColModel(void) { return m_bOwnsColModel; }
void DeleteCollisionModel(void);
void ClearTexDictionary(void) { m_txdSlot = -1; }
short GetObjectID(void) { return m_objectId; }
int16 GetObjectID(void) { return m_objectId; }
void SetObjectID(int16 id) { m_objectId = id; }
short GetTxdSlot(void) { return m_txdSlot; }
int16 GetTxdSlot(void) { return m_txdSlot; }
void AddRef(void);
void RemoveRef(void);
void SetTexDictionary(const char *name);

View file

@ -11,6 +11,18 @@ public:
float m_lodDistances[3];
uint8 m_numAtomics;
uint8 m_alpha;
/* // For reference, PS2 has:
uint8 m_firstDamaged;
uint8 m_normalCull : 1;
uint8 m_isDamaged : 1;
uint8 m_isBigBuilding : 1;
uint8 m_noFade : 1;
uint8 m_drawLast : 1;
uint8 m_additive : 1;
uint8 m_isSubway : 1;
uint8 m_ignoreLight : 1;
// m_noZwrite is missing because not needed
*/
uint16 m_firstDamaged : 2; // 0: no damage model
// 1: 1 and 2 are damage models
// 2: 2 is damage model

View file

@ -778,8 +778,10 @@ CHeli::InitHelis(void)
for(i = 0; i < NUM_HELIS; i++)
pHelis[i] = nil;
#if GTA_VERSION >= GTA3_PS2_160
((CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_ESCAPE))->SetColModel(&CTempColModels::ms_colModelPed1);
((CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_CHOPPER))->SetColModel(&CTempColModels::ms_colModelPed1);
#endif
}
CHeli*
@ -789,6 +791,13 @@ GenerateHeli(bool catalina)
CVector heliPos;
int i;
#if GTA_VERSION < GTA3_PS2_160
if(catalina)
((CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_ESCAPE))->SetColModel(&CTempColModels::ms_colModelPed1);
else
((CVehicleModelInfo*)CModelInfo::GetModelInfo(MI_CHOPPER))->SetColModel(&CTempColModels::ms_colModelPed1);
#endif
if(catalina)
heli = new CHeli(MI_ESCAPE, PERMANENT_VEHICLE);
else