update CKStateChunk
This commit is contained in:
parent
0519a557b8
commit
00a7e041c6
|
@ -26,6 +26,7 @@ namespace LibCmo {
|
||||||
using XIntArray = std::vector<int32_t>;
|
using XIntArray = std::vector<int32_t>;
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using XClassArray = std::vector<T>;
|
using XClassArray = std::vector<T>;
|
||||||
|
using XObjectArray = std::vector<CK_ID>;
|
||||||
//using CKObjectArray = std::vector<CKObject*>;
|
//using CKObjectArray = std::vector<CKObject*>;
|
||||||
|
|
||||||
|
|
||||||
|
@ -131,6 +132,39 @@ namespace LibCmo {
|
||||||
VxMatrix(float m[4][4]) : m_Data() { std::memcpy(m_Data, m, sizeof(m_Data)); }
|
VxMatrix(float m[4][4]) : m_Data() { std::memcpy(m_Data, m, sizeof(m_Data)); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct VxImageDescEx {
|
||||||
|
CK2::CKINT Size;
|
||||||
|
CK2::CKDWORD Flags;
|
||||||
|
|
||||||
|
CK2::CKINT Width;
|
||||||
|
CK2::CKINT Height;
|
||||||
|
union {
|
||||||
|
CK2::CKINT BytesPerLine;
|
||||||
|
CK2::CKINT TotalImageSize;
|
||||||
|
};
|
||||||
|
CK2::CKINT BitsPerPixel;
|
||||||
|
union {
|
||||||
|
CK2::CKDWORD RedMask;
|
||||||
|
CK2::CKDWORD BumpDuMask;
|
||||||
|
};
|
||||||
|
union {
|
||||||
|
CK2::CKDWORD GreenMask;
|
||||||
|
CK2::CKDWORD BumpDvMask;
|
||||||
|
};
|
||||||
|
union {
|
||||||
|
CK2::CKDWORD BlueMask;
|
||||||
|
CK2::CKDWORD BumpLumMask;
|
||||||
|
|
||||||
|
};
|
||||||
|
CK2::CKDWORD AlphaMask;
|
||||||
|
|
||||||
|
CK2::CKWORD BytesPerColorEntry;
|
||||||
|
CK2::CKWORD ColorMapEntries;
|
||||||
|
|
||||||
|
CK2::CKBYTE* ColorMap;
|
||||||
|
CK2::CKBYTE* Image;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,7 @@ namespace LibCmo::CK2 {
|
||||||
m_ClassId(rhs.m_ClassId), m_DataVersion(rhs.m_DataVersion), m_ChunkVersion(rhs.m_ChunkVersion),
|
m_ClassId(rhs.m_ClassId), m_DataVersion(rhs.m_DataVersion), m_ChunkVersion(rhs.m_ChunkVersion),
|
||||||
m_Parser(rhs.m_Parser),
|
m_Parser(rhs.m_Parser),
|
||||||
m_ObjectList(rhs.m_ObjectList), m_ManagerList(rhs.m_ManagerList), m_ChunkList(rhs.m_ChunkList),
|
m_ObjectList(rhs.m_ObjectList), m_ManagerList(rhs.m_ManagerList), m_ChunkList(rhs.m_ChunkList),
|
||||||
m_pData(nullptr), m_DataDwSize(rhs.m_DataDwSize)
|
m_pData(nullptr), m_DataDwSize(rhs.m_DataDwSize) {
|
||||||
{
|
|
||||||
// copy buffer
|
// copy buffer
|
||||||
if (rhs.m_pData != nullptr) {
|
if (rhs.m_pData != nullptr) {
|
||||||
this->m_pData = new(std::nothrow) CKDWORD[rhs.m_DataDwSize];
|
this->m_pData = new(std::nothrow) CKDWORD[rhs.m_DataDwSize];
|
||||||
|
@ -62,8 +61,8 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
void CKStateChunk::Clear(void) {
|
void CKStateChunk::Clear(void) {
|
||||||
this->m_ClassId = CK_CLASSID::CKCID_OBJECT;
|
this->m_ClassId = CK_CLASSID::CKCID_OBJECT;
|
||||||
//this->m_DataVersion = CK_STATECHUNK_DATAVERSION::CHUNK_DEV_2_1;
|
this->m_DataVersion = CK_STATECHUNK_DATAVERSION::CHUNK_DEV_2_1;
|
||||||
//this->m_ChunkVersion = CK_STATECHUNK_CHUNKVERSION::CHUNK_VERSION4;
|
this->m_ChunkVersion = CK_STATECHUNK_CHUNKVERSION::CHUNK_VERSION4;
|
||||||
|
|
||||||
this->m_Parser.m_CurrentPos = 0;
|
this->m_Parser.m_CurrentPos = 0;
|
||||||
this->m_Parser.m_DataSize = 0;
|
this->m_Parser.m_DataSize = 0;
|
||||||
|
@ -84,8 +83,82 @@ namespace LibCmo::CK2 {
|
||||||
return sizeof(CKDWORD) * this->m_DataDwSize;
|
return sizeof(CKDWORD) * this->m_DataDwSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKStateChunk::_EnsureWriteSpace(CKDWORD size) {
|
CK_STATECHUNK_DATAVERSION CKStateChunk::GetDataVersion() {
|
||||||
;
|
return this->m_DataVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CKStateChunk::SetDataVersion(CK_STATECHUNK_DATAVERSION version) {
|
||||||
|
this->m_DataVersion = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CKStateChunk::EnsureReadSpace(CKDWORD dword_required) {
|
||||||
|
return (m_Parser.m_Status == CKStateChunkStatus::READ) &&
|
||||||
|
(this->m_Parser.m_CurrentPos + dword_required <= this->m_Parser.m_DataSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CKStateChunk::ResizeBuffer(CKDWORD new_dwsize) {
|
||||||
|
if (new_dwsize == 0u) {
|
||||||
|
// if reuqired size is zero, we just delete it
|
||||||
|
if (this->m_pData != nullptr) {
|
||||||
|
delete[] this->m_pData;
|
||||||
|
this->m_pData = nullptr;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// otherwise, we create a new buffer instead it
|
||||||
|
CKDWORD* newbuf = new(std::nothrow) CKDWORD[new_dwsize];
|
||||||
|
if (newbuf == nullptr) return false; // if fail to create, return
|
||||||
|
|
||||||
|
// if no original data, we do not need copy it and free it
|
||||||
|
if (this->m_pData != nullptr) {
|
||||||
|
std::memcpy(newbuf, this->m_pData, sizeof(CKDWORD) * new_dwsize);
|
||||||
|
delete[] this->m_pData;
|
||||||
|
}
|
||||||
|
|
||||||
|
// assign new buffer
|
||||||
|
this->m_pData = newbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CKStateChunk::EnsureWriteSpace(CKDWORD dwsize) {
|
||||||
|
if (this->m_Parser.m_Status != CKStateChunkStatus::WRITE) return false;
|
||||||
|
|
||||||
|
// check whether need enlarge
|
||||||
|
CKDWORD needed = dwsize + this->m_Parser.m_CurrentPos;
|
||||||
|
if (needed > this->m_Parser.m_DataSize) {
|
||||||
|
// add a very enough space to buffer
|
||||||
|
if (dwsize < 512) dwsize = 512;
|
||||||
|
needed = dwsize + this->m_Parser.m_CurrentPos;
|
||||||
|
|
||||||
|
// try resizing it
|
||||||
|
this->ResizeBuffer(needed);
|
||||||
|
|
||||||
|
// update size
|
||||||
|
this->m_Parser.m_DataSize = needed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CKStateChunk::Skip(CKDWORD DwordCount) {
|
||||||
|
bool result;
|
||||||
|
switch (this->m_Parser.m_Status) {
|
||||||
|
case CKStateChunkStatus::READ:
|
||||||
|
result = EnsureReadSpace(DwordCount);
|
||||||
|
break;
|
||||||
|
case CKStateChunkStatus::WRITE:
|
||||||
|
result = EnsureWriteSpace(DwordCount);
|
||||||
|
break;
|
||||||
|
case CKStateChunkStatus::IDLE:
|
||||||
|
default:
|
||||||
|
result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if success, move cursor
|
||||||
|
if (result) {
|
||||||
|
this->m_Parser.m_CurrentPos += DwordCount;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -258,9 +331,7 @@ namespace LibCmo::CK2 {
|
||||||
// return true;
|
// return true;
|
||||||
//}
|
//}
|
||||||
|
|
||||||
bool CKStateChunk::SeekIdentifier(CKDWORD identifier) {
|
#pragma region Read Functions
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CKStateChunk::StartRead(void) {
|
void CKStateChunk::StartRead(void) {
|
||||||
if (this->m_Parser.m_Status != CKStateChunkStatus::IDLE) return;
|
if (this->m_Parser.m_Status != CKStateChunkStatus::IDLE) return;
|
||||||
|
@ -271,8 +342,116 @@ namespace LibCmo::CK2 {
|
||||||
this->m_Parser.m_Status = CKStateChunkStatus::READ;
|
this->m_Parser.m_Status = CKStateChunkStatus::READ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKStateChunk::ReadString(std::string& strl) {
|
bool CKStateChunk::SeekIdentifier(CKDWORD identifier) {
|
||||||
;
|
CKDWORD cache;
|
||||||
|
return SeekIdentifierAndReturnSize(identifier, &cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CKStateChunk::SeekIdentifierAndReturnSize(CKDWORD identifier, CKDWORD* out_size) {
|
||||||
|
if (this->m_Parser.m_Status != CKStateChunkStatus::READ) return false;
|
||||||
|
|
||||||
|
CKDWORD pos = 0u;
|
||||||
|
if (this->m_DataDwSize < 2) return false; // impossible to have a identifier
|
||||||
|
|
||||||
|
// search identifier
|
||||||
|
while (this->m_pData[pos] != identifier) {
|
||||||
|
pos = this->m_pData[pos + 1];
|
||||||
|
if (pos == 0u) return false; // got tail. no more identifier
|
||||||
|
if (pos + 1 >= this->m_DataDwSize) return false; // out of buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
// got identifier
|
||||||
|
this->m_Parser.m_PrevIdentifierPos = pos;
|
||||||
|
this->m_Parser.m_CurrentPos = pos + 2;
|
||||||
|
|
||||||
|
// calc size
|
||||||
|
CKDWORD nextptr = this->m_pData[pos + 1];
|
||||||
|
if (nextptr == 0) {
|
||||||
|
// the last identifier, use chunk size instead
|
||||||
|
nextptr = this->m_DataDwSize;
|
||||||
|
}
|
||||||
|
*out_size = sizeof(CKDWORD) * (nextptr - pos);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
CKERROR CKStateChunk::ReadString(std::string& strl) {
|
||||||
|
// get byte based size
|
||||||
|
CKDWORD strByteSize = 0u;
|
||||||
|
CKERROR err = this->ReadStructPtr(&strByteSize);
|
||||||
|
if (err != CKERROR::CKERR_OK) {
|
||||||
|
strl.clear();
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert to DWORD based
|
||||||
|
CKDWORD strDwordSize = this->GetCeilDwordSize(strByteSize);
|
||||||
|
|
||||||
|
// cp
|
||||||
|
if (this->EnsureReadSpace(strDwordSize)) {
|
||||||
|
strl.resize(strByteSize);
|
||||||
|
std::memcpy(strl.data(), this->m_pData + this->m_Parser.m_CurrentPos, strByteSize);
|
||||||
|
this->m_Parser.m_CurrentPos += strDwordSize;
|
||||||
|
} else strl.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CKStateChunk::StopRead(void) {
|
||||||
|
if (this->m_Parser.m_Status != CKStateChunkStatus::READ) return;
|
||||||
|
|
||||||
|
this->m_Parser.m_CurrentPos = 0u;
|
||||||
|
this->m_Parser.m_DataSize = this->m_DataDwSize;
|
||||||
|
this->m_Parser.m_PrevIdentifierPos = 0u;
|
||||||
|
this->m_Parser.m_Status = CKStateChunkStatus::IDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
|
||||||
|
#pragma region Write Functions
|
||||||
|
|
||||||
|
void CKStateChunk::StartWrite() {
|
||||||
|
if (this->m_Parser.m_Status != CKStateChunkStatus::IDLE) return;
|
||||||
|
|
||||||
|
// delete all current buffer
|
||||||
|
if (this->m_pData != nullptr) {
|
||||||
|
delete[] this->m_pData;
|
||||||
|
this->m_pData = nullptr;
|
||||||
|
}
|
||||||
|
this->m_DataDwSize = 0u;
|
||||||
|
|
||||||
|
// reset parser
|
||||||
|
this->m_Parser.m_CurrentPos = 0u;
|
||||||
|
this->m_Parser.m_DataSize = this->m_DataDwSize;
|
||||||
|
this->m_Parser.m_PrevIdentifierPos = 0u;
|
||||||
|
|
||||||
|
// force chunk version
|
||||||
|
this->m_ChunkVersion = CK_STATECHUNK_CHUNKVERSION::CHUNK_VERSION4;
|
||||||
|
|
||||||
|
// switch status
|
||||||
|
this->m_Parser.m_Status = CKStateChunkStatus::WRITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CKStateChunk::StopWrite(void) {
|
||||||
|
if (this->m_Parser.m_Status != CKStateChunkStatus::WRITE) return;
|
||||||
|
|
||||||
|
// update buffer size
|
||||||
|
this->m_DataDwSize = this->m_Parser.m_CurrentPos;
|
||||||
|
// shrink it
|
||||||
|
ResizeBuffer(this->m_DataDwSize);
|
||||||
|
|
||||||
|
// shrink 3 vector also
|
||||||
|
this->m_ObjectList.shrink_to_fit();
|
||||||
|
this->m_ManagerList.shrink_to_fit();
|
||||||
|
this->m_ChunkList.shrink_to_fit();
|
||||||
|
|
||||||
|
// reset parser
|
||||||
|
this->m_Parser.m_CurrentPos = 0u;
|
||||||
|
this->m_Parser.m_DataSize = this->m_DataDwSize;
|
||||||
|
this->m_Parser.m_PrevIdentifierPos = 0u;
|
||||||
|
this->m_Parser.m_Status = CKStateChunkStatus::IDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#include "CKDefines.hpp"
|
#include "CKDefines.hpp"
|
||||||
#include "CKEnums.hpp"
|
#include "CKEnums.hpp"
|
||||||
|
#include <type_traits>
|
||||||
|
#include <cinttypes>
|
||||||
|
|
||||||
namespace LibCmo::CK2 {
|
namespace LibCmo::CK2 {
|
||||||
|
|
||||||
|
@ -12,19 +14,6 @@ namespace LibCmo::CK2 {
|
||||||
CKStateChunk& operator=(const CKStateChunk&);
|
CKStateChunk& operator=(const CKStateChunk&);
|
||||||
~CKStateChunk();
|
~CKStateChunk();
|
||||||
|
|
||||||
void Clear(void);
|
|
||||||
|
|
||||||
bool ConvertFromBuffer(const void* buf);
|
|
||||||
CKDWORD ConvertToBuffer(void* buf);
|
|
||||||
|
|
||||||
//bool UnPack(CKDWORD DestSize);
|
|
||||||
CKDWORD GetDataSize(void);
|
|
||||||
|
|
||||||
bool SeekIdentifier(CKDWORD identifier);
|
|
||||||
|
|
||||||
void StartRead(void);
|
|
||||||
void ReadString(std::string& strl);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class CKStateChunkStatus : int32_t {
|
enum class CKStateChunkStatus : int32_t {
|
||||||
IDLE,
|
IDLE,
|
||||||
|
@ -51,10 +40,120 @@ namespace LibCmo::CK2 {
|
||||||
std::vector<CKDWORD> m_ManagerList;
|
std::vector<CKDWORD> m_ManagerList;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void _EnsureWriteSpace(CKDWORD size);
|
inline size_t GetCeilDwordSize(size_t char_size) {
|
||||||
inline bool _EnsureReadSpace(CKDWORD required) {
|
return (char_size + 3) >> 3;
|
||||||
return (this->m_Parser.m_CurrentPos <= this->m_Parser.m_DataSize) && (required <= (this->m_Parser.m_DataSize - this->m_Parser.m_CurrentPos));
|
|
||||||
}
|
}
|
||||||
|
bool ResizeBuffer(CKDWORD new_dwsize);
|
||||||
|
bool EnsureWriteSpace(CKDWORD dwsize);
|
||||||
|
bool EnsureReadSpace(CKDWORD dword_required);
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool ConvertFromBuffer(const void* buf);
|
||||||
|
CKDWORD ConvertToBuffer(void* buf);
|
||||||
|
|
||||||
|
//bool UnPack(CKDWORD DestSize);
|
||||||
|
void Clear(void);
|
||||||
|
CKDWORD GetDataSize(void);
|
||||||
|
CK_STATECHUNK_DATAVERSION GetDataVersion();
|
||||||
|
void SetDataVersion(CK_STATECHUNK_DATAVERSION version);
|
||||||
|
bool Skip(CKDWORD DwordCount);
|
||||||
|
|
||||||
|
#pragma region Read Function
|
||||||
|
|
||||||
|
public:
|
||||||
|
void StartRead(void);
|
||||||
|
bool SeekIdentifier(CKDWORD identifier);
|
||||||
|
bool SeekIdentifierAndReturnSize(CKDWORD identifier, CKDWORD* out_size);
|
||||||
|
CKERROR ReadString(std::string& strl);
|
||||||
|
/*
|
||||||
|
* Read Struct
|
||||||
|
Primitive type: ReadInt, ReadByte, ReadWord, ReadDword, ReadFloat, etc...
|
||||||
|
Struct type: ReadGuid, ReadVector, ReadMatrix, etc...
|
||||||
|
Both of them are redirected to this.
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
CKERROR ReadStructPtr(T* data) {
|
||||||
|
size_t size = GetCeilDwordSize(sizeof(T));
|
||||||
|
if (EnsureReadSpace(static_cast<CKDWORD>(size))) {
|
||||||
|
std::memcpy(data, this->m_pData + this->m_Parser.m_CurrentPos, size);
|
||||||
|
|
||||||
|
} return CKERROR::CKERR_OUTOFMEMORY;
|
||||||
|
return CKERROR::CKERR_OK;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Read Struct
|
||||||
|
A wrapper for ReadStructPtr.
|
||||||
|
Use reference, not pointer.
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
inline CKERROR ReadStructRef(T& data) {
|
||||||
|
return ReadStructPtr(&data);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Read Enum Data
|
||||||
|
A wrapper for ReadStructPtr.
|
||||||
|
All Enum read redirect to this.
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
inline CKERROR ReadEnum(T& data) {
|
||||||
|
return ReadStructPtr(reinterpret_cast<std::underlying_type_t<T>*>(&data));
|
||||||
|
}
|
||||||
|
|
||||||
|
CKERROR ReadBuffer(void* allocatedBuf);
|
||||||
|
CKERROR ReadNoSizeBuffer(CKDWORD size, void* allocatedBuf);
|
||||||
|
|
||||||
|
//int ReadInt();
|
||||||
|
//int StartReadSequence();
|
||||||
|
//CK_ID ReadObjectID();
|
||||||
|
//CKStateChunk* ReadSubChunk();
|
||||||
|
//int StartManagerReadSequence(CKGUID* guid);
|
||||||
|
//CKGUID ReadGuid();
|
||||||
|
//void ReadAndFillBuffer_LEndian(void* buffer);
|
||||||
|
//void ReadAndFillBuffer_LEndian16(void* buffer);
|
||||||
|
//float ReadFloat();
|
||||||
|
//CKWORD ReadWord();
|
||||||
|
//CKDWORD ReadDword();
|
||||||
|
//CKDWORD ReadDwordAsWords();
|
||||||
|
//void ReadVector(VxMath::VxVector* v);
|
||||||
|
//void ReadMatrix(VxMath::VxMatrix& mat);
|
||||||
|
//CKObjectImplements::CKObject* ReadObject(CKMinContext*);
|
||||||
|
//void ReadAndFillBuffer(void* buffer);
|
||||||
|
//CKBYTE* ReadRawBitmap(VxMath::VxImageDescEx& desc);
|
||||||
|
//XObjectArray ReadXObjectArray(void);
|
||||||
|
void StopRead(void);
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
#pragma region Write Function
|
||||||
|
|
||||||
|
public:
|
||||||
|
void StartWrite();
|
||||||
|
//void WriteIdentifier(CKDWORD id);
|
||||||
|
//void AddChunkAndDelete(CKStateChunk*);
|
||||||
|
//void StartObjectIDSequence(int count);
|
||||||
|
//void WriteObjectSequence(CKObjectImplements::CKObject* obj);
|
||||||
|
//void WriteInt(int data);
|
||||||
|
//void WriteFloat(float data);
|
||||||
|
//void WriteDword(CKDWORD data);
|
||||||
|
//void WriteDwordAsWords(CKDWORD data);
|
||||||
|
//void WriteVector(const VxMath::VxVector* v);
|
||||||
|
//void WriteMatrix(const VxMath::VxMatrix& mat);
|
||||||
|
//void WriteObject(CKObjectImplements::CKObject* obj);
|
||||||
|
//void WriteBuffer_LEndian(int size, void* buf);
|
||||||
|
//void WriteBuffer_LEndian16(int size, void* buf);
|
||||||
|
//void WriteBufferNoSize_LEndian(int size, void* buf);
|
||||||
|
///*void UpdateDataSize();*/
|
||||||
|
//void* LockWriteBuffer(int DwordCount);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Old Name: CloseChunk();
|
||||||
|
*/
|
||||||
|
void StopWrite(void);
|
||||||
|
|
||||||
|
#pragma endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user