grf-file-extractor 1.0.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -0
- package/dist/index.js +32 -0
- package/dist/index.mjs +7 -0
- package/index.js +192 -0
- package/lib/Loaders/GameFile.js +368 -0
- package/lib/Loaders/GameFileDecrypt.js +346 -0
- package/lib/Utils/BinaryReader.js +334 -0
- package/lib/Utils/BinaryWriter.js +326 -0
- package/lib/Utils/Inflate.js +382 -0
- package/lib/Utils/Struct.js +76 -0
- package/lib/Vendors/text-encoding.js +2494 -0
- package/lib/cps.js +72 -0
- package/lib/extractor.js +258 -0
- package/lib/grf.js +41 -0
- package/package.json +24 -0
- package/profile.js +17 -0
- package/src/index.ts +3 -0
- package/tsconfig.json +18 -0
- package/tsup.config.ts +10 -0
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loaders/GameFileDecrypt.js
|
|
3
|
+
*
|
|
4
|
+
* Decrypt Gravity DES encryption stored in GRF file
|
|
5
|
+
* Converted from https://rathena.svn.sourceforge.net/svnroot/rathena/trunk/src/common/des.c
|
|
6
|
+
*
|
|
7
|
+
* This file is part of ROBrowser, Ragnarok Online in the Web Browser (http://www.robrowser.com/).
|
|
8
|
+
*
|
|
9
|
+
* @author Vincent Thibault
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
"use strict";
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
var mask = new Uint8Array([0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01]);
|
|
16
|
+
var tmp = new Uint8Array(8);
|
|
17
|
+
var tmp2 = new Uint8Array(8);
|
|
18
|
+
var clean = new Uint8Array(8);
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Initial permutation (IP).
|
|
23
|
+
*
|
|
24
|
+
* @param {Uint8Array} src
|
|
25
|
+
* @param {number} index
|
|
26
|
+
*/
|
|
27
|
+
function initialPermutation( src, index )
|
|
28
|
+
{
|
|
29
|
+
var i, j;
|
|
30
|
+
|
|
31
|
+
for (i = 0; i < 64; ++i) {
|
|
32
|
+
j = initialPermutation.table[i] - 1;
|
|
33
|
+
if (src[ index + ((j >> 3) & 7) ] & mask[j & 7]) {
|
|
34
|
+
tmp[(i >> 3) & 7] |= mask[i & 7];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
src.set(tmp, index);
|
|
39
|
+
tmp.set(clean);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
initialPermutation.table = new Uint8Array([
|
|
43
|
+
58, 50, 42, 34, 26, 18, 10, 2,
|
|
44
|
+
60, 52, 44, 36, 28, 20, 12, 4,
|
|
45
|
+
62, 54, 46, 38, 30, 22, 14, 6,
|
|
46
|
+
64, 56, 48, 40, 32, 24, 16, 8,
|
|
47
|
+
57, 49, 41, 33, 25, 17, 9, 1,
|
|
48
|
+
59, 51, 43, 35, 27, 19, 11, 3,
|
|
49
|
+
61, 53, 45, 37, 29, 21, 13, 5,
|
|
50
|
+
63, 55, 47, 39, 31, 23, 15, 7
|
|
51
|
+
]);
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Final permutation (IP^-1).
|
|
56
|
+
*
|
|
57
|
+
* @param {Uint8Array} src
|
|
58
|
+
* @param {number} index
|
|
59
|
+
*/
|
|
60
|
+
function finalPermutation( src, index )
|
|
61
|
+
{
|
|
62
|
+
var i, j;
|
|
63
|
+
|
|
64
|
+
for (i = 0; i<64; ++i) {
|
|
65
|
+
j = finalPermutation.table[i] - 1;
|
|
66
|
+
if (src[ index + ((j >> 3) & 7) ] & mask[j & 7]) {
|
|
67
|
+
tmp[ (i >> 3) & 7 ] |= mask[i & 7];
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
src.set(tmp, index);
|
|
72
|
+
tmp.set(clean);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
finalPermutation.table = new Uint8Array([
|
|
76
|
+
40, 8, 48, 16, 56, 24, 64, 32,
|
|
77
|
+
39, 7, 47, 15, 55, 23, 63, 31,
|
|
78
|
+
38, 6, 46, 14, 54, 22, 62, 30,
|
|
79
|
+
37, 5, 45, 13, 53, 21, 61, 29,
|
|
80
|
+
36, 4, 44, 12, 52, 20, 60, 28,
|
|
81
|
+
35, 3, 43, 11, 51, 19, 59, 27,
|
|
82
|
+
34, 2, 42, 10, 50, 18, 58, 26,
|
|
83
|
+
33, 1, 41, 9, 49, 17, 57, 25
|
|
84
|
+
]);
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Transposition (P-BOX).
|
|
89
|
+
*
|
|
90
|
+
* @param {Uint8Array} src
|
|
91
|
+
* @param {number} index
|
|
92
|
+
*/
|
|
93
|
+
function transposition( src, index )
|
|
94
|
+
{
|
|
95
|
+
var i, j;
|
|
96
|
+
|
|
97
|
+
for (i = 0; i<32; ++i) {
|
|
98
|
+
j = transposition.table[i] - 1;
|
|
99
|
+
if (src[ index + (j >> 3) ] & mask[j & 7]) {
|
|
100
|
+
tmp[(i >> 3) + 4] |= mask[i & 7];
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
src.set(tmp, index);
|
|
105
|
+
tmp.set(clean);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
transposition.table = new Uint8Array([
|
|
109
|
+
16, 7, 20, 21,
|
|
110
|
+
29, 12, 28, 17,
|
|
111
|
+
1, 15, 23, 26,
|
|
112
|
+
5, 18, 31, 10,
|
|
113
|
+
2, 8, 24, 14,
|
|
114
|
+
32, 27, 3, 9,
|
|
115
|
+
19, 13, 30, 6,
|
|
116
|
+
22, 11, 4, 25
|
|
117
|
+
]);
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Expansion (E).
|
|
122
|
+
* Expands upper four 8-bits (32b) into eight 6-bits (48b).
|
|
123
|
+
*
|
|
124
|
+
* @param {Uint8Array} src
|
|
125
|
+
* @param {number} index
|
|
126
|
+
*/
|
|
127
|
+
function expansion( src, index )
|
|
128
|
+
{
|
|
129
|
+
tmp[0] = ((src[index+7]<<5) | (src[index+4]>>3)) & 0x3f; // ..0 vutsr
|
|
130
|
+
tmp[1] = ((src[index+4]<<1) | (src[index+5]>>7)) & 0x3f; // ..srqpo n
|
|
131
|
+
tmp[2] = ((src[index+4]<<5) | (src[index+5]>>3)) & 0x3f; // ..o nmlkj
|
|
132
|
+
tmp[3] = ((src[index+5]<<1) | (src[index+6]>>7)) & 0x3f; // ..kjihg f
|
|
133
|
+
tmp[4] = ((src[index+5]<<5) | (src[index+6]>>3)) & 0x3f; // ..g fedcb
|
|
134
|
+
tmp[5] = ((src[index+6]<<1) | (src[index+7]>>7)) & 0x3f; // ..cba98 7
|
|
135
|
+
tmp[6] = ((src[index+6]<<5) | (src[index+7]>>3)) & 0x3f; // ..8 76543
|
|
136
|
+
tmp[7] = ((src[index+7]<<1) | (src[index+4]>>7)) & 0x3f; // ..43210 v
|
|
137
|
+
|
|
138
|
+
src.set(tmp, index);
|
|
139
|
+
tmp.set(clean);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Substitution boxes (S-boxes).
|
|
145
|
+
* NOTE: This implementation was optimized to process two nibbles in one step (twice as fast).
|
|
146
|
+
*
|
|
147
|
+
* @param {Uint8Array} src
|
|
148
|
+
* @param {number} index
|
|
149
|
+
*/
|
|
150
|
+
function substitutionBox( src, index )
|
|
151
|
+
{
|
|
152
|
+
var i;
|
|
153
|
+
|
|
154
|
+
for (i = 0; i < 4; ++i) {
|
|
155
|
+
tmp[i] = (substitutionBox.table[i][src[i*2+0+index]] & 0xf0)
|
|
156
|
+
| (substitutionBox.table[i][src[i*2+1+index]] & 0x0f);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
src.set(tmp, index);
|
|
160
|
+
tmp.set(clean);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
substitutionBox.table = [
|
|
164
|
+
new Uint8Array([
|
|
165
|
+
0xef, 0x03, 0x41, 0xfd, 0xd8, 0x74, 0x1e, 0x47, 0x26, 0xef, 0xfb, 0x22, 0xb3, 0xd8, 0x84, 0x1e,
|
|
166
|
+
0x39, 0xac, 0xa7, 0x60, 0x62, 0xc1, 0xcd, 0xba, 0x5c, 0x96, 0x90, 0x59, 0x05, 0x3b, 0x7a, 0x85,
|
|
167
|
+
0x40, 0xfd, 0x1e, 0xc8, 0xe7, 0x8a, 0x8b, 0x21, 0xda, 0x43, 0x64, 0x9f, 0x2d, 0x14, 0xb1, 0x72,
|
|
168
|
+
0xf5, 0x5b, 0xc8, 0xb6, 0x9c, 0x37, 0x76, 0xec, 0x39, 0xa0, 0xa3, 0x05, 0x52, 0x6e, 0x0f, 0xd9 ]),
|
|
169
|
+
new Uint8Array([
|
|
170
|
+
0xa7, 0xdd, 0x0d, 0x78, 0x9e, 0x0b, 0xe3, 0x95, 0x60, 0x36, 0x36, 0x4f, 0xf9, 0x60, 0x5a, 0xa3,
|
|
171
|
+
0x11, 0x24, 0xd2, 0x87, 0xc8, 0x52, 0x75, 0xec, 0xbb, 0xc1, 0x4c, 0xba, 0x24, 0xfe, 0x8f, 0x19,
|
|
172
|
+
0xda, 0x13, 0x66, 0xaf, 0x49, 0xd0, 0x90, 0x06, 0x8c, 0x6a, 0xfb, 0x91, 0x37, 0x8d, 0x0d, 0x78,
|
|
173
|
+
0xbf, 0x49, 0x11, 0xf4, 0x23, 0xe5, 0xce, 0x3b, 0x55, 0xbc, 0xa2, 0x57, 0xe8, 0x22, 0x74, 0xce ]),
|
|
174
|
+
new Uint8Array([
|
|
175
|
+
0x2c, 0xea, 0xc1, 0xbf, 0x4a, 0x24, 0x1f, 0xc2, 0x79, 0x47, 0xa2, 0x7c, 0xb6, 0xd9, 0x68, 0x15,
|
|
176
|
+
0x80, 0x56, 0x5d, 0x01, 0x33, 0xfd, 0xf4, 0xae, 0xde, 0x30, 0x07, 0x9b, 0xe5, 0x83, 0x9b, 0x68,
|
|
177
|
+
0x49, 0xb4, 0x2e, 0x83, 0x1f, 0xc2, 0xb5, 0x7c, 0xa2, 0x19, 0xd8, 0xe5, 0x7c, 0x2f, 0x83, 0xda,
|
|
178
|
+
0xf7, 0x6b, 0x90, 0xfe, 0xc4, 0x01, 0x5a, 0x97, 0x61, 0xa6, 0x3d, 0x40, 0x0b, 0x58, 0xe6, 0x3d ]),
|
|
179
|
+
new Uint8Array([
|
|
180
|
+
0x4d, 0xd1, 0xb2, 0x0f, 0x28, 0xbd, 0xe4, 0x78, 0xf6, 0x4a, 0x0f, 0x93, 0x8b, 0x17, 0xd1, 0xa4,
|
|
181
|
+
0x3a, 0xec, 0xc9, 0x35, 0x93, 0x56, 0x7e, 0xcb, 0x55, 0x20, 0xa0, 0xfe, 0x6c, 0x89, 0x17, 0x62,
|
|
182
|
+
0x17, 0x62, 0x4b, 0xb1, 0xb4, 0xde, 0xd1, 0x87, 0xc9, 0x14, 0x3c, 0x4a, 0x7e, 0xa8, 0xe2, 0x7d,
|
|
183
|
+
0xa0, 0x9f, 0xf6, 0x5c, 0x6a, 0x09, 0x8d, 0xf0, 0x0f, 0xe3, 0x53, 0x25, 0x95, 0x36, 0x28, 0xcb ])
|
|
184
|
+
];
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* DES round function.
|
|
189
|
+
* XORs src[0..3] with TP(SBOX(E(src[4..7]))).
|
|
190
|
+
*
|
|
191
|
+
* @param {Uint8Array} src
|
|
192
|
+
* @param {number} index
|
|
193
|
+
*/
|
|
194
|
+
function roundFunction( src, index )
|
|
195
|
+
{
|
|
196
|
+
for (var i = 0; i < 8; i++) {
|
|
197
|
+
tmp2[i] = src[index+i];
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
expansion( tmp2, 0 );
|
|
201
|
+
substitutionBox( tmp2, 0 );
|
|
202
|
+
transposition( tmp2, 0 );
|
|
203
|
+
|
|
204
|
+
src[index+0] ^= tmp2[4];
|
|
205
|
+
src[index+1] ^= tmp2[5];
|
|
206
|
+
src[index+2] ^= tmp2[6];
|
|
207
|
+
src[index+3] ^= tmp2[7];
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* DEcrypt a block
|
|
213
|
+
*
|
|
214
|
+
* @param {Uint8Array} src
|
|
215
|
+
* @param {number} index
|
|
216
|
+
*/
|
|
217
|
+
function decryptBlock( src, index )
|
|
218
|
+
{
|
|
219
|
+
initialPermutation( src, index );
|
|
220
|
+
roundFunction( src, index );
|
|
221
|
+
finalPermutation( src, index );
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Decode the whole file
|
|
227
|
+
*
|
|
228
|
+
* @param {Uint8Array} buf
|
|
229
|
+
* @param {number} len
|
|
230
|
+
* @param {number} entry_len
|
|
231
|
+
*/
|
|
232
|
+
function decodeFull( buf, len, entry_len)
|
|
233
|
+
{
|
|
234
|
+
var nblocks = len >> 3;
|
|
235
|
+
var i, j;
|
|
236
|
+
var digits, cycle;
|
|
237
|
+
|
|
238
|
+
// compute number of digits of the entry length
|
|
239
|
+
digits = entry_len.toString().length;
|
|
240
|
+
|
|
241
|
+
// choose size of gap between two encrypted blocks
|
|
242
|
+
// digits: 0 1 2 3 4 5 6 7 8 9 ...
|
|
243
|
+
// cycle: 1 1 1 4 5 14 15 22 23 24 ...
|
|
244
|
+
cycle = ( digits < 3 ) ? 1
|
|
245
|
+
: ( digits < 5 ) ? digits + 1
|
|
246
|
+
: ( digits < 7 ) ? digits + 9
|
|
247
|
+
: digits + 15;
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
// first 20 blocks are all des-encrypted
|
|
251
|
+
for (i = 0; i < 20 && i < nblocks; ++i) {
|
|
252
|
+
decryptBlock( buf, i * 8);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
for (i = 20, j = 0; i < nblocks; ++i) {
|
|
257
|
+
|
|
258
|
+
// decrypt block
|
|
259
|
+
if (i % cycle === 0) {
|
|
260
|
+
decryptBlock( buf, i * 8);
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// de-shuffle block
|
|
265
|
+
if (j === 7) {
|
|
266
|
+
shuffleDec( buf, i * 8);
|
|
267
|
+
j = 0;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
j++;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Decode only the header
|
|
277
|
+
*
|
|
278
|
+
* @param {Uint8Array} buf
|
|
279
|
+
* @param {number} len
|
|
280
|
+
*/
|
|
281
|
+
function decodeHeader( buf, len )
|
|
282
|
+
{
|
|
283
|
+
var nblocks = len >> 3;
|
|
284
|
+
var i;
|
|
285
|
+
|
|
286
|
+
// first 20 blocks are all des-encrypted
|
|
287
|
+
for (i = 0; i < 20 && i < nblocks; ++i) {
|
|
288
|
+
decryptBlock( buf, i*8 );
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// the rest is plaintext, done.
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Shuffle decode
|
|
297
|
+
*
|
|
298
|
+
* @param {Uint8Array} src
|
|
299
|
+
* @param {number} index
|
|
300
|
+
*/
|
|
301
|
+
function shuffleDec( src, index )
|
|
302
|
+
{
|
|
303
|
+
tmp[0] = src[index+3];
|
|
304
|
+
tmp[1] = src[index+4];
|
|
305
|
+
tmp[2] = src[index+6];
|
|
306
|
+
tmp[3] = src[index+0];
|
|
307
|
+
tmp[4] = src[index+1];
|
|
308
|
+
tmp[5] = src[index+2];
|
|
309
|
+
tmp[6] = src[index+5];
|
|
310
|
+
tmp[7] = shuffleDec.table[ src[index+7] ];
|
|
311
|
+
src.set(tmp, index);
|
|
312
|
+
tmp.set(clean);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* GRF substitution table
|
|
318
|
+
*
|
|
319
|
+
* @var {Uint8Array[]}
|
|
320
|
+
*/
|
|
321
|
+
shuffleDec.table = (function init_substitution()
|
|
322
|
+
{
|
|
323
|
+
var i, count;
|
|
324
|
+
var out = new Uint8Array(256);
|
|
325
|
+
var list = [ 0x00, 0x2b, 0x6c, 0x80, 0x01, 0x68, 0x48, 0x77, 0x60, 0xff, 0xb9, 0xc0, 0xfe, 0xeb ];
|
|
326
|
+
|
|
327
|
+
for (i = 0; i < 256; ++i) {
|
|
328
|
+
out[i] = i;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
for (i = 0, count = list.length; i < count; i += 2) {
|
|
332
|
+
out[ list[i+0] ] = list[i+1];
|
|
333
|
+
out[ list[i+1] ] = list[i+0];
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
return out;
|
|
337
|
+
})();
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Exports
|
|
342
|
+
*/
|
|
343
|
+
module.exports = {
|
|
344
|
+
decodeFull: decodeFull,
|
|
345
|
+
decodeHeader: decodeHeader
|
|
346
|
+
};
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utils/BinaryReader.js
|
|
3
|
+
*
|
|
4
|
+
* BinaryReader Helper
|
|
5
|
+
*
|
|
6
|
+
* Helper to load/parse Binary data (sockets, files)
|
|
7
|
+
*
|
|
8
|
+
* This file is part of ROBrowser, Ragnarok Online in the Web Browser (http://www.robrowser.com/).
|
|
9
|
+
*
|
|
10
|
+
* @author Vincent Thibault
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
'use strict';
|
|
14
|
+
|
|
15
|
+
var _global = this;
|
|
16
|
+
|
|
17
|
+
var TextEnconding = require('../Vendors/text-encoding');
|
|
18
|
+
var Struct = require('./Struct');
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Binary Constant for BinaryReader::seek();
|
|
22
|
+
* Export to global context
|
|
23
|
+
*/
|
|
24
|
+
_global.SEEK_CUR = 1;
|
|
25
|
+
_global.SEEK_SET = 2;
|
|
26
|
+
_global.SEEK_END = 3;
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* BinaryReader
|
|
31
|
+
*
|
|
32
|
+
* @param mixed buffer
|
|
33
|
+
* @param {number} start optional
|
|
34
|
+
* @param {number} end optional
|
|
35
|
+
*/
|
|
36
|
+
function BinaryReader(mixed, start, end) {
|
|
37
|
+
var buffer;
|
|
38
|
+
|
|
39
|
+
if (typeof mixed === 'string') {
|
|
40
|
+
var uint8;
|
|
41
|
+
var i, length;
|
|
42
|
+
|
|
43
|
+
length = mixed.length;
|
|
44
|
+
buffer = new ArrayBuffer(length);
|
|
45
|
+
uint8 = new Uint8Array(buffer);
|
|
46
|
+
|
|
47
|
+
for (i = 0; i < length; ++i) {
|
|
48
|
+
uint8[i] = mixed.charCodeAt(i) & 0xff;
|
|
49
|
+
}
|
|
50
|
+
} else if (mixed instanceof ArrayBuffer) {
|
|
51
|
+
buffer = mixed;
|
|
52
|
+
} else if (mixed instanceof Uint8Array) {
|
|
53
|
+
buffer = mixed.buffer;
|
|
54
|
+
} else {
|
|
55
|
+
throw new Error('BinaryReader() - Undefined buffer type');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
this.buffer = buffer;
|
|
59
|
+
this.view = new DataView(buffer, start || 0, end || buffer.byteLength);
|
|
60
|
+
this.offset = 0;
|
|
61
|
+
this.length = (end || buffer.byteLength) - (start || 0);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Read Int8 from buffer
|
|
67
|
+
* @return int8
|
|
68
|
+
*/
|
|
69
|
+
BinaryReader.prototype.getInt8 =
|
|
70
|
+
BinaryReader.prototype.readChar =
|
|
71
|
+
BinaryReader.prototype.readByte = function getInt8() {
|
|
72
|
+
return this.view.getInt8(this.offset++);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Read Uint8 from buffer
|
|
78
|
+
* @return uint8
|
|
79
|
+
*/
|
|
80
|
+
BinaryReader.prototype.getUint8 =
|
|
81
|
+
BinaryReader.prototype.readUChar =
|
|
82
|
+
BinaryReader.prototype.readUByte = function getUint8() {
|
|
83
|
+
return this.view.getUint8(this.offset++);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Read Int16 from buffer
|
|
89
|
+
* @return int16
|
|
90
|
+
*/
|
|
91
|
+
BinaryReader.prototype.getInt16 =
|
|
92
|
+
BinaryReader.prototype.readShort = function getInt16() {
|
|
93
|
+
var data = this.view.getInt16(this.offset, true);
|
|
94
|
+
this.offset += 2;
|
|
95
|
+
|
|
96
|
+
return data;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Read Uint16 from buffer
|
|
102
|
+
* @return Uint16
|
|
103
|
+
*/
|
|
104
|
+
BinaryReader.prototype.getUint16 =
|
|
105
|
+
BinaryReader.prototype.readUShort = function getUint16() {
|
|
106
|
+
var data = this.view.getUint16(this.offset, true);
|
|
107
|
+
this.offset += 2;
|
|
108
|
+
|
|
109
|
+
return data;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Read Int32 from buffer
|
|
115
|
+
* @return int32
|
|
116
|
+
*/
|
|
117
|
+
BinaryReader.prototype.getInt32 =
|
|
118
|
+
BinaryReader.prototype.readInt =
|
|
119
|
+
BinaryReader.prototype.readLong = function getInt32() {
|
|
120
|
+
var data = this.view.getInt32(this.offset, true);
|
|
121
|
+
this.offset += 4;
|
|
122
|
+
|
|
123
|
+
return data;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Read Uint32 from buffer
|
|
129
|
+
* @return Uint32
|
|
130
|
+
*/
|
|
131
|
+
BinaryReader.prototype.getUint32 =
|
|
132
|
+
BinaryReader.prototype.readUInt =
|
|
133
|
+
BinaryReader.prototype.readULong = function getUint32() {
|
|
134
|
+
var data = this.view.getUint32(this.offset, true);
|
|
135
|
+
this.offset += 4;
|
|
136
|
+
|
|
137
|
+
return data;
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Read float32 from buffer
|
|
143
|
+
* @return float32
|
|
144
|
+
*/
|
|
145
|
+
BinaryReader.prototype.getFloat32 =
|
|
146
|
+
BinaryReader.prototype.readFloat = function getFloat32() {
|
|
147
|
+
var data = this.view.getFloat32(this.offset, true);
|
|
148
|
+
this.offset += 4;
|
|
149
|
+
|
|
150
|
+
return data;
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Read Float64 from buffer
|
|
156
|
+
* @return Float64
|
|
157
|
+
*/
|
|
158
|
+
BinaryReader.prototype.getFloat64 =
|
|
159
|
+
BinaryReader.prototype.readDouble = function getFloat64() {
|
|
160
|
+
var data = this.view.getFloat64(this.offset, true);
|
|
161
|
+
this.offset += 8;
|
|
162
|
+
|
|
163
|
+
return data;
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Read Buffer position
|
|
169
|
+
* @return {number}
|
|
170
|
+
*/
|
|
171
|
+
BinaryReader.prototype.tell = function tell() {
|
|
172
|
+
return this.offset;
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Read string from buffer
|
|
178
|
+
*
|
|
179
|
+
* @param integer string length
|
|
180
|
+
* @return string
|
|
181
|
+
*/
|
|
182
|
+
BinaryReader.prototype.getString =
|
|
183
|
+
BinaryReader.prototype.readString = function getString(len) {
|
|
184
|
+
var offset = this.offset + 0;
|
|
185
|
+
var i, uint8, data = new Uint8Array(len);
|
|
186
|
+
|
|
187
|
+
for (i = 0; i < len; ++i) {
|
|
188
|
+
if (!(uint8 = this.getUint8())) {
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
data[i] = uint8;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
this.offset = offset + len;
|
|
195
|
+
|
|
196
|
+
return TextEncoding.decode(data.subarray(0, i));
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Read binary string from buffer
|
|
202
|
+
*
|
|
203
|
+
* @param integer string length
|
|
204
|
+
* @return string
|
|
205
|
+
*/
|
|
206
|
+
BinaryReader.prototype.getBinaryString =
|
|
207
|
+
BinaryReader.prototype.readBinaryString = function getBinaryString(len) {
|
|
208
|
+
var offset = this.offset + 0,
|
|
209
|
+
i;
|
|
210
|
+
var uint8, out = '';
|
|
211
|
+
|
|
212
|
+
for (i = 0; i < len; ++i) {
|
|
213
|
+
if (!(uint8 = this.getUint8())) {
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
out += String.fromCharCode(uint8);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
this.offset = offset + len;
|
|
220
|
+
return out;
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Structure reader in JS
|
|
226
|
+
*
|
|
227
|
+
* @param Struct
|
|
228
|
+
*/
|
|
229
|
+
BinaryReader.prototype.getStruct =
|
|
230
|
+
BinaryReader.prototype.readStruct = function getStruct(struct) {
|
|
231
|
+
if (!(struct instanceof Struct)) {
|
|
232
|
+
throw new Error('BinaryReader::getStruct() - Invalid data as argument');
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
var list = struct._list;
|
|
236
|
+
var name;
|
|
237
|
+
var out = {}, current, keys;
|
|
238
|
+
var i, j, count;
|
|
239
|
+
|
|
240
|
+
keys = Object.keys(list);
|
|
241
|
+
count = keys.length;
|
|
242
|
+
|
|
243
|
+
for (j = 0; j < count; ++j) {
|
|
244
|
+
name = keys[j];
|
|
245
|
+
current = list[name];
|
|
246
|
+
|
|
247
|
+
if (current.count > 1) {
|
|
248
|
+
out[name] = new Array(current.count);
|
|
249
|
+
for (i = 0; i < current.count; ++i) {
|
|
250
|
+
out[name][i] = this[current.func]();
|
|
251
|
+
}
|
|
252
|
+
} else {
|
|
253
|
+
out[name] = this[current.func]();
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
return out;
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Move cursor to another offset
|
|
263
|
+
*
|
|
264
|
+
* @param {number} index
|
|
265
|
+
* @param {number} type - const SEEK_*
|
|
266
|
+
*/
|
|
267
|
+
BinaryReader.prototype.seek = function seek(index, type) {
|
|
268
|
+
type = type || SEEK_SET;
|
|
269
|
+
this.offset =
|
|
270
|
+
type === SEEK_CUR ? this.offset + index :
|
|
271
|
+
type === SEEK_END ? this.length + index :
|
|
272
|
+
index;
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
// Old compatibility for pos and pos2
|
|
277
|
+
var bf_byteBuff = new ArrayBuffer(4);
|
|
278
|
+
var bf_wba = new Int8Array(bf_byteBuff);
|
|
279
|
+
var bf_wia = new Int32Array(bf_byteBuff);
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Read Position from Buffer
|
|
284
|
+
*
|
|
285
|
+
* @return array (pos_x, pos_y, direction)
|
|
286
|
+
*/
|
|
287
|
+
BinaryReader.prototype.getPos =
|
|
288
|
+
BinaryReader.prototype.readPos = function getPos() {
|
|
289
|
+
var p, dir, x, y;
|
|
290
|
+
|
|
291
|
+
bf_wba[2] = this.getUint8();
|
|
292
|
+
bf_wba[1] = this.getUint8();
|
|
293
|
+
bf_wba[0] = this.getUint8();
|
|
294
|
+
bf_wba[3] = 0;
|
|
295
|
+
|
|
296
|
+
p = 0 + bf_wia[0];
|
|
297
|
+
dir = p & 0x0f;
|
|
298
|
+
p >>= 4;
|
|
299
|
+
|
|
300
|
+
y = p & 0x03FF;
|
|
301
|
+
p >>= 10;
|
|
302
|
+
|
|
303
|
+
x = p & 0x03FF;
|
|
304
|
+
|
|
305
|
+
return [x, y, dir];
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Read Position (walk) from buffer
|
|
311
|
+
*
|
|
312
|
+
* @return array ( from_x, from_y, to_x, to_y )
|
|
313
|
+
*/
|
|
314
|
+
BinaryReader.prototype.getPos2 =
|
|
315
|
+
BinaryReader.prototype.readPos2 = function getPos2() {
|
|
316
|
+
var a, b, c, d, e;
|
|
317
|
+
|
|
318
|
+
a = this.getInt8();
|
|
319
|
+
b = this.getInt8();
|
|
320
|
+
c = this.getInt8();
|
|
321
|
+
d = this.getInt8();
|
|
322
|
+
e = this.getInt8();
|
|
323
|
+
|
|
324
|
+
return [
|
|
325
|
+
((a & 0xFF) << 2) | ((b & 0xC0) >> 6), // x1
|
|
326
|
+
((b & 0x3F) << 4) | ((c & 0xF0) >> 4), // y1
|
|
327
|
+
((d & 0xFC) >> 2) | ((c & 0x0F) << 6), // x2
|
|
328
|
+
((d & 0x03) << 8) | ((e & 0xFF)) // y2
|
|
329
|
+
];
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
// Export
|
|
334
|
+
module.exports = BinaryReader;
|