Files
healer-man/scripts/dungeon-pipeline/lib/wow-adt-terrain-audit.test.mjs
T
2026-10-07 13:05:04 -04:00

86 lines
3.3 KiB
JavaScript

import test from "node:test";
import assert from "node:assert/strict";
import { parseWowAdtTerrain } from "./wow-adt-terrain-audit.mjs";
import { decodeWowAdtAlphaMap } from "./wow-adt-terrain-material.mjs";
function chunk(name, payload) {
const header = Buffer.alloc(8);
Buffer.from(name, "ascii").reverse().copy(header);
header.writeUInt32LE(payload.length, 4);
return Buffer.concat([header, payload]);
}
function rleFill(value) {
const bytes = [];
let remaining = 4096;
while (remaining) {
const count = Math.min(127, remaining);
bytes.push(0x80 | count, value);
remaining -= count;
}
return Buffer.from(bytes);
}
function zeroSizedMcalAdt({ declaredPayloadBytes = null } = {}) {
const mtex = Buffer.from("Base.blp\0Overlay.blp\0", "utf8");
const layers = Buffer.alloc(32);
layers.writeUInt32LE(0, 0);
layers.writeUInt32LE(0, 4);
layers.writeUInt32LE(1, 16);
layers.writeUInt32LE(0x300, 20);
layers.writeUInt32LE(0, 24);
const alpha = rleFill(91);
const payloadLength = declaredPayloadBytes ?? alpha.length;
const alphaSubchunk = Buffer.alloc(8 + alpha.length);
Buffer.from("MCAL", "ascii").reverse().copy(alphaSubchunk);
alphaSubchunk.writeUInt32LE(0, 4);
alpha.copy(alphaSubchunk, 8);
const mcnkHeader = Buffer.alloc(128);
mcnkHeader.writeUInt32LE(0, 4);
mcnkHeader.writeUInt32LE(0, 8);
mcnkHeader.writeUInt32LE(2, 12);
mcnkHeader.writeUInt32LE(136, 28);
mcnkHeader.writeUInt32LE(176, 36);
mcnkHeader.writeUInt32LE(8 + payloadLength, 40);
mcnkHeader.writeUInt16LE(0xa55a, 60);
mcnkHeader.writeUInt16LE(0x1234, 62);
mcnkHeader.writeUInt16LE(0xabcd, 64);
const mcnk = Buffer.concat([mcnkHeader, chunk("MCLY", layers), alphaSubchunk]);
const mver = Buffer.alloc(4);
mver.writeUInt32LE(18);
return Buffer.concat([chunk("MVER", mver), chunk("MTEX", mtex), chunk("MCNK", mcnk)]);
}
test("MVER 18 zero-sized MCAL headers use the enclosing MCNK size span", () => {
const source = zeroSizedMcalAdt();
const parsed = parseWowAdtTerrain(source, { label: "zero-sized MCAL fixture" });
const target = parsed.chunks[0];
const overlay = target.layers[1];
assert.equal(target.alphaChunkHeaderSize, 0);
assert.equal(target.alphaChunkSizeSource, "mcnk-header");
assert.equal(target.holeMask, 0xa55a);
assert.equal(target.highResolutionHoles, false);
assert.equal(target.lowResolutionTextureMap[0], 0xabcd);
assert.equal(target.alphaSizeMatchesHeader, true);
assert.equal(target.alphaChunkWithinMcnk, true);
assert.equal(overlay.alphaMapEncoding, "rle-8");
assert.equal(overlay.alphaMapAvailable, true);
assert.equal(overlay.alphaMapBytes, target.alphaBytes);
const decoded = decodeWowAdtAlphaMap(source, target, overlay);
assert.equal(decoded.length, 4096);
assert.equal(decoded[0], 91);
assert.equal(decoded[4095], 91);
});
test("MVER 18 MCAL spans still fail closed when the declared payload leaves MCNK", () => {
const source = zeroSizedMcalAdt({ declaredPayloadBytes: 0xffff });
const parsed = parseWowAdtTerrain(source, { label: "overrun MCAL fixture" });
const target = parsed.chunks[0];
assert.equal(target.alphaChunkWithinMcnk, false);
assert.equal(target.layers[1].alphaMapAvailable, false);
assert.throws(() => decodeWowAdtAlphaMap(source, target, target.layers[1]), /unsupported or invalid MCAL span/);
});