write other CKStateChunk writer and remove sub chunk function

This commit is contained in:
yyc12345 2023-09-24 13:55:41 +08:00
parent 3e265cdf1d
commit 6870fca911
5 changed files with 222 additions and 133 deletions

View File

@ -326,7 +326,7 @@ namespace LibCmo::CK2 {
CKDWORD CKFileVisitor::GetIndexByObjectID(CK_ID objid) {
// see CKFile::SaveFindObjectIndex in IDA
CKDWORD idx = -1;
CKDWORD idx = static_cast<CKDWORD>(-1);
if (m_IsReader) return idx;
auto finder = m_Writer->m_ObjectsHashTable.find(objid);

View File

@ -232,6 +232,29 @@ namespace LibCmo::CK2 {
*/
bool EnsureReadSpace(CKDWORD dword_required);
/**
* @brief The helper writer of m_ObjectList, m_ManagerList and m_ChunkList.
*
* Add a position indicator into list which represent a single data.
*
* @param entry_ls[in] The list to be written.
* @param pos[int] The written position data.
* @remark:
* + IntList::AddEntry() redirect to this.
*/
void AddEntry(XContainer::XArray<CKDWORD>& entry_ls, CKDWORD pos);
/**
* @brief The helper writer of m_ObjectList, m_ManagerList and m_ChunkList.
*
* Add a position indicator into list which represent a series of data.
*
* @param entry_ls[in] The list to be written.
* @param pos[int] The written position data.
* @remark:
* + IntList::AddEntries() redirect to this.
*/
void AddEntries(XContainer::XArray<CKDWORD>& entry_ls, CKDWORD pos);
#pragma endregion
#pragma region Read Function
@ -368,12 +391,12 @@ namespace LibCmo::CK2 {
return ReadManagerInt(&guid, &intval);
}
/**
* @brief Read sub chunk
* @return Returned a new created of CKStateChunk if success, otherwise nullptr.
* Returned CKStateChunk should be manually released!
*/
CKStateChunk* ReadSubChunk();
///**
// * @brief Read sub chunk
// * @return Returned a new created of CKStateChunk if success, otherwise nullptr.
// * Returned CKStateChunk should be manually released!
//*/
//CKStateChunk* ReadSubChunk();
/* ========== Buffer Functions ==========*/
@ -480,17 +503,17 @@ namespace LibCmo::CK2 {
return ReadManagerIntSequence(&guid, &ls);
}
/// <summary>
/// Read Sub Chunk Sequence
/// <para>The combination using of StartReadSequence() and ReadSubChunk() redirect to this.</para>
/// <para>The item of returned CKStateChunk* list should be manually released!</para>
/// </summary>
/// <param name="ls"></param>
/// <returns></returns>
bool ReadSubChunkSequence(XContainer::XArray<CKStateChunk*>* ls);
inline bool ReadSubChunkSequence(XContainer::XArray<CKStateChunk*>& ls) {
return ReadSubChunkSequence(&ls);
}
///// <summary>
///// Read Sub Chunk Sequence
///// <para>The combination using of StartReadSequence() and ReadSubChunk() redirect to this.</para>
///// <para>The item of returned CKStateChunk* list should be manually released!</para>
///// </summary>
///// <param name="ls"></param>
///// <returns></returns>
//bool ReadSubChunkSequence(XContainer::XArray<CKStateChunk*>* ls);
//inline bool ReadSubChunkSequence(XContainer::XArray<CKStateChunk*>& ls) {
// return ReadSubChunkSequence(&ls);
//}
/**
* @brief Read Object Array (actually still is CK_ID)
@ -601,7 +624,7 @@ namespace LibCmo::CK2 {
public:
bool WriteObjectIDSequence(const XContainer::XObjectArray* ls);
inline bool ReadObjectIDSequence(const XContainer::XObjectArray& ls) {
inline bool WriteObjectIDSequence(const XContainer::XObjectArray& ls) {
return WriteObjectIDSequence(&ls);
}

View File

@ -303,6 +303,14 @@ namespace LibCmo::CK2 {
(this->m_Parser.m_CurrentPos + dword_required <= this->m_Parser.m_DataSize);
}
void CKStateChunk::AddEntry(XContainer::XArray<CKDWORD>& entry_ls, CKDWORD pos) {
entry_ls.emplace_back(pos);
}
void CKStateChunk::AddEntries(XContainer::XArray<CKDWORD>& entry_ls, CKDWORD pos) {
entry_ls.emplace_back(static_cast<CKDWORD>(-1));
entry_ls.emplace_back(pos);
}
#pragma endregion

View File

@ -205,98 +205,98 @@ namespace LibCmo::CK2 {
return true;
}
CKStateChunk* CKStateChunk::ReadSubChunk(void) {
CKStateChunk* subchunk = nullptr;
//CKStateChunk* CKStateChunk::ReadSubChunk(void) {
// CKStateChunk* subchunk = nullptr;
// get size and do a enough space check
CKDWORD subDwordChunkSize;
if (!this->ReadStruct(subDwordChunkSize)) goto subchunk_defer;
if (!this->EnsureReadSpace(subDwordChunkSize)) goto subchunk_defer;
// // get size and do a enough space check
// CKDWORD subDwordChunkSize;
// if (!this->ReadStruct(subDwordChunkSize)) goto subchunk_defer;
// if (!this->EnsureReadSpace(subDwordChunkSize)) goto subchunk_defer;
// create statechunk
subchunk = new CKStateChunk(this->m_BindFile, this->m_BindContext);
// // create statechunk
// subchunk = new CKStateChunk(this->m_BindFile, this->m_BindContext);
// start read data
// read class id
if (!this->ReadStruct(subchunk->m_ClassId)) goto subchunk_defer;
// // start read data
// // read class id
// if (!this->ReadStruct(subchunk->m_ClassId)) goto subchunk_defer;
// different read strategy by chunk version
if (this->m_ChunkVersion >= CK_STATECHUNK_CHUNKVERSION::CHUNK_VERSION1) {
// new file
// // different read strategy by chunk version
// if (this->m_ChunkVersion >= CK_STATECHUNK_CHUNKVERSION::CHUNK_VERSION1) {
// // new file
// read combined version
CKDWORD versionInfo;
if (!this->ReadStruct(versionInfo)) goto subchunk_defer;
subchunk->m_DataVersion = static_cast<CK_STATECHUNK_DATAVERSION>(versionInfo & 0xffff);
subchunk->m_ChunkVersion = static_cast<CK_STATECHUNK_CHUNKVERSION>((versionInfo >> 16) & 0xffff);
// // read combined version
// CKDWORD versionInfo;
// if (!this->ReadStruct(versionInfo)) goto subchunk_defer;
// subchunk->m_DataVersion = static_cast<CK_STATECHUNK_DATAVERSION>(versionInfo & 0xffff);
// subchunk->m_ChunkVersion = static_cast<CK_STATECHUNK_CHUNKVERSION>((versionInfo >> 16) & 0xffff);
// read data size and create it
if (!this->ReadStruct(subchunk->m_DataDwSize)) goto subchunk_defer;
subchunk->m_pData = new CKDWORD[subchunk->m_DataDwSize];
// // read data size and create it
// if (!this->ReadStruct(subchunk->m_DataDwSize)) goto subchunk_defer;
// subchunk->m_pData = new CKDWORD[subchunk->m_DataDwSize];
// has bind file?
CKDWORD hasBindFile;
if (!this->ReadStruct(hasBindFile)) goto subchunk_defer;
if (hasBindFile == 1) subchunk->m_BindFile = nullptr;
// // has bind file?
// CKDWORD hasBindFile;
// if (!this->ReadStruct(hasBindFile)) goto subchunk_defer;
// if (hasBindFile == 1) subchunk->m_BindFile = nullptr;
// 3 list size
// manager only existed when ver > 4
CKDWORD lssize;
if (!this->ReadStruct(lssize)) goto subchunk_defer;
subchunk->m_ObjectList.resize(lssize);
if (!this->ReadStruct(lssize)) goto subchunk_defer;
subchunk->m_ChunkList.resize(lssize);
if (this->m_ChunkVersion > CK_STATECHUNK_CHUNKVERSION::CHUNK_VERSION1) {
if (!this->ReadStruct(lssize)) goto subchunk_defer;
subchunk->m_ManagerList.resize(lssize);
}
// // 3 list size
// // manager only existed when ver > 4
// CKDWORD lssize;
// if (!this->ReadStruct(lssize)) goto subchunk_defer;
// subchunk->m_ObjectList.resize(lssize);
// if (!this->ReadStruct(lssize)) goto subchunk_defer;
// subchunk->m_ChunkList.resize(lssize);
// if (this->m_ChunkVersion > CK_STATECHUNK_CHUNKVERSION::CHUNK_VERSION1) {
// if (!this->ReadStruct(lssize)) goto subchunk_defer;
// subchunk->m_ManagerList.resize(lssize);
// }
// core data
if (subchunk->m_DataDwSize != 0) {
if (!this->ReadByteData(subchunk->m_pData, subchunk->m_DataDwSize * CKSizeof(CKDWORD))) goto subchunk_defer;
}
// // core data
// if (subchunk->m_DataDwSize != 0) {
// if (!this->ReadByteData(subchunk->m_pData, subchunk->m_DataDwSize * CKSizeof(CKDWORD))) goto subchunk_defer;
// }
// 3 list data
if (!subchunk->m_ObjectList.empty()) {
if (!this->ReadByteData(
subchunk->m_ObjectList.data(),
static_cast<CKDWORD>(subchunk->m_ObjectList.size()) * CKSizeof(CKDWORD)
)) goto subchunk_defer;
}
if (!subchunk->m_ChunkList.empty()) {
if (!this->ReadByteData(
subchunk->m_ChunkList.data(),
static_cast<CKDWORD>(subchunk->m_ChunkList.size()) * CKSizeof(CKDWORD)
)) goto subchunk_defer;
}
if (!subchunk->m_ManagerList.empty()) {
if (!this->ReadByteData(
subchunk->m_ManagerList.data(),
static_cast<CKDWORD>(subchunk->m_ManagerList.size()) * CKSizeof(CKDWORD)
)) goto subchunk_defer;
}
// // 3 list data
// if (!subchunk->m_ObjectList.empty()) {
// if (!this->ReadByteData(
// subchunk->m_ObjectList.data(),
// static_cast<CKDWORD>(subchunk->m_ObjectList.size()) * CKSizeof(CKDWORD)
// )) goto subchunk_defer;
// }
// if (!subchunk->m_ChunkList.empty()) {
// if (!this->ReadByteData(
// subchunk->m_ChunkList.data(),
// static_cast<CKDWORD>(subchunk->m_ChunkList.size()) * CKSizeof(CKDWORD)
// )) goto subchunk_defer;
// }
// if (!subchunk->m_ManagerList.empty()) {
// if (!this->ReadByteData(
// subchunk->m_ManagerList.data(),
// static_cast<CKDWORD>(subchunk->m_ManagerList.size()) * CKSizeof(CKDWORD)
// )) goto subchunk_defer;
// }
} else {
// old file
// } else {
// // old file
// read data size and create it
if (!this->ReadStruct(subchunk->m_DataDwSize)) goto subchunk_defer;
subchunk->m_pData = new CKDWORD[subchunk->m_DataDwSize];
// // read data size and create it
// if (!this->ReadStruct(subchunk->m_DataDwSize)) goto subchunk_defer;
// subchunk->m_pData = new CKDWORD[subchunk->m_DataDwSize];
// skip one?
// I don't know why
this->Skip(1u);
// // skip one?
// // I don't know why
// this->Skip(1u);
// read core buf
if (!this->ReadByteData(subchunk->m_pData, subchunk->m_DataDwSize * CKSizeof(CKDWORD))) goto subchunk_defer;
// // read core buf
// if (!this->ReadByteData(subchunk->m_pData, subchunk->m_DataDwSize * CKSizeof(CKDWORD))) goto subchunk_defer;
}
// }
return subchunk;
subchunk_defer:
if (subchunk != nullptr) delete subchunk;
return nullptr;
}
// return subchunk;
//subchunk_defer:
// if (subchunk != nullptr) delete subchunk;
// return nullptr;
//}
/* ========== Buffer Functions ==========*/
@ -427,38 +427,38 @@ namespace LibCmo::CK2 {
return true;
}
bool CKStateChunk::ReadSubChunkSequence(XContainer::XArray<CKStateChunk*>* ls) {
if (ls == nullptr) return false;
//bool CKStateChunk::ReadSubChunkSequence(XContainer::XArray<CKStateChunk*>* ls) {
// if (ls == nullptr) return false;
// clear first
for (auto& item : *ls) {
if (item != nullptr)
delete (item);
}
ls->clear();
// // clear first
// for (auto& item : *ls) {
// if (item != nullptr)
// delete (item);
// }
// ls->clear();
// read count
CKDWORD count;
if (!this->ReadStruct(count)) return false;
// // read count
// CKDWORD count;
// if (!this->ReadStruct(count)) return false;
// resize list and read it
ls->resize(count, nullptr);
for (size_t i = 0; i < count; ++i) {
(*ls)[i] = this->ReadSubChunk();
if ((*ls)[i] == nullptr) {
// fail. remove all created statechunk and clear it
for (auto& item : *ls) {
if (item != nullptr)
delete (item);
}
ls->clear();
// return
return false;
}
}
// // resize list and read it
// ls->resize(count, nullptr);
// for (size_t i = 0; i < count; ++i) {
// (*ls)[i] = this->ReadSubChunk();
// if ((*ls)[i] == nullptr) {
// // fail. remove all created statechunk and clear it
// for (auto& item : *ls) {
// if (item != nullptr)
// delete (item);
// }
// ls->clear();
// // return
// return false;
// }
// }
return true;
}
// return true;
//}
bool CKStateChunk::ReadXObjectArray(XContainer::XObjectArray* ls) {
if (ls == nullptr) return false;

View File

@ -3,6 +3,22 @@
#include "CKContext.hpp"
#include "ObjImpls/CKObject.hpp"
/*
Memorandum:
No need to write any data in m_ObjectList when writing Object ID.
Because m_ObjectList only need to be written in when no bind CKFile
according to IDA reversed code.
However we assuem all CKStateChunk have bind file so no need to treat it.
However, m_ManagerList should be filled when writing Manager Int.
This is also instructed by IDA revsersed code.
For m_ChunkList, it is same as m_ManagerList. We need write it.
*/
namespace LibCmo::CK2 {
void CKStateChunk::StartWrite() {
@ -129,7 +145,7 @@ namespace LibCmo::CK2 {
}
bool CKStateChunk::WriteString(const XContainer::XString* strl) {
if (strl == nullptr) return;
if (strl == nullptr) return false;
// convert encoding
XContainer::XString cache;
@ -156,17 +172,15 @@ namespace LibCmo::CK2 {
}
bool CKStateChunk::WriteObjectPointer(ObjImpls::CKObject* obj) {
CK_ID objid;
if (obj != nullptr) {
objid = obj->GetID();
}
CK_ID objid = 0;
if (obj != nullptr) objid = obj->GetID();
return WriteObjectID(objid);
}
bool CKStateChunk::WriteManagerInt(const CKGUID* guid, CKINT intval) {
// push into manager list
m_ManagerList.emplace_back(m_Parser.m_CurrentPos);
AddEntry(m_ManagerList, m_Parser.m_CurrentPos);
// write data
if (!this->WriteStruct(guid)) return false;
if (!this->WriteStruct(intval)) return false;
@ -207,19 +221,63 @@ namespace LibCmo::CK2 {
/* ========== Sequence Functions ==========*/
bool CKStateChunk::WriteObjectIDSequence(const XContainer::XObjectArray* ls) {
return false;
if (ls == nullptr) return false;
// MARK: there is a recording oper for object list when no bind file.
// but we always have bind file, so ignore it
// write size first
CKDWORD objidsize = static_cast<CKDWORD>(ls->size());
if (!this->WriteStruct(objidsize)) return false;
// write each data
for (auto objid : *ls) {
// MARK: originally we should not call WriteObjectID like ReadObjectIDSequence.
// because we do not write position data in obj list for each item.
// even if bind file always is not nullptr.
if (!this->WriteStruct(m_BindFile->GetIndexByObjectID(objid))) return false;
}
return true;
}
bool CKStateChunk::WriteManagerIntSequence(const CKGUID* guid, const XContainer::XArray<CKINT>* ls) {
return false;
if (guid == nullptr || ls == nullptr) return false;
// add current pos into manager list
AddEntries(m_ManagerList, m_Parser.m_CurrentPos);
// write data length
CKDWORD lssize = static_cast<CKDWORD>(ls->size());
if (!this->WriteStruct(lssize)) return false;
// write guid
if (!this->WriteStruct(guid)) return false;
// then write each items
for (auto iv : *ls) {
// MARK: we should not call WriteManagerInt like ReadManagerIntSequence.
// because we do not want to write postion info into manager list for each item.
if (!this->WriteStruct(iv)) return false;
}
return true;
}
bool CKStateChunk::WriteXObjectArray(const XContainer::XObjectArray* ls) {
return false;
// same as WriteObjectIDSequence.
return WriteObjectIDSequence(ls);
}
bool CKStateChunk::WriteXObjectPointerArray(const XContainer::XObjectPointerArray* ls) {
return false;
if (ls == nullptr) return false;
XContainer::XObjectArray conv;
for (auto obj : *ls) {
if (obj == nullptr) conv.emplace_back(0);
else conv.emplace_back(obj->GetID());
}
return WriteObjectIDSequence(conv);
}
}