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);
|
||||
std::unique_ptr<CKBYTE[]> filebuf(new CKBYTE[expectedSize]);
|
||||
reader->SaveMemory(filebuf.get(), slot, *savefmt);
|
||||
reader.reset();
|
||||
|
||||
// in original Virtools design, only save alpha data when raw data can not represent alpha data
|
||||
bool canSaveAlpha = reader->CanSaveAlpha();
|
||||
|
@ -201,6 +200,9 @@ namespace LibCmo::CK2 {
|
|||
|
||||
}
|
||||
|
||||
// free reader
|
||||
reader.reset();
|
||||
|
||||
// explicitly return to skip fallback
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -174,7 +174,7 @@ namespace LibCmo::CK2 {
|
|||
CKFileWriter::CKFileWriter(CKContext* ctx, CKFileReader* reader, bool is_shallow) :
|
||||
m_Ctx(ctx), m_Visitor(this),
|
||||
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_FileObjects(), m_ManagersData(), m_PluginsDep(), m_IncludedFiles(),
|
||||
m_FileInfo()
|
||||
|
|
|
@ -104,6 +104,10 @@ namespace LibCmo::CK2 {
|
|||
struct ChunkParser {
|
||||
CKStateChunkStatus m_Status;
|
||||
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_PrevIdentifierPos;
|
||||
};
|
||||
|
|
|
@ -261,18 +261,26 @@ namespace LibCmo::CK2 {
|
|||
delete[] this->m_pData;
|
||||
this->m_pData = nullptr;
|
||||
}
|
||||
|
||||
// set buf size
|
||||
this->m_Parser.m_DataSize = 0u;
|
||||
} else {
|
||||
// otherwise, we create a new buffer instead it
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
// assign new buffer
|
||||
this->m_pData = newbuf;
|
||||
|
||||
// set buf size
|
||||
this->m_Parser.m_DataSize = new_dwsize;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -290,9 +298,6 @@ namespace LibCmo::CK2 {
|
|||
|
||||
// try resizing it
|
||||
if (!this->ResizeBuffer(needed)) return false;
|
||||
|
||||
// update size
|
||||
this->m_Parser.m_DataSize = needed;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -130,9 +130,18 @@ namespace LibCmo::CK2 {
|
|||
return false;
|
||||
}
|
||||
|
||||
// check blank string
|
||||
if (strByteSize == 0) {
|
||||
strl->clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
// 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;
|
||||
cache.resize(strByteSize);
|
||||
cache.resize(strByteSize - 1);
|
||||
if (!this->ReadByteData(cache.data(), strByteSize)) {
|
||||
strl->clear();
|
||||
return false;
|
||||
|
|
|
@ -140,18 +140,25 @@ namespace LibCmo::CK2 {
|
|||
XContainer::XString cache;
|
||||
m_BindContext->GetNativeString(*strl, cache);
|
||||
|
||||
// get size
|
||||
CKDWORD strByteSize = static_cast<CKDWORD>(cache.size());
|
||||
if (!this->WriteStruct(strByteSize)) {
|
||||
return false;
|
||||
}
|
||||
if (cache.empty()) {
|
||||
// write zero string
|
||||
return this->WriteStruct(0);
|
||||
} else {
|
||||
// write string with NULL terminal
|
||||
|
||||
// write data
|
||||
if (!this->WriteByteData(cache.c_str(), strByteSize)) {
|
||||
return false;
|
||||
}
|
||||
// write size
|
||||
CKDWORD strByteSize = static_cast<CKDWORD>(cache.size()) + 1;
|
||||
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) {
|
||||
|
|
|
@ -78,6 +78,13 @@ namespace LibCmo::CK2::MgrImpls {
|
|||
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
|
||||
for (const auto& extrapath : m_ExtraPathes) {
|
||||
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
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -47,8 +47,8 @@ namespace LibCmo::CK2::MgrImpls {
|
|||
* @remark
|
||||
* We match file in following order.
|
||||
* + Whether given file is absolute path. return if true.
|
||||
* + User provided extra path.
|
||||
* + Virtools temp folder.
|
||||
* + User provided extra path.
|
||||
* @return true if success
|
||||
*/
|
||||
bool ResolveFileName(XContainer::XString& u8_filename);
|
||||
|
|
|
@ -164,10 +164,9 @@ namespace LibCmo::CK2::ObjImpls {
|
|||
chunk->ReadStruct(m_ZOrder);
|
||||
}
|
||||
|
||||
} else {
|
||||
// MARK: compatibility code removed because I don't need them
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// MARK: compatibility alternative core data read code removed because I don't need them
|
||||
|
||||
|
||||
// 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
|
||||
CKDWORD mixdata = 0;
|
||||
// save options
|
||||
mixdata &= static_cast<CKDWORD>(m_ImageHost.GetSaveOptions()) & 0xFF;
|
||||
mixdata |= static_cast<CKDWORD>(m_ImageHost.GetSaveOptions()) & 0xFF;
|
||||
mixdata <<= 8;
|
||||
// mix flags
|
||||
CKDWORD mixflags = 0;
|
||||
if (m_ImageHost.IsTransparent()) {
|
||||
mixflags &= 0x1;
|
||||
mixflags |= 0x1;
|
||||
}
|
||||
if (m_VideoFormat != VxMath::VX_PIXELFORMAT::UNKNOWN_PF) {
|
||||
mixflags &= 0x2;
|
||||
mixflags |= 0x2;
|
||||
}
|
||||
if (m_ImageHost.IsCubeMap()) {
|
||||
mixflags &= 0x4;
|
||||
mixflags |= 0x4;
|
||||
}
|
||||
mixdata &= mixflags & 0xFF;
|
||||
mixdata |= mixflags & 0xFF;
|
||||
mixdata <<= 8;
|
||||
// mipmap
|
||||
mixdata &= (IsUseMipmap() ? 0xFF : 0);
|
||||
mixdata |= (IsUseMipmap() ? 0xFF : 0);
|
||||
|
||||
// write mix data
|
||||
chunk->WriteStruct(mixdata);
|
||||
|
|
Loading…
Reference in New Issue
Block a user