From d68b0f8f2dcaa073c486cf7256e8ed4f4ec255b2 Mon Sep 17 00:00:00 2001 From: sehugg Date: Sun, 6 Sep 2026 08:56:15 +0000 Subject: [PATCH] =?UTF-8?q?Deploying=20to=20gh-pages=20from=20@=20sehugg/8?= =?UTF-8?q?bitworkshop@e576c4ec87aacf278e2cd5ef6390033c2997f634=20?= =?UTF-8?q?=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gen/astrocade-HHSBZP55.js | 14 ++ gen/astrocade-HHSBZP55.js.map | 7 + gen/astrocade-SQ7A55O6.js | 14 -- gen/astrocade-SQ7A55O6.js.map | 7 - gen/{basic-WBBOCYX7.js => basic-DESTZ5TS.js} | 4 +- ...-WBBOCYX7.js.map => basic-DESTZ5TS.js.map} | 0 gen/chunk-PUOMI72S.js.map | 7 - gen/{chunk-WEPPO4GD.js => chunk-THWBEUY4.js} | 4 +- ...-WEPPO4GD.js.map => chunk-THWBEUY4.js.map} | 0 gen/{chunk-PUOMI72S.js => chunk-X3GW3E7W.js} | 6 +- gen/chunk-X3GW3E7W.js.map | 7 + gen/common/toolmeta.js | 4 +- gen/common/toolmeta.js.map | 2 +- gen/common/wasi/wasishim.js | 27 +++ gen/common/wasi/wasishim.js.map | 2 +- gen/{devel-MXNMHFEG.js => devel-62JTH7LV.js} | 4 +- ...-MXNMHFEG.js.map => devel-62JTH7LV.js.map} | 0 gen/embedui.js | 2 +- gen/machine/astrocade.js | 96 +++++++--- gen/machine/astrocade.js.map | 2 +- gen/src/common/toolmeta.js | 4 +- gen/src/common/toolmeta.js.map | 2 +- gen/src/common/wasi/wasishim.js | 27 +++ gen/src/common/wasi/wasishim.js.map | 2 +- gen/src/machine/astrocade.js | 96 +++++++--- gen/src/machine/astrocade.js.map | 2 +- gen/src/tools/nodemock.js | 1 + gen/src/tools/nodemock.js.map | 2 +- gen/src/worker/platforms.js | 3 +- gen/src/worker/platforms.js.map | 2 +- gen/src/worker/tools/acme.js | 54 ++++-- gen/src/worker/tools/acme.js.map | 2 +- gen/src/worker/tools/z80.js | 51 ++++-- gen/src/worker/tools/z80.js.map | 2 +- gen/tools/nodemock.js | 1 + gen/tools/nodemock.js.map | 2 +- gen/ui.js | 2 +- gen/worker/bundle.js | 168 ++++++++++++------ gen/worker/bundle.js.map | 6 +- gen/worker/platforms.js | 3 +- gen/worker/platforms.js.map | 2 +- gen/worker/tools/acme.js | 54 ++++-- gen/worker/tools/acme.js.map | 2 +- gen/worker/tools/z80.js | 51 ++++-- gen/worker/tools/z80.js.map | 2 +- presets/c64/skeleton.oscar64 | 20 +++ presets/coleco/common.c | 45 ++++- presets/coleco/common.h | 43 ++++- presets/sms-sms-libcv/common.c | 126 +------------ presets/sms-sms-libcv/common.h | 69 +------ src/common/toolmeta.ts | 4 +- src/common/wasi/wasishim.ts | 22 +++ src/machine/astrocade.ts | 102 ++++++++--- src/tools/nodemock.ts | 1 + src/worker/platforms.ts | 4 +- src/worker/tools/acme.ts | 60 ++++--- src/worker/tools/z80.ts | 57 +++--- src/worker/wasm/acme.js | 21 --- src/worker/wasm/acme.wasm | Bin 100249 -> 137375 bytes src/worker/wasm/zmac.js | 18 -- src/worker/wasm/zmac.wasm | Bin 237594 -> 497878 bytes tss/js/Log.js | 7 +- 62 files changed, 821 insertions(+), 530 deletions(-) create mode 100644 gen/astrocade-HHSBZP55.js create mode 100644 gen/astrocade-HHSBZP55.js.map delete mode 100644 gen/astrocade-SQ7A55O6.js delete mode 100644 gen/astrocade-SQ7A55O6.js.map rename gen/{basic-WBBOCYX7.js => basic-DESTZ5TS.js} (99%) rename gen/{basic-WBBOCYX7.js.map => basic-DESTZ5TS.js.map} (100%) delete mode 100644 gen/chunk-PUOMI72S.js.map rename gen/{chunk-WEPPO4GD.js => chunk-THWBEUY4.js} (96%) rename gen/{chunk-WEPPO4GD.js.map => chunk-THWBEUY4.js.map} (100%) rename gen/{chunk-PUOMI72S.js => chunk-X3GW3E7W.js} (98%) create mode 100644 gen/chunk-X3GW3E7W.js.map rename gen/{devel-MXNMHFEG.js => devel-62JTH7LV.js} (95%) rename gen/{devel-MXNMHFEG.js.map => devel-62JTH7LV.js.map} (100%) create mode 100644 presets/c64/skeleton.oscar64 mode change 100644 => 120000 presets/sms-sms-libcv/common.c mode change 100644 => 120000 presets/sms-sms-libcv/common.h delete mode 100644 src/worker/wasm/acme.js delete mode 100644 src/worker/wasm/zmac.js diff --git a/gen/astrocade-HHSBZP55.js b/gen/astrocade-HHSBZP55.js new file mode 100644 index 00000000..255695e9 --- /dev/null +++ b/gen/astrocade-HHSBZP55.js @@ -0,0 +1,14 @@ +import{K as D0,c as l0,d as m0,e as u0,k as h0,r as E0}from"./chunk-CZ7OSHSE.js";import{$ as x0,K as k,W as A,X as C0,Z as X0,aa as N,g,l as c0,m as B0,t as g0}from"./chunk-TYDI7JZQ.js";import"./chunk-KT7KMEQC.js";var I0=X0([[A.UP,16,1],[A.DOWN,16,2],[A.LEFT,16,4],[A.RIGHT,16,8],[A.A,16,16],[A.P2_UP,17,1],[A.P2_DOWN,17,2],[A.P2_LEFT,17,4],[A.P2_RIGHT,17,8],[A.P2_A,17,16],[A.VK_P,20,1],[A.VK_SLASH,20,2],[A.VK_X,20,4],[A.VK_MINUS,20,8],[A.VK_COMMA,20,16],[A.VK_EQUALS,20,32],[A.VK_O,21,1],[A.VK_L,21,2],[A.VK_9,21,4],[A.VK_6,21,8],[A.VK_3,21,16],[A.VK_PERIOD,21,32],[A.VK_I,22,1],[A.VK_K,22,2],[A.VK_8,22,4],[A.VK_5,22,8],[A.VK_2,22,16],[A.VK_0,22,32],[A.VK_U,23,1],[A.VK_J,23,2],[A.VK_7,23,4],[A.VK_4,23,8],[A.VK_1,23,16],[A.VK_BACK_SLASH,23,32]]),P0=2,R0=function(d){var f,t,i,o,U,X,W,i0,J;let G=d?320:160,K=d?204:102,s0=G>>2,b0=d?16383:4095,H0=256,v0=4293848814,y0=4278190080,p0=d?3:1,w0=.7;var n0=0,j=new Uint8Array(32),c=0,D=0,m=!1,Y=0,b=0,p=0,V=0,w=0,Q=K,T=new Uint32Array(8),H=new Uint8Array(8),Z=0,v=new Uint8Array(d?262:131),u=new Uint8Array(4),h=0,S=0,l=0,L=0,B=new Uint8Array(8),M=0;function Q0(){return f.scanline=(b&63)?0:4;i0[s--]=T[E+(x&3)],x>>=2}}function a0(e){for(var x=e*G/4,s=0;s>=4);for(var n=0;n<4;n++){var E=x&1?D>>2&3:D&3;s|=E<>=1}x=s,m=!m}if(c&4){if(h&4){var a=2*(~h&3);x=(u[3]>>a&3)<<6|(u[2]>>a&3)<<4|(u[1]>>a&3)<<2|(u[0]>>a&3)<<0}else u[h&3]=x;h++}else{var a=(c&3)<<1,s=x>>a|Y;Y=x<<8-a&255,x=s}if(c&64&&(x=(x&3)<<6|(x&12)<<2|(x&48)>>2|(x&192)>>6),c&48){var F=i[e],r=0;F&192&&x&192&&(r|=1),F&48&&x&48&&(r|=2),F&12&&x&12&&(r|=4),F&3&&x&3&&(r|=8),c&16&&(x|=F),c&32&&(x^=F),S=S&240|r|r<<4}y(e,x)}function _(e,x){H[e&7]=x&255,T[e&7]=F0[x&255],O()}function M0(){var e=b>>6}function O(){Z=K}function V0(){let e=B[0]|B[1]<<8,x=B[2]&63,s=B[3],n=M&255|B[4]<<8,E=B[5],a=B[6]+1,F,r=0,C=0,N0=l;r=0,(x&2)===0&&(r=1);function f0(){r&&(x&4)!==0&&(F!==0||(x&8)===0)&&e++,(x&2)!==0&&(r^=1)}function o0(){F!==0&&((x&32)!==0?n++:n--)}for(;a>=0;){let q;for(F=E;F>=0;){let $,e0;$=(x&1)===0?e:n,F===0&&(x&8)!==0?e0=0:e0=o.read(e),(x&1)===0?f0():o0(),$=(x&1)!==0?e:n,y($,e0),(x&1)===0?o0():f0(),C+=4,F--}q=(n&255)+s&256,n=n&65280|n+s&255,(x&16)===0?n+=q:n-=q^256,a--}l=N0+C}this.drawScanline=e=>{e==V&&p&8&&(t.retryInterrupts=!(p&4),this.probe&&this.probe.logInterrupt(w),t.interrupt(w)),e0?(v[e]=0,a0(e),Z--):v[e]&&(v[e]=0,a0(e))},this.init=(e,x,s,n,E)=>{f=e,n0=e.cpuCyclesPerLine*w0,t=x,i=s,j=n,J=E,d?o={read:N([[16384,32767,16383,function(F){return z(),i[F]}],[53248,57343,4095,function(F){return i[F+16384]}],[0,16383,16383,function(F){return X?X[F]:0}],[32768,49151,16383,function(F){return X?X[F+16384]:0}]]),write:N([[16384,32767,16383,y],[0,16383,16383,d0],[53248,57343,4095,function(F,r){i[F+16384]=r}]])}:(W=x0(new c0().decode(B0(atob(G0))),8192),o={read:N([[0,8191,8191,function(F){return W[F]}],[8192,16383,8191,function(F){return X?X[F]:0}],[16384,20479,4095,function(F){return z(),i[F]}]]),write:N([[16384,20479,4095,y],[0,16383,4095,d0]])}),U={read:function(F){F&=31;var r;switch(F){case 8:r=S,S=0;break;default:r=j[F];break}return r},write:function(F,r){if(F!=42331){if(F&=255,F>120&&F<128){B[F&7]=r,F==114&&(M=0),F==116&&(M=M+B[3]&255),F==126&&V0();return}switch(F&=31,r&=255,F){case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7:_(F,r);break;case 9:b=r,M0(),O();break;case 10:Q=d?r:r>>1,O();break;case 11:var C=t.saveState();_((C.BC>>8)-1,o.read(C.HL));break;case 12:c=r,Y=0,h=0,m=!1;break;case 13:w=r;break;case 14:p=r;break;case 15:V=d?r:r>>1;break;case 16:case 17:case 18:case 19:case 20:case 21:case 22:case 23:J.setACRegister(F,r);break;case 24:var C=t.saveState();J.setACRegister((C.BC>>8)-1,o.read(C.HL));break;case 25:D=r;break;case 26:case 27:case 28:case 29:case 30:break;default:break}}}},e.connectCPUMemoryBus(o),e.connectCPUIOBus(U),this.membus=o,this.iobus=U;for(var a=0;a<8;a++)_(a,a)},this.resetWaitStates=function(){var e=l;return l=0,e},this.peek=function(e){var x=l,s=o.read(e);return l=x,s},this.loadState=e=>{t.loadState(e.c),i.set(e.ram),T.set(e.palette),H.set(e.palinds),c=e.magicop,D=e.xpand,m=e.xplower,Y=e.shift2,b=e.horcb,p=e.inmod,V=e.inlin,w=e.infbk,Q=e.verbl,h=e.rotcount,u.set(e.rotdata),S=e.intst,L=e.slotphase|0,j.set(e.inputs),B.set(e.patboard),M=e.patdest,O()},this.saveState=()=>({c:t.saveState(),ram:i.slice(0),inputs:j.slice(0),palette:T.slice(0),palinds:H.slice(0),magicop:c,xpand:D,xplower:m,shift2:Y,horcb:b,inmod:p,inlin:V,infbk:w,verbl:Q,rotcount:h,rotdata:u.slice(0),intst:S,slotphase:L,patboard:B.slice(0),patdest:M}),this.reset=()=>{c=D=p=V=w=Y=b=0,Q=K,m=!1},this.toLongString=e=>{var x="";x+=` + INLIN: `+e.inlin,x+=` + VERBL: `+e.verbl,x+=` +MAGICOP: $`+g(e.magicop),x+=` + XPAND: $`+g(e.xpand),x+=` +XPLOWER: `+e.xplower,x+=` + SHIFT2: $`+g(e.shift2),x+=` + HORCB: $`+g(e.horcb),x+=` + INMOD: $`+g(e.inmod),x+=` + INFBK: $`+g(e.infbk),x+=` + INTST: $`+g(e.intst),x+=` +Palette: `;for(var s=0;s<8;s++)x+=g(H[s]);return x+=` +`,x},this.connectVideo=function(e){i0=e},this.loadROM=function(e){X=e},this.loadBIOS=function(e){W=e},this.getVisiblePixelWords=function(){return Q*G}},P=class extends E0{constructor(t){super();this.cpuFrequency=1789e3;this.arcade=t,this.cpu=new l0,this.psg=new t0(new m0),this.numTotalScanlines=t?262:131;var i=P0*(t?1:2);this.sampleRate=60*this.numTotalScanlines*i,this.audioadapter=new h0(this.psg.psg,i,this.sampleRate),this.handler=C0(this.inputs,I0),this.defaultROMSize=t?45056:8192,this.ram=new Uint8Array(t?20480:4096),this.numVisibleScanlines=t?204:102,this.canvasWidth=t?320:160,this.cpuCyclesPerLine=this.cpuFrequency/(60*this.numVisibleScanlines*1.286)|0,this.m=new R0(t),this.m.init(this,this.cpu,this.ram,this.inputs,this.psg),t&&(this.inputs[16]=255,this.inputs[17]=255,this.inputs[18]=0,this.inputs[19]=8)}read(t){return this.m.peek(t)}write(t,i){this.m.membus.write(t,i)}connectVideo(t){super.connectVideo(t),this.frontbuffer=t,this.backbuffer=new Uint32Array(t.length),this.m.connectVideo(this.backbuffer)}preFrame(){this.m.resetWaitStates()}postFrame(){var t=this.m.getVisiblePixelWords();this.frontbuffer.set(this.backbuffer.slice(0,t),0),this.frontbuffer.fill(0,t)}setPaddleInput(t,i){switch(t){case 0:this.inputs[28]=i&255;break;case 1:this.inputs[29]=i&255;break}}startScanline(){this.audio&&this.audioadapter.generate(this.audio)}drawScanline(){var t=this.scanline;this.m.drawScanline(t)}advanceCPU(){var t=super.advanceCPU(),i=this.m.resetWaitStates();return i&&(t+=i,this.probe.logClocks(i)),t}loadROM(t){super.loadROM(t),this.m.loadROM(this.rom),this.reset()}loadBIOS(t){this.m.loadBIOS(x0(t,8192)),this.reset()}reset(){super.reset(),this.m.reset()}loadState(t){this.m.loadState(t)}saveState(){return this.m.saveState()}getDebugCategories(){return["CPU","Stack","Astro"]}getDebugInfo(t,i){switch(t){case"Astro":return this.m.toLongString(i)}}getRasterCanvasPosition(){return{x:this.getRasterX(),y:this.getRasterY()}}getVideoParams(){return this.arcade?{width:320,height:204,rotate:180}:{width:160,height:102}}},t0=class extends u0{setACRegister(f,t){switch(f&=7,t&=255,f){case 0:this.psg.setClock(1789e3*16/(t+1)),this.psg.writeRegisterAY(7,248);break;case 1:case 2:case 3:var i=(f-1)*2,o=t*2+1;this.psg.writeRegisterAY(i,o&255),this.psg.writeRegisterAY(i+1,o>>8&255);break;case 5:this.psg.writeRegisterAY(10,t&15);break;case 6:this.psg.writeRegisterAY(8,t&15),this.psg.writeRegisterAY(9,t>>4&15);break}}},F0=[0,2368548,4737096,7171437,9539985,11974326,14342874,16777215,2425019,4784352,7213567,9582079,12016383,14384895,16753663,16762879,4784304,7143637,9568761,11937279,14306047,16740095,16749311,16758783,6946975,9306307,11731175,14096639,16465151,16736767,16745983,16755199,8847495,11206827,13631696,15994612,16724735,16733951,16743423,16752639,10420330,12779662,15138995,16713687,16723195,16732415,16741631,16751103,11534409,13959277,16318610,16713142,16722394,16731647,16741119,16750335,12255269,14680137,16711790,16713362,16722615,16732123,16741375,16750847,12517376,14876708,16711752,16714605,16724113,16733366,16742874,16752127,12255232,14680064,16711715,16716871,16726380,16735632,16745141,16754393,11534336,13959168,16318464,16720164,16729416,16738924,16748177,16757685,10420224,12779520,15141888,16723971,16733479,16742731,16752240,16761492,8847360,11206656,13639168,16007680,16738058,16747310,16756563,16766071,6946816,9309440,11743488,14112256,16480768,16752151,16761659,16770911,4784128,7151872,9585920,11954688,14323200,16757509,16766761,16776270,2429184,4797696,7232e3,9600512,12034816,14403328,16771870,16777027,9472,2377984,4746496,7180800,9549312,11983616,14352155,16777023,14080,23296,2326528,4695040,7129344,9497856,11927326,14286659,18176,27648,36864,2405376,4774144,7142661,9568041,11927374,21760,30976,40192,246272,2614784,4980503,7405371,9764703,24320,33536,43008,52224,716810,3079982,5504851,7864183,25856,35328,44544,53763,63271,1572683,3932016,6291348,26624,35840,45312,54564,63816,393068,2752401,5177269,26112,35584,44835,54343,63596,65424,2031541,4456409,24832,34084,43592,52845,62353,65462,1834970,4194302,22565,31817,41326,50578,60087,65499,2031615,4456447,19273,28781,38034,47542,56794,393215,2752511,5177343,15466,24718,34227,43479,52987,1569535,3932159,6291455,10887,20395,29648,38900,703743,3072255,5505023,7864319,6047,15299,24807,230655,2599167,4967935,7401983,9764863,688,10197,19449,2388223,4756735,7125503,9559551,11927551,187,5088,2308095,4676607,7110911,9479423,11913727,14282239];for(I=0;I<256;I++)Y0=F0[I],F0[I]=g0(Y0)|4278190080;var Y0,I;var G0="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";var K0=[{id:"01-helloworlds.asm",name:"Hello World (ASM)"},{id:"02-telephone.asm",name:"Telephone (ASM)"},{id:"03-horcbpal.asm",name:"Paddle Demo (ASM)"},{id:"hello.c",name:"Hello Graphics"},{id:"lines.c",name:"Lines"},{id:"sprites.c",name:"Sprites"},{id:"vsync.c",name:"Sprites w/ VSYNC"},{id:"fastsprites.c",name:"Fast Sprites"},{id:"music.c",name:"Music"},{id:"rotate.c",name:"Rotate Op"},{id:"rainbow.c",name:"Rainbow"},{id:"cosmic.c",name:"Cosmic Impalas Game"},{id:"racing.c",name:"Pseudo 3-D Racing Game"}],j0=[{id:"bios.c",name:"BIOS"}],T0=[{id:"hello.c",name:"Hello Graphics"}],R=class extends D0{constructor(){super(...arguments);this.getMemoryMap=function(){return{main:[{name:"BIOS",start:0,size:8192,type:"rom"},{name:"Screen RAM",start:16384,size:4096,type:"ram"},{name:"BIOS Variables",start:20430,size:50,type:"ram"}]}}}newMachine(){return new P(!1)}getPresets(){return K0}readAddress(t){return this.machine.read(t)}showHelp(){return"https://8bitworkshop.com/docs/platforms/astrocade/"}},A0=class extends R{getPresets(){return j0}loadROM(f,t){this.machine.loadBIOS(t)}},r0=class extends R{constructor(){super(...arguments);this.getMemoryMap=function(){return{main:[{name:"ROM",start:0,size:16384,type:"rom"},{name:"Magic RAM",start:0,size:16384,type:"ram"},{name:"Screen RAM",start:16384,size:16384,type:"ram"},{name:"ROM",start:32768,size:16384,type:"rom"}]}}}newMachine(){return new P(!0)}getPresets(){return T0}};k.astrocade=R;k["astrocade-bios"]=A0;k["astrocade-arcade"]=r0; +//# sourceMappingURL=astrocade-HHSBZP55.js.map diff --git a/gen/astrocade-HHSBZP55.js.map b/gen/astrocade-HHSBZP55.js.map new file mode 100644 index 00000000..d0d52324 --- /dev/null +++ b/gen/astrocade-HHSBZP55.js.map @@ -0,0 +1,7 @@ +{ + "version": 3, + "sources": ["../src/machine/astrocade.ts", "../src/platform/astrocade.ts"], + "sourcesContent": ["\nimport { Z80, Z80State } from \"../common/cpu/ZilogZ80\";\nimport { BasicScanlineMachine, AcceptsPaddleInput, Bus } from \"../common/devices\";\nimport { KeyFlags, newAddressDecoder, padBytes, Keys, makeKeycodeMap, newKeyboardHandler } from \"../common/emu\";\nimport { TssChannelAdapter, MasterAudio, AY38910_Audio } from \"../common/audio\";\nimport { hex, rgb2bgr, lzgmini, stringToByteArray } from \"../common/util\";\n\n// http://metopal.com/projects/ballybook/doku.php\n\n// TODO: fix keys, more controllers, vibrato/noise, border color\n// http://atariage.com/forums/topic/251416-programming-the-bally-arcadeastrocade/\n// https://ballyalley.com/faqs/BPA%20Video%20Hardware%20FAQ/Bally_Professional_Arcade_Video_Hardware%20(2001)(Tony%20Miller).pdf\n// https://atariage.com/forums/topic/290858-notes-from-a-2019-interview-with-jamie-fenton/ (http://www.fentonia.com/bio/)\n// https://thehistoryofhowweplay.wordpress.com/2018/04/03/interview-tom-mchugh/\n// https://ballyalley.com/faqs/Programmers%20of%20the%20Astrocade%20Built-In%20Programs.txt\n\nconst ASTROCADE_KEYCODE_MAP = makeKeycodeMap([\n // player 1\n [Keys.UP, 0x10, 0x1],\n [Keys.DOWN, 0x10, 0x2],\n [Keys.LEFT, 0x10, 0x4],\n [Keys.RIGHT, 0x10, 0x8],\n [Keys.A, 0x10, 0x10],\n // player 2\n [Keys.P2_UP, 0x11, 0x1],\n [Keys.P2_DOWN, 0x11, 0x2],\n [Keys.P2_LEFT, 0x11, 0x4],\n [Keys.P2_RIGHT, 0x11, 0x8],\n [Keys.P2_A, 0x11, 0x10],\n // keypad $14\n [Keys.VK_P, 0x14, 0x1],\n [Keys.VK_SLASH, 0x14, 0x2],\n [Keys.VK_X, 0x14, 0x4],\n [Keys.VK_MINUS, 0x14, 0x8],\n [Keys.VK_COMMA, 0x14, 0x10],\n [Keys.VK_EQUALS, 0x14, 0x20],\n // keypad $15\n [Keys.VK_O, 0x15, 0x1],\n [Keys.VK_L, 0x15, 0x2],\n [Keys.VK_9, 0x15, 0x4],\n [Keys.VK_6, 0x15, 0x8],\n [Keys.VK_3, 0x15, 0x10],\n [Keys.VK_PERIOD, 0x15, 0x20],\n // keypad $16\n [Keys.VK_I, 0x16, 0x1],\n [Keys.VK_K, 0x16, 0x2],\n [Keys.VK_8, 0x16, 0x4],\n [Keys.VK_5, 0x16, 0x8],\n [Keys.VK_2, 0x16, 0x10],\n [Keys.VK_0, 0x16, 0x20],\n // keypad $17\n [Keys.VK_U, 0x17, 0x1],\n [Keys.VK_J, 0x17, 0x2],\n [Keys.VK_7, 0x17, 0x4],\n [Keys.VK_4, 0x17, 0x8],\n [Keys.VK_1, 0x17, 0x10],\n [Keys.VK_BACK_SLASH, 0x17, 0x20],\n]);\n\nconst audioOversample = 2;\n\nconst _BallyAstrocade = function(arcade:boolean) {\n\n var machine : BallyAstrocade;\n var cpu : Z80;\n var ram : Uint8Array;\n var membus, iobus : Bus;\n var rom, bios;\n var pixels;\n var psg;\n //var watchdog_counter;\n const swidth = arcade ? 320 : 160;\n const sheight = arcade ? 204 : 102;\n const swbytes = swidth >> 2;\n const samask = arcade ? 0x3fff : 0xfff;\n const INITIAL_WATCHDOG = 256;\n const PIXEL_ON = 0xffeeeeee;\n const PIXEL_OFF = 0xff000000;\n\n /*\n Screen RAM is DRAM shared by three requesters in priority order: DRAM refresh\n (blanking only, so it never costs the CPU), screen refresh, then Z80/Magic.\n CAS# free-runs, so memory timeslots are fixed and one Z80 M clock wide:\n\n - Every Z80 screen-RAM access takes at least T1,T2,Tw,T3 \u2014 \"A Z80 access cycle\n to this memory always results in at least one wait state\" \u2014 blanked or not.\n That's +1 over the usual 3 T-states.\n - During active video, the refresh wins the slot. Consumer mode fetches 1 byte\n (4 px) every 4 PX = every 2 M clocks \u2192 memory is unavailable half the time\n \u2192 50% of accesses eat a second wait state. Commercial/arcade fetches 4 bytes\n (16 px) every 8 PX = every 4 M clocks \u2192 unavailable \u00BC of the time \u2192 25% eat\n a second one.\n - The fetch only runs for the 40 (consumer) / 20 (arcade) reads per line \u2014 160\n px of the 63.5 \u00B5s line, \u224870%. Border and hblank are free, as is ROM and the\n arcade's separate scratch RAM board.\n */\n const REFRESH_SLOT_MASK = arcade ? 3 : 1;\n // the refresh reads 40 (consumer) or 20 (commercial) times per line, covering the\n // 160 displayed pixels of the 63.5 us line; the rest is border and hblank\n const ACTIVE_LINE_FRACTION = 0.7;\n var activecycles = 0; // = ACTIVE_LINE_FRACTION of a scanline, set by init()\n\n // state variables\n var inputs = new Uint8Array(0x20);\n var magicop = 0;\n var xpand = 0;\n var xplower = false;\n var shift2 = 0;\n var horcb = 0;\n var inmod = 0;\n var inlin = 0;\n var infbk = 0;\n var verbl = sheight;\n var palette = new Uint32Array(8);\n var palinds = new Uint8Array(8);\n var refreshlines = 0;\n var dirtylines = new Uint8Array(arcade ? 262 : 131);\n var rotdata = new Uint8Array(4);\n var rotcount = 0;\n var intst = 0;\n var waitstates = 0;\n var slotphase = 0;\n var patboard = new Uint8Array(0x08);\n var patdest = 0;\n\n // is the video refresh reading screen RAM at this point in the frame?\n function refreshing() : boolean {\n return machine.scanline < verbl && machine.getRasterX() < activecycles;\n }\n\n // charge the Z80 for one screen RAM (DRAM) bus cycle\n function screenwait() {\n waitstates++; // always at least one wait state\n if (refreshing() && !(slotphase++ & REFRESH_SLOT_MASK)) {\n waitstates++; // and a second one when we collide with the screen refresh\n }\n }\n\n function ramwrite(a: number, v: number) {\n // set RAM\n ram[a] = v;\n screenwait();\n // mark scanline as dirty\n dirtylines[((a & samask) / swbytes) | 0] = 1;\n // this was old behavior where we updated instantly\n // but it had problems if we had mid-screen palette changes\n //ramupdate(a, v);\n }\n\n function ramupdate(a: number, v: number) {\n var ofs = a * 4 + 3; // 4 pixels per byte\n for (var i = 0; i < 4; i++) {\n var lr = ((a % swbytes) >= (horcb & 0x3f)) ? 0 : 4;\n pixels[ofs--] = palette[lr + (v & 3)];\n v >>= 2;\n }\n }\n\n function refreshline(y: number) {\n var ofs = y * swidth / 4;\n for (var i = 0; i < swidth / 4; i++)\n ramupdate(ofs + i, ram[ofs + i]);\n }\n\n function magicwrite(a: number, v: number) {\n // expand\n if (magicop & 0x8) {\n var v2 = 0;\n if (!xplower)\n v >>= 4;\n for (var i = 0; i < 4; i++) {\n var pix = (v & 1) ? ((xpand >> 2) & 3) : (xpand & 3);\n v2 |= pix << (i * 2);\n v >>= 1;\n }\n v = v2;\n xplower = !xplower;\n }\n // rotate\n if (magicop & 0x4) {\n if (rotcount & 4) {\n // drain buffer\n var sh = 2 * (~rotcount & 3);\n v = (((rotdata[3] >> sh) & 3) << 6) |\n (((rotdata[2] >> sh) & 3) << 4) |\n (((rotdata[1] >> sh) & 3) << 2) |\n (((rotdata[0] >> sh) & 3) << 0);\n } else {\n // fill buffer\n rotdata[rotcount & 3] = v;\n }\n rotcount++;\n } else {\n // shift\n var sh = (magicop & 3) << 1;\n var v2 = (v >> sh) | shift2;\n shift2 = (v << (8 - sh)) & 0xff;\n v = v2;\n }\n // flop\n if (magicop & 0x40) {\n v =\n ((v & 0x03) << 6) |\n ((v & 0x0c) << 2) |\n ((v & 0x30) >> 2) |\n ((v & 0xc0) >> 6);\n }\n // or/xor\n if (magicop & 0x30) {\n var oldv = ram[a];\n // collision detect\n var icpt = 0;\n if ((oldv & 0xc0) && (v & 0xc0)) icpt |= 0x1;\n if ((oldv & 0x30) && (v & 0x30)) icpt |= 0x2;\n if ((oldv & 0x0c) && (v & 0x0c)) icpt |= 0x4;\n if ((oldv & 0x03) && (v & 0x03)) icpt |= 0x8;\n // apply op\n if (magicop & 0x10)\n v |= oldv;\n if (magicop & 0x20)\n v ^= oldv; // TODO: what if both?\n // upper 4 bits persist, lower are just since last write\n intst = (intst & 0xf0) | icpt | (icpt << 4);\n }\n // commit write to ram/screen\n ramwrite(a, v);\n }\n\n function setpalette(a: number, v: number) {\n palinds[a & 7] = v & 0xff;\n palette[a & 7] = ASTROCADE_PALETTE[v & 0xff];\n refreshall();\n }\n\n function setbordercolor() {\n var col = horcb >> 6;\n // TODO\n }\n\n function refreshall() {\n refreshlines = sheight;\n }\n\n // bally astrocade pattern board\n // https://github.com/mamedev/mame/blob/7ff10685c56a6e123336c684e5e96fdb9e8b3674/src/mame/midway/astrocde_v.cpp#L726\n function xfer_patboard() {\n let m_pattern_source = patboard[0] | (patboard[1] << 8);\n let m_pattern_mode = patboard[2] & 0x3f;\n let m_pattern_skip = patboard[3];\n let m_pattern_dest = (patdest & 0xff) | (patboard[4] << 8);\n let m_pattern_width = patboard[5];\n let m_pattern_height = patboard[6] + 1;\n\n let curwidth: number;\n let u13ff: number = 0;\n let cycles: number = 0;\n const wsave = waitstates;\n\n u13ff = 0;\n\n if ((m_pattern_mode & 0x02) === 0) {\n u13ff = 1;\n }\n\n function incrementSource(): void {\n if (u13ff && (m_pattern_mode & 0x04) !== 0 && (curwidth !== 0 || (m_pattern_mode & 0x08) === 0)) {\n m_pattern_source++;\n }\n\n if ((m_pattern_mode & 0x02) !== 0) {\n u13ff ^= 1;\n }\n }\n\n function incrementDest(): void {\n if (curwidth !== 0) {\n if ((m_pattern_mode & 0x20) !== 0) {\n m_pattern_dest++;\n } else {\n m_pattern_dest--;\n }\n }\n }\n\n // Loop over height\n while (m_pattern_height >= 0) {\n let carry: number;\n\n curwidth = m_pattern_width;\n\n // Loop over width\n while (curwidth >= 0) {\n let busaddr: number;\n let busdata: number;\n\n // Read Phase\n busaddr = (m_pattern_mode & 0x01) === 0 ? m_pattern_source : m_pattern_dest;\n\n if (curwidth === 0 && (m_pattern_mode & 0x08) !== 0) {\n busdata = 0;\n } else {\n busdata = membus.read(m_pattern_source);\n }\n\n if ((m_pattern_mode & 0x01) === 0) {\n incrementSource();\n } else {\n incrementDest();\n }\n\n // Write Phase\n busaddr = (m_pattern_mode & 0x01) !== 0 ? m_pattern_source : m_pattern_dest;\n ramwrite(busaddr, busdata);\n\n if ((m_pattern_mode & 0x01) === 0) {\n incrementDest();\n } else {\n incrementSource();\n }\n\n cycles += 4;\n curwidth--;\n }\n\n // At the end of each row, adjust m_pattern_dest\n carry = ((m_pattern_dest & 0xff) + m_pattern_skip) & 0x100;\n m_pattern_dest = (m_pattern_dest & 0xff00) | ((m_pattern_dest + m_pattern_skip) & 0xff);\n\n if ((m_pattern_mode & 0x10) === 0) {\n m_pattern_dest += carry;\n } else {\n m_pattern_dest -= carry ^ 0x100;\n }\n\n m_pattern_height--;\n }\n\n // the pattern board owns the bus while it runs, so its own cycles (two reads\n // and two writes per byte, as MAME counts them) replace the Z80 wait states\n // that the transfers above accrued\n waitstates = wsave + cycles;\n }\n \n this.drawScanline = (sl:number) => {\n // interrupt\n if (sl == inlin && (inmod & 0x8)) {\n cpu.retryInterrupts = !(inmod & 0x4);\n this.probe && this.probe.logInterrupt(infbk);\n cpu.interrupt(infbk);\n }\n // refresh this line in frame buffer?\n if (sl < sheight && refreshlines > 0) {\n dirtylines[sl] = 0;\n refreshline(sl);\n refreshlines--;\n }\n else if (dirtylines[sl]) {\n dirtylines[sl] = 0;\n refreshline(sl);\n }\n }\n \n this.init = (mach:BallyAstrocade, c:Z80, r:Uint8Array, inp:Uint8Array, psgg) => {\n machine = mach;\n activecycles = mach.cpuCyclesPerLine * ACTIVE_LINE_FRACTION;\n cpu = c;\n ram = r;\n inputs = inp;\n psg = psgg;\n if (!arcade) {\n //bios = padBytes(ASTROCADE_MINIMAL_BIOS, 0x2000);\n bios = padBytes(new lzgmini().decode(stringToByteArray(atob(ASTROLIBRE_BIOS_LZG))), 0x2000);\n // game console\n membus = {\n read: newAddressDecoder([\n [0x0000, 0x1fff, 0x1fff, function(a) { return bios[a]; }],\n [0x2000, 0x3fff, 0x1fff, function(a) { return rom ? rom[a] : 0; }],\n [0x4000, 0x4fff, 0xfff, function(a) { screenwait(); return ram[a]; }],\n ]),\n write: newAddressDecoder([\n [0x4000, 0x4fff, 0xfff, ramwrite],\n [0x0000, 0x3fff, 0xfff, magicwrite],\n ]),\n }\n } else {\n // arcade game\n membus = {\n read: newAddressDecoder([\n [0x4000, 0x7fff, 0x3fff, function(a) { screenwait(); return ram[a]; }],\t// screen RAM\n [0xd000, 0xdfff, 0x0fff, function(a) { return ram[a + 0x4000]; }], // static RAM (own board, no wait states)\n [0x0000, 0x3fff, 0x3fff, function(a) { return rom ? rom[a] : 0; }], // ROM\n [0x8000, 0xbfff, 0x3fff, function(a) { return rom ? rom[a + 0x4000] : 0; }], // ROM\n ]),\n write: newAddressDecoder([\n [0x4000, 0x7fff, 0x3fff, ramwrite],\n [0x0000, 0x3fff, 0x3fff, magicwrite],\n [0xd000, 0xdfff, 0x0fff, function(a, v) { ram[a + 0x4000] = v; }], // static RAM (not displayed, no wait states)\n ]),\n }\n }\n iobus = {\n read: function(addr) {\n addr &= 0x1f;\n var rtn;\n switch (addr) {\n case 8:\n rtn = intst;\n intst = 0;\n break;\n default:\n rtn = inputs[addr];\n break;\n // $10 = watchdog\n }\n return rtn;\n },\n write: function(addr, val) {\n if (addr == 0xa55b) {\n // TODO: protected_ram_enable_w\n return;\n }\n addr &= 0xff;\n // pattern board\n if (addr > 0x78 && addr < 0x80) {\n patboard[addr & 7] = val;\n if (addr == 0x72) { patdest = 0; }\n if (addr == 0x74) { patdest = (patdest + patboard[3]) & 0xff; }\n if (addr == 0x7e) { xfer_patboard(); }\n return;\n }\n addr &= 0x1f;\n val &= 0xff;\n switch (addr) {\n case 0:\n case 1:\n case 2:\n case 3:\n case 4:\n case 5:\n case 6:\n case 7:\n setpalette(addr, val);\n break;\n case 9: // HORCB (horizontal boundary byte)\n horcb = val;\n setbordercolor();\n refreshall();\n break;\n case 0xa: // VERBL (vertical blank)\n verbl = arcade ? val : val >> 1;\n refreshall();\n break;\n case 0xb: // OTIR (set palette)\n var c = cpu.saveState();\n //console.log(c.BC>>8, c.HL);\n setpalette((c.BC >> 8) - 1, membus.read(c.HL));\n break;\n case 0xc: // magic register\n magicop = val;\n shift2 = 0;\n rotcount = 0;\n xplower = false;\n break;\n case 0xd: // INFBK (interrupt feedback)\n infbk = val;\n break;\n case 0xe: // INMOD (interrupt enable)\n inmod = val;\n break;\n case 0xf: // INLIN (interrupt line)\n inlin = arcade ? val : val >> 1;\n break;\n case 0x10:\n case 0x11:\n case 0x12:\n case 0x13:\n case 0x14:\n case 0x15:\n case 0x16:\n case 0x17:\n psg.setACRegister(addr, val);\n break;\n case 0x18:\n var c = cpu.saveState();\n psg.setACRegister((c.BC >> 8) - 1, membus.read(c.HL));\n break;\n case 0x19: // XPAND\n xpand = val;\t\n break;\n case 0x1a:\n case 0x1b:\n case 0x1c:\n case 0x1d:\n case 0x1e:\n //psg2.setACRegister(addr - 0x1a, val);\n break;\n default:\n //console.log('IO write', hex(addr, 4), hex(val, 2));\n break;\n }\n }\n }\n mach.connectCPUMemoryBus(membus);\n mach.connectCPUIOBus(iobus);\n this.membus = membus;\n this.iobus = iobus;\n // default palette\n for (var i = 0; i < 8; i++) {\n setpalette(i,i);\n }\n };\n\n // wait states accrued since the last call, charged to the CPU by advanceCPU()\n this.resetWaitStates = function() {\n var n = waitstates;\n waitstates = 0;\n return n;\n }\n\n // read for the debugger/UI, without stalling the CPU\n this.peek = function(a: number) {\n var n = waitstates;\n var v = membus.read(a);\n waitstates = n;\n return v;\n }\n\n this.loadState = (state) => {\n cpu.loadState(state.c);\n ram.set(state.ram);\n palette.set(state.palette);\n palinds.set(state.palinds);\n magicop = state.magicop;\n xpand = state.xpand;\n xplower = state.xplower;\n shift2 = state.shift2;\n horcb = state.horcb;\n inmod = state.inmod;\n inlin = state.inlin;\n infbk = state.infbk;\n verbl = state.verbl;\n rotcount = state.rotcount;\n rotdata.set(state.rotdata);\n intst = state.intst;\n slotphase = state.slotphase | 0;\n inputs.set(state.inputs);\n patboard.set(state.patboard);\n patdest = state.patdest;\n refreshall();\n }\n \n this.saveState = () => {\n return {\n c: cpu.saveState(),\n ram: ram.slice(0),\n inputs: inputs.slice(0),\n palette: palette.slice(0),\n palinds: palinds.slice(0),\n magicop: magicop,\n xpand: xpand,\n xplower: xplower,\n shift2: shift2,\n horcb: horcb,\n inmod: inmod,\n inlin: inlin,\n infbk: infbk,\n verbl: verbl,\n rotcount: rotcount,\n rotdata: rotdata.slice(0),\n intst: intst,\n slotphase: slotphase,\n patboard: patboard.slice(0),\n patdest: patdest,\n };\n }\n this.reset = () => {\n // TODO?\n magicop = xpand = inmod = inlin = infbk = shift2 = horcb = 0;\n verbl = sheight;\n xplower = false;\n //watchdog_counter = INITIAL_WATCHDOG;\n }\n \n this.toLongString = (st) => {\n var s = \"\";\n //s += \" Scan Y: \" + st.sl;\n s += \"\\n INLIN: \" + st.inlin;\n s += \"\\n VERBL: \" + st.verbl;\n s += \"\\nMAGICOP: $\" + hex(st.magicop);\n s += \"\\n XPAND: $\" + hex(st.xpand);\n s += \"\\nXPLOWER: \" + st.xplower;\n s += \"\\n SHIFT2: $\" + hex(st.shift2);\n s += \"\\n HORCB: $\" + hex(st.horcb);\n s += \"\\n INMOD: $\" + hex(st.inmod);\n s += \"\\n INFBK: $\" + hex(st.infbk);\n s += \"\\n INTST: $\" + hex(st.intst); // intercept status\n s += \"\\nPalette: \";\n for (var i = 0; i < 8; i++)\n s += hex(palinds[i]);\n s += \"\\n\";\n return s;\n }\n \n this.connectVideo = function(pix) {\n pixels = pix;\n }\n this.loadROM = function(data) {\n rom = data;\n }\n this.loadBIOS = function(data) {\n bios = data;\n }\n this.getVisiblePixelWords = function() {\n return verbl * swidth;\n }\n}\n\nexport class BallyAstrocade extends BasicScanlineMachine implements AcceptsPaddleInput {\n \n cpuFrequency = 1789000;\n numTotalScanlines : number;\n numVisibleScanlines : number;\n cpuCyclesPerLine : number;\n defaultROMSize : number;\n canvasWidth : number;\n sampleRate : number;\n ram : Uint8Array;\n cpu : Z80;\n m; // _BallyAstrocade\n arcade : boolean;\n\n psg: AstrocadeAudio;\n audioadapter;\n backbuffer : Uint32Array;\n frontbuffer : Uint32Array;\n\n constructor(arcade:boolean) {\n super();\n this.arcade = arcade;\n this.cpu = new Z80();\n this.psg = new AstrocadeAudio(new MasterAudio());\n // in consumer mode every line of screen RAM is displayed twice, so one emulated\n // scanline is two of the 262 NTSC lines (as are INLIN and VERBL, hence the >>1)\n this.numTotalScanlines = arcade ? 262 : 131;\n // one audio sample per emulated scanline, so oversample twice as much in\n // consumer mode to keep the sample rate the same\n var oversample = audioOversample * (arcade ? 1 : 2);\n this.sampleRate = 60 * this.numTotalScanlines * oversample;\n this.audioadapter = new TssChannelAdapter(this.psg.psg, oversample, this.sampleRate);\n this.handler = newKeyboardHandler(this.inputs, ASTROCADE_KEYCODE_MAP);\n this.defaultROMSize = arcade ? 0xb000 : 0x2000;\n this.ram = new Uint8Array(arcade ? 0x5000 : 0x1000);\n this.numVisibleScanlines = arcade ? 204 : 102;\n this.canvasWidth = arcade ? 320 : 160;\n this.cpuCyclesPerLine = (this.cpuFrequency / (60 * this.numVisibleScanlines * 1.286)) | 0;\n //this.cpuCyclesPerHBlank = Math.floor(this.cpuCyclesPerLine * 0.33);\n //this.cpuCyclesPerVisible = this.cpuCyclesPerLine - this.cpuCyclesPerHBlank;\n this.m = new _BallyAstrocade(arcade);\n this.m.init(this, this.cpu, this.ram, this.inputs, this.psg);\n if (arcade) {\n this.inputs[0x10] = 0xff; // switches (active low)\n this.inputs[0x11] = 0xff; // switches (active low)\n this.inputs[0x12] = 0x00;\n this.inputs[0x13] = 0x08; // dip switches\n }\n }\n \n read(a:number) : number {\n return this.m.peek(a);\n }\n write(a:number, v:number) : void {\n this.m.membus.write(a,v);\n }\n \n connectVideo(pixels:Uint32Array) : void {\n super.connectVideo(pixels);\n this.frontbuffer = pixels;\n this.backbuffer = new Uint32Array(pixels.length);\n this.m.connectVideo(this.backbuffer);\n }\n preFrame() {\n this.m.resetWaitStates();\n }\n postFrame() {\n // copy back buffer to front buffer, omitting bottom non-visible pixels\n var nbytes = this.m.getVisiblePixelWords();\n this.frontbuffer.set(this.backbuffer.slice(0, nbytes), 0);\n this.frontbuffer.fill(0, nbytes);\n }\n\n setPaddleInput(controller:number, value:number) : void {\n switch (controller) {\n case 0: this.inputs[0x1c] = value & 0xff; break;\n case 1: this.inputs[0x1d] = value & 0xff; break;\n }\n }\n\n startScanline() {\n this.audio && this.audioadapter.generate(this.audio);\n }\n \n drawScanline() {\n var sl = this.scanline;\n this.m.drawScanline(sl);\n /*\n if (watchdog_counter-- <= 0) {\n console.log(\"WATCHDOG FIRED\"); // TODO: alert on video\n this.reset();\n }\n */\n }\n\n advanceCPU() {\n var clk = super.advanceCPU();\n // charge the CPU for screen RAM contention during this instruction\n var xtra = this.m.resetWaitStates();\n if (xtra) {\n clk += xtra;\n this.probe.logClocks(xtra);\n }\n return clk;\n }\n\n loadROM(data) {\n super.loadROM(data);\n this.m.loadROM(this.rom);\n this.reset();\n }\n loadBIOS(data) {\n this.m.loadBIOS(padBytes(data, 0x2000));\n this.reset();\n }\n reset() {\n super.reset();\n this.m.reset();\n }\n loadState(state) {\n this.m.loadState(state);\n }\n saveState() {\n return this.m.saveState();\n }\n getDebugCategories() {\n return ['CPU','Stack','Astro'];\n }\n getDebugInfo(category, state) {\n switch (category) {\n case 'Astro': return this.m.toLongString(state);\n }\n }\n getRasterCanvasPosition() {\n return { x: this.getRasterX(), y: this.getRasterY() };\n }\n getVideoParams() {\n if (this.arcade) {\n return { width: 320, height: 204, rotate: 180 };\n } else {\n return { width: 160, height: 102 };\n }\n }\n}\n\n/////\n\n// TODO: https://github.com/mamedev/mame/blob/master/src/devices/sound/astrocde.cpp\nclass AstrocadeAudio extends AY38910_Audio {\n setACRegister(addr: number, val: number) {\n addr &= 0x7;\n val &= 0xff;\n switch (addr) {\n case 0:\n this.psg.setClock(1789000 * 16 / (val + 1));\n this.psg.writeRegisterAY(7, 0x7 ^ 0xff); // disable noise\n break;\n case 1:\n case 2:\n case 3:\n var i = (addr - 1) * 2;\n var j = val * 2 + 1;\n this.psg.writeRegisterAY(i, j & 0xff); // freq lo\n this.psg.writeRegisterAY(i + 1, (j >> 8) & 0xff); // freq hi\n break;\n case 5:\n this.psg.writeRegisterAY(10, val & 0xf); // tone c vol\n break;\n case 6:\n this.psg.writeRegisterAY(8, val & 0xf);\t// tone a vol\n this.psg.writeRegisterAY(9, (val >> 4) & 0xf); // tone b vol\n break;\n }\n }\n}\n\n/////\n\n//http://glankonian.com/~lance/astrocade_palette.html\nvar ASTROCADE_PALETTE = [0x000000, 0x242424, 0x484848, 0x6D6D6D, 0x919191, 0xB6B6B6, 0xDADADA, 0xFFFFFF, 0x2500BB, 0x4900E0, 0x6E11FF, 0x9235FF, 0xB75AFF, 0xDB7EFF, 0xFFA3FF, 0xFFC7FF, 0x4900B0, 0x6D00D5, 0x9201F9, 0xB625FF, 0xDA4AFF, 0xFF6EFF, 0xFF92FF, 0xFFB7FF, 0x6A009F, 0x8E00C3, 0xB300E7, 0xD718FF, 0xFB3CFF, 0xFF61FF, 0xFF85FF, 0xFFA9FF, 0x870087, 0xAB00AB, 0xD000D0, 0xF40EF4, 0xFF32FF, 0xFF56FF, 0xFF7BFF, 0xFF9FFF, 0x9F006A, 0xC3008E, 0xE700B3, 0xFF07D7, 0xFF2CFB, 0xFF50FF, 0xFF74FF, 0xFF99FF, 0xB00049, 0xD5006D, 0xF90092, 0xFF05B6, 0xFF29DA, 0xFF4DFF, 0xFF72FF, 0xFF96FF, 0xBB0025, 0xE00049, 0xFF006E, 0xFF0692, 0xFF2AB7, 0xFF4FDB, 0xFF73FF, 0xFF98FF, 0xBF0000, 0xE30024, 0xFF0048, 0xFF0B6D, 0xFF3091, 0xFF54B6, 0xFF79DA, 0xFF9DFF, 0xBB0000, 0xE00000, 0xFF0023, 0xFF1447, 0xFF396C, 0xFF5D90, 0xFF82B5, 0xFFA6D9, 0xB00000, 0xD50000, 0xF90000, 0xFF2124, 0xFF4548, 0xFF6A6C, 0xFF8E91, 0xFFB3B5, 0x9F0000, 0xC30000, 0xE70C00, 0xFF3003, 0xFF5527, 0xFF794B, 0xFF9E70, 0xFFC294, 0x870000, 0xAB0000, 0xD01E00, 0xF44200, 0xFF670A, 0xFF8B2E, 0xFFAF53, 0xFFD477, 0x6A0000, 0x8E0D00, 0xB33100, 0xD75600, 0xFB7A00, 0xFF9E17, 0xFFC33B, 0xFFE75F, 0x490000, 0x6D2100, 0x924500, 0xB66A00, 0xDA8E00, 0xFFB305, 0xFFD729, 0xFFFC4E, 0x251100, 0x493500, 0x6E5A00, 0x927E00, 0xB7A300, 0xDBC700, 0xFFEB1E, 0xFFFF43, 0x002500, 0x244900, 0x486D00, 0x6D9200, 0x91B600, 0xB6DB00, 0xDAFF1B, 0xFFFF3F, 0x003700, 0x005B00, 0x238000, 0x47A400, 0x6CC900, 0x90ED00, 0xB5FF1E, 0xD9FF43, 0x004700, 0x006C00, 0x009000, 0x24B400, 0x48D900, 0x6CFD05, 0x91FF29, 0xB5FF4E, 0x005500, 0x007900, 0x009D00, 0x03C200, 0x27E600, 0x4BFF17, 0x70FF3B, 0x94FF5F, 0x005F00, 0x008300, 0x00A800, 0x00CC00, 0x0AF00A, 0x2EFF2E, 0x53FF53, 0x77FF77, 0x006500, 0x008A00, 0x00AE00, 0x00D203, 0x00F727, 0x17FF4B, 0x3BFF70, 0x5FFF94, 0x006800, 0x008C00, 0x00B100, 0x00D524, 0x00F948, 0x05FF6C, 0x29FF91, 0x4EFFB5, 0x006600, 0x008B00, 0x00AF23, 0x00D447, 0x00F86C, 0x00FF90, 0x1EFFB5, 0x43FFD9, 0x006100, 0x008524, 0x00AA48, 0x00CE6D, 0x00F391, 0x00FFB6, 0x1BFFDA, 0x3FFFFE, 0x005825, 0x007C49, 0x00A16E, 0x00C592, 0x00EAB7, 0x00FFDB, 0x1EFFFF, 0x43FFFF, 0x004B49, 0x00706D, 0x009492, 0x00B9B6, 0x00DDDA, 0x05FFFF, 0x29FFFF, 0x4EFFFF, 0x003C6A, 0x00608E, 0x0085B3, 0x00A9D7, 0x00CEFB, 0x17F2FF, 0x3BFFFF, 0x5FFFFF, 0x002A87, 0x004FAB, 0x0073D0, 0x0097F4, 0x0ABCFF, 0x2EE0FF, 0x53FFFF, 0x77FFFF, 0x00179F, 0x003BC3, 0x0060E7, 0x0384FF, 0x27A8FF, 0x4BCDFF, 0x70F1FF, 0x94FFFF, 0x0002B0, 0x0027D5, 0x004BF9, 0x2470FF, 0x4894FF, 0x6CB9FF, 0x91DDFF, 0xB5FFFF, 0x0000BB, 0x0013E0, 0x2337FF, 0x475BFF, 0x6C80FF, 0x90A4FF, 0xB5C9FF, 0xD9EDFF];\n// swap palette RGB to BGR\nfor (var i = 0; i < 256; i++) {\n var x = ASTROCADE_PALETTE[i];\n ASTROCADE_PALETTE[i] = rgb2bgr(x) | 0xff000000;\n}\n\n/*\n0000 F3 [ 4] 196 \tDI\t; disable interrupts\n0001 21 00 20 [10] 197 \tLD\tHL,#0x2000\n0004 7E [ 7] 198 \tLD\tA,(HL) ; A <- mem[0x2000]\n0005 FE 55 [ 7] 199 \tCP\t#0x55 ; found sentinel byte? ($55)\n0007 CA 0D 00 [10] 200 \tJP\tZ,FoundSentinel ; yes, load program\n000A C3 00 20 [10] 201 \tJP\t_main ; jump to test program\n000D 202 \tFoundSentinel:\n000D 31 CE 4F [10] 203 \tLD\tSP,#0x4fce ; position stack below BIOS vars\n0010 CD 84 02 [17] 204 \tCALL\t_bios_init ; misc. bios init routines\n0013 21 05 20 [10] 205 \tLD\tHL,#0x2005 ; cartridge start vector\n0016 7E [ 7] 206 \tLD\tA,(HL)\n0017 23 [ 6] 207 \tINC\tHL\n0018 66 [ 7] 208 \tLD\tH,(HL)\n0019 6F [ 4] 209 \tLD\tL,A\n001A E9 [ 4] 210 \tJP\t(HL) ; jump to cart start vector\n*/\nvar ASTROCADE_MINIMAL_BIOS = [\n 0xf3, 0x21, 0x00, 0x20, 0x7e, 0xfe, 0x55, 0xca, 0x0d, 0x00, 0xc3, 0x00, 0x20,\n 0x31, 0xce, 0x4f,\n 0x21, 0x05, 0x20, 0x7e, 0x23, 0x66, 0x6f,\n 0xe9,\n];\n\nvar ASTROLIBRE_BIOS_LZG = `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`;\n\n", "\nimport { BallyAstrocade } from \"../machine/astrocade\";\nimport { BaseZ80MachinePlatform } from \"../common/baseplatform\";\nimport { Platform } from \"../common/baseplatform\";\nimport { PLATFORMS } from \"../common/emu\";\n\n// http://metopal.com/projects/ballybook/doku.php\n\nconst ASTROCADE_PRESETS = [\n { id: '01-helloworlds.asm', name: 'Hello World (ASM)' },\n { id: '02-telephone.asm', name: 'Telephone (ASM)' },\n { id: '03-horcbpal.asm', name: 'Paddle Demo (ASM)' },\n { id: 'hello.c', name: 'Hello Graphics' },\n { id: 'lines.c', name: 'Lines' },\n { id: 'sprites.c', name: 'Sprites' },\n { id: 'vsync.c', name: 'Sprites w/ VSYNC' },\n { id: 'fastsprites.c', name: 'Fast Sprites' },\n { id: 'music.c', name: 'Music' },\n { id: 'rotate.c', name: 'Rotate Op' },\n { id: 'rainbow.c', name: 'Rainbow' },\n { id: 'cosmic.c', name: 'Cosmic Impalas Game' },\n { id: 'racing.c', name: 'Pseudo 3-D Racing Game' },\n];\n\nconst ASTROCADE_BIOS_PRESETS = [\n { id: 'bios.c', name: 'BIOS' },\n];\n\nconst ASTROCADE_ARCADE_PRESETS = [\n { id: 'hello.c', name: 'Hello Graphics' },\n];\n\nclass BallyAstrocadePlatform extends BaseZ80MachinePlatform implements Platform {\n\n newMachine() { return new BallyAstrocade(false); }\n getPresets() { return ASTROCADE_PRESETS; }\n readAddress(a) { return this.machine.read(a); }\n getMemoryMap = function() { return { main:[\n {name:'BIOS',start:0x0,size:0x2000,type:'rom'},\n //{name:'Cart ROM',start:0x2000,size:0x2000,type:'rom'},\n //{name:'Magic RAM',start:0x0,size:0x4000,type:'ram'},\n {name:'Screen RAM',start:0x4000,size:0x1000,type:'ram'},\n {name:'BIOS Variables',start:0x4fce,size:0x5000-0x4fce,type:'ram'},\n ] } };\n showHelp() { return \"https://8bitworkshop.com/docs/platforms/astrocade/\"; }\n}\n\nclass BallyAstrocadeBIOSPlatform extends BallyAstrocadePlatform implements Platform {\n\n getPresets() { return ASTROCADE_BIOS_PRESETS; }\n loadROM(title,rom) { this.machine.loadBIOS(rom); }\n\n}\n\nclass BallyArcadePlatform extends BallyAstrocadePlatform implements Platform {\n\n newMachine() { return new BallyAstrocade(true); }\n getPresets() { return ASTROCADE_ARCADE_PRESETS; }\n\n getMemoryMap = function() { return { main:[\n {name:'ROM',start:0x0,size:0x4000,type:'rom'},\n {name:'Magic RAM',start:0x0,size:0x4000,type:'ram'},\n {name:'Screen RAM',start:0x4000,size:0x4000,type:'ram'},\n {name:'ROM',start:0x8000,size:0x4000,type:'rom'},\n ] } };\n}\n\nPLATFORMS['astrocade'] = BallyAstrocadePlatform;\nPLATFORMS['astrocade-bios'] = BallyAstrocadeBIOSPlatform;\nPLATFORMS['astrocade-arcade'] = BallyArcadePlatform;\n\n"], + "mappings": "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", + "names": ["ASTROCADE_KEYCODE_MAP", "makeKeycodeMap", "Keys", "audioOversample", "_BallyAstrocade", "arcade", "machine", "cpu", "ram", "membus", "iobus", "rom", "bios", "pixels", "psg", "swidth", "sheight", "swbytes", "samask", "INITIAL_WATCHDOG", "PIXEL_ON", "PIXEL_OFF", "REFRESH_SLOT_MASK", "ACTIVE_LINE_FRACTION", "activecycles", "inputs", "magicop", "xpand", "xplower", "shift2", "horcb", "inmod", "inlin", "infbk", "verbl", "palette", "palinds", "refreshlines", "dirtylines", "rotdata", "rotcount", "intst", "waitstates", "slotphase", "patboard", "patdest", "refreshing", "screenwait", "ramwrite", "a", "v", "ramupdate", "ofs", "i", "lr", "refreshline", "y", "magicwrite", "v2", "pix", "sh", "oldv", "icpt", "setpalette", "ASTROCADE_PALETTE", "refreshall", "setbordercolor", "col", "xfer_patboard", "m_pattern_source", "m_pattern_mode", "m_pattern_skip", "m_pattern_dest", "m_pattern_width", "m_pattern_height", "curwidth", "u13ff", "cycles", "wsave", "incrementSource", "incrementDest", "carry", "busaddr", "busdata", "sl", "mach", "c", "r", "inp", "psgg", "newAddressDecoder", "padBytes", "lzgmini", "stringToByteArray", "ASTROLIBRE_BIOS_LZG", "addr", "rtn", "val", "n", "state", "st", "s", "hex", "data", "BallyAstrocade", "BasicScanlineMachine", "Z80", "AstrocadeAudio", "MasterAudio", "oversample", "TssChannelAdapter", "newKeyboardHandler", "nbytes", "controller", "value", "clk", "xtra", "category", "AY38910_Audio", "j", "x", "rgb2bgr", "ASTROLIBRE_BIOS_LZG", "ASTROCADE_PRESETS", "ASTROCADE_BIOS_PRESETS", "ASTROCADE_ARCADE_PRESETS", "BallyAstrocadePlatform", "BaseZ80MachinePlatform", "BallyAstrocade", "a", "BallyAstrocadeBIOSPlatform", "title", "rom", "BallyArcadePlatform", "PLATFORMS"] +} diff --git a/gen/astrocade-SQ7A55O6.js b/gen/astrocade-SQ7A55O6.js deleted file mode 100644 index 91a0646c..00000000 --- a/gen/astrocade-SQ7A55O6.js +++ /dev/null @@ -1,14 +0,0 @@ -import{K as m0,c as B0,d as g0,e as X0,k as C0,r as l0}from"./chunk-CZ7OSHSE.js";import{$ as q,K as k,W as A,X as c0,Z as o0,aa as N,g as o,l as d0,m as a0,t as f0}from"./chunk-TYDI7JZQ.js";import"./chunk-KT7KMEQC.js";var p0=o0([[A.UP,16,1],[A.DOWN,16,2],[A.LEFT,16,4],[A.RIGHT,16,8],[A.A,16,16],[A.P2_UP,17,1],[A.P2_DOWN,17,2],[A.P2_LEFT,17,4],[A.P2_RIGHT,17,8],[A.P2_A,17,16],[A.VK_P,20,1],[A.VK_SLASH,20,2],[A.VK_X,20,4],[A.VK_MINUS,20,8],[A.VK_COMMA,20,16],[A.VK_EQUALS,20,32],[A.VK_O,21,1],[A.VK_L,21,2],[A.VK_9,21,4],[A.VK_6,21,8],[A.VK_3,21,16],[A.VK_PERIOD,21,32],[A.VK_I,22,1],[A.VK_K,22,2],[A.VK_8,22,4],[A.VK_5,22,8],[A.VK_2,22,16],[A.VK_0,22,32],[A.VK_U,23,1],[A.VK_J,23,2],[A.VK_7,23,4],[A.VK_4,23,8],[A.VK_1,23,16],[A.VK_BACK_SLASH,23,32]]),h0=2,w0=function(f){var d,t,i,D,g,U,F0,W;let R=f?320:160,K=f?204:102,A0=R>>2,E0=f?16383:4095,N0=256,I0=4293848814,P0=4278190080;var j=new Uint8Array(32),B=0,E=0,X=!1,u=0,Y=0,b=0,M=0,p=0,w=K,H=new Uint32Array(8),y=new Uint8Array(8),J=0,T=new Uint8Array(f?262:131),C=new Uint8Array(4),l=0,Q=0,v=0,c=new Uint8Array(8),S=0;function V(e,x){t[e]=x,v++,T[(e&E0)/A0|0]=1}function u0(e,x){for(var s=e*4+3,n=0;n<4;n++){var m=e%A0>=(Y&63)?0:4;F0[s--]=H[m+(x&3)],x>>=2}}function r0(e){for(var x=e*R/4,s=0;s>=4);for(var n=0;n<4;n++){var m=x&1?E>>2&3:E&3;s|=m<>=1}x=s,X=!X}if(B&4){if(l&4){var a=2*(~l&3);x=(C[3]>>a&3)<<6|(C[2]>>a&3)<<4|(C[1]>>a&3)<<2|(C[0]>>a&3)<<0}else C[l&3]=x;l++}else{var a=(B&3)<<1,s=x>>a|u;u=x<<8-a&255,x=s}if(B&64&&(x=(x&3)<<6|(x&12)<<2|(x&48)>>2|(x&192)>>6),B&48){var F=t[e],r=0;F&192&&x&192&&(r|=1),F&48&&x&48&&(r|=2),F&12&&x&12&&(r|=4),F&3&&x&3&&(r|=8),B&16&&(x|=F),B&32&&(x^=F),Q=Q&240|r|r<<4}V(e,x)}function Z(e,x){y[e&7]=x&255,H[e&7]=e0[x&255],O()}function Y0(){var e=Y>>6}function O(){J=K}function b0(){let e=c[0]|c[1]<<8,x=c[2]&63,s=c[3],n=S&255|c[4]<<8,m=c[5],a=c[6]+1,F,r=0,h=0;r=0,(x&2)===0&&(r=1);function s0(){r&&(x&4)!==0&&(F!==0||(x&8)===0)&&e++,(x&2)!==0&&(r^=1)}function n0(){F!==0&&((x&32)!==0?n++:n--)}for(;a>=0;){let L;for(F=m;F>=0;){let z,_;z=(x&1)===0?e:n,F===0&&(x&8)!==0?_=0:_=i.read(e),(x&1)===0?s0():n0(),z=(x&1)!==0?e:n,V(z,_),(x&1)===0?n0():s0(),h+=4,F--}L=(n&255)+s&256,n=n&65280|n+s&255,(x&16)===0?n+=L:n-=L^256,a--}}this.drawScanline=e=>{e==M&&b&8&&(d.retryInterrupts=!(b&4),this.probe&&this.probe.logInterrupt(p),d.interrupt(p)),e0?(T[e]=0,r0(e),J--):T[e]&&(T[e]=0,r0(e))},this.init=(e,x,s,n,m)=>{d=x,t=s,j=n,W=m,f?i={read:N([[16384,32767,16383,function(F){return t[F]}],[53248,57343,4095,function(F){return t[F+16384]}],[0,16383,16383,function(F){return g?g[F]:0}],[32768,49151,16383,function(F){return g?g[F+16384]:0}]]),write:N([[16384,32767,16383,V],[0,16383,16383,i0],[53248,57343,4095,function(F,r){V(F+16384,r)}]])}:(U=q(new d0().decode(a0(atob(Q0))),8192),i={read:N([[0,8191,8191,function(F){return U[F]}],[8192,16383,8191,function(F){return g?g[F]:0}],[16384,20479,4095,function(F){return v++,t[F]}]]),write:N([[16384,20479,4095,V],[0,16383,4095,i0]])}),D={read:function(F){F&=31;var r;switch(F){case 8:r=Q,Q=0;break;default:r=j[F];break}return r},write:function(F,r){if(F!=42331){if(F&=255,F>120&&F<128){c[F&7]=r,F==114&&(S=0),F==116&&(S=S+c[3]&255),F==126&&b0();return}switch(F&=31,r&=255,F){case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7:Z(F,r);break;case 9:Y=r,Y0(),O();break;case 10:w=f?r:r>>1,O();break;case 11:var h=d.saveState();Z((h.BC>>8)-1,i.read(h.HL));break;case 12:B=r,u=0,l=0,X=!1;break;case 13:p=r;break;case 14:b=r;break;case 15:M=f?r:r>>1;break;case 16:case 17:case 18:case 19:case 20:case 21:case 22:case 23:W.setACRegister(F,r);break;case 24:var h=d.saveState();W.setACRegister((h.BC>>8)-1,i.read(h.HL));break;case 25:E=r;break;case 26:case 27:case 28:case 29:case 30:break;default:break}}}},e.connectCPUMemoryBus(i),e.connectCPUIOBus(D),this.membus=i,this.iobus=D;for(var a=0;a<8;a++)Z(a,a)},this.resetWaitStates=function(e){var x=e{d.loadState(e.c),t.set(e.ram),H.set(e.palette),y.set(e.palinds),B=e.magicop,E=e.xpand,X=e.xplower,u=e.shift2,Y=e.horcb,b=e.inmod,M=e.inlin,p=e.infbk,w=e.verbl,l=e.rotcount,C.set(e.rotdata),Q=e.intst,j.set(e.inputs),c.set(e.patboard),S=e.patdest,O()},this.saveState=()=>({c:d.saveState(),ram:t.slice(0),inputs:j.slice(0),palette:H.slice(0),palinds:y.slice(0),magicop:B,xpand:E,xplower:X,shift2:u,horcb:Y,inmod:b,inlin:M,infbk:p,verbl:w,rotcount:l,rotdata:C.slice(0),intst:Q,patboard:c.slice(0),patdest:S}),this.reset=()=>{B=E=b=M=p=u=Y=0,w=K,X=!1},this.toLongString=e=>{var x="";x+=` - INLIN: `+e.inlin,x+=` - VERBL: `+e.verbl,x+=` -MAGICOP: $`+o(e.magicop),x+=` - XPAND: $`+o(e.xpand),x+=` -XPLOWER: `+e.xplower,x+=` - SHIFT2: $`+o(e.shift2),x+=` - HORCB: $`+o(e.horcb),x+=` - INMOD: $`+o(e.inmod),x+=` - INFBK: $`+o(e.infbk),x+=` - INTST: $`+o(e.intst),x+=` -Palette: `;for(var s=0;s<8;s++)x+=o(y[s]);return x+=` -`,x},this.connectVideo=function(e){F0=e},this.loadROM=function(e){g=e},this.loadBIOS=function(e){U=e},this.getVisiblePixelWords=function(){return w*R}},P=class extends l0{constructor(t){super();this.cpuFrequency=1789e3;this.numTotalScanlines=262;this.sampleRate=60*262*h0;this.arcade=t,this.cpu=new B0,this.psg=new $(new g0),this.audioadapter=new C0(this.psg.psg,h0,this.sampleRate),this.handler=c0(this.inputs,p0),this.defaultROMSize=t?45056:8192,this.ram=new Uint8Array(t?20480:4096),this.numVisibleScanlines=t?204:102,this.canvasWidth=t?320:160,this.cpuCyclesPerLine=this.cpuFrequency/(60*this.numVisibleScanlines*1.286)|0,this.m=new w0(t),this.m.init(this,this.cpu,this.ram,this.inputs,this.psg),t&&(this.inputs[16]=255,this.inputs[17]=255,this.inputs[18]=0,this.inputs[19]=8)}read(t){return this.m.membus.read(t)}write(t,i){this.m.membus.write(t,i)}connectVideo(t){super.connectVideo(t),this.frontbuffer=t,this.backbuffer=new Uint32Array(t.length),this.m.connectVideo(this.backbuffer)}preFrame(){this.m.resetWaitStates(0)}postFrame(){var t=this.m.getVisiblePixelWords();this.frontbuffer.set(this.backbuffer.slice(0,t),0),this.frontbuffer.fill(0,t)}setPaddleInput(t,i){switch(t){case 0:this.inputs[28]=i&255;break;case 1:this.inputs[29]=i&255;break}}startScanline(){this.audio&&this.audioadapter.generate(this.audio)}drawScanline(){var t=this.scanline;this.m.drawScanline(t)}advanceCPU(){var t=super.advanceCPU(),i=this.m.resetWaitStates(this.scanline);return i&&(t+=i,this.probe.logClocks(i)),t}loadROM(t){super.loadROM(t),this.m.loadROM(this.rom),this.reset()}loadBIOS(t){this.m.loadBIOS(q(t,8192)),this.reset()}reset(){super.reset(),this.m.reset()}loadState(t){this.m.loadState(t)}saveState(){return this.m.saveState()}getDebugCategories(){return["CPU","Stack","Astro"]}getDebugInfo(t,i){switch(t){case"Astro":return this.m.toLongString(i)}}getRasterCanvasPosition(){return{x:this.getRasterX(),y:this.getRasterY()}}getVideoParams(){return this.arcade?{width:320,height:204,rotate:180}:{width:160,height:102}}},$=class extends X0{setACRegister(d,t){switch(d&=7,t&=255,d){case 0:this.psg.setClock(1789e3*16/(t+1)),this.psg.writeRegisterAY(7,248);break;case 1:case 2:case 3:var i=(d-1)*2,D=t*2+1;this.psg.writeRegisterAY(i,D&255),this.psg.writeRegisterAY(i+1,D>>8&255);break;case 5:this.psg.writeRegisterAY(10,t&15);break;case 6:this.psg.writeRegisterAY(8,t&15),this.psg.writeRegisterAY(9,t>>4&15);break}}},e0=[0,2368548,4737096,7171437,9539985,11974326,14342874,16777215,2425019,4784352,7213567,9582079,12016383,14384895,16753663,16762879,4784304,7143637,9568761,11937279,14306047,16740095,16749311,16758783,6946975,9306307,11731175,14096639,16465151,16736767,16745983,16755199,8847495,11206827,13631696,15994612,16724735,16733951,16743423,16752639,10420330,12779662,15138995,16713687,16723195,16732415,16741631,16751103,11534409,13959277,16318610,16713142,16722394,16731647,16741119,16750335,12255269,14680137,16711790,16713362,16722615,16732123,16741375,16750847,12517376,14876708,16711752,16714605,16724113,16733366,16742874,16752127,12255232,14680064,16711715,16716871,16726380,16735632,16745141,16754393,11534336,13959168,16318464,16720164,16729416,16738924,16748177,16757685,10420224,12779520,15141888,16723971,16733479,16742731,16752240,16761492,8847360,11206656,13639168,16007680,16738058,16747310,16756563,16766071,6946816,9309440,11743488,14112256,16480768,16752151,16761659,16770911,4784128,7151872,9585920,11954688,14323200,16757509,16766761,16776270,2429184,4797696,7232e3,9600512,12034816,14403328,16771870,16777027,9472,2377984,4746496,7180800,9549312,11983616,14352155,16777023,14080,23296,2326528,4695040,7129344,9497856,11927326,14286659,18176,27648,36864,2405376,4774144,7142661,9568041,11927374,21760,30976,40192,246272,2614784,4980503,7405371,9764703,24320,33536,43008,52224,716810,3079982,5504851,7864183,25856,35328,44544,53763,63271,1572683,3932016,6291348,26624,35840,45312,54564,63816,393068,2752401,5177269,26112,35584,44835,54343,63596,65424,2031541,4456409,24832,34084,43592,52845,62353,65462,1834970,4194302,22565,31817,41326,50578,60087,65499,2031615,4456447,19273,28781,38034,47542,56794,393215,2752511,5177343,15466,24718,34227,43479,52987,1569535,3932159,6291455,10887,20395,29648,38900,703743,3072255,5505023,7864319,6047,15299,24807,230655,2599167,4967935,7401983,9764863,688,10197,19449,2388223,4756735,7125503,9559551,11927551,187,5088,2308095,4676607,7110911,9479423,11913727,14282239];for(I=0;I<256;I++)D0=e0[I],e0[I]=f0(D0)|4278190080;var D0,I;var Q0="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";var S0=[{id:"01-helloworlds.asm",name:"Hello World (ASM)"},{id:"02-telephone.asm",name:"Telephone (ASM)"},{id:"03-horcbpal.asm",name:"Paddle Demo (ASM)"},{id:"hello.c",name:"Hello Graphics"},{id:"lines.c",name:"Lines"},{id:"sprites.c",name:"Sprites"},{id:"vsync.c",name:"Sprites w/ VSYNC"},{id:"fastsprites.c",name:"Fast Sprites"},{id:"music.c",name:"Music"},{id:"rotate.c",name:"Rotate Op"},{id:"rainbow.c",name:"Rainbow"},{id:"cosmic.c",name:"Cosmic Impalas Game"},{id:"racing.c",name:"Pseudo 3-D Racing Game"}],M0=[{id:"bios.c",name:"BIOS"}],V0=[{id:"hello.c",name:"Hello Graphics"}],G=class extends m0{constructor(){super(...arguments);this.getMemoryMap=function(){return{main:[{name:"BIOS",start:0,size:8192,type:"rom"},{name:"Screen RAM",start:16384,size:4096,type:"ram"},{name:"BIOS Variables",start:20430,size:50,type:"ram"}]}}}newMachine(){return new P(!1)}getPresets(){return S0}readAddress(t){return this.machine.read(t)}showHelp(){return"https://8bitworkshop.com/docs/platforms/astrocade/"}},x0=class extends G{getPresets(){return M0}loadROM(d,t){this.machine.loadBIOS(t)}},t0=class extends G{constructor(){super(...arguments);this.getMemoryMap=function(){return{main:[{name:"ROM",start:0,size:16384,type:"rom"},{name:"Magic RAM",start:0,size:16384,type:"ram"},{name:"Screen RAM",start:16384,size:16384,type:"ram"},{name:"ROM",start:32768,size:16384,type:"rom"}]}}}newMachine(){return new P(!0)}getPresets(){return V0}};k.astrocade=G;k["astrocade-bios"]=x0;k["astrocade-arcade"]=t0; -//# sourceMappingURL=astrocade-SQ7A55O6.js.map diff --git a/gen/astrocade-SQ7A55O6.js.map b/gen/astrocade-SQ7A55O6.js.map deleted file mode 100644 index 87b59e25..00000000 --- a/gen/astrocade-SQ7A55O6.js.map +++ /dev/null @@ -1,7 +0,0 @@ -{ - "version": 3, - "sources": ["../src/machine/astrocade.ts", "../src/platform/astrocade.ts"], - "sourcesContent": ["\nimport { Z80, Z80State } from \"../common/cpu/ZilogZ80\";\nimport { BasicScanlineMachine, AcceptsPaddleInput, Bus } from \"../common/devices\";\nimport { KeyFlags, newAddressDecoder, padBytes, Keys, makeKeycodeMap, newKeyboardHandler } from \"../common/emu\";\nimport { TssChannelAdapter, MasterAudio, AY38910_Audio } from \"../common/audio\";\nimport { hex, rgb2bgr, lzgmini, stringToByteArray } from \"../common/util\";\n\n// http://metopal.com/projects/ballybook/doku.php\n\n// TODO: fix keys, more controllers, vibrato/noise, border color\n// http://atariage.com/forums/topic/251416-programming-the-bally-arcadeastrocade/\n// https://ballyalley.com/faqs/BPA%20Video%20Hardware%20FAQ/Bally_Professional_Arcade_Video_Hardware%20(2001)(Tony%20Miller).pdf\n// https://atariage.com/forums/topic/290858-notes-from-a-2019-interview-with-jamie-fenton/ (http://www.fentonia.com/bio/)\n// https://thehistoryofhowweplay.wordpress.com/2018/04/03/interview-tom-mchugh/\n// https://ballyalley.com/faqs/Programmers%20of%20the%20Astrocade%20Built-In%20Programs.txt\n\nconst ASTROCADE_KEYCODE_MAP = makeKeycodeMap([\n // player 1\n [Keys.UP, 0x10, 0x1],\n [Keys.DOWN, 0x10, 0x2],\n [Keys.LEFT, 0x10, 0x4],\n [Keys.RIGHT, 0x10, 0x8],\n [Keys.A, 0x10, 0x10],\n // player 2\n [Keys.P2_UP, 0x11, 0x1],\n [Keys.P2_DOWN, 0x11, 0x2],\n [Keys.P2_LEFT, 0x11, 0x4],\n [Keys.P2_RIGHT, 0x11, 0x8],\n [Keys.P2_A, 0x11, 0x10],\n // keypad $14\n [Keys.VK_P, 0x14, 0x1],\n [Keys.VK_SLASH, 0x14, 0x2],\n [Keys.VK_X, 0x14, 0x4],\n [Keys.VK_MINUS, 0x14, 0x8],\n [Keys.VK_COMMA, 0x14, 0x10],\n [Keys.VK_EQUALS, 0x14, 0x20],\n // keypad $15\n [Keys.VK_O, 0x15, 0x1],\n [Keys.VK_L, 0x15, 0x2],\n [Keys.VK_9, 0x15, 0x4],\n [Keys.VK_6, 0x15, 0x8],\n [Keys.VK_3, 0x15, 0x10],\n [Keys.VK_PERIOD, 0x15, 0x20],\n // keypad $16\n [Keys.VK_I, 0x16, 0x1],\n [Keys.VK_K, 0x16, 0x2],\n [Keys.VK_8, 0x16, 0x4],\n [Keys.VK_5, 0x16, 0x8],\n [Keys.VK_2, 0x16, 0x10],\n [Keys.VK_0, 0x16, 0x20],\n // keypad $17\n [Keys.VK_U, 0x17, 0x1],\n [Keys.VK_J, 0x17, 0x2],\n [Keys.VK_7, 0x17, 0x4],\n [Keys.VK_4, 0x17, 0x8],\n [Keys.VK_1, 0x17, 0x10],\n [Keys.VK_BACK_SLASH, 0x17, 0x20],\n]);\n\nconst audioOversample = 2;\n\nconst _BallyAstrocade = function(arcade:boolean) {\n\n var cpu : Z80;\n var ram : Uint8Array;\n var membus, iobus : Bus;\n var rom, bios;\n var pixels;\n var psg;\n //var watchdog_counter;\n const swidth = arcade ? 320 : 160;\n const sheight = arcade ? 204 : 102;\n const swbytes = swidth >> 2;\n const samask = arcade ? 0x3fff : 0xfff;\n const INITIAL_WATCHDOG = 256;\n const PIXEL_ON = 0xffeeeeee;\n const PIXEL_OFF = 0xff000000;\n\n // state variables\n var inputs = new Uint8Array(0x20);\n var magicop = 0;\n var xpand = 0;\n var xplower = false;\n var shift2 = 0;\n var horcb = 0;\n var inmod = 0;\n var inlin = 0;\n var infbk = 0;\n var verbl = sheight;\n var palette = new Uint32Array(8);\n var palinds = new Uint8Array(8);\n var refreshlines = 0;\n var dirtylines = new Uint8Array(arcade ? 262 : 131);\n var rotdata = new Uint8Array(4);\n var rotcount = 0;\n var intst = 0;\n var waitstates = 0;\n var patboard = new Uint8Array(0x08);\n var patdest = 0;\n\n function ramwrite(a: number, v: number) {\n // set RAM\n ram[a] = v;\n waitstates++;\n // mark scanline as dirty\n dirtylines[((a & samask) / swbytes) | 0] = 1;\n // this was old behavior where we updated instantly\n // but it had problems if we had mid-screen palette changes\n //ramupdate(a, v);\n }\n\n function ramupdate(a: number, v: number) {\n var ofs = a * 4 + 3; // 4 pixels per byte\n for (var i = 0; i < 4; i++) {\n var lr = ((a % swbytes) >= (horcb & 0x3f)) ? 0 : 4;\n pixels[ofs--] = palette[lr + (v & 3)];\n v >>= 2;\n }\n }\n\n function refreshline(y: number) {\n var ofs = y * swidth / 4;\n for (var i = 0; i < swidth / 4; i++)\n ramupdate(ofs + i, ram[ofs + i]);\n }\n\n function magicwrite(a: number, v: number) {\n // expand\n if (magicop & 0x8) {\n var v2 = 0;\n if (!xplower)\n v >>= 4;\n for (var i = 0; i < 4; i++) {\n var pix = (v & 1) ? ((xpand >> 2) & 3) : (xpand & 3);\n v2 |= pix << (i * 2);\n v >>= 1;\n }\n v = v2;\n xplower = !xplower;\n }\n // rotate\n if (magicop & 0x4) {\n if (rotcount & 4) {\n // drain buffer\n var sh = 2 * (~rotcount & 3);\n v = (((rotdata[3] >> sh) & 3) << 6) |\n (((rotdata[2] >> sh) & 3) << 4) |\n (((rotdata[1] >> sh) & 3) << 2) |\n (((rotdata[0] >> sh) & 3) << 0);\n } else {\n // fill buffer\n rotdata[rotcount & 3] = v;\n }\n rotcount++;\n } else {\n // shift\n var sh = (magicop & 3) << 1;\n var v2 = (v >> sh) | shift2;\n shift2 = (v << (8 - sh)) & 0xff;\n v = v2;\n }\n // flop\n if (magicop & 0x40) {\n v =\n ((v & 0x03) << 6) |\n ((v & 0x0c) << 2) |\n ((v & 0x30) >> 2) |\n ((v & 0xc0) >> 6);\n }\n // or/xor\n if (magicop & 0x30) {\n var oldv = ram[a];\n // collision detect\n var icpt = 0;\n if ((oldv & 0xc0) && (v & 0xc0)) icpt |= 0x1;\n if ((oldv & 0x30) && (v & 0x30)) icpt |= 0x2;\n if ((oldv & 0x0c) && (v & 0x0c)) icpt |= 0x4;\n if ((oldv & 0x03) && (v & 0x03)) icpt |= 0x8;\n // apply op\n if (magicop & 0x10)\n v |= oldv;\n if (magicop & 0x20)\n v ^= oldv; // TODO: what if both?\n // upper 4 bits persist, lower are just since last write\n intst = (intst & 0xf0) | icpt | (icpt << 4);\n }\n // commit write to ram/screen\n ramwrite(a, v);\n }\n\n function setpalette(a: number, v: number) {\n palinds[a & 7] = v & 0xff;\n palette[a & 7] = ASTROCADE_PALETTE[v & 0xff];\n refreshall();\n }\n\n function setbordercolor() {\n var col = horcb >> 6;\n // TODO\n }\n\n function refreshall() {\n refreshlines = sheight;\n }\n\n // bally astrocade pattern board\n // https://github.com/mamedev/mame/blob/7ff10685c56a6e123336c684e5e96fdb9e8b3674/src/mame/midway/astrocde_v.cpp#L726\n function xfer_patboard() {\n let m_pattern_source = patboard[0] | (patboard[1] << 8);\n let m_pattern_mode = patboard[2] & 0x3f;\n let m_pattern_skip = patboard[3];\n let m_pattern_dest = (patdest & 0xff) | (patboard[4] << 8);\n let m_pattern_width = patboard[5];\n let m_pattern_height = patboard[6] + 1;\n\n let curwidth: number;\n let u13ff: number = 0;\n let cycles: number = 0;\n\n u13ff = 0;\n\n if ((m_pattern_mode & 0x02) === 0) {\n u13ff = 1;\n }\n\n function incrementSource(): void {\n if (u13ff && (m_pattern_mode & 0x04) !== 0 && (curwidth !== 0 || (m_pattern_mode & 0x08) === 0)) {\n m_pattern_source++;\n }\n\n if ((m_pattern_mode & 0x02) !== 0) {\n u13ff ^= 1;\n }\n }\n\n function incrementDest(): void {\n if (curwidth !== 0) {\n if ((m_pattern_mode & 0x20) !== 0) {\n m_pattern_dest++;\n } else {\n m_pattern_dest--;\n }\n }\n }\n\n // Loop over height\n while (m_pattern_height >= 0) {\n let carry: number;\n\n curwidth = m_pattern_width;\n\n // Loop over width\n while (curwidth >= 0) {\n let busaddr: number;\n let busdata: number;\n\n // Read Phase\n busaddr = (m_pattern_mode & 0x01) === 0 ? m_pattern_source : m_pattern_dest;\n\n if (curwidth === 0 && (m_pattern_mode & 0x08) !== 0) {\n busdata = 0;\n } else {\n busdata = membus.read(m_pattern_source);\n }\n\n if ((m_pattern_mode & 0x01) === 0) {\n incrementSource();\n } else {\n incrementDest();\n }\n\n // Write Phase\n busaddr = (m_pattern_mode & 0x01) !== 0 ? m_pattern_source : m_pattern_dest;\n ramwrite(busaddr, busdata);\n\n if ((m_pattern_mode & 0x01) === 0) {\n incrementDest();\n } else {\n incrementSource();\n }\n\n cycles += 4;\n curwidth--;\n }\n\n // At the end of each row, adjust m_pattern_dest\n carry = ((m_pattern_dest & 0xff) + m_pattern_skip) & 0x100;\n m_pattern_dest = (m_pattern_dest & 0xff00) | ((m_pattern_dest + m_pattern_skip) & 0xff);\n\n if ((m_pattern_mode & 0x10) === 0) {\n m_pattern_dest += carry;\n } else {\n m_pattern_dest -= carry ^ 0x100;\n }\n\n m_pattern_height--;\n }\n\n // Adjust m_maincpu.icount\n // m_maincpu.adjust_icount(-cycles);\n // Replace the above line with the actual adjustment of icount.\n }\n \n this.drawScanline = (sl:number) => {\n // interrupt\n if (sl == inlin && (inmod & 0x8)) {\n cpu.retryInterrupts = !(inmod & 0x4);\n this.probe && this.probe.logInterrupt(infbk);\n cpu.interrupt(infbk);\n }\n // refresh this line in frame buffer?\n if (sl < sheight && refreshlines > 0) {\n dirtylines[sl] = 0;\n refreshline(sl);\n refreshlines--;\n }\n else if (dirtylines[sl]) {\n dirtylines[sl] = 0;\n refreshline(sl);\n }\n }\n \n this.init = (machine:BallyAstrocade, c:Z80, r:Uint8Array, inp:Uint8Array, psgg) => {\n cpu = c;\n ram = r;\n inputs = inp;\n psg = psgg;\n if (!arcade) {\n //bios = padBytes(ASTROCADE_MINIMAL_BIOS, 0x2000);\n bios = padBytes(new lzgmini().decode(stringToByteArray(atob(ASTROLIBRE_BIOS_LZG))), 0x2000);\n // game console\n membus = {\n read: newAddressDecoder([\n [0x0000, 0x1fff, 0x1fff, function(a) { return bios[a]; }],\n [0x2000, 0x3fff, 0x1fff, function(a) { return rom ? rom[a] : 0; }],\n [0x4000, 0x4fff, 0xfff, function(a) { waitstates++; return ram[a]; }],\n ]),\n write: newAddressDecoder([\n [0x4000, 0x4fff, 0xfff, ramwrite],\n [0x0000, 0x3fff, 0xfff, magicwrite],\n ]),\n }\n } else {\n // arcade game (TODO: wait states 1/4 of the time)\n membus = {\n read: newAddressDecoder([\n [0x4000, 0x7fff, 0x3fff, function(a) { return ram[a]; }],\t// screen RAM\n [0xd000, 0xdfff, 0x0fff, function(a) { return ram[a + 0x4000]; }], // static RAM\n [0x0000, 0x3fff, 0x3fff, function(a) { return rom ? rom[a] : 0; }], // ROM\n [0x8000, 0xbfff, 0x3fff, function(a) { return rom ? rom[a + 0x4000] : 0; }], // ROM\n ]),\n write: newAddressDecoder([\n [0x4000, 0x7fff, 0x3fff, ramwrite],\n [0x0000, 0x3fff, 0x3fff, magicwrite],\n [0xd000, 0xdfff, 0x0fff, function(a, v) { ramwrite(a + 0x4000, v); }], // static RAM\n ]),\n }\n }\n iobus = {\n read: function(addr) {\n addr &= 0x1f;\n var rtn;\n switch (addr) {\n case 8:\n rtn = intst;\n intst = 0;\n break;\n default:\n rtn = inputs[addr];\n break;\n // $10 = watchdog\n }\n return rtn;\n },\n write: function(addr, val) {\n if (addr == 0xa55b) {\n // TODO: protected_ram_enable_w\n return;\n }\n addr &= 0xff;\n // pattern board\n if (addr > 0x78 && addr < 0x80) {\n patboard[addr & 7] = val;\n if (addr == 0x72) { patdest = 0; }\n if (addr == 0x74) { patdest = (patdest + patboard[3]) & 0xff; }\n if (addr == 0x7e) { xfer_patboard(); }\n return;\n }\n addr &= 0x1f;\n val &= 0xff;\n switch (addr) {\n case 0:\n case 1:\n case 2:\n case 3:\n case 4:\n case 5:\n case 6:\n case 7:\n setpalette(addr, val);\n break;\n case 9: // HORCB (horizontal boundary byte)\n horcb = val;\n setbordercolor();\n refreshall();\n break;\n case 0xa: // VERBL (vertical blank)\n verbl = arcade ? val : val >> 1;\n refreshall();\n break;\n case 0xb: // OTIR (set palette)\n var c = cpu.saveState();\n //console.log(c.BC>>8, c.HL);\n setpalette((c.BC >> 8) - 1, membus.read(c.HL));\n break;\n case 0xc: // magic register\n magicop = val;\n shift2 = 0;\n rotcount = 0;\n xplower = false;\n break;\n case 0xd: // INFBK (interrupt feedback)\n infbk = val;\n break;\n case 0xe: // INMOD (interrupt enable)\n inmod = val;\n break;\n case 0xf: // INLIN (interrupt line)\n inlin = arcade ? val : val >> 1;\n break;\n case 0x10:\n case 0x11:\n case 0x12:\n case 0x13:\n case 0x14:\n case 0x15:\n case 0x16:\n case 0x17:\n psg.setACRegister(addr, val);\n break;\n case 0x18:\n var c = cpu.saveState();\n psg.setACRegister((c.BC >> 8) - 1, membus.read(c.HL));\n break;\n case 0x19: // XPAND\n xpand = val;\t\n break;\n case 0x1a:\n case 0x1b:\n case 0x1c:\n case 0x1d:\n case 0x1e:\n //psg2.setACRegister(addr - 0x1a, val);\n break;\n default:\n //console.log('IO write', hex(addr, 4), hex(val, 2));\n break;\n }\n }\n }\n machine.connectCPUMemoryBus(membus);\n machine.connectCPUIOBus(iobus);\n this.membus = membus;\n this.iobus = iobus;\n // default palette\n for (var i = 0; i < 8; i++) {\n setpalette(i,i);\n }\n };\n\n this.resetWaitStates = function(sl) {\n var n = sl < verbl ? waitstates : 0; // only wait if video active\n waitstates = 0;\n return n;\n }\n\n this.loadState = (state) => {\n cpu.loadState(state.c);\n ram.set(state.ram);\n palette.set(state.palette);\n palinds.set(state.palinds);\n magicop = state.magicop;\n xpand = state.xpand;\n xplower = state.xplower;\n shift2 = state.shift2;\n horcb = state.horcb;\n inmod = state.inmod;\n inlin = state.inlin;\n infbk = state.infbk;\n verbl = state.verbl;\n rotcount = state.rotcount;\n rotdata.set(state.rotdata);\n intst = state.intst;\n inputs.set(state.inputs);\n patboard.set(state.patboard);\n patdest = state.patdest;\n refreshall();\n }\n \n this.saveState = () => {\n return {\n c: cpu.saveState(),\n ram: ram.slice(0),\n inputs: inputs.slice(0),\n palette: palette.slice(0),\n palinds: palinds.slice(0),\n magicop: magicop,\n xpand: xpand,\n xplower: xplower,\n shift2: shift2,\n horcb: horcb,\n inmod: inmod,\n inlin: inlin,\n infbk: infbk,\n verbl: verbl,\n rotcount: rotcount,\n rotdata: rotdata.slice(0),\n intst: intst,\n patboard: patboard.slice(0),\n patdest: patdest,\n };\n }\n this.reset = () => {\n // TODO?\n magicop = xpand = inmod = inlin = infbk = shift2 = horcb = 0;\n verbl = sheight;\n xplower = false;\n //watchdog_counter = INITIAL_WATCHDOG;\n }\n \n this.toLongString = (st) => {\n var s = \"\";\n //s += \" Scan Y: \" + st.sl;\n s += \"\\n INLIN: \" + st.inlin;\n s += \"\\n VERBL: \" + st.verbl;\n s += \"\\nMAGICOP: $\" + hex(st.magicop);\n s += \"\\n XPAND: $\" + hex(st.xpand);\n s += \"\\nXPLOWER: \" + st.xplower;\n s += \"\\n SHIFT2: $\" + hex(st.shift2);\n s += \"\\n HORCB: $\" + hex(st.horcb);\n s += \"\\n INMOD: $\" + hex(st.inmod);\n s += \"\\n INFBK: $\" + hex(st.infbk);\n s += \"\\n INTST: $\" + hex(st.intst); // intercept status\n s += \"\\nPalette: \";\n for (var i = 0; i < 8; i++)\n s += hex(palinds[i]);\n s += \"\\n\";\n return s;\n }\n \n this.connectVideo = function(pix) {\n pixels = pix;\n }\n this.loadROM = function(data) {\n rom = data;\n }\n this.loadBIOS = function(data) {\n bios = data;\n }\n this.getVisiblePixelWords = function() {\n return verbl * swidth;\n }\n}\n\nexport class BallyAstrocade extends BasicScanlineMachine implements AcceptsPaddleInput {\n \n cpuFrequency = 1789000;\n numTotalScanlines = 262;\n numVisibleScanlines : number;\n cpuCyclesPerLine : number;\n defaultROMSize : number;\n canvasWidth : number;\n sampleRate = 60 * 262 * audioOversample;\n ram : Uint8Array;\n cpu : Z80;\n m; // _BallyAstrocade\n arcade : boolean;\n\n psg: AstrocadeAudio;\n audioadapter;\n backbuffer : Uint32Array;\n frontbuffer : Uint32Array;\n\n constructor(arcade:boolean) {\n super();\n this.arcade = arcade;\n this.cpu = new Z80();\n this.psg = new AstrocadeAudio(new MasterAudio());\n this.audioadapter = new TssChannelAdapter(this.psg.psg, audioOversample, this.sampleRate);\n this.handler = newKeyboardHandler(this.inputs, ASTROCADE_KEYCODE_MAP);\n this.defaultROMSize = arcade ? 0xb000 : 0x2000;\n this.ram = new Uint8Array(arcade ? 0x5000 : 0x1000);\n this.numVisibleScanlines = arcade ? 204 : 102;\n this.canvasWidth = arcade ? 320 : 160;\n this.cpuCyclesPerLine = (this.cpuFrequency / (60 * this.numVisibleScanlines * 1.286)) | 0;\n //this.cpuCyclesPerHBlank = Math.floor(this.cpuCyclesPerLine * 0.33);\n //this.cpuCyclesPerVisible = this.cpuCyclesPerLine - this.cpuCyclesPerHBlank;\n this.m = new _BallyAstrocade(arcade);\n this.m.init(this, this.cpu, this.ram, this.inputs, this.psg);\n if (arcade) {\n this.inputs[0x10] = 0xff; // switches (active low)\n this.inputs[0x11] = 0xff; // switches (active low)\n this.inputs[0x12] = 0x00;\n this.inputs[0x13] = 0x08; // dip switches\n }\n }\n \n read(a:number) : number {\n return this.m.membus.read(a);\n }\n write(a:number, v:number) : void {\n this.m.membus.write(a,v);\n }\n \n connectVideo(pixels:Uint32Array) : void {\n super.connectVideo(pixels);\n this.frontbuffer = pixels;\n this.backbuffer = new Uint32Array(pixels.length);\n this.m.connectVideo(this.backbuffer);\n }\n preFrame() {\n this.m.resetWaitStates(0);\n }\n postFrame() {\n // copy back buffer to front buffer, omitting bottom non-visible pixels\n var nbytes = this.m.getVisiblePixelWords();\n this.frontbuffer.set(this.backbuffer.slice(0, nbytes), 0);\n this.frontbuffer.fill(0, nbytes);\n }\n\n setPaddleInput(controller:number, value:number) : void {\n switch (controller) {\n case 0: this.inputs[0x1c] = value & 0xff; break;\n case 1: this.inputs[0x1d] = value & 0xff; break;\n }\n }\n\n startScanline() {\n this.audio && this.audioadapter.generate(this.audio);\n }\n \n drawScanline() {\n var sl = this.scanline;\n this.m.drawScanline(sl);\n /*\n if (watchdog_counter-- <= 0) {\n console.log(\"WATCHDOG FIRED\"); // TODO: alert on video\n this.reset();\n }\n */\n }\n\n advanceCPU() {\n var clk = super.advanceCPU();\n // TODO: disable 33% of the time (hblank)\n var xtra = this.m.resetWaitStates(this.scanline);\n if (xtra) {\n clk += xtra;\n this.probe.logClocks(xtra);\n }\n return clk;\n }\n\n loadROM(data) {\n super.loadROM(data);\n this.m.loadROM(this.rom);\n this.reset();\n }\n loadBIOS(data) {\n this.m.loadBIOS(padBytes(data, 0x2000));\n this.reset();\n }\n reset() {\n super.reset();\n this.m.reset();\n }\n loadState(state) {\n this.m.loadState(state);\n }\n saveState() {\n return this.m.saveState();\n }\n getDebugCategories() {\n return ['CPU','Stack','Astro'];\n }\n getDebugInfo(category, state) {\n switch (category) {\n case 'Astro': return this.m.toLongString(state);\n }\n }\n getRasterCanvasPosition() {\n return { x: this.getRasterX(), y: this.getRasterY() };\n }\n getVideoParams() {\n if (this.arcade) {\n return { width: 320, height: 204, rotate: 180 };\n } else {\n return { width: 160, height: 102 };\n }\n }\n}\n\n/////\n\n// TODO: https://github.com/mamedev/mame/blob/master/src/devices/sound/astrocde.cpp\nclass AstrocadeAudio extends AY38910_Audio {\n setACRegister(addr: number, val: number) {\n addr &= 0x7;\n val &= 0xff;\n switch (addr) {\n case 0:\n this.psg.setClock(1789000 * 16 / (val + 1));\n this.psg.writeRegisterAY(7, 0x7 ^ 0xff); // disable noise\n break;\n case 1:\n case 2:\n case 3:\n var i = (addr - 1) * 2;\n var j = val * 2 + 1;\n this.psg.writeRegisterAY(i, j & 0xff); // freq lo\n this.psg.writeRegisterAY(i + 1, (j >> 8) & 0xff); // freq hi\n break;\n case 5:\n this.psg.writeRegisterAY(10, val & 0xf); // tone c vol\n break;\n case 6:\n this.psg.writeRegisterAY(8, val & 0xf);\t// tone a vol\n this.psg.writeRegisterAY(9, (val >> 4) & 0xf); // tone b vol\n break;\n }\n }\n}\n\n/////\n\n//http://glankonian.com/~lance/astrocade_palette.html\nvar ASTROCADE_PALETTE = [0x000000, 0x242424, 0x484848, 0x6D6D6D, 0x919191, 0xB6B6B6, 0xDADADA, 0xFFFFFF, 0x2500BB, 0x4900E0, 0x6E11FF, 0x9235FF, 0xB75AFF, 0xDB7EFF, 0xFFA3FF, 0xFFC7FF, 0x4900B0, 0x6D00D5, 0x9201F9, 0xB625FF, 0xDA4AFF, 0xFF6EFF, 0xFF92FF, 0xFFB7FF, 0x6A009F, 0x8E00C3, 0xB300E7, 0xD718FF, 0xFB3CFF, 0xFF61FF, 0xFF85FF, 0xFFA9FF, 0x870087, 0xAB00AB, 0xD000D0, 0xF40EF4, 0xFF32FF, 0xFF56FF, 0xFF7BFF, 0xFF9FFF, 0x9F006A, 0xC3008E, 0xE700B3, 0xFF07D7, 0xFF2CFB, 0xFF50FF, 0xFF74FF, 0xFF99FF, 0xB00049, 0xD5006D, 0xF90092, 0xFF05B6, 0xFF29DA, 0xFF4DFF, 0xFF72FF, 0xFF96FF, 0xBB0025, 0xE00049, 0xFF006E, 0xFF0692, 0xFF2AB7, 0xFF4FDB, 0xFF73FF, 0xFF98FF, 0xBF0000, 0xE30024, 0xFF0048, 0xFF0B6D, 0xFF3091, 0xFF54B6, 0xFF79DA, 0xFF9DFF, 0xBB0000, 0xE00000, 0xFF0023, 0xFF1447, 0xFF396C, 0xFF5D90, 0xFF82B5, 0xFFA6D9, 0xB00000, 0xD50000, 0xF90000, 0xFF2124, 0xFF4548, 0xFF6A6C, 0xFF8E91, 0xFFB3B5, 0x9F0000, 0xC30000, 0xE70C00, 0xFF3003, 0xFF5527, 0xFF794B, 0xFF9E70, 0xFFC294, 0x870000, 0xAB0000, 0xD01E00, 0xF44200, 0xFF670A, 0xFF8B2E, 0xFFAF53, 0xFFD477, 0x6A0000, 0x8E0D00, 0xB33100, 0xD75600, 0xFB7A00, 0xFF9E17, 0xFFC33B, 0xFFE75F, 0x490000, 0x6D2100, 0x924500, 0xB66A00, 0xDA8E00, 0xFFB305, 0xFFD729, 0xFFFC4E, 0x251100, 0x493500, 0x6E5A00, 0x927E00, 0xB7A300, 0xDBC700, 0xFFEB1E, 0xFFFF43, 0x002500, 0x244900, 0x486D00, 0x6D9200, 0x91B600, 0xB6DB00, 0xDAFF1B, 0xFFFF3F, 0x003700, 0x005B00, 0x238000, 0x47A400, 0x6CC900, 0x90ED00, 0xB5FF1E, 0xD9FF43, 0x004700, 0x006C00, 0x009000, 0x24B400, 0x48D900, 0x6CFD05, 0x91FF29, 0xB5FF4E, 0x005500, 0x007900, 0x009D00, 0x03C200, 0x27E600, 0x4BFF17, 0x70FF3B, 0x94FF5F, 0x005F00, 0x008300, 0x00A800, 0x00CC00, 0x0AF00A, 0x2EFF2E, 0x53FF53, 0x77FF77, 0x006500, 0x008A00, 0x00AE00, 0x00D203, 0x00F727, 0x17FF4B, 0x3BFF70, 0x5FFF94, 0x006800, 0x008C00, 0x00B100, 0x00D524, 0x00F948, 0x05FF6C, 0x29FF91, 0x4EFFB5, 0x006600, 0x008B00, 0x00AF23, 0x00D447, 0x00F86C, 0x00FF90, 0x1EFFB5, 0x43FFD9, 0x006100, 0x008524, 0x00AA48, 0x00CE6D, 0x00F391, 0x00FFB6, 0x1BFFDA, 0x3FFFFE, 0x005825, 0x007C49, 0x00A16E, 0x00C592, 0x00EAB7, 0x00FFDB, 0x1EFFFF, 0x43FFFF, 0x004B49, 0x00706D, 0x009492, 0x00B9B6, 0x00DDDA, 0x05FFFF, 0x29FFFF, 0x4EFFFF, 0x003C6A, 0x00608E, 0x0085B3, 0x00A9D7, 0x00CEFB, 0x17F2FF, 0x3BFFFF, 0x5FFFFF, 0x002A87, 0x004FAB, 0x0073D0, 0x0097F4, 0x0ABCFF, 0x2EE0FF, 0x53FFFF, 0x77FFFF, 0x00179F, 0x003BC3, 0x0060E7, 0x0384FF, 0x27A8FF, 0x4BCDFF, 0x70F1FF, 0x94FFFF, 0x0002B0, 0x0027D5, 0x004BF9, 0x2470FF, 0x4894FF, 0x6CB9FF, 0x91DDFF, 0xB5FFFF, 0x0000BB, 0x0013E0, 0x2337FF, 0x475BFF, 0x6C80FF, 0x90A4FF, 0xB5C9FF, 0xD9EDFF];\n// swap palette RGB to BGR\nfor (var i = 0; i < 256; i++) {\n var x = ASTROCADE_PALETTE[i];\n ASTROCADE_PALETTE[i] = rgb2bgr(x) | 0xff000000;\n}\n\n/*\n0000 F3 [ 4] 196 \tDI\t; disable interrupts\n0001 21 00 20 [10] 197 \tLD\tHL,#0x2000\n0004 7E [ 7] 198 \tLD\tA,(HL) ; A <- mem[0x2000]\n0005 FE 55 [ 7] 199 \tCP\t#0x55 ; found sentinel byte? ($55)\n0007 CA 0D 00 [10] 200 \tJP\tZ,FoundSentinel ; yes, load program\n000A C3 00 20 [10] 201 \tJP\t_main ; jump to test program\n000D 202 \tFoundSentinel:\n000D 31 CE 4F [10] 203 \tLD\tSP,#0x4fce ; position stack below BIOS vars\n0010 CD 84 02 [17] 204 \tCALL\t_bios_init ; misc. bios init routines\n0013 21 05 20 [10] 205 \tLD\tHL,#0x2005 ; cartridge start vector\n0016 7E [ 7] 206 \tLD\tA,(HL)\n0017 23 [ 6] 207 \tINC\tHL\n0018 66 [ 7] 208 \tLD\tH,(HL)\n0019 6F [ 4] 209 \tLD\tL,A\n001A E9 [ 4] 210 \tJP\t(HL) ; jump to cart start vector\n*/\nvar ASTROCADE_MINIMAL_BIOS = [\n 0xf3, 0x21, 0x00, 0x20, 0x7e, 0xfe, 0x55, 0xca, 0x0d, 0x00, 0xc3, 0x00, 0x20,\n 0x31, 0xce, 0x4f,\n 0x21, 0x05, 0x20, 0x7e, 0x23, 0x66, 0x6f,\n 0xe9,\n];\n\nvar ASTROLIBRE_BIOS_LZG = `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`;\n\n", "\nimport { BallyAstrocade } from \"../machine/astrocade\";\nimport { BaseZ80MachinePlatform } from \"../common/baseplatform\";\nimport { Platform } from \"../common/baseplatform\";\nimport { PLATFORMS } from \"../common/emu\";\n\n// http://metopal.com/projects/ballybook/doku.php\n\nconst ASTROCADE_PRESETS = [\n { id: '01-helloworlds.asm', name: 'Hello World (ASM)' },\n { id: '02-telephone.asm', name: 'Telephone (ASM)' },\n { id: '03-horcbpal.asm', name: 'Paddle Demo (ASM)' },\n { id: 'hello.c', name: 'Hello Graphics' },\n { id: 'lines.c', name: 'Lines' },\n { id: 'sprites.c', name: 'Sprites' },\n { id: 'vsync.c', name: 'Sprites w/ VSYNC' },\n { id: 'fastsprites.c', name: 'Fast Sprites' },\n { id: 'music.c', name: 'Music' },\n { id: 'rotate.c', name: 'Rotate Op' },\n { id: 'rainbow.c', name: 'Rainbow' },\n { id: 'cosmic.c', name: 'Cosmic Impalas Game' },\n { id: 'racing.c', name: 'Pseudo 3-D Racing Game' },\n];\n\nconst ASTROCADE_BIOS_PRESETS = [\n { id: 'bios.c', name: 'BIOS' },\n];\n\nconst ASTROCADE_ARCADE_PRESETS = [\n { id: 'hello.c', name: 'Hello Graphics' },\n];\n\nclass BallyAstrocadePlatform extends BaseZ80MachinePlatform implements Platform {\n\n newMachine() { return new BallyAstrocade(false); }\n getPresets() { return ASTROCADE_PRESETS; }\n readAddress(a) { return this.machine.read(a); }\n getMemoryMap = function() { return { main:[\n {name:'BIOS',start:0x0,size:0x2000,type:'rom'},\n //{name:'Cart ROM',start:0x2000,size:0x2000,type:'rom'},\n //{name:'Magic RAM',start:0x0,size:0x4000,type:'ram'},\n {name:'Screen RAM',start:0x4000,size:0x1000,type:'ram'},\n {name:'BIOS Variables',start:0x4fce,size:0x5000-0x4fce,type:'ram'},\n ] } };\n showHelp() { return \"https://8bitworkshop.com/docs/platforms/astrocade/\"; }\n}\n\nclass BallyAstrocadeBIOSPlatform extends BallyAstrocadePlatform implements Platform {\n\n getPresets() { return ASTROCADE_BIOS_PRESETS; }\n loadROM(title,rom) { this.machine.loadBIOS(rom); }\n\n}\n\nclass BallyArcadePlatform extends BallyAstrocadePlatform implements Platform {\n\n newMachine() { return new BallyAstrocade(true); }\n getPresets() { return ASTROCADE_ARCADE_PRESETS; }\n\n getMemoryMap = function() { return { main:[\n {name:'ROM',start:0x0,size:0x4000,type:'rom'},\n {name:'Magic RAM',start:0x0,size:0x4000,type:'ram'},\n {name:'Screen RAM',start:0x4000,size:0x4000,type:'ram'},\n {name:'ROM',start:0x8000,size:0x4000,type:'rom'},\n ] } };\n}\n\nPLATFORMS['astrocade'] = BallyAstrocadePlatform;\nPLATFORMS['astrocade-bios'] = BallyAstrocadeBIOSPlatform;\nPLATFORMS['astrocade-arcade'] = BallyArcadePlatform;\n\n"], - "mappings": "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", - "names": ["ASTROCADE_KEYCODE_MAP", "makeKeycodeMap", "Keys", "audioOversample", "_BallyAstrocade", "arcade", "cpu", "ram", "membus", "iobus", "rom", "bios", "pixels", "psg", "swidth", "sheight", "swbytes", "samask", "INITIAL_WATCHDOG", "PIXEL_ON", "PIXEL_OFF", "inputs", "magicop", "xpand", "xplower", "shift2", "horcb", "inmod", "inlin", "infbk", "verbl", "palette", "palinds", "refreshlines", "dirtylines", "rotdata", "rotcount", "intst", "waitstates", "patboard", "patdest", "ramwrite", "a", "v", "ramupdate", "ofs", "i", "lr", "refreshline", "y", "magicwrite", "v2", "pix", "sh", "oldv", "icpt", "setpalette", "ASTROCADE_PALETTE", "refreshall", "setbordercolor", "col", "xfer_patboard", "m_pattern_source", "m_pattern_mode", "m_pattern_skip", "m_pattern_dest", "m_pattern_width", "m_pattern_height", "curwidth", "u13ff", "cycles", "incrementSource", "incrementDest", "carry", "busaddr", "busdata", "sl", "machine", "c", "r", "inp", "psgg", "newAddressDecoder", "padBytes", "lzgmini", "stringToByteArray", "ASTROLIBRE_BIOS_LZG", "addr", "rtn", "val", "n", "state", "st", "s", "hex", "data", "BallyAstrocade", "BasicScanlineMachine", "Z80", "AstrocadeAudio", "MasterAudio", "TssChannelAdapter", "newKeyboardHandler", "nbytes", "controller", "value", "clk", "xtra", "category", "AY38910_Audio", "j", "x", "rgb2bgr", "ASTROLIBRE_BIOS_LZG", "ASTROCADE_PRESETS", "ASTROCADE_BIOS_PRESETS", "ASTROCADE_ARCADE_PRESETS", "BallyAstrocadePlatform", "BaseZ80MachinePlatform", "BallyAstrocade", "a", "BallyAstrocadeBIOSPlatform", "title", "rom", "BallyArcadePlatform", "PLATFORMS"] -} diff --git a/gen/basic-WBBOCYX7.js b/gen/basic-DESTZ5TS.js similarity index 99% rename from gen/basic-WBBOCYX7.js rename to gen/basic-DESTZ5TS.js index eb2c2e0a..c708e07d 100644 --- a/gen/basic-WBBOCYX7.js +++ b/gen/basic-DESTZ5TS.js @@ -1,4 +1,4 @@ -import{b as S}from"./chunk-3FIVEUG2.js";import{u as E}from"./chunk-PUOMI72S.js";import"./chunk-UG4IOEUD.js";import"./chunk-LNOKARBD.js";import"./chunk-A7SWO6EA.js";import"./chunk-WEPPO4GD.js";import"./chunk-CZ7OSHSE.js";import{B as c,K as f,T as d,U as v,a as g}from"./chunk-TYDI7JZQ.js";import"./chunk-KT7KMEQC.js";function k(u){return u.value!=null}function y(u){return u.name!=null}function O(u){return u.op!=null&&u.left!=null&&u.right!=null}function N(u){return u.op!=null&&u.expr!=null}var m=class{randomize(){this.seed(Math.random()*2147483647,Math.random()*2147483647,Math.random()*2147483647,Math.random()*2147483647)}constructor(){(()=>{var r,e,i,n;this.seed=function(s,a,h,o){r=s,e=a,i=h,n=o},this.seedfloat=function(s){this.seed(s,s*4294,s*429496,s*4294967296),this.next(),this.next(),this.next()},this.next=function(){r>>>=0,e>>>=0,i>>>=0,n>>>=0;var s=r+e|0;return r=e^e>>>9,e=i+(i<<3)|0,i=i<<21|i>>>11,n=n+1|0,s=s+n|0,i=i+s|0,(s>>>0)/4294967296}})(),this.seedfloat(-1)}},I=1024*1024,l=class u{constructor(){this.margin=80;this.running=!1;this.exited=!0;this.trace=!1}load(t){let r=null,e=0;if(this.pc2label!=null){let s=this.curpc;for(;s>0&&(r=this.pc2label.get(s))==null;)s--;e=this.curpc-s,console.log("oldpc=",this.curpc,"restart @ label",r,"+",e)}this.program=t,this.opts=t.opts,this.opts.maxArrayElements||(this.opts.maxArrayElements=I),this.allstmts=t.stmts,this.label2pc=t.labels,this.label2dataptr={},this.pc2label=new Map,this.datums=[],this.subroutines={},this.builtins=this.getBuiltinFunctions();for(var i in t.labels){var n=t.labels[i];this.pc2label.set(n,i)}return this.allstmts.forEach((s,a)=>{this.curpc=a+1,this.compileStatement(s),s.command=="DATA"&&(this.label2dataptr[s.$loc.label]=this.datums.length,s.datums.forEach(h=>{this.curpc=s.$loc.offset,this.datums.push(h)}))}),this.label2pc[r]!=null?(this.curpc=this.label2pc[r]+e,!0):(this.curpc=0,!1)}reset(){this.curpc=0,this.dataptr=0,this.clearVars(),this.returnStack=[],this.column=0,this.running=!0,this.exited=!1}clearVars(){this.globals=this.vars={},this.arrays={},this.defs={},this.forLoops={},this.forLoopStack=[],this.whileLoops=[],this.rng=new m,this.opts&&this.opts.staticArrays&&this.allstmts.filter(t=>t.command=="DIM").forEach(t=>{t.args.forEach(r=>this.compileJS(this._DIM(r))())})}saveState(){return $.extend(!0,{},this)}loadState(t){$.extend(!0,this,t)}getBuiltinFunctions(){var t=this.program&&this.opts.validFunctions;t||(t=Object.getOwnPropertyNames(u.prototype).filter(i=>/^[A-Z]{3,}[$]?$/.test(i)));var r={};for(var e of t)this.supportsFunction(e)&&(r[e]=this[e].bind(this));return r}supportsFunction(t){return typeof this[t]=="function"}runtimeError(t){throw this.curpc--,new d(t,this.getCurrentSourceLocation())}dialectError(t){this.runtimeError(`I can't ${t} in this dialect of BASIC.`)}getLineForPC(t){var r=this.allstmts[t];return r&&r.$loc&&r.$loc.line}getLabelForPC(t){var r=this.allstmts[t];return r&&r.$loc&&r.$loc.label}getCurrentSourceLocation(){var t=this.getStatement();return t&&t.$loc}getCurrentLabel(){var t=this.getCurrentSourceLocation();return t&&t.label}getStatement(){return this.allstmts[this.curpc]}step(){if(!this.running)return!1;var t=this.getStatement();return t?(this.trace&&console.log(this.curpc,t,this.vars,Object.keys(this.arrays)),this.curpc++,this.executeStatement(t),this.running):(this.running=!1,this.exited=!0,!1)}compileStatement(t){if(t.$run==null)try{var r=this["do__"+t.command];r==null&&this.runtimeError(`I don't know how to "${t.command}".`);var e=r.bind(this)(t);this.trace&&console.log(e),t.$run=this.compileJS(e)}catch(i){throw e&&console.log(e),i}}compileJS(t){return new Function(t).bind(this)}executeStatement(t){this.compileStatement(t),t.$run()}skipToEOL(){do this.curpc++;while(this.curpc=0?this.curpc=r:this.runtimeError(`I tried to go to the label "${t}" but couldn't find it.`)}newLocalScope(){this.vars=Object.create(this.vars)}popLocalScope(){this.vars!==this.globals&&(this.vars=Object.getPrototypeOf(this.vars))}gosubLabel(t){this.returnStack.length>32767&&this.runtimeError("I did too many GOSUBs without a RETURN."),this.returnStack.push(this.curpc),this.gotoLabel(t)}returnFromGosub(){this.returnStack.length==0&&this.runtimeError("I tried to RETURN, but there wasn't a corresponding GOSUB.");var t=this.returnStack.pop();this.curpc=t,this.popLocalScope()}popReturnStack(){this.returnStack.length==0&&this.runtimeError("I tried to POP, but there wasn't a corresponding GOSUB."),this.returnStack.pop()}valueToString(t,r){var e;if(typeof t=="number"){var i=this.float2str(t,this.opts.printZoneLength-4);return r?i.startsWith("-")?`${i} `:` ${i} `:i}else if(t==` +import{b as S}from"./chunk-3FIVEUG2.js";import{u as E}from"./chunk-X3GW3E7W.js";import"./chunk-UG4IOEUD.js";import"./chunk-LNOKARBD.js";import"./chunk-A7SWO6EA.js";import"./chunk-THWBEUY4.js";import"./chunk-CZ7OSHSE.js";import{B as c,K as f,T as d,U as v,a as g}from"./chunk-TYDI7JZQ.js";import"./chunk-KT7KMEQC.js";function k(u){return u.value!=null}function y(u){return u.name!=null}function O(u){return u.op!=null&&u.left!=null&&u.right!=null}function N(u){return u.op!=null&&u.expr!=null}var m=class{randomize(){this.seed(Math.random()*2147483647,Math.random()*2147483647,Math.random()*2147483647,Math.random()*2147483647)}constructor(){(()=>{var r,e,i,n;this.seed=function(s,a,h,o){r=s,e=a,i=h,n=o},this.seedfloat=function(s){this.seed(s,s*4294,s*429496,s*4294967296),this.next(),this.next(),this.next()},this.next=function(){r>>>=0,e>>>=0,i>>>=0,n>>>=0;var s=r+e|0;return r=e^e>>>9,e=i+(i<<3)|0,i=i<<21|i>>>11,n=n+1|0,s=s+n|0,i=i+s|0,(s>>>0)/4294967296}})(),this.seedfloat(-1)}},I=1024*1024,l=class u{constructor(){this.margin=80;this.running=!1;this.exited=!0;this.trace=!1}load(t){let r=null,e=0;if(this.pc2label!=null){let s=this.curpc;for(;s>0&&(r=this.pc2label.get(s))==null;)s--;e=this.curpc-s,console.log("oldpc=",this.curpc,"restart @ label",r,"+",e)}this.program=t,this.opts=t.opts,this.opts.maxArrayElements||(this.opts.maxArrayElements=I),this.allstmts=t.stmts,this.label2pc=t.labels,this.label2dataptr={},this.pc2label=new Map,this.datums=[],this.subroutines={},this.builtins=this.getBuiltinFunctions();for(var i in t.labels){var n=t.labels[i];this.pc2label.set(n,i)}return this.allstmts.forEach((s,a)=>{this.curpc=a+1,this.compileStatement(s),s.command=="DATA"&&(this.label2dataptr[s.$loc.label]=this.datums.length,s.datums.forEach(h=>{this.curpc=s.$loc.offset,this.datums.push(h)}))}),this.label2pc[r]!=null?(this.curpc=this.label2pc[r]+e,!0):(this.curpc=0,!1)}reset(){this.curpc=0,this.dataptr=0,this.clearVars(),this.returnStack=[],this.column=0,this.running=!0,this.exited=!1}clearVars(){this.globals=this.vars={},this.arrays={},this.defs={},this.forLoops={},this.forLoopStack=[],this.whileLoops=[],this.rng=new m,this.opts&&this.opts.staticArrays&&this.allstmts.filter(t=>t.command=="DIM").forEach(t=>{t.args.forEach(r=>this.compileJS(this._DIM(r))())})}saveState(){return $.extend(!0,{},this)}loadState(t){$.extend(!0,this,t)}getBuiltinFunctions(){var t=this.program&&this.opts.validFunctions;t||(t=Object.getOwnPropertyNames(u.prototype).filter(i=>/^[A-Z]{3,}[$]?$/.test(i)));var r={};for(var e of t)this.supportsFunction(e)&&(r[e]=this[e].bind(this));return r}supportsFunction(t){return typeof this[t]=="function"}runtimeError(t){throw this.curpc--,new d(t,this.getCurrentSourceLocation())}dialectError(t){this.runtimeError(`I can't ${t} in this dialect of BASIC.`)}getLineForPC(t){var r=this.allstmts[t];return r&&r.$loc&&r.$loc.line}getLabelForPC(t){var r=this.allstmts[t];return r&&r.$loc&&r.$loc.label}getCurrentSourceLocation(){var t=this.getStatement();return t&&t.$loc}getCurrentLabel(){var t=this.getCurrentSourceLocation();return t&&t.label}getStatement(){return this.allstmts[this.curpc]}step(){if(!this.running)return!1;var t=this.getStatement();return t?(this.trace&&console.log(this.curpc,t,this.vars,Object.keys(this.arrays)),this.curpc++,this.executeStatement(t),this.running):(this.running=!1,this.exited=!0,!1)}compileStatement(t){if(t.$run==null)try{var r=this["do__"+t.command];r==null&&this.runtimeError(`I don't know how to "${t.command}".`);var e=r.bind(this)(t);this.trace&&console.log(e),t.$run=this.compileJS(e)}catch(i){throw e&&console.log(e),i}}compileJS(t){return new Function(t).bind(this)}executeStatement(t){this.compileStatement(t),t.$run()}skipToEOL(){do this.curpc++;while(this.curpc=0?this.curpc=r:this.runtimeError(`I tried to go to the label "${t}" but couldn't find it.`)}newLocalScope(){this.vars=Object.create(this.vars)}popLocalScope(){this.vars!==this.globals&&(this.vars=Object.getPrototypeOf(this.vars))}gosubLabel(t){this.returnStack.length>32767&&this.runtimeError("I did too many GOSUBs without a RETURN."),this.returnStack.push(this.curpc),this.gotoLabel(t)}returnFromGosub(){this.returnStack.length==0&&this.runtimeError("I tried to RETURN, but there wasn't a corresponding GOSUB.");var t=this.returnStack.pop();this.curpc=t,this.popLocalScope()}popReturnStack(){this.returnStack.length==0&&this.runtimeError("I tried to POP, but there wasn't a corresponding GOSUB."),this.returnStack.pop()}valueToString(t,r){var e;if(typeof t=="number"){var i=this.float2str(t,this.opts.printZoneLength-4);return r?i.startsWith("-")?`${i} `:` ${i} `:i}else if(t==` `)this.column=0,e=t;else if(t==" "){var n=this.opts.printZoneLength,s=Math.floor(this.column/n),a=(s+1)*this.opts.printZoneLength;a+n>this.margin?(this.column=0,e=` `):e=this.TAB(a)}else e=`${t}`;return e}float2str(t,r){var e=t.toString().toUpperCase();if(r>0){for(var i=r;e.length>r;)e=t.toPrecision(i--);e.startsWith("0.")?e=e.substr(1):e.startsWith("-0.")&&(e="-"+e.substr(2))}return e}printExpr(t){var r=this.valueToString(t,this.opts.numericPadding);this.column+=r.length,this.print(r)}print(t){console.log(t)}async input(t,r){return{line:"",vals:[]}}resume(){}expr2js(t,r){if(r||(r={}),k(t))return JSON.stringify(t.value);if(y(t)){if(!t.args&&r.locals&&r.locals.indexOf(t.name)>=0)return t.name;{r.isconst&&this.runtimeError("I expected a constant value here.");var e="",i=JSON.stringify(t.name);let h=t.args?t.args.map(o=>this.expr2js(o,r)).join(", "):[];return t.name.startsWith("FN")?e+=`this.getDef(${i})(${h})`:this.builtins[t.name]?(this.checkFuncArgs(t,this.builtins[t.name]),e+=`this.builtins.${t.name}(${h})`):t.args?this.opts.arraysContainChars&&t.name.endsWith("$")?e+=`this.getStringSlice(this.vars.${t.name}, ${h})`:e+=`this.arrayGet(${i}, ${h})`:e+=`this.vars.${t.name}`,r.novalid?e:`this.checkValue(${e}, ${i})`}}else if(O(t)){var n=this.expr2js(t.left,r),s=this.expr2js(t.right,r);return`this.${t.op}(${n}, ${s})`}else if(N(t)){var a=this.expr2js(t.expr,r);return`this.${t.op}(${a})`}}assign2js(t,r){r||(r={});var e="";return(t.name.startsWith("FN")||this.builtins[t.name])&&this.runtimeError("I can't call a function here."),t.args?this.opts.arraysContainChars&&t.name.endsWith("$")?this.runtimeError("I can't set array slices via this command yet."):e+=this.array2js(t,r):e=`this.globals.${t.name}`,e}array2js(t,r){var e=JSON.stringify(t.name),i=t.args||[];return this.expr2js(t,{novalid:!0})+`;this.getArray(${e}, ${i.length})`+i.map(n=>"[this.ROUND("+this.expr2js(n,r)+")]").join("")}checkFuncArgs(t,r){var e=t.args?t.args.length:0;t.name=="RND"&&e==0||t.name=="MID$"&&e==2||t.name=="INSTR"&&e==2||r.length!=e&&this.runtimeError(`I expected ${r.length} arguments for the ${t.name} function, but I got ${e}.`)}startForLoop(t,r,e,i,n){var s=this.curpc-1,a=this.pc2label.get(s);i||(i=1),this.vars[t]=r,this.trace&&console.log(`FOR ${t} = ${r} TO ${e} STEP ${i}`);var h=()=>i>=0?this.vars[t]>e:this.vars[t]o==t)),this.forLoopStack.push(t),this.forLoops[t]={$next:o=>{o&&t!=o&&this.runtimeError(`I executed NEXT "${o}", but the last FOR was for "${t}".`),this.vars[t]+=i;var b=h();b?(this.forLoopStack.pop(),delete this.forLoops[t]):this.curpc=(a!=null&&this.label2pc[a]||s)+1,this.trace&&console.log(`NEXT ${t}: ${this.vars[t]} TO ${e} STEP ${i} DONE=${b}`)}}}nextForLoop(t){var r=this.forLoops[t||this.opts.optionalNextVar&&this.forLoopStack[this.forLoopStack.length-1]];r||this.runtimeError("I couldn't find a matching FOR for this NEXT."),r.$next(t)}whileLoop(t){t?this.whileLoops.push(this.curpc-1):this.skipToAfterWend()}nextWhileLoop(){var t=this.whileLoops.pop();t==null?this.runtimeError("I couldn't find a matching WHILE for this WEND."):this.curpc=t}assign(t,r,e){return e&&t.endsWith("$")?this.checkValue(this.convert(t,r),t):t.endsWith("$")?this.convertToString(r,t):this.convertToNumber(r,t)}convert(t,r){return t.endsWith("$")?r==null?"":r.toString():typeof r=="number"?r:parseFloat(r+"")}convertToString(t,r){if(typeof t!="string")this.runtimeError(`I can't convert ${t} to a string.`);else return t}convertToNumber(t,r){if(typeof t!="number")this.runtimeError(`I can't convert ${t} to a number.`);else return this.checkNum(t)}dimArray(t,...r){if(r=r.map(Math.round),this.arrays[t]!=null){if(this.opts.staticArrays)return;this.runtimeError(`I already dimensioned this array (${t}) earlier.`)}var e=this.getTotalArrayLength(r);e>this.opts.maxArrayElements&&this.runtimeError("I can't create an array with this many elements.");var i=t.endsWith("$"),n=i?Array:Float64Array;if(r.length==1)this.arrays[t]=new n(r[0]+1);else if(r.length==2){this.arrays[t]=new Array(r[0]+1);for(var s=0;s=i.length&&this.runtimeError(`I tried to lookup ${t}(${r}) but it exceeded the dimensions of the array.`),i=i[r[n]]}return c(i)&&this.runtimeError(`I tried to lookup ${t}(${r}) but used too few dimensions.`),i}modifyStringSlice(t,r,e,i){return t=t||"",this.checkString(t),this.checkString(r),i||(i=e),e=this.ROUND(e),i=this.ROUND(i),e<1&&this.dialectError("accept a string slice index less than 1"),ir.length)&&this.runtimeError(`I needed a number between 1 and ${r.length}, but I got ${t}.`),t<1||t>r.length?0:t}onGotoLabel(t,...r){t=this.checkOnGoto(t,r),t&&this.gotoLabel(r[t-1])}onGosubLabel(t,...r){t=this.checkOnGoto(t,r),t&&this.gosubLabel(r[t-1])}nextDatum(){return this.dataptr>=this.datums.length&&this.runtimeError("I tried to READ, but ran out of data."),this.datums[this.dataptr++].value}do__PRINT(t){var r="";for(var e of t.args){var i=this.expr2js(e),n=i.name;r+=`this.printExpr(this.checkValue(${i}, ${JSON.stringify(n)}));`}return r}preInput(){this.running=!1,this.curpc--}postInput(t){t&&this.curpc++,this.running=!0,this.resume()}do__INPUT(t){var r=t.prompt!=null?this.expr2js(t.prompt):'""',e=t.elapsed!=null?this.assign2js(t.elapsed):"let ___",i="";return t.args.forEach((n,s)=>{var a=this.assign2js(n);i+=` var value = this.convert(${JSON.stringify(n.name)}, response.vals[${s}]); @@ -34,4 +34,4 @@ import{b as S}from"./chunk-3FIVEUG2.js";import{u as E}from"./chunk-PUOMI72S.js"; `),this.tty.addtext("*** END OF PROGRAM ***",1),this.tty.showPrintHead(!1)}loadROM(t,r){var e=this.runtime.exited;this.program=r;var i=this.runtime.load(r);this.tty.uppercaseOnly=!0,(!this.hotReload||e||!i)&&this.reset()}getROMExtension(){return".json"}reset(){this.tty.clear(),this.runtime.reset(),this.clock=0,this.transcript=[]}pause(){this.timer.stop()}resume(){this.isBlocked()||(this.animcount=0,this.timer.start())}isBlocked(){return this.tty.waitingfor!=null||this.runtime.exited}isRunning(){return this.timer.isRunning()}getDefaultExtensions(){return[".bas"]}getToolForFilename(){return"basic"}getPresets(){return L}getPC(){return this.runtime.curpc}getSP(){return 4096-this.runtime.returnStack.length}isStable(){return!0}getCPUState(){return{PC:this.getPC(),SP:this.getSP()}}saveState(){return{c:this.getCPUState(),rt:this.runtime.saveState()}}loadState(t){this.runtime.loadState(t)}getDebugTree(){return{CurrentLine:this.runtime.getCurrentLabel(),Variables:this.runtime.vars,Arrays:this.runtime.arrays,Functions:this.runtime.defs,ForLoops:this.runtime.forLoops,WhileLoops:this.runtime.whileLoops,ReturnStack:this.runtime.returnStack,NextDatum:this.runtime.datums[this.runtime.dataptr],Clock:this.clock,Options:this.runtime.opts,Internals:this.runtime}}inspect(t){let r=this.runtime.vars[t];if(r!=null)return`${t} = ${r}`}showHelp(){return"https://8bitworkshop.com/docs/platforms/basic/"}getDebugCategories(){return["Variables"]}getDebugInfo(t,r){switch(t){case"Variables":return this.varsToLongString()}}varsToLongString(){var t="",r=Object.keys(this.runtime.vars);r.sort();for(var e of r){var i=this.runtime.vars[e],n=JSON.stringify(i);n.length>24&&(n=`${n.substr(0,24)}...(${n.length})`),t+=g(e,3)+" = "+n+` `}return t}setupDebug(t){this.onBreakpointHit=t}clearDebug(){this.onBreakpointHit=null,this.debugTrap=null}checkDebugTrap(){return this.debugTrap&&this.debugTrap()?(this.pause(),this.break(),!0):!1}break(){this.onBreakpointHit&&this.onBreakpointHit(this.saveState())}step(){var t=this.clock;this.debugTrap=()=>this.clock>t,this.resume()}stepOver(){var t=this.runtime.getStatement();if(t&&(t.command=="GOSUB"||t.command=="ONGOSUB")){var r=this.getPC()+1;this.runEval(()=>this.getPC()==r)}else this.step()}hasCustomStepOver(){return!0}runUntilReturn(){var t=this.getSP();this.runEval(()=>this.getSP()>t)}runEval(t){this.debugTrap=()=>t(this.getCPUState()),this.resume()}restartAtPC(t){return t=Math.round(t),t>=0&&t element; its readystatechange event will be fired asynchronously once it is inserted\n // into the document. Do so, thus queuing up the task. Remember to clean up once it's been called.\n var scriptEl = global.document.createElement('script');\n scriptEl.onreadystatechange = function () {\n nextTick();\n\n scriptEl.onreadystatechange = null;\n scriptEl.parentNode.removeChild(scriptEl);\n scriptEl = null;\n };\n global.document.documentElement.appendChild(scriptEl);\n };\n } else {\n scheduleDrain = function () {\n setTimeout(nextTick, 0);\n };\n }\n}\n\nvar draining;\nvar queue = [];\n//named nextTick for less confusing stack traces\nfunction nextTick() {\n draining = true;\n var i, oldQueue;\n var len = queue.length;\n while (len) {\n oldQueue = queue;\n queue = [];\n i = -1;\n while (++i < len) {\n oldQueue[i]();\n }\n len = queue.length;\n }\n draining = false;\n}\n\nmodule.exports = immediate;\nfunction immediate(task) {\n if (queue.push(task) === 1 && !draining) {\n scheduleDrain();\n }\n}\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{}],2:[function(_dereq_,module,exports){\n'use strict';\nvar immediate = _dereq_(1);\n\n/* istanbul ignore next */\nfunction INTERNAL() {}\n\nvar handlers = {};\n\nvar REJECTED = ['REJECTED'];\nvar FULFILLED = ['FULFILLED'];\nvar PENDING = ['PENDING'];\n\nmodule.exports = Promise;\n\nfunction Promise(resolver) {\n if (typeof resolver !== 'function') {\n throw new TypeError('resolver must be a function');\n }\n this.state = PENDING;\n this.queue = [];\n this.outcome = void 0;\n if (resolver !== INTERNAL) {\n safelyResolveThenable(this, resolver);\n }\n}\n\nPromise.prototype[\"catch\"] = function (onRejected) {\n return this.then(null, onRejected);\n};\nPromise.prototype.then = function (onFulfilled, onRejected) {\n if (typeof onFulfilled !== 'function' && this.state === FULFILLED ||\n typeof onRejected !== 'function' && this.state === REJECTED) {\n return this;\n }\n var promise = new this.constructor(INTERNAL);\n if (this.state !== PENDING) {\n var resolver = this.state === FULFILLED ? onFulfilled : onRejected;\n unwrap(promise, resolver, this.outcome);\n } else {\n this.queue.push(new QueueItem(promise, onFulfilled, onRejected));\n }\n\n return promise;\n};\nfunction QueueItem(promise, onFulfilled, onRejected) {\n this.promise = promise;\n if (typeof onFulfilled === 'function') {\n this.onFulfilled = onFulfilled;\n this.callFulfilled = this.otherCallFulfilled;\n }\n if (typeof onRejected === 'function') {\n this.onRejected = onRejected;\n this.callRejected = this.otherCallRejected;\n }\n}\nQueueItem.prototype.callFulfilled = function (value) {\n handlers.resolve(this.promise, value);\n};\nQueueItem.prototype.otherCallFulfilled = function (value) {\n unwrap(this.promise, this.onFulfilled, value);\n};\nQueueItem.prototype.callRejected = function (value) {\n handlers.reject(this.promise, value);\n};\nQueueItem.prototype.otherCallRejected = function (value) {\n unwrap(this.promise, this.onRejected, value);\n};\n\nfunction unwrap(promise, func, value) {\n immediate(function () {\n var returnValue;\n try {\n returnValue = func(value);\n } catch (e) {\n return handlers.reject(promise, e);\n }\n if (returnValue === promise) {\n handlers.reject(promise, new TypeError('Cannot resolve promise with itself'));\n } else {\n handlers.resolve(promise, returnValue);\n }\n });\n}\n\nhandlers.resolve = function (self, value) {\n var result = tryCatch(getThen, value);\n if (result.status === 'error') {\n return handlers.reject(self, result.value);\n }\n var thenable = result.value;\n\n if (thenable) {\n safelyResolveThenable(self, thenable);\n } else {\n self.state = FULFILLED;\n self.outcome = value;\n var i = -1;\n var len = self.queue.length;\n while (++i < len) {\n self.queue[i].callFulfilled(value);\n }\n }\n return self;\n};\nhandlers.reject = function (self, error) {\n self.state = REJECTED;\n self.outcome = error;\n var i = -1;\n var len = self.queue.length;\n while (++i < len) {\n self.queue[i].callRejected(error);\n }\n return self;\n};\n\nfunction getThen(obj) {\n // Make sure we only access the accessor once as required by the spec\n var then = obj && obj.then;\n if (obj && (typeof obj === 'object' || typeof obj === 'function') && typeof then === 'function') {\n return function appyThen() {\n then.apply(obj, arguments);\n };\n }\n}\n\nfunction safelyResolveThenable(self, thenable) {\n // Either fulfill, reject or reject with error\n var called = false;\n function onError(value) {\n if (called) {\n return;\n }\n called = true;\n handlers.reject(self, value);\n }\n\n function onSuccess(value) {\n if (called) {\n return;\n }\n called = true;\n handlers.resolve(self, value);\n }\n\n function tryToUnwrap() {\n thenable(onSuccess, onError);\n }\n\n var result = tryCatch(tryToUnwrap);\n if (result.status === 'error') {\n onError(result.value);\n }\n}\n\nfunction tryCatch(func, value) {\n var out = {};\n try {\n out.value = func(value);\n out.status = 'success';\n } catch (e) {\n out.status = 'error';\n out.value = e;\n }\n return out;\n}\n\nPromise.resolve = resolve;\nfunction resolve(value) {\n if (value instanceof this) {\n return value;\n }\n return handlers.resolve(new this(INTERNAL), value);\n}\n\nPromise.reject = reject;\nfunction reject(reason) {\n var promise = new this(INTERNAL);\n return handlers.reject(promise, reason);\n}\n\nPromise.all = all;\nfunction all(iterable) {\n var self = this;\n if (Object.prototype.toString.call(iterable) !== '[object Array]') {\n return this.reject(new TypeError('must be an array'));\n }\n\n var len = iterable.length;\n var called = false;\n if (!len) {\n return this.resolve([]);\n }\n\n var values = new Array(len);\n var resolved = 0;\n var i = -1;\n var promise = new this(INTERNAL);\n\n while (++i < len) {\n allResolver(iterable[i], i);\n }\n return promise;\n function allResolver(value, i) {\n self.resolve(value).then(resolveFromAll, function (error) {\n if (!called) {\n called = true;\n handlers.reject(promise, error);\n }\n });\n function resolveFromAll(outValue) {\n values[i] = outValue;\n if (++resolved === len && !called) {\n called = true;\n handlers.resolve(promise, values);\n }\n }\n }\n}\n\nPromise.race = race;\nfunction race(iterable) {\n var self = this;\n if (Object.prototype.toString.call(iterable) !== '[object Array]') {\n return this.reject(new TypeError('must be an array'));\n }\n\n var len = iterable.length;\n var called = false;\n if (!len) {\n return this.resolve([]);\n }\n\n var i = -1;\n var promise = new this(INTERNAL);\n\n while (++i < len) {\n resolver(iterable[i]);\n }\n return promise;\n function resolver(value) {\n self.resolve(value).then(function (response) {\n if (!called) {\n called = true;\n handlers.resolve(promise, response);\n }\n }, function (error) {\n if (!called) {\n called = true;\n handlers.reject(promise, error);\n }\n });\n }\n}\n\n},{\"1\":1}],3:[function(_dereq_,module,exports){\n(function (global){\n'use strict';\nif (typeof global.Promise !== 'function') {\n global.Promise = _dereq_(2);\n}\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n},{\"2\":2}],4:[function(_dereq_,module,exports){\n'use strict';\n\nvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction getIDB() {\n /* global indexedDB,webkitIndexedDB,mozIndexedDB,OIndexedDB,msIndexedDB */\n try {\n if (typeof indexedDB !== 'undefined') {\n return indexedDB;\n }\n if (typeof webkitIndexedDB !== 'undefined') {\n return webkitIndexedDB;\n }\n if (typeof mozIndexedDB !== 'undefined') {\n return mozIndexedDB;\n }\n if (typeof OIndexedDB !== 'undefined') {\n return OIndexedDB;\n }\n if (typeof msIndexedDB !== 'undefined') {\n return msIndexedDB;\n }\n } catch (e) {\n return;\n }\n}\n\nvar idb = getIDB();\n\nfunction isIndexedDBValid() {\n try {\n // Initialize IndexedDB; fall back to vendor-prefixed versions\n // if needed.\n if (!idb || !idb.open) {\n return false;\n }\n // We mimic PouchDB here;\n //\n // We test for openDatabase because IE Mobile identifies itself\n // as Safari. Oh the lulz...\n var isSafari = typeof openDatabase !== 'undefined' && /(Safari|iPhone|iPad|iPod)/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent) && !/BlackBerry/.test(navigator.platform);\n\n var hasFetch = typeof fetch === 'function' && fetch.toString().indexOf('[native code') !== -1;\n\n // Safari <10.1 does not meet our requirements for IDB support\n // (see: https://github.com/pouchdb/pouchdb/issues/5572).\n // Safari 10.1 shipped with fetch, we can use that to detect it.\n // Note: this creates issues with `window.fetch` polyfills and\n // overrides; see:\n // https://github.com/localForage/localForage/issues/856\n return (!isSafari || hasFetch) && typeof indexedDB !== 'undefined' &&\n // some outdated implementations of IDB that appear on Samsung\n // and HTC Android devices <4.4 are missing IDBKeyRange\n // See: https://github.com/mozilla/localForage/issues/128\n // See: https://github.com/mozilla/localForage/issues/272\n typeof IDBKeyRange !== 'undefined';\n } catch (e) {\n return false;\n }\n}\n\n// Abstracts constructing a Blob object, so it also works in older\n// browsers that don't support the native Blob constructor. (i.e.\n// old QtWebKit versions, at least).\n// Abstracts constructing a Blob object, so it also works in older\n// browsers that don't support the native Blob constructor. (i.e.\n// old QtWebKit versions, at least).\nfunction createBlob(parts, properties) {\n /* global BlobBuilder,MSBlobBuilder,MozBlobBuilder,WebKitBlobBuilder */\n parts = parts || [];\n properties = properties || {};\n try {\n return new Blob(parts, properties);\n } catch (e) {\n if (e.name !== 'TypeError') {\n throw e;\n }\n var Builder = typeof BlobBuilder !== 'undefined' ? BlobBuilder : typeof MSBlobBuilder !== 'undefined' ? MSBlobBuilder : typeof MozBlobBuilder !== 'undefined' ? MozBlobBuilder : WebKitBlobBuilder;\n var builder = new Builder();\n for (var i = 0; i < parts.length; i += 1) {\n builder.append(parts[i]);\n }\n return builder.getBlob(properties.type);\n }\n}\n\n// This is CommonJS because lie is an external dependency, so Rollup\n// can just ignore it.\nif (typeof Promise === 'undefined') {\n // In the \"nopromises\" build this will just throw if you don't have\n // a global promise object, but it would throw anyway later.\n _dereq_(3);\n}\nvar Promise$1 = Promise;\n\nfunction executeCallback(promise, callback) {\n if (callback) {\n promise.then(function (result) {\n callback(null, result);\n }, function (error) {\n callback(error);\n });\n }\n}\n\nfunction executeTwoCallbacks(promise, callback, errorCallback) {\n if (typeof callback === 'function') {\n promise.then(callback);\n }\n\n if (typeof errorCallback === 'function') {\n promise[\"catch\"](errorCallback);\n }\n}\n\nfunction normalizeKey(key) {\n // Cast the key to a string, as that's all we can set as a key.\n if (typeof key !== 'string') {\n console.warn(key + ' used as a key, but it is not a string.');\n key = String(key);\n }\n\n return key;\n}\n\nfunction getCallback() {\n if (arguments.length && typeof arguments[arguments.length - 1] === 'function') {\n return arguments[arguments.length - 1];\n }\n}\n\n// Some code originally from async_storage.js in\n// [Gaia](https://github.com/mozilla-b2g/gaia).\n\nvar DETECT_BLOB_SUPPORT_STORE = 'local-forage-detect-blob-support';\nvar supportsBlobs = void 0;\nvar dbContexts = {};\nvar toString = Object.prototype.toString;\n\n// Transaction Modes\nvar READ_ONLY = 'readonly';\nvar READ_WRITE = 'readwrite';\n\n// Transform a binary string to an array buffer, because otherwise\n// weird stuff happens when you try to work with the binary string directly.\n// It is known.\n// From http://stackoverflow.com/questions/14967647/ (continues on next line)\n// encode-decode-image-with-base64-breaks-image (2013-04-21)\nfunction _binStringToArrayBuffer(bin) {\n var length = bin.length;\n var buf = new ArrayBuffer(length);\n var arr = new Uint8Array(buf);\n for (var i = 0; i < length; i++) {\n arr[i] = bin.charCodeAt(i);\n }\n return buf;\n}\n\n//\n// Blobs are not supported in all versions of IndexedDB, notably\n// Chrome <37 and Android <5. In those versions, storing a blob will throw.\n//\n// Various other blob bugs exist in Chrome v37-42 (inclusive).\n// Detecting them is expensive and confusing to users, and Chrome 37-42\n// is at very low usage worldwide, so we do a hacky userAgent check instead.\n//\n// content-type bug: https://code.google.com/p/chromium/issues/detail?id=408120\n// 404 bug: https://code.google.com/p/chromium/issues/detail?id=447916\n// FileReader bug: https://code.google.com/p/chromium/issues/detail?id=447836\n//\n// Code borrowed from PouchDB. See:\n// https://github.com/pouchdb/pouchdb/blob/master/packages/node_modules/pouchdb-adapter-idb/src/blobSupport.js\n//\nfunction _checkBlobSupportWithoutCaching(idb) {\n return new Promise$1(function (resolve) {\n var txn = idb.transaction(DETECT_BLOB_SUPPORT_STORE, READ_WRITE);\n var blob = createBlob(['']);\n txn.objectStore(DETECT_BLOB_SUPPORT_STORE).put(blob, 'key');\n\n txn.onabort = function (e) {\n // If the transaction aborts now its due to not being able to\n // write to the database, likely due to the disk being full\n e.preventDefault();\n e.stopPropagation();\n resolve(false);\n };\n\n txn.oncomplete = function () {\n var matchedChrome = navigator.userAgent.match(/Chrome\\/(\\d+)/);\n var matchedEdge = navigator.userAgent.match(/Edge\\//);\n // MS Edge pretends to be Chrome 42:\n // https://msdn.microsoft.com/en-us/library/hh869301%28v=vs.85%29.aspx\n resolve(matchedEdge || !matchedChrome || parseInt(matchedChrome[1], 10) >= 43);\n };\n })[\"catch\"](function () {\n return false; // error, so assume unsupported\n });\n}\n\nfunction _checkBlobSupport(idb) {\n if (typeof supportsBlobs === 'boolean') {\n return Promise$1.resolve(supportsBlobs);\n }\n return _checkBlobSupportWithoutCaching(idb).then(function (value) {\n supportsBlobs = value;\n return supportsBlobs;\n });\n}\n\nfunction _deferReadiness(dbInfo) {\n var dbContext = dbContexts[dbInfo.name];\n\n // Create a deferred object representing the current database operation.\n var deferredOperation = {};\n\n deferredOperation.promise = new Promise$1(function (resolve, reject) {\n deferredOperation.resolve = resolve;\n deferredOperation.reject = reject;\n });\n\n // Enqueue the deferred operation.\n dbContext.deferredOperations.push(deferredOperation);\n\n // Chain its promise to the database readiness.\n if (!dbContext.dbReady) {\n dbContext.dbReady = deferredOperation.promise;\n } else {\n dbContext.dbReady = dbContext.dbReady.then(function () {\n return deferredOperation.promise;\n });\n }\n}\n\nfunction _advanceReadiness(dbInfo) {\n var dbContext = dbContexts[dbInfo.name];\n\n // Dequeue a deferred operation.\n var deferredOperation = dbContext.deferredOperations.pop();\n\n // Resolve its promise (which is part of the database readiness\n // chain of promises).\n if (deferredOperation) {\n deferredOperation.resolve();\n return deferredOperation.promise;\n }\n}\n\nfunction _rejectReadiness(dbInfo, err) {\n var dbContext = dbContexts[dbInfo.name];\n\n // Dequeue a deferred operation.\n var deferredOperation = dbContext.deferredOperations.pop();\n\n // Reject its promise (which is part of the database readiness\n // chain of promises).\n if (deferredOperation) {\n deferredOperation.reject(err);\n return deferredOperation.promise;\n }\n}\n\nfunction _getConnection(dbInfo, upgradeNeeded) {\n return new Promise$1(function (resolve, reject) {\n dbContexts[dbInfo.name] = dbContexts[dbInfo.name] || createDbContext();\n\n if (dbInfo.db) {\n if (upgradeNeeded) {\n _deferReadiness(dbInfo);\n dbInfo.db.close();\n } else {\n return resolve(dbInfo.db);\n }\n }\n\n var dbArgs = [dbInfo.name];\n\n if (upgradeNeeded) {\n dbArgs.push(dbInfo.version);\n }\n\n var openreq = idb.open.apply(idb, dbArgs);\n\n if (upgradeNeeded) {\n openreq.onupgradeneeded = function (e) {\n var db = openreq.result;\n try {\n db.createObjectStore(dbInfo.storeName);\n if (e.oldVersion <= 1) {\n // Added when support for blob shims was added\n db.createObjectStore(DETECT_BLOB_SUPPORT_STORE);\n }\n } catch (ex) {\n if (ex.name === 'ConstraintError') {\n console.warn('The database \"' + dbInfo.name + '\"' + ' has been upgraded from version ' + e.oldVersion + ' to version ' + e.newVersion + ', but the storage \"' + dbInfo.storeName + '\" already exists.');\n } else {\n throw ex;\n }\n }\n };\n }\n\n openreq.onerror = function (e) {\n e.preventDefault();\n reject(openreq.error);\n };\n\n openreq.onsuccess = function () {\n var db = openreq.result;\n db.onversionchange = function (e) {\n // Triggered when the database is modified (e.g. adding an objectStore) or\n // deleted (even when initiated by other sessions in different tabs).\n // Closing the connection here prevents those operations from being blocked.\n // If the database is accessed again later by this instance, the connection\n // will be reopened or the database recreated as needed.\n e.target.close();\n };\n resolve(db);\n _advanceReadiness(dbInfo);\n };\n });\n}\n\nfunction _getOriginalConnection(dbInfo) {\n return _getConnection(dbInfo, false);\n}\n\nfunction _getUpgradedConnection(dbInfo) {\n return _getConnection(dbInfo, true);\n}\n\nfunction _isUpgradeNeeded(dbInfo, defaultVersion) {\n if (!dbInfo.db) {\n return true;\n }\n\n var isNewStore = !dbInfo.db.objectStoreNames.contains(dbInfo.storeName);\n var isDowngrade = dbInfo.version < dbInfo.db.version;\n var isUpgrade = dbInfo.version > dbInfo.db.version;\n\n if (isDowngrade) {\n // If the version is not the default one\n // then warn for impossible downgrade.\n if (dbInfo.version !== defaultVersion) {\n console.warn('The database \"' + dbInfo.name + '\"' + \" can't be downgraded from version \" + dbInfo.db.version + ' to version ' + dbInfo.version + '.');\n }\n // Align the versions to prevent errors.\n dbInfo.version = dbInfo.db.version;\n }\n\n if (isUpgrade || isNewStore) {\n // If the store is new then increment the version (if needed).\n // This will trigger an \"upgradeneeded\" event which is required\n // for creating a store.\n if (isNewStore) {\n var incVersion = dbInfo.db.version + 1;\n if (incVersion > dbInfo.version) {\n dbInfo.version = incVersion;\n }\n }\n\n return true;\n }\n\n return false;\n}\n\n// encode a blob for indexeddb engines that don't support blobs\nfunction _encodeBlob(blob) {\n return new Promise$1(function (resolve, reject) {\n var reader = new FileReader();\n reader.onerror = reject;\n reader.onloadend = function (e) {\n var base64 = btoa(e.target.result || '');\n resolve({\n __local_forage_encoded_blob: true,\n data: base64,\n type: blob.type\n });\n };\n reader.readAsBinaryString(blob);\n });\n}\n\n// decode an encoded blob\nfunction _decodeBlob(encodedBlob) {\n var arrayBuff = _binStringToArrayBuffer(atob(encodedBlob.data));\n return createBlob([arrayBuff], { type: encodedBlob.type });\n}\n\n// is this one of our fancy encoded blobs?\nfunction _isEncodedBlob(value) {\n return value && value.__local_forage_encoded_blob;\n}\n\n// Specialize the default `ready()` function by making it dependent\n// on the current database operations. Thus, the driver will be actually\n// ready when it's been initialized (default) *and* there are no pending\n// operations on the database (initiated by some other instances).\nfunction _fullyReady(callback) {\n var self = this;\n\n var promise = self._initReady().then(function () {\n var dbContext = dbContexts[self._dbInfo.name];\n\n if (dbContext && dbContext.dbReady) {\n return dbContext.dbReady;\n }\n });\n\n executeTwoCallbacks(promise, callback, callback);\n return promise;\n}\n\n// Try to establish a new db connection to replace the\n// current one which is broken (i.e. experiencing\n// InvalidStateError while creating a transaction).\nfunction _tryReconnect(dbInfo) {\n _deferReadiness(dbInfo);\n\n var dbContext = dbContexts[dbInfo.name];\n var forages = dbContext.forages;\n\n for (var i = 0; i < forages.length; i++) {\n var forage = forages[i];\n if (forage._dbInfo.db) {\n forage._dbInfo.db.close();\n forage._dbInfo.db = null;\n }\n }\n dbInfo.db = null;\n\n return _getOriginalConnection(dbInfo).then(function (db) {\n dbInfo.db = db;\n if (_isUpgradeNeeded(dbInfo)) {\n // Reopen the database for upgrading.\n return _getUpgradedConnection(dbInfo);\n }\n return db;\n }).then(function (db) {\n // store the latest db reference\n // in case the db was upgraded\n dbInfo.db = dbContext.db = db;\n for (var i = 0; i < forages.length; i++) {\n forages[i]._dbInfo.db = db;\n }\n })[\"catch\"](function (err) {\n _rejectReadiness(dbInfo, err);\n throw err;\n });\n}\n\n// FF doesn't like Promises (micro-tasks) and IDDB store operations,\n// so we have to do it with callbacks\nfunction createTransaction(dbInfo, mode, callback, retries) {\n if (retries === undefined) {\n retries = 1;\n }\n\n try {\n var tx = dbInfo.db.transaction(dbInfo.storeName, mode);\n callback(null, tx);\n } catch (err) {\n if (retries > 0 && (!dbInfo.db || err.name === 'InvalidStateError' || err.name === 'NotFoundError')) {\n return Promise$1.resolve().then(function () {\n if (!dbInfo.db || err.name === 'NotFoundError' && !dbInfo.db.objectStoreNames.contains(dbInfo.storeName) && dbInfo.version <= dbInfo.db.version) {\n // increase the db version, to create the new ObjectStore\n if (dbInfo.db) {\n dbInfo.version = dbInfo.db.version + 1;\n }\n // Reopen the database for upgrading.\n return _getUpgradedConnection(dbInfo);\n }\n }).then(function () {\n return _tryReconnect(dbInfo).then(function () {\n createTransaction(dbInfo, mode, callback, retries - 1);\n });\n })[\"catch\"](callback);\n }\n\n callback(err);\n }\n}\n\nfunction createDbContext() {\n return {\n // Running localForages sharing a database.\n forages: [],\n // Shared database.\n db: null,\n // Database readiness (promise).\n dbReady: null,\n // Deferred operations on the database.\n deferredOperations: []\n };\n}\n\n// Open the IndexedDB database (automatically creates one if one didn't\n// previously exist), using any options set in the config.\nfunction _initStorage(options) {\n var self = this;\n var dbInfo = {\n db: null\n };\n\n if (options) {\n for (var i in options) {\n dbInfo[i] = options[i];\n }\n }\n\n // Get the current context of the database;\n var dbContext = dbContexts[dbInfo.name];\n\n // ...or create a new context.\n if (!dbContext) {\n dbContext = createDbContext();\n // Register the new context in the global container.\n dbContexts[dbInfo.name] = dbContext;\n }\n\n // Register itself as a running localForage in the current context.\n dbContext.forages.push(self);\n\n // Replace the default `ready()` function with the specialized one.\n if (!self._initReady) {\n self._initReady = self.ready;\n self.ready = _fullyReady;\n }\n\n // Create an array of initialization states of the related localForages.\n var initPromises = [];\n\n function ignoreErrors() {\n // Don't handle errors here,\n // just makes sure related localForages aren't pending.\n return Promise$1.resolve();\n }\n\n for (var j = 0; j < dbContext.forages.length; j++) {\n var forage = dbContext.forages[j];\n if (forage !== self) {\n // Don't wait for itself...\n initPromises.push(forage._initReady()[\"catch\"](ignoreErrors));\n }\n }\n\n // Take a snapshot of the related localForages.\n var forages = dbContext.forages.slice(0);\n\n // Initialize the connection process only when\n // all the related localForages aren't pending.\n return Promise$1.all(initPromises).then(function () {\n dbInfo.db = dbContext.db;\n // Get the connection or open a new one without upgrade.\n return _getOriginalConnection(dbInfo);\n }).then(function (db) {\n dbInfo.db = db;\n if (_isUpgradeNeeded(dbInfo, self._defaultConfig.version)) {\n // Reopen the database for upgrading.\n return _getUpgradedConnection(dbInfo);\n }\n return db;\n }).then(function (db) {\n dbInfo.db = dbContext.db = db;\n self._dbInfo = dbInfo;\n // Share the final connection amongst related localForages.\n for (var k = 0; k < forages.length; k++) {\n var forage = forages[k];\n if (forage !== self) {\n // Self is already up-to-date.\n forage._dbInfo.db = dbInfo.db;\n forage._dbInfo.version = dbInfo.version;\n }\n }\n });\n}\n\nfunction getItem(key, callback) {\n var self = this;\n\n key = normalizeKey(key);\n\n var promise = new Promise$1(function (resolve, reject) {\n self.ready().then(function () {\n createTransaction(self._dbInfo, READ_ONLY, function (err, transaction) {\n if (err) {\n return reject(err);\n }\n\n try {\n var store = transaction.objectStore(self._dbInfo.storeName);\n var req = store.get(key);\n\n req.onsuccess = function () {\n var value = req.result;\n if (value === undefined) {\n value = null;\n }\n if (_isEncodedBlob(value)) {\n value = _decodeBlob(value);\n }\n resolve(value);\n };\n\n req.onerror = function () {\n reject(req.error);\n };\n } catch (e) {\n reject(e);\n }\n });\n })[\"catch\"](reject);\n });\n\n executeCallback(promise, callback);\n return promise;\n}\n\n// Iterate over all items stored in database.\nfunction iterate(iterator, callback) {\n var self = this;\n\n var promise = new Promise$1(function (resolve, reject) {\n self.ready().then(function () {\n createTransaction(self._dbInfo, READ_ONLY, function (err, transaction) {\n if (err) {\n return reject(err);\n }\n\n try {\n var store = transaction.objectStore(self._dbInfo.storeName);\n var req = store.openCursor();\n var iterationNumber = 1;\n\n req.onsuccess = function () {\n var cursor = req.result;\n\n if (cursor) {\n var value = cursor.value;\n if (_isEncodedBlob(value)) {\n value = _decodeBlob(value);\n }\n var result = iterator(value, cursor.key, iterationNumber++);\n\n // when the iterator callback returns any\n // (non-`undefined`) value, then we stop\n // the iteration immediately\n if (result !== void 0) {\n resolve(result);\n } else {\n cursor[\"continue\"]();\n }\n } else {\n resolve();\n }\n };\n\n req.onerror = function () {\n reject(req.error);\n };\n } catch (e) {\n reject(e);\n }\n });\n })[\"catch\"](reject);\n });\n\n executeCallback(promise, callback);\n\n return promise;\n}\n\nfunction setItem(key, value, callback) {\n var self = this;\n\n key = normalizeKey(key);\n\n var promise = new Promise$1(function (resolve, reject) {\n var dbInfo;\n self.ready().then(function () {\n dbInfo = self._dbInfo;\n if (toString.call(value) === '[object Blob]') {\n return _checkBlobSupport(dbInfo.db).then(function (blobSupport) {\n if (blobSupport) {\n return value;\n }\n return _encodeBlob(value);\n });\n }\n return value;\n }).then(function (value) {\n createTransaction(self._dbInfo, READ_WRITE, function (err, transaction) {\n if (err) {\n return reject(err);\n }\n\n try {\n var store = transaction.objectStore(self._dbInfo.storeName);\n\n // The reason we don't _save_ null is because IE 10 does\n // not support saving the `null` type in IndexedDB. How\n // ironic, given the bug below!\n // See: https://github.com/mozilla/localForage/issues/161\n if (value === null) {\n value = undefined;\n }\n\n var req = store.put(value, key);\n\n transaction.oncomplete = function () {\n // Cast to undefined so the value passed to\n // callback/promise is the same as what one would get out\n // of `getItem()` later. This leads to some weirdness\n // (setItem('foo', undefined) will return `null`), but\n // it's not my fault localStorage is our baseline and that\n // it's weird.\n if (value === undefined) {\n value = null;\n }\n\n resolve(value);\n };\n transaction.onabort = transaction.onerror = function () {\n var err = req.error ? req.error : req.transaction.error;\n reject(err);\n };\n } catch (e) {\n reject(e);\n }\n });\n })[\"catch\"](reject);\n });\n\n executeCallback(promise, callback);\n return promise;\n}\n\nfunction removeItem(key, callback) {\n var self = this;\n\n key = normalizeKey(key);\n\n var promise = new Promise$1(function (resolve, reject) {\n self.ready().then(function () {\n createTransaction(self._dbInfo, READ_WRITE, function (err, transaction) {\n if (err) {\n return reject(err);\n }\n\n try {\n var store = transaction.objectStore(self._dbInfo.storeName);\n // We use a Grunt task to make this safe for IE and some\n // versions of Android (including those used by Cordova).\n // Normally IE won't like `.delete()` and will insist on\n // using `['delete']()`, but we have a build step that\n // fixes this for us now.\n var req = store[\"delete\"](key);\n transaction.oncomplete = function () {\n resolve();\n };\n\n transaction.onerror = function () {\n reject(req.error);\n };\n\n // The request will be also be aborted if we've exceeded our storage\n // space.\n transaction.onabort = function () {\n var err = req.error ? req.error : req.transaction.error;\n reject(err);\n };\n } catch (e) {\n reject(e);\n }\n });\n })[\"catch\"](reject);\n });\n\n executeCallback(promise, callback);\n return promise;\n}\n\nfunction clear(callback) {\n var self = this;\n\n var promise = new Promise$1(function (resolve, reject) {\n self.ready().then(function () {\n createTransaction(self._dbInfo, READ_WRITE, function (err, transaction) {\n if (err) {\n return reject(err);\n }\n\n try {\n var store = transaction.objectStore(self._dbInfo.storeName);\n var req = store.clear();\n\n transaction.oncomplete = function () {\n resolve();\n };\n\n transaction.onabort = transaction.onerror = function () {\n var err = req.error ? req.error : req.transaction.error;\n reject(err);\n };\n } catch (e) {\n reject(e);\n }\n });\n })[\"catch\"](reject);\n });\n\n executeCallback(promise, callback);\n return promise;\n}\n\nfunction length(callback) {\n var self = this;\n\n var promise = new Promise$1(function (resolve, reject) {\n self.ready().then(function () {\n createTransaction(self._dbInfo, READ_ONLY, function (err, transaction) {\n if (err) {\n return reject(err);\n }\n\n try {\n var store = transaction.objectStore(self._dbInfo.storeName);\n var req = store.count();\n\n req.onsuccess = function () {\n resolve(req.result);\n };\n\n req.onerror = function () {\n reject(req.error);\n };\n } catch (e) {\n reject(e);\n }\n });\n })[\"catch\"](reject);\n });\n\n executeCallback(promise, callback);\n return promise;\n}\n\nfunction key(n, callback) {\n var self = this;\n\n var promise = new Promise$1(function (resolve, reject) {\n if (n < 0) {\n resolve(null);\n\n return;\n }\n\n self.ready().then(function () {\n createTransaction(self._dbInfo, READ_ONLY, function (err, transaction) {\n if (err) {\n return reject(err);\n }\n\n try {\n var store = transaction.objectStore(self._dbInfo.storeName);\n var advanced = false;\n var req = store.openKeyCursor();\n\n req.onsuccess = function () {\n var cursor = req.result;\n if (!cursor) {\n // this means there weren't enough keys\n resolve(null);\n\n return;\n }\n\n if (n === 0) {\n // We have the first key, return it if that's what they\n // wanted.\n resolve(cursor.key);\n } else {\n if (!advanced) {\n // Otherwise, ask the cursor to skip ahead n\n // records.\n advanced = true;\n cursor.advance(n);\n } else {\n // When we get here, we've got the nth key.\n resolve(cursor.key);\n }\n }\n };\n\n req.onerror = function () {\n reject(req.error);\n };\n } catch (e) {\n reject(e);\n }\n });\n })[\"catch\"](reject);\n });\n\n executeCallback(promise, callback);\n return promise;\n}\n\nfunction keys(callback) {\n var self = this;\n\n var promise = new Promise$1(function (resolve, reject) {\n self.ready().then(function () {\n createTransaction(self._dbInfo, READ_ONLY, function (err, transaction) {\n if (err) {\n return reject(err);\n }\n\n try {\n var store = transaction.objectStore(self._dbInfo.storeName);\n var req = store.openKeyCursor();\n var keys = [];\n\n req.onsuccess = function () {\n var cursor = req.result;\n\n if (!cursor) {\n resolve(keys);\n return;\n }\n\n keys.push(cursor.key);\n cursor[\"continue\"]();\n };\n\n req.onerror = function () {\n reject(req.error);\n };\n } catch (e) {\n reject(e);\n }\n });\n })[\"catch\"](reject);\n });\n\n executeCallback(promise, callback);\n return promise;\n}\n\nfunction dropInstance(options, callback) {\n callback = getCallback.apply(this, arguments);\n\n var currentConfig = this.config();\n options = typeof options !== 'function' && options || {};\n if (!options.name) {\n options.name = options.name || currentConfig.name;\n options.storeName = options.storeName || currentConfig.storeName;\n }\n\n var self = this;\n var promise;\n if (!options.name) {\n promise = Promise$1.reject('Invalid arguments');\n } else {\n var isCurrentDb = options.name === currentConfig.name && self._dbInfo.db;\n\n var dbPromise = isCurrentDb ? Promise$1.resolve(self._dbInfo.db) : _getOriginalConnection(options).then(function (db) {\n var dbContext = dbContexts[options.name];\n var forages = dbContext.forages;\n dbContext.db = db;\n for (var i = 0; i < forages.length; i++) {\n forages[i]._dbInfo.db = db;\n }\n return db;\n });\n\n if (!options.storeName) {\n promise = dbPromise.then(function (db) {\n _deferReadiness(options);\n\n var dbContext = dbContexts[options.name];\n var forages = dbContext.forages;\n\n db.close();\n for (var i = 0; i < forages.length; i++) {\n var forage = forages[i];\n forage._dbInfo.db = null;\n }\n\n var dropDBPromise = new Promise$1(function (resolve, reject) {\n var req = idb.deleteDatabase(options.name);\n\n req.onerror = function () {\n var db = req.result;\n if (db) {\n db.close();\n }\n reject(req.error);\n };\n\n req.onblocked = function () {\n // Closing all open connections in onversionchange handler should prevent this situation, but if\n // we do get here, it just means the request remains pending - eventually it will succeed or error\n console.warn('dropInstance blocked for database \"' + options.name + '\" until all open connections are closed');\n };\n\n req.onsuccess = function () {\n var db = req.result;\n if (db) {\n db.close();\n }\n resolve(db);\n };\n });\n\n return dropDBPromise.then(function (db) {\n dbContext.db = db;\n for (var i = 0; i < forages.length; i++) {\n var _forage = forages[i];\n _advanceReadiness(_forage._dbInfo);\n }\n })[\"catch\"](function (err) {\n (_rejectReadiness(options, err) || Promise$1.resolve())[\"catch\"](function () {});\n throw err;\n });\n });\n } else {\n promise = dbPromise.then(function (db) {\n if (!db.objectStoreNames.contains(options.storeName)) {\n return;\n }\n\n var newVersion = db.version + 1;\n\n _deferReadiness(options);\n\n var dbContext = dbContexts[options.name];\n var forages = dbContext.forages;\n\n db.close();\n for (var i = 0; i < forages.length; i++) {\n var forage = forages[i];\n forage._dbInfo.db = null;\n forage._dbInfo.version = newVersion;\n }\n\n var dropObjectPromise = new Promise$1(function (resolve, reject) {\n var req = idb.open(options.name, newVersion);\n\n req.onerror = function (err) {\n var db = req.result;\n db.close();\n reject(err);\n };\n\n req.onupgradeneeded = function () {\n var db = req.result;\n db.deleteObjectStore(options.storeName);\n };\n\n req.onsuccess = function () {\n var db = req.result;\n db.close();\n resolve(db);\n };\n });\n\n return dropObjectPromise.then(function (db) {\n dbContext.db = db;\n for (var j = 0; j < forages.length; j++) {\n var _forage2 = forages[j];\n _forage2._dbInfo.db = db;\n _advanceReadiness(_forage2._dbInfo);\n }\n })[\"catch\"](function (err) {\n (_rejectReadiness(options, err) || Promise$1.resolve())[\"catch\"](function () {});\n throw err;\n });\n });\n }\n }\n\n executeCallback(promise, callback);\n return promise;\n}\n\nvar asyncStorage = {\n _driver: 'asyncStorage',\n _initStorage: _initStorage,\n _support: isIndexedDBValid(),\n iterate: iterate,\n getItem: getItem,\n setItem: setItem,\n removeItem: removeItem,\n clear: clear,\n length: length,\n key: key,\n keys: keys,\n dropInstance: dropInstance\n};\n\nfunction isWebSQLValid() {\n return typeof openDatabase === 'function';\n}\n\n// Sadly, the best way to save binary data in WebSQL/localStorage is serializing\n// it to Base64, so this is how we store it to prevent very strange errors with less\n// verbose ways of binary <-> string data storage.\nvar BASE_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n\nvar BLOB_TYPE_PREFIX = '~~local_forage_type~';\nvar BLOB_TYPE_PREFIX_REGEX = /^~~local_forage_type~([^~]+)~/;\n\nvar SERIALIZED_MARKER = '__lfsc__:';\nvar SERIALIZED_MARKER_LENGTH = SERIALIZED_MARKER.length;\n\n// OMG the serializations!\nvar TYPE_ARRAYBUFFER = 'arbf';\nvar TYPE_BLOB = 'blob';\nvar TYPE_INT8ARRAY = 'si08';\nvar TYPE_UINT8ARRAY = 'ui08';\nvar TYPE_UINT8CLAMPEDARRAY = 'uic8';\nvar TYPE_INT16ARRAY = 'si16';\nvar TYPE_INT32ARRAY = 'si32';\nvar TYPE_UINT16ARRAY = 'ur16';\nvar TYPE_UINT32ARRAY = 'ui32';\nvar TYPE_FLOAT32ARRAY = 'fl32';\nvar TYPE_FLOAT64ARRAY = 'fl64';\nvar TYPE_SERIALIZED_MARKER_LENGTH = SERIALIZED_MARKER_LENGTH + TYPE_ARRAYBUFFER.length;\n\nvar toString$1 = Object.prototype.toString;\n\nfunction stringToBuffer(serializedString) {\n // Fill the string into a ArrayBuffer.\n var bufferLength = serializedString.length * 0.75;\n var len = serializedString.length;\n var i;\n var p = 0;\n var encoded1, encoded2, encoded3, encoded4;\n\n if (serializedString[serializedString.length - 1] === '=') {\n bufferLength--;\n if (serializedString[serializedString.length - 2] === '=') {\n bufferLength--;\n }\n }\n\n var buffer = new ArrayBuffer(bufferLength);\n var bytes = new Uint8Array(buffer);\n\n for (i = 0; i < len; i += 4) {\n encoded1 = BASE_CHARS.indexOf(serializedString[i]);\n encoded2 = BASE_CHARS.indexOf(serializedString[i + 1]);\n encoded3 = BASE_CHARS.indexOf(serializedString[i + 2]);\n encoded4 = BASE_CHARS.indexOf(serializedString[i + 3]);\n\n /*jslint bitwise: true */\n bytes[p++] = encoded1 << 2 | encoded2 >> 4;\n bytes[p++] = (encoded2 & 15) << 4 | encoded3 >> 2;\n bytes[p++] = (encoded3 & 3) << 6 | encoded4 & 63;\n }\n return buffer;\n}\n\n// Converts a buffer to a string to store, serialized, in the backend\n// storage library.\nfunction bufferToString(buffer) {\n // base64-arraybuffer\n var bytes = new Uint8Array(buffer);\n var base64String = '';\n var i;\n\n for (i = 0; i < bytes.length; i += 3) {\n /*jslint bitwise: true */\n base64String += BASE_CHARS[bytes[i] >> 2];\n base64String += BASE_CHARS[(bytes[i] & 3) << 4 | bytes[i + 1] >> 4];\n base64String += BASE_CHARS[(bytes[i + 1] & 15) << 2 | bytes[i + 2] >> 6];\n base64String += BASE_CHARS[bytes[i + 2] & 63];\n }\n\n if (bytes.length % 3 === 2) {\n base64String = base64String.substring(0, base64String.length - 1) + '=';\n } else if (bytes.length % 3 === 1) {\n base64String = base64String.substring(0, base64String.length - 2) + '==';\n }\n\n return base64String;\n}\n\n// Serialize a value, afterwards executing a callback (which usually\n// instructs the `setItem()` callback/promise to be executed). This is how\n// we store binary data with localStorage.\nfunction serialize(value, callback) {\n var valueType = '';\n if (value) {\n valueType = toString$1.call(value);\n }\n\n // Cannot use `value instanceof ArrayBuffer` or such here, as these\n // checks fail when running the tests using casper.js...\n //\n // TODO: See why those tests fail and use a better solution.\n if (value && (valueType === '[object ArrayBuffer]' || value.buffer && toString$1.call(value.buffer) === '[object ArrayBuffer]')) {\n // Convert binary arrays to a string and prefix the string with\n // a special marker.\n var buffer;\n var marker = SERIALIZED_MARKER;\n\n if (value instanceof ArrayBuffer) {\n buffer = value;\n marker += TYPE_ARRAYBUFFER;\n } else {\n buffer = value.buffer;\n\n if (valueType === '[object Int8Array]') {\n marker += TYPE_INT8ARRAY;\n } else if (valueType === '[object Uint8Array]') {\n marker += TYPE_UINT8ARRAY;\n } else if (valueType === '[object Uint8ClampedArray]') {\n marker += TYPE_UINT8CLAMPEDARRAY;\n } else if (valueType === '[object Int16Array]') {\n marker += TYPE_INT16ARRAY;\n } else if (valueType === '[object Uint16Array]') {\n marker += TYPE_UINT16ARRAY;\n } else if (valueType === '[object Int32Array]') {\n marker += TYPE_INT32ARRAY;\n } else if (valueType === '[object Uint32Array]') {\n marker += TYPE_UINT32ARRAY;\n } else if (valueType === '[object Float32Array]') {\n marker += TYPE_FLOAT32ARRAY;\n } else if (valueType === '[object Float64Array]') {\n marker += TYPE_FLOAT64ARRAY;\n } else {\n callback(new Error('Failed to get type for BinaryArray'));\n }\n }\n\n callback(marker + bufferToString(buffer));\n } else if (valueType === '[object Blob]') {\n // Conver the blob to a binaryArray and then to a string.\n var fileReader = new FileReader();\n\n fileReader.onload = function () {\n // Backwards-compatible prefix for the blob type.\n var str = BLOB_TYPE_PREFIX + value.type + '~' + bufferToString(this.result);\n\n callback(SERIALIZED_MARKER + TYPE_BLOB + str);\n };\n\n fileReader.readAsArrayBuffer(value);\n } else {\n try {\n callback(JSON.stringify(value));\n } catch (e) {\n console.error(\"Couldn't convert value into a JSON string: \", value);\n\n callback(null, e);\n }\n }\n}\n\n// Deserialize data we've inserted into a value column/field. We place\n// special markers into our strings to mark them as encoded; this isn't\n// as nice as a meta field, but it's the only sane thing we can do whilst\n// keeping localStorage support intact.\n//\n// Oftentimes this will just deserialize JSON content, but if we have a\n// special marker (SERIALIZED_MARKER, defined above), we will extract\n// some kind of arraybuffer/binary data/typed array out of the string.\nfunction deserialize(value) {\n // If we haven't marked this string as being specially serialized (i.e.\n // something other than serialized JSON), we can just return it and be\n // done with it.\n if (value.substring(0, SERIALIZED_MARKER_LENGTH) !== SERIALIZED_MARKER) {\n return JSON.parse(value);\n }\n\n // The following code deals with deserializing some kind of Blob or\n // TypedArray. First we separate out the type of data we're dealing\n // with from the data itself.\n var serializedString = value.substring(TYPE_SERIALIZED_MARKER_LENGTH);\n var type = value.substring(SERIALIZED_MARKER_LENGTH, TYPE_SERIALIZED_MARKER_LENGTH);\n\n var blobType;\n // Backwards-compatible blob type serialization strategy.\n // DBs created with older versions of localForage will simply not have the blob type.\n if (type === TYPE_BLOB && BLOB_TYPE_PREFIX_REGEX.test(serializedString)) {\n var matcher = serializedString.match(BLOB_TYPE_PREFIX_REGEX);\n blobType = matcher[1];\n serializedString = serializedString.substring(matcher[0].length);\n }\n var buffer = stringToBuffer(serializedString);\n\n // Return the right type based on the code/type set during\n // serialization.\n switch (type) {\n case TYPE_ARRAYBUFFER:\n return buffer;\n case TYPE_BLOB:\n return createBlob([buffer], { type: blobType });\n case TYPE_INT8ARRAY:\n return new Int8Array(buffer);\n case TYPE_UINT8ARRAY:\n return new Uint8Array(buffer);\n case TYPE_UINT8CLAMPEDARRAY:\n return new Uint8ClampedArray(buffer);\n case TYPE_INT16ARRAY:\n return new Int16Array(buffer);\n case TYPE_UINT16ARRAY:\n return new Uint16Array(buffer);\n case TYPE_INT32ARRAY:\n return new Int32Array(buffer);\n case TYPE_UINT32ARRAY:\n return new Uint32Array(buffer);\n case TYPE_FLOAT32ARRAY:\n return new Float32Array(buffer);\n case TYPE_FLOAT64ARRAY:\n return new Float64Array(buffer);\n default:\n throw new Error('Unkown type: ' + type);\n }\n}\n\nvar localforageSerializer = {\n serialize: serialize,\n deserialize: deserialize,\n stringToBuffer: stringToBuffer,\n bufferToString: bufferToString\n};\n\n/*\n * Includes code from:\n *\n * base64-arraybuffer\n * https://github.com/niklasvh/base64-arraybuffer\n *\n * Copyright (c) 2012 Niklas von Hertzen\n * Licensed under the MIT license.\n */\n\nfunction createDbTable(t, dbInfo, callback, errorCallback) {\n t.executeSql('CREATE TABLE IF NOT EXISTS ' + dbInfo.storeName + ' ' + '(id INTEGER PRIMARY KEY, key unique, value)', [], callback, errorCallback);\n}\n\n// Open the WebSQL database (automatically creates one if one didn't\n// previously exist), using any options set in the config.\nfunction _initStorage$1(options) {\n var self = this;\n var dbInfo = {\n db: null\n };\n\n if (options) {\n for (var i in options) {\n dbInfo[i] = typeof options[i] !== 'string' ? options[i].toString() : options[i];\n }\n }\n\n var dbInfoPromise = new Promise$1(function (resolve, reject) {\n // Open the database; the openDatabase API will automatically\n // create it for us if it doesn't exist.\n try {\n dbInfo.db = openDatabase(dbInfo.name, String(dbInfo.version), dbInfo.description, dbInfo.size);\n } catch (e) {\n return reject(e);\n }\n\n // Create our key/value table if it doesn't exist.\n dbInfo.db.transaction(function (t) {\n createDbTable(t, dbInfo, function () {\n self._dbInfo = dbInfo;\n resolve();\n }, function (t, error) {\n reject(error);\n });\n }, reject);\n });\n\n dbInfo.serializer = localforageSerializer;\n return dbInfoPromise;\n}\n\nfunction tryExecuteSql(t, dbInfo, sqlStatement, args, callback, errorCallback) {\n t.executeSql(sqlStatement, args, callback, function (t, error) {\n if (error.code === error.SYNTAX_ERR) {\n t.executeSql('SELECT name FROM sqlite_master ' + \"WHERE type='table' AND name = ?\", [dbInfo.storeName], function (t, results) {\n if (!results.rows.length) {\n // if the table is missing (was deleted)\n // re-create it table and retry\n createDbTable(t, dbInfo, function () {\n t.executeSql(sqlStatement, args, callback, errorCallback);\n }, errorCallback);\n } else {\n errorCallback(t, error);\n }\n }, errorCallback);\n } else {\n errorCallback(t, error);\n }\n }, errorCallback);\n}\n\nfunction getItem$1(key, callback) {\n var self = this;\n\n key = normalizeKey(key);\n\n var promise = new Promise$1(function (resolve, reject) {\n self.ready().then(function () {\n var dbInfo = self._dbInfo;\n dbInfo.db.transaction(function (t) {\n tryExecuteSql(t, dbInfo, 'SELECT * FROM ' + dbInfo.storeName + ' WHERE key = ? LIMIT 1', [key], function (t, results) {\n var result = results.rows.length ? results.rows.item(0).value : null;\n\n // Check to see if this is serialized content we need to\n // unpack.\n if (result) {\n result = dbInfo.serializer.deserialize(result);\n }\n\n resolve(result);\n }, function (t, error) {\n reject(error);\n });\n });\n })[\"catch\"](reject);\n });\n\n executeCallback(promise, callback);\n return promise;\n}\n\nfunction iterate$1(iterator, callback) {\n var self = this;\n\n var promise = new Promise$1(function (resolve, reject) {\n self.ready().then(function () {\n var dbInfo = self._dbInfo;\n\n dbInfo.db.transaction(function (t) {\n tryExecuteSql(t, dbInfo, 'SELECT * FROM ' + dbInfo.storeName, [], function (t, results) {\n var rows = results.rows;\n var length = rows.length;\n\n for (var i = 0; i < length; i++) {\n var item = rows.item(i);\n var result = item.value;\n\n // Check to see if this is serialized content\n // we need to unpack.\n if (result) {\n result = dbInfo.serializer.deserialize(result);\n }\n\n result = iterator(result, item.key, i + 1);\n\n // void(0) prevents problems with redefinition\n // of `undefined`.\n if (result !== void 0) {\n resolve(result);\n return;\n }\n }\n\n resolve();\n }, function (t, error) {\n reject(error);\n });\n });\n })[\"catch\"](reject);\n });\n\n executeCallback(promise, callback);\n return promise;\n}\n\nfunction _setItem(key, value, callback, retriesLeft) {\n var self = this;\n\n key = normalizeKey(key);\n\n var promise = new Promise$1(function (resolve, reject) {\n self.ready().then(function () {\n // The localStorage API doesn't return undefined values in an\n // \"expected\" way, so undefined is always cast to null in all\n // drivers. See: https://github.com/mozilla/localForage/pull/42\n if (value === undefined) {\n value = null;\n }\n\n // Save the original value to pass to the callback.\n var originalValue = value;\n\n var dbInfo = self._dbInfo;\n dbInfo.serializer.serialize(value, function (value, error) {\n if (error) {\n reject(error);\n } else {\n dbInfo.db.transaction(function (t) {\n tryExecuteSql(t, dbInfo, 'INSERT OR REPLACE INTO ' + dbInfo.storeName + ' ' + '(key, value) VALUES (?, ?)', [key, value], function () {\n resolve(originalValue);\n }, function (t, error) {\n reject(error);\n });\n }, function (sqlError) {\n // The transaction failed; check\n // to see if it's a quota error.\n if (sqlError.code === sqlError.QUOTA_ERR) {\n // We reject the callback outright for now, but\n // it's worth trying to re-run the transaction.\n // Even if the user accepts the prompt to use\n // more storage on Safari, this error will\n // be called.\n //\n // Try to re-run the transaction.\n if (retriesLeft > 0) {\n resolve(_setItem.apply(self, [key, originalValue, callback, retriesLeft - 1]));\n return;\n }\n reject(sqlError);\n }\n });\n }\n });\n })[\"catch\"](reject);\n });\n\n executeCallback(promise, callback);\n return promise;\n}\n\nfunction setItem$1(key, value, callback) {\n return _setItem.apply(this, [key, value, callback, 1]);\n}\n\nfunction removeItem$1(key, callback) {\n var self = this;\n\n key = normalizeKey(key);\n\n var promise = new Promise$1(function (resolve, reject) {\n self.ready().then(function () {\n var dbInfo = self._dbInfo;\n dbInfo.db.transaction(function (t) {\n tryExecuteSql(t, dbInfo, 'DELETE FROM ' + dbInfo.storeName + ' WHERE key = ?', [key], function () {\n resolve();\n }, function (t, error) {\n reject(error);\n });\n });\n })[\"catch\"](reject);\n });\n\n executeCallback(promise, callback);\n return promise;\n}\n\n// Deletes every item in the table.\n// TODO: Find out if this resets the AUTO_INCREMENT number.\nfunction clear$1(callback) {\n var self = this;\n\n var promise = new Promise$1(function (resolve, reject) {\n self.ready().then(function () {\n var dbInfo = self._dbInfo;\n dbInfo.db.transaction(function (t) {\n tryExecuteSql(t, dbInfo, 'DELETE FROM ' + dbInfo.storeName, [], function () {\n resolve();\n }, function (t, error) {\n reject(error);\n });\n });\n })[\"catch\"](reject);\n });\n\n executeCallback(promise, callback);\n return promise;\n}\n\n// Does a simple `COUNT(key)` to get the number of items stored in\n// localForage.\nfunction length$1(callback) {\n var self = this;\n\n var promise = new Promise$1(function (resolve, reject) {\n self.ready().then(function () {\n var dbInfo = self._dbInfo;\n dbInfo.db.transaction(function (t) {\n // Ahhh, SQL makes this one soooooo easy.\n tryExecuteSql(t, dbInfo, 'SELECT COUNT(key) as c FROM ' + dbInfo.storeName, [], function (t, results) {\n var result = results.rows.item(0).c;\n resolve(result);\n }, function (t, error) {\n reject(error);\n });\n });\n })[\"catch\"](reject);\n });\n\n executeCallback(promise, callback);\n return promise;\n}\n\n// Return the key located at key index X; essentially gets the key from a\n// `WHERE id = ?`. This is the most efficient way I can think to implement\n// this rarely-used (in my experience) part of the API, but it can seem\n// inconsistent, because we do `INSERT OR REPLACE INTO` on `setItem()`, so\n// the ID of each key will change every time it's updated. Perhaps a stored\n// procedure for the `setItem()` SQL would solve this problem?\n// TODO: Don't change ID on `setItem()`.\nfunction key$1(n, callback) {\n var self = this;\n\n var promise = new Promise$1(function (resolve, reject) {\n self.ready().then(function () {\n var dbInfo = self._dbInfo;\n dbInfo.db.transaction(function (t) {\n tryExecuteSql(t, dbInfo, 'SELECT key FROM ' + dbInfo.storeName + ' WHERE id = ? LIMIT 1', [n + 1], function (t, results) {\n var result = results.rows.length ? results.rows.item(0).key : null;\n resolve(result);\n }, function (t, error) {\n reject(error);\n });\n });\n })[\"catch\"](reject);\n });\n\n executeCallback(promise, callback);\n return promise;\n}\n\nfunction keys$1(callback) {\n var self = this;\n\n var promise = new Promise$1(function (resolve, reject) {\n self.ready().then(function () {\n var dbInfo = self._dbInfo;\n dbInfo.db.transaction(function (t) {\n tryExecuteSql(t, dbInfo, 'SELECT key FROM ' + dbInfo.storeName, [], function (t, results) {\n var keys = [];\n\n for (var i = 0; i < results.rows.length; i++) {\n keys.push(results.rows.item(i).key);\n }\n\n resolve(keys);\n }, function (t, error) {\n reject(error);\n });\n });\n })[\"catch\"](reject);\n });\n\n executeCallback(promise, callback);\n return promise;\n}\n\n// https://www.w3.org/TR/webdatabase/#databases\n// > There is no way to enumerate or delete the databases available for an origin from this API.\nfunction getAllStoreNames(db) {\n return new Promise$1(function (resolve, reject) {\n db.transaction(function (t) {\n t.executeSql('SELECT name FROM sqlite_master ' + \"WHERE type='table' AND name <> '__WebKitDatabaseInfoTable__'\", [], function (t, results) {\n var storeNames = [];\n\n for (var i = 0; i < results.rows.length; i++) {\n storeNames.push(results.rows.item(i).name);\n }\n\n resolve({\n db: db,\n storeNames: storeNames\n });\n }, function (t, error) {\n reject(error);\n });\n }, function (sqlError) {\n reject(sqlError);\n });\n });\n}\n\nfunction dropInstance$1(options, callback) {\n callback = getCallback.apply(this, arguments);\n\n var currentConfig = this.config();\n options = typeof options !== 'function' && options || {};\n if (!options.name) {\n options.name = options.name || currentConfig.name;\n options.storeName = options.storeName || currentConfig.storeName;\n }\n\n var self = this;\n var promise;\n if (!options.name) {\n promise = Promise$1.reject('Invalid arguments');\n } else {\n promise = new Promise$1(function (resolve) {\n var db;\n if (options.name === currentConfig.name) {\n // use the db reference of the current instance\n db = self._dbInfo.db;\n } else {\n db = openDatabase(options.name, '', '', 0);\n }\n\n if (!options.storeName) {\n // drop all database tables\n resolve(getAllStoreNames(db));\n } else {\n resolve({\n db: db,\n storeNames: [options.storeName]\n });\n }\n }).then(function (operationInfo) {\n return new Promise$1(function (resolve, reject) {\n operationInfo.db.transaction(function (t) {\n function dropTable(storeName) {\n return new Promise$1(function (resolve, reject) {\n t.executeSql('DROP TABLE IF EXISTS ' + storeName, [], function () {\n resolve();\n }, function (t, error) {\n reject(error);\n });\n });\n }\n\n var operations = [];\n for (var i = 0, len = operationInfo.storeNames.length; i < len; i++) {\n operations.push(dropTable(operationInfo.storeNames[i]));\n }\n\n Promise$1.all(operations).then(function () {\n resolve();\n })[\"catch\"](function (e) {\n reject(e);\n });\n }, function (sqlError) {\n reject(sqlError);\n });\n });\n });\n }\n\n executeCallback(promise, callback);\n return promise;\n}\n\nvar webSQLStorage = {\n _driver: 'webSQLStorage',\n _initStorage: _initStorage$1,\n _support: isWebSQLValid(),\n iterate: iterate$1,\n getItem: getItem$1,\n setItem: setItem$1,\n removeItem: removeItem$1,\n clear: clear$1,\n length: length$1,\n key: key$1,\n keys: keys$1,\n dropInstance: dropInstance$1\n};\n\nfunction isLocalStorageValid() {\n try {\n return typeof localStorage !== 'undefined' && 'setItem' in localStorage &&\n // in IE8 typeof localStorage.setItem === 'object'\n !!localStorage.setItem;\n } catch (e) {\n return false;\n }\n}\n\nfunction _getKeyPrefix(options, defaultConfig) {\n var keyPrefix = options.name + '/';\n\n if (options.storeName !== defaultConfig.storeName) {\n keyPrefix += options.storeName + '/';\n }\n return keyPrefix;\n}\n\n// Check if localStorage throws when saving an item\nfunction checkIfLocalStorageThrows() {\n var localStorageTestKey = '_localforage_support_test';\n\n try {\n localStorage.setItem(localStorageTestKey, true);\n localStorage.removeItem(localStorageTestKey);\n\n return false;\n } catch (e) {\n return true;\n }\n}\n\n// Check if localStorage is usable and allows to save an item\n// This method checks if localStorage is usable in Safari Private Browsing\n// mode, or in any other case where the available quota for localStorage\n// is 0 and there wasn't any saved items yet.\nfunction _isLocalStorageUsable() {\n return !checkIfLocalStorageThrows() || localStorage.length > 0;\n}\n\n// Config the localStorage backend, using options set in the config.\nfunction _initStorage$2(options) {\n var self = this;\n var dbInfo = {};\n if (options) {\n for (var i in options) {\n dbInfo[i] = options[i];\n }\n }\n\n dbInfo.keyPrefix = _getKeyPrefix(options, self._defaultConfig);\n\n if (!_isLocalStorageUsable()) {\n return Promise$1.reject();\n }\n\n self._dbInfo = dbInfo;\n dbInfo.serializer = localforageSerializer;\n\n return Promise$1.resolve();\n}\n\n// Remove all keys from the datastore, effectively destroying all data in\n// the app's key/value store!\nfunction clear$2(callback) {\n var self = this;\n var promise = self.ready().then(function () {\n var keyPrefix = self._dbInfo.keyPrefix;\n\n for (var i = localStorage.length - 1; i >= 0; i--) {\n var key = localStorage.key(i);\n\n if (key.indexOf(keyPrefix) === 0) {\n localStorage.removeItem(key);\n }\n }\n });\n\n executeCallback(promise, callback);\n return promise;\n}\n\n// Retrieve an item from the store. Unlike the original async_storage\n// library in Gaia, we don't modify return values at all. If a key's value\n// is `undefined`, we pass that value to the callback function.\nfunction getItem$2(key, callback) {\n var self = this;\n\n key = normalizeKey(key);\n\n var promise = self.ready().then(function () {\n var dbInfo = self._dbInfo;\n var result = localStorage.getItem(dbInfo.keyPrefix + key);\n\n // If a result was found, parse it from the serialized\n // string into a JS object. If result isn't truthy, the key\n // is likely undefined and we'll pass it straight to the\n // callback.\n if (result) {\n result = dbInfo.serializer.deserialize(result);\n }\n\n return result;\n });\n\n executeCallback(promise, callback);\n return promise;\n}\n\n// Iterate over all items in the store.\nfunction iterate$2(iterator, callback) {\n var self = this;\n\n var promise = self.ready().then(function () {\n var dbInfo = self._dbInfo;\n var keyPrefix = dbInfo.keyPrefix;\n var keyPrefixLength = keyPrefix.length;\n var length = localStorage.length;\n\n // We use a dedicated iterator instead of the `i` variable below\n // so other keys we fetch in localStorage aren't counted in\n // the `iterationNumber` argument passed to the `iterate()`\n // callback.\n //\n // See: github.com/mozilla/localForage/pull/435#discussion_r38061530\n var iterationNumber = 1;\n\n for (var i = 0; i < length; i++) {\n var key = localStorage.key(i);\n if (key.indexOf(keyPrefix) !== 0) {\n continue;\n }\n var value = localStorage.getItem(key);\n\n // If a result was found, parse it from the serialized\n // string into a JS object. If result isn't truthy, the\n // key is likely undefined and we'll pass it straight\n // to the iterator.\n if (value) {\n value = dbInfo.serializer.deserialize(value);\n }\n\n value = iterator(value, key.substring(keyPrefixLength), iterationNumber++);\n\n if (value !== void 0) {\n return value;\n }\n }\n });\n\n executeCallback(promise, callback);\n return promise;\n}\n\n// Same as localStorage's key() method, except takes a callback.\nfunction key$2(n, callback) {\n var self = this;\n var promise = self.ready().then(function () {\n var dbInfo = self._dbInfo;\n var result;\n try {\n result = localStorage.key(n);\n } catch (error) {\n result = null;\n }\n\n // Remove the prefix from the key, if a key is found.\n if (result) {\n result = result.substring(dbInfo.keyPrefix.length);\n }\n\n return result;\n });\n\n executeCallback(promise, callback);\n return promise;\n}\n\nfunction keys$2(callback) {\n var self = this;\n var promise = self.ready().then(function () {\n var dbInfo = self._dbInfo;\n var length = localStorage.length;\n var keys = [];\n\n for (var i = 0; i < length; i++) {\n var itemKey = localStorage.key(i);\n if (itemKey.indexOf(dbInfo.keyPrefix) === 0) {\n keys.push(itemKey.substring(dbInfo.keyPrefix.length));\n }\n }\n\n return keys;\n });\n\n executeCallback(promise, callback);\n return promise;\n}\n\n// Supply the number of keys in the datastore to the callback function.\nfunction length$2(callback) {\n var self = this;\n var promise = self.keys().then(function (keys) {\n return keys.length;\n });\n\n executeCallback(promise, callback);\n return promise;\n}\n\n// Remove an item from the store, nice and simple.\nfunction removeItem$2(key, callback) {\n var self = this;\n\n key = normalizeKey(key);\n\n var promise = self.ready().then(function () {\n var dbInfo = self._dbInfo;\n localStorage.removeItem(dbInfo.keyPrefix + key);\n });\n\n executeCallback(promise, callback);\n return promise;\n}\n\n// Set a key's value and run an optional callback once the value is set.\n// Unlike Gaia's implementation, the callback function is passed the value,\n// in case you want to operate on that value only after you're sure it\n// saved, or something like that.\nfunction setItem$2(key, value, callback) {\n var self = this;\n\n key = normalizeKey(key);\n\n var promise = self.ready().then(function () {\n // Convert undefined values to null.\n // https://github.com/mozilla/localForage/pull/42\n if (value === undefined) {\n value = null;\n }\n\n // Save the original value to pass to the callback.\n var originalValue = value;\n\n return new Promise$1(function (resolve, reject) {\n var dbInfo = self._dbInfo;\n dbInfo.serializer.serialize(value, function (value, error) {\n if (error) {\n reject(error);\n } else {\n try {\n localStorage.setItem(dbInfo.keyPrefix + key, value);\n resolve(originalValue);\n } catch (e) {\n // localStorage capacity exceeded.\n // TODO: Make this a specific error/event.\n if (e.name === 'QuotaExceededError' || e.name === 'NS_ERROR_DOM_QUOTA_REACHED') {\n reject(e);\n }\n reject(e);\n }\n }\n });\n });\n });\n\n executeCallback(promise, callback);\n return promise;\n}\n\nfunction dropInstance$2(options, callback) {\n callback = getCallback.apply(this, arguments);\n\n options = typeof options !== 'function' && options || {};\n if (!options.name) {\n var currentConfig = this.config();\n options.name = options.name || currentConfig.name;\n options.storeName = options.storeName || currentConfig.storeName;\n }\n\n var self = this;\n var promise;\n if (!options.name) {\n promise = Promise$1.reject('Invalid arguments');\n } else {\n promise = new Promise$1(function (resolve) {\n if (!options.storeName) {\n resolve(options.name + '/');\n } else {\n resolve(_getKeyPrefix(options, self._defaultConfig));\n }\n }).then(function (keyPrefix) {\n for (var i = localStorage.length - 1; i >= 0; i--) {\n var key = localStorage.key(i);\n\n if (key.indexOf(keyPrefix) === 0) {\n localStorage.removeItem(key);\n }\n }\n });\n }\n\n executeCallback(promise, callback);\n return promise;\n}\n\nvar localStorageWrapper = {\n _driver: 'localStorageWrapper',\n _initStorage: _initStorage$2,\n _support: isLocalStorageValid(),\n iterate: iterate$2,\n getItem: getItem$2,\n setItem: setItem$2,\n removeItem: removeItem$2,\n clear: clear$2,\n length: length$2,\n key: key$2,\n keys: keys$2,\n dropInstance: dropInstance$2\n};\n\nvar sameValue = function sameValue(x, y) {\n return x === y || typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y);\n};\n\nvar includes = function includes(array, searchElement) {\n var len = array.length;\n var i = 0;\n while (i < len) {\n if (sameValue(array[i], searchElement)) {\n return true;\n }\n i++;\n }\n\n return false;\n};\n\nvar isArray = Array.isArray || function (arg) {\n return Object.prototype.toString.call(arg) === '[object Array]';\n};\n\n// Drivers are stored here when `defineDriver()` is called.\n// They are shared across all instances of localForage.\nvar DefinedDrivers = {};\n\nvar DriverSupport = {};\n\nvar DefaultDrivers = {\n INDEXEDDB: asyncStorage,\n WEBSQL: webSQLStorage,\n LOCALSTORAGE: localStorageWrapper\n};\n\nvar DefaultDriverOrder = [DefaultDrivers.INDEXEDDB._driver, DefaultDrivers.WEBSQL._driver, DefaultDrivers.LOCALSTORAGE._driver];\n\nvar OptionalDriverMethods = ['dropInstance'];\n\nvar LibraryMethods = ['clear', 'getItem', 'iterate', 'key', 'keys', 'length', 'removeItem', 'setItem'].concat(OptionalDriverMethods);\n\nvar DefaultConfig = {\n description: '',\n driver: DefaultDriverOrder.slice(),\n name: 'localforage',\n // Default DB size is _JUST UNDER_ 5MB, as it's the highest size\n // we can use without a prompt.\n size: 4980736,\n storeName: 'keyvaluepairs',\n version: 1.0\n};\n\nfunction callWhenReady(localForageInstance, libraryMethod) {\n localForageInstance[libraryMethod] = function () {\n var _args = arguments;\n return localForageInstance.ready().then(function () {\n return localForageInstance[libraryMethod].apply(localForageInstance, _args);\n });\n };\n}\n\nfunction extend() {\n for (var i = 1; i < arguments.length; i++) {\n var arg = arguments[i];\n\n if (arg) {\n for (var _key in arg) {\n if (arg.hasOwnProperty(_key)) {\n if (isArray(arg[_key])) {\n arguments[0][_key] = arg[_key].slice();\n } else {\n arguments[0][_key] = arg[_key];\n }\n }\n }\n }\n }\n\n return arguments[0];\n}\n\nvar LocalForage = function () {\n function LocalForage(options) {\n _classCallCheck(this, LocalForage);\n\n for (var driverTypeKey in DefaultDrivers) {\n if (DefaultDrivers.hasOwnProperty(driverTypeKey)) {\n var driver = DefaultDrivers[driverTypeKey];\n var driverName = driver._driver;\n this[driverTypeKey] = driverName;\n\n if (!DefinedDrivers[driverName]) {\n // we don't need to wait for the promise,\n // since the default drivers can be defined\n // in a blocking manner\n this.defineDriver(driver);\n }\n }\n }\n\n this._defaultConfig = extend({}, DefaultConfig);\n this._config = extend({}, this._defaultConfig, options);\n this._driverSet = null;\n this._initDriver = null;\n this._ready = false;\n this._dbInfo = null;\n\n this._wrapLibraryMethodsWithReady();\n this.setDriver(this._config.driver)[\"catch\"](function () {});\n }\n\n // Set any config values for localForage; can be called anytime before\n // the first API call (e.g. `getItem`, `setItem`).\n // We loop through options so we don't overwrite existing config\n // values.\n\n\n LocalForage.prototype.config = function config(options) {\n // If the options argument is an object, we use it to set values.\n // Otherwise, we return either a specified config value or all\n // config values.\n if ((typeof options === 'undefined' ? 'undefined' : _typeof(options)) === 'object') {\n // If localforage is ready and fully initialized, we can't set\n // any new configuration values. Instead, we return an error.\n if (this._ready) {\n return new Error(\"Can't call config() after localforage \" + 'has been used.');\n }\n\n for (var i in options) {\n if (i === 'storeName') {\n options[i] = options[i].replace(/\\W/g, '_');\n }\n\n if (i === 'version' && typeof options[i] !== 'number') {\n return new Error('Database version must be a number.');\n }\n\n this._config[i] = options[i];\n }\n\n // after all config options are set and\n // the driver option is used, try setting it\n if ('driver' in options && options.driver) {\n return this.setDriver(this._config.driver);\n }\n\n return true;\n } else if (typeof options === 'string') {\n return this._config[options];\n } else {\n return this._config;\n }\n };\n\n // Used to define a custom driver, shared across all instances of\n // localForage.\n\n\n LocalForage.prototype.defineDriver = function defineDriver(driverObject, callback, errorCallback) {\n var promise = new Promise$1(function (resolve, reject) {\n try {\n var driverName = driverObject._driver;\n var complianceError = new Error('Custom driver not compliant; see ' + 'https://mozilla.github.io/localForage/#definedriver');\n\n // A driver name should be defined and not overlap with the\n // library-defined, default drivers.\n if (!driverObject._driver) {\n reject(complianceError);\n return;\n }\n\n var driverMethods = LibraryMethods.concat('_initStorage');\n for (var i = 0, len = driverMethods.length; i < len; i++) {\n var driverMethodName = driverMethods[i];\n\n // when the property is there,\n // it should be a method even when optional\n var isRequired = !includes(OptionalDriverMethods, driverMethodName);\n if ((isRequired || driverObject[driverMethodName]) && typeof driverObject[driverMethodName] !== 'function') {\n reject(complianceError);\n return;\n }\n }\n\n var configureMissingMethods = function configureMissingMethods() {\n var methodNotImplementedFactory = function methodNotImplementedFactory(methodName) {\n return function () {\n var error = new Error('Method ' + methodName + ' is not implemented by the current driver');\n var promise = Promise$1.reject(error);\n executeCallback(promise, arguments[arguments.length - 1]);\n return promise;\n };\n };\n\n for (var _i = 0, _len = OptionalDriverMethods.length; _i < _len; _i++) {\n var optionalDriverMethod = OptionalDriverMethods[_i];\n if (!driverObject[optionalDriverMethod]) {\n driverObject[optionalDriverMethod] = methodNotImplementedFactory(optionalDriverMethod);\n }\n }\n };\n\n configureMissingMethods();\n\n var setDriverSupport = function setDriverSupport(support) {\n if (DefinedDrivers[driverName]) {\n console.info('Redefining LocalForage driver: ' + driverName);\n }\n DefinedDrivers[driverName] = driverObject;\n DriverSupport[driverName] = support;\n // don't use a then, so that we can define\n // drivers that have simple _support methods\n // in a blocking manner\n resolve();\n };\n\n if ('_support' in driverObject) {\n if (driverObject._support && typeof driverObject._support === 'function') {\n driverObject._support().then(setDriverSupport, reject);\n } else {\n setDriverSupport(!!driverObject._support);\n }\n } else {\n setDriverSupport(true);\n }\n } catch (e) {\n reject(e);\n }\n });\n\n executeTwoCallbacks(promise, callback, errorCallback);\n return promise;\n };\n\n LocalForage.prototype.driver = function driver() {\n return this._driver || null;\n };\n\n LocalForage.prototype.getDriver = function getDriver(driverName, callback, errorCallback) {\n var getDriverPromise = DefinedDrivers[driverName] ? Promise$1.resolve(DefinedDrivers[driverName]) : Promise$1.reject(new Error('Driver not found.'));\n\n executeTwoCallbacks(getDriverPromise, callback, errorCallback);\n return getDriverPromise;\n };\n\n LocalForage.prototype.getSerializer = function getSerializer(callback) {\n var serializerPromise = Promise$1.resolve(localforageSerializer);\n executeTwoCallbacks(serializerPromise, callback);\n return serializerPromise;\n };\n\n LocalForage.prototype.ready = function ready(callback) {\n var self = this;\n\n var promise = self._driverSet.then(function () {\n if (self._ready === null) {\n self._ready = self._initDriver();\n }\n\n return self._ready;\n });\n\n executeTwoCallbacks(promise, callback, callback);\n return promise;\n };\n\n LocalForage.prototype.setDriver = function setDriver(drivers, callback, errorCallback) {\n var self = this;\n\n if (!isArray(drivers)) {\n drivers = [drivers];\n }\n\n var supportedDrivers = this._getSupportedDrivers(drivers);\n\n function setDriverToConfig() {\n self._config.driver = self.driver();\n }\n\n function extendSelfWithDriver(driver) {\n self._extend(driver);\n setDriverToConfig();\n\n self._ready = self._initStorage(self._config);\n return self._ready;\n }\n\n function initDriver(supportedDrivers) {\n return function () {\n var currentDriverIndex = 0;\n\n function driverPromiseLoop() {\n while (currentDriverIndex < supportedDrivers.length) {\n var driverName = supportedDrivers[currentDriverIndex];\n currentDriverIndex++;\n\n self._dbInfo = null;\n self._ready = null;\n\n return self.getDriver(driverName).then(extendSelfWithDriver)[\"catch\"](driverPromiseLoop);\n }\n\n setDriverToConfig();\n var error = new Error('No available storage method found.');\n self._driverSet = Promise$1.reject(error);\n return self._driverSet;\n }\n\n return driverPromiseLoop();\n };\n }\n\n // There might be a driver initialization in progress\n // so wait for it to finish in order to avoid a possible\n // race condition to set _dbInfo\n var oldDriverSetDone = this._driverSet !== null ? this._driverSet[\"catch\"](function () {\n return Promise$1.resolve();\n }) : Promise$1.resolve();\n\n this._driverSet = oldDriverSetDone.then(function () {\n var driverName = supportedDrivers[0];\n self._dbInfo = null;\n self._ready = null;\n\n return self.getDriver(driverName).then(function (driver) {\n self._driver = driver._driver;\n setDriverToConfig();\n self._wrapLibraryMethodsWithReady();\n self._initDriver = initDriver(supportedDrivers);\n });\n })[\"catch\"](function () {\n setDriverToConfig();\n var error = new Error('No available storage method found.');\n self._driverSet = Promise$1.reject(error);\n return self._driverSet;\n });\n\n executeTwoCallbacks(this._driverSet, callback, errorCallback);\n return this._driverSet;\n };\n\n LocalForage.prototype.supports = function supports(driverName) {\n return !!DriverSupport[driverName];\n };\n\n LocalForage.prototype._extend = function _extend(libraryMethodsAndProperties) {\n extend(this, libraryMethodsAndProperties);\n };\n\n LocalForage.prototype._getSupportedDrivers = function _getSupportedDrivers(drivers) {\n var supportedDrivers = [];\n for (var i = 0, len = drivers.length; i < len; i++) {\n var driverName = drivers[i];\n if (this.supports(driverName)) {\n supportedDrivers.push(driverName);\n }\n }\n return supportedDrivers;\n };\n\n LocalForage.prototype._wrapLibraryMethodsWithReady = function _wrapLibraryMethodsWithReady() {\n // Add a stub for each driver API method that delays the call to the\n // corresponding driver method until localForage is ready. These stubs\n // will be replaced by the driver methods as soon as the driver is\n // loaded, so there is no performance impact.\n for (var i = 0, len = LibraryMethods.length; i < len; i++) {\n callWhenReady(this, LibraryMethods[i]);\n }\n };\n\n LocalForage.prototype.createInstance = function createInstance(options) {\n return new LocalForage(options);\n };\n\n return LocalForage;\n}();\n\n// The actual localForage object that we expose as a module or via a\n// global. It's extended by pulling in one of our other libraries.\n\n\nvar localforage_js = new LocalForage();\n\nmodule.exports = localforage_js;\n\n},{\"3\":3}]},{},[4])(4)\n});\n", "const {\n entries,\n setPrototypeOf,\n isFrozen,\n getPrototypeOf,\n getOwnPropertyDescriptor,\n} = Object;\n\nlet { freeze, seal, create } = Object; // eslint-disable-line import/no-mutable-exports\nlet { apply, construct } = typeof Reflect !== 'undefined' && Reflect;\n\nif (!freeze) {\n freeze = function (x: T): T {\n return x;\n };\n}\n\nif (!seal) {\n seal = function (x: T): T {\n return x;\n };\n}\n\nif (!apply) {\n apply = function (\n func: (thisArg: any, ...args: any[]) => T,\n thisArg: any,\n ...args: any[]\n ): T {\n return func.apply(thisArg, args);\n };\n}\n\nif (!construct) {\n construct = function (Func: new (...args: any[]) => T, ...args: any[]): T {\n return new Func(...args);\n };\n}\n\nconst arrayForEach = unapply(Array.prototype.forEach);\nconst arrayIndexOf = unapply(Array.prototype.indexOf);\nconst arrayLastIndexOf = unapply(Array.prototype.lastIndexOf);\nconst arrayPop = unapply(Array.prototype.pop);\nconst arrayPush = unapply(Array.prototype.push);\nconst arraySlice = unapply(Array.prototype.slice);\nconst arraySplice = unapply(Array.prototype.splice);\nconst arrayIsArray = Array.isArray;\n\nconst stringToLowerCase = unapply(String.prototype.toLowerCase);\nconst stringToString = unapply(String.prototype.toString);\nconst stringMatch = unapply(String.prototype.match);\nconst stringReplace = unapply(String.prototype.replace);\nconst stringIndexOf = unapply(String.prototype.indexOf);\nconst stringTrim = unapply(String.prototype.trim);\n\nconst numberToString = unapply(Number.prototype.toString);\nconst booleanToString = unapply(Boolean.prototype.toString);\nconst bigintToString =\n typeof BigInt === 'undefined' ? null : unapply(BigInt.prototype.toString);\nconst symbolToString =\n typeof Symbol === 'undefined' ? null : unapply(Symbol.prototype.toString);\n\nconst objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);\nconst objectToString = unapply(Object.prototype.toString);\n\nconst regExpTest = unapply(RegExp.prototype.test);\n\nconst typeErrorCreate = unconstruct(TypeError);\n\n/**\n * Creates a new function that calls the given function with a specified thisArg and arguments.\n *\n * @param func - The function to be wrapped and called.\n * @returns A new function that calls the given function with a specified thisArg and arguments.\n */\nfunction unapply(\n func: (thisArg: any, ...args: any[]) => T\n): (thisArg: any, ...args: any[]) => T {\n return (thisArg: any, ...args: any[]): T => {\n if (thisArg instanceof RegExp) {\n thisArg.lastIndex = 0;\n }\n\n return apply(func, thisArg, args);\n };\n}\n\n/**\n * Creates a new function that constructs an instance of the given constructor function with the provided arguments.\n *\n * @param func - The constructor function to be wrapped and called.\n * @returns A new function that constructs an instance of the given constructor function with the provided arguments.\n */\nfunction unconstruct(\n Func: new (...args: any[]) => T\n): (...args: any[]) => T {\n return (...args: any[]): T => construct(Func, args);\n}\n\n/**\n * Add properties to a lookup table\n *\n * @param set - The set to which elements will be added.\n * @param array - The array containing elements to be added to the set.\n * @param transformCaseFunc - An optional function to transform the case of each element before adding to the set.\n * @returns The modified set with added elements.\n */\nfunction addToSet(\n set: Record,\n array: readonly unknown[],\n transformCaseFunc: ReturnType> = stringToLowerCase\n): Record {\n if (setPrototypeOf) {\n // Make 'in' and truthy checks like Boolean(set.constructor)\n // independent of any properties defined on Object.prototype.\n // Prevent prototype setters from intercepting set as a this value.\n setPrototypeOf(set, null);\n }\n\n if (!arrayIsArray(array)) {\n return set;\n }\n\n let l = array.length;\n while (l--) {\n let element = array[l];\n\n if (typeof element === 'string') {\n const lcElement = transformCaseFunc(element);\n\n if (lcElement !== element) {\n // Config presets (e.g. tags.js, attrs.js) are immutable.\n if (!isFrozen(array)) {\n (array as unknown[])[l] = lcElement;\n }\n\n element = lcElement;\n }\n }\n\n set[element as string] = true;\n }\n\n return set;\n}\n\n/**\n * Clean up an array to harden against CSPP\n *\n * @param array - The array to be cleaned.\n * @returns The cleaned version of the array\n */\nfunction cleanArray(array: T[]): Array {\n for (let index = 0; index < array.length; index++) {\n const isPropertyExist = objectHasOwnProperty(array, index);\n\n if (!isPropertyExist) {\n array[index] = null;\n }\n }\n\n return array;\n}\n\n/**\n * Shallow clone an object\n *\n * @param object - The object to be cloned.\n * @returns A new object that copies the original.\n */\nfunction clone>(object: T): T {\n const newObject = create(null);\n\n for (const [property, value] of entries(object)) {\n const isPropertyExist = objectHasOwnProperty(object, property);\n\n if (isPropertyExist) {\n if (arrayIsArray(value)) {\n newObject[property] = cleanArray(value);\n } else if (\n value &&\n typeof value === 'object' &&\n value.constructor === Object\n ) {\n newObject[property] = clone(value);\n } else {\n newObject[property] = value;\n }\n }\n }\n\n return newObject;\n}\n\n/**\n * Convert non-node values into strings without depending on direct property access.\n *\n * @param value - The value to stringify.\n * @returns A string representation of the provided value.\n */\nfunction stringifyValue(value: unknown): string {\n switch (typeof value) {\n case 'string': {\n return value;\n }\n\n case 'number': {\n return numberToString(value);\n }\n\n case 'boolean': {\n return booleanToString(value);\n }\n\n case 'bigint': {\n return bigintToString ? bigintToString(value) : '0';\n }\n\n case 'symbol': {\n return symbolToString ? symbolToString(value) : 'Symbol()';\n }\n\n case 'undefined': {\n return objectToString(value);\n }\n\n case 'function':\n case 'object': {\n if (value === null) {\n return objectToString(value);\n }\n\n const valueAsRecord = value as Record;\n const valueToString = lookupGetter(valueAsRecord, 'toString');\n\n if (typeof valueToString === 'function') {\n const stringified = valueToString(valueAsRecord);\n\n return typeof stringified === 'string'\n ? stringified\n : objectToString(stringified);\n }\n\n return objectToString(value);\n }\n\n default: {\n return objectToString(value);\n }\n }\n}\n\n/**\n * This method automatically checks if the prop is function or getter and behaves accordingly.\n *\n * @param object - The object to look up the getter function in its prototype chain.\n * @param prop - The property name for which to find the getter function.\n * @returns The getter function found in the prototype chain or a fallback function.\n */\nfunction lookupGetter>(\n object: T,\n prop: string\n): ReturnType> | (() => null) {\n while (object !== null) {\n const desc = getOwnPropertyDescriptor(object, prop);\n\n if (desc) {\n if (desc.get) {\n return unapply(desc.get);\n }\n\n if (typeof desc.value === 'function') {\n return unapply(desc.value);\n }\n }\n\n object = getPrototypeOf(object);\n }\n\n function fallbackValue(): null {\n return null;\n }\n\n return fallbackValue;\n}\n\nfunction isRegex(value: unknown): value is RegExp {\n try {\n regExpTest(value as RegExp, '');\n return true;\n } catch {\n return false;\n }\n}\n\nexport {\n // Array\n arrayForEach,\n arrayIndexOf,\n arrayIsArray,\n arrayLastIndexOf,\n arrayPop,\n arrayPush,\n arraySlice,\n arraySplice,\n // Object\n entries,\n freeze,\n getPrototypeOf,\n getOwnPropertyDescriptor,\n isFrozen,\n setPrototypeOf,\n seal,\n clone,\n create,\n objectHasOwnProperty,\n objectToString,\n // RegExp\n regExpTest,\n isRegex,\n // String\n stringIndexOf,\n stringMatch,\n stringReplace,\n stringToLowerCase,\n stringToString,\n stringTrim,\n // Other conversion\n stringifyValue,\n // Errors\n typeErrorCreate,\n // Other\n lookupGetter,\n addToSet,\n // Reflect\n unapply,\n unconstruct,\n};\n", "import { freeze } from './utils.js';\n\nexport const html = freeze([\n 'a',\n 'abbr',\n 'acronym',\n 'address',\n 'area',\n 'article',\n 'aside',\n 'audio',\n 'b',\n 'bdi',\n 'bdo',\n 'big',\n 'blink',\n 'blockquote',\n 'body',\n 'br',\n 'button',\n 'canvas',\n 'caption',\n 'center',\n 'cite',\n 'code',\n 'col',\n 'colgroup',\n 'content',\n 'data',\n 'datalist',\n 'dd',\n 'decorator',\n 'del',\n 'details',\n 'dfn',\n 'dialog',\n 'dir',\n 'div',\n 'dl',\n 'dt',\n 'element',\n 'em',\n 'fieldset',\n 'figcaption',\n 'figure',\n 'font',\n 'footer',\n 'form',\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'head',\n 'header',\n 'hgroup',\n 'hr',\n 'html',\n 'i',\n 'img',\n 'input',\n 'ins',\n 'kbd',\n 'label',\n 'legend',\n 'li',\n 'main',\n 'map',\n 'mark',\n 'marquee',\n 'menu',\n 'menuitem',\n 'meter',\n 'nav',\n 'nobr',\n 'ol',\n 'optgroup',\n 'option',\n 'output',\n 'p',\n 'picture',\n 'pre',\n 'progress',\n 'q',\n 'rp',\n 'rt',\n 'ruby',\n 's',\n 'samp',\n 'search',\n 'section',\n 'select',\n 'shadow',\n 'slot',\n 'small',\n 'source',\n 'spacer',\n 'span',\n 'strike',\n 'strong',\n 'style',\n 'sub',\n 'summary',\n 'sup',\n 'table',\n 'tbody',\n 'td',\n 'template',\n 'textarea',\n 'tfoot',\n 'th',\n 'thead',\n 'time',\n 'tr',\n 'track',\n 'tt',\n 'u',\n 'ul',\n 'var',\n 'video',\n 'wbr',\n] as const);\n\nexport const svg = freeze([\n 'svg',\n 'a',\n 'altglyph',\n 'altglyphdef',\n 'altglyphitem',\n 'animatecolor',\n 'animatemotion',\n 'animatetransform',\n 'circle',\n 'clippath',\n 'defs',\n 'desc',\n 'ellipse',\n 'enterkeyhint',\n 'exportparts',\n 'filter',\n 'font',\n 'g',\n 'glyph',\n 'glyphref',\n 'hkern',\n 'image',\n 'inputmode',\n 'line',\n 'lineargradient',\n 'marker',\n 'mask',\n 'metadata',\n 'mpath',\n 'part',\n 'path',\n 'pattern',\n 'polygon',\n 'polyline',\n 'radialgradient',\n 'rect',\n 'stop',\n 'style',\n 'switch',\n 'symbol',\n 'text',\n 'textpath',\n 'title',\n 'tref',\n 'tspan',\n 'view',\n 'vkern',\n] as const);\n\nexport const svgFilters = freeze([\n 'feBlend',\n 'feColorMatrix',\n 'feComponentTransfer',\n 'feComposite',\n 'feConvolveMatrix',\n 'feDiffuseLighting',\n 'feDisplacementMap',\n 'feDistantLight',\n 'feDropShadow',\n 'feFlood',\n 'feFuncA',\n 'feFuncB',\n 'feFuncG',\n 'feFuncR',\n 'feGaussianBlur',\n 'feImage',\n 'feMerge',\n 'feMergeNode',\n 'feMorphology',\n 'feOffset',\n 'fePointLight',\n 'feSpecularLighting',\n 'feSpotLight',\n 'feTile',\n 'feTurbulence',\n] as const);\n\n// List of SVG elements that are disallowed by default.\n// We still need to know them so that we can do namespace\n// checks properly in case one wants to add them to\n// allow-list.\nexport const svgDisallowed = freeze([\n 'animate',\n 'color-profile',\n 'cursor',\n 'discard',\n 'font-face',\n 'font-face-format',\n 'font-face-name',\n 'font-face-src',\n 'font-face-uri',\n 'foreignobject',\n 'hatch',\n 'hatchpath',\n 'mesh',\n 'meshgradient',\n 'meshpatch',\n 'meshrow',\n 'missing-glyph',\n 'script',\n 'set',\n 'solidcolor',\n 'unknown',\n 'use',\n] as const);\n\nexport const mathMl = freeze([\n 'math',\n 'menclose',\n 'merror',\n 'mfenced',\n 'mfrac',\n 'mglyph',\n 'mi',\n 'mlabeledtr',\n 'mmultiscripts',\n 'mn',\n 'mo',\n 'mover',\n 'mpadded',\n 'mphantom',\n 'mroot',\n 'mrow',\n 'ms',\n 'mspace',\n 'msqrt',\n 'mstyle',\n 'msub',\n 'msup',\n 'msubsup',\n 'mtable',\n 'mtd',\n 'mtext',\n 'mtr',\n 'munder',\n 'munderover',\n 'mprescripts',\n] as const);\n\n// Similarly to SVG, we want to know all MathML elements,\n// even those that we disallow by default.\nexport const mathMlDisallowed = freeze([\n 'maction',\n 'maligngroup',\n 'malignmark',\n 'mlongdiv',\n 'mscarries',\n 'mscarry',\n 'msgroup',\n 'mstack',\n 'msline',\n 'msrow',\n 'semantics',\n 'annotation',\n 'annotation-xml',\n 'mprescripts',\n 'none',\n] as const);\n\nexport const text = freeze(['#text'] as const);\n", "import { freeze } from './utils.js';\n\nexport const html = freeze([\n 'accept',\n 'action',\n 'align',\n 'alt',\n 'autocapitalize',\n 'autocomplete',\n 'autopictureinpicture',\n 'autoplay',\n 'background',\n 'bgcolor',\n 'border',\n 'capture',\n 'cellpadding',\n 'cellspacing',\n 'checked',\n 'cite',\n 'class',\n 'clear',\n 'color',\n 'cols',\n 'colspan',\n 'command',\n 'commandfor',\n 'controls',\n 'controlslist',\n 'coords',\n 'crossorigin',\n 'datetime',\n 'decoding',\n 'default',\n 'dir',\n 'disabled',\n 'disablepictureinpicture',\n 'disableremoteplayback',\n 'download',\n 'draggable',\n 'enctype',\n 'enterkeyhint',\n 'exportparts',\n 'face',\n 'for',\n 'headers',\n 'height',\n 'hidden',\n 'high',\n 'href',\n 'hreflang',\n 'id',\n 'inert',\n 'inputmode',\n 'integrity',\n 'ismap',\n 'kind',\n 'label',\n 'lang',\n 'list',\n 'loading',\n 'loop',\n 'low',\n 'max',\n 'maxlength',\n 'media',\n 'method',\n 'min',\n 'minlength',\n 'multiple',\n 'muted',\n 'name',\n 'nonce',\n 'noshade',\n 'novalidate',\n 'nowrap',\n 'open',\n 'optimum',\n 'part',\n 'pattern',\n 'placeholder',\n 'playsinline',\n 'popover',\n 'popovertarget',\n 'popovertargetaction',\n 'poster',\n 'preload',\n 'pubdate',\n 'radiogroup',\n 'readonly',\n 'rel',\n 'required',\n 'rev',\n 'reversed',\n 'role',\n 'rows',\n 'rowspan',\n 'spellcheck',\n 'scope',\n 'selected',\n 'shape',\n 'size',\n 'sizes',\n 'slot',\n 'span',\n 'srclang',\n 'start',\n 'src',\n 'srcset',\n 'step',\n 'style',\n 'summary',\n 'tabindex',\n 'title',\n 'translate',\n 'type',\n 'usemap',\n 'valign',\n 'value',\n 'width',\n 'wrap',\n 'xmlns',\n] as const);\n\nexport const svg = freeze([\n 'accent-height',\n 'accumulate',\n 'additive',\n 'alignment-baseline',\n 'amplitude',\n 'ascent',\n 'attributename',\n 'attributetype',\n 'azimuth',\n 'basefrequency',\n 'baseline-shift',\n 'begin',\n 'bias',\n 'by',\n 'class',\n 'clip',\n 'clippathunits',\n 'clip-path',\n 'clip-rule',\n 'color',\n 'color-interpolation',\n 'color-interpolation-filters',\n 'color-profile',\n 'color-rendering',\n 'cx',\n 'cy',\n 'd',\n 'dx',\n 'dy',\n 'diffuseconstant',\n 'direction',\n 'display',\n 'divisor',\n 'dominant-baseline',\n 'dur',\n 'edgemode',\n 'elevation',\n 'end',\n 'exponent',\n 'fill',\n 'fill-opacity',\n 'fill-rule',\n 'filter',\n 'filterunits',\n 'flood-color',\n 'flood-opacity',\n 'font-family',\n 'font-size',\n 'font-size-adjust',\n 'font-stretch',\n 'font-style',\n 'font-variant',\n 'font-weight',\n 'fx',\n 'fy',\n 'g1',\n 'g2',\n 'glyph-name',\n 'glyphref',\n 'gradientunits',\n 'gradienttransform',\n 'height',\n 'href',\n 'id',\n 'image-rendering',\n 'in',\n 'in2',\n 'intercept',\n 'k',\n 'k1',\n 'k2',\n 'k3',\n 'k4',\n 'kerning',\n 'keypoints',\n 'keysplines',\n 'keytimes',\n 'lang',\n 'lengthadjust',\n 'letter-spacing',\n 'kernelmatrix',\n 'kernelunitlength',\n 'lighting-color',\n 'local',\n 'marker-end',\n 'marker-mid',\n 'marker-start',\n 'markerheight',\n 'markerunits',\n 'markerwidth',\n 'maskcontentunits',\n 'maskunits',\n 'max',\n 'mask',\n 'mask-type',\n 'media',\n 'method',\n 'mode',\n 'min',\n 'name',\n 'numoctaves',\n 'offset',\n 'operator',\n 'opacity',\n 'order',\n 'orient',\n 'orientation',\n 'origin',\n 'overflow',\n 'paint-order',\n 'path',\n 'pathlength',\n 'patterncontentunits',\n 'patterntransform',\n 'patternunits',\n 'points',\n 'preservealpha',\n 'preserveaspectratio',\n 'primitiveunits',\n 'r',\n 'rx',\n 'ry',\n 'radius',\n 'refx',\n 'refy',\n 'repeatcount',\n 'repeatdur',\n 'restart',\n 'result',\n 'rotate',\n 'scale',\n 'seed',\n 'shape-rendering',\n 'slope',\n 'specularconstant',\n 'specularexponent',\n 'spreadmethod',\n 'startoffset',\n 'stddeviation',\n 'stitchtiles',\n 'stop-color',\n 'stop-opacity',\n 'stroke-dasharray',\n 'stroke-dashoffset',\n 'stroke-linecap',\n 'stroke-linejoin',\n 'stroke-miterlimit',\n 'stroke-opacity',\n 'stroke',\n 'stroke-width',\n 'style',\n 'surfacescale',\n 'systemlanguage',\n 'tabindex',\n 'tablevalues',\n 'targetx',\n 'targety',\n 'transform',\n 'transform-origin',\n 'text-anchor',\n 'text-decoration',\n 'text-orientation',\n 'text-rendering',\n 'textlength',\n 'type',\n 'u1',\n 'u2',\n 'unicode',\n 'values',\n 'viewbox',\n 'visibility',\n 'version',\n 'vert-adv-y',\n 'vert-origin-x',\n 'vert-origin-y',\n 'width',\n 'word-spacing',\n 'wrap',\n 'writing-mode',\n 'xchannelselector',\n 'ychannelselector',\n 'x',\n 'x1',\n 'x2',\n 'xmlns',\n 'y',\n 'y1',\n 'y2',\n 'z',\n 'zoomandpan',\n] as const);\n\nexport const mathMl = freeze([\n 'accent',\n 'accentunder',\n 'align',\n 'bevelled',\n 'close',\n 'columnalign',\n 'columnlines',\n 'columnspacing',\n 'columnspan',\n 'denomalign',\n 'depth',\n 'dir',\n 'display',\n 'displaystyle',\n 'encoding',\n 'fence',\n 'frame',\n 'height',\n 'href',\n 'id',\n 'largeop',\n 'length',\n 'linethickness',\n 'lquote',\n 'lspace',\n 'mathbackground',\n 'mathcolor',\n 'mathsize',\n 'mathvariant',\n 'maxsize',\n 'minsize',\n 'movablelimits',\n 'notation',\n 'numalign',\n 'open',\n 'rowalign',\n 'rowlines',\n 'rowspacing',\n 'rowspan',\n 'rspace',\n 'rquote',\n 'scriptlevel',\n 'scriptminsize',\n 'scriptsizemultiplier',\n 'selection',\n 'separator',\n 'separators',\n 'stretchy',\n 'subscriptshift',\n 'supscriptshift',\n 'symmetric',\n 'voffset',\n 'width',\n 'xmlns',\n]);\n\nexport const xml = freeze([\n 'xlink:href',\n 'xml:id',\n 'xlink:title',\n 'xml:space',\n 'xmlns:xlink',\n] as const);\n", "import { seal } from './utils.js';\n\nexport const MUSTACHE_EXPR = seal(/{{[\\w\\W]*|^[\\w\\W]*}}/g);\nexport const ERB_EXPR = seal(/<%[\\w\\W]*|^[\\w\\W]*%>/g);\nexport const TMPLIT_EXPR = seal(/\\${[\\w\\W]*/g);\nexport const DATA_ATTR = seal(/^data-[\\-\\w.\\u00B7-\\uFFFF]+$/); // eslint-disable-line no-useless-escape\nexport const ARIA_ATTR = seal(/^aria-[\\-\\w]+$/); // eslint-disable-line no-useless-escape\nexport const IS_ALLOWED_URI = seal(\n /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\\-]+(?:[^a-z+.\\-:]|$))/i // eslint-disable-line no-useless-escape\n);\nexport const IS_SCRIPT_OR_DATA = seal(/^(?:\\w+script|data):/i);\nexport const ATTR_WHITESPACE = seal(\n /[\\u0000-\\u0020\\u00A0\\u1680\\u180E\\u2000-\\u2029\\u205F\\u3000]/g // eslint-disable-line no-control-regex\n);\nexport const DOCTYPE_NAME = seal(/^html$/i);\nexport const CUSTOM_ELEMENT = seal(/^[a-z][.\\w]*(-[.\\w]+)+$/i);\n\n// Markup-significant character probes used by _sanitizeElements.\n// Shared module-level instances are safe despite the sticky /g flags:\n// unapply() resets lastIndex for RegExp receivers before every call.\nexport const ELEMENT_MARKUP_PROBE = seal(/<[/\\w!]/g);\nexport const COMMENT_MARKUP_PROBE = seal(/<[/\\w]/g);\nexport const FALLBACK_TAG_CLOSE = seal(/<\\/no(script|embed|frames)/i);\nexport const SELF_CLOSING_TAG = seal(/\\/>/i);\n", "import type { Config, UseProfilesConfig } from './config';\nimport type { DOMPurify, HooksMap, HookFunction, WindowLike } from './types';\nimport * as TAGS from './tags.js';\nimport * as ATTRS from './attrs.js';\nimport * as EXPRESSIONS from './regexp.js';\nimport {\n addToSet,\n clone,\n entries,\n freeze,\n seal,\n arrayForEach,\n arrayIsArray,\n arrayLastIndexOf,\n arrayPop,\n arrayPush,\n arraySplice,\n stringMatch,\n stringReplace,\n stringToLowerCase,\n stringToString,\n stringIndexOf,\n stringTrim,\n regExpTest,\n isRegex,\n typeErrorCreate,\n lookupGetter,\n create,\n objectHasOwnProperty,\n stringifyValue,\n} from './utils.js';\n\nexport type { Config } from './config';\n\nexport type {\n DOMPurify,\n RemovedElement,\n RemovedAttribute,\n HookName,\n NodeHook,\n ElementHook,\n DocumentFragmentHook,\n UponSanitizeElementHook,\n UponSanitizeAttributeHook,\n UponSanitizeElementHookEvent,\n UponSanitizeAttributeHookEvent,\n WindowLike,\n} from './types';\n\ndeclare const VERSION: string;\n\n// https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType\nconst NODE_TYPE = {\n element: 1,\n attribute: 2,\n text: 3,\n cdataSection: 4,\n entityReference: 5, // Deprecated\n entityNode: 6, // Deprecated\n processingInstruction: 7,\n comment: 8,\n document: 9,\n documentType: 10,\n documentFragment: 11,\n notation: 12, // Deprecated\n};\n\nconst getGlobal = function (): WindowLike {\n return typeof window === 'undefined' ? null : window;\n};\n\n/**\n * Creates a no-op policy for internal use only.\n * Don't export this function outside this module!\n * @param trustedTypes The policy factory.\n * @param purifyHostElement The Script element used to load DOMPurify (to determine policy name suffix).\n * @return The policy created (or null, if Trusted Types\n * are not supported or creating the policy failed).\n */\nconst _createTrustedTypesPolicy = function (\n trustedTypes: TrustedTypePolicyFactory,\n purifyHostElement: HTMLScriptElement\n) {\n if (\n typeof trustedTypes !== 'object' ||\n typeof trustedTypes.createPolicy !== 'function'\n ) {\n return null;\n }\n\n // Allow the callers to control the unique policy name\n // by adding a data-tt-policy-suffix to the script element with the DOMPurify.\n // Policy creation with duplicate names throws in Trusted Types.\n let suffix = null;\n const ATTR_NAME = 'data-tt-policy-suffix';\n if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) {\n suffix = purifyHostElement.getAttribute(ATTR_NAME);\n }\n\n const policyName = 'dompurify' + (suffix ? '#' + suffix : '');\n\n try {\n return trustedTypes.createPolicy(policyName, {\n createHTML(html) {\n return html;\n },\n createScriptURL(scriptUrl) {\n return scriptUrl;\n },\n });\n } catch (_) {\n // Policy creation failed (most likely another DOMPurify script has\n // already run). Skip creating the policy, as this will only cause errors\n // if TT are enforced.\n console.warn(\n 'TrustedTypes policy ' + policyName + ' could not be created.'\n );\n return null;\n }\n};\n\nconst _createHooksMap = function (): HooksMap {\n return {\n afterSanitizeAttributes: [],\n afterSanitizeElements: [],\n afterSanitizeShadowDOM: [],\n beforeSanitizeAttributes: [],\n beforeSanitizeElements: [],\n beforeSanitizeShadowDOM: [],\n uponSanitizeAttribute: [],\n uponSanitizeElement: [],\n uponSanitizeShadowNode: [],\n };\n};\n\n/**\n * Resolve a set-valued configuration option: a fresh set built from\n * cfg[key] when it is an own array property (seeded with a clone of\n * options.base when given, case-normalized via options.transform),\n * the fallback set otherwise.\n *\n * @param cfg the cloned, prototype-free configuration object\n * @param key the configuration property to read\n * @param fallback the set to use when the option is absent or not an array\n * @param options transform and optional base set to merge into\n * @returns the resolved set\n */\nconst _resolveSetOption = function (\n cfg: Config,\n key: keyof Config,\n fallback: Record,\n options: {\n transform: Parameters[2];\n base?: Record;\n }\n): Record {\n return objectHasOwnProperty(cfg, key) && arrayIsArray(cfg[key])\n ? addToSet(\n options.base ? clone(options.base) : {},\n cfg[key] as readonly unknown[],\n options.transform\n )\n : fallback;\n};\n\nfunction createDOMPurify(window: WindowLike = getGlobal()): DOMPurify {\n const DOMPurify: DOMPurify = (root: WindowLike) => createDOMPurify(root);\n\n DOMPurify.version = VERSION;\n\n DOMPurify.removed = [];\n\n if (\n !window ||\n !window.document ||\n window.document.nodeType !== NODE_TYPE.document ||\n !window.Element\n ) {\n // Not running in a browser, provide a factory function\n // so that you can pass your own Window\n DOMPurify.isSupported = false;\n\n return DOMPurify;\n }\n\n let { document } = window;\n\n const originalDocument = document;\n const currentScript: HTMLScriptElement =\n originalDocument.currentScript as HTMLScriptElement;\n const {\n DocumentFragment,\n HTMLTemplateElement,\n Node,\n Element,\n NodeFilter,\n NamedNodeMap = window.NamedNodeMap || (window as any).MozNamedAttrMap,\n HTMLFormElement,\n DOMParser,\n trustedTypes,\n } = window;\n\n const ElementPrototype = Element.prototype;\n\n const cloneNode = lookupGetter(ElementPrototype, 'cloneNode');\n const remove = lookupGetter(ElementPrototype, 'remove');\n const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');\n const getChildNodes = lookupGetter(ElementPrototype, 'childNodes');\n const getParentNode = lookupGetter(ElementPrototype, 'parentNode');\n const getShadowRoot = lookupGetter(ElementPrototype, 'shadowRoot');\n const getAttributes = lookupGetter(ElementPrototype, 'attributes');\n const getNodeType =\n Node && Node.prototype ? lookupGetter(Node.prototype, 'nodeType') : null;\n const getNodeName =\n Node && Node.prototype ? lookupGetter(Node.prototype, 'nodeName') : null;\n const getOwnerDocument =\n Node && Node.prototype\n ? lookupGetter(Node.prototype, 'ownerDocument')\n : null;\n\n // As per issue #47, the web-components registry is inherited by a\n // new document created via createHTMLDocument. As per the spec\n // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)\n // a new empty registry is used when creating a template contents owner\n // document, so we use that as our parent document to ensure nothing\n // is inherited.\n if (typeof HTMLTemplateElement === 'function') {\n const template = document.createElement('template');\n if (template.content && template.content.ownerDocument) {\n document = template.content.ownerDocument;\n }\n }\n\n let trustedTypesPolicy;\n let emptyHTML = '';\n\n // The instance's own internal Trusted Types policy. Unlike a caller-supplied\n // `TRUSTED_TYPES_POLICY`, this is created at most once \u2014 Trusted Types throws\n // on duplicate policy names \u2014 and is the only policy allowed to persist\n // across configurations and survive `clearConfig()`.\n let defaultTrustedTypesPolicy;\n let defaultTrustedTypesPolicyResolved = false;\n\n // Tracks whether we are already inside a call to the configured Trusted Types\n // policy (`createHTML` or `createScriptURL`). If a supplied policy callback\n // itself calls `DOMPurify.sanitize` (the cause of #1422), `sanitize` would\n // re-enter the policy and recurse until the stack overflows. We detect that\n // re-entry and throw a clear, actionable error instead. The guard is shared\n // across both callbacks, because either one re-entering `sanitize` triggers\n // the same unbounded recursion.\n let IN_TRUSTED_TYPES_POLICY = 0;\n const _assertNotInTrustedTypesPolicy = function (): void {\n if (IN_TRUSTED_TYPES_POLICY > 0) {\n throw typeErrorCreate(\n 'A configured TRUSTED_TYPES_POLICY callback (createHTML or ' +\n 'createScriptURL) must not call DOMPurify.sanitize, as that causes ' +\n 'infinite recursion. Do not pass a policy whose callbacks wrap ' +\n 'DOMPurify as TRUSTED_TYPES_POLICY; see the \"DOMPurify and Trusted ' +\n 'Types\" section of the README.'\n );\n }\n };\n\n const _createTrustedHTML = function (html: string): string {\n _assertNotInTrustedTypesPolicy();\n\n IN_TRUSTED_TYPES_POLICY++;\n try {\n return trustedTypesPolicy.createHTML(html);\n } finally {\n IN_TRUSTED_TYPES_POLICY--;\n }\n };\n\n const _createTrustedScriptURL = function (scriptUrl: string): string {\n _assertNotInTrustedTypesPolicy();\n\n IN_TRUSTED_TYPES_POLICY++;\n try {\n return trustedTypesPolicy.createScriptURL(scriptUrl);\n } finally {\n IN_TRUSTED_TYPES_POLICY--;\n }\n };\n\n // Lazily resolve (and cache) the instance's internal default policy.\n // Resolution is attempted at most once: a successful `createPolicy` cannot be\n // repeated (Trusted Types throws on duplicate names), and a failed or\n // unsupported attempt must not be retried on every parse.\n const _getDefaultTrustedTypesPolicy = function () {\n if (!defaultTrustedTypesPolicyResolved) {\n defaultTrustedTypesPolicy = _createTrustedTypesPolicy(\n trustedTypes,\n currentScript\n );\n defaultTrustedTypesPolicyResolved = true;\n }\n\n return defaultTrustedTypesPolicy;\n };\n\n const {\n implementation,\n createNodeIterator,\n createDocumentFragment,\n getElementsByTagName,\n } = document;\n const { importNode } = originalDocument;\n\n let hooks = _createHooksMap();\n\n /**\n * Expose whether this browser supports running the full DOMPurify.\n */\n DOMPurify.isSupported =\n typeof entries === 'function' &&\n typeof getParentNode === 'function' &&\n implementation &&\n implementation.createHTMLDocument !== undefined;\n\n const {\n MUSTACHE_EXPR,\n ERB_EXPR,\n TMPLIT_EXPR,\n DATA_ATTR,\n ARIA_ATTR,\n IS_SCRIPT_OR_DATA,\n ATTR_WHITESPACE,\n CUSTOM_ELEMENT,\n } = EXPRESSIONS;\n\n let { IS_ALLOWED_URI } = EXPRESSIONS;\n\n /**\n * We consider the elements and attributes below to be safe. Ideally\n * don't add any new ones but feel free to remove unwanted ones.\n */\n\n /* allowed element names */\n let ALLOWED_TAGS = null;\n const DEFAULT_ALLOWED_TAGS = addToSet({}, [\n ...TAGS.html,\n ...TAGS.svg,\n ...TAGS.svgFilters,\n ...TAGS.mathMl,\n ...TAGS.text,\n ]);\n\n /* Allowed attribute names */\n let ALLOWED_ATTR = null;\n const DEFAULT_ALLOWED_ATTR = addToSet({}, [\n ...ATTRS.html,\n ...ATTRS.svg,\n ...ATTRS.mathMl,\n ...ATTRS.xml,\n ]);\n\n /*\n * Configure how DOMPurify should handle custom elements and their attributes as well as customized built-in elements.\n * @property {RegExp|Function|null} tagNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any custom elements)\n * @property {RegExp|Function|null} attributeNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any attributes not on the allow list)\n * @property {boolean} allowCustomizedBuiltInElements allow custom elements derived from built-ins if they pass CUSTOM_ELEMENT_HANDLING.tagNameCheck. Default: `false`.\n */\n let CUSTOM_ELEMENT_HANDLING = Object.seal(\n create(null, {\n tagNameCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null,\n },\n attributeNameCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null,\n },\n allowCustomizedBuiltInElements: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: false,\n },\n })\n );\n\n /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */\n let FORBID_TAGS = null;\n\n /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */\n let FORBID_ATTR = null;\n\n /* Config object to store ADD_TAGS/ADD_ATTR functions (when used as functions) */\n const EXTRA_ELEMENT_HANDLING = Object.seal(\n create(null, {\n tagCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null,\n },\n attributeCheck: {\n writable: true,\n configurable: false,\n enumerable: true,\n value: null,\n },\n })\n );\n\n /* Decide if ARIA attributes are okay */\n let ALLOW_ARIA_ATTR = true;\n\n /* Decide if custom data attributes are okay */\n let ALLOW_DATA_ATTR = true;\n\n /* Decide if unknown protocols are okay */\n let ALLOW_UNKNOWN_PROTOCOLS = false;\n\n /* Decide if self-closing tags in attributes are allowed.\n * Usually removed due to a mXSS issue in jQuery 3.0 */\n let ALLOW_SELF_CLOSE_IN_ATTR = true;\n\n /* Output should be safe for common template engines.\n * This means, DOMPurify removes data attributes, mustaches and ERB\n */\n let SAFE_FOR_TEMPLATES = false;\n\n /* Output should be safe even for XML used within HTML and alike.\n * This means, DOMPurify removes comments when containing risky content.\n */\n let SAFE_FOR_XML = true;\n\n /* Decide if document with ... should be returned */\n let WHOLE_DOCUMENT = false;\n\n /* Track whether config is already set on this instance of DOMPurify. */\n let SET_CONFIG = false;\n\n /* Pristine allowlist bindings captured at setConfig() time. On the\n * persistent-config path sanitize() restores the sets from these before\n * the per-walk hook clone-guard, so a hook's in-call widening cannot\n * carry across calls. Null until setConfig() is called; reset by\n * clearConfig(). */\n let SET_CONFIG_ALLOWED_TAGS = null;\n let SET_CONFIG_ALLOWED_ATTR = null;\n\n /* Decide if all elements (e.g. style, script) must be children of\n * document.body. By default, browsers might move them to document.head */\n let FORCE_BODY = false;\n\n /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html\n * string (or a TrustedHTML object if Trusted Types are supported).\n * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead\n */\n let RETURN_DOM = false;\n\n /* Decide if a DOM `DocumentFragment` should be returned, instead of a html\n * string (or a TrustedHTML object if Trusted Types are supported) */\n let RETURN_DOM_FRAGMENT = false;\n\n /* Try to return a Trusted Type object instead of a string, return a string in\n * case Trusted Types are not supported */\n let RETURN_TRUSTED_TYPE = false;\n\n /* Output should be free from DOM clobbering attacks?\n * This sanitizes markups named with colliding, clobberable built-in DOM APIs.\n */\n let SANITIZE_DOM = true;\n\n /* Achieve full DOM Clobbering protection by isolating the namespace of named\n * properties and JS variables, mitigating attacks that abuse the HTML/DOM spec rules.\n *\n * HTML/DOM spec rules that enable DOM Clobbering:\n * - Named Access on Window (\u00A77.3.3)\n * - DOM Tree Accessors (\u00A73.1.5)\n * - Form Element Parent-Child Relations (\u00A74.10.3)\n * - Iframe srcdoc / Nested WindowProxies (\u00A74.8.5)\n * - HTMLCollection (\u00A74.2.10.2)\n *\n * Namespace isolation is implemented by prefixing `id` and `name` attributes\n * with a constant string, i.e., `user-content-`\n */\n let SANITIZE_NAMED_PROPS = false;\n const SANITIZE_NAMED_PROPS_PREFIX = 'user-content-';\n\n /* Keep element content when removing element? */\n let KEEP_CONTENT = true;\n\n /* If a `Node` is passed to sanitize(), then performs sanitization in-place instead\n * of importing it into a new Document and returning a sanitized copy */\n let IN_PLACE = false;\n\n /* Allow usage of profiles like html, svg and mathMl */\n let USE_PROFILES: UseProfilesConfig | false = {};\n\n /* Tags to ignore content of when KEEP_CONTENT is true */\n let FORBID_CONTENTS = null;\n const DEFAULT_FORBID_CONTENTS = addToSet({}, [\n 'annotation-xml',\n 'audio',\n 'colgroup',\n 'desc',\n 'foreignobject',\n 'head',\n 'iframe',\n 'math',\n 'mi',\n 'mn',\n 'mo',\n 'ms',\n 'mtext',\n 'noembed',\n 'noframes',\n 'noscript',\n 'plaintext',\n 'script',\n // mirrors the selected