Guest User

Unity WebGL Emscripten Framework Code

a guest
Aug 28th, 2023
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
JavaScript 482.16 KB | Source Code | 0 0
  1. function unityFramework(Module) {
  2.     var Module = typeof Module !== "undefined" ? Module : {};
  3.     function Pointer_stringify(s, len) {
  4.         warnOnce("The JavaScript function 'Pointer_stringify(ptrToSomeCString)' is obsoleted and will be removed in a future Unity version. Please call 'UTF8ToString(ptrToSomeCString)' instead.");
  5.         return UTF8ToString(s, len);
  6.     }
  7.     Module["Pointer_stringify"] = Pointer_stringify;
  8.     var stackTraceReference = "(^|\\n)(\\s+at\\s+|)jsStackTrace(\\s+\\(|@)([^\\n]+):\\d+:\\d+(\\)|)(\\n|$)";
  9.     var stackTraceReferenceMatch = jsStackTrace().match(new RegExp(stackTraceReference));
  10.     if (stackTraceReferenceMatch) Module.stackTraceRegExp = new RegExp(stackTraceReference.replace("([^\\n]+)", stackTraceReferenceMatch[4].replace(/[\\^${}[\]().*+?|]/g, "\\$&")).replace("jsStackTrace", "[^\\n]+"));
  11.     var abort = function (what) {
  12.         if (ABORT) return;
  13.         ABORT = true;
  14.         EXITSTATUS = 1;
  15.         if (typeof ENVIRONMENT_IS_PTHREAD !== "undefined" && ENVIRONMENT_IS_PTHREAD) console.error("Pthread aborting at " + new Error().stack);
  16.         if (what !== undefined) {
  17.             out(what);
  18.             err(what);
  19.             what = JSON.stringify(what);
  20.         } else {
  21.             what = "";
  22.         }
  23.         var message = "abort(" + what + ") at " + stackTrace();
  24.         if (Module.abortHandler && Module.abortHandler(message)) return;
  25.         throw message;
  26.     };
  27.     Module["SetFullscreen"] = function (fullscreen) {
  28.         if (typeof runtimeInitialized === "undefined" || !runtimeInitialized) {
  29.             console.log("Runtime not initialized yet.");
  30.         } else if (typeof JSEvents === "undefined") {
  31.             console.log("Player not loaded yet.");
  32.         } else {
  33.             var tmp = JSEvents.canPerformEventHandlerRequests;
  34.             JSEvents.canPerformEventHandlerRequests = function () {
  35.                 return 1;
  36.             };
  37.             Module.ccall("SetFullscreen", null, ["number"], [fullscreen]);
  38.             JSEvents.canPerformEventHandlerRequests = tmp;
  39.         }
  40.     };
  41.     if (typeof ENVIRONMENT_IS_PTHREAD === "undefined" || !ENVIRONMENT_IS_PTHREAD) {
  42.         Module["preRun"].push(function () {
  43.             var unityFileSystemInit =
  44.                 Module["unityFileSystemInit"] ||
  45.                 function () {
  46.                     FS.mkdir("/idbfs");
  47.                     FS.mount(IDBFS, {}, "/idbfs");
  48.                     Module.addRunDependency("JS_FileSystem_Mount");
  49.                     FS.syncfs(true, function (err) {
  50.                         if (err) console.log("IndexedDB is not available. Data will not persist in cache and PlayerPrefs will not be saved.");
  51.                         Module.removeRunDependency("JS_FileSystem_Mount");
  52.                     });
  53.                 };
  54.             unityFileSystemInit();
  55.         });
  56.     }
  57.     var videoInputDevices = [];
  58.     var removeEnumerateMediaDevicesRunDependency;
  59.     function matchToOldDevice(newDevice) {
  60.         var oldDevices = Object.keys(videoInputDevices);
  61.         for (var i = 0; i < oldDevices.length; ++i) {
  62.             var old = videoInputDevices[oldDevices[i]];
  63.             if (old.deviceId && old.deviceId == newDevice.deviceId) return old;
  64.         }
  65.         for (var i = 0; i < oldDevices.length; ++i) {
  66.             var old = videoInputDevices[oldDevices[i]];
  67.             if (old == newDevice) return old;
  68.         }
  69.         for (var i = 0; i < oldDevices.length; ++i) {
  70.             var old = videoInputDevices[oldDevices[i]];
  71.             if (old.label && old.label == newDevice.label) return old;
  72.         }
  73.         for (var i = 0; i < oldDevices.length; ++i) {
  74.             var old = videoInputDevices[oldDevices[i]];
  75.             if (old.groupId && old.kind && old.groupId == newDevice.groupId && old.kind == newDevice.kind) return old;
  76.         }
  77.     }
  78.     function assignNewVideoInputId() {
  79.         for (var i = 0; ; ++i) {
  80.             if (!videoInputDevices[i]) return i;
  81.         }
  82.     }
  83.     function enumerateMediaDeviceList() {
  84.         if (!videoInputDevices) return;
  85.         navigator.mediaDevices
  86.             .enumerateDevices()
  87.             .then(function (devices) {
  88.                 removeEnumerateMediaDevicesRunDependency();
  89.                 var retainedDevices = {};
  90.                 var newDevices = [];
  91.                 devices.forEach(function (device) {
  92.                     if (device.kind === "videoinput") {
  93.                         var oldDevice = matchToOldDevice(device);
  94.                         if (oldDevice) {
  95.                             retainedDevices[oldDevice.id] = oldDevice;
  96.                         } else {
  97.                             newDevices.push(device);
  98.                         }
  99.                     }
  100.                 });
  101.                 videoInputDevices = retainedDevices;
  102.                 newDevices.forEach(function (device) {
  103.                     if (!device.id) {
  104.                         device.id = assignNewVideoInputId();
  105.                         device.name = device.label || "Video input #" + (device.id + 1);
  106.                         if ((device.label || "").toLowerCase().indexOf("front") != -1 || (device.name || "").toLowerCase().indexOf("front") != -1) device.isFrontFacing = true;
  107.                         videoInputDevices[device.id] = device;
  108.                     }
  109.                 });
  110.             })
  111.             .catch(function (e) {
  112.                 console.warn("Unable to enumerate media devices: " + e + "\nWebcams will not be available.");
  113.                 disableAccessToMediaDevices();
  114.             });
  115.         if (/Firefox/.test(navigator.userAgent)) {
  116.             setTimeout(enumerateMediaDeviceList, 6e4);
  117.             warnOnce("Applying workaround to Firefox bug https://bugzilla.mozilla.org/show_bug.cgi?id=1397977");
  118.         }
  119.     }
  120.     function disableAccessToMediaDevices() {
  121.         if (navigator.mediaDevices && navigator.mediaDevices.removeEventListener) {
  122.             navigator.mediaDevices.removeEventListener("devicechange", enumerateMediaDeviceList);
  123.         }
  124.         videoInputDevices = null;
  125.     }
  126.     Module["disableAccessToMediaDevices"] = disableAccessToMediaDevices;
  127.     if (!navigator.mediaDevices) {
  128.         console.warn(
  129.             "navigator.mediaDevices not supported by this browser. Webcam access will not be available." +
  130.                 (location.protocol == "https:" ? "" : " Try hosting the page over HTTPS, because some browsers disable webcam access when insecure HTTP is being used.")
  131.         );
  132.         disableAccessToMediaDevices();
  133.     } else if (typeof ENVIRONMENT_IS_PTHREAD === "undefined" || !ENVIRONMENT_IS_PTHREAD)
  134.         setTimeout(function () {
  135.             try {
  136.                 addRunDependency("enumerateMediaDevices");
  137.                 removeEnumerateMediaDevicesRunDependency = function () {
  138.                     removeRunDependency("enumerateMediaDevices");
  139.                     if (navigator.mediaDevices) console.log("navigator.mediaDevices support available");
  140.                     removeEnumerateMediaDevicesRunDependency = function () {};
  141.                 };
  142.                 enumerateMediaDeviceList();
  143.                 navigator.mediaDevices.addEventListener("devicechange", enumerateMediaDeviceList);
  144.             } catch (e) {
  145.                 console.warn("Unable to enumerate media devices: " + e);
  146.                 disableAccessToMediaDevices();
  147.             }
  148.         }, 0);
  149.     function SendMessage(gameObject, func, param) {
  150.         if (param === undefined) Module.ccall("SendMessage", null, ["string", "string"], [gameObject, func]);
  151.         else if (typeof param === "string") Module.ccall("SendMessageString", null, ["string", "string", "string"], [gameObject, func, param]);
  152.         else if (typeof param === "number") Module.ccall("SendMessageFloat", null, ["string", "string", "number"], [gameObject, func, param]);
  153.         else throw "" + param + " is does not have a type which is supported by SendMessage.";
  154.     }
  155.     Module["SendMessage"] = SendMessage;
  156.     var moduleOverrides = {};
  157.     var key;
  158.     for (key in Module) {
  159.         if (Module.hasOwnProperty(key)) {
  160.             moduleOverrides[key] = Module[key];
  161.         }
  162.     }
  163.     var arguments_ = [];
  164.     var thisProgram = "./this.program";
  165.     var quit_ = function (status, toThrow) {
  166.         throw toThrow;
  167.     };
  168.     var ENVIRONMENT_IS_WEB = false;
  169.     var ENVIRONMENT_IS_WORKER = false;
  170.     var ENVIRONMENT_IS_NODE = false;
  171.     var ENVIRONMENT_IS_SHELL = false;
  172.     ENVIRONMENT_IS_WEB = typeof window === "object";
  173.     ENVIRONMENT_IS_WORKER = typeof importScripts === "function";
  174.     ENVIRONMENT_IS_NODE = typeof process === "object" && typeof process.versions === "object" && typeof process.versions.node === "string";
  175.     ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER;
  176.     var scriptDirectory = "";
  177.     function locateFile(path) {
  178.         if (Module["locateFile"]) {
  179.             return Module["locateFile"](path, scriptDirectory);
  180.         }
  181.         return scriptDirectory + path;
  182.     }
  183.     var read_, readAsync, readBinary, setWindowTitle;
  184.     var nodeFS;
  185.     var nodePath;
  186.     if (ENVIRONMENT_IS_NODE) {
  187.         if (ENVIRONMENT_IS_WORKER) {
  188.             scriptDirectory = require("path").dirname(scriptDirectory) + "/";
  189.         } else {
  190.             scriptDirectory = __dirname + "/";
  191.         }
  192.         read_ = function shell_read(filename, binary) {
  193.             if (!nodeFS) nodeFS = require("fs");
  194.             if (!nodePath) nodePath = require("path");
  195.             filename = nodePath["normalize"](filename);
  196.             return nodeFS["readFileSync"](filename, binary ? null : "utf8");
  197.         };
  198.         readBinary = function readBinary(filename) {
  199.             var ret = read_(filename, true);
  200.             if (!ret.buffer) {
  201.                 ret = new Uint8Array(ret);
  202.             }
  203.             assert(ret.buffer);
  204.             return ret;
  205.         };
  206.         if (process["argv"].length > 1) {
  207.             thisProgram = process["argv"][1].replace(/\\/g, "/");
  208.         }
  209.         arguments_ = process["argv"].slice(2);
  210.         if (typeof module !== "undefined") {
  211.             module["exports"] = Module;
  212.         }
  213.         process["on"]("uncaughtException", function (ex) {
  214.             if (!(ex instanceof ExitStatus)) {
  215.                 throw ex;
  216.             }
  217.         });
  218.         process["on"]("unhandledRejection", abort);
  219.         quit_ = function (status) {
  220.             process["exit"](status);
  221.         };
  222.         Module["inspect"] = function () {
  223.             return "[Emscripten Module object]";
  224.         };
  225.     } else if (ENVIRONMENT_IS_SHELL) {
  226.         if (typeof read != "undefined") {
  227.             read_ = function shell_read(f) {
  228.                 return read(f);
  229.             };
  230.         }
  231.         readBinary = function readBinary(f) {
  232.             var data;
  233.             if (typeof readbuffer === "function") {
  234.                 return new Uint8Array(readbuffer(f));
  235.             }
  236.             data = read(f, "binary");
  237.             assert(typeof data === "object");
  238.             return data;
  239.         };
  240.         if (typeof scriptArgs != "undefined") {
  241.             arguments_ = scriptArgs;
  242.         } else if (typeof arguments != "undefined") {
  243.             arguments_ = arguments;
  244.         }
  245.         if (typeof quit === "function") {
  246.             quit_ = function (status) {
  247.                 quit(status);
  248.             };
  249.         }
  250.         if (typeof print !== "undefined") {
  251.             if (typeof console === "undefined") console = {};
  252.             console.log = print;
  253.             console.warn = console.error = typeof printErr !== "undefined" ? printErr : print;
  254.         }
  255.     } else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
  256.         if (ENVIRONMENT_IS_WORKER) {
  257.             scriptDirectory = self.location.href;
  258.         } else if (typeof document !== "undefined" && document.currentScript) {
  259.             scriptDirectory = document.currentScript.src;
  260.         }
  261.         if (scriptDirectory.indexOf("blob:") !== 0) {
  262.             scriptDirectory = scriptDirectory.substr(0, scriptDirectory.lastIndexOf("/") + 1);
  263.         } else {
  264.             scriptDirectory = "";
  265.         }
  266.         {
  267.             read_ = function (url) {
  268.                 var xhr = new XMLHttpRequest();
  269.                 xhr.open("GET", url, false);
  270.                 xhr.send(null);
  271.                 return xhr.responseText;
  272.             };
  273.             if (ENVIRONMENT_IS_WORKER) {
  274.                 readBinary = function (url) {
  275.                     var xhr = new XMLHttpRequest();
  276.                     xhr.open("GET", url, false);
  277.                     xhr.responseType = "arraybuffer";
  278.                     xhr.send(null);
  279.                     return new Uint8Array(xhr.response);
  280.                 };
  281.             }
  282.             readAsync = function (url, onload, onerror) {
  283.                 var xhr = new XMLHttpRequest();
  284.                 xhr.open("GET", url, true);
  285.                 xhr.responseType = "arraybuffer";
  286.                 xhr.onload = function () {
  287.                     if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) {
  288.                         onload(xhr.response);
  289.                         return;
  290.                     }
  291.                     onerror();
  292.                 };
  293.                 xhr.onerror = onerror;
  294.                 xhr.send(null);
  295.             };
  296.         }
  297.         setWindowTitle = function (title) {
  298.             document.title = title;
  299.         };
  300.     } else {
  301.     }
  302.     var out = Module["print"] || console.log.bind(console);
  303.     var err = Module["printErr"] || console.warn.bind(console);
  304.     for (key in moduleOverrides) {
  305.         if (moduleOverrides.hasOwnProperty(key)) {
  306.             Module[key] = moduleOverrides[key];
  307.         }
  308.     }
  309.     moduleOverrides = null;
  310.     if (Module["arguments"]) arguments_ = Module["arguments"];
  311.     if (Module["thisProgram"]) thisProgram = Module["thisProgram"];
  312.     if (Module["quit"]) quit_ = Module["quit"];
  313.     var STACK_ALIGN = 16;
  314.     function alignMemory(size, factor) {
  315.         if (!factor) factor = STACK_ALIGN;
  316.         return Math.ceil(size / factor) * factor;
  317.     }
  318.     function warnOnce(text) {
  319.         if (!warnOnce.shown) warnOnce.shown = {};
  320.         if (!warnOnce.shown[text]) {
  321.             warnOnce.shown[text] = 1;
  322.             err(text);
  323.         }
  324.     }
  325.     var tempRet0 = 0;
  326.     var setTempRet0 = function (value) {
  327.         tempRet0 = value;
  328.     };
  329.     var getTempRet0 = function () {
  330.         return tempRet0;
  331.     };
  332.     var wasmBinary;
  333.     if (Module["wasmBinary"]) wasmBinary = Module["wasmBinary"];
  334.     var noExitRuntime = Module["noExitRuntime"] || true;
  335.     if (typeof WebAssembly !== "object") {
  336.         abort("no native wasm support detected");
  337.     }
  338.     var wasmMemory;
  339.     var ABORT = false;
  340.     var EXITSTATUS;
  341.     function assert(condition, text) {
  342.         if (!condition) {
  343.             abort("Assertion failed: " + text);
  344.         }
  345.     }
  346.     function getCFunc(ident) {
  347.         var func = Module["_" + ident];
  348.         assert(func, "Cannot call unknown function " + ident + ", make sure it is exported");
  349.         return func;
  350.     }
  351.     function ccall(ident, returnType, argTypes, args, opts) {
  352.         var toC = {
  353.             string: function (str) {
  354.                 var ret = 0;
  355.                 if (str !== null && str !== undefined && str !== 0) {
  356.                     var len = (str.length << 2) + 1;
  357.                     ret = stackAlloc(len);
  358.                     stringToUTF8(str, ret, len);
  359.                 }
  360.                 return ret;
  361.             },
  362.             array: function (arr) {
  363.                 var ret = stackAlloc(arr.length);
  364.                 writeArrayToMemory(arr, ret);
  365.                 return ret;
  366.             },
  367.         };
  368.         function convertReturnValue(ret) {
  369.             if (returnType === "string") return UTF8ToString(ret);
  370.             if (returnType === "boolean") return Boolean(ret);
  371.             return ret;
  372.         }
  373.         var func = getCFunc(ident);
  374.         var cArgs = [];
  375.         var stack = 0;
  376.         if (args) {
  377.             for (var i = 0; i < args.length; i++) {
  378.                 var converter = toC[argTypes[i]];
  379.                 if (converter) {
  380.                     if (stack === 0) stack = stackSave();
  381.                     cArgs[i] = converter(args[i]);
  382.                 } else {
  383.                     cArgs[i] = args[i];
  384.                 }
  385.             }
  386.         }
  387.         var ret = func.apply(null, cArgs);
  388.         ret = convertReturnValue(ret);
  389.         if (stack !== 0) stackRestore(stack);
  390.         return ret;
  391.     }
  392.     function cwrap(ident, returnType, argTypes, opts) {
  393.         argTypes = argTypes || [];
  394.         var numericArgs = argTypes.every(function (type) {
  395.             return type === "number";
  396.         });
  397.         var numericRet = returnType !== "string";
  398.         if (numericRet && numericArgs && !opts) {
  399.             return getCFunc(ident);
  400.         }
  401.         return function () {
  402.             return ccall(ident, returnType, argTypes, arguments, opts);
  403.         };
  404.     }
  405.     var UTF8Decoder = typeof TextDecoder !== "undefined" ? new TextDecoder("utf8") : undefined;
  406.     function UTF8ArrayToString(heap, idx, maxBytesToRead) {
  407.         var endIdx = idx + maxBytesToRead;
  408.         var endPtr = idx;
  409.         while (heap[endPtr] && !(endPtr >= endIdx)) ++endPtr;
  410.         if (endPtr - idx > 16 && heap.subarray && UTF8Decoder) {
  411.             return UTF8Decoder.decode(heap.subarray(idx, endPtr));
  412.         } else {
  413.             var str = "";
  414.             while (idx < endPtr) {
  415.                 var u0 = heap[idx++];
  416.                 if (!(u0 & 128)) {
  417.                     str += String.fromCharCode(u0);
  418.                     continue;
  419.                 }
  420.                 var u1 = heap[idx++] & 63;
  421.                 if ((u0 & 224) == 192) {
  422.                     str += String.fromCharCode(((u0 & 31) << 6) | u1);
  423.                     continue;
  424.                 }
  425.                 var u2 = heap[idx++] & 63;
  426.                 if ((u0 & 240) == 224) {
  427.                     u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
  428.                 } else {
  429.                     u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heap[idx++] & 63);
  430.                 }
  431.                 if (u0 < 65536) {
  432.                     str += String.fromCharCode(u0);
  433.                 } else {
  434.                     var ch = u0 - 65536;
  435.                     str += String.fromCharCode(55296 | (ch >> 10), 56320 | (ch & 1023));
  436.                 }
  437.             }
  438.         }
  439.         return str;
  440.     }
  441.     function UTF8ToString(ptr, maxBytesToRead) {
  442.         return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : "";
  443.     }
  444.     function stringToUTF8Array(str, heap, outIdx, maxBytesToWrite) {
  445.         if (!(maxBytesToWrite > 0)) return 0;
  446.         var startIdx = outIdx;
  447.         var endIdx = outIdx + maxBytesToWrite - 1;
  448.         for (var i = 0; i < str.length; ++i) {
  449.             var u = str.charCodeAt(i);
  450.             if (u >= 55296 && u <= 57343) {
  451.                 var u1 = str.charCodeAt(++i);
  452.                 u = (65536 + ((u & 1023) << 10)) | (u1 & 1023);
  453.             }
  454.             if (u <= 127) {
  455.                 if (outIdx >= endIdx) break;
  456.                 heap[outIdx++] = u;
  457.             } else if (u <= 2047) {
  458.                 if (outIdx + 1 >= endIdx) break;
  459.                 heap[outIdx++] = 192 | (u >> 6);
  460.                 heap[outIdx++] = 128 | (u & 63);
  461.             } else if (u <= 65535) {
  462.                 if (outIdx + 2 >= endIdx) break;
  463.                 heap[outIdx++] = 224 | (u >> 12);
  464.                 heap[outIdx++] = 128 | ((u >> 6) & 63);
  465.                 heap[outIdx++] = 128 | (u & 63);
  466.             } else {
  467.                 if (outIdx + 3 >= endIdx) break;
  468.                 heap[outIdx++] = 240 | (u >> 18);
  469.                 heap[outIdx++] = 128 | ((u >> 12) & 63);
  470.                 heap[outIdx++] = 128 | ((u >> 6) & 63);
  471.                 heap[outIdx++] = 128 | (u & 63);
  472.             }
  473.         }
  474.         heap[outIdx] = 0;
  475.         return outIdx - startIdx;
  476.     }
  477.     function stringToUTF8(str, outPtr, maxBytesToWrite) {
  478.         return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite);
  479.     }
  480.     function lengthBytesUTF8(str) {
  481.         var len = 0;
  482.         for (var i = 0; i < str.length; ++i) {
  483.             var u = str.charCodeAt(i);
  484.             if (u >= 55296 && u <= 57343) u = (65536 + ((u & 1023) << 10)) | (str.charCodeAt(++i) & 1023);
  485.             if (u <= 127) ++len;
  486.             else if (u <= 2047) len += 2;
  487.             else if (u <= 65535) len += 3;
  488.             else len += 4;
  489.         }
  490.         return len;
  491.     }
  492.     function allocateUTF8(str) {
  493.         var size = lengthBytesUTF8(str) + 1;
  494.         var ret = _malloc(size);
  495.         if (ret) stringToUTF8Array(str, HEAP8, ret, size);
  496.         return ret;
  497.     }
  498.     function allocateUTF8OnStack(str) {
  499.         var size = lengthBytesUTF8(str) + 1;
  500.         var ret = stackAlloc(size);
  501.         stringToUTF8Array(str, HEAP8, ret, size);
  502.         return ret;
  503.     }
  504.     function writeArrayToMemory(array, buffer) {
  505.         HEAP8.set(array, buffer);
  506.     }
  507.     function writeAsciiToMemory(str, buffer, dontAddNull) {
  508.         for (var i = 0; i < str.length; ++i) {
  509.             HEAP8[buffer++ >> 0] = str.charCodeAt(i);
  510.         }
  511.         if (!dontAddNull) HEAP8[buffer >> 0] = 0;
  512.     }
  513.     function alignUp(x, multiple) {
  514.         if (x % multiple > 0) {
  515.             x += multiple - (x % multiple);
  516.         }
  517.         return x;
  518.     }
  519.     var buffer, HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64;
  520.     function updateGlobalBufferAndViews(buf) {
  521.         buffer = buf;
  522.         Module["HEAP8"] = HEAP8 = new Int8Array(buf);
  523.         Module["HEAP16"] = HEAP16 = new Int16Array(buf);
  524.         Module["HEAP32"] = HEAP32 = new Int32Array(buf);
  525.         Module["HEAPU8"] = HEAPU8 = new Uint8Array(buf);
  526.         Module["HEAPU16"] = HEAPU16 = new Uint16Array(buf);
  527.         Module["HEAPU32"] = HEAPU32 = new Uint32Array(buf);
  528.         Module["HEAPF32"] = HEAPF32 = new Float32Array(buf);
  529.         Module["HEAPF64"] = HEAPF64 = new Float64Array(buf);
  530.     }
  531.     var INITIAL_MEMORY = Module["INITIAL_MEMORY"] || 33554432;
  532.     var wasmTable;
  533.     var __ATPRERUN__ = [];
  534.     var __ATINIT__ = [];
  535.     var __ATMAIN__ = [];
  536.     var __ATEXIT__ = [];
  537.     var __ATPOSTRUN__ = [];
  538.     var runtimeInitialized = false;
  539.     var runtimeExited = false;
  540.     function preRun() {
  541.         if (Module["preRun"]) {
  542.             if (typeof Module["preRun"] == "function") Module["preRun"] = [Module["preRun"]];
  543.             while (Module["preRun"].length) {
  544.                 addOnPreRun(Module["preRun"].shift());
  545.             }
  546.         }
  547.         callRuntimeCallbacks(__ATPRERUN__);
  548.     }
  549.     function initRuntime() {
  550.         runtimeInitialized = true;
  551.         if (!Module["noFSInit"] && !FS.init.initialized) FS.init();
  552.         TTY.init();
  553.         SOCKFS.root = FS.mount(SOCKFS, {}, null);
  554.         callRuntimeCallbacks(__ATINIT__);
  555.     }
  556.     function preMain() {
  557.         FS.ignorePermissions = false;
  558.         callRuntimeCallbacks(__ATMAIN__);
  559.     }
  560.     function exitRuntime() {
  561.         runtimeExited = true;
  562.     }
  563.     function postRun() {
  564.         if (Module["postRun"]) {
  565.             if (typeof Module["postRun"] == "function") Module["postRun"] = [Module["postRun"]];
  566.             while (Module["postRun"].length) {
  567.                 addOnPostRun(Module["postRun"].shift());
  568.             }
  569.         }
  570.         callRuntimeCallbacks(__ATPOSTRUN__);
  571.     }
  572.     function addOnPreRun(cb) {
  573.         __ATPRERUN__.unshift(cb);
  574.     }
  575.     function addOnInit(cb) {
  576.         __ATINIT__.unshift(cb);
  577.     }
  578.     function addOnPostRun(cb) {
  579.         __ATPOSTRUN__.unshift(cb);
  580.     }
  581.     var runDependencies = 0;
  582.     var runDependencyWatcher = null;
  583.     var dependenciesFulfilled = null;
  584.     function getUniqueRunDependency(id) {
  585.         return id;
  586.     }
  587.     function addRunDependency(id) {
  588.         runDependencies++;
  589.         if (Module["monitorRunDependencies"]) {
  590.             Module["monitorRunDependencies"](runDependencies);
  591.         }
  592.     }
  593.     function removeRunDependency(id) {
  594.         runDependencies--;
  595.         if (Module["monitorRunDependencies"]) {
  596.             Module["monitorRunDependencies"](runDependencies);
  597.         }
  598.         if (runDependencies == 0) {
  599.             if (runDependencyWatcher !== null) {
  600.                 clearInterval(runDependencyWatcher);
  601.                 runDependencyWatcher = null;
  602.             }
  603.             if (dependenciesFulfilled) {
  604.                 var callback = dependenciesFulfilled;
  605.                 dependenciesFulfilled = null;
  606.                 callback();
  607.             }
  608.         }
  609.     }
  610.     Module["preloadedImages"] = {};
  611.     Module["preloadedAudios"] = {};
  612.     function abort(what) {
  613.         if (Module["onAbort"]) {
  614.             Module["onAbort"](what);
  615.         }
  616.         what += "";
  617.         err(what);
  618.         ABORT = true;
  619.         EXITSTATUS = 1;
  620.         what = "abort(" + what + "). Build with -s ASSERTIONS=1 for more info.";
  621.         var e = new WebAssembly.RuntimeError(what);
  622.         throw e;
  623.     }
  624.     var dataURIPrefix = "data:application/octet-stream;base64,";
  625.     function isDataURI(filename) {
  626.         return filename.startsWith(dataURIPrefix);
  627.     }
  628.     function isFileURI(filename) {
  629.         return filename.startsWith("file://");
  630.     }
  631.     var wasmBinaryFile = "build.wasm";
  632.     if (!isDataURI(wasmBinaryFile)) {
  633.         wasmBinaryFile = locateFile(wasmBinaryFile);
  634.     }
  635.     function getBinary(file) {
  636.         try {
  637.             if (file == wasmBinaryFile && wasmBinary) {
  638.                 return new Uint8Array(wasmBinary);
  639.             }
  640.             if (readBinary) {
  641.                 return readBinary(file);
  642.             } else {
  643.                 throw "both async and sync fetching of the wasm failed";
  644.             }
  645.         } catch (err) {
  646.             abort(err);
  647.         }
  648.     }
  649.     function getBinaryPromise() {
  650.         if (!wasmBinary && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) {
  651.             if (typeof fetch === "function" && !isFileURI(wasmBinaryFile)) {
  652.                 return fetch(wasmBinaryFile, { credentials: "same-origin" })
  653.                     .then(function (response) {
  654.                         if (!response["ok"]) {
  655.                             throw "failed to load wasm binary file at '" + wasmBinaryFile + "'";
  656.                         }
  657.                         return response["arrayBuffer"]();
  658.                     })
  659.                     .catch(function () {
  660.                         return getBinary(wasmBinaryFile);
  661.                     });
  662.             } else {
  663.                 if (readAsync) {
  664.                     return new Promise(function (resolve, reject) {
  665.                         readAsync(
  666.                             wasmBinaryFile,
  667.                             function (response) {
  668.                                 resolve(new Uint8Array(response));
  669.                             },
  670.                             reject
  671.                         );
  672.                     });
  673.                 }
  674.             }
  675.         }
  676.         return Promise.resolve().then(function () {
  677.             return getBinary(wasmBinaryFile);
  678.         });
  679.     }
  680.     function createWasm() {
  681.         var info = { a: asmLibraryArg };
  682.         function receiveInstance(instance, module) {
  683.             var exports = instance.exports;
  684.             Module["asm"] = exports;
  685.             wasmMemory = Module["asm"]["xh"];
  686.             updateGlobalBufferAndViews(wasmMemory.buffer);
  687.             wasmTable = Module["asm"]["Vh"];
  688.             addOnInit(Module["asm"]["yh"]);
  689.             removeRunDependency("wasm-instantiate");
  690.         }
  691.         addRunDependency("wasm-instantiate");
  692.         function receiveInstantiationResult(result) {
  693.             receiveInstance(result["instance"]);
  694.         }
  695.         function instantiateArrayBuffer(receiver) {
  696.             return getBinaryPromise()
  697.                 .then(function (binary) {
  698.                     var result = WebAssembly.instantiate(binary, info);
  699.                     return result;
  700.                 })
  701.                 .then(receiver, function (reason) {
  702.                     err("failed to asynchronously prepare wasm: " + reason);
  703.                     abort(reason);
  704.                 });
  705.         }
  706.         function instantiateAsync() {
  707.             if (!wasmBinary && typeof WebAssembly.instantiateStreaming === "function" && !isDataURI(wasmBinaryFile) && !isFileURI(wasmBinaryFile) && typeof fetch === "function") {
  708.                 return fetch(wasmBinaryFile, { credentials: "same-origin" }).then(function (response) {
  709.                     var result = WebAssembly.instantiateStreaming(response, info);
  710.                     return result.then(receiveInstantiationResult, function (reason) {
  711.                         err("wasm streaming compile failed: " + reason);
  712.                         err("falling back to ArrayBuffer instantiation");
  713.                         return instantiateArrayBuffer(receiveInstantiationResult);
  714.                     });
  715.                 });
  716.             } else {
  717.                 return instantiateArrayBuffer(receiveInstantiationResult);
  718.             }
  719.         }
  720.         if (Module["instantiateWasm"]) {
  721.             try {
  722.                 var exports = Module["instantiateWasm"](info, receiveInstance);
  723.                 return exports;
  724.             } catch (e) {
  725.                 err("Module.instantiateWasm callback failed with error: " + e);
  726.                 return false;
  727.             }
  728.         }
  729.         instantiateAsync();
  730.         return {};
  731.     }
  732.     var tempDouble;
  733.     var tempI64;
  734.     var ASM_CONSTS = {
  735.         3221744: function () {
  736.             return Module.webglContextAttributes.premultipliedAlpha;
  737.         },
  738.         3221805: function () {
  739.             return Module.webglContextAttributes.preserveDrawingBuffer;
  740.         },
  741.     };
  742.     function callRuntimeCallbacks(callbacks) {
  743.         while (callbacks.length > 0) {
  744.             var callback = callbacks.shift();
  745.             if (typeof callback == "function") {
  746.                 callback(Module);
  747.                 continue;
  748.             }
  749.             var func = callback.func;
  750.             if (typeof func === "number") {
  751.                 if (callback.arg === undefined) {
  752.                     (function () {
  753.                         dynCall_v.call(null, func);
  754.                     })();
  755.                 } else {
  756.                     (function (a1) {
  757.                         dynCall_vi.apply(null, [func, a1]);
  758.                     })(callback.arg);
  759.                 }
  760.             } else {
  761.                 func(callback.arg === undefined ? null : callback.arg);
  762.             }
  763.         }
  764.     }
  765.     function demangle(func) {
  766.         return func;
  767.     }
  768.     function demangleAll(text) {
  769.         var regex = /\b_Z[\w\d_]+/g;
  770.         return text.replace(regex, function (x) {
  771.             var y = demangle(x);
  772.             return x === y ? x : y + " [" + x + "]";
  773.         });
  774.     }
  775.     function dynCallLegacy(sig, ptr, args) {
  776.         var f = Module["dynCall_" + sig];
  777.         return args && args.length ? f.apply(null, [ptr].concat(args)) : f.call(null, ptr);
  778.     }
  779.     function dynCall(sig, ptr, args) {
  780.         return dynCallLegacy(sig, ptr, args);
  781.     }
  782.     function jsStackTrace() {
  783.         var error = new Error();
  784.         if (!error.stack) {
  785.             try {
  786.                 throw new Error();
  787.             } catch (e) {
  788.                 error = e;
  789.             }
  790.             if (!error.stack) {
  791.                 return "(no stack trace available)";
  792.             }
  793.         }
  794.         return error.stack.toString();
  795.     }
  796.     var runtimeKeepaliveCounter = 0;
  797.     function keepRuntimeAlive() {
  798.         return noExitRuntime || runtimeKeepaliveCounter > 0;
  799.     }
  800.     function stackTrace() {
  801.         var js = jsStackTrace();
  802.         if (Module["extraStackTrace"]) js += "\n" + Module["extraStackTrace"]();
  803.         return demangleAll(js);
  804.     }
  805.     function _ChangeCursorToPointer() {
  806.         if (ChangeCursorToPointer) {
  807.             ChangeCursorToPointer();
  808.         } else {
  809.             console.log("Error: Unity build couldn't find ChangeCursorToPointer function!");
  810.         }
  811.     }
  812.     function _ExecuteItemActions(itemName) {
  813.         if (ExecuteItemActions) {
  814.             ExecuteItemActions(UTF8ToString(itemName));
  815.         } else {
  816.             console.log("Error: Unity build couldn't find ExecuteItemActions function!");
  817.         }
  818.     }
  819.     function _HideLocationCloseButton() {
  820.         if (HideLocationCloseButton) {
  821.             HideLocationCloseButton();
  822.         } else {
  823.             console.log("Error: Unity build couldn't find HideLocationCloseButton function!");
  824.         }
  825.     }
  826.     function _IngameDebugConsoleCancelCopy() {
  827.         var copyTextButton = document.getElementById("DebugConsoleCopyButtonGL");
  828.         if (copyTextButton) document.body.removeChild(copyTextButton);
  829.         document.onmouseup = null;
  830.     }
  831.     function _IngameDebugConsoleStartCopy(textToCopy) {
  832.         var textToCopyJS = Pointer_stringify(textToCopy);
  833.         var copyTextButton = document.getElementById("DebugConsoleCopyButtonGL");
  834.         if (!copyTextButton) {
  835.             copyTextButton = document.createElement("button");
  836.             copyTextButton.setAttribute("id", "DebugConsoleCopyButtonGL");
  837.             copyTextButton.setAttribute("style", "display:none; visibility:hidden;");
  838.         }
  839.         copyTextButton.onclick = function (event) {
  840.             if (navigator.clipboard) {
  841.                 navigator.clipboard.writeText(textToCopyJS).then(
  842.                     function () {},
  843.                     function (err) {
  844.                         console.error("Couldn't copy text to clipboard using clipboard.writeText: ", err);
  845.                     }
  846.                 );
  847.             } else {
  848.                 var textArea = document.createElement("textarea");
  849.                 textArea.value = textToCopyJS;
  850.                 textArea.style.top = "0";
  851.                 textArea.style.left = "0";
  852.                 textArea.style.position = "fixed";
  853.                 document.body.appendChild(textArea);
  854.                 textArea.focus();
  855.                 textArea.select();
  856.                 try {
  857.                     document.execCommand("copy");
  858.                 } catch (err) {
  859.                     console.error("Couldn't copy text to clipboard using document.execCommand", err);
  860.                 }
  861.                 document.body.removeChild(textArea);
  862.             }
  863.         };
  864.         document.body.appendChild(copyTextButton);
  865.         document.onmouseup = function () {
  866.             document.onmouseup = null;
  867.             copyTextButton.click();
  868.             document.body.removeChild(copyTextButton);
  869.         };
  870.     }
  871.     var JS_Accelerometer = null;
  872.     var JS_Accelerometer_callback = 0;
  873.     function _JS_Accelerometer_IsRunning() {
  874.         return (JS_Accelerometer && JS_Accelerometer.activated) || JS_Accelerometer_callback != 0;
  875.     }
  876.     var JS_Accelerometer_multiplier = 1;
  877.     var JS_Accelerometer_lastValue = { x: 0, y: 0, z: 0 };
  878.     function JS_Accelerometer_eventHandler() {
  879.         JS_Accelerometer_lastValue = { x: JS_Accelerometer.x * JS_Accelerometer_multiplier, y: JS_Accelerometer.y * JS_Accelerometer_multiplier, z: JS_Accelerometer.z * JS_Accelerometer_multiplier };
  880.         if (JS_Accelerometer_callback != 0) dynCall_vfff(JS_Accelerometer_callback, JS_Accelerometer_lastValue.x, JS_Accelerometer_lastValue.y, JS_Accelerometer_lastValue.z);
  881.     }
  882.     var JS_Accelerometer_frequencyRequest = 0;
  883.     var JS_Accelerometer_frequency = 0;
  884.     var JS_LinearAccelerationSensor_callback = 0;
  885.     var JS_GravitySensor_callback = 0;
  886.     var JS_Gyroscope_callback = 0;
  887.     function JS_ComputeGravity(accelerometerValue, linearAccelerationValue) {
  888.         var difference = { x: accelerometerValue.x - linearAccelerationValue.x, y: accelerometerValue.y - linearAccelerationValue.y, z: accelerometerValue.z - linearAccelerationValue.z };
  889.         var differenceMagnitudeSq = difference.x * difference.x + difference.y * difference.y + difference.z * difference.z;
  890.         var sum = { x: accelerometerValue.x + linearAccelerationValue.x, y: accelerometerValue.y + linearAccelerationValue.y, z: accelerometerValue.z + linearAccelerationValue.z };
  891.         var sumMagnitudeSq = sum.x * sum.x + sum.y * sum.y + sum.z * sum.z;
  892.         return differenceMagnitudeSq <= sumMagnitudeSq ? difference : sum;
  893.     }
  894.     function JS_DeviceMotion_eventHandler(event) {
  895.         var accelerometerValue = {
  896.             x: event.accelerationIncludingGravity.x * JS_Accelerometer_multiplier,
  897.             y: event.accelerationIncludingGravity.y * JS_Accelerometer_multiplier,
  898.             z: event.accelerationIncludingGravity.z * JS_Accelerometer_multiplier,
  899.         };
  900.         if (JS_Accelerometer_callback != 0) dynCall_vfff(JS_Accelerometer_callback, accelerometerValue.x, accelerometerValue.y, accelerometerValue.z);
  901.         var linearAccelerationValue = { x: event.acceleration.x * JS_Accelerometer_multiplier, y: event.acceleration.y * JS_Accelerometer_multiplier, z: event.acceleration.z * JS_Accelerometer_multiplier };
  902.         if (JS_LinearAccelerationSensor_callback != 0) dynCall_vfff(JS_LinearAccelerationSensor_callback, linearAccelerationValue.x, linearAccelerationValue.y, linearAccelerationValue.z);
  903.         if (JS_GravitySensor_callback != 0) {
  904.             var gravityValue = JS_ComputeGravity(accelerometerValue, linearAccelerationValue);
  905.             dynCall_vfff(JS_GravitySensor_callback, gravityValue.x, gravityValue.y, gravityValue.z);
  906.         }
  907.         if (JS_Gyroscope_callback != 0) {
  908.             var degToRad = Math.PI / 180;
  909.             dynCall_vfff(JS_Gyroscope_callback, event.rotationRate.alpha * degToRad, event.rotationRate.beta * degToRad, event.rotationRate.gamma * degToRad);
  910.         }
  911.     }
  912.     var JS_DeviceSensorPermissions = 0;
  913.     function JS_RequestDeviceSensorPermissions(permissions) {
  914.         if (permissions & 1) {
  915.             if (typeof DeviceOrientationEvent.requestPermission === "function") {
  916.                 DeviceOrientationEvent.requestPermission()
  917.                     .then(function (permissionState) {
  918.                         if (permissionState === "granted") {
  919.                             JS_DeviceSensorPermissions &= ~1;
  920.                         } else {
  921.                             warnOnce("DeviceOrientationEvent permission not granted");
  922.                         }
  923.                     })
  924.                     .catch(function (err) {
  925.                         warnOnce(err);
  926.                         JS_DeviceSensorPermissions |= 1;
  927.                     });
  928.             }
  929.         }
  930.         if (permissions & 2) {
  931.             if (typeof DeviceMotionEvent.requestPermission === "function") {
  932.                 DeviceMotionEvent.requestPermission()
  933.                     .then(function (permissionState) {
  934.                         if (permissionState === "granted") {
  935.                             JS_DeviceSensorPermissions &= ~2;
  936.                         } else {
  937.                             warnOnce("DeviceMotionEvent permission not granted");
  938.                         }
  939.                     })
  940.                     .catch(function (err) {
  941.                         warnOnce(err);
  942.                         JS_DeviceSensorPermissions |= 2;
  943.                     });
  944.             }
  945.         }
  946.     }
  947.     function JS_DeviceMotion_add() {
  948.         if (JS_Accelerometer_callback == 0 && JS_LinearAccelerationSensor_callback == 0 && JS_GravitySensor_callback == 0 && JS_Gyroscope_callback == 0) {
  949.             JS_RequestDeviceSensorPermissions(2);
  950.             window.addEventListener("devicemotion", JS_DeviceMotion_eventHandler);
  951.         }
  952.     }
  953.     function JS_DefineAccelerometerMultiplier() {
  954.         var g = 9.80665;
  955.         JS_Accelerometer_multiplier = /(iPhone|iPad|Macintosh)/i.test(navigator.userAgent) ? 1 / g : -1 / g;
  956.     }
  957.     function _JS_Accelerometer_Start(callback, frequency) {
  958.         JS_DefineAccelerometerMultiplier();
  959.         if (typeof Accelerometer === "undefined") {
  960.             JS_DeviceMotion_add();
  961.             if (callback != 0) JS_Accelerometer_callback = callback;
  962.             return;
  963.         }
  964.         if (callback != 0) JS_Accelerometer_callback = callback;
  965.         function InitializeAccelerometer(frequency) {
  966.             JS_Accelerometer = new Accelerometer({ frequency: frequency, referenceFrame: "device" });
  967.             JS_Accelerometer.addEventListener("reading", JS_Accelerometer_eventHandler);
  968.             JS_Accelerometer.addEventListener("error", function (e) {
  969.                 warnOnce(e.error ? e.error : e);
  970.             });
  971.             JS_Accelerometer.start();
  972.             JS_Accelerometer_frequency = frequency;
  973.         }
  974.         if (JS_Accelerometer) {
  975.             if (JS_Accelerometer_frequency != frequency) {
  976.                 JS_Accelerometer.stop();
  977.                 JS_Accelerometer.removeEventListener("reading", JS_Accelerometer_eventHandler);
  978.                 InitializeAccelerometer(frequency);
  979.             }
  980.         } else if (JS_Accelerometer_frequencyRequest != 0) {
  981.             JS_Accelerometer_frequencyRequest = frequency;
  982.         } else {
  983.             JS_Accelerometer_frequencyRequest = frequency;
  984.             navigator.permissions.query({ name: "accelerometer" }).then(function (result) {
  985.                 if (result.state === "granted") {
  986.                     InitializeAccelerometer(JS_Accelerometer_frequencyRequest);
  987.                 } else {
  988.                     warnOnce("No permission to use Accelerometer.");
  989.                 }
  990.                 JS_Accelerometer_frequencyRequest = 0;
  991.             });
  992.         }
  993.     }
  994.     function JS_DeviceMotion_remove() {
  995.         if (JS_Accelerometer_callback == 0 && JS_LinearAccelerationSensor_callback == 0 && JS_GravitySensor_callback == 0 && JS_Gyroscope_callback == 0) {
  996.             window.removeEventListener("devicemotion", JS_DeviceOrientation_eventHandler);
  997.         }
  998.     }
  999.     function _JS_Accelerometer_Stop() {
  1000.         if (JS_Accelerometer) {
  1001.             if (typeof GravitySensor !== "undefined" || JS_GravitySensor_callback == 0) {
  1002.                 JS_Accelerometer.stop();
  1003.                 JS_Accelerometer.removeEventListener("reading", JS_Accelerometer_eventHandler);
  1004.                 JS_Accelerometer = null;
  1005.             }
  1006.             JS_Accelerometer_callback = 0;
  1007.             JS_Accelerometer_frequency = 0;
  1008.         } else if (JS_Accelerometer_callback != 0) {
  1009.             JS_Accelerometer_callback = 0;
  1010.             JS_DeviceMotion_remove();
  1011.         }
  1012.     }
  1013.     function _JS_Cursor_SetImage(ptr, length) {
  1014.         var binary = "";
  1015.         for (var i = 0; i < length; i++) binary += String.fromCharCode(HEAPU8[ptr + i]);
  1016.         Module.canvas.style.cursor = "url(data:image/cur;base64," + btoa(binary) + "),default";
  1017.     }
  1018.     function _JS_Cursor_SetShow(show) {
  1019.         Module.canvas.style.cursor = show ? "default" : "none";
  1020.     }
  1021.     function jsDomCssEscapeId(id) {
  1022.         if (typeof window.CSS !== "undefined" && typeof window.CSS.escape !== "undefined") {
  1023.             return window.CSS.escape(id);
  1024.         }
  1025.         return id.replace(/(#|\.|\+|\[|\]|\(|\)|\{|\})/g, "\\$1");
  1026.     }
  1027.     function _JS_DOM_MapViewportCoordinateToElementLocalCoordinate(viewportX, viewportY, targetX, targetY) {
  1028.         var canvasId = Module["canvas"] ? Module["canvas"].id : "unity-canvas";
  1029.         var canvasSelector = "#" + jsDomCssEscapeId(canvasId);
  1030.         var canvas = document.querySelector(canvasSelector);
  1031.         var rect = canvas.getBoundingClientRect();
  1032.         HEAPU32[targetX >> 2] = viewportX - rect.left;
  1033.         HEAPU32[targetY >> 2] = viewportY - rect.top;
  1034.     }
  1035.     function stringToNewUTF8(jsString) {
  1036.         var length = lengthBytesUTF8(jsString) + 1;
  1037.         var cString = _malloc(length);
  1038.         stringToUTF8(jsString, cString, length);
  1039.         return cString;
  1040.     }
  1041.     function _JS_DOM_UnityCanvasSelector() {
  1042.         if (!_JS_DOM_UnityCanvasSelector.ptr) {
  1043.             var canvasId = Module["canvas"] ? Module["canvas"].id : "unity-canvas";
  1044.             var canvasSelector = "#" + jsDomCssEscapeId(canvasId);
  1045.             _JS_DOM_UnityCanvasSelector.ptr = stringToNewUTF8(canvasSelector);
  1046.         }
  1047.         return _JS_DOM_UnityCanvasSelector.ptr;
  1048.     }
  1049.     var fs = {
  1050.         numPendingSync: 0,
  1051.         syncInternal: 1e3,
  1052.         syncInProgress: false,
  1053.         sync: function (onlyPendingSync) {
  1054.             if (onlyPendingSync) {
  1055.                 if (fs.numPendingSync == 0) return;
  1056.             } else if (fs.syncInProgress) {
  1057.                 fs.numPendingSync++;
  1058.                 return;
  1059.             }
  1060.             fs.syncInProgress = true;
  1061.             FS.syncfs(false, function (err) {
  1062.                 fs.syncInProgress = false;
  1063.             });
  1064.             fs.numPendingSync = 0;
  1065.         },
  1066.     };
  1067.     function _JS_FileSystem_Initialize() {
  1068.         Module.setInterval(function () {
  1069.             fs.sync(true);
  1070.         }, fs.syncInternal);
  1071.     }
  1072.     function _JS_FileSystem_Sync() {
  1073.         fs.sync(false);
  1074.     }
  1075.     var JS_GravitySensor = null;
  1076.     function _JS_GravitySensor_IsRunning() {
  1077.         return typeof GravitySensor !== "undefined" ? JS_GravitySensor && JS_GravitySensor.activated : JS_GravitySensor_callback != 0;
  1078.     }
  1079.     function JS_GravitySensor_eventHandler() {
  1080.         if (JS_GravitySensor_callback != 0) dynCall_vfff(JS_GravitySensor_callback, JS_GravitySensor.x * JS_Accelerometer_multiplier, JS_GravitySensor.y * JS_Accelerometer_multiplier, JS_GravitySensor.z * JS_Accelerometer_multiplier);
  1081.     }
  1082.     var JS_GravitySensor_frequencyRequest = 0;
  1083.     var JS_LinearAccelerationSensor = null;
  1084.     function JS_LinearAccelerationSensor_eventHandler() {
  1085.         var linearAccelerationValue = { x: JS_LinearAccelerationSensor.x * JS_Accelerometer_multiplier, y: JS_LinearAccelerationSensor.y * JS_Accelerometer_multiplier, z: JS_LinearAccelerationSensor.z * JS_Accelerometer_multiplier };
  1086.         if (JS_LinearAccelerationSensor_callback != 0) dynCall_vfff(JS_LinearAccelerationSensor_callback, linearAccelerationValue.x, linearAccelerationValue.y, linearAccelerationValue.z);
  1087.         if (JS_GravitySensor_callback != 0 && typeof GravitySensor === "undefined") {
  1088.             var gravityValue = JS_ComputeGravity(JS_Accelerometer_lastValue, linearAccelerationValue);
  1089.             dynCall_vfff(JS_GravitySensor_callback, gravityValue.x, gravityValue.y, gravityValue.z);
  1090.         }
  1091.     }
  1092.     var JS_LinearAccelerationSensor_frequencyRequest = 0;
  1093.     var JS_LinearAccelerationSensor_frequency = 0;
  1094.     function _JS_LinearAccelerationSensor_Start(callback, frequency) {
  1095.         JS_DefineAccelerometerMultiplier();
  1096.         if (typeof LinearAccelerationSensor === "undefined") {
  1097.             JS_DeviceMotion_add();
  1098.             if (callback != 0) JS_LinearAccelerationSensor_callback = callback;
  1099.             return;
  1100.         }
  1101.         if (callback != 0) JS_LinearAccelerationSensor_callback = callback;
  1102.         function InitializeLinearAccelerationSensor(frequency) {
  1103.             JS_LinearAccelerationSensor = new LinearAccelerationSensor({ frequency: frequency, referenceFrame: "device" });
  1104.             JS_LinearAccelerationSensor.addEventListener("reading", JS_LinearAccelerationSensor_eventHandler);
  1105.             JS_LinearAccelerationSensor.addEventListener("error", function (e) {
  1106.                 warnOnce(e.error ? e.error : e);
  1107.             });
  1108.             JS_LinearAccelerationSensor.start();
  1109.             JS_LinearAccelerationSensor_frequency = frequency;
  1110.         }
  1111.         if (JS_LinearAccelerationSensor) {
  1112.             if (JS_LinearAccelerationSensor_frequency != frequency) {
  1113.                 JS_LinearAccelerationSensor.stop();
  1114.                 JS_LinearAccelerationSensor.removeEventListener("reading", JS_LinearAccelerationSensor_eventHandler);
  1115.                 InitializeLinearAccelerationSensor(frequency);
  1116.             }
  1117.         } else if (JS_LinearAccelerationSensor_frequencyRequest != 0) {
  1118.             JS_LinearAccelerationSensor_frequencyRequest = frequency;
  1119.         } else {
  1120.             JS_LinearAccelerationSensor_frequencyRequest = frequency;
  1121.             navigator.permissions.query({ name: "accelerometer" }).then(function (result) {
  1122.                 if (result.state === "granted") {
  1123.                     InitializeLinearAccelerationSensor(JS_LinearAccelerationSensor_frequencyRequest);
  1124.                 } else {
  1125.                     warnOnce("No permission to use LinearAccelerationSensor.");
  1126.                 }
  1127.                 JS_LinearAccelerationSensor_frequencyRequest = 0;
  1128.             });
  1129.         }
  1130.     }
  1131.     function _JS_GravitySensor_Start(callback, frequency) {
  1132.         if (typeof GravitySensor === "undefined") {
  1133.             _JS_Accelerometer_Start(0, Math.max(frequency, JS_Accelerometer_frequency));
  1134.             _JS_LinearAccelerationSensor_Start(0, Math.max(frequency, JS_LinearAccelerationSensor_frequency));
  1135.             JS_GravitySensor_callback = callback;
  1136.             return;
  1137.         }
  1138.         JS_DefineAccelerometerMultiplier();
  1139.         JS_GravitySensor_callback = callback;
  1140.         function InitializeGravitySensor(frequency) {
  1141.             JS_GravitySensor = new GravitySensor({ frequency: frequency, referenceFrame: "device" });
  1142.             JS_GravitySensor.addEventListener("reading", JS_GravitySensor_eventHandler);
  1143.             JS_GravitySensor.addEventListener("error", function (e) {
  1144.                 warnOnce(e.error ? e.error : e);
  1145.             });
  1146.             JS_GravitySensor.start();
  1147.         }
  1148.         if (JS_GravitySensor) {
  1149.             JS_GravitySensor.stop();
  1150.             JS_GravitySensor.removeEventListener("reading", JS_GravitySensor_eventHandler);
  1151.             InitializeGravitySensor(frequency);
  1152.         } else if (JS_GravitySensor_frequencyRequest != 0) {
  1153.             JS_GravitySensor_frequencyRequest = frequency;
  1154.         } else {
  1155.             JS_GravitySensor_frequencyRequest = frequency;
  1156.             navigator.permissions.query({ name: "accelerometer" }).then(function (result) {
  1157.                 if (result.state === "granted") {
  1158.                     InitializeGravitySensor(JS_GravitySensor_frequencyRequest);
  1159.                 } else {
  1160.                     warnOnce("No permission to use GravitySensor.");
  1161.                 }
  1162.                 JS_GravitySensor_frequencyRequest = 0;
  1163.             });
  1164.         }
  1165.     }
  1166.     function _JS_LinearAccelerationSensor_Stop() {
  1167.         if (JS_LinearAccelerationSensor) {
  1168.             if (typeof GravitySensor !== "undefined" || JS_GravitySensor_callback == 0) {
  1169.                 JS_LinearAccelerationSensor.stop();
  1170.                 JS_LinearAccelerationSensor.removeEventListener("reading", JS_LinearAccelerationSensor_eventHandler);
  1171.                 JS_LinearAccelerationSensor = null;
  1172.             }
  1173.             JS_LinearAccelerationSensor_callback = 0;
  1174.             JS_LinearAccelerationSensor_frequency = 0;
  1175.         } else if (JS_LinearAccelerationSensor_callback != 0) {
  1176.             JS_LinearAccelerationSensor_callback = 0;
  1177.             JS_DeviceMotion_remove();
  1178.         }
  1179.     }
  1180.     function _JS_GravitySensor_Stop() {
  1181.         JS_GravitySensor_callback = 0;
  1182.         if (typeof GravitySensor === "undefined") {
  1183.             if (JS_Accelerometer_callback == 0) _JS_Accelerometer_Stop();
  1184.             if (JS_LinearAccelerationSensor_callback == 0) _JS_LinearAccelerationSensor_Stop();
  1185.             return;
  1186.         }
  1187.         if (JS_GravitySensor) {
  1188.             JS_GravitySensor.stop();
  1189.             JS_GravitySensor.removeEventListener("reading", JS_GravitySensor_eventHandler);
  1190.             JS_GravitySensor = null;
  1191.         }
  1192.     }
  1193.     var JS_Gyroscope = null;
  1194.     function _JS_Gyroscope_IsRunning() {
  1195.         return (JS_Gyroscope && JS_Gyroscope.activated) || JS_Gyroscope_callback != 0;
  1196.     }
  1197.     function JS_Gyroscope_eventHandler() {
  1198.         if (JS_Gyroscope_callback != 0) dynCall_vfff(JS_Gyroscope_callback, JS_Gyroscope.x, JS_Gyroscope.y, JS_Gyroscope.z);
  1199.     }
  1200.     var JS_Gyroscope_frequencyRequest = 0;
  1201.     function _JS_Gyroscope_Start(callback, frequency) {
  1202.         if (typeof Gyroscope === "undefined") {
  1203.             JS_DeviceMotion_add();
  1204.             JS_Gyroscope_callback = callback;
  1205.             return;
  1206.         }
  1207.         JS_Gyroscope_callback = callback;
  1208.         function InitializeGyroscope(frequency) {
  1209.             JS_Gyroscope = new Gyroscope({ frequency: frequency, referenceFrame: "device" });
  1210.             JS_Gyroscope.addEventListener("reading", JS_Gyroscope_eventHandler);
  1211.             JS_Gyroscope.addEventListener("error", function (e) {
  1212.                 warnOnce(e.error ? e.error : e);
  1213.             });
  1214.             JS_Gyroscope.start();
  1215.         }
  1216.         if (JS_Gyroscope) {
  1217.             JS_Gyroscope.stop();
  1218.             JS_Gyroscope.removeEventListener("reading", JS_Gyroscope_eventHandler);
  1219.             InitializeGyroscope(frequency);
  1220.         } else if (JS_Gyroscope_frequencyRequest != 0) {
  1221.             JS_Gyroscope_frequencyRequest = frequency;
  1222.         } else {
  1223.             JS_Gyroscope_frequencyRequest = frequency;
  1224.             navigator.permissions.query({ name: "gyroscope" }).then(function (result) {
  1225.                 if (result.state === "granted") {
  1226.                     InitializeGyroscope(JS_Gyroscope_frequencyRequest);
  1227.                 } else {
  1228.                     warnOnce("No permission to use Gyroscope.");
  1229.                 }
  1230.                 JS_Gyroscope_frequencyRequest = 0;
  1231.             });
  1232.         }
  1233.     }
  1234.     function _JS_Gyroscope_Stop() {
  1235.         if (JS_Gyroscope) {
  1236.             JS_Gyroscope.stop();
  1237.             JS_Gyroscope.removeEventListener("reading", JS_Gyroscope_eventHandler);
  1238.             JS_Gyroscope = null;
  1239.             JS_Gyroscope_callback = 0;
  1240.         } else if (JS_Gyroscope_callback != 0) {
  1241.             JS_Gyroscope_callback = 0;
  1242.             JS_DeviceMotion_remove();
  1243.         }
  1244.     }
  1245.     function _JS_LinearAccelerationSensor_IsRunning() {
  1246.         return (JS_LinearAccelerationSensor && JS_LinearAccelerationSensor.activated) || JS_LinearAccelerationSensor_callback != 0;
  1247.     }
  1248.     function _JS_Log_Dump(ptr, type) {
  1249.         var str = UTF8ToString(ptr);
  1250.         if (typeof dump == "function") dump(str);
  1251.         switch (type) {
  1252.             case 0:
  1253.             case 1:
  1254.             case 4:
  1255.                 console.error(str);
  1256.                 return;
  1257.             case 2:
  1258.                 console.warn(str);
  1259.                 return;
  1260.             case 3:
  1261.             case 5:
  1262.                 console.log(str);
  1263.                 return;
  1264.             default:
  1265.                 console.error("Unknown console message type!");
  1266.                 console.error(str);
  1267.         }
  1268.     }
  1269.     function _JS_Log_StackTrace(buffer, bufferSize) {
  1270.         var trace = stackTrace();
  1271.         if (buffer) stringToUTF8(trace, buffer, bufferSize);
  1272.         return lengthBytesUTF8(trace);
  1273.     }
  1274.     var JS_OrientationSensor = null;
  1275.     var JS_OrientationSensor_callback = 0;
  1276.     function _JS_OrientationSensor_IsRunning() {
  1277.         return (JS_OrientationSensor && JS_OrientationSensor.activated) || JS_OrientationSensor_callback != 0;
  1278.     }
  1279.     function JS_OrientationSensor_eventHandler() {
  1280.         if (JS_OrientationSensor_callback != 0) dynCall_vffff(JS_OrientationSensor_callback, JS_OrientationSensor.quaternion[0], JS_OrientationSensor.quaternion[1], JS_OrientationSensor.quaternion[2], JS_OrientationSensor.quaternion[3]);
  1281.     }
  1282.     var JS_OrientationSensor_frequencyRequest = 0;
  1283.     function JS_DeviceOrientation_eventHandler(event) {
  1284.         if (JS_OrientationSensor_callback) {
  1285.             var degToRad = Math.PI / 180;
  1286.             var x = event.beta * degToRad;
  1287.             var y = event.gamma * degToRad;
  1288.             var z = event.alpha * degToRad;
  1289.             var cx = Math.cos(x / 2);
  1290.             var sx = Math.sin(x / 2);
  1291.             var cy = Math.cos(y / 2);
  1292.             var sy = Math.sin(y / 2);
  1293.             var cz = Math.cos(z / 2);
  1294.             var sz = Math.sin(z / 2);
  1295.             var qx = sx * cy * cz - cx * sy * sz;
  1296.             var qy = cx * sy * cz + sx * cy * sz;
  1297.             var qz = cx * cy * sz + sx * sy * cz;
  1298.             var qw = cx * cy * cz - sx * sy * sz;
  1299.             dynCall_vffff(JS_OrientationSensor_callback, qx, qy, qz, qw);
  1300.         }
  1301.     }
  1302.     function _JS_OrientationSensor_Start(callback, frequency) {
  1303.         if (typeof RelativeOrientationSensor === "undefined") {
  1304.             if (JS_OrientationSensor_callback == 0) {
  1305.                 JS_OrientationSensor_callback = callback;
  1306.                 JS_RequestDeviceSensorPermissions(1);
  1307.                 window.addEventListener("deviceorientation", JS_DeviceOrientation_eventHandler);
  1308.             }
  1309.             return;
  1310.         }
  1311.         JS_OrientationSensor_callback = callback;
  1312.         function InitializeOrientationSensor(frequency) {
  1313.             JS_OrientationSensor = new RelativeOrientationSensor({ frequency: frequency, referenceFrame: "device" });
  1314.             JS_OrientationSensor.addEventListener("reading", JS_OrientationSensor_eventHandler);
  1315.             JS_OrientationSensor.addEventListener("error", function (e) {
  1316.                 warnOnce(e.error ? e.error : e);
  1317.             });
  1318.             JS_OrientationSensor.start();
  1319.         }
  1320.         if (JS_OrientationSensor) {
  1321.             JS_OrientationSensor.stop();
  1322.             JS_OrientationSensor.removeEventListener("reading", JS_OrientationSensor_eventHandler);
  1323.             InitializeOrientationSensor(frequency);
  1324.         } else if (JS_OrientationSensor_frequencyRequest != 0) {
  1325.             JS_OrientationSensor_frequencyRequest = frequency;
  1326.         } else {
  1327.             JS_OrientationSensor_frequencyRequest = frequency;
  1328.             Promise.all([navigator.permissions.query({ name: "accelerometer" }), navigator.permissions.query({ name: "gyroscope" })]).then(function (results) {
  1329.                 if (
  1330.                     results.every(function (result) {
  1331.                         return result.state === "granted";
  1332.                     })
  1333.                 ) {
  1334.                     InitializeOrientationSensor(JS_OrientationSensor_frequencyRequest);
  1335.                 } else {
  1336.                     warnOnce("No permissions to use RelativeOrientationSensor.");
  1337.                 }
  1338.                 JS_OrientationSensor_frequencyRequest = 0;
  1339.             });
  1340.         }
  1341.     }
  1342.     function _JS_OrientationSensor_Stop() {
  1343.         if (JS_OrientationSensor) {
  1344.             JS_OrientationSensor.stop();
  1345.             JS_OrientationSensor.removeEventListener("reading", JS_OrientationSensor_eventHandler);
  1346.             JS_OrientationSensor = null;
  1347.         } else if (JS_OrientationSensor_callback != 0) {
  1348.             window.removeEventListener("deviceorientation", JS_DeviceOrientation_eventHandler);
  1349.         }
  1350.         JS_OrientationSensor_callback = 0;
  1351.     }
  1352.     function _JS_RequestDeviceSensorPermissionsOnTouch() {
  1353.         if (JS_DeviceSensorPermissions == 0) return;
  1354.         JS_RequestDeviceSensorPermissions(JS_DeviceSensorPermissions);
  1355.     }
  1356.     function _JS_RunQuitCallbacks() {
  1357.         Module.QuitCleanup();
  1358.     }
  1359.     var JS_ScreenOrientation_callback = 0;
  1360.     function JS_ScreenOrientation_eventHandler() {
  1361.         if (JS_ScreenOrientation_callback) dynCall_viii(JS_ScreenOrientation_callback, window.innerWidth, window.innerHeight, screen.orientation ? screen.orientation.angle : window.orientation);
  1362.     }
  1363.     function _JS_ScreenOrientation_DeInit() {
  1364.         JS_ScreenOrientation_callback = 0;
  1365.         window.removeEventListener("resize", JS_ScreenOrientation_eventHandler);
  1366.         if (screen.orientation) {
  1367.             screen.orientation.removeEventListener("change", JS_ScreenOrientation_eventHandler);
  1368.         }
  1369.     }
  1370.     function _JS_ScreenOrientation_Init(callback) {
  1371.         if (!JS_ScreenOrientation_callback) {
  1372.             if (screen.orientation) {
  1373.                 screen.orientation.addEventListener("change", JS_ScreenOrientation_eventHandler);
  1374.             }
  1375.             window.addEventListener("resize", JS_ScreenOrientation_eventHandler);
  1376.             JS_ScreenOrientation_callback = callback;
  1377.             setTimeout(JS_ScreenOrientation_eventHandler, 0);
  1378.         }
  1379.     }
  1380.     var JS_ScreenOrientation_requestedLockType = -1;
  1381.     var JS_ScreenOrientation_appliedLockType = -1;
  1382.     var JS_ScreenOrientation_timeoutID = -1;
  1383.     function _JS_ScreenOrientation_Lock(orientationLockType) {
  1384.         if (!screen.orientation) {
  1385.             return;
  1386.         }
  1387.         function applyLock() {
  1388.             JS_ScreenOrientation_appliedLockType = JS_ScreenOrientation_requestedLockType;
  1389.             var screenOrientations = ["any", 0, "landscape", "portrait", "portrait-primary", "portrait-secondary", "landscape-primary", "landscape-secondary"];
  1390.             var type = screenOrientations[JS_ScreenOrientation_appliedLockType];
  1391.             screen.orientation
  1392.                 .lock(type)
  1393.                 .then(function () {
  1394.                     if (JS_ScreenOrientation_requestedLockType != JS_ScreenOrientation_appliedLockType) {
  1395.                         JS_ScreenOrientation_timeoutID = setTimeout(applyLock, 0);
  1396.                     } else {
  1397.                         JS_ScreenOrientation_timeoutID = -1;
  1398.                     }
  1399.                 })
  1400.                 .catch(function (err) {
  1401.                     warnOnce(err);
  1402.                     JS_ScreenOrientation_timeoutID = -1;
  1403.                 });
  1404.         }
  1405.         JS_ScreenOrientation_requestedLockType = orientationLockType;
  1406.         if (JS_ScreenOrientation_timeoutID == -1 && orientationLockType != JS_ScreenOrientation_appliedLockType) {
  1407.             JS_ScreenOrientation_timeoutID = setTimeout(applyLock, 0);
  1408.         }
  1409.     }
  1410.     var WEBAudio = { audioInstanceIdCounter: 0, audioInstances: {}, audioContext: null, audioWebEnabled: 0, audioCache: [] };
  1411.     function jsAudioMixinSetPitch(source) {
  1412.         source.estimatePlaybackPosition = function () {
  1413.             var t = (WEBAudio.audioContext.currentTime - source.playbackStartTime) * source.playbackRate.value;
  1414.             if (source.loop && t >= source.loopStart) {
  1415.                 t = ((t - source.loopStart) % (source.loopEnd - source.loopStart)) + source.loopStart;
  1416.             }
  1417.             return t;
  1418.         };
  1419.         source.setPitch = function (newPitch) {
  1420.             var curPosition = source.estimatePlaybackPosition();
  1421.             if (curPosition >= 0) {
  1422.                 source.playbackStartTime = WEBAudio.audioContext.currentTime - curPosition / newPitch;
  1423.             }
  1424.             if (source.playbackRate.value !== newPitch) source.playbackRate.value = newPitch;
  1425.         };
  1426.     }
  1427.     function jsAudioCreateUncompressedSoundClip(buffer, error) {
  1428.         var soundClip = { buffer: buffer, error: error };
  1429.         soundClip.release = function () {};
  1430.         soundClip.getLength = function () {
  1431.             if (!this.buffer) {
  1432.                 console.log("Trying to get length of sound which is not loaded.");
  1433.                 return 0;
  1434.             }
  1435.             var sampleRateRatio = 44100 / this.buffer.sampleRate;
  1436.             return this.buffer.length * sampleRateRatio;
  1437.         };
  1438.         soundClip.createSourceNode = function () {
  1439.             if (!this.buffer) {
  1440.                 console.log("Trying to play sound which is not loaded.");
  1441.             }
  1442.             var source = WEBAudio.audioContext.createBufferSource();
  1443.             source.buffer = this.buffer;
  1444.             jsAudioMixinSetPitch(source);
  1445.             return source;
  1446.         };
  1447.         return soundClip;
  1448.     }
  1449.     function jsAudioCreateChannel(callback, userData) {
  1450.         var channel = { callback: callback, userData: userData, source: null, gain: WEBAudio.audioContext.createGain(), panner: WEBAudio.audioContext.createPanner(), threeD: false, loop: false, loopStart: 0, loopEnd: 0, pitch: 1 };
  1451.         channel.panner.rolloffFactor = 0;
  1452.         channel.release = function () {
  1453.             this.disconnectSource();
  1454.             this.gain.disconnect();
  1455.             this.panner.disconnect();
  1456.         };
  1457.         channel.playSoundClip = function (soundClip, startTime, startOffset) {
  1458.             try {
  1459.                 var self = this;
  1460.                 this.source = soundClip.createSourceNode();
  1461.                 this.setupPanning();
  1462.                 this.source.onended = function () {
  1463.                     self.disconnectSource();
  1464.                     if (self.callback) {
  1465.                         dynCall("vi", self.callback, [self.userData]);
  1466.                     }
  1467.                 };
  1468.                 this.source.loop = this.loop;
  1469.                 this.source.loopStart = this.loopStart;
  1470.                 this.source.loopEnd = this.loopEnd;
  1471.                 this.source.start(startTime, startOffset);
  1472.                 this.source.scheduledStartTime = startTime;
  1473.                 this.source.playbackStartTime = startTime - startOffset / this.source.playbackRate.value;
  1474.                 this.source.setPitch(this.pitch);
  1475.             } catch (e) {
  1476.                 console.error("Channel.playSoundClip error. Exception: " + e);
  1477.             }
  1478.         };
  1479.         channel.stop = function (delay) {
  1480.             if (!this.source) {
  1481.                 return;
  1482.             }
  1483.             if (this.source.isPausedMockNode) {
  1484.                 delete this.source;
  1485.                 return;
  1486.             }
  1487.             try {
  1488.                 channel.source.stop(WEBAudio.audioContext.currentTime + delay);
  1489.             } catch (e) {}
  1490.             if (delay == 0) {
  1491.                 this.disconnectSource();
  1492.             }
  1493.         };
  1494.         channel.isPaused = function () {
  1495.             if (!this.source) {
  1496.                 return true;
  1497.             }
  1498.             if (this.source.isPausedMockNode) {
  1499.                 return true;
  1500.             }
  1501.             if (this.source.mediaElement) {
  1502.                 return this.source.mediaElement.paused || this.source.pauseRequested;
  1503.             }
  1504.             return false;
  1505.         };
  1506.         channel.pause = function () {
  1507.             if (!this.source || this.source.isPausedMockNode) {
  1508.                 return;
  1509.             }
  1510.             if (this.source.mediaElement) {
  1511.                 this.source._pauseMediaElement();
  1512.                 return;
  1513.             }
  1514.             var pausedSource = {
  1515.                 isPausedMockNode: true,
  1516.                 buffer: this.source.buffer,
  1517.                 loop: this.source.loop,
  1518.                 loopStart: this.source.loopStart,
  1519.                 loopEnd: this.source.loopEnd,
  1520.                 playbackRate: this.source.playbackRate.value,
  1521.                 scheduledStartTime: this.source.scheduledStartTime,
  1522.                 playbackPausedAtPosition: this.source.estimatePlaybackPosition(),
  1523.                 setPitch: function (v) {
  1524.                     this.playbackRate = v;
  1525.                 },
  1526.             };
  1527.             this.stop(0);
  1528.             this.disconnectSource();
  1529.             this.source = pausedSource;
  1530.         };
  1531.         channel.resume = function () {
  1532.             if (this.source && this.source.mediaElement) {
  1533.                 this.source.start();
  1534.                 return;
  1535.             }
  1536.             if (!this.source || !this.source.isPausedMockNode) {
  1537.                 return;
  1538.             }
  1539.             var pausedSource = this.source;
  1540.             var soundClip = jsAudioCreateUncompressedSoundClip(pausedSource.buffer, false);
  1541.             this.playSoundClip(soundClip, pausedSource.scheduledStartTime, Math.max(0, pausedSource.playbackPausedAtPosition));
  1542.             this.source.loop = pausedSource.loop;
  1543.             this.source.loopStart = pausedSource.loopStart;
  1544.             this.source.loopEnd = pausedSource.loopEnd;
  1545.             this.source.setPitch(pausedSource.playbackRate);
  1546.         };
  1547.         channel.setLoop = function (loop) {
  1548.             this.loop = loop;
  1549.             if (!this.source || this.source.loop == loop) {
  1550.                 return;
  1551.             }
  1552.             this.source.loop = loop;
  1553.         };
  1554.         channel.setLoopPoints = function (loopStart, loopEnd) {
  1555.             this.loopStart = loopStart;
  1556.             this.loopEnd = loopEnd;
  1557.             if (!this.source) {
  1558.                 return;
  1559.             }
  1560.             if (this.source.loopStart !== loopStart) {
  1561.                 this.source.loopStart = loopStart;
  1562.             }
  1563.             if (this.source.loopEnd !== loopEnd) {
  1564.                 this.source.loopEnd = loopEnd;
  1565.             }
  1566.         };
  1567.         channel.set3D = function (threeD) {
  1568.             if (this.threeD == threeD) {
  1569.                 return;
  1570.             }
  1571.             this.threeD = threeD;
  1572.             if (!this.source) {
  1573.                 return;
  1574.             }
  1575.             this.setupPanning();
  1576.         };
  1577.         channel.setPitch = function (pitch) {
  1578.             this.pitch = pitch;
  1579.             if (!this.source) {
  1580.                 return;
  1581.             }
  1582.             this.source.setPitch(pitch);
  1583.         };
  1584.         channel.setVolume = function (volume) {
  1585.             if (this.gain.gain.value == volume) {
  1586.                 return;
  1587.             }
  1588.             this.gain.gain.value = volume;
  1589.         };
  1590.         channel.setPosition = function (x, y, z) {
  1591.             var p = this.panner;
  1592.             if (p.positionX) {
  1593.                 if (p.positionX.value !== x) p.positionX.value = x;
  1594.                 if (p.positionY.value !== y) p.positionY.value = y;
  1595.                 if (p.positionZ.value !== z) p.positionZ.value = z;
  1596.             } else if (p._x !== x || p._y !== y || p._z !== z) {
  1597.                 p.setPosition(x, y, z);
  1598.                 p._x = x;
  1599.                 p._y = y;
  1600.                 p._z = z;
  1601.             }
  1602.         };
  1603.         channel.disconnectSource = function () {
  1604.             if (!this.source || this.source.isPausedMockNode) {
  1605.                 return;
  1606.             }
  1607.             if (this.source.mediaElement) {
  1608.                 this.source._pauseMediaElement();
  1609.             }
  1610.             this.source.onended = null;
  1611.             this.source.disconnect();
  1612.             delete this.source;
  1613.         };
  1614.         channel.setupPanning = function () {
  1615.             if (this.source.isPausedMockNode) return;
  1616.             this.source.disconnect();
  1617.             this.panner.disconnect();
  1618.             this.gain.disconnect();
  1619.             if (this.threeD) {
  1620.                 this.source.connect(this.panner);
  1621.                 this.panner.connect(this.gain);
  1622.             } else {
  1623.                 this.source.connect(this.gain);
  1624.             }
  1625.             this.gain.connect(WEBAudio.audioContext.destination);
  1626.         };
  1627.         return channel;
  1628.     }
  1629.     function _JS_Sound_Create_Channel(callback, userData) {
  1630.         if (WEBAudio.audioWebEnabled == 0) return;
  1631.         WEBAudio.audioInstances[++WEBAudio.audioInstanceIdCounter] = jsAudioCreateChannel(callback, userData);
  1632.         return WEBAudio.audioInstanceIdCounter;
  1633.     }
  1634.     function _JS_Sound_GetLength(bufferInstance) {
  1635.         if (WEBAudio.audioWebEnabled == 0) return 0;
  1636.         var soundClip = WEBAudio.audioInstances[bufferInstance];
  1637.         return soundClip.getLength();
  1638.     }
  1639.     function _JS_Sound_GetLoadState(bufferInstance) {
  1640.         if (WEBAudio.audioWebEnabled == 0) return 2;
  1641.         var sound = WEBAudio.audioInstances[bufferInstance];
  1642.         if (sound.error) return 2;
  1643.         if (sound.buffer || sound.url) return 0;
  1644.         return 1;
  1645.     }
  1646.     function _JS_Sound_Init() {
  1647.         try {
  1648.             window.AudioContext = window.AudioContext || window.webkitAudioContext;
  1649.             WEBAudio.audioContext = new AudioContext();
  1650.             var tryToResumeAudioContext = function () {
  1651.                 if (WEBAudio.audioContext.state === "suspended") WEBAudio.audioContext.resume();
  1652.                 else Module.clearInterval(resumeInterval);
  1653.             };
  1654.             var resumeInterval = Module.setInterval(tryToResumeAudioContext, 400);
  1655.             WEBAudio.audioWebEnabled = 1;
  1656.             var _userEventCallback = function () {
  1657.                 try {
  1658.                     if (WEBAudio.audioContext.state !== "running") {
  1659.                         WEBAudio.audioContext.resume();
  1660.                     }
  1661.                     var audioCacheSize = 20;
  1662.                     while (WEBAudio.audioCache.length < audioCacheSize) {
  1663.                         var audio = new Audio();
  1664.                         audio.autoplay = false;
  1665.                         WEBAudio.audioCache.push(audio);
  1666.                     }
  1667.                 } catch (e) {}
  1668.             };
  1669.             window.addEventListener("mousedown", _userEventCallback);
  1670.             window.addEventListener("touchstart", _userEventCallback);
  1671.             Module.deinitializers.push(function () {
  1672.                 window.removeEventListener("mousedown", _userEventCallback);
  1673.                 window.removeEventListener("touchstart", _userEventCallback);
  1674.             });
  1675.         } catch (e) {
  1676.             alert("Web Audio API is not supported in this browser");
  1677.         }
  1678.     }
  1679.     function jsAudioCreateUncompressedSoundClipFromCompressedAudio(audioData) {
  1680.         var soundClip = jsAudioCreateUncompressedSoundClip(null, false);
  1681.         WEBAudio.audioContext.decodeAudioData(
  1682.             audioData,
  1683.             function (_buffer) {
  1684.                 soundClip.buffer = _buffer;
  1685.             },
  1686.             function (_error) {
  1687.                 soundClip.error = true;
  1688.                 console.log("Decode error: " + _error);
  1689.             }
  1690.         );
  1691.         return soundClip;
  1692.     }
  1693.     function jsAudioCreateCompressedSoundClip(audioData) {
  1694.         var blob = new Blob([audioData], { type: "audio/mp4" });
  1695.         var soundClip = { url: URL.createObjectURL(blob), error: false, mediaElement: new Audio() };
  1696.         soundClip.mediaElement.preload = "metadata";
  1697.         soundClip.mediaElement.src = soundClip.url;
  1698.         soundClip.release = function () {
  1699.             if (!this.mediaElement) {
  1700.                 return;
  1701.             }
  1702.             this.mediaElement.src = "";
  1703.             URL.revokeObjectURL(this.url);
  1704.             delete this.mediaElement;
  1705.             delete this.url;
  1706.         };
  1707.         soundClip.getLength = function () {
  1708.             return this.mediaElement.duration * 44100;
  1709.         };
  1710.         soundClip.createSourceNode = function () {
  1711.             var self = this;
  1712.             var mediaElement = WEBAudio.audioCache.length ? WEBAudio.audioCache.pop() : new Audio();
  1713.             mediaElement.preload = "metadata";
  1714.             mediaElement.src = this.url;
  1715.             var source = WEBAudio.audioContext.createMediaElementSource(mediaElement);
  1716.             Object.defineProperty(source, "loop", {
  1717.                 get: function () {
  1718.                     return source.mediaElement.loop;
  1719.                 },
  1720.                 set: function (v) {
  1721.                     if (source.mediaElement.loop !== v) source.mediaElement.loop = v;
  1722.                 },
  1723.             });
  1724.             source.playbackRate = {};
  1725.             Object.defineProperty(source.playbackRate, "value", {
  1726.                 get: function () {
  1727.                     return source.mediaElement.playbackRate;
  1728.                 },
  1729.                 set: function (v) {
  1730.                     if (source.mediaElement.playbackRate !== v) source.mediaElement.playbackRate = v;
  1731.                 },
  1732.             });
  1733.             Object.defineProperty(source, "currentTime", {
  1734.                 get: function () {
  1735.                     return source.mediaElement.currentTime;
  1736.                 },
  1737.                 set: function (v) {
  1738.                     if (source.mediaElement.currentTime !== v) source.mediaElement.currentTime = v;
  1739.                 },
  1740.             });
  1741.             Object.defineProperty(source, "mute", {
  1742.                 get: function () {
  1743.                     return source.mediaElement.mute;
  1744.                 },
  1745.                 set: function (v) {
  1746.                     if (source.mediaElement.mute !== v) source.mediaElement.mute = v;
  1747.                 },
  1748.             });
  1749.             source.playPromise = null;
  1750.             source.playTimeout = null;
  1751.             source.pauseRequested = false;
  1752.             source._pauseMediaElement = function () {
  1753.                 if (source.playPromise || source.playTimeout) {
  1754.                     source.pauseRequested = true;
  1755.                 } else {
  1756.                     source.mediaElement.pause();
  1757.                 }
  1758.             };
  1759.             source._startPlayback = function (offset) {
  1760.                 if (source.playPromise || source.playTimeout) {
  1761.                     source.mediaElement.currentTime = offset;
  1762.                     source.pauseRequested = false;
  1763.                     return;
  1764.                 }
  1765.                 source.mediaElement.currentTime = offset;
  1766.                 source.playPromise = source.mediaElement.play();
  1767.                 if (source.playPromise) {
  1768.                     source.playPromise.then(function () {
  1769.                         if (source.pauseRequested) {
  1770.                             source.mediaElement.pause();
  1771.                             source.pauseRequested = false;
  1772.                         }
  1773.                         source.playPromise = null;
  1774.                     });
  1775.                 }
  1776.             };
  1777.             source.start = function (startTime, offset) {
  1778.                 if (typeof startTime === "undefined") {
  1779.                     startTime = WEBAudio.audioContext.currentTime;
  1780.                 }
  1781.                 if (typeof offset === "undefined") {
  1782.                     offset = 0;
  1783.                 }
  1784.                 var startDelayThresholdMS = 4;
  1785.                 var startDelayMS = (startTime - WEBAudio.audioContext.currentTime) * 1e3;
  1786.                 if (startDelayMS > startDelayThresholdMS) {
  1787.                     source.playTimeout = setTimeout(function () {
  1788.                         source.playTimeout = null;
  1789.                         source._startPlayback(offset);
  1790.                     }, startDelayMS);
  1791.                 } else {
  1792.                     source._startPlayback(offset);
  1793.                 }
  1794.             };
  1795.             source.stop = function (stopTime) {
  1796.                 if (typeof stopTime === "undefined") {
  1797.                     stopTime = WEBAudio.audioContext.currentTime;
  1798.                 }
  1799.                 var stopDelayThresholdMS = 4;
  1800.                 var stopDelayMS = (stopTime - WEBAudio.audioContext.currentTime) * 1e3;
  1801.                 if (stopDelayMS > stopDelayThresholdMS) {
  1802.                     setTimeout(function () {
  1803.                         source._pauseMediaElement();
  1804.                     }, stopDelayMS);
  1805.                 } else {
  1806.                     source._pauseMediaElement();
  1807.                 }
  1808.             };
  1809.             jsAudioMixinSetPitch(source);
  1810.             return source;
  1811.         };
  1812.         return soundClip;
  1813.     }
  1814.     function _JS_Sound_Load(ptr, length, decompress) {
  1815.         if (WEBAudio.audioWebEnabled == 0) return 0;
  1816.         var audioData = HEAPU8.buffer.slice(ptr, ptr + length);
  1817.         if (length < 131072) decompress = 1;
  1818.         var sound;
  1819.         if (decompress) {
  1820.             sound = jsAudioCreateUncompressedSoundClipFromCompressedAudio(audioData);
  1821.         } else {
  1822.             sound = jsAudioCreateCompressedSoundClip(audioData);
  1823.         }
  1824.         WEBAudio.audioInstances[++WEBAudio.audioInstanceIdCounter] = sound;
  1825.         return WEBAudio.audioInstanceIdCounter;
  1826.     }
  1827.     function jsAudioCreateUncompressedSoundClipFromPCM(channels, length, sampleRate, ptr) {
  1828.         var buffer = WEBAudio.audioContext.createBuffer(channels, length, sampleRate);
  1829.         for (var i = 0; i < channels; i++) {
  1830.             var offs = (ptr >> 2) + length * i;
  1831.             var copyToChannel =
  1832.                 buffer["copyToChannel"] ||
  1833.                 function (source, channelNumber, startInChannel) {
  1834.                     var clipped = source.subarray(0, Math.min(source.length, this.length - (startInChannel | 0)));
  1835.                     this.getChannelData(channelNumber | 0).set(clipped, startInChannel | 0);
  1836.                 };
  1837.             copyToChannel.apply(buffer, [HEAPF32.subarray(offs, offs + length), i, 0]);
  1838.         }
  1839.         return jsAudioCreateUncompressedSoundClip(buffer, false);
  1840.     }
  1841.     function _JS_Sound_Load_PCM(channels, length, sampleRate, ptr) {
  1842.         if (WEBAudio.audioWebEnabled == 0) return 0;
  1843.         var sound = jsAudioCreateUncompressedSoundClipFromPCM(channels, length, sampleRate, ptr);
  1844.         WEBAudio.audioInstances[++WEBAudio.audioInstanceIdCounter] = sound;
  1845.         return WEBAudio.audioInstanceIdCounter;
  1846.     }
  1847.     function _JS_Sound_Play(bufferInstance, channelInstance, offset, delay) {
  1848.         if (WEBAudio.audioWebEnabled == 0) return;
  1849.         _JS_Sound_Stop(channelInstance, 0);
  1850.         var soundClip = WEBAudio.audioInstances[bufferInstance];
  1851.         var channel = WEBAudio.audioInstances[channelInstance];
  1852.         if (!soundClip) {
  1853.             console.log("Trying to play sound which is not loaded.");
  1854.             return;
  1855.         }
  1856.         try {
  1857.             channel.playSoundClip(soundClip, WEBAudio.audioContext.currentTime + delay, offset);
  1858.         } catch (error) {
  1859.             console.error("playSoundClip error. Exception: " + e);
  1860.         }
  1861.     }
  1862.     function _JS_Sound_ReleaseInstance(instance) {
  1863.         var object = WEBAudio.audioInstances[instance];
  1864.         if (object) {
  1865.             object.release();
  1866.         }
  1867.         delete WEBAudio.audioInstances[instance];
  1868.     }
  1869.     function _JS_Sound_ResumeIfNeeded() {
  1870.         if (WEBAudio.audioWebEnabled == 0) return;
  1871.         if (WEBAudio.audioContext.state === "suspended") WEBAudio.audioContext.resume();
  1872.     }
  1873.     function _JS_Sound_Set3D(channelInstance, threeD) {
  1874.         var channel = WEBAudio.audioInstances[channelInstance];
  1875.         channel.set3D(threeD);
  1876.     }
  1877.     function _JS_Sound_SetListenerOrientation(x, y, z, xUp, yUp, zUp) {
  1878.         if (WEBAudio.audioWebEnabled == 0) return;
  1879.         x = -x;
  1880.         y = -y;
  1881.         z = -z;
  1882.         var l = WEBAudio.audioContext.listener;
  1883.         if (l.forwardX) {
  1884.             if (l.forwardX.value !== x) l.forwardX.value = x;
  1885.             if (l.forwardY.value !== y) l.forwardY.value = y;
  1886.             if (l.forwardZ.value !== z) l.forwardZ.value = z;
  1887.             if (l.upX.value !== x) l.upX.value = x;
  1888.             if (l.upY.value !== y) l.upY.value = y;
  1889.             if (l.upZ.value !== z) l.upZ.value = z;
  1890.         } else if (l._forwardX !== x || l._forwardY !== y || l._forwardZ !== z || l._upX !== xUp || l._upY !== yUp || l._upZ !== zUp) {
  1891.             l.setOrientation(x, y, z, xUp, yUp, zUp);
  1892.             l._forwardX = x;
  1893.             l._forwardY = y;
  1894.             l._forwardZ = z;
  1895.             l._upX = xUp;
  1896.             l._upY = yUp;
  1897.             l._upZ = zUp;
  1898.         }
  1899.     }
  1900.     function _JS_Sound_SetListenerPosition(x, y, z) {
  1901.         if (WEBAudio.audioWebEnabled == 0) return;
  1902.         var l = WEBAudio.audioContext.listener;
  1903.         if (l.positionX) {
  1904.             if (l.positionX.value !== x) l.positionX.value = x;
  1905.             if (l.positionY.value !== y) l.positionY.value = y;
  1906.             if (l.positionZ.value !== z) l.positionZ.value = z;
  1907.         } else if (l._positionX !== x || l._positionY !== y || l._positionZ !== z) {
  1908.             l.setPosition(x, y, z);
  1909.             l._positionX = x;
  1910.             l._positionY = y;
  1911.             l._positionZ = z;
  1912.         }
  1913.     }
  1914.     function _JS_Sound_SetLoop(channelInstance, loop) {
  1915.         if (WEBAudio.audioWebEnabled == 0) return;
  1916.         var channel = WEBAudio.audioInstances[channelInstance];
  1917.         channel.setLoop(loop);
  1918.     }
  1919.     function _JS_Sound_SetLoopPoints(channelInstance, loopStart, loopEnd) {
  1920.         if (WEBAudio.audioWebEnabled == 0) return;
  1921.         var channel = WEBAudio.audioInstances[channelInstance];
  1922.         channel.setLoopPoints(loopStart, loopEnd);
  1923.     }
  1924.     function _JS_Sound_SetPaused(channelInstance, paused) {
  1925.         if (WEBAudio.audioWebEnabled == 0) return;
  1926.         var channel = WEBAudio.audioInstances[channelInstance];
  1927.         if (paused != channel.isPaused()) {
  1928.             if (paused) channel.pause();
  1929.             else channel.resume();
  1930.         }
  1931.     }
  1932.     function _JS_Sound_SetPitch(channelInstance, v) {
  1933.         if (WEBAudio.audioWebEnabled == 0) return;
  1934.         try {
  1935.             var channel = WEBAudio.audioInstances[channelInstance];
  1936.             channel.setPitch(v);
  1937.         } catch (e) {
  1938.             console.error("JS_Sound_SetPitch(channel=" + channelInstance + ", pitch=" + v + ") threw an exception: " + e);
  1939.         }
  1940.     }
  1941.     function _JS_Sound_SetPosition(channelInstance, x, y, z) {
  1942.         if (WEBAudio.audioWebEnabled == 0) return;
  1943.         var channel = WEBAudio.audioInstances[channelInstance];
  1944.         channel.setPosition(x, y, z);
  1945.     }
  1946.     function _JS_Sound_SetVolume(channelInstance, v) {
  1947.         if (WEBAudio.audioWebEnabled == 0) return;
  1948.         try {
  1949.             var channel = WEBAudio.audioInstances[channelInstance];
  1950.             channel.setVolume(v);
  1951.         } catch (e) {
  1952.             console.error("JS_Sound_SetVolume(channel=" + channelInstance + ", volume=" + v + ") threw an exception: " + e);
  1953.         }
  1954.     }
  1955.     function _JS_Sound_Stop(channelInstance, delay) {
  1956.         if (WEBAudio.audioWebEnabled == 0) return;
  1957.         var channel = WEBAudio.audioInstances[channelInstance];
  1958.         channel.stop(delay);
  1959.     }
  1960.     function _JS_SystemInfo_GetBrowserName(buffer, bufferSize) {
  1961.         var browser = Module.SystemInfo.browser;
  1962.         if (buffer) stringToUTF8(browser, buffer, bufferSize);
  1963.         return lengthBytesUTF8(browser);
  1964.     }
  1965.     function _JS_SystemInfo_GetBrowserVersionString(buffer, bufferSize) {
  1966.         var browserVer = Module.SystemInfo.browserVersion;
  1967.         if (buffer) stringToUTF8(browserVer, buffer, bufferSize);
  1968.         return lengthBytesUTF8(browserVer);
  1969.     }
  1970.     function _JS_SystemInfo_GetCanvasClientSize(domElementSelector, outWidth, outHeight) {
  1971.         var selector = UTF8ToString(domElementSelector);
  1972.         var canvas = selector == "#canvas" ? Module["canvas"] : document.querySelector(selector);
  1973.         var w = 0,
  1974.             h = 0;
  1975.         if (canvas) {
  1976.             var size = canvas.getBoundingClientRect();
  1977.             w = size.width;
  1978.             h = size.height;
  1979.         }
  1980.         HEAPF64[outWidth >> 3] = w;
  1981.         HEAPF64[outHeight >> 3] = h;
  1982.     }
  1983.     function _JS_SystemInfo_GetDocumentURL(buffer, bufferSize) {
  1984.         if (buffer) stringToUTF8(document.URL, buffer, bufferSize);
  1985.         return lengthBytesUTF8(document.URL);
  1986.     }
  1987.     function _JS_SystemInfo_GetGPUInfo(buffer, bufferSize) {
  1988.         var gpuinfo = Module.SystemInfo.gpu;
  1989.         if (buffer) stringToUTF8(gpuinfo, buffer, bufferSize);
  1990.         return lengthBytesUTF8(gpuinfo);
  1991.     }
  1992.     function _JS_SystemInfo_GetMatchWebGLToCanvasSize() {
  1993.         return Module.matchWebGLToCanvasSize || Module.matchWebGLToCanvasSize === undefined;
  1994.     }
  1995.     function _JS_SystemInfo_GetMemory() {
  1996.         return HEAPU8.length / (1024 * 1024);
  1997.     }
  1998.     function _JS_SystemInfo_GetOS(buffer, bufferSize) {
  1999.         var browser = Module.SystemInfo.os + " " + Module.SystemInfo.osVersion;
  2000.         if (buffer) stringToUTF8(browser, buffer, bufferSize);
  2001.         return lengthBytesUTF8(browser);
  2002.     }
  2003.     function _JS_SystemInfo_GetPreferredDevicePixelRatio() {
  2004.         return Module.matchWebGLToCanvasSize == false ? 1 : Module.devicePixelRatio || window.devicePixelRatio || 1;
  2005.     }
  2006.     function _JS_SystemInfo_GetScreenSize(outWidth, outHeight) {
  2007.         HEAPF64[outWidth >> 3] = Module.SystemInfo.width;
  2008.         HEAPF64[outHeight >> 3] = Module.SystemInfo.height;
  2009.     }
  2010.     function _JS_SystemInfo_GetStreamingAssetsURL(buffer, bufferSize) {
  2011.         if (buffer) stringToUTF8(Module.streamingAssetsUrl, buffer, bufferSize);
  2012.         return lengthBytesUTF8(Module.streamingAssetsUrl);
  2013.     }
  2014.     function _JS_SystemInfo_HasAstcHdr() {
  2015.         var ext = GLctx.getExtension("WEBGL_compressed_texture_astc");
  2016.         if (ext && ext.getSupportedProfiles) {
  2017.             return ext.getSupportedProfiles().includes("hdr");
  2018.         }
  2019.         return false;
  2020.     }
  2021.     function _JS_SystemInfo_HasCursorLock() {
  2022.         return Module.SystemInfo.hasCursorLock;
  2023.     }
  2024.     function _JS_SystemInfo_HasFullscreen() {
  2025.         return Module.SystemInfo.hasFullscreen;
  2026.     }
  2027.     function _JS_SystemInfo_HasWebGL() {
  2028.         return Module.SystemInfo.hasWebGL;
  2029.     }
  2030.     function _JS_SystemInfo_IsMobile() {
  2031.         return Module.SystemInfo.mobile;
  2032.     }
  2033.     function _JS_UnityEngineShouldQuit() {
  2034.         return !!Module.shouldQuit;
  2035.     }
  2036.     var wr = { requestInstances: {}, nextRequestId: 1 };
  2037.     function _JS_WebRequest_Abort(request) {
  2038.         wr.requestInstances[request].abort();
  2039.     }
  2040.     function _JS_WebRequest_Create(url, method) {
  2041.         var _url = UTF8ToString(url);
  2042.         var _method = UTF8ToString(method);
  2043.         var http =
  2044.             Module.companyName && Module.productName && Module.XMLHttpRequest ? new Module.XMLHttpRequest({ companyName: Module.companyName, productName: Module.productName, cacheControl: Module.cacheControl(_url) }) : new XMLHttpRequest();
  2045.         http.open(_method, _url, true);
  2046.         http.responseType = "arraybuffer";
  2047.         wr.requestInstances[wr.nextRequestId] = http;
  2048.         return wr.nextRequestId++;
  2049.     }
  2050.     function _JS_WebRequest_GetResponseHeaders(request, buffer, bufferSize) {
  2051.         var headers = wr.requestInstances[request].getAllResponseHeaders();
  2052.         if (buffer) stringToUTF8(headers, buffer, bufferSize);
  2053.         return lengthBytesUTF8(headers);
  2054.     }
  2055.     function _JS_WebRequest_Release(request) {
  2056.         var http = wr.requestInstances[request];
  2057.         http.onload = null;
  2058.         http.onerror = null;
  2059.         http.ontimeout = null;
  2060.         http.onabort = null;
  2061.         null;
  2062.         wr.requestInstances[request] = null;
  2063.     }
  2064.     function _JS_WebRequest_Send(request, ptr, length) {
  2065.         var http = wr.requestInstances[request];
  2066.         try {
  2067.             if (length > 0) {
  2068.                 var postData = HEAPU8.subarray(ptr, ptr + length);
  2069.                 http.send(postData);
  2070.             } else http.send();
  2071.         } catch (e) {
  2072.             console.error(e.name + ": " + e.message);
  2073.         }
  2074.     }
  2075.     function _JS_WebRequest_SetProgressHandler(request, arg, onprogress) {
  2076.         var http = wr.requestInstances[request];
  2077.         http.onprogress = function http_onprogress(e) {
  2078.             if (onprogress) {
  2079.                 if (e.lengthComputable) dynCall("viii", onprogress, [arg, e.loaded, e.total]);
  2080.             }
  2081.         };
  2082.     }
  2083.     function _JS_WebRequest_SetRequestHeader(request, header, value) {
  2084.         var _header = UTF8ToString(header);
  2085.         var _value = UTF8ToString(value);
  2086.         wr.requestInstances[request].setRequestHeader(_header, _value);
  2087.     }
  2088.     function _JS_WebRequest_SetResponseHandler(request, arg, onresponse) {
  2089.         var http = wr.requestInstances[request];
  2090.         http.onload = function http_onload(e) {
  2091.             if (onresponse) {
  2092.                 var kWebRequestOK = 0;
  2093.                 var byteArray = new Uint8Array(http.response);
  2094.                 if (byteArray.length != 0) {
  2095.                     var buffer = _malloc(byteArray.length);
  2096.                     HEAPU8.set(byteArray, buffer);
  2097.                     dynCall("viiiiii", onresponse, [arg, http.status, buffer, byteArray.length, 0, kWebRequestOK]);
  2098.                 } else {
  2099.                     dynCall("viiiiii", onresponse, [arg, http.status, 0, 0, 0, kWebRequestOK]);
  2100.                 }
  2101.             }
  2102.         };
  2103.         function HandleError(err, code) {
  2104.             if (onresponse) {
  2105.                 var len = lengthBytesUTF8(err) + 1;
  2106.                 var buffer = _malloc(len);
  2107.                 stringToUTF8(err, buffer, len);
  2108.                 dynCall("viiiiii", onresponse, [arg, http.status, 0, 0, buffer, code]);
  2109.                 _free(buffer);
  2110.             }
  2111.         }
  2112.         http.onerror = function http_onerror(e) {
  2113.             var kWebErrorUnknown = 2;
  2114.             HandleError("Unknown error.", kWebErrorUnknown);
  2115.         };
  2116.         http.ontimeout = function http_onerror(e) {
  2117.             var kWebErrorTimeout = 14;
  2118.             HandleError("Connection timed out.", kWebErrorTimeout);
  2119.         };
  2120.         http.onabort = function http_onerror(e) {
  2121.             var kWebErrorAborted = 17;
  2122.             HandleError("Aborted.", kWebErrorAborted);
  2123.         };
  2124.     }
  2125.     function _JS_WebRequest_SetTimeout(request, timeout) {
  2126.         wr.requestInstances[request].timeout = timeout;
  2127.     }
  2128.     function _OnDeviceReadyToConnect() {
  2129.         if (OnDeviceReadyToConnect) {
  2130.             OnDeviceReadyToConnect();
  2131.         } else {
  2132.             console.log("Error: Unity build couldn't find OnDeviceReadyToConnect function!");
  2133.         }
  2134.     }
  2135.     function _OnLeaveLocation() {
  2136.         if (OnLeaveLocation) {
  2137.             OnLeaveLocation();
  2138.         } else {
  2139.             console.log("Error: Unity build couldn't find OnLeaveLocation function!");
  2140.         }
  2141.     }
  2142.     function _OnWebGLLoaded() {
  2143.         if (webGLLoaded) {
  2144.             webGLLoaded();
  2145.         } else {
  2146.             console.log("Error: Unity build couldn't find webGLLoaded function!");
  2147.         }
  2148.     }
  2149.     function _ResetCursor() {
  2150.         if (ResetCursor) {
  2151.             ResetCursor();
  2152.         } else {
  2153.             console.log("Error: Unity build couldn't find ResetCursor function!");
  2154.         }
  2155.     }
  2156.     function _SetProgress(progressPoint) {
  2157.         if (SetProgress) {
  2158.             SetProgress(UTF8ToString(progressPoint));
  2159.         } else {
  2160.             console.log("Error: Unity build couldn't find SetProgress function!");
  2161.         }
  2162.     }
  2163.     function _ShowLocationCloseButton() {
  2164.         if (ShowLocationCloseButton) {
  2165.             ShowLocationCloseButton();
  2166.         } else {
  2167.             console.log("Error: Unity build couldn't find ShowLocationCloseButton function!");
  2168.         }
  2169.     }
  2170.     function _TargetBuildingFound() {
  2171.         if (TargetBuildingFound) {
  2172.             TargetBuildingFound();
  2173.         } else {
  2174.             console.log("Error: Unity build couldn't find TargetBuildingFound function!");
  2175.         }
  2176.     }
  2177.     var ExceptionInfoAttrs = { DESTRUCTOR_OFFSET: 0, REFCOUNT_OFFSET: 4, TYPE_OFFSET: 8, CAUGHT_OFFSET: 12, RETHROWN_OFFSET: 13, SIZE: 16 };
  2178.     function ___cxa_allocate_exception(size) {
  2179.         return _malloc(size + ExceptionInfoAttrs.SIZE) + ExceptionInfoAttrs.SIZE;
  2180.     }
  2181.     function ExceptionInfo(excPtr) {
  2182.         this.excPtr = excPtr;
  2183.         this.ptr = excPtr - ExceptionInfoAttrs.SIZE;
  2184.         this.set_type = function (type) {
  2185.             HEAP32[(this.ptr + ExceptionInfoAttrs.TYPE_OFFSET) >> 2] = type;
  2186.         };
  2187.         this.get_type = function () {
  2188.             return HEAP32[(this.ptr + ExceptionInfoAttrs.TYPE_OFFSET) >> 2];
  2189.         };
  2190.         this.set_destructor = function (destructor) {
  2191.             HEAP32[(this.ptr + ExceptionInfoAttrs.DESTRUCTOR_OFFSET) >> 2] = destructor;
  2192.         };
  2193.         this.get_destructor = function () {
  2194.             return HEAP32[(this.ptr + ExceptionInfoAttrs.DESTRUCTOR_OFFSET) >> 2];
  2195.         };
  2196.         this.set_refcount = function (refcount) {
  2197.             HEAP32[(this.ptr + ExceptionInfoAttrs.REFCOUNT_OFFSET) >> 2] = refcount;
  2198.         };
  2199.         this.set_caught = function (caught) {
  2200.             caught = caught ? 1 : 0;
  2201.             HEAP8[(this.ptr + ExceptionInfoAttrs.CAUGHT_OFFSET) >> 0] = caught;
  2202.         };
  2203.         this.get_caught = function () {
  2204.             return HEAP8[(this.ptr + ExceptionInfoAttrs.CAUGHT_OFFSET) >> 0] != 0;
  2205.         };
  2206.         this.set_rethrown = function (rethrown) {
  2207.             rethrown = rethrown ? 1 : 0;
  2208.             HEAP8[(this.ptr + ExceptionInfoAttrs.RETHROWN_OFFSET) >> 0] = rethrown;
  2209.         };
  2210.         this.get_rethrown = function () {
  2211.             return HEAP8[(this.ptr + ExceptionInfoAttrs.RETHROWN_OFFSET) >> 0] != 0;
  2212.         };
  2213.         this.init = function (type, destructor) {
  2214.             this.set_type(type);
  2215.             this.set_destructor(destructor);
  2216.             this.set_refcount(0);
  2217.             this.set_caught(false);
  2218.             this.set_rethrown(false);
  2219.         };
  2220.         this.add_ref = function () {
  2221.             var value = HEAP32[(this.ptr + ExceptionInfoAttrs.REFCOUNT_OFFSET) >> 2];
  2222.             HEAP32[(this.ptr + ExceptionInfoAttrs.REFCOUNT_OFFSET) >> 2] = value + 1;
  2223.         };
  2224.         this.release_ref = function () {
  2225.             var prev = HEAP32[(this.ptr + ExceptionInfoAttrs.REFCOUNT_OFFSET) >> 2];
  2226.             HEAP32[(this.ptr + ExceptionInfoAttrs.REFCOUNT_OFFSET) >> 2] = prev - 1;
  2227.             return prev === 1;
  2228.         };
  2229.     }
  2230.     function CatchInfo(ptr) {
  2231.         this.free = function () {
  2232.             _free(this.ptr);
  2233.             this.ptr = 0;
  2234.         };
  2235.         this.set_base_ptr = function (basePtr) {
  2236.             HEAP32[this.ptr >> 2] = basePtr;
  2237.         };
  2238.         this.get_base_ptr = function () {
  2239.             return HEAP32[this.ptr >> 2];
  2240.         };
  2241.         this.set_adjusted_ptr = function (adjustedPtr) {
  2242.             var ptrSize = 4;
  2243.             HEAP32[(this.ptr + ptrSize) >> 2] = adjustedPtr;
  2244.         };
  2245.         this.get_adjusted_ptr = function () {
  2246.             var ptrSize = 4;
  2247.             return HEAP32[(this.ptr + ptrSize) >> 2];
  2248.         };
  2249.         this.get_exception_ptr = function () {
  2250.             var isPointer = ___cxa_is_pointer_type(this.get_exception_info().get_type());
  2251.             if (isPointer) {
  2252.                 return HEAP32[this.get_base_ptr() >> 2];
  2253.             }
  2254.             var adjusted = this.get_adjusted_ptr();
  2255.             if (adjusted !== 0) return adjusted;
  2256.             return this.get_base_ptr();
  2257.         };
  2258.         this.get_exception_info = function () {
  2259.             return new ExceptionInfo(this.get_base_ptr());
  2260.         };
  2261.         if (ptr === undefined) {
  2262.             this.ptr = _malloc(8);
  2263.             this.set_adjusted_ptr(0);
  2264.         } else {
  2265.             this.ptr = ptr;
  2266.         }
  2267.     }
  2268.     var exceptionCaught = [];
  2269.     function exception_addRef(info) {
  2270.         info.add_ref();
  2271.     }
  2272.     var uncaughtExceptionCount = 0;
  2273.     function ___cxa_begin_catch(ptr) {
  2274.         var catchInfo = new CatchInfo(ptr);
  2275.         var info = catchInfo.get_exception_info();
  2276.         if (!info.get_caught()) {
  2277.             info.set_caught(true);
  2278.             uncaughtExceptionCount--;
  2279.         }
  2280.         info.set_rethrown(false);
  2281.         exceptionCaught.push(catchInfo);
  2282.         exception_addRef(info);
  2283.         return catchInfo.get_exception_ptr();
  2284.     }
  2285.     var exceptionLast = 0;
  2286.     function ___cxa_free_exception(ptr) {
  2287.         return _free(new ExceptionInfo(ptr).ptr);
  2288.     }
  2289.     function exception_decRef(info) {
  2290.         if (info.release_ref() && !info.get_rethrown()) {
  2291.             var destructor = info.get_destructor();
  2292.             if (destructor) {
  2293.                 (function (a1) {
  2294.                     return dynCall_ii.apply(null, [destructor, a1]);
  2295.                 })(info.excPtr);
  2296.             }
  2297.             ___cxa_free_exception(info.excPtr);
  2298.         }
  2299.     }
  2300.     function ___cxa_end_catch() {
  2301.         _setThrew(0);
  2302.         var catchInfo = exceptionCaught.pop();
  2303.         exception_decRef(catchInfo.get_exception_info());
  2304.         catchInfo.free();
  2305.         exceptionLast = 0;
  2306.     }
  2307.     function ___resumeException(catchInfoPtr) {
  2308.         var catchInfo = new CatchInfo(catchInfoPtr);
  2309.         var ptr = catchInfo.get_base_ptr();
  2310.         if (!exceptionLast) {
  2311.             exceptionLast = ptr;
  2312.         }
  2313.         catchInfo.free();
  2314.         throw ptr;
  2315.     }
  2316.     function ___cxa_find_matching_catch_2() {
  2317.         var thrown = exceptionLast;
  2318.         if (!thrown) {
  2319.             setTempRet0(0);
  2320.             return 0 | 0;
  2321.         }
  2322.         var info = new ExceptionInfo(thrown);
  2323.         var thrownType = info.get_type();
  2324.         var catchInfo = new CatchInfo();
  2325.         catchInfo.set_base_ptr(thrown);
  2326.         if (!thrownType) {
  2327.             setTempRet0(0);
  2328.             return catchInfo.ptr | 0;
  2329.         }
  2330.         var typeArray = Array.prototype.slice.call(arguments);
  2331.         var stackTop = stackSave();
  2332.         var exceptionThrowBuf = stackAlloc(4);
  2333.         HEAP32[exceptionThrowBuf >> 2] = thrown;
  2334.         for (var i = 0; i < typeArray.length; i++) {
  2335.             var caughtType = typeArray[i];
  2336.             if (caughtType === 0 || caughtType === thrownType) {
  2337.                 break;
  2338.             }
  2339.             if (___cxa_can_catch(caughtType, thrownType, exceptionThrowBuf)) {
  2340.                 var adjusted = HEAP32[exceptionThrowBuf >> 2];
  2341.                 if (thrown !== adjusted) {
  2342.                     catchInfo.set_adjusted_ptr(adjusted);
  2343.                 }
  2344.                 setTempRet0(caughtType);
  2345.                 return catchInfo.ptr | 0;
  2346.             }
  2347.         }
  2348.         stackRestore(stackTop);
  2349.         setTempRet0(thrownType);
  2350.         return catchInfo.ptr | 0;
  2351.     }
  2352.     function ___cxa_find_matching_catch_3() {
  2353.         var thrown = exceptionLast;
  2354.         if (!thrown) {
  2355.             setTempRet0(0);
  2356.             return 0 | 0;
  2357.         }
  2358.         var info = new ExceptionInfo(thrown);
  2359.         var thrownType = info.get_type();
  2360.         var catchInfo = new CatchInfo();
  2361.         catchInfo.set_base_ptr(thrown);
  2362.         if (!thrownType) {
  2363.             setTempRet0(0);
  2364.             return catchInfo.ptr | 0;
  2365.         }
  2366.         var typeArray = Array.prototype.slice.call(arguments);
  2367.         var stackTop = stackSave();
  2368.         var exceptionThrowBuf = stackAlloc(4);
  2369.         HEAP32[exceptionThrowBuf >> 2] = thrown;
  2370.         for (var i = 0; i < typeArray.length; i++) {
  2371.             var caughtType = typeArray[i];
  2372.             if (caughtType === 0 || caughtType === thrownType) {
  2373.                 break;
  2374.             }
  2375.             if (___cxa_can_catch(caughtType, thrownType, exceptionThrowBuf)) {
  2376.                 var adjusted = HEAP32[exceptionThrowBuf >> 2];
  2377.                 if (thrown !== adjusted) {
  2378.                     catchInfo.set_adjusted_ptr(adjusted);
  2379.                 }
  2380.                 setTempRet0(caughtType);
  2381.                 return catchInfo.ptr | 0;
  2382.             }
  2383.         }
  2384.         stackRestore(stackTop);
  2385.         setTempRet0(thrownType);
  2386.         return catchInfo.ptr | 0;
  2387.     }
  2388.     function ___cxa_find_matching_catch_4() {
  2389.         var thrown = exceptionLast;
  2390.         if (!thrown) {
  2391.             setTempRet0(0);
  2392.             return 0 | 0;
  2393.         }
  2394.         var info = new ExceptionInfo(thrown);
  2395.         var thrownType = info.get_type();
  2396.         var catchInfo = new CatchInfo();
  2397.         catchInfo.set_base_ptr(thrown);
  2398.         if (!thrownType) {
  2399.             setTempRet0(0);
  2400.             return catchInfo.ptr | 0;
  2401.         }
  2402.         var typeArray = Array.prototype.slice.call(arguments);
  2403.         var stackTop = stackSave();
  2404.         var exceptionThrowBuf = stackAlloc(4);
  2405.         HEAP32[exceptionThrowBuf >> 2] = thrown;
  2406.         for (var i = 0; i < typeArray.length; i++) {
  2407.             var caughtType = typeArray[i];
  2408.             if (caughtType === 0 || caughtType === thrownType) {
  2409.                 break;
  2410.             }
  2411.             if (___cxa_can_catch(caughtType, thrownType, exceptionThrowBuf)) {
  2412.                 var adjusted = HEAP32[exceptionThrowBuf >> 2];
  2413.                 if (thrown !== adjusted) {
  2414.                     catchInfo.set_adjusted_ptr(adjusted);
  2415.                 }
  2416.                 setTempRet0(caughtType);
  2417.                 return catchInfo.ptr | 0;
  2418.             }
  2419.         }
  2420.         stackRestore(stackTop);
  2421.         setTempRet0(thrownType);
  2422.         return catchInfo.ptr | 0;
  2423.     }
  2424.     function ___cxa_rethrow() {
  2425.         var catchInfo = exceptionCaught.pop();
  2426.         if (!catchInfo) {
  2427.             abort("no exception to throw");
  2428.         }
  2429.         var info = catchInfo.get_exception_info();
  2430.         var ptr = catchInfo.get_base_ptr();
  2431.         if (!info.get_rethrown()) {
  2432.             exceptionCaught.push(catchInfo);
  2433.             info.set_rethrown(true);
  2434.             info.set_caught(false);
  2435.             uncaughtExceptionCount++;
  2436.         } else {
  2437.             catchInfo.free();
  2438.         }
  2439.         exceptionLast = ptr;
  2440.         throw ptr;
  2441.     }
  2442.     function ___cxa_throw(ptr, type, destructor) {
  2443.         var info = new ExceptionInfo(ptr);
  2444.         info.init(type, destructor);
  2445.         exceptionLast = ptr;
  2446.         uncaughtExceptionCount++;
  2447.         throw ptr;
  2448.     }
  2449.     function _gmtime_r(time, tmPtr) {
  2450.         var date = new Date(HEAP32[time >> 2] * 1e3);
  2451.         HEAP32[tmPtr >> 2] = date.getUTCSeconds();
  2452.         HEAP32[(tmPtr + 4) >> 2] = date.getUTCMinutes();
  2453.         HEAP32[(tmPtr + 8) >> 2] = date.getUTCHours();
  2454.         HEAP32[(tmPtr + 12) >> 2] = date.getUTCDate();
  2455.         HEAP32[(tmPtr + 16) >> 2] = date.getUTCMonth();
  2456.         HEAP32[(tmPtr + 20) >> 2] = date.getUTCFullYear() - 1900;
  2457.         HEAP32[(tmPtr + 24) >> 2] = date.getUTCDay();
  2458.         HEAP32[(tmPtr + 36) >> 2] = 0;
  2459.         HEAP32[(tmPtr + 32) >> 2] = 0;
  2460.         var start = Date.UTC(date.getUTCFullYear(), 0, 1, 0, 0, 0, 0);
  2461.         var yday = ((date.getTime() - start) / (1e3 * 60 * 60 * 24)) | 0;
  2462.         HEAP32[(tmPtr + 28) >> 2] = yday;
  2463.         if (!_gmtime_r.GMTString) _gmtime_r.GMTString = allocateUTF8("GMT");
  2464.         HEAP32[(tmPtr + 40) >> 2] = _gmtime_r.GMTString;
  2465.         return tmPtr;
  2466.     }
  2467.     function ___gmtime_r(a0, a1) {
  2468.         return _gmtime_r(a0, a1);
  2469.     }
  2470.     function _tzset() {
  2471.         if (_tzset.called) return;
  2472.         _tzset.called = true;
  2473.         var currentYear = new Date().getFullYear();
  2474.         var winter = new Date(currentYear, 0, 1);
  2475.         var summer = new Date(currentYear, 6, 1);
  2476.         var winterOffset = winter.getTimezoneOffset();
  2477.         var summerOffset = summer.getTimezoneOffset();
  2478.         var stdTimezoneOffset = Math.max(winterOffset, summerOffset);
  2479.         HEAP32[__get_timezone() >> 2] = stdTimezoneOffset * 60;
  2480.         HEAP32[__get_daylight() >> 2] = Number(winterOffset != summerOffset);
  2481.         function extractZone(date) {
  2482.             var match = date.toTimeString().match(/\(([A-Za-z ]+)\)$/);
  2483.             return match ? match[1] : "GMT";
  2484.         }
  2485.         var winterName = extractZone(winter);
  2486.         var summerName = extractZone(summer);
  2487.         var winterNamePtr = allocateUTF8(winterName);
  2488.         var summerNamePtr = allocateUTF8(summerName);
  2489.         if (summerOffset < winterOffset) {
  2490.             HEAP32[__get_tzname() >> 2] = winterNamePtr;
  2491.             HEAP32[(__get_tzname() + 4) >> 2] = summerNamePtr;
  2492.         } else {
  2493.             HEAP32[__get_tzname() >> 2] = summerNamePtr;
  2494.             HEAP32[(__get_tzname() + 4) >> 2] = winterNamePtr;
  2495.         }
  2496.     }
  2497.     function _localtime_r(time, tmPtr) {
  2498.         _tzset();
  2499.         var date = new Date(HEAP32[time >> 2] * 1e3);
  2500.         HEAP32[tmPtr >> 2] = date.getSeconds();
  2501.         HEAP32[(tmPtr + 4) >> 2] = date.getMinutes();
  2502.         HEAP32[(tmPtr + 8) >> 2] = date.getHours();
  2503.         HEAP32[(tmPtr + 12) >> 2] = date.getDate();
  2504.         HEAP32[(tmPtr + 16) >> 2] = date.getMonth();
  2505.         HEAP32[(tmPtr + 20) >> 2] = date.getFullYear() - 1900;
  2506.         HEAP32[(tmPtr + 24) >> 2] = date.getDay();
  2507.         var start = new Date(date.getFullYear(), 0, 1);
  2508.         var yday = ((date.getTime() - start.getTime()) / (1e3 * 60 * 60 * 24)) | 0;
  2509.         HEAP32[(tmPtr + 28) >> 2] = yday;
  2510.         HEAP32[(tmPtr + 36) >> 2] = -(date.getTimezoneOffset() * 60);
  2511.         var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset();
  2512.         var winterOffset = start.getTimezoneOffset();
  2513.         var dst = (summerOffset != winterOffset && date.getTimezoneOffset() == Math.min(winterOffset, summerOffset)) | 0;
  2514.         HEAP32[(tmPtr + 32) >> 2] = dst;
  2515.         var zonePtr = HEAP32[(__get_tzname() + (dst ? 4 : 0)) >> 2];
  2516.         HEAP32[(tmPtr + 40) >> 2] = zonePtr;
  2517.         return tmPtr;
  2518.     }
  2519.     function ___localtime_r(a0, a1) {
  2520.         return _localtime_r(a0, a1);
  2521.     }
  2522.     var PATH = {
  2523.         splitPath: function (filename) {
  2524.             var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
  2525.             return splitPathRe.exec(filename).slice(1);
  2526.         },
  2527.         normalizeArray: function (parts, allowAboveRoot) {
  2528.             var up = 0;
  2529.             for (var i = parts.length - 1; i >= 0; i--) {
  2530.                 var last = parts[i];
  2531.                 if (last === ".") {
  2532.                     parts.splice(i, 1);
  2533.                 } else if (last === "..") {
  2534.                     parts.splice(i, 1);
  2535.                     up++;
  2536.                 } else if (up) {
  2537.                     parts.splice(i, 1);
  2538.                     up--;
  2539.                 }
  2540.             }
  2541.             if (allowAboveRoot) {
  2542.                 for (; up; up--) {
  2543.                     parts.unshift("..");
  2544.                 }
  2545.             }
  2546.             return parts;
  2547.         },
  2548.         normalize: function (path) {
  2549.             var isAbsolute = path.charAt(0) === "/",
  2550.                 trailingSlash = path.substr(-1) === "/";
  2551.             path = PATH.normalizeArray(
  2552.                 path.split("/").filter(function (p) {
  2553.                     return !!p;
  2554.                 }),
  2555.                 !isAbsolute
  2556.             ).join("/");
  2557.             if (!path && !isAbsolute) {
  2558.                 path = ".";
  2559.             }
  2560.             if (path && trailingSlash) {
  2561.                 path += "/";
  2562.             }
  2563.             return (isAbsolute ? "/" : "") + path;
  2564.         },
  2565.         dirname: function (path) {
  2566.             var result = PATH.splitPath(path),
  2567.                 root = result[0],
  2568.                 dir = result[1];
  2569.             if (!root && !dir) {
  2570.                 return ".";
  2571.             }
  2572.             if (dir) {
  2573.                 dir = dir.substr(0, dir.length - 1);
  2574.             }
  2575.             return root + dir;
  2576.         },
  2577.         basename: function (path) {
  2578.             if (path === "/") return "/";
  2579.             path = PATH.normalize(path);
  2580.             path = path.replace(/\/$/, "");
  2581.             var lastSlash = path.lastIndexOf("/");
  2582.             if (lastSlash === -1) return path;
  2583.             return path.substr(lastSlash + 1);
  2584.         },
  2585.         extname: function (path) {
  2586.             return PATH.splitPath(path)[3];
  2587.         },
  2588.         join: function () {
  2589.             var paths = Array.prototype.slice.call(arguments, 0);
  2590.             return PATH.normalize(paths.join("/"));
  2591.         },
  2592.         join2: function (l, r) {
  2593.             return PATH.normalize(l + "/" + r);
  2594.         },
  2595.     };
  2596.     function getRandomDevice() {
  2597.         if (typeof crypto === "object" && typeof crypto["getRandomValues"] === "function") {
  2598.             var randomBuffer = new Uint8Array(1);
  2599.             return function () {
  2600.                 crypto.getRandomValues(randomBuffer);
  2601.                 return randomBuffer[0];
  2602.             };
  2603.         } else if (ENVIRONMENT_IS_NODE) {
  2604.             try {
  2605.                 var crypto_module = require("crypto");
  2606.                 return function () {
  2607.                     return crypto_module["randomBytes"](1)[0];
  2608.                 };
  2609.             } catch (e) {}
  2610.         }
  2611.         return function () {
  2612.             abort("randomDevice");
  2613.         };
  2614.     }
  2615.     var PATH_FS = {
  2616.         resolve: function () {
  2617.             var resolvedPath = "",
  2618.                 resolvedAbsolute = false;
  2619.             for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
  2620.                 var path = i >= 0 ? arguments[i] : FS.cwd();
  2621.                 if (typeof path !== "string") {
  2622.                     throw new TypeError("Arguments to path.resolve must be strings");
  2623.                 } else if (!path) {
  2624.                     return "";
  2625.                 }
  2626.                 resolvedPath = path + "/" + resolvedPath;
  2627.                 resolvedAbsolute = path.charAt(0) === "/";
  2628.             }
  2629.             resolvedPath = PATH.normalizeArray(
  2630.                 resolvedPath.split("/").filter(function (p) {
  2631.                     return !!p;
  2632.                 }),
  2633.                 !resolvedAbsolute
  2634.             ).join("/");
  2635.             return (resolvedAbsolute ? "/" : "") + resolvedPath || ".";
  2636.         },
  2637.         relative: function (from, to) {
  2638.             from = PATH_FS.resolve(from).substr(1);
  2639.             to = PATH_FS.resolve(to).substr(1);
  2640.             function trim(arr) {
  2641.                 var start = 0;
  2642.                 for (; start < arr.length; start++) {
  2643.                     if (arr[start] !== "") break;
  2644.                 }
  2645.                 var end = arr.length - 1;
  2646.                 for (; end >= 0; end--) {
  2647.                     if (arr[end] !== "") break;
  2648.                 }
  2649.                 if (start > end) return [];
  2650.                 return arr.slice(start, end - start + 1);
  2651.             }
  2652.             var fromParts = trim(from.split("/"));
  2653.             var toParts = trim(to.split("/"));
  2654.             var length = Math.min(fromParts.length, toParts.length);
  2655.             var samePartsLength = length;
  2656.             for (var i = 0; i < length; i++) {
  2657.                 if (fromParts[i] !== toParts[i]) {
  2658.                     samePartsLength = i;
  2659.                     break;
  2660.                 }
  2661.             }
  2662.             var outputParts = [];
  2663.             for (var i = samePartsLength; i < fromParts.length; i++) {
  2664.                 outputParts.push("..");
  2665.             }
  2666.             outputParts = outputParts.concat(toParts.slice(samePartsLength));
  2667.             return outputParts.join("/");
  2668.         },
  2669.     };
  2670.     var TTY = {
  2671.         ttys: [],
  2672.         init: function () {},
  2673.         shutdown: function () {},
  2674.         register: function (dev, ops) {
  2675.             TTY.ttys[dev] = { input: [], output: [], ops: ops };
  2676.             FS.registerDevice(dev, TTY.stream_ops);
  2677.         },
  2678.         stream_ops: {
  2679.             open: function (stream) {
  2680.                 var tty = TTY.ttys[stream.node.rdev];
  2681.                 if (!tty) {
  2682.                     throw new FS.ErrnoError(43);
  2683.                 }
  2684.                 stream.tty = tty;
  2685.                 stream.seekable = false;
  2686.             },
  2687.             close: function (stream) {
  2688.                 stream.tty.ops.flush(stream.tty);
  2689.             },
  2690.             flush: function (stream) {
  2691.                 stream.tty.ops.flush(stream.tty);
  2692.             },
  2693.             read: function (stream, buffer, offset, length, pos) {
  2694.                 if (!stream.tty || !stream.tty.ops.get_char) {
  2695.                     throw new FS.ErrnoError(60);
  2696.                 }
  2697.                 var bytesRead = 0;
  2698.                 for (var i = 0; i < length; i++) {
  2699.                     var result;
  2700.                     try {
  2701.                         result = stream.tty.ops.get_char(stream.tty);
  2702.                     } catch (e) {
  2703.                         throw new FS.ErrnoError(29);
  2704.                     }
  2705.                     if (result === undefined && bytesRead === 0) {
  2706.                         throw new FS.ErrnoError(6);
  2707.                     }
  2708.                     if (result === null || result === undefined) break;
  2709.                     bytesRead++;
  2710.                     buffer[offset + i] = result;
  2711.                 }
  2712.                 if (bytesRead) {
  2713.                     stream.node.timestamp = Date.now();
  2714.                 }
  2715.                 return bytesRead;
  2716.             },
  2717.             write: function (stream, buffer, offset, length, pos) {
  2718.                 if (!stream.tty || !stream.tty.ops.put_char) {
  2719.                     throw new FS.ErrnoError(60);
  2720.                 }
  2721.                 try {
  2722.                     for (var i = 0; i < length; i++) {
  2723.                         stream.tty.ops.put_char(stream.tty, buffer[offset + i]);
  2724.                     }
  2725.                 } catch (e) {
  2726.                     throw new FS.ErrnoError(29);
  2727.                 }
  2728.                 if (length) {
  2729.                     stream.node.timestamp = Date.now();
  2730.                 }
  2731.                 return i;
  2732.             },
  2733.         },
  2734.         default_tty_ops: {
  2735.             get_char: function (tty) {
  2736.                 if (!tty.input.length) {
  2737.                     var result = null;
  2738.                     if (ENVIRONMENT_IS_NODE) {
  2739.                         var BUFSIZE = 256;
  2740.                         var buf = Buffer.alloc ? Buffer.alloc(BUFSIZE) : new Buffer(BUFSIZE);
  2741.                         var bytesRead = 0;
  2742.                         try {
  2743.                             bytesRead = nodeFS.readSync(process.stdin.fd, buf, 0, BUFSIZE, null);
  2744.                         } catch (e) {
  2745.                             if (e.toString().includes("EOF")) bytesRead = 0;
  2746.                             else throw e;
  2747.                         }
  2748.                         if (bytesRead > 0) {
  2749.                             result = buf.slice(0, bytesRead).toString("utf-8");
  2750.                         } else {
  2751.                             result = null;
  2752.                         }
  2753.                     } else if (typeof window != "undefined" && typeof window.prompt == "function") {
  2754.                         result = window.prompt("Input: ");
  2755.                         if (result !== null) {
  2756.                             result += "\n";
  2757.                         }
  2758.                     } else if (typeof readline == "function") {
  2759.                         result = readline();
  2760.                         if (result !== null) {
  2761.                             result += "\n";
  2762.                         }
  2763.                     }
  2764.                     if (!result) {
  2765.                         return null;
  2766.                     }
  2767.                     tty.input = intArrayFromString(result, true);
  2768.                 }
  2769.                 return tty.input.shift();
  2770.             },
  2771.             put_char: function (tty, val) {
  2772.                 if (val === null || val === 10) {
  2773.                     out(UTF8ArrayToString(tty.output, 0));
  2774.                     tty.output = [];
  2775.                 } else {
  2776.                     if (val != 0) tty.output.push(val);
  2777.                 }
  2778.             },
  2779.             flush: function (tty) {
  2780.                 if (tty.output && tty.output.length > 0) {
  2781.                     out(UTF8ArrayToString(tty.output, 0));
  2782.                     tty.output = [];
  2783.                 }
  2784.             },
  2785.         },
  2786.         default_tty1_ops: {
  2787.             put_char: function (tty, val) {
  2788.                 if (val === null || val === 10) {
  2789.                     err(UTF8ArrayToString(tty.output, 0));
  2790.                     tty.output = [];
  2791.                 } else {
  2792.                     if (val != 0) tty.output.push(val);
  2793.                 }
  2794.             },
  2795.             flush: function (tty) {
  2796.                 if (tty.output && tty.output.length > 0) {
  2797.                     err(UTF8ArrayToString(tty.output, 0));
  2798.                     tty.output = [];
  2799.                 }
  2800.             },
  2801.         },
  2802.     };
  2803.     function mmapAlloc(size) {
  2804.         var alignedSize = alignMemory(size, 65536);
  2805.         var ptr = _malloc(alignedSize);
  2806.         while (size < alignedSize) HEAP8[ptr + size++] = 0;
  2807.         return ptr;
  2808.     }
  2809.     var MEMFS = {
  2810.         ops_table: null,
  2811.         mount: function (mount) {
  2812.             return MEMFS.createNode(null, "/", 16384 | 511, 0);
  2813.         },
  2814.         createNode: function (parent, name, mode, dev) {
  2815.             if (FS.isBlkdev(mode) || FS.isFIFO(mode)) {
  2816.                 throw new FS.ErrnoError(63);
  2817.             }
  2818.             if (!MEMFS.ops_table) {
  2819.                 MEMFS.ops_table = {
  2820.                     dir: {
  2821.                         node: {
  2822.                             getattr: MEMFS.node_ops.getattr,
  2823.                             setattr: MEMFS.node_ops.setattr,
  2824.                             lookup: MEMFS.node_ops.lookup,
  2825.                             mknod: MEMFS.node_ops.mknod,
  2826.                             rename: MEMFS.node_ops.rename,
  2827.                             unlink: MEMFS.node_ops.unlink,
  2828.                             rmdir: MEMFS.node_ops.rmdir,
  2829.                             readdir: MEMFS.node_ops.readdir,
  2830.                             symlink: MEMFS.node_ops.symlink,
  2831.                         },
  2832.                         stream: { llseek: MEMFS.stream_ops.llseek },
  2833.                     },
  2834.                     file: {
  2835.                         node: { getattr: MEMFS.node_ops.getattr, setattr: MEMFS.node_ops.setattr },
  2836.                         stream: { llseek: MEMFS.stream_ops.llseek, read: MEMFS.stream_ops.read, write: MEMFS.stream_ops.write, allocate: MEMFS.stream_ops.allocate, mmap: MEMFS.stream_ops.mmap, msync: MEMFS.stream_ops.msync },
  2837.                     },
  2838.                     link: { node: { getattr: MEMFS.node_ops.getattr, setattr: MEMFS.node_ops.setattr, readlink: MEMFS.node_ops.readlink }, stream: {} },
  2839.                     chrdev: { node: { getattr: MEMFS.node_ops.getattr, setattr: MEMFS.node_ops.setattr }, stream: FS.chrdev_stream_ops },
  2840.                 };
  2841.             }
  2842.             var node = FS.createNode(parent, name, mode, dev);
  2843.             if (FS.isDir(node.mode)) {
  2844.                 node.node_ops = MEMFS.ops_table.dir.node;
  2845.                 node.stream_ops = MEMFS.ops_table.dir.stream;
  2846.                 node.contents = {};
  2847.             } else if (FS.isFile(node.mode)) {
  2848.                 node.node_ops = MEMFS.ops_table.file.node;
  2849.                 node.stream_ops = MEMFS.ops_table.file.stream;
  2850.                 node.usedBytes = 0;
  2851.                 node.contents = null;
  2852.             } else if (FS.isLink(node.mode)) {
  2853.                 node.node_ops = MEMFS.ops_table.link.node;
  2854.                 node.stream_ops = MEMFS.ops_table.link.stream;
  2855.             } else if (FS.isChrdev(node.mode)) {
  2856.                 node.node_ops = MEMFS.ops_table.chrdev.node;
  2857.                 node.stream_ops = MEMFS.ops_table.chrdev.stream;
  2858.             }
  2859.             node.timestamp = Date.now();
  2860.             if (parent) {
  2861.                 parent.contents[name] = node;
  2862.                 parent.timestamp = node.timestamp;
  2863.             }
  2864.             return node;
  2865.         },
  2866.         getFileDataAsTypedArray: function (node) {
  2867.             if (!node.contents) return new Uint8Array(0);
  2868.             if (node.contents.subarray) return node.contents.subarray(0, node.usedBytes);
  2869.             return new Uint8Array(node.contents);
  2870.         },
  2871.         expandFileStorage: function (node, newCapacity) {
  2872.             var prevCapacity = node.contents ? node.contents.length : 0;
  2873.             if (prevCapacity >= newCapacity) return;
  2874.             var CAPACITY_DOUBLING_MAX = 1024 * 1024;
  2875.             newCapacity = Math.max(newCapacity, (prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2 : 1.125)) >>> 0);
  2876.             if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256);
  2877.             var oldContents = node.contents;
  2878.             node.contents = new Uint8Array(newCapacity);
  2879.             if (node.usedBytes > 0) node.contents.set(oldContents.subarray(0, node.usedBytes), 0);
  2880.         },
  2881.         resizeFileStorage: function (node, newSize) {
  2882.             if (node.usedBytes == newSize) return;
  2883.             if (newSize == 0) {
  2884.                 node.contents = null;
  2885.                 node.usedBytes = 0;
  2886.             } else {
  2887.                 var oldContents = node.contents;
  2888.                 node.contents = new Uint8Array(newSize);
  2889.                 if (oldContents) {
  2890.                     node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes)));
  2891.                 }
  2892.                 node.usedBytes = newSize;
  2893.             }
  2894.         },
  2895.         node_ops: {
  2896.             getattr: function (node) {
  2897.                 var attr = {};
  2898.                 attr.dev = FS.isChrdev(node.mode) ? node.id : 1;
  2899.                 attr.ino = node.id;
  2900.                 attr.mode = node.mode;
  2901.                 attr.nlink = 1;
  2902.                 attr.uid = 0;
  2903.                 attr.gid = 0;
  2904.                 attr.rdev = node.rdev;
  2905.                 if (FS.isDir(node.mode)) {
  2906.                     attr.size = 4096;
  2907.                 } else if (FS.isFile(node.mode)) {
  2908.                     attr.size = node.usedBytes;
  2909.                 } else if (FS.isLink(node.mode)) {
  2910.                     attr.size = node.link.length;
  2911.                 } else {
  2912.                     attr.size = 0;
  2913.                 }
  2914.                 attr.atime = new Date(node.timestamp);
  2915.                 attr.mtime = new Date(node.timestamp);
  2916.                 attr.ctime = new Date(node.timestamp);
  2917.                 attr.blksize = 4096;
  2918.                 attr.blocks = Math.ceil(attr.size / attr.blksize);
  2919.                 return attr;
  2920.             },
  2921.             setattr: function (node, attr) {
  2922.                 if (attr.mode !== undefined) {
  2923.                     node.mode = attr.mode;
  2924.                 }
  2925.                 if (attr.timestamp !== undefined) {
  2926.                     node.timestamp = attr.timestamp;
  2927.                 }
  2928.                 if (attr.size !== undefined) {
  2929.                     MEMFS.resizeFileStorage(node, attr.size);
  2930.                 }
  2931.             },
  2932.             lookup: function (parent, name) {
  2933.                 throw FS.genericErrors[44];
  2934.             },
  2935.             mknod: function (parent, name, mode, dev) {
  2936.                 return MEMFS.createNode(parent, name, mode, dev);
  2937.             },
  2938.             rename: function (old_node, new_dir, new_name) {
  2939.                 if (FS.isDir(old_node.mode)) {
  2940.                     var new_node;
  2941.                     try {
  2942.                         new_node = FS.lookupNode(new_dir, new_name);
  2943.                     } catch (e) {}
  2944.                     if (new_node) {
  2945.                         for (var i in new_node.contents) {
  2946.                             throw new FS.ErrnoError(55);
  2947.                         }
  2948.                     }
  2949.                 }
  2950.                 delete old_node.parent.contents[old_node.name];
  2951.                 old_node.parent.timestamp = Date.now();
  2952.                 old_node.name = new_name;
  2953.                 new_dir.contents[new_name] = old_node;
  2954.                 new_dir.timestamp = old_node.parent.timestamp;
  2955.                 old_node.parent = new_dir;
  2956.             },
  2957.             unlink: function (parent, name) {
  2958.                 delete parent.contents[name];
  2959.                 parent.timestamp = Date.now();
  2960.             },
  2961.             rmdir: function (parent, name) {
  2962.                 var node = FS.lookupNode(parent, name);
  2963.                 for (var i in node.contents) {
  2964.                     throw new FS.ErrnoError(55);
  2965.                 }
  2966.                 delete parent.contents[name];
  2967.                 parent.timestamp = Date.now();
  2968.             },
  2969.             readdir: function (node) {
  2970.                 var entries = [".", ".."];
  2971.                 for (var key in node.contents) {
  2972.                     if (!node.contents.hasOwnProperty(key)) {
  2973.                         continue;
  2974.                     }
  2975.                     entries.push(key);
  2976.                 }
  2977.                 return entries;
  2978.             },
  2979.             symlink: function (parent, newname, oldpath) {
  2980.                 var node = MEMFS.createNode(parent, newname, 511 | 40960, 0);
  2981.                 node.link = oldpath;
  2982.                 return node;
  2983.             },
  2984.             readlink: function (node) {
  2985.                 if (!FS.isLink(node.mode)) {
  2986.                     throw new FS.ErrnoError(28);
  2987.                 }
  2988.                 return node.link;
  2989.             },
  2990.         },
  2991.         stream_ops: {
  2992.             read: function (stream, buffer, offset, length, position) {
  2993.                 var contents = stream.node.contents;
  2994.                 if (position >= stream.node.usedBytes) return 0;
  2995.                 var size = Math.min(stream.node.usedBytes - position, length);
  2996.                 if (size > 8 && contents.subarray) {
  2997.                     buffer.set(contents.subarray(position, position + size), offset);
  2998.                 } else {
  2999.                     for (var i = 0; i < size; i++) buffer[offset + i] = contents[position + i];
  3000.                 }
  3001.                 return size;
  3002.             },
  3003.             write: function (stream, buffer, offset, length, position, canOwn) {
  3004.                 if (buffer.buffer === HEAP8.buffer) {
  3005.                     canOwn = false;
  3006.                 }
  3007.                 if (!length) return 0;
  3008.                 var node = stream.node;
  3009.                 node.timestamp = Date.now();
  3010.                 if (buffer.subarray && (!node.contents || node.contents.subarray)) {
  3011.                     if (canOwn) {
  3012.                         node.contents = buffer.subarray(offset, offset + length);
  3013.                         node.usedBytes = length;
  3014.                         return length;
  3015.                     } else if (node.usedBytes === 0 && position === 0) {
  3016.                         node.contents = buffer.slice(offset, offset + length);
  3017.                         node.usedBytes = length;
  3018.                         return length;
  3019.                     } else if (position + length <= node.usedBytes) {
  3020.                         node.contents.set(buffer.subarray(offset, offset + length), position);
  3021.                         return length;
  3022.                     }
  3023.                 }
  3024.                 MEMFS.expandFileStorage(node, position + length);
  3025.                 if (node.contents.subarray && buffer.subarray) {
  3026.                     node.contents.set(buffer.subarray(offset, offset + length), position);
  3027.                 } else {
  3028.                     for (var i = 0; i < length; i++) {
  3029.                         node.contents[position + i] = buffer[offset + i];
  3030.                     }
  3031.                 }
  3032.                 node.usedBytes = Math.max(node.usedBytes, position + length);
  3033.                 return length;
  3034.             },
  3035.             llseek: function (stream, offset, whence) {
  3036.                 var position = offset;
  3037.                 if (whence === 1) {
  3038.                     position += stream.position;
  3039.                 } else if (whence === 2) {
  3040.                     if (FS.isFile(stream.node.mode)) {
  3041.                         position += stream.node.usedBytes;
  3042.                     }
  3043.                 }
  3044.                 if (position < 0) {
  3045.                     throw new FS.ErrnoError(28);
  3046.                 }
  3047.                 return position;
  3048.             },
  3049.             allocate: function (stream, offset, length) {
  3050.                 MEMFS.expandFileStorage(stream.node, offset + length);
  3051.                 stream.node.usedBytes = Math.max(stream.node.usedBytes, offset + length);
  3052.             },
  3053.             mmap: function (stream, address, length, position, prot, flags) {
  3054.                 if (address !== 0) {
  3055.                     throw new FS.ErrnoError(28);
  3056.                 }
  3057.                 if (!FS.isFile(stream.node.mode)) {
  3058.                     throw new FS.ErrnoError(43);
  3059.                 }
  3060.                 var ptr;
  3061.                 var allocated;
  3062.                 var contents = stream.node.contents;
  3063.                 if (!(flags & 2) && contents.buffer === buffer) {
  3064.                     allocated = false;
  3065.                     ptr = contents.byteOffset;
  3066.                 } else {
  3067.                     if (position > 0 || position + length < contents.length) {
  3068.                         if (contents.subarray) {
  3069.                             contents = contents.subarray(position, position + length);
  3070.                         } else {
  3071.                             contents = Array.prototype.slice.call(contents, position, position + length);
  3072.                         }
  3073.                     }
  3074.                     allocated = true;
  3075.                     ptr = mmapAlloc(length);
  3076.                     if (!ptr) {
  3077.                         throw new FS.ErrnoError(48);
  3078.                     }
  3079.                     HEAP8.set(contents, ptr);
  3080.                 }
  3081.                 return { ptr: ptr, allocated: allocated };
  3082.             },
  3083.             msync: function (stream, buffer, offset, length, mmapFlags) {
  3084.                 if (!FS.isFile(stream.node.mode)) {
  3085.                     throw new FS.ErrnoError(43);
  3086.                 }
  3087.                 if (mmapFlags & 2) {
  3088.                     return 0;
  3089.                 }
  3090.                 var bytesWritten = MEMFS.stream_ops.write(stream, buffer, 0, length, offset, false);
  3091.                 return 0;
  3092.             },
  3093.         },
  3094.     };
  3095.     var IDBFS = {
  3096.         dbs: {},
  3097.         indexedDB: function () {
  3098.             if (typeof indexedDB !== "undefined") return indexedDB;
  3099.             var ret = null;
  3100.             if (typeof window === "object") ret = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
  3101.             assert(ret, "IDBFS used, but indexedDB not supported");
  3102.             return ret;
  3103.         },
  3104.         DB_VERSION: 21,
  3105.         DB_STORE_NAME: "FILE_DATA",
  3106.         mount: function (mount) {
  3107.             return MEMFS.mount.apply(null, arguments);
  3108.         },
  3109.         syncfs: function (mount, populate, callback) {
  3110.             IDBFS.getLocalSet(mount, function (err, local) {
  3111.                 if (err) return callback(err);
  3112.                 IDBFS.getRemoteSet(mount, function (err, remote) {
  3113.                     if (err) return callback(err);
  3114.                     var src = populate ? remote : local;
  3115.                     var dst = populate ? local : remote;
  3116.                     IDBFS.reconcile(src, dst, callback);
  3117.                 });
  3118.             });
  3119.         },
  3120.         getDB: function (name, callback) {
  3121.             var db = IDBFS.dbs[name];
  3122.             if (db) {
  3123.                 return callback(null, db);
  3124.             }
  3125.             var req;
  3126.             try {
  3127.                 req = IDBFS.indexedDB().open(name, IDBFS.DB_VERSION);
  3128.             } catch (e) {
  3129.                 return callback(e);
  3130.             }
  3131.             if (!req) {
  3132.                 return callback("Unable to connect to IndexedDB");
  3133.             }
  3134.             req.onupgradeneeded = function (e) {
  3135.                 var db = e.target.result;
  3136.                 var transaction = e.target.transaction;
  3137.                 var fileStore;
  3138.                 if (db.objectStoreNames.contains(IDBFS.DB_STORE_NAME)) {
  3139.                     fileStore = transaction.objectStore(IDBFS.DB_STORE_NAME);
  3140.                 } else {
  3141.                     fileStore = db.createObjectStore(IDBFS.DB_STORE_NAME);
  3142.                 }
  3143.                 if (!fileStore.indexNames.contains("timestamp")) {
  3144.                     fileStore.createIndex("timestamp", "timestamp", { unique: false });
  3145.                 }
  3146.             };
  3147.             req.onsuccess = function () {
  3148.                 db = req.result;
  3149.                 IDBFS.dbs[name] = db;
  3150.                 callback(null, db);
  3151.             };
  3152.             req.onerror = function (e) {
  3153.                 callback(this.error);
  3154.                 e.preventDefault();
  3155.             };
  3156.         },
  3157.         getLocalSet: function (mount, callback) {
  3158.             var entries = {};
  3159.             function isRealDir(p) {
  3160.                 return p !== "." && p !== "..";
  3161.             }
  3162.             function toAbsolute(root) {
  3163.                 return function (p) {
  3164.                     return PATH.join2(root, p);
  3165.                 };
  3166.             }
  3167.             var check = FS.readdir(mount.mountpoint).filter(isRealDir).map(toAbsolute(mount.mountpoint));
  3168.             while (check.length) {
  3169.                 var path = check.pop();
  3170.                 var stat;
  3171.                 try {
  3172.                     stat = FS.stat(path);
  3173.                 } catch (e) {
  3174.                     return callback(e);
  3175.                 }
  3176.                 if (FS.isDir(stat.mode)) {
  3177.                     check.push.apply(check, FS.readdir(path).filter(isRealDir).map(toAbsolute(path)));
  3178.                 }
  3179.                 entries[path] = { timestamp: stat.mtime };
  3180.             }
  3181.             return callback(null, { type: "local", entries: entries });
  3182.         },
  3183.         getRemoteSet: function (mount, callback) {
  3184.             var entries = {};
  3185.             IDBFS.getDB(mount.mountpoint, function (err, db) {
  3186.                 if (err) return callback(err);
  3187.                 try {
  3188.                     var transaction = db.transaction([IDBFS.DB_STORE_NAME], "readonly");
  3189.                     transaction.onerror = function (e) {
  3190.                         callback(this.error);
  3191.                         e.preventDefault();
  3192.                     };
  3193.                     var store = transaction.objectStore(IDBFS.DB_STORE_NAME);
  3194.                     var index = store.index("timestamp");
  3195.                     index.openKeyCursor().onsuccess = function (event) {
  3196.                         var cursor = event.target.result;
  3197.                         if (!cursor) {
  3198.                             return callback(null, { type: "remote", db: db, entries: entries });
  3199.                         }
  3200.                         entries[cursor.primaryKey] = { timestamp: cursor.key };
  3201.                         cursor.continue();
  3202.                     };
  3203.                 } catch (e) {
  3204.                     return callback(e);
  3205.                 }
  3206.             });
  3207.         },
  3208.         loadLocalEntry: function (path, callback) {
  3209.             var stat, node;
  3210.             try {
  3211.                 var lookup = FS.lookupPath(path);
  3212.                 node = lookup.node;
  3213.                 stat = FS.stat(path);
  3214.             } catch (e) {
  3215.                 return callback(e);
  3216.             }
  3217.             if (FS.isDir(stat.mode)) {
  3218.                 return callback(null, { timestamp: stat.mtime, mode: stat.mode });
  3219.             } else if (FS.isFile(stat.mode)) {
  3220.                 node.contents = MEMFS.getFileDataAsTypedArray(node);
  3221.                 return callback(null, { timestamp: stat.mtime, mode: stat.mode, contents: node.contents });
  3222.             } else {
  3223.                 return callback(new Error("node type not supported"));
  3224.             }
  3225.         },
  3226.         storeLocalEntry: function (path, entry, callback) {
  3227.             try {
  3228.                 if (FS.isDir(entry["mode"])) {
  3229.                     FS.mkdirTree(path, entry["mode"]);
  3230.                 } else if (FS.isFile(entry["mode"])) {
  3231.                     FS.writeFile(path, entry["contents"], { canOwn: true });
  3232.                 } else {
  3233.                     return callback(new Error("node type not supported"));
  3234.                 }
  3235.                 FS.chmod(path, entry["mode"]);
  3236.                 FS.utime(path, entry["timestamp"], entry["timestamp"]);
  3237.             } catch (e) {
  3238.                 return callback(e);
  3239.             }
  3240.             callback(null);
  3241.         },
  3242.         removeLocalEntry: function (path, callback) {
  3243.             try {
  3244.                 var lookup = FS.lookupPath(path);
  3245.                 var stat = FS.stat(path);
  3246.                 if (FS.isDir(stat.mode)) {
  3247.                     FS.rmdir(path);
  3248.                 } else if (FS.isFile(stat.mode)) {
  3249.                     FS.unlink(path);
  3250.                 }
  3251.             } catch (e) {
  3252.                 return callback(e);
  3253.             }
  3254.             callback(null);
  3255.         },
  3256.         loadRemoteEntry: function (store, path, callback) {
  3257.             var req = store.get(path);
  3258.             req.onsuccess = function (event) {
  3259.                 callback(null, event.target.result);
  3260.             };
  3261.             req.onerror = function (e) {
  3262.                 callback(this.error);
  3263.                 e.preventDefault();
  3264.             };
  3265.         },
  3266.         storeRemoteEntry: function (store, path, entry, callback) {
  3267.             var req = store.put(entry, path);
  3268.             req.onsuccess = function () {
  3269.                 callback(null);
  3270.             };
  3271.             req.onerror = function (e) {
  3272.                 callback(this.error);
  3273.                 e.preventDefault();
  3274.             };
  3275.         },
  3276.         removeRemoteEntry: function (store, path, callback) {
  3277.             var req = store.delete(path);
  3278.             req.onsuccess = function () {
  3279.                 callback(null);
  3280.             };
  3281.             req.onerror = function (e) {
  3282.                 callback(this.error);
  3283.                 e.preventDefault();
  3284.             };
  3285.         },
  3286.         reconcile: function (src, dst, callback) {
  3287.             var total = 0;
  3288.             var create = [];
  3289.             Object.keys(src.entries).forEach(function (key) {
  3290.                 var e = src.entries[key];
  3291.                 var e2 = dst.entries[key];
  3292.                 if (!e2 || e["timestamp"].getTime() != e2["timestamp"].getTime()) {
  3293.                     create.push(key);
  3294.                     total++;
  3295.                 }
  3296.             });
  3297.             var remove = [];
  3298.             Object.keys(dst.entries).forEach(function (key) {
  3299.                 if (!src.entries[key]) {
  3300.                     remove.push(key);
  3301.                     total++;
  3302.                 }
  3303.             });
  3304.             if (!total) {
  3305.                 return callback(null);
  3306.             }
  3307.             var errored = false;
  3308.             var db = src.type === "remote" ? src.db : dst.db;
  3309.             var transaction = db.transaction([IDBFS.DB_STORE_NAME], "readwrite");
  3310.             var store = transaction.objectStore(IDBFS.DB_STORE_NAME);
  3311.             function done(err) {
  3312.                 if (err && !errored) {
  3313.                     errored = true;
  3314.                     return callback(err);
  3315.                 }
  3316.             }
  3317.             transaction.onerror = function (e) {
  3318.                 done(this.error);
  3319.                 e.preventDefault();
  3320.             };
  3321.             transaction.oncomplete = function (e) {
  3322.                 if (!errored) {
  3323.                     callback(null);
  3324.                 }
  3325.             };
  3326.             create.sort().forEach(function (path) {
  3327.                 if (dst.type === "local") {
  3328.                     IDBFS.loadRemoteEntry(store, path, function (err, entry) {
  3329.                         if (err) return done(err);
  3330.                         IDBFS.storeLocalEntry(path, entry, done);
  3331.                     });
  3332.                 } else {
  3333.                     IDBFS.loadLocalEntry(path, function (err, entry) {
  3334.                         if (err) return done(err);
  3335.                         IDBFS.storeRemoteEntry(store, path, entry, done);
  3336.                     });
  3337.                 }
  3338.             });
  3339.             remove
  3340.                 .sort()
  3341.                 .reverse()
  3342.                 .forEach(function (path) {
  3343.                     if (dst.type === "local") {
  3344.                         IDBFS.removeLocalEntry(path, done);
  3345.                     } else {
  3346.                         IDBFS.removeRemoteEntry(store, path, done);
  3347.                     }
  3348.                 });
  3349.         },
  3350.     };
  3351.     var FS = {
  3352.         root: null,
  3353.         mounts: [],
  3354.         devices: {},
  3355.         streams: [],
  3356.         nextInode: 1,
  3357.         nameTable: null,
  3358.         currentPath: "/",
  3359.         initialized: false,
  3360.         ignorePermissions: true,
  3361.         trackingDelegate: {},
  3362.         tracking: { openFlags: { READ: 1, WRITE: 2 } },
  3363.         ErrnoError: null,
  3364.         genericErrors: {},
  3365.         filesystems: null,
  3366.         syncFSRequests: 0,
  3367.         lookupPath: function (path, opts) {
  3368.             path = PATH_FS.resolve(FS.cwd(), path);
  3369.             opts = opts || {};
  3370.             if (!path) return { path: "", node: null };
  3371.             var defaults = { follow_mount: true, recurse_count: 0 };
  3372.             for (var key in defaults) {
  3373.                 if (opts[key] === undefined) {
  3374.                     opts[key] = defaults[key];
  3375.                 }
  3376.             }
  3377.             if (opts.recurse_count > 8) {
  3378.                 throw new FS.ErrnoError(32);
  3379.             }
  3380.             var parts = PATH.normalizeArray(
  3381.                 path.split("/").filter(function (p) {
  3382.                     return !!p;
  3383.                 }),
  3384.                 false
  3385.             );
  3386.             var current = FS.root;
  3387.             var current_path = "/";
  3388.             for (var i = 0; i < parts.length; i++) {
  3389.                 var islast = i === parts.length - 1;
  3390.                 if (islast && opts.parent) {
  3391.                     break;
  3392.                 }
  3393.                 current = FS.lookupNode(current, parts[i]);
  3394.                 current_path = PATH.join2(current_path, parts[i]);
  3395.                 if (FS.isMountpoint(current)) {
  3396.                     if (!islast || (islast && opts.follow_mount)) {
  3397.                         current = current.mounted.root;
  3398.                     }
  3399.                 }
  3400.                 if (!islast || opts.follow) {
  3401.                     var count = 0;
  3402.                     while (FS.isLink(current.mode)) {
  3403.                         var link = FS.readlink(current_path);
  3404.                         current_path = PATH_FS.resolve(PATH.dirname(current_path), link);
  3405.                         var lookup = FS.lookupPath(current_path, { recurse_count: opts.recurse_count });
  3406.                         current = lookup.node;
  3407.                         if (count++ > 40) {
  3408.                             throw new FS.ErrnoError(32);
  3409.                         }
  3410.                     }
  3411.                 }
  3412.             }
  3413.             return { path: current_path, node: current };
  3414.         },
  3415.         getPath: function (node) {
  3416.             var path;
  3417.             while (true) {
  3418.                 if (FS.isRoot(node)) {
  3419.                     var mount = node.mount.mountpoint;
  3420.                     if (!path) return mount;
  3421.                     return mount[mount.length - 1] !== "/" ? mount + "/" + path : mount + path;
  3422.                 }
  3423.                 path = path ? node.name + "/" + path : node.name;
  3424.                 node = node.parent;
  3425.             }
  3426.         },
  3427.         hashName: function (parentid, name) {
  3428.             var hash = 0;
  3429.             for (var i = 0; i < name.length; i++) {
  3430.                 hash = ((hash << 5) - hash + name.charCodeAt(i)) | 0;
  3431.             }
  3432.             return ((parentid + hash) >>> 0) % FS.nameTable.length;
  3433.         },
  3434.         hashAddNode: function (node) {
  3435.             var hash = FS.hashName(node.parent.id, node.name);
  3436.             node.name_next = FS.nameTable[hash];
  3437.             FS.nameTable[hash] = node;
  3438.         },
  3439.         hashRemoveNode: function (node) {
  3440.             var hash = FS.hashName(node.parent.id, node.name);
  3441.             if (FS.nameTable[hash] === node) {
  3442.                 FS.nameTable[hash] = node.name_next;
  3443.             } else {
  3444.                 var current = FS.nameTable[hash];
  3445.                 while (current) {
  3446.                     if (current.name_next === node) {
  3447.                         current.name_next = node.name_next;
  3448.                         break;
  3449.                     }
  3450.                     current = current.name_next;
  3451.                 }
  3452.             }
  3453.         },
  3454.         lookupNode: function (parent, name) {
  3455.             var errCode = FS.mayLookup(parent);
  3456.             if (errCode) {
  3457.                 throw new FS.ErrnoError(errCode, parent);
  3458.             }
  3459.             var hash = FS.hashName(parent.id, name);
  3460.             for (var node = FS.nameTable[hash]; node; node = node.name_next) {
  3461.                 var nodeName = node.name;
  3462.                 if (node.parent.id === parent.id && nodeName === name) {
  3463.                     return node;
  3464.                 }
  3465.             }
  3466.             return FS.lookup(parent, name);
  3467.         },
  3468.         createNode: function (parent, name, mode, rdev) {
  3469.             var node = new FS.FSNode(parent, name, mode, rdev);
  3470.             FS.hashAddNode(node);
  3471.             return node;
  3472.         },
  3473.         destroyNode: function (node) {
  3474.             FS.hashRemoveNode(node);
  3475.         },
  3476.         isRoot: function (node) {
  3477.             return node === node.parent;
  3478.         },
  3479.         isMountpoint: function (node) {
  3480.             return !!node.mounted;
  3481.         },
  3482.         isFile: function (mode) {
  3483.             return (mode & 61440) === 32768;
  3484.         },
  3485.         isDir: function (mode) {
  3486.             return (mode & 61440) === 16384;
  3487.         },
  3488.         isLink: function (mode) {
  3489.             return (mode & 61440) === 40960;
  3490.         },
  3491.         isChrdev: function (mode) {
  3492.             return (mode & 61440) === 8192;
  3493.         },
  3494.         isBlkdev: function (mode) {
  3495.             return (mode & 61440) === 24576;
  3496.         },
  3497.         isFIFO: function (mode) {
  3498.             return (mode & 61440) === 4096;
  3499.         },
  3500.         isSocket: function (mode) {
  3501.             return (mode & 49152) === 49152;
  3502.         },
  3503.         flagModes: { r: 0, "r+": 2, w: 577, "w+": 578, a: 1089, "a+": 1090 },
  3504.         modeStringToFlags: function (str) {
  3505.             var flags = FS.flagModes[str];
  3506.             if (typeof flags === "undefined") {
  3507.                 throw new Error("Unknown file open mode: " + str);
  3508.             }
  3509.             return flags;
  3510.         },
  3511.         flagsToPermissionString: function (flag) {
  3512.             var perms = ["r", "w", "rw"][flag & 3];
  3513.             if (flag & 512) {
  3514.                 perms += "w";
  3515.             }
  3516.             return perms;
  3517.         },
  3518.         nodePermissions: function (node, perms) {
  3519.             if (FS.ignorePermissions) {
  3520.                 return 0;
  3521.             }
  3522.             if (perms.includes("r") && !(node.mode & 292)) {
  3523.                 return 2;
  3524.             } else if (perms.includes("w") && !(node.mode & 146)) {
  3525.                 return 2;
  3526.             } else if (perms.includes("x") && !(node.mode & 73)) {
  3527.                 return 2;
  3528.             }
  3529.             return 0;
  3530.         },
  3531.         mayLookup: function (dir) {
  3532.             var errCode = FS.nodePermissions(dir, "x");
  3533.             if (errCode) return errCode;
  3534.             if (!dir.node_ops.lookup) return 2;
  3535.             return 0;
  3536.         },
  3537.         mayCreate: function (dir, name) {
  3538.             try {
  3539.                 var node = FS.lookupNode(dir, name);
  3540.                 return 20;
  3541.             } catch (e) {}
  3542.             return FS.nodePermissions(dir, "wx");
  3543.         },
  3544.         mayDelete: function (dir, name, isdir) {
  3545.             var node;
  3546.             try {
  3547.                 node = FS.lookupNode(dir, name);
  3548.             } catch (e) {
  3549.                 return e.errno;
  3550.             }
  3551.             var errCode = FS.nodePermissions(dir, "wx");
  3552.             if (errCode) {
  3553.                 return errCode;
  3554.             }
  3555.             if (isdir) {
  3556.                 if (!FS.isDir(node.mode)) {
  3557.                     return 54;
  3558.                 }
  3559.                 if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) {
  3560.                     return 10;
  3561.                 }
  3562.             } else {
  3563.                 if (FS.isDir(node.mode)) {
  3564.                     return 31;
  3565.                 }
  3566.             }
  3567.             return 0;
  3568.         },
  3569.         mayOpen: function (node, flags) {
  3570.             if (!node) {
  3571.                 return 44;
  3572.             }
  3573.             if (FS.isLink(node.mode)) {
  3574.                 return 32;
  3575.             } else if (FS.isDir(node.mode)) {
  3576.                 if (FS.flagsToPermissionString(flags) !== "r" || flags & 512) {
  3577.                     return 31;
  3578.                 }
  3579.             }
  3580.             return FS.nodePermissions(node, FS.flagsToPermissionString(flags));
  3581.         },
  3582.         MAX_OPEN_FDS: 4096,
  3583.         nextfd: function (fd_start, fd_end) {
  3584.             fd_start = fd_start || 0;
  3585.             fd_end = fd_end || FS.MAX_OPEN_FDS;
  3586.             for (var fd = fd_start; fd <= fd_end; fd++) {
  3587.                 if (!FS.streams[fd]) {
  3588.                     return fd;
  3589.                 }
  3590.             }
  3591.             throw new FS.ErrnoError(33);
  3592.         },
  3593.         getStream: function (fd) {
  3594.             return FS.streams[fd];
  3595.         },
  3596.         createStream: function (stream, fd_start, fd_end) {
  3597.             if (!FS.FSStream) {
  3598.                 FS.FSStream = function () {};
  3599.                 FS.FSStream.prototype = {
  3600.                     object: {
  3601.                         get: function () {
  3602.                             return this.node;
  3603.                         },
  3604.                         set: function (val) {
  3605.                             this.node = val;
  3606.                         },
  3607.                     },
  3608.                     isRead: {
  3609.                         get: function () {
  3610.                             return (this.flags & 2097155) !== 1;
  3611.                         },
  3612.                     },
  3613.                     isWrite: {
  3614.                         get: function () {
  3615.                             return (this.flags & 2097155) !== 0;
  3616.                         },
  3617.                     },
  3618.                     isAppend: {
  3619.                         get: function () {
  3620.                             return this.flags & 1024;
  3621.                         },
  3622.                     },
  3623.                 };
  3624.             }
  3625.             var newStream = new FS.FSStream();
  3626.             for (var p in stream) {
  3627.                 newStream[p] = stream[p];
  3628.             }
  3629.             stream = newStream;
  3630.             var fd = FS.nextfd(fd_start, fd_end);
  3631.             stream.fd = fd;
  3632.             FS.streams[fd] = stream;
  3633.             return stream;
  3634.         },
  3635.         closeStream: function (fd) {
  3636.             FS.streams[fd] = null;
  3637.         },
  3638.         chrdev_stream_ops: {
  3639.             open: function (stream) {
  3640.                 var device = FS.getDevice(stream.node.rdev);
  3641.                 stream.stream_ops = device.stream_ops;
  3642.                 if (stream.stream_ops.open) {
  3643.                     stream.stream_ops.open(stream);
  3644.                 }
  3645.             },
  3646.             llseek: function () {
  3647.                 throw new FS.ErrnoError(70);
  3648.             },
  3649.         },
  3650.         major: function (dev) {
  3651.             return dev >> 8;
  3652.         },
  3653.         minor: function (dev) {
  3654.             return dev & 255;
  3655.         },
  3656.         makedev: function (ma, mi) {
  3657.             return (ma << 8) | mi;
  3658.         },
  3659.         registerDevice: function (dev, ops) {
  3660.             FS.devices[dev] = { stream_ops: ops };
  3661.         },
  3662.         getDevice: function (dev) {
  3663.             return FS.devices[dev];
  3664.         },
  3665.         getMounts: function (mount) {
  3666.             var mounts = [];
  3667.             var check = [mount];
  3668.             while (check.length) {
  3669.                 var m = check.pop();
  3670.                 mounts.push(m);
  3671.                 check.push.apply(check, m.mounts);
  3672.             }
  3673.             return mounts;
  3674.         },
  3675.         syncfs: function (populate, callback) {
  3676.             if (typeof populate === "function") {
  3677.                 callback = populate;
  3678.                 populate = false;
  3679.             }
  3680.             FS.syncFSRequests++;
  3681.             if (FS.syncFSRequests > 1) {
  3682.                 err("warning: " + FS.syncFSRequests + " FS.syncfs operations in flight at once, probably just doing extra work");
  3683.             }
  3684.             var mounts = FS.getMounts(FS.root.mount);
  3685.             var completed = 0;
  3686.             function doCallback(errCode) {
  3687.                 FS.syncFSRequests--;
  3688.                 return callback(errCode);
  3689.             }
  3690.             function done(errCode) {
  3691.                 if (errCode) {
  3692.                     if (!done.errored) {
  3693.                         done.errored = true;
  3694.                         return doCallback(errCode);
  3695.                     }
  3696.                     return;
  3697.                 }
  3698.                 if (++completed >= mounts.length) {
  3699.                     doCallback(null);
  3700.                 }
  3701.             }
  3702.             mounts.forEach(function (mount) {
  3703.                 if (!mount.type.syncfs) {
  3704.                     return done(null);
  3705.                 }
  3706.                 mount.type.syncfs(mount, populate, done);
  3707.             });
  3708.         },
  3709.         mount: function (type, opts, mountpoint) {
  3710.             var root = mountpoint === "/";
  3711.             var pseudo = !mountpoint;
  3712.             var node;
  3713.             if (root && FS.root) {
  3714.                 throw new FS.ErrnoError(10);
  3715.             } else if (!root && !pseudo) {
  3716.                 var lookup = FS.lookupPath(mountpoint, { follow_mount: false });
  3717.                 mountpoint = lookup.path;
  3718.                 node = lookup.node;
  3719.                 if (FS.isMountpoint(node)) {
  3720.                     throw new FS.ErrnoError(10);
  3721.                 }
  3722.                 if (!FS.isDir(node.mode)) {
  3723.                     throw new FS.ErrnoError(54);
  3724.                 }
  3725.             }
  3726.             var mount = { type: type, opts: opts, mountpoint: mountpoint, mounts: [] };
  3727.             var mountRoot = type.mount(mount);
  3728.             mountRoot.mount = mount;
  3729.             mount.root = mountRoot;
  3730.             if (root) {
  3731.                 FS.root = mountRoot;
  3732.             } else if (node) {
  3733.                 node.mounted = mount;
  3734.                 if (node.mount) {
  3735.                     node.mount.mounts.push(mount);
  3736.                 }
  3737.             }
  3738.             return mountRoot;
  3739.         },
  3740.         unmount: function (mountpoint) {
  3741.             var lookup = FS.lookupPath(mountpoint, { follow_mount: false });
  3742.             if (!FS.isMountpoint(lookup.node)) {
  3743.                 throw new FS.ErrnoError(28);
  3744.             }
  3745.             var node = lookup.node;
  3746.             var mount = node.mounted;
  3747.             var mounts = FS.getMounts(mount);
  3748.             Object.keys(FS.nameTable).forEach(function (hash) {
  3749.                 var current = FS.nameTable[hash];
  3750.                 while (current) {
  3751.                     var next = current.name_next;
  3752.                     if (mounts.includes(current.mount)) {
  3753.                         FS.destroyNode(current);
  3754.                     }
  3755.                     current = next;
  3756.                 }
  3757.             });
  3758.             node.mounted = null;
  3759.             var idx = node.mount.mounts.indexOf(mount);
  3760.             node.mount.mounts.splice(idx, 1);
  3761.         },
  3762.         lookup: function (parent, name) {
  3763.             return parent.node_ops.lookup(parent, name);
  3764.         },
  3765.         mknod: function (path, mode, dev) {
  3766.             var lookup = FS.lookupPath(path, { parent: true });
  3767.             var parent = lookup.node;
  3768.             var name = PATH.basename(path);
  3769.             if (!name || name === "." || name === "..") {
  3770.                 throw new FS.ErrnoError(28);
  3771.             }
  3772.             var errCode = FS.mayCreate(parent, name);
  3773.             if (errCode) {
  3774.                 throw new FS.ErrnoError(errCode);
  3775.             }
  3776.             if (!parent.node_ops.mknod) {
  3777.                 throw new FS.ErrnoError(63);
  3778.             }
  3779.             return parent.node_ops.mknod(parent, name, mode, dev);
  3780.         },
  3781.         create: function (path, mode) {
  3782.             mode = mode !== undefined ? mode : 438;
  3783.             mode &= 4095;
  3784.             mode |= 32768;
  3785.             return FS.mknod(path, mode, 0);
  3786.         },
  3787.         mkdir: function (path, mode) {
  3788.             mode = mode !== undefined ? mode : 511;
  3789.             mode &= 511 | 512;
  3790.             mode |= 16384;
  3791.             return FS.mknod(path, mode, 0);
  3792.         },
  3793.         mkdirTree: function (path, mode) {
  3794.             var dirs = path.split("/");
  3795.             var d = "";
  3796.             for (var i = 0; i < dirs.length; ++i) {
  3797.                 if (!dirs[i]) continue;
  3798.                 d += "/" + dirs[i];
  3799.                 try {
  3800.                     FS.mkdir(d, mode);
  3801.                 } catch (e) {
  3802.                     if (e.errno != 20) throw e;
  3803.                 }
  3804.             }
  3805.         },
  3806.         mkdev: function (path, mode, dev) {
  3807.             if (typeof dev === "undefined") {
  3808.                 dev = mode;
  3809.                 mode = 438;
  3810.             }
  3811.             mode |= 8192;
  3812.             return FS.mknod(path, mode, dev);
  3813.         },
  3814.         symlink: function (oldpath, newpath) {
  3815.             if (!PATH_FS.resolve(oldpath)) {
  3816.                 throw new FS.ErrnoError(44);
  3817.             }
  3818.             var lookup = FS.lookupPath(newpath, { parent: true });
  3819.             var parent = lookup.node;
  3820.             if (!parent) {
  3821.                 throw new FS.ErrnoError(44);
  3822.             }
  3823.             var newname = PATH.basename(newpath);
  3824.             var errCode = FS.mayCreate(parent, newname);
  3825.             if (errCode) {
  3826.                 throw new FS.ErrnoError(errCode);
  3827.             }
  3828.             if (!parent.node_ops.symlink) {
  3829.                 throw new FS.ErrnoError(63);
  3830.             }
  3831.             return parent.node_ops.symlink(parent, newname, oldpath);
  3832.         },
  3833.         rename: function (old_path, new_path) {
  3834.             var old_dirname = PATH.dirname(old_path);
  3835.             var new_dirname = PATH.dirname(new_path);
  3836.             var old_name = PATH.basename(old_path);
  3837.             var new_name = PATH.basename(new_path);
  3838.             var lookup, old_dir, new_dir;
  3839.             lookup = FS.lookupPath(old_path, { parent: true });
  3840.             old_dir = lookup.node;
  3841.             lookup = FS.lookupPath(new_path, { parent: true });
  3842.             new_dir = lookup.node;
  3843.             if (!old_dir || !new_dir) throw new FS.ErrnoError(44);
  3844.             if (old_dir.mount !== new_dir.mount) {
  3845.                 throw new FS.ErrnoError(75);
  3846.             }
  3847.             var old_node = FS.lookupNode(old_dir, old_name);
  3848.             var relative = PATH_FS.relative(old_path, new_dirname);
  3849.             if (relative.charAt(0) !== ".") {
  3850.                 throw new FS.ErrnoError(28);
  3851.             }
  3852.             relative = PATH_FS.relative(new_path, old_dirname);
  3853.             if (relative.charAt(0) !== ".") {
  3854.                 throw new FS.ErrnoError(55);
  3855.             }
  3856.             var new_node;
  3857.             try {
  3858.                 new_node = FS.lookupNode(new_dir, new_name);
  3859.             } catch (e) {}
  3860.             if (old_node === new_node) {
  3861.                 return;
  3862.             }
  3863.             var isdir = FS.isDir(old_node.mode);
  3864.             var errCode = FS.mayDelete(old_dir, old_name, isdir);
  3865.             if (errCode) {
  3866.                 throw new FS.ErrnoError(errCode);
  3867.             }
  3868.             errCode = new_node ? FS.mayDelete(new_dir, new_name, isdir) : FS.mayCreate(new_dir, new_name);
  3869.             if (errCode) {
  3870.                 throw new FS.ErrnoError(errCode);
  3871.             }
  3872.             if (!old_dir.node_ops.rename) {
  3873.                 throw new FS.ErrnoError(63);
  3874.             }
  3875.             if (FS.isMountpoint(old_node) || (new_node && FS.isMountpoint(new_node))) {
  3876.                 throw new FS.ErrnoError(10);
  3877.             }
  3878.             if (new_dir !== old_dir) {
  3879.                 errCode = FS.nodePermissions(old_dir, "w");
  3880.                 if (errCode) {
  3881.                     throw new FS.ErrnoError(errCode);
  3882.                 }
  3883.             }
  3884.             try {
  3885.                 if (FS.trackingDelegate["willMovePath"]) {
  3886.                     FS.trackingDelegate["willMovePath"](old_path, new_path);
  3887.                 }
  3888.             } catch (e) {
  3889.                 err("FS.trackingDelegate['willMovePath']('" + old_path + "', '" + new_path + "') threw an exception: " + e.message);
  3890.             }
  3891.             FS.hashRemoveNode(old_node);
  3892.             try {
  3893.                 old_dir.node_ops.rename(old_node, new_dir, new_name);
  3894.             } catch (e) {
  3895.                 throw e;
  3896.             } finally {
  3897.                 FS.hashAddNode(old_node);
  3898.             }
  3899.             try {
  3900.                 if (FS.trackingDelegate["onMovePath"]) FS.trackingDelegate["onMovePath"](old_path, new_path);
  3901.             } catch (e) {
  3902.                 err("FS.trackingDelegate['onMovePath']('" + old_path + "', '" + new_path + "') threw an exception: " + e.message);
  3903.             }
  3904.         },
  3905.         rmdir: function (path) {
  3906.             var lookup = FS.lookupPath(path, { parent: true });
  3907.             var parent = lookup.node;
  3908.             var name = PATH.basename(path);
  3909.             var node = FS.lookupNode(parent, name);
  3910.             var errCode = FS.mayDelete(parent, name, true);
  3911.             if (errCode) {
  3912.                 throw new FS.ErrnoError(errCode);
  3913.             }
  3914.             if (!parent.node_ops.rmdir) {
  3915.                 throw new FS.ErrnoError(63);
  3916.             }
  3917.             if (FS.isMountpoint(node)) {
  3918.                 throw new FS.ErrnoError(10);
  3919.             }
  3920.             try {
  3921.                 if (FS.trackingDelegate["willDeletePath"]) {
  3922.                     FS.trackingDelegate["willDeletePath"](path);
  3923.                 }
  3924.             } catch (e) {
  3925.                 err("FS.trackingDelegate['willDeletePath']('" + path + "') threw an exception: " + e.message);
  3926.             }
  3927.             parent.node_ops.rmdir(parent, name);
  3928.             FS.destroyNode(node);
  3929.             try {
  3930.                 if (FS.trackingDelegate["onDeletePath"]) FS.trackingDelegate["onDeletePath"](path);
  3931.             } catch (e) {
  3932.                 err("FS.trackingDelegate['onDeletePath']('" + path + "') threw an exception: " + e.message);
  3933.             }
  3934.         },
  3935.         readdir: function (path) {
  3936.             var lookup = FS.lookupPath(path, { follow: true });
  3937.             var node = lookup.node;
  3938.             if (!node.node_ops.readdir) {
  3939.                 throw new FS.ErrnoError(54);
  3940.             }
  3941.             return node.node_ops.readdir(node);
  3942.         },
  3943.         unlink: function (path) {
  3944.             var lookup = FS.lookupPath(path, { parent: true });
  3945.             var parent = lookup.node;
  3946.             var name = PATH.basename(path);
  3947.             var node = FS.lookupNode(parent, name);
  3948.             var errCode = FS.mayDelete(parent, name, false);
  3949.             if (errCode) {
  3950.                 throw new FS.ErrnoError(errCode);
  3951.             }
  3952.             if (!parent.node_ops.unlink) {
  3953.                 throw new FS.ErrnoError(63);
  3954.             }
  3955.             if (FS.isMountpoint(node)) {
  3956.                 throw new FS.ErrnoError(10);
  3957.             }
  3958.             try {
  3959.                 if (FS.trackingDelegate["willDeletePath"]) {
  3960.                     FS.trackingDelegate["willDeletePath"](path);
  3961.                 }
  3962.             } catch (e) {
  3963.                 err("FS.trackingDelegate['willDeletePath']('" + path + "') threw an exception: " + e.message);
  3964.             }
  3965.             parent.node_ops.unlink(parent, name);
  3966.             FS.destroyNode(node);
  3967.             try {
  3968.                 if (FS.trackingDelegate["onDeletePath"]) FS.trackingDelegate["onDeletePath"](path);
  3969.             } catch (e) {
  3970.                 err("FS.trackingDelegate['onDeletePath']('" + path + "') threw an exception: " + e.message);
  3971.             }
  3972.         },
  3973.         readlink: function (path) {
  3974.             var lookup = FS.lookupPath(path);
  3975.             var link = lookup.node;
  3976.             if (!link) {
  3977.                 throw new FS.ErrnoError(44);
  3978.             }
  3979.             if (!link.node_ops.readlink) {
  3980.                 throw new FS.ErrnoError(28);
  3981.             }
  3982.             return PATH_FS.resolve(FS.getPath(link.parent), link.node_ops.readlink(link));
  3983.         },
  3984.         stat: function (path, dontFollow) {
  3985.             var lookup = FS.lookupPath(path, { follow: !dontFollow });
  3986.             var node = lookup.node;
  3987.             if (!node) {
  3988.                 throw new FS.ErrnoError(44);
  3989.             }
  3990.             if (!node.node_ops.getattr) {
  3991.                 throw new FS.ErrnoError(63);
  3992.             }
  3993.             return node.node_ops.getattr(node);
  3994.         },
  3995.         lstat: function (path) {
  3996.             return FS.stat(path, true);
  3997.         },
  3998.         chmod: function (path, mode, dontFollow) {
  3999.             var node;
  4000.             if (typeof path === "string") {
  4001.                 var lookup = FS.lookupPath(path, { follow: !dontFollow });
  4002.                 node = lookup.node;
  4003.             } else {
  4004.                 node = path;
  4005.             }
  4006.             if (!node.node_ops.setattr) {
  4007.                 throw new FS.ErrnoError(63);
  4008.             }
  4009.             node.node_ops.setattr(node, { mode: (mode & 4095) | (node.mode & ~4095), timestamp: Date.now() });
  4010.         },
  4011.         lchmod: function (path, mode) {
  4012.             FS.chmod(path, mode, true);
  4013.         },
  4014.         fchmod: function (fd, mode) {
  4015.             var stream = FS.getStream(fd);
  4016.             if (!stream) {
  4017.                 throw new FS.ErrnoError(8);
  4018.             }
  4019.             FS.chmod(stream.node, mode);
  4020.         },
  4021.         chown: function (path, uid, gid, dontFollow) {
  4022.             var node;
  4023.             if (typeof path === "string") {
  4024.                 var lookup = FS.lookupPath(path, { follow: !dontFollow });
  4025.                 node = lookup.node;
  4026.             } else {
  4027.                 node = path;
  4028.             }
  4029.             if (!node.node_ops.setattr) {
  4030.                 throw new FS.ErrnoError(63);
  4031.             }
  4032.             node.node_ops.setattr(node, { timestamp: Date.now() });
  4033.         },
  4034.         lchown: function (path, uid, gid) {
  4035.             FS.chown(path, uid, gid, true);
  4036.         },
  4037.         fchown: function (fd, uid, gid) {
  4038.             var stream = FS.getStream(fd);
  4039.             if (!stream) {
  4040.                 throw new FS.ErrnoError(8);
  4041.             }
  4042.             FS.chown(stream.node, uid, gid);
  4043.         },
  4044.         truncate: function (path, len) {
  4045.             if (len < 0) {
  4046.                 throw new FS.ErrnoError(28);
  4047.             }
  4048.             var node;
  4049.             if (typeof path === "string") {
  4050.                 var lookup = FS.lookupPath(path, { follow: true });
  4051.                 node = lookup.node;
  4052.             } else {
  4053.                 node = path;
  4054.             }
  4055.             if (!node.node_ops.setattr) {
  4056.                 throw new FS.ErrnoError(63);
  4057.             }
  4058.             if (FS.isDir(node.mode)) {
  4059.                 throw new FS.ErrnoError(31);
  4060.             }
  4061.             if (!FS.isFile(node.mode)) {
  4062.                 throw new FS.ErrnoError(28);
  4063.             }
  4064.             var errCode = FS.nodePermissions(node, "w");
  4065.             if (errCode) {
  4066.                 throw new FS.ErrnoError(errCode);
  4067.             }
  4068.             node.node_ops.setattr(node, { size: len, timestamp: Date.now() });
  4069.         },
  4070.         ftruncate: function (fd, len) {
  4071.             var stream = FS.getStream(fd);
  4072.             if (!stream) {
  4073.                 throw new FS.ErrnoError(8);
  4074.             }
  4075.             if ((stream.flags & 2097155) === 0) {
  4076.                 throw new FS.ErrnoError(28);
  4077.             }
  4078.             FS.truncate(stream.node, len);
  4079.         },
  4080.         utime: function (path, atime, mtime) {
  4081.             var lookup = FS.lookupPath(path, { follow: true });
  4082.             var node = lookup.node;
  4083.             node.node_ops.setattr(node, { timestamp: Math.max(atime, mtime) });
  4084.         },
  4085.         open: function (path, flags, mode, fd_start, fd_end) {
  4086.             if (path === "") {
  4087.                 throw new FS.ErrnoError(44);
  4088.             }
  4089.             flags = typeof flags === "string" ? FS.modeStringToFlags(flags) : flags;
  4090.             mode = typeof mode === "undefined" ? 438 : mode;
  4091.             if (flags & 64) {
  4092.                 mode = (mode & 4095) | 32768;
  4093.             } else {
  4094.                 mode = 0;
  4095.             }
  4096.             var node;
  4097.             if (typeof path === "object") {
  4098.                 node = path;
  4099.             } else {
  4100.                 path = PATH.normalize(path);
  4101.                 try {
  4102.                     var lookup = FS.lookupPath(path, { follow: !(flags & 131072) });
  4103.                     node = lookup.node;
  4104.                 } catch (e) {}
  4105.             }
  4106.             var created = false;
  4107.             if (flags & 64) {
  4108.                 if (node) {
  4109.                     if (flags & 128) {
  4110.                         throw new FS.ErrnoError(20);
  4111.                     }
  4112.                 } else {
  4113.                     node = FS.mknod(path, mode, 0);
  4114.                     created = true;
  4115.                 }
  4116.             }
  4117.             if (!node) {
  4118.                 throw new FS.ErrnoError(44);
  4119.             }
  4120.             if (FS.isChrdev(node.mode)) {
  4121.                 flags &= ~512;
  4122.             }
  4123.             if (flags & 65536 && !FS.isDir(node.mode)) {
  4124.                 throw new FS.ErrnoError(54);
  4125.             }
  4126.             if (!created) {
  4127.                 var errCode = FS.mayOpen(node, flags);
  4128.                 if (errCode) {
  4129.                     throw new FS.ErrnoError(errCode);
  4130.                 }
  4131.             }
  4132.             if (flags & 512) {
  4133.                 FS.truncate(node, 0);
  4134.             }
  4135.             flags &= ~(128 | 512 | 131072);
  4136.             var stream = FS.createStream({ node: node, path: FS.getPath(node), flags: flags, seekable: true, position: 0, stream_ops: node.stream_ops, ungotten: [], error: false }, fd_start, fd_end);
  4137.             if (stream.stream_ops.open) {
  4138.                 stream.stream_ops.open(stream);
  4139.             }
  4140.             if (Module["logReadFiles"] && !(flags & 1)) {
  4141.                 if (!FS.readFiles) FS.readFiles = {};
  4142.                 if (!(path in FS.readFiles)) {
  4143.                     FS.readFiles[path] = 1;
  4144.                     err("FS.trackingDelegate error on read file: " + path);
  4145.                 }
  4146.             }
  4147.             try {
  4148.                 if (FS.trackingDelegate["onOpenFile"]) {
  4149.                     var trackingFlags = 0;
  4150.                     if ((flags & 2097155) !== 1) {
  4151.                         trackingFlags |= FS.tracking.openFlags.READ;
  4152.                     }
  4153.                     if ((flags & 2097155) !== 0) {
  4154.                         trackingFlags |= FS.tracking.openFlags.WRITE;
  4155.                     }
  4156.                     FS.trackingDelegate["onOpenFile"](path, trackingFlags);
  4157.                 }
  4158.             } catch (e) {
  4159.                 err("FS.trackingDelegate['onOpenFile']('" + path + "', flags) threw an exception: " + e.message);
  4160.             }
  4161.             return stream;
  4162.         },
  4163.         close: function (stream) {
  4164.             if (FS.isClosed(stream)) {
  4165.                 throw new FS.ErrnoError(8);
  4166.             }
  4167.             if (stream.getdents) stream.getdents = null;
  4168.             try {
  4169.                 if (stream.stream_ops.close) {
  4170.                     stream.stream_ops.close(stream);
  4171.                 }
  4172.             } catch (e) {
  4173.                 throw e;
  4174.             } finally {
  4175.                 FS.closeStream(stream.fd);
  4176.             }
  4177.             stream.fd = null;
  4178.         },
  4179.         isClosed: function (stream) {
  4180.             return stream.fd === null;
  4181.         },
  4182.         llseek: function (stream, offset, whence) {
  4183.             if (FS.isClosed(stream)) {
  4184.                 throw new FS.ErrnoError(8);
  4185.             }
  4186.             if (!stream.seekable || !stream.stream_ops.llseek) {
  4187.                 throw new FS.ErrnoError(70);
  4188.             }
  4189.             if (whence != 0 && whence != 1 && whence != 2) {
  4190.                 throw new FS.ErrnoError(28);
  4191.             }
  4192.             stream.position = stream.stream_ops.llseek(stream, offset, whence);
  4193.             stream.ungotten = [];
  4194.             return stream.position;
  4195.         },
  4196.         read: function (stream, buffer, offset, length, position) {
  4197.             if (length < 0 || position < 0) {
  4198.                 throw new FS.ErrnoError(28);
  4199.             }
  4200.             if (FS.isClosed(stream)) {
  4201.                 throw new FS.ErrnoError(8);
  4202.             }
  4203.             if ((stream.flags & 2097155) === 1) {
  4204.                 throw new FS.ErrnoError(8);
  4205.             }
  4206.             if (FS.isDir(stream.node.mode)) {
  4207.                 throw new FS.ErrnoError(31);
  4208.             }
  4209.             if (!stream.stream_ops.read) {
  4210.                 throw new FS.ErrnoError(28);
  4211.             }
  4212.             var seeking = typeof position !== "undefined";
  4213.             if (!seeking) {
  4214.                 position = stream.position;
  4215.             } else if (!stream.seekable) {
  4216.                 throw new FS.ErrnoError(70);
  4217.             }
  4218.             var bytesRead = stream.stream_ops.read(stream, buffer, offset, length, position);
  4219.             if (!seeking) stream.position += bytesRead;
  4220.             return bytesRead;
  4221.         },
  4222.         write: function (stream, buffer, offset, length, position, canOwn) {
  4223.             if (length < 0 || position < 0) {
  4224.                 throw new FS.ErrnoError(28);
  4225.             }
  4226.             if (FS.isClosed(stream)) {
  4227.                 throw new FS.ErrnoError(8);
  4228.             }
  4229.             if ((stream.flags & 2097155) === 0) {
  4230.                 throw new FS.ErrnoError(8);
  4231.             }
  4232.             if (FS.isDir(stream.node.mode)) {
  4233.                 throw new FS.ErrnoError(31);
  4234.             }
  4235.             if (!stream.stream_ops.write) {
  4236.                 throw new FS.ErrnoError(28);
  4237.             }
  4238.             if (stream.seekable && stream.flags & 1024) {
  4239.                 FS.llseek(stream, 0, 2);
  4240.             }
  4241.             var seeking = typeof position !== "undefined";
  4242.             if (!seeking) {
  4243.                 position = stream.position;
  4244.             } else if (!stream.seekable) {
  4245.                 throw new FS.ErrnoError(70);
  4246.             }
  4247.             var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position, canOwn);
  4248.             if (!seeking) stream.position += bytesWritten;
  4249.             try {
  4250.                 if (stream.path && FS.trackingDelegate["onWriteToFile"]) FS.trackingDelegate["onWriteToFile"](stream.path);
  4251.             } catch (e) {
  4252.                 err("FS.trackingDelegate['onWriteToFile']('" + stream.path + "') threw an exception: " + e.message);
  4253.             }
  4254.             return bytesWritten;
  4255.         },
  4256.         allocate: function (stream, offset, length) {
  4257.             if (FS.isClosed(stream)) {
  4258.                 throw new FS.ErrnoError(8);
  4259.             }
  4260.             if (offset < 0 || length <= 0) {
  4261.                 throw new FS.ErrnoError(28);
  4262.             }
  4263.             if ((stream.flags & 2097155) === 0) {
  4264.                 throw new FS.ErrnoError(8);
  4265.             }
  4266.             if (!FS.isFile(stream.node.mode) && !FS.isDir(stream.node.mode)) {
  4267.                 throw new FS.ErrnoError(43);
  4268.             }
  4269.             if (!stream.stream_ops.allocate) {
  4270.                 throw new FS.ErrnoError(138);
  4271.             }
  4272.             stream.stream_ops.allocate(stream, offset, length);
  4273.         },
  4274.         mmap: function (stream, address, length, position, prot, flags) {
  4275.             if ((prot & 2) !== 0 && (flags & 2) === 0 && (stream.flags & 2097155) !== 2) {
  4276.                 throw new FS.ErrnoError(2);
  4277.             }
  4278.             if ((stream.flags & 2097155) === 1) {
  4279.                 throw new FS.ErrnoError(2);
  4280.             }
  4281.             if (!stream.stream_ops.mmap) {
  4282.                 throw new FS.ErrnoError(43);
  4283.             }
  4284.             return stream.stream_ops.mmap(stream, address, length, position, prot, flags);
  4285.         },
  4286.         msync: function (stream, buffer, offset, length, mmapFlags) {
  4287.             if (!stream || !stream.stream_ops.msync) {
  4288.                 return 0;
  4289.             }
  4290.             return stream.stream_ops.msync(stream, buffer, offset, length, mmapFlags);
  4291.         },
  4292.         munmap: function (stream) {
  4293.             return 0;
  4294.         },
  4295.         ioctl: function (stream, cmd, arg) {
  4296.             if (!stream.stream_ops.ioctl) {
  4297.                 throw new FS.ErrnoError(59);
  4298.             }
  4299.             return stream.stream_ops.ioctl(stream, cmd, arg);
  4300.         },
  4301.         readFile: function (path, opts) {
  4302.             opts = opts || {};
  4303.             opts.flags = opts.flags || 0;
  4304.             opts.encoding = opts.encoding || "binary";
  4305.             if (opts.encoding !== "utf8" && opts.encoding !== "binary") {
  4306.                 throw new Error('Invalid encoding type "' + opts.encoding + '"');
  4307.             }
  4308.             var ret;
  4309.             var stream = FS.open(path, opts.flags);
  4310.             var stat = FS.stat(path);
  4311.             var length = stat.size;
  4312.             var buf = new Uint8Array(length);
  4313.             FS.read(stream, buf, 0, length, 0);
  4314.             if (opts.encoding === "utf8") {
  4315.                 ret = UTF8ArrayToString(buf, 0);
  4316.             } else if (opts.encoding === "binary") {
  4317.                 ret = buf;
  4318.             }
  4319.             FS.close(stream);
  4320.             return ret;
  4321.         },
  4322.         writeFile: function (path, data, opts) {
  4323.             opts = opts || {};
  4324.             opts.flags = opts.flags || 577;
  4325.             var stream = FS.open(path, opts.flags, opts.mode);
  4326.             if (typeof data === "string") {
  4327.                 var buf = new Uint8Array(lengthBytesUTF8(data) + 1);
  4328.                 var actualNumBytes = stringToUTF8Array(data, buf, 0, buf.length);
  4329.                 FS.write(stream, buf, 0, actualNumBytes, undefined, opts.canOwn);
  4330.             } else if (ArrayBuffer.isView(data)) {
  4331.                 FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn);
  4332.             } else {
  4333.                 throw new Error("Unsupported data type");
  4334.             }
  4335.             FS.close(stream);
  4336.         },
  4337.         cwd: function () {
  4338.             return FS.currentPath;
  4339.         },
  4340.         chdir: function (path) {
  4341.             var lookup = FS.lookupPath(path, { follow: true });
  4342.             if (lookup.node === null) {
  4343.                 throw new FS.ErrnoError(44);
  4344.             }
  4345.             if (!FS.isDir(lookup.node.mode)) {
  4346.                 throw new FS.ErrnoError(54);
  4347.             }
  4348.             var errCode = FS.nodePermissions(lookup.node, "x");
  4349.             if (errCode) {
  4350.                 throw new FS.ErrnoError(errCode);
  4351.             }
  4352.             FS.currentPath = lookup.path;
  4353.         },
  4354.         createDefaultDirectories: function () {
  4355.             FS.mkdir("/tmp");
  4356.             FS.mkdir("/home");
  4357.             FS.mkdir("/home/web_user");
  4358.         },
  4359.         createDefaultDevices: function () {
  4360.             FS.mkdir("/dev");
  4361.             FS.registerDevice(FS.makedev(1, 3), {
  4362.                 read: function () {
  4363.                     return 0;
  4364.                 },
  4365.                 write: function (stream, buffer, offset, length, pos) {
  4366.                     return length;
  4367.                 },
  4368.             });
  4369.             FS.mkdev("/dev/null", FS.makedev(1, 3));
  4370.             TTY.register(FS.makedev(5, 0), TTY.default_tty_ops);
  4371.             TTY.register(FS.makedev(6, 0), TTY.default_tty1_ops);
  4372.             FS.mkdev("/dev/tty", FS.makedev(5, 0));
  4373.             FS.mkdev("/dev/tty1", FS.makedev(6, 0));
  4374.             var random_device = getRandomDevice();
  4375.             FS.createDevice("/dev", "random", random_device);
  4376.             FS.createDevice("/dev", "urandom", random_device);
  4377.             FS.mkdir("/dev/shm");
  4378.             FS.mkdir("/dev/shm/tmp");
  4379.         },
  4380.         createSpecialDirectories: function () {
  4381.             FS.mkdir("/proc");
  4382.             var proc_self = FS.mkdir("/proc/self");
  4383.             FS.mkdir("/proc/self/fd");
  4384.             FS.mount(
  4385.                 {
  4386.                     mount: function () {
  4387.                         var node = FS.createNode(proc_self, "fd", 16384 | 511, 73);
  4388.                         node.node_ops = {
  4389.                             lookup: function (parent, name) {
  4390.                                 var fd = +name;
  4391.                                 var stream = FS.getStream(fd);
  4392.                                 if (!stream) throw new FS.ErrnoError(8);
  4393.                                 var ret = {
  4394.                                     parent: null,
  4395.                                     mount: { mountpoint: "fake" },
  4396.                                     node_ops: {
  4397.                                         readlink: function () {
  4398.                                             return stream.path;
  4399.                                         },
  4400.                                     },
  4401.                                 };
  4402.                                 ret.parent = ret;
  4403.                                 return ret;
  4404.                             },
  4405.                         };
  4406.                         return node;
  4407.                     },
  4408.                 },
  4409.                 {},
  4410.                 "/proc/self/fd"
  4411.             );
  4412.         },
  4413.         createStandardStreams: function () {
  4414.             if (Module["stdin"]) {
  4415.                 FS.createDevice("/dev", "stdin", Module["stdin"]);
  4416.             } else {
  4417.                 FS.symlink("/dev/tty", "/dev/stdin");
  4418.             }
  4419.             if (Module["stdout"]) {
  4420.                 FS.createDevice("/dev", "stdout", null, Module["stdout"]);
  4421.             } else {
  4422.                 FS.symlink("/dev/tty", "/dev/stdout");
  4423.             }
  4424.             if (Module["stderr"]) {
  4425.                 FS.createDevice("/dev", "stderr", null, Module["stderr"]);
  4426.             } else {
  4427.                 FS.symlink("/dev/tty1", "/dev/stderr");
  4428.             }
  4429.             var stdin = FS.open("/dev/stdin", 0);
  4430.             var stdout = FS.open("/dev/stdout", 1);
  4431.             var stderr = FS.open("/dev/stderr", 1);
  4432.         },
  4433.         ensureErrnoError: function () {
  4434.             if (FS.ErrnoError) return;
  4435.             FS.ErrnoError = function ErrnoError(errno, node) {
  4436.                 this.node = node;
  4437.                 this.setErrno = function (errno) {
  4438.                     this.errno = errno;
  4439.                 };
  4440.                 this.setErrno(errno);
  4441.                 this.message = "FS error";
  4442.             };
  4443.             FS.ErrnoError.prototype = new Error();
  4444.             FS.ErrnoError.prototype.constructor = FS.ErrnoError;
  4445.             [44].forEach(function (code) {
  4446.                 FS.genericErrors[code] = new FS.ErrnoError(code);
  4447.                 FS.genericErrors[code].stack = "<generic error, no stack>";
  4448.             });
  4449.         },
  4450.         staticInit: function () {
  4451.             FS.ensureErrnoError();
  4452.             FS.nameTable = new Array(4096);
  4453.             FS.mount(MEMFS, {}, "/");
  4454.             FS.createDefaultDirectories();
  4455.             FS.createDefaultDevices();
  4456.             FS.createSpecialDirectories();
  4457.             FS.filesystems = { MEMFS: MEMFS, IDBFS: IDBFS };
  4458.         },
  4459.         init: function (input, output, error) {
  4460.             FS.init.initialized = true;
  4461.             FS.ensureErrnoError();
  4462.             Module["stdin"] = input || Module["stdin"];
  4463.             Module["stdout"] = output || Module["stdout"];
  4464.             Module["stderr"] = error || Module["stderr"];
  4465.             FS.createStandardStreams();
  4466.         },
  4467.         quit: function () {
  4468.             FS.init.initialized = false;
  4469.             var fflush = Module["_fflush"];
  4470.             if (fflush) fflush(0);
  4471.             for (var i = 0; i < FS.streams.length; i++) {
  4472.                 var stream = FS.streams[i];
  4473.                 if (!stream) {
  4474.                     continue;
  4475.                 }
  4476.                 FS.close(stream);
  4477.             }
  4478.         },
  4479.         getMode: function (canRead, canWrite) {
  4480.             var mode = 0;
  4481.             if (canRead) mode |= 292 | 73;
  4482.             if (canWrite) mode |= 146;
  4483.             return mode;
  4484.         },
  4485.         findObject: function (path, dontResolveLastLink) {
  4486.             var ret = FS.analyzePath(path, dontResolveLastLink);
  4487.             if (ret.exists) {
  4488.                 return ret.object;
  4489.             } else {
  4490.                 return null;
  4491.             }
  4492.         },
  4493.         analyzePath: function (path, dontResolveLastLink) {
  4494.             try {
  4495.                 var lookup = FS.lookupPath(path, { follow: !dontResolveLastLink });
  4496.                 path = lookup.path;
  4497.             } catch (e) {}
  4498.             var ret = { isRoot: false, exists: false, error: 0, name: null, path: null, object: null, parentExists: false, parentPath: null, parentObject: null };
  4499.             try {
  4500.                 var lookup = FS.lookupPath(path, { parent: true });
  4501.                 ret.parentExists = true;
  4502.                 ret.parentPath = lookup.path;
  4503.                 ret.parentObject = lookup.node;
  4504.                 ret.name = PATH.basename(path);
  4505.                 lookup = FS.lookupPath(path, { follow: !dontResolveLastLink });
  4506.                 ret.exists = true;
  4507.                 ret.path = lookup.path;
  4508.                 ret.object = lookup.node;
  4509.                 ret.name = lookup.node.name;
  4510.                 ret.isRoot = lookup.path === "/";
  4511.             } catch (e) {
  4512.                 ret.error = e.errno;
  4513.             }
  4514.             return ret;
  4515.         },
  4516.         createPath: function (parent, path, canRead, canWrite) {
  4517.             parent = typeof parent === "string" ? parent : FS.getPath(parent);
  4518.             var parts = path.split("/").reverse();
  4519.             while (parts.length) {
  4520.                 var part = parts.pop();
  4521.                 if (!part) continue;
  4522.                 var current = PATH.join2(parent, part);
  4523.                 try {
  4524.                     FS.mkdir(current);
  4525.                 } catch (e) {}
  4526.                 parent = current;
  4527.             }
  4528.             return current;
  4529.         },
  4530.         createFile: function (parent, name, properties, canRead, canWrite) {
  4531.             var path = PATH.join2(typeof parent === "string" ? parent : FS.getPath(parent), name);
  4532.             var mode = FS.getMode(canRead, canWrite);
  4533.             return FS.create(path, mode);
  4534.         },
  4535.         createDataFile: function (parent, name, data, canRead, canWrite, canOwn) {
  4536.             var path = name ? PATH.join2(typeof parent === "string" ? parent : FS.getPath(parent), name) : parent;
  4537.             var mode = FS.getMode(canRead, canWrite);
  4538.             var node = FS.create(path, mode);
  4539.             if (data) {
  4540.                 if (typeof data === "string") {
  4541.                     var arr = new Array(data.length);
  4542.                     for (var i = 0, len = data.length; i < len; ++i) arr[i] = data.charCodeAt(i);
  4543.                     data = arr;
  4544.                 }
  4545.                 FS.chmod(node, mode | 146);
  4546.                 var stream = FS.open(node, 577);
  4547.                 FS.write(stream, data, 0, data.length, 0, canOwn);
  4548.                 FS.close(stream);
  4549.                 FS.chmod(node, mode);
  4550.             }
  4551.             return node;
  4552.         },
  4553.         createDevice: function (parent, name, input, output) {
  4554.             var path = PATH.join2(typeof parent === "string" ? parent : FS.getPath(parent), name);
  4555.             var mode = FS.getMode(!!input, !!output);
  4556.             if (!FS.createDevice.major) FS.createDevice.major = 64;
  4557.             var dev = FS.makedev(FS.createDevice.major++, 0);
  4558.             FS.registerDevice(dev, {
  4559.                 open: function (stream) {
  4560.                     stream.seekable = false;
  4561.                 },
  4562.                 close: function (stream) {
  4563.                     if (output && output.buffer && output.buffer.length) {
  4564.                         output(10);
  4565.                     }
  4566.                 },
  4567.                 read: function (stream, buffer, offset, length, pos) {
  4568.                     var bytesRead = 0;
  4569.                     for (var i = 0; i < length; i++) {
  4570.                         var result;
  4571.                         try {
  4572.                             result = input();
  4573.                         } catch (e) {
  4574.                             throw new FS.ErrnoError(29);
  4575.                         }
  4576.                         if (result === undefined && bytesRead === 0) {
  4577.                             throw new FS.ErrnoError(6);
  4578.                         }
  4579.                         if (result === null || result === undefined) break;
  4580.                         bytesRead++;
  4581.                         buffer[offset + i] = result;
  4582.                     }
  4583.                     if (bytesRead) {
  4584.                         stream.node.timestamp = Date.now();
  4585.                     }
  4586.                     return bytesRead;
  4587.                 },
  4588.                 write: function (stream, buffer, offset, length, pos) {
  4589.                     for (var i = 0; i < length; i++) {
  4590.                         try {
  4591.                             output(buffer[offset + i]);
  4592.                         } catch (e) {
  4593.                             throw new FS.ErrnoError(29);
  4594.                         }
  4595.                     }
  4596.                     if (length) {
  4597.                         stream.node.timestamp = Date.now();
  4598.                     }
  4599.                     return i;
  4600.                 },
  4601.             });
  4602.             return FS.mkdev(path, mode, dev);
  4603.         },
  4604.         forceLoadFile: function (obj) {
  4605.             if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true;
  4606.             if (typeof XMLHttpRequest !== "undefined") {
  4607.                 throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.");
  4608.             } else if (read_) {
  4609.                 try {
  4610.                     obj.contents = intArrayFromString(read_(obj.url), true);
  4611.                     obj.usedBytes = obj.contents.length;
  4612.                 } catch (e) {
  4613.                     throw new FS.ErrnoError(29);
  4614.                 }
  4615.             } else {
  4616.                 throw new Error("Cannot load without read() or XMLHttpRequest.");
  4617.             }
  4618.         },
  4619.         createLazyFile: function (parent, name, url, canRead, canWrite) {
  4620.             function LazyUint8Array() {
  4621.                 this.lengthKnown = false;
  4622.                 this.chunks = [];
  4623.             }
  4624.             LazyUint8Array.prototype.get = function LazyUint8Array_get(idx) {
  4625.                 if (idx > this.length - 1 || idx < 0) {
  4626.                     return undefined;
  4627.                 }
  4628.                 var chunkOffset = idx % this.chunkSize;
  4629.                 var chunkNum = (idx / this.chunkSize) | 0;
  4630.                 return this.getter(chunkNum)[chunkOffset];
  4631.             };
  4632.             LazyUint8Array.prototype.setDataGetter = function LazyUint8Array_setDataGetter(getter) {
  4633.                 this.getter = getter;
  4634.             };
  4635.             LazyUint8Array.prototype.cacheLength = function LazyUint8Array_cacheLength() {
  4636.                 var xhr = new XMLHttpRequest();
  4637.                 xhr.open("HEAD", url, false);
  4638.                 xhr.send(null);
  4639.                 if (!((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status);
  4640.                 var datalength = Number(xhr.getResponseHeader("Content-length"));
  4641.                 var header;
  4642.                 var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes";
  4643.                 var usesGzip = (header = xhr.getResponseHeader("Content-Encoding")) && header === "gzip";
  4644.                 var chunkSize = 1024 * 1024;
  4645.                 if (!hasByteServing) chunkSize = datalength;
  4646.                 var doXHR = function (from, to) {
  4647.                     if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!");
  4648.                     if (to > datalength - 1) throw new Error("only " + datalength + " bytes available! programmer error!");
  4649.                     var xhr = new XMLHttpRequest();
  4650.                     xhr.open("GET", url, false);
  4651.                     if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to);
  4652.                     if (typeof Uint8Array != "undefined") xhr.responseType = "arraybuffer";
  4653.                     if (xhr.overrideMimeType) {
  4654.                         xhr.overrideMimeType("text/plain; charset=x-user-defined");
  4655.                     }
  4656.                     xhr.send(null);
  4657.                     if (!((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status);
  4658.                     if (xhr.response !== undefined) {
  4659.                         return new Uint8Array(xhr.response || []);
  4660.                     } else {
  4661.                         return intArrayFromString(xhr.responseText || "", true);
  4662.                     }
  4663.                 };
  4664.                 var lazyArray = this;
  4665.                 lazyArray.setDataGetter(function (chunkNum) {
  4666.                     var start = chunkNum * chunkSize;
  4667.                     var end = (chunkNum + 1) * chunkSize - 1;
  4668.                     end = Math.min(end, datalength - 1);
  4669.                     if (typeof lazyArray.chunks[chunkNum] === "undefined") {
  4670.                         lazyArray.chunks[chunkNum] = doXHR(start, end);
  4671.                     }
  4672.                     if (typeof lazyArray.chunks[chunkNum] === "undefined") throw new Error("doXHR failed!");
  4673.                     return lazyArray.chunks[chunkNum];
  4674.                 });
  4675.                 if (usesGzip || !datalength) {
  4676.                     chunkSize = datalength = 1;
  4677.                     datalength = this.getter(0).length;
  4678.                     chunkSize = datalength;
  4679.                     out("LazyFiles on gzip forces download of the whole file when length is accessed");
  4680.                 }
  4681.                 this._length = datalength;
  4682.                 this._chunkSize = chunkSize;
  4683.                 this.lengthKnown = true;
  4684.             };
  4685.             if (typeof XMLHttpRequest !== "undefined") {
  4686.                 if (!ENVIRONMENT_IS_WORKER) throw "Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";
  4687.                 var lazyArray = new LazyUint8Array();
  4688.                 Object.defineProperties(lazyArray, {
  4689.                     length: {
  4690.                         get: function () {
  4691.                             if (!this.lengthKnown) {
  4692.                                 this.cacheLength();
  4693.                             }
  4694.                             return this._length;
  4695.                         },
  4696.                     },
  4697.                     chunkSize: {
  4698.                         get: function () {
  4699.                             if (!this.lengthKnown) {
  4700.                                 this.cacheLength();
  4701.                             }
  4702.                             return this._chunkSize;
  4703.                         },
  4704.                     },
  4705.                 });
  4706.                 var properties = { isDevice: false, contents: lazyArray };
  4707.             } else {
  4708.                 var properties = { isDevice: false, url: url };
  4709.             }
  4710.             var node = FS.createFile(parent, name, properties, canRead, canWrite);
  4711.             if (properties.contents) {
  4712.                 node.contents = properties.contents;
  4713.             } else if (properties.url) {
  4714.                 node.contents = null;
  4715.                 node.url = properties.url;
  4716.             }
  4717.             Object.defineProperties(node, {
  4718.                 usedBytes: {
  4719.                     get: function () {
  4720.                         return this.contents.length;
  4721.                     },
  4722.                 },
  4723.             });
  4724.             var stream_ops = {};
  4725.             var keys = Object.keys(node.stream_ops);
  4726.             keys.forEach(function (key) {
  4727.                 var fn = node.stream_ops[key];
  4728.                 stream_ops[key] = function forceLoadLazyFile() {
  4729.                     FS.forceLoadFile(node);
  4730.                     return fn.apply(null, arguments);
  4731.                 };
  4732.             });
  4733.             stream_ops.read = function stream_ops_read(stream, buffer, offset, length, position) {
  4734.                 FS.forceLoadFile(node);
  4735.                 var contents = stream.node.contents;
  4736.                 if (position >= contents.length) return 0;
  4737.                 var size = Math.min(contents.length - position, length);
  4738.                 if (contents.slice) {
  4739.                     for (var i = 0; i < size; i++) {
  4740.                         buffer[offset + i] = contents[position + i];
  4741.                     }
  4742.                 } else {
  4743.                     for (var i = 0; i < size; i++) {
  4744.                         buffer[offset + i] = contents.get(position + i);
  4745.                     }
  4746.                 }
  4747.                 return size;
  4748.             };
  4749.             node.stream_ops = stream_ops;
  4750.             return node;
  4751.         },
  4752.         createPreloadedFile: function (parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) {
  4753.             Browser.init();
  4754.             var fullname = name ? PATH_FS.resolve(PATH.join2(parent, name)) : parent;
  4755.             var dep = getUniqueRunDependency("cp " + fullname);
  4756.             function processData(byteArray) {
  4757.                 function finish(byteArray) {
  4758.                     if (preFinish) preFinish();
  4759.                     if (!dontCreateFile) {
  4760.                         FS.createDataFile(parent, name, byteArray, canRead, canWrite, canOwn);
  4761.                     }
  4762.                     if (onload) onload();
  4763.                     removeRunDependency(dep);
  4764.                 }
  4765.                 var handled = false;
  4766.                 Module["preloadPlugins"].forEach(function (plugin) {
  4767.                     if (handled) return;
  4768.                     if (plugin["canHandle"](fullname)) {
  4769.                         plugin["handle"](byteArray, fullname, finish, function () {
  4770.                             if (onerror) onerror();
  4771.                             removeRunDependency(dep);
  4772.                         });
  4773.                         handled = true;
  4774.                     }
  4775.                 });
  4776.                 if (!handled) finish(byteArray);
  4777.             }
  4778.             addRunDependency(dep);
  4779.             if (typeof url == "string") {
  4780.                 Browser.asyncLoad(
  4781.                     url,
  4782.                     function (byteArray) {
  4783.                         processData(byteArray);
  4784.                     },
  4785.                     onerror
  4786.                 );
  4787.             } else {
  4788.                 processData(url);
  4789.             }
  4790.         },
  4791.         indexedDB: function () {
  4792.             return window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
  4793.         },
  4794.         DB_NAME: function () {
  4795.             return "EM_FS_" + window.location.pathname;
  4796.         },
  4797.         DB_VERSION: 20,
  4798.         DB_STORE_NAME: "FILE_DATA",
  4799.         saveFilesToDB: function (paths, onload, onerror) {
  4800.             onload = onload || function () {};
  4801.             onerror = onerror || function () {};
  4802.             var indexedDB = FS.indexedDB();
  4803.             try {
  4804.                 var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION);
  4805.             } catch (e) {
  4806.                 return onerror(e);
  4807.             }
  4808.             openRequest.onupgradeneeded = function openRequest_onupgradeneeded() {
  4809.                 out("creating db");
  4810.                 var db = openRequest.result;
  4811.                 db.createObjectStore(FS.DB_STORE_NAME);
  4812.             };
  4813.             openRequest.onsuccess = function openRequest_onsuccess() {
  4814.                 var db = openRequest.result;
  4815.                 var transaction = db.transaction([FS.DB_STORE_NAME], "readwrite");
  4816.                 var files = transaction.objectStore(FS.DB_STORE_NAME);
  4817.                 var ok = 0,
  4818.                     fail = 0,
  4819.                     total = paths.length;
  4820.                 function finish() {
  4821.                     if (fail == 0) onload();
  4822.                     else onerror();
  4823.                 }
  4824.                 paths.forEach(function (path) {
  4825.                     var putRequest = files.put(FS.analyzePath(path).object.contents, path);
  4826.                     putRequest.onsuccess = function putRequest_onsuccess() {
  4827.                         ok++;
  4828.                         if (ok + fail == total) finish();
  4829.                     };
  4830.                     putRequest.onerror = function putRequest_onerror() {
  4831.                         fail++;
  4832.                         if (ok + fail == total) finish();
  4833.                     };
  4834.                 });
  4835.                 transaction.onerror = onerror;
  4836.             };
  4837.             openRequest.onerror = onerror;
  4838.         },
  4839.         loadFilesFromDB: function (paths, onload, onerror) {
  4840.             onload = onload || function () {};
  4841.             onerror = onerror || function () {};
  4842.             var indexedDB = FS.indexedDB();
  4843.             try {
  4844.                 var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION);
  4845.             } catch (e) {
  4846.                 return onerror(e);
  4847.             }
  4848.             openRequest.onupgradeneeded = onerror;
  4849.             openRequest.onsuccess = function openRequest_onsuccess() {
  4850.                 var db = openRequest.result;
  4851.                 try {
  4852.                     var transaction = db.transaction([FS.DB_STORE_NAME], "readonly");
  4853.                 } catch (e) {
  4854.                     onerror(e);
  4855.                     return;
  4856.                 }
  4857.                 var files = transaction.objectStore(FS.DB_STORE_NAME);
  4858.                 var ok = 0,
  4859.                     fail = 0,
  4860.                     total = paths.length;
  4861.                 function finish() {
  4862.                     if (fail == 0) onload();
  4863.                     else onerror();
  4864.                 }
  4865.                 paths.forEach(function (path) {
  4866.                     var getRequest = files.get(path);
  4867.                     getRequest.onsuccess = function getRequest_onsuccess() {
  4868.                         if (FS.analyzePath(path).exists) {
  4869.                             FS.unlink(path);
  4870.                         }
  4871.                         FS.createDataFile(PATH.dirname(path), PATH.basename(path), getRequest.result, true, true, true);
  4872.                         ok++;
  4873.                         if (ok + fail == total) finish();
  4874.                     };
  4875.                     getRequest.onerror = function getRequest_onerror() {
  4876.                         fail++;
  4877.                         if (ok + fail == total) finish();
  4878.                     };
  4879.                 });
  4880.                 transaction.onerror = onerror;
  4881.             };
  4882.             openRequest.onerror = onerror;
  4883.         },
  4884.     };
  4885.     var SYSCALLS = {
  4886.         mappings: {},
  4887.         DEFAULT_POLLMASK: 5,
  4888.         umask: 511,
  4889.         calculateAt: function (dirfd, path, allowEmpty) {
  4890.             if (path[0] === "/") {
  4891.                 return path;
  4892.             }
  4893.             var dir;
  4894.             if (dirfd === -100) {
  4895.                 dir = FS.cwd();
  4896.             } else {
  4897.                 var dirstream = FS.getStream(dirfd);
  4898.                 if (!dirstream) throw new FS.ErrnoError(8);
  4899.                 dir = dirstream.path;
  4900.             }
  4901.             if (path.length == 0) {
  4902.                 if (!allowEmpty) {
  4903.                     throw new FS.ErrnoError(44);
  4904.                 }
  4905.                 return dir;
  4906.             }
  4907.             return PATH.join2(dir, path);
  4908.         },
  4909.         doStat: function (func, path, buf) {
  4910.             try {
  4911.                 var stat = func(path);
  4912.             } catch (e) {
  4913.                 if (e && e.node && PATH.normalize(path) !== PATH.normalize(FS.getPath(e.node))) {
  4914.                     return -54;
  4915.                 }
  4916.                 throw e;
  4917.             }
  4918.             HEAP32[buf >> 2] = stat.dev;
  4919.             HEAP32[(buf + 4) >> 2] = 0;
  4920.             HEAP32[(buf + 8) >> 2] = stat.ino;
  4921.             HEAP32[(buf + 12) >> 2] = stat.mode;
  4922.             HEAP32[(buf + 16) >> 2] = stat.nlink;
  4923.             HEAP32[(buf + 20) >> 2] = stat.uid;
  4924.             HEAP32[(buf + 24) >> 2] = stat.gid;
  4925.             HEAP32[(buf + 28) >> 2] = stat.rdev;
  4926.             HEAP32[(buf + 32) >> 2] = 0;
  4927.             (tempI64 = [
  4928.                 stat.size >>> 0,
  4929.                 ((tempDouble = stat.size), +Math.abs(tempDouble) >= 1 ? (tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0) : 0),
  4930.             ]),
  4931.                 (HEAP32[(buf + 40) >> 2] = tempI64[0]),
  4932.                 (HEAP32[(buf + 44) >> 2] = tempI64[1]);
  4933.             HEAP32[(buf + 48) >> 2] = 4096;
  4934.             HEAP32[(buf + 52) >> 2] = stat.blocks;
  4935.             HEAP32[(buf + 56) >> 2] = (stat.atime.getTime() / 1e3) | 0;
  4936.             HEAP32[(buf + 60) >> 2] = 0;
  4937.             HEAP32[(buf + 64) >> 2] = (stat.mtime.getTime() / 1e3) | 0;
  4938.             HEAP32[(buf + 68) >> 2] = 0;
  4939.             HEAP32[(buf + 72) >> 2] = (stat.ctime.getTime() / 1e3) | 0;
  4940.             HEAP32[(buf + 76) >> 2] = 0;
  4941.             (tempI64 = [
  4942.                 stat.ino >>> 0,
  4943.                 ((tempDouble = stat.ino), +Math.abs(tempDouble) >= 1 ? (tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0) : 0),
  4944.             ]),
  4945.                 (HEAP32[(buf + 80) >> 2] = tempI64[0]),
  4946.                 (HEAP32[(buf + 84) >> 2] = tempI64[1]);
  4947.             return 0;
  4948.         },
  4949.         doMsync: function (addr, stream, len, flags, offset) {
  4950.             var buffer = HEAPU8.slice(addr, addr + len);
  4951.             FS.msync(stream, buffer, offset, len, flags);
  4952.         },
  4953.         doMkdir: function (path, mode) {
  4954.             path = PATH.normalize(path);
  4955.             if (path[path.length - 1] === "/") path = path.substr(0, path.length - 1);
  4956.             FS.mkdir(path, mode, 0);
  4957.             return 0;
  4958.         },
  4959.         doMknod: function (path, mode, dev) {
  4960.             switch (mode & 61440) {
  4961.                 case 32768:
  4962.                 case 8192:
  4963.                 case 24576:
  4964.                 case 4096:
  4965.                 case 49152:
  4966.                     break;
  4967.                 default:
  4968.                     return -28;
  4969.             }
  4970.             FS.mknod(path, mode, dev);
  4971.             return 0;
  4972.         },
  4973.         doReadlink: function (path, buf, bufsize) {
  4974.             if (bufsize <= 0) return -28;
  4975.             var ret = FS.readlink(path);
  4976.             var len = Math.min(bufsize, lengthBytesUTF8(ret));
  4977.             var endChar = HEAP8[buf + len];
  4978.             stringToUTF8(ret, buf, bufsize + 1);
  4979.             HEAP8[buf + len] = endChar;
  4980.             return len;
  4981.         },
  4982.         doAccess: function (path, amode) {
  4983.             if (amode & ~7) {
  4984.                 return -28;
  4985.             }
  4986.             var node;
  4987.             var lookup = FS.lookupPath(path, { follow: true });
  4988.             node = lookup.node;
  4989.             if (!node) {
  4990.                 return -44;
  4991.             }
  4992.             var perms = "";
  4993.             if (amode & 4) perms += "r";
  4994.             if (amode & 2) perms += "w";
  4995.             if (amode & 1) perms += "x";
  4996.             if (perms && FS.nodePermissions(node, perms)) {
  4997.                 return -2;
  4998.             }
  4999.             return 0;
  5000.         },
  5001.         doDup: function (path, flags, suggestFD) {
  5002.             var suggest = FS.getStream(suggestFD);
  5003.             if (suggest) FS.close(suggest);
  5004.             return FS.open(path, flags, 0, suggestFD, suggestFD).fd;
  5005.         },
  5006.         doReadv: function (stream, iov, iovcnt, offset) {
  5007.             var ret = 0;
  5008.             for (var i = 0; i < iovcnt; i++) {
  5009.                 var ptr = HEAP32[(iov + i * 8) >> 2];
  5010.                 var len = HEAP32[(iov + (i * 8 + 4)) >> 2];
  5011.                 var curr = FS.read(stream, HEAP8, ptr, len, offset);
  5012.                 if (curr < 0) return -1;
  5013.                 ret += curr;
  5014.                 if (curr < len) break;
  5015.             }
  5016.             return ret;
  5017.         },
  5018.         doWritev: function (stream, iov, iovcnt, offset) {
  5019.             var ret = 0;
  5020.             for (var i = 0; i < iovcnt; i++) {
  5021.                 var ptr = HEAP32[(iov + i * 8) >> 2];
  5022.                 var len = HEAP32[(iov + (i * 8 + 4)) >> 2];
  5023.                 var curr = FS.write(stream, HEAP8, ptr, len, offset);
  5024.                 if (curr < 0) return -1;
  5025.                 ret += curr;
  5026.             }
  5027.             return ret;
  5028.         },
  5029.         varargs: undefined,
  5030.         get: function () {
  5031.             SYSCALLS.varargs += 4;
  5032.             var ret = HEAP32[(SYSCALLS.varargs - 4) >> 2];
  5033.             return ret;
  5034.         },
  5035.         getStr: function (ptr) {
  5036.             var ret = UTF8ToString(ptr);
  5037.             return ret;
  5038.         },
  5039.         getStreamFromFD: function (fd) {
  5040.             var stream = FS.getStream(fd);
  5041.             if (!stream) throw new FS.ErrnoError(8);
  5042.             return stream;
  5043.         },
  5044.         get64: function (low, high) {
  5045.             return low;
  5046.         },
  5047.     };
  5048.     function ___sys__newselect(nfds, readfds, writefds, exceptfds, timeout) {
  5049.         try {
  5050.             var total = 0;
  5051.             var srcReadLow = readfds ? HEAP32[readfds >> 2] : 0,
  5052.                 srcReadHigh = readfds ? HEAP32[(readfds + 4) >> 2] : 0;
  5053.             var srcWriteLow = writefds ? HEAP32[writefds >> 2] : 0,
  5054.                 srcWriteHigh = writefds ? HEAP32[(writefds + 4) >> 2] : 0;
  5055.             var srcExceptLow = exceptfds ? HEAP32[exceptfds >> 2] : 0,
  5056.                 srcExceptHigh = exceptfds ? HEAP32[(exceptfds + 4) >> 2] : 0;
  5057.             var dstReadLow = 0,
  5058.                 dstReadHigh = 0;
  5059.             var dstWriteLow = 0,
  5060.                 dstWriteHigh = 0;
  5061.             var dstExceptLow = 0,
  5062.                 dstExceptHigh = 0;
  5063.             var allLow = (readfds ? HEAP32[readfds >> 2] : 0) | (writefds ? HEAP32[writefds >> 2] : 0) | (exceptfds ? HEAP32[exceptfds >> 2] : 0);
  5064.             var allHigh = (readfds ? HEAP32[(readfds + 4) >> 2] : 0) | (writefds ? HEAP32[(writefds + 4) >> 2] : 0) | (exceptfds ? HEAP32[(exceptfds + 4) >> 2] : 0);
  5065.             var check = function (fd, low, high, val) {
  5066.                 return fd < 32 ? low & val : high & val;
  5067.             };
  5068.             for (var fd = 0; fd < nfds; fd++) {
  5069.                 var mask = 1 << fd % 32;
  5070.                 if (!check(fd, allLow, allHigh, mask)) {
  5071.                     continue;
  5072.                 }
  5073.                 var stream = FS.getStream(fd);
  5074.                 if (!stream) throw new FS.ErrnoError(8);
  5075.                 var flags = SYSCALLS.DEFAULT_POLLMASK;
  5076.                 if (stream.stream_ops.poll) {
  5077.                     flags = stream.stream_ops.poll(stream);
  5078.                 }
  5079.                 if (flags & 1 && check(fd, srcReadLow, srcReadHigh, mask)) {
  5080.                     fd < 32 ? (dstReadLow = dstReadLow | mask) : (dstReadHigh = dstReadHigh | mask);
  5081.                     total++;
  5082.                 }
  5083.                 if (flags & 4 && check(fd, srcWriteLow, srcWriteHigh, mask)) {
  5084.                     fd < 32 ? (dstWriteLow = dstWriteLow | mask) : (dstWriteHigh = dstWriteHigh | mask);
  5085.                     total++;
  5086.                 }
  5087.                 if (flags & 2 && check(fd, srcExceptLow, srcExceptHigh, mask)) {
  5088.                     fd < 32 ? (dstExceptLow = dstExceptLow | mask) : (dstExceptHigh = dstExceptHigh | mask);
  5089.                     total++;
  5090.                 }
  5091.             }
  5092.             if (readfds) {
  5093.                 HEAP32[readfds >> 2] = dstReadLow;
  5094.                 HEAP32[(readfds + 4) >> 2] = dstReadHigh;
  5095.             }
  5096.             if (writefds) {
  5097.                 HEAP32[writefds >> 2] = dstWriteLow;
  5098.                 HEAP32[(writefds + 4) >> 2] = dstWriteHigh;
  5099.             }
  5100.             if (exceptfds) {
  5101.                 HEAP32[exceptfds >> 2] = dstExceptLow;
  5102.                 HEAP32[(exceptfds + 4) >> 2] = dstExceptHigh;
  5103.             }
  5104.             return total;
  5105.         } catch (e) {
  5106.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  5107.             return -e.errno;
  5108.         }
  5109.     }
  5110.     function ___sys_access(path, amode) {
  5111.         try {
  5112.             path = SYSCALLS.getStr(path);
  5113.             return SYSCALLS.doAccess(path, amode);
  5114.         } catch (e) {
  5115.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  5116.             return -e.errno;
  5117.         }
  5118.     }
  5119.     function ___sys_chmod(path, mode) {
  5120.         try {
  5121.             path = SYSCALLS.getStr(path);
  5122.             FS.chmod(path, mode);
  5123.             return 0;
  5124.         } catch (e) {
  5125.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  5126.             return -e.errno;
  5127.         }
  5128.     }
  5129.     var ERRNO_CODES = {
  5130.         EPERM: 63,
  5131.         ENOENT: 44,
  5132.         ESRCH: 71,
  5133.         EINTR: 27,
  5134.         EIO: 29,
  5135.         ENXIO: 60,
  5136.         E2BIG: 1,
  5137.         ENOEXEC: 45,
  5138.         EBADF: 8,
  5139.         ECHILD: 12,
  5140.         EAGAIN: 6,
  5141.         EWOULDBLOCK: 6,
  5142.         ENOMEM: 48,
  5143.         EACCES: 2,
  5144.         EFAULT: 21,
  5145.         ENOTBLK: 105,
  5146.         EBUSY: 10,
  5147.         EEXIST: 20,
  5148.         EXDEV: 75,
  5149.         ENODEV: 43,
  5150.         ENOTDIR: 54,
  5151.         EISDIR: 31,
  5152.         EINVAL: 28,
  5153.         ENFILE: 41,
  5154.         EMFILE: 33,
  5155.         ENOTTY: 59,
  5156.         ETXTBSY: 74,
  5157.         EFBIG: 22,
  5158.         ENOSPC: 51,
  5159.         ESPIPE: 70,
  5160.         EROFS: 69,
  5161.         EMLINK: 34,
  5162.         EPIPE: 64,
  5163.         EDOM: 18,
  5164.         ERANGE: 68,
  5165.         ENOMSG: 49,
  5166.         EIDRM: 24,
  5167.         ECHRNG: 106,
  5168.         EL2NSYNC: 156,
  5169.         EL3HLT: 107,
  5170.         EL3RST: 108,
  5171.         ELNRNG: 109,
  5172.         EUNATCH: 110,
  5173.         ENOCSI: 111,
  5174.         EL2HLT: 112,
  5175.         EDEADLK: 16,
  5176.         ENOLCK: 46,
  5177.         EBADE: 113,
  5178.         EBADR: 114,
  5179.         EXFULL: 115,
  5180.         ENOANO: 104,
  5181.         EBADRQC: 103,
  5182.         EBADSLT: 102,
  5183.         EDEADLOCK: 16,
  5184.         EBFONT: 101,
  5185.         ENOSTR: 100,
  5186.         ENODATA: 116,
  5187.         ETIME: 117,
  5188.         ENOSR: 118,
  5189.         ENONET: 119,
  5190.         ENOPKG: 120,
  5191.         EREMOTE: 121,
  5192.         ENOLINK: 47,
  5193.         EADV: 122,
  5194.         ESRMNT: 123,
  5195.         ECOMM: 124,
  5196.         EPROTO: 65,
  5197.         EMULTIHOP: 36,
  5198.         EDOTDOT: 125,
  5199.         EBADMSG: 9,
  5200.         ENOTUNIQ: 126,
  5201.         EBADFD: 127,
  5202.         EREMCHG: 128,
  5203.         ELIBACC: 129,
  5204.         ELIBBAD: 130,
  5205.         ELIBSCN: 131,
  5206.         ELIBMAX: 132,
  5207.         ELIBEXEC: 133,
  5208.         ENOSYS: 52,
  5209.         ENOTEMPTY: 55,
  5210.         ENAMETOOLONG: 37,
  5211.         ELOOP: 32,
  5212.         EOPNOTSUPP: 138,
  5213.         EPFNOSUPPORT: 139,
  5214.         ECONNRESET: 15,
  5215.         ENOBUFS: 42,
  5216.         EAFNOSUPPORT: 5,
  5217.         EPROTOTYPE: 67,
  5218.         ENOTSOCK: 57,
  5219.         ENOPROTOOPT: 50,
  5220.         ESHUTDOWN: 140,
  5221.         ECONNREFUSED: 14,
  5222.         EADDRINUSE: 3,
  5223.         ECONNABORTED: 13,
  5224.         ENETUNREACH: 40,
  5225.         ENETDOWN: 38,
  5226.         ETIMEDOUT: 73,
  5227.         EHOSTDOWN: 142,
  5228.         EHOSTUNREACH: 23,
  5229.         EINPROGRESS: 26,
  5230.         EALREADY: 7,
  5231.         EDESTADDRREQ: 17,
  5232.         EMSGSIZE: 35,
  5233.         EPROTONOSUPPORT: 66,
  5234.         ESOCKTNOSUPPORT: 137,
  5235.         EADDRNOTAVAIL: 4,
  5236.         ENETRESET: 39,
  5237.         EISCONN: 30,
  5238.         ENOTCONN: 53,
  5239.         ETOOMANYREFS: 141,
  5240.         EUSERS: 136,
  5241.         EDQUOT: 19,
  5242.         ESTALE: 72,
  5243.         ENOTSUP: 138,
  5244.         ENOMEDIUM: 148,
  5245.         EILSEQ: 25,
  5246.         EOVERFLOW: 61,
  5247.         ECANCELED: 11,
  5248.         ENOTRECOVERABLE: 56,
  5249.         EOWNERDEAD: 62,
  5250.         ESTRPIPE: 135,
  5251.     };
  5252.     var SOCKFS = {
  5253.         mount: function (mount) {
  5254.             Module["websocket"] = Module["websocket"] && "object" === typeof Module["websocket"] ? Module["websocket"] : {};
  5255.             Module["websocket"]._callbacks = {};
  5256.             Module["websocket"]["on"] = function (event, callback) {
  5257.                 if ("function" === typeof callback) {
  5258.                     this._callbacks[event] = callback;
  5259.                 }
  5260.                 return this;
  5261.             };
  5262.             Module["websocket"].emit = function (event, param) {
  5263.                 if ("function" === typeof this._callbacks[event]) {
  5264.                     this._callbacks[event].call(this, param);
  5265.                 }
  5266.             };
  5267.             return FS.createNode(null, "/", 16384 | 511, 0);
  5268.         },
  5269.         createSocket: function (family, type, protocol) {
  5270.             type &= ~526336;
  5271.             var streaming = type == 1;
  5272.             if (protocol) {
  5273.                 assert(streaming == (protocol == 6));
  5274.             }
  5275.             var sock = { family: family, type: type, protocol: protocol, server: null, error: null, peers: {}, pending: [], recv_queue: [], sock_ops: SOCKFS.websocket_sock_ops };
  5276.             var name = SOCKFS.nextname();
  5277.             var node = FS.createNode(SOCKFS.root, name, 49152, 0);
  5278.             node.sock = sock;
  5279.             var stream = FS.createStream({ path: name, node: node, flags: 2, seekable: false, stream_ops: SOCKFS.stream_ops });
  5280.             sock.stream = stream;
  5281.             return sock;
  5282.         },
  5283.         getSocket: function (fd) {
  5284.             var stream = FS.getStream(fd);
  5285.             if (!stream || !FS.isSocket(stream.node.mode)) {
  5286.                 return null;
  5287.             }
  5288.             return stream.node.sock;
  5289.         },
  5290.         stream_ops: {
  5291.             poll: function (stream) {
  5292.                 var sock = stream.node.sock;
  5293.                 return sock.sock_ops.poll(sock);
  5294.             },
  5295.             ioctl: function (stream, request, varargs) {
  5296.                 var sock = stream.node.sock;
  5297.                 return sock.sock_ops.ioctl(sock, request, varargs);
  5298.             },
  5299.             read: function (stream, buffer, offset, length, position) {
  5300.                 var sock = stream.node.sock;
  5301.                 var msg = sock.sock_ops.recvmsg(sock, length);
  5302.                 if (!msg) {
  5303.                     return 0;
  5304.                 }
  5305.                 buffer.set(msg.buffer, offset);
  5306.                 return msg.buffer.length;
  5307.             },
  5308.             write: function (stream, buffer, offset, length, position) {
  5309.                 var sock = stream.node.sock;
  5310.                 return sock.sock_ops.sendmsg(sock, buffer, offset, length);
  5311.             },
  5312.             close: function (stream) {
  5313.                 var sock = stream.node.sock;
  5314.                 sock.sock_ops.close(sock);
  5315.             },
  5316.         },
  5317.         nextname: function () {
  5318.             if (!SOCKFS.nextname.current) {
  5319.                 SOCKFS.nextname.current = 0;
  5320.             }
  5321.             return "socket[" + SOCKFS.nextname.current++ + "]";
  5322.         },
  5323.         websocket_sock_ops: {
  5324.             createPeer: function (sock, addr, port) {
  5325.                 var ws;
  5326.                 if (typeof addr === "object") {
  5327.                     ws = addr;
  5328.                     addr = null;
  5329.                     port = null;
  5330.                 }
  5331.                 if (ws) {
  5332.                     if (ws._socket) {
  5333.                         addr = ws._socket.remoteAddress;
  5334.                         port = ws._socket.remotePort;
  5335.                     } else {
  5336.                         var result = /ws[s]?:\/\/([^:]+):(\d+)/.exec(ws.url);
  5337.                         if (!result) {
  5338.                             throw new Error("WebSocket URL must be in the format ws(s)://address:port");
  5339.                         }
  5340.                         addr = result[1];
  5341.                         port = parseInt(result[2], 10);
  5342.                     }
  5343.                 } else {
  5344.                     try {
  5345.                         var runtimeConfig = Module["websocket"] && "object" === typeof Module["websocket"];
  5346.                         var url = "ws:#".replace("#", "//");
  5347.                         if (runtimeConfig) {
  5348.                             if ("string" === typeof Module["websocket"]["url"]) {
  5349.                                 url = Module["websocket"]["url"];
  5350.                             }
  5351.                         }
  5352.                         if (url === "ws://" || url === "wss://") {
  5353.                             var parts = addr.split("/");
  5354.                             url = url + parts[0] + ":" + port + "/" + parts.slice(1).join("/");
  5355.                         }
  5356.                         var subProtocols = "binary";
  5357.                         if (runtimeConfig) {
  5358.                             if ("string" === typeof Module["websocket"]["subprotocol"]) {
  5359.                                 subProtocols = Module["websocket"]["subprotocol"];
  5360.                             }
  5361.                         }
  5362.                         var opts = undefined;
  5363.                         if (subProtocols !== "null") {
  5364.                             subProtocols = subProtocols.replace(/^ +| +$/g, "").split(/ *, */);
  5365.                             opts = ENVIRONMENT_IS_NODE ? { protocol: subProtocols.toString() } : subProtocols;
  5366.                         }
  5367.                         if (runtimeConfig && null === Module["websocket"]["subprotocol"]) {
  5368.                             subProtocols = "null";
  5369.                             opts = undefined;
  5370.                         }
  5371.                         var WebSocketConstructor;
  5372.                         if (ENVIRONMENT_IS_NODE) {
  5373.                             WebSocketConstructor = require("ws");
  5374.                         } else {
  5375.                             WebSocketConstructor = WebSocket;
  5376.                         }
  5377.                         ws = new WebSocketConstructor(url, opts);
  5378.                         ws.binaryType = "arraybuffer";
  5379.                     } catch (e) {
  5380.                         throw new FS.ErrnoError(ERRNO_CODES.EHOSTUNREACH);
  5381.                     }
  5382.                 }
  5383.                 var peer = { addr: addr, port: port, socket: ws, dgram_send_queue: [] };
  5384.                 SOCKFS.websocket_sock_ops.addPeer(sock, peer);
  5385.                 SOCKFS.websocket_sock_ops.handlePeerEvents(sock, peer);
  5386.                 if (sock.type === 2 && typeof sock.sport !== "undefined") {
  5387.                     peer.dgram_send_queue.push(new Uint8Array([255, 255, 255, 255, "p".charCodeAt(0), "o".charCodeAt(0), "r".charCodeAt(0), "t".charCodeAt(0), (sock.sport & 65280) >> 8, sock.sport & 255]));
  5388.                 }
  5389.                 return peer;
  5390.             },
  5391.             getPeer: function (sock, addr, port) {
  5392.                 return sock.peers[addr + ":" + port];
  5393.             },
  5394.             addPeer: function (sock, peer) {
  5395.                 sock.peers[peer.addr + ":" + peer.port] = peer;
  5396.             },
  5397.             removePeer: function (sock, peer) {
  5398.                 delete sock.peers[peer.addr + ":" + peer.port];
  5399.             },
  5400.             handlePeerEvents: function (sock, peer) {
  5401.                 var first = true;
  5402.                 var handleOpen = function () {
  5403.                     Module["websocket"].emit("open", sock.stream.fd);
  5404.                     try {
  5405.                         var queued = peer.dgram_send_queue.shift();
  5406.                         while (queued) {
  5407.                             peer.socket.send(queued);
  5408.                             queued = peer.dgram_send_queue.shift();
  5409.                         }
  5410.                     } catch (e) {
  5411.                         peer.socket.close();
  5412.                     }
  5413.                 };
  5414.                 function handleMessage(data) {
  5415.                     if (typeof data === "string") {
  5416.                         var encoder = new TextEncoder();
  5417.                         data = encoder.encode(data);
  5418.                     } else {
  5419.                         assert(data.byteLength !== undefined);
  5420.                         if (data.byteLength == 0) {
  5421.                             return;
  5422.                         } else {
  5423.                             data = new Uint8Array(data);
  5424.                         }
  5425.                     }
  5426.                     var wasfirst = first;
  5427.                     first = false;
  5428.                     if (
  5429.                         wasfirst &&
  5430.                         data.length === 10 &&
  5431.                         data[0] === 255 &&
  5432.                         data[1] === 255 &&
  5433.                         data[2] === 255 &&
  5434.                         data[3] === 255 &&
  5435.                         data[4] === "p".charCodeAt(0) &&
  5436.                         data[5] === "o".charCodeAt(0) &&
  5437.                         data[6] === "r".charCodeAt(0) &&
  5438.                         data[7] === "t".charCodeAt(0)
  5439.                     ) {
  5440.                         var newport = (data[8] << 8) | data[9];
  5441.                         SOCKFS.websocket_sock_ops.removePeer(sock, peer);
  5442.                         peer.port = newport;
  5443.                         SOCKFS.websocket_sock_ops.addPeer(sock, peer);
  5444.                         return;
  5445.                     }
  5446.                     sock.recv_queue.push({ addr: peer.addr, port: peer.port, data: data });
  5447.                     Module["websocket"].emit("message", sock.stream.fd);
  5448.                 }
  5449.                 if (ENVIRONMENT_IS_NODE) {
  5450.                     peer.socket.on("open", handleOpen);
  5451.                     peer.socket.on("message", function (data, flags) {
  5452.                         if (!flags.binary) {
  5453.                             return;
  5454.                         }
  5455.                         handleMessage(new Uint8Array(data).buffer);
  5456.                     });
  5457.                     peer.socket.on("close", function () {
  5458.                         Module["websocket"].emit("close", sock.stream.fd);
  5459.                     });
  5460.                     peer.socket.on("error", function (error) {
  5461.                         sock.error = ERRNO_CODES.ECONNREFUSED;
  5462.                         Module["websocket"].emit("error", [sock.stream.fd, sock.error, "ECONNREFUSED: Connection refused"]);
  5463.                     });
  5464.                 } else {
  5465.                     peer.socket.onopen = handleOpen;
  5466.                     peer.socket.onclose = function () {
  5467.                         Module["websocket"].emit("close", sock.stream.fd);
  5468.                     };
  5469.                     peer.socket.onmessage = function peer_socket_onmessage(event) {
  5470.                         handleMessage(event.data);
  5471.                     };
  5472.                     peer.socket.onerror = function (error) {
  5473.                         sock.error = ERRNO_CODES.ECONNREFUSED;
  5474.                         Module["websocket"].emit("error", [sock.stream.fd, sock.error, "ECONNREFUSED: Connection refused"]);
  5475.                     };
  5476.                 }
  5477.             },
  5478.             poll: function (sock) {
  5479.                 if (sock.type === 1 && sock.server) {
  5480.                     return sock.pending.length ? 64 | 1 : 0;
  5481.                 }
  5482.                 var mask = 0;
  5483.                 var dest = sock.type === 1 ? SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport) : null;
  5484.                 if (sock.recv_queue.length || !dest || (dest && dest.socket.readyState === dest.socket.CLOSING) || (dest && dest.socket.readyState === dest.socket.CLOSED)) {
  5485.                     mask |= 64 | 1;
  5486.                 }
  5487.                 if (!dest || (dest && dest.socket.readyState === dest.socket.OPEN)) {
  5488.                     mask |= 4;
  5489.                 }
  5490.                 if ((dest && dest.socket.readyState === dest.socket.CLOSING) || (dest && dest.socket.readyState === dest.socket.CLOSED)) {
  5491.                     mask |= 16;
  5492.                 }
  5493.                 return mask;
  5494.             },
  5495.             ioctl: function (sock, request, arg) {
  5496.                 switch (request) {
  5497.                     case 21531:
  5498.                         var bytes = 0;
  5499.                         if (sock.recv_queue.length) {
  5500.                             bytes = sock.recv_queue[0].data.length;
  5501.                         }
  5502.                         HEAP32[arg >> 2] = bytes;
  5503.                         return 0;
  5504.                     default:
  5505.                         return ERRNO_CODES.EINVAL;
  5506.                 }
  5507.             },
  5508.             close: function (sock) {
  5509.                 if (sock.server) {
  5510.                     try {
  5511.                         sock.server.close();
  5512.                     } catch (e) {}
  5513.                     sock.server = null;
  5514.                 }
  5515.                 var peers = Object.keys(sock.peers);
  5516.                 for (var i = 0; i < peers.length; i++) {
  5517.                     var peer = sock.peers[peers[i]];
  5518.                     try {
  5519.                         peer.socket.close();
  5520.                     } catch (e) {}
  5521.                     SOCKFS.websocket_sock_ops.removePeer(sock, peer);
  5522.                 }
  5523.                 return 0;
  5524.             },
  5525.             bind: function (sock, addr, port) {
  5526.                 if (typeof sock.saddr !== "undefined" || typeof sock.sport !== "undefined") {
  5527.                     throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
  5528.                 }
  5529.                 sock.saddr = addr;
  5530.                 sock.sport = port;
  5531.                 if (sock.type === 2) {
  5532.                     if (sock.server) {
  5533.                         sock.server.close();
  5534.                         sock.server = null;
  5535.                     }
  5536.                     try {
  5537.                         sock.sock_ops.listen(sock, 0);
  5538.                     } catch (e) {
  5539.                         if (!(e instanceof FS.ErrnoError)) throw e;
  5540.                         if (e.errno !== ERRNO_CODES.EOPNOTSUPP) throw e;
  5541.                     }
  5542.                 }
  5543.             },
  5544.             connect: function (sock, addr, port) {
  5545.                 if (sock.server) {
  5546.                     throw new FS.ErrnoError(ERRNO_CODES.EOPNOTSUPP);
  5547.                 }
  5548.                 if (typeof sock.daddr !== "undefined" && typeof sock.dport !== "undefined") {
  5549.                     var dest = SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport);
  5550.                     if (dest) {
  5551.                         if (dest.socket.readyState === dest.socket.CONNECTING) {
  5552.                             throw new FS.ErrnoError(ERRNO_CODES.EALREADY);
  5553.                         } else {
  5554.                             throw new FS.ErrnoError(ERRNO_CODES.EISCONN);
  5555.                         }
  5556.                     }
  5557.                 }
  5558.                 var peer = SOCKFS.websocket_sock_ops.createPeer(sock, addr, port);
  5559.                 sock.daddr = peer.addr;
  5560.                 sock.dport = peer.port;
  5561.                 throw new FS.ErrnoError(ERRNO_CODES.EINPROGRESS);
  5562.             },
  5563.             listen: function (sock, backlog) {
  5564.                 if (!ENVIRONMENT_IS_NODE) {
  5565.                     throw new FS.ErrnoError(ERRNO_CODES.EOPNOTSUPP);
  5566.                 }
  5567.                 if (sock.server) {
  5568.                     throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
  5569.                 }
  5570.                 var WebSocketServer = require("ws").Server;
  5571.                 var host = sock.saddr;
  5572.                 sock.server = new WebSocketServer({ host: host, port: sock.sport });
  5573.                 Module["websocket"].emit("listen", sock.stream.fd);
  5574.                 sock.server.on("connection", function (ws) {
  5575.                     if (sock.type === 1) {
  5576.                         var newsock = SOCKFS.createSocket(sock.family, sock.type, sock.protocol);
  5577.                         var peer = SOCKFS.websocket_sock_ops.createPeer(newsock, ws);
  5578.                         newsock.daddr = peer.addr;
  5579.                         newsock.dport = peer.port;
  5580.                         sock.pending.push(newsock);
  5581.                         Module["websocket"].emit("connection", newsock.stream.fd);
  5582.                     } else {
  5583.                         SOCKFS.websocket_sock_ops.createPeer(sock, ws);
  5584.                         Module["websocket"].emit("connection", sock.stream.fd);
  5585.                     }
  5586.                 });
  5587.                 sock.server.on("closed", function () {
  5588.                     Module["websocket"].emit("close", sock.stream.fd);
  5589.                     sock.server = null;
  5590.                 });
  5591.                 sock.server.on("error", function (error) {
  5592.                     sock.error = ERRNO_CODES.EHOSTUNREACH;
  5593.                     Module["websocket"].emit("error", [sock.stream.fd, sock.error, "EHOSTUNREACH: Host is unreachable"]);
  5594.                 });
  5595.             },
  5596.             accept: function (listensock) {
  5597.                 if (!listensock.server) {
  5598.                     throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
  5599.                 }
  5600.                 var newsock = listensock.pending.shift();
  5601.                 newsock.stream.flags = listensock.stream.flags;
  5602.                 return newsock;
  5603.             },
  5604.             getname: function (sock, peer) {
  5605.                 var addr, port;
  5606.                 if (peer) {
  5607.                     if (sock.daddr === undefined || sock.dport === undefined) {
  5608.                         throw new FS.ErrnoError(ERRNO_CODES.ENOTCONN);
  5609.                     }
  5610.                     addr = sock.daddr;
  5611.                     port = sock.dport;
  5612.                 } else {
  5613.                     addr = sock.saddr || 0;
  5614.                     port = sock.sport || 0;
  5615.                 }
  5616.                 return { addr: addr, port: port };
  5617.             },
  5618.             sendmsg: function (sock, buffer, offset, length, addr, port) {
  5619.                 if (sock.type === 2) {
  5620.                     if (addr === undefined || port === undefined) {
  5621.                         addr = sock.daddr;
  5622.                         port = sock.dport;
  5623.                     }
  5624.                     if (addr === undefined || port === undefined) {
  5625.                         throw new FS.ErrnoError(ERRNO_CODES.EDESTADDRREQ);
  5626.                     }
  5627.                 } else {
  5628.                     addr = sock.daddr;
  5629.                     port = sock.dport;
  5630.                 }
  5631.                 var dest = SOCKFS.websocket_sock_ops.getPeer(sock, addr, port);
  5632.                 if (sock.type === 1) {
  5633.                     if (!dest || dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) {
  5634.                         throw new FS.ErrnoError(ERRNO_CODES.ENOTCONN);
  5635.                     } else if (dest.socket.readyState === dest.socket.CONNECTING) {
  5636.                         throw new FS.ErrnoError(ERRNO_CODES.EAGAIN);
  5637.                     }
  5638.                 }
  5639.                 if (ArrayBuffer.isView(buffer)) {
  5640.                     offset += buffer.byteOffset;
  5641.                     buffer = buffer.buffer;
  5642.                 }
  5643.                 var data;
  5644.                 data = buffer.slice(offset, offset + length);
  5645.                 if (sock.type === 2) {
  5646.                     if (!dest || dest.socket.readyState !== dest.socket.OPEN) {
  5647.                         if (!dest || dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) {
  5648.                             dest = SOCKFS.websocket_sock_ops.createPeer(sock, addr, port);
  5649.                         }
  5650.                         dest.dgram_send_queue.push(data);
  5651.                         return length;
  5652.                     }
  5653.                 }
  5654.                 try {
  5655.                     dest.socket.send(data);
  5656.                     return length;
  5657.                 } catch (e) {
  5658.                     throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
  5659.                 }
  5660.             },
  5661.             recvmsg: function (sock, length) {
  5662.                 if (sock.type === 1 && sock.server) {
  5663.                     throw new FS.ErrnoError(ERRNO_CODES.ENOTCONN);
  5664.                 }
  5665.                 var queued = sock.recv_queue.shift();
  5666.                 if (!queued) {
  5667.                     if (sock.type === 1) {
  5668.                         var dest = SOCKFS.websocket_sock_ops.getPeer(sock, sock.daddr, sock.dport);
  5669.                         if (!dest) {
  5670.                             throw new FS.ErrnoError(ERRNO_CODES.ENOTCONN);
  5671.                         } else if (dest.socket.readyState === dest.socket.CLOSING || dest.socket.readyState === dest.socket.CLOSED) {
  5672.                             return null;
  5673.                         } else {
  5674.                             throw new FS.ErrnoError(ERRNO_CODES.EAGAIN);
  5675.                         }
  5676.                     } else {
  5677.                         throw new FS.ErrnoError(ERRNO_CODES.EAGAIN);
  5678.                     }
  5679.                 }
  5680.                 var queuedLength = queued.data.byteLength || queued.data.length;
  5681.                 var queuedOffset = queued.data.byteOffset || 0;
  5682.                 var queuedBuffer = queued.data.buffer || queued.data;
  5683.                 var bytesRead = Math.min(length, queuedLength);
  5684.                 var res = { buffer: new Uint8Array(queuedBuffer, queuedOffset, bytesRead), addr: queued.addr, port: queued.port };
  5685.                 if (sock.type === 1 && bytesRead < queuedLength) {
  5686.                     var bytesRemaining = queuedLength - bytesRead;
  5687.                     queued.data = new Uint8Array(queuedBuffer, queuedOffset + bytesRead, bytesRemaining);
  5688.                     sock.recv_queue.unshift(queued);
  5689.                 }
  5690.                 return res;
  5691.             },
  5692.         },
  5693.     };
  5694.     function getSocketFromFD(fd) {
  5695.         var socket = SOCKFS.getSocket(fd);
  5696.         if (!socket) throw new FS.ErrnoError(8);
  5697.         return socket;
  5698.     }
  5699.     function setErrNo(value) {
  5700.         HEAP32[___errno_location() >> 2] = value;
  5701.         return value;
  5702.     }
  5703.     function inetNtop4(addr) {
  5704.         return (addr & 255) + "." + ((addr >> 8) & 255) + "." + ((addr >> 16) & 255) + "." + ((addr >> 24) & 255);
  5705.     }
  5706.     function inetNtop6(ints) {
  5707.         var str = "";
  5708.         var word = 0;
  5709.         var longest = 0;
  5710.         var lastzero = 0;
  5711.         var zstart = 0;
  5712.         var len = 0;
  5713.         var i = 0;
  5714.         var parts = [ints[0] & 65535, ints[0] >> 16, ints[1] & 65535, ints[1] >> 16, ints[2] & 65535, ints[2] >> 16, ints[3] & 65535, ints[3] >> 16];
  5715.         var hasipv4 = true;
  5716.         var v4part = "";
  5717.         for (i = 0; i < 5; i++) {
  5718.             if (parts[i] !== 0) {
  5719.                 hasipv4 = false;
  5720.                 break;
  5721.             }
  5722.         }
  5723.         if (hasipv4) {
  5724.             v4part = inetNtop4(parts[6] | (parts[7] << 16));
  5725.             if (parts[5] === -1) {
  5726.                 str = "::ffff:";
  5727.                 str += v4part;
  5728.                 return str;
  5729.             }
  5730.             if (parts[5] === 0) {
  5731.                 str = "::";
  5732.                 if (v4part === "0.0.0.0") v4part = "";
  5733.                 if (v4part === "0.0.0.1") v4part = "1";
  5734.                 str += v4part;
  5735.                 return str;
  5736.             }
  5737.         }
  5738.         for (word = 0; word < 8; word++) {
  5739.             if (parts[word] === 0) {
  5740.                 if (word - lastzero > 1) {
  5741.                     len = 0;
  5742.                 }
  5743.                 lastzero = word;
  5744.                 len++;
  5745.             }
  5746.             if (len > longest) {
  5747.                 longest = len;
  5748.                 zstart = word - longest + 1;
  5749.             }
  5750.         }
  5751.         for (word = 0; word < 8; word++) {
  5752.             if (longest > 1) {
  5753.                 if (parts[word] === 0 && word >= zstart && word < zstart + longest) {
  5754.                     if (word === zstart) {
  5755.                         str += ":";
  5756.                         if (zstart === 0) str += ":";
  5757.                     }
  5758.                     continue;
  5759.                 }
  5760.             }
  5761.             str += Number(_ntohs(parts[word] & 65535)).toString(16);
  5762.             str += word < 7 ? ":" : "";
  5763.         }
  5764.         return str;
  5765.     }
  5766.     function readSockaddr(sa, salen) {
  5767.         var family = HEAP16[sa >> 1];
  5768.         var port = _ntohs(HEAPU16[(sa + 2) >> 1]);
  5769.         var addr;
  5770.         switch (family) {
  5771.             case 2:
  5772.                 if (salen !== 16) {
  5773.                     return { errno: 28 };
  5774.                 }
  5775.                 addr = HEAP32[(sa + 4) >> 2];
  5776.                 addr = inetNtop4(addr);
  5777.                 break;
  5778.             case 10:
  5779.                 if (salen !== 28) {
  5780.                     return { errno: 28 };
  5781.                 }
  5782.                 addr = [HEAP32[(sa + 8) >> 2], HEAP32[(sa + 12) >> 2], HEAP32[(sa + 16) >> 2], HEAP32[(sa + 20) >> 2]];
  5783.                 addr = inetNtop6(addr);
  5784.                 break;
  5785.             default:
  5786.                 return { errno: 5 };
  5787.         }
  5788.         return { family: family, addr: addr, port: port };
  5789.     }
  5790.     function getSocketAddress(addrp, addrlen, allowNull) {
  5791.         if (allowNull && addrp === 0) return null;
  5792.         var info = readSockaddr(addrp, addrlen);
  5793.         if (info.errno) throw new FS.ErrnoError(info.errno);
  5794.         info.addr = DNS.lookup_addr(info.addr) || info.addr;
  5795.         return info;
  5796.     }
  5797.     function ___sys_connect(fd, addr, addrlen) {
  5798.         try {
  5799.             var sock = getSocketFromFD(fd);
  5800.             var info = getSocketAddress(addr, addrlen);
  5801.             sock.sock_ops.connect(sock, info.addr, info.port);
  5802.             return 0;
  5803.         } catch (e) {
  5804.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  5805.             return -e.errno;
  5806.         }
  5807.     }
  5808.     function ___sys_fcntl64(fd, cmd, varargs) {
  5809.         SYSCALLS.varargs = varargs;
  5810.         try {
  5811.             var stream = SYSCALLS.getStreamFromFD(fd);
  5812.             switch (cmd) {
  5813.                 case 0: {
  5814.                     var arg = SYSCALLS.get();
  5815.                     if (arg < 0) {
  5816.                         return -28;
  5817.                     }
  5818.                     var newStream;
  5819.                     newStream = FS.open(stream.path, stream.flags, 0, arg);
  5820.                     return newStream.fd;
  5821.                 }
  5822.                 case 1:
  5823.                 case 2:
  5824.                     return 0;
  5825.                 case 3:
  5826.                     return stream.flags;
  5827.                 case 4: {
  5828.                     var arg = SYSCALLS.get();
  5829.                     stream.flags |= arg;
  5830.                     return 0;
  5831.                 }
  5832.                 case 12: {
  5833.                     var arg = SYSCALLS.get();
  5834.                     var offset = 0;
  5835.                     HEAP16[(arg + offset) >> 1] = 2;
  5836.                     return 0;
  5837.                 }
  5838.                 case 13:
  5839.                 case 14:
  5840.                     return 0;
  5841.                 case 16:
  5842.                 case 8:
  5843.                     return -28;
  5844.                 case 9:
  5845.                     setErrNo(28);
  5846.                     return -1;
  5847.                 default: {
  5848.                     return -28;
  5849.                 }
  5850.             }
  5851.         } catch (e) {
  5852.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  5853.             return -e.errno;
  5854.         }
  5855.     }
  5856.     function ___sys_fstat64(fd, buf) {
  5857.         try {
  5858.             var stream = SYSCALLS.getStreamFromFD(fd);
  5859.             return SYSCALLS.doStat(FS.stat, stream.path, buf);
  5860.         } catch (e) {
  5861.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  5862.             return -e.errno;
  5863.         }
  5864.     }
  5865.     function ___sys_getcwd(buf, size) {
  5866.         try {
  5867.             if (size === 0) return -28;
  5868.             var cwd = FS.cwd();
  5869.             var cwdLengthInBytes = lengthBytesUTF8(cwd);
  5870.             if (size < cwdLengthInBytes + 1) return -68;
  5871.             stringToUTF8(cwd, buf, size);
  5872.             return buf;
  5873.         } catch (e) {
  5874.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  5875.             return -e.errno;
  5876.         }
  5877.     }
  5878.     function ___sys_getdents64(fd, dirp, count) {
  5879.         try {
  5880.             var stream = SYSCALLS.getStreamFromFD(fd);
  5881.             if (!stream.getdents) {
  5882.                 stream.getdents = FS.readdir(stream.path);
  5883.             }
  5884.             var struct_size = 280;
  5885.             var pos = 0;
  5886.             var off = FS.llseek(stream, 0, 1);
  5887.             var idx = Math.floor(off / struct_size);
  5888.             while (idx < stream.getdents.length && pos + struct_size <= count) {
  5889.                 var id;
  5890.                 var type;
  5891.                 var name = stream.getdents[idx];
  5892.                 if (name[0] === ".") {
  5893.                     id = 1;
  5894.                     type = 4;
  5895.                 } else {
  5896.                     var child = FS.lookupNode(stream.node, name);
  5897.                     id = child.id;
  5898.                     type = FS.isChrdev(child.mode) ? 2 : FS.isDir(child.mode) ? 4 : FS.isLink(child.mode) ? 10 : 8;
  5899.                 }
  5900.                 (tempI64 = [
  5901.                     id >>> 0,
  5902.                     ((tempDouble = id), +Math.abs(tempDouble) >= 1 ? (tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0) : 0),
  5903.                 ]),
  5904.                     (HEAP32[(dirp + pos) >> 2] = tempI64[0]),
  5905.                     (HEAP32[(dirp + pos + 4) >> 2] = tempI64[1]);
  5906.                 (tempI64 = [
  5907.                     ((idx + 1) * struct_size) >>> 0,
  5908.                     ((tempDouble = (idx + 1) * struct_size),
  5909.                     +Math.abs(tempDouble) >= 1 ? (tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0) : 0),
  5910.                 ]),
  5911.                     (HEAP32[(dirp + pos + 8) >> 2] = tempI64[0]),
  5912.                     (HEAP32[(dirp + pos + 12) >> 2] = tempI64[1]);
  5913.                 HEAP16[(dirp + pos + 16) >> 1] = 280;
  5914.                 HEAP8[(dirp + pos + 18) >> 0] = type;
  5915.                 stringToUTF8(name, dirp + pos + 19, 256);
  5916.                 pos += struct_size;
  5917.                 idx += 1;
  5918.             }
  5919.             FS.llseek(stream, idx * struct_size, 0);
  5920.             return pos;
  5921.         } catch (e) {
  5922.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  5923.             return -e.errno;
  5924.         }
  5925.     }
  5926.     function ___sys_getrusage(who, usage) {
  5927.         try {
  5928.             _memset(usage, 0, 136);
  5929.             HEAP32[usage >> 2] = 1;
  5930.             HEAP32[(usage + 4) >> 2] = 2;
  5931.             HEAP32[(usage + 8) >> 2] = 3;
  5932.             HEAP32[(usage + 12) >> 2] = 4;
  5933.             return 0;
  5934.         } catch (e) {
  5935.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  5936.             return -e.errno;
  5937.         }
  5938.     }
  5939.     function ___sys_getegid32() {
  5940.         return 0;
  5941.     }
  5942.     function ___sys_getuid32() {
  5943.         return ___sys_getegid32();
  5944.     }
  5945.     function ___sys_ioctl(fd, op, varargs) {
  5946.         SYSCALLS.varargs = varargs;
  5947.         try {
  5948.             var stream = SYSCALLS.getStreamFromFD(fd);
  5949.             switch (op) {
  5950.                 case 21509:
  5951.                 case 21505: {
  5952.                     if (!stream.tty) return -59;
  5953.                     return 0;
  5954.                 }
  5955.                 case 21510:
  5956.                 case 21511:
  5957.                 case 21512:
  5958.                 case 21506:
  5959.                 case 21507:
  5960.                 case 21508: {
  5961.                     if (!stream.tty) return -59;
  5962.                     return 0;
  5963.                 }
  5964.                 case 21519: {
  5965.                     if (!stream.tty) return -59;
  5966.                     var argp = SYSCALLS.get();
  5967.                     HEAP32[argp >> 2] = 0;
  5968.                     return 0;
  5969.                 }
  5970.                 case 21520: {
  5971.                     if (!stream.tty) return -59;
  5972.                     return -28;
  5973.                 }
  5974.                 case 21531: {
  5975.                     var argp = SYSCALLS.get();
  5976.                     return FS.ioctl(stream, op, argp);
  5977.                 }
  5978.                 case 21523: {
  5979.                     if (!stream.tty) return -59;
  5980.                     return 0;
  5981.                 }
  5982.                 case 21524: {
  5983.                     if (!stream.tty) return -59;
  5984.                     return 0;
  5985.                 }
  5986.                 default:
  5987.                     abort("bad ioctl syscall " + op);
  5988.             }
  5989.         } catch (e) {
  5990.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  5991.             return -e.errno;
  5992.         }
  5993.     }
  5994.     function ___sys_lstat64(path, buf) {
  5995.         try {
  5996.             path = SYSCALLS.getStr(path);
  5997.             return SYSCALLS.doStat(FS.lstat, path, buf);
  5998.         } catch (e) {
  5999.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  6000.             return -e.errno;
  6001.         }
  6002.     }
  6003.     function ___sys_mkdir(path, mode) {
  6004.         try {
  6005.             path = SYSCALLS.getStr(path);
  6006.             return SYSCALLS.doMkdir(path, mode);
  6007.         } catch (e) {
  6008.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  6009.             return -e.errno;
  6010.         }
  6011.     }
  6012.     function syscallMmap2(addr, len, prot, flags, fd, off) {
  6013.         off <<= 12;
  6014.         var ptr;
  6015.         var allocated = false;
  6016.         if ((flags & 16) !== 0 && addr % 65536 !== 0) {
  6017.             return -28;
  6018.         }
  6019.         if ((flags & 32) !== 0) {
  6020.             ptr = _memalign(65536, len);
  6021.             if (!ptr) return -48;
  6022.             _memset(ptr, 0, len);
  6023.             allocated = true;
  6024.         } else {
  6025.             var info = FS.getStream(fd);
  6026.             if (!info) return -8;
  6027.             var res = FS.mmap(info, addr, len, off, prot, flags);
  6028.             ptr = res.ptr;
  6029.             allocated = res.allocated;
  6030.         }
  6031.         SYSCALLS.mappings[ptr] = { malloc: ptr, len: len, allocated: allocated, fd: fd, prot: prot, flags: flags, offset: off };
  6032.         return ptr;
  6033.     }
  6034.     function ___sys_mmap2(addr, len, prot, flags, fd, off) {
  6035.         try {
  6036.             return syscallMmap2(addr, len, prot, flags, fd, off);
  6037.         } catch (e) {
  6038.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  6039.             return -e.errno;
  6040.         }
  6041.     }
  6042.     function syscallMunmap(addr, len) {
  6043.         if ((addr | 0) === -1 || len === 0) {
  6044.             return -28;
  6045.         }
  6046.         var info = SYSCALLS.mappings[addr];
  6047.         if (!info) return 0;
  6048.         if (len === info.len) {
  6049.             var stream = FS.getStream(info.fd);
  6050.             if (stream) {
  6051.                 if (info.prot & 2) {
  6052.                     SYSCALLS.doMsync(addr, stream, len, info.flags, info.offset);
  6053.                 }
  6054.                 FS.munmap(stream);
  6055.             }
  6056.             SYSCALLS.mappings[addr] = null;
  6057.             if (info.allocated) {
  6058.                 _free(info.malloc);
  6059.             }
  6060.         }
  6061.         return 0;
  6062.     }
  6063.     function ___sys_munmap(addr, len) {
  6064.         try {
  6065.             return syscallMunmap(addr, len);
  6066.         } catch (e) {
  6067.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  6068.             return -e.errno;
  6069.         }
  6070.     }
  6071.     function ___sys_open(path, flags, varargs) {
  6072.         SYSCALLS.varargs = varargs;
  6073.         try {
  6074.             var pathname = SYSCALLS.getStr(path);
  6075.             var mode = varargs ? SYSCALLS.get() : 0;
  6076.             var stream = FS.open(pathname, flags, mode);
  6077.             return stream.fd;
  6078.         } catch (e) {
  6079.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  6080.             return -e.errno;
  6081.         }
  6082.     }
  6083.     function ___sys_readlink(path, buf, bufsize) {
  6084.         try {
  6085.             path = SYSCALLS.getStr(path);
  6086.             return SYSCALLS.doReadlink(path, buf, bufsize);
  6087.         } catch (e) {
  6088.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  6089.             return -e.errno;
  6090.         }
  6091.     }
  6092.     function inetPton4(str) {
  6093.         var b = str.split(".");
  6094.         for (var i = 0; i < 4; i++) {
  6095.             var tmp = Number(b[i]);
  6096.             if (isNaN(tmp)) return null;
  6097.             b[i] = tmp;
  6098.         }
  6099.         return (b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24)) >>> 0;
  6100.     }
  6101.     function jstoi_q(str) {
  6102.         return parseInt(str);
  6103.     }
  6104.     function inetPton6(str) {
  6105.         var words;
  6106.         var w, offset, z;
  6107.         var valid6regx = /^((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\3)::|:\b|$))|(?!\2\3)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})$/i;
  6108.         var parts = [];
  6109.         if (!valid6regx.test(str)) {
  6110.             return null;
  6111.         }
  6112.         if (str === "::") {
  6113.             return [0, 0, 0, 0, 0, 0, 0, 0];
  6114.         }
  6115.         if (str.startsWith("::")) {
  6116.             str = str.replace("::", "Z:");
  6117.         } else {
  6118.             str = str.replace("::", ":Z:");
  6119.         }
  6120.         if (str.indexOf(".") > 0) {
  6121.             str = str.replace(new RegExp("[.]", "g"), ":");
  6122.             words = str.split(":");
  6123.             words[words.length - 4] = jstoi_q(words[words.length - 4]) + jstoi_q(words[words.length - 3]) * 256;
  6124.             words[words.length - 3] = jstoi_q(words[words.length - 2]) + jstoi_q(words[words.length - 1]) * 256;
  6125.             words = words.slice(0, words.length - 2);
  6126.         } else {
  6127.             words = str.split(":");
  6128.         }
  6129.         offset = 0;
  6130.         z = 0;
  6131.         for (w = 0; w < words.length; w++) {
  6132.             if (typeof words[w] === "string") {
  6133.                 if (words[w] === "Z") {
  6134.                     for (z = 0; z < 8 - words.length + 1; z++) {
  6135.                         parts[w + z] = 0;
  6136.                     }
  6137.                     offset = z - 1;
  6138.                 } else {
  6139.                     parts[w + offset] = _htons(parseInt(words[w], 16));
  6140.                 }
  6141.             } else {
  6142.                 parts[w + offset] = words[w];
  6143.             }
  6144.         }
  6145.         return [(parts[1] << 16) | parts[0], (parts[3] << 16) | parts[2], (parts[5] << 16) | parts[4], (parts[7] << 16) | parts[6]];
  6146.     }
  6147.     function writeSockaddr(sa, family, addr, port, addrlen) {
  6148.         switch (family) {
  6149.             case 2:
  6150.                 addr = inetPton4(addr);
  6151.                 if (addrlen) {
  6152.                     HEAP32[addrlen >> 2] = 16;
  6153.                 }
  6154.                 HEAP16[sa >> 1] = family;
  6155.                 HEAP32[(sa + 4) >> 2] = addr;
  6156.                 HEAP16[(sa + 2) >> 1] = _htons(port);
  6157.                 (tempI64 = [
  6158.                     0 >>> 0,
  6159.                     ((tempDouble = 0), +Math.abs(tempDouble) >= 1 ? (tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0) : 0),
  6160.                 ]),
  6161.                     (HEAP32[(sa + 8) >> 2] = tempI64[0]),
  6162.                     (HEAP32[(sa + 12) >> 2] = tempI64[1]);
  6163.                 break;
  6164.             case 10:
  6165.                 addr = inetPton6(addr);
  6166.                 if (addrlen) {
  6167.                     HEAP32[addrlen >> 2] = 28;
  6168.                 }
  6169.                 HEAP32[sa >> 2] = family;
  6170.                 HEAP32[(sa + 8) >> 2] = addr[0];
  6171.                 HEAP32[(sa + 12) >> 2] = addr[1];
  6172.                 HEAP32[(sa + 16) >> 2] = addr[2];
  6173.                 HEAP32[(sa + 20) >> 2] = addr[3];
  6174.                 HEAP16[(sa + 2) >> 1] = _htons(port);
  6175.                 HEAP32[(sa + 4) >> 2] = 0;
  6176.                 HEAP32[(sa + 24) >> 2] = 0;
  6177.                 break;
  6178.             default:
  6179.                 return 5;
  6180.         }
  6181.         return 0;
  6182.     }
  6183.     var DNS = {
  6184.         address_map: { id: 1, addrs: {}, names: {} },
  6185.         lookup_name: function (name) {
  6186.             var res = inetPton4(name);
  6187.             if (res !== null) {
  6188.                 return name;
  6189.             }
  6190.             res = inetPton6(name);
  6191.             if (res !== null) {
  6192.                 return name;
  6193.             }
  6194.             var addr;
  6195.             if (DNS.address_map.addrs[name]) {
  6196.                 addr = DNS.address_map.addrs[name];
  6197.             } else {
  6198.                 var id = DNS.address_map.id++;
  6199.                 assert(id < 65535, "exceeded max address mappings of 65535");
  6200.                 addr = "172.29." + (id & 255) + "." + (id & 65280);
  6201.                 DNS.address_map.names[addr] = name;
  6202.                 DNS.address_map.addrs[name] = addr;
  6203.             }
  6204.             return addr;
  6205.         },
  6206.         lookup_addr: function (addr) {
  6207.             if (DNS.address_map.names[addr]) {
  6208.                 return DNS.address_map.names[addr];
  6209.             }
  6210.             return null;
  6211.         },
  6212.     };
  6213.     function ___sys_recvfrom(fd, buf, len, flags, addr, addrlen) {
  6214.         try {
  6215.             var sock = getSocketFromFD(fd);
  6216.             var msg = sock.sock_ops.recvmsg(sock, len);
  6217.             if (!msg) return 0;
  6218.             if (addr) {
  6219.                 var errno = writeSockaddr(addr, sock.family, DNS.lookup_name(msg.addr), msg.port, addrlen);
  6220.             }
  6221.             HEAPU8.set(msg.buffer, buf);
  6222.             return msg.buffer.byteLength;
  6223.         } catch (e) {
  6224.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  6225.             return -e.errno;
  6226.         }
  6227.     }
  6228.     function ___sys_rename(old_path, new_path) {
  6229.         try {
  6230.             old_path = SYSCALLS.getStr(old_path);
  6231.             new_path = SYSCALLS.getStr(new_path);
  6232.             FS.rename(old_path, new_path);
  6233.             return 0;
  6234.         } catch (e) {
  6235.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  6236.             return -e.errno;
  6237.         }
  6238.     }
  6239.     function ___sys_rmdir(path) {
  6240.         try {
  6241.             path = SYSCALLS.getStr(path);
  6242.             FS.rmdir(path);
  6243.             return 0;
  6244.         } catch (e) {
  6245.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  6246.             return -e.errno;
  6247.         }
  6248.     }
  6249.     function ___sys_sendto(fd, message, length, flags, addr, addr_len) {
  6250.         try {
  6251.             var sock = getSocketFromFD(fd);
  6252.             var dest = getSocketAddress(addr, addr_len, true);
  6253.             if (!dest) {
  6254.                 return FS.write(sock.stream, HEAP8, message, length);
  6255.             } else {
  6256.                 return sock.sock_ops.sendmsg(sock, HEAP8, message, length, dest.addr, dest.port);
  6257.             }
  6258.         } catch (e) {
  6259.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  6260.             return -e.errno;
  6261.         }
  6262.     }
  6263.     function ___sys_shutdown(fd, how) {
  6264.         try {
  6265.             getSocketFromFD(fd);
  6266.             return -52;
  6267.         } catch (e) {
  6268.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  6269.             return -e.errno;
  6270.         }
  6271.     }
  6272.     function ___sys_socket(domain, type, protocol) {
  6273.         try {
  6274.             var sock = SOCKFS.createSocket(domain, type, protocol);
  6275.             return sock.stream.fd;
  6276.         } catch (e) {
  6277.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  6278.             return -e.errno;
  6279.         }
  6280.     }
  6281.     function ___sys_stat64(path, buf) {
  6282.         try {
  6283.             path = SYSCALLS.getStr(path);
  6284.             return SYSCALLS.doStat(FS.stat, path, buf);
  6285.         } catch (e) {
  6286.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  6287.             return -e.errno;
  6288.         }
  6289.     }
  6290.     function ___sys_statfs64(path, size, buf) {
  6291.         try {
  6292.             path = SYSCALLS.getStr(path);
  6293.             HEAP32[(buf + 4) >> 2] = 4096;
  6294.             HEAP32[(buf + 40) >> 2] = 4096;
  6295.             HEAP32[(buf + 8) >> 2] = 1e6;
  6296.             HEAP32[(buf + 12) >> 2] = 5e5;
  6297.             HEAP32[(buf + 16) >> 2] = 5e5;
  6298.             HEAP32[(buf + 20) >> 2] = FS.nextInode;
  6299.             HEAP32[(buf + 24) >> 2] = 1e6;
  6300.             HEAP32[(buf + 28) >> 2] = 42;
  6301.             HEAP32[(buf + 44) >> 2] = 2;
  6302.             HEAP32[(buf + 36) >> 2] = 255;
  6303.             return 0;
  6304.         } catch (e) {
  6305.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  6306.             return -e.errno;
  6307.         }
  6308.     }
  6309.     function ___sys_truncate64(path, zero, low, high) {
  6310.         try {
  6311.             path = SYSCALLS.getStr(path);
  6312.             var length = SYSCALLS.get64(low, high);
  6313.             FS.truncate(path, length);
  6314.             return 0;
  6315.         } catch (e) {
  6316.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  6317.             return -e.errno;
  6318.         }
  6319.     }
  6320.     function ___sys_unlink(path) {
  6321.         try {
  6322.             path = SYSCALLS.getStr(path);
  6323.             FS.unlink(path);
  6324.             return 0;
  6325.         } catch (e) {
  6326.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  6327.             return -e.errno;
  6328.         }
  6329.     }
  6330.     function _abort() {
  6331.         abort();
  6332.     }
  6333.     function _clock() {
  6334.         if (_clock.start === undefined) _clock.start = Date.now();
  6335.         return ((Date.now() - _clock.start) * (1e6 / 1e3)) | 0;
  6336.     }
  6337.     function _emscripten_get_now_res() {
  6338.         if (ENVIRONMENT_IS_NODE) {
  6339.             return 1;
  6340.         } else if (typeof dateNow !== "undefined") {
  6341.             return 1e3;
  6342.         } else return 1e3;
  6343.     }
  6344.     var _emscripten_get_now_is_monotonic = true;
  6345.     function _clock_getres(clk_id, res) {
  6346.         var nsec;
  6347.         if (clk_id === 0) {
  6348.             nsec = 1e3 * 1e3;
  6349.         } else if (clk_id === 1 && _emscripten_get_now_is_monotonic) {
  6350.             nsec = _emscripten_get_now_res();
  6351.         } else {
  6352.             setErrNo(28);
  6353.             return -1;
  6354.         }
  6355.         HEAP32[res >> 2] = (nsec / 1e9) | 0;
  6356.         HEAP32[(res + 4) >> 2] = nsec;
  6357.         return 0;
  6358.     }
  6359.     var _emscripten_get_now;
  6360.     if (ENVIRONMENT_IS_NODE) {
  6361.         _emscripten_get_now = function () {
  6362.             var t = process["hrtime"]();
  6363.             return t[0] * 1e3 + t[1] / 1e6;
  6364.         };
  6365.     } else if (typeof dateNow !== "undefined") {
  6366.         _emscripten_get_now = dateNow;
  6367.     } else
  6368.         _emscripten_get_now = function () {
  6369.             return performance.now();
  6370.         };
  6371.     function _clock_gettime(clk_id, tp) {
  6372.         var now;
  6373.         if (clk_id === 0) {
  6374.             now = Date.now();
  6375.         } else if ((clk_id === 1 || clk_id === 4) && _emscripten_get_now_is_monotonic) {
  6376.             now = _emscripten_get_now();
  6377.         } else {
  6378.             setErrNo(28);
  6379.             return -1;
  6380.         }
  6381.         HEAP32[tp >> 2] = (now / 1e3) | 0;
  6382.         HEAP32[(tp + 4) >> 2] = ((now % 1e3) * 1e3 * 1e3) | 0;
  6383.         return 0;
  6384.     }
  6385.     function _difftime(time1, time0) {
  6386.         return time1 - time0;
  6387.     }
  6388.     function _dlclose(handle) {}
  6389.     function _dlerror() {
  6390.         return 0;
  6391.     }
  6392.     function _dlopen(filename, flag) {}
  6393.     function _dlsym(handle, symbol) {
  6394.         return 0;
  6395.     }
  6396.     var readAsmConstArgsArray = [];
  6397.     function readAsmConstArgs(sigPtr, buf) {
  6398.         readAsmConstArgsArray.length = 0;
  6399.         var ch;
  6400.         buf >>= 2;
  6401.         while ((ch = HEAPU8[sigPtr++])) {
  6402.             var double = ch < 105;
  6403.             if (double && buf & 1) buf++;
  6404.             readAsmConstArgsArray.push(double ? HEAPF64[buf++ >> 1] : HEAP32[buf]);
  6405.             ++buf;
  6406.         }
  6407.         return readAsmConstArgsArray;
  6408.     }
  6409.     function mainThreadEM_ASM(code, sigPtr, argbuf, sync) {
  6410.         var args = readAsmConstArgs(sigPtr, argbuf);
  6411.         return ASM_CONSTS[code].apply(null, args);
  6412.     }
  6413.     function _emscripten_asm_const_int_sync_on_main_thread(code, sigPtr, argbuf) {
  6414.         return mainThreadEM_ASM(code, sigPtr, argbuf, 1);
  6415.     }
  6416.     function _emscripten_set_main_loop_timing(mode, value) {
  6417.         console.log("_emscripten_set_main_loop_timing called with " + mode + ", " + value);
  6418.         mode = 0;
  6419.         value = 1000/30;
  6420.         Browser.mainLoop.timingMode = 0;//mode;
  6421.         Browser.mainLoop.timingValue = 1000/30;//value;
  6422.         if (!Browser.mainLoop.func) {
  6423.             return 1;
  6424.         }
  6425.         if (!Browser.mainLoop.running) {
  6426.             Browser.mainLoop.running = true;
  6427.         }
  6428.         if (mode == 0) {
  6429.             console.log("setting timeout");
  6430.             Browser.mainLoop.scheduler = function Browser_mainLoop_scheduler_setTimeout() {
  6431.                 var timeUntilNextTick = Math.max(0, Browser.mainLoop.tickStartTime + value - _emscripten_get_now()) | 0;
  6432.                 console.log("timeUntilNextTick: " + timeUntilNextTick);
  6433.                 setTimeout(Browser.mainLoop.runner, timeUntilNextTick * 2);
  6434.             };
  6435.             Browser.mainLoop.method = "timeout";
  6436.         } else if (mode == 1) {
  6437.             Browser.mainLoop.scheduler = function Browser_mainLoop_scheduler_rAF() {
  6438.                 Browser.requestAnimationFrame(Browser.mainLoop.runner);
  6439.             };
  6440.             Browser.mainLoop.method = "rAF";
  6441.         } else if (mode == 2) {
  6442.             if (typeof setImmediate === "undefined") {
  6443.                 var setImmediates = [];
  6444.                 var emscriptenMainLoopMessageId = "setimmediate";
  6445.                 var Browser_setImmediate_messageHandler = function (event) {
  6446.                     if (event.data === emscriptenMainLoopMessageId || event.data.target === emscriptenMainLoopMessageId) {
  6447.                         event.stopPropagation();
  6448.                         setImmediates.shift()();
  6449.                     }
  6450.                 };
  6451.                 addEventListener("message", Browser_setImmediate_messageHandler, true);
  6452.                 setImmediate = function Browser_emulated_setImmediate(func) {
  6453.                     setImmediates.push(func);
  6454.                     if (ENVIRONMENT_IS_WORKER) {
  6455.                         if (Module["setImmediates"] === undefined) Module["setImmediates"] = [];
  6456.                         Module["setImmediates"].push(func);
  6457.                         postMessage({ target: emscriptenMainLoopMessageId });
  6458.                     } else postMessage(emscriptenMainLoopMessageId, "*");
  6459.                 };
  6460.             }
  6461.             Browser.mainLoop.scheduler = function Browser_mainLoop_scheduler_setImmediate() {
  6462.                 setImmediate(Browser.mainLoop.runner);
  6463.             };
  6464.             Browser.mainLoop.method = "immediate";
  6465.         }
  6466.         return 0;
  6467.     }
  6468.     function _exit(status) {
  6469.         exit(status);
  6470.     }
  6471.     function maybeExit() {
  6472.         if (!keepRuntimeAlive()) {
  6473.             try {
  6474.                 _exit(EXITSTATUS);
  6475.             } catch (e) {
  6476.                 if (e instanceof ExitStatus) {
  6477.                     return;
  6478.                 }
  6479.                 throw e;
  6480.             }
  6481.         }
  6482.     }
  6483.     function setMainLoop(browserIterationFunc, fps, simulateInfiniteLoop, arg, noSetTiming) {
  6484.         assert(!Browser.mainLoop.func, "emscripten_set_main_loop: there can only be one main loop function at once: call emscripten_cancel_main_loop to cancel the previous one before setting a new one with different parameters.");
  6485.         Browser.mainLoop.func = browserIterationFunc;
  6486.         Browser.mainLoop.arg = arg;
  6487.         var thisMainLoopId = Browser.mainLoop.currentlyRunningMainloop;
  6488.         function checkIsRunning() {
  6489.             if (thisMainLoopId < Browser.mainLoop.currentlyRunningMainloop) {
  6490.                 maybeExit();
  6491.                 return false;
  6492.             }
  6493.             return true;
  6494.         }
  6495.         Browser.mainLoop.running = false;
  6496.         Browser.mainLoop.runner = function Browser_mainLoop_runner() {
  6497.             if (ABORT) return;
  6498.             if (Browser.mainLoop.queue.length > 0) {
  6499.                 var start = Date.now();
  6500.                 var blocker = Browser.mainLoop.queue.shift();
  6501.                 blocker.func(blocker.arg);
  6502.                 if (Browser.mainLoop.remainingBlockers) {
  6503.                     var remaining = Browser.mainLoop.remainingBlockers;
  6504.                     var next = remaining % 1 == 0 ? remaining - 1 : Math.floor(remaining);
  6505.                     if (blocker.counted) {
  6506.                         Browser.mainLoop.remainingBlockers = next;
  6507.                     } else {
  6508.                         next = next + 0.5;
  6509.                         Browser.mainLoop.remainingBlockers = (8 * remaining + next) / 9;
  6510.                     }
  6511.                 }
  6512.                 console.log('main loop blocker "' + blocker.name + '" took ' + (Date.now() - start) + " ms");
  6513.                 Browser.mainLoop.updateStatus();
  6514.                 if (!checkIsRunning()) return;
  6515.                 console.log("Setting timeout to 0");
  6516.                 setTimeout(Browser.mainLoop.runner, 0);
  6517.                 return;
  6518.             }
  6519.             if (!checkIsRunning()) return;
  6520.             Browser.mainLoop.currentFrameNumber = (Browser.mainLoop.currentFrameNumber + 1) | 0;
  6521.             if (Browser.mainLoop.timingMode == 1 && Browser.mainLoop.timingValue > 1 && Browser.mainLoop.currentFrameNumber % Browser.mainLoop.timingValue != 0) {
  6522.                 console.log("Browser.mainLoop.timingMode == 1");
  6523.                 Browser.mainLoop.scheduler();
  6524.                 return;
  6525.             } else if (Browser.mainLoop.timingMode == 0) {
  6526.                 console.log("Browser.mainLoop.timingMode == 0");
  6527.                 Browser.mainLoop.tickStartTime = _emscripten_get_now();
  6528.             }
  6529.             GL.newRenderingFrameStarted();
  6530.             Browser.mainLoop.runIter(browserIterationFunc);
  6531.             if (!checkIsRunning()) return;
  6532.             if (typeof SDL === "object" && SDL.audio && SDL.audio.queueNewAudioData) SDL.audio.queueNewAudioData();
  6533.             Browser.mainLoop.scheduler();
  6534.         };
  6535.         if (!noSetTiming) {
  6536.             console.log("fps: " + fps);
  6537.             fps = 30;
  6538.             if (fps && fps > 0) _emscripten_set_main_loop_timing(0, 1e3 / fps);
  6539.             else _emscripten_set_main_loop_timing(1, 1);
  6540.             Browser.mainLoop.scheduler();
  6541.         }
  6542.         if (simulateInfiniteLoop) {
  6543.             throw "unwind";
  6544.         }
  6545.     }
  6546.     function callUserCallback(func, synchronous) {
  6547.         if (ABORT) {
  6548.             return;
  6549.         }
  6550.         if (synchronous) {
  6551.             func();
  6552.             return;
  6553.         }
  6554.         try {
  6555.             func();
  6556.         } catch (e) {
  6557.             if (e instanceof ExitStatus) {
  6558.                 return;
  6559.             } else if (e !== "unwind") {
  6560.                 if (e && typeof e === "object" && e.stack) err("exception thrown: " + [e, e.stack]);
  6561.                 throw e;
  6562.             }
  6563.         }
  6564.     }
  6565.     var Browser = {
  6566.         mainLoop: {
  6567.             running: false,
  6568.             scheduler: null,
  6569.             method: "",
  6570.             currentlyRunningMainloop: 0,
  6571.             func: null,
  6572.             arg: 0,
  6573.             timingMode: 0,
  6574.             timingValue: 0,
  6575.             currentFrameNumber: 0,
  6576.             queue: [],
  6577.             pause: function () {
  6578.                 Browser.mainLoop.scheduler = null;
  6579.                 Browser.mainLoop.currentlyRunningMainloop++;
  6580.             },
  6581.             resume: function () {
  6582.                 console.log("resume");
  6583.                 Browser.mainLoop.currentlyRunningMainloop++;
  6584.                 var timingMode = Browser.mainLoop.timingMode;
  6585.                 var timingValue = Browser.mainLoop.timingValue;
  6586.                 var func = Browser.mainLoop.func;
  6587.                 Browser.mainLoop.func = null;
  6588.                 setMainLoop(func, 0, false, Browser.mainLoop.arg, true);
  6589.                 _emscripten_set_main_loop_timing(timingMode, timingValue);
  6590.                 Browser.mainLoop.scheduler();
  6591.             },
  6592.             updateStatus: function () {
  6593.                 if (Module["setStatus"]) {
  6594.                     var message = Module["statusMessage"] || "Please wait...";
  6595.                     var remaining = Browser.mainLoop.remainingBlockers;
  6596.                     var expected = Browser.mainLoop.expectedBlockers;
  6597.                     if (remaining) {
  6598.                         if (remaining < expected) {
  6599.                             Module["setStatus"](message + " (" + (expected - remaining) + "/" + expected + ")");
  6600.                         } else {
  6601.                             Module["setStatus"](message);
  6602.                         }
  6603.                     } else {
  6604.                         Module["setStatus"]("");
  6605.                     }
  6606.                 }
  6607.             },
  6608.             runIter: function (func) {
  6609.                 if (ABORT) return;
  6610.                 if (Module["preMainLoop"]) {
  6611.                     var preRet = Module["preMainLoop"]();
  6612.                     if (preRet === false) {
  6613.                         return;
  6614.                     }
  6615.                 }
  6616.                 callUserCallback(func);
  6617.                 if (Module["postMainLoop"]) Module["postMainLoop"]();
  6618.             },
  6619.         },
  6620.         isFullscreen: false,
  6621.         pointerLock: false,
  6622.         moduleContextCreatedCallbacks: [],
  6623.         workers: [],
  6624.         init: function () {
  6625.             if (!Module["preloadPlugins"]) Module["preloadPlugins"] = [];
  6626.             if (Browser.initted) return;
  6627.             Browser.initted = true;
  6628.             try {
  6629.                 new Blob();
  6630.                 Browser.hasBlobConstructor = true;
  6631.             } catch (e) {
  6632.                 Browser.hasBlobConstructor = false;
  6633.                 console.log("warning: no blob constructor, cannot create blobs with mimetypes");
  6634.             }
  6635.             Browser.BlobBuilder = typeof MozBlobBuilder != "undefined" ? MozBlobBuilder : typeof WebKitBlobBuilder != "undefined" ? WebKitBlobBuilder : !Browser.hasBlobConstructor ? console.log("warning: no BlobBuilder") : null;
  6636.             Browser.URLObject = typeof window != "undefined" ? (window.URL ? window.URL : window.webkitURL) : undefined;
  6637.             if (!Module.noImageDecoding && typeof Browser.URLObject === "undefined") {
  6638.                 console.log("warning: Browser does not support creating object URLs. Built-in browser image decoding will not be available.");
  6639.                 Module.noImageDecoding = true;
  6640.             }
  6641.             var imagePlugin = {};
  6642.             imagePlugin["canHandle"] = function imagePlugin_canHandle(name) {
  6643.                 return !Module.noImageDecoding && /\.(jpg|jpeg|png|bmp)$/i.test(name);
  6644.             };
  6645.             imagePlugin["handle"] = function imagePlugin_handle(byteArray, name, onload, onerror) {
  6646.                 var b = null;
  6647.                 if (Browser.hasBlobConstructor) {
  6648.                     try {
  6649.                         b = new Blob([byteArray], { type: Browser.getMimetype(name) });
  6650.                         if (b.size !== byteArray.length) {
  6651.                             b = new Blob([new Uint8Array(byteArray).buffer], { type: Browser.getMimetype(name) });
  6652.                         }
  6653.                     } catch (e) {
  6654.                         warnOnce("Blob constructor present but fails: " + e + "; falling back to blob builder");
  6655.                     }
  6656.                 }
  6657.                 if (!b) {
  6658.                     var bb = new Browser.BlobBuilder();
  6659.                     bb.append(new Uint8Array(byteArray).buffer);
  6660.                     b = bb.getBlob();
  6661.                 }
  6662.                 var url = Browser.URLObject.createObjectURL(b);
  6663.                 var img = new Image();
  6664.                 img.onload = function img_onload() {
  6665.                     assert(img.complete, "Image " + name + " could not be decoded");
  6666.                     var canvas = document.createElement("canvas");
  6667.                     canvas.width = img.width;
  6668.                     canvas.height = img.height;
  6669.                     var ctx = canvas.getContext("2d");
  6670.                     ctx.drawImage(img, 0, 0);
  6671.                     Module["preloadedImages"][name] = canvas;
  6672.                     Browser.URLObject.revokeObjectURL(url);
  6673.                     if (onload) onload(byteArray);
  6674.                 };
  6675.                 img.onerror = function img_onerror(event) {
  6676.                     console.log("Image " + url + " could not be decoded");
  6677.                     if (onerror) onerror();
  6678.                 };
  6679.                 img.src = url;
  6680.             };
  6681.             Module["preloadPlugins"].push(imagePlugin);
  6682.             var audioPlugin = {};
  6683.             audioPlugin["canHandle"] = function audioPlugin_canHandle(name) {
  6684.                 return !Module.noAudioDecoding && name.substr(-4) in { ".ogg": 1, ".wav": 1, ".mp3": 1 };
  6685.             };
  6686.             audioPlugin["handle"] = function audioPlugin_handle(byteArray, name, onload, onerror) {
  6687.                 var done = false;
  6688.                 function finish(audio) {
  6689.                     if (done) return;
  6690.                     done = true;
  6691.                     Module["preloadedAudios"][name] = audio;
  6692.                     if (onload) onload(byteArray);
  6693.                 }
  6694.                 function fail() {
  6695.                     if (done) return;
  6696.                     done = true;
  6697.                     Module["preloadedAudios"][name] = new Audio();
  6698.                     if (onerror) onerror();
  6699.                 }
  6700.                 if (Browser.hasBlobConstructor) {
  6701.                     try {
  6702.                         var b = new Blob([byteArray], { type: Browser.getMimetype(name) });
  6703.                     } catch (e) {
  6704.                         return fail();
  6705.                     }
  6706.                     var url = Browser.URLObject.createObjectURL(b);
  6707.                     var audio = new Audio();
  6708.                     audio.addEventListener(
  6709.                         "canplaythrough",
  6710.                         function () {
  6711.                             finish(audio);
  6712.                         },
  6713.                         false
  6714.                     );
  6715.                     audio.onerror = function audio_onerror(event) {
  6716.                         if (done) return;
  6717.                         console.log("warning: browser could not fully decode audio " + name + ", trying slower base64 approach");
  6718.                         function encode64(data) {
  6719.                             var BASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  6720.                             var PAD = "=";
  6721.                             var ret = "";
  6722.                             var leftchar = 0;
  6723.                             var leftbits = 0;
  6724.                             for (var i = 0; i < data.length; i++) {
  6725.                                 leftchar = (leftchar << 8) | data[i];
  6726.                                 leftbits += 8;
  6727.                                 while (leftbits >= 6) {
  6728.                                     var curr = (leftchar >> (leftbits - 6)) & 63;
  6729.                                     leftbits -= 6;
  6730.                                     ret += BASE[curr];
  6731.                                 }
  6732.                             }
  6733.                             if (leftbits == 2) {
  6734.                                 ret += BASE[(leftchar & 3) << 4];
  6735.                                 ret += PAD + PAD;
  6736.                             } else if (leftbits == 4) {
  6737.                                 ret += BASE[(leftchar & 15) << 2];
  6738.                                 ret += PAD;
  6739.                             }
  6740.                             return ret;
  6741.                         }
  6742.                         audio.src = "data:audio/x-" + name.substr(-3) + ";base64," + encode64(byteArray);
  6743.                         finish(audio);
  6744.                     };
  6745.                     audio.src = url;
  6746.                     Browser.safeSetTimeout(function () {
  6747.                         finish(audio);
  6748.                     }, 1e4);
  6749.                 } else {
  6750.                     return fail();
  6751.                 }
  6752.             };
  6753.             Module["preloadPlugins"].push(audioPlugin);
  6754.             function pointerLockChange() {
  6755.                 Browser.pointerLock =
  6756.                     document["pointerLockElement"] === Module["canvas"] ||
  6757.                     document["mozPointerLockElement"] === Module["canvas"] ||
  6758.                     document["webkitPointerLockElement"] === Module["canvas"] ||
  6759.                     document["msPointerLockElement"] === Module["canvas"];
  6760.             }
  6761.             var canvas = Module["canvas"];
  6762.             if (canvas) {
  6763.                 canvas.requestPointerLock = canvas["requestPointerLock"] || canvas["mozRequestPointerLock"] || canvas["webkitRequestPointerLock"] || canvas["msRequestPointerLock"] || function () {};
  6764.                 canvas.exitPointerLock = document["exitPointerLock"] || document["mozExitPointerLock"] || document["webkitExitPointerLock"] || document["msExitPointerLock"] || function () {};
  6765.                 canvas.exitPointerLock = canvas.exitPointerLock.bind(document);
  6766.                 document.addEventListener("pointerlockchange", pointerLockChange, false);
  6767.                 document.addEventListener("mozpointerlockchange", pointerLockChange, false);
  6768.                 document.addEventListener("webkitpointerlockchange", pointerLockChange, false);
  6769.                 document.addEventListener("mspointerlockchange", pointerLockChange, false);
  6770.                 if (Module["elementPointerLock"]) {
  6771.                     canvas.addEventListener(
  6772.                         "click",
  6773.                         function (ev) {
  6774.                             if (!Browser.pointerLock && Module["canvas"].requestPointerLock) {
  6775.                                 Module["canvas"].requestPointerLock();
  6776.                                 ev.preventDefault();
  6777.                             }
  6778.                         },
  6779.                         false
  6780.                     );
  6781.                 }
  6782.             }
  6783.         },
  6784.         createContext: function (canvas, useWebGL, setInModule, webGLContextAttributes) {
  6785.             if (useWebGL && Module.ctx && canvas == Module.canvas) return Module.ctx;
  6786.             var ctx;
  6787.             var contextHandle;
  6788.             if (useWebGL) {
  6789.                 var contextAttributes = { antialias: false, alpha: false, majorVersion: typeof WebGL2RenderingContext !== "undefined" ? 2 : 1 };
  6790.                 if (webGLContextAttributes) {
  6791.                     for (var attribute in webGLContextAttributes) {
  6792.                         contextAttributes[attribute] = webGLContextAttributes[attribute];
  6793.                     }
  6794.                 }
  6795.                 if (typeof GL !== "undefined") {
  6796.                     contextHandle = GL.createContext(canvas, contextAttributes);
  6797.                     if (contextHandle) {
  6798.                         ctx = GL.getContext(contextHandle).GLctx;
  6799.                     }
  6800.                 }
  6801.             } else {
  6802.                 ctx = canvas.getContext("2d");
  6803.             }
  6804.             if (!ctx) return null;
  6805.             if (setInModule) {
  6806.                 if (!useWebGL) assert(typeof GLctx === "undefined", "cannot set in module if GLctx is used, but we are a non-GL context that would replace it");
  6807.                 Module.ctx = ctx;
  6808.                 if (useWebGL) GL.makeContextCurrent(contextHandle);
  6809.                 Module.useWebGL = useWebGL;
  6810.                 Browser.moduleContextCreatedCallbacks.forEach(function (callback) {
  6811.                     callback();
  6812.                 });
  6813.                 Browser.init();
  6814.             }
  6815.             return ctx;
  6816.         },
  6817.         destroyContext: function (canvas, useWebGL, setInModule) {},
  6818.         fullscreenHandlersInstalled: false,
  6819.         lockPointer: undefined,
  6820.         resizeCanvas: undefined,
  6821.         requestFullscreen: function (lockPointer, resizeCanvas) {
  6822.             Browser.lockPointer = lockPointer;
  6823.             Browser.resizeCanvas = resizeCanvas;
  6824.             if (typeof Browser.lockPointer === "undefined") Browser.lockPointer = true;
  6825.             if (typeof Browser.resizeCanvas === "undefined") Browser.resizeCanvas = false;
  6826.             var canvas = Module["canvas"];
  6827.             function fullscreenChange() {
  6828.                 Browser.isFullscreen = false;
  6829.                 var canvasContainer = canvas.parentNode;
  6830.                 if ((document["fullscreenElement"] || document["mozFullScreenElement"] || document["msFullscreenElement"] || document["webkitFullscreenElement"] || document["webkitCurrentFullScreenElement"]) === canvasContainer) {
  6831.                     canvas.exitFullscreen = Browser.exitFullscreen;
  6832.                     if (Browser.lockPointer) canvas.requestPointerLock();
  6833.                     Browser.isFullscreen = true;
  6834.                     if (Browser.resizeCanvas) {
  6835.                         Browser.setFullscreenCanvasSize();
  6836.                     } else {
  6837.                         Browser.updateCanvasDimensions(canvas);
  6838.                     }
  6839.                 } else {
  6840.                     canvasContainer.parentNode.insertBefore(canvas, canvasContainer);
  6841.                     canvasContainer.parentNode.removeChild(canvasContainer);
  6842.                     if (Browser.resizeCanvas) {
  6843.                         Browser.setWindowedCanvasSize();
  6844.                     } else {
  6845.                         Browser.updateCanvasDimensions(canvas);
  6846.                     }
  6847.                 }
  6848.                 if (Module["onFullScreen"]) Module["onFullScreen"](Browser.isFullscreen);
  6849.                 if (Module["onFullscreen"]) Module["onFullscreen"](Browser.isFullscreen);
  6850.             }
  6851.             if (!Browser.fullscreenHandlersInstalled) {
  6852.                 Browser.fullscreenHandlersInstalled = true;
  6853.                 document.addEventListener("fullscreenchange", fullscreenChange, false);
  6854.                 document.addEventListener("mozfullscreenchange", fullscreenChange, false);
  6855.                 document.addEventListener("webkitfullscreenchange", fullscreenChange, false);
  6856.                 document.addEventListener("MSFullscreenChange", fullscreenChange, false);
  6857.             }
  6858.             var canvasContainer = document.createElement("div");
  6859.             canvas.parentNode.insertBefore(canvasContainer, canvas);
  6860.             canvasContainer.appendChild(canvas);
  6861.             canvasContainer.requestFullscreen =
  6862.                 canvasContainer["requestFullscreen"] ||
  6863.                 canvasContainer["mozRequestFullScreen"] ||
  6864.                 canvasContainer["msRequestFullscreen"] ||
  6865.                 (canvasContainer["webkitRequestFullscreen"]
  6866.                     ? function () {
  6867.                           canvasContainer["webkitRequestFullscreen"](Element["ALLOW_KEYBOARD_INPUT"]);
  6868.                       }
  6869.                     : null) ||
  6870.                 (canvasContainer["webkitRequestFullScreen"]
  6871.                     ? function () {
  6872.                           canvasContainer["webkitRequestFullScreen"](Element["ALLOW_KEYBOARD_INPUT"]);
  6873.                       }
  6874.                     : null);
  6875.             canvasContainer.requestFullscreen();
  6876.         },
  6877.         exitFullscreen: function () {
  6878.             if (!Browser.isFullscreen) {
  6879.                 return false;
  6880.             }
  6881.             var CFS = document["exitFullscreen"] || document["cancelFullScreen"] || document["mozCancelFullScreen"] || document["msExitFullscreen"] || document["webkitCancelFullScreen"] || function () {};
  6882.             CFS.apply(document, []);
  6883.             return true;
  6884.         },
  6885.         nextRAF: 0,
  6886.         fakeRequestAnimationFrame: function (func) {
  6887.             var now = Date.now();
  6888.             if (Browser.nextRAF === 0) {
  6889.                 Browser.nextRAF = now + 1e3 / 60;
  6890.             } else {
  6891.                 while (now + 2 >= Browser.nextRAF) {
  6892.                     Browser.nextRAF += 1e3 / 60;
  6893.                 }
  6894.             }
  6895.             var delay = Math.max(Browser.nextRAF - now, 0);
  6896.             setTimeout(func, delay);
  6897.         },
  6898.         requestAnimationFrame: function (func) {
  6899.             if (typeof requestAnimationFrame === "function") {
  6900.                 requestAnimationFrame(func);
  6901.                 return;
  6902.             }
  6903.             var RAF = Browser.fakeRequestAnimationFrame;
  6904.             RAF(func);
  6905.         },
  6906.         safeRequestAnimationFrame: function (func) {
  6907.             return Browser.requestAnimationFrame(function () {
  6908.                 callUserCallback(func);
  6909.             });
  6910.         },
  6911.         safeSetTimeout: function (func, timeout) {
  6912.             return setTimeout(function () {
  6913.                 callUserCallback(func);
  6914.             }, timeout);
  6915.         },
  6916.         getMimetype: function (name) {
  6917.             return { jpg: "image/jpeg", jpeg: "image/jpeg", png: "image/png", bmp: "image/bmp", ogg: "audio/ogg", wav: "audio/wav", mp3: "audio/mpeg" }[name.substr(name.lastIndexOf(".") + 1)];
  6918.         },
  6919.         getUserMedia: function (func) {
  6920.             if (!window.getUserMedia) {
  6921.                 window.getUserMedia = navigator["getUserMedia"] || navigator["mozGetUserMedia"];
  6922.             }
  6923.             window.getUserMedia(func);
  6924.         },
  6925.         getMovementX: function (event) {
  6926.             return event["movementX"] || event["mozMovementX"] || event["webkitMovementX"] || 0;
  6927.         },
  6928.         getMovementY: function (event) {
  6929.             return event["movementY"] || event["mozMovementY"] || event["webkitMovementY"] || 0;
  6930.         },
  6931.         getMouseWheelDelta: function (event) {
  6932.             var delta = 0;
  6933.             switch (event.type) {
  6934.                 case "DOMMouseScroll":
  6935.                     delta = event.detail / 3;
  6936.                     break;
  6937.                 case "mousewheel":
  6938.                     delta = event.wheelDelta / 120;
  6939.                     break;
  6940.                 case "wheel":
  6941.                     delta = event.deltaY;
  6942.                     switch (event.deltaMode) {
  6943.                         case 0:
  6944.                             delta /= 100;
  6945.                             break;
  6946.                         case 1:
  6947.                             delta /= 3;
  6948.                             break;
  6949.                         case 2:
  6950.                             delta *= 80;
  6951.                             break;
  6952.                         default:
  6953.                             throw "unrecognized mouse wheel delta mode: " + event.deltaMode;
  6954.                     }
  6955.                     break;
  6956.                 default:
  6957.                     throw "unrecognized mouse wheel event: " + event.type;
  6958.             }
  6959.             return delta;
  6960.         },
  6961.         mouseX: 0,
  6962.         mouseY: 0,
  6963.         mouseMovementX: 0,
  6964.         mouseMovementY: 0,
  6965.         touches: {},
  6966.         lastTouches: {},
  6967.         calculateMouseEvent: function (event) {
  6968.             if (Browser.pointerLock) {
  6969.                 if (event.type != "mousemove" && "mozMovementX" in event) {
  6970.                     Browser.mouseMovementX = Browser.mouseMovementY = 0;
  6971.                 } else {
  6972.                     Browser.mouseMovementX = Browser.getMovementX(event);
  6973.                     Browser.mouseMovementY = Browser.getMovementY(event);
  6974.                 }
  6975.                 if (typeof SDL != "undefined") {
  6976.                     Browser.mouseX = SDL.mouseX + Browser.mouseMovementX;
  6977.                     Browser.mouseY = SDL.mouseY + Browser.mouseMovementY;
  6978.                 } else {
  6979.                     Browser.mouseX += Browser.mouseMovementX;
  6980.                     Browser.mouseY += Browser.mouseMovementY;
  6981.                 }
  6982.             } else {
  6983.                 var rect = Module["canvas"].getBoundingClientRect();
  6984.                 var cw = Module["canvas"].width;
  6985.                 var ch = Module["canvas"].height;
  6986.                 var scrollX = typeof window.scrollX !== "undefined" ? window.scrollX : window.pageXOffset;
  6987.                 var scrollY = typeof window.scrollY !== "undefined" ? window.scrollY : window.pageYOffset;
  6988.                 if (event.type === "touchstart" || event.type === "touchend" || event.type === "touchmove") {
  6989.                     var touch = event.touch;
  6990.                     if (touch === undefined) {
  6991.                         return;
  6992.                     }
  6993.                     var adjustedX = touch.pageX - (scrollX + rect.left);
  6994.                     var adjustedY = touch.pageY - (scrollY + rect.top);
  6995.                     adjustedX = adjustedX * (cw / rect.width);
  6996.                     adjustedY = adjustedY * (ch / rect.height);
  6997.                     var coords = { x: adjustedX, y: adjustedY };
  6998.                     if (event.type === "touchstart") {
  6999.                         Browser.lastTouches[touch.identifier] = coords;
  7000.                         Browser.touches[touch.identifier] = coords;
  7001.                     } else if (event.type === "touchend" || event.type === "touchmove") {
  7002.                         var last = Browser.touches[touch.identifier];
  7003.                         if (!last) last = coords;
  7004.                         Browser.lastTouches[touch.identifier] = last;
  7005.                         Browser.touches[touch.identifier] = coords;
  7006.                     }
  7007.                     return;
  7008.                 }
  7009.                 var x = event.pageX - (scrollX + rect.left);
  7010.                 var y = event.pageY - (scrollY + rect.top);
  7011.                 x = x * (cw / rect.width);
  7012.                 y = y * (ch / rect.height);
  7013.                 Browser.mouseMovementX = x - Browser.mouseX;
  7014.                 Browser.mouseMovementY = y - Browser.mouseY;
  7015.                 Browser.mouseX = x;
  7016.                 Browser.mouseY = y;
  7017.             }
  7018.         },
  7019.         asyncLoad: function (url, onload, onerror, noRunDep) {
  7020.             var dep = !noRunDep ? getUniqueRunDependency("al " + url) : "";
  7021.             readAsync(
  7022.                 url,
  7023.                 function (arrayBuffer) {
  7024.                     assert(arrayBuffer, 'Loading data file "' + url + '" failed (no arrayBuffer).');
  7025.                     onload(new Uint8Array(arrayBuffer));
  7026.                     if (dep) removeRunDependency(dep);
  7027.                 },
  7028.                 function (event) {
  7029.                     if (onerror) {
  7030.                         onerror();
  7031.                     } else {
  7032.                         throw 'Loading data file "' + url + '" failed.';
  7033.                     }
  7034.                 }
  7035.             );
  7036.             if (dep) addRunDependency(dep);
  7037.         },
  7038.         resizeListeners: [],
  7039.         updateResizeListeners: function () {
  7040.             var canvas = Module["canvas"];
  7041.             Browser.resizeListeners.forEach(function (listener) {
  7042.                 listener(canvas.width, canvas.height);
  7043.             });
  7044.         },
  7045.         setCanvasSize: function (width, height, noUpdates) {
  7046.             var canvas = Module["canvas"];
  7047.             Browser.updateCanvasDimensions(canvas, width, height);
  7048.             if (!noUpdates) Browser.updateResizeListeners();
  7049.         },
  7050.         windowedWidth: 0,
  7051.         windowedHeight: 0,
  7052.         setFullscreenCanvasSize: function () {
  7053.             if (typeof SDL != "undefined") {
  7054.                 var flags = HEAPU32[SDL.screen >> 2];
  7055.                 flags = flags | 8388608;
  7056.                 HEAP32[SDL.screen >> 2] = flags;
  7057.             }
  7058.             Browser.updateCanvasDimensions(Module["canvas"]);
  7059.             Browser.updateResizeListeners();
  7060.         },
  7061.         setWindowedCanvasSize: function () {
  7062.             if (typeof SDL != "undefined") {
  7063.                 var flags = HEAPU32[SDL.screen >> 2];
  7064.                 flags = flags & ~8388608;
  7065.                 HEAP32[SDL.screen >> 2] = flags;
  7066.             }
  7067.             Browser.updateCanvasDimensions(Module["canvas"]);
  7068.             Browser.updateResizeListeners();
  7069.         },
  7070.         updateCanvasDimensions: function (canvas, wNative, hNative) {
  7071.             if (wNative && hNative) {
  7072.                 canvas.widthNative = wNative;
  7073.                 canvas.heightNative = hNative;
  7074.             } else {
  7075.                 wNative = canvas.widthNative;
  7076.                 hNative = canvas.heightNative;
  7077.             }
  7078.             var w = wNative;
  7079.             var h = hNative;
  7080.             if (Module["forcedAspectRatio"] && Module["forcedAspectRatio"] > 0) {
  7081.                 if (w / h < Module["forcedAspectRatio"]) {
  7082.                     w = Math.round(h * Module["forcedAspectRatio"]);
  7083.                 } else {
  7084.                     h = Math.round(w / Module["forcedAspectRatio"]);
  7085.                 }
  7086.             }
  7087.             if (
  7088.                 (document["fullscreenElement"] || document["mozFullScreenElement"] || document["msFullscreenElement"] || document["webkitFullscreenElement"] || document["webkitCurrentFullScreenElement"]) === canvas.parentNode &&
  7089.                 typeof screen != "undefined"
  7090.             ) {
  7091.                 var factor = Math.min(screen.width / w, screen.height / h);
  7092.                 w = Math.round(w * factor);
  7093.                 h = Math.round(h * factor);
  7094.             }
  7095.             if (Browser.resizeCanvas) {
  7096.                 if (canvas.width != w) canvas.width = w;
  7097.                 if (canvas.height != h) canvas.height = h;
  7098.                 if (typeof canvas.style != "undefined") {
  7099.                     canvas.style.removeProperty("width");
  7100.                     canvas.style.removeProperty("height");
  7101.                 }
  7102.             } else {
  7103.                 if (canvas.width != wNative) canvas.width = wNative;
  7104.                 if (canvas.height != hNative) canvas.height = hNative;
  7105.                 if (typeof canvas.style != "undefined") {
  7106.                     if (w != wNative || h != hNative) {
  7107.                         canvas.style.setProperty("width", w + "px", "important");
  7108.                         canvas.style.setProperty("height", h + "px", "important");
  7109.                     } else {
  7110.                         canvas.style.removeProperty("width");
  7111.                         canvas.style.removeProperty("height");
  7112.                     }
  7113.                 }
  7114.             }
  7115.         },
  7116.         wgetRequests: {},
  7117.         nextWgetRequestHandle: 0,
  7118.         getNextWgetRequestHandle: function () {
  7119.             var handle = Browser.nextWgetRequestHandle;
  7120.             Browser.nextWgetRequestHandle++;
  7121.             return handle;
  7122.         },
  7123.     };
  7124.     function _emscripten_cancel_main_loop() {
  7125.         Browser.mainLoop.pause();
  7126.         Browser.mainLoop.func = null;
  7127.     }
  7128.     function _emscripten_clear_interval(id) {
  7129.         clearInterval(id);
  7130.     }
  7131.     var JSEvents = {
  7132.         inEventHandler: 0,
  7133.         removeAllEventListeners: function () {
  7134.             for (var i = JSEvents.eventHandlers.length - 1; i >= 0; --i) {
  7135.                 JSEvents._removeHandler(i);
  7136.             }
  7137.             JSEvents.eventHandlers = [];
  7138.             JSEvents.deferredCalls = [];
  7139.         },
  7140.         registerRemoveEventListeners: function () {
  7141.             if (!JSEvents.removeEventListenersRegistered) {
  7142.                 __ATEXIT__.push(JSEvents.removeAllEventListeners);
  7143.                 JSEvents.removeEventListenersRegistered = true;
  7144.             }
  7145.         },
  7146.         deferredCalls: [],
  7147.         deferCall: function (targetFunction, precedence, argsList) {
  7148.             function arraysHaveEqualContent(arrA, arrB) {
  7149.                 if (arrA.length != arrB.length) return false;
  7150.                 for (var i in arrA) {
  7151.                     if (arrA[i] != arrB[i]) return false;
  7152.                 }
  7153.                 return true;
  7154.             }
  7155.             for (var i in JSEvents.deferredCalls) {
  7156.                 var call = JSEvents.deferredCalls[i];
  7157.                 if (call.targetFunction == targetFunction && arraysHaveEqualContent(call.argsList, argsList)) {
  7158.                     return;
  7159.                 }
  7160.             }
  7161.             JSEvents.deferredCalls.push({ targetFunction: targetFunction, precedence: precedence, argsList: argsList });
  7162.             JSEvents.deferredCalls.sort(function (x, y) {
  7163.                 return x.precedence < y.precedence;
  7164.             });
  7165.         },
  7166.         removeDeferredCalls: function (targetFunction) {
  7167.             for (var i = 0; i < JSEvents.deferredCalls.length; ++i) {
  7168.                 if (JSEvents.deferredCalls[i].targetFunction == targetFunction) {
  7169.                     JSEvents.deferredCalls.splice(i, 1);
  7170.                     --i;
  7171.                 }
  7172.             }
  7173.         },
  7174.         canPerformEventHandlerRequests: function () {
  7175.             return JSEvents.inEventHandler && JSEvents.currentEventHandler.allowsDeferredCalls;
  7176.         },
  7177.         runDeferredCalls: function () {
  7178.             if (!JSEvents.canPerformEventHandlerRequests()) {
  7179.                 return;
  7180.             }
  7181.             for (var i = 0; i < JSEvents.deferredCalls.length; ++i) {
  7182.                 var call = JSEvents.deferredCalls[i];
  7183.                 JSEvents.deferredCalls.splice(i, 1);
  7184.                 --i;
  7185.                 call.targetFunction.apply(null, call.argsList);
  7186.             }
  7187.         },
  7188.         eventHandlers: [],
  7189.         removeAllHandlersOnTarget: function (target, eventTypeString) {
  7190.             for (var i = 0; i < JSEvents.eventHandlers.length; ++i) {
  7191.                 if (JSEvents.eventHandlers[i].target == target && (!eventTypeString || eventTypeString == JSEvents.eventHandlers[i].eventTypeString)) {
  7192.                     JSEvents._removeHandler(i--);
  7193.                 }
  7194.             }
  7195.         },
  7196.         _removeHandler: function (i) {
  7197.             var h = JSEvents.eventHandlers[i];
  7198.             h.target.removeEventListener(h.eventTypeString, h.eventListenerFunc, h.useCapture);
  7199.             JSEvents.eventHandlers.splice(i, 1);
  7200.         },
  7201.         registerOrRemoveHandler: function (eventHandler) {
  7202.             var jsEventHandler = function jsEventHandler(event) {
  7203.                 ++JSEvents.inEventHandler;
  7204.                 JSEvents.currentEventHandler = eventHandler;
  7205.                 JSEvents.runDeferredCalls();
  7206.                 eventHandler.handlerFunc(event);
  7207.                 JSEvents.runDeferredCalls();
  7208.                 --JSEvents.inEventHandler;
  7209.             };
  7210.             if (eventHandler.callbackfunc) {
  7211.                 eventHandler.eventListenerFunc = jsEventHandler;
  7212.                 eventHandler.target.addEventListener(eventHandler.eventTypeString, jsEventHandler, eventHandler.useCapture);
  7213.                 JSEvents.eventHandlers.push(eventHandler);
  7214.                 JSEvents.registerRemoveEventListeners();
  7215.             } else {
  7216.                 for (var i = 0; i < JSEvents.eventHandlers.length; ++i) {
  7217.                     if (JSEvents.eventHandlers[i].target == eventHandler.target && JSEvents.eventHandlers[i].eventTypeString == eventHandler.eventTypeString) {
  7218.                         JSEvents._removeHandler(i--);
  7219.                     }
  7220.                 }
  7221.             }
  7222.         },
  7223.         getNodeNameForTarget: function (target) {
  7224.             if (!target) return "";
  7225.             if (target == window) return "#window";
  7226.             if (target == screen) return "#screen";
  7227.             return target && target.nodeName ? target.nodeName : "";
  7228.         },
  7229.         fullscreenEnabled: function () {
  7230.             return document.fullscreenEnabled || document.webkitFullscreenEnabled;
  7231.         },
  7232.     };
  7233.     var currentFullscreenStrategy = {};
  7234.     function maybeCStringToJsString(cString) {
  7235.         return cString > 2 ? UTF8ToString(cString) : cString;
  7236.     }
  7237.     var specialHTMLTargets = [0, typeof document !== "undefined" ? document : 0, typeof window !== "undefined" ? window : 0];
  7238.     function findEventTarget(target) {
  7239.         target = maybeCStringToJsString(target);
  7240.         var domElement = specialHTMLTargets[target] || (typeof document !== "undefined" ? document.querySelector(target) : undefined);
  7241.         return domElement;
  7242.     }
  7243.     function findCanvasEventTarget(target) {
  7244.         return findEventTarget(target);
  7245.     }
  7246.     function _emscripten_get_canvas_element_size(target, width, height) {
  7247.         var canvas = findCanvasEventTarget(target);
  7248.         if (!canvas) return -4;
  7249.         HEAP32[width >> 2] = canvas.width;
  7250.         HEAP32[height >> 2] = canvas.height;
  7251.     }
  7252.     function getCanvasElementSize(target) {
  7253.         var stackTop = stackSave();
  7254.         var w = stackAlloc(8);
  7255.         var h = w + 4;
  7256.         var targetInt = stackAlloc(target.id.length + 1);
  7257.         stringToUTF8(target.id, targetInt, target.id.length + 1);
  7258.         var ret = _emscripten_get_canvas_element_size(targetInt, w, h);
  7259.         var size = [HEAP32[w >> 2], HEAP32[h >> 2]];
  7260.         stackRestore(stackTop);
  7261.         return size;
  7262.     }
  7263.     function _emscripten_set_canvas_element_size(target, width, height) {
  7264.         var canvas = findCanvasEventTarget(target);
  7265.         if (!canvas) return -4;
  7266.         canvas.width = width;
  7267.         canvas.height = height;
  7268.         return 0;
  7269.     }
  7270.     function setCanvasElementSize(target, width, height) {
  7271.         if (!target.controlTransferredOffscreen) {
  7272.             target.width = width;
  7273.             target.height = height;
  7274.         } else {
  7275.             var stackTop = stackSave();
  7276.             var targetInt = stackAlloc(target.id.length + 1);
  7277.             stringToUTF8(target.id, targetInt, target.id.length + 1);
  7278.             _emscripten_set_canvas_element_size(targetInt, width, height);
  7279.             stackRestore(stackTop);
  7280.         }
  7281.     }
  7282.     function registerRestoreOldStyle(canvas) {
  7283.         var canvasSize = getCanvasElementSize(canvas);
  7284.         var oldWidth = canvasSize[0];
  7285.         var oldHeight = canvasSize[1];
  7286.         var oldCssWidth = canvas.style.width;
  7287.         var oldCssHeight = canvas.style.height;
  7288.         var oldBackgroundColor = canvas.style.backgroundColor;
  7289.         var oldDocumentBackgroundColor = document.body.style.backgroundColor;
  7290.         var oldPaddingLeft = canvas.style.paddingLeft;
  7291.         var oldPaddingRight = canvas.style.paddingRight;
  7292.         var oldPaddingTop = canvas.style.paddingTop;
  7293.         var oldPaddingBottom = canvas.style.paddingBottom;
  7294.         var oldMarginLeft = canvas.style.marginLeft;
  7295.         var oldMarginRight = canvas.style.marginRight;
  7296.         var oldMarginTop = canvas.style.marginTop;
  7297.         var oldMarginBottom = canvas.style.marginBottom;
  7298.         var oldDocumentBodyMargin = document.body.style.margin;
  7299.         var oldDocumentOverflow = document.documentElement.style.overflow;
  7300.         var oldDocumentScroll = document.body.scroll;
  7301.         var oldImageRendering = canvas.style.imageRendering;
  7302.         function restoreOldStyle() {
  7303.             var fullscreenElement = document.fullscreenElement || document.webkitFullscreenElement || document.msFullscreenElement;
  7304.             if (!fullscreenElement) {
  7305.                 document.removeEventListener("fullscreenchange", restoreOldStyle);
  7306.                 document.removeEventListener("webkitfullscreenchange", restoreOldStyle);
  7307.                 setCanvasElementSize(canvas, oldWidth, oldHeight);
  7308.                 canvas.style.width = oldCssWidth;
  7309.                 canvas.style.height = oldCssHeight;
  7310.                 canvas.style.backgroundColor = oldBackgroundColor;
  7311.                 if (!oldDocumentBackgroundColor) document.body.style.backgroundColor = "white";
  7312.                 document.body.style.backgroundColor = oldDocumentBackgroundColor;
  7313.                 canvas.style.paddingLeft = oldPaddingLeft;
  7314.                 canvas.style.paddingRight = oldPaddingRight;
  7315.                 canvas.style.paddingTop = oldPaddingTop;
  7316.                 canvas.style.paddingBottom = oldPaddingBottom;
  7317.                 canvas.style.marginLeft = oldMarginLeft;
  7318.                 canvas.style.marginRight = oldMarginRight;
  7319.                 canvas.style.marginTop = oldMarginTop;
  7320.                 canvas.style.marginBottom = oldMarginBottom;
  7321.                 document.body.style.margin = oldDocumentBodyMargin;
  7322.                 document.documentElement.style.overflow = oldDocumentOverflow;
  7323.                 document.body.scroll = oldDocumentScroll;
  7324.                 canvas.style.imageRendering = oldImageRendering;
  7325.                 if (canvas.GLctxObject) canvas.GLctxObject.GLctx.viewport(0, 0, oldWidth, oldHeight);
  7326.                 if (currentFullscreenStrategy.canvasResizedCallback) {
  7327.                     (function (a1, a2, a3) {
  7328.                         return dynCall_iiii.apply(null, [currentFullscreenStrategy.canvasResizedCallback, a1, a2, a3]);
  7329.                     })(37, 0, currentFullscreenStrategy.canvasResizedCallbackUserData);
  7330.                 }
  7331.             }
  7332.         }
  7333.         document.addEventListener("fullscreenchange", restoreOldStyle);
  7334.         document.addEventListener("webkitfullscreenchange", restoreOldStyle);
  7335.         return restoreOldStyle;
  7336.     }
  7337.     function setLetterbox(element, topBottom, leftRight) {
  7338.         element.style.paddingLeft = element.style.paddingRight = leftRight + "px";
  7339.         element.style.paddingTop = element.style.paddingBottom = topBottom + "px";
  7340.     }
  7341.     function getBoundingClientRect(e) {
  7342.         return specialHTMLTargets.indexOf(e) < 0 ? e.getBoundingClientRect() : { left: 0, top: 0 };
  7343.     }
  7344.     function _JSEvents_resizeCanvasForFullscreen(target, strategy) {
  7345.         var restoreOldStyle = registerRestoreOldStyle(target);
  7346.         var cssWidth = strategy.softFullscreen ? innerWidth : screen.width;
  7347.         var cssHeight = strategy.softFullscreen ? innerHeight : screen.height;
  7348.         var rect = getBoundingClientRect(target);
  7349.         var windowedCssWidth = rect.width;
  7350.         var windowedCssHeight = rect.height;
  7351.         var canvasSize = getCanvasElementSize(target);
  7352.         var windowedRttWidth = canvasSize[0];
  7353.         var windowedRttHeight = canvasSize[1];
  7354.         if (strategy.scaleMode == 3) {
  7355.             setLetterbox(target, (cssHeight - windowedCssHeight) / 2, (cssWidth - windowedCssWidth) / 2);
  7356.             cssWidth = windowedCssWidth;
  7357.             cssHeight = windowedCssHeight;
  7358.         } else if (strategy.scaleMode == 2) {
  7359.             if (cssWidth * windowedRttHeight < windowedRttWidth * cssHeight) {
  7360.                 var desiredCssHeight = (windowedRttHeight * cssWidth) / windowedRttWidth;
  7361.                 setLetterbox(target, (cssHeight - desiredCssHeight) / 2, 0);
  7362.                 cssHeight = desiredCssHeight;
  7363.             } else {
  7364.                 var desiredCssWidth = (windowedRttWidth * cssHeight) / windowedRttHeight;
  7365.                 setLetterbox(target, 0, (cssWidth - desiredCssWidth) / 2);
  7366.                 cssWidth = desiredCssWidth;
  7367.             }
  7368.         }
  7369.         if (!target.style.backgroundColor) target.style.backgroundColor = "black";
  7370.         if (!document.body.style.backgroundColor) document.body.style.backgroundColor = "black";
  7371.         target.style.width = cssWidth + "px";
  7372.         target.style.height = cssHeight + "px";
  7373.         if (strategy.filteringMode == 1) {
  7374.             target.style.imageRendering = "optimizeSpeed";
  7375.             target.style.imageRendering = "-moz-crisp-edges";
  7376.             target.style.imageRendering = "-o-crisp-edges";
  7377.             target.style.imageRendering = "-webkit-optimize-contrast";
  7378.             target.style.imageRendering = "optimize-contrast";
  7379.             target.style.imageRendering = "crisp-edges";
  7380.             target.style.imageRendering = "pixelated";
  7381.         }
  7382.         var dpiScale = strategy.canvasResolutionScaleMode == 2 ? devicePixelRatio : 1;
  7383.         if (strategy.canvasResolutionScaleMode != 0) {
  7384.             var newWidth = (cssWidth * dpiScale) | 0;
  7385.             var newHeight = (cssHeight * dpiScale) | 0;
  7386.             setCanvasElementSize(target, newWidth, newHeight);
  7387.             if (target.GLctxObject) target.GLctxObject.GLctx.viewport(0, 0, newWidth, newHeight);
  7388.         }
  7389.         return restoreOldStyle;
  7390.     }
  7391.     function _JSEvents_requestFullscreen(target, strategy) {
  7392.         if (strategy.scaleMode != 0 || strategy.canvasResolutionScaleMode != 0) {
  7393.             _JSEvents_resizeCanvasForFullscreen(target, strategy);
  7394.         }
  7395.         if (target.requestFullscreen) {
  7396.             target.requestFullscreen();
  7397.         } else if (target.webkitRequestFullscreen) {
  7398.             target.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT);
  7399.         } else {
  7400.             return JSEvents.fullscreenEnabled() ? -3 : -1;
  7401.         }
  7402.         currentFullscreenStrategy = strategy;
  7403.         if (strategy.canvasResizedCallback) {
  7404.             (function (a1, a2, a3) {
  7405.                 return dynCall_iiii.apply(null, [strategy.canvasResizedCallback, a1, a2, a3]);
  7406.             })(37, 0, strategy.canvasResizedCallbackUserData);
  7407.         }
  7408.         return 0;
  7409.     }
  7410.     function _emscripten_exit_fullscreen() {
  7411.         if (!JSEvents.fullscreenEnabled()) return -1;
  7412.         JSEvents.removeDeferredCalls(_JSEvents_requestFullscreen);
  7413.         var d = specialHTMLTargets[1];
  7414.         if (d.exitFullscreen) {
  7415.             d.fullscreenElement && d.exitFullscreen();
  7416.         } else if (d.webkitExitFullscreen) {
  7417.             d.webkitFullscreenElement && d.webkitExitFullscreen();
  7418.         } else {
  7419.             return -1;
  7420.         }
  7421.         return 0;
  7422.     }
  7423.     function requestPointerLock(target) {
  7424.         if (target.requestPointerLock) {
  7425.             target.requestPointerLock();
  7426.         } else if (target.msRequestPointerLock) {
  7427.             target.msRequestPointerLock();
  7428.         } else {
  7429.             if (document.body.requestPointerLock || document.body.msRequestPointerLock) {
  7430.                 return -3;
  7431.             } else {
  7432.                 return -1;
  7433.             }
  7434.         }
  7435.         return 0;
  7436.     }
  7437.     function _emscripten_exit_pointerlock() {
  7438.         JSEvents.removeDeferredCalls(requestPointerLock);
  7439.         if (document.exitPointerLock) {
  7440.             document.exitPointerLock();
  7441.         } else if (document.msExitPointerLock) {
  7442.             document.msExitPointerLock();
  7443.         } else {
  7444.             return -1;
  7445.         }
  7446.         return 0;
  7447.     }
  7448.     function fillFullscreenChangeEventData(eventStruct) {
  7449.         var fullscreenElement = document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement;
  7450.         var isFullscreen = !!fullscreenElement;
  7451.         HEAP32[eventStruct >> 2] = isFullscreen;
  7452.         HEAP32[(eventStruct + 4) >> 2] = JSEvents.fullscreenEnabled();
  7453.         var reportedElement = isFullscreen ? fullscreenElement : JSEvents.previousFullscreenElement;
  7454.         var nodeName = JSEvents.getNodeNameForTarget(reportedElement);
  7455.         var id = reportedElement && reportedElement.id ? reportedElement.id : "";
  7456.         stringToUTF8(nodeName, eventStruct + 8, 128);
  7457.         stringToUTF8(id, eventStruct + 136, 128);
  7458.         HEAP32[(eventStruct + 264) >> 2] = reportedElement ? reportedElement.clientWidth : 0;
  7459.         HEAP32[(eventStruct + 268) >> 2] = reportedElement ? reportedElement.clientHeight : 0;
  7460.         HEAP32[(eventStruct + 272) >> 2] = screen.width;
  7461.         HEAP32[(eventStruct + 276) >> 2] = screen.height;
  7462.         if (isFullscreen) {
  7463.             JSEvents.previousFullscreenElement = fullscreenElement;
  7464.         }
  7465.     }
  7466.     function _emscripten_get_fullscreen_status(fullscreenStatus) {
  7467.         if (!JSEvents.fullscreenEnabled()) return -1;
  7468.         fillFullscreenChangeEventData(fullscreenStatus);
  7469.         return 0;
  7470.     }
  7471.     function fillGamepadEventData(eventStruct, e) {
  7472.         HEAPF64[eventStruct >> 3] = e.timestamp;
  7473.         for (var i = 0; i < e.axes.length; ++i) {
  7474.             HEAPF64[(eventStruct + i * 8 + 16) >> 3] = e.axes[i];
  7475.         }
  7476.         for (var i = 0; i < e.buttons.length; ++i) {
  7477.             if (typeof e.buttons[i] === "object") {
  7478.                 HEAPF64[(eventStruct + i * 8 + 528) >> 3] = e.buttons[i].value;
  7479.             } else {
  7480.                 HEAPF64[(eventStruct + i * 8 + 528) >> 3] = e.buttons[i];
  7481.             }
  7482.         }
  7483.         for (var i = 0; i < e.buttons.length; ++i) {
  7484.             if (typeof e.buttons[i] === "object") {
  7485.                 HEAP32[(eventStruct + i * 4 + 1040) >> 2] = e.buttons[i].pressed;
  7486.             } else {
  7487.                 HEAP32[(eventStruct + i * 4 + 1040) >> 2] = e.buttons[i] == 1;
  7488.             }
  7489.         }
  7490.         HEAP32[(eventStruct + 1296) >> 2] = e.connected;
  7491.         HEAP32[(eventStruct + 1300) >> 2] = e.index;
  7492.         HEAP32[(eventStruct + 8) >> 2] = e.axes.length;
  7493.         HEAP32[(eventStruct + 12) >> 2] = e.buttons.length;
  7494.         stringToUTF8(e.id, eventStruct + 1304, 64);
  7495.         stringToUTF8(e.mapping, eventStruct + 1368, 64);
  7496.     }
  7497.     function _emscripten_get_gamepad_status(index, gamepadState) {
  7498.         if (index < 0 || index >= JSEvents.lastGamepadState.length) return -5;
  7499.         if (!JSEvents.lastGamepadState[index]) return -7;
  7500.         fillGamepadEventData(gamepadState, JSEvents.lastGamepadState[index]);
  7501.         return 0;
  7502.     }
  7503.     function _emscripten_get_heap_max() {
  7504.         return 2147483648;
  7505.     }
  7506.     function _emscripten_get_num_gamepads() {
  7507.         return JSEvents.lastGamepadState.length;
  7508.     }
  7509.     function _emscripten_html5_remove_all_event_listeners() {
  7510.         JSEvents.removeAllEventListeners();
  7511.     }
  7512.     function _emscripten_is_webgl_context_lost(contextHandle) {
  7513.         return !GL.contexts[contextHandle] || GL.contexts[contextHandle].GLctx.isContextLost();
  7514.     }
  7515.     function reallyNegative(x) {
  7516.         return x < 0 || (x === 0 && 1 / x === -Infinity);
  7517.     }
  7518.     function convertI32PairToI53(lo, hi) {
  7519.         return (lo >>> 0) + hi * 4294967296;
  7520.     }
  7521.     function convertU32PairToI53(lo, hi) {
  7522.         return (lo >>> 0) + (hi >>> 0) * 4294967296;
  7523.     }
  7524.     function reSign(value, bits) {
  7525.         if (value <= 0) {
  7526.             return value;
  7527.         }
  7528.         var half = bits <= 32 ? Math.abs(1 << (bits - 1)) : Math.pow(2, bits - 1);
  7529.         if (value >= half && (bits <= 32 || value > half)) {
  7530.             value = -2 * half + value;
  7531.         }
  7532.         return value;
  7533.     }
  7534.     function unSign(value, bits) {
  7535.         if (value >= 0) {
  7536.             return value;
  7537.         }
  7538.         return bits <= 32 ? 2 * Math.abs(1 << (bits - 1)) + value : Math.pow(2, bits) + value;
  7539.     }
  7540.     function formatString(format, varargs) {
  7541.         var textIndex = format;
  7542.         var argIndex = varargs;
  7543.         function prepVararg(ptr, type) {
  7544.             if (type === "double" || type === "i64") {
  7545.                 if (ptr & 7) {
  7546.                     ptr += 4;
  7547.                 }
  7548.             } else {
  7549.             }
  7550.             return ptr;
  7551.         }
  7552.         function getNextArg(type) {
  7553.             var ret;
  7554.             argIndex = prepVararg(argIndex, type);
  7555.             if (type === "double") {
  7556.                 ret = HEAPF64[argIndex >> 3];
  7557.                 argIndex += 8;
  7558.             } else if (type == "i64") {
  7559.                 ret = [HEAP32[argIndex >> 2], HEAP32[(argIndex + 4) >> 2]];
  7560.                 argIndex += 8;
  7561.             } else {
  7562.                 type = "i32";
  7563.                 ret = HEAP32[argIndex >> 2];
  7564.                 argIndex += 4;
  7565.             }
  7566.             return ret;
  7567.         }
  7568.         var ret = [];
  7569.         var curr, next, currArg;
  7570.         while (1) {
  7571.             var startTextIndex = textIndex;
  7572.             curr = HEAP8[textIndex >> 0];
  7573.             if (curr === 0) break;
  7574.             next = HEAP8[(textIndex + 1) >> 0];
  7575.             if (curr == 37) {
  7576.                 var flagAlwaysSigned = false;
  7577.                 var flagLeftAlign = false;
  7578.                 var flagAlternative = false;
  7579.                 var flagZeroPad = false;
  7580.                 var flagPadSign = false;
  7581.                 flagsLoop: while (1) {
  7582.                     switch (next) {
  7583.                         case 43:
  7584.                             flagAlwaysSigned = true;
  7585.                             break;
  7586.                         case 45:
  7587.                             flagLeftAlign = true;
  7588.                             break;
  7589.                         case 35:
  7590.                             flagAlternative = true;
  7591.                             break;
  7592.                         case 48:
  7593.                             if (flagZeroPad) {
  7594.                                 break flagsLoop;
  7595.                             } else {
  7596.                                 flagZeroPad = true;
  7597.                                 break;
  7598.                             }
  7599.                         case 32:
  7600.                             flagPadSign = true;
  7601.                             break;
  7602.                         default:
  7603.                             break flagsLoop;
  7604.                     }
  7605.                     textIndex++;
  7606.                     next = HEAP8[(textIndex + 1) >> 0];
  7607.                 }
  7608.                 var width = 0;
  7609.                 if (next == 42) {
  7610.                     width = getNextArg("i32");
  7611.                     textIndex++;
  7612.                     next = HEAP8[(textIndex + 1) >> 0];
  7613.                 } else {
  7614.                     while (next >= 48 && next <= 57) {
  7615.                         width = width * 10 + (next - 48);
  7616.                         textIndex++;
  7617.                         next = HEAP8[(textIndex + 1) >> 0];
  7618.                     }
  7619.                 }
  7620.                 var precisionSet = false,
  7621.                     precision = -1;
  7622.                 if (next == 46) {
  7623.                     precision = 0;
  7624.                     precisionSet = true;
  7625.                     textIndex++;
  7626.                     next = HEAP8[(textIndex + 1) >> 0];
  7627.                     if (next == 42) {
  7628.                         precision = getNextArg("i32");
  7629.                         textIndex++;
  7630.                     } else {
  7631.                         while (1) {
  7632.                             var precisionChr = HEAP8[(textIndex + 1) >> 0];
  7633.                             if (precisionChr < 48 || precisionChr > 57) break;
  7634.                             precision = precision * 10 + (precisionChr - 48);
  7635.                             textIndex++;
  7636.                         }
  7637.                     }
  7638.                     next = HEAP8[(textIndex + 1) >> 0];
  7639.                 }
  7640.                 if (precision < 0) {
  7641.                     precision = 6;
  7642.                     precisionSet = false;
  7643.                 }
  7644.                 var argSize;
  7645.                 switch (String.fromCharCode(next)) {
  7646.                     case "h":
  7647.                         var nextNext = HEAP8[(textIndex + 2) >> 0];
  7648.                         if (nextNext == 104) {
  7649.                             textIndex++;
  7650.                             argSize = 1;
  7651.                         } else {
  7652.                             argSize = 2;
  7653.                         }
  7654.                         break;
  7655.                     case "l":
  7656.                         var nextNext = HEAP8[(textIndex + 2) >> 0];
  7657.                         if (nextNext == 108) {
  7658.                             textIndex++;
  7659.                             argSize = 8;
  7660.                         } else {
  7661.                             argSize = 4;
  7662.                         }
  7663.                         break;
  7664.                     case "L":
  7665.                     case "q":
  7666.                     case "j":
  7667.                         argSize = 8;
  7668.                         break;
  7669.                     case "z":
  7670.                     case "t":
  7671.                     case "I":
  7672.                         argSize = 4;
  7673.                         break;
  7674.                     default:
  7675.                         argSize = null;
  7676.                 }
  7677.                 if (argSize) textIndex++;
  7678.                 next = HEAP8[(textIndex + 1) >> 0];
  7679.                 switch (String.fromCharCode(next)) {
  7680.                     case "d":
  7681.                     case "i":
  7682.                     case "u":
  7683.                     case "o":
  7684.                     case "x":
  7685.                     case "X":
  7686.                     case "p": {
  7687.                         var signed = next == 100 || next == 105;
  7688.                         argSize = argSize || 4;
  7689.                         currArg = getNextArg("i" + argSize * 8);
  7690.                         var argText;
  7691.                         if (argSize == 8) {
  7692.                             currArg = next == 117 ? convertU32PairToI53(currArg[0], currArg[1]) : convertI32PairToI53(currArg[0], currArg[1]);
  7693.                         }
  7694.                         if (argSize <= 4) {
  7695.                             var limit = Math.pow(256, argSize) - 1;
  7696.                             currArg = (signed ? reSign : unSign)(currArg & limit, argSize * 8);
  7697.                         }
  7698.                         var currAbsArg = Math.abs(currArg);
  7699.                         var prefix = "";
  7700.                         if (next == 100 || next == 105) {
  7701.                             argText = reSign(currArg, 8 * argSize, 1).toString(10);
  7702.                         } else if (next == 117) {
  7703.                             argText = unSign(currArg, 8 * argSize, 1).toString(10);
  7704.                             currArg = Math.abs(currArg);
  7705.                         } else if (next == 111) {
  7706.                             argText = (flagAlternative ? "0" : "") + currAbsArg.toString(8);
  7707.                         } else if (next == 120 || next == 88) {
  7708.                             prefix = flagAlternative && currArg != 0 ? "0x" : "";
  7709.                             if (currArg < 0) {
  7710.                                 currArg = -currArg;
  7711.                                 argText = (currAbsArg - 1).toString(16);
  7712.                                 var buffer = [];
  7713.                                 for (var i = 0; i < argText.length; i++) {
  7714.                                     buffer.push((15 - parseInt(argText[i], 16)).toString(16));
  7715.                                 }
  7716.                                 argText = buffer.join("");
  7717.                                 while (argText.length < argSize * 2) argText = "f" + argText;
  7718.                             } else {
  7719.                                 argText = currAbsArg.toString(16);
  7720.                             }
  7721.                             if (next == 88) {
  7722.                                 prefix = prefix.toUpperCase();
  7723.                                 argText = argText.toUpperCase();
  7724.                             }
  7725.                         } else if (next == 112) {
  7726.                             if (currAbsArg === 0) {
  7727.                                 argText = "(nil)";
  7728.                             } else {
  7729.                                 prefix = "0x";
  7730.                                 argText = currAbsArg.toString(16);
  7731.                             }
  7732.                         }
  7733.                         if (precisionSet) {
  7734.                             while (argText.length < precision) {
  7735.                                 argText = "0" + argText;
  7736.                             }
  7737.                         }
  7738.                         if (currArg >= 0) {
  7739.                             if (flagAlwaysSigned) {
  7740.                                 prefix = "+" + prefix;
  7741.                             } else if (flagPadSign) {
  7742.                                 prefix = " " + prefix;
  7743.                             }
  7744.                         }
  7745.                         if (argText.charAt(0) == "-") {
  7746.                             prefix = "-" + prefix;
  7747.                             argText = argText.substr(1);
  7748.                         }
  7749.                         while (prefix.length + argText.length < width) {
  7750.                             if (flagLeftAlign) {
  7751.                                 argText += " ";
  7752.                             } else {
  7753.                                 if (flagZeroPad) {
  7754.                                     argText = "0" + argText;
  7755.                                 } else {
  7756.                                     prefix = " " + prefix;
  7757.                                 }
  7758.                             }
  7759.                         }
  7760.                         argText = prefix + argText;
  7761.                         argText.split("").forEach(function (chr) {
  7762.                             ret.push(chr.charCodeAt(0));
  7763.                         });
  7764.                         break;
  7765.                     }
  7766.                     case "f":
  7767.                     case "F":
  7768.                     case "e":
  7769.                     case "E":
  7770.                     case "g":
  7771.                     case "G": {
  7772.                         currArg = getNextArg("double");
  7773.                         var argText;
  7774.                         if (isNaN(currArg)) {
  7775.                             argText = "nan";
  7776.                             flagZeroPad = false;
  7777.                         } else if (!isFinite(currArg)) {
  7778.                             argText = (currArg < 0 ? "-" : "") + "inf";
  7779.                             flagZeroPad = false;
  7780.                         } else {
  7781.                             var isGeneral = false;
  7782.                             var effectivePrecision = Math.min(precision, 20);
  7783.                             if (next == 103 || next == 71) {
  7784.                                 isGeneral = true;
  7785.                                 precision = precision || 1;
  7786.                                 var exponent = parseInt(currArg.toExponential(effectivePrecision).split("e")[1], 10);
  7787.                                 if (precision > exponent && exponent >= -4) {
  7788.                                     next = (next == 103 ? "f" : "F").charCodeAt(0);
  7789.                                     precision -= exponent + 1;
  7790.                                 } else {
  7791.                                     next = (next == 103 ? "e" : "E").charCodeAt(0);
  7792.                                     precision--;
  7793.                                 }
  7794.                                 effectivePrecision = Math.min(precision, 20);
  7795.                             }
  7796.                             if (next == 101 || next == 69) {
  7797.                                 argText = currArg.toExponential(effectivePrecision);
  7798.                                 if (/[eE][-+]\d$/.test(argText)) {
  7799.                                     argText = argText.slice(0, -1) + "0" + argText.slice(-1);
  7800.                                 }
  7801.                             } else if (next == 102 || next == 70) {
  7802.                                 argText = currArg.toFixed(effectivePrecision);
  7803.                                 if (currArg === 0 && reallyNegative(currArg)) {
  7804.                                     argText = "-" + argText;
  7805.                                 }
  7806.                             }
  7807.                             var parts = argText.split("e");
  7808.                             if (isGeneral && !flagAlternative) {
  7809.                                 while (parts[0].length > 1 && parts[0].includes(".") && (parts[0].slice(-1) == "0" || parts[0].slice(-1) == ".")) {
  7810.                                     parts[0] = parts[0].slice(0, -1);
  7811.                                 }
  7812.                             } else {
  7813.                                 if (flagAlternative && argText.indexOf(".") == -1) parts[0] += ".";
  7814.                                 while (precision > effectivePrecision++) parts[0] += "0";
  7815.                             }
  7816.                             argText = parts[0] + (parts.length > 1 ? "e" + parts[1] : "");
  7817.                             if (next == 69) argText = argText.toUpperCase();
  7818.                             if (currArg >= 0) {
  7819.                                 if (flagAlwaysSigned) {
  7820.                                     argText = "+" + argText;
  7821.                                 } else if (flagPadSign) {
  7822.                                     argText = " " + argText;
  7823.                                 }
  7824.                             }
  7825.                         }
  7826.                         while (argText.length < width) {
  7827.                             if (flagLeftAlign) {
  7828.                                 argText += " ";
  7829.                             } else {
  7830.                                 if (flagZeroPad && (argText[0] == "-" || argText[0] == "+")) {
  7831.                                     argText = argText[0] + "0" + argText.slice(1);
  7832.                                 } else {
  7833.                                     argText = (flagZeroPad ? "0" : " ") + argText;
  7834.                                 }
  7835.                             }
  7836.                         }
  7837.                         if (next < 97) argText = argText.toUpperCase();
  7838.                         argText.split("").forEach(function (chr) {
  7839.                             ret.push(chr.charCodeAt(0));
  7840.                         });
  7841.                         break;
  7842.                     }
  7843.                     case "s": {
  7844.                         var arg = getNextArg("i8*");
  7845.                         var argLength = arg ? _strlen(arg) : "(null)".length;
  7846.                         if (precisionSet) argLength = Math.min(argLength, precision);
  7847.                         if (!flagLeftAlign) {
  7848.                             while (argLength < width--) {
  7849.                                 ret.push(32);
  7850.                             }
  7851.                         }
  7852.                         if (arg) {
  7853.                             for (var i = 0; i < argLength; i++) {
  7854.                                 ret.push(HEAPU8[arg++ >> 0]);
  7855.                             }
  7856.                         } else {
  7857.                             ret = ret.concat(intArrayFromString("(null)".substr(0, argLength), true));
  7858.                         }
  7859.                         if (flagLeftAlign) {
  7860.                             while (argLength < width--) {
  7861.                                 ret.push(32);
  7862.                             }
  7863.                         }
  7864.                         break;
  7865.                     }
  7866.                     case "c": {
  7867.                         if (flagLeftAlign) ret.push(getNextArg("i8"));
  7868.                         while (--width > 0) {
  7869.                             ret.push(32);
  7870.                         }
  7871.                         if (!flagLeftAlign) ret.push(getNextArg("i8"));
  7872.                         break;
  7873.                     }
  7874.                     case "n": {
  7875.                         var ptr = getNextArg("i32*");
  7876.                         HEAP32[ptr >> 2] = ret.length;
  7877.                         break;
  7878.                     }
  7879.                     case "%": {
  7880.                         ret.push(curr);
  7881.                         break;
  7882.                     }
  7883.                     default: {
  7884.                         for (var i = startTextIndex; i < textIndex + 2; i++) {
  7885.                             ret.push(HEAP8[i >> 0]);
  7886.                         }
  7887.                     }
  7888.                 }
  7889.                 textIndex += 2;
  7890.             } else {
  7891.                 ret.push(curr);
  7892.                 textIndex += 1;
  7893.             }
  7894.         }
  7895.         return ret;
  7896.     }
  7897.     function traverseStack(args) {
  7898.         if (!args || !args.callee || !args.callee.name) {
  7899.             return [null, "", ""];
  7900.         }
  7901.         var funstr = args.callee.toString();
  7902.         var funcname = args.callee.name;
  7903.         var str = "(";
  7904.         var first = true;
  7905.         for (var i in args) {
  7906.             var a = args[i];
  7907.             if (!first) {
  7908.                 str += ", ";
  7909.             }
  7910.             first = false;
  7911.             if (typeof a === "number" || typeof a === "string") {
  7912.                 str += a;
  7913.             } else {
  7914.                 str += "(" + typeof a + ")";
  7915.             }
  7916.         }
  7917.         str += ")";
  7918.         var caller = args.callee.caller;
  7919.         args = caller ? caller.arguments : [];
  7920.         if (first) str = "";
  7921.         return [args, funcname, str];
  7922.     }
  7923.     function _emscripten_get_callstack_js(flags) {
  7924.         var callstack = jsStackTrace();
  7925.         var iThisFunc = callstack.lastIndexOf("_emscripten_log");
  7926.         var iThisFunc2 = callstack.lastIndexOf("_emscripten_get_callstack");
  7927.         var iNextLine = callstack.indexOf("\n", Math.max(iThisFunc, iThisFunc2)) + 1;
  7928.         callstack = callstack.slice(iNextLine);
  7929.         if (flags & 32) {
  7930.             warnOnce("EM_LOG_DEMANGLE is deprecated; ignoring");
  7931.         }
  7932.         if (flags & 8 && typeof emscripten_source_map === "undefined") {
  7933.             warnOnce('Source map information is not available, emscripten_log with EM_LOG_C_STACK will be ignored. Build with "--pre-js $EMSCRIPTEN/src/emscripten-source-map.min.js" linker flag to add source map loading to code.');
  7934.             flags ^= 8;
  7935.             flags |= 16;
  7936.         }
  7937.         var stack_args = null;
  7938.         if (flags & 128) {
  7939.             stack_args = traverseStack(arguments);
  7940.             while (stack_args[1].includes("_emscripten_")) stack_args = traverseStack(stack_args[0]);
  7941.         }
  7942.         var lines = callstack.split("\n");
  7943.         callstack = "";
  7944.         var newFirefoxRe = new RegExp("\\s*(.*?)@(.*?):([0-9]+):([0-9]+)");
  7945.         var firefoxRe = new RegExp("\\s*(.*?)@(.*):(.*)(:(.*))?");
  7946.         var chromeRe = new RegExp("\\s*at (.*?) \\((.*):(.*):(.*)\\)");
  7947.         for (var l in lines) {
  7948.             var line = lines[l];
  7949.             var symbolName = "";
  7950.             var file = "";
  7951.             var lineno = 0;
  7952.             var column = 0;
  7953.             var parts = chromeRe.exec(line);
  7954.             if (parts && parts.length == 5) {
  7955.                 symbolName = parts[1];
  7956.                 file = parts[2];
  7957.                 lineno = parts[3];
  7958.                 column = parts[4];
  7959.             } else {
  7960.                 parts = newFirefoxRe.exec(line);
  7961.                 if (!parts) parts = firefoxRe.exec(line);
  7962.                 if (parts && parts.length >= 4) {
  7963.                     symbolName = parts[1];
  7964.                     file = parts[2];
  7965.                     lineno = parts[3];
  7966.                     column = parts[4] | 0;
  7967.                 } else {
  7968.                     callstack += line + "\n";
  7969.                     continue;
  7970.                 }
  7971.             }
  7972.             var haveSourceMap = false;
  7973.             if (flags & 8) {
  7974.                 var orig = emscripten_source_map.originalPositionFor({ line: lineno, column: column });
  7975.                 haveSourceMap = orig && orig.source;
  7976.                 if (haveSourceMap) {
  7977.                     if (flags & 64) {
  7978.                         orig.source = orig.source.substring(orig.source.replace(/\\/g, "/").lastIndexOf("/") + 1);
  7979.                     }
  7980.                     callstack += "    at " + symbolName + " (" + orig.source + ":" + orig.line + ":" + orig.column + ")\n";
  7981.                 }
  7982.             }
  7983.             if (flags & 16 || !haveSourceMap) {
  7984.                 if (flags & 64) {
  7985.                     file = file.substring(file.replace(/\\/g, "/").lastIndexOf("/") + 1);
  7986.                 }
  7987.                 callstack += (haveSourceMap ? "     = " + symbolName : "    at " + symbolName) + " (" + file + ":" + lineno + ":" + column + ")\n";
  7988.             }
  7989.             if (flags & 128 && stack_args[0]) {
  7990.                 if (stack_args[1] == symbolName && stack_args[2].length > 0) {
  7991.                     callstack = callstack.replace(/\s+$/, "");
  7992.                     callstack += " with values: " + stack_args[1] + stack_args[2] + "\n";
  7993.                 }
  7994.                 stack_args = traverseStack(stack_args[0]);
  7995.             }
  7996.         }
  7997.         callstack = callstack.replace(/\s+$/, "");
  7998.         return callstack;
  7999.     }
  8000.     function _emscripten_log_js(flags, str) {
  8001.         if (flags & 24) {
  8002.             str = str.replace(/\s+$/, "");
  8003.             str += (str.length > 0 ? "\n" : "") + _emscripten_get_callstack_js(flags);
  8004.         }
  8005.         if (flags & 1) {
  8006.             if (flags & 4) {
  8007.                 console.error(str);
  8008.             } else if (flags & 2) {
  8009.                 console.warn(str);
  8010.             } else if (flags & 512) {
  8011.                 console.info(str);
  8012.             } else if (flags & 256) {
  8013.                 console.debug(str);
  8014.             } else {
  8015.                 console.log(str);
  8016.             }
  8017.         } else if (flags & 6) {
  8018.             err(str);
  8019.         } else {
  8020.             out(str);
  8021.         }
  8022.     }
  8023.     function _emscripten_log(flags, format, varargs) {
  8024.         var result = formatString(format, varargs);
  8025.         var str = UTF8ArrayToString(result, 0);
  8026.         _emscripten_log_js(flags, str);
  8027.     }
  8028.     function _longjmp(env, value) {
  8029.         _setThrew(env, value || 1);
  8030.         throw "longjmp";
  8031.     }
  8032.     function _emscripten_longjmp(a0, a1) {
  8033.         return _longjmp(a0, a1);
  8034.     }
  8035.     function _emscripten_memcpy_big(dest, src, num) {
  8036.         HEAPU8.copyWithin(dest, src, src + num);
  8037.     }
  8038.     function doRequestFullscreen(target, strategy) {
  8039.         if (!JSEvents.fullscreenEnabled()) return -1;
  8040.         target = findEventTarget(target);
  8041.         if (!target) return -4;
  8042.         if (!target.requestFullscreen && !target.webkitRequestFullscreen) {
  8043.             return -3;
  8044.         }
  8045.         var canPerformRequests = JSEvents.canPerformEventHandlerRequests();
  8046.         if (!canPerformRequests) {
  8047.             if (strategy.deferUntilInEventHandler) {
  8048.                 JSEvents.deferCall(_JSEvents_requestFullscreen, 1, [target, strategy]);
  8049.                 return 1;
  8050.             } else {
  8051.                 return -2;
  8052.             }
  8053.         }
  8054.         return _JSEvents_requestFullscreen(target, strategy);
  8055.     }
  8056.     function _emscripten_request_fullscreen(target, deferUntilInEventHandler) {
  8057.         var strategy = { scaleMode: 0, canvasResolutionScaleMode: 0, filteringMode: 0, deferUntilInEventHandler: deferUntilInEventHandler, canvasResizedCallbackTargetThread: 2 };
  8058.         return doRequestFullscreen(target, strategy);
  8059.     }
  8060.     function _emscripten_request_pointerlock(target, deferUntilInEventHandler) {
  8061.         target = findEventTarget(target);
  8062.         if (!target) return -4;
  8063.         if (!target.requestPointerLock && !target.msRequestPointerLock) {
  8064.             return -1;
  8065.         }
  8066.         var canPerformRequests = JSEvents.canPerformEventHandlerRequests();
  8067.         if (!canPerformRequests) {
  8068.             if (deferUntilInEventHandler) {
  8069.                 JSEvents.deferCall(requestPointerLock, 2, [target]);
  8070.                 return 1;
  8071.             } else {
  8072.                 return -2;
  8073.             }
  8074.         }
  8075.         return requestPointerLock(target);
  8076.     }
  8077.     function emscripten_realloc_buffer(size) {
  8078.         try {
  8079.             wasmMemory.grow((size - buffer.byteLength + 65535) >>> 16);
  8080.             updateGlobalBufferAndViews(wasmMemory.buffer);
  8081.             return 1;
  8082.         } catch (e) {}
  8083.     }
  8084.     function _emscripten_resize_heap(requestedSize) {
  8085.         var oldSize = HEAPU8.length;
  8086.         requestedSize = requestedSize >>> 0;
  8087.         var maxHeapSize = 2147483648;
  8088.         if (requestedSize > maxHeapSize) {
  8089.             return false;
  8090.         }
  8091.         for (var cutDown = 1; cutDown <= 4; cutDown *= 2) {
  8092.             var overGrownHeapSize = oldSize * (1 + 0.2 / cutDown);
  8093.             overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296);
  8094.             var newSize = Math.min(maxHeapSize, alignUp(Math.max(requestedSize, overGrownHeapSize), 65536));
  8095.             var replacement = emscripten_realloc_buffer(newSize);
  8096.             if (replacement) {
  8097.                 return true;
  8098.             }
  8099.         }
  8100.         return false;
  8101.     }
  8102.     function _emscripten_sample_gamepad_data() {
  8103.         return (JSEvents.lastGamepadState = navigator.getGamepads ? navigator.getGamepads() : navigator.webkitGetGamepads ? navigator.webkitGetGamepads() : null) ? 0 : -1;
  8104.     }
  8105.     function registerFocusEventCallback(target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) {
  8106.         if (!JSEvents.focusEvent) JSEvents.focusEvent = _malloc(256);
  8107.         var focusEventHandlerFunc = function (ev) {
  8108.             var e = ev || event;
  8109.             var nodeName = JSEvents.getNodeNameForTarget(e.target);
  8110.             var id = e.target.id ? e.target.id : "";
  8111.             var focusEvent = JSEvents.focusEvent;
  8112.             stringToUTF8(nodeName, focusEvent + 0, 128);
  8113.             stringToUTF8(id, focusEvent + 128, 128);
  8114.             if (
  8115.                 (function (a1, a2, a3) {
  8116.                     return dynCall_iiii.apply(null, [callbackfunc, a1, a2, a3]);
  8117.                 })(eventTypeId, focusEvent, userData)
  8118.             )
  8119.                 e.preventDefault();
  8120.         };
  8121.         var eventHandler = { target: findEventTarget(target), eventTypeString: eventTypeString, callbackfunc: callbackfunc, handlerFunc: focusEventHandlerFunc, useCapture: useCapture };
  8122.         JSEvents.registerOrRemoveHandler(eventHandler);
  8123.     }
  8124.     function _emscripten_set_blur_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
  8125.         registerFocusEventCallback(target, userData, useCapture, callbackfunc, 12, "blur", targetThread);
  8126.         return 0;
  8127.     }
  8128.     function _emscripten_set_focus_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
  8129.         registerFocusEventCallback(target, userData, useCapture, callbackfunc, 13, "focus", targetThread);
  8130.         return 0;
  8131.     }
  8132.     function registerFullscreenChangeEventCallback(target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) {
  8133.         if (!JSEvents.fullscreenChangeEvent) JSEvents.fullscreenChangeEvent = _malloc(280);
  8134.         var fullscreenChangeEventhandlerFunc = function (ev) {
  8135.             var e = ev || event;
  8136.             var fullscreenChangeEvent = JSEvents.fullscreenChangeEvent;
  8137.             fillFullscreenChangeEventData(fullscreenChangeEvent);
  8138.             if (
  8139.                 (function (a1, a2, a3) {
  8140.                     return dynCall_iiii.apply(null, [callbackfunc, a1, a2, a3]);
  8141.                 })(eventTypeId, fullscreenChangeEvent, userData)
  8142.             )
  8143.                 e.preventDefault();
  8144.         };
  8145.         var eventHandler = { target: target, eventTypeString: eventTypeString, callbackfunc: callbackfunc, handlerFunc: fullscreenChangeEventhandlerFunc, useCapture: useCapture };
  8146.         JSEvents.registerOrRemoveHandler(eventHandler);
  8147.     }
  8148.     function _emscripten_set_fullscreenchange_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
  8149.         if (!JSEvents.fullscreenEnabled()) return -1;
  8150.         target = findEventTarget(target);
  8151.         if (!target) return -4;
  8152.         registerFullscreenChangeEventCallback(target, userData, useCapture, callbackfunc, 19, "fullscreenchange", targetThread);
  8153.         registerFullscreenChangeEventCallback(target, userData, useCapture, callbackfunc, 19, "webkitfullscreenchange", targetThread);
  8154.         return 0;
  8155.     }
  8156.     function registerGamepadEventCallback(target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) {
  8157.         if (!JSEvents.gamepadEvent) JSEvents.gamepadEvent = _malloc(1432);
  8158.         var gamepadEventHandlerFunc = function (ev) {
  8159.             var e = ev || event;
  8160.             var gamepadEvent = JSEvents.gamepadEvent;
  8161.             fillGamepadEventData(gamepadEvent, e["gamepad"]);
  8162.             if (
  8163.                 (function (a1, a2, a3) {
  8164.                     return dynCall_iiii.apply(null, [callbackfunc, a1, a2, a3]);
  8165.                 })(eventTypeId, gamepadEvent, userData)
  8166.             )
  8167.                 e.preventDefault();
  8168.         };
  8169.         var eventHandler = { target: findEventTarget(target), allowsDeferredCalls: true, eventTypeString: eventTypeString, callbackfunc: callbackfunc, handlerFunc: gamepadEventHandlerFunc, useCapture: useCapture };
  8170.         JSEvents.registerOrRemoveHandler(eventHandler);
  8171.     }
  8172.     function _emscripten_set_gamepadconnected_callback_on_thread(userData, useCapture, callbackfunc, targetThread) {
  8173.         if (!navigator.getGamepads && !navigator.webkitGetGamepads) return -1;
  8174.         registerGamepadEventCallback(2, userData, useCapture, callbackfunc, 26, "gamepadconnected", targetThread);
  8175.         return 0;
  8176.     }
  8177.     function _emscripten_set_gamepaddisconnected_callback_on_thread(userData, useCapture, callbackfunc, targetThread) {
  8178.         if (!navigator.getGamepads && !navigator.webkitGetGamepads) return -1;
  8179.         registerGamepadEventCallback(2, userData, useCapture, callbackfunc, 27, "gamepaddisconnected", targetThread);
  8180.         return 0;
  8181.     }
  8182.     function _emscripten_set_interval(cb, msecs, userData) {
  8183.         return setInterval(function () {
  8184.             (function (a1) {
  8185.                 dynCall_vi.apply(null, [cb, a1]);
  8186.             })(userData);
  8187.         }, msecs);
  8188.     }
  8189.     function registerKeyEventCallback(target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) {
  8190.         if (!JSEvents.keyEvent) JSEvents.keyEvent = _malloc(164);
  8191.         var keyEventHandlerFunc = function (e) {
  8192.             var keyEventData = JSEvents.keyEvent;
  8193.             var idx = keyEventData >> 2;
  8194.             HEAP32[idx + 0] = e.location;
  8195.             HEAP32[idx + 1] = e.ctrlKey;
  8196.             HEAP32[idx + 2] = e.shiftKey;
  8197.             HEAP32[idx + 3] = e.altKey;
  8198.             HEAP32[idx + 4] = e.metaKey;
  8199.             HEAP32[idx + 5] = e.repeat;
  8200.             HEAP32[idx + 6] = e.charCode;
  8201.             HEAP32[idx + 7] = e.keyCode;
  8202.             HEAP32[idx + 8] = e.which;
  8203.             stringToUTF8(e.key || "", keyEventData + 36, 32);
  8204.             stringToUTF8(e.code || "", keyEventData + 68, 32);
  8205.             stringToUTF8(e.char || "", keyEventData + 100, 32);
  8206.             stringToUTF8(e.locale || "", keyEventData + 132, 32);
  8207.             if (
  8208.                 (function (a1, a2, a3) {
  8209.                     return dynCall_iiii.apply(null, [callbackfunc, a1, a2, a3]);
  8210.                 })(eventTypeId, keyEventData, userData)
  8211.             )
  8212.                 e.preventDefault();
  8213.         };
  8214.         var eventHandler = { target: findEventTarget(target), allowsDeferredCalls: true, eventTypeString: eventTypeString, callbackfunc: callbackfunc, handlerFunc: keyEventHandlerFunc, useCapture: useCapture };
  8215.         JSEvents.registerOrRemoveHandler(eventHandler);
  8216.     }
  8217.     function _emscripten_set_keydown_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
  8218.         registerKeyEventCallback(target, userData, useCapture, callbackfunc, 2, "keydown", targetThread);
  8219.         return 0;
  8220.     }
  8221.     function _emscripten_set_keypress_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
  8222.         registerKeyEventCallback(target, userData, useCapture, callbackfunc, 1, "keypress", targetThread);
  8223.         return 0;
  8224.     }
  8225.     function _emscripten_set_keyup_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
  8226.         registerKeyEventCallback(target, userData, useCapture, callbackfunc, 3, "keyup", targetThread);
  8227.         return 0;
  8228.     }
  8229.     function _emscripten_set_main_loop(func, fps, simulateInfiniteLoop) {
  8230.         console.log("_emscripten_set_main_loop fps: " + fps);
  8231.         var browserIterationFunc = function () {
  8232.             dynCall_v.call(null, func);
  8233.         };
  8234.         setMainLoop(browserIterationFunc, fps, simulateInfiniteLoop);
  8235.     }
  8236.     function fillMouseEventData(eventStruct, e, target) {
  8237.         var idx = eventStruct >> 2;
  8238.         HEAP32[idx + 0] = e.screenX;
  8239.         HEAP32[idx + 1] = e.screenY;
  8240.         HEAP32[idx + 2] = e.clientX;
  8241.         HEAP32[idx + 3] = e.clientY;
  8242.         HEAP32[idx + 4] = e.ctrlKey;
  8243.         HEAP32[idx + 5] = e.shiftKey;
  8244.         HEAP32[idx + 6] = e.altKey;
  8245.         HEAP32[idx + 7] = e.metaKey;
  8246.         HEAP16[idx * 2 + 16] = e.button;
  8247.         HEAP16[idx * 2 + 17] = e.buttons;
  8248.         HEAP32[idx + 9] = e["movementX"];
  8249.         HEAP32[idx + 10] = e["movementY"];
  8250.         var rect = getBoundingClientRect(target);
  8251.         HEAP32[idx + 11] = e.clientX - rect.left;
  8252.         HEAP32[idx + 12] = e.clientY - rect.top;
  8253.     }
  8254.     function registerMouseEventCallback(target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) {
  8255.         if (!JSEvents.mouseEvent) JSEvents.mouseEvent = _malloc(64);
  8256.         target = findEventTarget(target);
  8257.         var mouseEventHandlerFunc = function (ev) {
  8258.             var e = ev || event;
  8259.             fillMouseEventData(JSEvents.mouseEvent, e, target);
  8260.             if (
  8261.                 (function (a1, a2, a3) {
  8262.                     return dynCall_iiii.apply(null, [callbackfunc, a1, a2, a3]);
  8263.                 })(eventTypeId, JSEvents.mouseEvent, userData)
  8264.             )
  8265.                 e.preventDefault();
  8266.         };
  8267.         var eventHandler = {
  8268.             target: target,
  8269.             allowsDeferredCalls: eventTypeString != "mousemove" && eventTypeString != "mouseenter" && eventTypeString != "mouseleave",
  8270.             eventTypeString: eventTypeString,
  8271.             callbackfunc: callbackfunc,
  8272.             handlerFunc: mouseEventHandlerFunc,
  8273.             useCapture: useCapture,
  8274.         };
  8275.         JSEvents.registerOrRemoveHandler(eventHandler);
  8276.     }
  8277.     function _emscripten_set_mousedown_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
  8278.         registerMouseEventCallback(target, userData, useCapture, callbackfunc, 5, "mousedown", targetThread);
  8279.         return 0;
  8280.     }
  8281.     function _emscripten_set_mousemove_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
  8282.         registerMouseEventCallback(target, userData, useCapture, callbackfunc, 8, "mousemove", targetThread);
  8283.         return 0;
  8284.     }
  8285.     function _emscripten_set_mouseup_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
  8286.         registerMouseEventCallback(target, userData, useCapture, callbackfunc, 6, "mouseup", targetThread);
  8287.         return 0;
  8288.     }
  8289.     function registerTouchEventCallback(target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) {
  8290.         if (!JSEvents.touchEvent) JSEvents.touchEvent = _malloc(1684);
  8291.         target = findEventTarget(target);
  8292.         var touchEventHandlerFunc = function (e) {
  8293.             var t,
  8294.                 touches = {},
  8295.                 et = e.touches;
  8296.             for (var i = 0; i < et.length; ++i) {
  8297.                 t = et[i];
  8298.                 t.isChanged = t.onTarget = 0;
  8299.                 touches[t.identifier] = t;
  8300.             }
  8301.             for (var i = 0; i < e.changedTouches.length; ++i) {
  8302.                 t = e.changedTouches[i];
  8303.                 t.isChanged = 1;
  8304.                 touches[t.identifier] = t;
  8305.             }
  8306.             for (var i = 0; i < e.targetTouches.length; ++i) {
  8307.                 touches[e.targetTouches[i].identifier].onTarget = 1;
  8308.             }
  8309.             var touchEvent = JSEvents.touchEvent;
  8310.             var idx = touchEvent >> 2;
  8311.             HEAP32[idx + 1] = e.ctrlKey;
  8312.             HEAP32[idx + 2] = e.shiftKey;
  8313.             HEAP32[idx + 3] = e.altKey;
  8314.             HEAP32[idx + 4] = e.metaKey;
  8315.             idx += 5;
  8316.             var targetRect = getBoundingClientRect(target);
  8317.             var numTouches = 0;
  8318.             for (var i in touches) {
  8319.                 var t = touches[i];
  8320.                 HEAP32[idx + 0] = t.identifier;
  8321.                 HEAP32[idx + 1] = t.screenX;
  8322.                 HEAP32[idx + 2] = t.screenY;
  8323.                 HEAP32[idx + 3] = t.clientX;
  8324.                 HEAP32[idx + 4] = t.clientY;
  8325.                 HEAP32[idx + 5] = t.pageX;
  8326.                 HEAP32[idx + 6] = t.pageY;
  8327.                 HEAP32[idx + 7] = t.isChanged;
  8328.                 HEAP32[idx + 8] = t.onTarget;
  8329.                 HEAP32[idx + 9] = t.clientX - targetRect.left;
  8330.                 HEAP32[idx + 10] = t.clientY - targetRect.top;
  8331.                 idx += 13;
  8332.                 if (++numTouches > 31) {
  8333.                     break;
  8334.                 }
  8335.             }
  8336.             HEAP32[touchEvent >> 2] = numTouches;
  8337.             if (
  8338.                 (function (a1, a2, a3) {
  8339.                     return dynCall_iiii.apply(null, [callbackfunc, a1, a2, a3]);
  8340.                 })(eventTypeId, touchEvent, userData)
  8341.             )
  8342.                 e.preventDefault();
  8343.         };
  8344.         var eventHandler = {
  8345.             target: target,
  8346.             allowsDeferredCalls: eventTypeString == "touchstart" || eventTypeString == "touchend",
  8347.             eventTypeString: eventTypeString,
  8348.             callbackfunc: callbackfunc,
  8349.             handlerFunc: touchEventHandlerFunc,
  8350.             useCapture: useCapture,
  8351.         };
  8352.         JSEvents.registerOrRemoveHandler(eventHandler);
  8353.     }
  8354.     function _emscripten_set_touchcancel_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
  8355.         registerTouchEventCallback(target, userData, useCapture, callbackfunc, 25, "touchcancel", targetThread);
  8356.         return 0;
  8357.     }
  8358.     function _emscripten_set_touchend_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
  8359.         registerTouchEventCallback(target, userData, useCapture, callbackfunc, 23, "touchend", targetThread);
  8360.         return 0;
  8361.     }
  8362.     function _emscripten_set_touchmove_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
  8363.         registerTouchEventCallback(target, userData, useCapture, callbackfunc, 24, "touchmove", targetThread);
  8364.         return 0;
  8365.     }
  8366.     function _emscripten_set_touchstart_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
  8367.         registerTouchEventCallback(target, userData, useCapture, callbackfunc, 22, "touchstart", targetThread);
  8368.         return 0;
  8369.     }
  8370.     function registerWheelEventCallback(target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) {
  8371.         if (!JSEvents.wheelEvent) JSEvents.wheelEvent = _malloc(96);
  8372.         var wheelHandlerFunc = function (ev) {
  8373.             var e = ev || event;
  8374.             var wheelEvent = JSEvents.wheelEvent;
  8375.             fillMouseEventData(wheelEvent, e, target);
  8376.             HEAPF64[(wheelEvent + 64) >> 3] = e["deltaX"];
  8377.             HEAPF64[(wheelEvent + 72) >> 3] = e["deltaY"];
  8378.             HEAPF64[(wheelEvent + 80) >> 3] = e["deltaZ"];
  8379.             HEAP32[(wheelEvent + 88) >> 2] = e["deltaMode"];
  8380.             if (
  8381.                 (function (a1, a2, a3) {
  8382.                     return dynCall_iiii.apply(null, [callbackfunc, a1, a2, a3]);
  8383.                 })(eventTypeId, wheelEvent, userData)
  8384.             )
  8385.                 e.preventDefault();
  8386.         };
  8387.         var eventHandler = { target: target, allowsDeferredCalls: true, eventTypeString: eventTypeString, callbackfunc: callbackfunc, handlerFunc: wheelHandlerFunc, useCapture: useCapture };
  8388.         JSEvents.registerOrRemoveHandler(eventHandler);
  8389.     }
  8390.     function _emscripten_set_wheel_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
  8391.         target = findEventTarget(target);
  8392.         if (typeof target.onwheel !== "undefined") {
  8393.             registerWheelEventCallback(target, userData, useCapture, callbackfunc, 9, "wheel", targetThread);
  8394.             return 0;
  8395.         } else {
  8396.             return -1;
  8397.         }
  8398.     }
  8399.     function _emscripten_thread_sleep(msecs) {
  8400.         var start = _emscripten_get_now();
  8401.         while (_emscripten_get_now() - start < msecs) {}
  8402.     }
  8403.     function __webgl_enable_ANGLE_instanced_arrays(ctx) {
  8404.         var ext = ctx.getExtension("ANGLE_instanced_arrays");
  8405.         if (ext) {
  8406.             ctx["vertexAttribDivisor"] = function (index, divisor) {
  8407.                 ext["vertexAttribDivisorANGLE"](index, divisor);
  8408.             };
  8409.             ctx["drawArraysInstanced"] = function (mode, first, count, primcount) {
  8410.                 ext["drawArraysInstancedANGLE"](mode, first, count, primcount);
  8411.             };
  8412.             ctx["drawElementsInstanced"] = function (mode, count, type, indices, primcount) {
  8413.                 ext["drawElementsInstancedANGLE"](mode, count, type, indices, primcount);
  8414.             };
  8415.             return 1;
  8416.         }
  8417.     }
  8418.     function __webgl_enable_OES_vertex_array_object(ctx) {
  8419.         var ext = ctx.getExtension("OES_vertex_array_object");
  8420.         if (ext) {
  8421.             ctx["createVertexArray"] = function () {
  8422.                 return ext["createVertexArrayOES"]();
  8423.             };
  8424.             ctx["deleteVertexArray"] = function (vao) {
  8425.                 ext["deleteVertexArrayOES"](vao);
  8426.             };
  8427.             ctx["bindVertexArray"] = function (vao) {
  8428.                 ext["bindVertexArrayOES"](vao);
  8429.             };
  8430.             ctx["isVertexArray"] = function (vao) {
  8431.                 return ext["isVertexArrayOES"](vao);
  8432.             };
  8433.             return 1;
  8434.         }
  8435.     }
  8436.     function __webgl_enable_WEBGL_draw_buffers(ctx) {
  8437.         var ext = ctx.getExtension("WEBGL_draw_buffers");
  8438.         if (ext) {
  8439.             ctx["drawBuffers"] = function (n, bufs) {
  8440.                 ext["drawBuffersWEBGL"](n, bufs);
  8441.             };
  8442.             return 1;
  8443.         }
  8444.     }
  8445.     function __webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(ctx) {
  8446.         return !!(ctx.dibvbi = ctx.getExtension("WEBGL_draw_instanced_base_vertex_base_instance"));
  8447.     }
  8448.     function __webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance(ctx) {
  8449.         return !!(ctx.mdibvbi = ctx.getExtension("WEBGL_multi_draw_instanced_base_vertex_base_instance"));
  8450.     }
  8451.     function __webgl_enable_WEBGL_multi_draw(ctx) {
  8452.         return !!(ctx.multiDrawWebgl = ctx.getExtension("WEBGL_multi_draw"));
  8453.     }
  8454.     var GL = {
  8455.         counter: 1,
  8456.         buffers: [],
  8457.         mappedBuffers: {},
  8458.         programs: [],
  8459.         framebuffers: [],
  8460.         renderbuffers: [],
  8461.         textures: [],
  8462.         shaders: [],
  8463.         vaos: [],
  8464.         contexts: [],
  8465.         offscreenCanvases: {},
  8466.         queries: [],
  8467.         samplers: [],
  8468.         transformFeedbacks: [],
  8469.         syncs: [],
  8470.         byteSizeByTypeRoot: 5120,
  8471.         byteSizeByType: [1, 1, 2, 2, 4, 4, 4, 2, 3, 4, 8],
  8472.         stringCache: {},
  8473.         stringiCache: {},
  8474.         unpackAlignment: 4,
  8475.         recordError: function recordError(errorCode) {
  8476.             if (!GL.lastError) {
  8477.                 GL.lastError = errorCode;
  8478.             }
  8479.         },
  8480.         getNewId: function (table) {
  8481.             var ret = GL.counter++;
  8482.             for (var i = table.length; i < ret; i++) {
  8483.                 table[i] = null;
  8484.             }
  8485.             return ret;
  8486.         },
  8487.         MAX_TEMP_BUFFER_SIZE: 2097152,
  8488.         numTempVertexBuffersPerSize: 64,
  8489.         log2ceilLookup: function (i) {
  8490.             return 32 - Math.clz32(i === 0 ? 0 : i - 1);
  8491.         },
  8492.         generateTempBuffers: function (quads, context) {
  8493.             var largestIndex = GL.log2ceilLookup(GL.MAX_TEMP_BUFFER_SIZE);
  8494.             context.tempVertexBufferCounters1 = [];
  8495.             context.tempVertexBufferCounters2 = [];
  8496.             context.tempVertexBufferCounters1.length = context.tempVertexBufferCounters2.length = largestIndex + 1;
  8497.             context.tempVertexBuffers1 = [];
  8498.             context.tempVertexBuffers2 = [];
  8499.             context.tempVertexBuffers1.length = context.tempVertexBuffers2.length = largestIndex + 1;
  8500.             context.tempIndexBuffers = [];
  8501.             context.tempIndexBuffers.length = largestIndex + 1;
  8502.             for (var i = 0; i <= largestIndex; ++i) {
  8503.                 context.tempIndexBuffers[i] = null;
  8504.                 context.tempVertexBufferCounters1[i] = context.tempVertexBufferCounters2[i] = 0;
  8505.                 var ringbufferLength = GL.numTempVertexBuffersPerSize;
  8506.                 context.tempVertexBuffers1[i] = [];
  8507.                 context.tempVertexBuffers2[i] = [];
  8508.                 var ringbuffer1 = context.tempVertexBuffers1[i];
  8509.                 var ringbuffer2 = context.tempVertexBuffers2[i];
  8510.                 ringbuffer1.length = ringbuffer2.length = ringbufferLength;
  8511.                 for (var j = 0; j < ringbufferLength; ++j) {
  8512.                     ringbuffer1[j] = ringbuffer2[j] = null;
  8513.                 }
  8514.             }
  8515.             if (quads) {
  8516.                 context.tempQuadIndexBuffer = GLctx.createBuffer();
  8517.                 context.GLctx.bindBuffer(34963, context.tempQuadIndexBuffer);
  8518.                 var numIndexes = GL.MAX_TEMP_BUFFER_SIZE >> 1;
  8519.                 var quadIndexes = new Uint16Array(numIndexes);
  8520.                 var i = 0,
  8521.                     v = 0;
  8522.                 while (1) {
  8523.                     quadIndexes[i++] = v;
  8524.                     if (i >= numIndexes) break;
  8525.                     quadIndexes[i++] = v + 1;
  8526.                     if (i >= numIndexes) break;
  8527.                     quadIndexes[i++] = v + 2;
  8528.                     if (i >= numIndexes) break;
  8529.                     quadIndexes[i++] = v;
  8530.                     if (i >= numIndexes) break;
  8531.                     quadIndexes[i++] = v + 2;
  8532.                     if (i >= numIndexes) break;
  8533.                     quadIndexes[i++] = v + 3;
  8534.                     if (i >= numIndexes) break;
  8535.                     v += 4;
  8536.                 }
  8537.                 context.GLctx.bufferData(34963, quadIndexes, 35044);
  8538.                 context.GLctx.bindBuffer(34963, null);
  8539.             }
  8540.         },
  8541.         getTempVertexBuffer: function getTempVertexBuffer(sizeBytes) {
  8542.             var idx = GL.log2ceilLookup(sizeBytes);
  8543.             var ringbuffer = GL.currentContext.tempVertexBuffers1[idx];
  8544.             var nextFreeBufferIndex = GL.currentContext.tempVertexBufferCounters1[idx];
  8545.             GL.currentContext.tempVertexBufferCounters1[idx] = (GL.currentContext.tempVertexBufferCounters1[idx] + 1) & (GL.numTempVertexBuffersPerSize - 1);
  8546.             var vbo = ringbuffer[nextFreeBufferIndex];
  8547.             if (vbo) {
  8548.                 return vbo;
  8549.             }
  8550.             var prevVBO = GLctx.getParameter(34964);
  8551.             ringbuffer[nextFreeBufferIndex] = GLctx.createBuffer();
  8552.             GLctx.bindBuffer(34962, ringbuffer[nextFreeBufferIndex]);
  8553.             GLctx.bufferData(34962, 1 << idx, 35048);
  8554.             GLctx.bindBuffer(34962, prevVBO);
  8555.             return ringbuffer[nextFreeBufferIndex];
  8556.         },
  8557.         getTempIndexBuffer: function getTempIndexBuffer(sizeBytes) {
  8558.             var idx = GL.log2ceilLookup(sizeBytes);
  8559.             var ibo = GL.currentContext.tempIndexBuffers[idx];
  8560.             if (ibo) {
  8561.                 return ibo;
  8562.             }
  8563.             var prevIBO = GLctx.getParameter(34965);
  8564.             GL.currentContext.tempIndexBuffers[idx] = GLctx.createBuffer();
  8565.             GLctx.bindBuffer(34963, GL.currentContext.tempIndexBuffers[idx]);
  8566.             GLctx.bufferData(34963, 1 << idx, 35048);
  8567.             GLctx.bindBuffer(34963, prevIBO);
  8568.             return GL.currentContext.tempIndexBuffers[idx];
  8569.         },
  8570.         newRenderingFrameStarted: function newRenderingFrameStarted() {
  8571.             if (!GL.currentContext) {
  8572.                 return;
  8573.             }
  8574.             var vb = GL.currentContext.tempVertexBuffers1;
  8575.             GL.currentContext.tempVertexBuffers1 = GL.currentContext.tempVertexBuffers2;
  8576.             GL.currentContext.tempVertexBuffers2 = vb;
  8577.             vb = GL.currentContext.tempVertexBufferCounters1;
  8578.             GL.currentContext.tempVertexBufferCounters1 = GL.currentContext.tempVertexBufferCounters2;
  8579.             GL.currentContext.tempVertexBufferCounters2 = vb;
  8580.             var largestIndex = GL.log2ceilLookup(GL.MAX_TEMP_BUFFER_SIZE);
  8581.             for (var i = 0; i <= largestIndex; ++i) {
  8582.                 GL.currentContext.tempVertexBufferCounters1[i] = 0;
  8583.             }
  8584.         },
  8585.         getSource: function (shader, count, string, length) {
  8586.             var source = "";
  8587.             for (var i = 0; i < count; ++i) {
  8588.                 var len = length ? HEAP32[(length + i * 4) >> 2] : -1;
  8589.                 source += UTF8ToString(HEAP32[(string + i * 4) >> 2], len < 0 ? undefined : len);
  8590.             }
  8591.             return source;
  8592.         },
  8593.         calcBufLength: function calcBufLength(size, type, stride, count) {
  8594.             if (stride > 0) {
  8595.                 return count * stride;
  8596.             }
  8597.             var typeSize = GL.byteSizeByType[type - GL.byteSizeByTypeRoot];
  8598.             return size * typeSize * count;
  8599.         },
  8600.         usedTempBuffers: [],
  8601.         preDrawHandleClientVertexAttribBindings: function preDrawHandleClientVertexAttribBindings(count) {
  8602.             GL.resetBufferBinding = false;
  8603.             for (var i = 0; i < GL.currentContext.maxVertexAttribs; ++i) {
  8604.                 var cb = GL.currentContext.clientBuffers[i];
  8605.                 if (!cb.clientside || !cb.enabled) continue;
  8606.                 GL.resetBufferBinding = true;
  8607.                 var size = GL.calcBufLength(cb.size, cb.type, cb.stride, count);
  8608.                 var buf = GL.getTempVertexBuffer(size);
  8609.                 GLctx.bindBuffer(34962, buf);
  8610.                 GLctx.bufferSubData(34962, 0, HEAPU8.subarray(cb.ptr, cb.ptr + size));
  8611.                 cb.vertexAttribPointerAdaptor.call(GLctx, i, cb.size, cb.type, cb.normalized, cb.stride, 0);
  8612.             }
  8613.         },
  8614.         postDrawHandleClientVertexAttribBindings: function postDrawHandleClientVertexAttribBindings() {
  8615.             if (GL.resetBufferBinding) {
  8616.                 GLctx.bindBuffer(34962, GL.buffers[GLctx.currentArrayBufferBinding]);
  8617.             }
  8618.         },
  8619.         createContext: function (canvas, webGLContextAttributes) {
  8620.             if (!canvas.getContextSafariWebGL2Fixed) {
  8621.                 canvas.getContextSafariWebGL2Fixed = canvas.getContext;
  8622.                 canvas.getContext = function (ver, attrs) {
  8623.                     var gl = canvas.getContextSafariWebGL2Fixed(ver, attrs);
  8624.                     return (ver == "webgl") == gl instanceof WebGLRenderingContext ? gl : null;
  8625.                 };
  8626.             }
  8627.             var ctx = webGLContextAttributes.majorVersion > 1 ? canvas.getContext("webgl2", webGLContextAttributes) : canvas.getContext("webgl", webGLContextAttributes);
  8628.             if (!ctx) return 0;
  8629.             var handle = GL.registerContext(ctx, webGLContextAttributes);
  8630.             return handle;
  8631.         },
  8632.         registerContext: function (ctx, webGLContextAttributes) {
  8633.             var handle = GL.getNewId(GL.contexts);
  8634.             var context = { handle: handle, attributes: webGLContextAttributes, version: webGLContextAttributes.majorVersion, GLctx: ctx };
  8635.             if (ctx.canvas) ctx.canvas.GLctxObject = context;
  8636.             GL.contexts[handle] = context;
  8637.             if (typeof webGLContextAttributes.enableExtensionsByDefault === "undefined" || webGLContextAttributes.enableExtensionsByDefault) {
  8638.                 GL.initExtensions(context);
  8639.             }
  8640.             context.maxVertexAttribs = context.GLctx.getParameter(34921);
  8641.             context.clientBuffers = [];
  8642.             for (var i = 0; i < context.maxVertexAttribs; i++) {
  8643.                 context.clientBuffers[i] = { enabled: false, clientside: false, size: 0, type: 0, normalized: 0, stride: 0, ptr: 0, vertexAttribPointerAdaptor: null };
  8644.             }
  8645.             GL.generateTempBuffers(false, context);
  8646.             return handle;
  8647.         },
  8648.         makeContextCurrent: function (contextHandle) {
  8649.             GL.currentContext = GL.contexts[contextHandle];
  8650.             Module.ctx = GLctx = GL.currentContext && GL.currentContext.GLctx;
  8651.             return !(contextHandle && !GLctx);
  8652.         },
  8653.         getContext: function (contextHandle) {
  8654.             return GL.contexts[contextHandle];
  8655.         },
  8656.         deleteContext: function (contextHandle) {
  8657.             if (GL.currentContext === GL.contexts[contextHandle]) GL.currentContext = null;
  8658.             if (typeof JSEvents === "object") JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas);
  8659.             if (GL.contexts[contextHandle] && GL.contexts[contextHandle].GLctx.canvas) GL.contexts[contextHandle].GLctx.canvas.GLctxObject = undefined;
  8660.             GL.contexts[contextHandle] = null;
  8661.         },
  8662.         initExtensions: function (context) {
  8663.             if (!context) context = GL.currentContext;
  8664.             if (context.initExtensionsDone) return;
  8665.             context.initExtensionsDone = true;
  8666.             var GLctx = context.GLctx;
  8667.             __webgl_enable_ANGLE_instanced_arrays(GLctx);
  8668.             __webgl_enable_OES_vertex_array_object(GLctx);
  8669.             __webgl_enable_WEBGL_draw_buffers(GLctx);
  8670.             __webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(GLctx);
  8671.             __webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance(GLctx);
  8672.             if (context.version >= 2) {
  8673.                 GLctx.disjointTimerQueryExt = GLctx.getExtension("EXT_disjoint_timer_query_webgl2");
  8674.             }
  8675.             if (context.version < 2 || !GLctx.disjointTimerQueryExt) {
  8676.                 GLctx.disjointTimerQueryExt = GLctx.getExtension("EXT_disjoint_timer_query");
  8677.             }
  8678.             __webgl_enable_WEBGL_multi_draw(GLctx);
  8679.             var exts = GLctx.getSupportedExtensions() || [];
  8680.             exts.forEach(function (ext) {
  8681.                 if (!ext.includes("lose_context") && !ext.includes("debug")) {
  8682.                     GLctx.getExtension(ext);
  8683.                 }
  8684.             });
  8685.         },
  8686.     };
  8687.     var __emscripten_webgl_power_preferences = ["default", "low-power", "high-performance"];
  8688.     function _emscripten_webgl_do_create_context(target, attributes) {
  8689.         var a = attributes >> 2;
  8690.         var powerPreference = HEAP32[a + (24 >> 2)];
  8691.         var contextAttributes = {
  8692.             alpha: !!HEAP32[a + (0 >> 2)],
  8693.             depth: !!HEAP32[a + (4 >> 2)],
  8694.             stencil: !!HEAP32[a + (8 >> 2)],
  8695.             antialias: !!HEAP32[a + (12 >> 2)],
  8696.             premultipliedAlpha: !!HEAP32[a + (16 >> 2)],
  8697.             preserveDrawingBuffer: !!HEAP32[a + (20 >> 2)],
  8698.             powerPreference: __emscripten_webgl_power_preferences[powerPreference],
  8699.             failIfMajorPerformanceCaveat: !!HEAP32[a + (28 >> 2)],
  8700.             majorVersion: HEAP32[a + (32 >> 2)],
  8701.             minorVersion: HEAP32[a + (36 >> 2)],
  8702.             enableExtensionsByDefault: HEAP32[a + (40 >> 2)],
  8703.             explicitSwapControl: HEAP32[a + (44 >> 2)],
  8704.             proxyContextToMainThread: HEAP32[a + (48 >> 2)],
  8705.             renderViaOffscreenBackBuffer: HEAP32[a + (52 >> 2)],
  8706.         };
  8707.         var canvas = findCanvasEventTarget(target);
  8708.         if (!canvas) {
  8709.             return 0;
  8710.         }
  8711.         if (contextAttributes.explicitSwapControl) {
  8712.             return 0;
  8713.         }
  8714.         var contextHandle = GL.createContext(canvas, contextAttributes);
  8715.         return contextHandle;
  8716.     }
  8717.     function _emscripten_webgl_create_context(a0, a1) {
  8718.         return _emscripten_webgl_do_create_context(a0, a1);
  8719.     }
  8720.     function _emscripten_webgl_do_get_current_context() {
  8721.         return GL.currentContext ? GL.currentContext.handle : 0;
  8722.     }
  8723.     function _emscripten_webgl_get_current_context() {
  8724.         return _emscripten_webgl_do_get_current_context();
  8725.     }
  8726.     Module["_emscripten_webgl_get_current_context"] = _emscripten_webgl_get_current_context;
  8727.     function _emscripten_webgl_make_context_current(contextHandle) {
  8728.         var success = GL.makeContextCurrent(contextHandle);
  8729.         return success ? 0 : -5;
  8730.     }
  8731.     Module["_emscripten_webgl_make_context_current"] = _emscripten_webgl_make_context_current;
  8732.     function _emscripten_webgl_destroy_context(contextHandle) {
  8733.         if (GL.currentContext == contextHandle) GL.currentContext = 0;
  8734.         GL.deleteContext(contextHandle);
  8735.     }
  8736.     function _emscripten_webgl_enable_extension(contextHandle, extension) {
  8737.         var context = GL.getContext(contextHandle);
  8738.         var extString = UTF8ToString(extension);
  8739.         if (extString.startsWith("GL_")) extString = extString.substr(3);
  8740.         if (extString == "ANGLE_instanced_arrays") __webgl_enable_ANGLE_instanced_arrays(GLctx);
  8741.         if (extString == "OES_vertex_array_object") __webgl_enable_OES_vertex_array_object(GLctx);
  8742.         if (extString == "WEBGL_draw_buffers") __webgl_enable_WEBGL_draw_buffers(GLctx);
  8743.         if (extString == "WEBGL_draw_instanced_base_vertex_base_instance") __webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(GLctx);
  8744.         if (extString == "WEBGL_multi_draw_instanced_base_vertex_base_instance") __webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance(GLctx);
  8745.         if (extString == "WEBGL_multi_draw") __webgl_enable_WEBGL_multi_draw(GLctx);
  8746.         var ext = context.GLctx.getExtension(extString);
  8747.         return !!ext;
  8748.     }
  8749.     function _emscripten_webgl_init_context_attributes(attributes) {
  8750.         var a = attributes >> 2;
  8751.         for (var i = 0; i < 56 >> 2; ++i) {
  8752.             HEAP32[a + i] = 0;
  8753.         }
  8754.         HEAP32[a + (0 >> 2)] = HEAP32[a + (4 >> 2)] = HEAP32[a + (12 >> 2)] = HEAP32[a + (16 >> 2)] = HEAP32[a + (32 >> 2)] = HEAP32[a + (40 >> 2)] = 1;
  8755.     }
  8756.     var ENV = {};
  8757.     function getExecutableName() {
  8758.         return thisProgram || "./this.program";
  8759.     }
  8760.     function getEnvStrings() {
  8761.         if (!getEnvStrings.strings) {
  8762.             var lang = ((typeof navigator === "object" && navigator.languages && navigator.languages[0]) || "C").replace("-", "_") + ".UTF-8";
  8763.             var env = { USER: "web_user", LOGNAME: "web_user", PATH: "/", PWD: "/", HOME: "/home/web_user", LANG: lang, _: getExecutableName() };
  8764.             for (var x in ENV) {
  8765.                 env[x] = ENV[x];
  8766.             }
  8767.             var strings = [];
  8768.             for (var x in env) {
  8769.                 strings.push(x + "=" + env[x]);
  8770.             }
  8771.             getEnvStrings.strings = strings;
  8772.         }
  8773.         return getEnvStrings.strings;
  8774.     }
  8775.     function _environ_get(__environ, environ_buf) {
  8776.         try {
  8777.             var bufSize = 0;
  8778.             getEnvStrings().forEach(function (string, i) {
  8779.                 var ptr = environ_buf + bufSize;
  8780.                 HEAP32[(__environ + i * 4) >> 2] = ptr;
  8781.                 writeAsciiToMemory(string, ptr);
  8782.                 bufSize += string.length + 1;
  8783.             });
  8784.             return 0;
  8785.         } catch (e) {
  8786.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  8787.             return e.errno;
  8788.         }
  8789.     }
  8790.     function _environ_sizes_get(penviron_count, penviron_buf_size) {
  8791.         try {
  8792.             var strings = getEnvStrings();
  8793.             HEAP32[penviron_count >> 2] = strings.length;
  8794.             var bufSize = 0;
  8795.             strings.forEach(function (string) {
  8796.                 bufSize += string.length + 1;
  8797.             });
  8798.             HEAP32[penviron_buf_size >> 2] = bufSize;
  8799.             return 0;
  8800.         } catch (e) {
  8801.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  8802.             return e.errno;
  8803.         }
  8804.     }
  8805.     function _fd_close(fd) {
  8806.         try {
  8807.             var stream = SYSCALLS.getStreamFromFD(fd);
  8808.             FS.close(stream);
  8809.             return 0;
  8810.         } catch (e) {
  8811.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  8812.             return e.errno;
  8813.         }
  8814.     }
  8815.     function _fd_fdstat_get(fd, pbuf) {
  8816.         try {
  8817.             var stream = SYSCALLS.getStreamFromFD(fd);
  8818.             var type = stream.tty ? 2 : FS.isDir(stream.mode) ? 3 : FS.isLink(stream.mode) ? 7 : 4;
  8819.             HEAP8[pbuf >> 0] = type;
  8820.             return 0;
  8821.         } catch (e) {
  8822.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  8823.             return e.errno;
  8824.         }
  8825.     }
  8826.     function _fd_read(fd, iov, iovcnt, pnum) {
  8827.         try {
  8828.             var stream = SYSCALLS.getStreamFromFD(fd);
  8829.             var num = SYSCALLS.doReadv(stream, iov, iovcnt);
  8830.             HEAP32[pnum >> 2] = num;
  8831.             return 0;
  8832.         } catch (e) {
  8833.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  8834.             return e.errno;
  8835.         }
  8836.     }
  8837.     function _fd_seek(fd, offset_low, offset_high, whence, newOffset) {
  8838.         try {
  8839.             var stream = SYSCALLS.getStreamFromFD(fd);
  8840.             var HIGH_OFFSET = 4294967296;
  8841.             var offset = offset_high * HIGH_OFFSET + (offset_low >>> 0);
  8842.             var DOUBLE_LIMIT = 9007199254740992;
  8843.             if (offset <= -DOUBLE_LIMIT || offset >= DOUBLE_LIMIT) {
  8844.                 return -61;
  8845.             }
  8846.             FS.llseek(stream, offset, whence);
  8847.             (tempI64 = [
  8848.                 stream.position >>> 0,
  8849.                 ((tempDouble = stream.position),
  8850.                 +Math.abs(tempDouble) >= 1 ? (tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0) : 0),
  8851.             ]),
  8852.                 (HEAP32[newOffset >> 2] = tempI64[0]),
  8853.                 (HEAP32[(newOffset + 4) >> 2] = tempI64[1]);
  8854.             if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null;
  8855.             return 0;
  8856.         } catch (e) {
  8857.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  8858.             return e.errno;
  8859.         }
  8860.     }
  8861.     function _fd_write(fd, iov, iovcnt, pnum) {
  8862.         try {
  8863.             var stream = SYSCALLS.getStreamFromFD(fd);
  8864.             var num = SYSCALLS.doWritev(stream, iov, iovcnt);
  8865.             HEAP32[pnum >> 2] = num;
  8866.             return 0;
  8867.         } catch (e) {
  8868.             if (typeof FS === "undefined" || !(e instanceof FS.ErrnoError)) abort(e);
  8869.             return e.errno;
  8870.         }
  8871.     }
  8872.     function _flock(fd, operation) {
  8873.         return 0;
  8874.     }
  8875.     function _getTempRet0() {
  8876.         return getTempRet0();
  8877.     }
  8878.     function getHostByName(name) {
  8879.         var ret = _malloc(20);
  8880.         var nameBuf = _malloc(name.length + 1);
  8881.         stringToUTF8(name, nameBuf, name.length + 1);
  8882.         HEAP32[ret >> 2] = nameBuf;
  8883.         var aliasesBuf = _malloc(4);
  8884.         HEAP32[aliasesBuf >> 2] = 0;
  8885.         HEAP32[(ret + 4) >> 2] = aliasesBuf;
  8886.         var afinet = 2;
  8887.         HEAP32[(ret + 8) >> 2] = afinet;
  8888.         HEAP32[(ret + 12) >> 2] = 4;
  8889.         var addrListBuf = _malloc(12);
  8890.         HEAP32[addrListBuf >> 2] = addrListBuf + 8;
  8891.         HEAP32[(addrListBuf + 4) >> 2] = 0;
  8892.         HEAP32[(addrListBuf + 8) >> 2] = inetPton4(DNS.lookup_name(name));
  8893.         HEAP32[(ret + 16) >> 2] = addrListBuf;
  8894.         return ret;
  8895.     }
  8896.     function _gethostbyaddr(addr, addrlen, type) {
  8897.         if (type !== 2) {
  8898.             setErrNo(5);
  8899.             return null;
  8900.         }
  8901.         addr = HEAP32[addr >> 2];
  8902.         var host = inetNtop4(addr);
  8903.         var lookup = DNS.lookup_addr(host);
  8904.         if (lookup) {
  8905.             host = lookup;
  8906.         }
  8907.         return getHostByName(host);
  8908.     }
  8909.     function _gethostbyname(name) {
  8910.         return getHostByName(UTF8ToString(name));
  8911.     }
  8912.     function _getpwuid() {
  8913.         throw "getpwuid: TODO";
  8914.     }
  8915.     function _gettimeofday(ptr) {
  8916.         var now = Date.now();
  8917.         HEAP32[ptr >> 2] = (now / 1e3) | 0;
  8918.         HEAP32[(ptr + 4) >> 2] = ((now % 1e3) * 1e3) | 0;
  8919.         return 0;
  8920.     }
  8921.     function _glActiveTexture(x0) {
  8922.         GLctx["activeTexture"](x0);
  8923.     }
  8924.     function _glAttachShader(program, shader) {
  8925.         program = GL.programs[program];
  8926.         shader = GL.shaders[shader];
  8927.         program[shader.shaderType] = shader;
  8928.         GLctx.attachShader(program, shader);
  8929.     }
  8930.     function _glBeginQuery(target, id) {
  8931.         GLctx["beginQuery"](target, GL.queries[id]);
  8932.     }
  8933.     function _glBeginTransformFeedback(x0) {
  8934.         GLctx["beginTransformFeedback"](x0);
  8935.     }
  8936.     function _glBindAttribLocation(program, index, name) {
  8937.         GLctx.bindAttribLocation(GL.programs[program], index, UTF8ToString(name));
  8938.     }
  8939.     function _glBindBuffer(target, buffer) {
  8940.         if (target == 34962) {
  8941.             GLctx.currentArrayBufferBinding = buffer;
  8942.         } else if (target == 34963) {
  8943.             GLctx.currentElementArrayBufferBinding = buffer;
  8944.         }
  8945.         if (target == 35051) {
  8946.             GLctx.currentPixelPackBufferBinding = buffer;
  8947.         } else if (target == 35052) {
  8948.             GLctx.currentPixelUnpackBufferBinding = buffer;
  8949.         }
  8950.         GLctx.bindBuffer(target, GL.buffers[buffer]);
  8951.     }
  8952.     function _glBindBufferBase(target, index, buffer) {
  8953.         GLctx["bindBufferBase"](target, index, GL.buffers[buffer]);
  8954.     }
  8955.     function _glBindBufferRange(target, index, buffer, offset, ptrsize) {
  8956.         GLctx["bindBufferRange"](target, index, GL.buffers[buffer], offset, ptrsize);
  8957.     }
  8958.     function _glBindFramebuffer(target, framebuffer) {
  8959.         GLctx.bindFramebuffer(target, GL.framebuffers[framebuffer]);
  8960.     }
  8961.     function _glBindRenderbuffer(target, renderbuffer) {
  8962.         GLctx.bindRenderbuffer(target, GL.renderbuffers[renderbuffer]);
  8963.     }
  8964.     function _glBindSampler(unit, sampler) {
  8965.         GLctx["bindSampler"](unit, GL.samplers[sampler]);
  8966.     }
  8967.     function _glBindTexture(target, texture) {
  8968.         GLctx.bindTexture(target, GL.textures[texture]);
  8969.     }
  8970.     function _glBindTransformFeedback(target, id) {
  8971.         GLctx["bindTransformFeedback"](target, GL.transformFeedbacks[id]);
  8972.     }
  8973.     function _glBindVertexArray(vao) {
  8974.         GLctx["bindVertexArray"](GL.vaos[vao]);
  8975.         var ibo = GLctx.getParameter(34965);
  8976.         GLctx.currentElementArrayBufferBinding = ibo ? ibo.name | 0 : 0;
  8977.     }
  8978.     function _glBlendEquation(x0) {
  8979.         GLctx["blendEquation"](x0);
  8980.     }
  8981.     function _glBlendEquationSeparate(x0, x1) {
  8982.         GLctx["blendEquationSeparate"](x0, x1);
  8983.     }
  8984.     function _glBlendFuncSeparate(x0, x1, x2, x3) {
  8985.         GLctx["blendFuncSeparate"](x0, x1, x2, x3);
  8986.     }
  8987.     function _glBlitFramebuffer(x0, x1, x2, x3, x4, x5, x6, x7, x8, x9) {
  8988.         GLctx["blitFramebuffer"](x0, x1, x2, x3, x4, x5, x6, x7, x8, x9);
  8989.     }
  8990.     function _glBufferData(target, size, data, usage) {
  8991.         if (GL.currentContext.version >= 2) {
  8992.             if (data) {
  8993.                 GLctx.bufferData(target, HEAPU8, usage, data, size);
  8994.             } else {
  8995.                 GLctx.bufferData(target, size, usage);
  8996.             }
  8997.         } else {
  8998.             GLctx.bufferData(target, data ? HEAPU8.subarray(data, data + size) : size, usage);
  8999.         }
  9000.     }
  9001.     function _glBufferSubData(target, offset, size, data) {
  9002.         if (GL.currentContext.version >= 2) {
  9003.             GLctx.bufferSubData(target, offset, HEAPU8, data, size);
  9004.             return;
  9005.         }
  9006.         GLctx.bufferSubData(target, offset, HEAPU8.subarray(data, data + size));
  9007.     }
  9008.     function _glCheckFramebufferStatus(x0) {
  9009.         return GLctx["checkFramebufferStatus"](x0);
  9010.     }
  9011.     function _glClear(mask) {
  9012.         if (mask == 16384) {
  9013.             var v = GLctx.getParameter(GLctx.COLOR_WRITEMASK);
  9014.             if (!v[0] && !v[1] && !v[2] && v[3]) return;
  9015.         }
  9016.         GLctx.clear(mask);
  9017.     }
  9018.     function _glClearBufferfi(x0, x1, x2, x3) {
  9019.         GLctx["clearBufferfi"](x0, x1, x2, x3);
  9020.     }
  9021.     function _glClearBufferfv(buffer, drawbuffer, value) {
  9022.         GLctx["clearBufferfv"](buffer, drawbuffer, HEAPF32, value >> 2);
  9023.     }
  9024.     function _glClearBufferuiv(buffer, drawbuffer, value) {
  9025.         GLctx["clearBufferuiv"](buffer, drawbuffer, HEAPU32, value >> 2);
  9026.     }
  9027.     function _glClearColor(x0, x1, x2, x3) {
  9028.         GLctx["clearColor"](x0, x1, x2, x3);
  9029.     }
  9030.     function _glClearDepthf(x0) {
  9031.         GLctx["clearDepth"](x0);
  9032.     }
  9033.     function _glClearStencil(x0) {
  9034.         GLctx["clearStencil"](x0);
  9035.     }
  9036.     function _glClientWaitSync(sync, flags, timeoutLo, timeoutHi) {
  9037.         return GLctx.clientWaitSync(GL.syncs[sync], flags, convertI32PairToI53(timeoutLo, timeoutHi));
  9038.     }
  9039.     function _glColorMask(red, green, blue, alpha) {
  9040.         GLctx.colorMask(!!red, !!green, !!blue, !!alpha);
  9041.     }
  9042.     function _glCompileShader(shader) {
  9043.         GLctx.compileShader(GL.shaders[shader]);
  9044.     }
  9045.     function _glCompressedTexImage2D(target, level, internalFormat, width, height, border, imageSize, data) {
  9046.         if (GL.currentContext.version >= 2) {
  9047.             if (GLctx.currentPixelUnpackBufferBinding) {
  9048.                 GLctx["compressedTexImage2D"](target, level, internalFormat, width, height, border, imageSize, data);
  9049.             } else {
  9050.                 GLctx["compressedTexImage2D"](target, level, internalFormat, width, height, border, HEAPU8, data, imageSize);
  9051.             }
  9052.             return;
  9053.         }
  9054.         GLctx["compressedTexImage2D"](target, level, internalFormat, width, height, border, data ? HEAPU8.subarray(data, data + imageSize) : null);
  9055.     }
  9056.     function _glCompressedTexImage3D(target, level, internalFormat, width, height, depth, border, imageSize, data) {
  9057.         if (GLctx.currentPixelUnpackBufferBinding) {
  9058.             GLctx["compressedTexImage3D"](target, level, internalFormat, width, height, depth, border, imageSize, data);
  9059.         } else {
  9060.             GLctx["compressedTexImage3D"](target, level, internalFormat, width, height, depth, border, HEAPU8, data, imageSize);
  9061.         }
  9062.     }
  9063.     function _glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data) {
  9064.         if (GL.currentContext.version >= 2) {
  9065.             if (GLctx.currentPixelUnpackBufferBinding) {
  9066.                 GLctx["compressedTexSubImage2D"](target, level, xoffset, yoffset, width, height, format, imageSize, data);
  9067.             } else {
  9068.                 GLctx["compressedTexSubImage2D"](target, level, xoffset, yoffset, width, height, format, HEAPU8, data, imageSize);
  9069.             }
  9070.             return;
  9071.         }
  9072.         GLctx["compressedTexSubImage2D"](target, level, xoffset, yoffset, width, height, format, data ? HEAPU8.subarray(data, data + imageSize) : null);
  9073.     }
  9074.     function _glCompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data) {
  9075.         if (GLctx.currentPixelUnpackBufferBinding) {
  9076.             GLctx["compressedTexSubImage3D"](target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
  9077.         } else {
  9078.             GLctx["compressedTexSubImage3D"](target, level, xoffset, yoffset, zoffset, width, height, depth, format, HEAPU8, data, imageSize);
  9079.         }
  9080.     }
  9081.     function _glCopyBufferSubData(x0, x1, x2, x3, x4) {
  9082.         GLctx["copyBufferSubData"](x0, x1, x2, x3, x4);
  9083.     }
  9084.     function _glCopyTexImage2D(x0, x1, x2, x3, x4, x5, x6, x7) {
  9085.         GLctx["copyTexImage2D"](x0, x1, x2, x3, x4, x5, x6, x7);
  9086.     }
  9087.     function _glCopyTexSubImage2D(x0, x1, x2, x3, x4, x5, x6, x7) {
  9088.         GLctx["copyTexSubImage2D"](x0, x1, x2, x3, x4, x5, x6, x7);
  9089.     }
  9090.     function _glCreateProgram() {
  9091.         var id = GL.getNewId(GL.programs);
  9092.         var program = GLctx.createProgram();
  9093.         program.name = id;
  9094.         program.maxUniformLength = program.maxAttributeLength = program.maxUniformBlockNameLength = 0;
  9095.         program.uniformIdCounter = 1;
  9096.         GL.programs[id] = program;
  9097.         return id;
  9098.     }
  9099.     function _glCreateShader(shaderType) {
  9100.         var id = GL.getNewId(GL.shaders);
  9101.         GL.shaders[id] = GLctx.createShader(shaderType);
  9102.         GL.shaders[id].shaderType = shaderType & 1 ? "vs" : "fs";
  9103.         return id;
  9104.     }
  9105.     function _glCullFace(x0) {
  9106.         GLctx["cullFace"](x0);
  9107.     }
  9108.     function _glDeleteBuffers(n, buffers) {
  9109.         for (var i = 0; i < n; i++) {
  9110.             var id = HEAP32[(buffers + i * 4) >> 2];
  9111.             var buffer = GL.buffers[id];
  9112.             if (!buffer) continue;
  9113.             GLctx.deleteBuffer(buffer);
  9114.             buffer.name = 0;
  9115.             GL.buffers[id] = null;
  9116.             if (id == GLctx.currentArrayBufferBinding) GLctx.currentArrayBufferBinding = 0;
  9117.             if (id == GLctx.currentElementArrayBufferBinding) GLctx.currentElementArrayBufferBinding = 0;
  9118.             if (id == GLctx.currentPixelPackBufferBinding) GLctx.currentPixelPackBufferBinding = 0;
  9119.             if (id == GLctx.currentPixelUnpackBufferBinding) GLctx.currentPixelUnpackBufferBinding = 0;
  9120.         }
  9121.     }
  9122.     function _glDeleteFramebuffers(n, framebuffers) {
  9123.         for (var i = 0; i < n; ++i) {
  9124.             var id = HEAP32[(framebuffers + i * 4) >> 2];
  9125.             var framebuffer = GL.framebuffers[id];
  9126.             if (!framebuffer) continue;
  9127.             GLctx.deleteFramebuffer(framebuffer);
  9128.             framebuffer.name = 0;
  9129.             GL.framebuffers[id] = null;
  9130.         }
  9131.     }
  9132.     function _glDeleteProgram(id) {
  9133.         if (!id) return;
  9134.         var program = GL.programs[id];
  9135.         if (!program) {
  9136.             GL.recordError(1281);
  9137.             return;
  9138.         }
  9139.         GLctx.deleteProgram(program);
  9140.         program.name = 0;
  9141.         GL.programs[id] = null;
  9142.     }
  9143.     function _glDeleteQueries(n, ids) {
  9144.         for (var i = 0; i < n; i++) {
  9145.             var id = HEAP32[(ids + i * 4) >> 2];
  9146.             var query = GL.queries[id];
  9147.             if (!query) continue;
  9148.             GLctx["deleteQuery"](query);
  9149.             GL.queries[id] = null;
  9150.         }
  9151.     }
  9152.     function _glDeleteRenderbuffers(n, renderbuffers) {
  9153.         for (var i = 0; i < n; i++) {
  9154.             var id = HEAP32[(renderbuffers + i * 4) >> 2];
  9155.             var renderbuffer = GL.renderbuffers[id];
  9156.             if (!renderbuffer) continue;
  9157.             GLctx.deleteRenderbuffer(renderbuffer);
  9158.             renderbuffer.name = 0;
  9159.             GL.renderbuffers[id] = null;
  9160.         }
  9161.     }
  9162.     function _glDeleteSamplers(n, samplers) {
  9163.         for (var i = 0; i < n; i++) {
  9164.             var id = HEAP32[(samplers + i * 4) >> 2];
  9165.             var sampler = GL.samplers[id];
  9166.             if (!sampler) continue;
  9167.             GLctx["deleteSampler"](sampler);
  9168.             sampler.name = 0;
  9169.             GL.samplers[id] = null;
  9170.         }
  9171.     }
  9172.     function _glDeleteShader(id) {
  9173.         if (!id) return;
  9174.         var shader = GL.shaders[id];
  9175.         if (!shader) {
  9176.             GL.recordError(1281);
  9177.             return;
  9178.         }
  9179.         GLctx.deleteShader(shader);
  9180.         GL.shaders[id] = null;
  9181.     }
  9182.     function _glDeleteSync(id) {
  9183.         if (!id) return;
  9184.         var sync = GL.syncs[id];
  9185.         if (!sync) {
  9186.             GL.recordError(1281);
  9187.             return;
  9188.         }
  9189.         GLctx.deleteSync(sync);
  9190.         sync.name = 0;
  9191.         GL.syncs[id] = null;
  9192.     }
  9193.     function _glDeleteTextures(n, textures) {
  9194.         for (var i = 0; i < n; i++) {
  9195.             var id = HEAP32[(textures + i * 4) >> 2];
  9196.             var texture = GL.textures[id];
  9197.             if (!texture) continue;
  9198.             GLctx.deleteTexture(texture);
  9199.             texture.name = 0;
  9200.             GL.textures[id] = null;
  9201.         }
  9202.     }
  9203.     function _glDeleteTransformFeedbacks(n, ids) {
  9204.         for (var i = 0; i < n; i++) {
  9205.             var id = HEAP32[(ids + i * 4) >> 2];
  9206.             var transformFeedback = GL.transformFeedbacks[id];
  9207.             if (!transformFeedback) continue;
  9208.             GLctx["deleteTransformFeedback"](transformFeedback);
  9209.             transformFeedback.name = 0;
  9210.             GL.transformFeedbacks[id] = null;
  9211.         }
  9212.     }
  9213.     function _glDeleteVertexArrays(n, vaos) {
  9214.         for (var i = 0; i < n; i++) {
  9215.             var id = HEAP32[(vaos + i * 4) >> 2];
  9216.             GLctx["deleteVertexArray"](GL.vaos[id]);
  9217.             GL.vaos[id] = null;
  9218.         }
  9219.     }
  9220.     function _glDepthFunc(x0) {
  9221.         GLctx["depthFunc"](x0);
  9222.     }
  9223.     function _glDepthMask(flag) {
  9224.         GLctx.depthMask(!!flag);
  9225.     }
  9226.     function _glDetachShader(program, shader) {
  9227.         GLctx.detachShader(GL.programs[program], GL.shaders[shader]);
  9228.     }
  9229.     function _glDisable(x0) {
  9230.         GLctx["disable"](x0);
  9231.     }
  9232.     function _glDisableVertexAttribArray(index) {
  9233.         var cb = GL.currentContext.clientBuffers[index];
  9234.         cb.enabled = false;
  9235.         GLctx.disableVertexAttribArray(index);
  9236.     }
  9237.     function _glDrawArrays(mode, first, count) {
  9238.         GL.preDrawHandleClientVertexAttribBindings(first + count);
  9239.         GLctx.drawArrays(mode, first, count);
  9240.         GL.postDrawHandleClientVertexAttribBindings();
  9241.     }
  9242.     function _glDrawArraysInstanced(mode, first, count, primcount) {
  9243.         GLctx["drawArraysInstanced"](mode, first, count, primcount);
  9244.     }
  9245.     var tempFixedLengthArray = [];
  9246.     function _glDrawBuffers(n, bufs) {
  9247.         var bufArray = tempFixedLengthArray[n];
  9248.         for (var i = 0; i < n; i++) {
  9249.             bufArray[i] = HEAP32[(bufs + i * 4) >> 2];
  9250.         }
  9251.         GLctx["drawBuffers"](bufArray);
  9252.     }
  9253.     function _glDrawElements(mode, count, type, indices) {
  9254.         var buf;
  9255.         if (!GLctx.currentElementArrayBufferBinding) {
  9256.             var size = GL.calcBufLength(1, type, 0, count);
  9257.             buf = GL.getTempIndexBuffer(size);
  9258.             GLctx.bindBuffer(34963, buf);
  9259.             GLctx.bufferSubData(34963, 0, HEAPU8.subarray(indices, indices + size));
  9260.             indices = 0;
  9261.         }
  9262.         GL.preDrawHandleClientVertexAttribBindings(count);
  9263.         GLctx.drawElements(mode, count, type, indices);
  9264.         GL.postDrawHandleClientVertexAttribBindings(count);
  9265.         if (!GLctx.currentElementArrayBufferBinding) {
  9266.             GLctx.bindBuffer(34963, null);
  9267.         }
  9268.     }
  9269.     function _glDrawElementsInstanced(mode, count, type, indices, primcount) {
  9270.         GLctx["drawElementsInstanced"](mode, count, type, indices, primcount);
  9271.     }
  9272.     function _glEnable(x0) {
  9273.         GLctx["enable"](x0);
  9274.     }
  9275.     function _glEnableVertexAttribArray(index) {
  9276.         var cb = GL.currentContext.clientBuffers[index];
  9277.         cb.enabled = true;
  9278.         GLctx.enableVertexAttribArray(index);
  9279.     }
  9280.     function _glEndQuery(x0) {
  9281.         GLctx["endQuery"](x0);
  9282.     }
  9283.     function _glEndTransformFeedback() {
  9284.         GLctx["endTransformFeedback"]();
  9285.     }
  9286.     function _glFenceSync(condition, flags) {
  9287.         var sync = GLctx.fenceSync(condition, flags);
  9288.         if (sync) {
  9289.             var id = GL.getNewId(GL.syncs);
  9290.             sync.name = id;
  9291.             GL.syncs[id] = sync;
  9292.             return id;
  9293.         } else {
  9294.             return 0;
  9295.         }
  9296.     }
  9297.     function _glFinish() {
  9298.         GLctx["finish"]();
  9299.     }
  9300.     function _glFlush() {
  9301.         GLctx["flush"]();
  9302.     }
  9303.     function emscriptenWebGLGetBufferBinding(target) {
  9304.         switch (target) {
  9305.             case 34962:
  9306.                 target = 34964;
  9307.                 break;
  9308.             case 34963:
  9309.                 target = 34965;
  9310.                 break;
  9311.             case 35051:
  9312.                 target = 35053;
  9313.                 break;
  9314.             case 35052:
  9315.                 target = 35055;
  9316.                 break;
  9317.             case 35982:
  9318.                 target = 35983;
  9319.                 break;
  9320.             case 36662:
  9321.                 target = 36662;
  9322.                 break;
  9323.             case 36663:
  9324.                 target = 36663;
  9325.                 break;
  9326.             case 35345:
  9327.                 target = 35368;
  9328.                 break;
  9329.         }
  9330.         var buffer = GLctx.getParameter(target);
  9331.         if (buffer) return buffer.name | 0;
  9332.         else return 0;
  9333.     }
  9334.     function emscriptenWebGLValidateMapBufferTarget(target) {
  9335.         switch (target) {
  9336.             case 34962:
  9337.             case 34963:
  9338.             case 36662:
  9339.             case 36663:
  9340.             case 35051:
  9341.             case 35052:
  9342.             case 35882:
  9343.             case 35982:
  9344.             case 35345:
  9345.                 return true;
  9346.             default:
  9347.                 return false;
  9348.         }
  9349.     }
  9350.     function _glFlushMappedBufferRange(target, offset, length) {
  9351.         if (!emscriptenWebGLValidateMapBufferTarget(target)) {
  9352.             GL.recordError(1280);
  9353.             err("GL_INVALID_ENUM in glFlushMappedBufferRange");
  9354.             return;
  9355.         }
  9356.         var mapping = GL.mappedBuffers[emscriptenWebGLGetBufferBinding(target)];
  9357.         if (!mapping) {
  9358.             GL.recordError(1282);
  9359.             err("buffer was never mapped in glFlushMappedBufferRange");
  9360.             return;
  9361.         }
  9362.         if (!(mapping.access & 16)) {
  9363.             GL.recordError(1282);
  9364.             err("buffer was not mapped with GL_MAP_FLUSH_EXPLICIT_BIT in glFlushMappedBufferRange");
  9365.             return;
  9366.         }
  9367.         if (offset < 0 || length < 0 || offset + length > mapping.length) {
  9368.             GL.recordError(1281);
  9369.             err("invalid range in glFlushMappedBufferRange");
  9370.             return;
  9371.         }
  9372.         GLctx.bufferSubData(target, mapping.offset, HEAPU8.subarray(mapping.mem + offset, mapping.mem + offset + length));
  9373.     }
  9374.     function _glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer) {
  9375.         GLctx.framebufferRenderbuffer(target, attachment, renderbuffertarget, GL.renderbuffers[renderbuffer]);
  9376.     }
  9377.     function _glFramebufferTexture2D(target, attachment, textarget, texture, level) {
  9378.         GLctx.framebufferTexture2D(target, attachment, textarget, GL.textures[texture], level);
  9379.     }
  9380.     function _glFramebufferTextureLayer(target, attachment, texture, level, layer) {
  9381.         GLctx.framebufferTextureLayer(target, attachment, GL.textures[texture], level, layer);
  9382.     }
  9383.     function _glFrontFace(x0) {
  9384.         GLctx["frontFace"](x0);
  9385.     }
  9386.     function __glGenObject(n, buffers, createFunction, objectTable) {
  9387.         for (var i = 0; i < n; i++) {
  9388.             var buffer = GLctx[createFunction]();
  9389.             var id = buffer && GL.getNewId(objectTable);
  9390.             if (buffer) {
  9391.                 buffer.name = id;
  9392.                 objectTable[id] = buffer;
  9393.             } else {
  9394.                 GL.recordError(1282);
  9395.             }
  9396.             HEAP32[(buffers + i * 4) >> 2] = id;
  9397.         }
  9398.     }
  9399.     function _glGenBuffers(n, buffers) {
  9400.         __glGenObject(n, buffers, "createBuffer", GL.buffers);
  9401.     }
  9402.     function _glGenFramebuffers(n, ids) {
  9403.         __glGenObject(n, ids, "createFramebuffer", GL.framebuffers);
  9404.     }
  9405.     function _glGenQueries(n, ids) {
  9406.         __glGenObject(n, ids, "createQuery", GL.queries);
  9407.     }
  9408.     function _glGenRenderbuffers(n, renderbuffers) {
  9409.         __glGenObject(n, renderbuffers, "createRenderbuffer", GL.renderbuffers);
  9410.     }
  9411.     function _glGenSamplers(n, samplers) {
  9412.         __glGenObject(n, samplers, "createSampler", GL.samplers);
  9413.     }
  9414.     function _glGenTextures(n, textures) {
  9415.         __glGenObject(n, textures, "createTexture", GL.textures);
  9416.     }
  9417.     function _glGenTransformFeedbacks(n, ids) {
  9418.         __glGenObject(n, ids, "createTransformFeedback", GL.transformFeedbacks);
  9419.     }
  9420.     function _glGenVertexArrays(n, arrays) {
  9421.         __glGenObject(n, arrays, "createVertexArray", GL.vaos);
  9422.     }
  9423.     function _glGenerateMipmap(x0) {
  9424.         GLctx["generateMipmap"](x0);
  9425.     }
  9426.     function __glGetActiveAttribOrUniform(funcName, program, index, bufSize, length, size, type, name) {
  9427.         program = GL.programs[program];
  9428.         var info = GLctx[funcName](program, index);
  9429.         if (info) {
  9430.             var numBytesWrittenExclNull = name && stringToUTF8(info.name, name, bufSize);
  9431.             if (length) HEAP32[length >> 2] = numBytesWrittenExclNull;
  9432.             if (size) HEAP32[size >> 2] = info.size;
  9433.             if (type) HEAP32[type >> 2] = info.type;
  9434.         }
  9435.     }
  9436.     function _glGetActiveAttrib(program, index, bufSize, length, size, type, name) {
  9437.         __glGetActiveAttribOrUniform("getActiveAttrib", program, index, bufSize, length, size, type, name);
  9438.     }
  9439.     function _glGetActiveUniform(program, index, bufSize, length, size, type, name) {
  9440.         __glGetActiveAttribOrUniform("getActiveUniform", program, index, bufSize, length, size, type, name);
  9441.     }
  9442.     function _glGetActiveUniformBlockName(program, uniformBlockIndex, bufSize, length, uniformBlockName) {
  9443.         program = GL.programs[program];
  9444.         var result = GLctx["getActiveUniformBlockName"](program, uniformBlockIndex);
  9445.         if (!result) return;
  9446.         if (uniformBlockName && bufSize > 0) {
  9447.             var numBytesWrittenExclNull = stringToUTF8(result, uniformBlockName, bufSize);
  9448.             if (length) HEAP32[length >> 2] = numBytesWrittenExclNull;
  9449.         } else {
  9450.             if (length) HEAP32[length >> 2] = 0;
  9451.         }
  9452.     }
  9453.     function _glGetActiveUniformBlockiv(program, uniformBlockIndex, pname, params) {
  9454.         if (!params) {
  9455.             GL.recordError(1281);
  9456.             return;
  9457.         }
  9458.         program = GL.programs[program];
  9459.         if (pname == 35393) {
  9460.             var name = GLctx["getActiveUniformBlockName"](program, uniformBlockIndex);
  9461.             HEAP32[params >> 2] = name.length + 1;
  9462.             return;
  9463.         }
  9464.         var result = GLctx["getActiveUniformBlockParameter"](program, uniformBlockIndex, pname);
  9465.         if (result === null) return;
  9466.         if (pname == 35395) {
  9467.             for (var i = 0; i < result.length; i++) {
  9468.                 HEAP32[(params + i * 4) >> 2] = result[i];
  9469.             }
  9470.         } else {
  9471.             HEAP32[params >> 2] = result;
  9472.         }
  9473.     }
  9474.     function _glGetActiveUniformsiv(program, uniformCount, uniformIndices, pname, params) {
  9475.         if (!params) {
  9476.             GL.recordError(1281);
  9477.             return;
  9478.         }
  9479.         if (uniformCount > 0 && uniformIndices == 0) {
  9480.             GL.recordError(1281);
  9481.             return;
  9482.         }
  9483.         program = GL.programs[program];
  9484.         var ids = [];
  9485.         for (var i = 0; i < uniformCount; i++) {
  9486.             ids.push(HEAP32[(uniformIndices + i * 4) >> 2]);
  9487.         }
  9488.         var result = GLctx["getActiveUniforms"](program, ids, pname);
  9489.         if (!result) return;
  9490.         var len = result.length;
  9491.         for (var i = 0; i < len; i++) {
  9492.             HEAP32[(params + i * 4) >> 2] = result[i];
  9493.         }
  9494.     }
  9495.     function _glGetAttribLocation(program, name) {
  9496.         return GLctx.getAttribLocation(GL.programs[program], UTF8ToString(name));
  9497.     }
  9498.     function _glGetError() {
  9499.         var error = GLctx.getError() || GL.lastError;
  9500.         GL.lastError = 0;
  9501.         return error;
  9502.     }
  9503.     function _glGetFramebufferAttachmentParameteriv(target, attachment, pname, params) {
  9504.         var result = GLctx.getFramebufferAttachmentParameter(target, attachment, pname);
  9505.         if (result instanceof WebGLRenderbuffer || result instanceof WebGLTexture) {
  9506.             result = result.name | 0;
  9507.         }
  9508.         HEAP32[params >> 2] = result;
  9509.     }
  9510.     function writeI53ToI64(ptr, num) {
  9511.         HEAPU32[ptr >> 2] = num;
  9512.         HEAPU32[(ptr + 4) >> 2] = (num - HEAPU32[ptr >> 2]) / 4294967296;
  9513.     }
  9514.     function emscriptenWebGLGetIndexed(target, index, data, type) {
  9515.         if (!data) {
  9516.             GL.recordError(1281);
  9517.             return;
  9518.         }
  9519.         var result = GLctx["getIndexedParameter"](target, index);
  9520.         var ret;
  9521.         switch (typeof result) {
  9522.             case "boolean":
  9523.                 ret = result ? 1 : 0;
  9524.                 break;
  9525.             case "number":
  9526.                 ret = result;
  9527.                 break;
  9528.             case "object":
  9529.                 if (result === null) {
  9530.                     switch (target) {
  9531.                         case 35983:
  9532.                         case 35368:
  9533.                             ret = 0;
  9534.                             break;
  9535.                         default: {
  9536.                             GL.recordError(1280);
  9537.                             return;
  9538.                         }
  9539.                     }
  9540.                 } else if (result instanceof WebGLBuffer) {
  9541.                     ret = result.name | 0;
  9542.                 } else {
  9543.                     GL.recordError(1280);
  9544.                     return;
  9545.                 }
  9546.                 break;
  9547.             default:
  9548.                 GL.recordError(1280);
  9549.                 return;
  9550.         }
  9551.         switch (type) {
  9552.             case 1:
  9553.                 writeI53ToI64(data, ret);
  9554.                 break;
  9555.             case 0:
  9556.                 HEAP32[data >> 2] = ret;
  9557.                 break;
  9558.             case 2:
  9559.                 HEAPF32[data >> 2] = ret;
  9560.                 break;
  9561.             case 4:
  9562.                 HEAP8[data >> 0] = ret ? 1 : 0;
  9563.                 break;
  9564.             default:
  9565.                 throw "internal emscriptenWebGLGetIndexed() error, bad type: " + type;
  9566.         }
  9567.     }
  9568.     function _glGetIntegeri_v(target, index, data) {
  9569.         emscriptenWebGLGetIndexed(target, index, data, 0);
  9570.     }
  9571.     function emscriptenWebGLGet(name_, p, type) {
  9572.         if (!p) {
  9573.             GL.recordError(1281);
  9574.             return;
  9575.         }
  9576.         var ret = undefined;
  9577.         switch (name_) {
  9578.             case 36346:
  9579.                 ret = 1;
  9580.                 break;
  9581.             case 36344:
  9582.                 if (type != 0 && type != 1) {
  9583.                     GL.recordError(1280);
  9584.                 }
  9585.                 return;
  9586.             case 34814:
  9587.             case 36345:
  9588.                 ret = 0;
  9589.                 break;
  9590.             case 34466:
  9591.                 var formats = GLctx.getParameter(34467);
  9592.                 ret = formats ? formats.length : 0;
  9593.                 break;
  9594.             case 33390:
  9595.                 ret = 1048576;
  9596.                 break;
  9597.             case 33309:
  9598.                 if (GL.currentContext.version < 2) {
  9599.                     GL.recordError(1282);
  9600.                     return;
  9601.                 }
  9602.                 var exts = GLctx.getSupportedExtensions() || [];
  9603.                 ret = 2 * exts.length;
  9604.                 break;
  9605.             case 33307:
  9606.             case 33308:
  9607.                 if (GL.currentContext.version < 2) {
  9608.                     GL.recordError(1280);
  9609.                     return;
  9610.                 }
  9611.                 ret = name_ == 33307 ? 3 : 0;
  9612.                 break;
  9613.         }
  9614.         if (ret === undefined) {
  9615.             var result = GLctx.getParameter(name_);
  9616.             switch (typeof result) {
  9617.                 case "number":
  9618.                     ret = result;
  9619.                     break;
  9620.                 case "boolean":
  9621.                     ret = result ? 1 : 0;
  9622.                     break;
  9623.                 case "string":
  9624.                     GL.recordError(1280);
  9625.                     return;
  9626.                 case "object":
  9627.                     if (result === null) {
  9628.                         switch (name_) {
  9629.                             case 34964:
  9630.                             case 35725:
  9631.                             case 34965:
  9632.                             case 36006:
  9633.                             case 36007:
  9634.                             case 32873:
  9635.                             case 34229:
  9636.                             case 36662:
  9637.                             case 36663:
  9638.                             case 35053:
  9639.                             case 35055:
  9640.                             case 36010:
  9641.                             case 35097:
  9642.                             case 35869:
  9643.                             case 32874:
  9644.                             case 36389:
  9645.                             case 35983:
  9646.                             case 35368:
  9647.                             case 34068: {
  9648.                                 ret = 0;
  9649.                                 break;
  9650.                             }
  9651.                             default: {
  9652.                                 GL.recordError(1280);
  9653.                                 return;
  9654.                             }
  9655.                         }
  9656.                     } else if (result instanceof Float32Array || result instanceof Uint32Array || result instanceof Int32Array || result instanceof Array) {
  9657.                         for (var i = 0; i < result.length; ++i) {
  9658.                             switch (type) {
  9659.                                 case 0:
  9660.                                     HEAP32[(p + i * 4) >> 2] = result[i];
  9661.                                     break;
  9662.                                 case 2:
  9663.                                     HEAPF32[(p + i * 4) >> 2] = result[i];
  9664.                                     break;
  9665.                                 case 4:
  9666.                                     HEAP8[(p + i) >> 0] = result[i] ? 1 : 0;
  9667.                                     break;
  9668.                             }
  9669.                         }
  9670.                         return;
  9671.                     } else {
  9672.                         try {
  9673.                             ret = result.name | 0;
  9674.                         } catch (e) {
  9675.                             GL.recordError(1280);
  9676.                             err("GL_INVALID_ENUM in glGet" + type + "v: Unknown object returned from WebGL getParameter(" + name_ + ")! (error: " + e + ")");
  9677.                             return;
  9678.                         }
  9679.                     }
  9680.                     break;
  9681.                 default:
  9682.                     GL.recordError(1280);
  9683.                     err("GL_INVALID_ENUM in glGet" + type + "v: Native code calling glGet" + type + "v(" + name_ + ") and it returns " + result + " of type " + typeof result + "!");
  9684.                     return;
  9685.             }
  9686.         }
  9687.         switch (type) {
  9688.             case 1:
  9689.                 writeI53ToI64(p, ret);
  9690.                 break;
  9691.             case 0:
  9692.                 HEAP32[p >> 2] = ret;
  9693.                 break;
  9694.             case 2:
  9695.                 HEAPF32[p >> 2] = ret;
  9696.                 break;
  9697.             case 4:
  9698.                 HEAP8[p >> 0] = ret ? 1 : 0;
  9699.                 break;
  9700.         }
  9701.     }
  9702.     function _glGetIntegerv(name_, p) {
  9703.         emscriptenWebGLGet(name_, p, 0);
  9704.     }
  9705.     function _glGetInternalformativ(target, internalformat, pname, bufSize, params) {
  9706.         if (bufSize < 0) {
  9707.             GL.recordError(1281);
  9708.             return;
  9709.         }
  9710.         if (!params) {
  9711.             GL.recordError(1281);
  9712.             return;
  9713.         }
  9714.         var ret = GLctx["getInternalformatParameter"](target, internalformat, pname);
  9715.         if (ret === null) return;
  9716.         for (var i = 0; i < ret.length && i < bufSize; ++i) {
  9717.             HEAP32[(params + i * 4) >> 2] = ret[i];
  9718.         }
  9719.     }
  9720.     function _glGetProgramBinary(program, bufSize, length, binaryFormat, binary) {
  9721.         GL.recordError(1282);
  9722.     }
  9723.     function _glGetProgramInfoLog(program, maxLength, length, infoLog) {
  9724.         var log = GLctx.getProgramInfoLog(GL.programs[program]);
  9725.         if (log === null) log = "(unknown error)";
  9726.         var numBytesWrittenExclNull = maxLength > 0 && infoLog ? stringToUTF8(log, infoLog, maxLength) : 0;
  9727.         if (length) HEAP32[length >> 2] = numBytesWrittenExclNull;
  9728.     }
  9729.     function _glGetProgramiv(program, pname, p) {
  9730.         if (!p) {
  9731.             GL.recordError(1281);
  9732.             return;
  9733.         }
  9734.         if (program >= GL.counter) {
  9735.             GL.recordError(1281);
  9736.             return;
  9737.         }
  9738.         program = GL.programs[program];
  9739.         if (pname == 35716) {
  9740.             var log = GLctx.getProgramInfoLog(program);
  9741.             if (log === null) log = "(unknown error)";
  9742.             HEAP32[p >> 2] = log.length + 1;
  9743.         } else if (pname == 35719) {
  9744.             if (!program.maxUniformLength) {
  9745.                 for (var i = 0; i < GLctx.getProgramParameter(program, 35718); ++i) {
  9746.                     program.maxUniformLength = Math.max(program.maxUniformLength, GLctx.getActiveUniform(program, i).name.length + 1);
  9747.                 }
  9748.             }
  9749.             HEAP32[p >> 2] = program.maxUniformLength;
  9750.         } else if (pname == 35722) {
  9751.             if (!program.maxAttributeLength) {
  9752.                 for (var i = 0; i < GLctx.getProgramParameter(program, 35721); ++i) {
  9753.                     program.maxAttributeLength = Math.max(program.maxAttributeLength, GLctx.getActiveAttrib(program, i).name.length + 1);
  9754.                 }
  9755.             }
  9756.             HEAP32[p >> 2] = program.maxAttributeLength;
  9757.         } else if (pname == 35381) {
  9758.             if (!program.maxUniformBlockNameLength) {
  9759.                 for (var i = 0; i < GLctx.getProgramParameter(program, 35382); ++i) {
  9760.                     program.maxUniformBlockNameLength = Math.max(program.maxUniformBlockNameLength, GLctx.getActiveUniformBlockName(program, i).length + 1);
  9761.                 }
  9762.             }
  9763.             HEAP32[p >> 2] = program.maxUniformBlockNameLength;
  9764.         } else {
  9765.             HEAP32[p >> 2] = GLctx.getProgramParameter(program, pname);
  9766.         }
  9767.     }
  9768.     function _glGetQueryObjectuiv(id, pname, params) {
  9769.         if (!params) {
  9770.             GL.recordError(1281);
  9771.             return;
  9772.         }
  9773.         var query = GL.queries[id];
  9774.         var param = GLctx["getQueryParameter"](query, pname);
  9775.         var ret;
  9776.         if (typeof param == "boolean") {
  9777.             ret = param ? 1 : 0;
  9778.         } else {
  9779.             ret = param;
  9780.         }
  9781.         HEAP32[params >> 2] = ret;
  9782.     }
  9783.     function _glGetQueryiv(target, pname, params) {
  9784.         if (!params) {
  9785.             GL.recordError(1281);
  9786.             return;
  9787.         }
  9788.         HEAP32[params >> 2] = GLctx["getQuery"](target, pname);
  9789.     }
  9790.     function _glGetRenderbufferParameteriv(target, pname, params) {
  9791.         if (!params) {
  9792.             GL.recordError(1281);
  9793.             return;
  9794.         }
  9795.         HEAP32[params >> 2] = GLctx.getRenderbufferParameter(target, pname);
  9796.     }
  9797.     function _glGetShaderInfoLog(shader, maxLength, length, infoLog) {
  9798.         var log = GLctx.getShaderInfoLog(GL.shaders[shader]);
  9799.         if (log === null) log = "(unknown error)";
  9800.         var numBytesWrittenExclNull = maxLength > 0 && infoLog ? stringToUTF8(log, infoLog, maxLength) : 0;
  9801.         if (length) HEAP32[length >> 2] = numBytesWrittenExclNull;
  9802.     }
  9803.     function _glGetShaderPrecisionFormat(shaderType, precisionType, range, precision) {
  9804.         var result = GLctx.getShaderPrecisionFormat(shaderType, precisionType);
  9805.         HEAP32[range >> 2] = result.rangeMin;
  9806.         HEAP32[(range + 4) >> 2] = result.rangeMax;
  9807.         HEAP32[precision >> 2] = result.precision;
  9808.     }
  9809.     function _glGetShaderSource(shader, bufSize, length, source) {
  9810.         var result = GLctx.getShaderSource(GL.shaders[shader]);
  9811.         if (!result) return;
  9812.         var numBytesWrittenExclNull = bufSize > 0 && source ? stringToUTF8(result, source, bufSize) : 0;
  9813.         if (length) HEAP32[length >> 2] = numBytesWrittenExclNull;
  9814.     }
  9815.     function _glGetShaderiv(shader, pname, p) {
  9816.         if (!p) {
  9817.             GL.recordError(1281);
  9818.             return;
  9819.         }
  9820.         if (pname == 35716) {
  9821.             var log = GLctx.getShaderInfoLog(GL.shaders[shader]);
  9822.             if (log === null) log = "(unknown error)";
  9823.             var logLength = log ? log.length + 1 : 0;
  9824.             HEAP32[p >> 2] = logLength;
  9825.         } else if (pname == 35720) {
  9826.             var source = GLctx.getShaderSource(GL.shaders[shader]);
  9827.             var sourceLength = source ? source.length + 1 : 0;
  9828.             HEAP32[p >> 2] = sourceLength;
  9829.         } else {
  9830.             HEAP32[p >> 2] = GLctx.getShaderParameter(GL.shaders[shader], pname);
  9831.         }
  9832.     }
  9833.     function _glGetString(name_) {
  9834.         var ret = GL.stringCache[name_];
  9835.         if (!ret) {
  9836.             switch (name_) {
  9837.                 case 7939:
  9838.                     var exts = GLctx.getSupportedExtensions() || [];
  9839.                     exts = exts.concat(
  9840.                         exts.map(function (e) {
  9841.                             return "GL_" + e;
  9842.                         })
  9843.                     );
  9844.                     ret = stringToNewUTF8(exts.join(" "));
  9845.                     break;
  9846.                 case 7936:
  9847.                 case 7937:
  9848.                 case 37445:
  9849.                 case 37446:
  9850.                     var s = GLctx.getParameter(name_);
  9851.                     if (!s) {
  9852.                         GL.recordError(1280);
  9853.                     }
  9854.                     ret = s && stringToNewUTF8(s);
  9855.                     break;
  9856.                 case 7938:
  9857.                     var glVersion = GLctx.getParameter(7938);
  9858.                     if (GL.currentContext.version >= 2) glVersion = "OpenGL ES 3.0 (" + glVersion + ")";
  9859.                     else {
  9860.                         glVersion = "OpenGL ES 2.0 (" + glVersion + ")";
  9861.                     }
  9862.                     ret = stringToNewUTF8(glVersion);
  9863.                     break;
  9864.                 case 35724:
  9865.                     var glslVersion = GLctx.getParameter(35724);
  9866.                     var ver_re = /^WebGL GLSL ES ([0-9]\.[0-9][0-9]?)(?:$| .*)/;
  9867.                     var ver_num = glslVersion.match(ver_re);
  9868.                     if (ver_num !== null) {
  9869.                         if (ver_num[1].length == 3) ver_num[1] = ver_num[1] + "0";
  9870.                         glslVersion = "OpenGL ES GLSL ES " + ver_num[1] + " (" + glslVersion + ")";
  9871.                     }
  9872.                     ret = stringToNewUTF8(glslVersion);
  9873.                     break;
  9874.                 default:
  9875.                     GL.recordError(1280);
  9876.             }
  9877.             GL.stringCache[name_] = ret;
  9878.         }
  9879.         return ret;
  9880.     }
  9881.     function _glGetStringi(name, index) {
  9882.         if (GL.currentContext.version < 2) {
  9883.             GL.recordError(1282);
  9884.             return 0;
  9885.         }
  9886.         var stringiCache = GL.stringiCache[name];
  9887.         if (stringiCache) {
  9888.             if (index < 0 || index >= stringiCache.length) {
  9889.                 GL.recordError(1281);
  9890.                 return 0;
  9891.             }
  9892.             return stringiCache[index];
  9893.         }
  9894.         switch (name) {
  9895.             case 7939:
  9896.                 var exts = GLctx.getSupportedExtensions() || [];
  9897.                 exts = exts.concat(
  9898.                     exts.map(function (e) {
  9899.                         return "GL_" + e;
  9900.                     })
  9901.                 );
  9902.                 exts = exts.map(function (e) {
  9903.                     return stringToNewUTF8(e);
  9904.                 });
  9905.                 stringiCache = GL.stringiCache[name] = exts;
  9906.                 if (index < 0 || index >= stringiCache.length) {
  9907.                     GL.recordError(1281);
  9908.                     return 0;
  9909.                 }
  9910.                 return stringiCache[index];
  9911.             default:
  9912.                 GL.recordError(1280);
  9913.                 return 0;
  9914.         }
  9915.     }
  9916.     function _glGetTexParameteriv(target, pname, params) {
  9917.         if (!params) {
  9918.             GL.recordError(1281);
  9919.             return;
  9920.         }
  9921.         HEAP32[params >> 2] = GLctx.getTexParameter(target, pname);
  9922.     }
  9923.     function _glGetUniformBlockIndex(program, uniformBlockName) {
  9924.         return GLctx["getUniformBlockIndex"](GL.programs[program], UTF8ToString(uniformBlockName));
  9925.     }
  9926.     function _glGetUniformIndices(program, uniformCount, uniformNames, uniformIndices) {
  9927.         if (!uniformIndices) {
  9928.             GL.recordError(1281);
  9929.             return;
  9930.         }
  9931.         if (uniformCount > 0 && (uniformNames == 0 || uniformIndices == 0)) {
  9932.             GL.recordError(1281);
  9933.             return;
  9934.         }
  9935.         program = GL.programs[program];
  9936.         var names = [];
  9937.         for (var i = 0; i < uniformCount; i++) names.push(UTF8ToString(HEAP32[(uniformNames + i * 4) >> 2]));
  9938.         var result = GLctx["getUniformIndices"](program, names);
  9939.         if (!result) return;
  9940.         var len = result.length;
  9941.         for (var i = 0; i < len; i++) {
  9942.             HEAP32[(uniformIndices + i * 4) >> 2] = result[i];
  9943.         }
  9944.     }
  9945.     function _glGetUniformLocation(program, name) {
  9946.         function getLeftBracePos(name) {
  9947.             return name.slice(-1) == "]" && name.lastIndexOf("[");
  9948.         }
  9949.         name = UTF8ToString(name);
  9950.         if ((program = GL.programs[program])) {
  9951.             var uniformLocsById = program.uniformLocsById;
  9952.             var uniformSizeAndIdsByName = program.uniformSizeAndIdsByName;
  9953.             var i, j;
  9954.             var arrayIndex = 0;
  9955.             var uniformBaseName = name;
  9956.             var leftBrace = getLeftBracePos(name);
  9957.             if (!uniformLocsById) {
  9958.                 program.uniformLocsById = uniformLocsById = {};
  9959.                 program.uniformArrayNamesById = {};
  9960.                 for (i = 0; i < GLctx.getProgramParameter(program, 35718); ++i) {
  9961.                     var u = GLctx.getActiveUniform(program, i);
  9962.                     var nm = u.name;
  9963.                     var sz = u.size;
  9964.                     var lb = getLeftBracePos(nm);
  9965.                     var arrayName = lb > 0 ? nm.slice(0, lb) : nm;
  9966.                     var id = uniformSizeAndIdsByName[arrayName] ? uniformSizeAndIdsByName[arrayName][1] : program.uniformIdCounter;
  9967.                     program.uniformIdCounter = Math.max(id + sz, program.uniformIdCounter);
  9968.                     uniformSizeAndIdsByName[arrayName] = [sz, id];
  9969.                     for (j = 0; j < sz; ++j) {
  9970.                         uniformLocsById[id] = j;
  9971.                         program.uniformArrayNamesById[id++] = arrayName;
  9972.                     }
  9973.                 }
  9974.             }
  9975.             if (leftBrace > 0) {
  9976.                 arrayIndex = jstoi_q(name.slice(leftBrace + 1)) >>> 0;
  9977.                 uniformBaseName = name.slice(0, leftBrace);
  9978.             }
  9979.             var sizeAndId = uniformSizeAndIdsByName[uniformBaseName];
  9980.             if (sizeAndId && arrayIndex < sizeAndId[0]) {
  9981.                 arrayIndex += sizeAndId[1];
  9982.                 if ((uniformLocsById[arrayIndex] = uniformLocsById[arrayIndex] || GLctx.getUniformLocation(program, name))) {
  9983.                     return arrayIndex;
  9984.                 }
  9985.             }
  9986.         } else {
  9987.             GL.recordError(1281);
  9988.         }
  9989.         return -1;
  9990.     }
  9991.     function webglGetUniformLocation(location) {
  9992.         var p = GLctx.currentProgram;
  9993.         if (p) {
  9994.             var webglLoc = p.uniformLocsById[location];
  9995.             if (typeof webglLoc === "number") {
  9996.                 p.uniformLocsById[location] = webglLoc = GLctx.getUniformLocation(p, p.uniformArrayNamesById[location] + (webglLoc > 0 ? "[" + webglLoc + "]" : ""));
  9997.             }
  9998.             return webglLoc;
  9999.         } else {
  10000.             GL.recordError(1282);
  10001.         }
  10002.     }
  10003.     function emscriptenWebGLGetUniform(program, location, params, type) {
  10004.         if (!params) {
  10005.             GL.recordError(1281);
  10006.             return;
  10007.         }
  10008.         program = GL.programs[program];
  10009.         var data = GLctx.getUniform(program, webglGetUniformLocation(location));
  10010.         if (typeof data == "number" || typeof data == "boolean") {
  10011.             switch (type) {
  10012.                 case 0:
  10013.                     HEAP32[params >> 2] = data;
  10014.                     break;
  10015.                 case 2:
  10016.                     HEAPF32[params >> 2] = data;
  10017.                     break;
  10018.             }
  10019.         } else {
  10020.             for (var i = 0; i < data.length; i++) {
  10021.                 switch (type) {
  10022.                     case 0:
  10023.                         HEAP32[(params + i * 4) >> 2] = data[i];
  10024.                         break;
  10025.                     case 2:
  10026.                         HEAPF32[(params + i * 4) >> 2] = data[i];
  10027.                         break;
  10028.                 }
  10029.             }
  10030.         }
  10031.     }
  10032.     function _glGetUniformiv(program, location, params) {
  10033.         emscriptenWebGLGetUniform(program, location, params, 0);
  10034.     }
  10035.     function emscriptenWebGLGetVertexAttrib(index, pname, params, type) {
  10036.         if (!params) {
  10037.             GL.recordError(1281);
  10038.             return;
  10039.         }
  10040.         if (GL.currentContext.clientBuffers[index].enabled) {
  10041.             err("glGetVertexAttrib*v on client-side array: not supported, bad data returned");
  10042.         }
  10043.         var data = GLctx.getVertexAttrib(index, pname);
  10044.         if (pname == 34975) {
  10045.             HEAP32[params >> 2] = data && data["name"];
  10046.         } else if (typeof data == "number" || typeof data == "boolean") {
  10047.             switch (type) {
  10048.                 case 0:
  10049.                     HEAP32[params >> 2] = data;
  10050.                     break;
  10051.                 case 2:
  10052.                     HEAPF32[params >> 2] = data;
  10053.                     break;
  10054.                 case 5:
  10055.                     HEAP32[params >> 2] = Math.fround(data);
  10056.                     break;
  10057.             }
  10058.         } else {
  10059.             for (var i = 0; i < data.length; i++) {
  10060.                 switch (type) {
  10061.                     case 0:
  10062.                         HEAP32[(params + i * 4) >> 2] = data[i];
  10063.                         break;
  10064.                     case 2:
  10065.                         HEAPF32[(params + i * 4) >> 2] = data[i];
  10066.                         break;
  10067.                     case 5:
  10068.                         HEAP32[(params + i * 4) >> 2] = Math.fround(data[i]);
  10069.                         break;
  10070.                 }
  10071.             }
  10072.         }
  10073.     }
  10074.     function _glGetVertexAttribiv(index, pname, params) {
  10075.         emscriptenWebGLGetVertexAttrib(index, pname, params, 5);
  10076.     }
  10077.     function _glInvalidateFramebuffer(target, numAttachments, attachments) {
  10078.         var list = tempFixedLengthArray[numAttachments];
  10079.         for (var i = 0; i < numAttachments; i++) {
  10080.             list[i] = HEAP32[(attachments + i * 4) >> 2];
  10081.         }
  10082.         GLctx["invalidateFramebuffer"](target, list);
  10083.     }
  10084.     function _glIsEnabled(x0) {
  10085.         return GLctx["isEnabled"](x0);
  10086.     }
  10087.     function _glIsVertexArray(array) {
  10088.         var vao = GL.vaos[array];
  10089.         if (!vao) return 0;
  10090.         return GLctx["isVertexArray"](vao);
  10091.     }
  10092.     function _glLinkProgram(program) {
  10093.         program = GL.programs[program];
  10094.         GLctx.linkProgram(program);
  10095.         program.uniformLocsById = 0;
  10096.         program.uniformSizeAndIdsByName = {};
  10097.         [program["vs"], program["fs"]].forEach(function (s) {
  10098.             Object.keys(s.explicitUniformLocations).forEach(function (shaderLocation) {
  10099.                 var loc = s.explicitUniformLocations[shaderLocation];
  10100.                 program.uniformSizeAndIdsByName[shaderLocation] = [1, loc];
  10101.                 program.uniformIdCounter = Math.max(program.uniformIdCounter, loc + 1);
  10102.             });
  10103.         });
  10104.         function copyKeys(dst, src) {
  10105.             Object.keys(src).forEach(function (key) {
  10106.                 dst[key] = src[key];
  10107.             });
  10108.         }
  10109.         program.explicitUniformBindings = {};
  10110.         program.explicitSamplerBindings = {};
  10111.         [program["vs"], program["fs"]].forEach(function (s) {
  10112.             copyKeys(program.explicitUniformBindings, s.explicitUniformBindings);
  10113.             copyKeys(program.explicitSamplerBindings, s.explicitSamplerBindings);
  10114.         });
  10115.         program.explicitProgramBindingsApplied = 0;
  10116.     }
  10117.     function _glMapBufferRange(target, offset, length, access) {
  10118.         if (access != 26 && access != 10) {
  10119.             err("glMapBufferRange is only supported when access is MAP_WRITE|INVALIDATE_BUFFER");
  10120.             return 0;
  10121.         }
  10122.         if (!emscriptenWebGLValidateMapBufferTarget(target)) {
  10123.             GL.recordError(1280);
  10124.             err("GL_INVALID_ENUM in glMapBufferRange");
  10125.             return 0;
  10126.         }
  10127.         var mem = _malloc(length);
  10128.         if (!mem) return 0;
  10129.         GL.mappedBuffers[emscriptenWebGLGetBufferBinding(target)] = { offset: offset, length: length, mem: mem, access: access };
  10130.         return mem;
  10131.     }
  10132.     function _glPixelStorei(pname, param) {
  10133.         if (pname == 3317) {
  10134.             GL.unpackAlignment = param;
  10135.         }
  10136.         GLctx.pixelStorei(pname, param);
  10137.     }
  10138.     function _glPolygonOffset(x0, x1) {
  10139.         GLctx["polygonOffset"](x0, x1);
  10140.     }
  10141.     function _glProgramBinary(program, binaryFormat, binary, length) {
  10142.         GL.recordError(1280);
  10143.     }
  10144.     function _glProgramParameteri(program, pname, value) {
  10145.         GL.recordError(1280);
  10146.     }
  10147.     function _glReadBuffer(x0) {
  10148.         GLctx["readBuffer"](x0);
  10149.     }
  10150.     function computeUnpackAlignedImageSize(width, height, sizePerPixel, alignment) {
  10151.         function roundedToNextMultipleOf(x, y) {
  10152.             return (x + y - 1) & -y;
  10153.         }
  10154.         var plainRowSize = width * sizePerPixel;
  10155.         var alignedRowSize = roundedToNextMultipleOf(plainRowSize, alignment);
  10156.         return height * alignedRowSize;
  10157.     }
  10158.     function __colorChannelsInGlTextureFormat(format) {
  10159.         var colorChannels = { 5: 3, 6: 4, 8: 2, 29502: 3, 29504: 4, 26917: 2, 26918: 2, 29846: 3, 29847: 4 };
  10160.         return colorChannels[format - 6402] || 1;
  10161.     }
  10162.     function heapObjectForWebGLType(type) {
  10163.         type -= 5120;
  10164.         if (type == 0) return HEAP8;
  10165.         if (type == 1) return HEAPU8;
  10166.         if (type == 2) return HEAP16;
  10167.         if (type == 4) return HEAP32;
  10168.         if (type == 6) return HEAPF32;
  10169.         if (type == 5 || type == 28922 || type == 28520 || type == 30779 || type == 30782) return HEAPU32;
  10170.         return HEAPU16;
  10171.     }
  10172.     function heapAccessShiftForWebGLHeap(heap) {
  10173.         return 31 - Math.clz32(heap.BYTES_PER_ELEMENT);
  10174.     }
  10175.     function emscriptenWebGLGetTexPixelData(type, format, width, height, pixels, internalFormat) {
  10176.         var heap = heapObjectForWebGLType(type);
  10177.         var shift = heapAccessShiftForWebGLHeap(heap);
  10178.         var byteSize = 1 << shift;
  10179.         var sizePerPixel = __colorChannelsInGlTextureFormat(format) * byteSize;
  10180.         var bytes = computeUnpackAlignedImageSize(width, height, sizePerPixel, GL.unpackAlignment);
  10181.         return heap.subarray(pixels >> shift, (pixels + bytes) >> shift);
  10182.     }
  10183.     function _glReadPixels(x, y, width, height, format, type, pixels) {
  10184.         if (GL.currentContext.version >= 2) {
  10185.             if (GLctx.currentPixelPackBufferBinding) {
  10186.                 GLctx.readPixels(x, y, width, height, format, type, pixels);
  10187.             } else {
  10188.                 var heap = heapObjectForWebGLType(type);
  10189.                 GLctx.readPixels(x, y, width, height, format, type, heap, pixels >> heapAccessShiftForWebGLHeap(heap));
  10190.             }
  10191.             return;
  10192.         }
  10193.         var pixelData = emscriptenWebGLGetTexPixelData(type, format, width, height, pixels, format);
  10194.         if (!pixelData) {
  10195.             GL.recordError(1280);
  10196.             return;
  10197.         }
  10198.         GLctx.readPixels(x, y, width, height, format, type, pixelData);
  10199.     }
  10200.     function _glRenderbufferStorage(x0, x1, x2, x3) {
  10201.         GLctx["renderbufferStorage"](x0, x1, x2, x3);
  10202.     }
  10203.     function _glRenderbufferStorageMultisample(x0, x1, x2, x3, x4) {
  10204.         GLctx["renderbufferStorageMultisample"](x0, x1, x2, x3, x4);
  10205.     }
  10206.     function _glSamplerParameteri(sampler, pname, param) {
  10207.         GLctx["samplerParameteri"](GL.samplers[sampler], pname, param);
  10208.     }
  10209.     function _glScissor(x0, x1, x2, x3) {
  10210.         GLctx["scissor"](x0, x1, x2, x3);
  10211.     }
  10212.     function find_closing_parens_index(arr, i, opening = "(", closing = ")") {
  10213.         for (var nesting = 0; i < arr.length; ++i) {
  10214.             if (arr[i] == opening) ++nesting;
  10215.             if (arr[i] == closing && --nesting == 0) {
  10216.                 return i;
  10217.             }
  10218.         }
  10219.     }
  10220.     function preprocess_c_code(code) {
  10221.         var i = 0,
  10222.             len = code.length,
  10223.             out = "",
  10224.             stack = [1],
  10225.             defs = {
  10226.                 defined: function (args) {
  10227.                     return defs[args[0]] ? 1 : 0;
  10228.                 },
  10229.                 GL_FRAGMENT_PRECISION_HIGH: function () {
  10230.                     return 1;
  10231.                 },
  10232.             };
  10233.         function isWhitespace(str, i) {
  10234.             return !(str.charCodeAt(i) > 32);
  10235.         }
  10236.         function nextWhitespace(str, i) {
  10237.             while (!isWhitespace(str, i)) ++i;
  10238.             return i;
  10239.         }
  10240.         function classifyChar(str, idx) {
  10241.             var cc = str.charCodeAt(idx);
  10242.             if (cc > 32) {
  10243.                 if (cc < 48) return 1;
  10244.                 if (cc < 58) return 2;
  10245.                 if (cc < 65) return 1;
  10246.                 if (cc < 91 || cc == 95) return 3;
  10247.                 if (cc < 97) return 1;
  10248.                 if (cc < 123) return 3;
  10249.                 return 1;
  10250.             }
  10251.             return cc < 33 ? 0 : 4;
  10252.         }
  10253.         function tokenize(exprString, keepWhitespace) {
  10254.             var out = [],
  10255.                 len = exprString.length;
  10256.             for (var i = 0; i <= len; ++i) {
  10257.                 var kind = classifyChar(exprString, i);
  10258.                 if (kind == 2 || kind == 3) {
  10259.                     for (var j = i + 1; j <= len; ++j) {
  10260.                         var kind2 = classifyChar(exprString, j);
  10261.                         if (kind2 != kind && (kind2 != 2 || kind != 3)) {
  10262.                             out.push(exprString.substring(i, j));
  10263.                             i = j - 1;
  10264.                             break;
  10265.                         }
  10266.                     }
  10267.                 } else if (kind == 1) {
  10268.                     var op2 = exprString.substr(i, 2);
  10269.                     if (["<=", ">=", "==", "!=", "&&", "||"].includes(op2)) {
  10270.                         out.push(op2);
  10271.                         ++i;
  10272.                     } else {
  10273.                         out.push(exprString[i]);
  10274.                     }
  10275.                 }
  10276.             }
  10277.             return out;
  10278.         }
  10279.         function expandMacros(str, lineStart, lineEnd) {
  10280.             if (lineEnd === undefined) lineEnd = str.length;
  10281.             var len = str.length;
  10282.             var out = "";
  10283.             for (var i = lineStart; i < lineEnd; ++i) {
  10284.                 var kind = classifyChar(str, i);
  10285.                 if (kind == 3) {
  10286.                     for (var j = i + 1; j <= lineEnd; ++j) {
  10287.                         var kind2 = classifyChar(str, j);
  10288.                         if (kind2 != 2 && kind2 != 3) {
  10289.                             var symbol = str.substring(i, j);
  10290.                             var pp = defs[symbol];
  10291.                             if (pp) {
  10292.                                 var expanded = str.substring(lineStart, i);
  10293.                                 if (pp.length && str[j] == "(") {
  10294.                                     var closeParens = find_closing_parens_index(str, j);
  10295.                                     expanded += pp(str.substring(j + 1, closeParens).split(",")) + str.substring(closeParens + 1, lineEnd);
  10296.                                 } else {
  10297.                                     expanded += pp() + str.substring(j, lineEnd);
  10298.                                 }
  10299.                                 return expandMacros(expanded, 0);
  10300.                             } else {
  10301.                                 out += symbol;
  10302.                                 i = j - 1;
  10303.                                 break;
  10304.                             }
  10305.                         }
  10306.                     }
  10307.                 } else {
  10308.                     out += str[i];
  10309.                 }
  10310.             }
  10311.             return out;
  10312.         }
  10313.         function buildExprTree(tokens) {
  10314.             while (tokens.length > 1 || typeof tokens[0] != "function") {
  10315.                 tokens = (function (tokens) {
  10316.                     var i,
  10317.                         j,
  10318.                         p,
  10319.                         operatorAndPriority = -2;
  10320.                     for (j = 0; j < tokens.length; ++j) {
  10321.                         if ((p = ["*", "/", "+", "-", "!", "<", "<=", ">", ">=", "==", "!=", "&&", "||", "("].indexOf(tokens[j])) > operatorAndPriority) {
  10322.                             i = j;
  10323.                             operatorAndPriority = p;
  10324.                         }
  10325.                     }
  10326.                     if (operatorAndPriority == 13) {
  10327.                         var j = find_closing_parens_index(tokens, i);
  10328.                         if (j) {
  10329.                             tokens.splice(i, j + 1 - i, buildExprTree(tokens.slice(i + 1, j)));
  10330.                             return tokens;
  10331.                         }
  10332.                     }
  10333.                     if (operatorAndPriority == 4) {
  10334.                         i = tokens.lastIndexOf("!");
  10335.                         var innerExpr = buildExprTree(tokens.slice(i + 1, i + 2));
  10336.                         tokens.splice(i, 2, function () {
  10337.                             return !innerExpr();
  10338.                         });
  10339.                         return tokens;
  10340.                     }
  10341.                     if (operatorAndPriority >= 0) {
  10342.                         var left = buildExprTree(tokens.slice(0, i));
  10343.                         var right = buildExprTree(tokens.slice(i + 1));
  10344.                         switch (tokens[i]) {
  10345.                             case "&&":
  10346.                                 return [
  10347.                                     function () {
  10348.                                         return left() && right();
  10349.                                     },
  10350.                                 ];
  10351.                             case "||":
  10352.                                 return [
  10353.                                     function () {
  10354.                                         return left() || right();
  10355.                                     },
  10356.                                 ];
  10357.                             case "==":
  10358.                                 return [
  10359.                                     function () {
  10360.                                         return left() == right();
  10361.                                     },
  10362.                                 ];
  10363.                             case "!=":
  10364.                                 return [
  10365.                                     function () {
  10366.                                         return left() != right();
  10367.                                     },
  10368.                                 ];
  10369.                             case "<":
  10370.                                 return [
  10371.                                     function () {
  10372.                                         return left() < right();
  10373.                                     },
  10374.                                 ];
  10375.                             case "<=":
  10376.                                 return [
  10377.                                     function () {
  10378.                                         return left() <= right();
  10379.                                     },
  10380.                                 ];
  10381.                             case ">":
  10382.                                 return [
  10383.                                     function () {
  10384.                                         return left() > right();
  10385.                                     },
  10386.                                 ];
  10387.                             case ">=":
  10388.                                 return [
  10389.                                     function () {
  10390.                                         return left() >= right();
  10391.                                     },
  10392.                                 ];
  10393.                             case "+":
  10394.                                 return [
  10395.                                     function () {
  10396.                                         return left() + right();
  10397.                                     },
  10398.                                 ];
  10399.                             case "-":
  10400.                                 return [
  10401.                                     function () {
  10402.                                         return left() - right();
  10403.                                     },
  10404.                                 ];
  10405.                             case "*":
  10406.                                 return [
  10407.                                     function () {
  10408.                                         return left() * right();
  10409.                                     },
  10410.                                 ];
  10411.                             case "/":
  10412.                                 return [
  10413.                                     function () {
  10414.                                         return Math.floor(left() / right());
  10415.                                     },
  10416.                                 ];
  10417.                         }
  10418.                     }
  10419.                     var num = jstoi_q(tokens[i]);
  10420.                     return [
  10421.                         function () {
  10422.                             return num;
  10423.                         },
  10424.                     ];
  10425.                 })(tokens);
  10426.             }
  10427.             return tokens[0];
  10428.         }
  10429.         for (; i < len; ++i) {
  10430.             var lineStart = i;
  10431.             i = code.indexOf("\n", i);
  10432.             if (i < 0) i = len;
  10433.             for (var j = lineStart; j < i && isWhitespace(code, j); ++j);
  10434.             var thisLineIsInActivePreprocessingBlock = stack[stack.length - 1];
  10435.             if (code[j] != "#") {
  10436.                 if (thisLineIsInActivePreprocessingBlock) {
  10437.                     out += expandMacros(code, lineStart, i) + "\n";
  10438.                 }
  10439.                 continue;
  10440.             }
  10441.             var space = nextWhitespace(code, j);
  10442.             var directive = code.substring(j + 1, space);
  10443.             var expression = code.substring(space, i).trim();
  10444.             switch (directive) {
  10445.                 case "if":
  10446.                     var tokens = tokenize(expandMacros(expression, 0));
  10447.                     var exprTree = buildExprTree(tokens);
  10448.                     var evaluated = exprTree();
  10449.                     stack.push(!!evaluated * stack[stack.length - 1]);
  10450.                     break;
  10451.                 case "ifdef":
  10452.                     stack.push(!!defs[expression] * stack[stack.length - 1]);
  10453.                     break;
  10454.                 case "ifndef":
  10455.                     stack.push(!defs[expression] * stack[stack.length - 1]);
  10456.                     break;
  10457.                 case "else":
  10458.                     stack[stack.length - 1] = 1 - stack[stack.length - 1];
  10459.                     break;
  10460.                 case "endif":
  10461.                     stack.pop();
  10462.                     break;
  10463.                 case "define":
  10464.                     if (thisLineIsInActivePreprocessingBlock) {
  10465.                         var macroStart = expression.indexOf("(");
  10466.                         var firstWs = nextWhitespace(expression, 0);
  10467.                         if (firstWs < macroStart) macroStart = 0;
  10468.                         if (macroStart > 0) {
  10469.                             var macroEnd = expression.indexOf(")", macroStart);
  10470.                             let params = expression
  10471.                                 .substring(macroStart + 1, macroEnd)
  10472.                                 .split(",")
  10473.                                 .map((x) => x.trim());
  10474.                             let value = tokenize(expression.substring(macroEnd + 1).trim());
  10475.                             defs[expression.substring(0, macroStart)] = function (args) {
  10476.                                 var ret = "";
  10477.                                 value.forEach((x) => {
  10478.                                     var argIndex = params.indexOf(x);
  10479.                                     ret += argIndex >= 0 ? args[argIndex] : x;
  10480.                                 });
  10481.                                 return ret;
  10482.                             };
  10483.                         } else {
  10484.                             let value = expandMacros(expression.substring(firstWs + 1).trim(), 0);
  10485.                             defs[expression.substring(0, firstWs)] = function () {
  10486.                                 return value;
  10487.                             };
  10488.                         }
  10489.                     }
  10490.                     break;
  10491.                 case "undef":
  10492.                     if (thisLineIsInActivePreprocessingBlock) delete defs[expression];
  10493.                     break;
  10494.                 default:
  10495.                     if (directive != "version" && directive != "pragma" && directive != "extension") {
  10496.                     }
  10497.                     out += expandMacros(code, lineStart, i) + "\n";
  10498.             }
  10499.         }
  10500.         return out;
  10501.     }
  10502.     function remove_cpp_comments_in_shaders(code) {
  10503.         var i = 0,
  10504.             out = "",
  10505.             ch,
  10506.             next,
  10507.             len = code.length;
  10508.         for (; i < len; ++i) {
  10509.             ch = code[i];
  10510.             if (ch == "/") {
  10511.                 next = code[i + 1];
  10512.                 if (next == "/") {
  10513.                     while (i < len && code[i + 1] != "\n") ++i;
  10514.                 } else if (next == "*") {
  10515.                     while (i < len && (code[i - 1] != "*" || code[i] != "/")) ++i;
  10516.                 } else {
  10517.                     out += ch;
  10518.                 }
  10519.             } else {
  10520.                 out += ch;
  10521.             }
  10522.         }
  10523.         return out;
  10524.     }
  10525.     function _glShaderSource(shader, count, string, length) {
  10526.         var source = GL.getSource(shader, count, string, length);
  10527.         source = preprocess_c_code(remove_cpp_comments_in_shaders(source));
  10528.         var regex = /layout\s*\(\s*location\s*=\s*(-?\d+)\s*\)\s*(uniform\s+((lowp|mediump|highp)\s+)?\w+\s+(\w+))/g,
  10529.             explicitUniformLocations = {},
  10530.             match;
  10531.         while ((match = regex.exec(source))) {
  10532.             explicitUniformLocations[match[5]] = jstoi_q(match[1]);
  10533.             if (!(explicitUniformLocations[match[5]] >= 0 && explicitUniformLocations[match[5]] < 1048576)) {
  10534.                 console.error('Specified an out of range layout(location=x) directive "' + explicitUniformLocations[match[5]] + '"! (' + match[0] + ")");
  10535.                 GL.recordError(1281);
  10536.                 return;
  10537.             }
  10538.         }
  10539.         source = source.replace(regex, "$2");
  10540.         GL.shaders[shader].explicitUniformLocations = explicitUniformLocations;
  10541.         var bindingRegex = /layout\s*\(.*?binding\s*=\s*(-?\d+).*?\)\s*uniform\s+(\w+)\s+(\w+)?/g,
  10542.             samplerBindings = {},
  10543.             uniformBindings = {},
  10544.             bindingMatch;
  10545.         while ((bindingMatch = bindingRegex.exec(source))) {
  10546.             var arrayLength = 1;
  10547.             for (var i = bindingMatch.index; i < source.length && source[i] != ";"; ++i) {
  10548.                 if (source[i] == "[") {
  10549.                     arrayLength = jstoi_q(source.slice(i + 1));
  10550.                     break;
  10551.                 }
  10552.                 if (source[i] == "{") i = find_closing_parens_index(source, i, "{", "}") - 1;
  10553.             }
  10554.             var binding = jstoi_q(bindingMatch[1]);
  10555.             var bindingsType = 34930;
  10556.             if (bindingMatch[3] && bindingMatch[2].indexOf("sampler") != -1) {
  10557.                 samplerBindings[bindingMatch[3]] = [binding, arrayLength];
  10558.             } else {
  10559.                 bindingsType = 35374;
  10560.                 uniformBindings[bindingMatch[2]] = [binding, arrayLength];
  10561.             }
  10562.             var numBindingPoints = GLctx.getParameter(bindingsType);
  10563.             if (!(binding >= 0 && binding + arrayLength <= numBindingPoints)) {
  10564.                 console.error('Specified an out of range layout(binding=x) directive "' + binding + '"! (' + bindingMatch[0] + "). Valid range is [0, " + numBindingPoints + "-1]");
  10565.                 GL.recordError(1281);
  10566.                 return;
  10567.             }
  10568.         }
  10569.         source = source.replace(/layout\s*\(.*?binding\s*=\s*([-\d]+).*?\)/g, "");
  10570.         source = source.replace(/(layout\s*\((.*?)),\s*binding\s*=\s*([-\d]+)\)/g, "$1)");
  10571.         source = source.replace(/layout\s*\(\s*binding\s*=\s*([-\d]+)\s*,(.*?)\)/g, "layout($2)");
  10572.         GL.shaders[shader].explicitSamplerBindings = samplerBindings;
  10573.         GL.shaders[shader].explicitUniformBindings = uniformBindings;
  10574.         GLctx.shaderSource(GL.shaders[shader], source);
  10575.     }
  10576.     function _glStencilFuncSeparate(x0, x1, x2, x3) {
  10577.         GLctx["stencilFuncSeparate"](x0, x1, x2, x3);
  10578.     }
  10579.     function _glStencilMask(x0) {
  10580.         GLctx["stencilMask"](x0);
  10581.     }
  10582.     function _glStencilOpSeparate(x0, x1, x2, x3) {
  10583.         GLctx["stencilOpSeparate"](x0, x1, x2, x3);
  10584.     }
  10585.     function _glTexImage2D(target, level, internalFormat, width, height, border, format, type, pixels) {
  10586.         if (GL.currentContext.version >= 2) {
  10587.             if (GLctx.currentPixelUnpackBufferBinding) {
  10588.                 GLctx.texImage2D(target, level, internalFormat, width, height, border, format, type, pixels);
  10589.             } else if (pixels) {
  10590.                 var heap = heapObjectForWebGLType(type);
  10591.                 GLctx.texImage2D(target, level, internalFormat, width, height, border, format, type, heap, pixels >> heapAccessShiftForWebGLHeap(heap));
  10592.             } else {
  10593.                 GLctx.texImage2D(target, level, internalFormat, width, height, border, format, type, null);
  10594.             }
  10595.             return;
  10596.         }
  10597.         GLctx.texImage2D(target, level, internalFormat, width, height, border, format, type, pixels ? emscriptenWebGLGetTexPixelData(type, format, width, height, pixels, internalFormat) : null);
  10598.     }
  10599.     function _glTexImage3D(target, level, internalFormat, width, height, depth, border, format, type, pixels) {
  10600.         if (GLctx.currentPixelUnpackBufferBinding) {
  10601.             GLctx["texImage3D"](target, level, internalFormat, width, height, depth, border, format, type, pixels);
  10602.         } else if (pixels) {
  10603.             var heap = heapObjectForWebGLType(type);
  10604.             GLctx["texImage3D"](target, level, internalFormat, width, height, depth, border, format, type, heap, pixels >> heapAccessShiftForWebGLHeap(heap));
  10605.         } else {
  10606.             GLctx["texImage3D"](target, level, internalFormat, width, height, depth, border, format, type, null);
  10607.         }
  10608.     }
  10609.     function _glTexParameterf(x0, x1, x2) {
  10610.         GLctx["texParameterf"](x0, x1, x2);
  10611.     }
  10612.     function _glTexParameteri(x0, x1, x2) {
  10613.         GLctx["texParameteri"](x0, x1, x2);
  10614.     }
  10615.     function _glTexParameteriv(target, pname, params) {
  10616.         var param = HEAP32[params >> 2];
  10617.         GLctx.texParameteri(target, pname, param);
  10618.     }
  10619.     function _glTexStorage2D(x0, x1, x2, x3, x4) {
  10620.         GLctx["texStorage2D"](x0, x1, x2, x3, x4);
  10621.     }
  10622.     function _glTexStorage3D(x0, x1, x2, x3, x4, x5) {
  10623.         GLctx["texStorage3D"](x0, x1, x2, x3, x4, x5);
  10624.     }
  10625.     function _glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels) {
  10626.         if (GL.currentContext.version >= 2) {
  10627.             if (GLctx.currentPixelUnpackBufferBinding) {
  10628.                 GLctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
  10629.             } else if (pixels) {
  10630.                 var heap = heapObjectForWebGLType(type);
  10631.                 GLctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, heap, pixels >> heapAccessShiftForWebGLHeap(heap));
  10632.             } else {
  10633.                 GLctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, null);
  10634.             }
  10635.             return;
  10636.         }
  10637.         var pixelData = null;
  10638.         if (pixels) pixelData = emscriptenWebGLGetTexPixelData(type, format, width, height, pixels, 0);
  10639.         GLctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixelData);
  10640.     }
  10641.     function _glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels) {
  10642.         if (GLctx.currentPixelUnpackBufferBinding) {
  10643.             GLctx["texSubImage3D"](target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
  10644.         } else if (pixels) {
  10645.             var heap = heapObjectForWebGLType(type);
  10646.             GLctx["texSubImage3D"](target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, heap, pixels >> heapAccessShiftForWebGLHeap(heap));
  10647.         } else {
  10648.             GLctx["texSubImage3D"](target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, null);
  10649.         }
  10650.     }
  10651.     function _glTransformFeedbackVaryings(program, count, varyings, bufferMode) {
  10652.         program = GL.programs[program];
  10653.         var vars = [];
  10654.         for (var i = 0; i < count; i++) vars.push(UTF8ToString(HEAP32[(varyings + i * 4) >> 2]));
  10655.         GLctx["transformFeedbackVaryings"](program, vars, bufferMode);
  10656.     }
  10657.     var miniTempWebGLFloatBuffers = [];
  10658.     function _glUniform1fv(location, count, value) {
  10659.         if (GL.currentContext.version >= 2) {
  10660.             GLctx.uniform1fv(webglGetUniformLocation(location), HEAPF32, value >> 2, count);
  10661.             return;
  10662.         }
  10663.         if (count <= 288) {
  10664.             var view = miniTempWebGLFloatBuffers[count - 1];
  10665.             for (var i = 0; i < count; ++i) {
  10666.                 view[i] = HEAPF32[(value + 4 * i) >> 2];
  10667.             }
  10668.         } else {
  10669.             var view = HEAPF32.subarray(value >> 2, (value + count * 4) >> 2);
  10670.         }
  10671.         GLctx.uniform1fv(webglGetUniformLocation(location), view);
  10672.     }
  10673.     function _glUniform1i(location, v0) {
  10674.         GLctx.uniform1i(webglGetUniformLocation(location), v0);
  10675.     }
  10676.     var __miniTempWebGLIntBuffers = [];
  10677.     function _glUniform1iv(location, count, value) {
  10678.         if (GL.currentContext.version >= 2) {
  10679.             GLctx.uniform1iv(webglGetUniformLocation(location), HEAP32, value >> 2, count);
  10680.             return;
  10681.         }
  10682.         if (count <= 288) {
  10683.             var view = __miniTempWebGLIntBuffers[count - 1];
  10684.             for (var i = 0; i < count; ++i) {
  10685.                 view[i] = HEAP32[(value + 4 * i) >> 2];
  10686.             }
  10687.         } else {
  10688.             var view = HEAP32.subarray(value >> 2, (value + count * 4) >> 2);
  10689.         }
  10690.         GLctx.uniform1iv(webglGetUniformLocation(location), view);
  10691.     }
  10692.     function _glUniform1uiv(location, count, value) {
  10693.         GLctx.uniform1uiv(webglGetUniformLocation(location), HEAPU32, value >> 2, count);
  10694.     }
  10695.     function _glUniform2fv(location, count, value) {
  10696.         if (GL.currentContext.version >= 2) {
  10697.             GLctx.uniform2fv(webglGetUniformLocation(location), HEAPF32, value >> 2, count * 2);
  10698.             return;
  10699.         }
  10700.         if (count <= 144) {
  10701.             var view = miniTempWebGLFloatBuffers[2 * count - 1];
  10702.             for (var i = 0; i < 2 * count; i += 2) {
  10703.                 view[i] = HEAPF32[(value + 4 * i) >> 2];
  10704.                 view[i + 1] = HEAPF32[(value + (4 * i + 4)) >> 2];
  10705.             }
  10706.         } else {
  10707.             var view = HEAPF32.subarray(value >> 2, (value + count * 8) >> 2);
  10708.         }
  10709.         GLctx.uniform2fv(webglGetUniformLocation(location), view);
  10710.     }
  10711.     function _glUniform2iv(location, count, value) {
  10712.         if (GL.currentContext.version >= 2) {
  10713.             GLctx.uniform2iv(webglGetUniformLocation(location), HEAP32, value >> 2, count * 2);
  10714.             return;
  10715.         }
  10716.         if (count <= 144) {
  10717.             var view = __miniTempWebGLIntBuffers[2 * count - 1];
  10718.             for (var i = 0; i < 2 * count; i += 2) {
  10719.                 view[i] = HEAP32[(value + 4 * i) >> 2];
  10720.                 view[i + 1] = HEAP32[(value + (4 * i + 4)) >> 2];
  10721.             }
  10722.         } else {
  10723.             var view = HEAP32.subarray(value >> 2, (value + count * 8) >> 2);
  10724.         }
  10725.         GLctx.uniform2iv(webglGetUniformLocation(location), view);
  10726.     }
  10727.     function _glUniform2uiv(location, count, value) {
  10728.         GLctx.uniform2uiv(webglGetUniformLocation(location), HEAPU32, value >> 2, count * 2);
  10729.     }
  10730.     function _glUniform3fv(location, count, value) {
  10731.         if (GL.currentContext.version >= 2) {
  10732.             GLctx.uniform3fv(webglGetUniformLocation(location), HEAPF32, value >> 2, count * 3);
  10733.             return;
  10734.         }
  10735.         if (count <= 96) {
  10736.             var view = miniTempWebGLFloatBuffers[3 * count - 1];
  10737.             for (var i = 0; i < 3 * count; i += 3) {
  10738.                 view[i] = HEAPF32[(value + 4 * i) >> 2];
  10739.                 view[i + 1] = HEAPF32[(value + (4 * i + 4)) >> 2];
  10740.                 view[i + 2] = HEAPF32[(value + (4 * i + 8)) >> 2];
  10741.             }
  10742.         } else {
  10743.             var view = HEAPF32.subarray(value >> 2, (value + count * 12) >> 2);
  10744.         }
  10745.         GLctx.uniform3fv(webglGetUniformLocation(location), view);
  10746.     }
  10747.     function _glUniform3iv(location, count, value) {
  10748.         if (GL.currentContext.version >= 2) {
  10749.             GLctx.uniform3iv(webglGetUniformLocation(location), HEAP32, value >> 2, count * 3);
  10750.             return;
  10751.         }
  10752.         if (count <= 96) {
  10753.             var view = __miniTempWebGLIntBuffers[3 * count - 1];
  10754.             for (var i = 0; i < 3 * count; i += 3) {
  10755.                 view[i] = HEAP32[(value + 4 * i) >> 2];
  10756.                 view[i + 1] = HEAP32[(value + (4 * i + 4)) >> 2];
  10757.                 view[i + 2] = HEAP32[(value + (4 * i + 8)) >> 2];
  10758.             }
  10759.         } else {
  10760.             var view = HEAP32.subarray(value >> 2, (value + count * 12) >> 2);
  10761.         }
  10762.         GLctx.uniform3iv(webglGetUniformLocation(location), view);
  10763.     }
  10764.     function _glUniform3uiv(location, count, value) {
  10765.         GLctx.uniform3uiv(webglGetUniformLocation(location), HEAPU32, value >> 2, count * 3);
  10766.     }
  10767.     function _glUniform4fv(location, count, value) {
  10768.         if (GL.currentContext.version >= 2) {
  10769.             GLctx.uniform4fv(webglGetUniformLocation(location), HEAPF32, value >> 2, count * 4);
  10770.             return;
  10771.         }
  10772.         if (count <= 72) {
  10773.             var view = miniTempWebGLFloatBuffers[4 * count - 1];
  10774.             var heap = HEAPF32;
  10775.             value >>= 2;
  10776.             for (var i = 0; i < 4 * count; i += 4) {
  10777.                 var dst = value + i;
  10778.                 view[i] = heap[dst];
  10779.                 view[i + 1] = heap[dst + 1];
  10780.                 view[i + 2] = heap[dst + 2];
  10781.                 view[i + 3] = heap[dst + 3];
  10782.             }
  10783.         } else {
  10784.             var view = HEAPF32.subarray(value >> 2, (value + count * 16) >> 2);
  10785.         }
  10786.         GLctx.uniform4fv(webglGetUniformLocation(location), view);
  10787.     }
  10788.     function _glUniform4iv(location, count, value) {
  10789.         if (GL.currentContext.version >= 2) {
  10790.             GLctx.uniform4iv(webglGetUniformLocation(location), HEAP32, value >> 2, count * 4);
  10791.             return;
  10792.         }
  10793.         if (count <= 72) {
  10794.             var view = __miniTempWebGLIntBuffers[4 * count - 1];
  10795.             for (var i = 0; i < 4 * count; i += 4) {
  10796.                 view[i] = HEAP32[(value + 4 * i) >> 2];
  10797.                 view[i + 1] = HEAP32[(value + (4 * i + 4)) >> 2];
  10798.                 view[i + 2] = HEAP32[(value + (4 * i + 8)) >> 2];
  10799.                 view[i + 3] = HEAP32[(value + (4 * i + 12)) >> 2];
  10800.             }
  10801.         } else {
  10802.             var view = HEAP32.subarray(value >> 2, (value + count * 16) >> 2);
  10803.         }
  10804.         GLctx.uniform4iv(webglGetUniformLocation(location), view);
  10805.     }
  10806.     function _glUniform4uiv(location, count, value) {
  10807.         GLctx.uniform4uiv(webglGetUniformLocation(location), HEAPU32, value >> 2, count * 4);
  10808.     }
  10809.     function _glUniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding) {
  10810.         program = GL.programs[program];
  10811.         GLctx["uniformBlockBinding"](program, uniformBlockIndex, uniformBlockBinding);
  10812.     }
  10813.     function _glUniformMatrix3fv(location, count, transpose, value) {
  10814.         if (GL.currentContext.version >= 2) {
  10815.             GLctx.uniformMatrix3fv(webglGetUniformLocation(location), !!transpose, HEAPF32, value >> 2, count * 9);
  10816.             return;
  10817.         }
  10818.         if (count <= 32) {
  10819.             var view = miniTempWebGLFloatBuffers[9 * count - 1];
  10820.             for (var i = 0; i < 9 * count; i += 9) {
  10821.                 view[i] = HEAPF32[(value + 4 * i) >> 2];
  10822.                 view[i + 1] = HEAPF32[(value + (4 * i + 4)) >> 2];
  10823.                 view[i + 2] = HEAPF32[(value + (4 * i + 8)) >> 2];
  10824.                 view[i + 3] = HEAPF32[(value + (4 * i + 12)) >> 2];
  10825.                 view[i + 4] = HEAPF32[(value + (4 * i + 16)) >> 2];
  10826.                 view[i + 5] = HEAPF32[(value + (4 * i + 20)) >> 2];
  10827.                 view[i + 6] = HEAPF32[(value + (4 * i + 24)) >> 2];
  10828.                 view[i + 7] = HEAPF32[(value + (4 * i + 28)) >> 2];
  10829.                 view[i + 8] = HEAPF32[(value + (4 * i + 32)) >> 2];
  10830.             }
  10831.         } else {
  10832.             var view = HEAPF32.subarray(value >> 2, (value + count * 36) >> 2);
  10833.         }
  10834.         GLctx.uniformMatrix3fv(webglGetUniformLocation(location), !!transpose, view);
  10835.     }
  10836.     function _glUniformMatrix4fv(location, count, transpose, value) {
  10837.         if (GL.currentContext.version >= 2) {
  10838.             GLctx.uniformMatrix4fv(webglGetUniformLocation(location), !!transpose, HEAPF32, value >> 2, count * 16);
  10839.             return;
  10840.         }
  10841.         if (count <= 18) {
  10842.             var view = miniTempWebGLFloatBuffers[16 * count - 1];
  10843.             var heap = HEAPF32;
  10844.             value >>= 2;
  10845.             for (var i = 0; i < 16 * count; i += 16) {
  10846.                 var dst = value + i;
  10847.                 view[i] = heap[dst];
  10848.                 view[i + 1] = heap[dst + 1];
  10849.                 view[i + 2] = heap[dst + 2];
  10850.                 view[i + 3] = heap[dst + 3];
  10851.                 view[i + 4] = heap[dst + 4];
  10852.                 view[i + 5] = heap[dst + 5];
  10853.                 view[i + 6] = heap[dst + 6];
  10854.                 view[i + 7] = heap[dst + 7];
  10855.                 view[i + 8] = heap[dst + 8];
  10856.                 view[i + 9] = heap[dst + 9];
  10857.                 view[i + 10] = heap[dst + 10];
  10858.                 view[i + 11] = heap[dst + 11];
  10859.                 view[i + 12] = heap[dst + 12];
  10860.                 view[i + 13] = heap[dst + 13];
  10861.                 view[i + 14] = heap[dst + 14];
  10862.                 view[i + 15] = heap[dst + 15];
  10863.             }
  10864.         } else {
  10865.             var view = HEAPF32.subarray(value >> 2, (value + count * 64) >> 2);
  10866.         }
  10867.         GLctx.uniformMatrix4fv(webglGetUniformLocation(location), !!transpose, view);
  10868.     }
  10869.     function _glUnmapBuffer(target) {
  10870.         if (!emscriptenWebGLValidateMapBufferTarget(target)) {
  10871.             GL.recordError(1280);
  10872.             err("GL_INVALID_ENUM in glUnmapBuffer");
  10873.             return 0;
  10874.         }
  10875.         var buffer = emscriptenWebGLGetBufferBinding(target);
  10876.         var mapping = GL.mappedBuffers[buffer];
  10877.         if (!mapping) {
  10878.             GL.recordError(1282);
  10879.             err("buffer was never mapped in glUnmapBuffer");
  10880.             return 0;
  10881.         }
  10882.         GL.mappedBuffers[buffer] = null;
  10883.         if (!(mapping.access & 16))
  10884.             if (GL.currentContext.version >= 2) {
  10885.                 GLctx.bufferSubData(target, mapping.offset, HEAPU8, mapping.mem, mapping.length);
  10886.             } else {
  10887.                 GLctx.bufferSubData(target, mapping.offset, HEAPU8.subarray(mapping.mem, mapping.mem + mapping.length));
  10888.             }
  10889.         _free(mapping.mem);
  10890.         return 1;
  10891.     }
  10892.     function webglApplyExplicitProgramBindings() {
  10893.         var p = GLctx.currentProgram;
  10894.         if (!p.explicitProgramBindingsApplied) {
  10895.             if (GL.currentContext.version >= 2) {
  10896.                 Object.keys(p.explicitUniformBindings).forEach(function (ubo) {
  10897.                     var bindings = p.explicitUniformBindings[ubo];
  10898.                     for (var i = 0; i < bindings[1]; ++i) {
  10899.                         var blockIndex = GLctx.getUniformBlockIndex(p, ubo + (bindings[1] > 1 ? "[" + i + "]" : ""));
  10900.                         GLctx.uniformBlockBinding(p, blockIndex, bindings[0] + i);
  10901.                     }
  10902.                 });
  10903.             }
  10904.             Object.keys(p.explicitSamplerBindings).forEach(function (sampler) {
  10905.                 var bindings = p.explicitSamplerBindings[sampler];
  10906.                 for (var i = 0; i < bindings[1]; ++i) {
  10907.                     GLctx.uniform1i(GLctx.getUniformLocation(p, sampler + (i ? "[" + i + "]" : "")), bindings[0] + i);
  10908.                 }
  10909.             });
  10910.             p.explicitProgramBindingsApplied = 1;
  10911.         }
  10912.     }
  10913.     function _glUseProgram(program) {
  10914.         program = GL.programs[program];
  10915.         GLctx.useProgram(program);
  10916.         if ((GLctx.currentProgram = program)) {
  10917.             webglApplyExplicitProgramBindings();
  10918.         }
  10919.     }
  10920.     function _glValidateProgram(program) {
  10921.         GLctx.validateProgram(GL.programs[program]);
  10922.     }
  10923.     function _glVertexAttrib4f(x0, x1, x2, x3, x4) {
  10924.         GLctx["vertexAttrib4f"](x0, x1, x2, x3, x4);
  10925.     }
  10926.     function _glVertexAttrib4fv(index, v) {
  10927.         GLctx.vertexAttrib4f(index, HEAPF32[v >> 2], HEAPF32[(v + 4) >> 2], HEAPF32[(v + 8) >> 2], HEAPF32[(v + 12) >> 2]);
  10928.     }
  10929.     function _glVertexAttribIPointer(index, size, type, stride, ptr) {
  10930.         var cb = GL.currentContext.clientBuffers[index];
  10931.         if (!GLctx.currentArrayBufferBinding) {
  10932.             cb.size = size;
  10933.             cb.type = type;
  10934.             cb.normalized = false;
  10935.             cb.stride = stride;
  10936.             cb.ptr = ptr;
  10937.             cb.clientside = true;
  10938.             cb.vertexAttribPointerAdaptor = function (index, size, type, normalized, stride, ptr) {
  10939.                 this.vertexAttribIPointer(index, size, type, stride, ptr);
  10940.             };
  10941.             return;
  10942.         }
  10943.         cb.clientside = false;
  10944.         GLctx["vertexAttribIPointer"](index, size, type, stride, ptr);
  10945.     }
  10946.     function _glVertexAttribPointer(index, size, type, normalized, stride, ptr) {
  10947.         var cb = GL.currentContext.clientBuffers[index];
  10948.         if (!GLctx.currentArrayBufferBinding) {
  10949.             cb.size = size;
  10950.             cb.type = type;
  10951.             cb.normalized = normalized;
  10952.             cb.stride = stride;
  10953.             cb.ptr = ptr;
  10954.             cb.clientside = true;
  10955.             cb.vertexAttribPointerAdaptor = function (index, size, type, normalized, stride, ptr) {
  10956.                 this.vertexAttribPointer(index, size, type, normalized, stride, ptr);
  10957.             };
  10958.             return;
  10959.         }
  10960.         cb.clientside = false;
  10961.         GLctx.vertexAttribPointer(index, size, type, !!normalized, stride, ptr);
  10962.     }
  10963.     function _glViewport(x0, x1, x2, x3) {
  10964.         GLctx["viewport"](x0, x1, x2, x3);
  10965.     }
  10966.     function _llvm_eh_typeid_for(type) {
  10967.         return type;
  10968.     }
  10969.     function _mktime(tmPtr) {
  10970.         _tzset();
  10971.         var date = new Date(HEAP32[(tmPtr + 20) >> 2] + 1900, HEAP32[(tmPtr + 16) >> 2], HEAP32[(tmPtr + 12) >> 2], HEAP32[(tmPtr + 8) >> 2], HEAP32[(tmPtr + 4) >> 2], HEAP32[tmPtr >> 2], 0);
  10972.         var dst = HEAP32[(tmPtr + 32) >> 2];
  10973.         var guessedOffset = date.getTimezoneOffset();
  10974.         var start = new Date(date.getFullYear(), 0, 1);
  10975.         var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset();
  10976.         var winterOffset = start.getTimezoneOffset();
  10977.         var dstOffset = Math.min(winterOffset, summerOffset);
  10978.         if (dst < 0) {
  10979.             HEAP32[(tmPtr + 32) >> 2] = Number(summerOffset != winterOffset && dstOffset == guessedOffset);
  10980.         } else if (dst > 0 != (dstOffset == guessedOffset)) {
  10981.             var nonDstOffset = Math.max(winterOffset, summerOffset);
  10982.             var trueOffset = dst > 0 ? dstOffset : nonDstOffset;
  10983.             date.setTime(date.getTime() + (trueOffset - guessedOffset) * 6e4);
  10984.         }
  10985.         HEAP32[(tmPtr + 24) >> 2] = date.getDay();
  10986.         var yday = ((date.getTime() - start.getTime()) / (1e3 * 60 * 60 * 24)) | 0;
  10987.         HEAP32[(tmPtr + 28) >> 2] = yday;
  10988.         HEAP32[tmPtr >> 2] = date.getSeconds();
  10989.         HEAP32[(tmPtr + 4) >> 2] = date.getMinutes();
  10990.         HEAP32[(tmPtr + 8) >> 2] = date.getHours();
  10991.         HEAP32[(tmPtr + 12) >> 2] = date.getDate();
  10992.         HEAP32[(tmPtr + 16) >> 2] = date.getMonth();
  10993.         return (date.getTime() / 1e3) | 0;
  10994.     }
  10995.     function _setTempRet0(val) {
  10996.         setTempRet0(val);
  10997.     }
  10998.     function __isLeapYear(year) {
  10999.         return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
  11000.     }
  11001.     function __arraySum(array, index) {
  11002.         var sum = 0;
  11003.         for (var i = 0; i <= index; sum += array[i++]) {}
  11004.         return sum;
  11005.     }
  11006.     var __MONTH_DAYS_LEAP = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
  11007.     var __MONTH_DAYS_REGULAR = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
  11008.     function __addDays(date, days) {
  11009.         var newDate = new Date(date.getTime());
  11010.         while (days > 0) {
  11011.             var leap = __isLeapYear(newDate.getFullYear());
  11012.             var currentMonth = newDate.getMonth();
  11013.             var daysInCurrentMonth = (leap ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR)[currentMonth];
  11014.             if (days > daysInCurrentMonth - newDate.getDate()) {
  11015.                 days -= daysInCurrentMonth - newDate.getDate() + 1;
  11016.                 newDate.setDate(1);
  11017.                 if (currentMonth < 11) {
  11018.                     newDate.setMonth(currentMonth + 1);
  11019.                 } else {
  11020.                     newDate.setMonth(0);
  11021.                     newDate.setFullYear(newDate.getFullYear() + 1);
  11022.                 }
  11023.             } else {
  11024.                 newDate.setDate(newDate.getDate() + days);
  11025.                 return newDate;
  11026.             }
  11027.         }
  11028.         return newDate;
  11029.     }
  11030.     function _strftime(s, maxsize, format, tm) {
  11031.         var tm_zone = HEAP32[(tm + 40) >> 2];
  11032.         var date = {
  11033.             tm_sec: HEAP32[tm >> 2],
  11034.             tm_min: HEAP32[(tm + 4) >> 2],
  11035.             tm_hour: HEAP32[(tm + 8) >> 2],
  11036.             tm_mday: HEAP32[(tm + 12) >> 2],
  11037.             tm_mon: HEAP32[(tm + 16) >> 2],
  11038.             tm_year: HEAP32[(tm + 20) >> 2],
  11039.             tm_wday: HEAP32[(tm + 24) >> 2],
  11040.             tm_yday: HEAP32[(tm + 28) >> 2],
  11041.             tm_isdst: HEAP32[(tm + 32) >> 2],
  11042.             tm_gmtoff: HEAP32[(tm + 36) >> 2],
  11043.             tm_zone: tm_zone ? UTF8ToString(tm_zone) : "",
  11044.         };
  11045.         var pattern = UTF8ToString(format);
  11046.         var EXPANSION_RULES_1 = {
  11047.             "%c": "%a %b %d %H:%M:%S %Y",
  11048.             "%D": "%m/%d/%y",
  11049.             "%F": "%Y-%m-%d",
  11050.             "%h": "%b",
  11051.             "%r": "%I:%M:%S %p",
  11052.             "%R": "%H:%M",
  11053.             "%T": "%H:%M:%S",
  11054.             "%x": "%m/%d/%y",
  11055.             "%X": "%H:%M:%S",
  11056.             "%Ec": "%c",
  11057.             "%EC": "%C",
  11058.             "%Ex": "%m/%d/%y",
  11059.             "%EX": "%H:%M:%S",
  11060.             "%Ey": "%y",
  11061.             "%EY": "%Y",
  11062.             "%Od": "%d",
  11063.             "%Oe": "%e",
  11064.             "%OH": "%H",
  11065.             "%OI": "%I",
  11066.             "%Om": "%m",
  11067.             "%OM": "%M",
  11068.             "%OS": "%S",
  11069.             "%Ou": "%u",
  11070.             "%OU": "%U",
  11071.             "%OV": "%V",
  11072.             "%Ow": "%w",
  11073.             "%OW": "%W",
  11074.             "%Oy": "%y",
  11075.         };
  11076.         for (var rule in EXPANSION_RULES_1) {
  11077.             pattern = pattern.replace(new RegExp(rule, "g"), EXPANSION_RULES_1[rule]);
  11078.         }
  11079.         var WEEKDAYS = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
  11080.         var MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
  11081.         function leadingSomething(value, digits, character) {
  11082.             var str = typeof value === "number" ? value.toString() : value || "";
  11083.             while (str.length < digits) {
  11084.                 str = character[0] + str;
  11085.             }
  11086.             return str;
  11087.         }
  11088.         function leadingNulls(value, digits) {
  11089.             return leadingSomething(value, digits, "0");
  11090.         }
  11091.         function compareByDay(date1, date2) {
  11092.             function sgn(value) {
  11093.                 return value < 0 ? -1 : value > 0 ? 1 : 0;
  11094.             }
  11095.             var compare;
  11096.             if ((compare = sgn(date1.getFullYear() - date2.getFullYear())) === 0) {
  11097.                 if ((compare = sgn(date1.getMonth() - date2.getMonth())) === 0) {
  11098.                     compare = sgn(date1.getDate() - date2.getDate());
  11099.                 }
  11100.             }
  11101.             return compare;
  11102.         }
  11103.         function getFirstWeekStartDate(janFourth) {
  11104.             switch (janFourth.getDay()) {
  11105.                 case 0:
  11106.                     return new Date(janFourth.getFullYear() - 1, 11, 29);
  11107.                 case 1:
  11108.                     return janFourth;
  11109.                 case 2:
  11110.                     return new Date(janFourth.getFullYear(), 0, 3);
  11111.                 case 3:
  11112.                     return new Date(janFourth.getFullYear(), 0, 2);
  11113.                 case 4:
  11114.                     return new Date(janFourth.getFullYear(), 0, 1);
  11115.                 case 5:
  11116.                     return new Date(janFourth.getFullYear() - 1, 11, 31);
  11117.                 case 6:
  11118.                     return new Date(janFourth.getFullYear() - 1, 11, 30);
  11119.             }
  11120.         }
  11121.         function getWeekBasedYear(date) {
  11122.             var thisDate = __addDays(new Date(date.tm_year + 1900, 0, 1), date.tm_yday);
  11123.             var janFourthThisYear = new Date(thisDate.getFullYear(), 0, 4);
  11124.             var janFourthNextYear = new Date(thisDate.getFullYear() + 1, 0, 4);
  11125.             var firstWeekStartThisYear = getFirstWeekStartDate(janFourthThisYear);
  11126.             var firstWeekStartNextYear = getFirstWeekStartDate(janFourthNextYear);
  11127.             if (compareByDay(firstWeekStartThisYear, thisDate) <= 0) {
  11128.                 if (compareByDay(firstWeekStartNextYear, thisDate) <= 0) {
  11129.                     return thisDate.getFullYear() + 1;
  11130.                 } else {
  11131.                     return thisDate.getFullYear();
  11132.                 }
  11133.             } else {
  11134.                 return thisDate.getFullYear() - 1;
  11135.             }
  11136.         }
  11137.         var EXPANSION_RULES_2 = {
  11138.             "%a": function (date) {
  11139.                 return WEEKDAYS[date.tm_wday].substring(0, 3);
  11140.             },
  11141.             "%A": function (date) {
  11142.                 return WEEKDAYS[date.tm_wday];
  11143.             },
  11144.             "%b": function (date) {
  11145.                 return MONTHS[date.tm_mon].substring(0, 3);
  11146.             },
  11147.             "%B": function (date) {
  11148.                 return MONTHS[date.tm_mon];
  11149.             },
  11150.             "%C": function (date) {
  11151.                 var year = date.tm_year + 1900;
  11152.                 return leadingNulls((year / 100) | 0, 2);
  11153.             },
  11154.             "%d": function (date) {
  11155.                 return leadingNulls(date.tm_mday, 2);
  11156.             },
  11157.             "%e": function (date) {
  11158.                 return leadingSomething(date.tm_mday, 2, " ");
  11159.             },
  11160.             "%g": function (date) {
  11161.                 return getWeekBasedYear(date).toString().substring(2);
  11162.             },
  11163.             "%G": function (date) {
  11164.                 return getWeekBasedYear(date);
  11165.             },
  11166.             "%H": function (date) {
  11167.                 return leadingNulls(date.tm_hour, 2);
  11168.             },
  11169.             "%I": function (date) {
  11170.                 var twelveHour = date.tm_hour;
  11171.                 if (twelveHour == 0) twelveHour = 12;
  11172.                 else if (twelveHour > 12) twelveHour -= 12;
  11173.                 return leadingNulls(twelveHour, 2);
  11174.             },
  11175.             "%j": function (date) {
  11176.                 return leadingNulls(date.tm_mday + __arraySum(__isLeapYear(date.tm_year + 1900) ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR, date.tm_mon - 1), 3);
  11177.             },
  11178.             "%m": function (date) {
  11179.                 return leadingNulls(date.tm_mon + 1, 2);
  11180.             },
  11181.             "%M": function (date) {
  11182.                 return leadingNulls(date.tm_min, 2);
  11183.             },
  11184.             "%n": function () {
  11185.                 return "\n";
  11186.             },
  11187.             "%p": function (date) {
  11188.                 if (date.tm_hour >= 0 && date.tm_hour < 12) {
  11189.                     return "AM";
  11190.                 } else {
  11191.                     return "PM";
  11192.                 }
  11193.             },
  11194.             "%S": function (date) {
  11195.                 return leadingNulls(date.tm_sec, 2);
  11196.             },
  11197.             "%t": function () {
  11198.                 return "\t";
  11199.             },
  11200.             "%u": function (date) {
  11201.                 return date.tm_wday || 7;
  11202.             },
  11203.             "%U": function (date) {
  11204.                 var janFirst = new Date(date.tm_year + 1900, 0, 1);
  11205.                 var firstSunday = janFirst.getDay() === 0 ? janFirst : __addDays(janFirst, 7 - janFirst.getDay());
  11206.                 var endDate = new Date(date.tm_year + 1900, date.tm_mon, date.tm_mday);
  11207.                 if (compareByDay(firstSunday, endDate) < 0) {
  11208.                     var februaryFirstUntilEndMonth = __arraySum(__isLeapYear(endDate.getFullYear()) ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR, endDate.getMonth() - 1) - 31;
  11209.                     var firstSundayUntilEndJanuary = 31 - firstSunday.getDate();
  11210.                     var days = firstSundayUntilEndJanuary + februaryFirstUntilEndMonth + endDate.getDate();
  11211.                     return leadingNulls(Math.ceil(days / 7), 2);
  11212.                 }
  11213.                 return compareByDay(firstSunday, janFirst) === 0 ? "01" : "00";
  11214.             },
  11215.             "%V": function (date) {
  11216.                 var janFourthThisYear = new Date(date.tm_year + 1900, 0, 4);
  11217.                 var janFourthNextYear = new Date(date.tm_year + 1901, 0, 4);
  11218.                 var firstWeekStartThisYear = getFirstWeekStartDate(janFourthThisYear);
  11219.                 var firstWeekStartNextYear = getFirstWeekStartDate(janFourthNextYear);
  11220.                 var endDate = __addDays(new Date(date.tm_year + 1900, 0, 1), date.tm_yday);
  11221.                 if (compareByDay(endDate, firstWeekStartThisYear) < 0) {
  11222.                     return "53";
  11223.                 }
  11224.                 if (compareByDay(firstWeekStartNextYear, endDate) <= 0) {
  11225.                     return "01";
  11226.                 }
  11227.                 var daysDifference;
  11228.                 if (firstWeekStartThisYear.getFullYear() < date.tm_year + 1900) {
  11229.                     daysDifference = date.tm_yday + 32 - firstWeekStartThisYear.getDate();
  11230.                 } else {
  11231.                     daysDifference = date.tm_yday + 1 - firstWeekStartThisYear.getDate();
  11232.                 }
  11233.                 return leadingNulls(Math.ceil(daysDifference / 7), 2);
  11234.             },
  11235.             "%w": function (date) {
  11236.                 return date.tm_wday;
  11237.             },
  11238.             "%W": function (date) {
  11239.                 var janFirst = new Date(date.tm_year, 0, 1);
  11240.                 var firstMonday = janFirst.getDay() === 1 ? janFirst : __addDays(janFirst, janFirst.getDay() === 0 ? 1 : 7 - janFirst.getDay() + 1);
  11241.                 var endDate = new Date(date.tm_year + 1900, date.tm_mon, date.tm_mday);
  11242.                 if (compareByDay(firstMonday, endDate) < 0) {
  11243.                     var februaryFirstUntilEndMonth = __arraySum(__isLeapYear(endDate.getFullYear()) ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR, endDate.getMonth() - 1) - 31;
  11244.                     var firstMondayUntilEndJanuary = 31 - firstMonday.getDate();
  11245.                     var days = firstMondayUntilEndJanuary + februaryFirstUntilEndMonth + endDate.getDate();
  11246.                     return leadingNulls(Math.ceil(days / 7), 2);
  11247.                 }
  11248.                 return compareByDay(firstMonday, janFirst) === 0 ? "01" : "00";
  11249.             },
  11250.             "%y": function (date) {
  11251.                 return (date.tm_year + 1900).toString().substring(2);
  11252.             },
  11253.             "%Y": function (date) {
  11254.                 return date.tm_year + 1900;
  11255.             },
  11256.             "%z": function (date) {
  11257.                 var off = date.tm_gmtoff;
  11258.                 var ahead = off >= 0;
  11259.                 off = Math.abs(off) / 60;
  11260.                 off = (off / 60) * 100 + (off % 60);
  11261.                 return (ahead ? "+" : "-") + String("0000" + off).slice(-4);
  11262.             },
  11263.             "%Z": function (date) {
  11264.                 return date.tm_zone;
  11265.             },
  11266.             "%%": function () {
  11267.                 return "%";
  11268.             },
  11269.         };
  11270.         for (var rule in EXPANSION_RULES_2) {
  11271.             if (pattern.includes(rule)) {
  11272.                 pattern = pattern.replace(new RegExp(rule, "g"), EXPANSION_RULES_2[rule](date));
  11273.             }
  11274.         }
  11275.         var bytes = intArrayFromString(pattern, false);
  11276.         if (bytes.length > maxsize) {
  11277.             return 0;
  11278.         }
  11279.         writeArrayToMemory(bytes, s);
  11280.         return bytes.length - 1;
  11281.     }
  11282.     function _time(ptr) {
  11283.         var ret = (Date.now() / 1e3) | 0;
  11284.         if (ptr) {
  11285.             HEAP32[ptr >> 2] = ret;
  11286.         }
  11287.         return ret;
  11288.     }
  11289.     function setFileTime(path, time) {
  11290.         path = UTF8ToString(path);
  11291.         try {
  11292.             FS.utime(path, time, time);
  11293.             return 0;
  11294.         } catch (e) {
  11295.             if (!(e instanceof FS.ErrnoError)) throw e + " : " + stackTrace();
  11296.             setErrNo(e.errno);
  11297.             return -1;
  11298.         }
  11299.     }
  11300.     function _utime(path, times) {
  11301.         var time;
  11302.         if (times) {
  11303.             time = HEAP32[(times + 4) >> 2] * 1e3;
  11304.         } else {
  11305.             time = Date.now();
  11306.         }
  11307.         return setFileTime(path, time);
  11308.     }
  11309.     var FSNode = function (parent, name, mode, rdev) {
  11310.         if (!parent) {
  11311.             parent = this;
  11312.         }
  11313.         this.parent = parent;
  11314.         this.mount = parent.mount;
  11315.         this.mounted = null;
  11316.         this.id = FS.nextInode++;
  11317.         this.name = name;
  11318.         this.mode = mode;
  11319.         this.node_ops = {};
  11320.         this.stream_ops = {};
  11321.         this.rdev = rdev;
  11322.     };
  11323.     var readMode = 292 | 73;
  11324.     var writeMode = 146;
  11325.     Object.defineProperties(FSNode.prototype, {
  11326.         read: {
  11327.             get: function () {
  11328.                 return (this.mode & readMode) === readMode;
  11329.             },
  11330.             set: function (val) {
  11331.                 val ? (this.mode |= readMode) : (this.mode &= ~readMode);
  11332.             },
  11333.         },
  11334.         write: {
  11335.             get: function () {
  11336.                 return (this.mode & writeMode) === writeMode;
  11337.             },
  11338.             set: function (val) {
  11339.                 val ? (this.mode |= writeMode) : (this.mode &= ~writeMode);
  11340.             },
  11341.         },
  11342.         isFolder: {
  11343.             get: function () {
  11344.                 return FS.isDir(this.mode);
  11345.             },
  11346.         },
  11347.         isDevice: {
  11348.             get: function () {
  11349.                 return FS.isChrdev(this.mode);
  11350.             },
  11351.         },
  11352.     });
  11353.     FS.FSNode = FSNode;
  11354.     FS.staticInit();
  11355.     Module["FS_createPath"] = FS.createPath;
  11356.     Module["FS_createDataFile"] = FS.createDataFile;
  11357.     Module["requestFullscreen"] = function Module_requestFullscreen(lockPointer, resizeCanvas) {
  11358.         Browser.requestFullscreen(lockPointer, resizeCanvas);
  11359.     };
  11360.     Module["requestAnimationFrame"] = function Module_requestAnimationFrame(func) {
  11361.         Browser.requestAnimationFrame(func);
  11362.     };
  11363.     Module["setCanvasSize"] = function Module_setCanvasSize(width, height, noUpdates) {
  11364.         Browser.setCanvasSize(width, height, noUpdates);
  11365.     };
  11366.     Module["pauseMainLoop"] = function Module_pauseMainLoop() {
  11367.         Browser.mainLoop.pause();
  11368.     };
  11369.     Module["resumeMainLoop"] = function Module_resumeMainLoop() {
  11370.         Browser.mainLoop.resume();
  11371.     };
  11372.     Module["getUserMedia"] = function Module_getUserMedia() {
  11373.         Browser.getUserMedia();
  11374.     };
  11375.     Module["createContext"] = function Module_createContext(canvas, useWebGL, setInModule, webGLContextAttributes) {
  11376.         return Browser.createContext(canvas, useWebGL, setInModule, webGLContextAttributes);
  11377.     };
  11378.     var GLctx;
  11379.     for (var i = 0; i < 32; ++i) tempFixedLengthArray.push(new Array(i));
  11380.     var miniTempWebGLFloatBuffersStorage = new Float32Array(288);
  11381.     for (var i = 0; i < 288; ++i) {
  11382.         miniTempWebGLFloatBuffers[i] = miniTempWebGLFloatBuffersStorage.subarray(0, i + 1);
  11383.     }
  11384.     var __miniTempWebGLIntBuffersStorage = new Int32Array(288);
  11385.     for (var i = 0; i < 288; ++i) {
  11386.         __miniTempWebGLIntBuffers[i] = __miniTempWebGLIntBuffersStorage.subarray(0, i + 1);
  11387.     }
  11388.     function intArrayFromString(stringy, dontAddNull, length) {
  11389.         var len = length > 0 ? length : lengthBytesUTF8(stringy) + 1;
  11390.         var u8array = new Array(len);
  11391.         var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length);
  11392.         if (dontAddNull) u8array.length = numBytesWritten;
  11393.         return u8array;
  11394.     }
  11395.     Module["ccall"] = ccall;
  11396.     Module["cwrap"] = cwrap;
  11397.     Module["stackTrace"] = stackTrace;
  11398.     Module["addRunDependency"] = addRunDependency;
  11399.     Module["removeRunDependency"] = removeRunDependency;
  11400.     Module["FS_createPath"] = FS.createPath;
  11401.     Module["FS_createDataFile"] = FS.createDataFile;
  11402.     Module["stackTrace"] = stackTrace;
  11403.     var calledRun;
  11404.     function ExitStatus(status) {
  11405.         this.name = "ExitStatus";
  11406.         this.message = "Program terminated with exit(" + status + ")";
  11407.         this.status = status;
  11408.     }
  11409.     var calledMain = false;
  11410.     dependenciesFulfilled = function runCaller() {
  11411.         if (!calledRun) run();
  11412.         if (!calledRun) dependenciesFulfilled = runCaller;
  11413.     };
  11414.     function callMain(args) {
  11415.         var entryFunction = Module["_main"];
  11416.         args = args || [];
  11417.         var argc = args.length + 1;
  11418.         var argv = stackAlloc((argc + 1) * 4);
  11419.         HEAP32[argv >> 2] = allocateUTF8OnStack(thisProgram);
  11420.         for (var i = 1; i < argc; i++) {
  11421.             HEAP32[(argv >> 2) + i] = allocateUTF8OnStack(args[i - 1]);
  11422.         }
  11423.         HEAP32[(argv >> 2) + argc] = 0;
  11424.         try {
  11425.             var ret = entryFunction(argc, argv);
  11426.             exit(ret, true);
  11427.         } catch (e) {
  11428.             if (e instanceof ExitStatus) {
  11429.                 return;
  11430.             } else if (e == "unwind") {
  11431.                 return;
  11432.             } else {
  11433.                 var toLog = e;
  11434.                 if (e && typeof e === "object" && e.stack) {
  11435.                     toLog = [e, e.stack];
  11436.                 }
  11437.                 err("exception thrown: " + toLog);
  11438.                 quit_(1, e);
  11439.             }
  11440.         } finally {
  11441.             calledMain = true;
  11442.         }
  11443.     }
  11444.     function run(args) {
  11445.         args = args || arguments_;
  11446.         if (runDependencies > 0) {
  11447.             return;
  11448.         }
  11449.         preRun();
  11450.         if (runDependencies > 0) {
  11451.             return;
  11452.         }
  11453.         function doRun() {
  11454.             if (calledRun) return;
  11455.             calledRun = true;
  11456.             Module["calledRun"] = true;
  11457.             if (ABORT) return;
  11458.             initRuntime();
  11459.             preMain();
  11460.             if (Module["onRuntimeInitialized"]) Module["onRuntimeInitialized"]();
  11461.             if (shouldRunNow) callMain(args);
  11462.             postRun();
  11463.         }
  11464.         if (Module["setStatus"]) {
  11465.             Module["setStatus"]("Running...");
  11466.             setTimeout(function () {
  11467.                 setTimeout(function () {
  11468.                     Module["setStatus"]("");
  11469.                 }, 1);
  11470.                 doRun();
  11471.             }, 1);
  11472.         } else {
  11473.             doRun();
  11474.         }
  11475.     }
  11476.     Module["run"] = run;
  11477.     function exit(status, implicit) {
  11478.         EXITSTATUS = status;
  11479.         if (implicit && keepRuntimeAlive() && status === 0) {
  11480.             return;
  11481.         }
  11482.         if (keepRuntimeAlive()) {
  11483.         } else {
  11484.             exitRuntime();
  11485.             if (Module["onExit"]) Module["onExit"](status);
  11486.             ABORT = true;
  11487.         }
  11488.         quit_(status, new ExitStatus(status));
  11489.     }
  11490.     if (Module["preInit"]) {
  11491.         if (typeof Module["preInit"] == "function") Module["preInit"] = [Module["preInit"]];
  11492.         while (Module["preInit"].length > 0) {
  11493.             Module["preInit"].pop()();
  11494.         }
  11495.     }
  11496.     var shouldRunNow = true;
  11497.     if (Module["noInitialRun"]) shouldRunNow = false;
  11498.     run();
  11499. }
  11500.  
Add Comment
Please, Sign In to add comment