From 811c0453269496a72ade474f0bb1bf2043a2bb65 Mon Sep 17 00:00:00 2001 From: Angelo Papenhoff Date: Tue, 6 Jan 2015 23:17:05 +0100 Subject: [PATCH] Implemented Extra vertex colors and (crippled) ADC plugin. --- Makefile | 5 +- Makefile.mingw | 5 +- Makefile.ps2 | 5 +- dffwrite.cpp | 13 +- src/geometry.cpp | 1 + src/plugins.cpp | 388 ----------------------------------------------- src/ps2.cpp | 129 +++++++++++++++- src/rwbase.h | 4 +- src/rwobjects.h | 8 +- src/rwps2.h | 17 ++- 10 files changed, 166 insertions(+), 409 deletions(-) delete mode 100644 src/plugins.cpp diff --git a/Makefile b/Makefile index 4d4f4cf..9e7b5d7 100644 --- a/Makefile +++ b/Makefile @@ -6,8 +6,9 @@ BUILDDEF:=$(shell echo $(BUILD) | tr a-z A-Z | sed 's/^/-DRW_/') BUILDDIR=build-$(BUILD) SRCDIR=src SRC := $(patsubst %.cpp,$(SRCDIR)/%.cpp, rwbase.cpp clump.cpp\ - geometry.cpp plugins.cpp ps2.cpp\ - ogl.cpp image.cpp) + geometry.cpp geometryplg.cpp\ + ps2.cpp ogl.cpp\ + image.cpp gtaplg.cpp) OBJ := $(patsubst $(SRCDIR)/%.cpp,$(BUILDDIR)/%.o,$(SRC)) DEP := $(patsubst $(SRCDIR)/%.cpp,$(BUILDDIR)/%.d,$(SRC)) CFLAGS=-Wall -Wextra -g $(BUILDDEF) #-Wno-parentheses #-Wconversion diff --git a/Makefile.mingw b/Makefile.mingw index e1b9c6f..f50600d 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -6,8 +6,9 @@ BUILDDEF:=$(shell echo $(BUILD) | tr a-z A-Z | sed 's/^/-DRW_/') BUILDDIR=build-$(BUILD) SRCDIR=src SRC := $(patsubst %.cpp,$(SRCDIR)/%.cpp, rwbase.cpp clump.cpp\ - geometry.cpp plugins.cpp ps2.cpp\ - ogl.cpp) + geometry.cpp geometryplg.cpp\ + ps2.cpp ogl.cpp\ + image.cpp gtaplg.cpp) OBJ := $(patsubst $(SRCDIR)/%.cpp,$(BUILDDIR)/%.o,$(SRC)) DEP := $(patsubst $(SRCDIR)/%.cpp,$(BUILDDIR)/%.d,$(SRC)) CFLAGS=-Wall -Wextra -g -DGLEW_STATIC $(BUILDDEF) #-Wno-parentheses #-Wconversion diff --git a/Makefile.ps2 b/Makefile.ps2 index f8586c7..fee7f97 100644 --- a/Makefile.ps2 +++ b/Makefile.ps2 @@ -7,8 +7,9 @@ BUILDDEF:=$(shell echo $(BUILD) | tr a-z A-Z | sed 's/^/-DRW_/') BUILDDIR=build-$(BUILD) SRCDIR=src SRC := $(patsubst %.cpp,$(SRCDIR)/%.cpp, rwbase.cpp clump.cpp\ - geometry.cpp plugins.cpp ps2.cpp\ - ogl.cpp image.cpp) + geometry.cpp geometryplg.cpp\ + ps2.cpp ogl.cpp\ + image.cpp gtaplg.cpp) OBJ := $(patsubst $(SRCDIR)/%.cpp,$(BUILDDIR)/%.o,$(SRC)) DEP := $(patsubst $(SRCDIR)/%.cpp,$(BUILDDIR)/%.d,$(SRC)) CFLAGS=-Wall -g $(BUILDDEF) #-Wno-parentheses #-Wconversion diff --git a/dffwrite.cpp b/dffwrite.cpp index c8725ea..dbb424e 100644 --- a/dffwrite.cpp +++ b/dffwrite.cpp @@ -6,6 +6,7 @@ #include #include "rw.h" +#include "src/gtaplg.h" using namespace std; @@ -15,11 +16,13 @@ main(int argc, char *argv[]) // Rw::Version = 0x31000; // Rw::Build = 0; - registerNodeNamePlugin(); - registerBreakableModelPlugin(); - registerNativeDataPlugin(); -// Ps2::registerNativeDataPlugin(); - registerMeshPlugin(); + Rw::RegisterNodeNamePlugin(); + Rw::RegisterBreakableModelPlugin(); + Rw::RegisterExtraVertColorPlugin(); + Rw::Ps2::RegisterADCPlugin(); + Rw::RegisterNativeDataPlugin(); +// Rw::Ps2::RegisterNativeDataPlugin(); + Rw::RegisterMeshPlugin(); Rw::Clump *c; // ifstream in(argv[1], ios::binary); diff --git a/src/geometry.cpp b/src/geometry.cpp index d4d3525..c3387a0 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -435,6 +435,7 @@ Texture::streamWrite(Stream *stream) WriteChunkHeader(stream, ID_STRUCT, 4); stream->writeU32(this->filterAddressing); + // TODO: 4 char string -> 8 bytes // TODO: length can't be > 32 size = strlen(this->name)+3 & ~3; if(size < 4) diff --git a/src/plugins.cpp b/src/plugins.cpp deleted file mode 100644 index f04d96e..0000000 --- a/src/plugins.cpp +++ /dev/null @@ -1,388 +0,0 @@ -#include -#include -#include -#include - -//#include -//#include -#include - -#include "rwbase.h" -#include "rwplugin.h" -#include "rwobjects.h" -#include "rwps2.h" -#include "rwogl.h" - -using namespace std; -using namespace Rw; - -// -// Frame -// - -// Node Name - -static void* -createNodeName(void *object, int32 offset, int32) -{ - char *name = PLUGINOFFSET(char, object, offset); - name[0] = '\0'; - return object; -} - -static void* -copyNodeName(void *dst, void *src, int32 offset, int32) -{ - char *dstname = PLUGINOFFSET(char, dst, offset); - char *srcname = PLUGINOFFSET(char, src, offset); - strncpy(dstname, srcname, 17); - return dst; -} - -static void* -destroyNodeName(void *object, int32, int32) -{ - return object; -} - -static void -readNodeName(Stream *stream, int32 len, void *object, int32 offset, int32) -{ - char *name = PLUGINOFFSET(char, object, offset); - stream->read(name, len); - name[len] = '\0'; -} - -static void -writeNodeName(Stream *stream, int32 len, void *object, int32 offset, int32) -{ - char *name = PLUGINOFFSET(char, object, offset); - stream->write(name, len); -} - -static int32 -getSizeNodeName(void *object, int32 offset) -{ - char *name = PLUGINOFFSET(char, object, offset); - int32 len = strlen(name); - return len > 0 ? len : -1; -} - - -void -registerNodeNamePlugin(void) -{ - Frame::registerPlugin(18, 0x253f2fe, (Constructor)createNodeName, - (Destructor)destroyNodeName, - (CopyConstructor)copyNodeName); - Frame::registerPluginStream(0x253f2fe, (StreamRead)readNodeName, - (StreamWrite)writeNodeName, - (StreamGetSize)getSizeNodeName); -} - -// -// Geometry -// - -// Mesh - -static void -readMesh(Stream *stream, int32 len, void *object, int32, int32) -{ - Geometry *geo = (Geometry*)object; - int32 indbuf[256]; - uint32 buf[3]; - stream->read(buf, 12); - geo->meshHeader = new MeshHeader; - geo->meshHeader->flags = buf[0]; - geo->meshHeader->numMeshes = buf[1]; - geo->meshHeader->totalIndices = buf[2]; - geo->meshHeader->mesh = new Mesh[geo->meshHeader->numMeshes]; - Mesh *mesh = geo->meshHeader->mesh; - bool hasData = len > 12+geo->meshHeader->numMeshes*8; - for(uint32 i = 0; i < geo->meshHeader->numMeshes; i++){ - stream->read(buf, 8); - mesh->numIndices = buf[0]; - mesh->material = geo->materialList[buf[1]]; - mesh->indices = NULL; - if(geo->geoflags & Geometry::NATIVE){ - // OpenGL stores uint16 indices here - if(hasData){ - mesh->indices = new uint16[mesh->numIndices]; - stream->read(mesh->indices, - mesh->numIndices*2); - } - }else{ - mesh->indices = new uint16[mesh->numIndices]; - uint16 *ind = mesh->indices; - int32 numIndices = mesh->numIndices; - for(; numIndices > 0; numIndices -= 256){ - int32 n = numIndices < 256 ? numIndices : 256; - stream->read(indbuf, n*4); - for(int32 j = 0; j < n; j++) - ind[j] = indbuf[j]; - ind += n; - } - } - mesh++; - } -} - -static void -writeMesh(Stream *stream, int32, void *object, int32, int32) -{ - Geometry *geo = (Geometry*)object; - int32 indbuf[256]; - uint32 buf[3]; - buf[0] = geo->meshHeader->flags; - buf[1] = geo->meshHeader->numMeshes; - buf[2] = geo->meshHeader->totalIndices; - stream->write(buf, 12); - Mesh *mesh = geo->meshHeader->mesh; - for(uint32 i = 0; i < geo->meshHeader->numMeshes; i++){ - buf[0] = mesh->numIndices; - buf[1] = findPointer((void*)mesh->material, - (void**)geo->materialList, - geo->numMaterials); - stream->write(buf, 8); - if(geo->geoflags & Geometry::NATIVE){ - assert(geo->instData != NULL); - if(geo->instData->platform == PLATFORM_OGL) - stream->write(mesh->indices, - mesh->numIndices*2); - }else{ - uint16 *ind = mesh->indices; - int32 numIndices = mesh->numIndices; - for(; numIndices > 0; numIndices -= 256){ - int32 n = numIndices < 256 ? numIndices : 256; - for(int32 j = 0; j < n; j++) - indbuf[j] = ind[j]; - stream->write(indbuf, n*4); - ind += n; - } - } - mesh++; - } -} - -static int32 -getSizeMesh(void *object, int32) -{ - Geometry *geo = (Geometry*)object; - if(geo->meshHeader == NULL) - return -1; - int32 size = 12 + geo->meshHeader->numMeshes*8; - if(geo->geoflags & Geometry::NATIVE){ - assert(geo->instData != NULL); - if(geo->instData->platform == PLATFORM_OGL) - size += geo->meshHeader->totalIndices*2; - }else{ - size += geo->meshHeader->totalIndices*4; - } - return size; -} - - -void -registerMeshPlugin(void) -{ - Geometry::registerPlugin(0, 0x50E, NULL, NULL, NULL); - Geometry::registerPluginStream(0x50E, (StreamRead)readMesh, - (StreamWrite)writeMesh, - (StreamGetSize)getSizeMesh); -} - -// Native Data - -static void* -destroyNativeData(void *object, int32 offset, int32 size) -{ - Geometry *geometry = (Geometry*)object; - if(geometry->instData == NULL) - return object; - if(geometry->instData->platform == PLATFORM_PS2) - return Ps2::DestroyNativeData(object, offset, size); - if(geometry->instData->platform == PLATFORM_OGL) - return Gl::DestroyNativeData(object, offset, size); - return object; -} - -static void -readNativeData(Stream *stream, int32 len, void *object, int32 o, int32 s) -{ - ChunkHeaderInfo header; - uint32 libid; - uint32 platform; - // ugly hack to find out platform - stream->seek(-4); - libid = stream->readU32(); - ReadChunkHeaderInfo(stream, &header); - if(header.type == ID_STRUCT && - LibraryIDPack(header.version, header.build) == libid){ - // must be PS2 or Xbox - platform = stream->readU32(); - stream->seek(-16); - if(platform == PLATFORM_PS2) - Ps2::ReadNativeData(stream, len, object, o, s); - else if(platform == PLATFORM_XBOX) - stream->seek(len); - }else{ - stream->seek(-12); - Gl::ReadNativeData(stream, len, object, o, s); - } -} - -static void -writeNativeData(Stream *stream, int32 len, void *object, int32 o, int32 s) -{ - Geometry *geometry = (Geometry*)object; - if(geometry->instData == NULL) - return; - if(geometry->instData->platform == PLATFORM_PS2) - Ps2::WriteNativeData(stream, len, object, o, s); - else if(geometry->instData->platform == PLATFORM_OGL) - Gl::WriteNativeData(stream, len, object, o, s); -} - -static int32 -getSizeNativeData(void *object, int32 offset, int32 size) -{ - Geometry *geometry = (Geometry*)object; - if(geometry->instData == NULL) - return -1; - if(geometry->instData->platform == PLATFORM_PS2) - return Ps2::GetSizeNativeData(object, offset, size); - else if(geometry->instData->platform == PLATFORM_XBOX) - return -1; - else if(geometry->instData->platform == PLATFORM_OGL) - return Gl::GetSizeNativeData(object, offset, size); - return -1; -} - -void -registerNativeDataPlugin(void) -{ - Geometry::registerPlugin(0, ID_NATIVEDATA, - NULL, destroyNativeData, NULL); - Geometry::registerPluginStream(ID_NATIVEDATA, - (StreamRead)readNativeData, - (StreamWrite)writeNativeData, - (StreamGetSize)getSizeNativeData); -} - -// Breakable Model - -// TODO: put this in a header -struct Breakable -{ - uint32 position; - uint32 numVertices; - uint32 numFaces; - uint32 numMaterials; - - float32 *vertices; - float32 *texCoords; - uint8 *colors; - uint16 *faces; - uint16 *matIDs; - char (*texNames)[32]; - char (*maskNames)[32]; - float32 (*surfaceProps)[3]; -}; - -static void* -createBreakableModel(void *object, int32 offset, int32) -{ - *PLUGINOFFSET(uint8*, object, offset) = 0; - return object; -} - -static void* -destroyBreakableModel(void *object, int32 offset, int32) -{ - uint8 *p = *PLUGINOFFSET(uint8*, object, offset); - delete[] p; - return object; -} - -static void -readBreakableModel(Stream *stream, int32, void *object, int32 o, int32) -{ - uint32 header[13]; - uint32 hasBreakable = stream->readU32(); - if(hasBreakable == 0) - return; - stream->read(header, 13*4); - uint32 size = header[1]*(12+8+4) + header[5]*(6+2) + - header[8]*(32+32+12); - uint8 *p = new uint8[sizeof(Breakable)+size]; - Breakable *breakable = (Breakable*)p; - *PLUGINOFFSET(Breakable*, object, o) = breakable; - breakable->position = header[0]; - breakable->numVertices = header[1]; - breakable->numFaces = header[5]; - breakable->numMaterials = header[8]; - p += sizeof(Breakable); - stream->read(p, size); - breakable->vertices = (float*)p; - p += breakable->numVertices*12; - breakable->texCoords = (float*)p; - p += breakable->numVertices*8; - breakable->colors = (uint8*)p; - p += breakable->numVertices*4; - breakable->faces = (uint16*)p; - p += breakable->numFaces*6; - breakable->matIDs = (uint16*)p; - p += breakable->numFaces*2; - breakable->texNames = (char(*)[32])p; - p += breakable->numMaterials*32; - breakable->maskNames = (char(*)[32])p; - p += breakable->numMaterials*32; - breakable->surfaceProps = (float32(*)[3])p; -} - -static void -writeBreakableModel(Stream *stream, int32, void *object, int32 o, int32) -{ - uint32 header[13]; - Breakable *breakable = *PLUGINOFFSET(Breakable*, object, o); - uint8 *p = (uint8*)breakable; - if(breakable == NULL){ - stream->writeU32(0); - return; - } - stream->writeU32(1); - memset((char*)header, 0, 13*4); - header[0] = breakable->position; - header[1] = breakable->numVertices; - header[5] = breakable->numFaces; - header[8] = breakable->numMaterials; - stream->write(header, 13*4); - p += sizeof(Breakable); - stream->write(p, breakable->numVertices*(12+8+4) + - breakable->numFaces*(6+2) + - breakable->numMaterials*(32+32+12)); -} - -static int32 -getSizeBreakableModel(void *object, int32 offset, int32) -{ - Breakable *breakable = *PLUGINOFFSET(Breakable*, object, offset); - if(breakable == NULL) - return 4; - return 56 + breakable->numVertices*(12+8+4) + - breakable->numFaces*(6+2) + - breakable->numMaterials*(32+32+12); -} - -void -registerBreakableModelPlugin(void) -{ - Geometry::registerPlugin(sizeof(Breakable*), ID_BREAKABLE, - createBreakableModel, - destroyBreakableModel, NULL); - Geometry::registerPluginStream(ID_BREAKABLE, - (StreamRead)readBreakableModel, - (StreamWrite)writeBreakableModel, - (StreamGetSize)getSizeBreakableModel); -} diff --git a/src/ps2.cpp b/src/ps2.cpp index 576de52..9e959fa 100644 --- a/src/ps2.cpp +++ b/src/ps2.cpp @@ -53,6 +53,7 @@ ReadNativeData(Stream *stream, int32, void *object, int32, int32) assert(a % 0x10 == 0); #endif stream->read(instance->data, instance->dataSize); +// sizedebug(instance); } } @@ -94,7 +95,7 @@ GetSizeNativeData(void *object, int32, int32) } void -registerNativeDataPlugin(void) +RegisterNativeDataPlugin(void) { Geometry::registerPlugin(0, ID_NATIVEDATA, NULL, DestroyNativeData, NULL); @@ -180,5 +181,131 @@ unfixDmaOffsets(InstanceData *inst) #endif } +// ADC + +static void* +createADC(void *object, int32 offset, int32) +{ + ADCData *adc = PLUGINOFFSET(ADCData, object, offset); + adc->adcFormatted = 0; + return object; +} + +static void* +copyADC(void *dst, void *src, int32 offset, int32) +{ + ADCData *dstadc = PLUGINOFFSET(ADCData, dst, offset); + ADCData *srcadc = PLUGINOFFSET(ADCData, src, offset); + dstadc->adcFormatted = srcadc->adcFormatted; + return dst; +} + +static void +readADC(Stream *stream, int32, void *object, int32 offset, int32) +{ + ADCData *adc = PLUGINOFFSET(ADCData, object, offset); + stream->seek(12); + uint32 x = stream->readU32(); + assert(x == 0); + adc->adcFormatted = 1; +} + +static void +writeADC(Stream *stream, int32, void *, int32, int32) +{ + WriteChunkHeader(stream, ID_ADC, 4); + stream->writeI32(0); +} + +static int32 +getSizeADC(void *object, int32 offset, int32) +{ + ADCData *adc = PLUGINOFFSET(ADCData, object, offset); + return adc->adcFormatted ? 16 : -1; +} + +void +RegisterADCPlugin(void) +{ + Geometry::registerPlugin(sizeof(ADCData), ID_ADC, + createADC, NULL, copyADC); + Geometry::registerPluginStream(ID_ADC, + (StreamRead)readADC, + (StreamWrite)writeADC, + (StreamGetSize)getSizeADC); +} + + +// misc stuff + +/* Function to specifically walk geometry chains */ +void +walkDMA(InstanceData *inst, void (*f)(uint32 *data, int32 size)) +{ + if(inst->arePointersFixed == 2) + return; + uint32 *base = (uint32*)inst->data; + uint32 *tag = (uint32*)inst->data; + for(;;){ + switch(tag[0]&0x70000000){ + // DMAcnt + case 0x10000000: + f(tag+2, 2+(tag[0]&0xFFFF)*4); + tag += (1+(tag[0]&0xFFFF))*4; + break; + + // DMAref + case 0x3000000: + f(base + tag[1]*4, (tag[0]&0xFFFF)*4); + tag += 4; + break; + + // DMAret + case 0x60000000: + f(tag+2, 2+(tag[0]&0xFFFF)*4); + return; + } + } +} + +void +sizedebug(InstanceData *inst) +{ + if(inst->arePointersFixed == 2) + return; + uint32 *base = (uint32*)inst->data; + uint32 *tag = (uint32*)inst->data; + uint32 *last = NULL; + for(;;){ + switch(tag[0]&0x70000000){ + // DMAcnt + case 0x10000000: + tag += (1+(tag[0]&0xFFFF))*4; + break; + + // DMAref + case 0x30000000: + last = base + tag[1]*4 + (tag[0]&0xFFFF)*4; + tag += 4; + break; + + // DMAret + case 0x60000000: + tag += (1+(tag[0]&0xFFFF))*4; + uint32 diff; + if(!last) + diff = (uint8*)tag - (uint8*)base; + else + diff = (uint8*)last - (uint8*)base; + printf("%x %x %x\n", inst->dataSize-diff, diff, inst->dataSize); + return; + + default: + printf("unkown DMAtag: %X %X\n", tag[0], tag[1]); + break; + } + } +} + } } diff --git a/src/rwbase.h b/src/rwbase.h index 18005ab..e77bb3e 100644 --- a/src/rwbase.h +++ b/src/rwbase.h @@ -104,10 +104,8 @@ enum PluginID ID_RIGHTTORENDER = 0x1F, ID_UVANIMDICT = 0x2B, + ID_ADC = 0x134, ID_NATIVEDATA = 0x510, - - ID_EXTRACOLORS = 0x253f2f9, - ID_BREAKABLE = 0x253f2fd }; extern int Version; diff --git a/src/rwobjects.h b/src/rwobjects.h index 016317e..35ac4ca 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -225,9 +225,7 @@ private: void frameListStreamWrite(Stream *stream, Frame **flp, int32 nf); }; -} +void RegisterMeshPlugin(void); +void RegisterNativeDataPlugin(void); -void registerNodeNamePlugin(void); -void registerMeshPlugin(void); -void registerNativeDataPlugin(void); -void registerBreakableModelPlugin(void); +} diff --git a/src/rwps2.h b/src/rwps2.h index 81d50e8..59f8cc0 100644 --- a/src/rwps2.h +++ b/src/rwps2.h @@ -23,11 +23,26 @@ void *DestroyNativeData(void *object, int32, int32); void ReadNativeData(Stream *stream, int32 len, void *object, int32, int32); void WriteNativeData(Stream *stream, int32 len, void *object, int32, int32); int32 GetSizeNativeData(void *object, int32, int32); -void registerNativeDataPlugin(void); +void RegisterNativeDataPlugin(void); + +void walkDMA(InstanceData *inst, void (*f)(uint32 *data, int32 size)); +void sizedebug(InstanceData *inst); // only RW_PS2 void fixDmaOffsets(InstanceData *inst); void unfixDmaOffsets(InstanceData *inst); +// ADC plugin + +// The plugin is a little crippled due to lack of documentation + +struct ADCData +{ + // only information we can get from GTA DFFs :/ + uint32 adcFormatted; +}; + +void RegisterADCPlugin(void); + } }