update shit

This commit is contained in:
yyc12345 2023-02-17 15:53:24 +08:00
parent 427c9ee06f
commit 522660e65a
4 changed files with 227 additions and 6 deletions

View File

@ -169,7 +169,7 @@ namespace LibCmo {
dep.ValidGuids.resize(guid_size);
// read data
if (guid_size != 0) {
parser->Read(dep.m_Guids.data(), sizeof(CKGUID)* guid_size);
parser->Read(dep.m_Guids.data(), sizeof(CKGUID) * guid_size);
}
// extra load flag
@ -277,7 +277,140 @@ namespace LibCmo {
}
// ========== 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);
}
}
}
// ========== 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);
}
}
}
}
return CKERROR::CKERR_OK;
}

View File

@ -1,3 +1,10 @@
#include "VTUtils.hpp"
#if defined(LIBCMO_OS_WIN32)
#define ZLIB_WINAPI
#include <zconf.h>
#endif
#include <zlib.h>;
#include "VTStruct.hpp"
namespace LibCmo {
@ -10,12 +17,46 @@ namespace LibCmo {
{
;
}
LibCmo::CKStateChunk::CKStateChunk(CK_CLASSID clsid) :
m_ClassId(clsid), m_DataDwSize(0u), m_pData(nullptr),
m_DataVersion(CK_STATECHUNK_DATAVERSION::CHUNKDATA_CURRENTVERSION), m_ChunkVersion(CK_STATECHUNK_CHUNKVERSION::CHUNK_VERSION4),
m_Parser{ 0u, 0u, 0u },
m_ObjectList(), m_ChunkList(), m_ManagerList()
{
;
}
CKStateChunk::~CKStateChunk() {
if (this->m_pData != nullptr)
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;
@ -149,6 +190,39 @@ namespace LibCmo {
return 0u;
}
bool CKStateChunk::SeekIdentifier(CKDWORD identifier) {
return false;
}
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);
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;
}
void LibCmo::CKStateChunk::_EnsureEnoughSpace(CKDWORD size) {
;
}

View File

@ -1,7 +1,7 @@
#include "VTUtils.hpp"
#if defined(LIBCMO_OS_WIN32)
#define ZLIB_WINAPI
#include "zconf.h"
#include <zconf.h>
#endif
#include "VTStruct.hpp"

View File

@ -85,13 +85,22 @@ 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;
@ -138,7 +147,7 @@ namespace LibCmo {
CK_CLASSID ObjectCid;
void* ObjPtr;
std::string Name;
void* Data;
CKStateChunk* Data;
CKDWORD PostPackSize;
CKDWORD PrePackSize;
CK_FO_OPTIONS Options;
@ -146,6 +155,11 @@ namespace LibCmo {
CK_FILE_WRITEMODE SaveFlags;
};
struct CKFileManagerData {
CKStateChunk* Data;
CKGUID Manager;
};
struct CKFilePluginDependencies {
CK_PLUGIN_TYPE m_PluginCategory;
XArray<CKGUID> m_Guids;
@ -170,7 +184,7 @@ namespace LibCmo {
int32_t m_SaveIDMax;
XArray<CKFileObject> m_FileObject;
//XArray<CKFileManagerData> m_ManagersData;
XArray<CKFileManagerData> m_ManagersData;
XClassArray<CKFilePluginDependencies> m_PluginDep;
XClassArray<XIntArray> m_IndexByClassId;
XClassArray<XString> m_IncludedFiles;