diff --git a/.vscode/settings.json b/.vscode/settings.json index 5440801cb..6b7e71aa3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -6,6 +6,7 @@ "alphatest", "apcr", "atgm", + "AYUV", "bepaint", "BINORMAL", "Binormals", @@ -18,14 +19,18 @@ "CUBETEXCOORD", "customperiod", "datasource", + "Ddpf", + "Ddsd", "debugflags", "deburr", "decalmask", "diacriticless", "dvpl", "DVPLCRC", + "dxgi", "Everytime", "FASTNAME", + "FOURCC", "fullstats", "fuzzysort", "gamemode", @@ -60,6 +65,7 @@ "searchclans", "searchplayers", "searchtanks", + "SHAREDEXP", "SKLLD", "Smri", "Specularity", diff --git a/src/core/blitzkrieg/readDds.ts b/src/core/blitzkrieg/readDds.ts deleted file mode 100644 index cd7062764..000000000 --- a/src/core/blitzkrieg/readDds.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { readDVPLFile } from '../blitz/readDVPLFile'; -import { PrimitiveStream } from '../streams/primitive'; - -export function readDds(buffer: Buffer) { - const stream = new PrimitiveStream(buffer); - const name = stream.consumeAscii(4); - - if (name !== 'DDS ') throw new TypeError('Not a DDS file'); -} - -readDds( - await readDVPLFile( - 'C:/Program Files (x86)/Steam/steamapps/common/World of Tanks Blitz/Data/3d/Tanks/German/images_pbr/E_100_BC.dx11.dds.dvpl', - ), -); diff --git a/src/core/streams/dds.ts b/src/core/streams/dds.ts new file mode 100644 index 000000000..eb726e3e8 --- /dev/null +++ b/src/core/streams/dds.ts @@ -0,0 +1,236 @@ +import { times } from 'lodash'; +import { readDVPLFile } from '../blitz/readDVPLFile'; +import { WindowsStream } from './windows'; + +enum DxgiFormat { + UNKNOWN = 0, + R32G32B32A32_TYPELESS = 1, + R32G32B32A32_FLOAT = 2, + R32G32B32A32_UINT = 3, + R32G32B32A32_SINT = 4, + R32G32B32_TYPELESS = 5, + R32G32B32_FLOAT = 6, + R32G32B32_UINT = 7, + R32G32B32_SINT = 8, + R16G16B16A16_TYPELESS = 9, + R16G16B16A16_FLOAT = 10, + R16G16B16A16_UNORM = 11, + R16G16B16A16_UINT = 12, + R16G16B16A16_SNORM = 13, + R16G16B16A16_SINT = 14, + R32G32_TYPELESS = 15, + R32G32_FLOAT = 16, + R32G32_UINT = 17, + R32G32_SINT = 18, + R32G8X24_TYPELESS = 19, + D32_FLOAT_S8X24_UINT = 20, + R32_FLOAT_X8X24_TYPELESS = 21, + X32_TYPELESS_G8X24_UINT = 22, + R10G10B10A2_TYPELESS = 23, + R10G10B10A2_UNORM = 24, + R10G10B10A2_UINT = 25, + R11G11B10_FLOAT = 26, + R8G8B8A8_TYPELESS = 27, + R8G8B8A8_UNORM = 28, + R8G8B8A8_UNORM_SRGB = 29, + R8G8B8A8_UINT = 30, + R8G8B8A8_SNORM = 31, + R8G8B8A8_SINT = 32, + R16G16_TYPELESS = 33, + R16G16_FLOAT = 34, + R16G16_UNORM = 35, + R16G16_UINT = 36, + R16G16_SNORM = 37, + R16G16_SINT = 38, + R32_TYPELESS = 39, + D32_FLOAT = 40, + R32_FLOAT = 41, + R32_UINT = 42, + R32_SINT = 43, + R24G8_TYPELESS = 44, + D24_UNORM_S8_UINT = 45, + R24_UNORM_X8_TYPELESS = 46, + X24_TYPELESS_G8_UINT = 47, + R8G8_TYPELESS = 48, + R8G8_UNORM = 49, + R8G8_UINT = 50, + R8G8_SNORM = 51, + R8G8_SINT = 52, + R16_TYPELESS = 53, + R16_FLOAT = 54, + D16_UNORM = 55, + R16_UNORM = 56, + R16_UINT = 57, + R16_SNORM = 58, + R16_SINT = 59, + R8_TYPELESS = 60, + R8_UNORM = 61, + R8_UINT = 62, + R8_SNORM = 63, + R8_SINT = 64, + A8_UNORM = 65, + R1_UNORM = 66, + R9G9B9E5_SHAREDEXP = 67, + R8G8_B8G8_UNORM = 68, + G8R8_G8B8_UNORM = 69, + BC1_TYPELESS = 70, + BC1_UNORM = 71, + BC1_UNORM_SRGB = 72, + BC2_TYPELESS = 73, + BC2_UNORM = 74, + BC2_UNORM_SRGB = 75, + BC3_TYPELESS = 76, + BC3_UNORM = 77, + BC3_UNORM_SRGB = 78, + BC4_TYPELESS = 79, + BC4_UNORM = 80, + BC4_SNORM = 81, + BC5_TYPELESS = 82, + BC5_UNORM = 83, + BC5_SNORM = 84, + B5G6R5_UNORM = 85, + B5G5R5A1_UNORM = 86, + B8G8R8A8_UNORM = 87, + B8G8R8X8_UNORM = 88, + R10G10B10_XR_BIAS_A2_UNORM = 89, + B8G8R8A8_TYPELESS = 90, + B8G8R8A8_UNORM_SRGB = 91, + B8G8R8X8_TYPELESS = 92, + B8G8R8X8_UNORM_SRGB = 93, + BC6H_TYPELESS = 94, + BC6H_UF16 = 95, + BC6H_SF16 = 96, + BC7_TYPELESS = 97, + BC7_UNORM = 98, + BC7_UNORM_SRGB = 99, + AYUV = 100, + Y410 = 101, + Y416 = 102, + NV12 = 103, + P010 = 104, + P016 = 105, + '420_OPAQUE' = 106, + YUY2 = 107, + Y210 = 108, + Y216 = 109, + NV11 = 110, + AI44 = 111, + IA44 = 112, + P8 = 113, + A8P8 = 114, + B4G4R4A4_UNORM = 115, + P208 = 130, + V208 = 131, + V408 = 132, + SAMPLER_FEEDBACK_MIN_MIP_OPAQUE, + SAMPLER_FEEDBACK_MIP_REGION_USED_OPAQUE, + FORCE_UINT = 0xffffffff, +} + +enum D3d10ResourceDimension { + UNKNOWN = 0, + BUFFER = 1, + TEXTURE1D = 2, + TEXTURE2D = 3, + TEXTURE3D = 4, +} + +enum DdsdFlags { + CAPS = 0x1, + HEIGHT = 0x2, + WIDTH = 0x4, + PITCH = 0x8, + PIXELFORMAT = 0x1000, + MIPMAPCOUNT = 0x20000, + LINEARSIZE = 0x80000, + DEPTH = 0x800000, +} + +enum DdpfFlags { + ALPHA = 0x1, + FOURCC = 0x4, + RGB = 0x40, + YUV = 0x200, + LUMINANCE = 0x20000, +} + +enum DdsCaps { + COMPLEX = 0x8, + MIPMAP = 0x400000, + TEXTURE = 0x1000, +} + +enum DdsCaps2 { + CUBEMAP = 0x200, + CUBEMAP_POSITIVEX = 0x400, + CUBEMAP_NEGATIVEX = 0x800, + CUBEMAP_POSITIVEY = 0x1000, + CUBEMAP_NEGATIVEY = 0x2000, + CUBEMAP_POSITIVEZ = 0x4000, + CUBEMAP_NEGATIVEZ = 0x8000, + VOLUME = 0x200000, +} + +export class DdsStream extends WindowsStream { + dds() { + const magicNumber = this.magicNumber(); + const header = this.header(); + const headerDxt10 = + header.pf.flags === DdpfFlags.FOURCC && header.pf.fourCC === 0x30315844 + ? this.headerDxt10() + : undefined; + } + + magicNumber() { + return this.dword(); + } + + header() { + return { + size: this.dword(), + flags: this.dword() as DdsdFlags, + height: this.dword(), + width: this.dword(), + pitchOrLinearSize: this.dword(), + depth: this.dword(), + mipMapCount: this.dword(), + reserved1: times(11, () => this.dword()), + pf: this.pixelFormat(), + caps: this.dword() as DdsCaps, + caps2: this.dword() as DdsCaps2, + caps3: this.dword(), + caps4: this.dword(), + reserved2: times(1, () => this.dword()), + headerDxt10: undefined, + }; + } + + pixelFormat() { + return { + size: this.dword(), + flags: this.dword() as DdpfFlags, + fourCC: this.dword(), + rgbBitCount: this.dword(), + rBitMask: this.dword(), + gBitMask: this.dword(), + bBitMask: this.dword(), + aBitMask: this.dword(), + }; + } + + headerDxt10() { + return { + dxgiFormat: this.uint() as DxgiFormat, + resourceDimension: this.uint() as D3d10ResourceDimension, + miscFlag: this.uint(), + arraySize: this.uint(), + miscFlags2: this.uint(), + }; + } +} + +new DdsStream( + await readDVPLFile( + 'C:/Program Files (x86)/Steam/steamapps/common/World of Tanks Blitz/Data/3d/Tanks/German/images_pbr/E_100_BC.dx11.dds.dvpl', + ), +).dds(); diff --git a/src/core/streams/primitive.ts b/src/core/streams/primitive.ts index f01e2ea0c..b842c591f 100644 --- a/src/core/streams/primitive.ts +++ b/src/core/streams/primitive.ts @@ -25,11 +25,11 @@ export class PrimitiveStream { return this.consume(Number.POSITIVE_INFINITY); } - consumeByteArray(size: number) { + byte(size: number) { return this.consume(size); } - consumeAscii(size: number) { + ascii(size: number) { return this.consume(size).toString('ascii'); } diff --git a/src/core/streams/sc2.ts b/src/core/streams/sc2.ts index 9949e3b4a..51bc50ae1 100644 --- a/src/core/streams/sc2.ts +++ b/src/core/streams/sc2.ts @@ -177,7 +177,7 @@ interface SceneComponents { export class Sc2Stream extends ScpgStream { header() { return { - name: this.consumeAscii(4), + name: this.ascii(4), version: this.uint32(), nodeCount: this.uint32(), }; diff --git a/src/core/streams/scg.ts b/src/core/streams/scg.ts index 50fc3e240..c9524930f 100644 --- a/src/core/streams/scg.ts +++ b/src/core/streams/scg.ts @@ -49,7 +49,7 @@ export const vertexAttributeVectorSizes = { export class ScgStream extends ScpgStream { header() { return { - name: this.consumeAscii(4), + name: this.ascii(4), version: this.uint32(), nodeCount: this.uint32(), nodeCount2: this.uint32(), diff --git a/src/core/streams/scpg.ts b/src/core/streams/scpg.ts index 342914141..24d6c9a8f 100644 --- a/src/core/streams/scpg.ts +++ b/src/core/streams/scpg.ts @@ -97,13 +97,13 @@ export class ScpgStream extends PrimitiveStream { return stringTable[id]; } else { const length = this.uint32(); - return this.consumeAscii(length); + return this.ascii(length); } } case KAType.BYTE_ARRAY: { const length = this.uint32(); - return this.consumeByteArray(length); + return this.byte(length); } case KAType.FLOAT: @@ -215,7 +215,7 @@ export class ScpgStream extends PrimitiveStream { for (let index = 0; index < count; index++) { const length = this.uint16(); - const string = this.consumeAscii(length); + const string = this.ascii(length); strings.push(string); } diff --git a/src/core/streams/windows.ts b/src/core/streams/windows.ts index 61e1d8fc2..ee5b71146 100644 --- a/src/core/streams/windows.ts +++ b/src/core/streams/windows.ts @@ -1,3 +1,11 @@ import { PrimitiveStream } from './primitive'; -export class WindowsStream extends PrimitiveStream {} +export class WindowsStream extends PrimitiveStream { + dword() { + return this.uint32(); + } + + uint() { + return this.uint32(); + } +}