0.8.0: "Maximum Power"
I think this is it. The last major format for icondumper2. It's been a fun ride while it lasted. See you on the flip-side! Thanks for the pineapples. + Now supports MAX files + Added an LZARI implementation to the repository. * Now considering icondumper2 feature-complete. * [HTML] Fixed no-webgl fallback mode. * Reworked modules object to not clobber one that already exists - Dropped "goes here" terminology from file input boxes. Ending comments: There's still a few bugs involving the HTML client... Ambient lighting is quite jank. Needs better support... Feature: Do interpolated animations of models For now though... I want to do something else... for a bit, at least.
This commit is contained in:
parent
73e618369b
commit
eb8bc8e068
|
@ -0,0 +1,261 @@
|
||||||
|
// based on Luigi Auriemma's memory2memory LZARI modification. LZARI was created by Haruhiko Okumura.
|
||||||
|
// yellows111 modifications: forced all magic constants to be their actual values,
|
||||||
|
// static calculations have been squashed, some functions have been transcluded into others
|
||||||
|
|
||||||
|
/** @copyright MIT license:
|
||||||
|
* Based on a work by Haruhiko Okumura dated 1989-07-04.
|
||||||
|
* Copyright 2023 yellows111
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
**/
|
||||||
|
|
||||||
|
//TODO: privatize variables and document the library
|
||||||
|
|
||||||
|
var inputData = null;
|
||||||
|
var inputLocation = 0;
|
||||||
|
var low = 0;
|
||||||
|
var high = 131072;
|
||||||
|
var value = 0;
|
||||||
|
var text_buffer = new Array(4155);
|
||||||
|
var characterToSymbol = new Array(314);
|
||||||
|
var symbolToCharacter = new Array(315);
|
||||||
|
var symbolFrequency = new Array(315);
|
||||||
|
var symbolCumulative = new Array(315);
|
||||||
|
var positionCumulative = new Array(4097);
|
||||||
|
var bit_Buffer = 0;
|
||||||
|
var bit_Mask = 0;
|
||||||
|
|
||||||
|
function GetBit() {
|
||||||
|
//partial xgetc modification
|
||||||
|
if(inputLocation >= inputData.length) {return -1};
|
||||||
|
if((bit_Mask >>= 1) === 0) {
|
||||||
|
bit_Buffer = inputData[inputLocation++];
|
||||||
|
bit_Mask = 128;
|
||||||
|
}
|
||||||
|
return +((bit_Buffer & bit_Mask) !== 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function BinarySearchSym(x) {
|
||||||
|
let i = 1;
|
||||||
|
let j = 314;
|
||||||
|
while (i < j) {
|
||||||
|
let k = ~~((i + j) / 2);
|
||||||
|
if (symbolCumulative[k] > x) {
|
||||||
|
i = k + 1;
|
||||||
|
} else {
|
||||||
|
j = k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
function BinarySearchPos(x) {
|
||||||
|
let i = 1;
|
||||||
|
let j = 4096;
|
||||||
|
while (i < j) {
|
||||||
|
let k = ~~((i + j) / 2);
|
||||||
|
if (positionCumulative[k] > x) {
|
||||||
|
i = k + 1;
|
||||||
|
} else {
|
||||||
|
j = k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function DecodeChar() {
|
||||||
|
var range = high - low;
|
||||||
|
var sym = BinarySearchSym(~~(((value - low + 1) * symbolCumulative[0] - 1) / range));
|
||||||
|
high = low + ~~((range * symbolCumulative[sym - 1]) / symbolCumulative[0]);
|
||||||
|
low += ~~((range * symbolCumulative[sym ]) / symbolCumulative[0]);
|
||||||
|
for ( ; ; ) {
|
||||||
|
if (low >= 65536) {
|
||||||
|
value -= 65536;
|
||||||
|
low -= 65536;
|
||||||
|
high -= 65536;
|
||||||
|
} else if (low >= 32768 && high <= 98304) {
|
||||||
|
value -= 32768;
|
||||||
|
low -= 32768;
|
||||||
|
high -= 32768;
|
||||||
|
} else if (high > 65536) { break };
|
||||||
|
low += low;
|
||||||
|
high += high;
|
||||||
|
value = 2 * value + GetBit();
|
||||||
|
}
|
||||||
|
//transcluded UpdateModel
|
||||||
|
let character = symbolToCharacter[sym];
|
||||||
|
// do not remove above, will be overwritten otherwise!
|
||||||
|
let i;
|
||||||
|
|
||||||
|
if(symbolCumulative[0] >= 32767) {
|
||||||
|
let 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--) {};
|
||||||
|
if (i < sym) {
|
||||||
|
let ch_i = symbolToCharacter[i];
|
||||||
|
let ch_sym = symbolToCharacter[sym];
|
||||||
|
symbolToCharacter[i] = ch_sym;
|
||||||
|
symbolToCharacter[sym] = ch_i;
|
||||||
|
characterToSymbol[ch_i] = sym;
|
||||||
|
characterToSymbol[ch_sym] = i;
|
||||||
|
//i would change these vars...
|
||||||
|
//but it looks so darn cool...
|
||||||
|
}
|
||||||
|
symbolFrequency[i]++;
|
||||||
|
while (--i >= 0) {
|
||||||
|
symbolCumulative[i]++;
|
||||||
|
}
|
||||||
|
//end transclusion
|
||||||
|
return character;
|
||||||
|
}
|
||||||
|
|
||||||
|
function DecodePosition() {
|
||||||
|
var range = high - low;
|
||||||
|
var position = BinarySearchPos(~~(((value - low + 1) * positionCumulative[0] - 1) / range));
|
||||||
|
high = low + (~~((range * positionCumulative[position ]) / positionCumulative[0]));
|
||||||
|
low += (~~((range * positionCumulative[position + 1]) / positionCumulative[0]));
|
||||||
|
for ( ; ; ) {
|
||||||
|
if (low >= 65536) {
|
||||||
|
value -= 65536;
|
||||||
|
low -= 65536;
|
||||||
|
high -= 65536;
|
||||||
|
} else if (low >= 32768 && high <= 98304) {
|
||||||
|
value -= 32768;
|
||||||
|
low -= 32768;
|
||||||
|
high -= 32768;
|
||||||
|
} else if (high > 65536) { break };
|
||||||
|
low += low;
|
||||||
|
high += high;
|
||||||
|
value = 2 * value + GetBit();
|
||||||
|
}
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decompresses LZARI-formatted data.
|
||||||
|
* @param {Uint8Array} input - source data
|
||||||
|
* @returns {Uint8Array} output - uncompressed data
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
function decodeLzari(input) {
|
||||||
|
//transcluded reset function.
|
||||||
|
inputData = null;
|
||||||
|
inputLocation = 0;
|
||||||
|
low = 0;
|
||||||
|
high = 131072;
|
||||||
|
value = 0;
|
||||||
|
text_buffer = new Array(4155);
|
||||||
|
characterToSymbol = new Array(314);
|
||||||
|
symbolToCharacter = new Array(315);
|
||||||
|
symbolFrequency = new Array(315);
|
||||||
|
symbolCumulative = new Array(315);
|
||||||
|
positionCumulative = new Array(4097);
|
||||||
|
bit_Buffer = 0;
|
||||||
|
bit_Mask = 0;
|
||||||
|
//end transclusion
|
||||||
|
|
||||||
|
inputData = input;
|
||||||
|
inputLocation = 4;
|
||||||
|
|
||||||
|
let 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;
|
||||||
|
|
||||||
|
//transcluded StartDecode
|
||||||
|
for (let 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;
|
||||||
|
characterToSymbol[ch] = sym;
|
||||||
|
symbolToCharacter[sym] = ch;
|
||||||
|
symbolFrequency[sym] = 1;
|
||||||
|
symbolCumulative[sym - 1] = (symbolCumulative[sym] + symbolFrequency[sym]);
|
||||||
|
}
|
||||||
|
symbolFrequency[0] = 0;
|
||||||
|
positionCumulative[4096] = 0;
|
||||||
|
for (let i = 4096; i >= 1; i--) {
|
||||||
|
positionCumulative[i - 1] = (positionCumulative[i] + ~~(10000 / (i + 200)));
|
||||||
|
}
|
||||||
|
//end transclusion
|
||||||
|
//normal Decode process
|
||||||
|
|
||||||
|
for (let i = 0; i < 4036; i++) {
|
||||||
|
text_buffer[i] = 32;
|
||||||
|
}
|
||||||
|
var r = 4036;
|
||||||
|
|
||||||
|
for (let count = 0; count < dataSize; ) {
|
||||||
|
if(inputLocation >= inputData.length) {break};
|
||||||
|
let 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++) {
|
||||||
|
c = text_buffer[(i + k) & 4095];
|
||||||
|
outputData[outputLocation++] = c;
|
||||||
|
text_buffer[r++] = c;
|
||||||
|
r &= (4095);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//console.debug("LZARI I/O", {inputData, outputData});
|
||||||
|
return(outputData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define (module.)exports with all public functions.
|
||||||
|
* @exports icondumper2/lzari
|
||||||
|
*/ // start c6js
|
||||||
|
if(typeof exports !== "object") {
|
||||||
|
exports = {
|
||||||
|
decodeLzari
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
exports.decodeLzari = decodeLzari;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(typeof module !== "undefined") {
|
||||||
|
module.exports = exports;
|
||||||
|
}
|
||||||
|
|
||||||
|
//end c6js
|
||||||
|
//start esm
|
||||||
|
/*export {
|
||||||
|
decodeLzari
|
||||||
|
};*/
|
||||||
|
//end esm
|
Loading…
Reference in New Issue