🧠 Description
This project demonstrates a full-featured browser game loader built using HTML and JavaScript, designed to run a WebAssembly (WASM) game inside an HTML5 canvas.
The page acts as a bridge between the browser and the compiled game engine, handling rendering, input, resizing, ads, and SDK communication.
The loader integrates Poki SDK, manages loading progress, initializes WebGL contexts, and ensures the game runs smoothly across different screen sizes.
It is commonly used in modern web-based games deployed on platforms like Poki, CrazyGames, or custom portals.
💻 HTML Structure
1<!DOCTYPE html>
2<html lang="en-us">
3
4<head>
5 <script src="https://deckard.openprocessing.org/user485717/visual2458132/hf42bec4b58ab09712c0f3bedb92cada1/index.wasm.js"></script>
6 <script src="https://deckard.openprocessing.org/user485717/visual2458132/hf42bec4b58ab09712c0f3bedb92cada1/index.data.js"></script>
7 <title>Drive Mad | @coding.stella</title>
8</head>
9
10<body id="body">
11 <style>
12 @font-face {
13 font-family: 'baloo 2';
14 font-style: normal;
15 font-weight: 800;
16 font-display: swap;
17 src: url(baloo2.woff) format('woff');
18 unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD
19 }
20
21 .fullscreen {
22 position: absolute;
23 width: 100%;
24 height: 100%
25 }
26
27 .center {
28 text-align: center
29 }
30
31 .centered {
32 margin-left: auto;
33 margin-right: auto;
34 display: block;
35 text-align: center
36 }
37
38 #play_overlay {
39 display: none;
40 z-index: 10
41 }
42
43 .middle {
44 position: absolute;
45 top: 50%;
46 left: 50%;
47 transform: translate(-50%, -50%)
48 }
49
50 .middle_vertical {
51 position: absolute;
52 top: 50%;
53 transform: translate(0%, -50%)
54 }
55
56 .edge {
57 margin-left: auto;
58 margin-right: auto;
59 width: 164px;
60 height: 180px;
61 background-color: #cfdaed;
62 box-shadow: 5px 1px 5px rgba(0, 0, 0, .25);
63 transform: rotate(-5deg)
64 }
65
66 .box {
67 width: 164px;
68 height: 164px;
69 background-color: #fff;
70 position: relative
71 }
72
73 .black {
74 width: 132px;
75 height: 156px;
76 background-color: #000;
77 position: absolute;
78 top: 4px;
79 right: 4px;
80 margin: 0 auto
81 }
82
83 .cover {
84 width: 128px;
85 height: 128px;
86 margin: 2px
87 }
88
89 .title {
90 font-size: 14px;
91 font-family: 'baloo 2', ubuntu, verdana, sans-serif
92 }
93
94 .author {
95 font-family: 'baloo 2', ubuntu, verdana, sans-serif;
96 border-spacing: 0;
97 font-size: 14px;
98 color: #ccc;
99 text-align: right;
100 white-space: nowrap;
101 overflow: hidden;
102 text-overflow: ellipsis;
103 position: absolute;
104 width: 150px;
105 top: 4px;
106 right: 142px;
107 transform-origin: right top;
108 transform: rotate(-90deg)
109 }
110
111 .loading {
112 margin-top: 20px;
113 margin-bottom: 10px
114 }
115
116 .description {
117 font-family: 'baloo 2', ubuntu, verdana, sans-serif;
118 display: inline-block;
119 font-size: 16px;
120 line-height: 1.2em;
121 width: 240px
122 }
123
124 .button {
125 display: inline-block;
126 border: 2px solid #00a2ff;
127 border-radius: 7px;
128 width: 133px;
129 height: 43px;
130 font-size: 16px;
131 line-height: 43px;
132 margin: 0 auto
133 }
134
135 .overlay_button {
136 display: inline-block;
137 border: 2px solid #000;
138 border-radius: 12px;
139 width: 200px;
140 height: 50px;
141 font-size: 18px;
142 line-height: 50px;
143 margin: 11px
144 }
145
146 #play_button {
147 color: #333;
148 background-color: #eee
149 }
150
151 .emscripten_border {
152 position: relative
153 }
154
155 #gradient {
156 background-image: linear-gradient(135deg, #70e1fd, #00a2ff);
157 position: absolute;
158 top: 0;
159 width: 100%;
160 height: 768px
161 }
162
163 * {
164 margin: 0;
165 padding: 0
166 }
167
168 p,
169 ul,
170 ol,
171 dl {
172 margin-bottom: 1em
173 }
174
175 h1,
176 h2,
177 h3,
178 h4,
179 h5,
180 h6,
181 p,
182 ul,
183 ol,
184 dl {
185 margin-left: 16px;
186 margin-right: 16px
187 }
188
189 img {
190 vertical-align: top
191 }
192
193 html,
194 body {
195 font-family: 'baloo 2', ubuntu, verdana, sans-serif;
196 font-size: 18px;
197 color: #bbb;
198 padding: 0;
199 width: 100%;
200 height: 100%;
201 margin: 0;
202 border: 0;
203 line-height: 1.8;
204 overflow: hidden;
205 display: block
206 }
207
208 canvas {
209 padding-right: 0;
210 margin-left: auto;
211 margin-right: auto;
212 display: block;
213 margin-top: auto;
214 margin-bottom: auto;
215 position: relative;
216 width: 1024px;
217 height: 768px
218 }
219
220 div.emscripten {
221 text-align: center
222 }
223
224 canvas.emscripten {
225 border: 0;
226 background-color: #000
227 }
228
229 #status {
230 display: inline-block;
231 width: 100%;
232 font-weight: 700;
233 color: #787878;
234 text-align: center
235 }
236
237 #modal_parent {
238 display: none;
239 position: fixed;
240 z-index: 1;
241 left: 0;
242 top: 0;
243 width: 100%;
244 height: 100%;
245 overflow: auto;
246 background-color: #000;
247 background-color: rgba(0, 0, 0, .4)
248 }
249
250 .modal_inner {
251 display: none
252 }
253
254 #play_content {
255 color: #fff;
256 z-index: 10
257 }
258
259 #modal_content {
260 position: relative;
261 background-color: #fefefe;
262 margin: auto;
263 padding: 20px;
264 border: 1px solid #888;
265 box-sizing: border-box
266 }
267
268 .error_message {
269 color: red
270 }
271
272 .error_text {
273 color: red;
274 font-family: sans-serif;
275 font-size: .8em
276 }
277
278 #modal_close_button {
279 color: #aaa;
280 position: absolute;
281 right: 15px;
282 top: 10px;
283 font-size: 28px;
284 line-height: 28px;
285 font-weight: 700;
286 transition: .2s
287 }
288
289 #modal_close_button:hover,
290 #modal_close_button:focus {
291 color: #000;
292 text-decoration: none;
293 cursor: pointer
294 }
295
296 a:link {
297 color: #00b9fe;
298 text-decoration: none;
299 transition: .2s
300 }
301
302 a:visited {
303 color: #00b9fe
304 }
305
306 a:hover,
307 a:active {
308 opacity: .5
309 }
310
311 .link_image_button {
312 margin-right: 10px
313 }
314
315 .playstore075 {
316 width: 153px;
317 height: 45px
318 }
319
320 .appstore075 {
321 width: 135px;
322 height: 45px
323 }
324
325 #progress_or_play {
326 margin-top: 10px
327 }
328
329 #terms_p {
330 font-family: sans-serif;
331 color: #141414;
332 font-size: .7em;
333 margin-bottom: 0
334 }
335
336 #terms_p a {
337 color: #f0f0f0
338 }
339
340 .deeplink_message {
341 font-size: 1em;
342 color: #f0f0f0;
343 line-height: 1.1em;
344 font-size: 20px
345 }
346
347 .menu {
348 color: #f0f0f0
349 }
350
351 .level_button {
352 border: 2px solid #222;
353 border-radius: 1em;
354 color: #f0f0f0;
355 background-color: #00a2ff;
356 line-height: 1em;
357 height: 2.5em;
358 width: 5em;
359 justify-self: center;
360 position: relative;
361 padding-top: .6em
362 }
363
364 .grid_element_center {
365 justify-self: center
366 }
367
368 .level_button_name {
369 font-size: .6em;
370 white-space: nowrap;
371 overflow: hidden;
372 text-overflow: ellipsis
373 }
374
375 .level_button_number {
376 font-size: 1.2em
377 }
378
379 .level_button:hover {
380 background-color: #00c2ff
381 }
382
383 .level_checkmark {
384 position: absolute;
385 right: 0;
386 top: 0;
387 margin: 0;
388 padding: 0;
389 text-align: right;
390 font-size: 1.2em;
391 line-height: 1.2em
392 }
393
394 .level_button a {
395 color: #f0f0f0;
396 opacity: 1
397 }
398
399 .menu_items {
400 display: grid;
401 grid-template-columns: repeat(3, 1fr);
402 gap: 10px;
403 margin-bottom: 20px
404 }
405
406 .menu_header {
407 font-size: 3em;
408 margin-top: 40px
409 }
410
411 #webview_content {
412 display: none;
413 background-color: transparent;
414 position: absolute;
415 top: 0;
416 width: 100%;
417 height: 768px
418 }
419
420 .webview {
421 width: 100%;
422 height: 100%;
423 background: 0 0;
424 margin: 0;
425 border: 0;
426 overflow: hidden
427 }
428 </style>
429
430 <div id="modal_parent">
431 <div id="modal_content">
432 <span id="modal_close_button">×</span>
433 <div id="store_link_modal_content" class="modal_inner"></div>
434 <div id="share_file_modal_content" class="modal_inner"></div>
435 </div>
436 </div>
437 <div id="canvas_border" class="emscripten_border">
438 <div id="play_content" class="middle center">
439 <div class="edge">
440 <div class="box">
441 <div class="black">
442 <img src="webapp/cover.jpg" class="cover" />
443 <p class="title">Drive Mad</p>
444 <p class="author">Martin Magni</p>
445 </div>
446 </div>
447 </div>
448 <div id="progress_or_play"><progress id="progress" class="loading" value="0" max="100"></progress></div>
449 <p class="description"></p>
450 </div>
451 <canvas class="emscripten" id="canvas" tabindex="-1"></canvas>
452 <div id="gradient"></div>
453 <div id="webview_content"></div>
454 </div>
455 <script type="text/javascript">
456 var pokiDebug = false;
457 var postRunDone = false;
458 var theDomLoaded = false;
459 var pokiInited = false;
460 var gameReadyToStart = false;
461 var requestedCanvas = false;
462 var adblocker = false;
463 var gameStarted = false;
464 var updatedScreenSize = false;
465 var startupTimeStr = "";
466 var loadProgressFrac = 0;
467 var fakeProgressPercentStart = 80 + Math.random() * 15;
468 window.addEventListener('DOMContentLoaded', domContentLoaded);
469 window.addEventListener('load', function() {
470 console.log("Load event received");
471 if (inIframe()) {
472 document.addEventListener('click', ev => {
473 let canvas = document.getElementById('canvas');
474 if (canvas) {
475 canvas.focus();
476 }
477 });
478 }
479 });
480
481 function inIframe() {
482 try {
483 return window.self !== window.top;
484 } catch (e) {
485 return true;
486 }
487 }
488
489 function updateLoadProgress() {
490 let progressElement = document.getElementById('progress');
491 if (progressElement) {
492 progressElement.value = Math.round(loadProgressFrac * fakeProgressPercentStart);
493 progressElement.max = 100;
494 }
495 if (loadProgressFrac >= 1) {
496 console.log("Loading done");
497 tryStartGame();
498 }
499 }
500
501 function domContentLoaded() {
502 initPokiSdk();
503 console.log("DOM content loaded event received");
504 let canvas = document.getElementById('canvas');
505 canvas.addEventListener("contextmenu", stopContextMenu);
506 if (!postRunDone) {
507 resizeCanvas(false);
508 }
509 window.addEventListener('blur', ev => setGameFocus(true));
510 window.addEventListener('focus', ev => setGameFocus(false));
511 canvas.onpointerdown = beginPointerDrag;
512 canvas.onpointerup = endPointerDrag;
513 theDomLoaded = true;
514 }
515
516 function beginPointerDrag(e) {
517 let canvas = document.getElementById('canvas');
518 canvas.setPointerCapture(e.pointerId);
519 }
520
521 function endPointerDrag(e) {
522 let canvas = document.getElementById('canvas');
523 canvas.releasePointerCapture(e.pointerId);
524 }
525
526 function setGameFocus(f) {
527 if (postRunDone) {
528 Module.ccall('set_game_focus', 'v', ['number'], [f]);
529 }
530 }
531
532 function canBeGameGuid(str) {
533 return str && str.match('([A-F]|[0-9]){16}');
534 }
535
536 function getMeta(metaName) {
537 const metas = document.getElementsByTagName('meta');
538 for (let i = 0; i < metas.length; i++) {
539 if (metas[i].getAttribute('name') === metaName) {
540 return metas[i].getAttribute('content');
541 }
542 }
543 return '';
544 }
545
546 function getCSSRgb(color) {
547 return `rgb(${Math.round(color[0])}, ${Math.round(color[1])}, ${Math.round(color[2])})`;
548 }
549 let lastGradientStyleStr = "";
550 let lastDeepLinkLoadFraction = 0;
551
552 function getGradientStr(frac) {
553 let fromColor = [frac * 0x70, frac * 0xe1, frac * 0xfd];
554 let toColor = [frac * 0x00, frac * 0xa2, frac * 0xff];
555 let str = `linear-gradient(135deg, ${getCSSRgb(fromColor)}, ${getCSSRgb(toColor)})`
556 return str;
557 }
558
559 function hideOverlayGradient() {
560 var gradient = document.getElementById('gradient');
561 gradient.style.display = "none";
562 }
563 var showedStartGameError = false;
564
565 function setPokiInited() {
566 pokiInited = true;
567 }
568
569 function initPokiSdk() {
570 setPokiInited();
571 }
572
573 function hideOverlay() {
574 var playContent = document.getElementById('play_content');
575 playContent.style.display = "none";
576 hideOverlayGradient();
577 }
578
579 function startGame() {
580 try {
581 console.log("Registering event listeners");
582 window.addEventListener("beforeunload", function(event) {
583 Module.ccall('app_terminate_if_necessary', 'v');
584 });
585 window.addEventListener("unload", function(event) {
586 Module.ccall('app_terminate_if_necessary', 'v');
587 });
588 document.addEventListener("visibilitychange", function() {
589 if (document.visibilityState === 'visible') {
590 Module.ccall('app_resume', 'v');
591 } else {
592 Module.ccall('app_pause', 'v');
593 }
594 });
595 console.log("Confirming accept in app");
596 try {
597 Module.ccall('user_accepted_and_clicked', 'v');
598 Module.ccall('set_is_mobile', 'v', ['number'], [matchMedia('(pointer:coarse)').matches]);
599 } catch (err4) {}
600 gameStarted = true;
601 if (!updatedScreenSize) {
602 resizeCanvas(true);
603 }
604 } catch (err) {
605 if (!showedStartGameError) {
606 let foundModuleAsm = false;
607 let additionalInfo = "";
608 try {
609 if (Module["asm"]) {
610 foundModuleAsm = true;
611 }
612 } catch (err2) {}
613 if (!foundModuleAsm) {
614 additionalInfo += "Could not find Module.asm";
615 }
616 console.log(`Error when starting game. Try to reload the page. Error message: ${err}. ${additionalInfo}`);
617 showedStartGameError = true;
618 }
619 }
620 }
621 var pokiStopped = true;
622
623 function pokiEnsureStop() {
624 if (!pokiStopped) {
625 pokiStopped = true;
626 }
627 }
628
629 function pokiEnsureStart() {
630 if (pokiStopped) {
631 pokiStopped = false;
632 }
633 }
634 var startGameAttempts = 0;
635 var tryStartGameTimeout = null;
636
637 function tryStartGame() {
638 console.log("tryStartGame()", gameReadyToStart);
639 if (gameReadyToStart) {
640 return;
641 }
642 if (!postRunDone || !theDomLoaded || !pokiInited) {
643 startGameAttempts++;
644 if (startGameAttempts == 20) {
645 return;
646 }
647 if (tryStartGameTimeout != null) {
648 clearTimeout(tryStartGameTimeout);
649 }
650 tryStartGameTimeout = setTimeout(tryStartGame, startGameAttempts * 100);
651 console.log("Not ready to start game yet...");
652 return;
653 }
654 gameReadyToStart = true;
655 console.log("Starting game");
656 startGame();
657 }
658
659 function simpleLogC(str) {
660 if (postRunDone) {
661 Module.ccall('log_simple', 'v', ['string'], [str]);
662 } else {
663 console.log(str);
664 }
665 }
666
667 function appErrorC(code, str) {
668 if (postRunDone) {
669 Module.ccall('app_error', 'v', ['number', 'string'], [code, str]);
670 } else {
671 console.error(str, code);
672 }
673 }
674
675 function simpleAppErrorC(str) {
676 appErrorC(1, str);
677 }
678
679 function parseUrlArgument(name) {
680 let result = "";
681 let str = window.location.search;
682 if (str.length > 0 && str[0] == '?') {
683 var arr = str.substr(1).split('&');
684 for (let i = 0; i < arr.length; i++) {
685 if (arr[i].startsWith(name + "=")) {
686 result = arr[i].substr(name.length + 1);
687 break;
688 }
689 }
690 }
691 return result;
692 }
693
694 function parseUrlArgumentInt(name) {
695 let str = parseUrlArgument(name);
696 let parsed = parseInt(str);
697 if (isNaN(parsed)) {
698 return 0;
699 } else {
700 return parsed;
701 }
702 }
703
704 function resizeCanvas(informC) {
705 let iw = window.innerWidth;
706 let ih = window.innerHeight;
707 let canvas = document.getElementById('canvas');
708 let border = document.getElementById('canvas_border');
709 canvas.width = iw * window.devicePixelRatio;
710 canvas.height = ih * window.devicePixelRatio;
711 border.style.marginTop = '0px';
712 let gradient = document.getElementById("gradient");
713 let webViewContent = document.getElementById("webview_content");
714 [gradient, webViewContent].forEach(e => {
715 if (e) {
716 e.style.left = '0px';
717 }
718 });
719 [canvas, gradient, webViewContent].forEach(e => {
720 if (e) {
721 e.style.width = iw + 'px';
722 e.style.height = ih + 'px';
723 e.style.borderRadius = '0px';
724 }
725 });
726 if (informC && gameStarted && requestedCanvas) {
727 Module.ccall("update_screen_size", "v", ["number", "number", "number"], [canvas.width, canvas.height, window.devicePixelRatio]);
728 updatedScreenSize = true;
729 }
730 }
731
732 function stopContextMenu(event) {
733 event.preventDefault();
734 return false;
735 }
736 var Module = {
737 locateFile: function(path, prefix) {
738 if (prefix == "") {
739 return "" + path;
740 }
741 return prefix + path;
742 },
743 preRun: [function() {
744 console.log("preRun() called");
745 }],
746 postRun: [function() {
747 console.log("postRun() called");
748 document.onfullscreenchange = function() {
749 setTimeout(function() {
750 resizeCanvas(true);
751 if (document.fullscreenElement && gameStarted && requestedCanvas) {
752 let canvas = document.getElementById('canvas');
753 Module.ccall("update_screen_size", "v", ["number", "number", "number"], [canvas.width, canvas.height, 1]);
754 }
755 }, 500);
756 };
757 window.addEventListener('resize', (event) => resizeCanvas(true), false);
758 if (theDomLoaded) {
759 resizeCanvas(true);
760 }
761 console.log("Registering keydown listener");
762 window.addEventListener('keydown', e => {
763 ccall("keydown_browser", "v", ["string"], [e.key]);
764 });
765 postRunDone = true;
766 }],
767 print: (function() {
768 return function(text) {
769 if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
770 console.log(text);
771 };
772 })(),
773 printErr: function(text) {
774 if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
775 console.error(text);
776 },
777 canvas: (function() {
778 var canvas = document.getElementById('canvas');
779 canvas.addEventListener("webglcontextlost", function(e) {
780 alert('WebGL context lost. You will need to reload the page.');
781 e.preventDefault();
782 }, false);
783 requestedCanvas = true;
784 return canvas;
785 })(),
786 setStatus: function(text) {
787 if (!Module.setStatus.last) Module.setStatus.last = {
788 time: Date.now(),
789 text: ''
790 };
791 if (text === Module.setStatus.last.text) return;
792 var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
793 var now = Date.now();
794 if (m && now - Module.setStatus.last.time < 30) return;
795 Module.setStatus.last.time = now;
796 Module.setStatus.last.text = text;
797 if (m) {
798 text = m[1];
799 loadProgressFrac = parseInt(m[2]) / parseInt(m[4]);
800 } else {
801 loadProgressFrac = 1;
802 }
803 updateLoadProgress();
804 },
805 totalDependencies: 0,
806 monitorRunDependencies: function(left) {
807 this.totalDependencies = Math.max(this.totalDependencies, left);
808 }
809 };
810 var notifications = [];
811 var webViewIframe = null;
812 var storedScripts = [];
813 var webviewDomLoaded = false;
814 async function isUrlFound(url) {
815 try {
816 const response = await fetch(url, {
817 method: 'HEAD',
818 cache: 'no-cache'
819 });
820 return response.status === 200;
821 } catch (error) {
822 return false;
823 }
824 }
825
826 function checkHintFileExist(src, li) {
827 isUrlFound(src).then(found => {
828 if (found) {
829 Module.ccall("hint_file_exists", "v", ["number"], [li]);
830 }
831 });
832 }
833
834 function postStored() {
835 for (var i = 0; i < storedScripts.length; i++) {
836 webViewIframe.contentWindow.postMessage("eval:" + storedScripts[i], '*');
837 }
838 storedScripts = [];
839 }
840
841 function onWebviewDomContentLoaded() {
842 webviewDomLoaded = true;
843 postStored();
844 }
845
846 function webViewPostMessage(message) {
847 Module.ccall("app_webview_message", "v", ["string"], [message]);
848 }
849
850 function webViewError(type, message) {
851 webViewPostMessage(`error|${type}|${message}`);
852 }
853
854 function webViewClose() {
855 try {
856 var content = document.getElementById("webview_content");
857 content.style.display = 'none';
858 if (content.contains(webViewIframe)) {
859 webviewDomLoaded = false;
860 webViewIframe.contentWindow.removeEventListener('DOMContentLoaded', onWebviewDomContentLoaded);
861 content.removeChild(webViewIframe);
862 }
863 setTimeout(function() {
864 Module.ccall("set_game_focus", "v", ["number"], [true])
865 }, 100);
866 } catch (err) {
867 webViewError("unknown", err);
868 }
869 }
870
871 function webViewOpen(path) {
872 try {
873 let arr = readLocalFile(path);
874 let html = new TextDecoder("utf-8").decode(arr);
875 if (webViewIframe == null) {
876 window.onmessage = function(e) {
877 webViewPostMessage(e.data);
878 }
879 }
880 html = html.replace("common.js", `webapp/view_common.js`);
881 html = html.replace("common.css", `webapp/view_common.css`);
882 var content = document.getElementById("webview_content");
883 content.style.display = 'block';
884 webViewIframe = document.createElement('iframe');
885 webViewIframe.classList.add('webview');
886 webViewIframe.allowtransparency = true;
887 content.appendChild(webViewIframe);
888 webViewIframe.contentWindow.document.open();
889 webviewDomLoaded = false;
890 webViewIframe.contentWindow.addEventListener('DOMContentLoaded', onWebviewDomContentLoaded);
891 webViewIframe.contentWindow.document.write(html);
892 webViewIframe.contentWindow.document.close();
893 } catch (err) {
894 webViewError("unknown", err);
895 }
896 }
897
898 function webViewExecuteJS(jsString) {
899 try {
900 if (!webviewDomLoaded) {
901 storedScripts.push(jsString);
902 } else {
903 webViewIframe.contentWindow.postMessage("eval:" + jsString, '*');
904 }
905 } catch (err) {
906 webViewError("unknown", err);
907 }
908 }
909
910 function getHostname() {
911 let hostname = window.location.hostname.split(':')[0];
912 let lengthBytes = lengthBytesUTF8(hostname) + 1;
913 let stringOnWasmHeap = _malloc(lengthBytes);
914 stringToUTF8(hostname, stringOnWasmHeap, lengthBytes);
915 return stringOnWasmHeap;
916 }
917
918 function parseUrlArgumentString(name) {
919 let str = parseUrlArgument(name);
920 let lengthBytes = lengthBytesUTF8(str) + 1;
921 let stringOnWasmHeap = _malloc(lengthBytes);
922 stringToUTF8(str, stringOnWasmHeap, lengthBytes);
923 return stringOnWasmHeap;
924 }
925
926 function writeLocalFile(buffer, pathDevice) {
927 let arr = new Uint8Array(buffer);
928 let stream = FS.open(pathDevice, 'w');
929 FS.write(stream, arr, 0, arr.length, 0);
930 FS.close(stream);
931 }
932
933 function readLocalFile(path) {
934 let stream = FS.open(path, 'r');
935 FS.llseek(stream, 0, 2);
936 let fileSize = stream.position;
937 FS.llseek(stream, 0, 0);
938 let buf = new Uint8Array(fileSize);
939 FS.read(stream, buf, 0, fileSize, 0);
940 FS.close(stream);
941 return buf;
942 }
943
944 function resizeModal(modal, modalContent, maxWidth) {
945 let iw = window.innerWidth;
946 let ih = window.innerHeight;
947 let top = Math.min(0.15 * ih, 100);
948 let w = Math.min(iw, maxWidth);
949 modal.style.display = "block";
950 modalContent.style.width = w + "px";
951 modal.style.paddingTop = top + "px";
952 return w;
953 }
954
955 function fetchUrl(url, id, useToken) {}
956
957 function adInit() {
958 setTimeout(() => Module.ccall("ad_on_inited", "v"), 100);
959 }
960
961 function firebasePause() {}
962
963 function firebaseResume() {}
964
965 function adInterstitialLoad() {
966 setTimeout(() => Module.ccall("ad_interstitial_on_loaded", "v", ["number"], [1]), 100);
967 }
968
969 function adInterstitialShow() {
970 Module.ccall("ad_interstitial_on_showed", "v", ["number"], [1]);
971 }
972
973 function adRewardedLoad() {
974 setTimeout(() => Module.ccall("ad_rewarded_on_loaded", "v", ["number"], [1]), 100);
975 }
976
977 function adRewardedShow() {
978 pokiEnsureStop();
979 Module.ccall("ad_rewarded_on_reward", "v");
980 Module.ccall("ad_rewarded_on_showed", "v", ["number"], [true]);
981 }
982
983 function firebaseDeinit() {}
984
985 function currentTimeSecondsRound() {
986 return Math.round(Date.now() / 1000);
987 }
988 </script>
989 <script type="text/javascript">
990 var Module = typeof Module != "undefined" ? Module : {};
991 if (!Module.expectedDataFileDownloads) {
992 Module.expectedDataFileDownloads = 0
993 }
994 Module.expectedDataFileDownloads++;
995 (function() {
996 if (Module["ENVIRONMENT_IS_PTHREAD"]) return;
997 var loadPackage = function(metadata) {
998 var PACKAGE_PATH = "";
999 if (typeof window === "object") {
1000 PACKAGE_PATH = window["encodeURIComponent"](window.location.pathname.toString().substring(0, window.location.pathname.toString().lastIndexOf("/")) + "/")
1001 } else if (typeof process === "undefined" && typeof location !== "undefined") {
1002 PACKAGE_PATH = encodeURIComponent(location.pathname.toString().substring(0, location.pathname.toString().lastIndexOf("/")) + "/")
1003 }
1004 var PACKAGE_NAME = "index.data";
1005 var REMOTE_PACKAGE_BASE = "index.data";
1006 if (typeof Module["locateFilePackage"] === "function" && !Module["locateFile"]) {
1007 Module["locateFile"] = Module["locateFilePackage"];
1008 err("warning: you defined Module.locateFilePackage, that has been renamed to Module.locateFile (using your locateFilePackage for now)")
1009 }
1010 var REMOTE_PACKAGE_NAME = Module["locateFile"] ? Module["locateFile"](REMOTE_PACKAGE_BASE, "") : REMOTE_PACKAGE_BASE;
1011 var REMOTE_PACKAGE_SIZE = metadata["remote_package_size"];
1012
1013 function fetchRemotePackage(packageName, packageSize, callback, errback) {
1014 if (typeof process === "object" && typeof process.versions === "object" && typeof process.versions.node === "string") {
1015 require("fs").readFile(packageName, function(err, contents) {
1016 if (err) {
1017 errback(err)
1018 } else {
1019 callback(contents.buffer)
1020 }
1021 });
1022 return
1023 }
1024 var xhr = new XMLHttpRequest;
1025 xhr.open("GET", window["index.data"], true);
1026 xhr.responseType = "arraybuffer";
1027 xhr.onprogress = function(event) {
1028 var url = packageName;
1029 var size = packageSize;
1030 if (event.total) size = event.total;
1031 if (event.loaded) {
1032 if (!xhr.addedTotal) {
1033 xhr.addedTotal = true;
1034 if (!Module.dataFileDownloads) Module.dataFileDownloads = {};
1035 Module.dataFileDownloads[url] = {
1036 loaded: event.loaded,
1037 total: size
1038 }
1039 } else {
1040 Module.dataFileDownloads[url].loaded = event.loaded
1041 }
1042 var total = 0;
1043 var loaded = 0;
1044 var num = 0;
1045 for (var download in Module.dataFileDownloads) {
1046 var data = Module.dataFileDownloads[download];
1047 total += data.total;
1048 loaded += data.loaded;
1049 num++
1050 }
1051 total = Math.ceil(total * Module.expectedDataFileDownloads / num);
1052 if (Module["setStatus"]) Module["setStatus"]("Downloading data... (" + loaded + "/" + total + ")")
1053 } else if (!Module.dataFileDownloads) {
1054 if (Module["setStatus"]) Module["setStatus"]("Downloading data...")
1055 }
1056 };
1057 xhr.onerror = function(event) {
1058 throw new Error("NetworkError for: " + packageName)
1059 };
1060 xhr.onload = function(event) {
1061 if (xhr.status == 200 || xhr.status == 304 || xhr.status == 206 || xhr.status == 0 && xhr.response) {
1062 var packageData = xhr.response;
1063 callback(packageData)
1064 } else {
1065 throw new Error(xhr.statusText + " : " + xhr.responseURL)
1066 }
1067 };
1068 xhr.send(null)
1069 }
1070
1071 function handleError(error) {
1072 console.error("package error:", error)
1073 }
1074 var fetchedCallback = null;
1075 var fetched = Module["getPreloadedPackage"] ? Module["getPreloadedPackage"](REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE) : null;
1076 if (!fetched) fetchRemotePackage(REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE, function(data) {
1077 if (fetchedCallback) {
1078 fetchedCallback(data);
1079 fetchedCallback = null
1080 } else {
1081 fetched = data
1082 }
1083 }, handleError);
1084
1085 function runWithFS() {
1086 function assert(check, msg) {
1087 if (!check) throw msg + (new Error).stack
1088 }
1089 Module["FS_createPath"]("/", "assets", true, true);
1090 Module["FS_createPath"]("/assets", "blocks", true, true);
1091 Module["FS_createPath"]("/assets", "views", true, true);
1092 Module["FS_createPath"]("/assets", "games", true, true);
1093 Module["FS_createPath"]("/assets", "sounds", true, true);
1094
1095 function DataRequest(start, end, audio) {
1096 this.start = start;
1097 this.end = end;
1098 this.audio = audio
1099 }
1100 DataRequest.prototype = {
1101 requests: {},
1102 open: function(mode, name) {
1103 this.name = name;
1104 this.requests[name] = this;
1105 Module["addRunDependency"]("fp " + this.name)
1106 },
1107 send: function() {},
1108 onload: function() {
1109 var byteArray = this.byteArray.subarray(this.start, this.end);
1110 this.finish(byteArray)
1111 },
1112 finish: function(byteArray) {
1113 var that = this;
1114 Module["FS_createDataFile"](this.name, null, byteArray, true, true, true);
1115 Module["removeRunDependency"]("fp " + that.name);
1116 this.requests[this.name] = null
1117 }
1118 };
1119 var files = metadata["files"];
1120 for (var i = 0; i < files.length; ++i) {
1121 new DataRequest(files[i]["start"], files[i]["end"], files[i]["audio"] || 0).open("GET", files[i]["filename"])
1122 }
1123
1124 function processPackageData(arrayBuffer) {
1125 assert(arrayBuffer, "Loading data file failed.");
1126 assert(arrayBuffer instanceof ArrayBuffer, "bad input to processPackageData");
1127 var byteArray = new Uint8Array(arrayBuffer);
1128 DataRequest.prototype.byteArray = byteArray;
1129 var files = metadata["files"];
1130 for (var i = 0; i < files.length; ++i) {
1131 DataRequest.prototype.requests[files[i].filename].onload()
1132 }
1133 Module["removeRunDependency"]("datafile_index.data")
1134 }
1135 Module["addRunDependency"]("datafile_index.data");
1136 if (!Module.preloadResults) Module.preloadResults = {};
1137 Module.preloadResults[PACKAGE_NAME] = {
1138 fromCache: false
1139 };
1140 if (fetched) {
1141 processPackageData(fetched);
1142 fetched = null
1143 } else {
1144 fetchedCallback = processPackageData
1145 }
1146 }
1147 if (Module["calledRun"]) {
1148 runWithFS()
1149 } else {
1150 if (!Module["preRun"]) Module["preRun"] = [];
1151 Module["preRun"].push(runWithFS)
1152 }
1153 };
1154 loadPackage({
1155 "files": [{
1156 "filename": "/assets/blocks/ACCELEROMETER_V",
1157 "start": 0,
1158 "end": 313
1159 }, {
1160 "filename": "/assets/blocks/ARCH",
1161 "start": 313,
1162 "end": 490
1163 }, {
1164 "filename": "/assets/blocks/BALL",
1165 "start": 490,
1166 "end": 635
1167 }, {
1168 "filename": "/assets/blocks/BOX",
1169 "start": 635,
1170 "end": 850
1171 }, {
1172 "filename": "/assets/blocks/BRICKS",
1173 "start": 850,
1174 "end": 1033
1175 }, {
1176 "filename": "/assets/blocks/BUTTERFLY",
1177 "start": 1033,
1178 "end": 2330
1179 }, {
1180 "filename": "/assets/blocks/BUTTON",
1181 "start": 2330,
1182 "end": 2853
1183 }, {
1184 "filename": "/assets/blocks/BUTTON_B",
1185 "start": 2853,
1186 "end": 3738
1187 }, {
1188 "filename": "/assets/blocks/CAMERA_ORBIT",
1189 "start": 3738,
1190 "end": 5126
1191 }, {
1192 "filename": "/assets/blocks/COMMENT",
1193 "start": 5126,
1194 "end": 5240
1195 }, {
1196 "filename": "/assets/blocks/CpF_LIST_ELEMENT_Cp",
1197 "start": 5240,
1198 "end": 5606
1199 }, {
1200 "filename": "/assets/blocks/DASH_CAT",
1201 "start": 5606,
1202 "end": 7471
1203 }, {
1204 "filename": "/assets/blocks/DINO",
1205 "start": 7471,
1206 "end": 12090
1207 }, {
1208 "filename": "/assets/blocks/DINO_RED",
1209 "start": 12090,
1210 "end": 13825
1211 }, {
1212 "filename": "/assets/blocks/DIRT",
1213 "start": 13825,
1214 "end": 13918
1215 }, {
1216 "filename": "/assets/blocks/DIRT_B",
1217 "start": 13918,
1218 "end": 14097
1219 }, {
1220 "filename": "/assets/blocks/DIRT_SLAB",
1221 "start": 14097,
1222 "end": 14219
1223 }, {
1224 "filename": "/assets/blocks/ECpC_SET_VAR_E",
1225 "start": 14219,
1226 "end": 14596
1227 }, {
1228 "filename": "/assets/blocks/ECVV_SET_ANG_LIMITS_E",
1229 "start": 14596,
1230 "end": 15053
1231 }, {
1232 "filename": "/assets/blocks/ECVV_SET_ANG_MOTOR_E",
1233 "start": 15053,
1234 "end": 15508
1235 }, {
1236 "filename": "/assets/blocks/ECVV_SET_ANG_SPRING_E",
1237 "start": 15508,
1238 "end": 15963
1239 }, {
1240 "filename": "/assets/blocks/ECVV_SET_LIN_LIMITS_E",
1241 "start": 15963,
1242 "end": 16418
1243 }, {
1244 "filename": "/assets/blocks/ECVV_SET_LIN_MOTOR_E",
1245 "start": 16418,
1246 "end": 16874
1247 }, {
1248 "filename": "/assets/blocks/ECVV_SET_LIN_SPRING_E",
1249 "start": 16874,
1250 "end": 17324
1251 }, {
1252 "filename": "/assets/blocks/EC_SET_VAR_E",
1253 "start": 17324,
1254 "end": 17579
1255 }, {
1256 "filename": "/assets/blocks/EFFF_VOLUME_PITCH_E",
1257 "start": 17579,
1258 "end": 18022
1259 }, {
1260 "filename": "/assets/blocks/EFF_LOOP_EFE",
1261 "start": 18022,
1262 "end": 18392
1263 }, {
1264 "filename": "/assets/blocks/EFF_SET_SCORE_E",
1265 "start": 18392,
1266 "end": 18776
1267 }, {
1268 "filename": "/assets/blocks/EFF_SFX_PLAY_FE",
1269 "start": 18776,
1270 "end": 19158
1271 }, {
1272 "filename": "/assets/blocks/EFpF_SET_VAR_E",
1273 "start": 19158,
1274 "end": 19532
1275 }, {
1276 "filename": "/assets/blocks/EFpO_MENU_ITEM_E",
1277 "start": 19532,
1278 "end": 19904
1279 }, {
1280 "filename": "/assets/blocks/EFp_DEC_VAR_E",
1281 "start": 19904,
1282 "end": 20170
1283 }, {
1284 "filename": "/assets/blocks/EFp_INC_VAR_E",
1285 "start": 20170,
1286 "end": 20442
1287 }, {
1288 "filename": "/assets/blocks/EF_INSPECT_E",
1289 "start": 20442,
1290 "end": 20791
1291 }, {
1292 "filename": "/assets/blocks/EF_RANDOM_SEED_E",
1293 "start": 20791,
1294 "end": 21179
1295 }, {
1296 "filename": "/assets/blocks/EF_SET_VAR_E",
1297 "start": 21179,
1298 "end": 21430
1299 }, {
1300 "filename": "/assets/blocks/EF_SFX_STOP_E",
1301 "start": 21430,
1302 "end": 21806
1303 }, {
1304 "filename": "/assets/blocks/EOF_SET_BOUNCE_E",
1305 "start": 21806,
1306 "end": 22198
1307 }, {
1308 "filename": "/assets/blocks/EOF_SET_FRICTION_E",
1309 "start": 22198,
1310 "end": 22594
1311 }, {
1312 "filename": "/assets/blocks/EOF_SET_MASS_E",
1313 "start": 22594,
1314 "end": 22977
1315 }, {
1316 "filename": "/assets/blocks/EOOV_ADD_CONSTRAINT_EC",
1317 "start": 22977,
1318 "end": 23428
1319 }, {
1320 "filename": "/assets/blocks/EOpO_SET_VAR_E",
1321 "start": 23428,
1322 "end": 23802
1323 }, {
1324 "filename": "/assets/blocks/EOT_SET_VISIBLE_E",
1325 "start": 23802,
1326 "end": 24180
1327 }, {
1328 "filename": "/assets/blocks/EOVQ_SET_POS_E",
1329 "start": 24180,
1330 "end": 24642
1331 }, {
1332 "filename": "/assets/blocks/EOVVV_ADD_FORCE_E",
1333 "start": 24642,
1334 "end": 25155
1335 }, {
1336 "filename": "/assets/blocks/EOVV_SET_LOCKED_E",
1337 "start": 25155,
1338 "end": 25617
1339 }, {
1340 "filename": "/assets/blocks/EOVV_SET_VEL_E",
1341 "start": 25617,
1342 "end": 26075
1343 }, {
1344 "filename": "/assets/blocks/EO_COLLISION_EOFVE",
1345 "start": 26075,
1346 "end": 26596
1347 }, {
1348 "filename": "/assets/blocks/EO_CREATE_EO",
1349 "start": 26596,
1350 "end": 26972
1351 }, {
1352 "filename": "/assets/blocks/EO_DESTROY_E",
1353 "start": 26972,
1354 "end": 27349
1355 }, {
1356 "filename": "/assets/blocks/EO_INSPECT_E",
1357 "start": 27349,
1358 "end": 27697
1359 }, {
1360 "filename": "/assets/blocks/EO_SET_VAR_E",
1361 "start": 27697,
1362 "end": 27948
1363 }, {
1364 "filename": "/assets/blocks/EQpQ_SET_VAR_E",
1365 "start": 27948,
1366 "end": 28324
1367 }, {
1368 "filename": "/assets/blocks/EQ_INSPECT_E",
1369 "start": 28324,
1370 "end": 28675
1371 }, {
1372 "filename": "/assets/blocks/EQ_SET_VAR_E",
1373 "start": 28675,
1374 "end": 28928
1375 }, {
1376 "filename": "/assets/blocks/ETpT_SET_VAR_E",
1377 "start": 28928,
1378 "end": 29302
1379 }, {
1380 "filename": "/assets/blocks/ET_IF_EEE",
1381 "start": 29302,
1382 "end": 29666
1383 }, {
1384 "filename": "/assets/blocks/ET_INSPECT_E",
1385 "start": 29666,
1386 "end": 30015
1387 }, {
1388 "filename": "/assets/blocks/ET_SET_VAR_E",
1389 "start": 30015,
1390 "end": 30265
1391 }, {
1392 "filename": "/assets/blocks/EVpV_SET_VAR_E",
1393 "start": 30265,
1394 "end": 30640
1395 }, {
1396 "filename": "/assets/blocks/EVQF_SET_CAM_E",
1397 "start": 30640,
1398 "end": 31090
1399 }, {
1400 "filename": "/assets/blocks/EVQ_SET_LIT_E",
1401 "start": 31090,
1402 "end": 31487
1403 }, {
1404 "filename": "/assets/blocks/EV_INSPECT_E",
1405 "start": 31487,
1406 "end": 31835
1407 }, {
1408 "filename": "/assets/blocks/EV_SET_GRAVITY_E",
1409 "start": 31835,
1410 "end": 32214
1411 }, {
1412 "filename": "/assets/blocks/EV_SET_VAR_E",
1413 "start": 32214,
1414 "end": 32466
1415 }, {
1416 "filename": "/assets/blocks/E_BUT_SENSOR_EE",
1417 "start": 32466,
1418 "end": 32836
1419 }, {
1420 "filename": "/assets/blocks/E_JOY_SENSOR_VE",
1421 "start": 32836,
1422 "end": 33198
1423 }, {
1424 "filename": "/assets/blocks/E_LATE_UPDATE_EE",
1425 "start": 33198,
1426 "end": 33563
1427 }, {
1428 "filename": "/assets/blocks/E_LOSE_E",
1429 "start": 33563,
1430 "end": 33936
1431 }, {
1432 "filename": "/assets/blocks/E_PLAY_EE",
1433 "start": 33936,
1434 "end": 34298
1435 }, {
1436 "filename": "/assets/blocks/E_SCREENSHOT_EE",
1437 "start": 34298,
1438 "end": 34687
1439 }, {
1440 "filename": "/assets/blocks/E_SWIPE_EVE",
1441 "start": 34687,
1442 "end": 35059
1443 }, {
1444 "filename": "/assets/blocks/E_TOUCH_EFFE",
1445 "start": 35059,
1446 "end": 35494
1447 }, {
1448 "filename": "/assets/blocks/E_WIN_E",
1449 "start": 35494,
1450 "end": 35871
1451 }, {
1452 "filename": "/assets/blocks/FALSE_T",
1453 "start": 35871,
1454 "end": 36118
1455 }, {
1456 "filename": "/assets/blocks/FFF_EULER_Q",
1457 "start": 36118,
1458 "end": 36507
1459 }, {
1460 "filename": "/assets/blocks/FFF_JOIN_V",
1461 "start": 36507,
1462 "end": 36894
1463 }, {
1464 "filename": "/assets/blocks/FF_ADD_F",
1465 "start": 36894,
1466 "end": 37193
1467 }, {
1468 "filename": "/assets/blocks/FF_DIV_F",
1469 "start": 37193,
1470 "end": 37487
1471 }, {
1472 "filename": "/assets/blocks/FF_EQL_T",
1473 "start": 37487,
1474 "end": 37788
1475 }, {
1476 "filename": "/assets/blocks/FF_GT_T",
1477 "start": 37788,
1478 "end": 38097
1479 }, {
1480 "filename": "/assets/blocks/FF_LOG_F",
1481 "start": 38097,
1482 "end": 38413
1483 }, {
1484 "filename": "/assets/blocks/FF_LT_T",
1485 "start": 38413,
1486 "end": 38720
1487 }, {
1488 "filename": "/assets/blocks/FF_MAX_F",
1489 "start": 38720,
1490 "end": 39025
1491 }, {
1492 "filename": "/assets/blocks/FF_MIN_F",
1493 "start": 39025,
1494 "end": 39331
1495 }, {
1496 "filename": "/assets/blocks/FF_MOD_F",
1497 "start": 39331,
1498 "end": 39625
1499 }, {
1500 "filename": "/assets/blocks/FF_MUL_F",
1501 "start": 39625,
1502 "end": 39930
1503 }, {
1504 "filename": "/assets/blocks/FF_POW_F",
1505 "start": 39930,
1506 "end": 40229
1507 }, {
1508 "filename": "/assets/blocks/FF_RANDOM_F",
1509 "start": 40229,
1510 "end": 40545
1511 }, {
1512 "filename": "/assets/blocks/FF_S2W_VV",
1513 "start": 40545,
1514 "end": 40876
1515 }, {
1516 "filename": "/assets/blocks/FF_SUB_F",
1517 "start": 40876,
1518 "end": 41174
1519 }, {
1520 "filename": "/assets/blocks/FLOWERS",
1521 "start": 41174,
1522 "end": 41311
1523 }, {
1524 "filename": "/assets/blocks/FOLDER_EMPTY",
1525 "start": 41311,
1526 "end": 41451
1527 }, {
1528 "filename": "/assets/blocks/FOLDER_LOCKED",
1529 "start": 41451,
1530 "end": 41644
1531 }, {
1532 "filename": "/assets/blocks/FOLDER_UNKNOWN",
1533 "start": 41644,
1534 "end": 41809
1535 }, {
1536 "filename": "/assets/blocks/FOLIAGE",
1537 "start": 41809,
1538 "end": 41901
1539 }, {
1540 "filename": "/assets/blocks/FOLIAGE_B",
1541 "start": 41901,
1542 "end": 42076
1543 }, {
1544 "filename": "/assets/blocks/FOLIAGE_BOT",
1545 "start": 42076,
1546 "end": 42209
1547 }, {
1548 "filename": "/assets/blocks/FOLIAGE_SLAB",
1549 "start": 42209,
1550 "end": 42370
1551 }, {
1552 "filename": "/assets/blocks/FOLIAGE_TOP",
1553 "start": 42370,
1554 "end": 42499
1555 }, {
1556 "filename": "/assets/blocks/FpF_LIST_ELEMENT_Fp",
1557 "start": 42499,
1558 "end": 42861
1559 }, {
1560 "filename": "/assets/blocks/FRAME_F",
1561 "start": 42861,
1562 "end": 43071
1563 }, {
1564 "filename": "/assets/blocks/F_ABS_F",
1565 "start": 43071,
1566 "end": 43288
1567 }, {
1568 "filename": "/assets/blocks/F_CEIL_F",
1569 "start": 43288,
1570 "end": 43506
1571 }, {
1572 "filename": "/assets/blocks/F_COS_F",
1573 "start": 43506,
1574 "end": 43724
1575 }, {
1576 "filename": "/assets/blocks/F_FLOOR_F",
1577 "start": 43724,
1578 "end": 43945
1579 }, {
1580 "filename": "/assets/blocks/F_NEG_F",
1581 "start": 43945,
1582 "end": 44158
1583 }, {
1584 "filename": "/assets/blocks/F_ROUND_F",
1585 "start": 44158,
1586 "end": 44378
1587 }, {
1588 "filename": "/assets/blocks/F_SIN_F",
1589 "start": 44378,
1590 "end": 44600
1591 }, {
1592 "filename": "/assets/blocks/GOAL",
1593 "start": 44600,
1594 "end": 45039
1595 }, {
1596 "filename": "/assets/blocks/GRASS_A",
1597 "start": 45039,
1598 "end": 45182
1599 }, {
1600 "filename": "/assets/blocks/GRASS_B",
1601 "start": 45182,
1602 "end": 45344
1603 }, {
1604 "filename": "/assets/blocks/L2R",
1605 "start": 45344,
1606 "end": 45452
1607 }, {
1608 "filename": "/assets/blocks/MARKER",
1609 "start": 45452,
1610 "end": 45565
1611 }, {
1612 "filename": "/assets/blocks/MOTOR_X",
1613 "start": 45565,
1614 "end": 46196
1615 }, {
1616 "filename": "/assets/blocks/MOTOR_Y",
1617 "start": 46196,
1618 "end": 47053
1619 }, {
1620 "filename": "/assets/blocks/MOTOR_Z",
1621 "start": 47053,
1622 "end": 47710
1623 }, {
1624 "filename": "/assets/blocks/MULTI_IN",
1625 "start": 47710,
1626 "end": 47819
1627 }, {
1628 "filename": "/assets/blocks/MULTI_IN_E",
1629 "start": 47819,
1630 "end": 47932
1631 }, {
1632 "filename": "/assets/blocks/MULTI_OUT",
1633 "start": 47932,
1634 "end": 48044
1635 }, {
1636 "filename": "/assets/blocks/MULTI_OUT_E",
1637 "start": 48044,
1638 "end": 48159
1639 }, {
1640 "filename": "/assets/blocks/NONE",
1641 "start": 48159,
1642 "end": 48369
1643 }, {
1644 "filename": "/assets/blocks/NUMBER_F",
1645 "start": 48369,
1646 "end": 48618
1647 }, {
1648 "filename": "/assets/blocks/OBSTACLE",
1649 "start": 48618,
1650 "end": 48746
1651 }, {
1652 "filename": "/assets/blocks/OO_EQL_T",
1653 "start": 48746,
1654 "end": 49049
1655 }, {
1656 "filename": "/assets/blocks/OpF_LIST_ELEMENT_Op",
1657 "start": 49049,
1658 "end": 49410
1659 }, {
1660 "filename": "/assets/blocks/O_GET_POS_VQ",
1661 "start": 49410,
1662 "end": 49744
1663 }, {
1664 "filename": "/assets/blocks/O_GET_SIZE_VV",
1665 "start": 49744,
1666 "end": 50068
1667 }, {
1668 "filename": "/assets/blocks/O_GET_VEL_VV",
1669 "start": 50068,
1670 "end": 50400
1671 }, {
1672 "filename": "/assets/blocks/PARTICLE",
1673 "start": 50400,
1674 "end": 50512
1675 }, {
1676 "filename": "/assets/blocks/PASS_THROUGH",
1677 "start": 50512,
1678 "end": 50636
1679 }, {
1680 "filename": "/assets/blocks/QpF_LIST_ELEMENT_Qp",
1681 "start": 50636,
1682 "end": 51e3
1683 }, {
1684 "filename": "/assets/blocks/QQF_LERP_Q",
1685 "start": 51e3,
1686 "end": 51389
1687 }, {
1688 "filename": "/assets/blocks/QQ_MUL_Q",
1689 "start": 51389,
1690 "end": 51692
1691 }, {
1692 "filename": "/assets/blocks/QUATERNION_Q",
1693 "start": 51692,
1694 "end": 52037
1695 }, {
1696 "filename": "/assets/blocks/Q_EULER_FFF",
1697 "start": 52037,
1698 "end": 52426
1699 }, {
1700 "filename": "/assets/blocks/Q_INV_Q",
1701 "start": 52426,
1702 "end": 52641
1703 }, {
1704 "filename": "/assets/blocks/SCREEN_SIZE_FF",
1705 "start": 52641,
1706 "end": 52956
1707 }, {
1708 "filename": "/assets/blocks/SCRIPT",
1709 "start": 52956,
1710 "end": 53102
1711 }, {
1712 "filename": "/assets/blocks/SFX_Fp",
1713 "start": 53102,
1714 "end": 53424
1715 }, {
1716 "filename": "/assets/blocks/SHRUB",
1717 "start": 53424,
1718 "end": 53623
1719 }, {
1720 "filename": "/assets/blocks/SLATE",
1721 "start": 53623,
1722 "end": 53717
1723 }, {
1724 "filename": "/assets/blocks/SLATE_B",
1725 "start": 53717,
1726 "end": 53922
1727 }, {
1728 "filename": "/assets/blocks/SLATE_BOT",
1729 "start": 53922,
1730 "end": 54060
1731 }, {
1732 "filename": "/assets/blocks/SLATE_NE",
1733 "start": 54060,
1734 "end": 54173
1735 }, {
1736 "filename": "/assets/blocks/SLATE_NW",
1737 "start": 54173,
1738 "end": 54293
1739 }, {
1740 "filename": "/assets/blocks/SLATE_SE",
1741 "start": 54293,
1742 "end": 54409
1743 }, {
1744 "filename": "/assets/blocks/SLATE_SW",
1745 "start": 54409,
1746 "end": 54529
1747 }, {
1748 "filename": "/assets/blocks/SLATE_TOP",
1749 "start": 54529,
1750 "end": 54653
1751 }, {
1752 "filename": "/assets/blocks/SLIDER",
1753 "start": 54653,
1754 "end": 56555
1755 }, {
1756 "filename": "/assets/blocks/SLIDER_X",
1757 "start": 56555,
1758 "end": 56835
1759 }, {
1760 "filename": "/assets/blocks/SLIDER_Y",
1761 "start": 56835,
1762 "end": 57156
1763 }, {
1764 "filename": "/assets/blocks/SLIDER_Z",
1765 "start": 57156,
1766 "end": 57454
1767 }, {
1768 "filename": "/assets/blocks/SPHERE",
1769 "start": 57454,
1770 "end": 57594
1771 }, {
1772 "filename": "/assets/blocks/STEEL",
1773 "start": 57594,
1774 "end": 57734
1775 }, {
1776 "filename": "/assets/blocks/STICK_DE",
1777 "start": 57734,
1778 "end": 57885
1779 }, {
1780 "filename": "/assets/blocks/STICK_DN",
1781 "start": 57885,
1782 "end": 58037
1783 }, {
1784 "filename": "/assets/blocks/STICK_DS",
1785 "start": 58037,
1786 "end": 58194
1787 }, {
1788 "filename": "/assets/blocks/STICK_DW",
1789 "start": 58194,
1790 "end": 58352
1791 }, {
1792 "filename": "/assets/blocks/STICK_NE",
1793 "start": 58352,
1794 "end": 58506
1795 }, {
1796 "filename": "/assets/blocks/STICK_NW",
1797 "start": 58506,
1798 "end": 58669
1799 }, {
1800 "filename": "/assets/blocks/STICK_SE",
1801 "start": 58669,
1802 "end": 58826
1803 }, {
1804 "filename": "/assets/blocks/STICK_SW",
1805 "start": 58826,
1806 "end": 58986
1807 }, {
1808 "filename": "/assets/blocks/STICK_UE",
1809 "start": 58986,
1810 "end": 59140
1811 }, {
1812 "filename": "/assets/blocks/STICK_UN",
1813 "start": 59140,
1814 "end": 59310
1815 }, {
1816 "filename": "/assets/blocks/STICK_US",
1817 "start": 59310,
1818 "end": 59467
1819 }, {
1820 "filename": "/assets/blocks/STICK_UW",
1821 "start": 59467,
1822 "end": 59622
1823 }, {
1824 "filename": "/assets/blocks/STICK_X",
1825 "start": 59622,
1826 "end": 59764
1827 }, {
1828 "filename": "/assets/blocks/STICK_Y",
1829 "start": 59764,
1830 "end": 59913
1831 }, {
1832 "filename": "/assets/blocks/STICK_Z",
1833 "start": 59913,
1834 "end": 60051
1835 }, {
1836 "filename": "/assets/blocks/STONE",
1837 "start": 60051,
1838 "end": 60145
1839 }, {
1840 "filename": "/assets/blocks/STONE_B",
1841 "start": 60145,
1842 "end": 60322
1843 }, {
1844 "filename": "/assets/blocks/STONE_BLOCK",
1845 "start": 60322,
1846 "end": 60520
1847 }, {
1848 "filename": "/assets/blocks/STONE_BOT",
1849 "start": 60520,
1850 "end": 60658
1851 }, {
1852 "filename": "/assets/blocks/STONE_LOWER",
1853 "start": 60658,
1854 "end": 60799
1855 }, {
1856 "filename": "/assets/blocks/STONE_PILLAR",
1857 "start": 60799,
1858 "end": 60954
1859 }, {
1860 "filename": "/assets/blocks/STONE_SLAB",
1861 "start": 60954,
1862 "end": 61102
1863 }, {
1864 "filename": "/assets/blocks/STONE_TOP",
1865 "start": 61102,
1866 "end": 61227
1867 }, {
1868 "filename": "/assets/blocks/SWIPE_CHICK",
1869 "start": 61227,
1870 "end": 64004
1871 }, {
1872 "filename": "/assets/blocks/THIS_O",
1873 "start": 64004,
1874 "end": 64119
1875 }, {
1876 "filename": "/assets/blocks/TILT_BALL",
1877 "start": 64119,
1878 "end": 64366
1879 }, {
1880 "filename": "/assets/blocks/TpF_LIST_ELEMENT_Tp",
1881 "start": 64366,
1882 "end": 64728
1883 }, {
1884 "filename": "/assets/blocks/TRUE_T",
1885 "start": 64728,
1886 "end": 64974
1887 }, {
1888 "filename": "/assets/blocks/TT_AND_T",
1889 "start": 64974,
1890 "end": 65267
1891 }, {
1892 "filename": "/assets/blocks/TT_EQL_T",
1893 "start": 65267,
1894 "end": 65568
1895 }, {
1896 "filename": "/assets/blocks/TT_OR_T",
1897 "start": 65568,
1898 "end": 65859
1899 }, {
1900 "filename": "/assets/blocks/T_NOT_T",
1901 "start": 65859,
1902 "end": 66073
1903 }, {
1904 "filename": "/assets/blocks/VAR_Cp",
1905 "start": 66073,
1906 "end": 66326
1907 }, {
1908 "filename": "/assets/blocks/VAR_Fp",
1909 "start": 66326,
1910 "end": 66575
1911 }, {
1912 "filename": "/assets/blocks/VAR_Op",
1913 "start": 66575,
1914 "end": 66825
1915 }, {
1916 "filename": "/assets/blocks/VAR_Qp",
1917 "start": 66825,
1918 "end": 67077
1919 }, {
1920 "filename": "/assets/blocks/VAR_Tp",
1921 "start": 67077,
1922 "end": 67327
1923 }, {
1924 "filename": "/assets/blocks/VAR_Vp",
1925 "start": 67327,
1926 "end": 67577
1927 }, {
1928 "filename": "/assets/blocks/VECTOR_V",
1929 "start": 67577,
1930 "end": 67920
1931 }, {
1932 "filename": "/assets/blocks/VF_AXIS_ANG_Q",
1933 "start": 67920,
1934 "end": 68245
1935 }, {
1936 "filename": "/assets/blocks/VF_MUL_V",
1937 "start": 68245,
1938 "end": 68546
1939 }, {
1940 "filename": "/assets/blocks/VpF_LIST_ELEMENT_Vp",
1941 "start": 68546,
1942 "end": 68909
1943 }, {
1944 "filename": "/assets/blocks/VQ_MUL_V",
1945 "start": 68909,
1946 "end": 69211
1947 }, {
1948 "filename": "/assets/blocks/VVVV_LINE_VS_PLANE_V",
1949 "start": 69211,
1950 "end": 69656
1951 }, {
1952 "filename": "/assets/blocks/VV_ADD_V",
1953 "start": 69656,
1954 "end": 69955
1955 }, {
1956 "filename": "/assets/blocks/VV_CROSS_V",
1957 "start": 69955,
1958 "end": 70260
1959 }, {
1960 "filename": "/assets/blocks/VV_DIST_F",
1961 "start": 70260,
1962 "end": 70559
1963 }, {
1964 "filename": "/assets/blocks/VV_DOT_F",
1965 "start": 70559,
1966 "end": 70872
1967 }, {
1968 "filename": "/assets/blocks/VV_EQL_T",
1969 "start": 70872,
1970 "end": 71174
1971 }, {
1972 "filename": "/assets/blocks/VV_LOOK_ROT_Q",
1973 "start": 71174,
1974 "end": 71501
1975 }, {
1976 "filename": "/assets/blocks/VV_RAYCAST_TVO",
1977 "start": 71501,
1978 "end": 71886
1979 }, {
1980 "filename": "/assets/blocks/VV_SUB_V",
1981 "start": 71886,
1982 "end": 72184
1983 }, {
1984 "filename": "/assets/blocks/V_NORMALIZE_V",
1985 "start": 72184,
1986 "end": 72408
1987 }, {
1988 "filename": "/assets/blocks/V_SPLIT_FFF",
1989 "start": 72408,
1990 "end": 72794
1991 }, {
1992 "filename": "/assets/blocks/V_W2S_FF",
1993 "start": 72794,
1994 "end": 73126
1995 }, {
1996 "filename": "/assets/blocks/WHEEL",
1997 "start": 73126,
1998 "end": 74867
1999 }, {
2000 "filename": "/assets/blocks/WOOD_LOWER_X",
2001 "start": 74867,
2002 "end": 75058
2003 }, {
2004 "filename": "/assets/blocks/WOOD_LOWER_Z",
2005 "start": 75058,
2006 "end": 75248
2007 }, {
2008 "filename": "/assets/blocks/WOOD_UPPER_X",
2009 "start": 75248,
2010 "end": 75439
2011 }, {
2012 "filename": "/assets/blocks/WOOD_UPPER_Z",
2013 "start": 75439,
2014 "end": 75629
2015 }, {
2016 "filename": "/assets/blocks/WOOD_X",
2017 "start": 75629,
2018 "end": 75804
2019 }, {
2020 "filename": "/assets/blocks/WOOD_Y",
2021 "start": 75804,
2022 "end": 75994
2023 }, {
2024 "filename": "/assets/blocks/WOOD_Z",
2025 "start": 75994,
2026 "end": 76165
2027 }, {
2028 "filename": "/assets/views/baloo2.woff",
2029 "start": 76165,
2030 "end": 100237
2031 }, {
2032 "filename": "/assets/views/block_settings.html",
2033 "start": 100237,
2034 "end": 102302
2035 }, {
2036 "filename": "/assets/views/common.css",
2037 "start": 102302,
2038 "end": 107895
2039 }, {
2040 "filename": "/assets/views/common.js",
2041 "start": 107895,
2042 "end": 115815
2043 }, {
2044 "filename": "/assets/views/confirm_deletion.html",
2045 "start": 115815,
2046 "end": 118184
2047 }, {
2048 "filename": "/assets/views/create_user.html",
2049 "start": 118184,
2050 "end": 120412
2051 }, {
2052 "filename": "/assets/views/game_moderation.html",
2053 "start": 120412,
2054 "end": 125080
2055 }, {
2056 "filename": "/assets/views/messagebox.html",
2057 "start": 125080,
2058 "end": 127196
2059 }, {
2060 "filename": "/assets/views/select_level.html",
2061 "start": 127196,
2062 "end": 139970
2063 }, {
2064 "filename": "/assets/views/show_hint.html",
2065 "start": 139970,
2066 "end": 141099
2067 }, {
2068 "filename": "/assets/views/sign_in.html",
2069 "start": 141099,
2070 "end": 143557
2071 }, {
2072 "filename": "/assets/atlas.png",
2073 "start": 143557,
2074 "end": 395104
2075 }, {
2076 "filename": "/assets/db",
2077 "start": 395104,
2078 "end": 395346
2079 }, {
2080 "filename": "/assets/games/menu",
2081 "start": 395346,
2082 "end": 400941
2083 }, {
2084 "filename": "/assets/games/5F084A0BCE06B710",
2085 "start": 400941,
2086 "end": 451559
2087 }, {
2088 "filename": "/bundle_games.txt",
2089 "start": 451559,
2090 "end": 451575
2091 }, {
2092 "filename": "/assets/sounds/36837_engine_no_click.wav",
2093 "start": 451575,
2094 "end": 463613,
2095 "audio": 1
2096 }, {
2097 "filename": "/assets/sounds/188204_scrape.wav",
2098 "start": 463613,
2099 "end": 495649,
2100 "audio": 1
2101 }, {
2102 "filename": "/assets/sounds/78937_squeek.wav",
2103 "start": 495649,
2104 "end": 505759,
2105 "audio": 1
2106 }, {
2107 "filename": "/assets/sounds/257357_button.wav",
2108 "start": 505759,
2109 "end": 507123,
2110 "audio": 1
2111 }, {
2112 "filename": "/assets/sounds/249929_splash1.wav",
2113 "start": 507123,
2114 "end": 518827,
2115 "audio": 1
2116 }, {
2117 "filename": "/assets/sounds/315935_bang.wav",
2118 "start": 518827,
2119 "end": 571337,
2120 "audio": 1
2121 }, {
2122 "filename": "/assets/sounds/floor6.wav",
2123 "start": 571337,
2124 "end": 602361,
2125 "audio": 1
2126 }, {
2127 "filename": "/assets/sounds/399095_jump.wav",
2128 "start": 602361,
2129 "end": 607739,
2130 "audio": 1
2131 }, {
2132 "filename": "/assets/sounds/521481_camera.wav",
2133 "start": 607739,
2134 "end": 623171,
2135 "audio": 1
2136 }, {
2137 "filename": "/assets/sounds/194795_ui_button.wav",
2138 "start": 623171,
2139 "end": 625273,
2140 "audio": 1
2141 }, {
2142 "filename": "/assets/sounds/146721_ui_beep.wav",
2143 "start": 625273,
2144 "end": 629775,
2145 "audio": 1
2146 }, {
2147 "filename": "/assets/sounds/chaching.wav",
2148 "start": 629775,
2149 "end": 679055,
2150 "audio": 1
2151 }, {
2152 "filename": "/assets/sounds/363090_coin.wav",
2153 "start": 679055,
2154 "end": 683813,
2155 "audio": 1
2156 }, {
2157 "filename": "/assets/sounds/coin02_band.wav",
2158 "start": 683813,
2159 "end": 695797,
2160 "audio": 1
2161 }, {
2162 "filename": "/assets/sounds/error1.wav",
2163 "start": 695797,
2164 "end": 717057,
2165 "audio": 1
2166 }],
2167 "remote_package_size": 717057
2168 })
2169 })();
2170 var moduleOverrides = Object.assign({}, Module);
2171 var arguments_ = [];
2172 var thisProgram = "./this.program";
2173 var quit_ = (status, toThrow) => {
2174 throw toThrow
2175 };
2176 var ENVIRONMENT_IS_WEB = typeof window == "object";
2177 var ENVIRONMENT_IS_WORKER = typeof importScripts == "function";
2178 var ENVIRONMENT_IS_NODE = typeof process == "object" && typeof process.versions == "object" && typeof process.versions.node == "string";
2179 var scriptDirectory = "";
2180
2181 function locateFile(path) {
2182 if (Module["locateFile"]) {
2183 return Module["locateFile"](path, scriptDirectory)
2184 }
2185 return scriptDirectory + path
2186 }
2187 var read_, readAsync, readBinary, setWindowTitle;
2188
2189 function logExceptionOnExit(e) {
2190 if (e instanceof ExitStatus) return;
2191 let toLog = e;
2192 err("exiting due to exception: " + toLog)
2193 }
2194 var fs;
2195 var nodePath;
2196 var requireNodeFS;
2197 if (ENVIRONMENT_IS_NODE) {
2198 if (ENVIRONMENT_IS_WORKER) {
2199 scriptDirectory = require("path").dirname(scriptDirectory) + "/"
2200 } else {
2201 scriptDirectory = __dirname + "/"
2202 }
2203 requireNodeFS = () => {
2204 if (!nodePath) {
2205 fs = require("fs");
2206 nodePath = require("path")
2207 }
2208 };
2209 read_ = function shell_read(filename, binary) {
2210 requireNodeFS();
2211 filename = nodePath["normalize"](filename);
2212 return fs.readFileSync(filename, binary ? undefined : "utf8")
2213 };
2214 readBinary = filename => {
2215 var ret = read_(filename, true);
2216 if (!ret.buffer) {
2217 ret = new Uint8Array(ret)
2218 }
2219 return ret
2220 };
2221 readAsync = (filename, onload, onerror) => {
2222 requireNodeFS();
2223 filename = nodePath["normalize"](filename);
2224 fs.readFile(filename, function(err, data) {
2225 if (err) onerror(err);
2226 else onload(data.buffer)
2227 })
2228 };
2229 if (process["argv"].length > 1) {
2230 thisProgram = process["argv"][1].replace(/\\/g, "/")
2231 }
2232 arguments_ = process["argv"].slice(2);
2233 if (typeof module != "undefined") {
2234 module["exports"] = Module
2235 }
2236 process["on"]("uncaughtException", function(ex) {
2237 if (!(ex instanceof ExitStatus)) {
2238 throw ex
2239 }
2240 });
2241 process["on"]("unhandledRejection", function(reason) {
2242 throw reason
2243 });
2244 quit_ = (status, toThrow) => {
2245 if (keepRuntimeAlive()) {
2246 process["exitCode"] = status;
2247 throw toThrow
2248 }
2249 logExceptionOnExit(toThrow);
2250 process["exit"](status)
2251 };
2252 Module["inspect"] = function() {
2253 return "[Emscripten Module object]"
2254 }
2255 } else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
2256 if (ENVIRONMENT_IS_WORKER) {
2257 scriptDirectory = self.location.href
2258 } else if (typeof document != "undefined" && document.currentScript) {
2259 scriptDirectory = document.currentScript.src
2260 }
2261 if (scriptDirectory.indexOf("blob:") !== 0) {
2262 scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, "").lastIndexOf("/") + 1)
2263 } else {
2264 scriptDirectory = ""
2265 } {
2266 read_ = url => {
2267 var xhr = new XMLHttpRequest;
2268 xhr.open("GET", url, false);
2269 xhr.send(null);
2270 return xhr.responseText
2271 };
2272 if (ENVIRONMENT_IS_WORKER) {
2273 readBinary = url => {
2274 var xhr = new XMLHttpRequest;
2275 xhr.open("GET", url, false);
2276 xhr.responseType = "arraybuffer";
2277 xhr.send(null);
2278 return new Uint8Array(xhr.response)
2279 }
2280 }
2281 readAsync = (url, onload, onerror) => {
2282 var xhr = new XMLHttpRequest;
2283 xhr.open("GET", url, true);
2284 xhr.responseType = "arraybuffer";
2285 xhr.onload = () => {
2286 if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
2287 onload(xhr.response);
2288 return
2289 }
2290 onerror()
2291 };
2292 xhr.onerror = onerror;
2293 xhr.send(null)
2294 }
2295 }
2296 setWindowTitle = title => document.title = title
2297 } else {}
2298 var out = Module["print"] || console.log.bind(console);
2299 var err = Module["printErr"] || console.warn.bind(console);
2300 Object.assign(Module, moduleOverrides);
2301 moduleOverrides = null;
2302 if (Module["arguments"]) arguments_ = Module["arguments"];
2303 if (Module["thisProgram"]) thisProgram = Module["thisProgram"];
2304 if (Module["quit"]) quit_ = Module["quit"];
2305
2306 function warnOnce(text) {
2307 if (!warnOnce.shown) warnOnce.shown = {};
2308 if (!warnOnce.shown[text]) {
2309 warnOnce.shown[text] = 1;
2310 err(text)
2311 }
2312 }
2313 var wasmBinary;
2314 if (Module["wasmBinary"]) wasmBinary = Module["wasmBinary"];
2315 var noExitRuntime = Module["noExitRuntime"] || true;
2316 if (typeof WebAssembly != "object") {
2317 abort("no native wasm support detected")
2318 }
2319 var wasmMemory;
2320 var ABORT = false;
2321 var EXITSTATUS;
2322
2323 function assert(condition, text) {
2324 if (!condition) {
2325 abort(text)
2326 }
2327 }
2328
2329 function getCFunc(ident) {
2330 var func = Module["_" + ident];
2331 return func
2332 }
2333
2334 function ccall(ident, returnType, argTypes, args, opts) {
2335 var toC = {
2336 "string": function(str) {
2337 var ret = 0;
2338 if (str !== null && str !== undefined && str !== 0) {
2339 var len = (str.length << 2) + 1;
2340 ret = stackAlloc(len);
2341 stringToUTF8(str, ret, len)
2342 }
2343 return ret
2344 },
2345 "array": function(arr) {
2346 var ret = stackAlloc(arr.length);
2347 writeArrayToMemory(arr, ret);
2348 return ret
2349 }
2350 };
2351
2352 function convertReturnValue(ret) {
2353 if (returnType === "string") {
2354 return UTF8ToString(ret)
2355 }
2356 if (returnType === "boolean") return Boolean(ret);
2357 return ret
2358 }
2359 var func = getCFunc(ident);
2360 var cArgs = [];
2361 var stack = 0;
2362 if (args) {
2363 for (var i = 0; i < args.length; i++) {
2364 var converter = toC[argTypes[i]];
2365 if (converter) {
2366 if (stack === 0) stack = stackSave();
2367 cArgs[i] = converter(args[i])
2368 } else {
2369 cArgs[i] = args[i]
2370 }
2371 }
2372 }
2373 var ret = func.apply(null, cArgs);
2374
2375 function onDone(ret) {
2376 if (stack !== 0) stackRestore(stack);
2377 return convertReturnValue(ret)
2378 }
2379 ret = onDone(ret);
2380 return ret
2381 }
2382
2383 function cwrap(ident, returnType, argTypes, opts) {
2384 argTypes = argTypes || [];
2385 var numericArgs = argTypes.every(function(type) {
2386 return type === "number"
2387 });
2388 var numericRet = returnType !== "string";
2389 if (numericRet && numericArgs && !opts) {
2390 return getCFunc(ident)
2391 }
2392 return function() {
2393 return ccall(ident, returnType, argTypes, arguments, opts)
2394 }
2395 }
2396 var UTF8Decoder = typeof TextDecoder != "undefined" ? new TextDecoder("utf8") : undefined;
2397
2398 function UTF8ArrayToString(heapOrArray, idx, maxBytesToRead) {
2399 var endIdx = idx + maxBytesToRead;
2400 var endPtr = idx;
2401 while (heapOrArray[endPtr] && !(endPtr >= endIdx)) ++endPtr;
2402 if (endPtr - idx > 16 && heapOrArray.buffer && UTF8Decoder) {
2403 return UTF8Decoder.decode(heapOrArray.subarray(idx, endPtr))
2404 } else {
2405 var str = "";
2406 while (idx < endPtr) {
2407 var u0 = heapOrArray[idx++];
2408 if (!(u0 & 128)) {
2409 str += String.fromCharCode(u0);
2410 continue
2411 }
2412 var u1 = heapOrArray[idx++] & 63;
2413 if ((u0 & 224) == 192) {
2414 str += String.fromCharCode((u0 & 31) << 6 | u1);
2415 continue
2416 }
2417 var u2 = heapOrArray[idx++] & 63;
2418 if ((u0 & 240) == 224) {
2419 u0 = (u0 & 15) << 12 | u1 << 6 | u2
2420 } else {
2421 u0 = (u0 & 7) << 18 | u1 << 12 | u2 << 6 | heapOrArray[idx++] & 63
2422 }
2423 if (u0 < 65536) {
2424 str += String.fromCharCode(u0)
2425 } else {
2426 var ch = u0 - 65536;
2427 str += String.fromCharCode(55296 | ch >> 10, 56320 | ch & 1023)
2428 }
2429 }
2430 }
2431 return str
2432 }
2433
2434 function UTF8ToString(ptr, maxBytesToRead) {
2435 return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : ""
2436 }
2437
2438 function stringToUTF8Array(str, heap, outIdx, maxBytesToWrite) {
2439 if (!(maxBytesToWrite > 0)) return 0;
2440 var startIdx = outIdx;
2441 var endIdx = outIdx + maxBytesToWrite - 1;
2442 for (var i = 0; i < str.length; ++i) {
2443 var u = str.charCodeAt(i);
2444 if (u >= 55296 && u <= 57343) {
2445 var u1 = str.charCodeAt(++i);
2446 u = 65536 + ((u & 1023) << 10) | u1 & 1023
2447 }
2448 if (u <= 127) {
2449 if (outIdx >= endIdx) break;
2450 heap[outIdx++] = u
2451 } else if (u <= 2047) {
2452 if (outIdx + 1 >= endIdx) break;
2453 heap[outIdx++] = 192 | u >> 6;
2454 heap[outIdx++] = 128 | u & 63
2455 } else if (u <= 65535) {
2456 if (outIdx + 2 >= endIdx) break;
2457 heap[outIdx++] = 224 | u >> 12;
2458 heap[outIdx++] = 128 | u >> 6 & 63;
2459 heap[outIdx++] = 128 | u & 63
2460 } else {
2461 if (outIdx + 3 >= endIdx) break;
2462 heap[outIdx++] = 240 | u >> 18;
2463 heap[outIdx++] = 128 | u >> 12 & 63;
2464 heap[outIdx++] = 128 | u >> 6 & 63;
2465 heap[outIdx++] = 128 | u & 63
2466 }
2467 }
2468 heap[outIdx] = 0;
2469 return outIdx - startIdx
2470 }
2471
2472 function stringToUTF8(str, outPtr, maxBytesToWrite) {
2473 return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite)
2474 }
2475
2476 function lengthBytesUTF8(str) {
2477 var len = 0;
2478 for (var i = 0; i < str.length; ++i) {
2479 var u = str.charCodeAt(i);
2480 if (u >= 55296 && u <= 57343) u = 65536 + ((u & 1023) << 10) | str.charCodeAt(++i) & 1023;
2481 if (u <= 127) ++len;
2482 else if (u <= 2047) len += 2;
2483 else if (u <= 65535) len += 3;
2484 else len += 4
2485 }
2486 return len
2487 }
2488
2489 function allocateUTF8(str) {
2490 var size = lengthBytesUTF8(str) + 1;
2491 var ret = _malloc(size);
2492 if (ret) stringToUTF8Array(str, HEAP8, ret, size);
2493 return ret
2494 }
2495
2496 function allocateUTF8OnStack(str) {
2497 var size = lengthBytesUTF8(str) + 1;
2498 var ret = stackAlloc(size);
2499 stringToUTF8Array(str, HEAP8, ret, size);
2500 return ret
2501 }
2502
2503 function writeArrayToMemory(array, buffer) {
2504 HEAP8.set(array, buffer)
2505 }
2506 var buffer, HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64;
2507
2508 function updateGlobalBufferAndViews(buf) {
2509 buffer = buf;
2510 Module["HEAP8"] = HEAP8 = new Int8Array(buf);
2511 Module["HEAP16"] = HEAP16 = new Int16Array(buf);
2512 Module["HEAP32"] = HEAP32 = new Int32Array(buf);
2513 Module["HEAPU8"] = HEAPU8 = new Uint8Array(buf);
2514 Module["HEAPU16"] = HEAPU16 = new Uint16Array(buf);
2515 Module["HEAPU32"] = HEAPU32 = new Uint32Array(buf);
2516 Module["HEAPF32"] = HEAPF32 = new Float32Array(buf);
2517 Module["HEAPF64"] = HEAPF64 = new Float64Array(buf)
2518 }
2519 var INITIAL_MEMORY = Module["INITIAL_MEMORY"] || 33554432;
2520 var wasmTable;
2521 var __ATPRERUN__ = [];
2522 var __ATINIT__ = [];
2523 var __ATMAIN__ = [];
2524 var __ATEXIT__ = [];
2525 var __ATPOSTRUN__ = [];
2526 var runtimeInitialized = false;
2527
2528 function keepRuntimeAlive() {
2529 return noExitRuntime
2530 }
2531
2532 function preRun() {
2533 if (Module["preRun"]) {
2534 if (typeof Module["preRun"] == "function") Module["preRun"] = [Module["preRun"]];
2535 while (Module["preRun"].length) {
2536 addOnPreRun(Module["preRun"].shift())
2537 }
2538 }
2539 callRuntimeCallbacks(__ATPRERUN__)
2540 }
2541
2542 function initRuntime() {
2543 runtimeInitialized = true;
2544 if (!Module["noFSInit"] && !FS.init.initialized) FS.init();
2545 FS.ignorePermissions = false;
2546 TTY.init();
2547 callRuntimeCallbacks(__ATINIT__)
2548 }
2549
2550 function preMain() {
2551 callRuntimeCallbacks(__ATMAIN__)
2552 }
2553
2554 function postRun() {
2555 if (Module["postRun"]) {
2556 if (typeof Module["postRun"] == "function") Module["postRun"] = [Module["postRun"]];
2557 while (Module["postRun"].length) {
2558 addOnPostRun(Module["postRun"].shift())
2559 }
2560 }
2561 callRuntimeCallbacks(__ATPOSTRUN__)
2562 }
2563
2564 function addOnPreRun(cb) {
2565 __ATPRERUN__.unshift(cb)
2566 }
2567
2568 function addOnInit(cb) {
2569 __ATINIT__.unshift(cb)
2570 }
2571
2572 function addOnPostRun(cb) {
2573 __ATPOSTRUN__.unshift(cb)
2574 }
2575 var runDependencies = 0;
2576 var runDependencyWatcher = null;
2577 var dependenciesFulfilled = null;
2578
2579 function getUniqueRunDependency(id) {
2580 return id
2581 }
2582
2583 function addRunDependency(id) {
2584 runDependencies++;
2585 if (Module["monitorRunDependencies"]) {
2586 Module["monitorRunDependencies"](runDependencies)
2587 }
2588 }
2589
2590 function removeRunDependency(id) {
2591 runDependencies--;
2592 if (Module["monitorRunDependencies"]) {
2593 Module["monitorRunDependencies"](runDependencies)
2594 }
2595 if (runDependencies == 0) {
2596 if (runDependencyWatcher !== null) {
2597 clearInterval(runDependencyWatcher);
2598 runDependencyWatcher = null
2599 }
2600 if (dependenciesFulfilled) {
2601 var callback = dependenciesFulfilled;
2602 dependenciesFulfilled = null;
2603 callback()
2604 }
2605 }
2606 }
2607
2608 function abort(what) {
2609 {
2610 if (Module["onAbort"]) {
2611 Module["onAbort"](what)
2612 }
2613 }
2614 what = "Aborted(" + what + ")";
2615 err(what);
2616 ABORT = true;
2617 EXITSTATUS = 1;
2618 what += ". Build with -sASSERTIONS for more info.";
2619 var e = new WebAssembly.RuntimeError(what);
2620 throw e
2621 }
2622 var dataURIPrefix = "data:application/octet-stream;base64,";
2623
2624 function isDataURI(filename) {
2625 return filename.startsWith(dataURIPrefix)
2626 }
2627
2628 function isFileURI(filename) {
2629 return filename.startsWith("file://")
2630 }
2631 var wasmBinaryFile;
2632 window["index.wasm"] = window["index.wasm"];
2633 if (!isDataURI(window["index.wasm"])) {
2634 window["index.wasm"] = locateFile(window["index.wasm"])
2635 }
2636
2637 function getBinary(file) {
2638 try {
2639 if (file == window["index.wasm"] && wasmBinary) {
2640 return new Uint8Array(wasmBinary)
2641 }
2642 if (readBinary) {
2643 return readBinary(file)
2644 } else {
2645 throw "both async and sync fetching of the wasm failed"
2646 }
2647 } catch (err) {
2648 abort(err)
2649 }
2650 }
2651
2652 function getBinaryPromise() {
2653 if (!wasmBinary && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) {
2654 if (typeof fetch == "function" && !isFileURI(window["index.wasm"])) {
2655 return fetch(window["index.wasm"], {
2656 credentials: "same-origin"
2657 }).then(function(response) {
2658 if (!response["ok"]) {
2659 throw "failed to load wasm binary file at '" + window["index.wasm"] + "'"
2660 }
2661 return response["arrayBuffer"]()
2662 }).catch(function() {
2663 return getBinary(window["index.wasm"])
2664 })
2665 } else {
2666 if (readAsync) {
2667 return new Promise(function(resolve, reject) {
2668 readAsync(window["index.wasm"], function(response) {
2669 resolve(new Uint8Array(response))
2670 }, reject)
2671 })
2672 }
2673 }
2674 }
2675 return Promise.resolve().then(function() {
2676 return getBinary(window["index.wasm"])
2677 })
2678 }
2679
2680 function createWasm() {
2681 var info = {
2682 "a": asmLibraryArg
2683 };
2684
2685 function receiveInstance(instance, module) {
2686 var exports = instance.exports;
2687 Module["asm"] = exports;
2688 wasmMemory = Module["asm"]["kb"];
2689 updateGlobalBufferAndViews(wasmMemory.buffer);
2690 wasmTable = Module["asm"]["Nb"];
2691 addOnInit(Module["asm"]["lb"]);
2692 removeRunDependency("wasm-instantiate")
2693 }
2694 addRunDependency("wasm-instantiate");
2695
2696 function receiveInstantiationResult(result) {
2697 receiveInstance(result["instance"])
2698 }
2699
2700 function instantiateArrayBuffer(receiver) {
2701 return getBinaryPromise().then(function(binary) {
2702 return WebAssembly.instantiate(binary, info)
2703 }).then(function(instance) {
2704 return instance
2705 }).then(receiver, function(reason) {
2706 err("failed to asynchronously prepare wasm: " + reason);
2707 abort(reason)
2708 })
2709 }
2710
2711 function instantiateAsync() {
2712 if (!wasmBinary && typeof WebAssembly.instantiateStreaming == "function" && !isDataURI(window["index.wasm"]) && !isFileURI(window["index.wasm"]) && !ENVIRONMENT_IS_NODE && typeof fetch == "function") {
2713 return fetch(window["index.wasm"], {
2714 credentials: "same-origin"
2715 }).then(function(response) {
2716 var result = WebAssembly.instantiateStreaming(response, info);
2717 return result.then(receiveInstantiationResult, function(reason) {
2718 err("wasm streaming compile failed: " + reason);
2719 err("falling back to ArrayBuffer instantiation");
2720 return instantiateArrayBuffer(receiveInstantiationResult)
2721 })
2722 })
2723 } else {
2724 return instantiateArrayBuffer(receiveInstantiationResult)
2725 }
2726 }
2727 if (Module["instantiateWasm"]) {
2728 try {
2729 var exports = Module["instantiateWasm"](info, receiveInstance);
2730 return exports
2731 } catch (e) {
2732 err("Module.instantiateWasm callback failed with error: " + e);
2733 return false
2734 }
2735 }
2736 instantiateAsync();
2737 return {}
2738 }
2739 var tempDouble;
2740 var tempI64;
2741 var ASM_CONSTS = {
2742 287104: ($0, $1) => {
2743 checkHintFileExist(UTF8ToString($0), $1)
2744 },
2745 287148: () => {
2746 hideOverlayGradient()
2747 },
2748 287173: $0 => {
2749 downloadFileInBrowser(UTF8ToString($0))
2750 },
2751 287215: ($0, $1, $2) => {
2752 fetchUrl(UTF8ToString($0), $1, $2)
2753 },
2754 287252: $0 => {
2755 webViewOpen(UTF8ToString($0))
2756 },
2757 287285: () => {
2758 webViewClose()
2759 },
2760 287303: $0 => {
2761 webViewExecuteJS(UTF8ToString($0))
2762 },
2763 287341: () => {
2764 hideOverlayGradient()
2765 },
2766 287366: () => {
2767 FS.syncfs(false, function(err) {
2768 if (err) {
2769 simpleLogC("syncfs error " + err)
2770 }
2771 })
2772 },
2773 287452: () => {
2774 FS.syncfs(true, function(err) {
2775 if (err) {
2776 simpleLogC("syncfs error " + err)
2777 }
2778 })
2779 },
2780 287537: () => {
2781 firebaseSignout()
2782 },
2783 287558: () => {
2784 adInterstitialLoad()
2785 },
2786 287584: () => {
2787 adInterstitialShow()
2788 },
2789 287610: () => {
2790 adRewardedLoad()
2791 },
2792 287632: () => {
2793 adRewardedShow()
2794 },
2795 287654: () => {
2796 adInit()
2797 },
2798 287668: () => {
2799 adInit()
2800 },
2801 287682: ($0, $1, $2) => {
2802 showShareFileModal(UTF8ToString($0), UTF8ToString($1), UTF8ToString($2))
2803 },
2804 287757: $0 => {
2805 window.open(UTF8ToString($0), "_blank")
2806 },
2807 287802: () => {
2808 location.reload()
2809 },
2810 287825: ($0, $1, $2, $3) => {
2811 showStoreLinkModal(UTF8ToString($0), $1, $2, $3)
2812 },
2813 287877: () => {
2814 FS.mkdir("/sandbox");
2815 FS.mount(IDBFS, {}, "/sandbox");
2816 FS.syncfs(true, function(err) {
2817 if (err) {
2818 simpleLogC("syncfs error " + err)
2819 }
2820 try {
2821 ccall("app_init", "v")
2822 } catch (err) {
2823 simpleLogC("app_init() error " + err)
2824 }
2825 hideOverlay()
2826 })
2827 },
2828 288123: () => {
2829 return document.getElementById("canvas").width
2830 },
2831 288173: () => {
2832 return document.getElementById("canvas").height
2833 },
2834 288224: $0 => {
2835 setDeepLinkLoadingFraction($0)
2836 }
2837 };
2838
2839 function get_device_pixel_ratio() {
2840 return window.devicePixelRatio
2841 }
2842
2843 function get_hostname() {
2844 return getHostname()
2845 }
2846
2847 function get_url_level_index() {
2848 return getUrlLevelIndex()
2849 }
2850
2851 function is_daily_reward_possible() {
2852 return dailyRewardPossible
2853 }
2854
2855 function is_latest_browser_tab() {
2856 try {
2857 return localStorage["startup-time"] == startupTimeStr
2858 } catch (err) {
2859 return true
2860 }
2861 }
2862
2863 function poki_gameplay_start() {
2864 pokiEnsureStart()
2865 }
2866
2867 function poki_gameplay_stop() {
2868 pokiEnsureStop()
2869 }
2870
2871 function poki_level_start(li) {
2872 try {} catch (err) {}
2873 }
2874
2875 function set_latest_browser_tab() {
2876 startupTimeStr = Date.now().toString();
2877 try {
2878 localStorage["startup-time"] = startupTimeStr
2879 } catch (err) {}
2880 }
2881
2882 function callRuntimeCallbacks(callbacks) {
2883 while (callbacks.length > 0) {
2884 var callback = callbacks.shift();
2885 if (typeof callback == "function") {
2886 callback(Module);
2887 continue
2888 }
2889 var func = callback.func;
2890 if (typeof func == "number") {
2891 if (callback.arg === undefined) {
2892 getWasmTableEntry(func)()
2893 } else {
2894 getWasmTableEntry(func)(callback.arg)
2895 }
2896 } else {
2897 func(callback.arg === undefined ? null : callback.arg)
2898 }
2899 }
2900 }
2901
2902 function withStackSave(f) {
2903 var stack = stackSave();
2904 var ret = f();
2905 stackRestore(stack);
2906 return ret
2907 }
2908 var wasmTableMirror = [];
2909
2910 function getWasmTableEntry(funcPtr) {
2911 var func = wasmTableMirror[funcPtr];
2912 if (!func) {
2913 if (funcPtr >= wasmTableMirror.length) wasmTableMirror.length = funcPtr + 1;
2914 wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr)
2915 }
2916 return func
2917 }
2918
2919 function handleException(e) {
2920 if (e instanceof ExitStatus || e == "unwind") {
2921 return EXITSTATUS
2922 }
2923 quit_(1, e)
2924 }
2925
2926 function getRandomDevice() {
2927 if (typeof crypto == "object" && typeof crypto["getRandomValues"] == "function") {
2928 var randomBuffer = new Uint8Array(1);
2929 return function() {
2930 crypto.getRandomValues(randomBuffer);
2931 return randomBuffer[0]
2932 }
2933 } else if (ENVIRONMENT_IS_NODE) {
2934 try {
2935 var crypto_module = require("crypto");
2936 return function() {
2937 return crypto_module["randomBytes"](1)[0]
2938 }
2939 } catch (e) {}
2940 }
2941 return function() {
2942 abort("randomDevice")
2943 }
2944 }
2945 var PATH = {
2946 isAbs: path => path.charAt(0) === "/",
2947 splitPath: filename => {
2948 var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
2949 return splitPathRe.exec(filename).slice(1)
2950 },
2951 normalizeArray: (parts, allowAboveRoot) => {
2952 var up = 0;
2953 for (var i = parts.length - 1; i >= 0; i--) {
2954 var last = parts[i];
2955 if (last === ".") {
2956 parts.splice(i, 1)
2957 } else if (last === "..") {
2958 parts.splice(i, 1);
2959 up++
2960 } else if (up) {
2961 parts.splice(i, 1);
2962 up--
2963 }
2964 }
2965 if (allowAboveRoot) {
2966 for (; up; up--) {
2967 parts.unshift("..")
2968 }
2969 }
2970 return parts
2971 },
2972 normalize: path => {
2973 var isAbsolute = PATH.isAbs(path),
2974 trailingSlash = path.substr(-1) === "/";
2975 path = PATH.normalizeArray(path.split("/").filter(p => !!p), !isAbsolute).join("/");
2976 if (!path && !isAbsolute) {
2977 path = "."
2978 }
2979 if (path && trailingSlash) {
2980 path += "/"
2981 }
2982 return (isAbsolute ? "/" : "") + path
2983 },
2984 dirname: path => {
2985 var result = PATH.splitPath(path),
2986 root = result[0],
2987 dir = result[1];
2988 if (!root && !dir) {
2989 return "."
2990 }
2991 if (dir) {
2992 dir = dir.substr(0, dir.length - 1)
2993 }
2994 return root + dir
2995 },
2996 basename: path => {
2997 if (path === "/") return "/";
2998 path = PATH.normalize(path);
2999 path = path.replace(/\/$/, "");
3000 var lastSlash = path.lastIndexOf("/");
3001 if (lastSlash === -1) return path;
3002 return path.substr(lastSlash + 1)
3003 },
3004 join: function() {
3005 var paths = Array.prototype.slice.call(arguments, 0);
3006 return PATH.normalize(paths.join("/"))
3007 },
3008 join2: (l, r) => {
3009 return PATH.normalize(l + "/" + r)
3010 }
3011 };
3012 var PATH_FS = {
3013 resolve: function() {
3014 var resolvedPath = "",
3015 resolvedAbsolute = false;
3016 for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
3017 var path = i >= 0 ? arguments[i] : FS.cwd();
3018 if (typeof path != "string") {
3019 throw new TypeError("Arguments to path.resolve must be strings")
3020 } else if (!path) {
3021 return ""
3022 }
3023 resolvedPath = path + "/" + resolvedPath;
3024 resolvedAbsolute = PATH.isAbs(path)
3025 }
3026 resolvedPath = PATH.normalizeArray(resolvedPath.split("/").filter(p => !!p), !resolvedAbsolute).join("/");
3027 return (resolvedAbsolute ? "/" : "") + resolvedPath || "."
3028 },
3029 relative: (from, to) => {
3030 from = PATH_FS.resolve(from).substr(1);
3031 to = PATH_FS.resolve(to).substr(1);
3032
3033 function trim(arr) {
3034 var start = 0;
3035 for (; start < arr.length; start++) {
3036 if (arr[start] !== "") break
3037 }
3038 var end = arr.length - 1;
3039 for (; end >= 0; end--) {
3040 if (arr[end] !== "") break
3041 }
3042 if (start > end) return [];
3043 return arr.slice(start, end - start + 1)
3044 }
3045 var fromParts = trim(from.split("/"));
3046 var toParts = trim(to.split("/"));
3047 var length = Math.min(fromParts.length, toParts.length);
3048 var samePartsLength = length;
3049 for (var i = 0; i < length; i++) {
3050 if (fromParts[i] !== toParts[i]) {
3051 samePartsLength = i;
3052 break
3053 }
3054 }
3055 var outputParts = [];
3056 for (var i = samePartsLength; i < fromParts.length; i++) {
3057 outputParts.push("..")
3058 }
3059 outputParts = outputParts.concat(toParts.slice(samePartsLength));
3060 return outputParts.join("/")
3061 }
3062 };
3063 var TTY = {
3064 ttys: [],
3065 init: function() {},
3066 shutdown: function() {},
3067 register: function(dev, ops) {
3068 TTY.ttys[dev] = {
3069 input: [],
3070 output: [],
3071 ops: ops
3072 };
3073 FS.registerDevice(dev, TTY.stream_ops)
3074 },
3075 stream_ops: {
3076 open: function(stream) {
3077 var tty = TTY.ttys[stream.node.rdev];
3078 if (!tty) {
3079 throw new FS.ErrnoError(43)
3080 }
3081 stream.tty = tty;
3082 stream.seekable = false
3083 },
3084 close: function(stream) {
3085 stream.tty.ops.flush(stream.tty)
3086 },
3087 flush: function(stream) {
3088 stream.tty.ops.flush(stream.tty)
3089 },
3090 read: function(stream, buffer, offset, length, pos) {
3091 if (!stream.tty || !stream.tty.ops.get_char) {
3092 throw new FS.ErrnoError(60)
3093 }
3094 var bytesRead = 0;
3095 for (var i = 0; i < length; i++) {
3096 var result;
3097 try {
3098 result = stream.tty.ops.get_char(stream.tty)
3099 } catch (e) {
3100 throw new FS.ErrnoError(29)
3101 }
3102 if (result === undefined && bytesRead === 0) {
3103 throw new FS.ErrnoError(6)
3104 }
3105 if (result === null || result === undefined) break;
3106 bytesRead++;
3107 buffer[offset + i] = result
3108 }
3109 if (bytesRead) {
3110 stream.node.timestamp = Date.now()
3111 }
3112 return bytesRead
3113 },
3114 write: function(stream, buffer, offset, length, pos) {
3115 if (!stream.tty || !stream.tty.ops.put_char) {
3116 throw new FS.ErrnoError(60)
3117 }
3118 try {
3119 for (var i = 0; i < length; i++) {
3120 stream.tty.ops.put_char(stream.tty, buffer[offset + i])
3121 }
3122 } catch (e) {
3123 throw new FS.ErrnoError(29)
3124 }
3125 if (length) {
3126 stream.node.timestamp = Date.now()
3127 }
3128 return i
3129 }
3130 },
3131 default_tty_ops: {
3132 get_char: function(tty) {
3133 if (!tty.input.length) {
3134 var result = null;
3135 if (ENVIRONMENT_IS_NODE) {
3136 var BUFSIZE = 256;
3137 var buf = Buffer.alloc(BUFSIZE);
3138 var bytesRead = 0;
3139 try {
3140 bytesRead = fs.readSync(process.stdin.fd, buf, 0, BUFSIZE, -1)
3141 } catch (e) {
3142 if (e.toString().includes("EOF")) bytesRead = 0;
3143 else throw e
3144 }
3145 if (bytesRead > 0) {
3146 result = buf.slice(0, bytesRead).toString("utf-8")
3147 } else {
3148 result = null
3149 }
3150 } else if (typeof window != "undefined" && typeof window.prompt == "function") {
3151 result = window.prompt("Input: ");
3152 if (result !== null) {
3153 result += "\n"
3154 }
3155 } else if (typeof readline == "function") {
3156 result = readline();
3157 if (result !== null) {
3158 result += "\n"
3159 }
3160 }
3161 if (!result) {
3162 return null
3163 }
3164 tty.input = intArrayFromString(result, true)
3165 }
3166 return tty.input.shift()
3167 },
3168 put_char: function(tty, val) {
3169 if (val === null || val === 10) {
3170 out(UTF8ArrayToString(tty.output, 0));
3171 tty.output = []
3172 } else {
3173 if (val != 0) tty.output.push(val)
3174 }
3175 },
3176 flush: function(tty) {
3177 if (tty.output && tty.output.length > 0) {
3178 out(UTF8ArrayToString(tty.output, 0));
3179 tty.output = []
3180 }
3181 }
3182 },
3183 default_tty1_ops: {
3184 put_char: function(tty, val) {
3185 if (val === null || val === 10) {
3186 err(UTF8ArrayToString(tty.output, 0));
3187 tty.output = []
3188 } else {
3189 if (val != 0) tty.output.push(val)
3190 }
3191 },
3192 flush: function(tty) {
3193 if (tty.output && tty.output.length > 0) {
3194 err(UTF8ArrayToString(tty.output, 0));
3195 tty.output = []
3196 }
3197 }
3198 }
3199 };
3200
3201 function zeroMemory(address, size) {
3202 HEAPU8.fill(0, address, address + size)
3203 }
3204
3205 function mmapAlloc(size) {
3206 abort()
3207 }
3208 var MEMFS = {
3209 ops_table: null,
3210 mount: function(mount) {
3211 return MEMFS.createNode(null, "/", 16384 | 511, 0)
3212 },
3213 createNode: function(parent, name, mode, dev) {
3214 if (FS.isBlkdev(mode) || FS.isFIFO(mode)) {
3215 throw new FS.ErrnoError(63)
3216 }
3217 if (!MEMFS.ops_table) {
3218 MEMFS.ops_table = {
3219 dir: {
3220 node: {
3221 getattr: MEMFS.node_ops.getattr,
3222 setattr: MEMFS.node_ops.setattr,
3223 lookup: MEMFS.node_ops.lookup,
3224 mknod: MEMFS.node_ops.mknod,
3225 rename: MEMFS.node_ops.rename,
3226 unlink: MEMFS.node_ops.unlink,
3227 rmdir: MEMFS.node_ops.rmdir,
3228 readdir: MEMFS.node_ops.readdir,
3229 symlink: MEMFS.node_ops.symlink
3230 },
3231 stream: {
3232 llseek: MEMFS.stream_ops.llseek
3233 }
3234 },
3235 file: {
3236 node: {
3237 getattr: MEMFS.node_ops.getattr,
3238 setattr: MEMFS.node_ops.setattr
3239 },
3240 stream: {
3241 llseek: MEMFS.stream_ops.llseek,
3242 read: MEMFS.stream_ops.read,
3243 write: MEMFS.stream_ops.write,
3244 allocate: MEMFS.stream_ops.allocate,
3245 mmap: MEMFS.stream_ops.mmap,
3246 msync: MEMFS.stream_ops.msync
3247 }
3248 },
3249 link: {
3250 node: {
3251 getattr: MEMFS.node_ops.getattr,
3252 setattr: MEMFS.node_ops.setattr,
3253 readlink: MEMFS.node_ops.readlink
3254 },
3255 stream: {}
3256 },
3257 chrdev: {
3258 node: {
3259 getattr: MEMFS.node_ops.getattr,
3260 setattr: MEMFS.node_ops.setattr
3261 },
3262 stream: FS.chrdev_stream_ops
3263 }
3264 }
3265 }
3266 var node = FS.createNode(parent, name, mode, dev);
3267 if (FS.isDir(node.mode)) {
3268 node.node_ops = MEMFS.ops_table.dir.node;
3269 node.stream_ops = MEMFS.ops_table.dir.stream;
3270 node.contents = {}
3271 } else if (FS.isFile(node.mode)) {
3272 node.node_ops = MEMFS.ops_table.file.node;
3273 node.stream_ops = MEMFS.ops_table.file.stream;
3274 node.usedBytes = 0;
3275 node.contents = null
3276 } else if (FS.isLink(node.mode)) {
3277 node.node_ops = MEMFS.ops_table.link.node;
3278 node.stream_ops = MEMFS.ops_table.link.stream
3279 } else if (FS.isChrdev(node.mode)) {
3280 node.node_ops = MEMFS.ops_table.chrdev.node;
3281 node.stream_ops = MEMFS.ops_table.chrdev.stream
3282 }
3283 node.timestamp = Date.now();
3284 if (parent) {
3285 parent.contents[name] = node;
3286 parent.timestamp = node.timestamp
3287 }
3288 return node
3289 },
3290 getFileDataAsTypedArray: function(node) {
3291 if (!node.contents) return new Uint8Array(0);
3292 if (node.contents.subarray) return node.contents.subarray(0, node.usedBytes);
3293 return new Uint8Array(node.contents)
3294 },
3295 expandFileStorage: function(node, newCapacity) {
3296 var prevCapacity = node.contents ? node.contents.length : 0;
3297 if (prevCapacity >= newCapacity) return;
3298 var CAPACITY_DOUBLING_MAX = 1024 * 1024;
3299 newCapacity = Math.max(newCapacity, prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2 : 1.125) >>> 0);
3300 if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256);
3301 var oldContents = node.contents;
3302 node.contents = new Uint8Array(newCapacity);
3303 if (node.usedBytes > 0) node.contents.set(oldContents.subarray(0, node.usedBytes), 0)
3304 },
3305 resizeFileStorage: function(node, newSize) {
3306 if (node.usedBytes == newSize) return;
3307 if (newSize == 0) {
3308 node.contents = null;
3309 node.usedBytes = 0
3310 } else {
3311 var oldContents = node.contents;
3312 node.contents = new Uint8Array(newSize);
3313 if (oldContents) {
3314 node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes)))
3315 }
3316 node.usedBytes = newSize
3317 }
3318 },
3319 node_ops: {
3320 getattr: function(node) {
3321 var attr = {};
3322 attr.dev = FS.isChrdev(node.mode) ? node.id : 1;
3323 attr.ino = node.id;
3324 attr.mode = node.mode;
3325 attr.nlink = 1;
3326 attr.uid = 0;
3327 attr.gid = 0;
3328 attr.rdev = node.rdev;
3329 if (FS.isDir(node.mode)) {
3330 attr.size = 4096
3331 } else if (FS.isFile(node.mode)) {
3332 attr.size = node.usedBytes
3333 } else if (FS.isLink(node.mode)) {
3334 attr.size = node.link.length
3335 } else {
3336 attr.size = 0
3337 }
3338 attr.atime = new Date(node.timestamp);
3339 attr.mtime = new Date(node.timestamp);
3340 attr.ctime = new Date(node.timestamp);
3341 attr.blksize = 4096;
3342 attr.blocks = Math.ceil(attr.size / attr.blksize);
3343 return attr
3344 },
3345 setattr: function(node, attr) {
3346 if (attr.mode !== undefined) {
3347 node.mode = attr.mode
3348 }
3349 if (attr.timestamp !== undefined) {
3350 node.timestamp = attr.timestamp
3351 }
3352 if (attr.size !== undefined) {
3353 MEMFS.resizeFileStorage(node, attr.size)
3354 }
3355 },
3356 lookup: function(parent, name) {
3357 throw FS.genericErrors[44]
3358 },
3359 mknod: function(parent, name, mode, dev) {
3360 return MEMFS.createNode(parent, name, mode, dev)
3361 },
3362 rename: function(old_node, new_dir, new_name) {
3363 if (FS.isDir(old_node.mode)) {
3364 var new_node;
3365 try {
3366 new_node = FS.lookupNode(new_dir, new_name)
3367 } catch (e) {}
3368 if (new_node) {
3369 for (var i in new_node.contents) {
3370 throw new FS.ErrnoError(55)
3371 }
3372 }
3373 }
3374 delete old_node.parent.contents[old_node.name];
3375 old_node.parent.timestamp = Date.now();
3376 old_node.name = new_name;
3377 new_dir.contents[new_name] = old_node;
3378 new_dir.timestamp = old_node.parent.timestamp;
3379 old_node.parent = new_dir
3380 },
3381 unlink: function(parent, name) {
3382 delete parent.contents[name];
3383 parent.timestamp = Date.now()
3384 },
3385 rmdir: function(parent, name) {
3386 var node = FS.lookupNode(parent, name);
3387 for (var i in node.contents) {
3388 throw new FS.ErrnoError(55)
3389 }
3390 delete parent.contents[name];
3391 parent.timestamp = Date.now()
3392 },
3393 readdir: function(node) {
3394 var entries = [".", ".."];
3395 for (var key in node.contents) {
3396 if (!node.contents.hasOwnProperty(key)) {
3397 continue
3398 }
3399 entries.push(key)
3400 }
3401 return entries
3402 },
3403 symlink: function(parent, newname, oldpath) {
3404 var node = MEMFS.createNode(parent, newname, 511 | 40960, 0);
3405 node.link = oldpath;
3406 return node
3407 },
3408 readlink: function(node) {
3409 if (!FS.isLink(node.mode)) {
3410 throw new FS.ErrnoError(28)
3411 }
3412 return node.link
3413 }
3414 },
3415 stream_ops: {
3416 read: function(stream, buffer, offset, length, position) {
3417 var contents = stream.node.contents;
3418 if (position >= stream.node.usedBytes) return 0;
3419 var size = Math.min(stream.node.usedBytes - position, length);
3420 if (size > 8 && contents.subarray) {
3421 buffer.set(contents.subarray(position, position + size), offset)
3422 } else {
3423 for (var i = 0; i < size; i++) buffer[offset + i] = contents[position + i]
3424 }
3425 return size
3426 },
3427 write: function(stream, buffer, offset, length, position, canOwn) {
3428 if (buffer.buffer === HEAP8.buffer) {
3429 canOwn = false
3430 }
3431 if (!length) return 0;
3432 var node = stream.node;
3433 node.timestamp = Date.now();
3434 if (buffer.subarray && (!node.contents || node.contents.subarray)) {
3435 if (canOwn) {
3436 node.contents = buffer.subarray(offset, offset + length);
3437 node.usedBytes = length;
3438 return length
3439 } else if (node.usedBytes === 0 && position === 0) {
3440 node.contents = buffer.slice(offset, offset + length);
3441 node.usedBytes = length;
3442 return length
3443 } else if (position + length <= node.usedBytes) {
3444 node.contents.set(buffer.subarray(offset, offset + length), position);
3445 return length
3446 }
3447 }
3448 MEMFS.expandFileStorage(node, position + length);
3449 if (node.contents.subarray && buffer.subarray) {
3450 node.contents.set(buffer.subarray(offset, offset + length), position)
3451 } else {
3452 for (var i = 0; i < length; i++) {
3453 node.contents[position + i] = buffer[offset + i]
3454 }
3455 }
3456 node.usedBytes = Math.max(node.usedBytes, position + length);
3457 return length
3458 },
3459 llseek: function(stream, offset, whence) {
3460 var position = offset;
3461 if (whence === 1) {
3462 position += stream.position
3463 } else if (whence === 2) {
3464 if (FS.isFile(stream.node.mode)) {
3465 position += stream.node.usedBytes
3466 }
3467 }
3468 if (position < 0) {
3469 throw new FS.ErrnoError(28)
3470 }
3471 return position
3472 },
3473 allocate: function(stream, offset, length) {
3474 MEMFS.expandFileStorage(stream.node, offset + length);
3475 stream.node.usedBytes = Math.max(stream.node.usedBytes, offset + length)
3476 },
3477 mmap: function(stream, length, position, prot, flags) {
3478 if (!FS.isFile(stream.node.mode)) {
3479 throw new FS.ErrnoError(43)
3480 }
3481 var ptr;
3482 var allocated;
3483 var contents = stream.node.contents;
3484 if (!(flags & 2) && contents.buffer === buffer) {
3485 allocated = false;
3486 ptr = contents.byteOffset
3487 } else {
3488 if (position > 0 || position + length < contents.length) {
3489 if (contents.subarray) {
3490 contents = contents.subarray(position, position + length)
3491 } else {
3492 contents = Array.prototype.slice.call(contents, position, position + length)
3493 }
3494 }
3495 allocated = true;
3496 ptr = mmapAlloc(length);
3497 if (!ptr) {
3498 throw new FS.ErrnoError(48)
3499 }
3500 HEAP8.set(contents, ptr)
3501 }
3502 return {
3503 ptr: ptr,
3504 allocated: allocated
3505 }
3506 },
3507 msync: function(stream, buffer, offset, length, mmapFlags) {
3508 if (!FS.isFile(stream.node.mode)) {
3509 throw new FS.ErrnoError(43)
3510 }
3511 if (mmapFlags & 2) {
3512 return 0
3513 }
3514 var bytesWritten = MEMFS.stream_ops.write(stream, buffer, 0, length, offset, false);
3515 return 0
3516 }
3517 }
3518 };
3519
3520 function asyncLoad(url, onload, onerror, noRunDep) {
3521 var dep = !noRunDep ? getUniqueRunDependency("al " + url) : "";
3522 readAsync(url, function(arrayBuffer) {
3523 assert(arrayBuffer, 'Loading data file "' + url + '" failed (no arrayBuffer).');
3524 onload(new Uint8Array(arrayBuffer));
3525 if (dep) removeRunDependency(dep)
3526 }, function(event) {
3527 if (onerror) {
3528 onerror()
3529 } else {
3530 throw 'Loading data file "' + url + '" failed.'
3531 }
3532 });
3533 if (dep) addRunDependency(dep)
3534 }
3535 var IDBFS = {
3536 dbs: {},
3537 indexedDB: () => {
3538 if (typeof indexedDB != "undefined") return indexedDB;
3539 var ret = null;
3540 if (typeof window == "object") ret = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
3541 assert(ret, "IDBFS used, but indexedDB not supported");
3542 return ret
3543 },
3544 DB_VERSION: 21,
3545 DB_STORE_NAME: "FILE_DATA",
3546 mount: function(mount) {
3547 return MEMFS.mount.apply(null, arguments)
3548 },
3549 syncfs: (mount, populate, callback) => {
3550 IDBFS.getLocalSet(mount, (err, local) => {
3551 if (err) return callback(err);
3552 IDBFS.getRemoteSet(mount, (err, remote) => {
3553 if (err) return callback(err);
3554 var src = populate ? remote : local;
3555 var dst = populate ? local : remote;
3556 IDBFS.reconcile(src, dst, callback)
3557 })
3558 })
3559 },
3560 quit: () => {
3561 Object.values(IDBFS.dbs).forEach(value => value.close());
3562 IDBFS.dbs = {}
3563 },
3564 getDB: (name, callback) => {
3565 var db = IDBFS.dbs[name];
3566 if (db) {
3567 return callback(null, db)
3568 }
3569 var req;
3570 try {
3571 req = IDBFS.indexedDB().open(name, IDBFS.DB_VERSION)
3572 } catch (e) {
3573 return callback(e)
3574 }
3575 if (!req) {
3576 return callback("Unable to connect to IndexedDB")
3577 }
3578 req.onupgradeneeded = e => {
3579 var db = e.target.result;
3580 var transaction = e.target.transaction;
3581 var fileStore;
3582 if (db.objectStoreNames.contains(IDBFS.DB_STORE_NAME)) {
3583 fileStore = transaction.objectStore(IDBFS.DB_STORE_NAME)
3584 } else {
3585 fileStore = db.createObjectStore(IDBFS.DB_STORE_NAME)
3586 }
3587 if (!fileStore.indexNames.contains("timestamp")) {
3588 fileStore.createIndex("timestamp", "timestamp", {
3589 unique: false
3590 })
3591 }
3592 };
3593 req.onsuccess = () => {
3594 db = req.result;
3595 IDBFS.dbs[name] = db;
3596 callback(null, db)
3597 };
3598 req.onerror = e => {
3599 callback(this.error);
3600 e.preventDefault()
3601 }
3602 },
3603 getLocalSet: (mount, callback) => {
3604 var entries = {};
3605
3606 function isRealDir(p) {
3607 return p !== "." && p !== ".."
3608 }
3609
3610 function toAbsolute(root) {
3611 return p => {
3612 return PATH.join2(root, p)
3613 }
3614 }
3615 var check = FS.readdir(mount.mountpoint).filter(isRealDir).map(toAbsolute(mount.mountpoint));
3616 while (check.length) {
3617 var path = check.pop();
3618 var stat;
3619 try {
3620 stat = FS.stat(path)
3621 } catch (e) {
3622 return callback(e)
3623 }
3624 if (FS.isDir(stat.mode)) {
3625 check.push.apply(check, FS.readdir(path).filter(isRealDir).map(toAbsolute(path)))
3626 }
3627 entries[path] = {
3628 "timestamp": stat.mtime
3629 }
3630 }
3631 return callback(null, {
3632 type: "local",
3633 entries: entries
3634 })
3635 },
3636 getRemoteSet: (mount, callback) => {
3637 var entries = {};
3638 IDBFS.getDB(mount.mountpoint, (err, db) => {
3639 if (err) return callback(err);
3640 try {
3641 var transaction = db.transaction([IDBFS.DB_STORE_NAME], "readonly");
3642 transaction.onerror = e => {
3643 callback(this.error);
3644 e.preventDefault()
3645 };
3646 var store = transaction.objectStore(IDBFS.DB_STORE_NAME);
3647 var index = store.index("timestamp");
3648 index.openKeyCursor().onsuccess = event => {
3649 var cursor = event.target.result;
3650 if (!cursor) {
3651 return callback(null, {
3652 type: "remote",
3653 db: db,
3654 entries: entries
3655 })
3656 }
3657 entries[cursor.primaryKey] = {
3658 "timestamp": cursor.key
3659 };
3660 cursor.continue()
3661 }
3662 } catch (e) {
3663 return callback(e)
3664 }
3665 })
3666 },
3667 loadLocalEntry: (path, callback) => {
3668 var stat, node;
3669 try {
3670 var lookup = FS.lookupPath(path);
3671 node = lookup.node;
3672 stat = FS.stat(path)
3673 } catch (e) {
3674 return callback(e)
3675 }
3676 if (FS.isDir(stat.mode)) {
3677 return callback(null, {
3678 "timestamp": stat.mtime,
3679 "mode": stat.mode
3680 })
3681 } else if (FS.isFile(stat.mode)) {
3682 node.contents = MEMFS.getFileDataAsTypedArray(node);
3683 return callback(null, {
3684 "timestamp": stat.mtime,
3685 "mode": stat.mode,
3686 "contents": node.contents
3687 })
3688 } else {
3689 return callback(new Error("node type not supported"))
3690 }
3691 },
3692 storeLocalEntry: (path, entry, callback) => {
3693 try {
3694 if (FS.isDir(entry["mode"])) {
3695 FS.mkdirTree(path, entry["mode"])
3696 } else if (FS.isFile(entry["mode"])) {
3697 FS.writeFile(path, entry["contents"], {
3698 canOwn: true
3699 })
3700 } else {
3701 return callback(new Error("node type not supported"))
3702 }
3703 FS.chmod(path, entry["mode"]);
3704 FS.utime(path, entry["timestamp"], entry["timestamp"])
3705 } catch (e) {
3706 return callback(e)
3707 }
3708 callback(null)
3709 },
3710 removeLocalEntry: (path, callback) => {
3711 try {
3712 var stat = FS.stat(path);
3713 if (FS.isDir(stat.mode)) {
3714 FS.rmdir(path)
3715 } else if (FS.isFile(stat.mode)) {
3716 FS.unlink(path)
3717 }
3718 } catch (e) {
3719 return callback(e)
3720 }
3721 callback(null)
3722 },
3723 loadRemoteEntry: (store, path, callback) => {
3724 var req = store.get(path);
3725 req.onsuccess = event => {
3726 callback(null, event.target.result)
3727 };
3728 req.onerror = e => {
3729 callback(this.error);
3730 e.preventDefault()
3731 }
3732 },
3733 storeRemoteEntry: (store, path, entry, callback) => {
3734 try {
3735 var req = store.put(entry, path)
3736 } catch (e) {
3737 callback(e);
3738 return
3739 }
3740 req.onsuccess = () => {
3741 callback(null)
3742 };
3743 req.onerror = e => {
3744 callback(this.error);
3745 e.preventDefault()
3746 }
3747 },
3748 removeRemoteEntry: (store, path, callback) => {
3749 var req = store.delete(path);
3750 req.onsuccess = () => {
3751 callback(null)
3752 };
3753 req.onerror = e => {
3754 callback(this.error);
3755 e.preventDefault()
3756 }
3757 },
3758 reconcile: (src, dst, callback) => {
3759 var total = 0;
3760 var create = [];
3761 Object.keys(src.entries).forEach(function(key) {
3762 var e = src.entries[key];
3763 var e2 = dst.entries[key];
3764 if (!e2 || e["timestamp"].getTime() != e2["timestamp"].getTime()) {
3765 create.push(key);
3766 total++
3767 }
3768 });
3769 var remove = [];
3770 Object.keys(dst.entries).forEach(function(key) {
3771 if (!src.entries[key]) {
3772 remove.push(key);
3773 total++
3774 }
3775 });
3776 if (!total) {
3777 return callback(null)
3778 }
3779 var errored = false;
3780 var db = src.type === "remote" ? src.db : dst.db;
3781 var transaction = db.transaction([IDBFS.DB_STORE_NAME], "readwrite");
3782 var store = transaction.objectStore(IDBFS.DB_STORE_NAME);
3783
3784 function done(err) {
3785 if (err && !errored) {
3786 errored = true;
3787 return callback(err)
3788 }
3789 }
3790 transaction.onerror = e => {
3791 done(this.error);
3792 e.preventDefault()
3793 };
3794 transaction.oncomplete = e => {
3795 if (!errored) {
3796 callback(null)
3797 }
3798 };
3799 create.sort().forEach(path => {
3800 if (dst.type === "local") {
3801 IDBFS.loadRemoteEntry(store, path, (err, entry) => {
3802 if (err) return done(err);
3803 IDBFS.storeLocalEntry(path, entry, done)
3804 })
3805 } else {
3806 IDBFS.loadLocalEntry(path, (err, entry) => {
3807 if (err) return done(err);
3808 IDBFS.storeRemoteEntry(store, path, entry, done)
3809 })
3810 }
3811 });
3812 remove.sort().reverse().forEach(path => {
3813 if (dst.type === "local") {
3814 IDBFS.removeLocalEntry(path, done)
3815 } else {
3816 IDBFS.removeRemoteEntry(store, path, done)
3817 }
3818 })
3819 }
3820 };
3821 var FS = {
3822 root: null,
3823 mounts: [],
3824 devices: {},
3825 streams: [],
3826 nextInode: 1,
3827 nameTable: null,
3828 currentPath: "/",
3829 initialized: false,
3830 ignorePermissions: true,
3831 ErrnoError: null,
3832 genericErrors: {},
3833 filesystems: null,
3834 syncFSRequests: 0,
3835 lookupPath: (path, opts = {}) => {
3836 path = PATH_FS.resolve(FS.cwd(), path);
3837 if (!path) return {
3838 path: "",
3839 node: null
3840 };
3841 var defaults = {
3842 follow_mount: true,
3843 recurse_count: 0
3844 };
3845 opts = Object.assign(defaults, opts);
3846 if (opts.recurse_count > 8) {
3847 throw new FS.ErrnoError(32)
3848 }
3849 var parts = PATH.normalizeArray(path.split("/").filter(p => !!p), false);
3850 var current = FS.root;
3851 var current_path = "/";
3852 for (var i = 0; i < parts.length; i++) {
3853 var islast = i === parts.length - 1;
3854 if (islast && opts.parent) {
3855 break
3856 }
3857 current = FS.lookupNode(current, parts[i]);
3858 current_path = PATH.join2(current_path, parts[i]);
3859 if (FS.isMountpoint(current)) {
3860 if (!islast || islast && opts.follow_mount) {
3861 current = current.mounted.root
3862 }
3863 }
3864 if (!islast || opts.follow) {
3865 var count = 0;
3866 while (FS.isLink(current.mode)) {
3867 var link = FS.readlink(current_path);
3868 current_path = PATH_FS.resolve(PATH.dirname(current_path), link);
3869 var lookup = FS.lookupPath(current_path, {
3870 recurse_count: opts.recurse_count + 1
3871 });
3872 current = lookup.node;
3873 if (count++ > 40) {
3874 throw new FS.ErrnoError(32)
3875 }
3876 }
3877 }
3878 }
3879 return {
3880 path: current_path,
3881 node: current
3882 }
3883 },
3884 getPath: node => {
3885 var path;
3886 while (true) {
3887 if (FS.isRoot(node)) {
3888 var mount = node.mount.mountpoint;
3889 if (!path) return mount;
3890 return mount[mount.length - 1] !== "/" ? mount + "/" + path : mount + path
3891 }
3892 path = path ? node.name + "/" + path : node.name;
3893 node = node.parent
3894 }
3895 },
3896 hashName: (parentid, name) => {
3897 var hash = 0;
3898 for (var i = 0; i < name.length; i++) {
3899 hash = (hash << 5) - hash + name.charCodeAt(i) | 0
3900 }
3901 return (parentid + hash >>> 0) % FS.nameTable.length
3902 },
3903 hashAddNode: node => {
3904 var hash = FS.hashName(node.parent.id, node.name);
3905 node.name_next = FS.nameTable[hash];
3906 FS.nameTable[hash] = node
3907 },
3908 hashRemoveNode: node => {
3909 var hash = FS.hashName(node.parent.id, node.name);
3910 if (FS.nameTable[hash] === node) {
3911 FS.nameTable[hash] = node.name_next
3912 } else {
3913 var current = FS.nameTable[hash];
3914 while (current) {
3915 if (current.name_next === node) {
3916 current.name_next = node.name_next;
3917 break
3918 }
3919 current = current.name_next
3920 }
3921 }
3922 },
3923 lookupNode: (parent, name) => {
3924 var errCode = FS.mayLookup(parent);
3925 if (errCode) {
3926 throw new FS.ErrnoError(errCode, parent)
3927 }
3928 var hash = FS.hashName(parent.id, name);
3929 for (var node = FS.nameTable[hash]; node; node = node.name_next) {
3930 var nodeName = node.name;
3931 if (node.parent.id === parent.id && nodeName === name) {
3932 return node
3933 }
3934 }
3935 return FS.lookup(parent, name)
3936 },
3937 createNode: (parent, name, mode, rdev) => {
3938 var node = new FS.FSNode(parent, name, mode, rdev);
3939 FS.hashAddNode(node);
3940 return node
3941 },
3942 destroyNode: node => {
3943 FS.hashRemoveNode(node)
3944 },
3945 isRoot: node => {
3946 return node === node.parent
3947 },
3948 isMountpoint: node => {
3949 return !!node.mounted
3950 },
3951 isFile: mode => {
3952 return (mode & 61440) === 32768
3953 },
3954 isDir: mode => {
3955 return (mode & 61440) === 16384
3956 },
3957 isLink: mode => {
3958 return (mode & 61440) === 40960
3959 },
3960 isChrdev: mode => {
3961 return (mode & 61440) === 8192
3962 },
3963 isBlkdev: mode => {
3964 return (mode & 61440) === 24576
3965 },
3966 isFIFO: mode => {
3967 return (mode & 61440) === 4096
3968 },
3969 isSocket: mode => {
3970 return (mode & 49152) === 49152
3971 },
3972 flagModes: {
3973 "r": 0,
3974 "r+": 2,
3975 "w": 577,
3976 "w+": 578,
3977 "a": 1089,
3978 "a+": 1090
3979 },
3980 modeStringToFlags: str => {
3981 var flags = FS.flagModes[str];
3982 if (typeof flags == "undefined") {
3983 throw new Error("Unknown file open mode: " + str)
3984 }
3985 return flags
3986 },
3987 flagsToPermissionString: flag => {
3988 var perms = ["r", "w", "rw"][flag & 3];
3989 if (flag & 512) {
3990 perms += "w"
3991 }
3992 return perms
3993 },
3994 nodePermissions: (node, perms) => {
3995 if (FS.ignorePermissions) {
3996 return 0
3997 }
3998 if (perms.includes("r") && !(node.mode & 292)) {
3999 return 2
4000 } else if (perms.includes("w") && !(node.mode & 146)) {
4001 return 2
4002 } else if (perms.includes("x") && !(node.mode & 73)) {
4003 return 2
4004 }
4005 return 0
4006 },
4007 mayLookup: dir => {
4008 var errCode = FS.nodePermissions(dir, "x");
4009 if (errCode) return errCode;
4010 if (!dir.node_ops.lookup) return 2;
4011 return 0
4012 },
4013 mayCreate: (dir, name) => {
4014 try {
4015 var node = FS.lookupNode(dir, name);
4016 return 20
4017 } catch (e) {}
4018 return FS.nodePermissions(dir, "wx")
4019 },
4020 mayDelete: (dir, name, isdir) => {
4021 var node;
4022 try {
4023 node = FS.lookupNode(dir, name)
4024 } catch (e) {
4025 return e.errno
4026 }
4027 var errCode = FS.nodePermissions(dir, "wx");
4028 if (errCode) {
4029 return errCode
4030 }
4031 if (isdir) {
4032 if (!FS.isDir(node.mode)) {
4033 return 54
4034 }
4035 if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) {
4036 return 10
4037 }
4038 } else {
4039 if (FS.isDir(node.mode)) {
4040 return 31
4041 }
4042 }
4043 return 0
4044 },
4045 mayOpen: (node, flags) => {
4046 if (!node) {
4047 return 44
4048 }
4049 if (FS.isLink(node.mode)) {
4050 return 32
4051 } else if (FS.isDir(node.mode)) {
4052 if (FS.flagsToPermissionString(flags) !== "r" || flags & 512) {
4053 return 31
4054 }
4055 }
4056 return FS.nodePermissions(node, FS.flagsToPermissionString(flags))
4057 },
4058 MAX_OPEN_FDS: 4096,
4059 nextfd: (fd_start = 0, fd_end = FS.MAX_OPEN_FDS) => {
4060 for (var fd = fd_start; fd <= fd_end; fd++) {
4061 if (!FS.streams[fd]) {
4062 return fd
4063 }
4064 }
4065 throw new FS.ErrnoError(33)
4066 },
4067 getStream: fd => FS.streams[fd],
4068 createStream: (stream, fd_start, fd_end) => {
4069 if (!FS.FSStream) {
4070 FS.FSStream = function() {
4071 this.shared = {}
4072 };
4073 FS.FSStream.prototype = {};
4074 Object.defineProperties(FS.FSStream.prototype, {
4075 object: {
4076 get: function() {
4077 return this.node
4078 },
4079 set: function(val) {
4080 this.node = val
4081 }
4082 },
4083 isRead: {
4084 get: function() {
4085 return (this.flags & 2097155) !== 1
4086 }
4087 },
4088 isWrite: {
4089 get: function() {
4090 return (this.flags & 2097155) !== 0
4091 }
4092 },
4093 isAppend: {
4094 get: function() {
4095 return this.flags & 1024
4096 }
4097 },
4098 flags: {
4099 get: function() {
4100 return this.shared.flags
4101 },
4102 set: function(val) {
4103 this.shared.flags = val
4104 }
4105 },
4106 position: {
4107 get: function() {
4108 return this.shared.position
4109 },
4110 set: function(val) {
4111 this.shared.position = val
4112 }
4113 }
4114 })
4115 }
4116 stream = Object.assign(new FS.FSStream, stream);
4117 var fd = FS.nextfd(fd_start, fd_end);
4118 stream.fd = fd;
4119 FS.streams[fd] = stream;
4120 return stream
4121 },
4122 closeStream: fd => {
4123 FS.streams[fd] = null
4124 },
4125 chrdev_stream_ops: {
4126 open: stream => {
4127 var device = FS.getDevice(stream.node.rdev);
4128 stream.stream_ops = device.stream_ops;
4129 if (stream.stream_ops.open) {
4130 stream.stream_ops.open(stream)
4131 }
4132 },
4133 llseek: () => {
4134 throw new FS.ErrnoError(70)
4135 }
4136 },
4137 major: dev => dev >> 8,
4138 minor: dev => dev & 255,
4139 makedev: (ma, mi) => ma << 8 | mi,
4140 registerDevice: (dev, ops) => {
4141 FS.devices[dev] = {
4142 stream_ops: ops
4143 }
4144 },
4145 getDevice: dev => FS.devices[dev],
4146 getMounts: mount => {
4147 var mounts = [];
4148 var check = [mount];
4149 while (check.length) {
4150 var m = check.pop();
4151 mounts.push(m);
4152 check.push.apply(check, m.mounts)
4153 }
4154 return mounts
4155 },
4156 syncfs: (populate, callback) => {
4157 if (typeof populate == "function") {
4158 callback = populate;
4159 populate = false
4160 }
4161 FS.syncFSRequests++;
4162 if (FS.syncFSRequests > 1) {
4163 err("warning: " + FS.syncFSRequests + " FS.syncfs operations in flight at once, probably just doing extra work")
4164 }
4165 var mounts = FS.getMounts(FS.root.mount);
4166 var completed = 0;
4167
4168 function doCallback(errCode) {
4169 FS.syncFSRequests--;
4170 return callback(errCode)
4171 }
4172
4173 function done(errCode) {
4174 if (errCode) {
4175 if (!done.errored) {
4176 done.errored = true;
4177 return doCallback(errCode)
4178 }
4179 return
4180 }
4181 if (++completed >= mounts.length) {
4182 doCallback(null)
4183 }
4184 }
4185 mounts.forEach(mount => {
4186 if (!mount.type.syncfs) {
4187 return done(null)
4188 }
4189 mount.type.syncfs(mount, populate, done)
4190 })
4191 },
4192 mount: (type, opts, mountpoint) => {
4193 var root = mountpoint === "/";
4194 var pseudo = !mountpoint;
4195 var node;
4196 if (root && FS.root) {
4197 throw new FS.ErrnoError(10)
4198 } else if (!root && !pseudo) {
4199 var lookup = FS.lookupPath(mountpoint, {
4200 follow_mount: false
4201 });
4202 mountpoint = lookup.path;
4203 node = lookup.node;
4204 if (FS.isMountpoint(node)) {
4205 throw new FS.ErrnoError(10)
4206 }
4207 if (!FS.isDir(node.mode)) {
4208 throw new FS.ErrnoError(54)
4209 }
4210 }
4211 var mount = {
4212 type: type,
4213 opts: opts,
4214 mountpoint: mountpoint,
4215 mounts: []
4216 };
4217 var mountRoot = type.mount(mount);
4218 mountRoot.mount = mount;
4219 mount.root = mountRoot;
4220 if (root) {
4221 FS.root = mountRoot
4222 } else if (node) {
4223 node.mounted = mount;
4224 if (node.mount) {
4225 node.mount.mounts.push(mount)
4226 }
4227 }
4228 return mountRoot
4229 },
4230 unmount: mountpoint => {
4231 var lookup = FS.lookupPath(mountpoint, {
4232 follow_mount: false
4233 });
4234 if (!FS.isMountpoint(lookup.node)) {
4235 throw new FS.ErrnoError(28)
4236 }
4237 var node = lookup.node;
4238 var mount = node.mounted;
4239 var mounts = FS.getMounts(mount);
4240 Object.keys(FS.nameTable).forEach(hash => {
4241 var current = FS.nameTable[hash];
4242 while (current) {
4243 var next = current.name_next;
4244 if (mounts.includes(current.mount)) {
4245 FS.destroyNode(current)
4246 }
4247 current = next
4248 }
4249 });
4250 node.mounted = null;
4251 var idx = node.mount.mounts.indexOf(mount);
4252 node.mount.mounts.splice(idx, 1)
4253 },
4254 lookup: (parent, name) => {
4255 return parent.node_ops.lookup(parent, name)
4256 },
4257 mknod: (path, mode, dev) => {
4258 var lookup = FS.lookupPath(path, {
4259 parent: true
4260 });
4261 var parent = lookup.node;
4262 var name = PATH.basename(path);
4263 if (!name || name === "." || name === "..") {
4264 throw new FS.ErrnoError(28)
4265 }
4266 var errCode = FS.mayCreate(parent, name);
4267 if (errCode) {
4268 throw new FS.ErrnoError(errCode)
4269 }
4270 if (!parent.node_ops.mknod) {
4271 throw new FS.ErrnoError(63)
4272 }
4273 return parent.node_ops.mknod(parent, name, mode, dev)
4274 },
4275 create: (path, mode) => {
4276 mode = mode !== undefined ? mode : 438;
4277 mode &= 4095;
4278 mode |= 32768;
4279 return FS.mknod(path, mode, 0)
4280 },
4281 mkdir: (path, mode) => {
4282 mode = mode !== undefined ? mode : 511;
4283 mode &= 511 | 512;
4284 mode |= 16384;
4285 return FS.mknod(path, mode, 0)
4286 },
4287 mkdirTree: (path, mode) => {
4288 var dirs = path.split("/");
4289 var d = "";
4290 for (var i = 0; i < dirs.length; ++i) {
4291 if (!dirs[i]) continue;
4292 d += "/" + dirs[i];
4293 try {
4294 FS.mkdir(d, mode)
4295 } catch (e) {
4296 if (e.errno != 20) throw e
4297 }
4298 }
4299 },
4300 mkdev: (path, mode, dev) => {
4301 if (typeof dev == "undefined") {
4302 dev = mode;
4303 mode = 438
4304 }
4305 mode |= 8192;
4306 return FS.mknod(path, mode, dev)
4307 },
4308 symlink: (oldpath, newpath) => {
4309 if (!PATH_FS.resolve(oldpath)) {
4310 throw new FS.ErrnoError(44)
4311 }
4312 var lookup = FS.lookupPath(newpath, {
4313 parent: true
4314 });
4315 var parent = lookup.node;
4316 if (!parent) {
4317 throw new FS.ErrnoError(44)
4318 }
4319 var newname = PATH.basename(newpath);
4320 var errCode = FS.mayCreate(parent, newname);
4321 if (errCode) {
4322 throw new FS.ErrnoError(errCode)
4323 }
4324 if (!parent.node_ops.symlink) {
4325 throw new FS.ErrnoError(63)
4326 }
4327 return parent.node_ops.symlink(parent, newname, oldpath)
4328 },
4329 rename: (old_path, new_path) => {
4330 var old_dirname = PATH.dirname(old_path);
4331 var new_dirname = PATH.dirname(new_path);
4332 var old_name = PATH.basename(old_path);
4333 var new_name = PATH.basename(new_path);
4334 var lookup, old_dir, new_dir;
4335 lookup = FS.lookupPath(old_path, {
4336 parent: true
4337 });
4338 old_dir = lookup.node;
4339 lookup = FS.lookupPath(new_path, {
4340 parent: true
4341 });
4342 new_dir = lookup.node;
4343 if (!old_dir || !new_dir) throw new FS.ErrnoError(44);
4344 if (old_dir.mount !== new_dir.mount) {
4345 throw new FS.ErrnoError(75)
4346 }
4347 var old_node = FS.lookupNode(old_dir, old_name);
4348 var relative = PATH_FS.relative(old_path, new_dirname);
4349 if (relative.charAt(0) !== ".") {
4350 throw new FS.ErrnoError(28)
4351 }
4352 relative = PATH_FS.relative(new_path, old_dirname);
4353 if (relative.charAt(0) !== ".") {
4354 throw new FS.ErrnoError(55)
4355 }
4356 var new_node;
4357 try {
4358 new_node = FS.lookupNode(new_dir, new_name)
4359 } catch (e) {}
4360 if (old_node === new_node) {
4361 return
4362 }
4363 var isdir = FS.isDir(old_node.mode);
4364 var errCode = FS.mayDelete(old_dir, old_name, isdir);
4365 if (errCode) {
4366 throw new FS.ErrnoError(errCode)
4367 }
4368 errCode = new_node ? FS.mayDelete(new_dir, new_name, isdir) : FS.mayCreate(new_dir, new_name);
4369 if (errCode) {
4370 throw new FS.ErrnoError(errCode)
4371 }
4372 if (!old_dir.node_ops.rename) {
4373 throw new FS.ErrnoError(63)
4374 }
4375 if (FS.isMountpoint(old_node) || new_node && FS.isMountpoint(new_node)) {
4376 throw new FS.ErrnoError(10)
4377 }
4378 if (new_dir !== old_dir) {
4379 errCode = FS.nodePermissions(old_dir, "w");
4380 if (errCode) {
4381 throw new FS.ErrnoError(errCode)
4382 }
4383 }
4384 FS.hashRemoveNode(old_node);
4385 try {
4386 old_dir.node_ops.rename(old_node, new_dir, new_name)
4387 } catch (e) {
4388 throw e
4389 } finally {
4390 FS.hashAddNode(old_node)
4391 }
4392 },
4393 rmdir: path => {
4394 var lookup = FS.lookupPath(path, {
4395 parent: true
4396 });
4397 var parent = lookup.node;
4398 var name = PATH.basename(path);
4399 var node = FS.lookupNode(parent, name);
4400 var errCode = FS.mayDelete(parent, name, true);
4401 if (errCode) {
4402 throw new FS.ErrnoError(errCode)
4403 }
4404 if (!parent.node_ops.rmdir) {
4405 throw new FS.ErrnoError(63)
4406 }
4407 if (FS.isMountpoint(node)) {
4408 throw new FS.ErrnoError(10)
4409 }
4410 parent.node_ops.rmdir(parent, name);
4411 FS.destroyNode(node)
4412 },
4413 readdir: path => {
4414 var lookup = FS.lookupPath(path, {
4415 follow: true
4416 });
4417 var node = lookup.node;
4418 if (!node.node_ops.readdir) {
4419 throw new FS.ErrnoError(54)
4420 }
4421 return node.node_ops.readdir(node)
4422 },
4423 unlink: path => {
4424 var lookup = FS.lookupPath(path, {
4425 parent: true
4426 });
4427 var parent = lookup.node;
4428 if (!parent) {
4429 throw new FS.ErrnoError(44)
4430 }
4431 var name = PATH.basename(path);
4432 var node = FS.lookupNode(parent, name);
4433 var errCode = FS.mayDelete(parent, name, false);
4434 if (errCode) {
4435 throw new FS.ErrnoError(errCode)
4436 }
4437 if (!parent.node_ops.unlink) {
4438 throw new FS.ErrnoError(63)
4439 }
4440 if (FS.isMountpoint(node)) {
4441 throw new FS.ErrnoError(10)
4442 }
4443 parent.node_ops.unlink(parent, name);
4444 FS.destroyNode(node)
4445 },
4446 readlink: path => {
4447 var lookup = FS.lookupPath(path);
4448 var link = lookup.node;
4449 if (!link) {
4450 throw new FS.ErrnoError(44)
4451 }
4452 if (!link.node_ops.readlink) {
4453 throw new FS.ErrnoError(28)
4454 }
4455 return PATH_FS.resolve(FS.getPath(link.parent), link.node_ops.readlink(link))
4456 },
4457 stat: (path, dontFollow) => {
4458 var lookup = FS.lookupPath(path, {
4459 follow: !dontFollow
4460 });
4461 var node = lookup.node;
4462 if (!node) {
4463 throw new FS.ErrnoError(44)
4464 }
4465 if (!node.node_ops.getattr) {
4466 throw new FS.ErrnoError(63)
4467 }
4468 return node.node_ops.getattr(node)
4469 },
4470 lstat: path => {
4471 return FS.stat(path, true)
4472 },
4473 chmod: (path, mode, dontFollow) => {
4474 var node;
4475 if (typeof path == "string") {
4476 var lookup = FS.lookupPath(path, {
4477 follow: !dontFollow
4478 });
4479 node = lookup.node
4480 } else {
4481 node = path
4482 }
4483 if (!node.node_ops.setattr) {
4484 throw new FS.ErrnoError(63)
4485 }
4486 node.node_ops.setattr(node, {
4487 mode: mode & 4095 | node.mode & ~4095,
4488 timestamp: Date.now()
4489 })
4490 },
4491 lchmod: (path, mode) => {
4492 FS.chmod(path, mode, true)
4493 },
4494 fchmod: (fd, mode) => {
4495 var stream = FS.getStream(fd);
4496 if (!stream) {
4497 throw new FS.ErrnoError(8)
4498 }
4499 FS.chmod(stream.node, mode)
4500 },
4501 chown: (path, uid, gid, dontFollow) => {
4502 var node;
4503 if (typeof path == "string") {
4504 var lookup = FS.lookupPath(path, {
4505 follow: !dontFollow
4506 });
4507 node = lookup.node
4508 } else {
4509 node = path
4510 }
4511 if (!node.node_ops.setattr) {
4512 throw new FS.ErrnoError(63)
4513 }
4514 node.node_ops.setattr(node, {
4515 timestamp: Date.now()
4516 })
4517 },
4518 lchown: (path, uid, gid) => {
4519 FS.chown(path, uid, gid, true)
4520 },
4521 fchown: (fd, uid, gid) => {
4522 var stream = FS.getStream(fd);
4523 if (!stream) {
4524 throw new FS.ErrnoError(8)
4525 }
4526 FS.chown(stream.node, uid, gid)
4527 },
4528 truncate: (path, len) => {
4529 if (len < 0) {
4530 throw new FS.ErrnoError(28)
4531 }
4532 var node;
4533 if (typeof path == "string") {
4534 var lookup = FS.lookupPath(path, {
4535 follow: true
4536 });
4537 node = lookup.node
4538 } else {
4539 node = path
4540 }
4541 if (!node.node_ops.setattr) {
4542 throw new FS.ErrnoError(63)
4543 }
4544 if (FS.isDir(node.mode)) {
4545 throw new FS.ErrnoError(31)
4546 }
4547 if (!FS.isFile(node.mode)) {
4548 throw new FS.ErrnoError(28)
4549 }
4550 var errCode = FS.nodePermissions(node, "w");
4551 if (errCode) {
4552 throw new FS.ErrnoError(errCode)
4553 }
4554 node.node_ops.setattr(node, {
4555 size: len,
4556 timestamp: Date.now()
4557 })
4558 },
4559 ftruncate: (fd, len) => {
4560 var stream = FS.getStream(fd);
4561 if (!stream) {
4562 throw new FS.ErrnoError(8)
4563 }
4564 if ((stream.flags & 2097155) === 0) {
4565 throw new FS.ErrnoError(28)
4566 }
4567 FS.truncate(stream.node, len)
4568 },
4569 utime: (path, atime, mtime) => {
4570 var lookup = FS.lookupPath(path, {
4571 follow: true
4572 });
4573 var node = lookup.node;
4574 node.node_ops.setattr(node, {
4575 timestamp: Math.max(atime, mtime)
4576 })
4577 },
4578 open: (path, flags, mode) => {
4579 if (path === "") {
4580 throw new FS.ErrnoError(44)
4581 }
4582 flags = typeof flags == "string" ? FS.modeStringToFlags(flags) : flags;
4583 mode = typeof mode == "undefined" ? 438 : mode;
4584 if (flags & 64) {
4585 mode = mode & 4095 | 32768
4586 } else {
4587 mode = 0
4588 }
4589 var node;
4590 if (typeof path == "object") {
4591 node = path
4592 } else {
4593 path = PATH.normalize(path);
4594 try {
4595 var lookup = FS.lookupPath(path, {
4596 follow: !(flags & 131072)
4597 });
4598 node = lookup.node
4599 } catch (e) {}
4600 }
4601 var created = false;
4602 if (flags & 64) {
4603 if (node) {
4604 if (flags & 128) {
4605 throw new FS.ErrnoError(20)
4606 }
4607 } else {
4608 node = FS.mknod(path, mode, 0);
4609 created = true
4610 }
4611 }
4612 if (!node) {
4613 throw new FS.ErrnoError(44)
4614 }
4615 if (FS.isChrdev(node.mode)) {
4616 flags &= ~512
4617 }
4618 if (flags & 65536 && !FS.isDir(node.mode)) {
4619 throw new FS.ErrnoError(54)
4620 }
4621 if (!created) {
4622 var errCode = FS.mayOpen(node, flags);
4623 if (errCode) {
4624 throw new FS.ErrnoError(errCode)
4625 }
4626 }
4627 if (flags & 512 && !created) {
4628 FS.truncate(node, 0)
4629 }
4630 flags &= ~(128 | 512 | 131072);
4631 var stream = FS.createStream({
4632 node: node,
4633 path: FS.getPath(node),
4634 flags: flags,
4635 seekable: true,
4636 position: 0,
4637 stream_ops: node.stream_ops,
4638 ungotten: [],
4639 error: false
4640 });
4641 if (stream.stream_ops.open) {
4642 stream.stream_ops.open(stream)
4643 }
4644 if (Module["logReadFiles"] && !(flags & 1)) {
4645 if (!FS.readFiles) FS.readFiles = {};
4646 if (!(path in FS.readFiles)) {
4647 FS.readFiles[path] = 1
4648 }
4649 }
4650 return stream
4651 },
4652 close: stream => {
4653 if (FS.isClosed(stream)) {
4654 throw new FS.ErrnoError(8)
4655 }
4656 if (stream.getdents) stream.getdents = null;
4657 try {
4658 if (stream.stream_ops.close) {
4659 stream.stream_ops.close(stream)
4660 }
4661 } catch (e) {
4662 throw e
4663 } finally {
4664 FS.closeStream(stream.fd)
4665 }
4666 stream.fd = null
4667 },
4668 isClosed: stream => {
4669 return stream.fd === null
4670 },
4671 llseek: (stream, offset, whence) => {
4672 if (FS.isClosed(stream)) {
4673 throw new FS.ErrnoError(8)
4674 }
4675 if (!stream.seekable || !stream.stream_ops.llseek) {
4676 throw new FS.ErrnoError(70)
4677 }
4678 if (whence != 0 && whence != 1 && whence != 2) {
4679 throw new FS.ErrnoError(28)
4680 }
4681 stream.position = stream.stream_ops.llseek(stream, offset, whence);
4682 stream.ungotten = [];
4683 return stream.position
4684 },
4685 read: (stream, buffer, offset, length, position) => {
4686 if (length < 0 || position < 0) {
4687 throw new FS.ErrnoError(28)
4688 }
4689 if (FS.isClosed(stream)) {
4690 throw new FS.ErrnoError(8)
4691 }
4692 if ((stream.flags & 2097155) === 1) {
4693 throw new FS.ErrnoError(8)
4694 }
4695 if (FS.isDir(stream.node.mode)) {
4696 throw new FS.ErrnoError(31)
4697 }
4698 if (!stream.stream_ops.read) {
4699 throw new FS.ErrnoError(28)
4700 }
4701 var seeking = typeof position != "undefined";
4702 if (!seeking) {
4703 position = stream.position
4704 } else if (!stream.seekable) {
4705 throw new FS.ErrnoError(70)
4706 }
4707 var bytesRead = stream.stream_ops.read(stream, buffer, offset, length, position);
4708 if (!seeking) stream.position += bytesRead;
4709 return bytesRead
4710 },
4711 write: (stream, buffer, offset, length, position, canOwn) => {
4712 if (length < 0 || position < 0) {
4713 throw new FS.ErrnoError(28)
4714 }
4715 if (FS.isClosed(stream)) {
4716 throw new FS.ErrnoError(8)
4717 }
4718 if ((stream.flags & 2097155) === 0) {
4719 throw new FS.ErrnoError(8)
4720 }
4721 if (FS.isDir(stream.node.mode)) {
4722 throw new FS.ErrnoError(31)
4723 }
4724 if (!stream.stream_ops.write) {
4725 throw new FS.ErrnoError(28)
4726 }
4727 if (stream.seekable && stream.flags & 1024) {
4728 FS.llseek(stream, 0, 2)
4729 }
4730 var seeking = typeof position != "undefined";
4731 if (!seeking) {
4732 position = stream.position
4733 } else if (!stream.seekable) {
4734 throw new FS.ErrnoError(70)
4735 }
4736 var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position, canOwn);
4737 if (!seeking) stream.position += bytesWritten;
4738 return bytesWritten
4739 },
4740 allocate: (stream, offset, length) => {
4741 if (FS.isClosed(stream)) {
4742 throw new FS.ErrnoError(8)
4743 }
4744 if (offset < 0 || length <= 0) {
4745 throw new FS.ErrnoError(28)
4746 }
4747 if ((stream.flags & 2097155) === 0) {
4748 throw new FS.ErrnoError(8)
4749 }
4750 if (!FS.isFile(stream.node.mode) && !FS.isDir(stream.node.mode)) {
4751 throw new FS.ErrnoError(43)
4752 }
4753 if (!stream.stream_ops.allocate) {
4754 throw new FS.ErrnoError(138)
4755 }
4756 stream.stream_ops.allocate(stream, offset, length)
4757 },
4758 mmap: (stream, length, position, prot, flags) => {
4759 if ((prot & 2) !== 0 && (flags & 2) === 0 && (stream.flags & 2097155) !== 2) {
4760 throw new FS.ErrnoError(2)
4761 }
4762 if ((stream.flags & 2097155) === 1) {
4763 throw new FS.ErrnoError(2)
4764 }
4765 if (!stream.stream_ops.mmap) {
4766 throw new FS.ErrnoError(43)
4767 }
4768 return stream.stream_ops.mmap(stream, length, position, prot, flags)
4769 },
4770 msync: (stream, buffer, offset, length, mmapFlags) => {
4771 if (!stream || !stream.stream_ops.msync) {
4772 return 0
4773 }
4774 return stream.stream_ops.msync(stream, buffer, offset, length, mmapFlags)
4775 },
4776 munmap: stream => 0,
4777 ioctl: (stream, cmd, arg) => {
4778 if (!stream.stream_ops.ioctl) {
4779 throw new FS.ErrnoError(59)
4780 }
4781 return stream.stream_ops.ioctl(stream, cmd, arg)
4782 },
4783 readFile: (path, opts = {}) => {
4784 opts.flags = opts.flags || 0;
4785 opts.encoding = opts.encoding || "binary";
4786 if (opts.encoding !== "utf8" && opts.encoding !== "binary") {
4787 throw new Error('Invalid encoding type "' + opts.encoding + '"')
4788 }
4789 var ret;
4790 var stream = FS.open(path, opts.flags);
4791 var stat = FS.stat(path);
4792 var length = stat.size;
4793 var buf = new Uint8Array(length);
4794 FS.read(stream, buf, 0, length, 0);
4795 if (opts.encoding === "utf8") {
4796 ret = UTF8ArrayToString(buf, 0)
4797 } else if (opts.encoding === "binary") {
4798 ret = buf
4799 }
4800 FS.close(stream);
4801 return ret
4802 },
4803 writeFile: (path, data, opts = {}) => {
4804 opts.flags = opts.flags || 577;
4805 var stream = FS.open(path, opts.flags, opts.mode);
4806 if (typeof data == "string") {
4807 var buf = new Uint8Array(lengthBytesUTF8(data) + 1);
4808 var actualNumBytes = stringToUTF8Array(data, buf, 0, buf.length);
4809 FS.write(stream, buf, 0, actualNumBytes, undefined, opts.canOwn)
4810 } else if (ArrayBuffer.isView(data)) {
4811 FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn)
4812 } else {
4813 throw new Error("Unsupported data type")
4814 }
4815 FS.close(stream)
4816 },
4817 cwd: () => FS.currentPath,
4818 chdir: path => {
4819 var lookup = FS.lookupPath(path, {
4820 follow: true
4821 });
4822 if (lookup.node === null) {
4823 throw new FS.ErrnoError(44)
4824 }
4825 if (!FS.isDir(lookup.node.mode)) {
4826 throw new FS.ErrnoError(54)
4827 }
4828 var errCode = FS.nodePermissions(lookup.node, "x");
4829 if (errCode) {
4830 throw new FS.ErrnoError(errCode)
4831 }
4832 FS.currentPath = lookup.path
4833 },
4834 createDefaultDirectories: () => {
4835 FS.mkdir("/tmp");
4836 FS.mkdir("/home");
4837 FS.mkdir("/home/web_user")
4838 },
4839 createDefaultDevices: () => {
4840 FS.mkdir("/dev");
4841 FS.registerDevice(FS.makedev(1, 3), {
4842 read: () => 0,
4843 write: (stream, buffer, offset, length, pos) => length
4844 });
4845 FS.mkdev("/dev/null", FS.makedev(1, 3));
4846 TTY.register(FS.makedev(5, 0), TTY.default_tty_ops);
4847 TTY.register(FS.makedev(6, 0), TTY.default_tty1_ops);
4848 FS.mkdev("/dev/tty", FS.makedev(5, 0));
4849 FS.mkdev("/dev/tty1", FS.makedev(6, 0));
4850 var random_device = getRandomDevice();
4851 FS.createDevice("/dev", "random", random_device);
4852 FS.createDevice("/dev", "urandom", random_device);
4853 FS.mkdir("/dev/shm");
4854 FS.mkdir("/dev/shm/tmp")
4855 },
4856 createSpecialDirectories: () => {
4857 FS.mkdir("/proc");
4858 var proc_self = FS.mkdir("/proc/self");
4859 FS.mkdir("/proc/self/fd");
4860 FS.mount({
4861 mount: () => {
4862 var node = FS.createNode(proc_self, "fd", 16384 | 511, 73);
4863 node.node_ops = {
4864 lookup: (parent, name) => {
4865 var fd = +name;
4866 var stream = FS.getStream(fd);
4867 if (!stream) throw new FS.ErrnoError(8);
4868 var ret = {
4869 parent: null,
4870 mount: {
4871 mountpoint: "fake"
4872 },
4873 node_ops: {
4874 readlink: () => stream.path
4875 }
4876 };
4877 ret.parent = ret;
4878 return ret
4879 }
4880 };
4881 return node
4882 }
4883 }, {}, "/proc/self/fd")
4884 },
4885 createStandardStreams: () => {
4886 if (Module["stdin"]) {
4887 FS.createDevice("/dev", "stdin", Module["stdin"])
4888 } else {
4889 FS.symlink("/dev/tty", "/dev/stdin")
4890 }
4891 if (Module["stdout"]) {
4892 FS.createDevice("/dev", "stdout", null, Module["stdout"])
4893 } else {
4894 FS.symlink("/dev/tty", "/dev/stdout")
4895 }
4896 if (Module["stderr"]) {
4897 FS.createDevice("/dev", "stderr", null, Module["stderr"])
4898 } else {
4899 FS.symlink("/dev/tty1", "/dev/stderr")
4900 }
4901 var stdin = FS.open("/dev/stdin", 0);
4902 var stdout = FS.open("/dev/stdout", 1);
4903 var stderr = FS.open("/dev/stderr", 1)
4904 },
4905 ensureErrnoError: () => {
4906 if (FS.ErrnoError) return;
4907 FS.ErrnoError = function ErrnoError(errno, node) {
4908 this.node = node;
4909 this.setErrno = function(errno) {
4910 this.errno = errno
4911 };
4912 this.setErrno(errno);
4913 this.message = "FS error"
4914 };
4915 FS.ErrnoError.prototype = new Error;
4916 FS.ErrnoError.prototype.constructor = FS.ErrnoError;
4917 [44].forEach(code => {
4918 FS.genericErrors[code] = new FS.ErrnoError(code);
4919 FS.genericErrors[code].stack = "<generic error, no stack>"
4920 })
4921 },
4922 staticInit: () => {
4923 FS.ensureErrnoError();
4924 FS.nameTable = new Array(4096);
4925 FS.mount(MEMFS, {}, "/");
4926 FS.createDefaultDirectories();
4927 FS.createDefaultDevices();
4928 FS.createSpecialDirectories();
4929 FS.filesystems = {
4930 "MEMFS": MEMFS,
4931 "IDBFS": IDBFS
4932 }
4933 },
4934 init: (input, output, error) => {
4935 FS.init.initialized = true;
4936 FS.ensureErrnoError();
4937 Module["stdin"] = input || Module["stdin"];
4938 Module["stdout"] = output || Module["stdout"];
4939 Module["stderr"] = error || Module["stderr"];
4940 FS.createStandardStreams()
4941 },
4942 quit: () => {
4943 FS.init.initialized = false;
4944 for (var i = 0; i < FS.streams.length; i++) {
4945 var stream = FS.streams[i];
4946 if (!stream) {
4947 continue
4948 }
4949 FS.close(stream)
4950 }
4951 },
4952 getMode: (canRead, canWrite) => {
4953 var mode = 0;
4954 if (canRead) mode |= 292 | 73;
4955 if (canWrite) mode |= 146;
4956 return mode
4957 },
4958 findObject: (path, dontResolveLastLink) => {
4959 var ret = FS.analyzePath(path, dontResolveLastLink);
4960 if (ret.exists) {
4961 return ret.object
4962 } else {
4963 return null
4964 }
4965 },
4966 analyzePath: (path, dontResolveLastLink) => {
4967 try {
4968 var lookup = FS.lookupPath(path, {
4969 follow: !dontResolveLastLink
4970 });
4971 path = lookup.path
4972 } catch (e) {}
4973 var ret = {
4974 isRoot: false,
4975 exists: false,
4976 error: 0,
4977 name: null,
4978 path: null,
4979 object: null,
4980 parentExists: false,
4981 parentPath: null,
4982 parentObject: null
4983 };
4984 try {
4985 var lookup = FS.lookupPath(path, {
4986 parent: true
4987 });
4988 ret.parentExists = true;
4989 ret.parentPath = lookup.path;
4990 ret.parentObject = lookup.node;
4991 ret.name = PATH.basename(path);
4992 lookup = FS.lookupPath(path, {
4993 follow: !dontResolveLastLink
4994 });
4995 ret.exists = true;
4996 ret.path = lookup.path;
4997 ret.object = lookup.node;
4998 ret.name = lookup.node.name;
4999 ret.isRoot = lookup.path === "/"
5000 } catch (e) {
5001 ret.error = e.errno
5002 }
5003 return ret
5004 },
5005 createPath: (parent, path, canRead, canWrite) => {
5006 parent = typeof parent == "string" ? parent : FS.getPath(parent);
5007 var parts = path.split("/").reverse();
5008 while (parts.length) {
5009 var part = parts.pop();
5010 if (!part) continue;
5011 var current = PATH.join2(parent, part);
5012 try {
5013 FS.mkdir(current)
5014 } catch (e) {}
5015 parent = current
5016 }
5017 return current
5018 },
5019 createFile: (parent, name, properties, canRead, canWrite) => {
5020 var path = PATH.join2(typeof parent == "string" ? parent : FS.getPath(parent), name);
5021 var mode = FS.getMode(canRead, canWrite);
5022 return FS.create(path, mode)
5023 },
5024 createDataFile: (parent, name, data, canRead, canWrite, canOwn) => {
5025 var path = name;
5026 if (parent) {
5027 parent = typeof parent == "string" ? parent : FS.getPath(parent);
5028 path = name ? PATH.join2(parent, name) : parent
5029 }
5030 var mode = FS.getMode(canRead, canWrite);
5031 var node = FS.create(path, mode);
5032 if (data) {
5033 if (typeof data == "string") {
5034 var arr = new Array(data.length);
5035 for (var i = 0, len = data.length; i < len; ++i) arr[i] = data.charCodeAt(i);
5036 data = arr
5037 }
5038 FS.chmod(node, mode | 146);
5039 var stream = FS.open(node, 577);
5040 FS.write(stream, data, 0, data.length, 0, canOwn);
5041 FS.close(stream);
5042 FS.chmod(node, mode)
5043 }
5044 return node
5045 },
5046 createDevice: (parent, name, input, output) => {
5047 var path = PATH.join2(typeof parent == "string" ? parent : FS.getPath(parent), name);
5048 var mode = FS.getMode(!!input, !!output);
5049 if (!FS.createDevice.major) FS.createDevice.major = 64;
5050 var dev = FS.makedev(FS.createDevice.major++, 0);
5051 FS.registerDevice(dev, {
5052 open: stream => {
5053 stream.seekable = false
5054 },
5055 close: stream => {
5056 if (output && output.buffer && output.buffer.length) {
5057 output(10)
5058 }
5059 },
5060 read: (stream, buffer, offset, length, pos) => {
5061 var bytesRead = 0;
5062 for (var i = 0; i < length; i++) {
5063 var result;
5064 try {
5065 result = input()
5066 } catch (e) {
5067 throw new FS.ErrnoError(29)
5068 }
5069 if (result === undefined && bytesRead === 0) {
5070 throw new FS.ErrnoError(6)
5071 }
5072 if (result === null || result === undefined) break;
5073 bytesRead++;
5074 buffer[offset + i] = result
5075 }
5076 if (bytesRead) {
5077 stream.node.timestamp = Date.now()
5078 }
5079 return bytesRead
5080 },
5081 write: (stream, buffer, offset, length, pos) => {
5082 for (var i = 0; i < length; i++) {
5083 try {
5084 output(buffer[offset + i])
5085 } catch (e) {
5086 throw new FS.ErrnoError(29)
5087 }
5088 }
5089 if (length) {
5090 stream.node.timestamp = Date.now()
5091 }
5092 return i
5093 }
5094 });
5095 return FS.mkdev(path, mode, dev)
5096 },
5097 forceLoadFile: obj => {
5098 if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true;
5099 if (typeof XMLHttpRequest != "undefined") {
5100 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.")
5101 } else if (read_) {
5102 try {
5103 obj.contents = intArrayFromString(read_(obj.url), true);
5104 obj.usedBytes = obj.contents.length
5105 } catch (e) {
5106 throw new FS.ErrnoError(29)
5107 }
5108 } else {
5109 throw new Error("Cannot load without read() or XMLHttpRequest.")
5110 }
5111 },
5112 createLazyFile: (parent, name, url, canRead, canWrite) => {
5113 function LazyUint8Array() {
5114 this.lengthKnown = false;
5115 this.chunks = []
5116 }
5117 LazyUint8Array.prototype.get = function LazyUint8Array_get(idx) {
5118 if (idx > this.length - 1 || idx < 0) {
5119 return undefined
5120 }
5121 var chunkOffset = idx % this.chunkSize;
5122 var chunkNum = idx / this.chunkSize | 0;
5123 return this.getter(chunkNum)[chunkOffset]
5124 };
5125 LazyUint8Array.prototype.setDataGetter = function LazyUint8Array_setDataGetter(getter) {
5126 this.getter = getter
5127 };
5128 LazyUint8Array.prototype.cacheLength = function LazyUint8Array_cacheLength() {
5129 var xhr = new XMLHttpRequest;
5130 xhr.open("HEAD", url, false);
5131 xhr.send(null);
5132 if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status);
5133 var datalength = Number(xhr.getResponseHeader("Content-length"));
5134 var header;
5135 var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes";
5136 var usesGzip = (header = xhr.getResponseHeader("Content-Encoding")) && header === "gzip";
5137 var chunkSize = 1024 * 1024;
5138 if (!hasByteServing) chunkSize = datalength;
5139 var doXHR = (from, to) => {
5140 if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!");
5141 if (to > datalength - 1) throw new Error("only " + datalength + " bytes available! programmer error!");
5142 var xhr = new XMLHttpRequest;
5143 xhr.open("GET", url, false);
5144 if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to);
5145 xhr.responseType = "arraybuffer";
5146 if (xhr.overrideMimeType) {
5147 xhr.overrideMimeType("text/plain; charset=x-user-defined")
5148 }
5149 xhr.send(null);
5150 if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status);
5151 if (xhr.response !== undefined) {
5152 return new Uint8Array(xhr.response || [])
5153 } else {
5154 return intArrayFromString(xhr.responseText || "", true)
5155 }
5156 };
5157 var lazyArray = this;
5158 lazyArray.setDataGetter(chunkNum => {
5159 var start = chunkNum * chunkSize;
5160 var end = (chunkNum + 1) * chunkSize - 1;
5161 end = Math.min(end, datalength - 1);
5162 if (typeof lazyArray.chunks[chunkNum] == "undefined") {
5163 lazyArray.chunks[chunkNum] = doXHR(start, end)
5164 }
5165 if (typeof lazyArray.chunks[chunkNum] == "undefined") throw new Error("doXHR failed!");
5166 return lazyArray.chunks[chunkNum]
5167 });
5168 if (usesGzip || !datalength) {
5169 chunkSize = datalength = 1;
5170 datalength = this.getter(0).length;
5171 chunkSize = datalength;
5172 out("LazyFiles on gzip forces download of the whole file when length is accessed")
5173 }
5174 this._length = datalength;
5175 this._chunkSize = chunkSize;
5176 this.lengthKnown = true
5177 };
5178 if (typeof XMLHttpRequest != "undefined") {
5179 if (!ENVIRONMENT_IS_WORKER) throw "Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";
5180 var lazyArray = new LazyUint8Array;
5181 Object.defineProperties(lazyArray, {
5182 length: {
5183 get: function() {
5184 if (!this.lengthKnown) {
5185 this.cacheLength()
5186 }
5187 return this._length
5188 }
5189 },
5190 chunkSize: {
5191 get: function() {
5192 if (!this.lengthKnown) {
5193 this.cacheLength()
5194 }
5195 return this._chunkSize
5196 }
5197 }
5198 });
5199 var properties = {
5200 isDevice: false,
5201 contents: lazyArray
5202 }
5203 } else {
5204 var properties = {
5205 isDevice: false,
5206 url: url
5207 }
5208 }
5209 var node = FS.createFile(parent, name, properties, canRead, canWrite);
5210 if (properties.contents) {
5211 node.contents = properties.contents
5212 } else if (properties.url) {
5213 node.contents = null;
5214 node.url = properties.url
5215 }
5216 Object.defineProperties(node, {
5217 usedBytes: {
5218 get: function() {
5219 return this.contents.length
5220 }
5221 }
5222 });
5223 var stream_ops = {};
5224 var keys = Object.keys(node.stream_ops);
5225 keys.forEach(key => {
5226 var fn = node.stream_ops[key];
5227 stream_ops[key] = function forceLoadLazyFile() {
5228 FS.forceLoadFile(node);
5229 return fn.apply(null, arguments)
5230 }
5231 });
5232
5233 function writeChunks(stream, buffer, offset, length, position) {
5234 var contents = stream.node.contents;
5235 if (position >= contents.length) return 0;
5236 var size = Math.min(contents.length - position, length);
5237 if (contents.slice) {
5238 for (var i = 0; i < size; i++) {
5239 buffer[offset + i] = contents[position + i]
5240 }
5241 } else {
5242 for (var i = 0; i < size; i++) {
5243 buffer[offset + i] = contents.get(position + i)
5244 }
5245 }
5246 return size
5247 }
5248 stream_ops.read = (stream, buffer, offset, length, position) => {
5249 FS.forceLoadFile(node);
5250 return writeChunks(stream, buffer, offset, length, position)
5251 };
5252 stream_ops.mmap = (stream, length, position, prot, flags) => {
5253 FS.forceLoadFile(node);
5254 var ptr = mmapAlloc(length);
5255 if (!ptr) {
5256 throw new FS.ErrnoError(48)
5257 }
5258 writeChunks(stream, HEAP8, ptr, length, position);
5259 return {
5260 ptr: ptr,
5261 allocated: true
5262 }
5263 };
5264 node.stream_ops = stream_ops;
5265 return node
5266 },
5267 createPreloadedFile: (parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) => {
5268 var fullname = name ? PATH_FS.resolve(PATH.join2(parent, name)) : parent;
5269 var dep = getUniqueRunDependency("cp " + fullname);
5270
5271 function processData(byteArray) {
5272 function finish(byteArray) {
5273 if (preFinish) preFinish();
5274 if (!dontCreateFile) {
5275 FS.createDataFile(parent, name, byteArray, canRead, canWrite, canOwn)
5276 }
5277 if (onload) onload();
5278 removeRunDependency(dep)
5279 }
5280 if (Browser.handledByPreloadPlugin(byteArray, fullname, finish, () => {
5281 if (onerror) onerror();
5282 removeRunDependency(dep)
5283 })) {
5284 return
5285 }
5286 finish(byteArray)
5287 }
5288 addRunDependency(dep);
5289 if (typeof url == "string") {
5290 asyncLoad(url, byteArray => processData(byteArray), onerror)
5291 } else {
5292 processData(url)
5293 }
5294 },
5295 indexedDB: () => {
5296 return window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB
5297 },
5298 DB_NAME: () => {
5299 return "EM_FS_" + window.location.pathname
5300 },
5301 DB_VERSION: 20,
5302 DB_STORE_NAME: "FILE_DATA",
5303 saveFilesToDB: (paths, onload, onerror) => {
5304 onload = onload || (() => {});
5305 onerror = onerror || (() => {});
5306 var indexedDB = FS.indexedDB();
5307 try {
5308 var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION)
5309 } catch (e) {
5310 return onerror(e)
5311 }
5312 openRequest.onupgradeneeded = () => {
5313 out("creating db");
5314 var db = openRequest.result;
5315 db.createObjectStore(FS.DB_STORE_NAME)
5316 };
5317 openRequest.onsuccess = () => {
5318 var db = openRequest.result;
5319 var transaction = db.transaction([FS.DB_STORE_NAME], "readwrite");
5320 var files = transaction.objectStore(FS.DB_STORE_NAME);
5321 var ok = 0,
5322 fail = 0,
5323 total = paths.length;
5324
5325 function finish() {
5326 if (fail == 0) onload();
5327 else onerror()
5328 }
5329 paths.forEach(path => {
5330 var putRequest = files.put(FS.analyzePath(path).object.contents, path);
5331 putRequest.onsuccess = () => {
5332 ok++;
5333 if (ok + fail == total) finish()
5334 };
5335 putRequest.onerror = () => {
5336 fail++;
5337 if (ok + fail == total) finish()
5338 }
5339 });
5340 transaction.onerror = onerror
5341 };
5342 openRequest.onerror = onerror
5343 },
5344 loadFilesFromDB: (paths, onload, onerror) => {
5345 onload = onload || (() => {});
5346 onerror = onerror || (() => {});
5347 var indexedDB = FS.indexedDB();
5348 try {
5349 var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION)
5350 } catch (e) {
5351 return onerror(e)
5352 }
5353 openRequest.onupgradeneeded = onerror;
5354 openRequest.onsuccess = () => {
5355 var db = openRequest.result;
5356 try {
5357 var transaction = db.transaction([FS.DB_STORE_NAME], "readonly")
5358 } catch (e) {
5359 onerror(e);
5360 return
5361 }
5362 var files = transaction.objectStore(FS.DB_STORE_NAME);
5363 var ok = 0,
5364 fail = 0,
5365 total = paths.length;
5366
5367 function finish() {
5368 if (fail == 0) onload();
5369 else onerror()
5370 }
5371 paths.forEach(path => {
5372 var getRequest = files.get(path);
5373 getRequest.onsuccess = () => {
5374 if (FS.analyzePath(path).exists) {
5375 FS.unlink(path)
5376 }
5377 FS.createDataFile(PATH.dirname(path), PATH.basename(path), getRequest.result, true, true, true);
5378 ok++;
5379 if (ok + fail == total) finish()
5380 };
5381 getRequest.onerror = () => {
5382 fail++;
5383 if (ok + fail == total) finish()
5384 }
5385 });
5386 transaction.onerror = onerror
5387 };
5388 openRequest.onerror = onerror
5389 }
5390 };
5391
5392 function _emscripten_set_main_loop_timing(mode, value) {
5393 Browser.mainLoop.timingMode = mode;
5394 Browser.mainLoop.timingValue = value;
5395 if (!Browser.mainLoop.func) {
5396 return 1
5397 }
5398 if (!Browser.mainLoop.running) {
5399 Browser.mainLoop.running = true
5400 }
5401 if (mode == 0) {
5402 Browser.mainLoop.scheduler = function Browser_mainLoop_scheduler_setTimeout() {
5403 var timeUntilNextTick = Math.max(0, Browser.mainLoop.tickStartTime + value - _emscripten_get_now()) | 0;
5404 setTimeout(Browser.mainLoop.runner, timeUntilNextTick)
5405 };
5406 Browser.mainLoop.method = "timeout"
5407 } else if (mode == 1) {
5408 Browser.mainLoop.scheduler = function Browser_mainLoop_scheduler_rAF() {
5409 Browser.requestAnimationFrame(Browser.mainLoop.runner)
5410 };
5411 Browser.mainLoop.method = "rAF"
5412 } else if (mode == 2) {
5413 if (typeof setImmediate == "undefined") {
5414 var setImmediates = [];
5415 var emscriptenMainLoopMessageId = "setimmediate";
5416 var Browser_setImmediate_messageHandler = function(event) {
5417 if (event.data === emscriptenMainLoopMessageId || event.data.target === emscriptenMainLoopMessageId) {
5418 event.stopPropagation();
5419 setImmediates.shift()()
5420 }
5421 };
5422 addEventListener("message", Browser_setImmediate_messageHandler, true);
5423 setImmediate = function Browser_emulated_setImmediate(func) {
5424 setImmediates.push(func);
5425 if (ENVIRONMENT_IS_WORKER) {
5426 if (Module["setImmediates"] === undefined) Module["setImmediates"] = [];
5427 Module["setImmediates"].push(func);
5428 postMessage({
5429 target: emscriptenMainLoopMessageId
5430 })
5431 } else postMessage(emscriptenMainLoopMessageId, "*")
5432 }
5433 }
5434 Browser.mainLoop.scheduler = function Browser_mainLoop_scheduler_setImmediate() {
5435 setImmediate(Browser.mainLoop.runner)
5436 };
5437 Browser.mainLoop.method = "immediate"
5438 }
5439 return 0
5440 }
5441 var _emscripten_get_now;
5442 if (ENVIRONMENT_IS_NODE) {
5443 _emscripten_get_now = () => {
5444 var t = process["hrtime"]();
5445 return t[0] * 1e3 + t[1] / 1e6
5446 }
5447 } else _emscripten_get_now = () => performance.now();
5448
5449 function _exit(status) {
5450 exit(status)
5451 }
5452
5453 function maybeExit() {}
5454
5455 function setMainLoop(browserIterationFunc, fps, simulateInfiniteLoop, arg, noSetTiming) {
5456 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.");
5457 Browser.mainLoop.func = browserIterationFunc;
5458 Browser.mainLoop.arg = arg;
5459 var thisMainLoopId = Browser.mainLoop.currentlyRunningMainloop;
5460
5461 function checkIsRunning() {
5462 if (thisMainLoopId < Browser.mainLoop.currentlyRunningMainloop) {
5463 maybeExit();
5464 return false
5465 }
5466 return true
5467 }
5468 Browser.mainLoop.running = false;
5469 Browser.mainLoop.runner = function Browser_mainLoop_runner() {
5470 if (ABORT) return;
5471 if (Browser.mainLoop.queue.length > 0) {
5472 var start = Date.now();
5473 var blocker = Browser.mainLoop.queue.shift();
5474 blocker.func(blocker.arg);
5475 if (Browser.mainLoop.remainingBlockers) {
5476 var remaining = Browser.mainLoop.remainingBlockers;
5477 var next = remaining % 1 == 0 ? remaining - 1 : Math.floor(remaining);
5478 if (blocker.counted) {
5479 Browser.mainLoop.remainingBlockers = next
5480 } else {
5481 next = next + .5;
5482 Browser.mainLoop.remainingBlockers = (8 * remaining + next) / 9
5483 }
5484 }
5485 out('main loop blocker "' + blocker.name + '" took ' + (Date.now() - start) + " ms");
5486 Browser.mainLoop.updateStatus();
5487 if (!checkIsRunning()) return;
5488 setTimeout(Browser.mainLoop.runner, 0);
5489 return
5490 }
5491 if (!checkIsRunning()) return;
5492 Browser.mainLoop.currentFrameNumber = Browser.mainLoop.currentFrameNumber + 1 | 0;
5493 if (Browser.mainLoop.timingMode == 1 && Browser.mainLoop.timingValue > 1 && Browser.mainLoop.currentFrameNumber % Browser.mainLoop.timingValue != 0) {
5494 Browser.mainLoop.scheduler();
5495 return
5496 } else if (Browser.mainLoop.timingMode == 0) {
5497 Browser.mainLoop.tickStartTime = _emscripten_get_now()
5498 }
5499 Browser.mainLoop.runIter(browserIterationFunc);
5500 if (!checkIsRunning()) return;
5501 if (typeof SDL == "object" && SDL.audio && SDL.audio.queueNewAudioData) SDL.audio.queueNewAudioData();
5502 Browser.mainLoop.scheduler()
5503 };
5504 if (!noSetTiming) {
5505 if (fps && fps > 0) _emscripten_set_main_loop_timing(0, 1e3 / fps);
5506 else _emscripten_set_main_loop_timing(1, 1);
5507 Browser.mainLoop.scheduler()
5508 }
5509 if (simulateInfiniteLoop) {
5510 throw "unwind"
5511 }
5512 }
5513
5514 function callUserCallback(func, synchronous) {
5515 if (ABORT) {
5516 return
5517 }
5518 if (synchronous) {
5519 func();
5520 return
5521 }
5522 try {
5523 func()
5524 } catch (e) {
5525 handleException(e)
5526 }
5527 }
5528
5529 function safeSetTimeout(func, timeout) {
5530 return setTimeout(function() {
5531 callUserCallback(func)
5532 }, timeout)
5533 }
5534 var Browser = {
5535 mainLoop: {
5536 running: false,
5537 scheduler: null,
5538 method: "",
5539 currentlyRunningMainloop: 0,
5540 func: null,
5541 arg: 0,
5542 timingMode: 0,
5543 timingValue: 0,
5544 currentFrameNumber: 0,
5545 queue: [],
5546 pause: function() {
5547 Browser.mainLoop.scheduler = null;
5548 Browser.mainLoop.currentlyRunningMainloop++
5549 },
5550 resume: function() {
5551 Browser.mainLoop.currentlyRunningMainloop++;
5552 var timingMode = Browser.mainLoop.timingMode;
5553 var timingValue = Browser.mainLoop.timingValue;
5554 var func = Browser.mainLoop.func;
5555 Browser.mainLoop.func = null;
5556 setMainLoop(func, 0, false, Browser.mainLoop.arg, true);
5557 _emscripten_set_main_loop_timing(timingMode, timingValue);
5558 Browser.mainLoop.scheduler()
5559 },
5560 updateStatus: function() {
5561 if (Module["setStatus"]) {
5562 var message = Module["statusMessage"] || "Please wait...";
5563 var remaining = Browser.mainLoop.remainingBlockers;
5564 var expected = Browser.mainLoop.expectedBlockers;
5565 if (remaining) {
5566 if (remaining < expected) {
5567 Module["setStatus"](message + " (" + (expected - remaining) + "/" + expected + ")")
5568 } else {
5569 Module["setStatus"](message)
5570 }
5571 } else {
5572 Module["setStatus"]("")
5573 }
5574 }
5575 },
5576 runIter: function(func) {
5577 if (ABORT) return;
5578 if (Module["preMainLoop"]) {
5579 var preRet = Module["preMainLoop"]();
5580 if (preRet === false) {
5581 return
5582 }
5583 }
5584 callUserCallback(func);
5585 if (Module["postMainLoop"]) Module["postMainLoop"]()
5586 }
5587 },
5588 isFullscreen: false,
5589 pointerLock: false,
5590 moduleContextCreatedCallbacks: [],
5591 workers: [],
5592 init: function() {
5593 if (!Module["preloadPlugins"]) Module["preloadPlugins"] = [];
5594 if (Browser.initted) return;
5595 Browser.initted = true;
5596 try {
5597 new Blob;
5598 Browser.hasBlobConstructor = true
5599 } catch (e) {
5600 Browser.hasBlobConstructor = false;
5601 out("warning: no blob constructor, cannot create blobs with mimetypes")
5602 }
5603 Browser.BlobBuilder = typeof MozBlobBuilder != "undefined" ? MozBlobBuilder : typeof WebKitBlobBuilder != "undefined" ? WebKitBlobBuilder : !Browser.hasBlobConstructor ? out("warning: no BlobBuilder") : null;
5604 Browser.URLObject = typeof window != "undefined" ? window.URL ? window.URL : window.webkitURL : undefined;
5605 if (!Module.noImageDecoding && typeof Browser.URLObject == "undefined") {
5606 out("warning: Browser does not support creating object URLs. Built-in browser image decoding will not be available.");
5607 Module.noImageDecoding = true
5608 }
5609 var imagePlugin = {};
5610 imagePlugin["canHandle"] = function imagePlugin_canHandle(name) {
5611 return !Module.noImageDecoding && /\.(jpg|jpeg|png|bmp)$/i.test(name)
5612 };
5613 imagePlugin["handle"] = function imagePlugin_handle(byteArray, name, onload, onerror) {
5614 var b = null;
5615 if (Browser.hasBlobConstructor) {
5616 try {
5617 b = new Blob([byteArray], {
5618 type: Browser.getMimetype(name)
5619 });
5620 if (b.size !== byteArray.length) {
5621 b = new Blob([new Uint8Array(byteArray).buffer], {
5622 type: Browser.getMimetype(name)
5623 })
5624 }
5625 } catch (e) {
5626 warnOnce("Blob constructor present but fails: " + e + "; falling back to blob builder")
5627 }
5628 }
5629 if (!b) {
5630 var bb = new Browser.BlobBuilder;
5631 bb.append(new Uint8Array(byteArray).buffer);
5632 b = bb.getBlob()
5633 }
5634 var url = Browser.URLObject.createObjectURL(b);
5635 var img = new Image;
5636 img.onload = () => {
5637 assert(img.complete, "Image " + name + " could not be decoded");
5638 var canvas = document.createElement("canvas");
5639 canvas.width = img.width;
5640 canvas.height = img.height;
5641 var ctx = canvas.getContext("2d");
5642 ctx.drawImage(img, 0, 0);
5643 preloadedImages[name] = canvas;
5644 Browser.URLObject.revokeObjectURL(url);
5645 if (onload) onload(byteArray)
5646 };
5647 img.onerror = event => {
5648 out("Image " + url + " could not be decoded");
5649 if (onerror) onerror()
5650 };
5651 img.src = url
5652 };
5653 Module["preloadPlugins"].push(imagePlugin);
5654 var audioPlugin = {};
5655 audioPlugin["canHandle"] = function audioPlugin_canHandle(name) {
5656 return !Module.noAudioDecoding && name.substr(-4) in {
5657 ".ogg": 1,
5658 ".wav": 1,
5659 ".mp3": 1
5660 }
5661 };
5662 audioPlugin["handle"] = function audioPlugin_handle(byteArray, name, onload, onerror) {
5663 var done = false;
5664
5665 function finish(audio) {
5666 if (done) return;
5667 done = true;
5668 preloadedAudios[name] = audio;
5669 if (onload) onload(byteArray)
5670 }
5671
5672 function fail() {
5673 if (done) return;
5674 done = true;
5675 preloadedAudios[name] = new Audio;
5676 if (onerror) onerror()
5677 }
5678 if (Browser.hasBlobConstructor) {
5679 try {
5680 var b = new Blob([byteArray], {
5681 type: Browser.getMimetype(name)
5682 })
5683 } catch (e) {
5684 return fail()
5685 }
5686 var url = Browser.URLObject.createObjectURL(b);
5687 var audio = new Audio;
5688 audio.addEventListener("canplaythrough", function() {
5689 finish(audio)
5690 }, false);
5691 audio.onerror = function audio_onerror(event) {
5692 if (done) return;
5693 out("warning: browser could not fully decode audio " + name + ", trying slower base64 approach");
5694
5695 function encode64(data) {
5696 var BASE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
5697 var PAD = "=";
5698 var ret = "";
5699 var leftchar = 0;
5700 var leftbits = 0;
5701 for (var i = 0; i < data.length; i++) {
5702 leftchar = leftchar << 8 | data[i];
5703 leftbits += 8;
5704 while (leftbits >= 6) {
5705 var curr = leftchar >> leftbits - 6 & 63;
5706 leftbits -= 6;
5707 ret += BASE[curr]
5708 }
5709 }
5710 if (leftbits == 2) {
5711 ret += BASE[(leftchar & 3) << 4];
5712 ret += PAD + PAD
5713 } else if (leftbits == 4) {
5714 ret += BASE[(leftchar & 15) << 2];
5715 ret += PAD
5716 }
5717 return ret
5718 }
5719 audio.src = "data:audio/x-" + name.substr(-3) + ";base64," + encode64(byteArray);
5720 finish(audio)
5721 };
5722 audio.src = url;
5723 safeSetTimeout(function() {
5724 finish(audio)
5725 }, 1e4)
5726 } else {
5727 return fail()
5728 }
5729 };
5730 Module["preloadPlugins"].push(audioPlugin);
5731
5732 function pointerLockChange() {
5733 Browser.pointerLock = document["pointerLockElement"] === Module["canvas"] || document["mozPointerLockElement"] === Module["canvas"] || document["webkitPointerLockElement"] === Module["canvas"] || document["msPointerLockElement"] === Module["canvas"]
5734 }
5735 var canvas = Module["canvas"];
5736 if (canvas) {
5737 canvas.requestPointerLock = canvas["requestPointerLock"] || canvas["mozRequestPointerLock"] || canvas["webkitRequestPointerLock"] || canvas["msRequestPointerLock"] || function() {};
5738 canvas.exitPointerLock = document["exitPointerLock"] || document["mozExitPointerLock"] || document["webkitExitPointerLock"] || document["msExitPointerLock"] || function() {};
5739 canvas.exitPointerLock = canvas.exitPointerLock.bind(document);
5740 document.addEventListener("pointerlockchange", pointerLockChange, false);
5741 document.addEventListener("mozpointerlockchange", pointerLockChange, false);
5742 document.addEventListener("webkitpointerlockchange", pointerLockChange, false);
5743 document.addEventListener("mspointerlockchange", pointerLockChange, false);
5744 if (Module["elementPointerLock"]) {
5745 canvas.addEventListener("click", function(ev) {
5746 if (!Browser.pointerLock && Module["canvas"].requestPointerLock) {
5747 Module["canvas"].requestPointerLock();
5748 ev.preventDefault()
5749 }
5750 }, false)
5751 }
5752 }
5753 },
5754 handledByPreloadPlugin: function(byteArray, fullname, finish, onerror) {
5755 Browser.init();
5756 var handled = false;
5757 Module["preloadPlugins"].forEach(function(plugin) {
5758 if (handled) return;
5759 if (plugin["canHandle"](fullname)) {
5760 plugin["handle"](byteArray, fullname, finish, onerror);
5761 handled = true
5762 }
5763 });
5764 return handled
5765 },
5766 createContext: function(canvas, useWebGL, setInModule, webGLContextAttributes) {
5767 if (useWebGL && Module.ctx && canvas == Module.canvas) return Module.ctx;
5768 var ctx;
5769 var contextHandle;
5770 if (useWebGL) {
5771 var contextAttributes = {
5772 antialias: false,
5773 alpha: false,
5774 majorVersion: typeof WebGL2RenderingContext != "undefined" ? 2 : 1
5775 };
5776 if (webGLContextAttributes) {
5777 for (var attribute in webGLContextAttributes) {
5778 contextAttributes[attribute] = webGLContextAttributes[attribute]
5779 }
5780 }
5781 if (typeof GL != "undefined") {
5782 contextHandle = GL.createContext(canvas, contextAttributes);
5783 if (contextHandle) {
5784 ctx = GL.getContext(contextHandle).GLctx
5785 }
5786 }
5787 } else {
5788 ctx = canvas.getContext("2d")
5789 }
5790 if (!ctx) return null;
5791 if (setInModule) {
5792 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");
5793 Module.ctx = ctx;
5794 if (useWebGL) GL.makeContextCurrent(contextHandle);
5795 Module.useWebGL = useWebGL;
5796 Browser.moduleContextCreatedCallbacks.forEach(function(callback) {
5797 callback()
5798 });
5799 Browser.init()
5800 }
5801 return ctx
5802 },
5803 destroyContext: function(canvas, useWebGL, setInModule) {},
5804 fullscreenHandlersInstalled: false,
5805 lockPointer: undefined,
5806 resizeCanvas: undefined,
5807 requestFullscreen: function(lockPointer, resizeCanvas) {
5808 Browser.lockPointer = lockPointer;
5809 Browser.resizeCanvas = resizeCanvas;
5810 if (typeof Browser.lockPointer == "undefined") Browser.lockPointer = true;
5811 if (typeof Browser.resizeCanvas == "undefined") Browser.resizeCanvas = false;
5812 var canvas = Module["canvas"];
5813
5814 function fullscreenChange() {
5815 Browser.isFullscreen = false;
5816 var canvasContainer = canvas.parentNode;
5817 if ((document["fullscreenElement"] || document["mozFullScreenElement"] || document["msFullscreenElement"] || document["webkitFullscreenElement"] || document["webkitCurrentFullScreenElement"]) === canvasContainer) {
5818 canvas.exitFullscreen = Browser.exitFullscreen;
5819 if (Browser.lockPointer) canvas.requestPointerLock();
5820 Browser.isFullscreen = true;
5821 if (Browser.resizeCanvas) {
5822 Browser.setFullscreenCanvasSize()
5823 } else {
5824 Browser.updateCanvasDimensions(canvas)
5825 }
5826 } else {
5827 canvasContainer.parentNode.insertBefore(canvas, canvasContainer);
5828 canvasContainer.parentNode.removeChild(canvasContainer);
5829 if (Browser.resizeCanvas) {
5830 Browser.setWindowedCanvasSize()
5831 } else {
5832 Browser.updateCanvasDimensions(canvas)
5833 }
5834 }
5835 if (Module["onFullScreen"]) Module["onFullScreen"](Browser.isFullscreen);
5836 if (Module["onFullscreen"]) Module["onFullscreen"](Browser.isFullscreen)
5837 }
5838 if (!Browser.fullscreenHandlersInstalled) {
5839 Browser.fullscreenHandlersInstalled = true;
5840 document.addEventListener("fullscreenchange", fullscreenChange, false);
5841 document.addEventListener("mozfullscreenchange", fullscreenChange, false);
5842 document.addEventListener("webkitfullscreenchange", fullscreenChange, false);
5843 document.addEventListener("MSFullscreenChange", fullscreenChange, false)
5844 }
5845 var canvasContainer = document.createElement("div");
5846 canvas.parentNode.insertBefore(canvasContainer, canvas);
5847 canvasContainer.appendChild(canvas);
5848 canvasContainer.requestFullscreen = canvasContainer["requestFullscreen"] || canvasContainer["mozRequestFullScreen"] || canvasContainer["msRequestFullscreen"] || (canvasContainer["webkitRequestFullscreen"] ? function() {
5849 canvasContainer["webkitRequestFullscreen"](Element["ALLOW_KEYBOARD_INPUT"])
5850 } : null) || (canvasContainer["webkitRequestFullScreen"] ? function() {
5851 canvasContainer["webkitRequestFullScreen"](Element["ALLOW_KEYBOARD_INPUT"])
5852 } : null);
5853 canvasContainer.requestFullscreen()
5854 },
5855 exitFullscreen: function() {
5856 if (!Browser.isFullscreen) {
5857 return false
5858 }
5859 var CFS = document["exitFullscreen"] || document["cancelFullScreen"] || document["mozCancelFullScreen"] || document["msExitFullscreen"] || document["webkitCancelFullScreen"] || function() {};
5860 CFS.apply(document, []);
5861 return true
5862 },
5863 nextRAF: 0,
5864 fakeRequestAnimationFrame: function(func) {
5865 var now = Date.now();
5866 if (Browser.nextRAF === 0) {
5867 Browser.nextRAF = now + 1e3 / 60
5868 } else {
5869 while (now + 2 >= Browser.nextRAF) {
5870 Browser.nextRAF += 1e3 / 60
5871 }
5872 }
5873 var delay = Math.max(Browser.nextRAF - now, 0);
5874 setTimeout(func, delay)
5875 },
5876 requestAnimationFrame: function(func) {
5877 if (typeof requestAnimationFrame == "function") {
5878 requestAnimationFrame(func);
5879 return
5880 }
5881 var RAF = Browser.fakeRequestAnimationFrame;
5882 RAF(func)
5883 },
5884 safeSetTimeout: function(func) {
5885 return safeSetTimeout(func)
5886 },
5887 safeRequestAnimationFrame: function(func) {
5888 return Browser.requestAnimationFrame(function() {
5889 callUserCallback(func)
5890 })
5891 },
5892 getMimetype: function(name) {
5893 return {
5894 "jpg": "image/jpeg",
5895 "jpeg": "image/jpeg",
5896 "png": "image/png",
5897 "bmp": "image/bmp",
5898 "ogg": "audio/ogg",
5899 "wav": "audio/wav",
5900 "mp3": "audio/mpeg"
5901 } [name.substr(name.lastIndexOf(".") + 1)]
5902 },
5903 getUserMedia: function(func) {
5904 if (!window.getUserMedia) {
5905 window.getUserMedia = navigator["getUserMedia"] || navigator["mozGetUserMedia"]
5906 }
5907 window.getUserMedia(func)
5908 },
5909 getMovementX: function(event) {
5910 return event["movementX"] || event["mozMovementX"] || event["webkitMovementX"] || 0
5911 },
5912 getMovementY: function(event) {
5913 return event["movementY"] || event["mozMovementY"] || event["webkitMovementY"] || 0
5914 },
5915 getMouseWheelDelta: function(event) {
5916 var delta = 0;
5917 switch (event.type) {
5918 case "DOMMouseScroll":
5919 delta = event.detail / 3;
5920 break;
5921 case "mousewheel":
5922 delta = event.wheelDelta / 120;
5923 break;
5924 case "wheel":
5925 delta = event.deltaY;
5926 switch (event.deltaMode) {
5927 case 0:
5928 delta /= 100;
5929 break;
5930 case 1:
5931 delta /= 3;
5932 break;
5933 case 2:
5934 delta *= 80;
5935 break;
5936 default:
5937 throw "unrecognized mouse wheel delta mode: " + event.deltaMode
5938 }
5939 break;
5940 default:
5941 throw "unrecognized mouse wheel event: " + event.type
5942 }
5943 return delta
5944 },
5945 mouseX: 0,
5946 mouseY: 0,
5947 mouseMovementX: 0,
5948 mouseMovementY: 0,
5949 touches: {},
5950 lastTouches: {},
5951 calculateMouseEvent: function(event) {
5952 if (Browser.pointerLock) {
5953 if (event.type != "mousemove" && "mozMovementX" in event) {
5954 Browser.mouseMovementX = Browser.mouseMovementY = 0
5955 } else {
5956 Browser.mouseMovementX = Browser.getMovementX(event);
5957 Browser.mouseMovementY = Browser.getMovementY(event)
5958 }
5959 if (typeof SDL != "undefined") {
5960 Browser.mouseX = SDL.mouseX + Browser.mouseMovementX;
5961 Browser.mouseY = SDL.mouseY + Browser.mouseMovementY
5962 } else {
5963 Browser.mouseX += Browser.mouseMovementX;
5964 Browser.mouseY += Browser.mouseMovementY
5965 }
5966 } else {
5967 var rect = Module["canvas"].getBoundingClientRect();
5968 var cw = Module["canvas"].width;
5969 var ch = Module["canvas"].height;
5970 var scrollX = typeof window.scrollX != "undefined" ? window.scrollX : window.pageXOffset;
5971 var scrollY = typeof window.scrollY != "undefined" ? window.scrollY : window.pageYOffset;
5972 if (event.type === "touchstart" || event.type === "touchend" || event.type === "touchmove") {
5973 var touch = event.touch;
5974 if (touch === undefined) {
5975 return
5976 }
5977 var adjustedX = touch.pageX - (scrollX + rect.left);
5978 var adjustedY = touch.pageY - (scrollY + rect.top);
5979 adjustedX = adjustedX * (cw / rect.width);
5980 adjustedY = adjustedY * (ch / rect.height);
5981 var coords = {
5982 x: adjustedX,
5983 y: adjustedY
5984 };
5985 if (event.type === "touchstart") {
5986 Browser.lastTouches[touch.identifier] = coords;
5987 Browser.touches[touch.identifier] = coords
5988 } else if (event.type === "touchend" || event.type === "touchmove") {
5989 var last = Browser.touches[touch.identifier];
5990 if (!last) last = coords;
5991 Browser.lastTouches[touch.identifier] = last;
5992 Browser.touches[touch.identifier] = coords
5993 }
5994 return
5995 }
5996 var x = event.pageX - (scrollX + rect.left);
5997 var y = event.pageY - (scrollY + rect.top);
5998 x = x * (cw / rect.width);
5999 y = y * (ch / rect.height);
6000 Browser.mouseMovementX = x - Browser.mouseX;
6001 Browser.mouseMovementY = y - Browser.mouseY;
6002 Browser.mouseX = x;
6003 Browser.mouseY = y
6004 }
6005 },
6006 resizeListeners: [],
6007 updateResizeListeners: function() {
6008 var canvas = Module["canvas"];
6009 Browser.resizeListeners.forEach(function(listener) {
6010 listener(canvas.width, canvas.height)
6011 })
6012 },
6013 setCanvasSize: function(width, height, noUpdates) {
6014 var canvas = Module["canvas"];
6015 Browser.updateCanvasDimensions(canvas, width, height);
6016 if (!noUpdates) Browser.updateResizeListeners()
6017 },
6018 windowedWidth: 0,
6019 windowedHeight: 0,
6020 setFullscreenCanvasSize: function() {
6021 if (typeof SDL != "undefined") {
6022 var flags = HEAPU32[SDL.screen >> 2];
6023 flags = flags | 8388608;
6024 HEAP32[SDL.screen >> 2] = flags
6025 }
6026 Browser.updateCanvasDimensions(Module["canvas"]);
6027 Browser.updateResizeListeners()
6028 },
6029 setWindowedCanvasSize: function() {
6030 if (typeof SDL != "undefined") {
6031 var flags = HEAPU32[SDL.screen >> 2];
6032 flags = flags & ~8388608;
6033 HEAP32[SDL.screen >> 2] = flags
6034 }
6035 Browser.updateCanvasDimensions(Module["canvas"]);
6036 Browser.updateResizeListeners()
6037 },
6038 updateCanvasDimensions: function(canvas, wNative, hNative) {
6039 if (wNative && hNative) {
6040 canvas.widthNative = wNative;
6041 canvas.heightNative = hNative
6042 } else {
6043 wNative = canvas.widthNative;
6044 hNative = canvas.heightNative
6045 }
6046 var w = wNative;
6047 var h = hNative;
6048 if (Module["forcedAspectRatio"] && Module["forcedAspectRatio"] > 0) {
6049 if (w / h < Module["forcedAspectRatio"]) {
6050 w = Math.round(h * Module["forcedAspectRatio"])
6051 } else {
6052 h = Math.round(w / Module["forcedAspectRatio"])
6053 }
6054 }
6055 if ((document["fullscreenElement"] || document["mozFullScreenElement"] || document["msFullscreenElement"] || document["webkitFullscreenElement"] || document["webkitCurrentFullScreenElement"]) === canvas.parentNode && typeof screen != "undefined") {
6056 var factor = Math.min(screen.width / w, screen.height / h);
6057 w = Math.round(w * factor);
6058 h = Math.round(h * factor)
6059 }
6060 if (Browser.resizeCanvas) {
6061 if (canvas.width != w) canvas.width = w;
6062 if (canvas.height != h) canvas.height = h;
6063 if (typeof canvas.style != "undefined") {
6064 canvas.style.removeProperty("width");
6065 canvas.style.removeProperty("height")
6066 }
6067 } else {
6068 if (canvas.width != wNative) canvas.width = wNative;
6069 if (canvas.height != hNative) canvas.height = hNative;
6070 if (typeof canvas.style != "undefined") {
6071 if (w != wNative || h != hNative) {
6072 canvas.style.setProperty("width", w + "px", "important");
6073 canvas.style.setProperty("height", h + "px", "important")
6074 } else {
6075 canvas.style.removeProperty("width");
6076 canvas.style.removeProperty("height")
6077 }
6078 }
6079 }
6080 }
6081 };
6082
6083 function _SDL_GetTicks() {
6084 return Date.now() - SDL.startTime | 0
6085 }
6086
6087 function _SDL_LockSurface(surf) {
6088 var surfData = SDL.surfaces[surf];
6089 surfData.locked++;
6090 if (surfData.locked > 1) return 0;
6091 if (!surfData.buffer) {
6092 surfData.buffer = _malloc(surfData.width * surfData.height * 4);
6093 HEAPU32[surf + 20 >> 2] = surfData.buffer
6094 }
6095 HEAPU32[surf + 20 >> 2] = surfData.buffer;
6096 if (surf == SDL.screen && Module.screenIsReadOnly && surfData.image) return 0;
6097 if (SDL.defaults.discardOnLock) {
6098 if (!surfData.image) {
6099 surfData.image = surfData.ctx.createImageData(surfData.width, surfData.height)
6100 }
6101 if (!SDL.defaults.opaqueFrontBuffer) return
6102 } else {
6103 surfData.image = surfData.ctx.getImageData(0, 0, surfData.width, surfData.height)
6104 }
6105 if (surf == SDL.screen && SDL.defaults.opaqueFrontBuffer) {
6106 var data = surfData.image.data;
6107 var num = data.length;
6108 for (var i = 0; i < num / 4; i++) {
6109 data[i * 4 + 3] = 255
6110 }
6111 }
6112 if (SDL.defaults.copyOnLock && !SDL.defaults.discardOnLock) {
6113 if (surfData.isFlagSet(2097152)) {
6114 throw "CopyOnLock is not supported for SDL_LockSurface with SDL_HWPALETTE flag set" + (new Error).stack
6115 } else {
6116 HEAPU8.set(surfData.image.data, surfData.buffer)
6117 }
6118 }
6119 return 0
6120 }
6121
6122 function SDL_unicode() {
6123 return SDL.unicode
6124 }
6125
6126 function SDL_ttfContext() {
6127 return SDL.ttfContext
6128 }
6129
6130 function SDL_audio() {
6131 return SDL.audio
6132 }
6133 var SDL = {
6134 defaults: {
6135 width: 320,
6136 height: 200,
6137 copyOnLock: true,
6138 discardOnLock: false,
6139 opaqueFrontBuffer: true
6140 },
6141 version: null,
6142 surfaces: {},
6143 canvasPool: [],
6144 events: [],
6145 fonts: [null],
6146 audios: [null],
6147 rwops: [null],
6148 music: {
6149 audio: null,
6150 volume: 1
6151 },
6152 mixerFrequency: 22050,
6153 mixerFormat: 32784,
6154 mixerNumChannels: 2,
6155 mixerChunkSize: 1024,
6156 channelMinimumNumber: 0,
6157 GL: false,
6158 glAttributes: {
6159 0: 3,
6160 1: 3,
6161 2: 2,
6162 3: 0,
6163 4: 0,
6164 5: 1,
6165 6: 16,
6166 7: 0,
6167 8: 0,
6168 9: 0,
6169 10: 0,
6170 11: 0,
6171 12: 0,
6172 13: 0,
6173 14: 0,
6174 15: 1,
6175 16: 0,
6176 17: 0,
6177 18: 0
6178 },
6179 keyboardState: null,
6180 keyboardMap: {},
6181 canRequestFullscreen: false,
6182 isRequestingFullscreen: false,
6183 textInput: false,
6184 startTime: null,
6185 initFlags: 0,
6186 buttonState: 0,
6187 modState: 0,
6188 DOMButtons: [0, 0, 0],
6189 DOMEventToSDLEvent: {},
6190 TOUCH_DEFAULT_ID: 0,
6191 eventHandler: null,
6192 eventHandlerContext: null,
6193 eventHandlerTemp: 0,
6194 keyCodes: {
6195 16: 1249,
6196 17: 1248,
6197 18: 1250,
6198 20: 1081,
6199 33: 1099,
6200 34: 1102,
6201 35: 1101,
6202 36: 1098,
6203 37: 1104,
6204 38: 1106,
6205 39: 1103,
6206 40: 1105,
6207 44: 316,
6208 45: 1097,
6209 46: 127,
6210 91: 1251,
6211 93: 1125,
6212 96: 1122,
6213 97: 1113,
6214 98: 1114,
6215 99: 1115,
6216 100: 1116,
6217 101: 1117,
6218 102: 1118,
6219 103: 1119,
6220 104: 1120,
6221 105: 1121,
6222 106: 1109,
6223 107: 1111,
6224 109: 1110,
6225 110: 1123,
6226 111: 1108,
6227 112: 1082,
6228 113: 1083,
6229 114: 1084,
6230 115: 1085,
6231 116: 1086,
6232 117: 1087,
6233 118: 1088,
6234 119: 1089,
6235 120: 1090,
6236 121: 1091,
6237 122: 1092,
6238 123: 1093,
6239 124: 1128,
6240 125: 1129,
6241 126: 1130,
6242 127: 1131,
6243 128: 1132,
6244 129: 1133,
6245 130: 1134,
6246 131: 1135,
6247 132: 1136,
6248 133: 1137,
6249 134: 1138,
6250 135: 1139,
6251 144: 1107,
6252 160: 94,
6253 161: 33,
6254 162: 34,
6255 163: 35,
6256 164: 36,
6257 165: 37,
6258 166: 38,
6259 167: 95,
6260 168: 40,
6261 169: 41,
6262 170: 42,
6263 171: 43,
6264 172: 124,
6265 173: 45,
6266 174: 123,
6267 175: 125,
6268 176: 126,
6269 181: 127,
6270 182: 129,
6271 183: 128,
6272 188: 44,
6273 190: 46,
6274 191: 47,
6275 192: 96,
6276 219: 91,
6277 220: 92,
6278 221: 93,
6279 222: 39,
6280 224: 1251
6281 },
6282 scanCodes: {
6283 8: 42,
6284 9: 43,
6285 13: 40,
6286 27: 41,
6287 32: 44,
6288 35: 204,
6289 39: 53,
6290 44: 54,
6291 46: 55,
6292 47: 56,
6293 48: 39,
6294 49: 30,
6295 50: 31,
6296 51: 32,
6297 52: 33,
6298 53: 34,
6299 54: 35,
6300 55: 36,
6301 56: 37,
6302 57: 38,
6303 58: 203,
6304 59: 51,
6305 61: 46,
6306 91: 47,
6307 92: 49,
6308 93: 48,
6309 96: 52,
6310 97: 4,
6311 98: 5,
6312 99: 6,
6313 100: 7,
6314 101: 8,
6315 102: 9,
6316 103: 10,
6317 104: 11,
6318 105: 12,
6319 106: 13,
6320 107: 14,
6321 108: 15,
6322 109: 16,
6323 110: 17,
6324 111: 18,
6325 112: 19,
6326 113: 20,
6327 114: 21,
6328 115: 22,
6329 116: 23,
6330 117: 24,
6331 118: 25,
6332 119: 26,
6333 120: 27,
6334 121: 28,
6335 122: 29,
6336 127: 76,
6337 305: 224,
6338 308: 226,
6339 316: 70
6340 },
6341 loadRect: function(rect) {
6342 return {
6343 x: HEAP32[rect + 0 >> 2],
6344 y: HEAP32[rect + 4 >> 2],
6345 w: HEAP32[rect + 8 >> 2],
6346 h: HEAP32[rect + 12 >> 2]
6347 }
6348 },
6349 updateRect: function(rect, r) {
6350 HEAP32[rect >> 2] = r.x;
6351 HEAP32[rect + 4 >> 2] = r.y;
6352 HEAP32[rect + 8 >> 2] = r.w;
6353 HEAP32[rect + 12 >> 2] = r.h
6354 },
6355 intersectionOfRects: function(first, second) {
6356 var leftX = Math.max(first.x, second.x);
6357 var leftY = Math.max(first.y, second.y);
6358 var rightX = Math.min(first.x + first.w, second.x + second.w);
6359 var rightY = Math.min(first.y + first.h, second.y + second.h);
6360 return {
6361 x: leftX,
6362 y: leftY,
6363 w: Math.max(leftX, rightX) - leftX,
6364 h: Math.max(leftY, rightY) - leftY
6365 }
6366 },
6367 checkPixelFormat: function(fmt) {},
6368 loadColorToCSSRGB: function(color) {
6369 var rgba = HEAP32[color >> 2];
6370 return "rgb(" + (rgba & 255) + "," + (rgba >> 8 & 255) + "," + (rgba >> 16 & 255) + ")"
6371 },
6372 loadColorToCSSRGBA: function(color) {
6373 var rgba = HEAP32[color >> 2];
6374 return "rgba(" + (rgba & 255) + "," + (rgba >> 8 & 255) + "," + (rgba >> 16 & 255) + "," + (rgba >> 24 & 255) / 255 + ")"
6375 },
6376 translateColorToCSSRGBA: function(rgba) {
6377 return "rgba(" + (rgba & 255) + "," + (rgba >> 8 & 255) + "," + (rgba >> 16 & 255) + "," + (rgba >>> 24) / 255 + ")"
6378 },
6379 translateRGBAToCSSRGBA: function(r, g, b, a) {
6380 return "rgba(" + (r & 255) + "," + (g & 255) + "," + (b & 255) + "," + (a & 255) / 255 + ")"
6381 },
6382 translateRGBAToColor: function(r, g, b, a) {
6383 return r | g << 8 | b << 16 | a << 24
6384 },
6385 makeSurface: function(width, height, flags, usePageCanvas, source, rmask, gmask, bmask, amask) {
6386 flags = flags || 0;
6387 var is_SDL_HWSURFACE = flags & 1;
6388 var is_SDL_HWPALETTE = flags & 2097152;
6389 var is_SDL_OPENGL = flags & 67108864;
6390 var surf = _malloc(60);
6391 var pixelFormat = _malloc(44);
6392 var bpp = is_SDL_HWPALETTE ? 1 : 4;
6393 var buffer = 0;
6394 if (!is_SDL_HWSURFACE && !is_SDL_OPENGL) {
6395 buffer = _malloc(width * height * 4)
6396 }
6397 HEAP32[surf >> 2] = flags;
6398 HEAPU32[surf + 4 >> 2] = pixelFormat;
6399 HEAP32[surf + 8 >> 2] = width;
6400 HEAP32[surf + 12 >> 2] = height;
6401 HEAP32[surf + 16 >> 2] = width * bpp;
6402 HEAPU32[surf + 20 >> 2] = buffer;
6403 HEAP32[surf + 36 >> 2] = 0;
6404 HEAP32[surf + 40 >> 2] = 0;
6405 HEAP32[surf + 44 >> 2] = Module["canvas"].width;
6406 HEAP32[surf + 48 >> 2] = Module["canvas"].height;
6407 HEAP32[surf + 56 >> 2] = 1;
6408 HEAP32[pixelFormat >> 2] = -2042224636;
6409 HEAP32[pixelFormat + 4 >> 2] = 0;
6410 HEAP8[pixelFormat + 8 >> 0] = bpp * 8;
6411 HEAP8[pixelFormat + 9 >> 0] = bpp;
6412 HEAP32[pixelFormat + 12 >> 2] = rmask || 255;
6413 HEAP32[pixelFormat + 16 >> 2] = gmask || 65280;
6414 HEAP32[pixelFormat + 20 >> 2] = bmask || 16711680;
6415 HEAP32[pixelFormat + 24 >> 2] = amask || 4278190080;
6416 SDL.GL = SDL.GL || is_SDL_OPENGL;
6417 var canvas;
6418 if (!usePageCanvas) {
6419 if (SDL.canvasPool.length > 0) {
6420 canvas = SDL.canvasPool.pop()
6421 } else {
6422 canvas = document.createElement("canvas")
6423 }
6424 canvas.width = width;
6425 canvas.height = height
6426 } else {
6427 canvas = Module["canvas"]
6428 }
6429 var webGLContextAttributes = {
6430 antialias: SDL.glAttributes[13] != 0 && SDL.glAttributes[14] > 1,
6431 depth: SDL.glAttributes[6] > 0,
6432 stencil: SDL.glAttributes[7] > 0,
6433 alpha: SDL.glAttributes[3] > 0
6434 };
6435 var ctx = Browser.createContext(canvas, is_SDL_OPENGL, usePageCanvas, webGLContextAttributes);
6436 SDL.surfaces[surf] = {
6437 width: width,
6438 height: height,
6439 canvas: canvas,
6440 ctx: ctx,
6441 surf: surf,
6442 buffer: buffer,
6443 pixelFormat: pixelFormat,
6444 alpha: 255,
6445 flags: flags,
6446 locked: 0,
6447 usePageCanvas: usePageCanvas,
6448 source: source,
6449 isFlagSet: function(flag) {
6450 return flags & flag
6451 }
6452 };
6453 return surf
6454 },
6455 copyIndexedColorData: function(surfData, rX, rY, rW, rH) {
6456 if (!surfData.colors) {
6457 return
6458 }
6459 var fullWidth = Module["canvas"].width;
6460 var fullHeight = Module["canvas"].height;
6461 var startX = rX || 0;
6462 var startY = rY || 0;
6463 var endX = (rW || fullWidth - startX) + startX;
6464 var endY = (rH || fullHeight - startY) + startY;
6465 var buffer = surfData.buffer;
6466 if (!surfData.image.data32) {
6467 surfData.image.data32 = new Uint32Array(surfData.image.data.buffer)
6468 }
6469 var data32 = surfData.image.data32;
6470 var colors32 = surfData.colors32;
6471 for (var y = startY; y < endY; ++y) {
6472 var base = y * fullWidth;
6473 for (var x = startX; x < endX; ++x) {
6474 data32[base + x] = colors32[HEAPU8[buffer + base + x >> 0]]
6475 }
6476 }
6477 },
6478 freeSurface: function(surf) {
6479 var refcountPointer = surf + 56;
6480 var refcount = HEAP32[refcountPointer >> 2];
6481 if (refcount > 1) {
6482 HEAP32[refcountPointer >> 2] = refcount - 1;
6483 return
6484 }
6485 var info = SDL.surfaces[surf];
6486 if (!info.usePageCanvas && info.canvas) SDL.canvasPool.push(info.canvas);
6487 if (info.buffer) _free(info.buffer);
6488 _free(info.pixelFormat);
6489 _free(surf);
6490 SDL.surfaces[surf] = null;
6491 if (surf === SDL.screen) {
6492 SDL.screen = null
6493 }
6494 },
6495 blitSurface: function(src, srcrect, dst, dstrect, scale) {
6496 var srcData = SDL.surfaces[src];
6497 var dstData = SDL.surfaces[dst];
6498 var sr, dr;
6499 if (srcrect) {
6500 sr = SDL.loadRect(srcrect)
6501 } else {
6502 sr = {
6503 x: 0,
6504 y: 0,
6505 w: srcData.width,
6506 h: srcData.height
6507 }
6508 }
6509 if (dstrect) {
6510 dr = SDL.loadRect(dstrect)
6511 } else {
6512 dr = {
6513 x: 0,
6514 y: 0,
6515 w: srcData.width,
6516 h: srcData.height
6517 }
6518 }
6519 if (dstData.clipRect) {
6520 var widthScale = !scale || sr.w === 0 ? 1 : sr.w / dr.w;
6521 var heightScale = !scale || sr.h === 0 ? 1 : sr.h / dr.h;
6522 dr = SDL.intersectionOfRects(dstData.clipRect, dr);
6523 sr.w = dr.w * widthScale;
6524 sr.h = dr.h * heightScale;
6525 if (dstrect) {
6526 SDL.updateRect(dstrect, dr)
6527 }
6528 }
6529 var blitw, blith;
6530 if (scale) {
6531 blitw = dr.w;
6532 blith = dr.h
6533 } else {
6534 blitw = sr.w;
6535 blith = sr.h
6536 }
6537 if (sr.w === 0 || sr.h === 0 || blitw === 0 || blith === 0) {
6538 return 0
6539 }
6540 var oldAlpha = dstData.ctx.globalAlpha;
6541 dstData.ctx.globalAlpha = srcData.alpha / 255;
6542 dstData.ctx.drawImage(srcData.canvas, sr.x, sr.y, sr.w, sr.h, dr.x, dr.y, blitw, blith);
6543 dstData.ctx.globalAlpha = oldAlpha;
6544 if (dst != SDL.screen) {
6545 warnOnce("WARNING: copying canvas data to memory for compatibility");
6546 _SDL_LockSurface(dst);
6547 dstData.locked--
6548 }
6549 return 0
6550 },
6551 downFingers: {},
6552 savedKeydown: null,
6553 receiveEvent: function(event) {
6554 function unpressAllPressedKeys() {
6555 for (var code in SDL.keyboardMap) {
6556 SDL.events.push({
6557 type: "keyup",
6558 keyCode: SDL.keyboardMap[code]
6559 })
6560 }
6561 }
6562 switch (event.type) {
6563 case "touchstart":
6564 case "touchmove": {
6565 event.preventDefault();
6566 var touches = [];
6567 if (event.type === "touchstart") {
6568 for (var i = 0; i < event.touches.length; i++) {
6569 var touch = event.touches[i];
6570 if (SDL.downFingers[touch.identifier] != true) {
6571 SDL.downFingers[touch.identifier] = true;
6572 touches.push(touch)
6573 }
6574 }
6575 } else {
6576 touches = event.touches
6577 }
6578 var firstTouch = touches[0];
6579 if (firstTouch) {
6580 if (event.type == "touchstart") {
6581 SDL.DOMButtons[0] = 1
6582 }
6583 var mouseEventType;
6584 switch (event.type) {
6585 case "touchstart":
6586 mouseEventType = "mousedown";
6587 break;
6588 case "touchmove":
6589 mouseEventType = "mousemove";
6590 break
6591 }
6592 var mouseEvent = {
6593 type: mouseEventType,
6594 button: 0,
6595 pageX: firstTouch.clientX,
6596 pageY: firstTouch.clientY
6597 };
6598 SDL.events.push(mouseEvent)
6599 }
6600 for (var i = 0; i < touches.length; i++) {
6601 var touch = touches[i];
6602 SDL.events.push({
6603 type: event.type,
6604 touch: touch
6605 })
6606 }
6607 break
6608 }
6609 case "touchend": {
6610 event.preventDefault();
6611 for (var i = 0; i < event.changedTouches.length; i++) {
6612 var touch = event.changedTouches[i];
6613 if (SDL.downFingers[touch.identifier] === true) {
6614 delete SDL.downFingers[touch.identifier]
6615 }
6616 }
6617 var mouseEvent = {
6618 type: "mouseup",
6619 button: 0,
6620 pageX: event.changedTouches[0].clientX,
6621 pageY: event.changedTouches[0].clientY
6622 };
6623 SDL.DOMButtons[0] = 0;
6624 SDL.events.push(mouseEvent);
6625 for (var i = 0; i < event.changedTouches.length; i++) {
6626 var touch = event.changedTouches[i];
6627 SDL.events.push({
6628 type: "touchend",
6629 touch: touch
6630 })
6631 }
6632 break
6633 }
6634 case "DOMMouseScroll":
6635 case "mousewheel":
6636 case "wheel":
6637 var delta = -Browser.getMouseWheelDelta(event);
6638 delta = delta == 0 ? 0 : delta > 0 ? Math.max(delta, 1) : Math.min(delta, -1);
6639 var button = delta > 0 ? 3 : 4;
6640 SDL.events.push({
6641 type: "mousedown",
6642 button: button,
6643 pageX: event.pageX,
6644 pageY: event.pageY
6645 });
6646 SDL.events.push({
6647 type: "mouseup",
6648 button: button,
6649 pageX: event.pageX,
6650 pageY: event.pageY
6651 });
6652 SDL.events.push({
6653 type: "wheel",
6654 deltaX: 0,
6655 deltaY: delta
6656 });
6657 event.preventDefault();
6658 break;
6659 case "mousemove":
6660 if (SDL.DOMButtons[0] === 1) {
6661 SDL.events.push({
6662 type: "touchmove",
6663 touch: {
6664 identifier: 0,
6665 deviceID: -1,
6666 pageX: event.pageX,
6667 pageY: event.pageY
6668 }
6669 })
6670 }
6671 if (Browser.pointerLock) {
6672 if ("mozMovementX" in event) {
6673 event["movementX"] = event["mozMovementX"];
6674 event["movementY"] = event["mozMovementY"]
6675 }
6676 if (event["movementX"] == 0 && event["movementY"] == 0) {
6677 event.preventDefault();
6678 return
6679 }
6680 }
6681 case "keydown":
6682 case "keyup":
6683 case "keypress":
6684 case "mousedown":
6685 case "mouseup":
6686 if (event.type !== "keydown" || !SDL_unicode() && !SDL.textInput || (event.keyCode === 8 || event.keyCode === 9)) {
6687 event.preventDefault()
6688 }
6689 if (event.type == "mousedown") {
6690 SDL.DOMButtons[event.button] = 1;
6691 SDL.events.push({
6692 type: "touchstart",
6693 touch: {
6694 identifier: 0,
6695 deviceID: -1,
6696 pageX: event.pageX,
6697 pageY: event.pageY
6698 }
6699 })
6700 } else if (event.type == "mouseup") {
6701 if (!SDL.DOMButtons[event.button]) {
6702 return
6703 }
6704 SDL.events.push({
6705 type: "touchend",
6706 touch: {
6707 identifier: 0,
6708 deviceID: -1,
6709 pageX: event.pageX,
6710 pageY: event.pageY
6711 }
6712 });
6713 SDL.DOMButtons[event.button] = 0
6714 }
6715 if (event.type === "keydown" || event.type === "mousedown") {
6716 SDL.canRequestFullscreen = true
6717 } else if (event.type === "keyup" || event.type === "mouseup") {
6718 if (SDL.isRequestingFullscreen) {
6719 Module["requestFullscreen"](true, true);
6720 SDL.isRequestingFullscreen = false
6721 }
6722 SDL.canRequestFullscreen = false
6723 }
6724 if (event.type === "keypress" && SDL.savedKeydown) {
6725 SDL.savedKeydown.keypressCharCode = event.charCode;
6726 SDL.savedKeydown = null
6727 } else if (event.type === "keydown") {
6728 SDL.savedKeydown = event
6729 }
6730 if (event.type !== "keypress" || SDL.textInput) {
6731 SDL.events.push(event)
6732 }
6733 break;
6734 case "mouseout":
6735 for (var i = 0; i < 3; i++) {
6736 if (SDL.DOMButtons[i]) {
6737 SDL.events.push({
6738 type: "mouseup",
6739 button: i,
6740 pageX: event.pageX,
6741 pageY: event.pageY
6742 });
6743 SDL.DOMButtons[i] = 0
6744 }
6745 }
6746 event.preventDefault();
6747 break;
6748 case "focus":
6749 SDL.events.push(event);
6750 event.preventDefault();
6751 break;
6752 case "blur":
6753 SDL.events.push(event);
6754 unpressAllPressedKeys();
6755 event.preventDefault();
6756 break;
6757 case "visibilitychange":
6758 SDL.events.push({
6759 type: "visibilitychange",
6760 visible: !document.hidden
6761 });
6762 unpressAllPressedKeys();
6763 event.preventDefault();
6764 break;
6765 case "unload":
6766 if (Browser.mainLoop.runner) {
6767 SDL.events.push(event);
6768 Browser.mainLoop.runner()
6769 }
6770 return;
6771 case "resize":
6772 SDL.events.push(event);
6773 if (event.preventDefault) {
6774 event.preventDefault()
6775 }
6776 break
6777 }
6778 if (SDL.events.length >= 1e4) {
6779 err("SDL event queue full, dropping events");
6780 SDL.events = SDL.events.slice(0, 1e4)
6781 }
6782 SDL.flushEventsToHandler();
6783 return
6784 },
6785 lookupKeyCodeForEvent: function(event) {
6786 var code = event.keyCode;
6787 if (code >= 65 && code <= 90) {
6788 code += 32
6789 } else {
6790 code = SDL.keyCodes[event.keyCode] || event.keyCode;
6791 if (event.location === 2 && code >= (224 | 1 << 10) && code <= (227 | 1 << 10)) {
6792 code += 4
6793 }
6794 }
6795 return code
6796 },
6797 handleEvent: function(event) {
6798 if (event.handled) return;
6799 event.handled = true;
6800 switch (event.type) {
6801 case "touchstart":
6802 case "touchend":
6803 case "touchmove": {
6804 Browser.calculateMouseEvent(event);
6805 break
6806 }
6807 case "keydown":
6808 case "keyup": {
6809 var down = event.type === "keydown";
6810 var code = SDL.lookupKeyCodeForEvent(event);
6811 HEAP8[SDL.keyboardState + code >> 0] = down;
6812 SDL.modState = (HEAP8[SDL.keyboardState + 1248 >> 0] ? 64 : 0) | (HEAP8[SDL.keyboardState + 1249 >> 0] ? 1 : 0) | (HEAP8[SDL.keyboardState + 1250 >> 0] ? 256 : 0) | (HEAP8[SDL.keyboardState + 1252 >> 0] ? 128 : 0) | (HEAP8[SDL.keyboardState + 1253 >> 0] ? 2 : 0) | (HEAP8[SDL.keyboardState + 1254 >> 0] ? 512 : 0);
6813 if (down) {
6814 SDL.keyboardMap[code] = event.keyCode
6815 } else {
6816 delete SDL.keyboardMap[code]
6817 }
6818 break
6819 }
6820 case "mousedown":
6821 case "mouseup":
6822 if (event.type == "mousedown") {
6823 SDL.buttonState |= 1 << event.button
6824 } else if (event.type == "mouseup") {
6825 SDL.buttonState &= ~(1 << event.button)
6826 }
6827 case "mousemove": {
6828 Browser.calculateMouseEvent(event);
6829 break
6830 }
6831 }
6832 },
6833 flushEventsToHandler: function() {
6834 if (!SDL.eventHandler) return;
6835 while (SDL.pollEvent(SDL.eventHandlerTemp)) {
6836 getWasmTableEntry(SDL.eventHandler)(SDL.eventHandlerContext, SDL.eventHandlerTemp)
6837 }
6838 },
6839 pollEvent: function(ptr) {
6840 if (SDL.initFlags & 512 && SDL.joystickEventState) {
6841 SDL.queryJoysticks()
6842 }
6843 if (ptr) {
6844 while (SDL.events.length > 0) {
6845 if (SDL.makeCEvent(SDL.events.shift(), ptr) !== false) return 1
6846 }
6847 return 0
6848 } else {
6849 return SDL.events.length > 0
6850 }
6851 },
6852 makeCEvent: function(event, ptr) {
6853 if (typeof event == "number") {
6854 _memcpy(ptr, event, 28);
6855 _free(event);
6856 return
6857 }
6858 SDL.handleEvent(event);
6859 switch (event.type) {
6860 case "keydown":
6861 case "keyup": {
6862 var down = event.type === "keydown";
6863 var key = SDL.lookupKeyCodeForEvent(event);
6864 var scan;
6865 if (key >= 1024) {
6866 scan = key - 1024
6867 } else {
6868 scan = SDL.scanCodes[key] || key
6869 }
6870 HEAP32[ptr >> 2] = SDL.DOMEventToSDLEvent[event.type];
6871 HEAP8[ptr + 8 >> 0] = down ? 1 : 0;
6872 HEAP8[ptr + 9 >> 0] = 0;
6873 HEAP32[ptr + 12 >> 2] = scan;
6874 HEAP32[ptr + 16 >> 2] = key;
6875 HEAP16[ptr + 20 >> 1] = SDL.modState;
6876 HEAP32[ptr + 24 >> 2] = event.keypressCharCode || key;
6877 break
6878 }
6879 case "keypress": {
6880 HEAP32[ptr >> 2] = SDL.DOMEventToSDLEvent[event.type];
6881 var cStr = intArrayFromString(String.fromCharCode(event.charCode));
6882 for (var i = 0; i < cStr.length; ++i) {
6883 HEAP8[ptr + (8 + i) >> 0] = cStr[i]
6884 }
6885 break
6886 }
6887 case "mousedown":
6888 case "mouseup":
6889 case "mousemove": {
6890 if (event.type != "mousemove") {
6891 var down = event.type === "mousedown";
6892 HEAP32[ptr >> 2] = SDL.DOMEventToSDLEvent[event.type];
6893 HEAP32[ptr + 4 >> 2] = 0;
6894 HEAP32[ptr + 8 >> 2] = 0;
6895 HEAP32[ptr + 12 >> 2] = 0;
6896 HEAP8[ptr + 16 >> 0] = event.button + 1;
6897 HEAP8[ptr + 17 >> 0] = down ? 1 : 0;
6898 HEAP32[ptr + 20 >> 2] = Browser.mouseX;
6899 HEAP32[ptr + 24 >> 2] = Browser.mouseY
6900 } else {
6901 HEAP32[ptr >> 2] = SDL.DOMEventToSDLEvent[event.type];
6902 HEAP32[ptr + 4 >> 2] = 0;
6903 HEAP32[ptr + 8 >> 2] = 0;
6904 HEAP32[ptr + 12 >> 2] = 0;
6905 HEAP32[ptr + 16 >> 2] = SDL.buttonState;
6906 HEAP32[ptr + 20 >> 2] = Browser.mouseX;
6907 HEAP32[ptr + 24 >> 2] = Browser.mouseY;
6908 HEAP32[ptr + 28 >> 2] = Browser.mouseMovementX;
6909 HEAP32[ptr + 32 >> 2] = Browser.mouseMovementY
6910 }
6911 break
6912 }
6913 case "wheel": {
6914 HEAP32[ptr >> 2] = SDL.DOMEventToSDLEvent[event.type];
6915 HEAP32[ptr + 16 >> 2] = event.deltaX;
6916 HEAP32[ptr + 20 >> 2] = event.deltaY;
6917 break
6918 }
6919 case "touchstart":
6920 case "touchend":
6921 case "touchmove": {
6922 var touch = event.touch;
6923 if (!Browser.touches[touch.identifier]) break;
6924 var w = Module["canvas"].width;
6925 var h = Module["canvas"].height;
6926 var x = Browser.touches[touch.identifier].x / w;
6927 var y = Browser.touches[touch.identifier].y / h;
6928 var lx = Browser.lastTouches[touch.identifier].x / w;
6929 var ly = Browser.lastTouches[touch.identifier].y / h;
6930 var dx = x - lx;
6931 var dy = y - ly;
6932 if (touch["deviceID"] === undefined) touch.deviceID = SDL.TOUCH_DEFAULT_ID;
6933 if (dx === 0 && dy === 0 && event.type === "touchmove") return false;
6934 HEAP32[ptr >> 2] = SDL.DOMEventToSDLEvent[event.type];
6935 HEAP32[ptr + 4 >> 2] = _SDL_GetTicks();
6936 tempI64 = [touch.deviceID >>> 0, (tempDouble = touch.deviceID, +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 + 8 >> 2] = tempI64[0], HEAP32[ptr + 12 >> 2] = tempI64[1];
6937 tempI64 = [touch.identifier >>> 0, (tempDouble = touch.identifier, +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 + 16 >> 2] = tempI64[0], HEAP32[ptr + 20 >> 2] = tempI64[1];
6938 HEAPF32[ptr + 24 >> 2] = x;
6939 HEAPF32[ptr + 28 >> 2] = y;
6940 HEAPF32[ptr + 32 >> 2] = dx;
6941 HEAPF32[ptr + 36 >> 2] = dy;
6942 if (touch.force !== undefined) {
6943 HEAPF32[ptr + 40 >> 2] = touch.force
6944 } else {
6945 HEAPF32[ptr + 40 >> 2] = event.type == "touchend" ? 0 : 1
6946 }
6947 break
6948 }
6949 case "unload": {
6950 HEAP32[ptr >> 2] = SDL.DOMEventToSDLEvent[event.type];
6951 break
6952 }
6953 case "resize": {
6954 HEAP32[ptr >> 2] = SDL.DOMEventToSDLEvent[event.type];
6955 HEAP32[ptr + 4 >> 2] = event.w;
6956 HEAP32[ptr + 8 >> 2] = event.h;
6957 break
6958 }
6959 case "joystick_button_up":
6960 case "joystick_button_down": {
6961 var state = event.type === "joystick_button_up" ? 0 : 1;
6962 HEAP32[ptr >> 2] = SDL.DOMEventToSDLEvent[event.type];
6963 HEAP8[ptr + 4 >> 0] = event.index;
6964 HEAP8[ptr + 5 >> 0] = event.button;
6965 HEAP8[ptr + 6 >> 0] = state;
6966 break
6967 }
6968 case "joystick_axis_motion": {
6969 HEAP32[ptr >> 2] = SDL.DOMEventToSDLEvent[event.type];
6970 HEAP8[ptr + 4 >> 0] = event.index;
6971 HEAP8[ptr + 5 >> 0] = event.axis;
6972 HEAP32[ptr + 8 >> 2] = SDL.joystickAxisValueConversion(event.value);
6973 break
6974 }
6975 case "focus": {
6976 var SDL_WINDOWEVENT_FOCUS_GAINED = 12;
6977 HEAP32[ptr >> 2] = SDL.DOMEventToSDLEvent[event.type];
6978 HEAP32[ptr + 4 >> 2] = 0;
6979 HEAP8[ptr + 8 >> 0] = SDL_WINDOWEVENT_FOCUS_GAINED;
6980 break
6981 }
6982 case "blur": {
6983 var SDL_WINDOWEVENT_FOCUS_LOST = 13;
6984 HEAP32[ptr >> 2] = SDL.DOMEventToSDLEvent[event.type];
6985 HEAP32[ptr + 4 >> 2] = 0;
6986 HEAP8[ptr + 8 >> 0] = SDL_WINDOWEVENT_FOCUS_LOST;
6987 break
6988 }
6989 case "visibilitychange": {
6990 var SDL_WINDOWEVENT_SHOWN = 1;
6991 var SDL_WINDOWEVENT_HIDDEN = 2;
6992 var visibilityEventID = event.visible ? SDL_WINDOWEVENT_SHOWN : SDL_WINDOWEVENT_HIDDEN;
6993 HEAP32[ptr >> 2] = SDL.DOMEventToSDLEvent[event.type];
6994 HEAP32[ptr + 4 >> 2] = 0;
6995 HEAP8[ptr + 8 >> 0] = visibilityEventID;
6996 break
6997 }
6998 default:
6999 throw "Unhandled SDL event: " + event.type
7000 }
7001 },
7002 makeFontString: function(height, fontName) {
7003 if (fontName.charAt(0) != "'" && fontName.charAt(0) != '"') {
7004 fontName = '"' + fontName + '"'
7005 }
7006 return height + "px " + fontName + ", serif"
7007 },
7008 estimateTextWidth: function(fontData, text) {
7009 var h = fontData.size;
7010 var fontString = SDL.makeFontString(h, fontData.name);
7011 var tempCtx = SDL_ttfContext();
7012 tempCtx.font = fontString;
7013 var ret = tempCtx.measureText(text).width | 0;
7014 return ret
7015 },
7016 allocateChannels: function(num) {
7017 if (SDL.numChannels && SDL.numChannels >= num && num != 0) return;
7018 SDL.numChannels = num;
7019 SDL.channels = [];
7020 for (var i = 0; i < num; i++) {
7021 SDL.channels[i] = {
7022 audio: null,
7023 volume: 1
7024 }
7025 }
7026 },
7027 setGetVolume: function(info, volume) {
7028 if (!info) return 0;
7029 var ret = info.volume * 128;
7030 if (volume != -1) {
7031 info.volume = Math.min(Math.max(volume, 0), 128) / 128;
7032 if (info.audio) {
7033 try {
7034 info.audio.volume = info.volume;
7035 if (info.audio.webAudioGainNode) info.audio.webAudioGainNode["gain"]["value"] = info.volume
7036 } catch (e) {
7037 err("setGetVolume failed to set audio volume: " + e)
7038 }
7039 }
7040 }
7041 return ret
7042 },
7043 setPannerPosition: function(info, x, y, z) {
7044 if (!info) return;
7045 if (info.audio) {
7046 if (info.audio.webAudioPannerNode) {
7047 info.audio.webAudioPannerNode["setPosition"](x, y, z)
7048 }
7049 }
7050 },
7051 playWebAudio: function(audio) {
7052 if (!audio) return;
7053 if (audio.webAudioNode) return;
7054 if (!SDL.webAudioAvailable()) return;
7055 try {
7056 var webAudio = audio.resource.webAudio;
7057 audio.paused = false;
7058 if (!webAudio.decodedBuffer) {
7059 if (webAudio.onDecodeComplete === undefined) abort("Cannot play back audio object that was not loaded");
7060 webAudio.onDecodeComplete.push(function() {
7061 if (!audio.paused) SDL.playWebAudio(audio)
7062 });
7063 return
7064 }
7065 audio.webAudioNode = SDL.audioContext["createBufferSource"]();
7066 audio.webAudioNode["buffer"] = webAudio.decodedBuffer;
7067 audio.webAudioNode["loop"] = audio.loop;
7068 audio.webAudioNode["onended"] = function() {
7069 audio["onended"]()
7070 };
7071 audio.webAudioPannerNode = SDL.audioContext["createPanner"]();
7072 audio.webAudioPannerNode["setPosition"](0, 0, -.5);
7073 audio.webAudioPannerNode["panningModel"] = "equalpower";
7074 audio.webAudioGainNode = SDL.audioContext["createGain"]();
7075 audio.webAudioGainNode["gain"]["value"] = audio.volume;
7076 audio.webAudioNode["connect"](audio.webAudioPannerNode);
7077 audio.webAudioPannerNode["connect"](audio.webAudioGainNode);
7078 audio.webAudioGainNode["connect"](SDL.audioContext["destination"]);
7079 audio.webAudioNode["start"](0, audio.currentPosition);
7080 audio.startTime = SDL.audioContext["currentTime"] - audio.currentPosition
7081 } catch (e) {
7082 err("playWebAudio failed: " + e)
7083 }
7084 },
7085 pauseWebAudio: function(audio) {
7086 if (!audio) return;
7087 if (audio.webAudioNode) {
7088 try {
7089 audio.currentPosition = (SDL.audioContext["currentTime"] - audio.startTime) % audio.resource.webAudio.decodedBuffer.duration;
7090 audio.webAudioNode["onended"] = undefined;
7091 audio.webAudioNode.stop(0);
7092 audio.webAudioNode = undefined
7093 } catch (e) {
7094 err("pauseWebAudio failed: " + e)
7095 }
7096 }
7097 audio.paused = true
7098 },
7099 openAudioContext: function() {
7100 if (!SDL.audioContext) {
7101 if (typeof AudioContext != "undefined") SDL.audioContext = new AudioContext;
7102 else if (typeof webkitAudioContext != "undefined") SDL.audioContext = new webkitAudioContext
7103 }
7104 },
7105 webAudioAvailable: function() {
7106 return !!SDL.audioContext
7107 },
7108 fillWebAudioBufferFromHeap: function(heapPtr, sizeSamplesPerChannel, dstAudioBuffer) {
7109 var audio = SDL_audio();
7110 var numChannels = audio.channels;
7111 for (var c = 0; c < numChannels; ++c) {
7112 var channelData = dstAudioBuffer["getChannelData"](c);
7113 if (channelData.length != sizeSamplesPerChannel) {
7114 throw "Web Audio output buffer length mismatch! Destination size: " + channelData.length + " samples vs expected " + sizeSamplesPerChannel + " samples!"
7115 }
7116 if (audio.format == 32784) {
7117 for (var j = 0; j < sizeSamplesPerChannel; ++j) {
7118 channelData[j] = HEAP16[heapPtr + (j * numChannels + c) * 2 >> 1] / 32768
7119 }
7120 } else if (audio.format == 8) {
7121 for (var j = 0; j < sizeSamplesPerChannel; ++j) {
7122 var v = HEAP8[heapPtr + (j * numChannels + c) >> 0];
7123 channelData[j] = (v >= 0 ? v - 128 : v + 128) / 128
7124 }
7125 } else if (audio.format == 33056) {
7126 for (var j = 0; j < sizeSamplesPerChannel; ++j) {
7127 channelData[j] = HEAPF32[heapPtr + (j * numChannels + c) * 4 >> 2]
7128 }
7129 } else {
7130 throw "Invalid SDL audio format " + audio.format + "!"
7131 }
7132 }
7133 },
7134 debugSurface: function(surfData) {
7135 out("dumping surface " + [surfData.surf, surfData.source, surfData.width, surfData.height]);
7136 var image = surfData.ctx.getImageData(0, 0, surfData.width, surfData.height);
7137 var data = image.data;
7138 var num = Math.min(surfData.width, surfData.height);
7139 for (var i = 0; i < num; i++) {
7140 out(" diagonal " + i + ":" + [data[i * surfData.width * 4 + i * 4 + 0], data[i * surfData.width * 4 + i * 4 + 1], data[i * surfData.width * 4 + i * 4 + 2], data[i * surfData.width * 4 + i * 4 + 3]])
7141 }
7142 },
7143 joystickEventState: 1,
7144 lastJoystickState: {},
7145 joystickNamePool: {},
7146 recordJoystickState: function(joystick, state) {
7147 var buttons = new Array(state.buttons.length);
7148 for (var i = 0; i < state.buttons.length; i++) {
7149 buttons[i] = SDL.getJoystickButtonState(state.buttons[i])
7150 }
7151 SDL.lastJoystickState[joystick] = {
7152 buttons: buttons,
7153 axes: state.axes.slice(0),
7154 timestamp: state.timestamp,
7155 index: state.index,
7156 id: state.id
7157 }
7158 },
7159 getJoystickButtonState: function(button) {
7160 if (typeof button == "object") {
7161 return button["pressed"]
7162 } else {
7163 return button > 0
7164 }
7165 },
7166 queryJoysticks: function() {
7167 for (var joystick in SDL.lastJoystickState) {
7168 var state = SDL.getGamepad(joystick - 1);
7169 var prevState = SDL.lastJoystickState[joystick];
7170 if (typeof state == "undefined") return;
7171 if (state === null) return;
7172 if (typeof state.timestamp != "number" || state.timestamp != prevState.timestamp || !state.timestamp) {
7173 var i;
7174 for (i = 0; i < state.buttons.length; i++) {
7175 var buttonState = SDL.getJoystickButtonState(state.buttons[i]);
7176 if (buttonState !== prevState.buttons[i]) {
7177 SDL.events.push({
7178 type: buttonState ? "joystick_button_down" : "joystick_button_up",
7179 joystick: joystick,
7180 index: joystick - 1,
7181 button: i
7182 })
7183 }
7184 }
7185 for (i = 0; i < state.axes.length; i++) {
7186 if (state.axes[i] !== prevState.axes[i]) {
7187 SDL.events.push({
7188 type: "joystick_axis_motion",
7189 joystick: joystick,
7190 index: joystick - 1,
7191 axis: i,
7192 value: state.axes[i]
7193 })
7194 }
7195 }
7196 SDL.recordJoystickState(joystick, state)
7197 }
7198 }
7199 },
7200 joystickAxisValueConversion: function(value) {
7201 value = Math.min(1, Math.max(value, -1));
7202 return Math.ceil((value + 1) * 32767.5 - 32768)
7203 },
7204 getGamepads: function() {
7205 var fcn = navigator.getGamepads || navigator.webkitGamepads || navigator.mozGamepads || navigator.gamepads || navigator.webkitGetGamepads;
7206 if (fcn !== undefined) {
7207 return fcn.apply(navigator)
7208 } else {
7209 return []
7210 }
7211 },
7212 getGamepad: function(deviceIndex) {
7213 var gamepads = SDL.getGamepads();
7214 if (gamepads.length > deviceIndex && deviceIndex >= 0) {
7215 return gamepads[deviceIndex]
7216 }
7217 return null
7218 }
7219 };
7220
7221 function _SDL_GetNumAudioDrivers() {
7222 return 1
7223 }
7224
7225 function _SDL_Init(initFlags) {
7226 SDL.startTime = Date.now();
7227 SDL.initFlags = initFlags;
7228 if (!Module["doNotCaptureKeyboard"]) {
7229 var keyboardListeningElement = Module["keyboardListeningElement"] || document;
7230 keyboardListeningElement.addEventListener("keydown", SDL.receiveEvent);
7231 keyboardListeningElement.addEventListener("keyup", SDL.receiveEvent);
7232 keyboardListeningElement.addEventListener("keypress", SDL.receiveEvent);
7233 window.addEventListener("focus", SDL.receiveEvent);
7234 window.addEventListener("blur", SDL.receiveEvent);
7235 document.addEventListener("visibilitychange", SDL.receiveEvent)
7236 }
7237 window.addEventListener("unload", SDL.receiveEvent);
7238 SDL.keyboardState = _malloc(65536);
7239 zeroMemory(SDL.keyboardState, 65536);
7240 SDL.DOMEventToSDLEvent["keydown"] = 768;
7241 SDL.DOMEventToSDLEvent["keyup"] = 769;
7242 SDL.DOMEventToSDLEvent["keypress"] = 771;
7243 SDL.DOMEventToSDLEvent["mousedown"] = 1025;
7244 SDL.DOMEventToSDLEvent["mouseup"] = 1026;
7245 SDL.DOMEventToSDLEvent["mousemove"] = 1024;
7246 SDL.DOMEventToSDLEvent["wheel"] = 1027;
7247 SDL.DOMEventToSDLEvent["touchstart"] = 1792;
7248 SDL.DOMEventToSDLEvent["touchend"] = 1793;
7249 SDL.DOMEventToSDLEvent["touchmove"] = 1794;
7250 SDL.DOMEventToSDLEvent["unload"] = 256;
7251 SDL.DOMEventToSDLEvent["resize"] = 28673;
7252 SDL.DOMEventToSDLEvent["visibilitychange"] = 512;
7253 SDL.DOMEventToSDLEvent["focus"] = 512;
7254 SDL.DOMEventToSDLEvent["blur"] = 512;
7255 SDL.DOMEventToSDLEvent["joystick_axis_motion"] = 1536;
7256 SDL.DOMEventToSDLEvent["joystick_button_down"] = 1539;
7257 SDL.DOMEventToSDLEvent["joystick_button_up"] = 1540;
7258 return 0
7259 }
7260
7261 function listenOnce(object, event, func) {
7262 object.addEventListener(event, func, {
7263 "once": true
7264 })
7265 }
7266
7267 function autoResumeAudioContext(ctx, elements) {
7268 if (!elements) {
7269 elements = [document, document.getElementById("canvas")]
7270 } ["keydown", "mousedown", "touchstart"].forEach(function(event) {
7271 elements.forEach(function(element) {
7272 if (element) {
7273 listenOnce(element, event, function() {
7274 if (ctx.state === "suspended") ctx.resume()
7275 })
7276 }
7277 })
7278 })
7279 }
7280
7281 function _SDL_OpenAudio(desired, obtained) {
7282 try {
7283 SDL.audio = {
7284 freq: HEAPU32[desired >> 2],
7285 format: HEAPU16[desired + 4 >> 1],
7286 channels: HEAPU8[desired + 6 >> 0],
7287 samples: HEAPU16[desired + 8 >> 1],
7288 callback: HEAPU32[desired + 16 >> 2],
7289 userdata: HEAPU32[desired + 20 >> 2],
7290 paused: true,
7291 timer: null
7292 };
7293 if (SDL.audio.format == 8) {
7294 SDL.audio.silence = 128
7295 } else if (SDL.audio.format == 32784) {
7296 SDL.audio.silence = 0
7297 } else if (SDL.audio.format == 33056) {
7298 SDL.audio.silence = 0
7299 } else {
7300 throw "Invalid SDL audio format " + SDL.audio.format + "!"
7301 }
7302 if (SDL.audio.freq <= 0) {
7303 throw "Unsupported sound frequency " + SDL.audio.freq + "!"
7304 } else if (SDL.audio.freq <= 22050) {
7305 SDL.audio.freq = 22050
7306 } else if (SDL.audio.freq <= 32e3) {
7307 SDL.audio.freq = 32e3
7308 } else if (SDL.audio.freq <= 44100) {
7309 SDL.audio.freq = 44100
7310 } else if (SDL.audio.freq <= 48e3) {
7311 SDL.audio.freq = 48e3
7312 } else if (SDL.audio.freq <= 96e3) {
7313 SDL.audio.freq = 96e3
7314 } else {
7315 throw "Unsupported sound frequency " + SDL.audio.freq + "!"
7316 }
7317 if (SDL.audio.channels == 0) {
7318 SDL.audio.channels = 1
7319 } else if (SDL.audio.channels < 0 || SDL.audio.channels > 32) {
7320 throw "Unsupported number of audio channels for SDL audio: " + SDL.audio.channels + "!"
7321 } else if (SDL.audio.channels != 1 && SDL.audio.channels != 2) {
7322 out("Warning: Using untested number of audio channels " + SDL.audio.channels)
7323 }
7324 if (SDL.audio.samples < 128 || SDL.audio.samples > 524288) {
7325 throw "Unsupported audio callback buffer size " + SDL.audio.samples + "!"
7326 } else if ((SDL.audio.samples & SDL.audio.samples - 1) != 0) {
7327 throw "Audio callback buffer size " + SDL.audio.samples + " must be a power-of-two!"
7328 }
7329 var totalSamples = SDL.audio.samples * SDL.audio.channels;
7330 if (SDL.audio.format == 8) {
7331 SDL.audio.bytesPerSample = 1
7332 } else if (SDL.audio.format == 32784) {
7333 SDL.audio.bytesPerSample = 2
7334 } else if (SDL.audio.format == 33056) {
7335 SDL.audio.bytesPerSample = 4
7336 } else {
7337 throw "Invalid SDL audio format " + SDL.audio.format + "!"
7338 }
7339 SDL.audio.bufferSize = totalSamples * SDL.audio.bytesPerSample;
7340 SDL.audio.bufferDurationSecs = SDL.audio.bufferSize / SDL.audio.bytesPerSample / SDL.audio.channels / SDL.audio.freq;
7341 SDL.audio.bufferingDelay = 50 / 1e3;
7342 SDL.audio.buffer = _malloc(SDL.audio.bufferSize);
7343 SDL.audio.numSimultaneouslyQueuedBuffers = Module["SDL_numSimultaneouslyQueuedBuffers"] || 5;
7344 SDL.audio.queueNewAudioData = function SDL_queueNewAudioData() {
7345 if (!SDL.audio) return;
7346 for (var i = 0; i < SDL.audio.numSimultaneouslyQueuedBuffers; ++i) {
7347 var secsUntilNextPlayStart = SDL.audio.nextPlayTime - SDL.audioContext["currentTime"];
7348 if (secsUntilNextPlayStart >= SDL.audio.bufferingDelay + SDL.audio.bufferDurationSecs * SDL.audio.numSimultaneouslyQueuedBuffers) return;
7349 getWasmTableEntry(SDL.audio.callback)(SDL.audio.userdata, SDL.audio.buffer, SDL.audio.bufferSize);
7350 SDL.audio.pushAudio(SDL.audio.buffer, SDL.audio.bufferSize)
7351 }
7352 };
7353 SDL.audio.caller = function SDL_audioCaller() {
7354 if (!SDL.audio) return;
7355 --SDL.audio.numAudioTimersPending;
7356 SDL.audio.queueNewAudioData();
7357 var secsUntilNextPlayStart = SDL.audio.nextPlayTime - SDL.audioContext["currentTime"];
7358 var preemptBufferFeedSecs = SDL.audio.bufferDurationSecs / 2;
7359 if (SDL.audio.numAudioTimersPending < SDL.audio.numSimultaneouslyQueuedBuffers) {
7360 ++SDL.audio.numAudioTimersPending;
7361 SDL.audio.timer = safeSetTimeout(SDL.audio.caller, Math.max(0, 1e3 * (secsUntilNextPlayStart - preemptBufferFeedSecs)));
7362 if (SDL.audio.numAudioTimersPending < SDL.audio.numSimultaneouslyQueuedBuffers) {
7363 ++SDL.audio.numAudioTimersPending;
7364 safeSetTimeout(SDL.audio.caller, 1)
7365 }
7366 }
7367 };
7368 SDL.audio.audioOutput = new Audio;
7369 SDL.openAudioContext();
7370 if (!SDL.audioContext) throw "Web Audio API is not available!";
7371 autoResumeAudioContext(SDL.audioContext);
7372 SDL.audio.nextPlayTime = 0;
7373 SDL.audio.pushAudio = function(ptr, sizeBytes) {
7374 try {
7375 if (SDL.audio.paused) return;
7376 var sizeSamples = sizeBytes / SDL.audio.bytesPerSample;
7377 var sizeSamplesPerChannel = sizeSamples / SDL.audio.channels;
7378 if (sizeSamplesPerChannel != SDL.audio.samples) {
7379 throw "Received mismatching audio buffer size!"
7380 }
7381 var source = SDL.audioContext["createBufferSource"]();
7382 var soundBuffer = SDL.audioContext["createBuffer"](SDL.audio.channels, sizeSamplesPerChannel, SDL.audio.freq);
7383 source["connect"](SDL.audioContext["destination"]);
7384 SDL.fillWebAudioBufferFromHeap(ptr, sizeSamplesPerChannel, soundBuffer);
7385 source["buffer"] = soundBuffer;
7386 var curtime = SDL.audioContext["currentTime"];
7387 var playtime = Math.max(curtime + SDL.audio.bufferingDelay, SDL.audio.nextPlayTime);
7388 if (typeof source["start"] != "undefined") {
7389 source["start"](playtime)
7390 } else if (typeof source["noteOn"] != "undefined") {
7391 source["noteOn"](playtime)
7392 }
7393 SDL.audio.nextPlayTime = playtime + SDL.audio.bufferDurationSecs
7394 } catch (e) {
7395 out("Web Audio API error playing back audio: " + e.toString())
7396 }
7397 };
7398 if (obtained) {
7399 HEAP32[obtained >> 2] = SDL.audio.freq;
7400 HEAP16[obtained + 4 >> 1] = SDL.audio.format;
7401 HEAP8[obtained + 6 >> 0] = SDL.audio.channels;
7402 HEAP8[obtained + 7 >> 0] = SDL.audio.silence;
7403 HEAP16[obtained + 8 >> 1] = SDL.audio.samples;
7404 HEAPU32[obtained + 16 >> 2] = SDL.audio.callback;
7405 HEAPU32[obtained + 20 >> 2] = SDL.audio.userdata
7406 }
7407 SDL.allocateChannels(32)
7408 } catch (e) {
7409 out('Initializing SDL audio threw an exception: "' + e.toString() + '"! Continuing without audio.');
7410 SDL.audio = null;
7411 SDL.allocateChannels(0);
7412 if (obtained) {
7413 HEAP32[obtained >> 2] = 0;
7414 HEAP16[obtained + 4 >> 1] = 0;
7415 HEAP8[obtained + 6 >> 0] = 0;
7416 HEAP8[obtained + 7 >> 0] = 0;
7417 HEAP16[obtained + 8 >> 1] = 0;
7418 HEAPU32[obtained + 16 >> 2] = 0;
7419 HEAPU32[obtained + 20 >> 2] = 0
7420 }
7421 }
7422 if (!SDL.audio) {
7423 return -1
7424 }
7425 return 0
7426 }
7427
7428 function _SDL_PauseAudio(pauseOn) {
7429 if (!SDL.audio) {
7430 return
7431 }
7432 if (pauseOn) {
7433 if (SDL.audio.timer !== undefined) {
7434 clearTimeout(SDL.audio.timer);
7435 SDL.audio.numAudioTimersPending = 0;
7436 SDL.audio.timer = undefined
7437 }
7438 } else if (!SDL.audio.timer) {
7439 SDL.audio.numAudioTimersPending = 1;
7440 SDL.audio.timer = safeSetTimeout(SDL.audio.caller, 1)
7441 }
7442 SDL.audio.paused = pauseOn
7443 }
7444
7445 function _SDL_AudioQuit() {
7446 for (var i = 0; i < SDL.numChannels; ++i) {
7447 var chan = SDL.channels[i];
7448 if (chan.audio) {
7449 chan.audio.pause();
7450 chan.audio = undefined
7451 }
7452 }
7453 var audio = SDL.music.audio;
7454 if (audio) audio.pause();
7455 SDL.music.audio = undefined
7456 }
7457
7458 function _SDL_Quit() {
7459 _SDL_AudioQuit();
7460 out("SDL_Quit called (and ignored)")
7461 }
7462
7463 function ___assert_fail(condition, filename, line, func) {
7464 abort("Assertion failed: " + UTF8ToString(condition) + ", at: " + [filename ? UTF8ToString(filename) : "unknown filename", line, func ? UTF8ToString(func) : "unknown function"])
7465 }
7466 var SYSCALLS = {
7467 DEFAULT_POLLMASK: 5,
7468 calculateAt: function(dirfd, path, allowEmpty) {
7469 if (PATH.isAbs(path)) {
7470 return path
7471 }
7472 var dir;
7473 if (dirfd === -100) {
7474 dir = FS.cwd()
7475 } else {
7476 var dirstream = FS.getStream(dirfd);
7477 if (!dirstream) throw new FS.ErrnoError(8);
7478 dir = dirstream.path
7479 }
7480 if (path.length == 0) {
7481 if (!allowEmpty) {
7482 throw new FS.ErrnoError(44)
7483 }
7484 return dir
7485 }
7486 return PATH.join2(dir, path)
7487 },
7488 doStat: function(func, path, buf) {
7489 try {
7490 var stat = func(path)
7491 } catch (e) {
7492 if (e && e.node && PATH.normalize(path) !== PATH.normalize(FS.getPath(e.node))) {
7493 return -54
7494 }
7495 throw e
7496 }
7497 HEAP32[buf >> 2] = stat.dev;
7498 HEAP32[buf + 4 >> 2] = 0;
7499 HEAP32[buf + 8 >> 2] = stat.ino;
7500 HEAP32[buf + 12 >> 2] = stat.mode;
7501 HEAP32[buf + 16 >> 2] = stat.nlink;
7502 HEAP32[buf + 20 >> 2] = stat.uid;
7503 HEAP32[buf + 24 >> 2] = stat.gid;
7504 HEAP32[buf + 28 >> 2] = stat.rdev;
7505 HEAP32[buf + 32 >> 2] = 0;
7506 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];
7507 HEAP32[buf + 48 >> 2] = 4096;
7508 HEAP32[buf + 52 >> 2] = stat.blocks;
7509 HEAP32[buf + 56 >> 2] = stat.atime.getTime() / 1e3 | 0;
7510 HEAP32[buf + 60 >> 2] = 0;
7511 HEAP32[buf + 64 >> 2] = stat.mtime.getTime() / 1e3 | 0;
7512 HEAP32[buf + 68 >> 2] = 0;
7513 HEAP32[buf + 72 >> 2] = stat.ctime.getTime() / 1e3 | 0;
7514 HEAP32[buf + 76 >> 2] = 0;
7515 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];
7516 return 0
7517 },
7518 doMsync: function(addr, stream, len, flags, offset) {
7519 var buffer = HEAPU8.slice(addr, addr + len);
7520 FS.msync(stream, buffer, offset, len, flags)
7521 },
7522 varargs: undefined,
7523 get: function() {
7524 SYSCALLS.varargs += 4;
7525 var ret = HEAP32[SYSCALLS.varargs - 4 >> 2];
7526 return ret
7527 },
7528 getStr: function(ptr) {
7529 var ret = UTF8ToString(ptr);
7530 return ret
7531 },
7532 getStreamFromFD: function(fd) {
7533 var stream = FS.getStream(fd);
7534 if (!stream) throw new FS.ErrnoError(8);
7535 return stream
7536 }
7537 };
7538
7539 function ___syscall_faccessat(dirfd, path, amode, flags) {
7540 try {
7541 path = SYSCALLS.getStr(path);
7542 path = SYSCALLS.calculateAt(dirfd, path);
7543 if (amode & ~7) {
7544 return -28
7545 }
7546 var lookup = FS.lookupPath(path, {
7547 follow: true
7548 });
7549 var node = lookup.node;
7550 if (!node) {
7551 return -44
7552 }
7553 var perms = "";
7554 if (amode & 4) perms += "r";
7555 if (amode & 2) perms += "w";
7556 if (amode & 1) perms += "x";
7557 if (perms && FS.nodePermissions(node, perms)) {
7558 return -2
7559 }
7560 return 0
7561 } catch (e) {
7562 if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e;
7563 return -e.errno
7564 }
7565 }
7566
7567 function setErrNo(value) {
7568 HEAP32[___errno_location() >> 2] = value;
7569 return value
7570 }
7571
7572 function ___syscall_fcntl64(fd, cmd, varargs) {
7573 SYSCALLS.varargs = varargs;
7574 try {
7575 var stream = SYSCALLS.getStreamFromFD(fd);
7576 switch (cmd) {
7577 case 0: {
7578 var arg = SYSCALLS.get();
7579 if (arg < 0) {
7580 return -28
7581 }
7582 var newStream;
7583 newStream = FS.createStream(stream, arg);
7584 return newStream.fd
7585 }
7586 case 1:
7587 case 2:
7588 return 0;
7589 case 3:
7590 return stream.flags;
7591 case 4: {
7592 var arg = SYSCALLS.get();
7593 stream.flags |= arg;
7594 return 0
7595 }
7596 case 5: {
7597 var arg = SYSCALLS.get();
7598 var offset = 0;
7599 HEAP16[arg + offset >> 1] = 2;
7600 return 0
7601 }
7602 case 6:
7603 case 7:
7604 return 0;
7605 case 16:
7606 case 8:
7607 return -28;
7608 case 9:
7609 setErrNo(28);
7610 return -1;
7611 default: {
7612 return -28
7613 }
7614 }
7615 } catch (e) {
7616 if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e;
7617 return -e.errno
7618 }
7619 }
7620
7621 function ___syscall_getdents64(fd, dirp, count) {
7622 try {
7623 var stream = SYSCALLS.getStreamFromFD(fd);
7624 if (!stream.getdents) {
7625 stream.getdents = FS.readdir(stream.path)
7626 }
7627 var struct_size = 280;
7628 var pos = 0;
7629 var off = FS.llseek(stream, 0, 1);
7630 var idx = Math.floor(off / struct_size);
7631 while (idx < stream.getdents.length && pos + struct_size <= count) {
7632 var id;
7633 var type;
7634 var name = stream.getdents[idx];
7635 if (name === ".") {
7636 id = stream.node.id;
7637 type = 4
7638 } else if (name === "..") {
7639 var lookup = FS.lookupPath(stream.path, {
7640 parent: true
7641 });
7642 id = lookup.node.id;
7643 type = 4
7644 } else {
7645 var child = FS.lookupNode(stream.node, name);
7646 id = child.id;
7647 type = FS.isChrdev(child.mode) ? 2 : FS.isDir(child.mode) ? 4 : FS.isLink(child.mode) ? 10 : 8
7648 }
7649 tempI64 = [id >>> 0, (tempDouble = id, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0)], HEAP32[dirp + pos >> 2] = tempI64[0], HEAP32[dirp + pos + 4 >> 2] = tempI64[1];
7650 tempI64 = [(idx + 1) * struct_size >>> 0, (tempDouble = (idx + 1) * struct_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[dirp + pos + 8 >> 2] = tempI64[0], HEAP32[dirp + pos + 12 >> 2] = tempI64[1];
7651 HEAP16[dirp + pos + 16 >> 1] = 280;
7652 HEAP8[dirp + pos + 18 >> 0] = type;
7653 stringToUTF8(name, dirp + pos + 19, 256);
7654 pos += struct_size;
7655 idx += 1
7656 }
7657 FS.llseek(stream, idx * struct_size, 0);
7658 return pos
7659 } catch (e) {
7660 if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e;
7661 return -e.errno
7662 }
7663 }
7664
7665 function ___syscall_ioctl(fd, op, varargs) {
7666 SYSCALLS.varargs = varargs;
7667 try {
7668 var stream = SYSCALLS.getStreamFromFD(fd);
7669 switch (op) {
7670 case 21509:
7671 case 21505: {
7672 if (!stream.tty) return -59;
7673 return 0
7674 }
7675 case 21510:
7676 case 21511:
7677 case 21512:
7678 case 21506:
7679 case 21507:
7680 case 21508: {
7681 if (!stream.tty) return -59;
7682 return 0
7683 }
7684 case 21519: {
7685 if (!stream.tty) return -59;
7686 var argp = SYSCALLS.get();
7687 HEAP32[argp >> 2] = 0;
7688 return 0
7689 }
7690 case 21520: {
7691 if (!stream.tty) return -59;
7692 return -28
7693 }
7694 case 21531: {
7695 var argp = SYSCALLS.get();
7696 return FS.ioctl(stream, op, argp)
7697 }
7698 case 21523: {
7699 if (!stream.tty) return -59;
7700 return 0
7701 }
7702 case 21524: {
7703 if (!stream.tty) return -59;
7704 return 0
7705 }
7706 default:
7707 abort("bad ioctl syscall " + op)
7708 }
7709 } catch (e) {
7710 if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e;
7711 return -e.errno
7712 }
7713 }
7714
7715 function ___syscall_mkdirat(dirfd, path, mode) {
7716 try {
7717 path = SYSCALLS.getStr(path);
7718 path = SYSCALLS.calculateAt(dirfd, path);
7719 path = PATH.normalize(path);
7720 if (path[path.length - 1] === "/") path = path.substr(0, path.length - 1);
7721 FS.mkdir(path, mode, 0);
7722 return 0
7723 } catch (e) {
7724 if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e;
7725 return -e.errno
7726 }
7727 }
7728
7729 function ___syscall_openat(dirfd, path, flags, varargs) {
7730 SYSCALLS.varargs = varargs;
7731 try {
7732 path = SYSCALLS.getStr(path);
7733 path = SYSCALLS.calculateAt(dirfd, path);
7734 var mode = varargs ? SYSCALLS.get() : 0;
7735 return FS.open(path, flags, mode).fd
7736 } catch (e) {
7737 if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e;
7738 return -e.errno
7739 }
7740 }
7741
7742 function ___syscall_renameat(olddirfd, oldpath, newdirfd, newpath) {
7743 try {
7744 oldpath = SYSCALLS.getStr(oldpath);
7745 newpath = SYSCALLS.getStr(newpath);
7746 oldpath = SYSCALLS.calculateAt(olddirfd, oldpath);
7747 newpath = SYSCALLS.calculateAt(newdirfd, newpath);
7748 FS.rename(oldpath, newpath);
7749 return 0
7750 } catch (e) {
7751 if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e;
7752 return -e.errno
7753 }
7754 }
7755
7756 function ___syscall_rmdir(path) {
7757 try {
7758 path = SYSCALLS.getStr(path);
7759 FS.rmdir(path);
7760 return 0
7761 } catch (e) {
7762 if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e;
7763 return -e.errno
7764 }
7765 }
7766
7767 function ___syscall_stat64(path, buf) {
7768 try {
7769 path = SYSCALLS.getStr(path);
7770 return SYSCALLS.doStat(FS.stat, path, buf)
7771 } catch (e) {
7772 if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e;
7773 return -e.errno
7774 }
7775 }
7776
7777 function ___syscall_unlinkat(dirfd, path, flags) {
7778 try {
7779 path = SYSCALLS.getStr(path);
7780 path = SYSCALLS.calculateAt(dirfd, path);
7781 if (flags === 0) {
7782 FS.unlink(path)
7783 } else if (flags === 512) {
7784 FS.rmdir(path)
7785 } else {
7786 abort("Invalid flags passed to unlinkat")
7787 }
7788 return 0
7789 } catch (e) {
7790 if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e;
7791 return -e.errno
7792 }
7793 }
7794
7795 function __emscripten_date_now() {
7796 return Date.now()
7797 }
7798
7799 function __localtime_js(time, tmPtr) {
7800 var date = new Date(HEAP32[time >> 2] * 1e3);
7801 HEAP32[tmPtr >> 2] = date.getSeconds();
7802 HEAP32[tmPtr + 4 >> 2] = date.getMinutes();
7803 HEAP32[tmPtr + 8 >> 2] = date.getHours();
7804 HEAP32[tmPtr + 12 >> 2] = date.getDate();
7805 HEAP32[tmPtr + 16 >> 2] = date.getMonth();
7806 HEAP32[tmPtr + 20 >> 2] = date.getFullYear() - 1900;
7807 HEAP32[tmPtr + 24 >> 2] = date.getDay();
7808 var start = new Date(date.getFullYear(), 0, 1);
7809 var yday = (date.getTime() - start.getTime()) / (1e3 * 60 * 60 * 24) | 0;
7810 HEAP32[tmPtr + 28 >> 2] = yday;
7811 HEAP32[tmPtr + 36 >> 2] = -(date.getTimezoneOffset() * 60);
7812 var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset();
7813 var winterOffset = start.getTimezoneOffset();
7814 var dst = (summerOffset != winterOffset && date.getTimezoneOffset() == Math.min(winterOffset, summerOffset)) | 0;
7815 HEAP32[tmPtr + 32 >> 2] = dst
7816 }
7817
7818 function __mktime_js(tmPtr) {
7819 var date = new Date(HEAP32[tmPtr + 20 >> 2] + 1900, HEAP32[tmPtr + 16 >> 2], HEAP32[tmPtr + 12 >> 2], HEAP32[tmPtr + 8 >> 2], HEAP32[tmPtr + 4 >> 2], HEAP32[tmPtr >> 2], 0);
7820 var dst = HEAP32[tmPtr + 32 >> 2];
7821 var guessedOffset = date.getTimezoneOffset();
7822 var start = new Date(date.getFullYear(), 0, 1);
7823 var summerOffset = new Date(date.getFullYear(), 6, 1).getTimezoneOffset();
7824 var winterOffset = start.getTimezoneOffset();
7825 var dstOffset = Math.min(winterOffset, summerOffset);
7826 if (dst < 0) {
7827 HEAP32[tmPtr + 32 >> 2] = Number(summerOffset != winterOffset && dstOffset == guessedOffset)
7828 } else if (dst > 0 != (dstOffset == guessedOffset)) {
7829 var nonDstOffset = Math.max(winterOffset, summerOffset);
7830 var trueOffset = dst > 0 ? dstOffset : nonDstOffset;
7831 date.setTime(date.getTime() + (trueOffset - guessedOffset) * 6e4)
7832 }
7833 HEAP32[tmPtr + 24 >> 2] = date.getDay();
7834 var yday = (date.getTime() - start.getTime()) / (1e3 * 60 * 60 * 24) | 0;
7835 HEAP32[tmPtr + 28 >> 2] = yday;
7836 HEAP32[tmPtr >> 2] = date.getSeconds();
7837 HEAP32[tmPtr + 4 >> 2] = date.getMinutes();
7838 HEAP32[tmPtr + 8 >> 2] = date.getHours();
7839 HEAP32[tmPtr + 12 >> 2] = date.getDate();
7840 HEAP32[tmPtr + 16 >> 2] = date.getMonth();
7841 return date.getTime() / 1e3 | 0
7842 }
7843
7844 function _tzset_impl(timezone, daylight, tzname) {
7845 var currentYear = (new Date).getFullYear();
7846 var winter = new Date(currentYear, 0, 1);
7847 var summer = new Date(currentYear, 6, 1);
7848 var winterOffset = winter.getTimezoneOffset();
7849 var summerOffset = summer.getTimezoneOffset();
7850 var stdTimezoneOffset = Math.max(winterOffset, summerOffset);
7851 HEAP32[timezone >> 2] = stdTimezoneOffset * 60;
7852 HEAP32[daylight >> 2] = Number(winterOffset != summerOffset);
7853
7854 function extractZone(date) {
7855 var match = date.toTimeString().match(/\(([A-Za-z ]+)\)$/);
7856 return match ? match[1] : "GMT"
7857 }
7858 var winterName = extractZone(winter);
7859 var summerName = extractZone(summer);
7860 var winterNamePtr = allocateUTF8(winterName);
7861 var summerNamePtr = allocateUTF8(summerName);
7862 if (summerOffset < winterOffset) {
7863 HEAPU32[tzname >> 2] = winterNamePtr;
7864 HEAPU32[tzname + 4 >> 2] = summerNamePtr
7865 } else {
7866 HEAPU32[tzname >> 2] = summerNamePtr;
7867 HEAPU32[tzname + 4 >> 2] = winterNamePtr
7868 }
7869 }
7870
7871 function __tzset_js(timezone, daylight, tzname) {
7872 if (__tzset_js.called) return;
7873 __tzset_js.called = true;
7874 _tzset_impl(timezone, daylight, tzname)
7875 }
7876
7877 function _abort() {
7878 abort("")
7879 }
7880 var readAsmConstArgsArray = [];
7881
7882 function readAsmConstArgs(sigPtr, buf) {
7883 readAsmConstArgsArray.length = 0;
7884 var ch;
7885 buf >>= 2;
7886 while (ch = HEAPU8[sigPtr++]) {
7887 buf += ch != 105 & buf;
7888 readAsmConstArgsArray.push(ch == 105 ? HEAP32[buf] : HEAPF64[buf++ >> 1]);
7889 ++buf
7890 }
7891 return readAsmConstArgsArray
7892 }
7893
7894 function _emscripten_asm_const_int(code, sigPtr, argbuf) {
7895 var args = readAsmConstArgs(sigPtr, argbuf);
7896 return ASM_CONSTS[code].apply(null, args)
7897 }
7898
7899 function _emscripten_cancel_main_loop() {
7900 Browser.mainLoop.pause();
7901 Browser.mainLoop.func = null
7902 }
7903
7904 function _emscripten_memcpy_big(dest, src, num) {
7905 HEAPU8.copyWithin(dest, src, src + num)
7906 }
7907 var JSEvents = {
7908 inEventHandler: 0,
7909 removeAllEventListeners: function() {
7910 for (var i = JSEvents.eventHandlers.length - 1; i >= 0; --i) {
7911 JSEvents._removeHandler(i)
7912 }
7913 JSEvents.eventHandlers = [];
7914 JSEvents.deferredCalls = []
7915 },
7916 registerRemoveEventListeners: function() {
7917 if (!JSEvents.removeEventListenersRegistered) {
7918 __ATEXIT__.push(JSEvents.removeAllEventListeners);
7919 JSEvents.removeEventListenersRegistered = true
7920 }
7921 },
7922 deferredCalls: [],
7923 deferCall: function(targetFunction, precedence, argsList) {
7924 function arraysHaveEqualContent(arrA, arrB) {
7925 if (arrA.length != arrB.length) return false;
7926 for (var i in arrA) {
7927 if (arrA[i] != arrB[i]) return false
7928 }
7929 return true
7930 }
7931 for (var i in JSEvents.deferredCalls) {
7932 var call = JSEvents.deferredCalls[i];
7933 if (call.targetFunction == targetFunction && arraysHaveEqualContent(call.argsList, argsList)) {
7934 return
7935 }
7936 }
7937 JSEvents.deferredCalls.push({
7938 targetFunction: targetFunction,
7939 precedence: precedence,
7940 argsList: argsList
7941 });
7942 JSEvents.deferredCalls.sort(function(x, y) {
7943 return x.precedence < y.precedence
7944 })
7945 },
7946 removeDeferredCalls: function(targetFunction) {
7947 for (var i = 0; i < JSEvents.deferredCalls.length; ++i) {
7948 if (JSEvents.deferredCalls[i].targetFunction == targetFunction) {
7949 JSEvents.deferredCalls.splice(i, 1);
7950 --i
7951 }
7952 }
7953 },
7954 canPerformEventHandlerRequests: function() {
7955 return JSEvents.inEventHandler && JSEvents.currentEventHandler.allowsDeferredCalls
7956 },
7957 runDeferredCalls: function() {
7958 if (!JSEvents.canPerformEventHandlerRequests()) {
7959 return
7960 }
7961 for (var i = 0; i < JSEvents.deferredCalls.length; ++i) {
7962 var call = JSEvents.deferredCalls[i];
7963 JSEvents.deferredCalls.splice(i, 1);
7964 --i;
7965 call.targetFunction.apply(null, call.argsList)
7966 }
7967 },
7968 eventHandlers: [],
7969 removeAllHandlersOnTarget: function(target, eventTypeString) {
7970 for (var i = 0; i < JSEvents.eventHandlers.length; ++i) {
7971 if (JSEvents.eventHandlers[i].target == target && (!eventTypeString || eventTypeString == JSEvents.eventHandlers[i].eventTypeString)) {
7972 JSEvents._removeHandler(i--)
7973 }
7974 }
7975 },
7976 _removeHandler: function(i) {
7977 var h = JSEvents.eventHandlers[i];
7978 h.target.removeEventListener(h.eventTypeString, h.eventListenerFunc, h.useCapture);
7979 JSEvents.eventHandlers.splice(i, 1)
7980 },
7981 registerOrRemoveHandler: function(eventHandler) {
7982 var jsEventHandler = function jsEventHandler(event) {
7983 ++JSEvents.inEventHandler;
7984 JSEvents.currentEventHandler = eventHandler;
7985 JSEvents.runDeferredCalls();
7986 eventHandler.handlerFunc(event);
7987 JSEvents.runDeferredCalls();
7988 --JSEvents.inEventHandler
7989 };
7990 if (eventHandler.callbackfunc) {
7991 eventHandler.eventListenerFunc = jsEventHandler;
7992 eventHandler.target.addEventListener(eventHandler.eventTypeString, jsEventHandler, eventHandler.useCapture);
7993 JSEvents.eventHandlers.push(eventHandler);
7994 JSEvents.registerRemoveEventListeners()
7995 } else {
7996 for (var i = 0; i < JSEvents.eventHandlers.length; ++i) {
7997 if (JSEvents.eventHandlers[i].target == eventHandler.target && JSEvents.eventHandlers[i].eventTypeString == eventHandler.eventTypeString) {
7998 JSEvents._removeHandler(i--)
7999 }
8000 }
8001 }
8002 },
8003 getNodeNameForTarget: function(target) {
8004 if (!target) return "";
8005 if (target == window) return "#window";
8006 if (target == screen) return "#screen";
8007 return target && target.nodeName ? target.nodeName : ""
8008 },
8009 fullscreenEnabled: function() {
8010 return document.fullscreenEnabled || document.webkitFullscreenEnabled
8011 }
8012 };
8013
8014 function setLetterbox(element, topBottom, leftRight) {
8015 element.style.paddingLeft = element.style.paddingRight = leftRight + "px";
8016 element.style.paddingTop = element.style.paddingBottom = topBottom + "px"
8017 }
8018
8019 function maybeCStringToJsString(cString) {
8020 return cString > 2 ? UTF8ToString(cString) : cString
8021 }
8022 var specialHTMLTargets = [0, typeof document != "undefined" ? document : 0, typeof window != "undefined" ? window : 0];
8023
8024 function findEventTarget(target) {
8025 target = maybeCStringToJsString(target);
8026 var domElement = specialHTMLTargets[target] || (typeof document != "undefined" ? document.querySelector(target) : undefined);
8027 return domElement
8028 }
8029
8030 function findCanvasEventTarget(target) {
8031 return findEventTarget(target)
8032 }
8033
8034 function _emscripten_set_canvas_element_size(target, width, height) {
8035 var canvas = findCanvasEventTarget(target);
8036 if (!canvas) return -4;
8037 canvas.width = width;
8038 canvas.height = height;
8039 return 0
8040 }
8041
8042 function _emscripten_get_canvas_element_size(target, width, height) {
8043 var canvas = findCanvasEventTarget(target);
8044 if (!canvas) return -4;
8045 HEAP32[width >> 2] = canvas.width;
8046 HEAP32[height >> 2] = canvas.height
8047 }
8048
8049 function getCanvasElementSize(target) {
8050 return withStackSave(function() {
8051 var w = stackAlloc(8);
8052 var h = w + 4;
8053 var targetInt = stackAlloc(target.id.length + 1);
8054 stringToUTF8(target.id, targetInt, target.id.length + 1);
8055 var ret = _emscripten_get_canvas_element_size(targetInt, w, h);
8056 var size = [HEAP32[w >> 2], HEAP32[h >> 2]];
8057 return size
8058 })
8059 }
8060
8061 function setCanvasElementSize(target, width, height) {
8062 if (!target.controlTransferredOffscreen) {
8063 target.width = width;
8064 target.height = height
8065 } else {
8066 withStackSave(function() {
8067 var targetInt = stackAlloc(target.id.length + 1);
8068 stringToUTF8(target.id, targetInt, target.id.length + 1);
8069 _emscripten_set_canvas_element_size(targetInt, width, height)
8070 })
8071 }
8072 }
8073
8074 function registerRestoreOldStyle(canvas) {
8075 var canvasSize = getCanvasElementSize(canvas);
8076 var oldWidth = canvasSize[0];
8077 var oldHeight = canvasSize[1];
8078 var oldCssWidth = canvas.style.width;
8079 var oldCssHeight = canvas.style.height;
8080 var oldBackgroundColor = canvas.style.backgroundColor;
8081 var oldDocumentBackgroundColor = document.body.style.backgroundColor;
8082 var oldPaddingLeft = canvas.style.paddingLeft;
8083 var oldPaddingRight = canvas.style.paddingRight;
8084 var oldPaddingTop = canvas.style.paddingTop;
8085 var oldPaddingBottom = canvas.style.paddingBottom;
8086 var oldMarginLeft = canvas.style.marginLeft;
8087 var oldMarginRight = canvas.style.marginRight;
8088 var oldMarginTop = canvas.style.marginTop;
8089 var oldMarginBottom = canvas.style.marginBottom;
8090 var oldDocumentBodyMargin = document.body.style.margin;
8091 var oldDocumentOverflow = document.documentElement.style.overflow;
8092 var oldDocumentScroll = document.body.scroll;
8093 var oldImageRendering = canvas.style.imageRendering;
8094
8095 function restoreOldStyle() {
8096 var fullscreenElement = document.fullscreenElement || document.webkitFullscreenElement || document.msFullscreenElement;
8097 if (!fullscreenElement) {
8098 document.removeEventListener("fullscreenchange", restoreOldStyle);
8099 document.removeEventListener("webkitfullscreenchange", restoreOldStyle);
8100 setCanvasElementSize(canvas, oldWidth, oldHeight);
8101 canvas.style.width = oldCssWidth;
8102 canvas.style.height = oldCssHeight;
8103 canvas.style.backgroundColor = oldBackgroundColor;
8104 if (!oldDocumentBackgroundColor) document.body.style.backgroundColor = "white";
8105 document.body.style.backgroundColor = oldDocumentBackgroundColor;
8106 canvas.style.paddingLeft = oldPaddingLeft;
8107 canvas.style.paddingRight = oldPaddingRight;
8108 canvas.style.paddingTop = oldPaddingTop;
8109 canvas.style.paddingBottom = oldPaddingBottom;
8110 canvas.style.marginLeft = oldMarginLeft;
8111 canvas.style.marginRight = oldMarginRight;
8112 canvas.style.marginTop = oldMarginTop;
8113 canvas.style.marginBottom = oldMarginBottom;
8114 document.body.style.margin = oldDocumentBodyMargin;
8115 document.documentElement.style.overflow = oldDocumentOverflow;
8116 document.body.scroll = oldDocumentScroll;
8117 canvas.style.imageRendering = oldImageRendering;
8118 if (canvas.GLctxObject) canvas.GLctxObject.GLctx.viewport(0, 0, oldWidth, oldHeight);
8119 if (currentFullscreenStrategy.canvasResizedCallback) {
8120 getWasmTableEntry(currentFullscreenStrategy.canvasResizedCallback)(37, 0, currentFullscreenStrategy.canvasResizedCallbackUserData)
8121 }
8122 }
8123 }
8124 document.addEventListener("fullscreenchange", restoreOldStyle);
8125 document.addEventListener("webkitfullscreenchange", restoreOldStyle);
8126 return restoreOldStyle
8127 }
8128
8129 function getBoundingClientRect(e) {
8130 return specialHTMLTargets.indexOf(e) < 0 ? e.getBoundingClientRect() : {
8131 "left": 0,
8132 "top": 0
8133 }
8134 }
8135
8136 function JSEvents_resizeCanvasForFullscreen(target, strategy) {
8137 var restoreOldStyle = registerRestoreOldStyle(target);
8138 var cssWidth = strategy.softFullscreen ? innerWidth : screen.width;
8139 var cssHeight = strategy.softFullscreen ? innerHeight : screen.height;
8140 var rect = getBoundingClientRect(target);
8141 var windowedCssWidth = rect.width;
8142 var windowedCssHeight = rect.height;
8143 var canvasSize = getCanvasElementSize(target);
8144 var windowedRttWidth = canvasSize[0];
8145 var windowedRttHeight = canvasSize[1];
8146 if (strategy.scaleMode == 3) {
8147 setLetterbox(target, (cssHeight - windowedCssHeight) / 2, (cssWidth - windowedCssWidth) / 2);
8148 cssWidth = windowedCssWidth;
8149 cssHeight = windowedCssHeight
8150 } else if (strategy.scaleMode == 2) {
8151 if (cssWidth * windowedRttHeight < windowedRttWidth * cssHeight) {
8152 var desiredCssHeight = windowedRttHeight * cssWidth / windowedRttWidth;
8153 setLetterbox(target, (cssHeight - desiredCssHeight) / 2, 0);
8154 cssHeight = desiredCssHeight
8155 } else {
8156 var desiredCssWidth = windowedRttWidth * cssHeight / windowedRttHeight;
8157 setLetterbox(target, 0, (cssWidth - desiredCssWidth) / 2);
8158 cssWidth = desiredCssWidth
8159 }
8160 }
8161 if (!target.style.backgroundColor) target.style.backgroundColor = "black";
8162 if (!document.body.style.backgroundColor) document.body.style.backgroundColor = "black";
8163 target.style.width = cssWidth + "px";
8164 target.style.height = cssHeight + "px";
8165 if (strategy.filteringMode == 1) {
8166 target.style.imageRendering = "optimizeSpeed";
8167 target.style.imageRendering = "-moz-crisp-edges";
8168 target.style.imageRendering = "-o-crisp-edges";
8169 target.style.imageRendering = "-webkit-optimize-contrast";
8170 target.style.imageRendering = "optimize-contrast";
8171 target.style.imageRendering = "crisp-edges";
8172 target.style.imageRendering = "pixelated"
8173 }
8174 var dpiScale = strategy.canvasResolutionScaleMode == 2 ? devicePixelRatio : 1;
8175 if (strategy.canvasResolutionScaleMode != 0) {
8176 var newWidth = cssWidth * dpiScale | 0;
8177 var newHeight = cssHeight * dpiScale | 0;
8178 setCanvasElementSize(target, newWidth, newHeight);
8179 if (target.GLctxObject) target.GLctxObject.GLctx.viewport(0, 0, newWidth, newHeight)
8180 }
8181 return restoreOldStyle
8182 }
8183
8184 function JSEvents_requestFullscreen(target, strategy) {
8185 if (strategy.scaleMode != 0 || strategy.canvasResolutionScaleMode != 0) {
8186 JSEvents_resizeCanvasForFullscreen(target, strategy)
8187 }
8188 if (target.requestFullscreen) {
8189 target.requestFullscreen()
8190 } else if (target.webkitRequestFullscreen) {
8191 target.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT)
8192 } else {
8193 return JSEvents.fullscreenEnabled() ? -3 : -1
8194 }
8195 currentFullscreenStrategy = strategy;
8196 if (strategy.canvasResizedCallback) {
8197 getWasmTableEntry(strategy.canvasResizedCallback)(37, 0, strategy.canvasResizedCallbackUserData)
8198 }
8199 return 0
8200 }
8201
8202 function doRequestFullscreen(target, strategy) {
8203 if (!JSEvents.fullscreenEnabled()) return -1;
8204 target = findEventTarget(target);
8205 if (!target) return -4;
8206 if (!target.requestFullscreen && !target.webkitRequestFullscreen) {
8207 return -3
8208 }
8209 var canPerformRequests = JSEvents.canPerformEventHandlerRequests();
8210 if (!canPerformRequests) {
8211 if (strategy.deferUntilInEventHandler) {
8212 JSEvents.deferCall(JSEvents_requestFullscreen, 1, [target, strategy]);
8213 return 1
8214 } else {
8215 return -2
8216 }
8217 }
8218 return JSEvents_requestFullscreen(target, strategy)
8219 }
8220 var currentFullscreenStrategy = {};
8221
8222 function _emscripten_request_fullscreen_strategy(target, deferUntilInEventHandler, fullscreenStrategy) {
8223 var strategy = {
8224 scaleMode: HEAP32[fullscreenStrategy >> 2],
8225 canvasResolutionScaleMode: HEAP32[fullscreenStrategy + 4 >> 2],
8226 filteringMode: HEAP32[fullscreenStrategy + 8 >> 2],
8227 deferUntilInEventHandler: deferUntilInEventHandler,
8228 canvasResizedCallback: HEAP32[fullscreenStrategy + 12 >> 2],
8229 canvasResizedCallbackUserData: HEAP32[fullscreenStrategy + 16 >> 2]
8230 };
8231 return doRequestFullscreen(target, strategy)
8232 }
8233
8234 function getHeapMax() {
8235 return 2147483648
8236 }
8237
8238 function emscripten_realloc_buffer(size) {
8239 try {
8240 wasmMemory.grow(size - buffer.byteLength + 65535 >>> 16);
8241 updateGlobalBufferAndViews(wasmMemory.buffer);
8242 return 1
8243 } catch (e) {}
8244 }
8245
8246 function _emscripten_resize_heap(requestedSize) {
8247 var oldSize = HEAPU8.length;
8248 requestedSize = requestedSize >>> 0;
8249 var maxHeapSize = getHeapMax();
8250 if (requestedSize > maxHeapSize) {
8251 return false
8252 }
8253 let alignUp = (x, multiple) => x + (multiple - x % multiple) % multiple;
8254 for (var cutDown = 1; cutDown <= 4; cutDown *= 2) {
8255 var overGrownHeapSize = oldSize * (1 + .2 / cutDown);
8256 overGrownHeapSize = Math.min(overGrownHeapSize, requestedSize + 100663296);
8257 var newSize = Math.min(maxHeapSize, alignUp(Math.max(requestedSize, overGrownHeapSize), 65536));
8258 var replacement = emscripten_realloc_buffer(newSize);
8259 if (replacement) {
8260 return true
8261 }
8262 }
8263 return false
8264 }
8265
8266 function _emscripten_set_main_loop(func, fps, simulateInfiniteLoop) {
8267 var browserIterationFunc = getWasmTableEntry(func);
8268 setMainLoop(browserIterationFunc, fps, simulateInfiniteLoop)
8269 }
8270
8271 function fillMouseEventData(eventStruct, e, target) {
8272 HEAPF64[eventStruct >> 3] = e.timeStamp;
8273 var idx = eventStruct >> 2;
8274 HEAP32[idx + 2] = e.screenX;
8275 HEAP32[idx + 3] = e.screenY;
8276 HEAP32[idx + 4] = e.clientX;
8277 HEAP32[idx + 5] = e.clientY;
8278 HEAP32[idx + 6] = e.ctrlKey;
8279 HEAP32[idx + 7] = e.shiftKey;
8280 HEAP32[idx + 8] = e.altKey;
8281 HEAP32[idx + 9] = e.metaKey;
8282 HEAP16[idx * 2 + 20] = e.button;
8283 HEAP16[idx * 2 + 21] = e.buttons;
8284 HEAP32[idx + 11] = e["movementX"];
8285 HEAP32[idx + 12] = e["movementY"];
8286 var rect = getBoundingClientRect(target);
8287 HEAP32[idx + 13] = e.clientX - rect.left;
8288 HEAP32[idx + 14] = e.clientY - rect.top
8289 }
8290
8291 function registerMouseEventCallback(target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) {
8292 if (!JSEvents.mouseEvent) JSEvents.mouseEvent = _malloc(72);
8293 target = findEventTarget(target);
8294 var mouseEventHandlerFunc = function(ev) {
8295 var e = ev || event;
8296 fillMouseEventData(JSEvents.mouseEvent, e, target);
8297 if (getWasmTableEntry(callbackfunc)(eventTypeId, JSEvents.mouseEvent, userData)) e.preventDefault()
8298 };
8299 var eventHandler = {
8300 target: target,
8301 allowsDeferredCalls: eventTypeString != "mousemove" && eventTypeString != "mouseenter" && eventTypeString != "mouseleave",
8302 eventTypeString: eventTypeString,
8303 callbackfunc: callbackfunc,
8304 handlerFunc: mouseEventHandlerFunc,
8305 useCapture: useCapture
8306 };
8307 JSEvents.registerOrRemoveHandler(eventHandler)
8308 }
8309
8310 function _emscripten_set_mousedown_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
8311 registerMouseEventCallback(target, userData, useCapture, callbackfunc, 5, "mousedown", targetThread);
8312 return 0
8313 }
8314
8315 function _emscripten_set_mousemove_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
8316 registerMouseEventCallback(target, userData, useCapture, callbackfunc, 8, "mousemove", targetThread);
8317 return 0
8318 }
8319
8320 function _emscripten_set_mouseup_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
8321 registerMouseEventCallback(target, userData, useCapture, callbackfunc, 6, "mouseup", targetThread);
8322 return 0
8323 }
8324
8325 function registerTouchEventCallback(target, userData, useCapture, callbackfunc, eventTypeId, eventTypeString, targetThread) {
8326 if (!JSEvents.touchEvent) JSEvents.touchEvent = _malloc(1696);
8327 target = findEventTarget(target);
8328 var touchEventHandlerFunc = function(e) {
8329 var t, touches = {},
8330 et = e.touches;
8331 for (var i = 0; i < et.length; ++i) {
8332 t = et[i];
8333 t.isChanged = t.onTarget = 0;
8334 touches[t.identifier] = t
8335 }
8336 for (var i = 0; i < e.changedTouches.length; ++i) {
8337 t = e.changedTouches[i];
8338 t.isChanged = 1;
8339 touches[t.identifier] = t
8340 }
8341 for (var i = 0; i < e.targetTouches.length; ++i) {
8342 touches[e.targetTouches[i].identifier].onTarget = 1
8343 }
8344 var touchEvent = JSEvents.touchEvent;
8345 HEAPF64[touchEvent >> 3] = e.timeStamp;
8346 var idx = touchEvent >> 2;
8347 HEAP32[idx + 3] = e.ctrlKey;
8348 HEAP32[idx + 4] = e.shiftKey;
8349 HEAP32[idx + 5] = e.altKey;
8350 HEAP32[idx + 6] = e.metaKey;
8351 idx += 7;
8352 var targetRect = getBoundingClientRect(target);
8353 var numTouches = 0;
8354 for (var i in touches) {
8355 t = touches[i];
8356 HEAP32[idx + 0] = t.identifier;
8357 HEAP32[idx + 1] = t.screenX;
8358 HEAP32[idx + 2] = t.screenY;
8359 HEAP32[idx + 3] = t.clientX;
8360 HEAP32[idx + 4] = t.clientY;
8361 HEAP32[idx + 5] = t.pageX;
8362 HEAP32[idx + 6] = t.pageY;
8363 HEAP32[idx + 7] = t.isChanged;
8364 HEAP32[idx + 8] = t.onTarget;
8365 HEAP32[idx + 9] = t.clientX - targetRect.left;
8366 HEAP32[idx + 10] = t.clientY - targetRect.top;
8367 idx += 13;
8368 if (++numTouches > 31) {
8369 break
8370 }
8371 }
8372 HEAP32[touchEvent + 8 >> 2] = numTouches;
8373 if (getWasmTableEntry(callbackfunc)(eventTypeId, touchEvent, userData)) e.preventDefault()
8374 };
8375 var eventHandler = {
8376 target: target,
8377 allowsDeferredCalls: eventTypeString == "touchstart" || eventTypeString == "touchend",
8378 eventTypeString: eventTypeString,
8379 callbackfunc: callbackfunc,
8380 handlerFunc: touchEventHandlerFunc,
8381 useCapture: useCapture
8382 };
8383 JSEvents.registerOrRemoveHandler(eventHandler)
8384 }
8385
8386 function _emscripten_set_touchcancel_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
8387 registerTouchEventCallback(target, userData, useCapture, callbackfunc, 25, "touchcancel", targetThread);
8388 return 0
8389 }
8390
8391 function _emscripten_set_touchend_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
8392 registerTouchEventCallback(target, userData, useCapture, callbackfunc, 23, "touchend", targetThread);
8393 return 0
8394 }
8395
8396 function _emscripten_set_touchmove_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
8397 registerTouchEventCallback(target, userData, useCapture, callbackfunc, 24, "touchmove", targetThread);
8398 return 0
8399 }
8400
8401 function _emscripten_set_touchstart_callback_on_thread(target, userData, useCapture, callbackfunc, targetThread) {
8402 registerTouchEventCallback(target, userData, useCapture, callbackfunc, 22, "touchstart", targetThread);
8403 return 0
8404 }
8405
8406 function _fd_close(fd) {
8407 try {
8408 var stream = SYSCALLS.getStreamFromFD(fd);
8409 FS.close(stream);
8410 return 0
8411 } catch (e) {
8412 if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e;
8413 return e.errno
8414 }
8415 }
8416
8417 function doReadv(stream, iov, iovcnt, offset) {
8418 var ret = 0;
8419 for (var i = 0; i < iovcnt; i++) {
8420 var ptr = HEAPU32[iov >> 2];
8421 var len = HEAPU32[iov + 4 >> 2];
8422 iov += 8;
8423 var curr = FS.read(stream, HEAP8, ptr, len, offset);
8424 if (curr < 0) return -1;
8425 ret += curr;
8426 if (curr < len) break
8427 }
8428 return ret
8429 }
8430
8431 function _fd_read(fd, iov, iovcnt, pnum) {
8432 try {
8433 var stream = SYSCALLS.getStreamFromFD(fd);
8434 var num = doReadv(stream, iov, iovcnt);
8435 HEAP32[pnum >> 2] = num;
8436 return 0
8437 } catch (e) {
8438 if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e;
8439 return e.errno
8440 }
8441 }
8442
8443 function convertI32PairToI53Checked(lo, hi) {
8444 return hi + 2097152 >>> 0 < 4194305 - !!lo ? (lo >>> 0) + hi * 4294967296 : NaN
8445 }
8446
8447 function _fd_seek(fd, offset_low, offset_high, whence, newOffset) {
8448 try {
8449 var offset = convertI32PairToI53Checked(offset_low, offset_high);
8450 if (isNaN(offset)) return 61;
8451 var stream = SYSCALLS.getStreamFromFD(fd);
8452 FS.llseek(stream, offset, whence);
8453 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[newOffset >> 2] = tempI64[0], HEAP32[newOffset + 4 >> 2] = tempI64[1];
8454 if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null;
8455 return 0
8456 } catch (e) {
8457 if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e;
8458 return e.errno
8459 }
8460 }
8461
8462 function doWritev(stream, iov, iovcnt, offset) {
8463 var ret = 0;
8464 for (var i = 0; i < iovcnt; i++) {
8465 var ptr = HEAPU32[iov >> 2];
8466 var len = HEAPU32[iov + 4 >> 2];
8467 iov += 8;
8468 var curr = FS.write(stream, HEAP8, ptr, len, offset);
8469 if (curr < 0) return -1;
8470 ret += curr
8471 }
8472 return ret
8473 }
8474
8475 function _fd_write(fd, iov, iovcnt, pnum) {
8476 try {
8477 var stream = SYSCALLS.getStreamFromFD(fd);
8478 var num = doWritev(stream, iov, iovcnt);
8479 HEAPU32[pnum >> 2] = num;
8480 return 0
8481 } catch (e) {
8482 if (typeof FS == "undefined" || !(e instanceof FS.ErrnoError)) throw e;
8483 return e.errno
8484 }
8485 }
8486
8487 function __webgl_enable_ANGLE_instanced_arrays(ctx) {
8488 var ext = ctx.getExtension("ANGLE_instanced_arrays");
8489 if (ext) {
8490 ctx["vertexAttribDivisor"] = function(index, divisor) {
8491 ext["vertexAttribDivisorANGLE"](index, divisor)
8492 };
8493 ctx["drawArraysInstanced"] = function(mode, first, count, primcount) {
8494 ext["drawArraysInstancedANGLE"](mode, first, count, primcount)
8495 };
8496 ctx["drawElementsInstanced"] = function(mode, count, type, indices, primcount) {
8497 ext["drawElementsInstancedANGLE"](mode, count, type, indices, primcount)
8498 };
8499 return 1
8500 }
8501 }
8502
8503 function __webgl_enable_OES_vertex_array_object(ctx) {
8504 var ext = ctx.getExtension("OES_vertex_array_object");
8505 if (ext) {
8506 ctx["createVertexArray"] = function() {
8507 return ext["createVertexArrayOES"]()
8508 };
8509 ctx["deleteVertexArray"] = function(vao) {
8510 ext["deleteVertexArrayOES"](vao)
8511 };
8512 ctx["bindVertexArray"] = function(vao) {
8513 ext["bindVertexArrayOES"](vao)
8514 };
8515 ctx["isVertexArray"] = function(vao) {
8516 return ext["isVertexArrayOES"](vao)
8517 };
8518 return 1
8519 }
8520 }
8521
8522 function __webgl_enable_WEBGL_draw_buffers(ctx) {
8523 var ext = ctx.getExtension("WEBGL_draw_buffers");
8524 if (ext) {
8525 ctx["drawBuffers"] = function(n, bufs) {
8526 ext["drawBuffersWEBGL"](n, bufs)
8527 };
8528 return 1
8529 }
8530 }
8531
8532 function __webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(ctx) {
8533 return !!(ctx.dibvbi = ctx.getExtension("WEBGL_draw_instanced_base_vertex_base_instance"))
8534 }
8535
8536 function __webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance(ctx) {
8537 return !!(ctx.mdibvbi = ctx.getExtension("WEBGL_multi_draw_instanced_base_vertex_base_instance"))
8538 }
8539
8540 function __webgl_enable_WEBGL_multi_draw(ctx) {
8541 return !!(ctx.multiDrawWebgl = ctx.getExtension("WEBGL_multi_draw"))
8542 }
8543 var GL = {
8544 counter: 1,
8545 buffers: [],
8546 programs: [],
8547 framebuffers: [],
8548 renderbuffers: [],
8549 textures: [],
8550 shaders: [],
8551 vaos: [],
8552 contexts: [],
8553 offscreenCanvases: {},
8554 queries: [],
8555 samplers: [],
8556 transformFeedbacks: [],
8557 syncs: [],
8558 stringCache: {},
8559 stringiCache: {},
8560 unpackAlignment: 4,
8561 recordError: function recordError(errorCode) {
8562 if (!GL.lastError) {
8563 GL.lastError = errorCode
8564 }
8565 },
8566 getNewId: function(table) {
8567 var ret = GL.counter++;
8568 for (var i = table.length; i < ret; i++) {
8569 table[i] = null
8570 }
8571 return ret
8572 },
8573 getSource: function(shader, count, string, length) {
8574 var source = "";
8575 for (var i = 0; i < count; ++i) {
8576 var len = length ? HEAP32[length + i * 4 >> 2] : -1;
8577 source += UTF8ToString(HEAP32[string + i * 4 >> 2], len < 0 ? undefined : len)
8578 }
8579 return source
8580 },
8581 createContext: function(canvas, webGLContextAttributes) {
8582 if (!canvas.getContextSafariWebGL2Fixed) {
8583 canvas.getContextSafariWebGL2Fixed = canvas.getContext;
8584
8585 function fixedGetContext(ver, attrs) {
8586 var gl = canvas.getContextSafariWebGL2Fixed(ver, attrs);
8587 return ver == "webgl" == gl instanceof WebGLRenderingContext ? gl : null
8588 }
8589 canvas.getContext = fixedGetContext
8590 }
8591 var ctx = webGLContextAttributes.majorVersion > 1 ? canvas.getContext("webgl2", webGLContextAttributes) : canvas.getContext("webgl", webGLContextAttributes);
8592 if (!ctx) return 0;
8593 var handle = GL.registerContext(ctx, webGLContextAttributes);
8594 return handle
8595 },
8596 registerContext: function(ctx, webGLContextAttributes) {
8597 var handle = GL.getNewId(GL.contexts);
8598 var context = {
8599 handle: handle,
8600 attributes: webGLContextAttributes,
8601 version: webGLContextAttributes.majorVersion,
8602 GLctx: ctx
8603 };
8604 if (ctx.canvas) ctx.canvas.GLctxObject = context;
8605 GL.contexts[handle] = context;
8606 if (typeof webGLContextAttributes.enableExtensionsByDefault == "undefined" || webGLContextAttributes.enableExtensionsByDefault) {
8607 GL.initExtensions(context)
8608 }
8609 return handle
8610 },
8611 makeContextCurrent: function(contextHandle) {
8612 GL.currentContext = GL.contexts[contextHandle];
8613 Module.ctx = GLctx = GL.currentContext && GL.currentContext.GLctx;
8614 return !(contextHandle && !GLctx)
8615 },
8616 getContext: function(contextHandle) {
8617 return GL.contexts[contextHandle]
8618 },
8619 deleteContext: function(contextHandle) {
8620 if (GL.currentContext === GL.contexts[contextHandle]) GL.currentContext = null;
8621 if (typeof JSEvents == "object") JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas);
8622 if (GL.contexts[contextHandle] && GL.contexts[contextHandle].GLctx.canvas) GL.contexts[contextHandle].GLctx.canvas.GLctxObject = undefined;
8623 GL.contexts[contextHandle] = null
8624 },
8625 initExtensions: function(context) {
8626 if (!context) context = GL.currentContext;
8627 if (context.initExtensionsDone) return;
8628 context.initExtensionsDone = true;
8629 var GLctx = context.GLctx;
8630 __webgl_enable_ANGLE_instanced_arrays(GLctx);
8631 __webgl_enable_OES_vertex_array_object(GLctx);
8632 __webgl_enable_WEBGL_draw_buffers(GLctx);
8633 __webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(GLctx);
8634 __webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance(GLctx);
8635 if (context.version >= 2) {
8636 GLctx.disjointTimerQueryExt = GLctx.getExtension("EXT_disjoint_timer_query_webgl2")
8637 }
8638 if (context.version < 2 || !GLctx.disjointTimerQueryExt) {
8639 GLctx.disjointTimerQueryExt = GLctx.getExtension("EXT_disjoint_timer_query")
8640 }
8641 __webgl_enable_WEBGL_multi_draw(GLctx);
8642 var exts = GLctx.getSupportedExtensions() || [];
8643 exts.forEach(function(ext) {
8644 if (!ext.includes("lose_context") && !ext.includes("debug")) {
8645 GLctx.getExtension(ext)
8646 }
8647 })
8648 }
8649 };
8650
8651 function _glActiveTexture(x0) {
8652 GLctx["activeTexture"](x0)
8653 }
8654
8655 function _glAttachShader(program, shader) {
8656 GLctx.attachShader(GL.programs[program], GL.shaders[shader])
8657 }
8658
8659 function _glBindBuffer(target, buffer) {
8660 if (target == 35051) {
8661 GLctx.currentPixelPackBufferBinding = buffer
8662 } else if (target == 35052) {
8663 GLctx.currentPixelUnpackBufferBinding = buffer
8664 }
8665 GLctx.bindBuffer(target, GL.buffers[buffer])
8666 }
8667
8668 function _glBindFramebuffer(target, framebuffer) {
8669 GLctx.bindFramebuffer(target, GL.framebuffers[framebuffer])
8670 }
8671
8672 function _glBindRenderbuffer(target, renderbuffer) {
8673 GLctx.bindRenderbuffer(target, GL.renderbuffers[renderbuffer])
8674 }
8675
8676 function _glBindTexture(target, texture) {
8677 GLctx.bindTexture(target, GL.textures[texture])
8678 }
8679
8680 function _glBlendFunc(x0, x1) {
8681 GLctx["blendFunc"](x0, x1)
8682 }
8683
8684 function _glBufferData(target, size, data, usage) {
8685 if (GL.currentContext.version >= 2) {
8686 if (data && size) {
8687 GLctx.bufferData(target, HEAPU8, usage, data, size)
8688 } else {
8689 GLctx.bufferData(target, size, usage)
8690 }
8691 } else {
8692 GLctx.bufferData(target, data ? HEAPU8.subarray(data, data + size) : size, usage)
8693 }
8694 }
8695
8696 function _glCheckFramebufferStatus(x0) {
8697 return GLctx["checkFramebufferStatus"](x0)
8698 }
8699
8700 function _glClear(x0) {
8701 GLctx["clear"](x0)
8702 }
8703
8704 function _glClearColor(x0, x1, x2, x3) {
8705 GLctx["clearColor"](x0, x1, x2, x3)
8706 }
8707
8708 function _glCompileShader(shader) {
8709 GLctx.compileShader(GL.shaders[shader])
8710 }
8711
8712 function _glCreateProgram() {
8713 var id = GL.getNewId(GL.programs);
8714 var program = GLctx.createProgram();
8715 program.name = id;
8716 program.maxUniformLength = program.maxAttributeLength = program.maxUniformBlockNameLength = 0;
8717 program.uniformIdCounter = 1;
8718 GL.programs[id] = program;
8719 return id
8720 }
8721
8722 function _glCreateShader(shaderType) {
8723 var id = GL.getNewId(GL.shaders);
8724 GL.shaders[id] = GLctx.createShader(shaderType);
8725 return id
8726 }
8727
8728 function _glDeleteBuffers(n, buffers) {
8729 for (var i = 0; i < n; i++) {
8730 var id = HEAP32[buffers + i * 4 >> 2];
8731 var buffer = GL.buffers[id];
8732 if (!buffer) continue;
8733 GLctx.deleteBuffer(buffer);
8734 buffer.name = 0;
8735 GL.buffers[id] = null;
8736 if (id == GLctx.currentPixelPackBufferBinding) GLctx.currentPixelPackBufferBinding = 0;
8737 if (id == GLctx.currentPixelUnpackBufferBinding) GLctx.currentPixelUnpackBufferBinding = 0
8738 }
8739 }
8740
8741 function _glDeleteFramebuffers(n, framebuffers) {
8742 for (var i = 0; i < n; ++i) {
8743 var id = HEAP32[framebuffers + i * 4 >> 2];
8744 var framebuffer = GL.framebuffers[id];
8745 if (!framebuffer) continue;
8746 GLctx.deleteFramebuffer(framebuffer);
8747 framebuffer.name = 0;
8748 GL.framebuffers[id] = null
8749 }
8750 }
8751
8752 function _glDeleteRenderbuffers(n, renderbuffers) {
8753 for (var i = 0; i < n; i++) {
8754 var id = HEAP32[renderbuffers + i * 4 >> 2];
8755 var renderbuffer = GL.renderbuffers[id];
8756 if (!renderbuffer) continue;
8757 GLctx.deleteRenderbuffer(renderbuffer);
8758 renderbuffer.name = 0;
8759 GL.renderbuffers[id] = null
8760 }
8761 }
8762
8763 function _glDeleteTextures(n, textures) {
8764 for (var i = 0; i < n; i++) {
8765 var id = HEAP32[textures + i * 4 >> 2];
8766 var texture = GL.textures[id];
8767 if (!texture) continue;
8768 GLctx.deleteTexture(texture);
8769 texture.name = 0;
8770 GL.textures[id] = null
8771 }
8772 }
8773
8774 function _glDepthFunc(x0) {
8775 GLctx["depthFunc"](x0)
8776 }
8777
8778 function _glDepthMask(flag) {
8779 GLctx.depthMask(!!flag)
8780 }
8781
8782 function _glDisable(x0) {
8783 GLctx["disable"](x0)
8784 }
8785
8786 function _glDisableVertexAttribArray(index) {
8787 GLctx.disableVertexAttribArray(index)
8788 }
8789
8790 function _glDrawArrays(mode, first, count) {
8791 GLctx.drawArrays(mode, first, count)
8792 }
8793
8794 function _glEnable(x0) {
8795 GLctx["enable"](x0)
8796 }
8797
8798 function _glEnableVertexAttribArray(index) {
8799 GLctx.enableVertexAttribArray(index)
8800 }
8801
8802 function _glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer) {
8803 GLctx.framebufferRenderbuffer(target, attachment, renderbuffertarget, GL.renderbuffers[renderbuffer])
8804 }
8805
8806 function _glFramebufferTexture2D(target, attachment, textarget, texture, level) {
8807 GLctx.framebufferTexture2D(target, attachment, textarget, GL.textures[texture], level)
8808 }
8809
8810 function __glGenObject(n, buffers, createFunction, objectTable) {
8811 for (var i = 0; i < n; i++) {
8812 var buffer = GLctx[createFunction]();
8813 var id = buffer && GL.getNewId(objectTable);
8814 if (buffer) {
8815 buffer.name = id;
8816 objectTable[id] = buffer
8817 } else {
8818 GL.recordError(1282)
8819 }
8820 HEAP32[buffers + i * 4 >> 2] = id
8821 }
8822 }
8823
8824 function _glGenBuffers(n, buffers) {
8825 __glGenObject(n, buffers, "createBuffer", GL.buffers)
8826 }
8827
8828 function _glGenFramebuffers(n, ids) {
8829 __glGenObject(n, ids, "createFramebuffer", GL.framebuffers)
8830 }
8831
8832 function _glGenRenderbuffers(n, renderbuffers) {
8833 __glGenObject(n, renderbuffers, "createRenderbuffer", GL.renderbuffers)
8834 }
8835
8836 function _glGenTextures(n, textures) {
8837 __glGenObject(n, textures, "createTexture", GL.textures)
8838 }
8839
8840 function _glGetAttribLocation(program, name) {
8841 return GLctx.getAttribLocation(GL.programs[program], UTF8ToString(name))
8842 }
8843
8844 function writeI53ToI64(ptr, num) {
8845 HEAPU32[ptr >> 2] = num;
8846 HEAPU32[ptr + 4 >> 2] = (num - HEAPU32[ptr >> 2]) / 4294967296
8847 }
8848
8849 function emscriptenWebGLGet(name_, p, type) {
8850 if (!p) {
8851 GL.recordError(1281);
8852 return
8853 }
8854 var ret = undefined;
8855 switch (name_) {
8856 case 36346:
8857 ret = 1;
8858 break;
8859 case 36344:
8860 if (type != 0 && type != 1) {
8861 GL.recordError(1280)
8862 }
8863 return;
8864 case 34814:
8865 case 36345:
8866 ret = 0;
8867 break;
8868 case 34466:
8869 var formats = GLctx.getParameter(34467);
8870 ret = formats ? formats.length : 0;
8871 break;
8872 case 33309:
8873 if (GL.currentContext.version < 2) {
8874 GL.recordError(1282);
8875 return
8876 }
8877 var exts = GLctx.getSupportedExtensions() || [];
8878 ret = 2 * exts.length;
8879 break;
8880 case 33307:
8881 case 33308:
8882 if (GL.currentContext.version < 2) {
8883 GL.recordError(1280);
8884 return
8885 }
8886 ret = name_ == 33307 ? 3 : 0;
8887 break
8888 }
8889 if (ret === undefined) {
8890 var result = GLctx.getParameter(name_);
8891 switch (typeof result) {
8892 case "number":
8893 ret = result;
8894 break;
8895 case "boolean":
8896 ret = result ? 1 : 0;
8897 break;
8898 case "string":
8899 GL.recordError(1280);
8900 return;
8901 case "object":
8902 if (result === null) {
8903 switch (name_) {
8904 case 34964:
8905 case 35725:
8906 case 34965:
8907 case 36006:
8908 case 36007:
8909 case 32873:
8910 case 34229:
8911 case 36662:
8912 case 36663:
8913 case 35053:
8914 case 35055:
8915 case 36010:
8916 case 35097:
8917 case 35869:
8918 case 32874:
8919 case 36389:
8920 case 35983:
8921 case 35368:
8922 case 34068: {
8923 ret = 0;
8924 break
8925 }
8926 default: {
8927 GL.recordError(1280);
8928 return
8929 }
8930 }
8931 } else if (result instanceof Float32Array || result instanceof Uint32Array || result instanceof Int32Array || result instanceof Array) {
8932 for (var i = 0; i < result.length; ++i) {
8933 switch (type) {
8934 case 0:
8935 HEAP32[p + i * 4 >> 2] = result[i];
8936 break;
8937 case 2:
8938 HEAPF32[p + i * 4 >> 2] = result[i];
8939 break;
8940 case 4:
8941 HEAP8[p + i >> 0] = result[i] ? 1 : 0;
8942 break
8943 }
8944 }
8945 return
8946 } else {
8947 try {
8948 ret = result.name | 0
8949 } catch (e) {
8950 GL.recordError(1280);
8951 err("GL_INVALID_ENUM in glGet" + type + "v: Unknown object returned from WebGL getParameter(" + name_ + ")! (error: " + e + ")");
8952 return
8953 }
8954 }
8955 break;
8956 default:
8957 GL.recordError(1280);
8958 err("GL_INVALID_ENUM in glGet" + type + "v: Native code calling glGet" + type + "v(" + name_ + ") and it returns " + result + " of type " + typeof result + "!");
8959 return
8960 }
8961 }
8962 switch (type) {
8963 case 1:
8964 writeI53ToI64(p, ret);
8965 break;
8966 case 0:
8967 HEAP32[p >> 2] = ret;
8968 break;
8969 case 2:
8970 HEAPF32[p >> 2] = ret;
8971 break;
8972 case 4:
8973 HEAP8[p >> 0] = ret ? 1 : 0;
8974 break
8975 }
8976 }
8977
8978 function _glGetIntegerv(name_, p) {
8979 emscriptenWebGLGet(name_, p, 0)
8980 }
8981
8982 function _glGetProgramInfoLog(program, maxLength, length, infoLog) {
8983 var log = GLctx.getProgramInfoLog(GL.programs[program]);
8984 if (log === null) log = "(unknown error)";
8985 var numBytesWrittenExclNull = maxLength > 0 && infoLog ? stringToUTF8(log, infoLog, maxLength) : 0;
8986 if (length) HEAP32[length >> 2] = numBytesWrittenExclNull
8987 }
8988
8989 function _glGetProgramiv(program, pname, p) {
8990 if (!p) {
8991 GL.recordError(1281);
8992 return
8993 }
8994 if (program >= GL.counter) {
8995 GL.recordError(1281);
8996 return
8997 }
8998 program = GL.programs[program];
8999 if (pname == 35716) {
9000 var log = GLctx.getProgramInfoLog(program);
9001 if (log === null) log = "(unknown error)";
9002 HEAP32[p >> 2] = log.length + 1
9003 } else if (pname == 35719) {
9004 if (!program.maxUniformLength) {
9005 for (var i = 0; i < GLctx.getProgramParameter(program, 35718); ++i) {
9006 program.maxUniformLength = Math.max(program.maxUniformLength, GLctx.getActiveUniform(program, i).name.length + 1)
9007 }
9008 }
9009 HEAP32[p >> 2] = program.maxUniformLength
9010 } else if (pname == 35722) {
9011 if (!program.maxAttributeLength) {
9012 for (var i = 0; i < GLctx.getProgramParameter(program, 35721); ++i) {
9013 program.maxAttributeLength = Math.max(program.maxAttributeLength, GLctx.getActiveAttrib(program, i).name.length + 1)
9014 }
9015 }
9016 HEAP32[p >> 2] = program.maxAttributeLength
9017 } else if (pname == 35381) {
9018 if (!program.maxUniformBlockNameLength) {
9019 for (var i = 0; i < GLctx.getProgramParameter(program, 35382); ++i) {
9020 program.maxUniformBlockNameLength = Math.max(program.maxUniformBlockNameLength, GLctx.getActiveUniformBlockName(program, i).length + 1)
9021 }
9022 }
9023 HEAP32[p >> 2] = program.maxUniformBlockNameLength
9024 } else {
9025 HEAP32[p >> 2] = GLctx.getProgramParameter(program, pname)
9026 }
9027 }
9028
9029 function _glGetShaderInfoLog(shader, maxLength, length, infoLog) {
9030 var log = GLctx.getShaderInfoLog(GL.shaders[shader]);
9031 if (log === null) log = "(unknown error)";
9032 var numBytesWrittenExclNull = maxLength > 0 && infoLog ? stringToUTF8(log, infoLog, maxLength) : 0;
9033 if (length) HEAP32[length >> 2] = numBytesWrittenExclNull
9034 }
9035
9036 function _glGetShaderiv(shader, pname, p) {
9037 if (!p) {
9038 GL.recordError(1281);
9039 return
9040 }
9041 if (pname == 35716) {
9042 var log = GLctx.getShaderInfoLog(GL.shaders[shader]);
9043 if (log === null) log = "(unknown error)";
9044 var logLength = log ? log.length + 1 : 0;
9045 HEAP32[p >> 2] = logLength
9046 } else if (pname == 35720) {
9047 var source = GLctx.getShaderSource(GL.shaders[shader]);
9048 var sourceLength = source ? source.length + 1 : 0;
9049 HEAP32[p >> 2] = sourceLength
9050 } else {
9051 HEAP32[p >> 2] = GLctx.getShaderParameter(GL.shaders[shader], pname)
9052 }
9053 }
9054
9055 function jstoi_q(str) {
9056 return parseInt(str)
9057 }
9058
9059 function webglGetLeftBracePos(name) {
9060 return name.slice(-1) == "]" && name.lastIndexOf("[")
9061 }
9062
9063 function webglPrepareUniformLocationsBeforeFirstUse(program) {
9064 var uniformLocsById = program.uniformLocsById,
9065 uniformSizeAndIdsByName = program.uniformSizeAndIdsByName,
9066 i, j;
9067 if (!uniformLocsById) {
9068 program.uniformLocsById = uniformLocsById = {};
9069 program.uniformArrayNamesById = {};
9070 for (i = 0; i < GLctx.getProgramParameter(program, 35718); ++i) {
9071 var u = GLctx.getActiveUniform(program, i);
9072 var nm = u.name;
9073 var sz = u.size;
9074 var lb = webglGetLeftBracePos(nm);
9075 var arrayName = lb > 0 ? nm.slice(0, lb) : nm;
9076 var id = program.uniformIdCounter;
9077 program.uniformIdCounter += sz;
9078 uniformSizeAndIdsByName[arrayName] = [sz, id];
9079 for (j = 0; j < sz; ++j) {
9080 uniformLocsById[id] = j;
9081 program.uniformArrayNamesById[id++] = arrayName
9082 }
9083 }
9084 }
9085 }
9086
9087 function _glGetUniformLocation(program, name) {
9088 name = UTF8ToString(name);
9089 if (program = GL.programs[program]) {
9090 webglPrepareUniformLocationsBeforeFirstUse(program);
9091 var uniformLocsById = program.uniformLocsById;
9092 var arrayIndex = 0;
9093 var uniformBaseName = name;
9094 var leftBrace = webglGetLeftBracePos(name);
9095 if (leftBrace > 0) {
9096 arrayIndex = jstoi_q(name.slice(leftBrace + 1)) >>> 0;
9097 uniformBaseName = name.slice(0, leftBrace)
9098 }
9099 var sizeAndId = program.uniformSizeAndIdsByName[uniformBaseName];
9100 if (sizeAndId && arrayIndex < sizeAndId[0]) {
9101 arrayIndex += sizeAndId[1];
9102 if (uniformLocsById[arrayIndex] = uniformLocsById[arrayIndex] || GLctx.getUniformLocation(program, name)) {
9103 return arrayIndex
9104 }
9105 }
9106 } else {
9107 GL.recordError(1281)
9108 }
9109 return -1
9110 }
9111
9112 function _glLinkProgram(program) {
9113 program = GL.programs[program];
9114 GLctx.linkProgram(program);
9115 program.uniformLocsById = 0;
9116 program.uniformSizeAndIdsByName = {}
9117 }
9118
9119 function computeUnpackAlignedImageSize(width, height, sizePerPixel, alignment) {
9120 function roundedToNextMultipleOf(x, y) {
9121 return x + y - 1 & -y
9122 }
9123 var plainRowSize = width * sizePerPixel;
9124 var alignedRowSize = roundedToNextMultipleOf(plainRowSize, alignment);
9125 return height * alignedRowSize
9126 }
9127
9128 function __colorChannelsInGlTextureFormat(format) {
9129 var colorChannels = {
9130 5: 3,
9131 6: 4,
9132 8: 2,
9133 29502: 3,
9134 29504: 4,
9135 26917: 2,
9136 26918: 2,
9137 29846: 3,
9138 29847: 4
9139 };
9140 return colorChannels[format - 6402] || 1
9141 }
9142
9143 function heapObjectForWebGLType(type) {
9144 type -= 5120;
9145 if (type == 0) return HEAP8;
9146 if (type == 1) return HEAPU8;
9147 if (type == 2) return HEAP16;
9148 if (type == 4) return HEAP32;
9149 if (type == 6) return HEAPF32;
9150 if (type == 5 || type == 28922 || type == 28520 || type == 30779 || type == 30782) return HEAPU32;
9151 return HEAPU16
9152 }
9153
9154 function heapAccessShiftForWebGLHeap(heap) {
9155 return 31 - Math.clz32(heap.BYTES_PER_ELEMENT)
9156 }
9157
9158 function emscriptenWebGLGetTexPixelData(type, format, width, height, pixels, internalFormat) {
9159 var heap = heapObjectForWebGLType(type);
9160 var shift = heapAccessShiftForWebGLHeap(heap);
9161 var byteSize = 1 << shift;
9162 var sizePerPixel = __colorChannelsInGlTextureFormat(format) * byteSize;
9163 var bytes = computeUnpackAlignedImageSize(width, height, sizePerPixel, GL.unpackAlignment);
9164 return heap.subarray(pixels >> shift, pixels + bytes >> shift)
9165 }
9166
9167 function _glReadPixels(x, y, width, height, format, type, pixels) {
9168 if (GL.currentContext.version >= 2) {
9169 if (GLctx.currentPixelPackBufferBinding) {
9170 GLctx.readPixels(x, y, width, height, format, type, pixels)
9171 } else {
9172 var heap = heapObjectForWebGLType(type);
9173 GLctx.readPixels(x, y, width, height, format, type, heap, pixels >> heapAccessShiftForWebGLHeap(heap))
9174 }
9175 return
9176 }
9177 var pixelData = emscriptenWebGLGetTexPixelData(type, format, width, height, pixels, format);
9178 if (!pixelData) {
9179 GL.recordError(1280);
9180 return
9181 }
9182 GLctx.readPixels(x, y, width, height, format, type, pixelData)
9183 }
9184
9185 function _glRenderbufferStorage(x0, x1, x2, x3) {
9186 GLctx["renderbufferStorage"](x0, x1, x2, x3)
9187 }
9188
9189 function _glShaderSource(shader, count, string, length) {
9190 var source = GL.getSource(shader, count, string, length);
9191 GLctx.shaderSource(GL.shaders[shader], source)
9192 }
9193
9194 function _glTexImage2D(target, level, internalFormat, width, height, border, format, type, pixels) {
9195 if (GL.currentContext.version >= 2) {
9196 if (GLctx.currentPixelUnpackBufferBinding) {
9197 GLctx.texImage2D(target, level, internalFormat, width, height, border, format, type, pixels)
9198 } else if (pixels) {
9199 var heap = heapObjectForWebGLType(type);
9200 GLctx.texImage2D(target, level, internalFormat, width, height, border, format, type, heap, pixels >> heapAccessShiftForWebGLHeap(heap))
9201 } else {
9202 GLctx.texImage2D(target, level, internalFormat, width, height, border, format, type, null)
9203 }
9204 return
9205 }
9206 GLctx.texImage2D(target, level, internalFormat, width, height, border, format, type, pixels ? emscriptenWebGLGetTexPixelData(type, format, width, height, pixels, internalFormat) : null)
9207 }
9208
9209 function _glTexParameterf(x0, x1, x2) {
9210 GLctx["texParameterf"](x0, x1, x2)
9211 }
9212
9213 function _glTexParameteri(x0, x1, x2) {
9214 GLctx["texParameteri"](x0, x1, x2)
9215 }
9216
9217 function _glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels) {
9218 if (GL.currentContext.version >= 2) {
9219 if (GLctx.currentPixelUnpackBufferBinding) {
9220 GLctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels)
9221 } else if (pixels) {
9222 var heap = heapObjectForWebGLType(type);
9223 GLctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, heap, pixels >> heapAccessShiftForWebGLHeap(heap))
9224 } else {
9225 GLctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, null)
9226 }
9227 return
9228 }
9229 var pixelData = null;
9230 if (pixels) pixelData = emscriptenWebGLGetTexPixelData(type, format, width, height, pixels, 0);
9231 GLctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixelData)
9232 }
9233
9234 function webglGetUniformLocation(location) {
9235 var p = GLctx.currentProgram;
9236 if (p) {
9237 var webglLoc = p.uniformLocsById[location];
9238 if (typeof webglLoc == "number") {
9239 p.uniformLocsById[location] = webglLoc = GLctx.getUniformLocation(p, p.uniformArrayNamesById[location] + (webglLoc > 0 ? "[" + webglLoc + "]" : ""))
9240 }
9241 return webglLoc
9242 } else {
9243 GL.recordError(1282)
9244 }
9245 }
9246
9247 function _glUniform1f(location, v0) {
9248 GLctx.uniform1f(webglGetUniformLocation(location), v0)
9249 }
9250
9251 function _glUniform1i(location, v0) {
9252 GLctx.uniform1i(webglGetUniformLocation(location), v0)
9253 }
9254
9255 function _glUniform2f(location, v0, v1) {
9256 GLctx.uniform2f(webglGetUniformLocation(location), v0, v1)
9257 }
9258 var miniTempWebGLFloatBuffers = [];
9259
9260 function _glUniform3fv(location, count, value) {
9261 if (GL.currentContext.version >= 2) {
9262 count && GLctx.uniform3fv(webglGetUniformLocation(location), HEAPF32, value >> 2, count * 3);
9263 return
9264 }
9265 if (count <= 96) {
9266 var view = miniTempWebGLFloatBuffers[3 * count - 1];
9267 for (var i = 0; i < 3 * count; i += 3) {
9268 view[i] = HEAPF32[value + 4 * i >> 2];
9269 view[i + 1] = HEAPF32[value + (4 * i + 4) >> 2];
9270 view[i + 2] = HEAPF32[value + (4 * i + 8) >> 2]
9271 }
9272 } else {
9273 var view = HEAPF32.subarray(value >> 2, value + count * 12 >> 2)
9274 }
9275 GLctx.uniform3fv(webglGetUniformLocation(location), view)
9276 }
9277
9278 function _glUniformMatrix4fv(location, count, transpose, value) {
9279 if (GL.currentContext.version >= 2) {
9280 count && GLctx.uniformMatrix4fv(webglGetUniformLocation(location), !!transpose, HEAPF32, value >> 2, count * 16);
9281 return
9282 }
9283 if (count <= 18) {
9284 var view = miniTempWebGLFloatBuffers[16 * count - 1];
9285 var heap = HEAPF32;
9286 value >>= 2;
9287 for (var i = 0; i < 16 * count; i += 16) {
9288 var dst = value + i;
9289 view[i] = heap[dst];
9290 view[i + 1] = heap[dst + 1];
9291 view[i + 2] = heap[dst + 2];
9292 view[i + 3] = heap[dst + 3];
9293 view[i + 4] = heap[dst + 4];
9294 view[i + 5] = heap[dst + 5];
9295 view[i + 6] = heap[dst + 6];
9296 view[i + 7] = heap[dst + 7];
9297 view[i + 8] = heap[dst + 8];
9298 view[i + 9] = heap[dst + 9];
9299 view[i + 10] = heap[dst + 10];
9300 view[i + 11] = heap[dst + 11];
9301 view[i + 12] = heap[dst + 12];
9302 view[i + 13] = heap[dst + 13];
9303 view[i + 14] = heap[dst + 14];
9304 view[i + 15] = heap[dst + 15]
9305 }
9306 } else {
9307 var view = HEAPF32.subarray(value >> 2, value + count * 64 >> 2)
9308 }
9309 GLctx.uniformMatrix4fv(webglGetUniformLocation(location), !!transpose, view)
9310 }
9311
9312 function _glUseProgram(program) {
9313 program = GL.programs[program];
9314 GLctx.useProgram(program);
9315 GLctx.currentProgram = program
9316 }
9317
9318 function _glVertexAttribPointer(index, size, type, normalized, stride, ptr) {
9319 GLctx.vertexAttribPointer(index, size, type, !!normalized, stride, ptr)
9320 }
9321
9322 function _glViewport(x0, x1, x2, x3) {
9323 GLctx["viewport"](x0, x1, x2, x3)
9324 }
9325
9326 function GLFW_Window(id, width, height, title, monitor, share) {
9327 this.id = id;
9328 this.x = 0;
9329 this.y = 0;
9330 this.fullscreen = false;
9331 this.storedX = 0;
9332 this.storedY = 0;
9333 this.width = width;
9334 this.height = height;
9335 this.storedWidth = width;
9336 this.storedHeight = height;
9337 this.title = title;
9338 this.monitor = monitor;
9339 this.share = share;
9340 this.attributes = GLFW.hints;
9341 this.inputModes = {
9342 208897: 212993,
9343 208898: 0,
9344 208899: 0
9345 };
9346 this.buttons = 0;
9347 this.keys = new Array;
9348 this.domKeys = new Array;
9349 this.shouldClose = 0;
9350 this.title = null;
9351 this.windowPosFunc = null;
9352 this.windowSizeFunc = null;
9353 this.windowCloseFunc = null;
9354 this.windowRefreshFunc = null;
9355 this.windowFocusFunc = null;
9356 this.windowIconifyFunc = null;
9357 this.framebufferSizeFunc = null;
9358 this.mouseButtonFunc = null;
9359 this.cursorPosFunc = null;
9360 this.cursorEnterFunc = null;
9361 this.scrollFunc = null;
9362 this.dropFunc = null;
9363 this.keyFunc = null;
9364 this.charFunc = null;
9365 this.userptr = null
9366 }
9367 var GLFW = {
9368 WindowFromId: function(id) {
9369 if (id <= 0 || !GLFW.windows) return null;
9370 return GLFW.windows[id - 1]
9371 },
9372 joystickFunc: null,
9373 errorFunc: null,
9374 monitorFunc: null,
9375 active: null,
9376 windows: null,
9377 monitors: null,
9378 monitorString: null,
9379 versionString: null,
9380 initialTime: null,
9381 extensions: null,
9382 hints: null,
9383 defaultHints: {
9384 131073: 0,
9385 131074: 0,
9386 131075: 1,
9387 131076: 1,
9388 131077: 1,
9389 135169: 8,
9390 135170: 8,
9391 135171: 8,
9392 135172: 8,
9393 135173: 24,
9394 135174: 8,
9395 135175: 0,
9396 135176: 0,
9397 135177: 0,
9398 135178: 0,
9399 135179: 0,
9400 135180: 0,
9401 135181: 0,
9402 135182: 0,
9403 135183: 0,
9404 139265: 196609,
9405 139266: 1,
9406 139267: 0,
9407 139268: 0,
9408 139269: 0,
9409 139270: 0,
9410 139271: 0,
9411 139272: 0
9412 },
9413 DOMToGLFWKeyCode: function(keycode) {
9414 switch (keycode) {
9415 case 32:
9416 return 32;
9417 case 222:
9418 return 39;
9419 case 188:
9420 return 44;
9421 case 173:
9422 return 45;
9423 case 189:
9424 return 45;
9425 case 190:
9426 return 46;
9427 case 191:
9428 return 47;
9429 case 48:
9430 return 48;
9431 case 49:
9432 return 49;
9433 case 50:
9434 return 50;
9435 case 51:
9436 return 51;
9437 case 52:
9438 return 52;
9439 case 53:
9440 return 53;
9441 case 54:
9442 return 54;
9443 case 55:
9444 return 55;
9445 case 56:
9446 return 56;
9447 case 57:
9448 return 57;
9449 case 59:
9450 return 59;
9451 case 61:
9452 return 61;
9453 case 187:
9454 return 61;
9455 case 65:
9456 return 65;
9457 case 66:
9458 return 66;
9459 case 67:
9460 return 67;
9461 case 68:
9462 return 68;
9463 case 69:
9464 return 69;
9465 case 70:
9466 return 70;
9467 case 71:
9468 return 71;
9469 case 72:
9470 return 72;
9471 case 73:
9472 return 73;
9473 case 74:
9474 return 74;
9475 case 75:
9476 return 75;
9477 case 76:
9478 return 76;
9479 case 77:
9480 return 77;
9481 case 78:
9482 return 78;
9483 case 79:
9484 return 79;
9485 case 80:
9486 return 80;
9487 case 81:
9488 return 81;
9489 case 82:
9490 return 82;
9491 case 83:
9492 return 83;
9493 case 84:
9494 return 84;
9495 case 85:
9496 return 85;
9497 case 86:
9498 return 86;
9499 case 87:
9500 return 87;
9501 case 88:
9502 return 88;
9503 case 89:
9504 return 89;
9505 case 90:
9506 return 90;
9507 case 219:
9508 return 91;
9509 case 220:
9510 return 92;
9511 case 221:
9512 return 93;
9513 case 192:
9514 return 96;
9515 case 27:
9516 return 256;
9517 case 13:
9518 return 257;
9519 case 9:
9520 return 258;
9521 case 8:
9522 return 259;
9523 case 45:
9524 return 260;
9525 case 46:
9526 return 261;
9527 case 39:
9528 return 262;
9529 case 37:
9530 return 263;
9531 case 40:
9532 return 264;
9533 case 38:
9534 return 265;
9535 case 33:
9536 return 266;
9537 case 34:
9538 return 267;
9539 case 36:
9540 return 268;
9541 case 35:
9542 return 269;
9543 case 20:
9544 return 280;
9545 case 145:
9546 return 281;
9547 case 144:
9548 return 282;
9549 case 44:
9550 return 283;
9551 case 19:
9552 return 284;
9553 case 112:
9554 return 290;
9555 case 113:
9556 return 291;
9557 case 114:
9558 return 292;
9559 case 115:
9560 return 293;
9561 case 116:
9562 return 294;
9563 case 117:
9564 return 295;
9565 case 118:
9566 return 296;
9567 case 119:
9568 return 297;
9569 case 120:
9570 return 298;
9571 case 121:
9572 return 299;
9573 case 122:
9574 return 300;
9575 case 123:
9576 return 301;
9577 case 124:
9578 return 302;
9579 case 125:
9580 return 303;
9581 case 126:
9582 return 304;
9583 case 127:
9584 return 305;
9585 case 128:
9586 return 306;
9587 case 129:
9588 return 307;
9589 case 130:
9590 return 308;
9591 case 131:
9592 return 309;
9593 case 132:
9594 return 310;
9595 case 133:
9596 return 311;
9597 case 134:
9598 return 312;
9599 case 135:
9600 return 313;
9601 case 136:
9602 return 314;
9603 case 96:
9604 return 320;
9605 case 97:
9606 return 321;
9607 case 98:
9608 return 322;
9609 case 99:
9610 return 323;
9611 case 100:
9612 return 324;
9613 case 101:
9614 return 325;
9615 case 102:
9616 return 326;
9617 case 103:
9618 return 327;
9619 case 104:
9620 return 328;
9621 case 105:
9622 return 329;
9623 case 110:
9624 return 330;
9625 case 111:
9626 return 331;
9627 case 106:
9628 return 332;
9629 case 109:
9630 return 333;
9631 case 107:
9632 return 334;
9633 case 16:
9634 return 340;
9635 case 17:
9636 return 341;
9637 case 18:
9638 return 342;
9639 case 91:
9640 return 343;
9641 case 93:
9642 return 348;
9643 default:
9644 return -1
9645 }
9646 },
9647 getModBits: function(win) {
9648 var mod = 0;
9649 if (win.keys[340]) mod |= 1;
9650 if (win.keys[341]) mod |= 2;
9651 if (win.keys[342]) mod |= 4;
9652 if (win.keys[343]) mod |= 8;
9653 return mod
9654 },
9655 onKeyPress: function(event) {
9656 if (!GLFW.active || !GLFW.active.charFunc) return;
9657 if (event.ctrlKey || event.metaKey) return;
9658 var charCode = event.charCode;
9659 if (charCode == 0 || charCode >= 0 && charCode <= 31) return;
9660 getWasmTableEntry(GLFW.active.charFunc)(GLFW.active.id, charCode)
9661 },
9662 onKeyChanged: function(keyCode, status) {
9663 if (!GLFW.active) return;
9664 var key = GLFW.DOMToGLFWKeyCode(keyCode);
9665 if (key == -1) return;
9666 var repeat = status && GLFW.active.keys[key];
9667 GLFW.active.keys[key] = status;
9668 GLFW.active.domKeys[keyCode] = status;
9669 if (!GLFW.active.keyFunc) return;
9670 if (repeat) status = 2;
9671 getWasmTableEntry(GLFW.active.keyFunc)(GLFW.active.id, key, keyCode, status, GLFW.getModBits(GLFW.active))
9672 },
9673 onGamepadConnected: function(event) {
9674 GLFW.refreshJoysticks()
9675 },
9676 onGamepadDisconnected: function(event) {
9677 GLFW.refreshJoysticks()
9678 },
9679 onKeydown: function(event) {
9680 GLFW.onKeyChanged(event.keyCode, 1);
9681 if (event.keyCode === 8 || event.keyCode === 9) {
9682 event.preventDefault()
9683 }
9684 },
9685 onKeyup: function(event) {
9686 GLFW.onKeyChanged(event.keyCode, 0)
9687 },
9688 onBlur: function(event) {
9689 if (!GLFW.active) return;
9690 for (var i = 0; i < GLFW.active.domKeys.length; ++i) {
9691 if (GLFW.active.domKeys[i]) {
9692 GLFW.onKeyChanged(i, 0)
9693 }
9694 }
9695 },
9696 onMousemove: function(event) {
9697 if (!GLFW.active) return;
9698 Browser.calculateMouseEvent(event);
9699 if (event.target != Module["canvas"] || !GLFW.active.cursorPosFunc) return;
9700 getWasmTableEntry(GLFW.active.cursorPosFunc)(GLFW.active.id, Browser.mouseX, Browser.mouseY)
9701 },
9702 DOMToGLFWMouseButton: function(event) {
9703 var eventButton = event["button"];
9704 if (eventButton > 0) {
9705 if (eventButton == 1) {
9706 eventButton = 2
9707 } else {
9708 eventButton = 1
9709 }
9710 }
9711 return eventButton
9712 },
9713 onMouseenter: function(event) {
9714 if (!GLFW.active) return;
9715 if (event.target != Module["canvas"] || !GLFW.active.cursorEnterFunc) return;
9716 getWasmTableEntry(GLFW.active.cursorEnterFunc)(GLFW.active.id, 1)
9717 },
9718 onMouseleave: function(event) {
9719 if (!GLFW.active) return;
9720 if (event.target != Module["canvas"] || !GLFW.active.cursorEnterFunc) return;
9721 getWasmTableEntry(GLFW.active.cursorEnterFunc)(GLFW.active.id, 0)
9722 },
9723 onMouseButtonChanged: function(event, status) {
9724 if (!GLFW.active) return;
9725 Browser.calculateMouseEvent(event);
9726 if (event.target != Module["canvas"]) return;
9727 var eventButton = GLFW.DOMToGLFWMouseButton(event);
9728 if (status == 1) {
9729 GLFW.active.buttons |= 1 << eventButton;
9730 try {
9731 event.target.setCapture()
9732 } catch (e) {}
9733 } else {
9734 GLFW.active.buttons &= ~(1 << eventButton)
9735 }
9736 if (!GLFW.active.mouseButtonFunc) return;
9737 getWasmTableEntry(GLFW.active.mouseButtonFunc)(GLFW.active.id, eventButton, status, GLFW.getModBits(GLFW.active))
9738 },
9739 onMouseButtonDown: function(event) {
9740 if (!GLFW.active) return;
9741 GLFW.onMouseButtonChanged(event, 1)
9742 },
9743 onMouseButtonUp: function(event) {
9744 if (!GLFW.active) return;
9745 GLFW.onMouseButtonChanged(event, 0)
9746 },
9747 onMouseWheel: function(event) {
9748 var delta = -Browser.getMouseWheelDelta(event);
9749 delta = delta == 0 ? 0 : delta > 0 ? Math.max(delta, 1) : Math.min(delta, -1);
9750 GLFW.wheelPos += delta;
9751 if (!GLFW.active || !GLFW.active.scrollFunc || event.target != Module["canvas"]) return;
9752 var sx = 0;
9753 var sy = delta;
9754 if (event.type == "mousewheel") {
9755 sx = event.wheelDeltaX
9756 } else {
9757 sx = event.deltaX
9758 }
9759 getWasmTableEntry(GLFW.active.scrollFunc)(GLFW.active.id, sx, sy);
9760 event.preventDefault()
9761 },
9762 onCanvasResize: function(width, height) {
9763 if (!GLFW.active) return;
9764 var resizeNeeded = true;
9765 if (document["fullscreen"] || document["fullScreen"] || document["mozFullScreen"] || document["webkitIsFullScreen"]) {
9766 GLFW.active.storedX = GLFW.active.x;
9767 GLFW.active.storedY = GLFW.active.y;
9768 GLFW.active.storedWidth = GLFW.active.width;
9769 GLFW.active.storedHeight = GLFW.active.height;
9770 GLFW.active.x = GLFW.active.y = 0;
9771 GLFW.active.width = screen.width;
9772 GLFW.active.height = screen.height;
9773 GLFW.active.fullscreen = true
9774 } else if (GLFW.active.fullscreen == true) {
9775 GLFW.active.x = GLFW.active.storedX;
9776 GLFW.active.y = GLFW.active.storedY;
9777 GLFW.active.width = GLFW.active.storedWidth;
9778 GLFW.active.height = GLFW.active.storedHeight;
9779 GLFW.active.fullscreen = false
9780 } else if (GLFW.active.width != width || GLFW.active.height != height) {
9781 GLFW.active.width = width;
9782 GLFW.active.height = height
9783 } else {
9784 resizeNeeded = false
9785 }
9786 if (resizeNeeded) {
9787 Browser.setCanvasSize(GLFW.active.width, GLFW.active.height, true);
9788 GLFW.onWindowSizeChanged();
9789 GLFW.onFramebufferSizeChanged()
9790 }
9791 },
9792 onWindowSizeChanged: function() {
9793 if (!GLFW.active) return;
9794 if (!GLFW.active.windowSizeFunc) return;
9795 callUserCallback(function() {
9796 getWasmTableEntry(GLFW.active.windowSizeFunc)(GLFW.active.id, GLFW.active.width, GLFW.active.height)
9797 })
9798 },
9799 onFramebufferSizeChanged: function() {
9800 if (!GLFW.active) return;
9801 if (!GLFW.active.framebufferSizeFunc) return;
9802 callUserCallback(function() {
9803 getWasmTableEntry(GLFW.active.framebufferSizeFunc)(GLFW.active.id, GLFW.active.width, GLFW.active.height)
9804 })
9805 },
9806 getTime: function() {
9807 return _emscripten_get_now() / 1e3
9808 },
9809 setWindowTitle: function(winid, title) {
9810 var win = GLFW.WindowFromId(winid);
9811 if (!win) return;
9812 win.title = UTF8ToString(title);
9813 if (GLFW.active.id == win.id) {
9814 document.title = win.title
9815 }
9816 },
9817 setJoystickCallback: function(cbfun) {
9818 GLFW.joystickFunc = cbfun;
9819 GLFW.refreshJoysticks()
9820 },
9821 joys: {},
9822 lastGamepadState: [],
9823 lastGamepadStateFrame: null,
9824 refreshJoysticks: function() {
9825 if (Browser.mainLoop.currentFrameNumber !== GLFW.lastGamepadStateFrame || !Browser.mainLoop.currentFrameNumber) {
9826 GLFW.lastGamepadState = navigator.getGamepads ? navigator.getGamepads() : navigator.webkitGetGamepads ? navigator.webkitGetGamepads : [];
9827 GLFW.lastGamepadStateFrame = Browser.mainLoop.currentFrameNumber;
9828 for (var joy = 0; joy < GLFW.lastGamepadState.length; ++joy) {
9829 var gamepad = GLFW.lastGamepadState[joy];
9830 if (gamepad) {
9831 if (!GLFW.joys[joy]) {
9832 out("glfw joystick connected:", joy);
9833 GLFW.joys[joy] = {
9834 id: allocateUTF8(gamepad.id),
9835 buttonsCount: gamepad.buttons.length,
9836 axesCount: gamepad.axes.length,
9837 buttons: _malloc(gamepad.buttons.length),
9838 axes: _malloc(gamepad.axes.length * 4)
9839 };
9840 if (GLFW.joystickFunc) {
9841 getWasmTableEntry(GLFW.joystickFunc)(joy, 262145)
9842 }
9843 }
9844 var data = GLFW.joys[joy];
9845 for (var i = 0; i < gamepad.buttons.length; ++i) {
9846 HEAP8[data.buttons + i >> 0] = gamepad.buttons[i].pressed
9847 }
9848 for (var i = 0; i < gamepad.axes.length; ++i) {
9849 HEAPF32[data.axes + i * 4 >> 2] = gamepad.axes[i]
9850 }
9851 } else {
9852 if (GLFW.joys[joy]) {
9853 out("glfw joystick disconnected", joy);
9854 if (GLFW.joystickFunc) {
9855 getWasmTableEntry(GLFW.joystickFunc)(joy, 262146)
9856 }
9857 _free(GLFW.joys[joy].id);
9858 _free(GLFW.joys[joy].buttons);
9859 _free(GLFW.joys[joy].axes);
9860 delete GLFW.joys[joy]
9861 }
9862 }
9863 }
9864 }
9865 },
9866 setKeyCallback: function(winid, cbfun) {
9867 var win = GLFW.WindowFromId(winid);
9868 if (!win) return null;
9869 var prevcbfun = win.keyFunc;
9870 win.keyFunc = cbfun;
9871 return prevcbfun
9872 },
9873 setCharCallback: function(winid, cbfun) {
9874 var win = GLFW.WindowFromId(winid);
9875 if (!win) return null;
9876 var prevcbfun = win.charFunc;
9877 win.charFunc = cbfun;
9878 return prevcbfun
9879 },
9880 setMouseButtonCallback: function(winid, cbfun) {
9881 var win = GLFW.WindowFromId(winid);
9882 if (!win) return null;
9883 var prevcbfun = win.mouseButtonFunc;
9884 win.mouseButtonFunc = cbfun;
9885 return prevcbfun
9886 },
9887 setCursorPosCallback: function(winid, cbfun) {
9888 var win = GLFW.WindowFromId(winid);
9889 if (!win) return null;
9890 var prevcbfun = win.cursorPosFunc;
9891 win.cursorPosFunc = cbfun;
9892 return prevcbfun
9893 },
9894 setScrollCallback: function(winid, cbfun) {
9895 var win = GLFW.WindowFromId(winid);
9896 if (!win) return null;
9897 var prevcbfun = win.scrollFunc;
9898 win.scrollFunc = cbfun;
9899 return prevcbfun
9900 },
9901 setDropCallback: function(winid, cbfun) {
9902 var win = GLFW.WindowFromId(winid);
9903 if (!win) return null;
9904 var prevcbfun = win.dropFunc;
9905 win.dropFunc = cbfun;
9906 return prevcbfun
9907 },
9908 onDrop: function(event) {
9909 if (!GLFW.active || !GLFW.active.dropFunc) return;
9910 if (!event.dataTransfer || !event.dataTransfer.files || event.dataTransfer.files.length == 0) return;
9911 event.preventDefault();
9912 var filenames = _malloc(event.dataTransfer.files.length * 4);
9913 var filenamesArray = [];
9914 var count = event.dataTransfer.files.length;
9915 var written = 0;
9916 var drop_dir = ".glfw_dropped_files";
9917 FS.createPath("/", drop_dir);
9918
9919 function save(file) {
9920 var path = "/" + drop_dir + "/" + file.name.replace(/\//g, "_");
9921 var reader = new FileReader;
9922 reader.onloadend = e => {
9923 if (reader.readyState != 2) {
9924 ++written;
9925 out("failed to read dropped file: " + file.name + ": " + reader.error);
9926 return
9927 }
9928 var data = e.target.result;
9929 FS.writeFile(path, new Uint8Array(data));
9930 if (++written === count) {
9931 getWasmTableEntry(GLFW.active.dropFunc)(GLFW.active.id, count, filenames);
9932 for (var i = 0; i < filenamesArray.length; ++i) {
9933 _free(filenamesArray[i])
9934 }
9935 _free(filenames)
9936 }
9937 };
9938 reader.readAsArrayBuffer(file);
9939 var filename = allocateUTF8(path);
9940 filenamesArray.push(filename);
9941 HEAPU32[filenames + i * 4 >> 2] = filename
9942 }
9943 for (var i = 0; i < count; ++i) {
9944 save(event.dataTransfer.files[i])
9945 }
9946 return false
9947 },
9948 onDragover: function(event) {
9949 if (!GLFW.active || !GLFW.active.dropFunc) return;
9950 event.preventDefault();
9951 return false
9952 },
9953 setWindowSizeCallback: function(winid, cbfun) {
9954 var win = GLFW.WindowFromId(winid);
9955 if (!win) return null;
9956 var prevcbfun = win.windowSizeFunc;
9957 win.windowSizeFunc = cbfun;
9958 return prevcbfun
9959 },
9960 setWindowCloseCallback: function(winid, cbfun) {
9961 var win = GLFW.WindowFromId(winid);
9962 if (!win) return null;
9963 var prevcbfun = win.windowCloseFunc;
9964 win.windowCloseFunc = cbfun;
9965 return prevcbfun
9966 },
9967 setWindowRefreshCallback: function(winid, cbfun) {
9968 var win = GLFW.WindowFromId(winid);
9969 if (!win) return null;
9970 var prevcbfun = win.windowRefreshFunc;
9971 win.windowRefreshFunc = cbfun;
9972 return prevcbfun
9973 },
9974 onClickRequestPointerLock: function(e) {
9975 if (!Browser.pointerLock && Module["canvas"].requestPointerLock) {
9976 Module["canvas"].requestPointerLock();
9977 e.preventDefault()
9978 }
9979 },
9980 setInputMode: function(winid, mode, value) {
9981 var win = GLFW.WindowFromId(winid);
9982 if (!win) return;
9983 switch (mode) {
9984 case 208897: {
9985 switch (value) {
9986 case 212993: {
9987 win.inputModes[mode] = value;
9988 Module["canvas"].removeEventListener("click", GLFW.onClickRequestPointerLock, true);
9989 Module["canvas"].exitPointerLock();
9990 break
9991 }
9992 case 212994: {
9993 out("glfwSetInputMode called with GLFW_CURSOR_HIDDEN value not implemented.");
9994 break
9995 }
9996 case 212995: {
9997 win.inputModes[mode] = value;
9998 Module["canvas"].addEventListener("click", GLFW.onClickRequestPointerLock, true);
9999 Module["canvas"].requestPointerLock();
10000 break
10001 }
10002 default: {
10003 out("glfwSetInputMode called with unknown value parameter value: " + value + ".");
10004 break
10005 }
10006 }
10007 break
10008 }
10009 case 208898: {
10010 out("glfwSetInputMode called with GLFW_STICKY_KEYS mode not implemented.");
10011 break
10012 }
10013 case 208899: {
10014 out("glfwSetInputMode called with GLFW_STICKY_MOUSE_BUTTONS mode not implemented.");
10015 break
10016 }
10017 default: {
10018 out("glfwSetInputMode called with unknown mode parameter value: " + mode + ".");
10019 break
10020 }
10021 }
10022 },
10023 getKey: function(winid, key) {
10024 var win = GLFW.WindowFromId(winid);
10025 if (!win) return 0;
10026 return win.keys[key]
10027 },
10028 getMouseButton: function(winid, button) {
10029 var win = GLFW.WindowFromId(winid);
10030 if (!win) return 0;
10031 return (win.buttons & 1 << button) > 0
10032 },
10033 getCursorPos: function(winid, x, y) {
10034 HEAPF64[x >> 3] = Browser.mouseX;
10035 HEAPF64[y >> 3] = Browser.mouseY
10036 },
10037 getMousePos: function(winid, x, y) {
10038 HEAP32[x >> 2] = Browser.mouseX;
10039 HEAP32[y >> 2] = Browser.mouseY
10040 },
10041 setCursorPos: function(winid, x, y) {},
10042 getWindowPos: function(winid, x, y) {
10043 var wx = 0;
10044 var wy = 0;
10045 var win = GLFW.WindowFromId(winid);
10046 if (win) {
10047 wx = win.x;
10048 wy = win.y
10049 }
10050 if (x) {
10051 HEAP32[x >> 2] = wx
10052 }
10053 if (y) {
10054 HEAP32[y >> 2] = wy
10055 }
10056 },
10057 setWindowPos: function(winid, x, y) {
10058 var win = GLFW.WindowFromId(winid);
10059 if (!win) return;
10060 win.x = x;
10061 win.y = y
10062 },
10063 getWindowSize: function(winid, width, height) {
10064 var ww = 0;
10065 var wh = 0;
10066 var win = GLFW.WindowFromId(winid);
10067 if (win) {
10068 ww = win.width;
10069 wh = win.height
10070 }
10071 if (width) {
10072 HEAP32[width >> 2] = ww
10073 }
10074 if (height) {
10075 HEAP32[height >> 2] = wh
10076 }
10077 },
10078 setWindowSize: function(winid, width, height) {
10079 var win = GLFW.WindowFromId(winid);
10080 if (!win) return;
10081 if (GLFW.active.id == win.id) {
10082 if (width == screen.width && height == screen.height) {
10083 Browser.requestFullscreen()
10084 } else {
10085 Browser.exitFullscreen();
10086 Browser.setCanvasSize(width, height);
10087 win.width = width;
10088 win.height = height
10089 }
10090 }
10091 if (!win.windowSizeFunc) return;
10092 getWasmTableEntry(win.windowSizeFunc)(win.id, width, height)
10093 },
10094 createWindow: function(width, height, title, monitor, share) {
10095 var i, id;
10096 for (i = 0; i < GLFW.windows.length && GLFW.windows[i] !== null; i++) {}
10097 if (i > 0) throw "glfwCreateWindow only supports one window at time currently";
10098 id = i + 1;
10099 if (width <= 0 || height <= 0) return 0;
10100 if (monitor) {
10101 Browser.requestFullscreen()
10102 } else {
10103 Browser.setCanvasSize(width, height)
10104 }
10105 for (i = 0; i < GLFW.windows.length && GLFW.windows[i] == null; i++) {}
10106 var useWebGL = GLFW.hints[139265] > 0;
10107 if (i == GLFW.windows.length) {
10108 if (useWebGL) {
10109 var contextAttributes = {
10110 antialias: GLFW.hints[135181] > 1,
10111 depth: GLFW.hints[135173] > 0,
10112 stencil: GLFW.hints[135174] > 0,
10113 alpha: GLFW.hints[135172] > 0
10114 };
10115 Module.ctx = Browser.createContext(Module["canvas"], true, true, contextAttributes)
10116 } else {
10117 Browser.init()
10118 }
10119 }
10120 if (!Module.ctx && useWebGL) return 0;
10121 var win = new GLFW_Window(id, width, height, title, monitor, share);
10122 if (id - 1 == GLFW.windows.length) {
10123 GLFW.windows.push(win)
10124 } else {
10125 GLFW.windows[id - 1] = win
10126 }
10127 GLFW.active = win;
10128 return win.id
10129 },
10130 destroyWindow: function(winid) {
10131 var win = GLFW.WindowFromId(winid);
10132 if (!win) return;
10133 if (win.windowCloseFunc) getWasmTableEntry(win.windowCloseFunc)(win.id);
10134 GLFW.windows[win.id - 1] = null;
10135 if (GLFW.active.id == win.id) GLFW.active = null;
10136 for (var i = 0; i < GLFW.windows.length; i++)
10137 if (GLFW.windows[i] !== null) return;
10138 Module.ctx = Browser.destroyContext(Module["canvas"], true, true)
10139 },
10140 swapBuffers: function(winid) {},
10141 GLFW2ParamToGLFW3Param: function(param) {
10142 var table = {
10143 196609: 0,
10144 196610: 0,
10145 196611: 0,
10146 196612: 0,
10147 196613: 0,
10148 196614: 0,
10149 131073: 0,
10150 131074: 0,
10151 131075: 0,
10152 131076: 0,
10153 131077: 135169,
10154 131078: 135170,
10155 131079: 135171,
10156 131080: 135172,
10157 131081: 135173,
10158 131082: 135174,
10159 131083: 135183,
10160 131084: 135175,
10161 131085: 135176,
10162 131086: 135177,
10163 131087: 135178,
10164 131088: 135179,
10165 131089: 135180,
10166 131090: 0,
10167 131091: 135181,
10168 131092: 139266,
10169 131093: 139267,
10170 131094: 139270,
10171 131095: 139271,
10172 131096: 139272
10173 };
10174 return table[param]
10175 }
10176 };
10177
10178 function _glfwCreateWindow(width, height, title, monitor, share) {
10179 return GLFW.createWindow(width, height, title, monitor, share)
10180 }
10181
10182 function _glfwGetPrimaryMonitor() {
10183 return 1
10184 }
10185
10186 function _glfwGetVideoMode(monitor) {
10187 return 0
10188 }
10189
10190 function _glfwInit() {
10191 if (GLFW.windows) return 1;
10192 GLFW.initialTime = GLFW.getTime();
10193 GLFW.hints = GLFW.defaultHints;
10194 GLFW.windows = new Array;
10195 GLFW.active = null;
10196 window.addEventListener("gamepadconnected", GLFW.onGamepadConnected, true);
10197 window.addEventListener("gamepaddisconnected", GLFW.onGamepadDisconnected, true);
10198 window.addEventListener("keydown", GLFW.onKeydown, true);
10199 window.addEventListener("keypress", GLFW.onKeyPress, true);
10200 window.addEventListener("keyup", GLFW.onKeyup, true);
10201 window.addEventListener("blur", GLFW.onBlur, true);
10202 Module["canvas"].addEventListener("touchmove", GLFW.onMousemove, true);
10203 Module["canvas"].addEventListener("touchstart", GLFW.onMouseButtonDown, true);
10204 Module["canvas"].addEventListener("touchcancel", GLFW.onMouseButtonUp, true);
10205 Module["canvas"].addEventListener("touchend", GLFW.onMouseButtonUp, true);
10206 Module["canvas"].addEventListener("mousemove", GLFW.onMousemove, true);
10207 Module["canvas"].addEventListener("mousedown", GLFW.onMouseButtonDown, true);
10208 Module["canvas"].addEventListener("mouseup", GLFW.onMouseButtonUp, true);
10209 Module["canvas"].addEventListener("wheel", GLFW.onMouseWheel, true);
10210 Module["canvas"].addEventListener("mousewheel", GLFW.onMouseWheel, true);
10211 Module["canvas"].addEventListener("mouseenter", GLFW.onMouseenter, true);
10212 Module["canvas"].addEventListener("mouseleave", GLFW.onMouseleave, true);
10213 Module["canvas"].addEventListener("drop", GLFW.onDrop, true);
10214 Module["canvas"].addEventListener("dragover", GLFW.onDragover, true);
10215 Browser.resizeListeners.push(function(width, height) {
10216 GLFW.onCanvasResize(width, height)
10217 });
10218 return 1
10219 }
10220
10221 function _glfwMakeContextCurrent(winid) {}
10222
10223 function _glfwPollEvents() {}
10224
10225 function _glfwSetClipboardString(win, string) {}
10226
10227 function _glfwSetDropCallback(winid, cbfun) {
10228 return GLFW.setDropCallback(winid, cbfun)
10229 }
10230
10231 function _glfwSetErrorCallback(cbfun) {
10232 var prevcbfun = GLFW.errorFunc;
10233 GLFW.errorFunc = cbfun;
10234 return prevcbfun
10235 }
10236
10237 function _glfwSetKeyCallback(winid, cbfun) {
10238 return GLFW.setKeyCallback(winid, cbfun)
10239 }
10240
10241 function _glfwSetScrollCallback(winid, cbfun) {
10242 return GLFW.setScrollCallback(winid, cbfun)
10243 }
10244
10245 function _glfwSetWindowSizeCallback(winid, cbfun) {
10246 return GLFW.setWindowSizeCallback(winid, cbfun)
10247 }
10248
10249 function _glfwSwapBuffers(winid) {
10250 GLFW.swapBuffers(winid)
10251 }
10252
10253 function _glfwSwapInterval(interval) {
10254 interval = Math.abs(interval);
10255 if (interval == 0) _emscripten_set_main_loop_timing(0, 0);
10256 else _emscripten_set_main_loop_timing(1, interval)
10257 }
10258
10259 function _glfwTerminate() {
10260 window.removeEventListener("gamepadconnected", GLFW.onGamepadConnected, true);
10261 window.removeEventListener("gamepaddisconnected", GLFW.onGamepadDisconnected, true);
10262 window.removeEventListener("keydown", GLFW.onKeydown, true);
10263 window.removeEventListener("keypress", GLFW.onKeyPress, true);
10264 window.removeEventListener("keyup", GLFW.onKeyup, true);
10265 window.removeEventListener("blur", GLFW.onBlur, true);
10266 Module["canvas"].removeEventListener("touchmove", GLFW.onMousemove, true);
10267 Module["canvas"].removeEventListener("touchstart", GLFW.onMouseButtonDown, true);
10268 Module["canvas"].removeEventListener("touchcancel", GLFW.onMouseButtonUp, true);
10269 Module["canvas"].removeEventListener("touchend", GLFW.onMouseButtonUp, true);
10270 Module["canvas"].removeEventListener("mousemove", GLFW.onMousemove, true);
10271 Module["canvas"].removeEventListener("mousedown", GLFW.onMouseButtonDown, true);
10272 Module["canvas"].removeEventListener("mouseup", GLFW.onMouseButtonUp, true);
10273 Module["canvas"].removeEventListener("wheel", GLFW.onMouseWheel, true);
10274 Module["canvas"].removeEventListener("mousewheel", GLFW.onMouseWheel, true);
10275 Module["canvas"].removeEventListener("mouseenter", GLFW.onMouseenter, true);
10276 Module["canvas"].removeEventListener("mouseleave", GLFW.onMouseleave, true);
10277 Module["canvas"].removeEventListener("drop", GLFW.onDrop, true);
10278 Module["canvas"].removeEventListener("dragover", GLFW.onDragover, true);
10279 Module["canvas"].width = Module["canvas"].height = 1;
10280 GLFW.windows = null;
10281 GLFW.active = null
10282 }
10283
10284 function _glfwWindowHint(target, hint) {
10285 GLFW.hints[target] = hint
10286 }
10287 var FSNode = function(parent, name, mode, rdev) {
10288 if (!parent) {
10289 parent = this
10290 }
10291 this.parent = parent;
10292 this.mount = parent.mount;
10293 this.mounted = null;
10294 this.id = FS.nextInode++;
10295 this.name = name;
10296 this.mode = mode;
10297 this.node_ops = {};
10298 this.stream_ops = {};
10299 this.rdev = rdev
10300 };
10301 var readMode = 292 | 73;
10302 var writeMode = 146;
10303 Object.defineProperties(FSNode.prototype, {
10304 read: {
10305 get: function() {
10306 return (this.mode & readMode) === readMode
10307 },
10308 set: function(val) {
10309 val ? this.mode |= readMode : this.mode &= ~readMode
10310 }
10311 },
10312 write: {
10313 get: function() {
10314 return (this.mode & writeMode) === writeMode
10315 },
10316 set: function(val) {
10317 val ? this.mode |= writeMode : this.mode &= ~writeMode
10318 }
10319 },
10320 isFolder: {
10321 get: function() {
10322 return FS.isDir(this.mode)
10323 }
10324 },
10325 isDevice: {
10326 get: function() {
10327 return FS.isChrdev(this.mode)
10328 }
10329 }
10330 });
10331 FS.FSNode = FSNode;
10332 FS.staticInit();
10333 Module["FS_createPath"] = FS.createPath;
10334 Module["FS_createDataFile"] = FS.createDataFile;
10335 Module["FS_createPreloadedFile"] = FS.createPreloadedFile;
10336 Module["FS_unlink"] = FS.unlink;
10337 Module["FS_createLazyFile"] = FS.createLazyFile;
10338 Module["FS_createDevice"] = FS.createDevice;
10339 Module["requestFullscreen"] = function Module_requestFullscreen(lockPointer, resizeCanvas) {
10340 Browser.requestFullscreen(lockPointer, resizeCanvas)
10341 };
10342 Module["requestAnimationFrame"] = function Module_requestAnimationFrame(func) {
10343 Browser.requestAnimationFrame(func)
10344 };
10345 Module["setCanvasSize"] = function Module_setCanvasSize(width, height, noUpdates) {
10346 Browser.setCanvasSize(width, height, noUpdates)
10347 };
10348 Module["pauseMainLoop"] = function Module_pauseMainLoop() {
10349 Browser.mainLoop.pause()
10350 };
10351 Module["resumeMainLoop"] = function Module_resumeMainLoop() {
10352 Browser.mainLoop.resume()
10353 };
10354 Module["getUserMedia"] = function Module_getUserMedia() {
10355 Browser.getUserMedia()
10356 };
10357 Module["createContext"] = function Module_createContext(canvas, useWebGL, setInModule, webGLContextAttributes) {
10358 return Browser.createContext(canvas, useWebGL, setInModule, webGLContextAttributes)
10359 };
10360 var preloadedImages = {};
10361 var preloadedAudios = {};
10362 var GLctx;
10363 var miniTempWebGLFloatBuffersStorage = new Float32Array(288);
10364 for (var i = 0; i < 288; ++i) {
10365 miniTempWebGLFloatBuffers[i] = miniTempWebGLFloatBuffersStorage.subarray(0, i + 1)
10366 }
10367
10368 function intArrayFromString(stringy, dontAddNull, length) {
10369 var len = length > 0 ? length : lengthBytesUTF8(stringy) + 1;
10370 var u8array = new Array(len);
10371 var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length);
10372 if (dontAddNull) u8array.length = numBytesWritten;
10373 return u8array
10374 }
10375 var asmLibraryArg = {
10376 "Ra": _SDL_GetNumAudioDrivers,
10377 "Sa": _SDL_Init,
10378 "Qa": _SDL_OpenAudio,
10379 "Q": _SDL_PauseAudio,
10380 "Pa": _SDL_Quit,
10381 "a": ___assert_fail,
10382 "da": ___syscall_faccessat,
10383 "aa": ___syscall_fcntl64,
10384 "cb": ___syscall_getdents64,
10385 "fb": ___syscall_ioctl,
10386 "db": ___syscall_mkdirat,
10387 "ba": ___syscall_openat,
10388 "$a": ___syscall_renameat,
10389 "ab": ___syscall_rmdir,
10390 "_a": ___syscall_stat64,
10391 "bb": ___syscall_unlinkat,
10392 "gb": __emscripten_date_now,
10393 "hb": __localtime_js,
10394 "ib": __mktime_js,
10395 "jb": __tzset_js,
10396 "_": _abort,
10397 "d": _emscripten_asm_const_int,
10398 "ta": _emscripten_cancel_main_loop,
10399 "ca": _emscripten_memcpy_big,
10400 "La": _emscripten_request_fullscreen_strategy,
10401 "Za": _emscripten_resize_heap,
10402 "sa": _emscripten_set_main_loop,
10403 "Ja": _emscripten_set_mousedown_callback_on_thread,
10404 "Ka": _emscripten_set_mousemove_callback_on_thread,
10405 "Ia": _emscripten_set_mouseup_callback_on_thread,
10406 "Ea": _emscripten_set_touchcancel_callback_on_thread,
10407 "Ga": _emscripten_set_touchend_callback_on_thread,
10408 "Fa": _emscripten_set_touchmove_callback_on_thread,
10409 "Ha": _emscripten_set_touchstart_callback_on_thread,
10410 "X": _exit,
10411 "G": _fd_close,
10412 "eb": _fd_read,
10413 "Ya": _fd_seek,
10414 "$": _fd_write,
10415 "Y": get_device_pixel_ratio,
10416 "K": get_hostname,
10417 "Ta": get_url_level_index,
10418 "x": _glActiveTexture,
10419 "V": _glAttachShader,
10420 "n": _glBindBuffer,
10421 "r": _glBindFramebuffer,
10422 "p": _glBindRenderbuffer,
10423 "e": _glBindTexture,
10424 "ea": _glBlendFunc,
10425 "B": _glBufferData,
10426 "ga": _glCheckFramebufferStatus,
10427 "t": _glClear,
10428 "D": _glClearColor,
10429 "na": _glCompileShader,
10430 "la": _glCreateProgram,
10431 "pa": _glCreateShader,
10432 "M": _glDeleteBuffers,
10433 "L": _glDeleteFramebuffers,
10434 "C": _glDeleteRenderbuffers,
10435 "O": _glDeleteTextures,
10436 "fa": _glDepthFunc,
10437 "l": _glDepthMask,
10438 "c": _glDisable,
10439 "h": _glDisableVertexAttribArray,
10440 "q": _glDrawArrays,
10441 "b": _glEnable,
10442 "m": _glEnableVertexAttribArray,
10443 "y": _glFramebufferRenderbuffer,
10444 "ha": _glFramebufferTexture2D,
10445 "N": _glGenBuffers,
10446 "J": _glGenFramebuffers,
10447 "v": _glGenRenderbuffers,
10448 "F": _glGenTextures,
10449 "i": _glGetAttribLocation,
10450 "s": _glGetIntegerv,
10451 "ja": _glGetProgramInfoLog,
10452 "U": _glGetProgramiv,
10453 "ma": _glGetShaderInfoLog,
10454 "W": _glGetShaderiv,
10455 "k": _glGetUniformLocation,
10456 "ka": _glLinkProgram,
10457 "R": _glReadPixels,
10458 "z": _glRenderbufferStorage,
10459 "oa": _glShaderSource,
10460 "E": _glTexImage2D,
10461 "j": _glTexParameterf,
10462 "H": _glTexParameteri,
10463 "ia": _glTexSubImage2D,
10464 "T": _glUniform1f,
10465 "I": _glUniform1i,
10466 "A": _glUniform2f,
10467 "u": _glUniform3fv,
10468 "g": _glUniformMatrix4fv,
10469 "w": _glUseProgram,
10470 "f": _glVertexAttribPointer,
10471 "o": _glViewport,
10472 "za": _glfwCreateWindow,
10473 "Ba": _glfwGetPrimaryMonitor,
10474 "Aa": _glfwGetVideoMode,
10475 "Ca": _glfwInit,
10476 "ya": _glfwMakeContextCurrent,
10477 "Na": _glfwPollEvents,
10478 "Ma": _glfwSetClipboardString,
10479 "va": _glfwSetDropCallback,
10480 "Da": _glfwSetErrorCallback,
10481 "xa": _glfwSetKeyCallback,
10482 "wa": _glfwSetScrollCallback,
10483 "ua": _glfwSetWindowSizeCallback,
10484 "Oa": _glfwSwapBuffers,
10485 "ra": _glfwSwapInterval,
10486 "qa": _glfwTerminate,
10487 "P": _glfwWindowHint,
10488 "Wa": is_daily_reward_possible,
10489 "Va": is_latest_browser_tab,
10490 "S": poki_gameplay_start,
10491 "Xa": poki_gameplay_stop,
10492 "Z": poki_level_start,
10493 "Ua": set_latest_browser_tab
10494 };
10495 var asm = createWasm();
10496 var ___wasm_call_ctors = Module["___wasm_call_ctors"] = function() {
10497 return (___wasm_call_ctors = Module["___wasm_call_ctors"] = Module["asm"]["lb"]).apply(null, arguments)
10498 };
10499 var _ad_on_inited = Module["_ad_on_inited"] = function() {
10500 return (_ad_on_inited = Module["_ad_on_inited"] = Module["asm"]["mb"]).apply(null, arguments)
10501 };
10502 var _ad_interstitial_on_loaded = Module["_ad_interstitial_on_loaded"] = function() {
10503 return (_ad_interstitial_on_loaded = Module["_ad_interstitial_on_loaded"] = Module["asm"]["nb"]).apply(null, arguments)
10504 };
10505 var _ad_interstitial_on_showed = Module["_ad_interstitial_on_showed"] = function() {
10506 return (_ad_interstitial_on_showed = Module["_ad_interstitial_on_showed"] = Module["asm"]["ob"]).apply(null, arguments)
10507 };
10508 var _ad_rewarded_on_loaded = Module["_ad_rewarded_on_loaded"] = function() {
10509 return (_ad_rewarded_on_loaded = Module["_ad_rewarded_on_loaded"] = Module["asm"]["pb"]).apply(null, arguments)
10510 };
10511 var _ad_rewarded_on_reward = Module["_ad_rewarded_on_reward"] = function() {
10512 return (_ad_rewarded_on_reward = Module["_ad_rewarded_on_reward"] = Module["asm"]["qb"]).apply(null, arguments)
10513 };
10514 var _ad_rewarded_on_showed = Module["_ad_rewarded_on_showed"] = function() {
10515 return (_ad_rewarded_on_showed = Module["_ad_rewarded_on_showed"] = Module["asm"]["rb"]).apply(null, arguments)
10516 };
10517 var _app_error = Module["_app_error"] = function() {
10518 return (_app_error = Module["_app_error"] = Module["asm"]["sb"]).apply(null, arguments)
10519 };
10520 var _free = Module["_free"] = function() {
10521 return (_free = Module["_free"] = Module["asm"]["tb"]).apply(null, arguments)
10522 };
10523 var _hint_file_exists = Module["_hint_file_exists"] = function() {
10524 return (_hint_file_exists = Module["_hint_file_exists"] = Module["asm"]["ub"]).apply(null, arguments)
10525 };
10526 var _malloc = Module["_malloc"] = function() {
10527 return (_malloc = Module["_malloc"] = Module["asm"]["vb"]).apply(null, arguments)
10528 };
10529 var _menu_query_games_add_result = Module["_menu_query_games_add_result"] = function() {
10530 return (_menu_query_games_add_result = Module["_menu_query_games_add_result"] = Module["asm"]["wb"]).apply(null, arguments)
10531 };
10532 var _menu_query_games_finished = Module["_menu_query_games_finished"] = function() {
10533 return (_menu_query_games_finished = Module["_menu_query_games_finished"] = Module["asm"]["xb"]).apply(null, arguments)
10534 };
10535 var _menu_read_game_finished = Module["_menu_read_game_finished"] = function() {
10536 return (_menu_read_game_finished = Module["_menu_read_game_finished"] = Module["asm"]["yb"]).apply(null, arguments)
10537 };
10538 var _menu_read_counts_finished = Module["_menu_read_counts_finished"] = function() {
10539 return (_menu_read_counts_finished = Module["_menu_read_counts_finished"] = Module["asm"]["zb"]).apply(null, arguments)
10540 };
10541 var _menu_read_ledger_finished = Module["_menu_read_ledger_finished"] = function() {
10542 return (_menu_read_ledger_finished = Module["_menu_read_ledger_finished"] = Module["asm"]["Ab"]).apply(null, arguments)
10543 };
10544 var _menu_write_ledger_finished = Module["_menu_write_ledger_finished"] = function() {
10545 return (_menu_write_ledger_finished = Module["_menu_write_ledger_finished"] = Module["asm"]["Bb"]).apply(null, arguments)
10546 };
10547 var _menu_read_gems_finished = Module["_menu_read_gems_finished"] = function() {
10548 return (_menu_read_gems_finished = Module["_menu_read_gems_finished"] = Module["asm"]["Cb"]).apply(null, arguments)
10549 };
10550 var _memcpy = Module["_memcpy"] = function() {
10551 return (_memcpy = Module["_memcpy"] = Module["asm"]["Db"]).apply(null, arguments)
10552 };
10553 var _state_menu_deeplink_stop = Module["_state_menu_deeplink_stop"] = function() {
10554 return (_state_menu_deeplink_stop = Module["_state_menu_deeplink_stop"] = Module["asm"]["Eb"]).apply(null, arguments)
10555 };
10556 var _menu_file_upload_finished = Module["_menu_file_upload_finished"] = function() {
10557 return (_menu_file_upload_finished = Module["_menu_file_upload_finished"] = Module["asm"]["Fb"]).apply(null, arguments)
10558 };
10559 var _share_file_finished = Module["_share_file_finished"] = function() {
10560 return (_share_file_finished = Module["_share_file_finished"] = Module["asm"]["Gb"]).apply(null, arguments)
10561 };
10562 var _iap_cancelled = Module["_iap_cancelled"] = function() {
10563 return (_iap_cancelled = Module["_iap_cancelled"] = Module["asm"]["Hb"]).apply(null, arguments)
10564 };
10565 var _state_menu_payout_add = Module["_state_menu_payout_add"] = function() {
10566 return (_state_menu_payout_add = Module["_state_menu_payout_add"] = Module["asm"]["Ib"]).apply(null, arguments)
10567 };
10568 var _state_menu_payout_stop = Module["_state_menu_payout_stop"] = function() {
10569 return (_state_menu_payout_stop = Module["_state_menu_payout_stop"] = Module["asm"]["Jb"]).apply(null, arguments)
10570 };
10571 var _menu_on_password_reset_email_sent = Module["_menu_on_password_reset_email_sent"] = function() {
10572 return (_menu_on_password_reset_email_sent = Module["_menu_on_password_reset_email_sent"] = Module["asm"]["Kb"]).apply(null, arguments)
10573 };
10574 var _menu_sync_upload_finished = Module["_menu_sync_upload_finished"] = function() {
10575 return (_menu_sync_upload_finished = Module["_menu_sync_upload_finished"] = Module["asm"]["Lb"]).apply(null, arguments)
10576 };
10577 var _menu_sync_download_finished = Module["_menu_sync_download_finished"] = function() {
10578 return (_menu_sync_download_finished = Module["_menu_sync_download_finished"] = Module["asm"]["Mb"]).apply(null, arguments)
10579 };
10580 var _game_download_finished = Module["_game_download_finished"] = function() {
10581 return (_game_download_finished = Module["_game_download_finished"] = Module["asm"]["Ob"]).apply(null, arguments)
10582 };
10583 var _app_fetch_url_done = Module["_app_fetch_url_done"] = function() {
10584 return (_app_fetch_url_done = Module["_app_fetch_url_done"] = Module["asm"]["Pb"]).apply(null, arguments)
10585 };
10586 var _app_webview_message = Module["_app_webview_message"] = function() {
10587 return (_app_webview_message = Module["_app_webview_message"] = Module["asm"]["Qb"]).apply(null, arguments)
10588 };
10589 var _app_pause = Module["_app_pause"] = function() {
10590 return (_app_pause = Module["_app_pause"] = Module["asm"]["Rb"]).apply(null, arguments)
10591 };
10592 var _app_resume = Module["_app_resume"] = function() {
10593 return (_app_resume = Module["_app_resume"] = Module["asm"]["Sb"]).apply(null, arguments)
10594 };
10595 var _app_on_signin = Module["_app_on_signin"] = function() {
10596 return (_app_on_signin = Module["_app_on_signin"] = Module["asm"]["Tb"]).apply(null, arguments)
10597 };
10598 var _app_on_signout = Module["_app_on_signout"] = function() {
10599 return (_app_on_signout = Module["_app_on_signout"] = Module["asm"]["Ub"]).apply(null, arguments)
10600 };
10601 var _notification_show_inapp = Module["_notification_show_inapp"] = function() {
10602 return (_notification_show_inapp = Module["_notification_show_inapp"] = Module["asm"]["Vb"]).apply(null, arguments)
10603 };
10604 var _app_init = Module["_app_init"] = function() {
10605 return (_app_init = Module["_app_init"] = Module["asm"]["Wb"]).apply(null, arguments)
10606 };
10607 var _set_is_mobile = Module["_set_is_mobile"] = function() {
10608 return (_set_is_mobile = Module["_set_is_mobile"] = Module["asm"]["Xb"]).apply(null, arguments)
10609 };
10610 var _get_app_version = Module["_get_app_version"] = function() {
10611 return (_get_app_version = Module["_get_app_version"] = Module["asm"]["Yb"]).apply(null, arguments)
10612 };
10613 var _use_test_api_server = Module["_use_test_api_server"] = function() {
10614 return (_use_test_api_server = Module["_use_test_api_server"] = Module["asm"]["Zb"]).apply(null, arguments)
10615 };
10616 var _level_select_menu_start_level = Module["_level_select_menu_start_level"] = function() {
10617 return (_level_select_menu_start_level = Module["_level_select_menu_start_level"] = Module["asm"]["_b"]).apply(null, arguments)
10618 };
10619 var _set_game_focus = Module["_set_game_focus"] = function() {
10620 return (_set_game_focus = Module["_set_game_focus"] = Module["asm"]["$b"]).apply(null, arguments)
10621 };
10622 var _set_ad_freq = Module["_set_ad_freq"] = function() {
10623 return (_set_ad_freq = Module["_set_ad_freq"] = Module["asm"]["ac"]).apply(null, arguments)
10624 };
10625 var _set_ad_duration_offline = Module["_set_ad_duration_offline"] = function() {
10626 return (_set_ad_duration_offline = Module["_set_ad_duration_offline"] = Module["asm"]["bc"]).apply(null, arguments)
10627 };
10628 var _set_abtest_in_game_get = Module["_set_abtest_in_game_get"] = function() {
10629 return (_set_abtest_in_game_get = Module["_set_abtest_in_game_get"] = Module["asm"]["cc"]).apply(null, arguments)
10630 };
10631 var _set_user_premium_ends = Module["_set_user_premium_ends"] = function() {
10632 return (_set_user_premium_ends = Module["_set_user_premium_ends"] = Module["asm"]["dc"]).apply(null, arguments)
10633 };
10634 var _get_user_premium_ends = Module["_get_user_premium_ends"] = function() {
10635 return (_get_user_premium_ends = Module["_get_user_premium_ends"] = Module["asm"]["ec"]).apply(null, arguments)
10636 };
10637 var _set_user_banned = Module["_set_user_banned"] = function() {
10638 return (_set_user_banned = Module["_set_user_banned"] = Module["asm"]["fc"]).apply(null, arguments)
10639 };
10640 var _set_user_gems = Module["_set_user_gems"] = function() {
10641 return (_set_user_gems = Module["_set_user_gems"] = Module["asm"]["gc"]).apply(null, arguments)
10642 };
10643 var _set_user_nick = Module["_set_user_nick"] = function() {
10644 return (_set_user_nick = Module["_set_user_nick"] = Module["asm"]["hc"]).apply(null, arguments)
10645 };
10646 var _set_user_state = Module["_set_user_state"] = function() {
10647 return (_set_user_state = Module["_set_user_state"] = Module["asm"]["ic"]).apply(null, arguments)
10648 };
10649 var _set_user_uid = Module["_set_user_uid"] = function() {
10650 return (_set_user_uid = Module["_set_user_uid"] = Module["asm"]["jc"]).apply(null, arguments)
10651 };
10652 var _set_user_adfree_ends = Module["_set_user_adfree_ends"] = function() {
10653 return (_set_user_adfree_ends = Module["_set_user_adfree_ends"] = Module["asm"]["kc"]).apply(null, arguments)
10654 };
10655 var _get_app_inited = Module["_get_app_inited"] = function() {
10656 return (_get_app_inited = Module["_get_app_inited"] = Module["asm"]["lc"]).apply(null, arguments)
10657 };
10658 var _log_simple = Module["_log_simple"] = function() {
10659 return (_log_simple = Module["_log_simple"] = Module["asm"]["mc"]).apply(null, arguments)
10660 };
10661 var _app_terminate_if_necessary = Module["_app_terminate_if_necessary"] = function() {
10662 return (_app_terminate_if_necessary = Module["_app_terminate_if_necessary"] = Module["asm"]["nc"]).apply(null, arguments)
10663 };
10664 var _score_set_top_nicks_and_scores = Module["_score_set_top_nicks_and_scores"] = function() {
10665 return (_score_set_top_nicks_and_scores = Module["_score_set_top_nicks_and_scores"] = Module["asm"]["oc"]).apply(null, arguments)
10666 };
10667 var _score_set_above_nicks_and_scores = Module["_score_set_above_nicks_and_scores"] = function() {
10668 return (_score_set_above_nicks_and_scores = Module["_score_set_above_nicks_and_scores"] = Module["asm"]["pc"]).apply(null, arguments)
10669 };
10670 var _score_set_below_nicks_and_scores = Module["_score_set_below_nicks_and_scores"] = function() {
10671 return (_score_set_below_nicks_and_scores = Module["_score_set_below_nicks_and_scores"] = Module["asm"]["qc"]).apply(null, arguments)
10672 };
10673 var _score_read_finished_em = Module["_score_read_finished_em"] = function() {
10674 return (_score_read_finished_em = Module["_score_read_finished_em"] = Module["asm"]["rc"]).apply(null, arguments)
10675 };
10676 var _keydown_browser = Module["_keydown_browser"] = function() {
10677 return (_keydown_browser = Module["_keydown_browser"] = Module["asm"]["sc"]).apply(null, arguments)
10678 };
10679 var _update_screen_size = Module["_update_screen_size"] = function() {
10680 return (_update_screen_size = Module["_update_screen_size"] = Module["asm"]["tc"]).apply(null, arguments)
10681 };
10682 var _request_fullscreen = Module["_request_fullscreen"] = function() {
10683 return (_request_fullscreen = Module["_request_fullscreen"] = Module["asm"]["uc"]).apply(null, arguments)
10684 };
10685 var _user_accepted_and_clicked = Module["_user_accepted_and_clicked"] = function() {
10686 return (_user_accepted_and_clicked = Module["_user_accepted_and_clicked"] = Module["asm"]["vc"]).apply(null, arguments)
10687 };
10688 var _main = Module["_main"] = function() {
10689 return (_main = Module["_main"] = Module["asm"]["wc"]).apply(null, arguments)
10690 };
10691 var _ntp_set_server_time = Module["_ntp_set_server_time"] = function() {
10692 return (_ntp_set_server_time = Module["_ntp_set_server_time"] = Module["asm"]["xc"]).apply(null, arguments)
10693 };
10694 var _moderation_publish_perform = Module["_moderation_publish_perform"] = function() {
10695 return (_moderation_publish_perform = Module["_moderation_publish_perform"] = Module["asm"]["yc"]).apply(null, arguments)
10696 };
10697 var _play_counter_falloff = Module["_play_counter_falloff"] = function() {
10698 return (_play_counter_falloff = Module["_play_counter_falloff"] = Module["asm"]["zc"]).apply(null, arguments)
10699 };
10700 var _news_create = Module["_news_create"] = function() {
10701 return (_news_create = Module["_news_create"] = Module["asm"]["Ac"]).apply(null, arguments)
10702 };
10703 var _news_update_started = Module["_news_update_started"] = function() {
10704 return (_news_update_started = Module["_news_update_started"] = Module["asm"]["Bc"]).apply(null, arguments)
10705 };
10706 var _news_update_finished = Module["_news_update_finished"] = function() {
10707 return (_news_update_finished = Module["_news_update_finished"] = Module["asm"]["Cc"]).apply(null, arguments)
10708 };
10709 var ___errno_location = Module["___errno_location"] = function() {
10710 return (___errno_location = Module["___errno_location"] = Module["asm"]["Dc"]).apply(null, arguments)
10711 };
10712 var stackSave = Module["stackSave"] = function() {
10713 return (stackSave = Module["stackSave"] = Module["asm"]["Ec"]).apply(null, arguments)
10714 };
10715 var stackRestore = Module["stackRestore"] = function() {
10716 return (stackRestore = Module["stackRestore"] = Module["asm"]["Fc"]).apply(null, arguments)
10717 };
10718 var stackAlloc = Module["stackAlloc"] = function() {
10719 return (stackAlloc = Module["stackAlloc"] = Module["asm"]["Gc"]).apply(null, arguments)
10720 };
10721 Module["ccall"] = ccall;
10722 Module["cwrap"] = cwrap;
10723 Module["addRunDependency"] = addRunDependency;
10724 Module["removeRunDependency"] = removeRunDependency;
10725 Module["FS_createPath"] = FS.createPath;
10726 Module["FS_createDataFile"] = FS.createDataFile;
10727 Module["FS_createPreloadedFile"] = FS.createPreloadedFile;
10728 Module["FS_createLazyFile"] = FS.createLazyFile;
10729 Module["FS_createDevice"] = FS.createDevice;
10730 Module["FS_unlink"] = FS.unlink;
10731 var calledRun;
10732
10733 function ExitStatus(status) {
10734 this.name = "ExitStatus";
10735 this.message = "Program terminated with exit(" + status + ")";
10736 this.status = status
10737 }
10738 var calledMain = false;
10739 dependenciesFulfilled = function runCaller() {
10740 if (!calledRun) run();
10741 if (!calledRun) dependenciesFulfilled = runCaller
10742 };
10743
10744 function callMain(args) {
10745 var entryFunction = Module["_main"];
10746 args = args || [];
10747 args.unshift(thisProgram);
10748 var argc = args.length;
10749 var argv = stackAlloc((argc + 1) * 4);
10750 var argv_ptr = argv >> 2;
10751 args.forEach(arg => {
10752 HEAP32[argv_ptr++] = allocateUTF8OnStack(arg)
10753 });
10754 HEAP32[argv_ptr] = 0;
10755 try {
10756 var ret = entryFunction(argc, argv);
10757 exit(ret, true);
10758 return ret
10759 } catch (e) {
10760 return handleException(e)
10761 } finally {
10762 calledMain = true
10763 }
10764 }
10765
10766 function run(args) {
10767 args = args || arguments_;
10768 if (runDependencies > 0) {
10769 return
10770 }
10771 preRun();
10772 if (runDependencies > 0) {
10773 return
10774 }
10775
10776 function doRun() {
10777 if (calledRun) return;
10778 calledRun = true;
10779 Module["calledRun"] = true;
10780 if (ABORT) return;
10781 initRuntime();
10782 preMain();
10783 if (Module["onRuntimeInitialized"]) Module["onRuntimeInitialized"]();
10784 if (shouldRunNow) callMain(args);
10785 postRun()
10786 }
10787 if (Module["setStatus"]) {
10788 Module["setStatus"]("Running...");
10789 setTimeout(function() {
10790 setTimeout(function() {
10791 Module["setStatus"]("")
10792 }, 1);
10793 doRun()
10794 }, 1)
10795 } else {
10796 doRun()
10797 }
10798 }
10799 Module["run"] = run;
10800
10801 function exit(status, implicit) {
10802 EXITSTATUS = status;
10803 procExit(status)
10804 }
10805
10806 function procExit(code) {
10807 EXITSTATUS = code;
10808 if (!keepRuntimeAlive()) {
10809 if (Module["onExit"]) Module["onExit"](code);
10810 ABORT = true
10811 }
10812 quit_(code, new ExitStatus(code))
10813 }
10814 if (Module["preInit"]) {
10815 if (typeof Module["preInit"] == "function") Module["preInit"] = [Module["preInit"]];
10816 while (Module["preInit"].length > 0) {
10817 Module["preInit"].pop()()
10818 }
10819 }
10820 var shouldRunNow = true;
10821 if (Module["noInitialRun"]) shouldRunNow = false;
10822 run();
10823 </script>
10824</body>
10825
10826</html>
10827
HTML Explanation
The HTML sets up the canvas-based rendering environment for the game.
Key elements:
A <canvas> element where the WASM game is rendered.
A loading overlay with a progress bar.
A cover preview showing the game title and author.
Supporting containers for gradients, modals, and web views.
The structure is minimal, relying heavily on JavaScript and WebAssembly for functionality.
CSS Explanation
The CSS is focused on fullscreen presentation and game immersion.
Highlights:
Fixed-size canvas optimized for WebGL rendering.
Gradient background for a modern, polished look.
Minimal UI styling to keep focus on gameplay.
Fonts and spacing designed for readability during loading.
Responsive resizing is later handled dynamically using JavaScript.
Javascrip Explanation
The JavaScript handles game initialization and runtime control.
Main responsibilities:
Initializing the canvas and preventing default browser actions.
Dynamically resizing the canvas for different screen sizes.
Communicating screen updates to the WebAssembly game via Module.ccall.
Tracking loading progress and triggering the game start once ready.
Behind the scenes, additional logic manages:
WebGL contexts
Poki SDK ads
Input handling
File loading
Game lifecycle events
🚀 Key Features
WebAssembly-powered game execution
High-performance WebGL rendering
Dynamic canvas resizing
Poki SDK ad and event integration
Loading progress visualization
Modular and production-ready structure
🎯 Use Cases
Browser-based arcade games
WebGL and WASM game deployment
Poki / CrazyGames integration
Learning advanced canvas + WASM workflows
Hosting Unity or C++ compiled games on the web
