diff --git a/code/nel/tools/pipeline/max_dump/main.cpp b/code/nel/tools/pipeline/max_dump/main.cpp index 35d8cacaa..fa12c1119 100644 --- a/code/nel/tools/pipeline/max_dump/main.cpp +++ b/code/nel/tools/pipeline/max_dump/main.cpp @@ -1,4 +1,7 @@ +#include +#include + #include #include #include @@ -9,11 +12,14 @@ #include #include +#include +#include + #include "storage_stream.h" -static const char *filename = "/srv/work/database/interfaces/anims_max/cp_fy_hof_species.max"; -//static const char *filename = "/home/kaetemi/source/minimax/GE_Acc_MikotoBaniere.max"; -static const char *streamname = "DllDirectory"; +//static const char *filename = "/srv/work/database/interfaces/anims_max/cp_fy_hof_species.max"; +static const char *filename = "/home/kaetemi/source/minimax/GE_Acc_MikotoBaniere.max"; +static const char *streamname = "ClassData"; inline uint8 cleanChar(uint8 c) { @@ -21,6 +27,214 @@ inline uint8 cleanChar(uint8 c) return 46; } +namespace PIPELINE { +namespace MAX { + +struct EStorage : public NLMISC::Exception +{ + EStorage() : NLMISC::Exception("PIPELINE::MAX::EStorage") { } + virtual ~EStorage() throw() { } +}; + +// IStorageObject : exposes serial(CStorageStream *stream) and dump(const std::string &pad) +class IStorageObject +{ +public: + virtual void serial(CStorageStream *stream) = 0; + virtual void dump(const std::string &pad) = 0; +}; + +// CStorageContainer : serializes a container chunk +class CStorageContainer : public std::vector >, public IStorageObject +{ +public: + virtual void serial(CStorageStream *stream); + virtual void dump(const std::string &pad); + + // override in subclasses, call parent if not handled + virtual IStorageObject *serialChunk(CStorageStream *stream); +}; + +// CStorageRaw : serializes raw data, use for unknown data +class CStorageRaw : public std::vector, public IStorageObject +{ +public: + virtual void serial(CStorageStream *stream); + virtual void dump(const std::string &pad); +}; + +// CStorageUCString : serializes an ucstring chunk +class CStorageUCString : public ucstring, public IStorageObject +{ +public: + virtual void serial(CStorageStream *stream); + virtual void dump(const std::string &pad); +}; + +// CStorageString : serializes a string chunk +class CStorageString : public std::string, public IStorageObject +{ +public: + virtual void serial(CStorageStream *stream); + virtual void dump(const std::string &pad); +}; + +template +class CStorageValue : public IStorageObject +{ +public: + T Value; + virtual void serial(CStorageStream *stream); + virtual void dump(const std::string &pad); +}; + +void CStorageContainer::serial(CStorageStream *stream) +{ + if (stream->isReading()) + { + while (stream->enterChunk()) + { + uint16 id = stream->getChunkId(); + IStorageObject *storageObject = serialChunk(stream); + push_back(std::pair(id, storageObject)); + if (stream->leaveChunk()) // bytes were skipped while reading + throw EStorage(); + } + } + else + { + throw EStorage(); + } +} +IStorageObject *CStorageContainer::serialChunk(CStorageStream *stream) +{ + IStorageObject *storageObject = NULL; + if (stream->isChunkContainer()) + { + switch (stream->getChunkId()) + { + case 0x2038: // container with dll desc and name + default: + storageObject = new CStorageContainer(); + break; + } + } + else + { + switch (stream->getChunkId()) + { + case 0x21C0: // unknown 4 byte in the dlldir thing, exists in 2010 but not in 3.x + storageObject = new CStorageValue(); + break; + case 0x2039: // dll description in the dlldir + case 0x2037: // dll name in the dlldir + storageObject = new CStorageUCString(); + break; + default: + storageObject = new CStorageRaw(); + break; + } + } + storageObject->serial(stream); + return storageObject; +} +void CStorageContainer::dump(const std::string &pad) +{ + printf("CStorageContainer - items: %i\n", (sint32)size()); + for (iterator it = this->begin(), end = this->end(); it != end; ++it) + { + std::string padpad = pad + "\t"; + printf("%s[0x%X] ", padpad.c_str(), (sint32)(it->first)); + (it->second)->dump(padpad); + } +} + +void CStorageRaw::serial(CStorageStream *stream) +{ + if (stream->isReading()) + { + resize(stream->getChunkSize()); + stream->serialBuffer(&(*this)[0], size()); + } + else + { + throw EStorage(); + } +} +void CStorageRaw::dump(const std::string &pad) +{ + std::vector buffer; + buffer.resize(size() + 1); + for (std::vector::size_type i = 0; i < size(); ++i) + buffer[i] = cleanChar((*this)[i]); + buffer[buffer.size() - 1] = 0; + printf("CStorageRaw - bytes: %i\n", (sint32)size()); + printf("%s%s\n", pad.c_str(), &buffer[0]); +} + +void CStorageUCString::serial(CStorageStream *stream) +{ + if (stream->isReading()) + { + sint32 size = stream->getChunkSize(); + resize(size / 2); + stream->serialBuffer((uint8 *)&(*this)[0], size); + } + else + { + throw EStorage(); + } +} +void CStorageUCString::dump(const std::string &pad) +{ + std::vector buffer; + buffer.resize(size() + 1); + for (size_type i = 0; i < size(); ++i) + buffer[i] = (*this)[i] > 255 ? 46 : cleanChar((*this)[i]); + buffer[buffer.size() - 1] = 0; + printf("CStorageUCString - length: %i\n", (sint32)size()); + printf("%s%s\n", pad.c_str(), &buffer[0]); +} + +void CStorageString::serial(CStorageStream *stream) +{ + if (stream->isReading()) + { + resize(stream->getChunkSize()); + stream->serialBuffer((uint8 *)(&(*this)[0]), size()); + } + else + { + throw EStorage(); + } +} +void CStorageString::dump(const std::string &pad) +{ + std::vector buffer; + buffer.resize(size() + 1); + for (std::vector::size_type i = 0; i < size(); ++i) + buffer[i] = cleanChar((*this)[i]); + buffer[buffer.size() - 1] = 0; + printf("CStorageString - length: %i\n", (sint32)size()); + printf("%s%s\n", pad.c_str(), &buffer[0]); +} + +template +void CStorageValue::serial(CStorageStream *stream) +{ + stream->serial(Value); +} +template +void CStorageValue::dump(const std::string &pad) +{ + printf("CStorageValue - bytes: %i\n", (sint32)(sizeof(T))); + std::string valstr = NLMISC::toString(Value); + printf("%s%s\n", pad.c_str(), valstr.c_str()); +} + +} +} + static void dumpData(PIPELINE::CStorageStream *in, const std::string &pad) { sint32 size = in->getChunkSize(); @@ -110,7 +324,10 @@ int main(int argc, char **argv) GsfInput *input = gsf_infile_child_by_name(infile, streamname); //gsf_input_dump(input, 1); // just a regular hex dump of this input stream PIPELINE::CStorageStream *instream = new PIPELINE::CStorageStream(input); - dumpContainer(instream, ""); + //dumpContainer(instream, ""); + PIPELINE::MAX::CStorageContainer ctr; + ctr.serial(instream); + ctr.dump(""); delete instream; g_object_unref(input);