From cbc31bdb2585f42e35132d062da43055db9eca43 Mon Sep 17 00:00:00 2001 From: Angelo Papenhoff Date: Tue, 30 Dec 2014 17:39:39 +0100 Subject: [PATCH] Implemented rudimentary StreamMemory. --- dffwrite.cpp | 37 +++++++++++++++----- src/plugins.cpp | 19 +++-------- src/ps2.cpp | 43 +++++++++++++++--------- src/rwbase.cpp | 89 +++++++++++++++++++++++++++++++++++++++++++++++++ src/rwbase.h | 21 ++++++++++++ src/rwobjects.h | 1 - src/rwps2.h | 17 ++++++---- 7 files changed, 181 insertions(+), 46 deletions(-) diff --git a/dffwrite.cpp b/dffwrite.cpp index e8a2d03..c8725ea 100644 --- a/dffwrite.cpp +++ b/dffwrite.cpp @@ -3,9 +3,6 @@ #include #include -//#include -//#include -//#include #include #include "rw.h" @@ -21,17 +18,32 @@ main(int argc, char *argv[]) registerNodeNamePlugin(); registerBreakableModelPlugin(); registerNativeDataPlugin(); -// registerNativeDataPS2Plugin(); +// Ps2::registerNativeDataPlugin(); registerMeshPlugin(); Rw::Clump *c; // ifstream in(argv[1], ios::binary); - Rw::StreamFile in; - in.open(argv[1], "rb"); + +// Rw::StreamFile in; +// in.open(argv[1], "rb"); + + FILE *cf = fopen(argv[1], "rb"); + assert(cf != NULL); + fseek(cf, 0, SEEK_END); + Rw::uint32 len = ftell(cf); + fseek(cf, 0, SEEK_SET); + Rw::uint8 *data = new Rw::uint8[len]; + fread(data, len, 1, cf); + fclose(cf); + Rw::StreamMemory in; + in.open(data, len); + Rw::FindChunk(&in, Rw::ID_CLUMP, NULL, NULL); c = Rw::Clump::streamRead(&in); assert(c != NULL); + in.close(); + delete[] data; // Rw::Image *tga = Rw::readTGA("b.tga"); // assert(tga != NULL); @@ -41,10 +53,19 @@ main(int argc, char *argv[]) // Rw::Gl::Instance(c->atomicList[i]); // ofstream out(argv[2], ios::binary); - Rw::StreamFile out; - out.open(argv[2], "wb"); +// Rw::StreamFile out; +// out.open(argv[2], "wb"); + data = new Rw::uint8[256*1024]; + Rw::StreamMemory out; + out.open(data, 0, 256*1024); c->streamWrite(&out); + + cf = fopen(argv[2], "wb"); + assert(cf != NULL); + fwrite(data, out.getLength(), 1, cf); + fclose(cf); out.close(); + delete[] data; delete c; diff --git a/src/plugins.cpp b/src/plugins.cpp index 9894232..f04d96e 100644 --- a/src/plugins.cpp +++ b/src/plugins.cpp @@ -201,7 +201,7 @@ destroyNativeData(void *object, int32 offset, int32 size) if(geometry->instData == NULL) return object; if(geometry->instData->platform == PLATFORM_PS2) - return DestroyNativeDataPS2(object, offset, size); + return Ps2::DestroyNativeData(object, offset, size); if(geometry->instData->platform == PLATFORM_OGL) return Gl::DestroyNativeData(object, offset, size); return object; @@ -223,7 +223,7 @@ readNativeData(Stream *stream, int32 len, void *object, int32 o, int32 s) platform = stream->readU32(); stream->seek(-16); if(platform == PLATFORM_PS2) - ReadNativeDataPS2(stream, len, object, o, s); + Ps2::ReadNativeData(stream, len, object, o, s); else if(platform == PLATFORM_XBOX) stream->seek(len); }else{ @@ -239,7 +239,7 @@ writeNativeData(Stream *stream, int32 len, void *object, int32 o, int32 s) if(geometry->instData == NULL) return; if(geometry->instData->platform == PLATFORM_PS2) - WriteNativeDataPS2(stream, len, object, o, s); + Ps2::WriteNativeData(stream, len, object, o, s); else if(geometry->instData->platform == PLATFORM_OGL) Gl::WriteNativeData(stream, len, object, o, s); } @@ -251,7 +251,7 @@ getSizeNativeData(void *object, int32 offset, int32 size) if(geometry->instData == NULL) return -1; if(geometry->instData->platform == PLATFORM_PS2) - return GetSizeNativeDataPS2(object, offset, size); + return Ps2::GetSizeNativeData(object, offset, size); else if(geometry->instData->platform == PLATFORM_XBOX) return -1; else if(geometry->instData->platform == PLATFORM_OGL) @@ -270,17 +270,6 @@ registerNativeDataPlugin(void) (StreamGetSize)getSizeNativeData); } -void -registerNativeDataPS2Plugin(void) -{ - Geometry::registerPlugin(0, ID_NATIVEDATA, - NULL, DestroyNativeDataPS2, NULL); - Geometry::registerPluginStream(ID_NATIVEDATA, - (StreamRead)ReadNativeDataPS2, - (StreamWrite)WriteNativeDataPS2, - (StreamGetSize)GetSizeNativeDataPS2); -} - // Breakable Model // TODO: put this in a header diff --git a/src/ps2.cpp b/src/ps2.cpp index c485508..753d9e4 100644 --- a/src/ps2.cpp +++ b/src/ps2.cpp @@ -13,14 +13,14 @@ using namespace std; namespace Rw { +namespace Ps2 { void* -DestroyNativeDataPS2(void *object, int32, int32) +DestroyNativeData(void *object, int32, int32) { Geometry *geometry = (Geometry*)object; assert(geometry->instData->platform == PLATFORM_PS2); - PS2InstanceDataHeader *header = - (PS2InstanceDataHeader*)geometry->instData; + InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData; for(uint32 i = 0; i < header->numMeshes; i++) delete[] header->instanceMeshes[i].data; delete[] header->instanceMeshes; @@ -29,40 +29,42 @@ DestroyNativeDataPS2(void *object, int32, int32) } void -ReadNativeDataPS2(Stream *stream, int32, void *object, int32, int32) +ReadNativeData(Stream *stream, int32, void *object, int32, int32) { Geometry *geometry = (Geometry*)object; assert(FindChunk(stream, ID_STRUCT, NULL, NULL)); assert(stream->readU32() == PLATFORM_PS2); - PS2InstanceDataHeader *header = new PS2InstanceDataHeader; + InstanceDataHeader *header = new InstanceDataHeader; geometry->instData = header; header->platform = PLATFORM_PS2; assert(geometry->meshHeader != NULL); header->numMeshes = geometry->meshHeader->numMeshes; - header->instanceMeshes = new PS2InstanceData[header->numMeshes]; + header->instanceMeshes = new InstanceData[header->numMeshes]; for(uint32 i = 0; i < header->numMeshes; i++){ - PS2InstanceData *instance = &header->instanceMeshes[i]; + InstanceData *instance = &header->instanceMeshes[i]; uint32 buf[2]; stream->read(buf, 8); instance->dataSize = buf[0]; instance->noRefChain = buf[1]; +// TODO: force alignment instance->data = new uint8[instance->dataSize]; + uint64 a = (uint64)instance->data ; + assert(a % 0x10 == 0); stream->read(instance->data, instance->dataSize); } } void -WriteNativeDataPS2(Stream *stream, int32 len, void *object, int32, int32) +WriteNativeData(Stream *stream, int32 len, void *object, int32, int32) { Geometry *geometry = (Geometry*)object; WriteChunkHeader(stream, ID_STRUCT, len-12); assert(geometry->instData->platform == PLATFORM_PS2); stream->writeU32(PLATFORM_PS2); assert(geometry->instData != NULL); - PS2InstanceDataHeader *header = - (PS2InstanceDataHeader*)geometry->instData; + InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData; for(uint32 i = 0; i < header->numMeshes; i++){ - PS2InstanceData *instance = &header->instanceMeshes[i]; + InstanceData *instance = &header->instanceMeshes[i]; uint32 buf[2]; buf[0] = instance->dataSize; buf[1] = instance->noRefChain; @@ -72,20 +74,31 @@ WriteNativeDataPS2(Stream *stream, int32 len, void *object, int32, int32) } int32 -GetSizeNativeDataPS2(void *object, int32, int32) +GetSizeNativeData(void *object, int32, int32) { Geometry *geometry = (Geometry*)object; int32 size = 16; assert(geometry->instData->platform == PLATFORM_PS2); assert(geometry->instData != NULL); - PS2InstanceDataHeader *header = - (PS2InstanceDataHeader*)geometry->instData; + InstanceDataHeader *header = (InstanceDataHeader*)geometry->instData; for(uint32 i = 0; i < header->numMeshes; i++){ - PS2InstanceData *instance = &header->instanceMeshes[i]; + InstanceData *instance = &header->instanceMeshes[i]; size += 8; size += instance->dataSize; } return size; } +void +registerNativeDataPlugin(void) +{ + Geometry::registerPlugin(0, ID_NATIVEDATA, + NULL, DestroyNativeData, NULL); + Geometry::registerPluginStream(ID_NATIVEDATA, + (StreamRead)ReadNativeData, + (StreamWrite)WriteNativeData, + (StreamGetSize)GetSizeNativeData); +} + +} } diff --git a/src/rwbase.cpp b/src/rwbase.cpp index 1501c64..ee19fb4 100644 --- a/src/rwbase.cpp +++ b/src/rwbase.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -113,6 +114,94 @@ Stream::readF32(void) } + +void +StreamMemory::close(void) +{ +} + +uint32 +StreamMemory::write(const void *data, uint32 len) +{ + if(this->eof()) + return 0; + uint32 l = len; + if(this->position+l > this->length){ + if(this->position+l > this->capacity) + l = this->capacity-this->position; + this->length = this->position+l; + } + memcpy(&this->data[this->position], data, l); + this->position += l; + if(len != l) + this->position = S_EOF; + return l; +} + +uint32 +StreamMemory::read(void *data, uint32 len) +{ + if(this->eof()) + return 0; + uint32 l = len; + if(this->position+l > this->length) + l = this->length-this->position; + memcpy(data, &this->data[this->position], l); + this->position += l; + if(len != l) + this->position = S_EOF; + return l; +} + +void +StreamMemory::seek(int32 offset, int32 whence) +{ + if(whence == 0) + this->position = offset; + else if(whence == 1) + this->position += offset; + else + this->position = this->length-offset; + if(this->position > this->length){ + // TODO: ideally this would depend on the mode + if(this->position > this->capacity) + this->position = S_EOF; + else + this->length = this->position; + } +} + +uint32 +StreamMemory::tell(void) +{ + return this->position; +} + +bool +StreamMemory::eof(void) +{ + return this->position == S_EOF; +} + +StreamMemory* +StreamMemory::open(uint8 *data, uint32 length, uint32 capacity) +{ + this->data = data; + this->capacity = capacity; + this->length = length; + if(this->capacity < this->length) + this->capacity = this->length; + this->position = 0; + return this; +} + +uint32 +StreamMemory::getLength(void) +{ + return this->length; +} + + StreamFile* StreamFile::open(const char *path, const char *mode) { diff --git a/src/rwbase.h b/src/rwbase.h index d45bb5b..18005ab 100644 --- a/src/rwbase.h +++ b/src/rwbase.h @@ -38,6 +38,27 @@ public: float32 readF32(void); }; +class StreamMemory : public Stream +{ + uint8 *data; + uint32 length; + uint32 capacity; + uint32 position; +public: + void close(void); + uint32 write(const void *data, uint32 length); + uint32 read(void *data, uint32 length); + void seek(int32 offset, int32 whence); + uint32 tell(void); + bool eof(void); + StreamMemory *open(uint8 *data, uint32 length, uint32 capacity = 0); + uint32 getLength(void); + + enum { + S_EOF = 0xFFFFFFFF + }; +}; + class StreamFile : public Stream { FILE *file; diff --git a/src/rwobjects.h b/src/rwobjects.h index d9c9f97..016317e 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -230,5 +230,4 @@ private: void registerNodeNamePlugin(void); void registerMeshPlugin(void); void registerNativeDataPlugin(void); -void registerNativeDataPS2Plugin(void); void registerBreakableModelPlugin(void); diff --git a/src/rwps2.h b/src/rwps2.h index 90543ea..5fa41b4 100644 --- a/src/rwps2.h +++ b/src/rwps2.h @@ -1,6 +1,7 @@ namespace Rw { +namespace Ps2 { -struct PS2InstanceData +struct InstanceData { uint32 noRefChain; uint32 dataSize; @@ -8,15 +9,17 @@ struct PS2InstanceData Material *material; }; -struct PS2InstanceDataHeader : InstanceDataHeader +struct InstanceDataHeader : Rw::InstanceDataHeader { uint32 numMeshes; - PS2InstanceData *instanceMeshes; + InstanceData *instanceMeshes; }; -void *DestroyNativeDataPS2(void *object, int32, int32); -void ReadNativeDataPS2(Stream *stream, int32 len, void *object, int32, int32); -void WriteNativeDataPS2(Stream *stream, int32 len, void *object, int32, int32); -int32 GetSizeNativeDataPS2(void *object, int32, int32); +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); } +}