diff --git a/src/core/blitzkrieg/superCompress.ts b/src/core/blitzkrieg/superCompress.ts index 68406dac1..5236447e3 100644 --- a/src/core/blitzkrieg/superCompress.ts +++ b/src/core/blitzkrieg/superCompress.ts @@ -3,6 +3,6 @@ import { CdonWriteStream } from '../streams/cdon'; export function superCompress(object: any) { const write = new CdonWriteStream().cdon(object); - const compressed = compress(write.buffer); + const compressed = compress(write.uint8Array); return Buffer.from(compressed).toString('base64'); } diff --git a/src/core/streams/buffer.ts b/src/core/streams/buffer.ts index 1edd1730f..872c11acb 100644 --- a/src/core/streams/buffer.ts +++ b/src/core/streams/buffer.ts @@ -1,19 +1,27 @@ export class ReadStream { public index = 0; - constructor(public buffer: Buffer) {} + private dataView: DataView; + private textDecoderAscii = new TextDecoder('ascii'); + private textDecoderUtf8 = new TextDecoder('utf8'); - skip(size: number) { + constructor(public buffer: ArrayBuffer) { + this.dataView = new DataView(buffer); + } + + seek(size: number) { this.index += size; } read(size: number) { - return this.buffer.subarray(this.index, this.index + size); + return this.buffer.slice(this.index, this.index + size); } consume(size: number) { const subarray = this.read(size); - this.skip(size); - + this.seek(size); return subarray; } + consumeUint8Array(size: number) { + return new Uint8Array(this.consume(size)); + } increment(size: number) { return (this.index += size) - size; } @@ -21,9 +29,6 @@ export class ReadStream { readRemaining() { return this.read(Number.POSITIVE_INFINITY); } - readRemainingLength() { - return this.buffer.length - this.index; - } consumeRemaining() { return this.consume(Number.POSITIVE_INFINITY); } @@ -33,57 +38,54 @@ export class ReadStream { } ascii(size: number) { - return this.buffer.toString('ascii', this.increment(size), this.index); + return this.textDecoderAscii.decode(this.consume(size)); } utf8(size: number) { - return this.buffer.toString('utf8', this.increment(size), this.index); + return this.textDecoderUtf8.decode(this.consume(size)); } int8() { - return this.buffer.readInt8(this.increment(1)); + return this.dataView.getInt8(this.increment(1)); } int16() { - return this.buffer.readInt16LE(this.increment(2)); + return this.dataView.getInt16(this.increment(2), true); } int32() { - return this.buffer.readInt32LE(this.increment(4)); + return this.dataView.getInt32(this.increment(4), true); } int64() { - return this.buffer.readBigInt64LE(this.increment(8)); + return this.dataView.getBigInt64(this.increment(8), true); } uint8() { - return this.buffer.readUInt8(this.increment(1)); + return this.dataView.getUint8(this.increment(1)); } uint16() { - return this.buffer.readUInt16LE(this.increment(2)); + return this.dataView.getUint16(this.increment(2), true); } uint32() { - return this.buffer.readUInt32LE(this.increment(4)); + return this.dataView.getUint32(this.increment(4), true); } uint64() { - return this.buffer.readBigUInt64LE(this.increment(8)); + return this.dataView.getBigUint64(this.increment(8), true); } float32() { - return this.buffer.readFloatLE(this.increment(4)); + return this.dataView.getFloat32(this.increment(4), true); } float64() { - return this.buffer.readDoubleLE(this.increment(8)); + return this.dataView.getFloat64(this.increment(8), true); } boolean() { - return this.buffer.readUInt8(this.increment(1)) === 1; + return this.dataView.getUint8(this.increment(1)) === 1; } } export class WriteStream { private array: number[] = []; + private textEncoder = new TextEncoder(); - get buffer() { - return Buffer.from(this.array); - } - - constructor(buffer?: Buffer) { - if (buffer) this.array = Array.from(buffer); + get uint8Array() { + return new Uint8Array(this.array); } byte(value: Uint8Array) { @@ -98,13 +100,7 @@ export class WriteStream { return this; } utf8(value: string) { - const buffer = Buffer.alloc(Buffer.byteLength(value)); - - buffer.write(value, 'utf8'); - buffer.forEach((value) => { - this.array.push(value); - }); - + this.array.push(...this.textEncoder.encode(value)); return this; } diff --git a/src/core/streams/dds.ts b/src/core/streams/dds.ts index db1b7d7e5..a57bf589a 100644 --- a/src/core/streams/dds.ts +++ b/src/core/streams/dds.ts @@ -331,10 +331,10 @@ export class DdsReadStream extends WindowsReadStream { } readR5G6B5Int() { - return this.read(2).readUInt16LE(); + return new DataView(this.read(2)).getUint16(0, true); } R5G6B5() { - const buffer = this.consume(2); + const buffer = this.consumeUint8Array(2); const r = (buffer[1] & 0b11111000) >>> 3; const g = ((buffer[1] & 0b111) << 3) | ((buffer[0] & 0b11100000) >>> 5); const b = buffer[0] & 0b11111; @@ -375,7 +375,7 @@ export class DdsReadStream extends WindowsReadStream { } as Record; } bc1ColorKeys() { - const buffer = this.consume(4); + const buffer = this.consumeUint8Array(4); const d = (buffer[0] & 0b11000000) >>> 6; const c = (buffer[0] & 0b110000) >>> 4; const b = (buffer[0] & 0b1100) >>> 2; @@ -396,7 +396,7 @@ export class DdsReadStream extends WindowsReadStream { return [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p]; } bc2AlphaInterpolations() { - const buffer = this.consume(8); + const buffer = this.consumeUint8Array(8); const d = (buffer[1] & 0b11110000) >>> 4; const c = buffer[1] & 0b1111; const b = (buffer[0] & 0b11110000) >>> 4; @@ -464,7 +464,7 @@ export class DdsReadStream extends WindowsReadStream { } as Record; } bc3AlphaKeys() { - const buffer = this.consume(6); + const buffer = this.consumeUint8Array(6); const h = (buffer[2] & 0b11100000) >>> 5; const g = (buffer[2] & 0b11100) >>> 2; const f = ((buffer[2] & 0b11) << 1) | ((buffer[1] & 0b10000000) >>> 7); diff --git a/src/core/streams/pvr.ts b/src/core/streams/pvr.ts index 4009abf3b..d23360ddf 100644 --- a/src/core/streams/pvr.ts +++ b/src/core/streams/pvr.ts @@ -116,7 +116,7 @@ export class PvrReadStream extends ReadStream { const data = Buffer.alloc(pixelCount * 4); times(pixelCount, (index) => { - const buffer = this.consume(2); + const buffer = this.consumeUint8Array(2); const bufferIndex = index * 4; const r = ((buffer[1] & 0b11110000) >>> 4) / 15; const g = (buffer[1] & 0b1111) / 15; @@ -141,7 +141,7 @@ export class PvrReadStream extends ReadStream { const data = Buffer.alloc(pixelCount * 3); times(pixelCount, (index) => { - const buffer = this.consume(2); + const buffer = this.consumeUint8Array(2); const bufferIndex = index * 4; const r = ((buffer[1] & 0b11111000) >>> 3) / 31; const g = @@ -191,9 +191,9 @@ export class PvrReadStream extends ReadStream { return header; } pixelFormat() { - this.skip(4); + this.seek(4); const usesPresetFormat = this.uint32() === 0; - this.skip(-8); + this.seek(-8); return usesPresetFormat ? (Number(this.uint64()) as PvrPixelFormat) diff --git a/src/core/streams/sc2.ts b/src/core/streams/sc2.ts index d802fd6cc..b9dd1c5d3 100644 --- a/src/core/streams/sc2.ts +++ b/src/core/streams/sc2.ts @@ -306,7 +306,7 @@ export class Sc2ReadStream extends ScpgReadStream { const fileType = this.uint32(); // other felids that we don't have any info about - this.skip(size - 4); + this.seek(size - 4); return { size, fileType }; } diff --git a/src/core/streams/scg.ts b/src/core/streams/scg.ts index 26c4b946e..c703a3f7b 100644 --- a/src/core/streams/scg.ts +++ b/src/core/streams/scg.ts @@ -89,9 +89,9 @@ export class ScgReadStream extends ScpgReadStream { ); const strideBasedSize = stride * polygonGroupRaw.vertexCount; - if (verticesStream.buffer.length !== strideBasedSize) { + if (verticesStream.buffer.byteLength !== strideBasedSize) { console.warn( - `Vertex stride mismatch; expected ${strideBasedSize}, got ${verticesStream.buffer.length}; skipping...`, + `Vertex stride mismatch; expected ${strideBasedSize}, got ${verticesStream.buffer.byteLength}; skipping...`, ); return; @@ -104,10 +104,6 @@ export class ScgReadStream extends ScpgReadStream { })); } - if (verticesStream.readRemainingLength() !== 0) { - throw new RangeError('Vertices stream was not fully consumed'); - } - polygonGroups.set(polygonGroupRaw['#id'].readBigUInt64LE(), { vertices, indices, diff --git a/src/core/streams/scpg.ts b/src/core/streams/scpg.ts index 48ccf01e0..8d8401b71 100644 --- a/src/core/streams/scpg.ts +++ b/src/core/streams/scpg.ts @@ -121,7 +121,7 @@ export class ScpgReadStream extends ReadStream { } case KAType.KEYED_ARCHIVE: { - this.skip(4); // UInt32 length of the nested archive in bytes + this.seek(4); // UInt32 length of the nested archive in bytes return this.ka(stringTable); } @@ -195,7 +195,7 @@ export class ScpgReadStream extends ReadStream { } } ka(stringTable?: Record) { - this.skip(2); // "KA" + this.seek(2); // "KA" const version = this.uint16(); const pairs: Record = {};