mirror of https://github.com/aap/librw.git
implemented leeds dff stream read
This commit is contained in:
parent
fab7f20c6d
commit
a42bfb90ac
|
@ -76,7 +76,6 @@ Global
|
||||||
{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
|
{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
|
||||||
|
@ -96,7 +95,6 @@ Global
|
||||||
{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
|
{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|Win32.Build.0 = 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
|
||||||
{403C35A9-6D06-4261-B305-9ED000F00136}.Debug|x64.ActiveCfg = Debug|x64
|
{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.ActiveCfg = Release|x64
|
||||||
{403C35A9-6D06-4261-B305-9ED000F00136}.Release|x64.Build.0 = 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|x64.ActiveCfg = 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.ActiveCfg = Debug - null|Win32
|
||||||
{27ECE916-900F-49B2-8E9F-95E6B347E161}.Debug|Win32.Build.0 = Debug - null|Win32
|
{27ECE916-900F-49B2-8E9F-95E6B347E161}.Debug|Win32.Build.0 = Debug - null|Win32
|
||||||
|
|
|
@ -400,7 +400,9 @@ Material::Material(void)
|
||||||
{
|
{
|
||||||
this->texture = NULL;
|
this->texture = NULL;
|
||||||
memset(this->color, 0xFF, 4);
|
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->pipeline = NULL;
|
||||||
this->refCount = 1;
|
this->refCount = 1;
|
||||||
this->constructPlugins();
|
this->constructPlugins();
|
||||||
|
@ -412,9 +414,9 @@ Material::Material(Material *m)
|
||||||
this->color[1] = m->color[1];
|
this->color[1] = m->color[1];
|
||||||
this->color[2] = m->color[2];
|
this->color[2] = m->color[2];
|
||||||
this->color[3] = m->color[3];
|
this->color[3] = m->color[3];
|
||||||
this->surfaceProps[0] = m->surfaceProps[0];
|
this->surfaceProps.ambient = m->surfaceProps.ambient;
|
||||||
this->surfaceProps[1] = m->surfaceProps[1];
|
this->surfaceProps.specular = m->surfaceProps.specular;
|
||||||
this->surfaceProps[2] = m->surfaceProps[2];
|
this->surfaceProps.diffuse = m->surfaceProps.diffuse;
|
||||||
this->texture = m->texture;
|
this->texture = m->texture;
|
||||||
if(this->texture)
|
if(this->texture)
|
||||||
this->texture->refCount++;
|
this->texture->refCount++;
|
||||||
|
@ -463,15 +465,15 @@ Material::streamRead(Stream *stream)
|
||||||
mat->color[2] = buf.color[2];
|
mat->color[2] = buf.color[2];
|
||||||
mat->color[3] = buf.color[3];
|
mat->color[3] = buf.color[3];
|
||||||
if(version < 0x30400){
|
if(version < 0x30400){
|
||||||
mat->surfaceProps[0] = 1.0f;
|
mat->surfaceProps.ambient = 1.0f;
|
||||||
mat->surfaceProps[1] = 1.0f;
|
mat->surfaceProps.specular = 1.0f;
|
||||||
mat->surfaceProps[2] = 1.0f;
|
mat->surfaceProps.diffuse = 1.0f;
|
||||||
}else{
|
}else{
|
||||||
float32 surfaceProps[3];
|
float32 surfaceProps[3];
|
||||||
stream->read(surfaceProps, sizeof(surfaceProps));
|
stream->read(surfaceProps, sizeof(surfaceProps));
|
||||||
mat->surfaceProps[0] = surfaceProps[0];
|
mat->surfaceProps.ambient = surfaceProps[0];
|
||||||
mat->surfaceProps[1] = surfaceProps[1];
|
mat->surfaceProps.specular = surfaceProps[1];
|
||||||
mat->surfaceProps[2] = surfaceProps[2];
|
mat->surfaceProps.diffuse = surfaceProps[2];
|
||||||
}
|
}
|
||||||
if(buf.textured){
|
if(buf.textured){
|
||||||
assert(findChunk(stream, ID_TEXTURE, &length, NULL));
|
assert(findChunk(stream, ID_TEXTURE, &length, NULL));
|
||||||
|
@ -505,9 +507,9 @@ Material::streamWrite(Stream *stream)
|
||||||
|
|
||||||
if(rw::version >= 0x30400){
|
if(rw::version >= 0x30400){
|
||||||
float32 surfaceProps[3];
|
float32 surfaceProps[3];
|
||||||
surfaceProps[0] = this->surfaceProps[0];
|
surfaceProps[0] = this->surfaceProps.ambient;
|
||||||
surfaceProps[1] = this->surfaceProps[1];
|
surfaceProps[1] = this->surfaceProps.specular;
|
||||||
surfaceProps[2] = this->surfaceProps[2];
|
surfaceProps[2] = this->surfaceProps.diffuse;
|
||||||
stream->write(surfaceProps, sizeof(surfaceProps));
|
stream->write(surfaceProps, sizeof(surfaceProps));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -374,10 +374,10 @@ geometryStreamReadRsl(Stream *stream)
|
||||||
for(int32 i = 0; i < g->numMaterials; i++){
|
for(int32 i = 0; i < g->numMaterials; i++){
|
||||||
assert(findChunk(stream, ID_MATERIAL, NULL, NULL));
|
assert(findChunk(stream, ID_MATERIAL, NULL, NULL));
|
||||||
g->materialList[i] = Material::streamRead(stream);
|
g->materialList[i] = Material::streamRead(stream);
|
||||||
// fucked somehow
|
// unimplemented by Rsl
|
||||||
g->materialList[i]->surfaceProps[0] = 1.0f;
|
g->materialList[i]->surfaceProps.ambient = 1.0f;
|
||||||
g->materialList[i]->surfaceProps[1] = 1.0f;
|
g->materialList[i]->surfaceProps.specular = 1.0f;
|
||||||
g->materialList[i]->surfaceProps[2] = 1.0f;
|
g->materialList[i]->surfaceProps.diffuse = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
g->streamReadPlugins(stream);
|
g->streamReadPlugins(stream);
|
||||||
|
|
|
@ -791,17 +791,17 @@ clearMatFX(MatFX *matfx)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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);
|
clearMatFX(this);
|
||||||
this->flags = flags;
|
this->type = type;
|
||||||
switch(flags){
|
switch(type){
|
||||||
case BUMPMAP:
|
case BUMPMAP:
|
||||||
case ENVMAP:
|
case ENVMAP:
|
||||||
case DUAL:
|
case DUAL:
|
||||||
case UVTRANSFORM:
|
case UVTRANSFORM:
|
||||||
this->fx[0].type = flags;
|
this->fx[0].type = type;
|
||||||
this->fx[1].type = NOTHING;
|
this->fx[1].type = NOTHING;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -889,7 +889,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->flags == MatFX::BUMPMAP && matFXGlobals.hack){
|
if(matfx->type == MatFX::BUMPMAP && matFXGlobals.hack){
|
||||||
stream->seek(12);
|
stream->seek(12);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -961,7 +961,7 @@ writeMaterialMatFX(Stream *stream, int32, void *object, int32 offset, int32)
|
||||||
{
|
{
|
||||||
MatFX *matfx = *PLUGINOFFSET(MatFX*, object, offset);
|
MatFX *matfx = *PLUGINOFFSET(MatFX*, object, offset);
|
||||||
|
|
||||||
stream->writeU32(matfx->flags);
|
stream->writeU32(matfx->type);
|
||||||
for(int i = 0; i < 2; i++){
|
for(int i = 0; i < 2; i++){
|
||||||
stream->writeU32(matfx->fx[i].type);
|
stream->writeU32(matfx->fx[i].type);
|
||||||
switch(matfx->fx[i].type){
|
switch(matfx->fx[i].type){
|
||||||
|
|
66
src/ps2.cpp
66
src/ps2.cpp
|
@ -1515,24 +1515,24 @@ ps2MinSize(int32 psm, int32 flags, int32 *minw, int32 *minh)
|
||||||
{
|
{
|
||||||
*minh = 1;
|
*minh = 1;
|
||||||
switch(psm){
|
switch(psm){
|
||||||
case 0x00:
|
case 0x00:
|
||||||
case 0x30:
|
case 0x30:
|
||||||
*minw = 2; // 32 bit
|
*minw = 2; // 32 bit
|
||||||
break;
|
break;
|
||||||
case 0x02:
|
case 0x02:
|
||||||
case 0x0A:
|
case 0x0A:
|
||||||
case 0x32:
|
case 0x32:
|
||||||
case 0x3A:
|
case 0x3A:
|
||||||
*minw = 4; // 16 bit
|
*minw = 4; // 16 bit
|
||||||
break;
|
break;
|
||||||
case 0x01:
|
case 0x01:
|
||||||
case 0x13:
|
case 0x13:
|
||||||
case 0x14:
|
case 0x14:
|
||||||
case 0x1B:
|
case 0x1B:
|
||||||
case 0x24:
|
case 0x24:
|
||||||
case 0x2C:
|
case 0x2C:
|
||||||
case 0x31:
|
case 0x31:
|
||||||
*minw = 8; // everything else
|
*minw = 8; // everything else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(flags & 0x2 && psm == 0x13){ // PSMT8
|
if(flags & 0x2 && psm == 0x13){ // PSMT8
|
||||||
|
@ -1896,21 +1896,21 @@ registerNativeRaster(void)
|
||||||
Texture::registerPluginStream(ID_SKYMIPMAP, readMipmap, writeMipmap, getSizeMipmap);
|
Texture::registerPluginStream(ID_SKYMIPMAP, readMipmap, writeMipmap, getSizeMipmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct StreamRasterExt
|
struct StreamRasterExt
|
||||||
{
|
{
|
||||||
int32 width;
|
int32 width;
|
||||||
int32 height;
|
int32 height;
|
||||||
int32 depth;
|
int32 depth;
|
||||||
uint16 rasterFormat;
|
uint16 rasterFormat;
|
||||||
int16 type;
|
int16 type;
|
||||||
uint32 tex0[2];
|
uint32 tex0[2];
|
||||||
uint32 tex1[2];
|
uint32 tex1[2];
|
||||||
uint32 miptbp1[2];
|
uint32 miptbp1[2];
|
||||||
uint32 miptbp2[2];
|
uint32 miptbp2[2];
|
||||||
uint32 texelSize;
|
uint32 texelSize;
|
||||||
uint32 paletteSize;
|
uint32 paletteSize;
|
||||||
uint32 gsSize;
|
uint32 gsSize;
|
||||||
uint32 mipmapVal;
|
uint32 mipmapVal;
|
||||||
};
|
};
|
||||||
|
|
||||||
Texture*
|
Texture*
|
||||||
|
|
|
@ -199,11 +199,18 @@ struct Texture : PluginBase<Texture>
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SurfaceProperties
|
||||||
|
{
|
||||||
|
float32 ambient;
|
||||||
|
float32 specular;
|
||||||
|
float32 diffuse;
|
||||||
|
};
|
||||||
|
|
||||||
struct Material : PluginBase<Material>
|
struct Material : PluginBase<Material>
|
||||||
{
|
{
|
||||||
Texture *texture;
|
Texture *texture;
|
||||||
uint8 color[4];
|
uint8 color[4];
|
||||||
float32 surfaceProps[3];
|
SurfaceProperties surfaceProps;
|
||||||
Pipeline *pipeline;
|
Pipeline *pipeline;
|
||||||
int32 refCount;
|
int32 refCount;
|
||||||
|
|
||||||
|
@ -220,7 +227,7 @@ void registerMaterialRightsPlugin(void);
|
||||||
|
|
||||||
struct MatFX
|
struct MatFX
|
||||||
{
|
{
|
||||||
enum Flags {
|
enum {
|
||||||
NOTHING = 0,
|
NOTHING = 0,
|
||||||
BUMPMAP,
|
BUMPMAP,
|
||||||
ENVMAP,
|
ENVMAP,
|
||||||
|
@ -259,7 +266,7 @@ struct MatFX
|
||||||
UVtransform uvtransform;
|
UVtransform uvtransform;
|
||||||
};
|
};
|
||||||
} fx[2];
|
} fx[2];
|
||||||
uint32 flags;
|
uint32 type;
|
||||||
|
|
||||||
void setEffects(uint32 flags);
|
void setEffects(uint32 flags);
|
||||||
int32 getEffectIndex(uint32 type);
|
int32 getEffectIndex(uint32 type);
|
||||||
|
|
|
@ -0,0 +1,671 @@
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
#include <cassert>
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include <args.h>
|
||||||
|
#include <rw.h>
|
||||||
|
#include <src/gtaplg.h>
|
||||||
|
|
||||||
|
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<<i;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
if(w >= 16 && h >= 4)
|
||||||
|
swiz |= 1<<i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
w /= 2;
|
||||||
|
h /= 2;
|
||||||
|
}
|
||||||
|
return swiz;
|
||||||
|
}
|
||||||
|
|
||||||
|
RslRaster*
|
||||||
|
RslCreateRasterPS2(uint32 w, uint32 h, uint32 d, uint32 mipmaps)
|
||||||
|
{
|
||||||
|
RslRasterPS2 *r;
|
||||||
|
r = new RslRasterPS2;
|
||||||
|
uint32 tmp, logw = 0, logh = 0;
|
||||||
|
for(tmp = 1; tmp < w; tmp <<= 1)
|
||||||
|
logw++;
|
||||||
|
for(tmp = 1; tmp < h; tmp <<= 1)
|
||||||
|
logh++;
|
||||||
|
r->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;
|
||||||
|
}
|
|
@ -42,12 +42,41 @@ typedef RslAtomic *(*RslAtomicCallBack)(RslAtomic *atomic, void *data);
|
||||||
typedef RslMaterial *(*RslMaterialCallBack)(RslMaterial *material, void *data);
|
typedef RslMaterial *(*RslMaterialCallBack)(RslMaterial *material, void *data);
|
||||||
typedef RslTexture *(*RslTextureCallBack)(RslTexture *texture, void *pData);
|
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 *next;
|
||||||
RslLLLink *prev;
|
RslLLLink *prev;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RslLinkList {
|
struct RslLinkList
|
||||||
|
{
|
||||||
RslLLLink link;
|
RslLLLink link;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -68,20 +97,31 @@ struct RslLinkList {
|
||||||
((linkvar)->next)
|
((linkvar)->next)
|
||||||
|
|
||||||
struct RslObject {
|
struct RslObject {
|
||||||
uint8 type;
|
uint8 type;
|
||||||
uint8 subType;
|
uint8 subType;
|
||||||
uint8 flags;
|
uint8 flags;
|
||||||
uint8 privateFlags;
|
uint8 privateFlags;
|
||||||
void *parent;
|
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 {
|
struct RslObjectHasFrame {
|
||||||
RslObject object;
|
RslObject object;
|
||||||
RslLLLink lFrame;
|
RslLLLink lFrame;
|
||||||
void (*sync)();
|
void (*sync)();
|
||||||
};
|
};
|
||||||
|
|
||||||
#define rslObjectGetParent(object) (((const RslObject *)(object))->parent)
|
void rslObjectHasFrameSetFrame(RslObjectHasFrame *object, RslFrame *f);
|
||||||
|
|
||||||
struct RslRasterPS2 {
|
struct RslRasterPS2 {
|
||||||
uint8 *data;
|
uint8 *data;
|
||||||
|
@ -110,6 +150,8 @@ union RslRaster {
|
||||||
RslRasterPSP psp;
|
RslRasterPSP psp;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
RslRaster *RslCreateRasterPS2(uint32 w, uint32 h, uint32 d, uint32 mipmaps);
|
||||||
|
|
||||||
struct RslTexDictionary {
|
struct RslTexDictionary {
|
||||||
RslObject object;
|
RslObject object;
|
||||||
RslLinkList texturesInDict;
|
RslLinkList texturesInDict;
|
||||||
|
@ -119,6 +161,7 @@ struct RslTexDictionary {
|
||||||
RslTexDictionary *RslTexDictionaryStreamRead(Stream *stream);
|
RslTexDictionary *RslTexDictionaryStreamRead(Stream *stream);
|
||||||
RslTexDictionary *RslTexDictionaryCreate(void);
|
RslTexDictionary *RslTexDictionaryCreate(void);
|
||||||
RslTexture *RslTexDictionaryAddTexture(RslTexDictionary *dict, RslTexture *tex);
|
RslTexture *RslTexDictionaryAddTexture(RslTexDictionary *dict, RslTexture *tex);
|
||||||
|
RslTexDictionary *RslTexDictionaryForAllTextures(RslTexDictionary *dict, RslTextureCallBack fpCallBack, void *pData);
|
||||||
|
|
||||||
struct RslTexture {
|
struct RslTexture {
|
||||||
RslRaster *raster;
|
RslRaster *raster;
|
||||||
|
@ -129,13 +172,16 @@ struct RslTexture {
|
||||||
};
|
};
|
||||||
|
|
||||||
RslTexture *RslTextureCreate(RslRaster *raster);
|
RslTexture *RslTextureCreate(RslRaster *raster);
|
||||||
|
void RslTextureDestroy(RslTexture *texture);
|
||||||
|
RslTexture *RslTextureStreamRead(Stream *stream);
|
||||||
|
RslTexture *RslReadNativeTexturePS2(Stream *stream);
|
||||||
|
|
||||||
struct RslFrame {
|
struct RslFrame {
|
||||||
RslObject object;
|
RslObject object;
|
||||||
RslLLLink inDirtyListLink; // ?
|
RslLinkList objectList;
|
||||||
|
|
||||||
float32 modelling[16];
|
RslMatrix modelling;
|
||||||
float32 ltm[16];
|
RslMatrix ltm;
|
||||||
RslFrame *child;
|
RslFrame *child;
|
||||||
RslFrame *next;
|
RslFrame *next;
|
||||||
RslFrame *root;
|
RslFrame *root;
|
||||||
|
@ -149,6 +195,16 @@ struct RslFrame {
|
||||||
int32 hierId;
|
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 {
|
struct RslClump {
|
||||||
RslObject object;
|
RslObject object;
|
||||||
RslLinkList atomicList;
|
RslLinkList atomicList;
|
||||||
|
@ -157,6 +213,10 @@ struct RslClump {
|
||||||
#define RslClumpGetFrame(_clump) \
|
#define RslClumpGetFrame(_clump) \
|
||||||
((RslFrame *) rslObjectGetParent(_clump))
|
((RslFrame *) rslObjectGetParent(_clump))
|
||||||
|
|
||||||
|
RslClump *RslClumpStreamRead(Stream *stream);
|
||||||
|
RslClump *RslClumpAddAtomic(RslClump *clump, RslAtomic *a);
|
||||||
|
RslClump *RslClumpForAllAtomics(RslClump *clump, RslAtomicCallBack callback, void *pData);
|
||||||
|
|
||||||
struct RslAtomic {
|
struct RslAtomic {
|
||||||
RslObjectHasFrame object;
|
RslObjectHasFrame object;
|
||||||
RslGeometry *geometry;
|
RslGeometry *geometry;
|
||||||
|
@ -176,6 +236,10 @@ struct RslAtomic {
|
||||||
#define RslAtomicGetFrame(_atomic) \
|
#define RslAtomicGetFrame(_atomic) \
|
||||||
((RslFrame *) rslObjectGetParent(_atomic))
|
((RslFrame *) rslObjectGetParent(_atomic))
|
||||||
|
|
||||||
|
RslAtomic *RslAtomicCreate(void);
|
||||||
|
RslAtomic *RslAtomicSetFrame(RslAtomic *atomic, RslFrame *frame);
|
||||||
|
RslAtomic *RslAtomicStreamRead(Stream *stream, rslFrameList *framelist);
|
||||||
|
|
||||||
struct RslMaterialList {
|
struct RslMaterialList {
|
||||||
RslMaterial **materials;
|
RslMaterial **materials;
|
||||||
int32 numMaterials;
|
int32 numMaterials;
|
||||||
|
@ -193,9 +257,15 @@ struct RslGeometry {
|
||||||
uint32 pad2; // 0xAAAAAAAA
|
uint32 pad2; // 0xAAAAAAAA
|
||||||
};
|
};
|
||||||
|
|
||||||
|
RslGeometry *RslGeometryCreatePS2(uint32 sz);
|
||||||
|
RslGeometry *RslGeometryForAllMaterials(RslGeometry *geometry, RslMaterialCallBack fpCallBack, void *pData);
|
||||||
|
|
||||||
struct RslMatFXEnv {
|
struct RslMatFXEnv {
|
||||||
RslFrame *frame;
|
RslFrame *frame;
|
||||||
char *texname;
|
union {
|
||||||
|
char *texname;
|
||||||
|
RslTexture *texture;
|
||||||
|
};
|
||||||
float32 intensity;
|
float32 intensity;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -207,12 +277,18 @@ struct RslMatFX {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RslMaterial {
|
struct RslMaterial {
|
||||||
char *texname;
|
union {
|
||||||
uint32 color;
|
char *texname;
|
||||||
|
RslTexture *texture;
|
||||||
|
};
|
||||||
|
RslRGBA color;
|
||||||
uint32 refCount;
|
uint32 refCount;
|
||||||
RslMatFX *matfx;
|
RslMatFX *matfx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
RslMaterial *RslMaterialCreate(void);
|
||||||
|
RslMaterial *RslMaterialStreamRead(Stream *stream);
|
||||||
|
|
||||||
struct RslHAnimNodeInfo {
|
struct RslHAnimNodeInfo {
|
||||||
int8 id;
|
int8 id;
|
||||||
int8 index;
|
int8 index;
|
||||||
|
@ -262,6 +338,8 @@ struct RslSkin {
|
||||||
void *data; // NULL
|
void *data; // NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
RslSkin *RslSkinStreamRead(Stream *stream, RslGeometry *g);
|
||||||
|
|
||||||
struct RslPS2ResEntryHeader {
|
struct RslPS2ResEntryHeader {
|
||||||
float32 bound[4];
|
float32 bound[4];
|
||||||
uint32 size; // and numMeshes
|
uint32 size; // and numMeshes
|
||||||
|
@ -275,9 +353,9 @@ struct RslPS2ResEntryHeader {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RslPS2InstanceData {
|
struct RslPS2InstanceData {
|
||||||
float32 bound[4]; // ?
|
float32 bound[4];
|
||||||
float32 uvScale[2];
|
float32 uvScale[2];
|
||||||
int32 unk1;
|
int32 unknown;
|
||||||
uint32 dmaPacket;
|
uint32 dmaPacket;
|
||||||
uint16 numTriangles;
|
uint16 numTriangles;
|
||||||
int16 matID;
|
int16 matID;
|
||||||
|
|
|
@ -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<<i;
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
if(w >= 16 && h >= 4)
|
|
||||||
swiz |= 1<<i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
w /= 2;
|
|
||||||
h /= 2;
|
|
||||||
}
|
|
||||||
return swiz;
|
|
||||||
}
|
|
||||||
|
|
||||||
RslRaster*
|
|
||||||
RslCreateRasterPS2(uint32 w, uint32 h, uint32 d, uint32 mipmaps)
|
|
||||||
{
|
|
||||||
RslRasterPS2 *r;
|
|
||||||
r = new RslRasterPS2;
|
|
||||||
uint32 tmp, logw = 0, logh = 0;
|
|
||||||
for(tmp = 1; tmp < w; tmp <<= 1)
|
|
||||||
logw++;
|
|
||||||
for(tmp = 1; tmp < h; tmp <<= 1)
|
|
||||||
logh++;
|
|
||||||
r->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)
|
RslFrame *dumpFrameCB(RslFrame *frame, void *data)
|
||||||
|
@ -569,13 +401,19 @@ main(int argc, char *argv[])
|
||||||
uint32 ident = stream.readU32();
|
uint32 ident = stream.readU32();
|
||||||
stream.seek(0, 0);
|
stream.seek(0, 0);
|
||||||
|
|
||||||
if(ident == 0x16){
|
if(ident == ID_TEXDICTIONARY){
|
||||||
findChunk(&stream, ID_TEXDICTIONARY, NULL, NULL);
|
findChunk(&stream, ID_TEXDICTIONARY, NULL, NULL);
|
||||||
txd = RslTexDictionaryStreamRead(&stream);
|
txd = RslTexDictionaryStreamRead(&stream);
|
||||||
stream.close();
|
stream.close();
|
||||||
assert(txd);
|
assert(txd);
|
||||||
goto writeTxd;
|
goto writeTxd;
|
||||||
}
|
}
|
||||||
|
if(ident == 0x10){
|
||||||
|
findChunk(&stream, ID_CLUMP, NULL, NULL);
|
||||||
|
clump = RslClumpStreamRead(&stream);
|
||||||
|
stream.close();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
RslStream *rslstr = new RslStream;
|
RslStream *rslstr = new RslStream;
|
||||||
stream.read(rslstr, 0x20);
|
stream.read(rslstr, 0x20);
|
||||||
|
|
|
@ -80,6 +80,7 @@
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="rsl.cpp" />
|
||||||
<ClCompile Include="rsltest.cpp" />
|
<ClCompile Include="rsltest.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
Loading…
Reference in New Issue