diff --git a/dffwrite.cpp b/dffwrite.cpp
index 9e689fa..49d28ca 100644
--- a/dffwrite.cpp
+++ b/dffwrite.cpp
@@ -18,6 +18,9 @@ main(int argc, char *argv[])
// Rw::Version = 0x33002;
+ Rw::RegisterMaterialRightsPlugin();
+ Rw::RegisterMatFXPlugin();
+ Rw::RegisterAtomicRightsPlugin();
Rw::RegisterNodeNamePlugin();
Rw::RegisterBreakableModelPlugin();
Rw::RegisterExtraVertColorPlugin();
@@ -26,6 +29,7 @@ main(int argc, char *argv[])
Rw::RegisterNativeDataPlugin();
// Rw::Ps2::RegisterNativeDataPlugin();
Rw::RegisterMeshPlugin();
+
Rw::Clump *c;
// ifstream in(argv[1], ios::binary);
@@ -45,6 +49,7 @@ main(int argc, char *argv[])
in.open(data, len);
Rw::FindChunk(&in, Rw::ID_CLUMP, NULL, NULL);
+ Rw::DebugFile = argv[1];
c = Rw::Clump::streamRead(&in);
assert(c != NULL);
diff --git a/src/clump.cpp b/src/clump.cpp
index b18267b..32d6be8 100644
--- a/src/clump.cpp
+++ b/src/clump.cpp
@@ -117,7 +117,9 @@ makeFrameList(Frame *frame, Frame **flist)
return flist;
}
-
+//
+// Clump
+//
Clump::Clump(void)
{
@@ -367,6 +369,9 @@ Clump::frameListStreamWrite(Stream *stream, Frame **frameList, int32 numFrames)
frameList[i]->streamWritePlugins(stream);
}
+//
+// Atomic
+//
Atomic::Atomic(void)
{
@@ -430,6 +435,33 @@ Atomic::streamGetSize(void)
return 12 + 16 + 12 + this->streamGetPluginSize();
}
+// Atomic Rights plugin
+
+static void
+readAtomicRights(Stream *stream, int32, void *, int32, int32)
+{
+ uint32 buffer[2];
+ uint32 version;
+stream->seek(-4);
+version = stream->readU32();
+ stream->read(buffer, 8);
+// printf("atomicrights: %s %X %X %X\n", DebugFile, LibraryIDUnpackVersion(version), buffer[0], buffer[1]);
+ printf("atomicrights: %X %X %X\n", LibraryIDUnpackVersion(version), buffer[0], buffer[1]);
+}
+
+void
+RegisterAtomicRightsPlugin(void)
+{
+ Atomic::registerPlugin(0, ID_RIGHTTORENDER, NULL, NULL, NULL);
+ Atomic::registerPluginStream(ID_RIGHTTORENDER,
+ (StreamRead)readAtomicRights,
+ NULL, NULL);
+}
+
+
+//
+// Light
+//
Light::Light(void)
{
diff --git a/src/geometry.cpp b/src/geometry.cpp
index c3387a0..8aba1e9 100644
--- a/src/geometry.cpp
+++ b/src/geometry.cpp
@@ -269,7 +269,9 @@ Geometry::addMorphTargets(int32 n)
}
-
+//
+// Material
+//
Material::Material(void)
{
@@ -383,7 +385,29 @@ Material::streamGetSize(void)
return size;
}
+// Material Rights plugin
+static void
+readMaterialRights(Stream *stream, int32, void *, int32, int32)
+{
+ uint32 buffer[2];
+ stream->read(buffer, 8);
+ printf("materialrights: %X %X\n", buffer[0], buffer[1]);
+}
+
+void
+RegisterMaterialRightsPlugin(void)
+{
+ Material::registerPlugin(0, ID_RIGHTTORENDER, NULL, NULL, NULL);
+ Material::registerPluginStream(ID_RIGHTTORENDER,
+ (StreamRead)readMaterialRights,
+ NULL, NULL);
+}
+
+
+//
+// Texture
+//
Texture::Texture(void)
{
diff --git a/src/geometryplg.cpp b/src/geometryplg.cpp
index 28fa01f..7261cab 100644
--- a/src/geometryplg.cpp
+++ b/src/geometryplg.cpp
@@ -229,12 +229,12 @@ destroySkin(void *object, int32 offset, int32)
static void*
copySkin(void *dst, void *src, int32 offset, int32)
{
- Geometry *geometry = (Geometry*)src;
- assert(geometry->instData == NULL);
- assert(((Geometry*)src)->numVertices == ((Geometry*)dst)->numVertices);
Skin *srcskin = *PLUGINOFFSET(Skin*, src, offset);
if(srcskin == NULL)
return dst;
+ Geometry *geometry = (Geometry*)src;
+ assert(geometry->instData == NULL);
+ assert(((Geometry*)src)->numVertices == ((Geometry*)dst)->numVertices);
Skin *dstskin = new Skin;
*PLUGINOFFSET(Skin*, dst, offset) = dstskin;
dstskin->numBones = srcskin->numBones;
@@ -413,9 +413,330 @@ RegisterSkinPlugin(void)
Geometry::registerPlugin(sizeof(Skin*), ID_SKIN,
createSkin, destroySkin, copySkin);
Geometry::registerPluginStream(ID_SKIN,
- (StreamRead)readSkin,
- (StreamWrite)writeSkin,
- (StreamGetSize)getSizeSkin);
+ readSkin, writeSkin, getSizeSkin);
+}
+
+// Atomic MatFX
+
+static void*
+createAtomicMatFX(void *object, int32 offset, int32)
+{
+ *PLUGINOFFSET(int32, object, offset) = 0;
+ return object;
+}
+
+static void*
+copyAtomicMatFX(void *dst, void *src, int32 offset, int32)
+{
+ *PLUGINOFFSET(int32, dst, offset) = *PLUGINOFFSET(int32, src, offset);
+ return dst;
+}
+
+static void
+readAtomicMatFX(Stream *stream, int32, void *object, int32 offset, int32)
+{
+ int32 flag;
+// uint32 version;
+//stream->seek(-4);
+//version = stream->readU32();
+ stream->read(&flag, 4);
+//printf("atomicMatFX: %X %X\n", LibraryIDUnpackVersion(version), flag);
+ *PLUGINOFFSET(int32, object, offset) = flag;
+ // TODO: set Pipeline
+}
+
+static void
+writeAtomicMatFX(Stream *stream, int32, void *object, int32 offset, int32)
+{
+ int32 flag;
+ flag = *PLUGINOFFSET(int32, object, offset);
+ stream->writeI32(flag);
+}
+
+static int32
+getSizeAtomicMatFX(void *object, int32 offset, int32)
+{
+ int32 flag;
+ flag = *PLUGINOFFSET(int32, object, offset);
+ return flag ? 4 : -1;
+}
+
+// Material MatFX
+
+// TODO: Frames and Matrices?
+static void
+clearMatFX(MatFX *matfx)
+{
+ for(int i = 0; i < 2; i++)
+ switch(matfx->fx[i].type){
+ case MatFX::BUMPMAP:
+ if(matfx->fx[i].bump.bumpedTex)
+ matfx->fx[i].bump.bumpedTex->decRef();
+ if(matfx->fx[i].bump.tex)
+ matfx->fx[i].bump.tex->decRef();
+ break;
+
+ case MatFX::ENVMAP:
+ if(matfx->fx[i].env.tex)
+ matfx->fx[i].env.tex->decRef();
+ break;
+
+ case MatFX::DUAL:
+ if(matfx->fx[i].dual.tex)
+ matfx->fx[i].dual.tex->decRef();
+ break;
+ }
+ memset(matfx, 0, sizeof(MatFX));
+}
+
+void
+MatFX::setEffects(uint32 flags)
+{
+ if(this->flags != 0 && this->flags != flags)
+ clearMatFX(this);
+ this->flags = flags;
+ switch(flags){
+ case BUMPMAP:
+ case ENVMAP:
+ case DUAL:
+ case UVTRANSFORM:
+ this->fx[0].type = flags;
+ this->fx[1].type = NOTHING;
+ break;
+
+ case BUMPENVMAP:
+ this->fx[0].type = BUMPMAP;
+ this->fx[1].type = ENVMAP;
+ break;
+
+ case DUALUVTRANSFORM:
+ this->fx[0].type = UVTRANSFORM;
+ this->fx[1].type = DUAL;
+ break;
+ }
+}
+
+int32
+MatFX::getEffectIndex(uint32 type)
+{
+ for(int i = 0; i < 2; i++)
+ if(this->fx[i].type == type)
+ return i;
+ return -1;
+}
+
+static void*
+createMaterialMatFX(void *object, int32 offset, int32)
+{
+ *PLUGINOFFSET(MatFX*, object, offset) = NULL;
+ return object;
+}
+
+static void*
+destroyMaterialMatFX(void *object, int32 offset, int32)
+{
+ MatFX *matfx = *PLUGINOFFSET(MatFX*, object, offset);
+ if(matfx){
+ clearMatFX(matfx);
+ delete matfx;
+ }
+ return object;
+}
+
+static void*
+copyMaterialMatFX(void *dst, void *src, int32 offset, int32)
+{
+ MatFX *srcfx = *PLUGINOFFSET(MatFX*, src, offset);
+ if(srcfx == NULL)
+ return dst;
+ MatFX *dstfx = new MatFX;
+ *PLUGINOFFSET(MatFX*, dst, offset) = dstfx;
+ memcpy(dstfx, srcfx, sizeof(MatFX));
+ for(int i = 0; i < 2; i++)
+ switch(dstfx->fx[i].type){
+ case MatFX::BUMPMAP:
+ if(dstfx->fx[i].bump.bumpedTex)
+ dstfx->fx[i].bump.bumpedTex->refCount++;
+ if(dstfx->fx[i].bump.tex)
+ dstfx->fx[i].bump.tex->refCount++;
+ break;
+
+ case MatFX::ENVMAP:
+ if(dstfx->fx[i].env.tex)
+ dstfx->fx[i].env.tex->refCount++;
+ break;
+
+ case MatFX::DUAL:
+ if(dstfx->fx[i].dual.tex)
+ dstfx->fx[i].dual.tex->refCount++;
+ break;
+ }
+ return dst;
+}
+
+static void
+readMaterialMatFX(Stream *stream, int32, void *object, int32 offset, int32)
+{
+ Texture *tex, *bumpedTex;
+ float coefficient;
+ int32 fbAlpha;
+ int32 srcBlend, dstBlend;
+ int32 idx;
+
+ MatFX *matfx = new MatFX;
+ memset(matfx, 0, sizeof(MatFX));
+ *PLUGINOFFSET(MatFX*, object, offset) = matfx;
+ matfx->setEffects(stream->readU32());
+
+ for(int i = 0; i < 2; i++){
+ uint32 type = stream->readU32();
+ switch(type){
+ case MatFX::BUMPMAP:
+ coefficient = stream->readF32();
+ bumpedTex = tex = NULL;
+ if(stream->readI32()){
+ assert(FindChunk(stream, ID_TEXTURE,
+ NULL, NULL));
+ bumpedTex = Texture::streamRead(stream);
+ }
+ if(stream->readI32()){
+ assert(FindChunk(stream, ID_TEXTURE,
+ NULL, NULL));
+ tex = Texture::streamRead(stream);
+ }
+ idx = matfx->getEffectIndex(type);
+ assert(idx >= 0);
+ matfx->fx[idx].bump.bumpedTex = bumpedTex;
+ matfx->fx[idx].bump.tex = tex;
+ matfx->fx[idx].bump.coefficient = coefficient;
+ break;
+
+ case MatFX::ENVMAP:
+ coefficient = stream->readF32();
+ fbAlpha = stream->readI32();
+ tex = NULL;
+ if(stream->readI32()){
+ assert(FindChunk(stream, ID_TEXTURE,
+ NULL, NULL));
+ tex = Texture::streamRead(stream);
+ }
+ idx = matfx->getEffectIndex(type);
+ assert(idx >= 0);
+ matfx->fx[idx].env.tex = tex;
+ matfx->fx[idx].env.fbAlpha = fbAlpha;
+ matfx->fx[idx].env.coefficient = coefficient;
+ break;
+
+ case MatFX::DUAL:
+ srcBlend = stream->readI32();
+ dstBlend = stream->readI32();
+ tex = NULL;
+ if(stream->readI32()){
+ assert(FindChunk(stream, ID_TEXTURE,
+ NULL, NULL));
+ tex = Texture::streamRead(stream);
+ }
+ idx = matfx->getEffectIndex(type);
+ assert(idx >= 0);
+ matfx->fx[idx].dual.tex = tex;
+ matfx->fx[idx].dual.srcBlend = srcBlend;
+ matfx->fx[idx].dual.dstBlend = dstBlend;
+ break;
+ }
+ }
+}
+
+static void
+writeMaterialMatFX(Stream *stream, int32, void *object, int32 offset, int32)
+{
+ MatFX *matfx = *PLUGINOFFSET(MatFX*, object, offset);
+
+ stream->writeU32(matfx->flags);
+ for(int i = 0; i < 2; i++){
+ stream->writeU32(matfx->fx[i].type);
+ switch(matfx->fx[i].type){
+ case MatFX::BUMPMAP:
+ stream->writeF32(matfx->fx[i].bump.coefficient);
+ stream->writeI32(matfx->fx[i].bump.bumpedTex != NULL);
+ if(matfx->fx[i].bump.bumpedTex)
+ matfx->fx[i].bump.bumpedTex->streamWrite(stream);
+ stream->writeI32(matfx->fx[i].bump.tex != NULL);
+ if(matfx->fx[i].bump.tex)
+ matfx->fx[i].bump.tex->streamWrite(stream);
+ break;
+
+ case MatFX::ENVMAP:
+ stream->writeF32(matfx->fx[i].env.coefficient);
+ stream->writeI32(matfx->fx[i].env.fbAlpha);
+ stream->writeI32(matfx->fx[i].env.tex != NULL);
+ if(matfx->fx[i].env.tex)
+ matfx->fx[i].env.tex->streamWrite(stream);
+ break;
+
+ case MatFX::DUAL:
+ stream->writeI32(matfx->fx[i].dual.srcBlend);
+ stream->writeI32(matfx->fx[i].dual.dstBlend);
+ stream->writeI32(matfx->fx[i].dual.tex != NULL);
+ if(matfx->fx[i].dual.tex)
+ matfx->fx[i].dual.tex->streamWrite(stream);
+ break;
+ }
+ }
+}
+
+static int32
+getSizeMaterialMatFX(void *object, int32 offset, int32)
+{
+ MatFX *matfx = *PLUGINOFFSET(MatFX*, object, offset);
+ if(matfx == NULL)
+ return -1;
+ int32 size = 4 + 4 + 4;
+
+ for(int i = 0; i < 2; i++)
+ switch(matfx->fx[i].type){
+ case MatFX::BUMPMAP:
+ size += 4 + 4 + 4;
+ if(matfx->fx[i].bump.bumpedTex)
+ size += 12 +
+ matfx->fx[i].bump.bumpedTex->streamGetSize();
+ if(matfx->fx[i].bump.tex)
+ size += 12 +
+ matfx->fx[i].bump.tex->streamGetSize();
+ break;
+
+ case MatFX::ENVMAP:
+ size += 4 + 4 + 4;
+ if(matfx->fx[i].env.tex)
+ size += 12 +
+ matfx->fx[i].env.tex->streamGetSize();
+ break;
+
+ case MatFX::DUAL:
+ size += 4 + 4 + 4;
+ if(matfx->fx[i].dual.tex)
+ size += 12 +
+ matfx->fx[i].dual.tex->streamGetSize();
+ break;
+ }
+ return size;
+}
+
+void
+RegisterMatFXPlugin(void)
+{
+ Atomic::registerPlugin(sizeof(int32), ID_MATFX,
+ createAtomicMatFX, NULL, copyAtomicMatFX);
+ Atomic::registerPluginStream(ID_MATFX,
+ readAtomicMatFX,
+ writeAtomicMatFX,
+ getSizeAtomicMatFX);
+ Material::registerPlugin(sizeof(MatFX*), ID_MATFX,
+ createMaterialMatFX, destroyMaterialMatFX,
+ copyMaterialMatFX);
+ Material::registerPluginStream(ID_MATFX,
+ readMaterialMatFX,
+ writeMaterialMatFX,
+ getSizeMaterialMatFX);
}
}
diff --git a/src/rwbase.cpp b/src/rwbase.cpp
index ee19fb4..9520e35 100644
--- a/src/rwbase.cpp
+++ b/src/rwbase.cpp
@@ -14,6 +14,7 @@ namespace Rw {
int Version = 0x36003;
int Build = 0xFFFF;
+char *DebugFile = NULL;
int32
Stream::writeI8(int8 val)
diff --git a/src/rwbase.h b/src/rwbase.h
index 21fa2e2..175e72d 100644
--- a/src/rwbase.h
+++ b/src/rwbase.h
@@ -110,12 +110,16 @@ enum PluginID
ID_UVANIMDICT = 0x2B,
ID_SKIN = 0x116,
+ ID_MATFX = 0x120,
+ ID_PDS = 0x131,
ID_ADC = 0x134,
+ ID_MESH = 0x50E,
ID_NATIVEDATA = 0x510,
};
extern int Version;
extern int Build;
+extern char *DebugFile;
inline uint32
LibraryIDPack(int version, int build)
diff --git a/src/rwobjects.h b/src/rwobjects.h
index 374ab0c..74c8b73 100644
--- a/src/rwobjects.h
+++ b/src/rwobjects.h
@@ -1,5 +1,12 @@
namespace Rw {
+// TODO: mostly
+struct Pipeline
+{
+ uint32 pluginID;
+ uint32 pluginData;
+};
+
struct Object
{
uint8 type;
@@ -8,6 +15,28 @@ struct Object
void *parent;
};
+struct Frame : PluginBase, Object
+{
+ typedef Frame *(*Callback)(Frame *f, void *data);
+ float32 matrix[16];
+ float32 ltm[16];
+
+ Frame *child;
+ Frame *next;
+ Frame *root;
+
+ // temporary
+ int32 matflag;
+
+ Frame(void);
+ Frame(Frame *f);
+ ~Frame(void);
+ Frame *addChild(Frame *f);
+ Frame *removeChild(void);
+ Frame *forAllChildren(Callback cb, void *data);
+ int32 count(void);
+};
+
struct Image
{
int32 flags;
@@ -74,6 +103,56 @@ struct Material : PluginBase
uint32 streamGetSize(void);
};
+struct MatFX
+{
+ enum Flags {
+ NOTHING = 0,
+ BUMPMAP,
+ ENVMAP,
+ BUMPENVMAP,
+ DUAL,
+ UVTRANSFORM,
+ DUALUVTRANSFORM
+ };
+ struct Bump {
+ Frame *frame;
+ Texture *bumpedTex;
+ Texture *tex;
+ float coefficient;
+ };
+ struct Env {
+ Frame *frame;
+ Texture *tex;
+ float coefficient;
+ int32 fbAlpha;
+ };
+ struct Dual {
+ Texture *tex;
+ int32 srcBlend;
+ int32 dstBlend;
+ };
+ struct UVtransform {
+ float *baseTransform;
+ float *dualTransform;
+ };
+ struct {
+ uint32 type;
+ union {
+ Bump bump;
+ Env env;
+ Dual dual;
+ UVtransform uvtransform;
+ };
+ } fx[2];
+ uint32 flags;
+
+ void setEffects(uint32 flags);
+ int32 getEffectIndex(uint32 type);
+};
+
+void RegisterMaterialRightsPlugin(void);
+void RegisterMatFXPlugin(void);
+
struct Mesh
{
uint16 *indices;
@@ -160,27 +239,9 @@ struct Skin
uint8 *data; // only used by delete
};
-struct Frame : PluginBase, Object
-{
- typedef Frame *(*Callback)(Frame *f, void *data);
- float32 matrix[16];
- float32 ltm[16];
-
- Frame *child;
- Frame *next;
- Frame *root;
-
- // temporary
- int32 matflag;
-
- Frame(void);
- Frame(Frame *f);
- ~Frame(void);
- Frame *addChild(Frame *f);
- Frame *removeChild(void);
- Frame *forAllChildren(Callback cb, void *data);
- int32 count(void);
-};
+void RegisterMeshPlugin(void);
+void RegisterNativeDataPlugin(void);
+void RegisterSkinPlugin(void);
struct Clump;
@@ -216,6 +277,8 @@ struct Atomic : PluginBase, Object
uint32 streamGetSize(void);
};
+void RegisterAtomicRightsPlugin(void);
+
struct Clump : PluginBase, Object
{
int32 numAtomics;
@@ -237,8 +300,4 @@ private:
void frameListStreamWrite(Stream *stream, Frame **flp, int32 nf);
};
-void RegisterMeshPlugin(void);
-void RegisterNativeDataPlugin(void);
-void RegisterSkinPlugin(void);
-
}
diff --git a/src/rwplugin.h b/src/rwplugin.h
index 1605f94..f91e4a7 100644
--- a/src/rwplugin.h
+++ b/src/rwplugin.h
@@ -105,7 +105,8 @@ PluginBase::streamWritePlugins(Stream *stream)
int size = this->streamGetPluginSize();
Rw::WriteChunkHeader(stream, Rw::ID_EXTENSION, size);
for(Plugin *p = this->s_plugins; p; p = p->next){
- if((size = p->getSize(this, p->offset, p->size)) < 0)
+ if(p->getSize == NULL ||
+ (size = p->getSize(this, p->offset, p->size)) < 0)
continue;
Rw::WriteChunkHeader(stream, p->id, size);
p->write(stream, size, this, p->offset, p->size);