fix saving issue
- fix CKStateChunk resize memory error. - fix wrong CKBitmapHandler free position in CKBitmapData writer. - fix init value error of CKFileWriter::m_DisableAddingFile when copying from reader. - fix ReadString, WriteString error in CKStateChunk (forget NULL terminal) - change CKPathManager resolve path order. Resolve temp path first, then resources folder. - fix mixdata combine error when writing CKTexture.
This commit is contained in:
parent
abea66d6f0
commit
ee4b621cac
|
@ -138,7 +138,6 @@ namespace LibCmo::CK2 {
|
||||||
CKDWORD expectedSize = reader->SaveMemory(nullptr, slot, *savefmt);
|
CKDWORD expectedSize = reader->SaveMemory(nullptr, slot, *savefmt);
|
||||||
std::unique_ptr<CKBYTE[]> filebuf(new CKBYTE[expectedSize]);
|
std::unique_ptr<CKBYTE[]> filebuf(new CKBYTE[expectedSize]);
|
||||||
reader->SaveMemory(filebuf.get(), slot, *savefmt);
|
reader->SaveMemory(filebuf.get(), slot, *savefmt);
|
||||||
reader.reset();
|
|
||||||
|
|
||||||
// in original Virtools design, only save alpha data when raw data can not represent alpha data
|
// in original Virtools design, only save alpha data when raw data can not represent alpha data
|
||||||
bool canSaveAlpha = reader->CanSaveAlpha();
|
bool canSaveAlpha = reader->CanSaveAlpha();
|
||||||
|
@ -201,6 +200,9 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// free reader
|
||||||
|
reader.reset();
|
||||||
|
|
||||||
// explicitly return to skip fallback
|
// explicitly return to skip fallback
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -174,7 +174,7 @@ namespace LibCmo::CK2 {
|
||||||
CKFileWriter::CKFileWriter(CKContext* ctx, CKFileReader* reader, bool is_shallow) :
|
CKFileWriter::CKFileWriter(CKContext* ctx, CKFileReader* reader, bool is_shallow) :
|
||||||
m_Ctx(ctx), m_Visitor(this),
|
m_Ctx(ctx), m_Visitor(this),
|
||||||
m_Done(false),
|
m_Done(false),
|
||||||
m_DisableAddingObject(true), m_DisableAddingFile(!is_shallow), // only disable adding file in shallow mode. but disable adding object in all mode.
|
m_DisableAddingObject(true), m_DisableAddingFile(is_shallow), // only disable adding file in shallow mode. but disable adding object in all mode.
|
||||||
m_SaveIDMax(0),
|
m_SaveIDMax(0),
|
||||||
m_FileObjects(), m_ManagersData(), m_PluginsDep(), m_IncludedFiles(),
|
m_FileObjects(), m_ManagersData(), m_PluginsDep(), m_IncludedFiles(),
|
||||||
m_FileInfo()
|
m_FileInfo()
|
||||||
|
|
|
@ -104,6 +104,10 @@ namespace LibCmo::CK2 {
|
||||||
struct ChunkParser {
|
struct ChunkParser {
|
||||||
CKStateChunkStatus m_Status;
|
CKStateChunkStatus m_Status;
|
||||||
CKDWORD m_CurrentPos;
|
CKDWORD m_CurrentPos;
|
||||||
|
/**
|
||||||
|
* @brief The runtime size of CKStateChunk internal buf in DWORD unit.
|
||||||
|
* Usually be used and changed when resizing buffer in writing mode.
|
||||||
|
*/
|
||||||
CKDWORD m_DataSize;
|
CKDWORD m_DataSize;
|
||||||
CKDWORD m_PrevIdentifierPos;
|
CKDWORD m_PrevIdentifierPos;
|
||||||
};
|
};
|
||||||
|
|
|
@ -261,18 +261,26 @@ namespace LibCmo::CK2 {
|
||||||
delete[] this->m_pData;
|
delete[] this->m_pData;
|
||||||
this->m_pData = nullptr;
|
this->m_pData = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set buf size
|
||||||
|
this->m_Parser.m_DataSize = 0u;
|
||||||
} else {
|
} else {
|
||||||
// otherwise, we create a new buffer instead it
|
// otherwise, we create a new buffer instead it
|
||||||
CKDWORD* newbuf = new CKDWORD[new_dwsize];
|
CKDWORD* newbuf = new CKDWORD[new_dwsize];
|
||||||
|
|
||||||
// if no original data, we do not need copy it and free it
|
// we copy original data only when it has.
|
||||||
if (this->m_pData != nullptr) {
|
if (this->m_pData != nullptr) {
|
||||||
std::memcpy(newbuf, this->m_pData, sizeof(CKDWORD) * new_dwsize);
|
// MARK: use std::min to copy for the minilist one
|
||||||
|
// otherwise, EnsureWriteSpace or StopWrite will crash.
|
||||||
|
std::memcpy(newbuf, this->m_pData, sizeof(CKDWORD) * std::min(this->m_Parser.m_DataSize, new_dwsize));
|
||||||
delete[] this->m_pData;
|
delete[] this->m_pData;
|
||||||
}
|
}
|
||||||
|
|
||||||
// assign new buffer
|
// assign new buffer
|
||||||
this->m_pData = newbuf;
|
this->m_pData = newbuf;
|
||||||
|
|
||||||
|
// set buf size
|
||||||
|
this->m_Parser.m_DataSize = new_dwsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -290,9 +298,6 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
// try resizing it
|
// try resizing it
|
||||||
if (!this->ResizeBuffer(needed)) return false;
|
if (!this->ResizeBuffer(needed)) return false;
|
||||||
|
|
||||||
// update size
|
|
||||||
this->m_Parser.m_DataSize = needed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -130,9 +130,18 @@ namespace LibCmo::CK2 {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check blank string
|
||||||
|
if (strByteSize == 0) {
|
||||||
|
strl->clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// read data
|
// read data
|
||||||
|
// MARK: the written string has NULL terminal.
|
||||||
|
// strByteSize also include NULL terminal,
|
||||||
|
// so we need minus 1 when resizing (not ReadByteData, because we still need read NULL terminal to skip it.)
|
||||||
XContainer::XString cache;
|
XContainer::XString cache;
|
||||||
cache.resize(strByteSize);
|
cache.resize(strByteSize - 1);
|
||||||
if (!this->ReadByteData(cache.data(), strByteSize)) {
|
if (!this->ReadByteData(cache.data(), strByteSize)) {
|
||||||
strl->clear();
|
strl->clear();
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -140,18 +140,25 @@ namespace LibCmo::CK2 {
|
||||||
XContainer::XString cache;
|
XContainer::XString cache;
|
||||||
m_BindContext->GetNativeString(*strl, cache);
|
m_BindContext->GetNativeString(*strl, cache);
|
||||||
|
|
||||||
// get size
|
if (cache.empty()) {
|
||||||
CKDWORD strByteSize = static_cast<CKDWORD>(cache.size());
|
// write zero string
|
||||||
if (!this->WriteStruct(strByteSize)) {
|
return this->WriteStruct(0);
|
||||||
return false;
|
} else {
|
||||||
}
|
// write string with NULL terminal
|
||||||
|
|
||||||
// write data
|
// write size
|
||||||
if (!this->WriteByteData(cache.c_str(), strByteSize)) {
|
CKDWORD strByteSize = static_cast<CKDWORD>(cache.size()) + 1;
|
||||||
return false;
|
if (!this->WriteStruct(strByteSize)) {
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
// write data with NULL terminal
|
||||||
|
if (!this->WriteByteData(cache.c_str(), strByteSize)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CKStateChunk::WriteObjectID(const CK_ID* id) {
|
bool CKStateChunk::WriteObjectID(const CK_ID* id) {
|
||||||
|
|
|
@ -78,6 +78,13 @@ namespace LibCmo::CK2::MgrImpls {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// test in temp folder
|
||||||
|
auto tempfile = m_TempFolder / filepath;
|
||||||
|
if (std::filesystem::is_regular_file(tempfile)) {
|
||||||
|
EncodingHelper::StdPathToU8Path(u8_filename, tempfile);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// otherwise check it in extra path
|
// otherwise check it in extra path
|
||||||
for (const auto& extrapath : m_ExtraPathes) {
|
for (const auto& extrapath : m_ExtraPathes) {
|
||||||
auto combinedpath = extrapath / filepath;
|
auto combinedpath = extrapath / filepath;
|
||||||
|
@ -88,13 +95,6 @@ namespace LibCmo::CK2::MgrImpls {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// test in temp folder
|
|
||||||
auto tempfile = m_TempFolder / filepath;
|
|
||||||
if (std::filesystem::is_regular_file(tempfile)) {
|
|
||||||
EncodingHelper::StdPathToU8Path(u8_filename, tempfile);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// failed
|
// failed
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,8 +47,8 @@ namespace LibCmo::CK2::MgrImpls {
|
||||||
* @remark
|
* @remark
|
||||||
* We match file in following order.
|
* We match file in following order.
|
||||||
* + Whether given file is absolute path. return if true.
|
* + Whether given file is absolute path. return if true.
|
||||||
* + User provided extra path.
|
|
||||||
* + Virtools temp folder.
|
* + Virtools temp folder.
|
||||||
|
* + User provided extra path.
|
||||||
* @return true if success
|
* @return true if success
|
||||||
*/
|
*/
|
||||||
bool ResolveFileName(XContainer::XString& u8_filename);
|
bool ResolveFileName(XContainer::XString& u8_filename);
|
||||||
|
|
|
@ -164,10 +164,9 @@ namespace LibCmo::CK2::ObjImpls {
|
||||||
chunk->ReadStruct(m_ZOrder);
|
chunk->ReadStruct(m_ZOrder);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
}
|
||||||
// MARK: compatibility code removed because I don't need them
|
// MARK: compatibility alternative core data read code removed because I don't need them
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: skin and bone are skipped.
|
// MARK: skin and bone are skipped.
|
||||||
|
|
||||||
|
|
|
@ -87,23 +87,23 @@ namespace LibCmo::CK2::ObjImpls {
|
||||||
// prepare mix data. see Read for more info about the struct of this mix data
|
// prepare mix data. see Read for more info about the struct of this mix data
|
||||||
CKDWORD mixdata = 0;
|
CKDWORD mixdata = 0;
|
||||||
// save options
|
// save options
|
||||||
mixdata &= static_cast<CKDWORD>(m_ImageHost.GetSaveOptions()) & 0xFF;
|
mixdata |= static_cast<CKDWORD>(m_ImageHost.GetSaveOptions()) & 0xFF;
|
||||||
mixdata <<= 8;
|
mixdata <<= 8;
|
||||||
// mix flags
|
// mix flags
|
||||||
CKDWORD mixflags = 0;
|
CKDWORD mixflags = 0;
|
||||||
if (m_ImageHost.IsTransparent()) {
|
if (m_ImageHost.IsTransparent()) {
|
||||||
mixflags &= 0x1;
|
mixflags |= 0x1;
|
||||||
}
|
}
|
||||||
if (m_VideoFormat != VxMath::VX_PIXELFORMAT::UNKNOWN_PF) {
|
if (m_VideoFormat != VxMath::VX_PIXELFORMAT::UNKNOWN_PF) {
|
||||||
mixflags &= 0x2;
|
mixflags |= 0x2;
|
||||||
}
|
}
|
||||||
if (m_ImageHost.IsCubeMap()) {
|
if (m_ImageHost.IsCubeMap()) {
|
||||||
mixflags &= 0x4;
|
mixflags |= 0x4;
|
||||||
}
|
}
|
||||||
mixdata &= mixflags & 0xFF;
|
mixdata |= mixflags & 0xFF;
|
||||||
mixdata <<= 8;
|
mixdata <<= 8;
|
||||||
// mipmap
|
// mipmap
|
||||||
mixdata &= (IsUseMipmap() ? 0xFF : 0);
|
mixdata |= (IsUseMipmap() ? 0xFF : 0);
|
||||||
|
|
||||||
// write mix data
|
// write mix data
|
||||||
chunk->WriteStruct(mixdata);
|
chunk->WriteStruct(mixdata);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user