Seperate module.exports into readers, helpers and options

Also add helpers to exports (uncompress and bgr2rgb functions)
Still stuck on the whole oversaturation thing.

Considering writing something to convert icon objects to a more usable model format.
This commit is contained in:
yellows111 2023-10-24 14:45:55 +01:00
parent d5ec733b07
commit 42286ba7f8
3 changed files with 153 additions and 74 deletions

20
icon.js
View File

@ -1,7 +1,8 @@
//todo: Make this a module/mjs file. C6 compatibility can stay, if needed. //todo: Make this a module/mjs file. C6 compatibility can stay, if needed.
//LOOKING FOR: LZARI implementation (for MAX), description of CBS compression (node zlib doesn't tackle it, even with RC4'ing the data)
ICONJS_DEBUG = false; ICONJS_DEBUG = false;
ICONJS_STRICT = true; ICONJS_STRICT = true;
ICONJS_VERSION = "0.4.2"; ICONJS_VERSION = "0.5.0";
function setDebug(value) { function setDebug(value) {
ICONJS_DEBUG = !!value; ICONJS_DEBUG = !!value;
@ -77,6 +78,7 @@ function convertBGR5A1toRGB5A1(bgrData) {
let r = ((bgrData[index] >> 10) & 0b11111); let r = ((bgrData[index] >> 10) & 0b11111);
// rrrrrgggggbbbbba (a = 1 because 0 is 127 which is 1.0f opacity for the GS) // rrrrrgggggbbbbba (a = 1 because 0 is 127 which is 1.0f opacity for the GS)
let newValue = 0b0000000000000001; let newValue = 0b0000000000000001;
// mind you, the alpha bit ^ seems to be set randomly on textures, anyway. Maybe i'm reading these wrong?
newValue |= (r << 1); newValue |= (r << 1);
newValue |= (g << 6); newValue |= (g << 6);
newValue |= (b << 11); newValue |= (b << 11);
@ -166,7 +168,8 @@ function readIconFile(input) {
}}; }};
const magic = u32le(0); const magic = u32le(0);
if (magic !== 0x010000) { if (magic !== 0x010000) {
// USER WARNING: APPARENTLY NOT ALL ICONS ARE 0x010000. THIS THROW WILL BE DROPPED LATER. // USER NOTICE: So far, I have yet to parse an icon that hasn't had 0x00010000 as it's magic.
// Can someone provide me pointers to such an icon if one exists?
throw `Not a PS2 icon file (was ${magic}, expected ${0x010000})`; throw `Not a PS2 icon file (was ${magic}, expected ${0x010000})`;
} }
const numberOfShapes = u32le(4); const numberOfShapes = u32le(4);
@ -237,6 +240,7 @@ function readIconFile(input) {
case 'U': { case 'U': {
//where every 16-bit entry is a BGR5A1 color 0b[bbbbbgggggrrrrra] //where every 16-bit entry is a BGR5A1 color 0b[bbbbbgggggrrrrra]
texture = new Uint16Array(input.slice(offset, (offset+0x8000))); texture = new Uint16Array(input.slice(offset, (offset+0x8000)));
//see convertBGR5A1toRGB5A1() for more info.
break; break;
} }
case 'C': { case 'C': {
@ -257,6 +261,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.
size = u32le(offset); size = u32le(offset);
texture = {size, data: input.slice(offset+4, offset+(4+size))}; texture = {size, data: input.slice(offset+4, offset+(4+size))};
} }
@ -333,7 +338,7 @@ function readEmsPsuFile(input){
offset += ((fdesc.size & 0b11111111110000000000) + 1024); offset += ((fdesc.size & 0b11111111110000000000) + 1024);
} else { } else {
offset += fdesc.size; offset += fdesc.size;
// if we're already filling sectors fully, no to change anything about it // if we're already filling 1k blocks fully, why change the value?
} }
output[fdesc.filename] = { output[fdesc.filename] = {
size: fdesc.size, size: fdesc.size,
@ -370,7 +375,7 @@ function readPsvFile(input){
const type1 = u32le(56); const type1 = u32le(56);
const type2 = u32le(60); const type2 = u32le(60);
if(type1 !== 0x2c && type2 !== 2) { if(type1 !== 0x2c && type2 !== 2) {
throw `Not parsing, this is not a PS2 save export (was ${type1}:${type2}, expected 44:2)`; throw `Not parsing, this is not in the PS2 save export format (was ${type1}:${type2}, expected 44:2)`;
} }
const displayedSize = u32le(64); const displayedSize = u32le(64);
const ps2dOffset = u32le(68); const ps2dOffset = u32le(68);
@ -509,5 +514,10 @@ function readSharkXPortSxpsFile(input) {
if(typeof module !== "undefined") { if(typeof module !== "undefined") {
// for C6JS // for C6JS
module.exports = {readIconFile, readPS2D, readEmsPsuFile, readPsvFile, readSharkXPortSxpsFile, setDebug, setStrictness}; module.exports = {
readers: {readIconFile, readPS2D, readEmsPsuFile, readPsvFile, readSharkXPortSxpsFile},
helpers: {uncompressTexture, convertBGR5A1toRGB5A1},
options: {setDebug, setStrictness},
version: ICONJS_VERSION
};
} }

View File

@ -1,4 +1,5 @@
const iconjs = require("./icon.js"); const icondumper2 = require("./icon.js");
const iconjs = icondumper2.readers;
const filesystem = require("fs"); const filesystem = require("fs");
const processObj = require("process"); const processObj = require("process");
@ -7,11 +8,13 @@ require("util").inspect.defaultOptions.maxArrayLength = 10;
require("util").inspect.defaultOptions.compact = true; require("util").inspect.defaultOptions.compact = true;
require("util").inspect.defaultOptions.depth = 2; require("util").inspect.defaultOptions.depth = 2;
// debugger // output debugging information
iconjs.setDebug(false); icondumper2.options.setDebug(false);
// node.js client // node.js client
if(processObj.argv[2] === "psu") { console.log(`icon.js version ${icondumper2.version}, 2023 (c) yellows111`);
switch(processObj.argv[2]) {
case "psu": {
let inputFile = filesystem.readFileSync(processObj.argv[3] ? processObj.argv[3] : "file.psu"); let inputFile = filesystem.readFileSync(processObj.argv[3] ? processObj.argv[3] : "file.psu");
const parsed = iconjs.readEmsPsuFile(inputFile.buffer.slice(inputFile.byteOffset, inputFile.byteOffset + inputFile.byteLength)); const parsed = iconjs.readEmsPsuFile(inputFile.buffer.slice(inputFile.byteOffset, inputFile.byteOffset + inputFile.byteLength));
const PS2D = iconjs.readPS2D(parsed[parsed.rootDirectory]["icon.sys"].data); const PS2D = iconjs.readPS2D(parsed[parsed.rootDirectory]["icon.sys"].data);
@ -20,14 +23,19 @@ if(processObj.argv[2] === "psu") {
output[file] = iconjs.readIconFile(parsed[parsed.rootDirectory][PS2D.filenames[file]].data); output[file] = iconjs.readIconFile(parsed[parsed.rootDirectory][PS2D.filenames[file]].data);
}); });
console.log(output); console.log(output);
} else if(processObj.argv[2] === "psv") { break;
}
case "psv": {
let inputFile = filesystem.readFileSync(processObj.argv[3] ? processObj.argv[3] : "file.psv"); let inputFile = filesystem.readFileSync(processObj.argv[3] ? processObj.argv[3] : "file.psv");
const parsed = iconjs.readPsvFile(inputFile.buffer.slice(inputFile.byteOffset, inputFile.byteOffset + inputFile.byteLength)); const parsed = iconjs.readPsvFile(inputFile.buffer.slice(inputFile.byteOffset, inputFile.byteOffset + inputFile.byteLength));
console.log(parsed); console.log(parsed);
const PS2D = iconjs.readPS2D(parsed["icon.sys"]); const PS2D = iconjs.readPS2D(parsed["icon.sys"]);
let output = {parsed, PS2D}; let output = {parsed, PS2D};
console.log(output); console.log(output);
} else if(processObj.argv[2] === "sps") { break;
}
case "sps":
case "xps": {
let inputFile = filesystem.readFileSync(processObj.argv[3] ? processObj.argv[3] : "file.sps"); let inputFile = filesystem.readFileSync(processObj.argv[3] ? processObj.argv[3] : "file.sps");
const parsed = iconjs.readSharkXPortSxpsFile(inputFile.buffer.slice(inputFile.byteOffset, inputFile.byteOffset + inputFile.byteLength)); const parsed = iconjs.readSharkXPortSxpsFile(inputFile.buffer.slice(inputFile.byteOffset, inputFile.byteOffset + inputFile.byteLength));
console.log(parsed); console.log(parsed);
@ -37,15 +45,34 @@ if(processObj.argv[2] === "psu") {
output[file] = iconjs.readIconFile(parsed[parsed.rootDirectory][PS2D.filenames[file]].data); output[file] = iconjs.readIconFile(parsed[parsed.rootDirectory][PS2D.filenames[file]].data);
}); });
console.log(output); console.log(output);
} else { break;
let inputFile = filesystem.readFileSync(processObj.argv[2] ? processObj.argv[2] : "icon.sys"); }
case "sys": {
let inputFile = filesystem.readFileSync(processObj.argv[3] ? processObj.argv[3] : "icon.sys");
const metadata = iconjs.readPS2D(inputFile.buffer.slice(inputFile.byteOffset, inputFile.byteOffset + inputFile.byteLength)); const metadata = iconjs.readPS2D(inputFile.buffer.slice(inputFile.byteOffset, inputFile.byteOffset + inputFile.byteLength));
console.log("\noutput:", metadata, "\n") console.log("\noutput:", metadata, "\n")
if(processObj.argv.length > 4 && processObj.argv[4].toLowerCase() === "--no-read-models") {break;} else {
Object.keys(metadata.filenames).forEach(function(file) { Object.keys(metadata.filenames).forEach(function(file) {
let getFile = filesystem.readFileSync(metadata.filenames[file]); let getFile = filesystem.readFileSync(metadata.filenames[file]);
const output = iconjs.readIconFile(getFile.buffer.slice(getFile.byteOffset, getFile.byteOffset + getFile.byteLength)); const output = iconjs.readIconFile(getFile.buffer.slice(getFile.byteOffset, getFile.byteOffset + getFile.byteLength));
//console.log(individialIcon); //console.log(individialIcon);
console.log(`contents of ${metadata.filenames[file]} (${file}):`, output, "\n"); console.log(`contents of ${metadata.filenames[file]} (${file}):`, output, "\n");
}); });
}
break;
}
default: {
//Template literal goes here.
console.log(
`${(processObj.argv.length > 2) ? "Unknown argument: "+processObj.argv[2]+"\n\n": ""}icondumper2 node.js client subcommands:
psu: Read a EMS Memory Adapter export file.
psv: Read a PS3 export file.
sps: Read a SharkPort export file.
xps: Read a X-Port export file.
sys: Read a icon.sys (964 bytes) file, and attempt
to read icon files from the current directory.
(suppress behaviour with --no-read-models)
` ); // end of template
}
} }

102
input.htm
View File

@ -28,6 +28,7 @@
attribute vec4 a_color; attribute vec4 a_color;
uniform float u_rotation; uniform float u_rotation;
uniform float u_scale;
uniform highp vec3 u_ambientLight; uniform highp vec3 u_ambientLight;
//uniform highp vec3 u_lightColorA; //uniform highp vec3 u_lightColorA;
//uniform highp vec3 u_lightColorB; //uniform highp vec3 u_lightColorB;
@ -44,7 +45,7 @@
(a_position.x * pos.x) + (a_position.z * pos.y), //transform the x position (a_position.x * pos.x) + (a_position.z * pos.y), //transform the x position
(0.0 - a_position.y) - 2.75, // invert the y position and move down -2.75, which will center the model (0.0 - a_position.y) - 2.75, // invert the y position and move down -2.75, which will center the model
(a_position.x * -pos.y) + (a_position.z * pos.x), //transform the z position (a_position.x * -pos.y) + (a_position.z * pos.x), //transform the z position
3.5 u_scale
); );
// flip it, scale it // flip it, scale it
v_textureCoords = a_textureCoords; v_textureCoords = a_textureCoords;
@ -72,10 +73,13 @@
mediump vec4 texture_c = texture2D(u_sampler, v_textureCoords); mediump vec4 texture_c = texture2D(u_sampler, v_textureCoords);
highp vec3 ambientColorT = (u_ambientLight * vec3(texture_c)); highp vec3 ambientColorT = (u_ambientLight * vec3(texture_c));
highp vec3 ambientColorV = (u_ambientLight * vec3(v_color)); highp vec3 ambientColorV = (u_ambientLight * vec3(v_color));
//This has issues with oversaturation, but it means blended icons work. //This has issues with oversaturation (JXCR), but it means blended icons work.
//This also makes scaling a bit strange (JXCR, WLK). Why does it change depending on the scale?
if(v_color == vec4(1.0,1.0,1.0,1.0)) { if(v_color == vec4(1.0,1.0,1.0,1.0)) {
gl_FragColor = vec4((ambientColorT * ambientColorV), texture_c.a); gl_FragColor = vec4((ambientColorT * ambientColorV), texture_c.a);
} else { } else {
//WLK *SHOULD* follow this path, but doesn't. What can I do to fix this?
//Removing this path makes the models very dark, doing this fixes it, with oversaturation on false positives.
gl_FragColor = vec4((ambientColorT * ambientColorV) * 2.0, texture_c.a); gl_FragColor = vec4((ambientColorT * ambientColorV) * 2.0, texture_c.a);
} }
} }
@ -113,9 +117,9 @@
<h1 id="title1">&#xFF2E;&#xFF4F;&#x3000;&#xFF26;&#xFF49;&#xFF4C;&#xFF45;</h1> <h1 id="title1">&#xFF2E;&#xFF4F;&#x3000;&#xFF26;&#xFF49;&#xFF4C;&#xFF45;</h1>
<h1 id="title2">&#xFF2C;&#xFF4F;&#xFF41;&#xFF44;&#xFF45;&#xFF44;</h1> <h1 id="title2">&#xFF2C;&#xFF4F;&#xFF41;&#xFF44;&#xFF45;&#xFF44;</h1>
</div> </div>
<span>Background/icon preview (rotate: &larr;/&rarr; keys):</span><br> <span>Background/icon preview (rotate: &larr;/&rarr; keys, scale: &uarr;/&darr; keys):</span><br>
<canvas id="bgcanvas" width="360" height="360"></canvas> <canvas id="bgcanvas" width="480" height="480"></canvas>
<canvas id="iconcanvas" width="360" height="360"></canvas> <canvas id="iconcanvas" width="480" height="480"></canvas>
<hr> <hr>
<p>Normal: <kbd id="iconn">(no&nbsp;file)<wbr></kbd> Copying: <kbd id="iconc">(no&nbsp;file)<wbr></kbd> Deleting: <kbd id="icond">(no&nbsp;file)</kbd></p> <p>Normal: <kbd id="iconn">(no&nbsp;file)<wbr></kbd> Copying: <kbd id="iconc">(no&nbsp;file)<wbr></kbd> Deleting: <kbd id="icond">(no&nbsp;file)</kbd></p>
<div id="advanced"> <div id="advanced">
@ -146,28 +150,52 @@
<span>File comments: </span><span id="fileCommentGame">(no title)</span></span><span> - </span><span id="fileCommentName">(no description)</span> <span>File comments: </span><span id="fileCommentGame">(no title)</span></span><span> - </span><span id="fileCommentName">(no description)</span>
</p> </p>
<script> <script>
// I usually don't do in-body <script>'s, but I didn't want to do an await onload() again
const GlobalState = {rotations: 2, dataLength: 0, uniforms: {rotation: null, scale: null}};
// I don't care HOW disgusting doing this is, I'm sick of pressing escape to clear these.
let allInputs = document.querySelectorAll('input[type="file"]');
allInputs.forEach(
function(nodeObject) {
nodeObject.onclick = function() {
allInputs.forEach(function(elementObject) {elementObject.value = null;});
}
}
);
// rotation stuff
const rotationDensity = 60; const rotationDensity = 60;
rotations = 2;
document.body.onkeydown = function(ev) { document.body.onkeydown = function(ev) {
if(glBgContext === null) {return;} if(glBgContext === null) {return;}
if(typeof URotation !== "undefined") { if(typeof GlobalState.uniforms.rotation !== "undefined") {
switch(ev.code) { switch(ev.code) {
case "ArrowLeft": { case "ArrowLeft": {
rotations--; GlobalState.rotations--;
if(rotations < -rotationDensity) {rotations = -1;} if(GlobalState.rotations < -rotationDensity) {GlobalState.rotations = -1;}
break; break;
} }
case "ArrowRight": { case "ArrowRight": {
rotations++; GlobalState.rotations++;
if(rotations > rotationDensity) {rotations = 1;} if(GlobalState.rotations > rotationDensity) {GlobalState.rotations = 1;}
break; break;
} }
case "ArrowUp": {
GlobalState.scale -= 0.1;
if(GlobalState.scale <= 2) {GlobalState.scale = 2.0;}
break;
}
case "ArrowDown": {
GlobalState.scale += 0.1;
if(GlobalState.scale >= 6.0) {GlobalState.scale = 6.0;}
break;
}
default: {
return;
}
}; };
glFgContext.uniform1f(URotation, (rotations/rotationDensity)); glFgContext.uniform1f(GlobalState.uniforms.scale, GlobalState.scale);
glFgContext.drawArrays(glFgContext.TRIANGLES, 0, ULength); glFgContext.uniform1f(GlobalState.uniforms.rotation, (GlobalState.rotations/rotationDensity));
glFgContext.drawArrays(glFgContext.TRIANGLES, 0, GlobalState.dataLength);
} else {return;} } else {return;}
} }
// I usually don't do in-body <script>'s, but I didn't want to do an await onload again
function updateDisplay(input) { function updateDisplay(input) {
document.getElementById("title1").textContent = input.title[0]; document.getElementById("title1").textContent = input.title[0];
document.getElementById("title2").textContent = input.title[1]; document.getElementById("title2").textContent = input.title[1];
@ -254,7 +282,8 @@
}; };
var uniforms = { var uniforms = {
rotation: glFgContext.getUniformLocation(iconProgram, "u_rotation"), rotation: glFgContext.getUniformLocation(iconProgram, "u_rotation"),
ambientLighting: glFgContext.getUniformLocation(iconProgram, "u_ambientLight") ambientLighting: glFgContext.getUniformLocation(iconProgram, "u_ambientLight"),
scale: glFgContext.getUniformLocation(iconProgram, "u_scale")
} }
} else { } else {
var attributes = { var attributes = {
@ -264,7 +293,8 @@
var uniforms = { var uniforms = {
sampler: glFgContext.getUniformLocation(iconProgram, "u_sampler"), sampler: glFgContext.getUniformLocation(iconProgram, "u_sampler"),
rotation: glFgContext.getUniformLocation(iconProgram, "u_rotation"), rotation: glFgContext.getUniformLocation(iconProgram, "u_rotation"),
ambientLighting: glFgContext.getUniformLocation(iconProgram, "u_ambientLight") ambientLighting: glFgContext.getUniformLocation(iconProgram, "u_ambientLight"),
scale: glFgContext.getUniformLocation(iconProgram, "u_scale")
} }
} }
//.section SETUP //.section SETUP
@ -309,19 +339,24 @@
//.section ROTATE //.section ROTATE
// sets the angle uniform to 2/rotationDensity, this puts the icon at an angle. // sets the angle uniform to 2/rotationDensity, this puts the icon at an angle.
// globalize uniform rotation // globalize uniform rotation
URotation = uniforms.rotation; GlobalState.uniforms.rotation = uniforms.rotation;
rotations = 2; GlobalState.rotations = 2;
glFgContext.uniform1f(URotation, rotations/rotationDensity); glFgContext.uniform1f(GlobalState.uniforms.rotation, GlobalState.rotations/rotationDensity);
//.section LIGHTING //.section LIGHTING
let colours = fileMetadata.lighting.colors[0]; let colours = fileMetadata.lighting.colors[0];
//glFgContext.uniform3f(uniforms.ambientLighting, colours.r, colours.g, colours.b); //glFgContext.uniform3f(uniforms.ambientLighting, colours.r, colours.g, colours.b);
glFgContext.uniform3f(uniforms.ambientLighting, 1, 1, 1); glFgContext.uniform3f(uniforms.ambientLighting, 1, 1, 1);
//.section SCALING
GlobalState.uniforms.scale = uniforms.scale;
GlobalState.scale = 3.5;
glFgContext.uniform1f(GlobalState.uniforms.scale, GlobalState.scale);
//.section WRITE //.section WRITE
//globalize count of triangles, as well //globalize count of triangles, as well
ULength = (verticesArray.length/3); GlobalState.dataLength = (verticesArray.length/3);
glFgContext.drawArrays(glFgContext.TRIANGLES, 0, ULength); glFgContext.drawArrays(glFgContext.TRIANGLES, 0, GlobalState.dataLength);
} }
} }
document.getElementById("strictnessOption").onchange = function(e) { document.getElementById("strictnessOption").onchange = function(e) {
@ -358,7 +393,7 @@
try { try {
let output = readIconFile(d); let output = readIconFile(d);
renderIcon(output); renderIcon(output);
console.log("model data",output); console.log("model data (ic*)",output);
} catch(e) { } catch(e) {
if(glFgContext!==null){glFgContext.clear(glFgContext.COLOR_BUFFER_BIT | glFgContext.DEPTH_BUFFER_BIT);} if(glFgContext!==null){glFgContext.clear(glFgContext.COLOR_BUFFER_BIT | glFgContext.DEPTH_BUFFER_BIT);}
alert(e); alert(e);
@ -386,7 +421,8 @@
//TODO: use Time() to align JST times to user-local timezone //TODO: use Time() to align JST times to user-local timezone
document.getElementById("dateCreated").textContent = `${cTime.hours.toString().padStart("2","0")}:${cTime.minutes.toString().padStart("2","0")}:${cTime.seconds.toString().padStart("2","0")} ${cTime.day.toString().padStart("2","0")}/${cTime.month.toString().padStart("2","0")}/${cTime.year}`; document.getElementById("dateCreated").textContent = `${cTime.hours.toString().padStart("2","0")}:${cTime.minutes.toString().padStart("2","0")}:${cTime.seconds.toString().padStart("2","0")} ${cTime.day.toString().padStart("2","0")}/${cTime.month.toString().padStart("2","0")}/${cTime.year}`;
document.getElementById("dateModified").textContent = `${mTime.hours.toString().padStart("2","0")}:${mTime.minutes.toString().padStart("2","0")}:${mTime.seconds.toString().padStart("2","0")} ${mTime.day.toString().padStart("2","0")}/${mTime.month.toString().padStart("2","0")}/${mTime.year}`; document.getElementById("dateModified").textContent = `${mTime.hours.toString().padStart("2","0")}:${mTime.minutes.toString().padStart("2","0")}:${mTime.seconds.toString().padStart("2","0")} ${mTime.day.toString().padStart("2","0")}/${mTime.month.toString().padStart("2","0")}/${mTime.year}`;
console.log("model files", output2); console.log("model files (psu)", output2);
console.log("icon.sys (psu)", output);
} catch(e) { } catch(e) {
if(glBgContext!==null){glBgContext.clear(glBgContext.COLOR_BUFFER_BIT);} if(glBgContext!==null){glBgContext.clear(glBgContext.COLOR_BUFFER_BIT);}
if(glFgContext!==null){glFgContext.clear(glFgContext.COLOR_BUFFER_BIT | glFgContext.DEPTH_BUFFER_BIT);} if(glFgContext!==null){glFgContext.clear(glFgContext.COLOR_BUFFER_BIT | glFgContext.DEPTH_BUFFER_BIT);}
@ -405,13 +441,19 @@
let inputData = readPsvFile(d); let inputData = readPsvFile(d);
let output = readPS2D(inputData["icon.sys"]); let output = readPS2D(inputData["icon.sys"]);
updateDisplay(output); updateDisplay(output);
renderIcon(readIconFile(inputData.icons.n), output); const icons = {
console.log(readIconFile(inputData.icons.n)); n: readIconFile(inputData.icons.n),
c: readIconFile(inputData.icons.c),
d: readIconFile(inputData.icons.d),
}
renderIcon(icons.n, output);
let cTime = inputData.timestamps.created; let cTime = inputData.timestamps.created;
let mTime = inputData.timestamps.modified; let mTime = inputData.timestamps.modified;
//TODO: use Time() to align JST times to user-local timezone //TODO: use Time() to align JST times to user-local timezone
document.getElementById("dateCreated").textContent = `${cTime.hours.toString().padStart("2","0")}:${cTime.minutes.toString().padStart("2","0")}:${cTime.seconds.toString().padStart("2","0")} ${cTime.day.toString().padStart("2","0")}/${cTime.month.toString().padStart("2","0")}/${cTime.year}`; document.getElementById("dateCreated").textContent = `${cTime.hours.toString().padStart("2","0")}:${cTime.minutes.toString().padStart("2","0")}:${cTime.seconds.toString().padStart("2","0")} ${cTime.day.toString().padStart("2","0")}/${cTime.month.toString().padStart("2","0")}/${cTime.year}`;
document.getElementById("dateModified").textContent = `${mTime.hours.toString().padStart("2","0")}:${mTime.minutes.toString().padStart("2","0")}:${mTime.seconds.toString().padStart("2","0")} ${mTime.day.toString().padStart("2","0")}/${mTime.month.toString().padStart("2","0")}/${mTime.year}`; document.getElementById("dateModified").textContent = `${mTime.hours.toString().padStart("2","0")}:${mTime.minutes.toString().padStart("2","0")}:${mTime.seconds.toString().padStart("2","0")} ${mTime.day.toString().padStart("2","0")}/${mTime.month.toString().padStart("2","0")}/${mTime.year}`;
console.log("model files (psv)", icons);
console.log("icon.sys (psv)", output);
} catch(e) { } catch(e) {
if(glBgContext!==null){glBgContext.clear(glBgContext.COLOR_BUFFER_BIT);} if(glBgContext!==null){glBgContext.clear(glBgContext.COLOR_BUFFER_BIT);}
if(glFgContext!==null){glFgContext.clear(glFgContext.COLOR_BUFFER_BIT | glFgContext.DEPTH_BUFFER_BIT);} if(glFgContext!==null){glFgContext.clear(glFgContext.COLOR_BUFFER_BIT | glFgContext.DEPTH_BUFFER_BIT);}
@ -442,7 +484,8 @@
document.getElementById("dateModified").textContent = `${mTime.hours.toString().padStart("2","0")}:${mTime.minutes.toString().padStart("2","0")}:${mTime.seconds.toString().padStart("2","0")} ${mTime.day.toString().padStart("2","0")}/${mTime.month.toString().padStart("2","0")}/${mTime.year}`; document.getElementById("dateModified").textContent = `${mTime.hours.toString().padStart("2","0")}:${mTime.minutes.toString().padStart("2","0")}:${mTime.seconds.toString().padStart("2","0")} ${mTime.day.toString().padStart("2","0")}/${mTime.month.toString().padStart("2","0")}/${mTime.year}`;
document.getElementById("fileCommentGame").textContent = vFilesystem.comments.game; document.getElementById("fileCommentGame").textContent = vFilesystem.comments.game;
document.getElementById("fileCommentName").textContent = vFilesystem.comments.name; document.getElementById("fileCommentName").textContent = vFilesystem.comments.name;
console.log("model files", output2); console.log("model files (*ps)", output2);
console.log("icon.sys (*ps)", output);
} catch(e) { } catch(e) {
if(glBgContext!==null){glBgContext.clear(glBgContext.COLOR_BUFFER_BIT);} if(glBgContext!==null){glBgContext.clear(glBgContext.COLOR_BUFFER_BIT);}
if(glFgContext!==null){glFgContext.clear(glFgContext.COLOR_BUFFER_BIT | glFgContext.DEPTH_BUFFER_BIT);} if(glFgContext!==null){glFgContext.clear(glFgContext.COLOR_BUFFER_BIT | glFgContext.DEPTH_BUFFER_BIT);}
@ -459,7 +502,7 @@
return shader; return shader;
} }
console.log(gl.getShaderInfoLog(shader), source); console.log(gl.getShaderInfoLog(shader), (new String().padStart(60, "-")), source);
gl.deleteShader(shader); gl.deleteShader(shader);
} }
function createProgram(gl, vertexShader, fragmentShader) { function createProgram(gl, vertexShader, fragmentShader) {
@ -509,7 +552,6 @@
} }
if(glBgContext !== null) { if(glBgContext !== null) {
//.section CONFIGURATION //.section CONFIGURATION
glBgContext.enable(glBgContext.DEPTH_TEST);
glFgContext.enable(glFgContext.DEPTH_TEST); glFgContext.enable(glFgContext.DEPTH_TEST);
//.section CLEAR //.section CLEAR
glBgContext.clearColor(0.1,0.1,0.4,1); glBgContext.clearColor(0.1,0.1,0.4,1);
@ -523,10 +565,10 @@
document.getElementById("showExtractedInputOption").onchange = function(e) { document.getElementById("showExtractedInputOption").onchange = function(e) {
document.getElementById("advanced").style.display = ((e.target.checked) ? "block" : "none"); document.getElementById("advanced").style.display = ((e.target.checked) ? "block" : "none");
} }
//todo: Animation parsing, animation tweening //todo: More than one model shape rendering, other 2 icons, Animation parsing, animation tweening
</script> </script>
<span id="version">icondumper2 <span id="iconjsVersion">(unknown icon.js version)</span> [C: <span id="clientVersion">Loading...</span>] &mdash; &copy; 2023 yellows111</span> <span id="version">icondumper2 <span id="iconjsVersion">(unknown icon.js version)</span> [C: <span id="clientVersion">Loading...</span>] &mdash; &copy; 2023 yellows111</span>
<script>document.getElementById("iconjsVersion").textContent = ICONJS_VERSION;</script> <script>document.getElementById("iconjsVersion").textContent = ICONJS_VERSION;</script>
<script>document.getElementById("clientVersion").textContent = "0.6.2";</script> <script>document.getElementById("clientVersion").textContent = "0.6.3";</script>
</body> </body>
</html> </html>