This commit is contained in:
Gaël committed 2026-10-19 20:59:15 +02:00
commit 87bff164f1
416 files changed
+279512

No files matched your search

+60
View File
@@ -0,0 +1,60 @@
#pragma once
// FastLZ (level 1 and 2) block decompressor, as used by Noita for chunk files and stream info.
// The level is in the top 3 bits of the first byte (0 = level 1, 1 = level 2).
#include <cstddef>
#include <cstdint>
#include <vector>
namespace ng {
// Returns false on malformed input or if the output would exceed max_out.
inline bool fastlz_decompress(const uint8_t* in, size_t in_len, std::vector<uint8_t>& out, size_t max_out) {
out.clear();
if (in_len == 0) return true;
const int level = (in[0] >> 5) + 1;
if (level != 1 && level != 2) return false;
size_t ip = 0;
uint32_t ctrl = in[ip++] & 31;
for (;;) {
if (ctrl >= 32) {
uint32_t len = (ctrl >> 5) - 1;
uint32_t ofs = (ctrl & 31) << 8;
if (len == 6) {
uint8_t code;
do {
if (ip >= in_len) return false;
code = in[ip++];
len += code;
} while (code == 255 && level == 2);
if (level == 1 && false) return false;
}
if (ip >= in_len) return false;
const uint8_t code = in[ip++];
ofs += code;
size_t back;
if (level == 2 && code == 255 && (ctrl & 31) == 31) {
if (ip + 1 >= in_len) return false;
ofs = ((uint32_t)in[ip] << 8) + in[ip + 1];
ip += 2;
back = (size_t)ofs + 8191 + 1; // 16-bit distance: MAX_L2_DISTANCE + 1 (the +1 is easy to miss)
} else {
back = (size_t)ofs + 1;
}
if (back > out.size()) return false;
len += 3;
if (out.size() + len > max_out) return false;
size_t ref = out.size() - back;
for (uint32_t k = 0; k < len; ++k) out.push_back(out[ref + k]);
} else {
const size_t n = (size_t)ctrl + 1;
if (ip + n > in_len || out.size() + n > max_out) return false;
out.insert(out.end(), in + ip, in + ip + n);
ip += n;
}
if (ip >= in_len) break;
ctrl = in[ip++];
}
return true;
}
} // namespace ng