Studytime171 commited on
Commit
d9f8c7b
·
verified ·
1 Parent(s): d344831

Upload 10 files

Browse files
.gitattributes CHANGED
@@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ b2_download_file_by_id.iso filter=lfs diff=lfs merge=lfs -text
37
+ VirtualXP.iso filter=lfs diff=lfs merge=lfs -text
VirtualXP.iso ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d21665dfe3585e46c95bfe5ba45495e8ceccce3e2bc92fd993bbfaa011a216a5
3
+ size 45568000
VirtualXP.js ADDED
@@ -0,0 +1 @@
 
 
1
+ var Module=typeof Module!=="undefined"?Module:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=require("path").dirname(scriptDirectory)+"/"}else{scriptDirectory=__dirname+"/"}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=require("fs");if(!nodePath)nodePath=require("path");filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/")}arguments_=process["argv"].slice(2);if(typeof module!=="undefined"){module["exports"]=Module}process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status)};Module["inspect"]=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)}}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs}else if(typeof arguments!="undefined"){arguments_=arguments}if(typeof quit==="function"){quit_=function(status){quit(status)}}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!=="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1)}else{scriptDirectory=""}{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)}}setWindowTitle=function(title){}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;err(text)}}var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(typeof WebAssembly!=="object"){abort("no native wasm support detected")}var wasmMemory;var ABORT=false;var EXITSTATUS=0;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}var UTF8Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf8"):undefined;function UTF8ArrayToString(heap,idx,maxBytesToRead){var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heap[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heap.subarray&&UTF8Decoder){return UTF8Decoder.decode(heap.subarray(idx,endPtr))}else{var str="";while(idx<endPtr){var u0=heap[idx++];if(!(u0&128)){str+=String.fromCharCode(u0);continue}var u1=heap[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}var u2=heap[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2}else{u0=(u0&7)<<18|u1<<12|u2<<6|heap[idx++]&63}if(u0<65536){str+=String.fromCharCode(u0)}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i<str.length;++i){var u=str.charCodeAt(i);if(u>=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx}function lengthBytesUTF8(str){var len=0;for(var i=0;i<str.length;++i){var u=str.charCodeAt(i);if(u>=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4}return len}function allocateUTF8(str){var size=lengthBytesUTF8(str)+1;var ret=_malloc(size);if(ret)stringToUTF8Array(str,HEAP8,ret,size);return ret}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf)}var INITIAL_MEMORY=Module["INITIAL_MEMORY"]||268435456;if(Module["wasmMemory"]){wasmMemory=Module["wasmMemory"]}else{wasmMemory=new WebAssembly.Memory({"initial":INITIAL_MEMORY/65536,"maximum":INITIAL_MEMORY/65536})}if(wasmMemory){buffer=wasmMemory.buffer}INITIAL_MEMORY=buffer.byteLength;updateGlobalBufferAndViews(buffer);var wasmTable;var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){runtimeExited=true}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function getUniqueRunDependency(id){return id}function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what+="";err(what);ABORT=true;EXITSTATUS=1;what="abort("+what+"). Build with -s ASSERTIONS=1 for more info.";var e=new WebAssembly.RuntimeError(what);throw e}function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="VirtualXP.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw"both async and sync fetching of the wasm failed"}}catch(err){abort(err)}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw"failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return Promise.resolve().then(getBinary)}function createWasm(){var info={"a":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmTable=Module["asm"]["s"];removeRunDependency("wasm-instantiate")}addRunDependency("wasm-instantiate");function receiveInstantiatedSource(output){receiveInstance(output["instance"])}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason)})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(receiveInstantiatedSource)})})}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return{}}var tempDouble;var tempI64;var ASM_CONSTS={1386:function($0,$1,$2){window["loadFile"]($0,$1,$2)},1422:function($0,$1,$2){window["saveFile"]($0,$1,$2)},2444:function($0,$1,$2){window["drives"][$0]["flushReadQueue"]($1,$2)},2517:function($0,$1,$2,$3,$4){return window["drives"][$0]["readCache"]($1,$2,$3,$4)|0},2583:function($0,$1,$2){return window["drives"][$0]["readQueue"]($1,$2)},2682:function($0,$1,$2,$3,$4){return window["drives"][$0]["writeCache"]($1,$2,$3,$4)},2820:function($0,$1,$2){window["update_size"]($0,$1,$2)},2859:function(){window["update_screen"]()},3298:function($0,$1,$2){window["load_file_xhr"]($0,$1,$2)},3551:function($0,$1,$2){window["drive_init"]($0,$1,$2)}};function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){wasmTable.get(func)()}else{wasmTable.get(func)(callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}var PATH={splitPath:function(filename){var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:function(parts,allowAboveRoot){var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:function(path){var isAbsolute=path.charAt(0)==="/",trailingSlash=path.substr(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(function(p){return!!p}),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:function(path){var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir},basename:function(path){if(path==="/")return"/";path=PATH.normalize(path);path=path.replace(/\/$/,"");var lastSlash=path.lastIndexOf("/");if(lastSlash===-1)return path;return path.substr(lastSlash+1)},extname:function(path){return PATH.splitPath(path)[3]},join:function(){var paths=Array.prototype.slice.call(arguments,0);return PATH.normalize(paths.join("/"))},join2:function(l,r){return PATH.normalize(l+"/"+r)}};function _emscripten_set_main_loop_timing(mode,value){Browser.mainLoop.timingMode=mode;Browser.mainLoop.timingValue=value;if(!Browser.mainLoop.func){return 1}if(mode==0){Browser.mainLoop.scheduler=function Browser_mainLoop_scheduler_setTimeout(){var timeUntilNextTick=Math.max(0,Browser.mainLoop.tickStartTime+value-_emscripten_get_now())|0;setTimeout(Browser.mainLoop.runner,timeUntilNextTick)};Browser.mainLoop.method="timeout"}else if(mode==1){Browser.mainLoop.scheduler=function Browser_mainLoop_scheduler_rAF(){Browser.requestAnimationFrame(Browser.mainLoop.runner)};Browser.mainLoop.method="rAF"}else if(mode==2){if(typeof setImmediate==="undefined"){var setImmediates=[];var emscriptenMainLoopMessageId="setimmediate";var Browser_setImmediate_messageHandler=function(event){if(event.data===emscriptenMainLoopMessageId||event.data.target===emscriptenMainLoopMessageId){event.stopPropagation();setImmediates.shift()()}};addEventListener("message",Browser_setImmediate_messageHandler,true);setImmediate=function Browser_emulated_setImmediate(func){setImmediates.push(func);if(ENVIRONMENT_IS_WORKER){if(Module["setImmediates"]===undefined)Module["setImmediates"]=[];Module["setImmediates"].push(func);postMessage({target:emscriptenMainLoopMessageId})}else postMessage(emscriptenMainLoopMessageId,"*")}}Browser.mainLoop.scheduler=function Browser_mainLoop_scheduler_setImmediate(){setImmediate(Browser.mainLoop.runner)};Browser.mainLoop.method="immediate"}return 0}function setMainLoop(browserIterationFunc,fps,simulateInfiniteLoop,arg,noSetTiming){noExitRuntime=true;assert(!Browser.mainLoop.func,"emscripten_set_main_loop: there can only be one main loop function at once: call emscripten_cancel_main_loop to cancel the previous one before setting a new one with different parameters.");Browser.mainLoop.func=browserIterationFunc;Browser.mainLoop.arg=arg;var thisMainLoopId=Browser.mainLoop.currentlyRunningMainloop;Browser.mainLoop.runner=function Browser_mainLoop_runner(){if(ABORT)return;if(Browser.mainLoop.queue.length>0){var start=Date.now();var blocker=Browser.mainLoop.queue.shift();blocker.func(blocker.arg);if(Browser.mainLoop.remainingBlockers){var remaining=Browser.mainLoop.remainingBlockers;var next=remaining%1==0?remaining-1:Math.floor(remaining);if(blocker.counted){Browser.mainLoop.remainingBlockers=next}else{next=next+.5;Browser.mainLoop.remainingBlockers=(8*remaining+next)/9}}console.log('main loop blocker "'+blocker.name+'" took '+(Date.now()-start)+" ms");Browser.mainLoop.updateStatus();if(thisMainLoopId<Browser.mainLoop.currentlyRunningMainloop)return;setTimeout(Browser.mainLoop.runner,0);return}if(thisMainLoopId<Browser.mainLoop.currentlyRunningMainloop)return;Browser.mainLoop.currentFrameNumber=Browser.mainLoop.currentFrameNumber+1|0;if(Browser.mainLoop.timingMode==1&&Browser.mainLoop.timingValue>1&&Browser.mainLoop.currentFrameNumber%Browser.mainLoop.timingValue!=0){Browser.mainLoop.scheduler();return}else if(Browser.mainLoop.timingMode==0){Browser.mainLoop.tickStartTime=_emscripten_get_now()}Browser.mainLoop.runIter(browserIterationFunc);if(thisMainLoopId<Browser.mainLoop.currentlyRunningMainloop)return;if(typeof SDL==="object"&&SDL.audio&&SDL.audio.queueNewAudioData)SDL.audio.queueNewAudioData();Browser.mainLoop.scheduler()};if(!noSetTiming){if(fps&&fps>0)_emscripten_set_main_loop_timing(0,1e3/fps);else _emscripten_set_main_loop_timing(1,1);Browser.mainLoop.scheduler()}if(simulateInfiniteLoop){throw"unwind"}}var Browser={mainLoop:{scheduler:null,method:"",currentlyRunningMainloop:0,func:null,arg:0,timingMode:0,timingValue:0,currentFrameNumber:0,queue:[],pause:function(){Browser.mainLoop.scheduler=null;Browser.mainLoop.currentlyRunningMainloop++},resume:function(){Browser.mainLoop.currentlyRunningMainloop++;var timingMode=Browser.mainLoop.timingMode;var timingValue=Browser.mainLoop.timingValue;var func=Browser.mainLoop.func;Browser.mainLoop.func=null;setMainLoop(func,0,false,Browser.mainLoop.arg,true);_emscripten_set_main_loop_timing(timingMode,timingValue);Browser.mainLoop.scheduler()},updateStatus:function(){if(Module["setStatus"]){var message=Module["statusMessage"]||"Please wait...";var remaining=Browser.mainLoop.remainingBlockers;var expected=Browser.mainLoop.expectedBlockers;if(remaining){if(remaining<expected){Module["setStatus"](message+" ("+(expected-remaining)+"/"+expected+")")}else{Module["setStatus"](message)}}else{Module["setStatus"]("")}}},runIter:function(func){if(ABORT)return;if(Module["preMainLoop"]){var preRet=Module["preMainLoop"]();if(preRet===false){return}}try{func()}catch(e){if(e instanceof ExitStatus){return}else if(e=="unwind"){return}else{if(e&&typeof e==="object"&&e.stack)err("exception thrown: "+[e,e.stack]);throw e}}if(Module["postMainLoop"])Module["postMainLoop"]()}},isFullscreen:false,pointerLock:false,moduleContextCreatedCallbacks:[],workers:[],init:function(){if(!Module["preloadPlugins"])Module["preloadPlugins"]=[];if(Browser.initted)return;Browser.initted=true;try{new Blob;Browser.hasBlobConstructor=true}catch(e){Browser.hasBlobConstructor=false;console.log("warning: no blob constructor, cannot create blobs with mimetypes")}Browser.BlobBuilder=typeof MozBlobBuilder!="undefined"?MozBlobBuilder:typeof WebKitBlobBuilder!="undefined"?WebKitBlobBuilder:!Browser.hasBlobConstructor?console.log("warning: no BlobBuilder"):null;Browser.URLObject=typeof window!="undefined"?window.URL?window.URL:window.webkitURL:undefined;if(!Module.noImageDecoding&&typeof Browser.URLObject==="undefined"){console.log("warning: Browser does not support creating object URLs. Built-in browser image decoding will not be available.");Module.noImageDecoding=true}var imagePlugin={};imagePlugin["canHandle"]=function imagePlugin_canHandle(name){return!Module.noImageDecoding&&/\.(jpg|jpeg|png|bmp)$/i.test(name)};imagePlugin["handle"]=function imagePlugin_handle(byteArray,name,onload,onerror){var b=null;if(Browser.hasBlobConstructor){try{b=new Blob([byteArray],{type:Browser.getMimetype(name)});if(b.size!==byteArray.length){b=new Blob([new Uint8Array(byteArray).buffer],{type:Browser.getMimetype(name)})}}catch(e){warnOnce("Blob constructor present but fails: "+e+"; falling back to blob builder")}}if(!b){var bb=new Browser.BlobBuilder;bb.append(new Uint8Array(byteArray).buffer);b=bb.getBlob()}var url=Browser.URLObject.createObjectURL(b);var img=new Image;img.onload=function img_onload(){assert(img.complete,"Image "+name+" could not be decoded");var canvas=document.createElement("canvas");canvas.width=img.width;canvas.height=img.height;var ctx=canvas.getContext("2d");ctx.drawImage(img,0,0);Module["preloadedImages"][name]=canvas;Browser.URLObject.revokeObjectURL(url);if(onload)onload(byteArray)};img.onerror=function img_onerror(event){console.log("Image "+url+" could not be decoded");if(onerror)onerror()};img.src=url};Module["preloadPlugins"].push(imagePlugin);var audioPlugin={};audioPlugin["canHandle"]=function audioPlugin_canHandle(name){return!Module.noAudioDecoding&&name.substr(-4)in{".ogg":1,".wav":1,".mp3":1}};audioPlugin["handle"]=function audioPlugin_handle(byteArray,name,onload,onerror){var done=false;function finish(audio){if(done)return;done=true;Module["preloadedAudios"][name]=audio;if(onload)onload(byteArray)}function fail(){if(done)return;done=true;Module["preloadedAudios"][name]=new Audio;if(onerror)onerror()}if(Browser.hasBlobConstructor){try{var b=new Blob([byteArray],{type:Browser.getMimetype(name)})}catch(e){return fail()}var url=Browser.URLObject.createObjectURL(b);var audio=new Audio;audio.addEventListener("canplaythrough",function(){finish(audio)},false);audio.onerror=function audio_onerror(event){if(done)return;console.log("warning: browser could not fully decode audio "+name+", trying slower base64 approach");function encode64(data){var BASE="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";var PAD="=";var ret="";var leftchar=0;var leftbits=0;for(var i=0;i<data.length;i++){leftchar=leftchar<<8|data[i];leftbits+=8;while(leftbits>=6){var curr=leftchar>>leftbits-6&63;leftbits-=6;ret+=BASE[curr]}}if(leftbits==2){ret+=BASE[(leftchar&3)<<4];ret+=PAD+PAD}else if(leftbits==4){ret+=BASE[(leftchar&15)<<2];ret+=PAD}return ret}audio.src="data:audio/x-"+name.substr(-3)+";base64,"+encode64(byteArray);finish(audio)};audio.src=url;Browser.safeSetTimeout(function(){finish(audio)},1e4)}else{return fail()}};Module["preloadPlugins"].push(audioPlugin);function pointerLockChange(){Browser.pointerLock=document["pointerLockElement"]===Module["canvas"]||document["mozPointerLockElement"]===Module["canvas"]||document["webkitPointerLockElement"]===Module["canvas"]||document["msPointerLockElement"]===Module["canvas"]}var canvas=Module["canvas"];if(canvas){canvas.requestPointerLock=canvas["requestPointerLock"]||canvas["mozRequestPointerLock"]||canvas["webkitRequestPointerLock"]||canvas["msRequestPointerLock"]||function(){};canvas.exitPointerLock=document["exitPointerLock"]||document["mozExitPointerLock"]||document["webkitExitPointerLock"]||document["msExitPointerLock"]||function(){};canvas.exitPointerLock=canvas.exitPointerLock.bind(document);document.addEventListener("pointerlockchange",pointerLockChange,false);document.addEventListener("mozpointerlockchange",pointerLockChange,false);document.addEventListener("webkitpointerlockchange",pointerLockChange,false);document.addEventListener("mspointerlockchange",pointerLockChange,false);if(Module["elementPointerLock"]){canvas.addEventListener("click",function(ev){if(!Browser.pointerLock&&Module["canvas"].requestPointerLock){Module["canvas"].requestPointerLock();ev.preventDefault()}},false)}}},createContext:function(canvas,useWebGL,setInModule,webGLContextAttributes){if(useWebGL&&Module.ctx&&canvas==Module.canvas)return Module.ctx;var ctx;var contextHandle;if(useWebGL){var contextAttributes={antialias:false,alpha:false,majorVersion:1};if(webGLContextAttributes){for(var attribute in webGLContextAttributes){contextAttributes[attribute]=webGLContextAttributes[attribute]}}if(typeof GL!=="undefined"){contextHandle=GL.createContext(canvas,contextAttributes);if(contextHandle){ctx=GL.getContext(contextHandle).GLctx}}}else{ctx=canvas.getContext("2d")}if(!ctx)return null;if(setInModule){if(!useWebGL)assert(typeof GLctx==="undefined","cannot set in module if GLctx is used, but we are a non-GL context that would replace it");Module.ctx=ctx;if(useWebGL)GL.makeContextCurrent(contextHandle);Module.useWebGL=useWebGL;Browser.moduleContextCreatedCallbacks.forEach(function(callback){callback()});Browser.init()}return ctx},destroyContext:function(canvas,useWebGL,setInModule){},fullscreenHandlersInstalled:false,lockPointer:undefined,resizeCanvas:undefined,requestFullscreen:function(lockPointer,resizeCanvas){Browser.lockPointer=lockPointer;Browser.resizeCanvas=resizeCanvas;if(typeof Browser.lockPointer==="undefined")Browser.lockPointer=true;if(typeof Browser.resizeCanvas==="undefined")Browser.resizeCanvas=false;var canvas=Module["canvas"];function fullscreenChange(){Browser.isFullscreen=false;var canvasContainer=canvas.parentNode;if((document["fullscreenElement"]||document["mozFullScreenElement"]||document["msFullscreenElement"]||document["webkitFullscreenElement"]||document["webkitCurrentFullScreenElement"])===canvasContainer){canvas.exitFullscreen=Browser.exitFullscreen;if(Browser.lockPointer)canvas.requestPointerLock();Browser.isFullscreen=true;if(Browser.resizeCanvas){Browser.setFullscreenCanvasSize()}else{Browser.updateCanvasDimensions(canvas)}}else{canvasContainer.parentNode.insertBefore(canvas,canvasContainer);canvasContainer.parentNode.removeChild(canvasContainer);if(Browser.resizeCanvas){Browser.setWindowedCanvasSize()}else{Browser.updateCanvasDimensions(canvas)}}if(Module["onFullScreen"])Module["onFullScreen"](Browser.isFullscreen);if(Module["onFullscreen"])Module["onFullscreen"](Browser.isFullscreen)}if(!Browser.fullscreenHandlersInstalled){Browser.fullscreenHandlersInstalled=true;document.addEventListener("fullscreenchange",fullscreenChange,false);document.addEventListener("mozfullscreenchange",fullscreenChange,false);document.addEventListener("webkitfullscreenchange",fullscreenChange,false);document.addEventListener("MSFullscreenChange",fullscreenChange,false)}var canvasContainer=document.createElement("div");canvas.parentNode.insertBefore(canvasContainer,canvas);canvasContainer.appendChild(canvas);canvasContainer.requestFullscreen=canvasContainer["requestFullscreen"]||canvasContainer["mozRequestFullScreen"]||canvasContainer["msRequestFullscreen"]||(canvasContainer["webkitRequestFullscreen"]?function(){canvasContainer["webkitRequestFullscreen"](Element["ALLOW_KEYBOARD_INPUT"])}:null)||(canvasContainer["webkitRequestFullScreen"]?function(){canvasContainer["webkitRequestFullScreen"](Element["ALLOW_KEYBOARD_INPUT"])}:null);canvasContainer.requestFullscreen()},exitFullscreen:function(){if(!Browser.isFullscreen){return false}var CFS=document["exitFullscreen"]||document["cancelFullScreen"]||document["mozCancelFullScreen"]||document["msExitFullscreen"]||document["webkitCancelFullScreen"]||function(){};CFS.apply(document,[]);return true},nextRAF:0,fakeRequestAnimationFrame:function(func){var now=Date.now();if(Browser.nextRAF===0){Browser.nextRAF=now+1e3/60}else{while(now+2>=Browser.nextRAF){Browser.nextRAF+=1e3/60}}var delay=Math.max(Browser.nextRAF-now,0);setTimeout(func,delay)},requestAnimationFrame:function(func){if(typeof requestAnimationFrame==="function"){requestAnimationFrame(func);return}var RAF=Browser.fakeRequestAnimationFrame;RAF(func)},safeCallback:function(func){return function(){if(!ABORT)return func.apply(null,arguments)}},allowAsyncCallbacks:true,queuedAsyncCallbacks:[],pauseAsyncCallbacks:function(){Browser.allowAsyncCallbacks=false},resumeAsyncCallbacks:function(){Browser.allowAsyncCallbacks=true;if(Browser.queuedAsyncCallbacks.length>0){var callbacks=Browser.queuedAsyncCallbacks;Browser.queuedAsyncCallbacks=[];callbacks.forEach(function(func){func()})}},safeRequestAnimationFrame:function(func){return Browser.requestAnimationFrame(function(){if(ABORT)return;if(Browser.allowAsyncCallbacks){func()}else{Browser.queuedAsyncCallbacks.push(func)}})},safeSetTimeout:function(func,timeout){noExitRuntime=true;return setTimeout(function(){if(ABORT)return;if(Browser.allowAsyncCallbacks){func()}else{Browser.queuedAsyncCallbacks.push(func)}},timeout)},safeSetInterval:function(func,timeout){noExitRuntime=true;return setInterval(function(){if(ABORT)return;if(Browser.allowAsyncCallbacks){func()}},timeout)},getMimetype:function(name){return{"jpg":"image/jpeg","jpeg":"image/jpeg","png":"image/png","bmp":"image/bmp","ogg":"audio/ogg","wav":"audio/wav","mp3":"audio/mpeg"}[name.substr(name.lastIndexOf(".")+1)]},getUserMedia:function(func){if(!window.getUserMedia){window.getUserMedia=navigator["getUserMedia"]||navigator["mozGetUserMedia"]}window.getUserMedia(func)},getMovementX:function(event){return event["movementX"]||event["mozMovementX"]||event["webkitMovementX"]||0},getMovementY:function(event){return event["movementY"]||event["mozMovementY"]||event["webkitMovementY"]||0},getMouseWheelDelta:function(event){var delta=0;switch(event.type){case"DOMMouseScroll":delta=event.detail/3;break;case"mousewheel":delta=event.wheelDelta/120;break;case"wheel":delta=event.deltaY;switch(event.deltaMode){case 0:delta/=100;break;case 1:delta/=3;break;case 2:delta*=80;break;default:throw"unrecognized mouse wheel delta mode: "+event.deltaMode}break;default:throw"unrecognized mouse wheel event: "+event.type}return delta},mouseX:0,mouseY:0,mouseMovementX:0,mouseMovementY:0,touches:{},lastTouches:{},calculateMouseEvent:function(event){if(Browser.pointerLock){if(event.type!="mousemove"&&"mozMovementX"in event){Browser.mouseMovementX=Browser.mouseMovementY=0}else{Browser.mouseMovementX=Browser.getMovementX(event);Browser.mouseMovementY=Browser.getMovementY(event)}if(typeof SDL!="undefined"){Browser.mouseX=SDL.mouseX+Browser.mouseMovementX;Browser.mouseY=SDL.mouseY+Browser.mouseMovementY}else{Browser.mouseX+=Browser.mouseMovementX;Browser.mouseY+=Browser.mouseMovementY}}else{var rect=Module["canvas"].getBoundingClientRect();var cw=Module["canvas"].width;var ch=Module["canvas"].height;var scrollX=typeof window.scrollX!=="undefined"?window.scrollX:window.pageXOffset;var scrollY=typeof window.scrollY!=="undefined"?window.scrollY:window.pageYOffset;if(event.type==="touchstart"||event.type==="touchend"||event.type==="touchmove"){var touch=event.touch;if(touch===undefined){return}var adjustedX=touch.pageX-(scrollX+rect.left);var adjustedY=touch.pageY-(scrollY+rect.top);adjustedX=adjustedX*(cw/rect.width);adjustedY=adjustedY*(ch/rect.height);var coords={x:adjustedX,y:adjustedY};if(event.type==="touchstart"){Browser.lastTouches[touch.identifier]=coords;Browser.touches[touch.identifier]=coords}else if(event.type==="touchend"||event.type==="touchmove"){var last=Browser.touches[touch.identifier];if(!last)last=coords;Browser.lastTouches[touch.identifier]=last;Browser.touches[touch.identifier]=coords}return}var x=event.pageX-(scrollX+rect.left);var y=event.pageY-(scrollY+rect.top);x=x*(cw/rect.width);y=y*(ch/rect.height);Browser.mouseMovementX=x-Browser.mouseX;Browser.mouseMovementY=y-Browser.mouseY;Browser.mouseX=x;Browser.mouseY=y}},asyncLoad:function(url,onload,onerror,noRunDep){var dep=!noRunDep?getUniqueRunDependency("al "+url):"";readAsync(url,function(arrayBuffer){assert(arrayBuffer,'Loading data file "'+url+'" failed (no arrayBuffer).');onload(new Uint8Array(arrayBuffer));if(dep)removeRunDependency(dep)},function(event){if(onerror){onerror()}else{throw'Loading data file "'+url+'" failed.'}});if(dep)addRunDependency(dep)},resizeListeners:[],updateResizeListeners:function(){var canvas=Module["canvas"];Browser.resizeListeners.forEach(function(listener){listener(canvas.width,canvas.height)})},setCanvasSize:function(width,height,noUpdates){var canvas=Module["canvas"];Browser.updateCanvasDimensions(canvas,width,height);if(!noUpdates)Browser.updateResizeListeners()},windowedWidth:0,windowedHeight:0,setFullscreenCanvasSize:function(){if(typeof SDL!="undefined"){var flags=HEAPU32[SDL.screen>>2];flags=flags|8388608;HEAP32[SDL.screen>>2]=flags}Browser.updateCanvasDimensions(Module["canvas"]);Browser.updateResizeListeners()},setWindowedCanvasSize:function(){if(typeof SDL!="undefined"){var flags=HEAPU32[SDL.screen>>2];flags=flags&~8388608;HEAP32[SDL.screen>>2]=flags}Browser.updateCanvasDimensions(Module["canvas"]);Browser.updateResizeListeners()},updateCanvasDimensions:function(canvas,wNative,hNative){if(wNative&&hNative){canvas.widthNative=wNative;canvas.heightNative=hNative}else{wNative=canvas.widthNative;hNative=canvas.heightNative}var w=wNative;var h=hNative;if(Module["forcedAspectRatio"]&&Module["forcedAspectRatio"]>0){if(w/h<Module["forcedAspectRatio"]){w=Math.round(h*Module["forcedAspectRatio"])}else{h=Math.round(w/Module["forcedAspectRatio"])}}if((document["fullscreenElement"]||document["mozFullScreenElement"]||document["msFullscreenElement"]||document["webkitFullscreenElement"]||document["webkitCurrentFullScreenElement"])===canvas.parentNode&&typeof screen!="undefined"){var factor=Math.min(screen.width/w,screen.height/h);w=Math.round(w*factor);h=Math.round(h*factor)}if(Browser.resizeCanvas){if(canvas.width!=w)canvas.width=w;if(canvas.height!=h)canvas.height=h;if(typeof canvas.style!="undefined"){canvas.style.removeProperty("width");canvas.style.removeProperty("height")}}else{if(canvas.width!=wNative)canvas.width=wNative;if(canvas.height!=hNative)canvas.height=hNative;if(typeof canvas.style!="undefined"){if(w!=wNative||h!=hNative){canvas.style.setProperty("width",w+"px","important");canvas.style.setProperty("height",h+"px","important")}else{canvas.style.removeProperty("width");canvas.style.removeProperty("height")}}}},wgetRequests:{},nextWgetRequestHandle:0,getNextWgetRequestHandle:function(){var handle=Browser.nextWgetRequestHandle;Browser.nextWgetRequestHandle++;return handle}};function _SDL_GetTicks(){return Date.now()-SDL.startTime|0}function _SDL_LockSurface(surf){var surfData=SDL.surfaces[surf];surfData.locked++;if(surfData.locked>1)return 0;if(!surfData.buffer){surfData.buffer=_malloc(surfData.width*surfData.height*4);HEAP32[surf+20>>2]=surfData.buffer}HEAP32[surf+20>>2]=surfData.buffer;if(surf==SDL.screen&&Module.screenIsReadOnly&&surfData.image)return 0;if(SDL.defaults.discardOnLock){if(!surfData.image){surfData.image=surfData.ctx.createImageData(surfData.width,surfData.height)}if(!SDL.defaults.opaqueFrontBuffer)return}else{surfData.image=surfData.ctx.getImageData(0,0,surfData.width,surfData.height)}if(surf==SDL.screen&&SDL.defaults.opaqueFrontBuffer){var data=surfData.image.data;var num=data.length;for(var i=0;i<num/4;i++){data[i*4+3]=255}}if(SDL.defaults.copyOnLock&&!SDL.defaults.discardOnLock){if(surfData.isFlagSet(2097152)){throw"CopyOnLock is not supported for SDL_LockSurface with SDL_HWPALETTE flag set"+(new Error).stack}else{HEAPU8.set(surfData.image.data,surfData.buffer)}}return 0}function SDL_unicode(){return SDL.unicode}function SDL_ttfContext(){return SDL.ttfContext}function SDL_audio(){return SDL.audio}var SDL={defaults:{width:320,height:200,copyOnLock:true,discardOnLock:false,opaqueFrontBuffer:true},version:null,surfaces:{},canvasPool:[],events:[],fonts:[null],audios:[null],rwops:[null],music:{audio:null,volume:1},mixerFrequency:22050,mixerFormat:32784,mixerNumChannels:2,mixerChunkSize:1024,channelMinimumNumber:0,GL:false,glAttributes:{0:3,1:3,2:2,3:0,4:0,5:1,6:16,7:0,8:0,9:0,10:0,11:0,12:0,13:0,14:0,15:1,16:0,17:0,18:0},keyboardState:null,keyboardMap:{},canRequestFullscreen:false,isRequestingFullscreen:false,textInput:false,startTime:null,initFlags:0,buttonState:0,modState:0,DOMButtons:[0,0,0],DOMEventToSDLEvent:{},TOUCH_DEFAULT_ID:0,eventHandler:null,eventHandlerContext:null,eventHandlerTemp:0,keyCodes:{16:1249,17:1248,18:1250,20:1081,33:1099,34:1102,35:1101,36:1098,37:1104,38:1106,39:1103,40:1105,44:316,45:1097,46:127,91:1251,93:1125,96:1122,97:1113,98:1114,99:1115,100:1116,101:1117,102:1118,103:1119,104:1120,105:1121,106:1109,107:1111,109:1110,110:1123,111:1108,112:1082,113:1083,114:1084,115:1085,116:1086,117:1087,118:1088,119:1089,120:1090,121:1091,122:1092,123:1093,124:1128,125:1129,126:1130,127:1131,128:1132,129:1133,130:1134,131:1135,132:1136,133:1137,134:1138,135:1139,144:1107,160:94,161:33,162:34,163:35,164:36,165:37,166:38,167:95,168:40,169:41,170:42,171:43,172:124,173:45,174:123,175:125,176:126,181:127,182:129,183:128,188:44,190:46,191:47,192:96,219:91,220:92,221:93,222:39,224:1251},scanCodes:{8:42,9:43,13:40,27:41,32:44,35:204,39:53,44:54,46:55,47:56,48:39,49:30,50:31,51:32,52:33,53:34,54:35,55:36,56:37,57:38,58:203,59:51,61:46,91:47,92:49,93:48,96:52,97:4,98:5,99:6,100:7,101:8,102:9,103:10,104:11,105:12,106:13,107:14,108:15,109:16,110:17,111:18,112:19,113:20,114:21,115:22,116:23,117:24,118:25,119:26,120:27,121:28,122:29,127:76,305:224,308:226,316:70},loadRect:function(rect){return{x:HEAP32[rect+0>>2],y:HEAP32[rect+4>>2],w:HEAP32[rect+8>>2],h:HEAP32[rect+12>>2]}},updateRect:function(rect,r){HEAP32[rect>>2]=r.x;HEAP32[rect+4>>2]=r.y;HEAP32[rect+8>>2]=r.w;HEAP32[rect+12>>2]=r.h},intersectionOfRects:function(first,second){var leftX=Math.max(first.x,second.x);var leftY=Math.max(first.y,second.y);var rightX=Math.min(first.x+first.w,second.x+second.w);var rightY=Math.min(first.y+first.h,second.y+second.h);return{x:leftX,y:leftY,w:Math.max(leftX,rightX)-leftX,h:Math.max(leftY,rightY)-leftY}},checkPixelFormat:function(fmt){},loadColorToCSSRGB:function(color){var rgba=HEAP32[color>>2];return"rgb("+(rgba&255)+","+(rgba>>8&255)+","+(rgba>>16&255)+")"},loadColorToCSSRGBA:function(color){var rgba=HEAP32[color>>2];return"rgba("+(rgba&255)+","+(rgba>>8&255)+","+(rgba>>16&255)+","+(rgba>>24&255)/255+")"},translateColorToCSSRGBA:function(rgba){return"rgba("+(rgba&255)+","+(rgba>>8&255)+","+(rgba>>16&255)+","+(rgba>>>24)/255+")"},translateRGBAToCSSRGBA:function(r,g,b,a){return"rgba("+(r&255)+","+(g&255)+","+(b&255)+","+(a&255)/255+")"},translateRGBAToColor:function(r,g,b,a){return r|g<<8|b<<16|a<<24},makeSurface:function(width,height,flags,usePageCanvas,source,rmask,gmask,bmask,amask){flags=flags||0;var is_SDL_HWSURFACE=flags&1;var is_SDL_HWPALETTE=flags&2097152;var is_SDL_OPENGL=flags&67108864;var surf=_malloc(60);var pixelFormat=_malloc(44);var bpp=is_SDL_HWPALETTE?1:4;var buffer=0;if(!is_SDL_HWSURFACE&&!is_SDL_OPENGL){buffer=_malloc(width*height*4)}HEAP32[surf>>2]=flags;HEAP32[surf+4>>2]=pixelFormat;HEAP32[surf+8>>2]=width;HEAP32[surf+12>>2]=height;HEAP32[surf+16>>2]=width*bpp;HEAP32[surf+20>>2]=buffer;HEAP32[surf+36>>2]=0;HEAP32[surf+40>>2]=0;HEAP32[surf+44>>2]=Module["canvas"].width;HEAP32[surf+48>>2]=Module["canvas"].height;HEAP32[surf+56>>2]=1;HEAP32[pixelFormat>>2]=-2042224636;HEAP32[pixelFormat+4>>2]=0;HEAP8[pixelFormat+8>>0]=bpp*8;HEAP8[pixelFormat+9>>0]=bpp;HEAP32[pixelFormat+12>>2]=rmask||255;HEAP32[pixelFormat+16>>2]=gmask||65280;HEAP32[pixelFormat+20>>2]=bmask||16711680;HEAP32[pixelFormat+24>>2]=amask||4278190080;SDL.GL=SDL.GL||is_SDL_OPENGL;var canvas;if(!usePageCanvas){if(SDL.canvasPool.length>0){canvas=SDL.canvasPool.pop()}else{canvas=document.createElement("canvas")}canvas.width=width;canvas.height=height}else{canvas=Module["canvas"]}var webGLContextAttributes={antialias:SDL.glAttributes[13]!=0&&SDL.glAttributes[14]>1,depth:SDL.glAttributes[6]>0,stencil:SDL.glAttributes[7]>0,alpha:SDL.glAttributes[3]>0};var ctx=Browser.createContext(canvas,is_SDL_OPENGL,usePageCanvas,webGLContextAttributes);SDL.surfaces[surf]={width:width,height:height,canvas:canvas,ctx:ctx,surf:surf,buffer:buffer,pixelFormat:pixelFormat,alpha:255,flags:flags,locked:0,usePageCanvas:usePageCanvas,source:source,isFlagSet:function(flag){return flags&flag}};return surf},copyIndexedColorData:function(surfData,rX,rY,rW,rH){if(!surfData.colors){return}var fullWidth=Module["canvas"].width;var fullHeight=Module["canvas"].height;var startX=rX||0;var startY=rY||0;var endX=(rW||fullWidth-startX)+startX;var endY=(rH||fullHeight-startY)+startY;var buffer=surfData.buffer;if(!surfData.image.data32){surfData.image.data32=new Uint32Array(surfData.image.data.buffer)}var data32=surfData.image.data32;var colors32=surfData.colors32;for(var y=startY;y<endY;++y){var base=y*fullWidth;for(var x=startX;x<endX;++x){data32[base+x]=colors32[HEAPU8[buffer+base+x>>0]]}}},freeSurface:function(surf){var refcountPointer=surf+56;var refcount=HEAP32[refcountPointer>>2];if(refcount>1){HEAP32[refcountPointer>>2]=refcount-1;return}var info=SDL.surfaces[surf];if(!info.usePageCanvas&&info.canvas)SDL.canvasPool.push(info.canvas);if(info.buffer)_free(info.buffer);_free(info.pixelFormat);_free(surf);SDL.surfaces[surf]=null;if(surf===SDL.screen){SDL.screen=null}},blitSurface:function(src,srcrect,dst,dstrect,scale){var srcData=SDL.surfaces[src];var dstData=SDL.surfaces[dst];var sr,dr;if(srcrect){sr=SDL.loadRect(srcrect)}else{sr={x:0,y:0,w:srcData.width,h:srcData.height}}if(dstrect){dr=SDL.loadRect(dstrect)}else{dr={x:0,y:0,w:srcData.width,h:srcData.height}}if(dstData.clipRect){var widthScale=!scale||sr.w===0?1:sr.w/dr.w;var heightScale=!scale||sr.h===0?1:sr.h/dr.h;dr=SDL.intersectionOfRects(dstData.clipRect,dr);sr.w=dr.w*widthScale;sr.h=dr.h*heightScale;if(dstrect){SDL.updateRect(dstrect,dr)}}var blitw,blith;if(scale){blitw=dr.w;blith=dr.h}else{blitw=sr.w;blith=sr.h}if(sr.w===0||sr.h===0||blitw===0||blith===0){return 0}var oldAlpha=dstData.ctx.globalAlpha;dstData.ctx.globalAlpha=srcData.alpha/255;dstData.ctx.drawImage(srcData.canvas,sr.x,sr.y,sr.w,sr.h,dr.x,dr.y,blitw,blith);dstData.ctx.globalAlpha=oldAlpha;if(dst!=SDL.screen){warnOnce("WARNING: copying canvas data to memory for compatibility");_SDL_LockSurface(dst);dstData.locked--}return 0},downFingers:{},savedKeydown:null,receiveEvent:function(event){function unpressAllPressedKeys(){for(var code in SDL.keyboardMap){SDL.events.push({type:"keyup",keyCode:SDL.keyboardMap[code]})}}switch(event.type){case"touchstart":case"touchmove":{event.preventDefault();var touches=[];if(event.type==="touchstart"){for(var i=0;i<event.touches.length;i++){var touch=event.touches[i];if(SDL.downFingers[touch.identifier]!=true){SDL.downFingers[touch.identifier]=true;touches.push(touch)}}}else{touches=event.touches}var firstTouch=touches[0];if(firstTouch){if(event.type=="touchstart"){SDL.DOMButtons[0]=1}var mouseEventType;switch(event.type){case"touchstart":mouseEventType="mousedown";break;case"touchmove":mouseEventType="mousemove";break}var mouseEvent={type:mouseEventType,button:0,pageX:firstTouch.clientX,pageY:firstTouch.clientY};SDL.events.push(mouseEvent)}for(var i=0;i<touches.length;i++){var touch=touches[i];SDL.events.push({type:event.type,touch:touch})}break}case"touchend":{event.preventDefault();for(var i=0;i<event.changedTouches.length;i++){var touch=event.changedTouches[i];if(SDL.downFingers[touch.identifier]===true){delete SDL.downFingers[touch.identifier]}}var mouseEvent={type:"mouseup",button:0,pageX:event.changedTouches[0].clientX,pageY:event.changedTouches[0].clientY};SDL.DOMButtons[0]=0;SDL.events.push(mouseEvent);for(var i=0;i<event.changedTouches.length;i++){var touch=event.changedTouches[i];SDL.events.push({type:"touchend",touch:touch})}break}case"DOMMouseScroll":case"mousewheel":case"wheel":var delta=-Browser.getMouseWheelDelta(event);delta=delta==0?0:delta>0?Math.max(delta,1):Math.min(delta,-1);var button=delta>0?3:4;SDL.events.push({type:"mousedown",button:button,pageX:event.pageX,pageY:event.pageY});SDL.events.push({type:"mouseup",button:button,pageX:event.pageX,pageY:event.pageY});SDL.events.push({type:"wheel",deltaX:0,deltaY:delta});event.preventDefault();break;case"mousemove":if(SDL.DOMButtons[0]===1){SDL.events.push({type:"touchmove",touch:{identifier:0,deviceID:-1,pageX:event.pageX,pageY:event.pageY}})}if(Browser.pointerLock){if("mozMovementX"in event){event["movementX"]=event["mozMovementX"];event["movementY"]=event["mozMovementY"]}if(event["movementX"]==0&&event["movementY"]==0){event.preventDefault();return}}case"keydown":case"keyup":case"keypress":case"mousedown":case"mouseup":if(event.type!=="keydown"||!SDL_unicode()&&!SDL.textInput||(event.keyCode===8||event.keyCode===9)){event.preventDefault()}if(event.type=="mousedown"){SDL.DOMButtons[event.button]=1;SDL.events.push({type:"touchstart",touch:{identifier:0,deviceID:-1,pageX:event.pageX,pageY:event.pageY}})}else if(event.type=="mouseup"){if(!SDL.DOMButtons[event.button]){return}SDL.events.push({type:"touchend",touch:{identifier:0,deviceID:-1,pageX:event.pageX,pageY:event.pageY}});SDL.DOMButtons[event.button]=0}if(event.type==="keydown"||event.type==="mousedown"){SDL.canRequestFullscreen=true}else if(event.type==="keyup"||event.type==="mouseup"){if(SDL.isRequestingFullscreen){Module["requestFullscreen"](true,true);SDL.isRequestingFullscreen=false}SDL.canRequestFullscreen=false}if(event.type==="keypress"&&SDL.savedKeydown){SDL.savedKeydown.keypressCharCode=event.charCode;SDL.savedKeydown=null}else if(event.type==="keydown"){SDL.savedKeydown=event}if(event.type!=="keypress"||SDL.textInput){SDL.events.push(event)}break;case"mouseout":for(var i=0;i<3;i++){if(SDL.DOMButtons[i]){SDL.events.push({type:"mouseup",button:i,pageX:event.pageX,pageY:event.pageY});SDL.DOMButtons[i]=0}}event.preventDefault();break;case"focus":SDL.events.push(event);event.preventDefault();break;case"blur":SDL.events.push(event);unpressAllPressedKeys();event.preventDefault();break;case"visibilitychange":SDL.events.push({type:"visibilitychange",visible:!document.hidden});unpressAllPressedKeys();event.preventDefault();break;case"unload":if(Browser.mainLoop.runner){SDL.events.push(event);Browser.mainLoop.runner()}return;case"resize":SDL.events.push(event);if(event.preventDefault){event.preventDefault()}break}if(SDL.events.length>=1e4){err("SDL event queue full, dropping events");SDL.events=SDL.events.slice(0,1e4)}SDL.flushEventsToHandler();return},lookupKeyCodeForEvent:function(event){var code=event.keyCode;if(code>=65&&code<=90){code+=32}else{code=SDL.keyCodes[event.keyCode]||event.keyCode;if(event.location===2&&code>=(224|1<<10)&&code<=(227|1<<10)){code+=4}}return code},handleEvent:function(event){if(event.handled)return;event.handled=true;switch(event.type){case"touchstart":case"touchend":case"touchmove":{Browser.calculateMouseEvent(event);break}case"keydown":case"keyup":{var down=event.type==="keydown";var code=SDL.lookupKeyCodeForEvent(event);HEAP8[SDL.keyboardState+code>>0]=down;SDL.modState=(HEAP8[SDL.keyboardState+1248>>0]?64:0)|(HEAP8[SDL.keyboardState+1249>>0]?1:0)|(HEAP8[SDL.keyboardState+1250>>0]?256:0)|(HEAP8[SDL.keyboardState+1252>>0]?128:0)|(HEAP8[SDL.keyboardState+1253>>0]?2:0)|(HEAP8[SDL.keyboardState+1254>>0]?512:0);if(down){SDL.keyboardMap[code]=event.keyCode}else{delete SDL.keyboardMap[code]}break}case"mousedown":case"mouseup":if(event.type=="mousedown"){SDL.buttonState|=1<<event.button}else if(event.type=="mouseup"){SDL.buttonState&=~(1<<event.button)}case"mousemove":{Browser.calculateMouseEvent(event);break}}},flushEventsToHandler:function(){if(!SDL.eventHandler)return;while(SDL.pollEvent(SDL.eventHandlerTemp)){wasmTable.get(SDL.eventHandler)(SDL.eventHandlerContext,SDL.eventHandlerTemp)}},pollEvent:function(ptr){if(SDL.initFlags&512&&SDL.joystickEventState){SDL.queryJoysticks()}if(ptr){while(SDL.events.length>0){if(SDL.makeCEvent(SDL.events.shift(),ptr)!==false)return 1}return 0}else{return SDL.events.length>0}},makeCEvent:function(event,ptr){if(typeof event==="number"){_memcpy(ptr,event,28);_free(event);return}SDL.handleEvent(event);switch(event.type){case"keydown":case"keyup":{var down=event.type==="keydown";var key=SDL.lookupKeyCodeForEvent(event);var scan;if(key>=1024){scan=key-1024}else{scan=SDL.scanCodes[key]||key}HEAP32[ptr>>2]=SDL.DOMEventToSDLEvent[event.type];HEAP8[ptr+8>>0]=down?1:0;HEAP8[ptr+9>>0]=0;HEAP32[ptr+12>>2]=scan;HEAP32[ptr+16>>2]=key;HEAP16[ptr+20>>1]=SDL.modState;HEAP32[ptr+24>>2]=event.keypressCharCode||key;break}case"keypress":{HEAP32[ptr>>2]=SDL.DOMEventToSDLEvent[event.type];var cStr=intArrayFromString(String.fromCharCode(event.charCode));for(var i=0;i<cStr.length;++i){HEAP8[ptr+(8+i)>>0]=cStr[i]}break}case"mousedown":case"mouseup":case"mousemove":{if(event.type!="mousemove"){var down=event.type==="mousedown";HEAP32[ptr>>2]=SDL.DOMEventToSDLEvent[event.type];HEAP32[ptr+4>>2]=0;HEAP32[ptr+8>>2]=0;HEAP32[ptr+12>>2]=0;HEAP8[ptr+16>>0]=event.button+1;HEAP8[ptr+17>>0]=down?1:0;HEAP32[ptr+20>>2]=Browser.mouseX;HEAP32[ptr+24>>2]=Browser.mouseY}else{HEAP32[ptr>>2]=SDL.DOMEventToSDLEvent[event.type];HEAP32[ptr+4>>2]=0;HEAP32[ptr+8>>2]=0;HEAP32[ptr+12>>2]=0;HEAP32[ptr+16>>2]=SDL.buttonState;HEAP32[ptr+20>>2]=Browser.mouseX;HEAP32[ptr+24>>2]=Browser.mouseY;HEAP32[ptr+28>>2]=Browser.mouseMovementX;HEAP32[ptr+32>>2]=Browser.mouseMovementY}break}case"wheel":{HEAP32[ptr>>2]=SDL.DOMEventToSDLEvent[event.type];HEAP32[ptr+16>>2]=event.deltaX;HEAP32[ptr+20>>2]=event.deltaY;break}case"touchstart":case"touchend":case"touchmove":{var touch=event.touch;if(!Browser.touches[touch.identifier])break;var w=Module["canvas"].width;var h=Module["canvas"].height;var x=Browser.touches[touch.identifier].x/w;var y=Browser.touches[touch.identifier].y/h;var lx=Browser.lastTouches[touch.identifier].x/w;var ly=Browser.lastTouches[touch.identifier].y/h;var dx=x-lx;var dy=y-ly;if(touch["deviceID"]===undefined)touch.deviceID=SDL.TOUCH_DEFAULT_ID;if(dx===0&&dy===0&&event.type==="touchmove")return false;HEAP32[ptr>>2]=SDL.DOMEventToSDLEvent[event.type];HEAP32[ptr+4>>2]=_SDL_GetTicks();tempI64=[touch.deviceID>>>0,(tempDouble=touch.deviceID,+Math.abs(tempDouble)>=1?tempDouble>0?(Math.min(+Math.floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[ptr+8>>2]=tempI64[0],HEAP32[ptr+12>>2]=tempI64[1];tempI64=[touch.identifier>>>0,(tempDouble=touch.identifier,+Math.abs(tempDouble)>=1?tempDouble>0?(Math.min(+Math.floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[ptr+16>>2]=tempI64[0],HEAP32[ptr+20>>2]=tempI64[1];HEAPF32[ptr+24>>2]=x;HEAPF32[ptr+28>>2]=y;HEAPF32[ptr+32>>2]=dx;HEAPF32[ptr+36>>2]=dy;if(touch.force!==undefined){HEAPF32[ptr+40>>2]=touch.force}else{HEAPF32[ptr+40>>2]=event.type=="touchend"?0:1}break}case"unload":{HEAP32[ptr>>2]=SDL.DOMEventToSDLEvent[event.type];break}case"resize":{HEAP32[ptr>>2]=SDL.DOMEventToSDLEvent[event.type];HEAP32[ptr+4>>2]=event.w;HEAP32[ptr+8>>2]=event.h;break}case"joystick_button_up":case"joystick_button_down":{var state=event.type==="joystick_button_up"?0:1;HEAP32[ptr>>2]=SDL.DOMEventToSDLEvent[event.type];HEAP8[ptr+4>>0]=event.index;HEAP8[ptr+5>>0]=event.button;HEAP8[ptr+6>>0]=state;break}case"joystick_axis_motion":{HEAP32[ptr>>2]=SDL.DOMEventToSDLEvent[event.type];HEAP8[ptr+4>>0]=event.index;HEAP8[ptr+5>>0]=event.axis;HEAP32[ptr+8>>2]=SDL.joystickAxisValueConversion(event.value);break}case"focus":{var SDL_WINDOWEVENT_FOCUS_GAINED=12;HEAP32[ptr>>2]=SDL.DOMEventToSDLEvent[event.type];HEAP32[ptr+4>>2]=0;HEAP8[ptr+8>>0]=SDL_WINDOWEVENT_FOCUS_GAINED;break}case"blur":{var SDL_WINDOWEVENT_FOCUS_LOST=13;HEAP32[ptr>>2]=SDL.DOMEventToSDLEvent[event.type];HEAP32[ptr+4>>2]=0;HEAP8[ptr+8>>0]=SDL_WINDOWEVENT_FOCUS_LOST;break}case"visibilitychange":{var SDL_WINDOWEVENT_SHOWN=1;var SDL_WINDOWEVENT_HIDDEN=2;var visibilityEventID=event.visible?SDL_WINDOWEVENT_SHOWN:SDL_WINDOWEVENT_HIDDEN;HEAP32[ptr>>2]=SDL.DOMEventToSDLEvent[event.type];HEAP32[ptr+4>>2]=0;HEAP8[ptr+8>>0]=visibilityEventID;break}default:throw"Unhandled SDL event: "+event.type}},makeFontString:function(height,fontName){if(fontName.charAt(0)!="'"&&fontName.charAt(0)!='"'){fontName='"'+fontName+'"'}return height+"px "+fontName+", serif"},estimateTextWidth:function(fontData,text){var h=fontData.size;var fontString=SDL.makeFontString(h,fontData.name);var tempCtx=SDL_ttfContext();tempCtx.font=fontString;var ret=tempCtx.measureText(text).width|0;return ret},allocateChannels:function(num){if(SDL.numChannels&&SDL.numChannels>=num&&num!=0)return;SDL.numChannels=num;SDL.channels=[];for(var i=0;i<num;i++){SDL.channels[i]={audio:null,volume:1}}},setGetVolume:function(info,volume){if(!info)return 0;var ret=info.volume*128;if(volume!=-1){info.volume=Math.min(Math.max(volume,0),128)/128;if(info.audio){try{info.audio.volume=info.volume;if(info.audio.webAudioGainNode)info.audio.webAudioGainNode["gain"]["value"]=info.volume}catch(e){err("setGetVolume failed to set audio volume: "+e)}}}return ret},setPannerPosition:function(info,x,y,z){if(!info)return;if(info.audio){if(info.audio.webAudioPannerNode){info.audio.webAudioPannerNode["setPosition"](x,y,z)}}},playWebAudio:function(audio){if(!audio)return;if(audio.webAudioNode)return;if(!SDL.webAudioAvailable())return;try{var webAudio=audio.resource.webAudio;audio.paused=false;if(!webAudio.decodedBuffer){if(webAudio.onDecodeComplete===undefined)abort("Cannot play back audio object that was not loaded");webAudio.onDecodeComplete.push(function(){if(!audio.paused)SDL.playWebAudio(audio)});return}audio.webAudioNode=SDL.audioContext["createBufferSource"]();audio.webAudioNode["buffer"]=webAudio.decodedBuffer;audio.webAudioNode["loop"]=audio.loop;audio.webAudioNode["onended"]=function(){audio["onended"]()};audio.webAudioPannerNode=SDL.audioContext["createPanner"]();audio.webAudioPannerNode["setPosition"](0,0,-.5);audio.webAudioPannerNode["panningModel"]="equalpower";audio.webAudioGainNode=SDL.audioContext["createGain"]();audio.webAudioGainNode["gain"]["value"]=audio.volume;audio.webAudioNode["connect"](audio.webAudioPannerNode);audio.webAudioPannerNode["connect"](audio.webAudioGainNode);audio.webAudioGainNode["connect"](SDL.audioContext["destination"]);audio.webAudioNode["start"](0,audio.currentPosition);audio.startTime=SDL.audioContext["currentTime"]-audio.currentPosition}catch(e){err("playWebAudio failed: "+e)}},pauseWebAudio:function(audio){if(!audio)return;if(audio.webAudioNode){try{audio.currentPosition=(SDL.audioContext["currentTime"]-audio.startTime)%audio.resource.webAudio.decodedBuffer.duration;audio.webAudioNode["onended"]=undefined;audio.webAudioNode.stop(0);audio.webAudioNode=undefined}catch(e){err("pauseWebAudio failed: "+e)}}audio.paused=true},openAudioContext:function(){if(!SDL.audioContext){if(typeof AudioContext!=="undefined")SDL.audioContext=new AudioContext;else if(typeof webkitAudioContext!=="undefined")SDL.audioContext=new webkitAudioContext}},webAudioAvailable:function(){return!!SDL.audioContext},fillWebAudioBufferFromHeap:function(heapPtr,sizeSamplesPerChannel,dstAudioBuffer){var audio=SDL_audio();var numChannels=audio.channels;for(var c=0;c<numChannels;++c){var channelData=dstAudioBuffer["getChannelData"](c);if(channelData.length!=sizeSamplesPerChannel){throw"Web Audio output buffer length mismatch! Destination size: "+channelData.length+" samples vs expected "+sizeSamplesPerChannel+" samples!"}if(audio.format==32784){for(var j=0;j<sizeSamplesPerChannel;++j){channelData[j]=HEAP16[heapPtr+(j*numChannels+c)*2>>1]/32768}}else if(audio.format==8){for(var j=0;j<sizeSamplesPerChannel;++j){var v=HEAP8[heapPtr+(j*numChannels+c)>>0];channelData[j]=(v>=0?v-128:v+128)/128}}else if(audio.format==33056){for(var j=0;j<sizeSamplesPerChannel;++j){channelData[j]=HEAPF32[heapPtr+(j*numChannels+c)*4>>2]}}else{throw"Invalid SDL audio format "+audio.format+"!"}}},debugSurface:function(surfData){console.log("dumping surface "+[surfData.surf,surfData.source,surfData.width,surfData.height]);var image=surfData.ctx.getImageData(0,0,surfData.width,surfData.height);var data=image.data;var num=Math.min(surfData.width,surfData.height);for(var i=0;i<num;i++){console.log(" diagonal "+i+":"+[data[i*surfData.width*4+i*4+0],data[i*surfData.width*4+i*4+1],data[i*surfData.width*4+i*4+2],data[i*surfData.width*4+i*4+3]])}},joystickEventState:1,lastJoystickState:{},joystickNamePool:{},recordJoystickState:function(joystick,state){var buttons=new Array(state.buttons.length);for(var i=0;i<state.buttons.length;i++){buttons[i]=SDL.getJoystickButtonState(state.buttons[i])}SDL.lastJoystickState[joystick]={buttons:buttons,axes:state.axes.slice(0),timestamp:state.timestamp,index:state.index,id:state.id}},getJoystickButtonState:function(button){if(typeof button==="object"){return button["pressed"]}else{return button>0}},queryJoysticks:function(){for(var joystick in SDL.lastJoystickState){var state=SDL.getGamepad(joystick-1);var prevState=SDL.lastJoystickState[joystick];if(typeof state==="undefined")return;if(state===null)return;if(typeof state.timestamp!=="number"||state.timestamp!==prevState.timestamp||!state.timestamp){var i;for(i=0;i<state.buttons.length;i++){var buttonState=SDL.getJoystickButtonState(state.buttons[i]);if(buttonState!==prevState.buttons[i]){SDL.events.push({type:buttonState?"joystick_button_down":"joystick_button_up",joystick:joystick,index:joystick-1,button:i})}}for(i=0;i<state.axes.length;i++){if(state.axes[i]!==prevState.axes[i]){SDL.events.push({type:"joystick_axis_motion",joystick:joystick,index:joystick-1,axis:i,value:state.axes[i]})}}SDL.recordJoystickState(joystick,state)}}},joystickAxisValueConversion:function(value){value=Math.min(1,Math.max(value,-1));return Math.ceil((value+1)*32767.5-32768)},getGamepads:function(){var fcn=navigator.getGamepads||navigator.webkitGamepads||navigator.mozGamepads||navigator.gamepads||navigator.webkitGetGamepads;if(fcn!==undefined){return fcn.apply(navigator)}else{return[]}},getGamepad:function(deviceIndex){var gamepads=SDL.getGamepads();if(gamepads.length>deviceIndex&&deviceIndex>=0){return gamepads[deviceIndex]}return null}};function _SDL_Init(initFlags){SDL.startTime=Date.now();SDL.initFlags=initFlags;if(!Module["doNotCaptureKeyboard"]){var keyboardListeningElement=Module["keyboardListeningElement"]||document;keyboardListeningElement.addEventListener("keydown",SDL.receiveEvent);keyboardListeningElement.addEventListener("keyup",SDL.receiveEvent);keyboardListeningElement.addEventListener("keypress",SDL.receiveEvent);window.addEventListener("focus",SDL.receiveEvent);window.addEventListener("blur",SDL.receiveEvent);document.addEventListener("visibilitychange",SDL.receiveEvent)}window.addEventListener("unload",SDL.receiveEvent);SDL.keyboardState=_malloc(65536);_memset(SDL.keyboardState,0,65536);SDL.DOMEventToSDLEvent["keydown"]=768;SDL.DOMEventToSDLEvent["keyup"]=769;SDL.DOMEventToSDLEvent["keypress"]=771;SDL.DOMEventToSDLEvent["mousedown"]=1025;SDL.DOMEventToSDLEvent["mouseup"]=1026;SDL.DOMEventToSDLEvent["mousemove"]=1024;SDL.DOMEventToSDLEvent["wheel"]=1027;SDL.DOMEventToSDLEvent["touchstart"]=1792;SDL.DOMEventToSDLEvent["touchend"]=1793;SDL.DOMEventToSDLEvent["touchmove"]=1794;SDL.DOMEventToSDLEvent["unload"]=256;SDL.DOMEventToSDLEvent["resize"]=28673;SDL.DOMEventToSDLEvent["visibilitychange"]=512;SDL.DOMEventToSDLEvent["focus"]=512;SDL.DOMEventToSDLEvent["blur"]=512;SDL.DOMEventToSDLEvent["joystick_axis_motion"]=1536;SDL.DOMEventToSDLEvent["joystick_button_down"]=1539;SDL.DOMEventToSDLEvent["joystick_button_up"]=1540;return 0}function _SDL_PollEvent(ptr){return SDL.pollEvent(ptr)}function __webgl_enable_ANGLE_instanced_arrays(ctx){var ext=ctx.getExtension("ANGLE_instanced_arrays");if(ext){ctx["vertexAttribDivisor"]=function(index,divisor){ext["vertexAttribDivisorANGLE"](index,divisor)};ctx["drawArraysInstanced"]=function(mode,first,count,primcount){ext["drawArraysInstancedANGLE"](mode,first,count,primcount)};ctx["drawElementsInstanced"]=function(mode,count,type,indices,primcount){ext["drawElementsInstancedANGLE"](mode,count,type,indices,primcount)};return 1}}function __webgl_enable_OES_vertex_array_object(ctx){var ext=ctx.getExtension("OES_vertex_array_object");if(ext){ctx["createVertexArray"]=function(){return ext["createVertexArrayOES"]()};ctx["deleteVertexArray"]=function(vao){ext["deleteVertexArrayOES"](vao)};ctx["bindVertexArray"]=function(vao){ext["bindVertexArrayOES"](vao)};ctx["isVertexArray"]=function(vao){return ext["isVertexArrayOES"](vao)};return 1}}function __webgl_enable_WEBGL_draw_buffers(ctx){var ext=ctx.getExtension("WEBGL_draw_buffers");if(ext){ctx["drawBuffers"]=function(n,bufs){ext["drawBuffersWEBGL"](n,bufs)};return 1}}function __webgl_enable_WEBGL_multi_draw(ctx){return!!(ctx.multiDrawWebgl=ctx.getExtension("WEBGL_multi_draw"))}var GL={counter:1,buffers:[],programs:[],framebuffers:[],renderbuffers:[],textures:[],uniforms:[],shaders:[],vaos:[],contexts:[],offscreenCanvases:{},timerQueriesEXT:[],programInfos:{},stringCache:{},unpackAlignment:4,recordError:function recordError(errorCode){if(!GL.lastError){GL.lastError=errorCode}},getNewId:function(table){var ret=GL.counter++;for(var i=table.length;i<ret;i++){table[i]=null}return ret},getSource:function(shader,count,string,length){var source="";for(var i=0;i<count;++i){var len=length?HEAP32[length+i*4>>2]:-1;source+=UTF8ToString(HEAP32[string+i*4>>2],len<0?undefined:len)}return source},createContext:function(canvas,webGLContextAttributes){var ctx=canvas.getContext("webgl",webGLContextAttributes);if(!ctx)return 0;var handle=GL.registerContext(ctx,webGLContextAttributes);return handle},registerContext:function(ctx,webGLContextAttributes){var handle=GL.getNewId(GL.contexts);var context={handle:handle,attributes:webGLContextAttributes,version:webGLContextAttributes.majorVersion,GLctx:ctx};if(ctx.canvas)ctx.canvas.GLctxObject=context;GL.contexts[handle]=context;if(typeof webGLContextAttributes.enableExtensionsByDefault==="undefined"||webGLContextAttributes.enableExtensionsByDefault){GL.initExtensions(context)}return handle},makeContextCurrent:function(contextHandle){GL.currentContext=GL.contexts[contextHandle];Module.ctx=GLctx=GL.currentContext&&GL.currentContext.GLctx;return!(contextHandle&&!GLctx)},getContext:function(contextHandle){return GL.contexts[contextHandle]},deleteContext:function(contextHandle){if(GL.currentContext===GL.contexts[contextHandle])GL.currentContext=null;if(typeof JSEvents==="object")JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas);if(GL.contexts[contextHandle]&&GL.contexts[contextHandle].GLctx.canvas)GL.contexts[contextHandle].GLctx.canvas.GLctxObject=undefined;GL.contexts[contextHandle]=null},initExtensions:function(context){if(!context)context=GL.currentContext;if(context.initExtensionsDone)return;context.initExtensionsDone=true;var GLctx=context.GLctx;__webgl_enable_ANGLE_instanced_arrays(GLctx);__webgl_enable_OES_vertex_array_object(GLctx);__webgl_enable_WEBGL_draw_buffers(GLctx);GLctx.disjointTimerQueryExt=GLctx.getExtension("EXT_disjoint_timer_query");__webgl_enable_WEBGL_multi_draw(GLctx);var automaticallyEnabledExtensions=["OES_texture_float","OES_texture_half_float","OES_standard_derivatives","OES_vertex_array_object","WEBGL_compressed_texture_s3tc","WEBGL_depth_texture","OES_element_index_uint","EXT_texture_filter_anisotropic","EXT_frag_depth","WEBGL_draw_buffers","ANGLE_instanced_arrays","OES_texture_float_linear","OES_texture_half_float_linear","EXT_blend_minmax","EXT_shader_texture_lod","EXT_texture_norm16","WEBGL_compressed_texture_pvrtc","EXT_color_buffer_half_float","WEBGL_color_buffer_float","EXT_sRGB","WEBGL_compressed_texture_etc1","EXT_disjoint_timer_query","WEBGL_compressed_texture_etc","WEBGL_compressed_texture_astc","EXT_color_buffer_float","WEBGL_compressed_texture_s3tc_srgb","EXT_disjoint_timer_query_webgl2","WEBKIT_WEBGL_compressed_texture_pvrtc"];var exts=GLctx.getSupportedExtensions()||[];exts.forEach(function(ext){if(automaticallyEnabledExtensions.indexOf(ext)!=-1){GLctx.getExtension(ext)}})},populateUniformTable:function(program){var p=GL.programs[program];var ptable=GL.programInfos[program]={uniforms:{},maxUniformLength:0,maxAttributeLength:-1,maxUniformBlockNameLength:-1};var utable=ptable.uniforms;var numUniforms=GLctx.getProgramParameter(p,35718);for(var i=0;i<numUniforms;++i){var u=GLctx.getActiveUniform(p,i);var name=u.name;ptable.maxUniformLength=Math.max(ptable.maxUniformLength,name.length+1);if(name.slice(-1)=="]"){name=name.slice(0,name.lastIndexOf("["))}var loc=GLctx.getUniformLocation(p,name);if(loc){var id=GL.getNewId(GL.uniforms);utable[name]=[u.size,id];GL.uniforms[id]=loc;for(var j=1;j<u.size;++j){var n=name+"["+j+"]";loc=GLctx.getUniformLocation(p,n);id=GL.getNewId(GL.uniforms);GL.uniforms[id]=loc}}}}};function _SDL_SetVideoMode(width,height,depth,flags){["touchstart","touchend","touchmove","mousedown","mouseup","mousemove","DOMMouseScroll","mousewheel","wheel","mouseout"].forEach(function(event){Module["canvas"].addEventListener(event,SDL.receiveEvent,true)});var canvas=Module["canvas"];if(width==0&&height==0){width=canvas.width;height=canvas.height}if(!SDL.addedResizeListener){SDL.addedResizeListener=true;Browser.resizeListeners.push(function(w,h){if(!SDL.settingVideoMode){SDL.receiveEvent({type:"resize",w:w,h:h})}})}SDL.settingVideoMode=true;Browser.setCanvasSize(width,height);SDL.settingVideoMode=false;if(SDL.screen){SDL.freeSurface(SDL.screen);assert(!SDL.screen)}if(SDL.GL)flags=flags|67108864;SDL.screen=SDL.makeSurface(width,height,flags,true,"screen");return SDL.screen}function _SDL_ShowCursor(toggle){switch(toggle){case 0:if(Browser.isFullscreen){Module["canvas"].requestPointerLock();return 0}else{return 1}break;case 1:Module["canvas"].exitPointerLock();return 1;break;case-1:return!Browser.pointerLock;break;default:console.log("SDL_ShowCursor called with unknown toggle parameter value: "+toggle+".");break}}function _SDL_WM_GrabInput(){}function _SDL_WM_SetCaption(title,icon){if(title&&typeof setWindowTitle!=="undefined"){setWindowTitle(UTF8ToString(title))}icon=icon&&UTF8ToString(icon)}function _tzset(){if(_tzset.called)return;_tzset.called=true;var currentYear=(new Date).getFullYear();var winter=new Date(currentYear,0,1);var summer=new Date(currentYear,6,1);var winterOffset=winter.getTimezoneOffset();var summerOffset=summer.getTimezoneOffset();var stdTimezoneOffset=Math.max(winterOffset,summerOffset);HEAP32[__get_timezone()>>2]=stdTimezoneOffset*60;HEAP32[__get_daylight()>>2]=Number(winterOffset!=summerOffset);function extractZone(date){var match=date.toTimeString().match(/\(([A-Za-z ]+)\)$/);return match?match[1]:"GMT"}var winterName=extractZone(winter);var summerName=extractZone(summer);var winterNamePtr=allocateUTF8(winterName);var summerNamePtr=allocateUTF8(summerName);if(summerOffset<winterOffset){HEAP32[__get_tzname()>>2]=winterNamePtr;HEAP32[__get_tzname()+4>>2]=summerNamePtr}else{HEAP32[__get_tzname()>>2]=summerNamePtr;HEAP32[__get_tzname()+4>>2]=winterNamePtr}}function _localtime_r(time,tmPtr){_tzset();var date=new Date(HEAP32[time>>2]*1e3);HEAP32[tmPtr>>2]=date.getSeconds();HEAP32[tmPtr+4>>2]=date.getMinutes();HEAP32[tmPtr+8>>2]=date.getHours();HEAP32[tmPtr+12>>2]=date.getDate();HEAP32[tmPtr+16>>2]=date.getMonth();HEAP32[tmPtr+20>>2]=date.getFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getDay();var start=new Date(date.getFullYear(),0,1);var yday=(date.getTime()-start.getTime())/(1e3*60*60*24)|0;HEAP32[tmPtr+28>>2]=yday;HEAP32[tmPtr+36>>2]=-(date.getTimezoneOffset()*60);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dst=(summerOffset!=winterOffset&&date.getTimezoneOffset()==Math.min(winterOffset,summerOffset))|0;HEAP32[tmPtr+32>>2]=dst;var zonePtr=HEAP32[__get_tzname()+(dst?4:0)>>2];HEAP32[tmPtr+40>>2]=zonePtr;return tmPtr}function ___localtime_r(a0,a1){return _localtime_r(a0,a1)}function _abort(){abort()}function _emscripten_asm_const_int(code,sigPtr,argbuf){var args=readAsmConstArgs(sigPtr,argbuf);return ASM_CONSTS[code].apply(null,args)}function _emscripten_memcpy_big(dest,src,num){HEAPU8.copyWithin(dest,src,src+num)}function abortOnCannotGrowMemory(requestedSize){abort("OOM")}function _emscripten_resize_heap(requestedSize){requestedSize=requestedSize>>>0;abortOnCannotGrowMemory(requestedSize)}function _exit(status){exit(status)}var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0}else{buffer.push(curr)}},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){return low}};function _fd_close(fd){return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){}function _fd_write(fd,iov,iovcnt,pnum){var num=0;for(var i=0;i<iovcnt;i++){var ptr=HEAP32[iov+i*8>>2];var len=HEAP32[iov+(i*8+4)>>2];for(var j=0;j<len;j++){SYSCALLS.printChar(fd,HEAPU8[ptr+j])}num+=len}HEAP32[pnum>>2]=num;return 0}function _mktime(tmPtr){_tzset();var date=new Date(HEAP32[tmPtr+20>>2]+1900,HEAP32[tmPtr+16>>2],HEAP32[tmPtr+12>>2],HEAP32[tmPtr+8>>2],HEAP32[tmPtr+4>>2],HEAP32[tmPtr>>2],0);var dst=HEAP32[tmPtr+32>>2];var guessedOffset=date.getTimezoneOffset();var start=new Date(date.getFullYear(),0,1);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dstOffset=Math.min(winterOffset,summerOffset);if(dst<0){HEAP32[tmPtr+32>>2]=Number(summerOffset!=winterOffset&&dstOffset==guessedOffset)}else if(dst>0!=(dstOffset==guessedOffset)){var nonDstOffset=Math.max(winterOffset,summerOffset);var trueOffset=dst>0?dstOffset:nonDstOffset;date.setTime(date.getTime()+(trueOffset-guessedOffset)*6e4)}HEAP32[tmPtr+24>>2]=date.getDay();var yday=(date.getTime()-start.getTime())/(1e3*60*60*24)|0;HEAP32[tmPtr+28>>2]=yday;HEAP32[tmPtr>>2]=date.getSeconds();HEAP32[tmPtr+4>>2]=date.getMinutes();HEAP32[tmPtr+8>>2]=date.getHours();HEAP32[tmPtr+12>>2]=date.getDate();HEAP32[tmPtr+16>>2]=date.getMonth();return date.getTime()/1e3|0}function _time(ptr){var ret=Date.now()/1e3|0;if(ptr){HEAP32[ptr>>2]=ret}return ret}var readAsmConstArgsArray=[];function readAsmConstArgs(sigPtr,buf){readAsmConstArgsArray.length=0;var ch;buf>>=2;while(ch=HEAPU8[sigPtr++]){var double=ch<105;if(double&&buf&1)buf++;readAsmConstArgsArray.push(double?HEAPF64[buf++>>1]:HEAP32[buf]);++buf}return readAsmConstArgsArray}Module["requestFullscreen"]=function Module_requestFullscreen(lockPointer,resizeCanvas){Browser.requestFullscreen(lockPointer,resizeCanvas)};Module["requestAnimationFrame"]=function Module_requestAnimationFrame(func){Browser.requestAnimationFrame(func)};Module["setCanvasSize"]=function Module_setCanvasSize(width,height,noUpdates){Browser.setCanvasSize(width,height,noUpdates)};Module["pauseMainLoop"]=function Module_pauseMainLoop(){Browser.mainLoop.pause()};Module["resumeMainLoop"]=function Module_resumeMainLoop(){Browser.mainLoop.resume()};Module["getUserMedia"]=function Module_getUserMedia(){Browser.getUserMedia()};Module["createContext"]=function Module_createContext(canvas,useWebGL,setInModule,webGLContextAttributes){return Browser.createContext(canvas,useWebGL,setInModule,webGLContextAttributes)};var GLctx;function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}__ATINIT__.push({func:function(){___wasm_call_ctors()}});var asmLibraryArg={"l":_SDL_Init,"i":_SDL_PollEvent,"g":_SDL_SetVideoMode,"e":_SDL_ShowCursor,"f":_SDL_WM_GrabInput,"d":_SDL_WM_SetCaption,"p":___localtime_r,"b":_abort,"c":_emscripten_asm_const_int,"n":_emscripten_memcpy_big,"o":_emscripten_resize_heap,"h":_exit,"q":_fd_close,"m":_fd_seek,"j":_fd_write,"a":wasmMemory,"r":_mktime,"k":_time};var asm=createWasm();var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){return(___wasm_call_ctors=Module["___wasm_call_ctors"]=Module["asm"]["t"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return(_malloc=Module["_malloc"]=Module["asm"]["u"]).apply(null,arguments)};var _free=Module["_free"]=function(){return(_free=Module["_free"]=Module["asm"]["v"]).apply(null,arguments)};var _memcpy=Module["_memcpy"]=function(){return(_memcpy=Module["_memcpy"]=Module["asm"]["w"]).apply(null,arguments)};var _memset=Module["_memset"]=function(){return(_memset=Module["_memset"]=Module["asm"]["x"]).apply(null,arguments)};var _display_send_ctrl_alt_del=Module["_display_send_ctrl_alt_del"]=function(){return(_display_send_ctrl_alt_del=Module["_display_send_ctrl_alt_del"]=Module["asm"]["y"]).apply(null,arguments)};var _display_send_scancode=Module["_display_send_scancode"]=function(){return(_display_send_scancode=Module["_display_send_scancode"]=Module["asm"]["z"]).apply(null,arguments)};var _drive_emscripten_init=Module["_drive_emscripten_init"]=function(){return(_drive_emscripten_init=Module["_drive_emscripten_init"]=Module["asm"]["A"]).apply(null,arguments)};var _emscripten_alloc=Module["_emscripten_alloc"]=function(){return(_emscripten_alloc=Module["_emscripten_alloc"]=Module["asm"]["B"]).apply(null,arguments)};var _emscripten_get_pc_config=Module["_emscripten_get_pc_config"]=function(){return(_emscripten_get_pc_config=Module["_emscripten_get_pc_config"]=Module["asm"]["C"]).apply(null,arguments)};var _emscripten_init=Module["_emscripten_init"]=function(){return(_emscripten_init=Module["_emscripten_init"]=Module["asm"]["D"]).apply(null,arguments)};var _emscripten_run=Module["_emscripten_run"]=function(){return(_emscripten_run=Module["_emscripten_run"]=Module["asm"]["E"]).apply(null,arguments)};var _emscripten_vga_update=Module["_emscripten_vga_update"]=function(){return(_emscripten_vga_update=Module["_emscripten_vga_update"]=Module["asm"]["F"]).apply(null,arguments)};var _emscripten_debug=Module["_emscripten_debug"]=function(){return(_emscripten_debug=Module["_emscripten_debug"]=Module["asm"]["G"]).apply(null,arguments)};var _emscripten_savestate=Module["_emscripten_savestate"]=function(){return(_emscripten_savestate=Module["_emscripten_savestate"]=Module["asm"]["H"]).apply(null,arguments)};var _emscripten_get_cycles=Module["_emscripten_get_cycles"]=function(){return(_emscripten_get_cycles=Module["_emscripten_get_cycles"]=Module["asm"]["I"]).apply(null,arguments)};var _emscripten_get_now=Module["_emscripten_get_now"]=function(){return(_emscripten_get_now=Module["_emscripten_get_now"]=Module["asm"]["J"]).apply(null,arguments)};var _emscripten_set_fast=Module["_emscripten_set_fast"]=function(){return(_emscripten_set_fast=Module["_emscripten_set_fast"]=Module["asm"]["K"]).apply(null,arguments)};var _emscripten_dyncall_vii=Module["_emscripten_dyncall_vii"]=function(){return(_emscripten_dyncall_vii=Module["_emscripten_dyncall_vii"]=Module["asm"]["L"]).apply(null,arguments)};var _main=Module["_main"]=function(){return(_main=Module["_main"]=Module["asm"]["M"]).apply(null,arguments)};var _parse_cfg=Module["_parse_cfg"]=function(){return(_parse_cfg=Module["_parse_cfg"]=Module["asm"]["N"]).apply(null,arguments)};var __get_tzname=Module["__get_tzname"]=function(){return(__get_tzname=Module["__get_tzname"]=Module["asm"]["O"]).apply(null,arguments)};var __get_daylight=Module["__get_daylight"]=function(){return(__get_daylight=Module["__get_daylight"]=Module["asm"]["P"]).apply(null,arguments)};var __get_timezone=Module["__get_timezone"]=function(){return(__get_timezone=Module["__get_timezone"]=Module["asm"]["Q"]).apply(null,arguments)};var calledRun;function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}var calledMain=false;dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function callMain(args){var entryFunction=Module["_main"];var argc=0;var argv=0;try{var ret=entryFunction(argc,argv);exit(ret,true)}catch(e){if(e instanceof ExitStatus){return}else if(e=="unwind"){noExitRuntime=true;return}else{var toLog=e;if(e&&typeof e==="object"&&e.stack){toLog=[e,e.stack]}err("exception thrown: "+toLog);quit_(1,e)}}finally{calledMain=true}}function run(args){args=args||arguments_;if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();if(shouldRunNow)callMain(args);postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}Module["run"]=run;function exit(status,implicit){if(implicit&&noExitRuntime&&status===0){return}if(noExitRuntime){}else{EXITSTATUS=status;exitRuntime();if(Module["onExit"])Module["onExit"](status);ABORT=true}quit_(status,new ExitStatus(status))}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}var shouldRunNow=true;if(Module["noInitialRun"])shouldRunNow=false;noExitRuntime=true;run();
VirtualXP.json ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "VirtualXP",
3
+ "short_name": "VirtualXP",
4
+ "lang": "en-US",
5
+ "start_url": "https://lrusso.github.io/VirtualXP/VirtualXP.htm",
6
+ "display": "standalone",
7
+ "orientation": "landscape",
8
+ "theme_color": "#000000",
9
+ "background_color": "#000000",
10
+ "icons": [
11
+ {
12
+ "src": "https://lrusso.github.io/VirtualXP/VirtualXPFavIcon_192x192.png",
13
+ "sizes": "192x192",
14
+ "type": "image/png"
15
+ },
16
+ {
17
+ "src": "https://lrusso.github.io/VirtualXP/VirtualXPFavIcon_512x512.png",
18
+ "sizes": "512x512",
19
+ "type": "image/png"
20
+ }
21
+ ]
22
+ }
VirtualXP.wasm ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:44b91fa2810c3350ea54f6b38b75e9bdb63a7d651d0ea3e2d72ef34af225acf8
3
+ size 534550
VirtualXPBIOS.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:4824f2aba4db9b633b5a92c4bca85ac17f57f785911d53b21296166a2558504b
3
+ size 131072
VirtualXPLoader.js ADDED
@@ -0,0 +1,978 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function (global) {
2
+ /**
3
+ * Emulator constructor
4
+ * @param {object} options
5
+ */
6
+ function Halfix(options) {
7
+ this.options = options || {};
8
+
9
+ this.canvas = this.options["canvas"] || null;
10
+ this.ctx = this.canvas ? this.canvas.getContext("2d") : null;
11
+
12
+ this.total_memory = 256;
13
+
14
+ this.fast = options["fast"] || false;
15
+ this.winnt_hack = options["winnt_hack"] || false;
16
+
17
+ this.reportSpeed = options["reportSpeed"] || function (n) { };
18
+ console.log(options.reportSpeed);
19
+
20
+ this.paused = false;
21
+
22
+ /** @type {ImageData} */
23
+ this.image_data = null;
24
+
25
+ this.config = this.buildConfiguration();
26
+
27
+ this.onprogress = options["onprogress"] || function (a, b, c) { };
28
+ }
29
+
30
+ var _cache = [];
31
+
32
+ /**
33
+ * @param {string} name
34
+ * @returns {string|null} Value of the parameter or null
35
+ */
36
+ Halfix.prototype.getParameterByName = function (name) {
37
+ var opt = this.options[name];
38
+ if (!opt) return null;
39
+
40
+ // Check if we have a special kind of object here
41
+ var index = _cache.length;
42
+ if (opt instanceof ArrayBuffer) {
43
+ _cache.push(opt);
44
+ // Return that we have this in the cache
45
+ return "ab!" + index;
46
+ } else if (opt instanceof File) {
47
+ _cache.push(opt);
48
+ return "file!" + index;
49
+ }
50
+ return opt;
51
+ };
52
+
53
+ /**
54
+ * @param {string} name
55
+ * @param {boolean} defaultValue
56
+ * @returns {boolean} Value of parameter as a boolean
57
+ */
58
+ Halfix.prototype.getBooleanByName = function (name, defaultValue) {
59
+ var res = this.getParameterByName(name);
60
+ if (res === null) return defaultValue | 0;
61
+ else return !!res | 0;
62
+ };
63
+ /**
64
+ * @param {string} name
65
+ * @param {number} defaultValue
66
+ * @returns {number} Value of parameter as an integer
67
+ */
68
+ Halfix.prototype.getIntegerByName = function (name, defaultValue) {
69
+ var res = this.getParameterByName(name);
70
+ if (res === null) return defaultValue;
71
+ else return parseInt(res) | 0;
72
+ };
73
+ /**
74
+ * @param {string} name
75
+ * @param {number} defaultValue
76
+ * @returns {number} Value of parameter as a double
77
+ */
78
+ Halfix.prototype.getDoubleByName = function (name, defaultValue) {
79
+ var res = this.getParameterByName(name);
80
+ if (res === null) return defaultValue;
81
+ else return +parseFloat(res);
82
+ };
83
+
84
+ /**
85
+ * Build drive configuration
86
+ * @param {array} config
87
+ * @param {string} drvid A drive ID (a/b/c/d)
88
+ * @param {number} primary Primary? (0=yes, 1=no)
89
+ * @param {number} master Master? (0=yes, 1=no)
90
+ */
91
+ Halfix.prototype.buildDrive = function (config, drvid, primary, master) {
92
+ var hd = this.getParameterByName("hd" + drvid),
93
+ cd = this.getParameterByName("cd" + drvid);
94
+ if (!hd && !cd)
95
+ return;
96
+ config.push("[ata" + primary + "-" + master + "]");
97
+ if (hd) {
98
+ if (hd !== "none") {
99
+ config.push("file=" + hd);
100
+ config.push("inserted=1");
101
+ }
102
+ config.push("type=hd");
103
+ } else {
104
+ if (cd !== "none") {
105
+ config.push("file=" + cd);
106
+ config.push("inserted=1");
107
+ }
108
+ config.push("type=cd");
109
+ }
110
+ };
111
+
112
+ /**
113
+ * @param {string} f name of file
114
+ * @param {number} a current position
115
+ * @param {number} b end
116
+ */
117
+ Halfix.prototype.updateNetworkProgress = function (f, a, b) {
118
+ this.onprogress(f, a, b);
119
+ };
120
+ /**
121
+ * @param {number} total Total bytes loaded
122
+ */
123
+ Halfix.prototype.updateTotalBytes = function (total) {
124
+
125
+ };
126
+
127
+ Halfix.prototype.handleSavestate = function () {
128
+ // TODO
129
+ };
130
+
131
+ /**
132
+ * Build floppy configuration
133
+ */
134
+ Halfix.prototype.buildFloppy = function (config, drvid) {
135
+ var fd = this.getParameterByName("fd" + drvid);
136
+ if (!fd)
137
+ return;
138
+ config.push("[fd" + drvid + "]");
139
+ config.push("file=" + fd);
140
+ config.push("inserted=1");
141
+ }
142
+
143
+ /**
144
+ * From the given URL parameters, we build a .conf file for Halfix to consume.
145
+ */
146
+ Halfix.prototype.buildConfiguration = function () {
147
+ var config = [];
148
+ /*
149
+
150
+ bios_path: getParameterByName("bios") || "bios.bin",
151
+ bios: null,
152
+ vgabios_path: getParameterByName("vgabios") || "vgabios.bin",
153
+ vgabios: null,
154
+ hd: [getParameterByName("hda"), getParameterByName("hdb"), getParameterByName("hdc"), getParameterByName("hdd")],
155
+ cd: [getParameterByName("cda"), getParameterByName("cdb"), getParameterByName("cdc"), getParameterByName("cdd")],
156
+ pci: getBooleanByName("pcienabled"),
157
+ apic: getBooleanByName("apicenabled"),
158
+ acpi: getBooleanByName("apicenabled"),
159
+ now: getParameterByName("now") ? parseFloat(getParameterByName("now")) : 1563602400,
160
+ mem: getParameterByName("mem") ? parseInt(getParameterByName("mem")) : 32,
161
+ vgamem: getParameterByName("vgamem") ? parseInt(getParameterByName("vgamem")) : 32,
162
+ fd: [getParameterByName("fda"), getParameterByName("fdb")],
163
+ boot: getParameterByName("boot") || "chf" // HDA, FDC, CDROM
164
+ */
165
+ config.push("bios=" + (this.getParameterByName("bios") || "bios.bin"));
166
+ config.push("vgabios=" + (this.getParameterByName("vgabios") || "vgabios.bin"));
167
+ config.push("pci=" + this.getBooleanByName("pcienabled", true));
168
+ config.push("apic=" + this.getBooleanByName("apicenabled", true));
169
+ config.push("acpi=" + this.getBooleanByName("acpienabled", true));
170
+ config.push("pcivga=" + this.getBooleanByName("pcivga", false));
171
+ config.push("now=" + this.getDoubleByName("now", new Date().getTime()));
172
+ var floppyRequired = (!!this.getParameterByName("fda") || !!this.getParameterByName("fdb")) | 0;
173
+ console.log(floppyRequired);
174
+ config.push("floppy=" + floppyRequired);
175
+ var mem = this.getIntegerByName("mem", 32),
176
+ vgamem = this.getIntegerByName("vgamem", 4);
177
+
178
+ function roundUp(v) {
179
+ v--;
180
+ v |= v >> 1;
181
+ v |= v >> 2;
182
+ v |= v >> 4;
183
+ v |= v >> 8;
184
+ v |= v >> 16;
185
+ v++;
186
+ return v;
187
+ }
188
+
189
+ this.total_memory = roundUp(mem + 32 + vgamem) * 1024 * 1024 | 0;
190
+ //Module["TOTAL_MEMORY"] = roundUp(mem + 32 + vgamem) * 1024 * 1024 | 0;
191
+ config.push("memory=" + mem + "M");
192
+ config.push("vgamemory=" + vgamem + "M");
193
+ this.buildDrive(config, "a", 0, "master");
194
+ this.buildDrive(config, "b", 0, "slave");
195
+ this.buildDrive(config, "c", 1, "master");
196
+ this.buildDrive(config, "d", 1, "slave");
197
+
198
+ this.buildFloppy(config, "a");
199
+ this.buildFloppy(config, "b");
200
+ config.push("[boot]");
201
+
202
+ var bootOrder = this.getParameterByName("boot") || "hcf";
203
+ config.push("a=" + bootOrder[0] + "d");
204
+ config.push("b=" + bootOrder[1] + "d");
205
+ config.push("c=" + bootOrder[2] + "d");
206
+
207
+ config.push("[cpu]");
208
+ config.push("cpuid_limit_winnt=" + (this.winnt_hack ? "1" : "0"));
209
+ config.push(""); // Trailing empty line
210
+
211
+ return config.join("\n");
212
+ }
213
+ Halfix.prototype["send_ctrlaltdel"] = function () {
214
+ send_ctrlaltdel(1);
215
+ send_ctrlaltdel(0);
216
+ };
217
+
218
+ function loadFiles(paths, cb, gz) {
219
+ var resultCounter = paths.length | 0,
220
+ results = [];
221
+
222
+ inLoading = true;
223
+ for (var i = 0; i < paths.length; i = i + 1 | 0) {
224
+ (function () {
225
+ // Save some state information inside the closure.
226
+ var xhr = new XMLHttpRequest(),
227
+ idx = i,
228
+ lastProgress = 0;
229
+ var path = paths[i] + (gz ? ".gz" : "");
230
+ xhr.open("GET", paths[i] + (gz ? ".gz" : ""));
231
+
232
+ xhr.onprogress = function (e) {
233
+ if (e.lengthComputable) {
234
+ _halfix.updateNetworkProgress(path, e.loaded, e.total);
235
+ lastProgress = now;
236
+ }
237
+ };
238
+ xhr.responseType = "arraybuffer";
239
+ xhr.onload = function () {
240
+ if (!gz)
241
+ results[idx] = new Uint8Array(xhr.response);
242
+ else
243
+ results[idx] = pako.inflate(new Uint8Array(xhr.response));
244
+ resultCounter = resultCounter - 1 | 0;
245
+ _halfix.updateTotalBytes(xhr.response.byteLength | 0);
246
+ if (resultCounter === 0) {
247
+ cb(null, results);
248
+
249
+ inLoading = false;
250
+
251
+ // If we have requested a savestate, then create it now.
252
+ _halfix.handleSavestate();
253
+ }
254
+ };
255
+ xhr.onerror = function (e) {
256
+ alert("Unable to load file");
257
+ cb(e, null);
258
+ };
259
+ xhr.send();
260
+ })();
261
+ }
262
+ }
263
+
264
+ Halfix.prototype.updateScreen = function () {
265
+ if (this.ctx)
266
+ this.ctx.putImageData(this.image_data, 0, 0);
267
+ };
268
+
269
+ var _loaded = false;
270
+
271
+ // ========================================================================
272
+ // Public API
273
+ // ========================================================================
274
+ /**
275
+ * Get configuration file
276
+ * @returns {string} Configuration text
277
+ */
278
+ Halfix.prototype["getConfiguration"] = function () {
279
+ return this.config;
280
+ };
281
+
282
+ /** @type {Halfix} */
283
+ var _halfix = null;
284
+
285
+ var init_cb = null;
286
+
287
+ /**
288
+ * Load and initialize emulator instance
289
+ * @param {function(Error, object)} cb Callback
290
+ */
291
+ Halfix.prototype["init"] = function (cb) {
292
+ // Only one instance can be loaded at a time, unfortunately
293
+ if (_loaded) cb(new Error("Already initialized"), null);
294
+ _loaded = true;
295
+
296
+ // Save our Halfix instance for later
297
+ _halfix = this;
298
+
299
+ // Set up our module instance
300
+ global["Module"]["canvas"] = this.canvas;
301
+ global["Module"]["TOTAL_MEMORY"] = this.total_memory;
302
+
303
+ init_cb = cb;
304
+
305
+ // Load emulator
306
+ var script = document.createElement("script");
307
+ script.src = this.getParameterByName("emulator") || "VirtualXP.js";
308
+ document.head.appendChild(script);
309
+ };
310
+
311
+ var savestate_files = {};
312
+ function u8tostr(u) {
313
+ var str = "";
314
+ for (var i = 0; i < u.length; i = i + 1 | 0)str += String.fromCharCode(u[i]);
315
+ return str;
316
+ }
317
+ /**
318
+ * Load savestate from directory
319
+ * @param {string} statepath
320
+ * @param {function} cb
321
+ */
322
+ Halfix.prototype["loadStateXHR"] = function (statepath, cb) {
323
+ loadFiles([
324
+ statepath + "/state.bin",
325
+ statepath + "/ram",
326
+ statepath + "/vram",
327
+ statepath + "/diskinfo.json"], function (err, data) {
328
+ if (err) throw err;
329
+ savestate_files["/state.bin"] = data[0];
330
+ savestate_files["/ram"] = data[1];
331
+ savestate_files["/vram"] = data[2];
332
+ savestate_files["/diskinfo.json"] = JSON.parse(u8tostr(data[3]));
333
+
334
+ wrap("emscripten_load_state")();
335
+
336
+ delete data[3]; // try to get this gc'ed
337
+
338
+ cb();
339
+ }, true);
340
+ };
341
+
342
+ /**
343
+ * Pause the emulator
344
+ * @param {boolean} paused
345
+ */
346
+ Halfix.prototype["pause"] = function (paused) {
347
+ this.paused = paused;
348
+ };
349
+
350
+ /**
351
+ * Send a fullscreen request to the brower.
352
+ */
353
+ Halfix.prototype["fullscreen"] = function () {
354
+ Module["requestFullscreen"]();
355
+ };
356
+ var cyclebase = 0;
357
+
358
+ function run_again(me, x) {
359
+ if (requests_in_progress !== 0) {
360
+ setTimeout(function () { run_again(me, x); }, x)
361
+ } else
362
+ me["run"]();
363
+ }
364
+
365
+ Halfix.prototype["run"] = function () {
366
+ if (this.paused) return;
367
+ try {
368
+ var x = run();
369
+ var temp;
370
+ var elapsed = (temp = new Date().getTime()) - now;
371
+ if (elapsed >= 1000) {
372
+ var curcycles = cycles();
373
+ this.reportSpeed(((curcycles - cyclebase) / (elapsed) / (1000)).toFixed(2));
374
+ //console.log(((curcycles - cyclebase) / (elapsed) / (1000)).toFixed(2));
375
+ //$("speed").innerHTML = ((curcycles - cyclebase) / (elapsed) / (1000)).toFixed(2);
376
+ cyclebase = curcycles;
377
+ now = temp;
378
+ }
379
+ var me = this;
380
+ setTimeout(function () {
381
+ run_again(me, x);
382
+ }, x);
383
+ } catch (e) {
384
+ $("error").innerHTML = "Exception thrown -- see JavaScript console";
385
+ $("messages").innerHTML = e.toString() + "<br />" + e.stack;
386
+ failed = true;
387
+ console.log(e);
388
+ throw e;
389
+ }
390
+ };
391
+
392
+ // ========================================================================
393
+ // Emscripten support code
394
+ // ========================================================================
395
+
396
+ var dynCall_vii, send_ctrlaltdel;
397
+ var cycles, now;
398
+ function run_wrapper2() {
399
+ wrap("emscripten_init")();
400
+
401
+ now = new Date().getTime();
402
+ cycles = wrap("emscripten_get_cycles");
403
+ get_now = wrap("emscripten_get_now");
404
+ dynCall_vii = wrap("emscripten_dyncall_vii");
405
+ run = wrap("emscripten_run");
406
+ send_ctrlaltdel = wrap("display_send_ctrl_alt_del");
407
+
408
+ wrap("emscripten_set_fast")(_halfix.fast);
409
+ init_cb();
410
+ }
411
+
412
+ // Initialize module instance
413
+ global["Module"] = {};
414
+
415
+ // Set up some stuff that we might find helpful
416
+
417
+ const SAVE_LOGS = true;
418
+ var arr = [];
419
+ Module["printErr"] = function (ln) { if (SAVE_LOGS) arr.push(ln); };
420
+ function save(filename, data) {
421
+ var blob = new Blob([data], { type: 'text/csv' });
422
+ if (window.navigator.msSaveOrOpenBlob) {
423
+ window.navigator.msSaveBlob(blob, filename);
424
+ }
425
+ else {
426
+ var elem = window.document.createElement('a');
427
+ elem.href = window.URL.createObjectURL(blob);
428
+ elem.download = filename;
429
+ document.body.appendChild(elem);
430
+ elem.click();
431
+ document.body.removeChild(elem);
432
+ }
433
+ }
434
+ function saveLog() {
435
+ save("test.txt", arr.join("\n"));
436
+ }
437
+ window["saveLog"] = saveLog;
438
+ Module["print"] = function (ln) { console.log(ln); };
439
+
440
+ global["update_screen"] = function () {
441
+ _halfix.updateScreen();
442
+ };
443
+
444
+ var requests_in_progress = 0;
445
+ /**
446
+ * @param {number} lenptr Pointer to length (type: int*)
447
+ * @param {number} dataptr Pointer to allocated data (type: void**)
448
+ * @param {number} Pointer to path (type: char*)
449
+ */
450
+ global["load_file_xhr"] = function (lenptr, dataptr, path) {
451
+ var pathstr = readstr(path);
452
+ var cb = function (err, data) {
453
+ if (err) throw err;
454
+
455
+ var destination = Module["_emscripten_alloc"](data.length, 4096);
456
+ memcpy(destination, data);
457
+
458
+ i32[lenptr >> 2] = data.length;
459
+ i32[dataptr >> 2] = destination;
460
+ requests_in_progress = requests_in_progress - 1 | 0;
461
+
462
+ if (requests_in_progress === 0) run_wrapper2();
463
+ };
464
+
465
+ // Increment requests in progress by one
466
+ requests_in_progress = requests_in_progress + 1 | 0;
467
+
468
+ if (pathstr.indexOf("!") !== -1) {
469
+ // If the user specified an arraybuffer or a file
470
+ var pathparts = pathstr.split("!");
471
+ var data = _cache[parseInt(pathparts[1])];
472
+ /** @type {WholeFileLoader} */
473
+ var driver = new xhr_replacements[pathparts[0]](data);
474
+ driver.load(cb);
475
+ } else loadFiles([pathstr], function (err, datas) {
476
+ cb(err, datas[0]);
477
+ }, false);
478
+
479
+ };
480
+
481
+ /**
482
+ * @param {number} fbptr Pointer to framebuffer information
483
+ * @param {number} x The width of the window
484
+ * @param {number} y The height of the window
485
+ */
486
+ global["update_size"] = function (fbptr, x, y) {
487
+ if (x == 0 || y == 0) return; // Don't do anything if x or y is zero (VGA resizing sometimes gives weird sizes)
488
+ Module["canvas"].width = x;
489
+ Module["canvas"].height = y;
490
+ _halfix.image_data = new ImageData(new Uint8ClampedArray(Module["HEAPU8"].buffer, fbptr, (x * y) << 2), x, y);
491
+ };
492
+
493
+ Module["onRuntimeInitialized"] = function () {
494
+ // Initialize runtime
495
+ u8 = Module["HEAPU8"];
496
+ u16 = Module["HEAPU16"];
497
+ i32 = Module["HEAP32"];
498
+
499
+ // Get pointer to configuration
500
+ var pc = Module["_emscripten_get_pc_config"]();
501
+
502
+ var cfg = _halfix.getConfiguration();
503
+
504
+ var area = alloc(cfg.length + 1);
505
+ strcpy(area, cfg);
506
+ Module["_parse_cfg"](pc, area);
507
+
508
+ var fast = _halfix.getBooleanByName("fast", false);
509
+ Module["_emscripten_set_fast"](fast);
510
+
511
+ // The story continues in global["load_file_xhr"], which loads the BIOS/VGA BIOS files
512
+
513
+ // Run some primitive garbage collection
514
+ gc();
515
+ };
516
+
517
+ global["drives"] = [];
518
+
519
+ global["drive_init"] = function (info_ptr, path, id) {
520
+ var p = readstr(path), image;
521
+ if (p.indexOf("!") !== -1) {
522
+ var chunks = p.split("!");
523
+ image = new image_backends[chunks[0]](_cache[parseInt(chunks[1]) | 0]);
524
+ } else
525
+ image = new XHRImage();
526
+ requests_in_progress = requests_in_progress + 1 | 0;
527
+ image.init(p, function (err, data) {
528
+ if (err) throw err;
529
+
530
+ var dataptr = alloc(data.length), strptr = alloc(p.length + 1);
531
+ memcpy(dataptr, data);
532
+ strcpy(strptr, p);
533
+ wrap("drive_emscripten_init")(info_ptr, strptr, dataptr, id);
534
+ gc();
535
+
536
+ global["drives"][id] = image;
537
+ requests_in_progress = requests_in_progress - 1 | 0;
538
+ if (requests_in_progress === 0) run_wrapper2();
539
+ });
540
+ };
541
+
542
+ // ========================================================================
543
+ // Data reading functions
544
+ // ========================================================================
545
+ /**
546
+ * @constructor
547
+ */
548
+ function WholeFileLoader() { }
549
+ /**
550
+ * Load a file
551
+ * @param {function} cb Callback
552
+ */
553
+ WholeFileLoader.prototype.load = function (cb) {
554
+ throw new Error("requires implementation");
555
+ };
556
+ /**
557
+ * @extends WholeFileLoader
558
+ * @constructor
559
+ * @param {ArrayBuffer} data
560
+ */
561
+ function ArrayBufferLoader(data) {
562
+ this.data = data;
563
+ }
564
+ ArrayBufferLoader.prototype = new WholeFileLoader();
565
+ ArrayBufferLoader.prototype.load = function (cb) {
566
+ cb(null, new Uint8Array(this.data));
567
+ };
568
+
569
+ /**
570
+ * @extends WholeFileLoader
571
+ * @constructor
572
+ * @param {File} file
573
+ */
574
+ function FileReaderLoader(file) {
575
+ this.file = file;
576
+ }
577
+ FileReaderLoader.prototype = new WholeFileLoader();
578
+ FileReaderLoader.prototype.load = function (cb) {
579
+ var fr = new FileReader();
580
+ fr.onload = function () {
581
+ cb(null, new Uint8Array(fr.result));
582
+ };
583
+ fr.onerror = function (e) {
584
+ cb(e, null);
585
+ };
586
+ fr.onabort = function () {
587
+ cb(new Error("filereader aborted"), null);
588
+ };
589
+ fr.readAsArrayBuffer(this.file);
590
+ };
591
+ // see load_file_xhr
592
+ var xhr_replacements = {
593
+ "file": FileReaderLoader,
594
+ "ab": ArrayBufferLoader
595
+ };
596
+
597
+ /**
598
+ * Generic hard drive image. All you have to do is fill in
599
+ * @constructor
600
+ */
601
+ function HardDriveImage() {
602
+ /** @type {Uint8Array[]} */
603
+ this.blocks = [];
604
+
605
+ /** @type {string[]} */
606
+ this.request_queue = [];
607
+
608
+ /** @type {number[]} */
609
+ this.request_queue_ids = [];
610
+
611
+ /** @type {number} */
612
+ this.cb = 0;
613
+ /** @type {number} */
614
+ this.arg1 = 0;
615
+ }
616
+ /**
617
+ * Adds a block to the cache. Called on IDE writes, typically
618
+ *
619
+ * @param {number} id
620
+ * @param {number} offset Offset in memory to read from
621
+ * @param {number} length
622
+ */
623
+ HardDriveImage.prototype["addCache"] = function (id, offset, length) {
624
+ this.blocks[id] = u8.slice(offset, length + offset | 0);
625
+ };
626
+ /**
627
+ * Reads a section of a block from the cache
628
+ *
629
+ * See src/drive.c: drive_read_block_internal
630
+ *
631
+ * @param {number} id Block ID
632
+ * @param {number} buffer Position in the buffer
633
+ * @param {number} offset Offset in the block to read from
634
+ * @param {number} length Number of bytes to read
635
+ */
636
+ HardDriveImage.prototype["readCache"] = function (id, buffer, offset, length) {
637
+ id = id | 0;
638
+ if (!this.blocks[id]) {
639
+ //printElt.value += "[JSError] readCache(id=0x" + id.toString(16) + ", buffer=0x" + buffer.toString(16) + ", length=0x" + buffer.toString(16) + ")\n";
640
+ return 1; // No block here with that data.
641
+ }
642
+ var buf = this.blocks[id].subarray(offset, length + offset | 0);
643
+ if (buf.length > length) throw new Error("Block too long");
644
+ u8.set(this.blocks[id].subarray(offset, length + offset | 0), buffer);
645
+ return 0;
646
+ };
647
+ /**
648
+ * Writes a section of a block with some data
649
+ *
650
+ * See src/drive.c: drive_write_block_internal
651
+ *
652
+ * @param {number} id Block ID
653
+ * @param {number} buffer Position in the buffer
654
+ * @param {number} offset Offset in the block to read from
655
+ * @param {number} length Number of bytes to read
656
+ */
657
+ HardDriveImage.prototype["writeCache"] = function (id, buffer, offset, length) {
658
+ id = id | 0;
659
+ if (!this.blocks[id]) {
660
+ //printElt.value += "[JSError] writeCache(id=0x" + id.toString(16) + ", buffer=0x" + buffer.toString(16) + ", length=0x" + buffer.toString(16) + ")\n";
661
+ return 1; // No block here with that data.
662
+ }
663
+ var buf = u8.subarray(buffer, length + buffer | 0);
664
+ if (buf.length > length) throw new Error("Block too long");
665
+ this.blocks[id].set(buf, offset);
666
+ return 0;
667
+ };
668
+ /**
669
+ * Queues a memory read. Useful for multi-block reads
670
+ *
671
+ * @param {number} str Pointer to URL
672
+ * @param {number} id Block ID to store it in
673
+ */
674
+ HardDriveImage.prototype["readQueue"] = function (str, id) {
675
+ this.request_queue.push(readstr(str));
676
+ this.request_queue_ids.push(id);
677
+ };
678
+
679
+ /**
680
+ * Runs all requests simultaneously.
681
+ *
682
+ * @param {number} cb Callback pointer
683
+ * @param {number} arg1 Callback argument
684
+ */
685
+ HardDriveImage.prototype["flushReadQueue"] = function (cb, arg1) {
686
+ /** @type {HardDriveImage} */
687
+ var me = this;
688
+
689
+ this.cb = cb;
690
+ this.arg1 = arg1;
691
+
692
+ this.load(this.request_queue, function (err, data) {
693
+ if (err) throw err;
694
+
695
+ var rql = me.request_queue.length;
696
+ for (var i = 0; i < rql; i = i + 1 | 0)
697
+ me.blocks[me.request_queue_ids[i]] = data[i];
698
+
699
+ // Empty request queue
700
+ me.request_queue = [];
701
+ me.request_queue_ids = [];
702
+
703
+ me.callback(0);
704
+ }, true);
705
+ };
706
+ /**
707
+ * Call an Emscripten callback
708
+ * @type {number} res
709
+ */
710
+ HardDriveImage.prototype.callback = function (res) {
711
+ fptr_vii(this.cb | 0, this.arg1 | 0, res | 0);
712
+ };
713
+ /**
714
+ * @param {string[]} paths
715
+ * @param {function(object,Uint8Array[])} cb
716
+ *
717
+ * Note that all Uint8Arrays passed back to cb MUST be BLOCK_SIZE bytes long
718
+ */
719
+ HardDriveImage.prototype.load = function (reqs, cb) {
720
+ throw new Error("implement me");
721
+ };
722
+
723
+ /**
724
+ * Initialize hard drive image
725
+ * @param {string} arg
726
+ * @param {function(Uint8Array)} cb
727
+ */
728
+ HardDriveImage.prototype.init = function (arg, cb) {
729
+ throw new Error("implement me");
730
+ };
731
+
732
+ /**
733
+ * Convert a URL (i.e. os2/blk0000005a.bin) into a number (i.e. 0x5a)
734
+ * @param {string} str
735
+ * @return {number}
736
+ */
737
+ function _url_to_blkid(str) {
738
+ var parts = str.match(/blk([0-9a-f]{8})\.bin/);
739
+ return parseInt(parts[1], 16) >>> 0;
740
+ }
741
+
742
+ /**
743
+ * Create an "info.dat" file
744
+ * @param {number} size
745
+ * @param {number} blksize
746
+ * @returns {Uint8Array} The data that would have been contained in info.dat
747
+ */
748
+ function _construct_info(size, blksize) {
749
+ var i32 = new Int32Array(2);
750
+ i32[0] = size;
751
+ i32[1] = blksize;
752
+ return new Uint8Array(i32.buffer);
753
+ }
754
+
755
+ /**
756
+ * ArrayBuffer-backed image
757
+ * @param {ArrayBuffer} ab
758
+ * @constructor
759
+ * @extends HardDriveImage
760
+ */
761
+ function ArrayBufferImage(ab) {
762
+ this.data = new Uint8Array(ab);
763
+ }
764
+ ArrayBufferImage.prototype = new HardDriveImage();
765
+ /**
766
+ * @param {string[]} paths
767
+ * @param {function(object,Uint8Array[])} cb
768
+ */
769
+ ArrayBufferImage.prototype.load = function (reqs, cb) {
770
+ var data = [];
771
+ for (var i = 0; i < reqs.length; i = i + 1 | 0) {
772
+ // note to self: Math.log(256*1024)/Math.log(2) === 18
773
+ var blockoffs = (_url_to_blkid(i) << 18) >>> 0;
774
+ data[i] = this.data.slice(blockoffs, (blockoffs + (256 << 10)) >>> 0);
775
+ }
776
+ setTimeout(function () {
777
+ cb(null, data);
778
+ }, 0);
779
+ };
780
+ ArrayBufferImage.prototype.init = function (arg, cb) {
781
+ var data = _construct_info(this.data.byteLength, 256 << 10);
782
+ setTimeout(function () {
783
+ cb(null, data);
784
+ }, 0);
785
+ };
786
+
787
+ /**
788
+ * File API-backed image
789
+ * @param {File} f
790
+ * @constructor
791
+ * @extends HardDriveImage
792
+ */
793
+ function FileImage(f) {
794
+ this.file = finalResponse;
795
+ }
796
+ FileImage.prototype = new HardDriveImage();
797
+ FileImage.prototype.load = function (reqs, cb) {
798
+ console.log(reqs);
799
+ // Ensure that loads are in order and consecutive, which speeds things up
800
+ var blockBase = _url_to_blkid(reqs[0]);
801
+ for (var i = 1; i < reqs.length; i = i + 1 | 0)
802
+ if ((_url_to_blkid(reqs[i]) - i | 0) !== blockBase) throw new Error("non-consecutive reads");
803
+ var blocks = reqs.length;
804
+
805
+ /** @type {File} */
806
+ var fileslice = this.file.slice((blockBase << 18) >>> 0, ((blockBase + blocks) << 18) >>> 0);
807
+
808
+ var fr = new FileReader();
809
+ fr.onload = function () {
810
+ var arr = [];
811
+ for (var i = 0; i < reqs.length; i = i + 1 | 0) {
812
+ // Slice a 256 KB chunk of the file
813
+ arr.push(new Uint8Array(fr.result.slice(i << 18, (i + 1) << 18)));
814
+ }
815
+ cb(null, arr);
816
+ };
817
+ fr.onerror = function (e) {
818
+ cb(e, null);
819
+ };
820
+ fr.onabort = function () {
821
+ cb(new Error("filereader aborted"), null);
822
+ };
823
+ fr.readAsArrayBuffer(fileslice);
824
+ };
825
+ FileImage.prototype.init = function (arg, cb) {
826
+ var data = _construct_info(this.file.size, 256 << 10);
827
+ setTimeout(function () {
828
+ cb(null, data);
829
+ }, 0);
830
+ };
831
+
832
+ /**
833
+ * XHR-backed image
834
+ * @constructor
835
+ * @extends HardDriveImage
836
+ */
837
+ function XHRImage() {
838
+ }
839
+ XHRImage.prototype = new HardDriveImage();
840
+ XHRImage.prototype.load = function (reqs, cb) {
841
+ loadFiles(reqs, cb, true);
842
+ };
843
+ XHRImage.prototype.init = function (arg, cb) {
844
+ loadFiles([join_path(arg, "info.dat")], function (err, data) {
845
+ if (err) throw err;
846
+ cb(null, data[0]);
847
+ });
848
+ };
849
+
850
+ var image_backends = {
851
+ "file": FileImage,
852
+ "ab": ArrayBufferImage
853
+ };
854
+
855
+ // ========================================================================
856
+ // Useful functions
857
+ // ========================================================================
858
+
859
+ var _allocs = [];
860
+ /**
861
+ * Allocates a patch of memory in Emscripten. Returns the address pointer
862
+ * @param {number} size
863
+ * @return {number} Address
864
+ */
865
+ function alloc(size) {
866
+ var n = Module["_malloc"](size);
867
+ _allocs.push(n);
868
+ return n;
869
+ }
870
+
871
+ var u8 = null, u16 = null, i32 = null;
872
+ /**
873
+ * Copy a string into memory
874
+ * @param {number} dest
875
+ * @param {string} src
876
+ */
877
+ function strcpy(dest, src) {
878
+ var srclen = src.length | 0;
879
+ for (var i = 0; i < srclen; i = i + 1 | 0)
880
+ u8[i + dest | 0] = src.charCodeAt(i);
881
+ u8[dest + srclen | 0] = 0; // End with NULL terminator
882
+ }
883
+ /**
884
+ * Copy a Uint8Array into memory
885
+ * @param {number} dest
886
+ * @param {Uint8Array} src
887
+ */
888
+ function memcpy(dest, src) {
889
+ var srclen = src.length | 0;
890
+ for (var i = 0; i < srclen; i = i + 1 | 0)
891
+ u8[i + dest | 0] = src[i | 0];
892
+ }
893
+
894
+ /**
895
+ * Frees every single patch of memory we have reserved with alloc()
896
+ */
897
+ function gc() {
898
+ var free = Module["_free"];
899
+ for (var i = 0; i < _allocs.length; i = i + 1 | 0) free(_allocs[i]);
900
+ _allocs = [];
901
+ }
902
+
903
+ /**
904
+ * Call an Emscripten function pointer with the signature void func(int, int);
905
+ * @param {number} cb The function pointer itself
906
+ * @param {number} cb_ptr The first argument
907
+ * @param {number} arg2 The second argument
908
+ */
909
+ function fptr_vii(cb, cb_ptr, arg2) {
910
+ dynCall_vii(cb, cb_ptr, arg2);
911
+ }
912
+ /**
913
+ * Copy a string into JavaScript
914
+ * @param {number} src
915
+ */
916
+ function readstr(src) {
917
+ var str = "";
918
+ while (u8[src] !== 0) {
919
+ str += String.fromCharCode(u8[src]);
920
+ src = src + 1 | 0;
921
+ }
922
+ return str;
923
+ }
924
+
925
+ // Returns a pointer to an Emscripten-compiled function
926
+ function wrap(nm) {
927
+ return Module["_" + nm];
928
+ }
929
+
930
+ /**
931
+ * Join two fragments of a path together
932
+ * @param {string} a The first part of the path
933
+ * @param {string} b The second part of the path
934
+ */
935
+ function join_path(a, b) {
936
+ if (b.charAt(0) !== "/")
937
+ b = "/" + b;
938
+ if (a.charAt(a.length - 1 | 0) === "/")
939
+ a = a.substring(0, a.length - 1 | 0);
940
+ return a + b; //normalize_path(a + b);
941
+ }
942
+
943
+ // Some more savestate-related functions
944
+ /**
945
+ * Load file from file cache
946
+ * @param {number} pathstr Pointer to path string
947
+ * @param {number} addr Address to load the data
948
+ */
949
+ window["loadFile"] = function (pathstr, addr) {
950
+ var path = readstr(pathstr);
951
+ var data = savestate_files[path];
952
+ if (!data) throw new Error("ENOENT: " + path);
953
+ memcpy(addr, data);
954
+ return addr;
955
+ };
956
+ /**
957
+ * Load file from file cache and allocate a buffer to store it in.
958
+ * It is the responsibility of the caller to free the memory.
959
+ * @param {number} pathstr Pointer to path string
960
+ * @param {number} addr Address to load the data
961
+ */
962
+ window["loadFile2"] = function (pathstr, addr) {
963
+ var path = readstr(pathstr);
964
+ var data = savestate_files[path];
965
+ if (!data) throw new Error("ENOENT: " + path);
966
+ var len = data.length;
967
+ var addr = alloc(len);
968
+ _allocs.pop();
969
+ memcpy(addr, data);
970
+ console.log(path, data, addr);
971
+ return addr;
972
+ };
973
+
974
+ if (typeof module !== "undefined" && module["exports"])
975
+ module["exports"] = Halfix;
976
+ else
977
+ global["Halfix"] = Halfix;
978
+ })(typeof window !== "undefined" ? window : global);
VirtualXPVGA.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a071b5a9608c0b9e5e6918480964a37b05ec1744c166c68d3d54f7d64176d889
3
+ size 41472
b2_download_file_by_id.iso ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:277a3848d7275fb43610a506b134931018df4f512dc73cf28bd090b4a52f2fa7
3
+ size 64520648
index.html CHANGED
@@ -1,426 +1,212 @@
1
  <!DOCTYPE html>
2
  <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>V86 x86 PC Emulator</title>
7
- <link rel="stylesheet" href="v86.css">
8
- <script src="v86_all.js"></script>
9
- <style>
10
- body {
11
- font-family: Arial, sans-serif;
12
- background: #111;
13
- color: #eee;
14
- margin: 0;
15
- padding: 20px;
16
- max-width: 1200px;
17
- margin: auto;
18
- }
19
- #boot_options {
20
- background: #222;
21
- padding: 20px;
22
- border-radius: 8px;
23
- box-shadow: 0 4px 8px rgba(0,0,0,0.5);
24
- }
25
- h2 {
26
- margin: 0 0 15px 0;
27
- color: #fff;
28
- }
29
- table {
30
- width: 100%;
31
- border-collapse: collapse;
32
- margin: 15px 0;
33
- }
34
- th, td {
35
- padding: 12px;
36
- text-align: left;
37
- border-bottom: 1px solid #555;
38
- }
39
- input[type="file"], input[type="url"], select, button {
40
- padding: 8px;
41
- background: #333;
42
- color: #eee;
43
- border: 1px solid #555;
44
- border-radius: 4px;
45
- width: 100%;
46
- box-sizing: border-box;
47
- }
48
- input[type="url"] { width: 70%; }
49
- button {
50
- background: #2a4;
51
- cursor: pointer;
52
- font-weight: bold;
53
- width: auto;
54
- margin-top: 10px;
55
- }
56
- button:hover:not(:disabled) {
57
- background: #3b5;
58
- }
59
- button:disabled {
60
- background: #555;
61
- cursor: not-allowed;
62
- }
63
- .info {
64
- font-size: 12px;
65
- color: #bbb;
66
- margin-top: 5px;
67
- }
68
- .url-note {
69
- font-size: 11px;
70
- color: #ff6;
71
- margin-top: 2px;
72
- }
73
- #status {
74
- margin-top: 15px;
75
- padding: 10px;
76
- border-radius: 4px;
77
- font-weight: bold;
78
- }
79
- #runtime_options {
80
- margin: 10px 0;
81
- }
82
- #runtime_options button {
83
- margin-right: 10px;
84
- padding: 10px;
85
- width: auto;
86
- }
87
- #screen_container {
88
- position: relative;
89
- background: #000;
90
- margin: 20px 0;
91
- border: 2px solid #333;
92
- border-radius: 8px;
93
- overflow: hidden;
94
- }
95
- #debug_console {
96
- position: fixed;
97
- bottom: 0;
98
- left: 0;
99
- right: 0;
100
- background: #000;
101
- color: #0f0;
102
- padding: 10px;
103
- font-family: monospace;
104
- font-size: 12px;
105
- max-height: 200px;
106
- overflow-y: auto;
107
- border-top: 2px solid #0f0;
108
- z-index: 1000;
109
- display: block;
110
- }
111
- .demo-note {
112
- background: #333;
113
- padding: 15px;
114
- border-radius: 4px;
115
- margin: 15px 0;
116
- color: #ff6;
117
- }
118
- @media (max-width: 768px) {
119
- body { padding: 10px; }
120
- table { font-size: 14px; }
121
- input[type="url"] { width: 100%; }
122
- #debug_console { font-size: 10px; max-height: 150px; }
123
- }
124
- </style>
125
- </head>
126
- <body>
127
-
128
- <div id="boot_options">
129
- <h2>🖥️ V86 x86 PC Emulator</h2>
130
- <p>Load disk images via file upload or URL (direct link to ISO/IMG/BIN/IMA from any site).</p>
131
-
132
- <div class="demo-note">
133
- <strong>URL Tip:</strong> Use raw links (e.g., GitHub: raw.githubusercontent.com/user/repo/main/file.iso). CORS may block some sites – fallback to file upload.
134
- </div>
135
-
136
- <table>
137
- <tr>
138
- <th width="200">Boot Device</th>
139
- <th>URL or File</th>
140
- </tr>
141
- <tr>
142
- <td>CD/DVD Image</td>
143
- <td>
144
- <input type="url" id="cd_url" placeholder="https://example.com/image.iso">
145
- <div class="url-note">Enter direct URL (optional)</div>
146
- <input type="file" id="cd_file" accept=".iso,.img,.bin">
147
- <div id="cd_info" class="info">No URL or file selected</div>
148
- </td>
149
- </tr>
150
- <tr>
151
- <td>Floppy Disk Image</td>
152
- <td>
153
- <input type="url" id="floppy_url" placeholder="https://example.com/disk.ima">
154
- <div class="url-note">Enter direct URL (optional)</div>
155
- <input type="file" id="floppy_file" accept=".ima,.img">
156
- <div id="floppy_info" class="info">No URL or file selected</div>
157
- </td>
158
- </tr>
159
- <tr>
160
- <td>Hard Disk Image</td>
161
- <td>
162
- <input type="url" id="hda_url" placeholder="https://example.com/hdd.img">
163
- <div class="url-note">Enter direct URL (optional)</div>
164
- <input type="file" id="hda_file" accept=".img,.bin">
165
- <div id="hda_info" class="info">No URL or file selected</div>
166
- </td>
167
- </tr>
168
- <tr>
169
- <td colspan="2"><hr></td>
170
- </tr>
171
- <tr>
172
- <td>Memory Size</td>
173
- <td><input type="number" id="memory_size" value="256" min="16" max="2048" step="64"> MB</td>
174
- </tr>
175
- <tr>
176
- <td>Video Memory</td>
177
- <td><input type="number" id="vga_memory_size" value="8" min="1" max="64" step="1"> MB</td>
178
- </tr>
179
- <tr>
180
- <td>Boot Order</td>
181
- <td>
182
- <select id="boot_order">
183
- <option value="213">CD → Floppy → HDD</option>
184
- <option value="123">CD → HDD → Floppy</option>
185
- <option value="231">Floppy CD HDD</option>
186
- <option value="321">Floppy → HDD → CD</option>
187
- <option value="312">HDD → Floppy → CD</option>
188
- <option value="132">HDD → CD → Floppy</option>
189
- </select>
190
- </td>
191
- </tr>
192
- </table>
193
-
194
- <br>
195
- <button id="start_emulation" disabled>🚀 Start Emulator</button>
196
- <div id="status"></div>
197
- </div>
198
-
199
- <div id="runtime_options" style="display: none;">
200
- <button id="pause_btn">⏸️ Pause</button>
201
- <button id="reset_btn">🔄 Reset</button>
202
- <button id="exit_btn">❌ Exit</button>
203
- <button id="send_cad">⌨️ Ctrl+Alt+Del</button>
204
- </div>
205
-
206
- <div id="screen_container" style="display: none; position: relative; background: #000; margin: 20px 0; border: 2px solid #333; border-radius: 8px;">
207
- <div id="screen"></div>
208
- <canvas id="vga" style="width: 100%; height: auto; display: block;"></canvas>
209
- <div style="position: absolute; top: 0; z-index: 10; pointer-events: none;">
210
- <textarea class="phone_keyboard" style="opacity: 0; position: absolute;"></textarea>
211
- </div>
212
- </div>
213
-
214
- <div id="debug_console">
215
- <div style="color: #ff6; font-weight: bold;">DEBUG CONSOLE (Hugging Face + URL Support)</div>
216
- <div id="debug_output"></div>
217
- </div>
218
-
219
- <script>
220
- (function() {
221
- const debugLog = (msg) => {
222
- const output = document.getElementById('debug_output');
223
- const time = new Date().toLocaleTimeString();
224
- output.innerHTML += `<div>[${time}] ${msg}</div>`;
225
- output.scrollTop = output.scrollHeight;
226
- console.log(msg);
227
- };
228
-
229
- debugLog('V86 Loaded - URL + File Mode Ready');
230
-
231
- const devices = [
232
- { urlId: 'cd_url', fileId: 'cd_file', infoId: 'cd_info', key: 'cdrom', accept: '.iso,.img,.bin' },
233
- { urlId: 'floppy_url', fileId: 'floppy_file', infoId: 'floppy_info', key: 'fda', accept: '.ima,.img' },
234
- { urlId: 'hda_url', fileId: 'hda_file', infoId: 'hda_info', key: 'hda', accept: '.img,.bin' }
235
- ];
236
-
237
- let loadedBuffers = {};
238
-
239
- // Handle URL or File input
240
- devices.forEach(device => {
241
- const urlInput = document.getElementById(device.urlId);
242
- const fileInput = document.getElementById(device.fileId);
243
- const info = document.getElementById(device.infoId);
244
-
245
- const updateInfo = (type, name, size) => {
246
- info.textContent = type === 'url' ? `URL: ${name}` : `File: ${name} (${(size / (1024*1024)).toFixed(2)} MB)`;
247
- info.style.color = '#0f0';
248
- checkReady();
249
- };
250
-
251
- const clearInfo = () => {
252
- info.textContent = 'No URL or file selected';
253
- info.style.color = '#bbb';
254
- delete loadedBuffers[device.key];
255
- checkReady();
256
- };
257
-
258
- // URL input (load on blur or start)
259
- urlInput.addEventListener('input', () => {
260
- if (urlInput.value.trim()) {
261
- updateInfo('url', urlInput.value, null);
262
- debugLog(`URL entered for ${device.key}: ${urlInput.value}`);
263
- } else {
264
- clearInfo();
265
- }
266
- });
267
-
268
- // File input
269
- fileInput.addEventListener('change', (e) => {
270
- const file = e.target.files[0];
271
- if (file) {
272
- updateInfo('file', file.name, file.size);
273
- debugLog(`File selected for ${device.key}: ${file.name}`);
274
- } else {
275
- clearInfo();
276
- }
277
- });
278
- });
279
-
280
- const checkReady = () => {
281
- const startBtn = document.getElementById('start_emulation');
282
- const hasInput = devices.some(d => {
283
- const urlVal = document.getElementById(d.urlId).value.trim();
284
- const fileVal = document.getElementById(d.fileId).files.length > 0;
285
- return urlVal || fileVal;
286
- });
287
- startBtn.disabled = !hasInput;
288
- };
289
-
290
- // Fetch buffer from URL
291
- const fetchBuffer = async (url) => {
292
- debugLog(`Fetching URL: ${url}`);
293
- const response = await fetch(url);
294
- if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);
295
- const buffer = await response.arrayBuffer();
296
- const sizeMB = (buffer.byteLength / (1024 * 1024)).toFixed(2);
297
- debugLog(`✓ Fetched: ${sizeMB} MB from ${url}`);
298
- return buffer;
299
- };
300
-
301
- // V86 Starter
302
- let emulator = null;
303
-
304
- document.getElementById('start_emulation').addEventListener('click', async () => {
305
- debugLog('=== Starting Emulation ===');
306
- const status = document.getElementById('status');
307
- status.textContent = 'Loading images...';
308
- status.style.color = '#ff6';
309
-
310
- if (typeof V86Starter !== 'function') {
311
- status.style.color = '#f88';
312
- status.textContent = 'Error: V86 library not loaded.';
313
- debugLog('ERROR: V86Starter unavailable');
314
- return;
315
- }
316
-
317
- const memoryMB = parseInt(document.getElementById('memory_size').value) || 256;
318
- const vgaMB = parseInt(document.getElementById('vga_memory_size').value) || 8;
319
- const bootOrder = parseInt(document.getElementById('boot_order').value) || 213;
320
-
321
- debugLog(`Config: ${memoryMB}MB RAM, ${vgaMB}MB VRAM, Boot: ${bootOrder}`);
322
-
323
- const options = {
324
- wasm_path: 'v86.wasm',
325
- memory_size: memoryMB * 1024 * 1024,
326
- vga_memory_size: vgaMB * 1024 * 1024,
327
- screen_container: document.getElementById('screen_container'),
328
- bios: { url: 'bios/seabios.bin' },
329
- vga_bios: { url: 'bios/vgabios.bin' },
330
- boot_order: bootOrder,
331
- autostart: true
332
- };
333
-
334
- // Load for each device
335
- for (const device of devices) {
336
- const url = document.getElementById(device.urlId).value.trim();
337
- const file = document.getElementById(device.fileId).files[0];
338
-
339
- if (url || file) {
340
- try {
341
- let buffer;
342
- if (url) {
343
- status.textContent = `Fetching ${url}...`;
344
- buffer = await fetchBuffer(url);
345
- } else if (file) {
346
- status.textContent = `Reading ${file.name}...`;
347
- buffer = await new Promise((resolve, reject) => {
348
- const reader = new FileReader();
349
- reader.onload = () => resolve(reader.result);
350
- reader.onerror = reject;
351
- reader.readAsArrayBuffer(file);
352
- });
353
- }
354
- loadedBuffers[device.key] = buffer;
355
- debugLog(`✓ Loaded ${device.key}: ${(buffer.byteLength / (1024*1024)).toFixed(2)} MB`);
356
- } catch (err) {
357
- status.style.color = '#f88';
358
- status.textContent = `Failed to load ${url || file.name}: ${err.message}`;
359
- debugLog(`ERROR for ${device.key}: ${err.message}`);
360
- return;
361
- }
362
- }
363
- }
364
-
365
- if (Object.keys(loadedBuffers).length === 0) {
366
- status.style.color = '#f88';
367
- status.textContent = 'No valid input!';
368
- return;
369
- }
370
-
371
- // Assign to options
372
- if (loadedBuffers.cdrom) options.cdrom = { buffer: loadedBuffers.cdrom };
373
- if (loadedBuffers.fda) options.fda = { buffer: loadedBuffers.fda };
374
- if (loadedBuffers.hda) options.hda = { buffer: loadedBuffers.hda };
375
-
376
- // Show emulator
377
- document.getElementById('boot_options').style.display = 'none';
378
- document.getElementById('screen_container').style.display = 'block';
379
- document.getElementById('runtime_options').style.display = 'block';
380
- status.textContent = 'Starting emulator...';
381
-
382
- try {
383
- emulator = new V86Starter(options);
384
- debugLog('Emulator started!');
385
- status.style.color = '#0f0';
386
- status.textContent = 'Running!';
387
- } catch (err) {
388
- status.style.color = '#f88';
389
- status.textContent = `Failed: ${err.message}`;
390
- debugLog(`FATAL: ${err.message}`);
391
- }
392
- });
393
-
394
- // Runtime controls (same as before)
395
- document.getElementById('pause_btn').addEventListener('click', () => { if (emulator) emulator.stop?.(); debugLog('Paused'); });
396
- document.getElementById('reset_btn').addEventListener('click', () => { if (emulator) emulator.restart?.(); debugLog('Reset'); });
397
- document.getElementById('send_cad').addEventListener('click', () => { if (emulator) emulator.keyboard_send_scancodes?.([0x1D, 0x38, 0x53]); debugLog('Ctrl+Alt+Del'); });
398
- document.getElementById('exit_btn').addEventListener('click', () => {
399
- if (emulator) emulator.stop?.();
400
- document.getElementById('boot_options').style.display = 'block';
401
- document.getElementById('runtime_options').style.display = 'none';
402
- document.getElementById('screen_container').style.display = 'none';
403
- document.getElementById('status').textContent = '';
404
- loadedBuffers = {};
405
- devices.forEach(d => {
406
- document.getElementById(d.urlId).value = '';
407
- document.getElementById(d.fileId).value = '';
408
- document.getElementById(d.infoId).textContent = 'No URL or file selected';
409
- document.getElementById(d.infoId).style.color = '#bbb';
410
- });
411
- checkReady();
412
- debugLog('Exited');
413
- });
414
-
415
- // Keyboard shortcut for CAD
416
- document.addEventListener('keydown', (e) => {
417
- if (e.ctrlKey && e.altKey && e.key === 'Delete') document.getElementById('send_cad').click();
418
- });
419
-
420
- checkReady();
421
- debugLog('Setup complete - Enter URL or select file to boot');
422
- })();
423
- </script>
424
-
425
- </body>
426
- </html>
 
1
  <!DOCTYPE html>
2
  <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>VirtualXP</title>
6
+ <meta property="og:title" content="VirtualXP"/>
7
+ <meta property="og:url" content="https://lrusso.github.io/VirtualXP/VirtualXP.htm"/>
8
+ <meta property="og:description" content="info@lrusso.com"/>
9
+ <meta property="og:image" content="https://lrusso.github.io/VirtualXP/VirtualXPShare.png"/>
10
+ <meta property="og:type" content="website"/>
11
+ <meta property="og:site_name" content="VirtualXP"/>
12
+ <meta name="theme-color" content="#000000"/>
13
+ <meta name="mobile-web-app-capable" content="yes"/>
14
+ <meta name="apple-mobile-web-app-capable" content="yes"/>
15
+ <link rel="manifest" href="VirtualXP.json"/>
16
+ <link rel="icon" sizes="16x16" type="image/png" href="VirtualXPFavIcon_16x16.png"/>
17
+ <link rel="icon" sizes="192x192" type="image/png" href="VirtualXPFavIcon_192x192.png"/>
18
+ <link rel="apple-touch-icon" href="data:image/png;base64,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">
19
+ <link rel="apple-touch-startup-image" href="data:image/png;base64,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">
20
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, user-scalable=no"/>
21
+ <style>
22
+ html,body{background-color:black;margin:0;padding:0;-webkit-user-select:none;-moz-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;cursor:default}
23
+ #canvas{position:fixed;left:0;right:0;top:0;bottom:0;height:100%;width:100%}
24
+
25
+ .percentage{position:fixed;width:64px;height:64px;left:0;right:0;top:120px;bottom:0;margin:auto auto;border:0;font-family:Arial;font-weight:bold;font-size:20px;background-color:black;color:white;text-align:center}
26
+ .pleasewait{position:fixed;width:64px;height:64px;left:0;right:0;top:-50px;bottom:0;margin:auto auto;border:0}
27
+ .lds-spinner{color:white;display:inline-block;position:relative;width:64px;height:64px}
28
+ .lds-spinner div{transform-origin:32px 32px;animation:lds-spinner 1.2s linear infinite}
29
+ .lds-spinner div:after{content:" ";display:block;position:fixed;top:3px;left:29px;width:5px;height:14px;border-radius:20%;background:white}
30
+ .lds-spinner div:nth-child(1){transform:rotate(0deg);animation-delay:-1.1s}
31
+ .lds-spinner div:nth-child(2){transform:rotate(30deg);animation-delay:-1s}
32
+ .lds-spinner div:nth-child(3){transform:rotate(60deg);animation-delay:-0.9s}
33
+ .lds-spinner div:nth-child(4){transform:rotate(90deg);animation-delay:-0.8s}
34
+ .lds-spinner div:nth-child(5){transform:rotate(120deg);animation-delay:-0.7s}
35
+ .lds-spinner div:nth-child(6){transform:rotate(150deg);animation-delay:-0.6s}
36
+ .lds-spinner div:nth-child(7){transform:rotate(180deg);animation-delay:-0.5s}
37
+ .lds-spinner div:nth-child(8){transform:rotate(210deg);animation-delay:-0.4s}
38
+ .lds-spinner div:nth-child(9){transform:rotate(240deg);animation-delay:-0.3s}
39
+ .lds-spinner div:nth-child(10){transform:rotate(270deg);animation-delay:-0.2s}
40
+ .lds-spinner div:nth-child(11){transform:rotate(300deg);animation-delay:-0.1s}
41
+ .lds-spinner div:nth-child(12){transform:rotate(330deg);animation-delay:0s}
42
+ @keyframes lds-spinner{0%{opacity:1}100%{opacity:0}}
43
+ </style>
44
+ </head>
45
+ <body>
46
+ <div class="pleasewait"><div class="lds-spinner"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div></div>
47
+ <div class="percentage"></div>
48
+ <canvas id="canvas" height="640" width="480"></canvas>
49
+
50
+ <script src="VirtualXPLoader.js"></script>
51
+ <script>
52
+ var finalResponse;
53
+
54
+ // FUNCTION FOR GETTING THE ISO IMAGE
55
+ function getISOImage()
56
+ {
57
+ // CREATING THE REQUEST
58
+ var oReq = new XMLHttpRequest();
59
+
60
+ // SETTING WHICH FILE MUST BE OBTAINED
61
+ oReq.open("GET", "VirtualXP.iso", true);
62
+
63
+ // SETTING THE RESPONSE TYPE
64
+ oReq.responseType = "blob";
65
+
66
+ // SETTING WHAT WILL HAPPEN WHEN THE REQUEST IS FULLY LOADED
67
+ oReq.onload = function (oEvent)
68
+ {
69
+ // CHECKING IF THE REQUEST IT'S DONE
70
+ if (oReq.readyState==oReq.DONE)
71
+ {
72
+ // CHECKING IF THE REQUEST STATUS
73
+ if (oReq.status==200)
74
+ {
75
+ // GETTING THE RESPONSE CONTENT
76
+ finalResponse = oReq.response;
77
+
78
+ // SETTING THE OPTIONS FOR THE EMULATOR
79
+ var opts = {reportSpeed: function(s){document.title = "VirtualXP - " + s + " MIPS";}};
80
+ opts.mem = "192";
81
+ opts.vgamem = "16";
82
+ opts.fast = true;
83
+ opts.bios = "VirtualXPBIOS.bin";
84
+ opts.vgabios = "VirtualXPVGA.bin";
85
+ opts.apic = false;
86
+ opts.acpi = false;
87
+ opts.pci = false;
88
+ opts.pcivga = false;
89
+ opts.floppy = false;
90
+ opts.winnt_hack = true;
91
+ opts.canvas = document.getElementById("canvas");
92
+ opts["cda"] = new File(["empty.txt"], "filename");
93
+
94
+ // CREATING THE EMULATOR
95
+ var halfix = new Halfix(opts);
96
+ halfix.init(function()
97
+ {
98
+ // RUNNING THE EMULATOR
99
+ halfix.run();
100
+
101
+ // FORCING TO UPDATE THE SCREEN EVERY 1 SECOND
102
+ setInterval(function(){try{halfix.updateScreen();}catch(err){}}, 1000);
103
+
104
+ // WAITING 5 SECONDS
105
+ setTimeout(function()
106
+ {
107
+ // HIDING THE PLEASE WAIT ANIMATION AND THE PERCENTAGE
108
+ document.getElementsByClassName("pleasewait")[0].style.display = "none";
109
+ document.getElementsByClassName("percentage")[0].style.display = "none";
110
+ },5000);
111
+ });
112
+ }
113
+ else
114
+ {
115
+ // IF THERE IS AN ERROR, THE REQUEST IS EXECUTED ONE MORE TIME
116
+ getISOImage();
117
+ }
118
+ }
119
+ };
120
+
121
+ // SETTING WHAT WILL HAPPEN WHEN THE REQUEST IS DOWNLOADING THE FILE
122
+ oReq.onprogress = function (oEvent)
123
+ {
124
+ // CHECKING IF THERE IS A FILE SIZE
125
+ if (oEvent.total>0)
126
+ {
127
+ // UPDATING THE PERCENTAGE LABEL
128
+ document.getElementsByClassName("percentage")[0].innerHTML = Math.floor(oEvent.loaded * 100 / oEvent.total) + "%";
129
+ }
130
+ };
131
+
132
+ // IF DURING THE REQUEST IS AN ERROR, THE REQUEST IS EXECUTED ONE MORE TIME
133
+ oReq.onerror = function(){setTimeout(function(){getISOImage();},1000);};
134
+
135
+ // IF DURING THE REQUEST IS A TIMEOUT, THE REQUEST IS EXECUTED ONE MORE TIME
136
+ oReq.ontimeout = function(e){setTimeout(function(){getISOImage();},1000);};
137
+
138
+ // EXECUTING THE REQUEST
139
+ oReq.send(null);
140
+ }
141
+
142
+ function blockSpecialKeys(e)
143
+ {
144
+ try
145
+ {
146
+ // GETTING THE KEY EVENT
147
+ e = e || window.event;
148
+
149
+ // CHECKING IF IT ANY SPECIAL KEY IS PRESSED
150
+ if (e.altKey || e.ctrlKey || e.metaKey || e.keyCode == 27)
151
+ {
152
+ // BLOCKING THE SPECIAL KEY
153
+ e.preventDefault();
154
+ e.stopPropagation();
155
+ e.stopImmediatePropagation();
156
+ }
157
+ }
158
+ catch(err)
159
+ {
160
+ }
161
+ }
162
+
163
+ // DISABLING THE CONTEXT MENU
164
+ window.oncontextmenu = function()
165
+ {
166
+ return false;
167
+ }
168
+
169
+ // SETTING WHAT WILL HAPPEN WHEN THE WEBSITE IS FULLY LOADED
170
+ window.addEventListener("load", function()
171
+ {
172
+ // SETTING WHAT WILL HAPPEN WHEN THE USER CLICKS ON THE CANVAS
173
+ document.getElementById("canvas").addEventListener("click",function(event)
174
+ {
175
+ try
176
+ {
177
+ // REQUESTING POINTER LOCK ON THE CANVAS
178
+ document.getElementById("canvas").requestPointerLock();
179
+ }
180
+ catch(err)
181
+ {
182
+ }
183
+ });
184
+
185
+ // BUGFIX FOR THE SPECIALS KEYS
186
+ document.addEventListener("keydown",function(e){blockSpecialKeys(e)});
187
+ document.addEventListener("keypress",function(e){blockSpecialKeys(e)});
188
+ document.addEventListener("keyup", function(e){blockSpecialKeys(e)});
189
+
190
+ // CHECKING IF IS NOT RUNNING WITHIN AN IFRAME
191
+ if (window.top == window.self)
192
+ {
193
+ // REQUESTING THE ISO IMAGE
194
+ getISOImage();
195
+ }
196
+ });
197
+
198
+ if ("serviceWorker" in navigator)
199
+ {
200
+ navigator.serviceWorker.register("worker.js").then(function(registration)
201
+ {
202
+ // Registration successful
203
+ //console.log("ServiceWorker registration successful with scope: " + registration.scope);
204
+ }).catch(function(err)
205
+ {
206
+ // Registration failed
207
+ //console.log("ServiceWorker registration failed: " + err);
208
+ });
209
+ }
210
+ </script>
211
+ </body>
212
+ </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
worker.js ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const filesToCache = [
2
+ "VirtualXP.htm",
3
+ "VirtualXP.iso",
4
+ "VirtualXP.js",
5
+ "VirtualXP.json",
6
+ "VirtualXP.png",
7
+ "VirtualXP.wasm",
8
+ "VirtualXPBIOS.bin",
9
+ "VirtualXPFavIcon_16x16.png",
10
+ "VirtualXPFavIcon_192x192.png",
11
+ "VirtualXPFavIcon_512x512.png",
12
+ "VirtualXPLoader.js",
13
+ "VirtualXPShare.png",
14
+ "VirtualXPVGA.bin"
15
+ ];
16
+
17
+ const staticCacheName = "virtualxp-v1";
18
+
19
+ self.addEventListener("install", event => {
20
+ event.waitUntil(
21
+ caches.open(staticCacheName)
22
+ .then(cache => {
23
+ return cache.addAll(filesToCache);
24
+ })
25
+ );
26
+ });
27
+
28
+ self.addEventListener("fetch", event => {
29
+ event.respondWith(
30
+ caches.match(event.request)
31
+ .then(response => {
32
+ if (response) {
33
+ return response;
34
+ }
35
+ return fetch(event.request)
36
+ }).catch(error => {
37
+ })
38
+ );
39
+ });