/
05_read_binary_format_2.lua
105 lines (73 loc) · 2.42 KB
/
05_read_binary_format_2.lua
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
-- Description: Updated binary file io to read Crimsonland data files --
--[[
This is my 2nd attempt to re-write my Crimsonland data file python script in
lua. Again avoided 3rd party libraries.
This seems much nicer, but I'm not 100% sure about wrapping a file object
I'm going to need to learn terminology too, file object? file table?
file handle? file is the handle, but it has a metatable pointed it
to the table file that has methods on it...
----
I just spent two hours debugging this POS. I thought I had a off by one error
then I thought it must have been a scope error (global clobbering) then a
reference error (how are file handles copied/assigned). Turned out to be
missing qoutes about 'rb' in io.open. Fuck me.
Use require('strict') always, always fucking always
]]
require('strict')
BinaryFile = {}
BinaryFile.new = function(file)
return setmetatable({file=file}, {__index=BinaryFile})
end
BinaryFile.readint32 = function(self)
local data = self.file:read(4)
return (data:byte(4) * (256^3)) +
(data:byte(3) * (256^2)) +
(data:byte(2) * (256^1)) +
(data:byte(1) * (256^0))
end
BinaryFile.readnulstring = function(self)
local buf = ''
while true do
local ch = self.file:read(1)
if ch:byte() == 0 then break end
buf = buf .. ch
end
return buf
end
BinaryFile.read = function(self, ...)
return self.file:read(...)
end
BinaryFile.skip = BinaryFile.read
BinaryFile.seek = function(self, ...)
return self.file:seek(...)
end
local readindex = function(filename)
local f = io.open(filename, 'rb')
local bf = BinaryFile.new(f)
-- Header
assert(bf:readnulstring() == 'PAK')
assert(bf:readnulstring() == 'V11')
-- index offsets
local indexstartoffset = bf:readint32()
local indexendoffset = bf:readint32()
-- just to index
bf:seek('set', indexstartoffset)
-- number of entries
local indexsize = bf:readint32()
local index = {}
for i=1, indexsize do
table.insert(index, {
name = bf:readnulstring(),
offset = bf:readint32(),
length = bf:readint32()
})
-- Unknown (junk?)
bf:skip(8)
end
f:close()
return index
end
local index = readindex('D:\\Steam\\steamapps\\common\\Crimsonland\\data.pak')
for _,v in ipairs(index) do
print(string.format('name:%s offset:%d length:%d', v.name, v.offset, v.length))
end