write some shit

This commit is contained in:
yyc12345 2023-02-15 21:03:26 +08:00
parent bdea4c5bcd
commit b74d8a4e58
4 changed files with 175 additions and 40 deletions

View File

@ -16,6 +16,7 @@ in VT25 +32, 128
VxMemoryMappedFile and CKFileInfo seems no change
CKFileObject still no change
CKFilePluginDependencies still no change
CKFileManagerData no change (12)
CKStateChunk is 0x28u black box
CKBufferParser also is 0x10u black box
@ -55,6 +56,25 @@ struct XBitArray {
DWORD m_Size;
};
// <T, K> = <int, CK_ID>
typedef struct XFileObjectsTable::Entry {
CK_ID key;
int data;
struct Entry* next;
} *XFileObjectsTable::pEntry;
struct XFileObjectsTable {
struct XFileObjectsTable::XSArray_pEntry_ {
XFileObjectsTable::pEntry* m_Begin;
XFileObjectsTable::pEntry* m_End;
}m_Table;
struct XFileObjectsTable::XClassArray_pEntry_ {
XFileObjectsTable::pEntry* m_Begin;
XFileObjectsTable::pEntry* m_End;
XFileObjectsTable::pEntry* m_AllocatedEnd;
}m_Pool;
};
struct CKFileInfo
{
DWORD ProductVersion; // Virtools Version (Dev/Creation). (CK_VIRTOOLS_VERSION)
@ -87,6 +107,11 @@ struct CKFileObject {
CKDWORD SaveFlags; // Flags used when this object was saved.
};
struct CKFileManagerData {
CKStateChunk *data;
CKGUID Manager;
}
struct CKFilePluginDependencies{
int m_PluginCategory;
XArray/*<CKGUID>*/ m_Guids;
@ -130,7 +155,7 @@ struct CKFile {
VxMemoryMappedFile* m_MappedFile;
// 33 + 5 = 38
// guess
float m_Chrono[5];
XFileObjectsTable m_ObjectsHashTable;
// 38 + 5 = 43
//[guess]
CKBOOL m_SceneSaved;

View File

@ -54,7 +54,7 @@ namespace LibCmo {
CKDWORD fhdr1[8];
CKDWORD fhdr2[8];
if (parser->GetSize() < sizeof(fhdr1)) return CKERROR::CKERR_INVALIDFILE;
parser->ReadAndMove(fhdr1, sizeof(fhdr1));
parser->Read(fhdr1, sizeof(fhdr1));
if (fhdr1[5]) { // it seems that there is a ZERO checker?
memset(fhdr1, 0, sizeof(fhdr1));
@ -68,7 +68,7 @@ namespace LibCmo {
memset(fhdr2, 0, sizeof(fhdr2));
} else {
if (parser->GetSize() < sizeof(fhdr1) + sizeof(fhdr2)) return CKERROR::CKERR_INVALIDFILE;
parser->ReadAndMove(fhdr2, sizeof(fhdr2));
parser->Read(fhdr2, sizeof(fhdr2));
}
// forcely reset too big product ver
@ -100,23 +100,23 @@ namespace LibCmo {
fhdr1[2] = 0;
// compute crc
uLong gotten_crc = adler32(0u, reinterpret_cast<const Bytef*>(&fhdr1), sizeof(fhdr1));
CKDWORD gotten_crc = CKComputeDataCRC(&fhdr1, sizeof(fhdr1), 0u);
parser->SetCursor(sizeof(fhdr1));
gotten_crc = adler32(gotten_crc, reinterpret_cast<const Bytef*>(parser->GetPtr()), sizeof(fhdr2));
gotten_crc = CKComputeDataCRC(parser->GetPtr(), sizeof(fhdr2), gotten_crc);
parser->MoveCursor(sizeof(fhdr2));
gotten_crc = adler32(gotten_crc, reinterpret_cast<const Bytef*>(parser->GetPtr()), this->m_FileInfo.Hdr1PackSize);
gotten_crc = CKComputeDataCRC(parser->GetPtr(), this->m_FileInfo.Hdr1PackSize, gotten_crc);
parser->MoveCursor(this->m_FileInfo.Hdr1PackSize);
gotten_crc = adler32(gotten_crc, reinterpret_cast<const Bytef*>(parser->GetPtr()), this->m_FileInfo.DataPackSize);
gotten_crc = CKComputeDataCRC(parser->GetPtr(), this->m_FileInfo.DataPackSize, gotten_crc);
parser->SetCursor(sizeof(fhdr1) + sizeof(fhdr2));
if (gotten_crc != static_cast<uLong>(this->m_FileInfo.Crc)) return CKERROR::CKERR_FILECRCERROR;
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) {
free(decomp_buffer);
delete[] decomp_buffer;
return CKERROR::CKERR_OUTOFMEMORY;
}
}
@ -137,15 +137,15 @@ namespace LibCmo {
fileobj.Data = nullptr;
// read basic fields
parser->ReadAndMove(&(fileobj.Object), sizeof(CK_ID));
parser->ReadAndMove(&(fileobj.ObjectCid), sizeof(CK_CLASSID));
parser->ReadAndMove(&(fileobj.FileIndex), sizeof(CKDWORD));
parser->Read(&(fileobj.Object), sizeof(CK_ID));
parser->Read(&(fileobj.ObjectCid), sizeof(CK_CLASSID));
parser->Read(&(fileobj.FileIndex), sizeof(CKDWORD));
CKDWORD namelen;
parser->ReadAndMove(&namelen, sizeof(CKDWORD));
parser->Read(&namelen, sizeof(CKDWORD));
if (namelen != 0) {
fileobj.Name.resize(namelen);
parser->ReadAndMove(fileobj.Name.data(), namelen);
parser->Read(fileobj.Name.data(), namelen);
}
}
}
@ -156,20 +156,20 @@ namespace LibCmo {
if (this->m_FileInfo.FileVersion >= 8) {
// get size and resize
CKDWORD depSize;
parser->ReadAndMove(&depSize, sizeof(CKDWORD));
parser->Read(&depSize, sizeof(CKDWORD));
this->m_PluginDep.resize(depSize);
CKDWORD guid_size;
for (auto& dep : this->m_PluginDep) {
// read category
parser->ReadAndMove(&(dep.m_PluginCategory), sizeof(CK_PLUGIN_TYPE));
parser->Read(&(dep.m_PluginCategory), sizeof(CK_PLUGIN_TYPE));
// get size and resize
parser->ReadAndMove(&guid_size, sizeof(CKDWORD));
parser->Read(&guid_size, sizeof(CKDWORD));
dep.m_Guids.resize(guid_size);
dep.ValidGuids.resize(guid_size);
// read data
if (guid_size != 0) {
parser->ReadAndMove(dep.m_Guids.data(), sizeof(CKGUID)* guid_size);
parser->Read(dep.m_Guids.data(), sizeof(CKGUID)* guid_size);
}
// extra load flag
@ -193,20 +193,20 @@ namespace LibCmo {
// file ver >= 8 have this feature
if (this->m_FileInfo.FileVersion >= 8) {
// MARK: i don't knwo what is this!
int32_t unknowIncludedFileFlag;
parser->ReadAndMove(&unknowIncludedFileFlag, sizeof(int32_t));
int32_t hasIncludedFile;
parser->Read(&hasIncludedFile, sizeof(int32_t));
if (unknowIncludedFileFlag > 0) {
if (hasIncludedFile > 0) {
// read included file size and resize
CKDWORD includedFileCount;
parser->ReadAndMove(&includedFileCount, sizeof(CKDWORD));
parser->Read(&includedFileCount, sizeof(CKDWORD));
this->m_IncludedFiles.resize(includedFileCount);
unknowIncludedFileFlag -= 4;
hasIncludedFile -= 4;
}
// backward pos
parser->SetCursor(unknowIncludedFileFlag);
parser->SetCursor(hasIncludedFile);
}
// ========== read data ==========
@ -229,10 +229,101 @@ namespace LibCmo {
}
CKERROR CKFile::ReadFileData(CKBufferParser** ParserPtr) {
CKBufferParser* parser = *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.Hdr1UnPackSize, true);
if (parser == nullptr) {
delete[] decomp_buffer;
return CKERROR::CKERR_OUTOFMEMORY;
}
}
}
// ========== 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 ==========
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 (this->m_Parser != nullptr) {
delete this->m_Parser;
this->m_Parser = 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;
}
}

View File

@ -10,21 +10,33 @@
namespace LibCmo {
#pragma region CKZLib Func
void* CKUnPackData(CKINT DestSize, const void* SrcBuffer, CKINT SrcSize) {
char* DestBuffer = (char*)malloc(DestSize);
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) {
free(DestBuffer);
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) :
@ -129,13 +141,13 @@ namespace LibCmo {
#pragma region CKBufferParser
CKBufferParser::CKBufferParser(void* ptr, size_t rsize, bool need_manual_free) :
m_ReaderBegin(static_cast<char*>(ptr)),
m_ReaderPos(0u), m_ReaderSize(rsize),
m_MemBegin(static_cast<char*>(ptr)),
m_MemPos(0u), m_MemSize(rsize),
m_NeedManualFree(need_manual_free) {
;
}
CKBufferParser::~CKBufferParser() {
if (this->m_NeedManualFree) free(this->m_ReaderBegin);
if (this->m_NeedManualFree) delete[](this->m_MemBegin);
}
#pragma endregion

View File

@ -14,6 +14,7 @@
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 {
@ -55,10 +56,10 @@ namespace LibCmo {
class CKBufferParser {
private:
char* m_ReaderBegin;
size_t m_ReaderPos;
char* m_MemBegin;
size_t m_MemPos;
bool m_NeedManualFree;
size_t m_ReaderSize;
size_t m_MemSize;
public:
CKBufferParser(void* ptr, size_t rsize, bool need_manual_free);
@ -66,14 +67,19 @@ namespace LibCmo {
CKBufferParser& operator=(const CKBufferParser&) = delete;
~CKBufferParser();
inline const void* GetPtr(void) { return (this->m_ReaderBegin + m_ReaderPos); }
inline void ReadAndMove(void* data, size_t data_size) {
memcpy(data, (this->m_ReaderBegin + m_ReaderPos), data_size);
this->m_ReaderPos += data_size;
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 size_t GetSize(void) { return this->m_ReaderSize; }
inline void MoveCursor(size_t off) { this->m_ReaderPos += off; }
inline void SetCursor(size_t off) { this->m_ReaderPos = off; }
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; }
};
struct CKFileInfo {
@ -127,6 +133,7 @@ namespace LibCmo {
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;