Last active
May 18, 2021 22:17
-
-
Save uyjulian/c026f3ba0234de3dbfde16607c5a4b38 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- You are probably going to have a much, much better time using my Python implementation… | |
-- https://gist.github.com/uyjulian/55475c98c631632ddfd5453469726439 | |
file_util = require"file_util" | |
ffi = require"ffi" | |
bit = require"bit" | |
S = require"syscall" | |
struct = require"struct" | |
dir = arg[1] .. "_" | |
S.mkdir(dir, "RWXU") | |
f = io.open(arg[1], "rb") | |
indat = f\read("*a") | |
f\close() | |
___1, total, bl = struct.unpack("<I4I4", indat) | |
--the first uint32 is all zeros... | |
--print("filecount: " .. total) | |
trim = (s) -> | |
return s\match'^%z*(.*%Z)' or '' | |
--get entries | |
filez = {} | |
num = total | |
ffi.cdef[[void * memmove(void *dst, const void *src, size_t len);]] | |
decompress = (v) -> | |
des, bl = struct.unpack("<I4", indat, bl) | |
if des ~= v.decsize | |
des = (des > v.decsize) and des or v.decsize | |
cms, bl = struct.unpack("<I4", indat, bl) | |
if (cms ~= v.cmpsize) and ((v.cmpsize - cms) ~= 4) | |
error("compression size in header and stream don't match") | |
num3, bl = struct.unpack("<I4", indat, bl) | |
fin = bl + cms - 13 | |
cd = ffi.new("unsigned char[?]", des) | |
i = 0 | |
num4 = 0 | |
while bl <= fin | |
i += 1 | |
b, bl = struct.unpack("<I1", indat, bl) | |
if b == num3 | |
i += 1 | |
b2, bl = struct.unpack("<I1", indat, bl) | |
if b2 ~= num3 | |
i += 1 | |
if b2 >= num3 | |
b2 -= 1 | |
b3, bl = struct.unpack("<I1", indat, bl) | |
ffi.C.memmove(cd + (num4), cd + (num4 - b2), b3) | |
num4 += b3 | |
else | |
cd[num4] = b2 | |
num4 += 1 | |
else | |
cd[num4] = b | |
num4 += 1 | |
return ffi.string(cd, des) | |
while num ~= 0 | |
num -= 1 | |
filename, bl = struct.unpack("<c64", indat, bl) | |
filename = trim(filename) | |
decsize, cmpsize, offset, flags, bl = struct.unpack("<I4I4I4I4", indat, bl) | |
compressed = bit.band(flags, 1) ~= 0 | |
skip4bytes = bit.band(flags, 2) ~= 0 | |
filez[total - num] = {:filename, :cmpsize, :decsize, :offset, :flags, :compressed, :skip4bytes} | |
--extract entries | |
for i, v in ipairs(filez) | |
-- print("filename: " .. v.filename) | |
-- print("compressed size: " .. v.cmpsize) | |
-- print("decompressed size: " .. v.decsize) | |
-- print("offset: " .. v.offset) | |
-- print("extra flags: 0x" .. bit.tohex(v.flags)) | |
-- print("compressed: " .. (v.compressed and "true" or "false")) | |
-- print("skip 4 bytes: " .. (v.skip4bytes and "true" or "false")) | |
-- print("file number: " .. i) | |
bl = v.offset + 1 | |
data = "" | |
if v.skip4bytes | |
bl += 4 | |
if v.compressed | |
data = decompress(v) | |
else | |
if v.cmpsize ~= v.decsize | |
error("compress size is not equal to decompress size") | |
data = string.sub(indat, bl, bl + v.decsize) | |
file_util.writefile(dir .. "/" .. v.filename, data) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment