Files
ctrff-pub/source/lz11.cpp

125 lines
3.3 KiB
C++
Raw Normal View History

2025-05-04 13:32:07 +02:00
#include <cstring>
#include <ctrff/lz11.hpp>
/// REWRITTEN CODE FROM BANNERTOOL !!!!!!
namespace ctrff {
namespace LZ11 {
ctrff::u32 GetOccurenceLength(const ctrff::u8* new_ptr, u32 new_len,
const ctrff::u8* old_ptr, u32 old_len,
2025-12-06 21:34:19 +01:00
ctrff::u32& disp) {
2025-05-04 13:32:07 +02:00
disp = 0;
if (new_len == 0) {
return 0;
}
2025-12-06 21:34:19 +01:00
ctrff::u32 res = 0;
2025-05-04 13:32:07 +02:00
if (old_len > 0) {
for (u32 i = 0; i < old_len - 1; i++) {
2025-05-04 13:32:07 +02:00
auto ref = old_ptr + i;
u32 len = 0;
for (u32 j = 0; j < new_len; j++) {
if (*(ref + j) != *(new_ptr + j)) {
2025-05-04 13:32:07 +02:00
break;
}
len++;
}
if (len > res) {
res = len;
disp = old_len - i;
if (res == new_len) {
break;
}
}
}
}
return res;
}
2025-12-06 21:34:19 +01:00
CTRFF_API std::vector<ctrff::u8> Compress(const std::vector<ctrff::u8>& in) {
2025-05-04 13:32:07 +02:00
if (in.size() > 0xFFFFFF) {
std::cout << "ERROR: LZ11 input is too large!" << std::endl;
2025-12-06 21:34:19 +01:00
return std::vector<ctrff::u8>();
2025-05-04 13:32:07 +02:00
}
std::stringstream s;
struct header {
u8 Magic;
u8 Size1;
u8 Size2;
u8 Size3;
};
header hdr;
hdr.Magic = 0x11;
hdr.Size1 = in.size() & 0xFF;
hdr.Size2 = (in.size() >> 8) & 0xFF;
hdr.Size3 = (in.size() >> 16) & 0xFF;
2025-05-04 13:32:07 +02:00
// SETUP HEADER //
s.write(reinterpret_cast<const char*>(&hdr), sizeof(hdr));
2025-05-04 13:32:07 +02:00
u32 res_len = 4; // 4-byte header
2025-12-06 21:34:19 +01:00
ctrff::u8 out_buf[0x21]; // 33 bytes
memset(out_buf, 0x0, sizeof(out_buf));
u32 obl = 1; // out_buf_len
u32 buf_blocks = 0;
u32 rb = 0;
2025-05-04 13:32:07 +02:00
while (rb < in.size()) {
if (buf_blocks == 8) {
2025-05-04 13:32:07 +02:00
s.write(reinterpret_cast<const char*>(out_buf), obl);
res_len += obl;
memset(out_buf, 0x0, sizeof(out_buf));
2025-05-04 13:32:07 +02:00
obl = 1;
buf_blocks = 0;
}
2025-12-06 21:34:19 +01:00
ctrff::u32 disp = 0;
u32 old_len = std::min(rb, static_cast<u32>(0x1000));
u32 len = LZ11::GetOccurenceLength(
in.data() + rb,
std::min((u32)in.size() - rb, static_cast<u32>(0x10110)),
2025-05-04 13:32:07 +02:00
in.data() + rb - old_len, old_len, disp);
if (len < 3) {
out_buf[obl++] = in[rb++];
} else {
rb += len;
2025-12-06 21:34:19 +01:00
out_buf[0] |= static_cast<ctrff::u8>(1 << (7 - buf_blocks));
2025-05-04 13:32:07 +02:00
if (len > 0x110) {
out_buf[obl] = 0x10;
out_buf[obl] |= static_cast<ctrff::u8>(((len - 0x111) >> 12) & 0x0F);
obl++;
out_buf[obl] = static_cast<ctrff::u8>(((len - 0x111) >> 4) & 0xFF);
obl++;
2025-12-06 21:34:19 +01:00
out_buf[obl] = static_cast<ctrff::u8>(((len - 0x111) << 4) & 0xF0);
2025-05-04 13:32:07 +02:00
} else if (len > 0x10) {
out_buf[obl] = 0x00;
out_buf[obl] |= static_cast<ctrff::u8>(((len - 0x111) >> 4) & 0x0F);
obl++;
out_buf[obl] = static_cast<ctrff::u8>(((len - 0x111) << 4) & 0xF0);
2025-05-04 13:32:07 +02:00
} else {
out_buf[obl] = static_cast<ctrff::u8>(((len - 1) << 4) & 0xF0);
2025-05-04 13:32:07 +02:00
}
out_buf[obl] |= static_cast<ctrff::u8>(((disp - 1) >> 8) & 0x0F);
obl++;
out_buf[obl] = static_cast<ctrff::u8>((disp - 1) & 0xFF);
2025-05-04 13:32:07 +02:00
obl++;
}
buf_blocks++;
}
if (buf_blocks > 0) {
s.write(reinterpret_cast<const char*>(out_buf), obl);
res_len += obl;
}
if (res_len % 4 != 0) {
2025-12-06 21:34:19 +01:00
ctrff::u32 pad_len = 4 - (res_len % 4);
ctrff::u8 pad[4] = {0};
2025-05-04 13:32:07 +02:00
s.write(reinterpret_cast<const char*>(pad), pad_len);
res_len += pad_len;
}
std::string tmp = s.str();
return std::vector<u8>(tmp.begin(), tmp.end());
2025-05-04 13:32:07 +02:00
}
} // namespace LZ11
} // namespace ctrff