jsgbc
Version:
jsGBC Core Emulator
1 lines • 201 kB
JavaScript
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define("jsgbc-core",[],e):"object"==typeof exports?exports["jsgbc-core"]=e():t["jsgbc-core"]=e()}("undefined"!=typeof self?self:this,(function(){return(()=>{"use strict";var t={m:{},n:e=>{var i=e&&e.__esModule?()=>e.default:()=>e;return t.d(i,{a:i}),i},d:(e,i)=>{for(var r in i)t.o(i,r)&&!t.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:i[r]})},u:t=>t+".js",o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},p:"/"};t.b=document.baseURI||self.location.href;var e={};t.r(e),t.d(e,{GameBoy:()=>mt,LocalStorage:()=>st,MemoryStorage:()=>ht,Storage:()=>rt,default:()=>ct,util:()=>i});var i={};t.r(i),t.d(i,{concatArrayBuffers:()=>g,debounce:()=>d,fetchFileAsArrayBuffer:()=>c,fromTypedArray:()=>o,getTypedArray:()=>n,hasExtension:()=>b,readBlob:()=>l,readFirstMatchingExtension:()=>u,saveAs:()=>y,stringToArrayBuffer:()=>m,toTypedArray:()=>a});const r=require("jszip");var s=t.n(r);const h=require("file-saver");function a(t,e){try{if(!(t&&t.length<1))return[];var i=t.length;let s;switch(e){case"uint8":s=new Uint8Array(i);break;case"int8":s=new Int8Array(i);break;case"int32":s=new Int32Array(i);break;case"float32":s=new Float32Array(i)}for(var r=0;r<i;r++)s[r]=t[r];return s}catch(e){return console.log("Could not convert an array to a typed array: "+e.message,1),t}}function o(t){try{if(!t||!t.length)return[];for(var e=[],i=0;i<t.length;++i)e[i]=t[i];return e}catch(e){return console.log("Conversion from a typed array failed: "+e.message,1),t}}function n(t,e,i){let r;switch(i){case"int8":r=new Int8Array(t);break;case"uint8":r=new Uint8Array(t);break;case"int32":r=new Int32Array(t);break;case"float32":r=new Float32Array(t)}if(0!==e){let i=0;for(;i<t;)r[i++]=e}return r}function m(t){const e=new Uint8Array(t.length);for(let i=0,r=t.length;i<r;i++)e[i]=t.charCodeAt(i);return e}async function c(t){const e=await fetch(t);return await e.arrayBuffer()}function g(...t){let e=0;for(let i=0;i<t.length;i++)e+=t[i].byteLength;const i=new Uint8Array(e);for(let e=0;e<t.length;e++){const r=new Uint8Array(t[e]);0===e?i.set(r):i.set(r,t[e-1].byteLength)}return i.buffer}function y(t,e){t instanceof ArrayBuffer&&(t=new Uint8Array(t)),t instanceof Uint8Array&&(t=new Blob([t],{type:"application/octet-binary"})),h.saveAs(t,e)}async function l(t){return new Promise(((e,i)=>{if(t){const i=new FileReader;i.addEventListener("load",(function(){2===this.readyState&&e(this.result)})),i.readAsArrayBuffer(t)}else i()}))}async function u(t,e="",i){let r=await l(t);if(!i.includes("zip")&&b(e,"zip")){const t=await s().loadAsync(r),e=Object.keys(t.files).filter((t=>i.find((e=>b(t,e)))));r=e.length>0?await t.file(e[0]).async("arraybuffer"):void 0}return r}function b(t,e){return t=t.toLowerCase(),e="."+e.toLowerCase(),t.lastIndexOf(e)===t.length-e.length}function d(t,e){var i,r,s,h,a;function o(){var n=Date.now()-h;n<e&&n>=0?i=setTimeout(o,e-n):(i=null,a=t.apply(s,r),s=r=null)}var n=function(){return s=this,r=arguments,h=Date.now(),i||(i=setTimeout(o,e)),a};return n.clear=function(){i&&(clearTimeout(i),i=null)},n.flush=function(){i&&(a=t.apply(s,r),s=r=null,clearTimeout(i),i=null)},n}const f=[!0,!0,!0,!0];class C{constructor(){this.speed=1,this.ticks=0,this.cyclesTotal=0,this.cyclesTotalBase=0,this.cyclesTotalCurrent=0,this.cyclesTotalRoundoff=0,this.baseCyclesPerIteration=0,this.totalLinesPassed=0,this.stopped=!1,this.calculateTimings()}calculateTimings(){this.clocksPerSecond=4194304*this.speed,this.baseCyclesPerIteration=this.clocksPerSecond/1e3*8,this.cyclesTotalRoundoff=this.baseCyclesPerIteration%4,this.cyclesTotalBase=this.cyclesTotal=this.baseCyclesPerIteration-this.cyclesTotalRoundoff|0,this.cyclesTotalCurrent=0}setSpeed(t){this.speed=t,this.calculateTimings()}}class p{constructor(t){t instanceof Uint8Array?this.data=t:this.data=new Uint8Array(t)}getByte(t){return this.data[t]}getChar(t){return String.fromCharCode(this.getByte(t))}getString(t,e){let i="";for(let r=t;r<=e;r++)i+=this.getChar(r);return i}get length(){return this.data.byteLength}}class B{constructor(t,{canvas:e,context:i,offscreenCanvas:r,offscreenContext:s,width:h,height:a}){if(this.gameboy=t,this.canvas=e,this.context=i,this.offscreenCanvas=r,this.offscreenContext=s,this.gameboy=t,this.offscreenWidth=160,this.offscreenHeight=144,this.offscreenRgbCount=this.offscreenWidth*this.offscreenHeight*3,this.offscreenRgbaCount=this.offscreenWidth*this.offscreenHeight*4,this.width=h||this.offscreenWidth,this.height=a||this.offscreenHeight,"undefined"!=typeof document&&(this.canvas||(this.canvas=document.createElement("canvas")),this.offscreenCanvas||(this.offscreenCanvas=document.createElement("canvas"))),this.canvas&&(this.canvas.height=this.height,this.canvas.width=this.width,this.context||(this.context=this.canvas.getContext("2d"))),this.offscreenCanvas&&(this.offscreenCanvas.height=this.offscreenHeight,this.offscreenCanvas.width=this.offscreenWidth,this.offscreenContext||(this.offscreenContext=this.offscreenCanvas.getContext("2d"))),!this.context)throw new Error("please provide a canvas context in the lcd options");if(!this.offscreenContext)throw new Error("please provide a canvas offscreen context in the lcd options")}init(){this.offscreenContext.msImageSmoothingEnabled=!1,this.offscreenContext.mozImageSmoothingEnabled=!1,this.offscreenContext.webkitImageSmoothingEnabled=!1,this.offscreenContext.imageSmoothingEnabled=!1,this.context.msImageSmoothingEnabled=!1,this.context.mozImageSmoothingEnabled=!1,this.context.webkitImageSmoothingEnabled=!1,this.context.imageSmoothingEnabled=!1,this.canvasBuffer=this.offscreenContext.createImageData(this.offscreenWidth,this.offscreenHeight),this.swizzledFrame=n(this.offscreenRgbCount,255,"uint8");let t=this.offscreenRgbaCount;for(;t>0;)t-=4,this.canvasBuffer.data[t]=248,this.canvasBuffer.data[t+1]=248,this.canvasBuffer.data[t+2]=248,this.canvasBuffer.data[t+3]=255;this.newFrameAvailable=!0,this.draw()}drawToCanvas(){this.offscreenWidth===this.width&&this.offscreenHeight===this.height?this.context.putImageData(this.canvasBuffer,0,0):(this.offscreenContext.putImageData(this.canvasBuffer,0,0),this.context.drawImage(this.offscreenCanvas,0,0,this.width,this.height))}draw(){if(!this.newFrameAvailable||92160!==this.offscreenRgbaCount)return;const t=this.canvasBuffer.data;let e=0,i=0;for(;i<this.offscreenRgbaCount;)t[i++]=this.swizzledFrame[e++],t[i++]=this.swizzledFrame[e++],t[i++]=this.swizzledFrame[e++],++i;this.drawToCanvas(),this.newFrameAvailable=!1}outputFrameBuffer(){const t=this.gameboy.frameBuffer,e=this.swizzledFrame;let i=0,r=0;for(;r<this.offscreenRgbCount;)e[r++]=t[i]>>16&255,e[r++]=t[i]>>8&255,e[r++]=255&t[i],++i;this.newFrameAvailable=!0}turnOff(){0===this.drewBlank&&(this.clearFrameBuffer(),this.newFrameAvailable=!0),this.drewBlank=2}clearFrameBuffer(){const t=this.swizzledFrame;let e=0;if(this.gameboy.cartridge.useGbcMode||this.colorizedGbPalettes)for(;e<this.offscreenRgbCount;)t[e++]=248;else for(;e<this.offscreenRgbCount;)t[e++]=239,t[e++]=255,t[e++]=222}}const F=40960,S=49151,k=65280,R=65281,M=65282,H=65284,L=65287,w=65360;class T{constructor(t){this.gameboy=t,this.value=255,this.writeMemory=(t,e)=>{const i=48&e,r=0==(16&e),s=15&this.value,h=0==(32&e),a=this.value>>4&15;this.gameboy.memory[t]=i+((h?a:15)&(r?s:15))},this.readMemory=()=>192|this.gameboy.memoryNew.readDirectly(k)}init(){this.gameboy.memory[65280]=15}down(t){this.value&=255^1<<t,!this.gameboy.cartridge||this.gameboy.cartridge.useGbcMode||this.gameboy.usedBootRom&&this.gameboy.usedGbcBootRom||(this.gameboy.interruptRequestedFlags|=16,this.gameboy.remainingClocks=0,this.gameboy.checkIrqMatching()),this.writeMemory(k,this.gameboy.memory[65280]),this.gameboy.cpu.stopped=!1}up(t){this.value|=1<<t,this.writeMemory(k,this.gameboy.memory[65280]),this.gameboy.cpu.stopped=!1}}const A=require("events");class P extends A.EventEmitter{constructor(){super(...arguments),this.map={}}register(t){return this.map[t]=!0,this}getAll(){return Object.keys(this.map)}is(t){return!!this.map[t]}down(t,e){this.emit("Down"+t,e)}change(t,e){this.emit("Change"+t,e)}up(t,e){this.emit("Up"+t,e)}}const v=[4,12,8,8,4,4,8,4,20,8,8,8,4,4,8,4,4,12,8,8,4,4,8,4,12,8,8,8,4,4,8,4,8,12,8,8,4,4,8,4,8,8,8,8,4,4,8,4,8,12,8,8,12,12,12,4,8,8,8,8,4,4,8,4,4,4,4,4,4,4,8,4,4,4,4,4,4,4,8,4,4,4,4,4,4,4,8,4,4,4,4,4,4,4,8,4,4,4,4,4,4,4,8,4,4,4,4,4,4,4,8,4,8,8,8,8,8,8,4,8,4,4,4,4,4,4,8,4,4,4,4,4,4,4,8,4,4,4,4,4,4,4,8,4,4,4,4,4,4,4,8,4,4,4,4,4,4,4,8,4,4,4,4,4,4,4,8,4,4,4,4,4,4,4,8,4,4,4,4,4,4,4,8,4,4,4,4,4,4,4,8,4,8,12,12,16,12,16,8,16,8,16,12,0,12,24,8,16,8,12,12,4,12,16,8,16,8,16,12,4,12,4,8,16,12,12,8,4,4,16,8,16,16,4,16,4,4,4,8,16,12,12,8,4,4,16,8,16,12,8,16,4,0,4,8,16];class W{constructor(t,e=new Uint8Array(65536)){this.gameboy=t,this.data=e,this.readers=[],this.highReaders=[],this.writers=[],this.highWriters=[],this.writeIllegal=(t,e)=>{},this.readBad=t=>255,this.readDirectly=t=>this.data[t]}read(t){const e=this.readers[t];if(!e)throw new Error("no_reader");return e(t)}readHigh(t){t&=255;const e=this.highReaders[t];if(!e)throw new Error("no_high_reader");return e(65280|t)}hasReader(t){return!!this.readers[t]}hasHighReader(t){return t&=255,!!this.highReaders[t]}setReaders(t,e,i){for(let r=t;r<=e;r++)this.setReader(r,i)}setReader(t,e){this.readers[t]=e}setHighReaders(t,e,i){for(let r=t;r<=e;r++)this.setHighReader(r,i)}setHighReader(t,e){t&=255,this.highReaders[t]=e}write(t,e){const i=this.writers[t];if(!i)throw new Error("no_writer");return i(t,e)}writeHigh(t,e){t&=255;const i=this.highWriters[t];if(!i)throw new Error("no_high_writer");return i(65280|t,e)}hasWriter(t){return!!this.writers[t]}hasHighWriter(t){return t&=255,!!this.highWriters[t]}setWriters(t,e,i){for(let r=t;r<=e;r++)this.setWriter(r,i)}setWriter(t,e){this.writers[t]=e}setHighWriter(t,e){t&=255,this.highWriters[t]=e}init(){this.setReaders(0,16383,(t=>this.data[t])),this.setReaders(16384,32767,(t=>this.gameboy.cartridge.rom.getByte((this.gameboy.cartridge?.mbc?.currentRomBank||0)+t))),this.setReaders(32768,38911,this.gameboy.cartridge.useGbcMode?this.gameboy.readGbcVideoRam:this.gameboy.readVideoRam),this.setReaders(F,S,this.gameboy.cartridge.useGbcMode?this.gameboy.readGbcCharacterVideoRam:this.gameboy.readCharacterVideoRam),0===this.gameboy.cartridge?.mbc?.ramSize?this.setReaders(F,S,this.readBad):(this.gameboy.cartridge.hasMbc7||this.gameboy.cartridge.hasMbc3,this.setReaders(F,S,this.gameboy.cartridge.mbc?.readRam||this.readBad)),this.setReaders(49152,53247,this.readDirectly),this.gameboy.cartridge?.useGbcMode?this.setReaders(53248,57343,this.gameboy.memoryReadGBCMemory):this.setReaders(53248,57343,this.readDirectly),this.setReaders(57344,61439,this.gameboy.readEchoRam),this.gameboy.cartridge?.useGbcMode?this.setReaders(61440,65023,this.gameboy.readGbcEchoRam):this.setReaders(61440,65023,this.gameboy.readEchoRam),this.setReaders(65024,65183,this.gameboy.memoryReadOAM),this.gameboy.cartridge?.useGbcMode&&this.setReaders(65184,65279,this.readDirectly),this.setWriter(k,this.gameboy.joypad.writeMemory),this.setHighWriter(k,this.gameboy.joypad.writeMemory),this.setReader(k,this.gameboy.joypad.readMemory),this.setHighReader(k,this.gameboy.joypad.readMemory);const t=()=>this.readDirectly(M)<128?this.readDirectly(R):255;this.setReader(R,t),this.setHighReader(R,t);const e=this.gameboy.cartridge.useGbcMode?()=>(this.gameboy.serialTimer<=0?124:252)|this.readDirectly(M):()=>(this.gameboy.serialTimer<=0?126:254)|this.readDirectly(M);this.setReader(M,e),this.setHighReader(M,e),this.setReader(65283,this.readBad),this.setHighReader(65283,this.readBad);const i=()=>(this.gameboy.memory[65284]=this.readDirectly(H)+(this.gameboy.DIVTicks>>8)&255,this.gameboy.DIVTicks&=255,this.readDirectly(H));this.setReader(H,i),this.setHighReader(H,i),this.setReader(65285,this.readDirectly),this.setHighReader(65285,this.gameboy.memoryHighReadNormal),this.setReader(65286,this.readDirectly),this.setHighReader(65286,this.gameboy.memoryHighReadNormal);const r=()=>248|this.readDirectly(L);this.setReader(L,r),this.setHighReader(L,r),this.setReaders(65288,65294,this.readBad),this.setHighReaders(65288,65294,this.readBad);const s=()=>224|this.gameboy.interruptRequestedFlags;this.setReader(65295,s),this.setHighReader(65295,s),this.memoryReadJumpCompile(),this.memoryWriteJumpCompile()}updateIoRegisters(){if(this.gameboy.isBootingRom){if(this.enableBootRomControl(),this.gameboy.cartridge.useGbcMode){const t=(t,e)=>{e&=1,this.gameboy.isBootingRom&&this.gameboy.cartridge.setGbcMode(e),this.data[65388]=e};this.setWriter(65388,t),this.setHighWriter(65388,t)}}else this.disableBootRomControl()}enableBootRomControl(){const t=(t,e)=>{console.log("Bootstrap process has ended"),this.gameboy.isBootingRom=!1,this.gameboy.disableBootRom(),this.data[65360]=e};this.setWriter(w,t),this.setHighWriter(w,t)}disableBootRomControl(){this.setWriter(w,this.writeIllegal),this.setHighWriter(w,this.writeIllegal)}memoryReadJumpCompile(){for(let t=0;t<=65535;t++)if(t>=65280)switch(t){case 65296:this.gameboy.highMemoryReader[16]=this.gameboy.memoryReader[65296]=t=>128|this.gameboy.memory[65296];break;case 65297:this.gameboy.highMemoryReader[17]=this.gameboy.memoryReader[65297]=t=>63|this.gameboy.memory[65297];break;case 65298:this.gameboy.highMemoryReader[18]=this.gameboy.memoryHighReadNormal,this.gameboy.memoryReader[65298]=this.readDirectly;break;case 65299:this.gameboy.highMemoryReader[19]=this.gameboy.memoryReader[65299]=this.readBad;break;case 65300:this.gameboy.highMemoryReader[20]=this.gameboy.memoryReader[65300]=t=>191|this.gameboy.memory[65300];break;case 65301:this.gameboy.highMemoryReader[21]=this.readBad,this.gameboy.memoryReader[65301]=this.readBad;break;case 65302:this.gameboy.highMemoryReader[22]=this.gameboy.memoryReader[65302]=t=>63|this.gameboy.memory[65302];break;case 65303:this.gameboy.highMemoryReader[23]=this.gameboy.memoryHighReadNormal,this.gameboy.memoryReader[65303]=this.readDirectly;break;case 65304:this.gameboy.highMemoryReader[24]=this.gameboy.memoryReader[65304]=this.readBad;break;case 65305:this.gameboy.highMemoryReader[25]=this.gameboy.memoryReader[65305]=t=>191|this.gameboy.memory[65305];break;case 65306:this.gameboy.highMemoryReader[26]=this.gameboy.memoryReader[65306]=t=>127|this.gameboy.memory[65306];break;case 65307:this.gameboy.highMemoryReader[27]=this.gameboy.memoryReader[65307]=this.readBad;break;case 65308:this.gameboy.highMemoryReader[28]=this.gameboy.memoryReader[65308]=t=>159|this.gameboy.memory[65308];break;case 65309:this.gameboy.highMemoryReader[29]=this.gameboy.memoryReader[65309]=this.readBad;break;case 65310:this.gameboy.highMemoryReader[30]=this.gameboy.memoryReader[65310]=t=>191|this.gameboy.memory[65310];break;case 65311:case 65312:this.gameboy.highMemoryReader[255&t]=this.gameboy.memoryReader[t]=this.readBad;break;case 65313:case 65314:this.gameboy.highMemoryReader[255&t]=this.gameboy.memoryHighReadNormal,this.gameboy.memoryReader[t]=this.readDirectly;break;case 65315:this.gameboy.highMemoryReader[35]=this.gameboy.memoryReader[65315]=t=>191|this.gameboy.memory[65315];break;case 65316:case 65317:this.gameboy.highMemoryReader[255&t]=this.gameboy.memoryHighReadNormal,this.gameboy.memoryReader[t]=this.readDirectly;break;case 65318:this.gameboy.highMemoryReader[38]=this.gameboy.memoryReader[65318]=t=>(this.gameboy.audioController.run(),112|this.gameboy.memory[65318]);break;case 65319:case 65320:case 65321:case 65322:case 65323:case 65324:case 65325:case 65326:case 65327:this.gameboy.highMemoryReader[255&t]=this.gameboy.memoryReader[t]=this.readBad;break;case 65328:case 65329:case 65330:case 65331:case 65332:case 65333:case 65334:case 65335:case 65336:case 65337:case 65338:case 65339:case 65340:case 65341:case 65342:case 65343:this.gameboy.memoryReader[t]=t=>this.gameboy.audioController.channel3CanPlay?this.gameboy.memory[65280|this.gameboy.audioController.channel3LastSampleLookup>>1]:this.gameboy.memory[t],this.gameboy.highMemoryReader[255&t]=t=>this.gameboy.audioController.channel3CanPlay?this.gameboy.memory[65280|this.gameboy.audioController.channel3LastSampleLookup>>1]:this.gameboy.memory[65280|t];break;case 65344:this.gameboy.highMemoryReader[64]=this.gameboy.memoryHighReadNormal,this.gameboy.memoryReader[65344]=this.readDirectly;break;case 65345:this.gameboy.highMemoryReader[65]=this.gameboy.memoryReader[65345]=t=>128|this.gameboy.memory[65345]|this.gameboy.modeSTAT;break;case 65346:this.gameboy.highMemoryReader[66]=this.gameboy.memoryReader[65346]=t=>this.gameboy.backgroundY;break;case 65347:this.gameboy.highMemoryReader[67]=this.gameboy.memoryReader[65347]=t=>this.gameboy.backgroundX;break;case 65348:this.gameboy.highMemoryReader[68]=this.gameboy.memoryReader[65348]=t=>this.gameboy.gpu.lcdEnabled?this.gameboy.memory[65348]:0;break;case 65349:case 65350:case 65351:case 65352:case 65353:this.gameboy.highMemoryReader[255&t]=this.gameboy.memoryHighReadNormal,this.gameboy.memoryReader[t]=this.readDirectly;break;case 65354:this.gameboy.highMemoryReader[74]=this.gameboy.memoryReader[65354]=t=>this.gameboy.windowY;break;case 65355:this.gameboy.highMemoryReader[75]=this.gameboy.memoryHighReadNormal,this.gameboy.memoryReader[65355]=this.readDirectly;break;case 65356:this.gameboy.highMemoryReader[76]=this.gameboy.memoryReader[65356]=this.readBad;break;case 65357:this.gameboy.highMemoryReader[77]=this.gameboy.memoryHighReadNormal,this.gameboy.memoryReader[65357]=this.readDirectly;break;case 65358:this.gameboy.highMemoryReader[78]=this.gameboy.memoryReader[65358]=this.readBad;break;case 65359:this.gameboy.highMemoryReader[79]=this.gameboy.memoryReader[65359]=t=>this.gameboy.currentVideoRamBank;break;case w:case 65361:case 65362:case 65363:case 65364:this.gameboy.highMemoryReader[255&t]=this.gameboy.memoryHighReadNormal,this.gameboy.memoryReader[t]=this.readDirectly;break;case 65365:this.gameboy.cartridge.useGbcMode?this.gameboy.highMemoryReader[85]=this.gameboy.memoryReader[65365]=t=>(!this.gameboy.gpu.lcdEnabled&&this.gameboy.hdmaRunning&&(this.gameboy.writeDirectlyToMemory(1+(127&this.gameboy.memory[65365])),this.gameboy.memory[65365]=255,this.gameboy.hdmaRunning=!1),this.gameboy.memory[65365]):(this.gameboy.memoryReader[65365]=this.readDirectly,this.gameboy.highMemoryReader[85]=this.gameboy.memoryHighReadNormal);break;case 65366:this.gameboy.cartridge.useGbcMode?this.gameboy.highMemoryReader[86]=this.gameboy.memoryReader[65366]=t=>60|(this.gameboy.memory[65366]>=192?2|193&this.gameboy.memory[65366]:195&this.gameboy.memory[65366]):(this.gameboy.memoryReader[65366]=this.readDirectly,this.gameboy.highMemoryReader[86]=this.gameboy.memoryHighReadNormal);break;case 65367:case 65368:case 65369:case 65370:case 65371:case 65372:case 65373:case 65374:case 65375:case 65376:case 65377:case 65378:case 65379:case 65380:case 65381:case 65382:case 65383:this.gameboy.highMemoryReader[255&t]=this.gameboy.memoryReader[t]=this.readBad;break;case 65384:case 65385:case 65386:case 65387:this.gameboy.highMemoryReader[255&t]=this.gameboy.memoryHighReadNormal,this.gameboy.memoryReader[t]=this.readDirectly;break;case 65388:this.gameboy.cartridge.useGbcMode?this.gameboy.highMemoryReader[108]=this.gameboy.memoryReader[65388]=t=>254|this.gameboy.memory[65388]:this.gameboy.highMemoryReader[108]=this.gameboy.memoryReader[65388]=this.readBad;break;case 65389:case 65390:case 65391:this.gameboy.highMemoryReader[255&t]=this.gameboy.memoryReader[t]=this.readBad;break;case 65392:this.gameboy.cartridge.useGbcMode?this.gameboy.highMemoryReader[112]=this.gameboy.memoryReader[65392]=t=>64|this.gameboy.memory[65392]:this.gameboy.highMemoryReader[112]=this.gameboy.memoryReader[65392]=this.readBad;break;case 65393:this.gameboy.highMemoryReader[113]=this.gameboy.memoryReader[65393]=this.readBad;break;case 65394:case 65395:this.gameboy.highMemoryReader[255&t]=this.gameboy.memoryReader[t]=this.readDirectly;break;case 65396:this.gameboy.cartridge.useGbcMode?this.gameboy.highMemoryReader[116]=this.gameboy.memoryReader[65396]=this.readDirectly:this.gameboy.highMemoryReader[116]=this.gameboy.memoryReader[65396]=this.readBad;break;case 65397:this.gameboy.highMemoryReader[117]=this.gameboy.memoryReader[65397]=t=>143|this.gameboy.memory[65397];break;case 65398:this.gameboy.highMemoryReader[118]=this.gameboy.memoryReader[65398]=t=>(this.gameboy.audioController.run(),this.gameboy.audioController.channel2.envelopeVolume<<4|this.gameboy.audioController.channel1.envelopeVolume);break;case 65399:this.gameboy.highMemoryReader[119]=this.gameboy.memoryReader[65399]=t=>(this.gameboy.audioController.run(),this.gameboy.audioController.channel4EnvelopeVolume<<4|this.gameboy.audioController.channel3envelopeVolume);break;case 65400:case 65401:case 65402:case 65403:case 65404:case 65405:case 65406:case 65407:this.gameboy.highMemoryReader[255&t]=this.gameboy.memoryReader[t]=this.readBad;break;case 65535:this.gameboy.highMemoryReader[255]=this.gameboy.memoryReader[65535]=t=>this.gameboy.interruptEnabledFlags;break;default:this.gameboy.memoryReader[t]=this.readDirectly,this.gameboy.highMemoryReader[255&t]=this.gameboy.memoryHighReadNormal}else this.gameboy.memoryReader[t]=this.readBad}memoryWriteJumpCompile(){for(let t=0;t<=65535;t++)t<=32767?this.gameboy.cartridge.hasMbc1?this.gameboy.memoryWriter[t]=t<8192?this.gameboy.cartridge.mbc.toggle:t<16384?this.gameboy.cartridge.mbc1.writeRomBank:t<24576?this.gameboy.cartridge.mbc1.writeRamBank:this.gameboy.cartridge.mbc1.writeType:this.gameboy.cartridge.hasMbc2?this.gameboy.memoryWriter[t]=t<4096?this.gameboy.cartridge.mbc.toggle:t>=8448&&t<8704?this.gameboy.cartridge.mbc2.writeRomBank:this.writeIllegal:this.gameboy.cartridge.hasMbc3?this.gameboy.memoryWriter[t]=t<8192?this.gameboy.cartridge.mbc.toggle:t<16384?this.gameboy.cartridge.mbc3.writeRomBank:t<24576?this.gameboy.cartridge.mbc3.writeRamBank:this.gameboy.cartridge.mbc3.rtc.writeLatch:this.gameboy.cartridge.hasMbc5||this.gameboy.cartridge.hasMbc7||this.gameboy.cartridge.hasRumble?this.gameboy.memoryWriter[t]=t<8192?this.gameboy.cartridge.mbc.toggle:t<12288?this.gameboy.cartridge.mbc5.writRomBank:t<16384?this.gameboy.cartridge.mbc5.writeHighRomBank:t<24576?this.gameboy.cartridge.hasRumble?this.gameboy.cartridge.rumble.writeRamBank:this.gameboy.cartridge.mbc5.writeRamBank:this.writeIllegal:this.gameboy.cartridge.hasHuc3?this.gameboy.memoryWriter[t]=t<8192?this.gameboy.cartridge.mbc.toggle:t<16384?this.gameboy.cartridge.mbc3.writeRomBank:t<24576?this.gameboy.cartridge.mbc3.writeHuc3RamBank:this.writeIllegal:this.gameboy.memoryWriter[t]=this.writeIllegal:t<=36863?this.gameboy.memoryWriter[t]=this.gameboy.cartridge.useGbcMode?this.gameboy.VRAMGBCDATAWrite:this.gameboy.VRAMGBDATAWrite:t<38912?this.gameboy.memoryWriter[t]=this.gameboy.cartridge.useGbcMode?this.gameboy.VRAMGBCDATAWrite:this.gameboy.VRAMGBDATAUpperWrite:t<40960?this.gameboy.memoryWriter[t]=this.gameboy.cartridge.useGbcMode?this.gameboy.VRAMGBCCHRMAPWrite:this.gameboy.VRAMGBCHRMAPWrite:t<49152?this.gameboy.cartridge?.mbc?.ramSize>0?this.gameboy.memoryWriter[t]=this.gameboy.cartridge.mbc.writeRam:this.gameboy.memoryWriter[t]=this.writeIllegal:t<57344?this.gameboy.cartridge.useGbcMode&&t>=53248?this.gameboy.memoryWriter[t]=this.gameboy.memoryWriteGBCRAM:this.gameboy.memoryWriter[t]=this.gameboy.memoryWriteNormal:t<65024?this.gameboy.cartridge.useGbcMode&&t>=61440?this.gameboy.memoryWriter[t]=this.gameboy.memoryWriteECHOGBCRAM:this.gameboy.memoryWriter[t]=this.gameboy.memoryWriteECHONormal:t<=65184?this.gameboy.memoryWriter[t]=this.gameboy.memoryWriteOAMRAM:t<65280?this.gameboy.cartridge.useGbcMode?this.gameboy.memoryWriter[t]=this.gameboy.memoryWriteNormal:this.gameboy.memoryWriter[t]=this.writeIllegal:(this.gameboy.memoryWriter[t]=this.gameboy.memoryWriteNormal,this.gameboy.highMemoryWriter[255&t]=this.gameboy.memoryHighWriteNormal);this.registerIOMemoryWriters()}registerIOMemoryWriters(){this.gameboy.highMemoryWriter[1]=this.gameboy.memoryWriter[65281]=(t,e)=>{this.gameboy.memory[65282]<128&&(this.gameboy.memory[65281]=e)},this.gameboy.highMemoryWriter[2]=this.gameboy.memoryHighWriteNormal,this.gameboy.memoryWriter[65282]=this.gameboy.memoryWriteNormal,this.gameboy.highMemoryWriter[3]=this.gameboy.memoryWriter[65283]=this.writeIllegal,this.gameboy.highMemoryWriter[4]=this.gameboy.memoryWriter[65284]=(t,e)=>{this.gameboy.DIVTicks&=255,this.gameboy.memory[65284]=0},this.gameboy.highMemoryWriter[5]=this.gameboy.memoryWriter[65285]=(t,e)=>{this.gameboy.memory[65285]=e},this.gameboy.highMemoryWriter[6]=this.gameboy.memoryWriter[65286]=(t,e)=>{this.gameboy.memory[65286]=e},this.gameboy.highMemoryWriter[7]=this.gameboy.memoryWriter[65287]=(t,e)=>{this.gameboy.memory[65287]=7&e,this.gameboy.TIMAEnabled=4==(4&e),this.gameboy.TACClocker=Math.pow(4,0!=(3&e)?3&e:4)<<2},this.gameboy.highMemoryWriter[8]=this.gameboy.memoryWriter[65288]=this.writeIllegal,this.gameboy.highMemoryWriter[9]=this.gameboy.memoryWriter[65289]=this.writeIllegal,this.gameboy.highMemoryWriter[10]=this.gameboy.memoryWriter[65290]=this.writeIllegal,this.gameboy.highMemoryWriter[11]=this.gameboy.memoryWriter[65291]=this.writeIllegal,this.gameboy.highMemoryWriter[12]=this.gameboy.memoryWriter[65292]=this.writeIllegal,this.gameboy.highMemoryWriter[13]=this.gameboy.memoryWriter[65293]=this.writeIllegal,this.gameboy.highMemoryWriter[14]=this.gameboy.memoryWriter[65294]=this.writeIllegal,this.gameboy.highMemoryWriter[15]=this.gameboy.memoryWriter[65295]=(t,e)=>{this.gameboy.interruptRequestedFlags=e,this.gameboy.checkIrqMatching()},this.gameboy.audioController.registerMemoryWriters(),this.gameboy.highMemoryWriter[39]=this.gameboy.memoryWriter[65319]=this.writeIllegal,this.gameboy.highMemoryWriter[40]=this.gameboy.memoryWriter[65320]=this.writeIllegal,this.gameboy.highMemoryWriter[41]=this.gameboy.memoryWriter[65321]=this.writeIllegal,this.gameboy.highMemoryWriter[42]=this.gameboy.memoryWriter[65322]=this.writeIllegal,this.gameboy.highMemoryWriter[43]=this.gameboy.memoryWriter[65323]=this.writeIllegal,this.gameboy.highMemoryWriter[44]=this.gameboy.memoryWriter[65324]=this.writeIllegal,this.gameboy.highMemoryWriter[45]=this.gameboy.memoryWriter[65325]=this.writeIllegal,this.gameboy.highMemoryWriter[46]=this.gameboy.memoryWriter[65326]=this.writeIllegal,this.gameboy.highMemoryWriter[47]=this.gameboy.memoryWriter[65327]=this.writeIllegal,this.gameboy.audioController.registerWaveformMemoryWriters(),this.gameboy.highMemoryWriter[66]=this.gameboy.memoryWriter[65346]=(t,e)=>{this.gameboy.backgroundY!==e&&(this.gameboy.midScanlineJIT(),this.gameboy.backgroundY=e)},this.gameboy.highMemoryWriter[67]=this.gameboy.memoryWriter[65347]=(t,e)=>{this.gameboy.backgroundX!==e&&(this.gameboy.midScanlineJIT(),this.gameboy.backgroundX=e)},this.gameboy.highMemoryWriter[68]=this.gameboy.memoryWriter[65348]=(t,e)=>{this.gameboy.gpu.lcdEnabled&&(this.gameboy.modeSTAT=2,this.gameboy.midScanlineOffset=-1,this.gameboy.cpu.totalLinesPassed=this.gameboy.currentX=this.gameboy.queuedScanlines=this.gameboy.lastUnrenderedLine=this.gameboy.LCDTicks=this.gameboy.STATTracker=this.gameboy.actualScanline=this.gameboy.memory[65348]=0)},this.gameboy.highMemoryWriter[69]=this.gameboy.memoryWriter[65349]=(t,e)=>{this.gameboy.memory[65349]!==e&&(this.gameboy.memory[65349]=e,this.gameboy.gpu.lcdEnabled&&this.gameboy.matchLYC())},this.gameboy.highMemoryWriter[74]=this.gameboy.memoryWriter[65354]=(t,e)=>{this.gameboy.windowY!==e&&(this.gameboy.midScanlineJIT(),this.gameboy.windowY=e)},this.gameboy.highMemoryWriter[75]=this.gameboy.memoryWriter[65355]=(t,e)=>{this.gameboy.memory[65355]!==e&&(this.gameboy.midScanlineJIT(),this.gameboy.memory[65355]=e,this.gameboy.windowX=e-7)},this.gameboy.highMemoryWriter[114]=this.gameboy.memoryWriter[65394]=(t,e)=>{this.gameboy.memory[65394]=e},this.gameboy.highMemoryWriter[115]=this.gameboy.memoryWriter[65395]=(t,e)=>{this.gameboy.memory[65395]=e},this.gameboy.highMemoryWriter[117]=this.gameboy.memoryWriter[65397]=(t,e)=>{this.gameboy.memory[65397]=e},this.gameboy.highMemoryWriter[118]=this.gameboy.memoryWriter[65398]=this.writeIllegal,this.gameboy.highMemoryWriter[119]=this.gameboy.memoryWriter[65399]=this.writeIllegal,this.gameboy.highMemoryWriter[255]=this.gameboy.memoryWriter[65535]=(t,e)=>{this.gameboy.interruptEnabledFlags=e,this.gameboy.checkIrqMatching()},this.recompileModelSpecificIOWriteHandling(),this.updateIoRegisters()}recompileModelSpecificIOWriteHandling(){this.gameboy.cartridge.useGbcMode?(this.gameboy.highMemoryWriter[2]=this.gameboy.memoryWriter[65282]=(t,e)=>{1==(1&e)?(this.gameboy.memory[65282]=127&e,this.gameboy.serialTimer=0==(2&e)?4096:128,this.gameboy.serialShiftTimer=this.gameboy.serialShiftTimerAllocated=0==(2&e)?512:16):(this.gameboy.memory[65282]=e,this.gameboy.serialShiftTimer=this.gameboy.serialShiftTimerAllocated=this.gameboy.serialTimer=0)},this.gameboy.highMemoryWriter[64]=this.gameboy.memoryWriter[65344]=(t,e)=>{if(this.gameboy.memory[65344]!==e){this.gameboy.midScanlineJIT();const t=e>127;t!==this.gameboy.gpu.lcdEnabled&&(this.gameboy.gpu.lcdEnabled=t,this.gameboy.memory[65345]&=120,this.gameboy.midScanlineOffset=-1,this.gameboy.cpu.totalLinesPassed=this.gameboy.currentX=this.gameboy.queuedScanlines=this.gameboy.lastUnrenderedLine=this.gameboy.STATTracker=this.gameboy.LCDTicks=this.gameboy.actualScanline=this.gameboy.memory[65348]=0,this.gameboy.gpu.lcdEnabled?(this.gameboy.modeSTAT=2,this.gameboy.matchLYC(),this.gameboy.gpu.enableLCD()):(this.gameboy.modeSTAT=0,this.gameboy.gpu.disableLCD(),this.gameboy.lcdDevice.turnOff()),this.gameboy.interruptRequestedFlags&=253),this.gameboy.gfxWindowCHRBankPosition=64==(64&e)?1024:0,this.gameboy.gfxWindowDisplay=32==(32&e),this.gameboy.gfxBackgroundBankOffset=16==(16&e)?0:128,this.gameboy.gfxBackgroundCHRBankPosition=8==(8&e)?1024:0,this.gameboy.gfxSpriteNormalHeight=0==(4&e),this.gameboy.gfxSpriteShow=2==(2&e),this.gameboy.hasBackgroundPriority=1==(1&e),this.gameboy.gpu.initRenderer(),this.gameboy.memory[65344]=e}},this.gameboy.highMemoryWriter[65]=this.gameboy.memoryWriter[65345]=(t,e)=>{this.gameboy.LYCMatchTriggerSTAT=64==(64&e),this.gameboy.mode2TriggerSTAT=32==(32&e),this.gameboy.mode1TriggerSTAT=16==(16&e),this.gameboy.mode0TriggerSTAT=8==(8&e),this.gameboy.memory[65345]=120&e},this.gameboy.highMemoryWriter[70]=this.gameboy.memoryWriter[65350]=(t,e)=>{if(this.gameboy.memory[65350]=e,e<224){e<<=8,t=65024;const i=this.gameboy.modeSTAT;this.gameboy.modeSTAT=0;do{const r=this.readDirectly(e++);if(r!==this.gameboy.memory[t]){this.gameboy.modeSTAT=i,this.gameboy.graphicsJIT(),this.gameboy.modeSTAT=0,this.gameboy.memory[t++]=r;break}}while(++t<65184);if(t<65184)do{this.gameboy.memory[t++]=this.readDirectly(e++),this.gameboy.memory[t++]=this.readDirectly(e++),this.gameboy.memory[t++]=this.readDirectly(e++),this.gameboy.memory[t++]=this.readDirectly(e++)}while(t<65184);this.gameboy.modeSTAT=i}},this.gameboy.highMemoryWriter[77]=this.gameboy.memoryWriter[65357]=(t,e)=>{this.gameboy.memory[65357]=127&e|128&this.gameboy.memory[65357]},this.gameboy.highMemoryWriter[79]=this.gameboy.memoryWriter[65359]=(t,e)=>{this.gameboy.currentVideoRamBank=1&e,this.gameboy.currentVideoRamBank>0?this.gameboy.BGCHRCurrentBank=this.gameboy.BGCHRBank2:this.gameboy.BGCHRCurrentBank=this.gameboy.BGCHRBank1},this.gameboy.highMemoryWriter[81]=this.gameboy.memoryWriter[65361]=(t,e)=>{this.gameboy.hdmaRunning||(this.gameboy.memory[65361]=e)},this.gameboy.highMemoryWriter[82]=this.gameboy.memoryWriter[65362]=(t,e)=>{this.gameboy.hdmaRunning||(this.gameboy.memory[65362]=240&e)},this.gameboy.highMemoryWriter[83]=this.gameboy.memoryWriter[65363]=(t,e)=>{this.gameboy.hdmaRunning||(this.gameboy.memory[65363]=31&e)},this.gameboy.highMemoryWriter[84]=this.gameboy.memoryWriter[65364]=(t,e)=>{this.gameboy.hdmaRunning||(this.gameboy.memory[65364]=240&e)},this.gameboy.highMemoryWriter[85]=this.gameboy.memoryWriter[65365]=(t,e)=>{this.gameboy.hdmaRunning?0==(128&e)?(this.gameboy.hdmaRunning=!1,this.gameboy.memory[65365]|=128):this.gameboy.memory[65365]=127&e:0==(128&e)?(this.gameboy.writeDirectlyToMemory(1+(127&e)),this.gameboy.memory[65365]=255):(this.gameboy.hdmaRunning=!0,this.gameboy.memory[65365]=127&e)},this.gameboy.highMemoryWriter[104]=this.gameboy.memoryWriter[65384]=(t,e)=>{this.gameboy.memory[65385]=this.gameboy.gbcBGRawPalette[63&e],this.gameboy.memory[65384]=e},this.gameboy.highMemoryWriter[105]=this.gameboy.memoryWriter[65385]=(t,e)=>{if(this.gameboy.updateGBCBGPalette(63&this.gameboy.memory[65384],e),this.gameboy.memory[65384]>127){var i=this.gameboy.memory[65384]+1&63;this.gameboy.memory[65384]=128|i,this.gameboy.memory[65385]=this.gameboy.gbcBGRawPalette[i]}else this.gameboy.memory[65385]=e},this.gameboy.highMemoryWriter[106]=this.gameboy.memoryWriter[65386]=(t,e)=>{this.gameboy.memory[65387]=this.gameboy.gbcOBJRawPalette[63&e],this.gameboy.memory[65386]=e},this.gameboy.highMemoryWriter[107]=this.gameboy.memoryWriter[65387]=(t,e)=>{if(this.gameboy.updateGBCOBJPalette(63&this.gameboy.memory[65386],e),this.gameboy.memory[65386]>127){var i=this.gameboy.memory[65386]+1&63;this.gameboy.memory[65386]=128|i,this.gameboy.memory[65387]=this.gameboy.gbcOBJRawPalette[i]}else this.gameboy.memory[65387]=e},this.gameboy.highMemoryWriter[112]=this.gameboy.memoryWriter[65392]=(t,e)=>{var i=this.gameboy.memory[65361]<<8|this.gameboy.memory[65362];(!this.gameboy.hdmaRunning||i<53248||i>=57344)&&(this.gameboy.gbcRamBank=Math.max(7&e,1),this.gameboy.gbcRamBankPosition=(this.gameboy.gbcRamBank-1<<12)-53248,this.gameboy.gbcEchoRamBankPosition=this.gameboy.gbcRamBankPosition-8192),this.gameboy.memory[65392]=e},this.gameboy.highMemoryWriter[116]=this.gameboy.memoryWriter[65396]=(t,e)=>{this.gameboy.memory[65396]=e}):(this.gameboy.highMemoryWriter[2]=this.gameboy.memoryWriter[65282]=(t,e)=>{1==(1&e)?(this.gameboy.memory[65282]=127&e,this.gameboy.serialTimer=4096,this.gameboy.serialShiftTimer=this.gameboy.serialShiftTimerAllocated=512):(this.gameboy.memory[65282]=e,this.gameboy.serialShiftTimer=this.gameboy.serialShiftTimerAllocated=this.gameboy.serialTimer=0)},this.gameboy.highMemoryWriter[64]=this.gameboy.memoryWriter[65344]=(t,e)=>{if(this.gameboy.memory[65344]!==e){this.gameboy.midScanlineJIT();const t=e>127;t!==this.gameboy.gpu.lcdEnabled&&(this.gameboy.gpu.lcdEnabled=t,this.gameboy.memory[65345]&=120,this.gameboy.midScanlineOffset=-1,this.gameboy.cpu.totalLinesPassed=this.gameboy.currentX=this.gameboy.queuedScanlines=this.gameboy.lastUnrenderedLine=this.gameboy.STATTracker=this.gameboy.LCDTicks=this.gameboy.actualScanline=this.gameboy.memory[65348]=0,this.gameboy.gpu.lcdEnabled?(this.gameboy.modeSTAT=2,this.gameboy.matchLYC(),this.gameboy.gpu.enableLCD()):(this.gameboy.modeSTAT=0,this.gameboy.gpu.disableLCD(),this.gameboy.lcdDevice.turnOff()),this.gameboy.interruptRequestedFlags&=253),this.gameboy.gfxWindowCHRBankPosition=64==(64&e)?1024:0,this.gameboy.gfxWindowDisplay=32==(32&e),this.gameboy.gfxBackgroundBankOffset=16==(16&e)?0:128,this.gameboy.gfxBackgroundCHRBankPosition=8==(8&e)?1024:0,this.gameboy.gfxSpriteNormalHeight=0==(4&e),this.gameboy.gfxSpriteShow=2==(2&e),this.gameboy.backgroundEnabled=1==(1&e),this.gameboy.memory[65344]=e}},this.gameboy.highMemoryWriter[65]=this.gameboy.memoryWriter[65345]=(t,e)=>{this.gameboy.LYCMatchTriggerSTAT=64==(64&e),this.gameboy.mode2TriggerSTAT=32==(32&e),this.gameboy.mode1TriggerSTAT=16==(16&e),this.gameboy.mode0TriggerSTAT=8==(8&e),this.gameboy.memory[65345]=120&e,(!this.gameboy.usedBootRom||!this.gameboy.usedGbcBootRom)&&this.gameboy.gpu.lcdEnabled&&this.gameboy.modeSTAT<2&&(this.gameboy.interruptRequestedFlags|=2,this.gameboy.checkIrqMatching())},this.gameboy.highMemoryWriter[70]=this.gameboy.memoryWriter[65350]=(t,e)=>{if(this.gameboy.memory[65350]=e,e>127&&e<224){e<<=8,t=65024;var i=this.gameboy.modeSTAT;this.gameboy.modeSTAT=0;var r=0;do{if((r=this.readDirectly(e++))!==this.gameboy.memory[t]){this.gameboy.modeSTAT=i,this.gameboy.graphicsJIT(),this.gameboy.modeSTAT=0,this.gameboy.memory[t++]=r;break}}while(++t<65184);if(t<65184)do{this.gameboy.memory[t++]=this.readDirectly(e++),this.gameboy.memory[t++]=this.readDirectly(e++),this.gameboy.memory[t++]=this.readDirectly(e++),this.gameboy.memory[t++]=this.readDirectly(e++)}while(t<65184);this.gameboy.modeSTAT=i}},this.gameboy.highMemoryWriter[71]=this.gameboy.memoryWriter[65351]=(t,e)=>{this.gameboy.memory[65351]!==e&&(this.gameboy.midScanlineJIT(),this.gameboy.updateGBBGPalette(e),this.gameboy.memory[65351]=e)},this.gameboy.highMemoryWriter[72]=this.gameboy.memoryWriter[65352]=(t,e)=>{this.gameboy.memory[65352]!==e&&(this.gameboy.midScanlineJIT(),this.gameboy.updateGBOBJPalette(0,e),this.gameboy.memory[65352]=e)},this.gameboy.highMemoryWriter[73]=this.gameboy.memoryWriter[65353]=(t,e)=>{this.gameboy.memory[65353]!==e&&(this.gameboy.midScanlineJIT(),this.gameboy.updateGBOBJPalette(4,e),this.gameboy.memory[65353]=e)},this.gameboy.highMemoryWriter[77]=this.gameboy.memoryWriter[65357]=(t,e)=>{this.gameboy.memory[65357]=e},this.gameboy.highMemoryWriter[79]=this.gameboy.memoryWriter[65359]=this.writeIllegal,this.gameboy.highMemoryWriter[85]=this.gameboy.memoryWriter[65365]=this.writeIllegal,this.gameboy.highMemoryWriter[104]=this.gameboy.memoryWriter[65384]=this.writeIllegal,this.gameboy.highMemoryWriter[105]=this.gameboy.memoryWriter[65385]=this.writeIllegal,this.gameboy.highMemoryWriter[106]=this.gameboy.memoryWriter[65386]=this.writeIllegal,this.gameboy.highMemoryWriter[107]=this.gameboy.memoryWriter[65387]=this.writeIllegal,this.gameboy.highMemoryWriter[108]=this.gameboy.memoryWriter[65388]=this.writeIllegal,this.gameboy.highMemoryWriter[112]=this.gameboy.memoryWriter[65392]=this.writeIllegal,this.gameboy.highMemoryWriter[116]=this.gameboy.memoryWriter[65396]=this.writeIllegal)}}const G=[[!1,!1,!1,!1,!1,!1,!1,!0],[!0,!1,!1,!1,!1,!1,!1,!0],[!0,!1,!1,!1,!1,!0,!0,!0],[!1,!0,!0,!0,!0,!0,!0,!1]],E=[!0,1,!0,!1,!0,!0,0,19,0,216,333,65534,256,!1,!0,!1,0,0,[],[],0,[],1,-53248,0,0,0,!1,!1,!1,!1,!1,0,!1,!1,!0,0,128,!1,56,60,0,1024,0,0,0,0,(new Date).getTime(),0,[],!0,8192,512,0,0,!1,0,0,!0,0,!1,0,1,0,!1,0,!1,8192,512,0,0,!1,0,0,!0,0,!1,0,4,0,!0,null,8,0,0,0,0,!1,0,0,!0,32767,!1,8,8,!1,!1,!1,!1,!1,!1,!1,!1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,G[2],0,G[2],!1,!1,!1,!1,8192,0,2048,8,0,0,2048,0,144,0,0,!1,0,0,0,0,0,0,0,0,0,!1,!1,!1,!1,0,-61440,0,0,null,null,null,null,null,null,null,null,null,null,null,null,0,0,0,0,!1,0,0,!1,1,1];class D{constructor(t){this.gameboy=t}init(){this.loadOld(E.slice(0))}get(){const t=this.gameboy;return t.cartridge?g(t.memory.buffer.slice(0),t.videoRam.buffer.slice(0)):null}load(t){this.gameboy}loadOld(t){let e=0;const i=this.gameboy;i.isBootingRom=t[e++],i.registerA=t[e++],i.FZero=t[e++],i.FSubtract=t[e++],i.FHalfCarry=t[e++],i.FCarry=t[e++],i.registerB=t[e++],i.registerC=t[e++],i.registerD=t[e++],i.registerE=t[e++],i.registersHL=t[e++],i.stackPointer=t[e++],i.programCounter=t[e++],i.halt=t[e++],i.IME=t[e++],i.hdmaRunning=t[e++],i.currentInstructionCycleCount=t[e++],i.doubleSpeedShifter=t[e++],i.memory=a(t[e++],"uint8"),i.videoRam=a(t[e++],"uint8"),i.currentVideoRamBank=t[e++],i.gbcMemory=a(t[e++],"uint8"),i.gbcRamBank=t[e++],i.gbcRamBankPosition=t[e++],i.ROMBank1Offset=t[e++],i.cartridge?.mbc?i.cartridge.mbc.currentRomBank=t[e++]:e++,i.modeSTAT=t[e++],i.LYCMatchTriggerSTAT=t[e++],i.mode2TriggerSTAT=t[e++],i.mode1TriggerSTAT=t[e++],i.mode0TriggerSTAT=t[e++],i.gpu.lcdEnabled=t[e++],i.gfxWindowCHRBankPosition=t[e++],i.gfxWindowDisplay=t[e++],i.gfxSpriteShow=t[e++],i.gfxSpriteNormalHeight=t[e++],i.gfxBackgroundCHRBankPosition=t[e++],i.gfxBackgroundBankOffset=t[e++],i.TIMAEnabled=t[e++],i.DIVTicks=t[e++],i.LCDTicks=t[e++],i.timerTicks=t[e++],i.TACClocker=t[e++],i.serialTimer=t[e++],i.serialShiftTimer=t[e++],i.serialShiftTimerAllocated=t[e++],i.IRQEnableDelay=t[e++],i.cartridge?.hasRtc?i.cartridge.mbc3.rtc.lastTime=t[e++]:e++,i.drewBlank=t[e++],i.frameBuffer=a(t[e++],"int32"),i.backgroundEnabled=t[e++],i.audioController.channel1.frequencyTracker=t[e++],i.audioController.channel1.frequencyCounter=t[e++],i.audioController.channel1.totalLength=t[e++],i.audioController.channel1.envelopeVolume=t[e++],i.audioController.channel1.envelopeType=t[e++],i.audioController.channel1.envelopeSweeps=t[e++],i.audioController.channel1.envelopeSweepsLast=t[e++],i.audioController.channel1.consecutive=t[e++],i.audioController.channel1.frequency=t[e++],i.audioController.channel1.sweepFault=t[e++],i.audioController.channel1.shadowFrequency=t[e++],i.audioController.channel1.timeSweep=t[e++],i.audioController.channel1.lastTimeSweep=t[e++],i.audioController.channel1.swept=t[e++],i.audioController.channel1.frequencySweepDivider=t[e++],i.audioController.channel1.decreaseSweep=t[e++],i.audioController.channel2.frequencyTracker=t[e++],i.audioController.channel2.frequencyCounter=t[e++],i.audioController.channel2.totalLength=t[e++],i.audioController.channel2.envelopeVolume=t[e++],i.audioController.channel2.envelopeType=t[e++],i.audioController.channel2.envelopeSweeps=t[e++],i.audioController.channel2.envelopeSweepsLast=t[e++],i.audioController.channel2.consecutive=t[e++],i.audioController.channel2.frequency=t[e++],i.audioController.channel3CanPlay=t[e++],i.audioController.channel3TotalLength=t[e++],i.audioController.channel3PatternType=t[e++],i.audioController.channel3frequency=t[e++],i.audioController.channel3Consecutive=t[e++],i.audioController.channel3PcmData=a(t[e++],"int8"),i.audioController.channel4FrequencyPeriod=t[e++],i.audioController.channel4LastSampleLookup=t[e++],i.audioController.channel4TotalLength=t[e++],i.audioController.channel4EnvelopeVolume=t[e++],i.audioController.channel4CurrentVolume=t[e++],i.audioController.channel4EnvelopeType=t[e++],i.audioController.channel4EnvelopeSweeps=t[e++],i.audioController.channel4EnvelopeSweepsLast=t[e++],i.audioController.channel4Consecutive=t[e++],i.audioController.channel4BitRange=t[e++],i.audioController.enabled=t[e++],i.audioController.cartridgeLeftChannelInputVolume=t[e++],i.audioController.cartridgeRightChannelInputVolume=t[e++],i.audioController.channel1.leftChannelEnabled=t[e++],i.audioController.channel2.leftChannelEnabled=t[e++],i.audioController.leftChannel3=t[e++],i.audioController.leftChannel4=t[e++],i.audioController.channel1.rightChannelEnabled=t[e++],i.audioController.channel2.rightChannelEnabled=t[e++],i.audioController.rightChannel3=t[e++],i.audioController.rightChannel4=t[e++],i.audioController.channel1.currentSampleLeft=t[e++],i.audioController.channel1.currentSampleRight=t[e++],i.audioController.channel2.currentSampleLeft=t[e++],i.audioController.channel2.currentSampleRight=t[e++],i.audioController.channel3CurrentSampleLeft=t[e++],i.audioController.channel3CurrentSampleRight=t[e++],i.audioController.channel4CurrentSampleLeft=t[e++],i.audioController.channel4CurrentSampleRight=t[e++],i.audioController.channel1.currentSampleLeftSecondary=t[e++],i.audioController.channel1.currentSampleRightSecondary=t[e++],i.audioController.channel2.currentSampleLeftSecondary=t[e++],i.audioController.channel2.currentSampleRightSecondary=t[e++],i.audioController.channel3CurrentSampleLeftSecondary=t[e++],i.audioController.channel3CurrentSampleRightSecondary=t[e++],i.audioController.channel4CurrentSampleLeftSecondary=t[e++],i.audioController.channel4CurrentSampleRightSecondary=t[e++],i.audioController.channel1.currentSampleLeftTrimary=t[e++],i.audioController.channel1.currentSampleRightTrimary=t[e++],i.audioController.channel2.currentSampleLeftTrimary=t[e++],i.audioController.channel2.currentSampleRightTrimary=t[e++],i.audioController.mixerOutputCache=t[e++],i.audioController.channel1.dutyTracker=t[e++],i.audioController.channel1.cachedDuty=t[e++],i.audioController.channel2.dutyTracker=t[e++],i.audioController.channel2.cachedDuty=t[e++],i.audioController.channel1.enabled=t[e++],i.audioController.channel2.enabled=t[e++],i.audioController.channel3Enabled=t[e++],i.audioController.channel4Enabled=t[e++],i.audioController.sequencerClocks=t[e++],i.audioController.sequencePosition=t[e++],i.audioController.channel3Counter=t[e++],i.audioController.channel4Counter=t[e++],i.audioController.cachedChannel3Sample=t[e++],i.audioController.cachedChannel4Sample=t[e++],i.audioController.channel3FrequencyPeriod=t[e++],i.audioController.channel3LastSampleLookup=t[e++],i.actualScanline=t[e++],i.lastUnrenderedLine=t[e++],i.queuedScanlines=t[e++],i.cartridge?.hasRtc?(i.cartridge.mbc3.rtc.RTCisLatched=t[e++],i.cartridge.mbc3.rtc.latchedSeconds=t[e++],i.cartridge.mbc3.rtc.latchedMinutes=t[e++],i.cartridge.mbc3.rtc.latchedHours=t[e++],i.cartridge.mbc3.rtc.latchedLDays=t[e++],i.cartridge.mbc3.rtc.latchedHDays=t[e++],i.cartridge.mbc3.rtc.RTCSeconds=t[e++],i.cartridge.mbc3.rtc.RTCMinutes=t[e++],i.cartridge.mbc3.rtc.RTCHours=t[e++],i.cartridge.mbc3.rtc.RTCDays=t[e++],i.cartridge.mbc3.rtc.RTCDayOverFlow=t[e++],i.cartridge.mbc3.rtc.RTCHalt=t[e++]):e+=12,i.usedBootRom=t[e++],i.skipPCIncrement=t[e++],i.STATTracker=t[e++],i.gbcEchoRamBankPosition=t[e++],i.windowY=t[e++],i.windowX=t[e++],i.gbcOBJRawPalette=a(t[e++],"uint8"),i.gbcBGRawPalette=a(t[e++],"uint8"),i.gbOBJPalette=a(t[e++],"int32"),i.gbBGPalette=a(t[e++],"int32"),i.gbcOBJPalette=a(t[e++],"int32"),i.gbcBGPalette=a(t[e++],"int32"),i.gbBGColorizedPalette=a(t[e++],"int32"),i.gbOBJColorizedPalette=a(t[e++],"int32"),i.cachedBGPaletteConversion=a(t[e++],"int32"),i.cachedOBJPaletteConversion=a(t[e++],"int32"),i.BGCHRBank1=a(t[e++],"uint8"),i.BGCHRBank2=a(t[e++],"uint8"),i.haltPostClocks=t[e++],i.interruptRequestedFlags=t[e++],i.interruptEnabledFlags=t[e++],i.checkIrqMatching(),i.remainingClocks=t[e++],i.colorizedGBPalettes=t[e++],i.backgroundY=t[e++],i.backgroundX=t[e++],i.cpu.stopped=t[e++],i.audioController.audioClocksUntilNextEvent=t[e++],i.audioController.audioClocksUntilNextEventCounter=t[e]}}class I{constructor(t,e,i,r){if(this.fromSampleRate=t,this.toSampleRate=e,this.channels=i,this.outputBufferSize=r,this.fromSampleRate<=0||this.toSampleRate<=0||this.channels<=0)throw new Error("Invalid settings specified for the resampler.");this.ratioWeight=this.fromSampleRate/this.toSampleRate,this.fromSampleRate<this.toSampleRate&&(this.lastWeight=1),this.outputBuffer=new Float32Array(this.outputBufferSize),this.lastOutput=new Float32Array(this.channels)}resample(t){let e=t.length;if(e%this.channels!=0)throw new Error("Buffer was of incorrect sample length.");if(0===e)return;let i=this.lastWeight,r=0,s=0,h=0,a=0;for(;i<1;i+=this.ratioWeight){s=i%1,r=1-s;for(let e=0;e<this.channels;e++)this.outputBuffer[a++]=this.lastOutput[e]*r+t[e]*s}for(i-=1,e-=this.channels,h=Math.floor(i)*this.channels;a<this.outputBufferSize&&h<e;){s=i%1,r=1-s;for(let e=0;e<this.channels;e++)this.outputBuffer[a++]=t[h+e]*r+t[h+this.channels+e]*s;i+=this.ratioWeight,h=Math.floor(i)*this.channels}for(let e=0;e<this.channels;++e)this.lastOutput[e]=t[h++];return this.lastWeight=i%1,a}}const x=require("worker-url"),O="undefined"!=typeof window?"undefined"!=typeof AudioContext?AudioContext:window.webkitAudioContext:null;class Z{constructor({context:t,channels:e,minBufferSize:i}){this.volume=1,this.samplesPerCallback=2048,this.context=t,this.channelsAllocated=Math.max(e,1),this.bufferSize=this.samplesPerCallback*this.channelsAllocated,this.minBufferSize=i||this.bufferSize}setSampleRate(t){this.sampleRate=t}setMaxBufferSize(t){this.maxBufferSize=Math.floor(t)>this.minBufferSize+this.channelsAllocated?t&-this.channelsAllocated:this.minBufferSize*this.channelsAllocated}writeAudio(t){let e=0;for(;e<t.length&&this.inputBufferSize<this.maxBufferSize;)this.inputBuffer[this.inputBufferSize++]=t[e++]}remainingBuffer(){return Math.floor(this.resampledSamplesLeft()*this.resampler?.ratioWeight/this.channelsAllocated)*this.channelsAllocated+this.inputBufferSize}async init(){if(this.context||(this.context=new O),!this.audioNode){if(this.gainNode=this.context.createGain(),this.context?.audioWorklet)(this.audioNode=this.context.createScriptProcessor(this.samplesPerCallback,0,this.channelsAllocated)).onaudioprocess=t=>this.processAudio(t);else{const e=new x.WorkerUrl(new URL(t.p+t.u(259),t.b),{name:"worklet"});await this.context.audioWorklet.addModule(e),this.audioNode=new AudioWorkletNode(this.context,"noise-generator")}this.audioNode.connect(this.gainNode),this.gainNode.connect(this.context.destination),this.resetAudioBuffer(this.context.sampleRate)}}processAudio(t){const e=[];let i=0;for(;i<this.channelsAllocated;)e[i]=t.outputBuffer.getChannelData(i),++i;this.refillResampledBuffer();let r=0;for(;r<this.samplesPerCallback&&this.outputBufferStart!==this.outputBufferEnd;){for(i=0;i<this.channelsAllocated;)e[i][r]=this.outputBuffer[this.outputBufferStart++],++i;this.outputBufferStart===this.outputBufferSize&&(this.outputBufferStart=0),++r}for(;r<this.samplesPerCallback;){for(i=0;i<this.channelsAllocated;++i)e[i][r]=0;++r}}setVolume(t){this.volume=Math.max(0,Math.min(1,t)),this.gainNode.gain.setTargetAtTime(this.volume,this.context.currentTime,0)}resetAudioBuffer(t){this.inputBufferSize=this.outputBufferEnd=this.outputBufferStart=0,this.initializeResampler(t),this.outputBuffer=new Float32Array(this.outputBufferSize)}refillResampledBuffer(){if(this.inputBufferSize>0){const t=this.resampler.resample(this.getBufferSamples()),e=this.resampler.outputBuffer;for(let i=0;i<t;)this.outputBuffer[this.outputBufferEnd++]=e[i++],this.outputBufferEnd===this.outputBufferSize&&(this.outputBufferEnd=0),this.outputBufferStart===this.outputBufferEnd&&(this.outputBufferStart+=this.channelsAllocated,this.outputBufferStart===this.outputBufferSize&&(this.outputBufferStart=0));this.inputBufferSize=0}}initializeResampler(t){this.inputBuffer=new Float32Array(this.maxBufferSize),this.outputBufferSize=Math.max(this.maxBufferSize*Math.ceil(t/this.sampleRate)+this.channelsAllocated,this.bufferSize),this.resampler=new I(this.sampleRate,t,this.channelsAllocated,this.outputBufferSize)}resampledSamplesLeft(){return(this.outputBuffe