Comparing version 0.2.19 to 0.2.20
176
dist/apu.js
@@ -1,1 +0,175 @@ | ||
!function(A,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.APU=t():A.APU=t()}(window,(function(){return function(A){var t={};function n(e){if(t[e])return t[e].exports;var Q=t[e]={i:e,l:!1,exports:{}};return A[e].call(Q.exports,Q,Q.exports,n),Q.l=!0,Q.exports}return n.m=A,n.c=t,n.d=function(A,t,e){n.o(A,t)||Object.defineProperty(A,t,{enumerable:!0,get:e})},n.r=function(A){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(A,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(A,"__esModule",{value:!0})},n.t=function(A,t){if(1&t&&(A=n(A)),8&t)return A;if(4&t&&"object"==typeof A&&A&&A.__esModule)return A;var e=Object.create(null);if(n.r(e),Object.defineProperty(e,"default",{enumerable:!0,value:A}),2&t&&"string"!=typeof A)for(var Q in A)n.d(e,Q,function(t){return A[t]}.bind(null,Q));return e},n.n=function(A){var t=A&&A.__esModule?function(){return A.default}:function(){return A};return n.d(t,"a",t),t},n.o=function(A,t){return Object.prototype.hasOwnProperty.call(A,t)},n.p="",n(n.s=0)}([function(A,t,n){"use strict";n.r(t),n.d(t,"C3",(function(){return B})),n.d(t,"Cs3",(function(){return o})),n.d(t,"D3",(function(){return g})),n.d(t,"Ds3",(function(){return C})),n.d(t,"E3",(function(){return i})),n.d(t,"F3",(function(){return r})),n.d(t,"Fs3",(function(){return I})),n.d(t,"G3",(function(){return E})),n.d(t,"Gs3",(function(){return a})),n.d(t,"A3",(function(){return u})),n.d(t,"As3",(function(){return s})),n.d(t,"B3",(function(){return c})),n.d(t,"C4",(function(){return f})),n.d(t,"Cs4",(function(){return J})),n.d(t,"D4",(function(){return d})),n.d(t,"Ds4",(function(){return k})),n.d(t,"E4",(function(){return l})),n.d(t,"F4",(function(){return p})),n.d(t,"Fs4",(function(){return w})),n.d(t,"G4",(function(){return m})),n.d(t,"Gs4",(function(){return G})),n.d(t,"A4",(function(){return D})),n.d(t,"As4",(function(){return y})),n.d(t,"B4",(function(){return h})),n.d(t,"C5",(function(){return q})),n.d(t,"Cs5",(function(){return H})),n.d(t,"D5",(function(){return R})),n.d(t,"Ds5",(function(){return F})),n.d(t,"E5",(function(){return Y})),n.d(t,"F5",(function(){return L})),n.d(t,"Fs5",(function(){return N})),n.d(t,"G5",(function(){return P})),n.d(t,"Gs5",(function(){return S})),n.d(t,"A5",(function(){return U})),n.d(t,"As5",(function(){return Z})),n.d(t,"B5",(function(){return x})),n.d(t,"C6",(function(){return j})),n.d(t,"Cs6",(function(){return M})),n.d(t,"D6",(function(){return O})),n.d(t,"Ds6",(function(){return b})),n.d(t,"E6",(function(){return K})),n.d(t,"F6",(function(){return v})),n.d(t,"Fs6",(function(){return W})),n.d(t,"G6",(function(){return T})),n.d(t,"Gs6",(function(){return X})),n.d(t,"A6",(function(){return V})),n.d(t,"As6",(function(){return z})),n.d(t,"B6",(function(){return $})),n.d(t,"C7",(function(){return _})),n.d(t,"Cs7",(function(){return AA})),n.d(t,"D7",(function(){return tA})),n.d(t,"Ds7",(function(){return nA})),n.d(t,"E7",(function(){return eA})),n.d(t,"F7",(function(){return QA})),n.d(t,"Fs7",(function(){return BA})),n.d(t,"G7",(function(){return oA})),n.d(t,"Gs7",(function(){return gA})),n.d(t,"A7",(function(){return CA})),n.d(t,"As7",(function(){return iA})),n.d(t,"B7",(function(){return rA})),n.d(t,"C8",(function(){return IA})),n.d(t,"Cs8",(function(){return EA})),n.d(t,"D8",(function(){return aA})),n.d(t,"Ds8",(function(){return uA})),n.d(t,"E8",(function(){return sA})),n.d(t,"F8",(function(){return cA})),n.d(t,"Fs8",(function(){return fA})),n.d(t,"G8",(function(){return JA})),n.d(t,"Gs8",(function(){return dA})),n.d(t,"A8",(function(){return kA})),n.d(t,"As8",(function(){return lA})),n.d(t,"B8",(function(){return pA})),n.d(t,"audioContext",(function(){return wA})),n.d(t,"allow",(function(){return mA})),n.d(t,"changeUserVolume",(function(){return yA})),n.d(t,"audioNode",(function(){return hA})),n.d(t,"bgm",(function(){return NA})),n.d(t,"sfx",(function(){return PA})),n.d(t,"fromFile",(function(){return SA})),n.d(t,"fade",(function(){return UA})),n(1);var e=n(2).default,Q=n(3).default,B=44,o=156,g=263,C=363,i=457,r=547,I=631,E=710,a=786,u=856,s=923,c=986,f=1046,J=1102,d=1155,k=1205,l=1253,p=1297,w=1339,m=1379,G=1417,D=1452,y=1486,h=1517,q=1547,H=1575,R=1602,F=1627,Y=1650,L=1673,N=1694,P=1714,S=1732,U=1750,Z=1767,x=1783,j=1798,M=1812,O=1825,b=1837,K=1849,v=1860,W=1871,T=1881,X=1890,V=1899,z=1907,$=1915,_=1923,AA=1930,tA=1936,nA=1943,eA=1949,QA=1954,BA=1959,oA=1964,gA=1969,CA=1974,iA=1978,rA=1982,IA=1985,EA=1989,aA=1992,uA=1995,sA=1998,cA=2001,fA=2004,JA=2006,dA=2009,kA=2011,lA=2013,pA=2015;"webkitAudioContext"in window&&(window.AudioContext=webkitAudioContext);var wA=new AudioContext({latencyHint:"interactive"});function mA(){wA.resume()}var GA=1,DA=wA.createGain();function yA(A){A>=0&&A<=1&&(DA.gain.setValueAtTime(GA,wA.currentTime),DA.gain.linearRampToValueAtTime(A,wA.currentTime+.05),GA=A)}DA.gain.setValueAtTime(GA,wA.currentTime),DA.connect(wA.destination);var hA=DA,qA=new Blob([e],{type:"application/javascript"}),HA=URL.createObjectURL(qA),RA=wA.audioWorklet.addModule(HA).then((function(){var A=new AudioWorkletNode(wA,"gameboy-processor",{outputChannelCount:[2]});return A.connect(DA),new Promise((function(t){A.port.onmessage=function(n){return"ready"===n.data&&t(A)};var n=new XMLHttpRequest;n.open("GET",Q),n.responseType="arraybuffer",n.onload=function(){return A.port.postMessage({type:"module",data:n.response})},n.send()}))})),FA=0,YA=!0;function LA(A,t,n){return void 0===n&&(n=null),{play:function(){if(n&&!YA)return null;var e=++FA;return RA.then((function(Q){Q.port.postMessage({id:e,type:"play",data:A,loop:t,mask:n})})),{pause:function(){RA.then((function(A){return A.port.postMessage({id:e,type:"pause"})}))},resume:function(){RA.then((function(A){return A.port.postMessage({id:e,type:"resume"})}))}}}}}function NA(A,t){return void 0===t&&(t=0),LA(A,t)}function PA(A,t){return void 0===t&&(t=[1,1,1,1]),LA(A,-1,t)}function SA(A){for(var t=new Uint8Array(A,0,4),n=0;n<4;++n)if(t[n]!=="Vgm ".charCodeAt(n))throw new Error("Invalid header");var e=52+new Uint32Array(A,52,1)[0],Q=28+new Uint32Array(A,28,1)[0]-e;return NA(A.slice(e),Q)}function UA(A){return RA.then((function(t){PA(new ArrayBuffer(0),[0,0,0,0]).play(),YA=!1;for(var n=function(n){var e=6-n;setTimeout((function(){return t.port.postMessage({type:"write",layer:0,register:20,value:(e<<4)+e})}),A*n/7)},e=0;e<=5;++e)n(e);return setTimeout((function(){t.port.postMessage({type:"write",layer:0,register:22,value:0}),NA(new ArrayBuffer(0),-1).play()}),6*A/7),new Promise((function(t){return setTimeout(t,A)})).then((function(){YA=!0}))}))}},function(A,t){!function(){function A(A,t){var n=document.createElement("iframe");n.style.cssText="position:absolute;left:0;top:-999px;width:1px;height:1px;",t.appendChild(n);var e=n.contentWindow,Q=e.document,B="var window,$hook";for(var o in e)o in A||"eval"===o||(B+=",",B+=o);for(var g in A)B+=",",B+=g,B+="=self.",B+=g;var C=Q.createElement("script");C.appendChild(Q.createTextNode('function $hook(self,console) {"use strict";\n '+B+";return function() {return eval(arguments[0])}}")),Q.body.appendChild(C),this.exec=e.$hook.call(A,A,console)}var t,n=[];function e(A){var t=this,e={},B=-1;this.parameters.forEach((function(A,Q){var o=n[++B]||(n[B]=new Float32Array(t.bufferSize));o.fill(A.value),e[Q]=o})),this.processor.realm.exec("self.sampleRate=sampleRate="+this.context.sampleRate+";self.currentTime=currentTime="+this.context.currentTime);var o=Q(A.inputBuffer),g=Q(A.outputBuffer);this.instance.process([o],[g],e)}function Q(A){for(var t=[],n=0;n<A.numberOfChannels;n++)t[n]=A.getChannelData(n);return t}function B(A){return A.$$processors||(A.$$processors={})}"function"==typeof AudioWorkletNode&&"audioWorklet"in AudioContext.prototype||(self.AudioWorkletNode=function(A,n,Q){var o=B(A)[n],g=A.createScriptProcessor(2048,2,Q&&Q.outputChannelCount?Q.outputChannelCount[0]:2);if(g.parameters=new Map,o.properties)for(var C=0;C<o.properties.length;C++){var i=o.properties[C],r=A.createGain().gain;r.value=i.defaultValue,g.parameters.set(i.name,r)}var I=new MessageChannel;t=I.port2;var E=new o.Processor(Q||{});return t=null,g.port=I.port1,g.processor=o,g.instance=E,g.onaudioprocess=e,g},Object.defineProperty((self.AudioContext||self.webkitAudioContext).prototype,"audioWorklet",{get:function(){return this.$$audioWorklet||(this.$$audioWorklet=new self.AudioWorklet(this))}}),self.AudioWorklet=function(){function n(A){this.$$context=A}return n.prototype.addModule=function(n,e){var Q=this;return fetch(n).then((function(A){if(!A.ok)throw Error(A.status);return A.text()})).then((function(n){var o={sampleRate:Q.$$context.sampleRate,currentTime:Q.$$context.currentTime,AudioWorkletProcessor:function(){this.port=t},registerProcessor:function(A,t){B(Q.$$context)[A]={realm:g,context:o,Processor:t,properties:t.parameterDescriptors||[]}}};o.self=o;var g=new A(o,document.documentElement);return g.exec((e&&e.transpile||String)(n)),null}))},n}())}()},function(A,t,n){"use strict";n.r(t),t.default='class GameboyProcessor extends AudioWorkletProcessor{constructor(...e){super(...e),this.port.onmessage=({data:e})=>{if("write"===e.type)this.s.registerWrite(e.layer,e.register,e.value);else if("play"===e.type){const t=new Uint8Array(e.data);this.ready.then(()=>{e.mask?this.s.playSFX(t,e.mask):this.s.playSong(t,e.loop)})}else if("module"===e.type){const t=WebAssembly.instantiate(e.data).then(e=>e.instance.exports);t.then(e=>{e.init(sampleRate),this.lchan=new Float32Array(e.memory.buffer,e.lchan,128),this.rchan=new Float32Array(e.memory.buffer,e.rchan,128),this.updateGB=e.update,this.s=songContext(e.gb_sound_w,e.enable_channel,e.disable_channel),this.port.postMessage("ready")}),this.ready=t.then(()=>!0)}}}process(e,t){if(this.updateGB){const e=t[0][0],s=t[0][1];for(let t=0;t<e.length;t+=128){for(let e=0;e<128;++e)this.s.tick();this.updateGB(),e.set(this.lchan,t),s.set(this.rchan,t)}}return!0}}function songContext(e,t,s){let r=null,n=-1,o=0,i=-1,a=null,l=-1,h=0,c=[0,0,0,0];return{playSong:function(e,t,f=0){r=e,n=f,o=0,i=t,a=null,l=-1,h=0,c=[0,0,0,0];for(let e=0;e<4;++e)s(1,e)},playSFX:function(e,t){a=e,l=0,h=0,c=t;for(let e=0;e<4;++e)t[e]&&s(0,e)},tick:function(){for(;o<=0&&n>=0&&!(n>=r.length&&(n=i,-1===n));){const s=r[n++];if(179===s){const s=r[n++],o=r[n++];e(0,s,o),128&o&&(4!==s||c[0]?9!==s||c[1]?14!==s||c[2]?19!==s||c[3]||t(0,3):t(0,2):t(0,1):t(0,0))}else if(97===s){const e=r[n++]+(r[n++]<<8);o+=e}else if(98===s){o+=735}else if(112==(240&s)){o+=1+(15&s)}else{if(102!==s)throw new Error("What is op "+s.toString(16));n=i}}for(;h<=0&&l>=0;){if(l>=a.length){l=-1,c=[0,0,0,0];break}const s=a[l++];if(179===s){const s=a[l++],r=a[l++];e(1,s,r),128&r&&(4===s?t(1,0):9===s?t(1,1):14===s?t(1,2):19===s&&t(1,3))}else if(97===s){const e=a[l++]+(a[l++]<<8);h+=e}else if(98===s){h+=735}else if(112==(240&s)){h+=1+(15&s)}else{if(102!==s)throw new Error("What is op "+s.toString(16));l=a.length}}const s=44100/sampleRate;o-=s,h-=s},registerWrite:e}}registerProcessor("gameboy-processor",GameboyProcessor);'},function(A,t,n){"use strict";n.r(t),t.default="data:application/wasm;base64,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AmpB//8BOwEAIABB3JACakE+OgAAIABB2JACakEANgIAIABBzJACaiAAQaCRAmotAABBBHY2AgAgAEGlkQJqIgAgAC0AAEEIcjoAAA8LIABBhZECaiACQQdxOgAAIABBhpECaiACQQR2QQdxOgAADwsgAEGIkQJqIAJBAXE6AAAgAEGNkQJqIAJBB3Y6AAAgAEGKkQJqIAJBAXZBAXE6AAAgAEGHkQJqIAJBBHZBAXE6AAAgAEGMkQJqIAJBAnZBAXE6AAAgAEGJkQJqIAJBBXZBAXE6AAAgAEGOkQJqIAJBA3ZBAXE6AAAgAEGLkQJqIAJBBnZBAXE6AAAPCyAAIAJBB3Y6AISRAiACQRh0QRh1QQBIDQAgAEGA/wA7AI+RAiAAQfiOAmpBfzYCACAAQfyOAmogACgCJDYCACAAQZGRAmpBADoAACAAQeCOAmpB/wE6AAAgAEHcjgJqQQA2AgAgAEGSkQJqQf7/AjsAACAAQeSOAmogACgCBCIBNgIAIABB8I4CakL+HzcCACAAQdiOAmpBADsBACAAQciOAmogAEHAhgJqKAIAIgI2AgAgAEHQjgJqIABBvIABaigCADYCACAALQDEjgJFBEAgAEHMjgJqQQA2AgALIABBADYC3I4CIABBAToAxI4CIABBgI8CakEANgIAIABB6I4CakEANgIAIABB1I4CakEANgIAIABB7I4CakEBOgAAIABBmI8CaiACNgIAIABBlZECakG/gPz/ezYAACAAQbSPAmogATYCACAAQbCPAmpB/wE6AAAgAEGsjwJqQQA2AgAgAEGojwJqQQA7AQAgAEGgjwJqIABBwIABaigCADYCACAAQaWRAmoiAyADLQAAIgNBAXI6AAAgAC0AlI8CRQRAIABBnI8CakEANgIACyAAQQA2AqyPAiAAQQE6AJSPAiAAQQE6AOSPAiAAQZmRAmpB//4DOwAAIABBvI8CakEBOgAAIABBuI8CakEANgIAIABBpI8CakEANgIAIABBm5ECakGfAToAACAAQZyRAmpB//8COwAAIABBpJACakEAOwEAIABB7I8CakEANgIAIAAgA0EHcjoApZECIABBqJACakEANgIAIABB+I8CakGAAjsBACAAQfSPAmpBADYCACAAQeiPAmogAEHAjgJqKAIANgIAIABB8I8CaiAAQcCAAmooAgA2AgAg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"}])})); | ||
var APU; | ||
(function (APU) { | ||
var workletSource = "\"use strict\";function _classCallCheck(t,e){if(!(t instanceof e))throw new TypeError(\"Cannot call a class as a function\")}function _defineProperties(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,\"value\"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}function _createClass(t,e,r){return e&&_defineProperties(t.prototype,e),r&&_defineProperties(t,r),t}function _possibleConstructorReturn(t,e){return!e||\"object\"!=typeof e&&\"function\"!=typeof e?_assertThisInitialized(t):e}function _assertThisInitialized(t){if(void 0===t)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return t}function _inherits(t,e){if(\"function\"!=typeof e&&null!==e)throw new TypeError(\"Super expression must either be null or a function\");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&_setPrototypeOf(t,e)}function _wrapNativeSuper(t){var e=\"function\"==typeof Map?new Map:void 0;return(_wrapNativeSuper=function(t){if(null===t||!_isNativeFunction(t))return t;if(\"function\"!=typeof t)throw new TypeError(\"Super expression must either be null or a function\");if(void 0!==e){if(e.has(t))return e.get(t);e.set(t,r)}function r(){return _construct(t,arguments,_getPrototypeOf(this).constructor)}return r.prototype=Object.create(t.prototype,{constructor:{value:r,enumerable:!1,writable:!0,configurable:!0}}),_setPrototypeOf(r,t)})(t)}function isNativeReflectConstruct(){if(\"undefined\"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if(\"function\"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}function _construct(t,e,r){return(_construct=isNativeReflectConstruct()?Reflect.construct:function(t,e,r){var n=[null];n.push.apply(n,e);var o=new(Function.bind.apply(t,n));return r&&_setPrototypeOf(o,r.prototype),o}).apply(null,arguments)}function _isNativeFunction(t){return-1!==Function.toString.call(t).indexOf(\"[native code]\")}function _setPrototypeOf(t,e){return(_setPrototypeOf=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function _getPrototypeOf(t){return(_getPrototypeOf=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}var GameboyProcessor=function(t){function e(){var t,r;_classCallCheck(this,e);for(var n=arguments.length,o=new Array(n),i=0;i<n;i++)o[i]=arguments[i];return(r=_possibleConstructorReturn(this,(t=_getPrototypeOf(e)).call.apply(t,[this].concat(o)))).port.onmessage=function(t){var e=t.data;if(\"write\"===e.type)r.s.registerWrite(e.layer,e.register,e.value);else if(\"play\"===e.type){var n=new Uint8Array(e.data);r.ready.then((function(){e.mask?r.s.playSFX(n,e.mask):r.s.playSong(n,e.loop)}))}else if(\"module\"===e.type){var o=WebAssembly.instantiate(e.data).then((function(t){return t.instance.exports}));o.then((function(t){t.init(sampleRate),r.lchan=new Float32Array(t.memory.buffer,t.lchan,128),r.rchan=new Float32Array(t.memory.buffer,t.rchan,128),r.updateGB=t.update,r.s=songContext(t.gb_sound_w,t.enable_channel,t.disable_channel),r.port.postMessage(\"ready\")})),r.ready=o.then((function(){return!0}))}},r}return _inherits(e,_wrapNativeSuper(AudioWorkletProcessor)),_createClass(e,[{key:\"process\",value:function(t,e){if(this.updateGB)for(var r=e[0][0],n=e[0][1],o=0;o<r.length;o+=128){for(var i=0;i<128;++i)this.s.tick();this.updateGB(),r.set(this.lchan,o),n.set(this.rchan,o)}return!0}}]),e}();function songContext(t,e,r){var n=[0,1].map((function(r){return chip(t.bind(null,r),e.bind(null,r))}));return{playSong:function(e,o){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;n[0].track=e,n[0].idx=i,n[0].timer=0,n[0].loopPoint=o,n[0].mask=[1,1,1,1],n[0].doneCallback=null,n[1].track=null,n[1].idx=-1,n[1].timer=0,n[1].loopPoint=-1,n[1].mask=[0,0,0,0],n[1].doneCallback=null;for(var a=0;a<4;++a)r(1,a);t(0,22,0)},playSFX:function(t,e){n[0].mask=e.map((function(t){return 1-t})),n[1].track=t,n[1].idx=0,n[1].timer=0,n[1].loopPoint=-1,n[1].mask=e,n[1].doneCallback=function(){n[0].mask=[1,1,1,1],n[1].mask=[0,0,0,0]};for(var o=0;o<4;++o)e[o]&&r(0,o)},tick:function(){n.forEach((function(t){return t.tick()}))},registerWrite:t}}function chip(t,e){var r={track:null,idx:-1,timer:0,loopPoint:-1,mask:[0,0,0,0],doneCallback:null,tick:function(){for(;r.timer<=0&&r.idx>=0;){if(r.idx>=r.track.length&&(r.idx=r.loopPoint,-1===r.idx)){r.doneCallback&&r.doneCallback();break}var n=r.track[r.idx++];if(179===n){var o=r.track[r.idx++],i=r.track[r.idx++];t(o,i),128&i&&(4===o&&r.mask[0]?e(0):9===o&&r.mask[1]?e(1):14===o&&r.mask[2]?e(2):19===o&&r.mask[3]&&e(3))}else if(97===n){var a=r.track[r.idx++]+(r.track[r.idx++]<<8);r.timer+=a}else if(98===n){r.timer+=735}else if(112==(240&n)){var c=1+(15&n);r.timer+=c}else{if(102!==n)throw new Error(\"What is op \"+n.toString(16)+\" at \"+(r.idx-1));r.idx=r.track.length}}var u=44100/sampleRate;r.timer-=u}};return r}registerProcessor(\"gameboy-processor\",GameboyProcessor);\n"; | ||
var wasmEncoded = 'AGFzbQEAAAABGQVgAn9/AGABfwBgA39/fwBgAABgAn9/AX8DCgkCAgAEAQEAAAMFAwEAAwYPAn8AQZC7BAt/AEGQxwQLB5QBCgZtZW1vcnkCAApnYl9zb3VuZF93AAAaZGV2aWNlX3N0YXJ0X2dhbWVib3lfc291bmQAAxpkZXZpY2VfcmVzZXRfZ2FtZWJveV9zb3VuZAAEBGluaXQABQ9kaXNhYmxlX2NoYW5uZWwABg5lbmFibGVfY2hhbm5lbAAHBnVwZGF0ZQAIBWxjaGFuAwAFcmNoYW4DAQqhOglTAAJAIAFBH00EQCAAQcCRAmwhACABQRZHBEAgAEGUoQJqLQAARQ0CCyAAQZAQaiABIAIQAQ8LIAFBL0sNACAAQcCRAmwgAWpBn6ECaiACOgAACwuBFgECfyAAIAFqQY+RAmoiAyACOgAAAkAgAUEWSw0AAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAAkACQAJAIAFBAWsOFgECAwQVBQYHCAkKCwwNFQ4PEBESExQACyAAQfSOAmogAkEHcTYCACAAQfiOAmogAkEDdkEBcSIBQX9qIAFyNgIAIABB/I4CaiAAIAJBAnZBHHFqQSRqKAIANgIADwsgAEHZjgJqIAJBBnY6AAAgAEHIjgJqIAAgAkE/cUECdGpBxIQCaigCADYCAA8LIABB4I4CaiACQQN2QQFxIgE6AAACQCABBEAgAEHcjgJqIgNBACADKAIAIgNBAWogA0EOShs2AgAMAQsgAEHcjgJqIAJBBHY2AgALIAAgAUF/aiABcjoA4I4CIABB5I4CaiAAIAJBB3FBAnRqQQRqKAIANgIADwsgAEHwjgJqIABBkpECai0AACAAQZORAmotAABBD3FBCHRyIgE2AgAgAEHQjgJqIAAgAUECdGpBxABqKAIANgIADwsgAEHwjgJqIABBkpECai0AACAAQZORAmotAABBD3FBCHRyIgE2AgAgAEHYjgJqIAJBBnZBAXE6AAAgAEHQjgJqIAAgAUECdGpBxABqKAIANgIAIAJBGHRBGHVBf0oNECAALQDEjgJFBEAgAEHMjgJqQQA2AgALIABBAToAxI4CIABB1I4CakEANgIAIABBgI8CakEANgIAIABB6I4CakEANgIAIABB7I4CakEBOgAAIABB3I4CaiAAQZGRAmotAABBBHY2AgAgAEGlkQJqIgAgAC0AAEEBcjoAAA8LIABBqY8CaiACQQZ2OgAAIABBmI8CaiAAIAJBP3FBAnRqQcSEAmooAgA2AgAPCyAAQbCPAmogAkEDdkEBcSIBOgAAAkAgAQRAIABBrI8CaiIDQQAgAygCACIDQQFqIANBDkobNgIADAELIABBrI8CaiACQQR2NgIACyAAIAFBf2ogAXI6ALCPAiAAQbSPAmogACACQQdxQQJ0akEEaigCADYCAA8LIABBoI8CaiAAIABBmJECai0AAEEPcUEKdCAAQZeRAmotAABBAnRyakHEAGooAgA2AgAPCyAAQaiPAmogAkEGdkEBcToAACAAQaCPAmogACAAQZiRAmotAABBD3FBCnQgAEGXkQJqLQAAQQJ0cmpBxABqKAIANgIAIAJBGHRBGHVBf0oNDCAALQCUjwJFBEAgAEGcjwJqQQA2AgALIABBAToAlI8CIABBpI8CakEANgIAIABBvI8CakEBOgAAIABBuI8CakEANgIAIABBrI8CaiAAQZaRAmotAABBBHY2AgAgAEGlkQJqIgAgAC0AAEECcjoAAA8LIAAgAkEHdjoA5I8CDwsgAEHojwJqIAAgAkECdGpBxIYCaigCADYCAA8LIABBpJACaiACQQV2QQNxOgAADwsgAEHwjwJqIAAgAEGdkQJqLQAAQQ9xQQp0IABBnJECai0AAEECdHJqQcSAAWooAgA2AgAPCyAAQfiPAmogAkEGdkEBcToAACAAQfCPAmogACAAQZ2RAmotAABBD3FBCnQgAEGckQJqLQAAQQJ0cmpBxIABaigCADYCACACQRh0QRh1QX9KDQcgAC0A5I8CRQRAIABBpZACakEAOgAAIABB7I8CakEANgIAIABB+Y8CakEAOgAACyAAQQE6AOSPAiAAQaiQAmpBADYCACAAQfmPAmpBAToAACAAQfSPAmpBADYCACAAQaWRAmoiACAALQAAQQRyOgAADwsgAEG4kAJqIAAgAkE/cUECdGpBxIQCaigCADYCAA8LIABB0JACaiACQQN2QQFxIgE6AAACQCABBEAgAEHMkAJqIgNBACADKAIAIgNBAWogA0EOShs2AgAMAQsgAEHMkAJqIAJBBHY2AgALIAAgAUF/aiABcjoA0JACIABB1JACaiAAIAJBB3FBAnRqQQRqKAIA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'; | ||
APU.C3 = 44, APU.Cs3 = 156, APU.D3 = 263, APU.Ds3 = 363, APU.E3 = 457, APU.F3 = 547, APU.Fs3 = 631, APU.G3 = 710, APU.Gs3 = 786, APU.A3 = 856, APU.As3 = 923, APU.B3 = 986, APU.C4 = 1046, APU.Cs4 = 1102, APU.D4 = 1155, APU.Ds4 = 1205, APU.E4 = 1253, APU.F4 = 1297, APU.Fs4 = 1339, APU.G4 = 1379, APU.Gs4 = 1417, APU.A4 = 1452, APU.As4 = 1486, APU.B4 = 1517, APU.C5 = 1547, APU.Cs5 = 1575, APU.D5 = 1602, APU.Ds5 = 1627, APU.E5 = 1650, APU.F5 = 1673, APU.Fs5 = 1694, APU.G5 = 1714, APU.Gs5 = 1732, APU.A5 = 1750, APU.As5 = 1767, APU.B5 = 1783, APU.C6 = 1798, APU.Cs6 = 1812, APU.D6 = 1825, APU.Ds6 = 1837, APU.E6 = 1849, APU.F6 = 1860, APU.Fs6 = 1871, APU.G6 = 1881, APU.Gs6 = 1890, APU.A6 = 1899, APU.As6 = 1907, APU.B6 = 1915, APU.C7 = 1923, APU.Cs7 = 1930, APU.D7 = 1936, APU.Ds7 = 1943, APU.E7 = 1949, APU.F7 = 1954, APU.Fs7 = 1959, APU.G7 = 1964, APU.Gs7 = 1969, APU.A7 = 1974, APU.As7 = 1978, APU.B7 = 1982, APU.C8 = 1985, APU.Cs8 = 1989, APU.D8 = 1992, APU.Ds8 = 1995, APU.E8 = 1998, APU.F8 = 2001, APU.Fs8 = 2004, APU.G8 = 2006, APU.Gs8 = 2009, APU.A8 = 2011, APU.As8 = 2013, APU.B8 = 2015; | ||
if ('webkitAudioContext' in window) { | ||
window.AudioContext = webkitAudioContext; | ||
} | ||
/** | ||
* Audio Context that all APU stuff runs on | ||
*/ | ||
APU.audioContext = new AudioContext({ latencyHint: 'interactive' }); | ||
/** | ||
* Resumes the audio context. Should be called as a result of some user event, like a click. | ||
* Until this is called, the browser won't allow any sound to play. | ||
*/ | ||
function allow() { | ||
APU.audioContext.resume(); | ||
} | ||
APU.allow = allow; | ||
var lastVolume = 1; | ||
var userVolumeNode = APU.audioContext.createGain(); | ||
userVolumeNode.gain.setValueAtTime(lastVolume, APU.audioContext.currentTime); | ||
userVolumeNode.connect(APU.audioContext.destination); | ||
/** | ||
* Volume multiplier intended to be changed by a user-facing volume control | ||
* @param newVolume Value between 0 and 1 | ||
*/ | ||
function changeUserVolume(newVolume) { | ||
if (newVolume >= 0 && newVolume <= 1) { | ||
userVolumeNode.gain.setValueAtTime(lastVolume, APU.audioContext.currentTime); | ||
userVolumeNode.gain.linearRampToValueAtTime(newVolume, APU.audioContext.currentTime + 0.05); | ||
lastVolume = newVolume; | ||
} | ||
} | ||
APU.changeUserVolume = changeUserVolume; | ||
/** | ||
* The last audio node, which is connected to the AudioContext's destination | ||
*/ | ||
APU.audioNode = userVolumeNode; | ||
var workletBlob = new Blob([workletSource], { type: 'application/javascript' }); | ||
var workletURL = URL.createObjectURL(workletBlob); | ||
var wasmBuffer = new Uint8Array(atob(wasmEncoded).split('').map(function (s) { return s.charCodeAt(0); })).buffer; | ||
var nodePromise = APU.audioContext.audioWorklet.addModule(workletURL).then(function () { | ||
var node = new AudioWorkletNode(APU.audioContext, 'gameboy-processor', { outputChannelCount: [2] }); | ||
node.connect(userVolumeNode); | ||
return new Promise(function (resolve) { | ||
node.port.onmessage = function (_a) { | ||
var e = _a.data; | ||
return (e === 'ready') && resolve(node); | ||
}; | ||
node.port.postMessage({ type: 'module', data: wasmBuffer }); | ||
}); | ||
}); | ||
var nextInstanceId = 0; | ||
var allowSFX = true; | ||
function track(data, loop, mask) { | ||
if (mask === void 0) { mask = null; } | ||
return { | ||
play: function () { | ||
if (mask && !allowSFX) | ||
return null; | ||
var id = ++nextInstanceId; | ||
nodePromise.then(function (node) { | ||
node.port.postMessage({ id: id, type: 'play', data: data, loop: loop, mask: mask }); | ||
}); | ||
return { | ||
pause: function () { | ||
nodePromise.then(function (node) { return node.port.postMessage({ id: id, type: 'pause' }); }); | ||
}, | ||
resume: function () { | ||
nodePromise.then(function (node) { return node.port.postMessage({ id: id, type: 'resume' }); }); | ||
} | ||
}; | ||
} | ||
}; | ||
} | ||
/** | ||
* Create a BGM object | ||
* | ||
* When a BGM is played, it will immediately stop any previous BGM and SFX | ||
* | ||
* TODO: resume paused BGM | ||
* @param data Data block of a VGM file | ||
* @param loop Byte offset of the data block to loop back to upon completion. (-1 if no loop) | ||
*/ | ||
function bgm(data, loop) { | ||
if (loop === void 0) { loop = 0; } | ||
return track(data, loop); | ||
} | ||
APU.bgm = bgm; | ||
/** | ||
* Create an SFX object | ||
* | ||
* When a SFX is played, it will immediately stop any previous SFX | ||
* | ||
* It will also immediately take control away from the BGM for playing on channels, | ||
* and should silence those channels. When the SFX completes, it will give control | ||
* back to the BGM for all channels. | ||
* | ||
* Right now a channel mask is used for an SFX to declare which channels it intends | ||
* to use. A smarter mechanism may be used in the future, such as scanning the data. | ||
* @param data Data block of a VGM file | ||
* @param mask Array of four 0's or 1's that indicates which channels this SFX will be using | ||
*/ | ||
function sfx(data, mask) { | ||
if (mask === void 0) { mask = [1, 1, 1, 1]; } | ||
return track(data, -1, mask); | ||
} | ||
APU.sfx = sfx; | ||
/** | ||
* Creates a BGM object from an entire .vgm file contents, as an ArrayBuffer | ||
* @param arrayBuffer | ||
*/ | ||
function fromFile(arrayBuffer) { | ||
// make sure the 4-byte header is correct. | ||
// It should be "Vgm " (space at the end) | ||
var header = new Uint8Array(arrayBuffer, 0, 4); | ||
for (var i = 0; i < 4; ++i) { | ||
if (header[i] !== 'Vgm '.charCodeAt(i)) { | ||
throw new Error('Invalid header'); | ||
} | ||
} | ||
// get where vgm data starts. this is | ||
// (address of where vgm offset is stored, always 0x34) | ||
// + (value of vgm offset.) | ||
var data0 = 0x34 + new Uint32Array(arrayBuffer, 0x34, 1)[0]; | ||
// the loop point works similarly | ||
var loopPoint = 0x1c + new Uint32Array(arrayBuffer, 0x1c, 1)[0] - data0; | ||
// finally, the rest of the file is the data | ||
var data = arrayBuffer.slice(data0); | ||
return bgm(data, loopPoint); | ||
} | ||
APU.fromFile = fromFile; | ||
/** | ||
* Slowly fade out the BGM. This also immediately stops current | ||
* SFX, and prevents any new SFX from playing until completion. | ||
* @param millis Number of milliseconds for the fade to complete | ||
* @returns A promise that resolves when the fade has completed | ||
*/ | ||
function fade(millis) { | ||
if (millis === void 0) { millis = 2000; } | ||
// TODO: should be no-op if already fading | ||
return nodePromise.then(function (node) { | ||
// halt any currently-playing SFX | ||
sfx(new ArrayBuffer(0), [0, 0, 0, 0]).play(); | ||
if (millis > 0) { | ||
// disallow sfx until fade completes | ||
allowSFX = false; | ||
var _loop_1 = function (i) { | ||
var vol = 6 - i; | ||
setTimeout(function () { return node.port.postMessage({ type: 'write', layer: 0, register: 0x14, value: (vol << 4) + (vol) }); }, millis * i / 7); | ||
}; | ||
// use NR50 to fade out | ||
for (var i = 0; i <= 5; ++i) { | ||
_loop_1(i); | ||
} | ||
// stop sound with NR52 | ||
setTimeout(function () { | ||
node.port.postMessage({ type: 'write', layer: 0, register: 0x16, value: 0 }); | ||
// and clear song | ||
bgm(new ArrayBuffer(0), -1).play(); | ||
}, millis * 6 / 7); | ||
} | ||
// resolve | ||
return new Promise(function (resolve) { return setTimeout(resolve, millis); }) | ||
// ... and allow sfx once again | ||
.then(function () { allowSFX = true; }); | ||
}); | ||
} | ||
APU.fade = fade; | ||
function compile(commands) { | ||
} | ||
APU.compile = compile; | ||
})(APU || (APU = {})); |
101
index.d.ts
@@ -1,26 +0,81 @@ | ||
declare type APUTrackMask = [0 | 1, 0 | 1, 0 | 1, 0 | 1]; | ||
export declare const C3 = 44, Cs3 = 156, D3 = 263, Ds3 = 363, E3 = 457, F3 = 547, Fs3 = 631, G3 = 710, Gs3 = 786, A3 = 856, As3 = 923, B3 = 986, C4 = 1046, Cs4 = 1102, D4 = 1155, Ds4 = 1205, E4 = 1253, F4 = 1297, Fs4 = 1339, G4 = 1379, Gs4 = 1417, A4 = 1452, As4 = 1486, B4 = 1517, C5 = 1547, Cs5 = 1575, D5 = 1602, Ds5 = 1627, E5 = 1650, F5 = 1673, Fs5 = 1694, G5 = 1714, Gs5 = 1732, A5 = 1750, As5 = 1767, B5 = 1783, C6 = 1798, Cs6 = 1812, D6 = 1825, Ds6 = 1837, E6 = 1849, F6 = 1860, Fs6 = 1871, G6 = 1881, Gs6 = 1890, A6 = 1899, As6 = 1907, B6 = 1915, C7 = 1923, Cs7 = 1930, D7 = 1936, Ds7 = 1943, E7 = 1949, F7 = 1954, Fs7 = 1959, G7 = 1964, Gs7 = 1969, A7 = 1974, As7 = 1978, B7 = 1982, C8 = 1985, Cs8 = 1989, D8 = 1992, Ds8 = 1995, E8 = 1998, F8 = 2001, Fs8 = 2004, G8 = 2006, Gs8 = 2009, A8 = 2011, As8 = 2013, B8 = 2015; | ||
export declare const audioContext: AudioContext; | ||
export declare function allow(): void; | ||
export declare function changeUserVolume(newVolume: number): void; | ||
export declare const audioNode: AudioNode; | ||
export declare function bgm(data: ArrayBuffer, loop?: number): { | ||
play(): { | ||
pause(): void; | ||
resume(): void; | ||
declare namespace APU { | ||
type APUTrackMask = [0 | 1, 0 | 1, 0 | 1, 0 | 1]; | ||
export const C3 = 44, Cs3 = 156, D3 = 263, Ds3 = 363, E3 = 457, F3 = 547, Fs3 = 631, G3 = 710, Gs3 = 786, A3 = 856, As3 = 923, B3 = 986, C4 = 1046, Cs4 = 1102, D4 = 1155, Ds4 = 1205, E4 = 1253, F4 = 1297, Fs4 = 1339, G4 = 1379, Gs4 = 1417, A4 = 1452, As4 = 1486, B4 = 1517, C5 = 1547, Cs5 = 1575, D5 = 1602, Ds5 = 1627, E5 = 1650, F5 = 1673, Fs5 = 1694, G5 = 1714, Gs5 = 1732, A5 = 1750, As5 = 1767, B5 = 1783, C6 = 1798, Cs6 = 1812, D6 = 1825, Ds6 = 1837, E6 = 1849, F6 = 1860, Fs6 = 1871, G6 = 1881, Gs6 = 1890, A6 = 1899, As6 = 1907, B6 = 1915, C7 = 1923, Cs7 = 1930, D7 = 1936, Ds7 = 1943, E7 = 1949, F7 = 1954, Fs7 = 1959, G7 = 1964, Gs7 = 1969, A7 = 1974, As7 = 1978, B7 = 1982, C8 = 1985, Cs8 = 1989, D8 = 1992, Ds8 = 1995, E8 = 1998, F8 = 2001, Fs8 = 2004, G8 = 2006, Gs8 = 2009, A8 = 2011, As8 = 2013, B8 = 2015; | ||
/** | ||
* Audio Context that all APU stuff runs on | ||
*/ | ||
export const audioContext: AudioContext; | ||
/** | ||
* Resumes the audio context. Should be called as a result of some user event, like a click. | ||
* Until this is called, the browser won't allow any sound to play. | ||
*/ | ||
export function allow(): void; | ||
/** | ||
* Volume multiplier intended to be changed by a user-facing volume control | ||
* @param newVolume Value between 0 and 1 | ||
*/ | ||
export function changeUserVolume(newVolume: number): void; | ||
/** | ||
* The last audio node, which is connected to the AudioContext's destination | ||
*/ | ||
export const audioNode: AudioNode; | ||
/** | ||
* Create a BGM object | ||
* | ||
* When a BGM is played, it will immediately stop any previous BGM and SFX | ||
* | ||
* TODO: resume paused BGM | ||
* @param data Data block of a VGM file | ||
* @param loop Byte offset of the data block to loop back to upon completion. (-1 if no loop) | ||
*/ | ||
export function bgm(data: ArrayBuffer, loop?: number): { | ||
play(): { | ||
pause(): void; | ||
resume(): void; | ||
}; | ||
}; | ||
}; | ||
export declare function sfx(data: ArrayBuffer, mask?: APUTrackMask): { | ||
play(): { | ||
pause(): void; | ||
resume(): void; | ||
/** | ||
* Create an SFX object | ||
* | ||
* When a SFX is played, it will immediately stop any previous SFX | ||
* | ||
* It will also immediately take control away from the BGM for playing on channels, | ||
* and should silence those channels. When the SFX completes, it will give control | ||
* back to the BGM for all channels. | ||
* | ||
* Right now a channel mask is used for an SFX to declare which channels it intends | ||
* to use. A smarter mechanism may be used in the future, such as scanning the data. | ||
* @param data Data block of a VGM file | ||
* @param mask Array of four 0's or 1's that indicates which channels this SFX will be using | ||
*/ | ||
export function sfx(data: ArrayBuffer, mask?: APUTrackMask): { | ||
play(): { | ||
pause(): void; | ||
resume(): void; | ||
}; | ||
}; | ||
}; | ||
export declare function fromFile(arrayBuffer: ArrayBuffer): { | ||
play(): { | ||
pause(): void; | ||
resume(): void; | ||
/** | ||
* Creates a BGM object from an entire .vgm file contents, as an ArrayBuffer | ||
* @param arrayBuffer | ||
*/ | ||
export function fromFile(arrayBuffer: ArrayBuffer): { | ||
play(): { | ||
pause(): void; | ||
resume(): void; | ||
}; | ||
}; | ||
}; | ||
export declare function fade(millis: number): Promise<void>; | ||
export {}; | ||
/** | ||
* Slowly fade out the BGM. This also immediately stops current | ||
* SFX, and prevents any new SFX from playing until completion. | ||
* @param millis Number of milliseconds for the fade to complete | ||
* @returns A promise that resolves when the fade has completed | ||
*/ | ||
export function fade(millis?: number): Promise<void>; | ||
type APUWait = number; | ||
type APUCommand = APUPulseCommand | APUWaveCommand | APUNoiseCommand; | ||
type APUPulseCommand = {}; | ||
type APUWaveCommand = {}; | ||
type APUNoiseCommand = {}; | ||
export function compile(commands: (APUCommand | APUWait)[]): void; | ||
export {}; | ||
} |
{ | ||
"name": "apu", | ||
"version": "0.2.19", | ||
"version": "0.2.20", | ||
"description": "Easy 3 kB library for 98% accurate Gameboy audio", | ||
@@ -11,7 +11,7 @@ "browser": "dist/apu.js", | ||
"scripts": { | ||
"start": "webpack-dev-server --mode=development", | ||
"build": "npm run build-browser && npm run build-typings", | ||
"build-browser": "webpack --mode=production", | ||
"build-typings": "tsc --emitDeclarationOnly --declaration lib/index.ts --outDir .", | ||
"lint": "eslint '**/*.js' '**/*.ts'", | ||
"start": "concurrently --names serve,watch 'npm run serve' 'npm run watch'", | ||
"serve": "live-server example", | ||
"watch": "nodemon -w ./lib -e '*' -x 'make || exit 1'", | ||
"build": "make", | ||
"lint": "eslint 'lib/*.js' 'lib/*.ts'", | ||
"prepublishOnly": "npm run build" | ||
@@ -23,4 +23,4 @@ }, | ||
}, | ||
"author": "Nigel Nelson, Grant Galitz", | ||
"license": "MIT", | ||
"author": "Nigel Nelson", | ||
"license": "BSD-3-Clause", | ||
"bugs": { | ||
@@ -31,2 +31,3 @@ "url": "https://github.com/shamblesides/apu/issues" | ||
"devDependencies": { | ||
"@babel/cli": "^7.10.1", | ||
"@babel/core": "^7.4.5", | ||
@@ -37,20 +38,10 @@ "@babel/preset-env": "^7.4.5", | ||
"@typescript-eslint/parser": "^2.34.0", | ||
"babel-loader": "^8.0.6", | ||
"clean-webpack-plugin": "^3.0.0", | ||
"concurrently": "^5.2.0", | ||
"ejs": "^3.1.3", | ||
"eslint": "^5.16.0", | ||
"file-loader": "^6.0.0", | ||
"html-webpack-plugin": "^3.2.0", | ||
"raw-loader": "^4.0.1", | ||
"live-server": "^1.2.1", | ||
"nodemon": "^2.0.4", | ||
"terser": "^4.7.0", | ||
"ts-loader": "^7.0.4", | ||
"typescript": "^3.9.2", | ||
"url-loader": "^4.1.0", | ||
"webpack": "^4.33.0", | ||
"webpack-cli": "^3.3.4", | ||
"webpack-dev-server": "^3.7.1" | ||
"typescript": "^3.9.2" | ||
}, | ||
"eslintIgnore": [ | ||
"./webpack.config.js", | ||
"./dist" | ||
], | ||
"browserslist": [ | ||
@@ -57,0 +48,0 @@ "last 2 versions and not dead and > 0.5% in US", |
@@ -1,50 +0,68 @@ | ||
JavaScript GameBoy Color Emulator | ||
================================= | ||
APU | ||
=== | ||
**Copyright (C) 2010 - 2016 Grant Galitz** | ||
Want some hardware-accurate Gameboy music and sounds in your HTML5 game or app? Don't want to load megabytes of .mp3 files? [Overwhelmed or frustrated](https://blog.mecheye.net/2017/09/i-dont-know-who-the-web-audio-api-is-designed-for/) by the Web Audio API? Welcome to **apu**! | ||
A GameBoy Color emulator that utilizes HTML5 canvas and JavaScript audio APIs to provide a full emulation of the console. | ||
**License:** | ||
Features | ||
-------- | ||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | ||
* Tiny; single .js file, about 9 kB (gzip) | ||
* Supports playing .vgm files (which are typically a few kB after gzip) | ||
* Mute BGM channels while playing SFX | ||
* Highly performant | ||
* * Fast sample generation in WebAssembly | ||
* * When possible, uses AudioWorklet to run completely outside the main thread (works in latest Chrome and FireFox) | ||
* UMD module; works as script tag, AMD module, in webpack, etc | ||
* TypeScript bindings | ||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
Browser support | ||
--------------- | ||
Known browsers to work well in: | ||
------------------------------- | ||
Latest Chrome, Safari, Firefox | ||
* Firefox 4-27 (Windows 7, Windows Vista, Mac OS X) | ||
* Google Chrome 18+ | ||
* Safari 5.1.5+ | ||
Browsers that suck at performance or fail to run the code correctly: | ||
-------------------------------------------------------------------- | ||
Developing | ||
---------- | ||
* Firefox 4+ (*nix versions of Firefox have audio lockup bugs) - Retest this | ||
* Firefox 28+ (Web Audio API creates 500 ms or greater latency, forced by Firefox) | ||
* Opera (Crashes + Slow + Graphics Glitches) - Retest this | ||
* Safari 5.1.X (Below 5.1.5) (Slow or crashes) | ||
* IE 1-8 (Cannot run) | ||
* IE 9-10 (Slow, No native audio support (Requires flash bridge in the audio lib)) | ||
* IE 11 (No native audio support (Requires flash bridge in the audio lib)) | ||
* Firefox 1-3.6 (Slow) | ||
* ALL VERSIONS OF MOBILE SAFARI AND OPERA (Stop pestering me, iOS just **CAN'T** run this well.) | ||
To develop this project you'll need: | ||
CPU instruction set accuracy test results (Blargg's cpu_instrs.gb test ROM): | ||
----------------------------------------------------- | ||
* Unix system (MacOS and Ubuntu definitely work) | ||
* Node 12+ (older versions may work but untested) | ||
* Make | ||
* Clang | ||
* LLVM 8+ (should include wasm-ld; or, on Ubuntu 20.04, wasm-ld-10) | ||
* Binaryen (should include wasm-opt) | ||
* **GameBoy Online:** | ||
To build it: | ||
```sh | ||
make | ||
``` | ||
![GameBoy Online (This emulator)](http://i.imgur.com/ivs7F.png "Passes") | ||
* **Visual Boy Advance 1.7.2:** | ||
To watch & rebuild: | ||
```sh | ||
npm run watch | ||
``` | ||
![Visual Boy Advance 1.7.2](http://i.imgur.com/NYnYu.png "Fails") | ||
* **KiGB:** | ||
To watch, rebuild, and run a live-updating web server: | ||
```sh | ||
npm start | ||
``` | ||
![KiGB](http://i.imgur.com/eYHDH.png "Fails") | ||
* **Gambatte:** | ||
Troubleshooting: | ||
![Gambatte](http://i.imgur.com/vGHFz.png "Passes") | ||
* On Mac, when installing llvm through Brew, you might find that wasm-ld is still not available. Try `brew link --force llvm` | ||
Acknowledgments | ||
--------------- | ||
The high-performance WebAssembly bundle for emulating the GameBoy's APU is compiled from C code that was adapted from | ||
an old version of VGMPlay, which was written by Anthony Kruize in 2002. Without that code, this module would not be | ||
nearly as performant nor as accurate as it is today. | ||
License | ||
------- | ||
[BSD 3-Clause](/LICENSE) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
97401
13
8
721
69
3