diff --git a/premake5.lua b/premake5.lua index a90e6837..68a08a1a 100644 --- a/premake5.lua +++ b/premake5.lua @@ -66,4 +66,8 @@ project "re3" defines { "NDEBUG" } optimize "On" staticruntime "on" + filter "configurations:DebugCI" + defines { "DEBUG" } + staticruntime "on" + symbols "On" diff --git a/src/FileMgr.cpp b/src/FileMgr.cpp index 02c797ba..d4e0b89b 100644 --- a/src/FileMgr.cpp +++ b/src/FileMgr.cpp @@ -163,8 +163,8 @@ myfseek(int fd, long offset, int whence) static int myfeof(int fd) { -// return feof(myfiles[fd].file); - return ferror(myfiles[fd].file); + return feof(myfiles[fd].file); +// return ferror(myfiles[fd].file); } diff --git a/src/RwClumpRead.cpp b/src/RwClumpRead.cpp new file mode 100644 index 00000000..c9f027e7 --- /dev/null +++ b/src/RwClumpRead.cpp @@ -0,0 +1,230 @@ +#include "common.h" +#include "patcher.h" + +struct rpGeometryList +{ + RpGeometry **geometries; + int32 numGeoms; +}; + +struct rpAtomicBinary +{ + RwInt32 frameIndex; + RwInt32 geomIndex; + RwInt32 flags; + RwInt32 unused; +}; + +static int32 numberGeometrys; +static int32 streamPosition; +static rpGeometryList gGeomList; +static rwFrameList gFrameList; +static RpClumpChunkInfo gClumpInfo; + +rpGeometryList* +GeometryListStreamRead1(RwStream *stream, rpGeometryList *geomlist) +{ + int i; + RwUInt32 size, version; + RwInt32 numGeoms; + + numberGeometrys = 0; + if(!RwStreamFindChunk(stream, rwID_STRUCT, &size, &version)) + return nil; + assert(size == 4); + if(RwStreamRead(stream, &numGeoms, 4) != 4) + return nil; + + numberGeometrys = numGeoms/2; + geomlist->numGeoms = numGeoms; + if(geomlist->numGeoms > 0){ + geomlist->geometries = (RpGeometry**)RwMalloc(geomlist->numGeoms * sizeof(RpGeometry*)); + if(geomlist->geometries == nil) + return nil; + memset(geomlist->geometries, 0, geomlist->numGeoms * sizeof(RpGeometry*)); + }else + geomlist->geometries = nil; + + for(i = 0; i < numberGeometrys; i++){ + if(!RwStreamFindChunk(stream, rwID_GEOMETRY, nil, &version)) + return nil; + geomlist->geometries[i] = RpGeometryStreamRead(stream); + if(geomlist->geometries[i] == nil) + return nil; + } + + return geomlist; +} + +rpGeometryList* +GeometryListStreamRead2(RwStream *stream, rpGeometryList *geomlist) +{ + int i; + RwUInt32 version; + + for(i = numberGeometrys; i < geomlist->numGeoms; i++){ + if(!RwStreamFindChunk(stream, rwID_GEOMETRY, nil, &version)) + return nil; + geomlist->geometries[i] = RpGeometryStreamRead(stream); + if(geomlist->geometries[i] == nil) + return nil; + } + + return geomlist; +} + +void +GeometryListDeinitialize(rpGeometryList *geomlist) +{ + int i; + + for(i = 0; i < geomlist->numGeoms; i++) + if(geomlist->geometries[i]) + RpGeometryDestroy(geomlist->geometries[i]); + + if(geomlist->numGeoms){ + RwFree(geomlist->geometries); + geomlist->numGeoms = 0; + } +} + +RpAtomic* +ClumpAtomicStreamRead(RwStream *stream, rwFrameList *frmList, rpGeometryList *geomList) +{ + RwUInt32 size, version; + rpAtomicBinary a; + RpAtomic *atomic; + + numberGeometrys = 0; + if(!RwStreamFindChunk(stream, rwID_STRUCT, &size, &version)) + return nil; + assert(size <= sizeof(rpAtomicBinary)); + if(RwStreamRead(stream, &a, size) != size) + return nil; + + atomic = RpAtomicCreate(); + if(atomic == nil) + return nil; + + RpAtomicSetFlags(atomic, a.flags); + + if(frmList->numFrames){ + assert(a.frameIndex < frmList->numFrames); + RpAtomicSetFrame(atomic, frmList->frames[a.frameIndex]); + } + + if(geomList->numGeoms){ + assert(a.geomIndex < geomList->numGeoms); + RpAtomicSetGeometry(atomic, geomList->geometries[a.geomIndex], 0); + }else{ + RpGeometry *geom; + if(!RwStreamFindChunk(stream, rwID_GEOMETRY, nil, &version)){ + RpAtomicDestroy(atomic); + return nil; + } + geom = RpGeometryStreamRead(stream); + if(geom == nil){ + RpAtomicDestroy(atomic); + return nil; + } + RpAtomicSetGeometry(atomic, geom, 0); + RpGeometryDestroy(geom); + } + + return atomic; +} + +bool +RpClumpGtaStreamRead1(RwStream *stream) +{ + RwUInt32 size, version; + + if(!RwStreamFindChunk(stream, rwID_STRUCT, &size, &version)) + return false; + if(version >= 0x33000){ + assert(size == 12); + if(RwStreamRead(stream, &gClumpInfo, 12) != 12) + return false; + }else{ + assert(size == 4); + if(RwStreamRead(stream, &gClumpInfo, 4) != 4) + return false; + } + + if(!RwStreamFindChunk(stream, rwID_FRAMELIST, nil, &version)) + return false; + if(_rwFrameListStreamRead(stream, &gFrameList) == nil) + return false; + + if(!RwStreamFindChunk(stream, rwID_GEOMETRYLIST, nil, &version)){ + rwFrameListDeinitialize(&gFrameList); + return false; + } + if(GeometryListStreamRead1(stream, &gGeomList) == nil){ + rwFrameListDeinitialize(&gFrameList); + return false; + } + streamPosition = stream->Type.memory.position; + return true; +} + +RpClump* +RpClumpGtaStreamRead2(RwStream *stream) +{ + int i; + RwUInt32 version; + RpAtomic *atomic; + RpClump *clump; + + clump = RpClumpCreate(); + if(clump == nil) + return nil; + + RwStreamSkip(stream, streamPosition - stream->Type.memory.position); + + if(GeometryListStreamRead2(stream, &gGeomList) == nil){ + GeometryListDeinitialize(&gGeomList); + rwFrameListDeinitialize(&gFrameList); + RpClumpDestroy(clump); + return nil; + } + + RpClumpSetFrame(clump, gFrameList.frames[0]); + + for(i = 0; i < gClumpInfo.numAtomics; i++){ + if(!RwStreamFindChunk(stream, rwID_ATOMIC, nil, &version)){ + GeometryListDeinitialize(&gGeomList); + rwFrameListDeinitialize(&gFrameList); + RpClumpDestroy(clump); + return nil; + } + + atomic = ClumpAtomicStreamRead(stream, &gFrameList, &gGeomList); + if(atomic == nil){ + GeometryListDeinitialize(&gGeomList); + rwFrameListDeinitialize(&gFrameList); + RpClumpDestroy(clump); + return nil; + } + + RpClumpAddAtomic(clump, atomic); + } + + GeometryListDeinitialize(&gGeomList); + rwFrameListDeinitialize(&gFrameList); + return clump; +} + +void +RpClumpGtaCancelStream(void) +{ + GeometryListDeinitialize(&gGeomList); + rwFrameListDeinitialize(&gFrameList); + gFrameList.numFrames = 0; +} + +STARTPATCHES + InjectHook(0x526060, RpClumpGtaStreamRead1, PATCH_JUMP); + InjectHook(0x526180, RpClumpGtaStreamRead2, PATCH_JUMP); + InjectHook(0x5262D0, RpClumpGtaCancelStream, PATCH_JUMP); +ENDPATCHES diff --git a/src/RwHelper.cpp b/src/RwHelper.cpp index 2ff58393..6a8c7530 100644 --- a/src/RwHelper.cpp +++ b/src/RwHelper.cpp @@ -88,7 +88,7 @@ CameraSize(RwCamera * camera, RwRect * rect, { RwVideoMode videoMode; RwRect r; - RwRect origSize; + RwRect origSize = { 0, 0, 0, 0 }; // FIX just to make the compier happy RwV2d vw; RwEngineGetVideoModeInfo(&videoMode, diff --git a/src/RwHelper.h b/src/RwHelper.h index 75525d25..b65a53ad 100644 --- a/src/RwHelper.h +++ b/src/RwHelper.h @@ -5,6 +5,11 @@ RwFrame *GetFirstChild(RwFrame *frame); RwObject *GetFirstObject(RwFrame *frame); RpAtomic *GetFirstAtomic(RpClump *clump); +RwTexDictionary *RwTexDictionaryGtaStreamRead(RwStream *stream); +bool RpClumpGtaStreamRead1(RwStream *stream); +RpClump *RpClumpGtaStreamRead2(RwStream *stream); +void RpClumpGtaCancelStream(void); + void CameraSize(RwCamera *camera, RwRect *rect, RwReal viewWindow, diff --git a/src/RwTexRead.cpp b/src/RwTexRead.cpp new file mode 100644 index 00000000..a1a7050a --- /dev/null +++ b/src/RwTexRead.cpp @@ -0,0 +1,126 @@ +#include "common.h" +#include "patcher.h" + +RwTexture* +RwTextureGtaStreamRead(RwStream *stream) +{ + RwUInt32 size, version; + RwTexture *tex; + + if(!RwStreamFindChunk(stream, rwID_TEXTURENATIVE, &size, &version)) + return nil; + + // TODO: unused timing + + if(!RWSRCGLOBAL(stdFunc[rwSTANDARDNATIVETEXTUREREAD](stream, &tex, size))) + return nil; + + return tex; +} + +RwTexture* +destroyTexture(RwTexture *texture, void *data) +{ + RwTextureDestroy(texture); + return texture; +} + +RwTexDictionary* +RwTexDictionaryGtaStreamRead(RwStream *stream) +{ + RwUInt32 size, version; + RwInt32 numTextures; + RwTexDictionary *texDict; + RwTexture *tex; + + if(!RwStreamFindChunk(stream, rwID_STRUCT, &size, &version)) + return nil; + assert(size == 4); + if(RwStreamRead(stream, &numTextures, size) != size) + return nil; + + texDict = RwTexDictionaryCreate(); + if(texDict == nil) + return nil; + + while(numTextures--){ + tex = RwTextureGtaStreamRead(stream); + if(tex == nil){ + RwTexDictionaryForAllTextures(texDict, destroyTexture, nil); + RwTexDictionaryDestroy(texDict); + return nil; + } + RwTexDictionaryAddTexture(texDict, tex); + } + + return texDict; +} + +static int32 numberTextures = -1; +static int32 streamPosition; + +RwTexDictionary* +RwTexDictionaryGtaStreamRead1(RwStream *stream) +{ + RwUInt32 size, version; + RwInt32 numTextures; + RwTexDictionary *texDict; + RwTexture *tex; + + numberTextures = 0; + if(!RwStreamFindChunk(stream, rwID_STRUCT, &size, &version)) + return nil; + assert(size == 4); + if(RwStreamRead(stream, &numTextures, size) != size) + return nil; + + texDict = RwTexDictionaryCreate(); + if(texDict == nil) + return nil; + + numberTextures = numTextures/2; + + while(numTextures > numberTextures){ + numTextures--; + + tex = RwTextureGtaStreamRead(stream); + if(tex == nil){ + RwTexDictionaryForAllTextures(texDict, destroyTexture, nil); + RwTexDictionaryDestroy(texDict); + return nil; + } + RwTexDictionaryAddTexture(texDict, tex); + } + + numberTextures = numTextures; + streamPosition = stream->Type.memory.position; + + return texDict; +} + +RwTexDictionary* +RwTexDictionaryGtaStreamRead2(RwStream *stream, RwTexDictionary *texDict) +{ + RwTexture *tex; + + RwStreamSkip(stream, streamPosition - stream->Type.memory.position); + + while(numberTextures--){ + tex = RwTextureGtaStreamRead(stream); + if(tex == nil){ + RwTexDictionaryForAllTextures(texDict, destroyTexture, nil); + RwTexDictionaryDestroy(texDict); + return nil; + } + RwTexDictionaryAddTexture(texDict, tex); + } + + return texDict; +} + +STARTPATCHES + InjectHook(0x592380, RwTextureGtaStreamRead, PATCH_JUMP); + InjectHook(0x5924A0, RwTexDictionaryGtaStreamRead, PATCH_JUMP); + InjectHook(0x592550, RwTexDictionaryGtaStreamRead1, PATCH_JUMP); + InjectHook(0x592650, RwTexDictionaryGtaStreamRead2, PATCH_JUMP); +ENDPATCHES diff --git a/src/TxdStore.cpp b/src/TxdStore.cpp index a5fc1758..10d6e1f5 100644 --- a/src/TxdStore.cpp +++ b/src/TxdStore.cpp @@ -2,11 +2,9 @@ #include "patcher.h" #include "templates.h" #include "Streaming.h" +#include "RwHelper.h" #include "TxdStore.h" -WRAPPER RwTexDictionary *RwTexDictionaryGtaStreamRead(RwStream *stream) { EAXJMP(0x5924A0); } - - CPool *&CTxdStore::ms_pTxdPool = *(CPool**)0x8F5FB8; RwTexDictionary *&CTxdStore::ms_pStoredTxd = *(RwTexDictionary**)0x9405BC;