rw-parser
Version:
Parses RenderWare DFF and TXD files into usable format!
186 lines (185 loc) • 9.02 kB
JavaScript
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.TxdParser = void 0;
var RwFile_1 = require("../RwFile");
var ImageDecoder_1 = require("../utils/ImageDecoder");
var ImageFormatEnums_1 = require("../utils/ImageFormatEnums");
var TxdParser = /** @class */ (function (_super) {
__extends(TxdParser, _super);
function TxdParser(stream) {
return _super.call(this, stream) || this;
}
TxdParser.prototype.parse = function () {
return {
textureDictionary: this.readTextureDictionary(),
};
};
TxdParser.prototype.readTextureDictionary = function () {
this.readSectionHeader();
this.readSectionHeader();
var textureCount = this.readUint16();
this.skip(2);
var textureNatives = [];
for (var i = 0; i < textureCount; i++) {
var textureNative = this.readTextureNative();
textureNatives.push(textureNative);
}
// Skip unused extension
this.skip(this.readSectionHeader().sectionSize);
return { textureCount: textureCount, textureNatives: textureNatives };
};
TxdParser.prototype.readTextureNative = function () {
this.readSectionHeader();
this.readSectionHeader();
// TODO: Structure this part better
// Texture format
var platformId = this.readUint32();
var flags = this.readUint32();
var filterMode = (flags & 0xFF);
var uAddressing = (flags & 0xF00) >> 8;
var vAddressing = (flags & 0xF000) >> 12;
var textureName = this.readString(32);
var maskName = this.readString(32);
// Raster format
var rasterFormat = this.readUint32();
var d3dFormat = this.readString(4);
var width = this.readUint16();
var height = this.readUint16();
var depth = this.readUint8();
var mipmapCount = this.readUint8();
var rasterType = this.readUint8();
var compressionFlags = this.readUint8(); // Is "dxtType" for III/VC
// SA
var alpha = (compressionFlags & (1 << 0)) !== 0;
var cubeTexture = (compressionFlags & (1 << 1)) !== 0;
var autoMipMaps = (compressionFlags & (1 << 2)) !== 0;
var compressed = (compressionFlags & (1 << 3)) !== 0;
var paletteType = (rasterFormat >> 13) & 3;
var mipWidth = width;
var mipHeight = height;
var mipmaps = [];
var palette = (paletteType !== ImageFormatEnums_1.PaletteType.PALETTE_NONE ? this.readPalette(paletteType, depth) : new Uint8Array(0));
for (var i = 0; i < mipmapCount; i++) {
var rasterSize = this.readUint32();
var raster = this.read(rasterSize);
if (i == 0) {
// Raw RGBA presentation
var bitmap = void 0;
if (palette.length !== 0) {
var rasterFormatsWithoutAlpha = [
ImageFormatEnums_1.RasterFormat.RASTER_565,
ImageFormatEnums_1.RasterFormat.RASTER_LUM,
ImageFormatEnums_1.RasterFormat.RASTER_888,
ImageFormatEnums_1.RasterFormat.RASTER_555
];
var hasAlpha = ((platformId === ImageFormatEnums_1.PlatformType.D3D9 && alpha) || (platformId == ImageFormatEnums_1.PlatformType.D3D8 && !rasterFormatsWithoutAlpha.includes(rasterFormat)));
bitmap = Array.from(this.getBitmapWithPalette(paletteType, depth, hasAlpha, raster, palette, width, height));
}
else if (platformId === ImageFormatEnums_1.PlatformType.D3D8 && compressionFlags !== 0) {
bitmap = Array.from(this.getBitmapWithDXT('DXT' + compressionFlags, raster, width, height));
}
else if (platformId === ImageFormatEnums_1.PlatformType.D3D9 && compressed) {
bitmap = Array.from(this.getBitmapWithDXT(d3dFormat, raster, width, height));
}
else {
bitmap = Array.from(this.getBitmapWithRasterFormat(rasterFormat, raster, width, height));
}
mipmaps.push(bitmap);
}
mipWidth /= 2;
mipHeight /= 2;
}
// Skip extension
this.skip(this.readSectionHeader().sectionSize);
return {
platformId: platformId,
filterMode: filterMode,
uAddressing: uAddressing,
vAddressing: vAddressing,
textureName: textureName,
maskName: maskName,
rasterFormat: rasterFormat,
d3dFormat: d3dFormat,
width: width,
height: height,
depth: depth,
mipmapCount: mipmapCount,
rasterType: rasterType,
alpha: alpha,
cubeTexture: cubeTexture,
autoMipMaps: autoMipMaps,
compressed: compressed,
mipmaps: mipmaps,
};
};
TxdParser.prototype.readPalette = function (paletteType, depth) {
var size = (paletteType === ImageFormatEnums_1.PaletteType.PALETTE_8 ? 1024 : (depth === 4 ? 64 : 128));
return this.read(size);
};
TxdParser.prototype.getBitmapWithPalette = function (paletteType, depth, hasAlpha, raster, palette, width, height) {
if (paletteType !== ImageFormatEnums_1.PaletteType.PALETTE_8 && depth == 4) {
return (hasAlpha
? ImageDecoder_1.ImageDecoder.pal4(raster, palette, width, height)
: ImageDecoder_1.ImageDecoder.pal4NoAlpha(raster, palette, width, height));
}
return (hasAlpha
? ImageDecoder_1.ImageDecoder.pal8(raster, palette, width, height)
: ImageDecoder_1.ImageDecoder.pal8NoAlpha(raster, palette, width, height));
};
TxdParser.prototype.getBitmapWithDXT = function (dxtType, raster, width, height) {
switch (dxtType) {
case ImageFormatEnums_1.D3DFormat.D3D_DXT1:
return ImageDecoder_1.ImageDecoder.bc1(raster, width, height);
case ImageFormatEnums_1.D3DFormat.D3D_DXT2:
return ImageDecoder_1.ImageDecoder.bc2(raster, width, height, true);
case ImageFormatEnums_1.D3DFormat.D3D_DXT3:
return ImageDecoder_1.ImageDecoder.bc2(raster, width, height, false);
case ImageFormatEnums_1.D3DFormat.D3D_DXT4:
return ImageDecoder_1.ImageDecoder.bc3(raster, width, height, true);
case ImageFormatEnums_1.D3DFormat.D3D_DXT5:
return ImageDecoder_1.ImageDecoder.bc3(raster, width, height, false);
// LUM8_A8 has compressed flag
case ImageFormatEnums_1.D3DFormat.D3DFMT_A8L8:
return ImageDecoder_1.ImageDecoder.lum8a8(raster, width, height);
default:
return new Uint8Array(0);
}
};
TxdParser.prototype.getBitmapWithRasterFormat = function (rasterFormat, raster, width, height) {
switch (rasterFormat) {
case ImageFormatEnums_1.RasterFormat.RASTER_1555:
return ImageDecoder_1.ImageDecoder.bgra1555(raster, width, height);
case ImageFormatEnums_1.RasterFormat.RASTER_565:
return ImageDecoder_1.ImageDecoder.bgra565(raster, width, height);
case ImageFormatEnums_1.RasterFormat.RASTER_4444:
return ImageDecoder_1.ImageDecoder.bgra4444(raster, width, height);
case ImageFormatEnums_1.RasterFormat.RASTER_LUM:
return ImageDecoder_1.ImageDecoder.lum8(raster, width, height);
case ImageFormatEnums_1.RasterFormat.RASTER_8888:
return ImageDecoder_1.ImageDecoder.bgra8888(raster, width, height);
case ImageFormatEnums_1.RasterFormat.RASTER_888:
return ImageDecoder_1.ImageDecoder.bgra888(raster, width, height);
case ImageFormatEnums_1.RasterFormat.RASTER_555:
return ImageDecoder_1.ImageDecoder.bgra555(raster, width, height);
default:
return new Uint8Array(0);
}
};
return TxdParser;
}(RwFile_1.RwFile));
exports.TxdParser = TxdParser;