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.
@@ -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;