From 90be379bede299aa53bca5027ecc19c356e50f86 Mon Sep 17 00:00:00 2001
From: aap <aap@papnet.eu>
Date: Wed, 15 Apr 2020 14:05:24 +0200
Subject: [PATCH] implemented most of librw wrapper

---
 premake5.lua               |  22 +-
 src/audio/AudioManager.cpp |   4 +-
 src/control/Replay.cpp     |  10 +-
 src/core/TempColModels.cpp |  42 +-
 src/core/common.h          |  14 +-
 src/fakerw/fake.cpp        | 795 +++++++++++++++++++++++++++++++++++++
 src/fakerw/rphanim.h       |  20 +
 src/fakerw/rpmatfx.h       |  43 ++
 src/fakerw/rpskin.h        |   8 +
 src/fakerw/rpworld.h       | 336 ++++++++++++++++
 src/fakerw/rtbmp.h         |   4 +
 src/fakerw/rwcore.h        | 413 +++++++++++++++++++
 src/fakerw/rwplcore.h      | 498 +++++++++++++++++++++++
 src/peds/Ped.cpp           |   2 +-
 src/render/Console.cpp     |   1 +
 src/render/Shadows.h       |   1 -
 src/render/Weather.cpp     |   2 +-
 src/rw/ClumpRead.cpp       |   6 +-
 src/rw/RwHelper.cpp        |   4 +
 src/rw/RwMatFX.cpp         |   4 +
 src/rw/TexRead.cpp         |  25 +-
 src/rw/rw.cpp              |   2 +
 22 files changed, 2212 insertions(+), 44 deletions(-)
 create mode 100644 src/fakerw/fake.cpp
 create mode 100644 src/fakerw/rphanim.h
 create mode 100644 src/fakerw/rpmatfx.h
 create mode 100644 src/fakerw/rpskin.h
 create mode 100644 src/fakerw/rpworld.h
 create mode 100644 src/fakerw/rtbmp.h
 create mode 100644 src/fakerw/rwcore.h
 create mode 100644 src/fakerw/rwplcore.h

diff --git a/premake5.lua b/premake5.lua
index 173fe3e4..cebc8ee9 100644
--- a/premake5.lua
+++ b/premake5.lua
@@ -1,5 +1,7 @@
+Librw = os.getenv("LIBRW")
+
 workspace "re3"
-	configurations { "Debug", "Release", "ReleaseFH", "DebugRW", "ReleaseRW"  }
+	configurations { "Debug", "Release", "ReleaseFH", "DebugRW", "ReleaseRW", "DebugLIBRW"  }
 	location "build"
 
 	files { "src/*.*" }
@@ -43,18 +45,28 @@ workspace "re3"
 	includedirs { "eax" }
 
 	includedirs { "dxsdk/include" }
-	includedirs { "rwsdk/include/d3d8" }
 	includedirs { "milessdk/include" }
 	includedirs { "eax" }
 
 	libdirs { "dxsdk/lib" }
 	libdirs { "milessdk/lib" }
 
+	filter "configurations:*LIBRW"
+	files { "src/fakerw/*.*" }
+	includedirs { "src/fakerw" }
+	includedirs { Librw }
+	libdirs { path.join(Librw, "lib/win-x86-d3d9/Debug") }
+	links { "rw", "d3d9" }
+
+	filter "configurations:not *LIBRW"
+	includedirs { "rwsdk/include/d3d8" }
+
 	filter "configurations:DebugRW or configurations:ReleaseRW"
 	defines { "RWLIBS" }
 	libdirs { "rwsdk/lib/d3d8/release" }
 	links { "rwcore", "rpworld", "rpmatfx", "rpskin", "rphanim", "rtbmp" }
 	filter  {}
+
 	
     pbcommands = { 
        "setlocal EnableDelayedExpansion",
@@ -123,3 +135,9 @@ project "re3"
 		optimize "On"
 		staticruntime "on"
 		setpaths("$(GTA_III_RE_DIR)/", "gta3.exe", "plugins/")
+
+	filter "configurations:DebugLIBRW"
+		defines { "DEBUG", "LIBRW", "RW_D3D9" }
+		symbols "On"
+		setpaths("$(GTA_III_RE_DIR)/", "gta3.exe", "plugins/")
+
diff --git a/src/audio/AudioManager.cpp b/src/audio/AudioManager.cpp
index 1d2835cf..f99891ec 100644
--- a/src/audio/AudioManager.cpp
+++ b/src/audio/AudioManager.cpp
@@ -1,4 +1,4 @@
-#include "common.h"
+#include "common.h"
 #include "patcher.h"
 
 #include "audio_enums.h"
@@ -6269,7 +6269,7 @@ cAudioManager::ProcessPedHeadphones(cPedParams *params)
 				emittingVol = 10;
 				veh = (CAutomobile *)ped->m_pMyVehicle;
 				if(veh && veh->IsCar()) {
-					for(int32 i = 2; i < ARRAYSIZE(veh->Doors); i++) {
+					for(int32 i = 2; i < ARRAY_SIZE(veh->Doors); i++) {
 						if(!veh->IsDoorClosed((eDoors)i) ||
 						   veh->IsDoorMissing((eDoors)i)) {
 							emittingVol = 42;
diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp
index 0da32dd2..9e0bed66 100644
--- a/src/control/Replay.cpp
+++ b/src/control/Replay.cpp
@@ -1215,7 +1215,7 @@ void CReplay::RestoreStuffFromMem(void)
 		vehicle->SetModelIndex(mi);
 		if (mi == MI_DODO){
 			CAutomobile* dodo = (CAutomobile*)vehicle;
-			RpAtomicSetFlags(GetFirstObject(dodo->m_aCarNodes[CAR_WHEEL_LF]), 0);
+			RpAtomicSetFlags((RpAtomic*)GetFirstObject(dodo->m_aCarNodes[CAR_WHEEL_LF]), 0);
 			CMatrix tmp1;
 			tmp1.Attach(RwFrameGetMatrix(dodo->m_aCarNodes[CAR_WHEEL_RF]), false);
 			CMatrix tmp2(RwFrameGetMatrix(dodo->m_aCarNodes[CAR_WHEEL_LF]), false);
@@ -1243,7 +1243,7 @@ void CReplay::RestoreStuffFromMem(void)
 				vehicle->GetMatrix().Detach();
 				if (vehicle->m_rwObject){
 					if (RwObjectGetType(vehicle->m_rwObject) == rpATOMIC){
-						RwFrame* frame = RpAtomicGetFrame(vehicle->m_rwObject);
+						RwFrame* frame = RpAtomicGetFrame((RpAtomic*)vehicle->m_rwObject);
 						RpAtomicDestroy((RpAtomic*)vehicle->m_rwObject);
 						RwFrameDestroy(frame);
 					}
@@ -1254,7 +1254,7 @@ void CReplay::RestoreStuffFromMem(void)
 				int model_id = info->m_wheelId;
 				if (model_id != -1){
 					if ((vehicle->m_rwObject = CModelInfo::GetModelInfo(model_id)->CreateInstance())){
-						vehicle->GetMatrix().AttachRW(&((RwFrame*)vehicle->m_rwObject->parent)->modelling, false);
+						vehicle->GetMatrix().AttachRW(RwFrameGetMatrix(RpClumpGetFrame((RpClump*)vehicle->m_rwObject)), false);
 					}
 				}
 			}
@@ -1274,7 +1274,7 @@ void CReplay::RestoreStuffFromMem(void)
 		object->SetModelIndex(mi);
 		object->GetMatrix().m_attachment = nil;
 		if (RwObjectGetType(object->m_rwObject) == rpATOMIC)
-			object->GetMatrix().AttachRW(RwFrameGetMatrix(RpAtomicGetFrame(object->m_rwObject)), false);
+			object->GetMatrix().AttachRW(RwFrameGetMatrix(RpAtomicGetFrame((RpAtomic*)object->m_rwObject)), false);
 	}
 	i = CPools::GetDummyPool()->GetSize();
 	while (--i >= 0) {
@@ -1289,7 +1289,7 @@ void CReplay::RestoreStuffFromMem(void)
 		dummy->SetModelIndex(mi);
 		dummy->GetMatrix().m_attachment = nil;
 		if (RwObjectGetType(dummy->m_rwObject) == rpATOMIC)
-			dummy->GetMatrix().AttachRW(RwFrameGetMatrix(RpAtomicGetFrame(dummy->m_rwObject)), false);
+			dummy->GetMatrix().AttachRW(RwFrameGetMatrix(RpAtomicGetFrame((RpAtomic*)dummy->m_rwObject)), false);
 	}
 	CTimer::SetTimeInMilliseconds(Time1);
 	CTimer::SetTimeInMillisecondsNonClipped(Time2);
diff --git a/src/core/TempColModels.cpp b/src/core/TempColModels.cpp
index f7cf035e..22ef31bd 100644
--- a/src/core/TempColModels.cpp
+++ b/src/core/TempColModels.cpp
@@ -34,7 +34,7 @@ void
 CTempColModels::Initialise(void)
 {
 #define SET_COLMODEL_SPHERES(colmodel, sphrs)\
-	colmodel.numSpheres = ARRAYSIZE(sphrs);\
+	colmodel.numSpheres = ARRAY_SIZE(sphrs);\
 	colmodel.spheres = sphrs;\
 	colmodel.level = LEVEL_NONE;\
 	colmodel.ownsCollisionVolumes = false;\
@@ -45,7 +45,7 @@ CTempColModels::Initialise(void)
 	ms_colModelBBox.boundingBox.Set(CVector(-2.0f, -2.0f, -2.0f), CVector(2.0f, 2.0f, 2.0f), SURFACE_DEFAULT, 0);
 	ms_colModelBBox.level = LEVEL_NONE;
 
-	for (i = 0; i < ARRAYSIZE(ms_colModelCutObj); i++) {
+	for (i = 0; i < ARRAY_SIZE(ms_colModelCutObj); i++) {
 		ms_colModelCutObj[i].boundingSphere.Set(2.0f, CVector(0.0f, 0.0f, 0.0f), SURFACE_DEFAULT, 0);
 		ms_colModelCutObj[i].boundingBox.Set(CVector(-2.0f, -2.0f, -2.0f), CVector(2.0f, 2.0f, 2.0f), SURFACE_DEFAULT, 0);
 		ms_colModelCutObj[i].level = LEVEL_NONE;
@@ -53,7 +53,7 @@ CTempColModels::Initialise(void)
 
 	// Ped Spheres
 
-	for (i = 0; i < ARRAYSIZE(s_aPedSpheres); i++)
+	for (i = 0; i < ARRAY_SIZE(s_aPedSpheres); i++)
 		s_aPedSpheres[i].radius = 0.35f;
 
 	s_aPedSpheres[0].center = CVector(0.0f, 0.0f, -0.25f);
@@ -61,9 +61,9 @@ CTempColModels::Initialise(void)
 	s_aPedSpheres[2].center = CVector(0.0f, 0.0f, 0.55f);
 
 #ifdef FIX_BUGS
-	for (i = 0; i < ARRAYSIZE(s_aPedSpheres); i++) {
+	for (i = 0; i < ARRAY_SIZE(s_aPedSpheres); i++) {
 #else
-	for (i = 0; i < ARRAYSIZE(s_aPedGSpheres); i++) {
+	for (i = 0; i < ARRAY_SIZE(s_aPedGSpheres); i++) {
 #endif
 		s_aPedSpheres[i].surface = SURFACE_FLESH;
 		s_aPedSpheres[i].piece = 0;
@@ -83,7 +83,7 @@ CTempColModels::Initialise(void)
 	s_aPed2Spheres[1].center = CVector(0.0f, 0.0f, -0.9f);
 	s_aPed2Spheres[2].center = CVector(0.0f, -0.35f, -0.9f);
 
-	for (i = 0; i < ARRAYSIZE(s_aPed2Spheres); i++) {
+	for (i = 0; i < ARRAY_SIZE(s_aPed2Spheres); i++) {
 		s_aPed2Spheres[i].surface = SURFACE_FLESH;
 		s_aPed2Spheres[i].piece = 0;
 	}
@@ -129,7 +129,7 @@ CTempColModels::Initialise(void)
 	s_aDoorSpheres[1].center = CVector(0.0f, -0.95f, -0.35f);
 	s_aDoorSpheres[2].center = CVector(0.0f, -0.6f, 0.25f);
 
-	for (i = 0; i < ARRAYSIZE(s_aDoorSpheres); i++) {
+	for (i = 0; i < ARRAY_SIZE(s_aDoorSpheres); i++) {
 		s_aDoorSpheres[i].surface = SURFACE_BILLBOARD;
 		s_aDoorSpheres[i].piece = 0;
 	}
@@ -141,7 +141,7 @@ CTempColModels::Initialise(void)
 
 	// Bumper Spheres
 
-	for (i = 0; i < ARRAYSIZE(s_aBumperSpheres); i++)
+	for (i = 0; i < ARRAY_SIZE(s_aBumperSpheres); i++)
 		s_aBumperSpheres[i].radius = 0.15f;
 
 	s_aBumperSpheres[0].center = CVector(0.85f, -0.05f, 0.0f);
@@ -149,7 +149,7 @@ CTempColModels::Initialise(void)
 	s_aBumperSpheres[2].center = CVector(-0.4f, 0.05f, 0.0f);
 	s_aBumperSpheres[3].center = CVector(-0.85f, -0.05f, 0.0f);
 
-	for (i = 0; i < ARRAYSIZE(s_aBumperSpheres); i++) {
+	for (i = 0; i < ARRAY_SIZE(s_aBumperSpheres); i++) {
 		s_aBumperSpheres[i].surface = SURFACE_BILLBOARD;
 		s_aBumperSpheres[i].piece = 0;
 	}
@@ -161,7 +161,7 @@ CTempColModels::Initialise(void)
 
 	// Panel Spheres
 
-	for (i = 0; i < ARRAYSIZE(s_aPanelSpheres); i++)
+	for (i = 0; i < ARRAY_SIZE(s_aPanelSpheres); i++)
 		s_aPanelSpheres[i].radius = 0.15f;
 
 	s_aPanelSpheres[0].center = CVector(0.15f, 0.45f, 0.0f);
@@ -169,7 +169,7 @@ CTempColModels::Initialise(void)
 	s_aPanelSpheres[2].center = CVector(-0.15f, -0.45f, 0.0f);
 	s_aPanelSpheres[3].center = CVector(-0.15f, 0.45f, 0.0f);
 
-	for (i = 0; i < ARRAYSIZE(s_aPanelSpheres); i++) {
+	for (i = 0; i < ARRAY_SIZE(s_aPanelSpheres); i++) {
 		s_aPanelSpheres[i].surface = SURFACE_BILLBOARD;
 		s_aPanelSpheres[i].piece = 0;
 	}
@@ -181,7 +181,7 @@ CTempColModels::Initialise(void)
 
 	// Bonnet Spheres
 
-	for (i = 0; i < ARRAYSIZE(s_aBonnetSpheres); i++)
+	for (i = 0; i < ARRAY_SIZE(s_aBonnetSpheres); i++)
 		s_aBonnetSpheres[i].radius = 0.2f;
 
 	s_aBonnetSpheres[0].center = CVector(-0.4f, 0.1f, 0.0f);
@@ -189,7 +189,7 @@ CTempColModels::Initialise(void)
 	s_aBonnetSpheres[2].center = CVector(0.4f, 0.1f, 0.0f);
 	s_aBonnetSpheres[3].center = CVector(0.4f, 0.9f, 0.0f);
 
-	for (i = 0; i < ARRAYSIZE(s_aBonnetSpheres); i++) {
+	for (i = 0; i < ARRAY_SIZE(s_aBonnetSpheres); i++) {
 		s_aBonnetSpheres[i].surface = SURFACE_BILLBOARD;
 		s_aBonnetSpheres[i].piece = 0;
 	}
@@ -201,7 +201,7 @@ CTempColModels::Initialise(void)
 
 	// Boot Spheres
 
-	for (i = 0; i < ARRAYSIZE(s_aBootSpheres); i++)
+	for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++)
 		s_aBootSpheres[i].radius = 0.2f;
 
 	s_aBootSpheres[0].center = CVector(-0.4f, -0.1f, 0.0f);
@@ -209,7 +209,7 @@ CTempColModels::Initialise(void)
 	s_aBootSpheres[2].center = CVector(0.4f, -0.1f, 0.0f);
 	s_aBootSpheres[3].center = CVector(0.4f, -0.6f, 0.0f);
 
-	for (i = 0; i < ARRAYSIZE(s_aBootSpheres); i++) {
+	for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) {
 		s_aBootSpheres[i].surface = SURFACE_BILLBOARD;
 		s_aBootSpheres[i].piece = 0;
 	}
@@ -228,9 +228,9 @@ CTempColModels::Initialise(void)
 	s_aWheelSpheres[1].center = CVector(0.3f, 0.0f, 0.0f);
 
 #ifdef FIX_BUGS
-	for (i = 0; i < ARRAYSIZE(s_aWheelSpheres); i++) {
+	for (i = 0; i < ARRAY_SIZE(s_aWheelSpheres); i++) {
 #else
-	for (i = 0; i < ARRAYSIZE(s_aBootSpheres); i++) {
+	for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) {
 #endif
 		s_aWheelSpheres[i].surface = SURFACE_RUBBER29;
 		s_aWheelSpheres[i].piece = 0;
@@ -250,9 +250,9 @@ CTempColModels::Initialise(void)
 	s_aBodyPartSpheres1[1].center = CVector(0.8f, 0.0f, 0.0f);
 
 #ifdef FIX_BUGS
-	for (i = 0; i < ARRAYSIZE(s_aBodyPartSpheres1); i++) {
+	for (i = 0; i < ARRAY_SIZE(s_aBodyPartSpheres1); i++) {
 #else
-	for (i = 0; i < ARRAYSIZE(s_aBootSpheres); i++) {
+	for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) {
 #endif
 		s_aBodyPartSpheres1[i].surface = SURFACE_FLESH;
 		s_aBodyPartSpheres1[i].piece = 0;
@@ -272,9 +272,9 @@ CTempColModels::Initialise(void)
 	s_aBodyPartSpheres2[1].center = CVector(0.5f, 0.0f, 0.0f);
 
 #ifdef FIX_BUGS
-	for (i = 0; i < ARRAYSIZE(s_aBodyPartSpheres2); i++) {
+	for (i = 0; i < ARRAY_SIZE(s_aBodyPartSpheres2); i++) {
 #else
-	for (i = 0; i < ARRAYSIZE(s_aBootSpheres); i++) {
+	for (i = 0; i < ARRAY_SIZE(s_aBootSpheres); i++) {
 #endif
 		s_aBodyPartSpheres2[i].surface = SURFACE_FLESH;
 		s_aBodyPartSpheres2[i].piece = 0;
diff --git a/src/core/common.h b/src/core/common.h
index 7688b182..454b848a 100644
--- a/src/core/common.h
+++ b/src/core/common.h
@@ -23,6 +23,15 @@
 #include <rwcore.h>
 #include <rpworld.h>
 
+// gotta put this somewhere
+#ifdef LIBRW
+#define STREAMPOS(str) ((str)->tell())
+#define STREAMFILE(str) (((rw::StreamFile*)(str))->file)
+#else
+#define STREAMPOS(str) ((str)->Type.memory.position)
+#define STREAMFILE(str) ((str)->Type.file.fpFile)
+#endif
+
 #define rwVENDORID_ROCKSTAR 0x0253F2
 
 // Get rid of bullshit windows definitions, we're not running on an 8086
@@ -39,9 +48,6 @@
 #ifndef min
 #define min(a,b) ((a) < (b) ? (a) : (b))
 #endif
-#ifndef ARRAYSIZE
-#define ARRAYSIZE(a) (sizeof(a) / sizeof(*(a)))
-#endif
 
 typedef uint8_t uint8;
 typedef int8_t int8;
@@ -55,7 +61,9 @@ typedef int64_t int64;
 // hardcode ucs-2
 typedef uint16_t wchar;
 
+#ifndef nil
 #define nil nullptr
+#endif
 
 #include "config.h"
 
diff --git a/src/fakerw/fake.cpp b/src/fakerw/fake.cpp
new file mode 100644
index 00000000..1aaa8d11
--- /dev/null
+++ b/src/fakerw/fake.cpp
@@ -0,0 +1,795 @@
+#define _CRT_SECURE_NO_WARNINGS
+#define WITH_D3D
+#include <rwcore.h>
+#include <rpworld.h>
+#include <rpmatfx.h>
+#include <rphanim.h>
+#include <assert.h>
+#include <string.h>
+
+// TODO: split image<->raster functions in two
+//       implement raster context
+//	BMP reader
+//	geometry locking
+
+using namespace rw;
+
+RwUInt8 RwObjectGetType(const RwObject *obj) { return obj->type; }
+
+
+void *RwMalloc(size_t size) { return malloc(size); }
+void *RwCalloc(size_t numObj, size_t sizeObj) { return calloc(numObj, sizeObj); }
+void  RwFree(void *mem) { free(mem); }
+
+
+//RwReal RwV3dNormalize(RwV3d * out, const RwV3d * in);
+RwReal RwV3dLength(const RwV3d * in) { return length(*in); }
+//RwReal RwV2dLength(const RwV2d * in);
+//RwReal RwV2dNormalize(RwV2d * out, const RwV2d * in);
+//void RwV2dAssign(RwV2d * out, const RwV2d * ina);
+//void RwV2dAdd(RwV2d * out, const RwV2d * ina, const RwV2d * inb);
+//void RwV2dLineNormal(RwV2d * out, const RwV2d * ina, const RwV2d * inb);
+//void RwV2dSub(RwV2d * out, const RwV2d * ina, const RwV2d * inb);
+//void RwV2dPerp(RwV2d * out, const RwV2d * in);
+//void RwV2dScale(RwV2d * out, const RwV2d * in, RwReal scalar);
+//RwReal RwV2dDotProduct(const RwV2d * ina, const RwV2d * inb);
+//void RwV3dAssign(RwV3d * out, const RwV3d * ina);
+void RwV3dAdd(RwV3d * out, const RwV3d * ina, const RwV3d * inb) { *out = add(*ina, *inb); }
+void RwV3dSub(RwV3d * out, const RwV3d * ina, const RwV3d * inb) { *out = sub(*ina, *inb); }
+//void RwV3dScale(RwV3d * out, const RwV3d * in, RwReal scalar);
+//void RwV3dIncrementScaled(RwV3d * out,  const RwV3d * in, RwReal scalar);
+//void RwV3dNegate(RwV3d * out, const RwV3d * in);
+RwReal RwV3dDotProduct(const RwV3d * ina, const RwV3d * inb) { return dot(*ina, *inb); }
+//void RwV3dCrossProduct(RwV3d * out, const RwV3d * ina, const RwV3d * inb);
+RwV3d *RwV3dTransformPoints(RwV3d * pointsOut, const RwV3d * pointsIn, RwInt32 numPoints, const RwMatrix * matrix)
+	{ V3d::transformPoints(pointsOut, pointsIn, numPoints, matrix); return pointsOut; }
+//RwV3d *RwV3dTransformVectors(RwV3d * vectorsOut, const RwV3d * vectorsIn, RwInt32 numPoints, const RwMatrix * matrix);
+
+
+
+RwBool RwMatrixDestroy(RwMatrix *mpMat) { mpMat->destroy(); return true; }
+RwMatrix *RwMatrixCreate(void) { return Matrix::create(); }
+void RwMatrixCopy(RwMatrix * dstMatrix, const RwMatrix * srcMatrix) { *dstMatrix = *srcMatrix; }
+void RwMatrixSetIdentity(RwMatrix * matrix) { matrix->setIdentity(); }
+RwMatrix *RwMatrixMultiply(RwMatrix * matrixOut, const RwMatrix * MatrixIn1, const RwMatrix * matrixIn2);
+RwMatrix *RwMatrixTransform(RwMatrix * matrix, const RwMatrix * transform, RwOpCombineType combineOp)
+	{ matrix->transform(transform, (rw::CombineOp)combineOp); return matrix; }
+//RwMatrix *RwMatrixOrthoNormalize(RwMatrix * matrixOut, const RwMatrix * matrixIn);
+//RwMatrix *RwMatrixInvert(RwMatrix * matrixOut, const RwMatrix * matrixIn);
+RwMatrix *RwMatrixScale(RwMatrix * matrix, const RwV3d * scale, RwOpCombineType combineOp)
+	{ matrix->scale(scale, (rw::CombineOp)combineOp); return matrix; }
+RwMatrix *RwMatrixTranslate(RwMatrix * matrix, const RwV3d * translation, RwOpCombineType combineOp)
+	{ matrix->translate(translation, (rw::CombineOp)combineOp); return matrix; }
+RwMatrix *RwMatrixRotate(RwMatrix * matrix, const RwV3d * axis, RwReal angle, RwOpCombineType combineOp)
+	{ matrix->rotate(axis, angle, (rw::CombineOp)combineOp); return matrix; }
+//RwMatrix *RwMatrixRotateOneMinusCosineSine(RwMatrix * matrix, const RwV3d * unitAxis, RwReal oneMinusCosine, RwReal sine, RwOpCombineType combineOp);
+//const RwMatrix *RwMatrixQueryRotate(const RwMatrix * matrix, RwV3d * unitAxis, RwReal * angle, RwV3d * center);
+RwV3d *RwMatrixGetRight(RwMatrix * matrix) { return &matrix->right; }
+RwV3d *RwMatrixGetUp(RwMatrix * matrix) { return &matrix->up; }
+RwV3d *RwMatrixGetAt(RwMatrix * matrix) { return &matrix->at; }
+RwV3d *RwMatrixGetPos(RwMatrix * matrix) { return &matrix->pos; }
+RwMatrix *RwMatrixUpdate(RwMatrix * matrix) { matrix->update(); return matrix; }
+//RwMatrix *RwMatrixOptimize(RwMatrix * matrix, const RwMatrixTolerance *tolerance);
+
+
+
+
+RwFrame *RwFrameForAllObjects(RwFrame * frame, RwObjectCallBack callBack, void *data) {
+	FORLIST(lnk, frame->objectList)
+		if(callBack(&ObjectWithFrame::fromFrame(lnk)->object, data) == nil)
+			break;
+	return frame;
+}
+RwFrame *RwFrameTranslate(RwFrame * frame, const RwV3d * v, RwOpCombineType combine) { frame->translate(v, (CombineOp)combine); return frame; }
+RwFrame *RwFrameRotate(RwFrame * frame, const RwV3d * axis, RwReal angle, RwOpCombineType combine) { frame->rotate(axis, angle, (CombineOp)combine); return frame; }
+RwFrame *RwFrameScale(RwFrame * frame, const RwV3d * v, RwOpCombineType combine) { frame->scale(v, (CombineOp)combine); return frame; }
+RwFrame *RwFrameTransform(RwFrame * frame, const RwMatrix * m, RwOpCombineType combine) { frame->transform(m, (CombineOp)combine); return frame; }
+//RwFrame *RwFrameOrthoNormalize(RwFrame * frame);
+RwFrame *RwFrameSetIdentity(RwFrame * frame) { frame->matrix.setIdentity(); frame->updateObjects(); return frame; }
+//RwFrame *RwFrameCloneHierarchy(RwFrame * root);
+//RwBool RwFrameDestroyHierarchy(RwFrame * frame);
+RwFrame *RwFrameForAllChildren(RwFrame * frame, RwFrameCallBack callBack, void *data)
+	{ return frame->forAllChildren(callBack, data); }
+RwFrame *RwFrameRemoveChild(RwFrame * child) { child->removeChild(); return child; }
+RwFrame *RwFrameAddChild(RwFrame * parent, RwFrame * child) { parent->addChild(child); return parent; }
+RwFrame *RwFrameGetParent(const RwFrame * frame) { return frame->getParent(); }
+//RwFrame *RwFrameGetRoot(const RwFrame * frame);
+RwMatrix *RwFrameGetLTM(RwFrame * frame) { return frame->getLTM(); }
+RwMatrix *RwFrameGetMatrix(RwFrame * frame) { return &frame->matrix; }
+RwFrame *RwFrameUpdateObjects(RwFrame * frame) { frame->updateObjects(); return frame; }
+RwFrame *RwFrameCreate(void) { return rw::Frame::create(); }
+//RwBool RwFrameInit(RwFrame *frame);
+//RwBool RwFrameDeInit(RwFrame *frame);
+RwBool RwFrameDestroy(RwFrame * frame) { frame->destroy(); return true; }
+//void _rwFrameInit(RwFrame *frame);
+//void _rwFrameDeInit(RwFrame *frame);
+//RwBool RwFrameDirty(const RwFrame * frame);
+//RwInt32 RwFrameCount(RwFrame * frame);
+//RwBool RwFrameSetStaticPluginsSize(RwInt32 size);
+RwInt32 RwFrameRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB)
+	{ return Frame::registerPlugin(size, pluginID, constructCB, destructCB, (CopyConstructor)copyCB); }
+//RwInt32 RwFrameGetPluginOffset(RwUInt32 pluginID);
+//RwBool RwFrameValidatePlugins(const RwFrame * frame);
+//RwFrame *_rwFrameCloneAndLinkClones(RwFrame * root);
+//RwFrame *_rwFramePurgeClone(RwFrame *root);
+
+RwInt32 RwFrameRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB)
+	{ return Frame::registerPluginStream(pluginID, readCB, (StreamWrite)writeCB, (StreamGetSize)getSizeCB); }
+
+
+rwFrameList *rwFrameListDeinitialize(rwFrameList *frameList) {
+	rwFree(frameList->frames);
+	frameList->frames = nil;
+	return frameList;
+}
+rwFrameList *rwFrameListStreamRead(RwStream *stream, rwFrameList *fl) { return fl->streamRead(stream); }
+
+
+
+
+RwCamera    *RwCameraBeginUpdate(RwCamera * camera) { camera->beginUpdate(); return camera; }
+RwCamera    *RwCameraEndUpdate(RwCamera * camera) { camera->endUpdate(); return camera; }
+RwCamera    *RwCameraClear(RwCamera * camera, RwRGBA * colour, RwInt32 clearMode) { camera->clear(colour, clearMode); return camera; }
+// WARNING: ignored arguments
+RwCamera    *RwCameraShowRaster(RwCamera * camera, void *pDev, RwUInt32 flags) { camera->showRaster(); return camera; }
+RwBool       RwCameraDestroy(RwCamera * camera) { camera->destroy(); return true; }
+RwCamera    *RwCameraCreate(void) { return rw::Camera::create(); }
+RwCamera    *RwCameraClone(RwCamera * camera) { return camera->clone(); }
+RwCamera    *RwCameraSetViewOffset(RwCamera *camera, const RwV2d *offset) { camera->setViewOffset(offset); return camera; }
+RwCamera    *RwCameraSetViewWindow(RwCamera *camera, const RwV2d *viewWindow) { camera->setViewWindow(viewWindow); return camera; }
+RwCamera    *RwCameraSetProjection(RwCamera *camera, RwCameraProjection projection);
+RwCamera    *RwCameraSetNearClipPlane(RwCamera *camera, RwReal nearClip) { camera->setNearPlane(nearClip); return camera; }
+RwCamera    *RwCameraSetFarClipPlane(RwCamera *camera, RwReal farClip) { camera->setFarPlane(farClip); return camera; }
+RwInt32      RwCameraRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);
+RwInt32      RwCameraGetPluginOffset(RwUInt32 pluginID);
+RwBool       RwCameraValidatePlugins(const RwCamera * camera);
+RwFrustumTestResult RwCameraFrustumTestSphere(const RwCamera * camera, const RwSphere * sphere) { return (RwFrustumTestResult)camera->frustumTestSphere(sphere); }
+const RwV2d *RwCameraGetViewOffset(const RwCamera *camera) { return &camera->viewOffset; }
+RwCamera    *RwCameraSetRaster(RwCamera *camera, RwRaster *raster) { camera->frameBuffer = raster; return camera; }
+RwRaster    *RwCameraGetRaster(const RwCamera *camera) { return camera->frameBuffer; }
+RwCamera    *RwCameraSetZRaster(RwCamera *camera, RwRaster *zRaster) { camera->zBuffer = zRaster; return camera; }
+RwRaster    *RwCameraGetZRaster(const RwCamera *camera) { return camera->zBuffer; }
+RwReal       RwCameraGetNearClipPlane(const RwCamera *camera) { return camera->nearPlane; }
+RwReal       RwCameraGetFarClipPlane(const RwCamera *camera) { return camera->farPlane; }
+RwCamera    *RwCameraSetFogDistance(RwCamera *camera, RwReal fogDistance) { camera->fogPlane = fogDistance; return camera; }
+RwReal       RwCameraGetFogDistance(const RwCamera *camera) { return camera->fogPlane; }
+RwCamera    *RwCameraGetCurrentCamera(void);
+RwCameraProjection RwCameraGetProjection(const RwCamera *camera);
+const RwV2d *RwCameraGetViewWindow(const RwCamera *camera) { return &camera->viewWindow; }
+RwMatrix    *RwCameraGetViewMatrix(RwCamera *camera) { return &camera->viewMatrix; }
+RwCamera    *RwCameraSetFrame(RwCamera *camera, RwFrame *frame) { camera->setFrame(frame); return camera; }
+RwFrame     *RwCameraGetFrame(const RwCamera *camera) { return camera->getFrame(); }
+
+
+
+
+
+RwImage     *RwImageCreate(RwInt32 width, RwInt32 height, RwInt32 depth) { return Image::create(width, height, depth); }
+RwBool       RwImageDestroy(RwImage * image) { image->destroy(); return true; }
+RwImage     *RwImageAllocatePixels(RwImage * image);
+RwImage     *RwImageFreePixels(RwImage * image);
+RwImage     *RwImageCopy(RwImage * destImage, const RwImage * sourceImage);
+RwImage     *RwImageResize(RwImage * image, RwInt32 width, RwInt32 height);
+RwImage     *RwImageApplyMask(RwImage * image, const RwImage * mask);
+RwImage     *RwImageMakeMask(RwImage * image);
+RwImage     *RwImageReadMaskedImage(const RwChar * imageName, const RwChar * maskname);
+RwImage     *RwImageRead(const RwChar * imageName);
+RwImage     *RwImageWrite(RwImage * image, const RwChar * imageName);
+RwChar      *RwImageGetPath(void);
+const RwChar *RwImageSetPath(const RwChar * path) { Image::setSearchPath(path); return path; }
+RwImage     *RwImageSetStride(RwImage * image, RwInt32 stride) { image->stride = stride; return image; }
+RwImage     *RwImageSetPixels(RwImage * image, RwUInt8 * pixels) { image->setPixels(pixels); return image; }
+RwImage     *RwImageSetPalette(RwImage * image, RwRGBA * palette) { image->setPalette((uint8*)palette); return image; }
+RwInt32      RwImageGetWidth(const RwImage * image);
+RwInt32      RwImageGetHeight(const RwImage * image);
+RwInt32      RwImageGetDepth(const RwImage * image);
+RwInt32      RwImageGetStride(const RwImage * image);
+RwUInt8     *RwImageGetPixels(const RwImage * image);
+RwRGBA      *RwImageGetPalette(const RwImage * image);
+RwUInt32     RwRGBAToPixel(RwRGBA * rgbIn, RwInt32 rasterFormat);
+RwRGBA      *RwRGBASetFromPixel(RwRGBA * rgbOut, RwUInt32 pixelValue, RwInt32 rasterFormat);
+RwBool       RwImageSetGamma(RwReal gammaValue);
+RwReal       RwImageGetGamma(void);
+RwImage     *RwImageGammaCorrect(RwImage * image);
+RwRGBA      *RwRGBAGammaCorrect(RwRGBA * rgb);
+RwInt32      RwImageRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);
+RwInt32      RwImageGetPluginOffset(RwUInt32 pluginID);
+RwBool       RwImageValidatePlugins(const RwImage * image);
+//RwBool       RwImageRegisterImageFormat(const RwChar * extension, RwImageCallBackRead imageRead, RwImageCallBackWrite imageWrite);
+const RwChar *RwImageFindFileType(const RwChar * imageName);
+RwInt32      RwImageStreamGetSize(const RwImage * image);
+RwImage     *RwImageStreamRead(RwStream * stream);
+const RwImage *RwImageStreamWrite(const RwImage * image, RwStream * stream);
+
+// TODO: this is kind hard...
+RwImage *RwImageFindRasterFormat(RwImage *ipImage,RwInt32 nRasterType, RwInt32 *npWidth,RwInt32 *npHeight, RwInt32 *npDepth,RwInt32 *npFormat)
+{
+	// very dumb implementation for now
+	// this is also platform specific
+	if((nRasterType&rwRASTERTYPEMASK) != rwRASTERTYPETEXTURE){
+		*npFormat = 0;
+		return nil;
+	}
+	*npWidth = ipImage->width;
+	*npHeight = ipImage->height;
+	switch(ipImage->depth){
+	case 4:
+	case 8:
+		*npDepth = 8;
+		*npFormat = Raster::C8888 | Raster::PAL8;
+		break;
+	case 16:
+		*npDepth = 16;
+		*npFormat = Raster::C1555;
+		break;
+	case 24:
+		*npDepth = 32;
+		*npFormat = Raster::C888;
+		break;
+	case 32:
+		*npDepth = 32;
+		*npFormat = Raster::C8888;
+		break;
+	default:
+		assert(0 && "invalid depth");
+		return nil;
+	}
+	return ipImage;
+}
+
+
+
+
+RwRaster    *RwRasterCreate(RwInt32 width, RwInt32 height, RwInt32 depth, RwInt32 flags) { return Raster::create(width, height, depth, flags); }
+RwBool       RwRasterDestroy(RwRaster * raster) { raster->destroy(); return true; }
+RwInt32      RwRasterGetWidth(const RwRaster *raster) { return raster->width; }
+RwInt32      RwRasterGetHeight(const RwRaster *raster) { return raster->height; }
+RwInt32      RwRasterGetStride(const RwRaster *raster);
+RwInt32      RwRasterGetDepth(const RwRaster *raster) { return raster->depth; }
+RwInt32      RwRasterGetFormat(const RwRaster *raster);
+RwInt32      RwRasterGetType(const RwRaster *raster);
+RwRaster    *RwRasterGetParent(const RwRaster *raster) { return raster->parent; }
+RwRaster    *RwRasterGetOffset(RwRaster *raster,  RwInt16 *xOffset, RwInt16 *yOffset);
+RwInt32      RwRasterGetNumLevels(RwRaster * raster);
+RwRaster    *RwRasterSubRaster(RwRaster * subRaster, RwRaster * raster, RwRect * rect);
+RwRaster    *RwRasterRenderFast(RwRaster * raster, RwInt32 x, RwInt32 y);
+RwRaster    *RwRasterRender(RwRaster * raster, RwInt32 x, RwInt32 y);
+RwRaster    *RwRasterRenderScaled(RwRaster * raster, RwRect * rect);
+RwRaster    *RwRasterPushContext(RwRaster * raster);
+RwRaster    *RwRasterPopContext(void);
+RwRaster    *RwRasterGetCurrentContext(void);
+RwBool       RwRasterClear(RwInt32 pixelValue);
+RwBool       RwRasterClearRect(RwRect * rpRect, RwInt32 pixelValue);
+RwRaster    *RwRasterShowRaster(RwRaster * raster, void *dev, RwUInt32 flags);
+RwUInt8     *RwRasterLock(RwRaster * raster, RwUInt8 level, RwInt32 lockMode);
+RwRaster    *RwRasterUnlock(RwRaster * raster);
+RwUInt8     *RwRasterLockPalette(RwRaster * raster, RwInt32 lockMode);
+RwRaster    *RwRasterUnlockPalette(RwRaster * raster);
+RwInt32      RwRasterRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);
+RwInt32      RwRasterGetPluginOffset(RwUInt32 pluginID);
+RwBool       RwRasterValidatePlugins(const RwRaster * raster);
+
+// TODO: let's hope this works
+RwRaster *RwRasterSetFromImage(RwRaster *raster, RwImage *image) {
+	engine->driver[raster->platform]->rasterFromImage(raster, image);
+	return raster;
+}
+
+
+
+
+RwTexture *RwTextureCreate(RwRaster * raster) { return Texture::create(raster); }
+RwBool RwTextureDestroy(RwTexture * texture) { texture->destroy(); return true; }
+RwTexture *RwTextureAddRef(RwTexture *texture) { texture->refCount++; return texture; }
+// TODO
+RwBool RwTextureSetMipmapping(RwBool enable) { return true; }
+RwBool RwTextureGetMipmapping(void);
+// TODO
+RwBool RwTextureSetAutoMipmapping(RwBool enable) { return true; }
+RwBool RwTextureGetAutoMipmapping(void);
+RwBool RwTextureSetMipmapGenerationCallBack(RwTextureCallBackMipmapGeneration callback);
+RwTextureCallBackMipmapGeneration RwTextureGetMipmapGenerationCallBack(void);
+RwBool RwTextureSetMipmapNameCallBack(RwTextureCallBackMipmapName callback);
+RwTextureCallBackMipmapName RwTextureGetMipmapNameCallBack(void);
+RwBool RwTextureGenerateMipmapName(RwChar * name, RwChar * maskName, RwUInt8 mipLevel, RwInt32 format);
+RwBool RwTextureRasterGenerateMipmaps(RwRaster * raster, RwImage * image);
+RwTextureCallBackRead RwTextureGetReadCallBack(void);
+RwBool RwTextureSetReadCallBack(RwTextureCallBackRead fpCallBack);
+RwTexture *RwTextureSetName(RwTexture * texture, const RwChar * name) { strncpy(texture->name, name, 32); return texture; }
+RwTexture *RwTextureSetMaskName(RwTexture * texture, const RwChar * maskName);
+RwChar *RwTextureGetName(RwTexture *texture) { return texture->name; }
+RwChar *RwTextureGetMaskName(RwTexture *texture);
+RwTexture *RwTextureSetRaster(RwTexture * texture, RwRaster * raster) { texture->raster = raster; return texture; }
+RwTexture   *RwTextureRead(const RwChar * name, const RwChar * maskName) { return Texture::read(name, maskName); }
+RwRaster *RwTextureGetRaster(const RwTexture *texture) { return texture->raster; }
+RwInt32 RwTextureRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);
+RwInt32 RwTextureGetPluginOffset(RwUInt32 pluginID);
+RwBool RwTextureValidatePlugins(const RwTexture * texture);
+
+RwTexDictionary *RwTextureGetDictionary(RwTexture *texture);
+RwTexture *RwTextureSetFilterMode(RwTexture *texture, RwTextureFilterMode filtering) { texture->setFilter((Texture::FilterMode)filtering); return texture; }
+RwTextureFilterMode RwTextureGetFilterMode(const RwTexture *texture);
+RwTexture *RwTextureSetAddressing(RwTexture *texture, RwTextureAddressMode addressing) {
+	texture->setAddressU((Texture::Addressing)addressing);
+	texture->setAddressV((Texture::Addressing)addressing);
+	return texture;
+}
+RwTexture *RwTextureSetAddressingU(RwTexture *texture, RwTextureAddressMode addressing) {
+	texture->setAddressU((Texture::Addressing)addressing);
+	return texture;
+}
+RwTexture *RwTextureSetAddressingV(RwTexture *texture, RwTextureAddressMode addressing) {
+	texture->setAddressV((Texture::Addressing)addressing);
+	return texture;
+}
+RwTextureAddressMode RwTextureGetAddressing(const RwTexture *texture);
+RwTextureAddressMode RwTextureGetAddressingU(const RwTexture *texture);
+RwTextureAddressMode RwTextureGetAddressingV(const RwTexture *texture);
+
+// TODO
+void _rwD3D8TexDictionaryEnableRasterFormatConversion(bool enable) { }
+
+// hack for reading native textures
+RwBool rwNativeTextureHackRead(RwStream *stream, RwTexture **tex, RwInt32 size)
+	{ *tex = Texture::streamReadNative(stream); return *tex != nil; }
+
+
+
+
+
+RwTexDictionary *RwTexDictionaryCreate(void) { return TexDictionary::create(); }
+RwBool RwTexDictionaryDestroy(RwTexDictionary * dict) { dict->destroy(); return true; }
+RwTexture *RwTexDictionaryAddTexture(RwTexDictionary * dict, RwTexture * texture) { dict->add(texture); return texture; }
+//RwTexture *RwTexDictionaryRemoveTexture(RwTexture * texture);
+RwTexture *RwTexDictionaryFindNamedTexture(RwTexDictionary * dict, const RwChar * name) { return dict->find(name); }
+RwTexDictionary *RwTexDictionaryGetCurrent(void) { return TexDictionary::getCurrent(); }
+RwTexDictionary *RwTexDictionarySetCurrent(RwTexDictionary * dict) { TexDictionary::setCurrent(dict); return dict; }
+const RwTexDictionary *RwTexDictionaryForAllTextures(const RwTexDictionary * dict, RwTextureCallBack fpCallBack, void *pData) {
+	FORLIST(lnk, ((RwTexDictionary*)dict)->textures)
+		if(fpCallBack(Texture::fromDict(lnk), pData) == nil)
+			break;
+	return dict;
+}
+RwBool RwTexDictionaryForAllTexDictionaries(RwTexDictionaryCallBack fpCallBack, void *pData);
+RwInt32 RwTexDictionaryRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);
+RwInt32 RwTexDictionaryGetPluginOffset(RwUInt32 pluginID);
+RwBool RwTexDictionaryValidatePlugins(const RwTexDictionary * dict);
+RwUInt32 RwTexDictionaryStreamGetSize(const RwTexDictionary *texDict);
+RwTexDictionary *RwTexDictionaryStreamRead(RwStream *stream);
+const RwTexDictionary *RwTexDictionaryStreamWrite(const RwTexDictionary *texDict, RwStream *stream) {
+	((RwTexDictionary*)texDict)->streamWrite(stream);
+	return texDict;
+}
+
+
+
+
+
+RwStream *RwStreamOpen(RwStreamType type, RwStreamAccessType accessType, const void *pData) {
+	StreamFile *file;
+	StreamMemory *mem;
+	RwMemory *memargs;
+	const char *mode;
+
+	switch(accessType){
+	case rwSTREAMREAD: mode = "rb"; break;
+	case rwSTREAMWRITE: mode = "wb"; break;
+	case rwSTREAMAPPEND: mode = "ab"; break;
+	default: return nil;
+	}
+
+	switch(type){
+	case rwSTREAMFILENAME:
+		file = rwNewT(StreamFile, 1, 0);
+		if(file->open((char*)pData, mode))
+			return file;
+		rwFree(file);
+		return nil;
+	case rwSTREAMMEMORY:
+		memargs = (RwMemory*)pData;
+		mem = rwNewT(StreamMemory, 1, 0);
+		if(mem->open(memargs->start, memargs->length))
+			return mem;
+		rwFree(mem);
+		return nil;
+	default:
+		assert(0 && "unknown type");
+		return nil;
+	}
+}
+RwBool RwStreamClose(RwStream * stream, void *pData) { stream->close(); rwFree(stream); return true; }
+RwUInt32 RwStreamRead(RwStream * stream, void *buffer, RwUInt32 length) { return stream->read(buffer, length); }
+RwStream *RwStreamWrite(RwStream * stream, const void *buffer, RwUInt32 length) { stream->write(buffer, length); return stream; }
+RwStream *RwStreamSkip(RwStream * stream, RwUInt32 offset) { stream->seek(offset); return stream; }
+
+RwBool RwStreamFindChunk(RwStream *stream, RwUInt32 type, RwUInt32 *lengthOut, RwUInt32 *versionOut)
+	{ return findChunk(stream, type, lengthOut, versionOut); }
+
+
+
+void RwIm2DVertexSetCameraX(RwIm2DVertex *vert, RwReal camx) { }
+void RwIm2DVertexSetCameraY(RwIm2DVertex *vert, RwReal camy) { }
+void RwIm2DVertexSetCameraZ(RwIm2DVertex *vert, RwReal camz) { vert->setCameraZ(camz); }
+void RwIm2DVertexSetRecipCameraZ(RwIm2DVertex *vert, RwReal recipz) { vert->setRecipCameraZ(recipz); }
+void RwIm2DVertexSetScreenX(RwIm2DVertex *vert, RwReal scrnx) { vert->setScreenX(scrnx); }
+void RwIm2DVertexSetScreenY(RwIm2DVertex *vert, RwReal scrny) { vert->setScreenY(scrny); }
+void RwIm2DVertexSetScreenZ(RwIm2DVertex *vert, RwReal scrnz) { vert->setScreenZ(scrnz); }
+void RwIm2DVertexSetU(RwIm2DVertex *vert, RwReal texU, RwReal recipz) { vert->setU(texU, recipz); }
+void RwIm2DVertexSetV(RwIm2DVertex *vert, RwReal texV, RwReal recipz) { vert->setV(texV, recipz); }
+void RwIm2DVertexSetIntRGBA(RwIm2DVertex *vert, RwUInt8 red, RwUInt8 green, RwUInt8 blue, RwUInt8 alpha) { vert->setColor(red, green, blue, alpha); }
+
+RwReal RwIm2DGetNearScreenZ(void) { return im2d::GetNearZ(); }
+RwReal RwIm2DGetFarScreenZ(void) { return im2d::GetFarZ(); }
+RwBool RwIm2DRenderLine(RwIm2DVertex *vertices, RwInt32 numVertices, RwInt32 vert1, RwInt32 vert2)
+	{ im2d::RenderLine(vertices, numVertices, vert1, vert2); return true; }
+RwBool RwIm2DRenderTriangle(RwIm2DVertex *vertices, RwInt32 numVertices, RwInt32 vert1, RwInt32 vert2, RwInt32 vert3 )
+	{ im2d::RenderTriangle(vertices, numVertices, vert1, vert2, vert3); return true; }
+RwBool RwIm2DRenderPrimitive(RwPrimitiveType primType, RwIm2DVertex *vertices, RwInt32 numVertices)
+	{ im2d::RenderPrimitive((PrimitiveType)primType, vertices, numVertices); return true; }
+RwBool RwIm2DRenderIndexedPrimitive(RwPrimitiveType primType, RwIm2DVertex *vertices, RwInt32 numVertices, RwImVertexIndex *indices, RwInt32 numIndices)
+	{ im2d::RenderIndexedPrimitive((PrimitiveType)primType, vertices, numVertices, indices, numIndices); return true; }
+
+
+void RwIm3DVertexSetPos(RwIm3DVertex *vert, RwReal x, RwReal y, RwReal z) { vert->setX(x); vert->setY(y); vert->setZ(z); }
+void RwIm3DVertexSetU(RwIm3DVertex *vert, RwReal u) { vert->setU(u); }
+void RwIm3DVertexSetV(RwIm3DVertex *vert, RwReal v) { vert->setV(v); }
+void RwIm3DVertexSetRGBA(RwIm3DVertex *vert, RwUInt8 r, RwUInt8 g, RwUInt8 b, RwUInt8 a) { vert->setColor(r, g, b, a); }
+
+// WARNING: ignoring flags
+void  *RwIm3DTransform(RwIm3DVertex *pVerts, RwUInt32 numVerts, RwMatrix *ltm, RwUInt32 flags) { im3d::Transform(pVerts, numVerts, ltm); return pVerts; }
+RwBool RwIm3DEnd(void) { im3d::End(); return true; }
+RwBool RwIm3DRenderLine(RwInt32 vert1, RwInt32 vert2) {
+	RwImVertexIndex indices[2];
+	indices[0] = vert1;
+	indices[1] = vert2;
+	im3d::RenderIndexed((PrimitiveType)PRIMTYPELINELIST, indices, 2);
+	return true;
+}
+RwBool RwIm3DRenderTriangle(RwInt32 vert1, RwInt32 vert2, RwInt32 vert3);
+RwBool RwIm3DRenderIndexedPrimitive(RwPrimitiveType primType, RwImVertexIndex *indices, RwInt32 numIndices) { im3d::RenderIndexed((PrimitiveType)primType, indices, numIndices); return true; }
+RwBool RwIm3DRenderPrimitive(RwPrimitiveType primType);
+
+
+
+
+
+RwBool RwRenderStateSet(RwRenderState state, void *value)
+{
+	uint32 uival = (uintptr)value;
+	switch(state){
+	case rwRENDERSTATETEXTURERASTER: SetRenderState(TEXTURERASTER, uival); return true;
+	case rwRENDERSTATETEXTUREADDRESS: SetRenderState(TEXTUREADDRESS, uival); return true;
+	case rwRENDERSTATETEXTUREADDRESSU: SetRenderState(TEXTUREADDRESSU, uival); return true;
+	case rwRENDERSTATETEXTUREADDRESSV: SetRenderState(TEXTUREADDRESSV, uival); return true;
+	case rwRENDERSTATETEXTUREPERSPECTIVE: return true;
+	case rwRENDERSTATEZTESTENABLE: SetRenderState(ZTESTENABLE, uival); return true;
+	case rwRENDERSTATESHADEMODE: return true;
+	case rwRENDERSTATEZWRITEENABLE: SetRenderState(ZWRITEENABLE, uival); return true;
+	case rwRENDERSTATETEXTUREFILTER: SetRenderState(TEXTUREFILTER, uival); return true;
+	case rwRENDERSTATESRCBLEND: SetRenderState(SRCBLEND, uival); return true;
+	case rwRENDERSTATEDESTBLEND: SetRenderState(DESTBLEND, uival); return true;
+	case rwRENDERSTATEVERTEXALPHAENABLE: SetRenderState(VERTEXALPHA, uival); return true;
+	case rwRENDERSTATEBORDERCOLOR: return true;
+	case rwRENDERSTATEFOGENABLE: SetRenderState(FOGENABLE, uival); return true;
+	case rwRENDERSTATEFOGCOLOR: SetRenderState(FOGCOLOR, uival); return true;
+	case rwRENDERSTATEFOGTYPE: return true;
+	case rwRENDERSTATEFOGDENSITY: return true;
+	case rwRENDERSTATEFOGTABLE: return true;
+	case rwRENDERSTATEALPHAPRIMITIVEBUFFER: return true;
+	case rwRENDERSTATECULLMODE: SetRenderState(CULLMODE, uival); return true;
+
+	// all unsupported
+	case rwRENDERSTATESTENCILENABLE:
+	case rwRENDERSTATESTENCILFAIL:
+	case rwRENDERSTATESTENCILZFAIL:
+	case rwRENDERSTATESTENCILPASS:
+	case rwRENDERSTATESTENCILFUNCTION:
+	case rwRENDERSTATESTENCILFUNCTIONREF:
+	case rwRENDERSTATESTENCILFUNCTIONMASK:
+	case rwRENDERSTATESTENCILFUNCTIONWRITEMASK:
+	default:
+		return true;
+	}
+}
+
+
+static EngineOpenParams openParams;
+// WARNING: unused parameters
+RwBool RwEngineInit(RwMemoryFunctions *memFuncs, RwUInt32 initFlags, RwUInt32 resArenaSize) { Engine::init(); return true; }
+// TODO: this is platform dependent
+RwBool RwEngineOpen(RwEngineOpenParams *initParams) {
+	openParams.window = (HWND)initParams->displayID;
+	return Engine::open(&openParams);
+}
+RwBool RwEngineStart(void) { return Engine::start(); }
+RwBool RwEngineStop(void) { Engine::stop(); return true; }
+RwBool RwEngineClose(void) { Engine::close(); return true; }
+RwBool RwEngineTerm(void) { Engine::term(); return true; }
+RwInt32 RwEngineRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor initCB, RwPluginObjectDestructor termCB);
+RwInt32 RwEngineGetPluginOffset(RwUInt32 pluginID);
+RwInt32 RwEngineGetNumSubSystems(void) { return Engine::getNumSubSystems(); }
+RwSubSystemInfo *RwEngineGetSubSystemInfo(RwSubSystemInfo *subSystemInfo, RwInt32 subSystemIndex)
+	{ return Engine::getSubSystemInfo(subSystemInfo, subSystemIndex); }
+RwInt32 RwEngineGetCurrentSubSystem(void) { return Engine::getCurrentSubSystem(); }
+RwBool RwEngineSetSubSystem(RwInt32 subSystemIndex) { return Engine::setSubSystem(subSystemIndex); }
+RwInt32 RwEngineGetNumVideoModes(void) { return Engine::getNumVideoModes(); }
+RwVideoMode *RwEngineGetVideoModeInfo(RwVideoMode *modeinfo, RwInt32 modeIndex)
+	{ return Engine::getVideoModeInfo(modeinfo, modeIndex); }
+RwInt32 RwEngineGetCurrentVideoMode(void) { return Engine::getCurrentVideoMode(); }
+RwBool RwEngineSetVideoMode(RwInt32 modeIndex) { return Engine::setVideoMode(modeIndex); }
+RwInt32 RwEngineGetTextureMemorySize(void);
+RwInt32 RwEngineGetMaxTextureSize(void);
+
+
+
+// TODO
+void RwD3D8EngineSetRefreshRate(RwUInt32 refreshRate) {}
+RwBool RwD3D8DeviceSupportsDXTTexture(void) { return true; }
+
+
+
+RpMaterial *RpMaterialCreate(void) { return Material::create(); }
+RwBool RpMaterialDestroy(RpMaterial *material) { material->destroy(); return true; }
+//RpMaterial *RpMaterialClone(RpMaterial *material);
+RpMaterial *RpMaterialSetTexture(RpMaterial *material, RwTexture *texture) { material->setTexture(texture); return material; }
+//RpMaterial *RpMaterialAddRef(RpMaterial *material);
+RwTexture *RpMaterialGetTexture(const RpMaterial *material) { return material->texture; }
+RpMaterial *RpMaterialSetColor(RpMaterial *material, const RwRGBA *color) { material->color = *color; return material; }
+const RwRGBA *RpMaterialGetColor(const RpMaterial *material) { return &material->color; }
+RpMaterial *RpMaterialSetSurfaceProperties(RpMaterial *material, const RwSurfaceProperties *surfaceProperties);
+const RwSurfaceProperties *RpMaterialGetSurfaceProperties(const RpMaterial *material) { return &material->surfaceProps; }
+//RwInt32 RpMaterialRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);
+//RwInt32 RpMaterialRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB);
+//RwInt32 RpMaterialSetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB);
+//RwInt32 RpMaterialGetPluginOffset(RwUInt32 pluginID);
+//RwBool RpMaterialValidatePlugins(const RpMaterial *material);
+//RwUInt32 RpMaterialStreamGetSize(const RpMaterial *material);
+//RpMaterial *RpMaterialStreamRead(RwStream *stream);
+//const RpMaterial *RpMaterialStreamWrite(const RpMaterial *material, RwStream *stream);
+//RpMaterialChunkInfo *_rpMaterialChunkInfoRead(RwStream *stream,  RpMaterialChunkInfo *materialChunkInfo, RwInt32 *bytesRead);
+
+
+
+
+
+RwReal RpLightGetRadius(const RpLight *light) { return light->radius; }
+//const RwRGBAReal *RpLightGetColor(const RpLight *light);
+RpLight *RpLightSetFrame(RpLight *light, RwFrame *frame) { light->setFrame(frame); return light; }
+RwFrame *RpLightGetFrame(const RpLight *light) { return light->getFrame(); }
+//RpLightType RpLightGetType(const RpLight *light);
+RpLight *RpLightSetFlags(RpLight *light, RwUInt32 flags) { light->setFlags(flags); return light; }
+//RwUInt32 RpLightGetFlags(const RpLight *light);
+RpLight *RpLightCreate(RwInt32 type) { return rw::Light::create(type); }
+RwBool RpLightDestroy(RpLight *light) { light->destroy(); return true; }
+RpLight *RpLightSetRadius(RpLight *light, RwReal radius) { light->radius = radius; return light; }
+RpLight *RpLightSetColor(RpLight *light, const RwRGBAReal *color) { light->setColor(color->red, color->green, color->blue); return light; }
+//RwReal RpLightGetConeAngle(const RpLight *light);
+//RpLight *RpLightSetConeAngle(RpLight * ight, RwReal angle);
+//RwUInt32 RpLightStreamGetSize(const RpLight *light);
+//RpLight *RpLightStreamRead(RwStream *stream);
+//const RpLight *RpLightStreamWrite(const RpLight *light, RwStream *stream);
+//RpLightChunkInfo *_rpLightChunkInfoRead(RwStream *stream, RpLightChunkInfo *lightChunkInfo, RwInt32 *bytesRead);
+//RwInt32 RpLightRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);
+//RwInt32 RpLightRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB);
+//RwInt32 RpLightSetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB);
+//RwInt32 RpLightGetPluginOffset(RwUInt32 pluginID);
+//RwBool RpLightValidatePlugins(const RpLight * light);
+
+
+
+
+
+RpGeometry  *RpGeometryCreate(RwInt32 numVert, RwInt32 numTriangles, RwUInt32 format) { return Geometry::create(numVert, numTriangles, format); }
+RwBool RpGeometryDestroy(RpGeometry *geometry) { geometry->destroy(); return true; }
+RpGeometry *_rpGeometryAddRef(RpGeometry *geometry);
+// TODO: implement this
+RpGeometry  *RpGeometryLock(RpGeometry *geometry, RwInt32 lockMode) { return geometry; }
+RpGeometry  *RpGeometryUnlock(RpGeometry *geometry) { return geometry; }
+RpGeometry  *RpGeometryTransform(RpGeometry *geometry, const RwMatrix *matrix);
+RpGeometry  *RpGeometryCreateSpace(RwReal radius);
+RpMorphTarget  *RpMorphTargetSetBoundingSphere(RpMorphTarget *morphTarget, const RwSphere *boundingSphere) { morphTarget->boundingSphere = *boundingSphere; return morphTarget; }
+RwSphere  *RpMorphTargetGetBoundingSphere(RpMorphTarget *morphTarget) { return &morphTarget->boundingSphere; }
+const RpMorphTarget  *RpMorphTargetCalcBoundingSphere(const RpMorphTarget *morphTarget, RwSphere *boundingSphere) { *boundingSphere = morphTarget->calculateBoundingSphere(); return morphTarget; }
+RwInt32 RpGeometryAddMorphTargets(RpGeometry *geometry, RwInt32 mtcount);
+RwInt32 RpGeometryAddMorphTarget(RpGeometry *geometry);
+RpGeometry  *RpGeometryRemoveMorphTarget(RpGeometry *geometry, RwInt32 morphTarget);
+RwInt32 RpGeometryGetNumMorphTargets(const RpGeometry *geometry);
+RpMorphTarget  *RpGeometryGetMorphTarget(const RpGeometry *geometry, RwInt32 morphTarget) { return &geometry->morphTargets[morphTarget]; }
+RwRGBA  *RpGeometryGetPreLightColors(const RpGeometry *geometry) { return geometry->colors; }
+RwTexCoords  *RpGeometryGetVertexTexCoords(const RpGeometry *geometry, RwTextureCoordinateIndex uvIndex) { return geometry->texCoords[uvIndex]; }
+RwInt32 RpGeometryGetNumTexCoordSets(const RpGeometry *geometry) { return geometry->numTexCoordSets; }
+RwInt32 RpGeometryGetNumVertices (const RpGeometry *geometry) { return geometry->numVertices; }
+RwV3d  *RpMorphTargetGetVertices(const RpMorphTarget *morphTarget) { return morphTarget->vertices; }
+RwV3d  *RpMorphTargetGetVertexNormals(const RpMorphTarget *morphTarget) { return morphTarget->normals; }
+RpTriangle  *RpGeometryGetTriangles(const RpGeometry *geometry) { return geometry->triangles; }
+RwInt32 RpGeometryGetNumTriangles(const RpGeometry *geometry) { return geometry->numTriangles; }
+RpMaterial  *RpGeometryGetMaterial(const RpGeometry *geometry, RwInt32 matNum) { return geometry->matList.materials[matNum]; }
+const RpGeometry  *RpGeometryTriangleSetVertexIndices(const RpGeometry *geometry, RpTriangle *triangle, RwUInt16 vert1, RwUInt16 vert2, RwUInt16 vert3)
+	{ triangle->v[0] = vert1; triangle->v[1] = vert2; triangle->v[2] = vert3; return geometry; }
+RpGeometry  *RpGeometryTriangleSetMaterial(RpGeometry *geometry, RpTriangle *triangle, RpMaterial *material) {
+	int id = geometry->matList.findIndex(material);
+	if(id < 0)
+		id = geometry->matList.appendMaterial(material);
+	if(id < 0)
+		return nil;
+	triangle->matId = id;
+	return geometry;
+}
+const RpGeometry  *RpGeometryTriangleGetVertexIndices(const RpGeometry *geometry, const RpTriangle *triangle, RwUInt16 *vert1, RwUInt16 *vert2, RwUInt16 *vert3);
+RpMaterial   *RpGeometryTriangleGetMaterial(const RpGeometry *geometry, const RpTriangle *triangle);
+RwInt32 RpGeometryGetNumMaterials(const RpGeometry *geometry);
+RpGeometry  *RpGeometryForAllMaterials(RpGeometry *geometry, RpMaterialCallBack fpCallBack, void *pData) {
+	int i;
+	for(i = 0; i < geometry->matList.numMaterials; i++)
+		if(fpCallBack(geometry->matList.materials[i], pData) == nil)
+			break;
+	return geometry;
+}
+//const RpGeometry  *RpGeometryForAllMeshes(const RpGeometry *geometry, RpMeshCallBack fpCallBack, void *pData);
+RwInt32 RpGeometryRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);
+RwInt32 RpGeometryRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB);
+RwInt32 RpGeometrySetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB);
+RwInt32 RpGeometryGetPluginOffset(RwUInt32 pluginID);
+RwBool RpGeometryValidatePlugins(const RpGeometry *geometry);
+RwUInt32 RpGeometryStreamGetSize(const RpGeometry *geometry);
+const RpGeometry  *RpGeometryStreamWrite(const RpGeometry *geometry, RwStream *stream);
+RpGeometry  *RpGeometryStreamRead(RwStream *stream) { return Geometry::streamRead(stream); }
+//RpGeometryChunkInfo *_rpGeometryChunkInfoRead(RwStream *stream, RpGeometryChunkInfo *geometryChunkInfo, RwInt32 *bytesRead);
+RwUInt32 RpGeometryGetFlags(const RpGeometry *geometry) { return geometry->flags; }
+RpGeometry  *RpGeometrySetFlags(RpGeometry *geometry, RwUInt32 flags) { geometry->flags = flags; return geometry; }
+const RwSurfaceProperties *_rpGeometryGetSurfaceProperties(const RpGeometry *geometry);
+RpGeometry *_rpGeometrySetSurfaceProperties(RpGeometry *geometry, const RwSurfaceProperties *surfaceProperties);
+
+
+
+
+
+RwFrame *RpClumpGetFrame(const RpClump * clump) { return clump->getFrame(); }
+RpClump *RpClumpSetFrame(RpClump * clump, RwFrame * frame) { clump->setFrame(frame); return clump; }
+RpClump *RpClumpForAllAtomics(RpClump * clump, RpAtomicCallBack callback, void *pData) {
+	FORLIST(lnk, clump->atomics)
+		if(callback(Atomic::fromClump(lnk), pData) == nil)
+			break;
+	return clump;
+}
+RpClump *RpClumpForAllLights(RpClump * clump, RpLightCallBack callback, void *pData);
+RpClump *RpClumpForAllCameras(RpClump * clump, RwCameraCallBack callback, void *pData);
+//RpClump *RpClumpCreateSpace(const RwV3d * position, RwReal radius);
+RpClump *RpClumpRender(RpClump * clump) { clump->render(); return clump; }
+RpClump *RpClumpRemoveAtomic(RpClump * clump, RpAtomic * atomic) { atomic->removeFromClump(); return clump; }
+RpClump *RpClumpAddAtomic(RpClump * clump, RpAtomic * atomic) { clump->addAtomic(atomic); return clump; }
+//RpClump *RpClumpRemoveLight(RpClump * clump, RpLight * light);
+//RpClump *RpClumpAddLight(RpClump * clump, RpLight * light);
+//RpClump *RpClumpRemoveCamera(RpClump * clump, RwCamera * camera);
+//RpClump *RpClumpAddCamera(RpClump * clump, RwCamera * camera);
+RwBool RpClumpDestroy(RpClump * clump) { clump->destroy(); return true; }
+RpClump *RpClumpCreate(void) { return rw::Clump::create(); }
+RpClump *RpClumpClone(RpClump * clump) { return clump->clone(); }
+//RpClump *RpClumpSetCallBack(RpClump * clump, RpClumpCallBack callback);
+//RpClumpCallBack RpClumpGetCallBack(const RpClump * clump);
+RwInt32 RpClumpGetNumAtomics(RpClump * clump) { return clump->countAtomics(); }
+//RwInt32 RpClumpGetNumLights(RpClump * clump);
+//RwInt32 RpClumpGetNumCameras(RpClump * clump);
+RpClump *RpClumpStreamRead(RwStream * stream) { return rw::Clump::streamRead(stream); }
+//RpClump *RpClumpStreamWrite(RpClump * clump, RwStream * stream);
+RwInt32 RpClumpRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB)
+	{ return Clump::registerPlugin(size, pluginID, constructCB, destructCB, (CopyConstructor)copyCB); }
+RwInt32 RpClumpRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack  readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB)
+	{ return Clump::registerPluginStream(pluginID, readCB, (StreamWrite)writeCB, (StreamGetSize)getSizeCB); }
+//RwInt32 RpClumpSetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB);
+//RwInt32 RpClumpGetPluginOffset(RwUInt32 pluginID);
+//RwBool RpClumpValidatePlugins(const RpClump * clump);
+
+
+
+RpAtomic *RpAtomicCreate(void) { return rw::Atomic::create(); }
+RwBool RpAtomicDestroy(RpAtomic * atomic) { atomic->destroy(); return true; }
+RpAtomic *RpAtomicClone(RpAtomic * atomic) { return atomic->clone(); }
+RpAtomic *RpAtomicSetFrame(RpAtomic * atomic, RwFrame * frame) { atomic->setFrame(frame); return atomic; }
+RpAtomic *RpAtomicSetGeometry(RpAtomic * atomic, RpGeometry * geometry, RwUInt32 flags) { atomic->setGeometry(geometry, flags); return atomic; }
+
+RwFrame *RpAtomicGetFrame(const RpAtomic * atomic) { return atomic->getFrame(); }
+RpAtomic *RpAtomicSetFlags(RpAtomic * atomic, RwUInt32 flags) { atomic->setFlags(flags); return atomic; }
+RwUInt32 RpAtomicGetFlags(const RpAtomic * atomic) { return atomic->getFlags(); }
+RwSphere *RpAtomicGetBoundingSphere(RpAtomic * atomic) { return &atomic->boundingSphere; }
+RpAtomic *RpAtomicRender(RpAtomic * atomic) { atomic->render(); return atomic; }
+RpClump *RpAtomicGetClump(const RpAtomic * atomic) { return atomic->clump; }
+//RpInterpolator *RpAtomicGetInterpolator(RpAtomic * atomic);
+RpGeometry *RpAtomicGetGeometry(const RpAtomic * atomic) { return atomic->geometry; }
+// WARNING: illegal cast
+void RpAtomicSetRenderCallBack(RpAtomic * atomic, RpAtomicCallBackRender callback) { atomic->setRenderCB((Atomic::RenderCB)callback); }
+RpAtomicCallBackRender RpAtomicGetRenderCallBack(const RpAtomic * atomic) { return (RpAtomicCallBackRender)atomic->renderCB; }
+//RwBool RpAtomicInstance(RpAtomic *atomic);
+//RwUInt32 RpAtomicStreamGetSize(RpAtomic * atomic);
+//RpAtomic *RpAtomicStreamRead(RwStream * stream);
+//RpAtomic *RpAtomicStreamWrite(RpAtomic * atomic, RwStream * stream);
+RwInt32 RpAtomicRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB)
+	{ return Atomic::registerPlugin(size, pluginID, constructCB, destructCB, (CopyConstructor)copyCB); }
+//RwInt32 RpAtomicRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB);
+//RwInt32 RpAtomicSetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB);
+//RwInt32 RpAtomicSetStreamRightsCallBack(RwUInt32 pluginID, RwPluginDataChunkRightsCallBack rightsCB);
+//RwInt32 RpAtomicGetPluginOffset(RwUInt32 pluginID);
+//RwBool RpAtomicValidatePlugins(const RpAtomic * atomic);
+
+RpAtomic *AtomicDefaultRenderCallBack(RpAtomic * atomic) { Atomic::defaultRenderCB(atomic); return atomic; }
+
+
+// TODO: this is extremely simplified
+RpWorld     *RpWorldCreate(RwBBox * boundingBox) { return World::create(); }
+RwBool       RpWorldDestroy(RpWorld * world) { world->destroy(); return true; }
+
+RwBool       RpWorldPluginAttach(void) {
+	registerMeshPlugin();
+	registerNativeDataPlugin();
+	registerAtomicRightsPlugin();
+	registerMaterialRightsPlugin();
+	return true;
+}
+
+RpWorld *RpWorldRemoveCamera(RpWorld *world, RwCamera *camera) { world->removeCamera(camera); return world; }
+RpWorld *RpWorldAddCamera(RpWorld *world, RwCamera *camera) { world->addCamera(camera); return world; }
+RpWorld *RwCameraGetWorld(const RwCamera *camera);
+RpWorld *RpWorldRemoveAtomic(RpWorld *world, RpAtomic *atomic);
+RpWorld *RpWorldAddAtomic(RpWorld *world, RpAtomic *atomic);
+RpWorld *RpAtomicGetWorld(const RpAtomic *atomic);
+RpWorld *RpWorldAddClump(RpWorld *world, RpClump *clump);
+RpWorld *RpWorldRemoveClump(RpWorld *world, RpClump *clump);
+RpWorld *RpClumpGetWorld(const RpClump *clump);
+RpWorld *RpWorldAddLight(RpWorld *world, RpLight *light) { world->addLight(light); return world; }
+RpWorld *RpWorldRemoveLight(RpWorld *world, RpLight *light) { world->removeLight(light); return world; }
+RpWorld *RpLightGetWorld(const RpLight *light);
+RwCamera *RwCameraForAllClumpsInFrustum(RwCamera *camera, void *data);
+RwCamera *RwCameraForAllClumpsNotInFrustum(RwCamera *camera, RwInt32 numClumps, void *data);
+
+
+
+
+RwBool RpMatFXPluginAttach( void ) { registerMatFXPlugin(); return true; }
+RpAtomic *RpMatFXAtomicEnableEffects( RpAtomic *atomic ) { MatFX::enableEffects(atomic); return atomic; }
+RpMaterial *RpMatFXMaterialSetEffects( RpMaterial *material, RpMatFXMaterialFlags flags ) { MatFX::setEffects(material, (uint32)flags); return material; }
+RpMaterial *RpMatFXMaterialSetupEnvMap( RpMaterial *material, RwTexture *texture, RwFrame *frame, RwBool useFrameBufferAlpha, RwReal coef ) {
+	MatFX *mfx = MatFX::get(material);
+	mfx->setEnvTexture(texture);
+	mfx->setEnvFrame(frame);
+	mfx->setEnvCoefficient(coef);
+	return material;
+}
+
+
+
+
+
+RwBool RpHAnimPluginAttach(void) {
+	registerHAnimPlugin();
+	return true;
+}
+
+RwBool RpHAnimFrameSetHierarchy(RwFrame *frame, RpHAnimHierarchy *hierarchy) { HAnimData::get(frame)->hierarchy = hierarchy; return true; }
+RpHAnimHierarchy *RpHAnimFrameGetHierarchy(RwFrame *frame) { return HAnimHierarchy::get(frame); }
+
+RwBool RpHAnimHierarchySetCurrentAnim(RpHAnimHierarchy *hierarchy, RpHAnimAnimation *anim) { hierarchy->currentAnim->setCurrentAnim(anim); return true; }
+RwBool RpHAnimHierarchyAddAnimTime(RpHAnimHierarchy *hierarchy, RwReal time) { hierarchy->currentAnim->addTime(time); return true; }
+
+RwBool RpHAnimHierarchyUpdateMatrices(RpHAnimHierarchy *hierarchy) { hierarchy->updateMatrices(); return true; }
+
+RpHAnimAnimation  *RpHAnimAnimationStreamRead(RwStream *stream) { return Animation::streamRead(stream); }
+
+
+
+
+
+
+RwBool RpSkinPluginAttach(void) {
+	registerSkinPlugin();
+	return true;
+}
+
+RpAtomic *RpSkinAtomicSetHAnimHierarchy( RpAtomic *atomic, RpHAnimHierarchy *hierarchy ) { Skin::setHierarchy(atomic, hierarchy); return atomic; }
+RpHAnimHierarchy *RpSkinAtomicGetHAnimHierarchy( const RpAtomic *atomic ) { return Skin::getHierarchy(atomic); }
+
+
+
+
+
+RwImage *RtBMPImageWrite(RwImage * image, const RwChar * imageName) { rw::writeBMP(image, imageName); return image; }
+RwImage *RtBMPImageRead(const RwChar * imageName) { return rw::readBMP(imageName); }
diff --git a/src/fakerw/rphanim.h b/src/fakerw/rphanim.h
new file mode 100644
index 00000000..665e03f8
--- /dev/null
+++ b/src/fakerw/rphanim.h
@@ -0,0 +1,20 @@
+#pragma once
+
+//struct RpHAnimHierarchy;
+typedef rw::HAnimHierarchy RpHAnimHierarchy;
+//struct RpHAnimAnimation;
+typedef rw::Animation RpHAnimAnimation;
+
+RwBool RpHAnimPluginAttach(void);
+
+RwBool RpHAnimFrameSetHierarchy(RwFrame *frame, RpHAnimHierarchy *hierarchy);
+RpHAnimHierarchy *RpHAnimFrameGetHierarchy(RwFrame *frame);
+
+RwBool RpHAnimHierarchySetCurrentAnim(RpHAnimHierarchy *hierarchy, RpHAnimAnimation *anim);
+RwBool RpHAnimHierarchySetCurrentAnimTime(RpHAnimHierarchy *hierarchy, RwReal time);
+RwBool RpHAnimHierarchySubAnimTime(RpHAnimHierarchy *hierarchy, RwReal time);
+RwBool RpHAnimHierarchyAddAnimTime(RpHAnimHierarchy *hierarchy, RwReal time);
+
+RwBool RpHAnimHierarchyUpdateMatrices(RpHAnimHierarchy *hierarchy);
+
+RpHAnimAnimation  *RpHAnimAnimationStreamRead(RwStream *stream);
diff --git a/src/fakerw/rpmatfx.h b/src/fakerw/rpmatfx.h
new file mode 100644
index 00000000..87c8fb2e
--- /dev/null
+++ b/src/fakerw/rpmatfx.h
@@ -0,0 +1,43 @@
+#pragma once
+
+enum RpMatFXMaterialFlags
+{
+	rpMATFXEFFECTNULL       = rw::MatFX::NOTHING,
+	rpMATFXEFFECTBUMPMAP    = rw::MatFX::BUMPMAP,
+	rpMATFXEFFECTENVMAP     = rw::MatFX::ENVMAP,
+	rpMATFXEFFECTBUMPENVMAP = rw::MatFX::BUMPENVMAP,
+	rpMATFXEFFECTDUAL       = rw::MatFX::DUAL,
+
+	rpMATFXEFFECTMAX,
+	rpMATFXNUMEFFECTS       = rpMATFXEFFECTMAX - 1,
+};
+
+RwBool RpMatFXPluginAttach( void );
+RpAtomic *RpMatFXAtomicEnableEffects( RpAtomic *atomic );
+RwBool RpMatFXAtomicQueryEffects( RpAtomic *atomic );
+//RpWorldSector *RpMatFXWorldSectorEnableEffects( RpWorldSector *worldSector );
+//RwBool RpMatFXWorldSectorQueryEffects( RpWorldSector *worldSector );
+RpMaterial *RpMatFXMaterialSetEffects( RpMaterial *material, RpMatFXMaterialFlags flags );
+RpMaterial *RpMatFXMaterialSetupBumpMap( RpMaterial *material, RwTexture *texture, RwFrame *frame, RwReal coef );
+RpMaterial *RpMatFXMaterialSetupEnvMap( RpMaterial *material, RwTexture *texture, RwFrame *frame, RwBool useFrameBufferAlpha, RwReal coef );
+RpMaterial *RpMatFXMaterialSetupDualTexture( RpMaterial *material, RwTexture *texture, RwBlendFunction srcBlendMode, RwBlendFunction dstBlendMode );
+RpMatFXMaterialFlags RpMatFXMaterialGetEffects( const RpMaterial *material );
+RpMaterial *RpMatFXMaterialSetBumpMapTexture( RpMaterial *material, RwTexture *texture );
+RpMaterial *RpMatFXMaterialSetBumpMapFrame( RpMaterial *material, RwFrame *frame );
+RpMaterial *RpMatFXMaterialSetBumpMapCoefficient( RpMaterial *material, RwReal coef );
+RwTexture *RpMatFXMaterialGetBumpMapTexture( const RpMaterial *material );
+RwTexture *RpMatFXMaterialGetBumpMapBumpedTexture( const RpMaterial *material );
+RwFrame *RpMatFXMaterialGetBumpMapFrame( const RpMaterial *material );
+RwReal RpMatFXMaterialGetBumpMapCoefficient( const RpMaterial *material );
+RpMaterial *RpMatFXMaterialSetEnvMapTexture( RpMaterial *material, RwTexture *texture );
+RpMaterial *RpMatFXMaterialSetEnvMapFrame( RpMaterial *material, RwFrame *frame );
+RpMaterial *RpMatFXMaterialSetEnvMapFrameBufferAlpha( RpMaterial *material, RwBool useFrameBufferAlpha );
+RpMaterial *RpMatFXMaterialSetEnvMapCoefficient( RpMaterial *material, RwReal coef );
+RwTexture *RpMatFXMaterialGetEnvMapTexture( const RpMaterial *material );
+RwFrame *RpMatFXMaterialGetEnvMapFrame( const RpMaterial *material );
+RwBool RpMatFXMaterialGetEnvMapFrameBufferAlpha( const RpMaterial *material );
+RwReal RpMatFXMaterialGetEnvMapCoefficient( const RpMaterial *material );
+RpMaterial *RpMatFXMaterialSetDualTexture( RpMaterial *material, RwTexture *texture );
+RpMaterial *RpMatFXMaterialSetDualBlendModes( RpMaterial *material, RwBlendFunction srcBlendMode, RwBlendFunction dstBlendMode );
+RwTexture *RpMatFXMaterialGetDualTexture( const RpMaterial *material );
+const RpMaterial *RpMatFXMaterialGetDualBlendModes( const RpMaterial *material, RwBlendFunction *srcBlendMode, RwBlendFunction *dstBlendMode );
diff --git a/src/fakerw/rpskin.h b/src/fakerw/rpskin.h
new file mode 100644
index 00000000..dd8551ae
--- /dev/null
+++ b/src/fakerw/rpskin.h
@@ -0,0 +1,8 @@
+#pragma once
+
+#include <rphanim.h>
+
+RwBool RpSkinPluginAttach(void);
+
+RpAtomic *RpSkinAtomicSetHAnimHierarchy( RpAtomic *atomic, RpHAnimHierarchy *hierarchy );
+RpHAnimHierarchy *RpSkinAtomicGetHAnimHierarchy( const RpAtomic *atomic );
diff --git a/src/fakerw/rpworld.h b/src/fakerw/rpworld.h
new file mode 100644
index 00000000..d2ac2454
--- /dev/null
+++ b/src/fakerw/rpworld.h
@@ -0,0 +1,336 @@
+#pragma once
+
+#define rpATOMIC rw::Atomic::ID
+#define rpCLUMP rw::Clump::ID
+
+/*
+ ***********************************************
+ *
+ * RpMaterial
+ *
+ ***********************************************
+ */
+
+//struct RpMaterial;
+typedef rw::Material RpMaterial;
+
+typedef RpMaterial *(*RpMaterialCallBack)(RpMaterial *material, void *data);
+
+RpMaterial *RpMaterialCreate(void);
+RwBool RpMaterialDestroy(RpMaterial *material);
+RpMaterial *RpMaterialClone(RpMaterial *material);
+RpMaterial *RpMaterialSetTexture(RpMaterial *material, RwTexture *texture);
+RpMaterial *RpMaterialAddRef(RpMaterial *material);
+RwTexture *RpMaterialGetTexture(const RpMaterial *material);
+RpMaterial *RpMaterialSetColor(RpMaterial *material, const RwRGBA *color);
+const RwRGBA *RpMaterialGetColor(const RpMaterial *material);
+RpMaterial *RpMaterialSetSurfaceProperties(RpMaterial *material, const RwSurfaceProperties *surfaceProperties);
+const RwSurfaceProperties *RpMaterialGetSurfaceProperties(const RpMaterial *material);
+RwInt32 RpMaterialRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);
+RwInt32 RpMaterialRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB);
+RwInt32 RpMaterialSetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB);
+RwInt32 RpMaterialGetPluginOffset(RwUInt32 pluginID);
+RwBool RpMaterialValidatePlugins(const RpMaterial *material);
+RwUInt32 RpMaterialStreamGetSize(const RpMaterial *material);
+RpMaterial *RpMaterialStreamRead(RwStream *stream);
+const RpMaterial *RpMaterialStreamWrite(const RpMaterial *material, RwStream *stream);
+//RpMaterialChunkInfo *_rpMaterialChunkInfoRead(RwStream *stream,  RpMaterialChunkInfo *materialChunkInfo, RwInt32 *bytesRead);
+
+
+/*
+ ***********************************************
+ *
+ * RpLight
+ *
+ ***********************************************
+ */
+
+//struct RpLight;
+typedef rw::Light RpLight;
+
+enum RpLightType
+{
+	rpNALIGHTTYPE = 0,
+	rpLIGHTDIRECTIONAL,
+	rpLIGHTAMBIENT,
+	rpLIGHTPOINT = 0x80,
+	rpLIGHTSPOT,
+	rpLIGHTSPOTSOFT,
+};
+
+enum RpLightFlag
+{
+	rpLIGHTLIGHTATOMICS = 0x01,
+	rpLIGHTLIGHTWORLD = 0x02,
+};
+
+typedef RpLight    *(*RpLightCallBack) (RpLight * light, void *data);
+
+RwReal RpLightGetRadius(const RpLight *light);
+const RwRGBAReal *RpLightGetColor(const RpLight *light);
+RpLight *RpLightSetFrame(RpLight *light, RwFrame *frame);
+RwFrame *RpLightGetFrame(const RpLight *light);
+RpLightType RpLightGetType(const RpLight *light);
+RpLight *RpLightSetFlags(RpLight *light, RwUInt32 flags);
+RwUInt32 RpLightGetFlags(const RpLight *light);
+RpLight *RpLightCreate(RwInt32 type);
+RwBool RpLightDestroy(RpLight *light);
+RpLight *RpLightSetRadius(RpLight *light, RwReal radius);
+RpLight *RpLightSetColor(RpLight *light, const RwRGBAReal *color);
+RwReal RpLightGetConeAngle(const RpLight *light);
+RpLight *RpLightSetConeAngle(RpLight * ight, RwReal angle);
+RwUInt32 RpLightStreamGetSize(const RpLight *light);
+RpLight *RpLightStreamRead(RwStream *stream);
+const RpLight *RpLightStreamWrite(const RpLight *light, RwStream *stream);
+//RpLightChunkInfo *_rpLightChunkInfoRead(RwStream *stream, RpLightChunkInfo *lightChunkInfo, RwInt32 *bytesRead);
+RwInt32 RpLightRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);
+RwInt32 RpLightRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB);
+RwInt32 RpLightSetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB);
+RwInt32 RpLightGetPluginOffset(RwUInt32 pluginID);
+RwBool RpLightValidatePlugins(const RpLight * light);
+
+/*
+ ***********************************************
+ *
+ * RpGeometry
+ *
+ ***********************************************
+ */
+
+typedef rw::Triangle RpTriangle;
+
+//struct RpGeometry;
+typedef rw::Geometry RpGeometry;
+//struct RpMorphTarget;
+typedef rw::MorphTarget RpMorphTarget;
+
+enum RpGeometryFlag
+{
+	rpGEOMETRYTRISTRIP  = rw::Geometry::TRISTRIP,
+	rpGEOMETRYPOSITIONS = rw::Geometry::POSITIONS,
+	rpGEOMETRYTEXTURED  = rw::Geometry::TEXTURED,
+	rpGEOMETRYPRELIT    = rw::Geometry::PRELIT,
+	rpGEOMETRYNORMALS   = rw::Geometry::NORMALS,
+	rpGEOMETRYLIGHT     = rw::Geometry::LIGHT,
+	rpGEOMETRYMODULATEMATERIALCOLOR = rw::Geometry::MODULATE,
+	rpGEOMETRYTEXTURED2 = rw::Geometry::TEXTURED2,
+	rpGEOMETRYNATIVE            = rw::Geometry::NATIVE,
+	rpGEOMETRYNATIVEINSTANCE    = rw::Geometry::NATIVEINSTANCE,
+	rpGEOMETRYFLAGSMASK         = 0x000000FF,
+	rpGEOMETRYNATIVEFLAGSMASK   = 0x0F000000,
+};
+
+enum RpGeometryLockMode
+{
+	rpGEOMETRYLOCKPOLYGONS   =   0x01,
+	rpGEOMETRYLOCKVERTICES   =   0x02,
+	rpGEOMETRYLOCKNORMALS    =   0x04,
+	rpGEOMETRYLOCKPRELIGHT   =   0x08,
+	rpGEOMETRYLOCKTEXCOORDS  =   0x10,
+	rpGEOMETRYLOCKTEXCOORDS1 =   0x10,
+	rpGEOMETRYLOCKTEXCOORDS2 =   0x20,
+	rpGEOMETRYLOCKTEXCOORDS3 =   0x40,
+	rpGEOMETRYLOCKTEXCOORDS4 =   0x80,
+	rpGEOMETRYLOCKTEXCOORDS5 = 0x0100,
+	rpGEOMETRYLOCKTEXCOORDS6 = 0x0200,
+	rpGEOMETRYLOCKTEXCOORDS7 = 0x0400,
+	rpGEOMETRYLOCKTEXCOORDS8 = 0x0800,
+	rpGEOMETRYLOCKTEXCOORDSALL = 0x0ff0,
+	rpGEOMETRYLOCKALL        = 0x0fff
+};
+
+RpGeometry  *RpGeometryCreate(RwInt32 numVert, RwInt32 numTriangles, RwUInt32 format);
+RwBool RpGeometryDestroy(RpGeometry *geometry);
+RpGeometry *_rpGeometryAddRef(RpGeometry *geometry);
+RpGeometry  *RpGeometryLock(RpGeometry *geometry, RwInt32 lockMode);
+RpGeometry  *RpGeometryUnlock(RpGeometry *geometry);
+RpGeometry  *RpGeometryTransform(RpGeometry *geometry, const RwMatrix *matrix);
+RpGeometry  *RpGeometryCreateSpace(RwReal radius);
+RpMorphTarget  *RpMorphTargetSetBoundingSphere(RpMorphTarget *morphTarget, const RwSphere *boundingSphere);
+RwSphere  *RpMorphTargetGetBoundingSphere(RpMorphTarget *morphTarget);
+const RpMorphTarget  *RpMorphTargetCalcBoundingSphere(const RpMorphTarget *morphTarget, RwSphere *boundingSphere);
+RwInt32 RpGeometryAddMorphTargets(RpGeometry *geometry, RwInt32 mtcount);
+RwInt32 RpGeometryAddMorphTarget(RpGeometry *geometry);
+RpGeometry  *RpGeometryRemoveMorphTarget(RpGeometry *geometry, RwInt32 morphTarget);
+RwInt32 RpGeometryGetNumMorphTargets(const RpGeometry *geometry);
+RpMorphTarget  *RpGeometryGetMorphTarget(const RpGeometry *geometry, RwInt32 morphTarget);
+RwRGBA  *RpGeometryGetPreLightColors(const RpGeometry *geometry);
+RwTexCoords  *RpGeometryGetVertexTexCoords(const RpGeometry *geometry, RwTextureCoordinateIndex uvIndex);
+RwInt32 RpGeometryGetNumTexCoordSets(const RpGeometry *geometry);
+RwInt32 RpGeometryGetNumVertices (const RpGeometry *geometry);
+RwV3d  *RpMorphTargetGetVertices(const RpMorphTarget *morphTarget);
+RwV3d  *RpMorphTargetGetVertexNormals(const RpMorphTarget *morphTarget);
+RpTriangle  *RpGeometryGetTriangles(const RpGeometry *geometry);
+RwInt32 RpGeometryGetNumTriangles(const RpGeometry *geometry);
+RpMaterial  *RpGeometryGetMaterial(const RpGeometry *geometry, RwInt32 matNum);
+const RpGeometry  *RpGeometryTriangleSetVertexIndices(const RpGeometry *geometry, RpTriangle *triangle, RwUInt16 vert1, RwUInt16 vert2, RwUInt16 vert3);
+RpGeometry  *RpGeometryTriangleSetMaterial(RpGeometry *geometry, RpTriangle *triangle, RpMaterial *material);
+const RpGeometry  *RpGeometryTriangleGetVertexIndices(const RpGeometry *geometry, const RpTriangle *triangle, RwUInt16 *vert1, RwUInt16 *vert2, RwUInt16 *vert3);
+RpMaterial   *RpGeometryTriangleGetMaterial(const RpGeometry *geometry, const RpTriangle *triangle);
+RwInt32 RpGeometryGetNumMaterials(const RpGeometry *geometry);
+RpGeometry  *RpGeometryForAllMaterials(RpGeometry *geometry, RpMaterialCallBack fpCallBack, void *pData);
+//const RpGeometry  *RpGeometryForAllMeshes(const RpGeometry *geometry, RpMeshCallBack fpCallBack, void *pData);
+RwInt32 RpGeometryRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);
+RwInt32 RpGeometryRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB);
+RwInt32 RpGeometrySetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB);
+RwInt32 RpGeometryGetPluginOffset(RwUInt32 pluginID);
+RwBool RpGeometryValidatePlugins(const RpGeometry *geometry);
+RwUInt32 RpGeometryStreamGetSize(const RpGeometry *geometry);
+const RpGeometry  *RpGeometryStreamWrite(const RpGeometry *geometry, RwStream *stream);
+RpGeometry  *RpGeometryStreamRead(RwStream *stream);
+//RpGeometryChunkInfo *_rpGeometryChunkInfoRead(RwStream *stream, RpGeometryChunkInfo *geometryChunkInfo, RwInt32 *bytesRead);
+RwUInt32 RpGeometryGetFlags(const RpGeometry *geometry);
+RpGeometry  *RpGeometrySetFlags(RpGeometry *geometry, RwUInt32 flags);
+const RwSurfaceProperties *_rpGeometryGetSurfaceProperties(const RpGeometry *geometry);
+RpGeometry *_rpGeometrySetSurfaceProperties(RpGeometry *geometry, const RwSurfaceProperties *surfaceProperties);
+
+
+/*
+ ***********************************************
+ *
+ * RpAtomic and RpClump
+ *
+ ***********************************************
+ */
+
+//struct RpAtomic;
+typedef rw::Atomic RpAtomic;
+
+enum RpAtomicFlag
+{
+	rpATOMICCOLLISIONTEST = 0x01,
+	rpATOMICRENDER = 0x04,
+};
+
+enum RpAtomicSetGeomFlag
+{
+	rpATOMICSAMEBOUNDINGSPHERE = 0x01,
+};
+
+typedef RpAtomic   *(*RpAtomicCallBack) (RpAtomic * atomic, void *data);
+typedef RpAtomic   *(*RpAtomicCallBackRender) (RpAtomic * atomic);
+
+
+//struct RpClump;
+typedef rw::Clump RpClump;
+
+struct RpClumpChunkInfo
+{
+	RwInt32             numAtomics;
+	RwInt32             numLights;
+	RwInt32             numCameras;
+};
+
+typedef RpClump    *(*RpClumpCallBack) (RpClump * clump, void *data);
+
+
+RpAtomic *AtomicDefaultRenderCallBack(RpAtomic * atomic);
+//void _rpAtomicResyncInterpolatedSphere(RpAtomic * atomic);
+//const RwSphere *RpAtomicGetWorldBoundingSphere(RpAtomic *  atomic);
+
+RwFrame *RpClumpGetFrame(const RpClump * clump);
+RpClump *RpClumpSetFrame(RpClump * clump, RwFrame * frame);
+RpClump *RpClumpForAllAtomics(RpClump * clump, RpAtomicCallBack callback, void *pData);
+RpClump *RpClumpForAllLights(RpClump * clump, RpLightCallBack callback, void *pData);
+RpClump *RpClumpForAllCameras(RpClump * clump, RwCameraCallBack callback, void *pData);
+RpClump *RpClumpCreateSpace(const RwV3d * position, RwReal radius);
+RpClump *RpClumpRender(RpClump * clump);
+RpClump *RpClumpRemoveAtomic(RpClump * clump, RpAtomic * atomic);
+RpClump *RpClumpAddAtomic(RpClump * clump, RpAtomic * atomic);
+RpClump *RpClumpRemoveLight(RpClump * clump, RpLight * light);
+RpClump *RpClumpAddLight(RpClump * clump, RpLight * light);
+RpClump *RpClumpRemoveCamera(RpClump * clump, RwCamera * camera);
+RpClump *RpClumpAddCamera(RpClump * clump, RwCamera * camera);
+RwBool RpClumpDestroy(RpClump * clump);
+RpClump *RpClumpCreate(void);
+RpClump *RpClumpClone(RpClump * clump);
+RpClump *RpClumpSetCallBack(RpClump * clump, RpClumpCallBack callback);
+RpClumpCallBack RpClumpGetCallBack(const RpClump * clump);
+RwInt32 RpClumpGetNumAtomics(RpClump * clump);
+RwInt32 RpClumpGetNumLights(RpClump * clump);
+RwInt32 RpClumpGetNumCameras(RpClump * clump);
+RwUInt32 RpClumpStreamGetSize(RpClump * clump);
+RpClump *RpClumpStreamRead(RwStream * stream);
+RpClump *RpClumpStreamWrite(RpClump * clump, RwStream * stream);
+RwInt32 RpClumpRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);
+RwInt32 RpClumpRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack  readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB);
+RwInt32 RpClumpSetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB);
+RwInt32 RpClumpGetPluginOffset(RwUInt32 pluginID);
+RwBool RpClumpValidatePlugins(const RpClump * clump);
+
+RpAtomic *RpAtomicCreate(void);
+RwBool RpAtomicDestroy(RpAtomic * atomic);
+RpAtomic *RpAtomicClone(RpAtomic * atomic);
+RpAtomic *RpAtomicSetFrame(RpAtomic * atomic, RwFrame * frame);
+RpAtomic *RpAtomicSetGeometry(RpAtomic * atomic, RpGeometry * geometry, RwUInt32 flags);
+
+RwFrame *RpAtomicGetFrame(const RpAtomic * atomic);
+RpAtomic *RpAtomicSetFlags(RpAtomic * atomic, RwUInt32 flags);
+RwUInt32 RpAtomicGetFlags(const RpAtomic * atomic);
+RwSphere *RpAtomicGetBoundingSphere(RpAtomic * atomic);
+RpAtomic *RpAtomicRender(RpAtomic * atomic);
+RpClump *RpAtomicGetClump(const RpAtomic * atomic);
+//RpInterpolator *RpAtomicGetInterpolator(RpAtomic * atomic);
+RpGeometry *RpAtomicGetGeometry(const RpAtomic * atomic);
+void RpAtomicSetRenderCallBack(RpAtomic * atomic, RpAtomicCallBackRender callback);
+RpAtomicCallBackRender RpAtomicGetRenderCallBack(const RpAtomic * atomic);
+RwBool RpAtomicInstance(RpAtomic *atomic);
+RwUInt32 RpAtomicStreamGetSize(RpAtomic * atomic);
+RpAtomic *RpAtomicStreamRead(RwStream * stream);
+RpAtomic *RpAtomicStreamWrite(RpAtomic * atomic, RwStream * stream);
+RwInt32 RpAtomicRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);
+RwInt32 RpAtomicRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB);
+RwInt32 RpAtomicSetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB);
+RwInt32 RpAtomicSetStreamRightsCallBack(RwUInt32 pluginID, RwPluginDataChunkRightsCallBack rightsCB);
+RwInt32 RpAtomicGetPluginOffset(RwUInt32 pluginID);
+RwBool RpAtomicValidatePlugins(const RpAtomic * atomic);
+
+//RwInt32 RpInterpolatorGetEndMorphTarget(const RpInterpolator * interpolator);
+//RwInt32 RpInterpolatorGetStartMorphTarget(const RpInterpolator * interpolator);
+//RwReal RpInterpolatorGetValue(const RpInterpolator * interpolator);
+//RwReal RpInterpolatorGetScale(const RpInterpolator * interpolator);
+//RpInterpolator *RpInterpolatorSetEndMorphTarget(RpInterpolator * interpolator, RwInt32 morphTarget, RpAtomic * atomic);
+//RpInterpolator *RpInterpolatorSetStartMorphTarget(RpInterpolator * interpolator, RwInt32 morphTarget, RpAtomic * atomic);
+//RpInterpolator *RpInterpolatorSetValue(RpInterpolator *  interpolator, RwReal value, RpAtomic *atomic);
+//RpInterpolator *RpInterpolatorSetScale(RpInterpolator * interpolator, RwReal scale, RpAtomic *atomic);
+
+
+RpClump *RpLightGetClump(const RpLight *light);
+RpClump *RwCameraGetClump(const RwCamera *camera);
+
+/*
+ ***********************************************
+ *
+ * RpWorld
+ *
+ ***********************************************
+ */
+
+//struct RpWorld;
+typedef rw::World RpWorld;
+
+RwBool       RpWorldDestroy(RpWorld * world);
+RpWorld     *RpWorldCreate(RwBBox * boundingBox);
+
+RwBool       RpWorldPluginAttach(void);
+
+RpWorld *RpWorldRemoveCamera(RpWorld *world, RwCamera *camera);
+RpWorld *RpWorldAddCamera(RpWorld *world, RwCamera *camera);
+RpWorld *RwCameraGetWorld(const RwCamera *camera);
+RpWorld *RpWorldRemoveAtomic(RpWorld *world, RpAtomic *atomic);
+RpWorld *RpWorldAddAtomic(RpWorld *world, RpAtomic *atomic);
+RpWorld *RpAtomicGetWorld(const RpAtomic *atomic);
+RpWorld *RpWorldAddClump(RpWorld *world, RpClump *clump);
+RpWorld *RpWorldRemoveClump(RpWorld *world, RpClump *clump);
+RpWorld *RpClumpGetWorld(const RpClump *clump);
+RpWorld *RpWorldAddLight(RpWorld *world, RpLight *light);
+RpWorld *RpWorldRemoveLight(RpWorld *world, RpLight *light);
+RpWorld *RpLightGetWorld(const RpLight *light);
+RwCamera *RwCameraForAllClumpsInFrustum(RwCamera *camera, void *data);
+RwCamera *RwCameraForAllClumpsNotInFrustum(RwCamera *camera, RwInt32 numClumps, void *data);
+//RwCamera *RwCameraForAllSectorsInFrustum(RwCamera *camera, RpWorldSectorCallBack callBack, void *pData);
+//RpLight *RpLightForAllWorldSectors(RpLight *light, RpWorldSectorCallBack callback, void *data);
+//RpAtomic *RpAtomicForAllWorldSectors(RpAtomic *atomic, RpWorldSectorCallBack callback, void *data);
+//RpWorldSector *RpWorldSectorForAllAtomics(RpWorldSector *sector, RpAtomicCallBack callback, void *data);
+//RpWorldSector *RpWorldSectorForAllCollisionAtomics(RpWorldSector *sector, RpAtomicCallBack callback, void *data);
+//RpWorldSector *RpWorldSectorForAllLights(RpWorldSector *sector, RpLightCallBack callback, void *data);
diff --git a/src/fakerw/rtbmp.h b/src/fakerw/rtbmp.h
new file mode 100644
index 00000000..896d276b
--- /dev/null
+++ b/src/fakerw/rtbmp.h
@@ -0,0 +1,4 @@
+#pragma once
+
+RwImage *RtBMPImageWrite(RwImage * image, const RwChar * imageName);
+RwImage *RtBMPImageRead(const RwChar * imageName);
diff --git a/src/fakerw/rwcore.h b/src/fakerw/rwcore.h
new file mode 100644
index 00000000..22e29737
--- /dev/null
+++ b/src/fakerw/rwcore.h
@@ -0,0 +1,413 @@
+#pragma once
+
+#define RWCORE_H	// needed by CVector
+
+#include <rw.h>
+
+#include <rwplcore.h>
+
+/*
+ ***********************************************
+ *
+ * RwIm2D and RwIm3D
+ *
+ ***********************************************
+ */
+
+typedef rw::RWDEVICE::Im2DVertex RwIm2DVertex;
+typedef rw::RWDEVICE::Im3DVertex RwIm3DVertex;
+typedef RwUInt16 RwImVertexIndex;
+
+enum RwIm3DTransformFlags
+{
+	rwIM3D_VERTEXUV      = 1,
+	rwIM3D_ALLOPAQUE     = 2,
+	rwIM3D_NOCLIP        = 4,
+	rwIM3D_VERTEXXYZ     = 8,
+	rwIM3D_VERTEXRGBA    = 16,
+};
+
+void RwIm2DVertexSetCameraX(RwIm2DVertex *vert, RwReal camx);
+void RwIm2DVertexSetCameraY(RwIm2DVertex *vert, RwReal camy);
+void RwIm2DVertexSetCameraZ(RwIm2DVertex *vert, RwReal camz);
+void RwIm2DVertexSetRecipCameraZ(RwIm2DVertex *vert, RwReal recipz);
+void RwIm2DVertexSetScreenX(RwIm2DVertex *vert, RwReal scrnx);
+void RwIm2DVertexSetScreenY(RwIm2DVertex *vert, RwReal scrny);
+void RwIm2DVertexSetScreenZ(RwIm2DVertex *vert, RwReal scrnz);
+void RwIm2DVertexSetU(RwIm2DVertex *vert, RwReal texU, RwReal recipz);
+void RwIm2DVertexSetV(RwIm2DVertex *vert, RwReal texV, RwReal recipz);
+void RwIm2DVertexSetIntRGBA(RwIm2DVertex *vert, RwUInt8 red, RwUInt8 green, RwUInt8 blue, RwUInt8 alpha);
+
+RwReal RwIm2DGetNearScreenZ(void);
+RwReal RwIm2DGetFarScreenZ(void);
+RwBool RwIm2DRenderLine(RwIm2DVertex *vertices, RwInt32 numVertices, RwInt32 vert1, RwInt32 vert2);
+RwBool RwIm2DRenderTriangle(RwIm2DVertex *vertices, RwInt32 numVertices, RwInt32 vert1, RwInt32 vert2, RwInt32 vert3 );
+RwBool RwIm2DRenderPrimitive(RwPrimitiveType primType, RwIm2DVertex *vertices, RwInt32 numVertices);
+RwBool RwIm2DRenderIndexedPrimitive(RwPrimitiveType primType, RwIm2DVertex *vertices, RwInt32 numVertices, RwImVertexIndex *indices, RwInt32 numIndices);
+
+
+void RwIm3DVertexSetPos(RwIm3DVertex *vert, RwReal x, RwReal y, RwReal z);
+void RwIm3DVertexSetU(RwIm3DVertex *vert, RwReal u);
+void RwIm3DVertexSetV(RwIm3DVertex *vert, RwReal v);
+void RwIm3DVertexSetRGBA(RwIm3DVertex *vert, RwUInt8 r, RwUInt8 g, RwUInt8 b, RwUInt8 a);
+
+void  *RwIm3DTransform(RwIm3DVertex *pVerts, RwUInt32 numVerts, RwMatrix *ltm, RwUInt32 flags);
+RwBool RwIm3DEnd(void);
+RwBool RwIm3DRenderLine(RwInt32 vert1, RwInt32 vert2);
+RwBool RwIm3DRenderTriangle(RwInt32 vert1, RwInt32 vert2, RwInt32 vert3);
+RwBool RwIm3DRenderIndexedPrimitive(RwPrimitiveType primType, RwImVertexIndex *indices, RwInt32 numIndices);
+RwBool RwIm3DRenderPrimitive(RwPrimitiveType primType);
+
+
+/*
+ ***********************************************
+ *
+ * RwRaster
+ *
+ ***********************************************
+ */
+
+//struct RwRaster;
+typedef rw::Raster RwRaster;
+
+enum RwRasterType
+{
+	rwRASTERTYPENORMAL = rw::Raster::NORMAL,
+	rwRASTERTYPEZBUFFER = rw::Raster::ZBUFFER,
+	rwRASTERTYPECAMERA = rw::Raster::CAMERA,
+	rwRASTERTYPETEXTURE = rw::Raster::TEXTURE,
+	rwRASTERTYPECAMERATEXTURE = rw::Raster::CAMERATEXTURE,
+	rwRASTERTYPEMASK = 0x07,
+	rwRASTERDONTALLOCATE = rw::Raster::DONTALLOCATE,
+};
+
+enum RwRasterFormat
+{
+	rwRASTERFORMATDEFAULT = rw::Raster::DEFAULT,
+	rwRASTERFORMAT1555 = rw::Raster::C1555,
+	rwRASTERFORMAT565 = rw::Raster::C565,
+	rwRASTERFORMAT4444 = rw::Raster::C4444,
+	rwRASTERFORMATLUM8 = rw::Raster::LUM8,
+	rwRASTERFORMAT8888 = rw::Raster::C8888,
+	rwRASTERFORMAT888 = rw::Raster::C888,
+	rwRASTERFORMAT16 = rw::Raster::D16,
+	rwRASTERFORMAT24 = rw::Raster::D24,
+	rwRASTERFORMAT32 = rw::Raster::D32,
+	rwRASTERFORMAT555 = rw::Raster::C555,
+
+	rwRASTERFORMATAUTOMIPMAP = rw::Raster::AUTOMIPMAP,
+	rwRASTERFORMATPAL8 = rw::Raster::PAL8,
+	rwRASTERFORMATPAL4 = rw::Raster::PAL4,
+	rwRASTERFORMATMIPMAP = rw::Raster::MIPMAP,
+
+	rwRASTERFORMATPIXELFORMATMASK = 0x0f00,
+	rwRASTERFORMATMASK = 0xff00
+};
+
+enum RwRasterFlipMode
+{
+	rwRASTERFLIPDONTWAIT = 0,
+	rwRASTERFLIPWAITVSYNC = 1,
+};
+
+RwRaster    *RwRasterCreate(RwInt32 width, RwInt32 height, RwInt32 depth, RwInt32 flags);
+RwBool       RwRasterDestroy(RwRaster * raster);
+RwInt32      RwRasterGetWidth(const RwRaster *raster);
+RwInt32      RwRasterGetHeight(const RwRaster *raster);
+RwInt32      RwRasterGetStride(const RwRaster *raster);
+RwInt32      RwRasterGetDepth(const RwRaster *raster);
+RwInt32      RwRasterGetFormat(const RwRaster *raster);
+RwInt32      RwRasterGetType(const RwRaster *raster);
+RwRaster    *RwRasterGetParent(const RwRaster *raster);
+RwRaster    *RwRasterGetOffset(RwRaster *raster,  RwInt16 *xOffset, RwInt16 *yOffset);
+RwInt32      RwRasterGetNumLevels(RwRaster * raster);
+RwRaster    *RwRasterSubRaster(RwRaster * subRaster, RwRaster * raster, RwRect * rect);
+RwRaster    *RwRasterRenderFast(RwRaster * raster, RwInt32 x, RwInt32 y);
+RwRaster    *RwRasterRender(RwRaster * raster, RwInt32 x, RwInt32 y);
+RwRaster    *RwRasterRenderScaled(RwRaster * raster, RwRect * rect);
+RwRaster    *RwRasterPushContext(RwRaster * raster);
+RwRaster    *RwRasterPopContext(void);
+RwRaster    *RwRasterGetCurrentContext(void);
+RwBool       RwRasterClear(RwInt32 pixelValue);
+RwBool       RwRasterClearRect(RwRect * rpRect, RwInt32 pixelValue);
+RwRaster    *RwRasterShowRaster(RwRaster * raster, void *dev, RwUInt32 flags);
+RwUInt8     *RwRasterLock(RwRaster * raster, RwUInt8 level, RwInt32 lockMode);
+RwRaster    *RwRasterUnlock(RwRaster * raster);
+RwUInt8     *RwRasterLockPalette(RwRaster * raster, RwInt32 lockMode);
+RwRaster    *RwRasterUnlockPalette(RwRaster * raster);
+RwInt32      RwRasterRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);
+RwInt32      RwRasterGetPluginOffset(RwUInt32 pluginID);
+RwBool       RwRasterValidatePlugins(const RwRaster * raster);
+
+
+/*
+ ***********************************************
+ *
+ * RwImage
+ *
+ ***********************************************
+ */
+
+//struct RwImage;
+typedef rw::Image RwImage;
+
+RwImage     *RwImageCreate(RwInt32 width, RwInt32 height, RwInt32 depth);
+RwBool       RwImageDestroy(RwImage * image);
+RwImage     *RwImageAllocatePixels(RwImage * image);
+RwImage     *RwImageFreePixels(RwImage * image);
+RwImage     *RwImageCopy(RwImage * destImage, const RwImage * sourceImage);
+RwImage     *RwImageResize(RwImage * image, RwInt32 width, RwInt32 height);
+RwImage     *RwImageApplyMask(RwImage * image, const RwImage * mask);
+RwImage     *RwImageMakeMask(RwImage * image);
+RwImage     *RwImageReadMaskedImage(const RwChar * imageName, const RwChar * maskname);
+RwImage     *RwImageRead(const RwChar * imageName);
+RwImage     *RwImageWrite(RwImage * image, const RwChar * imageName);
+RwChar      *RwImageGetPath(void);
+const RwChar *RwImageSetPath(const RwChar * path);
+RwImage     *RwImageSetStride(RwImage * image, RwInt32 stride);
+RwImage     *RwImageSetPixels(RwImage * image, RwUInt8 * pixels);
+RwImage     *RwImageSetPalette(RwImage * image, RwRGBA * palette);
+RwInt32      RwImageGetWidth(const RwImage * image);
+RwInt32      RwImageGetHeight(const RwImage * image);
+RwInt32      RwImageGetDepth(const RwImage * image);
+RwInt32      RwImageGetStride(const RwImage * image);
+RwUInt8     *RwImageGetPixels(const RwImage * image);
+RwRGBA      *RwImageGetPalette(const RwImage * image);
+RwUInt32     RwRGBAToPixel(RwRGBA * rgbIn, RwInt32 rasterFormat);
+RwRGBA      *RwRGBASetFromPixel(RwRGBA * rgbOut, RwUInt32 pixelValue, RwInt32 rasterFormat);
+RwBool       RwImageSetGamma(RwReal gammaValue);
+RwReal       RwImageGetGamma(void);
+RwImage     *RwImageGammaCorrect(RwImage * image);
+RwRGBA      *RwRGBAGammaCorrect(RwRGBA * rgb);
+RwInt32      RwImageRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);
+RwInt32      RwImageGetPluginOffset(RwUInt32 pluginID);
+RwBool       RwImageValidatePlugins(const RwImage * image);
+//RwBool       RwImageRegisterImageFormat(const RwChar * extension, RwImageCallBackRead imageRead, RwImageCallBackWrite imageWrite);
+const RwChar *RwImageFindFileType(const RwChar * imageName);
+RwInt32      RwImageStreamGetSize(const RwImage * image);
+RwImage     *RwImageStreamRead(RwStream * stream);
+const RwImage *RwImageStreamWrite(const RwImage * image, RwStream * stream);
+
+
+/*
+ ***********************************************
+ *
+ * RwTexture
+ *
+ ***********************************************
+ */
+
+//struct RwTexture;
+typedef rw::Texture RwTexture;
+//struct RwTexDictionary;
+typedef rw::TexDictionary RwTexDictionary;
+
+typedef RwTexture *(*RwTextureCallBackRead)(const RwChar *name, const RwChar *maskName);
+typedef RwTexture *(*RwTextureCallBack)(RwTexture *texture, void *pData);
+typedef RwTexDictionary *(*RwTexDictionaryCallBack)(RwTexDictionary *dict, void *data);
+typedef RwRaster *(*RwTextureCallBackMipmapGeneration)(RwRaster * raster, RwImage * image);
+typedef RwBool (*RwTextureCallBackMipmapName)(RwChar *name, RwChar *maskName, RwUInt8 mipLevel, RwInt32 format);
+
+RwTexture *RwTextureCreate(RwRaster * raster);
+RwBool RwTextureDestroy(RwTexture * texture);
+RwTexture *RwTextureAddRef(RwTexture *texture);
+RwBool RwTextureSetMipmapping(RwBool enable);
+RwBool RwTextureGetMipmapping(void);
+RwBool RwTextureSetAutoMipmapping(RwBool enable);
+RwBool RwTextureGetAutoMipmapping(void);
+RwBool RwTextureSetMipmapGenerationCallBack(RwTextureCallBackMipmapGeneration callback);
+RwTextureCallBackMipmapGeneration RwTextureGetMipmapGenerationCallBack(void);
+RwBool RwTextureSetMipmapNameCallBack(RwTextureCallBackMipmapName callback);
+RwTextureCallBackMipmapName RwTextureGetMipmapNameCallBack(void);
+RwBool RwTextureGenerateMipmapName(RwChar * name, RwChar * maskName, RwUInt8 mipLevel, RwInt32 format);
+RwBool RwTextureRasterGenerateMipmaps(RwRaster * raster, RwImage * image);
+RwTextureCallBackRead RwTextureGetReadCallBack(void);
+RwBool RwTextureSetReadCallBack(RwTextureCallBackRead fpCallBack);
+RwTexture *RwTextureSetName(RwTexture * texture, const RwChar * name);
+RwTexture *RwTextureSetMaskName(RwTexture * texture, const RwChar * maskName);
+RwChar *RwTextureGetName(RwTexture *texture);
+RwChar *RwTextureGetMaskName(RwTexture *texture);
+RwTexture *RwTextureSetRaster(RwTexture * texture, RwRaster * raster);
+RwTexture   *RwTextureRead(const RwChar * name, const RwChar * maskName);
+RwRaster *RwTextureGetRaster(const RwTexture *texture);
+RwInt32 RwTextureRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);
+RwInt32 RwTextureGetPluginOffset(RwUInt32 pluginID);
+RwBool RwTextureValidatePlugins(const RwTexture * texture);
+
+RwTexDictionary *RwTextureGetDictionary(RwTexture *texture);
+RwTexture *RwTextureSetFilterMode(RwTexture *texture, RwTextureFilterMode filtering);
+RwTextureFilterMode RwTextureGetFilterMode(const RwTexture *texture);
+RwTexture *RwTextureSetAddressing(RwTexture *texture, RwTextureAddressMode addressing);
+RwTexture *RwTextureSetAddressingU(RwTexture *texture, RwTextureAddressMode addressing);
+RwTexture *RwTextureSetAddressingV(RwTexture *texture, RwTextureAddressMode addressing);
+RwTextureAddressMode RwTextureGetAddressing(const RwTexture *texture);
+RwTextureAddressMode RwTextureGetAddressingU(const RwTexture *texture);
+RwTextureAddressMode RwTextureGetAddressingV(const RwTexture *texture);
+
+void _rwD3D8TexDictionaryEnableRasterFormatConversion(bool enable);
+
+// hack for reading native textures
+RwBool rwNativeTextureHackRead(RwStream *stream, RwTexture **tex, RwInt32 size);
+
+
+RwTexDictionary *RwTexDictionaryCreate(void);
+RwBool RwTexDictionaryDestroy(RwTexDictionary * dict);
+RwTexture *RwTexDictionaryAddTexture(RwTexDictionary * dict, RwTexture * texture);
+RwTexture *RwTexDictionaryRemoveTexture(RwTexture * texture);
+RwTexture *RwTexDictionaryFindNamedTexture(RwTexDictionary * dict, const RwChar * name);
+RwTexDictionary *RwTexDictionaryGetCurrent(void);
+RwTexDictionary *RwTexDictionarySetCurrent(RwTexDictionary * dict);
+const RwTexDictionary *RwTexDictionaryForAllTextures(const RwTexDictionary * dict, RwTextureCallBack fpCallBack, void *pData);
+RwBool RwTexDictionaryForAllTexDictionaries(RwTexDictionaryCallBack fpCallBack, void *pData);
+RwInt32 RwTexDictionaryRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);
+RwInt32 RwTexDictionaryGetPluginOffset(RwUInt32 pluginID);
+RwBool RwTexDictionaryValidatePlugins(const RwTexDictionary * dict);
+RwUInt32 RwTexDictionaryStreamGetSize(const RwTexDictionary *texDict);
+RwTexDictionary *RwTexDictionaryStreamRead(RwStream *stream);
+const RwTexDictionary *RwTexDictionaryStreamWrite(const RwTexDictionary *texDict, RwStream *stream);
+
+/* RwImage/RwRaster */
+
+RwImage *RwImageSetFromRaster(RwImage *image, RwRaster *raster);
+RwRaster *RwRasterSetFromImage(RwRaster *raster, RwImage *image);
+RwRGBA *RwRGBAGetRasterPixel(RwRGBA *rgbOut, RwRaster *raster, RwInt32 x, RwInt32 y);
+RwRaster *RwRasterRead(const RwChar *filename);
+RwRaster *RwRasterReadMaskedRaster(const RwChar *filename, const RwChar *maskname);
+RwImage *RwImageFindRasterFormat(RwImage *ipImage,RwInt32 nRasterType, RwInt32 *npWidth,RwInt32 *npHeight, RwInt32 *npDepth,RwInt32 *npFormat);
+
+
+/*
+ ***********************************************
+ *
+ * RwFrame
+ *
+ ***********************************************
+ */
+
+//struct RwFrame;
+typedef rw::Frame RwFrame;
+
+typedef RwFrame *(*RwFrameCallBack)(RwFrame *frame, void *data);
+
+
+RwFrame *RwFrameForAllObjects(RwFrame * frame, RwObjectCallBack callBack, void *data);
+RwFrame *RwFrameTranslate(RwFrame * frame, const RwV3d * v, RwOpCombineType combine);
+RwFrame *RwFrameRotate(RwFrame * frame, const RwV3d * axis, RwReal angle, RwOpCombineType combine);
+RwFrame *RwFrameScale(RwFrame * frame, const RwV3d * v, RwOpCombineType combine);
+RwFrame *RwFrameTransform(RwFrame * frame, const RwMatrix * m, RwOpCombineType combine);
+RwFrame *RwFrameOrthoNormalize(RwFrame * frame);
+RwFrame *RwFrameSetIdentity(RwFrame * frame);
+RwFrame *RwFrameCloneHierarchy(RwFrame * root);
+RwBool RwFrameDestroyHierarchy(RwFrame * frame);
+RwFrame *RwFrameForAllChildren(RwFrame * frame, RwFrameCallBack callBack, void *data);
+RwFrame *RwFrameRemoveChild(RwFrame * child);
+RwFrame *RwFrameAddChild(RwFrame * parent, RwFrame * child);
+RwFrame *RwFrameGetParent(const RwFrame * frame);
+RwFrame *RwFrameGetRoot(const RwFrame * frame);
+RwMatrix *RwFrameGetLTM(RwFrame * frame);
+RwMatrix *RwFrameGetMatrix(RwFrame * frame);
+RwFrame *RwFrameUpdateObjects(RwFrame * frame);
+RwFrame *RwFrameCreate(void);
+RwBool RwFrameInit(RwFrame *frame);
+RwBool RwFrameDeInit(RwFrame *frame);
+RwBool RwFrameDestroy(RwFrame * frame);
+void _rwFrameInit(RwFrame *frame);
+void _rwFrameDeInit(RwFrame *frame);
+RwBool RwFrameDirty(const RwFrame * frame);
+RwInt32 RwFrameCount(RwFrame * frame);
+RwBool RwFrameSetStaticPluginsSize(RwInt32 size);
+RwInt32 RwFrameRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);
+RwInt32 RwFrameGetPluginOffset(RwUInt32 pluginID);
+RwBool RwFrameValidatePlugins(const RwFrame * frame);
+RwFrame *_rwFrameCloneAndLinkClones(RwFrame * root);
+RwFrame *_rwFramePurgeClone(RwFrame *root);
+
+RwInt32 RwFrameRegisterPluginStream(RwUInt32 pluginID, RwPluginDataChunkReadCallBack readCB, RwPluginDataChunkWriteCallBack writeCB, RwPluginDataChunkGetSizeCallBack getSizeCB);
+RwInt32 RwFrameSetStreamAlwaysCallBack(RwUInt32 pluginID, RwPluginDataChunkAlwaysCallBack alwaysCB);
+
+typedef rw::FrameList_ rwFrameList;
+rwFrameList *rwFrameListInitialize(rwFrameList *frameList, RwFrame *frame);
+RwBool  rwFrameListFindFrame(const rwFrameList *frameList, const RwFrame *frame, RwInt32 *npIndex);
+rwFrameList *rwFrameListDeinitialize(rwFrameList *frameList);
+RwUInt32 rwFrameListStreamGetSize(const rwFrameList *frameList);
+rwFrameList *rwFrameListStreamRead(RwStream *stream, rwFrameList *fl);
+const rwFrameList *rwFrameListStreamWrite(const rwFrameList *frameList, RwStream *stream);
+
+
+typedef rw::BBox RwBBox;
+
+/*
+ ***********************************************
+ *
+ * RwCamera
+ *
+ ***********************************************
+ */
+
+//struct RwCamera;
+typedef rw::Camera RwCamera;
+
+typedef RwCamera *(*RwCameraCallBack)(RwCamera *camera, void *data);
+
+enum RwCameraClearMode
+{
+	rwCAMERACLEARIMAGE = 0x1,
+	rwCAMERACLEARZ = 0x2,
+	rwCAMERACLEARSTENCIL = 0x4
+};
+
+enum RwCameraProjection
+{
+	rwNACAMERAPROJECTION = 0,
+	rwPERSPECTIVE = 1,
+	rwPARALLEL = 2
+};
+
+enum RwFrustumTestResult
+{
+	rwSPHEREOUTSIDE = 0,
+	rwSPHEREBOUNDARY = 1,
+	rwSPHEREINSIDE = 2
+};
+
+RwCamera    *RwCameraBeginUpdate(RwCamera * camera);
+RwCamera    *RwCameraEndUpdate(RwCamera * camera);
+RwCamera    *RwCameraClear(RwCamera * camera, RwRGBA * colour, RwInt32 clearMode);
+RwCamera    *RwCameraShowRaster(RwCamera * camera, void *pDev, RwUInt32 flags);
+RwBool       RwCameraDestroy(RwCamera * camera);
+RwCamera    *RwCameraCreate(void);
+RwCamera    *RwCameraClone(RwCamera * camera);
+RwCamera    *RwCameraSetViewOffset(RwCamera *camera, const RwV2d *offset);
+RwCamera    *RwCameraSetViewWindow(RwCamera *camera, const RwV2d *viewWindow);
+RwCamera    *RwCameraSetProjection(RwCamera *camera, RwCameraProjection projection);
+RwCamera    *RwCameraSetNearClipPlane(RwCamera *camera, RwReal nearClip);
+RwCamera    *RwCameraSetFarClipPlane(RwCamera *camera, RwReal farClip);
+RwInt32      RwCameraRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor constructCB, RwPluginObjectDestructor destructCB, RwPluginObjectCopy copyCB);
+RwInt32      RwCameraGetPluginOffset(RwUInt32 pluginID);
+RwBool       RwCameraValidatePlugins(const RwCamera * camera);
+RwFrustumTestResult RwCameraFrustumTestSphere(const RwCamera * camera, const RwSphere * sphere);
+const RwV2d *RwCameraGetViewOffset(const RwCamera *camera);
+RwCamera    *RwCameraSetRaster(RwCamera *camera, RwRaster *raster);
+RwRaster    *RwCameraGetRaster(const RwCamera *camera);
+RwCamera    *RwCameraSetZRaster(RwCamera *camera, RwRaster *zRaster);
+RwRaster    *RwCameraGetZRaster(const RwCamera *camera);
+RwReal       RwCameraGetNearClipPlane(const RwCamera *camera);
+RwReal       RwCameraGetFarClipPlane(const RwCamera *camera);
+RwCamera    *RwCameraSetFogDistance(RwCamera *camera, RwReal fogDistance);
+RwReal       RwCameraGetFogDistance(const RwCamera *camera);
+RwCamera    *RwCameraGetCurrentCamera(void);
+RwCameraProjection RwCameraGetProjection(const RwCamera *camera);
+const RwV2d *RwCameraGetViewWindow(const RwCamera *camera);
+RwMatrix    *RwCameraGetViewMatrix(RwCamera *camera);
+RwCamera    *RwCameraSetFrame(RwCamera *camera, RwFrame *frame);
+RwFrame     *RwCameraGetFrame(const RwCamera *camera);
+
+
+/*
+ *
+ * D3D-engine specific stuff
+ *
+ */
+
+void RwD3D8EngineSetRefreshRate(RwUInt32 refreshRate);
+RwBool RwD3D8DeviceSupportsDXTTexture(void);
diff --git a/src/fakerw/rwplcore.h b/src/fakerw/rwplcore.h
new file mode 100644
index 00000000..79c745b6
--- /dev/null
+++ b/src/fakerw/rwplcore.h
@@ -0,0 +1,498 @@
+#pragma once
+
+typedef rw::int8 RwInt8;
+typedef rw::int16 RwInt16;
+typedef rw::int32 RwInt32;
+typedef rw::uint8 RwUInt8;
+typedef rw::uint16 RwUInt16;
+typedef rw::uint32 RwUInt32;
+typedef rw::float32 RwReal;
+
+typedef char RwChar;
+typedef RwInt32 RwBool;
+
+#define __RWUNUSED__
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef TRUE
+#define TRUE !FALSE
+#endif
+
+// used for unicode
+#define RWSTRING(x) x
+
+typedef rw::V2d RwV2d;
+
+typedef rw::V3d RwV3d;
+
+typedef rw::Rect RwRect;
+
+typedef rw::Sphere RwSphere;
+
+enum RwTextureCoordinateIndex
+{
+	rwNARWTEXTURECOORDINATEINDEX = 0,
+	rwTEXTURECOORDINATEINDEX0,
+	rwTEXTURECOORDINATEINDEX1,
+	rwTEXTURECOORDINATEINDEX2,
+	rwTEXTURECOORDINATEINDEX3,
+	rwTEXTURECOORDINATEINDEX4,
+	rwTEXTURECOORDINATEINDEX5,
+	rwTEXTURECOORDINATEINDEX6,
+	rwTEXTURECOORDINATEINDEX7,
+};
+
+typedef rw::TexCoords RwTexCoords;
+
+typedef rw::SurfaceProperties RwSurfaceProperties;
+
+#define RWRGBALONG(r,g,b,a)                                             \
+    ((RwUInt32) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)))
+
+
+#define MAKECHUNKID(vendorID, chunkID) (((vendorID & 0xFFFFFF) << 8) | (chunkID & 0xFF))
+
+enum RwCorePluginID
+{
+	rwID_NAOBJECT               = 0x00,
+	rwID_STRUCT                 = 0x01,
+	rwID_STRING                 = 0x02,
+	rwID_EXTENSION              = 0x03,
+	rwID_CAMERA                 = 0x05,
+	rwID_TEXTURE                = 0x06,
+	rwID_MATERIAL               = 0x07,
+	rwID_MATLIST                = 0x08,
+	rwID_ATOMICSECT             = 0x09,
+	rwID_PLANESECT              = 0x0A,
+	rwID_WORLD                  = 0x0B,
+	rwID_SPLINE                 = 0x0C,
+	rwID_MATRIX                 = 0x0D,
+	rwID_FRAMELIST              = 0x0E,
+	rwID_GEOMETRY               = 0x0F,
+	rwID_CLUMP                  = 0x10,
+	rwID_LIGHT                  = 0x12,
+	rwID_UNICODESTRING          = 0x13,
+	rwID_ATOMIC                 = 0x14,
+	rwID_TEXTURENATIVE          = 0x15,
+	rwID_TEXDICTIONARY          = 0x16,
+	rwID_ANIMDATABASE           = 0x17,
+	rwID_IMAGE                  = 0x18,
+	rwID_SKINANIMATION          = 0x19,
+	rwID_GEOMETRYLIST           = 0x1A,
+	rwID_HANIMANIMATION         = 0x1B,
+	rwID_TEAM                   = 0x1C,
+	rwID_CROWD                  = 0x1D,
+	rwID_DMORPHANIMATION        = 0x1E,
+	rwID_RIGHTTORENDER          = 0x1f,
+	rwID_MTEFFECTNATIVE         = 0x20,
+	rwID_MTEFFECTDICT           = 0x21,
+	rwID_TEAMDICTIONARY         = 0x22,
+	rwID_PITEXDICTIONARY        = 0x23,
+	rwID_TOC                    = 0x24,
+	rwID_PRTSTDGLOBALDATA       = 0x25,
+	/* Insert before MAX and increment MAX */
+	rwID_COREPLUGINIDMAX        = 0x26,
+};
+
+
+/*
+ ***********************************************
+ *
+ * RwObject
+ *
+ ***********************************************
+ */
+
+//struct RwObject;
+typedef rw::Object RwObject;
+
+typedef RwObject *(*RwObjectCallBack)(RwObject *object, void *data);
+
+RwUInt8 RwObjectGetType(const RwObject *obj);
+
+
+
+#define rwsprintf   sprintf
+#define rwvsprintf  vsprintf
+#define rwstrcpy    strcpy
+#define rwstrncpy   strncpy
+#define rwstrcat    strcat
+#define rwstrncat   strncat
+#define rwstrrchr   strrchr
+#define rwstrchr    strchr
+#define rwstrstr    strstr
+#define rwstrcmp    strcmp
+#define rwstricmp   stricmp
+#define rwstrlen    strlen
+#define rwstrupr    strupr
+#define rwstrlwr    strlwr
+#define rwstrtok    strtok
+#define rwsscanf    sscanf
+
+
+/*
+ ***********************************************
+ *
+ * Memory
+ *
+ ***********************************************
+ */
+
+struct RwMemoryFunctions;
+/*
+{
+	void *(*rwmalloc)(size_t size);
+	void  (*rwfree)(void *mem);
+	void *(*rwrealloc)(void *mem, size_t newSize);
+	void *(*rwcalloc)(size_t numObj, size_t sizeObj);
+};
+*/
+
+void *RwMalloc(size_t size);
+void  RwFree(void *mem);
+void *RwRealloc(void *mem, size_t newSize);
+void *RwCalloc(size_t numObj, size_t sizeObj);
+
+/*
+ ***********************************************
+ *
+ * RwStream
+ *
+ ***********************************************
+ */
+
+//struct RwStream;
+typedef rw::Stream RwStream;
+
+struct RwMemory
+{
+	RwUInt8     *start;
+	RwUInt32    length;
+};
+
+enum RwStreamType
+{
+	rwNASTREAM = 0,
+	rwSTREAMFILE,
+	rwSTREAMFILENAME,
+	rwSTREAMMEMORY,
+	rwSTREAMCUSTOM
+};
+
+enum RwStreamAccessType
+{
+	rwNASTREAMACCESS = 0,
+	rwSTREAMREAD,
+	rwSTREAMWRITE,
+	rwSTREAMAPPEND
+};
+
+RwStream *RwStreamOpen(RwStreamType type, RwStreamAccessType accessType, const void *pData);
+RwBool RwStreamClose(RwStream * stream, void *pData);
+RwUInt32 RwStreamRead(RwStream * stream, void *buffer, RwUInt32 length);
+RwStream *RwStreamWrite(RwStream * stream, const void *buffer, RwUInt32 length);
+RwStream *RwStreamSkip(RwStream * stream, RwUInt32 offset);
+
+
+/*
+ ***********************************************
+ *
+ * Plugin Registry 
+ *
+ ***********************************************
+ */
+
+#define RWPLUGINOFFSET(_type, _base, _offset)                   \
+   ((_type *)((RwUInt8 *)(_base) + (_offset)))
+
+typedef RwStream *(*RwPluginDataChunkWriteCallBack)(RwStream *stream, RwInt32 binaryLength, const void *object, RwInt32 offsetInObject, RwInt32 sizeInObject);
+typedef RwStream *(*RwPluginDataChunkReadCallBack)(RwStream *stream, RwInt32 binaryLength, void *object, RwInt32 offsetInObject, RwInt32 sizeInObject);
+typedef RwInt32(*RwPluginDataChunkGetSizeCallBack)(const void *object, RwInt32 offsetInObject, RwInt32 sizeInObject);
+typedef RwBool(*RwPluginDataChunkAlwaysCallBack)(void *object, RwInt32 offsetInObject, RwInt32 sizeInObject);
+typedef RwBool(*RwPluginDataChunkRightsCallBack)(void *object, RwInt32 offsetInObject, RwInt32 sizeInObject, RwUInt32 extraData);
+typedef void *(*RwPluginObjectConstructor)(void *object, RwInt32 offsetInObject, RwInt32 sizeInObject);
+typedef void *(*RwPluginObjectCopy)(void *dstObject, const void *srcObject, RwInt32 offsetInObject, RwInt32 sizeInObject);
+typedef void *(*RwPluginObjectDestructor)(void *object, RwInt32 offsetInObject, RwInt32 sizeInObject);
+
+/*
+ ***********************************************
+ *
+ * RwMatrix
+ *
+ ***********************************************
+ */
+
+typedef rw::Matrix RwMatrix;
+
+enum RwOpCombineType
+{
+	rwCOMBINEREPLACE = rw::COMBINEREPLACE,
+	rwCOMBINEPRECONCAT = rw::COMBINEPRECONCAT,
+	rwCOMBINEPOSTCONCAT = rw::COMBINEPOSTCONCAT
+};
+
+enum RwMatrixType
+{
+	rwMATRIXTYPENORMAL = rw::Matrix::TYPENORMAL,
+	rwMATRIXTYPEORTHOGANAL = rw::Matrix::TYPEORTHOGONAL,
+	rwMATRIXTYPEORTHONORMAL = rw::Matrix::TYPEORTHONORMAL,
+	rwMATRIXTYPEMASK = 0x00000003,
+};
+
+typedef rw::Matrix::Tolerance RwMatrixTolerance;
+
+RwBool RwMatrixDestroy(RwMatrix *mpMat);
+RwMatrix *RwMatrixCreate(void);
+void RwMatrixCopy(RwMatrix * dstMatrix, const RwMatrix * srcMatrix);
+void RwMatrixSetIdentity(RwMatrix * matrix);
+RwMatrix *RwMatrixMultiply(RwMatrix * matrixOut, const RwMatrix * MatrixIn1, const RwMatrix * matrixIn2);
+RwMatrix *RwMatrixTransform(RwMatrix * matrix, const RwMatrix * transform, RwOpCombineType combineOp);
+RwMatrix *RwMatrixOrthoNormalize(RwMatrix * matrixOut, const RwMatrix * matrixIn);
+RwMatrix *RwMatrixInvert(RwMatrix * matrixOut, const RwMatrix * matrixIn);
+RwMatrix *RwMatrixScale(RwMatrix * matrix, const RwV3d * scale, RwOpCombineType combineOp);
+RwMatrix *RwMatrixTranslate(RwMatrix * matrix, const RwV3d * translation, RwOpCombineType combineOp);
+RwMatrix *RwMatrixRotate(RwMatrix * matrix, const RwV3d * axis, RwReal angle, RwOpCombineType combineOp);
+RwMatrix *RwMatrixRotateOneMinusCosineSine(RwMatrix * matrix, const RwV3d * unitAxis, RwReal oneMinusCosine, RwReal sine, RwOpCombineType combineOp);
+const RwMatrix *RwMatrixQueryRotate(const RwMatrix * matrix, RwV3d * unitAxis, RwReal * angle, RwV3d * center);
+RwV3d *RwMatrixGetRight(RwMatrix * matrix);
+RwV3d *RwMatrixGetUp(RwMatrix * matrix);
+RwV3d *RwMatrixGetAt(RwMatrix * matrix);
+RwV3d *RwMatrixGetPos(RwMatrix * matrix);
+RwMatrix *RwMatrixUpdate(RwMatrix * matrix);
+RwMatrix *RwMatrixOptimize(RwMatrix * matrix, const RwMatrixTolerance *tolerance);
+
+/*
+ ***********************************************
+ *
+ * RwRGBA
+ *
+ ***********************************************
+ */
+
+typedef rw::RGBA RwRGBA;
+typedef rw::RGBAf RwRGBAReal;
+
+
+inline void RwRGBAAssign(RwRGBA *target, const RwRGBA *source) { *target = *source; }
+
+
+RwReal RwV3dNormalize(RwV3d * out, const RwV3d * in);
+RwReal RwV3dLength(const RwV3d * in);
+RwReal RwV2dLength(const RwV2d * in);
+RwReal RwV2dNormalize(RwV2d * out, const RwV2d * in);
+void RwV2dAssign(RwV2d * out, const RwV2d * ina);
+void RwV2dAdd(RwV2d * out, const RwV2d * ina, const RwV2d * inb);
+void RwV2dLineNormal(RwV2d * out, const RwV2d * ina, const RwV2d * inb);
+void RwV2dSub(RwV2d * out, const RwV2d * ina, const RwV2d * inb);
+void RwV2dPerp(RwV2d * out, const RwV2d * in);
+void RwV2dScale(RwV2d * out, const RwV2d * in, RwReal scalar);
+RwReal RwV2dDotProduct(const RwV2d * ina, const RwV2d * inb);
+void RwV3dAssign(RwV3d * out, const RwV3d * ina);
+void RwV3dAdd(RwV3d * out, const RwV3d * ina, const RwV3d * inb);
+void RwV3dSub(RwV3d * out, const RwV3d * ina, const RwV3d * inb);
+void RwV3dScale(RwV3d * out, const RwV3d * in, RwReal scalar);
+void RwV3dIncrementScaled(RwV3d * out,  const RwV3d * in, RwReal scalar);
+void RwV3dNegate(RwV3d * out, const RwV3d * in);
+RwReal RwV3dDotProduct(const RwV3d * ina, const RwV3d * inb);
+void RwV3dCrossProduct(RwV3d * out, const RwV3d * ina, const RwV3d * inb);
+RwV3d *RwV3dTransformPoints(RwV3d * pointsOut, const RwV3d * pointsIn, RwInt32 numPoints, const RwMatrix * matrix);
+RwV3d *RwV3dTransformVectors(RwV3d * vectorsOut, const RwV3d * vectorsIn, RwInt32 numPoints, const RwMatrix * matrix);
+
+
+/*
+ ***********************************************
+ *
+ * Render States
+ *
+ ***********************************************
+ */
+
+// not librw because we don't support all of them (yet?) - mapping in wrapper functions
+enum RwRenderState
+{
+	rwRENDERSTATENARENDERSTATE = 0,
+	rwRENDERSTATETEXTURERASTER,
+	rwRENDERSTATETEXTUREADDRESS,
+	rwRENDERSTATETEXTUREADDRESSU,
+	rwRENDERSTATETEXTUREADDRESSV,
+	rwRENDERSTATETEXTUREPERSPECTIVE,
+	rwRENDERSTATEZTESTENABLE,
+	rwRENDERSTATESHADEMODE,
+	rwRENDERSTATEZWRITEENABLE,
+	rwRENDERSTATETEXTUREFILTER,
+	rwRENDERSTATESRCBLEND,
+	rwRENDERSTATEDESTBLEND,
+	rwRENDERSTATEVERTEXALPHAENABLE,
+	rwRENDERSTATEBORDERCOLOR,
+	rwRENDERSTATEFOGENABLE,
+	rwRENDERSTATEFOGCOLOR,
+	rwRENDERSTATEFOGTYPE,
+	rwRENDERSTATEFOGDENSITY,
+	rwRENDERSTATEFOGTABLE,
+	rwRENDERSTATEALPHAPRIMITIVEBUFFER,
+	rwRENDERSTATECULLMODE,
+	rwRENDERSTATESTENCILENABLE,
+	rwRENDERSTATESTENCILFAIL,
+	rwRENDERSTATESTENCILZFAIL,
+	rwRENDERSTATESTENCILPASS,
+	rwRENDERSTATESTENCILFUNCTION,
+	rwRENDERSTATESTENCILFUNCTIONREF,
+	rwRENDERSTATESTENCILFUNCTIONMASK,
+	rwRENDERSTATESTENCILFUNCTIONWRITEMASK
+};
+
+// not supported - we only do gouraud
+enum RwShadeMode
+{
+	rwSHADEMODENASHADEMODE = 0,
+	rwSHADEMODEFLAT,
+	rwSHADEMODEGOURAUD
+};
+
+enum RwBlendFunction
+{
+	rwBLENDNABLEND = 0,
+	rwBLENDZERO = rw::BLENDZERO,
+	rwBLENDONE = rw::BLENDONE,
+	rwBLENDSRCCOLOR = rw::BLENDSRCCOLOR,
+	rwBLENDINVSRCCOLOR = rw::BLENDINVSRCCOLOR,
+	rwBLENDSRCALPHA = rw::BLENDSRCALPHA,
+	rwBLENDINVSRCALPHA = rw::BLENDINVSRCALPHA,
+	rwBLENDDESTALPHA = rw::BLENDDESTALPHA,
+	rwBLENDINVDESTALPHA = rw::BLENDINVDESTALPHA,
+	rwBLENDDESTCOLOR = rw::BLENDDESTCOLOR,
+	rwBLENDINVDESTCOLOR = rw::BLENDINVDESTCOLOR,
+	rwBLENDSRCALPHASAT = rw::BLENDSRCALPHASAT
+};
+
+// unsupported - we only need linear
+enum RwFogType
+{
+	rwFOGTYPENAFOGTYPE = 0,
+	rwFOGTYPELINEAR,
+	rwFOGTYPEEXPONENTIAL,
+	rwFOGTYPEEXPONENTIAL2
+};
+
+enum RwTextureFilterMode
+{
+	rwFILTERNAFILTERMODE = 0,
+	rwFILTERNEAREST = rw::Texture::NEAREST,
+	rwFILTERLINEAR = rw::Texture::LINEAR,
+	rwFILTERMIPNEAREST = rw::Texture::MIPNEAREST,
+	rwFILTERMIPLINEAR = rw::Texture::MIPLINEAR,
+	rwFILTERLINEARMIPNEAREST = rw::Texture::LINEARMIPNEAREST,
+	rwFILTERLINEARMIPLINEAR = rw::Texture::LINEARMIPLINEAR
+};
+
+enum RwTextureAddressMode
+{
+	rwTEXTUREADDRESSNATEXTUREADDRESS = 0,
+	rwTEXTUREADDRESSWRAP = rw::Texture::WRAP,
+	rwTEXTUREADDRESSMIRROR = rw::Texture::MIRROR,
+	rwTEXTUREADDRESSCLAMP = rw::Texture::CLAMP,
+	rwTEXTUREADDRESSBORDER = rw::Texture::BORDER
+};
+
+enum RwCullMode
+{
+	rwCULLMODENACULLMODE = 0,
+	rwCULLMODECULLNONE = rw::CULLNONE,
+	rwCULLMODECULLBACK = rw::CULLBACK,
+	rwCULLMODECULLFRONT = rw::CULLFRONT
+};
+
+enum RwPrimitiveType
+{
+	rwPRIMTYPENAPRIMTYPE = rw::PRIMTYPENONE,
+	rwPRIMTYPELINELIST = rw::PRIMTYPELINELIST,
+	rwPRIMTYPEPOLYLINE = rw::PRIMTYPEPOLYLINE,
+	rwPRIMTYPETRILIST = rw::PRIMTYPETRILIST,
+	rwPRIMTYPETRISTRIP = rw::PRIMTYPETRISTRIP,
+	rwPRIMTYPETRIFAN = rw::PRIMTYPETRIFAN,
+	rwPRIMTYPEPOINTLIST = rw::PRIMTYPEPOINTLIST
+};
+
+
+RwBool RwRenderStateGet(RwRenderState state, void *value);
+RwBool RwRenderStateSet(RwRenderState state, void *value);
+
+
+/*
+ ***********************************************
+ *
+ * Engine
+ *
+ ***********************************************
+ */
+
+struct RwEngineOpenParams
+{
+	void    *displayID;
+};
+
+typedef rw::SubSystemInfo RwSubSystemInfo;
+
+enum RwVideoModeFlag
+{
+	rwVIDEOMODEEXCLUSIVE  = rw::VIDEOMODEEXCLUSIVE,
+/*
+	rwVIDEOMODEINTERLACE  = 0x2,
+	rwVIDEOMODEFFINTERLACE  = 0x4,
+	rwVIDEOMODEFSAA0 = 0x8,
+	rwVIDEOMODEFSAA1 = 0x10
+*/
+};
+
+typedef rw::VideoMode RwVideoMode;
+
+#if 0
+struct RwFileFunctions
+{
+	rwFnFexist  rwfexist; /**< Pointer to fexist function */
+	rwFnFopen   rwfopen;  /**< Pointer to fopen function */
+	rwFnFclose  rwfclose; /**< Pointer to fclose function */
+	rwFnFread   rwfread;  /**< Pointer to fread function */
+	rwFnFwrite  rwfwrite; /**< Pointer to fwrite function */
+	rwFnFgets   rwfgets;  /**< Pointer to fgets function */
+	rwFnFputs   rwfputs;  /**< Pointer to puts function */
+	rwFnFeof    rwfeof;   /**< Pointer to feof function */
+	rwFnFseek   rwfseek;  /**< Pointer to fseek function */
+	rwFnFflush  rwfflush; /**< Pointer to fflush function */
+	rwFnFtell   rwftell;  /**< Pointer to ftell function */  
+};
+RwFileFunctions *RwOsGetFileInterface(void);
+#endif
+
+RwBool RwEngineInit(RwMemoryFunctions *memFuncs, RwUInt32 initFlags, RwUInt32 resArenaSize);
+RwInt32 RwEngineRegisterPlugin(RwInt32 size, RwUInt32 pluginID, RwPluginObjectConstructor initCB, RwPluginObjectDestructor termCB);
+RwInt32 RwEngineGetPluginOffset(RwUInt32 pluginID);
+RwBool RwEngineOpen(RwEngineOpenParams *initParams);
+RwBool RwEngineStart(void);
+RwBool RwEngineStop(void);
+RwBool RwEngineClose(void);
+RwBool RwEngineTerm(void);
+RwInt32 RwEngineGetNumSubSystems(void);
+RwSubSystemInfo *RwEngineGetSubSystemInfo(RwSubSystemInfo *subSystemInfo, RwInt32 subSystemIndex);
+RwInt32 RwEngineGetCurrentSubSystem(void);
+RwBool RwEngineSetSubSystem(RwInt32 subSystemIndex);
+RwInt32 RwEngineGetNumVideoModes(void);
+RwVideoMode *RwEngineGetVideoModeInfo(RwVideoMode *modeinfo, RwInt32 modeIndex);
+RwInt32 RwEngineGetCurrentVideoMode(void);
+RwBool RwEngineSetVideoMode(RwInt32 modeIndex);
+RwInt32 RwEngineGetTextureMemorySize(void);
+RwInt32 RwEngineGetMaxTextureSize(void);
+
+
+/*
+ ***********************************************
+ *
+ * Binary stream
+ *
+ ***********************************************
+ */
+
+RwBool RwStreamFindChunk(RwStream *stream, RwUInt32 type, RwUInt32 *lengthOut, RwUInt32 *versionOut);
diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp
index cee2b323..80d99e29 100644
--- a/src/peds/Ped.cpp
+++ b/src/peds/Ped.cpp
@@ -2244,7 +2244,7 @@ CPed::BuildPedLists(void)
 						if (nThreatReactionRangeMultiplier * 30.0f > dist) {
 							gapTempPedList[gnNumTempPedList] = ped;
 							gnNumTempPedList++;
-							assert(gnNumTempPedList < ARRAYSIZE(gapTempPedList));
+							assert(gnNumTempPedList < ARRAY_SIZE(gapTempPedList));
 						}
 					}
 				}
diff --git a/src/render/Console.cpp b/src/render/Console.cpp
index d4940955..545122b0 100644
--- a/src/render/Console.cpp
+++ b/src/render/Console.cpp
@@ -1,4 +1,5 @@
 #include "common.h"
+#include <stdarg.h>
 #include "patcher.h"
 #include "Console.h"
 #include "Font.h"
diff --git a/src/render/Shadows.h b/src/render/Shadows.h
index fb41ebbc..ced9f11b 100644
--- a/src/render/Shadows.h
+++ b/src/render/Shadows.h
@@ -6,7 +6,6 @@
 #define MAX_PERMAMENTSHADOWS 48
 
 
-struct RwTexture;
 class CEntity;
 
 enum eShadowType
diff --git a/src/render/Weather.cpp b/src/render/Weather.cpp
index b440e77c..7aa2778f 100644
--- a/src/render/Weather.cpp
+++ b/src/render/Weather.cpp
@@ -126,7 +126,7 @@ void CWeather::Update(void)
 		if (ForcedWeatherType >= 0)
 			NewWeatherType = ForcedWeatherType;
 		else {
-			WeatherTypeInList = (WeatherTypeInList + 1) % ARRAYSIZE(WeatherTypesList);
+			WeatherTypeInList = (WeatherTypeInList + 1) % ARRAY_SIZE(WeatherTypesList);
 			NewWeatherType = WeatherTypesList[WeatherTypeInList];
 #ifdef FIX_BUGS
 		}
diff --git a/src/rw/ClumpRead.cpp b/src/rw/ClumpRead.cpp
index c9f027e7..0bf62f32 100644
--- a/src/rw/ClumpRead.cpp
+++ b/src/rw/ClumpRead.cpp
@@ -153,7 +153,7 @@ RpClumpGtaStreamRead1(RwStream *stream)
 
 	if(!RwStreamFindChunk(stream, rwID_FRAMELIST, nil, &version))
 		return false;
-	if(_rwFrameListStreamRead(stream, &gFrameList) == nil)
+	if(rwFrameListStreamRead(stream, &gFrameList) == nil)
 		return false;
 
 	if(!RwStreamFindChunk(stream, rwID_GEOMETRYLIST, nil, &version)){
@@ -164,7 +164,7 @@ RpClumpGtaStreamRead1(RwStream *stream)
 		rwFrameListDeinitialize(&gFrameList);
 		return false;
 	}
-	streamPosition = stream->Type.memory.position;
+	streamPosition = STREAMPOS(stream);
 	return true;
 }
 
@@ -180,7 +180,7 @@ RpClumpGtaStreamRead2(RwStream *stream)
 	if(clump == nil)
 		return nil;
 
-	RwStreamSkip(stream, streamPosition - stream->Type.memory.position);
+	RwStreamSkip(stream, streamPosition - STREAMPOS(stream));
 
 	if(GeometryListStreamRead2(stream, &gGeomList) == nil){
 		GeometryListDeinitialize(&gGeomList);
diff --git a/src/rw/RwHelper.cpp b/src/rw/RwHelper.cpp
index 44ca3a0a..cf1a6f2b 100644
--- a/src/rw/RwHelper.cpp
+++ b/src/rw/RwHelper.cpp
@@ -90,9 +90,13 @@ DefinedState(void)
 	RwRenderStateSet(rwRENDERSTATEFOGTYPE, (void*)rwFOGTYPELINEAR);
 	RwRenderStateSet(rwRENDERSTATECULLMODE, (void*)rwCULLMODECULLNONE);
 
+#ifdef LIBRW
+	#pragma message ("	TODO: alphatest func")
+#else
 	// D3D stuff
 	RwD3D8SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATER);
 	RwD3D8SetRenderState(D3DRS_ALPHAREF, 2);
+#endif
 }
 
 RwFrame*
diff --git a/src/rw/RwMatFX.cpp b/src/rw/RwMatFX.cpp
index 3af6fabe..c4fe0b0b 100644
--- a/src/rw/RwMatFX.cpp
+++ b/src/rw/RwMatFX.cpp
@@ -1,3 +1,5 @@
+#ifndef LIBRW
+
 #define WITHD3D
 #include "common.h"
 #include "patcher.h"
@@ -224,3 +226,5 @@ STARTPATCHES
 ENDPATCHES
 
 #endif
+
+#endif
diff --git a/src/rw/TexRead.cpp b/src/rw/TexRead.cpp
index 50b99d47..8ada080d 100644
--- a/src/rw/TexRead.cpp
+++ b/src/rw/TexRead.cpp
@@ -25,6 +25,12 @@
 float &texLoadTime = *(float*)0x8F1B50;
 int32 &texNumLoaded = *(int32*)0x8F252C;
 
+#ifdef LIBRW
+#define READNATIVE(stream, tex, size) rwNativeTextureHackRead(stream, tex, size)
+#else
+#define READNATIVE(stream, tex, size) RWSRCGLOBAL(stdFunc[rwSTANDARDNATIVETEXTUREREAD](stream, tex, size))
+#endif
+
 RwTexture*
 RwTextureGtaStreamRead(RwStream *stream)
 {
@@ -36,7 +42,7 @@ RwTextureGtaStreamRead(RwStream *stream)
 
 	float preloadTime = (float)CTimer::GetCurrentTimeInCycles() / (float)CTimer::GetCyclesPerMillisecond();
 
-	if(!RWSRCGLOBAL(stdFunc[rwSTANDARDNATIVETEXTUREREAD](stream, &tex, size)))
+	if(!READNATIVE(stream, &tex, size))
 		return nil;
 
 	if (gGameState == GS_INIT_PLAYING_GAME) {
@@ -121,7 +127,7 @@ RwTexDictionaryGtaStreamRead1(RwStream *stream)
 	}
 
 	numberTextures = numTextures;
-	streamPosition = stream->Type.memory.position;
+	streamPosition = STREAMPOS(stream);
 
 	return texDict;
 }
@@ -131,7 +137,7 @@ RwTexDictionaryGtaStreamRead2(RwStream *stream, RwTexDictionary *texDict)
 {
 	RwTexture *tex;
 
-	RwStreamSkip(stream, streamPosition - stream->Type.memory.position);
+	RwStreamSkip(stream, streamPosition - STREAMPOS(stream));
 
 	while(numberTextures--){
 		tex = RwTextureGtaStreamRead(stream);
@@ -251,6 +257,12 @@ DealWithTxdWriteError(uint32 num, uint32 count, const char *text)
 	RsGlobal.quit = true;
 }
 
+#ifdef LIBRW
+#define STREAMTELL(str)	str->tell()
+#else
+#define STREAMTELL(str) filesys->rwftell((str)->Type.file.fpFile)
+#endif
+
 bool
 CreateTxdImageForVideoCard()
 {
@@ -260,7 +272,9 @@ CreateTxdImageForVideoCard()
 
 	CStreaming::FlushRequestList();
 
+#ifndef LIBRW
 	RwFileFunctions *filesys = RwOsGetFileInterface();
+#endif
 
 	RwStream *img = RwStreamOpen(rwSTREAMFILENAME, rwSTREAMWRITE, "models\\txd.img");
 	if (img == nil) {
@@ -287,7 +301,8 @@ CreateTxdImageForVideoCard()
 			sprintf(filename, "%s.txd", CTxdStore::GetTxdName(i));
 
 			if (CTxdStore::GetSlot(i)->texDict) {
-				int32 pos = filesys->rwftell(img->Type.file.fpFile);
+
+				int32 pos = STREAMTELL(img);
 
 				if (RwTexDictionaryStreamWrite(CTxdStore::GetSlot(i)->texDict, img) == nil) {
 					DealWithTxdWriteError(i, TXDSTORESIZE, "CVT_ERR");
@@ -298,7 +313,7 @@ CreateTxdImageForVideoCard()
 					return false;
 				}
 
-				int32 size = filesys->rwftell(img->Type.file.fpFile) - pos;
+				int32 size = STREAMTELL(img) - pos;
 				int32 num = size % CDSTREAM_SECTOR_SIZE;
 
 				size /= CDSTREAM_SECTOR_SIZE;
diff --git a/src/rw/rw.cpp b/src/rw/rw.cpp
index 3875f2a1..196cf189 100644
--- a/src/rw/rw.cpp
+++ b/src/rw/rw.cpp
@@ -1,3 +1,4 @@
+#ifndef LIBRW
 #include "common.h"
 #include "patcher.h"
 #include "rwcore.h"
@@ -836,4 +837,5 @@ InjectHook(0x5DF040, &RxNodeDefinitionGetLight, PATCH_JUMP);
 InjectHook(0x5DF560, &RxNodeDefinitionGetPostLight, PATCH_JUMP);
 InjectHook(0x5DFC60, &RxD3D8AllInOneSetRenderCallBack, PATCH_JUMP);
 ENDPATCHES
+#endif
 #endif
\ No newline at end of file