update layout
This commit is contained in:
parent
5ae8c8794b
commit
d32ed302d1
File diff suppressed because it is too large
Load Diff
12
Documents/IDAExportAddrConv.py
Normal file
12
Documents/IDAExportAddrConv.py
Normal file
|
@ -0,0 +1,12 @@
|
|||
def Conv(strl: str):
|
||||
if len(strl) & 3 != 0:
|
||||
print('Invalid length!')
|
||||
return
|
||||
|
||||
idaBytes = tuple(strl[i:i+2] for i in range(0, len(strl), 2))
|
||||
for i in range(0, len(idaBytes), 4):
|
||||
print(idaBytes[i+3] + idaBytes[i+2] + idaBytes[i+1] + idaBytes[i])
|
||||
|
||||
while True:
|
||||
Conv(input("data> "))
|
||||
|
|
@ -1,6 +1,24 @@
|
|||
CKFile in VT21: 0xC8, 200, count50; in VT25: 0xE0, 224, count 56
|
||||
lost 24 byte, 6 fields or 2 lists
|
||||
|
||||
|
||||
|
||||
Important CK Class size
|
||||
CKObject no change. 0x14(20)
|
||||
CKSceneObject no change 0x1C(28), share Load/Save with CKObject
|
||||
CKBeObject 0x50(80) count 20
|
||||
|
||||
CKGroup 0x68(104) count 26
|
||||
CKMaterial 0xF0(240) count 90
|
||||
CKTexture 0x94(148) count 52
|
||||
CKMesh 0x104(260) count 65
|
||||
|
||||
CKRenderObject 0x58(88) count 22, share Load/Save with CKBeObject
|
||||
CK3dEntity 0x1A8(424) count 106
|
||||
CK3dObject 0x1A8(424) count 106 same as CK3dEntity
|
||||
|
||||
|
||||
|
||||
m_FileName
|
||||
in VT21 +34, 136
|
||||
in VT25 +31, 124
|
||||
|
|
File diff suppressed because it is too large
Load Diff
38
LibCmo/CKDefines.hpp
Normal file
38
LibCmo/CKDefines.hpp
Normal file
|
@ -0,0 +1,38 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace LibCmo {
|
||||
|
||||
using CKINT = int32_t;
|
||||
using CK_ID = uint32_t;
|
||||
using CKDWORD = uint32_t;
|
||||
using CKWORD = uint16_t;
|
||||
using CKBYTE = uint8_t;
|
||||
using CKBOOL = int32_t;
|
||||
using CKMUTSTRING = char*;
|
||||
using CKSTRING = const char*;
|
||||
|
||||
using XString = std::string;
|
||||
using XBitArray = std::vector<bool>;
|
||||
template<typename T>
|
||||
using XArray = std::vector<T>;
|
||||
using XIntArray = std::vector<int32_t>;
|
||||
template<typename T>
|
||||
using XClassArray = std::vector<T>;
|
||||
//using CKObjectArray = std::vector<CKObject*>;
|
||||
|
||||
|
||||
struct CKGUID {
|
||||
union {
|
||||
struct {
|
||||
CKDWORD d1, d2;
|
||||
};
|
||||
CKDWORD d[2];
|
||||
};
|
||||
CKGUID(CKDWORD gd1 = 0, CKDWORD gd2 = 0) { d[0] = gd1; d[1] = gd2; }
|
||||
};
|
||||
|
||||
|
||||
}
|
|
@ -1,15 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
#include <cinttypes>
|
||||
#include <cstdint>
|
||||
#include <cstdarg>
|
||||
#include <type_traits>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace LibCmo {
|
||||
|
||||
namespace EnumHelper {
|
||||
namespace EnumsHelper {
|
||||
template<typename TEnum>
|
||||
inline TEnum FlagEnumAdd(TEnum e, ...) {
|
||||
TEnum result = e;
|
||||
|
@ -26,23 +24,6 @@ namespace LibCmo {
|
|||
}
|
||||
}
|
||||
|
||||
using CKINT = int32_t;
|
||||
using CK_ID = uint32_t;
|
||||
using CKDWORD = uint32_t;
|
||||
using CKWORD = uint16_t;
|
||||
using CKBOOL = int32_t;
|
||||
using CKMUTSTRING = char*;
|
||||
using CKSTRING = const char*;
|
||||
|
||||
using XString = std::string;
|
||||
using XBitArray = std::vector<bool>;
|
||||
template<typename T>
|
||||
using XArray = std::vector<T>;
|
||||
using XIntArray = std::vector<int32_t>;
|
||||
template<typename T>
|
||||
using XClassArray = std::vector<T>;
|
||||
//using CKObjectArray = std::vector<CKObject*>;
|
||||
|
||||
enum class CK_CLASSID : uint32_t {
|
||||
CKCID_OBJECT = 1,
|
||||
CKCID_PARAMETERIN = 2,
|
||||
|
@ -237,4 +218,3 @@ namespace LibCmo {
|
|||
};
|
||||
|
||||
}
|
||||
|
94
LibCmo/CKFile.cpp
Normal file
94
LibCmo/CKFile.cpp
Normal file
|
@ -0,0 +1,94 @@
|
|||
#include "CKFile.hpp"
|
||||
#include <cstdarg>
|
||||
|
||||
namespace LibCmo {
|
||||
|
||||
|
||||
#pragma region CKMinContext
|
||||
|
||||
CKMinContext::CKMinContext() {
|
||||
|
||||
}
|
||||
CKMinContext::~CKMinContext() {
|
||||
|
||||
}
|
||||
|
||||
void CKMinContext::Printf(CKSTRING fmt, ...) {
|
||||
va_list argptr;
|
||||
va_start(argptr, fmt);
|
||||
vfprintf(stdout, fmt, argptr);
|
||||
va_end(argptr);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region CKBufferParser
|
||||
|
||||
CKBufferParser::CKBufferParser(void* ptr, size_t rsize, bool need_manual_free) :
|
||||
m_MemBegin(static_cast<char*>(ptr)),
|
||||
m_MemPos(0u), m_MemSize(rsize),
|
||||
m_NeedManualFree(need_manual_free) {
|
||||
;
|
||||
}
|
||||
CKBufferParser::~CKBufferParser() {
|
||||
if (this->m_NeedManualFree) delete[](this->m_MemBegin);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region CKFileObject
|
||||
|
||||
LibCmo::CKFileObject::CKFileObject() :
|
||||
Data(nullptr) {
|
||||
;
|
||||
}
|
||||
|
||||
LibCmo::CKFileObject::~CKFileObject() {
|
||||
;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
|
||||
#pragma region ShallowDocument
|
||||
|
||||
LibCmo::CKFileData::ShallowDocument::ShallowDocument() {
|
||||
this->m_IndexByClassId.resize(static_cast<size_t>(CK_CLASSID::CKCID_MAXCLASSID));
|
||||
}
|
||||
|
||||
LibCmo::CKFileData::ShallowDocument::~ShallowDocument() {
|
||||
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region DeepDocument
|
||||
|
||||
LibCmo::CKFileData::DeepDocument::DeepDocument() {
|
||||
this->m_IndexByClassId.resize(static_cast<size_t>(CK_CLASSID::CKCID_MAXCLASSID));
|
||||
}
|
||||
|
||||
LibCmo::CKFileData::DeepDocument::~DeepDocument() {
|
||||
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
|
||||
#pragma region CKFile Misc
|
||||
|
||||
CKFile::CKFile(CKMinContext* ctx) :
|
||||
m_MappedFile(nullptr), m_FileName(),
|
||||
m_MinCtx(ctx) {
|
||||
;
|
||||
}
|
||||
|
||||
CKFile::~CKFile() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
#pragma endregion
|
||||
|
||||
|
||||
}
|
258
LibCmo/CKFile.hpp
Normal file
258
LibCmo/CKFile.hpp
Normal file
|
@ -0,0 +1,258 @@
|
|||
#pragma once
|
||||
|
||||
#include "CKDefines.hpp"
|
||||
#include "CKEnums.hpp"
|
||||
|
||||
#include "VxMemoryMappedFile.hpp"
|
||||
#include "CKStateChunk.hpp"
|
||||
#include "VTObjects.hpp"
|
||||
|
||||
namespace LibCmo {
|
||||
|
||||
class CKMinContext {
|
||||
public:
|
||||
CKMinContext();
|
||||
CKMinContext(const CKMinContext&) = delete;
|
||||
CKMinContext& operator=(const CKMinContext&) = delete;
|
||||
~CKMinContext();
|
||||
|
||||
void Printf(CKSTRING fmt, ...);
|
||||
|
||||
private:
|
||||
|
||||
std::string NameEncoding;
|
||||
std::string TempFolder;
|
||||
};
|
||||
|
||||
class CKBufferParser {
|
||||
private:
|
||||
char* m_MemBegin;
|
||||
size_t m_MemPos;
|
||||
bool m_NeedManualFree;
|
||||
size_t m_MemSize;
|
||||
|
||||
public:
|
||||
CKBufferParser(void* ptr, size_t rsize, bool need_manual_free);
|
||||
CKBufferParser(const CKBufferParser&) = delete;
|
||||
CKBufferParser& operator=(const CKBufferParser&) = delete;
|
||||
~CKBufferParser();
|
||||
|
||||
inline const void* GetPtr(void) { return (this->m_MemBegin + m_MemPos); }
|
||||
inline void Read(void* data, size_t data_size) {
|
||||
memcpy(data, (this->m_MemBegin + m_MemPos), data_size);
|
||||
this->m_MemPos += data_size;
|
||||
}
|
||||
inline void Write(const void* data, size_t data_size) {
|
||||
memcpy((this->m_MemBegin + m_MemPos), data, data_size);
|
||||
this->m_MemPos += data_size;
|
||||
}
|
||||
inline void* GetBase(void) { return this->m_MemBegin; }
|
||||
inline size_t GetSize(void) { return this->m_MemSize; }
|
||||
inline size_t GetCursor(void) { return this->m_MemPos; }
|
||||
inline void MoveCursor(size_t off) { this->m_MemPos += off; }
|
||||
inline void SetCursor(size_t off) { this->m_MemPos = off; }
|
||||
};
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
struct CKRawFileInfo {
|
||||
CKBYTE NeMo[8];
|
||||
CKDWORD Crc;
|
||||
CKDWORD CKVersion;
|
||||
CKDWORD FileVersion;
|
||||
CKDWORD Zero;
|
||||
CKDWORD FileWriteMode;
|
||||
CKDWORD Hdr1PackSize;
|
||||
|
||||
CKDWORD DataPackSize;
|
||||
CKDWORD DataUnPackSize;
|
||||
CKDWORD ManagerCount;
|
||||
CKDWORD ObjectCount;
|
||||
CKDWORD MaxIDSaved;
|
||||
CKDWORD ProductVersion;
|
||||
CKDWORD ProductBuild;
|
||||
CKDWORD Hdr1UnPackSize;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
class CKFileInfo {
|
||||
public:
|
||||
CKFileInfo();
|
||||
CKFileInfo(const CKFileInfo&) = delete;
|
||||
CKFileInfo& operator=(const CKFileInfo&) = delete;
|
||||
~CKFileInfo();
|
||||
|
||||
CKDWORD ProductVersion; // Virtools Version (Dev/Creation). (CK_VIRTOOLS_VERSION)
|
||||
CKDWORD ProductBuild; // Virtools Build Number.
|
||||
CK_FILE_WRITEMODE FileWriteMode; // Options used to save this file. (CK_FILE_WRITEMODE)
|
||||
CKDWORD FileVersion; // Version of file format when file was saved.
|
||||
CKDWORD CKVersion; // Version of CK when file was saved.
|
||||
size_t FileSize; // Size of file in bytes.
|
||||
CKDWORD ObjectCount; // Number of objects stored in the file.
|
||||
CKDWORD ManagerCount; // Number of managers which saved data in the file.
|
||||
CKDWORD MaxIDSaved; // Maximum Object identifier saved
|
||||
CKDWORD Crc; // Crc of data
|
||||
CKDWORD Hdr1PackSize; // Reserved
|
||||
CKDWORD Hdr1UnPackSize; // Reserved
|
||||
CKDWORD DataPackSize; // Reserved
|
||||
CKDWORD DataUnPackSize; // Reserved
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
class CKFileObject {
|
||||
public:
|
||||
CKFileObject();
|
||||
CKFileObject(const CKFileObject&) = delete;
|
||||
CKFileObject& operator=(const CKFileObject&) = delete;
|
||||
~CKFileObject();
|
||||
|
||||
CK_ID ObjectId;
|
||||
CK_CLASSID ObjectCid;
|
||||
std::string Name;
|
||||
CKStateChunk* Data;
|
||||
CKDWORD PostPackSize;
|
||||
CKDWORD PrePackSize;
|
||||
CKDWORD FileIndex;
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
class CKFileManagerData {
|
||||
public:
|
||||
CKFileManagerData();
|
||||
CKFileManagerData(const CKFileManagerData&) = delete;
|
||||
CKFileManagerData& operator=(const CKFileManagerData&) = delete;
|
||||
~CKFileManagerData();
|
||||
|
||||
CKStateChunk* Data;
|
||||
CKGUID Manager;
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
class CKFilePluginDependencies {
|
||||
public:
|
||||
CKFilePluginDependencies();
|
||||
CKFilePluginDependencies(const CKFilePluginDependencies&) = delete;
|
||||
CKFilePluginDependencies& operator=(const CKFilePluginDependencies&) = delete;
|
||||
~CKFilePluginDependencies();
|
||||
|
||||
CK_PLUGIN_TYPE m_PluginCategory;
|
||||
XArray<CKGUID> m_Guids;
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
namespace CKFileData {
|
||||
class ShallowDocument {
|
||||
public:
|
||||
ShallowDocument();
|
||||
ShallowDocument(const ShallowDocument&) = delete;
|
||||
ShallowDocument& operator=(const ShallowDocument&) = delete;
|
||||
~ShallowDocument();
|
||||
|
||||
int32_t m_SaveIDMax;
|
||||
CKFileInfo m_FileInfo;
|
||||
|
||||
XArray<CKFileObject> m_FileObjects;
|
||||
XArray<CKFileManagerData> m_FileManagersData;
|
||||
XClassArray<CKFilePluginDependencies> m_PluginDep;
|
||||
XClassArray<XIntArray> m_IndexByClassId;
|
||||
XClassArray<XString> m_IncludedFiles;
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
class DeepDocument {
|
||||
public:
|
||||
DeepDocument();
|
||||
DeepDocument(const DeepDocument&) = delete;
|
||||
DeepDocument& operator=(const DeepDocument&) = delete;
|
||||
~DeepDocument();
|
||||
|
||||
int32_t m_SaveIDMax;
|
||||
CKFileInfo m_FileInfo;
|
||||
|
||||
XArray<ObjsImpl::CKObject*> m_Objects;
|
||||
XClassArray<XIntArray> m_IndexByClassId;
|
||||
XClassArray<XString> m_IncludedFiles;
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
class HybridDocument {
|
||||
public:
|
||||
HybridDocument();
|
||||
HybridDocument(const HybridDocument&) = delete;
|
||||
HybridDocument& operator=(const HybridDocument&) = delete;
|
||||
~HybridDocument();
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
class CKFile {
|
||||
public:
|
||||
CKFile(CKMinContext* ctx);
|
||||
CKFile(const CKFile&) = delete;
|
||||
CKFile& operator=(const CKFile&) = delete;
|
||||
~CKFile();
|
||||
|
||||
void ClearData(void);
|
||||
|
||||
CKERROR ShallowLoad(CKSTRING u8_filename, CKFileData::ShallowDocument** out_doc);
|
||||
CKERROR DeepLoad(CKSTRING u8_filename, CKFileData::DeepDocument** out_doc);
|
||||
|
||||
CKERROR ShallowSave(CKSTRING u8_filename, CKFileData::ShallowDocument* in_doc);
|
||||
CKERROR DeepSave(CKSTRING u8_filename, CKFileData::DeepDocument* out_doc);
|
||||
CKERROR HybridSave(CKSTRING u8_filename, CKFileData::HybridDocument* out_doc);
|
||||
|
||||
CKERROR DestroyDocument(CKFileData::ShallowDocument* in_doc);
|
||||
CKERROR DestroyDocument(CKFileData::DeepDocument* in_doc);
|
||||
CKERROR DestroyDocument(CKFileData::HybridDocument* in_doc);
|
||||
|
||||
//CKERROR Load(CKSTRING u8_filename, /*CKObjectArray list, */ CK_LOAD_FLAGS flags);
|
||||
//CKERROR OpenFile(CKSTRING u8_filename, CK_LOAD_FLAGS flags);
|
||||
//CKERROR OpenMemory(void* MemoryBuffer, size_t BufferSize, CK_LOAD_FLAGS Flags);
|
||||
//CKERROR ReadFileHeaders(CKBufferParser** ParserPtr);
|
||||
//CKERROR ReadFileData(CKBufferParser** ParserPtr);
|
||||
//CKERROR LoadFileData(void/*CKObjectArray list*/);
|
||||
//CKERROR FinishLoading(/*CKObjectArray list, */CK_LOAD_FLAGS flags);
|
||||
|
||||
//int32_t m_SaveIDMax;
|
||||
//XArray<CKFileObject> m_FileObject;
|
||||
//XArray<CKFileManagerData> m_ManagersData;
|
||||
//XClassArray<CKFilePluginDependencies> m_PluginDep;
|
||||
//XClassArray<XIntArray> m_IndexByClassId;
|
||||
//XClassArray<XString> m_IncludedFiles;
|
||||
|
||||
//CKFileInfo m_FileInfo;
|
||||
|
||||
//CK_LOAD_FLAGS m_Flags;
|
||||
|
||||
|
||||
//bool m_ReadFileDataDone;
|
||||
|
||||
private:
|
||||
// reader function and variables
|
||||
CKERROR PrepareLoad(CKSTRING u8_filename);
|
||||
CKERROR ReadFileHeader(CKBufferParser* ParserPtr);
|
||||
CKERROR ReadFileData(CKBufferParser* ParserPtr);
|
||||
|
||||
CKFileData::ShallowDocument* m_ShallowDoc;
|
||||
CKFileData::DeepDocument* m_DeepDoc;
|
||||
|
||||
// writer function and varibales
|
||||
|
||||
// shared function and variables
|
||||
std::string m_FileName;
|
||||
VxMemoryMappedFile* m_MappedFile;
|
||||
|
||||
CKMinContext* m_MinCtx;
|
||||
};
|
||||
|
||||
}
|
684
LibCmo/CKFileReader.cpp
Normal file
684
LibCmo/CKFileReader.cpp
Normal file
|
@ -0,0 +1,684 @@
|
|||
#include "CKFile.hpp"
|
||||
#include "CKGlobals.hpp"
|
||||
#include <memory>
|
||||
|
||||
namespace LibCmo {
|
||||
|
||||
/*
|
||||
* NOTE:
|
||||
* We onlt support read Virtools file with FileVersion >= 7.
|
||||
* The file with FileVersion < 7 is older than NeMo 1.0 (CK 1.1).
|
||||
* No need to support them.
|
||||
*/
|
||||
|
||||
CKERROR CKFile::PrepareLoad(CKSTRING u8_filename) {
|
||||
// assign file name
|
||||
this->m_FileName = u8_filename;
|
||||
// create mapped file
|
||||
this->m_MappedFile = new(std::nothrow) VxMemoryMappedFile(this->m_FileName.c_str());
|
||||
if (this->m_MappedFile == nullptr) {
|
||||
this->m_MinCtx->Printf("Out of memory when creating Memory File.");
|
||||
return CKERROR::CKERR_OUTOFMEMORY;
|
||||
}
|
||||
if (!this->m_MappedFile->IsValid()) {
|
||||
this->m_MinCtx->Printf("Fail to create Memory File for \"%s\".", this->m_FileName.c_str());
|
||||
return CKERROR::CKERR_INVALIDFILE;
|
||||
}
|
||||
|
||||
return CKERROR::CKERR_OK;
|
||||
}
|
||||
|
||||
CKERROR CKFile::ShallowLoad(CKSTRING u8_filename, CKFileData::ShallowDocument** out_doc) {
|
||||
// check file and open memory
|
||||
if (u8_filename == nullptr) return CKERROR::CKERR_INVALIDPARAMETER;
|
||||
CKERROR err = PrepareLoad(u8_filename);
|
||||
if (err != CKERROR::CKERR_OK) return err;
|
||||
|
||||
// create document
|
||||
this->m_ShallowDoc = new(std::nothrow) CKFileData::ShallowDocument();
|
||||
if (this->m_ShallowDoc == nullptr) return CKERROR::CKERR_OUTOFMEMORY;
|
||||
|
||||
// create buffer and start loading
|
||||
CKBufferParser parser(this->m_MappedFile->GetBase(), this->m_MappedFile->GetFileSize(), false);
|
||||
err = this->ReadFileHeader(&parser);
|
||||
if (err != CKERROR::CKERR_OK) return err;
|
||||
err = this->ReadFileData(&parser);
|
||||
if (err != CKERROR::CKERR_OK) return err;
|
||||
|
||||
// free all data
|
||||
this->ClearData();
|
||||
return CKERROR::CKERR_OK;
|
||||
}
|
||||
|
||||
CKERROR CKFile::ReadFileHeader(CKBufferParser* ParserPtr) {
|
||||
std::unique_ptr<CKBufferParser> parser(new(std::nothrow) CKBufferParser(ParserPtr->GetBase(), ParserPtr->GetSize(), false));
|
||||
|
||||
// ========== read header ==========
|
||||
// check header size
|
||||
if (parser->GetSize() < sizeof(CKRawFileInfo)) return CKERROR::CKERR_INVALIDFILE;
|
||||
if (memcmp(parser->GetPtr(), "Nemo Fi", sizeof(CKRawFileInfo::NeMo))) return CKERROR::CKERR_INVALIDFILE;
|
||||
// read header
|
||||
CKRawFileInfo rawHeader;
|
||||
parser->Read(&rawHeader, sizeof(CKRawFileInfo));
|
||||
|
||||
// ========== header checker ==========
|
||||
// check zero flag?
|
||||
if (rawHeader.Zero) return CKERROR::CKERR_INVALIDFILE;
|
||||
// check file version
|
||||
if (rawHeader.FileVersion > 9 || rawHeader.FileVersion < 7) return CKERROR::CKERR_OBSOLETEVIRTOOLS;
|
||||
// force reset too big product ver?
|
||||
if (rawHeader.ProductVersion >= 12u) {
|
||||
rawHeader.ProductVersion = 0u;
|
||||
rawHeader.ProductBuild = 0x01010000;
|
||||
}
|
||||
|
||||
// ========== assign value ==========
|
||||
this->m_ShallowDoc->m_FileInfo.ProductVersion = rawHeader.ProductVersion;
|
||||
this->m_ShallowDoc->m_FileInfo.ProductBuild = rawHeader.ProductBuild;
|
||||
this->m_ShallowDoc->m_FileInfo.FileWriteMode = static_cast<CK_FILE_WRITEMODE>(rawHeader.FileWriteMode);
|
||||
this->m_ShallowDoc->m_FileInfo.CKVersion = rawHeader.CKVersion;
|
||||
this->m_ShallowDoc->m_FileInfo.FileVersion = rawHeader.FileVersion;
|
||||
this->m_ShallowDoc->m_FileInfo.FileSize = parser->GetSize();
|
||||
this->m_ShallowDoc->m_FileInfo.ManagerCount = rawHeader.ManagerCount;
|
||||
this->m_ShallowDoc->m_FileInfo.ObjectCount = rawHeader.ObjectCount;
|
||||
this->m_ShallowDoc->m_FileInfo.MaxIDSaved = rawHeader.MaxIDSaved;
|
||||
this->m_ShallowDoc->m_FileInfo.Hdr1PackSize = rawHeader.FileVersion >= 8 ? rawHeader.Hdr1PackSize : 0u;
|
||||
this->m_ShallowDoc->m_FileInfo.Hdr1UnPackSize = rawHeader.FileVersion >= 8 ? rawHeader.Hdr1UnPackSize : 0u;
|
||||
this->m_ShallowDoc->m_FileInfo.DataPackSize = rawHeader.DataPackSize;
|
||||
this->m_ShallowDoc->m_FileInfo.DataUnPackSize = rawHeader.DataUnPackSize;
|
||||
this->m_ShallowDoc->m_FileInfo.Crc = rawHeader.Crc;
|
||||
|
||||
// ========== crc and body unpacker ==========
|
||||
if (this->m_ShallowDoc->m_FileInfo.FileVersion >= 8) {
|
||||
// crc checker for file ver >= 8
|
||||
// reset crc field of header
|
||||
rawHeader.Crc = 0u;
|
||||
|
||||
// compute crc
|
||||
CKDWORD gotten_crc = CKComputeDataCRC(&rawHeader, sizeof(CKRawFileInfo), 0u);
|
||||
parser->SetCursor(sizeof(CKRawFileInfo));
|
||||
gotten_crc = CKComputeDataCRC(parser->GetPtr(), this->m_ShallowDoc->m_FileInfo.Hdr1PackSize, gotten_crc);
|
||||
parser->MoveCursor(this->m_ShallowDoc->m_FileInfo.Hdr1PackSize);
|
||||
gotten_crc = CKComputeDataCRC(parser->GetPtr(), this->m_ShallowDoc->m_FileInfo.DataPackSize, gotten_crc);
|
||||
|
||||
if (gotten_crc != this->m_ShallowDoc->m_FileInfo.Crc) return CKERROR::CKERR_FILECRCERROR;
|
||||
|
||||
// reset cursor
|
||||
parser->SetCursor(sizeof(CKRawFileInfo));
|
||||
|
||||
// compare size to decide wheher use compress feature
|
||||
void* decomp_buffer = CKUnPackData(this->m_ShallowDoc->m_FileInfo.Hdr1UnPackSize, parser->GetPtr(), this->m_ShallowDoc->m_FileInfo.Hdr1PackSize);
|
||||
if (decomp_buffer != nullptr) {
|
||||
parser = std::unique_ptr<CKBufferParser>(new(std::nothrow) CKBufferParser(decomp_buffer, this->m_ShallowDoc->m_FileInfo.Hdr1UnPackSize, true));
|
||||
if (parser == nullptr) {
|
||||
delete[] decomp_buffer;
|
||||
return CKERROR::CKERR_OUTOFMEMORY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ========== object list read ==========
|
||||
// file ver >= 7 have this features
|
||||
if (this->m_ShallowDoc->m_FileInfo.FileVersion >= 7) {
|
||||
// apply max id saved
|
||||
this->m_ShallowDoc->m_SaveIDMax = this->m_ShallowDoc->m_FileInfo.MaxIDSaved;
|
||||
// resize
|
||||
this->m_ShallowDoc->m_FileObjects.resize(this->m_ShallowDoc->m_FileInfo.ObjectCount);
|
||||
|
||||
// read data
|
||||
for (auto& fileobj : this->m_ShallowDoc->m_FileObjects) {
|
||||
// read basic fields
|
||||
parser->Read(&(fileobj.ObjectId), sizeof(CK_ID));
|
||||
parser->Read(&(fileobj.ObjectCid), sizeof(CK_CLASSID));
|
||||
parser->Read(&(fileobj.FileIndex), sizeof(CKDWORD));
|
||||
|
||||
CKDWORD namelen;
|
||||
parser->Read(&namelen, sizeof(CKDWORD));
|
||||
if (namelen != 0) {
|
||||
fileobj.Name.resize(namelen);
|
||||
parser->Read(fileobj.Name.data(), namelen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ========== dep list read ==========
|
||||
// file ver >= 8 have this feature
|
||||
bool noDepLost = true;
|
||||
if (this->m_ShallowDoc->m_FileInfo.FileVersion >= 8) {
|
||||
// get size and resize
|
||||
CKDWORD depSize;
|
||||
parser->Read(&depSize, sizeof(CKDWORD));
|
||||
this->m_ShallowDoc->m_PluginDep.resize(depSize);
|
||||
|
||||
CKDWORD guid_size;
|
||||
for (auto& dep : this->m_ShallowDoc->m_PluginDep) {
|
||||
// read category
|
||||
parser->Read(&(dep.m_PluginCategory), sizeof(CK_PLUGIN_TYPE));
|
||||
// get size and resize
|
||||
parser->Read(&guid_size, sizeof(CKDWORD));
|
||||
dep.m_Guids.resize(guid_size);
|
||||
// read data
|
||||
if (guid_size != 0) {
|
||||
parser->Read(dep.m_Guids.data(), sizeof(CKGUID) * guid_size);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ========== included file list read ==========
|
||||
// file ver >= 8 have this feature
|
||||
if (this->m_ShallowDoc->m_FileInfo.FileVersion >= 8) {
|
||||
// MARK: i don't knwo what is this!
|
||||
int32_t hasIncludedFile;
|
||||
parser->Read(&hasIncludedFile, sizeof(int32_t));
|
||||
|
||||
if (hasIncludedFile > 0) {
|
||||
// read included file size and resize
|
||||
CKDWORD includedFileCount;
|
||||
parser->Read(&includedFileCount, sizeof(CKDWORD));
|
||||
this->m_ShallowDoc->m_IncludedFiles.resize(includedFileCount);
|
||||
|
||||
hasIncludedFile -= 4;
|
||||
}
|
||||
|
||||
// backward pos
|
||||
parser->SetCursor(hasIncludedFile);
|
||||
}
|
||||
|
||||
return CKERROR::CKERR_OK;
|
||||
}
|
||||
|
||||
CKERROR CKFile::ReadFileData(CKBufferParser* ParserPtr) {
|
||||
return CKERROR();
|
||||
}
|
||||
|
||||
//CKERROR CKFile::Load(CKSTRING u8_filename, /*CKObjectArray list, */ CK_LOAD_FLAGS flags) {
|
||||
// CKERROR result = this->OpenFile(u8_filename, flags);
|
||||
// if (result == CKERROR::CKERR_OK || result == CKERROR::CKERR_PLUGINSMISSING) {
|
||||
// result = this->LoadFileData();
|
||||
// }
|
||||
|
||||
// return result;
|
||||
//}
|
||||
|
||||
//CKERROR CKFile::OpenFile(CKSTRING u8_filename, CK_LOAD_FLAGS flags) {
|
||||
// this->ClearData();
|
||||
// if (u8_filename == nullptr) return CKERROR::CKERR_INVALIDPARAMETER;
|
||||
|
||||
// this->m_FileName = u8_filename;
|
||||
// this->m_MappedFile = new(std::nothrow) VxMemoryMappedFile(this->m_FileName.c_str());
|
||||
// if (this->m_MappedFile == nullptr) return CKERROR::CKERR_OUTOFMEMORY;
|
||||
// if (!this->m_MappedFile->IsValid()) return CKERROR::CKERR_INVALIDFILE;
|
||||
|
||||
// // MARK: CKContext::SetLastCmoLoaded
|
||||
// return this->OpenMemory(this->m_MappedFile->GetBase(), this->m_MappedFile->GetFileSize(), flags);
|
||||
//}
|
||||
|
||||
//CKERROR CKFile::OpenMemory(void* MemoryBuffer, size_t BufferSize, CK_LOAD_FLAGS Flags) {
|
||||
// if (MemoryBuffer == nullptr) return CKERROR::CKERR_INVALIDPARAMETER;
|
||||
// // compare magic words
|
||||
// if (BufferSize < 0x20 || memcmp(MemoryBuffer, "Nemo", 4u)) return CKERROR::CKERR_INVALIDFILE;
|
||||
|
||||
// this->m_Parser = new(std::nothrow) CKBufferParser(MemoryBuffer, BufferSize, false);
|
||||
// if (this->m_Parser == nullptr) return CKERROR::CKERR_OUTOFMEMORY;
|
||||
// // MARK: eliminate check of m_Parser->m_ReaderBegin
|
||||
|
||||
// // MARK: dword_2405F6C0 = 0;
|
||||
// this->m_Flags = Flags;
|
||||
// this->m_IndexByClassId.resize(static_cast<size_t>(CK_CLASSID::CKCID_MAXCLASSID));
|
||||
// return this->ReadFileHeaders(&(this->m_Parser));
|
||||
//}
|
||||
|
||||
//CKERROR CKFile::ReadFileHeaders(CKBufferParser** ParserPtr) {
|
||||
// CKBufferParser* parser = *ParserPtr;
|
||||
// this->m_IncludedFiles.clear();
|
||||
|
||||
// // ========== read header1 ==========
|
||||
// CKDWORD fhdr1[8];
|
||||
// CKDWORD fhdr2[8];
|
||||
// if (parser->GetSize() < sizeof(fhdr1)) return CKERROR::CKERR_INVALIDFILE;
|
||||
// parser->Read(fhdr1, sizeof(fhdr1));
|
||||
|
||||
// if (fhdr1[5]) { // it seems that there is a ZERO checker?
|
||||
// memset(fhdr1, 0, sizeof(fhdr1));
|
||||
// }
|
||||
// // check outdated
|
||||
// if (fhdr1[4] > 9) return CKERROR::CKERR_OBSOLETEVIRTOOLS;
|
||||
|
||||
// // ========== read header2 ==========
|
||||
// // file ver < 5 do not have second header
|
||||
// if (fhdr1[4] < 5) {
|
||||
// memset(fhdr2, 0, sizeof(fhdr2));
|
||||
// } else {
|
||||
// if (parser->GetSize() < sizeof(fhdr1) + sizeof(fhdr2)) return CKERROR::CKERR_INVALIDFILE;
|
||||
// parser->Read(fhdr2, sizeof(fhdr2));
|
||||
// }
|
||||
|
||||
// // forcely reset too big product ver
|
||||
// if (fhdr2[5] >= 12) {
|
||||
// fhdr2[5] = 0;
|
||||
// fhdr2[6] = 0x1010000;
|
||||
// }
|
||||
|
||||
// // ========== assign value ==========
|
||||
// this->m_FileInfo.ProductVersion = fhdr2[5];
|
||||
// this->m_FileInfo.ProductBuild = fhdr2[6];
|
||||
// this->m_FileInfo.FileWriteMode = static_cast<CK_FILE_WRITEMODE>(fhdr1[6]);
|
||||
// this->m_FileInfo.CKVersion = fhdr1[3];
|
||||
// this->m_FileInfo.FileVersion = fhdr1[4];
|
||||
// this->m_FileInfo.FileSize = parser->GetSize();
|
||||
// this->m_FileInfo.ManagerCount = fhdr2[2];
|
||||
// this->m_FileInfo.ObjectCount = fhdr2[3];
|
||||
// this->m_FileInfo.MaxIDSaved = fhdr2[4];
|
||||
// this->m_FileInfo.Hdr1PackSize = fhdr1[7];
|
||||
// this->m_FileInfo.Hdr1UnPackSize = fhdr2[7];
|
||||
// this->m_FileInfo.DataPackSize = fhdr2[0];
|
||||
// this->m_FileInfo.DataUnPackSize = fhdr2[1];
|
||||
// this->m_FileInfo.Crc = fhdr1[2];
|
||||
|
||||
// // ========== crc and body unpacker ==========
|
||||
// if (this->m_FileInfo.FileVersion >= 8) {
|
||||
// // crc checker for file ver >= 8
|
||||
// // reset crc field of header
|
||||
// fhdr1[2] = 0;
|
||||
|
||||
// // compute crc
|
||||
// CKDWORD gotten_crc = CKComputeDataCRC(&fhdr1, sizeof(fhdr1), 0u);
|
||||
// parser->SetCursor(sizeof(fhdr1));
|
||||
// gotten_crc = CKComputeDataCRC(parser->GetPtr(), sizeof(fhdr2), gotten_crc);
|
||||
// parser->MoveCursor(sizeof(fhdr2));
|
||||
// gotten_crc = CKComputeDataCRC(parser->GetPtr(), this->m_FileInfo.Hdr1PackSize, gotten_crc);
|
||||
// parser->MoveCursor(this->m_FileInfo.Hdr1PackSize);
|
||||
// gotten_crc = CKComputeDataCRC(parser->GetPtr(), this->m_FileInfo.DataPackSize, gotten_crc);
|
||||
// parser->SetCursor(sizeof(fhdr1) + sizeof(fhdr2));
|
||||
|
||||
// if (gotten_crc != this->m_FileInfo.Crc) return CKERROR::CKERR_FILECRCERROR;
|
||||
|
||||
// // compare size to decide wheher use compress feature
|
||||
// void* decomp_buffer = CKUnPackData(this->m_FileInfo.Hdr1UnPackSize, parser->GetPtr(), this->m_FileInfo.Hdr1PackSize);
|
||||
// if (decomp_buffer != nullptr) {
|
||||
// parser = new(std::nothrow) CKBufferParser(decomp_buffer, this->m_FileInfo.Hdr1UnPackSize, true);
|
||||
// if (parser == nullptr) {
|
||||
// delete[] decomp_buffer;
|
||||
// return CKERROR::CKERR_OUTOFMEMORY;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// // ========== object list read ==========
|
||||
// // file ver >= 7 have this features
|
||||
// if (this->m_FileInfo.FileVersion >= 7) {
|
||||
// // apply max id saved
|
||||
// this->m_SaveIDMax = this->m_FileInfo.MaxIDSaved;
|
||||
// // resize
|
||||
// this->m_FileObject.resize(this->m_FileInfo.ObjectCount);
|
||||
|
||||
// // read data
|
||||
// for (auto& fileobj : this->m_FileObject) {
|
||||
// // setup useless fields
|
||||
// fileobj.ObjPtr = nullptr;
|
||||
// fileobj.Data = nullptr;
|
||||
|
||||
// // read basic fields
|
||||
// parser->Read(&(fileobj.Object), sizeof(CK_ID));
|
||||
// parser->Read(&(fileobj.ObjectCid), sizeof(CK_CLASSID));
|
||||
// parser->Read(&(fileobj.FileIndex), sizeof(CKDWORD));
|
||||
|
||||
// CKDWORD namelen;
|
||||
// parser->Read(&namelen, sizeof(CKDWORD));
|
||||
// if (namelen != 0) {
|
||||
// fileobj.Name.resize(namelen);
|
||||
// parser->Read(fileobj.Name.data(), namelen);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// // ========== dep list read ==========
|
||||
// // file ver >= 8 have this feature
|
||||
// bool noDepLost = true;
|
||||
// if (this->m_FileInfo.FileVersion >= 8) {
|
||||
// // get size and resize
|
||||
// CKDWORD depSize;
|
||||
// parser->Read(&depSize, sizeof(CKDWORD));
|
||||
// this->m_PluginDep.resize(depSize);
|
||||
|
||||
// CKDWORD guid_size;
|
||||
// for (auto& dep : this->m_PluginDep) {
|
||||
// // read category
|
||||
// parser->Read(&(dep.m_PluginCategory), sizeof(CK_PLUGIN_TYPE));
|
||||
// // get size and resize
|
||||
// parser->Read(&guid_size, sizeof(CKDWORD));
|
||||
// dep.m_Guids.resize(guid_size);
|
||||
// dep.ValidGuids.resize(guid_size);
|
||||
// // read data
|
||||
// if (guid_size != 0) {
|
||||
// parser->Read(dep.m_Guids.data(), sizeof(CKGUID) * guid_size);
|
||||
// }
|
||||
|
||||
// // extra load flag
|
||||
// if (EnumHelper::FlagEnumHas(this->m_Flags, CK_LOAD_FLAGS::CK_LOAD_CHECKDEPENDENCIES)) {
|
||||
// for (size_t i = 0u; i < dep.m_Guids.size(); ++i) {
|
||||
// // MARK: CKPluginManager::FindComponent
|
||||
// bool plgEntryIsNull = true;
|
||||
// if (plgEntryIsNull) {
|
||||
// noDepLost = false;
|
||||
// dep.ValidGuids[i] = false;
|
||||
// } else {
|
||||
// dep.ValidGuids[i] = true;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// }
|
||||
// }
|
||||
|
||||
// // ========== included file list read ==========
|
||||
// // file ver >= 8 have this feature
|
||||
// if (this->m_FileInfo.FileVersion >= 8) {
|
||||
// // MARK: i don't knwo what is this!
|
||||
// int32_t hasIncludedFile;
|
||||
// parser->Read(&hasIncludedFile, sizeof(int32_t));
|
||||
|
||||
// if (hasIncludedFile > 0) {
|
||||
// // read included file size and resize
|
||||
// CKDWORD includedFileCount;
|
||||
// parser->Read(&includedFileCount, sizeof(CKDWORD));
|
||||
// this->m_IncludedFiles.resize(includedFileCount);
|
||||
|
||||
// hasIncludedFile -= 4;
|
||||
// }
|
||||
|
||||
// // backward pos
|
||||
// parser->SetCursor(hasIncludedFile);
|
||||
// }
|
||||
|
||||
// // ========== read data ==========
|
||||
// // restore old parser if needed
|
||||
// if (parser != *ParserPtr) {
|
||||
// delete parser;
|
||||
// parser = *ParserPtr;
|
||||
// parser->MoveCursor(this->m_FileInfo.Hdr1PackSize);
|
||||
// }
|
||||
|
||||
// // MARK: dword_2405F6BC, dword_2405F6B8 set
|
||||
|
||||
// if (!(EnumHelper::FlagEnumHas(this->m_Flags, CK_LOAD_FLAGS::CK_LOAD_CHECKDEPENDENCIES) &&
|
||||
// this->m_FileInfo.FileVersion < 8)) {
|
||||
// // we have read all header. return result
|
||||
// return noDepLost ? CKERROR::CKERR_OK : CKERROR::CKERR_PLUGINSMISSING;
|
||||
// } // however, if we need check dep, and, we have not read dep list. continue read them.
|
||||
|
||||
// return CKERROR::CKERR_OK;
|
||||
//}
|
||||
|
||||
//CKERROR CKFile::ReadFileData(CKBufferParser** ParserPtr) {
|
||||
// CKBufferParser* parser = *ParserPtr;
|
||||
// CKBufferParser* parserSrc = *ParserPtr;
|
||||
|
||||
// // ========== compress feature process ==========
|
||||
// if (EnumHelper::FlagEnumHas(this->m_FileInfo.FileWriteMode, CK_FILE_WRITEMODE::CKFILE_CHUNKCOMPRESSED_OLD) ||
|
||||
// EnumHelper::FlagEnumHas(this->m_FileInfo.FileWriteMode, CK_FILE_WRITEMODE::CKFILE_WHOLECOMPRESSED)) {
|
||||
// void* decomp_buffer = CKUnPackData(this->m_FileInfo.DataUnPackSize, parser->GetPtr(), this->m_FileInfo.DataPackSize);
|
||||
// parser->MoveCursor(this->m_FileInfo.DataPackSize);
|
||||
|
||||
// if (decomp_buffer != nullptr) {
|
||||
// parser = new(std::nothrow) CKBufferParser(decomp_buffer, this->m_FileInfo.DataUnPackSize, true);
|
||||
// if (parser == nullptr) {
|
||||
// delete[] decomp_buffer;
|
||||
// return CKERROR::CKERR_OUTOFMEMORY;
|
||||
// }
|
||||
|
||||
// // sync to args
|
||||
// *ParserPtr = parser;
|
||||
// }
|
||||
// }
|
||||
|
||||
// // ========== old file crc and obj list read ==========
|
||||
// // only file ver < 8 run this
|
||||
// if (this->m_FileInfo.FileVersion < 8) {
|
||||
// // very very old flag
|
||||
// if (this->m_FileInfo.FileVersion < 2) {
|
||||
// ;
|
||||
// // MARK: dword_2405F6C0 setter
|
||||
// }
|
||||
|
||||
// // check crc
|
||||
// CKDWORD gotten_crc = CKComputeDataCRC(
|
||||
// parser->GetPtr(),
|
||||
// parser->GetSize() - parser->GetCursor(),
|
||||
// 0u
|
||||
// );
|
||||
// if (gotten_crc != this->m_FileInfo.Crc) {
|
||||
// // MARK: report crc error
|
||||
// return CKERROR::CKERR_FILECRCERROR;
|
||||
// }
|
||||
|
||||
// // get save id max
|
||||
// parser->Read(&this->m_SaveIDMax, sizeof(int32_t));
|
||||
// // get object count and resize
|
||||
// parser->Read(&this->m_FileInfo.ObjectCount, sizeof(CKDWORD));
|
||||
// if (this->m_FileObject.empty()) {
|
||||
// this->m_FileObject.resize(this->m_FileInfo.ObjectCount);
|
||||
// // MARK: ZeroMemory removed. i think it is not necessary.
|
||||
// }
|
||||
// }
|
||||
|
||||
// // ========== manager read ==========
|
||||
// // only file ver >= 6 have this
|
||||
// if (this->m_FileInfo.FileVersion >= 6 && this->m_FileInfo.ManagerCount != 0) {
|
||||
// this->m_ManagersData.resize(this->m_FileInfo.ManagerCount);
|
||||
// CKDWORD stateChunkLen = 0u;
|
||||
// bool stateChkParseSuccess = false;
|
||||
|
||||
// for (auto& mgr : this->m_ManagersData) {
|
||||
// // read guid
|
||||
// parser->Read(&(mgr.Manager), sizeof(CKGUID));
|
||||
|
||||
// // read statechunk len
|
||||
// parser->Read(&stateChunkLen, sizeof(CKDWORD));
|
||||
// // check len
|
||||
// if (stateChunkLen == 0) {
|
||||
// mgr.Data = nullptr;
|
||||
// continue;
|
||||
// }
|
||||
// // read statechunk
|
||||
// mgr.Data = new(std::nothrow) CKStateChunk();
|
||||
// if (mgr.Data != nullptr) {
|
||||
// stateChkParseSuccess = mgr.Data->ConvertFromBuffer(parser->GetPtr());
|
||||
// if (!stateChkParseSuccess) {
|
||||
// delete mgr.Data;
|
||||
// mgr.Data = nullptr;
|
||||
// }
|
||||
// }
|
||||
// parser->MoveCursor(stateChunkLen);
|
||||
// }
|
||||
// }
|
||||
|
||||
// // ========== object read ==========
|
||||
// if (this->m_FileInfo.ObjectCount != 0) {
|
||||
// if (this->m_FileInfo.FileVersion >= 4) {
|
||||
// // new file reader section
|
||||
// CKDWORD stateChunkLen = 0u;
|
||||
// bool stateChkParseSuccess = false;
|
||||
// for (auto& obj : this->m_FileObject) {
|
||||
// if (this->m_FileInfo.FileVersion < 7) {
|
||||
// // it seems that file ver < 7, ck id was stored first.
|
||||
// parser->Read(&(obj.Object), sizeof(CK_ID));
|
||||
// }
|
||||
// // get statechunk len
|
||||
// parser->Read(&stateChunkLen, sizeof(CKDWORD));
|
||||
|
||||
// // if only load behavior and current loaded obj is not behavior, give up.
|
||||
// // >= 7 is corresponding with obj header version requirement
|
||||
// // so don't worry about this
|
||||
// if (EnumHelper::FlagEnumHas(this->m_Flags, CK_LOAD_FLAGS::CK_LOAD_ONLYBEHAVIORS) &&
|
||||
// this->m_FileInfo.FileVersion >= 7 &&
|
||||
// obj.ObjectCid != CK_CLASSID::CKCID_BEHAVIOR) {
|
||||
// // move cursor for next one.
|
||||
// parser->MoveCursor(stateChunkLen);
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// // check state chunk len
|
||||
// if (stateChunkLen == 0) {
|
||||
// obj.Data = nullptr;
|
||||
// continue;
|
||||
// }
|
||||
// // read state chunk
|
||||
// obj.Data = new(std::nothrow) CKStateChunk();
|
||||
// if (obj.Data != nullptr) {
|
||||
// stateChkParseSuccess = obj.Data->ConvertFromBuffer(parser->GetPtr());
|
||||
// if (!stateChkParseSuccess) {
|
||||
// delete obj.Data;
|
||||
// obj.Data = nullptr;
|
||||
// } else {
|
||||
// // get data size and fill some fields
|
||||
// obj.PostPackSize = obj.Data->GetDataSize();
|
||||
// obj.PrePackSize = obj.PostPackSize;
|
||||
// }
|
||||
// }
|
||||
// parser->MoveCursor(stateChunkLen);
|
||||
|
||||
// }
|
||||
// } else {
|
||||
// // old file read section
|
||||
// for (auto& obj : this->m_FileObject) {
|
||||
// // read CK_ID
|
||||
// parser->Read(&(obj.Object), sizeof(CK_ID));
|
||||
// // get data len
|
||||
// CKDWORD dataLen = 0u;
|
||||
// parser->Read(&dataLen, sizeof(CKDWORD));
|
||||
|
||||
// // check state chunk len
|
||||
// if (dataLen == 0) {
|
||||
// obj.Data = nullptr;
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// // MARK: set dword_2405F6C0
|
||||
//
|
||||
// // read class id
|
||||
// CK_CLASSID clsid = CK_CLASSID::CKCID_OBJECT;
|
||||
// parser->Read(&clsid, sizeof(CK_CLASSID));
|
||||
// if (static_cast<uint32_t>(clsid) == UINT32_C(0)) {
|
||||
// // invalid cid;
|
||||
// return CKERROR::CKERR_INVALIDFILE;
|
||||
// }
|
||||
|
||||
// // read save flags
|
||||
// parser->Read(&obj.SaveFlags, sizeof(CK_FILE_WRITEMODE));
|
||||
|
||||
// // read statechunk len
|
||||
// CKDWORD oldBufLen = 0u;
|
||||
// parser->Read(&oldBufLen, sizeof(CKDWORD));
|
||||
|
||||
// // setup state chunk and order parse it
|
||||
// obj.Data = new(std::nothrow) CKStateChunk(clsid);
|
||||
// if (obj.Data != nullptr) {
|
||||
// if (!obj.Data->ConvertFromOldBuffer(parser->GetPtr(), oldBufLen, dataLen, obj.SaveFlags)) {
|
||||
// delete obj.Data;
|
||||
// obj.Data = nullptr;
|
||||
// }
|
||||
// }
|
||||
// // move to next
|
||||
// parser->MoveCursor(oldBufLen);
|
||||
// }
|
||||
|
||||
// // MARK: remove a weird assign: parserSrc = v46; it seems useless.
|
||||
// }
|
||||
// }
|
||||
|
||||
// // ========== object name get ==========
|
||||
// // only file ver < 7 need get it from statechunk
|
||||
// if (this->m_FileInfo.FileVersion < 7) {
|
||||
// for (auto& obj : this->m_FileObject) {
|
||||
// if (obj.Data != nullptr) {
|
||||
// // TODO: CK_STATESAVE_NAME
|
||||
// if (obj.Data->SeekIdentifier(1u)) {
|
||||
// obj.Data->ReadString(obj.Name);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// // ========== included file get ==========
|
||||
// // WARN: we use "parserSrc" to read, not "parser"!!!
|
||||
// for (size_t i = 0; i < this->m_IncludedFiles.size(); ++i) {
|
||||
// // get file name length and resize it
|
||||
// CKDWORD filenamelen = 0u;
|
||||
// parserSrc->Read(&filenamelen, sizeof(CKDWORD));
|
||||
// std::string filename;
|
||||
// filename.resize(filenamelen);
|
||||
|
||||
// // read filename
|
||||
// if (filenamelen != 0) {
|
||||
// parserSrc->Read(filename.data(), filenamelen);
|
||||
// }
|
||||
|
||||
// // todo: construct temp folder path
|
||||
// // and regulate file name
|
||||
|
||||
// // read file body length
|
||||
// CKDWORD filebodylen = 0u;
|
||||
// parserSrc->Read(&filebodylen, sizeof(CKDWORD));
|
||||
|
||||
// // todo: read file body
|
||||
// parserSrc->MoveCursor(filebodylen);
|
||||
// }
|
||||
|
||||
// // ========== free parser ==========
|
||||
// if (parserSrc != parser && parserSrc != nullptr) {
|
||||
// // WARN: we should free parserSrc! not free parser
|
||||
// // because "parser" has synced with ParserPtr and will be freed from outside.
|
||||
// delete parserSrc;
|
||||
|
||||
// }
|
||||
|
||||
// return CKERROR::CKERR_OK;
|
||||
//}
|
||||
|
||||
//CKERROR CKFile::LoadFileData(void/*CKObjectArray list*/) {
|
||||
// if (!this->m_Parser && !this->m_ReadFileDataDone) {
|
||||
// return CKERROR::CKERR_INVALIDFILE;
|
||||
// }
|
||||
|
||||
// // MARK: sub_240372EA, ctx + 193 = 1
|
||||
|
||||
// // if file data has not been read. read it
|
||||
// CKERROR err = CKERROR::CKERR_OK;
|
||||
// CKBufferParser** ParserPtr = &this->m_Parser;
|
||||
// if (!this->m_ReadFileDataDone) {
|
||||
// err = this->ReadFileData(ParserPtr);
|
||||
// }
|
||||
|
||||
// // MARK: i assume FinishLoading do not calling mapped file anymore
|
||||
// // free file data
|
||||
// if (*ParserPtr != nullptr) {
|
||||
// delete *ParserPtr;
|
||||
// *ParserPtr = nullptr;
|
||||
// }
|
||||
// if (this->m_MappedFile != nullptr) {
|
||||
// delete this->m_MappedFile;
|
||||
// this->m_MappedFile = nullptr;
|
||||
// }
|
||||
|
||||
// // if no error, do finish loading
|
||||
// if (err == CKERROR::CKERR_OK) {
|
||||
// this->FinishLoading(this->m_Flags);
|
||||
|
||||
// // MARK: dword_2405F6C0 old vt ver output
|
||||
// }
|
||||
// // MARK: CKContext::SetAutomaticLoadMode
|
||||
// // MARK:CKContext::SetUserLoadCallback
|
||||
|
||||
// // MARK: sub_24037360
|
||||
// // MARK: ctx + 193 = 0
|
||||
|
||||
// return err;
|
||||
//}
|
||||
|
||||
//CKERROR CKFile::FinishLoading(/*CKObjectArray list, */CK_LOAD_FLAGS flags) {
|
||||
// return CKERROR::CKERR_OK;
|
||||
//}
|
||||
|
||||
}
|
7
LibCmo/CKFileWriter.cpp
Normal file
7
LibCmo/CKFileWriter.cpp
Normal file
|
@ -0,0 +1,7 @@
|
|||
#include "CKFile.hpp"
|
||||
|
||||
namespace LibCmo {
|
||||
|
||||
|
||||
|
||||
}
|
38
LibCmo/CKGlobals.cpp
Normal file
38
LibCmo/CKGlobals.cpp
Normal file
|
@ -0,0 +1,38 @@
|
|||
#include "VTUtils.hpp"
|
||||
#if defined(LIBCMO_OS_WIN32)
|
||||
#define ZLIB_WINAPI
|
||||
#include <zconf.h>
|
||||
#endif
|
||||
|
||||
#include "CKDefines.hpp"
|
||||
#include "CKGlobals.hpp"
|
||||
#include <zlib.h>
|
||||
|
||||
namespace LibCmo {
|
||||
|
||||
|
||||
void* CKUnPackData(CKINT DestSize, const void* SrcBuffer, CKINT SrcSize) {
|
||||
char* DestBuffer = new(std::nothrow) char[DestSize];
|
||||
if (DestBuffer == nullptr) return nullptr;
|
||||
|
||||
uLongf cache = DestSize;
|
||||
if (uncompress(
|
||||
reinterpret_cast<Bytef*>(DestBuffer), &cache,
|
||||
reinterpret_cast<const Bytef*>(SrcBuffer), SrcSize) != Z_OK) {
|
||||
delete[] DestBuffer;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return DestBuffer;
|
||||
}
|
||||
|
||||
CKDWORD LibCmo::CKComputeDataCRC(const void* data, size_t size, CKDWORD PreviousCRC) {
|
||||
return static_cast<CKDWORD>(adler32(
|
||||
static_cast<uLong>(PreviousCRC),
|
||||
reinterpret_cast<const Bytef*>(data),
|
||||
static_cast<uInt>(size)
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
8
LibCmo/CKGlobals.hpp
Normal file
8
LibCmo/CKGlobals.hpp
Normal file
|
@ -0,0 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
namespace LibCmo {
|
||||
|
||||
void* CKUnPackData(CKINT DestSize, const void* SrcBuffer, CKINT SrcSize);
|
||||
CKDWORD CKComputeDataCRC(const void* data, size_t size, CKDWORD PreviousCRC = 0);
|
||||
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
#endif
|
||||
|
||||
#include <zlib.h>
|
||||
#include "VTStruct.hpp"
|
||||
#include "CKStateChunk.hpp"
|
||||
|
||||
namespace LibCmo {
|
||||
|
||||
|
@ -30,33 +30,6 @@ namespace LibCmo {
|
|||
delete[] this->m_pData;
|
||||
}
|
||||
|
||||
bool CKStateChunk::ConvertFromOldBuffer(const void* buf, CKDWORD buf_size, CKDWORD blk_size, CK_FILE_WRITEMODE mode) {
|
||||
// if not use compress or 2 size is equal, it mean that this buffer is raw.
|
||||
// assign it directly
|
||||
if (!EnumHelper::FlagEnumHas(mode, CK_FILE_WRITEMODE::CKFILE_CHUNKCOMPRESSED_OLD) ||
|
||||
buf_size == blk_size) {
|
||||
|
||||
this->m_DataDwSize = buf_size / sizeof(CKDWORD);
|
||||
this->m_pData = new(std::nothrow) CKDWORD[this->m_DataDwSize];
|
||||
if (this->m_pData != nullptr) {
|
||||
memcpy(this->m_pData, buf, this->m_DataDwSize * sizeof(CKDWORD));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} else {
|
||||
// otherwise, we need UnPack
|
||||
// prepare UnPack requirement
|
||||
this->m_DataDwSize = buf_size; // NOTE: store as BYTE length!!!
|
||||
this->m_pData = reinterpret_cast<CKDWORD*>(new(std::nothrow) char[buf_size]);
|
||||
if (this->m_pData == nullptr) return false;
|
||||
memcpy(this->m_pData, buf, buf_size);
|
||||
|
||||
// call UnPack
|
||||
return UnPack(blk_size);
|
||||
}
|
||||
}
|
||||
|
||||
bool CKStateChunk::ConvertFromBuffer(const void* buf) {
|
||||
if (buf == nullptr) return false;
|
||||
|
||||
|
@ -154,23 +127,23 @@ namespace LibCmo {
|
|||
memcpy(this->m_pData, dwbuf + bufpos, sizeof(CKDWORD) * this->m_DataDwSize);
|
||||
bufpos += this->m_DataDwSize;
|
||||
}
|
||||
if (EnumHelper::FlagEnumHas(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_FILE)) {
|
||||
if (EnumsHelper::FlagEnumHas(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_FILE)) {
|
||||
// MARK: set ckfile = nullptr;
|
||||
;
|
||||
}
|
||||
if (EnumHelper::FlagEnumHas(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_IDS)) {
|
||||
if (EnumsHelper::FlagEnumHas(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_IDS)) {
|
||||
this->m_ObjectList.resize(dwbuf[bufpos]);
|
||||
bufpos += 1u;
|
||||
memcpy(this->m_ObjectList.data(), dwbuf + bufpos, sizeof(CKDWORD) * this->m_ObjectList.size());
|
||||
bufpos += this->m_ObjectList.size();
|
||||
}
|
||||
if (EnumHelper::FlagEnumHas(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_CHN)) {
|
||||
if (EnumsHelper::FlagEnumHas(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_CHN)) {
|
||||
this->m_ChunkList.resize(dwbuf[bufpos]);
|
||||
bufpos += 1u;
|
||||
memcpy(this->m_ChunkList.data(), dwbuf + bufpos, sizeof(CKDWORD) * this->m_ChunkList.size());
|
||||
bufpos += this->m_ChunkList.size();
|
||||
}
|
||||
if (EnumHelper::FlagEnumHas(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_MAN)) {
|
||||
if (EnumsHelper::FlagEnumHas(options, CK_STATECHUNK_CHUNKOPTIONS::CHNK_OPTION_MAN)) {
|
||||
this->m_ManagerList.resize(dwbuf[bufpos]);
|
||||
bufpos += 1u;
|
||||
memcpy(this->m_ManagerList.data(), dwbuf + bufpos, sizeof(CKDWORD) * this->m_ManagerList.size());
|
||||
|
@ -190,34 +163,34 @@ namespace LibCmo {
|
|||
return 0u;
|
||||
}
|
||||
|
||||
bool CKStateChunk::UnPack(CKDWORD DestSize) {
|
||||
// NOTE: in UnPack. pData store the compressed buffer, and
|
||||
// dwSize store the length of compressed buffer as CHAR size, not DWORD size!
|
||||
//bool CKStateChunk::UnPack(CKDWORD DestSize) {
|
||||
// // NOTE: in UnPack. pData store the compressed buffer, and
|
||||
// // dwSize store the length of compressed buffer as CHAR size, not DWORD size!
|
||||
|
||||
// create a enough buffer
|
||||
char* buffer = new(std::nothrow) char[DestSize];
|
||||
if (buffer == nullptr) return false;
|
||||
uLongf destSize = DestSize;
|
||||
// uncompress it
|
||||
auto err = uncompress(
|
||||
reinterpret_cast<Bytef*>(buffer), &destSize,
|
||||
reinterpret_cast<const Bytef*>(this->m_pData), static_cast<uLong>(this->m_DataDwSize)
|
||||
);
|
||||
// if no error, assign data
|
||||
if (err == Z_OK) {
|
||||
// get dw size and copy it to remove useless blank data
|
||||
this->m_DataDwSize = static_cast<CKDWORD>(destSize) / sizeof(CKDWORD);
|
||||
// // create a enough buffer
|
||||
// char* buffer = new(std::nothrow) char[DestSize];
|
||||
// if (buffer == nullptr) return false;
|
||||
// uLongf destSize = DestSize;
|
||||
// // uncompress it
|
||||
// auto err = uncompress(
|
||||
// reinterpret_cast<Bytef*>(buffer), &destSize,
|
||||
// reinterpret_cast<const Bytef*>(this->m_pData), static_cast<uLong>(this->m_DataDwSize)
|
||||
// );
|
||||
// // if no error, assign data
|
||||
// if (err == Z_OK) {
|
||||
// // get dw size and copy it to remove useless blank data
|
||||
// this->m_DataDwSize = static_cast<CKDWORD>(destSize) / sizeof(CKDWORD);
|
||||
|
||||
delete[] this->m_pData;
|
||||
this->m_pData = nullptr;
|
||||
this->m_pData = new(std::nothrow) CKDWORD[this->m_DataDwSize];
|
||||
if (this->m_pData != nullptr) {
|
||||
memcpy(this->m_pData, buffer, this->m_DataDwSize * sizeof(CKDWORD));
|
||||
}
|
||||
}
|
||||
delete[] buffer;
|
||||
return true;
|
||||
}
|
||||
// delete[] this->m_pData;
|
||||
// this->m_pData = nullptr;
|
||||
// this->m_pData = new(std::nothrow) CKDWORD[this->m_DataDwSize];
|
||||
// if (this->m_pData != nullptr) {
|
||||
// memcpy(this->m_pData, buffer, this->m_DataDwSize * sizeof(CKDWORD));
|
||||
// }
|
||||
// }
|
||||
// delete[] buffer;
|
||||
// return true;
|
||||
//}
|
||||
|
||||
CKDWORD CKStateChunk::GetDataSize(void) {
|
||||
return sizeof(CKDWORD) * this->m_DataDwSize;
|
50
LibCmo/CKStateChunk.hpp
Normal file
50
LibCmo/CKStateChunk.hpp
Normal file
|
@ -0,0 +1,50 @@
|
|||
#pragma once
|
||||
|
||||
#include "CKDefines.hpp"
|
||||
#include "CKEnums.hpp"
|
||||
|
||||
namespace LibCmo {
|
||||
|
||||
class CKStateChunk {
|
||||
public:
|
||||
CKStateChunk();
|
||||
CKStateChunk(CK_CLASSID clsid);
|
||||
CKStateChunk(const CKStateChunk&) = delete;
|
||||
CKStateChunk& operator=(const CKStateChunk&) = delete;
|
||||
~CKStateChunk();
|
||||
|
||||
bool ConvertFromOldBuffer(const void* buf, CKDWORD buf_size, CKDWORD blk_size, CK_FILE_WRITEMODE mode);
|
||||
bool ConvertFromBuffer(const void* buf);
|
||||
CKDWORD ConvertToBuffer(void* buf);
|
||||
|
||||
bool UnPack(CKDWORD DestSize);
|
||||
CKDWORD GetDataSize(void);
|
||||
|
||||
bool SeekIdentifier(CKDWORD identifier);
|
||||
|
||||
void ReadString(std::string& strl);
|
||||
|
||||
private:
|
||||
CK_CLASSID m_ClassId;
|
||||
CKDWORD m_DataDwSize;
|
||||
CKDWORD* m_pData;
|
||||
|
||||
CK_STATECHUNK_DATAVERSION m_DataVersion;
|
||||
CK_STATECHUNK_CHUNKVERSION m_ChunkVersion;
|
||||
|
||||
struct {
|
||||
CKDWORD m_CurrentPos;
|
||||
CKDWORD m_DataSize;
|
||||
CKDWORD m_PrevIdentifierPos;
|
||||
}m_Parser;
|
||||
|
||||
std::vector<CKDWORD> m_ObjectList;
|
||||
std::vector<CKDWORD> m_ChunkList;
|
||||
std::vector<CKDWORD> m_ManagerList;
|
||||
|
||||
private:
|
||||
void _EnsureEnoughSpace(CKDWORD size);
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -171,16 +171,25 @@
|
|||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="CKFile.cpp" />
|
||||
<ClCompile Include="CKFileWriter.cpp" />
|
||||
<ClCompile Include="CKGlobals.cpp" />
|
||||
<ClCompile Include="ObjsImpl\CKObject.cpp" />
|
||||
<ClCompile Include="VTEncoding.cpp" />
|
||||
<ClCompile Include="VTReader.cpp" />
|
||||
<ClCompile Include="VTStateChunk.cpp" />
|
||||
<ClCompile Include="VTStruct.cpp" />
|
||||
<ClCompile Include="CKFileReader.cpp" />
|
||||
<ClCompile Include="CKStateChunk.cpp" />
|
||||
<ClCompile Include="VxMemoryMappedFile.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="VTConstants.hpp" />
|
||||
<ClInclude Include="CKDefines.hpp" />
|
||||
<ClInclude Include="CKEnums.hpp" />
|
||||
<ClInclude Include="CKFile.hpp" />
|
||||
<ClInclude Include="CKGlobals.hpp" />
|
||||
<ClInclude Include="CKStateChunk.hpp" />
|
||||
<ClInclude Include="VTEncoding.hpp" />
|
||||
<ClInclude Include="VTStruct.hpp" />
|
||||
<ClInclude Include="VTObjects.hpp" />
|
||||
<ClInclude Include="VTUtils.hpp" />
|
||||
<ClInclude Include="VxMemoryMappedFile.hpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
|
|
@ -13,33 +13,63 @@
|
|||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Sources\ObjsImpl">
|
||||
<UniqueIdentifier>{a8cd2188-b552-478c-9801-a6286b3d48a0}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="VTReader.cpp">
|
||||
<Filter>Sources</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="VTStruct.cpp">
|
||||
<ClCompile Include="CKFileReader.cpp">
|
||||
<Filter>Sources</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="VTEncoding.cpp">
|
||||
<Filter>Sources</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="VTStateChunk.cpp">
|
||||
<ClCompile Include="CKStateChunk.cpp">
|
||||
<Filter>Sources</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="VxMemoryMappedFile.cpp">
|
||||
<Filter>Sources</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CKFileWriter.cpp">
|
||||
<Filter>Sources</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ObjsImpl\CKObject.cpp">
|
||||
<Filter>Sources\ObjsImpl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CKGlobals.cpp">
|
||||
<Filter>Sources</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CKFile.cpp">
|
||||
<Filter>Sources</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="VTStruct.hpp">
|
||||
<Filter>Headers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="VTConstants.hpp">
|
||||
<Filter>Headers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="VTUtils.hpp">
|
||||
<Filter>Headers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="VTEncoding.hpp">
|
||||
<Filter>Headers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="VTObjects.hpp">
|
||||
<Filter>Headers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CKDefines.hpp">
|
||||
<Filter>Headers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CKEnums.hpp">
|
||||
<Filter>Headers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CKStateChunk.hpp">
|
||||
<Filter>Headers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CKGlobals.hpp">
|
||||
<Filter>Headers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CKFile.hpp">
|
||||
<Filter>Headers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="VxMemoryMappedFile.hpp">
|
||||
<Filter>Headers</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
15
LibCmo/ObjsImpl/CKObject.cpp
Normal file
15
LibCmo/ObjsImpl/CKObject.cpp
Normal file
|
@ -0,0 +1,15 @@
|
|||
#include "../VTObjects.hpp"
|
||||
|
||||
namespace LibCmo {
|
||||
namespace ObjsImpl {
|
||||
|
||||
CKObject::CKObject() {
|
||||
|
||||
}
|
||||
|
||||
CKObject::~CKObject() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
122
LibCmo/VTObjects.hpp
Normal file
122
LibCmo/VTObjects.hpp
Normal file
|
@ -0,0 +1,122 @@
|
|||
#pragma once
|
||||
|
||||
#include "CKDefines.hpp"
|
||||
#include "CKEnums.hpp"
|
||||
#include "CKStateChunk.hpp"
|
||||
|
||||
namespace LibCmo {
|
||||
namespace ObjsImpl {
|
||||
|
||||
class CKObject {
|
||||
public:
|
||||
CKObject();
|
||||
CKObject(const CKObject&) = delete;
|
||||
CKObject& operator=(const CKObject&) = delete;
|
||||
virtual ~CKObject();
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
class CKSceneObject : public CKObject {
|
||||
public:
|
||||
CKSceneObject();
|
||||
CKSceneObject(const CKSceneObject&) = delete;
|
||||
CKSceneObject& operator=(const CKSceneObject&) = delete;
|
||||
virtual ~CKSceneObject();
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
class CKBeObject : public CKSceneObject {
|
||||
public:
|
||||
CKBeObject();
|
||||
CKBeObject(const CKBeObject&) = delete;
|
||||
CKBeObject& operator=(const CKBeObject&) = delete;
|
||||
virtual ~CKBeObject();
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
class CKGroup : public CKBeObject {
|
||||
public:
|
||||
CKGroup();
|
||||
CKGroup(const CKGroup&) = delete;
|
||||
CKGroup& operator=(const CKGroup&) = delete;
|
||||
virtual ~CKGroup();
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
class CKMesh : public CKBeObject {
|
||||
public:
|
||||
CKMesh();
|
||||
CKMesh(const CKMesh&) = delete;
|
||||
CKMesh& operator=(const CKMesh&) = delete;
|
||||
virtual ~CKMesh();
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
class CKTexture : public CKBeObject {
|
||||
public:
|
||||
CKTexture();
|
||||
CKTexture(const CKTexture&) = delete;
|
||||
CKTexture& operator=(const CKTexture&) = delete;
|
||||
virtual ~CKTexture();
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
class CKMaterial : public CKBeObject {
|
||||
public:
|
||||
CKMaterial();
|
||||
CKMaterial(const CKMaterial&) = delete;
|
||||
CKMaterial& operator=(const CKMaterial&) = delete;
|
||||
virtual ~CKMaterial();
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
class CKRenderObject : public CKBeObject {
|
||||
public:
|
||||
CKRenderObject();
|
||||
CKRenderObject(const CKRenderObject&) = delete;
|
||||
CKRenderObject& operator=(const CKRenderObject&) = delete;
|
||||
~CKRenderObject();
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
class CK3dEntity : public CKBeObject {
|
||||
public:
|
||||
CK3dEntity();
|
||||
CK3dEntity(const CK3dEntity&) = delete;
|
||||
CK3dEntity& operator=(const CK3dEntity&) = delete;
|
||||
virtual ~CK3dEntity();
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
class CK3dObject :public CK3dEntity {
|
||||
public:
|
||||
CK3dObject();
|
||||
CK3dObject(const CK3dObject&) = delete;
|
||||
CK3dObject& operator=(const CK3dObject&) = delete;
|
||||
~CK3dObject();
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -1,501 +0,0 @@
|
|||
#include "VTUtils.hpp"
|
||||
#if defined(LIBCMO_OS_WIN32)
|
||||
#define ZLIB_WINAPI
|
||||
#include "zconf.h"
|
||||
#endif
|
||||
|
||||
#include "VTStruct.hpp"
|
||||
#include <zlib.h>
|
||||
|
||||
namespace LibCmo {
|
||||
|
||||
CKERROR CKFile::Load(CKSTRING u8_filename, /*CKObjectArray list, */ CK_LOAD_FLAGS flags) {
|
||||
CKERROR result = this->OpenFile(u8_filename, flags);
|
||||
if (result == CKERROR::CKERR_OK || result == CKERROR::CKERR_PLUGINSMISSING) {
|
||||
result = this->LoadFileData();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
CKERROR CKFile::OpenFile(CKSTRING u8_filename, CK_LOAD_FLAGS flags) {
|
||||
this->ClearData();
|
||||
if (u8_filename == nullptr) return CKERROR::CKERR_INVALIDPARAMETER;
|
||||
|
||||
this->m_FileName = u8_filename;
|
||||
this->m_MappedFile = new(std::nothrow) VxMemoryMappedFile(this->m_FileName.c_str());
|
||||
if (this->m_MappedFile == nullptr) return CKERROR::CKERR_OUTOFMEMORY;
|
||||
if (!this->m_MappedFile->IsValid()) return CKERROR::CKERR_INVALIDFILE;
|
||||
|
||||
// MARK: CKContext::SetLastCmoLoaded
|
||||
return this->OpenMemory(this->m_MappedFile->GetBase(), this->m_MappedFile->GetFileSize(), flags);
|
||||
}
|
||||
|
||||
CKERROR CKFile::OpenMemory(void* MemoryBuffer, size_t BufferSize, CK_LOAD_FLAGS Flags) {
|
||||
if (MemoryBuffer == nullptr) return CKERROR::CKERR_INVALIDPARAMETER;
|
||||
// compare magic words
|
||||
if (BufferSize < 0x20 || memcmp(MemoryBuffer, "Nemo", 4u)) return CKERROR::CKERR_INVALIDFILE;
|
||||
|
||||
this->m_Parser = new(std::nothrow) CKBufferParser(MemoryBuffer, BufferSize, false);
|
||||
if (this->m_Parser == nullptr) return CKERROR::CKERR_OUTOFMEMORY;
|
||||
// MARK: eliminate check of m_Parser->m_ReaderBegin
|
||||
|
||||
// MARK: dword_2405F6C0 = 0;
|
||||
this->m_Flags = Flags;
|
||||
this->m_IndexByClassId.resize(static_cast<size_t>(CK_CLASSID::CKCID_MAXCLASSID));
|
||||
return this->ReadFileHeaders(&(this->m_Parser));
|
||||
}
|
||||
|
||||
CKERROR CKFile::ReadFileHeaders(CKBufferParser** ParserPtr) {
|
||||
CKBufferParser* parser = *ParserPtr;
|
||||
this->m_IncludedFiles.clear();
|
||||
|
||||
// ========== read header1 ==========
|
||||
CKDWORD fhdr1[8];
|
||||
CKDWORD fhdr2[8];
|
||||
if (parser->GetSize() < sizeof(fhdr1)) return CKERROR::CKERR_INVALIDFILE;
|
||||
parser->Read(fhdr1, sizeof(fhdr1));
|
||||
|
||||
if (fhdr1[5]) { // it seems that there is a ZERO checker?
|
||||
memset(fhdr1, 0, sizeof(fhdr1));
|
||||
}
|
||||
// check outdated
|
||||
if (fhdr1[4] > 9) return CKERROR::CKERR_OBSOLETEVIRTOOLS;
|
||||
|
||||
// ========== read header2 ==========
|
||||
// file ver < 5 do not have second header
|
||||
if (fhdr1[4] < 5) {
|
||||
memset(fhdr2, 0, sizeof(fhdr2));
|
||||
} else {
|
||||
if (parser->GetSize() < sizeof(fhdr1) + sizeof(fhdr2)) return CKERROR::CKERR_INVALIDFILE;
|
||||
parser->Read(fhdr2, sizeof(fhdr2));
|
||||
}
|
||||
|
||||
// forcely reset too big product ver
|
||||
if (fhdr2[5] >= 12) {
|
||||
fhdr2[5] = 0;
|
||||
fhdr2[6] = 0x1010000;
|
||||
}
|
||||
|
||||
// ========== assign value ==========
|
||||
this->m_FileInfo.ProductVersion = fhdr2[5];
|
||||
this->m_FileInfo.ProductBuild = fhdr2[6];
|
||||
this->m_FileInfo.FileWriteMode = static_cast<CK_FILE_WRITEMODE>(fhdr1[6]);
|
||||
this->m_FileInfo.CKVersion = fhdr1[3];
|
||||
this->m_FileInfo.FileVersion = fhdr1[4];
|
||||
this->m_FileInfo.FileSize = parser->GetSize();
|
||||
this->m_FileInfo.ManagerCount = fhdr2[2];
|
||||
this->m_FileInfo.ObjectCount = fhdr2[3];
|
||||
this->m_FileInfo.MaxIDSaved = fhdr2[4];
|
||||
this->m_FileInfo.Hdr1PackSize = fhdr1[7];
|
||||
this->m_FileInfo.Hdr1UnPackSize = fhdr2[7];
|
||||
this->m_FileInfo.DataPackSize = fhdr2[0];
|
||||
this->m_FileInfo.DataUnPackSize = fhdr2[1];
|
||||
this->m_FileInfo.Crc = fhdr1[2];
|
||||
|
||||
// ========== crc and body unpacker ==========
|
||||
if (this->m_FileInfo.FileVersion >= 8) {
|
||||
// crc checker for file ver >= 8
|
||||
// reset crc field of header
|
||||
fhdr1[2] = 0;
|
||||
|
||||
// compute crc
|
||||
CKDWORD gotten_crc = CKComputeDataCRC(&fhdr1, sizeof(fhdr1), 0u);
|
||||
parser->SetCursor(sizeof(fhdr1));
|
||||
gotten_crc = CKComputeDataCRC(parser->GetPtr(), sizeof(fhdr2), gotten_crc);
|
||||
parser->MoveCursor(sizeof(fhdr2));
|
||||
gotten_crc = CKComputeDataCRC(parser->GetPtr(), this->m_FileInfo.Hdr1PackSize, gotten_crc);
|
||||
parser->MoveCursor(this->m_FileInfo.Hdr1PackSize);
|
||||
gotten_crc = CKComputeDataCRC(parser->GetPtr(), this->m_FileInfo.DataPackSize, gotten_crc);
|
||||
parser->SetCursor(sizeof(fhdr1) + sizeof(fhdr2));
|
||||
|
||||
if (gotten_crc != this->m_FileInfo.Crc) return CKERROR::CKERR_FILECRCERROR;
|
||||
|
||||
// compare size to decide wheher use compress feature
|
||||
void* decomp_buffer = CKUnPackData(this->m_FileInfo.Hdr1UnPackSize, parser->GetPtr(), this->m_FileInfo.Hdr1PackSize);
|
||||
if (decomp_buffer != nullptr) {
|
||||
parser = new(std::nothrow) CKBufferParser(decomp_buffer, this->m_FileInfo.Hdr1UnPackSize, true);
|
||||
if (parser == nullptr) {
|
||||
delete[] decomp_buffer;
|
||||
return CKERROR::CKERR_OUTOFMEMORY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ========== object list read ==========
|
||||
// file ver >= 7 have this features
|
||||
if (this->m_FileInfo.FileVersion >= 7) {
|
||||
// apply max id saved
|
||||
this->m_SaveIDMax = this->m_FileInfo.MaxIDSaved;
|
||||
// resize
|
||||
this->m_FileObject.resize(this->m_FileInfo.ObjectCount);
|
||||
|
||||
// read data
|
||||
for (auto& fileobj : this->m_FileObject) {
|
||||
// setup useless fields
|
||||
fileobj.ObjPtr = nullptr;
|
||||
fileobj.Data = nullptr;
|
||||
|
||||
// read basic fields
|
||||
parser->Read(&(fileobj.Object), sizeof(CK_ID));
|
||||
parser->Read(&(fileobj.ObjectCid), sizeof(CK_CLASSID));
|
||||
parser->Read(&(fileobj.FileIndex), sizeof(CKDWORD));
|
||||
|
||||
CKDWORD namelen;
|
||||
parser->Read(&namelen, sizeof(CKDWORD));
|
||||
if (namelen != 0) {
|
||||
fileobj.Name.resize(namelen);
|
||||
parser->Read(fileobj.Name.data(), namelen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ========== dep list read ==========
|
||||
// file ver >= 8 have this feature
|
||||
bool noDepLost = true;
|
||||
if (this->m_FileInfo.FileVersion >= 8) {
|
||||
// get size and resize
|
||||
CKDWORD depSize;
|
||||
parser->Read(&depSize, sizeof(CKDWORD));
|
||||
this->m_PluginDep.resize(depSize);
|
||||
|
||||
CKDWORD guid_size;
|
||||
for (auto& dep : this->m_PluginDep) {
|
||||
// read category
|
||||
parser->Read(&(dep.m_PluginCategory), sizeof(CK_PLUGIN_TYPE));
|
||||
// get size and resize
|
||||
parser->Read(&guid_size, sizeof(CKDWORD));
|
||||
dep.m_Guids.resize(guid_size);
|
||||
dep.ValidGuids.resize(guid_size);
|
||||
// read data
|
||||
if (guid_size != 0) {
|
||||
parser->Read(dep.m_Guids.data(), sizeof(CKGUID) * guid_size);
|
||||
}
|
||||
|
||||
// extra load flag
|
||||
if (EnumHelper::FlagEnumHas(this->m_Flags, CK_LOAD_FLAGS::CK_LOAD_CHECKDEPENDENCIES)) {
|
||||
for (size_t i = 0u; i < dep.m_Guids.size(); ++i) {
|
||||
// MARK: CKPluginManager::FindComponent
|
||||
bool plgEntryIsNull = true;
|
||||
if (plgEntryIsNull) {
|
||||
noDepLost = false;
|
||||
dep.ValidGuids[i] = false;
|
||||
} else {
|
||||
dep.ValidGuids[i] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ========== included file list read ==========
|
||||
// file ver >= 8 have this feature
|
||||
if (this->m_FileInfo.FileVersion >= 8) {
|
||||
// MARK: i don't knwo what is this!
|
||||
int32_t hasIncludedFile;
|
||||
parser->Read(&hasIncludedFile, sizeof(int32_t));
|
||||
|
||||
if (hasIncludedFile > 0) {
|
||||
// read included file size and resize
|
||||
CKDWORD includedFileCount;
|
||||
parser->Read(&includedFileCount, sizeof(CKDWORD));
|
||||
this->m_IncludedFiles.resize(includedFileCount);
|
||||
|
||||
hasIncludedFile -= 4;
|
||||
}
|
||||
|
||||
// backward pos
|
||||
parser->SetCursor(hasIncludedFile);
|
||||
}
|
||||
|
||||
// ========== read data ==========
|
||||
// restore old parser if needed
|
||||
if (parser != *ParserPtr) {
|
||||
delete parser;
|
||||
parser = *ParserPtr;
|
||||
parser->MoveCursor(this->m_FileInfo.Hdr1PackSize);
|
||||
}
|
||||
|
||||
// MARK: dword_2405F6BC, dword_2405F6B8 set
|
||||
|
||||
if (!(EnumHelper::FlagEnumHas(this->m_Flags, CK_LOAD_FLAGS::CK_LOAD_CHECKDEPENDENCIES) &&
|
||||
this->m_FileInfo.FileVersion < 8)) {
|
||||
// we have read all header. return result
|
||||
return noDepLost ? CKERROR::CKERR_OK : CKERROR::CKERR_PLUGINSMISSING;
|
||||
} // however, if we need check dep, and, we have not read dep list. continue read them.
|
||||
|
||||
return CKERROR::CKERR_OK;
|
||||
}
|
||||
|
||||
CKERROR CKFile::ReadFileData(CKBufferParser** ParserPtr) {
|
||||
CKBufferParser* parser = *ParserPtr;
|
||||
CKBufferParser* parserSrc = *ParserPtr;
|
||||
|
||||
// ========== compress feature process ==========
|
||||
if (EnumHelper::FlagEnumHas(this->m_FileInfo.FileWriteMode, CK_FILE_WRITEMODE::CKFILE_CHUNKCOMPRESSED_OLD) ||
|
||||
EnumHelper::FlagEnumHas(this->m_FileInfo.FileWriteMode, CK_FILE_WRITEMODE::CKFILE_WHOLECOMPRESSED)) {
|
||||
void* decomp_buffer = CKUnPackData(this->m_FileInfo.DataUnPackSize, parser->GetPtr(), this->m_FileInfo.DataPackSize);
|
||||
parser->MoveCursor(this->m_FileInfo.DataPackSize);
|
||||
|
||||
if (decomp_buffer != nullptr) {
|
||||
parser = new(std::nothrow) CKBufferParser(decomp_buffer, this->m_FileInfo.DataUnPackSize, true);
|
||||
if (parser == nullptr) {
|
||||
delete[] decomp_buffer;
|
||||
return CKERROR::CKERR_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
// sync to args
|
||||
*ParserPtr = parser;
|
||||
}
|
||||
}
|
||||
|
||||
// ========== old file crc and obj list read ==========
|
||||
// only file ver < 8 run this
|
||||
if (this->m_FileInfo.FileVersion < 8) {
|
||||
// very very old flag
|
||||
if (this->m_FileInfo.FileVersion < 2) {
|
||||
;
|
||||
// MARK: dword_2405F6C0 setter
|
||||
}
|
||||
|
||||
// check crc
|
||||
CKDWORD gotten_crc = CKComputeDataCRC(
|
||||
parser->GetPtr(),
|
||||
parser->GetSize() - parser->GetCursor(),
|
||||
0u
|
||||
);
|
||||
if (gotten_crc != this->m_FileInfo.Crc) {
|
||||
// MARK: report crc error
|
||||
return CKERROR::CKERR_FILECRCERROR;
|
||||
}
|
||||
|
||||
// get save id max
|
||||
parser->Read(&this->m_SaveIDMax, sizeof(int32_t));
|
||||
// get object count and resize
|
||||
parser->Read(&this->m_FileInfo.ObjectCount, sizeof(CKDWORD));
|
||||
if (this->m_FileObject.empty()) {
|
||||
this->m_FileObject.resize(this->m_FileInfo.ObjectCount);
|
||||
// MARK: ZeroMemory removed. i think it is not necessary.
|
||||
}
|
||||
}
|
||||
|
||||
// ========== manager read ==========
|
||||
// only file ver >= 6 have this
|
||||
if (this->m_FileInfo.FileVersion >= 6 && this->m_FileInfo.ManagerCount != 0) {
|
||||
this->m_ManagersData.resize(this->m_FileInfo.ManagerCount);
|
||||
CKDWORD stateChunkLen = 0u;
|
||||
bool stateChkParseSuccess = false;
|
||||
|
||||
for (auto& mgr : this->m_ManagersData) {
|
||||
// read guid
|
||||
parser->Read(&(mgr.Manager), sizeof(CKGUID));
|
||||
|
||||
// read statechunk len
|
||||
parser->Read(&stateChunkLen, sizeof(CKDWORD));
|
||||
// check len
|
||||
if (stateChunkLen == 0) {
|
||||
mgr.Data = nullptr;
|
||||
continue;
|
||||
}
|
||||
// read statechunk
|
||||
mgr.Data = new(std::nothrow) CKStateChunk();
|
||||
if (mgr.Data != nullptr) {
|
||||
stateChkParseSuccess = mgr.Data->ConvertFromBuffer(parser->GetPtr());
|
||||
if (!stateChkParseSuccess) {
|
||||
delete mgr.Data;
|
||||
mgr.Data = nullptr;
|
||||
}
|
||||
}
|
||||
parser->MoveCursor(stateChunkLen);
|
||||
}
|
||||
}
|
||||
|
||||
// ========== object read ==========
|
||||
if (this->m_FileInfo.ObjectCount != 0) {
|
||||
if (this->m_FileInfo.FileVersion >= 4) {
|
||||
// new file reader section
|
||||
CKDWORD stateChunkLen = 0u;
|
||||
bool stateChkParseSuccess = false;
|
||||
for (auto& obj : this->m_FileObject) {
|
||||
if (this->m_FileInfo.FileVersion < 7) {
|
||||
// it seems that file ver < 7, ck id was stored first.
|
||||
parser->Read(&(obj.Object), sizeof(CK_ID));
|
||||
}
|
||||
// get statechunk len
|
||||
parser->Read(&stateChunkLen, sizeof(CKDWORD));
|
||||
|
||||
// if only load behavior and current loaded obj is not behavior, give up.
|
||||
// >= 7 is corresponding with obj header version requirement
|
||||
// so don't worry about this
|
||||
if (EnumHelper::FlagEnumHas(this->m_Flags, CK_LOAD_FLAGS::CK_LOAD_ONLYBEHAVIORS) &&
|
||||
this->m_FileInfo.FileVersion >= 7 &&
|
||||
obj.ObjectCid != CK_CLASSID::CKCID_BEHAVIOR) {
|
||||
// move cursor for next one.
|
||||
parser->MoveCursor(stateChunkLen);
|
||||
continue;
|
||||
}
|
||||
|
||||
// check state chunk len
|
||||
if (stateChunkLen == 0) {
|
||||
obj.Data = nullptr;
|
||||
continue;
|
||||
}
|
||||
// read state chunk
|
||||
obj.Data = new(std::nothrow) CKStateChunk();
|
||||
if (obj.Data != nullptr) {
|
||||
stateChkParseSuccess = obj.Data->ConvertFromBuffer(parser->GetPtr());
|
||||
if (!stateChkParseSuccess) {
|
||||
delete obj.Data;
|
||||
obj.Data = nullptr;
|
||||
} else {
|
||||
// get data size and fill some fields
|
||||
obj.PostPackSize = obj.Data->GetDataSize();
|
||||
obj.PrePackSize = obj.PostPackSize;
|
||||
}
|
||||
}
|
||||
parser->MoveCursor(stateChunkLen);
|
||||
|
||||
}
|
||||
} else {
|
||||
// old file read section
|
||||
for (auto& obj : this->m_FileObject) {
|
||||
// read CK_ID
|
||||
parser->Read(&(obj.Object), sizeof(CK_ID));
|
||||
// get data len
|
||||
CKDWORD dataLen = 0u;
|
||||
parser->Read(&dataLen, sizeof(CKDWORD));
|
||||
|
||||
// check state chunk len
|
||||
if (dataLen == 0) {
|
||||
obj.Data = nullptr;
|
||||
continue;
|
||||
}
|
||||
|
||||
// MARK: set dword_2405F6C0
|
||||
|
||||
// read class id
|
||||
CK_CLASSID clsid = CK_CLASSID::CKCID_OBJECT;
|
||||
parser->Read(&clsid, sizeof(CK_CLASSID));
|
||||
if (static_cast<uint32_t>(clsid) == UINT32_C(0)) {
|
||||
// invalid cid;
|
||||
return CKERROR::CKERR_INVALIDFILE;
|
||||
}
|
||||
|
||||
// read save flags
|
||||
parser->Read(&obj.SaveFlags, sizeof(CK_FILE_WRITEMODE));
|
||||
|
||||
// read statechunk len
|
||||
CKDWORD oldBufLen = 0u;
|
||||
parser->Read(&oldBufLen, sizeof(CKDWORD));
|
||||
|
||||
// setup state chunk and order parse it
|
||||
obj.Data = new(std::nothrow) CKStateChunk(clsid);
|
||||
if (obj.Data != nullptr) {
|
||||
if (!obj.Data->ConvertFromOldBuffer(parser->GetPtr(), oldBufLen, dataLen, obj.SaveFlags)) {
|
||||
delete obj.Data;
|
||||
obj.Data = nullptr;
|
||||
}
|
||||
}
|
||||
// move to next
|
||||
parser->MoveCursor(oldBufLen);
|
||||
}
|
||||
|
||||
// MARK: remove a weird assign: parserSrc = v46; it seems useless.
|
||||
}
|
||||
}
|
||||
|
||||
// ========== object name get ==========
|
||||
// only file ver < 7 need get it from statechunk
|
||||
if (this->m_FileInfo.FileVersion < 7) {
|
||||
for (auto& obj : this->m_FileObject) {
|
||||
if (obj.Data != nullptr) {
|
||||
// TODO: CK_STATESAVE_NAME
|
||||
if (obj.Data->SeekIdentifier(1u)) {
|
||||
obj.Data->ReadString(obj.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ========== included file get ==========
|
||||
// WARN: we use "parserSrc" to read, not "parser"!!!
|
||||
for (size_t i = 0; i < this->m_IncludedFiles.size(); ++i) {
|
||||
// get file name length and resize it
|
||||
CKDWORD filenamelen = 0u;
|
||||
parserSrc->Read(&filenamelen, sizeof(CKDWORD));
|
||||
std::string filename;
|
||||
filename.resize(filenamelen);
|
||||
|
||||
// read filename
|
||||
if (filenamelen != 0) {
|
||||
parserSrc->Read(filename.data(), filenamelen);
|
||||
}
|
||||
|
||||
// todo: construct temp folder path
|
||||
// and regulate file name
|
||||
|
||||
// read file body length
|
||||
CKDWORD filebodylen = 0u;
|
||||
parserSrc->Read(&filebodylen, sizeof(CKDWORD));
|
||||
|
||||
// todo: read file body
|
||||
parserSrc->MoveCursor(filebodylen);
|
||||
}
|
||||
|
||||
// ========== free parser ==========
|
||||
if (parserSrc != parser && parserSrc != nullptr) {
|
||||
// WARN: we should free parserSrc! not free parser
|
||||
// because "parser" has synced with ParserPtr and will be freed from outside.
|
||||
delete parserSrc;
|
||||
|
||||
}
|
||||
|
||||
return CKERROR::CKERR_OK;
|
||||
}
|
||||
|
||||
CKERROR CKFile::LoadFileData(void/*CKObjectArray list*/) {
|
||||
if (!this->m_Parser && !this->m_ReadFileDataDone) {
|
||||
return CKERROR::CKERR_INVALIDFILE;
|
||||
}
|
||||
|
||||
// MARK: sub_240372EA, ctx + 193 = 1
|
||||
|
||||
// if file data has not been read. read it
|
||||
CKERROR err = CKERROR::CKERR_OK;
|
||||
CKBufferParser** ParserPtr = &this->m_Parser;
|
||||
if (!this->m_ReadFileDataDone) {
|
||||
err = this->ReadFileData(ParserPtr);
|
||||
}
|
||||
|
||||
// MARK: i assume FinishLoading do not calling mapped file anymore
|
||||
// free file data
|
||||
if (*ParserPtr != nullptr) {
|
||||
delete *ParserPtr;
|
||||
*ParserPtr = nullptr;
|
||||
}
|
||||
if (this->m_MappedFile != nullptr) {
|
||||
delete this->m_MappedFile;
|
||||
this->m_MappedFile = nullptr;
|
||||
}
|
||||
|
||||
// if no error, do finish loading
|
||||
if (err == CKERROR::CKERR_OK) {
|
||||
this->FinishLoading(this->m_Flags);
|
||||
|
||||
// MARK: dword_2405F6C0 old vt ver output
|
||||
}
|
||||
// MARK: CKContext::SetAutomaticLoadMode
|
||||
// MARK:CKContext::SetUserLoadCallback
|
||||
|
||||
// MARK: sub_24037360
|
||||
// MARK: ctx + 193 = 0
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
CKERROR CKFile::FinishLoading(/*CKObjectArray list, */CK_LOAD_FLAGS flags) {
|
||||
return CKERROR::CKERR_OK;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,205 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "VTUtils.hpp"
|
||||
#include "VTConstants.hpp"
|
||||
#include "VTEncoding.hpp"
|
||||
#include <vector>
|
||||
|
||||
#if defined(LIBCMO_OS_WIN32)
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
namespace LibCmo {
|
||||
|
||||
void* CKUnPackData(CKINT DestSize, const void* SrcBuffer, CKINT SrcSize);
|
||||
CKDWORD CKComputeDataCRC(const void* data, size_t size, CKDWORD PreviousCRC = 0);
|
||||
|
||||
struct CKGUID {
|
||||
union {
|
||||
struct {
|
||||
CKDWORD d1, d2;
|
||||
};
|
||||
CKDWORD d[2];
|
||||
};
|
||||
CKGUID(CKDWORD gd1 = 0, CKDWORD gd2 = 0) { d[0] = gd1; d[1] = gd2; }
|
||||
};
|
||||
|
||||
class VxMemoryMappedFile {
|
||||
private:
|
||||
|
||||
#if defined(LIBCMO_OS_WIN32)
|
||||
std::wstring m_szFilePath;
|
||||
HANDLE m_hFile;
|
||||
DWORD m_dwFileSizeLow, m_dwFileSizeHigh;
|
||||
HANDLE m_hFileMapping;
|
||||
LPVOID m_hFileMapView;
|
||||
#else
|
||||
std::string m_szFilePath;
|
||||
#error NO IMPLEMENTATION FOR LINUX MMAP!
|
||||
#endif
|
||||
|
||||
void* m_pMemoryMappedFileBase;
|
||||
size_t m_cbFile;
|
||||
bool m_bIsValid;
|
||||
public:
|
||||
VxMemoryMappedFile(const char* u8_filepath);
|
||||
VxMemoryMappedFile(const VxMemoryMappedFile&) = delete;
|
||||
VxMemoryMappedFile& operator=(const VxMemoryMappedFile&) = delete;
|
||||
~VxMemoryMappedFile(void);
|
||||
|
||||
inline void* GetBase(void) { return this->m_pMemoryMappedFileBase; }
|
||||
inline size_t GetFileSize(void) { return this->m_cbFile; }
|
||||
inline bool IsValid(void) { return this->m_bIsValid; }
|
||||
};
|
||||
|
||||
class CKBufferParser {
|
||||
private:
|
||||
char* m_MemBegin;
|
||||
size_t m_MemPos;
|
||||
bool m_NeedManualFree;
|
||||
size_t m_MemSize;
|
||||
|
||||
public:
|
||||
CKBufferParser(void* ptr, size_t rsize, bool need_manual_free);
|
||||
CKBufferParser(const CKBufferParser&) = delete;
|
||||
CKBufferParser& operator=(const CKBufferParser&) = delete;
|
||||
~CKBufferParser();
|
||||
|
||||
inline const void* GetPtr(void) { return (this->m_MemBegin + m_MemPos); }
|
||||
inline void Read(void* data, size_t data_size) {
|
||||
memcpy(data, (this->m_MemBegin + m_MemPos), data_size);
|
||||
this->m_MemPos += data_size;
|
||||
}
|
||||
inline void Write(const void* data, size_t data_size) {
|
||||
memcpy((this->m_MemBegin + m_MemPos), data, data_size);
|
||||
this->m_MemPos += data_size;
|
||||
}
|
||||
inline size_t GetSize(void) { return this->m_MemSize; }
|
||||
inline size_t GetCursor(void) { return this->m_MemPos; }
|
||||
inline void MoveCursor(size_t off) { this->m_MemPos += off; }
|
||||
inline void SetCursor(size_t off) { this->m_MemPos = off; }
|
||||
};
|
||||
|
||||
class CKStateChunk {
|
||||
public:
|
||||
CKStateChunk();
|
||||
CKStateChunk(CK_CLASSID clsid);
|
||||
CKStateChunk(const CKStateChunk&) = delete;
|
||||
CKStateChunk& operator=(const CKStateChunk&) = delete;
|
||||
~CKStateChunk();
|
||||
|
||||
bool ConvertFromOldBuffer(const void* buf, CKDWORD buf_size, CKDWORD blk_size, CK_FILE_WRITEMODE mode);
|
||||
bool ConvertFromBuffer(const void* buf);
|
||||
CKDWORD ConvertToBuffer(void* buf);
|
||||
|
||||
bool UnPack(CKDWORD DestSize);
|
||||
CKDWORD GetDataSize(void);
|
||||
|
||||
bool SeekIdentifier(CKDWORD identifier);
|
||||
|
||||
void ReadString(std::string& strl);
|
||||
|
||||
private:
|
||||
CK_CLASSID m_ClassId;
|
||||
CKDWORD m_DataDwSize;
|
||||
CKDWORD* m_pData;
|
||||
|
||||
CK_STATECHUNK_DATAVERSION m_DataVersion;
|
||||
CK_STATECHUNK_CHUNKVERSION m_ChunkVersion;
|
||||
|
||||
struct {
|
||||
CKDWORD m_CurrentPos;
|
||||
CKDWORD m_DataSize;
|
||||
CKDWORD m_PrevIdentifierPos;
|
||||
}m_Parser;
|
||||
|
||||
std::vector<CKDWORD> m_ObjectList;
|
||||
std::vector<CKDWORD> m_ChunkList;
|
||||
std::vector<CKDWORD> m_ManagerList;
|
||||
|
||||
private:
|
||||
void _EnsureEnoughSpace(CKDWORD size);
|
||||
|
||||
};
|
||||
|
||||
struct CKFileInfo {
|
||||
CKDWORD ProductVersion; // Virtools Version (Dev/Creation). (CK_VIRTOOLS_VERSION)
|
||||
CKDWORD ProductBuild; // Virtools Build Number.
|
||||
CK_FILE_WRITEMODE FileWriteMode; // Options used to save this file. (CK_FILE_WRITEMODE)
|
||||
CKDWORD FileVersion; // Version of file format when file was saved.
|
||||
CKDWORD CKVersion; // Version of CK when file was saved.
|
||||
size_t FileSize; // Size of file in bytes.
|
||||
CKDWORD ObjectCount; // Number of objects stored in the file.
|
||||
CKDWORD ManagerCount; // Number of managers which saved data in the file.
|
||||
CKDWORD MaxIDSaved; // Maximum Object identifier saved
|
||||
CKDWORD Crc; // Crc of data
|
||||
CKDWORD Hdr1PackSize; // Reserved
|
||||
CKDWORD Hdr1UnPackSize; // Reserved
|
||||
CKDWORD DataPackSize; // Reserved
|
||||
CKDWORD DataUnPackSize; // Reserved
|
||||
};
|
||||
|
||||
struct CKFileObject {
|
||||
CK_ID Object;
|
||||
CK_ID CreatedObject;
|
||||
CK_CLASSID ObjectCid;
|
||||
void* ObjPtr;
|
||||
std::string Name;
|
||||
CKStateChunk* Data;
|
||||
CKDWORD PostPackSize;
|
||||
CKDWORD PrePackSize;
|
||||
CK_FO_OPTIONS Options;
|
||||
CKDWORD FileIndex;
|
||||
CK_FILE_WRITEMODE SaveFlags;
|
||||
};
|
||||
|
||||
struct CKFileManagerData {
|
||||
CKStateChunk* Data;
|
||||
CKGUID Manager;
|
||||
};
|
||||
|
||||
struct CKFilePluginDependencies {
|
||||
CK_PLUGIN_TYPE m_PluginCategory;
|
||||
XArray<CKGUID> m_Guids;
|
||||
XBitArray ValidGuids;
|
||||
};
|
||||
|
||||
class CKFile {
|
||||
public:
|
||||
CKFile(const Utils::VirtoolsEnvironment& cfg);
|
||||
CKFile(const CKFile&) = delete;
|
||||
CKFile& operator=(const CKFile&) = delete;
|
||||
~CKFile();
|
||||
|
||||
void ClearData(void);
|
||||
CKERROR Load(CKSTRING u8_filename, /*CKObjectArray list, */ CK_LOAD_FLAGS flags);
|
||||
CKERROR OpenFile(CKSTRING u8_filename, CK_LOAD_FLAGS flags);
|
||||
CKERROR OpenMemory(void* MemoryBuffer, size_t BufferSize, CK_LOAD_FLAGS Flags);
|
||||
CKERROR ReadFileHeaders(CKBufferParser** ParserPtr);
|
||||
CKERROR ReadFileData(CKBufferParser** ParserPtr);
|
||||
CKERROR LoadFileData(void/*CKObjectArray list*/);
|
||||
CKERROR FinishLoading(/*CKObjectArray list, */CK_LOAD_FLAGS flags);
|
||||
|
||||
int32_t m_SaveIDMax;
|
||||
XArray<CKFileObject> m_FileObject;
|
||||
XArray<CKFileManagerData> m_ManagersData;
|
||||
XClassArray<CKFilePluginDependencies> m_PluginDep;
|
||||
XClassArray<XIntArray> m_IndexByClassId;
|
||||
XClassArray<XString> m_IncludedFiles;
|
||||
|
||||
CKFileInfo m_FileInfo;
|
||||
|
||||
CK_LOAD_FLAGS m_Flags;
|
||||
std::string m_FileName;
|
||||
CKBufferParser* m_Parser;
|
||||
VxMemoryMappedFile* m_MappedFile;
|
||||
|
||||
bool m_ReadFileDataDone;
|
||||
|
||||
private:
|
||||
Utils::VirtoolsEnvironment m_UserCfg;
|
||||
};
|
||||
|
||||
}
|
|
@ -1,7 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
/*
|
||||
// https://stackoverflow.com/questions/2164827/explicitly-exporting-shared-library-functions-in-linux
|
||||
// generate import export macro
|
||||
|
@ -46,11 +44,7 @@
|
|||
namespace LibCmo {
|
||||
namespace Utils {
|
||||
|
||||
struct VirtoolsEnvironment {
|
||||
std::string NameEncoding;
|
||||
std::string TempFolder;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,44 +1,8 @@
|
|||
#include "VTUtils.hpp"
|
||||
#if defined(LIBCMO_OS_WIN32)
|
||||
#define ZLIB_WINAPI
|
||||
#include <zconf.h>
|
||||
#endif
|
||||
|
||||
#include "VTStruct.hpp"
|
||||
#include <cstdlib>
|
||||
#include <zlib.h>
|
||||
#include "VxMemoryMappedFile.hpp"
|
||||
#include "VTEncoding.hpp"
|
||||
|
||||
namespace LibCmo {
|
||||
|
||||
#pragma region CKZLib Func
|
||||
|
||||
void* CKUnPackData(CKINT DestSize, const void* SrcBuffer, CKINT SrcSize) {
|
||||
char* DestBuffer = new(std::nothrow) char[DestSize];
|
||||
if (DestBuffer == nullptr) return nullptr;
|
||||
|
||||
uLongf cache = DestSize;
|
||||
if (uncompress(
|
||||
reinterpret_cast<Bytef*>(DestBuffer), &cache,
|
||||
reinterpret_cast<const Bytef*>(SrcBuffer), SrcSize) != Z_OK) {
|
||||
delete[] DestBuffer;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return DestBuffer;
|
||||
}
|
||||
|
||||
CKDWORD LibCmo::CKComputeDataCRC(const void* data, size_t size, CKDWORD PreviousCRC) {
|
||||
return static_cast<CKDWORD>(adler32(
|
||||
static_cast<uLong>(PreviousCRC),
|
||||
reinterpret_cast<const Bytef*>(data),
|
||||
static_cast<uInt>(size)
|
||||
));
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region VxMemoryMappedFile
|
||||
|
||||
VxMemoryMappedFile::VxMemoryMappedFile(const char* u8_filepath) :
|
||||
// init members
|
||||
#if defined(LIBCMO_OS_WIN32)
|
||||
|
@ -136,54 +100,5 @@ namespace LibCmo {
|
|||
}
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region CKBufferParser
|
||||
|
||||
CKBufferParser::CKBufferParser(void* ptr, size_t rsize, bool need_manual_free) :
|
||||
m_MemBegin(static_cast<char*>(ptr)),
|
||||
m_MemPos(0u), m_MemSize(rsize),
|
||||
m_NeedManualFree(need_manual_free) {
|
||||
;
|
||||
}
|
||||
CKBufferParser::~CKBufferParser() {
|
||||
if (this->m_NeedManualFree) delete[](this->m_MemBegin);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region CKFile Misc
|
||||
|
||||
CKFile::CKFile(const Utils::VirtoolsEnvironment& cfg) :
|
||||
m_Parser(nullptr), m_MappedFile(nullptr),
|
||||
m_UserCfg(cfg) {
|
||||
;
|
||||
}
|
||||
|
||||
CKFile::~CKFile() {
|
||||
}
|
||||
|
||||
|
||||
void CKFile::ClearData(void) {
|
||||
m_SaveIDMax = 0;
|
||||
m_FileObject.clear();
|
||||
m_PluginDep.clear();
|
||||
|
||||
memset(&m_FileInfo, 0, sizeof(CKFileInfo));
|
||||
|
||||
m_Flags = CK_LOAD_FLAGS::CK_LOAD_DEFAULT;
|
||||
m_FileName.clear();
|
||||
if (m_Parser != nullptr) {
|
||||
delete m_Parser;
|
||||
m_Parser = nullptr;
|
||||
}
|
||||
if (m_MappedFile != nullptr) {
|
||||
delete m_MappedFile;
|
||||
m_MappedFile = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
|
||||
}
|
42
LibCmo/VxMemoryMappedFile.hpp
Normal file
42
LibCmo/VxMemoryMappedFile.hpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
#pragma once
|
||||
|
||||
#include "VTUtils.hpp"
|
||||
#if defined(LIBCMO_OS_WIN32)
|
||||
#include <Windows.h>
|
||||
#else
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace LibCmo {
|
||||
|
||||
class VxMemoryMappedFile {
|
||||
private:
|
||||
|
||||
#if defined(LIBCMO_OS_WIN32)
|
||||
std::wstring m_szFilePath;
|
||||
HANDLE m_hFile;
|
||||
DWORD m_dwFileSizeLow, m_dwFileSizeHigh;
|
||||
HANDLE m_hFileMapping;
|
||||
LPVOID m_hFileMapView;
|
||||
#else
|
||||
std::string m_szFilePath;
|
||||
#error NO IMPLEMENTATION FOR LINUX MMAP!
|
||||
#endif
|
||||
|
||||
void* m_pMemoryMappedFileBase;
|
||||
size_t m_cbFile;
|
||||
bool m_bIsValid;
|
||||
public:
|
||||
VxMemoryMappedFile(const char* u8_filepath);
|
||||
VxMemoryMappedFile(const VxMemoryMappedFile&) = delete;
|
||||
VxMemoryMappedFile& operator=(const VxMemoryMappedFile&) = delete;
|
||||
~VxMemoryMappedFile(void);
|
||||
|
||||
inline void* GetBase(void) { return this->m_pMemoryMappedFileBase; }
|
||||
inline size_t GetFileSize(void) { return this->m_cbFile; }
|
||||
inline bool IsValid(void) { return this->m_bIsValid; }
|
||||
};
|
||||
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <VTConstants.hpp>
|
||||
#include <CKEnums.hpp>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
|
@ -42,7 +42,7 @@ namespace Unvirt {
|
|||
}
|
||||
|
||||
// check flag match
|
||||
if (LibCmo::EnumHelper::FlagEnumHas(val, (*it).first)) {
|
||||
if (LibCmo::EnumsHelper::FlagEnumHas(val, (*it).first)) {
|
||||
// matched, add it
|
||||
if (strl.size() != 0u) strl += ", ";
|
||||
strl += (*it).second;
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#include <unordered_map>
|
||||
#include <stdexcept>
|
||||
#include "VTUtils.hpp"
|
||||
#include "VTStruct.hpp"
|
||||
|
||||
/*
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "VTStruct.hpp"
|
||||
#include <CKFile.hpp>
|
||||
|
||||
namespace Unvirt {
|
||||
namespace StructFormatter {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "AccessibleValue.hpp"
|
||||
#include "TerminalHelper.hpp"
|
||||
#include "StructFormatter.hpp"
|
||||
#include "VTStruct.hpp"
|
||||
#include "CKFile.hpp"
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
|
||||
|
@ -9,11 +9,12 @@ int main(int argc, char* argv[]) {
|
|||
Unvirt::TerminalHelper::EnsureTerminalColor();
|
||||
Unvirt::TerminalHelper::EnsureTerminalEncoding();
|
||||
|
||||
LibCmo::Utils::VirtoolsEnvironment vtctx;
|
||||
LibCmo::CKFile vtfile(vtctx);
|
||||
LibCmo::CKERROR err = vtfile.Load("vt2obj.nms", LibCmo::CK_LOAD_FLAGS::CK_LOAD_DEFAULT);
|
||||
LibCmo::CKMinContext vtctx;
|
||||
LibCmo::CKFile vtfile(&vtctx);
|
||||
LibCmo::CKFileData::ShallowDocument* doc;
|
||||
LibCmo::CKERROR err = vtfile.ShallowLoad("Language.old.nmo", &doc);
|
||||
|
||||
Unvirt::StructFormatter::PrintCKFileInfo(vtfile.m_FileInfo);
|
||||
Unvirt::StructFormatter::PrintCKFileInfo(doc->m_FileInfo);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -116,7 +116,7 @@ int main() {
|
|||
CKCID_MESH,
|
||||
CKCID_PATCHMESH,
|
||||
CKCID_RENDEROBJECT,
|
||||
CKCID_3DENTITY,
|
||||
CKCID_2DENTITY,
|
||||
CKCID_SPRITE,
|
||||
CKCID_SPRITETEXT,
|
||||
CKCID_3DENTITY,
|
||||
|
@ -169,7 +169,7 @@ int main() {
|
|||
"CKCID_MESH",
|
||||
"CKCID_PATCHMESH",
|
||||
"CKCID_RENDEROBJECT",
|
||||
"CKCID_3DENTITY",
|
||||
"CKCID_2DENTITY",
|
||||
"CKCID_SPRITE",
|
||||
"CKCID_SPRITETEXT",
|
||||
"CKCID_3DENTITY",
|
||||
|
|
Loading…
Reference in New Issue
Block a user