mirror of
https://github.com/4jcraft/4jcraft.git
synced 2026-04-23 14:33:36 +00:00
fix/saving: Final storage fix.
Some checks failed
Some checks failed
This commit is contained in:
parent
d30e18ef4d
commit
6215e1365f
|
|
@ -216,11 +216,13 @@ void ConsoleSaveFileSplit::RegionFileReference::Decompress() {
|
|||
unsigned char* dataIn = dataCompressed + 4;
|
||||
unsigned char* dataInLast = dataCompressed + dataCompressedSize;
|
||||
|
||||
while (dataIn != dataInLast) {
|
||||
while (dataIn < dataInLast) {
|
||||
unsigned char thisByte = *dataIn++;
|
||||
if (thisByte == 0) {
|
||||
if (dataIn >= dataInLast) break;
|
||||
thisByte = *dataIn++;
|
||||
if (thisByte == 0) {
|
||||
if (dataIn + 1 >= dataInLast) break;
|
||||
unsigned int runLength = (*dataIn++) << 8;
|
||||
runLength |= (*dataIn++);
|
||||
runLength += 256;
|
||||
|
|
@ -237,7 +239,6 @@ void ConsoleSaveFileSplit::RegionFileReference::Decompress() {
|
|||
if (fileEntry->data.length != uncompressedSize) {
|
||||
// Treat as if it was an empty region file
|
||||
fileEntry->data.length = 0;
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -246,21 +247,24 @@ void ConsoleSaveFileSplit::RegionFileReference::Decompress() {
|
|||
unsigned char* dataIn = dataCompressed + 4;
|
||||
unsigned char* dataInLast = dataCompressed + dataCompressedSize;
|
||||
unsigned char* dataOut = data;
|
||||
unsigned char* dataOutLast = data + fileEntry->data.length;
|
||||
|
||||
while (dataIn != dataInLast) {
|
||||
while (dataIn < dataInLast && dataOut < dataOutLast) {
|
||||
unsigned char thisByte = *dataIn++;
|
||||
if (thisByte == 0) {
|
||||
if (dataIn >= dataInLast) break;
|
||||
thisByte = *dataIn++;
|
||||
if (thisByte == 0) {
|
||||
if (dataIn + 1 >= dataInLast) break;
|
||||
unsigned int runLength = (*dataIn++) << 8;
|
||||
runLength |= (*dataIn++);
|
||||
runLength += 256;
|
||||
for (unsigned int i = 0; i < runLength; i++) {
|
||||
for (unsigned int i = 0; i < runLength && dataOut < dataOutLast; i++) {
|
||||
*dataOut++ = 0;
|
||||
}
|
||||
} else {
|
||||
unsigned int runLength = thisByte;
|
||||
for (unsigned int i = 0; i < runLength; i++) {
|
||||
for (unsigned int i = 0; i < runLength && dataOut < dataOutLast; i++) {
|
||||
*dataOut++ = 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -274,7 +278,6 @@ void ConsoleSaveFileSplit::RegionFileReference::Decompress() {
|
|||
free(data);
|
||||
fileEntry->data.length = 0;
|
||||
data = nullptr;
|
||||
assert(0);
|
||||
}
|
||||
// std::int64_t endTime = System::currentTimeMillis();
|
||||
// app.DebugPrintf("Decompressing region file from 0x%.8x %d to %d bytes -
|
||||
|
|
@ -437,6 +440,7 @@ void ConsoleSaveFileSplit::_init(const std::wstring& fileName, void* pvSaveData,
|
|||
// Get details of region files. From this point on we are responsible for
|
||||
// the memory that the storage manager initially allocated for them
|
||||
unsigned int regionCount = PlatformStorage.GetSubfileCount();
|
||||
|
||||
for (unsigned int i = 0; i < regionCount; i++) {
|
||||
unsigned int regionIndex;
|
||||
unsigned char* regionDataCompressed;
|
||||
|
|
@ -446,8 +450,14 @@ void ConsoleSaveFileSplit::_init(const std::wstring& fileName, void* pvSaveData,
|
|||
(void**)®ionDataCompressed,
|
||||
®ionSizeCompressed);
|
||||
|
||||
unsigned char* copiedData = nullptr;
|
||||
if (regionSizeCompressed > 0 && regionDataCompressed) {
|
||||
copiedData = (unsigned char*)malloc(regionSizeCompressed);
|
||||
memcpy(copiedData, regionDataCompressed, regionSizeCompressed);
|
||||
}
|
||||
|
||||
RegionFileReference* regionFileRef = new RegionFileReference(
|
||||
i, regionIndex, regionSizeCompressed, regionDataCompressed);
|
||||
regionIndex, regionIndex, regionSizeCompressed, copiedData);
|
||||
if (regionSizeCompressed > 0) {
|
||||
regionFileRef->Decompress();
|
||||
} else {
|
||||
|
|
@ -493,10 +503,12 @@ void ConsoleSaveFileSplit::_init(const std::wstring& fileName, void* pvSaveData,
|
|||
PlatformStorage.GetSaveData(pvSaveMem, &storageLength);
|
||||
app.DebugPrintf("Filesize - %d, Adjusted size - %d\n", fileSize,
|
||||
storageLength);
|
||||
|
||||
fileSize = storageLength;
|
||||
}
|
||||
|
||||
int compressed = *(int*)pvSaveMem;
|
||||
|
||||
if (compressed == 0) {
|
||||
unsigned int decompSize = *((int*)pvSaveMem + 1);
|
||||
|
||||
|
|
@ -1288,6 +1300,7 @@ void ConsoleSaveFileSplit::Flush(bool autosave, bool updateThumbnail) {
|
|||
|
||||
unsigned int fileSize = header.GetFileSize();
|
||||
|
||||
|
||||
// Assume that the compression will make it smaller so initially attempt to
|
||||
// allocate the current file size We add 4 bytes to the start so that we can
|
||||
// signal compressed data And another 4 bytes to store the decompressed data
|
||||
|
|
|
|||
|
|
@ -203,6 +203,7 @@ void FileHeader::ReadHeader(
|
|||
// based PlayerUID
|
||||
// : Bumped it to 8 for Durango v1 when to save the chunks in a
|
||||
// different compressed format
|
||||
case SAVE_FILE_VERSION_CHUNK_INHABITED_TIME:
|
||||
case SAVE_FILE_VERSION_COMPRESSED_CHUNK_STORAGE:
|
||||
case SAVE_FILE_VERSION_DURANGO_CHANGE_MAP_DATA_MAPPING_SIZE:
|
||||
case SAVE_FILE_VERSION_CHANGE_MAP_DATA_MAPPING_SIZE:
|
||||
|
|
|
|||
|
|
@ -33,8 +33,11 @@ static unsigned int s_SaveBufferSize = 0;
|
|||
struct SubfileData {
|
||||
std::vector<std::uint8_t> data;
|
||||
};
|
||||
|
||||
#include <mutex>
|
||||
static std::map<int, SubfileData> s_Subfiles;
|
||||
static int s_SubfileCounter = 0;
|
||||
static std::mutex s_SubfileMutex;
|
||||
|
||||
// helper functions
|
||||
static StdFileIO s_FileIO;
|
||||
|
|
@ -87,8 +90,11 @@ void C4JStorage::Init(unsigned int uiSaveVersion,
|
|||
void C4JStorage::ResetSaveData() {
|
||||
s_CurrentSaveTitle = L"New World";
|
||||
s_CurrentSaveFilename = "";
|
||||
s_Subfiles.clear();
|
||||
s_SubfileCounter = 0;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_SubfileMutex);
|
||||
s_Subfiles.clear();
|
||||
s_SubfileCounter = 0;
|
||||
}
|
||||
if (s_SaveBuffer) {
|
||||
free(s_SaveBuffer);
|
||||
s_SaveBuffer = nullptr;
|
||||
|
|
@ -314,19 +320,33 @@ C4JStorage::ESaveGameState C4JStorage::LoadSaveData(
|
|||
s_SaveBufferSize = (unsigned int)blobData.size();
|
||||
s_SaveBuffer = (std::uint8_t*)malloc(s_SaveBufferSize);
|
||||
memcpy(s_SaveBuffer, blobData.data(), s_SaveBufferSize);
|
||||
|
||||
}
|
||||
|
||||
// put in mem
|
||||
s_Subfiles.clear();
|
||||
for (int i = 0; i < 50; i++) {
|
||||
auto subData = s_FileIO.readFileToVec(
|
||||
GetSaveFile(s_CurrentSaveFilename,
|
||||
"subfile_" + std::to_string(i) + ".dat"));
|
||||
if (!subData.empty()) {
|
||||
SubfileData sd;
|
||||
sd.data = std::move(subData);
|
||||
s_Subfiles[i] = std::move(sd);
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(s_SubfileMutex);
|
||||
s_Subfiles.clear();
|
||||
int maxIndex = -1;
|
||||
auto dir = GetSaveDir(s_CurrentSaveFilename);
|
||||
std::error_code ec;
|
||||
for (const auto& entry : std::filesystem::directory_iterator(dir, ec)) {
|
||||
if (!entry.is_regular_file()) continue;
|
||||
std::string filename = entry.path().filename().string();
|
||||
if (filename.find("subfile_") == 0 && filename.find(".dat") == filename.size() - 4) {
|
||||
try {
|
||||
int i = std::stoi(filename.substr(8, filename.size() - 12));
|
||||
auto subData = s_FileIO.readFileToVec(entry.path());
|
||||
if (!subData.empty()) {
|
||||
SubfileData sd;
|
||||
sd.data = std::move(subData);
|
||||
s_Subfiles[i] = std::move(sd);
|
||||
if (i > maxIndex) maxIndex = i;
|
||||
}
|
||||
} catch (...) {}
|
||||
}
|
||||
}
|
||||
s_SubfileCounter = maxIndex + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -426,17 +446,30 @@ unsigned int C4JStorage::CRC(unsigned char* buf, int len) {
|
|||
|
||||
// that fucking bird that i hate
|
||||
int C4JStorage::AddSubfile(int regionIndex) {
|
||||
s_Subfiles[s_SubfileCounter] = SubfileData();
|
||||
return s_SubfileCounter++;
|
||||
std::lock_guard<std::mutex> lock(s_SubfileMutex);
|
||||
s_Subfiles[regionIndex] = SubfileData();
|
||||
if (regionIndex >= s_SubfileCounter) {
|
||||
s_SubfileCounter = regionIndex + 1;
|
||||
}
|
||||
return regionIndex;
|
||||
}
|
||||
|
||||
unsigned int C4JStorage::GetSubfileCount() { return s_Subfiles.size(); }
|
||||
unsigned int C4JStorage::GetSubfileCount() {
|
||||
std::lock_guard<std::mutex> lock(s_SubfileMutex);
|
||||
return s_Subfiles.size();
|
||||
}
|
||||
|
||||
void C4JStorage::GetSubfileDetails(unsigned int i, int* regionIndex,
|
||||
void** data, unsigned int* size) {
|
||||
auto it = s_Subfiles.find(i);
|
||||
std::lock_guard<std::mutex> lock(s_SubfileMutex);
|
||||
auto it = s_Subfiles.begin();
|
||||
unsigned int index = 0;
|
||||
while (it != s_Subfiles.end() && index < i) {
|
||||
++it;
|
||||
++index;
|
||||
}
|
||||
if (it != s_Subfiles.end()) {
|
||||
if (regionIndex) *regionIndex = 0;
|
||||
if (regionIndex) *regionIndex = it->first;
|
||||
if (data) *data = it->second.data.data();
|
||||
if (size) *size = (unsigned int)it->second.data.size();
|
||||
} else {
|
||||
|
|
@ -447,15 +480,18 @@ void C4JStorage::GetSubfileDetails(unsigned int i, int* regionIndex,
|
|||
}
|
||||
|
||||
void C4JStorage::ResetSubfiles() {
|
||||
std::lock_guard<std::mutex> lock(s_SubfileMutex);
|
||||
s_Subfiles.clear();
|
||||
s_SubfileCounter = 0;
|
||||
}
|
||||
void C4JStorage::UpdateSubfile(int index, void* data, unsigned int size) {
|
||||
std::lock_guard<std::mutex> lock(s_SubfileMutex);
|
||||
SubfileData& sd = s_Subfiles[index]; // inserts if missing
|
||||
sd.data.resize(size);
|
||||
memcpy(sd.data.data(), data, size);
|
||||
}
|
||||
void C4JStorage::SaveSubfiles(std::function<int(const bool)> callback) {
|
||||
std::lock_guard<std::mutex> lock(s_SubfileMutex);
|
||||
if (!s_CurrentSaveFilename.empty() && !s_Subfiles.empty()) {
|
||||
auto dir = GetSaveDir(s_CurrentSaveFilename);
|
||||
std::error_code ec;
|
||||
|
|
|
|||
Loading…
Reference in a new issue