mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Add experimental, disabled XOR mode, leaving all compression to ZSTD. Seems to perform worse.
This commit is contained in:
parent
f6e5249327
commit
7f6e6ae985
1 changed files with 59 additions and 32 deletions
|
@ -103,9 +103,14 @@ namespace SaveState
|
||||||
}
|
}
|
||||||
|
|
||||||
struct StateBuffer {
|
struct StateBuffer {
|
||||||
|
void Clear() {
|
||||||
|
zstd_compressed.clear();
|
||||||
|
decompressed_size = 0;
|
||||||
|
compressed_size = 0;
|
||||||
|
}
|
||||||
std::vector<u8> zstd_compressed;
|
std::vector<u8> zstd_compressed;
|
||||||
size_t decompressed_size;
|
size_t decompressed_size = 0;
|
||||||
size_t compressed_size;
|
size_t compressed_size = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// This ring buffer of states is for rewind save states, which are kept in RAM.
|
// This ring buffer of states is for rewind save states, which are kept in RAM.
|
||||||
|
@ -196,6 +201,8 @@ namespace SaveState
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool USE_XOR = false;
|
||||||
|
|
||||||
void Compress(StateBuffer *result, std::vector<u8> &state, const std::vector<u8> &base)
|
void Compress(StateBuffer *result, std::vector<u8> &state, const std::vector<u8> &base)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> guard(lock_);
|
std::lock_guard<std::mutex> guard(lock_);
|
||||||
|
@ -205,26 +212,36 @@ namespace SaveState
|
||||||
|
|
||||||
double start_time = time_now_d();
|
double start_time = time_now_d();
|
||||||
std::vector<u8> compressed;
|
std::vector<u8> compressed;
|
||||||
compressed.reserve(512 * 1024);
|
if (USE_XOR) {
|
||||||
for (size_t i = 0; i < state.size(); i += BLOCK_SIZE)
|
compressed.resize(state.size());
|
||||||
{
|
for (size_t i = 0; i < state.size(); i++) {
|
||||||
int blockSize = std::min(BLOCK_SIZE, (int)(state.size() - i));
|
if (i >= base.size()) {
|
||||||
if (i + blockSize > base.size() || memcmp(&state[i], &base[i], blockSize) != 0)
|
compressed[i] = state[i];
|
||||||
{
|
} else {
|
||||||
compressed.push_back(1);
|
compressed[i] = base[i] ^ state[i];
|
||||||
compressed.insert(compressed.end(), state.begin() + i, state.begin() + i + blockSize);
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
compressed.reserve(512 * 1024);
|
||||||
|
for (size_t i = 0; i < state.size(); i += BLOCK_SIZE)
|
||||||
|
{
|
||||||
|
int blockSize = std::min(BLOCK_SIZE, (int)(state.size() - i));
|
||||||
|
if (i + blockSize > base.size() || memcmp(&state[i], &base[i], blockSize) != 0)
|
||||||
|
{
|
||||||
|
compressed.push_back(1);
|
||||||
|
compressed.insert(compressed.end(), state.begin() + i, state.begin() + i + blockSize);
|
||||||
|
} else {
|
||||||
|
compressed.push_back(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
compressed.push_back(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double taken_s = time_now_d() - start_time;
|
double taken_s = time_now_d() - start_time;
|
||||||
DEBUG_LOG(SAVESTATE, "Rewind: Compressed save from %d bytes to %d in %0.2f ms.", (int)state.size(), (int)compressed.size(), taken_s * 1000.0);
|
DEBUG_LOG(SAVESTATE, "Rewind: Compressed save from %d bytes to %d in %0.2f ms.", (int)state.size(), (int)compressed.size(), taken_s * 1000.0);
|
||||||
|
|
||||||
// Temporarily allocate a buffer to do decompression in.
|
// Temporarily allocate a buffer to do compression in.
|
||||||
size_t compressCapacity = ZSTD_compressBound(compressed.size());
|
size_t compressCapacity = ZSTD_compressBound(compressed.size());
|
||||||
u8 *compress_buf = (u8 *)malloc(compressCapacity);
|
u8 *compress_buf = (u8 *)malloc(compressCapacity);
|
||||||
|
|
||||||
result->compressed_size = ZSTD_compress(compress_buf, compressCapacity, compressed.data(), compressed.size(), 0);
|
result->compressed_size = ZSTD_compress(compress_buf, compressCapacity, compressed.data(), compressed.size(), 0);
|
||||||
if (result->compressed_size) {
|
if (result->compressed_size) {
|
||||||
result->zstd_compressed = std::vector<u8>(result->compressed_size, 0);
|
result->zstd_compressed = std::vector<u8>(result->compressed_size, 0);
|
||||||
|
@ -247,25 +264,35 @@ namespace SaveState
|
||||||
std::vector<u8> compressed = std::vector<u8>(buffer.decompressed_size, 0);
|
std::vector<u8> compressed = std::vector<u8>(buffer.decompressed_size, 0);
|
||||||
ZSTD_decompress(&compressed[0], compressed.size(), buffer.zstd_compressed.data(), buffer.zstd_compressed.size());
|
ZSTD_decompress(&compressed[0], compressed.size(), buffer.zstd_compressed.data(), buffer.zstd_compressed.size());
|
||||||
|
|
||||||
for (size_t i = 0; i < compressed.size(); )
|
if (USE_XOR) {
|
||||||
{
|
result.resize(compressed.size());
|
||||||
if (compressed[i] == 0)
|
for (size_t i = 0; i < compressed.size(); i++) {
|
||||||
{
|
if (i < base.size()) {
|
||||||
++i;
|
result[i] = compressed[i] ^ base[i];
|
||||||
int blockSize = std::min(BLOCK_SIZE, (int)(base.size() - result.size()));
|
} else {
|
||||||
result.insert(result.end(), basePos, basePos + blockSize);
|
result[i] = compressed[i];
|
||||||
basePos += blockSize;
|
}
|
||||||
}
|
}
|
||||||
else
|
} else {
|
||||||
{
|
for (size_t i = 0; i < compressed.size(); ) {
|
||||||
++i;
|
if (compressed[i] == 0) {
|
||||||
int blockSize = std::min(BLOCK_SIZE, (int)(compressed.size() - i));
|
++i;
|
||||||
result.insert(result.end(), compressed.begin() + i, compressed.begin() + i + blockSize);
|
int blockSize = std::min(BLOCK_SIZE, (int)(base.size() - result.size()));
|
||||||
i += blockSize;
|
_dbg_assert_(blockSize >= 0);
|
||||||
// This check is to avoid advancing basePos out of range, which MSVC catches.
|
result.insert(result.end(), basePos, basePos + blockSize);
|
||||||
// When this happens, we're at the end of decoding anyway.
|
|
||||||
if (base.end() - basePos >= blockSize) {
|
|
||||||
basePos += blockSize;
|
basePos += blockSize;
|
||||||
|
} else {
|
||||||
|
++i;
|
||||||
|
int blockSize = std::min(BLOCK_SIZE, (int)(compressed.size() - i));
|
||||||
|
if (blockSize > 0) {
|
||||||
|
result.insert(result.end(), compressed.begin() + i, compressed.begin() + i + blockSize);
|
||||||
|
i += blockSize;
|
||||||
|
// This check is to avoid advancing basePos out of range, which MSVC catches.
|
||||||
|
// When this happens, we're at the end of decoding anyway.
|
||||||
|
if (base.end() - basePos >= blockSize) {
|
||||||
|
basePos += blockSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -286,7 +313,7 @@ namespace SaveState
|
||||||
baseMapping_.clear();
|
baseMapping_.clear();
|
||||||
baseMapping_.resize(size_);
|
baseMapping_.resize(size_);
|
||||||
for (auto &s : states_) {
|
for (auto &s : states_) {
|
||||||
s.clear();
|
s.Clear();
|
||||||
}
|
}
|
||||||
buffer_.clear();
|
buffer_.clear();
|
||||||
base_ = -1;
|
base_ = -1;
|
||||||
|
|
Loading…
Add table
Reference in a new issue