lainTSX/scripts/extract/lain_compress.js
2021-06-05 20:51:04 +09:30

40 lines
1.4 KiB
JavaScript

const KaitaiStream = require('kaitai-struct/KaitaiStream');
// based on https://github.com/magical/nlzss/blob/master/lzss3.py and https://github.com/m35/jpsxdec/blob/readme/laintools/src/laintools/Lain_Pk.java
class LainCompress {
decode (io) {
const bits = (byte) => { return [(byte >> 7) & 1, (byte >> 6) & 1,(byte >> 5) & 1,(byte >> 4) & 1,(byte >> 3) & 1,(byte >> 2) & 1, (byte >> 1) & 1, (byte) & 1] };
let compressed = new KaitaiStream(io);
let decompressed_size = compressed.readU4le();
let decompressed = Buffer.alloc(decompressed_size);
let decompressed_pos = 0;
while (decompressed_pos < decompressed_size) {
let flags = bits(compressed.readU1());
for (let flag of flags) {
if (flag === 0) {
decompressed[decompressed_pos] = compressed.readBytes(1);
decompressed_pos++;
}
else if (flag === 1) {
let offset = compressed.readU1() + 1;
let size = compressed.readU1() + 3;
for (let i = 0; i < size; i++) {
decompressed[decompressed_pos] = decompressed[decompressed_pos - offset];
decompressed_pos++;
}
}
if (decompressed_size <= decompressed_pos) break;
}
}
if (decompressed.length !== decompressed_size)
throw new Error("Decompressed size does not match the expected size!");
return decompressed;
}
}
module.exports = LainCompress;