@bis-toolkit/paa 1.0.0

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/dist/index.js ADDED
@@ -0,0 +1,1061 @@
1
+ // src/PaaType.ts
2
+ var PaaType = /* @__PURE__ */ ((PaaType2) => {
3
+ PaaType2[PaaType2["DXT1"] = 65281] = "DXT1";
4
+ PaaType2[PaaType2["DXT2"] = 65282] = "DXT2";
5
+ PaaType2[PaaType2["DXT3"] = 65283] = "DXT3";
6
+ PaaType2[PaaType2["DXT4"] = 65284] = "DXT4";
7
+ PaaType2[PaaType2["DXT5"] = 65285] = "DXT5";
8
+ PaaType2[PaaType2["RGBA_5551"] = 5461] = "RGBA_5551";
9
+ PaaType2[PaaType2["RGBA_4444"] = 17476] = "RGBA_4444";
10
+ PaaType2[PaaType2["RGBA_8888"] = 34952] = "RGBA_8888";
11
+ PaaType2[PaaType2["AI88"] = 32896] = "AI88";
12
+ return PaaType2;
13
+ })(PaaType || {});
14
+
15
+ // src/PaaColor.ts
16
+ var PaaColor = class _PaaColor {
17
+ constructor(valueOrRed, green, blue, alpha = 255) {
18
+ if (green === void 0) {
19
+ this._value = valueOrRed >>> 0;
20
+ } else {
21
+ this._value = _PaaColor.colorToUint(valueOrRed, green, blue ?? 0, alpha ?? 0);
22
+ }
23
+ }
24
+ get alpha() {
25
+ return this._value >>> 24 & 255;
26
+ }
27
+ get red() {
28
+ return this._value >>> 16 & 255;
29
+ }
30
+ get green() {
31
+ return this._value >>> 8 & 255;
32
+ }
33
+ get blue() {
34
+ return this._value & 255;
35
+ }
36
+ get color() {
37
+ return this._value;
38
+ }
39
+ static colorToUint(r, g, b, a) {
40
+ return (a << 24 | r << 16 | g << 8 | b) >>> 0;
41
+ }
42
+ static fromFloat(red, green, blue, alpha) {
43
+ return new _PaaColor(
44
+ Math.floor(red * 255),
45
+ Math.floor(green * 255),
46
+ Math.floor(blue * 255),
47
+ Math.floor(alpha * 255)
48
+ );
49
+ }
50
+ };
51
+
52
+ // src/Palette.ts
53
+ var Palette = class {
54
+ constructor() {
55
+ this.colors = [];
56
+ }
57
+ read(br) {
58
+ const nPaletteTriplets = br.readUInt16();
59
+ this.colors = [];
60
+ for (let i = 0; i < nPaletteTriplets; i++) {
61
+ const b = br.readByte();
62
+ const g = br.readByte();
63
+ const r = br.readByte();
64
+ this.colors.push(new PaaColor(r, g, b));
65
+ }
66
+ }
67
+ };
68
+
69
+ // ../utils/dist/index.js
70
+ var BinaryReader = class {
71
+ constructor(buffer) {
72
+ this.position = 0;
73
+ this.buffer = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
74
+ this.view = new DataView(this.buffer.buffer, this.buffer.byteOffset, this.buffer.byteLength);
75
+ }
76
+ get length() {
77
+ return this.buffer.length;
78
+ }
79
+ get pos() {
80
+ return this.position;
81
+ }
82
+ seek(offset, origin = "begin") {
83
+ switch (origin) {
84
+ case "begin":
85
+ this.position = offset;
86
+ break;
87
+ case "current":
88
+ this.position += offset;
89
+ break;
90
+ case "end":
91
+ this.position = this.buffer.length + offset;
92
+ break;
93
+ }
94
+ }
95
+ readByte() {
96
+ const value = this.view.getUint8(this.position);
97
+ this.position += 1;
98
+ return value;
99
+ }
100
+ readUInt16() {
101
+ const value = this.view.getUint16(this.position, true);
102
+ this.position += 2;
103
+ return value;
104
+ }
105
+ readUInt32() {
106
+ const value = this.view.getUint32(this.position, true);
107
+ this.position += 4;
108
+ return value;
109
+ }
110
+ readInt32() {
111
+ const value = this.view.getInt32(this.position, true);
112
+ this.position += 4;
113
+ return value;
114
+ }
115
+ readInt24() {
116
+ const b1 = this.view.getUint8(this.position);
117
+ const b2 = this.view.getUint8(this.position + 1);
118
+ const b3 = this.view.getUint8(this.position + 2);
119
+ this.position += 3;
120
+ return b1 | b2 << 8 | b3 << 16;
121
+ }
122
+ readBytes(count) {
123
+ const bytes = this.buffer.subarray(this.position, this.position + count);
124
+ this.position += count;
125
+ return bytes;
126
+ }
127
+ readRawString(length) {
128
+ const bytes = this.buffer.subarray(this.position, this.position + length);
129
+ this.position += length;
130
+ return String.fromCharCode(...bytes);
131
+ }
132
+ readFloat() {
133
+ const value = this.view.getFloat32(this.position, true);
134
+ this.position += 4;
135
+ return value;
136
+ }
137
+ readBoolean() {
138
+ return this.readByte() !== 0;
139
+ }
140
+ /**
141
+ * Read a null-terminated C-style string
142
+ */
143
+ readCString() {
144
+ const start = this.position;
145
+ let end = start;
146
+ while (end < this.buffer.length && this.buffer[end] !== 0) {
147
+ end++;
148
+ }
149
+ const bytes = this.buffer.subarray(start, end);
150
+ this.position = end + 1;
151
+ const decoder = new TextDecoder("utf-8");
152
+ return decoder.decode(bytes);
153
+ }
154
+ /**
155
+ * Alias for readRawString for compatibility
156
+ */
157
+ readString(length) {
158
+ return this.readRawString(length);
159
+ }
160
+ };
161
+ var LZO = class _LZO {
162
+ constructor() {
163
+ this._blockSize = 128 * 1024;
164
+ this._minNewSize = this.blockSize;
165
+ this._out = new Uint8Array(256 * 1024);
166
+ this._cbl = 0;
167
+ this._t = 0;
168
+ this._inputPointer = 0;
169
+ this._outputPointer = 0;
170
+ this._matchPosition = 0;
171
+ this._skipToFirstLiteralFunc = false;
172
+ }
173
+ get blockSize() {
174
+ return this._blockSize;
175
+ }
176
+ set blockSize(value) {
177
+ if (value <= 0) throw new Error("Block size must be a positive integer");
178
+ this._blockSize = value;
179
+ }
180
+ _extendBuffer() {
181
+ const newBuffer = new Uint8Array(
182
+ this._minNewSize + (this.blockSize - this._minNewSize % this.blockSize)
183
+ );
184
+ newBuffer.set(this._out);
185
+ this._out = newBuffer;
186
+ this._cbl = this._out.length;
187
+ }
188
+ _matchNext() {
189
+ this._minNewSize = this._outputPointer + 3;
190
+ if (this._minNewSize > this._cbl) this._extendBuffer();
191
+ this._out[this._outputPointer++] = this._buffer[this._inputPointer++];
192
+ if (this._t > 1) {
193
+ this._out[this._outputPointer++] = this._buffer[this._inputPointer++];
194
+ if (this._t > 2) {
195
+ this._out[this._outputPointer++] = this._buffer[this._inputPointer++];
196
+ }
197
+ }
198
+ this._t = this._buffer[this._inputPointer++];
199
+ }
200
+ _matchDone() {
201
+ this._t = this._buffer[this._inputPointer - 2] & 3;
202
+ return this._t;
203
+ }
204
+ _copyMatch() {
205
+ this._t += 2;
206
+ this._minNewSize = this._outputPointer + this._t;
207
+ if (this._minNewSize > this._cbl) {
208
+ this._extendBuffer();
209
+ }
210
+ do {
211
+ this._out[this._outputPointer++] = this._out[this._matchPosition++];
212
+ } while (--this._t > 0);
213
+ }
214
+ _copyFromBuffer() {
215
+ this._minNewSize = this._outputPointer + this._t;
216
+ if (this._minNewSize > this._cbl) {
217
+ this._extendBuffer();
218
+ }
219
+ do {
220
+ this._out[this._outputPointer++] = this._buffer[this._inputPointer++];
221
+ } while (--this._t > 0);
222
+ }
223
+ _match() {
224
+ while (true) {
225
+ if (this._t >= 64) {
226
+ this._matchPosition = this._outputPointer - 1 - (this._t >> 2 & 7) - (this._buffer[this._inputPointer++] << 3);
227
+ this._t = (this._t >> 5) - 1;
228
+ this._copyMatch();
229
+ } else if (this._t >= 32) {
230
+ this._t &= 31;
231
+ if (this._t === 0) {
232
+ while (this._buffer[this._inputPointer] === 0) {
233
+ this._t += 255;
234
+ this._inputPointer++;
235
+ }
236
+ this._t += 31 + this._buffer[this._inputPointer++];
237
+ }
238
+ this._matchPosition = this._outputPointer - 1 - (this._buffer[this._inputPointer] >> 2) - (this._buffer[this._inputPointer + 1] << 6);
239
+ this._inputPointer += 2;
240
+ this._copyMatch();
241
+ } else if (this._t >= 16) {
242
+ this._matchPosition = this._outputPointer - ((this._t & 8) << 11);
243
+ this._t &= 7;
244
+ if (this._t === 0) {
245
+ while (this._buffer[this._inputPointer] === 0) {
246
+ this._t += 255;
247
+ this._inputPointer++;
248
+ }
249
+ this._t += 7 + this._buffer[this._inputPointer++];
250
+ }
251
+ this._matchPosition -= (this._buffer[this._inputPointer] >> 2) + (this._buffer[this._inputPointer + 1] << 6);
252
+ this._inputPointer += 2;
253
+ if (this._matchPosition === this._outputPointer) {
254
+ return this._out.subarray(0, this._outputPointer);
255
+ } else {
256
+ this._matchPosition -= 16384;
257
+ this._copyMatch();
258
+ }
259
+ } else {
260
+ this._matchPosition = this._outputPointer - 1 - (this._t >> 2) - (this._buffer[this._inputPointer++] << 2);
261
+ this._minNewSize = this._outputPointer + 2;
262
+ if (this._minNewSize > this._cbl) {
263
+ this._extendBuffer();
264
+ }
265
+ this._out[this._outputPointer++] = this._out[this._matchPosition++];
266
+ this._out[this._outputPointer++] = this._out[this._matchPosition];
267
+ }
268
+ if (this._matchDone() === 0) {
269
+ return true;
270
+ }
271
+ this._matchNext();
272
+ }
273
+ }
274
+ _decompressBuffer(buffer) {
275
+ this._buffer = buffer;
276
+ this._cbl = this._out.length;
277
+ this._t = 0;
278
+ this._inputPointer = 0;
279
+ this._outputPointer = 0;
280
+ this._matchPosition = 0;
281
+ this._skipToFirstLiteralFunc = false;
282
+ if (this._buffer[this._inputPointer] > 17) {
283
+ this._t = this._buffer[this._inputPointer++] - 17;
284
+ if (this._t < 4) {
285
+ this._matchNext();
286
+ const matched = this._match();
287
+ if (matched !== true) return matched;
288
+ } else {
289
+ this._copyFromBuffer();
290
+ this._skipToFirstLiteralFunc = true;
291
+ }
292
+ }
293
+ while (true) {
294
+ if (!this._skipToFirstLiteralFunc) {
295
+ this._t = this._buffer[this._inputPointer++];
296
+ if (this._t >= 16) {
297
+ const matched2 = this._match();
298
+ if (matched2 !== true) return matched2;
299
+ continue;
300
+ } else if (this._t === 0) {
301
+ while (this._buffer[this._inputPointer] === 0) {
302
+ this._t += 255;
303
+ this._inputPointer++;
304
+ }
305
+ this._t += 15 + this._buffer[this._inputPointer++];
306
+ }
307
+ this._t += 3;
308
+ this._copyFromBuffer();
309
+ } else this._skipToFirstLiteralFunc = false;
310
+ this._t = this._buffer[this._inputPointer++];
311
+ if (this._t < 16) {
312
+ this._matchPosition = this._outputPointer - (1 + 2048);
313
+ this._matchPosition -= this._t >> 2;
314
+ this._matchPosition -= this._buffer[this._inputPointer++] << 2;
315
+ this._minNewSize = this._outputPointer + 3;
316
+ if (this._minNewSize > this._cbl) {
317
+ this._extendBuffer();
318
+ }
319
+ this._out[this._outputPointer++] = this._out[this._matchPosition++];
320
+ this._out[this._outputPointer++] = this._out[this._matchPosition++];
321
+ this._out[this._outputPointer++] = this._out[this._matchPosition];
322
+ if (this._matchDone() === 0) continue;
323
+ else this._matchNext();
324
+ }
325
+ const matched = this._match();
326
+ if (matched !== true) return matched;
327
+ }
328
+ }
329
+ /**
330
+ * Decompresses the given buffer using the LZO1X-1 algorithm.
331
+ * @param buffer The buffer to decompress.
332
+ * @returns The decompressed buffer.
333
+ */
334
+ static decompress(buffer) {
335
+ return new _LZO()._decompressBuffer(buffer);
336
+ }
337
+ /**
338
+ * Decompresses the given buffer and returns both the decompressed data and bytes read.
339
+ * @param buffer The buffer to decompress.
340
+ * @returns Object containing decompressed data and number of bytes consumed from input.
341
+ */
342
+ static decompressWithSize(buffer) {
343
+ const lzo = new _LZO();
344
+ const decompressed = lzo._decompressBuffer(buffer);
345
+ return {
346
+ data: decompressed,
347
+ bytesRead: lzo._inputPointer
348
+ };
349
+ }
350
+ };
351
+ function lzoDecompress(src, expectedSize) {
352
+ const input = src instanceof Uint8Array ? src : new Uint8Array(src);
353
+ const decompressed = LZO.decompress(input);
354
+ if (decompressed.length !== expectedSize) {
355
+ throw new Error(`LZO decompression size mismatch: expected ${expectedSize}, got ${decompressed.length}`);
356
+ }
357
+ return decompressed;
358
+ }
359
+ var N = 4096;
360
+ var F = 18;
361
+ var THRESHOLD = 2;
362
+ function lzssDecompress(input, inputOffset, expectedSize, useSignedChecksum = false) {
363
+ const buffer = new Array(N + F - 1);
364
+ const dst = new Uint8Array(expectedSize);
365
+ if (expectedSize <= 0) {
366
+ return { data: new Uint8Array(0), bytesRead: 0 };
367
+ }
368
+ const startPos = inputOffset;
369
+ let inPos = inputOffset;
370
+ let iDst = 0;
371
+ let calculatedChecksum = 0;
372
+ let r = N - F;
373
+ for (let i = 0; i < r; i++) {
374
+ buffer[i] = 32;
375
+ }
376
+ let flags = 0;
377
+ while (expectedSize > 0) {
378
+ if (((flags >>>= 1) & 256) === 0) {
379
+ const c = input[inPos++];
380
+ flags = c | 65280;
381
+ }
382
+ if ((flags & 1) !== 0) {
383
+ const c = input[inPos++];
384
+ calculatedChecksum = calculatedChecksum + (useSignedChecksum ? c << 24 >> 24 : c) | 0;
385
+ dst[iDst++] = c;
386
+ expectedSize--;
387
+ buffer[r] = c;
388
+ r = r + 1 & N - 1;
389
+ } else {
390
+ const i = input[inPos++];
391
+ const j = input[inPos++];
392
+ const offset = i | (j & 240) << 4;
393
+ const length = (j & 15) + THRESHOLD;
394
+ if (length + 1 > expectedSize + length - THRESHOLD) {
395
+ throw new Error("LZSS overflow");
396
+ }
397
+ let ii = r - offset;
398
+ const jj = length + ii;
399
+ for (; ii <= jj; ii++) {
400
+ const c = buffer[ii & N - 1];
401
+ calculatedChecksum = calculatedChecksum + (useSignedChecksum ? c << 24 >> 24 : c) | 0;
402
+ dst[iDst++] = c;
403
+ expectedSize--;
404
+ buffer[r] = c;
405
+ r = r + 1 & N - 1;
406
+ }
407
+ }
408
+ }
409
+ const view = new DataView(input.buffer, input.byteOffset, input.byteLength);
410
+ const checksum = view.getInt32(inPos, true);
411
+ inPos += 4;
412
+ if (checksum !== calculatedChecksum) {
413
+ throw new Error(`Checksum mismatch: expected ${checksum}, got ${calculatedChecksum}`);
414
+ }
415
+ return {
416
+ data: dst,
417
+ bytesRead: inPos - startPos
418
+ };
419
+ }
420
+ function calculateChecksum(data, signed = false) {
421
+ let checksum = 0;
422
+ for (const byte of data) {
423
+ checksum = checksum + (signed ? byte << 24 >> 24 : byte) | 0;
424
+ }
425
+ return checksum;
426
+ }
427
+
428
+ // ../bcn/dist/index.js
429
+ var ColorRgb565 = class {
430
+ constructor(r, g, b) {
431
+ if (r !== void 0 && g !== void 0 && b !== void 0) {
432
+ const r5 = r >> 3 & 31;
433
+ const g6 = g >> 2 & 63;
434
+ const b5 = b >> 3 & 31;
435
+ this.data = r5 << 11 | g6 << 5 | b5;
436
+ } else {
437
+ this.data = 0;
438
+ }
439
+ }
440
+ toColorRgb24() {
441
+ const r5 = this.data >> 11 & 31;
442
+ const g6 = this.data >> 5 & 63;
443
+ const b5 = this.data & 31;
444
+ const r = r5 << 3 | r5 >> 2;
445
+ const g = g6 << 2 | g6 >> 4;
446
+ const b = b5 << 3 | b5 >> 2;
447
+ return { r, g, b };
448
+ }
449
+ };
450
+ function interpolateHalf(c0, c1) {
451
+ return {
452
+ r: (c0.r + c1.r) / 2 | 0,
453
+ g: (c0.g + c1.g) / 2 | 0,
454
+ b: (c0.b + c1.b) / 2 | 0
455
+ };
456
+ }
457
+ function interpolateThird(c0, c1, step) {
458
+ if (step === 1) {
459
+ return {
460
+ r: (2 * c0.r + c1.r) / 3 | 0,
461
+ g: (2 * c0.g + c1.g) / 3 | 0,
462
+ b: (2 * c0.b + c1.b) / 3 | 0
463
+ };
464
+ } else {
465
+ return {
466
+ r: (c0.r + 2 * c1.r) / 3 | 0,
467
+ g: (c0.g + 2 * c1.g) / 3 | 0,
468
+ b: (c0.b + 2 * c1.b) / 3 | 0
469
+ };
470
+ }
471
+ }
472
+ function interpolateByteFifth(e0, e1, step) {
473
+ if (step === 1) return (4 * e0 + e1) / 5 | 0;
474
+ if (step === 2) return (3 * e0 + 2 * e1) / 5 | 0;
475
+ if (step === 3) return (2 * e0 + 3 * e1) / 5 | 0;
476
+ return (e0 + 4 * e1) / 5 | 0;
477
+ }
478
+ function interpolateByteSeventh(e0, e1, step) {
479
+ if (step === 1) return (6 * e0 + e1) / 7 | 0;
480
+ if (step === 2) return (5 * e0 + 2 * e1) / 7 | 0;
481
+ if (step === 3) return (4 * e0 + 3 * e1) / 7 | 0;
482
+ if (step === 4) return (3 * e0 + 4 * e1) / 7 | 0;
483
+ if (step === 5) return (2 * e0 + 5 * e1) / 7 | 0;
484
+ return (e0 + 6 * e1) / 7 | 0;
485
+ }
486
+ function decodeBC1(data, width, height, useAlpha = false) {
487
+ const rgba = new Uint8Array(width * height * 4);
488
+ const blocksX = Math.ceil(width / 4);
489
+ const blocksY = Math.ceil(height / 4);
490
+ let offset = 0;
491
+ for (let by = 0; by < blocksY; by++) {
492
+ for (let bx = 0; bx < blocksX; bx++) {
493
+ const color0Data = data.getUint16(offset, true);
494
+ const color1Data = data.getUint16(offset + 2, true);
495
+ const indices = data.getUint32(offset + 4, true);
496
+ const color0 = new ColorRgb565();
497
+ color0.data = color0Data;
498
+ const color1 = new ColorRgb565();
499
+ color1.data = color1Data;
500
+ const c0 = color0.toColorRgb24();
501
+ const c1 = color1.toColorRgb24();
502
+ const hasAlphaOrBlack = color0Data <= color1Data;
503
+ const actualUseAlpha = useAlpha && hasAlphaOrBlack;
504
+ const colors = hasAlphaOrBlack ? [
505
+ c0,
506
+ c1,
507
+ interpolateHalf(c0, c1),
508
+ { r: 0, g: 0, b: 0 }
509
+ ] : [
510
+ c0,
511
+ c1,
512
+ interpolateThird(c0, c1, 1),
513
+ interpolateThird(c0, c1, 2)
514
+ ];
515
+ for (let y = 0; y < 4; y++) {
516
+ for (let x = 0; x < 4; x++) {
517
+ const px = bx * 4 + x;
518
+ const py = by * 4 + y;
519
+ if (px < width && py < height) {
520
+ const i = y * 4 + x;
521
+ const colorIndex = indices >> i * 2 & 3;
522
+ const color = colors[colorIndex];
523
+ const dstIdx = (py * width + px) * 4;
524
+ if (actualUseAlpha && colorIndex === 3) {
525
+ rgba[dstIdx] = 0;
526
+ rgba[dstIdx + 1] = 0;
527
+ rgba[dstIdx + 2] = 0;
528
+ rgba[dstIdx + 3] = 0;
529
+ } else {
530
+ rgba[dstIdx] = color.r;
531
+ rgba[dstIdx + 1] = color.g;
532
+ rgba[dstIdx + 2] = color.b;
533
+ rgba[dstIdx + 3] = 255;
534
+ }
535
+ }
536
+ }
537
+ }
538
+ offset += 8;
539
+ }
540
+ }
541
+ return rgba;
542
+ }
543
+ function decodeBC2(data, width, height) {
544
+ const rgba = new Uint8Array(width * height * 4);
545
+ const blocksX = Math.ceil(width / 4);
546
+ const blocksY = Math.ceil(height / 4);
547
+ let offset = 0;
548
+ for (let by = 0; by < blocksY; by++) {
549
+ for (let bx = 0; bx < blocksX; bx++) {
550
+ const alphaLow = data.getUint32(offset, true);
551
+ const alphaHigh = data.getUint32(offset + 4, true);
552
+ const color0Data = data.getUint16(offset + 8, true);
553
+ const color1Data = data.getUint16(offset + 10, true);
554
+ const indices = data.getUint32(offset + 12, true);
555
+ const color0 = new ColorRgb565();
556
+ color0.data = color0Data;
557
+ const color1 = new ColorRgb565();
558
+ color1.data = color1Data;
559
+ const c0 = color0.toColorRgb24();
560
+ const c1 = color1.toColorRgb24();
561
+ const colors = [
562
+ c0,
563
+ c1,
564
+ interpolateThird(c0, c1, 1),
565
+ interpolateThird(c0, c1, 2)
566
+ ];
567
+ for (let y = 0; y < 4; y++) {
568
+ for (let x = 0; x < 4; x++) {
569
+ const px = bx * 4 + x;
570
+ const py = by * 4 + y;
571
+ if (px < width && py < height) {
572
+ const i = y * 4 + x;
573
+ const colorIndex = indices >> i * 2 & 3;
574
+ const color = colors[colorIndex];
575
+ const alphaIndex = i * 4;
576
+ let alpha;
577
+ if (alphaIndex < 32) {
578
+ alpha = alphaLow >> alphaIndex & 15;
579
+ } else {
580
+ alpha = alphaHigh >> alphaIndex - 32 & 15;
581
+ }
582
+ alpha = alpha << 4 | alpha;
583
+ const dstIdx = (py * width + px) * 4;
584
+ rgba[dstIdx] = color.r;
585
+ rgba[dstIdx + 1] = color.g;
586
+ rgba[dstIdx + 2] = color.b;
587
+ rgba[dstIdx + 3] = alpha;
588
+ }
589
+ }
590
+ }
591
+ offset += 16;
592
+ }
593
+ }
594
+ return rgba;
595
+ }
596
+ function decodeAlphaBlock(alphaData) {
597
+ const alpha = new Array(16);
598
+ const alpha0 = Number(alphaData & 0xFFn);
599
+ const alpha1 = Number(alphaData >> 8n & 0xFFn);
600
+ const alphas = alpha0 > alpha1 ? [
601
+ alpha0,
602
+ alpha1,
603
+ interpolateByteSeventh(alpha0, alpha1, 1),
604
+ interpolateByteSeventh(alpha0, alpha1, 2),
605
+ interpolateByteSeventh(alpha0, alpha1, 3),
606
+ interpolateByteSeventh(alpha0, alpha1, 4),
607
+ interpolateByteSeventh(alpha0, alpha1, 5),
608
+ interpolateByteSeventh(alpha0, alpha1, 6)
609
+ ] : [
610
+ alpha0,
611
+ alpha1,
612
+ interpolateByteFifth(alpha0, alpha1, 1),
613
+ interpolateByteFifth(alpha0, alpha1, 2),
614
+ interpolateByteFifth(alpha0, alpha1, 3),
615
+ interpolateByteFifth(alpha0, alpha1, 4),
616
+ 0,
617
+ 255
618
+ ];
619
+ for (let i = 0; i < 16; i++) {
620
+ const bitOffset = 16 + i * 3;
621
+ const index = Number(alphaData >> BigInt(bitOffset) & 0x7n);
622
+ alpha[i] = alphas[index];
623
+ }
624
+ return alpha;
625
+ }
626
+ function decodeBC3(data, width, height) {
627
+ const rgba = new Uint8Array(width * height * 4);
628
+ const blocksX = Math.ceil(width / 4);
629
+ const blocksY = Math.ceil(height / 4);
630
+ let offset = 0;
631
+ for (let by = 0; by < blocksY; by++) {
632
+ for (let bx = 0; bx < blocksX; bx++) {
633
+ const alphaBlock = data.getBigUint64(offset, true);
634
+ const alphas = decodeAlphaBlock(alphaBlock);
635
+ const color0Data = data.getUint16(offset + 8, true);
636
+ const color1Data = data.getUint16(offset + 10, true);
637
+ const indices = data.getUint32(offset + 12, true);
638
+ const color0 = new ColorRgb565();
639
+ color0.data = color0Data;
640
+ const color1 = new ColorRgb565();
641
+ color1.data = color1Data;
642
+ const c0 = color0.toColorRgb24();
643
+ const c1 = color1.toColorRgb24();
644
+ const colors = [
645
+ c0,
646
+ c1,
647
+ interpolateThird(c0, c1, 1),
648
+ interpolateThird(c0, c1, 2)
649
+ ];
650
+ for (let y = 0; y < 4; y++) {
651
+ for (let x = 0; x < 4; x++) {
652
+ const px = bx * 4 + x;
653
+ const py = by * 4 + y;
654
+ if (px < width && py < height) {
655
+ const i = y * 4 + x;
656
+ const colorIndex = indices >> i * 2 & 3;
657
+ const color = colors[colorIndex];
658
+ const dstIdx = (py * width + px) * 4;
659
+ rgba[dstIdx] = color.r;
660
+ rgba[dstIdx + 1] = color.g;
661
+ rgba[dstIdx + 2] = color.b;
662
+ rgba[dstIdx + 3] = alphas[i];
663
+ }
664
+ }
665
+ }
666
+ offset += 16;
667
+ }
668
+ }
669
+ return rgba;
670
+ }
671
+
672
+ // src/FormatConverter.ts
673
+ var PixelFormatConversion = class {
674
+ static setColor(img, offset, a, r, g, b) {
675
+ img[offset] = b;
676
+ img[offset + 1] = g;
677
+ img[offset + 2] = r;
678
+ img[offset + 3] = a;
679
+ }
680
+ static argb16ToArgb32(src) {
681
+ const dst = new Uint8Array(src.length * 2);
682
+ const nPixel = Math.floor(src.length / 2);
683
+ for (let index = 0; index < nPixel; index++) {
684
+ const hbyte = src[index * 2 + 1];
685
+ const lbyte = src[index * 2];
686
+ const lhbyte = hbyte & 15;
687
+ const hhbyte = (hbyte & 240) >> 4;
688
+ const llbyte = lbyte & 15;
689
+ const hlbyte = (lbyte & 240) >> 4;
690
+ const b = Math.floor(lhbyte * 255 / 15);
691
+ const a = Math.floor(hhbyte * 255 / 15);
692
+ const r = Math.floor(llbyte * 255 / 15);
693
+ const g = Math.floor(hlbyte * 255 / 15);
694
+ this.setColor(dst, index * 4, a, r, g, b);
695
+ }
696
+ return dst;
697
+ }
698
+ static argb1555ToArgb32(src) {
699
+ const dst = new Uint8Array(src.length * 2);
700
+ const nPixel = Math.floor(src.length / 2);
701
+ const view = new DataView(src.buffer, src.byteOffset, src.byteLength);
702
+ for (let index = 0; index < nPixel; index++) {
703
+ const s = view.getUint16(index * 2, true);
704
+ const abit = (s & 32768) >> 15 === 1;
705
+ const b5bit = s & 31;
706
+ const g5bit = (s & 992) >> 5;
707
+ const r5bit = (s & 31744) >> 10;
708
+ const b = Math.floor(b5bit * 255 / 31);
709
+ const a = abit ? 255 : 0;
710
+ const r = Math.floor(r5bit * 255 / 31);
711
+ const g = Math.floor(g5bit * 255 / 31);
712
+ this.setColor(dst, index * 4, a, r, g, b);
713
+ }
714
+ return dst;
715
+ }
716
+ static ai88ToArgb32(src) {
717
+ const dst = new Uint8Array(src.length * 2);
718
+ const nPixel = Math.floor(src.length / 2);
719
+ for (let index = 0; index < nPixel; index++) {
720
+ const grey = src[index * 2];
721
+ const alpha = src[index * 2 + 1];
722
+ this.setColor(dst, index * 4, alpha, grey, grey, grey);
723
+ }
724
+ return dst;
725
+ }
726
+ static p8ToARGB32(src, palette) {
727
+ const dst = new Uint8Array(src.length * 4);
728
+ const colors = palette.colors;
729
+ const nPixel = src.length;
730
+ for (let index = 0; index < nPixel; index++) {
731
+ const color = colors[src[index]];
732
+ this.setColor(dst, index * 4, color.alpha, color.red, color.green, color.blue);
733
+ }
734
+ return dst;
735
+ }
736
+ static dxtToRgba32(data, width, height, format, useAlpha = true) {
737
+ const dataView = new DataView(data.buffer, data.byteOffset, data.byteLength);
738
+ let rgba;
739
+ switch (format) {
740
+ case "BC1":
741
+ rgba = decodeBC1(dataView, width, height, useAlpha);
742
+ break;
743
+ case "BC2":
744
+ rgba = decodeBC2(dataView, width, height);
745
+ break;
746
+ case "BC3":
747
+ rgba = decodeBC3(dataView, width, height);
748
+ break;
749
+ default:
750
+ throw new Error(`Unsupported DXT format: ${format}`);
751
+ }
752
+ const bgra = new Uint8Array(rgba.length);
753
+ for (let i = 0; i < rgba.length; i += 4) {
754
+ bgra[i] = rgba[i + 2];
755
+ bgra[i + 1] = rgba[i + 1];
756
+ bgra[i + 2] = rgba[i];
757
+ bgra[i + 3] = rgba[i + 3];
758
+ }
759
+ return bgra;
760
+ }
761
+ static convertToARGB32(data, width, height, type) {
762
+ switch (type) {
763
+ case 65281 /* DXT1 */:
764
+ return this.dxtToRgba32(data, width, height, "BC1");
765
+ case 65282 /* DXT2 */:
766
+ return this.dxtToRgba32(data, width, height, "BC2");
767
+ case 65283 /* DXT3 */:
768
+ return this.dxtToRgba32(data, width, height, "BC2");
769
+ case 65284 /* DXT4 */:
770
+ return this.dxtToRgba32(data, width, height, "BC3");
771
+ case 65285 /* DXT5 */:
772
+ return this.dxtToRgba32(data, width, height, "BC3");
773
+ case 5461 /* RGBA_5551 */:
774
+ return this.argb1555ToArgb32(data);
775
+ case 17476 /* RGBA_4444 */:
776
+ return this.argb16ToArgb32(data);
777
+ case 32896 /* AI88 */:
778
+ return this.ai88ToArgb32(data);
779
+ case 34952 /* RGBA_8888 */:
780
+ return data instanceof Uint8Array ? data : new Uint8Array(data);
781
+ default:
782
+ throw new Error(`Unsupported PaaType: ${String(type)}`);
783
+ }
784
+ }
785
+ };
786
+
787
+ // src/Mipmap.ts
788
+ var Mipmap = class {
789
+ constructor(formatOrWidth, height, data, format) {
790
+ this.width = 0;
791
+ this.height = 0;
792
+ this.isLzss = false;
793
+ this.isLzo = false;
794
+ this.dataOffset = 0;
795
+ this.dataSize = 0;
796
+ this.rawData = null;
797
+ if (height !== void 0 && data !== void 0 && format !== void 0) {
798
+ this.width = formatOrWidth;
799
+ this.height = height;
800
+ this.format = format;
801
+ if (this.width * this.height > 16384) {
802
+ this.isLzo = true;
803
+ }
804
+ this.dataOffset = -1;
805
+ if (this.isLzo) {
806
+ this.rawData = data instanceof Uint8Array ? data : data;
807
+ this.dataSize = this.rawData?.length ?? 0;
808
+ } else {
809
+ this.rawData = data instanceof Uint8Array ? data : data;
810
+ this.dataSize = data?.length ?? 0;
811
+ }
812
+ } else {
813
+ this.format = formatOrWidth;
814
+ }
815
+ }
816
+ read(br) {
817
+ this.width = br.readUInt16();
818
+ this.height = br.readUInt16();
819
+ if (this.width === 1234 && this.height === 8765) {
820
+ this.width = br.readUInt16();
821
+ this.height = br.readUInt16();
822
+ this.isLzss = true;
823
+ }
824
+ if ((this.width & 32768) !== 0) {
825
+ this.width &= 32767;
826
+ this.isLzo = true;
827
+ }
828
+ this.dataSize = br.readInt24();
829
+ this.dataOffset = br.pos;
830
+ br.seek(this.dataSize, "current");
831
+ }
832
+ getRawPixelData(buffer) {
833
+ if (this.dataOffset === -1) {
834
+ throw new Error("Data offset is not set");
835
+ }
836
+ const br = new BinaryReader(buffer);
837
+ br.seek(this.dataOffset);
838
+ let uncompressedSize = this.width * this.height;
839
+ switch (this.format) {
840
+ case 65281 /* DXT1 */:
841
+ uncompressedSize = Math.floor(uncompressedSize / 2);
842
+ // Fall through
843
+ case 65282 /* DXT2 */:
844
+ case 65283 /* DXT3 */:
845
+ case 65284 /* DXT4 */:
846
+ case 65285 /* DXT5 */:
847
+ if (!this.isLzo) {
848
+ uncompressedSize = this.dataSize;
849
+ }
850
+ break;
851
+ case 5461 /* RGBA_5551 */:
852
+ case 17476 /* RGBA_4444 */:
853
+ case 32896 /* AI88 */:
854
+ uncompressedSize *= 2;
855
+ this.isLzss = uncompressedSize > 1023;
856
+ break;
857
+ case 34952 /* RGBA_8888 */:
858
+ uncompressedSize *= 4;
859
+ break;
860
+ }
861
+ if (this.isLzo) {
862
+ const compressedData = br.readBytes(this.dataSize);
863
+ return lzoDecompress(compressedData, uncompressedSize);
864
+ }
865
+ if (!this.isLzss) {
866
+ return br.readBytes(this.dataSize);
867
+ }
868
+ const result = lzssDecompress(buffer, br.pos, uncompressedSize, false);
869
+ br.seek(result.bytesRead, "current");
870
+ return result.data;
871
+ }
872
+ getRgba32PixelData(buffer) {
873
+ const data = this.getRawPixelData(buffer);
874
+ return PixelFormatConversion.convertToARGB32(data, this.width, this.height, this.format);
875
+ }
876
+ };
877
+
878
+ // src/ChannelSwizzler.ts
879
+ var ChannelSwizzle = /* @__PURE__ */ ((ChannelSwizzle3) => {
880
+ ChannelSwizzle3[ChannelSwizzle3["Alpha"] = 0] = "Alpha";
881
+ ChannelSwizzle3[ChannelSwizzle3["Red"] = 1] = "Red";
882
+ ChannelSwizzle3[ChannelSwizzle3["Green"] = 2] = "Green";
883
+ ChannelSwizzle3[ChannelSwizzle3["Blue"] = 3] = "Blue";
884
+ ChannelSwizzle3[ChannelSwizzle3["InvertedAlpha"] = 4] = "InvertedAlpha";
885
+ ChannelSwizzle3[ChannelSwizzle3["InvertedRed"] = 5] = "InvertedRed";
886
+ ChannelSwizzle3[ChannelSwizzle3["InvertedGreen"] = 6] = "InvertedGreen";
887
+ ChannelSwizzle3[ChannelSwizzle3["InvertedBlue"] = 7] = "InvertedBlue";
888
+ ChannelSwizzle3[ChannelSwizzle3["One"] = 8] = "One";
889
+ return ChannelSwizzle3;
890
+ })(ChannelSwizzle || {});
891
+ var _RgbaSwizzle = class _RgbaSwizzle {
892
+ constructor() {
893
+ this.swizBlue = 3 /* Blue */;
894
+ this.swizGreen = 2 /* Green */;
895
+ this.swizRed = 1 /* Red */;
896
+ this.swizAlpha = 0 /* Alpha */;
897
+ }
898
+ equals(other) {
899
+ return this.swizBlue === other.swizBlue && this.swizGreen === other.swizGreen && this.swizRed === other.swizRed && this.swizAlpha === other.swizAlpha;
900
+ }
901
+ };
902
+ _RgbaSwizzle.Default = new _RgbaSwizzle();
903
+ var RgbaSwizzle = _RgbaSwizzle;
904
+ var ChannelSwizzler = class {
905
+ static apply(rgbaData, swizzle) {
906
+ if (swizzle.equals(RgbaSwizzle.Default)) {
907
+ return;
908
+ }
909
+ for (let pixOffset = 0; pixOffset < rgbaData.length; pixOffset += 4) {
910
+ const pixel = (rgbaData[pixOffset + 2] | // Red at bit 0
911
+ rgbaData[pixOffset + 1] << 8 | // Green at bit 8
912
+ rgbaData[pixOffset] << 16 | // Blue at bit 16
913
+ rgbaData[pixOffset + 3] << 24) >>> 0;
914
+ rgbaData[pixOffset + 2] = this.transformChannel(pixel, swizzle.swizRed);
915
+ rgbaData[pixOffset + 1] = this.transformChannel(pixel, swizzle.swizGreen);
916
+ rgbaData[pixOffset + 0] = this.transformChannel(pixel, swizzle.swizBlue);
917
+ rgbaData[pixOffset + 3] = this.transformChannel(pixel, swizzle.swizAlpha);
918
+ }
919
+ }
920
+ static transformChannel(pixel, swizzle) {
921
+ if (swizzle === 8 /* One */) {
922
+ return 255;
923
+ }
924
+ const isInverted = swizzle >= 4 /* InvertedAlpha */ && swizzle <= 7 /* InvertedBlue */;
925
+ if (isInverted) {
926
+ swizzle = swizzle - 4 /* InvertedAlpha */ + 0 /* Alpha */;
927
+ }
928
+ let offset;
929
+ switch (swizzle) {
930
+ case 1 /* Red */:
931
+ offset = 0;
932
+ break;
933
+ case 2 /* Green */:
934
+ offset = 8;
935
+ break;
936
+ case 3 /* Blue */:
937
+ offset = 16;
938
+ break;
939
+ case 0 /* Alpha */:
940
+ offset = 24;
941
+ break;
942
+ default:
943
+ throw new Error(`Invalid swizzle: ${swizzle}`);
944
+ }
945
+ const result = pixel >>> offset & 255;
946
+ return isInverted ? 255 - result : result;
947
+ }
948
+ };
949
+
950
+ // src/Paa.ts
951
+ var Paa = class {
952
+ constructor() {
953
+ this.type = 65285 /* DXT5 */;
954
+ this.isAlpha = false;
955
+ this.isTransparent = false;
956
+ this.averageColor = null;
957
+ this.maxColor = null;
958
+ this.palette = new Palette();
959
+ this.mipmaps = [];
960
+ this.channelSwizzle = RgbaSwizzle.Default;
961
+ this.procedure = "";
962
+ }
963
+ /**
964
+ * Read a PAA file from a buffer
965
+ */
966
+ read(buffer) {
967
+ const br = new BinaryReader(buffer);
968
+ this.type = br.readUInt16();
969
+ let mipMapOffsets = null;
970
+ while (br.readRawString(4) === "GGAT") {
971
+ const name = br.readRawString(4).split("").reverse().join("");
972
+ const len = br.readInt32();
973
+ switch (name) {
974
+ case "AVGC":
975
+ this.averageColor = new PaaColor(br.readUInt32());
976
+ break;
977
+ case "MAXC":
978
+ this.maxColor = new PaaColor(br.readUInt32());
979
+ break;
980
+ case "FLAG":
981
+ const flag = br.readInt32();
982
+ if ((flag & 1) !== 0) {
983
+ this.isAlpha = true;
984
+ }
985
+ if ((flag & 2) !== 0) {
986
+ this.isTransparent = true;
987
+ }
988
+ break;
989
+ case "SWIZ":
990
+ this.channelSwizzle = new RgbaSwizzle();
991
+ this.channelSwizzle.swizAlpha = br.readByte();
992
+ this.channelSwizzle.swizRed = br.readByte();
993
+ this.channelSwizzle.swizGreen = br.readByte();
994
+ this.channelSwizzle.swizBlue = br.readByte();
995
+ break;
996
+ case "PROC":
997
+ this.procedure = br.readRawString(len);
998
+ break;
999
+ case "OFFS":
1000
+ const nOffsets = Math.floor(len / 4);
1001
+ mipMapOffsets = [];
1002
+ for (let i = 0; i < nOffsets; i++) {
1003
+ mipMapOffsets.push(br.readUInt32());
1004
+ }
1005
+ break;
1006
+ default:
1007
+ throw new Error(`Got unknown tag: ${name}`);
1008
+ }
1009
+ }
1010
+ br.seek(-4, "current");
1011
+ this.palette.read(br);
1012
+ this.mipmaps = [];
1013
+ if (mipMapOffsets !== null) {
1014
+ for (const mipMapOffset of mipMapOffsets) {
1015
+ if (mipMapOffset === 0) {
1016
+ break;
1017
+ }
1018
+ br.seek(mipMapOffset, "begin");
1019
+ const mipmap = new Mipmap(this.type);
1020
+ mipmap.read(br);
1021
+ this.mipmaps.push(mipmap);
1022
+ }
1023
+ }
1024
+ const terminator = br.readUInt16();
1025
+ if (terminator !== 0) {
1026
+ throw new Error("Invalid format: terminator bytes not found");
1027
+ }
1028
+ }
1029
+ /**
1030
+ * Get ARGB32 pixel data for a specific mipmap level
1031
+ */
1032
+ getArgb32PixelData(buffer, mipLevel = 0) {
1033
+ if (mipLevel < 0 || mipLevel >= this.mipmaps.length) {
1034
+ throw new RangeError(`mipLevel ${mipLevel} out of range`);
1035
+ }
1036
+ const data = this.mipmaps[mipLevel].getRgba32PixelData(buffer);
1037
+ ChannelSwizzler.apply(data, this.channelSwizzle);
1038
+ return data;
1039
+ }
1040
+ };
1041
+ export {
1042
+ BinaryReader,
1043
+ ChannelSwizzle,
1044
+ ChannelSwizzler,
1045
+ Mipmap,
1046
+ Paa,
1047
+ PaaColor,
1048
+ PaaType,
1049
+ Palette,
1050
+ PixelFormatConversion,
1051
+ RgbaSwizzle,
1052
+ calculateChecksum,
1053
+ lzoDecompress,
1054
+ lzssDecompress
1055
+ };
1056
+ /**
1057
+ * LZO1X compression and decompression
1058
+ * Based on https://github.com/thaumictom/lzo-ts
1059
+ * @license GPL-3.0
1060
+ */
1061
+ //# sourceMappingURL=index.js.map