Add LZ11 Decompression
- Add getetrs for bclim - Correctly load all bclim data - Fix RGB565ToRGBA converter to support all sizes possible
This commit is contained in:
@@ -22,7 +22,7 @@ class CTRFF_API _3dsx : public BinFile {
|
|||||||
void Write(std::fstream& f) const override;
|
void Write(std::fstream& f) const override;
|
||||||
void Read(std::fstream& f) override;
|
void Read(std::fstream& f) override;
|
||||||
|
|
||||||
ctrff::u32 Magic;
|
ctrff::u32 Magic; // 0x58534433 "3DSX"
|
||||||
ctrff::u16 HeaderSize;
|
ctrff::u16 HeaderSize;
|
||||||
ctrff::u16 RelocHeaderSize;
|
ctrff::u16 RelocHeaderSize;
|
||||||
ctrff::u32 FormatVersion;
|
ctrff::u32 FormatVersion;
|
||||||
|
|||||||
@@ -81,6 +81,11 @@ class CTRFF_API BCLIM : public BinFile {
|
|||||||
|
|
||||||
void CreateByImage(const std::vector<u8>& data, int w, int h, Format fmt);
|
void CreateByImage(const std::vector<u8>& data, int w, int h, Format fmt);
|
||||||
|
|
||||||
|
Format GetFmt() const { return (Format)pImag.Format; }
|
||||||
|
std::vector<u8> GetImage() { return pBuffer; }
|
||||||
|
int GetWidth() const { return pImag.Width; }
|
||||||
|
int GetHeight() const { return pImag.Height; }
|
||||||
|
|
||||||
/** Write not supported btw */
|
/** Write not supported btw */
|
||||||
void Write(std::fstream& f) const override;
|
void Write(std::fstream& f) const override;
|
||||||
void Read(std::fstream& f) override;
|
void Read(std::fstream& f) override;
|
||||||
|
|||||||
@@ -5,5 +5,6 @@
|
|||||||
namespace ctrff {
|
namespace ctrff {
|
||||||
namespace LZ11 {
|
namespace LZ11 {
|
||||||
CTRFF_API std::vector<ctrff::u8> Compress(const std::vector<ctrff::u8>& in);
|
CTRFF_API std::vector<ctrff::u8> Compress(const std::vector<ctrff::u8>& in);
|
||||||
}
|
CTRFF_API std::vector<ctrff::u8> Decompress(const std::vector<ctrff::u8>& in);
|
||||||
|
} // namespace LZ11
|
||||||
} // namespace ctrff
|
} // namespace ctrff
|
||||||
@@ -18,22 +18,23 @@ CTRFF_API void BCLIM::Write(std::fstream& f) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CTRFF_API void BCLIM::Read(std::fstream& f) {
|
CTRFF_API void BCLIM::Read(std::fstream& f) {
|
||||||
f.seekg(std::ios::end);
|
f.seekg(0, std::ios::end);
|
||||||
size_t size = f.tellg();
|
size_t size = f.tellg();
|
||||||
if (size < (sizeof(Header) + sizeof(ImagHeader))) {
|
if (size < (sizeof(Header) + sizeof(ImagHeader))) {
|
||||||
throw std::runtime_error("Invalid File!");
|
throw std::runtime_error("Invalid File!");
|
||||||
}
|
}
|
||||||
f.seekg(size - sizeof(Header) - sizeof(ImagHeader));
|
f.seekg(size - sizeof(Header) - sizeof(ImagHeader));
|
||||||
Header h;
|
f.read(reinterpret_cast<char*>(&pCurrent), sizeof(pCurrent));
|
||||||
ImagHeader imag;
|
f.read(reinterpret_cast<char*>(&pImag), sizeof(pImag));
|
||||||
f.read(reinterpret_cast<char*>(&h), sizeof(h));
|
if (pCurrent.Magic != 0x4d494c43) {
|
||||||
f.read(reinterpret_cast<char*>(&imag), sizeof(imag));
|
|
||||||
if (h.Magic != 0x4d494c43) {
|
|
||||||
throw std::runtime_error("[ctrff] BCLIM: Not a bclim file!");
|
throw std::runtime_error("[ctrff] BCLIM: Not a bclim file!");
|
||||||
}
|
}
|
||||||
if (imag.Magic != 0x67616d69) {
|
if (pImag.Magic != 0x67616d69) {
|
||||||
throw std::runtime_error("[ctrff] BCLIM: Invalid Data");
|
throw std::runtime_error("[ctrff] BCLIM: Invalid Data");
|
||||||
}
|
}
|
||||||
|
f.seekg(0, std::ios::beg);
|
||||||
|
pBuffer.resize(pImag.ImageSize);
|
||||||
|
f.read(reinterpret_cast<char*>(pBuffer.data()), pBuffer.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
CTRFF_API void BCLIM::CreateByImage(const std::vector<u8>& data, int w, int h,
|
CTRFF_API void BCLIM::CreateByImage(const std::vector<u8>& data, int w, int h,
|
||||||
|
|||||||
@@ -30,9 +30,9 @@ CTRFF_API ctrff::u32 ctrff::TileIndex(const int &x, const int &y,
|
|||||||
CTRFF_API void ctrff::RGB565toRGBA(std::vector<ctrff::u8> &img,
|
CTRFF_API void ctrff::RGB565toRGBA(std::vector<ctrff::u8> &img,
|
||||||
ctrff::u16 *icon, const int &w,
|
ctrff::u16 *icon, const int &w,
|
||||||
const int &h) {
|
const int &h) {
|
||||||
if (img.size() != (48 * 48 * 4)) {
|
if (img.size() != (w * h * 4)) {
|
||||||
img.resize(48 * 48 * 4);
|
|
||||||
img.clear();
|
img.clear();
|
||||||
|
img.resize(w * h * 4);
|
||||||
}
|
}
|
||||||
for (int y = 0; y < h; y++) {
|
for (int y = 0; y < h; y++) {
|
||||||
for (int x = 0; x < w; x++) {
|
for (int x = 0; x < w; x++) {
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ ctrff::u32 GetOccurenceLength(const ctrff::u8* new_ptr, u32 new_len,
|
|||||||
|
|
||||||
CTRFF_API std::vector<ctrff::u8> Compress(const std::vector<ctrff::u8>& in) {
|
CTRFF_API std::vector<ctrff::u8> Compress(const std::vector<ctrff::u8>& in) {
|
||||||
if (in.size() > 0xFFFFFF) {
|
if (in.size() > 0xFFFFFF) {
|
||||||
std::cout << "ERROR: LZ11 input is too large!" << std::endl;
|
throw std::runtime_error("[ctrff] LZ11: Input is tool large to compress");
|
||||||
return std::vector<ctrff::u8>();
|
return std::vector<ctrff::u8>();
|
||||||
}
|
}
|
||||||
std::stringstream s;
|
std::stringstream s;
|
||||||
@@ -121,5 +121,55 @@ CTRFF_API std::vector<ctrff::u8> Compress(const std::vector<ctrff::u8>& in) {
|
|||||||
std::string tmp = s.str();
|
std::string tmp = s.str();
|
||||||
return std::vector<u8>(tmp.begin(), tmp.end());
|
return std::vector<u8>(tmp.begin(), tmp.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Baed on
|
||||||
|
// https://github.com/Gericom/EveryFileExplorer/blob/master/CommonCompressors/LZ11.cs
|
||||||
|
// Needs some fixes cause this code looks very unsafe to me tbh
|
||||||
|
CTRFF_API std::vector<ctrff::u8> Decompress(const std::vector<ctrff::u8>& in) {
|
||||||
|
if (!in.size()) {
|
||||||
|
throw std::runtime_error("[ctrff] LZ11: Cannot decompress empty buffer!");
|
||||||
|
}
|
||||||
|
if (in[0] != 0x11) {
|
||||||
|
throw std::runtime_error("[ctrff] LZ11: Not a lz11 file!");
|
||||||
|
}
|
||||||
|
u32 len = in[1] | (in[2] << 8) | (in[3] << 16);
|
||||||
|
std::vector<u8> ret(len, 0x0);
|
||||||
|
int off = 4;
|
||||||
|
int dst_off = 0;
|
||||||
|
while (true) {
|
||||||
|
u8 header = in[off++];
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
if ((header & 0x80) == 0) {
|
||||||
|
ret[dst_off++] = in[off++];
|
||||||
|
} else {
|
||||||
|
u8 a = in[off++];
|
||||||
|
int off2;
|
||||||
|
int length;
|
||||||
|
if ((a >> 4) == 0) {
|
||||||
|
u8 b = in[off++];
|
||||||
|
u8 c = in[off++];
|
||||||
|
length = (((a & 0xF) << 4) | (b >> 4)) + 0x11;
|
||||||
|
off2 = (((b & 0xF) << 8) | c) + 1;
|
||||||
|
} else if ((a >> 4) == 1) {
|
||||||
|
u8 b = in[off++];
|
||||||
|
u8 c = in[off++];
|
||||||
|
u8 d = in[off++];
|
||||||
|
length = (((a & 0xF) << 12) | (b << 4) | (c >> 4)) + 0x111;
|
||||||
|
off2 = (((c & 0xF) << 8) | d) + 1;
|
||||||
|
} else {
|
||||||
|
u8 b = in[off++];
|
||||||
|
off2 = (((a & 0xF) << 8) | b) + 1;
|
||||||
|
length = (a >> 4) + 1;
|
||||||
|
}
|
||||||
|
for (int j = 0; j < length; j++) {
|
||||||
|
ret[dst_off] = ret[dst_off - off2];
|
||||||
|
dst_off++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dst_off >= len) return ret;
|
||||||
|
header <<= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} // namespace LZ11
|
} // namespace LZ11
|
||||||
} // namespace ctrff
|
} // namespace ctrff
|
||||||
Reference in New Issue
Block a user