init
This commit is contained in:
commit
87bff164f1
416 files changed
+279512
No files matched your search
@@ -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
|
||||
Reference in new issue
Block a user