summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/collision/TempColModels.cpp2
-rw-r--r--src/core/Game.cpp250
-rw-r--r--src/core/World.cpp38
-rw-r--r--src/core/config.h10
-rw-r--r--src/modelinfo/BaseModelInfo.h4
-rw-r--r--src/modelinfo/SimpleModelInfo.h12
-rw-r--r--src/vehicles/Heli.cpp9
7 files changed, 295 insertions, 30 deletions
diff --git a/src/collision/TempColModels.cpp b/src/collision/TempColModels.cpp
index 849eb01e..dabb6ebb 100644
--- a/src/collision/TempColModels.cpp
+++ b/src/collision/TempColModels.cpp
@@ -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;
diff --git a/src/core/Game.cpp b/src/core/Game.cpp
index 586b1469..43e2248f 100644
--- a/src/core/Game.cpp
+++ b/src/core/Game.cpp
@@ -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;
}
diff --git a/src/core/World.cpp b/src/core/World.cpp
index 844a4fb7..0bc564ff 100644
--- a/src/core/World.cpp
+++ b/src/core/World.cpp
@@ -922,24 +922,24 @@ CEntity *
CWorld::TestSphereAgainstSectorList(CPtrList &list, CVector spherePos, float radius, CEntity *entityToIgnore,
bool ignoreSomeObjects)
{
- static CColModel sphereCol;
-
- 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;
+ static CColModel OurColModel;
+
+ 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 ||
diff --git a/src/core/config.h b/src/core/config.h
index 4e71224f..ad0df2da 100644
--- a/src/core/config.h
+++ b/src/core/config.h
@@ -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
diff --git a/src/modelinfo/BaseModelInfo.h b/src/modelinfo/BaseModelInfo.h
index 2505967b..4c274aaf 100644
--- a/src/modelinfo/BaseModelInfo.h
+++ b/src/modelinfo/BaseModelInfo.h
@@ -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);
diff --git a/src/modelinfo/SimpleModelInfo.h b/src/modelinfo/SimpleModelInfo.h
index ee63f24b..94e55a2f 100644
--- a/src/modelinfo/SimpleModelInfo.h
+++ b/src/modelinfo/SimpleModelInfo.h
@@ -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
diff --git a/src/vehicles/Heli.cpp b/src/vehicles/Heli.cpp
index a8705524..7008818b 100644
--- a/src/vehicles/Heli.cpp
+++ b/src/vehicles/Heli.cpp
@@ -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