diff --git a/args.h b/args.h new file mode 100644 index 0000000..308339c --- /dev/null +++ b/args.h @@ -0,0 +1,24 @@ +extern char *argv0; +#define USED(x) ((void)x) +#define SET(x) ((x)=0) + +#define ARGBEGIN for((argv0||(argv0=*argv)),argv++,argc--;\ + argv[0] && argv[0][0]=='-' && argv[0][1];\ + argc--, argv++) {\ + char *_args, *_argt;\ + char _argc;\ + _args = &argv[0][1];\ + if(_args[0]=='-' && _args[1]==0){\ + argc--; argv++; break;\ + }\ + _argc = 0;\ + while(*_args && (_argc = *_args++))\ + switch(_argc) +#define ARGEND SET(_argt);USED(_argt);USED(_argc);USED(_args);}USED(argv);USED(argc); +#define ARGF() (_argt=_args, _args="",\ + (*_argt? _argt: argv[1]? (argc--, *++argv): 0)) +#define EARGF(x) (_argt=_args, _args="",\ + (*_argt? _argt: argv[1]? (argc--, *++argv): ((x), abort(), (char*)0))) + +#define ARGC() _argc + diff --git a/librw.sln b/librw.sln index 146ebde..2888863 100644 --- a/librw.sln +++ b/librw.sln @@ -31,6 +31,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "txdwrite", "tools\txdwrite\ EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rsltest", "tools\rsltest\rsltest.vcxproj", "{27ECE916-900F-49B2-8E9F-95E6B347E161}" + ProjectSection(ProjectDependencies) = postProject + {30552BB0-3B19-49A4-ABF4-87CF68AF9E38} = {30552BB0-3B19-49A4-ABF4-87CF68AF9E38} + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/src/gtaplg.cpp b/src/gtaplg.cpp index 7780bec..5a0bdd8 100644 --- a/src/gtaplg.cpp +++ b/src/gtaplg.cpp @@ -1064,7 +1064,6 @@ saUninstanceCB(ps2::MatPipeline *pipe, Geometry *geo, uint32 flags[], Mesh *mesh norms += 4; wghts += 4; } - } static void @@ -1205,7 +1204,7 @@ saInstanceCB(MatPipeline *pipe, Geometry *g, Mesh *m, uint8 **data) ADCData *adc = PLUGINOFFSET(ADCData, g, adcOffset); for(int i = 0; i < nelem(pipe->attribs); i++){ - PipeAttribute *a = pipe->attribs[i]; + rw::PipeAttribute *a = pipe->attribs[i]; if(a == &saXYZADC) instanceSAPositions(g, m, adc->adcFormatted ? adc->adcBits : NULL, (int16*)data[i], vertScale); diff --git a/src/ps2.cpp b/src/ps2.cpp index 4753227..bb96ccf 100644 --- a/src/ps2.cpp +++ b/src/ps2.cpp @@ -1212,6 +1212,12 @@ debugadc(Geometry *g, MeshHeader *mh, ADCData *adc) return n; } +// TODO +void +convertADC(Geometry *g) +{ +} + // Not optimal but works void unconvertADC(Geometry *g) @@ -1310,11 +1316,12 @@ readADC(Stream *stream, int32, void *object, int32 offset, int32) ADCData *adc = PLUGINOFFSET(ADCData, object, offset); assert(findChunk(stream, ID_ADC, NULL, NULL)); adc->numBits = stream->readI32(); + adc->adcFormatted = 1; if(adc->numBits == 0){ - adc->adcFormatted = 0; + adc->adcBits = NULL; + adc->numBits = 0; return; } - adc->adcFormatted = 1; int32 size = adc->numBits+3 & ~3; adc->adcBits = new int8[size]; stream->read(adc->adcBits, size); @@ -1357,7 +1364,7 @@ getSizeADC(void *object, int32 offset, int32) Geometry *geometry = (Geometry*)object; ADCData *adc = PLUGINOFFSET(ADCData, object, offset); if(!adc->adcFormatted) - return -1; + return 0; if(geometry->geoflags & Geometry::NATIVE) return 16; return 16 + (adc->numBits+3 & ~3); diff --git a/src/rwps2.h b/src/rwps2.h index 2b8d329..513277b 100644 --- a/src/rwps2.h +++ b/src/rwps2.h @@ -147,6 +147,7 @@ struct ADCData extern int32 adcOffset; void registerADCPlugin(void); +void convertADC(Geometry *g); void unconvertADC(Geometry *geo); void allocateADC(Geometry *geo); diff --git a/tools/insttest/insttest.cpp b/tools/insttest/insttest.cpp index d365c1f..0daeed2 100644 --- a/tools/insttest/insttest.cpp +++ b/tools/insttest/insttest.cpp @@ -5,11 +5,69 @@ #include #include +#include #include using namespace std; using namespace rw; +struct { + char *str; + uint32 val; +} platforms[] = { + { "mobile", PLATFORM_OGL }, + { "ps2", PLATFORM_PS2 }, + { "xbox", PLATFORM_XBOX }, + { "d3d8", PLATFORM_D3D8 }, + { "d3d9", PLATFORM_D3D9 }, + { NULL, 0 } +}; + +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 +usage(void) +{ + fprintf(stderr, "usage: %s [-u] [-i] [-v version] [-o platform] in.dff [out.dff]\n", argv0); + fprintf(stderr, "\t-u uninstance\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-o output platform. ps2, xbox, mobile, d3d8, d3d9\n"); + fprintf(stderr, "\t-s expect iOS LCS dff as input\n"); + exit(1); +} + int main(int argc, char *argv[]) { @@ -18,36 +76,66 @@ main(int argc, char *argv[]) rw::version = 0; // rw::version = 0x34003; // rw::version = 0x33002; - rw::platform = rw::PLATFORM_PS2; +// rw::platform = rw::PLATFORM_PS2; // rw::platform = rw::PLATFORM_OGL; // rw::platform = rw::PLATFORM_XBOX; -// rw::platform = rw::PLATFORM_D3D8; + rw::platform = rw::PLATFORM_D3D8; // rw::platform = rw::PLATFORM_D3D9; int uninstance = 0; - int arg = 1; + int instance = 0; + int lcs = 0; + int outplatform = rw::PLATFORM_D3D8; - if(argc < 2){ - printf("usage: %s [-u] in.dff\n", argv[0]); - return 0; - } - - if(strcmp(argv[arg], "-u") == 0){ + char *s; + ARGBEGIN{ + case 'u': uninstance++; - arg++; - if(argc < 3){ - printf("usage: %s [-u] in.dff\n", argv[0]); - return 0; + break; + case 'i': + instance++; + break; + case 'v': + sscanf(EARGF(usage()), "%x", &rw::version); + break; + case 'o': + s = EARGF(usage()); + for(int i = 0; platforms[i].str; i++){ + if(strcmp(platforms[i].str, s) == 0){ + outplatform = platforms[i].val; + goto found; + } } + printf("unknown platform %s\n", s); + outplatform = PLATFORM_D3D8; + found: + break; + case 's': + lcs++; + break; + default: + usage(); + }ARGEND; + + if(uninstance && instance){ + fprintf(stderr, "cannot both instance and uninstance, choose one!\n"); + return 1; } + matFXGlobals.hack = lcs; + skinGlobals.forceSkipUsedBones = lcs; + + if(argc < 1) + usage(); + Clump *c; - uint32 len; - uint8 *data = getFileContents(argv[arg], &len); - assert(data != NULL); - StreamMemory in; - in.open(data, len); - + //uint32 len; + //uint8 *data = getFileContents(argv[0], &len); + //assert(data != NULL); + //StreamMemory in; + //in.open(data, len); + StreamFile in; + in.open(argv[0], "rb"); ChunkHeaderInfo header; readChunkHeaderInfo(&in, &header); if(header.type == ID_UVANIMDICT){ @@ -56,9 +144,13 @@ main(int argc, char *argv[]) readChunkHeaderInfo(&in, &header); } assert(header.type == ID_CLUMP); - debugFile = argv[arg]; - c = Clump::streamRead(&in); + debugFile = argv[0]; + if(lcs) + c = clumpStreamReadRsl(&in); + else + c = Clump::streamRead(&in); assert(c != NULL); + in.close(); // printf("%s\n", argv[arg]); @@ -78,44 +170,74 @@ main(int argc, char *argv[]) int32 platform = findPlatform(c); if(platform){ rw::platform = platform; - switchPipes(c, platform); + switchPipes(c, rw::platform); } - for(int32 i = 0; i < c->numAtomics; i++){ - Atomic *a = c->atomicList[i]; - ObjPipeline *p = a->getPipeline(); - if(uninstance){ - p->uninstance(a); - //ps2::unconvertADC(a->geometry); - }else - p->instance(a); + 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) + for(int32 i = 0; i < c->numAtomics; i++){ + Atomic *a = c->atomicList[i]; + ObjPipeline *p = a->getPipeline(); + p->uninstance(a); + if(outplatform != PLATFORM_PS2) + ps2::unconvertADC(a->geometry); + } + + rw::platform = outplatform; + switchPipes(c, rw::platform); + + if(instance) + for(int32 i = 0; i < c->numAtomics; i++){ + Atomic *a = c->atomicList[i]; + ObjPipeline *p = a->getPipeline(); + p->instance(a); + if(outplatform != PLATFORM_PS2) + ps2::convertADC(a->geometry); + } + if(rw::version == 0){ rw::version = header.version; rw::build = header.build; } - if(uninstance) - rw::platform = rw::PLATFORM_D3D8; - - data = new rw::uint8[1024*1024]; - rw::StreamMemory out; - out.open(data, 0, 1024*1024); + StreamFile out; + if(argc > 1) + assert(out.open(argv[1], "wb")); + else + assert(out.open("out.dff", "wb")); if(currentUVAnimDictionary) currentUVAnimDictionary->streamWrite(&out); c->streamWrite(&out); - - FILE *cf; - if(arg+1 < argc) - cf = fopen(argv[arg+1], "wb"); - else - cf = fopen("out.dff", "wb"); - assert(cf != NULL); - fwrite(data, out.getLength(), 1, cf); - fclose(cf); out.close(); - delete[] data; + +// data = new rw::uint8[1024*1024]; +// rw::StreamMemory out; +// out.open(data, 0, 1024*1024); +// if(currentUVAnimDictionary) +// currentUVAnimDictionary->streamWrite(&out); +// c->streamWrite(&out); +// +// FILE *cf; +// if(argc > 1) +// cf = fopen(argv[1], "wb"); +// else +// cf = fopen("out.dff", "wb"); +// assert(cf != NULL); +// fwrite(data, out.getLength(), 1, cf); +// fclose(cf); +// out.close(); +// delete[] data; delete c; diff --git a/tools/rsltest/rsltest.vcxproj b/tools/rsltest/rsltest.vcxproj index a001194..4381678 100644 --- a/tools/rsltest/rsltest.vcxproj +++ b/tools/rsltest/rsltest.vcxproj @@ -68,6 +68,7 @@ true true true + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true