-
Notifications
You must be signed in to change notification settings - Fork 0
/
zeta.min.js
22 lines (22 loc) · 29.4 KB
/
zeta.min.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* Copyright (c) 2018, 2019, 2020, 2021, 2022, 2023, 2024 Adrian Siekierka
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
!function(){"use strict";let e,t=Date.now();function r(e,t,r){let i=32;for(;i>8&&(t.font="bold "+i+"px sans-serif",!(t.measureText(r).width<=e.width-4));)i--;t.fillStyle="rgba(0, 0, 0, 0.75)",t.fillRect(0,0,e.width,e.height),t.textBaseline="middle";const s=(e.width-t.measureText(r).width)/2,n=e.height/2;t.fillStyle="#000000",t.fillText(r,s+2,n+2),t.fillStyle="#ffffff",t.fillText(r,s,n)}function s(){return Date.now()-t}function n(){try{return window.indexedDB||window.webkitIndexedDB||window.mozIndexedDB}catch(e){return}}function o(e,t){return new Promise(((r,i)=>{var s=new XMLHttpRequest;s.open("GET",e,!0),s.overrideMimeType("text/plain; charset=x-user-defined"),s.responseType="arraybuffer",s.onprogress=e=>{t&&t(e.loaded/e.total)},s.onload=n=>{t&&t(1),200==s.status?r(s):i("Error downloading "+e+" ("+s.status+")")},s.onerror=t=>{i("Error downloading "+e+" (XHR)")},s.send()}))}document.addEventListener("mousedown",(function(t){null==e&&(e=new(window.AudioContext||window.webkitAudioContext))})),document.addEventListener("keydown",(function(t){null==e&&(e=new(window.AudioContext||window.webkitAudioContext))}));class a{constructor(e){this.lastCurrTime=0,this.lastTimeMs=0,this.timeSpeakerOn=0,this.audioGain=void 0,this.pc_speaker=void 0,this.volume=Math.min(1,Math.max(0,e&&e.volume||.1)),this.noteDelay=1}on(t,r,i){if(null==e)return;let s=e.currentTime;s!=this.lastCurrTime&&(this.lastCurrTime=s,this.lastTimeMs=t);let n=(t-this.lastTimeMs)/1e3;null==this.pc_speaker?(this.audioGain=e.createGain(),this.pc_speaker=e.createOscillator(),this.pc_speaker.type="square",this.pc_speaker.frequency.setValueAtTime(i,e.currentTime+n),this.pc_speaker.connect(this.audioGain),this.audioGain.connect(e.destination),this.audioGain.gain.setValueAtTime(this.volume,e.currentTime),this.pc_speaker.start(0)):this.pc_speaker.frequency.setValueAtTime(i,e.currentTime+n),this.timeSpeakerOn=t}off(t,r){if(null==this.pc_speaker)return;let i=e.currentTime;i!=this.lastCurrTime&&(this.lastCurrTime=i,this.lastTimeMs=t);let s=(t-this.lastTimeMs)/1e3;this.pc_speaker.frequency.setValueAtTime(0,e.currentTime+s)}setNoteDelay(e){this.noteDelay=e}setVolume(t){this.volume=Math.min(1,Math.max(0,t)),null!=this.pc_speaker&&this.audioGain.gain.setValueAtTime(this.volume,e.currentTime)}}class h{constructor(e,t){this.emu=e,this.sampleRate=t&&t.sampleRate||48e3,this.bufferSize=t&&t.bufferSize||2048,this.noteDelay=t&&t.noteDelay||void 0,this.volume=Math.min(1,Math.max(0,t&&t.volume||.1)),this.timeUnit=this.bufferSize/this.sampleRate,this.initialized=!1,this.lastTimeMs=0}_queueBufferSource(t){this.time+=this.timeUnit,this.time<e.currentTime&&(this.time=e.currentTime);const r=e.createBufferSource(),i=e.createBuffer(1,this.bufferSize,this.sampleRate);t&&t(i,r),r.buffer=i,r.onended=()=>this._queueNextSpeakerBuffer(),r.connect(e.destination),r.start(this.time)}_queueNextSpeakerBuffer(){const e=this;this._queueBufferSource(((t,r)=>{const i=e.bufferSize,n=e.nativeBuffer,o=e.nativeHeap,a=t.getChannelData(0);e.emu._audio_stream_generate(s(),n,2*e.bufferSize);for(let e=0;e<i;e++)a[e]=(o[e]-32768)/32768;for(var h=1;h<t.numberOfChannels;h++)t.getChannelData(h).set(a)}))}_initSpeaker(){return!!this.initialized||null!=e&&(this.initialized=!0,this.time=e.currentTime,this.emu._audio_generate_init(),this.emu._audio_stream_init(s(),this.sampleRate,!1,!0),this.emu._audio_stream_set_volume(Math.floor(this.volume*this.emu._audio_stream_get_max_volume())),this.noteDelay&&this.emu._audio_set_note_delay(this.noteDelay),this.nativeBuffer=this.emu._malloc(2*this.bufferSize),this.nativeHeap=new Uint16Array(this.emu.HEAPU8.buffer,this.nativeBuffer,this.bufferSize),this._queueBufferSource((()=>{})),this._queueNextSpeakerBuffer(),!0)}setNoteDelay(e){this.noteDelay=e,this.initialized&&this.emu._audio_set_note_delay(e)}setVolume(e){this.volume=Math.min(1,Math.max(0,e)),this.initialized&&this.emu._audio_stream_set_volume(Math.floor(this.volume*this.emu._audio_stream_get_max_volume()))}on(e,t,r){this._initSpeaker()&&this.emu._audio_stream_append_on(e,t,r)}off(e,t){this._initSpeaker()&&this.emu._audio_stream_append_off(e,t)}}class l{constructor(e,t,r){if(this.emu=e,this.canvas=t,this.ctx=t.getContext("2d",{alpha:!1}),this.ctx.imageSmoothingEnabled=!1,this.offscreenCanvas=document.createElement("canvas"),this.offscreenCanvas.width=640,this.offscreenCanvas.height=400,this.offscreenCtx=this.offscreenCanvas.getContext("2d",{alpha:!1}),this.offscreenCtx.imageSmoothingEnabled=!1,this.video_mode=-1,this.chrBuf=[],this.drawChrWidth=void 0,this.chrWidth=void 0,this.scrWidth=void 0,this.chrHeight=void 0,this.scrHeight=void 0,this.pw=void 0,this.ph=void 0,this.cw=void 0,this.ch=void 0,this.scale=1,this.asciiFg=null,this.charset=null,this.palette=null,this.rdDirty=!1,this.charset_override_enabled=r&&r.charset_override||!1,this.charset_override=null,this.charset_override_enabled){let e=new Image,t=this;e.src=r.charset_override,e.onload=function(){t.charset_override=e,t.rdDirty=!0}}}_updVideoMode(e,t){if(e!=this.video_mode&&(this.chrBuf=[],this.scrWidth=2==(2&e)?80:40,this.scrHeight=25,this.video_mode=e),this.drawChrWidth=this.chrWidth*Math.round(80/this.scrWidth),this.pw=this.scrWidth*this.drawChrWidth,this.ph=this.scrHeight*this.chrHeight,this.cw=this.canvas.width,this.ch=this.canvas.height,this.scale=Math.floor(Math.min(this.cw/this.pw,this.ch/this.ph)),this.scale<1&&(this.scale=1),this.emu._zzt_get_blink()){let e=this.emu._zzt_get_active_blink_duration_ms();this.blink_state=e>0&&t%(2*e)>=e?2:1}else this.blink_state=0;this.x_offset=Math.round((this.cw-this.pw*this.scale)/2),this.y_offset=Math.round((this.ch-this.ph*this.scale)/2)}_drawChar(e,t,r,i,s){switch(this.blink_state){case 0:break;case 1:s&=127;break;case 2:s>=128&&(s=17*((112&s)>>4))}const n=i<<8|s;if(this.chrBuf[80*r+t]===n)return;this.chrBuf[80*r+t]=n,t*=this.chrWidth,r*=this.chrHeight;const o=s>>4&15,a=15&s;e.fillStyle=this.palette[o],e.fillRect(t,r,this.chrWidth,this.chrHeight),o!=a&&e.drawImage(this.asciiFg[a],(15&i)*this.chrWidth,(i>>4&15)*this.chrHeight,this.chrWidth,this.chrHeight,t,r,this.chrWidth,this.chrHeight)}_updRenderData(){if(null==this.palette)return;let e=null;if(this.charset_override_enabled){if(null==this.charset_override)return;e=this.charset_override}else if(null==this.charset)return;if(this.asciiFg=[],null==e){let a=document.createElement("canvas");a.width=16*this.chrWidth,a.height=16*this.chrHeight;let h=a.getContext("2d"),l=h.createImageData(a.width,a.height),u=l.data,c=0;for(var t=0;t<256;t++){let e=(15&t)*this.chrWidth,h=(t>>4)*this.chrHeight;for(var r=0;r<this.chrHeight;r++,c++)for(var i=(h+r)*a.width+e,s=this.charset[c],n=0;n<this.chrWidth;n++,i++,s<<=1){var o=255*(s>>7&1);u[4*i+0]=o,u[4*i+1]=o,u[4*i+2]=o,u[4*i+3]=o}}h.putImageData(l,0,0),e=a}for(var a=0;a<16;a++){if("#ffffff"==this.palette[a].toLowerCase()){this.asciiFg[a]=e;continue}let t=document.createElement("canvas");t.width=16*this.chrWidth,t.height=16*this.chrHeight;let r=t.getContext("2d");r.globalCompositeOperation="copy",r.drawImage(e,0,0),r.globalCompositeOperation="source-in",r.fillStyle=this.palette[a],r.fillRect(0,0,t.width,t.height),this.asciiFg[a]=t}this.chrBuf=[],this.rdDirty=!1}render(e,t,r){this.rdDirty&&this._updRenderData(),this._updVideoMode(t,r);let i=0,s=Math.floor(80/this.scrWidth);var n=this.canvas,o=this.ctx;if((this.scale>1||s>1||0!=this.x_offset||0!=this.y_offset)&&(n=this.offscreenCanvas,o=this.offscreenCtx),null!=this.asciiFg&&null!=this.palette)for(var a=0;a<25;a++)for(var h=0;h<this.scrWidth;h++,i+=2)this._drawChar(o,h,a,e[i],e[i+1]);o!=this.ctx&&(this.ctx.fillStyle="#000000",this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height),this.ctx.drawImage(n,0,0,80*this.chrWidth/s,25*this.chrHeight,this.x_offset,this.y_offset,80*this.chrWidth*this.scale,25*this.chrHeight*this.scale))}setBlinkEnabled(e){this.emu._zzt_load_blink(0!=e)}setBlinkCycleDuration(e){this.emu._zzt_set_blink_duration_ms(Math.round(500*e))}setCharset(e,t,r){this.chrWidth=e,this.chrHeight=t,this.charset=r.slice(0),this.rdDirty=!0}setPalette(e){this.palette=new Array;for(var t=0;t<16;t++){let r=(16777215&e[t]).toString(16);for(;r.length<6;)r="0"+r;this.palette[t]="#"+r}this.rdDirty=!0}}let u={ArrowUp:72,ArrowLeft:75,ArrowRight:77,ArrowDown:80,Home:71,End:79,Insert:82,Delete:83,PageUp:73,PageDown:81,Enter:28,Escape:1,Backspace:14,Tab:15,"-":12,_:12,"=":13,"+":13,"`":41,"~":41,"\\":43,"|":43,"*":55," ":57},c={},f=function(e,t){for(var r=0;r<e.length;r++)u[e.charAt(r)]=t+r};f("1234567890",2),f("QWERTYUIOP{}",16),f("qwertyuiop[]",16),f("asdfghjkl;'",30),f('ASDFGHJKL:"',30),f("zxcvbnm,./",44),f("ZXCVBNM<>?",44);for(var d=1;d<=26;d++)c[String.fromCharCode(64+d)]=d,c[String.fromCharCode(96+d)]=d;for(d=1;d<=10;d++)u["F"+d]=58+d;const _=u,m=c,p={8:8,9:9,13:13,27:27};function g(e,t){if(null==t)return e;let r=[];for(var i=0;i<e.length;i++){const s=e[i];t(s)&&r.push(s)}return r}class w{constructor(e){this.use83Names=e&&e.use83Names||!1,this.ignoreCase=e&&e.ignoreCase||!1,this.readonly=e&&e.readonly||!1,this._clearCaches()}_clearCaches(){this.use83NameCache={},this.use83NameUsed={}}_transformKey(e){var t=e;if("upper"==this.ignoreCase?t=t.toUpperCase():this.ignoreCase&&(t=t.toLowerCase()),this.use83Names){var r="",i="";for(var s of t.split("\\"))if((i=i+(i.length>0?"\\":"")+s)in this.use83NameCache)r=this.use83NameCache[i];else{var n=s.split(".",2),o=!1;if(n[0].length>8&&(o=!0),n.length>=2&&n[1].length>3&&(n[1]=n[1].substring(0,3)),o)for(var a=1,h=n[0].replaceAll(" ","");;){var l=a.toString();if(n[0]=h.substring(0,7-l.length)+"~"+l,s=n.join("."),!(r+(r.length>0?"\\":"")+s in this.use83NameUsed))break;if((a+=1)>=1e3)throw new Error("Too many filenames! (at "+e+")")}else s=n.join(".");r.length>0&&(r+="\\"),r+=s,this.use83NameCache[i]=r,this.use83NameUsed[r]=i}t=r}return t}canSet(e){return!this.readonly&&(!this._canSet||this._canSet(this._transformKey(e)))}get(e){return this._get(this._transformKey(e))}list(e){return this._list(e)}set(e,t){return!this.readonly&&this._set(this._transformKey(e),t)}}class y{constructor(e){this.providers=e}canSet(e){for(var t=0;t<this.providers.length;t++){if(this.providers[t].canSet(e))return!0}return!1}get(e){for(var t=this.providers.length-1;t>=0;t--){const r=this.providers[t].get(e);if(null!=r)return r}return null}list(e){let t=[];for(var r=0;r<this.providers.length;r++){let i=this.providers[r];t=t.concat(i.list(e))}return t.sort().filter((function(e,t,r){return t<=0||e!=r[t-1]}))}set(e,t){Promise.resolve(!1);for(var r=this.providers.length-1;r>=0;r--){if(this.providers[r].set(e,t))return!0}return!1}}class v extends w{constructor(e,t){for(var r in super(t),this.map={},e)this.map[this._transformKey(r)]=e[r]}_get(e){return this.map.hasOwnProperty(e)?this.map[e].slice(0):null}_list(e){return g(Object.keys(this.map),e)}_set(e,t){return this.map[e]=t,!0}}class z extends v{constructor(e,t){super({},t),this.parent=e}_populate(){const e=this;return this.parent.list(null).then((t=>{e.map={};let r=[];for(var i=0;i<t.length;i++){const s=t[i];r.push(e.parent.get(s).then((e=>{this._set(s,e)})))}return Promise.all(r)}))}_set(e,t){return!!super._set(e,t)&&(this.parent.set(e,t),!0)}}class b extends w{constructor(e,t,r){super(r),this.storage=e,this.prefix=t+"_file_"}_get(e){const t=this.storage.getItem(this.prefix+e.toUpperCase());return t?t.split(",").map((e=>parseInt(e))):null}_list(e){for(var t=[],r=0;r<this.storage.length;r++){const e=this.storage.key(r);e.startsWith(this.prefix)&&t.push(e.substring(this.prefix.length))}return g(t,e)}_set(e,t){return this.storage.setItem(this.prefix+e,t.join(",")),!0}}class k{constructor(e,t){this.indexedDB=e,this.dbName=t}_open(){const e=this;return new Promise(((t,r)=>{var i=e.indexedDB.open(this.dbName,1);i.onupgradeneeded=t=>{e.database=t.target.result,e.files=e.database.createObjectStore("files",{keyPath:"filename"})},i.onsuccess=r=>{e.database=i.result,t()},i.onerror=e=>{r("Could not open IndexedDB! Upgrade your browser or disable private/incognito mode.")}}))}canSet(e){return Promise.resolve(!0)}get(e){const t=this.database.transaction(["files"],"readonly");return new Promise(((r,i)=>{const s=t.objectStore("files").get(e.toUpperCase());s.onsuccess=e=>{s.result&&s.result.value?r(s.result.value):r(null)},s.onerror=e=>{r(null)}}))}list(e){const t=this.database.transaction(["files"],"readonly");return new Promise(((r,i)=>{const s=t.objectStore("files");if("function"==typeof s.getAllKeys){const t=s.getAllKeys();t.onsuccess=i=>{r(g(t.result,e))},t.onerror=e=>{r([])}}else{var n,o=[];(n="function"==typeof s.openKeyCursor?s.openKeyCursor():s.openCursor()).onsuccess=t=>{var i=t.target.result;i?(o.push(i.key),i.continue()):r(g(o,e))},n.onerror=e=>{r(o)}}}))}set(e,t){const r=this.database.transaction(["files"],"readwrite");return new Promise(((i,s)=>{const n=r.objectStore("files").put({filename:e,value:t});n.onsuccess=e=>{i(!0)},n.onerror=e=>{i(!1)}}))}}function C(e,t){return new v(e,t)}function x(e,t,r){return o(e,r).then((e=>new Promise(((r,i)=>{let s,n={};try{s=UZIP.parse(e.response)}catch(e){return void i(e)}for(var o in s){const e=o;if(t&&t.filenameMapper)if("object"==typeof t.filenameMapper)o=t.filenameMapper[o]||void 0;else if("string"==typeof t.filenameMapper&&t.filenameMapper.length>0){let e=t.filenameMapper.toLowerCase();e.endsWith("/")||(e+="/"),o=o.toLowerCase().startsWith(e)?o.substring(e.length):void 0}else"function"==typeof t.filenameMapper&&(o=t.filenameMapper(o));if(o){if(o.endsWith("/"))continue;o=o.replaceAll("/","\\")}o&&(t&&t.filenameFilter&&!t.filenameFilter(o)||(n[o]=s[e]))}r(C(n,t))}))))}let A,S=C({}),M={};function E(e){A=e}function P(e){S=e}function T(){var e="";window.vfsg_getcwd=function(t,r){if(r>0){var i=0;let n=new Uint8Array(A.HEAPU8.buffer,t,r);for(var s=0;s<e.length&&i<r-1;s++)n[i++]=e.charCodeAt(s);n[i]=0}return 0},window.vfsg_chdir=function(t){if("string"!=typeof t&&(t=A.AsciiToString(t)),t.length>=3&&58==t.charCodeAt(1)&&92==t.charCodeAt(2))return e=t.substring(3),0;if(t.indexOf("\\")>=0){for(i of t.split("\\"))if(vfsg_chdir(i)<0)return-1;return 0}if("."==t)return 0;if(".."==t){let t=e.lastIndexOf("\\");e=t>=0?e.substring(0,t):""}else e.length>0&&(e+="\\"),e+=t;return 0},window.vfsg_open=function(t,r){"string"!=typeof t&&(t=A.AsciiToString(t)),(t=t.toUpperCase()).length>=3&&58==t.charCodeAt(1)&&92==t.charCodeAt(2)?t=t.substring(3):e.length>0&&(t=e+"\\"+t);let i=S.get(t);const s=1==(3&r);if(s){if(!S.canSet(t))return-1;i=null==i||0!=(65536&r)?new Uint8Array(0):Uint8Array.from(i)}else{if(null==i)return-1;i=Uint8Array.from(i)}let n=1;for(;n in M;)n++;return M[n]={fn:t,pos:0,mode:r,write_on_close:s,array:i},n},window.vfsg_close=function(e){return e in M?(M[e].write_on_close&&S.set(M[e].fn,M[e].array),delete M[e],0):-1},window.vfsg_seek=function(e,t,r){if(!(e in M))return-1;let i;switch(r){case 0:i=t;break;case 1:i=M[e].pos+t;break;case 2:i=M[e].array.length+t}return i>M[e].array.length?i=M[e].array.length:i<0&&(i=0),M[e].pos=i,0},window.vfsg_read=function(e,t,r){if(!(e in M))return-1;e=M[e];let i=Math.min(r,e.array.length-e.pos);return new Uint8Array(A.HEAPU8.buffer,t,i).set(e.array.subarray(e.pos,e.pos+i)),e.pos+=i,i},window.vfsg_write=function(e,t,r){if(!(e in M))return-1;let i=(e=M[e]).array.length,s=e.pos+r;if(s>i){var n=new Uint8Array(s);n.set(e.array,0),e.array=n,i=s}let o=new Uint8Array(A.HEAPU8.buffer,t,r);for(var a=0;a<r;a++)e.array[e.pos+a]=o[a];return e.pos+=r,r},window.vfsg_truncate=function(e,t){if(!(e in M))return-1;if((e=M[e]).array.length>t){var r=new Uint8Array(t);r.set(e.array,0),e.array=r}else e.array.length<t&&(e.array=e.array.slice(0,t));return 0};var t=[],r=0;window.vfsg_findfirst=function(i,s,n){n=A.AsciiToString(n),t=[];const o=function(t){if((t=t.toUpperCase()).startsWith("*")){let i=t.substring(1),s=S.list((t=>(0==e.length||t.startsWith(e+"\\"))&&(0==i.length||t.endsWith(i))));e.length>0&&(s=s.map((t=>t.substring(e.length+1))));let n=[],o=[];for(var r of s){let e=r.indexOf("\\");if(e>=0){let t=r.substring(0,e);n.includes(t)||n.push(t)}else o.push(r)}return n=n.sort(((e,t)=>{const r=e.length-t.length;return 0!=r?r:e.localeCompare(t)})).map((e=>({name:e.toUpperCase(),attr:16}))),o=o.sort(((e,t)=>{const r=e.length-t.length;return 0!=r?r:e.localeCompare(t)})).map((e=>({name:e.toUpperCase(),attr:0}))),n.concat(o)}return console.log("unknown findfirst spec: "+t),null}(n);return null==o?-1:(t=o,r=0,vfsg_findnext(i))},window.vfsg_findnext=function(i){if(r>=t.length)return-1;const s=new Uint8Array(A.HEAPU8.buffer,i,256);let n=t[r],o=n.name,a=o;e.length>0&&(a=e+"\\"+a);let h=S.get(a),l=n.attr,u=null==h?0:h.byteLength;s[21]=l,s[22]=0,s[23]=0,s[24]=0,s[25]=0,s[26]=255&u,s[27]=u>>8&255,s[28]=u>>16&255,s[29]=u>>24&255;for(var c=0;c<o.length;c++)s[30+c]=o.charCodeAt(c);return s[30+o.length]=0,r+=1,0}}const U=54.92457871,D=[0,1,2,3,4,5,20,7,56,57,58,59,60,61,62,63];class B{constructor(e,t,r,i,n,o){this.element=e,this.emu=t,this.render=r,this.audio=i,this.vfs=n,this.mouseSensitivity=o&&o.mouseSensitivity||4,this.frameQueued=!1,this.time_ms_cached=s(),this.time_ms_delay=void 0,this.last_timer_time=0,this.opcodes=1e3;const a=this;window.vfsg_time_ms=function(){return a.time_ms_cached},window.vfsg_has_feature=function(e){return 1==e||2==e},window.zetag_update_charset=function(e,i,s){const n=new Uint8Array(t.HEAPU8.buffer,s,256*i);r.setCharset(e,i,n)},window.zetag_update_palette=function(e){const i=new Uint32Array(t.HEAPU32.buffer,e,16);r.setPalette(i)},window.zetag_update_blink=function(e){},window.speakerg_on=function(e,t){document.hasFocus()?null!=i&&i.on(a.time_ms_cached,e,t):speakerg_off()},window.speakerg_off=function(e){null!=i&&i.off(a.time_ms_cached,e)},window.addEventListener("message",(function(e){"zzt_tick"==e.data&&(e.stopPropagation(),a._tick())}),!0);var h=function(e){!0===e.shiftKey?t._zzt_kmod_set(1):!1===e.shiftKey&&t._zzt_kmod_clear(1),!0===e.ctrlKey?t._zzt_kmod_set(4):!1===e.ctrlKey&&t._zzt_kmod_clear(4),!0===e.altKey?t._zzt_kmod_set(8):!1===e.altKey&&t._zzt_kmod_clear(8)};document.addEventListener("keydown",(function(r){if(r.target!=e)return!1;let i=!1;if(h(r),"Shift"==r.key?t._zzt_kmod_set(1):"Control"==r.key?t._zzt_kmod_set(4):"Alt"==r.key||"AltGraph"==r.key?t._zzt_kmod_set(8):i=!1,"F11"==r.key)return t._ui_activate(),r.preventDefault(),!1;let s=1==r.key.length?r.key.charCodeAt(0):p[r.keyCode]||0,n=_[r.key]||0;return 4&t._zzt_kmod_get()&&(s=m[r.key]||0,n=0),n>=70&&n<=83&&(s=0),(s>0||n>0)&&(t._zzt_key(s,n),i=!0),i&&r.preventDefault(),!1}),!1),document.addEventListener("keyup",(function(r){if(r.target!=e)return!1;let i=!0;h(r),"Shift"==r.key?t._zzt_kmod_clear(1):"Control"==r.key?t._zzt_kmod_clear(4):"Alt"==r.key||"AltGraph"==r.key?t._zzt_kmod_clear(8):i=!1;var s=_[r.key]||0;return 4&t._zzt_kmod_get()&&(s=0),t._zzt_keyup(s),i=!0,i&&r.preventDefault(),!1}),!1),this.element.addEventListener("mousemove",(function(e){if(null==t)return;const r=e.movementX*a.mouseSensitivity,i=e.movementY*a.mouseSensitivity;t._zzt_mouse_axis(0,r),t._zzt_mouse_axis(1,i)})),this.element.addEventListener("mousedown",(function(r){e.requestPointerLock(),null!=t&&(0==r.button?t._zzt_mouse_set(0):2==r.button?t._zzt_mouse_set(1):1==r.button&&t._zzt_mouse_set(2))})),this.element.addEventListener("mouseup",(function(e){null!=t&&(0==e.button?t._zzt_mouse_clear(0):2==e.button?t._zzt_mouse_clear(1):1==e.button&&t._zzt_mouse_clear(2))}))}loadCharset(e){const t=this.emu;if("string"==typeof e&&(e=this.vfs.get(e)),"object"==typeof e){if(0!=(255&e.length))return!1;const r=8,i=e.length>>8;if(i<=0||i>16)return!1;let s=!1;return this._u8array2buffer(e,(e=>{s=t._zzt_load_charset(r,i,e,!1)>=0})),s}return!1}_pal_file_append(e,t,r,i){const s=Math.floor(255*t[r]/i),n=Math.floor(255*t[r+1]/i),o=Math.floor(255*t[r+2]/i);e.push(o,n,s,0)}loadPalette(e){const t=this.emu;let r=[];if("string"==typeof e){let t="pal";e.toLowerCase().endsWith(".pld")&&(t="pld");const s=this.vfs.get(e);if(null==s)return!1;if("pld"==t){if(s.length<192)return!1;for(var i=0;i<16;i++)this._pal_file_append(r,s,3*D[i],63)}else{if(s.length<48)return!1;for(i=0;i<16;i++)this._pal_file_append(r,s,3*i,63)}}else if("object"==typeof e){const t=e.min||0,s=e.max||255;if(null==e.colors||e.colors.length<16)return console.warn("[zeta.loadPalette] missing or too small colors array"),!1;for(i=0;i<16;i++){const n=e.colors[i];if("string"==typeof n&&n.startsWith("#"))if(7==n.length){const e=parseInt(n.substring(1,3),16),t=parseInt(n.substring(3,5),16),i=parseInt(n.substring(5,7),16);r.push(i,t,e,0)}else{if(4!=n.length)return console.warn("[zeta.loadPalette] invalid color string length: "+n.length),!1;{const e=17*parseInt(n.substring(1,2),16),t=17*parseInt(n.substring(2,3),16),i=17*parseInt(n.substring(3,4),16);r.push(i,t,e,0)}}else{if(!("object"==typeof n&&n.length>=3))return console.warn("[zeta.loadPalette] invalid color type @ "+i),!1;{const n=Math.floor(255*(e.colors[i][0]-t)/(s-t)),o=Math.floor(255*(e.colors[i][1]-t)/(s-t)),a=Math.floor(255*(e.colors[i][2]-t)/(s-t));r.push(a,o,n,0)}}}}if(64==r.length){let e=!1;return this._u8array2buffer(r,(r=>{e=t._zzt_load_palette(r)>=0})),e}return!1}setBlinkCycleDuration(e){return this.render.setBlinkCycleDuration(e),!0}setVolume(e){return this.audio.setVolume(e),!0}getFile(e){return this.vfs.get(e)}listFiles(){return this.vfs.list()}_frame(){this._pollGamepads();const e=this.emu._zzt_get_ram(),t=new Uint8Array(this.emu.HEAPU8.buffer,e+753664,4e3);this.render.render(t,this.emu._zzt_video_mode(),this.time_ms_cached),this.emu._zzt_mark_frame(),this.frameQueued=!1}_resetLastTimerTime(){this.last_timer_time=s()}_tick(){for(this.time_ms_cached=s();this.time_ms_cached-this.last_timer_time>=U;)this.last_timer_time+=U,this.emu._zzt_mark_timer();const e=this.emu._zzt_execute(this.opcodes),t=s()-this.time_ms_cached;if(0!=e){t<5&&1==e?this.opcodes=20*this.opcodes/19:t>10&&this.opcodes>=1050&&(this.opcodes=19*this.opcodes/20),this.frameQueued||(this.frameQueued=!0,window.requestAnimationFrame((()=>this._frame())));const r=U-(this.time_ms_cached+t-this.last_timer_time);e<3||r<=1?window.postMessage("zzt_tick","*"):e>=5?setTimeout((()=>this._tick()),Math.min(e-5,r)):4==e||r<20?setTimeout((()=>this._tick()),r):window.requestAnimationFrame((()=>this._tick()))}else r(this.render.canvas,this.render.ctx,"Emulation stopped.")}_pollGamepads(){if(!navigator.getGamepads||"function"!=typeof navigator.getGamepads)return;const e=navigator.getGamepads();for(var t=0;t<e.length;t++){const i=e[t];if(null!=i&&i.axes.length>=2&&i.buttons.length>=1){const e=Math.round(127*i.axes[0]),t=Math.round(127*i.axes[1]);this.emu._zzt_joy_axis(0,e),this.emu._zzt_joy_axis(1,t);let s=!1;for(var r=0;r<i.buttons.length;r++)if(i.buttons[r].pressed){s=!0;break}s?this.emu._zzt_joy_set(0):this.emu._zzt_joy_clear(0)}}}_u8array2buffer(e,t){const r=this.emu._malloc(e.length),i=new Uint8Array(this.emu.HEAPU8.buffer,r,e.length);for(var s=0;s<e.length;s++)i[s]=e[s];t(r),this.emu._free(r)}_str2buffer(e,t){const r=this.emu._malloc(e.length+1),i=new Uint8Array(this.emu.HEAPU8.buffer,r,e.length+1);for(var s=0;s<e.length;s++){var n=e.charCodeAt(s);i[s]=n>=127?0:n}i[e.length]=0,t(r),this.emu._free(r)}}const W="1.0.6";class H{constructor(e,t,r,i){this.canvas=e,this.ctx=t,this.loaded=!1,this.path=i.path}_drawBackground(){const e=this;return new Promise(((t,r)=>{const i=new Image;i.onload=function(){const r=W,s=i.width,n=i.height;e.ctx.drawImage(i,0,0,s,n,(e.canvas.width-2*s)/2,(e.canvas.height-2*n)/2,2*s,2*n),e.ctx.font="16px sans-serif",e.ctx.fillStyle="#aaaaaa",e.ctx.textBaseline="bottom",e.ctx.fillText(r,(e.canvas.width+2*s)/2-6-e.ctx.measureText(r).width,(e.canvas.height+2*n)/2-6),e.loaded=!0,t(!0)},i.src=e.path+"loading.png"}))}progress(e){if(!this.loaded)return;const t=this.canvas,r=this.ctx,i=(t.width-640)/2,s=(t.height-350)/2;r.fillStyle="#ff0000",r.fillRect(i+28,s+224,292*e*2,20)}}window.ZetaInitialize=function(e,t){if(console.log(" _ \n _______| |_ __ _ \n|_ / _ \\ __/ _` |\n / / __/ || (_| |\n/___\\___|\\__\\__,_|\n\n "+W),!e.render)throw new Error("Missing option: render!");if(!e.render.canvas)throw new Error("Missing option: render.canvas!");const i=e.render.canvas;i.contentEditable=!0;const s=i.getContext("2d",{alpha:!1});s.imageSmoothingEnabled=!1;try{if(!e.path)throw new Error("Missing option: path!");if(!e.files)throw new Error("Missing option: files!")}catch(e){return r(i,s,e),Promise.reject(e)}const u=new H(i,s,W,e);var c=[],f=[],d=[];try{for(var _ in e.files)f.push(0),function(t,r){const i=function(r){f[t]=Math.min(r,1),u.progress(f.reduce(((e,t)=>e+t))/e.files.length)};var s=r;if(!s.hasOwnProperty("type"))throw new Error("Missing option: files.type!");if(s.hasOwnProperty("readonly")||(s.readonly=!0),s.hasOwnProperty("ignoreCase")||(s.ignoreCase="upper"),s.use83Names=!0,"zip"==s.type){if(!s.hasOwnProperty("url"))throw new Error("Missing option: files.url!");c.push(x(s.url,s,i).then((e=>d.push(e))))}else if("array"==s.type){if(!s.hasOwnProperty("filename"))throw new Error("Missing option: files.filename!");if(!s.hasOwnProperty("data"))throw new Error("Missing option: files.data!");var n={};n[s.filename]=new Uint8Array(s.data),d.push(C(n,s))}else if("file"==s.type){if(!s.hasOwnProperty("url"))throw new Error("Missing option: files.url!");if(!s.hasOwnProperty("filename"))throw new Error("Missing option: files.filename!");c.push(o(s.url,i).then((e=>{var t={};t[s.filename]=new Uint8Array(e.response),d.push(C(t,s))})))}}(f.length-1,e.files[_])}catch(e){return r(i,s,e),Promise.reject(e)}u._drawBackground().then((e=>Promise.all(c))).then((t=>{var r=!1;if(e.storage&&"auto"==e.storage.type&&(r=!0,null!=n()?e.storage.type="indexeddb":null!=function(){try{return window.localStorage}catch(e){return}}()?e.storage.type="localstorage":(console.log("Browser does not support any form of local storage! Storing to memory..."),e.storage=void 0)),e.storage&&e.storage.type){var i=null;if("indexeddb"==e.storage.type){if(!e.storage.database)throw new Error("Missing option: storage.database!");i=function(e){const t=n();if(!t)return Promise.reject("IndexedDB not supported!");const r=new k(t,e);return r._open().then((e=>r))}("zeta_"+e.storage.database).then((e=>function(e,t){const r=new z(e,t);return r._populate().then((e=>r))}(e,{ignoreCase:"upper"}))).then((e=>d.push(e)))}else{if("localstorage"!=e.storage.type)throw new Error("Unknown storage type: "+e.storage.type);i=new Promise((t=>{if(!e.storage.database)throw new Error("Missing option: storage.database!");let r=window.localStorage;if(e.storage.storage&&(r=e.storage.storage),null==r)throw new Error("Could not find storage object!");return d.push(function(e,t,r){return new b(e,t,r)}(r,"zeta_"+e.storage.database,{ignoreCase:"upper"})),!0}))}return r&&(i=i.catch((t=>(console.log("Browser failed to initialize local storage (type "+e.storage.type+", reason: "+t+"). Storing to memory..."),d.push(C({},{readonly:!1,ignoreCase:"upper"})),!0)))),i}return d.push(C({},{readonly:!1,ignoreCase:"upper"})),!0})).then((r=>{let n,o;s.fillStyle="#000000",s.fillRect(0,0,i.width,i.height),e&&e.render&&e.render.type,n=t=>new l(t,e.render.canvas,e.render),o="oscillator"==(e&&e.audio&&e.audio.type||"auto")?t=>new a(e.audio):t=>new h(t,e.audio);const u=function(e,t){return new y(e,t)}(d);return function(e,t,r,i){return new Promise((s=>{ZetaNative().then((n=>{P(r),E(n),T();const o=new B(i.render.canvas,n,e(n),t(n),r,i);if(n._zzt_init(i&&i.engine&&i.engine.memory_limit||-1),n._zzt_set_max_extended_memory(i&&i.engine&&i.engine.extended_memory_limit||-1),n._zzt_set_timer_offset(Date.now()%864e5),o.render.setBlinkCycleDuration(i&&i.render&&i.render.blink_cycle_duration||.534),o.render.setBlinkEnabled(n._zzt_get_blink_duration_ms()>0),i&&i.commands){const e=i.commands.length-1;for(var a=0;a<=e;a++){let t=i.commands[a];"string"==typeof t?t=[t,""]:1==t.length&&(t=[t[0],""]);let r=vfsg_open(t[0].toLowerCase(),0);if(r<0)throw new Error("Could not find executable "+t[0]+" (command #"+(a+1)+")!");if(o._str2buffer(t[1],(e=>{n._zzt_load_binary(r,e)})),vfsg_close(r),console.log("executing "+t[0]+" "+t[1]),a<e)for(;0!=n._zzt_execute(1e4););}}else{let e="zzt.exe",t=vfsg_open(e,0),s=".zzt";if(t<0&&(e="superz.exe",t=vfsg_open(e,0),s=void 0),t<0)throw new Error("Could not find ZZT/Super ZZT executable!");let a="";if(i&&i.arg)a=i.arg;else if(null!=s){const e=r.list((e=>e.toLowerCase().endsWith(s)));e.length>0&&(a=e[0])}o._str2buffer(a,(e=>{n._zzt_load_binary(t,e)})),vfsg_close(t),console.log("executing "+e+" "+a)}i&&i.engine&&(i.engine.charset&&(o.loadCharset(i.engine.charset)?n._zzt_set_lock_charset(i.engine.lock_charset):console.error("Could not load charset from options!")),i.engine.palette&&(o.loadPalette(i.engine.palette)?n._zzt_set_lock_palette(i.engine.lock_palette):console.error("Could not load palette from options!"))),o._resetLastTimerTime(),o._tick(),i&&i.engine&&i.engine.skip_kc&&(n._zzt_key(107,37),n._zzt_keyup(37),n._zzt_key(99,46),n._zzt_keyup(46),n._zzt_key(13,28),n._zzt_keyup(28)),s(o)}))}))}(n,o,u,e).then((e=>(null!=t&&t(e),e)))})).then((e=>!0)).catch((e=>{t(void 0,e),r(i,s,e)}))}}();