summaryrefslogtreecommitdiffhomepage
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/web/models/models_first_person_maze.html306
-rw-r--r--examples/web/models/models_first_person_maze.js9273
-rw-r--r--examples/web/models/models_first_person_maze.wasmbin171658 -> 178054 bytes
-rw-r--r--examples/web/models/models_first_person_maze.wasm.map1
4 files changed, 9577 insertions, 3 deletions
diff --git a/examples/web/models/models_first_person_maze.html b/examples/web/models/models_first_person_maze.html
index 6a48daa..6f240fd 100644
--- a/examples/web/models/models_first_person_maze.html
+++ b/examples/web/models/models_first_person_maze.html
@@ -1,4 +1,300 @@
-<!doctypehtml><html lang=en-us><head><meta charset=utf-8><meta content="text/html; charset=utf-8"http-equiv=Content-Type><title>raylib HTML5 GAME</title><meta content="raylib HTML5 GAME"name=title><meta content="New HTML5 videogame, developed using raylib videogames library"name=description><meta content="raylib, games, html5, programming, C, C++, library, learn, videogames"name=keywords><meta content="width=device-width"name=viewport><meta content="raylib HTML5 GAME"property=og:title><meta content=image/png property=og:image:type><meta content=https://www.raylib.com/common/img/raylib_logo.png property=og:image><meta content=raylib.com property=og:site_name><meta content=https://www.raylib.com/games.html property=og:url><meta content="New HTML5 videogame, developed using raylib videogames library"property=og:description><meta content=summary name=twitter:card><meta content=@raysan5 name=twitter:site><meta content="raylib HTML5 GAME"name=twitter:title><meta content=https://www.raylib.com/common/raylib_logo.png name=twitter:image><meta content=https://www.raylib.com/games.html name=twitter:url><meta content="New HTML5 videogame, developed using raylib videogames library"name=twitter:description><link href=https://www.raylib.com/favicon.ico rel="shortcut icon"><style>body{font-family:arial;margin:0;padding:none}#header{width:100%;height:80px;background-color:#888}#logo{width:64px;height:64px;float:left;position:relative;margin:10px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAIAAAAlC+aJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjExR/NCNwAAA7JJREFUaEPtk0FyWzEMQ+37X7fZhxX4YY3AD1OKF1nkzTRlSBCCLeVBnvl/AUdaELOunPno1kts1kixdtEZKVs+xIxebBkZsVknn/L5nFGDLR8T4zVC9fX19S/+tTFijrYK4jUjbPUtqBHpnEE6PkZD7jQZV8n5Recw1XQKciZuPaEtR6UjNs5ENVGMsBVqpPtER0ZMOhpyp8m4YL4OjD9yxsyZxnQycfMJETNSzsRE1+dihK3YMiJmpHTW3xpmXPC6BXlCHfqnBlsjY5hxf/6EVEOM2BTEi0fYCX4ONSI6Kq3Blg/prIOMq2CsRur4KQ0x64SdjOufEDEdHZGOhmz5RDHCVqhRuQ86YsVskbc+GXchLiHnFyYH+UigQDVGnImbT8hwFkgLg2qiM8JO6Ylx1FNLa3DmYwqCTsZd4BPqGJG7MwKzpeiWKTKxXkLMVE3MSOmsdwxLH6Rd/wCCLSNDx6djeKfJuArGeoYamRHpaEjnCBYZVy8hZqo2GI36qPjsiOiMsBXGcev4Mx9TLGTchbgEjN/uz6jGrBvDjg+LTNx8Qp2CbG2xMKgmOiPslJ4Yxx+eSnSkzlosZNwFPiHl7FRTkLNRJm4+IeVM0ymIH42wE/wcKalQI4MRl4EW3p6VcRWMua8F6WjIlqZDxvVPiHQ6CjVbYkV9ohhhp/Rk1wiYgpyJ78i4CsZbjkb8Qx+ihvzu3RPaKogZkY6GlEeMsKdPSOFIC8VoOusg44L5c+T8ouOoGhWbdWJ8tMi4egkxo4hoh2yNTGf3iIyr5Lyic4bRENXo+lvDjAt4C1Hk/OKtUaAj0+n4dMSZ2D+hrYJsaYh2SClG2jV9kJKKzhlGQ1SsW299Mq6C8dYZHTExo8fzieI5ivipYnYy7nwJqGKmOYyRwfiUBXITfh5qSHRGWEkfqJqURgvsdHyWYv7Ko8DnYYegk3EB00cxprdrJRzFd7YQzawu8L1GMTYS/KpPaAFTkIn1EmJmspJSs5xBzSyGhlkBmlxfNFiP5mw4wlbMh4F5Ddxp5jNINBdCEz9zPOC1zD7Q0HBdmXndwv0TMtydEdzlWJT4VZ8Qt9Qn4/onxMIwa5ZYGJU5yufBiCjwE50AGjLCVuS8Yt4H7OgZLKK5EKOsLviEWJSL/+0uMi7gLUSBseYwqEbXvSHCec1CJvZPyHCmYQffaBBfOTCGHM2aEbZi1+gO1XTWVXMnzrhAn5DSOZVsiQlHnSITKzGj6DeTcZWc/3oy7h9//PF4PL4BlvsWrb6RE+oAAAAASUVORK5CYII=)}.emscripten{padding-right:0;margin-left:auto;margin-right:auto;display:block}div.emscripten{text-align:center}div.emscripten_border{border:1px solid #000}canvas.emscripten{border:0 none;background:#000;width:100%}.spinner{height:30px;width:30px;margin:0;margin-top:20px;margin-left:20px;display:inline-block;vertical-align:top;-webkit-animation:rotation .8s linear infinite;-moz-animation:rotation .8s linear infinite;-o-animation:rotation .8s linear infinite;animation:rotation .8s linear infinite;border-left:5px solid #000;border-right:5px solid #000;border-bottom:5px solid #000;border-top:5px solid red;border-radius:100%;background-color:#f5f5f5}@-webkit-keyframes rotation{from{-webkit-transform:rotate(0)}to{-webkit-transform:rotate(360deg)}}@-moz-keyframes rotation{from{-moz-transform:rotate(0)}to{-moz-transform:rotate(360deg)}}@-o-keyframes rotation{from{-o-transform:rotate(0)}to{-o-transform:rotate(360deg)}}@keyframes rotation{from{transform:rotate(0)}to{transform:rotate(360deg)}}#status{display:inline-block;vertical-align:top;margin-top:30px;margin-left:20px;font-weight:700;color:#282828}#progress{height:0;width:0}#controls{display:inline-block;float:right;vertical-align:top;margin-top:15px;margin-right:20px}#output{width:100%;height:140px;margin:0 auto;margin-top:10px;display:block;background-color:#000;color:#25ae26;font-family:'Lucida Console',Monaco,monospace;outline:0}input[type=button]{background-color:#d3d3d3;border:4px solid #a9a9a9;color:#000;text-decoration:none;cursor:pointer;width:140px;height:50px}input[type=button]:hover{background-color:#f5f5f5ff;border-color:#000}</style></head><body><div id=header><a href=https://www.raylib.com id=logo></a><div class=spinner id=spinner></div><div class=emscripten id=status>Downloading...</div><span id=controls><span><input onclick=Module.requestFullscreen(!1,!1) type=button value="🖵 FULLSCREEN"></span><span><input onclick=toggleAudio() type=button value="🔇 SUSPEND"id=btn-audio></span></span><div class=emscripten><progress hidden id=progress max=100 value=0></progress></div></div><div class=emscripten_border><canvas class=emscripten id=canvas oncontextmenu=event.preventDefault() tabindex=-1></canvas></div><textarea id=output rows=8></textarea><script src=https://cdn.jsdelivr.net/gh/eligrey/FileSaver.js/dist/FileSaver.min.js></script><script>function saveFileFromMEMFSToDisk(e,a){var t,i=/^((?!chrome|android).)*safari/i.test(navigator.userAgent),o=FS.readFile(e);t=i?new Blob([o.buffer],{type:"application/octet-stream"}):new Blob([o.buffer],{type:"application/octet-binary"}),saveAs(t,a)}</script><script>var statusElement=document.querySelector("#status"),progressElement=document.querySelector("#progress"),spinnerElement=document.querySelector("#spinner"),Module={preRun:[],postRun:[],print:function(){var t=document.querySelector("#output");return t&&(t.value=""),function(e){1<arguments.length&&(e=Array.prototype.slice.call(arguments).join(" ")),console.log(e),t&&(t.value+=e+"\n",t.scrollTop=t.scrollHeight)}}(),printErr:function(e){1<arguments.length&&(e=Array.prototype.slice.call(arguments).join(" ")),console.error(e)},canvas:function(){var e=document.querySelector("#canvas");return e.addEventListener("webglcontextlost",function(e){alert("WebGL context lost. You will need to reload the page."),e.preventDefault()},!1),e}(),setStatus:function(e){if(Module.setStatus.last||(Module.setStatus.last={time:Date.now(),text:""}),e!==Module.setStatus.last.text){var t=e.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/),n=Date.now();t&&n-Module.setStatus.last.time<30||(Module.setStatus.last.time=n,Module.setStatus.last.text=e,t?(e=t[1],progressElement.value=100*parseInt(t[2]),progressElement.max=100*parseInt(t[4]),progressElement.hidden=!0,spinnerElement.hidden=!1):(progressElement.value=null,progressElement.max=null,progressElement.hidden=!0,e||(spinnerElement.style.display="none")),statusElement.innerHTML=e)}},totalDependencies:0,monitorRunDependencies:function(e){this.totalDependencies=Math.max(this.totalDependencies,e),Module.setStatus(e?"Preparing... ("+(this.totalDependencies-e)+"/"+this.totalDependencies+")":"All downloads complete.")}};Module.setStatus("Downloading..."),window.onerror=function(){Module.setStatus("Exception thrown, see JavaScript console"),spinnerElement.style.display="none",Module.setStatus=function(e){e&&Module.printErr("[post-exception status] "+e)}}</script><script>var audioBtn = document.querySelector('#btn-audio');
+<!doctype html>
+<html lang="en-us">
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+
+ <title>raylib HTML5 GAME</title>
+
+ <meta name="title" content="raylib HTML5 GAME">
+ <meta name="description" content="New HTML5 videogame, developed using raylib videogames library">
+ <meta name="keywords" content="raylib, games, html5, programming, C, C++, library, learn, videogames">
+ <meta name="viewport" content="width=device-width">
+
+ <!-- Open Graph metatags for sharing -->
+ <meta property="og:title" content="raylib HTML5 GAME">
+ <meta property="og:image:type" content="image/png">
+ <meta property="og:image" content="https://www.raylib.com/common/img/raylib_logo.png">
+ <meta property="og:site_name" content="raylib.com">
+ <meta property="og:url" content="https://www.raylib.com/games.html">
+ <meta property="og:description" content="New HTML5 videogame, developed using raylib videogames library">
+
+ <!-- Twitter metatags for sharing -->
+ <meta name="twitter:card" content="summary">
+ <meta name="twitter:site" content="@raysan5">
+ <meta name="twitter:title" content="raylib HTML5 GAME">
+ <meta name="twitter:image" content="https://www.raylib.com/common/raylib_logo.png">
+ <meta name="twitter:url" content="https://www.raylib.com/games.html">
+ <meta name="twitter:description" content="New HTML5 videogame, developed using raylib videogames library">
+
+ <!-- Favicon -->
+ <link rel="shortcut icon" href="https://www.raylib.com/favicon.ico">
+
+ <style>
+ body {
+ font-family: arial;
+ margin: 0;
+ padding: none;
+ }
+
+ #header {
+ width: 100%;
+ height: 80px;
+ background-color: #888888;
+ }
+
+ /* NOTE: raylib logo is embedded in the page as base64 png image */
+ #logo {
+ width:64px;
+ height:64px;
+ float:left;
+ position:relative;
+ margin:10px;
+ background-image:url('data:image/png;base64,\
+iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAIAAAAlC+aJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADs\
+MAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjExR/NCNwAAA7JJREFUaEPtk0FyWzEMQ+37X7fZhxX4\
+YY3AD1OKF1nkzTRlSBCCLeVBnvl/AUdaELOunPno1kts1kixdtEZKVs+xIxebBkZsVknn/L5nFGDLR8T4zVC9fX19S/+tTFijr\
+YK4jUjbPUtqBHpnEE6PkZD7jQZV8n5Recw1XQKciZuPaEtR6UjNs5ENVGMsBVqpPtER0ZMOhpyp8m4YL4OjD9yxsyZxnQycfMJ\
+ETNSzsRE1+dihK3YMiJmpHTW3xpmXPC6BXlCHfqnBlsjY5hxf/6EVEOM2BTEi0fYCX4ONSI6Kq3Blg/prIOMq2CsRur4KQ0x64\
+SdjOufEDEdHZGOhmz5RDHCVqhRuQ86YsVskbc+GXchLiHnFyYH+UigQDVGnImbT8hwFkgLg2qiM8JO6Ylx1FNLa3DmYwqCTsZd\
+4BPqGJG7MwKzpeiWKTKxXkLMVE3MSOmsdwxLH6Rd/wCCLSNDx6djeKfJuArGeoYamRHpaEjnCBYZVy8hZqo2GI36qPjsiOiMsB\
+XGcev4Mx9TLGTchbgEjN/uz6jGrBvDjg+LTNx8Qp2CbG2xMKgmOiPslJ4Yxx+eSnSkzlosZNwFPiHl7FRTkLNRJm4+IeVM0ymI\
+H42wE/wcKalQI4MRl4EW3p6VcRWMua8F6WjIlqZDxvVPiHQ6CjVbYkV9ohhhp/Rk1wiYgpyJ78i4CsZbjkb8Qx+ihvzu3RPaKo\
+gZkY6GlEeMsKdPSOFIC8VoOusg44L5c+T8ouOoGhWbdWJ8tMi4egkxo4hoh2yNTGf3iIyr5Lyic4bRENXo+lvDjAt4C1Hk/OKt\
+UaAj0+n4dMSZ2D+hrYJsaYh2SClG2jV9kJKKzhlGQ1SsW299Mq6C8dYZHTExo8fzieI5ivipYnYy7nwJqGKmOYyRwfiUBXITfh\
+5qSHRGWEkfqJqURgvsdHyWYv7Ko8DnYYegk3EB00cxprdrJRzFd7YQzawu8L1GMTYS/KpPaAFTkIn1EmJmspJSs5xBzSyGhlkB\
+mlxfNFiP5mw4wlbMh4F5Ddxp5jNINBdCEz9zPOC1zD7Q0HBdmXndwv0TMtydEdzlWJT4VZ8Qt9Qn4/onxMIwa5ZYGJU5yufBiC\
+jwE50AGjLCVuS8Yt4H7OgZLKK5EKOsLviEWJSL/+0uMi7gLUSBseYwqEbXvSHCec1CJvZPyHCmYQffaBBfOTCGHM2aEbZi1+gO\
+1XTWVXMnzrhAn5DSOZVsiQlHnSITKzGj6DeTcZWc/3oy7h9//PF4PL4BlvsWrb6RE+oAAAAASUVORK5CYII=');
+ }
+
+ .emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
+ div.emscripten { text-align: center; }
+ div.emscripten_border { border: 1px solid black; }
+
+ /* NOTE: Canvas *must not* have any border or padding, or mouse coords will be wrong */
+ canvas.emscripten {
+ border: 0px none;
+ background: black;
+ width: 100%
+ }
+
+ .spinner {
+ height: 30px;
+ width: 30px;
+ margin: 0;
+ margin-top: 20px;
+ margin-left: 20px;
+ display: inline-block;
+ vertical-align: top;
+ -webkit-animation: rotation .8s linear infinite;
+ -moz-animation: rotation .8s linear infinite;
+ -o-animation: rotation .8s linear infinite;
+ animation: rotation 0.8s linear infinite;
+ border-left: 5px solid black;
+ border-right: 5px solid black;
+ border-bottom: 5px solid black;
+ border-top: 5px solid red;
+ border-radius: 100%;
+ background-color: rgb(245, 245, 245);
+ }
+ @-webkit-keyframes rotation {
+ from {-webkit-transform: rotate(0deg);}
+ to {-webkit-transform: rotate(360deg);}
+ }
+ @-moz-keyframes rotation {
+ from {-moz-transform: rotate(0deg);}
+ to {-moz-transform: rotate(360deg);}
+ }
+ @-o-keyframes rotation {
+ from {-o-transform: rotate(0deg);}
+ to {-o-transform: rotate(360deg);}
+ }
+ @keyframes rotation {
+ from {transform: rotate(0deg);}
+ to {transform: rotate(360deg);}
+ }
+
+ #status {
+ display: inline-block;
+ vertical-align: top;
+ margin-top: 30px;
+ margin-left: 20px;
+ font-weight: bold;
+ color: rgb(40, 40, 40);
+ }
+
+ #progress {
+ height: 0px;
+ width: 0px;
+ }
+
+ #controls {
+ display: inline-block;
+ float: right;
+ vertical-align: top;
+ margin-top: 15px;
+ margin-right: 20px;
+ }
+
+ #output {
+ width: 100%;
+ height: 140px;
+ margin: 0 auto;
+ margin-top: 10px;
+ display: block;
+ background-color: black;
+ color: rgb(37, 174, 38);
+ font-family: 'Lucida Console', Monaco, monospace;
+ outline: none;
+ }
+
+ input[type=button] {
+ background-color: lightgray;
+ border: 4px solid darkgray;
+ color: black;
+ text-decoration: none;
+ cursor: pointer;
+ width: 140px;
+ height: 50px;
+ }
+
+ input[type=button]:hover {
+ background-color: #f5f5f5ff;
+ border-color: black;
+ }
+ </style>
+ </head>
+ <body>
+ <div id="header">
+ <a id="logo" href="https://www.raylib.com"></a>
+
+ <div class="spinner" id='spinner'></div>
+ <div class="emscripten" id="status">Downloading...</div>
+
+ <span id='controls'>
+ <span><input type="button" value="🖵 FULLSCREEN" onclick="Module.requestFullscreen(false, false)"></span>
+ <span><input type="button" id="btn-audio" value="🔇 SUSPEND" onclick="toggleAudio()"></span>
+ </span>
+
+ <div class="emscripten">
+ <progress value="0" max="100" id="progress" hidden=1></progress>
+ </div>
+ </div>
+
+ <div class="emscripten_border">
+ <canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()" tabindex=-1></canvas>
+ </div>
+
+ <textarea id="output" rows="8"></textarea>
+
+ <script type='text/javascript' src="https://cdn.jsdelivr.net/gh/eligrey/FileSaver.js/dist/FileSaver.min.js"> </script>
+ <script type='text/javascript'>
+ function saveFileFromMEMFSToDisk(memoryFSname, localFSname) // This can be called by C/C++ code
+ {
+ var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
+ var data = FS.readFile(memoryFSname);
+ var blob;
+
+ if (isSafari) blob = new Blob([data.buffer], { type: "application/octet-stream" });
+ else blob = new Blob([data.buffer], { type: "application/octet-binary" });
+
+ // NOTE: SaveAsDialog is a browser setting. For example, in Google Chrome,
+ // in Settings/Advanced/Downloads section you have a setting:
+ // 'Ask where to save each file before downloading' - which you can set true/false.
+ // If you enable this setting it would always ask you and bring the SaveAsDialog
+ saveAs(blob, localFSname);
+ }
+ </script>
+ <script type='text/javascript'>
+ var statusElement = document.querySelector('#status');
+ var progressElement = document.querySelector('#progress');
+ var spinnerElement = document.querySelector('#spinner');
+ var Module = {
+ preRun: [],
+ postRun: [],
+ print: (function() {
+ var element = document.querySelector('#output');
+
+ if (element) element.value = ''; // Clear browser cache
+
+ return function(text) {
+ if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
+ // These replacements are necessary if you render to raw HTML
+ //text = text.replace(/&/g, "&amp;");
+ //text = text.replace(/</g, "&lt;");
+ //text = text.replace(/>/g, "&gt;");
+ //text = text.replace('\n', '<br>', 'g');
+ console.log(text);
+
+ if (element) {
+ element.value += text + "\n";
+ element.scrollTop = element.scrollHeight; // focus on bottom
+ }
+ };
+ })(),
+ printErr: function(text) {
+ if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
+
+ console.error(text);
+ },
+ canvas: (function() {
+ var canvas = document.querySelector('#canvas');
+
+ // As a default initial behavior, pop up an alert when webgl context is lost.
+ // To make your application robust, you may want to override this behavior before shipping!
+ // See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
+ canvas.addEventListener("webglcontextlost", function(e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);
+
+ return canvas;
+ })(),
+ setStatus: function(text) {
+ if (!Module.setStatus.last) Module.setStatus.last = { time: Date.now(), text: '' };
+ if (text === Module.setStatus.last.text) return;
+
+ var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
+ var now = Date.now();
+
+ if (m && now - Module.setStatus.last.time < 30) return; // If this is a progress update, skip it if too soon
+
+ Module.setStatus.last.time = now;
+ Module.setStatus.last.text = text;
+
+ if (m) {
+ text = m[1];
+ progressElement.value = parseInt(m[2])*100;
+ progressElement.max = parseInt(m[4])*100;
+ progressElement.hidden = true;
+ spinnerElement.hidden = false;
+ } else {
+ progressElement.value = null;
+ progressElement.max = null;
+ progressElement.hidden = true;
+ if (!text) spinnerElement.style.display = 'none';
+ }
+
+ statusElement.innerHTML = text;
+ },
+ totalDependencies: 0,
+ monitorRunDependencies: function(left) {
+ this.totalDependencies = Math.max(this.totalDependencies, left);
+ Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
+ },
+ //noInitialRun: true
+ };
+
+ Module.setStatus('Downloading...');
+
+ window.onerror = function() {
+ Module.setStatus('Exception thrown, see JavaScript console');
+ spinnerElement.style.display = 'none';
+ Module.setStatus = function(text) { if (text) Module.printErr('[post-exception status] ' + text); };
+ };
+ </script>
+
+ <!-- REF: https://developers.google.com/web/updates/2018/11/web-audio-autoplay -->
+ <script type='text/javascript'>
+ var audioBtn = document.querySelector('#btn-audio');
// An array of all contexts to resume on the page
const audioContexList = [];
@@ -24,4 +320,10 @@
if (resumed) audioBtn.value = "🔇 SUSPEND";
else audioBtn.value = "🔈 RESUME";
- }</script><script src=models_first_person_maze.js async></script></body></html> \ No newline at end of file
+ }
+ </script>
+ <script async type="text/javascript" src="models_first_person_maze.js"></script>
+ </body>
+</html>
+
+
diff --git a/examples/web/models/models_first_person_maze.js b/examples/web/models/models_first_person_maze.js
index 2fdd2d0..b71ba88 100644
--- a/examples/web/models/models_first_person_maze.js
+++ b/examples/web/models/models_first_person_maze.js
@@ -1 +1,9272 @@
-var Module=typeof Module!=="undefined"?Module:{};if(!Module.expectedDataFileDownloads){Module.expectedDataFileDownloads=0;Module.finishedDataFileDownloads=0}Module.expectedDataFileDownloads++;(function(){var loadPackage=function(metadata){var PACKAGE_PATH;if(typeof window==="object"){PACKAGE_PATH=window["encodeURIComponent"](window.location.pathname.toString().substring(0,window.location.pathname.toString().lastIndexOf("/"))+"/")}else if(typeof location!=="undefined"){PACKAGE_PATH=encodeURIComponent(location.pathname.toString().substring(0,location.pathname.toString().lastIndexOf("/"))+"/")}else{throw"using preloaded data can only be done on a web page or in a web worker"}var PACKAGE_NAME="models/models_first_person_maze.data";var REMOTE_PACKAGE_BASE="models_first_person_maze.data";if(typeof Module["locateFilePackage"]==="function"&&!Module["locateFile"]){Module["locateFile"]=Module["locateFilePackage"];err("warning: you defined Module.locateFilePackage, that has been renamed to Module.locateFile (using your locateFilePackage for now)")}var REMOTE_PACKAGE_NAME=Module["locateFile"]?Module["locateFile"](REMOTE_PACKAGE_BASE,""):REMOTE_PACKAGE_BASE;var REMOTE_PACKAGE_SIZE=metadata.remote_package_size;var PACKAGE_UUID=metadata.package_uuid;function fetchRemotePackage(packageName,packageSize,callback,errback){var xhr=new XMLHttpRequest;xhr.open("GET",packageName,true);xhr.responseType="arraybuffer";xhr.onprogress=function(event){var url=packageName;var size=packageSize;if(event.total)size=event.total;if(event.loaded){if(!xhr.addedTotal){xhr.addedTotal=true;if(!Module.dataFileDownloads)Module.dataFileDownloads={};Module.dataFileDownloads[url]={loaded:event.loaded,total:size}}else{Module.dataFileDownloads[url].loaded=event.loaded}var total=0;var loaded=0;var num=0;for(var download in Module.dataFileDownloads){var data=Module.dataFileDownloads[download];total+=data.total;loaded+=data.loaded;num++}total=Math.ceil(total*Module.expectedDataFileDownloads/num);if(Module["setStatus"])Module["setStatus"]("Downloading data... ("+loaded+"/"+total+")")}else if(!Module.dataFileDownloads){if(Module["setStatus"])Module["setStatus"]("Downloading data...")}};xhr.onerror=function(event){throw new Error("NetworkError for: "+packageName)};xhr.onload=function(event){if(xhr.status==200||xhr.status==304||xhr.status==206||xhr.status==0&&xhr.response){var packageData=xhr.response;callback(packageData)}else{throw new Error(xhr.statusText+" : "+xhr.responseURL)}};xhr.send(null)}function handleError(error){console.error("package error:",error)}var fetchedCallback=null;var fetched=Module["getPreloadedPackage"]?Module["getPreloadedPackage"](REMOTE_PACKAGE_NAME,REMOTE_PACKAGE_SIZE):null;if(!fetched)fetchRemotePackage(REMOTE_PACKAGE_NAME,REMOTE_PACKAGE_SIZE,function(data){if(fetchedCallback){fetchedCallback(data);fetchedCallback=null}else{fetched=data}},handleError);function runWithFS(){function assert(check,msg){if(!check)throw msg+(new Error).stack}Module["FS_createPath"]("/","resources",true,true);function DataRequest(start,end,audio){this.start=start;this.end=end;this.audio=audio}DataRequest.prototype={requests:{},open:function(mode,name){this.name=name;this.requests[name]=this;Module["addRunDependency"]("fp "+this.name)},send:function(){},onload:function(){var byteArray=this.byteArray.subarray(this.start,this.end);this.finish(byteArray)},finish:function(byteArray){var that=this;Module["FS_createDataFile"](this.name,null,byteArray,true,true,true);Module["removeRunDependency"]("fp "+that.name);this.requests[this.name]=null}};var files=metadata.files;for(var i=0;i<files.length;++i){new DataRequest(files[i].start,files[i].end,files[i].audio).open("GET",files[i].filename)}function processPackageData(arrayBuffer){Module.finishedDataFileDownloads++;assert(arrayBuffer,"Loading data file failed.");assert(arrayBuffer instanceof ArrayBuffer,"bad input to processPackageData");var byteArray=new Uint8Array(arrayBuffer);var ptr=Module["getMemory"](byteArray.length);Module["HEAPU8"].set(byteArray,ptr);DataRequest.prototype.byteArray=Module["HEAPU8"].subarray(ptr,ptr+byteArray.length);var files=metadata.files;for(var i=0;i<files.length;++i){DataRequest.prototype.requests[files[i].filename].onload()}Module["removeRunDependency"]("datafile_models/models_first_person_maze.data")}Module["addRunDependency"]("datafile_models/models_first_person_maze.data");if(!Module.preloadResults)Module.preloadResults={};Module.preloadResults[PACKAGE_NAME]={fromCache:false};if(fetched){processPackageData(fetched);fetched=null}else{fetchedCallback=processPackageData}}if(Module["calledRun"]){runWithFS()}else{if(!Module["preRun"])Module["preRun"]=[];Module["preRun"].push(runWithFS)}};loadPackage({"files":[{"start":0,"audio":0,"end":201,"filename":"/resources/cubicmap.png"},{"start":201,"audio":0,"end":37426,"filename":"/resources/cubicmap_atlas.png"}],"remote_package_size":37426,"package_uuid":"e83439a9-1177-49a3-9147-d8051cedc8a6"})})();var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_HAS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_HAS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_NODE=ENVIRONMENT_HAS_NODE&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER;ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;if(ENVIRONMENT_IS_NODE){scriptDirectory=__dirname+"/";var nodeFS;var nodePath;read_=function shell_read(filename,binary){var ret;if(!nodeFS)nodeFS=require("fs");if(!nodePath)nodePath=require("path");filename=nodePath["normalize"](filename);ret=nodeFS["readFileSync"](filename);return binary?ret:ret.toString()};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/")}arguments_=process["argv"].slice(2);if(typeof module!=="undefined"){module["exports"]=Module}process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status)};Module["inspect"]=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)}}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs}else if(typeof arguments!="undefined"){arguments_=arguments}if(typeof quit==="function"){quit_=function(status){quit(status)}}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(document.currentScript){scriptDirectory=document.currentScript.src}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1)}else{scriptDirectory=""}read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)};setWindowTitle=function(title){document.title=title}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];function dynamicAlloc(size){var ret=HEAP32[DYNAMICTOP_PTR>>2];var end=ret+size+15&-16;if(end>_emscripten_get_heap_size()){abort()}HEAP32[DYNAMICTOP_PTR>>2]=end;return ret}function getNativeTypeSize(type){switch(type){case"i1":case"i8":return 1;case"i16":return 2;case"i32":return 4;case"i64":return 8;case"float":return 4;case"double":return 8;default:{if(type[type.length-1]==="*"){return 4}else if(type[0]==="i"){var bits=parseInt(type.substr(1));assert(bits%8===0,"getNativeTypeSize invalid bits "+bits+", type "+type);return bits/8}else{return 0}}}}function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;err(text)}}var asm2wasmImports={"f64-rem":function(x,y){return x%y},"debugger":function(){}};var functionPointers=new Array(0);var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(typeof WebAssembly!=="object"){err("no native wasm support detected")}function setValue(ptr,value,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":HEAP8[ptr>>0]=value;break;case"i8":HEAP8[ptr>>0]=value;break;case"i16":HEAP16[ptr>>1]=value;break;case"i32":HEAP32[ptr>>2]=value;break;case"i64":tempI64=[value>>>0,(tempDouble=value,+Math_abs(tempDouble)>=1?tempDouble>0?(Math_min(+Math_floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[ptr>>2]=tempI64[0],HEAP32[ptr+4>>2]=tempI64[1];break;case"float":HEAPF32[ptr>>2]=value;break;case"double":HEAPF64[ptr>>3]=value;break;default:abort("invalid type for setValue: "+type)}}var wasmMemory;var wasmTable;var ABORT=false;var EXITSTATUS=0;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}var ALLOC_NORMAL=0;var ALLOC_NONE=3;function allocate(slab,types,allocator,ptr){var zeroinit,size;if(typeof slab==="number"){zeroinit=true;size=slab}else{zeroinit=false;size=slab.length}var singleType=typeof types==="string"?types:null;var ret;if(allocator==ALLOC_NONE){ret=ptr}else{ret=[_malloc,stackAlloc,dynamicAlloc][allocator](Math.max(size,singleType?1:types.length))}if(zeroinit){var stop;ptr=ret;assert((ret&3)==0);stop=ret+(size&~3);for(;ptr<stop;ptr+=4){HEAP32[ptr>>2]=0}stop=ret+size;while(ptr<stop){HEAP8[ptr++>>0]=0}return ret}if(singleType==="i8"){if(slab.subarray||slab.slice){HEAPU8.set(slab,ret)}else{HEAPU8.set(new Uint8Array(slab),ret)}return ret}var i=0,type,typeSize,previousType;while(i<size){var curr=slab[i];type=singleType||types[i];if(type===0){i++;continue}if(type=="i64")type="i32";setValue(ret+i,curr,type);if(previousType!==type){typeSize=getNativeTypeSize(type);previousType=type}i+=typeSize}return ret}function getMemory(size){if(!runtimeInitialized)return dynamicAlloc(size);return _malloc(size)}var UTF8Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf8"):undefined;function UTF8ArrayToString(u8Array,idx,maxBytesToRead){var endIdx=idx+maxBytesToRead;var endPtr=idx;while(u8Array[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&u8Array.subarray&&UTF8Decoder){return UTF8Decoder.decode(u8Array.subarray(idx,endPtr))}else{var str="";while(idx<endPtr){var u0=u8Array[idx++];if(!(u0&128)){str+=String.fromCharCode(u0);continue}var u1=u8Array[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}var u2=u8Array[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2}else{u0=(u0&7)<<18|u1<<12|u2<<6|u8Array[idx++]&63}if(u0<65536){str+=String.fromCharCode(u0)}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,outU8Array,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i<str.length;++i){var u=str.charCodeAt(i);if(u>=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;outU8Array[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;outU8Array[outIdx++]=192|u>>6;outU8Array[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;outU8Array[outIdx++]=224|u>>12;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;outU8Array[outIdx++]=240|u>>18;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}}outU8Array[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i<str.length;++i){var u=str.charCodeAt(i);if(u>=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4}return len}var UTF16Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf-16le"):undefined;function allocateUTF8OnStack(str){var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8Array(str,HEAP8,ret,size);return ret}var WASM_PAGE_SIZE=65536;var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf)}var DYNAMIC_BASE=5280576,DYNAMICTOP_PTR=37664;var INITIAL_TOTAL_MEMORY=Module["TOTAL_MEMORY"]||16777216;if(Module["wasmMemory"]){wasmMemory=Module["wasmMemory"]}else{wasmMemory=new WebAssembly.Memory({"initial":INITIAL_TOTAL_MEMORY/WASM_PAGE_SIZE,"maximum":INITIAL_TOTAL_MEMORY/WASM_PAGE_SIZE})}if(wasmMemory){buffer=wasmMemory.buffer}INITIAL_TOTAL_MEMORY=buffer.byteLength;updateGlobalBufferAndViews(buffer);HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback();continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func)}else{Module["dynCall_vi"](func,callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATEXIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;if(!Module["noFSInit"]&&!FS.init.initialized)FS.init();TTY.init();callRuntimeCallbacks(__ATINIT__)}function preMain(){FS.ignorePermissions=false;callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){runtimeExited=true}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var Math_abs=Math.abs;var Math_ceil=Math.ceil;var Math_floor=Math.floor;var Math_min=Math.min;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function getUniqueRunDependency(id){return id}function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return String.prototype.startsWith?filename.startsWith(dataURIPrefix):filename.indexOf(dataURIPrefix)===0}var wasmBinaryFile="models_first_person_maze.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw"both async and sync fetching of the wasm failed"}}catch(err){abort(err)}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw"failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return new Promise(function(resolve,reject){resolve(getBinary())})}function createWasm(env){var info={"env":env,"wasi_unstable":env,"global":{"NaN":NaN,Infinity:Infinity},"global.Math":Math,"asm2wasm":asm2wasmImports};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;removeRunDependency("wasm-instantiate")}addRunDependency("wasm-instantiate");function receiveInstantiatedSource(output){receiveInstance(output["instance"])}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason)})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");instantiateArrayBuffer(receiveInstantiatedSource)})})}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return{}}Module["asm"]=function(global,env,providedBuffer){env["memory"]=wasmMemory;env["table"]=wasmTable=new WebAssembly.Table({"initial":322,"maximum":322,"element":"anyfunc"});env["__memory_base"]=1024;env["__table_base"]=0;var exports=createWasm(env);return exports};var tempDouble;var tempI64;function demangle(func){return func}function demangleAll(text){var regex=/\b__Z[\w\d_]+/g;return text.replace(regex,function(x){var y=demangle(x);return x===y?x:y+" ["+x+"]"})}function jsStackTrace(){var err=new Error;if(!err.stack){try{throw new Error(0)}catch(e){err=e}if(!err.stack){return"(no stack trace available)"}}return err.stack.toString()}function stackTrace(){var js=jsStackTrace();if(Module["extraStackTrace"])js+="\n"+Module["extraStackTrace"]();return demangleAll(js)}function ___assert_fail(condition,filename,line,func){abort("Assertion failed: "+UTF8ToString(condition)+", at: "+[filename?UTF8ToString(filename):"unknown filename",line,func?UTF8ToString(func):"unknown function"])}function ___lock(){}var PATH={splitPath:function(filename){var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:function(parts,allowAboveRoot){var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:function(path){var isAbsolute=path.charAt(0)==="/",trailingSlash=path.substr(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(function(p){return!!p}),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:function(path){var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir},basename:function(path){if(path==="/")return"/";var lastSlash=path.lastIndexOf("/");if(lastSlash===-1)return path;return path.substr(lastSlash+1)},extname:function(path){return PATH.splitPath(path)[3]},join:function(){var paths=Array.prototype.slice.call(arguments,0);return PATH.normalize(paths.join("/"))},join2:function(l,r){return PATH.normalize(l+"/"+r)}};function ___setErrNo(value){if(Module["___errno_location"])HEAP32[Module["___errno_location"]()>>2]=value;return value}var PATH_FS={resolve:function(){var resolvedPath="",resolvedAbsolute=false;for(var i=arguments.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?arguments[i]:FS.cwd();if(typeof path!=="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){return""}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=path.charAt(0)==="/"}resolvedPath=PATH.normalizeArray(resolvedPath.split("/").filter(function(p){return!!p}),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."},relative:function(from,to){from=PATH_FS.resolve(from).substr(1);to=PATH_FS.resolve(to).substr(1);function trim(arr){var start=0;for(;start<arr.length;start++){if(arr[start]!=="")break}var end=arr.length-1;for(;end>=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i<length;i++){if(fromParts[i]!==toParts[i]){samePartsLength=i;break}}var outputParts=[];for(var i=samePartsLength;i<fromParts.length;i++){outputParts.push("..")}outputParts=outputParts.concat(toParts.slice(samePartsLength));return outputParts.join("/")}};var TTY={ttys:[],init:function(){},shutdown:function(){},register:function(dev,ops){TTY.ttys[dev]={input:[],output:[],ops:ops};FS.registerDevice(dev,TTY.stream_ops)},stream_ops:{open:function(stream){var tty=TTY.ttys[stream.node.rdev];if(!tty){throw new FS.ErrnoError(19)}stream.tty=tty;stream.seekable=false},close:function(stream){stream.tty.ops.flush(stream.tty)},flush:function(stream){stream.tty.ops.flush(stream.tty)},read:function(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.get_char){throw new FS.ErrnoError(6)}var bytesRead=0;for(var i=0;i<length;i++){var result;try{result=stream.tty.ops.get_char(stream.tty)}catch(e){throw new FS.ErrnoError(5)}if(result===undefined&&bytesRead===0){throw new FS.ErrnoError(11)}if(result===null||result===undefined)break;bytesRead++;buffer[offset+i]=result}if(bytesRead){stream.node.timestamp=Date.now()}return bytesRead},write:function(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.put_char){throw new FS.ErrnoError(6)}try{for(var i=0;i<length;i++){stream.tty.ops.put_char(stream.tty,buffer[offset+i])}}catch(e){throw new FS.ErrnoError(5)}if(length){stream.node.timestamp=Date.now()}return i}},default_tty_ops:{get_char:function(tty){if(!tty.input.length){var result=null;if(ENVIRONMENT_IS_NODE){var BUFSIZE=256;var buf=Buffer.alloc?Buffer.alloc(BUFSIZE):new Buffer(BUFSIZE);var bytesRead=0;var isPosixPlatform=process.platform!="win32";var fd=process.stdin.fd;if(isPosixPlatform){var usingDevice=false;try{fd=fs.openSync("/dev/stdin","r");usingDevice=true}catch(e){}}try{bytesRead=fs.readSync(fd,buf,0,BUFSIZE,null)}catch(e){if(e.toString().indexOf("EOF")!=-1)bytesRead=0;else throw e}if(usingDevice){fs.closeSync(fd)}if(bytesRead>0){result=buf.slice(0,bytesRead).toString("utf-8")}else{result=null}}else if(typeof window!="undefined"&&typeof window.prompt=="function"){result=window.prompt("Input: ");if(result!==null){result+="\n"}}else if(typeof readline=="function"){result=readline();if(result!==null){result+="\n"}}if(!result){return null}tty.input=intArrayFromString(result,true)}return tty.input.shift()},put_char:function(tty,val){if(val===null||val===10){out(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},flush:function(tty){if(tty.output&&tty.output.length>0){out(UTF8ArrayToString(tty.output,0));tty.output=[]}}},default_tty1_ops:{put_char:function(tty,val){if(val===null||val===10){err(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},flush:function(tty){if(tty.output&&tty.output.length>0){err(UTF8ArrayToString(tty.output,0));tty.output=[]}}}};var MEMFS={ops_table:null,mount:function(mount){return MEMFS.createNode(null,"/",16384|511,0)},createNode:function(parent,name,mode,dev){if(FS.isBlkdev(mode)||FS.isFIFO(mode)){throw new FS.ErrnoError(1)}if(!MEMFS.ops_table){MEMFS.ops_table={dir:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,lookup:MEMFS.node_ops.lookup,mknod:MEMFS.node_ops.mknod,rename:MEMFS.node_ops.rename,unlink:MEMFS.node_ops.unlink,rmdir:MEMFS.node_ops.rmdir,readdir:MEMFS.node_ops.readdir,symlink:MEMFS.node_ops.symlink},stream:{llseek:MEMFS.stream_ops.llseek}},file:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},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}},link:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,readlink:MEMFS.node_ops.readlink},stream:{}},chrdev:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:FS.chrdev_stream_ops}}}var node=FS.createNode(parent,name,mode,dev);if(FS.isDir(node.mode)){node.node_ops=MEMFS.ops_table.dir.node;node.stream_ops=MEMFS.ops_table.dir.stream;node.contents={}}else if(FS.isFile(node.mode)){node.node_ops=MEMFS.ops_table.file.node;node.stream_ops=MEMFS.ops_table.file.stream;node.usedBytes=0;node.contents=null}else if(FS.isLink(node.mode)){node.node_ops=MEMFS.ops_table.link.node;node.stream_ops=MEMFS.ops_table.link.stream}else if(FS.isChrdev(node.mode)){node.node_ops=MEMFS.ops_table.chrdev.node;node.stream_ops=MEMFS.ops_table.chrdev.stream}node.timestamp=Date.now();if(parent){parent.contents[name]=node}return node},getFileDataAsRegularArray:function(node){if(node.contents&&node.contents.subarray){var arr=[];for(var i=0;i<node.usedBytes;++i)arr.push(node.contents[i]);return arr}return node.contents},getFileDataAsTypedArray:function(node){if(!node.contents)return new Uint8Array;if(node.contents.subarray)return node.contents.subarray(0,node.usedBytes);return new Uint8Array(node.contents)},expandFileStorage:function(node,newCapacity){var prevCapacity=node.contents?node.contents.length:0;if(prevCapacity>=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity<CAPACITY_DOUBLING_MAX?2:1.125)|0);if(prevCapacity!=0)newCapacity=Math.max(newCapacity,256);var oldContents=node.contents;node.contents=new Uint8Array(newCapacity);if(node.usedBytes>0)node.contents.set(oldContents.subarray(0,node.usedBytes),0);return},resizeFileStorage:function(node,newSize){if(node.usedBytes==newSize)return;if(newSize==0){node.contents=null;node.usedBytes=0;return}if(!node.contents||node.contents.subarray){var oldContents=node.contents;node.contents=new Uint8Array(new ArrayBuffer(newSize));if(oldContents){node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)))}node.usedBytes=newSize;return}if(!node.contents)node.contents=[];if(node.contents.length>newSize)node.contents.length=newSize;else while(node.contents.length<newSize)node.contents.push(0);node.usedBytes=newSize},node_ops:{getattr:function(node){var attr={};attr.dev=FS.isChrdev(node.mode)?node.id:1;attr.ino=node.id;attr.mode=node.mode;attr.nlink=1;attr.uid=0;attr.gid=0;attr.rdev=node.rdev;if(FS.isDir(node.mode)){attr.size=4096}else if(FS.isFile(node.mode)){attr.size=node.usedBytes}else if(FS.isLink(node.mode)){attr.size=node.link.length}else{attr.size=0}attr.atime=new Date(node.timestamp);attr.mtime=new Date(node.timestamp);attr.ctime=new Date(node.timestamp);attr.blksize=4096;attr.blocks=Math.ceil(attr.size/attr.blksize);return attr},setattr:function(node,attr){if(attr.mode!==undefined){node.mode=attr.mode}if(attr.timestamp!==undefined){node.timestamp=attr.timestamp}if(attr.size!==undefined){MEMFS.resizeFileStorage(node,attr.size)}},lookup:function(parent,name){throw FS.genericErrors[2]},mknod:function(parent,name,mode,dev){return MEMFS.createNode(parent,name,mode,dev)},rename:function(old_node,new_dir,new_name){if(FS.isDir(old_node.mode)){var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(new_node){for(var i in new_node.contents){throw new FS.ErrnoError(39)}}}delete old_node.parent.contents[old_node.name];old_node.name=new_name;new_dir.contents[new_name]=old_node;old_node.parent=new_dir},unlink:function(parent,name){delete parent.contents[name]},rmdir:function(parent,name){var node=FS.lookupNode(parent,name);for(var i in node.contents){throw new FS.ErrnoError(39)}delete parent.contents[name]},readdir:function(node){var entries=[".",".."];for(var key in node.contents){if(!node.contents.hasOwnProperty(key)){continue}entries.push(key)}return entries},symlink:function(parent,newname,oldpath){var node=MEMFS.createNode(parent,newname,511|40960,0);node.link=oldpath;return node},readlink:function(node){if(!FS.isLink(node.mode)){throw new FS.ErrnoError(22)}return node.link}},stream_ops:{read:function(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);if(size>8&&contents.subarray){buffer.set(contents.subarray(position,position+size),offset)}else{for(var i=0;i<size;i++)buffer[offset+i]=contents[position+i]}return size},write:function(stream,buffer,offset,length,position,canOwn){if(!length)return 0;var node=stream.node;node.timestamp=Date.now();if(buffer.subarray&&(!node.contents||node.contents.subarray)){if(canOwn){node.contents=buffer.subarray(offset,offset+length);node.usedBytes=length;return length}else if(node.usedBytes===0&&position===0){node.contents=new Uint8Array(buffer.subarray(offset,offset+length));node.usedBytes=length;return length}else if(position+length<=node.usedBytes){node.contents.set(buffer.subarray(offset,offset+length),position);return length}}MEMFS.expandFileStorage(node,position+length);if(node.contents.subarray&&buffer.subarray)node.contents.set(buffer.subarray(offset,offset+length),position);else{for(var i=0;i<length;i++){node.contents[position+i]=buffer[offset+i]}}node.usedBytes=Math.max(node.usedBytes,position+length);return length},llseek:function(stream,offset,whence){var position=offset;if(whence===1){position+=stream.position}else if(whence===2){if(FS.isFile(stream.node.mode)){position+=stream.node.usedBytes}}if(position<0){throw new FS.ErrnoError(22)}return position},allocate:function(stream,offset,length){MEMFS.expandFileStorage(stream.node,offset+length);stream.node.usedBytes=Math.max(stream.node.usedBytes,offset+length)},mmap:function(stream,buffer,offset,length,position,prot,flags){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(19)}var ptr;var allocated;var contents=stream.node.contents;if(!(flags&2)&&(contents.buffer===buffer||contents.buffer===buffer.buffer)){allocated=false;ptr=contents.byteOffset}else{if(position>0||position+length<stream.node.usedBytes){if(contents.subarray){contents=contents.subarray(position,position+length)}else{contents=Array.prototype.slice.call(contents,position,position+length)}}allocated=true;var fromHeap=buffer.buffer==HEAP8.buffer;ptr=_malloc(length);if(!ptr){throw new FS.ErrnoError(12)}(fromHeap?HEAP8:buffer).set(contents,ptr)}return{ptr:ptr,allocated:allocated}},msync:function(stream,buffer,offset,length,mmapFlags){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(19)}if(mmapFlags&2){return 0}var bytesWritten=MEMFS.stream_ops.write(stream,buffer,0,length,offset,false);return 0}}};var IDBFS={dbs:{},indexedDB:function(){if(typeof indexedDB!=="undefined")return indexedDB;var ret=null;if(typeof window==="object")ret=window.indexedDB||window.mozIndexedDB||window.webkitIndexedDB||window.msIndexedDB;assert(ret,"IDBFS used, but indexedDB not supported");return ret},DB_VERSION:21,DB_STORE_NAME:"FILE_DATA",mount:function(mount){return MEMFS.mount.apply(null,arguments)},syncfs:function(mount,populate,callback){IDBFS.getLocalSet(mount,function(err,local){if(err)return callback(err);IDBFS.getRemoteSet(mount,function(err,remote){if(err)return callback(err);var src=populate?remote:local;var dst=populate?local:remote;IDBFS.reconcile(src,dst,callback)})})},getDB:function(name,callback){var db=IDBFS.dbs[name];if(db){return callback(null,db)}var req;try{req=IDBFS.indexedDB().open(name,IDBFS.DB_VERSION)}catch(e){return callback(e)}if(!req){return callback("Unable to connect to IndexedDB")}req.onupgradeneeded=function(e){var db=e.target.result;var transaction=e.target.transaction;var fileStore;if(db.objectStoreNames.contains(IDBFS.DB_STORE_NAME)){fileStore=transaction.objectStore(IDBFS.DB_STORE_NAME)}else{fileStore=db.createObjectStore(IDBFS.DB_STORE_NAME)}if(!fileStore.indexNames.contains("timestamp")){fileStore.createIndex("timestamp","timestamp",{unique:false})}};req.onsuccess=function(){db=req.result;IDBFS.dbs[name]=db;callback(null,db)};req.onerror=function(e){callback(this.error);e.preventDefault()}},getLocalSet:function(mount,callback){var entries={};function isRealDir(p){return p!=="."&&p!==".."}function toAbsolute(root){return function(p){return PATH.join2(root,p)}}var check=FS.readdir(mount.mountpoint).filter(isRealDir).map(toAbsolute(mount.mountpoint));while(check.length){var path=check.pop();var stat;try{stat=FS.stat(path)}catch(e){return callback(e)}if(FS.isDir(stat.mode)){check.push.apply(check,FS.readdir(path).filter(isRealDir).map(toAbsolute(path)))}entries[path]={timestamp:stat.mtime}}return callback(null,{type:"local",entries:entries})},getRemoteSet:function(mount,callback){var entries={};IDBFS.getDB(mount.mountpoint,function(err,db){if(err)return callback(err);try{var transaction=db.transaction([IDBFS.DB_STORE_NAME],"readonly");transaction.onerror=function(e){callback(this.error);e.preventDefault()};var store=transaction.objectStore(IDBFS.DB_STORE_NAME);var index=store.index("timestamp");index.openKeyCursor().onsuccess=function(event){var cursor=event.target.result;if(!cursor){return callback(null,{type:"remote",db:db,entries:entries})}entries[cursor.primaryKey]={timestamp:cursor.key};cursor.continue()}}catch(e){return callback(e)}})},loadLocalEntry:function(path,callback){var stat,node;try{var lookup=FS.lookupPath(path);node=lookup.node;stat=FS.stat(path)}catch(e){return callback(e)}if(FS.isDir(stat.mode)){return callback(null,{timestamp:stat.mtime,mode:stat.mode})}else if(FS.isFile(stat.mode)){node.contents=MEMFS.getFileDataAsTypedArray(node);return callback(null,{timestamp:stat.mtime,mode:stat.mode,contents:node.contents})}else{return callback(new Error("node type not supported"))}},storeLocalEntry:function(path,entry,callback){try{if(FS.isDir(entry.mode)){FS.mkdir(path,entry.mode)}else if(FS.isFile(entry.mode)){FS.writeFile(path,entry.contents,{canOwn:true})}else{return callback(new Error("node type not supported"))}FS.chmod(path,entry.mode);FS.utime(path,entry.timestamp,entry.timestamp)}catch(e){return callback(e)}callback(null)},removeLocalEntry:function(path,callback){try{var lookup=FS.lookupPath(path);var stat=FS.stat(path);if(FS.isDir(stat.mode)){FS.rmdir(path)}else if(FS.isFile(stat.mode)){FS.unlink(path)}}catch(e){return callback(e)}callback(null)},loadRemoteEntry:function(store,path,callback){var req=store.get(path);req.onsuccess=function(event){callback(null,event.target.result)};req.onerror=function(e){callback(this.error);e.preventDefault()}},storeRemoteEntry:function(store,path,entry,callback){var req=store.put(entry,path);req.onsuccess=function(){callback(null)};req.onerror=function(e){callback(this.error);e.preventDefault()}},removeRemoteEntry:function(store,path,callback){var req=store.delete(path);req.onsuccess=function(){callback(null)};req.onerror=function(e){callback(this.error);e.preventDefault()}},reconcile:function(src,dst,callback){var total=0;var create=[];Object.keys(src.entries).forEach(function(key){var e=src.entries[key];var e2=dst.entries[key];if(!e2||e.timestamp>e2.timestamp){create.push(key);total++}});var remove=[];Object.keys(dst.entries).forEach(function(key){var e=dst.entries[key];var e2=src.entries[key];if(!e2){remove.push(key);total++}});if(!total){return callback(null)}var errored=false;var db=src.type==="remote"?src.db:dst.db;var transaction=db.transaction([IDBFS.DB_STORE_NAME],"readwrite");var store=transaction.objectStore(IDBFS.DB_STORE_NAME);function done(err){if(err&&!errored){errored=true;return callback(err)}}transaction.onerror=function(e){done(this.error);e.preventDefault()};transaction.oncomplete=function(e){if(!errored){callback(null)}};create.sort().forEach(function(path){if(dst.type==="local"){IDBFS.loadRemoteEntry(store,path,function(err,entry){if(err)return done(err);IDBFS.storeLocalEntry(path,entry,done)})}else{IDBFS.loadLocalEntry(path,function(err,entry){if(err)return done(err);IDBFS.storeRemoteEntry(store,path,entry,done)})}});remove.sort().reverse().forEach(function(path){if(dst.type==="local"){IDBFS.removeLocalEntry(path,done)}else{IDBFS.removeRemoteEntry(store,path,done)}})}};var NODEFS={isWindows:false,staticInit:function(){NODEFS.isWindows=!!process.platform.match(/^win/);var flags=process["binding"]("constants");if(flags["fs"]){flags=flags["fs"]}NODEFS.flagsForNodeMap={1024:flags["O_APPEND"],64:flags["O_CREAT"],128:flags["O_EXCL"],0:flags["O_RDONLY"],2:flags["O_RDWR"],4096:flags["O_SYNC"],512:flags["O_TRUNC"],1:flags["O_WRONLY"]}},bufferFrom:function(arrayBuffer){return Buffer["alloc"]?Buffer.from(arrayBuffer):new Buffer(arrayBuffer)},mount:function(mount){assert(ENVIRONMENT_HAS_NODE);return NODEFS.createNode(null,"/",NODEFS.getMode(mount.opts.root),0)},createNode:function(parent,name,mode,dev){if(!FS.isDir(mode)&&!FS.isFile(mode)&&!FS.isLink(mode)){throw new FS.ErrnoError(22)}var node=FS.createNode(parent,name,mode);node.node_ops=NODEFS.node_ops;node.stream_ops=NODEFS.stream_ops;return node},getMode:function(path){var stat;try{stat=fs.lstatSync(path);if(NODEFS.isWindows){stat.mode=stat.mode|(stat.mode&292)>>2}}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(-e.errno)}return stat.mode},realPath:function(node){var parts=[];while(node.parent!==node){parts.push(node.name);node=node.parent}parts.push(node.mount.opts.root);parts.reverse();return PATH.join.apply(null,parts)},flagsForNode:function(flags){flags&=~2097152;flags&=~2048;flags&=~32768;flags&=~524288;var newFlags=0;for(var k in NODEFS.flagsForNodeMap){if(flags&k){newFlags|=NODEFS.flagsForNodeMap[k];flags^=k}}if(!flags){return newFlags}else{throw new FS.ErrnoError(22)}},node_ops:{getattr:function(node){var path=NODEFS.realPath(node);var stat;try{stat=fs.lstatSync(path)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(-e.errno)}if(NODEFS.isWindows&&!stat.blksize){stat.blksize=4096}if(NODEFS.isWindows&&!stat.blocks){stat.blocks=(stat.size+stat.blksize-1)/stat.blksize|0}return{dev:stat.dev,ino:stat.ino,mode:stat.mode,nlink:stat.nlink,uid:stat.uid,gid:stat.gid,rdev:stat.rdev,size:stat.size,atime:stat.atime,mtime:stat.mtime,ctime:stat.ctime,blksize:stat.blksize,blocks:stat.blocks}},setattr:function(node,attr){var path=NODEFS.realPath(node);try{if(attr.mode!==undefined){fs.chmodSync(path,attr.mode);node.mode=attr.mode}if(attr.timestamp!==undefined){var date=new Date(attr.timestamp);fs.utimesSync(path,date,date)}if(attr.size!==undefined){fs.truncateSync(path,attr.size)}}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(-e.errno)}},lookup:function(parent,name){var path=PATH.join2(NODEFS.realPath(parent),name);var mode=NODEFS.getMode(path);return NODEFS.createNode(parent,name,mode)},mknod:function(parent,name,mode,dev){var node=NODEFS.createNode(parent,name,mode,dev);var path=NODEFS.realPath(node);try{if(FS.isDir(node.mode)){fs.mkdirSync(path,node.mode)}else{fs.writeFileSync(path,"",{mode:node.mode})}}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(-e.errno)}return node},rename:function(oldNode,newDir,newName){var oldPath=NODEFS.realPath(oldNode);var newPath=PATH.join2(NODEFS.realPath(newDir),newName);try{fs.renameSync(oldPath,newPath)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(-e.errno)}},unlink:function(parent,name){var path=PATH.join2(NODEFS.realPath(parent),name);try{fs.unlinkSync(path)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(-e.errno)}},rmdir:function(parent,name){var path=PATH.join2(NODEFS.realPath(parent),name);try{fs.rmdirSync(path)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(-e.errno)}},readdir:function(node){var path=NODEFS.realPath(node);try{return fs.readdirSync(path)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(-e.errno)}},symlink:function(parent,newName,oldPath){var newPath=PATH.join2(NODEFS.realPath(parent),newName);try{fs.symlinkSync(oldPath,newPath)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(-e.errno)}},readlink:function(node){var path=NODEFS.realPath(node);try{path=fs.readlinkSync(path);path=NODEJS_PATH.relative(NODEJS_PATH.resolve(node.mount.opts.root),path);return path}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(-e.errno)}}},stream_ops:{open:function(stream){var path=NODEFS.realPath(stream.node);try{if(FS.isFile(stream.node.mode)){stream.nfd=fs.openSync(path,NODEFS.flagsForNode(stream.flags))}}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(-e.errno)}},close:function(stream){try{if(FS.isFile(stream.node.mode)&&stream.nfd){fs.closeSync(stream.nfd)}}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(-e.errno)}},read:function(stream,buffer,offset,length,position){if(length===0)return 0;try{return fs.readSync(stream.nfd,NODEFS.bufferFrom(buffer.buffer),offset,length,position)}catch(e){throw new FS.ErrnoError(-e.errno)}},write:function(stream,buffer,offset,length,position){try{return fs.writeSync(stream.nfd,NODEFS.bufferFrom(buffer.buffer),offset,length,position)}catch(e){throw new FS.ErrnoError(-e.errno)}},llseek:function(stream,offset,whence){var position=offset;if(whence===1){position+=stream.position}else if(whence===2){if(FS.isFile(stream.node.mode)){try{var stat=fs.fstatSync(stream.nfd);position+=stat.size}catch(e){throw new FS.ErrnoError(-e.errno)}}}if(position<0){throw new FS.ErrnoError(22)}return position}}};var WORKERFS={DIR_MODE:16895,FILE_MODE:33279,reader:null,mount:function(mount){assert(ENVIRONMENT_IS_WORKER);if(!WORKERFS.reader)WORKERFS.reader=new FileReaderSync;var root=WORKERFS.createNode(null,"/",WORKERFS.DIR_MODE,0);var createdParents={};function ensureParent(path){var parts=path.split("/");var parent=root;for(var i=0;i<parts.length-1;i++){var curr=parts.slice(0,i+1).join("/");if(!createdParents[curr]){createdParents[curr]=WORKERFS.createNode(parent,parts[i],WORKERFS.DIR_MODE,0)}parent=createdParents[curr]}return parent}function base(path){var parts=path.split("/");return parts[parts.length-1]}Array.prototype.forEach.call(mount.opts["files"]||[],function(file){WORKERFS.createNode(ensureParent(file.name),base(file.name),WORKERFS.FILE_MODE,0,file,file.lastModifiedDate)});(mount.opts["blobs"]||[]).forEach(function(obj){WORKERFS.createNode(ensureParent(obj["name"]),base(obj["name"]),WORKERFS.FILE_MODE,0,obj["data"])});(mount.opts["packages"]||[]).forEach(function(pack){pack["metadata"].files.forEach(function(file){var name=file.filename.substr(1);WORKERFS.createNode(ensureParent(name),base(name),WORKERFS.FILE_MODE,0,pack["blob"].slice(file.start,file.end))})});return root},createNode:function(parent,name,mode,dev,contents,mtime){var node=FS.createNode(parent,name,mode);node.mode=mode;node.node_ops=WORKERFS.node_ops;node.stream_ops=WORKERFS.stream_ops;node.timestamp=(mtime||new Date).getTime();assert(WORKERFS.FILE_MODE!==WORKERFS.DIR_MODE);if(mode===WORKERFS.FILE_MODE){node.size=contents.size;node.contents=contents}else{node.size=4096;node.contents={}}if(parent){parent.contents[name]=node}return node},node_ops:{getattr:function(node){return{dev:1,ino:undefined,mode:node.mode,nlink:1,uid:0,gid:0,rdev:undefined,size:node.size,atime:new Date(node.timestamp),mtime:new Date(node.timestamp),ctime:new Date(node.timestamp),blksize:4096,blocks:Math.ceil(node.size/4096)}},setattr:function(node,attr){if(attr.mode!==undefined){node.mode=attr.mode}if(attr.timestamp!==undefined){node.timestamp=attr.timestamp}},lookup:function(parent,name){throw new FS.ErrnoError(2)},mknod:function(parent,name,mode,dev){throw new FS.ErrnoError(1)},rename:function(oldNode,newDir,newName){throw new FS.ErrnoError(1)},unlink:function(parent,name){throw new FS.ErrnoError(1)},rmdir:function(parent,name){throw new FS.ErrnoError(1)},readdir:function(node){var entries=[".",".."];for(var key in node.contents){if(!node.contents.hasOwnProperty(key)){continue}entries.push(key)}return entries},symlink:function(parent,newName,oldPath){throw new FS.ErrnoError(1)},readlink:function(node){throw new FS.ErrnoError(1)}},stream_ops:{read:function(stream,buffer,offset,length,position){if(position>=stream.node.size)return 0;var chunk=stream.node.contents.slice(position,position+length);var ab=WORKERFS.reader.readAsArrayBuffer(chunk);buffer.set(new Uint8Array(ab),offset);return chunk.size},write:function(stream,buffer,offset,length,position){throw new FS.ErrnoError(5)},llseek:function(stream,offset,whence){var position=offset;if(whence===1){position+=stream.position}else if(whence===2){if(FS.isFile(stream.node.mode)){position+=stream.node.size}}if(position<0){throw new FS.ErrnoError(22)}return position}}};var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,trackingDelegate:{},tracking:{openFlags:{READ:1,WRITE:2}},ErrnoError:null,genericErrors:{},filesystems:null,syncFSRequests:0,handleFSError:function(e){if(!(e instanceof FS.ErrnoError))throw e+" : "+stackTrace();return ___setErrNo(e.errno)},lookupPath:function(path,opts){path=PATH_FS.resolve(FS.cwd(),path);opts=opts||{};if(!path)return{path:"",node:null};var defaults={follow_mount:true,recurse_count:0};for(var key in defaults){if(opts[key]===undefined){opts[key]=defaults[key]}}if(opts.recurse_count>8){throw new FS.ErrnoError(40)}var parts=PATH.normalizeArray(path.split("/").filter(function(p){return!!p}),false);var current=FS.root;var current_path="/";for(var i=0;i<parts.length;i++){var islast=i===parts.length-1;if(islast&&opts.parent){break}current=FS.lookupNode(current,parts[i]);current_path=PATH.join2(current_path,parts[i]);if(FS.isMountpoint(current)){if(!islast||islast&&opts.follow_mount){current=current.mounted.root}}if(!islast||opts.follow){var count=0;while(FS.isLink(current.mode)){var link=FS.readlink(current_path);current_path=PATH_FS.resolve(PATH.dirname(current_path),link);var lookup=FS.lookupPath(current_path,{recurse_count:opts.recurse_count});current=lookup.node;if(count++>40){throw new FS.ErrnoError(40)}}}}return{path:current_path,node:current}},getPath:function(node){var path;while(true){if(FS.isRoot(node)){var mount=node.mount.mountpoint;if(!path)return mount;return mount[mount.length-1]!=="/"?mount+"/"+path:mount+path}path=path?node.name+"/"+path:node.name;node=node.parent}},hashName:function(parentid,name){var hash=0;for(var i=0;i<name.length;i++){hash=(hash<<5)-hash+name.charCodeAt(i)|0}return(parentid+hash>>>0)%FS.nameTable.length},hashAddNode:function(node){var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node},hashRemoveNode:function(node){var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}},lookupNode:function(parent,name){var err=FS.mayLookup(parent);if(err){throw new FS.ErrnoError(err,parent)}var hash=FS.hashName(parent.id,name);for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)},createNode:function(parent,name,mode,rdev){if(!FS.FSNode){FS.FSNode=function(parent,name,mode,rdev){if(!parent){parent=this}this.parent=parent;this.mount=parent.mount;this.mounted=null;this.id=FS.nextInode++;this.name=name;this.mode=mode;this.node_ops={};this.stream_ops={};this.rdev=rdev};FS.FSNode.prototype={};var readMode=292|73;var writeMode=146;Object.defineProperties(FS.FSNode.prototype,{read:{get:function(){return(this.mode&readMode)===readMode},set:function(val){val?this.mode|=readMode:this.mode&=~readMode}},write:{get:function(){return(this.mode&writeMode)===writeMode},set:function(val){val?this.mode|=writeMode:this.mode&=~writeMode}},isFolder:{get:function(){return FS.isDir(this.mode)}},isDevice:{get:function(){return FS.isChrdev(this.mode)}}})}var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node},destroyNode:function(node){FS.hashRemoveNode(node)},isRoot:function(node){return node===node.parent},isMountpoint:function(node){return!!node.mounted},isFile:function(mode){return(mode&61440)===32768},isDir:function(mode){return(mode&61440)===16384},isLink:function(mode){return(mode&61440)===40960},isChrdev:function(mode){return(mode&61440)===8192},isBlkdev:function(mode){return(mode&61440)===24576},isFIFO:function(mode){return(mode&61440)===4096},isSocket:function(mode){return(mode&49152)===49152},flagModes:{"r":0,"rs":1052672,"r+":2,"w":577,"wx":705,"xw":705,"w+":578,"wx+":706,"xw+":706,"a":1089,"ax":1217,"xa":1217,"a+":1090,"ax+":1218,"xa+":1218},modeStringToFlags:function(str){var flags=FS.flagModes[str];if(typeof flags==="undefined"){throw new Error("Unknown file open mode: "+str)}return flags},flagsToPermissionString:function(flag){var perms=["r","w","rw"][flag&3];if(flag&512){perms+="w"}return perms},nodePermissions:function(node,perms){if(FS.ignorePermissions){return 0}if(perms.indexOf("r")!==-1&&!(node.mode&292)){return 13}else if(perms.indexOf("w")!==-1&&!(node.mode&146)){return 13}else if(perms.indexOf("x")!==-1&&!(node.mode&73)){return 13}return 0},mayLookup:function(dir){var err=FS.nodePermissions(dir,"x");if(err)return err;if(!dir.node_ops.lookup)return 13;return 0},mayCreate:function(dir,name){try{var node=FS.lookupNode(dir,name);return 17}catch(e){}return FS.nodePermissions(dir,"wx")},mayDelete:function(dir,name,isdir){var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var err=FS.nodePermissions(dir,"wx");if(err){return err}if(isdir){if(!FS.isDir(node.mode)){return 20}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return 16}}else{if(FS.isDir(node.mode)){return 21}}return 0},mayOpen:function(node,flags){if(!node){return 2}if(FS.isLink(node.mode)){return 40}else if(FS.isDir(node.mode)){if(FS.flagsToPermissionString(flags)!=="r"||flags&512){return 21}}return FS.nodePermissions(node,FS.flagsToPermissionString(flags))},MAX_OPEN_FDS:4096,nextfd:function(fd_start,fd_end){fd_start=fd_start||0;fd_end=fd_end||FS.MAX_OPEN_FDS;for(var fd=fd_start;fd<=fd_end;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(24)},getStream:function(fd){return FS.streams[fd]},createStream:function(stream,fd_start,fd_end){if(!FS.FSStream){FS.FSStream=function(){};FS.FSStream.prototype={};Object.defineProperties(FS.FSStream.prototype,{object:{get:function(){return this.node},set:function(val){this.node=val}},isRead:{get:function(){return(this.flags&2097155)!==1}},isWrite:{get:function(){return(this.flags&2097155)!==0}},isAppend:{get:function(){return this.flags&1024}}})}var newStream=new FS.FSStream;for(var p in stream){newStream[p]=stream[p]}stream=newStream;var fd=FS.nextfd(fd_start,fd_end);stream.fd=fd;FS.streams[fd]=stream;return stream},closeStream:function(fd){FS.streams[fd]=null},chrdev_stream_ops:{open:function(stream){var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;if(stream.stream_ops.open){stream.stream_ops.open(stream)}},llseek:function(){throw new FS.ErrnoError(29)}},major:function(dev){return dev>>8},minor:function(dev){return dev&255},makedev:function(ma,mi){return ma<<8|mi},registerDevice:function(dev,ops){FS.devices[dev]={stream_ops:ops}},getDevice:function(dev){return FS.devices[dev]},getMounts:function(mount){var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push.apply(check,m.mounts)}return mounts},syncfs:function(populate,callback){if(typeof populate==="function"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){console.log("warning: "+FS.syncFSRequests+" FS.syncfs operations in flight at once, probably just doing extra work")}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(err){FS.syncFSRequests--;return callback(err)}function done(err){if(err){if(!done.errored){done.errored=true;return doCallback(err)}return}if(++completed>=mounts.length){doCallback(null)}}mounts.forEach(function(mount){if(!mount.type.syncfs){return done(null)}mount.type.syncfs(mount,populate,done)})},mount:function(type,opts,mountpoint){var root=mountpoint==="/";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(16)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(16)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(20)}}var mount={type:type,opts:opts,mountpoint:mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot},unmount:function(mountpoint){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(22)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);Object.keys(FS.nameTable).forEach(function(hash){var current=FS.nameTable[hash];while(current){var next=current.name_next;if(mounts.indexOf(current.mount)!==-1){FS.destroyNode(current)}current=next}});node.mounted=null;var idx=node.mount.mounts.indexOf(mount);node.mount.mounts.splice(idx,1)},lookup:function(parent,name){return parent.node_ops.lookup(parent,name)},mknod:function(path,mode,dev){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name||name==="."||name===".."){throw new FS.ErrnoError(22)}var err=FS.mayCreate(parent,name);if(err){throw new FS.ErrnoError(err)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(1)}return parent.node_ops.mknod(parent,name,mode,dev)},create:function(path,mode){mode=mode!==undefined?mode:438;mode&=4095;mode|=32768;return FS.mknod(path,mode,0)},mkdir:function(path,mode){mode=mode!==undefined?mode:511;mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)},mkdirTree:function(path,mode){var dirs=path.split("/");var d="";for(var i=0;i<dirs.length;++i){if(!dirs[i])continue;d+="/"+dirs[i];try{FS.mkdir(d,mode)}catch(e){if(e.errno!=17)throw e}}},mkdev:function(path,mode,dev){if(typeof dev==="undefined"){dev=mode;mode=438}mode|=8192;return FS.mknod(path,mode,dev)},symlink:function(oldpath,newpath){if(!PATH_FS.resolve(oldpath)){throw new FS.ErrnoError(2)}var lookup=FS.lookupPath(newpath,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(2)}var newname=PATH.basename(newpath);var err=FS.mayCreate(parent,newname);if(err){throw new FS.ErrnoError(err)}if(!parent.node_ops.symlink){throw new FS.ErrnoError(1)}return parent.node_ops.symlink(parent,newname,oldpath)},rename:function(old_path,new_path){var old_dirname=PATH.dirname(old_path);var new_dirname=PATH.dirname(new_path);var old_name=PATH.basename(old_path);var new_name=PATH.basename(new_path);var lookup,old_dir,new_dir;try{lookup=FS.lookupPath(old_path,{parent:true});old_dir=lookup.node;lookup=FS.lookupPath(new_path,{parent:true});new_dir=lookup.node}catch(e){throw new FS.ErrnoError(16)}if(!old_dir||!new_dir)throw new FS.ErrnoError(2);if(old_dir.mount!==new_dir.mount){throw new FS.ErrnoError(18)}var old_node=FS.lookupNode(old_dir,old_name);var relative=PATH_FS.relative(old_path,new_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(22)}relative=PATH_FS.relative(new_path,old_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(39)}var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(old_node===new_node){return}var isdir=FS.isDir(old_node.mode);var err=FS.mayDelete(old_dir,old_name,isdir);if(err){throw new FS.ErrnoError(err)}err=new_node?FS.mayDelete(new_dir,new_name,isdir):FS.mayCreate(new_dir,new_name);if(err){throw new FS.ErrnoError(err)}if(!old_dir.node_ops.rename){throw new FS.ErrnoError(1)}if(FS.isMountpoint(old_node)||new_node&&FS.isMountpoint(new_node)){throw new FS.ErrnoError(16)}if(new_dir!==old_dir){err=FS.nodePermissions(old_dir,"w");if(err){throw new FS.ErrnoError(err)}}try{if(FS.trackingDelegate["willMovePath"]){FS.trackingDelegate["willMovePath"](old_path,new_path)}}catch(e){console.log("FS.trackingDelegate['willMovePath']('"+old_path+"', '"+new_path+"') threw an exception: "+e.message)}FS.hashRemoveNode(old_node);try{old_dir.node_ops.rename(old_node,new_dir,new_name)}catch(e){throw e}finally{FS.hashAddNode(old_node)}try{if(FS.trackingDelegate["onMovePath"])FS.trackingDelegate["onMovePath"](old_path,new_path)}catch(e){console.log("FS.trackingDelegate['onMovePath']('"+old_path+"', '"+new_path+"') threw an exception: "+e.message)}},rmdir:function(path){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var err=FS.mayDelete(parent,name,true);if(err){throw new FS.ErrnoError(err)}if(!parent.node_ops.rmdir){throw new FS.ErrnoError(1)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(16)}try{if(FS.trackingDelegate["willDeletePath"]){FS.trackingDelegate["willDeletePath"](path)}}catch(e){console.log("FS.trackingDelegate['willDeletePath']('"+path+"') threw an exception: "+e.message)}parent.node_ops.rmdir(parent,name);FS.destroyNode(node);try{if(FS.trackingDelegate["onDeletePath"])FS.trackingDelegate["onDeletePath"](path)}catch(e){console.log("FS.trackingDelegate['onDeletePath']('"+path+"') threw an exception: "+e.message)}},readdir:function(path){var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;if(!node.node_ops.readdir){throw new FS.ErrnoError(20)}return node.node_ops.readdir(node)},unlink:function(path){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var err=FS.mayDelete(parent,name,false);if(err){throw new FS.ErrnoError(err)}if(!parent.node_ops.unlink){throw new FS.ErrnoError(1)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(16)}try{if(FS.trackingDelegate["willDeletePath"]){FS.trackingDelegate["willDeletePath"](path)}}catch(e){console.log("FS.trackingDelegate['willDeletePath']('"+path+"') threw an exception: "+e.message)}parent.node_ops.unlink(parent,name);FS.destroyNode(node);try{if(FS.trackingDelegate["onDeletePath"])FS.trackingDelegate["onDeletePath"](path)}catch(e){console.log("FS.trackingDelegate['onDeletePath']('"+path+"') threw an exception: "+e.message)}},readlink:function(path){var lookup=FS.lookupPath(path);var link=lookup.node;if(!link){throw new FS.ErrnoError(2)}if(!link.node_ops.readlink){throw new FS.ErrnoError(22)}return PATH_FS.resolve(FS.getPath(link.parent),link.node_ops.readlink(link))},stat:function(path,dontFollow){var lookup=FS.lookupPath(path,{follow:!dontFollow});var node=lookup.node;if(!node){throw new FS.ErrnoError(2)}if(!node.node_ops.getattr){throw new FS.ErrnoError(1)}return node.node_ops.getattr(node)},lstat:function(path){return FS.stat(path,true)},chmod:function(path,mode,dontFollow){var node;if(typeof path==="string"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(1)}node.node_ops.setattr(node,{mode:mode&4095|node.mode&~4095,timestamp:Date.now()})},lchmod:function(path,mode){FS.chmod(path,mode,true)},fchmod:function(fd,mode){var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(9)}FS.chmod(stream.node,mode)},chown:function(path,uid,gid,dontFollow){var node;if(typeof path==="string"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(1)}node.node_ops.setattr(node,{timestamp:Date.now()})},lchown:function(path,uid,gid){FS.chown(path,uid,gid,true)},fchown:function(fd,uid,gid){var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(9)}FS.chown(stream.node,uid,gid)},truncate:function(path,len){if(len<0){throw new FS.ErrnoError(22)}var node;if(typeof path==="string"){var lookup=FS.lookupPath(path,{follow:true});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(1)}if(FS.isDir(node.mode)){throw new FS.ErrnoError(21)}if(!FS.isFile(node.mode)){throw new FS.ErrnoError(22)}var err=FS.nodePermissions(node,"w");if(err){throw new FS.ErrnoError(err)}node.node_ops.setattr(node,{size:len,timestamp:Date.now()})},ftruncate:function(fd,len){var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(9)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(22)}FS.truncate(stream.node,len)},utime:function(path,atime,mtime){var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;node.node_ops.setattr(node,{timestamp:Math.max(atime,mtime)})},open:function(path,flags,mode,fd_start,fd_end){if(path===""){throw new FS.ErrnoError(2)}flags=typeof flags==="string"?FS.modeStringToFlags(flags):flags;mode=typeof mode==="undefined"?438:mode;if(flags&64){mode=mode&4095|32768}else{mode=0}var node;if(typeof path==="object"){node=path}else{path=PATH.normalize(path);try{var lookup=FS.lookupPath(path,{follow:!(flags&131072)});node=lookup.node}catch(e){}}var created=false;if(flags&64){if(node){if(flags&128){throw new FS.ErrnoError(17)}}else{node=FS.mknod(path,mode,0);created=true}}if(!node){throw new FS.ErrnoError(2)}if(FS.isChrdev(node.mode)){flags&=~512}if(flags&65536&&!FS.isDir(node.mode)){throw new FS.ErrnoError(20)}if(!created){var err=FS.mayOpen(node,flags);if(err){throw new FS.ErrnoError(err)}}if(flags&512){FS.truncate(node,0)}flags&=~(128|512);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);if(stream.stream_ops.open){stream.stream_ops.open(stream)}if(Module["logReadFiles"]&&!(flags&1)){if(!FS.readFiles)FS.readFiles={};if(!(path in FS.readFiles)){FS.readFiles[path]=1;console.log("FS.trackingDelegate error on read file: "+path)}}try{if(FS.trackingDelegate["onOpenFile"]){var trackingFlags=0;if((flags&2097155)!==1){trackingFlags|=FS.tracking.openFlags.READ}if((flags&2097155)!==0){trackingFlags|=FS.tracking.openFlags.WRITE}FS.trackingDelegate["onOpenFile"](path,trackingFlags)}}catch(e){console.log("FS.trackingDelegate['onOpenFile']('"+path+"', flags) threw an exception: "+e.message)}return stream},close:function(stream){if(FS.isClosed(stream)){throw new FS.ErrnoError(9)}if(stream.getdents)stream.getdents=null;try{if(stream.stream_ops.close){stream.stream_ops.close(stream)}}catch(e){throw e}finally{FS.closeStream(stream.fd)}stream.fd=null},isClosed:function(stream){return stream.fd===null},llseek:function(stream,offset,whence){if(FS.isClosed(stream)){throw new FS.ErrnoError(9)}if(!stream.seekable||!stream.stream_ops.llseek){throw new FS.ErrnoError(29)}if(whence!=0&&whence!=1&&whence!=2){throw new FS.ErrnoError(22)}stream.position=stream.stream_ops.llseek(stream,offset,whence);stream.ungotten=[];return stream.position},read:function(stream,buffer,offset,length,position){if(length<0||position<0){throw new FS.ErrnoError(22)}if(FS.isClosed(stream)){throw new FS.ErrnoError(9)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(9)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(21)}if(!stream.stream_ops.read){throw new FS.ErrnoError(22)}var seeking=typeof position!=="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(29)}var bytesRead=stream.stream_ops.read(stream,buffer,offset,length,position);if(!seeking)stream.position+=bytesRead;return bytesRead},write:function(stream,buffer,offset,length,position,canOwn){if(length<0||position<0){throw new FS.ErrnoError(22)}if(FS.isClosed(stream)){throw new FS.ErrnoError(9)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(9)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(21)}if(!stream.stream_ops.write){throw new FS.ErrnoError(22)}if(stream.flags&1024){FS.llseek(stream,0,2)}var seeking=typeof position!=="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(29)}var bytesWritten=stream.stream_ops.write(stream,buffer,offset,length,position,canOwn);if(!seeking)stream.position+=bytesWritten;try{if(stream.path&&FS.trackingDelegate["onWriteToFile"])FS.trackingDelegate["onWriteToFile"](stream.path)}catch(e){console.log("FS.trackingDelegate['onWriteToFile']('"+stream.path+"') threw an exception: "+e.message)}return bytesWritten},allocate:function(stream,offset,length){if(FS.isClosed(stream)){throw new FS.ErrnoError(9)}if(offset<0||length<=0){throw new FS.ErrnoError(22)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(9)}if(!FS.isFile(stream.node.mode)&&!FS.isDir(stream.node.mode)){throw new FS.ErrnoError(19)}if(!stream.stream_ops.allocate){throw new FS.ErrnoError(95)}stream.stream_ops.allocate(stream,offset,length)},mmap:function(stream,buffer,offset,length,position,prot,flags){if((prot&2)!==0&&(flags&2)===0&&(stream.flags&2097155)!==2){throw new FS.ErrnoError(13)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(13)}if(!stream.stream_ops.mmap){throw new FS.ErrnoError(19)}return stream.stream_ops.mmap(stream,buffer,offset,length,position,prot,flags)},msync:function(stream,buffer,offset,length,mmapFlags){if(!stream||!stream.stream_ops.msync){return 0}return stream.stream_ops.msync(stream,buffer,offset,length,mmapFlags)},munmap:function(stream){return 0},ioctl:function(stream,cmd,arg){if(!stream.stream_ops.ioctl){throw new FS.ErrnoError(25)}return stream.stream_ops.ioctl(stream,cmd,arg)},readFile:function(path,opts){opts=opts||{};opts.flags=opts.flags||"r";opts.encoding=opts.encoding||"binary";if(opts.encoding!=="utf8"&&opts.encoding!=="binary"){throw new Error('Invalid encoding type "'+opts.encoding+'"')}var ret;var stream=FS.open(path,opts.flags);var stat=FS.stat(path);var length=stat.size;var buf=new Uint8Array(length);FS.read(stream,buf,0,length,0);if(opts.encoding==="utf8"){ret=UTF8ArrayToString(buf,0)}else if(opts.encoding==="binary"){ret=buf}FS.close(stream);return ret},writeFile:function(path,data,opts){opts=opts||{};opts.flags=opts.flags||"w";var stream=FS.open(path,opts.flags,opts.mode);if(typeof data==="string"){var buf=new Uint8Array(lengthBytesUTF8(data)+1);var actualNumBytes=stringToUTF8Array(data,buf,0,buf.length);FS.write(stream,buf,0,actualNumBytes,undefined,opts.canOwn)}else if(ArrayBuffer.isView(data)){FS.write(stream,data,0,data.byteLength,undefined,opts.canOwn)}else{throw new Error("Unsupported data type")}FS.close(stream)},cwd:function(){return FS.currentPath},chdir:function(path){var lookup=FS.lookupPath(path,{follow:true});if(lookup.node===null){throw new FS.ErrnoError(2)}if(!FS.isDir(lookup.node.mode)){throw new FS.ErrnoError(20)}var err=FS.nodePermissions(lookup.node,"x");if(err){throw new FS.ErrnoError(err)}FS.currentPath=lookup.path},createDefaultDirectories:function(){FS.mkdir("/tmp");FS.mkdir("/home");FS.mkdir("/home/web_user")},createDefaultDevices:function(){FS.mkdir("/dev");FS.registerDevice(FS.makedev(1,3),{read:function(){return 0},write:function(stream,buffer,offset,length,pos){return length}});FS.mkdev("/dev/null",FS.makedev(1,3));TTY.register(FS.makedev(5,0),TTY.default_tty_ops);TTY.register(FS.makedev(6,0),TTY.default_tty1_ops);FS.mkdev("/dev/tty",FS.makedev(5,0));FS.mkdev("/dev/tty1",FS.makedev(6,0));var random_device;if(typeof crypto==="object"&&typeof crypto["getRandomValues"]==="function"){var randomBuffer=new Uint8Array(1);random_device=function(){crypto.getRandomValues(randomBuffer);return randomBuffer[0]}}else if(ENVIRONMENT_IS_NODE){try{var crypto_module=require("crypto");random_device=function(){return crypto_module["randomBytes"](1)[0]}}catch(e){}}else{}if(!random_device){random_device=function(){abort("random_device")}}FS.createDevice("/dev","random",random_device);FS.createDevice("/dev","urandom",random_device);FS.mkdir("/dev/shm");FS.mkdir("/dev/shm/tmp")},createSpecialDirectories:function(){FS.mkdir("/proc");FS.mkdir("/proc/self");FS.mkdir("/proc/self/fd");FS.mount({mount:function(){var node=FS.createNode("/proc/self","fd",16384|511,73);node.node_ops={lookup:function(parent,name){var fd=+name;var stream=FS.getStream(fd);if(!stream)throw new FS.ErrnoError(9);var ret={parent:null,mount:{mountpoint:"fake"},node_ops:{readlink:function(){return stream.path}}};ret.parent=ret;return ret}};return node}},{},"/proc/self/fd")},createStandardStreams:function(){if(Module["stdin"]){FS.createDevice("/dev","stdin",Module["stdin"])}else{FS.symlink("/dev/tty","/dev/stdin")}if(Module["stdout"]){FS.createDevice("/dev","stdout",null,Module["stdout"])}else{FS.symlink("/dev/tty","/dev/stdout")}if(Module["stderr"]){FS.createDevice("/dev","stderr",null,Module["stderr"])}else{FS.symlink("/dev/tty1","/dev/stderr")}var stdin=FS.open("/dev/stdin","r");var stdout=FS.open("/dev/stdout","w");var stderr=FS.open("/dev/stderr","w")},ensureErrnoError:function(){if(FS.ErrnoError)return;FS.ErrnoError=function ErrnoError(errno,node){this.node=node;this.setErrno=function(errno){this.errno=errno};this.setErrno(errno);this.message="FS error"};FS.ErrnoError.prototype=new Error;FS.ErrnoError.prototype.constructor=FS.ErrnoError;[2].forEach(function(code){FS.genericErrors[code]=new FS.ErrnoError(code);FS.genericErrors[code].stack="<generic error, no stack>"})},staticInit:function(){FS.ensureErrnoError();FS.nameTable=new Array(4096);FS.mount(MEMFS,{},"/");FS.createDefaultDirectories();FS.createDefaultDevices();FS.createSpecialDirectories();FS.filesystems={"MEMFS":MEMFS,"IDBFS":IDBFS,"NODEFS":NODEFS,"WORKERFS":WORKERFS}},init:function(input,output,error){FS.init.initialized=true;FS.ensureErrnoError();Module["stdin"]=input||Module["stdin"];Module["stdout"]=output||Module["stdout"];Module["stderr"]=error||Module["stderr"];FS.createStandardStreams()},quit:function(){FS.init.initialized=false;var fflush=Module["_fflush"];if(fflush)fflush(0);for(var i=0;i<FS.streams.length;i++){var stream=FS.streams[i];if(!stream){continue}FS.close(stream)}},getMode:function(canRead,canWrite){var mode=0;if(canRead)mode|=292|73;if(canWrite)mode|=146;return mode},joinPath:function(parts,forceRelative){var path=PATH.join.apply(null,parts);if(forceRelative&&path[0]=="/")path=path.substr(1);return path},absolutePath:function(relative,base){return PATH_FS.resolve(base,relative)},standardizePath:function(path){return PATH.normalize(path)},findObject:function(path,dontResolveLastLink){var ret=FS.analyzePath(path,dontResolveLastLink);if(ret.exists){return ret.object}else{___setErrNo(ret.error);return null}},analyzePath:function(path,dontResolveLastLink){try{var lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});path=lookup.path}catch(e){}var ret={isRoot:false,exists:false,error:0,name:null,path:null,object:null,parentExists:false,parentPath:null,parentObject:null};try{var lookup=FS.lookupPath(path,{parent:true});ret.parentExists=true;ret.parentPath=lookup.path;ret.parentObject=lookup.node;ret.name=PATH.basename(path);lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});ret.exists=true;ret.path=lookup.path;ret.object=lookup.node;ret.name=lookup.node.name;ret.isRoot=lookup.path==="/"}catch(e){ret.error=e.errno}return ret},createFolder:function(parent,name,canRead,canWrite){var path=PATH.join2(typeof parent==="string"?parent:FS.getPath(parent),name);var mode=FS.getMode(canRead,canWrite);return FS.mkdir(path,mode)},createPath:function(parent,path,canRead,canWrite){parent=typeof parent==="string"?parent:FS.getPath(parent);var parts=path.split("/").reverse();while(parts.length){var part=parts.pop();if(!part)continue;var current=PATH.join2(parent,part);try{FS.mkdir(current)}catch(e){}parent=current}return current},createFile:function(parent,name,properties,canRead,canWrite){var path=PATH.join2(typeof parent==="string"?parent:FS.getPath(parent),name);var mode=FS.getMode(canRead,canWrite);return FS.create(path,mode)},createDataFile:function(parent,name,data,canRead,canWrite,canOwn){var path=name?PATH.join2(typeof parent==="string"?parent:FS.getPath(parent),name):parent;var mode=FS.getMode(canRead,canWrite);var node=FS.create(path,mode);if(data){if(typeof data==="string"){var arr=new Array(data.length);for(var i=0,len=data.length;i<len;++i)arr[i]=data.charCodeAt(i);data=arr}FS.chmod(node,mode|146);var stream=FS.open(node,"w");FS.write(stream,data,0,data.length,0,canOwn);FS.close(stream);FS.chmod(node,mode)}return node},createDevice:function(parent,name,input,output){var path=PATH.join2(typeof parent==="string"?parent:FS.getPath(parent),name);var mode=FS.getMode(!!input,!!output);if(!FS.createDevice.major)FS.createDevice.major=64;var dev=FS.makedev(FS.createDevice.major++,0);FS.registerDevice(dev,{open:function(stream){stream.seekable=false},close:function(stream){if(output&&output.buffer&&output.buffer.length){output(10)}},read:function(stream,buffer,offset,length,pos){var bytesRead=0;for(var i=0;i<length;i++){var result;try{result=input()}catch(e){throw new FS.ErrnoError(5)}if(result===undefined&&bytesRead===0){throw new FS.ErrnoError(11)}if(result===null||result===undefined)break;bytesRead++;buffer[offset+i]=result}if(bytesRead){stream.node.timestamp=Date.now()}return bytesRead},write:function(stream,buffer,offset,length,pos){for(var i=0;i<length;i++){try{output(buffer[offset+i])}catch(e){throw new FS.ErrnoError(5)}}if(length){stream.node.timestamp=Date.now()}return i}});return FS.mkdev(path,mode,dev)},createLink:function(parent,name,target,canRead,canWrite){var path=PATH.join2(typeof parent==="string"?parent:FS.getPath(parent),name);return FS.symlink(target,path)},forceLoadFile:function(obj){if(obj.isDevice||obj.isFolder||obj.link||obj.contents)return true;var success=true;if(typeof XMLHttpRequest!=="undefined"){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.")}else if(read_){try{obj.contents=intArrayFromString(read_(obj.url),true);obj.usedBytes=obj.contents.length}catch(e){success=false}}else{throw new Error("Cannot load without read() or XMLHttpRequest.")}if(!success)___setErrNo(5);return success},createLazyFile:function(parent,name,url,canRead,canWrite){function LazyUint8Array(){this.lengthKnown=false;this.chunks=[]}LazyUint8Array.prototype.get=function LazyUint8Array_get(idx){if(idx>this.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]};LazyUint8Array.prototype.setDataGetter=function LazyUint8Array_setDataGetter(getter){this.getter=getter};LazyUint8Array.prototype.cacheLength=function LazyUint8Array_cacheLength(){var xhr=new XMLHttpRequest;xhr.open("HEAD",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);var datalength=Number(xhr.getResponseHeader("Content-length"));var header;var hasByteServing=(header=xhr.getResponseHeader("Accept-Ranges"))&&header==="bytes";var usesGzip=(header=xhr.getResponseHeader("Content-Encoding"))&&header==="gzip";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=function(from,to){if(from>to)throw new Error("invalid range ("+from+", "+to+") or no bytes requested!");if(to>datalength-1)throw new Error("only "+datalength+" bytes available! programmer error!");var xhr=new XMLHttpRequest;xhr.open("GET",url,false);if(datalength!==chunkSize)xhr.setRequestHeader("Range","bytes="+from+"-"+to);if(typeof Uint8Array!="undefined")xhr.responseType="arraybuffer";if(xhr.overrideMimeType){xhr.overrideMimeType("text/plain; charset=x-user-defined")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}else{return intArrayFromString(xhr.responseText||"",true)}};var lazyArray=this;lazyArray.setDataGetter(function(chunkNum){var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]==="undefined"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]==="undefined")throw new Error("doXHR failed!");return lazyArray.chunks[chunkNum]});if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;console.log("LazyFiles on gzip forces download of the whole file when length is accessed")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true};if(typeof XMLHttpRequest!=="undefined"){if(!ENVIRONMENT_IS_WORKER)throw"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";var lazyArray=new LazyUint8Array;Object.defineProperties(lazyArray,{length:{get:function(){if(!this.lengthKnown){this.cacheLength()}return this._length}},chunkSize:{get:function(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize}}});var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url:url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:function(){return this.contents.length}}});var stream_ops={};var keys=Object.keys(node.stream_ops);keys.forEach(function(key){var fn=node.stream_ops[key];stream_ops[key]=function forceLoadLazyFile(){if(!FS.forceLoadFile(node)){throw new FS.ErrnoError(5)}return fn.apply(null,arguments)}});stream_ops.read=function stream_ops_read(stream,buffer,offset,length,position){if(!FS.forceLoadFile(node)){throw new FS.ErrnoError(5)}var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);if(contents.slice){for(var i=0;i<size;i++){buffer[offset+i]=contents[position+i]}}else{for(var i=0;i<size;i++){buffer[offset+i]=contents.get(position+i)}}return size};node.stream_ops=stream_ops;return node},createPreloadedFile:function(parent,name,url,canRead,canWrite,onload,onerror,dontCreateFile,canOwn,preFinish){Browser.init();var fullname=name?PATH_FS.resolve(PATH.join2(parent,name)):parent;var dep=getUniqueRunDependency("cp "+fullname);function processData(byteArray){function finish(byteArray){if(preFinish)preFinish();if(!dontCreateFile){FS.createDataFile(parent,name,byteArray,canRead,canWrite,canOwn)}if(onload)onload();removeRunDependency(dep)}var handled=false;Module["preloadPlugins"].forEach(function(plugin){if(handled)return;if(plugin["canHandle"](fullname)){plugin["handle"](byteArray,fullname,finish,function(){if(onerror)onerror();removeRunDependency(dep)});handled=true}});if(!handled)finish(byteArray)}addRunDependency(dep);if(typeof url=="string"){Browser.asyncLoad(url,function(byteArray){processData(byteArray)},onerror)}else{processData(url)}},indexedDB:function(){return window.indexedDB||window.mozIndexedDB||window.webkitIndexedDB||window.msIndexedDB},DB_NAME:function(){return"EM_FS_"+window.location.pathname},DB_VERSION:20,DB_STORE_NAME:"FILE_DATA",saveFilesToDB:function(paths,onload,onerror){onload=onload||function(){};onerror=onerror||function(){};var indexedDB=FS.indexedDB();try{var openRequest=indexedDB.open(FS.DB_NAME(),FS.DB_VERSION)}catch(e){return onerror(e)}openRequest.onupgradeneeded=function openRequest_onupgradeneeded(){console.log("creating db");var db=openRequest.result;db.createObjectStore(FS.DB_STORE_NAME)};openRequest.onsuccess=function openRequest_onsuccess(){var db=openRequest.result;var transaction=db.transaction([FS.DB_STORE_NAME],"readwrite");var files=transaction.objectStore(FS.DB_STORE_NAME);var ok=0,fail=0,total=paths.length;function finish(){if(fail==0)onload();else onerror()}paths.forEach(function(path){var putRequest=files.put(FS.analyzePath(path).object.contents,path);putRequest.onsuccess=function putRequest_onsuccess(){ok++;if(ok+fail==total)finish()};putRequest.onerror=function putRequest_onerror(){fail++;if(ok+fail==total)finish()}});transaction.onerror=onerror};openRequest.onerror=onerror},loadFilesFromDB:function(paths,onload,onerror){onload=onload||function(){};onerror=onerror||function(){};var indexedDB=FS.indexedDB();try{var openRequest=indexedDB.open(FS.DB_NAME(),FS.DB_VERSION)}catch(e){return onerror(e)}openRequest.onupgradeneeded=onerror;openRequest.onsuccess=function openRequest_onsuccess(){var db=openRequest.result;try{var transaction=db.transaction([FS.DB_STORE_NAME],"readonly")}catch(e){onerror(e);return}var files=transaction.objectStore(FS.DB_STORE_NAME);var ok=0,fail=0,total=paths.length;function finish(){if(fail==0)onload();else onerror()}paths.forEach(function(path){var getRequest=files.get(path);getRequest.onsuccess=function getRequest_onsuccess(){if(FS.analyzePath(path).exists){FS.unlink(path)}FS.createDataFile(PATH.dirname(path),PATH.basename(path),getRequest.result,true,true,true);ok++;if(ok+fail==total)finish()};getRequest.onerror=function getRequest_onerror(){fail++;if(ok+fail==total)finish()}});transaction.onerror=onerror};openRequest.onerror=onerror}};var SYSCALLS={DEFAULT_POLLMASK:5,mappings:{},umask:511,calculateAt:function(dirfd,path){if(path[0]!=="/"){var dir;if(dirfd===-100){dir=FS.cwd()}else{var dirstream=FS.getStream(dirfd);if(!dirstream)throw new FS.ErrnoError(9);dir=dirstream.path}path=PATH.join2(dir,path)}return path},doStat:function(func,path,buf){try{var stat=func(path)}catch(e){if(e&&e.node&&PATH.normalize(path)!==PATH.normalize(FS.getPath(e.node))){return-20}throw e}HEAP32[buf>>2]=stat.dev;HEAP32[buf+4>>2]=0;HEAP32[buf+8>>2]=stat.ino;HEAP32[buf+12>>2]=stat.mode;HEAP32[buf+16>>2]=stat.nlink;HEAP32[buf+20>>2]=stat.uid;HEAP32[buf+24>>2]=stat.gid;HEAP32[buf+28>>2]=stat.rdev;HEAP32[buf+32>>2]=0;tempI64=[stat.size>>>0,(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)],HEAP32[buf+40>>2]=tempI64[0],HEAP32[buf+44>>2]=tempI64[1];HEAP32[buf+48>>2]=4096;HEAP32[buf+52>>2]=stat.blocks;HEAP32[buf+56>>2]=stat.atime.getTime()/1e3|0;HEAP32[buf+60>>2]=0;HEAP32[buf+64>>2]=stat.mtime.getTime()/1e3|0;HEAP32[buf+68>>2]=0;HEAP32[buf+72>>2]=stat.ctime.getTime()/1e3|0;HEAP32[buf+76>>2]=0;tempI64=[stat.ino>>>0,(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)],HEAP32[buf+80>>2]=tempI64[0],HEAP32[buf+84>>2]=tempI64[1];return 0},doMsync:function(addr,stream,len,flags){var buffer=new Uint8Array(HEAPU8.subarray(addr,addr+len));FS.msync(stream,buffer,0,len,flags)},doMkdir:function(path,mode){path=PATH.normalize(path);if(path[path.length-1]==="/")path=path.substr(0,path.length-1);FS.mkdir(path,mode,0);return 0},doMknod:function(path,mode,dev){switch(mode&61440){case 32768:case 8192:case 24576:case 4096:case 49152:break;default:return-22}FS.mknod(path,mode,dev);return 0},doReadlink:function(path,buf,bufsize){if(bufsize<=0)return-22;var ret=FS.readlink(path);var len=Math.min(bufsize,lengthBytesUTF8(ret));var endChar=HEAP8[buf+len];stringToUTF8(ret,buf,bufsize+1);HEAP8[buf+len]=endChar;return len},doAccess:function(path,amode){if(amode&~7){return-22}var node;var lookup=FS.lookupPath(path,{follow:true});node=lookup.node;if(!node){return-2}var perms="";if(amode&4)perms+="r";if(amode&2)perms+="w";if(amode&1)perms+="x";if(perms&&FS.nodePermissions(node,perms)){return-13}return 0},doDup:function(path,flags,suggestFD){var suggest=FS.getStream(suggestFD);if(suggest)FS.close(suggest);return FS.open(path,flags,0,suggestFD,suggestFD).fd},doReadv:function(stream,iov,iovcnt,offset){var ret=0;for(var i=0;i<iovcnt;i++){var ptr=HEAP32[iov+i*8>>2];var len=HEAP32[iov+(i*8+4)>>2];var curr=FS.read(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr<len)break}return ret},doWritev:function(stream,iov,iovcnt,offset){var ret=0;for(var i=0;i<iovcnt;i++){var ptr=HEAP32[iov+i*8>>2];var len=HEAP32[iov+(i*8+4)>>2];var curr=FS.write(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr}return ret},varargs:0,get:function(varargs){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(){var ret=UTF8ToString(SYSCALLS.get());return ret},getStreamFromFD:function(){var stream=FS.getStream(SYSCALLS.get());if(!stream)throw new FS.ErrnoError(9);return stream},get64:function(){var low=SYSCALLS.get(),high=SYSCALLS.get();return low},getZero:function(){SYSCALLS.get()}};function ___syscall140(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(),offset_high=SYSCALLS.get(),offset_low=SYSCALLS.get(),result=SYSCALLS.get(),whence=SYSCALLS.get();var HIGH_OFFSET=4294967296;var offset=offset_high*HIGH_OFFSET+(offset_low>>>0);var DOUBLE_LIMIT=9007199254740992;if(offset<=-DOUBLE_LIMIT||offset>=DOUBLE_LIMIT){return-75}FS.llseek(stream,offset,whence);tempI64=[stream.position>>>0,(tempDouble=stream.position,+Math_abs(tempDouble)>=1?tempDouble>0?(Math_min(+Math_floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[result>>2]=tempI64[0],HEAP32[result+4>>2]=tempI64[1];if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall145(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(),iov=SYSCALLS.get(),iovcnt=SYSCALLS.get();return SYSCALLS.doReadv(stream,iov,iovcnt)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall221(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(),cmd=SYSCALLS.get();switch(cmd){case 0:{var arg=SYSCALLS.get();if(arg<0){return-22}var newStream;newStream=FS.open(stream.path,stream.flags,0,arg);return newStream.fd}case 1:case 2:return 0;case 3:return stream.flags;case 4:{var arg=SYSCALLS.get();stream.flags|=arg;return 0}case 12:{var arg=SYSCALLS.get();var offset=0;HEAP16[arg+offset>>1]=2;return 0}case 13:case 14:return 0;case 16:case 8:return-22;case 9:___setErrNo(22);return-1;default:{return-22}}}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall5(which,varargs){SYSCALLS.varargs=varargs;try{var pathname=SYSCALLS.getStr(),flags=SYSCALLS.get(),mode=SYSCALLS.get();var stream=FS.open(pathname,flags,mode);return stream.fd}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall54(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(),op=SYSCALLS.get();switch(op){case 21509:case 21505:{if(!stream.tty)return-25;return 0}case 21510:case 21511:case 21512:case 21506:case 21507:case 21508:{if(!stream.tty)return-25;return 0}case 21519:{if(!stream.tty)return-25;var argp=SYSCALLS.get();HEAP32[argp>>2]=0;return 0}case 21520:{if(!stream.tty)return-25;return-22}case 21531:{var argp=SYSCALLS.get();return FS.ioctl(stream,op,argp)}case 21523:{if(!stream.tty)return-25;return 0}case 21524:{if(!stream.tty)return-25;return 0}default:abort("bad ioctl syscall "+op)}}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___syscall6(which,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD();FS.close(stream);return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___unlock(){}function _fd_write(stream,iov,iovcnt,pnum){try{stream=FS.getStream(stream);if(!stream)throw new FS.ErrnoError(9);var num=SYSCALLS.doWritev(stream,iov,iovcnt);HEAP32[pnum>>2]=num;return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___wasi_fd_write(){return _fd_write.apply(null,arguments)}function _emscripten_set_main_loop_timing(mode,value){Browser.mainLoop.timingMode=mode;Browser.mainLoop.timingValue=value;if(!Browser.mainLoop.func){return 1}if(mode==0){Browser.mainLoop.scheduler=function Browser_mainLoop_scheduler_setTimeout(){var timeUntilNextTick=Math.max(0,Browser.mainLoop.tickStartTime+value-_emscripten_get_now())|0;setTimeout(Browser.mainLoop.runner,timeUntilNextTick)};Browser.mainLoop.method="timeout"}else if(mode==1){Browser.mainLoop.scheduler=function Browser_mainLoop_scheduler_rAF(){Browser.requestAnimationFrame(Browser.mainLoop.runner)};Browser.mainLoop.method="rAF"}else if(mode==2){if(typeof setImmediate==="undefined"){var setImmediates=[];var emscriptenMainLoopMessageId="setimmediate";var Browser_setImmediate_messageHandler=function(event){if(event.data===emscriptenMainLoopMessageId||event.data.target===emscriptenMainLoopMessageId){event.stopPropagation();setImmediates.shift()()}};addEventListener("message",Browser_setImmediate_messageHandler,true);setImmediate=function Browser_emulated_setImmediate(func){setImmediates.push(func);if(ENVIRONMENT_IS_WORKER){if(Module["setImmediates"]===undefined)Module["setImmediates"]=[];Module["setImmediates"].push(func);postMessage({target:emscriptenMainLoopMessageId})}else postMessage(emscriptenMainLoopMessageId,"*")}}Browser.mainLoop.scheduler=function Browser_mainLoop_scheduler_setImmediate(){setImmediate(Browser.mainLoop.runner)};Browser.mainLoop.method="immediate"}return 0}function _emscripten_get_now(){abort()}function _emscripten_set_main_loop(func,fps,simulateInfiniteLoop,arg,noSetTiming){noExitRuntime=true;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.");Browser.mainLoop.func=func;Browser.mainLoop.arg=arg;var browserIterationFunc;if(typeof arg!=="undefined"){browserIterationFunc=function(){Module["dynCall_vi"](func,arg)}}else{browserIterationFunc=function(){Module["dynCall_v"](func)}}var thisMainLoopId=Browser.mainLoop.currentlyRunningMainloop;Browser.mainLoop.runner=function Browser_mainLoop_runner(){if(ABORT)return;if(Browser.mainLoop.queue.length>0){var start=Date.now();var blocker=Browser.mainLoop.queue.shift();blocker.func(blocker.arg);if(Browser.mainLoop.remainingBlockers){var remaining=Browser.mainLoop.remainingBlockers;var next=remaining%1==0?remaining-1:Math.floor(remaining);if(blocker.counted){Browser.mainLoop.remainingBlockers=next}else{next=next+.5;Browser.mainLoop.remainingBlockers=(8*remaining+next)/9}}console.log('main loop blocker "'+blocker.name+'" took '+(Date.now()-start)+" ms");Browser.mainLoop.updateStatus();if(thisMainLoopId<Browser.mainLoop.currentlyRunningMainloop)return;setTimeout(Browser.mainLoop.runner,0);return}if(thisMainLoopId<Browser.mainLoop.currentlyRunningMainloop)return;Browser.mainLoop.currentFrameNumber=Browser.mainLoop.currentFrameNumber+1|0;if(Browser.mainLoop.timingMode==1&&Browser.mainLoop.timingValue>1&&Browser.mainLoop.currentFrameNumber%Browser.mainLoop.timingValue!=0){Browser.mainLoop.scheduler();return}else if(Browser.mainLoop.timingMode==0){Browser.mainLoop.tickStartTime=_emscripten_get_now()}if(Browser.mainLoop.method==="timeout"&&Module.ctx){err("Looks like you are rendering without using requestAnimationFrame for the main loop. You should use 0 for the frame rate in emscripten_set_main_loop in order to use requestAnimationFrame, as that can greatly improve your frame rates!");Browser.mainLoop.method=""}Browser.mainLoop.runIter(browserIterationFunc);if(thisMainLoopId<Browser.mainLoop.currentlyRunningMainloop)return;if(typeof SDL==="object"&&SDL.audio&&SDL.audio.queueNewAudioData)SDL.audio.queueNewAudioData();Browser.mainLoop.scheduler()};if(!noSetTiming){if(fps&&fps>0)_emscripten_set_main_loop_timing(0,1e3/fps);else _emscripten_set_main_loop_timing(1,1);Browser.mainLoop.scheduler()}if(simulateInfiniteLoop){throw"SimulateInfiniteLoop"}}var Browser={mainLoop:{scheduler:null,method:"",currentlyRunningMainloop:0,func:null,arg:0,timingMode:0,timingValue:0,currentFrameNumber:0,queue:[],pause:function(){Browser.mainLoop.scheduler=null;Browser.mainLoop.currentlyRunningMainloop++},resume:function(){Browser.mainLoop.currentlyRunningMainloop++;var timingMode=Browser.mainLoop.timingMode;var timingValue=Browser.mainLoop.timingValue;var func=Browser.mainLoop.func;Browser.mainLoop.func=null;_emscripten_set_main_loop(func,0,false,Browser.mainLoop.arg,true);_emscripten_set_main_loop_timing(timingMode,timingValue);Browser.mainLoop.scheduler()},updateStatus:function(){if(Module["setStatus"]){var message=Module["statusMessage"]||"Please wait...";var remaining=Browser.mainLoop.remainingBlockers;var expected=Browser.mainLoop.expectedBlockers;if(remaining){if(remaining<expected){Module["setStatus"](message+" ("+(expected-remaining)+"/"+expected+")")}else{Module["setStatus"](message)}}else{Module["setStatus"]("")}}},runIter:function(func){if(ABORT)return;if(Module["preMainLoop"]){var preRet=Module["preMainLoop"]();if(preRet===false){return}}try{func()}catch(e){if(e instanceof ExitStatus){return}else{if(e&&typeof e==="object"&&e.stack)err("exception thrown: "+[e,e.stack]);throw e}}if(Module["postMainLoop"])Module["postMainLoop"]()}},isFullscreen:false,pointerLock:false,moduleContextCreatedCallbacks:[],workers:[],init:function(){if(!Module["preloadPlugins"])Module["preloadPlugins"]=[];if(Browser.initted)return;Browser.initted=true;try{new Blob;Browser.hasBlobConstructor=true}catch(e){Browser.hasBlobConstructor=false;console.log("warning: no blob constructor, cannot create blobs with mimetypes")}Browser.BlobBuilder=typeof MozBlobBuilder!="undefined"?MozBlobBuilder:typeof WebKitBlobBuilder!="undefined"?WebKitBlobBuilder:!Browser.hasBlobConstructor?console.log("warning: no BlobBuilder"):null;Browser.URLObject=typeof window!="undefined"?window.URL?window.URL:window.webkitURL:undefined;if(!Module.noImageDecoding&&typeof Browser.URLObject==="undefined"){console.log("warning: Browser does not support creating object URLs. Built-in browser image decoding will not be available.");Module.noImageDecoding=true}var imagePlugin={};imagePlugin["canHandle"]=function imagePlugin_canHandle(name){return!Module.noImageDecoding&&/\.(jpg|jpeg|png|bmp)$/i.test(name)};imagePlugin["handle"]=function imagePlugin_handle(byteArray,name,onload,onerror){var b=null;if(Browser.hasBlobConstructor){try{b=new Blob([byteArray],{type:Browser.getMimetype(name)});if(b.size!==byteArray.length){b=new Blob([new Uint8Array(byteArray).buffer],{type:Browser.getMimetype(name)})}}catch(e){warnOnce("Blob constructor present but fails: "+e+"; falling back to blob builder")}}if(!b){var bb=new Browser.BlobBuilder;bb.append(new Uint8Array(byteArray).buffer);b=bb.getBlob()}var url=Browser.URLObject.createObjectURL(b);var img=new Image;img.onload=function img_onload(){assert(img.complete,"Image "+name+" could not be decoded");var canvas=document.createElement("canvas");canvas.width=img.width;canvas.height=img.height;var ctx=canvas.getContext("2d");ctx.drawImage(img,0,0);Module["preloadedImages"][name]=canvas;Browser.URLObject.revokeObjectURL(url);if(onload)onload(byteArray)};img.onerror=function img_onerror(event){console.log("Image "+url+" could not be decoded");if(onerror)onerror()};img.src=url};Module["preloadPlugins"].push(imagePlugin);var audioPlugin={};audioPlugin["canHandle"]=function audioPlugin_canHandle(name){return!Module.noAudioDecoding&&name.substr(-4)in{".ogg":1,".wav":1,".mp3":1}};audioPlugin["handle"]=function audioPlugin_handle(byteArray,name,onload,onerror){var done=false;function finish(audio){if(done)return;done=true;Module["preloadedAudios"][name]=audio;if(onload)onload(byteArray)}function fail(){if(done)return;done=true;Module["preloadedAudios"][name]=new Audio;if(onerror)onerror()}if(Browser.hasBlobConstructor){try{var b=new Blob([byteArray],{type:Browser.getMimetype(name)})}catch(e){return fail()}var url=Browser.URLObject.createObjectURL(b);var audio=new Audio;audio.addEventListener("canplaythrough",function(){finish(audio)},false);audio.onerror=function audio_onerror(event){if(done)return;console.log("warning: browser could not fully decode audio "+name+", trying slower base64 approach");function encode64(data){var BASE="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";var PAD="=";var ret="";var leftchar=0;var leftbits=0;for(var i=0;i<data.length;i++){leftchar=leftchar<<8|data[i];leftbits+=8;while(leftbits>=6){var curr=leftchar>>leftbits-6&63;leftbits-=6;ret+=BASE[curr]}}if(leftbits==2){ret+=BASE[(leftchar&3)<<4];ret+=PAD+PAD}else if(leftbits==4){ret+=BASE[(leftchar&15)<<2];ret+=PAD}return ret}audio.src="data:audio/x-"+name.substr(-3)+";base64,"+encode64(byteArray);finish(audio)};audio.src=url;Browser.safeSetTimeout(function(){finish(audio)},1e4)}else{return fail()}};Module["preloadPlugins"].push(audioPlugin);function pointerLockChange(){Browser.pointerLock=document["pointerLockElement"]===Module["canvas"]||document["mozPointerLockElement"]===Module["canvas"]||document["webkitPointerLockElement"]===Module["canvas"]||document["msPointerLockElement"]===Module["canvas"]}var canvas=Module["canvas"];if(canvas){canvas.requestPointerLock=canvas["requestPointerLock"]||canvas["mozRequestPointerLock"]||canvas["webkitRequestPointerLock"]||canvas["msRequestPointerLock"]||function(){};canvas.exitPointerLock=document["exitPointerLock"]||document["mozExitPointerLock"]||document["webkitExitPointerLock"]||document["msExitPointerLock"]||function(){};canvas.exitPointerLock=canvas.exitPointerLock.bind(document);document.addEventListener("pointerlockchange",pointerLockChange,false);document.addEventListener("mozpointerlockchange",pointerLockChange,false);document.addEventListener("webkitpointerlockchange",pointerLockChange,false);document.addEventListener("mspointerlockchange",pointerLockChange,false);if(Module["elementPointerLock"]){canvas.addEventListener("click",function(ev){if(!Browser.pointerLock&&Module["canvas"].requestPointerLock){Module["canvas"].requestPointerLock();ev.preventDefault()}},false)}}},createContext:function(canvas,useWebGL,setInModule,webGLContextAttributes){if(useWebGL&&Module.ctx&&canvas==Module.canvas)return Module.ctx;var ctx;var contextHandle;if(useWebGL){var contextAttributes={antialias:false,alpha:false,majorVersion:1};if(webGLContextAttributes){for(var attribute in webGLContextAttributes){contextAttributes[attribute]=webGLContextAttributes[attribute]}}if(typeof GL!=="undefined"){contextHandle=GL.createContext(canvas,contextAttributes);if(contextHandle){ctx=GL.getContext(contextHandle).GLctx}}}else{ctx=canvas.getContext("2d")}if(!ctx)return null;if(setInModule){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");Module.ctx=ctx;if(useWebGL)GL.makeContextCurrent(contextHandle);Module.useWebGL=useWebGL;Browser.moduleContextCreatedCallbacks.forEach(function(callback){callback()});Browser.init()}return ctx},destroyContext:function(canvas,useWebGL,setInModule){},fullscreenHandlersInstalled:false,lockPointer:undefined,resizeCanvas:undefined,requestFullscreen:function(lockPointer,resizeCanvas,vrDevice){Browser.lockPointer=lockPointer;Browser.resizeCanvas=resizeCanvas;Browser.vrDevice=vrDevice;if(typeof Browser.lockPointer==="undefined")Browser.lockPointer=true;if(typeof Browser.resizeCanvas==="undefined")Browser.resizeCanvas=false;if(typeof Browser.vrDevice==="undefined")Browser.vrDevice=null;var canvas=Module["canvas"];function fullscreenChange(){Browser.isFullscreen=false;var canvasContainer=canvas.parentNode;if((document["fullscreenElement"]||document["mozFullScreenElement"]||document["msFullscreenElement"]||document["webkitFullscreenElement"]||document["webkitCurrentFullScreenElement"])===canvasContainer){canvas.exitFullscreen=Browser.exitFullscreen;if(Browser.lockPointer)canvas.requestPointerLock();Browser.isFullscreen=true;if(Browser.resizeCanvas){Browser.setFullscreenCanvasSize()}else{Browser.updateCanvasDimensions(canvas)}}else{canvasContainer.parentNode.insertBefore(canvas,canvasContainer);canvasContainer.parentNode.removeChild(canvasContainer);if(Browser.resizeCanvas){Browser.setWindowedCanvasSize()}else{Browser.updateCanvasDimensions(canvas)}}if(Module["onFullScreen"])Module["onFullScreen"](Browser.isFullscreen);if(Module["onFullscreen"])Module["onFullscreen"](Browser.isFullscreen)}if(!Browser.fullscreenHandlersInstalled){Browser.fullscreenHandlersInstalled=true;document.addEventListener("fullscreenchange",fullscreenChange,false);document.addEventListener("mozfullscreenchange",fullscreenChange,false);document.addEventListener("webkitfullscreenchange",fullscreenChange,false);document.addEventListener("MSFullscreenChange",fullscreenChange,false)}var canvasContainer=document.createElement("div");canvas.parentNode.insertBefore(canvasContainer,canvas);canvasContainer.appendChild(canvas);canvasContainer.requestFullscreen=canvasContainer["requestFullscreen"]||canvasContainer["mozRequestFullScreen"]||canvasContainer["msRequestFullscreen"]||(canvasContainer["webkitRequestFullscreen"]?function(){canvasContainer["webkitRequestFullscreen"](Element["ALLOW_KEYBOARD_INPUT"])}:null)||(canvasContainer["webkitRequestFullScreen"]?function(){canvasContainer["webkitRequestFullScreen"](Element["ALLOW_KEYBOARD_INPUT"])}:null);if(vrDevice){canvasContainer.requestFullscreen({vrDisplay:vrDevice})}else{canvasContainer.requestFullscreen()}},requestFullScreen:function(lockPointer,resizeCanvas,vrDevice){err("Browser.requestFullScreen() is deprecated. Please call Browser.requestFullscreen instead.");Browser.requestFullScreen=function(lockPointer,resizeCanvas,vrDevice){return Browser.requestFullscreen(lockPointer,resizeCanvas,vrDevice)};return Browser.requestFullscreen(lockPointer,resizeCanvas,vrDevice)},exitFullscreen:function(){if(!Browser.isFullscreen){return false}var CFS=document["exitFullscreen"]||document["cancelFullScreen"]||document["mozCancelFullScreen"]||document["msExitFullscreen"]||document["webkitCancelFullScreen"]||function(){};CFS.apply(document,[]);return true},nextRAF:0,fakeRequestAnimationFrame:function(func){var now=Date.now();if(Browser.nextRAF===0){Browser.nextRAF=now+1e3/60}else{while(now+2>=Browser.nextRAF){Browser.nextRAF+=1e3/60}}var delay=Math.max(Browser.nextRAF-now,0);setTimeout(func,delay)},requestAnimationFrame:function(func){if(typeof requestAnimationFrame==="function"){requestAnimationFrame(func);return}var RAF=Browser.fakeRequestAnimationFrame;RAF(func)},safeCallback:function(func){return function(){if(!ABORT)return func.apply(null,arguments)}},allowAsyncCallbacks:true,queuedAsyncCallbacks:[],pauseAsyncCallbacks:function(){Browser.allowAsyncCallbacks=false},resumeAsyncCallbacks:function(){Browser.allowAsyncCallbacks=true;if(Browser.queuedAsyncCallbacks.length>0){var callbacks=Browser.queuedAsyncCallbacks;Browser.queuedAsyncCallbacks=[];callbacks.forEach(function(func){func()})}},safeRequestAnimationFrame:function(func){return Browser.requestAnimationFrame(function(){if(ABORT)return;if(Browser.allowAsyncCallbacks){func()}else{Browser.queuedAsyncCallbacks.push(func)}})},safeSetTimeout:function(func,timeout){noExitRuntime=true;return setTimeout(function(){if(ABORT)return;if(Browser.allowAsyncCallbacks){func()}else{Browser.queuedAsyncCallbacks.push(func)}},timeout)},safeSetInterval:function(func,timeout){noExitRuntime=true;return setInterval(function(){if(ABORT)return;if(Browser.allowAsyncCallbacks){func()}},timeout)},getMimetype:function(name){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)]},getUserMedia:function(func){if(!window.getUserMedia){window.getUserMedia=navigator["getUserMedia"]||navigator["mozGetUserMedia"]}window.getUserMedia(func)},getMovementX:function(event){return event["movementX"]||event["mozMovementX"]||event["webkitMovementX"]||0},getMovementY:function(event){return event["movementY"]||event["mozMovementY"]||event["webkitMovementY"]||0},getMouseWheelDelta:function(event){var delta=0;switch(event.type){case"DOMMouseScroll":delta=event.detail/3;break;case"mousewheel":delta=event.wheelDelta/120;break;case"wheel":delta=event.deltaY;switch(event.deltaMode){case 0:delta/=100;break;case 1:delta/=3;break;case 2:delta*=80;break;default:throw"unrecognized mouse wheel delta mode: "+event.deltaMode}break;default:throw"unrecognized mouse wheel event: "+event.type}return delta},mouseX:0,mouseY:0,mouseMovementX:0,mouseMovementY:0,touches:{},lastTouches:{},calculateMouseEvent:function(event){if(Browser.pointerLock){if(event.type!="mousemove"&&"mozMovementX"in event){Browser.mouseMovementX=Browser.mouseMovementY=0}else{Browser.mouseMovementX=Browser.getMovementX(event);Browser.mouseMovementY=Browser.getMovementY(event)}if(typeof SDL!="undefined"){Browser.mouseX=SDL.mouseX+Browser.mouseMovementX;Browser.mouseY=SDL.mouseY+Browser.mouseMovementY}else{Browser.mouseX+=Browser.mouseMovementX;Browser.mouseY+=Browser.mouseMovementY}}else{var rect=Module["canvas"].getBoundingClientRect();var cw=Module["canvas"].width;var ch=Module["canvas"].height;var scrollX=typeof window.scrollX!=="undefined"?window.scrollX:window.pageXOffset;var scrollY=typeof window.scrollY!=="undefined"?window.scrollY:window.pageYOffset;if(event.type==="touchstart"||event.type==="touchend"||event.type==="touchmove"){var touch=event.touch;if(touch===undefined){return}var adjustedX=touch.pageX-(scrollX+rect.left);var adjustedY=touch.pageY-(scrollY+rect.top);adjustedX=adjustedX*(cw/rect.width);adjustedY=adjustedY*(ch/rect.height);var coords={x:adjustedX,y:adjustedY};if(event.type==="touchstart"){Browser.lastTouches[touch.identifier]=coords;Browser.touches[touch.identifier]=coords}else if(event.type==="touchend"||event.type==="touchmove"){var last=Browser.touches[touch.identifier];if(!last)last=coords;Browser.lastTouches[touch.identifier]=last;Browser.touches[touch.identifier]=coords}return}var x=event.pageX-(scrollX+rect.left);var y=event.pageY-(scrollY+rect.top);x=x*(cw/rect.width);y=y*(ch/rect.height);Browser.mouseMovementX=x-Browser.mouseX;Browser.mouseMovementY=y-Browser.mouseY;Browser.mouseX=x;Browser.mouseY=y}},asyncLoad:function(url,onload,onerror,noRunDep){var dep=!noRunDep?getUniqueRunDependency("al "+url):"";readAsync(url,function(arrayBuffer){assert(arrayBuffer,'Loading data file "'+url+'" failed (no arrayBuffer).');onload(new Uint8Array(arrayBuffer));if(dep)removeRunDependency(dep)},function(event){if(onerror){onerror()}else{throw'Loading data file "'+url+'" failed.'}});if(dep)addRunDependency(dep)},resizeListeners:[],updateResizeListeners:function(){var canvas=Module["canvas"];Browser.resizeListeners.forEach(function(listener){listener(canvas.width,canvas.height)})},setCanvasSize:function(width,height,noUpdates){var canvas=Module["canvas"];Browser.updateCanvasDimensions(canvas,width,height);if(!noUpdates)Browser.updateResizeListeners()},windowedWidth:0,windowedHeight:0,setFullscreenCanvasSize:function(){if(typeof SDL!="undefined"){var flags=HEAPU32[SDL.screen>>2];flags=flags|8388608;HEAP32[SDL.screen>>2]=flags}Browser.updateCanvasDimensions(Module["canvas"]);Browser.updateResizeListeners()},setWindowedCanvasSize:function(){if(typeof SDL!="undefined"){var flags=HEAPU32[SDL.screen>>2];flags=flags&~8388608;HEAP32[SDL.screen>>2]=flags}Browser.updateCanvasDimensions(Module["canvas"]);Browser.updateResizeListeners()},updateCanvasDimensions:function(canvas,wNative,hNative){if(wNative&&hNative){canvas.widthNative=wNative;canvas.heightNative=hNative}else{wNative=canvas.widthNative;hNative=canvas.heightNative}var w=wNative;var h=hNative;if(Module["forcedAspectRatio"]&&Module["forcedAspectRatio"]>0){if(w/h<Module["forcedAspectRatio"]){w=Math.round(h*Module["forcedAspectRatio"])}else{h=Math.round(w/Module["forcedAspectRatio"])}}if((document["fullscreenElement"]||document["mozFullScreenElement"]||document["msFullscreenElement"]||document["webkitFullscreenElement"]||document["webkitCurrentFullScreenElement"])===canvas.parentNode&&typeof screen!="undefined"){var factor=Math.min(screen.width/w,screen.height/h);w=Math.round(w*factor);h=Math.round(h*factor)}if(Browser.resizeCanvas){if(canvas.width!=w)canvas.width=w;if(canvas.height!=h)canvas.height=h;if(typeof canvas.style!="undefined"){canvas.style.removeProperty("width");canvas.style.removeProperty("height")}}else{if(canvas.width!=wNative)canvas.width=wNative;if(canvas.height!=hNative)canvas.height=hNative;if(typeof canvas.style!="undefined"){if(w!=wNative||h!=hNative){canvas.style.setProperty("width",w+"px","important");canvas.style.setProperty("height",h+"px","important")}else{canvas.style.removeProperty("width");canvas.style.removeProperty("height")}}}},wgetRequests:{},nextWgetRequestHandle:0,getNextWgetRequestHandle:function(){var handle=Browser.nextWgetRequestHandle;Browser.nextWgetRequestHandle++;return handle}};var EGL={errorCode:12288,defaultDisplayInitialized:false,currentContext:0,currentReadSurface:0,currentDrawSurface:0,contextAttributes:{alpha:false,depth:false,stencil:false,antialias:false},stringCache:{},setErrorCode:function(code){EGL.errorCode=code},chooseConfig:function(display,attribList,config,config_size,numConfigs){if(display!=62e3){EGL.setErrorCode(12296);return 0}if(attribList){for(;;){var param=HEAP32[attribList>>2];if(param==12321){var alphaSize=HEAP32[attribList+4>>2];EGL.contextAttributes.alpha=alphaSize>0}else if(param==12325){var depthSize=HEAP32[attribList+4>>2];EGL.contextAttributes.depth=depthSize>0}else if(param==12326){var stencilSize=HEAP32[attribList+4>>2];EGL.contextAttributes.stencil=stencilSize>0}else if(param==12337){var samples=HEAP32[attribList+4>>2];EGL.contextAttributes.antialias=samples>0}else if(param==12338){var samples=HEAP32[attribList+4>>2];EGL.contextAttributes.antialias=samples==1}else if(param==12544){var requestedPriority=HEAP32[attribList+4>>2];EGL.contextAttributes.lowLatency=requestedPriority!=12547}else if(param==12344){break}attribList+=8}}if((!config||!config_size)&&!numConfigs){EGL.setErrorCode(12300);return 0}if(numConfigs){HEAP32[numConfigs>>2]=1}if(config&&config_size>0){HEAP32[config>>2]=62002}EGL.setErrorCode(12288);return 1}};function _eglGetProcAddress(name_){return _emscripten_GetProcAddress(name_)}var JSEvents={keyEvent:0,mouseEvent:0,wheelEvent:0,uiEvent:0,focusEvent:0,deviceOrientationEvent:0,deviceMotionEvent:0,fullscreenChangeEvent:0,pointerlockChangeEvent:0,visibilityChangeEvent:0,touchEvent:0,previousFullscreenElement:null,previousScreenX:null,previousScreenY:null,removeEventListenersRegistered:false,removeAllEventListeners:function(){for(var i=JSEvents.eventHandlers.length-1;i>=0;--i){JSEvents._removeHandler(i)}JSEvents.eventHandlers=[];JSEvents.deferredCalls=[]},registerRemoveEventListeners:function(){if(!JSEvents.removeEventListenersRegistered){__ATEXIT__.push(JSEvents.removeAllEventListeners);JSEvents.removeEventListenersRegistered=true}},deferredCalls:[],deferCall:function(targetFunction,precedence,argsList){function arraysHaveEqualContent(arrA,arrB){if(arrA.length!=arrB.length)return false;for(var i in arrA){if(arrA[i]!=arrB[i])return false}return true}for(var i in JSEvents.deferredCalls){var call=JSEvents.deferredCalls[i];if(call.targetFunction==targetFunction&&arraysHaveEqualContent(call.argsList,argsList)){return}}JSEvents.deferredCalls.push({targetFunction:targetFunction,precedence:precedence,argsList:argsList});JSEvents.deferredCalls.sort(function(x,y){return x.precedence<y.precedence})},removeDeferredCalls:function(targetFunction){for(var i=0;i<JSEvents.deferredCalls.length;++i){if(JSEvents.deferredCalls[i].targetFunction==targetFunction){JSEvents.deferredCalls.splice(i,1);--i}}},canPerformEventHandlerRequests:function(){return JSEvents.inEventHandler&&JSEvents.currentEventHandler.allowsDeferredCalls},runDeferredCalls:function(){if(!JSEvents.canPerformEventHandlerRequests()){return}for(var i=0;i<JSEvents.deferredCalls.length;++i){var call=JSEvents.deferredCalls[i];JSEvents.deferredCalls.splice(i,1);--i;call.targetFunction.apply(this,call.argsList)}},inEventHandler:0,currentEventHandler:null,eventHandlers:[],isInternetExplorer:function(){return navigator.userAgent.indexOf("MSIE")!==-1||navigator.appVersion.indexOf("Trident/")>0},removeAllHandlersOnTarget:function(target,eventTypeString){for(var i=0;i<JSEvents.eventHandlers.length;++i){if(JSEvents.eventHandlers[i].target==target&&(!eventTypeString||eventTypeString==JSEvents.eventHandlers[i].eventTypeString)){JSEvents._removeHandler(i--)}}},_removeHandler:function(i){var h=JSEvents.eventHandlers[i];h.target.removeEventListener(h.eventTypeString,h.eventListenerFunc,h.useCapture);JSEvents.eventHandlers.splice(i,1)},registerOrRemoveHandler:function(eventHandler){var jsEventHandler=function jsEventHandler(event){++JSEvents.inEventHandler;JSEvents.currentEventHandler=eventHandler;JSEvents.runDeferredCalls();eventHandler.handlerFunc(event);JSEvents.runDeferredCalls();--JSEvents.inEventHandler};if(eventHandler.callbackfunc){eventHandler.eventListenerFunc=jsEventHandler;eventHandler.target.addEventListener(eventHandler.eventTypeString,jsEventHandler,eventHandler.useCapture);JSEvents.eventHandlers.push(eventHandler);JSEvents.registerRemoveEventListeners()}else{for(var i=0;i<JSEvents.eventHandlers.length;++i){if(JSEvents.eventHandlers[i].target==eventHandler.target&&JSEvents.eventHandlers[i].eventTypeString==eventHandler.eventTypeString){JSEvents._removeHandler(i--)}}}},getBoundingClientRectOrZeros:function(target){return target.getBoundingClientRect?target.getBoundingClientRect():{left:0,top:0}},pageScrollPos:function(){if(pageXOffset>0||pageYOffset>0){return[pageXOffset,pageYOffset]}if(typeof document.documentElement.scrollLeft!=="undefined"||typeof document.documentElement.scrollTop!=="undefined"){return[document.documentElement.scrollLeft,document.documentElement.scrollTop]}return[document.body.scrollLeft|0,document.body.scrollTop|0]},getNodeNameForTarget:function(target){if(!target)return"";if(target==window)return"#window";if(target==screen)return"#screen";return target&&target.nodeName?target.nodeName:""},tick:function(){if(window["performance"]&&window["performance"]["now"])return window["performance"]["now"]();else return Date.now()},fullscreenEnabled:function(){return document.fullscreenEnabled||document.mozFullScreenEnabled||document.webkitFullscreenEnabled||document.msFullscreenEnabled}};function __requestPointerLock(target){if(target.requestPointerLock){target.requestPointerLock()}else if(target.mozRequestPointerLock){target.mozRequestPointerLock()}else if(target.webkitRequestPointerLock){target.webkitRequestPointerLock()}else if(target.msRequestPointerLock){target.msRequestPointerLock()}else{if(document.body.requestPointerLock||document.body.mozRequestPointerLock||document.body.webkitRequestPointerLock||document.body.msRequestPointerLock){return-3}else{return-1}}return 0}function _emscripten_exit_pointerlock(){JSEvents.removeDeferredCalls(__requestPointerLock);if(document.exitPointerLock){document.exitPointerLock()}else if(document.msExitPointerLock){document.msExitPointerLock()}else if(document.mozExitPointerLock){document.mozExitPointerLock()}else if(document.webkitExitPointerLock){document.webkitExitPointerLock()}else{return-1}return 0}var __specialEventTargets=[0,typeof document!=="undefined"?document:0,typeof window!=="undefined"?window:0];function __findEventTarget(target){try{if(!target)return window;if(typeof target==="number")target=__specialEventTargets[target]||UTF8ToString(target);if(target==="#window")return window;else if(target==="#document")return document;else if(target==="#screen")return screen;else if(target==="#canvas")return Module["canvas"];return typeof target==="string"?document.getElementById(target):target}catch(e){return null}}function _emscripten_get_element_css_size(target,width,height){target=target?__findEventTarget(target):Module["canvas"];if(!target)return-4;if(target.getBoundingClientRect){var rect=target.getBoundingClientRect();HEAPF64[width>>3]=rect.right-rect.left;HEAPF64[height>>3]=rect.bottom-rect.top}else{HEAPF64[width>>3]=target.clientWidth;HEAPF64[height>>3]=target.clientHeight}return 0}function __fillGamepadEventData(eventStruct,e){HEAPF64[eventStruct>>3]=e.timestamp;for(var i=0;i<e.axes.length;++i){HEAPF64[eventStruct+i*8+16>>3]=e.axes[i]}for(var i=0;i<e.buttons.length;++i){if(typeof e.buttons[i]==="object"){HEAPF64[eventStruct+i*8+528>>3]=e.buttons[i].value}else{HEAPF64[eventStruct+i*8+528>>3]=e.buttons[i]}}for(var i=0;i<e.buttons.length;++i){if(typeof e.buttons[i]==="object"){HEAP32[eventStruct+i*4+1040>>2]=e.buttons[i].pressed}else{HEAP32[eventStruct+i*4+1040>>2]=e.buttons[i]==1}}HEAP32[eventStruct+1296>>2]=e.connected;HEAP32[eventStruct+1300>>2]=e.index;HEAP32[eventStruct+8>>2]=e.axes.length;HEAP32[eventStruct+12>>2]=e.buttons.length;stringToUTF8(e.id,eventStruct+1304,64);stringToUTF8(e.mapping,eventStruct+1368,64)}function _emscripten_get_gamepad_status(index,gamepadState){if(index<0||index>=JSEvents.lastGamepadState.length)return-5;if(!JSEvents.lastGamepadState[index])return-7;__fillGamepadEventData(gamepadState,JSEvents.lastGamepadState[index]);return 0}function _emscripten_get_heap_size(){return HEAP8.length}function _emscripten_get_num_gamepads(){return JSEvents.lastGamepadState.length}function __fillPointerlockChangeEventData(eventStruct,e){var pointerLockElement=document.pointerLockElement||document.mozPointerLockElement||document.webkitPointerLockElement||document.msPointerLockElement;var isPointerlocked=!!pointerLockElement;HEAP32[eventStruct>>2]=isPointerlocked;var nodeName=JSEvents.getNodeNameForTarget(pointerLockElement);var id=pointerLockElement&&pointerLockElement.id?pointerLockElement.id:"";stringToUTF8(nodeName,eventStruct+4,128);stringToUTF8(id,eventStruct+132,128)}function _emscripten_get_pointerlock_status(pointerlockStatus){if(pointerlockStatus)__fillPointerlockChangeEventData(pointerlockStatus);if(!document.body||!document.body.requestPointerLock&&!document.body.mozRequestPointerLock&&!document.body.webkitRequestPointerLock&&!document.body.msRequestPointerLock){return-1}return 0}var GL={counter:1,lastError:0,buffers:[],mappedBuffers:{},programs:[],framebuffers:[],renderbuffers:[],textures:[],uniforms:[],shaders:[],vaos:[],contexts:{},currentContext:null,offscreenCanvases:{},timerQueriesEXT:[],programInfos:{},stringCache:{},unpackAlignment:4,init:function(){GL.miniTempBuffer=new Float32Array(GL.MINI_TEMP_BUFFER_SIZE);for(var i=0;i<GL.MINI_TEMP_BUFFER_SIZE;i++){GL.miniTempBufferViews[i]=GL.miniTempBuffer.subarray(0,i+1)}},recordError:function recordError(errorCode){if(!GL.lastError){GL.lastError=errorCode}},getNewId:function(table){var ret=GL.counter++;for(var i=table.length;i<ret;i++){table[i]=null}return ret},MINI_TEMP_BUFFER_SIZE:256,miniTempBuffer:null,miniTempBufferViews:[0],getSource:function(shader,count,string,length){var source="";for(var i=0;i<count;++i){var len=length?HEAP32[length+i*4>>2]:-1;source+=UTF8ToString(HEAP32[string+i*4>>2],len<0?undefined:len)}return source},createContext:function(canvas,webGLContextAttributes){var ctx=canvas.getContext("webgl",webGLContextAttributes)||canvas.getContext("experimental-webgl",webGLContextAttributes);if(!ctx)return 0;var handle=GL.registerContext(ctx,webGLContextAttributes);return handle},registerContext:function(ctx,webGLContextAttributes){var handle=_malloc(8);var context={handle:handle,attributes:webGLContextAttributes,version:webGLContextAttributes.majorVersion,GLctx:ctx};if(ctx.canvas)ctx.canvas.GLctxObject=context;GL.contexts[handle]=context;if(typeof webGLContextAttributes.enableExtensionsByDefault==="undefined"||webGLContextAttributes.enableExtensionsByDefault){GL.initExtensions(context)}return handle},makeContextCurrent:function(contextHandle){GL.currentContext=GL.contexts[contextHandle];Module.ctx=GLctx=GL.currentContext&&GL.currentContext.GLctx;return!(contextHandle&&!GLctx)},getContext:function(contextHandle){return GL.contexts[contextHandle]},deleteContext:function(contextHandle){if(GL.currentContext===GL.contexts[contextHandle])GL.currentContext=null;if(typeof JSEvents==="object")JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas);if(GL.contexts[contextHandle]&&GL.contexts[contextHandle].GLctx.canvas)GL.contexts[contextHandle].GLctx.canvas.GLctxObject=undefined;_free(GL.contexts[contextHandle]);GL.contexts[contextHandle]=null},acquireInstancedArraysExtension:function(ctx){var ext=ctx.getExtension("ANGLE_instanced_arrays");if(ext){ctx["vertexAttribDivisor"]=function(index,divisor){ext["vertexAttribDivisorANGLE"](index,divisor)};ctx["drawArraysInstanced"]=function(mode,first,count,primcount){ext["drawArraysInstancedANGLE"](mode,first,count,primcount)};ctx["drawElementsInstanced"]=function(mode,count,type,indices,primcount){ext["drawElementsInstancedANGLE"](mode,count,type,indices,primcount)}}},acquireVertexArrayObjectExtension:function(ctx){var ext=ctx.getExtension("OES_vertex_array_object");if(ext){ctx["createVertexArray"]=function(){return ext["createVertexArrayOES"]()};ctx["deleteVertexArray"]=function(vao){ext["deleteVertexArrayOES"](vao)};ctx["bindVertexArray"]=function(vao){ext["bindVertexArrayOES"](vao)};ctx["isVertexArray"]=function(vao){return ext["isVertexArrayOES"](vao)}}},acquireDrawBuffersExtension:function(ctx){var ext=ctx.getExtension("WEBGL_draw_buffers");if(ext){ctx["drawBuffers"]=function(n,bufs){ext["drawBuffersWEBGL"](n,bufs)}}},initExtensions:function(context){if(!context)context=GL.currentContext;if(context.initExtensionsDone)return;context.initExtensionsDone=true;var GLctx=context.GLctx;if(context.version<2){GL.acquireInstancedArraysExtension(GLctx);GL.acquireVertexArrayObjectExtension(GLctx);GL.acquireDrawBuffersExtension(GLctx)}GLctx.disjointTimerQueryExt=GLctx.getExtension("EXT_disjoint_timer_query");var automaticallyEnabledExtensions=["OES_texture_float","OES_texture_half_float","OES_standard_derivatives","OES_vertex_array_object","WEBGL_compressed_texture_s3tc","WEBGL_depth_texture","OES_element_index_uint","EXT_texture_filter_anisotropic","EXT_frag_depth","WEBGL_draw_buffers","ANGLE_instanced_arrays","OES_texture_float_linear","OES_texture_half_float_linear","EXT_blend_minmax","EXT_shader_texture_lod","WEBGL_compressed_texture_pvrtc","EXT_color_buffer_half_float","WEBGL_color_buffer_float","EXT_sRGB","WEBGL_compressed_texture_etc1","EXT_disjoint_timer_query","WEBGL_compressed_texture_etc","WEBGL_compressed_texture_astc","EXT_color_buffer_float","WEBGL_compressed_texture_s3tc_srgb","EXT_disjoint_timer_query_webgl2"];var exts=GLctx.getSupportedExtensions()||[];exts.forEach(function(ext){if(automaticallyEnabledExtensions.indexOf(ext)!=-1){GLctx.getExtension(ext)}})},populateUniformTable:function(program){var p=GL.programs[program];var ptable=GL.programInfos[program]={uniforms:{},maxUniformLength:0,maxAttributeLength:-1,maxUniformBlockNameLength:-1};var utable=ptable.uniforms;var numUniforms=GLctx.getProgramParameter(p,35718);for(var i=0;i<numUniforms;++i){var u=GLctx.getActiveUniform(p,i);var name=u.name;ptable.maxUniformLength=Math.max(ptable.maxUniformLength,name.length+1);if(name.slice(-1)=="]"){name=name.slice(0,name.lastIndexOf("["))}var loc=GLctx.getUniformLocation(p,name);if(loc){var id=GL.getNewId(GL.uniforms);utable[name]=[u.size,id];GL.uniforms[id]=loc;for(var j=1;j<u.size;++j){var n=name+"["+j+"]";loc=GLctx.getUniformLocation(p,n);id=GL.getNewId(GL.uniforms);GL.uniforms[id]=loc}}}}};function _emscripten_glActiveTexture(x0){GLctx["activeTexture"](x0)}function _emscripten_glAttachShader(program,shader){GLctx.attachShader(GL.programs[program],GL.shaders[shader])}function _emscripten_glBeginQueryEXT(target,id){GLctx.disjointTimerQueryExt["beginQueryEXT"](target,GL.timerQueriesEXT[id])}function _emscripten_glBindAttribLocation(program,index,name){GLctx.bindAttribLocation(GL.programs[program],index,UTF8ToString(name))}function _emscripten_glBindBuffer(target,buffer){GLctx.bindBuffer(target,GL.buffers[buffer])}function _emscripten_glBindFramebuffer(target,framebuffer){GLctx.bindFramebuffer(target,GL.framebuffers[framebuffer])}function _emscripten_glBindRenderbuffer(target,renderbuffer){GLctx.bindRenderbuffer(target,GL.renderbuffers[renderbuffer])}function _emscripten_glBindTexture(target,texture){GLctx.bindTexture(target,GL.textures[texture])}function _emscripten_glBindVertexArrayOES(vao){GLctx["bindVertexArray"](GL.vaos[vao])}function _emscripten_glBlendColor(x0,x1,x2,x3){GLctx["blendColor"](x0,x1,x2,x3)}function _emscripten_glBlendEquation(x0){GLctx["blendEquation"](x0)}function _emscripten_glBlendEquationSeparate(x0,x1){GLctx["blendEquationSeparate"](x0,x1)}function _emscripten_glBlendFunc(x0,x1){GLctx["blendFunc"](x0,x1)}function _emscripten_glBlendFuncSeparate(x0,x1,x2,x3){GLctx["blendFuncSeparate"](x0,x1,x2,x3)}function _emscripten_glBufferData(target,size,data,usage){GLctx.bufferData(target,data?HEAPU8.subarray(data,data+size):size,usage)}function _emscripten_glBufferSubData(target,offset,size,data){GLctx.bufferSubData(target,offset,HEAPU8.subarray(data,data+size))}function _emscripten_glCheckFramebufferStatus(x0){return GLctx["checkFramebufferStatus"](x0)}function _emscripten_glClear(x0){GLctx["clear"](x0)}function _emscripten_glClearColor(x0,x1,x2,x3){GLctx["clearColor"](x0,x1,x2,x3)}function _emscripten_glClearDepthf(x0){GLctx["clearDepth"](x0)}function _emscripten_glClearStencil(x0){GLctx["clearStencil"](x0)}function _emscripten_glColorMask(red,green,blue,alpha){GLctx.colorMask(!!red,!!green,!!blue,!!alpha)}function _emscripten_glCompileShader(shader){GLctx.compileShader(GL.shaders[shader])}function _emscripten_glCompressedTexImage2D(target,level,internalFormat,width,height,border,imageSize,data){GLctx["compressedTexImage2D"](target,level,internalFormat,width,height,border,data?HEAPU8.subarray(data,data+imageSize):null)}function _emscripten_glCompressedTexSubImage2D(target,level,xoffset,yoffset,width,height,format,imageSize,data){GLctx["compressedTexSubImage2D"](target,level,xoffset,yoffset,width,height,format,data?HEAPU8.subarray(data,data+imageSize):null)}function _emscripten_glCopyTexImage2D(x0,x1,x2,x3,x4,x5,x6,x7){GLctx["copyTexImage2D"](x0,x1,x2,x3,x4,x5,x6,x7)}function _emscripten_glCopyTexSubImage2D(x0,x1,x2,x3,x4,x5,x6,x7){GLctx["copyTexSubImage2D"](x0,x1,x2,x3,x4,x5,x6,x7)}function _emscripten_glCreateProgram(){var id=GL.getNewId(GL.programs);var program=GLctx.createProgram();program.name=id;GL.programs[id]=program;return id}function _emscripten_glCreateShader(shaderType){var id=GL.getNewId(GL.shaders);GL.shaders[id]=GLctx.createShader(shaderType);return id}function _emscripten_glCullFace(x0){GLctx["cullFace"](x0)}function _emscripten_glDeleteBuffers(n,buffers){for(var i=0;i<n;i++){var id=HEAP32[buffers+i*4>>2];var buffer=GL.buffers[id];if(!buffer)continue;GLctx.deleteBuffer(buffer);buffer.name=0;GL.buffers[id]=null;if(id==GL.currArrayBuffer)GL.currArrayBuffer=0;if(id==GL.currElementArrayBuffer)GL.currElementArrayBuffer=0}}function _emscripten_glDeleteFramebuffers(n,framebuffers){for(var i=0;i<n;++i){var id=HEAP32[framebuffers+i*4>>2];var framebuffer=GL.framebuffers[id];if(!framebuffer)continue;GLctx.deleteFramebuffer(framebuffer);framebuffer.name=0;GL.framebuffers[id]=null}}function _emscripten_glDeleteProgram(id){if(!id)return;var program=GL.programs[id];if(!program){GL.recordError(1281);return}GLctx.deleteProgram(program);program.name=0;GL.programs[id]=null;GL.programInfos[id]=null}function _emscripten_glDeleteQueriesEXT(n,ids){for(var i=0;i<n;i++){var id=HEAP32[ids+i*4>>2];var query=GL.timerQueriesEXT[id];if(!query)continue;GLctx.disjointTimerQueryExt["deleteQueryEXT"](query);GL.timerQueriesEXT[id]=null}}function _emscripten_glDeleteRenderbuffers(n,renderbuffers){for(var i=0;i<n;i++){var id=HEAP32[renderbuffers+i*4>>2];var renderbuffer=GL.renderbuffers[id];if(!renderbuffer)continue;GLctx.deleteRenderbuffer(renderbuffer);renderbuffer.name=0;GL.renderbuffers[id]=null}}function _emscripten_glDeleteShader(id){if(!id)return;var shader=GL.shaders[id];if(!shader){GL.recordError(1281);return}GLctx.deleteShader(shader);GL.shaders[id]=null}function _emscripten_glDeleteTextures(n,textures){for(var i=0;i<n;i++){var id=HEAP32[textures+i*4>>2];var texture=GL.textures[id];if(!texture)continue;GLctx.deleteTexture(texture);texture.name=0;GL.textures[id]=null}}function _emscripten_glDeleteVertexArraysOES(n,vaos){for(var i=0;i<n;i++){var id=HEAP32[vaos+i*4>>2];GLctx["deleteVertexArray"](GL.vaos[id]);GL.vaos[id]=null}}function _emscripten_glDepthFunc(x0){GLctx["depthFunc"](x0)}function _emscripten_glDepthMask(flag){GLctx.depthMask(!!flag)}function _emscripten_glDepthRangef(x0,x1){GLctx["depthRange"](x0,x1)}function _emscripten_glDetachShader(program,shader){GLctx.detachShader(GL.programs[program],GL.shaders[shader])}function _emscripten_glDisable(x0){GLctx["disable"](x0)}function _emscripten_glDisableVertexAttribArray(index){GLctx.disableVertexAttribArray(index)}function _emscripten_glDrawArrays(mode,first,count){GLctx.drawArrays(mode,first,count)}function _emscripten_glDrawArraysInstancedANGLE(mode,first,count,primcount){GLctx["drawArraysInstanced"](mode,first,count,primcount)}var __tempFixedLengthArray=[];function _emscripten_glDrawBuffersWEBGL(n,bufs){var bufArray=__tempFixedLengthArray[n];for(var i=0;i<n;i++){bufArray[i]=HEAP32[bufs+i*4>>2]}GLctx["drawBuffers"](bufArray)}function _emscripten_glDrawElements(mode,count,type,indices){GLctx.drawElements(mode,count,type,indices)}function _emscripten_glDrawElementsInstancedANGLE(mode,count,type,indices,primcount){GLctx["drawElementsInstanced"](mode,count,type,indices,primcount)}function _emscripten_glEnable(x0){GLctx["enable"](x0)}function _emscripten_glEnableVertexAttribArray(index){GLctx.enableVertexAttribArray(index)}function _emscripten_glEndQueryEXT(target){GLctx.disjointTimerQueryExt["endQueryEXT"](target)}function _emscripten_glFinish(){GLctx["finish"]()}function _emscripten_glFlush(){GLctx["flush"]()}function _emscripten_glFramebufferRenderbuffer(target,attachment,renderbuffertarget,renderbuffer){GLctx.framebufferRenderbuffer(target,attachment,renderbuffertarget,GL.renderbuffers[renderbuffer])}function _emscripten_glFramebufferTexture2D(target,attachment,textarget,texture,level){GLctx.framebufferTexture2D(target,attachment,textarget,GL.textures[texture],level)}function _emscripten_glFrontFace(x0){GLctx["frontFace"](x0)}function __glGenObject(n,buffers,createFunction,objectTable){for(var i=0;i<n;i++){var buffer=GLctx[createFunction]();var id=buffer&&GL.getNewId(objectTable);if(buffer){buffer.name=id;objectTable[id]=buffer}else{GL.recordError(1282)}HEAP32[buffers+i*4>>2]=id}}function _emscripten_glGenBuffers(n,buffers){__glGenObject(n,buffers,"createBuffer",GL.buffers)}function _emscripten_glGenFramebuffers(n,ids){__glGenObject(n,ids,"createFramebuffer",GL.framebuffers)}function _emscripten_glGenQueriesEXT(n,ids){for(var i=0;i<n;i++){var query=GLctx.disjointTimerQueryExt["createQueryEXT"]();if(!query){GL.recordError(1282);while(i<n)HEAP32[ids+i++*4>>2]=0;return}var id=GL.getNewId(GL.timerQueriesEXT);query.name=id;GL.timerQueriesEXT[id]=query;HEAP32[ids+i*4>>2]=id}}function _emscripten_glGenRenderbuffers(n,renderbuffers){__glGenObject(n,renderbuffers,"createRenderbuffer",GL.renderbuffers)}function _emscripten_glGenTextures(n,textures){__glGenObject(n,textures,"createTexture",GL.textures)}function _emscripten_glGenVertexArraysOES(n,arrays){__glGenObject(n,arrays,"createVertexArray",GL.vaos)}function _emscripten_glGenerateMipmap(x0){GLctx["generateMipmap"](x0)}function _emscripten_glGetActiveAttrib(program,index,bufSize,length,size,type,name){program=GL.programs[program];var info=GLctx.getActiveAttrib(program,index);if(!info)return;var numBytesWrittenExclNull=bufSize>0&&name?stringToUTF8(info.name,name,bufSize):0;if(length)HEAP32[length>>2]=numBytesWrittenExclNull;if(size)HEAP32[size>>2]=info.size;if(type)HEAP32[type>>2]=info.type}function _emscripten_glGetActiveUniform(program,index,bufSize,length,size,type,name){program=GL.programs[program];var info=GLctx.getActiveUniform(program,index);if(!info)return;var numBytesWrittenExclNull=bufSize>0&&name?stringToUTF8(info.name,name,bufSize):0;if(length)HEAP32[length>>2]=numBytesWrittenExclNull;if(size)HEAP32[size>>2]=info.size;if(type)HEAP32[type>>2]=info.type}function _emscripten_glGetAttachedShaders(program,maxCount,count,shaders){var result=GLctx.getAttachedShaders(GL.programs[program]);var len=result.length;if(len>maxCount){len=maxCount}HEAP32[count>>2]=len;for(var i=0;i<len;++i){var id=GL.shaders.indexOf(result[i]);HEAP32[shaders+i*4>>2]=id}}function _emscripten_glGetAttribLocation(program,name){return GLctx.getAttribLocation(GL.programs[program],UTF8ToString(name))}function emscriptenWebGLGet(name_,p,type){if(!p){GL.recordError(1281);return}var ret=undefined;switch(name_){case 36346:ret=1;break;case 36344:if(type!=0&&type!=1){GL.recordError(1280)}return;case 36345:ret=0;break;case 34466:var formats=GLctx.getParameter(34467);ret=formats?formats.length:0;break}if(ret===undefined){var result=GLctx.getParameter(name_);switch(typeof result){case"number":ret=result;break;case"boolean":ret=result?1:0;break;case"string":GL.recordError(1280);return;case"object":if(result===null){switch(name_){case 34964:case 35725:case 34965:case 36006:case 36007:case 32873:case 34229:case 34068:{ret=0;break}default:{GL.recordError(1280);return}}}else if(result instanceof Float32Array||result instanceof Uint32Array||result instanceof Int32Array||result instanceof Array){for(var i=0;i<result.length;++i){switch(type){case 0:HEAP32[p+i*4>>2]=result[i];break;case 2:HEAPF32[p+i*4>>2]=result[i];break;case 4:HEAP8[p+i>>0]=result[i]?1:0;break}}return}else{try{ret=result.name|0}catch(e){GL.recordError(1280);err("GL_INVALID_ENUM in glGet"+type+"v: Unknown object returned from WebGL getParameter("+name_+")! (error: "+e+")");return}}break;default:GL.recordError(1280);err("GL_INVALID_ENUM in glGet"+type+"v: Native code calling glGet"+type+"v("+name_+") and it returns "+result+" of type "+typeof result+"!");return}}switch(type){case 1:tempI64=[ret>>>0,(tempDouble=ret,+Math_abs(tempDouble)>=1?tempDouble>0?(Math_min(+Math_floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[p>>2]=tempI64[0],HEAP32[p+4>>2]=tempI64[1];break;case 0:HEAP32[p>>2]=ret;break;case 2:HEAPF32[p>>2]=ret;break;case 4:HEAP8[p>>0]=ret?1:0;break}}function _emscripten_glGetBooleanv(name_,p){emscriptenWebGLGet(name_,p,4)}function _emscripten_glGetBufferParameteriv(target,value,data){if(!data){GL.recordError(1281);return}HEAP32[data>>2]=GLctx.getBufferParameter(target,value)}function _emscripten_glGetError(){var error=GLctx.getError()||GL.lastError;GL.lastError=0;return error}function _emscripten_glGetFloatv(name_,p){emscriptenWebGLGet(name_,p,2)}function _emscripten_glGetFramebufferAttachmentParameteriv(target,attachment,pname,params){var result=GLctx.getFramebufferAttachmentParameter(target,attachment,pname);if(result instanceof WebGLRenderbuffer||result instanceof WebGLTexture){result=result.name|0}HEAP32[params>>2]=result}function _emscripten_glGetIntegerv(name_,p){emscriptenWebGLGet(name_,p,0)}function _emscripten_glGetProgramInfoLog(program,maxLength,length,infoLog){var log=GLctx.getProgramInfoLog(GL.programs[program]);if(log===null)log="(unknown error)";var numBytesWrittenExclNull=maxLength>0&&infoLog?stringToUTF8(log,infoLog,maxLength):0;if(length)HEAP32[length>>2]=numBytesWrittenExclNull}function _emscripten_glGetProgramiv(program,pname,p){if(!p){GL.recordError(1281);return}if(program>=GL.counter){GL.recordError(1281);return}var ptable=GL.programInfos[program];if(!ptable){GL.recordError(1282);return}if(pname==35716){var log=GLctx.getProgramInfoLog(GL.programs[program]);if(log===null)log="(unknown error)";HEAP32[p>>2]=log.length+1}else if(pname==35719){HEAP32[p>>2]=ptable.maxUniformLength}else if(pname==35722){if(ptable.maxAttributeLength==-1){program=GL.programs[program];var numAttribs=GLctx.getProgramParameter(program,35721);ptable.maxAttributeLength=0;for(var i=0;i<numAttribs;++i){var activeAttrib=GLctx.getActiveAttrib(program,i);ptable.maxAttributeLength=Math.max(ptable.maxAttributeLength,activeAttrib.name.length+1)}}HEAP32[p>>2]=ptable.maxAttributeLength}else if(pname==35381){if(ptable.maxUniformBlockNameLength==-1){program=GL.programs[program];var numBlocks=GLctx.getProgramParameter(program,35382);ptable.maxUniformBlockNameLength=0;for(var i=0;i<numBlocks;++i){var activeBlockName=GLctx.getActiveUniformBlockName(program,i);ptable.maxUniformBlockNameLength=Math.max(ptable.maxUniformBlockNameLength,activeBlockName.length+1)}}HEAP32[p>>2]=ptable.maxUniformBlockNameLength}else{HEAP32[p>>2]=GLctx.getProgramParameter(GL.programs[program],pname)}}function _emscripten_glGetQueryObjecti64vEXT(id,pname,params){if(!params){GL.recordError(1281);return}var query=GL.timerQueriesEXT[id];var param=GLctx.disjointTimerQueryExt["getQueryObjectEXT"](query,pname);var ret;if(typeof param=="boolean"){ret=param?1:0}else{ret=param}tempI64=[ret>>>0,(tempDouble=ret,+Math_abs(tempDouble)>=1?tempDouble>0?(Math_min(+Math_floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[params>>2]=tempI64[0],HEAP32[params+4>>2]=tempI64[1]}function _emscripten_glGetQueryObjectivEXT(id,pname,params){if(!params){GL.recordError(1281);return}var query=GL.timerQueriesEXT[id];var param=GLctx.disjointTimerQueryExt["getQueryObjectEXT"](query,pname);var ret;if(typeof param=="boolean"){ret=param?1:0}else{ret=param}HEAP32[params>>2]=ret}function _emscripten_glGetQueryObjectui64vEXT(id,pname,params){if(!params){GL.recordError(1281);return}var query=GL.timerQueriesEXT[id];var param=GLctx.disjointTimerQueryExt["getQueryObjectEXT"](query,pname);var ret;if(typeof param=="boolean"){ret=param?1:0}else{ret=param}tempI64=[ret>>>0,(tempDouble=ret,+Math_abs(tempDouble)>=1?tempDouble>0?(Math_min(+Math_floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[params>>2]=tempI64[0],HEAP32[params+4>>2]=tempI64[1]}function _emscripten_glGetQueryObjectuivEXT(id,pname,params){if(!params){GL.recordError(1281);return}var query=GL.timerQueriesEXT[id];var param=GLctx.disjointTimerQueryExt["getQueryObjectEXT"](query,pname);var ret;if(typeof param=="boolean"){ret=param?1:0}else{ret=param}HEAP32[params>>2]=ret}function _emscripten_glGetQueryivEXT(target,pname,params){if(!params){GL.recordError(1281);return}HEAP32[params>>2]=GLctx.disjointTimerQueryExt["getQueryEXT"](target,pname)}function _emscripten_glGetRenderbufferParameteriv(target,pname,params){if(!params){GL.recordError(1281);return}HEAP32[params>>2]=GLctx.getRenderbufferParameter(target,pname)}function _emscripten_glGetShaderInfoLog(shader,maxLength,length,infoLog){var log=GLctx.getShaderInfoLog(GL.shaders[shader]);if(log===null)log="(unknown error)";var numBytesWrittenExclNull=maxLength>0&&infoLog?stringToUTF8(log,infoLog,maxLength):0;if(length)HEAP32[length>>2]=numBytesWrittenExclNull}function _emscripten_glGetShaderPrecisionFormat(shaderType,precisionType,range,precision){var result=GLctx.getShaderPrecisionFormat(shaderType,precisionType);HEAP32[range>>2]=result.rangeMin;HEAP32[range+4>>2]=result.rangeMax;HEAP32[precision>>2]=result.precision}function _emscripten_glGetShaderSource(shader,bufSize,length,source){var result=GLctx.getShaderSource(GL.shaders[shader]);if(!result)return;var numBytesWrittenExclNull=bufSize>0&&source?stringToUTF8(result,source,bufSize):0;if(length)HEAP32[length>>2]=numBytesWrittenExclNull}function _emscripten_glGetShaderiv(shader,pname,p){if(!p){GL.recordError(1281);return}if(pname==35716){var log=GLctx.getShaderInfoLog(GL.shaders[shader]);if(log===null)log="(unknown error)";HEAP32[p>>2]=log.length+1}else if(pname==35720){var source=GLctx.getShaderSource(GL.shaders[shader]);var sourceLength=source===null||source.length==0?0:source.length+1;HEAP32[p>>2]=sourceLength}else{HEAP32[p>>2]=GLctx.getShaderParameter(GL.shaders[shader],pname)}}function stringToNewUTF8(jsString){var length=lengthBytesUTF8(jsString)+1;var cString=_malloc(length);stringToUTF8(jsString,cString,length);return cString}function _emscripten_glGetString(name_){if(GL.stringCache[name_])return GL.stringCache[name_];var ret;switch(name_){case 7939:var exts=GLctx.getSupportedExtensions()||[];exts=exts.concat(exts.map(function(e){return"GL_"+e}));ret=stringToNewUTF8(exts.join(" "));break;case 7936:case 7937:case 37445:case 37446:var s=GLctx.getParameter(name_);if(!s){GL.recordError(1280)}ret=stringToNewUTF8(s);break;case 7938:var glVersion=GLctx.getParameter(GLctx.VERSION);{glVersion="OpenGL ES 2.0 ("+glVersion+")"}ret=stringToNewUTF8(glVersion);break;case 35724:var glslVersion=GLctx.getParameter(GLctx.SHADING_LANGUAGE_VERSION);var ver_re=/^WebGL GLSL ES ([0-9]\.[0-9][0-9]?)(?:$| .*)/;var ver_num=glslVersion.match(ver_re);if(ver_num!==null){if(ver_num[1].length==3)ver_num[1]=ver_num[1]+"0";glslVersion="OpenGL ES GLSL ES "+ver_num[1]+" ("+glslVersion+")"}ret=stringToNewUTF8(glslVersion);break;default:GL.recordError(1280);return 0}GL.stringCache[name_]=ret;return ret}function _emscripten_glGetTexParameterfv(target,pname,params){if(!params){GL.recordError(1281);return}HEAPF32[params>>2]=GLctx.getTexParameter(target,pname)}function _emscripten_glGetTexParameteriv(target,pname,params){if(!params){GL.recordError(1281);return}HEAP32[params>>2]=GLctx.getTexParameter(target,pname)}function _emscripten_glGetUniformLocation(program,name){name=UTF8ToString(name);var arrayIndex=0;if(name[name.length-1]=="]"){var leftBrace=name.lastIndexOf("[");arrayIndex=name[leftBrace+1]!="]"?parseInt(name.slice(leftBrace+1)):0;name=name.slice(0,leftBrace)}var uniformInfo=GL.programInfos[program]&&GL.programInfos[program].uniforms[name];if(uniformInfo&&arrayIndex>=0&&arrayIndex<uniformInfo[0]){return uniformInfo[1]+arrayIndex}else{return-1}}function emscriptenWebGLGetUniform(program,location,params,type){if(!params){GL.recordError(1281);return}var data=GLctx.getUniform(GL.programs[program],GL.uniforms[location]);if(typeof data=="number"||typeof data=="boolean"){switch(type){case 0:HEAP32[params>>2]=data;break;case 2:HEAPF32[params>>2]=data;break;default:throw"internal emscriptenWebGLGetUniform() error, bad type: "+type}}else{for(var i=0;i<data.length;i++){switch(type){case 0:HEAP32[params+i*4>>2]=data[i];break;case 2:HEAPF32[params+i*4>>2]=data[i];break;default:throw"internal emscriptenWebGLGetUniform() error, bad type: "+type}}}}function _emscripten_glGetUniformfv(program,location,params){emscriptenWebGLGetUniform(program,location,params,2)}function _emscripten_glGetUniformiv(program,location,params){emscriptenWebGLGetUniform(program,location,params,0)}function _emscripten_glGetVertexAttribPointerv(index,pname,pointer){if(!pointer){GL.recordError(1281);return}HEAP32[pointer>>2]=GLctx.getVertexAttribOffset(index,pname)}function emscriptenWebGLGetVertexAttrib(index,pname,params,type){if(!params){GL.recordError(1281);return}var data=GLctx.getVertexAttrib(index,pname);if(pname==34975){HEAP32[params>>2]=data["name"]}else if(typeof data=="number"||typeof data=="boolean"){switch(type){case 0:HEAP32[params>>2]=data;break;case 2:HEAPF32[params>>2]=data;break;case 5:HEAP32[params>>2]=Math.fround(data);break;default:throw"internal emscriptenWebGLGetVertexAttrib() error, bad type: "+type}}else{for(var i=0;i<data.length;i++){switch(type){case 0:HEAP32[params+i*4>>2]=data[i];break;case 2:HEAPF32[params+i*4>>2]=data[i];break;case 5:HEAP32[params+i*4>>2]=Math.fround(data[i]);break;default:throw"internal emscriptenWebGLGetVertexAttrib() error, bad type: "+type}}}}function _emscripten_glGetVertexAttribfv(index,pname,params){emscriptenWebGLGetVertexAttrib(index,pname,params,2)}function _emscripten_glGetVertexAttribiv(index,pname,params){emscriptenWebGLGetVertexAttrib(index,pname,params,5)}function _emscripten_glHint(x0,x1){GLctx["hint"](x0,x1)}function _emscripten_glIsBuffer(buffer){var b=GL.buffers[buffer];if(!b)return 0;return GLctx.isBuffer(b)}function _emscripten_glIsEnabled(x0){return GLctx["isEnabled"](x0)}function _emscripten_glIsFramebuffer(framebuffer){var fb=GL.framebuffers[framebuffer];if(!fb)return 0;return GLctx.isFramebuffer(fb)}function _emscripten_glIsProgram(program){program=GL.programs[program];if(!program)return 0;return GLctx.isProgram(program)}function _emscripten_glIsQueryEXT(id){var query=GL.timerQueriesEXT[id];if(!query)return 0;return GLctx.disjointTimerQueryExt["isQueryEXT"](query)}function _emscripten_glIsRenderbuffer(renderbuffer){var rb=GL.renderbuffers[renderbuffer];if(!rb)return 0;return GLctx.isRenderbuffer(rb)}function _emscripten_glIsShader(shader){var s=GL.shaders[shader];if(!s)return 0;return GLctx.isShader(s)}function _emscripten_glIsTexture(id){var texture=GL.textures[id];if(!texture)return 0;return GLctx.isTexture(texture)}function _emscripten_glIsVertexArrayOES(array){var vao=GL.vaos[array];if(!vao)return 0;return GLctx["isVertexArray"](vao)}function _emscripten_glLineWidth(x0){GLctx["lineWidth"](x0)}function _emscripten_glLinkProgram(program){GLctx.linkProgram(GL.programs[program]);GL.populateUniformTable(program)}function _emscripten_glPixelStorei(pname,param){if(pname==3317){GL.unpackAlignment=param}GLctx.pixelStorei(pname,param)}function _emscripten_glPolygonOffset(x0,x1){GLctx["polygonOffset"](x0,x1)}function _emscripten_glQueryCounterEXT(id,target){GLctx.disjointTimerQueryExt["queryCounterEXT"](GL.timerQueriesEXT[id],target)}function __computeUnpackAlignedImageSize(width,height,sizePerPixel,alignment){function roundedToNextMultipleOf(x,y){return x+y-1&-y}var plainRowSize=width*sizePerPixel;var alignedRowSize=roundedToNextMultipleOf(plainRowSize,alignment);return height*alignedRowSize}var __colorChannelsInGlTextureFormat={6402:1,6406:1,6407:3,6408:4,6409:1,6410:2,35904:3,35906:4};var __sizeOfGlTextureElementType={5121:1,5123:2,5125:4,5126:4,32819:2,32820:2,33635:2,34042:4,36193:2};function emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,internalFormat){var sizePerPixel=__colorChannelsInGlTextureFormat[format]*__sizeOfGlTextureElementType[type];if(!sizePerPixel){GL.recordError(1280);return}var bytes=__computeUnpackAlignedImageSize(width,height,sizePerPixel,GL.unpackAlignment);var end=pixels+bytes;switch(type){case 5121:return HEAPU8.subarray(pixels,end);case 5126:return HEAPF32.subarray(pixels>>2,end>>2);case 5125:case 34042:return HEAPU32.subarray(pixels>>2,end>>2);case 5123:case 33635:case 32819:case 32820:case 36193:return HEAPU16.subarray(pixels>>1,end>>1);default:GL.recordError(1280)}}function _emscripten_glReadPixels(x,y,width,height,format,type,pixels){var pixelData=emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,format);if(!pixelData){GL.recordError(1280);return}GLctx.readPixels(x,y,width,height,format,type,pixelData)}function _emscripten_glReleaseShaderCompiler(){}function _emscripten_glRenderbufferStorage(x0,x1,x2,x3){GLctx["renderbufferStorage"](x0,x1,x2,x3)}function _emscripten_glSampleCoverage(value,invert){GLctx.sampleCoverage(value,!!invert)}function _emscripten_glScissor(x0,x1,x2,x3){GLctx["scissor"](x0,x1,x2,x3)}function _emscripten_glShaderBinary(){GL.recordError(1280)}function _emscripten_glShaderSource(shader,count,string,length){var source=GL.getSource(shader,count,string,length);GLctx.shaderSource(GL.shaders[shader],source)}function _emscripten_glStencilFunc(x0,x1,x2){GLctx["stencilFunc"](x0,x1,x2)}function _emscripten_glStencilFuncSeparate(x0,x1,x2,x3){GLctx["stencilFuncSeparate"](x0,x1,x2,x3)}function _emscripten_glStencilMask(x0){GLctx["stencilMask"](x0)}function _emscripten_glStencilMaskSeparate(x0,x1){GLctx["stencilMaskSeparate"](x0,x1)}function _emscripten_glStencilOp(x0,x1,x2){GLctx["stencilOp"](x0,x1,x2)}function _emscripten_glStencilOpSeparate(x0,x1,x2,x3){GLctx["stencilOpSeparate"](x0,x1,x2,x3)}function _emscripten_glTexImage2D(target,level,internalFormat,width,height,border,format,type,pixels){GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,pixels?emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,internalFormat):null)}function _emscripten_glTexParameterf(x0,x1,x2){GLctx["texParameterf"](x0,x1,x2)}function _emscripten_glTexParameterfv(target,pname,params){var param=HEAPF32[params>>2];GLctx.texParameterf(target,pname,param)}function _emscripten_glTexParameteri(x0,x1,x2){GLctx["texParameteri"](x0,x1,x2)}function _emscripten_glTexParameteriv(target,pname,params){var param=HEAP32[params>>2];GLctx.texParameteri(target,pname,param)}function _emscripten_glTexSubImage2D(target,level,xoffset,yoffset,width,height,format,type,pixels){var pixelData=null;if(pixels)pixelData=emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,0);GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,pixelData)}function _emscripten_glUniform1f(location,v0){GLctx.uniform1f(GL.uniforms[location],v0)}function _emscripten_glUniform1fv(location,count,value){if(count<=GL.MINI_TEMP_BUFFER_SIZE){var view=GL.miniTempBufferViews[count-1];for(var i=0;i<count;++i){view[i]=HEAPF32[value+4*i>>2]}}else{var view=HEAPF32.subarray(value>>2,value+count*4>>2)}GLctx.uniform1fv(GL.uniforms[location],view)}function _emscripten_glUniform1i(location,v0){GLctx.uniform1i(GL.uniforms[location],v0)}function _emscripten_glUniform1iv(location,count,value){GLctx.uniform1iv(GL.uniforms[location],HEAP32.subarray(value>>2,value+count*4>>2))}function _emscripten_glUniform2f(location,v0,v1){GLctx.uniform2f(GL.uniforms[location],v0,v1)}function _emscripten_glUniform2fv(location,count,value){if(2*count<=GL.MINI_TEMP_BUFFER_SIZE){var view=GL.miniTempBufferViews[2*count-1];for(var i=0;i<2*count;i+=2){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2]}}else{var view=HEAPF32.subarray(value>>2,value+count*8>>2)}GLctx.uniform2fv(GL.uniforms[location],view)}function _emscripten_glUniform2i(location,v0,v1){GLctx.uniform2i(GL.uniforms[location],v0,v1)}function _emscripten_glUniform2iv(location,count,value){GLctx.uniform2iv(GL.uniforms[location],HEAP32.subarray(value>>2,value+count*8>>2))}function _emscripten_glUniform3f(location,v0,v1,v2){GLctx.uniform3f(GL.uniforms[location],v0,v1,v2)}function _emscripten_glUniform3fv(location,count,value){if(3*count<=GL.MINI_TEMP_BUFFER_SIZE){var view=GL.miniTempBufferViews[3*count-1];for(var i=0;i<3*count;i+=3){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2];view[i+2]=HEAPF32[value+(4*i+8)>>2]}}else{var view=HEAPF32.subarray(value>>2,value+count*12>>2)}GLctx.uniform3fv(GL.uniforms[location],view)}function _emscripten_glUniform3i(location,v0,v1,v2){GLctx.uniform3i(GL.uniforms[location],v0,v1,v2)}function _emscripten_glUniform3iv(location,count,value){GLctx.uniform3iv(GL.uniforms[location],HEAP32.subarray(value>>2,value+count*12>>2))}function _emscripten_glUniform4f(location,v0,v1,v2,v3){GLctx.uniform4f(GL.uniforms[location],v0,v1,v2,v3)}function _emscripten_glUniform4fv(location,count,value){if(4*count<=GL.MINI_TEMP_BUFFER_SIZE){var view=GL.miniTempBufferViews[4*count-1];for(var i=0;i<4*count;i+=4){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2];view[i+2]=HEAPF32[value+(4*i+8)>>2];view[i+3]=HEAPF32[value+(4*i+12)>>2]}}else{var view=HEAPF32.subarray(value>>2,value+count*16>>2)}GLctx.uniform4fv(GL.uniforms[location],view)}function _emscripten_glUniform4i(location,v0,v1,v2,v3){GLctx.uniform4i(GL.uniforms[location],v0,v1,v2,v3)}function _emscripten_glUniform4iv(location,count,value){GLctx.uniform4iv(GL.uniforms[location],HEAP32.subarray(value>>2,value+count*16>>2))}function _emscripten_glUniformMatrix2fv(location,count,transpose,value){if(4*count<=GL.MINI_TEMP_BUFFER_SIZE){var view=GL.miniTempBufferViews[4*count-1];for(var i=0;i<4*count;i+=4){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2];view[i+2]=HEAPF32[value+(4*i+8)>>2];view[i+3]=HEAPF32[value+(4*i+12)>>2]}}else{var view=HEAPF32.subarray(value>>2,value+count*16>>2)}GLctx.uniformMatrix2fv(GL.uniforms[location],!!transpose,view)}function _emscripten_glUniformMatrix3fv(location,count,transpose,value){if(9*count<=GL.MINI_TEMP_BUFFER_SIZE){var view=GL.miniTempBufferViews[9*count-1];for(var i=0;i<9*count;i+=9){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2];view[i+2]=HEAPF32[value+(4*i+8)>>2];view[i+3]=HEAPF32[value+(4*i+12)>>2];view[i+4]=HEAPF32[value+(4*i+16)>>2];view[i+5]=HEAPF32[value+(4*i+20)>>2];view[i+6]=HEAPF32[value+(4*i+24)>>2];view[i+7]=HEAPF32[value+(4*i+28)>>2];view[i+8]=HEAPF32[value+(4*i+32)>>2]}}else{var view=HEAPF32.subarray(value>>2,value+count*36>>2)}GLctx.uniformMatrix3fv(GL.uniforms[location],!!transpose,view)}function _emscripten_glUniformMatrix4fv(location,count,transpose,value){if(16*count<=GL.MINI_TEMP_BUFFER_SIZE){var view=GL.miniTempBufferViews[16*count-1];for(var i=0;i<16*count;i+=16){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2];view[i+2]=HEAPF32[value+(4*i+8)>>2];view[i+3]=HEAPF32[value+(4*i+12)>>2];view[i+4]=HEAPF32[value+(4*i+16)>>2];view[i+5]=HEAPF32[value+(4*i+20)>>2];view[i+6]=HEAPF32[value+(4*i+24)>>2];view[i+7]=HEAPF32[value+(4*i+28)>>2];view[i+8]=HEAPF32[value+(4*i+32)>>2];view[i+9]=HEAPF32[value+(4*i+36)>>2];view[i+10]=HEAPF32[value+(4*i+40)>>2];view[i+11]=HEAPF32[value+(4*i+44)>>2];view[i+12]=HEAPF32[value+(4*i+48)>>2];view[i+13]=HEAPF32[value+(4*i+52)>>2];view[i+14]=HEAPF32[value+(4*i+56)>>2];view[i+15]=HEAPF32[value+(4*i+60)>>2]}}else{var view=HEAPF32.subarray(value>>2,value+count*64>>2)}GLctx.uniformMatrix4fv(GL.uniforms[location],!!transpose,view)}function _emscripten_glUseProgram(program){GLctx.useProgram(GL.programs[program])}function _emscripten_glValidateProgram(program){GLctx.validateProgram(GL.programs[program])}function _emscripten_glVertexAttrib1f(x0,x1){GLctx["vertexAttrib1f"](x0,x1)}function _emscripten_glVertexAttrib1fv(index,v){GLctx.vertexAttrib1f(index,HEAPF32[v>>2])}function _emscripten_glVertexAttrib2f(x0,x1,x2){GLctx["vertexAttrib2f"](x0,x1,x2)}function _emscripten_glVertexAttrib2fv(index,v){GLctx.vertexAttrib2f(index,HEAPF32[v>>2],HEAPF32[v+4>>2])}function _emscripten_glVertexAttrib3f(x0,x1,x2,x3){GLctx["vertexAttrib3f"](x0,x1,x2,x3)}function _emscripten_glVertexAttrib3fv(index,v){GLctx.vertexAttrib3f(index,HEAPF32[v>>2],HEAPF32[v+4>>2],HEAPF32[v+8>>2])}function _emscripten_glVertexAttrib4f(x0,x1,x2,x3,x4){GLctx["vertexAttrib4f"](x0,x1,x2,x3,x4)}function _emscripten_glVertexAttrib4fv(index,v){GLctx.vertexAttrib4f(index,HEAPF32[v>>2],HEAPF32[v+4>>2],HEAPF32[v+8>>2],HEAPF32[v+12>>2])}function _emscripten_glVertexAttribDivisorANGLE(index,divisor){GLctx["vertexAttribDivisor"](index,divisor)}function _emscripten_glVertexAttribPointer(index,size,type,normalized,stride,ptr){GLctx.vertexAttribPointer(index,size,type,!!normalized,stride,ptr)}function _emscripten_glViewport(x0,x1,x2,x3){GLctx["viewport"](x0,x1,x2,x3)}function _emscripten_request_pointerlock(target,deferUntilInEventHandler){if(!target)target="#canvas";target=__findEventTarget(target);if(!target)return-4;if(!target.requestPointerLock&&!target.mozRequestPointerLock&&!target.webkitRequestPointerLock&&!target.msRequestPointerLock){return-1}var canPerformRequests=JSEvents.canPerformEventHandlerRequests();if(!canPerformRequests){if(deferUntilInEventHandler){JSEvents.deferCall(__requestPointerLock,2,[target]);return 1}else{return-2}}return __requestPointerLock(target)}function _emscripten_run_script(ptr){eval(UTF8ToString(ptr))}function _emscripten_sample_gamepad_data(){return(JSEvents.lastGamepadState=navigator.getGamepads?navigator.getGamepads():navigator.webkitGetGamepads?navigator.webkitGetGamepads():null)?0:-1}function __fillMouseEventData(eventStruct,e,target){HEAPF64[eventStruct>>3]=JSEvents.tick();HEAP32[eventStruct+8>>2]=e.screenX;HEAP32[eventStruct+12>>2]=e.screenY;HEAP32[eventStruct+16>>2]=e.clientX;HEAP32[eventStruct+20>>2]=e.clientY;HEAP32[eventStruct+24>>2]=e.ctrlKey;HEAP32[eventStruct+28>>2]=e.shiftKey;HEAP32[eventStruct+32>>2]=e.altKey;HEAP32[eventStruct+36>>2]=e.metaKey;HEAP16[eventStruct+40>>1]=e.button;HEAP16[eventStruct+42>>1]=e.buttons;HEAP32[eventStruct+44>>2]=e["movementX"]||e["mozMovementX"]||e["webkitMovementX"]||e.screenX-JSEvents.previousScreenX;HEAP32[eventStruct+48>>2]=e["movementY"]||e["mozMovementY"]||e["webkitMovementY"]||e.screenY-JSEvents.previousScreenY;if(Module["canvas"]){var rect=Module["canvas"].getBoundingClientRect();HEAP32[eventStruct+60>>2]=e.clientX-rect.left;HEAP32[eventStruct+64>>2]=e.clientY-rect.top}else{HEAP32[eventStruct+60>>2]=0;HEAP32[eventStruct+64>>2]=0}if(target){var rect=JSEvents.getBoundingClientRectOrZeros(target);HEAP32[eventStruct+52>>2]=e.clientX-rect.left;HEAP32[eventStruct+56>>2]=e.clientY-rect.top}else{HEAP32[eventStruct+52>>2]=0;HEAP32[eventStruct+56>>2]=0}if(e.type!=="wheel"&&e.type!=="mousewheel"){JSEvents.previousScreenX=e.screenX;JSEvents.previousScreenY=e.screenY}}function __registerMouseEventCallback(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread){if(!JSEvents.mouseEvent)JSEvents.mouseEvent=_malloc(72);target=__findEventTarget(target);var mouseEventHandlerFunc=function(ev){var e=ev||event;__fillMouseEventData(JSEvents.mouseEvent,e,target);if(dynCall_iiii(callbackfunc,eventTypeId,JSEvents.mouseEvent,userData))e.preventDefault()};var eventHandler={target:target,allowsDeferredCalls:eventTypeString!="mousemove"&&eventTypeString!="mouseenter"&&eventTypeString!="mouseleave",eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:mouseEventHandlerFunc,useCapture:useCapture};if(JSEvents.isInternetExplorer()&&eventTypeString=="mousedown")eventHandler.allowsDeferredCalls=false;JSEvents.registerOrRemoveHandler(eventHandler)}function _emscripten_set_click_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){__registerMouseEventCallback(target,userData,useCapture,callbackfunc,4,"click",targetThread);return 0}function __fillFullscreenChangeEventData(eventStruct,e){var fullscreenElement=document.fullscreenElement||document.mozFullScreenElement||document.webkitFullscreenElement||document.msFullscreenElement;var isFullscreen=!!fullscreenElement;HEAP32[eventStruct>>2]=isFullscreen;HEAP32[eventStruct+4>>2]=JSEvents.fullscreenEnabled();var reportedElement=isFullscreen?fullscreenElement:JSEvents.previousFullscreenElement;var nodeName=JSEvents.getNodeNameForTarget(reportedElement);var id=reportedElement&&reportedElement.id?reportedElement.id:"";stringToUTF8(nodeName,eventStruct+8,128);stringToUTF8(id,eventStruct+136,128);HEAP32[eventStruct+264>>2]=reportedElement?reportedElement.clientWidth:0;HEAP32[eventStruct+268>>2]=reportedElement?reportedElement.clientHeight:0;HEAP32[eventStruct+272>>2]=screen.width;HEAP32[eventStruct+276>>2]=screen.height;if(isFullscreen){JSEvents.previousFullscreenElement=fullscreenElement}}function __registerFullscreenChangeEventCallback(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread){if(!JSEvents.fullscreenChangeEvent)JSEvents.fullscreenChangeEvent=_malloc(280);var fullscreenChangeEventhandlerFunc=function(ev){var e=ev||event;var fullscreenChangeEvent=JSEvents.fullscreenChangeEvent;__fillFullscreenChangeEventData(fullscreenChangeEvent,e);if(dynCall_iiii(callbackfunc,eventTypeId,fullscreenChangeEvent,userData))e.preventDefault()};var eventHandler={target:target,allowsDeferredCalls:false,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:fullscreenChangeEventhandlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}function _emscripten_set_fullscreenchange_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){if(!JSEvents.fullscreenEnabled())return-1;target=target?__findEventTarget(target):__specialEventTargets[1];if(!target)return-4;__registerFullscreenChangeEventCallback(target,userData,useCapture,callbackfunc,19,"fullscreenchange",targetThread);__registerFullscreenChangeEventCallback(target,userData,useCapture,callbackfunc,19,"mozfullscreenchange",targetThread);__registerFullscreenChangeEventCallback(target,userData,useCapture,callbackfunc,19,"webkitfullscreenchange",targetThread);__registerFullscreenChangeEventCallback(target,userData,useCapture,callbackfunc,19,"msfullscreenchange",targetThread);return 0}function __registerGamepadEventCallback(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread){if(!JSEvents.gamepadEvent)JSEvents.gamepadEvent=_malloc(1432);var gamepadEventHandlerFunc=function(ev){var e=ev||event;var gamepadEvent=JSEvents.gamepadEvent;__fillGamepadEventData(gamepadEvent,e["gamepad"]);if(dynCall_iiii(callbackfunc,eventTypeId,gamepadEvent,userData))e.preventDefault()};var eventHandler={target:__findEventTarget(target),allowsDeferredCalls:true,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:gamepadEventHandlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}function _emscripten_set_gamepadconnected_callback_on_thread(userData,useCapture,callbackfunc,targetThread){if(!navigator.getGamepads&&!navigator.webkitGetGamepads)return-1;__registerGamepadEventCallback(2,userData,useCapture,callbackfunc,26,"gamepadconnected",targetThread);return 0}function _emscripten_set_gamepaddisconnected_callback_on_thread(userData,useCapture,callbackfunc,targetThread){if(!navigator.getGamepads&&!navigator.webkitGetGamepads)return-1;__registerGamepadEventCallback(2,userData,useCapture,callbackfunc,27,"gamepaddisconnected",targetThread);return 0}function __registerKeyEventCallback(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread){if(!JSEvents.keyEvent)JSEvents.keyEvent=_malloc(164);var keyEventHandlerFunc=function(ev){var e=ev||event;var keyEventData=JSEvents.keyEvent;stringToUTF8(e.key?e.key:"",keyEventData+0,32);stringToUTF8(e.code?e.code:"",keyEventData+32,32);HEAP32[keyEventData+64>>2]=e.location;HEAP32[keyEventData+68>>2]=e.ctrlKey;HEAP32[keyEventData+72>>2]=e.shiftKey;HEAP32[keyEventData+76>>2]=e.altKey;HEAP32[keyEventData+80>>2]=e.metaKey;HEAP32[keyEventData+84>>2]=e.repeat;stringToUTF8(e.locale?e.locale:"",keyEventData+88,32);stringToUTF8(e.char?e.char:"",keyEventData+120,32);HEAP32[keyEventData+152>>2]=e.charCode;HEAP32[keyEventData+156>>2]=e.keyCode;HEAP32[keyEventData+160>>2]=e.which;if(dynCall_iiii(callbackfunc,eventTypeId,keyEventData,userData))e.preventDefault()};var eventHandler={target:__findEventTarget(target),allowsDeferredCalls:JSEvents.isInternetExplorer()?false:true,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:keyEventHandlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}function _emscripten_set_keypress_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){__registerKeyEventCallback(target,userData,useCapture,callbackfunc,1,"keypress",targetThread);return 0}function __registerTouchEventCallback(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread){if(!JSEvents.touchEvent)JSEvents.touchEvent=_malloc(1684);target=__findEventTarget(target);var touchEventHandlerFunc=function(ev){var e=ev||event;var touches={};for(var i=0;i<e.touches.length;++i){var touch=e.touches[i];touch.changed=false;touches[touch.identifier]=touch}for(var i=0;i<e.changedTouches.length;++i){var touch=e.changedTouches[i];touches[touch.identifier]=touch;touch.changed=true}for(var i=0;i<e.targetTouches.length;++i){var touch=e.targetTouches[i];touches[touch.identifier].onTarget=true}var touchEvent=JSEvents.touchEvent;var ptr=touchEvent;HEAP32[ptr+4>>2]=e.ctrlKey;HEAP32[ptr+8>>2]=e.shiftKey;HEAP32[ptr+12>>2]=e.altKey;HEAP32[ptr+16>>2]=e.metaKey;ptr+=20;var canvasRect=Module["canvas"]?Module["canvas"].getBoundingClientRect():undefined;var targetRect=JSEvents.getBoundingClientRectOrZeros(target);var numTouches=0;for(var i in touches){var t=touches[i];HEAP32[ptr>>2]=t.identifier;HEAP32[ptr+4>>2]=t.screenX;HEAP32[ptr+8>>2]=t.screenY;HEAP32[ptr+12>>2]=t.clientX;HEAP32[ptr+16>>2]=t.clientY;HEAP32[ptr+20>>2]=t.pageX;HEAP32[ptr+24>>2]=t.pageY;HEAP32[ptr+28>>2]=t.changed;HEAP32[ptr+32>>2]=t.onTarget;if(canvasRect){HEAP32[ptr+44>>2]=t.clientX-canvasRect.left;HEAP32[ptr+48>>2]=t.clientY-canvasRect.top}else{HEAP32[ptr+44>>2]=0;HEAP32[ptr+48>>2]=0}HEAP32[ptr+36>>2]=t.clientX-targetRect.left;HEAP32[ptr+40>>2]=t.clientY-targetRect.top;ptr+=52;if(++numTouches>=32){break}}HEAP32[touchEvent>>2]=numTouches;if(dynCall_iiii(callbackfunc,eventTypeId,touchEvent,userData))e.preventDefault()};var eventHandler={target:target,allowsDeferredCalls:eventTypeString=="touchstart"||eventTypeString=="touchend",eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:touchEventHandlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}function _emscripten_set_touchcancel_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){__registerTouchEventCallback(target,userData,useCapture,callbackfunc,25,"touchcancel",targetThread);return 0}function _emscripten_set_touchend_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){__registerTouchEventCallback(target,userData,useCapture,callbackfunc,23,"touchend",targetThread);return 0}function _emscripten_set_touchmove_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){__registerTouchEventCallback(target,userData,useCapture,callbackfunc,24,"touchmove",targetThread);return 0}function _emscripten_set_touchstart_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){__registerTouchEventCallback(target,userData,useCapture,callbackfunc,22,"touchstart",targetThread);return 0}function _exit(status){exit(status)}function _glActiveTexture(x0){GLctx["activeTexture"](x0)}function _glAttachShader(program,shader){GLctx.attachShader(GL.programs[program],GL.shaders[shader])}function _glBindAttribLocation(program,index,name){GLctx.bindAttribLocation(GL.programs[program],index,UTF8ToString(name))}function _glBindBuffer(target,buffer){GLctx.bindBuffer(target,GL.buffers[buffer])}function _glBindTexture(target,texture){GLctx.bindTexture(target,GL.textures[texture])}function _glBlendFunc(x0,x1){GLctx["blendFunc"](x0,x1)}function _glBufferData(target,size,data,usage){GLctx.bufferData(target,data?HEAPU8.subarray(data,data+size):size,usage)}function _glBufferSubData(target,offset,size,data){GLctx.bufferSubData(target,offset,HEAPU8.subarray(data,data+size))}function _glClear(x0){GLctx["clear"](x0)}function _glClearColor(x0,x1,x2,x3){GLctx["clearColor"](x0,x1,x2,x3)}function _glClearDepthf(x0){GLctx["clearDepth"](x0)}function _glCompileShader(shader){GLctx.compileShader(GL.shaders[shader])}function _glCompressedTexImage2D(target,level,internalFormat,width,height,border,imageSize,data){GLctx["compressedTexImage2D"](target,level,internalFormat,width,height,border,data?HEAPU8.subarray(data,data+imageSize):null)}function _glCreateProgram(){var id=GL.getNewId(GL.programs);var program=GLctx.createProgram();program.name=id;GL.programs[id]=program;return id}function _glCreateShader(shaderType){var id=GL.getNewId(GL.shaders);GL.shaders[id]=GLctx.createShader(shaderType);return id}function _glCullFace(x0){GLctx["cullFace"](x0)}function _glDeleteBuffers(n,buffers){for(var i=0;i<n;i++){var id=HEAP32[buffers+i*4>>2];var buffer=GL.buffers[id];if(!buffer)continue;GLctx.deleteBuffer(buffer);buffer.name=0;GL.buffers[id]=null;if(id==GL.currArrayBuffer)GL.currArrayBuffer=0;if(id==GL.currElementArrayBuffer)GL.currElementArrayBuffer=0}}function _glDeleteProgram(id){if(!id)return;var program=GL.programs[id];if(!program){GL.recordError(1281);return}GLctx.deleteProgram(program);program.name=0;GL.programs[id]=null;GL.programInfos[id]=null}function _glDeleteShader(id){if(!id)return;var shader=GL.shaders[id];if(!shader){GL.recordError(1281);return}GLctx.deleteShader(shader);GL.shaders[id]=null}function _glDeleteTextures(n,textures){for(var i=0;i<n;i++){var id=HEAP32[textures+i*4>>2];var texture=GL.textures[id];if(!texture)continue;GLctx.deleteTexture(texture);texture.name=0;GL.textures[id]=null}}function _glDepthFunc(x0){GLctx["depthFunc"](x0)}function _glDetachShader(program,shader){GLctx.detachShader(GL.programs[program],GL.shaders[shader])}function _glDisable(x0){GLctx["disable"](x0)}function _glDisableVertexAttribArray(index){GLctx.disableVertexAttribArray(index)}function _glDrawArrays(mode,first,count){GLctx.drawArrays(mode,first,count)}function _glDrawElements(mode,count,type,indices){GLctx.drawElements(mode,count,type,indices)}function _glEnable(x0){GLctx["enable"](x0)}function _glEnableVertexAttribArray(index){GLctx.enableVertexAttribArray(index)}function _glFrontFace(x0){GLctx["frontFace"](x0)}function _glGenBuffers(n,buffers){__glGenObject(n,buffers,"createBuffer",GL.buffers)}function _glGenTextures(n,textures){__glGenObject(n,textures,"createTexture",GL.textures)}function _glGetAttribLocation(program,name){return GLctx.getAttribLocation(GL.programs[program],UTF8ToString(name))}function _glGetFloatv(name_,p){emscriptenWebGLGet(name_,p,2)}function _glGetProgramInfoLog(program,maxLength,length,infoLog){var log=GLctx.getProgramInfoLog(GL.programs[program]);if(log===null)log="(unknown error)";var numBytesWrittenExclNull=maxLength>0&&infoLog?stringToUTF8(log,infoLog,maxLength):0;if(length)HEAP32[length>>2]=numBytesWrittenExclNull}function _glGetProgramiv(program,pname,p){if(!p){GL.recordError(1281);return}if(program>=GL.counter){GL.recordError(1281);return}var ptable=GL.programInfos[program];if(!ptable){GL.recordError(1282);return}if(pname==35716){var log=GLctx.getProgramInfoLog(GL.programs[program]);if(log===null)log="(unknown error)";HEAP32[p>>2]=log.length+1}else if(pname==35719){HEAP32[p>>2]=ptable.maxUniformLength}else if(pname==35722){if(ptable.maxAttributeLength==-1){program=GL.programs[program];var numAttribs=GLctx.getProgramParameter(program,35721);ptable.maxAttributeLength=0;for(var i=0;i<numAttribs;++i){var activeAttrib=GLctx.getActiveAttrib(program,i);ptable.maxAttributeLength=Math.max(ptable.maxAttributeLength,activeAttrib.name.length+1)}}HEAP32[p>>2]=ptable.maxAttributeLength}else if(pname==35381){if(ptable.maxUniformBlockNameLength==-1){program=GL.programs[program];var numBlocks=GLctx.getProgramParameter(program,35382);ptable.maxUniformBlockNameLength=0;for(var i=0;i<numBlocks;++i){var activeBlockName=GLctx.getActiveUniformBlockName(program,i);ptable.maxUniformBlockNameLength=Math.max(ptable.maxUniformBlockNameLength,activeBlockName.length+1)}}HEAP32[p>>2]=ptable.maxUniformBlockNameLength}else{HEAP32[p>>2]=GLctx.getProgramParameter(GL.programs[program],pname)}}function _glGetShaderInfoLog(shader,maxLength,length,infoLog){var log=GLctx.getShaderInfoLog(GL.shaders[shader]);if(log===null)log="(unknown error)";var numBytesWrittenExclNull=maxLength>0&&infoLog?stringToUTF8(log,infoLog,maxLength):0;if(length)HEAP32[length>>2]=numBytesWrittenExclNull}function _glGetShaderiv(shader,pname,p){if(!p){GL.recordError(1281);return}if(pname==35716){var log=GLctx.getShaderInfoLog(GL.shaders[shader]);if(log===null)log="(unknown error)";HEAP32[p>>2]=log.length+1}else if(pname==35720){var source=GLctx.getShaderSource(GL.shaders[shader]);var sourceLength=source===null||source.length==0?0:source.length+1;HEAP32[p>>2]=sourceLength}else{HEAP32[p>>2]=GLctx.getShaderParameter(GL.shaders[shader],pname)}}function _glGetString(name_){if(GL.stringCache[name_])return GL.stringCache[name_];var ret;switch(name_){case 7939:var exts=GLctx.getSupportedExtensions()||[];exts=exts.concat(exts.map(function(e){return"GL_"+e}));ret=stringToNewUTF8(exts.join(" "));break;case 7936:case 7937:case 37445:case 37446:var s=GLctx.getParameter(name_);if(!s){GL.recordError(1280)}ret=stringToNewUTF8(s);break;case 7938:var glVersion=GLctx.getParameter(GLctx.VERSION);{glVersion="OpenGL ES 2.0 ("+glVersion+")"}ret=stringToNewUTF8(glVersion);break;case 35724:var glslVersion=GLctx.getParameter(GLctx.SHADING_LANGUAGE_VERSION);var ver_re=/^WebGL GLSL ES ([0-9]\.[0-9][0-9]?)(?:$| .*)/;var ver_num=glslVersion.match(ver_re);if(ver_num!==null){if(ver_num[1].length==3)ver_num[1]=ver_num[1]+"0";glslVersion="OpenGL ES GLSL ES "+ver_num[1]+" ("+glslVersion+")"}ret=stringToNewUTF8(glslVersion);break;default:GL.recordError(1280);return 0}GL.stringCache[name_]=ret;return ret}function _glGetUniformLocation(program,name){name=UTF8ToString(name);var arrayIndex=0;if(name[name.length-1]=="]"){var leftBrace=name.lastIndexOf("[");arrayIndex=name[leftBrace+1]!="]"?parseInt(name.slice(leftBrace+1)):0;name=name.slice(0,leftBrace)}var uniformInfo=GL.programInfos[program]&&GL.programInfos[program].uniforms[name];if(uniformInfo&&arrayIndex>=0&&arrayIndex<uniformInfo[0]){return uniformInfo[1]+arrayIndex}else{return-1}}function _glLinkProgram(program){GLctx.linkProgram(GL.programs[program]);GL.populateUniformTable(program)}function _glPixelStorei(pname,param){if(pname==3317){GL.unpackAlignment=param}GLctx.pixelStorei(pname,param)}function _glReadPixels(x,y,width,height,format,type,pixels){var pixelData=emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,format);if(!pixelData){GL.recordError(1280);return}GLctx.readPixels(x,y,width,height,format,type,pixelData)}function _glShaderSource(shader,count,string,length){var source=GL.getSource(shader,count,string,length);GLctx.shaderSource(GL.shaders[shader],source)}function _glTexImage2D(target,level,internalFormat,width,height,border,format,type,pixels){GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,pixels?emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,internalFormat):null)}function _glTexParameteri(x0,x1,x2){GLctx["texParameteri"](x0,x1,x2)}function _glUniform1i(location,v0){GLctx.uniform1i(GL.uniforms[location],v0)}function _glUniform4f(location,v0,v1,v2,v3){GLctx.uniform4f(GL.uniforms[location],v0,v1,v2,v3)}function _glUniformMatrix4fv(location,count,transpose,value){if(16*count<=GL.MINI_TEMP_BUFFER_SIZE){var view=GL.miniTempBufferViews[16*count-1];for(var i=0;i<16*count;i+=16){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2];view[i+2]=HEAPF32[value+(4*i+8)>>2];view[i+3]=HEAPF32[value+(4*i+12)>>2];view[i+4]=HEAPF32[value+(4*i+16)>>2];view[i+5]=HEAPF32[value+(4*i+20)>>2];view[i+6]=HEAPF32[value+(4*i+24)>>2];view[i+7]=HEAPF32[value+(4*i+28)>>2];view[i+8]=HEAPF32[value+(4*i+32)>>2];view[i+9]=HEAPF32[value+(4*i+36)>>2];view[i+10]=HEAPF32[value+(4*i+40)>>2];view[i+11]=HEAPF32[value+(4*i+44)>>2];view[i+12]=HEAPF32[value+(4*i+48)>>2];view[i+13]=HEAPF32[value+(4*i+52)>>2];view[i+14]=HEAPF32[value+(4*i+56)>>2];view[i+15]=HEAPF32[value+(4*i+60)>>2]}}else{var view=HEAPF32.subarray(value>>2,value+count*64>>2)}GLctx.uniformMatrix4fv(GL.uniforms[location],!!transpose,view)}function _glUseProgram(program){GLctx.useProgram(GL.programs[program])}function _glVertexAttrib2f(x0,x1,x2){GLctx["vertexAttrib2f"](x0,x1,x2)}function _glVertexAttrib3f(x0,x1,x2,x3){GLctx["vertexAttrib3f"](x0,x1,x2,x3)}function _glVertexAttrib4f(x0,x1,x2,x3,x4){GLctx["vertexAttrib4f"](x0,x1,x2,x3,x4)}function _glVertexAttribPointer(index,size,type,normalized,stride,ptr){GLctx.vertexAttribPointer(index,size,type,!!normalized,stride,ptr)}function _glViewport(x0,x1,x2,x3){GLctx["viewport"](x0,x1,x2,x3)}var GLFW={Window:function(id,width,height,title,monitor,share){this.id=id;this.x=0;this.y=0;this.fullscreen=false;this.storedX=0;this.storedY=0;this.width=width;this.height=height;this.storedWidth=width;this.storedHeight=height;this.title=title;this.monitor=monitor;this.share=share;this.attributes=GLFW.hints;this.inputModes={208897:212993,208898:0,208899:0};this.buttons=0;this.keys=new Array;this.domKeys=new Array;this.shouldClose=0;this.title=null;this.windowPosFunc=null;this.windowSizeFunc=null;this.windowCloseFunc=null;this.windowRefreshFunc=null;this.windowFocusFunc=null;this.windowIconifyFunc=null;this.framebufferSizeFunc=null;this.mouseButtonFunc=null;this.cursorPosFunc=null;this.cursorEnterFunc=null;this.scrollFunc=null;this.dropFunc=null;this.keyFunc=null;this.charFunc=null;this.userptr=null},WindowFromId:function(id){if(id<=0||!GLFW.windows)return null;return GLFW.windows[id-1]},joystickFunc:null,errorFunc:null,monitorFunc:null,active:null,windows:null,monitors:null,monitorString:null,versionString:null,initialTime:null,extensions:null,hints:null,defaultHints:{131073:0,131074:0,131075:1,131076:1,131077:1,135169:8,135170:8,135171:8,135172:8,135173:24,135174:8,135175:0,135176:0,135177:0,135178:0,135179:0,135180:0,135181:0,135182:0,135183:0,139265:196609,139266:1,139267:0,139268:0,139269:0,139270:0,139271:0,139272:0},DOMToGLFWKeyCode:function(keycode){switch(keycode){case 32:return 32;case 222:return 39;case 188:return 44;case 173:return 45;case 189:return 45;case 190:return 46;case 191:return 47;case 48:return 48;case 49:return 49;case 50:return 50;case 51:return 51;case 52:return 52;case 53:return 53;case 54:return 54;case 55:return 55;case 56:return 56;case 57:return 57;case 59:return 59;case 61:return 61;case 187:return 61;case 65:return 65;case 66:return 66;case 67:return 67;case 68:return 68;case 69:return 69;case 70:return 70;case 71:return 71;case 72:return 72;case 73:return 73;case 74:return 74;case 75:return 75;case 76:return 76;case 77:return 77;case 78:return 78;case 79:return 79;case 80:return 80;case 81:return 81;case 82:return 82;case 83:return 83;case 84:return 84;case 85:return 85;case 86:return 86;case 87:return 87;case 88:return 88;case 89:return 89;case 90:return 90;case 219:return 91;case 220:return 92;case 221:return 93;case 192:return 94;case 27:return 256;case 13:return 257;case 9:return 258;case 8:return 259;case 45:return 260;case 46:return 261;case 39:return 262;case 37:return 263;case 40:return 264;case 38:return 265;case 33:return 266;case 34:return 267;case 36:return 268;case 35:return 269;case 20:return 280;case 145:return 281;case 144:return 282;case 44:return 283;case 19:return 284;case 112:return 290;case 113:return 291;case 114:return 292;case 115:return 293;case 116:return 294;case 117:return 295;case 118:return 296;case 119:return 297;case 120:return 298;case 121:return 299;case 122:return 300;case 123:return 301;case 124:return 302;case 125:return 303;case 126:return 304;case 127:return 305;case 128:return 306;case 129:return 307;case 130:return 308;case 131:return 309;case 132:return 310;case 133:return 311;case 134:return 312;case 135:return 313;case 136:return 314;case 96:return 320;case 97:return 321;case 98:return 322;case 99:return 323;case 100:return 324;case 101:return 325;case 102:return 326;case 103:return 327;case 104:return 328;case 105:return 329;case 110:return 330;case 111:return 331;case 106:return 332;case 109:return 333;case 107:return 334;case 16:return 340;case 17:return 341;case 18:return 342;case 91:return 343;case 93:return 348;default:return-1}},getModBits:function(win){var mod=0;if(win.keys[340])mod|=1;if(win.keys[341])mod|=2;if(win.keys[342])mod|=4;if(win.keys[343])mod|=8;return mod},onKeyPress:function(event){if(!GLFW.active||!GLFW.active.charFunc)return;if(event.ctrlKey||event.metaKey)return;var charCode=event.charCode;if(charCode==0||charCode>=0&&charCode<=31)return;dynCall_vii(GLFW.active.charFunc,GLFW.active.id,charCode)},onKeyChanged:function(keyCode,status){if(!GLFW.active)return;var key=GLFW.DOMToGLFWKeyCode(keyCode);if(key==-1)return;var repeat=status&&GLFW.active.keys[key];GLFW.active.keys[key]=status;GLFW.active.domKeys[keyCode]=status;if(!GLFW.active.keyFunc)return;if(repeat)status=2;dynCall_viiiii(GLFW.active.keyFunc,GLFW.active.id,key,keyCode,status,GLFW.getModBits(GLFW.active))},onGamepadConnected:function(event){GLFW.refreshJoysticks()},onGamepadDisconnected:function(event){GLFW.refreshJoysticks()},onKeydown:function(event){GLFW.onKeyChanged(event.keyCode,1);if(event.keyCode===8||event.keyCode===9){event.preventDefault()}},onKeyup:function(event){GLFW.onKeyChanged(event.keyCode,0)},onBlur:function(event){if(!GLFW.active)return;for(var i=0;i<GLFW.active.domKeys.length;++i){if(GLFW.active.domKeys[i]){GLFW.onKeyChanged(i,0)}}},onMousemove:function(event){if(!GLFW.active)return;Browser.calculateMouseEvent(event);if(event.target!=Module["canvas"]||!GLFW.active.cursorPosFunc)return;dynCall_vidd(GLFW.active.cursorPosFunc,GLFW.active.id,Browser.mouseX,Browser.mouseY)},DOMToGLFWMouseButton:function(event){var eventButton=event["button"];if(eventButton>0){if(eventButton==1){eventButton=2}else{eventButton=1}}return eventButton},onMouseenter:function(event){if(!GLFW.active)return;if(event.target!=Module["canvas"]||!GLFW.active.cursorEnterFunc)return;dynCall_vii(GLFW.active.cursorEnterFunc,GLFW.active.id,1)},onMouseleave:function(event){if(!GLFW.active)return;if(event.target!=Module["canvas"]||!GLFW.active.cursorEnterFunc)return;dynCall_vii(GLFW.active.cursorEnterFunc,GLFW.active.id,0)},onMouseButtonChanged:function(event,status){if(!GLFW.active)return;Browser.calculateMouseEvent(event);if(event.target!=Module["canvas"])return;var eventButton=GLFW.DOMToGLFWMouseButton(event);if(status==1){GLFW.active.buttons|=1<<eventButton;try{event.target.setCapture()}catch(e){}}else{GLFW.active.buttons&=~(1<<eventButton)}if(!GLFW.active.mouseButtonFunc)return;dynCall_viiii(GLFW.active.mouseButtonFunc,GLFW.active.id,eventButton,status,GLFW.getModBits(GLFW.active))},onMouseButtonDown:function(event){if(!GLFW.active)return;GLFW.onMouseButtonChanged(event,1)},onMouseButtonUp:function(event){if(!GLFW.active)return;GLFW.onMouseButtonChanged(event,0)},onMouseWheel:function(event){var delta=-Browser.getMouseWheelDelta(event);delta=delta==0?0:delta>0?Math.max(delta,1):Math.min(delta,-1);GLFW.wheelPos+=delta;if(!GLFW.active||!GLFW.active.scrollFunc||event.target!=Module["canvas"])return;var sx=0;var sy=0;if(event.type=="mousewheel"){sx=event.wheelDeltaX;sy=event.wheelDeltaY}else{sx=event.deltaX;sy=event.deltaY}dynCall_vidd(GLFW.active.scrollFunc,GLFW.active.id,sx,sy);event.preventDefault()},onCanvasResize:function(width,height){if(!GLFW.active)return;var resizeNeeded=true;if(document["fullscreen"]||document["fullScreen"]||document["mozFullScreen"]||document["webkitIsFullScreen"]){GLFW.active.storedX=GLFW.active.x;GLFW.active.storedY=GLFW.active.y;GLFW.active.storedWidth=GLFW.active.width;GLFW.active.storedHeight=GLFW.active.height;GLFW.active.x=GLFW.active.y=0;GLFW.active.width=screen.width;GLFW.active.height=screen.height;GLFW.active.fullscreen=true}else if(GLFW.active.fullscreen==true){GLFW.active.x=GLFW.active.storedX;GLFW.active.y=GLFW.active.storedY;GLFW.active.width=GLFW.active.storedWidth;GLFW.active.height=GLFW.active.storedHeight;GLFW.active.fullscreen=false}else if(GLFW.active.width!=width||GLFW.active.height!=height){GLFW.active.width=width;GLFW.active.height=height}else{resizeNeeded=false}if(resizeNeeded){Browser.setCanvasSize(GLFW.active.width,GLFW.active.height,true);GLFW.onWindowSizeChanged();GLFW.onFramebufferSizeChanged()}},onWindowSizeChanged:function(){if(!GLFW.active)return;if(!GLFW.active.windowSizeFunc)return;dynCall_viii(GLFW.active.windowSizeFunc,GLFW.active.id,GLFW.active.width,GLFW.active.height)},onFramebufferSizeChanged:function(){if(!GLFW.active)return;if(!GLFW.active.framebufferSizeFunc)return;dynCall_viii(GLFW.active.framebufferSizeFunc,GLFW.active.id,GLFW.active.width,GLFW.active.height)},requestFullscreen:function(){var RFS=Module["canvas"]["requestFullscreen"]||Module["canvas"]["mozRequestFullScreen"]||Module["canvas"]["webkitRequestFullScreen"]||function(){};RFS.apply(Module["canvas"],[])},requestFullScreen:function(){err("GLFW.requestFullScreen() is deprecated. Please call GLFW.requestFullscreen instead.");GLFW.requestFullScreen=function(){return GLFW.requestFullscreen()};return GLFW.requestFullscreen()},exitFullscreen:function(){Browser.exitFullscreen()},cancelFullScreen:function(){err("GLFW.cancelFullScreen() is deprecated. Please call GLFW.exitFullscreen instead.");GLFW.cancelFullScreen=function(){return GLFW.exitFullscreen()};return GLFW.exitFullscreen()},getTime:function(){return _emscripten_get_now()/1e3},setWindowTitle:function(winid,title){var win=GLFW.WindowFromId(winid);if(!win)return;win.title=UTF8ToString(title);if(GLFW.active.id==win.id){document.title=win.title}},setJoystickCallback:function(cbfun){GLFW.joystickFunc=cbfun;GLFW.refreshJoysticks()},joys:{},lastGamepadState:null,lastGamepadStateFrame:null,refreshJoysticks:function(){if(Browser.mainLoop.currentFrameNumber!==GLFW.lastGamepadStateFrame||!Browser.mainLoop.currentFrameNumber){GLFW.lastGamepadState=navigator.getGamepads?navigator.getGamepads():navigator.webkitGetGamepads?navigator.webkitGetGamepads:null;GLFW.lastGamepadStateFrame=Browser.mainLoop.currentFrameNumber;for(var joy=0;joy<GLFW.lastGamepadState.length;++joy){var gamepad=GLFW.lastGamepadState[joy];if(gamepad){if(!GLFW.joys[joy]){console.log("glfw joystick connected:",joy);GLFW.joys[joy]={id:allocate(intArrayFromString(gamepad.id),"i8",ALLOC_NORMAL),buttonsCount:gamepad.buttons.length,axesCount:gamepad.axes.length,buttons:allocate(new Array(gamepad.buttons.length),"i8",ALLOC_NORMAL),axes:allocate(new Array(gamepad.axes.length*4),"float",ALLOC_NORMAL)};if(GLFW.joystickFunc){dynCall_vii(GLFW.joystickFunc,joy,262145)}}var data=GLFW.joys[joy];for(var i=0;i<gamepad.buttons.length;++i){setValue(data.buttons+i,gamepad.buttons[i].pressed,"i8")}for(var i=0;i<gamepad.axes.length;++i){setValue(data.axes+i*4,gamepad.axes[i],"float")}}else{if(GLFW.joys[joy]){console.log("glfw joystick disconnected",joy);if(GLFW.joystickFunc){dynCall_vii(GLFW.joystickFunc,joy,262146)}_free(GLFW.joys[joy].id);_free(GLFW.joys[joy].buttons);_free(GLFW.joys[joy].axes);delete GLFW.joys[joy]}}}}},setKeyCallback:function(winid,cbfun){var win=GLFW.WindowFromId(winid);if(!win)return null;var prevcbfun=win.keyFunc;win.keyFunc=cbfun;return prevcbfun},setCharCallback:function(winid,cbfun){var win=GLFW.WindowFromId(winid);if(!win)return null;var prevcbfun=win.charFunc;win.charFunc=cbfun;return prevcbfun},setMouseButtonCallback:function(winid,cbfun){var win=GLFW.WindowFromId(winid);if(!win)return null;var prevcbfun=win.mouseButtonFunc;win.mouseButtonFunc=cbfun;return prevcbfun},setCursorPosCallback:function(winid,cbfun){var win=GLFW.WindowFromId(winid);if(!win)return null;var prevcbfun=win.cursorPosFunc;win.cursorPosFunc=cbfun;return prevcbfun},setScrollCallback:function(winid,cbfun){var win=GLFW.WindowFromId(winid);if(!win)return null;var prevcbfun=win.scrollFunc;win.scrollFunc=cbfun;return prevcbfun},setDropCallback:function(winid,cbfun){var win=GLFW.WindowFromId(winid);if(!win)return null;var prevcbfun=win.dropFunc;win.dropFunc=cbfun;return prevcbfun},onDrop:function(event){if(!GLFW.active||!GLFW.active.dropFunc)return;if(!event.dataTransfer||!event.dataTransfer.files||event.dataTransfer.files.length==0)return;event.preventDefault();return false},onDragover:function(event){if(!GLFW.active||!GLFW.active.dropFunc)return;event.preventDefault();return false},setWindowSizeCallback:function(winid,cbfun){var win=GLFW.WindowFromId(winid);if(!win)return null;var prevcbfun=win.windowSizeFunc;win.windowSizeFunc=cbfun;return prevcbfun},setWindowCloseCallback:function(winid,cbfun){var win=GLFW.WindowFromId(winid);if(!win)return null;var prevcbfun=win.windowCloseFunc;win.windowCloseFunc=cbfun;return prevcbfun},setWindowRefreshCallback:function(winid,cbfun){var win=GLFW.WindowFromId(winid);if(!win)return null;var prevcbfun=win.windowRefreshFunc;win.windowRefreshFunc=cbfun;return prevcbfun},onClickRequestPointerLock:function(e){if(!Browser.pointerLock&&Module["canvas"].requestPointerLock){Module["canvas"].requestPointerLock();e.preventDefault()}},setInputMode:function(winid,mode,value){var win=GLFW.WindowFromId(winid);if(!win)return;switch(mode){case 208897:{switch(value){case 212993:{win.inputModes[mode]=value;Module["canvas"].removeEventListener("click",GLFW.onClickRequestPointerLock,true);Module["canvas"].exitPointerLock();break}case 212994:{console.log("glfwSetInputMode called with GLFW_CURSOR_HIDDEN value not implemented.");break}case 212995:{win.inputModes[mode]=value;Module["canvas"].addEventListener("click",GLFW.onClickRequestPointerLock,true);Module["canvas"].requestPointerLock();break}default:{console.log("glfwSetInputMode called with unknown value parameter value: "+value+".");break}}break}case 208898:{console.log("glfwSetInputMode called with GLFW_STICKY_KEYS mode not implemented.");break}case 208899:{console.log("glfwSetInputMode called with GLFW_STICKY_MOUSE_BUTTONS mode not implemented.");break}default:{console.log("glfwSetInputMode called with unknown mode parameter value: "+mode+".");break}}},getKey:function(winid,key){var win=GLFW.WindowFromId(winid);if(!win)return 0;return win.keys[key]},getMouseButton:function(winid,button){var win=GLFW.WindowFromId(winid);if(!win)return 0;return(win.buttons&1<<button)>0},getCursorPos:function(winid,x,y){setValue(x,Browser.mouseX,"double");setValue(y,Browser.mouseY,"double")},getMousePos:function(winid,x,y){setValue(x,Browser.mouseX,"i32");setValue(y,Browser.mouseY,"i32")},setCursorPos:function(winid,x,y){},getWindowPos:function(winid,x,y){var wx=0;var wy=0;var win=GLFW.WindowFromId(winid);if(win){wx=win.x;wy=win.y}setValue(x,wx,"i32");setValue(y,wy,"i32")},setWindowPos:function(winid,x,y){var win=GLFW.WindowFromId(winid);if(!win)return;win.x=x;win.y=y},getWindowSize:function(winid,width,height){var ww=0;var wh=0;var win=GLFW.WindowFromId(winid);if(win){ww=win.width;wh=win.height}setValue(width,ww,"i32");setValue(height,wh,"i32")},setWindowSize:function(winid,width,height){var win=GLFW.WindowFromId(winid);if(!win)return;if(GLFW.active.id==win.id){if(width==screen.width&&height==screen.height){GLFW.requestFullscreen()}else{GLFW.exitFullscreen();Browser.setCanvasSize(width,height);win.width=width;win.height=height}}if(!win.windowSizeFunc)return;dynCall_viii(win.windowSizeFunc,win.id,width,height)},createWindow:function(width,height,title,monitor,share){var i,id;for(i=0;i<GLFW.windows.length&&GLFW.windows[i]!==null;i++);if(i>0)throw"glfwCreateWindow only supports one window at time currently";id=i+1;if(width<=0||height<=0)return 0;if(monitor){GLFW.requestFullscreen()}else{Browser.setCanvasSize(width,height)}for(i=0;i<GLFW.windows.length&&GLFW.windows[i]==null;i++);if(i==GLFW.windows.length){var contextAttributes={antialias:GLFW.hints[135181]>1,depth:GLFW.hints[135173]>0,stencil:GLFW.hints[135174]>0,alpha:GLFW.hints[135172]>0};Module.ctx=Browser.createContext(Module["canvas"],true,true,contextAttributes)}if(!Module.ctx)return 0;var win=new GLFW.Window(id,width,height,title,monitor,share);if(id-1==GLFW.windows.length){GLFW.windows.push(win)}else{GLFW.windows[id-1]=win}GLFW.active=win;return win.id},destroyWindow:function(winid){var win=GLFW.WindowFromId(winid);if(!win)return;if(win.windowCloseFunc)dynCall_vi(win.windowCloseFunc,win.id);GLFW.windows[win.id-1]=null;if(GLFW.active.id==win.id)GLFW.active=null;for(var i=0;i<GLFW.windows.length;i++)if(GLFW.windows[i]!==null)return;Module.ctx=Browser.destroyContext(Module["canvas"],true,true)},swapBuffers:function(winid){},GLFW2ParamToGLFW3Param:function(param){var table={196609:0,196610:0,196611:0,196612:0,196613:0,196614:0,131073:0,131074:0,131075:0,131076:0,131077:135169,131078:135170,131079:135171,131080:135172,131081:135173,131082:135174,131083:135183,131084:135175,131085:135176,131086:135177,131087:135178,131088:135179,131089:135180,131090:0,131091:135181,131092:139266,131093:139267,131094:139270,131095:139271,131096:139272};return table[param]}};function _glfwCreateWindow(width,height,title,monitor,share){return GLFW.createWindow(width,height,title,monitor,share)}function _glfwDefaultWindowHints(){GLFW.hints=GLFW.defaultHints}function _glfwDestroyWindow(winid){return GLFW.destroyWindow(winid)}function _glfwGetCursorPos(winid,x,y){GLFW.getCursorPos(winid,x,y)}function _glfwGetKey(winid,key){return GLFW.getKey(winid,key)}function _glfwGetMouseButton(winid,button){return GLFW.getMouseButton(winid,button)}function _glfwGetPrimaryMonitor(){return 1}function _glfwGetTime(){return GLFW.getTime()-GLFW.initialTime}function _glfwGetVideoModes(monitor,count){setValue(count,0,"i32");return 0}function _glfwInit(){if(GLFW.windows)return 1;GLFW.initialTime=GLFW.getTime();GLFW.hints=GLFW.defaultHints;GLFW.windows=new Array;GLFW.active=null;window.addEventListener("gamepadconnected",GLFW.onGamepadConnected,true);window.addEventListener("gamepaddisconnected",GLFW.onGamepadDisconnected,true);window.addEventListener("keydown",GLFW.onKeydown,true);window.addEventListener("keypress",GLFW.onKeyPress,true);window.addEventListener("keyup",GLFW.onKeyup,true);window.addEventListener("blur",GLFW.onBlur,true);Module["canvas"].addEventListener("mousemove",GLFW.onMousemove,true);Module["canvas"].addEventListener("mousedown",GLFW.onMouseButtonDown,true);Module["canvas"].addEventListener("mouseup",GLFW.onMouseButtonUp,true);Module["canvas"].addEventListener("wheel",GLFW.onMouseWheel,true);Module["canvas"].addEventListener("mousewheel",GLFW.onMouseWheel,true);Module["canvas"].addEventListener("mouseenter",GLFW.onMouseenter,true);Module["canvas"].addEventListener("mouseleave",GLFW.onMouseleave,true);Module["canvas"].addEventListener("drop",GLFW.onDrop,true);Module["canvas"].addEventListener("dragover",GLFW.onDragover,true);Browser.resizeListeners.push(function(width,height){GLFW.onCanvasResize(width,height)});return 1}function _glfwMakeContextCurrent(winid){}function _glfwSetCharCallback(winid,cbfun){return GLFW.setCharCallback(winid,cbfun)}function _glfwSetCursorEnterCallback(winid,cbfun){var win=GLFW.WindowFromId(winid);if(!win)return null;var prevcbfun=win.cursorEnterFunc;win.cursorEnterFunc=cbfun;return prevcbfun}function _glfwSetCursorPosCallback(winid,cbfun){return GLFW.setCursorPosCallback(winid,cbfun)}function _glfwSetDropCallback(winid,cbfun){return GLFW.setDropCallback(winid,cbfun)}function _glfwSetErrorCallback(cbfun){var prevcbfun=GLFW.errorFunc;GLFW.errorFunc=cbfun;return prevcbfun}function _glfwSetKeyCallback(winid,cbfun){return GLFW.setKeyCallback(winid,cbfun)}function _glfwSetMouseButtonCallback(winid,cbfun){return GLFW.setMouseButtonCallback(winid,cbfun)}function _glfwSetScrollCallback(winid,cbfun){return GLFW.setScrollCallback(winid,cbfun)}function _glfwSetWindowIconifyCallback(winid,cbfun){var win=GLFW.WindowFromId(winid);if(!win)return null;var prevcbfun=win.windowIconifyFunc;win.windowIconifyFunc=cbfun;return prevcbfun}function _glfwSetWindowShouldClose(winid,value){var win=GLFW.WindowFromId(winid);if(!win)return;win.shouldClose=value}function _glfwSetWindowSizeCallback(winid,cbfun){return GLFW.setWindowSizeCallback(winid,cbfun)}function _glfwSwapBuffers(winid){GLFW.swapBuffers(winid)}function _glfwSwapInterval(interval){interval=Math.abs(interval);if(interval==0)_emscripten_set_main_loop_timing(0,0);else _emscripten_set_main_loop_timing(1,interval)}function _glfwTerminate(){window.removeEventListener("gamepadconnected",GLFW.onGamepadConnected,true);window.removeEventListener("gamepaddisconnected",GLFW.onGamepadDisconnected,true);window.removeEventListener("keydown",GLFW.onKeydown,true);window.removeEventListener("keypress",GLFW.onKeyPress,true);window.removeEventListener("keyup",GLFW.onKeyup,true);window.removeEventListener("blur",GLFW.onBlur,true);Module["canvas"].removeEventListener("mousemove",GLFW.onMousemove,true);Module["canvas"].removeEventListener("mousedown",GLFW.onMouseButtonDown,true);Module["canvas"].removeEventListener("mouseup",GLFW.onMouseButtonUp,true);Module["canvas"].removeEventListener("wheel",GLFW.onMouseWheel,true);Module["canvas"].removeEventListener("mousewheel",GLFW.onMouseWheel,true);Module["canvas"].removeEventListener("mouseenter",GLFW.onMouseenter,true);Module["canvas"].removeEventListener("mouseleave",GLFW.onMouseleave,true);Module["canvas"].removeEventListener("drop",GLFW.onDrop,true);Module["canvas"].removeEventListener("dragover",GLFW.onDragover,true);Module["canvas"].width=Module["canvas"].height=1;GLFW.windows=null;GLFW.active=null}function _glfwWindowHint(target,hint){GLFW.hints[target]=hint}function _llvm_stackrestore(p){var self=_llvm_stacksave;var ret=self.LLVM_SAVEDSTACKS[p];self.LLVM_SAVEDSTACKS.splice(p,1);stackRestore(ret)}function _llvm_stacksave(){var self=_llvm_stacksave;if(!self.LLVM_SAVEDSTACKS){self.LLVM_SAVEDSTACKS=[]}self.LLVM_SAVEDSTACKS.push(stackSave());return self.LLVM_SAVEDSTACKS.length-1}function _emscripten_memcpy_big(dest,src,num){HEAPU8.set(HEAPU8.subarray(src,src+num),dest)}function _usleep(useconds){var msec=useconds/1e3;if((ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&self["performance"]&&self["performance"]["now"]){var start=self["performance"]["now"]();while(self["performance"]["now"]()-start<msec){}}else{var start=Date.now();while(Date.now()-start<msec){}}return 0}function _nanosleep(rqtp,rmtp){if(rqtp===0){___setErrNo(22);return-1}var seconds=HEAP32[rqtp>>2];var nanoseconds=HEAP32[rqtp+4>>2];if(nanoseconds<0||nanoseconds>999999999||seconds<0){___setErrNo(22);return-1}if(rmtp!==0){HEAP32[rmtp>>2]=0;HEAP32[rmtp+4>>2]=0}return _usleep(seconds*1e6+nanoseconds/1e3)}function abortOnCannotGrowMemory(requestedSize){abort("OOM")}function _emscripten_resize_heap(requestedSize){abortOnCannotGrowMemory(requestedSize)}function _time(ptr){var ret=Date.now()/1e3|0;if(ptr){HEAP32[ptr>>2]=ret}return ret}FS.staticInit();Module["FS_createFolder"]=FS.createFolder;Module["FS_createPath"]=FS.createPath;Module["FS_createDataFile"]=FS.createDataFile;Module["FS_createPreloadedFile"]=FS.createPreloadedFile;Module["FS_createLazyFile"]=FS.createLazyFile;Module["FS_createLink"]=FS.createLink;Module["FS_createDevice"]=FS.createDevice;Module["FS_unlink"]=FS.unlink;if(ENVIRONMENT_HAS_NODE){var fs=require("fs");var NODEJS_PATH=require("path");NODEFS.staticInit()}Module["requestFullScreen"]=function Module_requestFullScreen(lockPointer,resizeCanvas,vrDevice){err("Module.requestFullScreen is deprecated. Please call Module.requestFullscreen instead.");Module["requestFullScreen"]=Module["requestFullscreen"];Browser.requestFullScreen(lockPointer,resizeCanvas,vrDevice)};Module["requestFullscreen"]=function Module_requestFullscreen(lockPointer,resizeCanvas,vrDevice){Browser.requestFullscreen(lockPointer,resizeCanvas,vrDevice)};Module["requestAnimationFrame"]=function Module_requestAnimationFrame(func){Browser.requestAnimationFrame(func)};Module["setCanvasSize"]=function Module_setCanvasSize(width,height,noUpdates){Browser.setCanvasSize(width,height,noUpdates)};Module["pauseMainLoop"]=function Module_pauseMainLoop(){Browser.mainLoop.pause()};Module["resumeMainLoop"]=function Module_resumeMainLoop(){Browser.mainLoop.resume()};Module["getUserMedia"]=function Module_getUserMedia(){Browser.getUserMedia()};Module["createContext"]=function Module_createContext(canvas,useWebGL,setInModule,webGLContextAttributes){return Browser.createContext(canvas,useWebGL,setInModule,webGLContextAttributes)};if(ENVIRONMENT_IS_NODE){_emscripten_get_now=function _emscripten_get_now_actual(){var t=process["hrtime"]();return t[0]*1e3+t[1]/1e6}}else if(typeof dateNow!=="undefined"){_emscripten_get_now=dateNow}else if(typeof performance==="object"&&performance&&typeof performance["now"]==="function"){_emscripten_get_now=function(){return performance["now"]()}}else{_emscripten_get_now=Date.now}var GLctx;GL.init();for(var i=0;i<32;i++)__tempFixedLengthArray.push(new Array(i));function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}var asmGlobalArg={};var asmLibraryArg={"d":abort,"b":___assert_fail,"sc":___lock,"D":___setErrNo,"gb":___syscall140,"Xa":___syscall145,"q":___syscall221,"Ca":___syscall5,"ra":___syscall54,"C":___syscall6,"B":___unlock,"be":___wasi_fd_write,"A":_eglGetProcAddress,"Y":_emscripten_exit_pointerlock,"yd":_emscripten_get_element_css_size,"nd":_emscripten_get_gamepad_status,"cd":_emscripten_get_heap_size,"Tc":_emscripten_get_num_gamepads,"X":_emscripten_get_pointerlock_status,"zc":_emscripten_glActiveTexture,"rc":_emscripten_glAttachShader,"lc":_emscripten_glBeginQueryEXT,"hc":_emscripten_glBindAttribLocation,"cc":_emscripten_glBindBuffer,"Xb":_emscripten_glBindFramebuffer,"Tb":_emscripten_glBindRenderbuffer,"Lb":_emscripten_glBindTexture,"Ab":_emscripten_glBindVertexArrayOES,"tb":_emscripten_glBlendColor,"rb":_emscripten_glBlendEquation,"qb":_emscripten_glBlendEquationSeparate,"pb":_emscripten_glBlendFunc,"ob":_emscripten_glBlendFuncSeparate,"nb":_emscripten_glBufferData,"mb":_emscripten_glBufferSubData,"lb":_emscripten_glCheckFramebufferStatus,"kb":_emscripten_glClear,"jb":_emscripten_glClearColor,"ib":_emscripten_glClearDepthf,"hb":_emscripten_glClearStencil,"fb":_emscripten_glColorMask,"eb":_emscripten_glCompileShader,"db":_emscripten_glCompressedTexImage2D,"cb":_emscripten_glCompressedTexSubImage2D,"bb":_emscripten_glCopyTexImage2D,"ab":_emscripten_glCopyTexSubImage2D,"$a":_emscripten_glCreateProgram,"_a":_emscripten_glCreateShader,"Za":_emscripten_glCullFace,"Ya":_emscripten_glDeleteBuffers,"Wa":_emscripten_glDeleteFramebuffers,"Va":_emscripten_glDeleteProgram,"Ua":_emscripten_glDeleteQueriesEXT,"Ta":_emscripten_glDeleteRenderbuffers,"Sa":_emscripten_glDeleteShader,"Ra":_emscripten_glDeleteTextures,"Qa":_emscripten_glDeleteVertexArraysOES,"Pa":_emscripten_glDepthFunc,"Oa":_emscripten_glDepthMask,"Na":_emscripten_glDepthRangef,"Ma":_emscripten_glDetachShader,"La":_emscripten_glDisable,"Ka":_emscripten_glDisableVertexAttribArray,"Ja":_emscripten_glDrawArrays,"Ia":_emscripten_glDrawArraysInstancedANGLE,"Ha":_emscripten_glDrawBuffersWEBGL,"Ga":_emscripten_glDrawElements,"Fa":_emscripten_glDrawElementsInstancedANGLE,"Ea":_emscripten_glEnable,"Da":_emscripten_glEnableVertexAttribArray,"Ba":_emscripten_glEndQueryEXT,"Aa":_emscripten_glFinish,"za":_emscripten_glFlush,"ya":_emscripten_glFramebufferRenderbuffer,"xa":_emscripten_glFramebufferTexture2D,"wa":_emscripten_glFrontFace,"va":_emscripten_glGenBuffers,"ua":_emscripten_glGenFramebuffers,"ta":_emscripten_glGenQueriesEXT,"sa":_emscripten_glGenRenderbuffers,"qa":_emscripten_glGenTextures,"pa":_emscripten_glGenVertexArraysOES,"oa":_emscripten_glGenerateMipmap,"na":_emscripten_glGetActiveAttrib,"ma":_emscripten_glGetActiveUniform,"la":_emscripten_glGetAttachedShaders,"ka":_emscripten_glGetAttribLocation,"ja":_emscripten_glGetBooleanv,"ia":_emscripten_glGetBufferParameteriv,"ha":_emscripten_glGetError,"ga":_emscripten_glGetFloatv,"fa":_emscripten_glGetFramebufferAttachmentParameteriv,"ea":_emscripten_glGetIntegerv,"da":_emscripten_glGetProgramInfoLog,"ca":_emscripten_glGetProgramiv,"ba":_emscripten_glGetQueryObjecti64vEXT,"aa":_emscripten_glGetQueryObjectivEXT,"$":_emscripten_glGetQueryObjectui64vEXT,"_":_emscripten_glGetQueryObjectuivEXT,"Z":_emscripten_glGetQueryivEXT,"le":_emscripten_glGetRenderbufferParameteriv,"ke":_emscripten_glGetShaderInfoLog,"je":_emscripten_glGetShaderPrecisionFormat,"ie":_emscripten_glGetShaderSource,"he":_emscripten_glGetShaderiv,"ge":_emscripten_glGetString,"fe":_emscripten_glGetTexParameterfv,"ee":_emscripten_glGetTexParameteriv,"de":_emscripten_glGetUniformLocation,"ce":_emscripten_glGetUniformfv,"ae":_emscripten_glGetUniformiv,"$d":_emscripten_glGetVertexAttribPointerv,"_d":_emscripten_glGetVertexAttribfv,"Zd":_emscripten_glGetVertexAttribiv,"Yd":_emscripten_glHint,"Xd":_emscripten_glIsBuffer,"Wd":_emscripten_glIsEnabled,"Vd":_emscripten_glIsFramebuffer,"Ud":_emscripten_glIsProgram,"Td":_emscripten_glIsQueryEXT,"Sd":_emscripten_glIsRenderbuffer,"Rd":_emscripten_glIsShader,"Qd":_emscripten_glIsTexture,"Pd":_emscripten_glIsVertexArrayOES,"Od":_emscripten_glLineWidth,"Nd":_emscripten_glLinkProgram,"Md":_emscripten_glPixelStorei,"Ld":_emscripten_glPolygonOffset,"Kd":_emscripten_glQueryCounterEXT,"Jd":_emscripten_glReadPixels,"Id":_emscripten_glReleaseShaderCompiler,"Hd":_emscripten_glRenderbufferStorage,"Gd":_emscripten_glSampleCoverage,"Fd":_emscripten_glScissor,"Ed":_emscripten_glShaderBinary,"Dd":_emscripten_glShaderSource,"Cd":_emscripten_glStencilFunc,"Bd":_emscripten_glStencilFuncSeparate,"Ad":_emscripten_glStencilMask,"zd":_emscripten_glStencilMaskSeparate,"xd":_emscripten_glStencilOp,"wd":_emscripten_glStencilOpSeparate,"vd":_emscripten_glTexImage2D,"ud":_emscripten_glTexParameterf,"td":_emscripten_glTexParameterfv,"sd":_emscripten_glTexParameteri,"rd":_emscripten_glTexParameteriv,"qd":_emscripten_glTexSubImage2D,"pd":_emscripten_glUniform1f,"od":_emscripten_glUniform1fv,"md":_emscripten_glUniform1i,"ld":_emscripten_glUniform1iv,"kd":_emscripten_glUniform2f,"jd":_emscripten_glUniform2fv,"id":_emscripten_glUniform2i,"hd":_emscripten_glUniform2iv,"gd":_emscripten_glUniform3f,"fd":_emscripten_glUniform3fv,"ed":_emscripten_glUniform3i,"dd":_emscripten_glUniform3iv,"bd":_emscripten_glUniform4f,"ad":_emscripten_glUniform4fv,"$c":_emscripten_glUniform4i,"_c":_emscripten_glUniform4iv,"Zc":_emscripten_glUniformMatrix2fv,"Yc":_emscripten_glUniformMatrix3fv,"Xc":_emscripten_glUniformMatrix4fv,"Wc":_emscripten_glUseProgram,"Vc":_emscripten_glValidateProgram,"Uc":_emscripten_glVertexAttrib1f,"Sc":_emscripten_glVertexAttrib1fv,"Rc":_emscripten_glVertexAttrib2f,"Qc":_emscripten_glVertexAttrib2fv,"Pc":_emscripten_glVertexAttrib3f,"Oc":_emscripten_glVertexAttrib3fv,"Nc":_emscripten_glVertexAttrib4f,"Mc":_emscripten_glVertexAttrib4fv,"Lc":_emscripten_glVertexAttribDivisorANGLE,"Kc":_emscripten_glVertexAttribPointer,"Jc":_emscripten_glViewport,"Ic":_emscripten_memcpy_big,"Hc":_emscripten_request_pointerlock,"Gc":_emscripten_resize_heap,"W":_emscripten_run_script,"Fc":_emscripten_sample_gamepad_data,"Ec":_emscripten_set_click_callback_on_thread,"Dc":_emscripten_set_fullscreenchange_callback_on_thread,"Cc":_emscripten_set_gamepadconnected_callback_on_thread,"Bc":_emscripten_set_gamepaddisconnected_callback_on_thread,"Ac":_emscripten_set_keypress_callback_on_thread,"yc":_emscripten_set_main_loop,"xc":_emscripten_set_touchcancel_callback_on_thread,"wc":_emscripten_set_touchend_callback_on_thread,"vc":_emscripten_set_touchmove_callback_on_thread,"uc":_emscripten_set_touchstart_callback_on_thread,"tc":_exit,"z":_glActiveTexture,"V":_glAttachShader,"n":_glBindAttribLocation,"c":_glBindBuffer,"k":_glBindTexture,"qc":_glBlendFunc,"i":_glBufferData,"y":_glBufferSubData,"U":_glClear,"T":_glClearColor,"pc":_glClearDepthf,"oc":_glCompileShader,"nc":_glCompressedTexImage2D,"mc":_glCreateProgram,"kc":_glCreateShader,"jc":_glCullFace,"p":_glDeleteBuffers,"S":_glDeleteProgram,"R":_glDeleteShader,"Q":_glDeleteTextures,"ic":_glDepthFunc,"P":_glDetachShader,"O":_glDisable,"j":_glDisableVertexAttribArray,"N":_glDrawArrays,"M":_glDrawElements,"x":_glEnable,"f":_glEnableVertexAttribArray,"gc":_glFrontFace,"h":_glGenBuffers,"fc":_glGenTextures,"w":_glGetAttribLocation,"ec":_glGetFloatv,"dc":_glGetProgramInfoLog,"L":_glGetProgramiv,"bc":_glGetShaderInfoLog,"K":_glGetShaderiv,"o":_glGetString,"v":_glGetUniformLocation,"ac":_glLinkProgram,"$b":_glPixelStorei,"_b":_glReadPixels,"Zb":_glShaderSource,"Yb":_glTexImage2D,"m":_glTexParameteri,"J":_glUniform1i,"u":_glUniform4f,"t":_glUniformMatrix4fv,"l":_glUseProgram,"Wb":_glVertexAttrib2f,"Vb":_glVertexAttrib3f,"s":_glVertexAttrib4f,"e":_glVertexAttribPointer,"Ub":_glViewport,"I":_glfwCreateWindow,"Sb":_glfwDefaultWindowHints,"Rb":_glfwDestroyWindow,"Qb":_glfwGetCursorPos,"Pb":_glfwGetKey,"Ob":_glfwGetMouseButton,"H":_glfwGetPrimaryMonitor,"r":_glfwGetTime,"Nb":_glfwGetVideoModes,"Mb":_glfwInit,"Kb":_glfwMakeContextCurrent,"Jb":_glfwSetCharCallback,"Ib":_glfwSetCursorEnterCallback,"Hb":_glfwSetCursorPosCallback,"Gb":_glfwSetDropCallback,"Fb":_glfwSetErrorCallback,"Eb":_glfwSetKeyCallback,"Db":_glfwSetMouseButtonCallback,"Cb":_glfwSetScrollCallback,"Bb":_glfwSetWindowIconifyCallback,"zb":_glfwSetWindowShouldClose,"yb":_glfwSetWindowSizeCallback,"xb":_glfwSwapBuffers,"wb":_glfwSwapInterval,"G":_glfwTerminate,"g":_glfwWindowHint,"F":_llvm_stackrestore,"E":_llvm_stacksave,"vb":_nanosleep,"ub":_time,"sb":abortOnCannotGrowMemory,"a":DYNAMICTOP_PTR};var asm=Module["asm"](asmGlobalArg,asmLibraryArg,buffer);Module["asm"]=asm;var ___errno_location=Module["___errno_location"]=function(){return Module["asm"]["me"].apply(null,arguments)};var _emscripten_GetProcAddress=Module["_emscripten_GetProcAddress"]=function(){return Module["asm"]["ne"].apply(null,arguments)};var _free=Module["_free"]=function(){return Module["asm"]["oe"].apply(null,arguments)};var _ma_device_process_pcm_frames_capture__webaudio=Module["_ma_device_process_pcm_frames_capture__webaudio"]=function(){return Module["asm"]["pe"].apply(null,arguments)};var _ma_device_process_pcm_frames_playback__webaudio=Module["_ma_device_process_pcm_frames_playback__webaudio"]=function(){return Module["asm"]["qe"].apply(null,arguments)};var _main=Module["_main"]=function(){return Module["asm"]["re"].apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return Module["asm"]["se"].apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){return Module["asm"]["Be"].apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){return Module["asm"]["Ce"].apply(null,arguments)};var stackSave=Module["stackSave"]=function(){return Module["asm"]["De"].apply(null,arguments)};var dynCall_iiii=Module["dynCall_iiii"]=function(){return Module["asm"]["te"].apply(null,arguments)};var dynCall_v=Module["dynCall_v"]=function(){return Module["asm"]["ue"].apply(null,arguments)};var dynCall_vi=Module["dynCall_vi"]=function(){return Module["asm"]["ve"].apply(null,arguments)};var dynCall_vidd=Module["dynCall_vidd"]=function(){return Module["asm"]["we"].apply(null,arguments)};var dynCall_vii=Module["dynCall_vii"]=function(){return Module["asm"]["xe"].apply(null,arguments)};var dynCall_viii=Module["dynCall_viii"]=function(){return Module["asm"]["ye"].apply(null,arguments)};var dynCall_viiii=Module["dynCall_viiii"]=function(){return Module["asm"]["ze"].apply(null,arguments)};var dynCall_viiiii=Module["dynCall_viiiii"]=function(){return Module["asm"]["Ae"].apply(null,arguments)};Module["asm"]=asm;Module["getMemory"]=getMemory;Module["addRunDependency"]=addRunDependency;Module["removeRunDependency"]=removeRunDependency;Module["FS_createFolder"]=FS.createFolder;Module["FS_createPath"]=FS.createPath;Module["FS_createDataFile"]=FS.createDataFile;Module["FS_createPreloadedFile"]=FS.createPreloadedFile;Module["FS_createLazyFile"]=FS.createLazyFile;Module["FS_createLink"]=FS.createLink;Module["FS_createDevice"]=FS.createDevice;Module["FS_unlink"]=FS.unlink;Module["calledRun"]=calledRun;var calledRun;function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}var calledMain=false;dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function callMain(args){args=args||[];var argc=args.length+1;var argv=stackAlloc((argc+1)*4);HEAP32[argv>>2]=allocateUTF8OnStack(thisProgram);for(var i=1;i<argc;i++){HEAP32[(argv>>2)+i]=allocateUTF8OnStack(args[i-1])}HEAP32[(argv>>2)+argc]=0;try{var ret=Module["_main"](argc,argv);exit(ret,true)}catch(e){if(e instanceof ExitStatus){return}else if(e=="SimulateInfiniteLoop"){noExitRuntime=true;return}else{var toLog=e;if(e&&typeof e==="object"&&e.stack){toLog=[e,e.stack]}err("exception thrown: "+toLog);quit_(1,e)}}finally{calledMain=true}}function run(args){args=args||arguments_;if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();if(shouldRunNow)callMain(args);postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}Module["run"]=run;function exit(status,implicit){if(implicit&&noExitRuntime&&status===0){return}if(noExitRuntime){}else{ABORT=true;EXITSTATUS=status;exitRuntime();if(Module["onExit"])Module["onExit"](status)}quit_(status,new ExitStatus(status))}function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what+="";out(what);err(what);ABORT=true;EXITSTATUS=1;throw"abort("+what+"). Build with -s ASSERTIONS=1 for more info."}Module["abort"]=abort;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}var shouldRunNow=true;if(Module["noInitialRun"])shouldRunNow=false;noExitRuntime=true;run();
+
+
+// The Module object: Our interface to the outside world. We import
+// and export values on it. There are various ways Module can be used:
+// 1. Not defined. We create it here
+// 2. A function parameter, function(Module) { ..generated code.. }
+// 3. pre-run appended it, var Module = {}; ..generated code..
+// 4. External script tag defines var Module.
+// We need to check if Module already exists (e.g. case 3 above).
+// Substitution will be replaced with actual code on later stage of the build,
+// this way Closure Compiler will not mangle it (e.g. case 4. above).
+// Note that if you want to run closure, and also to use Module
+// after the generated code, you will need to define var Module = {};
+// before the code. Then that object will be used in the code, and you
+// can continue to use Module afterwards as well.
+var Module = typeof Module !== 'undefined' ? Module : {};
+
+
+
+// --pre-jses are emitted after the Module integration code, so that they can
+// refer to Module (if they choose; they can also define Module)
+
+ if (!Module.expectedDataFileDownloads) {
+ Module.expectedDataFileDownloads = 0;
+ }
+ Module.expectedDataFileDownloads++;
+ (function() {
+ var loadPackage = function(metadata) {
+
+ var PACKAGE_PATH;
+ if (typeof window === 'object') {
+ PACKAGE_PATH = window['encodeURIComponent'](window.location.pathname.toString().substring(0, window.location.pathname.toString().lastIndexOf('/')) + '/');
+ } else if (typeof location !== 'undefined') {
+ // worker
+ PACKAGE_PATH = encodeURIComponent(location.pathname.toString().substring(0, location.pathname.toString().lastIndexOf('/')) + '/');
+ } else {
+ throw 'using preloaded data can only be done on a web page or in a web worker';
+ }
+ var PACKAGE_NAME = 'models/models_first_person_maze.data';
+ var REMOTE_PACKAGE_BASE = 'models_first_person_maze.data';
+ if (typeof Module['locateFilePackage'] === 'function' && !Module['locateFile']) {
+ Module['locateFile'] = Module['locateFilePackage'];
+ err('warning: you defined Module.locateFilePackage, that has been renamed to Module.locateFile (using your locateFilePackage for now)');
+ }
+ var REMOTE_PACKAGE_NAME = Module['locateFile'] ? Module['locateFile'](REMOTE_PACKAGE_BASE, '') : REMOTE_PACKAGE_BASE;
+
+ var REMOTE_PACKAGE_SIZE = metadata['remote_package_size'];
+ var PACKAGE_UUID = metadata['package_uuid'];
+
+ function fetchRemotePackage(packageName, packageSize, callback, errback) {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', packageName, true);
+ xhr.responseType = 'arraybuffer';
+ xhr.onprogress = function(event) {
+ var url = packageName;
+ var size = packageSize;
+ if (event.total) size = event.total;
+ if (event.loaded) {
+ if (!xhr.addedTotal) {
+ xhr.addedTotal = true;
+ if (!Module.dataFileDownloads) Module.dataFileDownloads = {};
+ Module.dataFileDownloads[url] = {
+ loaded: event.loaded,
+ total: size
+ };
+ } else {
+ Module.dataFileDownloads[url].loaded = event.loaded;
+ }
+ var total = 0;
+ var loaded = 0;
+ var num = 0;
+ for (var download in Module.dataFileDownloads) {
+ var data = Module.dataFileDownloads[download];
+ total += data.total;
+ loaded += data.loaded;
+ num++;
+ }
+ total = Math.ceil(total * Module.expectedDataFileDownloads/num);
+ if (Module['setStatus']) Module['setStatus']('Downloading data... (' + loaded + '/' + total + ')');
+ } else if (!Module.dataFileDownloads) {
+ if (Module['setStatus']) Module['setStatus']('Downloading data...');
+ }
+ };
+ xhr.onerror = function(event) {
+ throw new Error("NetworkError for: " + packageName);
+ }
+ xhr.onload = function(event) {
+ if (xhr.status == 200 || xhr.status == 304 || xhr.status == 206 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0
+ var packageData = xhr.response;
+ callback(packageData);
+ } else {
+ throw new Error(xhr.statusText + " : " + xhr.responseURL);
+ }
+ };
+ xhr.send(null);
+ };
+
+ function handleError(error) {
+ console.error('package error:', error);
+ };
+
+ var fetchedCallback = null;
+ var fetched = Module['getPreloadedPackage'] ? Module['getPreloadedPackage'](REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE) : null;
+
+ if (!fetched) fetchRemotePackage(REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE, function(data) {
+ if (fetchedCallback) {
+ fetchedCallback(data);
+ fetchedCallback = null;
+ } else {
+ fetched = data;
+ }
+ }, handleError);
+
+ function runWithFS() {
+
+ function assert(check, msg) {
+ if (!check) throw msg + new Error().stack;
+ }
+ Module['FS_createPath']('/', 'resources', true, true);
+
+ /** @constructor */
+ function DataRequest(start, end, audio) {
+ this.start = start;
+ this.end = end;
+ this.audio = audio;
+ }
+ DataRequest.prototype = {
+ requests: {},
+ open: function(mode, name) {
+ this.name = name;
+ this.requests[name] = this;
+ Module['addRunDependency']('fp ' + this.name);
+ },
+ send: function() {},
+ onload: function() {
+ var byteArray = this.byteArray.subarray(this.start, this.end);
+ this.finish(byteArray);
+ },
+ finish: function(byteArray) {
+ var that = this;
+
+ Module['FS_createDataFile'](this.name, null, byteArray, true, true, true); // canOwn this data in the filesystem, it is a slide into the heap that will never change
+ Module['removeRunDependency']('fp ' + that.name);
+
+ this.requests[this.name] = null;
+ }
+ };
+
+ var files = metadata['files'];
+ for (var i = 0; i < files.length; ++i) {
+ new DataRequest(files[i]['start'], files[i]['end'], files[i]['audio']).open('GET', files[i]['filename']);
+ }
+
+
+ function processPackageData(arrayBuffer) {
+ assert(arrayBuffer, 'Loading data file failed.');
+ assert(arrayBuffer instanceof ArrayBuffer, 'bad input to processPackageData');
+ var byteArray = new Uint8Array(arrayBuffer);
+ var curr;
+
+ // Reuse the bytearray from the XHR as the source for file reads.
+ DataRequest.prototype.byteArray = byteArray;
+
+ var files = metadata['files'];
+ for (var i = 0; i < files.length; ++i) {
+ DataRequest.prototype.requests[files[i].filename].onload();
+ }
+ Module['removeRunDependency']('datafile_models/models_first_person_maze.data');
+
+ };
+ Module['addRunDependency']('datafile_models/models_first_person_maze.data');
+
+ if (!Module.preloadResults) Module.preloadResults = {};
+
+ Module.preloadResults[PACKAGE_NAME] = {fromCache: false};
+ if (fetched) {
+ processPackageData(fetched);
+ fetched = null;
+ } else {
+ fetchedCallback = processPackageData;
+ }
+
+ }
+ if (Module['calledRun']) {
+ runWithFS();
+ } else {
+ if (!Module['preRun']) Module['preRun'] = [];
+ Module["preRun"].push(runWithFS); // FS is not initialized yet, wait for it
+ }
+
+ }
+ loadPackage({"files": [{"filename": "/resources/cubicmap.png", "start": 0, "end": 201, "audio": 0}, {"filename": "/resources/cubicmap_atlas.png", "start": 201, "end": 37426, "audio": 0}], "remote_package_size": 37426, "package_uuid": "41ddaf2d-de45-46a8-82a8-49135fa70e79"});
+
+ })();
+
+
+
+// Sometimes an existing Module object exists with properties
+// meant to overwrite the default module functionality. Here
+// we collect those properties and reapply _after_ we configure
+// the current environment's defaults to avoid having to be so
+// defensive during initialization.
+var moduleOverrides = {};
+var key;
+for (key in Module) {
+ if (Module.hasOwnProperty(key)) {
+ moduleOverrides[key] = Module[key];
+ }
+}
+
+var arguments_ = [];
+var thisProgram = './this.program';
+var quit_ = function(status, toThrow) {
+ throw toThrow;
+};
+
+// Determine the runtime environment we are in. You can customize this by
+// setting the ENVIRONMENT setting at compile time (see settings.js).
+
+var ENVIRONMENT_IS_WEB = false;
+var ENVIRONMENT_IS_WORKER = false;
+var ENVIRONMENT_IS_NODE = false;
+var ENVIRONMENT_IS_SHELL = false;
+ENVIRONMENT_IS_WEB = typeof window === 'object';
+ENVIRONMENT_IS_WORKER = typeof importScripts === 'function';
+// N.b. Electron.js environment is simultaneously a NODE-environment, but
+// also a web environment.
+ENVIRONMENT_IS_NODE = typeof process === 'object' && typeof process.versions === 'object' && typeof process.versions.node === 'string';
+ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER;
+
+
+
+
+// `/` should be present at the end if `scriptDirectory` is not empty
+var scriptDirectory = '';
+function locateFile(path) {
+ if (Module['locateFile']) {
+ return Module['locateFile'](path, scriptDirectory);
+ }
+ return scriptDirectory + path;
+}
+
+// Hooks that are implemented differently in different runtime environments.
+var read_,
+ readAsync,
+ readBinary,
+ setWindowTitle;
+
+var nodeFS;
+var nodePath;
+
+if (ENVIRONMENT_IS_NODE) {
+ if (ENVIRONMENT_IS_WORKER) {
+ scriptDirectory = require('path').dirname(scriptDirectory) + '/';
+ } else {
+ scriptDirectory = __dirname + '/';
+ }
+
+
+
+
+read_ = function shell_read(filename, binary) {
+ if (!nodeFS) nodeFS = require('fs');
+ if (!nodePath) nodePath = require('path');
+ filename = nodePath['normalize'](filename);
+ return nodeFS['readFileSync'](filename, binary ? null : 'utf8');
+};
+
+readBinary = function readBinary(filename) {
+ var ret = read_(filename, true);
+ if (!ret.buffer) {
+ ret = new Uint8Array(ret);
+ }
+ assert(ret.buffer);
+ return ret;
+};
+
+
+
+ if (process['argv'].length > 1) {
+ thisProgram = process['argv'][1].replace(/\\/g, '/');
+ }
+
+ arguments_ = process['argv'].slice(2);
+
+ if (typeof module !== 'undefined') {
+ module['exports'] = Module;
+ }
+
+ process['on']('uncaughtException', function(ex) {
+ // suppress ExitStatus exceptions from showing an error
+ if (!(ex instanceof ExitStatus)) {
+ throw ex;
+ }
+ });
+
+ process['on']('unhandledRejection', abort);
+
+ quit_ = function(status) {
+ process['exit'](status);
+ };
+
+ Module['inspect'] = function () { return '[Emscripten Module object]'; };
+
+
+
+} else
+if (ENVIRONMENT_IS_SHELL) {
+
+
+ if (typeof read != 'undefined') {
+ read_ = function shell_read(f) {
+ return read(f);
+ };
+ }
+
+ readBinary = function readBinary(f) {
+ var data;
+ if (typeof readbuffer === 'function') {
+ return new Uint8Array(readbuffer(f));
+ }
+ data = read(f, 'binary');
+ assert(typeof data === 'object');
+ return data;
+ };
+
+ if (typeof scriptArgs != 'undefined') {
+ arguments_ = scriptArgs;
+ } else if (typeof arguments != 'undefined') {
+ arguments_ = arguments;
+ }
+
+ if (typeof quit === 'function') {
+ quit_ = function(status) {
+ quit(status);
+ };
+ }
+
+ if (typeof print !== 'undefined') {
+ // Prefer to use print/printErr where they exist, as they usually work better.
+ if (typeof console === 'undefined') console = /** @type{!Console} */({});
+ console.log = /** @type{!function(this:Console, ...*): undefined} */ (print);
+ console.warn = console.error = /** @type{!function(this:Console, ...*): undefined} */ (typeof printErr !== 'undefined' ? printErr : print);
+ }
+
+
+} else
+
+// Note that this includes Node.js workers when relevant (pthreads is enabled).
+// Node.js workers are detected as a combination of ENVIRONMENT_IS_WORKER and
+// ENVIRONMENT_IS_NODE.
+if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
+ if (ENVIRONMENT_IS_WORKER) { // Check worker, not web, since window could be polyfilled
+ scriptDirectory = self.location.href;
+ } else if (document.currentScript) { // web
+ scriptDirectory = document.currentScript.src;
+ }
+ // blob urls look like blob:http://site.com/etc/etc and we cannot infer anything from them.
+ // otherwise, slice off the final part of the url to find the script directory.
+ // if scriptDirectory does not contain a slash, lastIndexOf will return -1,
+ // and scriptDirectory will correctly be replaced with an empty string.
+ if (scriptDirectory.indexOf('blob:') !== 0) {
+ scriptDirectory = scriptDirectory.substr(0, scriptDirectory.lastIndexOf('/')+1);
+ } else {
+ scriptDirectory = '';
+ }
+
+
+ // Differentiate the Web Worker from the Node Worker case, as reading must
+ // be done differently.
+ {
+
+
+
+
+ read_ = function shell_read(url) {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', url, false);
+ xhr.send(null);
+ return xhr.responseText;
+ };
+
+ if (ENVIRONMENT_IS_WORKER) {
+ readBinary = function readBinary(url) {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', url, false);
+ xhr.responseType = 'arraybuffer';
+ xhr.send(null);
+ return new Uint8Array(/** @type{!ArrayBuffer} */(xhr.response));
+ };
+ }
+
+ readAsync = function readAsync(url, onload, onerror) {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', url, true);
+ xhr.responseType = 'arraybuffer';
+ xhr.onload = function xhr_onload() {
+ if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0
+ onload(xhr.response);
+ return;
+ }
+ onerror();
+ };
+ xhr.onerror = onerror;
+ xhr.send(null);
+ };
+
+
+
+
+ }
+
+ setWindowTitle = function(title) { document.title = title };
+} else
+{
+}
+
+
+// Set up the out() and err() hooks, which are how we can print to stdout or
+// stderr, respectively.
+var out = Module['print'] || console.log.bind(console);
+var err = Module['printErr'] || console.warn.bind(console);
+
+// Merge back in the overrides
+for (key in moduleOverrides) {
+ if (moduleOverrides.hasOwnProperty(key)) {
+ Module[key] = moduleOverrides[key];
+ }
+}
+// Free the object hierarchy contained in the overrides, this lets the GC
+// reclaim data used e.g. in memoryInitializerRequest, which is a large typed array.
+moduleOverrides = null;
+
+// Emit code to handle expected values on the Module object. This applies Module.x
+// to the proper local x. This has two benefits: first, we only emit it if it is
+// expected to arrive, and second, by using a local everywhere else that can be
+// minified.
+if (Module['arguments']) arguments_ = Module['arguments'];
+if (Module['thisProgram']) thisProgram = Module['thisProgram'];
+if (Module['quit']) quit_ = Module['quit'];
+
+// perform assertions in shell.js after we set up out() and err(), as otherwise if an assertion fails it cannot print the message
+
+
+
+
+
+// {{PREAMBLE_ADDITIONS}}
+
+var STACK_ALIGN = 16;
+
+function alignMemory(size, factor) {
+ if (!factor) factor = STACK_ALIGN; // stack alignment (16-byte) by default
+ return Math.ceil(size / factor) * factor;
+}
+
+function getNativeTypeSize(type) {
+ switch (type) {
+ case 'i1': case 'i8': return 1;
+ case 'i16': return 2;
+ case 'i32': return 4;
+ case 'i64': return 8;
+ case 'float': return 4;
+ case 'double': return 8;
+ default: {
+ if (type[type.length-1] === '*') {
+ return 4; // A pointer
+ } else if (type[0] === 'i') {
+ var bits = Number(type.substr(1));
+ assert(bits % 8 === 0, 'getNativeTypeSize invalid bits ' + bits + ', type ' + type);
+ return bits / 8;
+ } else {
+ return 0;
+ }
+ }
+ }
+}
+
+function warnOnce(text) {
+ if (!warnOnce.shown) warnOnce.shown = {};
+ if (!warnOnce.shown[text]) {
+ warnOnce.shown[text] = 1;
+ err(text);
+ }
+}
+
+
+
+
+
+// Wraps a JS function as a wasm function with a given signature.
+function convertJsFunctionToWasm(func, sig) {
+
+ // If the type reflection proposal is available, use the new
+ // "WebAssembly.Function" constructor.
+ // Otherwise, construct a minimal wasm module importing the JS function and
+ // re-exporting it.
+ if (typeof WebAssembly.Function === "function") {
+ var typeNames = {
+ 'i': 'i32',
+ 'j': 'i64',
+ 'f': 'f32',
+ 'd': 'f64'
+ };
+ var type = {
+ parameters: [],
+ results: sig[0] == 'v' ? [] : [typeNames[sig[0]]]
+ };
+ for (var i = 1; i < sig.length; ++i) {
+ type.parameters.push(typeNames[sig[i]]);
+ }
+ return new WebAssembly.Function(type, func);
+ }
+
+ // The module is static, with the exception of the type section, which is
+ // generated based on the signature passed in.
+ var typeSection = [
+ 0x01, // id: section,
+ 0x00, // length: 0 (placeholder)
+ 0x01, // count: 1
+ 0x60, // form: func
+ ];
+ var sigRet = sig.slice(0, 1);
+ var sigParam = sig.slice(1);
+ var typeCodes = {
+ 'i': 0x7f, // i32
+ 'j': 0x7e, // i64
+ 'f': 0x7d, // f32
+ 'd': 0x7c, // f64
+ };
+
+ // Parameters, length + signatures
+ typeSection.push(sigParam.length);
+ for (var i = 0; i < sigParam.length; ++i) {
+ typeSection.push(typeCodes[sigParam[i]]);
+ }
+
+ // Return values, length + signatures
+ // With no multi-return in MVP, either 0 (void) or 1 (anything else)
+ if (sigRet == 'v') {
+ typeSection.push(0x00);
+ } else {
+ typeSection = typeSection.concat([0x01, typeCodes[sigRet]]);
+ }
+
+ // Write the overall length of the type section back into the section header
+ // (excepting the 2 bytes for the section id and length)
+ typeSection[1] = typeSection.length - 2;
+
+ // Rest of the module is static
+ var bytes = new Uint8Array([
+ 0x00, 0x61, 0x73, 0x6d, // magic ("\0asm")
+ 0x01, 0x00, 0x00, 0x00, // version: 1
+ ].concat(typeSection, [
+ 0x02, 0x07, // import section
+ // (import "e" "f" (func 0 (type 0)))
+ 0x01, 0x01, 0x65, 0x01, 0x66, 0x00, 0x00,
+ 0x07, 0x05, // export section
+ // (export "f" (func 0 (type 0)))
+ 0x01, 0x01, 0x66, 0x00, 0x00,
+ ]));
+
+ // We can compile this wasm module synchronously because it is very small.
+ // This accepts an import (at "e.f"), that it reroutes to an export (at "f")
+ var module = new WebAssembly.Module(bytes);
+ var instance = new WebAssembly.Instance(module, {
+ 'e': {
+ 'f': func
+ }
+ });
+ var wrappedFunc = instance.exports['f'];
+ return wrappedFunc;
+}
+
+var freeTableIndexes = [];
+
+// Weak map of functions in the table to their indexes, created on first use.
+var functionsInTableMap;
+
+// Add a wasm function to the table.
+function addFunctionWasm(func, sig) {
+ var table = wasmTable;
+
+ // Check if the function is already in the table, to ensure each function
+ // gets a unique index. First, create the map if this is the first use.
+ if (!functionsInTableMap) {
+ functionsInTableMap = new WeakMap();
+ for (var i = 0; i < table.length; i++) {
+ var item = table.get(i);
+ // Ignore null values.
+ if (item) {
+ functionsInTableMap.set(item, i);
+ }
+ }
+ }
+ if (functionsInTableMap.has(func)) {
+ return functionsInTableMap.get(func);
+ }
+
+ // It's not in the table, add it now.
+
+
+ var ret;
+ // Reuse a free index if there is one, otherwise grow.
+ if (freeTableIndexes.length) {
+ ret = freeTableIndexes.pop();
+ } else {
+ ret = table.length;
+ // Grow the table
+ try {
+ table.grow(1);
+ } catch (err) {
+ if (!(err instanceof RangeError)) {
+ throw err;
+ }
+ throw 'Unable to grow wasm table. Set ALLOW_TABLE_GROWTH.';
+ }
+ }
+
+ // Set the new value.
+ try {
+ // Attempting to call this with JS function will cause of table.set() to fail
+ table.set(ret, func);
+ } catch (err) {
+ if (!(err instanceof TypeError)) {
+ throw err;
+ }
+ var wrapped = convertJsFunctionToWasm(func, sig);
+ table.set(ret, wrapped);
+ }
+
+ functionsInTableMap.set(func, ret);
+
+ return ret;
+}
+
+function removeFunctionWasm(index) {
+ functionsInTableMap.delete(wasmTable.get(index));
+ freeTableIndexes.push(index);
+}
+
+// 'sig' parameter is required for the llvm backend but only when func is not
+// already a WebAssembly function.
+function addFunction(func, sig) {
+
+ return addFunctionWasm(func, sig);
+}
+
+function removeFunction(index) {
+ removeFunctionWasm(index);
+}
+
+
+
+
+
+
+
+
+
+function makeBigInt(low, high, unsigned) {
+ return unsigned ? ((+((low>>>0)))+((+((high>>>0)))*4294967296.0)) : ((+((low>>>0)))+((+((high|0)))*4294967296.0));
+}
+
+var tempRet0 = 0;
+
+var setTempRet0 = function(value) {
+ tempRet0 = value;
+};
+
+var getTempRet0 = function() {
+ return tempRet0;
+};
+
+
+// The address globals begin at. Very low in memory, for code size and optimization opportunities.
+// Above 0 is static memory, starting with globals.
+// Then the stack.
+// Then 'dynamic' memory for sbrk.
+var GLOBAL_BASE = 1024;
+
+
+
+
+// === Preamble library stuff ===
+
+// Documentation for the public APIs defined in this file must be updated in:
+// site/source/docs/api_reference/preamble.js.rst
+// A prebuilt local version of the documentation is available at:
+// site/build/text/docs/api_reference/preamble.js.txt
+// You can also build docs locally as HTML or other formats in site/
+// An online HTML version (which may be of a different version of Emscripten)
+// is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html
+
+
+var wasmBinary;if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];
+var noExitRuntime;if (Module['noExitRuntime']) noExitRuntime = Module['noExitRuntime'];
+
+
+if (typeof WebAssembly !== 'object') {
+ abort('no native wasm support detected');
+}
+
+
+
+
+// In MINIMAL_RUNTIME, setValue() and getValue() are only available when building with safe heap enabled, for heap safety checking.
+// In traditional runtime, setValue() and getValue() are always available (although their use is highly discouraged due to perf penalties)
+
+/** @param {number} ptr
+ @param {number} value
+ @param {string} type
+ @param {number|boolean=} noSafe */
+function setValue(ptr, value, type, noSafe) {
+ type = type || 'i8';
+ if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit
+ switch(type) {
+ case 'i1': HEAP8[((ptr)>>0)]=value; break;
+ case 'i8': HEAP8[((ptr)>>0)]=value; break;
+ case 'i16': HEAP16[((ptr)>>1)]=value; break;
+ case 'i32': HEAP32[((ptr)>>2)]=value; break;
+ case 'i64': (tempI64 = [value>>>0,(tempDouble=value,(+(Math_abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? ((Math_min((+(Math_floor((tempDouble)/4294967296.0))), 4294967295.0))|0)>>>0 : (~~((+(Math_ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)],HEAP32[((ptr)>>2)]=tempI64[0],HEAP32[(((ptr)+(4))>>2)]=tempI64[1]); break;
+ case 'float': HEAPF32[((ptr)>>2)]=value; break;
+ case 'double': HEAPF64[((ptr)>>3)]=value; break;
+ default: abort('invalid type for setValue: ' + type);
+ }
+}
+
+/** @param {number} ptr
+ @param {string} type
+ @param {number|boolean=} noSafe */
+function getValue(ptr, type, noSafe) {
+ type = type || 'i8';
+ if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit
+ switch(type) {
+ case 'i1': return HEAP8[((ptr)>>0)];
+ case 'i8': return HEAP8[((ptr)>>0)];
+ case 'i16': return HEAP16[((ptr)>>1)];
+ case 'i32': return HEAP32[((ptr)>>2)];
+ case 'i64': return HEAP32[((ptr)>>2)];
+ case 'float': return HEAPF32[((ptr)>>2)];
+ case 'double': return HEAPF64[((ptr)>>3)];
+ default: abort('invalid type for getValue: ' + type);
+ }
+ return null;
+}
+
+
+
+
+
+
+// Wasm globals
+
+var wasmMemory;
+
+// In fastcomp asm.js, we don't need a wasm Table at all.
+// In the wasm backend, we polyfill the WebAssembly object,
+// so this creates a (non-native-wasm) table for us.
+
+var wasmTable = new WebAssembly.Table({
+ 'initial': 196,
+ 'maximum': 196,
+ 'element': 'anyfunc'
+});
+
+
+
+
+//========================================
+// Runtime essentials
+//========================================
+
+// whether we are quitting the application. no code should run after this.
+// set in exit() and abort()
+var ABORT = false;
+
+// set by exit() and abort(). Passed to 'onExit' handler.
+// NOTE: This is also used as the process return code code in shell environments
+// but only when noExitRuntime is false.
+var EXITSTATUS = 0;
+
+/** @type {function(*, string=)} */
+function assert(condition, text) {
+ if (!condition) {
+ abort('Assertion failed: ' + text);
+ }
+}
+
+// Returns the C function with a specified identifier (for C++, you need to do manual name mangling)
+function getCFunc(ident) {
+ var func = Module['_' + ident]; // closure exported function
+ assert(func, 'Cannot call unknown function ' + ident + ', make sure it is exported');
+ return func;
+}
+
+// C calling interface.
+/** @param {string|null=} returnType
+ @param {Array=} argTypes
+ @param {Arguments|Array=} args
+ @param {Object=} opts */
+function ccall(ident, returnType, argTypes, args, opts) {
+ // For fast lookup of conversion functions
+ var toC = {
+ 'string': function(str) {
+ var ret = 0;
+ if (str !== null && str !== undefined && str !== 0) { // null string
+ // at most 4 bytes per UTF-8 code point, +1 for the trailing '\0'
+ var len = (str.length << 2) + 1;
+ ret = stackAlloc(len);
+ stringToUTF8(str, ret, len);
+ }
+ return ret;
+ },
+ 'array': function(arr) {
+ var ret = stackAlloc(arr.length);
+ writeArrayToMemory(arr, ret);
+ return ret;
+ }
+ };
+
+ function convertReturnValue(ret) {
+ if (returnType === 'string') return UTF8ToString(ret);
+ if (returnType === 'boolean') return Boolean(ret);
+ return ret;
+ }
+
+ var func = getCFunc(ident);
+ var cArgs = [];
+ var stack = 0;
+ if (args) {
+ for (var i = 0; i < args.length; i++) {
+ var converter = toC[argTypes[i]];
+ if (converter) {
+ if (stack === 0) stack = stackSave();
+ cArgs[i] = converter(args[i]);
+ } else {
+ cArgs[i] = args[i];
+ }
+ }
+ }
+ var ret = func.apply(null, cArgs);
+
+ ret = convertReturnValue(ret);
+ if (stack !== 0) stackRestore(stack);
+ return ret;
+}
+
+/** @param {string=} returnType
+ @param {Array=} argTypes
+ @param {Object=} opts */
+function cwrap(ident, returnType, argTypes, opts) {
+ argTypes = argTypes || [];
+ // When the function takes numbers and returns a number, we can just return
+ // the original function
+ var numericArgs = argTypes.every(function(type){ return type === 'number'});
+ var numericRet = returnType !== 'string';
+ if (numericRet && numericArgs && !opts) {
+ return getCFunc(ident);
+ }
+ return function() {
+ return ccall(ident, returnType, argTypes, arguments, opts);
+ }
+}
+
+
+var ALLOC_NORMAL = 0; // Tries to use _malloc()
+var ALLOC_STACK = 1; // Lives for the duration of the current function call
+var ALLOC_NONE = 2; // Do not allocate
+
+// allocate(): This is for internal use. You can use it yourself as well, but the interface
+// is a little tricky (see docs right below). The reason is that it is optimized
+// for multiple syntaxes to save space in generated code. So you should
+// normally not use allocate(), and instead allocate memory using _malloc(),
+// initialize it with setValue(), and so forth.
+// @slab: An array of data, or a number. If a number, then the size of the block to allocate,
+// in *bytes* (note that this is sometimes confusing: the next parameter does not
+// affect this!)
+// @types: Either an array of types, one for each byte (or 0 if no type at that position),
+// or a single type which is used for the entire block. This only matters if there
+// is initial data - if @slab is a number, then this does not matter at all and is
+// ignored.
+// @allocator: How to allocate memory, see ALLOC_*
+/** @type {function((TypedArray|Array<number>|number), string, number, number=)} */
+function allocate(slab, types, allocator, ptr) {
+ var zeroinit, size;
+ if (typeof slab === 'number') {
+ zeroinit = true;
+ size = slab;
+ } else {
+ zeroinit = false;
+ size = slab.length;
+ }
+
+ var singleType = typeof types === 'string' ? types : null;
+
+ var ret;
+ if (allocator == ALLOC_NONE) {
+ ret = ptr;
+ } else {
+ ret = [_malloc,
+ stackAlloc,
+ ][allocator](Math.max(size, singleType ? 1 : types.length));
+ }
+
+ if (zeroinit) {
+ var stop;
+ ptr = ret;
+ assert((ret & 3) == 0);
+ stop = ret + (size & ~3);
+ for (; ptr < stop; ptr += 4) {
+ HEAP32[((ptr)>>2)]=0;
+ }
+ stop = ret + size;
+ while (ptr < stop) {
+ HEAP8[((ptr++)>>0)]=0;
+ }
+ return ret;
+ }
+
+ if (singleType === 'i8') {
+ if (slab.subarray || slab.slice) {
+ HEAPU8.set(/** @type {!Uint8Array} */ (slab), ret);
+ } else {
+ HEAPU8.set(new Uint8Array(slab), ret);
+ }
+ return ret;
+ }
+
+ var i = 0, type, typeSize, previousType;
+ while (i < size) {
+ var curr = slab[i];
+
+ type = singleType || types[i];
+ if (type === 0) {
+ i++;
+ continue;
+ }
+
+ if (type == 'i64') type = 'i32'; // special case: we have one i32 here, and one i32 later
+
+ setValue(ret+i, curr, type);
+
+ // no need to look up size unless type changes, so cache it
+ if (previousType !== type) {
+ typeSize = getNativeTypeSize(type);
+ previousType = type;
+ }
+ i += typeSize;
+ }
+
+ return ret;
+}
+
+
+
+
+// runtime_strings.js: Strings related runtime functions that are part of both MINIMAL_RUNTIME and regular runtime.
+
+// Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the given array that contains uint8 values, returns
+// a copy of that string as a Javascript String object.
+
+var UTF8Decoder = typeof TextDecoder !== 'undefined' ? new TextDecoder('utf8') : undefined;
+
+/**
+ * @param {number} idx
+ * @param {number=} maxBytesToRead
+ * @return {string}
+ */
+function UTF8ArrayToString(heap, idx, maxBytesToRead) {
+ var endIdx = idx + maxBytesToRead;
+ var endPtr = idx;
+ // TextDecoder needs to know the byte length in advance, it doesn't stop on null terminator by itself.
+ // Also, use the length info to avoid running tiny strings through TextDecoder, since .subarray() allocates garbage.
+ // (As a tiny code save trick, compare endPtr against endIdx using a negation, so that undefined means Infinity)
+ while (heap[endPtr] && !(endPtr >= endIdx)) ++endPtr;
+
+ if (endPtr - idx > 16 && heap.subarray && UTF8Decoder) {
+ return UTF8Decoder.decode(heap.subarray(idx, endPtr));
+ } else {
+ var str = '';
+ // If building with TextDecoder, we have already computed the string length above, so test loop end condition against that
+ while (idx < endPtr) {
+ // For UTF8 byte structure, see:
+ // http://en.wikipedia.org/wiki/UTF-8#Description
+ // https://www.ietf.org/rfc/rfc2279.txt
+ // https://tools.ietf.org/html/rfc3629
+ var u0 = heap[idx++];
+ if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; }
+ var u1 = heap[idx++] & 63;
+ if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; }
+ var u2 = heap[idx++] & 63;
+ if ((u0 & 0xF0) == 0xE0) {
+ u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
+ } else {
+ u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heap[idx++] & 63);
+ }
+
+ if (u0 < 0x10000) {
+ str += String.fromCharCode(u0);
+ } else {
+ var ch = u0 - 0x10000;
+ str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF));
+ }
+ }
+ }
+ return str;
+}
+
+// Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the emscripten HEAP, returns a
+// copy of that string as a Javascript String object.
+// maxBytesToRead: an optional length that specifies the maximum number of bytes to read. You can omit
+// this parameter to scan the string until the first \0 byte. If maxBytesToRead is
+// passed, and the string at [ptr, ptr+maxBytesToReadr[ contains a null byte in the
+// middle, then the string will cut short at that byte index (i.e. maxBytesToRead will
+// not produce a string of exact length [ptr, ptr+maxBytesToRead[)
+// N.B. mixing frequent uses of UTF8ToString() with and without maxBytesToRead may
+// throw JS JIT optimizations off, so it is worth to consider consistently using one
+// style or the other.
+/**
+ * @param {number} ptr
+ * @param {number=} maxBytesToRead
+ * @return {string}
+ */
+function UTF8ToString(ptr, maxBytesToRead) {
+ return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : '';
+}
+
+// Copies the given Javascript String object 'str' to the given byte array at address 'outIdx',
+// encoded in UTF8 form and null-terminated. The copy will require at most str.length*4+1 bytes of space in the HEAP.
+// Use the function lengthBytesUTF8 to compute the exact number of bytes (excluding null terminator) that this function will write.
+// Parameters:
+// str: the Javascript string to copy.
+// heap: the array to copy to. Each index in this array is assumed to be one 8-byte element.
+// outIdx: The starting offset in the array to begin the copying.
+// maxBytesToWrite: The maximum number of bytes this function can write to the array.
+// This count should include the null terminator,
+// i.e. if maxBytesToWrite=1, only the null terminator will be written and nothing else.
+// maxBytesToWrite=0 does not write any bytes to the output, not even the null terminator.
+// Returns the number of bytes written, EXCLUDING the null terminator.
+
+function stringToUTF8Array(str, heap, outIdx, maxBytesToWrite) {
+ if (!(maxBytesToWrite > 0)) // Parameter maxBytesToWrite is not optional. Negative values, 0, null, undefined and false each don't write out any bytes.
+ return 0;
+
+ var startIdx = outIdx;
+ var endIdx = outIdx + maxBytesToWrite - 1; // -1 for string null terminator.
+ for (var i = 0; i < str.length; ++i) {
+ // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! So decode UTF16->UTF32->UTF8.
+ // See http://unicode.org/faq/utf_bom.html#utf16-3
+ // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description and https://www.ietf.org/rfc/rfc2279.txt and https://tools.ietf.org/html/rfc3629
+ var u = str.charCodeAt(i); // possibly a lead surrogate
+ if (u >= 0xD800 && u <= 0xDFFF) {
+ var u1 = str.charCodeAt(++i);
+ u = 0x10000 + ((u & 0x3FF) << 10) | (u1 & 0x3FF);
+ }
+ if (u <= 0x7F) {
+ if (outIdx >= endIdx) break;
+ heap[outIdx++] = u;
+ } else if (u <= 0x7FF) {
+ if (outIdx + 1 >= endIdx) break;
+ heap[outIdx++] = 0xC0 | (u >> 6);
+ heap[outIdx++] = 0x80 | (u & 63);
+ } else if (u <= 0xFFFF) {
+ if (outIdx + 2 >= endIdx) break;
+ heap[outIdx++] = 0xE0 | (u >> 12);
+ heap[outIdx++] = 0x80 | ((u >> 6) & 63);
+ heap[outIdx++] = 0x80 | (u & 63);
+ } else {
+ if (outIdx + 3 >= endIdx) break;
+ heap[outIdx++] = 0xF0 | (u >> 18);
+ heap[outIdx++] = 0x80 | ((u >> 12) & 63);
+ heap[outIdx++] = 0x80 | ((u >> 6) & 63);
+ heap[outIdx++] = 0x80 | (u & 63);
+ }
+ }
+ // Null-terminate the pointer to the buffer.
+ heap[outIdx] = 0;
+ return outIdx - startIdx;
+}
+
+// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr',
+// null-terminated and encoded in UTF8 form. The copy will require at most str.length*4+1 bytes of space in the HEAP.
+// Use the function lengthBytesUTF8 to compute the exact number of bytes (excluding null terminator) that this function will write.
+// Returns the number of bytes written, EXCLUDING the null terminator.
+
+function stringToUTF8(str, outPtr, maxBytesToWrite) {
+ return stringToUTF8Array(str, HEAPU8,outPtr, maxBytesToWrite);
+}
+
+// Returns the number of bytes the given Javascript string takes if encoded as a UTF8 byte array, EXCLUDING the null terminator byte.
+function lengthBytesUTF8(str) {
+ var len = 0;
+ for (var i = 0; i < str.length; ++i) {
+ // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! So decode UTF16->UTF32->UTF8.
+ // See http://unicode.org/faq/utf_bom.html#utf16-3
+ var u = str.charCodeAt(i); // possibly a lead surrogate
+ if (u >= 0xD800 && u <= 0xDFFF) u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF);
+ if (u <= 0x7F) ++len;
+ else if (u <= 0x7FF) len += 2;
+ else if (u <= 0xFFFF) len += 3;
+ else len += 4;
+ }
+ return len;
+}
+
+
+
+
+
+// runtime_strings_extra.js: Strings related runtime functions that are available only in regular runtime.
+
+// Given a pointer 'ptr' to a null-terminated ASCII-encoded string in the emscripten HEAP, returns
+// a copy of that string as a Javascript String object.
+
+function AsciiToString(ptr) {
+ var str = '';
+ while (1) {
+ var ch = HEAPU8[((ptr++)>>0)];
+ if (!ch) return str;
+ str += String.fromCharCode(ch);
+ }
+}
+
+// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr',
+// null-terminated and encoded in ASCII form. The copy will require at most str.length+1 bytes of space in the HEAP.
+
+function stringToAscii(str, outPtr) {
+ return writeAsciiToMemory(str, outPtr, false);
+}
+
+// Given a pointer 'ptr' to a null-terminated UTF16LE-encoded string in the emscripten HEAP, returns
+// a copy of that string as a Javascript String object.
+
+var UTF16Decoder = typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-16le') : undefined;
+
+function UTF16ToString(ptr, maxBytesToRead) {
+ var endPtr = ptr;
+ // TextDecoder needs to know the byte length in advance, it doesn't stop on null terminator by itself.
+ // Also, use the length info to avoid running tiny strings through TextDecoder, since .subarray() allocates garbage.
+ var idx = endPtr >> 1;
+ var maxIdx = idx + maxBytesToRead / 2;
+ // If maxBytesToRead is not passed explicitly, it will be undefined, and this
+ // will always evaluate to true. This saves on code size.
+ while (!(idx >= maxIdx) && HEAPU16[idx]) ++idx;
+ endPtr = idx << 1;
+
+ if (endPtr - ptr > 32 && UTF16Decoder) {
+ return UTF16Decoder.decode(HEAPU8.subarray(ptr, endPtr));
+ } else {
+ var i = 0;
+
+ var str = '';
+ while (1) {
+ var codeUnit = HEAP16[(((ptr)+(i*2))>>1)];
+ if (codeUnit == 0 || i == maxBytesToRead / 2) return str;
+ ++i;
+ // fromCharCode constructs a character from a UTF-16 code unit, so we can pass the UTF16 string right through.
+ str += String.fromCharCode(codeUnit);
+ }
+ }
+}
+
+// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr',
+// null-terminated and encoded in UTF16 form. The copy will require at most str.length*4+2 bytes of space in the HEAP.
+// Use the function lengthBytesUTF16() to compute the exact number of bytes (excluding null terminator) that this function will write.
+// Parameters:
+// str: the Javascript string to copy.
+// outPtr: Byte address in Emscripten HEAP where to write the string to.
+// maxBytesToWrite: The maximum number of bytes this function can write to the array. This count should include the null
+// terminator, i.e. if maxBytesToWrite=2, only the null terminator will be written and nothing else.
+// maxBytesToWrite<2 does not write any bytes to the output, not even the null terminator.
+// Returns the number of bytes written, EXCLUDING the null terminator.
+
+function stringToUTF16(str, outPtr, maxBytesToWrite) {
+ // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed.
+ if (maxBytesToWrite === undefined) {
+ maxBytesToWrite = 0x7FFFFFFF;
+ }
+ if (maxBytesToWrite < 2) return 0;
+ maxBytesToWrite -= 2; // Null terminator.
+ var startPtr = outPtr;
+ var numCharsToWrite = (maxBytesToWrite < str.length*2) ? (maxBytesToWrite / 2) : str.length;
+ for (var i = 0; i < numCharsToWrite; ++i) {
+ // charCodeAt returns a UTF-16 encoded code unit, so it can be directly written to the HEAP.
+ var codeUnit = str.charCodeAt(i); // possibly a lead surrogate
+ HEAP16[((outPtr)>>1)]=codeUnit;
+ outPtr += 2;
+ }
+ // Null-terminate the pointer to the HEAP.
+ HEAP16[((outPtr)>>1)]=0;
+ return outPtr - startPtr;
+}
+
+// Returns the number of bytes the given Javascript string takes if encoded as a UTF16 byte array, EXCLUDING the null terminator byte.
+
+function lengthBytesUTF16(str) {
+ return str.length*2;
+}
+
+function UTF32ToString(ptr, maxBytesToRead) {
+ var i = 0;
+
+ var str = '';
+ // If maxBytesToRead is not passed explicitly, it will be undefined, and this
+ // will always evaluate to true. This saves on code size.
+ while (!(i >= maxBytesToRead / 4)) {
+ var utf32 = HEAP32[(((ptr)+(i*4))>>2)];
+ if (utf32 == 0) break;
+ ++i;
+ // Gotcha: fromCharCode constructs a character from a UTF-16 encoded code (pair), not from a Unicode code point! So encode the code point to UTF-16 for constructing.
+ // See http://unicode.org/faq/utf_bom.html#utf16-3
+ if (utf32 >= 0x10000) {
+ var ch = utf32 - 0x10000;
+ str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF));
+ } else {
+ str += String.fromCharCode(utf32);
+ }
+ }
+ return str;
+}
+
+// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr',
+// null-terminated and encoded in UTF32 form. The copy will require at most str.length*4+4 bytes of space in the HEAP.
+// Use the function lengthBytesUTF32() to compute the exact number of bytes (excluding null terminator) that this function will write.
+// Parameters:
+// str: the Javascript string to copy.
+// outPtr: Byte address in Emscripten HEAP where to write the string to.
+// maxBytesToWrite: The maximum number of bytes this function can write to the array. This count should include the null
+// terminator, i.e. if maxBytesToWrite=4, only the null terminator will be written and nothing else.
+// maxBytesToWrite<4 does not write any bytes to the output, not even the null terminator.
+// Returns the number of bytes written, EXCLUDING the null terminator.
+
+function stringToUTF32(str, outPtr, maxBytesToWrite) {
+ // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed.
+ if (maxBytesToWrite === undefined) {
+ maxBytesToWrite = 0x7FFFFFFF;
+ }
+ if (maxBytesToWrite < 4) return 0;
+ var startPtr = outPtr;
+ var endPtr = startPtr + maxBytesToWrite - 4;
+ for (var i = 0; i < str.length; ++i) {
+ // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! We must decode the string to UTF-32 to the heap.
+ // See http://unicode.org/faq/utf_bom.html#utf16-3
+ var codeUnit = str.charCodeAt(i); // possibly a lead surrogate
+ if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) {
+ var trailSurrogate = str.charCodeAt(++i);
+ codeUnit = 0x10000 + ((codeUnit & 0x3FF) << 10) | (trailSurrogate & 0x3FF);
+ }
+ HEAP32[((outPtr)>>2)]=codeUnit;
+ outPtr += 4;
+ if (outPtr + 4 > endPtr) break;
+ }
+ // Null-terminate the pointer to the HEAP.
+ HEAP32[((outPtr)>>2)]=0;
+ return outPtr - startPtr;
+}
+
+// Returns the number of bytes the given Javascript string takes if encoded as a UTF16 byte array, EXCLUDING the null terminator byte.
+
+function lengthBytesUTF32(str) {
+ var len = 0;
+ for (var i = 0; i < str.length; ++i) {
+ // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! We must decode the string to UTF-32 to the heap.
+ // See http://unicode.org/faq/utf_bom.html#utf16-3
+ var codeUnit = str.charCodeAt(i);
+ if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) ++i; // possibly a lead surrogate, so skip over the tail surrogate.
+ len += 4;
+ }
+
+ return len;
+}
+
+// Allocate heap space for a JS string, and write it there.
+// It is the responsibility of the caller to free() that memory.
+function allocateUTF8(str) {
+ var size = lengthBytesUTF8(str) + 1;
+ var ret = _malloc(size);
+ if (ret) stringToUTF8Array(str, HEAP8, ret, size);
+ return ret;
+}
+
+// Allocate stack space for a JS string, and write it there.
+function allocateUTF8OnStack(str) {
+ var size = lengthBytesUTF8(str) + 1;
+ var ret = stackAlloc(size);
+ stringToUTF8Array(str, HEAP8, ret, size);
+ return ret;
+}
+
+// Deprecated: This function should not be called because it is unsafe and does not provide
+// a maximum length limit of how many bytes it is allowed to write. Prefer calling the
+// function stringToUTF8Array() instead, which takes in a maximum length that can be used
+// to be secure from out of bounds writes.
+/** @deprecated
+ @param {boolean=} dontAddNull */
+function writeStringToMemory(string, buffer, dontAddNull) {
+ warnOnce('writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!');
+
+ var /** @type {number} */ lastChar, /** @type {number} */ end;
+ if (dontAddNull) {
+ // stringToUTF8Array always appends null. If we don't want to do that, remember the
+ // character that existed at the location where the null will be placed, and restore
+ // that after the write (below).
+ end = buffer + lengthBytesUTF8(string);
+ lastChar = HEAP8[end];
+ }
+ stringToUTF8(string, buffer, Infinity);
+ if (dontAddNull) HEAP8[end] = lastChar; // Restore the value under the null character.
+}
+
+function writeArrayToMemory(array, buffer) {
+ HEAP8.set(array, buffer);
+}
+
+/** @param {boolean=} dontAddNull */
+function writeAsciiToMemory(str, buffer, dontAddNull) {
+ for (var i = 0; i < str.length; ++i) {
+ HEAP8[((buffer++)>>0)]=str.charCodeAt(i);
+ }
+ // Null-terminate the pointer to the HEAP.
+ if (!dontAddNull) HEAP8[((buffer)>>0)]=0;
+}
+
+
+
+// Memory management
+
+var PAGE_SIZE = 16384;
+var WASM_PAGE_SIZE = 65536;
+
+function alignUp(x, multiple) {
+ if (x % multiple > 0) {
+ x += multiple - (x % multiple);
+ }
+ return x;
+}
+
+var HEAP,
+/** @type {ArrayBuffer} */
+ buffer,
+/** @type {Int8Array} */
+ HEAP8,
+/** @type {Uint8Array} */
+ HEAPU8,
+/** @type {Int16Array} */
+ HEAP16,
+/** @type {Uint16Array} */
+ HEAPU16,
+/** @type {Int32Array} */
+ HEAP32,
+/** @type {Uint32Array} */
+ HEAPU32,
+/** @type {Float32Array} */
+ HEAPF32,
+/** @type {Float64Array} */
+ HEAPF64;
+
+function updateGlobalBufferAndViews(buf) {
+ buffer = buf;
+ Module['HEAP8'] = HEAP8 = new Int8Array(buf);
+ Module['HEAP16'] = HEAP16 = new Int16Array(buf);
+ Module['HEAP32'] = HEAP32 = new Int32Array(buf);
+ Module['HEAPU8'] = HEAPU8 = new Uint8Array(buf);
+ Module['HEAPU16'] = HEAPU16 = new Uint16Array(buf);
+ Module['HEAPU32'] = HEAPU32 = new Uint32Array(buf);
+ Module['HEAPF32'] = HEAPF32 = new Float32Array(buf);
+ Module['HEAPF64'] = HEAPF64 = new Float64Array(buf);
+}
+
+var STACK_BASE = 5284032,
+ STACKTOP = STACK_BASE,
+ STACK_MAX = 41152,
+ DYNAMIC_BASE = 5284032;
+
+
+
+
+var TOTAL_STACK = 5242880;
+
+var INITIAL_INITIAL_MEMORY = Module['INITIAL_MEMORY'] || 16777216;
+
+
+
+// In non-standalone/normal mode, we create the memory here.
+
+
+
+// Create the main memory. (Note: this isn't used in STANDALONE_WASM mode since the wasm
+// memory is created in the wasm, not in JS.)
+
+ if (Module['wasmMemory']) {
+ wasmMemory = Module['wasmMemory'];
+ } else
+ {
+ wasmMemory = new WebAssembly.Memory({
+ 'initial': INITIAL_INITIAL_MEMORY / WASM_PAGE_SIZE
+ ,
+ 'maximum': INITIAL_INITIAL_MEMORY / WASM_PAGE_SIZE
+ });
+ }
+
+
+if (wasmMemory) {
+ buffer = wasmMemory.buffer;
+}
+
+// If the user provides an incorrect length, just use that length instead rather than providing the user to
+// specifically provide the memory length with Module['INITIAL_MEMORY'].
+INITIAL_INITIAL_MEMORY = buffer.byteLength;
+updateGlobalBufferAndViews(buffer);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+var __ATPRERUN__ = []; // functions called before the runtime is initialized
+var __ATINIT__ = []; // functions called during startup
+var __ATMAIN__ = []; // functions called when main() is to be run
+var __ATEXIT__ = []; // functions called during shutdown
+var __ATPOSTRUN__ = []; // functions called after the main() is called
+
+var runtimeInitialized = false;
+var runtimeExited = false;
+
+
+function preRun() {
+
+ if (Module['preRun']) {
+ if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']];
+ while (Module['preRun'].length) {
+ addOnPreRun(Module['preRun'].shift());
+ }
+ }
+
+ callRuntimeCallbacks(__ATPRERUN__);
+}
+
+function initRuntime() {
+ runtimeInitialized = true;
+ if (!Module["noFSInit"] && !FS.init.initialized) FS.init();
+TTY.init();
+ callRuntimeCallbacks(__ATINIT__);
+}
+
+function preMain() {
+ FS.ignorePermissions = false;
+ callRuntimeCallbacks(__ATMAIN__);
+}
+
+function exitRuntime() {
+ runtimeExited = true;
+}
+
+function postRun() {
+
+ if (Module['postRun']) {
+ if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']];
+ while (Module['postRun'].length) {
+ addOnPostRun(Module['postRun'].shift());
+ }
+ }
+
+ callRuntimeCallbacks(__ATPOSTRUN__);
+}
+
+function addOnPreRun(cb) {
+ __ATPRERUN__.unshift(cb);
+}
+
+function addOnInit(cb) {
+ __ATINIT__.unshift(cb);
+}
+
+function addOnPreMain(cb) {
+ __ATMAIN__.unshift(cb);
+}
+
+function addOnExit(cb) {
+}
+
+function addOnPostRun(cb) {
+ __ATPOSTRUN__.unshift(cb);
+}
+
+
+
+
+// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul
+
+// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/fround
+
+// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32
+
+// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc
+
+
+var Math_abs = Math.abs;
+var Math_cos = Math.cos;
+var Math_sin = Math.sin;
+var Math_tan = Math.tan;
+var Math_acos = Math.acos;
+var Math_asin = Math.asin;
+var Math_atan = Math.atan;
+var Math_atan2 = Math.atan2;
+var Math_exp = Math.exp;
+var Math_log = Math.log;
+var Math_sqrt = Math.sqrt;
+var Math_ceil = Math.ceil;
+var Math_floor = Math.floor;
+var Math_pow = Math.pow;
+var Math_imul = Math.imul;
+var Math_fround = Math.fround;
+var Math_round = Math.round;
+var Math_min = Math.min;
+var Math_max = Math.max;
+var Math_clz32 = Math.clz32;
+var Math_trunc = Math.trunc;
+
+
+
+// A counter of dependencies for calling run(). If we need to
+// do asynchronous work before running, increment this and
+// decrement it. Incrementing must happen in a place like
+// Module.preRun (used by emcc to add file preloading).
+// Note that you can add dependencies in preRun, even though
+// it happens right before run - run will be postponed until
+// the dependencies are met.
+var runDependencies = 0;
+var runDependencyWatcher = null;
+var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled
+
+function getUniqueRunDependency(id) {
+ return id;
+}
+
+function addRunDependency(id) {
+ runDependencies++;
+
+ if (Module['monitorRunDependencies']) {
+ Module['monitorRunDependencies'](runDependencies);
+ }
+
+}
+
+function removeRunDependency(id) {
+ runDependencies--;
+
+ if (Module['monitorRunDependencies']) {
+ Module['monitorRunDependencies'](runDependencies);
+ }
+
+ if (runDependencies == 0) {
+ if (runDependencyWatcher !== null) {
+ clearInterval(runDependencyWatcher);
+ runDependencyWatcher = null;
+ }
+ if (dependenciesFulfilled) {
+ var callback = dependenciesFulfilled;
+ dependenciesFulfilled = null;
+ callback(); // can add another dependenciesFulfilled
+ }
+ }
+}
+
+Module["preloadedImages"] = {}; // maps url to image data
+Module["preloadedAudios"] = {}; // maps url to audio data
+
+/** @param {string|number=} what */
+function abort(what) {
+ if (Module['onAbort']) {
+ Module['onAbort'](what);
+ }
+
+ what += '';
+ err(what);
+
+ ABORT = true;
+ EXITSTATUS = 1;
+
+ what = 'abort(' + what + '). Build with -s ASSERTIONS=1 for more info.';
+
+ // Use a wasm runtime error, because a JS error might be seen as a foreign
+ // exception, which means we'd run destructors on it. We need the error to
+ // simply make the program stop.
+ var e = new WebAssembly.RuntimeError(what);
+
+ // Throw the error whether or not MODULARIZE is set because abort is used
+ // in code paths apart from instantiation where an exception is expected
+ // to be thrown when abort is called.
+ throw e;
+}
+
+var memoryInitializer = null;
+
+
+
+
+
+
+
+
+
+
+
+function hasPrefix(str, prefix) {
+ return String.prototype.startsWith ?
+ str.startsWith(prefix) :
+ str.indexOf(prefix) === 0;
+}
+
+// Prefix of data URIs emitted by SINGLE_FILE and related options.
+var dataURIPrefix = 'data:application/octet-stream;base64,';
+
+// Indicates whether filename is a base64 data URI.
+function isDataURI(filename) {
+ return hasPrefix(filename, dataURIPrefix);
+}
+
+var fileURIPrefix = "file://";
+
+// Indicates whether filename is delivered via file protocol (as opposed to http/https)
+function isFileURI(filename) {
+ return hasPrefix(filename, fileURIPrefix);
+}
+
+
+
+
+
+var wasmBinaryFile = 'models_first_person_maze.wasm';
+if (!isDataURI(wasmBinaryFile)) {
+ wasmBinaryFile = locateFile(wasmBinaryFile);
+}
+
+function getBinary() {
+ try {
+ if (wasmBinary) {
+ return new Uint8Array(wasmBinary);
+ }
+
+ if (readBinary) {
+ return readBinary(wasmBinaryFile);
+ } else {
+ throw "both async and sync fetching of the wasm failed";
+ }
+ }
+ catch (err) {
+ abort(err);
+ }
+}
+
+function getBinaryPromise() {
+ // If we don't have the binary yet, and have the Fetch api, use that;
+ // in some environments, like Electron's render process, Fetch api may be present, but have a different context than expected, let's only use it on the Web
+ if (!wasmBinary && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) && typeof fetch === 'function'
+ // Let's not use fetch to get objects over file:// as it's most likely Cordova which doesn't support fetch for file://
+ && !isFileURI(wasmBinaryFile)
+ ) {
+ return fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function(response) {
+ if (!response['ok']) {
+ throw "failed to load wasm binary file at '" + wasmBinaryFile + "'";
+ }
+ return response['arrayBuffer']();
+ }).catch(function () {
+ return getBinary();
+ });
+ }
+ // Otherwise, getBinary should be able to get it synchronously
+ return Promise.resolve().then(getBinary);
+}
+
+
+
+// Create the wasm instance.
+// Receives the wasm imports, returns the exports.
+function createWasm() {
+ // prepare imports
+ var info = {
+ 'env': asmLibraryArg,
+ 'wasi_snapshot_preview1': asmLibraryArg
+ };
+ // Load the wasm module and create an instance of using native support in the JS engine.
+ // handle a generated wasm instance, receiving its exports and
+ // performing other necessary setup
+ /** @param {WebAssembly.Module=} module*/
+ function receiveInstance(instance, module) {
+ var exports = instance.exports;
+ Module['asm'] = exports;
+ removeRunDependency('wasm-instantiate');
+ }
+ // we can't run yet (except in a pthread, where we have a custom sync instantiator)
+ addRunDependency('wasm-instantiate');
+
+
+ function receiveInstantiatedSource(output) {
+ // 'output' is a WebAssemblyInstantiatedSource object which has both the module and instance.
+ // receiveInstance() will swap in the exports (to Module.asm) so they can be called
+ // TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193, the above line no longer optimizes out down to the following line.
+ // When the regression is fixed, can restore the above USE_PTHREADS-enabled path.
+ receiveInstance(output['instance']);
+ }
+
+
+ function instantiateArrayBuffer(receiver) {
+ return getBinaryPromise().then(function(binary) {
+ return WebAssembly.instantiate(binary, info);
+ }).then(receiver, function(reason) {
+ err('failed to asynchronously prepare wasm: ' + reason);
+
+
+ abort(reason);
+ });
+ }
+
+ // Prefer streaming instantiation if available.
+ function instantiateAsync() {
+ if (!wasmBinary &&
+ typeof WebAssembly.instantiateStreaming === 'function' &&
+ !isDataURI(wasmBinaryFile) &&
+ // Don't use streaming for file:// delivered objects in a webview, fetch them synchronously.
+ !isFileURI(wasmBinaryFile) &&
+ typeof fetch === 'function') {
+ fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function (response) {
+ var result = WebAssembly.instantiateStreaming(response, info);
+ return result.then(receiveInstantiatedSource, function(reason) {
+ // We expect the most common failure cause to be a bad MIME type for the binary,
+ // in which case falling back to ArrayBuffer instantiation should work.
+ err('wasm streaming compile failed: ' + reason);
+ err('falling back to ArrayBuffer instantiation');
+ return instantiateArrayBuffer(receiveInstantiatedSource);
+ });
+ });
+ } else {
+ return instantiateArrayBuffer(receiveInstantiatedSource);
+ }
+ }
+ // User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback
+ // to manually instantiate the Wasm module themselves. This allows pages to run the instantiation parallel
+ // to any other async startup actions they are performing.
+ if (Module['instantiateWasm']) {
+ try {
+ var exports = Module['instantiateWasm'](info, receiveInstance);
+ return exports;
+ } catch(e) {
+ err('Module.instantiateWasm callback failed with error: ' + e);
+ return false;
+ }
+ }
+
+ instantiateAsync();
+ return {}; // no exports yet; we'll fill them in later
+}
+
+// Globals used by JS i64 conversions
+var tempDouble;
+var tempI64;
+
+// === Body ===
+
+var ASM_CONSTS = {
+
+};
+
+
+
+
+
+/* no memory initializer */
+// {{PRE_LIBRARY}}
+
+
+ function callRuntimeCallbacks(callbacks) {
+ while(callbacks.length > 0) {
+ var callback = callbacks.shift();
+ if (typeof callback == 'function') {
+ callback(Module); // Pass the module as the first argument.
+ continue;
+ }
+ var func = callback.func;
+ if (typeof func === 'number') {
+ if (callback.arg === undefined) {
+ wasmTable.get(func)();
+ } else {
+ wasmTable.get(func)(callback.arg);
+ }
+ } else {
+ func(callback.arg === undefined ? null : callback.arg);
+ }
+ }
+ }
+
+ function demangle(func) {
+ return func;
+ }
+
+ function demangleAll(text) {
+ var regex =
+ /\b_Z[\w\d_]+/g;
+ return text.replace(regex,
+ function(x) {
+ var y = demangle(x);
+ return x === y ? x : (y + ' [' + x + ']');
+ });
+ }
+
+
+ function dynCallLegacy(sig, ptr, args) {
+ if (args && args.length) {
+ return Module['dynCall_' + sig].apply(null, [ptr].concat(args));
+ }
+ return Module['dynCall_' + sig].call(null, ptr);
+ }function dynCall(sig, ptr, args) {
+ // Without WASM_BIGINT support we cannot directly call function with i64 as
+ // part of thier signature, so we rely the dynCall functions generated by
+ // wasm-emscripten-finalize
+ if (sig.indexOf('j') != -1) {
+ return dynCallLegacy(sig, ptr, args);
+ }
+
+ return wasmTable.get(ptr).apply(null, args)
+ }
+
+ function jsStackTrace() {
+ var error = new Error();
+ if (!error.stack) {
+ // IE10+ special cases: It does have callstack info, but it is only populated if an Error object is thrown,
+ // so try that as a special-case.
+ try {
+ throw new Error();
+ } catch(e) {
+ error = e;
+ }
+ if (!error.stack) {
+ return '(no stack trace available)';
+ }
+ }
+ return error.stack.toString();
+ }
+
+ function stackTrace() {
+ var js = jsStackTrace();
+ if (Module['extraStackTrace']) js += '\n' + Module['extraStackTrace']();
+ return demangleAll(js);
+ }
+
+ function ___assert_fail(condition, filename, line, func) {
+ abort('Assertion failed: ' + UTF8ToString(condition) + ', at: ' + [filename ? UTF8ToString(filename) : 'unknown filename', line, func ? UTF8ToString(func) : 'unknown function']);
+ }
+
+
+ function setErrNo(value) {
+ HEAP32[((___errno_location())>>2)]=value;
+ return value;
+ }
+
+
+ var PATH={splitPath:function(filename) {
+ var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
+ return splitPathRe.exec(filename).slice(1);
+ },normalizeArray:function(parts, allowAboveRoot) {
+ // if the path tries to go above the root, `up` ends up > 0
+ var up = 0;
+ for (var i = parts.length - 1; i >= 0; i--) {
+ var last = parts[i];
+ if (last === '.') {
+ parts.splice(i, 1);
+ } else if (last === '..') {
+ parts.splice(i, 1);
+ up++;
+ } else if (up) {
+ parts.splice(i, 1);
+ up--;
+ }
+ }
+ // if the path is allowed to go above the root, restore leading ..s
+ if (allowAboveRoot) {
+ for (; up; up--) {
+ parts.unshift('..');
+ }
+ }
+ return parts;
+ },normalize:function(path) {
+ var isAbsolute = path.charAt(0) === '/',
+ trailingSlash = path.substr(-1) === '/';
+ // Normalize the path
+ path = PATH.normalizeArray(path.split('/').filter(function(p) {
+ return !!p;
+ }), !isAbsolute).join('/');
+ if (!path && !isAbsolute) {
+ path = '.';
+ }
+ if (path && trailingSlash) {
+ path += '/';
+ }
+ return (isAbsolute ? '/' : '') + path;
+ },dirname:function(path) {
+ var result = PATH.splitPath(path),
+ root = result[0],
+ dir = result[1];
+ if (!root && !dir) {
+ // No dirname whatsoever
+ return '.';
+ }
+ if (dir) {
+ // It has a dirname, strip trailing slash
+ dir = dir.substr(0, dir.length - 1);
+ }
+ return root + dir;
+ },basename:function(path) {
+ // EMSCRIPTEN return '/'' for '/', not an empty string
+ if (path === '/') return '/';
+ path = PATH.normalize(path);
+ path = path.replace(/\/$/, "");
+ var lastSlash = path.lastIndexOf('/');
+ if (lastSlash === -1) return path;
+ return path.substr(lastSlash+1);
+ },extname:function(path) {
+ return PATH.splitPath(path)[3];
+ },join:function() {
+ var paths = Array.prototype.slice.call(arguments, 0);
+ return PATH.normalize(paths.join('/'));
+ },join2:function(l, r) {
+ return PATH.normalize(l + '/' + r);
+ }};
+
+
+ var PATH_FS={resolve:function() {
+ var resolvedPath = '',
+ resolvedAbsolute = false;
+ for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
+ var path = (i >= 0) ? arguments[i] : FS.cwd();
+ // Skip empty and invalid entries
+ if (typeof path !== 'string') {
+ throw new TypeError('Arguments to path.resolve must be strings');
+ } else if (!path) {
+ return ''; // an invalid portion invalidates the whole thing
+ }
+ resolvedPath = path + '/' + resolvedPath;
+ resolvedAbsolute = path.charAt(0) === '/';
+ }
+ // At this point the path should be resolved to a full absolute path, but
+ // handle relative paths to be safe (might happen when process.cwd() fails)
+ resolvedPath = PATH.normalizeArray(resolvedPath.split('/').filter(function(p) {
+ return !!p;
+ }), !resolvedAbsolute).join('/');
+ return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
+ },relative:function(from, to) {
+ from = PATH_FS.resolve(from).substr(1);
+ to = PATH_FS.resolve(to).substr(1);
+ function trim(arr) {
+ var start = 0;
+ for (; start < arr.length; start++) {
+ if (arr[start] !== '') break;
+ }
+ var end = arr.length - 1;
+ for (; end >= 0; end--) {
+ if (arr[end] !== '') break;
+ }
+ if (start > end) return [];
+ return arr.slice(start, end - start + 1);
+ }
+ var fromParts = trim(from.split('/'));
+ var toParts = trim(to.split('/'));
+ var length = Math.min(fromParts.length, toParts.length);
+ var samePartsLength = length;
+ for (var i = 0; i < length; i++) {
+ if (fromParts[i] !== toParts[i]) {
+ samePartsLength = i;
+ break;
+ }
+ }
+ var outputParts = [];
+ for (var i = samePartsLength; i < fromParts.length; i++) {
+ outputParts.push('..');
+ }
+ outputParts = outputParts.concat(toParts.slice(samePartsLength));
+ return outputParts.join('/');
+ }};
+
+ var TTY={ttys:[],init:function () {
+ // https://github.com/emscripten-core/emscripten/pull/1555
+ // if (ENVIRONMENT_IS_NODE) {
+ // // currently, FS.init does not distinguish if process.stdin is a file or TTY
+ // // device, it always assumes it's a TTY device. because of this, we're forcing
+ // // process.stdin to UTF8 encoding to at least make stdin reading compatible
+ // // with text files until FS.init can be refactored.
+ // process['stdin']['setEncoding']('utf8');
+ // }
+ },shutdown:function() {
+ // https://github.com/emscripten-core/emscripten/pull/1555
+ // if (ENVIRONMENT_IS_NODE) {
+ // // inolen: any idea as to why node -e 'process.stdin.read()' wouldn't exit immediately (with process.stdin being a tty)?
+ // // isaacs: because now it's reading from the stream, you've expressed interest in it, so that read() kicks off a _read() which creates a ReadReq operation
+ // // inolen: I thought read() in that case was a synchronous operation that just grabbed some amount of buffered data if it exists?
+ // // isaacs: it is. but it also triggers a _read() call, which calls readStart() on the handle
+ // // isaacs: do process.stdin.pause() and i'd think it'd probably close the pending call
+ // process['stdin']['pause']();
+ // }
+ },register:function(dev, ops) {
+ TTY.ttys[dev] = { input: [], output: [], ops: ops };
+ FS.registerDevice(dev, TTY.stream_ops);
+ },stream_ops:{open:function(stream) {
+ var tty = TTY.ttys[stream.node.rdev];
+ if (!tty) {
+ throw new FS.ErrnoError(43);
+ }
+ stream.tty = tty;
+ stream.seekable = false;
+ },close:function(stream) {
+ // flush any pending line data
+ stream.tty.ops.flush(stream.tty);
+ },flush:function(stream) {
+ stream.tty.ops.flush(stream.tty);
+ },read:function(stream, buffer, offset, length, pos /* ignored */) {
+ if (!stream.tty || !stream.tty.ops.get_char) {
+ throw new FS.ErrnoError(60);
+ }
+ var bytesRead = 0;
+ for (var i = 0; i < length; i++) {
+ var result;
+ try {
+ result = stream.tty.ops.get_char(stream.tty);
+ } catch (e) {
+ throw new FS.ErrnoError(29);
+ }
+ if (result === undefined && bytesRead === 0) {
+ throw new FS.ErrnoError(6);
+ }
+ if (result === null || result === undefined) break;
+ bytesRead++;
+ buffer[offset+i] = result;
+ }
+ if (bytesRead) {
+ stream.node.timestamp = Date.now();
+ }
+ return bytesRead;
+ },write:function(stream, buffer, offset, length, pos) {
+ if (!stream.tty || !stream.tty.ops.put_char) {
+ throw new FS.ErrnoError(60);
+ }
+ try {
+ for (var i = 0; i < length; i++) {
+ stream.tty.ops.put_char(stream.tty, buffer[offset+i]);
+ }
+ } catch (e) {
+ throw new FS.ErrnoError(29);
+ }
+ if (length) {
+ stream.node.timestamp = Date.now();
+ }
+ return i;
+ }},default_tty_ops:{get_char:function(tty) {
+ if (!tty.input.length) {
+ var result = null;
+ if (ENVIRONMENT_IS_NODE) {
+ // we will read data by chunks of BUFSIZE
+ var BUFSIZE = 256;
+ var buf = Buffer.alloc ? Buffer.alloc(BUFSIZE) : new Buffer(BUFSIZE);
+ var bytesRead = 0;
+
+ try {
+ bytesRead = nodeFS.readSync(process.stdin.fd, buf, 0, BUFSIZE, null);
+ } catch(e) {
+ // Cross-platform differences: on Windows, reading EOF throws an exception, but on other OSes,
+ // reading EOF returns 0. Uniformize behavior by treating the EOF exception to return 0.
+ if (e.toString().indexOf('EOF') != -1) bytesRead = 0;
+ else throw e;
+ }
+
+ if (bytesRead > 0) {
+ result = buf.slice(0, bytesRead).toString('utf-8');
+ } else {
+ result = null;
+ }
+ } else
+ if (typeof window != 'undefined' &&
+ typeof window.prompt == 'function') {
+ // Browser.
+ result = window.prompt('Input: '); // returns null on cancel
+ if (result !== null) {
+ result += '\n';
+ }
+ } else if (typeof readline == 'function') {
+ // Command line.
+ result = readline();
+ if (result !== null) {
+ result += '\n';
+ }
+ }
+ if (!result) {
+ return null;
+ }
+ tty.input = intArrayFromString(result, true);
+ }
+ return tty.input.shift();
+ },put_char:function(tty, val) {
+ if (val === null || val === 10) {
+ out(UTF8ArrayToString(tty.output, 0));
+ tty.output = [];
+ } else {
+ if (val != 0) tty.output.push(val); // val == 0 would cut text output off in the middle.
+ }
+ },flush:function(tty) {
+ if (tty.output && tty.output.length > 0) {
+ out(UTF8ArrayToString(tty.output, 0));
+ tty.output = [];
+ }
+ }},default_tty1_ops:{put_char:function(tty, val) {
+ if (val === null || val === 10) {
+ err(UTF8ArrayToString(tty.output, 0));
+ tty.output = [];
+ } else {
+ if (val != 0) tty.output.push(val);
+ }
+ },flush:function(tty) {
+ if (tty.output && tty.output.length > 0) {
+ err(UTF8ArrayToString(tty.output, 0));
+ tty.output = [];
+ }
+ }}};
+
+ var MEMFS={ops_table:null,mount:function(mount) {
+ return MEMFS.createNode(null, '/', 16384 | 511 /* 0777 */, 0);
+ },createNode:function(parent, name, mode, dev) {
+ if (FS.isBlkdev(mode) || FS.isFIFO(mode)) {
+ // no supported
+ throw new FS.ErrnoError(63);
+ }
+ if (!MEMFS.ops_table) {
+ MEMFS.ops_table = {
+ dir: {
+ node: {
+ getattr: MEMFS.node_ops.getattr,
+ setattr: MEMFS.node_ops.setattr,
+ lookup: MEMFS.node_ops.lookup,
+ mknod: MEMFS.node_ops.mknod,
+ rename: MEMFS.node_ops.rename,
+ unlink: MEMFS.node_ops.unlink,
+ rmdir: MEMFS.node_ops.rmdir,
+ readdir: MEMFS.node_ops.readdir,
+ symlink: MEMFS.node_ops.symlink
+ },
+ stream: {
+ llseek: MEMFS.stream_ops.llseek
+ }
+ },
+ file: {
+ node: {
+ getattr: MEMFS.node_ops.getattr,
+ setattr: MEMFS.node_ops.setattr
+ },
+ 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
+ }
+ },
+ link: {
+ node: {
+ getattr: MEMFS.node_ops.getattr,
+ setattr: MEMFS.node_ops.setattr,
+ readlink: MEMFS.node_ops.readlink
+ },
+ stream: {}
+ },
+ chrdev: {
+ node: {
+ getattr: MEMFS.node_ops.getattr,
+ setattr: MEMFS.node_ops.setattr
+ },
+ stream: FS.chrdev_stream_ops
+ }
+ };
+ }
+ var node = FS.createNode(parent, name, mode, dev);
+ if (FS.isDir(node.mode)) {
+ node.node_ops = MEMFS.ops_table.dir.node;
+ node.stream_ops = MEMFS.ops_table.dir.stream;
+ node.contents = {};
+ } else if (FS.isFile(node.mode)) {
+ node.node_ops = MEMFS.ops_table.file.node;
+ node.stream_ops = MEMFS.ops_table.file.stream;
+ node.usedBytes = 0; // The actual number of bytes used in the typed array, as opposed to contents.length which gives the whole capacity.
+ // When the byte data of the file is populated, this will point to either a typed array, or a normal JS array. Typed arrays are preferred
+ // for performance, and used by default. However, typed arrays are not resizable like normal JS arrays are, so there is a small disk size
+ // penalty involved for appending file writes that continuously grow a file similar to std::vector capacity vs used -scheme.
+ node.contents = null;
+ } else if (FS.isLink(node.mode)) {
+ node.node_ops = MEMFS.ops_table.link.node;
+ node.stream_ops = MEMFS.ops_table.link.stream;
+ } else if (FS.isChrdev(node.mode)) {
+ node.node_ops = MEMFS.ops_table.chrdev.node;
+ node.stream_ops = MEMFS.ops_table.chrdev.stream;
+ }
+ node.timestamp = Date.now();
+ // add the new node to the parent
+ if (parent) {
+ parent.contents[name] = node;
+ }
+ return node;
+ },getFileDataAsRegularArray:function(node) {
+ if (node.contents && node.contents.subarray) {
+ var arr = [];
+ for (var i = 0; i < node.usedBytes; ++i) arr.push(node.contents[i]);
+ return arr; // Returns a copy of the original data.
+ }
+ return node.contents; // No-op, the file contents are already in a JS array. Return as-is.
+ },getFileDataAsTypedArray:function(node) {
+ if (!node.contents) return new Uint8Array(0);
+ if (node.contents.subarray) return node.contents.subarray(0, node.usedBytes); // Make sure to not return excess unused bytes.
+ return new Uint8Array(node.contents);
+ },expandFileStorage:function(node, newCapacity) {
+ var prevCapacity = node.contents ? node.contents.length : 0;
+ if (prevCapacity >= newCapacity) return; // No need to expand, the storage was already large enough.
+ // Don't expand strictly to the given requested limit if it's only a very small increase, but instead geometrically grow capacity.
+ // For small filesizes (<1MB), perform size*2 geometric increase, but for large sizes, do a much more conservative size*1.125 increase to
+ // avoid overshooting the allocation cap by a very large margin.
+ var CAPACITY_DOUBLING_MAX = 1024 * 1024;
+ newCapacity = Math.max(newCapacity, (prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2.0 : 1.125)) >>> 0);
+ if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256); // At minimum allocate 256b for each file when expanding.
+ var oldContents = node.contents;
+ node.contents = new Uint8Array(newCapacity); // Allocate new storage.
+ if (node.usedBytes > 0) node.contents.set(oldContents.subarray(0, node.usedBytes), 0); // Copy old data over to the new storage.
+ return;
+ },resizeFileStorage:function(node, newSize) {
+ if (node.usedBytes == newSize) return;
+ if (newSize == 0) {
+ node.contents = null; // Fully decommit when requesting a resize to zero.
+ node.usedBytes = 0;
+ return;
+ }
+ if (!node.contents || node.contents.subarray) { // Resize a typed array if that is being used as the backing store.
+ var oldContents = node.contents;
+ node.contents = new Uint8Array(newSize); // Allocate new storage.
+ if (oldContents) {
+ node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes))); // Copy old data over to the new storage.
+ }
+ node.usedBytes = newSize;
+ return;
+ }
+ // Backing with a JS array.
+ if (!node.contents) node.contents = [];
+ if (node.contents.length > newSize) node.contents.length = newSize;
+ else while (node.contents.length < newSize) node.contents.push(0);
+ node.usedBytes = newSize;
+ },node_ops:{getattr:function(node) {
+ var attr = {};
+ // device numbers reuse inode numbers.
+ attr.dev = FS.isChrdev(node.mode) ? node.id : 1;
+ attr.ino = node.id;
+ attr.mode = node.mode;
+ attr.nlink = 1;
+ attr.uid = 0;
+ attr.gid = 0;
+ attr.rdev = node.rdev;
+ if (FS.isDir(node.mode)) {
+ attr.size = 4096;
+ } else if (FS.isFile(node.mode)) {
+ attr.size = node.usedBytes;
+ } else if (FS.isLink(node.mode)) {
+ attr.size = node.link.length;
+ } else {
+ attr.size = 0;
+ }
+ attr.atime = new Date(node.timestamp);
+ attr.mtime = new Date(node.timestamp);
+ attr.ctime = new Date(node.timestamp);
+ // NOTE: In our implementation, st_blocks = Math.ceil(st_size/st_blksize),
+ // but this is not required by the standard.
+ attr.blksize = 4096;
+ attr.blocks = Math.ceil(attr.size / attr.blksize);
+ return attr;
+ },setattr:function(node, attr) {
+ if (attr.mode !== undefined) {
+ node.mode = attr.mode;
+ }
+ if (attr.timestamp !== undefined) {
+ node.timestamp = attr.timestamp;
+ }
+ if (attr.size !== undefined) {
+ MEMFS.resizeFileStorage(node, attr.size);
+ }
+ },lookup:function(parent, name) {
+ throw FS.genericErrors[44];
+ },mknod:function(parent, name, mode, dev) {
+ return MEMFS.createNode(parent, name, mode, dev);
+ },rename:function(old_node, new_dir, new_name) {
+ // if we're overwriting a directory at new_name, make sure it's empty.
+ if (FS.isDir(old_node.mode)) {
+ var new_node;
+ try {
+ new_node = FS.lookupNode(new_dir, new_name);
+ } catch (e) {
+ }
+ if (new_node) {
+ for (var i in new_node.contents) {
+ throw new FS.ErrnoError(55);
+ }
+ }
+ }
+ // do the internal rewiring
+ delete old_node.parent.contents[old_node.name];
+ old_node.name = new_name;
+ new_dir.contents[new_name] = old_node;
+ old_node.parent = new_dir;
+ },unlink:function(parent, name) {
+ delete parent.contents[name];
+ },rmdir:function(parent, name) {
+ var node = FS.lookupNode(parent, name);
+ for (var i in node.contents) {
+ throw new FS.ErrnoError(55);
+ }
+ delete parent.contents[name];
+ },readdir:function(node) {
+ var entries = ['.', '..'];
+ for (var key in node.contents) {
+ if (!node.contents.hasOwnProperty(key)) {
+ continue;
+ }
+ entries.push(key);
+ }
+ return entries;
+ },symlink:function(parent, newname, oldpath) {
+ var node = MEMFS.createNode(parent, newname, 511 /* 0777 */ | 40960, 0);
+ node.link = oldpath;
+ return node;
+ },readlink:function(node) {
+ if (!FS.isLink(node.mode)) {
+ throw new FS.ErrnoError(28);
+ }
+ return node.link;
+ }},stream_ops:{read:function(stream, buffer, offset, length, position) {
+ var contents = stream.node.contents;
+ if (position >= stream.node.usedBytes) return 0;
+ var size = Math.min(stream.node.usedBytes - position, length);
+ if (size > 8 && contents.subarray) { // non-trivial, and typed array
+ buffer.set(contents.subarray(position, position + size), offset);
+ } else {
+ for (var i = 0; i < size; i++) buffer[offset + i] = contents[position + i];
+ }
+ return size;
+ },write:function(stream, buffer, offset, length, position, canOwn) {
+
+ if (!length) return 0;
+ var node = stream.node;
+ node.timestamp = Date.now();
+
+ if (buffer.subarray && (!node.contents || node.contents.subarray)) { // This write is from a typed array to a typed array?
+ if (canOwn) {
+ node.contents = buffer.subarray(offset, offset + length);
+ node.usedBytes = length;
+ return length;
+ } else if (node.usedBytes === 0 && position === 0) { // If this is a simple first write to an empty file, do a fast set since we don't need to care about old data.
+ node.contents = buffer.slice(offset, offset + length);
+ node.usedBytes = length;
+ return length;
+ } else if (position + length <= node.usedBytes) { // Writing to an already allocated and used subrange of the file?
+ node.contents.set(buffer.subarray(offset, offset + length), position);
+ return length;
+ }
+ }
+
+ // Appending to an existing file and we need to reallocate, or source data did not come as a typed array.
+ MEMFS.expandFileStorage(node, position+length);
+ if (node.contents.subarray && buffer.subarray) {
+ // Use typed array write which is available.
+ node.contents.set(buffer.subarray(offset, offset + length), position);
+ } else {
+ for (var i = 0; i < length; i++) {
+ node.contents[position + i] = buffer[offset + i]; // Or fall back to manual write if not.
+ }
+ }
+ node.usedBytes = Math.max(node.usedBytes, position + length);
+ return length;
+ },llseek:function(stream, offset, whence) {
+ var position = offset;
+ if (whence === 1) {
+ position += stream.position;
+ } else if (whence === 2) {
+ if (FS.isFile(stream.node.mode)) {
+ position += stream.node.usedBytes;
+ }
+ }
+ if (position < 0) {
+ throw new FS.ErrnoError(28);
+ }
+ return position;
+ },allocate:function(stream, offset, length) {
+ MEMFS.expandFileStorage(stream.node, offset + length);
+ stream.node.usedBytes = Math.max(stream.node.usedBytes, offset + length);
+ },mmap:function(stream, address, length, position, prot, flags) {
+ // We don't currently support location hints for the address of the mapping
+ assert(address === 0);
+
+ if (!FS.isFile(stream.node.mode)) {
+ throw new FS.ErrnoError(43);
+ }
+ var ptr;
+ var allocated;
+ var contents = stream.node.contents;
+ // Only make a new copy when MAP_PRIVATE is specified.
+ if (!(flags & 2) && contents.buffer === buffer) {
+ // We can't emulate MAP_SHARED when the file is not backed by the buffer
+ // we're mapping to (e.g. the HEAP buffer).
+ allocated = false;
+ ptr = contents.byteOffset;
+ } else {
+ // Try to avoid unnecessary slices.
+ if (position > 0 || position + length < contents.length) {
+ if (contents.subarray) {
+ contents = contents.subarray(position, position + length);
+ } else {
+ contents = Array.prototype.slice.call(contents, position, position + length);
+ }
+ }
+ allocated = true;
+ ptr = FS.mmapAlloc(length);
+ if (!ptr) {
+ throw new FS.ErrnoError(48);
+ }
+ HEAP8.set(contents, ptr);
+ }
+ return { ptr: ptr, allocated: allocated };
+ },msync:function(stream, buffer, offset, length, mmapFlags) {
+ if (!FS.isFile(stream.node.mode)) {
+ throw new FS.ErrnoError(43);
+ }
+ if (mmapFlags & 2) {
+ // MAP_PRIVATE calls need not to be synced back to underlying fs
+ return 0;
+ }
+
+ var bytesWritten = MEMFS.stream_ops.write(stream, buffer, 0, length, offset, false);
+ // should we check if bytesWritten and length are the same?
+ return 0;
+ }}};var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,trackingDelegate:{},tracking:{openFlags:{READ:1,WRITE:2}},ErrnoError:null,genericErrors:{},filesystems:null,syncFSRequests:0,handleFSError:function(e) {
+ if (!(e instanceof FS.ErrnoError)) throw e + ' : ' + stackTrace();
+ return setErrNo(e.errno);
+ },lookupPath:function(path, opts) {
+ path = PATH_FS.resolve(FS.cwd(), path);
+ opts = opts || {};
+
+ if (!path) return { path: '', node: null };
+
+ var defaults = {
+ follow_mount: true,
+ recurse_count: 0
+ };
+ for (var key in defaults) {
+ if (opts[key] === undefined) {
+ opts[key] = defaults[key];
+ }
+ }
+
+ if (opts.recurse_count > 8) { // max recursive lookup of 8
+ throw new FS.ErrnoError(32);
+ }
+
+ // split the path
+ var parts = PATH.normalizeArray(path.split('/').filter(function(p) {
+ return !!p;
+ }), false);
+
+ // start at the root
+ var current = FS.root;
+ var current_path = '/';
+
+ for (var i = 0; i < parts.length; i++) {
+ var islast = (i === parts.length-1);
+ if (islast && opts.parent) {
+ // stop resolving
+ break;
+ }
+
+ current = FS.lookupNode(current, parts[i]);
+ current_path = PATH.join2(current_path, parts[i]);
+
+ // jump to the mount's root node if this is a mountpoint
+ if (FS.isMountpoint(current)) {
+ if (!islast || (islast && opts.follow_mount)) {
+ current = current.mounted.root;
+ }
+ }
+
+ // by default, lookupPath will not follow a symlink if it is the final path component.
+ // setting opts.follow = true will override this behavior.
+ if (!islast || opts.follow) {
+ var count = 0;
+ while (FS.isLink(current.mode)) {
+ var link = FS.readlink(current_path);
+ current_path = PATH_FS.resolve(PATH.dirname(current_path), link);
+
+ var lookup = FS.lookupPath(current_path, { recurse_count: opts.recurse_count });
+ current = lookup.node;
+
+ if (count++ > 40) { // limit max consecutive symlinks to 40 (SYMLOOP_MAX).
+ throw new FS.ErrnoError(32);
+ }
+ }
+ }
+ }
+
+ return { path: current_path, node: current };
+ },getPath:function(node) {
+ var path;
+ while (true) {
+ if (FS.isRoot(node)) {
+ var mount = node.mount.mountpoint;
+ if (!path) return mount;
+ return mount[mount.length-1] !== '/' ? mount + '/' + path : mount + path;
+ }
+ path = path ? node.name + '/' + path : node.name;
+ node = node.parent;
+ }
+ },hashName:function(parentid, name) {
+ var hash = 0;
+
+
+ for (var i = 0; i < name.length; i++) {
+ hash = ((hash << 5) - hash + name.charCodeAt(i)) | 0;
+ }
+ return ((parentid + hash) >>> 0) % FS.nameTable.length;
+ },hashAddNode:function(node) {
+ var hash = FS.hashName(node.parent.id, node.name);
+ node.name_next = FS.nameTable[hash];
+ FS.nameTable[hash] = node;
+ },hashRemoveNode:function(node) {
+ var hash = FS.hashName(node.parent.id, node.name);
+ if (FS.nameTable[hash] === node) {
+ FS.nameTable[hash] = node.name_next;
+ } else {
+ var current = FS.nameTable[hash];
+ while (current) {
+ if (current.name_next === node) {
+ current.name_next = node.name_next;
+ break;
+ }
+ current = current.name_next;
+ }
+ }
+ },lookupNode:function(parent, name) {
+ var errCode = FS.mayLookup(parent);
+ if (errCode) {
+ throw new FS.ErrnoError(errCode, parent);
+ }
+ var hash = FS.hashName(parent.id, name);
+ for (var node = FS.nameTable[hash]; node; node = node.name_next) {
+ var nodeName = node.name;
+ if (node.parent.id === parent.id && nodeName === name) {
+ return node;
+ }
+ }
+ // if we failed to find it in the cache, call into the VFS
+ return FS.lookup(parent, name);
+ },createNode:function(parent, name, mode, rdev) {
+ var node = new FS.FSNode(parent, name, mode, rdev);
+
+ FS.hashAddNode(node);
+
+ return node;
+ },destroyNode:function(node) {
+ FS.hashRemoveNode(node);
+ },isRoot:function(node) {
+ return node === node.parent;
+ },isMountpoint:function(node) {
+ return !!node.mounted;
+ },isFile:function(mode) {
+ return (mode & 61440) === 32768;
+ },isDir:function(mode) {
+ return (mode & 61440) === 16384;
+ },isLink:function(mode) {
+ return (mode & 61440) === 40960;
+ },isChrdev:function(mode) {
+ return (mode & 61440) === 8192;
+ },isBlkdev:function(mode) {
+ return (mode & 61440) === 24576;
+ },isFIFO:function(mode) {
+ return (mode & 61440) === 4096;
+ },isSocket:function(mode) {
+ return (mode & 49152) === 49152;
+ },flagModes:{"r":0,"rs":1052672,"r+":2,"w":577,"wx":705,"xw":705,"w+":578,"wx+":706,"xw+":706,"a":1089,"ax":1217,"xa":1217,"a+":1090,"ax+":1218,"xa+":1218},modeStringToFlags:function(str) {
+ var flags = FS.flagModes[str];
+ if (typeof flags === 'undefined') {
+ throw new Error('Unknown file open mode: ' + str);
+ }
+ return flags;
+ },flagsToPermissionString:function(flag) {
+ var perms = ['r', 'w', 'rw'][flag & 3];
+ if ((flag & 512)) {
+ perms += 'w';
+ }
+ return perms;
+ },nodePermissions:function(node, perms) {
+ if (FS.ignorePermissions) {
+ return 0;
+ }
+ // return 0 if any user, group or owner bits are set.
+ if (perms.indexOf('r') !== -1 && !(node.mode & 292)) {
+ return 2;
+ } else if (perms.indexOf('w') !== -1 && !(node.mode & 146)) {
+ return 2;
+ } else if (perms.indexOf('x') !== -1 && !(node.mode & 73)) {
+ return 2;
+ }
+ return 0;
+ },mayLookup:function(dir) {
+ var errCode = FS.nodePermissions(dir, 'x');
+ if (errCode) return errCode;
+ if (!dir.node_ops.lookup) return 2;
+ return 0;
+ },mayCreate:function(dir, name) {
+ try {
+ var node = FS.lookupNode(dir, name);
+ return 20;
+ } catch (e) {
+ }
+ return FS.nodePermissions(dir, 'wx');
+ },mayDelete:function(dir, name, isdir) {
+ var node;
+ try {
+ node = FS.lookupNode(dir, name);
+ } catch (e) {
+ return e.errno;
+ }
+ var errCode = FS.nodePermissions(dir, 'wx');
+ if (errCode) {
+ return errCode;
+ }
+ if (isdir) {
+ if (!FS.isDir(node.mode)) {
+ return 54;
+ }
+ if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) {
+ return 10;
+ }
+ } else {
+ if (FS.isDir(node.mode)) {
+ return 31;
+ }
+ }
+ return 0;
+ },mayOpen:function(node, flags) {
+ if (!node) {
+ return 44;
+ }
+ if (FS.isLink(node.mode)) {
+ return 32;
+ } else if (FS.isDir(node.mode)) {
+ if (FS.flagsToPermissionString(flags) !== 'r' || // opening for write
+ (flags & 512)) { // TODO: check for O_SEARCH? (== search for dir only)
+ return 31;
+ }
+ }
+ return FS.nodePermissions(node, FS.flagsToPermissionString(flags));
+ },MAX_OPEN_FDS:4096,nextfd:function(fd_start, fd_end) {
+ fd_start = fd_start || 0;
+ fd_end = fd_end || FS.MAX_OPEN_FDS;
+ for (var fd = fd_start; fd <= fd_end; fd++) {
+ if (!FS.streams[fd]) {
+ return fd;
+ }
+ }
+ throw new FS.ErrnoError(33);
+ },getStream:function(fd) {
+ return FS.streams[fd];
+ },createStream:function(stream, fd_start, fd_end) {
+ if (!FS.FSStream) {
+ FS.FSStream = /** @constructor */ function(){};
+ FS.FSStream.prototype = {
+ object: {
+ get: function() { return this.node; },
+ set: function(val) { this.node = val; }
+ },
+ isRead: {
+ get: function() { return (this.flags & 2097155) !== 1; }
+ },
+ isWrite: {
+ get: function() { return (this.flags & 2097155) !== 0; }
+ },
+ isAppend: {
+ get: function() { return (this.flags & 1024); }
+ }
+ };
+ }
+ // clone it, so we can return an instance of FSStream
+ var newStream = new FS.FSStream();
+ for (var p in stream) {
+ newStream[p] = stream[p];
+ }
+ stream = newStream;
+ var fd = FS.nextfd(fd_start, fd_end);
+ stream.fd = fd;
+ FS.streams[fd] = stream;
+ return stream;
+ },closeStream:function(fd) {
+ FS.streams[fd] = null;
+ },chrdev_stream_ops:{open:function(stream) {
+ var device = FS.getDevice(stream.node.rdev);
+ // override node's stream ops with the device's
+ stream.stream_ops = device.stream_ops;
+ // forward the open call
+ if (stream.stream_ops.open) {
+ stream.stream_ops.open(stream);
+ }
+ },llseek:function() {
+ throw new FS.ErrnoError(70);
+ }},major:function(dev) {
+ return ((dev) >> 8);
+ },minor:function(dev) {
+ return ((dev) & 0xff);
+ },makedev:function(ma, mi) {
+ return ((ma) << 8 | (mi));
+ },registerDevice:function(dev, ops) {
+ FS.devices[dev] = { stream_ops: ops };
+ },getDevice:function(dev) {
+ return FS.devices[dev];
+ },getMounts:function(mount) {
+ var mounts = [];
+ var check = [mount];
+
+ while (check.length) {
+ var m = check.pop();
+
+ mounts.push(m);
+
+ check.push.apply(check, m.mounts);
+ }
+
+ return mounts;
+ },syncfs:function(populate, callback) {
+ if (typeof(populate) === 'function') {
+ callback = populate;
+ populate = false;
+ }
+
+ FS.syncFSRequests++;
+
+ if (FS.syncFSRequests > 1) {
+ err('warning: ' + FS.syncFSRequests + ' FS.syncfs operations in flight at once, probably just doing extra work');
+ }
+
+ var mounts = FS.getMounts(FS.root.mount);
+ var completed = 0;
+
+ function doCallback(errCode) {
+ FS.syncFSRequests--;
+ return callback(errCode);
+ }
+
+ function done(errCode) {
+ if (errCode) {
+ if (!done.errored) {
+ done.errored = true;
+ return doCallback(errCode);
+ }
+ return;
+ }
+ if (++completed >= mounts.length) {
+ doCallback(null);
+ }
+ };
+
+ // sync all mounts
+ mounts.forEach(function (mount) {
+ if (!mount.type.syncfs) {
+ return done(null);
+ }
+ mount.type.syncfs(mount, populate, done);
+ });
+ },mount:function(type, opts, mountpoint) {
+ var root = mountpoint === '/';
+ var pseudo = !mountpoint;
+ var node;
+
+ if (root && FS.root) {
+ throw new FS.ErrnoError(10);
+ } else if (!root && !pseudo) {
+ var lookup = FS.lookupPath(mountpoint, { follow_mount: false });
+
+ mountpoint = lookup.path; // use the absolute path
+ node = lookup.node;
+
+ if (FS.isMountpoint(node)) {
+ throw new FS.ErrnoError(10);
+ }
+
+ if (!FS.isDir(node.mode)) {
+ throw new FS.ErrnoError(54);
+ }
+ }
+
+ var mount = {
+ type: type,
+ opts: opts,
+ mountpoint: mountpoint,
+ mounts: []
+ };
+
+ // create a root node for the fs
+ var mountRoot = type.mount(mount);
+ mountRoot.mount = mount;
+ mount.root = mountRoot;
+
+ if (root) {
+ FS.root = mountRoot;
+ } else if (node) {
+ // set as a mountpoint
+ node.mounted = mount;
+
+ // add the new mount to the current mount's children
+ if (node.mount) {
+ node.mount.mounts.push(mount);
+ }
+ }
+
+ return mountRoot;
+ },unmount:function (mountpoint) {
+ var lookup = FS.lookupPath(mountpoint, { follow_mount: false });
+
+ if (!FS.isMountpoint(lookup.node)) {
+ throw new FS.ErrnoError(28);
+ }
+
+ // destroy the nodes for this mount, and all its child mounts
+ var node = lookup.node;
+ var mount = node.mounted;
+ var mounts = FS.getMounts(mount);
+
+ Object.keys(FS.nameTable).forEach(function (hash) {
+ var current = FS.nameTable[hash];
+
+ while (current) {
+ var next = current.name_next;
+
+ if (mounts.indexOf(current.mount) !== -1) {
+ FS.destroyNode(current);
+ }
+
+ current = next;
+ }
+ });
+
+ // no longer a mountpoint
+ node.mounted = null;
+
+ // remove this mount from the child mounts
+ var idx = node.mount.mounts.indexOf(mount);
+ node.mount.mounts.splice(idx, 1);
+ },lookup:function(parent, name) {
+ return parent.node_ops.lookup(parent, name);
+ },mknod:function(path, mode, dev) {
+ var lookup = FS.lookupPath(path, { parent: true });
+ var parent = lookup.node;
+ var name = PATH.basename(path);
+ if (!name || name === '.' || name === '..') {
+ throw new FS.ErrnoError(28);
+ }
+ var errCode = FS.mayCreate(parent, name);
+ if (errCode) {
+ throw new FS.ErrnoError(errCode);
+ }
+ if (!parent.node_ops.mknod) {
+ throw new FS.ErrnoError(63);
+ }
+ return parent.node_ops.mknod(parent, name, mode, dev);
+ },create:function(path, mode) {
+ mode = mode !== undefined ? mode : 438 /* 0666 */;
+ mode &= 4095;
+ mode |= 32768;
+ return FS.mknod(path, mode, 0);
+ },mkdir:function(path, mode) {
+ mode = mode !== undefined ? mode : 511 /* 0777 */;
+ mode &= 511 | 512;
+ mode |= 16384;
+ return FS.mknod(path, mode, 0);
+ },mkdirTree:function(path, mode) {
+ var dirs = path.split('/');
+ var d = '';
+ for (var i = 0; i < dirs.length; ++i) {
+ if (!dirs[i]) continue;
+ d += '/' + dirs[i];
+ try {
+ FS.mkdir(d, mode);
+ } catch(e) {
+ if (e.errno != 20) throw e;
+ }
+ }
+ },mkdev:function(path, mode, dev) {
+ if (typeof(dev) === 'undefined') {
+ dev = mode;
+ mode = 438 /* 0666 */;
+ }
+ mode |= 8192;
+ return FS.mknod(path, mode, dev);
+ },symlink:function(oldpath, newpath) {
+ if (!PATH_FS.resolve(oldpath)) {
+ throw new FS.ErrnoError(44);
+ }
+ var lookup = FS.lookupPath(newpath, { parent: true });
+ var parent = lookup.node;
+ if (!parent) {
+ throw new FS.ErrnoError(44);
+ }
+ var newname = PATH.basename(newpath);
+ var errCode = FS.mayCreate(parent, newname);
+ if (errCode) {
+ throw new FS.ErrnoError(errCode);
+ }
+ if (!parent.node_ops.symlink) {
+ throw new FS.ErrnoError(63);
+ }
+ return parent.node_ops.symlink(parent, newname, oldpath);
+ },rename:function(old_path, new_path) {
+ var old_dirname = PATH.dirname(old_path);
+ var new_dirname = PATH.dirname(new_path);
+ var old_name = PATH.basename(old_path);
+ var new_name = PATH.basename(new_path);
+ // parents must exist
+ var lookup, old_dir, new_dir;
+
+ // let the errors from non existant directories percolate up
+ lookup = FS.lookupPath(old_path, { parent: true });
+ old_dir = lookup.node;
+ lookup = FS.lookupPath(new_path, { parent: true });
+ new_dir = lookup.node;
+
+ if (!old_dir || !new_dir) throw new FS.ErrnoError(44);
+ // need to be part of the same mount
+ if (old_dir.mount !== new_dir.mount) {
+ throw new FS.ErrnoError(75);
+ }
+ // source must exist
+ var old_node = FS.lookupNode(old_dir, old_name);
+ // old path should not be an ancestor of the new path
+ var relative = PATH_FS.relative(old_path, new_dirname);
+ if (relative.charAt(0) !== '.') {
+ throw new FS.ErrnoError(28);
+ }
+ // new path should not be an ancestor of the old path
+ relative = PATH_FS.relative(new_path, old_dirname);
+ if (relative.charAt(0) !== '.') {
+ throw new FS.ErrnoError(55);
+ }
+ // see if the new path already exists
+ var new_node;
+ try {
+ new_node = FS.lookupNode(new_dir, new_name);
+ } catch (e) {
+ // not fatal
+ }
+ // early out if nothing needs to change
+ if (old_node === new_node) {
+ return;
+ }
+ // we'll need to delete the old entry
+ var isdir = FS.isDir(old_node.mode);
+ var errCode = FS.mayDelete(old_dir, old_name, isdir);
+ if (errCode) {
+ throw new FS.ErrnoError(errCode);
+ }
+ // need delete permissions if we'll be overwriting.
+ // need create permissions if new doesn't already exist.
+ errCode = new_node ?
+ FS.mayDelete(new_dir, new_name, isdir) :
+ FS.mayCreate(new_dir, new_name);
+ if (errCode) {
+ throw new FS.ErrnoError(errCode);
+ }
+ if (!old_dir.node_ops.rename) {
+ throw new FS.ErrnoError(63);
+ }
+ if (FS.isMountpoint(old_node) || (new_node && FS.isMountpoint(new_node))) {
+ throw new FS.ErrnoError(10);
+ }
+ // if we are going to change the parent, check write permissions
+ if (new_dir !== old_dir) {
+ errCode = FS.nodePermissions(old_dir, 'w');
+ if (errCode) {
+ throw new FS.ErrnoError(errCode);
+ }
+ }
+ try {
+ if (FS.trackingDelegate['willMovePath']) {
+ FS.trackingDelegate['willMovePath'](old_path, new_path);
+ }
+ } catch(e) {
+ err("FS.trackingDelegate['willMovePath']('"+old_path+"', '"+new_path+"') threw an exception: " + e.message);
+ }
+ // remove the node from the lookup hash
+ FS.hashRemoveNode(old_node);
+ // do the underlying fs rename
+ try {
+ old_dir.node_ops.rename(old_node, new_dir, new_name);
+ } catch (e) {
+ throw e;
+ } finally {
+ // add the node back to the hash (in case node_ops.rename
+ // changed its name)
+ FS.hashAddNode(old_node);
+ }
+ try {
+ if (FS.trackingDelegate['onMovePath']) FS.trackingDelegate['onMovePath'](old_path, new_path);
+ } catch(e) {
+ err("FS.trackingDelegate['onMovePath']('"+old_path+"', '"+new_path+"') threw an exception: " + e.message);
+ }
+ },rmdir:function(path) {
+ var lookup = FS.lookupPath(path, { parent: true });
+ var parent = lookup.node;
+ var name = PATH.basename(path);
+ var node = FS.lookupNode(parent, name);
+ var errCode = FS.mayDelete(parent, name, true);
+ if (errCode) {
+ throw new FS.ErrnoError(errCode);
+ }
+ if (!parent.node_ops.rmdir) {
+ throw new FS.ErrnoError(63);
+ }
+ if (FS.isMountpoint(node)) {
+ throw new FS.ErrnoError(10);
+ }
+ try {
+ if (FS.trackingDelegate['willDeletePath']) {
+ FS.trackingDelegate['willDeletePath'](path);
+ }
+ } catch(e) {
+ err("FS.trackingDelegate['willDeletePath']('"+path+"') threw an exception: " + e.message);
+ }
+ parent.node_ops.rmdir(parent, name);
+ FS.destroyNode(node);
+ try {
+ if (FS.trackingDelegate['onDeletePath']) FS.trackingDelegate['onDeletePath'](path);
+ } catch(e) {
+ err("FS.trackingDelegate['onDeletePath']('"+path+"') threw an exception: " + e.message);
+ }
+ },readdir:function(path) {
+ var lookup = FS.lookupPath(path, { follow: true });
+ var node = lookup.node;
+ if (!node.node_ops.readdir) {
+ throw new FS.ErrnoError(54);
+ }
+ return node.node_ops.readdir(node);
+ },unlink:function(path) {
+ var lookup = FS.lookupPath(path, { parent: true });
+ var parent = lookup.node;
+ var name = PATH.basename(path);
+ var node = FS.lookupNode(parent, name);
+ var errCode = FS.mayDelete(parent, name, false);
+ if (errCode) {
+ // According to POSIX, we should map EISDIR to EPERM, but
+ // we instead do what Linux does (and we must, as we use
+ // the musl linux libc).
+ throw new FS.ErrnoError(errCode);
+ }
+ if (!parent.node_ops.unlink) {
+ throw new FS.ErrnoError(63);
+ }
+ if (FS.isMountpoint(node)) {
+ throw new FS.ErrnoError(10);
+ }
+ try {
+ if (FS.trackingDelegate['willDeletePath']) {
+ FS.trackingDelegate['willDeletePath'](path);
+ }
+ } catch(e) {
+ err("FS.trackingDelegate['willDeletePath']('"+path+"') threw an exception: " + e.message);
+ }
+ parent.node_ops.unlink(parent, name);
+ FS.destroyNode(node);
+ try {
+ if (FS.trackingDelegate['onDeletePath']) FS.trackingDelegate['onDeletePath'](path);
+ } catch(e) {
+ err("FS.trackingDelegate['onDeletePath']('"+path+"') threw an exception: " + e.message);
+ }
+ },readlink:function(path) {
+ var lookup = FS.lookupPath(path);
+ var link = lookup.node;
+ if (!link) {
+ throw new FS.ErrnoError(44);
+ }
+ if (!link.node_ops.readlink) {
+ throw new FS.ErrnoError(28);
+ }
+ return PATH_FS.resolve(FS.getPath(link.parent), link.node_ops.readlink(link));
+ },stat:function(path, dontFollow) {
+ var lookup = FS.lookupPath(path, { follow: !dontFollow });
+ var node = lookup.node;
+ if (!node) {
+ throw new FS.ErrnoError(44);
+ }
+ if (!node.node_ops.getattr) {
+ throw new FS.ErrnoError(63);
+ }
+ return node.node_ops.getattr(node);
+ },lstat:function(path) {
+ return FS.stat(path, true);
+ },chmod:function(path, mode, dontFollow) {
+ var node;
+ if (typeof path === 'string') {
+ var lookup = FS.lookupPath(path, { follow: !dontFollow });
+ node = lookup.node;
+ } else {
+ node = path;
+ }
+ if (!node.node_ops.setattr) {
+ throw new FS.ErrnoError(63);
+ }
+ node.node_ops.setattr(node, {
+ mode: (mode & 4095) | (node.mode & ~4095),
+ timestamp: Date.now()
+ });
+ },lchmod:function(path, mode) {
+ FS.chmod(path, mode, true);
+ },fchmod:function(fd, mode) {
+ var stream = FS.getStream(fd);
+ if (!stream) {
+ throw new FS.ErrnoError(8);
+ }
+ FS.chmod(stream.node, mode);
+ },chown:function(path, uid, gid, dontFollow) {
+ var node;
+ if (typeof path === 'string') {
+ var lookup = FS.lookupPath(path, { follow: !dontFollow });
+ node = lookup.node;
+ } else {
+ node = path;
+ }
+ if (!node.node_ops.setattr) {
+ throw new FS.ErrnoError(63);
+ }
+ node.node_ops.setattr(node, {
+ timestamp: Date.now()
+ // we ignore the uid / gid for now
+ });
+ },lchown:function(path, uid, gid) {
+ FS.chown(path, uid, gid, true);
+ },fchown:function(fd, uid, gid) {
+ var stream = FS.getStream(fd);
+ if (!stream) {
+ throw new FS.ErrnoError(8);
+ }
+ FS.chown(stream.node, uid, gid);
+ },truncate:function(path, len) {
+ if (len < 0) {
+ throw new FS.ErrnoError(28);
+ }
+ var node;
+ if (typeof path === 'string') {
+ var lookup = FS.lookupPath(path, { follow: true });
+ node = lookup.node;
+ } else {
+ node = path;
+ }
+ if (!node.node_ops.setattr) {
+ throw new FS.ErrnoError(63);
+ }
+ if (FS.isDir(node.mode)) {
+ throw new FS.ErrnoError(31);
+ }
+ if (!FS.isFile(node.mode)) {
+ throw new FS.ErrnoError(28);
+ }
+ var errCode = FS.nodePermissions(node, 'w');
+ if (errCode) {
+ throw new FS.ErrnoError(errCode);
+ }
+ node.node_ops.setattr(node, {
+ size: len,
+ timestamp: Date.now()
+ });
+ },ftruncate:function(fd, len) {
+ var stream = FS.getStream(fd);
+ if (!stream) {
+ throw new FS.ErrnoError(8);
+ }
+ if ((stream.flags & 2097155) === 0) {
+ throw new FS.ErrnoError(28);
+ }
+ FS.truncate(stream.node, len);
+ },utime:function(path, atime, mtime) {
+ var lookup = FS.lookupPath(path, { follow: true });
+ var node = lookup.node;
+ node.node_ops.setattr(node, {
+ timestamp: Math.max(atime, mtime)
+ });
+ },open:function(path, flags, mode, fd_start, fd_end) {
+ if (path === "") {
+ throw new FS.ErrnoError(44);
+ }
+ flags = typeof flags === 'string' ? FS.modeStringToFlags(flags) : flags;
+ mode = typeof mode === 'undefined' ? 438 /* 0666 */ : mode;
+ if ((flags & 64)) {
+ mode = (mode & 4095) | 32768;
+ } else {
+ mode = 0;
+ }
+ var node;
+ if (typeof path === 'object') {
+ node = path;
+ } else {
+ path = PATH.normalize(path);
+ try {
+ var lookup = FS.lookupPath(path, {
+ follow: !(flags & 131072)
+ });
+ node = lookup.node;
+ } catch (e) {
+ // ignore
+ }
+ }
+ // perhaps we need to create the node
+ var created = false;
+ if ((flags & 64)) {
+ if (node) {
+ // if O_CREAT and O_EXCL are set, error out if the node already exists
+ if ((flags & 128)) {
+ throw new FS.ErrnoError(20);
+ }
+ } else {
+ // node doesn't exist, try to create it
+ node = FS.mknod(path, mode, 0);
+ created = true;
+ }
+ }
+ if (!node) {
+ throw new FS.ErrnoError(44);
+ }
+ // can't truncate a device
+ if (FS.isChrdev(node.mode)) {
+ flags &= ~512;
+ }
+ // if asked only for a directory, then this must be one
+ if ((flags & 65536) && !FS.isDir(node.mode)) {
+ throw new FS.ErrnoError(54);
+ }
+ // check permissions, if this is not a file we just created now (it is ok to
+ // create and write to a file with read-only permissions; it is read-only
+ // for later use)
+ if (!created) {
+ var errCode = FS.mayOpen(node, flags);
+ if (errCode) {
+ throw new FS.ErrnoError(errCode);
+ }
+ }
+ // do truncation if necessary
+ if ((flags & 512)) {
+ FS.truncate(node, 0);
+ }
+ // we've already handled these, don't pass down to the underlying vfs
+ flags &= ~(128 | 512 | 131072);
+
+ // register the stream with the filesystem
+ var stream = FS.createStream({
+ node: node,
+ path: FS.getPath(node), // we want the absolute path to the node
+ flags: flags,
+ seekable: true,
+ position: 0,
+ stream_ops: node.stream_ops,
+ // used by the file family libc calls (fopen, fwrite, ferror, etc.)
+ ungotten: [],
+ error: false
+ }, fd_start, fd_end);
+ // call the new stream's open function
+ if (stream.stream_ops.open) {
+ stream.stream_ops.open(stream);
+ }
+ if (Module['logReadFiles'] && !(flags & 1)) {
+ if (!FS.readFiles) FS.readFiles = {};
+ if (!(path in FS.readFiles)) {
+ FS.readFiles[path] = 1;
+ err("FS.trackingDelegate error on read file: " + path);
+ }
+ }
+ try {
+ if (FS.trackingDelegate['onOpenFile']) {
+ var trackingFlags = 0;
+ if ((flags & 2097155) !== 1) {
+ trackingFlags |= FS.tracking.openFlags.READ;
+ }
+ if ((flags & 2097155) !== 0) {
+ trackingFlags |= FS.tracking.openFlags.WRITE;
+ }
+ FS.trackingDelegate['onOpenFile'](path, trackingFlags);
+ }
+ } catch(e) {
+ err("FS.trackingDelegate['onOpenFile']('"+path+"', flags) threw an exception: " + e.message);
+ }
+ return stream;
+ },close:function(stream) {
+ if (FS.isClosed(stream)) {
+ throw new FS.ErrnoError(8);
+ }
+ if (stream.getdents) stream.getdents = null; // free readdir state
+ try {
+ if (stream.stream_ops.close) {
+ stream.stream_ops.close(stream);
+ }
+ } catch (e) {
+ throw e;
+ } finally {
+ FS.closeStream(stream.fd);
+ }
+ stream.fd = null;
+ },isClosed:function(stream) {
+ return stream.fd === null;
+ },llseek:function(stream, offset, whence) {
+ if (FS.isClosed(stream)) {
+ throw new FS.ErrnoError(8);
+ }
+ if (!stream.seekable || !stream.stream_ops.llseek) {
+ throw new FS.ErrnoError(70);
+ }
+ if (whence != 0 && whence != 1 && whence != 2) {
+ throw new FS.ErrnoError(28);
+ }
+ stream.position = stream.stream_ops.llseek(stream, offset, whence);
+ stream.ungotten = [];
+ return stream.position;
+ },read:function(stream, buffer, offset, length, position) {
+ if (length < 0 || position < 0) {
+ throw new FS.ErrnoError(28);
+ }
+ if (FS.isClosed(stream)) {
+ throw new FS.ErrnoError(8);
+ }
+ if ((stream.flags & 2097155) === 1) {
+ throw new FS.ErrnoError(8);
+ }
+ if (FS.isDir(stream.node.mode)) {
+ throw new FS.ErrnoError(31);
+ }
+ if (!stream.stream_ops.read) {
+ throw new FS.ErrnoError(28);
+ }
+ var seeking = typeof position !== 'undefined';
+ if (!seeking) {
+ position = stream.position;
+ } else if (!stream.seekable) {
+ throw new FS.ErrnoError(70);
+ }
+ var bytesRead = stream.stream_ops.read(stream, buffer, offset, length, position);
+ if (!seeking) stream.position += bytesRead;
+ return bytesRead;
+ },write:function(stream, buffer, offset, length, position, canOwn) {
+ if (length < 0 || position < 0) {
+ throw new FS.ErrnoError(28);
+ }
+ if (FS.isClosed(stream)) {
+ throw new FS.ErrnoError(8);
+ }
+ if ((stream.flags & 2097155) === 0) {
+ throw new FS.ErrnoError(8);
+ }
+ if (FS.isDir(stream.node.mode)) {
+ throw new FS.ErrnoError(31);
+ }
+ if (!stream.stream_ops.write) {
+ throw new FS.ErrnoError(28);
+ }
+ if (stream.seekable && stream.flags & 1024) {
+ // seek to the end before writing in append mode
+ FS.llseek(stream, 0, 2);
+ }
+ var seeking = typeof position !== 'undefined';
+ if (!seeking) {
+ position = stream.position;
+ } else if (!stream.seekable) {
+ throw new FS.ErrnoError(70);
+ }
+ var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position, canOwn);
+ if (!seeking) stream.position += bytesWritten;
+ try {
+ if (stream.path && FS.trackingDelegate['onWriteToFile']) FS.trackingDelegate['onWriteToFile'](stream.path);
+ } catch(e) {
+ err("FS.trackingDelegate['onWriteToFile']('"+stream.path+"') threw an exception: " + e.message);
+ }
+ return bytesWritten;
+ },allocate:function(stream, offset, length) {
+ if (FS.isClosed(stream)) {
+ throw new FS.ErrnoError(8);
+ }
+ if (offset < 0 || length <= 0) {
+ throw new FS.ErrnoError(28);
+ }
+ if ((stream.flags & 2097155) === 0) {
+ throw new FS.ErrnoError(8);
+ }
+ if (!FS.isFile(stream.node.mode) && !FS.isDir(stream.node.mode)) {
+ throw new FS.ErrnoError(43);
+ }
+ if (!stream.stream_ops.allocate) {
+ throw new FS.ErrnoError(138);
+ }
+ stream.stream_ops.allocate(stream, offset, length);
+ },mmap:function(stream, address, length, position, prot, flags) {
+ // User requests writing to file (prot & PROT_WRITE != 0).
+ // Checking if we have permissions to write to the file unless
+ // MAP_PRIVATE flag is set. According to POSIX spec it is possible
+ // to write to file opened in read-only mode with MAP_PRIVATE flag,
+ // as all modifications will be visible only in the memory of
+ // the current process.
+ if ((prot & 2) !== 0
+ && (flags & 2) === 0
+ && (stream.flags & 2097155) !== 2) {
+ throw new FS.ErrnoError(2);
+ }
+ if ((stream.flags & 2097155) === 1) {
+ throw new FS.ErrnoError(2);
+ }
+ if (!stream.stream_ops.mmap) {
+ throw new FS.ErrnoError(43);
+ }
+ return stream.stream_ops.mmap(stream, address, length, position, prot, flags);
+ },msync:function(stream, buffer, offset, length, mmapFlags) {
+ if (!stream || !stream.stream_ops.msync) {
+ return 0;
+ }
+ return stream.stream_ops.msync(stream, buffer, offset, length, mmapFlags);
+ },munmap:function(stream) {
+ return 0;
+ },ioctl:function(stream, cmd, arg) {
+ if (!stream.stream_ops.ioctl) {
+ throw new FS.ErrnoError(59);
+ }
+ return stream.stream_ops.ioctl(stream, cmd, arg);
+ },readFile:function(path, opts) {
+ opts = opts || {};
+ opts.flags = opts.flags || 'r';
+ opts.encoding = opts.encoding || 'binary';
+ if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') {
+ throw new Error('Invalid encoding type "' + opts.encoding + '"');
+ }
+ var ret;
+ var stream = FS.open(path, opts.flags);
+ var stat = FS.stat(path);
+ var length = stat.size;
+ var buf = new Uint8Array(length);
+ FS.read(stream, buf, 0, length, 0);
+ if (opts.encoding === 'utf8') {
+ ret = UTF8ArrayToString(buf, 0);
+ } else if (opts.encoding === 'binary') {
+ ret = buf;
+ }
+ FS.close(stream);
+ return ret;
+ },writeFile:function(path, data, opts) {
+ opts = opts || {};
+ opts.flags = opts.flags || 'w';
+ var stream = FS.open(path, opts.flags, opts.mode);
+ if (typeof data === 'string') {
+ var buf = new Uint8Array(lengthBytesUTF8(data)+1);
+ var actualNumBytes = stringToUTF8Array(data, buf, 0, buf.length);
+ FS.write(stream, buf, 0, actualNumBytes, undefined, opts.canOwn);
+ } else if (ArrayBuffer.isView(data)) {
+ FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn);
+ } else {
+ throw new Error('Unsupported data type');
+ }
+ FS.close(stream);
+ },cwd:function() {
+ return FS.currentPath;
+ },chdir:function(path) {
+ var lookup = FS.lookupPath(path, { follow: true });
+ if (lookup.node === null) {
+ throw new FS.ErrnoError(44);
+ }
+ if (!FS.isDir(lookup.node.mode)) {
+ throw new FS.ErrnoError(54);
+ }
+ var errCode = FS.nodePermissions(lookup.node, 'x');
+ if (errCode) {
+ throw new FS.ErrnoError(errCode);
+ }
+ FS.currentPath = lookup.path;
+ },createDefaultDirectories:function() {
+ FS.mkdir('/tmp');
+ FS.mkdir('/home');
+ FS.mkdir('/home/web_user');
+ },createDefaultDevices:function() {
+ // create /dev
+ FS.mkdir('/dev');
+ // setup /dev/null
+ FS.registerDevice(FS.makedev(1, 3), {
+ read: function() { return 0; },
+ write: function(stream, buffer, offset, length, pos) { return length; }
+ });
+ FS.mkdev('/dev/null', FS.makedev(1, 3));
+ // setup /dev/tty and /dev/tty1
+ // stderr needs to print output using Module['printErr']
+ // so we register a second tty just for it.
+ TTY.register(FS.makedev(5, 0), TTY.default_tty_ops);
+ TTY.register(FS.makedev(6, 0), TTY.default_tty1_ops);
+ FS.mkdev('/dev/tty', FS.makedev(5, 0));
+ FS.mkdev('/dev/tty1', FS.makedev(6, 0));
+ // setup /dev/[u]random
+ var random_device;
+ if (typeof crypto === 'object' && typeof crypto['getRandomValues'] === 'function') {
+ // for modern web browsers
+ var randomBuffer = new Uint8Array(1);
+ random_device = function() { crypto.getRandomValues(randomBuffer); return randomBuffer[0]; };
+ } else
+ if (ENVIRONMENT_IS_NODE) {
+ // for nodejs with or without crypto support included
+ try {
+ var crypto_module = require('crypto');
+ // nodejs has crypto support
+ random_device = function() { return crypto_module['randomBytes'](1)[0]; };
+ } catch (e) {
+ // nodejs doesn't have crypto support
+ }
+ } else
+ {}
+ if (!random_device) {
+ // we couldn't find a proper implementation, as Math.random() is not suitable for /dev/random, see emscripten-core/emscripten/pull/7096
+ random_device = function() { abort("random_device"); };
+ }
+ FS.createDevice('/dev', 'random', random_device);
+ FS.createDevice('/dev', 'urandom', random_device);
+ // we're not going to emulate the actual shm device,
+ // just create the tmp dirs that reside in it commonly
+ FS.mkdir('/dev/shm');
+ FS.mkdir('/dev/shm/tmp');
+ },createSpecialDirectories:function() {
+ // create /proc/self/fd which allows /proc/self/fd/6 => readlink gives the name of the stream for fd 6 (see test_unistd_ttyname)
+ FS.mkdir('/proc');
+ FS.mkdir('/proc/self');
+ FS.mkdir('/proc/self/fd');
+ FS.mount({
+ mount: function() {
+ var node = FS.createNode('/proc/self', 'fd', 16384 | 511 /* 0777 */, 73);
+ node.node_ops = {
+ lookup: function(parent, name) {
+ var fd = +name;
+ var stream = FS.getStream(fd);
+ if (!stream) throw new FS.ErrnoError(8);
+ var ret = {
+ parent: null,
+ mount: { mountpoint: 'fake' },
+ node_ops: { readlink: function() { return stream.path } }
+ };
+ ret.parent = ret; // make it look like a simple root node
+ return ret;
+ }
+ };
+ return node;
+ }
+ }, {}, '/proc/self/fd');
+ },createStandardStreams:function() {
+ // TODO deprecate the old functionality of a single
+ // input / output callback and that utilizes FS.createDevice
+ // and instead require a unique set of stream ops
+
+ // by default, we symlink the standard streams to the
+ // default tty devices. however, if the standard streams
+ // have been overwritten we create a unique device for
+ // them instead.
+ if (Module['stdin']) {
+ FS.createDevice('/dev', 'stdin', Module['stdin']);
+ } else {
+ FS.symlink('/dev/tty', '/dev/stdin');
+ }
+ if (Module['stdout']) {
+ FS.createDevice('/dev', 'stdout', null, Module['stdout']);
+ } else {
+ FS.symlink('/dev/tty', '/dev/stdout');
+ }
+ if (Module['stderr']) {
+ FS.createDevice('/dev', 'stderr', null, Module['stderr']);
+ } else {
+ FS.symlink('/dev/tty1', '/dev/stderr');
+ }
+
+ // open default streams for the stdin, stdout and stderr devices
+ var stdin = FS.open('/dev/stdin', 'r');
+ var stdout = FS.open('/dev/stdout', 'w');
+ var stderr = FS.open('/dev/stderr', 'w');
+ },ensureErrnoError:function() {
+ if (FS.ErrnoError) return;
+ FS.ErrnoError = /** @this{Object} */ function ErrnoError(errno, node) {
+ this.node = node;
+ this.setErrno = /** @this{Object} */ function(errno) {
+ this.errno = errno;
+ };
+ this.setErrno(errno);
+ this.message = 'FS error';
+
+ };
+ FS.ErrnoError.prototype = new Error();
+ FS.ErrnoError.prototype.constructor = FS.ErrnoError;
+ // Some errors may happen quite a bit, to avoid overhead we reuse them (and suffer a lack of stack info)
+ [44].forEach(function(code) {
+ FS.genericErrors[code] = new FS.ErrnoError(code);
+ FS.genericErrors[code].stack = '<generic error, no stack>';
+ });
+ },staticInit:function() {
+ FS.ensureErrnoError();
+
+ FS.nameTable = new Array(4096);
+
+ FS.mount(MEMFS, {}, '/');
+
+ FS.createDefaultDirectories();
+ FS.createDefaultDevices();
+ FS.createSpecialDirectories();
+
+ FS.filesystems = {
+ 'MEMFS': MEMFS,
+ };
+ },init:function(input, output, error) {
+ FS.init.initialized = true;
+
+ FS.ensureErrnoError();
+
+ // Allow Module.stdin etc. to provide defaults, if none explicitly passed to us here
+ Module['stdin'] = input || Module['stdin'];
+ Module['stdout'] = output || Module['stdout'];
+ Module['stderr'] = error || Module['stderr'];
+
+ FS.createStandardStreams();
+ },quit:function() {
+ FS.init.initialized = false;
+ // force-flush all streams, so we get musl std streams printed out
+ var fflush = Module['_fflush'];
+ if (fflush) fflush(0);
+ // close all of our streams
+ for (var i = 0; i < FS.streams.length; i++) {
+ var stream = FS.streams[i];
+ if (!stream) {
+ continue;
+ }
+ FS.close(stream);
+ }
+ },getMode:function(canRead, canWrite) {
+ var mode = 0;
+ if (canRead) mode |= 292 | 73;
+ if (canWrite) mode |= 146;
+ return mode;
+ },joinPath:function(parts, forceRelative) {
+ var path = PATH.join.apply(null, parts);
+ if (forceRelative && path[0] == '/') path = path.substr(1);
+ return path;
+ },absolutePath:function(relative, base) {
+ return PATH_FS.resolve(base, relative);
+ },standardizePath:function(path) {
+ return PATH.normalize(path);
+ },findObject:function(path, dontResolveLastLink) {
+ var ret = FS.analyzePath(path, dontResolveLastLink);
+ if (ret.exists) {
+ return ret.object;
+ } else {
+ setErrNo(ret.error);
+ return null;
+ }
+ },analyzePath:function(path, dontResolveLastLink) {
+ // operate from within the context of the symlink's target
+ try {
+ var lookup = FS.lookupPath(path, { follow: !dontResolveLastLink });
+ path = lookup.path;
+ } catch (e) {
+ }
+ var ret = {
+ isRoot: false, exists: false, error: 0, name: null, path: null, object: null,
+ parentExists: false, parentPath: null, parentObject: null
+ };
+ try {
+ var lookup = FS.lookupPath(path, { parent: true });
+ ret.parentExists = true;
+ ret.parentPath = lookup.path;
+ ret.parentObject = lookup.node;
+ ret.name = PATH.basename(path);
+ lookup = FS.lookupPath(path, { follow: !dontResolveLastLink });
+ ret.exists = true;
+ ret.path = lookup.path;
+ ret.object = lookup.node;
+ ret.name = lookup.node.name;
+ ret.isRoot = lookup.path === '/';
+ } catch (e) {
+ ret.error = e.errno;
+ };
+ return ret;
+ },createFolder:function(parent, name, canRead, canWrite) {
+ var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name);
+ var mode = FS.getMode(canRead, canWrite);
+ return FS.mkdir(path, mode);
+ },createPath:function(parent, path, canRead, canWrite) {
+ parent = typeof parent === 'string' ? parent : FS.getPath(parent);
+ var parts = path.split('/').reverse();
+ while (parts.length) {
+ var part = parts.pop();
+ if (!part) continue;
+ var current = PATH.join2(parent, part);
+ try {
+ FS.mkdir(current);
+ } catch (e) {
+ // ignore EEXIST
+ }
+ parent = current;
+ }
+ return current;
+ },createFile:function(parent, name, properties, canRead, canWrite) {
+ var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name);
+ var mode = FS.getMode(canRead, canWrite);
+ return FS.create(path, mode);
+ },createDataFile:function(parent, name, data, canRead, canWrite, canOwn) {
+ var path = name ? PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name) : parent;
+ var mode = FS.getMode(canRead, canWrite);
+ var node = FS.create(path, mode);
+ if (data) {
+ if (typeof data === 'string') {
+ var arr = new Array(data.length);
+ for (var i = 0, len = data.length; i < len; ++i) arr[i] = data.charCodeAt(i);
+ data = arr;
+ }
+ // make sure we can write to the file
+ FS.chmod(node, mode | 146);
+ var stream = FS.open(node, 'w');
+ FS.write(stream, data, 0, data.length, 0, canOwn);
+ FS.close(stream);
+ FS.chmod(node, mode);
+ }
+ return node;
+ },createDevice:function(parent, name, input, output) {
+ var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name);
+ var mode = FS.getMode(!!input, !!output);
+ if (!FS.createDevice.major) FS.createDevice.major = 64;
+ var dev = FS.makedev(FS.createDevice.major++, 0);
+ // Create a fake device that a set of stream ops to emulate
+ // the old behavior.
+ FS.registerDevice(dev, {
+ open: function(stream) {
+ stream.seekable = false;
+ },
+ close: function(stream) {
+ // flush any pending line data
+ if (output && output.buffer && output.buffer.length) {
+ output(10);
+ }
+ },
+ read: function(stream, buffer, offset, length, pos /* ignored */) {
+ var bytesRead = 0;
+ for (var i = 0; i < length; i++) {
+ var result;
+ try {
+ result = input();
+ } catch (e) {
+ throw new FS.ErrnoError(29);
+ }
+ if (result === undefined && bytesRead === 0) {
+ throw new FS.ErrnoError(6);
+ }
+ if (result === null || result === undefined) break;
+ bytesRead++;
+ buffer[offset+i] = result;
+ }
+ if (bytesRead) {
+ stream.node.timestamp = Date.now();
+ }
+ return bytesRead;
+ },
+ write: function(stream, buffer, offset, length, pos) {
+ for (var i = 0; i < length; i++) {
+ try {
+ output(buffer[offset+i]);
+ } catch (e) {
+ throw new FS.ErrnoError(29);
+ }
+ }
+ if (length) {
+ stream.node.timestamp = Date.now();
+ }
+ return i;
+ }
+ });
+ return FS.mkdev(path, mode, dev);
+ },createLink:function(parent, name, target, canRead, canWrite) {
+ var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name);
+ return FS.symlink(target, path);
+ },forceLoadFile:function(obj) {
+ if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true;
+ var success = true;
+ if (typeof XMLHttpRequest !== 'undefined') {
+ 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.");
+ } else if (read_) {
+ // Command-line.
+ try {
+ // WARNING: Can't read binary files in V8's d8 or tracemonkey's js, as
+ // read() will try to parse UTF8.
+ obj.contents = intArrayFromString(read_(obj.url), true);
+ obj.usedBytes = obj.contents.length;
+ } catch (e) {
+ success = false;
+ }
+ } else {
+ throw new Error('Cannot load without read() or XMLHttpRequest.');
+ }
+ if (!success) setErrNo(29);
+ return success;
+ },createLazyFile:function(parent, name, url, canRead, canWrite) {
+ // Lazy chunked Uint8Array (implements get and length from Uint8Array). Actual getting is abstracted away for eventual reuse.
+ /** @constructor */
+ function LazyUint8Array() {
+ this.lengthKnown = false;
+ this.chunks = []; // Loaded chunks. Index is the chunk number
+ }
+ LazyUint8Array.prototype.get = /** @this{Object} */ function LazyUint8Array_get(idx) {
+ if (idx > this.length-1 || idx < 0) {
+ return undefined;
+ }
+ var chunkOffset = idx % this.chunkSize;
+ var chunkNum = (idx / this.chunkSize)|0;
+ return this.getter(chunkNum)[chunkOffset];
+ };
+ LazyUint8Array.prototype.setDataGetter = function LazyUint8Array_setDataGetter(getter) {
+ this.getter = getter;
+ };
+ LazyUint8Array.prototype.cacheLength = function LazyUint8Array_cacheLength() {
+ // Find length
+ var xhr = new XMLHttpRequest();
+ xhr.open('HEAD', url, false);
+ xhr.send(null);
+ if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status);
+ var datalength = Number(xhr.getResponseHeader("Content-length"));
+ var header;
+ var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes";
+ var usesGzip = (header = xhr.getResponseHeader("Content-Encoding")) && header === "gzip";
+
+ var chunkSize = 1024*1024; // Chunk size in bytes
+
+ if (!hasByteServing) chunkSize = datalength;
+
+ // Function to get a range from the remote URL.
+ var doXHR = (function(from, to) {
+ if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!");
+ if (to > datalength-1) throw new Error("only " + datalength + " bytes available! programmer error!");
+
+ // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available.
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', url, false);
+ if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to);
+
+ // Some hints to the browser that we want binary data.
+ if (typeof Uint8Array != 'undefined') xhr.responseType = 'arraybuffer';
+ if (xhr.overrideMimeType) {
+ xhr.overrideMimeType('text/plain; charset=x-user-defined');
+ }
+
+ xhr.send(null);
+ if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status);
+ if (xhr.response !== undefined) {
+ return new Uint8Array(/** @type{Array<number>} */(xhr.response || []));
+ } else {
+ return intArrayFromString(xhr.responseText || '', true);
+ }
+ });
+ var lazyArray = this;
+ lazyArray.setDataGetter(function(chunkNum) {
+ var start = chunkNum * chunkSize;
+ var end = (chunkNum+1) * chunkSize - 1; // including this byte
+ end = Math.min(end, datalength-1); // if datalength-1 is selected, this is the last block
+ if (typeof(lazyArray.chunks[chunkNum]) === "undefined") {
+ lazyArray.chunks[chunkNum] = doXHR(start, end);
+ }
+ if (typeof(lazyArray.chunks[chunkNum]) === "undefined") throw new Error("doXHR failed!");
+ return lazyArray.chunks[chunkNum];
+ });
+
+ if (usesGzip || !datalength) {
+ // if the server uses gzip or doesn't supply the length, we have to download the whole file to get the (uncompressed) length
+ chunkSize = datalength = 1; // this will force getter(0)/doXHR do download the whole file
+ datalength = this.getter(0).length;
+ chunkSize = datalength;
+ out("LazyFiles on gzip forces download of the whole file when length is accessed");
+ }
+
+ this._length = datalength;
+ this._chunkSize = chunkSize;
+ this.lengthKnown = true;
+ };
+ if (typeof XMLHttpRequest !== 'undefined') {
+ if (!ENVIRONMENT_IS_WORKER) throw 'Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc';
+ var lazyArray = new LazyUint8Array();
+ Object.defineProperties(lazyArray, {
+ length: {
+ get: /** @this{Object} */ function() {
+ if(!this.lengthKnown) {
+ this.cacheLength();
+ }
+ return this._length;
+ }
+ },
+ chunkSize: {
+ get: /** @this{Object} */ function() {
+ if(!this.lengthKnown) {
+ this.cacheLength();
+ }
+ return this._chunkSize;
+ }
+ }
+ });
+
+ var properties = { isDevice: false, contents: lazyArray };
+ } else {
+ var properties = { isDevice: false, url: url };
+ }
+
+ var node = FS.createFile(parent, name, properties, canRead, canWrite);
+ // This is a total hack, but I want to get this lazy file code out of the
+ // core of MEMFS. If we want to keep this lazy file concept I feel it should
+ // be its own thin LAZYFS proxying calls to MEMFS.
+ if (properties.contents) {
+ node.contents = properties.contents;
+ } else if (properties.url) {
+ node.contents = null;
+ node.url = properties.url;
+ }
+ // Add a function that defers querying the file size until it is asked the first time.
+ Object.defineProperties(node, {
+ usedBytes: {
+ get: /** @this {FSNode} */ function() { return this.contents.length; }
+ }
+ });
+ // override each stream op with one that tries to force load the lazy file first
+ var stream_ops = {};
+ var keys = Object.keys(node.stream_ops);
+ keys.forEach(function(key) {
+ var fn = node.stream_ops[key];
+ stream_ops[key] = function forceLoadLazyFile() {
+ if (!FS.forceLoadFile(node)) {
+ throw new FS.ErrnoError(29);
+ }
+ return fn.apply(null, arguments);
+ };
+ });
+ // use a custom read function
+ stream_ops.read = function stream_ops_read(stream, buffer, offset, length, position) {
+ if (!FS.forceLoadFile(node)) {
+ throw new FS.ErrnoError(29);
+ }
+ var contents = stream.node.contents;
+ if (position >= contents.length)
+ return 0;
+ var size = Math.min(contents.length - position, length);
+ if (contents.slice) { // normal array
+ for (var i = 0; i < size; i++) {
+ buffer[offset + i] = contents[position + i];
+ }
+ } else {
+ for (var i = 0; i < size; i++) { // LazyUint8Array from sync binary XHR
+ buffer[offset + i] = contents.get(position + i);
+ }
+ }
+ return size;
+ };
+ node.stream_ops = stream_ops;
+ return node;
+ },createPreloadedFile:function(parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) {
+ Browser.init(); // XXX perhaps this method should move onto Browser?
+ // TODO we should allow people to just pass in a complete filename instead
+ // of parent and name being that we just join them anyways
+ var fullname = name ? PATH_FS.resolve(PATH.join2(parent, name)) : parent;
+ var dep = getUniqueRunDependency('cp ' + fullname); // might have several active requests for the same fullname
+ function processData(byteArray) {
+ function finish(byteArray) {
+ if (preFinish) preFinish();
+ if (!dontCreateFile) {
+ FS.createDataFile(parent, name, byteArray, canRead, canWrite, canOwn);
+ }
+ if (onload) onload();
+ removeRunDependency(dep);
+ }
+ var handled = false;
+ Module['preloadPlugins'].forEach(function(plugin) {
+ if (handled) return;
+ if (plugin['canHandle'](fullname)) {
+ plugin['handle'](byteArray, fullname, finish, function() {
+ if (onerror) onerror();
+ removeRunDependency(dep);
+ });
+ handled = true;
+ }
+ });
+ if (!handled) finish(byteArray);
+ }
+ addRunDependency(dep);
+ if (typeof url == 'string') {
+ Browser.asyncLoad(url, function(byteArray) {
+ processData(byteArray);
+ }, onerror);
+ } else {
+ processData(url);
+ }
+ },indexedDB:function() {
+ return window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
+ },DB_NAME:function() {
+ return 'EM_FS_' + window.location.pathname;
+ },DB_VERSION:20,DB_STORE_NAME:"FILE_DATA",saveFilesToDB:function(paths, onload, onerror) {
+ onload = onload || function(){};
+ onerror = onerror || function(){};
+ var indexedDB = FS.indexedDB();
+ try {
+ var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION);
+ } catch (e) {
+ return onerror(e);
+ }
+ openRequest.onupgradeneeded = function openRequest_onupgradeneeded() {
+ out('creating db');
+ var db = openRequest.result;
+ db.createObjectStore(FS.DB_STORE_NAME);
+ };
+ openRequest.onsuccess = function openRequest_onsuccess() {
+ var db = openRequest.result;
+ var transaction = db.transaction([FS.DB_STORE_NAME], 'readwrite');
+ var files = transaction.objectStore(FS.DB_STORE_NAME);
+ var ok = 0, fail = 0, total = paths.length;
+ function finish() {
+ if (fail == 0) onload(); else onerror();
+ }
+ paths.forEach(function(path) {
+ var putRequest = files.put(FS.analyzePath(path).object.contents, path);
+ putRequest.onsuccess = function putRequest_onsuccess() { ok++; if (ok + fail == total) finish() };
+ putRequest.onerror = function putRequest_onerror() { fail++; if (ok + fail == total) finish() };
+ });
+ transaction.onerror = onerror;
+ };
+ openRequest.onerror = onerror;
+ },loadFilesFromDB:function(paths, onload, onerror) {
+ onload = onload || function(){};
+ onerror = onerror || function(){};
+ var indexedDB = FS.indexedDB();
+ try {
+ var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION);
+ } catch (e) {
+ return onerror(e);
+ }
+ openRequest.onupgradeneeded = onerror; // no database to load from
+ openRequest.onsuccess = function openRequest_onsuccess() {
+ var db = openRequest.result;
+ try {
+ var transaction = db.transaction([FS.DB_STORE_NAME], 'readonly');
+ } catch(e) {
+ onerror(e);
+ return;
+ }
+ var files = transaction.objectStore(FS.DB_STORE_NAME);
+ var ok = 0, fail = 0, total = paths.length;
+ function finish() {
+ if (fail == 0) onload(); else onerror();
+ }
+ paths.forEach(function(path) {
+ var getRequest = files.get(path);
+ getRequest.onsuccess = function getRequest_onsuccess() {
+ if (FS.analyzePath(path).exists) {
+ FS.unlink(path);
+ }
+ FS.createDataFile(PATH.dirname(path), PATH.basename(path), getRequest.result, true, true, true);
+ ok++;
+ if (ok + fail == total) finish();
+ };
+ getRequest.onerror = function getRequest_onerror() { fail++; if (ok + fail == total) finish() };
+ });
+ transaction.onerror = onerror;
+ };
+ openRequest.onerror = onerror;
+ },mmapAlloc:function(size) {
+ var alignedSize = alignMemory(size, 16384);
+ var ptr = _malloc(alignedSize);
+ while (size < alignedSize) HEAP8[ptr + size++] = 0;
+ return ptr;
+ }};var SYSCALLS={mappings:{},DEFAULT_POLLMASK:5,umask:511,calculateAt:function(dirfd, path) {
+ if (path[0] !== '/') {
+ // relative path
+ var dir;
+ if (dirfd === -100) {
+ dir = FS.cwd();
+ } else {
+ var dirstream = FS.getStream(dirfd);
+ if (!dirstream) throw new FS.ErrnoError(8);
+ dir = dirstream.path;
+ }
+ path = PATH.join2(dir, path);
+ }
+ return path;
+ },doStat:function(func, path, buf) {
+ try {
+ var stat = func(path);
+ } catch (e) {
+ if (e && e.node && PATH.normalize(path) !== PATH.normalize(FS.getPath(e.node))) {
+ // an error occurred while trying to look up the path; we should just report ENOTDIR
+ return -54;
+ }
+ throw e;
+ }
+ HEAP32[((buf)>>2)]=stat.dev;
+ HEAP32[(((buf)+(4))>>2)]=0;
+ HEAP32[(((buf)+(8))>>2)]=stat.ino;
+ HEAP32[(((buf)+(12))>>2)]=stat.mode;
+ HEAP32[(((buf)+(16))>>2)]=stat.nlink;
+ HEAP32[(((buf)+(20))>>2)]=stat.uid;
+ HEAP32[(((buf)+(24))>>2)]=stat.gid;
+ HEAP32[(((buf)+(28))>>2)]=stat.rdev;
+ HEAP32[(((buf)+(32))>>2)]=0;
+ (tempI64 = [stat.size>>>0,(tempDouble=stat.size,(+(Math_abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? ((Math_min((+(Math_floor((tempDouble)/4294967296.0))), 4294967295.0))|0)>>>0 : (~~((+(Math_ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)],HEAP32[(((buf)+(40))>>2)]=tempI64[0],HEAP32[(((buf)+(44))>>2)]=tempI64[1]);
+ HEAP32[(((buf)+(48))>>2)]=4096;
+ HEAP32[(((buf)+(52))>>2)]=stat.blocks;
+ HEAP32[(((buf)+(56))>>2)]=(stat.atime.getTime() / 1000)|0;
+ HEAP32[(((buf)+(60))>>2)]=0;
+ HEAP32[(((buf)+(64))>>2)]=(stat.mtime.getTime() / 1000)|0;
+ HEAP32[(((buf)+(68))>>2)]=0;
+ HEAP32[(((buf)+(72))>>2)]=(stat.ctime.getTime() / 1000)|0;
+ HEAP32[(((buf)+(76))>>2)]=0;
+ (tempI64 = [stat.ino>>>0,(tempDouble=stat.ino,(+(Math_abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? ((Math_min((+(Math_floor((tempDouble)/4294967296.0))), 4294967295.0))|0)>>>0 : (~~((+(Math_ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)],HEAP32[(((buf)+(80))>>2)]=tempI64[0],HEAP32[(((buf)+(84))>>2)]=tempI64[1]);
+ return 0;
+ },doMsync:function(addr, stream, len, flags, offset) {
+ var buffer = HEAPU8.slice(addr, addr + len);
+ FS.msync(stream, buffer, offset, len, flags);
+ },doMkdir:function(path, mode) {
+ // remove a trailing slash, if one - /a/b/ has basename of '', but
+ // we want to create b in the context of this function
+ path = PATH.normalize(path);
+ if (path[path.length-1] === '/') path = path.substr(0, path.length-1);
+ FS.mkdir(path, mode, 0);
+ return 0;
+ },doMknod:function(path, mode, dev) {
+ // we don't want this in the JS API as it uses mknod to create all nodes.
+ switch (mode & 61440) {
+ case 32768:
+ case 8192:
+ case 24576:
+ case 4096:
+ case 49152:
+ break;
+ default: return -28;
+ }
+ FS.mknod(path, mode, dev);
+ return 0;
+ },doReadlink:function(path, buf, bufsize) {
+ if (bufsize <= 0) return -28;
+ var ret = FS.readlink(path);
+
+ var len = Math.min(bufsize, lengthBytesUTF8(ret));
+ var endChar = HEAP8[buf+len];
+ stringToUTF8(ret, buf, bufsize+1);
+ // readlink is one of the rare functions that write out a C string, but does never append a null to the output buffer(!)
+ // stringToUTF8() always appends a null byte, so restore the character under the null byte after the write.
+ HEAP8[buf+len] = endChar;
+
+ return len;
+ },doAccess:function(path, amode) {
+ if (amode & ~7) {
+ // need a valid mode
+ return -28;
+ }
+ var node;
+ var lookup = FS.lookupPath(path, { follow: true });
+ node = lookup.node;
+ if (!node) {
+ return -44;
+ }
+ var perms = '';
+ if (amode & 4) perms += 'r';
+ if (amode & 2) perms += 'w';
+ if (amode & 1) perms += 'x';
+ if (perms /* otherwise, they've just passed F_OK */ && FS.nodePermissions(node, perms)) {
+ return -2;
+ }
+ return 0;
+ },doDup:function(path, flags, suggestFD) {
+ var suggest = FS.getStream(suggestFD);
+ if (suggest) FS.close(suggest);
+ return FS.open(path, flags, 0, suggestFD, suggestFD).fd;
+ },doReadv:function(stream, iov, iovcnt, offset) {
+ var ret = 0;
+ for (var i = 0; i < iovcnt; i++) {
+ var ptr = HEAP32[(((iov)+(i*8))>>2)];
+ var len = HEAP32[(((iov)+(i*8 + 4))>>2)];
+ var curr = FS.read(stream, HEAP8,ptr, len, offset);
+ if (curr < 0) return -1;
+ ret += curr;
+ if (curr < len) break; // nothing more to read
+ }
+ return ret;
+ },doWritev:function(stream, iov, iovcnt, offset) {
+ var ret = 0;
+ for (var i = 0; i < iovcnt; i++) {
+ var ptr = HEAP32[(((iov)+(i*8))>>2)];
+ var len = HEAP32[(((iov)+(i*8 + 4))>>2)];
+ var curr = FS.write(stream, HEAP8,ptr, len, offset);
+ if (curr < 0) return -1;
+ ret += curr;
+ }
+ return ret;
+ },varargs:undefined,get:function() {
+ SYSCALLS.varargs += 4;
+ var ret = HEAP32[(((SYSCALLS.varargs)-(4))>>2)];
+ return ret;
+ },getStr:function(ptr) {
+ var ret = UTF8ToString(ptr);
+ return ret;
+ },getStreamFromFD:function(fd) {
+ var stream = FS.getStream(fd);
+ if (!stream) throw new FS.ErrnoError(8);
+ return stream;
+ },get64:function(low, high) {
+ return low;
+ }};function ___sys_fcntl64(fd, cmd, varargs) {SYSCALLS.varargs = varargs;
+ try {
+
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ switch (cmd) {
+ case 0: {
+ var arg = SYSCALLS.get();
+ if (arg < 0) {
+ return -28;
+ }
+ var newStream;
+ newStream = FS.open(stream.path, stream.flags, 0, arg);
+ return newStream.fd;
+ }
+ case 1:
+ case 2:
+ return 0; // FD_CLOEXEC makes no sense for a single process.
+ case 3:
+ return stream.flags;
+ case 4: {
+ var arg = SYSCALLS.get();
+ stream.flags |= arg;
+ return 0;
+ }
+ case 12:
+ /* case 12: Currently in musl F_GETLK64 has same value as F_GETLK, so omitted to avoid duplicate case blocks. If that changes, uncomment this */ {
+
+ var arg = SYSCALLS.get();
+ var offset = 0;
+ // We're always unlocked.
+ HEAP16[(((arg)+(offset))>>1)]=2;
+ return 0;
+ }
+ case 13:
+ case 14:
+ /* case 13: Currently in musl F_SETLK64 has same value as F_SETLK, so omitted to avoid duplicate case blocks. If that changes, uncomment this */
+ /* case 14: Currently in musl F_SETLKW64 has same value as F_SETLKW, so omitted to avoid duplicate case blocks. If that changes, uncomment this */
+
+
+ return 0; // Pretend that the locking is successful.
+ case 16:
+ case 8:
+ return -28; // These are for sockets. We don't have them fully implemented yet.
+ case 9:
+ // musl trusts getown return values, due to a bug where they must be, as they overlap with errors. just return -1 here, so fnctl() returns that, and we set errno ourselves.
+ setErrNo(28);
+ return -1;
+ default: {
+ return -28;
+ }
+ }
+ } catch (e) {
+ if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
+ return -e.errno;
+ }
+ }
+
+ function ___sys_ioctl(fd, op, varargs) {SYSCALLS.varargs = varargs;
+ try {
+
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ switch (op) {
+ case 21509:
+ case 21505: {
+ if (!stream.tty) return -59;
+ return 0;
+ }
+ case 21510:
+ case 21511:
+ case 21512:
+ case 21506:
+ case 21507:
+ case 21508: {
+ if (!stream.tty) return -59;
+ return 0; // no-op, not actually adjusting terminal settings
+ }
+ case 21519: {
+ if (!stream.tty) return -59;
+ var argp = SYSCALLS.get();
+ HEAP32[((argp)>>2)]=0;
+ return 0;
+ }
+ case 21520: {
+ if (!stream.tty) return -59;
+ return -28; // not supported
+ }
+ case 21531: {
+ var argp = SYSCALLS.get();
+ return FS.ioctl(stream, op, argp);
+ }
+ case 21523: {
+ // TODO: in theory we should write to the winsize struct that gets
+ // passed in, but for now musl doesn't read anything on it
+ if (!stream.tty) return -59;
+ return 0;
+ }
+ case 21524: {
+ // TODO: technically, this ioctl call should change the window size.
+ // but, since emscripten doesn't have any concept of a terminal window
+ // yet, we'll just silently throw it away as we do TIOCGWINSZ
+ if (!stream.tty) return -59;
+ return 0;
+ }
+ default: abort('bad ioctl syscall ' + op);
+ }
+ } catch (e) {
+ if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
+ return -e.errno;
+ }
+ }
+
+ function ___sys_open(path, flags, varargs) {SYSCALLS.varargs = varargs;
+ try {
+
+ var pathname = SYSCALLS.getStr(path);
+ var mode = SYSCALLS.get();
+ var stream = FS.open(pathname, flags, mode);
+ return stream.fd;
+ } catch (e) {
+ if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
+ return -e.errno;
+ }
+ }
+
+
+
+
+
+ function _emscripten_set_main_loop_timing(mode, value) {
+ Browser.mainLoop.timingMode = mode;
+ Browser.mainLoop.timingValue = value;
+
+ if (!Browser.mainLoop.func) {
+ return 1; // Return non-zero on failure, can't set timing mode when there is no main loop.
+ }
+
+ if (mode == 0 /*EM_TIMING_SETTIMEOUT*/) {
+ Browser.mainLoop.scheduler = function Browser_mainLoop_scheduler_setTimeout() {
+ var timeUntilNextTick = Math.max(0, Browser.mainLoop.tickStartTime + value - _emscripten_get_now())|0;
+ setTimeout(Browser.mainLoop.runner, timeUntilNextTick); // doing this each time means that on exception, we stop
+ };
+ Browser.mainLoop.method = 'timeout';
+ } else if (mode == 1 /*EM_TIMING_RAF*/) {
+ Browser.mainLoop.scheduler = function Browser_mainLoop_scheduler_rAF() {
+ Browser.requestAnimationFrame(Browser.mainLoop.runner);
+ };
+ Browser.mainLoop.method = 'rAF';
+ } else if (mode == 2 /*EM_TIMING_SETIMMEDIATE*/) {
+ if (typeof setImmediate === 'undefined') {
+ // Emulate setImmediate. (note: not a complete polyfill, we don't emulate clearImmediate() to keep code size to minimum, since not needed)
+ var setImmediates = [];
+ var emscriptenMainLoopMessageId = 'setimmediate';
+ var Browser_setImmediate_messageHandler = function(event) {
+ // When called in current thread or Worker, the main loop ID is structured slightly different to accommodate for --proxy-to-worker runtime listening to Worker events,
+ // so check for both cases.
+ if (event.data === emscriptenMainLoopMessageId || event.data.target === emscriptenMainLoopMessageId) {
+ event.stopPropagation();
+ setImmediates.shift()();
+ }
+ }
+ addEventListener("message", Browser_setImmediate_messageHandler, true);
+ setImmediate = /** @type{function(function(): ?, ...?): number} */(function Browser_emulated_setImmediate(func) {
+ setImmediates.push(func);
+ if (ENVIRONMENT_IS_WORKER) {
+ if (Module['setImmediates'] === undefined) Module['setImmediates'] = [];
+ Module['setImmediates'].push(func);
+ postMessage({target: emscriptenMainLoopMessageId}); // In --proxy-to-worker, route the message via proxyClient.js
+ } else postMessage(emscriptenMainLoopMessageId, "*"); // On the main thread, can just send the message to itself.
+ })
+ }
+ Browser.mainLoop.scheduler = function Browser_mainLoop_scheduler_setImmediate() {
+ setImmediate(Browser.mainLoop.runner);
+ };
+ Browser.mainLoop.method = 'immediate';
+ }
+ return 0;
+ }
+
+ var _emscripten_get_now;if (ENVIRONMENT_IS_NODE) {
+ _emscripten_get_now = function() {
+ var t = process['hrtime']();
+ return t[0] * 1e3 + t[1] / 1e6;
+ };
+ } else if (typeof dateNow !== 'undefined') {
+ _emscripten_get_now = dateNow;
+ } else _emscripten_get_now = function() { return performance.now(); }
+ ;function setMainLoop(browserIterationFunc, fps, simulateInfiniteLoop, arg, noSetTiming) {
+ noExitRuntime = true;
+
+ 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.');
+
+ Browser.mainLoop.func = browserIterationFunc;
+ Browser.mainLoop.arg = arg;
+
+ var thisMainLoopId = Browser.mainLoop.currentlyRunningMainloop;
+
+ Browser.mainLoop.runner = function Browser_mainLoop_runner() {
+ if (ABORT) return;
+ if (Browser.mainLoop.queue.length > 0) {
+ var start = Date.now();
+ var blocker = Browser.mainLoop.queue.shift();
+ blocker.func(blocker.arg);
+ if (Browser.mainLoop.remainingBlockers) {
+ var remaining = Browser.mainLoop.remainingBlockers;
+ var next = remaining%1 == 0 ? remaining-1 : Math.floor(remaining);
+ if (blocker.counted) {
+ Browser.mainLoop.remainingBlockers = next;
+ } else {
+ // not counted, but move the progress along a tiny bit
+ next = next + 0.5; // do not steal all the next one's progress
+ Browser.mainLoop.remainingBlockers = (8*remaining + next)/9;
+ }
+ }
+ console.log('main loop blocker "' + blocker.name + '" took ' + (Date.now() - start) + ' ms'); //, left: ' + Browser.mainLoop.remainingBlockers);
+ Browser.mainLoop.updateStatus();
+
+ // catches pause/resume main loop from blocker execution
+ if (thisMainLoopId < Browser.mainLoop.currentlyRunningMainloop) return;
+
+ setTimeout(Browser.mainLoop.runner, 0);
+ return;
+ }
+
+ // catch pauses from non-main loop sources
+ if (thisMainLoopId < Browser.mainLoop.currentlyRunningMainloop) return;
+
+ // Implement very basic swap interval control
+ Browser.mainLoop.currentFrameNumber = Browser.mainLoop.currentFrameNumber + 1 | 0;
+ if (Browser.mainLoop.timingMode == 1/*EM_TIMING_RAF*/ && Browser.mainLoop.timingValue > 1 && Browser.mainLoop.currentFrameNumber % Browser.mainLoop.timingValue != 0) {
+ // Not the scheduled time to render this frame - skip.
+ Browser.mainLoop.scheduler();
+ return;
+ } else if (Browser.mainLoop.timingMode == 0/*EM_TIMING_SETTIMEOUT*/) {
+ Browser.mainLoop.tickStartTime = _emscripten_get_now();
+ }
+
+ // Signal GL rendering layer that processing of a new frame is about to start. This helps it optimize
+ // VBO double-buffering and reduce GPU stalls.
+
+
+
+
+ Browser.mainLoop.runIter(browserIterationFunc);
+
+
+ // catch pauses from the main loop itself
+ if (thisMainLoopId < Browser.mainLoop.currentlyRunningMainloop) return;
+
+ // Queue new audio data. This is important to be right after the main loop invocation, so that we will immediately be able
+ // to queue the newest produced audio samples.
+ // TODO: Consider adding pre- and post- rAF callbacks so that GL.newRenderingFrameStarted() and SDL.audio.queueNewAudioData()
+ // do not need to be hardcoded into this function, but can be more generic.
+ if (typeof SDL === 'object' && SDL.audio && SDL.audio.queueNewAudioData) SDL.audio.queueNewAudioData();
+
+ Browser.mainLoop.scheduler();
+ }
+
+ if (!noSetTiming) {
+ if (fps && fps > 0) _emscripten_set_main_loop_timing(0/*EM_TIMING_SETTIMEOUT*/, 1000.0 / fps);
+ else _emscripten_set_main_loop_timing(1/*EM_TIMING_RAF*/, 1); // Do rAF by rendering each frame (no decimating)
+
+ Browser.mainLoop.scheduler();
+ }
+
+ if (simulateInfiniteLoop) {
+ throw 'unwind';
+ }
+ }var Browser={mainLoop:{scheduler:null,method:"",currentlyRunningMainloop:0,func:null,arg:0,timingMode:0,timingValue:0,currentFrameNumber:0,queue:[],pause:function() {
+ Browser.mainLoop.scheduler = null;
+ Browser.mainLoop.currentlyRunningMainloop++; // Incrementing this signals the previous main loop that it's now become old, and it must return.
+ },resume:function() {
+ Browser.mainLoop.currentlyRunningMainloop++;
+ var timingMode = Browser.mainLoop.timingMode;
+ var timingValue = Browser.mainLoop.timingValue;
+ var func = Browser.mainLoop.func;
+ Browser.mainLoop.func = null;
+ setMainLoop(func, 0, false, Browser.mainLoop.arg, true /* do not set timing and call scheduler, we will do it on the next lines */);
+ _emscripten_set_main_loop_timing(timingMode, timingValue);
+ Browser.mainLoop.scheduler();
+ },updateStatus:function() {
+ if (Module['setStatus']) {
+ var message = Module['statusMessage'] || 'Please wait...';
+ var remaining = Browser.mainLoop.remainingBlockers;
+ var expected = Browser.mainLoop.expectedBlockers;
+ if (remaining) {
+ if (remaining < expected) {
+ Module['setStatus'](message + ' (' + (expected - remaining) + '/' + expected + ')');
+ } else {
+ Module['setStatus'](message);
+ }
+ } else {
+ Module['setStatus']('');
+ }
+ }
+ },runIter:function(func) {
+ if (ABORT) return;
+ if (Module['preMainLoop']) {
+ var preRet = Module['preMainLoop']();
+ if (preRet === false) {
+ return; // |return false| skips a frame
+ }
+ }
+ try {
+ func();
+ } catch (e) {
+ if (e instanceof ExitStatus) {
+ return;
+ } else if (e == 'unwind') {
+ return;
+ } else {
+ if (e && typeof e === 'object' && e.stack) err('exception thrown: ' + [e, e.stack]);
+ throw e;
+ }
+ }
+ if (Module['postMainLoop']) Module['postMainLoop']();
+ }},isFullscreen:false,pointerLock:false,moduleContextCreatedCallbacks:[],workers:[],init:function() {
+ if (!Module["preloadPlugins"]) Module["preloadPlugins"] = []; // needs to exist even in workers
+
+ if (Browser.initted) return;
+ Browser.initted = true;
+
+ try {
+ new Blob();
+ Browser.hasBlobConstructor = true;
+ } catch(e) {
+ Browser.hasBlobConstructor = false;
+ console.log("warning: no blob constructor, cannot create blobs with mimetypes");
+ }
+ Browser.BlobBuilder = typeof MozBlobBuilder != "undefined" ? MozBlobBuilder : (typeof WebKitBlobBuilder != "undefined" ? WebKitBlobBuilder : (!Browser.hasBlobConstructor ? console.log("warning: no BlobBuilder") : null));
+ Browser.URLObject = typeof window != "undefined" ? (window.URL ? window.URL : window.webkitURL) : undefined;
+ if (!Module.noImageDecoding && typeof Browser.URLObject === 'undefined') {
+ console.log("warning: Browser does not support creating object URLs. Built-in browser image decoding will not be available.");
+ Module.noImageDecoding = true;
+ }
+
+ // Support for plugins that can process preloaded files. You can add more of these to
+ // your app by creating and appending to Module.preloadPlugins.
+ //
+ // Each plugin is asked if it can handle a file based on the file's name. If it can,
+ // it is given the file's raw data. When it is done, it calls a callback with the file's
+ // (possibly modified) data. For example, a plugin might decompress a file, or it
+ // might create some side data structure for use later (like an Image element, etc.).
+
+ var imagePlugin = {};
+ imagePlugin['canHandle'] = function imagePlugin_canHandle(name) {
+ return !Module.noImageDecoding && /\.(jpg|jpeg|png|bmp)$/i.test(name);
+ };
+ imagePlugin['handle'] = function imagePlugin_handle(byteArray, name, onload, onerror) {
+ var b = null;
+ if (Browser.hasBlobConstructor) {
+ try {
+ b = new Blob([byteArray], { type: Browser.getMimetype(name) });
+ if (b.size !== byteArray.length) { // Safari bug #118630
+ // Safari's Blob can only take an ArrayBuffer
+ b = new Blob([(new Uint8Array(byteArray)).buffer], { type: Browser.getMimetype(name) });
+ }
+ } catch(e) {
+ warnOnce('Blob constructor present but fails: ' + e + '; falling back to blob builder');
+ }
+ }
+ if (!b) {
+ var bb = new Browser.BlobBuilder();
+ bb.append((new Uint8Array(byteArray)).buffer); // we need to pass a buffer, and must copy the array to get the right data range
+ b = bb.getBlob();
+ }
+ var url = Browser.URLObject.createObjectURL(b);
+ var img = new Image();
+ img.onload = function img_onload() {
+ assert(img.complete, 'Image ' + name + ' could not be decoded');
+ var canvas = document.createElement('canvas');
+ canvas.width = img.width;
+ canvas.height = img.height;
+ var ctx = canvas.getContext('2d');
+ ctx.drawImage(img, 0, 0);
+ Module["preloadedImages"][name] = canvas;
+ Browser.URLObject.revokeObjectURL(url);
+ if (onload) onload(byteArray);
+ };
+ img.onerror = function img_onerror(event) {
+ console.log('Image ' + url + ' could not be decoded');
+ if (onerror) onerror();
+ };
+ img.src = url;
+ };
+ Module['preloadPlugins'].push(imagePlugin);
+
+ var audioPlugin = {};
+ audioPlugin['canHandle'] = function audioPlugin_canHandle(name) {
+ return !Module.noAudioDecoding && name.substr(-4) in { '.ogg': 1, '.wav': 1, '.mp3': 1 };
+ };
+ audioPlugin['handle'] = function audioPlugin_handle(byteArray, name, onload, onerror) {
+ var done = false;
+ function finish(audio) {
+ if (done) return;
+ done = true;
+ Module["preloadedAudios"][name] = audio;
+ if (onload) onload(byteArray);
+ }
+ function fail() {
+ if (done) return;
+ done = true;
+ Module["preloadedAudios"][name] = new Audio(); // empty shim
+ if (onerror) onerror();
+ }
+ if (Browser.hasBlobConstructor) {
+ try {
+ var b = new Blob([byteArray], { type: Browser.getMimetype(name) });
+ } catch(e) {
+ return fail();
+ }
+ var url = Browser.URLObject.createObjectURL(b); // XXX we never revoke this!
+ var audio = new Audio();
+ audio.addEventListener('canplaythrough', function() { finish(audio) }, false); // use addEventListener due to chromium bug 124926
+ audio.onerror = function audio_onerror(event) {
+ if (done) return;
+ console.log('warning: browser could not fully decode audio ' + name + ', trying slower base64 approach');
+ function encode64(data) {
+ var BASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+ var PAD = '=';
+ var ret = '';
+ var leftchar = 0;
+ var leftbits = 0;
+ for (var i = 0; i < data.length; i++) {
+ leftchar = (leftchar << 8) | data[i];
+ leftbits += 8;
+ while (leftbits >= 6) {
+ var curr = (leftchar >> (leftbits-6)) & 0x3f;
+ leftbits -= 6;
+ ret += BASE[curr];
+ }
+ }
+ if (leftbits == 2) {
+ ret += BASE[(leftchar&3) << 4];
+ ret += PAD + PAD;
+ } else if (leftbits == 4) {
+ ret += BASE[(leftchar&0xf) << 2];
+ ret += PAD;
+ }
+ return ret;
+ }
+ audio.src = 'data:audio/x-' + name.substr(-3) + ';base64,' + encode64(byteArray);
+ finish(audio); // we don't wait for confirmation this worked - but it's worth trying
+ };
+ audio.src = url;
+ // workaround for chrome bug 124926 - we do not always get oncanplaythrough or onerror
+ Browser.safeSetTimeout(function() {
+ finish(audio); // try to use it even though it is not necessarily ready to play
+ }, 10000);
+ } else {
+ return fail();
+ }
+ };
+ Module['preloadPlugins'].push(audioPlugin);
+
+
+ // Canvas event setup
+
+ function pointerLockChange() {
+ Browser.pointerLock = document['pointerLockElement'] === Module['canvas'] ||
+ document['mozPointerLockElement'] === Module['canvas'] ||
+ document['webkitPointerLockElement'] === Module['canvas'] ||
+ document['msPointerLockElement'] === Module['canvas'];
+ }
+ var canvas = Module['canvas'];
+ if (canvas) {
+ // forced aspect ratio can be enabled by defining 'forcedAspectRatio' on Module
+ // Module['forcedAspectRatio'] = 4 / 3;
+
+ canvas.requestPointerLock = canvas['requestPointerLock'] ||
+ canvas['mozRequestPointerLock'] ||
+ canvas['webkitRequestPointerLock'] ||
+ canvas['msRequestPointerLock'] ||
+ function(){};
+ canvas.exitPointerLock = document['exitPointerLock'] ||
+ document['mozExitPointerLock'] ||
+ document['webkitExitPointerLock'] ||
+ document['msExitPointerLock'] ||
+ function(){}; // no-op if function does not exist
+ canvas.exitPointerLock = canvas.exitPointerLock.bind(document);
+
+ document.addEventListener('pointerlockchange', pointerLockChange, false);
+ document.addEventListener('mozpointerlockchange', pointerLockChange, false);
+ document.addEventListener('webkitpointerlockchange', pointerLockChange, false);
+ document.addEventListener('mspointerlockchange', pointerLockChange, false);
+
+ if (Module['elementPointerLock']) {
+ canvas.addEventListener("click", function(ev) {
+ if (!Browser.pointerLock && Module['canvas'].requestPointerLock) {
+ Module['canvas'].requestPointerLock();
+ ev.preventDefault();
+ }
+ }, false);
+ }
+ }
+ },createContext:function(canvas, useWebGL, setInModule, webGLContextAttributes) {
+ if (useWebGL && Module.ctx && canvas == Module.canvas) return Module.ctx; // no need to recreate GL context if it's already been created for this canvas.
+
+ var ctx;
+ var contextHandle;
+ if (useWebGL) {
+ // For GLES2/desktop GL compatibility, adjust a few defaults to be different to WebGL defaults, so that they align better with the desktop defaults.
+ var contextAttributes = {
+ antialias: false,
+ alpha: false,
+ majorVersion: 1,
+ };
+
+ if (webGLContextAttributes) {
+ for (var attribute in webGLContextAttributes) {
+ contextAttributes[attribute] = webGLContextAttributes[attribute];
+ }
+ }
+
+ // This check of existence of GL is here to satisfy Closure compiler, which yells if variable GL is referenced below but GL object is not
+ // actually compiled in because application is not doing any GL operations. TODO: Ideally if GL is not being used, this function
+ // Browser.createContext() should not even be emitted.
+ if (typeof GL !== 'undefined') {
+ contextHandle = GL.createContext(canvas, contextAttributes);
+ if (contextHandle) {
+ ctx = GL.getContext(contextHandle).GLctx;
+ }
+ }
+ } else {
+ ctx = canvas.getContext('2d');
+ }
+
+ if (!ctx) return null;
+
+ if (setInModule) {
+ 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');
+
+ Module.ctx = ctx;
+ if (useWebGL) GL.makeContextCurrent(contextHandle);
+ Module.useWebGL = useWebGL;
+ Browser.moduleContextCreatedCallbacks.forEach(function(callback) { callback() });
+ Browser.init();
+ }
+ return ctx;
+ },destroyContext:function(canvas, useWebGL, setInModule) {},fullscreenHandlersInstalled:false,lockPointer:undefined,resizeCanvas:undefined,requestFullscreen:function(lockPointer, resizeCanvas) {
+ Browser.lockPointer = lockPointer;
+ Browser.resizeCanvas = resizeCanvas;
+ if (typeof Browser.lockPointer === 'undefined') Browser.lockPointer = true;
+ if (typeof Browser.resizeCanvas === 'undefined') Browser.resizeCanvas = false;
+
+ var canvas = Module['canvas'];
+ function fullscreenChange() {
+ Browser.isFullscreen = false;
+ var canvasContainer = canvas.parentNode;
+ if ((document['fullscreenElement'] || document['mozFullScreenElement'] ||
+ document['msFullscreenElement'] || document['webkitFullscreenElement'] ||
+ document['webkitCurrentFullScreenElement']) === canvasContainer) {
+ canvas.exitFullscreen = Browser.exitFullscreen;
+ if (Browser.lockPointer) canvas.requestPointerLock();
+ Browser.isFullscreen = true;
+ if (Browser.resizeCanvas) {
+ Browser.setFullscreenCanvasSize();
+ } else {
+ Browser.updateCanvasDimensions(canvas);
+ }
+ } else {
+ // remove the full screen specific parent of the canvas again to restore the HTML structure from before going full screen
+ canvasContainer.parentNode.insertBefore(canvas, canvasContainer);
+ canvasContainer.parentNode.removeChild(canvasContainer);
+
+ if (Browser.resizeCanvas) {
+ Browser.setWindowedCanvasSize();
+ } else {
+ Browser.updateCanvasDimensions(canvas);
+ }
+ }
+ if (Module['onFullScreen']) Module['onFullScreen'](Browser.isFullscreen);
+ if (Module['onFullscreen']) Module['onFullscreen'](Browser.isFullscreen);
+ }
+
+ if (!Browser.fullscreenHandlersInstalled) {
+ Browser.fullscreenHandlersInstalled = true;
+ document.addEventListener('fullscreenchange', fullscreenChange, false);
+ document.addEventListener('mozfullscreenchange', fullscreenChange, false);
+ document.addEventListener('webkitfullscreenchange', fullscreenChange, false);
+ document.addEventListener('MSFullscreenChange', fullscreenChange, false);
+ }
+
+ // create a new parent to ensure the canvas has no siblings. this allows browsers to optimize full screen performance when its parent is the full screen root
+ var canvasContainer = document.createElement("div");
+ canvas.parentNode.insertBefore(canvasContainer, canvas);
+ canvasContainer.appendChild(canvas);
+
+ // use parent of canvas as full screen root to allow aspect ratio correction (Firefox stretches the root to screen size)
+ canvasContainer.requestFullscreen = canvasContainer['requestFullscreen'] ||
+ canvasContainer['mozRequestFullScreen'] ||
+ canvasContainer['msRequestFullscreen'] ||
+ (canvasContainer['webkitRequestFullscreen'] ? function() { canvasContainer['webkitRequestFullscreen'](Element['ALLOW_KEYBOARD_INPUT']) } : null) ||
+ (canvasContainer['webkitRequestFullScreen'] ? function() { canvasContainer['webkitRequestFullScreen'](Element['ALLOW_KEYBOARD_INPUT']) } : null);
+
+ canvasContainer.requestFullscreen();
+ },exitFullscreen:function() {
+ // This is workaround for chrome. Trying to exit from fullscreen
+ // not in fullscreen state will cause "TypeError: Document not active"
+ // in chrome. See https://github.com/emscripten-core/emscripten/pull/8236
+ if (!Browser.isFullscreen) {
+ return false;
+ }
+
+ var CFS = document['exitFullscreen'] ||
+ document['cancelFullScreen'] ||
+ document['mozCancelFullScreen'] ||
+ document['msExitFullscreen'] ||
+ document['webkitCancelFullScreen'] ||
+ (function() {});
+ CFS.apply(document, []);
+ return true;
+ },nextRAF:0,fakeRequestAnimationFrame:function(func) {
+ // try to keep 60fps between calls to here
+ var now = Date.now();
+ if (Browser.nextRAF === 0) {
+ Browser.nextRAF = now + 1000/60;
+ } else {
+ while (now + 2 >= Browser.nextRAF) { // fudge a little, to avoid timer jitter causing us to do lots of delay:0
+ Browser.nextRAF += 1000/60;
+ }
+ }
+ var delay = Math.max(Browser.nextRAF - now, 0);
+ setTimeout(func, delay);
+ },requestAnimationFrame:function(func) {
+ if (typeof requestAnimationFrame === 'function') {
+ requestAnimationFrame(func);
+ return;
+ }
+ var RAF = Browser.fakeRequestAnimationFrame;
+ RAF(func);
+ },safeCallback:function(func) {
+ return function() {
+ if (!ABORT) return func.apply(null, arguments);
+ };
+ },allowAsyncCallbacks:true,queuedAsyncCallbacks:[],pauseAsyncCallbacks:function() {
+ Browser.allowAsyncCallbacks = false;
+ },resumeAsyncCallbacks:function() { // marks future callbacks as ok to execute, and synchronously runs any remaining ones right now
+ Browser.allowAsyncCallbacks = true;
+ if (Browser.queuedAsyncCallbacks.length > 0) {
+ var callbacks = Browser.queuedAsyncCallbacks;
+ Browser.queuedAsyncCallbacks = [];
+ callbacks.forEach(function(func) {
+ func();
+ });
+ }
+ },safeRequestAnimationFrame:function(func) {
+ return Browser.requestAnimationFrame(function() {
+ if (ABORT) return;
+ if (Browser.allowAsyncCallbacks) {
+ func();
+ } else {
+ Browser.queuedAsyncCallbacks.push(func);
+ }
+ });
+ },safeSetTimeout:function(func, timeout) {
+ noExitRuntime = true;
+ return setTimeout(function() {
+ if (ABORT) return;
+ if (Browser.allowAsyncCallbacks) {
+ func();
+ } else {
+ Browser.queuedAsyncCallbacks.push(func);
+ }
+ }, timeout);
+ },safeSetInterval:function(func, timeout) {
+ noExitRuntime = true;
+ return setInterval(function() {
+ if (ABORT) return;
+ if (Browser.allowAsyncCallbacks) {
+ func();
+ } // drop it on the floor otherwise, next interval will kick in
+ }, timeout);
+ },getMimetype:function(name) {
+ 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)];
+ },getUserMedia:function(func) {
+ if(!window.getUserMedia) {
+ window.getUserMedia = navigator['getUserMedia'] ||
+ navigator['mozGetUserMedia'];
+ }
+ window.getUserMedia(func);
+ },getMovementX:function(event) {
+ return event['movementX'] ||
+ event['mozMovementX'] ||
+ event['webkitMovementX'] ||
+ 0;
+ },getMovementY:function(event) {
+ return event['movementY'] ||
+ event['mozMovementY'] ||
+ event['webkitMovementY'] ||
+ 0;
+ },getMouseWheelDelta:function(event) {
+ var delta = 0;
+ switch (event.type) {
+ case 'DOMMouseScroll':
+ // 3 lines make up a step
+ delta = event.detail / 3;
+ break;
+ case 'mousewheel':
+ // 120 units make up a step
+ delta = event.wheelDelta / 120;
+ break;
+ case 'wheel':
+ delta = event.deltaY
+ switch(event.deltaMode) {
+ case 0:
+ // DOM_DELTA_PIXEL: 100 pixels make up a step
+ delta /= 100;
+ break;
+ case 1:
+ // DOM_DELTA_LINE: 3 lines make up a step
+ delta /= 3;
+ break;
+ case 2:
+ // DOM_DELTA_PAGE: A page makes up 80 steps
+ delta *= 80;
+ break;
+ default:
+ throw 'unrecognized mouse wheel delta mode: ' + event.deltaMode;
+ }
+ break;
+ default:
+ throw 'unrecognized mouse wheel event: ' + event.type;
+ }
+ return delta;
+ },mouseX:0,mouseY:0,mouseMovementX:0,mouseMovementY:0,touches:{},lastTouches:{},calculateMouseEvent:function(event) { // event should be mousemove, mousedown or mouseup
+ if (Browser.pointerLock) {
+ // When the pointer is locked, calculate the coordinates
+ // based on the movement of the mouse.
+ // Workaround for Firefox bug 764498
+ if (event.type != 'mousemove' &&
+ ('mozMovementX' in event)) {
+ Browser.mouseMovementX = Browser.mouseMovementY = 0;
+ } else {
+ Browser.mouseMovementX = Browser.getMovementX(event);
+ Browser.mouseMovementY = Browser.getMovementY(event);
+ }
+
+ // check if SDL is available
+ if (typeof SDL != "undefined") {
+ Browser.mouseX = SDL.mouseX + Browser.mouseMovementX;
+ Browser.mouseY = SDL.mouseY + Browser.mouseMovementY;
+ } else {
+ // just add the mouse delta to the current absolut mouse position
+ // FIXME: ideally this should be clamped against the canvas size and zero
+ Browser.mouseX += Browser.mouseMovementX;
+ Browser.mouseY += Browser.mouseMovementY;
+ }
+ } else {
+ // Otherwise, calculate the movement based on the changes
+ // in the coordinates.
+ var rect = Module["canvas"].getBoundingClientRect();
+ var cw = Module["canvas"].width;
+ var ch = Module["canvas"].height;
+
+ // Neither .scrollX or .pageXOffset are defined in a spec, but
+ // we prefer .scrollX because it is currently in a spec draft.
+ // (see: http://www.w3.org/TR/2013/WD-cssom-view-20131217/)
+ var scrollX = ((typeof window.scrollX !== 'undefined') ? window.scrollX : window.pageXOffset);
+ var scrollY = ((typeof window.scrollY !== 'undefined') ? window.scrollY : window.pageYOffset);
+
+ if (event.type === 'touchstart' || event.type === 'touchend' || event.type === 'touchmove') {
+ var touch = event.touch;
+ if (touch === undefined) {
+ return; // the "touch" property is only defined in SDL
+
+ }
+ var adjustedX = touch.pageX - (scrollX + rect.left);
+ var adjustedY = touch.pageY - (scrollY + rect.top);
+
+ adjustedX = adjustedX * (cw / rect.width);
+ adjustedY = adjustedY * (ch / rect.height);
+
+ var coords = { x: adjustedX, y: adjustedY };
+
+ if (event.type === 'touchstart') {
+ Browser.lastTouches[touch.identifier] = coords;
+ Browser.touches[touch.identifier] = coords;
+ } else if (event.type === 'touchend' || event.type === 'touchmove') {
+ var last = Browser.touches[touch.identifier];
+ if (!last) last = coords;
+ Browser.lastTouches[touch.identifier] = last;
+ Browser.touches[touch.identifier] = coords;
+ }
+ return;
+ }
+
+ var x = event.pageX - (scrollX + rect.left);
+ var y = event.pageY - (scrollY + rect.top);
+
+ // the canvas might be CSS-scaled compared to its backbuffer;
+ // SDL-using content will want mouse coordinates in terms
+ // of backbuffer units.
+ x = x * (cw / rect.width);
+ y = y * (ch / rect.height);
+
+ Browser.mouseMovementX = x - Browser.mouseX;
+ Browser.mouseMovementY = y - Browser.mouseY;
+ Browser.mouseX = x;
+ Browser.mouseY = y;
+ }
+ },asyncLoad:function(url, onload, onerror, noRunDep) {
+ var dep = !noRunDep ? getUniqueRunDependency('al ' + url) : '';
+ readAsync(url, function(arrayBuffer) {
+ assert(arrayBuffer, 'Loading data file "' + url + '" failed (no arrayBuffer).');
+ onload(new Uint8Array(arrayBuffer));
+ if (dep) removeRunDependency(dep);
+ }, function(event) {
+ if (onerror) {
+ onerror();
+ } else {
+ throw 'Loading data file "' + url + '" failed.';
+ }
+ });
+ if (dep) addRunDependency(dep);
+ },resizeListeners:[],updateResizeListeners:function() {
+ var canvas = Module['canvas'];
+ Browser.resizeListeners.forEach(function(listener) {
+ listener(canvas.width, canvas.height);
+ });
+ },setCanvasSize:function(width, height, noUpdates) {
+ var canvas = Module['canvas'];
+ Browser.updateCanvasDimensions(canvas, width, height);
+ if (!noUpdates) Browser.updateResizeListeners();
+ },windowedWidth:0,windowedHeight:0,setFullscreenCanvasSize:function() {
+ // check if SDL is available
+ if (typeof SDL != "undefined") {
+ var flags = HEAPU32[((SDL.screen)>>2)];
+ flags = flags | 0x00800000; // set SDL_FULLSCREEN flag
+ HEAP32[((SDL.screen)>>2)]=flags
+ }
+ Browser.updateCanvasDimensions(Module['canvas']);
+ Browser.updateResizeListeners();
+ },setWindowedCanvasSize:function() {
+ // check if SDL is available
+ if (typeof SDL != "undefined") {
+ var flags = HEAPU32[((SDL.screen)>>2)];
+ flags = flags & ~0x00800000; // clear SDL_FULLSCREEN flag
+ HEAP32[((SDL.screen)>>2)]=flags
+ }
+ Browser.updateCanvasDimensions(Module['canvas']);
+ Browser.updateResizeListeners();
+ },updateCanvasDimensions:function(canvas, wNative, hNative) {
+ if (wNative && hNative) {
+ canvas.widthNative = wNative;
+ canvas.heightNative = hNative;
+ } else {
+ wNative = canvas.widthNative;
+ hNative = canvas.heightNative;
+ }
+ var w = wNative;
+ var h = hNative;
+ if (Module['forcedAspectRatio'] && Module['forcedAspectRatio'] > 0) {
+ if (w/h < Module['forcedAspectRatio']) {
+ w = Math.round(h * Module['forcedAspectRatio']);
+ } else {
+ h = Math.round(w / Module['forcedAspectRatio']);
+ }
+ }
+ if (((document['fullscreenElement'] || document['mozFullScreenElement'] ||
+ document['msFullscreenElement'] || document['webkitFullscreenElement'] ||
+ document['webkitCurrentFullScreenElement']) === canvas.parentNode) && (typeof screen != 'undefined')) {
+ var factor = Math.min(screen.width / w, screen.height / h);
+ w = Math.round(w * factor);
+ h = Math.round(h * factor);
+ }
+ if (Browser.resizeCanvas) {
+ if (canvas.width != w) canvas.width = w;
+ if (canvas.height != h) canvas.height = h;
+ if (typeof canvas.style != 'undefined') {
+ canvas.style.removeProperty( "width");
+ canvas.style.removeProperty("height");
+ }
+ } else {
+ if (canvas.width != wNative) canvas.width = wNative;
+ if (canvas.height != hNative) canvas.height = hNative;
+ if (typeof canvas.style != 'undefined') {
+ if (w != wNative || h != hNative) {
+ canvas.style.setProperty( "width", w + "px", "important");
+ canvas.style.setProperty("height", h + "px", "important");
+ } else {
+ canvas.style.removeProperty( "width");
+ canvas.style.removeProperty("height");
+ }
+ }
+ }
+ },wgetRequests:{},nextWgetRequestHandle:0,getNextWgetRequestHandle:function() {
+ var handle = Browser.nextWgetRequestHandle;
+ Browser.nextWgetRequestHandle++;
+ return handle;
+ }};var EGL={errorCode:12288,defaultDisplayInitialized:false,currentContext:0,currentReadSurface:0,currentDrawSurface:0,contextAttributes:{alpha:false,depth:false,stencil:false,antialias:false},stringCache:{},setErrorCode:function(code) {
+ EGL.errorCode = code;
+ },chooseConfig:function(display, attribList, config, config_size, numConfigs) {
+ if (display != 62000 /* Magic ID for Emscripten 'default display' */) {
+ EGL.setErrorCode(0x3008 /* EGL_BAD_DISPLAY */);
+ return 0;
+ }
+
+ if (attribList) {
+ // read attribList if it is non-null
+ for(;;) {
+ var param = HEAP32[((attribList)>>2)];
+ if (param == 0x3021 /*EGL_ALPHA_SIZE*/) {
+ var alphaSize = HEAP32[(((attribList)+(4))>>2)];
+ EGL.contextAttributes.alpha = (alphaSize > 0);
+ } else if (param == 0x3025 /*EGL_DEPTH_SIZE*/) {
+ var depthSize = HEAP32[(((attribList)+(4))>>2)];
+ EGL.contextAttributes.depth = (depthSize > 0);
+ } else if (param == 0x3026 /*EGL_STENCIL_SIZE*/) {
+ var stencilSize = HEAP32[(((attribList)+(4))>>2)];
+ EGL.contextAttributes.stencil = (stencilSize > 0);
+ } else if (param == 0x3031 /*EGL_SAMPLES*/) {
+ var samples = HEAP32[(((attribList)+(4))>>2)];
+ EGL.contextAttributes.antialias = (samples > 0);
+ } else if (param == 0x3032 /*EGL_SAMPLE_BUFFERS*/) {
+ var samples = HEAP32[(((attribList)+(4))>>2)];
+ EGL.contextAttributes.antialias = (samples == 1);
+ } else if (param == 0x3100 /*EGL_CONTEXT_PRIORITY_LEVEL_IMG*/) {
+ var requestedPriority = HEAP32[(((attribList)+(4))>>2)];
+ EGL.contextAttributes.lowLatency = (requestedPriority != 0x3103 /*EGL_CONTEXT_PRIORITY_LOW_IMG*/);
+ } else if (param == 0x3038 /*EGL_NONE*/) {
+ break;
+ }
+ attribList += 8;
+ }
+ }
+
+ if ((!config || !config_size) && !numConfigs) {
+ EGL.setErrorCode(0x300C /* EGL_BAD_PARAMETER */);
+ return 0;
+ }
+ if (numConfigs) {
+ HEAP32[((numConfigs)>>2)]=1; // Total number of supported configs: 1.
+ }
+ if (config && config_size > 0) {
+ HEAP32[((config)>>2)]=62002;
+ }
+
+ EGL.setErrorCode(0x3000 /* EGL_SUCCESS */);
+ return 1;
+ }};function _eglGetProcAddress(name_) {
+ return _emscripten_GetProcAddress(name_);
+ }
+
+
+ var JSEvents={inEventHandler:0,removeAllEventListeners:function() {
+ for(var i = JSEvents.eventHandlers.length-1; i >= 0; --i) {
+ JSEvents._removeHandler(i);
+ }
+ JSEvents.eventHandlers = [];
+ JSEvents.deferredCalls = [];
+ },registerRemoveEventListeners:function() {
+ if (!JSEvents.removeEventListenersRegistered) {
+ __ATEXIT__.push(JSEvents.removeAllEventListeners);
+ JSEvents.removeEventListenersRegistered = true;
+ }
+ },deferredCalls:[],deferCall:function(targetFunction, precedence, argsList) {
+ function arraysHaveEqualContent(arrA, arrB) {
+ if (arrA.length != arrB.length) return false;
+
+ for(var i in arrA) {
+ if (arrA[i] != arrB[i]) return false;
+ }
+ return true;
+ }
+ // Test if the given call was already queued, and if so, don't add it again.
+ for(var i in JSEvents.deferredCalls) {
+ var call = JSEvents.deferredCalls[i];
+ if (call.targetFunction == targetFunction && arraysHaveEqualContent(call.argsList, argsList)) {
+ return;
+ }
+ }
+ JSEvents.deferredCalls.push({
+ targetFunction: targetFunction,
+ precedence: precedence,
+ argsList: argsList
+ });
+
+ JSEvents.deferredCalls.sort(function(x,y) { return x.precedence < y.precedence; });
+ },removeDeferredCalls:function(targetFunction) {
+ for(var i = 0; i < JSEvents.deferredCalls.length; ++i) {
+ if (JSEvents.deferredCalls[i].targetFunction == targetFunction) {
+ JSEvents.deferredCalls.splice(i, 1);
+ --i;
+ }
+ }
+ },canPerformEventHandlerRequests:function() {
+ return JSEvents.inEventHandler && JSEvents.currentEventHandler.allowsDeferredCalls;
+ },runDeferredCalls:function() {
+ if (!JSEvents.canPerformEventHandlerRequests()) {
+ return;
+ }
+ for(var i = 0; i < JSEvents.deferredCalls.length; ++i) {
+ var call = JSEvents.deferredCalls[i];
+ JSEvents.deferredCalls.splice(i, 1);
+ --i;
+ call.targetFunction.apply(null, call.argsList);
+ }
+ },eventHandlers:[],removeAllHandlersOnTarget:function(target, eventTypeString) {
+ for(var i = 0; i < JSEvents.eventHandlers.length; ++i) {
+ if (JSEvents.eventHandlers[i].target == target &&
+ (!eventTypeString || eventTypeString == JSEvents.eventHandlers[i].eventTypeString)) {
+ JSEvents._removeHandler(i--);
+ }
+ }
+ },_removeHandler:function(i) {
+ var h = JSEvents.eventHandlers[i];
+ h.target.removeEventListener(h.eventTypeString, h.eventListenerFunc, h.useCapture);
+ JSEvents.eventHandlers.splice(i, 1);
+ },registerOrRemoveHandler:function(eventHandler) {
+ var jsEventHandler = function jsEventHandler(event) {
+ // Increment nesting count for the event handler.
+ ++JSEvents.inEventHandler;
+ JSEvents.currentEventHandler = eventHandler;
+ // Process any old deferred calls the user has placed.
+ JSEvents.runDeferredCalls();
+ // Process the actual event, calls back to user C code handler.
+ eventHandler.handlerFunc(event);
+ // Process any new deferred calls that were placed right now from this event handler.
+ JSEvents.runDeferredCalls();
+ // Out of event handler - restore nesting count.
+ --JSEvents.inEventHandler;
+ };
+
+ if (eventHandler.callbackfunc) {
+ eventHandler.eventListenerFunc = jsEventHandler;
+ eventHandler.target.addEventListener(eventHandler.eventTypeString, jsEventHandler, eventHandler.useCapture);
+ JSEvents.eventHandlers.push(eventHandler);
+ JSEvents.registerRemoveEventListeners();
+ } else {
+ for(var i = 0; i < JSEvents.eventHandlers.length; ++i) {
+ if (JSEvents.eventHandlers[i].target == eventHandler.target
+ && JSEvents.eventHandlers[i].eventTypeString == eventHandler.eventTypeString) {
+ JSEvents._removeHandler(i--);
+ }
+ }
+ }
+ },getNodeNameForTarget:function(target) {
+ if (!target) return '';
+ if (target == window) return '#window';
+ if (target == screen) return '#screen';
+ return (target && target.nodeName) ? target.nodeName : '';
+ },fullscreenEnabled:function() {
+ return document.fullscreenEnabled
+ // Safari 13.0.3 on macOS Catalina 10.15.1 still ships with prefixed webkitFullscreenEnabled.
+ // TODO: If Safari at some point ships with unprefixed version, update the version check above.
+ || document.webkitFullscreenEnabled
+ ;
+ }};
+
+ function __requestPointerLock(target) {
+ if (target.requestPointerLock) {
+ target.requestPointerLock();
+ } else if (target.msRequestPointerLock) {
+ target.msRequestPointerLock();
+ } else {
+ // document.body is known to accept pointer lock, so use that to differentiate if the user passed a bad element,
+ // or if the whole browser just doesn't support the feature.
+ if (document.body.requestPointerLock
+ || document.body.msRequestPointerLock
+ ) {
+ return -3;
+ } else {
+ return -1;
+ }
+ }
+ return 0;
+ }function _emscripten_exit_pointerlock() {
+ // Make sure no queued up calls will fire after this.
+ JSEvents.removeDeferredCalls(__requestPointerLock);
+
+ if (document.exitPointerLock) {
+ document.exitPointerLock();
+ } else if (document.msExitPointerLock) {
+ document.msExitPointerLock();
+ } else {
+ return -1;
+ }
+ return 0;
+ }
+
+
+
+ function maybeCStringToJsString(cString) {
+ // "cString > 2" checks if the input is a number, and isn't of the special
+ // values we accept here, EMSCRIPTEN_EVENT_TARGET_* (which map to 0, 1, 2).
+ // In other words, if cString > 2 then it's a pointer to a valid place in
+ // memory, and points to a C string.
+ return cString > 2 ? UTF8ToString(cString) : cString;
+ }
+
+ var specialHTMLTargets=[0, typeof document !== 'undefined' ? document : 0, typeof window !== 'undefined' ? window : 0];function findEventTarget(target) {
+ target = maybeCStringToJsString(target);
+ var domElement = specialHTMLTargets[target] || (typeof document !== 'undefined' ? document.querySelector(target) : undefined);
+ return domElement;
+ }
+
+ function __getBoundingClientRect(e) {
+ return specialHTMLTargets.indexOf(e) < 0 ? e.getBoundingClientRect() : {'left':0,'top':0};
+ }function _emscripten_get_element_css_size(target, width, height) {
+ target = findEventTarget(target);
+ if (!target) return -4;
+
+ var rect = __getBoundingClientRect(target);
+ HEAPF64[((width)>>3)]=rect.width;
+ HEAPF64[((height)>>3)]=rect.height;
+
+ return 0;
+ }
+
+
+ function __fillGamepadEventData(eventStruct, e) {
+ HEAPF64[((eventStruct)>>3)]=e.timestamp;
+ for(var i = 0; i < e.axes.length; ++i) {
+ HEAPF64[(((eventStruct+i*8)+(16))>>3)]=e.axes[i];
+ }
+ for(var i = 0; i < e.buttons.length; ++i) {
+ if (typeof(e.buttons[i]) === 'object') {
+ HEAPF64[(((eventStruct+i*8)+(528))>>3)]=e.buttons[i].value;
+ } else {
+ HEAPF64[(((eventStruct+i*8)+(528))>>3)]=e.buttons[i];
+ }
+ }
+ for(var i = 0; i < e.buttons.length; ++i) {
+ if (typeof(e.buttons[i]) === 'object') {
+ HEAP32[(((eventStruct+i*4)+(1040))>>2)]=e.buttons[i].pressed;
+ } else {
+ // Assigning a boolean to HEAP32, that's ok, but Closure would like to warn about it:
+ /** @suppress {checkTypes} */
+ HEAP32[(((eventStruct+i*4)+(1040))>>2)]=e.buttons[i] == 1;
+ }
+ }
+ HEAP32[(((eventStruct)+(1296))>>2)]=e.connected;
+ HEAP32[(((eventStruct)+(1300))>>2)]=e.index;
+ HEAP32[(((eventStruct)+(8))>>2)]=e.axes.length;
+ HEAP32[(((eventStruct)+(12))>>2)]=e.buttons.length;
+ stringToUTF8(e.id, eventStruct + 1304, 64);
+ stringToUTF8(e.mapping, eventStruct + 1368, 64);
+ }function _emscripten_get_gamepad_status(index, gamepadState) {
+
+ // INVALID_PARAM is returned on a Gamepad index that never was there.
+ if (index < 0 || index >= JSEvents.lastGamepadState.length) return -5;
+
+ // NO_DATA is returned on a Gamepad index that was removed.
+ // For previously disconnected gamepads there should be an empty slot (null/undefined/false) at the index.
+ // This is because gamepads must keep their original position in the array.
+ // For example, removing the first of two gamepads produces [null/undefined/false, gamepad].
+ if (!JSEvents.lastGamepadState[index]) return -7;
+
+ __fillGamepadEventData(gamepadState, JSEvents.lastGamepadState[index]);
+ return 0;
+ }
+
+ function _emscripten_get_num_gamepads() {
+ // N.B. Do not call emscripten_get_num_gamepads() unless having first called emscripten_sample_gamepad_data(), and that has returned EMSCRIPTEN_RESULT_SUCCESS.
+ // Otherwise the following line will throw an exception.
+ return JSEvents.lastGamepadState.length;
+ }
+
+
+ function __fillPointerlockChangeEventData(eventStruct) {
+ var pointerLockElement = document.pointerLockElement || document.mozPointerLockElement || document.webkitPointerLockElement || document.msPointerLockElement;
+ var isPointerlocked = !!pointerLockElement;
+ /** @suppress {checkTypes} */
+ HEAP32[((eventStruct)>>2)]=isPointerlocked;
+ var nodeName = JSEvents.getNodeNameForTarget(pointerLockElement);
+ var id = (pointerLockElement && pointerLockElement.id) ? pointerLockElement.id : '';
+ stringToUTF8(nodeName, eventStruct + 4, 128);
+ stringToUTF8(id, eventStruct + 132, 128);
+ }/** @suppress {missingProperties} */
+ function _emscripten_get_pointerlock_status(pointerlockStatus) {
+ if (pointerlockStatus) __fillPointerlockChangeEventData(pointerlockStatus);
+ if (!document.body || (!document.body.requestPointerLock && !document.body.mozRequestPointerLock && !document.body.webkitRequestPointerLock && !document.body.msRequestPointerLock)) {
+ return -1;
+ }
+ return 0;
+ }
+
+
+
+ function __webgl_enable_ANGLE_instanced_arrays(ctx) {
+ // Extension available in WebGL 1 from Firefox 26 and Google Chrome 30 onwards. Core feature in WebGL 2.
+ var ext = ctx.getExtension('ANGLE_instanced_arrays');
+ if (ext) {
+ ctx['vertexAttribDivisor'] = function(index, divisor) { ext['vertexAttribDivisorANGLE'](index, divisor); };
+ ctx['drawArraysInstanced'] = function(mode, first, count, primcount) { ext['drawArraysInstancedANGLE'](mode, first, count, primcount); };
+ ctx['drawElementsInstanced'] = function(mode, count, type, indices, primcount) { ext['drawElementsInstancedANGLE'](mode, count, type, indices, primcount); };
+ return 1;
+ }
+ }
+
+ function __webgl_enable_OES_vertex_array_object(ctx) {
+ // Extension available in WebGL 1 from Firefox 25 and WebKit 536.28/desktop Safari 6.0.3 onwards. Core feature in WebGL 2.
+ var ext = ctx.getExtension('OES_vertex_array_object');
+ if (ext) {
+ ctx['createVertexArray'] = function() { return ext['createVertexArrayOES'](); };
+ ctx['deleteVertexArray'] = function(vao) { ext['deleteVertexArrayOES'](vao); };
+ ctx['bindVertexArray'] = function(vao) { ext['bindVertexArrayOES'](vao); };
+ ctx['isVertexArray'] = function(vao) { return ext['isVertexArrayOES'](vao); };
+ return 1;
+ }
+ }
+
+ function __webgl_enable_WEBGL_draw_buffers(ctx) {
+ // Extension available in WebGL 1 from Firefox 28 onwards. Core feature in WebGL 2.
+ var ext = ctx.getExtension('WEBGL_draw_buffers');
+ if (ext) {
+ ctx['drawBuffers'] = function(n, bufs) { ext['drawBuffersWEBGL'](n, bufs); };
+ return 1;
+ }
+ }
+
+ function __webgl_enable_WEBGL_multi_draw(ctx) {
+ // Closure is expected to be allowed to minify the '.multiDrawWebgl' property, so not accessing it quoted.
+ return !!(ctx.multiDrawWebgl = ctx.getExtension('WEBGL_multi_draw'));
+ }var GL={counter:1,buffers:[],programs:[],framebuffers:[],renderbuffers:[],textures:[],uniforms:[],shaders:[],vaos:[],contexts:[],offscreenCanvases:{},timerQueriesEXT:[],programInfos:{},stringCache:{},unpackAlignment:4,recordError:function recordError(errorCode) {
+ if (!GL.lastError) {
+ GL.lastError = errorCode;
+ }
+ },getNewId:function(table) {
+ var ret = GL.counter++;
+ for (var i = table.length; i < ret; i++) {
+ table[i] = null;
+ }
+ return ret;
+ },getSource:function(shader, count, string, length) {
+ var source = '';
+ for (var i = 0; i < count; ++i) {
+ var len = length ? HEAP32[(((length)+(i*4))>>2)] : -1;
+ source += UTF8ToString(HEAP32[(((string)+(i*4))>>2)], len < 0 ? undefined : len);
+ }
+ return source;
+ },createContext:function(canvas, webGLContextAttributes) {
+
+
+
+
+
+ var ctx =
+ (canvas.getContext("webgl", webGLContextAttributes)
+ // https://caniuse.com/#feat=webgl
+ );
+
+
+ if (!ctx) return 0;
+
+ var handle = GL.registerContext(ctx, webGLContextAttributes);
+
+
+
+ return handle;
+ },registerContext:function(ctx, webGLContextAttributes) {
+ // without pthreads a context is just an integer ID
+ var handle = GL.getNewId(GL.contexts);
+
+ var context = {
+ handle: handle,
+ attributes: webGLContextAttributes,
+ version: webGLContextAttributes.majorVersion,
+ GLctx: ctx
+ };
+
+
+ // Store the created context object so that we can access the context given a canvas without having to pass the parameters again.
+ if (ctx.canvas) ctx.canvas.GLctxObject = context;
+ GL.contexts[handle] = context;
+ if (typeof webGLContextAttributes.enableExtensionsByDefault === 'undefined' || webGLContextAttributes.enableExtensionsByDefault) {
+ GL.initExtensions(context);
+ }
+
+
+
+
+ return handle;
+ },makeContextCurrent:function(contextHandle) {
+
+ GL.currentContext = GL.contexts[contextHandle]; // Active Emscripten GL layer context object.
+ Module.ctx = GLctx = GL.currentContext && GL.currentContext.GLctx; // Active WebGL context object.
+ return !(contextHandle && !GLctx);
+ },getContext:function(contextHandle) {
+ return GL.contexts[contextHandle];
+ },deleteContext:function(contextHandle) {
+ if (GL.currentContext === GL.contexts[contextHandle]) GL.currentContext = null;
+ if (typeof JSEvents === 'object') JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas); // Release all JS event handlers on the DOM element that the GL context is associated with since the context is now deleted.
+ if (GL.contexts[contextHandle] && GL.contexts[contextHandle].GLctx.canvas) GL.contexts[contextHandle].GLctx.canvas.GLctxObject = undefined; // Make sure the canvas object no longer refers to the context object so there are no GC surprises.
+ GL.contexts[contextHandle] = null;
+ },initExtensions:function(context) {
+ // If this function is called without a specific context object, init the extensions of the currently active context.
+ if (!context) context = GL.currentContext;
+
+ if (context.initExtensionsDone) return;
+ context.initExtensionsDone = true;
+
+ var GLctx = context.GLctx;
+
+ // Detect the presence of a few extensions manually, this GL interop layer itself will need to know if they exist.
+
+ // Extensions that are only available in WebGL 1 (the calls will be no-ops if called on a WebGL 2 context active)
+ __webgl_enable_ANGLE_instanced_arrays(GLctx);
+ __webgl_enable_OES_vertex_array_object(GLctx);
+ __webgl_enable_WEBGL_draw_buffers(GLctx);
+
+ GLctx.disjointTimerQueryExt = GLctx.getExtension("EXT_disjoint_timer_query");
+ __webgl_enable_WEBGL_multi_draw(GLctx);
+
+ // These are the 'safe' feature-enabling extensions that don't add any performance impact related to e.g. debugging, and
+ // should be enabled by default so that client GLES2/GL code will not need to go through extra hoops to get its stuff working.
+ // As new extensions are ratified at http://www.khronos.org/registry/webgl/extensions/ , feel free to add your new extensions
+ // here, as long as they don't produce a performance impact for users that might not be using those extensions.
+ // E.g. debugging-related extensions should probably be off by default.
+ var automaticallyEnabledExtensions = [ // Khronos ratified WebGL extensions ordered by number (no debug extensions):
+ "OES_texture_float", "OES_texture_half_float", "OES_standard_derivatives",
+ "OES_vertex_array_object", "WEBGL_compressed_texture_s3tc", "WEBGL_depth_texture",
+ "OES_element_index_uint", "EXT_texture_filter_anisotropic", "EXT_frag_depth",
+ "WEBGL_draw_buffers", "ANGLE_instanced_arrays", "OES_texture_float_linear",
+ "OES_texture_half_float_linear", "EXT_blend_minmax", "EXT_shader_texture_lod",
+ "EXT_texture_norm16",
+ // Community approved WebGL extensions ordered by number:
+ "WEBGL_compressed_texture_pvrtc", "EXT_color_buffer_half_float", "WEBGL_color_buffer_float",
+ "EXT_sRGB", "WEBGL_compressed_texture_etc1", "EXT_disjoint_timer_query",
+ "WEBGL_compressed_texture_etc", "WEBGL_compressed_texture_astc", "EXT_color_buffer_float",
+ "WEBGL_compressed_texture_s3tc_srgb", "EXT_disjoint_timer_query_webgl2",
+ // Old style prefixed forms of extensions (but still currently used on e.g. iPhone Xs as
+ // tested on iOS 12.4.1):
+ "WEBKIT_WEBGL_compressed_texture_pvrtc"];
+
+ function shouldEnableAutomatically(extension) {
+ var ret = false;
+ automaticallyEnabledExtensions.forEach(function(include) {
+ if (extension.indexOf(include) != -1) {
+ ret = true;
+ }
+ });
+ return ret;
+ }
+
+ var exts = GLctx.getSupportedExtensions() || []; // .getSupportedExtensions() can return null if context is lost, so coerce to empty array.
+ exts.forEach(function(ext) {
+ if (automaticallyEnabledExtensions.indexOf(ext) != -1) {
+ GLctx.getExtension(ext); // Calling .getExtension enables that extension permanently, no need to store the return value to be enabled.
+ }
+ });
+ },populateUniformTable:function(program) {
+ var p = GL.programs[program];
+ var ptable = GL.programInfos[program] = {
+ uniforms: {},
+ maxUniformLength: 0, // This is eagerly computed below, since we already enumerate all uniforms anyway.
+ maxAttributeLength: -1, // This is lazily computed and cached, computed when/if first asked, "-1" meaning not computed yet.
+ maxUniformBlockNameLength: -1 // Lazily computed as well
+ };
+
+ var utable = ptable.uniforms;
+ // A program's uniform table maps the string name of an uniform to an integer location of that uniform.
+ // The global GL.uniforms map maps integer locations to WebGLUniformLocations.
+ var numUniforms = GLctx.getProgramParameter(p, 0x8B86/*GL_ACTIVE_UNIFORMS*/);
+ for (var i = 0; i < numUniforms; ++i) {
+ var u = GLctx.getActiveUniform(p, i);
+
+ var name = u.name;
+ ptable.maxUniformLength = Math.max(ptable.maxUniformLength, name.length+1);
+
+ // If we are dealing with an array, e.g. vec4 foo[3], strip off the array index part to canonicalize that "foo", "foo[]",
+ // and "foo[0]" will mean the same. Loop below will populate foo[1] and foo[2].
+ if (name.slice(-1) == ']') {
+ name = name.slice(0, name.lastIndexOf('['));
+ }
+
+ // Optimize memory usage slightly: If we have an array of uniforms, e.g. 'vec3 colors[3];', then
+ // only store the string 'colors' in utable, and 'colors[0]', 'colors[1]' and 'colors[2]' will be parsed as 'colors'+i.
+ // Note that for the GL.uniforms table, we still need to fetch the all WebGLUniformLocations for all the indices.
+ var loc = GLctx.getUniformLocation(p, name);
+ if (loc) {
+ var id = GL.getNewId(GL.uniforms);
+ utable[name] = [u.size, id];
+ GL.uniforms[id] = loc;
+
+ for (var j = 1; j < u.size; ++j) {
+ var n = name + '['+j+']';
+ loc = GLctx.getUniformLocation(p, n);
+ id = GL.getNewId(GL.uniforms);
+
+ GL.uniforms[id] = loc;
+ }
+ }
+ }
+ }};function _emscripten_glActiveTexture(x0) { GLctx['activeTexture'](x0) }
+
+ function _emscripten_glAttachShader(program, shader) {
+ GLctx.attachShader(GL.programs[program],
+ GL.shaders[shader]);
+ }
+
+ function _emscripten_glBeginQueryEXT(target, id) {
+ GLctx.disjointTimerQueryExt['beginQueryEXT'](target, GL.timerQueriesEXT[id]);
+ }
+
+ function _emscripten_glBindAttribLocation(program, index, name) {
+ GLctx.bindAttribLocation(GL.programs[program], index, UTF8ToString(name));
+ }
+
+ function _emscripten_glBindBuffer(target, buffer) {
+
+ GLctx.bindBuffer(target, GL.buffers[buffer]);
+ }
+
+ function _emscripten_glBindFramebuffer(target, framebuffer) {
+
+ GLctx.bindFramebuffer(target, GL.framebuffers[framebuffer]);
+
+ }
+
+ function _emscripten_glBindRenderbuffer(target, renderbuffer) {
+ GLctx.bindRenderbuffer(target, GL.renderbuffers[renderbuffer]);
+ }
+
+ function _emscripten_glBindTexture(target, texture) {
+ GLctx.bindTexture(target, GL.textures[texture]);
+ }
+
+ function _emscripten_glBindVertexArrayOES(vao) {
+ GLctx['bindVertexArray'](GL.vaos[vao]);
+ }
+
+ function _emscripten_glBlendColor(x0, x1, x2, x3) { GLctx['blendColor'](x0, x1, x2, x3) }
+
+ function _emscripten_glBlendEquation(x0) { GLctx['blendEquation'](x0) }
+
+ function _emscripten_glBlendEquationSeparate(x0, x1) { GLctx['blendEquationSeparate'](x0, x1) }
+
+ function _emscripten_glBlendFunc(x0, x1) { GLctx['blendFunc'](x0, x1) }
+
+ function _emscripten_glBlendFuncSeparate(x0, x1, x2, x3) { GLctx['blendFuncSeparate'](x0, x1, x2, x3) }
+
+ function _emscripten_glBufferData(target, size, data, usage) {
+
+ // N.b. here first form specifies a heap subarray, second form an integer size, so the ?: code here is polymorphic. It is advised to avoid
+ // randomly mixing both uses in calling code, to avoid any potential JS engine JIT issues.
+ GLctx.bufferData(target, data ? HEAPU8.subarray(data, data+size) : size, usage);
+ }
+
+ function _emscripten_glBufferSubData(target, offset, size, data) {
+ GLctx.bufferSubData(target, offset, HEAPU8.subarray(data, data+size));
+ }
+
+ function _emscripten_glCheckFramebufferStatus(x0) { return GLctx['checkFramebufferStatus'](x0) }
+
+ function _emscripten_glClear(x0) { GLctx['clear'](x0) }
+
+ function _emscripten_glClearColor(x0, x1, x2, x3) { GLctx['clearColor'](x0, x1, x2, x3) }
+
+ function _emscripten_glClearDepthf(x0) { GLctx['clearDepth'](x0) }
+
+ function _emscripten_glClearStencil(x0) { GLctx['clearStencil'](x0) }
+
+ function _emscripten_glColorMask(red, green, blue, alpha) {
+ GLctx.colorMask(!!red, !!green, !!blue, !!alpha);
+ }
+
+ function _emscripten_glCompileShader(shader) {
+ GLctx.compileShader(GL.shaders[shader]);
+ }
+
+ function _emscripten_glCompressedTexImage2D(target, level, internalFormat, width, height, border, imageSize, data) {
+ GLctx['compressedTexImage2D'](target, level, internalFormat, width, height, border, data ? HEAPU8.subarray((data),(data+imageSize)) : null);
+ }
+
+ function _emscripten_glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data) {
+ GLctx['compressedTexSubImage2D'](target, level, xoffset, yoffset, width, height, format, data ? HEAPU8.subarray((data),(data+imageSize)) : null);
+ }
+
+ function _emscripten_glCopyTexImage2D(x0, x1, x2, x3, x4, x5, x6, x7) { GLctx['copyTexImage2D'](x0, x1, x2, x3, x4, x5, x6, x7) }
+
+ function _emscripten_glCopyTexSubImage2D(x0, x1, x2, x3, x4, x5, x6, x7) { GLctx['copyTexSubImage2D'](x0, x1, x2, x3, x4, x5, x6, x7) }
+
+ function _emscripten_glCreateProgram() {
+ var id = GL.getNewId(GL.programs);
+ var program = GLctx.createProgram();
+ program.name = id;
+ GL.programs[id] = program;
+ return id;
+ }
+
+ function _emscripten_glCreateShader(shaderType) {
+ var id = GL.getNewId(GL.shaders);
+ GL.shaders[id] = GLctx.createShader(shaderType);
+ return id;
+ }
+
+ function _emscripten_glCullFace(x0) { GLctx['cullFace'](x0) }
+
+ function _emscripten_glDeleteBuffers(n, buffers) {
+ for (var i = 0; i < n; i++) {
+ var id = HEAP32[(((buffers)+(i*4))>>2)];
+ var buffer = GL.buffers[id];
+
+ // From spec: "glDeleteBuffers silently ignores 0's and names that do not
+ // correspond to existing buffer objects."
+ if (!buffer) continue;
+
+ GLctx.deleteBuffer(buffer);
+ buffer.name = 0;
+ GL.buffers[id] = null;
+
+ }
+ }
+
+ function _emscripten_glDeleteFramebuffers(n, framebuffers) {
+ for (var i = 0; i < n; ++i) {
+ var id = HEAP32[(((framebuffers)+(i*4))>>2)];
+ var framebuffer = GL.framebuffers[id];
+ if (!framebuffer) continue; // GL spec: "glDeleteFramebuffers silently ignores 0s and names that do not correspond to existing framebuffer objects".
+ GLctx.deleteFramebuffer(framebuffer);
+ framebuffer.name = 0;
+ GL.framebuffers[id] = null;
+ }
+ }
+
+ function _emscripten_glDeleteProgram(id) {
+ if (!id) return;
+ var program = GL.programs[id];
+ if (!program) { // glDeleteProgram actually signals an error when deleting a nonexisting object, unlike some other GL delete functions.
+ GL.recordError(0x501 /* GL_INVALID_VALUE */);
+ return;
+ }
+ GLctx.deleteProgram(program);
+ program.name = 0;
+ GL.programs[id] = null;
+ GL.programInfos[id] = null;
+ }
+
+ function _emscripten_glDeleteQueriesEXT(n, ids) {
+ for (var i = 0; i < n; i++) {
+ var id = HEAP32[(((ids)+(i*4))>>2)];
+ var query = GL.timerQueriesEXT[id];
+ if (!query) continue; // GL spec: "unused names in ids are ignored, as is the name zero."
+ GLctx.disjointTimerQueryExt['deleteQueryEXT'](query);
+ GL.timerQueriesEXT[id] = null;
+ }
+ }
+
+ function _emscripten_glDeleteRenderbuffers(n, renderbuffers) {
+ for (var i = 0; i < n; i++) {
+ var id = HEAP32[(((renderbuffers)+(i*4))>>2)];
+ var renderbuffer = GL.renderbuffers[id];
+ if (!renderbuffer) continue; // GL spec: "glDeleteRenderbuffers silently ignores 0s and names that do not correspond to existing renderbuffer objects".
+ GLctx.deleteRenderbuffer(renderbuffer);
+ renderbuffer.name = 0;
+ GL.renderbuffers[id] = null;
+ }
+ }
+
+ function _emscripten_glDeleteShader(id) {
+ if (!id) return;
+ var shader = GL.shaders[id];
+ if (!shader) { // glDeleteShader actually signals an error when deleting a nonexisting object, unlike some other GL delete functions.
+ GL.recordError(0x501 /* GL_INVALID_VALUE */);
+ return;
+ }
+ GLctx.deleteShader(shader);
+ GL.shaders[id] = null;
+ }
+
+ function _emscripten_glDeleteTextures(n, textures) {
+ for (var i = 0; i < n; i++) {
+ var id = HEAP32[(((textures)+(i*4))>>2)];
+ var texture = GL.textures[id];
+ if (!texture) continue; // GL spec: "glDeleteTextures silently ignores 0s and names that do not correspond to existing textures".
+ GLctx.deleteTexture(texture);
+ texture.name = 0;
+ GL.textures[id] = null;
+ }
+ }
+
+ function _emscripten_glDeleteVertexArraysOES(n, vaos) {
+ for (var i = 0; i < n; i++) {
+ var id = HEAP32[(((vaos)+(i*4))>>2)];
+ GLctx['deleteVertexArray'](GL.vaos[id]);
+ GL.vaos[id] = null;
+ }
+ }
+
+ function _emscripten_glDepthFunc(x0) { GLctx['depthFunc'](x0) }
+
+ function _emscripten_glDepthMask(flag) {
+ GLctx.depthMask(!!flag);
+ }
+
+ function _emscripten_glDepthRangef(x0, x1) { GLctx['depthRange'](x0, x1) }
+
+ function _emscripten_glDetachShader(program, shader) {
+ GLctx.detachShader(GL.programs[program],
+ GL.shaders[shader]);
+ }
+
+ function _emscripten_glDisable(x0) { GLctx['disable'](x0) }
+
+ function _emscripten_glDisableVertexAttribArray(index) {
+ GLctx.disableVertexAttribArray(index);
+ }
+
+ function _emscripten_glDrawArrays(mode, first, count) {
+
+ GLctx.drawArrays(mode, first, count);
+
+ }
+
+ function _emscripten_glDrawArraysInstancedANGLE(mode, first, count, primcount) {
+ GLctx['drawArraysInstanced'](mode, first, count, primcount);
+ }
+
+
+ var tempFixedLengthArray=[];function _emscripten_glDrawBuffersWEBGL(n, bufs) {
+
+ var bufArray = tempFixedLengthArray[n];
+ for (var i = 0; i < n; i++) {
+ bufArray[i] = HEAP32[(((bufs)+(i*4))>>2)];
+ }
+
+ GLctx['drawBuffers'](bufArray);
+ }
+
+ function _emscripten_glDrawElements(mode, count, type, indices) {
+
+ GLctx.drawElements(mode, count, type, indices);
+
+ }
+
+ function _emscripten_glDrawElementsInstancedANGLE(mode, count, type, indices, primcount) {
+ GLctx['drawElementsInstanced'](mode, count, type, indices, primcount);
+ }
+
+ function _emscripten_glEnable(x0) { GLctx['enable'](x0) }
+
+ function _emscripten_glEnableVertexAttribArray(index) {
+ GLctx.enableVertexAttribArray(index);
+ }
+
+ function _emscripten_glEndQueryEXT(target) {
+ GLctx.disjointTimerQueryExt['endQueryEXT'](target);
+ }
+
+ function _emscripten_glFinish() { GLctx['finish']() }
+
+ function _emscripten_glFlush() { GLctx['flush']() }
+
+ function _emscripten_glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer) {
+ GLctx.framebufferRenderbuffer(target, attachment, renderbuffertarget,
+ GL.renderbuffers[renderbuffer]);
+ }
+
+ function _emscripten_glFramebufferTexture2D(target, attachment, textarget, texture, level) {
+ GLctx.framebufferTexture2D(target, attachment, textarget,
+ GL.textures[texture], level);
+ }
+
+ function _emscripten_glFrontFace(x0) { GLctx['frontFace'](x0) }
+
+
+ function __glGenObject(n, buffers, createFunction, objectTable
+ ) {
+ for (var i = 0; i < n; i++) {
+ var buffer = GLctx[createFunction]();
+ var id = buffer && GL.getNewId(objectTable);
+ if (buffer) {
+ buffer.name = id;
+ objectTable[id] = buffer;
+ } else {
+ GL.recordError(0x502 /* GL_INVALID_OPERATION */);
+ }
+ HEAP32[(((buffers)+(i*4))>>2)]=id;
+ }
+ }function _emscripten_glGenBuffers(n, buffers) {
+ __glGenObject(n, buffers, 'createBuffer', GL.buffers
+ );
+ }
+
+ function _emscripten_glGenFramebuffers(n, ids) {
+ __glGenObject(n, ids, 'createFramebuffer', GL.framebuffers
+ );
+ }
+
+ function _emscripten_glGenQueriesEXT(n, ids) {
+ for (var i = 0; i < n; i++) {
+ var query = GLctx.disjointTimerQueryExt['createQueryEXT']();
+ if (!query) {
+ GL.recordError(0x502 /* GL_INVALID_OPERATION */);
+ while(i < n) HEAP32[(((ids)+(i++*4))>>2)]=0;
+ return;
+ }
+ var id = GL.getNewId(GL.timerQueriesEXT);
+ query.name = id;
+ GL.timerQueriesEXT[id] = query;
+ HEAP32[(((ids)+(i*4))>>2)]=id;
+ }
+ }
+
+ function _emscripten_glGenRenderbuffers(n, renderbuffers) {
+ __glGenObject(n, renderbuffers, 'createRenderbuffer', GL.renderbuffers
+ );
+ }
+
+ function _emscripten_glGenTextures(n, textures) {
+ __glGenObject(n, textures, 'createTexture', GL.textures
+ );
+ }
+
+ function _emscripten_glGenVertexArraysOES(n, arrays) {
+ __glGenObject(n, arrays, 'createVertexArray', GL.vaos
+ );
+ }
+
+ function _emscripten_glGenerateMipmap(x0) { GLctx['generateMipmap'](x0) }
+
+
+ function __glGetActiveAttribOrUniform(funcName, program, index, bufSize, length, size, type, name) {
+ program = GL.programs[program];
+ var info = GLctx[funcName](program, index);
+ if (info) { // If an error occurs, nothing will be written to length, size and type and name.
+ var numBytesWrittenExclNull = name && stringToUTF8(info.name, name, bufSize);
+ if (length) HEAP32[((length)>>2)]=numBytesWrittenExclNull;
+ if (size) HEAP32[((size)>>2)]=info.size;
+ if (type) HEAP32[((type)>>2)]=info.type;
+ }
+ }function _emscripten_glGetActiveAttrib(program, index, bufSize, length, size, type, name) {
+ __glGetActiveAttribOrUniform('getActiveAttrib', program, index, bufSize, length, size, type, name);
+ }
+
+ function _emscripten_glGetActiveUniform(program, index, bufSize, length, size, type, name) {
+ __glGetActiveAttribOrUniform('getActiveUniform', program, index, bufSize, length, size, type, name);
+ }
+
+ function _emscripten_glGetAttachedShaders(program, maxCount, count, shaders) {
+ var result = GLctx.getAttachedShaders(GL.programs[program]);
+ var len = result.length;
+ if (len > maxCount) {
+ len = maxCount;
+ }
+ HEAP32[((count)>>2)]=len;
+ for (var i = 0; i < len; ++i) {
+ var id = GL.shaders.indexOf(result[i]);
+ HEAP32[(((shaders)+(i*4))>>2)]=id;
+ }
+ }
+
+ function _emscripten_glGetAttribLocation(program, name) {
+ return GLctx.getAttribLocation(GL.programs[program], UTF8ToString(name));
+ }
+
+
+
+ function writeI53ToI64(ptr, num) {
+ HEAPU32[ptr>>2] = num;
+ HEAPU32[ptr+4>>2] = (num - HEAPU32[ptr>>2])/4294967296;
+ }function emscriptenWebGLGet(name_, p, type) {
+ // Guard against user passing a null pointer.
+ // Note that GLES2 spec does not say anything about how passing a null pointer should be treated.
+ // Testing on desktop core GL 3, the application crashes on glGetIntegerv to a null pointer, but
+ // better to report an error instead of doing anything random.
+ if (!p) {
+ GL.recordError(0x501 /* GL_INVALID_VALUE */);
+ return;
+ }
+ var ret = undefined;
+ switch(name_) { // Handle a few trivial GLES values
+ case 0x8DFA: // GL_SHADER_COMPILER
+ ret = 1;
+ break;
+ case 0x8DF8: // GL_SHADER_BINARY_FORMATS
+ if (type != 0 && type != 1) {
+ GL.recordError(0x500); // GL_INVALID_ENUM
+ }
+ return; // Do not write anything to the out pointer, since no binary formats are supported.
+ case 0x8DF9: // GL_NUM_SHADER_BINARY_FORMATS
+ ret = 0;
+ break;
+ case 0x86A2: // GL_NUM_COMPRESSED_TEXTURE_FORMATS
+ // WebGL doesn't have GL_NUM_COMPRESSED_TEXTURE_FORMATS (it's obsolete since GL_COMPRESSED_TEXTURE_FORMATS returns a JS array that can be queried for length),
+ // so implement it ourselves to allow C++ GLES2 code get the length.
+ var formats = GLctx.getParameter(0x86A3 /*GL_COMPRESSED_TEXTURE_FORMATS*/);
+ ret = formats ? formats.length : 0;
+ break;
+ }
+
+ if (ret === undefined) {
+ var result = GLctx.getParameter(name_);
+ switch (typeof(result)) {
+ case "number":
+ ret = result;
+ break;
+ case "boolean":
+ ret = result ? 1 : 0;
+ break;
+ case "string":
+ GL.recordError(0x500); // GL_INVALID_ENUM
+ return;
+ case "object":
+ if (result === null) {
+ // null is a valid result for some (e.g., which buffer is bound - perhaps nothing is bound), but otherwise
+ // can mean an invalid name_, which we need to report as an error
+ switch(name_) {
+ case 0x8894: // ARRAY_BUFFER_BINDING
+ case 0x8B8D: // CURRENT_PROGRAM
+ case 0x8895: // ELEMENT_ARRAY_BUFFER_BINDING
+ case 0x8CA6: // FRAMEBUFFER_BINDING or DRAW_FRAMEBUFFER_BINDING
+ case 0x8CA7: // RENDERBUFFER_BINDING
+ case 0x8069: // TEXTURE_BINDING_2D
+ case 0x85B5: // WebGL 2 GL_VERTEX_ARRAY_BINDING, or WebGL 1 extension OES_vertex_array_object GL_VERTEX_ARRAY_BINDING_OES
+ case 0x8514: { // TEXTURE_BINDING_CUBE_MAP
+ ret = 0;
+ break;
+ }
+ default: {
+ GL.recordError(0x500); // GL_INVALID_ENUM
+ return;
+ }
+ }
+ } else if (result instanceof Float32Array ||
+ result instanceof Uint32Array ||
+ result instanceof Int32Array ||
+ result instanceof Array) {
+ for (var i = 0; i < result.length; ++i) {
+ switch (type) {
+ case 0: HEAP32[(((p)+(i*4))>>2)]=result[i]; break;
+ case 2: HEAPF32[(((p)+(i*4))>>2)]=result[i]; break;
+ case 4: HEAP8[(((p)+(i))>>0)]=result[i] ? 1 : 0; break;
+ }
+ }
+ return;
+ } else {
+ try {
+ ret = result.name | 0;
+ } catch(e) {
+ GL.recordError(0x500); // GL_INVALID_ENUM
+ err('GL_INVALID_ENUM in glGet' + type + 'v: Unknown object returned from WebGL getParameter(' + name_ + ')! (error: ' + e + ')');
+ return;
+ }
+ }
+ break;
+ default:
+ GL.recordError(0x500); // GL_INVALID_ENUM
+ err('GL_INVALID_ENUM in glGet' + type + 'v: Native code calling glGet' + type + 'v(' + name_ + ') and it returns ' + result + ' of type ' + typeof(result) + '!');
+ return;
+ }
+ }
+
+ switch (type) {
+ case 1: writeI53ToI64(p, ret); break;
+ case 0: HEAP32[((p)>>2)]=ret; break;
+ case 2: HEAPF32[((p)>>2)]=ret; break;
+ case 4: HEAP8[((p)>>0)]=ret ? 1 : 0; break;
+ }
+ }function _emscripten_glGetBooleanv(name_, p) {
+ emscriptenWebGLGet(name_, p, 4);
+ }
+
+ function _emscripten_glGetBufferParameteriv(target, value, data) {
+ if (!data) {
+ // GLES2 specification does not specify how to behave if data is a null pointer. Since calling this function does not make sense
+ // if data == null, issue a GL error to notify user about it.
+ GL.recordError(0x501 /* GL_INVALID_VALUE */);
+ return;
+ }
+ HEAP32[((data)>>2)]=GLctx.getBufferParameter(target, value);
+ }
+
+ function _emscripten_glGetError() {
+ var error = GLctx.getError() || GL.lastError;
+ GL.lastError = 0/*GL_NO_ERROR*/;
+ return error;
+ }
+
+ function _emscripten_glGetFloatv(name_, p) {
+ emscriptenWebGLGet(name_, p, 2);
+ }
+
+ function _emscripten_glGetFramebufferAttachmentParameteriv(target, attachment, pname, params) {
+ var result = GLctx.getFramebufferAttachmentParameter(target, attachment, pname);
+ if (result instanceof WebGLRenderbuffer ||
+ result instanceof WebGLTexture) {
+ result = result.name | 0;
+ }
+ HEAP32[((params)>>2)]=result;
+ }
+
+ function _emscripten_glGetIntegerv(name_, p) {
+ emscriptenWebGLGet(name_, p, 0);
+ }
+
+ function _emscripten_glGetProgramInfoLog(program, maxLength, length, infoLog) {
+ var log = GLctx.getProgramInfoLog(GL.programs[program]);
+ if (log === null) log = '(unknown error)';
+ var numBytesWrittenExclNull = (maxLength > 0 && infoLog) ? stringToUTF8(log, infoLog, maxLength) : 0;
+ if (length) HEAP32[((length)>>2)]=numBytesWrittenExclNull;
+ }
+
+ function _emscripten_glGetProgramiv(program, pname, p) {
+ if (!p) {
+ // GLES2 specification does not specify how to behave if p is a null pointer. Since calling this function does not make sense
+ // if p == null, issue a GL error to notify user about it.
+ GL.recordError(0x501 /* GL_INVALID_VALUE */);
+ return;
+ }
+
+ if (program >= GL.counter) {
+ GL.recordError(0x501 /* GL_INVALID_VALUE */);
+ return;
+ }
+
+ var ptable = GL.programInfos[program];
+ if (!ptable) {
+ GL.recordError(0x502 /* GL_INVALID_OPERATION */);
+ return;
+ }
+
+ if (pname == 0x8B84) { // GL_INFO_LOG_LENGTH
+ var log = GLctx.getProgramInfoLog(GL.programs[program]);
+ if (log === null) log = '(unknown error)';
+ HEAP32[((p)>>2)]=log.length + 1;
+ } else if (pname == 0x8B87 /* GL_ACTIVE_UNIFORM_MAX_LENGTH */) {
+ HEAP32[((p)>>2)]=ptable.maxUniformLength;
+ } else if (pname == 0x8B8A /* GL_ACTIVE_ATTRIBUTE_MAX_LENGTH */) {
+ if (ptable.maxAttributeLength == -1) {
+ program = GL.programs[program];
+ var numAttribs = GLctx.getProgramParameter(program, 0x8B89/*GL_ACTIVE_ATTRIBUTES*/);
+ ptable.maxAttributeLength = 0; // Spec says if there are no active attribs, 0 must be returned.
+ for (var i = 0; i < numAttribs; ++i) {
+ var activeAttrib = GLctx.getActiveAttrib(program, i);
+ ptable.maxAttributeLength = Math.max(ptable.maxAttributeLength, activeAttrib.name.length+1);
+ }
+ }
+ HEAP32[((p)>>2)]=ptable.maxAttributeLength;
+ } else if (pname == 0x8A35 /* GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH */) {
+ if (ptable.maxUniformBlockNameLength == -1) {
+ program = GL.programs[program];
+ var numBlocks = GLctx.getProgramParameter(program, 0x8A36/*GL_ACTIVE_UNIFORM_BLOCKS*/);
+ ptable.maxUniformBlockNameLength = 0;
+ for (var i = 0; i < numBlocks; ++i) {
+ var activeBlockName = GLctx.getActiveUniformBlockName(program, i);
+ ptable.maxUniformBlockNameLength = Math.max(ptable.maxUniformBlockNameLength, activeBlockName.length+1);
+ }
+ }
+ HEAP32[((p)>>2)]=ptable.maxUniformBlockNameLength;
+ } else {
+ HEAP32[((p)>>2)]=GLctx.getProgramParameter(GL.programs[program], pname);
+ }
+ }
+
+ function _emscripten_glGetQueryObjecti64vEXT(id, pname, params) {
+ if (!params) {
+ // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense
+ // if p == null, issue a GL error to notify user about it.
+ GL.recordError(0x501 /* GL_INVALID_VALUE */);
+ return;
+ }
+ var query = GL.timerQueriesEXT[id];
+ var param = GLctx.disjointTimerQueryExt['getQueryObjectEXT'](query, pname);
+ var ret;
+ if (typeof param == 'boolean') {
+ ret = param ? 1 : 0;
+ } else {
+ ret = param;
+ }
+ writeI53ToI64(params, ret);
+ }
+
+ function _emscripten_glGetQueryObjectivEXT(id, pname, params) {
+ if (!params) {
+ // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense
+ // if p == null, issue a GL error to notify user about it.
+ GL.recordError(0x501 /* GL_INVALID_VALUE */);
+ return;
+ }
+ var query = GL.timerQueriesEXT[id];
+ var param = GLctx.disjointTimerQueryExt['getQueryObjectEXT'](query, pname);
+ var ret;
+ if (typeof param == 'boolean') {
+ ret = param ? 1 : 0;
+ } else {
+ ret = param;
+ }
+ HEAP32[((params)>>2)]=ret;
+ }
+
+ function _emscripten_glGetQueryObjectui64vEXT(id, pname, params) {
+ if (!params) {
+ // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense
+ // if p == null, issue a GL error to notify user about it.
+ GL.recordError(0x501 /* GL_INVALID_VALUE */);
+ return;
+ }
+ var query = GL.timerQueriesEXT[id];
+ var param = GLctx.disjointTimerQueryExt['getQueryObjectEXT'](query, pname);
+ var ret;
+ if (typeof param == 'boolean') {
+ ret = param ? 1 : 0;
+ } else {
+ ret = param;
+ }
+ writeI53ToI64(params, ret);
+ }
+
+ function _emscripten_glGetQueryObjectuivEXT(id, pname, params) {
+ if (!params) {
+ // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense
+ // if p == null, issue a GL error to notify user about it.
+ GL.recordError(0x501 /* GL_INVALID_VALUE */);
+ return;
+ }
+ var query = GL.timerQueriesEXT[id];
+ var param = GLctx.disjointTimerQueryExt['getQueryObjectEXT'](query, pname);
+ var ret;
+ if (typeof param == 'boolean') {
+ ret = param ? 1 : 0;
+ } else {
+ ret = param;
+ }
+ HEAP32[((params)>>2)]=ret;
+ }
+
+ function _emscripten_glGetQueryivEXT(target, pname, params) {
+ if (!params) {
+ // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense
+ // if p == null, issue a GL error to notify user about it.
+ GL.recordError(0x501 /* GL_INVALID_VALUE */);
+ return;
+ }
+ HEAP32[((params)>>2)]=GLctx.disjointTimerQueryExt['getQueryEXT'](target, pname);
+ }
+
+ function _emscripten_glGetRenderbufferParameteriv(target, pname, params) {
+ if (!params) {
+ // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense
+ // if params == null, issue a GL error to notify user about it.
+ GL.recordError(0x501 /* GL_INVALID_VALUE */);
+ return;
+ }
+ HEAP32[((params)>>2)]=GLctx.getRenderbufferParameter(target, pname);
+ }
+
+ function _emscripten_glGetShaderInfoLog(shader, maxLength, length, infoLog) {
+ var log = GLctx.getShaderInfoLog(GL.shaders[shader]);
+ if (log === null) log = '(unknown error)';
+ var numBytesWrittenExclNull = (maxLength > 0 && infoLog) ? stringToUTF8(log, infoLog, maxLength) : 0;
+ if (length) HEAP32[((length)>>2)]=numBytesWrittenExclNull;
+ }
+
+ function _emscripten_glGetShaderPrecisionFormat(shaderType, precisionType, range, precision) {
+ var result = GLctx.getShaderPrecisionFormat(shaderType, precisionType);
+ HEAP32[((range)>>2)]=result.rangeMin;
+ HEAP32[(((range)+(4))>>2)]=result.rangeMax;
+ HEAP32[((precision)>>2)]=result.precision;
+ }
+
+ function _emscripten_glGetShaderSource(shader, bufSize, length, source) {
+ var result = GLctx.getShaderSource(GL.shaders[shader]);
+ if (!result) return; // If an error occurs, nothing will be written to length or source.
+ var numBytesWrittenExclNull = (bufSize > 0 && source) ? stringToUTF8(result, source, bufSize) : 0;
+ if (length) HEAP32[((length)>>2)]=numBytesWrittenExclNull;
+ }
+
+ function _emscripten_glGetShaderiv(shader, pname, p) {
+ if (!p) {
+ // GLES2 specification does not specify how to behave if p is a null pointer. Since calling this function does not make sense
+ // if p == null, issue a GL error to notify user about it.
+ GL.recordError(0x501 /* GL_INVALID_VALUE */);
+ return;
+ }
+ if (pname == 0x8B84) { // GL_INFO_LOG_LENGTH
+ var log = GLctx.getShaderInfoLog(GL.shaders[shader]);
+ if (log === null) log = '(unknown error)';
+ // The GLES2 specification says that if the shader has an empty info log,
+ // a value of 0 is returned. Otherwise the log has a null char appended.
+ // (An empty string is falsey, so we can just check that instead of
+ // looking at log.length.)
+ var logLength = log ? log.length + 1 : 0;
+ HEAP32[((p)>>2)]=logLength;
+ } else if (pname == 0x8B88) { // GL_SHADER_SOURCE_LENGTH
+ var source = GLctx.getShaderSource(GL.shaders[shader]);
+ // source may be a null, or the empty string, both of which are falsey
+ // values that we report a 0 length for.
+ var sourceLength = source ? source.length + 1 : 0;
+ HEAP32[((p)>>2)]=sourceLength;
+ } else {
+ HEAP32[((p)>>2)]=GLctx.getShaderParameter(GL.shaders[shader], pname);
+ }
+ }
+
+
+ function stringToNewUTF8(jsString) {
+ var length = lengthBytesUTF8(jsString)+1;
+ var cString = _malloc(length);
+ stringToUTF8(jsString, cString, length);
+ return cString;
+ }function _emscripten_glGetString(name_) {
+ if (GL.stringCache[name_]) return GL.stringCache[name_];
+ var ret;
+ switch(name_) {
+ case 0x1F03 /* GL_EXTENSIONS */:
+ var exts = GLctx.getSupportedExtensions() || []; // .getSupportedExtensions() can return null if context is lost, so coerce to empty array.
+ exts = exts.concat(exts.map(function(e) { return "GL_" + e; }));
+ ret = stringToNewUTF8(exts.join(' '));
+ break;
+ case 0x1F00 /* GL_VENDOR */:
+ case 0x1F01 /* GL_RENDERER */:
+ case 0x9245 /* UNMASKED_VENDOR_WEBGL */:
+ case 0x9246 /* UNMASKED_RENDERER_WEBGL */:
+ var s = GLctx.getParameter(name_);
+ if (!s) {
+ GL.recordError(0x500/*GL_INVALID_ENUM*/);
+ }
+ ret = stringToNewUTF8(s);
+ break;
+
+ case 0x1F02 /* GL_VERSION */:
+ var glVersion = GLctx.getParameter(0x1F02 /*GL_VERSION*/);
+ // return GLES version string corresponding to the version of the WebGL context
+ {
+ glVersion = 'OpenGL ES 2.0 (' + glVersion + ')';
+ }
+ ret = stringToNewUTF8(glVersion);
+ break;
+ case 0x8B8C /* GL_SHADING_LANGUAGE_VERSION */:
+ var glslVersion = GLctx.getParameter(0x8B8C /*GL_SHADING_LANGUAGE_VERSION*/);
+ // extract the version number 'N.M' from the string 'WebGL GLSL ES N.M ...'
+ var ver_re = /^WebGL GLSL ES ([0-9]\.[0-9][0-9]?)(?:$| .*)/;
+ var ver_num = glslVersion.match(ver_re);
+ if (ver_num !== null) {
+ if (ver_num[1].length == 3) ver_num[1] = ver_num[1] + '0'; // ensure minor version has 2 digits
+ glslVersion = 'OpenGL ES GLSL ES ' + ver_num[1] + ' (' + glslVersion + ')';
+ }
+ ret = stringToNewUTF8(glslVersion);
+ break;
+ default:
+ GL.recordError(0x500/*GL_INVALID_ENUM*/);
+ return 0;
+ }
+ GL.stringCache[name_] = ret;
+ return ret;
+ }
+
+ function _emscripten_glGetTexParameterfv(target, pname, params) {
+ if (!params) {
+ // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense
+ // if p == null, issue a GL error to notify user about it.
+ GL.recordError(0x501 /* GL_INVALID_VALUE */);
+ return;
+ }
+ HEAPF32[((params)>>2)]=GLctx.getTexParameter(target, pname);
+ }
+
+ function _emscripten_glGetTexParameteriv(target, pname, params) {
+ if (!params) {
+ // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense
+ // if p == null, issue a GL error to notify user about it.
+ GL.recordError(0x501 /* GL_INVALID_VALUE */);
+ return;
+ }
+ HEAP32[((params)>>2)]=GLctx.getTexParameter(target, pname);
+ }
+
+
+ /** @suppress {checkTypes} */
+ function jstoi_q(str) {
+ return parseInt(str);
+ }function _emscripten_glGetUniformLocation(program, name) {
+ name = UTF8ToString(name);
+
+ var arrayIndex = 0;
+ // If user passed an array accessor "[index]", parse the array index off the accessor.
+ if (name[name.length - 1] == ']') {
+ var leftBrace = name.lastIndexOf('[');
+ arrayIndex = name[leftBrace+1] != ']' ? jstoi_q(name.slice(leftBrace + 1)) : 0; // "index]", parseInt will ignore the ']' at the end; but treat "foo[]" as "foo[0]"
+ name = name.slice(0, leftBrace);
+ }
+
+ var uniformInfo = GL.programInfos[program] && GL.programInfos[program].uniforms[name]; // returns pair [ dimension_of_uniform_array, uniform_location ]
+ if (uniformInfo && arrayIndex >= 0 && arrayIndex < uniformInfo[0]) { // Check if user asked for an out-of-bounds element, i.e. for 'vec4 colors[3];' user could ask for 'colors[10]' which should return -1.
+ return uniformInfo[1] + arrayIndex;
+ } else {
+ return -1;
+ }
+ }
+
+
+ /** @suppress{checkTypes} */
+ function emscriptenWebGLGetUniform(program, location, params, type) {
+ if (!params) {
+ // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense
+ // if params == null, issue a GL error to notify user about it.
+ GL.recordError(0x501 /* GL_INVALID_VALUE */);
+ return;
+ }
+ var data = GLctx.getUniform(GL.programs[program], GL.uniforms[location]);
+ if (typeof data == 'number' || typeof data == 'boolean') {
+ switch (type) {
+ case 0: HEAP32[((params)>>2)]=data; break;
+ case 2: HEAPF32[((params)>>2)]=data; break;
+ }
+ } else {
+ for (var i = 0; i < data.length; i++) {
+ switch (type) {
+ case 0: HEAP32[(((params)+(i*4))>>2)]=data[i]; break;
+ case 2: HEAPF32[(((params)+(i*4))>>2)]=data[i]; break;
+ }
+ }
+ }
+ }function _emscripten_glGetUniformfv(program, location, params) {
+ emscriptenWebGLGetUniform(program, location, params, 2);
+ }
+
+ function _emscripten_glGetUniformiv(program, location, params) {
+ emscriptenWebGLGetUniform(program, location, params, 0);
+ }
+
+ function _emscripten_glGetVertexAttribPointerv(index, pname, pointer) {
+ if (!pointer) {
+ // GLES2 specification does not specify how to behave if pointer is a null pointer. Since calling this function does not make sense
+ // if pointer == null, issue a GL error to notify user about it.
+ GL.recordError(0x501 /* GL_INVALID_VALUE */);
+ return;
+ }
+ HEAP32[((pointer)>>2)]=GLctx.getVertexAttribOffset(index, pname);
+ }
+
+
+ /** @suppress{checkTypes} */
+ function emscriptenWebGLGetVertexAttrib(index, pname, params, type) {
+ if (!params) {
+ // GLES2 specification does not specify how to behave if params is a null pointer. Since calling this function does not make sense
+ // if params == null, issue a GL error to notify user about it.
+ GL.recordError(0x501 /* GL_INVALID_VALUE */);
+ return;
+ }
+ var data = GLctx.getVertexAttrib(index, pname);
+ if (pname == 0x889F/*VERTEX_ATTRIB_ARRAY_BUFFER_BINDING*/) {
+ HEAP32[((params)>>2)]=data && data["name"];
+ } else if (typeof data == 'number' || typeof data == 'boolean') {
+ switch (type) {
+ case 0: HEAP32[((params)>>2)]=data; break;
+ case 2: HEAPF32[((params)>>2)]=data; break;
+ case 5: HEAP32[((params)>>2)]=Math.fround(data); break;
+ }
+ } else {
+ for (var i = 0; i < data.length; i++) {
+ switch (type) {
+ case 0: HEAP32[(((params)+(i*4))>>2)]=data[i]; break;
+ case 2: HEAPF32[(((params)+(i*4))>>2)]=data[i]; break;
+ case 5: HEAP32[(((params)+(i*4))>>2)]=Math.fround(data[i]); break;
+ }
+ }
+ }
+ }function _emscripten_glGetVertexAttribfv(index, pname, params) {
+ // N.B. This function may only be called if the vertex attribute was specified using the function glVertexAttrib*f(),
+ // otherwise the results are undefined. (GLES3 spec 6.1.12)
+ emscriptenWebGLGetVertexAttrib(index, pname, params, 2);
+ }
+
+ function _emscripten_glGetVertexAttribiv(index, pname, params) {
+ // N.B. This function may only be called if the vertex attribute was specified using the function glVertexAttrib*f(),
+ // otherwise the results are undefined. (GLES3 spec 6.1.12)
+ emscriptenWebGLGetVertexAttrib(index, pname, params, 5);
+ }
+
+ function _emscripten_glHint(x0, x1) { GLctx['hint'](x0, x1) }
+
+ function _emscripten_glIsBuffer(buffer) {
+ var b = GL.buffers[buffer];
+ if (!b) return 0;
+ return GLctx.isBuffer(b);
+ }
+
+ function _emscripten_glIsEnabled(x0) { return GLctx['isEnabled'](x0) }
+
+ function _emscripten_glIsFramebuffer(framebuffer) {
+ var fb = GL.framebuffers[framebuffer];
+ if (!fb) return 0;
+ return GLctx.isFramebuffer(fb);
+ }
+
+ function _emscripten_glIsProgram(program) {
+ program = GL.programs[program];
+ if (!program) return 0;
+ return GLctx.isProgram(program);
+ }
+
+ function _emscripten_glIsQueryEXT(id) {
+ var query = GL.timerQueriesEXT[id];
+ if (!query) return 0;
+ return GLctx.disjointTimerQueryExt['isQueryEXT'](query);
+ }
+
+ function _emscripten_glIsRenderbuffer(renderbuffer) {
+ var rb = GL.renderbuffers[renderbuffer];
+ if (!rb) return 0;
+ return GLctx.isRenderbuffer(rb);
+ }
+
+ function _emscripten_glIsShader(shader) {
+ var s = GL.shaders[shader];
+ if (!s) return 0;
+ return GLctx.isShader(s);
+ }
+
+ function _emscripten_glIsTexture(id) {
+ var texture = GL.textures[id];
+ if (!texture) return 0;
+ return GLctx.isTexture(texture);
+ }
+
+ function _emscripten_glIsVertexArrayOES(array) {
+
+ var vao = GL.vaos[array];
+ if (!vao) return 0;
+ return GLctx['isVertexArray'](vao);
+ }
+
+ function _emscripten_glLineWidth(x0) { GLctx['lineWidth'](x0) }
+
+ function _emscripten_glLinkProgram(program) {
+ GLctx.linkProgram(GL.programs[program]);
+ GL.populateUniformTable(program);
+ }
+
+ function _emscripten_glPixelStorei(pname, param) {
+ if (pname == 0xCF5 /* GL_UNPACK_ALIGNMENT */) {
+ GL.unpackAlignment = param;
+ }
+ GLctx.pixelStorei(pname, param);
+ }
+
+ function _emscripten_glPolygonOffset(x0, x1) { GLctx['polygonOffset'](x0, x1) }
+
+ function _emscripten_glQueryCounterEXT(id, target) {
+ GLctx.disjointTimerQueryExt['queryCounterEXT'](GL.timerQueriesEXT[id], target);
+ }
+
+
+
+ function computeUnpackAlignedImageSize(width, height, sizePerPixel, alignment) {
+ function roundedToNextMultipleOf(x, y) {
+ return (x + y - 1) & -y;
+ }
+ var plainRowSize = width * sizePerPixel;
+ var alignedRowSize = roundedToNextMultipleOf(plainRowSize, alignment);
+ return height * alignedRowSize;
+ }
+
+ function __colorChannelsInGlTextureFormat(format) {
+ // Micro-optimizations for size: map format to size by subtracting smallest enum value (0x1902) from all values first.
+ // Also omit the most common size value (1) from the list, which is assumed by formats not on the list.
+ var colorChannels = {
+ // 0x1902 /* GL_DEPTH_COMPONENT */ - 0x1902: 1,
+ // 0x1906 /* GL_ALPHA */ - 0x1902: 1,
+ 5: 3,
+ 6: 4,
+ // 0x1909 /* GL_LUMINANCE */ - 0x1902: 1,
+ 8: 2,
+ 29502: 3,
+ 29504: 4,
+ };
+ return colorChannels[format - 0x1902]||1;
+ }
+
+ function heapObjectForWebGLType(type) {
+ // Micro-optimization for size: Subtract lowest GL enum number (0x1400/* GL_BYTE */) from type to compare
+ // smaller values for the heap, for shorter generated code size.
+ // Also the type HEAPU16 is not tested for explicitly, but any unrecognized type will return out HEAPU16.
+ // (since most types are HEAPU16)
+ type -= 0x1400;
+
+ if (type == 1) return HEAPU8;
+
+
+ if (type == 4) return HEAP32;
+
+ if (type == 6) return HEAPF32;
+
+ if (type == 5
+ || type == 28922
+ )
+ return HEAPU32;
+
+ return HEAPU16;
+ }
+
+ function heapAccessShiftForWebGLHeap(heap) {
+ return 31 - Math.clz32(heap.BYTES_PER_ELEMENT);
+ }function emscriptenWebGLGetTexPixelData(type, format, width, height, pixels, internalFormat) {
+ var heap = heapObjectForWebGLType(type);
+ var shift = heapAccessShiftForWebGLHeap(heap);
+ var byteSize = 1<<shift;
+ var sizePerPixel = __colorChannelsInGlTextureFormat(format) * byteSize;
+ var bytes = computeUnpackAlignedImageSize(width, height, sizePerPixel, GL.unpackAlignment);
+ return heap.subarray(pixels >> shift, pixels + bytes >> shift);
+ }function _emscripten_glReadPixels(x, y, width, height, format, type, pixels) {
+ var pixelData = emscriptenWebGLGetTexPixelData(type, format, width, height, pixels, format);
+ if (!pixelData) {
+ GL.recordError(0x500/*GL_INVALID_ENUM*/);
+ return;
+ }
+ GLctx.readPixels(x, y, width, height, format, type, pixelData);
+ }
+
+ function _emscripten_glReleaseShaderCompiler() {
+ // NOP (as allowed by GLES 2.0 spec)
+ }
+
+ function _emscripten_glRenderbufferStorage(x0, x1, x2, x3) { GLctx['renderbufferStorage'](x0, x1, x2, x3) }
+
+ function _emscripten_glSampleCoverage(value, invert) {
+ GLctx.sampleCoverage(value, !!invert);
+ }
+
+ function _emscripten_glScissor(x0, x1, x2, x3) { GLctx['scissor'](x0, x1, x2, x3) }
+
+ function _emscripten_glShaderBinary() {
+ GL.recordError(0x500/*GL_INVALID_ENUM*/);
+ }
+
+ function _emscripten_glShaderSource(shader, count, string, length) {
+ var source = GL.getSource(shader, count, string, length);
+
+
+ GLctx.shaderSource(GL.shaders[shader], source);
+ }
+
+ function _emscripten_glStencilFunc(x0, x1, x2) { GLctx['stencilFunc'](x0, x1, x2) }
+
+ function _emscripten_glStencilFuncSeparate(x0, x1, x2, x3) { GLctx['stencilFuncSeparate'](x0, x1, x2, x3) }
+
+ function _emscripten_glStencilMask(x0) { GLctx['stencilMask'](x0) }
+
+ function _emscripten_glStencilMaskSeparate(x0, x1) { GLctx['stencilMaskSeparate'](x0, x1) }
+
+ function _emscripten_glStencilOp(x0, x1, x2) { GLctx['stencilOp'](x0, x1, x2) }
+
+ function _emscripten_glStencilOpSeparate(x0, x1, x2, x3) { GLctx['stencilOpSeparate'](x0, x1, x2, x3) }
+
+ function _emscripten_glTexImage2D(target, level, internalFormat, width, height, border, format, type, pixels) {
+ GLctx.texImage2D(target, level, internalFormat, width, height, border, format, type, pixels ? emscriptenWebGLGetTexPixelData(type, format, width, height, pixels, internalFormat) : null);
+ }
+
+ function _emscripten_glTexParameterf(x0, x1, x2) { GLctx['texParameterf'](x0, x1, x2) }
+
+ function _emscripten_glTexParameterfv(target, pname, params) {
+ var param = HEAPF32[((params)>>2)];
+ GLctx.texParameterf(target, pname, param);
+ }
+
+ function _emscripten_glTexParameteri(x0, x1, x2) { GLctx['texParameteri'](x0, x1, x2) }
+
+ function _emscripten_glTexParameteriv(target, pname, params) {
+ var param = HEAP32[((params)>>2)];
+ GLctx.texParameteri(target, pname, param);
+ }
+
+ function _emscripten_glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels) {
+ var pixelData = null;
+ if (pixels) pixelData = emscriptenWebGLGetTexPixelData(type, format, width, height, pixels, 0);
+ GLctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixelData);
+ }
+
+ function _emscripten_glUniform1f(location, v0) {
+ GLctx.uniform1f(GL.uniforms[location], v0);
+ }
+
+
+ var miniTempWebGLFloatBuffers=[];function _emscripten_glUniform1fv(location, count, value) {
+
+
+
+ if (count <= 288) {
+ // avoid allocation when uploading few enough uniforms
+ var view = miniTempWebGLFloatBuffers[count-1];
+ for (var i = 0; i < count; ++i) {
+ view[i] = HEAPF32[(((value)+(4*i))>>2)];
+ }
+ } else
+ {
+ var view = HEAPF32.subarray((value)>>2,(value+count*4)>>2);
+ }
+ GLctx.uniform1fv(GL.uniforms[location], view);
+ }
+
+ function _emscripten_glUniform1i(location, v0) {
+ GLctx.uniform1i(GL.uniforms[location], v0);
+ }
+
+
+ var __miniTempWebGLIntBuffers=[];function _emscripten_glUniform1iv(location, count, value) {
+
+
+
+ if (count <= 288) {
+ // avoid allocation when uploading few enough uniforms
+ var view = __miniTempWebGLIntBuffers[count-1];
+ for (var i = 0; i < count; ++i) {
+ view[i] = HEAP32[(((value)+(4*i))>>2)];
+ }
+ } else
+ {
+ var view = HEAP32.subarray((value)>>2,(value+count*4)>>2);
+ }
+ GLctx.uniform1iv(GL.uniforms[location], view);
+ }
+
+ function _emscripten_glUniform2f(location, v0, v1) {
+ GLctx.uniform2f(GL.uniforms[location], v0, v1);
+ }
+
+ function _emscripten_glUniform2fv(location, count, value) {
+
+
+
+ if (count <= 144) {
+ // avoid allocation when uploading few enough uniforms
+ var view = miniTempWebGLFloatBuffers[2*count-1];
+ for (var i = 0; i < 2*count; i += 2) {
+ view[i] = HEAPF32[(((value)+(4*i))>>2)];
+ view[i+1] = HEAPF32[(((value)+(4*i+4))>>2)];
+ }
+ } else
+ {
+ var view = HEAPF32.subarray((value)>>2,(value+count*8)>>2);
+ }
+ GLctx.uniform2fv(GL.uniforms[location], view);
+ }
+
+ function _emscripten_glUniform2i(location, v0, v1) {
+ GLctx.uniform2i(GL.uniforms[location], v0, v1);
+ }
+
+ function _emscripten_glUniform2iv(location, count, value) {
+
+
+
+ if (count <= 144) {
+ // avoid allocation when uploading few enough uniforms
+ var view = __miniTempWebGLIntBuffers[2*count-1];
+ for (var i = 0; i < 2*count; i += 2) {
+ view[i] = HEAP32[(((value)+(4*i))>>2)];
+ view[i+1] = HEAP32[(((value)+(4*i+4))>>2)];
+ }
+ } else
+ {
+ var view = HEAP32.subarray((value)>>2,(value+count*8)>>2);
+ }
+ GLctx.uniform2iv(GL.uniforms[location], view);
+ }
+
+ function _emscripten_glUniform3f(location, v0, v1, v2) {
+ GLctx.uniform3f(GL.uniforms[location], v0, v1, v2);
+ }
+
+ function _emscripten_glUniform3fv(location, count, value) {
+
+
+
+ if (count <= 96) {
+ // avoid allocation when uploading few enough uniforms
+ var view = miniTempWebGLFloatBuffers[3*count-1];
+ for (var i = 0; i < 3*count; i += 3) {
+ view[i] = HEAPF32[(((value)+(4*i))>>2)];
+ view[i+1] = HEAPF32[(((value)+(4*i+4))>>2)];
+ view[i+2] = HEAPF32[(((value)+(4*i+8))>>2)];
+ }
+ } else
+ {
+ var view = HEAPF32.subarray((value)>>2,(value+count*12)>>2);
+ }
+ GLctx.uniform3fv(GL.uniforms[location], view);
+ }
+
+ function _emscripten_glUniform3i(location, v0, v1, v2) {
+ GLctx.uniform3i(GL.uniforms[location], v0, v1, v2);
+ }
+
+ function _emscripten_glUniform3iv(location, count, value) {
+
+
+
+ if (count <= 96) {
+ // avoid allocation when uploading few enough uniforms
+ var view = __miniTempWebGLIntBuffers[3*count-1];
+ for (var i = 0; i < 3*count; i += 3) {
+ view[i] = HEAP32[(((value)+(4*i))>>2)];
+ view[i+1] = HEAP32[(((value)+(4*i+4))>>2)];
+ view[i+2] = HEAP32[(((value)+(4*i+8))>>2)];
+ }
+ } else
+ {
+ var view = HEAP32.subarray((value)>>2,(value+count*12)>>2);
+ }
+ GLctx.uniform3iv(GL.uniforms[location], view);
+ }
+
+ function _emscripten_glUniform4f(location, v0, v1, v2, v3) {
+ GLctx.uniform4f(GL.uniforms[location], v0, v1, v2, v3);
+ }
+
+ function _emscripten_glUniform4fv(location, count, value) {
+
+
+
+ if (count <= 72) {
+ // avoid allocation when uploading few enough uniforms
+ var view = miniTempWebGLFloatBuffers[4*count-1];
+ // hoist the heap out of the loop for size and for pthreads+growth.
+ var heap = HEAPF32;
+ value >>= 2;
+ for (var i = 0; i < 4 * count; i += 4) {
+ var dst = value + i;
+ view[i] = heap[dst];
+ view[i + 1] = heap[dst + 1];
+ view[i + 2] = heap[dst + 2];
+ view[i + 3] = heap[dst + 3];
+ }
+ } else
+ {
+ var view = HEAPF32.subarray((value)>>2,(value+count*16)>>2);
+ }
+ GLctx.uniform4fv(GL.uniforms[location], view);
+ }
+
+ function _emscripten_glUniform4i(location, v0, v1, v2, v3) {
+ GLctx.uniform4i(GL.uniforms[location], v0, v1, v2, v3);
+ }
+
+ function _emscripten_glUniform4iv(location, count, value) {
+
+
+
+ if (count <= 72) {
+ // avoid allocation when uploading few enough uniforms
+ var view = __miniTempWebGLIntBuffers[4*count-1];
+ for (var i = 0; i < 4*count; i += 4) {
+ view[i] = HEAP32[(((value)+(4*i))>>2)];
+ view[i+1] = HEAP32[(((value)+(4*i+4))>>2)];
+ view[i+2] = HEAP32[(((value)+(4*i+8))>>2)];
+ view[i+3] = HEAP32[(((value)+(4*i+12))>>2)];
+ }
+ } else
+ {
+ var view = HEAP32.subarray((value)>>2,(value+count*16)>>2);
+ }
+ GLctx.uniform4iv(GL.uniforms[location], view);
+ }
+
+ function _emscripten_glUniformMatrix2fv(location, count, transpose, value) {
+
+
+
+ if (count <= 72) {
+ // avoid allocation when uploading few enough uniforms
+ var view = miniTempWebGLFloatBuffers[4*count-1];
+ for (var i = 0; i < 4*count; i += 4) {
+ view[i] = HEAPF32[(((value)+(4*i))>>2)];
+ view[i+1] = HEAPF32[(((value)+(4*i+4))>>2)];
+ view[i+2] = HEAPF32[(((value)+(4*i+8))>>2)];
+ view[i+3] = HEAPF32[(((value)+(4*i+12))>>2)];
+ }
+ } else
+ {
+ var view = HEAPF32.subarray((value)>>2,(value+count*16)>>2);
+ }
+ GLctx.uniformMatrix2fv(GL.uniforms[location], !!transpose, view);
+ }
+
+ function _emscripten_glUniformMatrix3fv(location, count, transpose, value) {
+
+
+
+ if (count <= 32) {
+ // avoid allocation when uploading few enough uniforms
+ var view = miniTempWebGLFloatBuffers[9*count-1];
+ for (var i = 0; i < 9*count; i += 9) {
+ view[i] = HEAPF32[(((value)+(4*i))>>2)];
+ view[i+1] = HEAPF32[(((value)+(4*i+4))>>2)];
+ view[i+2] = HEAPF32[(((value)+(4*i+8))>>2)];
+ view[i+3] = HEAPF32[(((value)+(4*i+12))>>2)];
+ view[i+4] = HEAPF32[(((value)+(4*i+16))>>2)];
+ view[i+5] = HEAPF32[(((value)+(4*i+20))>>2)];
+ view[i+6] = HEAPF32[(((value)+(4*i+24))>>2)];
+ view[i+7] = HEAPF32[(((value)+(4*i+28))>>2)];
+ view[i+8] = HEAPF32[(((value)+(4*i+32))>>2)];
+ }
+ } else
+ {
+ var view = HEAPF32.subarray((value)>>2,(value+count*36)>>2);
+ }
+ GLctx.uniformMatrix3fv(GL.uniforms[location], !!transpose, view);
+ }
+
+ function _emscripten_glUniformMatrix4fv(location, count, transpose, value) {
+
+
+
+ if (count <= 18) {
+ // avoid allocation when uploading few enough uniforms
+ var view = miniTempWebGLFloatBuffers[16*count-1];
+ // hoist the heap out of the loop for size and for pthreads+growth.
+ var heap = HEAPF32;
+ value >>= 2;
+ for (var i = 0; i < 16 * count; i += 16) {
+ var dst = value + i;
+ view[i] = heap[dst];
+ view[i + 1] = heap[dst + 1];
+ view[i + 2] = heap[dst + 2];
+ view[i + 3] = heap[dst + 3];
+ view[i + 4] = heap[dst + 4];
+ view[i + 5] = heap[dst + 5];
+ view[i + 6] = heap[dst + 6];
+ view[i + 7] = heap[dst + 7];
+ view[i + 8] = heap[dst + 8];
+ view[i + 9] = heap[dst + 9];
+ view[i + 10] = heap[dst + 10];
+ view[i + 11] = heap[dst + 11];
+ view[i + 12] = heap[dst + 12];
+ view[i + 13] = heap[dst + 13];
+ view[i + 14] = heap[dst + 14];
+ view[i + 15] = heap[dst + 15];
+ }
+ } else
+ {
+ var view = HEAPF32.subarray((value)>>2,(value+count*64)>>2);
+ }
+ GLctx.uniformMatrix4fv(GL.uniforms[location], !!transpose, view);
+ }
+
+ function _emscripten_glUseProgram(program) {
+ GLctx.useProgram(GL.programs[program]);
+ }
+
+ function _emscripten_glValidateProgram(program) {
+ GLctx.validateProgram(GL.programs[program]);
+ }
+
+ function _emscripten_glVertexAttrib1f(x0, x1) { GLctx['vertexAttrib1f'](x0, x1) }
+
+ function _emscripten_glVertexAttrib1fv(index, v) {
+
+ GLctx.vertexAttrib1f(index, HEAPF32[v>>2]);
+ }
+
+ function _emscripten_glVertexAttrib2f(x0, x1, x2) { GLctx['vertexAttrib2f'](x0, x1, x2) }
+
+ function _emscripten_glVertexAttrib2fv(index, v) {
+
+ GLctx.vertexAttrib2f(index, HEAPF32[v>>2], HEAPF32[v+4>>2]);
+ }
+
+ function _emscripten_glVertexAttrib3f(x0, x1, x2, x3) { GLctx['vertexAttrib3f'](x0, x1, x2, x3) }
+
+ function _emscripten_glVertexAttrib3fv(index, v) {
+
+ GLctx.vertexAttrib3f(index, HEAPF32[v>>2], HEAPF32[v+4>>2], HEAPF32[v+8>>2]);
+ }
+
+ function _emscripten_glVertexAttrib4f(x0, x1, x2, x3, x4) { GLctx['vertexAttrib4f'](x0, x1, x2, x3, x4) }
+
+ function _emscripten_glVertexAttrib4fv(index, v) {
+
+ GLctx.vertexAttrib4f(index, HEAPF32[v>>2], HEAPF32[v+4>>2], HEAPF32[v+8>>2], HEAPF32[v+12>>2]);
+ }
+
+ function _emscripten_glVertexAttribDivisorANGLE(index, divisor) {
+ GLctx['vertexAttribDivisor'](index, divisor);
+ }
+
+ function _emscripten_glVertexAttribPointer(index, size, type, normalized, stride, ptr) {
+ GLctx.vertexAttribPointer(index, size, type, !!normalized, stride, ptr);
+ }
+
+ function _emscripten_glViewport(x0, x1, x2, x3) { GLctx['viewport'](x0, x1, x2, x3) }
+
+ function _emscripten_memcpy_big(dest, src, num) {
+ HEAPU8.copyWithin(dest, src, src + num);
+ }
+
+ function _emscripten_request_pointerlock(target, deferUntilInEventHandler) {
+ target = findEventTarget(target);
+ if (!target) return -4;
+ if (!target.requestPointerLock
+ && !target.msRequestPointerLock
+ ) {
+ return -1;
+ }
+
+ var canPerformRequests = JSEvents.canPerformEventHandlerRequests();
+
+ // Queue this function call if we're not currently in an event handler and the user saw it appropriate to do so.
+ if (!canPerformRequests) {
+ if (deferUntilInEventHandler) {
+ JSEvents.deferCall(__requestPointerLock, 2 /* priority below fullscreen */, [target]);
+ return 1;
+ } else {
+ return -2;
+ }
+ }
+
+ return __requestPointerLock(target);
+ }
+
+
+ function _emscripten_get_heap_size() {
+ return HEAPU8.length;
+ }
+
+ function abortOnCannotGrowMemory(requestedSize) {
+ abort('OOM');
+ }function _emscripten_resize_heap(requestedSize) {
+ requestedSize = requestedSize >>> 0;
+ abortOnCannotGrowMemory(requestedSize);
+ }
+
+ function _emscripten_run_script(ptr) {
+ eval(UTF8ToString(ptr));
+ }
+
+ function _emscripten_sample_gamepad_data() {
+ return (JSEvents.lastGamepadState = (navigator.getGamepads ? navigator.getGamepads() : (navigator.webkitGetGamepads ? navigator.webkitGetGamepads() : null)))
+ ? 0 : -1;
+ }
+
+
+
+ function __fillMouseEventData(eventStruct, e, target) {
+ var idx = eventStruct >> 2;
+ HEAP32[idx + 0] = e.screenX;
+ HEAP32[idx + 1] = e.screenY;
+ HEAP32[idx + 2] = e.clientX;
+ HEAP32[idx + 3] = e.clientY;
+ HEAP32[idx + 4] = e.ctrlKey;
+ HEAP32[idx + 5] = e.shiftKey;
+ HEAP32[idx + 6] = e.altKey;
+ HEAP32[idx + 7] = e.metaKey;
+ HEAP16[idx*2 + 16] = e.button;
+ HEAP16[idx*2 + 17] = e.buttons;
+
+ HEAP32[idx + 9] = e["movementX"]
+ ;
+
+ HEAP32[idx + 10] = e["movementY"]
+ ;
+
+ var rect = __getBoundingClientRect(target);
+ HEAP32[idx + 11] = e.clientX - rect.left;
+ HEAP32[idx + 12] = e.clientY - rect.top;
+
+ }function __registerMouseEventCallback(target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) {
+ if (!JSEvents.mouseEvent) JSEvents.mouseEvent = _malloc( 64 );
+ target = findEventTarget(target);
+
+ var mouseEventHandlerFunc = function(ev) {
+ var e = ev || event;
+
+ // TODO: Make this access thread safe, or this could update live while app is reading it.
+ __fillMouseEventData(JSEvents.mouseEvent, e, target);
+
+ if (wasmTable.get(callbackfunc)(eventTypeId, JSEvents.mouseEvent, userData)) e.preventDefault();
+ };
+
+ var eventHandler = {
+ target: target,
+ allowsDeferredCalls: eventTypeString != 'mousemove' && eventTypeString != 'mouseenter' && eventTypeString != 'mouseleave', // Mouse move events do not allow fullscreen/pointer lock requests to be handled in them!
+ eventTypeString: eventTypeString,
+ callbackfunc: callbackfunc,
+ handlerFunc: mouseEventHandlerFunc,
+ useCapture: useCapture
+ };
+ JSEvents.registerOrRemoveHandler(eventHandler);
+ }function _emscripten_set_click_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
+ __registerMouseEventCallback(target, userData, useCapture, callbackfunc, 4, "click", targetThread);
+ return 0;
+ }
+
+
+
+ function __fillFullscreenChangeEventData(eventStruct) {
+ var fullscreenElement = document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement;
+ var isFullscreen = !!fullscreenElement;
+ /** @suppress{checkTypes} */
+ HEAP32[((eventStruct)>>2)]=isFullscreen;
+ HEAP32[(((eventStruct)+(4))>>2)]=JSEvents.fullscreenEnabled();
+ // If transitioning to fullscreen, report info about the element that is now fullscreen.
+ // If transitioning to windowed mode, report info about the element that just was fullscreen.
+ var reportedElement = isFullscreen ? fullscreenElement : JSEvents.previousFullscreenElement;
+ var nodeName = JSEvents.getNodeNameForTarget(reportedElement);
+ var id = (reportedElement && reportedElement.id) ? reportedElement.id : '';
+ stringToUTF8(nodeName, eventStruct + 8, 128);
+ stringToUTF8(id, eventStruct + 136, 128);
+ HEAP32[(((eventStruct)+(264))>>2)]=reportedElement ? reportedElement.clientWidth : 0;
+ HEAP32[(((eventStruct)+(268))>>2)]=reportedElement ? reportedElement.clientHeight : 0;
+ HEAP32[(((eventStruct)+(272))>>2)]=screen.width;
+ HEAP32[(((eventStruct)+(276))>>2)]=screen.height;
+ if (isFullscreen) {
+ JSEvents.previousFullscreenElement = fullscreenElement;
+ }
+ }function __registerFullscreenChangeEventCallback(target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) {
+ if (!JSEvents.fullscreenChangeEvent) JSEvents.fullscreenChangeEvent = _malloc( 280 );
+
+ var fullscreenChangeEventhandlerFunc = function(ev) {
+ var e = ev || event;
+
+ var fullscreenChangeEvent = JSEvents.fullscreenChangeEvent;
+
+ __fillFullscreenChangeEventData(fullscreenChangeEvent);
+
+ if (wasmTable.get(callbackfunc)(eventTypeId, fullscreenChangeEvent, userData)) e.preventDefault();
+ };
+
+ var eventHandler = {
+ target: target,
+ eventTypeString: eventTypeString,
+ callbackfunc: callbackfunc,
+ handlerFunc: fullscreenChangeEventhandlerFunc,
+ useCapture: useCapture
+ };
+ JSEvents.registerOrRemoveHandler(eventHandler);
+ }function _emscripten_set_fullscreenchange_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
+ if (!JSEvents.fullscreenEnabled()) return -1;
+ target = findEventTarget(target);
+ if (!target) return -4;
+ __registerFullscreenChangeEventCallback(target, userData, useCapture, callbackfunc, 19, "fullscreenchange", targetThread);
+
+
+ // Unprefixed Fullscreen API shipped in Chromium 71 (https://bugs.chromium.org/p/chromium/issues/detail?id=383813)
+ // As of Safari 13.0.3 on macOS Catalina 10.15.1 still ships with prefixed webkitfullscreenchange. TODO: revisit this check once Safari ships unprefixed version.
+ __registerFullscreenChangeEventCallback(target, userData, useCapture, callbackfunc, 19, "webkitfullscreenchange", targetThread);
+
+ return 0;
+ }
+
+
+ function __registerGamepadEventCallback(target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) {
+ if (!JSEvents.gamepadEvent) JSEvents.gamepadEvent = _malloc( 1432 );
+
+ var gamepadEventHandlerFunc = function(ev) {
+ var e = ev || event;
+
+ var gamepadEvent = JSEvents.gamepadEvent;
+ __fillGamepadEventData(gamepadEvent, e["gamepad"]);
+
+ if (wasmTable.get(callbackfunc)(eventTypeId, gamepadEvent, userData)) e.preventDefault();
+ };
+
+ var eventHandler = {
+ target: findEventTarget(target),
+ allowsDeferredCalls: true,
+ eventTypeString: eventTypeString,
+ callbackfunc: callbackfunc,
+ handlerFunc: gamepadEventHandlerFunc,
+ useCapture: useCapture
+ };
+ JSEvents.registerOrRemoveHandler(eventHandler);
+ }function _emscripten_set_gamepadconnected_callback_on_thread(userData, useCapture, callbackfunc, targetThread) {
+ if (!navigator.getGamepads && !navigator.webkitGetGamepads) return -1;
+ __registerGamepadEventCallback(2, userData, useCapture, callbackfunc, 26, "gamepadconnected", targetThread);
+ return 0;
+ }
+
+ function _emscripten_set_gamepaddisconnected_callback_on_thread(userData, useCapture, callbackfunc, targetThread) {
+ if (!navigator.getGamepads && !navigator.webkitGetGamepads) return -1;
+ __registerGamepadEventCallback(2, userData, useCapture, callbackfunc, 27, "gamepaddisconnected", targetThread);
+ return 0;
+ }
+
+
+ function __registerKeyEventCallback(target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) {
+ if (!JSEvents.keyEvent) JSEvents.keyEvent = _malloc( 164 );
+
+ var keyEventHandlerFunc = function(e) {
+
+ var keyEventData = JSEvents.keyEvent;
+ var idx = keyEventData >> 2;
+
+ HEAP32[idx + 0] = e.location;
+ HEAP32[idx + 1] = e.ctrlKey;
+ HEAP32[idx + 2] = e.shiftKey;
+ HEAP32[idx + 3] = e.altKey;
+ HEAP32[idx + 4] = e.metaKey;
+ HEAP32[idx + 5] = e.repeat;
+ HEAP32[idx + 6] = e.charCode;
+ HEAP32[idx + 7] = e.keyCode;
+ HEAP32[idx + 8] = e.which;
+ stringToUTF8(e.key || '', keyEventData + 36, 32);
+ stringToUTF8(e.code || '', keyEventData + 68, 32);
+ stringToUTF8(e.char || '', keyEventData + 100, 32);
+ stringToUTF8(e.locale || '', keyEventData + 132, 32);
+
+ if (wasmTable.get(callbackfunc)(eventTypeId, keyEventData, userData)) e.preventDefault();
+ };
+
+ var eventHandler = {
+ target: findEventTarget(target),
+ allowsDeferredCalls: true,
+ eventTypeString: eventTypeString,
+ callbackfunc: callbackfunc,
+ handlerFunc: keyEventHandlerFunc,
+ useCapture: useCapture
+ };
+ JSEvents.registerOrRemoveHandler(eventHandler);
+ }function _emscripten_set_keydown_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
+ __registerKeyEventCallback(target, userData, useCapture, callbackfunc, 2, "keydown", targetThread);
+ return 0;
+ }
+
+ /** @param {number|boolean=} noSetTiming */
+ function _emscripten_set_main_loop(func, fps, simulateInfiniteLoop, arg, noSetTiming) {
+ var browserIterationFunc = function() { wasmTable.get(func)(); };
+ setMainLoop(browserIterationFunc, fps, simulateInfiniteLoop, arg, noSetTiming);
+ }
+
+
+ function __registerTouchEventCallback(target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) {
+ if (!JSEvents.touchEvent) JSEvents.touchEvent = _malloc( 1684 );
+
+ target = findEventTarget(target);
+
+ var touchEventHandlerFunc = function(e) {
+ var touches = {};
+ var et = e.touches;
+ for(var i = 0; i < et.length; ++i) {
+ var touch = et[i];
+ touches[touch.identifier] = touch;
+ }
+ et = e.changedTouches;
+ for(var i = 0; i < et.length; ++i) {
+ var touch = et[i];
+ touch.isChanged = 1;
+ touches[touch.identifier] = touch;
+ }
+ et = e.targetTouches;
+ for(var i = 0; i < et.length; ++i) {
+ touches[et[i].identifier].onTarget = 1;
+ }
+
+ var touchEvent = JSEvents.touchEvent;
+ var idx = touchEvent>>2; // Pre-shift the ptr to index to HEAP32 to save code size
+ HEAP32[idx + 1] = e.ctrlKey;
+ HEAP32[idx + 2] = e.shiftKey;
+ HEAP32[idx + 3] = e.altKey;
+ HEAP32[idx + 4] = e.metaKey;
+ idx += 5; // Advance to the start of the touch array.
+ var targetRect = __getBoundingClientRect(target);
+ var numTouches = 0;
+ for(var i in touches) {
+ var t = touches[i];
+ HEAP32[idx + 0] = t.identifier;
+ HEAP32[idx + 1] = t.screenX;
+ HEAP32[idx + 2] = t.screenY;
+ HEAP32[idx + 3] = t.clientX;
+ HEAP32[idx + 4] = t.clientY;
+ HEAP32[idx + 5] = t.pageX;
+ HEAP32[idx + 6] = t.pageY;
+ HEAP32[idx + 7] = t.isChanged;
+ HEAP32[idx + 8] = t.onTarget;
+ HEAP32[idx + 9] = t.clientX - targetRect.left;
+ HEAP32[idx + 10] = t.clientY - targetRect.top;
+
+ idx += 13;
+
+ if (++numTouches > 31) {
+ break;
+ }
+ }
+ HEAP32[((touchEvent)>>2)]=numTouches;
+
+ if (wasmTable.get(callbackfunc)(eventTypeId, touchEvent, userData)) e.preventDefault();
+ };
+
+ var eventHandler = {
+ target: target,
+ allowsDeferredCalls: eventTypeString == 'touchstart' || eventTypeString == 'touchend',
+ eventTypeString: eventTypeString,
+ callbackfunc: callbackfunc,
+ handlerFunc: touchEventHandlerFunc,
+ useCapture: useCapture
+ };
+ JSEvents.registerOrRemoveHandler(eventHandler);
+ }function _emscripten_set_touchcancel_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
+ __registerTouchEventCallback(target, userData, useCapture, callbackfunc, 25, "touchcancel", targetThread);
+ return 0;
+ }
+
+ function _emscripten_set_touchend_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
+ __registerTouchEventCallback(target, userData, useCapture, callbackfunc, 23, "touchend", targetThread);
+ return 0;
+ }
+
+ function _emscripten_set_touchmove_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
+ __registerTouchEventCallback(target, userData, useCapture, callbackfunc, 24, "touchmove", targetThread);
+ return 0;
+ }
+
+ function _emscripten_set_touchstart_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
+ __registerTouchEventCallback(target, userData, useCapture, callbackfunc, 22, "touchstart", targetThread);
+ return 0;
+ }
+
+ function _exit(status) {
+ // void _exit(int status);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/exit.html
+ exit(status);
+ }
+
+ function _fd_close(fd) {try {
+
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ FS.close(stream);
+ return 0;
+ } catch (e) {
+ if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
+ return e.errno;
+ }
+ }
+
+ function _fd_read(fd, iov, iovcnt, pnum) {try {
+
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ var num = SYSCALLS.doReadv(stream, iov, iovcnt);
+ HEAP32[((pnum)>>2)]=num
+ return 0;
+ } catch (e) {
+ if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
+ return e.errno;
+ }
+ }
+
+ function _fd_seek(fd, offset_low, offset_high, whence, newOffset) {try {
+
+
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ var HIGH_OFFSET = 0x100000000; // 2^32
+ // use an unsigned operator on low and shift high by 32-bits
+ var offset = offset_high * HIGH_OFFSET + (offset_low >>> 0);
+
+ var DOUBLE_LIMIT = 0x20000000000000; // 2^53
+ // we also check for equality since DOUBLE_LIMIT + 1 == DOUBLE_LIMIT
+ if (offset <= -DOUBLE_LIMIT || offset >= DOUBLE_LIMIT) {
+ return -61;
+ }
+
+ FS.llseek(stream, offset, whence);
+ (tempI64 = [stream.position>>>0,(tempDouble=stream.position,(+(Math_abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? ((Math_min((+(Math_floor((tempDouble)/4294967296.0))), 4294967295.0))|0)>>>0 : (~~((+(Math_ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)],HEAP32[((newOffset)>>2)]=tempI64[0],HEAP32[(((newOffset)+(4))>>2)]=tempI64[1]);
+ if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null; // reset readdir state
+ return 0;
+ } catch (e) {
+ if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
+ return e.errno;
+ }
+ }
+
+ function _fd_write(fd, iov, iovcnt, pnum) {try {
+
+ var stream = SYSCALLS.getStreamFromFD(fd);
+ var num = SYSCALLS.doWritev(stream, iov, iovcnt);
+ HEAP32[((pnum)>>2)]=num
+ return 0;
+ } catch (e) {
+ if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
+ return e.errno;
+ }
+ }
+
+ function _glActiveTexture(x0) { GLctx['activeTexture'](x0) }
+
+ function _glAttachShader(program, shader) {
+ GLctx.attachShader(GL.programs[program],
+ GL.shaders[shader]);
+ }
+
+ function _glBindAttribLocation(program, index, name) {
+ GLctx.bindAttribLocation(GL.programs[program], index, UTF8ToString(name));
+ }
+
+ function _glBindBuffer(target, buffer) {
+
+ GLctx.bindBuffer(target, GL.buffers[buffer]);
+ }
+
+ function _glBindTexture(target, texture) {
+ GLctx.bindTexture(target, GL.textures[texture]);
+ }
+
+ function _glBlendFunc(x0, x1) { GLctx['blendFunc'](x0, x1) }
+
+ function _glBufferData(target, size, data, usage) {
+
+ // N.b. here first form specifies a heap subarray, second form an integer size, so the ?: code here is polymorphic. It is advised to avoid
+ // randomly mixing both uses in calling code, to avoid any potential JS engine JIT issues.
+ GLctx.bufferData(target, data ? HEAPU8.subarray(data, data+size) : size, usage);
+ }
+
+ function _glBufferSubData(target, offset, size, data) {
+ GLctx.bufferSubData(target, offset, HEAPU8.subarray(data, data+size));
+ }
+
+ function _glClear(x0) { GLctx['clear'](x0) }
+
+ function _glClearColor(x0, x1, x2, x3) { GLctx['clearColor'](x0, x1, x2, x3) }
+
+ function _glClearDepthf(x0) { GLctx['clearDepth'](x0) }
+
+ function _glCompileShader(shader) {
+ GLctx.compileShader(GL.shaders[shader]);
+ }
+
+ function _glCompressedTexImage2D(target, level, internalFormat, width, height, border, imageSize, data) {
+ GLctx['compressedTexImage2D'](target, level, internalFormat, width, height, border, data ? HEAPU8.subarray((data),(data+imageSize)) : null);
+ }
+
+ function _glCreateProgram() {
+ var id = GL.getNewId(GL.programs);
+ var program = GLctx.createProgram();
+ program.name = id;
+ GL.programs[id] = program;
+ return id;
+ }
+
+ function _glCreateShader(shaderType) {
+ var id = GL.getNewId(GL.shaders);
+ GL.shaders[id] = GLctx.createShader(shaderType);
+ return id;
+ }
+
+ function _glCullFace(x0) { GLctx['cullFace'](x0) }
+
+ function _glDeleteBuffers(n, buffers) {
+ for (var i = 0; i < n; i++) {
+ var id = HEAP32[(((buffers)+(i*4))>>2)];
+ var buffer = GL.buffers[id];
+
+ // From spec: "glDeleteBuffers silently ignores 0's and names that do not
+ // correspond to existing buffer objects."
+ if (!buffer) continue;
+
+ GLctx.deleteBuffer(buffer);
+ buffer.name = 0;
+ GL.buffers[id] = null;
+
+ }
+ }
+
+ function _glDeleteProgram(id) {
+ if (!id) return;
+ var program = GL.programs[id];
+ if (!program) { // glDeleteProgram actually signals an error when deleting a nonexisting object, unlike some other GL delete functions.
+ GL.recordError(0x501 /* GL_INVALID_VALUE */);
+ return;
+ }
+ GLctx.deleteProgram(program);
+ program.name = 0;
+ GL.programs[id] = null;
+ GL.programInfos[id] = null;
+ }
+
+ function _glDeleteShader(id) {
+ if (!id) return;
+ var shader = GL.shaders[id];
+ if (!shader) { // glDeleteShader actually signals an error when deleting a nonexisting object, unlike some other GL delete functions.
+ GL.recordError(0x501 /* GL_INVALID_VALUE */);
+ return;
+ }
+ GLctx.deleteShader(shader);
+ GL.shaders[id] = null;
+ }
+
+ function _glDeleteTextures(n, textures) {
+ for (var i = 0; i < n; i++) {
+ var id = HEAP32[(((textures)+(i*4))>>2)];
+ var texture = GL.textures[id];
+ if (!texture) continue; // GL spec: "glDeleteTextures silently ignores 0s and names that do not correspond to existing textures".
+ GLctx.deleteTexture(texture);
+ texture.name = 0;
+ GL.textures[id] = null;
+ }
+ }
+
+ function _glDepthFunc(x0) { GLctx['depthFunc'](x0) }
+
+ function _glDetachShader(program, shader) {
+ GLctx.detachShader(GL.programs[program],
+ GL.shaders[shader]);
+ }
+
+ function _glDisable(x0) { GLctx['disable'](x0) }
+
+ function _glDisableVertexAttribArray(index) {
+ GLctx.disableVertexAttribArray(index);
+ }
+
+ function _glDrawArrays(mode, first, count) {
+
+ GLctx.drawArrays(mode, first, count);
+
+ }
+
+ function _glDrawElements(mode, count, type, indices) {
+
+ GLctx.drawElements(mode, count, type, indices);
+
+ }
+
+ function _glEnable(x0) { GLctx['enable'](x0) }
+
+ function _glEnableVertexAttribArray(index) {
+ GLctx.enableVertexAttribArray(index);
+ }
+
+ function _glFrontFace(x0) { GLctx['frontFace'](x0) }
+
+ function _glGenBuffers(n, buffers) {
+ __glGenObject(n, buffers, 'createBuffer', GL.buffers
+ );
+ }
+
+ function _glGenTextures(n, textures) {
+ __glGenObject(n, textures, 'createTexture', GL.textures
+ );
+ }
+
+ function _glGetAttribLocation(program, name) {
+ return GLctx.getAttribLocation(GL.programs[program], UTF8ToString(name));
+ }
+
+ function _glGetFloatv(name_, p) {
+ emscriptenWebGLGet(name_, p, 2);
+ }
+
+ function _glGetProgramInfoLog(program, maxLength, length, infoLog) {
+ var log = GLctx.getProgramInfoLog(GL.programs[program]);
+ if (log === null) log = '(unknown error)';
+ var numBytesWrittenExclNull = (maxLength > 0 && infoLog) ? stringToUTF8(log, infoLog, maxLength) : 0;
+ if (length) HEAP32[((length)>>2)]=numBytesWrittenExclNull;
+ }
+
+ function _glGetProgramiv(program, pname, p) {
+ if (!p) {
+ // GLES2 specification does not specify how to behave if p is a null pointer. Since calling this function does not make sense
+ // if p == null, issue a GL error to notify user about it.
+ GL.recordError(0x501 /* GL_INVALID_VALUE */);
+ return;
+ }
+
+ if (program >= GL.counter) {
+ GL.recordError(0x501 /* GL_INVALID_VALUE */);
+ return;
+ }
+
+ var ptable = GL.programInfos[program];
+ if (!ptable) {
+ GL.recordError(0x502 /* GL_INVALID_OPERATION */);
+ return;
+ }
+
+ if (pname == 0x8B84) { // GL_INFO_LOG_LENGTH
+ var log = GLctx.getProgramInfoLog(GL.programs[program]);
+ if (log === null) log = '(unknown error)';
+ HEAP32[((p)>>2)]=log.length + 1;
+ } else if (pname == 0x8B87 /* GL_ACTIVE_UNIFORM_MAX_LENGTH */) {
+ HEAP32[((p)>>2)]=ptable.maxUniformLength;
+ } else if (pname == 0x8B8A /* GL_ACTIVE_ATTRIBUTE_MAX_LENGTH */) {
+ if (ptable.maxAttributeLength == -1) {
+ program = GL.programs[program];
+ var numAttribs = GLctx.getProgramParameter(program, 0x8B89/*GL_ACTIVE_ATTRIBUTES*/);
+ ptable.maxAttributeLength = 0; // Spec says if there are no active attribs, 0 must be returned.
+ for (var i = 0; i < numAttribs; ++i) {
+ var activeAttrib = GLctx.getActiveAttrib(program, i);
+ ptable.maxAttributeLength = Math.max(ptable.maxAttributeLength, activeAttrib.name.length+1);
+ }
+ }
+ HEAP32[((p)>>2)]=ptable.maxAttributeLength;
+ } else if (pname == 0x8A35 /* GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH */) {
+ if (ptable.maxUniformBlockNameLength == -1) {
+ program = GL.programs[program];
+ var numBlocks = GLctx.getProgramParameter(program, 0x8A36/*GL_ACTIVE_UNIFORM_BLOCKS*/);
+ ptable.maxUniformBlockNameLength = 0;
+ for (var i = 0; i < numBlocks; ++i) {
+ var activeBlockName = GLctx.getActiveUniformBlockName(program, i);
+ ptable.maxUniformBlockNameLength = Math.max(ptable.maxUniformBlockNameLength, activeBlockName.length+1);
+ }
+ }
+ HEAP32[((p)>>2)]=ptable.maxUniformBlockNameLength;
+ } else {
+ HEAP32[((p)>>2)]=GLctx.getProgramParameter(GL.programs[program], pname);
+ }
+ }
+
+ function _glGetShaderInfoLog(shader, maxLength, length, infoLog) {
+ var log = GLctx.getShaderInfoLog(GL.shaders[shader]);
+ if (log === null) log = '(unknown error)';
+ var numBytesWrittenExclNull = (maxLength > 0 && infoLog) ? stringToUTF8(log, infoLog, maxLength) : 0;
+ if (length) HEAP32[((length)>>2)]=numBytesWrittenExclNull;
+ }
+
+ function _glGetShaderiv(shader, pname, p) {
+ if (!p) {
+ // GLES2 specification does not specify how to behave if p is a null pointer. Since calling this function does not make sense
+ // if p == null, issue a GL error to notify user about it.
+ GL.recordError(0x501 /* GL_INVALID_VALUE */);
+ return;
+ }
+ if (pname == 0x8B84) { // GL_INFO_LOG_LENGTH
+ var log = GLctx.getShaderInfoLog(GL.shaders[shader]);
+ if (log === null) log = '(unknown error)';
+ // The GLES2 specification says that if the shader has an empty info log,
+ // a value of 0 is returned. Otherwise the log has a null char appended.
+ // (An empty string is falsey, so we can just check that instead of
+ // looking at log.length.)
+ var logLength = log ? log.length + 1 : 0;
+ HEAP32[((p)>>2)]=logLength;
+ } else if (pname == 0x8B88) { // GL_SHADER_SOURCE_LENGTH
+ var source = GLctx.getShaderSource(GL.shaders[shader]);
+ // source may be a null, or the empty string, both of which are falsey
+ // values that we report a 0 length for.
+ var sourceLength = source ? source.length + 1 : 0;
+ HEAP32[((p)>>2)]=sourceLength;
+ } else {
+ HEAP32[((p)>>2)]=GLctx.getShaderParameter(GL.shaders[shader], pname);
+ }
+ }
+
+ function _glGetString(name_) {
+ if (GL.stringCache[name_]) return GL.stringCache[name_];
+ var ret;
+ switch(name_) {
+ case 0x1F03 /* GL_EXTENSIONS */:
+ var exts = GLctx.getSupportedExtensions() || []; // .getSupportedExtensions() can return null if context is lost, so coerce to empty array.
+ exts = exts.concat(exts.map(function(e) { return "GL_" + e; }));
+ ret = stringToNewUTF8(exts.join(' '));
+ break;
+ case 0x1F00 /* GL_VENDOR */:
+ case 0x1F01 /* GL_RENDERER */:
+ case 0x9245 /* UNMASKED_VENDOR_WEBGL */:
+ case 0x9246 /* UNMASKED_RENDERER_WEBGL */:
+ var s = GLctx.getParameter(name_);
+ if (!s) {
+ GL.recordError(0x500/*GL_INVALID_ENUM*/);
+ }
+ ret = stringToNewUTF8(s);
+ break;
+
+ case 0x1F02 /* GL_VERSION */:
+ var glVersion = GLctx.getParameter(0x1F02 /*GL_VERSION*/);
+ // return GLES version string corresponding to the version of the WebGL context
+ {
+ glVersion = 'OpenGL ES 2.0 (' + glVersion + ')';
+ }
+ ret = stringToNewUTF8(glVersion);
+ break;
+ case 0x8B8C /* GL_SHADING_LANGUAGE_VERSION */:
+ var glslVersion = GLctx.getParameter(0x8B8C /*GL_SHADING_LANGUAGE_VERSION*/);
+ // extract the version number 'N.M' from the string 'WebGL GLSL ES N.M ...'
+ var ver_re = /^WebGL GLSL ES ([0-9]\.[0-9][0-9]?)(?:$| .*)/;
+ var ver_num = glslVersion.match(ver_re);
+ if (ver_num !== null) {
+ if (ver_num[1].length == 3) ver_num[1] = ver_num[1] + '0'; // ensure minor version has 2 digits
+ glslVersion = 'OpenGL ES GLSL ES ' + ver_num[1] + ' (' + glslVersion + ')';
+ }
+ ret = stringToNewUTF8(glslVersion);
+ break;
+ default:
+ GL.recordError(0x500/*GL_INVALID_ENUM*/);
+ return 0;
+ }
+ GL.stringCache[name_] = ret;
+ return ret;
+ }
+
+ function _glGetUniformLocation(program, name) {
+ name = UTF8ToString(name);
+
+ var arrayIndex = 0;
+ // If user passed an array accessor "[index]", parse the array index off the accessor.
+ if (name[name.length - 1] == ']') {
+ var leftBrace = name.lastIndexOf('[');
+ arrayIndex = name[leftBrace+1] != ']' ? jstoi_q(name.slice(leftBrace + 1)) : 0; // "index]", parseInt will ignore the ']' at the end; but treat "foo[]" as "foo[0]"
+ name = name.slice(0, leftBrace);
+ }
+
+ var uniformInfo = GL.programInfos[program] && GL.programInfos[program].uniforms[name]; // returns pair [ dimension_of_uniform_array, uniform_location ]
+ if (uniformInfo && arrayIndex >= 0 && arrayIndex < uniformInfo[0]) { // Check if user asked for an out-of-bounds element, i.e. for 'vec4 colors[3];' user could ask for 'colors[10]' which should return -1.
+ return uniformInfo[1] + arrayIndex;
+ } else {
+ return -1;
+ }
+ }
+
+ function _glLinkProgram(program) {
+ GLctx.linkProgram(GL.programs[program]);
+ GL.populateUniformTable(program);
+ }
+
+ function _glPixelStorei(pname, param) {
+ if (pname == 0xCF5 /* GL_UNPACK_ALIGNMENT */) {
+ GL.unpackAlignment = param;
+ }
+ GLctx.pixelStorei(pname, param);
+ }
+
+ function _glReadPixels(x, y, width, height, format, type, pixels) {
+ var pixelData = emscriptenWebGLGetTexPixelData(type, format, width, height, pixels, format);
+ if (!pixelData) {
+ GL.recordError(0x500/*GL_INVALID_ENUM*/);
+ return;
+ }
+ GLctx.readPixels(x, y, width, height, format, type, pixelData);
+ }
+
+ function _glShaderSource(shader, count, string, length) {
+ var source = GL.getSource(shader, count, string, length);
+
+
+ GLctx.shaderSource(GL.shaders[shader], source);
+ }
+
+ function _glTexImage2D(target, level, internalFormat, width, height, border, format, type, pixels) {
+ GLctx.texImage2D(target, level, internalFormat, width, height, border, format, type, pixels ? emscriptenWebGLGetTexPixelData(type, format, width, height, pixels, internalFormat) : null);
+ }
+
+ function _glTexParameteri(x0, x1, x2) { GLctx['texParameteri'](x0, x1, x2) }
+
+ function _glUniform1i(location, v0) {
+ GLctx.uniform1i(GL.uniforms[location], v0);
+ }
+
+ function _glUniform4f(location, v0, v1, v2, v3) {
+ GLctx.uniform4f(GL.uniforms[location], v0, v1, v2, v3);
+ }
+
+ function _glUniformMatrix4fv(location, count, transpose, value) {
+
+
+
+ if (count <= 18) {
+ // avoid allocation when uploading few enough uniforms
+ var view = miniTempWebGLFloatBuffers[16*count-1];
+ // hoist the heap out of the loop for size and for pthreads+growth.
+ var heap = HEAPF32;
+ value >>= 2;
+ for (var i = 0; i < 16 * count; i += 16) {
+ var dst = value + i;
+ view[i] = heap[dst];
+ view[i + 1] = heap[dst + 1];
+ view[i + 2] = heap[dst + 2];
+ view[i + 3] = heap[dst + 3];
+ view[i + 4] = heap[dst + 4];
+ view[i + 5] = heap[dst + 5];
+ view[i + 6] = heap[dst + 6];
+ view[i + 7] = heap[dst + 7];
+ view[i + 8] = heap[dst + 8];
+ view[i + 9] = heap[dst + 9];
+ view[i + 10] = heap[dst + 10];
+ view[i + 11] = heap[dst + 11];
+ view[i + 12] = heap[dst + 12];
+ view[i + 13] = heap[dst + 13];
+ view[i + 14] = heap[dst + 14];
+ view[i + 15] = heap[dst + 15];
+ }
+ } else
+ {
+ var view = HEAPF32.subarray((value)>>2,(value+count*64)>>2);
+ }
+ GLctx.uniformMatrix4fv(GL.uniforms[location], !!transpose, view);
+ }
+
+ function _glUseProgram(program) {
+ GLctx.useProgram(GL.programs[program]);
+ }
+
+ function _glVertexAttrib2f(x0, x1, x2) { GLctx['vertexAttrib2f'](x0, x1, x2) }
+
+ function _glVertexAttrib3f(x0, x1, x2, x3) { GLctx['vertexAttrib3f'](x0, x1, x2, x3) }
+
+ function _glVertexAttrib4f(x0, x1, x2, x3, x4) { GLctx['vertexAttrib4f'](x0, x1, x2, x3, x4) }
+
+ function _glVertexAttribPointer(index, size, type, normalized, stride, ptr) {
+ GLctx.vertexAttribPointer(index, size, type, !!normalized, stride, ptr);
+ }
+
+ function _glViewport(x0, x1, x2, x3) { GLctx['viewport'](x0, x1, x2, x3) }
+
+
+
+ /** @constructor */
+ function GLFW_Window(id, width, height, title, monitor, share) {
+ this.id = id;
+ this.x = 0;
+ this.y = 0;
+ this.fullscreen = false; // Used to determine if app in fullscreen mode
+ this.storedX = 0; // Used to store X before fullscreen
+ this.storedY = 0; // Used to store Y before fullscreen
+ this.width = width;
+ this.height = height;
+ this.storedWidth = width; // Used to store width before fullscreen
+ this.storedHeight = height; // Used to store height before fullscreen
+ this.title = title;
+ this.monitor = monitor;
+ this.share = share;
+ this.attributes = GLFW.hints;
+ this.inputModes = {
+ 0x00033001:0x00034001, // GLFW_CURSOR (GLFW_CURSOR_NORMAL)
+ 0x00033002:0, // GLFW_STICKY_KEYS
+ 0x00033003:0, // GLFW_STICKY_MOUSE_BUTTONS
+ };
+ this.buttons = 0;
+ this.keys = new Array();
+ this.domKeys = new Array();
+ this.shouldClose = 0;
+ this.title = null;
+ this.windowPosFunc = null; // GLFWwindowposfun
+ this.windowSizeFunc = null; // GLFWwindowsizefun
+ this.windowCloseFunc = null; // GLFWwindowclosefun
+ this.windowRefreshFunc = null; // GLFWwindowrefreshfun
+ this.windowFocusFunc = null; // GLFWwindowfocusfun
+ this.windowIconifyFunc = null; // GLFWwindowiconifyfun
+ this.framebufferSizeFunc = null; // GLFWframebuffersizefun
+ this.mouseButtonFunc = null; // GLFWmousebuttonfun
+ this.cursorPosFunc = null; // GLFWcursorposfun
+ this.cursorEnterFunc = null; // GLFWcursorenterfun
+ this.scrollFunc = null; // GLFWscrollfun
+ this.dropFunc = null; // GLFWdropfun
+ this.keyFunc = null; // GLFWkeyfun
+ this.charFunc = null; // GLFWcharfun
+ this.userptr = null;
+ }var GLFW={WindowFromId:function(id) {
+ if (id <= 0 || !GLFW.windows) return null;
+ return GLFW.windows[id - 1];
+ },joystickFunc:null,errorFunc:null,monitorFunc:null,active:null,windows:null,monitors:null,monitorString:null,versionString:null,initialTime:null,extensions:null,hints:null,defaultHints:{131073:0,131074:0,131075:1,131076:1,131077:1,135169:8,135170:8,135171:8,135172:8,135173:24,135174:8,135175:0,135176:0,135177:0,135178:0,135179:0,135180:0,135181:0,135182:0,135183:0,139265:196609,139266:1,139267:0,139268:0,139269:0,139270:0,139271:0,139272:0},DOMToGLFWKeyCode:function(keycode) {
+ switch (keycode) {
+ // these keycodes are only defined for GLFW3, assume they are the same for GLFW2
+ case 0x20:return 32; // DOM_VK_SPACE -> GLFW_KEY_SPACE
+ case 0xDE:return 39; // DOM_VK_QUOTE -> GLFW_KEY_APOSTROPHE
+ case 0xBC:return 44; // DOM_VK_COMMA -> GLFW_KEY_COMMA
+ case 0xAD:return 45; // DOM_VK_HYPHEN_MINUS -> GLFW_KEY_MINUS
+ case 0xBD:return 45; // DOM_VK_MINUS -> GLFW_KEY_MINUS
+ case 0xBE:return 46; // DOM_VK_PERIOD -> GLFW_KEY_PERIOD
+ case 0xBF:return 47; // DOM_VK_SLASH -> GLFW_KEY_SLASH
+ case 0x30:return 48; // DOM_VK_0 -> GLFW_KEY_0
+ case 0x31:return 49; // DOM_VK_1 -> GLFW_KEY_1
+ case 0x32:return 50; // DOM_VK_2 -> GLFW_KEY_2
+ case 0x33:return 51; // DOM_VK_3 -> GLFW_KEY_3
+ case 0x34:return 52; // DOM_VK_4 -> GLFW_KEY_4
+ case 0x35:return 53; // DOM_VK_5 -> GLFW_KEY_5
+ case 0x36:return 54; // DOM_VK_6 -> GLFW_KEY_6
+ case 0x37:return 55; // DOM_VK_7 -> GLFW_KEY_7
+ case 0x38:return 56; // DOM_VK_8 -> GLFW_KEY_8
+ case 0x39:return 57; // DOM_VK_9 -> GLFW_KEY_9
+ case 0x3B:return 59; // DOM_VK_SEMICOLON -> GLFW_KEY_SEMICOLON
+ case 0x3D:return 61; // DOM_VK_EQUALS -> GLFW_KEY_EQUAL
+ case 0xBB:return 61; // DOM_VK_EQUALS -> GLFW_KEY_EQUAL
+ case 0x41:return 65; // DOM_VK_A -> GLFW_KEY_A
+ case 0x42:return 66; // DOM_VK_B -> GLFW_KEY_B
+ case 0x43:return 67; // DOM_VK_C -> GLFW_KEY_C
+ case 0x44:return 68; // DOM_VK_D -> GLFW_KEY_D
+ case 0x45:return 69; // DOM_VK_E -> GLFW_KEY_E
+ case 0x46:return 70; // DOM_VK_F -> GLFW_KEY_F
+ case 0x47:return 71; // DOM_VK_G -> GLFW_KEY_G
+ case 0x48:return 72; // DOM_VK_H -> GLFW_KEY_H
+ case 0x49:return 73; // DOM_VK_I -> GLFW_KEY_I
+ case 0x4A:return 74; // DOM_VK_J -> GLFW_KEY_J
+ case 0x4B:return 75; // DOM_VK_K -> GLFW_KEY_K
+ case 0x4C:return 76; // DOM_VK_L -> GLFW_KEY_L
+ case 0x4D:return 77; // DOM_VK_M -> GLFW_KEY_M
+ case 0x4E:return 78; // DOM_VK_N -> GLFW_KEY_N
+ case 0x4F:return 79; // DOM_VK_O -> GLFW_KEY_O
+ case 0x50:return 80; // DOM_VK_P -> GLFW_KEY_P
+ case 0x51:return 81; // DOM_VK_Q -> GLFW_KEY_Q
+ case 0x52:return 82; // DOM_VK_R -> GLFW_KEY_R
+ case 0x53:return 83; // DOM_VK_S -> GLFW_KEY_S
+ case 0x54:return 84; // DOM_VK_T -> GLFW_KEY_T
+ case 0x55:return 85; // DOM_VK_U -> GLFW_KEY_U
+ case 0x56:return 86; // DOM_VK_V -> GLFW_KEY_V
+ case 0x57:return 87; // DOM_VK_W -> GLFW_KEY_W
+ case 0x58:return 88; // DOM_VK_X -> GLFW_KEY_X
+ case 0x59:return 89; // DOM_VK_Y -> GLFW_KEY_Y
+ case 0x5a:return 90; // DOM_VK_Z -> GLFW_KEY_Z
+ case 0xDB:return 91; // DOM_VK_OPEN_BRACKET -> GLFW_KEY_LEFT_BRACKET
+ case 0xDC:return 92; // DOM_VK_BACKSLASH -> GLFW_KEY_BACKSLASH
+ case 0xDD:return 93; // DOM_VK_CLOSE_BRACKET -> GLFW_KEY_RIGHT_BRACKET
+ case 0xC0:return 94; // DOM_VK_BACK_QUOTE -> GLFW_KEY_GRAVE_ACCENT
+
+
+ case 0x1B:return 256; // DOM_VK_ESCAPE -> GLFW_KEY_ESCAPE
+ case 0x0D:return 257; // DOM_VK_RETURN -> GLFW_KEY_ENTER
+ case 0x09:return 258; // DOM_VK_TAB -> GLFW_KEY_TAB
+ case 0x08:return 259; // DOM_VK_BACK -> GLFW_KEY_BACKSPACE
+ case 0x2D:return 260; // DOM_VK_INSERT -> GLFW_KEY_INSERT
+ case 0x2E:return 261; // DOM_VK_DELETE -> GLFW_KEY_DELETE
+ case 0x27:return 262; // DOM_VK_RIGHT -> GLFW_KEY_RIGHT
+ case 0x25:return 263; // DOM_VK_LEFT -> GLFW_KEY_LEFT
+ case 0x28:return 264; // DOM_VK_DOWN -> GLFW_KEY_DOWN
+ case 0x26:return 265; // DOM_VK_UP -> GLFW_KEY_UP
+ case 0x21:return 266; // DOM_VK_PAGE_UP -> GLFW_KEY_PAGE_UP
+ case 0x22:return 267; // DOM_VK_PAGE_DOWN -> GLFW_KEY_PAGE_DOWN
+ case 0x24:return 268; // DOM_VK_HOME -> GLFW_KEY_HOME
+ case 0x23:return 269; // DOM_VK_END -> GLFW_KEY_END
+ case 0x14:return 280; // DOM_VK_CAPS_LOCK -> GLFW_KEY_CAPS_LOCK
+ case 0x91:return 281; // DOM_VK_SCROLL_LOCK -> GLFW_KEY_SCROLL_LOCK
+ case 0x90:return 282; // DOM_VK_NUM_LOCK -> GLFW_KEY_NUM_LOCK
+ case 0x2C:return 283; // DOM_VK_SNAPSHOT -> GLFW_KEY_PRINT_SCREEN
+ case 0x13:return 284; // DOM_VK_PAUSE -> GLFW_KEY_PAUSE
+ case 0x70:return 290; // DOM_VK_F1 -> GLFW_KEY_F1
+ case 0x71:return 291; // DOM_VK_F2 -> GLFW_KEY_F2
+ case 0x72:return 292; // DOM_VK_F3 -> GLFW_KEY_F3
+ case 0x73:return 293; // DOM_VK_F4 -> GLFW_KEY_F4
+ case 0x74:return 294; // DOM_VK_F5 -> GLFW_KEY_F5
+ case 0x75:return 295; // DOM_VK_F6 -> GLFW_KEY_F6
+ case 0x76:return 296; // DOM_VK_F7 -> GLFW_KEY_F7
+ case 0x77:return 297; // DOM_VK_F8 -> GLFW_KEY_F8
+ case 0x78:return 298; // DOM_VK_F9 -> GLFW_KEY_F9
+ case 0x79:return 299; // DOM_VK_F10 -> GLFW_KEY_F10
+ case 0x7A:return 300; // DOM_VK_F11 -> GLFW_KEY_F11
+ case 0x7B:return 301; // DOM_VK_F12 -> GLFW_KEY_F12
+ case 0x7C:return 302; // DOM_VK_F13 -> GLFW_KEY_F13
+ case 0x7D:return 303; // DOM_VK_F14 -> GLFW_KEY_F14
+ case 0x7E:return 304; // DOM_VK_F15 -> GLFW_KEY_F15
+ case 0x7F:return 305; // DOM_VK_F16 -> GLFW_KEY_F16
+ case 0x80:return 306; // DOM_VK_F17 -> GLFW_KEY_F17
+ case 0x81:return 307; // DOM_VK_F18 -> GLFW_KEY_F18
+ case 0x82:return 308; // DOM_VK_F19 -> GLFW_KEY_F19
+ case 0x83:return 309; // DOM_VK_F20 -> GLFW_KEY_F20
+ case 0x84:return 310; // DOM_VK_F21 -> GLFW_KEY_F21
+ case 0x85:return 311; // DOM_VK_F22 -> GLFW_KEY_F22
+ case 0x86:return 312; // DOM_VK_F23 -> GLFW_KEY_F23
+ case 0x87:return 313; // DOM_VK_F24 -> GLFW_KEY_F24
+ case 0x88:return 314; // 0x88 (not used?) -> GLFW_KEY_F25
+ case 0x60:return 320; // DOM_VK_NUMPAD0 -> GLFW_KEY_KP_0
+ case 0x61:return 321; // DOM_VK_NUMPAD1 -> GLFW_KEY_KP_1
+ case 0x62:return 322; // DOM_VK_NUMPAD2 -> GLFW_KEY_KP_2
+ case 0x63:return 323; // DOM_VK_NUMPAD3 -> GLFW_KEY_KP_3
+ case 0x64:return 324; // DOM_VK_NUMPAD4 -> GLFW_KEY_KP_4
+ case 0x65:return 325; // DOM_VK_NUMPAD5 -> GLFW_KEY_KP_5
+ case 0x66:return 326; // DOM_VK_NUMPAD6 -> GLFW_KEY_KP_6
+ case 0x67:return 327; // DOM_VK_NUMPAD7 -> GLFW_KEY_KP_7
+ case 0x68:return 328; // DOM_VK_NUMPAD8 -> GLFW_KEY_KP_8
+ case 0x69:return 329; // DOM_VK_NUMPAD9 -> GLFW_KEY_KP_9
+ case 0x6E:return 330; // DOM_VK_DECIMAL -> GLFW_KEY_KP_DECIMAL
+ case 0x6F:return 331; // DOM_VK_DIVIDE -> GLFW_KEY_KP_DIVIDE
+ case 0x6A:return 332; // DOM_VK_MULTIPLY -> GLFW_KEY_KP_MULTIPLY
+ case 0x6D:return 333; // DOM_VK_SUBTRACT -> GLFW_KEY_KP_SUBTRACT
+ case 0x6B:return 334; // DOM_VK_ADD -> GLFW_KEY_KP_ADD
+ // case 0x0D:return 335; // DOM_VK_RETURN -> GLFW_KEY_KP_ENTER (DOM_KEY_LOCATION_RIGHT)
+ // case 0x61:return 336; // DOM_VK_EQUALS -> GLFW_KEY_KP_EQUAL (DOM_KEY_LOCATION_RIGHT)
+ case 0x10:return 340; // DOM_VK_SHIFT -> GLFW_KEY_LEFT_SHIFT
+ case 0x11:return 341; // DOM_VK_CONTROL -> GLFW_KEY_LEFT_CONTROL
+ case 0x12:return 342; // DOM_VK_ALT -> GLFW_KEY_LEFT_ALT
+ case 0x5B:return 343; // DOM_VK_WIN -> GLFW_KEY_LEFT_SUPER
+ // case 0x10:return 344; // DOM_VK_SHIFT -> GLFW_KEY_RIGHT_SHIFT (DOM_KEY_LOCATION_RIGHT)
+ // case 0x11:return 345; // DOM_VK_CONTROL -> GLFW_KEY_RIGHT_CONTROL (DOM_KEY_LOCATION_RIGHT)
+ // case 0x12:return 346; // DOM_VK_ALT -> GLFW_KEY_RIGHT_ALT (DOM_KEY_LOCATION_RIGHT)
+ // case 0x5B:return 347; // DOM_VK_WIN -> GLFW_KEY_RIGHT_SUPER (DOM_KEY_LOCATION_RIGHT)
+ case 0x5D:return 348; // DOM_VK_CONTEXT_MENU -> GLFW_KEY_MENU
+ // XXX: GLFW_KEY_WORLD_1, GLFW_KEY_WORLD_2 what are these?
+ default:return -1; // GLFW_KEY_UNKNOWN
+ };
+ },getModBits:function(win) {
+ var mod = 0;
+ if (win.keys[340]) mod |= 0x0001; // GLFW_MOD_SHIFT
+ if (win.keys[341]) mod |= 0x0002; // GLFW_MOD_CONTROL
+ if (win.keys[342]) mod |= 0x0004; // GLFW_MOD_ALT
+ if (win.keys[343]) mod |= 0x0008; // GLFW_MOD_SUPER
+ return mod;
+ },onKeyPress:function(event) {
+ if (!GLFW.active || !GLFW.active.charFunc) return;
+ if (event.ctrlKey || event.metaKey) return;
+
+ // correct unicode charCode is only available with onKeyPress event
+ var charCode = event.charCode;
+ if (charCode == 0 || (charCode >= 0x00 && charCode <= 0x1F)) return;
+
+
+ wasmTable.get(GLFW.active.charFunc)(GLFW.active.id, charCode);
+ },onKeyChanged:function(keyCode, status) {
+ if (!GLFW.active) return;
+
+ var key = GLFW.DOMToGLFWKeyCode(keyCode);
+ if (key == -1) return;
+
+ var repeat = status && GLFW.active.keys[key];
+ GLFW.active.keys[key] = status;
+ GLFW.active.domKeys[keyCode] = status;
+ if (!GLFW.active.keyFunc) return;
+
+
+ if (repeat) status = 2; // GLFW_REPEAT
+ wasmTable.get(GLFW.active.keyFunc)(GLFW.active.id, key, keyCode, status, GLFW.getModBits(GLFW.active));
+ },onGamepadConnected:function(event) {
+ GLFW.refreshJoysticks();
+ },onGamepadDisconnected:function(event) {
+ GLFW.refreshJoysticks();
+ },onKeydown:function(event) {
+ GLFW.onKeyChanged(event.keyCode, 1); // GLFW_PRESS or GLFW_REPEAT
+
+ // This logic comes directly from the sdl implementation. We cannot
+ // call preventDefault on all keydown events otherwise onKeyPress will
+ // not get called
+ if (event.keyCode === 8 /* backspace */ || event.keyCode === 9 /* tab */) {
+ event.preventDefault();
+ }
+ },onKeyup:function(event) {
+ GLFW.onKeyChanged(event.keyCode, 0); // GLFW_RELEASE
+ },onBlur:function(event) {
+ if (!GLFW.active) return;
+
+ for (var i = 0; i < GLFW.active.domKeys.length; ++i) {
+ if (GLFW.active.domKeys[i]) {
+ GLFW.onKeyChanged(i, 0); // GLFW_RELEASE
+ }
+ }
+ },onMousemove:function(event) {
+ if (!GLFW.active) return;
+
+ Browser.calculateMouseEvent(event);
+
+ if (event.target != Module["canvas"] || !GLFW.active.cursorPosFunc) return;
+
+
+ wasmTable.get(GLFW.active.cursorPosFunc)(GLFW.active.id, Browser.mouseX, Browser.mouseY);
+ },DOMToGLFWMouseButton:function(event) {
+ // DOM and glfw have different button codes.
+ // See http://www.w3schools.com/jsref/event_button.asp.
+ var eventButton = event['button'];
+ if (eventButton > 0) {
+ if (eventButton == 1) {
+ eventButton = 2;
+ } else {
+ eventButton = 1;
+ }
+ }
+ return eventButton;
+ },onMouseenter:function(event) {
+ if (!GLFW.active) return;
+
+ if (event.target != Module["canvas"] || !GLFW.active.cursorEnterFunc) return;
+
+ wasmTable.get(GLFW.active.cursorEnterFunc)(GLFW.active.id, 1);
+ },onMouseleave:function(event) {
+ if (!GLFW.active) return;
+
+ if (event.target != Module["canvas"] || !GLFW.active.cursorEnterFunc) return;
+
+ wasmTable.get(GLFW.active.cursorEnterFunc)(GLFW.active.id, 0);
+ },onMouseButtonChanged:function(event, status) {
+ if (!GLFW.active) return;
+
+ Browser.calculateMouseEvent(event);
+
+ if (event.target != Module["canvas"]) return;
+
+ var eventButton = GLFW.DOMToGLFWMouseButton(event);
+
+ if (status == 1) { // GLFW_PRESS
+ GLFW.active.buttons |= (1 << eventButton);
+ try {
+ event.target.setCapture();
+ } catch (e) {}
+ } else { // GLFW_RELEASE
+ GLFW.active.buttons &= ~(1 << eventButton);
+ }
+
+ if (!GLFW.active.mouseButtonFunc) return;
+
+
+ wasmTable.get(GLFW.active.mouseButtonFunc)(GLFW.active.id, eventButton, status, GLFW.getModBits(GLFW.active));
+ },onMouseButtonDown:function(event) {
+ if (!GLFW.active) return;
+ GLFW.onMouseButtonChanged(event, 1); // GLFW_PRESS
+ },onMouseButtonUp:function(event) {
+ if (!GLFW.active) return;
+ GLFW.onMouseButtonChanged(event, 0); // GLFW_RELEASE
+ },onMouseWheel:function(event) {
+ // Note the minus sign that flips browser wheel direction (positive direction scrolls page down) to native wheel direction (positive direction is mouse wheel up)
+ var delta = -Browser.getMouseWheelDelta(event);
+ delta = (delta == 0) ? 0 : (delta > 0 ? Math.max(delta, 1) : Math.min(delta, -1)); // Quantize to integer so that minimum scroll is at least +/- 1.
+ GLFW.wheelPos += delta;
+
+ if (!GLFW.active || !GLFW.active.scrollFunc || event.target != Module['canvas']) return;
+
+
+ var sx = 0;
+ var sy = 0;
+ if (event.type == 'mousewheel') {
+ sx = event.wheelDeltaX;
+ sy = event.wheelDeltaY;
+ } else {
+ sx = event.deltaX;
+ sy = event.deltaY;
+ }
+
+ wasmTable.get(GLFW.active.scrollFunc)(GLFW.active.id, sx, sy);
+
+ event.preventDefault();
+ },onCanvasResize:function(width, height) {
+ if (!GLFW.active) return;
+
+ var resizeNeeded = true;
+
+ // If the client is requesting fullscreen mode
+ if (document["fullscreen"] || document["fullScreen"] || document["mozFullScreen"] || document["webkitIsFullScreen"]) {
+ GLFW.active.storedX = GLFW.active.x;
+ GLFW.active.storedY = GLFW.active.y;
+ GLFW.active.storedWidth = GLFW.active.width;
+ GLFW.active.storedHeight = GLFW.active.height;
+ GLFW.active.x = GLFW.active.y = 0;
+ GLFW.active.width = screen.width;
+ GLFW.active.height = screen.height;
+ GLFW.active.fullscreen = true;
+
+ // If the client is reverting from fullscreen mode
+ } else if (GLFW.active.fullscreen == true) {
+ GLFW.active.x = GLFW.active.storedX;
+ GLFW.active.y = GLFW.active.storedY;
+ GLFW.active.width = GLFW.active.storedWidth;
+ GLFW.active.height = GLFW.active.storedHeight;
+ GLFW.active.fullscreen = false;
+
+ // If the width/height values do not match current active window sizes
+ } else if (GLFW.active.width != width || GLFW.active.height != height) {
+ GLFW.active.width = width;
+ GLFW.active.height = height;
+ } else {
+ resizeNeeded = false;
+ }
+
+ // If any of the above conditions were true, we need to resize the canvas
+ if (resizeNeeded) {
+ // resets the canvas size to counter the aspect preservation of Browser.updateCanvasDimensions
+ Browser.setCanvasSize(GLFW.active.width, GLFW.active.height, true);
+ // TODO: Client dimensions (clientWidth/clientHeight) vs pixel dimensions (width/height) of
+ // the canvas should drive window and framebuffer size respectfully.
+ GLFW.onWindowSizeChanged();
+ GLFW.onFramebufferSizeChanged();
+ }
+ },onWindowSizeChanged:function() {
+ if (!GLFW.active) return;
+
+ if (!GLFW.active.windowSizeFunc) return;
+
+
+ wasmTable.get(GLFW.active.windowSizeFunc)(GLFW.active.id, GLFW.active.width, GLFW.active.height);
+ },onFramebufferSizeChanged:function() {
+ if (!GLFW.active) return;
+
+ if (!GLFW.active.framebufferSizeFunc) return;
+
+ wasmTable.get(GLFW.active.framebufferSizeFunc)(GLFW.active.id, GLFW.active.width, GLFW.active.height);
+ },getTime:function() {
+ return _emscripten_get_now() / 1000;
+ },setWindowTitle:function(winid, title) {
+ var win = GLFW.WindowFromId(winid);
+ if (!win) return;
+
+ win.title = UTF8ToString(title);
+ if (GLFW.active.id == win.id) {
+ document.title = win.title;
+ }
+ },setJoystickCallback:function(cbfun) {
+ GLFW.joystickFunc = cbfun;
+ GLFW.refreshJoysticks();
+ },joys:{},lastGamepadState:null,lastGamepadStateFrame:null,refreshJoysticks:function() {
+ // Produce a new Gamepad API sample if we are ticking a new game frame, or if not using emscripten_set_main_loop() at all to drive animation.
+ if (Browser.mainLoop.currentFrameNumber !== GLFW.lastGamepadStateFrame || !Browser.mainLoop.currentFrameNumber) {
+ GLFW.lastGamepadState = navigator.getGamepads ? navigator.getGamepads() : (navigator.webkitGetGamepads ? navigator.webkitGetGamepads : null);
+ GLFW.lastGamepadStateFrame = Browser.mainLoop.currentFrameNumber;
+
+ for (var joy = 0; joy < GLFW.lastGamepadState.length; ++joy) {
+ var gamepad = GLFW.lastGamepadState[joy];
+
+ if (gamepad) {
+ if (!GLFW.joys[joy]) {
+ console.log('glfw joystick connected:',joy);
+ GLFW.joys[joy] = {
+ id: allocate(intArrayFromString(gamepad.id), 'i8', ALLOC_NORMAL),
+ buttonsCount: gamepad.buttons.length,
+ axesCount: gamepad.axes.length,
+ buttons: allocate(new Array(gamepad.buttons.length), 'i8', ALLOC_NORMAL),
+ axes: allocate(new Array(gamepad.axes.length*4), 'float', ALLOC_NORMAL)
+ };
+
+ if (GLFW.joystickFunc) {
+ wasmTable.get(GLFW.joystickFunc)(joy, 0x00040001); // GLFW_CONNECTED
+ }
+ }
+
+ var data = GLFW.joys[joy];
+
+ for (var i = 0; i < gamepad.buttons.length; ++i) {
+ setValue(data.buttons + i, gamepad.buttons[i].pressed, 'i8');
+ }
+
+ for (var i = 0; i < gamepad.axes.length; ++i) {
+ setValue(data.axes + i*4, gamepad.axes[i], 'float');
+ }
+ } else {
+ if (GLFW.joys[joy]) {
+ console.log('glfw joystick disconnected',joy);
+
+ if (GLFW.joystickFunc) {
+ wasmTable.get(GLFW.joystickFunc)(joy, 0x00040002); // GLFW_DISCONNECTED
+ }
+
+ _free(GLFW.joys[joy].id);
+ _free(GLFW.joys[joy].buttons);
+ _free(GLFW.joys[joy].axes);
+
+ delete GLFW.joys[joy];
+ }
+ }
+ }
+ }
+ },setKeyCallback:function(winid, cbfun) {
+ var win = GLFW.WindowFromId(winid);
+ if (!win) return null;
+ var prevcbfun = win.keyFunc;
+ win.keyFunc = cbfun;
+ return prevcbfun;
+ },setCharCallback:function(winid, cbfun) {
+ var win = GLFW.WindowFromId(winid);
+ if (!win) return null;
+ var prevcbfun = win.charFunc;
+ win.charFunc = cbfun;
+ return prevcbfun;
+ },setMouseButtonCallback:function(winid, cbfun) {
+ var win = GLFW.WindowFromId(winid);
+ if (!win) return null;
+ var prevcbfun = win.mouseButtonFunc;
+ win.mouseButtonFunc = cbfun;
+ return prevcbfun;
+ },setCursorPosCallback:function(winid, cbfun) {
+ var win = GLFW.WindowFromId(winid);
+ if (!win) return null;
+ var prevcbfun = win.cursorPosFunc;
+ win.cursorPosFunc = cbfun;
+ return prevcbfun;
+ },setScrollCallback:function(winid, cbfun) {
+ var win = GLFW.WindowFromId(winid);
+ if (!win) return null;
+ var prevcbfun = win.scrollFunc;
+ win.scrollFunc = cbfun;
+ return prevcbfun;
+ },setDropCallback:function(winid, cbfun) {
+ var win = GLFW.WindowFromId(winid);
+ if (!win) return null;
+ var prevcbfun = win.dropFunc;
+ win.dropFunc = cbfun;
+ return prevcbfun;
+ },onDrop:function(event) {
+ if (!GLFW.active || !GLFW.active.dropFunc) return;
+ if (!event.dataTransfer || !event.dataTransfer.files || event.dataTransfer.files.length == 0) return;
+
+ event.preventDefault();
+
+ var filenames = allocate(new Array(event.dataTransfer.files.length*4), 'i8*', ALLOC_NORMAL);
+ var filenamesArray = [];
+ var count = event.dataTransfer.files.length;
+
+ // Read and save the files to emscripten's FS
+ var written = 0;
+ var drop_dir = '.glfw_dropped_files';
+ FS.createPath('/', drop_dir);
+
+ function save(file) {
+ var path = '/' + drop_dir + '/' + file.name.replace(/\//g, '_');
+ var reader = new FileReader();
+ reader.onloadend = function(e) {
+ if (reader.readyState != 2) { // not DONE
+ ++written;
+ console.log('failed to read dropped file: '+file.name+': '+reader.error);
+ return;
+ }
+
+ var data = e.target.result;
+ FS.writeFile(path, new Uint8Array(data));
+ if (++written === count) {
+ wasmTable.get(GLFW.active.dropFunc)(GLFW.active.id, count, filenames);
+
+ for (var i = 0; i < filenamesArray.length; ++i) {
+ _free(filenamesArray[i]);
+ }
+ _free(filenames);
+ }
+ };
+ reader.readAsArrayBuffer(file);
+
+ var filename = allocate(intArrayFromString(path), 'i8', ALLOC_NORMAL);
+ filenamesArray.push(filename);
+ setValue(filenames + i*4, filename, 'i8*');
+ }
+
+ for (var i = 0; i < count; ++i) {
+ save(event.dataTransfer.files[i]);
+ }
+
+ return false;
+ },onDragover:function(event) {
+ if (!GLFW.active || !GLFW.active.dropFunc) return;
+
+ event.preventDefault();
+ return false;
+ },setWindowSizeCallback:function(winid, cbfun) {
+ var win = GLFW.WindowFromId(winid);
+ if (!win) return null;
+ var prevcbfun = win.windowSizeFunc;
+ win.windowSizeFunc = cbfun;
+
+
+ return prevcbfun;
+ },setWindowCloseCallback:function(winid, cbfun) {
+ var win = GLFW.WindowFromId(winid);
+ if (!win) return null;
+ var prevcbfun = win.windowCloseFunc;
+ win.windowCloseFunc = cbfun;
+ return prevcbfun;
+ },setWindowRefreshCallback:function(winid, cbfun) {
+ var win = GLFW.WindowFromId(winid);
+ if (!win) return null;
+ var prevcbfun = win.windowRefreshFunc;
+ win.windowRefreshFunc = cbfun;
+ return prevcbfun;
+ },onClickRequestPointerLock:function(e) {
+ if (!Browser.pointerLock && Module['canvas'].requestPointerLock) {
+ Module['canvas'].requestPointerLock();
+ e.preventDefault();
+ }
+ },setInputMode:function(winid, mode, value) {
+ var win = GLFW.WindowFromId(winid);
+ if (!win) return;
+
+ switch(mode) {
+ case 0x00033001: { // GLFW_CURSOR
+ switch(value) {
+ case 0x00034001: { // GLFW_CURSOR_NORMAL
+ win.inputModes[mode] = value;
+ Module['canvas'].removeEventListener('click', GLFW.onClickRequestPointerLock, true);
+ Module['canvas'].exitPointerLock();
+ break;
+ }
+ case 0x00034002: { // GLFW_CURSOR_HIDDEN
+ console.log("glfwSetInputMode called with GLFW_CURSOR_HIDDEN value not implemented.");
+ break;
+ }
+ case 0x00034003: { // GLFW_CURSOR_DISABLED
+ win.inputModes[mode] = value;
+ Module['canvas'].addEventListener('click', GLFW.onClickRequestPointerLock, true);
+ Module['canvas'].requestPointerLock();
+ break;
+ }
+ default: {
+ console.log("glfwSetInputMode called with unknown value parameter value: " + value + ".");
+ break;
+ }
+ }
+ break;
+ }
+ case 0x00033002: { // GLFW_STICKY_KEYS
+ console.log("glfwSetInputMode called with GLFW_STICKY_KEYS mode not implemented.");
+ break;
+ }
+ case 0x00033003: { // GLFW_STICKY_MOUSE_BUTTONS
+ console.log("glfwSetInputMode called with GLFW_STICKY_MOUSE_BUTTONS mode not implemented.");
+ break;
+ }
+ default: {
+ console.log("glfwSetInputMode called with unknown mode parameter value: " + mode + ".");
+ break;
+ }
+ }
+ },getKey:function(winid, key) {
+ var win = GLFW.WindowFromId(winid);
+ if (!win) return 0;
+ return win.keys[key];
+ },getMouseButton:function(winid, button) {
+ var win = GLFW.WindowFromId(winid);
+ if (!win) return 0;
+ return (win.buttons & (1 << button)) > 0;
+ },getCursorPos:function(winid, x, y) {
+ setValue(x, Browser.mouseX, 'double');
+ setValue(y, Browser.mouseY, 'double');
+ },getMousePos:function(winid, x, y) {
+ setValue(x, Browser.mouseX, 'i32');
+ setValue(y, Browser.mouseY, 'i32');
+ },setCursorPos:function(winid, x, y) {
+ },getWindowPos:function(winid, x, y) {
+ var wx = 0;
+ var wy = 0;
+
+ var win = GLFW.WindowFromId(winid);
+ if (win) {
+ wx = win.x;
+ wy = win.y;
+ }
+
+ if (x) {
+ setValue(x, wx, 'i32');
+ }
+
+ if (y) {
+ setValue(y, wy, 'i32');
+ }
+ },setWindowPos:function(winid, x, y) {
+ var win = GLFW.WindowFromId(winid);
+ if (!win) return;
+ win.x = x;
+ win.y = y;
+ },getWindowSize:function(winid, width, height) {
+ var ww = 0;
+ var wh = 0;
+
+ var win = GLFW.WindowFromId(winid);
+ if (win) {
+ ww = win.width;
+ wh = win.height;
+ }
+
+ if (width) {
+ setValue(width, ww, 'i32');
+ }
+
+ if (height) {
+ setValue(height, wh, 'i32');
+ }
+ },setWindowSize:function(winid, width, height) {
+ var win = GLFW.WindowFromId(winid);
+ if (!win) return;
+
+ if (GLFW.active.id == win.id) {
+ if (width == screen.width && height == screen.height) {
+ Browser.requestFullscreen();
+ } else {
+ Browser.exitFullscreen();
+ Browser.setCanvasSize(width, height);
+ win.width = width;
+ win.height = height;
+ }
+ }
+
+ if (!win.windowSizeFunc) return;
+
+
+ wasmTable.get(win.windowSizeFunc)(win.id, width, height);
+ },createWindow:function(width, height, title, monitor, share) {
+ var i, id;
+ for (i = 0; i < GLFW.windows.length && GLFW.windows[i] !== null; i++) {
+ // no-op
+ }
+ if (i > 0) throw "glfwCreateWindow only supports one window at time currently";
+
+ // id for window
+ id = i + 1;
+
+ // not valid
+ if (width <= 0 || height <= 0) return 0;
+
+ if (monitor) {
+ Browser.requestFullscreen();
+ } else {
+ Browser.setCanvasSize(width, height);
+ }
+
+ // Create context when there are no existing alive windows
+ for (i = 0; i < GLFW.windows.length && GLFW.windows[i] == null; i++) {
+ // no-op
+ }
+ if (i == GLFW.windows.length) {
+ var contextAttributes = {
+ antialias: (GLFW.hints[0x0002100D] > 1), // GLFW_SAMPLES
+ depth: (GLFW.hints[0x00021005] > 0), // GLFW_DEPTH_BITS
+ stencil: (GLFW.hints[0x00021006] > 0), // GLFW_STENCIL_BITS
+ alpha: (GLFW.hints[0x00021004] > 0) // GLFW_ALPHA_BITS
+ }
+ Module.ctx = Browser.createContext(Module['canvas'], true, true, contextAttributes);
+ }
+
+ // If context creation failed, do not return a valid window
+ if (!Module.ctx) return 0;
+
+ // Get non alive id
+ var win = new GLFW_Window(id, width, height, title, monitor, share);
+
+ // Set window to array
+ if (id - 1 == GLFW.windows.length) {
+ GLFW.windows.push(win);
+ } else {
+ GLFW.windows[id - 1] = win;
+ }
+
+ GLFW.active = win;
+ return win.id;
+ },destroyWindow:function(winid) {
+ var win = GLFW.WindowFromId(winid);
+ if (!win) return;
+
+ if (win.windowCloseFunc)
+ wasmTable.get(win.windowCloseFunc)(win.id);
+
+ GLFW.windows[win.id - 1] = null;
+ if (GLFW.active.id == win.id)
+ GLFW.active = null;
+
+ // Destroy context when no alive windows
+ for (var i = 0; i < GLFW.windows.length; i++)
+ if (GLFW.windows[i] !== null) return;
+
+ Module.ctx = Browser.destroyContext(Module['canvas'], true, true);
+ },swapBuffers:function(winid) {
+ },GLFW2ParamToGLFW3Param:function(param) {
+ var table = {
+ 0x00030001:0, // GLFW_MOUSE_CURSOR
+ 0x00030002:0, // GLFW_STICKY_KEYS
+ 0x00030003:0, // GLFW_STICKY_MOUSE_BUTTONS
+ 0x00030004:0, // GLFW_SYSTEM_KEYS
+ 0x00030005:0, // GLFW_KEY_REPEAT
+ 0x00030006:0, // GLFW_AUTO_POLL_EVENTS
+ 0x00020001:0, // GLFW_OPENED
+ 0x00020002:0, // GLFW_ACTIVE
+ 0x00020003:0, // GLFW_ICONIFIED
+ 0x00020004:0, // GLFW_ACCELERATED
+ 0x00020005:0x00021001, // GLFW_RED_BITS
+ 0x00020006:0x00021002, // GLFW_GREEN_BITS
+ 0x00020007:0x00021003, // GLFW_BLUE_BITS
+ 0x00020008:0x00021004, // GLFW_ALPHA_BITS
+ 0x00020009:0x00021005, // GLFW_DEPTH_BITS
+ 0x0002000A:0x00021006, // GLFW_STENCIL_BITS
+ 0x0002000B:0x0002100F, // GLFW_REFRESH_RATE
+ 0x0002000C:0x00021007, // GLFW_ACCUM_RED_BITS
+ 0x0002000D:0x00021008, // GLFW_ACCUM_GREEN_BITS
+ 0x0002000E:0x00021009, // GLFW_ACCUM_BLUE_BITS
+ 0x0002000F:0x0002100A, // GLFW_ACCUM_ALPHA_BITS
+ 0x00020010:0x0002100B, // GLFW_AUX_BUFFERS
+ 0x00020011:0x0002100C, // GLFW_STEREO
+ 0x00020012:0, // GLFW_WINDOW_NO_RESIZE
+ 0x00020013:0x0002100D, // GLFW_FSAA_SAMPLES
+ 0x00020014:0x00022002, // GLFW_OPENGL_VERSION_MAJOR
+ 0x00020015:0x00022003, // GLFW_OPENGL_VERSION_MINOR
+ 0x00020016:0x00022006, // GLFW_OPENGL_FORWARD_COMPAT
+ 0x00020017:0x00022007, // GLFW_OPENGL_DEBUG_CONTEXT
+ 0x00020018:0x00022008, // GLFW_OPENGL_PROFILE
+ };
+ return table[param];
+ }};function _glfwCreateWindow(width, height, title, monitor, share) {
+ return GLFW.createWindow(width, height, title, monitor, share);
+ }
+
+ function _glfwDefaultWindowHints() {
+ GLFW.hints = GLFW.defaultHints;
+ }
+
+ function _glfwDestroyWindow(winid) {
+ return GLFW.destroyWindow(winid);
+ }
+
+ function _glfwGetPrimaryMonitor() {
+ return 1;
+ }
+
+ function _glfwGetTime() {
+ return GLFW.getTime() - GLFW.initialTime;
+ }
+
+ function _glfwGetVideoModes(monitor, count) {
+ setValue(count, 0, 'i32');
+ return 0;
+ }
+
+ function _glfwInit() {
+ if (GLFW.windows) return 1; // GL_TRUE
+
+ GLFW.initialTime = GLFW.getTime();
+ GLFW.hints = GLFW.defaultHints;
+ GLFW.windows = new Array()
+ GLFW.active = null;
+
+ window.addEventListener("gamepadconnected", GLFW.onGamepadConnected, true);
+ window.addEventListener("gamepaddisconnected", GLFW.onGamepadDisconnected, true);
+ window.addEventListener("keydown", GLFW.onKeydown, true);
+ window.addEventListener("keypress", GLFW.onKeyPress, true);
+ window.addEventListener("keyup", GLFW.onKeyup, true);
+ window.addEventListener("blur", GLFW.onBlur, true);
+ Module["canvas"].addEventListener("touchmove", GLFW.onMousemove, true);
+ Module["canvas"].addEventListener("touchstart", GLFW.onMouseButtonDown, true);
+ Module["canvas"].addEventListener("touchcancel", GLFW.onMouseButtonUp, true);
+ Module["canvas"].addEventListener("touchend", GLFW.onMouseButtonUp, true);
+ Module["canvas"].addEventListener("mousemove", GLFW.onMousemove, true);
+ Module["canvas"].addEventListener("mousedown", GLFW.onMouseButtonDown, true);
+ Module["canvas"].addEventListener("mouseup", GLFW.onMouseButtonUp, true);
+ Module["canvas"].addEventListener('wheel', GLFW.onMouseWheel, true);
+ Module["canvas"].addEventListener('mousewheel', GLFW.onMouseWheel, true);
+ Module["canvas"].addEventListener('mouseenter', GLFW.onMouseenter, true);
+ Module["canvas"].addEventListener('mouseleave', GLFW.onMouseleave, true);
+ Module["canvas"].addEventListener('drop', GLFW.onDrop, true);
+ Module["canvas"].addEventListener('dragover', GLFW.onDragover, true);
+
+ Browser.resizeListeners.push(function(width, height) {
+ GLFW.onCanvasResize(width, height);
+ });
+ return 1; // GL_TRUE
+ }
+
+ function _glfwMakeContextCurrent(winid) {}
+
+ function _glfwSetCharCallback(winid, cbfun) {
+ return GLFW.setCharCallback(winid, cbfun);
+ }
+
+ function _glfwSetCursorEnterCallback(winid, cbfun) {
+ var win = GLFW.WindowFromId(winid);
+ if (!win) return null;
+ var prevcbfun = win.cursorEnterFunc;
+ win.cursorEnterFunc = cbfun;
+ return prevcbfun;
+ }
+
+ function _glfwSetCursorPosCallback(winid, cbfun) {
+ return GLFW.setCursorPosCallback(winid, cbfun);
+ }
+
+ function _glfwSetDropCallback(winid, cbfun) {
+ return GLFW.setDropCallback(winid, cbfun);
+ }
+
+ function _glfwSetErrorCallback(cbfun) {
+ var prevcbfun = GLFW.errorFunc;
+ GLFW.errorFunc = cbfun;
+ return prevcbfun;
+ }
+
+ function _glfwSetKeyCallback(winid, cbfun) {
+ return GLFW.setKeyCallback(winid, cbfun);
+ }
+
+ function _glfwSetMouseButtonCallback(winid, cbfun) {
+ return GLFW.setMouseButtonCallback(winid, cbfun);
+ }
+
+ function _glfwSetScrollCallback(winid, cbfun) {
+ return GLFW.setScrollCallback(winid, cbfun);
+ }
+
+ function _glfwSetWindowFocusCallback(winid, cbfun) {
+ var win = GLFW.WindowFromId(winid);
+ if (!win) return null;
+ var prevcbfun = win.windowFocusFunc;
+ win.windowFocusFunc = cbfun;
+ return prevcbfun;
+ }
+
+ function _glfwSetWindowIconifyCallback(winid, cbfun) {
+ var win = GLFW.WindowFromId(winid);
+ if (!win) return null;
+ var prevcbfun = win.windowIconifyFunc;
+ win.windowIconifyFunc = cbfun;
+ return prevcbfun;
+ }
+
+ function _glfwSetWindowShouldClose(winid, value) {
+ var win = GLFW.WindowFromId(winid);
+ if (!win) return;
+ win.shouldClose = value;
+ }
+
+ function _glfwSetWindowSizeCallback(winid, cbfun) {
+ return GLFW.setWindowSizeCallback(winid, cbfun);
+ }
+
+ function _glfwSwapBuffers(winid) {
+ GLFW.swapBuffers(winid);
+ }
+
+ function _glfwSwapInterval(interval) {
+ interval = Math.abs(interval); // GLFW uses negative values to enable GLX_EXT_swap_control_tear, which we don't have, so just treat negative and positive the same.
+ if (interval == 0) _emscripten_set_main_loop_timing(0/*EM_TIMING_SETTIMEOUT*/, 0);
+ else _emscripten_set_main_loop_timing(1/*EM_TIMING_RAF*/, interval);
+ }
+
+ function _glfwTerminate() {
+ window.removeEventListener("gamepadconnected", GLFW.onGamepadConnected, true);
+ window.removeEventListener("gamepaddisconnected", GLFW.onGamepadDisconnected, true);
+ window.removeEventListener("keydown", GLFW.onKeydown, true);
+ window.removeEventListener("keypress", GLFW.onKeyPress, true);
+ window.removeEventListener("keyup", GLFW.onKeyup, true);
+ window.removeEventListener("blur", GLFW.onBlur, true);
+ Module["canvas"].removeEventListener("touchmove", GLFW.onMousemove, true);
+ Module["canvas"].removeEventListener("touchstart", GLFW.onMouseButtonDown, true);
+ Module["canvas"].removeEventListener("touchcancel", GLFW.onMouseButtonUp, true);
+ Module["canvas"].removeEventListener("touchend", GLFW.onMouseButtonUp, true);
+ Module["canvas"].removeEventListener("mousemove", GLFW.onMousemove, true);
+ Module["canvas"].removeEventListener("mousedown", GLFW.onMouseButtonDown, true);
+ Module["canvas"].removeEventListener("mouseup", GLFW.onMouseButtonUp, true);
+ Module["canvas"].removeEventListener('wheel', GLFW.onMouseWheel, true);
+ Module["canvas"].removeEventListener('mousewheel', GLFW.onMouseWheel, true);
+ Module["canvas"].removeEventListener('mouseenter', GLFW.onMouseenter, true);
+ Module["canvas"].removeEventListener('mouseleave', GLFW.onMouseleave, true);
+ Module["canvas"].removeEventListener('drop', GLFW.onDrop, true);
+ Module["canvas"].removeEventListener('dragover', GLFW.onDragover, true);
+
+
+ Module["canvas"].width = Module["canvas"].height = 1;
+ GLFW.windows = null;
+ GLFW.active = null;
+ }
+
+ function _glfwWindowHint(target, hint) {
+ GLFW.hints[target] = hint;
+ }
+
+
+ function _usleep(useconds) {
+ // int usleep(useconds_t useconds);
+ // http://pubs.opengroup.org/onlinepubs/000095399/functions/usleep.html
+ // We're single-threaded, so use a busy loop. Super-ugly.
+ var start = _emscripten_get_now();
+ while (_emscripten_get_now() - start < useconds / 1000) {
+ // Do nothing.
+ }
+ }function _nanosleep(rqtp, rmtp) {
+ // int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
+ if (rqtp === 0) {
+ setErrNo(28);
+ return -1;
+ }
+ var seconds = HEAP32[((rqtp)>>2)];
+ var nanoseconds = HEAP32[(((rqtp)+(4))>>2)];
+ if (nanoseconds < 0 || nanoseconds > 999999999 || seconds < 0) {
+ setErrNo(28);
+ return -1;
+ }
+ if (rmtp !== 0) {
+ HEAP32[((rmtp)>>2)]=0;
+ HEAP32[(((rmtp)+(4))>>2)]=0;
+ }
+ return _usleep((seconds * 1e6) + (nanoseconds / 1000));
+ }
+
+ function _setTempRet0($i) {
+ setTempRet0(($i) | 0);
+ }
+
+ function _time(ptr) {
+ var ret = (Date.now()/1000)|0;
+ if (ptr) {
+ HEAP32[((ptr)>>2)]=ret;
+ }
+ return ret;
+ }
+
+var FSNode = /** @constructor */ function(parent, name, mode, rdev) {
+ if (!parent) {
+ parent = this; // root node sets parent to itself
+ }
+ this.parent = parent;
+ this.mount = parent.mount;
+ this.mounted = null;
+ this.id = FS.nextInode++;
+ this.name = name;
+ this.mode = mode;
+ this.node_ops = {};
+ this.stream_ops = {};
+ this.rdev = rdev;
+ };
+ var readMode = 292/*292*/ | 73/*73*/;
+ var writeMode = 146/*146*/;
+ Object.defineProperties(FSNode.prototype, {
+ read: {
+ get: /** @this{FSNode} */function() {
+ return (this.mode & readMode) === readMode;
+ },
+ set: /** @this{FSNode} */function(val) {
+ val ? this.mode |= readMode : this.mode &= ~readMode;
+ }
+ },
+ write: {
+ get: /** @this{FSNode} */function() {
+ return (this.mode & writeMode) === writeMode;
+ },
+ set: /** @this{FSNode} */function(val) {
+ val ? this.mode |= writeMode : this.mode &= ~writeMode;
+ }
+ },
+ isFolder: {
+ get: /** @this{FSNode} */function() {
+ return FS.isDir(this.mode);
+ }
+ },
+ isDevice: {
+ get: /** @this{FSNode} */function() {
+ return FS.isChrdev(this.mode);
+ }
+ }
+ });
+ FS.FSNode = FSNode;
+ FS.staticInit();Module["FS_createFolder"] = FS.createFolder;Module["FS_createPath"] = FS.createPath;Module["FS_createDataFile"] = FS.createDataFile;Module["FS_createPreloadedFile"] = FS.createPreloadedFile;Module["FS_createLazyFile"] = FS.createLazyFile;Module["FS_createLink"] = FS.createLink;Module["FS_createDevice"] = FS.createDevice;Module["FS_unlink"] = FS.unlink;;
+Module["requestFullscreen"] = function Module_requestFullscreen(lockPointer, resizeCanvas) { Browser.requestFullscreen(lockPointer, resizeCanvas) };
+ Module["requestAnimationFrame"] = function Module_requestAnimationFrame(func) { Browser.requestAnimationFrame(func) };
+ Module["setCanvasSize"] = function Module_setCanvasSize(width, height, noUpdates) { Browser.setCanvasSize(width, height, noUpdates) };
+ Module["pauseMainLoop"] = function Module_pauseMainLoop() { Browser.mainLoop.pause() };
+ Module["resumeMainLoop"] = function Module_resumeMainLoop() { Browser.mainLoop.resume() };
+ Module["getUserMedia"] = function Module_getUserMedia() { Browser.getUserMedia() }
+ Module["createContext"] = function Module_createContext(canvas, useWebGL, setInModule, webGLContextAttributes) { return Browser.createContext(canvas, useWebGL, setInModule, webGLContextAttributes) };
+var GLctx;;
+for (var i = 0; i < 32; ++i) tempFixedLengthArray.push(new Array(i));;
+var miniTempWebGLFloatBuffersStorage = new Float32Array(288);
+ for (/**@suppress{duplicate}*/var i = 0; i < 288; ++i) {
+ miniTempWebGLFloatBuffers[i] = miniTempWebGLFloatBuffersStorage.subarray(0, i+1);
+ }
+ ;
+var __miniTempWebGLIntBuffersStorage = new Int32Array(288);
+ for (/**@suppress{duplicate}*/var i = 0; i < 288; ++i) {
+ __miniTempWebGLIntBuffers[i] = __miniTempWebGLIntBuffersStorage.subarray(0, i+1);
+ }
+ ;
+var ASSERTIONS = false;
+
+
+
+/** @type {function(string, boolean=, number=)} */
+function intArrayFromString(stringy, dontAddNull, length) {
+ var len = length > 0 ? length : lengthBytesUTF8(stringy)+1;
+ var u8array = new Array(len);
+ var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length);
+ if (dontAddNull) u8array.length = numBytesWritten;
+ return u8array;
+}
+
+function intArrayToString(array) {
+ var ret = [];
+ for (var i = 0; i < array.length; i++) {
+ var chr = array[i];
+ if (chr > 0xFF) {
+ if (ASSERTIONS) {
+ assert(false, 'Character code ' + chr + ' (' + String.fromCharCode(chr) + ') at offset ' + i + ' not in 0x00-0xFF.');
+ }
+ chr &= 0xFF;
+ }
+ ret.push(String.fromCharCode(chr));
+ }
+ return ret.join('');
+}
+
+
+
+/* global initializers */ __ATINIT__.push({ func: function() { ___wasm_call_ctors() } });
+
+var asmLibraryArg = { "__assert_fail": ___assert_fail, "__indirect_function_table": wasmTable, "__sys_fcntl64": ___sys_fcntl64, "__sys_ioctl": ___sys_ioctl, "__sys_open": ___sys_open, "eglGetProcAddress": _eglGetProcAddress, "emscripten_exit_pointerlock": _emscripten_exit_pointerlock, "emscripten_get_element_css_size": _emscripten_get_element_css_size, "emscripten_get_gamepad_status": _emscripten_get_gamepad_status, "emscripten_get_num_gamepads": _emscripten_get_num_gamepads, "emscripten_get_pointerlock_status": _emscripten_get_pointerlock_status, "emscripten_glActiveTexture": _emscripten_glActiveTexture, "emscripten_glAttachShader": _emscripten_glAttachShader, "emscripten_glBeginQueryEXT": _emscripten_glBeginQueryEXT, "emscripten_glBindAttribLocation": _emscripten_glBindAttribLocation, "emscripten_glBindBuffer": _emscripten_glBindBuffer, "emscripten_glBindFramebuffer": _emscripten_glBindFramebuffer, "emscripten_glBindRenderbuffer": _emscripten_glBindRenderbuffer, "emscripten_glBindTexture": _emscripten_glBindTexture, "emscripten_glBindVertexArrayOES": _emscripten_glBindVertexArrayOES, "emscripten_glBlendColor": _emscripten_glBlendColor, "emscripten_glBlendEquation": _emscripten_glBlendEquation, "emscripten_glBlendEquationSeparate": _emscripten_glBlendEquationSeparate, "emscripten_glBlendFunc": _emscripten_glBlendFunc, "emscripten_glBlendFuncSeparate": _emscripten_glBlendFuncSeparate, "emscripten_glBufferData": _emscripten_glBufferData, "emscripten_glBufferSubData": _emscripten_glBufferSubData, "emscripten_glCheckFramebufferStatus": _emscripten_glCheckFramebufferStatus, "emscripten_glClear": _emscripten_glClear, "emscripten_glClearColor": _emscripten_glClearColor, "emscripten_glClearDepthf": _emscripten_glClearDepthf, "emscripten_glClearStencil": _emscripten_glClearStencil, "emscripten_glColorMask": _emscripten_glColorMask, "emscripten_glCompileShader": _emscripten_glCompileShader, "emscripten_glCompressedTexImage2D": _emscripten_glCompressedTexImage2D, "emscripten_glCompressedTexSubImage2D": _emscripten_glCompressedTexSubImage2D, "emscripten_glCopyTexImage2D": _emscripten_glCopyTexImage2D, "emscripten_glCopyTexSubImage2D": _emscripten_glCopyTexSubImage2D, "emscripten_glCreateProgram": _emscripten_glCreateProgram, "emscripten_glCreateShader": _emscripten_glCreateShader, "emscripten_glCullFace": _emscripten_glCullFace, "emscripten_glDeleteBuffers": _emscripten_glDeleteBuffers, "emscripten_glDeleteFramebuffers": _emscripten_glDeleteFramebuffers, "emscripten_glDeleteProgram": _emscripten_glDeleteProgram, "emscripten_glDeleteQueriesEXT": _emscripten_glDeleteQueriesEXT, "emscripten_glDeleteRenderbuffers": _emscripten_glDeleteRenderbuffers, "emscripten_glDeleteShader": _emscripten_glDeleteShader, "emscripten_glDeleteTextures": _emscripten_glDeleteTextures, "emscripten_glDeleteVertexArraysOES": _emscripten_glDeleteVertexArraysOES, "emscripten_glDepthFunc": _emscripten_glDepthFunc, "emscripten_glDepthMask": _emscripten_glDepthMask, "emscripten_glDepthRangef": _emscripten_glDepthRangef, "emscripten_glDetachShader": _emscripten_glDetachShader, "emscripten_glDisable": _emscripten_glDisable, "emscripten_glDisableVertexAttribArray": _emscripten_glDisableVertexAttribArray, "emscripten_glDrawArrays": _emscripten_glDrawArrays, "emscripten_glDrawArraysInstancedANGLE": _emscripten_glDrawArraysInstancedANGLE, "emscripten_glDrawBuffersWEBGL": _emscripten_glDrawBuffersWEBGL, "emscripten_glDrawElements": _emscripten_glDrawElements, "emscripten_glDrawElementsInstancedANGLE": _emscripten_glDrawElementsInstancedANGLE, "emscripten_glEnable": _emscripten_glEnable, "emscripten_glEnableVertexAttribArray": _emscripten_glEnableVertexAttribArray, "emscripten_glEndQueryEXT": _emscripten_glEndQueryEXT, "emscripten_glFinish": _emscripten_glFinish, "emscripten_glFlush": _emscripten_glFlush, "emscripten_glFramebufferRenderbuffer": _emscripten_glFramebufferRenderbuffer, "emscripten_glFramebufferTexture2D": _emscripten_glFramebufferTexture2D, "emscripten_glFrontFace": _emscripten_glFrontFace, "emscripten_glGenBuffers": _emscripten_glGenBuffers, "emscripten_glGenFramebuffers": _emscripten_glGenFramebuffers, "emscripten_glGenQueriesEXT": _emscripten_glGenQueriesEXT, "emscripten_glGenRenderbuffers": _emscripten_glGenRenderbuffers, "emscripten_glGenTextures": _emscripten_glGenTextures, "emscripten_glGenVertexArraysOES": _emscripten_glGenVertexArraysOES, "emscripten_glGenerateMipmap": _emscripten_glGenerateMipmap, "emscripten_glGetActiveAttrib": _emscripten_glGetActiveAttrib, "emscripten_glGetActiveUniform": _emscripten_glGetActiveUniform, "emscripten_glGetAttachedShaders": _emscripten_glGetAttachedShaders, "emscripten_glGetAttribLocation": _emscripten_glGetAttribLocation, "emscripten_glGetBooleanv": _emscripten_glGetBooleanv, "emscripten_glGetBufferParameteriv": _emscripten_glGetBufferParameteriv, "emscripten_glGetError": _emscripten_glGetError, "emscripten_glGetFloatv": _emscripten_glGetFloatv, "emscripten_glGetFramebufferAttachmentParameteriv": _emscripten_glGetFramebufferAttachmentParameteriv, "emscripten_glGetIntegerv": _emscripten_glGetIntegerv, "emscripten_glGetProgramInfoLog": _emscripten_glGetProgramInfoLog, "emscripten_glGetProgramiv": _emscripten_glGetProgramiv, "emscripten_glGetQueryObjecti64vEXT": _emscripten_glGetQueryObjecti64vEXT, "emscripten_glGetQueryObjectivEXT": _emscripten_glGetQueryObjectivEXT, "emscripten_glGetQueryObjectui64vEXT": _emscripten_glGetQueryObjectui64vEXT, "emscripten_glGetQueryObjectuivEXT": _emscripten_glGetQueryObjectuivEXT, "emscripten_glGetQueryivEXT": _emscripten_glGetQueryivEXT, "emscripten_glGetRenderbufferParameteriv": _emscripten_glGetRenderbufferParameteriv, "emscripten_glGetShaderInfoLog": _emscripten_glGetShaderInfoLog, "emscripten_glGetShaderPrecisionFormat": _emscripten_glGetShaderPrecisionFormat, "emscripten_glGetShaderSource": _emscripten_glGetShaderSource, "emscripten_glGetShaderiv": _emscripten_glGetShaderiv, "emscripten_glGetString": _emscripten_glGetString, "emscripten_glGetTexParameterfv": _emscripten_glGetTexParameterfv, "emscripten_glGetTexParameteriv": _emscripten_glGetTexParameteriv, "emscripten_glGetUniformLocation": _emscripten_glGetUniformLocation, "emscripten_glGetUniformfv": _emscripten_glGetUniformfv, "emscripten_glGetUniformiv": _emscripten_glGetUniformiv, "emscripten_glGetVertexAttribPointerv": _emscripten_glGetVertexAttribPointerv, "emscripten_glGetVertexAttribfv": _emscripten_glGetVertexAttribfv, "emscripten_glGetVertexAttribiv": _emscripten_glGetVertexAttribiv, "emscripten_glHint": _emscripten_glHint, "emscripten_glIsBuffer": _emscripten_glIsBuffer, "emscripten_glIsEnabled": _emscripten_glIsEnabled, "emscripten_glIsFramebuffer": _emscripten_glIsFramebuffer, "emscripten_glIsProgram": _emscripten_glIsProgram, "emscripten_glIsQueryEXT": _emscripten_glIsQueryEXT, "emscripten_glIsRenderbuffer": _emscripten_glIsRenderbuffer, "emscripten_glIsShader": _emscripten_glIsShader, "emscripten_glIsTexture": _emscripten_glIsTexture, "emscripten_glIsVertexArrayOES": _emscripten_glIsVertexArrayOES, "emscripten_glLineWidth": _emscripten_glLineWidth, "emscripten_glLinkProgram": _emscripten_glLinkProgram, "emscripten_glPixelStorei": _emscripten_glPixelStorei, "emscripten_glPolygonOffset": _emscripten_glPolygonOffset, "emscripten_glQueryCounterEXT": _emscripten_glQueryCounterEXT, "emscripten_glReadPixels": _emscripten_glReadPixels, "emscripten_glReleaseShaderCompiler": _emscripten_glReleaseShaderCompiler, "emscripten_glRenderbufferStorage": _emscripten_glRenderbufferStorage, "emscripten_glSampleCoverage": _emscripten_glSampleCoverage, "emscripten_glScissor": _emscripten_glScissor, "emscripten_glShaderBinary": _emscripten_glShaderBinary, "emscripten_glShaderSource": _emscripten_glShaderSource, "emscripten_glStencilFunc": _emscripten_glStencilFunc, "emscripten_glStencilFuncSeparate": _emscripten_glStencilFuncSeparate, "emscripten_glStencilMask": _emscripten_glStencilMask, "emscripten_glStencilMaskSeparate": _emscripten_glStencilMaskSeparate, "emscripten_glStencilOp": _emscripten_glStencilOp, "emscripten_glStencilOpSeparate": _emscripten_glStencilOpSeparate, "emscripten_glTexImage2D": _emscripten_glTexImage2D, "emscripten_glTexParameterf": _emscripten_glTexParameterf, "emscripten_glTexParameterfv": _emscripten_glTexParameterfv, "emscripten_glTexParameteri": _emscripten_glTexParameteri, "emscripten_glTexParameteriv": _emscripten_glTexParameteriv, "emscripten_glTexSubImage2D": _emscripten_glTexSubImage2D, "emscripten_glUniform1f": _emscripten_glUniform1f, "emscripten_glUniform1fv": _emscripten_glUniform1fv, "emscripten_glUniform1i": _emscripten_glUniform1i, "emscripten_glUniform1iv": _emscripten_glUniform1iv, "emscripten_glUniform2f": _emscripten_glUniform2f, "emscripten_glUniform2fv": _emscripten_glUniform2fv, "emscripten_glUniform2i": _emscripten_glUniform2i, "emscripten_glUniform2iv": _emscripten_glUniform2iv, "emscripten_glUniform3f": _emscripten_glUniform3f, "emscripten_glUniform3fv": _emscripten_glUniform3fv, "emscripten_glUniform3i": _emscripten_glUniform3i, "emscripten_glUniform3iv": _emscripten_glUniform3iv, "emscripten_glUniform4f": _emscripten_glUniform4f, "emscripten_glUniform4fv": _emscripten_glUniform4fv, "emscripten_glUniform4i": _emscripten_glUniform4i, "emscripten_glUniform4iv": _emscripten_glUniform4iv, "emscripten_glUniformMatrix2fv": _emscripten_glUniformMatrix2fv, "emscripten_glUniformMatrix3fv": _emscripten_glUniformMatrix3fv, "emscripten_glUniformMatrix4fv": _emscripten_glUniformMatrix4fv, "emscripten_glUseProgram": _emscripten_glUseProgram, "emscripten_glValidateProgram": _emscripten_glValidateProgram, "emscripten_glVertexAttrib1f": _emscripten_glVertexAttrib1f, "emscripten_glVertexAttrib1fv": _emscripten_glVertexAttrib1fv, "emscripten_glVertexAttrib2f": _emscripten_glVertexAttrib2f, "emscripten_glVertexAttrib2fv": _emscripten_glVertexAttrib2fv, "emscripten_glVertexAttrib3f": _emscripten_glVertexAttrib3f, "emscripten_glVertexAttrib3fv": _emscripten_glVertexAttrib3fv, "emscripten_glVertexAttrib4f": _emscripten_glVertexAttrib4f, "emscripten_glVertexAttrib4fv": _emscripten_glVertexAttrib4fv, "emscripten_glVertexAttribDivisorANGLE": _emscripten_glVertexAttribDivisorANGLE, "emscripten_glVertexAttribPointer": _emscripten_glVertexAttribPointer, "emscripten_glViewport": _emscripten_glViewport, "emscripten_memcpy_big": _emscripten_memcpy_big, "emscripten_request_pointerlock": _emscripten_request_pointerlock, "emscripten_resize_heap": _emscripten_resize_heap, "emscripten_run_script": _emscripten_run_script, "emscripten_sample_gamepad_data": _emscripten_sample_gamepad_data, "emscripten_set_click_callback_on_thread": _emscripten_set_click_callback_on_thread, "emscripten_set_fullscreenchange_callback_on_thread": _emscripten_set_fullscreenchange_callback_on_thread, "emscripten_set_gamepadconnected_callback_on_thread": _emscripten_set_gamepadconnected_callback_on_thread, "emscripten_set_gamepaddisconnected_callback_on_thread": _emscripten_set_gamepaddisconnected_callback_on_thread, "emscripten_set_keydown_callback_on_thread": _emscripten_set_keydown_callback_on_thread, "emscripten_set_main_loop": _emscripten_set_main_loop, "emscripten_set_touchcancel_callback_on_thread": _emscripten_set_touchcancel_callback_on_thread, "emscripten_set_touchend_callback_on_thread": _emscripten_set_touchend_callback_on_thread, "emscripten_set_touchmove_callback_on_thread": _emscripten_set_touchmove_callback_on_thread, "emscripten_set_touchstart_callback_on_thread": _emscripten_set_touchstart_callback_on_thread, "exit": _exit, "fd_close": _fd_close, "fd_read": _fd_read, "fd_seek": _fd_seek, "fd_write": _fd_write, "glActiveTexture": _glActiveTexture, "glAttachShader": _glAttachShader, "glBindAttribLocation": _glBindAttribLocation, "glBindBuffer": _glBindBuffer, "glBindTexture": _glBindTexture, "glBlendFunc": _glBlendFunc, "glBufferData": _glBufferData, "glBufferSubData": _glBufferSubData, "glClear": _glClear, "glClearColor": _glClearColor, "glClearDepthf": _glClearDepthf, "glCompileShader": _glCompileShader, "glCompressedTexImage2D": _glCompressedTexImage2D, "glCreateProgram": _glCreateProgram, "glCreateShader": _glCreateShader, "glCullFace": _glCullFace, "glDeleteBuffers": _glDeleteBuffers, "glDeleteProgram": _glDeleteProgram, "glDeleteShader": _glDeleteShader, "glDeleteTextures": _glDeleteTextures, "glDepthFunc": _glDepthFunc, "glDetachShader": _glDetachShader, "glDisable": _glDisable, "glDisableVertexAttribArray": _glDisableVertexAttribArray, "glDrawArrays": _glDrawArrays, "glDrawElements": _glDrawElements, "glEnable": _glEnable, "glEnableVertexAttribArray": _glEnableVertexAttribArray, "glFrontFace": _glFrontFace, "glGenBuffers": _glGenBuffers, "glGenTextures": _glGenTextures, "glGetAttribLocation": _glGetAttribLocation, "glGetFloatv": _glGetFloatv, "glGetProgramInfoLog": _glGetProgramInfoLog, "glGetProgramiv": _glGetProgramiv, "glGetShaderInfoLog": _glGetShaderInfoLog, "glGetShaderiv": _glGetShaderiv, "glGetString": _glGetString, "glGetUniformLocation": _glGetUniformLocation, "glLinkProgram": _glLinkProgram, "glPixelStorei": _glPixelStorei, "glReadPixels": _glReadPixels, "glShaderSource": _glShaderSource, "glTexImage2D": _glTexImage2D, "glTexParameteri": _glTexParameteri, "glUniform1i": _glUniform1i, "glUniform4f": _glUniform4f, "glUniformMatrix4fv": _glUniformMatrix4fv, "glUseProgram": _glUseProgram, "glVertexAttrib2f": _glVertexAttrib2f, "glVertexAttrib3f": _glVertexAttrib3f, "glVertexAttrib4f": _glVertexAttrib4f, "glVertexAttribPointer": _glVertexAttribPointer, "glViewport": _glViewport, "glfwCreateWindow": _glfwCreateWindow, "glfwDefaultWindowHints": _glfwDefaultWindowHints, "glfwDestroyWindow": _glfwDestroyWindow, "glfwGetPrimaryMonitor": _glfwGetPrimaryMonitor, "glfwGetTime": _glfwGetTime, "glfwGetVideoModes": _glfwGetVideoModes, "glfwInit": _glfwInit, "glfwMakeContextCurrent": _glfwMakeContextCurrent, "glfwSetCharCallback": _glfwSetCharCallback, "glfwSetCursorEnterCallback": _glfwSetCursorEnterCallback, "glfwSetCursorPosCallback": _glfwSetCursorPosCallback, "glfwSetDropCallback": _glfwSetDropCallback, "glfwSetErrorCallback": _glfwSetErrorCallback, "glfwSetKeyCallback": _glfwSetKeyCallback, "glfwSetMouseButtonCallback": _glfwSetMouseButtonCallback, "glfwSetScrollCallback": _glfwSetScrollCallback, "glfwSetWindowFocusCallback": _glfwSetWindowFocusCallback, "glfwSetWindowIconifyCallback": _glfwSetWindowIconifyCallback, "glfwSetWindowShouldClose": _glfwSetWindowShouldClose, "glfwSetWindowSizeCallback": _glfwSetWindowSizeCallback, "glfwSwapBuffers": _glfwSwapBuffers, "glfwSwapInterval": _glfwSwapInterval, "glfwTerminate": _glfwTerminate, "glfwWindowHint": _glfwWindowHint, "memory": wasmMemory, "nanosleep": _nanosleep, "setTempRet0": _setTempRet0, "time": _time };
+var asm = createWasm();
+/** @type {function(...*):?} */
+var ___wasm_call_ctors = Module["___wasm_call_ctors"] = function() {
+ return (___wasm_call_ctors = Module["___wasm_call_ctors"] = Module["asm"]["__wasm_call_ctors"]).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _free = Module["_free"] = function() {
+ return (_free = Module["_free"] = Module["asm"]["free"]).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _main = Module["_main"] = function() {
+ return (_main = Module["_main"] = Module["asm"]["main"]).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _malloc = Module["_malloc"] = function() {
+ return (_malloc = Module["_malloc"] = Module["asm"]["malloc"]).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _strstr = Module["_strstr"] = function() {
+ return (_strstr = Module["_strstr"] = Module["asm"]["strstr"]).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _emscripten_GetProcAddress = Module["_emscripten_GetProcAddress"] = function() {
+ return (_emscripten_GetProcAddress = Module["_emscripten_GetProcAddress"] = Module["asm"]["emscripten_GetProcAddress"]).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var ___errno_location = Module["___errno_location"] = function() {
+ return (___errno_location = Module["___errno_location"] = Module["asm"]["__errno_location"]).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var stackSave = Module["stackSave"] = function() {
+ return (stackSave = Module["stackSave"] = Module["asm"]["stackSave"]).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var stackRestore = Module["stackRestore"] = function() {
+ return (stackRestore = Module["stackRestore"] = Module["asm"]["stackRestore"]).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var stackAlloc = Module["stackAlloc"] = function() {
+ return (stackAlloc = Module["stackAlloc"] = Module["asm"]["stackAlloc"]).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var _emscripten_main_thread_process_queued_calls = Module["_emscripten_main_thread_process_queued_calls"] = function() {
+ return (_emscripten_main_thread_process_queued_calls = Module["_emscripten_main_thread_process_queued_calls"] = Module["asm"]["emscripten_main_thread_process_queued_calls"]).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var dynCall_jiji = Module["dynCall_jiji"] = function() {
+ return (dynCall_jiji = Module["dynCall_jiji"] = Module["asm"]["dynCall_jiji"]).apply(null, arguments);
+};
+
+/** @type {function(...*):?} */
+var __growWasmMemory = Module["__growWasmMemory"] = function() {
+ return (__growWasmMemory = Module["__growWasmMemory"] = Module["asm"]["__growWasmMemory"]).apply(null, arguments);
+};
+
+
+
+
+
+// === Auto-generated postamble setup entry stuff ===
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Module["addRunDependency"] = addRunDependency;
+Module["removeRunDependency"] = removeRunDependency;
+Module["FS_createFolder"] = FS.createFolder;
+Module["FS_createPath"] = FS.createPath;
+Module["FS_createDataFile"] = FS.createDataFile;
+Module["FS_createPreloadedFile"] = FS.createPreloadedFile;
+Module["FS_createLazyFile"] = FS.createLazyFile;
+Module["FS_createLink"] = FS.createLink;
+Module["FS_createDevice"] = FS.createDevice;
+Module["FS_unlink"] = FS.unlink;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+var calledRun;
+
+/**
+ * @constructor
+ * @this {ExitStatus}
+ */
+function ExitStatus(status) {
+ this.name = "ExitStatus";
+ this.message = "Program terminated with exit(" + status + ")";
+ this.status = status;
+}
+
+var calledMain = false;
+
+
+dependenciesFulfilled = function runCaller() {
+ // If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false)
+ if (!calledRun) run();
+ if (!calledRun) dependenciesFulfilled = runCaller; // try this again later, after new deps are fulfilled
+};
+
+function callMain(args) {
+
+ var entryFunction = Module['_main'];
+
+
+ var argc = 0;
+ var argv = 0;
+
+ try {
+
+
+ var ret = entryFunction(argc, argv);
+
+
+ // In PROXY_TO_PTHREAD builds, we should never exit the runtime below, as execution is asynchronously handed
+ // off to a pthread.
+ // if we're not running an evented main loop, it's time to exit
+ exit(ret, /* implicit = */ true);
+ }
+ catch(e) {
+ if (e instanceof ExitStatus) {
+ // exit() throws this once it's done to make sure execution
+ // has been stopped completely
+ return;
+ } else if (e == 'unwind') {
+ // running an evented main loop, don't immediately exit
+ noExitRuntime = true;
+ return;
+ } else {
+ var toLog = e;
+ if (e && typeof e === 'object' && e.stack) {
+ toLog = [e, e.stack];
+ }
+ err('exception thrown: ' + toLog);
+ quit_(1, e);
+ }
+ } finally {
+ calledMain = true;
+
+ }
+}
+
+
+
+
+/** @type {function(Array=)} */
+function run(args) {
+ args = args || arguments_;
+
+ if (runDependencies > 0) {
+ return;
+ }
+
+
+ preRun();
+
+ if (runDependencies > 0) return; // a preRun added a dependency, run will be called later
+
+ function doRun() {
+ // run may have just been called through dependencies being fulfilled just in this very frame,
+ // or while the async setStatus time below was happening
+ if (calledRun) return;
+ calledRun = true;
+ Module['calledRun'] = true;
+
+ if (ABORT) return;
+
+ initRuntime();
+
+ preMain();
+
+ if (Module['onRuntimeInitialized']) Module['onRuntimeInitialized']();
+
+ if (shouldRunNow) callMain(args);
+
+ postRun();
+ }
+
+ if (Module['setStatus']) {
+ Module['setStatus']('Running...');
+ setTimeout(function() {
+ setTimeout(function() {
+ Module['setStatus']('');
+ }, 1);
+ doRun();
+ }, 1);
+ } else
+ {
+ doRun();
+ }
+}
+Module['run'] = run;
+
+
+/** @param {boolean|number=} implicit */
+function exit(status, implicit) {
+
+ // if this is just main exit-ing implicitly, and the status is 0, then we
+ // don't need to do anything here and can just leave. if the status is
+ // non-zero, though, then we need to report it.
+ // (we may have warned about this earlier, if a situation justifies doing so)
+ if (implicit && noExitRuntime && status === 0) {
+ return;
+ }
+
+ if (noExitRuntime) {
+ } else {
+
+ EXITSTATUS = status;
+
+ exitRuntime();
+
+ if (Module['onExit']) Module['onExit'](status);
+
+ ABORT = true;
+ }
+
+ quit_(status, new ExitStatus(status));
+}
+
+if (Module['preInit']) {
+ if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']];
+ while (Module['preInit'].length > 0) {
+ Module['preInit'].pop()();
+ }
+}
+
+// shouldRunNow refers to calling main(), not run().
+var shouldRunNow = true;
+
+if (Module['noInitialRun']) shouldRunNow = false;
+
+
+ noExitRuntime = true;
+
+run();
+
+
+
+
+
+
+// {{MODULE_ADDITIONS}}
+
+
+
diff --git a/examples/web/models/models_first_person_maze.wasm b/examples/web/models/models_first_person_maze.wasm
index f4b9e84..a9d9703 100644
--- a/examples/web/models/models_first_person_maze.wasm
+++ b/examples/web/models/models_first_person_maze.wasm
Binary files differ
diff --git a/examples/web/models/models_first_person_maze.wasm.map b/examples/web/models/models_first_person_maze.wasm.map
new file mode 100644
index 0000000..fb9fb31
--- /dev/null
+++ b/examples/web/models/models_first_person_maze.wasm.map
@@ -0,0 +1 @@
+{"version":3,"sources":["models/models_first_person_maze.c"],"names":[],"mappings":"+yTA+CA,eAGI,YAGS,0EAEK,YACH,mDAHF,IAGE,cAHF,IAGE,SAHF,IAGE,SACiC,YAAhC,oCAAgC,gBAAhC,iDACJ,mDAGE,YARD,IAQC,WARD,IAQC,WARD,IAQC,WACqC,AATtC,YASsC,mBAGnC,oCAZH,IAYG,YACZ,6CAbS,4BAiBT,MAjBS,UAiBT,WAjBS,AAoBT,EApBS,gBAoCT,EApCS,WAoCT,EApCS,WAoCT,EApCS,WAoCT,SApCS,AAqCT,EArCS,UAqCT,EArCS,UAqCT,EArCS,UAqCT,SACA,sBAEA,GAGA,QA3CS,EA2CT,GAOJ,eAG+B,iCAKP,EALO,aAKP,EALO,wBAST,AAAkB,AATT,AASS,EATT,QASS,SAAlB,8BADgB,EAAhB,AAAkB,AART,AAQO,GARP,QAQS,SAAlB,uBARS,SAoB3B,SAEiC,MAAX,OAAlB,aAEyC,AAAL,AAFpC,OAEoC,AAAhB,KAAgB,UAAK,MAEtB,gBADV,gBACmC,AAAzB,EAAyB,AAAX,AAAd,OAAc,MAAW,QAA6B,AAAtD,EAAsD,AAAT,AAA7C,OAA6C,MAAS,OADhE,+CAIiB,AAJjB,IAIiB,uBAPW,oBAArC,UAFc,AAAoB,OAApB,OAiBlB,GAEoB,UAAhB,mBAEA,yBAEwC,QAApC,+EAGJ,GAEmC,KAL/B,AAKJ,EALI,UAKJ,EALI,UAK6B,YAAmB,AAAnB,EAAmB,AAAW,AAAX,EAAW,AAL3D,OAK2D,IAAX,QAA2C,QAA/F,OALI,AAKJ,EALI,UAKJ,uCACmB,KAAmF,WAAtG,UAAuD,AAAR,AAAQ,EAAR,AAN3C,OAM2C,MAAQ,KAAvD,EAA4F,AANxF,OAMwF,GAA5F,QAGc,KAAoF,WAAlG,UAA0C,AATtC,AAS8C,EAT9C,AAS8C,EAAkB,AAxCpE,gBAwCoE,GAThE,AA/BQ,EA+BR,KASsC,AATtC,OASsC,IATtC,AASmD,EAAiC,AArCxF,gBAqCwF,GATpF,AA5BQ,EA4BR,IASuE,IAA3E,eAIJ,GAEJ"} \ No newline at end of file