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 VxMemoryMappedFile and CKFileInfo seems no change
CKFileObject still no change CKFileObject still no change
CKFilePluginDependencies still no change CKFilePluginDependencies still no change
CKFileManagerData no change (12)
CKStateChunk is 0x28u black box CKStateChunk is 0x28u black box
CKBufferParser also is 0x10u black box CKBufferParser also is 0x10u black box
@ -55,6 +56,25 @@ struct XBitArray {
DWORD m_Size; 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 struct CKFileInfo
{ {
DWORD ProductVersion; // Virtools Version (Dev/Creation). (CK_VIRTOOLS_VERSION) DWORD ProductVersion; // Virtools Version (Dev/Creation). (CK_VIRTOOLS_VERSION)
@ -87,6 +107,11 @@ struct CKFileObject {
CKDWORD SaveFlags; // Flags used when this object was saved. CKDWORD SaveFlags; // Flags used when this object was saved.
}; };
struct CKFileManagerData {
CKStateChunk *data;
CKGUID Manager;
}
struct CKFilePluginDependencies{ struct CKFilePluginDependencies{
int m_PluginCategory; int m_PluginCategory;
XArray/*<CKGUID>*/ m_Guids; XArray/*<CKGUID>*/ m_Guids;
@ -130,7 +155,7 @@ struct CKFile {
VxMemoryMappedFile* m_MappedFile; VxMemoryMappedFile* m_MappedFile;
// 33 + 5 = 38 // 33 + 5 = 38
// guess // guess
float m_Chrono[5]; XFileObjectsTable m_ObjectsHashTable;
// 38 + 5 = 43 // 38 + 5 = 43
//[guess] //[guess]
CKBOOL m_SceneSaved; CKBOOL m_SceneSaved;

View File

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

View File

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

View File

@ -14,6 +14,7 @@
namespace LibCmo { namespace LibCmo {
void* CKUnPackData(CKINT DestSize, const void* SrcBuffer, CKINT SrcSize); void* CKUnPackData(CKINT DestSize, const void* SrcBuffer, CKINT SrcSize);
CKDWORD CKComputeDataCRC(const void* data, size_t size, CKDWORD PreviousCRC = 0);
struct CKGUID { struct CKGUID {
union { union {
@ -55,10 +56,10 @@ namespace LibCmo {
class CKBufferParser { class CKBufferParser {
private: private:
char* m_ReaderBegin; char* m_MemBegin;
size_t m_ReaderPos; size_t m_MemPos;
bool m_NeedManualFree; bool m_NeedManualFree;
size_t m_ReaderSize; size_t m_MemSize;
public: public:
CKBufferParser(void* ptr, size_t rsize, bool need_manual_free); CKBufferParser(void* ptr, size_t rsize, bool need_manual_free);
@ -66,14 +67,19 @@ namespace LibCmo {
CKBufferParser& operator=(const CKBufferParser&) = delete; CKBufferParser& operator=(const CKBufferParser&) = delete;
~CKBufferParser(); ~CKBufferParser();
inline const void* GetPtr(void) { return (this->m_ReaderBegin + m_ReaderPos); } inline const void* GetPtr(void) { return (this->m_MemBegin + m_MemPos); }
inline void ReadAndMove(void* data, size_t data_size) { inline void Read(void* data, size_t data_size) {
memcpy(data, (this->m_ReaderBegin + m_ReaderPos), data_size); memcpy(data, (this->m_MemBegin + m_MemPos), data_size);
this->m_ReaderPos += data_size; this->m_MemPos += data_size;
} }
inline size_t GetSize(void) { return this->m_ReaderSize; } inline void Write(const void* data, size_t data_size) {
inline void MoveCursor(size_t off) { this->m_ReaderPos += off; } memcpy((this->m_MemBegin + m_MemPos), data, data_size);
inline void SetCursor(size_t off) { this->m_ReaderPos = off; } 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 { struct CKFileInfo {
@ -127,6 +133,7 @@ namespace LibCmo {
CKERROR ReadFileHeaders(CKBufferParser** ParserPtr); CKERROR ReadFileHeaders(CKBufferParser** ParserPtr);
CKERROR ReadFileData(CKBufferParser** ParserPtr); CKERROR ReadFileData(CKBufferParser** ParserPtr);
CKERROR LoadFileData(void/*CKObjectArray list*/); CKERROR LoadFileData(void/*CKObjectArray list*/);
CKERROR FinishLoading(/*CKObjectArray list, */CK_LOAD_FLAGS flags);
int32_t m_SaveIDMax; int32_t m_SaveIDMax;
XArray<CKFileObject> m_FileObject; XArray<CKFileObject> m_FileObject;