From 544660d8b3d08ec3493ff1ed82c0737f8098ccf6 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Fri, 17 Aug 2012 01:46:37 +0200 Subject: [PATCH] Added: #1440 NeL IStream interface to gsflib with max specific features --HG-- branch : build_pipeline_v3 --- .../tools/pipeline/max_dump/CMakeLists.txt | 1 + code/nel/tools/pipeline/max_dump/info.txt | 83 +++++++++ code/nel/tools/pipeline/max_dump/main.cpp | 59 ++++++- .../pipeline/max_dump/storage_stream.cpp | 159 ++++++++++++++++++ .../tools/pipeline/max_dump/storage_stream.h | 120 +++++++++++++ 5 files changed, 420 insertions(+), 2 deletions(-) create mode 100644 code/nel/tools/pipeline/max_dump/storage_stream.cpp create mode 100644 code/nel/tools/pipeline/max_dump/storage_stream.h diff --git a/code/nel/tools/pipeline/max_dump/CMakeLists.txt b/code/nel/tools/pipeline/max_dump/CMakeLists.txt index 0a47ebab2..0a7c617cd 100644 --- a/code/nel/tools/pipeline/max_dump/CMakeLists.txt +++ b/code/nel/tools/pipeline/max_dump/CMakeLists.txt @@ -25,6 +25,7 @@ ADD_EXECUTABLE(pipeline_max_dump TARGET_LINK_LIBRARIES(pipeline_max_dump ${LIBGSF_LIBRARIES} ${GLIB2_LIBRARIES} + nelmisc ) NL_DEFAULT_PROPS(pipeline_max_dump "NeL, Tools, Pipeline: Max Dump (Temporary Tool)") diff --git a/code/nel/tools/pipeline/max_dump/info.txt b/code/nel/tools/pipeline/max_dump/info.txt index 02e07b67d..4b782db3a 100644 --- a/code/nel/tools/pipeline/max_dump/info.txt +++ b/code/nel/tools/pipeline/max_dump/info.txt @@ -65,6 +65,89 @@ VideoPostQueue +Pipeline Max Dump (Temporary Tool) +/srv/work/database/interfaces/anims_max/cp_fy_hof_species.max +DllDirectory +CHUNK ID: 8248, SIZE: 112, CONTAINER: 1 + CHUNK ID: 8249, SIZE: 80, CONTAINER: 0 + UTF16: Default materials and textures (Kinetix) + SKIPPED: 0 + CHUNK ID: 8247, SIZE: 20, CONTAINER: 0 + UTF16: mtlgen.dlt + SKIPPED: 0 +SKIPPED: 0 +CHUNK ID: 8248, SIZE: 108, CONTAINER: 1 + CHUNK ID: 8249, SIZE: 82, CONTAINER: 0 + UTF16: Standard materials and textures (Kinetix) + SKIPPED: 0 + CHUNK ID: 8247, SIZE: 14, CONTAINER: 0 + UTF16: mtl.dlt + SKIPPED: 0 +SKIPPED: 0 +CHUNK ID: 8248, SIZE: 90, CONTAINER: 1 + CHUNK ID: 8249, SIZE: 54, CONTAINER: 0 + UTF16: Standard samplers (Kinetix) + SKIPPED: 0 + CHUNK ID: 8247, SIZE: 24, CONTAINER: 0 + UTF16: samplers.dlh + SKIPPED: 0 +SKIPPED: 0 +CHUNK ID: 8248, SIZE: 88, CONTAINER: 1 + CHUNK ID: 8249, SIZE: 60, CONTAINER: 0 + UTF16: Standard controllers (Kinetix) + SKIPPED: 0 + CHUNK ID: 8247, SIZE: 16, CONTAINER: 0 + UTF16: ctrl.dlc + SKIPPED: 0 +SKIPPED: 0 +CHUNK ID: 8248, SIZE: 128, CONTAINER: 1 + CHUNK ID: 8249, SIZE: 92, CONTAINER: 0 + UTF16: Physique Modifier: a skeletal deformation tool + SKIPPED: 0 + CHUNK ID: 8247, SIZE: 24, CONTAINER: 0 + UTF16: physique.dlm + SKIPPED: 0 +SKIPPED: 0 +CHUNK ID: 8248, SIZE: 94, CONTAINER: 1 + CHUNK ID: 8249, SIZE: 60, CONTAINER: 0 + UTF16: Editable mesh object (Kinetix) + SKIPPED: 0 + CHUNK ID: 8247, SIZE: 22, CONTAINER: 0 + UTF16: update1.dlo + SKIPPED: 0 +SKIPPED: 0 +CHUNK ID: 8248, SIZE: 84, CONTAINER: 1 + CHUNK ID: 8249, SIZE: 54, CONTAINER: 0 + UTF16: BIPED.DLC: Biped Controller + SKIPPED: 0 + CHUNK ID: 8247, SIZE: 18, CONTAINER: 0 + UTF16: biped.dlc + SKIPPED: 0 +SKIPPED: 0 +CHUNK ID: 8248, SIZE: 260, CONTAINER: 1 + CHUNK ID: 8249, SIZE: 218, CONTAINER: 0 + UTF16: Map extender plug-in --- made by 3DSMax Team - UBI Soft Romania & Daniel Raviart - Ubi Research & Development + SKIPPED: 0 + CHUNK ID: 8247, SIZE: 30, CONTAINER: 0 + UTF16: mapext198m3.dlm + SKIPPED: 0 +SKIPPED: 0 +CHUNK ID: 8248, SIZE: 106, CONTAINER: 1 + CHUNK ID: 8249, SIZE: 74, CONTAINER: 0 + UTF16: Standard pre-filter kernels (Kinetix) + SKIPPED: 0 + CHUNK ID: 8247, SIZE: 20, CONTAINER: 0 + UTF16: kernel.dlk + SKIPPED: 0 +SKIPPED: 0 +CHUNK ID: 8248, SIZE: 98, CONTAINER: 1 + CHUNK ID: 8249, SIZE: 70, CONTAINER: 0 + UTF16: Default scanline renderer (Kinetix) + SKIPPED: 0 + CHUNK ID: 8247, SIZE: 16, CONTAINER: 0 + UTF16: rend.dlr + SKIPPED: 0 +SKIPPED: 0 diff --git a/code/nel/tools/pipeline/max_dump/main.cpp b/code/nel/tools/pipeline/max_dump/main.cpp index 545595065..35d8cacaa 100644 --- a/code/nel/tools/pipeline/max_dump/main.cpp +++ b/code/nel/tools/pipeline/max_dump/main.cpp @@ -9,8 +9,59 @@ #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"; + +inline uint8 cleanChar(uint8 c) +{ + if (c >= 32 && c <= 126) return c; + return 46; +} + +static void dumpData(PIPELINE::CStorageStream *in, const std::string &pad) +{ + sint32 size = in->getChunkSize(); + std::vector buffer; + buffer.resize(size + 2); + in->serialBuffer(&buffer[0], size); + switch (in->getChunkId()) + { + case 8249: // some dll description + case 8247: // some dll name + for (std::vector::size_type i = 0; i < buffer.size() / 2; ++i) + buffer[i] = cleanChar(buffer[i * 2]); + buffer[(buffer.size() / 2) - 1] = 0; + printf("%sUTF16: %s\n", pad.c_str(), &buffer[0]); + break; + default: + for (std::vector::size_type i = 0; i < buffer.size(); ++i) + buffer[i] = cleanChar(buffer[i]); + buffer[buffer.size() - 2] = 0; + printf("%sRAW: %s\n", pad.c_str(), &buffer[0]); + break; + } +} + +static void dumpContainer(PIPELINE::CStorageStream *in, const std::string &pad) +{ + while (in->enterChunk()) + { + printf("%sCHUNK ID: %i, SIZE: %i, CONTAINER: %i\n", pad.c_str(), (sint32)in->getChunkId(), (sint32)in->getChunkSize(), (sint32)in->isChunkContainer()); + if (in->isChunkContainer()) + { + dumpContainer(in, pad + "\t"); + } + else + { + dumpData(in, pad + "\t"); + } + sint32 skipped = in->leaveChunk(); + printf("%sSKIPPED: %i\n", pad.c_str(), skipped); + } +} // int __stdcall WinMain(void *, void *, void *, int) int main(int argc, char **argv) @@ -54,9 +105,13 @@ int main(int argc, char **argv) display_name = g_filename_display_name(filename); g_print("%s\n", display_name); g_free(display_name); + g_print("%s\n", streamname); - GsfInput *input = gsf_infile_child_by_name(infile, "DllDirectory"); - gsf_input_dump(input, 1); // just a regular hex dump of this input stream + 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, ""); + delete instream; g_object_unref(input); g_object_unref(infile); diff --git a/code/nel/tools/pipeline/max_dump/storage_stream.cpp b/code/nel/tools/pipeline/max_dump/storage_stream.cpp new file mode 100644 index 000000000..92d0daecc --- /dev/null +++ b/code/nel/tools/pipeline/max_dump/storage_stream.cpp @@ -0,0 +1,159 @@ +/** + * \file storage_stream.cpp + * \brief CStorageStream + * \date 2012-08-16 22:06GMT + * \author Jan Boon (Kaetemi) + * CStorageStream + */ + +/* + * Copyright (C) 2012 by authors + * + * This file is part of RYZOM CORE PIPELINE. + * RYZOM CORE PIPELINE is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * RYZOM CORE PIPELINE is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with RYZOM CORE PIPELINE. If not, see + * . + */ + +#include +#include "storage_stream.h" + +// STL includes + +// 3rd Party includes +#include + +// NeL includes +// #include + +// Project includes + +using namespace std; +// using namespace NLMISC; + +namespace PIPELINE { + +CStorageStream::CStorageStream(GsfInput *input) : NLMISC::IStream(true), m_Input(input) +{ + m_RootChunk.OffsetBegin = -6; + m_RootChunk.Id = 0; + m_RootChunk.Size = 0x80000000; + m_CurrentChunk = &m_RootChunk; +} + +CStorageStream::~CStorageStream() +{ + +} + +bool CStorageStream::seek(sint32 offset, NLMISC::IStream::TSeekOrigin origin) const +{ + if (m_Input) + { + switch (origin) + { + case begin: + return gsf_input_seek(m_Input, offset, G_SEEK_SET); + case current: + return gsf_input_seek(m_Input, offset, G_SEEK_CUR); + case end: + return gsf_input_seek(m_Input, offset, G_SEEK_END); + } + } + return NLMISC::IStream::seek(offset, origin); +} + +sint32 CStorageStream::getPos() const +{ + if (m_Input) + { + gsf_off_t res = gsf_input_tell(m_Input); + if (res < 2147483647L) // exception when larger + return (sint32)res; + } + return NLMISC::IStream::getPos(); +} + +void CStorageStream::serialBuffer(uint8 *buf, uint len) +{ + if (!len) + return; + if (m_Input) + { + if (!gsf_input_read(m_Input, len, buf)) + throw NLMISC::EStream(); + } + else + { + throw NLMISC::EStream(); + } +} + +void CStorageStream::serialBit(bool &bit) +{ + uint8 var = (uint8)bit; + serial(var); + bit = (bool)var; +} + +bool CStorageStream::eof() +{ + return gsf_input_eof(m_Input); +} + +bool CStorageStream::enterChunk() +{ + // input logic + if (!isChunkContainer()) + return false; + if (endOfChunk()) + return false; + CChunk *chunk = new CChunk(); + chunk->OffsetBegin = CStorageStream::getPos(); + serial(chunk->Id); + serial(chunk->Size); + chunk->Parent = m_CurrentChunk; + { + // temp memleak fix + std::map::iterator it = m_CurrentChunk->Children.find(chunk->Id); + if (it != m_CurrentChunk->Children.end()) + m_CurrentChunk->Children.erase(it); + } + m_CurrentChunk->Children[chunk->Id] = chunk; // assuming there's one child per id... + m_CurrentChunk = chunk; + return true; +} + +sint32 CStorageStream::leaveChunk() +{ + // input logic + sint32 skipped = m_CurrentChunk->endOfChunk() - CStorageStream::getPos(); + if (skipped) + CStorageStream::seek(m_CurrentChunk->endOfChunk(), begin); + m_CurrentChunk = m_CurrentChunk->Parent; + return skipped; +} + +void CStorageStream::buildChunkIndexById() +{ + +} + +void CStorageStream::findChunkById(uint16 id) +{ + +} + +} /* namespace PIPELINE */ + +/* end of file */ diff --git a/code/nel/tools/pipeline/max_dump/storage_stream.h b/code/nel/tools/pipeline/max_dump/storage_stream.h new file mode 100644 index 000000000..2e3149583 --- /dev/null +++ b/code/nel/tools/pipeline/max_dump/storage_stream.h @@ -0,0 +1,120 @@ +/** + * \file storage_stream.h + * \brief CStorageStream + * \date 2012-08-16 22:06GMT + * \author Jan Boon (Kaetemi) + * CStorageStream + */ + +/* + * Copyright (C) 2012 by authors + * + * This file is part of RYZOM CORE PIPELINE. + * RYZOM CORE PIPELINE is free software: you can redistribute it + * and/or modify it under the terms of the GNU Affero General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * RYZOM CORE PIPELINE is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with RYZOM CORE PIPELINE. If not, see + * . + */ + +#ifndef PIPELINE_STORAGE_STREAM_H +#define PIPELINE_STORAGE_STREAM_H +#include + +// STL includes +#include + +// 3rd Party includes +#include + +// NeL includes +#include + +// Project includes + +namespace PIPELINE { + +struct CChunk +{ + CChunk() : Parent(NULL) { } + ~CChunk() + { + for (std::map::iterator it = Children.begin(), end = Children.end(); it != end; ++it) + delete it->second; + Children.clear(); + } + CChunk *Parent; + std::map Children; + + // Where the header starts + sint32 OffsetBegin; + + // Identifier + uint16 Id; + // Size including header size + uint32 Size; + + inline sint32 getSizeWithHeader() { return (sint32)(Size & 0x7FFFFFFF); } + inline sint32 getSize() { return getSizeWithHeader() - 6; } + inline bool isContainer() { return (Size & 0x80000000) == 0x80000000; } + inline sint32 endOfChunk() { return OffsetBegin + getSizeWithHeader(); } + inline sint32 getDataBegin() { return OffsetBegin + 6; } +}; + +/** + * \brief CStorageStream + * \date 2012-08-16 22:06GMT + * \author Jan Boon (Kaetemi) + * CStorageStream + */ +class CStorageStream : public NLMISC::IStream +{ +public: + CStorageStream(GsfInput *input); + virtual ~CStorageStream(); + + virtual bool seek(sint32 offset, TSeekOrigin origin) const; + virtual sint32 getPos() const; + // virtual std::string getStreamName() const; // char const * gsf_input_name (GsfInput *input); + virtual void serialBuffer(uint8 *buf, uint len); + virtual void serialBit(bool &bit); + + bool eof(); + + // Returns true if there's another chunk, false if no more chunks in this container or if the current chunk is not a container + bool enterChunk(); + // Returns the number of skipped bytes + sint32 leaveChunk(); + + inline uint16 getChunkId() { return m_CurrentChunk->Id; } + inline sint32 getChunkSize() { return m_CurrentChunk->getSize(); } + inline bool isChunkContainer() { return m_CurrentChunk->isContainer(); } + inline bool endOfChunk() { return m_CurrentChunk == &m_RootChunk ? eof() : CStorageStream::getPos() >= m_CurrentChunk->endOfChunk(); } + + void buildChunkIndexById(); + void findChunkById(uint16 id); + +private: + GsfInput *m_Input; + CChunk m_RootChunk; + CChunk *m_CurrentChunk; + +/* there exist compressed max files, so maybe we will need this at some point +GsfInput * gsf_input_uncompress (GsfInput *src); +*/ + +}; /* class CStorageStream */ + +} /* namespace PIPELINE */ + +#endif /* #ifndef PIPELINE_STORAGE_STREAM_H */ + +/* end of file */