mirror of
https://github.com/aap/librw.git
synced 2024-11-25 21:25:42 +00:00
moved iOS dff converter to rsltest
This commit is contained in:
parent
a42bfb90ac
commit
79c89ebbba
@ -65,7 +65,6 @@ Global
|
|||||||
{B487F101-0C2B-4F99-A1E0-B0B0C0F3FE7E}.Release|Win32.ActiveCfg = Release|Win32
|
{B487F101-0C2B-4F99-A1E0-B0B0C0F3FE7E}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
{B487F101-0C2B-4F99-A1E0-B0B0C0F3FE7E}.Release|Win32.Build.0 = Release|Win32
|
{B487F101-0C2B-4F99-A1E0-B0B0C0F3FE7E}.Release|Win32.Build.0 = Release|Win32
|
||||||
{B487F101-0C2B-4F99-A1E0-B0B0C0F3FE7E}.Release|x64.ActiveCfg = Release|x64
|
{B487F101-0C2B-4F99-A1E0-B0B0C0F3FE7E}.Release|x64.ActiveCfg = Release|x64
|
||||||
{B487F101-0C2B-4F99-A1E0-B0B0C0F3FE7E}.Release|x64.Build.0 = Release|x64
|
|
||||||
{85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Debug - null|Win32.ActiveCfg = Debug - null|Win32
|
{85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Debug - null|Win32.ActiveCfg = Debug - null|Win32
|
||||||
{85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Debug - null|x64.ActiveCfg = Debug - null|x64
|
{85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Debug - null|x64.ActiveCfg = Debug - null|x64
|
||||||
{85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Debug|Win32.ActiveCfg = Debug|Win32
|
{85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
@ -74,8 +73,8 @@ Global
|
|||||||
{85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Release|Win32.ActiveCfg = Release|Win32
|
{85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
{85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Release|Win32.Build.0 = Release|Win32
|
{85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Release|Win32.Build.0 = Release|Win32
|
||||||
{85F56A7D-6EA2-4B9B-806A-87AF6C577FDF}.Release|x64.ActiveCfg = Release|x64
|
{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.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 - null|x64.ActiveCfg = Debug - null|x64
|
||||||
{2592ED29-F258-4949-AB45-7B873BF697F7}.Debug|Win32.ActiveCfg = Debug|Win32
|
{2592ED29-F258-4949-AB45-7B873BF697F7}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
{2592ED29-F258-4949-AB45-7B873BF697F7}.Debug|x64.ActiveCfg = Debug|x64
|
{2592ED29-F258-4949-AB45-7B873BF697F7}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
@ -83,7 +82,6 @@ Global
|
|||||||
{2592ED29-F258-4949-AB45-7B873BF697F7}.Release|Win32.ActiveCfg = Release|Win32
|
{2592ED29-F258-4949-AB45-7B873BF697F7}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
{2592ED29-F258-4949-AB45-7B873BF697F7}.Release|Win32.Build.0 = Release|Win32
|
{2592ED29-F258-4949-AB45-7B873BF697F7}.Release|Win32.Build.0 = Release|Win32
|
||||||
{2592ED29-F258-4949-AB45-7B873BF697F7}.Release|x64.ActiveCfg = Release|x64
|
{2592ED29-F258-4949-AB45-7B873BF697F7}.Release|x64.ActiveCfg = Release|x64
|
||||||
{2592ED29-F258-4949-AB45-7B873BF697F7}.Release|x64.Build.0 = Release|x64
|
|
||||||
{E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Debug - null|Win32.ActiveCfg = Debug - null|Win32
|
{E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Debug - null|Win32.ActiveCfg = Debug - null|Win32
|
||||||
{E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Debug - null|x64.ActiveCfg = Debug - null|x64
|
{E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Debug - null|x64.ActiveCfg = Debug - null|x64
|
||||||
{E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Debug|Win32.ActiveCfg = Debug|Win32
|
{E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
@ -93,7 +91,6 @@ Global
|
|||||||
{E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Release|Win32.ActiveCfg = Release|Win32
|
{E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
{E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Release|Win32.Build.0 = Release|Win32
|
{E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Release|Win32.Build.0 = Release|Win32
|
||||||
{E5D477C8-4CAF-43BF-B7E3-6689503D469F}.Release|x64.ActiveCfg = Release|x64
|
{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.ActiveCfg = Debug - null|Win32
|
||||||
{403C35A9-6D06-4261-B305-9ED000F00136}.Debug - null|x64.ActiveCfg = Debug - null|x64
|
{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|Win32.ActiveCfg = Debug|Win32
|
||||||
@ -102,7 +99,6 @@ Global
|
|||||||
{403C35A9-6D06-4261-B305-9ED000F00136}.Release|Win32.ActiveCfg = Release|Win32
|
{403C35A9-6D06-4261-B305-9ED000F00136}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
{403C35A9-6D06-4261-B305-9ED000F00136}.Release|Win32.Build.0 = Release|Win32
|
{403C35A9-6D06-4261-B305-9ED000F00136}.Release|Win32.Build.0 = Release|Win32
|
||||||
{403C35A9-6D06-4261-B305-9ED000F00136}.Release|x64.ActiveCfg = Release|x64
|
{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.ActiveCfg = Debug - null|Win32
|
||||||
{27ECE916-900F-49B2-8E9F-95E6B347E161}.Debug - null|Win32.Build.0 = 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 - null|x64.ActiveCfg = Debug - null|Win32
|
||||||
|
@ -193,7 +193,6 @@
|
|||||||
<ClCompile Include="src\geometry.cpp" />
|
<ClCompile Include="src\geometry.cpp" />
|
||||||
<ClCompile Include="src\gtaplg.cpp" />
|
<ClCompile Include="src\gtaplg.cpp" />
|
||||||
<ClCompile Include="src\image.cpp" />
|
<ClCompile Include="src\image.cpp" />
|
||||||
<ClCompile Include="src\mdl.cpp" />
|
|
||||||
<ClCompile Include="src\ogl.cpp" />
|
<ClCompile Include="src\ogl.cpp" />
|
||||||
<ClCompile Include="src\pipeline.cpp" />
|
<ClCompile Include="src\pipeline.cpp" />
|
||||||
<ClCompile Include="src\plugins.cpp" />
|
<ClCompile Include="src\plugins.cpp" />
|
||||||
|
1
rw.h
1
rw.h
@ -8,4 +8,3 @@
|
|||||||
#include "src/rwd3d8.h"
|
#include "src/rwd3d8.h"
|
||||||
#include "src/rwd3d9.h"
|
#include "src/rwd3d9.h"
|
||||||
#include "src/rwogl.h"
|
#include "src/rwogl.h"
|
||||||
#include "src/mdl.h"
|
|
||||||
|
@ -31,6 +31,7 @@ Frame::Frame(void)
|
|||||||
this->matrix[5] = 1.0f;
|
this->matrix[5] = 1.0f;
|
||||||
this->matrix[10] = 1.0f;
|
this->matrix[10] = 1.0f;
|
||||||
this->matrix[15] = 1.0f;
|
this->matrix[15] = 1.0f;
|
||||||
|
this->matflag = 0;
|
||||||
this->dirty = true;
|
this->dirty = true;
|
||||||
constructPlugins();
|
constructPlugins();
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,10 @@ Geometry::Geometry(int32 numVerts, int32 numTris, uint32 flags)
|
|||||||
}
|
}
|
||||||
this->morphTargets = new MorphTarget[1];
|
this->morphTargets = new MorphTarget[1];
|
||||||
MorphTarget *m = this->morphTargets;
|
MorphTarget *m = this->morphTargets;
|
||||||
|
m->boundingSphere[0] = 0.0f;
|
||||||
|
m->boundingSphere[1] = 0.0f;
|
||||||
|
m->boundingSphere[2] = 0.0f;
|
||||||
|
m->boundingSphere[3] = 0.0f;
|
||||||
m->vertices = NULL;
|
m->vertices = NULL;
|
||||||
m->normals = NULL;
|
m->normals = NULL;
|
||||||
if(!(this->geoflags & NATIVE) && this->numVertices){
|
if(!(this->geoflags & NATIVE) && this->numVertices){
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
#include "rwps2.h"
|
#include "rwps2.h"
|
||||||
#include "rwd3d.h"
|
#include "rwd3d.h"
|
||||||
#include "rwxbox.h"
|
#include "rwxbox.h"
|
||||||
#include "mdl.h"
|
|
||||||
#include "gtaplg.h"
|
#include "gtaplg.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@ -82,8 +81,6 @@ attachPlugins(void)
|
|||||||
gta::register2dEffectPlugin();
|
gta::register2dEffectPlugin();
|
||||||
gta::registerPipelinePlugin();
|
gta::registerPipelinePlugin();
|
||||||
|
|
||||||
registerRslPlugin();
|
|
||||||
|
|
||||||
rw::Atomic::init();
|
rw::Atomic::init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,6 +153,12 @@ registerNodeNamePlugin(void)
|
|||||||
getSizeNodeName);
|
getSizeNodeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
getNodeName(Frame *f)
|
||||||
|
{
|
||||||
|
return PLUGINOFFSET(char, f, nodeNameOffset);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Geometry
|
// Geometry
|
||||||
//
|
//
|
||||||
|
@ -25,6 +25,7 @@ void attachPlugins(void);
|
|||||||
|
|
||||||
extern int32 nodeNameOffset;
|
extern int32 nodeNameOffset;
|
||||||
void registerNodeNamePlugin(void);
|
void registerNodeNamePlugin(void);
|
||||||
|
char *getNodeName(Frame *f);
|
||||||
|
|
||||||
// Breakable model
|
// Breakable model
|
||||||
|
|
||||||
|
@ -130,18 +130,19 @@ Texture::read(const char *name, const char *mask)
|
|||||||
tex = new Texture;
|
tex = new Texture;
|
||||||
strncpy(tex->name, name, 32);
|
strncpy(tex->name, name, 32);
|
||||||
strncpy(tex->mask, mask, 32);
|
strncpy(tex->mask, mask, 32);
|
||||||
char *n = (char*)malloc(strlen(name) + 5);
|
// char *n = (char*)malloc(strlen(name) + 5);
|
||||||
strcpy(n, name);
|
// strcpy(n, name);
|
||||||
strcat(n, ".tga");
|
// strcat(n, ".tga");
|
||||||
Image *img = readTGA(n);
|
// Image *img = readTGA(n);
|
||||||
free(n);
|
// free(n);
|
||||||
if(img){
|
// if(img){
|
||||||
raster = Raster::createFromImage(img);
|
// //raster = Raster::createFromImage(img);
|
||||||
delete img;
|
// raster = new Raster(0, 0, 0, 0x80);
|
||||||
}else
|
// delete img;
|
||||||
|
// }else
|
||||||
raster = new Raster(0, 0, 0, 0x80);
|
raster = new Raster(0, 0, 0, 0x80);
|
||||||
tex->raster = raster;
|
tex->raster = raster;
|
||||||
if(currentTexDictionary && img)
|
if(currentTexDictionary /*&& img*/)
|
||||||
currentTexDictionary->add(tex);
|
currentTexDictionary->add(tex);
|
||||||
return tex;
|
return tex;
|
||||||
}
|
}
|
||||||
|
602
src/mdl.cpp
602
src/mdl.cpp
@ -1,602 +0,0 @@
|
|||||||
#include <cstdio>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstring>
|
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
#include <new>
|
|
||||||
|
|
||||||
#include "rwbase.h"
|
|
||||||
#include "rwplugin.h"
|
|
||||||
#include "rwpipeline.h"
|
|
||||||
#include "rwobjects.h"
|
|
||||||
#include "rwps2.h"
|
|
||||||
#include "rwogl.h"
|
|
||||||
#include "rwxbox.h"
|
|
||||||
#include "rwd3d8.h"
|
|
||||||
#include "rwd3d9.h"
|
|
||||||
#include "mdl.h"
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace rw;
|
|
||||||
|
|
||||||
enum {
|
|
||||||
ID_RSL = 0xf00d0000
|
|
||||||
};
|
|
||||||
int32 rslPluginOffset;
|
|
||||||
|
|
||||||
struct RslMesh
|
|
||||||
{
|
|
||||||
float32 bound[4]; // ?
|
|
||||||
float32 uvScale[2];
|
|
||||||
uint32 unknown;
|
|
||||||
uint32 dmaOffset;
|
|
||||||
uint16 numTriangles;
|
|
||||||
int16 matID;
|
|
||||||
float32 pos[3]; // ?
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RslGeometry
|
|
||||||
{
|
|
||||||
float32 bound[4];
|
|
||||||
uint32 size;
|
|
||||||
int32 flags;
|
|
||||||
int32 unknown[4];
|
|
||||||
float32 scale[3];
|
|
||||||
float32 pos[3];
|
|
||||||
|
|
||||||
uint32 numMeshes;
|
|
||||||
RslMesh *meshes;
|
|
||||||
uint32 dataSize;
|
|
||||||
uint8 *data;
|
|
||||||
};
|
|
||||||
|
|
||||||
float32
|
|
||||||
halfFloat(uint16 half)
|
|
||||||
{
|
|
||||||
uint32 f = (uint32)(half & 0x7fff) << 13;
|
|
||||||
uint32 sgn = (uint32)(half & 0x8000) << 16;
|
|
||||||
f += 0x38000000;
|
|
||||||
if((half & 0x7c00) == 0) f = 0;
|
|
||||||
f |= sgn;
|
|
||||||
return *(float32*)&f;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32
|
|
||||||
unpackSize(uint32 unpack)
|
|
||||||
{
|
|
||||||
if((unpack&0x6F000000) == 0x6F000000)
|
|
||||||
return 2;
|
|
||||||
static uint32 size[] = { 32, 16, 8, 16 };
|
|
||||||
return ((unpack>>26 & 3)+1)*size[unpack>>24 & 3]/8;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
analyzeDMA(uint8 *p)
|
|
||||||
{
|
|
||||||
uint32 *w = (uint32*)p;
|
|
||||||
uint32 *end;
|
|
||||||
end = (uint32*)(p + ((w[0] & 0xFFFF) + 1)*0x10);
|
|
||||||
w += 4;
|
|
||||||
int flags = 0;
|
|
||||||
while(w < end){
|
|
||||||
if((w[0] & 0x60000000) == 0x60000000){
|
|
||||||
// printf("UNPACK %x %x\n", w[0], unpackSize(w[0]));
|
|
||||||
printf("UNPACK %x %x %x\n", w[0] & 0x7F004000, w[0], unpackSize(w[0]));
|
|
||||||
uint32 type = w[0] & 0x7F004000;
|
|
||||||
if(w[0] != 0x6c018000){
|
|
||||||
if(type == 0x79000000)
|
|
||||||
flags |= 0x1;
|
|
||||||
if(type == 0x76004000)
|
|
||||||
flags |= 0x10;
|
|
||||||
if(type == 0x6a000000)
|
|
||||||
flags |= 0x100;
|
|
||||||
if(type == 0x6f000000)
|
|
||||||
flags |= 0x1000;
|
|
||||||
if(type == 0x6c000000)
|
|
||||||
flags |= 0x10000;
|
|
||||||
}
|
|
||||||
int32 n = (w[0] >> 16) & 0xFF;
|
|
||||||
p = (uint8*)(w+1);
|
|
||||||
p += (n*unpackSize(w[0])+3)&~3;
|
|
||||||
w = (uint32*)p;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
switch(w[0] & 0x7F000000){
|
|
||||||
case 0x20000000: // STMASK
|
|
||||||
printf("STMASK %x\n", w[1]);
|
|
||||||
w++;
|
|
||||||
break;
|
|
||||||
case 0x30000000:
|
|
||||||
printf("STROW %x %x %x %x\n", w[1], w[2], w[3], w[4]);
|
|
||||||
w+=4;
|
|
||||||
break;
|
|
||||||
case 0x31000000:
|
|
||||||
printf("STCOL %x %x %x %x\n", w[1], w[2], w[3], w[4]);
|
|
||||||
w+=4;
|
|
||||||
break;
|
|
||||||
case 0x14000000:
|
|
||||||
printf("MSCAL %x\n", w[0]&0xFFFF);
|
|
||||||
return flags;
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
printf("vif: %x\n", w[0]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
w++;
|
|
||||||
}
|
|
||||||
return flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32*
|
|
||||||
skipUnpack(uint32 *p)
|
|
||||||
{
|
|
||||||
int32 n = (p[0] >> 16) & 0xFF;
|
|
||||||
return p + (n*unpackSize(p[0])+3 >> 2) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
convertRslMesh(Geometry *g, RslGeometry *rg, Mesh *m, RslMesh *rm)
|
|
||||||
{
|
|
||||||
ps2::SkinVertex v;
|
|
||||||
uint32 mask = 0x1001; // tex coords, vertices
|
|
||||||
if(g->geoflags & Geometry::NORMALS)
|
|
||||||
mask |= 0x10;
|
|
||||||
if(g->geoflags & Geometry::PRELIT)
|
|
||||||
mask |= 0x100;
|
|
||||||
float32 *verts = &g->morphTargets[0].vertices[g->numVertices*3];
|
|
||||||
float32 *norms = &g->morphTargets[0].normals[g->numVertices*3];
|
|
||||||
uint8 *cols = &g->colors[g->numVertices*4];
|
|
||||||
float32 *texCoords = &g->texCoords[0][g->numVertices*2];
|
|
||||||
uint8 *indices = NULL;
|
|
||||||
float32 *weights = NULL;
|
|
||||||
Skin *skin = *PLUGINOFFSET(Skin*, g, skinGlobals.offset);
|
|
||||||
if(skin){
|
|
||||||
indices = &skin->indices[g->numVertices*4];
|
|
||||||
weights = &skin->weights[g->numVertices*4];
|
|
||||||
mask |= 0x10000;
|
|
||||||
}
|
|
||||||
|
|
||||||
int16 *vuVerts = NULL;
|
|
||||||
int8 *vuNorms = NULL;
|
|
||||||
uint8 *vuTex = NULL;
|
|
||||||
uint16 *vuCols = NULL;
|
|
||||||
uint32 *vuSkin = NULL;
|
|
||||||
|
|
||||||
uint8 *p = rg->data + rm->dmaOffset;
|
|
||||||
uint32 *w = (uint32*)p;
|
|
||||||
uint32 *end = (uint32*)(p + ((w[0] & 0xFFFF) + 1)*0x10);
|
|
||||||
w += 4;
|
|
||||||
int flags = 0;
|
|
||||||
int32 nvert;
|
|
||||||
bool first = 1;
|
|
||||||
while(w < end){
|
|
||||||
/* Get data pointers */
|
|
||||||
|
|
||||||
// GIFtag probably
|
|
||||||
assert(w[0] == 0x6C018000); // UNPACK
|
|
||||||
nvert = w[4] & 0x7FFF;
|
|
||||||
if(!first) nvert -=2;
|
|
||||||
w += 5;
|
|
||||||
|
|
||||||
// positions
|
|
||||||
assert(w[0] == 0x20000000); // STMASK
|
|
||||||
w += 2;
|
|
||||||
assert(w[0] == 0x30000000); // STROW
|
|
||||||
w += 5;
|
|
||||||
assert((w[0] & 0xFF004000) == 0x79000000);
|
|
||||||
vuVerts = (int16*)(w+1);
|
|
||||||
if(!first) vuVerts += 2*3;
|
|
||||||
w = skipUnpack(w);
|
|
||||||
|
|
||||||
// tex coords
|
|
||||||
assert(w[0] == 0x20000000); // STMASK
|
|
||||||
w += 2;
|
|
||||||
assert(w[0] == 0x30000000); // STROW
|
|
||||||
w += 5;
|
|
||||||
assert((w[0] & 0xFF004000) == 0x76004000);
|
|
||||||
vuTex = (uint8*)(w+1);
|
|
||||||
if(!first) vuTex += 2*2;
|
|
||||||
w = skipUnpack(w);
|
|
||||||
|
|
||||||
if(g->geoflags & Geometry::NORMALS){
|
|
||||||
assert((w[0] & 0xFF004000) == 0x6A000000);
|
|
||||||
vuNorms = (int8*)(w+1);
|
|
||||||
if(!first) vuNorms += 2*3;
|
|
||||||
w = skipUnpack(w);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(g->geoflags & Geometry::PRELIT){
|
|
||||||
assert((w[0] & 0xFF004000) == 0x6F000000);
|
|
||||||
vuCols = (uint16*)(w+1);
|
|
||||||
if(!first) vuCols += 2;
|
|
||||||
w = skipUnpack(w);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(skin){
|
|
||||||
assert((w[0] & 0xFF004000) == 0x6C000000);
|
|
||||||
vuSkin = w+1;
|
|
||||||
if(!first) vuSkin += 2*4;
|
|
||||||
w = skipUnpack(w);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(w[0] == 0x14000006); // MSCAL
|
|
||||||
w++;
|
|
||||||
while(w[0] == 0) w++;
|
|
||||||
|
|
||||||
/* Insert Data */
|
|
||||||
for(int32 i = 0; i < nvert; i++){
|
|
||||||
v.p[0] = vuVerts[0]/32768.0f*rg->scale[0] + rg->pos[0];
|
|
||||||
v.p[1] = vuVerts[1]/32768.0f*rg->scale[1] + rg->pos[1];
|
|
||||||
v.p[2] = vuVerts[2]/32768.0f*rg->scale[2] + rg->pos[2];
|
|
||||||
v.t[0] = vuTex[0]/128.0f*rm->uvScale[0];
|
|
||||||
v.t[1] = vuTex[1]/128.0f*rm->uvScale[1];
|
|
||||||
if(mask & 0x10){
|
|
||||||
v.n[0] = vuNorms[0]/127.0f;
|
|
||||||
v.n[1] = vuNorms[1]/127.0f;
|
|
||||||
v.n[2] = vuNorms[2]/127.0f;
|
|
||||||
}
|
|
||||||
if(mask & 0x100){
|
|
||||||
v.c[0] = (vuCols[0] & 0x1f) * 255 / 0x1F;
|
|
||||||
v.c[1] = (vuCols[0]>>5 & 0x1f) * 255 / 0x1F;
|
|
||||||
v.c[2] = (vuCols[0]>>10 & 0x1f) * 255 / 0x1F;
|
|
||||||
v.c[3] = vuCols[0]&0x8000 ? 0xFF : 0;
|
|
||||||
}
|
|
||||||
if(mask & 0x10000){
|
|
||||||
for(int j = 0; j < 4; j++){
|
|
||||||
((uint32*)v.w)[j] = vuSkin[j] & ~0x3FF;
|
|
||||||
v.i[j] = vuSkin[j] >> 2;
|
|
||||||
//if(v.i[j]) v.i[j]--;
|
|
||||||
if(v.w[j] == 0.0f) v.i[j] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 idx = ps2::findVertexSkin(g, NULL, mask, &v);
|
|
||||||
if(idx < 0)
|
|
||||||
idx = g->numVertices++;
|
|
||||||
/* Insert mesh joining indices when we get the index of the first vertex
|
|
||||||
* in the first VU chunk of a non-first RslMesh. */
|
|
||||||
if(i == 0 && first && rm != &rg->meshes[0] && (rm-1)->matID == rm->matID){
|
|
||||||
m->indices[m->numIndices] = m->indices[m->numIndices-1];
|
|
||||||
m->numIndices++;
|
|
||||||
m->indices[m->numIndices++] = idx;
|
|
||||||
if((rm-1)->numTriangles % 2)
|
|
||||||
m->indices[m->numIndices++] = idx;
|
|
||||||
}
|
|
||||||
m->indices[m->numIndices++] = idx;
|
|
||||||
ps2::insertVertexSkin(g, idx, mask, &v);
|
|
||||||
|
|
||||||
vuVerts += 3;
|
|
||||||
vuTex += 2;
|
|
||||||
vuNorms += 3;
|
|
||||||
vuCols++;
|
|
||||||
vuSkin += 4;
|
|
||||||
}
|
|
||||||
first = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
convertRslGeometry(Geometry *g)
|
|
||||||
{
|
|
||||||
RslGeometry *rg = *PLUGINOFFSET(RslGeometry*, g, rslPluginOffset);
|
|
||||||
assert(rg != NULL);
|
|
||||||
|
|
||||||
g->meshHeader = new MeshHeader;
|
|
||||||
g->meshHeader->flags = 1;
|
|
||||||
g->meshHeader->numMeshes = g->numMaterials;
|
|
||||||
g->meshHeader->mesh = new Mesh[g->meshHeader->numMeshes];
|
|
||||||
g->meshHeader->totalIndices = 0;
|
|
||||||
Mesh *meshes = g->meshHeader->mesh;
|
|
||||||
for(uint32 i = 0; i < g->meshHeader->numMeshes; i++)
|
|
||||||
meshes[i].numIndices = 0;
|
|
||||||
RslMesh *rm = rg->meshes;
|
|
||||||
int32 lastId = -1;
|
|
||||||
for(uint32 i = 0; i < rg->numMeshes; i++, rm++){
|
|
||||||
Mesh *m = &meshes[rm->matID];
|
|
||||||
g->numVertices += rm->numTriangles+2;
|
|
||||||
m->numIndices += rm->numTriangles+2;
|
|
||||||
// Extra indices since we're merging tristrip
|
|
||||||
// meshes with the same material.
|
|
||||||
// Be careful with face winding.
|
|
||||||
if(lastId == rm->matID)
|
|
||||||
m->numIndices += (rm-1)->numTriangles % 2 ? 3 : 2;
|
|
||||||
lastId = rm->matID;
|
|
||||||
}
|
|
||||||
for(uint32 i = 0; i < g->meshHeader->numMeshes; i++){
|
|
||||||
g->meshHeader->mesh[i].material = g->materialList[i];
|
|
||||||
g->meshHeader->totalIndices += meshes[i].numIndices;
|
|
||||||
}
|
|
||||||
g->geoflags = Geometry::TRISTRIP |
|
|
||||||
Geometry::POSITIONS | /* 0x01 ? */
|
|
||||||
Geometry::TEXTURED | /* 0x04 ? */
|
|
||||||
Geometry::LIGHT;
|
|
||||||
if(g->hasColoredMaterial())
|
|
||||||
g->geoflags |= Geometry::MODULATE;
|
|
||||||
if(rg->flags & 0x2)
|
|
||||||
g->geoflags |= Geometry::NORMALS;
|
|
||||||
if(rg->flags & 0x8)
|
|
||||||
g->geoflags |= Geometry::PRELIT;
|
|
||||||
g->numTexCoordSets = 1;
|
|
||||||
|
|
||||||
g->allocateData();
|
|
||||||
g->meshHeader->allocateIndices();
|
|
||||||
|
|
||||||
Skin *skin = *PLUGINOFFSET(Skin*, g, skinGlobals.offset);
|
|
||||||
if(rg->flags & 0x10)
|
|
||||||
assert(skin);
|
|
||||||
if(skin){
|
|
||||||
uint8 *data = skin->data;
|
|
||||||
float *invMats = skin->inverseMatrices;
|
|
||||||
skin->init(skin->numBones, skin->numBones, g->numVertices);
|
|
||||||
memcpy(skin->inverseMatrices, invMats, skin->numBones*64);
|
|
||||||
delete[] data;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(uint32 i = 0; i < g->meshHeader->numMeshes; i++)
|
|
||||||
meshes[i].numIndices = 0;
|
|
||||||
g->numVertices = 0;
|
|
||||||
rm = rg->meshes;
|
|
||||||
for(uint32 i = 0; i < rg->numMeshes; i++, rm++)
|
|
||||||
convertRslMesh(g, rg, &meshes[rm->matID], rm);
|
|
||||||
|
|
||||||
if(skin){
|
|
||||||
skin->findNumWeights(g->numVertices);
|
|
||||||
skin->findUsedBones(g->numVertices);
|
|
||||||
}
|
|
||||||
g->calculateBoundingSphere();
|
|
||||||
g->generateTriangles();
|
|
||||||
}
|
|
||||||
|
|
||||||
Geometry*
|
|
||||||
geometryStreamReadRsl(Stream *stream)
|
|
||||||
{
|
|
||||||
RslGeometry *rg = new RslGeometry;
|
|
||||||
stream->read(rg, 0x40);
|
|
||||||
rg->numMeshes = rg->size >> 20;
|
|
||||||
rg->size &= 0xFFFFF;
|
|
||||||
rg->meshes = new RslMesh[rg->numMeshes];
|
|
||||||
rg->dataSize = rg->size - 0x40;
|
|
||||||
stream->read(rg->meshes, rg->numMeshes*sizeof(RslMesh));
|
|
||||||
rg->dataSize -= rg->numMeshes*sizeof(RslMesh);
|
|
||||||
rg->data = new uint8[rg->dataSize];
|
|
||||||
stream->read(rg->data, rg->dataSize);
|
|
||||||
|
|
||||||
Geometry *g = new Geometry(0, 0, 0);
|
|
||||||
*PLUGINOFFSET(RslGeometry*, g, rslPluginOffset) = rg;
|
|
||||||
|
|
||||||
assert(findChunk(stream, ID_MATLIST, NULL, NULL));
|
|
||||||
assert(findChunk(stream, ID_STRUCT, NULL, NULL));
|
|
||||||
g->numMaterials = stream->readI32();
|
|
||||||
g->materialList = new Material*[g->numMaterials];
|
|
||||||
stream->seek(g->numMaterials*4); // unused (-1)
|
|
||||||
for(int32 i = 0; i < g->numMaterials; i++){
|
|
||||||
assert(findChunk(stream, ID_MATERIAL, NULL, NULL));
|
|
||||||
g->materialList[i] = Material::streamRead(stream);
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
return g;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
geometryStreamWriteRsl(Stream *stream, Geometry *g)
|
|
||||||
{
|
|
||||||
uint32 buf[3] = { ID_GEOMETRY, geometryStreamGetSizeRsl(g), 0xf00d };
|
|
||||||
stream->write(&buf, 12);
|
|
||||||
|
|
||||||
RslGeometry *rg = *PLUGINOFFSET(RslGeometry*, g, rslPluginOffset);
|
|
||||||
assert(rg != NULL);
|
|
||||||
rg->size |= rg->numMeshes << 20;
|
|
||||||
stream->write(rg, 0x40);
|
|
||||||
rg->numMeshes = rg->size >> 20;
|
|
||||||
rg->size &= 0xFFFFF;
|
|
||||||
stream->write(rg->meshes, rg->numMeshes*sizeof(RslMesh));
|
|
||||||
stream->write(rg->data, rg->dataSize);
|
|
||||||
|
|
||||||
uint32 size = 12 + 4;
|
|
||||||
for(int32 i = 0; i < g->numMaterials; i++)
|
|
||||||
size += 4 + 12 + g->materialList[i]->streamGetSize();
|
|
||||||
writeChunkHeader(stream, ID_MATLIST, size);
|
|
||||||
writeChunkHeader(stream, ID_STRUCT, 4 + g->numMaterials*4);
|
|
||||||
stream->writeI32(g->numMaterials);
|
|
||||||
for(int32 i = 0; i < g->numMaterials; i++)
|
|
||||||
stream->writeI32(-1);
|
|
||||||
for(int32 i = 0; i < g->numMaterials; i++)
|
|
||||||
g->materialList[i]->streamWrite(stream);
|
|
||||||
|
|
||||||
g->streamWritePlugins(stream);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32
|
|
||||||
geometryStreamGetSizeRsl(Geometry *g)
|
|
||||||
{
|
|
||||||
RslGeometry *rg = *PLUGINOFFSET(RslGeometry*, g, rslPluginOffset);
|
|
||||||
assert(rg != NULL);
|
|
||||||
|
|
||||||
uint32 size = rg->size;
|
|
||||||
size += 12 + 12 + 4;
|
|
||||||
for(int32 i = 0; i < g->numMaterials; i++)
|
|
||||||
size += 4 + 12 + g->materialList[i]->streamGetSize();
|
|
||||||
size += 12 + g->streamGetPluginSize();
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32 atomicRights[2];
|
|
||||||
|
|
||||||
Atomic*
|
|
||||||
atomicStreamReadRsl(Stream *stream, Frame **frameList)
|
|
||||||
{
|
|
||||||
int32 buf[4];
|
|
||||||
uint32 version;
|
|
||||||
assert(findChunk(stream, ID_STRUCT, NULL, &version));
|
|
||||||
stream->read(buf, 16);
|
|
||||||
Atomic *atomic = new Atomic;
|
|
||||||
atomic->frame = frameList[buf[0]];
|
|
||||||
assert(findChunk(stream, ID_GEOMETRY, NULL, &version));
|
|
||||||
assert(version == 0x00f00d00);
|
|
||||||
atomic->geometry = geometryStreamReadRsl(stream);
|
|
||||||
|
|
||||||
atomicRights[0] = 0;
|
|
||||||
atomic->streamReadPlugins(stream);
|
|
||||||
if(atomicRights[0])
|
|
||||||
atomic->assertRights(atomicRights[0], atomicRights[1]);
|
|
||||||
return atomic;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
atomicStreamWriteRsl(Stream *stream, Atomic *a, Frame **frameList, int32 numFrames)
|
|
||||||
{
|
|
||||||
int32 buf[4] = { 0, 0, 5, 0 };
|
|
||||||
Clump *c = a->clump;
|
|
||||||
if(c == NULL)
|
|
||||||
return false;
|
|
||||||
writeChunkHeader(stream, ID_ATOMIC, atomicStreamGetSizeRsl(a));
|
|
||||||
buf[0] = findPointer((void*)a->frame, (void**)frameList, numFrames);
|
|
||||||
writeChunkHeader(stream, ID_STRUCT, 16);
|
|
||||||
stream->write(buf, sizeof(buf));
|
|
||||||
|
|
||||||
geometryStreamWriteRsl(stream, a->geometry);
|
|
||||||
|
|
||||||
a->streamWritePlugins(stream);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32
|
|
||||||
atomicStreamGetSizeRsl(Atomic *a)
|
|
||||||
{
|
|
||||||
uint32 size = 12 + 12 + 12 + a->streamGetPluginSize();
|
|
||||||
size += 16 + geometryStreamGetSizeRsl(a->geometry);
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
Clump*
|
|
||||||
clumpStreamReadRsl(Stream *stream)
|
|
||||||
{
|
|
||||||
uint32 length, version;
|
|
||||||
int32 buf[3];
|
|
||||||
Clump *clump;
|
|
||||||
assert(findChunk(stream, ID_STRUCT, &length, &version));
|
|
||||||
clump = new Clump;
|
|
||||||
stream->read(buf, length);
|
|
||||||
clump->numAtomics = buf[0];
|
|
||||||
clump->numLights = 0;
|
|
||||||
clump->numCameras = 0;
|
|
||||||
|
|
||||||
// Frame list
|
|
||||||
Frame **frameList;
|
|
||||||
int32 numFrames;
|
|
||||||
clump->frameListStreamRead(stream, &frameList, &numFrames);
|
|
||||||
clump->parent = (void*)frameList[0];
|
|
||||||
|
|
||||||
Geometry **geometryList = 0;
|
|
||||||
|
|
||||||
// Atomics
|
|
||||||
if(clump->numAtomics)
|
|
||||||
clump->atomicList = new Atomic*[clump->numAtomics];
|
|
||||||
for(int32 i = 0; i < clump->numAtomics; i++){
|
|
||||||
assert(findChunk(stream, ID_ATOMIC, NULL, NULL));
|
|
||||||
clump->atomicList[i] = atomicStreamReadRsl(stream, frameList);
|
|
||||||
clump->atomicList[i]->clump = clump;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete[] frameList;
|
|
||||||
|
|
||||||
clump->streamReadPlugins(stream);
|
|
||||||
return clump;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
clumpStreamWriteRsl(Stream *stream, Clump *c)
|
|
||||||
{
|
|
||||||
int size = clumpStreamGetSizeRsl(c);
|
|
||||||
writeChunkHeader(stream, ID_CLUMP, size);
|
|
||||||
int buf[3] = { c->numAtomics, 0, 0 };
|
|
||||||
writeChunkHeader(stream, ID_STRUCT, 4);
|
|
||||||
stream->write(buf, 4);
|
|
||||||
|
|
||||||
int32 numFrames = ((Frame*)c->parent)->count();
|
|
||||||
Frame **flist = new Frame*[numFrames];
|
|
||||||
makeFrameList((Frame*)c->parent, flist);
|
|
||||||
|
|
||||||
c->frameListStreamWrite(stream, flist, numFrames);
|
|
||||||
|
|
||||||
for(int32 i = 0; i < c->numAtomics; i++)
|
|
||||||
atomicStreamWriteRsl(stream, c->atomicList[i], flist, numFrames);
|
|
||||||
|
|
||||||
delete[] flist;
|
|
||||||
|
|
||||||
c->streamWritePlugins(stream);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Frame*
|
|
||||||
sizeCB(Frame *f, void *size)
|
|
||||||
{
|
|
||||||
*(int32*)size += f->streamGetPluginSize();
|
|
||||||
f->forAllChildren(sizeCB, size);
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32
|
|
||||||
clumpStreamGetSizeRsl(Clump *c)
|
|
||||||
{
|
|
||||||
uint32 size = 0;
|
|
||||||
size += 12; // Struct
|
|
||||||
size += 4; // numAtomics
|
|
||||||
|
|
||||||
// frame list
|
|
||||||
// TODO: make this into a function
|
|
||||||
int32 numFrames = ((Frame*)c->parent)->count();
|
|
||||||
size += 12 + 12 + 4 + numFrames*(56+12);
|
|
||||||
sizeCB((Frame*)c->parent, (void*)&size);
|
|
||||||
|
|
||||||
// atomics
|
|
||||||
for(int32 i = 0; i < c->numAtomics; i++)
|
|
||||||
size += 12 + atomicStreamGetSizeRsl(c->atomicList[i]);
|
|
||||||
|
|
||||||
size += 12 + c->streamGetPluginSize();
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void*
|
|
||||||
createRslGeo(void *object, int32 offset, int32)
|
|
||||||
{
|
|
||||||
*PLUGINOFFSET(RslGeometry*, object, offset) = NULL;
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void*
|
|
||||||
destroyRslGeo(void *object, int32 offset, int32)
|
|
||||||
{
|
|
||||||
RslGeometry *rg = *PLUGINOFFSET(RslGeometry*, object, offset);
|
|
||||||
delete rg->data;
|
|
||||||
delete rg->meshes;
|
|
||||||
delete rg;
|
|
||||||
*PLUGINOFFSET(RslGeometry*, object, offset) = NULL;
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void*
|
|
||||||
copyRslGeo(void *dst, void *src, int32 offset, int32)
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
return dst;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
registerRslPlugin(void)
|
|
||||||
{
|
|
||||||
rslPluginOffset = Geometry::registerPlugin(sizeof(RslGeometry*), ID_RSL,
|
|
||||||
createRslGeo,
|
|
||||||
destroyRslGeo,
|
|
||||||
copyRslGeo);
|
|
||||||
}
|
|
13
src/mdl.h
13
src/mdl.h
@ -1,13 +0,0 @@
|
|||||||
rw::Clump *clumpStreamReadRsl(rw::Stream *stream);
|
|
||||||
bool clumpStreamWriteRsl(rw::Stream *stream, rw::Clump *c);
|
|
||||||
rw::uint32 clumpStreamGetSizeRsl(rw::Clump *c);
|
|
||||||
|
|
||||||
rw::Atomic *atomicStreamReadRsl(rw::Stream *stream, rw::Frame **frameList);
|
|
||||||
rw::uint32 atomicStreamGetSizeRsl(rw::Atomic *a);
|
|
||||||
|
|
||||||
rw::Geometry *geometryStreamReadRsl(rw::Stream *stream);
|
|
||||||
rw::uint32 geometryStreamGetSizeRsl(rw::Geometry *g);
|
|
||||||
|
|
||||||
void convertRslGeometry(rw::Geometry *g);
|
|
||||||
|
|
||||||
void registerRslPlugin(void);
|
|
@ -499,7 +499,7 @@ readSkin(Stream *stream, int32 len, void *object, int32 offset, int32)
|
|||||||
skin->init(header[0], header[1], geometry->numVertices);
|
skin->init(header[0], header[1], geometry->numVertices);
|
||||||
skin->numWeights = header[2];
|
skin->numWeights = header[2];
|
||||||
|
|
||||||
if(!oldFormat && !skinGlobals.forceSkipUsedBones)
|
if(!oldFormat)
|
||||||
stream->read(skin->usedBones, skin->numUsedBones);
|
stream->read(skin->usedBones, skin->numUsedBones);
|
||||||
if(skin->indices)
|
if(skin->indices)
|
||||||
stream->read(skin->indices, geometry->numVertices*4);
|
stream->read(skin->indices, geometry->numVertices*4);
|
||||||
@ -826,6 +826,22 @@ MatFX::getEffectIndex(uint32 type)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MatFX::setEnvTexture(Texture *t)
|
||||||
|
{
|
||||||
|
int32 i = this->getEffectIndex(ENVMAP);
|
||||||
|
if(i >= 0)
|
||||||
|
this->fx[i].env.tex = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MatFX::setEnvCoefficient(float32 coef)
|
||||||
|
{
|
||||||
|
int32 i = this->getEffectIndex(ENVMAP);
|
||||||
|
if(i >= 0)
|
||||||
|
this->fx[i].env.coefficient = coef;
|
||||||
|
}
|
||||||
|
|
||||||
static void*
|
static void*
|
||||||
createMaterialMatFX(void *object, int32 offset, int32)
|
createMaterialMatFX(void *object, int32 offset, int32)
|
||||||
{
|
{
|
||||||
@ -889,13 +905,7 @@ readMaterialMatFX(Stream *stream, int32, void *object, int32 offset, int32)
|
|||||||
*PLUGINOFFSET(MatFX*, object, offset) = matfx;
|
*PLUGINOFFSET(MatFX*, object, offset) = matfx;
|
||||||
matfx->setEffects(stream->readU32());
|
matfx->setEffects(stream->readU32());
|
||||||
|
|
||||||
if(matfx->type == MatFX::BUMPMAP && matFXGlobals.hack){
|
for(int i = 0; i < 2; i++){
|
||||||
stream->seek(12);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 n = matFXGlobals.hack ? 1 : 2;
|
|
||||||
for(int i = 0; i < n; i++){
|
|
||||||
uint32 type = stream->readU32();
|
uint32 type = stream->readU32();
|
||||||
switch(type){
|
switch(type){
|
||||||
case MatFX::BUMPMAP:
|
case MatFX::BUMPMAP:
|
||||||
@ -920,9 +930,6 @@ readMaterialMatFX(Stream *stream, int32, void *object, int32 offset, int32)
|
|||||||
|
|
||||||
case MatFX::ENVMAP:
|
case MatFX::ENVMAP:
|
||||||
coefficient = stream->readF32();
|
coefficient = stream->readF32();
|
||||||
if(matFXGlobals.hack)
|
|
||||||
fbAlpha = 0;
|
|
||||||
else
|
|
||||||
fbAlpha = stream->readI32();
|
fbAlpha = stream->readI32();
|
||||||
tex = NULL;
|
tex = NULL;
|
||||||
if(stream->readI32()){
|
if(stream->readI32()){
|
||||||
|
@ -8,6 +8,7 @@ struct Object
|
|||||||
void *parent;
|
void *parent;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: missing: list of attached objects
|
||||||
struct Frame : PluginBase<Frame>, Object
|
struct Frame : PluginBase<Frame>, Object
|
||||||
{
|
{
|
||||||
typedef Frame *(*Callback)(Frame *f, void *data);
|
typedef Frame *(*Callback)(Frame *f, void *data);
|
||||||
@ -270,6 +271,8 @@ struct MatFX
|
|||||||
|
|
||||||
void setEffects(uint32 flags);
|
void setEffects(uint32 flags);
|
||||||
int32 getEffectIndex(uint32 type);
|
int32 getEffectIndex(uint32 type);
|
||||||
|
void setEnvTexture(Texture *t);
|
||||||
|
void setEnvCoefficient(float32 coef);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MatFXGlobals
|
struct MatFXGlobals
|
||||||
@ -277,7 +280,6 @@ struct MatFXGlobals
|
|||||||
int32 atomicOffset;
|
int32 atomicOffset;
|
||||||
int32 materialOffset;
|
int32 materialOffset;
|
||||||
ObjPipeline *pipelines[NUM_PLATFORMS];
|
ObjPipeline *pipelines[NUM_PLATFORMS];
|
||||||
bool32 hack;
|
|
||||||
};
|
};
|
||||||
extern MatFXGlobals matFXGlobals;
|
extern MatFXGlobals matFXGlobals;
|
||||||
void registerMatFXPlugin(void);
|
void registerMatFXPlugin(void);
|
||||||
@ -387,7 +389,6 @@ struct SkinGlobals
|
|||||||
{
|
{
|
||||||
int32 offset;
|
int32 offset;
|
||||||
ObjPipeline *pipelines[NUM_PLATFORMS];
|
ObjPipeline *pipelines[NUM_PLATFORMS];
|
||||||
bool32 forceSkipUsedBones;
|
|
||||||
};
|
};
|
||||||
extern SkinGlobals skinGlobals;
|
extern SkinGlobals skinGlobals;
|
||||||
void registerSkinPlugin(void);
|
void registerSkinPlugin(void);
|
||||||
|
@ -74,8 +74,8 @@ setMaterial(Material *mat)
|
|||||||
{
|
{
|
||||||
D3DMATERIAL9 mat9;
|
D3DMATERIAL9 mat9;
|
||||||
D3DCOLORVALUE black = { 0, 0, 0, 0 };
|
D3DCOLORVALUE black = { 0, 0, 0, 0 };
|
||||||
float ambmult = mat->surfaceProps[0]/255.0f;
|
float ambmult = mat->surfaceProps.ambient/255.0f;
|
||||||
float diffmult = mat->surfaceProps[2]/255.0f;
|
float diffmult = mat->surfaceProps.diffuse/255.0f;
|
||||||
mat9.Ambient.r = mat->color[0]*ambmult;
|
mat9.Ambient.r = mat->color[0]*ambmult;
|
||||||
mat9.Ambient.g = mat->color[1]*ambmult;
|
mat9.Ambient.g = mat->color[1]*ambmult;
|
||||||
mat9.Ambient.b = mat->color[2]*ambmult;
|
mat9.Ambient.b = mat->color[2]*ambmult;
|
||||||
|
@ -25,37 +25,6 @@ struct {
|
|||||||
|
|
||||||
char *argv0;
|
char *argv0;
|
||||||
|
|
||||||
Frame*
|
|
||||||
findHierCB(Frame *f, void *p)
|
|
||||||
{
|
|
||||||
HAnimData *hanim = PLUGINOFFSET(HAnimData, f, hAnimOffset);
|
|
||||||
if(hanim->hierarchy){
|
|
||||||
*(HAnimHierarchy**)p = hanim->hierarchy;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
f->forAllChildren(findHierCB, p);
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
HAnimHierarchy*
|
|
||||||
getHierarchy(Clump *c)
|
|
||||||
{
|
|
||||||
HAnimHierarchy *hier = NULL;
|
|
||||||
findHierCB((Frame*)c->parent, &hier);
|
|
||||||
return hier;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
fixLcsHier(HAnimHierarchy *hier)
|
|
||||||
{
|
|
||||||
hier->maxInterpKeyFrameSize = findAnimInterpolatorInfo(1)->keyFrameSize;
|
|
||||||
for(int32 i = 0; i < hier->numNodes; i++){
|
|
||||||
int32 id = hier->nodeInfo[i].id;
|
|
||||||
if(id == 255) hier->nodeInfo[i].id = -1;
|
|
||||||
else if(id > 0x80) hier->nodeInfo[i].id |= 0x1300;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
@ -64,7 +33,6 @@ usage(void)
|
|||||||
fprintf(stderr, "\t-i instance\n");
|
fprintf(stderr, "\t-i instance\n");
|
||||||
fprintf(stderr, "\t-v RW version, e.g. 33004 for 3.3.0.4\n");
|
fprintf(stderr, "\t-v RW version, e.g. 33004 for 3.3.0.4\n");
|
||||||
fprintf(stderr, "\t-o output platform. ps2, xbox, mobile, d3d8, d3d9\n");
|
fprintf(stderr, "\t-o output platform. ps2, xbox, mobile, d3d8, d3d9\n");
|
||||||
fprintf(stderr, "\t-s expect iOS LCS dff as input\n");
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +52,6 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
int uninstance = 0;
|
int uninstance = 0;
|
||||||
int instance = 0;
|
int instance = 0;
|
||||||
int lcs = 0;
|
|
||||||
int outplatform = rw::PLATFORM_D3D8;
|
int outplatform = rw::PLATFORM_D3D8;
|
||||||
|
|
||||||
char *s;
|
char *s;
|
||||||
@ -110,9 +77,6 @@ main(int argc, char *argv[])
|
|||||||
outplatform = PLATFORM_D3D8;
|
outplatform = PLATFORM_D3D8;
|
||||||
found:
|
found:
|
||||||
break;
|
break;
|
||||||
case 's':
|
|
||||||
lcs++;
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
usage();
|
usage();
|
||||||
}ARGEND;
|
}ARGEND;
|
||||||
@ -122,9 +86,6 @@ main(int argc, char *argv[])
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
matFXGlobals.hack = lcs;
|
|
||||||
skinGlobals.forceSkipUsedBones = lcs;
|
|
||||||
|
|
||||||
if(argc < 1)
|
if(argc < 1)
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
@ -145,9 +106,6 @@ main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
assert(header.type == ID_CLUMP);
|
assert(header.type == ID_CLUMP);
|
||||||
debugFile = argv[0];
|
debugFile = argv[0];
|
||||||
if(lcs)
|
|
||||||
c = clumpStreamReadRsl(&in);
|
|
||||||
else
|
|
||||||
c = Clump::streamRead(&in);
|
c = Clump::streamRead(&in);
|
||||||
assert(c != NULL);
|
assert(c != NULL);
|
||||||
in.close();
|
in.close();
|
||||||
@ -173,18 +131,6 @@ main(int argc, char *argv[])
|
|||||||
switchPipes(c, rw::platform);
|
switchPipes(c, rw::platform);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(lcs){
|
|
||||||
HAnimHierarchy *hier = getHierarchy(c);
|
|
||||||
if(hier)
|
|
||||||
fixLcsHier(hier);
|
|
||||||
for(int32 i = 0; i < c->numAtomics; i++){
|
|
||||||
Skin *skin = *PLUGINOFFSET(Skin*, c->atomicList[i]->geometry, skinGlobals.offset);
|
|
||||||
convertRslGeometry(c->atomicList[i]->geometry);
|
|
||||||
if(skin)
|
|
||||||
c->atomicList[i]->pipeline = skinGlobals.pipelines[rw::platform];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(uninstance)
|
if(uninstance)
|
||||||
for(int32 i = 0; i < c->numAtomics; i++){
|
for(int32 i = 0; i < c->numAtomics; i++){
|
||||||
Atomic *a = c->atomicList[i];
|
Atomic *a = c->atomicList[i];
|
||||||
|
@ -80,6 +80,15 @@ RslFrameAddChild(RslFrame *parent, RslFrame *child)
|
|||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
RslFrameCount(RslFrame *f)
|
||||||
|
{
|
||||||
|
int32 n = 1;
|
||||||
|
for(RslFrame *c = f->child; c; c = c->next)
|
||||||
|
n += RslFrameCount(c);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
RslFrame*
|
RslFrame*
|
||||||
RslFrameForAllChildren(RslFrame *frame, RslFrameCallBack callBack, void *data)
|
RslFrameForAllChildren(RslFrame *frame, RslFrameCallBack callBack, void *data)
|
||||||
{
|
{
|
||||||
@ -99,7 +108,7 @@ struct StreamFrame
|
|||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
rwFrameListStreamRead(Stream *stream, rslFrameList *framelist)
|
rslFrameListStreamRead(Stream *stream, rslFrameList *framelist)
|
||||||
{
|
{
|
||||||
uint32 length;
|
uint32 length;
|
||||||
StreamFrame strfrm;
|
StreamFrame strfrm;
|
||||||
@ -140,6 +149,25 @@ rwFrameListStreamRead(Stream *stream, rslFrameList *framelist)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static RslFrame**
|
||||||
|
rslFrameListFill(RslFrame *f, RslFrame **flist)
|
||||||
|
{
|
||||||
|
*flist++ = f;
|
||||||
|
if(f->next)
|
||||||
|
flist = rslFrameListFill(f->next, flist);
|
||||||
|
if(f->child)
|
||||||
|
flist = rslFrameListFill(f->child, flist);
|
||||||
|
return flist;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rslFrameListInitialize(rslFrameList *frameList, RslFrame *root)
|
||||||
|
{
|
||||||
|
frameList->numFrames = RslFrameCount(root);
|
||||||
|
frameList->frames = new RslFrame*[frameList->numFrames];
|
||||||
|
rslFrameListFill(root, frameList->frames);
|
||||||
|
}
|
||||||
|
|
||||||
RslHAnimHierarchy*
|
RslHAnimHierarchy*
|
||||||
RslHAnimHierarchyCreate(int32 numNodes, uint32 *nodeFlags, int32 *nodeIDs, int32 flags, int32 maxKeySize)
|
RslHAnimHierarchyCreate(int32 numNodes, uint32 *nodeFlags, int32 *nodeIDs, int32 flags, int32 maxKeySize)
|
||||||
{
|
{
|
||||||
@ -320,7 +348,7 @@ RslClumpStreamRead(Stream *stream)
|
|||||||
|
|
||||||
clump = RslClumpCreate();
|
clump = RslClumpCreate();
|
||||||
assert(findChunk(stream, ID_FRAMELIST, NULL, NULL));
|
assert(findChunk(stream, ID_FRAMELIST, NULL, NULL));
|
||||||
rwFrameListStreamRead(stream, &framelist);
|
rslFrameListStreamRead(stream, &framelist);
|
||||||
clump->object.parent = framelist.frames[0];
|
clump->object.parent = framelist.frames[0];
|
||||||
|
|
||||||
for(int32 i = 0; i < numAtomics; i++){
|
for(int32 i = 0; i < numAtomics; i++){
|
||||||
@ -336,6 +364,7 @@ RslClumpStreamRead(Stream *stream)
|
|||||||
stream->seek(header.length);
|
stream->seek(header.length);
|
||||||
length -= 12 + header.length;
|
length -= 12 + header.length;
|
||||||
}
|
}
|
||||||
|
delete[] framelist.frames;
|
||||||
return clump;
|
return clump;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -365,6 +394,18 @@ RslClumpForAllAtomics(RslClump *clump, RslAtomicCallBack callback, void *pData)
|
|||||||
return clump;
|
return clump;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
RslClumpGetNumAtomics(RslClump *clump)
|
||||||
|
{
|
||||||
|
int32 n = 0;
|
||||||
|
RslLLLink *link;
|
||||||
|
for(link = rslLLLinkGetNext(&clump->atomicList.link);
|
||||||
|
link != &clump->atomicList.link;
|
||||||
|
link = link->next)
|
||||||
|
n++;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
RslGeometry*
|
RslGeometry*
|
||||||
RslGeometryCreatePS2(uint32 sz)
|
RslGeometryCreatePS2(uint32 sz)
|
||||||
{
|
{
|
||||||
@ -479,11 +520,11 @@ void
|
|||||||
rpMaterialListAppendMaterial(RslMaterialList *matlist, RslMaterial *mat)
|
rpMaterialListAppendMaterial(RslMaterialList *matlist, RslMaterial *mat)
|
||||||
{
|
{
|
||||||
if(matlist->space <= matlist->numMaterials){
|
if(matlist->space <= matlist->numMaterials){
|
||||||
matlist->space += 16;
|
|
||||||
RslMaterial **mats = matlist->materials;
|
RslMaterial **mats = matlist->materials;
|
||||||
matlist->materials = new RslMaterial*[matlist->space];
|
matlist->materials = new RslMaterial*[matlist->space+16];
|
||||||
if(matlist->space-16)
|
if(matlist->space)
|
||||||
memcpy(matlist->materials, mats, (matlist->space+16)*sizeof(RslMaterial*));
|
memcpy(matlist->materials, mats, matlist->space*sizeof(RslMaterial*));
|
||||||
|
matlist->space += 16;
|
||||||
delete[] mats;
|
delete[] mats;
|
||||||
}
|
}
|
||||||
matlist->materials[matlist->numMaterials++] = mat;
|
matlist->materials[matlist->numMaterials++] = mat;
|
||||||
|
@ -113,7 +113,8 @@ struct RslObject {
|
|||||||
((RslObject*)(o))->parent = NULL; \
|
((RslObject*)(o))->parent = NULL; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define rslObjectGetParent(object) (((const RslObject *)(object))->parent)
|
#define rslObjectGetParent(object) (((RslObject*)(object))->parent)
|
||||||
|
#define rslObjectSetParent(c,p) (((RslObject*)(c))->parent) = (void*)(p)
|
||||||
|
|
||||||
struct RslObjectHasFrame {
|
struct RslObjectHasFrame {
|
||||||
RslObject object;
|
RslObject object;
|
||||||
@ -197,6 +198,7 @@ struct RslFrame {
|
|||||||
|
|
||||||
RslFrame *RslFrameCreate(void);
|
RslFrame *RslFrameCreate(void);
|
||||||
RslFrame *RslFrameAddChild(RslFrame *parent, RslFrame *child);
|
RslFrame *RslFrameAddChild(RslFrame *parent, RslFrame *child);
|
||||||
|
int32 RslFrameCount(RslFrame *f);
|
||||||
RslFrame *RslFrameForAllChildren(RslFrame *frame, RslFrameCallBack callBack, void *data);
|
RslFrame *RslFrameForAllChildren(RslFrame *frame, RslFrameCallBack callBack, void *data);
|
||||||
|
|
||||||
struct rslFrameList
|
struct rslFrameList
|
||||||
@ -205,6 +207,9 @@ struct rslFrameList
|
|||||||
int32 numFrames;
|
int32 numFrames;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void rslFrameListStreamRead(Stream *stream, rslFrameList *framelist);
|
||||||
|
void rslFrameListInitialize(rslFrameList *frameList, RslFrame *root);
|
||||||
|
|
||||||
struct RslClump {
|
struct RslClump {
|
||||||
RslObject object;
|
RslObject object;
|
||||||
RslLinkList atomicList;
|
RslLinkList atomicList;
|
||||||
@ -213,8 +218,14 @@ struct RslClump {
|
|||||||
#define RslClumpGetFrame(_clump) \
|
#define RslClumpGetFrame(_clump) \
|
||||||
((RslFrame*)rslObjectGetParent(_clump))
|
((RslFrame*)rslObjectGetParent(_clump))
|
||||||
|
|
||||||
|
#define RslClumpSetFrame(_clump, _frame) \
|
||||||
|
(rslObjectSetParent(_clump, _frame), \
|
||||||
|
(_clump))
|
||||||
|
|
||||||
|
RslClump *RslClumpCreate(void);
|
||||||
RslClump *RslClumpStreamRead(Stream *stream);
|
RslClump *RslClumpStreamRead(Stream *stream);
|
||||||
RslClump *RslClumpAddAtomic(RslClump *clump, RslAtomic *a);
|
RslClump *RslClumpAddAtomic(RslClump *clump, RslAtomic *a);
|
||||||
|
int32 RslClumpGetNumAtomics(RslClump *clump);
|
||||||
RslClump *RslClumpForAllAtomics(RslClump *clump, RslAtomicCallBack callback, void *pData);
|
RslClump *RslClumpForAllAtomics(RslClump *clump, RslAtomicCallBack callback, void *pData);
|
||||||
|
|
||||||
struct RslAtomic {
|
struct RslAtomic {
|
||||||
|
@ -40,7 +40,8 @@ RslFrame *dumpFrameCB(RslFrame *frame, void *data)
|
|||||||
|
|
||||||
RslMaterial *dumpMaterialCB(RslMaterial *material, void*)
|
RslMaterial *dumpMaterialCB(RslMaterial *material, void*)
|
||||||
{
|
{
|
||||||
printf(" mat: %s %x\n", material->texname, material->refCount);
|
printf(" mat: %d %d %d %d %s %x\n", material->color.red, material->color.green, material->color.blue, material->color.alpha,
|
||||||
|
material->texname, material->refCount);
|
||||||
if(material->matfx){
|
if(material->matfx){
|
||||||
RslMatFX *fx = material->matfx;
|
RslMatFX *fx = material->matfx;
|
||||||
printf(" matfx: ", fx->effectType);
|
printf(" matfx: ", fx->effectType);
|
||||||
@ -59,6 +60,411 @@ RslAtomic *dumpAtomicCB(RslAtomic *atomic, void*)
|
|||||||
return atomic;
|
return atomic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32
|
||||||
|
mapID(int32 id)
|
||||||
|
{
|
||||||
|
if(id == 255) return -1;
|
||||||
|
if(id > 0x80) id |= 0x1300;
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
Frame*
|
||||||
|
convertFrame(RslFrame *f)
|
||||||
|
{
|
||||||
|
Frame *rwf = new Frame;
|
||||||
|
rwf->matrix[0] = f->modelling.right.x;
|
||||||
|
rwf->matrix[1] = f->modelling.right.y;
|
||||||
|
rwf->matrix[2] = f->modelling.right.z;
|
||||||
|
rwf->matrix[4] = f->modelling.up.x;
|
||||||
|
rwf->matrix[5] = f->modelling.up.y;
|
||||||
|
rwf->matrix[6] = f->modelling.up.z;
|
||||||
|
rwf->matrix[8] = f->modelling.at.x;
|
||||||
|
rwf->matrix[9] = f->modelling.at.y;
|
||||||
|
rwf->matrix[10] = f->modelling.at.z;
|
||||||
|
rwf->matrix[12] = f->modelling.pos.x;
|
||||||
|
rwf->matrix[13] = f->modelling.pos.y;
|
||||||
|
rwf->matrix[14] = f->modelling.pos.z;
|
||||||
|
|
||||||
|
if(f->name)
|
||||||
|
strncpy(gta::getNodeName(rwf), f->name, 24);
|
||||||
|
|
||||||
|
HAnimData *hanim = PLUGINOFFSET(HAnimData, rwf, hAnimOffset);
|
||||||
|
hanim->id = f->nodeId;
|
||||||
|
if(f->hier){
|
||||||
|
HAnimHierarchy *hier;
|
||||||
|
hanim->hierarchy = hier = new HAnimHierarchy;
|
||||||
|
hier->numNodes = f->hier->numNodes;
|
||||||
|
hier->flags = f->hier->flags;
|
||||||
|
hier->maxInterpKeyFrameSize = f->hier->maxKeyFrameSize;
|
||||||
|
hier->parentFrame = rwf;
|
||||||
|
hier->parentHierarchy = hier;
|
||||||
|
hier->nodeInfo = new HAnimNodeInfo[hier->numNodes];
|
||||||
|
for(int32 i = 0; i < hier->numNodes; i++){
|
||||||
|
hier->nodeInfo[i].id = mapID((uint8)f->hier->pNodeInfo[i].id);
|
||||||
|
hier->nodeInfo[i].index = f->hier->pNodeInfo[i].index;
|
||||||
|
hier->nodeInfo[i].flags = f->hier->pNodeInfo[i].flags;
|
||||||
|
hier->nodeInfo[i].frame = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rwf;
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture*
|
||||||
|
convertTexture(RslTexture *t)
|
||||||
|
{
|
||||||
|
Texture *tex = Texture::read(t->name, t->mask);
|
||||||
|
//tex->refCount++; // ??
|
||||||
|
if(tex->refCount == 1)
|
||||||
|
tex->filterAddressing = (Texture::WRAP << 12) | (Texture::WRAP << 8) | Texture::LINEAR;
|
||||||
|
return tex;
|
||||||
|
}
|
||||||
|
|
||||||
|
Material*
|
||||||
|
convertMaterial(RslMaterial *m)
|
||||||
|
{
|
||||||
|
Material *rwm;
|
||||||
|
rwm = new Material;
|
||||||
|
|
||||||
|
rwm->color[0] = m->color.red;
|
||||||
|
rwm->color[1] = m->color.green;
|
||||||
|
rwm->color[2] = m->color.blue;
|
||||||
|
rwm->color[3] = m->color.alpha;
|
||||||
|
if(m->texture)
|
||||||
|
rwm->texture = convertTexture(m->texture);
|
||||||
|
|
||||||
|
if(m->matfx){
|
||||||
|
MatFX *matfx = new MatFX;
|
||||||
|
matfx->setEffects(m->matfx->effectType);
|
||||||
|
matfx->setEnvCoefficient(m->matfx->env.intensity);
|
||||||
|
if(m->matfx->env.texture)
|
||||||
|
matfx->setEnvTexture(convertTexture(m->matfx->env.texture));
|
||||||
|
*PLUGINOFFSET(MatFX*, rwm, matFXGlobals.materialOffset) = matfx;
|
||||||
|
}
|
||||||
|
return rwm;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32
|
||||||
|
unpackSize(uint32 unpack)
|
||||||
|
{
|
||||||
|
if((unpack&0x6F000000) == 0x6F000000)
|
||||||
|
return 2;
|
||||||
|
static uint32 size[] = { 32, 16, 8, 16 };
|
||||||
|
return ((unpack>>26 & 3)+1)*size[unpack>>24 & 3]/8;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32*
|
||||||
|
skipUnpack(uint32 *p)
|
||||||
|
{
|
||||||
|
int32 n = (p[0] >> 16) & 0xFF;
|
||||||
|
return p + (n*unpackSize(p[0])+3 >> 2) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
convertMesh(Geometry *rwg, RslGeometry *g, int32 ii)
|
||||||
|
{
|
||||||
|
RslPS2ResEntryHeader *resHeader = (RslPS2ResEntryHeader*)(g+1);
|
||||||
|
RslPS2InstanceData *inst = (RslPS2InstanceData*)(resHeader+1);
|
||||||
|
int32 numInst = resHeader->size >> 20;
|
||||||
|
uint8 *p = (uint8*)(inst+numInst);
|
||||||
|
inst += ii;
|
||||||
|
p += inst->dmaPacket;
|
||||||
|
Mesh *m = &rwg->meshHeader->mesh[inst->matID];
|
||||||
|
|
||||||
|
ps2::SkinVertex v;
|
||||||
|
uint32 mask = 0x1001; // tex coords, vertices
|
||||||
|
if(rwg->geoflags & Geometry::NORMALS)
|
||||||
|
mask |= 0x10;
|
||||||
|
if(rwg->geoflags & Geometry::PRELIT)
|
||||||
|
mask |= 0x100;
|
||||||
|
float32 *verts = &rwg->morphTargets[0].vertices[rwg->numVertices*3];
|
||||||
|
float32 *norms = &rwg->morphTargets[0].normals[rwg->numVertices*3];
|
||||||
|
uint8 *cols = &rwg->colors[rwg->numVertices*4];
|
||||||
|
float32 *texCoords = &rwg->texCoords[0][rwg->numVertices*2];
|
||||||
|
uint8 *indices = NULL;
|
||||||
|
float32 *weights = NULL;
|
||||||
|
Skin *skin = *PLUGINOFFSET(Skin*, rwg, skinGlobals.offset);
|
||||||
|
if(skin){
|
||||||
|
indices = &skin->indices[rwg->numVertices*4];
|
||||||
|
weights = &skin->weights[rwg->numVertices*4];
|
||||||
|
mask |= 0x10000;
|
||||||
|
}
|
||||||
|
|
||||||
|
int16 *vuVerts = NULL;
|
||||||
|
int8 *vuNorms = NULL;
|
||||||
|
uint8 *vuTex = NULL;
|
||||||
|
uint16 *vuCols = NULL;
|
||||||
|
uint32 *vuSkin = NULL;
|
||||||
|
|
||||||
|
uint32 *w = (uint32*)p;
|
||||||
|
uint32 *end = (uint32*)(p + ((w[0] & 0xFFFF) + 1)*0x10);
|
||||||
|
w += 4;
|
||||||
|
int flags = 0;
|
||||||
|
int32 nvert;
|
||||||
|
bool first = 1;
|
||||||
|
while(w < end){
|
||||||
|
/* Get data pointers */
|
||||||
|
|
||||||
|
// GIFtag probably
|
||||||
|
assert(w[0] == 0x6C018000); // UNPACK
|
||||||
|
nvert = w[4] & 0x7FFF;
|
||||||
|
if(!first) nvert -=2;
|
||||||
|
w += 5;
|
||||||
|
|
||||||
|
// positions
|
||||||
|
assert(w[0] == 0x20000000); // STMASK
|
||||||
|
w += 2;
|
||||||
|
assert(w[0] == 0x30000000); // STROW
|
||||||
|
w += 5;
|
||||||
|
assert((w[0] & 0xFF004000) == 0x79000000);
|
||||||
|
vuVerts = (int16*)(w+1);
|
||||||
|
if(!first) vuVerts += 2*3;
|
||||||
|
w = skipUnpack(w);
|
||||||
|
|
||||||
|
// tex coords
|
||||||
|
assert(w[0] == 0x20000000); // STMASK
|
||||||
|
w += 2;
|
||||||
|
assert(w[0] == 0x30000000); // STROW
|
||||||
|
w += 5;
|
||||||
|
assert((w[0] & 0xFF004000) == 0x76004000);
|
||||||
|
vuTex = (uint8*)(w+1);
|
||||||
|
if(!first) vuTex += 2*2;
|
||||||
|
w = skipUnpack(w);
|
||||||
|
|
||||||
|
if(rwg->geoflags & Geometry::NORMALS){
|
||||||
|
assert((w[0] & 0xFF004000) == 0x6A000000);
|
||||||
|
vuNorms = (int8*)(w+1);
|
||||||
|
if(!first) vuNorms += 2*3;
|
||||||
|
w = skipUnpack(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(rwg->geoflags & Geometry::PRELIT){
|
||||||
|
assert((w[0] & 0xFF004000) == 0x6F000000);
|
||||||
|
vuCols = (uint16*)(w+1);
|
||||||
|
if(!first) vuCols += 2;
|
||||||
|
w = skipUnpack(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(skin){
|
||||||
|
assert((w[0] & 0xFF004000) == 0x6C000000);
|
||||||
|
vuSkin = w+1;
|
||||||
|
if(!first) vuSkin += 2*4;
|
||||||
|
w = skipUnpack(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(w[0] == 0x14000006); // MSCAL
|
||||||
|
w++;
|
||||||
|
while(w[0] == 0) w++;
|
||||||
|
|
||||||
|
/* Insert Data */
|
||||||
|
for(int32 i = 0; i < nvert; i++){
|
||||||
|
v.p[0] = vuVerts[0]/32768.0f*resHeader->scale[0] + resHeader->pos[0];
|
||||||
|
v.p[1] = vuVerts[1]/32768.0f*resHeader->scale[1] + resHeader->pos[1];
|
||||||
|
v.p[2] = vuVerts[2]/32768.0f*resHeader->scale[2] + resHeader->pos[2];
|
||||||
|
v.t[0] = vuTex[0]/128.0f*inst->uvScale[0];
|
||||||
|
v.t[1] = vuTex[1]/128.0f*inst->uvScale[1];
|
||||||
|
if(mask & 0x10){
|
||||||
|
v.n[0] = vuNorms[0]/127.0f;
|
||||||
|
v.n[1] = vuNorms[1]/127.0f;
|
||||||
|
v.n[2] = vuNorms[2]/127.0f;
|
||||||
|
}
|
||||||
|
if(mask & 0x100){
|
||||||
|
v.c[0] = (vuCols[0] & 0x1f) * 255 / 0x1F;
|
||||||
|
v.c[1] = (vuCols[0]>>5 & 0x1f) * 255 / 0x1F;
|
||||||
|
v.c[2] = (vuCols[0]>>10 & 0x1f) * 255 / 0x1F;
|
||||||
|
v.c[3] = vuCols[0]&0x8000 ? 0xFF : 0;
|
||||||
|
}
|
||||||
|
if(mask & 0x10000){
|
||||||
|
for(int j = 0; j < 4; j++){
|
||||||
|
((uint32*)v.w)[j] = vuSkin[j] & ~0x3FF;
|
||||||
|
v.i[j] = vuSkin[j] >> 2;
|
||||||
|
//if(v.i[j]) v.i[j]--;
|
||||||
|
if(v.w[j] == 0.0f) v.i[j] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 idx = ps2::findVertexSkin(rwg, NULL, mask, &v);
|
||||||
|
if(idx < 0)
|
||||||
|
idx = rwg->numVertices++;
|
||||||
|
/* Insert mesh joining indices when we get the index of the first vertex
|
||||||
|
* in the first VU chunk of a non-first RslMesh. */
|
||||||
|
if(i == 0 && first && ii != 0 && inst[-1].matID == inst->matID){
|
||||||
|
m->indices[m->numIndices] = m->indices[m->numIndices-1];
|
||||||
|
m->numIndices++;
|
||||||
|
m->indices[m->numIndices++] = idx;
|
||||||
|
if(inst[-1].numTriangles % 2)
|
||||||
|
m->indices[m->numIndices++] = idx;
|
||||||
|
}
|
||||||
|
m->indices[m->numIndices++] = idx;
|
||||||
|
ps2::insertVertexSkin(rwg, idx, mask, &v);
|
||||||
|
|
||||||
|
vuVerts += 3;
|
||||||
|
vuTex += 2;
|
||||||
|
vuNorms += 3;
|
||||||
|
vuCols++;
|
||||||
|
vuSkin += 4;
|
||||||
|
}
|
||||||
|
first = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Atomic*
|
||||||
|
convertAtomic(RslAtomic *atomic)
|
||||||
|
{
|
||||||
|
Atomic *rwa = new Atomic;
|
||||||
|
RslGeometry *g = atomic->geometry;
|
||||||
|
Geometry *rwg = new Geometry(0, 0, 0);
|
||||||
|
rwa->geometry = rwg;
|
||||||
|
|
||||||
|
rwg->numMaterials = g->matList.numMaterials;
|
||||||
|
rwg->materialList = new Material*[rwg->numMaterials];
|
||||||
|
for(int32 i = 0; i < rwg->numMaterials; i++)
|
||||||
|
rwg->materialList[i] = convertMaterial(g->matList.materials[i]);
|
||||||
|
|
||||||
|
rwg->meshHeader = new MeshHeader;
|
||||||
|
rwg->meshHeader->flags = 1;
|
||||||
|
rwg->meshHeader->numMeshes = rwg->numMaterials;
|
||||||
|
rwg->meshHeader->mesh = new Mesh[rwg->meshHeader->numMeshes];
|
||||||
|
rwg->meshHeader->totalIndices = 0;
|
||||||
|
Mesh *meshes = rwg->meshHeader->mesh;
|
||||||
|
for(uint32 i = 0; i < rwg->meshHeader->numMeshes; i++)
|
||||||
|
meshes[i].numIndices = 0;
|
||||||
|
|
||||||
|
RslPS2ResEntryHeader *resHeader = (RslPS2ResEntryHeader*)(g+1);
|
||||||
|
RslPS2InstanceData *inst = (RslPS2InstanceData*)(resHeader+1);
|
||||||
|
int32 numInst = resHeader->size >> 20;
|
||||||
|
|
||||||
|
int32 lastId = -1;
|
||||||
|
for(int32 i = 0; i < numInst; i++){
|
||||||
|
Mesh *m = &meshes[inst[i].matID];
|
||||||
|
rwg->numVertices += inst[i].numTriangles+2;
|
||||||
|
m->numIndices += inst[i].numTriangles+2;
|
||||||
|
// Extra indices since we're merging tristrip
|
||||||
|
// meshes with the same material.
|
||||||
|
// Be careful with face winding.
|
||||||
|
if(lastId == inst[i].matID)
|
||||||
|
m->numIndices += inst[i-1].numTriangles % 2 ? 3 : 2;
|
||||||
|
lastId = inst[i].matID;
|
||||||
|
}
|
||||||
|
for(uint32 i = 0; i < rwg->meshHeader->numMeshes; i++){
|
||||||
|
rwg->meshHeader->mesh[i].material = rwg->materialList[i];
|
||||||
|
rwg->meshHeader->totalIndices += meshes[i].numIndices;
|
||||||
|
}
|
||||||
|
rwg->geoflags = Geometry::TRISTRIP |
|
||||||
|
Geometry::POSITIONS | /* 0x01 ? */
|
||||||
|
Geometry::TEXTURED | /* 0x04 ? */
|
||||||
|
Geometry::LIGHT;
|
||||||
|
if(rwg->hasColoredMaterial())
|
||||||
|
rwg->geoflags |= Geometry::MODULATE;
|
||||||
|
if(resHeader->flags & 0x2)
|
||||||
|
rwg->geoflags |= Geometry::NORMALS;
|
||||||
|
if(resHeader->flags & 0x8)
|
||||||
|
rwg->geoflags |= Geometry::PRELIT;
|
||||||
|
rwg->numTexCoordSets = 1;
|
||||||
|
|
||||||
|
rwg->allocateData();
|
||||||
|
rwg->meshHeader->allocateIndices();
|
||||||
|
|
||||||
|
Skin *skin = NULL;
|
||||||
|
if(resHeader->flags & 0x10)
|
||||||
|
assert(g->skin);
|
||||||
|
if(g->skin){
|
||||||
|
skin = new Skin;
|
||||||
|
*PLUGINOFFSET(Skin*, rwg, skinGlobals.offset) = skin;
|
||||||
|
skin->init(g->skin->numBones, g->skin->numBones, rwg->numVertices);
|
||||||
|
memcpy(skin->inverseMatrices, g->skin->invMatrices, skin->numBones*64);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(uint32 i = 0; i < rwg->meshHeader->numMeshes; i++)
|
||||||
|
meshes[i].numIndices = 0;
|
||||||
|
rwg->meshHeader->totalIndices = rwg->numVertices = 0;
|
||||||
|
for(int32 i = 0; i < numInst; i++)
|
||||||
|
convertMesh(rwg, g, i);
|
||||||
|
for(uint32 i = 0; i < rwg->meshHeader->numMeshes; i++)
|
||||||
|
rwg->meshHeader->totalIndices += meshes[i].numIndices;
|
||||||
|
if(skin){
|
||||||
|
skin->findNumWeights(rwg->numVertices);
|
||||||
|
skin->findUsedBones(rwg->numVertices);
|
||||||
|
}
|
||||||
|
rwg->calculateBoundingSphere();
|
||||||
|
rwg->generateTriangles();
|
||||||
|
return rwa;
|
||||||
|
}
|
||||||
|
|
||||||
|
RslAtomic*
|
||||||
|
collectAtomics(RslAtomic *atomic, void *data)
|
||||||
|
{
|
||||||
|
RslAtomic ***alist = (RslAtomic***)data;
|
||||||
|
*(*alist)++ = atomic;
|
||||||
|
return atomic;
|
||||||
|
}
|
||||||
|
|
||||||
|
Clump*
|
||||||
|
convertClump(RslClump *c)
|
||||||
|
{
|
||||||
|
Clump *rwc;
|
||||||
|
Frame *rwf;
|
||||||
|
Atomic *rwa;
|
||||||
|
rslFrameList frameList;
|
||||||
|
|
||||||
|
rwc = new Clump;
|
||||||
|
rslFrameListInitialize(&frameList, (RslFrame*)c->object.parent);
|
||||||
|
Frame **rwframes = new Frame*[frameList.numFrames];
|
||||||
|
for(int32 i = 0; i < frameList.numFrames; i++){
|
||||||
|
rwf = convertFrame(frameList.frames[i]);
|
||||||
|
rwframes[i] = rwf;
|
||||||
|
void *par = frameList.frames[i]->object.parent;
|
||||||
|
int32 parent = findPointer(par, (void**)frameList.frames, frameList.numFrames);
|
||||||
|
if(parent >= 0)
|
||||||
|
rwframes[parent]->addChild(rwf);
|
||||||
|
}
|
||||||
|
rwc->parent = rwframes[0];
|
||||||
|
|
||||||
|
rwc->numAtomics = RslClumpGetNumAtomics(c);
|
||||||
|
rwc->atomicList = new Atomic*[rwc->numAtomics];
|
||||||
|
RslAtomic **alist = new RslAtomic*[rwc->numAtomics];
|
||||||
|
RslAtomic **ap = &alist[0];
|
||||||
|
RslClumpForAllAtomics(c, collectAtomics, &ap);
|
||||||
|
for(int32 i = 0; i < rwc->numAtomics; i++){
|
||||||
|
rwa = convertAtomic(alist[i]);
|
||||||
|
rwc->atomicList[i] = rwa;
|
||||||
|
int32 fi = findPointer(alist[i]->object.object.parent, (void**)frameList.frames, frameList.numFrames);
|
||||||
|
rwa->frame = rwframes[fi];
|
||||||
|
rwa->clump = rwc;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] alist;
|
||||||
|
delete[] rwframes;
|
||||||
|
delete[] frameList.frames;
|
||||||
|
return rwc;
|
||||||
|
}
|
||||||
|
|
||||||
|
RslAtomic*
|
||||||
|
makeTextures(RslAtomic *atomic, void*)
|
||||||
|
{
|
||||||
|
RslGeometry *g = atomic->geometry;
|
||||||
|
RslMaterial *m;
|
||||||
|
for(int32 i = 0; i < g->matList.numMaterials; i++){
|
||||||
|
m = g->matList.materials[i];
|
||||||
|
if(m->texname){
|
||||||
|
RslTexture *tex = RslTextureCreate(NULL);
|
||||||
|
strncpy(tex->name, m->texname, 32);
|
||||||
|
strncpy(tex->mask, m->texname, 32);
|
||||||
|
m->texture = tex;
|
||||||
|
}
|
||||||
|
if(m->matfx && m->matfx->effectType == MatFX::ENVMAP &&
|
||||||
|
m->matfx->env.texname){
|
||||||
|
RslTexture *tex = RslTextureCreate(NULL);
|
||||||
|
strncpy(tex->name, m->matfx->env.texname, 32);
|
||||||
|
strncpy(tex->mask, m->matfx->env.texname, 32);
|
||||||
|
m->matfx->env.texture = tex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return atomic;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uint8*
|
uint8*
|
||||||
getPalettePS2(RslRaster *raster)
|
getPalettePS2(RslRaster *raster)
|
||||||
{
|
{
|
||||||
@ -356,10 +762,10 @@ convertTXD(RslTexDictionary *txd)
|
|||||||
void
|
void
|
||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s [-v version] [-x] [-s] input [output.txd]\n", argv0);
|
fprintf(stderr, "%s [-v version] [-x] [-s] input [output.{txd|dff}]\n", argv0);
|
||||||
fprintf(stderr, "\t-v RW version, e.g. 33004 for 3.3.0.4\n");
|
fprintf(stderr, "\t-v RW version, e.g. 33004 for 3.3.0.4\n");
|
||||||
fprintf(stderr, "\t-x extract to tga\n");
|
fprintf(stderr, "\t-x extract textures to tga\n");
|
||||||
fprintf(stderr, "\t-s don't unswizzle\n");
|
fprintf(stderr, "\t-s don't unswizzle textures\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,6 +774,7 @@ main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
gta::attachPlugins();
|
gta::attachPlugins();
|
||||||
rw::version = 0x34003;
|
rw::version = 0x34003;
|
||||||
|
rw::platform = PLATFORM_D3D8;
|
||||||
|
|
||||||
assert(sizeof(void*) == 4);
|
assert(sizeof(void*) == 4);
|
||||||
int extract = 0;
|
int extract = 0;
|
||||||
@ -389,10 +796,11 @@ main(int argc, char *argv[])
|
|||||||
if(argc < 1)
|
if(argc < 1)
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
World *world;
|
World *world = NULL;
|
||||||
Sector *sector;
|
Sector *sector = NULL;
|
||||||
RslClump *clump;
|
RslClump *clump = NULL;
|
||||||
RslTexDictionary *txd;
|
RslAtomic *atomic = NULL;
|
||||||
|
RslTexDictionary *txd = NULL;
|
||||||
|
|
||||||
|
|
||||||
StreamFile stream;
|
StreamFile stream;
|
||||||
@ -408,11 +816,12 @@ main(int argc, char *argv[])
|
|||||||
assert(txd);
|
assert(txd);
|
||||||
goto writeTxd;
|
goto writeTxd;
|
||||||
}
|
}
|
||||||
if(ident == 0x10){
|
if(ident == ID_CLUMP){
|
||||||
findChunk(&stream, ID_CLUMP, NULL, NULL);
|
findChunk(&stream, ID_CLUMP, NULL, NULL);
|
||||||
clump = RslClumpStreamRead(&stream);
|
clump = RslClumpStreamRead(&stream);
|
||||||
stream.close();
|
stream.close();
|
||||||
return 0;
|
assert(clump);
|
||||||
|
goto writeDff;
|
||||||
}
|
}
|
||||||
|
|
||||||
RslStream *rslstr = new RslStream;
|
RslStream *rslstr = new RslStream;
|
||||||
@ -486,14 +895,30 @@ main(int argc, char *argv[])
|
|||||||
}else if(rslstr->ident == MDL_IDENT){
|
}else if(rslstr->ident == MDL_IDENT){
|
||||||
uint8 *p = *rslstr->hashTab;
|
uint8 *p = *rslstr->hashTab;
|
||||||
p -= 0x24;
|
p -= 0x24;
|
||||||
RslAtomic *a = (RslAtomic*)p;
|
atomic = (RslAtomic*)p;
|
||||||
clump = a->clump;
|
clump = atomic->clump;
|
||||||
if(clump)
|
Clump *rwc;
|
||||||
|
if(clump){
|
||||||
|
RslClumpForAllAtomics(clump, makeTextures, NULL);
|
||||||
//RslClumpForAllAtomics(clump, dumpAtomicCB, NULL);
|
//RslClumpForAllAtomics(clump, dumpAtomicCB, NULL);
|
||||||
RslFrameForAllChildren(RslClumpGetFrame(clump), dumpFrameCB, NULL);
|
//RslFrameForAllChildren(RslClumpGetFrame(clump), dumpFrameCB, NULL);
|
||||||
else
|
}else{
|
||||||
|
makeTextures(atomic, NULL);
|
||||||
|
clump = RslClumpCreate();
|
||||||
|
RslAtomicSetFrame(atomic, RslFrameCreate());
|
||||||
|
RslClumpSetFrame(clump, RslAtomicGetFrame(atomic));
|
||||||
|
RslClumpAddAtomic(clump, atomic);
|
||||||
//dumpAtomicCB(a, NULL);
|
//dumpAtomicCB(a, NULL);
|
||||||
RslFrameForAllChildren(RslAtomicGetFrame(a), dumpFrameCB, NULL);
|
//RslFrameForAllChildren(RslAtomicGetFrame(atomic), dumpFrameCB, NULL);
|
||||||
|
}
|
||||||
|
writeDff:
|
||||||
|
rwc = convertClump(clump);
|
||||||
|
if(argc > 1)
|
||||||
|
assert(stream.open(argv[1], "wb"));
|
||||||
|
else
|
||||||
|
assert(stream.open("out.dff", "wb"));
|
||||||
|
rwc->streamWrite(&stream);
|
||||||
|
stream.close();
|
||||||
}else if(rslstr->ident == TEX_IDENT){
|
}else if(rslstr->ident == TEX_IDENT){
|
||||||
txd = (RslTexDictionary*)rslstr->data;
|
txd = (RslTexDictionary*)rslstr->data;
|
||||||
writeTxd:
|
writeTxd:
|
||||||
|
Loading…
Reference in New Issue
Block a user