Created
February 28, 2024 07:05
-
-
Save pypy-vrc/bd9e3b01c3992fa3d07188951c76d441 to your computer and use it in GitHub Desktop.
riot games tex file converter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @param {Buffer} data | |
* @returns {Buffer} | |
*/ | |
const tex_to_dds = (data) => { | |
if (data.byteLength < 12 || data.subarray(0, 4).toString() !== "TEX\0") { | |
throw new Error("invalid TEX file"); | |
} | |
const width = data.readUInt16LE(4); | |
const height = data.readUInt16LE(6); | |
const format = data.readUInt8(9); | |
const hasMipmaps = data.readUint8(11); | |
const ddspf = Buffer.alloc(32); | |
ddspf.writeUInt32LE(32, 0); | |
switch (format) { | |
case 10: // DXT1 | |
ddspf.writeUInt32LE(0x4, 4); | |
ddspf.write("DXT1", 8); | |
break; | |
case 12: // DXT5 | |
ddspf.writeUInt32LE(0x4, 4); | |
ddspf.write("DXT5", 8); | |
break; | |
case 20: // RGBA8 | |
ddspf.writeUInt32LE(0x41, 4); | |
ddspf.writeUInt32LE(32, 8); | |
ddspf.writeUInt32LE(0x000000ff, 12); | |
ddspf.writeUInt32LE(0x0000ff00, 16); | |
ddspf.writeUInt32LE(0x00ff0000, 20); | |
ddspf.writeUInt32LE(0xff000000, 24); | |
break; | |
default: | |
throw new Error(`unsupported TEX format: ${format}`); | |
} | |
let pixels; | |
if (hasMipmaps) { | |
// Note: only convert the largest mipmap | |
let blockSize = 0; | |
let bytesPerBlock = 0; | |
switch (format) { | |
case 10: // DXT1 | |
blockSize = 4; | |
bytesPerBlock = 8; | |
break; | |
case 12: // DXT5 | |
blockSize = 4; | |
bytesPerBlock = 16; | |
break; | |
case 20: // RGBA8 | |
blockSize = 4; | |
bytesPerBlock = 4; | |
break; | |
} | |
// Find mipmap count | |
// let mipmapCount = 0; | |
// for (let i = Math.max(width, height); i > 0; i >>= 1) { | |
// ++mipmapCount; | |
// } | |
const blockWidth = Math.floor((width + blockSize - 1) / blockSize); | |
const blockheight = Math.floor((height + blockSize - 1) / blockSize); | |
const mipmapSize = bytesPerBlock * blockWidth * blockheight; | |
pixels = data.subarray(-mipmapSize); | |
} else { | |
pixels = data.subarray(12); | |
} | |
const ddsHeader = Buffer.alloc(128); | |
ddsHeader.write("DDS ", 0); | |
ddsHeader.writeUInt32LE(124, 4); | |
ddsHeader.writeUInt32LE(0x1007, 8); | |
ddsHeader.writeUInt32LE(height, 12); | |
ddsHeader.writeUInt32LE(width, 16); | |
ddspf.copy(ddsHeader, 76); | |
ddsHeader.writeUInt32LE(0x1000, 108); | |
return Buffer.concat([ddsHeader, pixels]); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment