From 4e3e1d0b87b88738741955fd2b673ee6ea4295ab Mon Sep 17 00:00:00 2001
From: aap <aap@papnet.eu>
Date: Thu, 16 Jul 2020 13:36:25 +0200
Subject: [PATCH] make game load all platform dffs

---
 src/core/FileLoader.cpp            | 17 ++++++++
 src/modelinfo/VehicleModelInfo.cpp |  2 +-
 src/rw/RwHelper.cpp                | 69 +++++++++++++++++++++++++++++-
 src/rw/RwHelper.h                  |  4 +-
 4 files changed, 89 insertions(+), 3 deletions(-)

diff --git a/src/core/FileLoader.cpp b/src/core/FileLoader.cpp
index 08126081..a7ab365c 100644
--- a/src/core/FileLoader.cpp
+++ b/src/core/FileLoader.cpp
@@ -393,6 +393,16 @@ CFileLoader::FindRelatedModelInfoCB(RpAtomic *atomic, void *data)
 	return atomic;
 }
 
+#ifdef LIBRW
+void
+InitClump(RpClump *clump)
+{
+	RpClumpForAllAtomics(clump, ConvertPlatformAtomic, nil);
+}
+#else
+#define InitClump(clump)
+#endif
+
 void
 CFileLoader::LoadModelFile(const char *filename)
 {
@@ -404,6 +414,7 @@ CFileLoader::LoadModelFile(const char *filename)
 	if(RwStreamFindChunk(stream, rwID_CLUMP, nil, nil)){
 		clump = RpClumpStreamRead(stream);
 		if(clump){
+			InitClump(clump);
 			RpClumpForAllAtomics(clump, FindRelatedModelInfoCB, clump);
 			RpClumpDestroy(clump);
 		}
@@ -429,6 +440,7 @@ CFileLoader::LoadClumpFile(const char *filename)
 			GetNameAndLOD(nodename, name, &n);
 			mi = (CClumpModelInfo*)CModelInfo::GetModelInfo(name, nil);
 			if(mi){
+				InitClump(clump);
 				assert(mi->IsClump());
 				mi->SetClump(clump);
 			}else
@@ -449,6 +461,7 @@ CFileLoader::LoadClumpFile(RwStream *stream, uint32 id)
 	clump = RpClumpStreamRead(stream);
 	if(clump == nil)
 		return false;
+	InitClump(clump);
 	mi = (CClumpModelInfo*)CModelInfo::GetModelInfo(id);
 	mi->SetClump(clump);
 	return true;
@@ -476,6 +489,7 @@ CFileLoader::FinishLoadClumpFile(RwStream *stream, uint32 id)
 	clump = RpClumpGtaStreamRead2(stream);
 
 	if(clump){
+		InitClump(clump);
 		mi = (CClumpModelInfo*)CModelInfo::GetModelInfo(id);
 		mi->SetClump(clump);
 		return true;
@@ -496,6 +510,7 @@ CFileLoader::LoadAtomicFile(RwStream *stream, uint32 id)
 		clump = RpClumpStreamRead(stream);
 		if(clump == nil)
 			return false;
+		InitClump(clump);
 		gpRelatedModelInfo = (CSimpleModelInfo*)CModelInfo::GetModelInfo(id);
 		RpClumpForAllAtomics(clump, SetRelatedModelInfoCB, clump);
 		RpClumpDestroy(clump);
@@ -531,6 +546,8 @@ CFileLoader::LoadAtomicFile2Return(const char *filename)
 	stream = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMREAD, filename);
 	if(RwStreamFindChunk(stream, rwID_CLUMP, nil, nil))
 		clump = RpClumpStreamRead(stream);
+	if(clump)
+		InitClump(clump);
 	RwStreamClose(stream, nil);
 	return clump;
 }
diff --git a/src/modelinfo/VehicleModelInfo.cpp b/src/modelinfo/VehicleModelInfo.cpp
index f80e908a..d5396d12 100644
--- a/src/modelinfo/VehicleModelInfo.cpp
+++ b/src/modelinfo/VehicleModelInfo.cpp
@@ -1091,7 +1091,7 @@ CVehicleModelInfo::SetEnvironmentMapCB(RpAtomic *atomic, void *data)
 	RpGeometry *geo;
 
 	geo = RpAtomicGetGeometry(atomic);
-	fx = 0;
+	fx = rpMATFXEFFECTNULL;
 	RpGeometryForAllMaterials(geo, GetMatFXEffectMaterialCB, &fx);
 	if(fx != rpMATFXEFFECTNULL){
 		RpMatFXAtomicEnableEffects(atomic);
diff --git a/src/rw/RwHelper.cpp b/src/rw/RwHelper.cpp
index 76c6c753..e8a85be6 100644
--- a/src/rw/RwHelper.cpp
+++ b/src/rw/RwHelper.cpp
@@ -212,7 +212,7 @@ isSkinnedCb(RpAtomic *atomic, void *data)
 	RpAtomic **pAtomic = (RpAtomic**)data;
 	if(*pAtomic)
 		return nil;	// already found one
-	if(RpSkinGeometryGetSkin(atomic->geometry))
+	if(RpSkinGeometryGetSkin(RpAtomicGetGeometry(atomic)))
 		*pAtomic = atomic;	// we could just return nil here directly...
 	return atomic;
 }
@@ -621,3 +621,70 @@ CameraCreate(RwInt32 width, RwInt32 height, RwBool zBuffer)
 WRAPPER void _TexturePoolsInitialise() { EAXJMP(0x598B10); }
 WRAPPER void _TexturePoolsShutdown() { EAXJMP(0x598B30); }
 #endif
+
+#ifdef LIBRW
+#include <rpmatfx.h>
+#include "VehicleModelInfo.h"
+
+int32
+findPlatform(rw::Atomic *a)
+{
+	rw::Geometry *g = a->geometry;
+	if(g->instData)
+		return g->instData->platform;
+	return 0;
+}
+
+// Game doesn't read atomic extensions so we never get any other than the default pipe,
+// but we need it for uninstancing
+void
+attachPipe(rw::Atomic *atomic)
+{
+	if(RpSkinGeometryGetSkin(RpAtomicGetGeometry(atomic)))
+		atomic->pipeline = rw::skinGlobals.pipelines[rw::platform];
+	else{
+		int fx = rpMATFXEFFECTNULL;
+		RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), CVehicleModelInfo::GetMatFXEffectMaterialCB, &fx);
+		if(fx != rpMATFXEFFECTNULL)
+			RpMatFXAtomicEnableEffects(atomic);
+	}
+}
+
+// Attach pipes for the platform we have native data for so we can uninstance
+void
+switchPipes(rw::Atomic *a, int32 platform)
+{
+	if(a->pipeline && a->pipeline->platform != platform){
+		uint32 plgid = a->pipeline->pluginID;
+		switch(plgid){
+		// assume default pipe won't be attached explicitly
+		case rw::ID_SKIN:
+			a->pipeline = rw::skinGlobals.pipelines[platform];
+			break;
+		case rw::ID_MATFX:
+			a->pipeline = rw::matFXGlobals.pipelines[platform];
+			break;
+		}
+	}
+}
+
+RpAtomic*
+ConvertPlatformAtomic(RpAtomic *atomic, void *data)
+{
+	int32 driver = rw::platform;
+	int32 platform = findPlatform(atomic);
+	if(platform != 0 && platform != driver){
+		attachPipe(atomic);	// kludge
+		rw::ObjPipeline *origPipe = atomic->pipeline;
+		rw::platform = platform;
+		switchPipes(atomic, rw::platform);
+		if(atomic->geometry->flags & rw::Geometry::NATIVE)
+			atomic->uninstance();
+		// no ADC in this game
+		//rw::ps2::unconvertADC(atomic->geometry);
+		rw::platform = driver;
+		atomic->pipeline = origPipe;
+	}
+	return atomic;
+}
+#endif
diff --git a/src/rw/RwHelper.h b/src/rw/RwHelper.h
index 993acd89..94a8bd94 100644
--- a/src/rw/RwHelper.h
+++ b/src/rw/RwHelper.h
@@ -54,4 +54,6 @@ RwCamera *CameraCreate(RwInt32 width,
 
 					   
 void _TexturePoolsInitialise();
-void _TexturePoolsShutdown();
\ No newline at end of file
+void _TexturePoolsShutdown();
+
+RpAtomic *ConvertPlatformAtomic(RpAtomic *atomic, void *data);