evilbadmad / TT2 Optimizer / save file loader *modified

// ==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]);
  })

}();