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.
This commit is contained in:
parent
8ab26610e6
commit
a6ae91dffc
13
README.md
13
README.md
|
@ -6,9 +6,11 @@ A set of vertices with may or may not include a texture while defining colours f
|
||||||
|
|
||||||
## Why?
|
## Why?
|
||||||
Current implementations had some issues with rendering some icons. These were mostly:
|
Current implementations had some issues with rendering some icons. These were mostly:
|
||||||
* Not rendering any color for texture type 3.
|
* Not rendering any color for texture types 0-3.
|
||||||
* Failing to decompress some specific RLE-compressed icons. (types above 8)
|
* Failing to decompress some specific RLE-compressed icons. (types with bit 4 enabled)
|
||||||
* Requires writing/reading a specific format for successful output of data.
|
* 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.
|
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.
|
* Use any implementation-specific features.
|
||||||
|
|
||||||
## Client compatibility:
|
## 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:
|
### Tested clients:
|
||||||
* Chrome (or Blink-based browser) 49 (or higher) - HTML reference client
|
* Chrome (or Blink-based browser) 49 (or higher) - HTML reference client
|
||||||
|
@ -53,12 +55,13 @@ Because it replaced what *was* left of icondumper (1).
|
||||||
|
|
||||||
## Included files:
|
## Included files:
|
||||||
| File | Description |
|
| File | Description |
|
||||||
| ---------------- | ----------------------------------------- |
|
| ------------------- | ----------------------------------------------- |
|
||||||
| icon.js | The library itself. |
|
| icon.js | The library itself. |
|
||||||
| index.js | Node.js example client. |
|
| index.js | Node.js example client. |
|
||||||
| gltf-exporter.js | Node.js client to export icons to glTF 2. |
|
| gltf-exporter.js | Node.js client to export icons to glTF 2. |
|
||||||
| index.htm | HTML reference client. |
|
| index.htm | HTML reference client. |
|
||||||
| lzari.js | A LZARI decompression-only library. |
|
| lzari.js | A LZARI decompression-only library. |
|
||||||
|
| tests/iconwriter.js | Node.js. Creates icons with texture types 0-31. |
|
||||||
|
|
||||||
## Included example files:
|
## Included example files:
|
||||||
| Directory | Description | Formats |
|
| Directory | Description | Formats |
|
||||||
|
|
78
icon.js
78
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.
|
//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_DEBUG = false;
|
||||||
var ICONJS_STRICT = true;
|
var ICONJS_STRICT = true;
|
||||||
|
|
||||||
|
@ -7,7 +8,7 @@ var ICONJS_STRICT = true;
|
||||||
* @constant {string}
|
* @constant {string}
|
||||||
* @default
|
* @default
|
||||||
*/
|
*/
|
||||||
const ICONJS_VERSION = "0.8.2";
|
const ICONJS_VERSION = "0.8.3";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The RC4 key used for ciphering CodeBreaker Saves.
|
* The RC4 key used for ciphering CodeBreaker Saves.
|
||||||
|
@ -62,22 +63,22 @@ class yellowDataReader extends DataView {
|
||||||
* @param {number} i Indice offset.
|
* @param {number} i Indice offset.
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
u16le(i){return super.getUint16(i, 1)};
|
u16le(i){return super.getUint16(i, 1);}
|
||||||
/** Fixed-point 16-bit, Little Endian.
|
/** Fixed-point 16-bit, Little Endian.
|
||||||
* @param {number} i Indice offset.
|
* @param {number} i Indice offset.
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
f16le(i){return (super.getInt16(i, 1) / 4096)};
|
f16le(i){return (super.getInt16(i, 1) / 4096);}
|
||||||
/** Unsigned 32-bit, Little Endian.
|
/** Unsigned 32-bit, Little Endian.
|
||||||
* @param {number} i Indice offset.
|
* @param {number} i Indice offset.
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
u32le(i){return super.getUint32(i, 1)};
|
u32le(i){return super.getUint32(i, 1);}
|
||||||
/** Floating-point 32-bit, Little Endian.
|
/** Floating-point 32-bit, Little Endian.
|
||||||
* @param {number} i Indice offset.
|
* @param {number} i Indice offset.
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
f32le(i){return super.getFloat32(i, 1)};
|
f32le(i){return super.getFloat32(i, 1);}
|
||||||
/** 64-bit Timestamp structure, Little Endian.
|
/** 64-bit Timestamp structure, Little Endian.
|
||||||
* Time returned is set for JST (UTC+09:00) instead of UTC.
|
* Time returned is set for JST (UTC+09:00) instead of UTC.
|
||||||
* Time returned is going to be offseted for JST (GMT+09:00).
|
* 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),
|
day: super.getUint8(i+4),
|
||||||
month: super.getUint8(i+5),
|
month: super.getUint8(i+5),
|
||||||
year: super.getUint16(i+6, 1)
|
year: super.getUint16(i+6, 1)
|
||||||
}};
|
};}
|
||||||
constructor(buffer) {
|
constructor(buffer) {
|
||||||
super(buffer);
|
super(buffer);
|
||||||
return {
|
return {
|
||||||
|
@ -106,7 +107,7 @@ class yellowDataReader extends DataView {
|
||||||
u32le: this.u32le.bind(this),
|
u32le: this.u32le.bind(this),
|
||||||
f32le: this.f32le.bind(this),
|
f32le: this.f32le.bind(this),
|
||||||
t64le: this.t64le.bind(this)
|
t64le: this.t64le.bind(this)
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,7 +214,7 @@ function uncompressTexture(texData) {
|
||||||
uncompressed[index] = u16le(offset);
|
uncompressed[index] = u16le(offset);
|
||||||
for (let indey = 0; indey < currentValue; indey++) {
|
for (let indey = 0; indey < currentValue; indey++) {
|
||||||
uncompressed[index] = u16le(offset);
|
uncompressed[index] = u16le(offset);
|
||||||
index++
|
index++;
|
||||||
}
|
}
|
||||||
offset += 2;
|
offset += 2;
|
||||||
}
|
}
|
||||||
|
@ -285,13 +286,13 @@ function readPS2D(input) {
|
||||||
{x: f32le(80), y: f32le(84), z: f32le(88)}, //:skip 4
|
{x: f32le(80), y: f32le(84), z: f32le(88)}, //:skip 4
|
||||||
{x: f32le(96), y: f32le(100), z: f32le(104)}, //:skip 4
|
{x: f32le(96), y: f32le(100), z: f32le(104)}, //:skip 4
|
||||||
{x: f32le(112), y: f32le(116), z: f32le(120)} //:skip 4
|
{x: f32le(112), y: f32le(116), z: f32le(120)} //:skip 4
|
||||||
]
|
];
|
||||||
const lightColors = [
|
const lightColors = [
|
||||||
{r: f32le(128), g: f32le(132), b: f32le(136), a: f32le(140)},
|
{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(144), g: f32le(148), b: f32le(152), a: f32le(156)},
|
||||||
{r: f32le(160), g: f32le(164), b: f32le(168), a: f32le(172)},
|
{r: f32le(160), g: f32le(164), b: f32le(168), a: f32le(172)},
|
||||||
{r: f32le(176), g: f32le(180), b: f32le(184), a: f32le(188)}
|
{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
|
// 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.
|
// official HDD icon.sys files (completely different PS2ICON text-based format) also say the same.
|
||||||
const int_title = input.slice(0xc0, 0x100);
|
const int_title = input.slice(0xc0, 0x100);
|
||||||
|
@ -317,7 +318,7 @@ function readPS2D(input) {
|
||||||
n: stringScrubber((new TextDecoder("utf-8")).decode(int_filename_n)),
|
n: stringScrubber((new TextDecoder("utf-8")).decode(int_filename_n)),
|
||||||
c: stringScrubber((new TextDecoder("utf-8")).decode(int_filename_c)),
|
c: stringScrubber((new TextDecoder("utf-8")).decode(int_filename_c)),
|
||||||
d: stringScrubber((new TextDecoder("utf-8")).decode(int_filename_d))
|
d: stringScrubber((new TextDecoder("utf-8")).decode(int_filename_d))
|
||||||
}
|
};
|
||||||
if(ICONJS_DEBUG){
|
if(ICONJS_DEBUG){
|
||||||
console.debug({header, titleOffset, bgAlpha, bgColors, lightIndices, lightColors, title, filenames});
|
console.debug({header, titleOffset, bgAlpha, bgColors, lightIndices, lightColors, title, filenames});
|
||||||
}
|
}
|
||||||
|
@ -339,7 +340,7 @@ function readIconFile(input) {
|
||||||
b: ((i & 0xff0000) >> 16),
|
b: ((i & 0xff0000) >> 16),
|
||||||
a: (i > 0x7fffffff ? 255 : (((i & 0xff000000) >>> 24) * 2)+1)
|
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.
|
// I don't think alpha transparency is actually USED in icons?, rendering with it looks strange.
|
||||||
}};
|
};};
|
||||||
const magic = u32le(0);
|
const magic = u32le(0);
|
||||||
if (magic !== 0x010000) {
|
if (magic !== 0x010000) {
|
||||||
// USER NOTICE: So far, I have yet to parse an icon that hasn't had 0x00010000 as it's magic.
|
// 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);
|
const textureFormat = getTextureFormat(textureType);
|
||||||
//:skip 4
|
//:skip 4
|
||||||
const numberOfVertexes = u32le(16);
|
const numberOfVertexes = u32le(16);
|
||||||
if(!!(numberOfVertexes % 3)){
|
if((numberOfVertexes % 3) > 0){
|
||||||
throw `Not enough vertices to define a triangle (${numberOfVertexes % 3} vertices remained).`;
|
throw `Not enough vertices to define a triangle (${numberOfVertexes % 3} vertices remained).`;
|
||||||
}
|
}
|
||||||
// format: [xxyyzzaa * numberOfShapes][xxyyzzaa][uuvvrgba], ((8 * numberOfShapes) + 16) [per chunk]
|
// format: [xxyyzzaa * numberOfShapes][xxyyzzaa][uuvvrgba], ((8 * numberOfShapes) + 16) [per chunk]
|
||||||
|
@ -389,7 +390,7 @@ function readIconFile(input) {
|
||||||
vertices.push({shapes, normal, uv, color});
|
vertices.push({shapes, normal, uv, color});
|
||||||
}
|
}
|
||||||
offset = (20+(numberOfVertexes * chunkLength));
|
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();
|
let animData = new Array();
|
||||||
// now we have to enumerate values, so now we introduce an offset value.
|
// 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.
|
// 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
|
//output of this will be another u16[0x4000] of the decompressed texture
|
||||||
//after that just parse output as-if it was uncompressed.
|
//after that just parse output as-if it was uncompressed.
|
||||||
//see uncompressTexture() and convertBGR5A1toRGB5A1() for more info.
|
//see uncompressTexture() and convertBGR5A1toRGB5A1() for more info.
|
||||||
size = u32le(offset);
|
const size = u32le(offset);
|
||||||
texture = {size, data: input.slice(offset+4, offset+(4+size))};
|
texture = {size, data: input.slice(offset+4, offset+(4+size))};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -497,7 +498,7 @@ function readEmsPsuFile(input){
|
||||||
let output = new Object();
|
let output = new Object();
|
||||||
let offset = 512;
|
let offset = 512;
|
||||||
for (let index = 0; index < header.size; index++) {
|
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) {
|
switch(fdesc.type) {
|
||||||
case "directory": {
|
case "directory": {
|
||||||
offset += 512;
|
offset += 512;
|
||||||
|
@ -569,15 +570,21 @@ function readPsvFile(input){
|
||||||
for (let index = 0; index < numberOfFiles; index++) {
|
for (let index = 0; index < numberOfFiles; index++) {
|
||||||
fileData.push(input.slice(offset,offset+0x3c));
|
fileData.push(input.slice(offset,offset+0x3c));
|
||||||
offset += 0x3c;
|
offset += 0x3c;
|
||||||
};
|
}
|
||||||
//then file data after this but we already have pointers to the files we care about
|
//then file data after this but we already have pointers to the files we care about
|
||||||
const icons = {
|
const icons = {
|
||||||
n: input.slice(nModelOffset, nModelOffset+nModelSize),
|
n: input.slice(nModelOffset, nModelOffset+nModelSize),
|
||||||
c: input.slice(cModelOffset, cModelOffset+cModelSize),
|
c: input.slice(cModelOffset, cModelOffset+cModelSize),
|
||||||
d: input.slice(dModelOffset, dModelOffset+dModelSize),
|
d: input.slice(dModelOffset, dModelOffset+dModelSize),
|
||||||
}
|
};
|
||||||
if (ICONJS_DEBUG) {
|
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};
|
return {icons, "icon.sys": input.slice(ps2dOffset, ps2dOffset+ps2dSize), timestamps};
|
||||||
}
|
}
|
||||||
|
@ -660,11 +667,11 @@ function readSharkXPortSxpsFile(input) {
|
||||||
const comments = {
|
const comments = {
|
||||||
"game": stringScrubber((new TextDecoder("utf-8")).decode(title)),
|
"game": stringScrubber((new TextDecoder("utf-8")).decode(title)),
|
||||||
"name": stringScrubber((new TextDecoder("utf-8")).decode(description))
|
"name": stringScrubber((new TextDecoder("utf-8")).decode(description))
|
||||||
}
|
};
|
||||||
if(description2Length !== 0) {
|
if(description2Length !== 0) {
|
||||||
comments.desc = stringScrubber((new TextDecoder("utf-8")).decode(description2));
|
comments.desc = stringScrubber((new TextDecoder("utf-8")).decode(description2));
|
||||||
}
|
}
|
||||||
const totalSize = u32le(offset);
|
//const totalSize = u32le(offset); has data, unused in script
|
||||||
offset += 4;
|
offset += 4;
|
||||||
const header = readSxpsDescriptor(input.slice(offset, offset + 250));
|
const header = readSxpsDescriptor(input.slice(offset, offset + 250));
|
||||||
offset += 250;
|
offset += 250;
|
||||||
|
@ -672,7 +679,7 @@ function readSharkXPortSxpsFile(input) {
|
||||||
let fsOut = {length: header.size, rootDirectory: header.filename, timestamps: header.timestamps, comments};
|
let fsOut = {length: header.size, rootDirectory: header.filename, timestamps: header.timestamps, comments};
|
||||||
let output = new Object();
|
let output = new Object();
|
||||||
for (let index = 0; index < (header.size - 2); index++) {
|
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) {
|
switch(fdesc.type) {
|
||||||
case "directory": {
|
case "directory": {
|
||||||
offset += 250;
|
offset += 250;
|
||||||
|
@ -731,7 +738,7 @@ function readCodeBreakerCbsDirectory(input) {
|
||||||
*/
|
*/
|
||||||
function readCodeBreakerCbsFile(input, inflator = null) {
|
function readCodeBreakerCbsFile(input, inflator = null) {
|
||||||
if(typeof inflator !== "function") {
|
if(typeof inflator !== "function") {
|
||||||
throw `No inflator function passed. Skipping.`;
|
throw "No inflator function passed. Skipping.";
|
||||||
}
|
}
|
||||||
const {u32le, t64le} = new yellowDataReader(input);
|
const {u32le, t64le} = new yellowDataReader(input);
|
||||||
const magic = u32le(0);
|
const magic = u32le(0);
|
||||||
|
@ -773,13 +780,13 @@ function readCodeBreakerCbsFile(input, inflator = null) {
|
||||||
*/
|
*/
|
||||||
function readMaxPwsDirectory(input, directorySize) {
|
function readMaxPwsDirectory(input, directorySize) {
|
||||||
const {u32le} = new yellowDataReader(input);
|
const {u32le} = new yellowDataReader(input);
|
||||||
virtualFilesystem = new Object();
|
const virtualFilesystem = new Object();
|
||||||
let offset = 0;
|
let offset = 0;
|
||||||
for (let index = 0; index < directorySize; index++) {
|
for (let index = 0; index < directorySize; index++) {
|
||||||
const dataSize = u32le(offset);
|
const dataSize = u32le(offset);
|
||||||
const _filename = input.slice(offset+4, offset+36);
|
const _filename = input.slice(offset+4, offset+36);
|
||||||
const filename = stringScrubber((new TextDecoder("utf-8")).decode(_filename));
|
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;
|
offset += 36;
|
||||||
const data = input.slice(offset, offset+dataSize);
|
const data = input.slice(offset, offset+dataSize);
|
||||||
offset += dataSize;
|
offset += dataSize;
|
||||||
|
@ -802,12 +809,12 @@ function readMaxPwsDirectory(input, directorySize) {
|
||||||
*/
|
*/
|
||||||
function readMaxPwsFile(input, unlzari) {
|
function readMaxPwsFile(input, unlzari) {
|
||||||
if(typeof unlzari !== "function") {
|
if(typeof unlzari !== "function") {
|
||||||
throw `No decompresser function passed. Skipping.`;
|
throw "No decompresser function passed. Skipping.";
|
||||||
}
|
}
|
||||||
const {u32le} = new yellowDataReader(input);
|
const {u32le} = new yellowDataReader(input);
|
||||||
const ident = input.slice(0, 12);
|
const ident = input.slice(0, 12);
|
||||||
if((new TextDecoder("utf-8")).decode(ident) !== "Ps2PowerSave") {
|
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)
|
//:skip 4 (u32 checksum)
|
||||||
const _dirName = input.slice(0x10, 0x30);
|
const _dirName = input.slice(0x10, 0x30);
|
||||||
|
@ -834,21 +841,22 @@ function readMaxPwsFile(input, unlzari) {
|
||||||
/**
|
/**
|
||||||
* Define (module.)exports with all public functions.
|
* Define (module.)exports with all public functions.
|
||||||
* @exports icondumper2/icon
|
* @exports icondumper2/icon
|
||||||
*/ // start c6js
|
*/ // start c6js#
|
||||||
|
/* globals exports: true */
|
||||||
if(typeof exports !== "object") {
|
if(typeof exports !== "object") {
|
||||||
exports = {
|
exports = {
|
||||||
readers: {readIconFile, readPS2D, readEmsPsuFile, readPsvFile, readSharkXPortSxpsFile, readCodeBreakerCbsFile, readMaxPwsFile},
|
readers: {"readIconFile": readIconFile, "readPS2D": readPS2D, "readEmsPsuFile": readEmsPsuFile, "readPsvFile": readPsvFile, "readSharkXPortSxpsFile": readSharkXPortSxpsFile, "readCodeBreakerCbsFile": readCodeBreakerCbsFile, "readMaxPwsFile": readMaxPwsFile},
|
||||||
helpers: {uncompressTexture, convertBGR5A1toRGB5A1},
|
helpers: {"uncompressTexture": uncompressTexture, "convertBGR5A1toRGB5A1": convertBGR5A1toRGB5A1},
|
||||||
options: {setDebug, setStrictness},
|
options: {"setDebug": setDebug, "setStrictness": setStrictness},
|
||||||
version: ICONJS_VERSION
|
version: ICONJS_VERSION
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
exports.readers = {readIconFile, readPS2D, readEmsPsuFile, readPsvFile, readSharkXPortSxpsFile, readCodeBreakerCbsFile, readMaxPwsFile};
|
exports.readers = {"readIconFile": readIconFile, "readPS2D": readPS2D, "readEmsPsuFile": readEmsPsuFile, "readPsvFile": readPsvFile, "readSharkXPortSxpsFile": readSharkXPortSxpsFile, "readCodeBreakerCbsFile": readCodeBreakerCbsFile, "readMaxPwsFile": readMaxPwsFile};
|
||||||
exports.helpers = {uncompressTexture, convertBGR5A1toRGB5A1};
|
exports.helpers = {"uncompressTexture": uncompressTexture, "convertBGR5A1toRGB5A1": convertBGR5A1toRGB5A1};
|
||||||
exports.options = {setDebug, setStrictness};
|
exports.options = {"setDebug": setDebug, "setStrictness": setStrictness};
|
||||||
exports.version = ICONJS_VERSION;
|
exports.version = ICONJS_VERSION;
|
||||||
}
|
}
|
||||||
|
/* globals module: true */
|
||||||
if(typeof module !== "undefined") {
|
if(typeof module !== "undefined") {
|
||||||
module.exports = exports;
|
module.exports = exports;
|
||||||
}
|
}
|
||||||
|
|
66
lzari.js
66
lzari.js
|
@ -24,7 +24,7 @@
|
||||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
* DEALINGS IN THE SOFTWARE.
|
* DEALINGS IN THE SOFTWARE.
|
||||||
**/
|
**/
|
||||||
|
/* jshint bitwise: false */ // not doing this makes linters scream about BWOs
|
||||||
//TODO: privatize variables and document the library
|
//TODO: privatize variables and document the library
|
||||||
|
|
||||||
var inputData = null;
|
var inputData = null;
|
||||||
|
@ -43,7 +43,7 @@ var bit_Mask = 0;
|
||||||
|
|
||||||
function GetBit() {
|
function GetBit() {
|
||||||
//partial xgetc modification
|
//partial xgetc modification
|
||||||
if(inputLocation >= inputData.length) {return -1};
|
if(inputLocation >= inputData.length) {return -1;}
|
||||||
if((bit_Mask >>= 1) === 0) {
|
if((bit_Mask >>= 1) === 0) {
|
||||||
bit_Buffer = inputData[inputLocation++];
|
bit_Buffer = inputData[inputLocation++];
|
||||||
bit_Mask = 128;
|
bit_Mask = 128;
|
||||||
|
@ -52,10 +52,10 @@ function GetBit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function BinarySearchSym(x) {
|
function BinarySearchSym(x) {
|
||||||
let i = 1;
|
var i = 1;
|
||||||
let j = 314;
|
var j = 314;
|
||||||
while (i < j) {
|
while (i < j) {
|
||||||
let k = ((i + j) / 2)|0;
|
var k = ((i + j) / 2)|0;
|
||||||
if (symbolCumulative[k] > x) {
|
if (symbolCumulative[k] > x) {
|
||||||
i = k + 1;
|
i = k + 1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -66,10 +66,10 @@ function BinarySearchSym(x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function BinarySearchPos(x) {
|
function BinarySearchPos(x) {
|
||||||
let i = 1;
|
var i = 1;
|
||||||
let j = 4096;
|
var j = 4096;
|
||||||
while (i < j) {
|
while (i < j) {
|
||||||
let k = ((i + j) / 2)|0;
|
var k = ((i + j) / 2)|0;
|
||||||
if (positionCumulative[k] > x) {
|
if (positionCumulative[k] > x) {
|
||||||
i = k + 1;
|
i = k + 1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -93,28 +93,28 @@ function DecodeChar() {
|
||||||
value -= 32768;
|
value -= 32768;
|
||||||
low -= 32768;
|
low -= 32768;
|
||||||
high -= 32768;
|
high -= 32768;
|
||||||
} else if (high > 65536) { break };
|
} else if (high > 65536) { break; }
|
||||||
low += low;
|
low += low;
|
||||||
high += high;
|
high += high;
|
||||||
value = 2 * value + GetBit();
|
value = 2 * value + GetBit();
|
||||||
}
|
}
|
||||||
//transcluded UpdateModel
|
//transcluded UpdateModel
|
||||||
let character = symbolToCharacter[sym];
|
var character = symbolToCharacter[sym];
|
||||||
// do not remove above, will be overwritten otherwise!
|
// do not remove above, will be overwritten otherwise!
|
||||||
let i;
|
var i;
|
||||||
|
|
||||||
if(symbolCumulative[0] >= 32767) {
|
if(symbolCumulative[0] >= 32767) {
|
||||||
let chr = 0;
|
var chr = 0;
|
||||||
for (i = 314; i > 0; i--) {
|
for (i = 314; i > 0; i--) {
|
||||||
symbolCumulative[i] = chr;
|
symbolCumulative[i] = chr;
|
||||||
chr += (symbolFrequency[i] = (symbolFrequency[i] + 1) >> 1);
|
chr += (symbolFrequency[i] = (symbolFrequency[i] + 1) >> 1);
|
||||||
}
|
}
|
||||||
symbolCumulative[0] = chr;
|
symbolCumulative[0] = chr;
|
||||||
}
|
}
|
||||||
for(i = sym; symbolFrequency[i] === symbolFrequency[i - 1]; i--) {};
|
for(i = sym; symbolFrequency[i] === symbolFrequency[i - 1]; i--) {}
|
||||||
if (i < sym) {
|
if (i < sym) {
|
||||||
let ch_i = symbolToCharacter[i];
|
var ch_i = symbolToCharacter[i];
|
||||||
let ch_sym = symbolToCharacter[sym];
|
var ch_sym = symbolToCharacter[sym];
|
||||||
symbolToCharacter[i] = ch_sym;
|
symbolToCharacter[i] = ch_sym;
|
||||||
symbolToCharacter[sym] = ch_i;
|
symbolToCharacter[sym] = ch_i;
|
||||||
characterToSymbol[ch_i] = sym;
|
characterToSymbol[ch_i] = sym;
|
||||||
|
@ -144,7 +144,7 @@ function DecodePosition() {
|
||||||
value -= 32768;
|
value -= 32768;
|
||||||
low -= 32768;
|
low -= 32768;
|
||||||
high -= 32768;
|
high -= 32768;
|
||||||
} else if (high > 65536) { break };
|
} else if (high > 65536) { break; }
|
||||||
low += low;
|
low += low;
|
||||||
high += high;
|
high += high;
|
||||||
value = 2 * value + GetBit();
|
value = 2 * value + GetBit();
|
||||||
|
@ -178,23 +178,22 @@ function decodeLzari(input) {
|
||||||
inputData = input;
|
inputData = input;
|
||||||
inputLocation = 4;
|
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(0);
|
||||||
if (dataSize < 0) return(-1);
|
if (dataSize < 0) return(-1);
|
||||||
|
|
||||||
let outputLength = dataSize;
|
var outputData = new Uint8Array(dataSize);
|
||||||
let outputData = new Uint8Array(dataSize);
|
var outputLocation = 0;
|
||||||
let outputLocation = 0;
|
|
||||||
|
|
||||||
//transcluded StartDecode
|
//transcluded StartDecode
|
||||||
for (let i = 0; i < 17; i++) {
|
for (var i = 0; i < 17; i++) {
|
||||||
value = 2 * value + GetBit();
|
value = 2 * value + GetBit();
|
||||||
}
|
}
|
||||||
//transcluded StartModel
|
//transcluded StartModel
|
||||||
symbolCumulative[314] = 0;
|
symbolCumulative[314] = 0;
|
||||||
for (let sym = 314; sym >= 1; sym--) {
|
for (var sym = 314; sym >= 1; sym--) {
|
||||||
let ch = sym - 1;
|
var ch = sym - 1;
|
||||||
characterToSymbol[ch] = sym;
|
characterToSymbol[ch] = sym;
|
||||||
symbolToCharacter[sym] = ch;
|
symbolToCharacter[sym] = ch;
|
||||||
symbolFrequency[sym] = 1;
|
symbolFrequency[sym] = 1;
|
||||||
|
@ -202,29 +201,29 @@ function decodeLzari(input) {
|
||||||
}
|
}
|
||||||
symbolFrequency[0] = 0;
|
symbolFrequency[0] = 0;
|
||||||
positionCumulative[4096] = 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);
|
positionCumulative[i - 1] = (positionCumulative[i] + (10000 / (i + 200))|0);
|
||||||
}
|
}
|
||||||
//end transclusion
|
//end transclusion
|
||||||
//normal Decode process
|
//normal Decode process
|
||||||
|
|
||||||
for (let i = 0; i < 4036; i++) {
|
for (i = 0; i < 4036; i++) { // redefine i
|
||||||
text_buffer[i] = 32;
|
text_buffer[i] = 32;
|
||||||
}
|
}
|
||||||
var r = 4036;
|
var r = 4036;
|
||||||
|
|
||||||
for (let count = 0; count < dataSize; ) {
|
for (var count = 0; count < dataSize; ) {
|
||||||
if(inputLocation >= inputData.length) {break};
|
if(inputLocation >= inputData.length) {break;}
|
||||||
let c = DecodeChar();
|
var c = DecodeChar();
|
||||||
if (c < 256) {
|
if (c < 256) {
|
||||||
outputData[outputLocation++] = c;
|
outputData[outputLocation++] = c;
|
||||||
text_buffer[r++] = c;
|
text_buffer[r++] = c;
|
||||||
r &= (4095);
|
r &= (4095);
|
||||||
count++;
|
count++;
|
||||||
} else {
|
} else {
|
||||||
let i = (r - DecodePosition() - 1) & 4095;
|
i = (r - DecodePosition() - 1) & 4095; // redefine i
|
||||||
let j = c - 253;
|
var j = c - 253;
|
||||||
for (let k = 0; k < j; k++) {
|
for (var k = 0; k < j; k++) {
|
||||||
c = text_buffer[(i + k) & 4095];
|
c = text_buffer[(i + k) & 4095];
|
||||||
outputData[outputLocation++] = c;
|
outputData[outputLocation++] = c;
|
||||||
text_buffer[r++] = c;
|
text_buffer[r++] = c;
|
||||||
|
@ -241,14 +240,15 @@ function decodeLzari(input) {
|
||||||
* Define (module.)exports with all public functions.
|
* Define (module.)exports with all public functions.
|
||||||
* @exports icondumper2/lzari
|
* @exports icondumper2/lzari
|
||||||
*/ // start c6js
|
*/ // start c6js
|
||||||
|
/* globals exports: true */
|
||||||
if(typeof exports !== "object") {
|
if(typeof exports !== "object") {
|
||||||
exports = {
|
exports = {
|
||||||
decodeLzari
|
"decodeLzari": decodeLzari
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
exports.decodeLzari = decodeLzari;
|
exports.decodeLzari = decodeLzari;
|
||||||
}
|
}
|
||||||
|
/* globals module: true */
|
||||||
if(typeof module !== "undefined") {
|
if(typeof module !== "undefined") {
|
||||||
module.exports = exports;
|
module.exports = exports;
|
||||||
}
|
}
|
||||||
|
|
|
@ -174,16 +174,17 @@ const animData = new Uint8Array([
|
||||||
0x00, 0x00, 0x00, 0x00
|
0x00, 0x00, 0x00, 0x00
|
||||||
]); // 36 bytes
|
]); // 36 bytes
|
||||||
|
|
||||||
/** generate texture data (RAW: fill with red) **/
|
|
||||||
const texture_ = new Uint16Array(16384);
|
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) **/
|
/** for compressed textures (RLE: fill with blue) **/
|
||||||
texture_[0] = 0x0004;
|
texture_[0] = 0x0004;
|
||||||
texture_[1] = 0x0000;
|
texture_[1] = 0x0000;
|
||||||
texture_[2] = 0x4000;
|
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);
|
const textureData = new Uint8Array(texture_.buffer);
|
||||||
|
|
||||||
|
@ -271,6 +272,7 @@ CombinedIconData.set(iconData, 20);
|
||||||
CombinedIconData.set(animData, 20+864);
|
CombinedIconData.set(animData, 20+864);
|
||||||
CombinedIconData.set(textureData, 20+864+36);
|
CombinedIconData.set(textureData, 20+864+36);
|
||||||
|
|
||||||
|
// to be honest all of this could just be a generator
|
||||||
/** root directory **/
|
/** root directory **/
|
||||||
const psuHeader1 = new Uint8Array(Array.from({...[
|
const psuHeader1 = new Uint8Array(Array.from({...[
|
||||||
0x27, 0x84, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
|
0x27, 0x84, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
|
||||||
|
@ -344,7 +346,7 @@ for (let iconIndice = 0; iconIndice < 32; iconIndice++) { // realistically only
|
||||||
if(iconIndice > 9) {
|
if(iconIndice > 9) {
|
||||||
needsAlpha = 7; // if we're past 9, offset to start at A instead
|
needsAlpha = 7; // if we're past 9, offset to start at A instead
|
||||||
}
|
}
|
||||||
const PsuFileOutput = new Uint8Array(37888); // 37 uncompressed blocks
|
const PsuFileOutput = new Uint8Array(37888);// 37 uncompressed blocks
|
||||||
CombinedIconData[8] = iconIndice; // set texture type
|
CombinedIconData[8] = iconIndice; // set texture type
|
||||||
psuHeader1[75] = 0x30 + iconIndice+needsAlpha; // set folder name
|
psuHeader1[75] = 0x30 + iconIndice+needsAlpha; // set folder name
|
||||||
psuHeader5[71] = 0x30 + iconIndice+needsAlpha; // set file name
|
psuHeader5[71] = 0x30 + iconIndice+needsAlpha; // set file name
|
||||||
|
|
Loading…
Reference in New Issue