summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraap <aap@papnet.eu>2019-06-13 11:57:43 +0200
committeraap <aap@papnet.eu>2019-06-13 11:57:43 +0200
commitb4afb591a7465220ca40811924645932f568f319 (patch)
treedd4dd150905f99df9288c4f6f6babfbab0e0922b
parent12697a855353a1d537310d8f6dc293a6549e68da (diff)
implemented GTA stream read functions
-rw-r--r--premake5.lua4
-rw-r--r--src/FileMgr.cpp4
-rw-r--r--src/RwClumpRead.cpp230
-rw-r--r--src/RwHelper.cpp2
-rw-r--r--src/RwHelper.h5
-rw-r--r--src/RwTexRead.cpp126
-rw-r--r--src/TxdStore.cpp4
7 files changed, 369 insertions, 6 deletions
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<TxdDef,TxdDef> *&CTxdStore::ms_pTxdPool = *(CPool<TxdDef,TxdDef>**)0x8F5FB8;
RwTexDictionary *&CTxdStore::ms_pStoredTxd = *(RwTexDictionary**)0x9405BC;