NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name TT2 Optimizer / save file loader *modified // @namespace https://openuserjs.org/users/sytha/modified // @copyright 2018, sytha (https://openuserjs.org/users/sytha) // @license 0BSD // @version 0.1 // @description Load a save file from the Android version of the app to fill the artifacts inputs // @author Sytha (modified by Evilbadmad ) // @match https://tt2-optimizer.herokuapp.com/ // @grant GM.getValue // @grant GM.setValue // ==/UserScript== // ==OpenUserJS== // @author sytha // ==/OpenUserJS== // Thanks to https://etherhack.co.uk/symmetric/des_3des/des_3des.html const DECRYPT_KEY = "4bc07927192f4e9a"; function ReadSavefile(f, callback) { var r = new FileReader; r.onload = function (e) { try { var contents = e.target.result, key = chars_from_hex(DECRYPT_KEY), vector = contents.substring(0, 8), decrypted = des(key, contents.substring(8), 0, vector ? 1 : 0, vector), b = decrypted.indexOf("saveString"), k = decrypted.indexOf("playerData"), s = decrypted.substring(b + 12, k - 2), j = JSON.parse(JSON.parse(s), (k, v) => '$type' === k ? void 0 : v); console.log("Done parsing savefile"), callback(null, j) } catch (err) { callback(err, null) } }, r.readAsBinaryString(f) } function chars_from_hex(inputstr) { var outputstr = ''; inputstr = (inputstr = (inputstr = inputstr.replace(/^(0x)?/g, '')).replace(/[^A-Fa-f0-9]/g, '')).split(''); for (var i = 0; i < inputstr.length; i += 2) outputstr += String.fromCharCode(parseInt(inputstr[i] + '' + inputstr[i + 1], 16)); return outputstr } function des(key, message, encrypt, mode, iv, padding) { var i, j, temp, right1, right2, left, right, looping, cbcleft, cbcleft2, cbcright, cbcright2, endloop, loopinc, spfunction1 = new Array(16843776, 0, 65536, 16843780, 16842756, 66564, 4, 65536, 1024, 16843776, 16843780, 1024, 16778244, 16842756, 16777216, 4, 1028, 16778240, 16778240, 66560, 66560, 16842752, 16842752, 16778244, 65540, 16777220, 16777220, 65540, 0, 1028, 66564, 16777216, 65536, 16843780, 4, 16842752, 16843776, 16777216, 16777216, 1024, 16842756, 65536, 66560, 16777220, 1024, 4, 16778244, 66564, 16843780, 65540, 16842752, 16778244, 16777220, 1028, 66564, 16843776, 1028, 16778240, 16778240, 0, 65540, 66560, 0, 16842756), spfunction2 = new Array(-2146402272, -2147450880, 32768, 1081376, 1048576, 32, -2146435040, -2147450848, -2147483616, -2146402272, -2146402304, -2147483648, -2147450880, 1048576, 32, -2146435040, 1081344, 1048608, -2147450848, 0, -2147483648, 32768, 1081376, -2146435072, 1048608, -2147483616, 0, 1081344, 32800, -2146402304, -2146435072, 32800, 0, 1081376, -2146435040, 1048576, -2147450848, -2146435072, -2146402304, 32768, -2146435072, -2147450880, 32, -2146402272, 1081376, 32, 32768, -2147483648, 32800, -2146402304, 1048576, -2147483616, 1048608, -2147450848, -2147483616, 1048608, 1081344, 0, -2147450880, 32800, -2147483648, -2146435040, -2146402272, 1081344), spfunction3 = new Array(520, 134349312, 0, 134348808, 134218240, 0, 131592, 134218240, 131080, 134217736, 134217736, 131072, 134349320, 131080, 134348800, 520, 134217728, 8, 134349312, 512, 131584, 134348800, 134348808, 131592, 134218248, 131584, 131072, 134218248, 8, 134349320, 512, 134217728, 134349312, 134217728, 131080, 520, 131072, 134349312, 134218240, 0, 512, 131080, 134349320, 134218240, 134217736, 512, 0, 134348808, 134218248, 131072, 134217728, 134349320, 8, 131592, 131584, 134217736, 134348800, 134218248, 520, 134348800, 131592, 8, 134348808, 131584), spfunction4 = new Array(8396801, 8321, 8321, 128, 8396928, 8388737, 8388609, 8193, 0, 8396800, 8396800, 8396929, 129, 0, 8388736, 8388609, 1, 8192, 8388608, 8396801, 128, 8388608, 8193, 8320, 8388737, 1, 8320, 8388736, 8192, 8396928, 8396929, 129, 8388736, 8388609, 8396800, 8396929, 129, 0, 0, 8396800, 8320, 8388736, 8388737, 1, 8396801, 8321, 8321, 128, 8396929, 129, 1, 8192, 8388609, 8193, 8396928, 8388737, 8193, 8320, 8388608, 8396801, 128, 8388608, 8192, 8396928), spfunction5 = new Array(256, 34078976, 34078720, 1107296512, 524288, 256, 1073741824, 34078720, 1074266368, 524288, 33554688, 1074266368, 1107296512, 1107820544, 524544, 1073741824, 33554432, 1074266112, 1074266112, 0, 1073742080, 1107820800, 1107820800, 33554688, 1107820544, 1073742080, 0, 1107296256, 34078976, 33554432, 1107296256, 524544, 524288, 1107296512, 256, 33554432, 1073741824, 34078720, 1107296512, 1074266368, 33554688, 1073741824, 1107820544, 34078976, 1074266368, 256, 33554432, 1107820544, 1107820800, 524544, 1107296256, 1107820800, 34078720, 0, 1074266112, 1107296256, 524544, 33554688, 1073742080, 524288, 0, 1074266112, 34078976, 1073742080), spfunction6 = new Array(536870928, 541065216, 16384, 541081616, 541065216, 16, 541081616, 4194304, 536887296, 4210704, 4194304, 536870928, 4194320, 536887296, 536870912, 16400, 0, 4194320, 536887312, 16384, 4210688, 536887312, 16, 541065232, 541065232, 0, 4210704, 541081600, 16400, 4210688, 541081600, 536870912, 536887296, 16, 541065232, 4210688, 541081616, 4194304, 16400, 536870928, 4194304, 536887296, 536870912, 16400, 536870928, 541081616, 4210688, 541065216, 4210704, 541081600, 0, 541065232, 16, 16384, 541065216, 4210704, 16384, 4194320, 536887312, 0, 541081600, 536870912, 4194320, 536887312), spfunction7 = new Array(2097152, 69206018, 67110914, 0, 2048, 67110914, 2099202, 69208064, 69208066, 2097152, 0, 67108866, 2, 67108864, 69206018, 2050, 67110912, 2099202, 2097154, 67110912, 67108866, 69206016, 69208064, 2097154, 69206016, 2048, 2050, 69208066, 2099200, 2, 67108864, 2099200, 67108864, 2099200, 2097152, 67110914, 67110914, 69206018, 69206018, 2, 2097154, 67108864, 67110912, 2097152, 69208064, 2050, 2099202, 69208064, 2050, 67108866, 69208066, 69206016, 2099200, 0, 2, 69208066, 0, 2099202, 69206016, 2048, 67108866, 67110912, 2048, 2097154), spfunction8 = new Array(268439616, 4096, 262144, 268701760, 268435456, 268439616, 64, 268435456, 262208, 268697600, 268701760, 266240, 268701696, 266304, 4096, 64, 268697600, 268435520, 268439552, 4160, 266240, 262208, 268697664, 268701696, 4160, 0, 0, 268697664, 268435520, 268439552, 266304, 262144, 266304, 262144, 268701696, 4096, 64, 268697664, 4096, 266304, 268439552, 64, 268435520, 268697600, 268697664, 268435456, 262144, 268439616, 0, 268701760, 262208, 268435520, 268697600, 268439552, 268439616, 0, 268701760, 266240, 266240, 4160, 4160, 262208, 268435456, 268701696), keys = des_createKeys(key), m = 0, len = message.length, chunk = 0, iterations = 32 == keys.length ? 3 : 9; looping = 3 == iterations ? encrypt ? new Array(0, 32, 2) : new Array(30, -2, -2) : encrypt ? new Array(0, 32, 2, 62, 30, -2, 64, 96, 2) : new Array(94, 62, -2, 32, 64, 2, 30, -2, -2), 2 == padding ? message += " " : 1 == padding ? (temp = 8 - len % 8, message += String.fromCharCode(temp, temp, temp, temp, temp, temp, temp, temp), 8 == temp && (len += 8)) : padding || (message += "\0\0\0\0\0\0\0\0"); var result = "", tempresult = ""; for (1 == mode && (cbcleft = iv.charCodeAt(m++) << 24 | iv.charCodeAt(m++) << 16 | iv.charCodeAt(m++) << 8 | iv.charCodeAt(m++), cbcright = iv.charCodeAt(m++) << 24 | iv.charCodeAt(m++) << 16 | iv.charCodeAt(m++) << 8 | iv.charCodeAt(m++), m = 0); m < len;) { for (left = message.charCodeAt(m++) << 24 | message.charCodeAt(m++) << 16 | message.charCodeAt(m++) << 8 | message.charCodeAt(m++), right = message.charCodeAt(m++) << 24 | message.charCodeAt(m++) << 16 | message.charCodeAt(m++) << 8 | message.charCodeAt(m++), 1 == mode && (encrypt ? (left ^= cbcleft, right ^= cbcright) : (cbcleft2 = cbcleft, cbcright2 = cbcright, cbcleft = left, cbcright = right)), left ^= (temp = 252645135 & (left >>> 4 ^ right)) << 4, left ^= (temp = 65535 & (left >>> 16 ^ (right ^= temp))) << 16, left ^= temp = 858993459 & ((right ^= temp) >>> 2 ^ left), left ^= temp = 16711935 & ((right ^= temp << 2) >>> 8 ^ left), left = (left ^= (temp = 1431655765 & (left >>> 1 ^ (right ^= temp << 8))) << 1) << 1 | left >>> 31, right = (right ^= temp) << 1 | right >>> 31, j = 0; j < iterations; j += 3) { for (endloop = looping[j + 1], loopinc = looping[j + 2], i = looping[j]; i != endloop; i += loopinc) right1 = right ^ keys[i], right2 = (right >>> 4 | right << 28) ^ keys[i + 1], temp = left, left = right, right = temp ^ (spfunction2[right1 >>> 24 & 63] | spfunction4[right1 >>> 16 & 63] | spfunction6[right1 >>> 8 & 63] | spfunction8[63 & right1] | spfunction1[right2 >>> 24 & 63] | spfunction3[right2 >>> 16 & 63] | spfunction5[right2 >>> 8 & 63] | spfunction7[63 & right2]); temp = left, left = right, right = temp } right = right >>> 1 | right << 31, right ^= temp = 1431655765 & ((left = left >>> 1 | left << 31) >>> 1 ^ right), right ^= (temp = 16711935 & (right >>> 8 ^ (left ^= temp << 1))) << 8, right ^= (temp = 858993459 & (right >>> 2 ^ (left ^= temp))) << 2, right ^= temp = 65535 & ((left ^= temp) >>> 16 ^ right), right ^= temp = 252645135 & ((left ^= temp << 16) >>> 4 ^ right), left ^= temp << 4, 1 == mode && (encrypt ? (cbcleft = left, cbcright = right) : (left ^= cbcleft2, right ^= cbcright2)), tempresult += String.fromCharCode(left >>> 24, left >>> 16 & 255, left >>> 8 & 255, 255 & left, right >>> 24, right >>> 16 & 255, right >>> 8 & 255, 255 & right), 512 == (chunk += 8) && (result += tempresult, tempresult = "", chunk = 0) } return result = (result += tempresult).replace(/\0*$/g, "") } // ver 2.12 artifact default order var ordermap = new Array(22, 2, 19, 1, 20, 66, 43, 44, 45, 79, 82, 84, 26, 31, 29, 51, 59, 83, 35, 32, 33, 34, 61, 62, 38, 30, 64, 52, 53, 67, 42, 46, 55, 56, 75, 76, 77, 78, 40, 25, 17, 23, 73, 28, 86, 87, 88, 89, 90, 47, 11, 41, 9, 10, 7, 6, 65, 48, 13, 15, 16, 14, 12, 36, 27, 39, 37, 3, 8, 50, 58, 68, 18, 21, 5, 4, 54, 70, 74, 72, 69, 63, 24, 71, 49, 80, 81, 85, 57, 60); var scriptVer = "2.12"; // function des_createKeys(key) { for (var left, right, lefttemp, righttemp, i, temp, pc2bytes0 = new Array(0, 4, 536870912, 536870916, 65536, 65540, 536936448, 536936452, 512, 516, 536871424, 536871428, 66048, 66052, 536936960, 536936964), pc2bytes1 = new Array(0, 1, 1048576, 1048577, 67108864, 67108865, 68157440, 68157441, 256, 257, 1048832, 1048833, 67109120, 67109121, 68157696, 68157697), pc2bytes2 = new Array(0, 8, 2048, 2056, 16777216, 16777224, 16779264, 16779272, 0, 8, 2048, 2056, 16777216, 16777224, 16779264, 16779272), pc2bytes3 = new Array(0, 2097152, 134217728, 136314880, 8192, 2105344, 134225920, 136323072, 131072, 2228224, 134348800, 136445952, 139264, 2236416, 134356992, 136454144), pc2bytes4 = new Array(0, 262144, 16, 262160, 0, 262144, 16, 262160, 4096, 266240, 4112, 266256, 4096, 266240, 4112, 266256), pc2bytes5 = new Array(0, 1024, 32, 1056, 0, 1024, 32, 1056, 33554432, 33555456, 33554464, 33555488, 33554432, 33555456, 33554464, 33555488), pc2bytes6 = new Array(0, 268435456, 524288, 268959744, 2, 268435458, 524290, 268959746, 0, 268435456, 524288, 268959744, 2, 268435458, 524290, 268959746), pc2bytes7 = new Array(0, 65536, 2048, 67584, 536870912, 536936448, 536872960, 536938496, 131072, 196608, 133120, 198656, 537001984, 537067520, 537004032, 537069568), pc2bytes8 = new Array(0, 262144, 0, 262144, 2, 262146, 2, 262146, 33554432, 33816576, 33554432, 33816576, 33554434, 33816578, 33554434, 33816578), pc2bytes9 = new Array(0, 268435456, 8, 268435464, 0, 268435456, 8, 268435464, 1024, 268436480, 1032, 268436488, 1024, 268436480, 1032, 268436488), pc2bytes10 = new Array(0, 32, 0, 32, 1048576, 1048608, 1048576, 1048608, 8192, 8224, 8192, 8224, 1056768, 1056800, 1056768, 1056800), pc2bytes11 = new Array(0, 16777216, 512, 16777728, 2097152, 18874368, 2097664, 18874880, 67108864, 83886080, 67109376, 83886592, 69206016, 85983232, 69206528, 85983744), pc2bytes12 = new Array(0, 4096, 134217728, 134221824, 524288, 528384, 134742016, 134746112, 16, 4112, 134217744, 134221840, 524304, 528400, 134742032, 134746128), pc2bytes13 = new Array(0, 4, 256, 260, 0, 4, 256, 260, 1, 5, 257, 261, 1, 5, 257, 261), iterations = key.length > 8 ? 3 : 1, keys = new Array(32 * iterations), shifts = new Array(0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0), m = 0, n = 0, j = 0; j < iterations; j++) for (left = key.charCodeAt(m++) << 24 | key.charCodeAt(m++) << 16 | key.charCodeAt(m++) << 8 | key.charCodeAt(m++), left ^= (temp = 252645135 & (left >>> 4 ^ (right = key.charCodeAt(m++) << 24 | key.charCodeAt(m++) << 16 | key.charCodeAt(m++) << 8 | key.charCodeAt(m++)))) << 4, left ^= temp = 65535 & ((right ^= temp) >>> -16 ^ left), left ^= (temp = 858993459 & (left >>> 2 ^ (right ^= temp << -16))) << 2, left ^= temp = 65535 & ((right ^= temp) >>> -16 ^ left), left ^= (temp = 1431655765 & (left >>> 1 ^ (right ^= temp << -16))) << 1, left ^= temp = 16711935 & ((right ^= temp) >>> 8 ^ left), temp = (left ^= (temp = 1431655765 & (left >>> 1 ^ (right ^= temp << 8))) << 1) << 8 | (right ^= temp) >>> 20 & 240, left = right << 24 | right << 8 & 16711680 | right >>> 8 & 65280 | right >>> 24 & 240, right = temp, i = 0; i < shifts.length; i++) shifts[i] ? (left = left << 2 | left >>> 26, right = right << 2 | right >>> 26) : (left = left << 1 | left >>> 27, right = right << 1 | right >>> 27), right &= -15, lefttemp = pc2bytes0[(left &= -15) >>> 28] | pc2bytes1[left >>> 24 & 15] | pc2bytes2[left >>> 20 & 15] | pc2bytes3[left >>> 16 & 15] | pc2bytes4[left >>> 12 & 15] | pc2bytes5[left >>> 8 & 15] | pc2bytes6[left >>> 4 & 15], temp = 65535 & ((righttemp = pc2bytes7[right >>> 28] | pc2bytes8[right >>> 24 & 15] | pc2bytes9[right >>> 20 & 15] | pc2bytes10[right >>> 16 & 15] | pc2bytes11[right >>> 12 & 15] | pc2bytes12[right >>> 8 & 15] | pc2bytes13[right >>> 4 & 15]) >>> 16 ^ lefttemp), keys[n++] = lefttemp ^ temp, keys[n++] = righttemp ^ temp << 16; return keys }! function () { 'use strict'; // CREATE DROP DIV var fileLoader = document.createElement('input'); fileLoader.setAttribute('id', 'fileLoader2'); fileLoader.setAttribute('type', 'file'); fileLoader.setAttribute('accept', ".fadat,.adat"); fileLoader.setAttribute('label', "load save"); fileLoader.setAttribute('title', "Load"); fileLoader.innerHtml = 'Browse <b>ISavableGlobal.adat</b>'; document.body.appendChild(fileLoader); var fileLoaderStyle = { border: '2px solid', position: 'fixed', top: '130px', right: '10px', zIndex: 1e4, width: '100px', height: '100px', textAlign: 'center', paddingTop: '25px', boxSizing: 'border-box', borderRadius: '3px', background: '#960', boxShadow: '0 0 8px #000' }; for (var rule in fileLoaderStyle) fileLoader.style[rule] = fileLoaderStyle[rule]; // EVENT HANDLERS // PARSE SAVE FILE function parseAsBigIntString(Num) { var num = typeof (Num) == "string" && parseFloat(Num) || Num if ((typeof (num) != "number") || !isFinite(num)) return Num; // not a finite number return as is var n = ("" + num).split(/[eE]/); if (!n || n.length < 2 || n[1].indexOf("-") > -1) return num; var m = n[0].split("."); if (!m) m = new Array(n[0], ""); var ret = m[0] + m[1]; var extra = parseInt(n[1]) - m[1].length; if (extra > 0) for (var i = 0; i < extra; i++) ret += "0"; //var r =""+num+"\n"+Num+"\n"+n[0].length +"\n"+n[0]+"\n"+n[1] +"\n"+m[0]+"\n"+m[1]+"\n"+m[0].length +"\n"+m[1].length+"\n"+ret+"\n"+parseFloat(ret)+"\n"+(parseInt(n[1])-m[1].length) ; //alert(r) ; return ret; } function readSaveFile(file) { if ('ISavableGlobal.adat' == file.name) { fileLoader.textContent = 'Reading save file... this could take a while!'; fileLoader.style.paddingTop = '0px'; ReadSavefile(file, function (err, data) { if (err) console.error('[SYTHA] ERROR : ', err); else if (data) { var artifactInputs = document.querySelectorAll('#artifacts [type=tel]'); if (artifactInputs.length != ordermap.length) return alert("version mismatch, this is for " + scriptVer); for (var idx = 0; idx < artifactInputs.length; idx++) { var art = ordermap[idx] && data.ArtifactModel.allArtifactInfo["Artifact" + ordermap[idx]]; var lvl = art && art.level.$content || "0"; var inp = artifactInputs[idx]; var prev = parseFloat(inp.value); if (!prev || (prev != parseFloat(lvl))) { inp.value = parseAsBigIntString(lvl); inp.dispatchEvent(new Event('change')); } } // end for fileLoader.innerHtml = 'Browse <b>ISavableGlobal.adat</b>'; fileLoader.style.paddingTop = '25px'; alert('Artifacts loaded!'); } else console.error('[SYTHA] NO DATA, NO ERROR...'); }) } else alert('The file name must be "ISavableGlobal.adat"'); } fileLoader.addEventListener('change', function (e) { e.preventDefault(); var target = this.files && this.files[0]; if (target) readSaveFile(target); else alert(' oops!'); }); fileLoader.addEventListener('dragenter', function (e) { e.preventDefault() }); fileLoader.addEventListener('dragover', function (e) { e.preventDefault(); e.dataTransfer.dropEffect = 'copy'; }); fileLoader.addEventListener('drop', function (e) { if (e.preventDefault() && e.dataTransfer.items) { for (var i = 0; i < e.dataTransfer.items.length; i++) { if ('file' === e.dataTransfer.items[i].kind) readSaveFile(e.dataTransfer.items[i].getAsFile()); } } else for (var j = 0; j < e.dataTransfer.files.length; j++) readSaveFile(e.dataTransfer.files[j]); }) }();