mkjs/code/formats/.sublaf1.tmp

158 lines
4.9 KiB
Plaintext

//
// nsbtx.js
//--------------------
// Reads NSBTX files (or TEX0 sections) and provides canvases containing decoded texture data.
// by RHY3756547
//
// includes: gl-matrix.js (glMatrix 2.0)
// /formats/nitro.js
//
window.nsbtx = function(input, tex0, autogen) {
var texDataSize, texInfoOff, texOffset, compTexSize, compTexInfoOff,
compTexOffset, compTexInfoDataOff /*wtf*/, palSize, palInfoOff,
palOffset, mainOff
var textureInfo, paletteInfo, palData, texData, colourBuffer
var thisObj = this;
var bitDepths = [0, 8, 2, 4, 8, 2, 8, 16]
if (input != null) {
load(input, tex0, autogen);
}
this.load = load;
this.readTexWithPal = readTexWithPal;
this.scopeEval = function(code) {return eval(code)} //for debug purposes
function load(input, tex0, autogen) {
var colourBuffer = new Uint32Array(4);
var view = new DataView(input);
var header = null;
var offset = 0;
if (!tex0) { //nitro 3d header
header = nitro.readHeader(view);
if (header.stamp != "BTX0") throw "NSBTX invalid. Expected BTX0, found "+header.stamp;
if (header.numSections > 1) throw "NSBTX invalid. Too many sections - should only have one.";
offset = header.sectionOffsets[0];
}
mainOff = offset;
var stamp = readChar(view, offset+0x0)+readChar(view, offset+0x1)+readChar(view, offset+0x2)+readChar(view, offset+0x3);
if (stamp != "TEX0") throw "NSBTX invalid. Expected TEX0, found "+stamp;
var size = view.getUint32(offset+0x04, true);
var texDataSize = view.getUint16(offset+0x0C, true)<<8;
var texInfoOff = view.getUint16(offset+0x0E, true);
var texOffset = view.getUint16(offset+0x14, true);
var compTexSize = view.getUint16(offset+0x1C, true)<<8;
var compTexInfoOff = view.getUint16(offset+0x1E, true);
var compTexOffset = view.getUint32(offset+0x24, true);
var compTexInfoDataOff = view.getUint32(offset+0x28, true);
var palSize = view.getUint32(offset+0x30, true)<<3;
var palInfoOff = view.getUint32(offset+0x34, true);
var palOffset = view.getUint32(offset+0x38, true);
//read palletes, then textures.
palData = input.slice(mainOff + palOffset, palSize);
texData = input.slice(mainOff + texOffset, texDataSize);
paletteInfo = nitro.read3dInfo(view, palInfoOff, palInfoHandler);
textureInfo = nitro.read3dInfo(view, texInfoOff, texInfoHandler);
if (false) {
console.log(textureInfo.objectData.length)
for (var i=0; i<textureInfo.objectData.length; i++) {
var canvas = readTexWithPal(i, textureInfo.objectData[i].pal)
document.body.appendChild(canvas);
console.log("uh")
}
}
}
function readTexWithPal(textureId, palId) {
palView = new DataView(palData);
texView = new DataView(texData);
var tex = textureInfo.objectData[textureId];
var pal = paletteInfo.objectData[palId];
var bit = bitDepths[pal.format]; //todo, compressed format whatever that is
var canvas = document.createElement("canvas");
canvas.width = tex.width;
canvas.height = tex.height;
var ctx = canvas.getContext("2d");
var data = ctx.getImageData(0, 0, tex.width, tex.height);
var off = tex.texOffset
var palOff = pal.palOffset;
var total = tex.width*tex.height;
var databuf = texView.readUint8(off);
for (var i=0; i<total; i++) {
var col;
if (bitDepths == 2) {
col = readPalColour(palView, palOff, (databuf>>((i%4)*2))&3)
if (i%4 == 3) databuf = texView.readUint8(++off);
} else if (bitDepths == 4) {
if (i%2 == 0) {
col = readPalColour(palView, palOff, databuf&15)
} else {
col = readPalColour(palView, palOff, databuf>>4)
databuf = texView.readUint8(++off);
}
} else if (bitDepths == 8) {
col = readPalColour(palView, palOff, texView.readUint8(off))
off += 1;
} else if (bitDepths == 16) {
col = readPalColour(palView, palOff, texView.readUint16(off, true))
off += 2;
}
data.data.set(col, i*4);
}
return canvas;
}
function readPalColour(view, palOff, ind) {
var col = palView.getUint16(palOff+ind*2, true);
colourBuffer[0] = Math.round(((col&31)/31)*255)
colourBuffer[1] = Math.round((((col>>5)&31)/31)*255)
colourBuffer[2] = Math.round((((col>>10)&31)/31)*255)
colourBuffer[3] = Math.round((col>>15)*255)
}
function palInfoHandler(view, offset) {
var palOffset = view.getUint16(offset, true)<<3;
var unknown = view.getUint16(offset+2, true);
return {
palOffset: palOffset,
nextoff: offset+4
}
}
function texInfoHandler(view, offset) {
var texOffset = view.getUint16(offset, true)<<3;
var flags = view.getUint16(offset+2, true);
var width2 = view.getUint8(offset+4, true);
var unknown = view.getUint8(offset+5, true);
var height2 = view.getUint8(offset+6, true);
var unknown2 = view.getUint8(offset+7, true);
return {
texOffset: texOffset,
pal: (flags>>13),
format: ((flags>>10)&7),
height: ((flags>>7)&7)<<3,
width: ((flags>>4)&7)<<3,
nextoff: offset+8
}
}
function readChar(view, offset) {
return String.fromCharCode(view.getUint8(offset));
}
}