forked from hhrhhr/Lua-utils-for-Rebel-Galaxy
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathunpack.lua
More file actions
148 lines (121 loc) · 3.48 KB
/
Copy pathunpack.lua
File metadata and controls
148 lines (121 loc) · 3.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
--[[
1 - MESH/MDL (MeshSerializer_v1.40/MeshSerializer_Runic)
2 - SKELETON (Serializer_v1.10)
3 - DDS
4 - PNG/TGA/BMP
6 - OGG/WAV
9 - MATERIAL
10 - RAW
12 - IMAGESET
13 - TTF
15 - DAT
16 - LAYOUT
17 - ANIMATION
24 - PROGRAM
25 - FONTDEF
26 - COMPOSITOR
27 - FRAG/FX/HLSL/VERT
29 - PU
30 - ANNO
31 - SBIN (OGRE)
32 - WDAT
--]]
assert("Lua 5.3" == _VERSION)
local zlib = require("zlib")
local lfs = require("lfs")
local in_file = assert(arg[1], "no input")
local out_path = arg[2] or "debug"
local filter = tonumber(arg[3]) or nil
local function fromutf16le(str)
local s = string.gsub(str, "(.)\x00", "%1")
return s
end
local function mkdir(name)
local fullname = out_path .. "\\" .. name
local ok, msg = lfs.mkdir(fullname)
if true ~= ok and "File exists" ~= msg then
assert(false, msg)
end
end
local r
local function uint32() return string.unpack("<I", r:read(4)) end
local function uint16() return string.unpack("<H", r:read(2)) end
local function uint8() return string.unpack("B", r:read(1)) end
local function savefile(offset, fullname)
r:seek("set", offset)
local size = uint32()
local zsize = uint32()
local data = r:read(zsize)
local stream = zlib.inflate()
local eof, bytes_in, bytes_out
data, eof, bytes_in, bytes_out = stream(data)
assert(true == eof, "eof ~= true")
assert(zsize == bytes_in, "bytes_in mismatch")
assert(size == bytes_out, "bytes_out mismatch")
local w = assert(io.open(fullname, "w+b"))
w:write(data)
w:close()
end
--[[ main ]]--------------------------------------------------------------------
r = assert(io.open(in_file, "rb"))
-- check for big files support
local r_size = r:seek("end")
assert(-1 ~= r_size, "this Lua doesn't support files larger than 2 Gb")
r:seek("set")
local tmp
tmp = uint32() -- \x01\x00\x00\x00
tmp = uint16() -- \x00\x00
local filename_offset = uint32()
local flags = uint32() -- \x80\x00\x00\x01
r:seek("set", filename_offset)
local entries = uint32()
local count = uint32()
if "debug" == out_path then
print(entries, count)
end
for i = 1, count do
local len = uint16()
local name = r:read(len * 2)
local current_dir = fromutf16le(name):gsub("/", "\\")
if "debug" == out_path then
print("\n" .. i .. "/" .. count, current_dir)
else
mkdir(current_dir)
end
local count = uint32()
for j = 1, count do
local _crc = ("%08X"):format(uint32())
local typ = uint8()
local len = uint16()
local name = r:read(len * 2)
local offset = uint32()
local _unp = uint32()
local fn = fromutf16le(name)
fn = fn:gsub("/", "\\")
if "debug" == out_path then
local out = "%9s %s %2d %10d %8d %s"
print(out:format(j .. "/" .. count, _crc, typ, offset, _unp, fn))
else
local fullname = current_dir .. fn
if 8 == typ then
print("[" .. fullname .. "]")
mkdir(fullname)
elseif filter == nil or typ == filter then
print(fullname)
local save_pos = r:seek()
fullname = out_path .. "\\" .. current_dir .. typ .. "_" .. fn
savefile(offset, fullname)
r:seek("set", save_pos)
end
end
entries = entries - 1
end
end
if entries > 0 then
print("!!! left entries: " .. entries)
end
local left = r_size - r:seek()
if left > 0 then
print("!!! left unreaded: " .. left)
end
r:close()