From a6ae91dffc27e265478336dba1244db9011564fc Mon Sep 17 00:00:00 2001 From: yellows111 Date: Wed, 21 Feb 2024 01:45:19 +0000 Subject: [PATCH] formatting changes * made lzari.js very es5-friendly. * added jshint (yes, seriously) ruling to icon.js and lzari.js. * Updated README.md * Fixed up the werid mixed syntax on iconwriter.js * -> basically made all the tab-based jank that only showed up correctly in... * n++ a bit more readable outside of such. (minor tab to space consistancy fix) * Added and removed semicolons to match some syntax standards. * Made some things that should of been variables, variables !(global_leakage) * expand module exporting code to clean up some 'object short notation' uses. --- README.md | 25 ++++++++------ icon.js | 78 ++++++++++++++++++++++------------------- lzari.js | 66 +++++++++++++++++------------------ tests/iconwriter.js | 84 +++++++++++++++++++++++---------------------- 4 files changed, 133 insertions(+), 120 deletions(-) diff --git a/README.md b/README.md index 23bd080..3f15ebd 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,11 @@ A set of vertices with may or may not include a texture while defining colours f ## Why? Current implementations had some issues with rendering some icons. These were mostly: -* Not rendering any color for texture type 3. -* Failing to decompress some specific RLE-compressed icons. (types above 8) +* Not rendering any color for texture types 0-3. +* Failing to decompress some specific RLE-compressed icons. (types with bit 4 enabled) * Requires writing/reading a specific format for successful output of data. +* Incorrect analysis of texture types leading to assuming texture type 1 isn't the same group as texture type 3. +* Further incorrect analysis revealing it's that the texture type is a bitmask. As of writing, there was no exporter that exists for the format that exhibited one of these problems. @@ -39,9 +41,9 @@ As of writing, there was no exporter that exists for the format that exhibited o * Use any implementation-specific features. ## Client compatibility: -The library requires use of `const`, `let` and `class` declarations. +The library currently requires use of `const`, `let` and `class` declarations, template literals, and destructuring assignment for variables. -Any JavaScript implementation should work if they support all three of these declarations. +Any JavaScript implementation should work if they support all of the required features. ### Tested clients: * Chrome (or Blink-based browser) 49 (or higher) - HTML reference client @@ -52,13 +54,14 @@ Any JavaScript implementation should work if they support all three of these dec Because it replaced what *was* left of icondumper (1). ## Included files: -| File | Description | -| ---------------- | ----------------------------------------- | -| icon.js | The library itself. | -| index.js | Node.js example client. | -| gltf-exporter.js | Node.js client to export icons to glTF 2. | -| index.htm | HTML reference client. | -| lzari.js | A LZARI decompression-only library. | +| File | Description | +| ------------------- | ----------------------------------------------- | +| icon.js | The library itself. | +| index.js | Node.js example client. | +| gltf-exporter.js | Node.js client to export icons to glTF 2. | +| index.htm | HTML reference client. | +| lzari.js | A LZARI decompression-only library. | +| tests/iconwriter.js | Node.js. Creates icons with texture types 0-31. | ## Included example files: | Directory | Description | Formats | diff --git a/icon.js b/icon.js index ab5a577..72f8a82 100644 --- a/icon.js +++ b/icon.js @@ -1,4 +1,5 @@ //To swap between mjs/esm and c6js, go to the end of this file, and (un)comment your wanted module mode. +/* jshint bitwise: false, esversion: 6, -W009, -W010 */ // not doing this makes linters scream about BWOs, es6 features, and using new Primitive() instead of said primitives var ICONJS_DEBUG = false; var ICONJS_STRICT = true; @@ -7,7 +8,7 @@ var ICONJS_STRICT = true; * @constant {string} * @default */ -const ICONJS_VERSION = "0.8.2"; +const ICONJS_VERSION = "0.8.3"; /** * The RC4 key used for ciphering CodeBreaker Saves. @@ -62,22 +63,22 @@ class yellowDataReader extends DataView { * @param {number} i Indice offset. * @returns {number} */ - u16le(i){return super.getUint16(i, 1)}; + u16le(i){return super.getUint16(i, 1);} /** Fixed-point 16-bit, Little Endian. * @param {number} i Indice offset. * @returns {number} */ - f16le(i){return (super.getInt16(i, 1) / 4096)}; + f16le(i){return (super.getInt16(i, 1) / 4096);} /** Unsigned 32-bit, Little Endian. * @param {number} i Indice offset. * @returns {number} */ - u32le(i){return super.getUint32(i, 1)}; + u32le(i){return super.getUint32(i, 1);} /** Floating-point 32-bit, Little Endian. * @param {number} i Indice offset. * @returns {number} */ - f32le(i){return super.getFloat32(i, 1)}; + f32le(i){return super.getFloat32(i, 1);} /** 64-bit Timestamp structure, Little Endian. * Time returned is set for JST (UTC+09:00) instead of UTC. * Time returned is going to be offseted for JST (GMT+09:00). @@ -97,7 +98,7 @@ class yellowDataReader extends DataView { day: super.getUint8(i+4), month: super.getUint8(i+5), year: super.getUint16(i+6, 1) - }}; + };} constructor(buffer) { super(buffer); return { @@ -106,7 +107,7 @@ class yellowDataReader extends DataView { u32le: this.u32le.bind(this), f32le: this.f32le.bind(this), t64le: this.t64le.bind(this) - } + }; } } @@ -213,7 +214,7 @@ function uncompressTexture(texData) { uncompressed[index] = u16le(offset); for (let indey = 0; indey < currentValue; indey++) { uncompressed[index] = u16le(offset); - index++ + index++; } offset += 2; } @@ -285,13 +286,13 @@ function readPS2D(input) { {x: f32le(80), y: f32le(84), z: f32le(88)}, //:skip 4 {x: f32le(96), y: f32le(100), z: f32le(104)}, //:skip 4 {x: f32le(112), y: f32le(116), z: f32le(120)} //:skip 4 - ] + ]; const lightColors = [ {r: f32le(128), g: f32le(132), b: f32le(136), a: f32le(140)}, {r: f32le(144), g: f32le(148), b: f32le(152), a: f32le(156)}, {r: f32le(160), g: f32le(164), b: f32le(168), a: f32le(172)}, {r: f32le(176), g: f32le(180), b: f32le(184), a: f32le(188)} - ] + ]; // P2SB says color 1 is ambient, 2-4 are for 3-point cameras // official HDD icon.sys files (completely different PS2ICON text-based format) also say the same. const int_title = input.slice(0xc0, 0x100); @@ -317,7 +318,7 @@ function readPS2D(input) { n: stringScrubber((new TextDecoder("utf-8")).decode(int_filename_n)), c: stringScrubber((new TextDecoder("utf-8")).decode(int_filename_c)), d: stringScrubber((new TextDecoder("utf-8")).decode(int_filename_d)) - } + }; if(ICONJS_DEBUG){ console.debug({header, titleOffset, bgAlpha, bgColors, lightIndices, lightColors, title, filenames}); } @@ -339,7 +340,7 @@ function readIconFile(input) { b: ((i & 0xff0000) >> 16), a: (i > 0x7fffffff ? 255 : (((i & 0xff000000) >>> 24) * 2)+1) // I don't think alpha transparency is actually USED in icons?, rendering with it looks strange. - }}; + };}; const magic = u32le(0); if (magic !== 0x010000) { // USER NOTICE: So far, I have yet to parse an icon that hasn't had 0x00010000 as it's magic. @@ -354,7 +355,7 @@ function readIconFile(input) { const textureFormat = getTextureFormat(textureType); //:skip 4 const numberOfVertexes = u32le(16); - if(!!(numberOfVertexes % 3)){ + if((numberOfVertexes % 3) > 0){ throw `Not enough vertices to define a triangle (${numberOfVertexes % 3} vertices remained).`; } // format: [xxyyzzaa * numberOfShapes][xxyyzzaa][uuvvrgba], ((8 * numberOfShapes) + 16) [per chunk] @@ -389,7 +390,7 @@ function readIconFile(input) { vertices.push({shapes, normal, uv, color}); } offset = (20+(numberOfVertexes * chunkLength)); - animationHeader = {id: u32le(offset), length: u32le(offset+4), speed: f32le(offset+8), "offset": u32le(offset+12), keyframes: u32le(offset+16)}; + const animationHeader = {id: u32le(offset), length: u32le(offset+4), speed: f32le(offset+8), "offset": u32le(offset+12), keyframes: u32le(offset+16)}; let animData = new Array(); // now we have to enumerate values, so now we introduce an offset value. // format for a keyframe: sssskkkk[ffffvvvv] where [ffffvvvv] repeat based on the value that kkkk(eys) has. @@ -436,7 +437,7 @@ function readIconFile(input) { //output of this will be another u16[0x4000] of the decompressed texture //after that just parse output as-if it was uncompressed. //see uncompressTexture() and convertBGR5A1toRGB5A1() for more info. - size = u32le(offset); + const size = u32le(offset); texture = {size, data: input.slice(offset+4, offset+(4+size))}; } } @@ -497,7 +498,7 @@ function readEmsPsuFile(input){ let output = new Object(); let offset = 512; for (let index = 0; index < header.size; index++) { - fdesc = readEntryBlock(input.slice(offset, offset + 512)); + const fdesc = readEntryBlock(input.slice(offset, offset + 512)); switch(fdesc.type) { case "directory": { offset += 512; @@ -569,15 +570,21 @@ function readPsvFile(input){ for (let index = 0; index < numberOfFiles; index++) { fileData.push(input.slice(offset,offset+0x3c)); offset += 0x3c; - }; + } //then file data after this but we already have pointers to the files we care about const icons = { n: input.slice(nModelOffset, nModelOffset+nModelSize), c: input.slice(cModelOffset, cModelOffset+cModelSize), d: input.slice(dModelOffset, dModelOffset+dModelSize), - } + }; if (ICONJS_DEBUG) { - console.debug({magic, type1, type2, displayedSize, ps2dOffset, ps2dSize, nModelOffset, nModelSize, cModelOffset, cModelSize, dModelOffset, dModelSize, numberOfFiles, rootDirectoryData, fileData}) + console.debug({magic, type1, type2, displayedSize, + ps2dOffset, ps2dSize, + nModelOffset, nModelSize, + cModelOffset, cModelSize, + dModelOffset, dModelSize, + numberOfFiles, rootDirectoryData, fileData + }); } return {icons, "icon.sys": input.slice(ps2dOffset, ps2dOffset+ps2dSize), timestamps}; } @@ -660,11 +667,11 @@ function readSharkXPortSxpsFile(input) { const comments = { "game": stringScrubber((new TextDecoder("utf-8")).decode(title)), "name": stringScrubber((new TextDecoder("utf-8")).decode(description)) - } + }; if(description2Length !== 0) { comments.desc = stringScrubber((new TextDecoder("utf-8")).decode(description2)); } - const totalSize = u32le(offset); + //const totalSize = u32le(offset); has data, unused in script offset += 4; const header = readSxpsDescriptor(input.slice(offset, offset + 250)); offset += 250; @@ -672,7 +679,7 @@ function readSharkXPortSxpsFile(input) { let fsOut = {length: header.size, rootDirectory: header.filename, timestamps: header.timestamps, comments}; let output = new Object(); for (let index = 0; index < (header.size - 2); index++) { - fdesc = readSxpsDescriptor(input.slice(offset, offset + 250)); + const fdesc = readSxpsDescriptor(input.slice(offset, offset + 250)); switch(fdesc.type) { case "directory": { offset += 250; @@ -731,7 +738,7 @@ function readCodeBreakerCbsDirectory(input) { */ function readCodeBreakerCbsFile(input, inflator = null) { if(typeof inflator !== "function") { - throw `No inflator function passed. Skipping.`; + throw "No inflator function passed. Skipping."; } const {u32le, t64le} = new yellowDataReader(input); const magic = u32le(0); @@ -773,13 +780,13 @@ function readCodeBreakerCbsFile(input, inflator = null) { */ function readMaxPwsDirectory(input, directorySize) { const {u32le} = new yellowDataReader(input); - virtualFilesystem = new Object(); + const virtualFilesystem = new Object(); let offset = 0; for (let index = 0; index < directorySize; index++) { const dataSize = u32le(offset); const _filename = input.slice(offset+4, offset+36); const filename = stringScrubber((new TextDecoder("utf-8")).decode(_filename)); - if(filename === "") { throw `Unexpected null filename at byte ${offset+4}.`; }; + if(filename === "") { throw `Unexpected null filename at byte ${offset+4}.`; } offset += 36; const data = input.slice(offset, offset+dataSize); offset += dataSize; @@ -802,12 +809,12 @@ function readMaxPwsDirectory(input, directorySize) { */ function readMaxPwsFile(input, unlzari) { if(typeof unlzari !== "function") { - throw `No decompresser function passed. Skipping.`; + throw "No decompresser function passed. Skipping."; } const {u32le} = new yellowDataReader(input); const ident = input.slice(0, 12); if((new TextDecoder("utf-8")).decode(ident) !== "Ps2PowerSave") { - throw `Unrecognized file identification string. Expected "Ps2PowerSave".`; + throw "Unrecognized file identification string. Expected \"Ps2PowerSave\"."; } //:skip 4 (u32 checksum) const _dirName = input.slice(0x10, 0x30); @@ -834,21 +841,22 @@ function readMaxPwsFile(input, unlzari) { /** * Define (module.)exports with all public functions. * @exports icondumper2/icon - */ // start c6js + */ // start c6js# +/* globals exports: true */ if(typeof exports !== "object") { exports = { - readers: {readIconFile, readPS2D, readEmsPsuFile, readPsvFile, readSharkXPortSxpsFile, readCodeBreakerCbsFile, readMaxPwsFile}, - helpers: {uncompressTexture, convertBGR5A1toRGB5A1}, - options: {setDebug, setStrictness}, + readers: {"readIconFile": readIconFile, "readPS2D": readPS2D, "readEmsPsuFile": readEmsPsuFile, "readPsvFile": readPsvFile, "readSharkXPortSxpsFile": readSharkXPortSxpsFile, "readCodeBreakerCbsFile": readCodeBreakerCbsFile, "readMaxPwsFile": readMaxPwsFile}, + helpers: {"uncompressTexture": uncompressTexture, "convertBGR5A1toRGB5A1": convertBGR5A1toRGB5A1}, + options: {"setDebug": setDebug, "setStrictness": setStrictness}, version: ICONJS_VERSION }; } else { - exports.readers = {readIconFile, readPS2D, readEmsPsuFile, readPsvFile, readSharkXPortSxpsFile, readCodeBreakerCbsFile, readMaxPwsFile}; - exports.helpers = {uncompressTexture, convertBGR5A1toRGB5A1}; - exports.options = {setDebug, setStrictness}; + exports.readers = {"readIconFile": readIconFile, "readPS2D": readPS2D, "readEmsPsuFile": readEmsPsuFile, "readPsvFile": readPsvFile, "readSharkXPortSxpsFile": readSharkXPortSxpsFile, "readCodeBreakerCbsFile": readCodeBreakerCbsFile, "readMaxPwsFile": readMaxPwsFile}; + exports.helpers = {"uncompressTexture": uncompressTexture, "convertBGR5A1toRGB5A1": convertBGR5A1toRGB5A1}; + exports.options = {"setDebug": setDebug, "setStrictness": setStrictness}; exports.version = ICONJS_VERSION; } - +/* globals module: true */ if(typeof module !== "undefined") { module.exports = exports; } diff --git a/lzari.js b/lzari.js index 1adb47a..040bb44 100644 --- a/lzari.js +++ b/lzari.js @@ -24,7 +24,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. **/ - +/* jshint bitwise: false */ // not doing this makes linters scream about BWOs //TODO: privatize variables and document the library var inputData = null; @@ -43,7 +43,7 @@ var bit_Mask = 0; function GetBit() { //partial xgetc modification - if(inputLocation >= inputData.length) {return -1}; + if(inputLocation >= inputData.length) {return -1;} if((bit_Mask >>= 1) === 0) { bit_Buffer = inputData[inputLocation++]; bit_Mask = 128; @@ -52,10 +52,10 @@ function GetBit() { } function BinarySearchSym(x) { - let i = 1; - let j = 314; + var i = 1; + var j = 314; while (i < j) { - let k = ((i + j) / 2)|0; + var k = ((i + j) / 2)|0; if (symbolCumulative[k] > x) { i = k + 1; } else { @@ -66,10 +66,10 @@ function BinarySearchSym(x) { } function BinarySearchPos(x) { - let i = 1; - let j = 4096; + var i = 1; + var j = 4096; while (i < j) { - let k = ((i + j) / 2)|0; + var k = ((i + j) / 2)|0; if (positionCumulative[k] > x) { i = k + 1; } else { @@ -93,28 +93,28 @@ function DecodeChar() { value -= 32768; low -= 32768; high -= 32768; - } else if (high > 65536) { break }; + } else if (high > 65536) { break; } low += low; high += high; value = 2 * value + GetBit(); } //transcluded UpdateModel - let character = symbolToCharacter[sym]; + var character = symbolToCharacter[sym]; // do not remove above, will be overwritten otherwise! - let i; + var i; if(symbolCumulative[0] >= 32767) { - let chr = 0; + var chr = 0; for (i = 314; i > 0; i--) { symbolCumulative[i] = chr; chr += (symbolFrequency[i] = (symbolFrequency[i] + 1) >> 1); } symbolCumulative[0] = chr; } - for(i = sym; symbolFrequency[i] === symbolFrequency[i - 1]; i--) {}; + for(i = sym; symbolFrequency[i] === symbolFrequency[i - 1]; i--) {} if (i < sym) { - let ch_i = symbolToCharacter[i]; - let ch_sym = symbolToCharacter[sym]; + var ch_i = symbolToCharacter[i]; + var ch_sym = symbolToCharacter[sym]; symbolToCharacter[i] = ch_sym; symbolToCharacter[sym] = ch_i; characterToSymbol[ch_i] = sym; @@ -144,7 +144,7 @@ function DecodePosition() { value -= 32768; low -= 32768; high -= 32768; - } else if (high > 65536) { break }; + } else if (high > 65536) { break; } low += low; high += high; value = 2 * value + GetBit(); @@ -178,23 +178,22 @@ function decodeLzari(input) { inputData = input; inputLocation = 4; - let dataSize = new DataView(input.buffer).getInt32(0,1); + var dataSize = new DataView(input.buffer).getInt32(0,1); if (dataSize == 0) return(0); if (dataSize < 0) return(-1); - let outputLength = dataSize; - let outputData = new Uint8Array(dataSize); - let outputLocation = 0; + var outputData = new Uint8Array(dataSize); + var outputLocation = 0; //transcluded StartDecode - for (let i = 0; i < 17; i++) { + for (var i = 0; i < 17; i++) { value = 2 * value + GetBit(); } //transcluded StartModel symbolCumulative[314] = 0; - for (let sym = 314; sym >= 1; sym--) { - let ch = sym - 1; + for (var sym = 314; sym >= 1; sym--) { + var ch = sym - 1; characterToSymbol[ch] = sym; symbolToCharacter[sym] = ch; symbolFrequency[sym] = 1; @@ -202,29 +201,29 @@ function decodeLzari(input) { } symbolFrequency[0] = 0; positionCumulative[4096] = 0; - for (let i = 4096; i >= 1; i--) { + for (i = 4096; i >= 1; i--) { // redefine i positionCumulative[i - 1] = (positionCumulative[i] + (10000 / (i + 200))|0); } //end transclusion //normal Decode process - for (let i = 0; i < 4036; i++) { + for (i = 0; i < 4036; i++) { // redefine i text_buffer[i] = 32; } var r = 4036; - for (let count = 0; count < dataSize; ) { - if(inputLocation >= inputData.length) {break}; - let c = DecodeChar(); + for (var count = 0; count < dataSize; ) { + if(inputLocation >= inputData.length) {break;} + var c = DecodeChar(); if (c < 256) { outputData[outputLocation++] = c; text_buffer[r++] = c; r &= (4095); count++; } else { - let i = (r - DecodePosition() - 1) & 4095; - let j = c - 253; - for (let k = 0; k < j; k++) { + i = (r - DecodePosition() - 1) & 4095; // redefine i + var j = c - 253; + for (var k = 0; k < j; k++) { c = text_buffer[(i + k) & 4095]; outputData[outputLocation++] = c; text_buffer[r++] = c; @@ -241,14 +240,15 @@ function decodeLzari(input) { * Define (module.)exports with all public functions. * @exports icondumper2/lzari */ // start c6js +/* globals exports: true */ if(typeof exports !== "object") { exports = { - decodeLzari + "decodeLzari": decodeLzari }; } else { exports.decodeLzari = decodeLzari; } - +/* globals module: true */ if(typeof module !== "undefined") { module.exports = exports; } diff --git a/tests/iconwriter.js b/tests/iconwriter.js index 40418e3..cf63285 100644 --- a/tests/iconwriter.js +++ b/tests/iconwriter.js @@ -174,24 +174,25 @@ const animData = new Uint8Array([ 0x00, 0x00, 0x00, 0x00 ]); // 36 bytes -/** generate texture data (RAW: fill with red) **/ const texture_ = new Uint16Array(16384); -for (let indice = 0; indice < 16384; indice++) { - texture_[indice] = 0b1_00000_00000_11111; //A1BGR5 -} // 32768 bytes /** for compressed textures (RLE: fill with blue) **/ texture_[0] = 0x0004; texture_[1] = 0x0000; texture_[2] = 0x4000; -texture_[3] = 0b1_11111_00000_00000; +texture_[3] = 0b1_11111_00000_00000; // 16 bytes + +/** generate texture data (RAW: fill with red) **/ +for (let indice = 4; indice < 16384; indice++) { + texture_[indice] = 0b1_00000_00000_11111; //A1BGR5 +} // 32768 bytes const textureData = new Uint8Array(texture_.buffer); /** ps2d data **/ const metadataSkeleton = new Uint8Array(Array.from({...[ - 0x50, 0x53, 0x32, 0x44, 0x00, 0x00, + 0x50, 0x53, 0x32, 0x44, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, // PS2D files have a max limit of 16 characters per line - 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, // color1.rgba 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -226,41 +227,41 @@ const metadataSkeleton = new Uint8Array(Array.from({...[ 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, // title - 0x82, 0x89, 0x82, 0x83, 0x82, 0x8f, 0x82, 0x8e, // icon - 0x82, 0x84, 0x82, 0x95, 0x82, 0x8d, 0x82, 0x90, // dump - 0x82, 0x85, 0x82, 0x92, 0x82, 0x51, 0x81, 0x40, // er2 - 0x82, 0x73, 0x82, 0x85, 0x82, 0x93, 0x82, 0x94, // Test - 0x82, 0x73, 0x82, 0x85, 0x82, 0x98, 0x82, 0x94, // Text + 0x82, 0x89, 0x82, 0x83, 0x82, 0x8f, 0x82, 0x8e, // icon + 0x82, 0x84, 0x82, 0x95, 0x82, 0x8d, 0x82, 0x90, // dump + 0x82, 0x85, 0x82, 0x92, 0x82, 0x51, 0x81, 0x40, // er2 + 0x82, 0x73, 0x82, 0x85, 0x82, 0x93, 0x82, 0x94, // Test + 0x82, 0x73, 0x82, 0x85, 0x82, 0x98, 0x82, 0x94, // Text 0x82, 0x95, 0x82, 0x92, 0x82, 0x85, 0x81, 0x40, // ure - 0x82, 0x73, 0x82, 0x99, 0x82, 0x90, 0x82, 0x85, // Type - 0x81, 0x40, 0x82, 0x58, // 9 + 0x82, 0x73, 0x82, 0x99, 0x82, 0x90, 0x82, 0x85, // Type + 0x81, 0x40, 0x82, 0x58, // 9 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // file - normal - 0x74, 0x65, 0x78, 0x74, 0x79, 0x70, 0x65, 0x31, - 0x2E, 0x69, 0x63, 0x6E, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x74, 0x65, 0x78, 0x74, 0x79, 0x70, 0x65, 0x31, + 0x2E, 0x69, 0x63, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // file - copying - 0x74, 0x65, 0x78, 0x74, 0x79, 0x70, 0x65, 0x31, - 0x2E, 0x69, 0x63, 0x6E, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x74, 0x65, 0x78, 0x74, 0x79, 0x70, 0x65, 0x31, + 0x2E, 0x69, 0x63, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // file - deleting - 0x74, 0x65, 0x78, 0x74, 0x79, 0x70, 0x65, 0x31, - 0x2E, 0x69, 0x63, 0x6E, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x74, 0x65, 0x78, 0x74, 0x79, 0x70, 0x65, 0x31, + 0x2E, 0x69, 0x63, 0x6E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //], length:964})); ], length:1024})); // psu want block size @@ -271,6 +272,7 @@ CombinedIconData.set(iconData, 20); CombinedIconData.set(animData, 20+864); CombinedIconData.set(textureData, 20+864+36); +// to be honest all of this could just be a generator /** root directory **/ const psuHeader1 = new Uint8Array(Array.from({...[ 0x27, 0x84, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, @@ -321,7 +323,7 @@ const psuHeader4 = new Uint8Array(Array.from({...[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x69, 0x63, 0x6f, 0x6e, 0x2e, 0x73, 0x79, 0x73 + 0x69, 0x63, 0x6f, 0x6e, 0x2e, 0x73, 0x79, 0x73 ], length:512})); /** textypeX.icn **/ @@ -334,7 +336,7 @@ const psuHeader5 = new Uint8Array(Array.from({...[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x74, 0x65, 0x78, 0x74, 0x79, 0x70, 0x65, 0x39, + 0x74, 0x65, 0x78, 0x74, 0x79, 0x70, 0x65, 0x39, 0x2E, 0x69, 0x63, 0x6E ], length:512})); @@ -344,10 +346,10 @@ for (let iconIndice = 0; iconIndice < 32; iconIndice++) { // realistically only if(iconIndice > 9) { needsAlpha = 7; // if we're past 9, offset to start at A instead } - const PsuFileOutput = new Uint8Array(37888); // 37 uncompressed blocks - CombinedIconData[8] = iconIndice; // set texture type - psuHeader1[75] = 0x30 + iconIndice+needsAlpha; // set folder name - psuHeader5[71] = 0x30 + iconIndice+needsAlpha; // set file name + const PsuFileOutput = new Uint8Array(37888);// 37 uncompressed blocks + CombinedIconData[8] = iconIndice; // set texture type + psuHeader1[75] = 0x30 + iconIndice+needsAlpha; // set folder name + psuHeader5[71] = 0x30 + iconIndice+needsAlpha; // set file name metadataSkeleton[251] = 0x4f + iconIndice+needsAlpha; // set display name metadataSkeleton[267] = 0x30 + iconIndice+needsAlpha; // set normal file name metadataSkeleton[331] = 0x30 + iconIndice+needsAlpha; // set copy file name