From a42bfb90ac5072d3e0ad891833e87d4405688069 Mon Sep 17 00:00:00 2001 From: aap Date: Sat, 9 Jan 2016 22:01:21 +0100 Subject: [PATCH] implemented leeds dff stream read --- librw.sln | 3 +- src/geometry.cpp | 28 +- src/mdl.cpp | 8 +- src/plugins.cpp | 14 +- src/ps2.cpp | 66 ++-- src/rwobjects.h | 13 +- tools/rsltest/rsl.cpp | 671 ++++++++++++++++++++++++++++++++++ tools/rsltest/rsl.h | 112 +++++- tools/rsltest/rsltest.cpp | 176 +-------- tools/rsltest/rsltest.vcxproj | 1 + 10 files changed, 844 insertions(+), 248 deletions(-) create mode 100644 tools/rsltest/rsl.cpp diff --git a/librw.sln b/librw.sln index b44ee8b..d2e140e 100644 --- a/librw.sln +++ b/librw.sln @@ -76,7 +76,6 @@ Global {85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Release|x64.ActiveCfg = Release|x64 {85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Release|x64.Build.0 = Release|x64 {2592ED29-F258-4949-AB45-7B873BF697F7}.Debug - null|Win32.ActiveCfg = Debug - null|Win32 - {2592ED29-F258-4949-AB45-7B873BF697F7}.Debug - null|Win32.Build.0 = Debug - null|Win32 {2592ED29-F258-4949-AB45-7B873BF697F7}.Debug - null|x64.ActiveCfg = Debug - null|x64 {2592ED29-F258-4949-AB45-7B873BF697F7}.Debug|Win32.ActiveCfg = Debug|Win32 {2592ED29-F258-4949-AB45-7B873BF697F7}.Debug|x64.ActiveCfg = Debug|x64 @@ -96,7 +95,6 @@ Global {E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Release|x64.ActiveCfg = Release|x64 {E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Release|x64.Build.0 = Release|x64 {403C35A9-6D06-4261-B305-9ED000F00136}.Debug - null|Win32.ActiveCfg = Debug - null|Win32 - {403C35A9-6D06-4261-B305-9ED000F00136}.Debug - null|Win32.Build.0 = Debug - null|Win32 {403C35A9-6D06-4261-B305-9ED000F00136}.Debug - null|x64.ActiveCfg = Debug - null|x64 {403C35A9-6D06-4261-B305-9ED000F00136}.Debug|Win32.ActiveCfg = Debug|Win32 {403C35A9-6D06-4261-B305-9ED000F00136}.Debug|x64.ActiveCfg = Debug|x64 @@ -106,6 +104,7 @@ Global {403C35A9-6D06-4261-B305-9ED000F00136}.Release|x64.ActiveCfg = Release|x64 {403C35A9-6D06-4261-B305-9ED000F00136}.Release|x64.Build.0 = Release|x64 {27ECE916-900F-49B2-8E9F-95E6B347E161}.Debug - null|Win32.ActiveCfg = Debug - null|Win32 + {27ECE916-900F-49B2-8E9F-95E6B347E161}.Debug - null|Win32.Build.0 = Debug - null|Win32 {27ECE916-900F-49B2-8E9F-95E6B347E161}.Debug - null|x64.ActiveCfg = Debug - null|Win32 {27ECE916-900F-49B2-8E9F-95E6B347E161}.Debug|Win32.ActiveCfg = Debug - null|Win32 {27ECE916-900F-49B2-8E9F-95E6B347E161}.Debug|Win32.Build.0 = Debug - null|Win32 diff --git a/src/geometry.cpp b/src/geometry.cpp index ad23eab..9ba6b3d 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -400,7 +400,9 @@ Material::Material(void) { this->texture = NULL; memset(this->color, 0xFF, 4); - surfaceProps[0] = surfaceProps[1] = surfaceProps[2] = 1.0f; + surfaceProps.ambient = 1.0f; + surfaceProps.specular = 1.0f; + surfaceProps.diffuse = 1.0f; this->pipeline = NULL; this->refCount = 1; this->constructPlugins(); @@ -412,9 +414,9 @@ Material::Material(Material *m) this->color[1] = m->color[1]; this->color[2] = m->color[2]; this->color[3] = m->color[3]; - this->surfaceProps[0] = m->surfaceProps[0]; - this->surfaceProps[1] = m->surfaceProps[1]; - this->surfaceProps[2] = m->surfaceProps[2]; + this->surfaceProps.ambient = m->surfaceProps.ambient; + this->surfaceProps.specular = m->surfaceProps.specular; + this->surfaceProps.diffuse = m->surfaceProps.diffuse; this->texture = m->texture; if(this->texture) this->texture->refCount++; @@ -463,15 +465,15 @@ Material::streamRead(Stream *stream) mat->color[2] = buf.color[2]; mat->color[3] = buf.color[3]; if(version < 0x30400){ - mat->surfaceProps[0] = 1.0f; - mat->surfaceProps[1] = 1.0f; - mat->surfaceProps[2] = 1.0f; + mat->surfaceProps.ambient = 1.0f; + mat->surfaceProps.specular = 1.0f; + mat->surfaceProps.diffuse = 1.0f; }else{ float32 surfaceProps[3]; stream->read(surfaceProps, sizeof(surfaceProps)); - mat->surfaceProps[0] = surfaceProps[0]; - mat->surfaceProps[1] = surfaceProps[1]; - mat->surfaceProps[2] = surfaceProps[2]; + mat->surfaceProps.ambient = surfaceProps[0]; + mat->surfaceProps.specular = surfaceProps[1]; + mat->surfaceProps.diffuse = surfaceProps[2]; } if(buf.textured){ assert(findChunk(stream, ID_TEXTURE, &length, NULL)); @@ -505,9 +507,9 @@ Material::streamWrite(Stream *stream) if(rw::version >= 0x30400){ float32 surfaceProps[3]; - surfaceProps[0] = this->surfaceProps[0]; - surfaceProps[1] = this->surfaceProps[1]; - surfaceProps[2] = this->surfaceProps[2]; + surfaceProps[0] = this->surfaceProps.ambient; + surfaceProps[1] = this->surfaceProps.specular; + surfaceProps[2] = this->surfaceProps.diffuse; stream->write(surfaceProps, sizeof(surfaceProps)); } diff --git a/src/mdl.cpp b/src/mdl.cpp index 38b13a6..e2f4886 100644 --- a/src/mdl.cpp +++ b/src/mdl.cpp @@ -374,10 +374,10 @@ geometryStreamReadRsl(Stream *stream) for(int32 i = 0; i < g->numMaterials; i++){ assert(findChunk(stream, ID_MATERIAL, NULL, NULL)); g->materialList[i] = Material::streamRead(stream); - // fucked somehow - g->materialList[i]->surfaceProps[0] = 1.0f; - g->materialList[i]->surfaceProps[1] = 1.0f; - g->materialList[i]->surfaceProps[2] = 1.0f; + // unimplemented by Rsl + g->materialList[i]->surfaceProps.ambient = 1.0f; + g->materialList[i]->surfaceProps.specular = 1.0f; + g->materialList[i]->surfaceProps.diffuse = 1.0f; } g->streamReadPlugins(stream); diff --git a/src/plugins.cpp b/src/plugins.cpp index 116b264..4e88962 100644 --- a/src/plugins.cpp +++ b/src/plugins.cpp @@ -791,17 +791,17 @@ clearMatFX(MatFX *matfx) } void -MatFX::setEffects(uint32 flags) +MatFX::setEffects(uint32 type) { - if(this->flags != 0 && this->flags != flags) + if(this->type != 0 && this->type != type) clearMatFX(this); - this->flags = flags; - switch(flags){ + this->type = type; + switch(type){ case BUMPMAP: case ENVMAP: case DUAL: case UVTRANSFORM: - this->fx[0].type = flags; + this->fx[0].type = type; this->fx[1].type = NOTHING; break; @@ -889,7 +889,7 @@ readMaterialMatFX(Stream *stream, int32, void *object, int32 offset, int32) *PLUGINOFFSET(MatFX*, object, offset) = matfx; matfx->setEffects(stream->readU32()); - if(matfx->flags == MatFX::BUMPMAP && matFXGlobals.hack){ + if(matfx->type == MatFX::BUMPMAP && matFXGlobals.hack){ stream->seek(12); return; } @@ -961,7 +961,7 @@ writeMaterialMatFX(Stream *stream, int32, void *object, int32 offset, int32) { MatFX *matfx = *PLUGINOFFSET(MatFX*, object, offset); - stream->writeU32(matfx->flags); + stream->writeU32(matfx->type); for(int i = 0; i < 2; i++){ stream->writeU32(matfx->fx[i].type); switch(matfx->fx[i].type){ diff --git a/src/ps2.cpp b/src/ps2.cpp index 3edef74..564ee2f 100644 --- a/src/ps2.cpp +++ b/src/ps2.cpp @@ -1515,24 +1515,24 @@ ps2MinSize(int32 psm, int32 flags, int32 *minw, int32 *minh) { *minh = 1; switch(psm){ - case 0x00: - case 0x30: - *minw = 2; // 32 bit - break; - case 0x02: - case 0x0A: - case 0x32: - case 0x3A: - *minw = 4; // 16 bit - break; - case 0x01: - case 0x13: - case 0x14: - case 0x1B: - case 0x24: - case 0x2C: - case 0x31: - *minw = 8; // everything else + case 0x00: + case 0x30: + *minw = 2; // 32 bit + break; + case 0x02: + case 0x0A: + case 0x32: + case 0x3A: + *minw = 4; // 16 bit + break; + case 0x01: + case 0x13: + case 0x14: + case 0x1B: + case 0x24: + case 0x2C: + case 0x31: + *minw = 8; // everything else break; } if(flags & 0x2 && psm == 0x13){ // PSMT8 @@ -1896,21 +1896,21 @@ registerNativeRaster(void) Texture::registerPluginStream(ID_SKYMIPMAP, readMipmap, writeMipmap, getSizeMipmap); } -struct StreamRasterExt -{ - int32 width; - int32 height; - int32 depth; - uint16 rasterFormat; - int16 type; - uint32 tex0[2]; - uint32 tex1[2]; - uint32 miptbp1[2]; - uint32 miptbp2[2]; - uint32 texelSize; - uint32 paletteSize; - uint32 gsSize; - uint32 mipmapVal; +struct StreamRasterExt +{ + int32 width; + int32 height; + int32 depth; + uint16 rasterFormat; + int16 type; + uint32 tex0[2]; + uint32 tex1[2]; + uint32 miptbp1[2]; + uint32 miptbp2[2]; + uint32 texelSize; + uint32 paletteSize; + uint32 gsSize; + uint32 mipmapVal; }; Texture* diff --git a/src/rwobjects.h b/src/rwobjects.h index 0f03c37..4de0506 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -199,11 +199,18 @@ struct Texture : PluginBase }; }; +struct SurfaceProperties +{ + float32 ambient; + float32 specular; + float32 diffuse; +}; + struct Material : PluginBase { Texture *texture; uint8 color[4]; - float32 surfaceProps[3]; + SurfaceProperties surfaceProps; Pipeline *pipeline; int32 refCount; @@ -220,7 +227,7 @@ void registerMaterialRightsPlugin(void); struct MatFX { - enum Flags { + enum { NOTHING = 0, BUMPMAP, ENVMAP, @@ -259,7 +266,7 @@ struct MatFX UVtransform uvtransform; }; } fx[2]; - uint32 flags; + uint32 type; void setEffects(uint32 flags); int32 getEffectIndex(uint32 type); diff --git a/tools/rsltest/rsl.cpp b/tools/rsltest/rsl.cpp new file mode 100644 index 0000000..42f60b2 --- /dev/null +++ b/tools/rsltest/rsl.cpp @@ -0,0 +1,671 @@ +#include +#include +#include +#include +#include + +#include +#include +#include + +using namespace std; +using namespace rw; +#include "rsl.h" + +void rslMaterialListStreamRead(Stream *stream, RslMaterialList *matlist); +void hanimRead(Stream *stream, RslFrame *f); +void matfxRead(Stream *stream, RslMaterial *mat); + +void +RslMatrixSetIdentity(RslMatrix *matrix) +{ + memset(matrix, 0, sizeof(RslMatrix)); + matrix->right.x = 1.0f; + matrix->up.y = 1.0f; + matrix->at.z = 1.0f; +} + +void +rslObjectHasFrameSetFrame(RslObjectHasFrame *object, RslFrame *f) +{ + if(object->object.parent){ + object->lFrame.prev->next = object->lFrame.next; + object->lFrame.next->prev = object->lFrame.prev; + } + object->object.parent = f; + if(f){ + object->lFrame.prev = &f->objectList.link; + object->lFrame.next = f->objectList.link.next; + f->objectList.link.next->prev = &object->lFrame; + f->objectList.link.next = &object->lFrame; + + f->root->object.privateFlags |= 1; + f->object.privateFlags |= 2; + } +} + +RslFrame* +RslFrameCreate(void) +{ + RslFrame *f = new RslFrame; + rslObjectInitialize(&f->object, 0, 0); + f->objectList.link.prev = &f->objectList.link; + f->objectList.link.next = &f->objectList.link; + RslMatrixSetIdentity(&f->modelling); + RslMatrixSetIdentity(&f->ltm); + f->child = NULL; + f->next = NULL; + f->root = f; + + f->nodeId = -1; + f->hier = NULL; + + f->name = NULL; + + f->hierId = 0; + return f; +} + +RslFrame* +RslFrameAddChild(RslFrame *parent, RslFrame *child) +{ + RslFrame *p = (RslFrame*)child->object.parent; + assert(p == NULL); + child->next = parent->child; + parent->child = child; + child->object.parent = parent; + child->root = parent->root; + child->root->object.privateFlags |= 1; + child->object.privateFlags |= 2; + return parent; +} + +RslFrame* +RslFrameForAllChildren(RslFrame *frame, RslFrameCallBack callBack, void *data) +{ + for(RslFrame *child = frame->child; + child; + child = child->next) + if(callBack(child, data) == NULL) + break; + return frame; +} + +struct StreamFrame +{ + RslV3d right, up, at, pos; + int32 parent; + int32 flags; +}; + +void +rwFrameListStreamRead(Stream *stream, rslFrameList *framelist) +{ + uint32 length; + StreamFrame strfrm; + RslFrame *f; + + assert(findChunk(stream, ID_STRUCT, NULL, NULL)); + stream->read(&framelist->numFrames, 4); + framelist->frames = new RslFrame*[framelist->numFrames]; + for(int32 i = 0; i < framelist->numFrames; i++){ + stream->read(&strfrm, sizeof(strfrm)); + f = RslFrameCreate(); + f->modelling.right = strfrm.right; + f->modelling.up = strfrm.up; + f->modelling.at = strfrm.at; + f->modelling.pos = strfrm.pos; + framelist->frames[i] = f; + if(strfrm.parent >= 0) + RslFrameAddChild(framelist->frames[strfrm.parent], f); + } + ChunkHeaderInfo header; + for(int32 i = 0; i < framelist->numFrames; i++){ + f = framelist->frames[i]; + assert(findChunk(stream, ID_EXTENSION, &length, NULL)); + while(length){ + readChunkHeaderInfo(stream, &header); + if(header.type == ID_HANIMPLUGIN){ + hanimRead(stream, f); + }else if(header.type == gta::ID_NODENAME){ + f->name = new char[header.length+1]; + memset(f->name, 0, header.length+1); + stream->read(f->name, header.length); + f->name[header.length] = '\0'; + }else{ + stream->seek(header.length); + } + length -= 12 + header.length; + } + } +} + +RslHAnimHierarchy* +RslHAnimHierarchyCreate(int32 numNodes, uint32 *nodeFlags, int32 *nodeIDs, int32 flags, int32 maxKeySize) +{ + RslHAnimHierarchy *hier = new RslHAnimHierarchy; + memset(hier, 0, sizeof(RslHAnimHierarchy)); + if(maxKeySize < 0x24) + maxKeySize = 0x24; + hier->flags = flags; + hier->numNodes = numNodes; + hier->parentFrame = 0; + hier->maxKeyFrameSize = maxKeySize; + hier->currentKeyFrameSize = 0x24; + + int32 msz = numNodes*0x40 + 0x3f; + uint8 *p = new uint8[msz]; + memset(p, 0, msz); + hier->pMatrixArrayUnaligned = p; + uintptr ip = (uintptr)p; + ip &= ~0x3f; + hier->pMatrixArray = (float32*)ip; + + hier->pNodeInfo = new RslHAnimNodeInfo[numNodes]; + for(int32 i = 0; i < numNodes; i++){ + hier->pNodeInfo[i].id = nodeIDs[i]; + hier->pNodeInfo[i].index = i; + hier->pNodeInfo[i].flags = nodeFlags[i]; + hier->pNodeInfo[i].frame = NULL; + } + hier->parentHierarchy = hier; + return hier; +} + +static void +hanimRead(Stream *stream, RslFrame *f) +{ + int32 version; + int32 id; + int32 numNodes; + int32 flags; + int32 maxKeySize; + uint32 *nodeFlags; + int32 *nodeIDs; + + version = stream->readI32(); + assert(version == 0x100); + id = stream->readI32(); + f->nodeId = id; + numNodes = stream->readI32(); + if(numNodes == 0) + return; + + flags = stream->readI32(); + maxKeySize = stream->readI32(); + nodeFlags = new uint32[numNodes]; + nodeIDs = new int32[numNodes]; + memset(nodeFlags, 0, numNodes*4); + memset(nodeIDs, 0, numNodes*4); + for(int32 i = 0; i < numNodes; i++){ + nodeIDs[i] = stream->readI32(); + stream->readI32(); + nodeFlags[i] = stream->readI32(); + } + f->hier = RslHAnimHierarchyCreate(numNodes, nodeFlags, + nodeIDs, flags, maxKeySize); + delete[] nodeFlags; + delete[] nodeIDs; +} + + +RslAtomic* +RslAtomicCreate(void) +{ + RslAtomic *a = new RslAtomic; + memset(a, 0, sizeof(RslAtomic)); + rslObjectInitialize(&a->object, 1, 0); + a->object.object.flags = 5; + a->object.object.privateFlags |= 1; + rslObjectHasFrameSetFrame(&a->object, NULL); + return a; +} + +RslAtomic* +RslAtomicSetFrame(RslAtomic *atomic, RslFrame *frame) +{ + rslObjectHasFrameSetFrame(&atomic->object, frame); + return atomic; +} + +RslAtomic* +RslAtomicStreamRead(Stream *stream, rslFrameList *framelist) +{ + uint32 length; + int32 buf[4]; + RslAtomic *a; + assert(findChunk(stream, ID_STRUCT, NULL, NULL)); + stream->read(buf, 16); + a = RslAtomicCreate(); + a->object.object.flags = buf[2]; + assert(findChunk(stream, ID_GEOMETRY, NULL, NULL)); + + RslPS2ResEntryHeader res, *rp; + stream->read(&res, sizeof(RslPS2ResEntryHeader)); + RslGeometry *g = RslGeometryCreatePS2(res.size & 0xFFFFF); + rp = (RslPS2ResEntryHeader*)(g+1); + *rp++ = res; + stream->read(rp, (res.size&0xFFFFF)-sizeof(RslPS2ResEntryHeader)); + + rslMaterialListStreamRead(stream, &g->matList); + a->geometry = g; + RslAtomicSetFrame(a, framelist->frames[buf[0]]); + + // This is not how it's done in LCS, they got extensions wrong :( + // Geometry + ChunkHeaderInfo header; + assert(findChunk(stream, ID_EXTENSION, &length, NULL)); + while(length){ + readChunkHeaderInfo(stream, &header); + if(header.type == ID_SKIN){ + g->skin = RslSkinStreamRead(stream, g); + }else + stream->seek(header.length); + length -= 12 + header.length; + } + + // Atomic + assert(findChunk(stream, ID_EXTENSION, &length, NULL)); + while(length){ + readChunkHeaderInfo(stream, &header); + stream->seek(header.length); + length -= 12 + header.length; + } + return a; +} + +RslSkin* +RslSkinStreamRead(Stream *stream, RslGeometry *g) +{ + uint32 info; + RslSkin *skin = new RslSkin; + memset(skin, 0, sizeof(RslSkin)); + info = stream->readU32(); + // LCS is different here, doesn't matter + info &= 0xFF; + skin->numBones = info; + skin->numUsedBones = info; + skin->invMatrices = new float[skin->numBones*16]; + stream->read(skin->invMatrices, skin->numBones*16*4); + return skin; +} + + + +RslClump* +RslClumpCreate(void) +{ + RslClump *clump = new RslClump; + rslObjectInitialize(&clump->object, 2, 0); + clump->atomicList.link.prev = &clump->atomicList.link; + clump->atomicList.link.next = &clump->atomicList.link; + return clump; +} + +RslClump* +RslClumpStreamRead(Stream *stream) +{ + uint32 version, length; + int32 buf[3]; + int32 numAtomics; + rslFrameList framelist; + RslClump *clump; + + assert(findChunk(stream, ID_STRUCT, NULL, &version)); + if(version > 0x33000){ + stream->read(buf, 12); + numAtomics = buf[0]; + }else + stream->read(&numAtomics, 4); + + clump = RslClumpCreate(); + assert(findChunk(stream, ID_FRAMELIST, NULL, NULL)); + rwFrameListStreamRead(stream, &framelist); + clump->object.parent = framelist.frames[0]; + + for(int32 i = 0; i < numAtomics; i++){ + assert(findChunk(stream, ID_ATOMIC, NULL, &version)); + RslAtomic *a = RslAtomicStreamRead(stream, &framelist); + RslClumpAddAtomic(clump, a); + } + + ChunkHeaderInfo header; + assert(findChunk(stream, ID_EXTENSION, &length, NULL)); + while(length){ + readChunkHeaderInfo(stream, &header); + stream->seek(header.length); + length -= 12 + header.length; + } + return clump; +} + +RslClump* +RslClumpAddAtomic(RslClump *clump, RslAtomic *a) +{ + a->inClumpLink.prev = &clump->atomicList.link; + a->inClumpLink.next = clump->atomicList.link.next; + clump->atomicList.link.next->prev = &a->inClumpLink; + clump->atomicList.link.next = &a->inClumpLink; + a->clump = clump; + return clump; +} + +RslClump* +RslClumpForAllAtomics(RslClump *clump, RslAtomicCallBack callback, void *pData) +{ + RslAtomic *a; + RslLLLink *link; + for(link = rslLLLinkGetNext(&clump->atomicList.link); + link != &clump->atomicList.link; + link = link->next){ + a = rslLLLinkGetData(link, RslAtomic, inClumpLink); + if(callback(a, pData) == NULL) + break; + } + return clump; +} + +RslGeometry* +RslGeometryCreatePS2(uint32 sz) +{ + sz += sizeof(RslGeometry); + RslGeometry *g = (RslGeometry*)new uint8[sz]; + memset(g, 0, sz); + rslObjectInitialize(&g->object, 8, 0); + g->refCount = 1; + return g; +} + +RslGeometry* +RslGeometryForAllMaterials(RslGeometry *geometry, RslMaterialCallBack fpCallBack, void *pData) +{ + for(int32 i = 0; i < geometry->matList.numMaterials; i++) + if(fpCallBack(geometry->matList.materials[i], pData) == NULL) + break; + return geometry; +} + +struct RslMaterialChunkInfo +{ + int32 flags; + RslRGBA color; // used + int32 unused; + bool32 textured; // used + SurfaceProperties surfaceProps; +}; + +RslMaterial* +RslMaterialCreate(void) +{ + RslMaterial *mat = new RslMaterial; + mat->texture = NULL; + mat->color = RslRGBA{255, 255, 255, 255}; + mat->refCount = 1; + mat->matfx = NULL; + return mat; +} + +RslMaterial* +RslMaterialStreamRead(Stream *stream) +{ + uint32 length; + RslMaterialChunkInfo chunk; + assert(findChunk(stream, ID_STRUCT, NULL, NULL)); + stream->read(&chunk, sizeof(chunk)); + RslMaterial *mat = RslMaterialCreate(); + mat->color = chunk.color; + if(chunk.textured) + mat->texture = RslTextureStreamRead(stream); + + ChunkHeaderInfo header; + assert(findChunk(stream, ID_EXTENSION, &length, NULL)); + while(length){ + readChunkHeaderInfo(stream, &header); + if(header.type == ID_MATFX) + matfxRead(stream, mat); + else + stream->seek(header.length); + length -= 12 + header.length; + } + return mat; +} + +void +RslMatFXMaterialSetEffects(RslMaterial *mat, int32 effect) +{ + if(effect != MatFX::NOTHING){ + if(mat->matfx == NULL){ + mat->matfx = new RslMatFX; + memset(mat->matfx, 0, sizeof(RslMatFX)); + } + mat->matfx->effectType = effect; + }else{ + RslMatFX *matfx = mat->matfx; + if(matfx->env.texture) + RslTextureDestroy(matfx->env.texture); + delete matfx; + mat->matfx = NULL; + } +} + +void +matfxRead(Stream *stream, RslMaterial *mat) +{ + int32 effect = stream->readI32(); + RslMatFXMaterialSetEffects(mat, effect); + if(effect == MatFX::BUMPMAP){ + stream->seek(12); + return; + } + RslMatFX *mfx = mat->matfx; + int32 type = stream->readI32(); + float32 coef; + int32 fbalpha; + switch(type){ + case MatFX::ENVMAP: + coef = stream->readF32(); + fbalpha = stream->readI32(); + mfx->env.frame = NULL; + mfx->env.texture = RslTextureStreamRead(stream); + mfx->env.intensity = coef; + break; + case MatFX::BUMPMAP: + coef = stream->readF32(); + break; + } +} + +void +rpMaterialListAppendMaterial(RslMaterialList *matlist, RslMaterial *mat) +{ + if(matlist->space <= matlist->numMaterials){ + matlist->space += 16; + RslMaterial **mats = matlist->materials; + matlist->materials = new RslMaterial*[matlist->space]; + if(matlist->space-16) + memcpy(matlist->materials, mats, (matlist->space+16)*sizeof(RslMaterial*)); + delete[] mats; + } + matlist->materials[matlist->numMaterials++] = mat; +} + +void +rslMaterialListStreamRead(Stream *stream, RslMaterialList *matlist) +{ + int32 numMaterials; + RslMaterial *mat; + assert(findChunk(stream, ID_MATLIST, NULL, NULL)); + assert(findChunk(stream, ID_STRUCT, NULL, NULL)); + numMaterials = stream->readI32(); + int32 *refs = new int32[numMaterials]; + stream->read(refs, 4*numMaterials); + for(int32 i = 0; i < numMaterials; i++){ + assert(refs[i] < 0); + assert(findChunk(stream, ID_MATERIAL, NULL, NULL)); + mat = RslMaterialStreamRead(stream); + rpMaterialListAppendMaterial(matlist, mat); + } + delete[] refs; +} + +RslTexDictionary* +RslTexDictionaryCreate(void) +{ + RslTexDictionary *dict = new RslTexDictionary; + memset(dict, 0, sizeof(RslTexDictionary)); + rslObjectInitialize(&dict->object, 6, 0); + dict->texturesInDict.link.prev = &dict->texturesInDict.link; + dict->texturesInDict.link.next = &dict->texturesInDict.link; + return dict; +} + +RslTexture* +RslTexDictionaryAddTexture(RslTexDictionary *dict, RslTexture *tex) +{ + if(tex->dict){ + tex->lInDictionary.prev->next = tex->lInDictionary.next; + tex->lInDictionary.next->prev = tex->lInDictionary.prev; + } + tex->dict = dict; + tex->lInDictionary.prev = &dict->texturesInDict.link; + tex->lInDictionary.next = dict->texturesInDict.link.next; + dict->texturesInDict.link.next->prev = &tex->lInDictionary; + dict->texturesInDict.link.next = &tex->lInDictionary; + return tex; +} + +RslTexDictionary* +RslTexDictionaryForAllTextures(RslTexDictionary *dict, RslTextureCallBack fpCallBack, void *pData) +{ + RslTexture *t; + RslLLLink *link; + for(link = rslLLLinkGetNext(&dict->texturesInDict.link); + link != &dict->texturesInDict.link; + link = link->next){ + t = rslLLLinkGetData(link, RslTexture, lInDictionary); + if(fpCallBack(t, pData) == NULL) + break; + } + return dict; +} + +// TODO! +void +RslTextureDestroy(RslTexture *texture) +{ + delete texture; +} + +RslTexture* +RslTextureCreate(RslRaster *raster) +{ + RslTexture *tex = new RslTexture; + memset(tex, 0, sizeof(RslTexture)); + tex->raster = raster; + return tex; +} + +RslTexture* +RslTextureStreamRead(Stream *stream) +{ + uint32 length; + RslTexture *tex = RslTextureCreate(NULL); + assert(findChunk(stream, ID_TEXTURE, NULL, NULL)); + assert(findChunk(stream, ID_STRUCT, NULL, NULL)); + stream->readI32(); // filter addressing + assert(findChunk(stream, ID_STRING, &length, NULL)); + stream->read(tex->name, length); + assert(findChunk(stream, ID_STRING, &length, NULL)); + stream->read(tex->mask, length); + + ChunkHeaderInfo header; + assert(findChunk(stream, ID_EXTENSION, &length, NULL)); + while(length){ + readChunkHeaderInfo(stream, &header); + stream->seek(header.length); + length -= 12 + header.length; + } + return tex; +} + +static uint32 +guessSwizzling(uint32 w, uint32 h, uint32 d, uint32 mipmaps) +{ + uint32 swiz = 0; + for(uint32 i = 0; i < mipmaps; i++){ + switch(d){ + case 4: + if(w >= 32 && h >= 16) + swiz |= 1<= 16 && h >= 4) + swiz |= 1<flags = 0; + r->flags |= logw&0x3F; + r->flags |= (logh&0x3F)<<6; + r->flags |= d << 12; + r->flags |= mipmaps << 20; + uint32 swiz = guessSwizzling(w, h, d, mipmaps); + r->flags |= swiz << 24; + return (RslRaster*)r; +} + +RslTexture* +RslReadNativeTexturePS2(Stream *stream) +{ + RslPs2StreamRaster rasterInfo; + uint32 len; + uint32 buf[2]; + RslTexture *tex = RslTextureCreate(NULL); + assert(findChunk(stream, ID_STRUCT, NULL, NULL)); + stream->read(buf, sizeof(buf)); + assert(buf[0] == 0x00505350); /* "PSP\0" */ + assert(findChunk(stream, ID_STRING, &len, NULL)); + stream->read(tex->name, len); + assert(findChunk(stream, ID_STRING, &len, NULL)); + stream->read(tex->mask, len); + assert(findChunk(stream, ID_STRUCT, NULL, NULL)); + assert(findChunk(stream, ID_STRUCT, &len, NULL)); + stream->read(&rasterInfo, sizeof(rasterInfo)); + assert(findChunk(stream, ID_STRUCT, &len, NULL)); + tex->raster = RslCreateRasterPS2(rasterInfo.width, + rasterInfo.height, rasterInfo.depth, rasterInfo.mipmaps); + tex->raster->ps2.data = new uint8[len]; + stream->read(tex->raster->ps2.data, len); + assert(findChunk(stream, ID_EXTENSION, &len, NULL)); + stream->seek(len); + return tex; +} + +RslTexDictionary* +RslTexDictionaryStreamRead(Stream *stream) +{ + assert(findChunk(stream, ID_STRUCT, NULL, NULL)); + int32 numTex = stream->readI32(); + RslTexDictionary *txd = RslTexDictionaryCreate(); + for(int32 i = 0; i < numTex; i++){ + assert(findChunk(stream, ID_TEXTURENATIVE, NULL, NULL)); + RslTexture *tex = RslReadNativeTexturePS2(stream); + RslTexDictionaryAddTexture(txd, tex); + } + return txd; +} diff --git a/tools/rsltest/rsl.h b/tools/rsltest/rsl.h index d7dcbb1..10a8292 100644 --- a/tools/rsltest/rsl.h +++ b/tools/rsltest/rsl.h @@ -42,12 +42,41 @@ typedef RslAtomic *(*RslAtomicCallBack)(RslAtomic *atomic, void *data); typedef RslMaterial *(*RslMaterialCallBack)(RslMaterial *material, void *data); typedef RslTexture *(*RslTextureCallBack)(RslTexture *texture, void *pData); -struct RslLLLink { +struct RslRGBA +{ + uint8 red; + uint8 green; + uint8 blue; + uint8 alpha; +}; + +struct RslV3d +{ + float32 x, y, z; +}; + +struct RslMatrix +{ + RslV3d right; + uint32 flags; + RslV3d up; + uint32 pad1; + RslV3d at; + uint32 pad2; + RslV3d pos; + uint32 pad3; +}; + +void RslMatrixSetIdentity(RslMatrix *matrix); + +struct RslLLLink +{ RslLLLink *next; RslLLLink *prev; }; -struct RslLinkList { +struct RslLinkList +{ RslLLLink link; }; @@ -68,20 +97,31 @@ struct RslLinkList { ((linkvar)->next) struct RslObject { - uint8 type; - uint8 subType; - uint8 flags; - uint8 privateFlags; - void *parent; + uint8 type; + uint8 subType; + uint8 flags; + uint8 privateFlags; + void *parent; }; +#define rslObjectInitialize(o, t, s) \ +{ \ + ((RslObject*)(o))->type = (uint8)(t); \ + ((RslObject*)(o))->subType = (uint8)(s); \ + ((RslObject*)(o))->flags = 0; \ + ((RslObject*)(o))->privateFlags = 0; \ + ((RslObject*)(o))->parent = NULL; \ +} + +#define rslObjectGetParent(object) (((const RslObject *)(object))->parent) + struct RslObjectHasFrame { RslObject object; RslLLLink lFrame; void (*sync)(); }; -#define rslObjectGetParent(object) (((const RslObject *)(object))->parent) +void rslObjectHasFrameSetFrame(RslObjectHasFrame *object, RslFrame *f); struct RslRasterPS2 { uint8 *data; @@ -110,6 +150,8 @@ union RslRaster { RslRasterPSP psp; }; +RslRaster *RslCreateRasterPS2(uint32 w, uint32 h, uint32 d, uint32 mipmaps); + struct RslTexDictionary { RslObject object; RslLinkList texturesInDict; @@ -119,6 +161,7 @@ struct RslTexDictionary { RslTexDictionary *RslTexDictionaryStreamRead(Stream *stream); RslTexDictionary *RslTexDictionaryCreate(void); RslTexture *RslTexDictionaryAddTexture(RslTexDictionary *dict, RslTexture *tex); +RslTexDictionary *RslTexDictionaryForAllTextures(RslTexDictionary *dict, RslTextureCallBack fpCallBack, void *pData); struct RslTexture { RslRaster *raster; @@ -129,13 +172,16 @@ struct RslTexture { }; RslTexture *RslTextureCreate(RslRaster *raster); +void RslTextureDestroy(RslTexture *texture); +RslTexture *RslTextureStreamRead(Stream *stream); +RslTexture *RslReadNativeTexturePS2(Stream *stream); struct RslFrame { - RslObject object; - RslLLLink inDirtyListLink; // ? + RslObject object; + RslLinkList objectList; - float32 modelling[16]; - float32 ltm[16]; + RslMatrix modelling; + RslMatrix ltm; RslFrame *child; RslFrame *next; RslFrame *root; @@ -149,6 +195,16 @@ struct RslFrame { int32 hierId; }; +RslFrame *RslFrameCreate(void); +RslFrame *RslFrameAddChild(RslFrame *parent, RslFrame *child); +RslFrame *RslFrameForAllChildren(RslFrame *frame, RslFrameCallBack callBack, void *data); + +struct rslFrameList +{ + RslFrame **frames; + int32 numFrames; +}; + struct RslClump { RslObject object; RslLinkList atomicList; @@ -157,6 +213,10 @@ struct RslClump { #define RslClumpGetFrame(_clump) \ ((RslFrame *) rslObjectGetParent(_clump)) +RslClump *RslClumpStreamRead(Stream *stream); +RslClump *RslClumpAddAtomic(RslClump *clump, RslAtomic *a); +RslClump *RslClumpForAllAtomics(RslClump *clump, RslAtomicCallBack callback, void *pData); + struct RslAtomic { RslObjectHasFrame object; RslGeometry *geometry; @@ -176,6 +236,10 @@ struct RslAtomic { #define RslAtomicGetFrame(_atomic) \ ((RslFrame *) rslObjectGetParent(_atomic)) +RslAtomic *RslAtomicCreate(void); +RslAtomic *RslAtomicSetFrame(RslAtomic *atomic, RslFrame *frame); +RslAtomic *RslAtomicStreamRead(Stream *stream, rslFrameList *framelist); + struct RslMaterialList { RslMaterial **materials; int32 numMaterials; @@ -193,9 +257,15 @@ struct RslGeometry { uint32 pad2; // 0xAAAAAAAA }; +RslGeometry *RslGeometryCreatePS2(uint32 sz); +RslGeometry *RslGeometryForAllMaterials(RslGeometry *geometry, RslMaterialCallBack fpCallBack, void *pData); + struct RslMatFXEnv { RslFrame *frame; - char *texname; + union { + char *texname; + RslTexture *texture; + }; float32 intensity; }; @@ -207,12 +277,18 @@ struct RslMatFX { }; struct RslMaterial { - char *texname; - uint32 color; + union { + char *texname; + RslTexture *texture; + }; + RslRGBA color; uint32 refCount; RslMatFX *matfx; }; +RslMaterial *RslMaterialCreate(void); +RslMaterial *RslMaterialStreamRead(Stream *stream); + struct RslHAnimNodeInfo { int8 id; int8 index; @@ -262,6 +338,8 @@ struct RslSkin { void *data; // NULL }; +RslSkin *RslSkinStreamRead(Stream *stream, RslGeometry *g); + struct RslPS2ResEntryHeader { float32 bound[4]; uint32 size; // and numMeshes @@ -275,9 +353,9 @@ struct RslPS2ResEntryHeader { }; struct RslPS2InstanceData { - float32 bound[4]; // ? + float32 bound[4]; float32 uvScale[2]; - int32 unk1; + int32 unknown; uint32 dmaPacket; uint16 numTriangles; int16 matID; diff --git a/tools/rsltest/rsltest.cpp b/tools/rsltest/rsltest.cpp index 706ed87..31d4b73 100644 --- a/tools/rsltest/rsltest.cpp +++ b/tools/rsltest/rsltest.cpp @@ -29,174 +29,6 @@ RslStream::relocate(void) } } -RslFrame* -RslFrameForAllChildren(RslFrame *frame, RslFrameCallBack callBack, void *data) -{ - for(RslFrame *child = frame->child; - child; - child = child->next) - if(callBack(child, data) == NULL) - break; - return frame; -} - -RslClump* -RslClumpForAllAtomics(RslClump *clump, RslAtomicCallBack callback, void *pData) -{ - RslAtomic *a; - RslLLLink *link; - for(link = rslLLLinkGetNext(&clump->atomicList.link); - link != &clump->atomicList.link; - link = link->next){ - a = rslLLLinkGetData(link, RslAtomic, inClumpLink); - if(callback(a, pData) == NULL) - break; - } - return clump; -} - -RslGeometry* -RslGeometryForAllMaterials(RslGeometry *geometry, RslMaterialCallBack fpCallBack, void *pData) -{ - for(int32 i = 0; i < geometry->matList.numMaterials; i++) - if(fpCallBack(geometry->matList.materials[i], pData) == NULL) - break; - return geometry; -} - -RslTexDictionary* -RslTexDictionaryCreate(void) -{ - RslTexDictionary *dict = new RslTexDictionary; - memset(dict, 0, sizeof(RslTexDictionary)); - dict->object.type = 6; - dict->texturesInDict.link.prev = &dict->texturesInDict.link; - dict->texturesInDict.link.next = &dict->texturesInDict.link; - return dict; -} - -RslTexture* -RslTexDictionaryAddTexture(RslTexDictionary *dict, RslTexture *tex) -{ - if(tex->dict){ - tex->lInDictionary.prev->next = tex->lInDictionary.next; - tex->lInDictionary.next->prev = tex->lInDictionary.prev; - } - tex->dict = dict; - tex->lInDictionary.prev = &dict->texturesInDict.link; - tex->lInDictionary.next = dict->texturesInDict.link.next; - dict->texturesInDict.link.next->prev = &tex->lInDictionary; - dict->texturesInDict.link.next = &tex->lInDictionary; - return tex; -} - -RslTexDictionary* -RslTexDictionaryForAllTextures(RslTexDictionary *dict, RslTextureCallBack fpCallBack, void *pData) -{ - RslTexture *t; - RslLLLink *link; - for(link = rslLLLinkGetNext(&dict->texturesInDict.link); - link != &dict->texturesInDict.link; - link = link->next){ - t = rslLLLinkGetData(link, RslTexture, lInDictionary); - if(fpCallBack(t, pData) == NULL) - break; - } - return dict; -} - -uint32 -guessSwizzling(uint32 w, uint32 h, uint32 d, uint32 mipmaps) -{ - uint32 swiz = 0; - for(uint32 i = 0; i < mipmaps; i++){ - switch(d){ - case 4: - if(w >= 32 && h >= 16) - swiz |= 1<= 16 && h >= 4) - swiz |= 1<flags = 0; - r->flags |= logw&0x3F; - r->flags |= (logh&0x3F)<<6; - r->flags |= d << 12; - r->flags |= mipmaps << 20; - uint32 swiz = guessSwizzling(w, h, d, mipmaps); - r->flags |= swiz << 24; - return (RslRaster*)r; -} - -RslTexture* -RslReadNativeTexturePS2(Stream *stream) -{ - RslPs2StreamRaster rasterInfo; - uint32 len; - uint32 buf[2]; - RslTexture *tex = RslTextureCreate(NULL); - assert(findChunk(stream, ID_STRUCT, NULL, NULL)); - stream->read(buf, sizeof(buf)); - assert(buf[0] == 0x00505350); /* "PSP\0" */ - assert(findChunk(stream, ID_STRING, &len, NULL)); - stream->read(tex->name, len); - assert(findChunk(stream, ID_STRING, &len, NULL)); - stream->read(tex->mask, len); - assert(findChunk(stream, ID_STRUCT, NULL, NULL)); - assert(findChunk(stream, ID_STRUCT, &len, NULL)); - stream->read(&rasterInfo, sizeof(rasterInfo)); - assert(findChunk(stream, ID_STRUCT, &len, NULL)); - tex->raster = RslCreateRasterPS2(rasterInfo.width, - rasterInfo.height, rasterInfo.depth, rasterInfo.mipmaps); - tex->raster->ps2.data = new uint8[len]; - stream->read(tex->raster->ps2.data, len); - assert(findChunk(stream, ID_EXTENSION, &len, NULL)); - stream->seek(len); - return tex; -} - -RslTexDictionary* -RslTexDictionaryStreamRead(Stream *stream) -{ - assert(findChunk(stream, ID_STRUCT, NULL, NULL)); - int32 numTex = stream->readI32(); - RslTexDictionary *txd = RslTexDictionaryCreate(); - for(int32 i = 0; i < numTex; i++){ - assert(findChunk(stream, ID_TEXTURENATIVE, NULL, NULL)); - RslTexture *tex = RslReadNativeTexturePS2(stream); - RslTexDictionaryAddTexture(txd, tex); - } - return txd; -} - -RslTexture* -RslTextureCreate(RslRaster *raster) -{ - RslTexture *tex = new RslTexture; - memset(tex, 0, sizeof(RslTexture)); - tex->raster = raster; - return tex; -} - - RslFrame *dumpFrameCB(RslFrame *frame, void *data) @@ -569,13 +401,19 @@ main(int argc, char *argv[]) uint32 ident = stream.readU32(); stream.seek(0, 0); - if(ident == 0x16){ + if(ident == ID_TEXDICTIONARY){ findChunk(&stream, ID_TEXDICTIONARY, NULL, NULL); txd = RslTexDictionaryStreamRead(&stream); stream.close(); assert(txd); goto writeTxd; } + if(ident == 0x10){ + findChunk(&stream, ID_CLUMP, NULL, NULL); + clump = RslClumpStreamRead(&stream); + stream.close(); + return 0; + } RslStream *rslstr = new RslStream; stream.read(rslstr, 0x20); diff --git a/tools/rsltest/rsltest.vcxproj b/tools/rsltest/rsltest.vcxproj index 20dabb5..0526364 100644 --- a/tools/rsltest/rsltest.vcxproj +++ b/tools/rsltest/rsltest.vcxproj @@ -80,6 +80,7 @@ +