gd-webport-loopjackson 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/index.html +1435 -0
  2. package/package.json +11 -4
  3. package/README.md +0 -3
package/index.html ADDED
@@ -0,0 +1,1435 @@
1
+ <!DOCTYPE html><html><head><base href="https://cdn.jsdelivr.net/gh/Ale7208/geometry-dash-wasm/"><title>Geometry Dash webport</title>
2
+ <meta name="description" content="A Geometry Dash webport that runs in your browser with no installation.">
3
+ <link rel="canonical" href="https://gd-webport.pages.dev/">
4
+ <meta property="og:type" content="website">
5
+ <meta property="og:title" content="Geometry Dash webport">
6
+ <meta property="og:description" content="A Geometry Dash webport that runs in your browser with no installation.">
7
+ <meta property="og:url" content="https://gd-webport.pages.dev/">
8
+ <meta property="og:image" content="https://cdn.jsdelivr.net/gh/Ale7208/geometry-dash-wasm@main/ref/preview.png">
9
+ <meta property="og:image:width" content="1200">
10
+ <meta property="og:image:height" content="630">
11
+ <meta name="twitter:card" content="summary_large_image">
12
+ <meta name="twitter:title" content="Geometry Dash webport">
13
+ <meta name="twitter:description" content="A Geometry Dash webport that runs in your browser with no installation.">
14
+ <meta name="twitter:url" content="https://gd-webport.pages.dev/">
15
+ <meta name="twitter:image" content="https://cdn.jsdelivr.net/gh/Ale7208/geometry-dash-wasm@main/ref/preview.png">
16
+ <link rel="icon" type="image/x-icon" href="https://cdn.jsdelivr.net/gh/Ale7208/geometry-dash-wasm@main/ref/favicon.ico"><script>(function(){var U="data:font/woff2;base64,d09GMgABAAAAAB8kAAwAAAAAQGAAAB7TAAQBBgAAAAAAAAAAAAAAAAAAAAAAAAAAGx4cLgZgAIMSCudM0jYBNgIkA4ZoC4M2AAQgBYNcB4QLGzwzsyLYOACAotcVRX2Ye3bZf5XADRnwGqpIiNSqI1ajOj6FOgHDERFDhE2IyH/Wj7cTVqECxvvyfl8dcfj+CI19kktULfs3q3rft04Sc5Z55iyy1LvglorKU4WgoAAUFjaOiRkPb4bn59YjpI2EdkSugkX/xd/2V/kXbOSokbOQNLpQDy48jxl92HFRem22A3EzWDOPFXXvfnpnkzeJQDKgzUAjqxKojfNDbefY/9KV/VaPDO9J3iB3ELkcRQsNw1rW2jLwAqqcSbERjyhEimjAPOcDwAZkoKL+f3P9a5OFT1SmlQVhml+QPZElx/qpyZ2FzM5OTpbgcelxXrb0OTul3RSAXBVS9jPulpBc3betq6sQ8suirJCOVYaOFPZuxXL2EbcsZws9k5lRGQ0yYDTI5P66LWdtdn8RxUOJbQ9QAIekSRN2592ICcSIBFifQUBwPY2A/knPlAcpMMYKXvgsRc5/G2MWGQL0/doAD6xMeQwlMKT2jOX2e47ue0SmBceAi89Gpuy2KNsCbb4QwAcAvbQHABeKBBQwgDMihLHRkWmn14oeywTAUe0+h91j7KEO9l5/vHAMJgWTgcnC5GHYGAnmqr4ha1TWWG8BORpj00DDVqMxSZg0KetRzXoJrBNr8WrcxX7y8beP//+6/9dvfv361/5f9/665tfFvxb98u3Pgz+fAmHGe8CV/ucYUYaQUdOJFQePxshBq4BFrjFGEeHKQJRlhGw8SazGK5LJKV8kj5HYNBLRCdmkyCORxo1ptGgCchjDFUOk4kCZKeVwgR/jRsnISEoQ4BjwYanEe1A6KYWhrjPM7exMYBAvlnEKjUWRAL6HfIW/OPoNpz9jTpVA/hVx2teDG3sqQCtCqMk6ax1dtZ8LqWHgTkIibjdfbF1UBHvCFEV28QMq8Ny7cYMB0ejNnLFrjBV4wBNewhjsuTOqY5kAgWxWfMrAVAgwF91mdgCBEdbO0SMY9gFSo1Oqp0G2f0rVeT+7ETmkBWyP/5qvNkKYpMC4IJRsjlLyLRXhbJ1dZoge3gFNLeqoMPV9Y6a22fUTVi1oa+Wp1c6avY833HrEbDtiH/hw9pGGTVqDWAvIW5/+AZ2iCc0MUpWVQw2pyp6qtyJzEEIOr6PXZSyCPf3xmsJQa3lLDjAmfPnIXX2GuIZxJcoiW/VuRpuaM0kV9fsJzJO0jIMYWTZw5J0cNhQY+KGKQ2l0wYUPfzaGSf+eE7yglmVODnMvFaVrOS4GI+Jk4Su1rt76gNv+frUHKzLwtLSwYUjhcP8csk9jIE7LLOYJcnsU6Xe5krkh92ETa44+/WABc+9sFS4lSPECG+lp2+mpebTLfvlZZ2DDUud9ugXMP6XeyZ22l+cCq/qfPgWh2M0fkWOZNYuvs/DG+e1bR3MYAiXwuoS+ikZ3ONSFpsRv0+fOkcIcCRXVSu8xUawg7Ptw3trI0O+JQnsskZKD+/iSLEE9J3iFQe8mKL6NXwevUgYUR8yN6Xg+kic++QrQs6MLOv5eUvwFS5gi/XhRm+fouBbA6dnc2hap+O4ABnWl1t7vDx2xzc+NBdAlcuH+OimexFiPogmH8Uu1Kedp7GHZpvZycUJr4L8fKiikoLcxgO3ye6Rqf59WLKgxH3CuP29k9TR4E7hHWug0lrLeBdBgaZ/vhqJTkUHCFly9+rUylorCk9QmKY7cX+aFdwm4EMfzMUwOkgj2vT+NCImee4WJUCCxRGEsmUScGqQqD0sfQ0Yqls5wYv0d8xXoKMvAINZJRRJZpXgyvKKeujSG8exDtZTTM54ShVz+IdtE25rYSoaw+1nd1WgP9QX88peZxbL6+xGcgdiQzq2yuU7udW+RQibH7G9OWuWScV0BH0rVZklSu53WkGdXyLiV3skkcDHeh8Yfl7t+GDNBBSGmSFAwTZpBVs1Jz89hN1vJchPtpml7pZl7WkO9ikadtQbnqwE0hP1ZAhm6BLIs2ETB1oklLk5AcTNTn1haL6uCOJW6cPcFx1Recs/HirvnTKxHBtj+4WF/MJ6r0MIa0x807tK74tn872VtWC0+NMi016sKi1ME0FC8nIBK8QLC7/3lnMdnUE8q2nX1QxHmA+gSp5Al6jO6fHDu6LZyUcLnWhvmWlJcXmLI2AXc5jk9U3QV/5sp1SjKHSht/wuefm87T0234qw4eT8DbKZAqPYlN0GrcvC/ECeeeEF4v9CbeKcTAtfLlsNvW1WvN4JdjlLyienCfQaZB0RKE47jTzXYRJvLTdiRtlGaXOxMCs7EelZr8wtotAeutLPRx1y8Fz+7OwZsMX6Lbx/Otg28NZbLy6bDsZl3YYNbCABQV8yV3JxbVe9cQPYKmjgKrWIyHO7q1nD7jeO8eVWyQ4pIx80TUsTKMIgkLaLaaVjD56DEVMth2CBoO/ZLtD3ZG2qgePFAOKB+8farKbgA2H/XyNRoiBQTwzNjN5j3js6ORGk5PjY9HIdrzANSfMCGoinF7BAKHeo7RYNzddAy1VbVyM9VsIH3cZDWunEbFyk/CEJVuLbr2FLW4y0DDC4wv8S1noMzUq5x4bVmE+YwK2JZtpMSZIFM9rWa13TwyiO3KwZQp+8u776NenpiJKmrhIrUe8pvk5mpf9Vkl5zxkFfGsdzDfLdgGZUHb2LImRjJs6nwSaOCiEq6m65/MYv5BSnOynDpnsbUlrm7O9YkN+JyoqWBZ8JdexTzSHJo0et7E6P8PP5Azwolc8sQQlwybT6lGf5+r7yDRUwSL1DtEauRJSQfaziSplNT/5XdU3PIWiEf31PoDBMcDKfdSWyK/f5Hl38PcnrPDHRZZr8uzE/W5ol3WioyyGKZ1tXPqfoimbxrcoimONQeDDMuxprmdDxeGKecGfVuzPoRY+df9lLvjCH+leccadrTX3g6afxZTBd/BVBeNWHcsBuEhF7x1KNnIMzXuJd4rtBE156dfTEJtDDg8oXKusIjyQGJdvDdVzGvKMRi90MJBnQ4Yc4IsVzl75D/1kruhFH+8Rm+XOzB3Htsxfdks2eJ1O3k4ad8pYsp4326mM/yi/n0le5qPl+YfpmM6QCIuTVQlHY4zBwNRdTR7hfhcuH/ezms8rVx5IUh10fsd99BVhmtDD5IEZBJ01LBB+mZA+deI4NT63HzieOYreTlH9pPWk6egBfkrbjcrwHPhI3CsNbstrUp66vlCEEenG1Yims/a81xBBTPYl75rehDdhxGwWlQjg26liZzD9DA/gDOoB5A08lrR7FFP/SCczFunW3q/XQaywjRhR8bOndrACcG4p4j/eYpR6gpKXpydjPN7GQQvTQtblAQP/jTyAm0nM/9Zo5ubdFpK+g1yKzX9R3la3V7W+bqnl8rXp/XwLAFRIuTJYzQM/SO6MYyoPay6hLfiUfos1kqob7B7xpiZBhNUZXuaJVXzNz1QjTCkMVUiVrHLG34i3aH+tMBrohA3hf4HxQ263VCoV4nka4MUvnsZSHHOrepuHoCIZCV1YAntGf9f/iAoMtLdPoehnpnOwHf3rna31agzIHmNFMUcD2V6xEqDPW68S+P5uFwMmN+MUNbmK9MR2M+5RUkZGdEV12+kgo1+vTzh5asWzdXZCmsuXCxg1TNMaklIPqbtPhBQcIguIVWZ+7a21BUVeKJDVQ15G1cW51c4Y/1AGIoVlDU1248ozu0RymU1vfuyvuReVyge322cA5rLjNXPNE6fIVq2IqJtjxoDmtOcY54im34SmTESmCS3bxjvnNDfeOu+e5NsHtqIIEHJwDtkGTMPmV038gcm2PkGBvgpQWOzZvLPnv7A8fnztt+/zrLuIkyBSRBsr7VMW6SLoGA8HPPAXI7jIeuOzvBV30Lu30LpCK+UiZRmsJltohAx6TyyomNZUbfuqlBr8aG/CYC4okdlRUSH4lipPNl9nlDhMNVLoRFdVRSFdUz66PLbTVGlUwGw2xVqag8EUlCgYvNp0sEQr5KUG4H+Zuk7gd1P5ZpyzY7NkecT2gbCuJ6PPcD9gKasVKCq+XB9MZ6kcHfVTPUbj9jFAi1WrdGozVp6BpKqmXVN+DA8ma7dRZYV1rNFldO7miU0GqqBUhlM4rfPCEAfAF/rM709TJVFkFGRaxug8xgUWq0NjV4N3fsXGdyd7fmHpg9n2PkMuiWagqCYLEYFgabZzFdg92QSFDSQkOQJhqcRJDcc3XYba1IJsXs+UwDJIYMEuYvJ1wSqdChrl+ZdrUQQmUqcGgWzOMbNV1hqxEvhQtVMTh+Vc2U7qZ5Dd/ua8dtrTa7Khrrok2my4vNBrnKiCIygxVW6K0aIJn55MGT+81P7z99AGo/q706+laXBy5DnTQ33wvv8UkBt7+rLBDu1kasTy8NcIxcuZTHl4nZFi7d4SOLbKdjvwbr79xqtK4o1VIX+exiip79r5tMRyxOrYrfFdDIPRj5F1oyJmsEl17AVqU3MXvWLVw44UhTzelJoGfjggVueeZhW05NzRadbUXZ/K6//5y+SCJU0bAOBo0ppJFgZr6TQndRwd9rSMVrSt7v87/bV6K/P9Uz1QMul/yWoyii000VJFlk6J28lEDWUvhinTcsZ7VQyqHTuUW88n7WUDuLrRVDG15tBkUn0C0bUG9Tb11eWd2lWghRNEOiNpMRSP4QKZBa8aW6vNLe2ibvBge6uQKsHNhhsq2vqbGt22Fouhu6O6Nu/oKu7gWLZ7TntIOd9f98Un16kqaacGCCCtwaUBL/e6V8xUZDwPnoQp1YoWgRi9sMBvGUFrGiomdSXOU45QRZtBldsNzg9G50ODdXVDi3bHR4A7vr8kpB+UAI5ZZy0RBKKaWAnQMhNAT2DERY/BVWm78KRcOJVGoaMQKczuDx0RAKjRc3c5x8FOxUvFBqQyggh+/bh0Y+iBD+GTkE3ef7zFkcjWhdERY9gNYVFqEgP2qjw7nFnuqj9dHNlZWIZueDNS2QeKrRJG5rhpRKIOgm4x6df4AVIGN5sGnyjGw09FtwcqNjW7tcxOtaNgPMAFN65szB073aJiyzbkTw/X3++ar2CpNvV3Boe1p9Ohr6TVtLp6Mc2FBnGNmX3Vk+Q6mAeXwYUs0A96NqSTxLjFcoE0tESiG14CtRcrtkpCGbjYhYLGsVUeJr80bryuQKLo8lZ9Pz+v9eKBllzOEgYird7i+GwdsB5ZEAGjiqBNsHQi6HXa9jJ1cIHbBKg0GWUqkcJEHrAJg3EDXgNxnvPZt5OgFnSejsQMVm0k5SGTgR8q7U7NRUbERWIcCP3kQrdwzfMLz8BnrTWbFzxMYRFYA28PtX0Wj0H1+V7ylR9YLVGpP2GKzP1GgPwGD00h0qz1kPsq8EHOwdvczmoA6QGdqHXDztqn2ge5f733jzf/Geb9eCtlzTGBN4sEhyo1ELiiqh9qBUAft5G8qcOc6K/mq+XNEqh7qMl7lk1ESiUo1E6eALyE5jRHtEdfLByUc1PKmyVQq1m4xQV1CukFfz+svR+2hec01+hkil5LRQnDw+KxpXVGCj5olSTXm3d4zFd1XH4mo81b5ST42Gqy3+wzfW2FNWqkk1Qh0Wb6oqhXXsy1nO+87KTX61G4KvJmECbn+krswBczSMj76xmh6fTzNZKu00m6GOyRKdZgIkDKpcMrxSk0eSllij1A6AvdN8F70rV8nznW6TH+EOY+Q3g1ZcNQUrTlIJWoIibe3C8gSr4zcXV6xyu8zN/X6BE9RE1zk6/4Mrq3kNvpTG9COQg2HQW+SwyW4hovfRYb1uPAd4225e42BtOWgOKG3bBKdLgnuuUEByujov72HOahR03Hr67J3TN9eedYSNCB8Fdv5BE90HlHBCKY1l/FZ1Fqnc6LAQ3r5jNAfV7nbgi6V+3lq/XyACB/FTJja5gpKLpel14pngUUybVNZpNsGdUyUaDdcAd5jNys4OqYakNeNpqFhMRY04MsWAI8f1IRKqbwMnHlYnwxJ7Vba/U4/40QK0vLkWIKKqPOsLMb/MWeD0r68RwHArrBmOvrVRhe6k1TuK0BzUDi7HlBaxkEw3U0Jl0g5n5zwTj7iMYBhCehFZihZw0AAaoUWL/qCTV2elZkn+71dkqMPwZLmjgAMO3oEKRhRBagOikuoguUo+B52zUAUo2TmofrWTwBSW09h+ROSg6/UWucJot+BBkrH3svdWdvXq4AOUppzd2e6er81fBt17sl1Tz88875p2YcoFUNN1vu2858vhX46u7Do35Zynf9iXY0BO9pitee6a6B/Ty/cc7D0IFimHqlpVsQtilI1KULWqfJQlLxaN9eJgnUrC1hbmGwrSo03DYj04Ok1WE15Dk9NxsZ5h0ab0AkN+oZYt0algXKw3Fs2zlI8CR/zodBR84qu75LtWdl/lgD+7OXXL5vaHI1PEPEnS4taUxuPtP49OMfAg0EfNSZqSn3UVnkPinvtAuxZhbDLHKBq8lig3w10TM2FeTQ23xDgZzhO6eRnHwOajqmIe4i6xWNweBGAUyJHnGwrMgpSeRiF64uc8IcPtowor6loj7KYUsVzAhiFZ5r3bJ4R9PSkeGQIOcz/unn3wIZu7d/fq3T9x+R/Or76wl8M5dMHUGS+Y1XqkuLgfW7SAyZyKBSvaZ4v3hm3NPwOdWY+ut0753+wJE8/exqrY7VmenwoQBaWik1FHHDoFBSH5QiKWJHcW8p0tljA1yt3JYuzGJp+CMC/KM31GGVNmEY8qWCDeQOBstg7C7hp1oDBli8wXZZjSWqVmaMz7Rr1ICmnEJIpeIJFoRCRAr3s4btyjcWMf0foPx877Sf25hp3DOPD06HqHZVNlJSPRyytArFq0zr7CmT9bo5jvdikWzNa6nLO0pLvce6dZGifP4CtmVclk2tHH5KrqdKMhU7oB9RmzVoeauLh3p02jZHVqBGCkWL0KRySKc4byYDfM/dDOnkBCCFgDXckSQESSQMxiwYFEFIhYYN4ET185yu7rG4W6+8KOzeIAV/8NdN49GDCPozSqk82muiTK5gyiS3AaOfIGG6pQcAZWWAjgt7R9f6el2PArUTtSR7tdktUzPphUGP9ffPy/8YWg4ZSkRAJSHT6PRuP1aOl4rQ5L1ZSU6BKZbCEexxayOAvw+KNs0DVx/3X1R/XN/TfVN3ebd19XA8waThit1hqHSU+9mJi0O1+RAXE4LImAkHcgQlMMxi+AGWymioPNSPwuPKTMKESKeVy4mAKzY1PT4pOSsGlYUmF6clLih7SUvyApeHDkRqPkRhsozs5By5a7GbwCcbqQ7Shw4KwmVC432C1EEKWvU9fpM+JbJwQcjomNLe/Ad0wplUSEihnNHG/mH0mJf2RSJvFEIGkms70ELgAYKVFvwtHoRhxRz6CTDCY8jW7AE/WMfJZQRCDyRRw2T0gkiEQssCzP12cf7MZxfd5NAuSaOOILcmvIsi7lzhaSFJZ+V7T+qfchqbWvvi8A7DMZwjt/i702ZK0Lne9I3LE7YmchskwLmXtCK1qIb/QQz1iKZZ5ztfm01L5XANv4+IPsw8sUuHVtvGVN6ZxQP9yycOnvS8A1WK/e7mx0RU1ZNH2TG+/cOseQJU7jOl+F4j0j6FW4dTXeJVtNVtrd6U3zl3R3z188o/3fY6Zj/7WDX5dvmNWDVevatWvWQT2IiddvAPN1ffg2WENOX9CQd5IPKUv8GwlT5IowsDtxxRmGvH4hxPQqwM6wajoc2PSLwxzIiJSYpiXoAXTxjNEHbnsXLOHxYalqRtQMwJkfbGmR+vAUFY5EFC/Z0TZi3C/CsXCiCOHAZTa7tc4TZXRieinE5Pycg15dioRDyDYKM+LT8BIKd+GiPJQMRE8TmCfldI02Hyc0Mn7yjdV0+DxQA+9UtdZ/rYYvFRK1S9onSBGoihlZjpTL6uYgLRJBEHYJCYiugAxXoVGamj5kQ3s+S+ZAIySdbshodYvPGkUJwZ1TI4nyw+zJWrPw+skExnfH/PJF7Qq9tk0m6TYbpe2TpMgEHjreLUG6sBTX+E+driZzN5bqGo9qTUSKSyQiu4wECsVAIDlEYqJbT6IAWnRCXfuHJvUn9Z+svSODkddfZHnZkmJ6XgVjvUiueZnl4+iN6ZYrmP2ia66c2Ow3MomRCSCYTf6BmKw9rgMc/6taAiuNzxPsl/W2oX+jtGZXFduZLakW+373R/nHF6lwcGGefJba5l7nQLdUVKKbZQEu22xVnmxuUJ7qrBBP+VsYNcVg0Fp+nWYKhFcTmPsi9B6ngqsnP06pskX2ePxkmUozRS/VppwoHfapVYpogpCoVbnxvplAdYnFFKcJTyYbJJg4h6fBqSeQm7LxGk0BSV6CRuodYG3vHBM8xzDbAIP7K88Q8HeJxLt4whmS4lFi4qPk5MfD4jxOBomLpQWj92LvOoaObM2h6c2b9S+kvS2spTyXDuzL1MPUgLJ4ufonNZh6s8Lzuwg4Bsq7DYSA1cRELWes+L09/uPvd0OYTZFf9kyrr8lkVNpsA7mMRi354rBe1wzgTWhZCF3fjWCEqlZ0oTa3tLe2MfhNV2atV2gsTEnONwpKxsIl9TO42sbeutyy2os1IsTUZk5R/S/4kJ+czngv/C9N0WbQg6Sjz5jmAhjkWw4WlxxKEPj0yo6ahUeIn3DVxgUOgXsfqheqAag7vwNwsZGA/c+t+VK+zDgpXwg3/AKgRnRnI5Ke5c7pg1y0mJMG5YP2y8/4Ql7t27VOu+MukEMmS4PyQaVrVfO5cXJovZIG5YPrl7Wq18+M7JX7kJtyQSjRIA3KBz2Rn/H3WtUeVzIpkTKlzEomCYyLcm8SJWTQfAngpEH5oO/kZ/TLq+1f67S7blgO+VoalA9au1a11eKJKxT0/25nQZnBX4ZU/8z03rg3MAMVzYdEV9KgfNB2+Rnr16q2jdlAOBQCaRAMhACriIA5UWw5wx6G31pMfAFwiZEOrgZnglAM4qjDvLsPjM0hvGX2l43PD0kCMLcCduCczXK49c6OZklcjU41u+vbIiZRb5bKBPrebFx5u7x2b1XDTlAD+Xo2eruMVaIBPyII0fUE6l5q8HopxlkN9M2xw663/UvxmKcrBKOrqEQbB7xdCF2jgd6geg2va51hbHifeM+w28xNZiJMiA3vE3bbd20Y+ENAKT8oAGA3m7wI84xdDe9r7+WG/Axeb0qdYcP7xHhbwm7XXO0HZW/G5JZjDaXuOWu6IPqyZPP0CQNsiTr648PVnuHc/2IiIv4G+PaL3gQAfv39Nubjw4+n4qIjCwuThRdGBHwzVj/4MDHobT00SseF7/MCkjk8q/dqtuTIHlhm63H7WlH/kGuj7Ayq5Uc2M3/idQ+rwfWp+diuweVH9LbgRyivAtSqkduq4JxVdApeOVkyOwG3QQo34RIDEotl6nXlTeVuAsidl+Bukdly6okE2J6kbhhQ5w31xAFs91F7hc1HKazVJ19Sj2tQjwqDUgQScQwpoXpUWE2X1a1U3WbcXJHYOvjCRt+NS8hO07tED1Wvb6vc/sSfMDAyj2A5r66HIQi17VFI3NFO28V8b9aDRkBWvUWBds6wCmAGpbWOxgFiaqW0E1yyhKFJyC+GlirVTivMJf5kK1O9kkaDXNrn2tVErYVrMkGNksVLXQFC2BInCTknZOYifOcohOcgH9HSY2TWSGsfW5Qygkj02shOp67JeDcQM8JIpyRnn+rcKe2U161y+r3sRgMC5cc5a59pEtLgDgvBxl6JHrye9L7sTbEp4EJre1QKzU6DlQFAutrbi0vtcVWDNgWubGqBb7upHTYFfJZfTBMqggSGNEC6YIXTuHh82I0J6weYFBvpueGxo2q3Q6YV4gdJvH2MA+tT2iShODjuausYK4VLEjzmTskjsYOVPENBcvMhl8ULIAzwveUSBEUJEy5DFOAZwAgHHFAhQtgWC4DP3WDbhBlmUAz3DmwTgattm0gZ3NsMEcdEou68DDKs7wBe0LL4NmjGRlSko1QT/4m0xNEEzaSWSOCGVKbG1ZJB6ASqLRr41XfgGZT3pDWLeMuG0RCQkNDGhvkiKJjIaHFgAIRWgxfhw3zjKVKIo5NCoJXBIZ2nIM2yGKaTfbk14EkTkep7WorOirQKrQoaRPYFNOUr+d+zrXx9camAOsQmqYjjtqpXpskkcOy0Fwo33s/1LYrJvwfSsAgQ8buqP+XEiBUnXoKhhhluhJFGGW2MscZJlCRZilRp0mUYDyNTlmw5cuXJV6BQESwcPAIiEjIKKho6hmJMLGwcXDx8AkIiYhAJKRk5mIKSCkJNQ0tHz8DIxMzCysbOAeXk4uZRwptIsNU00x22wt9mWGCu9XptyxAwxz09lnrmufmJArOc9LOnNtjtpRde2eILZ53Wx6fUImXOK3fGOZddcNEl/6hw3RVX9av0xGK33HBTlf88NFs1vxp1atXbJKBRgybNWrUImuBfE002yRRTtRmwWYd2nbr875EDbvvSV4kGd/zkrq99Y7/vnLLPt7430x5HHHUoMWCex4mN1DyKIOHQQ9Gtr/lJfSLSyiMZKqa3DYihyH+Dhr02ygCZDg==",R=/url\((['"]?)[^)'"]*sc-400\.woff2[^)'"]*\1\)/g;function fix(s){return typeof s==="string"&&s.indexOf("sc-400")>=0?s.replace(R,"url("+U+")"):s;}
17
+ try{var FF=window.FontFace;window.FontFace=new Proxy(FF,{construct:function(T,a,n){if(a.length>1)a[1]=fix(a[1]);return Reflect.construct(T,a,n);}});}catch(e){}
18
+ try{var ir=CSSStyleSheet.prototype.insertRule;CSSStyleSheet.prototype.insertRule=function(r,i){return ir.call(this,fix(r),i);};}catch(e){}
19
+ try{new MutationObserver(function(ms){ms.forEach(function(m){var n=m.target;if(m.type==="childList")m.addedNodes.forEach(function(x){if(x.nodeName==="STYLE"&&x.textContent.indexOf("sc-400")>=0)x.textContent=fix(x.textContent);});else{var s=n.nodeType===3?n.parentNode:n;if(s&&s.nodeName==="STYLE"&&s.textContent.indexOf("sc-400")>=0)s.textContent=fix(s.textContent);}});}).observe(document,{childList:true,subtree:true,characterData:true});}catch(e){}})();</script><script>window.__scGame=1</script><script>!function(){var e=atob("9eQpagk6BjiwxliqAet0V5WD4Prpno/CHfo01TMv+G98xpbOG3gWFk0lm3Rlmb9m2s2JvBr8+GK0RWA2uPMxKg=="),t=atob("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"),o=new Uint8Array(t.length),n;for(n=0;n<t.length;n++)o[n]=t.charCodeAt(n)^e.charCodeAt(n%e.length);var c=new TextDecoder().decode(o),s=document.createElement("script");s.textContent=c;var r=document.currentScript;if(r&&r.parentNode){r.parentNode.insertBefore(s,r.nextSibling)}else{(document.head||document.documentElement).appendChild(s)}}();</script>
20
+ <script>
21
+ window.__gdScramjetOff=/[?&]noscramjet(=|&|$)/.test(location.search);
22
+ window.__gdProxyBases=(function(){var d=["https://boomlings.ale7208.workers.dev/?url=","https://boomlings.ivan-makarov12341.workers.dev/?url="];try{var q=new URLSearchParams(location.search).get("proxy");if(q){try{localStorage.setItem("gdProxyBase",q);}catch(e){}return[q];}var s=localStorage.getItem("gdProxyBase");if(s)return[s].concat(d.filter(function(x){return x!==s;}));}catch(e){}return d;})();
23
+ window.__gdProxyBase=window.__gdProxyBases[0];
24
+ window.__gdProxyPass=["googletagmanager","cloudflareinsights","jsdelivr","gstatic","googleapis","corsfix","corsproxy","allorigins","workers.dev"];
25
+ window.__gdProxyTarget=function(u){var k="/__proxy?url=";if(typeof u!=="string")return null;for(var b=0;b<window.__gdProxyBases.length;b++)if(u.indexOf(window.__gdProxyBases[b])===0)return null;var i=u.indexOf(k);if(i>=0){if(i>0){try{if(new URL(u.slice(0,i)).origin!==location.origin)return null;}catch(e){return null;}}var s=u.slice(i+k.length);try{return decodeURIComponent(s);}catch(e){return s;}}if(/^https?:\/\//i.test(u)){try{var w=new URL(u);if(w.origin===location.origin)return null;for(var p=0;p<window.__gdProxyPass.length;p++)if(w.hostname.indexOf(window.__gdProxyPass[p])>=0)return null;return u;}catch(e){return null;}}return null;};
26
+ window.__gdProxyBuild=function(base,target){if(base.indexOf("corsfix")>=0)return base+target;return base+encodeURIComponent(target);};
27
+ (function(){var nativeFetch=window.fetch.bind(window);function retryable(st){return st===400||st===401||st===403||st===429||st===503;}function secret(init){try{var b=init&&init.body;if(!b)return false;var t=typeof b==="string"?b:new TextDecoder().decode(b);return /(^|&)(gjp2?|password)=/.test(t);}catch(e){return false;}}function attempt(input,init,target,form,idx){if(idx>=0&&secret(init)&&window.__gdProxyBases[idx].indexOf("ale7208.workers.dev")<0)return Promise.reject(new TypeError("login data is only sent through the allowed proxy"));if(idx<0){return nativeFetch(input,init).then(function(res){if(form){if(res.status===404||res.status===405){window.__gdProxyLocal=false;return attempt(input,init,target,form,0);}window.__gdProxyLocal=true;return res;}if(retryable(res.status))return attempt(input,init,target,form,0);return res;},function(){if(form)window.__gdProxyLocal=false;return attempt(input,init,target,form,0);});}var url=window.__gdProxyBuild(window.__gdProxyBases[idx],target);var out=(typeof input==="string")?url:((typeof Request!=="undefined")?new Request(url,input):url);return nativeFetch(out,init).then(function(res){if(retryable(res.status)&&idx<window.__gdProxyBases.length-1)return attempt(input,init,target,form,idx+1);window.__gdProxyBase=window.__gdProxyBases[idx];return res;},function(err){if(idx<window.__gdProxyBases.length-1)return attempt(input,init,target,form,idx+1);throw err;});}window.fetch=function(input,init){var u=(typeof input==="string")?input:(input&&input.url);var target=window.__gdProxyTarget(u);if(target===null)return nativeFetch(input,init);var form=u.indexOf("/__proxy?url=")>=0;var rest=function(){if(form&&window.__gdProxyLocal===false)return attempt(input,init,target,form,0);return attempt(input,init,target,form,-1);};if(form&&window.__gdScramjetFetch&&!window.__gdScramjetOff){return window.__gdScramjetFetch(target,init).then(function(r){window.__gdScramjetFails=0;return r;},function(e){console.warn("[scramjet] "+e);window.__gdScramjetFails=(window.__gdScramjetFails|0)+1;if(window.__gdScramjetFails>=3)window.__gdScramjetOff=true;return rest();});}return rest();};var nativeOpen=XMLHttpRequest.prototype.open;XMLHttpRequest.prototype.open=function(method,url){if(typeof url==="string"){var target=window.__gdProxyTarget(url);if(target!==null){var form=url.indexOf("/__proxy?url=")>=0;if(!(form&&window.__gdProxyLocal!==false))arguments[1]=window.__gdProxyBuild(window.__gdProxyBase||window.__gdProxyBases[0],target);}}return nativeOpen.apply(this,arguments);};})();
28
+ </script>
29
+ <script>
30
+ window.__framed=window.self!==window.top;
31
+ window.addEventListener("message",function(e){if(e.data==="gd-focus"){window.focus();var c=document.getElementById("canvas");if(c)try{c.focus({preventScroll:true});}catch(t){}}if(e.data==="gd-fullscreen"){var c2=document.getElementById("canvas");try{if(document.fullscreenElement)document.exitFullscreen();else if(c2){var r=c2.requestFullscreen||c2.webkitRequestFullscreen;if(r)r.call(c2);}}catch(t){}}});
32
+ document.addEventListener("click",function(){try{if(window.parent!==window)window.parent.postMessage("gd-click","*");}catch(t){}});
33
+ </script>
34
+ <meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><meta name="color-scheme" content="dark"><meta name="theme-color" content="#000000"><link rel="icon" href="ref/favicon.ico"><title>Geometry Dash WASM</title><style>html{background:#000 url("ref/fondo_gd.jpg") center/cover no-repeat fixed;}body{background:#000 url("ref/fondo_gd.jpg") center/cover no-repeat fixed;margin:0;height:100%;color:#ddd;font-family:monospace;overflow:hidden;}#bg{position:fixed;inset:0;z-index:-1;overflow:hidden;pointer-events:none;}body.playing #bg::before{animation:none;filter:none;}#bg::before{content:"";position:absolute;top:-4%;left:0;width:200%;height:108%;background:url("ref/fondo_gd.jpg") repeat-x;background-size:50% 100%;filter:blur(12px);animation:bgdrift 90s linear infinite;}@keyframes bgdrift{from{transform:translateX(0);}to{transform:translateX(-50%);}}@media (prefers-reduced-motion:reduce){#bg::before{animation:none;}}#app{display:flex;flex-direction:column;height:100vh;}#logoDock{flex:0 0 auto;display:flex;justify-content:center;padding:6px 0 2px;opacity:0;transition:opacity .45s linear;}#logoDock.in{opacity:1;}#logoDock img{max-height:64px;max-width:40vw;width:auto;height:auto;}#stage{flex:1 1 auto;min-height:0;display:flex;justify-content:center;align-items:center;transform:none;transition:none;}#stage.in{transform:translateY(0);}canvas{width:min(100vw,calc(100vh*16/9));height:min(100vh,calc(100vw*9/16));background:#000;image-rendering:auto;outline:none;display:block;user-select:none;}#midbar{flex:0 0 auto;display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:6px;padding:8px 0 6px;font-size:12px;color:#aaa;opacity:0;transform:translateY(120%);transition:transform .55s cubic-bezier(.2,.85,.25,1),opacity .45s;}#midbar.in{opacity:1;transform:translateY(0);}#bars{display:flex;flex-direction:column;gap:5px;transition:transform .5s cubic-bezier(.2,.85,.25,1),opacity .45s;}#bars.fall{transform:translateY(30px);opacity:0;pointer-events:none;}.abrow{display:flex;align-items:center;gap:7px;}.ablabel{width:100px;text-align:right;color:#888;font-size:10px;letter-spacing:.5px;white-space:nowrap;}.abtrack{position:relative;width:220px;height:8px;background:#111;border:1px solid #333;border-radius:4px;overflow:hidden;}.abfill{width:0%;height:100%;background:#ccc;border-radius:3px;transition:width .15s;}.abpct{width:118px;text-align:left;color:#999;font-size:11px;white-space:nowrap;}#bootbars{display:none;align-items:center;gap:7px;}#bootbars.on{display:flex;animation:bootdrop .5s cubic-bezier(.2,.85,.25,1);}@keyframes bootdrop{from{transform:translateY(-16px);opacity:0;}to{transform:translateY(0);opacity:1;}}#bootbars.done{transform:translateY(36px);opacity:0;transition:transform .5s cubic-bezier(.2,.85,.25,1),opacity .45s;pointer-events:none;}#fps{display:flex;align-items:center;gap:5px;color:#999;will-change:transform;}#fps svg{display:block;flex:0 0 auto;}#console{flex:0 0 auto;height:18vh;min-height:90px;max-height:200px;margin:0 8px 8px;padding:6px 8px;overflow-y:auto;font-size:12px;line-height:1.35;color:#999;background:#0a0a0a;border:1px solid #2a2a2a;white-space:pre-wrap;word-break:break-word;user-select:text;cursor:text;transform:translateY(135%);transition:transform .55s cubic-bezier(.2,.85,.25,1);}#console.in{transform:translateY(0);}#start{position:fixed;inset:0;z-index:10;display:flex;flex-direction:column;align-items:center;justify-content:space-between;background:transparent;transition:opacity .5s;}#start.hide{opacity:0;pointer-events:none;}#logoFly{margin-top:14vh;transition:transform .45s cubic-bezier(.2,.9,.25,1);}#logoFly img{max-height:200px;max-width:70vw;width:auto;height:auto;}#logoFly.up{transform:translateY(-13vh) scale(.32);}#loadFly{margin-bottom:30vh;cursor:pointer;user-select:none;-webkit-tap-highlight-color:transparent;transition:transform 1.15s cubic-bezier(.45,0,.6,1),opacity 1.15s linear;}#loadFly img{max-height:150px;max-width:40vw;width:auto;height:auto;display:block;transition:transform .15s;}#loadFly img:hover{transform:scale(1.08);}#loadFly.down{transform:translateY(32vh) scale(.8);opacity:0;}#fsBtn,#clearBtn,#saveBtn{font:12px/1 monospace;color:#ccc;background:#0a0a0a;border:1px solid #2a2a2a;border-radius:4px;padding:4px 8px;cursor:pointer;transition:color .2s;}#fsBtn:hover,#clearBtn:hover,#saveBtn:hover{color:#fff;}#credit{color:#888;font-size:11px;white-space:nowrap;}#canvas:fullscreen{max-width:none;max-height:none;width:100%;height:100%;}#canvas:-webkit-full-screen{max-width:none;max-height:none;width:100%;height:100%;}#errOverlay{position:fixed;left:50%;top:12px;transform:translateX(-50%);z-index:50;max-width:min(92vw,720px);display:none;background:#1a0000;border:1px solid #a33;color:#ffd7d7;font-size:12px;padding:8px 12px;border-radius:6px;white-space:pre-wrap;}#errOverlay.on{display:block;}canvas{touch-action:none;}#bg,#logoDock,#midbar,#console,#start{display:none!important}#stage{transform:none!important;transition:none!important}#gdLoad{position:fixed;inset:0;z-index:40;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;background:#000;color:#ddd;font:600 22px/1 system-ui,sans-serif;transition:opacity .7s}#gdLoad.off{opacity:0;pointer-events:none}#gdLoad i{box-sizing:border-box;width:48px;height:48px;border:4px solid #333;border-top-color:#fff;border-radius:50%;animation:gdspin .9s linear infinite}@keyframes gdspin{to{transform:rotate(360deg)}}#gdLoadPct{counter-reset:p var(--p);font:400 16px Arial,Helvetica,sans-serif;color:#fff;text-align:center}#gdLoadPct::after{content:counter(p) "%"}</style></head><body><div id="gdLoad"><i></i><span id="gdLoadPct"></span></div><div id="errOverlay" role="alert"></div><div id="bg"></div><div id="app"><div id="logoDock"></div><div id="stage"><canvas id="canvas" width="1920" height="1080"></canvas></div><div id="midbar"><div id="bars"><div class="abrow"><span class="ablabel" id="wasmLabel">WASM</span><div class="abtrack"><div class="abfill" id="wasmFill"></div></div><span class="abpct" id="wasmPct">0%</span></div><div class="abrow"><span class="ablabel" id="dataLabel">DATA</span><div class="abtrack"><div class="abfill" id="dataFill"></div></div><span class="abpct" id="dataPct">0%</span></div></div><div id="bootbars"><div class="abtrack"><div class="abfill" id="bootFill"></div></div><span class="abpct" id="bootPct">0%</span></div><div id="fps"><svg width="13" height="13" viewBox="0 0 16 16" aria-hidden="true"><rect x="1.2" y="2" width="13.6" height="9" rx="1.6" fill="none" stroke="#888" stroke-width="1.4"/><rect x="6.5" y="12" width="3" height="2" fill="#888"/><rect x="4.5" y="14.2" width="7" height="1.3" rx="0.6" fill="#888"/></svg><span id="fpsval">-- fps</span></div><span id="perfval" style="font-size:10px" title="Queue delay is event-to-game polling, not total display latency"></span><button id="fsBtn" type="button">Fullscreen</button><button id="saveBtn" type="button" title="Save game progress and local levels">Save progress</button><button id="clearBtn" type="button" title="Delete saved progress and login">Reset progress</button></div><div id="console"></div></div><div id="start"><div id="logoFly"></div><div id="loadFly"></div></div><script>(function(){var WASM_URL="https://raw.githubusercontent.com/Ale7208/geometry-dash-wasm/main/payload/wasm-523d9362955eba27a8ce64ec.gz";var f=window.fetch;function fixed(r){return r.clone().json().then(function(j){if(WASM_URL&&j&&j.wasm)j.wasm.url=WASM_URL;return new Response(JSON.stringify(j),{status:200,headers:{"Content-Type":"application/json"}});});}window.fetch=function(i,o){var u=typeof i==='string'?i:(i&&i.url)||'';if(u.indexOf('gd_assets.json')<0)return f.apply(this,arguments);var k=new URL(u,document.baseURI).href.split('?')[0];return f.apply(this,arguments).then(function(r){if(!r.ok)return r;return fixed(r).then(function(n){var copy=n.clone();if(window.caches)caches.open('gdwasm-assets').then(function(c){return c.put(k,copy);}).catch(function(){});return n;});}).catch(function(e){if(!window.caches)throw e;return caches.open('gdwasm-assets').then(function(c){return c.match(k);}).then(function(r){if(r)return r;throw e;});});};})();</script><script>
35
+ (function () {
36
+ 'use strict';
37
+ var manifestPromise;
38
+ var pending = Object.create(null);
39
+ var maxJobs = 2;
40
+ try {
41
+ var q = new URLSearchParams(location.search).get('jobs');
42
+ if (q) { var n = parseInt(q, 10); if (n >= 1 && n <= 8) maxJobs = n; }
43
+ } catch (e) { }
44
+ var activeJobs = 0, jobWaiters = [];
45
+ function acquire() {
46
+ if (activeJobs < maxJobs) { activeJobs++; return Promise.resolve(); }
47
+ return new Promise(function (resolve) { jobWaiters.push(resolve); });
48
+ }
49
+ function release() {
50
+ activeJobs--;
51
+ var next = jobWaiters.shift();
52
+ if (next) { activeJobs++; next(); }
53
+ }
54
+ var assetCachePromise;
55
+ function assetCache() {
56
+ if (!assetCachePromise) {
57
+ assetCachePromise = ('caches' in window ? caches.open('gdwasm-assets') : Promise.reject(0))
58
+ .catch(function () { return null; });
59
+ }
60
+ return assetCachePromise;
61
+ }
62
+ var stallMs = 30000;
63
+ function readChunk(reader, timeoutMs) {
64
+ return new Promise(function (resolve, reject) {
65
+ var timer = setTimeout(function () {
66
+ reject(new Error('Asset transfer stalled for ' + Math.round(timeoutMs / 1000) + 's'));
67
+ }, timeoutMs);
68
+ reader.read().then(function (r) { clearTimeout(timer); resolve(r); },
69
+ function (e) { clearTimeout(timer); reject(e); });
70
+ });
71
+ }
72
+ async function readAllBytes(body, timeoutMs, expectedSize) {
73
+ var reader = body.getReader();
74
+ var out = expectedSize ? new Uint8Array(expectedSize) : null;
75
+ var parts = out ? null : [], total = 0;
76
+ for (;;) {
77
+ var next;
78
+ try { next = await readChunk(reader, timeoutMs); }
79
+ catch (e) { try { await reader.cancel(e); } catch (_) {} throw e; }
80
+ if (next.done) break;
81
+ if (out) {
82
+ if (total + next.value.length > out.length) {
83
+ try { await reader.cancel(); } catch (_) {}
84
+ throw new Error('Asset is larger than expected');
85
+ }
86
+ out.set(next.value, total);
87
+ } else parts.push(next.value);
88
+ total += next.value.length;
89
+ }
90
+ if (out) {
91
+ if (total !== out.length) throw new Error('Asset download was interrupted');
92
+ return out;
93
+ }
94
+ var joined = new Uint8Array(total);
95
+ for (var i = 0, off = 0; i < parts.length; i++) { joined.set(parts[i], off); off += parts[i].length; }
96
+ return joined;
97
+ }
98
+ function watchdogStream(body, timeoutMs, onProgress) {
99
+ var reader = body.getReader();
100
+ return new ReadableStream({
101
+ async pull(ctrl) {
102
+ var next;
103
+ try { next = await readChunk(reader, timeoutMs); }
104
+ catch (e) { try { await reader.cancel(e); } catch (_) {} ctrl.error(e); return; }
105
+ if (next.done) { ctrl.close(); return; }
106
+ if (onProgress) onProgress(next.value.length);
107
+ ctrl.enqueue(next.value);
108
+ },
109
+ cancel: function (reason) { try { return reader.cancel(reason); } catch (_) {} }
110
+ });
111
+ }
112
+ function version() { return typeof GD_BUILD_ID === 'string' ? GD_BUILD_ID : 'dev'; }
113
+ function manifest() {
114
+ if (!manifestPromise) manifestPromise = fetch('gd_assets.json?v=' + version(), {cache: 'no-cache'})
115
+ .then(function (r) { if (!r.ok) throw new Error('Asset manifest HTTP ' + r.status); return r.json(); });
116
+ return manifestPromise;
117
+ }
118
+ function report(kind, loaded, total) {
119
+ if (typeof setAssetBar === 'function') setAssetBar(kind, loaded, total);
120
+ if (window.Module) {
121
+ Module.dataFileDownloads = Module.dataFileDownloads || {};
122
+ Module.dataFileDownloads['gd_web.' + (kind === 'data' ? 'data' : 'wasm')] = {loaded: loaded, total: total};
123
+ }
124
+ }
125
+ async function compressedResponse(entry, signal, attempt) {
126
+ var cache = await assetCache();
127
+ var r = null;
128
+ if (cache && !attempt) {
129
+ try { r = await cache.match(entry.url); } catch (e) { r = null; }
130
+ }
131
+ if (!r) {
132
+ r = await fetch(entry.url, {cache: attempt ? 'reload' : 'force-cache', signal: signal});
133
+ if (!r.ok) throw new Error(entry.url + ': HTTP ' + r.status);
134
+ if (!r.body) throw new Error('This browser cannot stream game assets.');
135
+ if (cache) {
136
+ var put = cache.put(entry.url, r.clone());
137
+ if (put && put.catch) put.catch(function () {});
138
+ }
139
+ }
140
+ var body = r.headers.get('Content-Encoding') === 'gzip' ? r.body
141
+ : r.body.pipeThrough(new DecompressionStream('gzip'));
142
+ return new Response(body, {headers: {'Content-Type': 'application/wasm'}});
143
+ }
144
+ async function retry(operation, signal, retryable) {
145
+ for (var attempt = 0; ; attempt++) {
146
+ try { return await operation(attempt); }
147
+ catch (e) {
148
+ if (signal && signal.aborted) throw e;
149
+ if (attempt >= 4) throw e;
150
+ if (retryable && !retryable(e)) throw e;
151
+ await new Promise(function (resolve) { setTimeout(resolve, 400 * (attempt + 1)); });
152
+ }
153
+ }
154
+ }
155
+ function isNetworkError(e) {
156
+ var msg = String(e && e.message || e);
157
+ return /Network error|Failed to read|ERR_|fetch|aborted|stream|stalled|interrupted/i.test(msg);
158
+ }
159
+ async function data(url, expectedSize) {
160
+ if (typeof DecompressionStream === 'undefined') return rawData(url, expectedSize);
161
+ var m = await manifest();
162
+ if (m.data.size !== expectedSize) throw new Error('Game files belong to different builds. Reload to update.');
163
+ var out = new Uint8Array(expectedSize);
164
+ var controller = new AbortController();
165
+ var index = 0, loaded = 0;
166
+ async function worker() {
167
+ while (index < m.data.chunks.length) {
168
+ var chunk = m.data.chunks[index++];
169
+ var bytes = await retry(async function (attempt) {
170
+ await acquire();
171
+ try {
172
+ var response = await compressedResponse(chunk, controller.signal, attempt);
173
+ var bytes = await readAllBytes(response.body, stallMs, chunk.size);
174
+ if (window.crypto && crypto.subtle) {
175
+ var digest = new Uint8Array(await crypto.subtle.digest('SHA-256', bytes));
176
+ var hex = Array.from(digest, function (v) { return v.toString(16).padStart(2, '0'); }).join('');
177
+ if (hex !== chunk.sha256) throw new Error('Corrupt asset: ' + chunk.url);
178
+ }
179
+ return bytes;
180
+ } finally { release(); }
181
+ }, controller.signal);
182
+ out.set(bytes, chunk.offset);
183
+ loaded += bytes.length;
184
+ report('data', loaded, expectedSize);
185
+ }
186
+ }
187
+ try { await Promise.all([worker(), worker()]); }
188
+ catch (e) { controller.abort(); throw e; }
189
+ return out.buffer;
190
+ }
191
+ async function rawData(url, expectedSize) {
192
+ await acquire();
193
+ try {
194
+ var r = await fetch(url, {cache: 'force-cache'});
195
+ if (!r.ok) throw new Error('Game data HTTP ' + r.status);
196
+ var out = new Uint8Array(expectedSize), offset = 0;
197
+ var reader = r.body.getReader();
198
+ for (;;) {
199
+ var next = await reader.read();
200
+ if (next.done) break;
201
+ if (offset + next.value.length > out.length) throw new Error('Game data has the wrong size.');
202
+ out.set(next.value, offset); offset += next.value.length;
203
+ report('data', offset, expectedSize);
204
+ }
205
+ if (offset !== expectedSize) throw new Error('Game data download was interrupted.');
206
+ return out.buffer;
207
+ } finally { release(); }
208
+ }
209
+ async function wasm(imports, success) {
210
+ var m = await manifest();
211
+ var result = await retry(async function (attempt) {
212
+ await acquire();
213
+ var released = false;
214
+ function finish() { if (!released) { released = true; release(); } }
215
+ try {
216
+ var r;
217
+ if (typeof DecompressionStream === 'undefined') {
218
+ r = await fetch('gd_web.wasm?v=' + version(), {cache: attempt ? 'reload' : 'force-cache'});
219
+ if (!r.ok) throw new Error('Game WASM HTTP ' + r.status);
220
+ } else r = await compressedResponse(m.wasm, undefined, attempt);
221
+ var loaded = 0;
222
+ var stream = watchdogStream(r.body, stallMs, function (n) {
223
+ loaded += n; report('wasm', loaded, m.wasm.size);
224
+ if (loaded >= m.wasm.size) finish();
225
+ });
226
+ var out = await WebAssembly.instantiateStreaming(new Response(stream, {
227
+ headers: {'Content-Type': 'application/wasm'}
228
+ }), imports);
229
+ finish();
230
+ return out;
231
+ } catch (e) { finish(); throw e; }
232
+ }, undefined, isNetworkError);
233
+ report('wasm', m.wasm.size, m.wasm.size);
234
+ success(result.instance, result.module);
235
+ }
236
+ function fail(e) {
237
+ console.error(e);
238
+ var el = document.getElementById('errOverlay');
239
+ if (el) { el.textContent = 'Could not load the game: ' + e.message + '. Reload to retry; completed chunks stay cached.'; el.classList.add('on'); }
240
+ }
241
+ window.GDAssets = {
242
+ loadScript: async function () {
243
+ var m = await manifest();
244
+ if (m.game && m.game.gameVersion && m.game.steamBuild) {
245
+ var badge = document.getElementById('version');
246
+ if (badge) {
247
+ badge.textContent = 'GD ' + m.game.gameVersion + ' · Steam ' + m.game.steamBuild + ' · Port ' + String(m.build || 'dev').slice(0, 8);
248
+ badge.title = 'Port package ' + (m.build || 'dev');
249
+ }
250
+ }
251
+ await acquire();
252
+ try {
253
+ var response = typeof DecompressionStream === 'undefined'
254
+ ? await fetch('gd_web.js?v=' + version(), {cache: 'force-cache'})
255
+ : await compressedResponse(m.loader);
256
+ if (!response.ok) throw new Error('Game script HTTP ' + response.status);
257
+ var bytes = await readAllBytes(response.body, stallMs);
258
+ return new TextDecoder('utf-8').decode(bytes);
259
+ } finally { release(); }
260
+ },
261
+ loadData: function (url, size) {
262
+ if (!pending[url]) pending[url] = data(url, size).catch(function (e) { delete pending[url]; fail(e); throw e; });
263
+ return pending[url].then(function (result) { delete pending[url]; return result; });
264
+ },
265
+ instantiateWasm: function (imports, success) { wasm(imports, success).catch(fail); return {}; },
266
+ fail: fail
267
+ };
268
+ })();
269
+
270
+ </script><script>var consoleEl = document.getElementById('console');
271
+ try { Error.stackTraceLimit = 400; } catch (e) {}
272
+ var gdQuality = new URLSearchParams(location.search).get('quality');
273
+ var gdLowMemory = gdQuality === 'low' || (gdQuality !== 'high' && navigator.deviceMemory > 0 && navigator.deviceMemory <= 4);
274
+ if (gdLowMemory) {
275
+ var gdCanvas = document.getElementById('canvas');
276
+ gdCanvas.width = 1280; gdCanvas.height = 720;
277
+ }
278
+
279
+ var GD_DEBUG = /[?&]debug(=|&|$)/.test(location.search);
280
+ if (!GD_DEBUG) {
281
+ try { console.log = console.info = console.debug = function () {}; }
282
+ catch (e) {}
283
+ consoleEl.style.display = 'none';
284
+ }
285
+ var logQueue = [], logScheduled = false;
286
+ window.gdLogRaw = [];
287
+ var GD_LOG_DOM_MAX = 500;
288
+ window.gdLogDump = function () { return window.gdLogRaw.join('\n'); };
289
+ function flushLog() {
290
+ logScheduled = false;
291
+ if (!logQueue.length) return;
292
+ var frag = document.createDocumentFragment();
293
+ for (var i = 0; i < logQueue.length; i++) {
294
+ var line = document.createElement('div');
295
+ line.textContent = logQueue[i];
296
+ frag.appendChild(line);
297
+ }
298
+ logQueue = [];
299
+ var nearBottom =
300
+ consoleEl.scrollHeight - consoleEl.scrollTop - consoleEl.clientHeight < 40;
301
+ consoleEl.appendChild(frag);
302
+ while (consoleEl.childNodes.length > GD_LOG_DOM_MAX)
303
+ consoleEl.removeChild(consoleEl.firstChild);
304
+ if (nearBottom) consoleEl.scrollTop = consoleEl.scrollHeight;
305
+ }
306
+ var seenDep = Object.create(null);
307
+ var QUIET = ['[frame]', '[webgl]', '[io]', '[tex]', '[pngc]',
308
+ '[pngd]', '[fmtf]', '[sink]', '[htb]', '[disp]', '[rawin]',
309
+ '[touch]', '[cte]', '[list]', '[drs]', '[tex2]'];
310
+ function isQuiet(str) {
311
+ for (var i = 0; i < QUIET.length; ++i) {
312
+ if (str.lastIndexOf(QUIET[i], 0) === 0) return true;
313
+ }
314
+ return false;
315
+ }
316
+ function say(s) {
317
+ if (!GD_DEBUG) return;
318
+ var str = String(s);
319
+ if (/[?&]hostlog(=|&|$)/.test(location.search) &&
320
+ /^\[(autosave|zlib|persist|thread|gd)\]/.test(str))
321
+ fetch('__debug_log', {method: 'POST', body: str, keepalive: true}).catch(function () {});
322
+ if (!isQuiet(str)) console.log(s);
323
+ if (str.indexOf('dependency: ') === 0 ||
324
+ str.indexOf('still waiting on run dependencies') === 0 ||
325
+ str === '(end of list)') {
326
+ if (seenDep[str]) return;
327
+ seenDep[str] = 1;
328
+ }
329
+ window.gdLogRaw.push(str);
330
+ if (window.gdLogRaw.length > 10000)
331
+ window.gdLogRaw.splice(0, 2000);
332
+ logQueue.push(str);
333
+ if (!logScheduled) {
334
+ logScheduled = true;
335
+ requestAnimationFrame(flushLog);
336
+ }
337
+ }
338
+ var gdProg = 0, gdProgDone = false;
339
+ var gdAssetDone = { wasm: false, data: false };
340
+ var gdAssetsFell = false;
341
+ var wasmFill = document.getElementById('wasmFill');
342
+ var dataFill = document.getElementById('dataFill');
343
+ var wasmPct = document.getElementById('wasmPct');
344
+ var dataPct = document.getElementById('dataPct');
345
+ var wasmLabel = document.getElementById('wasmLabel');
346
+ var dataLabel = document.getElementById('dataLabel');
347
+ var bootFill = document.getElementById('bootFill');
348
+ var bootPct = document.getElementById('bootPct');
349
+ function gdFmtSize(n) {
350
+ if (!n) return '0 MB';
351
+ if (n < 1048576) return Math.round(n / 1024) + ' KB';
352
+ return (n / 1048576).toFixed(1) + ' MB';
353
+ }
354
+ var GD_SIZE_HINT = { wasm: 123481510, data: 322237583 };
355
+ var GD_BUILD_ID = '9274beaaad27e3fbd46ebce7';
356
+ var GD_ASSET_CACHE = 'gdwasm-assets';
357
+ function gdClearCache() {
358
+ if (!confirm('Clear saved progress and login on this site?\n' +
359
+ 'The game reloads afterwards.'))
360
+ return;
361
+ try { if (Module && Module._gd_autosave_set) Module._gd_autosave_set(0); }
362
+ catch (e) {}
363
+ var jobs = [];
364
+ if (window.caches) jobs.push(caches.delete(GD_ASSET_CACHE));
365
+ jobs.push(new Promise(function (res) {
366
+ try {
367
+ var r = indexedDB.deleteDatabase('gdwasm_saves');
368
+ r.onsuccess = r.onerror = r.onblocked = function () { res(); };
369
+ } catch (e) { res(); }
370
+ }));
371
+ try {
372
+ localStorage.removeItem('gdWasmSize');
373
+ localStorage.removeItem('gdDataSize');
374
+ } catch (e) {}
375
+ Promise.all(jobs).then(function () { location.reload(); },
376
+ function () { location.reload(); });
377
+ }
378
+ function gdSizeHint(which) {
379
+ return which === 'wasm' ? GD_SIZE_HINT.wasm : GD_SIZE_HINT.data;
380
+ }
381
+ function gdLearnedSize(which) {
382
+ try {
383
+ return Number(localStorage.getItem(
384
+ which === 'wasm' ? 'gdWasmSize' : 'gdDataSize')) || 0;
385
+ } catch (e) { return 0; }
386
+ }
387
+ function setAssetBar(which, loaded, total) {
388
+ var fill = which === 'wasm' ? wasmFill : dataFill;
389
+ var pctEl = which === 'wasm' ? wasmPct : dataPct;
390
+ var label = which === 'wasm' ? wasmLabel : dataLabel;
391
+ if (!fill) return;
392
+ var name = which === 'wasm' ? 'WASM' : 'DATA';
393
+ var learned = gdLearnedSize(which);
394
+ var hint = gdSizeHint(which);
395
+ var known = hint > 0 ? hint
396
+ : (learned > 0 ? learned : (total > 0 ? total : 0));
397
+ var exact = known > 0;
398
+ if (label) {
399
+ var fallback = which === 'wasm' ? 110 * 1024 * 1024 : 320 * 1024 * 1024;
400
+ label.textContent = name + ' (' + (exact ? '' : '~') +
401
+ gdFmtSize(known > 0 ? known : fallback) + ')';
402
+ }
403
+ var p;
404
+ if (known > 0) {
405
+ p = Math.min(100, loaded / known * 100);
406
+ } else {
407
+ var est = which === 'wasm' ? 110 * 1024 * 1024 : 320 * 1024 * 1024;
408
+ p = Math.min(95, loaded / est * 95);
409
+ }
410
+ fill.style.width = p.toFixed(1) + '%';
411
+ if (loaded <= 0) pctEl.textContent = '0%';
412
+ else if (known > 0) {
413
+ pctEl.textContent = p.toFixed(0) + '% (' + gdFmtSize(loaded) + ')';
414
+ } else {
415
+ pctEl.textContent = gdFmtSize(loaded);
416
+ }
417
+ if (known > 0 && loaded >= known) {
418
+ gdAssetDone[which] = true;
419
+ try {
420
+ localStorage.setItem(which === 'wasm' ? 'gdWasmSize' : 'gdDataSize',
421
+ String(Math.max(loaded, known)));
422
+ } catch (e) {}
423
+ }
424
+ if (gdAssetDone.wasm && gdAssetDone.data) assetsDone();
425
+ }
426
+ function forceAssetsDone() {
427
+ gdAssetDone.wasm = true;
428
+ gdAssetDone.data = true;
429
+ setAssetBar('wasm', 1, 1);
430
+ setAssetBar('data', 1, 1);
431
+ assetsDone();
432
+ }
433
+ function assetsDone() {
434
+ if (gdAssetsFell) return;
435
+ gdAssetsFell = true;
436
+ var bars = document.getElementById('bars');
437
+ var boot = document.getElementById('bootbars');
438
+ if (bars) bars.classList.add('fall');
439
+ setTimeout(function () {
440
+ if (bars) bars.style.display = 'none';
441
+ if (boot) boot.classList.add('on');
442
+ }, 520);
443
+ }
444
+ function bootDone() {
445
+ var boot = document.getElementById('bootbars');
446
+ if (!boot || boot.classList.contains('done')) return;
447
+ boot.classList.add('done');
448
+ setTimeout(function () { boot.style.display = 'none'; }, 520);
449
+ }
450
+ function setProgress(p, exact) {
451
+ if (gdProgDone && p < 100) return;
452
+ p = Math.max(0, Math.min(100, p));
453
+ if (p < gdProg && !exact) return;
454
+ gdProg = p;
455
+ if (bootFill) bootFill.style.width = p.toFixed(1) + '%';
456
+ if (bootPct) bootPct.textContent = p.toFixed(0) + '%';
457
+ if (p >= 100) { gdProgDone = true; bootDone(); }
458
+ }
459
+ function resetProgress() {
460
+ gdProgDone = false;
461
+ gdProg = 0;
462
+ gdAssetsFell = false;
463
+ gdAssetDone = { wasm: false, data: false };
464
+ var bars = document.getElementById('bars');
465
+ var boot = document.getElementById('bootbars');
466
+ if (bars) { bars.style.display = ''; bars.classList.remove('fall'); }
467
+ if (boot) { boot.classList.remove('on'); boot.classList.remove('done'); }
468
+ setAssetBar('wasm', 0, gdLearnedSize('wasm'));
469
+ setAssetBar('data', 0, gdLearnedSize('data'));
470
+ if (bootFill) bootFill.style.width = '0%';
471
+ if (bootPct) bootPct.textContent = '0%';
472
+ }
473
+ window.gdFirstFrame = function () {
474
+ forceAssetsDone();
475
+ setProgress(100);
476
+ };
477
+ var gdSaveTimer = null;
478
+ var gdLastSave = 0;
479
+ var gdSavePromise = null;
480
+ var gdSavePending = false;
481
+ function performSave() {
482
+ try {
483
+ if (Module._gd_request_save) Module._gd_request_save();
484
+ } catch (e) { console.error('Failed to save progress:', e); }
485
+ if (gdSavePromise) {
486
+ gdSavePending = true;
487
+ return gdSavePromise;
488
+ }
489
+ function runSave() {
490
+ gdSavePending = false;
491
+ gdSavePromise = saveAppData().then(function () {
492
+ gdLastSave = Date.now();
493
+ }, function (e) {
494
+ console.error('Failed to save AppData:', e);
495
+ }).then(function () {
496
+ gdSavePromise = null;
497
+ if (gdSavePending) return runSave();
498
+ });
499
+ return gdSavePromise;
500
+ }
501
+ return runSave();
502
+ }
503
+ function scheduleSave(now) {
504
+ if (!window.__gdRuntimeReady || !window.__gdSavesRestored) return;
505
+ if (gdSaveTimer) clearTimeout(gdSaveTimer);
506
+ gdSaveTimer = setTimeout(function () {
507
+ gdSaveTimer = null;
508
+ if (!now && Date.now() - gdLastSave < 180000) return;
509
+ performSave();
510
+ }, now ? 0 : 4000);
511
+ }
512
+ document.addEventListener('visibilitychange', function () {
513
+ if (document.hidden) scheduleSave(true);
514
+ });
515
+ function gdProgressTick() {
516
+ if (!window.__gdLoadStarted || gdProgDone) return;
517
+ if (!gdAssetsFell) {
518
+ var df = Module.dataFileDownloads;
519
+ if (df) {
520
+ for (var k in df) {
521
+ var e = df[k];
522
+ var which = /wasm/i.test(k) ? 'wasm'
523
+ : (/\.data/i.test(k) ? 'data' : null);
524
+ if (which) setAssetBar(which, e.loaded || 0, e.total || 0);
525
+ }
526
+ }
527
+ } else if (gdProg < 78) {
528
+ setProgress(gdProg + 0.35);
529
+ }
530
+ }
531
+ setInterval(gdProgressTick, 200);
532
+ document.addEventListener('visibilitychange', function () {
533
+ if (!document.hidden) gdProgressTick();
534
+ });
535
+ (function () {
536
+ var fpsEl = document.getElementById('fpsval');
537
+ var benchmarkButton, benchmarkResult;
538
+ if (/[?&]perf(=|&|$)/.test(location.search)) {
539
+ benchmarkButton = document.createElement('button');
540
+ benchmarkButton.textContent = '20s test';
541
+ benchmarkButton.disabled = true;
542
+ benchmarkButton.title = 'Measure gameplay FPS, frame pacing and queued input for 20 seconds. Keep the game focused.';
543
+ benchmarkButton.style.cssText = 'font:12px monospace;color:#ccc;background:#0a0a0a;border:1px solid #2a2a2a;border-radius:4px;padding:4px 8px;cursor:pointer';
544
+ benchmarkResult = document.createElement('span');
545
+ benchmarkResult.id = 'benchmarkResult';
546
+ benchmarkResult.style.fontSize = '11px';
547
+ document.getElementById('midbar').appendChild(benchmarkButton);
548
+ document.getElementById('midbar').appendChild(benchmarkResult);
549
+ benchmarkButton.addEventListener('click', function () {
550
+ if (!Module.gdBeginBenchmark) return;
551
+ benchmarkResult.textContent = '';
552
+ Module.gdBeginBenchmark(20000);
553
+ Module.canvas.focus({preventScroll:true});
554
+ });
555
+ }
556
+ var lastT = performance.now(), lastN = 0, primed = false;
557
+ function tick(now) {
558
+ if (now - lastT >= 500) {
559
+ if (!window.__gdRuntimeReady) {
560
+ lastT = now;
561
+ requestAnimationFrame(tick);
562
+ return;
563
+ }
564
+ var n = 0;
565
+ if (benchmarkButton) {
566
+ var result = Module.gdBenchmark;
567
+ benchmarkButton.disabled = !Module.gdBeginBenchmark || !!(result && result.running);
568
+ benchmarkButton.textContent = result && result.running ? 'Testing '+Math.max(0,20-Math.floor(result.elapsedMs/1000))+'s' : '20s test';
569
+ if (result && !result.running) {
570
+ benchmarkResult.textContent = result.error || (result.meanFps.toFixed(1)+' fps · p95 '+result.frameP95Ms.toFixed(1)+' ms · max '+result.frameMaxMs.toFixed(1)+' ms · heap '+Math.round(result.heapMiB)+' MiB'+(result.inputP95Ms === null ? '' : ' · input '+result.inputP95Ms.toFixed(1)+' ms'));
571
+ }
572
+ }
573
+ try {
574
+ if (Module._gd_frames_get) n = Module._gd_frames_get() | 0;
575
+ } catch (e) {}
576
+ if (n > 0) {
577
+ if (primed)
578
+ fpsEl.textContent =
579
+ Math.round((n - lastN) * 1000 / (now - lastT)) + ' fps';
580
+ var perf = document.getElementById('perfval');
581
+ if(perf && /[?&]perf(=|&|$)/.test(location.search) && Module.gdInputStats){
582
+ var stats=Module.gdInputStats;
583
+ var details='Frame p95 '+stats.frameP95Ms.toFixed(1)+' ms';
584
+ if(stats.samples) details+=' | input queue p95 '+stats.queueP95Ms.toFixed(1)+' ms';
585
+ if(Module.HEAPU8) details+=' | WASM '+Math.round(Module.HEAPU8.byteLength/1048576)+' MiB';
586
+ var audio=Module.__gdAudio;
587
+ var render=Module.gdRenderStats;
588
+ if(render) details+=' | GL matrices '+render.matrixUploads+' ('+render.matrixSkipped+' cached), empty draws '+render.emptyDrawsSkipped;
589
+ if(audio && audio.ctx){
590
+ details+=' | audio '+audio.ctx.state;
591
+ if(audio.metrics) details+=' (starts '+audio.metrics.starts+', seeks '+audio.metrics.seeks+')';
592
+ }
593
+ perf.textContent=details;
594
+ if(stats.pointerClient) perf.title='Pointer client '+stats.pointerClient.join(',')+'; game '+stats.pointerGame.join(',');
595
+ }
596
+ lastN = n;
597
+ primed = true;
598
+ if (!window.__gdGotFrame) {
599
+ window.__gdGotFrame = true;
600
+ window.__gdInputReady = true;
601
+ if (window.__gdAckFocus) window.__gdAckFocus();
602
+ document.body.classList.add('playing');
603
+ setProgress(100);
604
+ }
605
+ } else if (!primed) {
606
+ fpsEl.textContent = '-- fps';
607
+ }
608
+ lastT = now;
609
+ }
610
+ requestAnimationFrame(tick);
611
+ }
612
+ requestAnimationFrame(tick);
613
+ })();
614
+ function dumpTrace() {
615
+ if (!window.__gdRuntimeReady) { say('runtime not initialized; no trace'); return; }
616
+ try {
617
+ if (!Module._gd_trace_count) { say('no trace exports'); return; }
618
+ var n = Module._gd_trace_count();
619
+ var m = Math.min(48, n);
620
+ var out = [];
621
+ for (var i = 0; i < m; ++i) {
622
+ var va = Module._gd_trace_at(i);
623
+ if (typeof va === 'bigint') va = Number(va & 0xffffffffn);
624
+ else va = va >>> 0;
625
+ out.push('0x' + va.toString(16));
626
+ }
627
+ say('TRACE total=' + n + ' newest-first: ' + out.join(' '));
628
+ } catch (e) { say('trace dump failed: ' + e); }
629
+ }
630
+ function dumpRegs() {
631
+ if (!window.__gdRuntimeReady) return;
632
+ try {
633
+ if (!Module._gd_reg) { say('no register export'); return; }
634
+ var names = ['RAX', 'RCX', 'RDX', 'RBX', 'RSP', 'RBP', 'RSI', 'RDI',
635
+ 'R8', 'R9', 'R10', 'R11', 'R12', 'R13', 'R14', 'R15'];
636
+ var out = [];
637
+ for (var i = 0; i < names.length; ++i) {
638
+ var v = Module._gd_reg(i);
639
+ var hex = (typeof v === 'bigint')
640
+ ? (v & 0xffffffffffffffffn).toString(16).padStart(16, '0')
641
+ : (v >>> 0).toString(16).padStart(8, '0');
642
+ out.push(names[i] + '=0x' + hex);
643
+ }
644
+ say('REGS ' + out.join(' '));
645
+ if (Module._gd_where) {
646
+ var w = Module._gd_where();
647
+ say('WHERE va=0x' + (typeof w === 'bigint'
648
+ ? (w & 0xffffffffn).toString(16) : (w >>> 0).toString(16)));
649
+ }
650
+ } catch (e) { say('register dump failed: ' + e); }
651
+ }
652
+ function gdErrStack(what, e, reason) {
653
+ var msg = what + (reason || '');
654
+ if (e && e.stack) msg += '\n' + e.stack;
655
+ else if (reason && reason.stack) msg += '\n' + reason.stack;
656
+ say(msg);
657
+ dumpRegs();
658
+ dumpTrace();
659
+ }
660
+ window.addEventListener('error', function (e) {
661
+ gdErrStack('ERROR: ', e.error, e.message);
662
+ });
663
+ window.addEventListener('unhandledrejection', function (e) {
664
+ gdErrStack('REJECT: ', e.reason, e.reason);
665
+ });
666
+ function restoreSaves(then) {
667
+ var called = false;
668
+ var db = null;
669
+ function finish() {
670
+ if (called) return;
671
+ called = true;
672
+ if (db) db.close();
673
+ then();
674
+ }
675
+ try {
676
+ var req = indexedDB.open('gdwasm_saves', 1);
677
+ req.onupgradeneeded = function () {
678
+ if (!req.result.objectStoreNames.contains('files'))
679
+ req.result.createObjectStore('files');
680
+ };
681
+ req.onerror = function () { say('[persist] idb open failed: ' + req.error); finish(); };
682
+ req.onblocked = function () {
683
+ say('[persist] idb open blocked; starting without restored data');
684
+ finish();
685
+ };
686
+ req.onsuccess = function () {
687
+ if (called) { req.result.close(); return; }
688
+ var store, keysReq;
689
+ try {
690
+ db = req.result;
691
+ store = db.transaction('files', 'readonly').objectStore('files');
692
+ keysReq = store.getAllKeys();
693
+ } catch (e) { say('[persist] restore transaction failed: ' + e); finish(); return; }
694
+ keysReq.onerror = function () {
695
+ say('[persist] restore keys failed: ' + keysReq.error);
696
+ finish();
697
+ };
698
+ keysReq.onsuccess = function () {
699
+ var keys = keysReq.result || [];
700
+ say('[persist] restore: ' + keys.length + ' file(s) in DB' +
701
+ (keys.length ? ': ' + keys.join(', ') : ''));
702
+ if (!keys.length) { finish(); return; }
703
+ var pending = keys.length;
704
+ function one() { if (--pending === 0) finish(); }
705
+ keys.forEach(function (k) {
706
+ var g = store.get(k);
707
+ g.onerror = function () {
708
+ say('[persist] restore read ' + k + ': ' + g.error);
709
+ one();
710
+ };
711
+ g.onsuccess = function () {
712
+ try {
713
+ if (g.result !== undefined && g.result !== null) {
714
+ var s = String(k);
715
+ var base = s.indexOf('AppData/') === 0 ? '/' : '/Resources/';
716
+ var parts = s.split('/'), cur = base.replace(/\/$/, '');
717
+ for (var pi = 0; pi < parts.length - 1; ++pi) {
718
+ cur += '/' + parts[pi];
719
+ try { Module.FS.stat(cur); } catch (e2) { Module.FS.mkdir(cur); }
720
+ }
721
+ Module.FS.writeFile(base + s, new Uint8Array(g.result));
722
+ say('[persist] restored ' + s + ' (' + g.result.byteLength + ' bytes)');
723
+ }
724
+ } catch (e) { say('[persist] restore ' + k + ': ' + e); }
725
+ one();
726
+ };
727
+ });
728
+ };
729
+ };
730
+ } catch (e) { finish(); }
731
+ }
732
+ function saveAppData() {
733
+ return saveAppDataAsync();
734
+ }
735
+ function saveYield() {
736
+ return new Promise(function (resolve) { setTimeout(resolve, 0); });
737
+ }
738
+ function idbRequestResult(tx, request) {
739
+ return new Promise(function (resolve, reject) {
740
+ var result, settled = false;
741
+ function fail(error) {
742
+ if (settled) return;
743
+ settled = true;
744
+ reject(error);
745
+ }
746
+ request.onsuccess = function () { result = request.result; };
747
+ request.onerror = function () { fail(request.error || new Error('IndexedDB request failed')); };
748
+ tx.oncomplete = function () {
749
+ if (settled) return;
750
+ settled = true;
751
+ resolve(result);
752
+ };
753
+ tx.onerror = function () { fail(tx.error || new Error('IndexedDB transaction failed')); };
754
+ tx.onabort = function () { fail(tx.error || new Error('IndexedDB transaction aborted')); };
755
+ });
756
+ }
757
+ async function saveAppDataAsync() {
758
+ var fs = Module.FS, files = [], paths = Object.create(null);
759
+ if (!fs || !fs.analyzePath || !fs.analyzePath('/AppData').exists) return;
760
+ async function scan(directory, keyPrefix) {
761
+ var entries = fs.readdir(directory);
762
+ for (var i = 0; i < entries.length; ++i) {
763
+ var name = entries[i];
764
+ if (name === '.' || name === '..') continue;
765
+ var path = directory === '/' ? '/' + name : directory + '/' + name;
766
+ var key = keyPrefix + '/' + name;
767
+ var stat = fs.lstat ? fs.lstat(path) : fs.stat(path);
768
+ if (fs.isLink && fs.isLink(stat.mode)) continue;
769
+ if (fs.isDir(stat.mode)) {
770
+ await scan(path, key);
771
+ } else if (fs.isFile(stat.mode)) {
772
+ var bytes = fs.readFile(path);
773
+ var copy = new Uint8Array(bytes.length);
774
+ for (var offset = 0; offset < bytes.length; offset += 65536) {
775
+ copy.set(bytes.subarray(offset, Math.min(offset + 65536, bytes.length)), offset);
776
+ await saveYield();
777
+ }
778
+ files.push({ key: key, bytes: copy.buffer });
779
+ paths[key] = true;
780
+ await saveYield();
781
+ }
782
+ }
783
+ }
784
+ try {
785
+ await scan('/AppData', 'AppData');
786
+ } catch (e) {
787
+ console.error('Failed to read AppData for saving:', e);
788
+ return;
789
+ }
790
+ var db;
791
+ try {
792
+ db = await new Promise(function (resolve, reject) {
793
+ var request = indexedDB.open('gdwasm_saves', 1);
794
+ request.onupgradeneeded = function () {
795
+ if (!request.result.objectStoreNames.contains('files'))
796
+ request.result.createObjectStore('files');
797
+ };
798
+ request.onerror = function () {
799
+ reject(request.error || new Error('IndexedDB open failed'));
800
+ };
801
+ request.onsuccess = function () { resolve(request.result); };
802
+ });
803
+ } catch (e) {
804
+ console.error('Failed to open save database:', e);
805
+ return;
806
+ }
807
+ var savedKeys;
808
+ try {
809
+ var keysTx = db.transaction('files', 'readonly');
810
+ savedKeys = await idbRequestResult(keysTx, keysTx.objectStore('files').getAllKeys());
811
+ } catch (e) {
812
+ console.error('Failed to read saved file list:', e);
813
+ db.close();
814
+ return;
815
+ }
816
+ var written = [];
817
+ for (var fi = 0; fi < files.length; ++fi) {
818
+ var file = files[fi], saved;
819
+ try {
820
+ var readTx = db.transaction('files', 'readonly');
821
+ saved = await idbRequestResult(readTx, readTx.objectStore('files').get(file.key));
822
+ } catch (e) {
823
+ console.error('Failed to read saved file ' + file.key + ':', e);
824
+ continue;
825
+ }
826
+ var savedBytes = saved instanceof ArrayBuffer
827
+ ? new Uint8Array(saved)
828
+ : (ArrayBuffer.isView(saved)
829
+ ? new Uint8Array(saved.buffer, saved.byteOffset, saved.byteLength) : null);
830
+ var unchanged = savedBytes && savedBytes.length === file.bytes.byteLength;
831
+ if (unchanged) {
832
+ var currentBytes = new Uint8Array(file.bytes);
833
+ for (var compareOffset = 0; compareOffset < currentBytes.length; compareOffset += 65536) {
834
+ var compareEnd = Math.min(compareOffset + 65536, currentBytes.length);
835
+ for (var bi = compareOffset; bi < compareEnd; ++bi) {
836
+ if (currentBytes[bi] !== savedBytes[bi]) {
837
+ unchanged = false;
838
+ break;
839
+ }
840
+ }
841
+ if (!unchanged) break;
842
+ await saveYield();
843
+ }
844
+ }
845
+ if (!unchanged) {
846
+ try {
847
+ var writeTx = db.transaction('files', 'readwrite');
848
+ await idbRequestResult(writeTx, writeTx.objectStore('files').put(file.bytes, file.key));
849
+ written.push(file.key);
850
+ } catch (e) {
851
+ console.error('Failed to save AppData file ' + file.key + ':', e);
852
+ }
853
+ }
854
+ await saveYield();
855
+ }
856
+ for (var ki = 0; ki < savedKeys.length; ++ki) {
857
+ var oldKey = savedKeys[ki];
858
+ if (typeof oldKey !== 'string' || oldKey.indexOf('AppData/') !== 0 || paths[oldKey]) continue;
859
+ try {
860
+ var deleteTx = db.transaction('files', 'readwrite');
861
+ await idbRequestResult(deleteTx, deleteTx.objectStore('files').delete(oldKey));
862
+ } catch (e) {
863
+ console.error('Failed to delete saved AppData file ' + oldKey + ':', e);
864
+ }
865
+ await saveYield();
866
+ }
867
+ say('[persist] saved ' + written.length + ' changed AppData file(s): ' +
868
+ written.join(', '));
869
+ db.close();
870
+ }
871
+ var Module = {
872
+ canvas: document.getElementById('canvas'),
873
+ gdInputQueue: [],
874
+ gdCursorPos: [0, 0],
875
+ locateFile: function (p) { return p + '?v=' + GD_BUILD_ID; },
876
+ get dataFileDownloads() { return this.__dfd; },
877
+ set dataFileDownloads(v) {
878
+ if (this.__dfd === v) return;
879
+ this.__dfd = new Proxy(v || {}, {
880
+ set: function (t, k, val) {
881
+ t[k] = val;
882
+ try {
883
+ var which = /wasm/i.test(k) ? 'wasm'
884
+ : (/\.data/i.test(k) ? 'data' : null);
885
+ if (which) setAssetBar(which, (val && val.loaded) || 0,
886
+ (val && val.total) || 0);
887
+ } catch (e) {}
888
+ return true;
889
+ }
890
+ });
891
+ },
892
+ instantiateWasm: function (imports, success) {
893
+ return GDAssets.instantiateWasm(imports, success);
894
+ },
895
+ print: function (s) { say(s); },
896
+ printErr: function (s) { say(s); },
897
+ setStatus: function (t) {
898
+ if (!t) return;
899
+ var m = /\((\d+)\/(\d+)\)/.exec(t);
900
+ if (m) {
901
+ var total = +m[2] || 1;
902
+ setProgress(+m[1] / total * 78);
903
+ } else if (t.indexOf('Downloading') === 0) {
904
+ setProgress(4);
905
+ } else if (t.indexOf('Running') === 0) {
906
+ forceAssetsDone();
907
+ setProgress(80);
908
+ } else if (t.indexOf('Compiling') === 0) {
909
+ setProgress(76);
910
+ }
911
+ },
912
+ onRuntimeInitialized: function () {
913
+ window.__gdRuntimeReady = true;
914
+ if (!/[?&]noauto/.test(location.search))
915
+ setInterval(function () { scheduleSave(false); }, 30000);
916
+ if (Module._gd_log_set) Module._gd_log_set(GD_DEBUG ? 1 : 0);
917
+ if (/[?&]noauto/.test(location.search) && Module._gd_autosave_set)
918
+ Module._gd_autosave_set(0);
919
+ setProgress(82);
920
+ try {
921
+ Module.FS.chdir('/Resources');
922
+ } catch (e) {
923
+ say('FS.chdir failed: ' + e);
924
+ }
925
+ setTimeout(function () {
926
+ restoreSaves(function () {
927
+ window.__gdSavesRestored = true;
928
+ setProgress(88);
929
+ try {
930
+ const r = Module._gd_boot();
931
+ setProgress(92);
932
+ if (r && typeof r.then === 'function') {
933
+ r.then(function () { say('gd_boot resolved'); setProgress(100); })
934
+ .catch(function (e) {
935
+ try {
936
+ var ov = document.getElementById('errOverlay');
937
+ if (ov) {
938
+ ov.textContent = 'The game crashed (' + e + '). Reload the page to ' +
939
+ 'keep playing. Open it with ?debug to see logs.';
940
+ ov.classList.add('on');
941
+ }
942
+ } catch (e2) {}
943
+ say('gd_boot rejected: ' + e);
944
+ if (e && e.stack) say('STACK: ' + e.stack);
945
+ dumpRegs();
946
+ dumpTrace();
947
+ });
948
+ } else {
949
+ say('gd_boot returned (sync)');
950
+ setProgress(100);
951
+ }
952
+ } catch (e) {
953
+ say('gd_boot exception: ' + e);
954
+ }
955
+ });
956
+ }, 100);
957
+ }
958
+ };
959
+ (function () {
960
+ var nativeFetch = window.fetch;
961
+ var nativeXhrOpen = XMLHttpRequest.prototype.open;
962
+ var audioObjectUrls = new WeakMap();
963
+ function audioFilename(url) {
964
+ var path = String(url).replace(/\\/g, '/');
965
+ try { path = decodeURIComponent(path); }
966
+ catch (e) {
967
+ say('[audio] invalid encoded song path: ' + url);
968
+ return null;
969
+ }
970
+ path = path.replace(/\\/g, '/').split(/[?#]/)[0];
971
+ var match = /(?:^|\/)([^/]+\.mp3)$/i.exec(path);
972
+ return match ? match[1] : null;
973
+ }
974
+ function normalizeFsPath(path) {
975
+ return String(path).replace(/\\/g, '/').replace(/\/+/g, '/').replace(/\/$/, '') || '/';
976
+ }
977
+ function readLocalSong(url) {
978
+ var filename = audioFilename(url);
979
+ var fs = Module.FS;
980
+ if (!filename || !fs || !fs.analyzePath || !fs.readFile) return null;
981
+ var cwd = typeof fs.cwd === 'function' ? fs.cwd() : '/';
982
+ var roots = ['/Resources', '/', '/AppData', cwd];
983
+ var tried = [];
984
+ var scanErrors = [];
985
+ var checked = Object.create(null);
986
+ function readPath(path) {
987
+ path = normalizeFsPath(path);
988
+ if (checked[path]) return null;
989
+ checked[path] = true;
990
+ tried.push(path);
991
+ if (!fs.analyzePath(path).exists) return null;
992
+ try {
993
+ return { path: path, bytes: fs.readFile(path) };
994
+ } catch (e) {
995
+ console.error('[audio] failed to read saved song ' + path, e);
996
+ throw e;
997
+ }
998
+ }
999
+ for (var i = 0; i < roots.length; ++i) {
1000
+ var direct = readPath(normalizeFsPath(roots[i]) + '/' + filename);
1001
+ if (direct) return direct;
1002
+ }
1003
+ var mp3Files = [];
1004
+ var visited = Object.create(null);
1005
+ function scan(directory) {
1006
+ directory = normalizeFsPath(directory);
1007
+ if (visited[directory]) return null;
1008
+ visited[directory] = true;
1009
+ tried.push(directory);
1010
+ var entries;
1011
+ try {
1012
+ entries = fs.readdir(directory);
1013
+ } catch (e) {
1014
+ scanErrors.push({ path: directory, error: String(e) });
1015
+ return null;
1016
+ }
1017
+ for (var j = 0; j < entries.length; ++j) {
1018
+ var name = entries[j];
1019
+ if (name === '.' || name === '..') continue;
1020
+ var path = directory === '/' ? '/' + name : directory + '/' + name;
1021
+ var stat;
1022
+ try {
1023
+ stat = fs.lstat ? fs.lstat(path) : fs.stat(path);
1024
+ } catch (e) {
1025
+ scanErrors.push({ path: path, error: String(e) });
1026
+ continue;
1027
+ }
1028
+ if (fs.isLink && fs.isLink(stat.mode)) continue;
1029
+ if (fs.isDir(stat.mode)) {
1030
+ var found = scan(path);
1031
+ if (found) return found;
1032
+ } else if (/\.mp3$/i.test(name)) {
1033
+ if (name.toLowerCase() === filename.toLowerCase()) {
1034
+ var song = readPath(path);
1035
+ if (song) return song;
1036
+ }
1037
+ mp3Files.push(path);
1038
+ }
1039
+ }
1040
+ return null;
1041
+ }
1042
+ var recursive = scan('/');
1043
+ if (recursive) return recursive;
1044
+ console.warn('[audio] song not found in virtual FS', {
1045
+ filename: filename,
1046
+ tried: tried,
1047
+ mp3Files: mp3Files,
1048
+ scanErrors: scanErrors
1049
+ });
1050
+ return null;
1051
+ }
1052
+ window.fetch = function (input, init) {
1053
+ var url = typeof input === 'string' ? input : input && (input.url || input.href);
1054
+ var method = (init && init.method) || (input && input.method) || 'GET';
1055
+ var normalizedUrl = typeof input === 'string' ? input.replace(/\\/g, '/') : input;
1056
+ if (url && String(method).toUpperCase() === 'GET') {
1057
+ var song = readLocalSong(url);
1058
+ if (song) return Promise.resolve(new Response(song.bytes, {
1059
+ status: 200,
1060
+ headers: { 'Content-Type': 'audio/mpeg' }
1061
+ }));
1062
+ }
1063
+ if (normalizedUrl !== input) return nativeFetch.call(this, normalizedUrl, init);
1064
+ return nativeFetch.apply(this, arguments);
1065
+ };
1066
+ function releaseAudioUrl(xhr) {
1067
+ var url = audioObjectUrls.get(xhr);
1068
+ if (url) {
1069
+ URL.revokeObjectURL(url);
1070
+ audioObjectUrls.delete(xhr);
1071
+ }
1072
+ }
1073
+ XMLHttpRequest.prototype.open = function (method, url) {
1074
+ releaseAudioUrl(this);
1075
+ var args = Array.prototype.slice.call(arguments);
1076
+ var song = /^GET$/i.test(method) ? readLocalSong(url) : null;
1077
+ if (song) {
1078
+ var blobUrl = URL.createObjectURL(new Blob([song.bytes], { type: 'audio/mpeg' }));
1079
+ audioObjectUrls.set(this, blobUrl);
1080
+ var xhr = this;
1081
+ function cleanup() {
1082
+ if (audioObjectUrls.get(xhr) === blobUrl) releaseAudioUrl(xhr);
1083
+ }
1084
+ ['loadend', 'abort', 'error', 'timeout'].forEach(function (event) {
1085
+ xhr.addEventListener(event, cleanup, { once: true });
1086
+ });
1087
+ args[1] = blobUrl;
1088
+ } else if (typeof url === 'string') {
1089
+ args[1] = url.replace(/\\/g, '/');
1090
+ }
1091
+ try {
1092
+ return nativeXhrOpen.apply(this, args);
1093
+ } catch (e) {
1094
+ releaseAudioUrl(this);
1095
+ throw e;
1096
+ }
1097
+ };
1098
+ })();
1099
+ var started = false;
1100
+ function gdStart() {
1101
+ if (started) return;
1102
+ try {
1103
+ var AC = window.AudioContext || window.webkitAudioContext;
1104
+ if (AC && !Module.gdAudioContext) Module.gdAudioContext = new AC({latencyHint:'interactive'});
1105
+ if (Module.gdAudioContext) Module.gdAudioContext.resume().catch(function(){});
1106
+ } catch (_) {}
1107
+ started = true;
1108
+ window.__gdLoadStarted = true;
1109
+ resetProgress();
1110
+ var startEl = document.getElementById('start');
1111
+ var flyEl = document.getElementById('logoFly');
1112
+ var s = 0.32;
1113
+ try {
1114
+ var dh = document.querySelector('#logoDock img').getBoundingClientRect().height;
1115
+ var fh = flyEl.querySelector('img').getBoundingClientRect().height;
1116
+ if (dh > 0 && fh > 0 && dh / fh < 1) s = dh / fh;
1117
+ } catch (e) {}
1118
+ flyEl.style.transform = 'translateY(-13vh) scale(' + s + ')';
1119
+ document.getElementById('loadFly').classList.add('down');
1120
+ setTimeout(function () { startEl.classList.add('hide'); }, 420);
1121
+ setTimeout(function () { document.getElementById('logoDock').classList.add('in'); }, 420);
1122
+ setTimeout(function () { document.getElementById('stage').classList.add('in'); }, 430);
1123
+ setTimeout(function () { document.getElementById('midbar').classList.add('in'); }, 480);
1124
+ setTimeout(function () { document.getElementById('console').classList.add('in'); }, 540);
1125
+ setTimeout(function () {
1126
+ startEl.style.display = 'none';
1127
+
1128
+ }, 1700);
1129
+ function loadModule() {
1130
+ GDAssets.loadScript().then(function (code) {
1131
+ var s = document.createElement('script');
1132
+ s.textContent = code;
1133
+ document.body.appendChild(s);
1134
+ }).catch(function (e) {
1135
+ GDAssets.fail(e);
1136
+ });
1137
+ }
1138
+ loadModule();
1139
+ }
1140
+
1141
+ document.getElementById('saveBtn').addEventListener('click', function (e) {
1142
+ e.preventDefault(); e.stopPropagation();
1143
+ if (!window.__gdRuntimeReady) return;
1144
+ scheduleSave(true);
1145
+ this.textContent = 'Save requested';
1146
+ var button = this; setTimeout(function () { button.textContent = 'Save progress'; }, 3000);
1147
+ });
1148
+ document.getElementById('clearBtn').addEventListener('click', function (e) {
1149
+ e.preventDefault();
1150
+ e.stopPropagation();
1151
+ gdClearCache();
1152
+ });
1153
+ document.addEventListener('keydown', function (e) {
1154
+ if (!started && (e.code === 'Space' || e.key === ' ' || e.code === 'Enter' ||
1155
+ e.key === 'Enter' || e.code === 'NumpadEnter')) {
1156
+ e.preventDefault();
1157
+ gdStart();
1158
+ }
1159
+ });</script><script>
1160
+ (function () {
1161
+ 'use strict';
1162
+ var el = Module.canvas, head = 0;
1163
+ var keys = new Map(), pointers = new Map();
1164
+ var buttonCounts = [0, 0, 0], pointerButtons = new Map();
1165
+ var queueSamples = [], frameSamples = [], lastFrame = 0, frameN = 0, focusAcked = false;
1166
+ var mouseButtons = 0;
1167
+ var benchmark = null;
1168
+ Module.gdBeginBenchmark = function (durationMs) {
1169
+ benchmark = {duration: Math.max(1000, Math.min(60000, durationMs || 20000)),
1170
+ start: null, previous: 0, frames: [], input: [], heap: 0};
1171
+ Module.gdBenchmark = {running: true, elapsedMs: 0};
1172
+ };
1173
+ Module.gdKeyState = new Uint8Array(256);
1174
+ Module.gdInputStats = {samples: 0, queueMs: 0, queueP95Ms: 0, frameP95Ms: 0, pointerClient: null, pointerGame: null};
1175
+ function ready() { return window.__gdInputReady === true; }
1176
+ function timestamp(e) {
1177
+ var now = performance.now(), stamp = e && e.timeStamp;
1178
+ return stamp > 0 && stamp <= now && now - stamp < 60000 ? stamp : now;
1179
+ }
1180
+ function push(msg, wp, lp, time) {
1181
+ Module.gdInputQueue.push([msg | 0, wp | 0, lp | 0, time || performance.now()]);
1182
+ }
1183
+ function position(e) {
1184
+ var r = el.getBoundingClientRect();
1185
+ var width = el.width || 1920, height = el.height || 1080;
1186
+ var x = Math.max(0, Math.min(width - 1, Math.round((e.clientX - r.left) * width / r.width)));
1187
+ var y = Math.max(0, Math.min(height - 1, Math.round((e.clientY - r.top) * height / r.height)));
1188
+ Module.gdCursorPos[0] = x; Module.gdCursorPos[1] = y;
1189
+ Module.gdInputStats.pointerClient = [e.clientX, e.clientY];
1190
+ Module.gdInputStats.pointerGame = [x, y];
1191
+ return (x & 65535) | (y << 16);
1192
+ }
1193
+ function cursor() { return (Module.gdCursorPos[0] & 65535) | (Module.gdCursorPos[1] << 16); }
1194
+ function percentile(values) {
1195
+ if (!values.length) return 0;
1196
+ var sorted = values.slice().sort(function (a, b) { return a - b; });
1197
+ return sorted[Math.ceil(sorted.length * 0.95) - 1];
1198
+ }
1199
+ Module.gdPollInput = function () {
1200
+ if (head >= Module.gdInputQueue.length) return null;
1201
+ var entry = Module.gdInputQueue[head++];
1202
+ if (entry[0] === 0x100 || entry[0] === 0x201 || entry[0] === 0x204) {
1203
+ var delay = Math.max(0, performance.now() - entry[3]);
1204
+ queueSamples.push(delay); if (queueSamples.length > 120) queueSamples.shift();
1205
+ Module.gdInputStats.queueMs = delay; Module.gdInputStats.samples++;
1206
+ Module.gdInputStats.queueP95Ms = percentile(queueSamples);
1207
+ if (benchmark) benchmark.input.push(delay);
1208
+ }
1209
+ if (head >= Module.gdInputQueue.length) { Module.gdInputQueue.length = 0; head = 0; }
1210
+ return entry;
1211
+ };
1212
+ Module.gdMeasureFrame = function () {
1213
+ var now = performance.now();
1214
+ if (benchmark && !document.hidden) {
1215
+ var b = benchmark;
1216
+ if (b.start === null) b.start = now;
1217
+ else b.frames.push(now - b.previous);
1218
+ b.previous = now;
1219
+ if (Module.HEAPU8) b.heap = Math.max(b.heap, Module.HEAPU8.byteLength / 1048576);
1220
+ var elapsed = now - b.start;
1221
+ Module.gdBenchmark.elapsedMs = elapsed;
1222
+ if (elapsed >= b.duration && b.frames.length) {
1223
+ Module.gdBenchmark = {running: false, frames: b.frames.length,
1224
+ elapsedMs: elapsed, meanFps: b.frames.length * 1000 / elapsed,
1225
+ frameP95Ms: percentile(b.frames), frameMaxMs: Math.max.apply(null, b.frames),
1226
+ inputP95Ms: b.input.length ? percentile(b.input) : null, heapMiB: b.heap};
1227
+ benchmark = null;
1228
+ }
1229
+ }
1230
+ if (lastFrame && !document.hidden) {
1231
+ frameSamples.push(now - lastFrame);
1232
+ if (frameSamples.length > 120) frameSamples.shift();
1233
+ if (++frameN % 30 === 0) Module.gdInputStats.frameP95Ms = percentile(frameSamples);
1234
+ }
1235
+ lastFrame = now;
1236
+ };
1237
+ function acknowledgeFocus() {
1238
+ if (focusAcked || !ready()) return;
1239
+ focusAcked = true; push(6, 1, 0); push(7, 0, 0); push(0x1c, 1, 0);
1240
+ }
1241
+ window.__gdAckFocus = acknowledgeFocus;
1242
+ var downMsg = [0x201, 0x207, 0x204], upMsg = [0x202, 0x208, 0x205];
1243
+ function setButton(b, down, lp, time) {
1244
+ var count = buttonCounts[b];
1245
+ buttonCounts[b] += down ? 1 : -1;
1246
+ var vk = [1, 4, 2][b];
1247
+ Module.gdKeyState[vk] = buttonCounts[b] ? 1 : 0;
1248
+ if (down && count === 0) push(downMsg[b], b === 2 ? 2 : b === 1 ? 16 : 1, lp, time);
1249
+ if (!down && buttonCounts[b] === 0) { push(upMsg[b], 0, lp, time); push(0x200, 0, lp, time); }
1250
+ }
1251
+ function syncMouse(mask, lp, time) {
1252
+ [1, 4, 2].forEach(function (bit, b) {
1253
+ if ((mouseButtons & bit) !== (mask & bit)) setButton(b, !!(mask & bit), lp, time);
1254
+ });
1255
+ mouseButtons = mask;
1256
+ }
1257
+ function releasePointer(id, time) {
1258
+ if (!pointers.has(id)) return;
1259
+ var button = pointerButtons.get(id), lp = pointers.get(id);
1260
+ pointers.delete(id); pointerButtons.delete(id);
1261
+ setButton(button, false, lp, time);
1262
+ }
1263
+ el.addEventListener('pointerdown', function (e) {
1264
+ if (!ready() || e.button > 2) return;
1265
+ acknowledgeFocus();
1266
+ el.focus({preventScroll: true});
1267
+ var lp = position(e), b = e.pointerType === 'mouse' ? e.button : 0;
1268
+ if (e.pointerType === 'mouse') {
1269
+ syncMouse(e.buttons === undefined ? (mouseButtons | [1, 4, 2][b]) : e.buttons, lp, timestamp(e));
1270
+ try { el.setPointerCapture(e.pointerId); } catch (_) {}
1271
+ e.preventDefault(); return;
1272
+ }
1273
+ if (pointers.has(e.pointerId)) return;
1274
+ pointers.set(e.pointerId, lp); pointerButtons.set(e.pointerId, b);
1275
+ setButton(b, true, lp, timestamp(e));
1276
+ try { el.setPointerCapture(e.pointerId); } catch (_) {}
1277
+ e.preventDefault();
1278
+ }, {passive: false});
1279
+ el.addEventListener('pointermove', function (e) {
1280
+ if (!ready()) return;
1281
+ var lp = position(e);
1282
+ if (e.pointerType === 'mouse' && e.buttons !== undefined) syncMouse(e.buttons, lp, timestamp(e));
1283
+ if (pointers.has(e.pointerId)) pointers.set(e.pointerId, lp);
1284
+ var wp = (buttonCounts[0] ? 1 : 0) | (buttonCounts[2] ? 2 : 0) | (buttonCounts[1] ? 16 : 0);
1285
+ var q = Module.gdInputQueue, tail = q[q.length - 1];
1286
+ if (q.length > head && tail[0] === 0x200) q[q.length - 1] = [0x200, wp, lp, timestamp(e)];
1287
+ else push(0x200, wp, lp, timestamp(e));
1288
+ });
1289
+ ['pointerup', 'pointercancel', 'lostpointercapture'].forEach(function (name) {
1290
+ el.addEventListener(name, function (e) {
1291
+ if (e.pointerType === 'mouse') syncMouse(name === 'pointerup' ? (e.buttons || 0) : 0, cursor(), timestamp(e));
1292
+ else releasePointer(e.pointerId, timestamp(e));
1293
+ });
1294
+ });
1295
+ el.addEventListener('contextmenu', function (e) { e.preventDefault(); });
1296
+ el.addEventListener('wheel', function (e) {
1297
+ if (!ready() || (!e.deltaX && !e.deltaY)) return;
1298
+ var vertical = Math.abs(e.deltaY) >= Math.abs(e.deltaX);
1299
+ var notch = (vertical ? -e.deltaY : -e.deltaX) > 0 ? 120 : -120;
1300
+ push(vertical ? 0x20a : 0x20e, (notch & 65535) << 16, position(e), timestamp(e));
1301
+ e.preventDefault();
1302
+ }, {passive: false});
1303
+ var VK = {Escape:27, Space:32, Enter:13, Backspace:8, Tab:9, ArrowLeft:37, ArrowUp:38, ArrowRight:39, ArrowDown:40};
1304
+ var scan = {Escape:1, Space:57, Enter:28, Backspace:14, Tab:15, ArrowLeft:75, ArrowUp:72, ArrowRight:77, ArrowDown:80,
1305
+ KeyW:17, KeyA:30, KeyS:31, KeyD:32, KeyQ:16, KeyE:18, KeyR:19, KeyF:33, KeyP:25};
1306
+ function key(e, down) {
1307
+ if (!ready()) return;
1308
+ var vk = VK[e.code] || e.keyCode || 0;
1309
+ if (!vk || vk > 255) return;
1310
+ if (down && (e.ctrlKey || e.metaKey || e.altKey || e.target.closest && e.target.closest('button,input,textarea,select,a'))) return;
1311
+ if (!down && !keys.has(vk)) return;
1312
+ if (e.repeat && (e.code === 'Space' || e.code.indexOf('Arrow') === 0)) { e.preventDefault(); return; }
1313
+ var lp = 1 | ((scan[e.code] || 0) << 16);
1314
+ if (e.code.indexOf('Arrow') === 0) lp |= 0x1000000;
1315
+ if (down && keys.has(vk)) lp |= 0x40000000;
1316
+ if (!down) lp |= -1073741824;
1317
+ Module.gdKeyState[vk] = down ? 1 : 0;
1318
+ if (down) keys.set(vk, lp); else keys.delete(vk);
1319
+ push(down ? 0x100 : 0x101, vk, lp, timestamp(e));
1320
+ if (down) {
1321
+ var ch = e.key && e.key.length === 1 ? e.key.charCodeAt(0) : e.code === 'Backspace' ? 8 : e.code === 'Enter' ? 13 : 0;
1322
+ if (ch) push(0x102, ch, lp, timestamp(e));
1323
+ }
1324
+ if (VK[e.code]) e.preventDefault();
1325
+ }
1326
+ window.addEventListener('keydown', function (e) { key(e, true); }, {capture: true});
1327
+ window.addEventListener('keyup', function (e) { key(e, false); }, {capture: true});
1328
+ function releaseAll() {
1329
+ if (benchmark) {
1330
+ benchmark = null;
1331
+ Module.gdBenchmark = {running: false, error: 'Interrupted: keep the game focused for the test'};
1332
+ }
1333
+ syncMouse(0, cursor());
1334
+ pointers.forEach(function (_, id) { releasePointer(id); });
1335
+ keys.forEach(function (lp, vk) { push(0x101, vk, lp | -1073741824); });
1336
+ keys.clear(); Module.gdKeyState.fill(0); focusAcked = false;
1337
+ lastFrame = 0; frameSamples.length = 0;
1338
+ }
1339
+ window.addEventListener('blur', releaseAll);
1340
+ document.addEventListener('visibilitychange', function () { if (document.hidden) releaseAll(); });
1341
+ el.tabIndex = 0;
1342
+ })();
1343
+
1344
+ </script><script>(function(){var b=document.getElementById('fsBtn'),d=document,c=document.getElementById('canvas');function F(){return d.fullscreenElement||d.webkitFullscreenElement||d.mozFullScreenElement||d.msFullscreenElement;}function U(){b.textContent=F()?'Exit Fullscreen':'Fullscreen';}async function T(){try{if(F()){(d.exitFullscreen||d.webkitExitFullscreen||d.mozCancelFullScreen||d.msExitFullscreen).call(d);}else{await (document.documentElement.requestFullscreen||document.documentElement.webkitRequestFullscreen||document.documentElement.mozRequestFullScreen||document.documentElement.msRequestFullscreen).call(document.documentElement);try{if(navigator.keyboard&&navigator.keyboard.lock)await navigator.keyboard.lock(['Escape']);}catch(err){}}}catch(err){}}b.addEventListener('click',function(v){v.preventDefault();v.stopPropagation();T();b.blur();});['fullscreenchange','webkitfullscreenchange','mozfullscreenchange','MSFullscreenChange'].forEach(function(n){d.addEventListener(n,U);});d.addEventListener('fullscreenchange',function(){if(d.fullscreenElement===null&&navigator.keyboard&&navigator.keyboard.unlock)navigator.keyboard.unlock();});U();})();</script><script>(function(){
1345
+ var ov=document.getElementById('errOverlay');
1346
+ function err(m){ if(ov){ov.textContent=m;ov.classList.add('on');} }
1347
+ try{
1348
+ var c=document.createElement('canvas');
1349
+ var gl=c.getContext('webgl2');
1350
+ if(!gl) err('WebGL2 not available - use Chrome/Edge 137+ with hardware acceleration.');
1351
+ if(!window.crossOriginIsolated) console.log('[page] note: page is not cross-origin isolated; threads may be limited.');
1352
+ if(typeof WebAssembly.Suspending!=='function'||typeof WebAssembly.promising!=='function') err('This game needs a browser with WebAssembly JSPI support. Update Chrome or Edge.');
1353
+ if(gl){var lose=gl.getExtension('WEBGL_lose_context');if(lose)lose.loseContext();}
1354
+ }catch(e){ err('Feature check failed: '+e); }
1355
+ window.addEventListener('error',function(e){ if(e&&e.message&&/JSPI|WebAssembly|wasm|memory/i.test(String(e.message))) err('Runtime error: '+e.message); });
1356
+ })();</script>
1357
+ <script>(function(){
1358
+ var load=document.getElementById('gdLoad');
1359
+ var pct=document.getElementById('gdLoadPct');
1360
+ var totals={wasm:123481510,data:322237583};
1361
+ var loaded={wasm:0,data:0};
1362
+ var shown=1;
1363
+ pct.style.setProperty('--p',shown);
1364
+ var completed=false;
1365
+ var failed=false;
1366
+ var completionTimer=null;
1367
+ var hideTimer=null;
1368
+ function update(){
1369
+ if(completed||failed)return;
1370
+ var value=Math.floor((loaded.wasm+loaded.data)/(totals.wasm+totals.data)*100);
1371
+ value=Math.max(1,Math.min(99,value));
1372
+ if(value>shown){shown=value;pct.style.setProperty('--p',shown);}
1373
+ }
1374
+ var originalSetAssetBar=window.setAssetBar;
1375
+ window.setAssetBar=function(which,amount,total){
1376
+ if(which==='wasm'||which==='data'){
1377
+ loaded[which]=Math.max(0,Number(amount)||0);
1378
+ if(Number(total)>0)totals[which]=Number(total);
1379
+ update();
1380
+ }
1381
+ return originalSetAssetBar.apply(this,arguments);
1382
+ };
1383
+ function hide(){
1384
+ if(failed)return;
1385
+ if(completionTimer!==null)clearTimeout(completionTimer);
1386
+ pct.style.setProperty('--p',100);
1387
+ load.classList.add('off');
1388
+ hideTimer=setTimeout(function(){load.style.display='none';},700);
1389
+ }
1390
+ function complete(){
1391
+ if(completed||failed)return;
1392
+ completed=true;
1393
+ pct.style.setProperty('--p',100);
1394
+ completionTimer=setTimeout(hide,300);
1395
+ }
1396
+ var originalFirstFrame=window.gdFirstFrame;
1397
+ window.gdFirstFrame=function(){
1398
+ complete();
1399
+ if(typeof originalFirstFrame==='function')return originalFirstFrame.apply(this,arguments);
1400
+ };
1401
+ var bodyObserver=new MutationObserver(function(){
1402
+ if(document.body.classList.contains('playing'))complete();
1403
+ });
1404
+ bodyObserver.observe(document.body,{attributes:true,attributeFilter:['class']});
1405
+ var overlay=document.getElementById('errOverlay');
1406
+ function hideForError(){
1407
+ failed=true;
1408
+ if(completionTimer!==null)clearTimeout(completionTimer);
1409
+ if(hideTimer!==null)clearTimeout(hideTimer);
1410
+ load.style.display='none';
1411
+ }
1412
+ var errorObserver=new MutationObserver(function(){
1413
+ if(overlay.classList.contains('on'))hideForError();
1414
+ });
1415
+ errorObserver.observe(overlay,{attributes:true,attributeFilter:['class']});
1416
+ if(overlay.classList.contains('on'))hideForError();
1417
+ if(document.body.classList.contains('playing'))complete();
1418
+ window.addEventListener('load',function(){gdStart();});
1419
+ window.addEventListener('beforeunload',function(e){
1420
+ if(!window.__gdRuntimeReady)return;
1421
+ if(gdSaveTimer)clearTimeout(gdSaveTimer);
1422
+ gdSaveTimer=null;
1423
+ performSave();
1424
+ e.preventDefault();
1425
+ e.returnValue='';
1426
+ });
1427
+ document.addEventListener('contextmenu',function(e){e.preventDefault();});
1428
+ function firstPointerDown(){
1429
+ document.removeEventListener('pointerdown',firstPointerDown,true);
1430
+ var audio=window.Module&&window.Module.gdAudioContext;
1431
+ if(audio&&audio.state==='suspended')audio.resume();
1432
+ if(!document.fullscreenElement){var button=document.getElementById('fsBtn');if(button)button.click();}
1433
+ }
1434
+ document.addEventListener('pointerdown',firstPointerDown,true);
1435
+ })();</script></body></html>