-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparseLocres.lua
More file actions
150 lines (112 loc) · 3.89 KB
/
Copy pathparseLocres.lua
File metadata and controls
150 lines (112 loc) · 3.89 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
149
150
-- set to false to not check magic number
local MATCH_MAGIC = true
-- file to read from current directory
local LOCRES_FILE = "Game.locres"
local Buffer = require "buffer".Buffer
local fs = require "fs"
local function toUtf16LE(s)
local o = {}
for i = 1, #s do
o[#o+1] = s:sub(i,i)
o[#o+1] = '\x00'
end
return table.concat(o)
end
local buf = Buffer:new(assert(fs.readFileSync(LOCRES_FILE)))
local tag = os.date("%Y-%m-%d", fs.statSync(LOCRES_FILE).mtime.sec) -- YYYY-mm-dd
-- check header if file is a proper locres file
local MAGIC = "\x0E\x14\x74\x75\x67\x4A\x03\xFC"
assert((not MATCH_MAGIC) or buf:toString(1,8) == MAGIC, "ERROR: Hader magic doesn't match! Probably wrong locres ver.")
----- Strings -----
-- { str = "string", isUtf16 = true/false }[], 0 index C table
local strings = {}
local pos = buf:readUInt32LE(0x11 + 1) + 1
local size = buf:readUInt32LE(pos); pos = pos + 4;
for i = 0, size-1 do
local str
local isUtf16 = false
local strLen = buf:readInt32LE(pos); pos = pos + 4;
-- negative length: utf-16 --
if strLen < 0 then
strLen = -strLen * 2
str = buf:toString(pos, pos + strLen-1 - 2); pos = pos + strLen;
isUtf16 = true
else
str = buf:toString(pos, pos + strLen-1 - 1); pos = pos + strLen;
end
local users = buf:readUInt32LE(pos); pos = pos + 4;
strings[i] = { str = str, isUtf16 = isUtf16 }
end
----- Keys -----
-- { namespace = "namespaceName", key = "key", isUtf16 = true/false, valueId = 3 }[], 1 index normal Lua table
local keys = {}
local namespaceCount = buf:readUInt32LE(0x1D + 1)
pos = 0x21 + 1
for _ = 1, namespaceCount do
local nsHash = buf:readUInt32LE(pos); pos = pos + 4;
local nsNameLen = buf:readInt32LE(pos); pos = pos + 4;
local nsName
if nsNameLen <= 1 then
nsName = "_internal_"
pos = pos + (nsNameLen == 0 and 0 or 1);
else
nsName = buf:toString(pos, pos + nsNameLen-1 - 1); pos = pos + nsNameLen;
end
local nsItems = buf:readUInt32LE(pos); pos = pos + 4;
for _ = 1, nsItems do
local key
local isUtf16 = false
local keyHash1 = buf:readUInt32LE(pos); pos = pos + 4;
local keyLen = buf:readInt32LE(pos); pos = pos + 4;
if keyLen < 0 then -- utf16 --
keyLen = -keyLen * 2
key = buf:toString(pos, pos + keyLen-1 - 2); pos = pos + keyLen;
isUtf16 = true
else
key = buf:toString(pos, pos + keyLen-1 - 1); pos = pos + keyLen;
end
local keyHash2 = buf:readUInt32LE(pos); pos = pos + 4;
local valueId = buf:readUInt32LE(pos); pos = pos + 4;
table.insert(keys, {
namespace = nsName,
key = key,
isUtf16 = isUtf16,
valueId = valueId
})
end
end
----- Output -----
-- use io.open for writing in chunks
local out = assert(io.open(LOCRES_FILE .. "_" .. tag .. ".txt", 'wb'))
for _, key in ipairs(keys) do
local left
if key.isUtf16 then
if key.key:find('[="\\]\0') then
left = '"\0'..toUtf16LE(key.namespace..'.')..key.key:gsub('\\\0','\\\0\\\0'):gsub('"\0','\\\0"\0')..'"\0'
else
left = toUtf16LE(key.namespace..'.')..key.key
end
else
if key.key:find('[="\\]') then
left = toUtf16LE('"'..key.namespace..'.'..key.key:gsub('\\','\\\\'):gsub('"','\\"')..'"')
else
left = toUtf16LE(key.namespace..'.'..key.key)
end
end
local val = strings[key.valueId]
local right
if val.isUtf16 then
if val.str:find('\n\0') then
val.str = toUtf16LE('"""\n')..val.str..toUtf16LE('\n"""')
end
right = val.str
else
if val.str:find('\n') then
val.str = '"""\n'..val.str..'\n"""'
end
right = toUtf16LE(val.str)
end
out:write(left..'=\0'..right..'\n\0')
end
out:close()
print("Done.")