update CHIM to js-dos v8, update maze to latest
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "iew-site",
|
||||
"version": "0.14.0",
|
||||
"version": "0.14.1",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {},
|
||||
|
BIN
src/assets/_root/chim/chim.jsdos
Normal file
@ -1,348 +0,0 @@
|
||||
/*!
|
||||
* jQLite JavaScript Library v1.1.1 (http://code.google.com/p/jqlite/)
|
||||
* Copyright (c) 2010 Brett Fattori (bfattori@gmail.com)
|
||||
* Licensed under the MIT license
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* Many thanks to the jQuery team's efforts. Some code is
|
||||
* Copyright (c) 2010, John Resig. See
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* @author Brett Fattori (bfattori@gmail.com)
|
||||
* @author $Author: bfattori $
|
||||
* @version $Revision: 145 $
|
||||
*
|
||||
* Created: 03/29/2010
|
||||
* Modified: $Date: 2010-06-21 11:08:14 -0400 (Mon, 21 Jun 2010) $
|
||||
*/
|
||||
(function(){function B(){return+new Date}var D=function(a,b){if(a===""&&b)return b;var d=a.split(" "),c=d.shift(),e;if(c.charAt(0)=="#"){var g=i.getElementById(c.substring(1));e=g?[g]:[]}else{e=c.charAt(0)!=="."?c.split(".")[0]:"*";var h=c.split("."),j=null;if(e.indexOf("[")!=-1){j=e;e=e.substr(0,e.indexOf("["))}g=function(o){var n=arguments.callee,k;if(!(k=!n.needClass)){k=n.classes;if(o.className.length==0)k=false;else{for(var r=o.className.split(" "),l=k.length,p=0;p<k.length;p++)f.inArray(k[p],
|
||||
r)!=-1&&l--;k=l==0}}if(k=k){if(!(k=!n.needAttribute)){n=n.attributes;k=true;for(r=0;r<n.length;r++){l=n[r].split("=");p=l[0].indexOf("!")!=-1||l[0].indexOf("*")!=-1?l[0].charAt(l[0].length-1)+"=":"=";if(p!="=")l[0]=l[0].substring(0,l[0].length-1);switch(p){case "=":k&=o.getAttribute(l[0])===l[1];break;case "!=":k&=o.getAttribute(l[0])!==l[1];break;case "*=":k&=o.getAttribute(l[0]).indexOf(l[1])!=-1;break;default:k=false}}k=k}k=k}if(k)return o};for(var u=[],s=0;s<b.length;s++)for(var C=b[s].getElementsByTagName(e),
|
||||
v=0;v<C.length;v++)u.push(C[v]);h&&h.shift();e=[];g.classes=h;if(j!=null){var w=j.indexOf("[");s=j.lastIndexOf("]");w=j.substring(w+1,s).split("][")}g.attributes=j!=null?w:null;g.needClass=c.indexOf(".")!=-1&&h.length>0;g.needAttribute=j!=null;for(c=0;c<u.length;c++)g(u[c])&&e.push(u[c])}return D(d.join(" "),e)},Q=function(a,b){b=b||i;if(a.nodeType&&a.nodeType===E){a=i.body;if(a===null)return[i]}if(a.nodeType&&a.nodeType===m)return[a];if(a.jquery&&typeof a.jquery==="string")return a.toArray();if(b)b=
|
||||
F(b);if(f.isArray(a))return a;else if(typeof a==="string"){for(var d=[],c=0;c<b.length;c++){var e=[b[c]];if(!f.forceSimpleSelectorEngine&&e[0].querySelectorAll){e=e[0].querySelectorAll(a);for(var g=0;g<e.length;g++)d.push(e.item(g))}else d=d.concat(D(a,e))}return d}else return null},G=false;setTimeout(function(){var a=i.body;if(a){var b=i.createElement("script"),d="i"+(new Date).getTime();b.type="text/javascript";try{b.appendChild(i.createTextNode("window."+d+"=1;"))}catch(c){}a.insertBefore(b,a.firstChild);
|
||||
var e=true;if(window[d])delete window[d];else e=false;a.removeChild(b);G=e}else setTimeout(arguments.callee,33)},33);var H=function(a){var b=i.createElement("div");b.innerHTML=a;return{scripts:b.getElementsByTagName("script"),data:a}},I=function(a){a=a.replace(/-/g," ");a=a;var b=true;b=b||false;a=!a?"":a.toString().replace(/^\s*|\s*$/g,"");var d="";if(a.length<=0)a="";else{var c=false;d+=b?a.charAt(0):a.charAt(0).toUpperCase();for(b=1;b<a.length;b++){d+=c?a.charAt(b).toUpperCase():a.charAt(b).toLowerCase();
|
||||
var e=a.charCodeAt(b);c=e==32||e==45||e==46;if(e==99||e==67)if(a.charCodeAt(b-1)==77||a.charCodeAt(b-1)==109)c=true}a=d}return a.replace(/ /g,"")},J={click:"MouseEvents",dblclick:"MouseEvents",mousedown:"MouseEvents",mouseup:"MouseEvents",mouseover:"MouseEvents",mousemove:"MouseEvents",mouseout:"MouseEvents",contextmenu:"MouseEvents",keypress:"KeyEvents",keydown:"KeyEvents",keyup:"KeyEvents",load:"HTMLEvents",unload:"HTMLEvents",abort:"HTMLEvents",error:"HTMLEvents",resize:"HTMLEvents",scroll:"HTMLEvents",
|
||||
select:"HTMLEvents",change:"HTMLEvents",submit:"HTMLEvents",reset:"HTMLEvents",focus:"HTMLEvents",blur:"HTMLEvents",touchstart:"MouseEvents",touchend:"MouseEvents",touchmove:"MouseEvents"},K=function(a,b,d){if(f.isFunction(d)){if(typeof b==="string")b=b.toLowerCase();var c=J[b];if(b.indexOf("on")==0)b=b.substring(2);if(c){c=function(e){var g=arguments.callee,h=e.data||[];h.unshift(e);g=g.fn.apply(a,h);if(typeof g!="undefined"&&g===false){if(e.preventDefault&&e.stopPropagation){e.preventDefault();
|
||||
e.stopPropagation()}else{e.returnValue=false;e.cancelBubble=true}return false}return true};c.fn=d;a.addEventListener?a.addEventListener(b,c,false):a.attachEvent("on"+b,c)}else{if(!a._handlers)a._handlers={};c=a._handlers[b]||[];c.push(d);a._handlers[b]=c}}},f=function(a,b){return(new x).init(a,b)},i=window.document,y=Object.prototype.hasOwnProperty,z=Object.prototype.toString,L=Array.prototype.push,R=Array.prototype.slice,m=1,E=9,A=[],M=false,N=false,q;f.forceSimpleSelectorEngine=false;f.each=function(a,
|
||||
b){var d,c=0,e=a.length;if(e===undefined||f.isFunction(a))for(d in a){if(b.call(a[d],d,a[d])===false)break}else for(d=a[0];c<e&&b.call(d,c,d)!==false;d=a[++c]);return a};f.noop=function(){};f.isFunction=function(a){return z.call(a)==="[object Function]"};f.isArray=function(a){return z.call(a)==="[object Array]"};f.isPlainObject=function(a){if(!a||z.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!y.call(a,"constructor")&&!y.call(a.constructor.prototype,"isPrototypeOf"))return false;
|
||||
var b;for(b in a);return b===undefined||y.call(a,b)};f.merge=function(a,b){var d=a.length,c=0;if(typeof b.length==="number")for(var e=b.length;c<e;c++)a[d++]=b[c];else for(;b[c]!==undefined;)a[d++]=b[c++];a.length=d;return a};f.param=function(a){var b="";a&&f.each(a,function(d,c){b+=(b.length!=0?"&":"")+c+"="+encodeURIComponent(d)});return b};f.evalScripts=function(a){for(var b=i.getElementsByTagName("head")[0]||i.documentElement,d=0;d<a.length;d++){var c=i.createElement("script");c.type="text/javascript";
|
||||
if(G)c.appendChild(i.createTextNode(a[d].text));else c.text=a[d].text;b.insertBefore(c,b.firstChild);b.removeChild(c)}};f.ready=function(){for(M=true;A.length>0;)A.shift()()};var t="jQuery"+B(),S=0,O={};f.noData={embed:true,object:true,applet:true};f.cache={};f.data=function(a,b,d){if(!(a.nodeName&&jQuery.noData[a.nodeName.toLowerCase()])){a=a==window?O:a;var c=a[t];c||(c=a[t]=++S);if(b&&!jQuery.cache[c])jQuery.cache[c]={};if(d!==undefined)jQuery.cache[c][b]=d;return b?jQuery.cache[c][b]:c}};f.removeData=
|
||||
function(a,b){a=a==window?O:a;var d=a[t];if(b){if(jQuery.cache[d]){delete jQuery.cache[d][b];b="";for(b in jQuery.cache[d])break;b||jQuery.removeData(a)}}else{try{delete a[t]}catch(c){a.removeAttribute&&a.removeAttribute(t)}delete jQuery.cache[d]}};f.ajax={status:-1,statusText:"",responseText:null,responseXML:null,send:function(a,b,d){if(f.isFunction(b)){d=b;b={}}if(a){var c=true,e=null,g=null;if(typeof b.async!=="undefined"){c=b.async;delete b.async}if(typeof b.username!=="undefined"){e=b.username;
|
||||
delete b.username}if(typeof b.password!=="undefined"){g=b.password;delete b.password}b=f.param(b);if(b.length!=0)a+=(a.indexOf("?")==-1?"?":"&")+b;b=new XMLHttpRequest;b.open("GET",a,c,e,g);b.send();if(c){a=function(h){var j=arguments.callee;h.status==200?f.ajax.complete(h,j.cb):f.ajax.error(h,j.cb)};a.cb=d;d=function(){var h=arguments.callee;h.req.readyState!=4?setTimeout(h,250):h.xcb(h.req)};d.req=b;d.xcb=a;setTimeout(d,250)}}},complete:function(a,b){f.ajax.status=a.status;f.ajax.responseText=a.responseText;
|
||||
f.ajax.responseXML=a.responseXML;f.isFunction(b)&&b(a.responseText,a.status)},error:function(a,b){f.ajax.status=a.status;f.ajax.statusText=a.statusText;f.isFunction(b)&&b(a.status,a.statusText)}};f.makeArray=function(a,b){var d=b||[];if(a!=null)a.length==null||typeof a==="string"||jQuery.isFunction(a)||typeof a!=="function"&&a.setInterval?L.call(d,a):f.merge(d,a);return d};f.inArray=function(a,b){for(var d=0;d<b.length;d++)if(b[d]===a)return d;return-1};f.trim=function(a){return a!=null?a.toString().replace(/^\s*|\s*$/g,
|
||||
""):""};var x=function(){};x.prototype={selector:"",context:null,length:0,jquery:"jqlite-1.1.1",init:function(a,b){if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1}else if(typeof a==="function")this.ready(a);else{var d=[];if(a.jquery&&typeof a.jquery==="string")d=a.toArray();else if(f.isArray(a))d=a;else if(typeof a==="string"&&f.trim(a).indexOf("<")==0&&f.trim(a).indexOf(">")!=-1){d=f.trim(a).toLowerCase();d=d.indexOf("<option")==0?"SELECT":d.indexOf("<li")==0?"UL":d.indexOf("<tr")==
|
||||
0?"TBODY":d.indexOf("<td")==0?"TR":"DIV";d=i.createElement(d);d.innerHTML=a;d=[d.removeChild(d.firstChild)]}else{if(a.indexOf(",")!=-1){d=a.split(",");for(var c=0;c<d.length;c++)d[c]=f.trim(d[c])}else d=[a];c=[];for(var e=0;e<d.length;e++)c=c.concat(Q(d[e],b));d=c}L.apply(this,d)}return this},each:function(a){return f.each(this,a)},size:function(){return this.length},toArray:function(){return R.call(this,0)},ready:function(a){if(M)a();else{A.push(a);return this}},data:function(a,b){if(typeof a===
|
||||
"undefined"&&this.length)return jQuery.data(this[0]);else if(typeof a==="object")return this.each(function(){jQuery.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===undefined){if(data===undefined&&this.length)data=jQuery.data(this[0],a);return data===undefined&&d[1]?this.data(d[0]):data}else return this.each(function(){jQuery.data(this,a,b)})},removeData:function(a){return this.each(function(){jQuery.removeData(this,a)})},addClass:function(a){return this.each(function(){if(this.className.length!=
|
||||
0){var b=this.className.split(" ");if(f.inArray(a,b)==-1){b.push(a);this.className=b.join(" ")}}else this.className=a})},removeClass:function(a){return this.each(function(){if(this.className.length!=0){var b=this.className.split(" "),d=f.inArray(a,b);if(d!=-1){b.splice(d,1);this.className=b.join(" ")}}})},hasClass:function(a){if(this[0].className.length==0)return false;return f.inArray(a,this[0].className.split(" "))!=-1},isElementName:function(a){return this[0].nodeName.toLowerCase()===a.toLowerCase()},
|
||||
toggleClass:function(a){return this.each(function(){if(this.className.length==0)this.className=a;else{var b=this.className.split(" "),d=f.inArray(a,b);d!=-1?b.splice(d,1):b.push(a);this.className=b.join(" ")}})},hide:function(a){return this.each(function(){if(this.style&&this.style.display!=null)if(this.style.display.toString()!="none"){this._oldDisplay=this.style.display.toString()||(this.nodeName!="span"?"block":"inline");this.style.display="none"}f.isFunction(a)&&a(this)})},show:function(a){return this.each(function(){this.style.display=
|
||||
(this._oldDisplay&&this._oldDisplay!=""?this._oldDisplay:null)||(this.nodeName!="span"?"block":"inline");f.isFunction(a)&&a(this)})},css:function(a,b){if(typeof a==="string"&&b==null)return this[0].style[I(a)];else{a=typeof a==="string"?P(a,b):a;return this.each(function(){var d=this;typeof d.style!="undefined"&&f.each(a,function(c,e){e=typeof e==="number"?e+"px":e;var g=I(c);d.style[g]||(g=c);d.style[g]=e})})}},load:function(a,b,d){if(f.isFunction(b)){d=b;b={}}return this.each(function(){var c=function(e,
|
||||
g){var h=arguments.callee;if(e){var j=H(e);h.elem.innerHTML=j.data;f.evalScripts(j.scripts)}f.isFunction(h.cback)&&h.cback(e,g)};c.cback=d;c.elem=this;f.ajax.send(a,b,c)})},html:function(a){return a?this.each(function(){var b=H(a);this.innerHTML=b.data;f.evalScripts(b.scripts)}):this[0].innerHTML},attr:function(a,b){return typeof a==="string"&&b==null?this[0]?this[0].getAttribute(a):"":this.each(function(){a=typeof a==="string"?P(a,b):a;for(var d in a)this.setAttribute(d,a[d])})},eq:function(a){var b=
|
||||
this.toArray();this.context=this[0]=a<0?b[b.length+a]:b[a];this.length=1;return this},first:function(){this.context=this[0]=this.toArray()[0];this.length=1;return this},last:function(){var a=this.toArray();this.context=this[0]=a[a.length-1];this.length=1;return this},index:function(a){var b=-1;if(this.length!=0){var d=this[0];if(a){var c=f(a)[0];this.each(function(g){if(this===c){b=g;return false}})}else{a=this.parent()[0].firstChild;for(var e=[];a!=null;){a.nodeType===m&&e.push(a);a=a.nextSibling}f.each(a,
|
||||
function(g){if(this===d){b=g;return false}})}}return b},next:function(a){var b=[];if(a){var d=f(a);this.each(function(){for(var c=this.nextSibling;c!=null&&c.nodeType!==m;)c=c.nextSibling;if(c!=null){var e=false;d.each(function(){if(this==c){e=true;return false}});e&&b.push(c)}})}else this.each(function(){for(var c=this.nextSibling;c!=null&&c.nodeType!==m;)c=c.nextSibling;c!=null&&b.push(c)});return f(b)},prev:function(a){var b=[];if(a){var d=f(a);this.each(function(){for(var c=this.previousSibling;c!=
|
||||
null&&c.nodeType!==m;)c=c.previousSibling;if(c!=null){var e=false;d.each(function(){if(this==c){e=true;return false}});e&&b.push(c)}})}else this.each(function(){for(var c=this.previousSibling;c!=null&&c.nodeType!==m;)c=c.previousSibling;c!=null&&b.push(c)});return f(b)},parent:function(a){var b=[];if(a){var d=f(a);this.each(function(){var c=this.parentNode,e=false;d.each(function(){if(this==c){e=true;return false}});e&&b.push(c)})}else this.each(function(){b.push(this.parentNode)});return f(b)},parents:function(a){var b=
|
||||
[];if(a){var d=f(a);this.each(function(){for(var c=this;c!=i.body;){d.each(function(){this==c&&b.push(c)});c=c.parentNode}})}else this.each(function(){for(var c=this;c!=i.body;){c=c.parentNode;b.push(c)}});return f(b)},children:function(a){var b=[];if(a){var d=f(a);this.each(function(){for(var c=this.firstChild;c!=null;){c.nodeType==m&&d.each(function(){this===c&&b.push(c)});c=c.nextSibling}})}else this.each(function(){for(var c=this.firstChild;c!=null;){c.nodeType==m&&b.push(c);c=c.nextSibling}});
|
||||
return f(b)},append:function(a){a=F(a);return this.each(function(){for(var b=0;b<a.length;b++)this.appendChild(a[b])})},remove:function(a){return this.each(function(){a?$(a,this).remove():this.parentNode.removeChild(this)})},empty:function(){return this.each(function(){this.innerHTML=""})},val:function(a){if(a==null){var b=null;if(this&&this.length!=0&&typeof this[0].value!="undefined")b=this[0].value;return b}else return this.each(function(){if(typeof this.value!="undefined")this.value=a})},bind:function(a,
|
||||
b){return this.each(function(){K(this,a,b)})},trigger:function(a,b){return this.each(function(){var d;var c;c=a;if(typeof c==="string")c=c.toLowerCase();var e=null,g=J[c]||"Event";if(i.createEvent){e=i.createEvent(g);e._eventClass=g;c&&e.initEvent(c,true,true)}if(i.createEventObject){e=i.createEventObject();if(c){e.type=c;e._eventClass=g}}c=e;if(c._eventClass!=="Event"){c.data=b;d=this.dispatchEvent(c)}else if(e=(this._handlers||{})[a])for(g=0;g<e.length;g++){var h=f.isArray(b)?b:[];h.unshift(c);
|
||||
h=e[g].apply(this,h);if(!(typeof h=="undefined"?true:h))break}return d})},submit:function(a){return this.each(function(){if(f.isFunction(a))K(this,"onsubmit",a);else this.submit&&this.submit()})}};if(i.addEventListener)q=function(){i.removeEventListener("DOMContentLoaded",q,false);f.ready()};else if(i.attachEvent)q=function(){if(i.readyState==="complete"){i.detachEvent("onreadystatechange",q);f.ready()}};if(!N){N=true;if(i.readyState==="complete")return f.ready();if(i.addEventListener){i.addEventListener("DOMContentLoaded",
|
||||
q,false);window.addEventListener("load",f.ready,false)}else if(i.attachEvent){i.attachEvent("onreadystatechange",q);window.attachEvent("onload",f.ready)}}var P=function(a,b){var d={};d[a]=b;return d},F=function(a){if(a.nodeType&&(a.nodeType===m||a.nodeType===E))a=[a];else if(typeof a==="string")a=f(a).toArray();else if(a.jquery&&typeof a.jquery==="string")a=a.toArray();return a};if(typeof window.jQuery=="undefined"){window.jQuery=f;window.jQuery.fn=x.prototype;window.$=window.jQuery;window.now=B}jQuery.extend=
|
||||
jQuery.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,c=false,e,g,h,j;if(typeof a==="boolean"){c=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!jQuery.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(g in e){h=a[g];j=e[g];if(a!==j)if(c&&j&&(jQuery.isPlainObject(j)||jQuery.isArray(j))){h=h&&(jQuery.isPlainObject(h)||jQuery.isArray(h))?h:jQuery.isArray(j)?[]:{};a[g]=jQuery.extend(c,h,j)}else if(j!==undefined)a[g]=j}return a};jQuery.each("click,dblclick,mouseover,mouseout,mousedown,mouseup,keydown,keypress,keyup,focus,blur,change,select,error,load,unload,scroll,resize,touchstart,touchend,touchmove".split(","),
|
||||
function(a,b){jQuery.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)}})})();
|
||||
(function() {
|
||||
this.Dosbox = (function() {
|
||||
function Dosbox(options) {
|
||||
this.onload = options.onload;
|
||||
this.onrun = options.onrun;
|
||||
this.ui = new Dosbox.UI(options);
|
||||
this.module = new Dosbox.Module({
|
||||
canvas: this.ui.canvas
|
||||
});
|
||||
this.ui.onStart((function(_this) {
|
||||
return function() {
|
||||
_this.ui.showLoader();
|
||||
return _this.downloadScript();
|
||||
};
|
||||
})(this));
|
||||
}
|
||||
|
||||
Dosbox.prototype.run = function(archiveUrl, executable) {
|
||||
return new Dosbox.Mount(this.module, archiveUrl, {
|
||||
success: (function(_this) {
|
||||
return function() {
|
||||
var func, hide;
|
||||
_this.ui.updateMessage("Launching " + executable);
|
||||
hide = function() {
|
||||
return _this.ui.hideLoader();
|
||||
};
|
||||
func = function() {
|
||||
return _this._dosbox_main(_this, executable);
|
||||
};
|
||||
setTimeout(func, 1000);
|
||||
return setTimeout(hide, 3000);
|
||||
};
|
||||
})(this),
|
||||
progress: (function(_this) {
|
||||
return function(total, current) {
|
||||
return _this.ui.updateMessage("Mount " + executable + " (" + (current * 100 / total | 0) + "%)");
|
||||
};
|
||||
})(this)
|
||||
});
|
||||
};
|
||||
|
||||
Dosbox.prototype.requestFullScreen = function() {
|
||||
if (this.module.requestFullScreen) {
|
||||
return this.module.requestFullScreen(true, false);
|
||||
}
|
||||
};
|
||||
|
||||
Dosbox.prototype.downloadScript = function() {
|
||||
this.module.setStatus('Downloading js-dos');
|
||||
this.ui.updateMessage('Downloading js-dos');
|
||||
return new Dosbox.Xhr('https://js-dos.com/cdn/js-dos-v3.js', {
|
||||
success: (function(_this) {
|
||||
return function(script) {
|
||||
var func;
|
||||
_this.ui.updateMessage('Initializing dosbox');
|
||||
func = function() {
|
||||
return _this._jsdos_init(_this.module, script, _this.onload);
|
||||
};
|
||||
return setTimeout(func, 1000);
|
||||
};
|
||||
})(this),
|
||||
progress: (function(_this) {
|
||||
return function(total, current) {
|
||||
return _this.ui.updateMessage("Downloading js-dos (" + (current * 100 / total | 0) + "%)");
|
||||
};
|
||||
})(this)
|
||||
});
|
||||
};
|
||||
|
||||
Dosbox.prototype._jsdos_init = function(module, script, onload) {
|
||||
var Module;
|
||||
Module = module;
|
||||
eval(script);
|
||||
if (onload) {
|
||||
return onload(this);
|
||||
}
|
||||
};
|
||||
|
||||
Dosbox.prototype._dosbox_main = function(dosbox, executable) {
|
||||
var exception, func;
|
||||
try {
|
||||
if (dosbox.onrun) {
|
||||
func = function() {
|
||||
return dosbox.onrun(dosbox, executable);
|
||||
};
|
||||
setTimeout(func, 1000);
|
||||
}
|
||||
return dosbox.module.ccall('dosbox_main', 'int', ['string'], [executable]);
|
||||
} catch (error) {
|
||||
exception = error;
|
||||
if (exception === 'SimulateInfiniteLoop') {
|
||||
|
||||
} else {
|
||||
return typeof console !== "undefined" && console !== null ? typeof console.error === "function" ? console.error(exception) : void 0 : void 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return Dosbox;
|
||||
|
||||
})();
|
||||
|
||||
}).call(this);
|
||||
|
||||
(function() {
|
||||
Dosbox.Module = (function() {
|
||||
function Module(options) {
|
||||
this.elCanvas = options.canvas;
|
||||
this.canvas = this.elCanvas[0];
|
||||
}
|
||||
|
||||
Module.prototype.preRun = [];
|
||||
|
||||
Module.prototype.postRun = [];
|
||||
|
||||
Module.prototype.totalDependencies = 0;
|
||||
|
||||
Module.prototype.print = function(text) {
|
||||
text = Array.prototype.slice.call(arguments).join(' ');
|
||||
return typeof console !== "undefined" && console !== null ? typeof console.log === "function" ? console.log(text) : void 0 : void 0;
|
||||
};
|
||||
|
||||
Module.prototype.printErr = function(text) {
|
||||
text = Array.prototype.slice.call(arguments).join(' ');
|
||||
return typeof console !== "undefined" && console !== null ? typeof console.error === "function" ? console.error(text) : void 0 : void 0;
|
||||
};
|
||||
|
||||
Module.prototype.setStatus = function(text) {
|
||||
return typeof console !== "undefined" && console !== null ? typeof console.log === "function" ? console.log(text) : void 0 : void 0;
|
||||
};
|
||||
|
||||
Module.prototype.monitorRunDependencies = function(left) {
|
||||
var status;
|
||||
this.totalDependencies = Math.max(this.totalDependencies, left);
|
||||
status = left ? "Preparing... (" + (this.totalDependencies - left) + "/" + this.totalDependencies + ")" : 'All downloads complete.';
|
||||
return this.setStatus(status);
|
||||
};
|
||||
|
||||
return Module;
|
||||
|
||||
})();
|
||||
|
||||
}).call(this);
|
||||
|
||||
(function() {
|
||||
Dosbox.Mount = (function() {
|
||||
function Mount(module, url, options) {
|
||||
this.module = module;
|
||||
new Dosbox.Xhr(url, {
|
||||
success: (function(_this) {
|
||||
return function(data) {
|
||||
var bytes;
|
||||
bytes = _this._toArray(data);
|
||||
if (_this._mountZip(bytes)) {
|
||||
return options.success();
|
||||
} else {
|
||||
return typeof console !== "undefined" && console !== null ? typeof console.error === "function" ? console.error('Unable to mount', url) : void 0 : void 0;
|
||||
}
|
||||
};
|
||||
})(this),
|
||||
progress: options.progress
|
||||
});
|
||||
}
|
||||
|
||||
Mount.prototype._mountZip = function(bytes) {
|
||||
var buffer, extracted;
|
||||
buffer = this.module._malloc(bytes.length);
|
||||
this.module.HEAPU8.set(bytes, buffer);
|
||||
extracted = this.module.ccall('extract_zip', 'int', ['number', 'number'], [buffer, bytes.length]);
|
||||
this.module._free(buffer);
|
||||
return extracted === 0;
|
||||
};
|
||||
|
||||
Mount.prototype._toArray = function(data) {
|
||||
var arr, i, len;
|
||||
if (typeof data === 'string') {
|
||||
arr = new Array(data.length);
|
||||
i = 0;
|
||||
len = data.length;
|
||||
while (i < len) {
|
||||
arr[i] = data.charCodeAt(i);
|
||||
++i;
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
return Mount;
|
||||
|
||||
})();
|
||||
|
||||
}).call(this);
|
||||
|
||||
(function() {
|
||||
Dosbox.UI = (function() {
|
||||
function UI(options) {
|
||||
this.appendCss();
|
||||
this.div = $('#' + (options.id || 'dosbox'));
|
||||
this.wrapper = $('<div class="dosbox-container">');
|
||||
this.canvas = $('<canvas class="dosbox-canvas" oncontextmenu="event.preventDefault()">');
|
||||
this.overlay = $('<div class="dosbox-overlay">');
|
||||
this.loaderMessage = $('<div class="dosbox-loader-message">');
|
||||
this.loader = $('<div class="dosbox-loader">').append($('<div class="st-loader">').append($('<span class="equal">'))).append(this.loaderMessage);
|
||||
this.start = $('<div class="dosbox-start">Click to start');
|
||||
this.div.append(this.wrapper);
|
||||
this.wrapper.append(this.canvas);
|
||||
this.wrapper.append(this.loader);
|
||||
this.wrapper.append(this.overlay);
|
||||
this.overlay.append($('<div class="dosbox-powered">Powered by ').append($('<a href="http://js-dos.com">js-dos.com')));
|
||||
this.overlay.append(this.start);
|
||||
}
|
||||
|
||||
UI.prototype.onStart = function(fun) {
|
||||
return this.start.click((function(_this) {
|
||||
return function() {
|
||||
fun();
|
||||
return _this.overlay.hide();
|
||||
};
|
||||
})(this));
|
||||
};
|
||||
|
||||
UI.prototype.appendCss = function() {
|
||||
var head, style;
|
||||
head = document.head || document.getElementsByTagName('head')[0];
|
||||
style = document.createElement('style');
|
||||
style.type = 'text/css';
|
||||
if (style.styleSheet) {
|
||||
style.styleSheet.cssText = this.css;
|
||||
} else {
|
||||
style.appendChild(document.createTextNode(this.css));
|
||||
}
|
||||
return head.appendChild(style);
|
||||
};
|
||||
|
||||
UI.prototype.showLoader = function() {
|
||||
this.loader.show();
|
||||
return this.loaderMessage.html('');
|
||||
};
|
||||
|
||||
UI.prototype.updateMessage = function(message) {
|
||||
return this.loaderMessage.html(message);
|
||||
};
|
||||
|
||||
UI.prototype.hideLoader = function() {
|
||||
return this.loader.hide();
|
||||
};
|
||||
|
||||
UI.prototype.css = '.dosbox-container { position: relative; min-width: 320px; min-height: 200px; } .dosbox-canvas { } .dosbox-overlay, .dosbox-loader { position: absolute; left: 0; right: 0; top: 0; bottom: 0; background-color: #333; } .dosbox-start { text-align: center; position: absolute; left: 0; right: 0; bottom: 50%; color: #f80; font-size: 1.5em; text-decoration: underline; cursor: pointer; } .dosbox-overlay a { color: #f80; } .dosbox-loader { display: none; } .dosbox-powered { position: absolute; right: 1em; bottom: 1em; font-size: 0.8em; color: #9C9C9C; } .dosbox-loader-message { text-align: center; position: absolute; left: 0; right: 0; bottom: 50%; margin: 0 0 -3em 0; box-sizing: border-box; color: #f80; font-size: 1.5em; } @-moz-keyframes loading { 0% { left: 0; } 50% { left: 8.33333em; } 100% { left: 0; } } @-webkit-keyframes loading { 0% { left: 0; } 50% { left: 8.33333em; } 100% { left: 0; } } @keyframes loading { 0% { left: 0; } 50% { left: 8.33333em; } 100% { left: 0; } } .st-loader { width: 10em; height: 2.5em; position: absolute; top: 50%; left: 50%; margin: -1.25em 0 0 -5em; box-sizing: border-box; } .st-loader:before, .st-loader:after { content: ""; display: block; position: absolute; top: 0; bottom: 0; width: 1.25em; box-sizing: border-box; border: 0.25em solid #f80; } .st-loader:before { left: -0.76923em; border-right: 0; } .st-loader:after { right: -0.76923em; border-left: 0; } .st-loader .equal { display: block; position: absolute; top: 50%; margin-top: -0.5em; left: 4.16667em; height: 1em; width: 1.66667em; border: 0.25em solid #f80; box-sizing: border-box; border-width: 0.25em 0; -moz-animation: loading 1.5s infinite ease-in-out; -webkit-animation: loading 1.5s infinite ease-in-out; animation: loading 1.5s infinite ease-in-out; }';
|
||||
|
||||
return UI;
|
||||
|
||||
})();
|
||||
|
||||
}).call(this);
|
||||
|
||||
(function() {
|
||||
Dosbox.Xhr = (function() {
|
||||
function Xhr(url, options) {
|
||||
var e;
|
||||
this.success = options.success;
|
||||
this.progress = options.progress;
|
||||
if (window.ActiveXObject) {
|
||||
try {
|
||||
this.xhr = new ActiveXObject('Microsoft.XMLHTTP');
|
||||
} catch (error) {
|
||||
e = error;
|
||||
this.xhr = null;
|
||||
}
|
||||
} else {
|
||||
this.xhr = new XMLHttpRequest();
|
||||
}
|
||||
this.xhr.open('GET', url, true);
|
||||
this.xhr.overrideMimeType('text/plain; charset=x-user-defined');
|
||||
this.xhr.addEventListener('progress', (function(_this) {
|
||||
return function(evt) {
|
||||
if (_this.progress) {
|
||||
return _this.progress(evt.total, evt.loaded);
|
||||
}
|
||||
};
|
||||
})(this));
|
||||
this.xhr.onreadystatechange = (function(_this) {
|
||||
return function() {
|
||||
return _this._onReadyStateChange();
|
||||
};
|
||||
})(this);
|
||||
this.xhr.send();
|
||||
}
|
||||
|
||||
Xhr.prototype._onReadyStateChange = function() {
|
||||
if (this.xhr.readyState === 4 && this.success) {
|
||||
return this.success(this.xhr.responseText);
|
||||
}
|
||||
};
|
||||
|
||||
return Xhr;
|
||||
|
||||
})();
|
||||
|
||||
}).call(this);
|
4
src/assets/_root/webtoys/maze/assets/index-Bw4OooWg.js
Normal file
@ -1 +0,0 @@
|
||||
:root{font-family:system-ui,Avenir,Helvetica,Arial,sans-serif;line-height:1.5;font-weight:400;color-scheme:light dark;color:#ffffffde;background-color:#242424;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}a{font-weight:500;color:#646cff;text-decoration:inherit}a:hover{color:#535bf2}body{margin:0;display:flex;place-items:center;min-width:320px;min-height:100vh;font-size:16px}h1{font-size:3.2em;line-height:1.1}h4,h5{margin:1rem 0}pre{font-size:1em;font-family:monospace;font-weight:400;font-style:normal}#app{align-items:center;display:flex;flex-direction:column;flex-wrap:wrap;justify-content:center;margin:0 auto;max-width:800px;position:relative;text-align:center;width:100%}#app-controls-window{display:grid;grid-template-columns:1fr 1fr 1fr 1fr;grid-gap:.5rem;margin-top:.5rem}#app-controls-window>button{grid-column:span 2}#app-controls-window>button:first-child,#app-controls-window>button:last-child{grid-column:2 / span 2}#app-interface-window{display:flex;flex-basis:40%;flex-direction:column;font-size:16px;order:3}#app-inventory-controls{display:flex;flex-direction:row;gap:.5rem;width:100%}#app-inventory-controls select{font-size:16px;width:15rem}#app-maze-window{flex-basis:60%;order:1}#app-modal{background-color:#1b1e1fde;border-radius:4px;left:50%;position:fixed;top:50%;transform:translate(-50%,-50%);visibility:hidden;width:20rem}#app-modal.show{transition:visibility .5s cubic-bezier(.075,.82,.165,1);visibility:visible}#app-modal-button{margin:3rem auto 1rem}#app-text-output{flex-basis:100%;order:2;padding:.5rem;width:95%}#mazeOutput{margin:0}.logo{height:6em;padding:1.5em;will-change:filter;transition:filter .3s}.logo:hover{filter:drop-shadow(0 0 2em #646cffaa)}.logo.vanilla:hover{filter:drop-shadow(0 0 2em #3178c6aa)}.card{padding:2em}.read-the-docs{color:#888}button{background-color:#363c3e;border-radius:8px;border:1px solid transparent;cursor:pointer;font-family:inherit;font-size:1em;font-weight:500;padding:.6em 1.2em;touch-action:manipulation;transition:border-color .25s}button:hover{border-color:#646cff}button:focus,button:focus-visible{outline:4px auto -webkit-focus-ring-color}@media (min-width: 30em) and (orientation: landscape){#app{align-items:start;flex-direction:row;justify-content:space-around}#app-interface-window{order:2}#app-text-output{order:3}}
|
1
src/assets/_root/webtoys/maze/assets/index-f4dP9NA-.css
Normal file
BIN
src/assets/_root/webtoys/maze/fonts/SourceCodePro-Black.otf.woff
Normal file
BIN
src/assets/_root/webtoys/maze/fonts/SourceCodePro-Bold.otf.woff
Normal file
BIN
src/assets/_root/webtoys/maze/fonts/SourceCodePro-Bold.ttf.woff2
Normal file
BIN
src/assets/_root/webtoys/maze/fonts/SourceCodePro-It.otf.woff
Normal file
BIN
src/assets/_root/webtoys/maze/fonts/SourceCodePro-It.ttf.woff2
Normal file
BIN
src/assets/_root/webtoys/maze/fonts/SourceCodePro-Light.otf.woff
Normal file
@ -2,15 +2,11 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="./favicon.ico" />
|
||||
<link rel="icon" href="/webtoys/maze/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Maze of the Minotaur</title>
|
||||
<script
|
||||
type="module"
|
||||
crossorigin
|
||||
src="./assets/index-BR90kO-n.js"
|
||||
></script>
|
||||
<link rel="stylesheet" crossorigin href="./assets/index-BwPfcn-3.css" />
|
||||
<script type="module" crossorigin src="/webtoys/maze/assets/index-Bw4OooWg.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/webtoys/maze/assets/index-f4dP9NA-.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app">
|
||||
|
71
src/assets/scripts/backgroundScroller.js
Normal file
@ -0,0 +1,71 @@
|
||||
// @license magnet:?xt=urn:btih:90dc5c0be029de84e523b9b3922520e79e0e6f08&dn=cc0.txt CC0-1.0
|
||||
/****************************************************************************
|
||||
* It's Eric Woodward's Site
|
||||
*
|
||||
* Copyright 2014-2025 Eric Woodward
|
||||
* Source released under CC0 Public Domain License v1.0
|
||||
* https://www.itsericwoodward.com/licenses/cc0/
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* Execute returned function to add background scrolling
|
||||
*/
|
||||
export default (actionBox) => {
|
||||
if (!window.Cookies || !actionBox) return;
|
||||
|
||||
// default to no scrolling on devices under 600 px w
|
||||
const isMobile = window.matchMedia(
|
||||
"only screen and (max-width: 600px)"
|
||||
).matches;
|
||||
|
||||
// add background scrolling
|
||||
const hasScrollToggle =
|
||||
Cookies.get("scrollToggle") === true ||
|
||||
Cookies.get("scrollToggle") === "true" ||
|
||||
(Cookies.get("scrollToggle") === undefined && !isMobile);
|
||||
|
||||
const scrollToggle = document.createElement("div");
|
||||
scrollToggle.innerHTML = [
|
||||
'<label class="toggleSwitch" for="scrollingToggle">',
|
||||
'<div class="toggleSwitch-description">',
|
||||
"Background",
|
||||
"</div>",
|
||||
`<input class="toggleSwitch-checkbox" ${
|
||||
hasScrollToggle ? "checked" : ""
|
||||
} type="checkbox" id="scrollingToggle" />`,
|
||||
'<div class="toggleSwitch-status" data-ts-on="SCROLLING" data-ts-off="STATIC"></div>',
|
||||
"</label>",
|
||||
].join("\n");
|
||||
scrollToggle.classList.add("js-scrollToggle", "scrollToggle");
|
||||
|
||||
actionBox.append(scrollToggle);
|
||||
actionBox.classList.add("js-actionBox");
|
||||
|
||||
const actionBoxTitle = document.createElement("summary");
|
||||
actionBoxTitle.innerHTML =
|
||||
"<h3 class='actionBox-title'>Settings</h3>";
|
||||
actionBox.append(actionBoxTitle);
|
||||
|
||||
// add toggle event
|
||||
document
|
||||
.getElementById("scrollingToggle")
|
||||
.addEventListener("click", function (e) {
|
||||
const theList =
|
||||
document.getElementById("gridContainer").classList;
|
||||
|
||||
theList.toggle("js-isAnimated");
|
||||
Cookies.set(
|
||||
"scrollToggle",
|
||||
!!theList.contains("js-isAnimated")
|
||||
);
|
||||
});
|
||||
|
||||
// add class if active at startup
|
||||
if (hasScrollToggle)
|
||||
document
|
||||
.getElementById("gridContainer")
|
||||
.classList.add("js-isAnimated");
|
||||
|
||||
};
|
||||
// @license-end
|
2
src/assets/scripts/lib/js-dos/emulators.js
Normal file
1
src/assets/scripts/lib/js-dos/emulators.js.map
Normal file
1
src/assets/scripts/lib/js-dos/js-dos.css
Normal file
513
src/assets/scripts/lib/js-dos/js-dos.js
Normal file
5623
src/assets/scripts/lib/js-dos/test/adapter-latest.js
Normal file
BIN
src/assets/scripts/lib/js-dos/test/arkanoid.zip
Normal file
113
src/assets/scripts/lib/js-dos/test/audio-node.js
Normal file
@ -0,0 +1,113 @@
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
exports.audioNode = void 0;
|
||||
var SamplesQueue = /** @class */ (function () {
|
||||
function SamplesQueue() {
|
||||
this.samplesQueue = [];
|
||||
}
|
||||
SamplesQueue.prototype.push = function (samples) {
|
||||
this.samplesQueue.push(samples);
|
||||
};
|
||||
SamplesQueue.prototype.length = function () {
|
||||
var total = 0;
|
||||
for (var _i = 0, _a = this.samplesQueue; _i < _a.length; _i++) {
|
||||
var next = _a[_i];
|
||||
total += next.length;
|
||||
}
|
||||
return total;
|
||||
};
|
||||
SamplesQueue.prototype.writeTo = function (dst, bufferSize) {
|
||||
var writeIt = 0;
|
||||
while (this.samplesQueue.length > 0) {
|
||||
var src = this.samplesQueue[0];
|
||||
var toRead = Math.min(bufferSize - writeIt, src.length);
|
||||
if (toRead === src.length) {
|
||||
dst.set(src, writeIt);
|
||||
this.samplesQueue.shift();
|
||||
}
|
||||
else {
|
||||
dst.set(src.slice(0, toRead), writeIt);
|
||||
this.samplesQueue[0] = src.slice(toRead);
|
||||
}
|
||||
writeIt += toRead;
|
||||
if (writeIt === bufferSize) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (writeIt < bufferSize) {
|
||||
dst.fill(0, writeIt);
|
||||
}
|
||||
};
|
||||
return SamplesQueue;
|
||||
}());
|
||||
function audioNode(ci) {
|
||||
var sampleRate = ci.soundFrequency();
|
||||
var channels = 1;
|
||||
if (sampleRate === 0) {
|
||||
console.warn("Can't create audio node with sampleRate === 0, ingnoring");
|
||||
return;
|
||||
}
|
||||
var audioContext = null;
|
||||
if (typeof AudioContext !== "undefined") {
|
||||
audioContext = new AudioContext({
|
||||
sampleRate: sampleRate,
|
||||
latencyHint: "interactive"
|
||||
});
|
||||
}
|
||||
else if (typeof window.webkitAudioContext !== "undefined") {
|
||||
// eslint-disable-next-line new-cap
|
||||
audioContext = new window.webkitAudioContext({
|
||||
sampleRate: sampleRate,
|
||||
latencyHint: "interactive"
|
||||
});
|
||||
}
|
||||
if (audioContext == null) {
|
||||
return;
|
||||
}
|
||||
var samplesQueue = new SamplesQueue();
|
||||
var bufferSize = 2048;
|
||||
var preBufferSize = 2048;
|
||||
ci.events().onSoundPush(function (samples) {
|
||||
if (samplesQueue.length() < bufferSize * 2 + preBufferSize) {
|
||||
samplesQueue.push(samples);
|
||||
}
|
||||
});
|
||||
var audioNode = audioContext.createScriptProcessor(bufferSize, 0, channels);
|
||||
var started = false;
|
||||
var active = 0;
|
||||
var onQueueProcess = function (event) {
|
||||
var numFrames = event.outputBuffer.length;
|
||||
var numChannels = event.outputBuffer.numberOfChannels;
|
||||
var samplesCount = samplesQueue.length();
|
||||
if (!started) {
|
||||
started = samplesCount >= preBufferSize;
|
||||
}
|
||||
if (!started) {
|
||||
return;
|
||||
}
|
||||
for (var channel = 0; channel < numChannels; channel++) {
|
||||
var channelData = event.outputBuffer.getChannelData(channel);
|
||||
samplesQueue.writeTo(channelData, numFrames);
|
||||
}
|
||||
};
|
||||
audioNode.onaudioprocess = onQueueProcess;
|
||||
audioNode.connect(audioContext.destination);
|
||||
var resumeWebAudio = function () {
|
||||
if (audioContext !== null && audioContext.state === "suspended") {
|
||||
audioContext.resume();
|
||||
}
|
||||
};
|
||||
document.addEventListener("click", resumeWebAudio, { once: true });
|
||||
document.addEventListener("touchstart", resumeWebAudio, { once: true });
|
||||
document.addEventListener("keydown", resumeWebAudio, { once: true });
|
||||
ci.events().onExit(function () {
|
||||
if (audioContext !== null) {
|
||||
audioNode.disconnect();
|
||||
audioContext.close();
|
||||
}
|
||||
document.removeEventListener("click", resumeWebAudio);
|
||||
document.removeEventListener("touchstart", resumeWebAudio);
|
||||
document.removeEventListener("keydown", resumeWebAudio);
|
||||
});
|
||||
}
|
||||
exports.audioNode = audioNode;
|
10854
src/assets/scripts/lib/js-dos/test/chai.js
Normal file
85
src/assets/scripts/lib/js-dos/test/dhry2-node.js
Normal file
@ -0,0 +1,85 @@
|
||||
const fs = require("fs");
|
||||
require("../emulators");
|
||||
|
||||
const backend = process.argv[2] === "x" ? "dosboxXNode" : "dosboxNode";
|
||||
const emulators = global.emulators;
|
||||
emulators.pathPrefix = "./";
|
||||
|
||||
const bundle = fs.readFileSync("dhry2.jsdos");
|
||||
let startedAt = null;
|
||||
let runStartedAt = Date.now();
|
||||
let prevNonSkippableSleepCount = 0;
|
||||
let prevSleepCount = 0;
|
||||
let prevCycles = 0;
|
||||
const medianVax = [];
|
||||
const medianCycles = [];
|
||||
const medianNonSkippableSleepCount = [];
|
||||
const medianSleepCount = [];
|
||||
const sortFn = (a, b) => a - b;
|
||||
|
||||
console.log("Dhrystone 2 Test for " + backend);
|
||||
emulators[backend](bundle)
|
||||
.then((ci) => {
|
||||
ci.events().onStdout((message) => {
|
||||
if (!message.startsWith("dhry2:")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (startedAt === null) {
|
||||
startedAt = Date.now();
|
||||
}
|
||||
|
||||
const [_, runs, delta, vax] = message.split(" ");
|
||||
console.log("dhry2: " + runs + " runs, browser time " + delta + " ms, " +
|
||||
"VAX rating " + vax);
|
||||
ci.asyncifyStats().then((stats) => {
|
||||
const dt = Date.now() - runStartedAt;
|
||||
const nonSkippableSleepCount = stats.nonSkippableSleepCount - prevNonSkippableSleepCount;
|
||||
const sleepCount = stats.sleepCount - prevSleepCount;
|
||||
const cycles = stats.cycles - prevCycles;
|
||||
prevNonSkippableSleepCount = stats.nonSkippableSleepCount;
|
||||
prevSleepCount = stats.sleepCount;
|
||||
prevCycles = stats.cycles;
|
||||
runStartedAt = Date.now();
|
||||
medianNonSkippableSleepCount.push(nonSkippableSleepCount * 1000 / dt);
|
||||
medianSleepCount.push(sleepCount * 1000 / dt);
|
||||
medianCycles.push(cycles / dt);
|
||||
console.log("dhry2: sleep p/sec: " + Math.round(sleepCount * 1000 / dt) +
|
||||
" , non skippable p/sec: " + Math.round(nonSkippableSleepCount * 1000 / dt) +
|
||||
" , avg cycles p/ms: " + Math.round(cycles / dt));
|
||||
});
|
||||
medianVax.push(vax);
|
||||
if (runs === "320000") {
|
||||
const executionTimeSec = (Date.now() - startedAt) / 1000;
|
||||
medianVax.sort(sortFn);
|
||||
medianNonSkippableSleepCount.sort(sortFn);
|
||||
medianSleepCount.sort(sortFn);
|
||||
medianCycles.sort(sortFn);
|
||||
|
||||
console.log("Time:", Math.round(executionTimeSec * 10) / 10, "sec",
|
||||
"RpS:", Math.round((runs - 1000) / executionTimeSec),
|
||||
"Med VAX:", medianVax[Math.round(medianVax.length / 2)]);
|
||||
|
||||
ci.asyncifyStats().then((stats) => {
|
||||
console.log("Message sent:", stats.messageSent,
|
||||
"(frame", stats.messageFrame + ")",
|
||||
"(sound", stats.messageSound + ")");
|
||||
console.log("Message recv:", stats.messageReceived);
|
||||
|
||||
console.log("Sleep count:", stats.sleepCount);
|
||||
console.log("Sleep time:", Math.round(stats.sleepTime / 1000 * 10) / 10, "sec");
|
||||
console.log("Avg sleep:", stats.sleepTime / stats.sleepCount, "ms");
|
||||
console.log("Med non skippable sleep p/sec: ",
|
||||
Math.round(medianNonSkippableSleepCount[Math.round(medianNonSkippableSleepCount.length / 2)]));
|
||||
console.log("Med sleep p/sec:",
|
||||
Math.round(medianSleepCount[Math.round(medianSleepCount.length / 2)]));
|
||||
console.log("Med cycles p/ms:",
|
||||
Math.round(medianCycles[Math.round(medianCycles.length / 2)]));
|
||||
|
||||
// properly exit
|
||||
ci.exit();
|
||||
});
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch(console.error);
|
135
src/assets/scripts/lib/js-dos/test/dhry2.html
Normal file
@ -0,0 +1,135 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<style>
|
||||
html,
|
||||
body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
<script src="../emulators.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div>
|
||||
<button onClick="javascript:downloadBundleAndRun({worker: true, x: false})">dosboxWorker</button>
|
||||
<button onClick="javascript:downloadBundleAndRun({worker: false, x: false})">dosboxDirect</button>
|
||||
<button onClick="javascript:downloadBundleAndRun({worker: true, x: true})">xWorker</button>
|
||||
<button onClick="javascript:downloadBundleAndRun({worker: false, x: true})">xDirect</button>
|
||||
<pre id="stdout"></pre>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
emulators.pathPrefix = "../";
|
||||
|
||||
let runId = 0;
|
||||
async function runBundle(bundle, options) {
|
||||
const id = runId++;
|
||||
const stdout = document.getElementById("stdout");
|
||||
|
||||
// promise is resolved when emulator is started
|
||||
const ci = await (options.worker ?
|
||||
(options.x ? emulators.dosboxXWorker(bundle) : emulators.dosboxWorker(bundle)) :
|
||||
(options.x ? emulators.dosboxXDirect(bundle) : emulators.dosDirect(bundle)));
|
||||
|
||||
|
||||
let startedAt = null;
|
||||
let runStartedAt = Date.now();
|
||||
let prevNonSkippableSleepCount = 0;
|
||||
let prevSleepCount = 0;
|
||||
let prevCycles = 0;
|
||||
const medianVax = [];
|
||||
const medianCycles = [];
|
||||
const medianNonSkippableSleepCount = [];
|
||||
const medianSleepCount = [];
|
||||
const sortFn = (a, b) => a - b;
|
||||
ci.events().onStdout((message) => {
|
||||
if (!message.startsWith("dhry2:")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (startedAt === null) {
|
||||
startedAt = Date.now();
|
||||
}
|
||||
|
||||
const [_, runs, delta, vax] = message.split(" ");
|
||||
stdout.innerHTML += (id) + ": " + runs + " runs, browser time " + delta + " ms, " +
|
||||
"VAX rating " + vax + "\n";
|
||||
ci.asyncifyStats().then((stats) => {
|
||||
const dt = Date.now() - runStartedAt;
|
||||
const nonSkippableSleepCount = stats.nonSkippableSleepCount - prevNonSkippableSleepCount;
|
||||
const sleepCount = stats.sleepCount - prevSleepCount;
|
||||
const cycles = stats.cycles - prevCycles;
|
||||
prevNonSkippableSleepCount = stats.nonSkippableSleepCount;
|
||||
prevSleepCount = stats.sleepCount;
|
||||
prevCycles = stats.cycles;
|
||||
runStartedAt = Date.now();
|
||||
medianNonSkippableSleepCount.push(nonSkippableSleepCount * 1000 / dt);
|
||||
medianSleepCount.push(sleepCount * 1000 / dt);
|
||||
medianCycles.push(cycles / dt);
|
||||
stdout.innerHTML += (id) + ": sleep p/sec: " + Math.round(sleepCount * 1000 /dt) +
|
||||
" , non skippable p/sec: " + Math.round(nonSkippableSleepCount * 1000 / dt) +
|
||||
" , avg cycles p/ms: " + Math.round(cycles / dt) + "\n";
|
||||
});
|
||||
medianVax.push(vax);
|
||||
if (runs === "320000") {
|
||||
const executionTimeSec = (Date.now() - startedAt) / 1000;
|
||||
medianVax.sort(sortFn);
|
||||
medianNonSkippableSleepCount.sort(sortFn);
|
||||
medianSleepCount.sort(sortFn);
|
||||
medianCycles.sort(sortFn);
|
||||
|
||||
stdout.innerHTML += (id) +
|
||||
": Time: " + Math.round(executionTimeSec * 10) / 10 + " sec" +
|
||||
" RpS: " + Math.round((runs - 1000) / executionTimeSec) +
|
||||
" Med VAX: " + medianVax[medianVax.length / 2] + "\n";
|
||||
|
||||
ci.asyncifyStats().then((stats) => {
|
||||
const dt = Date.now() - startedAt;
|
||||
stdout.innerHTML += (id) + ": Message sent: " + stats.messageSent +
|
||||
"(frame " + stats.messageFrame + ") " +
|
||||
"(sound " + stats.messageSound + ")\n";
|
||||
stdout.innerHTML += (id) + ": Message recv: " + stats.messageReceived + "\n";
|
||||
stdout.innerHTML += (id) + ": Sleep count: " + stats.sleepCount + "\n";
|
||||
stdout.innerHTML += (id) + ": Sleep time: " + Math.round(stats.sleepTime / 1000 * 10) / 10 + "sec\n";
|
||||
stdout.innerHTML += (id) + ": Avg sleep time: " + stats.sleepTime / stats.sleepCount + "ms\n";
|
||||
stdout.innerHTML += (id) + ": Med non skippable sleep p/sec: " +
|
||||
Math.round(medianNonSkippableSleepCount[Math.round(medianNonSkippableSleepCount.length / 2)]) + "\n";
|
||||
stdout.innerHTML += (id) + ": Med sleep p/sec: " +
|
||||
Math.round(medianSleepCount[Math.round(medianSleepCount.length / 2)]) + "\n";
|
||||
stdout.innerHTML += (id) + ": Med cycles p/ms: " +
|
||||
Math.round(medianCycles[Math.round(medianCycles.length / 2)]) + "\n";
|
||||
|
||||
//properly exit
|
||||
ci.exit();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function downloadBundleAndRun(options) {
|
||||
const bundleUrl = "dhry2.jsdos";
|
||||
|
||||
// we need to download bundle, emulators accept only Uint8Array
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", bundleUrl, true);
|
||||
xhr.overrideMimeType("text/plain; charset=x-user-defined");
|
||||
xhr.responseType = "arraybuffer";
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === 4 && xhr.status === 200) {
|
||||
// do not forget to create Uint8Array,
|
||||
// arraybuffer will not work!
|
||||
runBundle(new Uint8Array(xhr.response), options);
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
BIN
src/assets/scripts/lib/js-dos/test/dhry2.jsdos
Normal file
BIN
src/assets/scripts/lib/js-dos/test/digger-end.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
src/assets/scripts/lib/js-dos/test/digger.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
src/assets/scripts/lib/js-dos/test/digger.zip
Normal file
BIN
src/assets/scripts/lib/js-dos/test/dosbox-x/dosboxconf.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
src/assets/scripts/lib/js-dos/test/dosbox-x/init.png
Normal file
After Width: | Height: | Size: 20 KiB |
BIN
src/assets/scripts/lib/js-dos/test/dosbox-x/mousetst.png
Normal file
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 16 KiB |
BIN
src/assets/scripts/lib/js-dos/test/dosbox-x/persistent-mount.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
src/assets/scripts/lib/js-dos/test/dosbox/dosboxconf.png
Normal file
After Width: | Height: | Size: 9.1 KiB |
BIN
src/assets/scripts/lib/js-dos/test/dosbox/init.png
Normal file
After Width: | Height: | Size: 9.1 KiB |
BIN
src/assets/scripts/lib/js-dos/test/dosbox/mousetst.png
Normal file
After Width: | Height: | Size: 8.8 KiB |
After Width: | Height: | Size: 7.0 KiB |
BIN
src/assets/scripts/lib/js-dos/test/dosbox/persistent-mount.png
Normal file
After Width: | Height: | Size: 7.0 KiB |
BIN
src/assets/scripts/lib/js-dos/test/elonmusk.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
src/assets/scripts/lib/js-dos/test/helloworld.jsdos
Normal file
325
src/assets/scripts/lib/js-dos/test/mocha.css
Normal file
@ -0,0 +1,325 @@
|
||||
@charset "utf-8";
|
||||
|
||||
body {
|
||||
margin:0;
|
||||
}
|
||||
|
||||
#mocha {
|
||||
font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
margin: 60px 50px;
|
||||
}
|
||||
|
||||
#mocha ul,
|
||||
#mocha li {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#mocha ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
#mocha h1,
|
||||
#mocha h2 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#mocha h1 {
|
||||
margin-top: 15px;
|
||||
font-size: 1em;
|
||||
font-weight: 200;
|
||||
}
|
||||
|
||||
#mocha h1 a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
#mocha h1 a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#mocha .suite .suite h1 {
|
||||
margin-top: 0;
|
||||
font-size: .8em;
|
||||
}
|
||||
|
||||
#mocha .hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#mocha h2 {
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#mocha .suite {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
#mocha .test {
|
||||
margin-left: 15px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#mocha .test.pending:hover h2::after {
|
||||
content: '(pending)';
|
||||
font-family: arial, sans-serif;
|
||||
}
|
||||
|
||||
#mocha .test.pass.medium .duration {
|
||||
background: #c09853;
|
||||
}
|
||||
|
||||
#mocha .test.pass.slow .duration {
|
||||
background: #b94a48;
|
||||
}
|
||||
|
||||
#mocha .test.pass::before {
|
||||
content: '✓';
|
||||
font-size: 12px;
|
||||
display: block;
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
color: #00d6b2;
|
||||
}
|
||||
|
||||
#mocha .test.pass .duration {
|
||||
font-size: 9px;
|
||||
margin-left: 5px;
|
||||
padding: 2px 5px;
|
||||
color: #fff;
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
|
||||
-moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
|
||||
box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
-ms-border-radius: 5px;
|
||||
-o-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
#mocha .test.pass.fast .duration {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#mocha .test.pending {
|
||||
color: #0b97c4;
|
||||
}
|
||||
|
||||
#mocha .test.pending::before {
|
||||
content: '◦';
|
||||
color: #0b97c4;
|
||||
}
|
||||
|
||||
#mocha .test.fail {
|
||||
color: #c00;
|
||||
}
|
||||
|
||||
#mocha .test.fail pre {
|
||||
color: black;
|
||||
}
|
||||
|
||||
#mocha .test.fail::before {
|
||||
content: '✖';
|
||||
font-size: 12px;
|
||||
display: block;
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
color: #c00;
|
||||
}
|
||||
|
||||
#mocha .test pre.error {
|
||||
color: #c00;
|
||||
max-height: 300px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#mocha .test .html-error {
|
||||
overflow: auto;
|
||||
color: black;
|
||||
display: block;
|
||||
float: left;
|
||||
clear: left;
|
||||
font: 12px/1.5 monaco, monospace;
|
||||
margin: 5px;
|
||||
padding: 15px;
|
||||
border: 1px solid #eee;
|
||||
max-width: 85%; /*(1)*/
|
||||
max-width: -webkit-calc(100% - 42px);
|
||||
max-width: -moz-calc(100% - 42px);
|
||||
max-width: calc(100% - 42px); /*(2)*/
|
||||
max-height: 300px;
|
||||
word-wrap: break-word;
|
||||
border-bottom-color: #ddd;
|
||||
-webkit-box-shadow: 0 1px 3px #eee;
|
||||
-moz-box-shadow: 0 1px 3px #eee;
|
||||
box-shadow: 0 1px 3px #eee;
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
#mocha .test .html-error pre.error {
|
||||
border: none;
|
||||
-webkit-border-radius: 0;
|
||||
-moz-border-radius: 0;
|
||||
border-radius: 0;
|
||||
-webkit-box-shadow: 0;
|
||||
-moz-box-shadow: 0;
|
||||
box-shadow: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
margin-top: 18px;
|
||||
max-height: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* (1): approximate for browsers not supporting calc
|
||||
* (2): 42 = 2*15 + 2*10 + 2*1 (padding + margin + border)
|
||||
* ^^ seriously
|
||||
*/
|
||||
#mocha .test pre {
|
||||
display: block;
|
||||
float: left;
|
||||
clear: left;
|
||||
font: 12px/1.5 monaco, monospace;
|
||||
margin: 5px;
|
||||
padding: 15px;
|
||||
border: 1px solid #eee;
|
||||
max-width: 85%; /*(1)*/
|
||||
max-width: -webkit-calc(100% - 42px);
|
||||
max-width: -moz-calc(100% - 42px);
|
||||
max-width: calc(100% - 42px); /*(2)*/
|
||||
word-wrap: break-word;
|
||||
border-bottom-color: #ddd;
|
||||
-webkit-box-shadow: 0 1px 3px #eee;
|
||||
-moz-box-shadow: 0 1px 3px #eee;
|
||||
box-shadow: 0 1px 3px #eee;
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
#mocha .test h2 {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#mocha .test a.replay {
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
right: 0;
|
||||
text-decoration: none;
|
||||
vertical-align: middle;
|
||||
display: block;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
line-height: 15px;
|
||||
text-align: center;
|
||||
background: #eee;
|
||||
font-size: 15px;
|
||||
-webkit-border-radius: 15px;
|
||||
-moz-border-radius: 15px;
|
||||
border-radius: 15px;
|
||||
-webkit-transition:opacity 200ms;
|
||||
-moz-transition:opacity 200ms;
|
||||
-o-transition:opacity 200ms;
|
||||
transition: opacity 200ms;
|
||||
opacity: 0.3;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
#mocha .test:hover a.replay {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
#mocha-report.pass .test.fail {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#mocha-report.fail .test.pass {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#mocha-report.pending .test.pass,
|
||||
#mocha-report.pending .test.fail {
|
||||
display: none;
|
||||
}
|
||||
#mocha-report.pending .test.pass.pending {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#mocha-error {
|
||||
color: #c00;
|
||||
font-size: 1.5em;
|
||||
font-weight: 100;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
#mocha-stats {
|
||||
position: fixed;
|
||||
top: 15px;
|
||||
right: 10px;
|
||||
font-size: 12px;
|
||||
margin: 0;
|
||||
color: #888;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
#mocha-stats .progress {
|
||||
float: right;
|
||||
padding-top: 0;
|
||||
|
||||
/**
|
||||
* Set safe initial values, so mochas .progress does not inherit these
|
||||
* properties from Bootstrap .progress (which causes .progress height to
|
||||
* equal line height set in Bootstrap).
|
||||
*/
|
||||
height: auto;
|
||||
-webkit-box-shadow: none;
|
||||
-moz-box-shadow: none;
|
||||
box-shadow: none;
|
||||
background-color: initial;
|
||||
}
|
||||
|
||||
#mocha-stats em {
|
||||
color: black;
|
||||
}
|
||||
|
||||
#mocha-stats a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
#mocha-stats a:hover {
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
#mocha-stats li {
|
||||
display: inline-block;
|
||||
margin: 0 5px;
|
||||
list-style: none;
|
||||
padding-top: 11px;
|
||||
}
|
||||
|
||||
#mocha-stats canvas {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
#mocha code .comment { color: #ddd; }
|
||||
#mocha code .init { color: #2f6fad; }
|
||||
#mocha code .string { color: #5890ad; }
|
||||
#mocha code .keyword { color: #8a6343; }
|
||||
#mocha code .number { color: #2f6fad; }
|
||||
|
||||
@media screen and (max-device-width: 480px) {
|
||||
#mocha {
|
||||
margin: 60px 0px;
|
||||
}
|
||||
|
||||
#mocha #stats {
|
||||
position: absolute;
|
||||
}
|
||||
}
|
18178
src/assets/scripts/lib/js-dos/test/mocha.js
Normal file
BIN
src/assets/scripts/lib/js-dos/test/mousetst.jsdos
Normal file
5
src/assets/scripts/lib/js-dos/test/stats.min.js
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
// stats.js - http://github.com/mrdoob/stats.js
|
||||
(function(f,e){"object"===typeof exports&&"undefined"!==typeof module?module.exports=e():"function"===typeof define&&define.amd?define(e):f.Stats=e()})(this,function(){var f=function(){function e(a){c.appendChild(a.dom);return a}function u(a){for(var d=0;d<c.children.length;d++)c.children[d].style.display=d===a?"block":"none";l=a}var l=0,c=document.createElement("div");c.style.cssText="position:fixed;top:0;left:0;cursor:pointer;opacity:0.9;z-index:10000";c.addEventListener("click",function(a){a.preventDefault();
|
||||
u(++l%c.children.length)},!1);var k=(performance||Date).now(),g=k,a=0,r=e(new f.Panel("FPS","#0ff","#002")),h=e(new f.Panel("MS","#0f0","#020"));if(self.performance&&self.performance.memory)var t=e(new f.Panel("MB","#f08","#201"));u(0);return{REVISION:16,dom:c,addPanel:e,showPanel:u,begin:function(){k=(performance||Date).now()},end:function(){a++;var c=(performance||Date).now();h.update(c-k,200);if(c>=g+1E3&&(r.update(1E3*a/(c-g),100),g=c,a=0,t)){var d=performance.memory;t.update(d.usedJSHeapSize/
|
||||
1048576,d.jsHeapSizeLimit/1048576)}return c},update:function(){k=this.end()},domElement:c,setMode:u}};f.Panel=function(e,f,l){var c=Infinity,k=0,g=Math.round,a=g(window.devicePixelRatio||1),r=80*a,h=48*a,t=3*a,v=2*a,d=3*a,m=15*a,n=74*a,p=30*a,q=document.createElement("canvas");q.width=r;q.height=h;q.style.cssText="width:80px;height:48px";var b=q.getContext("2d");b.font="bold "+9*a+"px Helvetica,Arial,sans-serif";b.textBaseline="top";b.fillStyle=l;b.fillRect(0,0,r,h);b.fillStyle=f;b.fillText(e,t,v);
|
||||
b.fillRect(d,m,n,p);b.fillStyle=l;b.globalAlpha=.9;b.fillRect(d,m,n,p);return{dom:q,update:function(h,w){c=Math.min(c,h);k=Math.max(k,h);b.fillStyle=l;b.globalAlpha=1;b.fillRect(0,0,r,m);b.fillStyle=f;b.fillText(g(h)+" "+e+" ("+g(c)+"-"+g(k)+")",t,v);b.drawImage(q,d+a,m,n-a,p,d,m,n-a,p);b.fillRect(d+n-a,m,a,p);b.fillStyle=l;b.globalAlpha=.9;b.fillRect(d+n-a,m,a,g((1-h/w)*p))}}};return f});
|
161
src/assets/scripts/lib/js-dos/test/template.html
Normal file
@ -0,0 +1,161 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<style>
|
||||
html,
|
||||
body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
layout {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
</style>
|
||||
<script src="../emulators.js"></script>
|
||||
<script src="audio-node.js"></script>
|
||||
<script src="webgl.js"></script>
|
||||
<script src="stats.min.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="layout">
|
||||
<div id="controls">
|
||||
<button onClick="javascript:downloadBundleAndRun({worker: true, x: false})">dosboxWorker</button>
|
||||
<button onClick="javascript:downloadBundleAndRun({worker: false, x: false})">dosboxDirect</button>
|
||||
<button onClick="javascript:downloadBundleAndRun({worker: true, x: true})">xWorker</button>
|
||||
<button onClick="javascript:downloadBundleAndRun({worker: false, x: true})">xDirect</button>
|
||||
</div>
|
||||
<p>FRAME:</p>
|
||||
<canvas id="canvas"></canvas>
|
||||
<p id="stats"></p>
|
||||
<p>STDOUT:</p>
|
||||
<pre id="stdout"></pre>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
emulators.pathPrefix = "../";
|
||||
|
||||
const stats = new Stats();
|
||||
stats.showPanel(0);
|
||||
stats.dom.style.left = "initial";
|
||||
stats.dom.style.right = "0px";
|
||||
document.body.appendChild(stats.dom);
|
||||
|
||||
let runId = 0;
|
||||
async function runBundle(bundle, options) {
|
||||
const id = runId++;
|
||||
const stdout = document.getElementById("stdout");
|
||||
const canvas = document.getElementById("canvas");
|
||||
const gl = canvas.getContext("webgl");
|
||||
const statsEl = document.getElementById("stats");
|
||||
|
||||
// promise is resolved when emulator is started
|
||||
const ci = await (options.worker ?
|
||||
(options.x ? emulators.dosboxXWorker(bundle) : emulators.dosboxWorker(bundle)) :
|
||||
(options.x ? emulators.dosboxXDirect(bundle) : emulators.dosDirect(bundle)));
|
||||
|
||||
let intervalStartedAt = Date.now();
|
||||
let prevNonSkippableSleepCount = 0;
|
||||
let prevSleepCount = 0;
|
||||
let prevCycles = 0;
|
||||
setInterval(() => {
|
||||
ci.asyncifyStats().then((stats) => {
|
||||
const dt = Date.now() - intervalStartedAt;
|
||||
const nonSkippableSleep = stats.nonSkippableSleepCount - prevNonSkippableSleepCount;
|
||||
const avgSleep = (stats.sleepCount - prevSleepCount) * 1000 / dt;
|
||||
const avgNonSkippableSleep = (stats.nonSkippableSleepCount - prevNonSkippableSleepCount) * 1000 / dt;
|
||||
const avgCycles = (stats.cycles - prevCycles) / dt;
|
||||
intervalStartedAt = Date.now();
|
||||
prevNonSkippableSleepCount = stats.nonSkippableSleepCount;
|
||||
prevSleepCount = stats.sleepCount;
|
||||
prevCycles = stats.cycles;
|
||||
statsEl.innerHTML = "Avg sleep p/sec: " + Math.round(avgSleep) +
|
||||
", avg non skippable sleep p/sec: " + Math.round(avgNonSkippableSleep) +
|
||||
", cycles p/ms: " + Math.round(avgCycles);
|
||||
});
|
||||
}, 3000);
|
||||
|
||||
window.ci = ci;
|
||||
|
||||
webGl({
|
||||
canvas,
|
||||
addOnResize: () => {},
|
||||
}, ci, stats);
|
||||
audioNode(ci);
|
||||
|
||||
ci.events().onStdout((message) => {
|
||||
stdout.innerHTML += message;
|
||||
});
|
||||
|
||||
// ci.events().onMessage(console.log.bind(console));
|
||||
|
||||
function getKeyCode(code) {
|
||||
switch (code) {
|
||||
case 13: return 257;
|
||||
case 38: return 265;
|
||||
case 39: return 262;
|
||||
case 37: return 263;
|
||||
case 40: return 264;
|
||||
case 17: return 342;
|
||||
case 190: return 46;
|
||||
default: return code;
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("keydown", (e) => {
|
||||
ci.sendKeyEvent(getKeyCode(e.keyCode), true);
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
});
|
||||
window.addEventListener("keyup", (e) => {
|
||||
ci.sendKeyEvent(getKeyCode(e.keyCode), false);
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
});
|
||||
canvas.addEventListener("mousemove", (e) => {
|
||||
ci.sendMouseMotion(
|
||||
(e.clientX - canvas.offsetLeft) / canvas.width,
|
||||
(e.clientY - canvas.offsetTop) / canvas.height);
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
});
|
||||
canvas.addEventListener("mousedown", (e) => {
|
||||
ci.sendMouseButton(0, true);
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
});
|
||||
canvas.addEventListener("mouseup", (e) => {
|
||||
ci.sendMouseButton(0, false);
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
});
|
||||
}
|
||||
|
||||
function downloadBundleAndRun(options) {
|
||||
document.getElementById("controls").style.display = "none";
|
||||
const bundleUrl = "temp.jsdos?timestamp=" + Date.now();
|
||||
|
||||
// we need to download bundle, emulators accept only Uint8Array
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", bundleUrl, true);
|
||||
xhr.overrideMimeType("text/plain; charset=x-user-defined");
|
||||
xhr.responseType = "arraybuffer";
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === 4 && xhr.status === 200) {
|
||||
// do not forget to create Uint8Array,
|
||||
// arraybuffer will not work!
|
||||
runBundle(new Uint8Array(xhr.response), options);
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
75
src/assets/scripts/lib/js-dos/test/test.html
Normal file
@ -0,0 +1,75 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Emulators Tests</title>
|
||||
<link href="mocha.css" rel="stylesheet" />
|
||||
<style>
|
||||
.test-config {
|
||||
position: fixed;
|
||||
left: 15px;
|
||||
top: 15px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.test-config-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="mocha"></div>
|
||||
<script src="mocha.js"></script>
|
||||
<script src="chai.js"></script>
|
||||
<script>
|
||||
mocha.setup({
|
||||
ui: 'qunit',
|
||||
allowUncaught: true,
|
||||
bail: true,
|
||||
fullTrace: true,
|
||||
timeout: 60000
|
||||
});
|
||||
mocha.allowUncaught();
|
||||
</script>
|
||||
<script src="test.js"></script>
|
||||
|
||||
<div id="test-config" class="test-config">
|
||||
<div class="test-config-row">
|
||||
Server Address:
|
||||
<input id="server-ip" type="text" value="wss://netherlands.dos.zone"></input>
|
||||
|
||||
<button id="start-net">Start Net Tests</button>
|
||||
</div>
|
||||
<br/>
|
||||
<button id="start">Start Tests</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const testConfig = document.getElementById("test-config");
|
||||
const start = document.getElementById("start");
|
||||
const startNet = document.getElementById("start-net");
|
||||
|
||||
start.addEventListener("click", () => {
|
||||
testConfig.style.display = "none";
|
||||
|
||||
window.createTests();
|
||||
mocha.run();
|
||||
});
|
||||
|
||||
startNet.addEventListener("click", () => {
|
||||
testConfig.style.display = "none";
|
||||
|
||||
window.ipxServerAddress = document.getElementById("server-ip").value.trim();
|
||||
window.createNetworkTests();
|
||||
mocha.run();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
18798
src/assets/scripts/lib/js-dos/test/test.js
Normal file
136
src/assets/scripts/lib/js-dos/test/webgl.js
Normal file
@ -0,0 +1,136 @@
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
exports.webGl = void 0;
|
||||
var vsSource = "\nattribute vec4 aVertexPosition;\nattribute vec2 aTextureCoord;\n\nvarying highp vec2 vTextureCoord;\n\nvoid main(void) {\n gl_Position = aVertexPosition;\n vTextureCoord = aTextureCoord;\n}\n";
|
||||
var fsSource = "\nvarying highp vec2 vTextureCoord;\nuniform sampler2D uSampler;\n\n\nvoid main(void) {\n highp vec4 color = texture2D(uSampler, vTextureCoord);\n gl_FragColor = vec4(color.r, color.g, color.b, 1.0);\n}\n";
|
||||
function webGl(layers, ci, stats) {
|
||||
var canvas = layers.canvas;
|
||||
var gl = canvas.getContext("webgl");
|
||||
if (gl === null) {
|
||||
throw new Error("Unable to create webgl context on given canvas");
|
||||
}
|
||||
var shaderProgram = initShaderProgram(gl, vsSource, fsSource);
|
||||
var vertexPosition = gl.getAttribLocation(shaderProgram, "aVertexPosition");
|
||||
var textureCoord = gl.getAttribLocation(shaderProgram, "aTextureCoord");
|
||||
var uSampler = gl.getUniformLocation(shaderProgram, "uSampler");
|
||||
initBuffers(gl, vertexPosition, textureCoord);
|
||||
var texture = gl.createTexture();
|
||||
gl.bindTexture(gl.TEXTURE_2D, texture);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
||||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
||||
var pixel = new Uint8Array([0, 0, 0]);
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, 1, 1, 0, gl.RGB, gl.UNSIGNED_BYTE, pixel);
|
||||
gl.useProgram(shaderProgram);
|
||||
gl.activeTexture(gl.TEXTURE0);
|
||||
gl.uniform1i(uSampler, 0);
|
||||
var containerWidth = layers.width;
|
||||
var containerHeight = layers.height;
|
||||
var frameWidth = 0;
|
||||
var frameHeight = 0;
|
||||
var onResize = function () {
|
||||
var aspect = frameWidth / frameHeight;
|
||||
var width = containerWidth;
|
||||
var height = containerWidth / aspect;
|
||||
if (height > containerHeight) {
|
||||
height = containerHeight;
|
||||
width = containerHeight * aspect;
|
||||
}
|
||||
canvas.style.position = "relative";
|
||||
canvas.style.top = (containerHeight - height) / 2 + "px";
|
||||
canvas.style.left = (containerWidth - width) / 2 + "px";
|
||||
canvas.style.width = width + "px";
|
||||
canvas.style.height = height + "px";
|
||||
};
|
||||
var onResizeLayer = function (w, h) {
|
||||
containerWidth = w;
|
||||
containerHeight = h;
|
||||
onResize();
|
||||
};
|
||||
layers.addOnResize(onResizeLayer);
|
||||
var onResizeFrame = function (w, h) {
|
||||
frameWidth = w;
|
||||
frameHeight = h;
|
||||
canvas.width = frameWidth;
|
||||
canvas.height = frameHeight;
|
||||
gl.viewport(0, 0, frameWidth, frameHeight);
|
||||
onResize();
|
||||
};
|
||||
ci.events().onFrameSize(onResizeFrame);
|
||||
onResizeFrame(ci.width(), ci.height());
|
||||
var requestAnimationFrameId = null;
|
||||
var frame = null;
|
||||
var frameFormat = 0;
|
||||
stats.begin();
|
||||
ci.events().onFrame(function (rgb, rgba) {
|
||||
stats.end();
|
||||
stats.begin();
|
||||
frame = rgb != null ? rgb : rgba;
|
||||
frameFormat = rgb != null ? gl.RGB : gl.RGBA;
|
||||
if (requestAnimationFrameId === null) {
|
||||
requestAnimationFrameId = requestAnimationFrame(updateTexture);
|
||||
}
|
||||
});
|
||||
var updateTexture = function () {
|
||||
gl.texImage2D(gl.TEXTURE_2D, 0, frameFormat, frameWidth, frameHeight, 0, frameFormat, gl.UNSIGNED_BYTE, frame);
|
||||
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
||||
requestAnimationFrameId = null;
|
||||
frame = null;
|
||||
};
|
||||
ci.events().onExit(function () {
|
||||
layers.removeOnResize(onResizeLayer);
|
||||
});
|
||||
}
|
||||
exports.webGl = webGl;
|
||||
function initShaderProgram(gl, vsSource, fsSource) {
|
||||
var vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
|
||||
var fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);
|
||||
var shaderProgram = gl.createProgram();
|
||||
gl.attachShader(shaderProgram, vertexShader);
|
||||
gl.attachShader(shaderProgram, fragmentShader);
|
||||
gl.linkProgram(shaderProgram);
|
||||
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
|
||||
throw new Error("Unable to initialize the shader program: " + gl.getProgramInfoLog(shaderProgram));
|
||||
}
|
||||
return shaderProgram;
|
||||
}
|
||||
function loadShader(gl, shaderType, source) {
|
||||
var shader = gl.createShader(shaderType);
|
||||
gl.shaderSource(shader, source);
|
||||
gl.compileShader(shader);
|
||||
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
||||
var info = gl.getShaderInfoLog(shader);
|
||||
gl.deleteShader(shader);
|
||||
throw new Error("An error occurred compiling the shaders: " + info);
|
||||
}
|
||||
return shader;
|
||||
}
|
||||
function initBuffers(gl, vertexPosition, textureCoord) {
|
||||
var positionBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
|
||||
var positions = [
|
||||
-1.0, -1.0, 0.0,
|
||||
1.0, -1.0, 0.0,
|
||||
1.0, 1.0, 0.0,
|
||||
-1.0, -1.0, 0.0,
|
||||
1.0, 1.0, 0.0,
|
||||
-1.0, 1.0, 0.0,
|
||||
];
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
|
||||
gl.vertexAttribPointer(vertexPosition, 3, gl.FLOAT, false, 0, 0);
|
||||
gl.enableVertexAttribArray(vertexPosition);
|
||||
var textureCoordBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, textureCoordBuffer);
|
||||
var textureCoordinates = [
|
||||
0.0, 1.0,
|
||||
1.0, 1.0,
|
||||
1.0, 0.0,
|
||||
0.0, 1.0,
|
||||
1.0, 0.0,
|
||||
0.0, 0.0,
|
||||
];
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoordinates), gl.STATIC_DRAW);
|
||||
gl.vertexAttribPointer(textureCoord, 2, gl.FLOAT, false, 0, 0);
|
||||
gl.enableVertexAttribArray(textureCoord);
|
||||
}
|
28
src/assets/scripts/lib/js-dos/types/build.d.ts
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
export declare const Build: {
|
||||
version: string;
|
||||
buildSeed: number;
|
||||
"wdosbox-x.wasm": {
|
||||
size: number;
|
||||
gzSize: number;
|
||||
};
|
||||
"wdosbox-x.js": {
|
||||
size: number;
|
||||
gzSize: number;
|
||||
};
|
||||
"wdosbox.wasm": {
|
||||
size: number;
|
||||
gzSize: number;
|
||||
};
|
||||
"wdosbox.js": {
|
||||
size: number;
|
||||
gzSize: number;
|
||||
};
|
||||
"wlibzip.wasm": {
|
||||
size: number;
|
||||
gzSize: number;
|
||||
};
|
||||
"wlibzip.js": {
|
||||
size: number;
|
||||
gzSize: number;
|
||||
};
|
||||
};
|
20
src/assets/scripts/lib/js-dos/types/dos/bundle/dos-bundle.d.ts
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
import { WasmModule } from "../../impl/modules";
|
||||
export interface DosArchiveSource {
|
||||
url: string;
|
||||
path: string;
|
||||
type?: "zip";
|
||||
}
|
||||
export default class DosBundle {
|
||||
dosboxConf: string;
|
||||
jsdosConf: {
|
||||
version: string;
|
||||
};
|
||||
sources: DosArchiveSource[];
|
||||
private libzipWasm;
|
||||
constructor(libzipWasm: WasmModule);
|
||||
autoexec(...lines: string[]): DosBundle;
|
||||
extract(url: string, path?: string, type?: "zip"): DosBundle;
|
||||
extractAll(sources: DosArchiveSource[]): DosBundle;
|
||||
toUint8Array(overwriteConfig?: boolean): Promise<Uint8Array>;
|
||||
}
|
||||
export declare const defaultConfig: string;
|
3
src/assets/scripts/lib/js-dos/types/dos/dosbox/ts/direct.d.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
import { WasmModule } from "../../../impl/modules";
|
||||
import { TransportLayer } from "../../../protocol/protocol";
|
||||
export declare function dosDirect(wasmModule: WasmModule, sessionId: string, canvas?: OffscreenCanvas): Promise<TransportLayer>;
|
3
src/assets/scripts/lib/js-dos/types/dos/dosbox/ts/worker.d.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
import { WasmModule } from "../../../impl/modules";
|
||||
import { TransportLayer } from "../../../protocol/protocol";
|
||||
export declare function dosWorker(workerUrl: string, wasmModule: WasmModule, sessionId: string, canvas?: OffscreenCanvas): Promise<TransportLayer>;
|
85
src/assets/scripts/lib/js-dos/types/emulators.d.ts
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
import DosBundle from "./dos/bundle/dos-bundle";
|
||||
import { AsyncifyStats, TransportLayer, FsNode } from "./protocol/protocol";
|
||||
export interface DosConfig {
|
||||
dosboxConf: string;
|
||||
jsdosConf: {
|
||||
version: string;
|
||||
};
|
||||
}
|
||||
export declare enum NetworkType {
|
||||
NETWORK_DOSBOX_IPX = 0
|
||||
}
|
||||
export interface BackendOptions {
|
||||
token?: string | undefined;
|
||||
onExtractProgress?: (bundleIndex: number, file: string, extracted: number, total: number) => void;
|
||||
canvas?: OffscreenCanvas;
|
||||
}
|
||||
export type InitBundleEntry = Uint8Array;
|
||||
export interface InitFileEntry {
|
||||
path: string;
|
||||
contents: Uint8Array;
|
||||
}
|
||||
export type InitFsEntry = InitBundleEntry | InitFileEntry | DosConfig | string;
|
||||
export type InitFs = InitFsEntry | InitFsEntry[];
|
||||
export type PersistedSockdrives = {
|
||||
drives: {
|
||||
url: string;
|
||||
persist: Uint8Array;
|
||||
}[];
|
||||
} | null;
|
||||
export interface Emulators {
|
||||
pathPrefix: string;
|
||||
pathSuffix: string;
|
||||
version: string;
|
||||
wdosboxJs: string;
|
||||
bundle: () => Promise<DosBundle>;
|
||||
bundleConfig: (bundle: InitBundleEntry) => Promise<DosConfig | null>;
|
||||
bundleUpdateConfig: (bundle: InitBundleEntry, config: DosConfig) => Promise<Uint8Array>;
|
||||
dosboxNode: (init: InitFs, options?: BackendOptions) => Promise<CommandInterface>;
|
||||
dosboxDirect: (init: InitFs, options?: BackendOptions) => Promise<CommandInterface>;
|
||||
dosboxWorker: (init: InitFs, options?: BackendOptions) => Promise<CommandInterface>;
|
||||
dosboxXNode: (init: InitFs, options?: BackendOptions) => Promise<CommandInterface>;
|
||||
dosboxXDirect: (init: InitFs, options?: BackendOptions) => Promise<CommandInterface>;
|
||||
dosboxXWorker: (init: InitFs, options?: BackendOptions) => Promise<CommandInterface>;
|
||||
backend: (init: InitFs, transportLayer: TransportLayer, options?: BackendOptions) => Promise<CommandInterface>;
|
||||
}
|
||||
export interface CommandInterface {
|
||||
config: () => Promise<DosConfig>;
|
||||
height: () => number;
|
||||
width: () => number;
|
||||
soundFrequency: () => number;
|
||||
screenshot: () => Promise<ImageData>;
|
||||
pause: () => void;
|
||||
resume: () => void;
|
||||
mute: () => void;
|
||||
unmute: () => void;
|
||||
exit: () => Promise<void>;
|
||||
simulateKeyPress: (...keyCodes: number[]) => void;
|
||||
sendKeyEvent: (keyCode: number, pressed: boolean) => void;
|
||||
sendMouseMotion: (x: number, y: number) => void;
|
||||
sendMouseRelativeMotion: (x: number, y: number) => void;
|
||||
sendMouseButton: (button: number, pressed: boolean) => void;
|
||||
sendMouseSync: () => void;
|
||||
sendBackendEvent: (event: any) => void;
|
||||
persist(onlyChanges?: boolean): Promise<Uint8Array | PersistedSockdrives | null>;
|
||||
events(): CommandInterfaceEvents;
|
||||
networkConnect(networkType: NetworkType, address: string): Promise<void>;
|
||||
networkDisconnect(networkType: NetworkType): Promise<void>;
|
||||
asyncifyStats(): Promise<AsyncifyStats>;
|
||||
fsTree(): Promise<FsNode>;
|
||||
fsReadFile(file: string): Promise<Uint8Array>;
|
||||
fsWriteFile(file: string, contents: ReadableStream<Uint8Array> | Uint8Array): Promise<void>;
|
||||
fsDeleteFile(file: string): Promise<boolean>;
|
||||
}
|
||||
export type MessageType = "log" | "warn" | "error" | string;
|
||||
export interface CommandInterfaceEvents {
|
||||
onStdout: (consumer: (message: string) => void) => void;
|
||||
onFrameSize: (consumer: (width: number, height: number) => void) => void;
|
||||
onFrame: (consumer: (rgb: Uint8Array | null, rgba: Uint8Array | null) => void) => void;
|
||||
onSoundPush: (consumer: (samples: Float32Array) => void) => void;
|
||||
onExit: (consumer: () => void) => void;
|
||||
onMessage: (consumer: (msgType: MessageType, ...args: any[]) => void) => void;
|
||||
onNetworkConnected: (consumer: (networkType: NetworkType, address: string) => void) => void;
|
||||
onNetworkDisconnected: (consumer: (networkType: NetworkType) => void) => void;
|
||||
onUnload: (consumer: () => Promise<void>) => void;
|
||||
}
|
9
src/assets/scripts/lib/js-dos/types/http.d.ts
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
export interface XhrOptions {
|
||||
method?: string;
|
||||
progress?: (total: number, loaded: number) => void;
|
||||
data?: string;
|
||||
responseType?: XMLHttpRequestResponseType;
|
||||
}
|
||||
export declare const httpRequest: typeof XhrRequest;
|
||||
declare function XhrRequest(url: string, options: XhrOptions): Promise<string | ArrayBuffer>;
|
||||
export {};
|
32
src/assets/scripts/lib/js-dos/types/impl/ci-impl.d.ts
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
import { CommandInterfaceEvents, MessageType, NetworkType } from "../emulators";
|
||||
export declare class CommandInterfaceEventsImpl implements CommandInterfaceEvents {
|
||||
private onStdoutConsumers;
|
||||
private delayedStdout;
|
||||
private onFrameSizeConsumers;
|
||||
private onFrameConsumers;
|
||||
private onSoundPushConsumers;
|
||||
private onExitConsumers;
|
||||
private onMessageConsumers;
|
||||
private delayedMessages;
|
||||
private onNetworkConnectedConsumers;
|
||||
private onNetworkDisconnectedConsumers;
|
||||
private onUnloadConsumers;
|
||||
onStdout: (consumer: (message: string) => void) => void;
|
||||
onFrameSize: (consumer: (width: number, height: number) => void) => void;
|
||||
onFrame: (consumer: (rgb: Uint8Array | null, rgba: Uint8Array | null) => void) => void;
|
||||
onSoundPush: (consumer: (samples: Float32Array) => void) => void;
|
||||
onExit: (consumer: () => void) => void;
|
||||
onMessage: (consumer: (msgType: MessageType, ...args: any[]) => void) => void;
|
||||
onNetworkConnected(consumer: (networkType: NetworkType, address: string) => void): void;
|
||||
onNetworkDisconnected(consumer: (networkType: NetworkType) => void): void;
|
||||
onUnload: (consumer: () => Promise<void>) => void;
|
||||
fireStdout: (message: string) => void;
|
||||
fireFrameSize: (width: number, height: number) => void;
|
||||
fireFrame: (rgb: Uint8Array | null, rgba: Uint8Array | null) => void;
|
||||
fireSoundPush: (samples: Float32Array) => void;
|
||||
fireExit: () => void;
|
||||
fireMessage: (msgType: MessageType, ...args: any[]) => void;
|
||||
fireNetworkConnected: (networkType: NetworkType, address: string) => void;
|
||||
fireNetworkDisconnected: (networkType: NetworkType) => void;
|
||||
fireUnload: () => Promise<void>;
|
||||
}
|
27
src/assets/scripts/lib/js-dos/types/impl/emulators-impl.d.ts
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
import { Emulators, CommandInterface, BackendOptions, DosConfig, InitFs, InitBundleEntry } from "../emulators";
|
||||
import { IWasmModules } from "./modules";
|
||||
import DosBundle from "../dos/bundle/dos-bundle";
|
||||
import { TransportLayer } from "../protocol/protocol";
|
||||
declare class EmulatorsImpl implements Emulators {
|
||||
pathPrefix: string;
|
||||
pathSuffix: string;
|
||||
version: string;
|
||||
wdosboxJs: string;
|
||||
wdosboxxJs: string;
|
||||
private wasmModulesPromise?;
|
||||
bundle(): Promise<DosBundle>;
|
||||
bundleConfig(bundle: InitBundleEntry): Promise<DosConfig | null>;
|
||||
bundleUpdateConfig(bundle: InitBundleEntry, config: DosConfig): Promise<Uint8Array>;
|
||||
dosboxNode(init: InitFs, options?: BackendOptions): Promise<CommandInterface>;
|
||||
dosboxDirect(init: InitFs, options?: BackendOptions): Promise<CommandInterface>;
|
||||
dosboxWorker(init: InitFs, options?: BackendOptions): Promise<CommandInterface>;
|
||||
dosboxXNode(init: InitFs, options?: BackendOptions): Promise<CommandInterface>;
|
||||
dosboxXDirect(init: InitFs, options?: BackendOptions): Promise<CommandInterface>;
|
||||
dosboxXWorker(init: InitFs, options?: BackendOptions): Promise<CommandInterface>;
|
||||
backend(init: InitFs, transportLayer: TransportLayer, options?: BackendOptions): Promise<CommandInterface>;
|
||||
wasmModules(): Promise<IWasmModules>;
|
||||
dosDirect(init: InitFs): Promise<CommandInterface>;
|
||||
dosWorker(init: InitFs): Promise<CommandInterface>;
|
||||
}
|
||||
declare const emulators: EmulatorsImpl;
|
||||
export default emulators;
|
42
src/assets/scripts/lib/js-dos/types/impl/modules.d.ts
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
export interface WasmModule {
|
||||
instantiate: (module?: any) => Promise<any>;
|
||||
}
|
||||
export interface IWasmModules {
|
||||
libzip: () => Promise<WasmModule>;
|
||||
dosbox: () => Promise<WasmModule>;
|
||||
dosboxx: () => Promise<WasmModule>;
|
||||
}
|
||||
interface Globals {
|
||||
exports: {
|
||||
[moduleName: string]: any;
|
||||
};
|
||||
module: {
|
||||
exports?: () => void;
|
||||
};
|
||||
compiled: {
|
||||
[moduleName: string]: Promise<WasmModule>;
|
||||
};
|
||||
}
|
||||
declare class Host {
|
||||
wasmSupported: boolean;
|
||||
globals: Globals;
|
||||
constructor();
|
||||
}
|
||||
export declare const host: Host;
|
||||
export declare class WasmModulesImpl implements IWasmModules {
|
||||
private pathPrefix;
|
||||
private pathSuffix;
|
||||
private wdosboxJs;
|
||||
private wdosboxxJs;
|
||||
private libzipPromise?;
|
||||
private dosboxPromise?;
|
||||
private dosboxxPromise?;
|
||||
wasmSupported: boolean;
|
||||
constructor(pathPrefix: string, pathSuffix: string, wdosboxJs: string, wdosboxxJs: string);
|
||||
libzip(): Promise<WasmModule>;
|
||||
dosbox(): Promise<WasmModule>;
|
||||
dosboxx(): Promise<WasmModule>;
|
||||
private loadModule;
|
||||
}
|
||||
export declare function loadWasmModule(url: string, moduleName: string, onprogress: (stage: string, total: number, loaded: number) => void): Promise<WasmModule>;
|
||||
export {};
|
16
src/assets/scripts/lib/js-dos/types/libzip/libzip.d.ts
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
export default class LibZip {
|
||||
module: any;
|
||||
private home;
|
||||
constructor(module: any, home?: string);
|
||||
zipFromFs(changedAfterMs?: number): Promise<Uint8Array>;
|
||||
zipToFs(zipArchive: Uint8Array, path?: string, filter?: string): Promise<void>;
|
||||
writeFile(file: string, body: ArrayBuffer | Uint8Array | string): void;
|
||||
readFile(file: string, encoding?: "binary" | "utf8"): Promise<string | Uint8Array>;
|
||||
exists(file: string): boolean;
|
||||
destroy(): any;
|
||||
private normalizeFilename;
|
||||
private createPath;
|
||||
private chdirToHome;
|
||||
private chdir;
|
||||
zipAddFile(archive: string, file: string): Promise<void>;
|
||||
}
|
8
src/assets/scripts/lib/js-dos/types/protocol/messages-queue.d.ts
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
import { ServerMessage, MessageHandler } from "./protocol";
|
||||
export declare class MessagesQueue {
|
||||
private messages;
|
||||
handler(name: ServerMessage, props: {
|
||||
[key: string]: any;
|
||||
}): void;
|
||||
sendTo(handler: MessageHandler): void;
|
||||
}
|
3
src/assets/scripts/lib/js-dos/types/protocol/mini-lz4.d.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
export declare const compressBound: any;
|
||||
export declare const compress: any;
|
||||
export declare const uncompress: any;
|
137
src/assets/scripts/lib/js-dos/types/protocol/protocol.d.ts
vendored
Normal file
@ -0,0 +1,137 @@
|
||||
import { CommandInterface, NetworkType, BackendOptions, DosConfig, InitFsEntry, PersistedSockdrives } from "../emulators";
|
||||
import { CommandInterfaceEventsImpl } from "../impl/ci-impl";
|
||||
export type ClientMessage = "wc-install" | "wc-run" | "wc-pack-fs-to-bundle" | "wc-add-key" | "wc-mouse-move" | "wc-mouse-button" | "wc-mouse-sync" | "wc-exit" | "wc-sync-sleep" | "wc-pause" | "wc-resume" | "wc-mute" | "wc-unmute" | "wc-connect" | "wc-disconnect" | "wc-backend-event" | "wc-asyncify-stats" | "wc-fs-tree" | "wc-fs-get-file" | "wc-send-data-chunk" | "wc-net-connected" | "wc-net-received" | "wc-sockdrive-opened" | "wc-sockdrive-new-range" | "wc-unload" | "wc-fs-delete-file";
|
||||
export type ServerMessage = "ws-extract-progress" | "ws-ready" | "ws-server-ready" | "ws-frame-set-size" | "ws-update-lines" | "ws-log" | "ws-warn" | "ws-err" | "ws-stdout" | "ws-exit" | "ws-persist" | "ws-sound-init" | "ws-sound-push" | "ws-config" | "ws-sync-sleep" | "ws-connected" | "ws-disconnected" | "ws-asyncify-stats" | "ws-fs-tree" | "ws-send-data-chunk" | "ws-net-connect" | "ws-net-disconnect" | "ws-net-send" | "ws-sockdrive-open" | "ws-sockdrive-ready" | "ws-sockdrive-close" | "ws-sockdrive-load-range" | "ws-sockdrive-write-sector" | "ws-unload" | "ws-fs-delete-file";
|
||||
export type MessageHandler = (name: ServerMessage, props: {
|
||||
[key: string]: any;
|
||||
}) => void;
|
||||
export interface TransportLayer {
|
||||
sessionId: string;
|
||||
sendMessageToServer(name: ClientMessage, props: {
|
||||
[key: string]: any;
|
||||
}, transfer?: (ArrayBuffer | OffscreenCanvas)[]): void;
|
||||
initMessageHandler(handler: MessageHandler): void;
|
||||
exit?: () => void;
|
||||
}
|
||||
export interface FrameLine {
|
||||
start: number;
|
||||
heapu8: Uint8Array;
|
||||
}
|
||||
export interface DataChunk {
|
||||
type: "ok" | "file" | "bundle";
|
||||
name: string;
|
||||
data: ArrayBuffer | null;
|
||||
}
|
||||
export interface AsyncifyStats {
|
||||
offscreenCanvas?: boolean;
|
||||
messageSent: number;
|
||||
messageReceived: number;
|
||||
messageFrame: number;
|
||||
messageSound: number;
|
||||
nonSkippableSleepCount: number;
|
||||
sleepCount: number;
|
||||
sleepTime: number;
|
||||
cycles: number;
|
||||
netSent: number;
|
||||
netRecv: number;
|
||||
driveIo: {
|
||||
url: string;
|
||||
preload: number;
|
||||
total: number;
|
||||
read: number;
|
||||
write: number;
|
||||
}[];
|
||||
}
|
||||
export interface FsNode {
|
||||
name: string;
|
||||
size: number | null;
|
||||
nodes: FsNode[] | null;
|
||||
}
|
||||
export declare class CommandInterfaceOverTransportLayer implements CommandInterface {
|
||||
private startedAt;
|
||||
private exited;
|
||||
private frameWidth;
|
||||
private frameHeight;
|
||||
private rgb;
|
||||
private rgba;
|
||||
private freq;
|
||||
private utf8Decoder;
|
||||
private init?;
|
||||
private transport;
|
||||
private ready;
|
||||
private persistPromise?;
|
||||
private persistResolve?;
|
||||
private exitPromise?;
|
||||
private exitResolve?;
|
||||
private eventsImpl;
|
||||
private keyMatrix;
|
||||
private configPromise;
|
||||
private configResolve;
|
||||
private panicMessages;
|
||||
private connectPromise;
|
||||
private connectResolve;
|
||||
private connectReject;
|
||||
private disconnectPromise;
|
||||
private disconnectResolve;
|
||||
private asyncifyStatsPromise;
|
||||
private asyncifyStatsResolve;
|
||||
private fsTreePromise;
|
||||
private fsTreeResolve;
|
||||
private fsGetFilePromise;
|
||||
private fsGetFileResolve;
|
||||
private fsGetFileParts;
|
||||
private fsDeleteFilePromise;
|
||||
private fsDeleteFileResolve;
|
||||
private dataChunkPromise;
|
||||
private dataChunkResolve;
|
||||
private networkId;
|
||||
private network;
|
||||
private sockdrives;
|
||||
options: BackendOptions;
|
||||
constructor(init: InitFsEntry[], transport: TransportLayer, ready: (err: Error | null) => void, options: BackendOptions);
|
||||
private sendClientMessage;
|
||||
private onServerMessage;
|
||||
private onConfig;
|
||||
private onFrameSize;
|
||||
private onFrameLines;
|
||||
private onSoundInit;
|
||||
private onSoundPush;
|
||||
private onLog;
|
||||
private onWarn;
|
||||
private onErr;
|
||||
private onStdout;
|
||||
config(): Promise<DosConfig>;
|
||||
width(): number;
|
||||
height(): number;
|
||||
soundFrequency(): number;
|
||||
screenshot(): Promise<ImageData>;
|
||||
simulateKeyPress(...keyCodes: number[]): void;
|
||||
sendKeyEvent(keyCode: number, pressed: boolean): void;
|
||||
addKey(keyCode: number, pressed: boolean, timeMs: number): void;
|
||||
sendMouseMotion(x: number, y: number): void;
|
||||
sendMouseRelativeMotion(x: number, y: number): void;
|
||||
sendMouseButton(button: number, pressed: boolean): void;
|
||||
sendMouseSync(): void;
|
||||
sendBackendEvent(payload: any): void;
|
||||
persist(optOnlyChanges?: boolean): Promise<Uint8Array | PersistedSockdrives | null>;
|
||||
private onPersist;
|
||||
pause(): void;
|
||||
resume(): void;
|
||||
mute(): void;
|
||||
unmute(): void;
|
||||
exit(): Promise<void>;
|
||||
private onExit;
|
||||
events(): CommandInterfaceEventsImpl;
|
||||
networkConnect(networkType: NetworkType, address: string): Promise<void>;
|
||||
networkDisconnect(networkType: NetworkType): Promise<void>;
|
||||
asyncifyStats(): Promise<AsyncifyStats>;
|
||||
fsTree(): Promise<FsNode>;
|
||||
fsReadFile(file: string): Promise<Uint8Array>;
|
||||
fsWriteFile(file: string, contents: ReadableStream<Uint8Array> | Uint8Array): Promise<void>;
|
||||
fsDeleteFile(file: string): Promise<boolean>;
|
||||
persistSockdrives(): Promise<PersistedSockdrives>;
|
||||
private sendDataChunk;
|
||||
private sendFullDataChunk;
|
||||
private dataChunkKey;
|
||||
private mergeChunks;
|
||||
}
|
18
src/assets/scripts/lib/js-dos/types/protocol/sockdrive-store.d.ts
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
export declare const RAW_STORE = "raw";
|
||||
export declare const WRITE_STORE = "write";
|
||||
export interface Store {
|
||||
put: (key: number, data: Uint8Array, store: string) => Promise<void>;
|
||||
get: (key: number, store: string) => Promise<Uint8Array | null>;
|
||||
keys: (store: string) => Promise<number[]>;
|
||||
each: (key: number[], store: string, callback: (key: number, data: Uint8Array) => void) => Promise<void>;
|
||||
close: () => void;
|
||||
}
|
||||
export declare class NoStore implements Store {
|
||||
owner: string;
|
||||
close(): void;
|
||||
put(key: number, data: Uint8Array, store: string): Promise<void>;
|
||||
get(range: number, store: string): Promise<Uint8Array | null>;
|
||||
keys(store: string): Promise<number[]>;
|
||||
each(keys: number[], store: string, callback: (key: number, data: Uint8Array) => void): Promise<void>;
|
||||
}
|
||||
export declare function getStore(owner: string): Promise<Store>;
|
28
src/assets/scripts/lib/js-dos/types/protocol/sockdrive.d.ts
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
interface DriveInfo {
|
||||
ahead_read: number;
|
||||
range_count: number;
|
||||
dropped_ranges: number[];
|
||||
preload_ranges: number[] | "_";
|
||||
small_ranges: number[];
|
||||
cylinders: number;
|
||||
heads: number;
|
||||
sectors: number;
|
||||
sector_size: number;
|
||||
size: number;
|
||||
name: string;
|
||||
url: string;
|
||||
preloadSizeInBytes: number;
|
||||
sizeInBytes: number;
|
||||
readInBytes: number;
|
||||
writeInBytes: number;
|
||||
}
|
||||
export interface Drive {
|
||||
info: DriveInfo;
|
||||
range(sector: number): number;
|
||||
readRangeAsync(range: number): void;
|
||||
ready(): void;
|
||||
write(sector: number, buffer: Uint8Array): void;
|
||||
persist(): Promise<Uint8Array | null>;
|
||||
}
|
||||
export declare function sockdrive(url: string, _onNewRange: (range: number, buffer: Uint8Array) => void): Promise<Drive>;
|
||||
export {};
|
58
src/assets/scripts/lib/js-dos/wdosbox-x.js
Normal file
9390
src/assets/scripts/lib/js-dos/wdosbox-x.js.symbols
Normal file
BIN
src/assets/scripts/lib/js-dos/wdosbox-x.wasm
Executable file
58
src/assets/scripts/lib/js-dos/wdosbox.js
Normal file
3041
src/assets/scripts/lib/js-dos/wdosbox.js.symbols
Normal file
BIN
src/assets/scripts/lib/js-dos/wdosbox.wasm
Executable file
21
src/assets/scripts/lib/js-dos/wlibzip.js
Normal file
277
src/assets/scripts/lib/js-dos/wlibzip.js.symbols
Normal file
@ -0,0 +1,277 @@
|
||||
0:exit
|
||||
1:__wasi_fd_close
|
||||
2:__wasi_fd_write
|
||||
3:emsc_getMTimeMs
|
||||
4:__syscall_openat
|
||||
5:__syscall_fcntl64
|
||||
6:legalimport$_mktime_js
|
||||
7:legalimport$_localtime_js
|
||||
8:legalimport$__wasi_fd_seek
|
||||
9:emscripten_resize_heap
|
||||
10:emscripten_force_exit
|
||||
11:emscripten_exit_with_live_runtime
|
||||
12:emscripten_date_now
|
||||
13:emsc_progress
|
||||
14:_tzset_js
|
||||
15:_setitimer_js
|
||||
16:_emscripten_runtime_keepalive_clear
|
||||
17:_abort_js
|
||||
18:__wasi_proc_exit
|
||||
19:__wasi_fd_read
|
||||
20:__syscall_unlinkat
|
||||
21:__syscall_stat64
|
||||
22:__syscall_rmdir
|
||||
23:__syscall_renameat
|
||||
24:__syscall_newfstatat
|
||||
25:__syscall_mkdirat
|
||||
26:__syscall_lstat64
|
||||
27:__syscall_ioctl
|
||||
28:__syscall_getdents64
|
||||
29:__syscall_fstat64
|
||||
30:__syscall_chmod
|
||||
31:__call_sighandler
|
||||
32:zip_error_set
|
||||
33:emmalloc_free
|
||||
34:_zip_error_set_from_source
|
||||
35:emmalloc_memalign
|
||||
36:_zip_buffer_free
|
||||
37:crc32_z
|
||||
38:zip_source_free
|
||||
39:_zip_buffer_put_16
|
||||
40:_zip_buffer_get_16
|
||||
41:_zip_buffer_get
|
||||
42:strlen
|
||||
43:out
|
||||
44:pad
|
||||
45:fiprintf
|
||||
46:_zip_source_call
|
||||
47:_zip_buffer_put_32
|
||||
48:_tr_flush_block
|
||||
49:zip_source_seek
|
||||
50:_zip_string_free
|
||||
51:_zip_buffer_new
|
||||
52:_zip_buffer_get_32
|
||||
53:zip_strerror
|
||||
54:zip_error_init
|
||||
55:zip_source_read
|
||||
56:_zip_ef_free
|
||||
57:_zip_buffer_set_offset
|
||||
58:_zip_buffer_put_64
|
||||
59:adler32_z
|
||||
60:_zip_buffer_left
|
||||
61:_zip_buffer_get_64
|
||||
62:__syscall_ret
|
||||
63:zip_source_tell_write
|
||||
64:zip_source_stat
|
||||
65:zip_source_make_command_bitmap
|
||||
66:zip_source_close
|
||||
67:fwrite
|
||||
68:buffer_free
|
||||
69:_zip_write
|
||||
70:zip_stat_init
|
||||
71:strchr
|
||||
72:_zip_guess_encoding
|
||||
73:_zip_dirent_free
|
||||
74:_zip_buffer_offset
|
||||
75:__wasi_syscall_ret
|
||||
76:zip_error_to_data
|
||||
77:zip_error_fini
|
||||
78:strcmp
|
||||
79:fmt_u
|
||||
80:flush_pending
|
||||
81:fclose
|
||||
82:crc32
|
||||
83:_zip_buffer_put
|
||||
84:_zip_buffer_new_from_source
|
||||
85:__memcpy
|
||||
86:zip_close
|
||||
87:umask
|
||||
88:remove
|
||||
89:memcmp
|
||||
90:fflush
|
||||
91:emmalloc_realloc
|
||||
92:buffer_new
|
||||
93:_zip_string_get
|
||||
94:_zip_error_copy
|
||||
95:_zip_dirent_clone
|
||||
96:_zip_cdir_free
|
||||
97:_zip_buffer_eof
|
||||
98:_tr_flush_bits
|
||||
99:zip_source_tell
|
||||
100:zip_source_open
|
||||
101:tolower
|
||||
102:open
|
||||
103:hash_resize
|
||||
104:fill_window
|
||||
105:_zip_string_new
|
||||
106:_zip_string_length
|
||||
107:_zip_progress_update
|
||||
108:_zip_get_dirent
|
||||
109:_zip_ef_new
|
||||
110:_zip_dirent_write
|
||||
111:_zip_dirent_init
|
||||
112:_tr_stored_block
|
||||
113:zip_source_rollback_write
|
||||
114:zip_source_layered
|
||||
115:zip_source_keep
|
||||
116:zip_source_error
|
||||
117:zip_open
|
||||
118:vfiprintf
|
||||
119:strcpy
|
||||
120:stat
|
||||
121:siprintf
|
||||
122:memchr
|
||||
123:inflate_table
|
||||
124:hash_string
|
||||
125:fputc
|
||||
126:fopen
|
||||
127:decrypt
|
||||
128:close
|
||||
129:build_tree
|
||||
130:attempt_allocate
|
||||
131:abort
|
||||
132:_zip_unchange_data
|
||||
133:_zip_u2d_time
|
||||
134:_zip_read_data
|
||||
135:_zip_read
|
||||
136:_zip_get_name
|
||||
137:_zip_get_encryption_implementation
|
||||
138:_zip_fseek
|
||||
139:_zip_file_get_offset
|
||||
140:_zip_entry_finalize
|
||||
141:_zip_ef_get_by_id
|
||||
142:_zip_dirent_finalize
|
||||
143:_zip_checkcons
|
||||
144:_zip_allocate_new
|
||||
145:__towrite
|
||||
146:__strerror_l
|
||||
147:__memset
|
||||
148:__fwritex
|
||||
149:__ftello
|
||||
150:__fseeko_unlocked
|
||||
151:zipfile_to_fs
|
||||
152:zip_stat_index
|
||||
153:zip_source_seek_write
|
||||
154:zip_source_seek_compute_offset
|
||||
155:zip_source_layered_create
|
||||
156:zip_source_function_create
|
||||
157:zip_source_file_create
|
||||
158:zip_source_file
|
||||
159:zip_source_decompress
|
||||
160:zip_source_crc
|
||||
161:zip_source_buffer
|
||||
162:zip_set_file_compression
|
||||
163:zip_recursively
|
||||
164:zip_file_add
|
||||
165:zip_error_to_str
|
||||
166:zip_error_strerror
|
||||
167:zip_discard
|
||||
168:zError
|
||||
169:wctomb
|
||||
170:strdup
|
||||
171:snprintf
|
||||
172:send_tree
|
||||
173:safe_create_dir
|
||||
174:printf_core
|
||||
175:pop_arg
|
||||
176:longest_match
|
||||
177:init_block.llvm.13708832007047381696
|
||||
178:getint
|
||||
179:frexp
|
||||
180:fread
|
||||
181:ferror
|
||||
182:emmalloc_calloc
|
||||
183:deflate_stored
|
||||
184:deflateEnd
|
||||
185:context_free
|
||||
186:compression_source_new
|
||||
187:compress_block
|
||||
188:claim_more_memory
|
||||
189:chmod
|
||||
190:buffer_seek
|
||||
191:buffer_grow_fragments
|
||||
192:buffer_find_fragment
|
||||
193:allocate
|
||||
194:_zip_string_write
|
||||
195:_zip_string_equal
|
||||
196:_zip_string_crc32
|
||||
197:_zip_stat_merge
|
||||
198:_zip_source_zip_new
|
||||
199:_zip_source_window_new
|
||||
200:_zip_source_new
|
||||
201:_zip_read_string
|
||||
202:_zip_progress_end
|
||||
203:_zip_name_locate
|
||||
204:_zip_hash_delete
|
||||
205:_zip_hash_add
|
||||
206:_zip_fseek_u
|
||||
207:_zip_file_replace
|
||||
208:_zip_error_clear
|
||||
209:_zip_entry_init
|
||||
210:_zip_ef_write
|
||||
211:_zip_ef_utf8
|
||||
212:_zip_ef_size
|
||||
213:_zip_ef_remove_internal
|
||||
214:_zip_ef_parse
|
||||
215:_zip_ef_merge
|
||||
216:_zip_dirent_read
|
||||
217:_zip_dirent_process_ef_utf_8
|
||||
218:_zip_dirent_needs_zip64
|
||||
219:_zip_cdir_new
|
||||
220:_zip_cdir_grow
|
||||
221:_zip_buffer_put_8
|
||||
222:_zip_buffer_get_8
|
||||
223:__vfprintf_internal
|
||||
224:__tzset
|
||||
225:__time
|
||||
226:__overflow
|
||||
227:__ftello_unlocked
|
||||
228:__fstatat
|
||||
229:__fseeko
|
||||
230:__fdopen
|
||||
231:zipfile_add
|
||||
232:zip_to_fs
|
||||
233:zip_source_pkware
|
||||
234:zip_from_fs
|
||||
235:zcfree
|
||||
236:zcalloc
|
||||
237:window_read
|
||||
238:strcasecmp
|
||||
239:start
|
||||
240:sn_write
|
||||
241:read_file
|
||||
242:read_data
|
||||
243:process
|
||||
244:pop_arg_long_double
|
||||
245:pkware_decrypt
|
||||
246:main
|
||||
247:libzip_destroy
|
||||
248:input
|
||||
249:get_changes_mtime_ms
|
||||
250:fmt_fp
|
||||
251:end_of_input
|
||||
252:end
|
||||
253:emmalloc_malloc
|
||||
254:demangling_terminate_handler\28\29
|
||||
255:deflate_slow
|
||||
256:deflate_fast
|
||||
257:decompress_allocate
|
||||
258:deallocate
|
||||
259:crc_read
|
||||
260:compression_flags
|
||||
261:compress_callback
|
||||
262:compress_allocate
|
||||
263:action_terminate
|
||||
264:action_abort
|
||||
265:abort_message
|
||||
266:_emscripten_timeout
|
||||
267:_emscripten_tempret_set
|
||||
268:_emscripten_stack_alloc
|
||||
269:__wasm_call_ctors
|
||||
270:__stdio_write
|
||||
271:__stdio_seek
|
||||
272:__stdio_read
|
||||
273:__stdio_close
|
||||
274:__pthread_mutex_lock
|
||||
275:__funcs_on_exit
|
||||
276:__emscripten_stdout_seek
|
BIN
src/assets/scripts/lib/js-dos/wlibzip.wasm
Executable file
@ -2,11 +2,14 @@
|
||||
/****************************************************************************
|
||||
* It's Eric Woodward's Site
|
||||
*
|
||||
* Copyright 2014-2024 Eric Woodward
|
||||
* Copyright 2014-2025 Eric Woodward
|
||||
* Source released under CC0 Public Domain License v1.0
|
||||
* https://www.itsericwoodward.com/licenses/cc0/
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
****************************************************************************/
|
||||
import backgroundScroller from './backgroundScroller.js';
|
||||
import themeSwitcher from './themeSwitcher.js';
|
||||
|
||||
export default (() => {
|
||||
// we load this library via "module" to guarantee baseline ES6 functionality
|
||||
|
||||
@ -51,119 +54,9 @@ export default (() => {
|
||||
|
||||
actionBox.setAttribute("open", "true");
|
||||
|
||||
/** THEME SWITCHER */
|
||||
themeSwitcher(actionBox);
|
||||
|
||||
// load last theme
|
||||
const currentTheme = Cookies.get("currentTheme") ?? "";
|
||||
|
||||
const themeSwitch = document.createElement("div");
|
||||
themeSwitch.innerHTML = [
|
||||
'<label class="themeSwitch" for="themeSwitch">',
|
||||
'<div class="themeSwitch-description">',
|
||||
"Theme",
|
||||
"</div>",
|
||||
'<select id="themeSwitch" name="themeSwitch">',
|
||||
`<option value="" ${
|
||||
currentTheme === "" ? "selected" : ""
|
||||
}>Default</option>`,
|
||||
`<option value="themeAdmiral" ${
|
||||
currentTheme === "themeAdmiral" ? "selected" : ""
|
||||
}>Admiral</option>`,
|
||||
`<option value="themeAntsy92" ${
|
||||
currentTheme === "themeAntsy92" ? "selected" : ""
|
||||
}>Antsy92</option>`,
|
||||
`<option value="themeBingo" ${
|
||||
currentTheme === "themeBingo" ? "selected" : ""
|
||||
}>Bingo</option>`,
|
||||
`<option value="themeCyber77" ${
|
||||
currentTheme === "themeCyber77" ? "selected" : ""
|
||||
}>Cyber77</option>`,
|
||||
`<option value="themeLightCyan" ${
|
||||
currentTheme === "themeLightCyan" ? "selected" : ""
|
||||
}>LightCyan</option>`,
|
||||
`<option value="themeTerminalGreen" ${
|
||||
currentTheme === "themeTerminalGreen" ? "selected" : ""
|
||||
}>Terminal Green</option>`,
|
||||
`<option value="themeVagabond" ${
|
||||
currentTheme === "themeVagabond" ? "selected" : ""
|
||||
}>Vagabond</option>`,
|
||||
"</label>",
|
||||
].join("\n");
|
||||
themeSwitch.classList.add("js-themeSwitch", "themeSwitch");
|
||||
if (currentTheme)
|
||||
document
|
||||
.getElementsByTagName("body")[0]
|
||||
.classList.add(currentTheme);
|
||||
|
||||
actionBox.append(themeSwitch);
|
||||
|
||||
// add toggle event
|
||||
document
|
||||
.getElementById("themeSwitch")
|
||||
.addEventListener("change", function (e) {
|
||||
const body = document.getElementsByTagName("body")[0];
|
||||
body.className = body.className
|
||||
.split(/\s/)
|
||||
.filter((val) => !val.startsWith("theme"))
|
||||
.concat(e.target.value)
|
||||
.join(" ");
|
||||
Cookies.set("currentTheme", e.target.value);
|
||||
});
|
||||
|
||||
/** SCROLLING BACKGROUND */
|
||||
|
||||
// default to no scrolling on devices under 600 px w
|
||||
const isMobile = window.matchMedia(
|
||||
"only screen and (max-width: 600px)"
|
||||
).matches;
|
||||
|
||||
// add background scrolling
|
||||
const hasScrollToggle =
|
||||
Cookies.get("scrollToggle") === true ||
|
||||
Cookies.get("scrollToggle") === "true" ||
|
||||
(Cookies.get("scrollToggle") === undefined && !isMobile);
|
||||
|
||||
const scrollToggle = document.createElement("div");
|
||||
scrollToggle.innerHTML = [
|
||||
'<label class="toggleSwitch" for="scrollingToggle">',
|
||||
'<div class="toggleSwitch-description">',
|
||||
"Background",
|
||||
"</div>",
|
||||
`<input class="toggleSwitch-checkbox" ${
|
||||
hasScrollToggle ? "checked" : ""
|
||||
} type="checkbox" id="scrollingToggle" />`,
|
||||
'<div class="toggleSwitch-status" data-ts-on="SCROLLING" data-ts-off="STATIC"></div>',
|
||||
"</label>",
|
||||
].join("\n");
|
||||
scrollToggle.classList.add("js-scrollToggle", "scrollToggle");
|
||||
|
||||
actionBox.append(scrollToggle);
|
||||
actionBox.classList.add("js-actionBox");
|
||||
|
||||
const actionBoxTitle = document.createElement("summary");
|
||||
actionBoxTitle.innerHTML =
|
||||
"<h3 class='actionBox-title'>Settings</h3>";
|
||||
actionBox.append(actionBoxTitle);
|
||||
|
||||
// add toggle event
|
||||
document
|
||||
.getElementById("scrollingToggle")
|
||||
.addEventListener("click", function (e) {
|
||||
const theList =
|
||||
document.getElementById("gridContainer").classList;
|
||||
|
||||
theList.toggle("js-isAnimated");
|
||||
Cookies.set(
|
||||
"scrollToggle",
|
||||
!!theList.contains("js-isAnimated")
|
||||
);
|
||||
});
|
||||
|
||||
// add class if active at startup
|
||||
if (hasScrollToggle)
|
||||
document
|
||||
.getElementById("gridContainer")
|
||||
.classList.add("js-isAnimated");
|
||||
backgroundScroller(actionBox);
|
||||
|
||||
if (document.documentElement.className.indexOf("is404") > -1) {
|
||||
document.getElementById("searchQuery").value =
|
||||
|
76
src/assets/scripts/themeSwitcher.js
Normal file
@ -0,0 +1,76 @@
|
||||
// @license magnet:?xt=urn:btih:90dc5c0be029de84e523b9b3922520e79e0e6f08&dn=cc0.txt CC0-1.0
|
||||
/****************************************************************************
|
||||
* It's Eric Woodward's Site
|
||||
*
|
||||
* Copyright 2014-2025 Eric Woodward
|
||||
* Source released under CC0 Public Domain License v1.0
|
||||
* https://www.itsericwoodward.com/licenses/cc0/
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* Execute returned function to add theme switching
|
||||
*/
|
||||
export default (actionBox) => {
|
||||
if (!window.Cookies) return;
|
||||
|
||||
// load last theme
|
||||
const currentTheme = Cookies.get("currentTheme") ?? "";
|
||||
|
||||
const themeSwitch = document.createElement("div");
|
||||
themeSwitch.innerHTML = [
|
||||
'<label class="themeSwitch" for="themeSwitch">',
|
||||
'<div class="themeSwitch-description">',
|
||||
"Theme",
|
||||
"</div>",
|
||||
'<select id="themeSwitch" name="themeSwitch">',
|
||||
`<option value="" ${
|
||||
currentTheme === "" ? "selected" : ""
|
||||
}>Default</option>`,
|
||||
`<option value="themeAdmiral" ${
|
||||
currentTheme === "themeAdmiral" ? "selected" : ""
|
||||
}>Admiral</option>`,
|
||||
`<option value="themeAntsy92" ${
|
||||
currentTheme === "themeAntsy92" ? "selected" : ""
|
||||
}>Antsy92</option>`,
|
||||
`<option value="themeBingo" ${
|
||||
currentTheme === "themeBingo" ? "selected" : ""
|
||||
}>Bingo</option>`,
|
||||
`<option value="themeCyber77" ${
|
||||
currentTheme === "themeCyber77" ? "selected" : ""
|
||||
}>Cyber77</option>`,
|
||||
`<option value="themeLightCyan" ${
|
||||
currentTheme === "themeLightCyan" ? "selected" : ""
|
||||
}>LightCyan</option>`,
|
||||
`<option value="themeTerminalGreen" ${
|
||||
currentTheme === "themeTerminalGreen" ? "selected" : ""
|
||||
}>Terminal Green</option>`,
|
||||
`<option value="themeVagabond" ${
|
||||
currentTheme === "themeVagabond" ? "selected" : ""
|
||||
}>Vagabond</option>`,
|
||||
"</label>",
|
||||
].join("\n");
|
||||
|
||||
themeSwitch.classList.add("js-themeSwitch", "themeSwitch");
|
||||
|
||||
if (currentTheme)
|
||||
document
|
||||
.getElementsByTagName("body")[0]
|
||||
.classList.add(currentTheme);
|
||||
|
||||
actionBox.append(themeSwitch);
|
||||
|
||||
// add toggle event
|
||||
document
|
||||
.getElementById("themeSwitch")
|
||||
.addEventListener("change", function (e) {
|
||||
const body = document.getElementsByTagName("body")[0];
|
||||
body.className = body.className
|
||||
.split(/\s/)
|
||||
.filter((val) => !val.startsWith("theme"))
|
||||
.concat(e.target.value)
|
||||
.join(" ");
|
||||
Cookies.set("currentTheme", e.target.value);
|
||||
});
|
||||
}
|
||||
// @license-end
|
@ -662,6 +662,16 @@ samp {
|
||||
margin: 0.5em;
|
||||
}
|
||||
|
||||
.dosboxScreen {
|
||||
margin: 1rem 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.dosboxScreen > div > div > .relative > .flex {
|
||||
background-color: #000;
|
||||
padding: .5rem;
|
||||
}
|
||||
|
||||
.embed {
|
||||
display: block;
|
||||
margin: 1em auto;
|
||||
@ -1720,3 +1730,42 @@ samp {
|
||||
display: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* CHIM / JS-DOS Pages Only
|
||||
****************************************************************************/
|
||||
|
||||
#jsChimDb {
|
||||
width: 100%;
|
||||
height: 24em;
|
||||
}
|
||||
|
||||
#jsChimDb a {
|
||||
color: #049c74;
|
||||
}
|
||||
|
||||
#jsChimDb a:hover {
|
||||
color: #040308;
|
||||
}
|
||||
|
||||
#jsChimDb a:hover:visited {
|
||||
color: #040308;
|
||||
}
|
||||
|
||||
#jsChimDb a:visited {
|
||||
color: #1e6e58;
|
||||
}
|
||||
|
||||
#jsChimDb .dosbox-canvas {
|
||||
display: block;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.dosbox-overlay, .dosbox-loader {
|
||||
background-color: #111;
|
||||
background-color: rgba(3,3,3,.7);
|
||||
}
|
||||
|
||||
.dosbox-start {
|
||||
color: #049c74;
|
||||
}
|
||||
|
@ -12,7 +12,7 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta http-equiv="Content-Security-Policy"
|
||||
content="<%- site.csp %>" />
|
||||
content="<%- page.csp ? page.csp : site.csp %>" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
|
||||
<!-- LEARN MORE:
|
||||
@ -48,7 +48,7 @@
|
||||
<link rel="icon" type="image/png" sizes="192x192" href="/images/favicons/android-icon-192x192.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/images/favicons/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="96x96" href="/images/favicons/favicon-96x96.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/images/favicons/favicon-16x16.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/images/favicons/favicon.png">
|
||||
<link rel="manifest" href="/manifest.json">
|
||||
<meta name="msapplication-TileColor" content="#9aa8bc">
|
||||
<meta name="msapplication-TileImage" content="/images/favicons/ms-icon-144x144.png">
|
||||
|
@ -6,7 +6,9 @@ license: CC0
|
||||
section: games
|
||||
subsection: chim
|
||||
content_type: feature
|
||||
csp: "default-src 'self' data:; img-src 'self' https://*; media-src 'self' https://* data:; script-src 'self' 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; worker-src 'self' blob:;"
|
||||
---
|
||||
|
||||
<style type='text/css'>
|
||||
a code {
|
||||
background-color: transparent;
|
||||
@ -22,65 +24,37 @@ content_type: feature
|
||||
a:visited code {
|
||||
color: #1e6e58;
|
||||
}
|
||||
#jsChimDb a {
|
||||
color: #049c74;
|
||||
}
|
||||
#jsChimDb a:hover {
|
||||
color: #040308;
|
||||
}
|
||||
#jsChimDb a:hover:visited {
|
||||
color: #040308;
|
||||
}
|
||||
#jsChimDb a:visited {
|
||||
color: #1e6e58;
|
||||
}
|
||||
|
||||
#jsChimDb .dosbox-canvas {
|
||||
display: block;
|
||||
margin: auto;
|
||||
}
|
||||
.btnFullscreen {
|
||||
background-color: #111;
|
||||
background-color: rgba(3,3,3,.7);
|
||||
color: #049c74 !important;
|
||||
display: block;
|
||||
margin: .5em auto;
|
||||
padding: .5em;
|
||||
}
|
||||
.dosbox-overlay, .dosbox-loader {
|
||||
background-color: #111;
|
||||
background-color: rgba(3,3,3,.7);
|
||||
}
|
||||
.dosbox-start {
|
||||
color: #049c74;
|
||||
}
|
||||
</style>
|
||||
|
||||
In 1997, I released my first (and, so far, only) computer game, **Camp Happy Island Massacre**, a comedy-horror text game for the DOS operating system. Originally written while I was still in college, the game is about a cursed summer camp and the 3 surviving counselors who try to stop a horrific force before it claims them.
|
||||
|
||||
If you have a functional DOS machine (or an emulator, like [DOSBox](https://www.dosbox.com/)), you can download the game in a [ZIP file](/files/chim/chim.zip), which contains the following files:
|
||||
|
||||
+ [`CHIM.EXE`](/files/chim/chim.exe) *(the main executable file)*
|
||||
+ [`CHIM.FAQ`](/files/chim/chim.faq) *(list of frequently asked questions)*
|
||||
+ [`FILE_ID.DIZ`](/files/chim/file_id.diz) *(ZIP file descriptor)*
|
||||
+ [`INTRO.TXT`](/files/chim/intro.txt) *(the intro screen)*
|
||||
+ [`LICENSE.TXT`](/files/chim/license.txt) *(the distribution license)*
|
||||
+ [`MAP.TXT`](/files/chim/map.txt) *(a text map of the island)*
|
||||
- [`CHIM.EXE`](/files/chim/chim.exe) _(the main executable file)_
|
||||
- [`CHIM.FAQ`](/files/chim/chim.faq) _(list of frequently asked questions)_
|
||||
- [`FILE_ID.DIZ`](/files/chim/file_id.diz) _(ZIP file descriptor)_
|
||||
- [`INTRO.TXT`](/files/chim/intro.txt) _(the intro screen)_
|
||||
- [`LICENSE.TXT`](/files/chim/license.txt) _(the distribution license)_
|
||||
- [`MAP.TXT`](/files/chim/map.txt) _(a text map of the island)_
|
||||
|
||||
And now, thanks to [DOSBox](https://www.dosbox.com/), [Emscripten](http://emscripten.org/), and their unholy lovechild, [JS-DOS](https://js-dos.com/), you can play **Camp Happy Island Massacre** in your browser:
|
||||
|
||||
<div id="jsChimDb"></div>
|
||||
<button class="btnFullscreen" onclick="chim_db.requestFullScreen();">Open in Fullscreen</button>
|
||||
<div class="dosboxScreen" id="jsChimDb"></div>
|
||||
|
||||
<script type="text/javascript" src="./js-dos-api.js"></script>
|
||||
<script type="text/javascript">
|
||||
var chim_db = new Dosbox({
|
||||
id: "jsChimDb",
|
||||
onload: function (chim_db) {
|
||||
chim_db.run("/chim/chim-exe.zip", "./CHIM.EXE");
|
||||
},
|
||||
onrun: function (chim_db, app) {
|
||||
console.log("App '" + app + "' is running!");
|
||||
}
|
||||
<!-- js-dos style sheet -->
|
||||
<link rel="stylesheet" href="/scripts/lib/js-dos/js-dos.css">
|
||||
<link rel="stylesheet" href="/styles/imports.css" type="text/css" />
|
||||
<link rel="stylesheet" href="/styles/fonts.css" type="text/css" />
|
||||
<link rel="stylesheet" href="/styles/styles.css" type="text/css" />
|
||||
|
||||
<!-- js-dos -->
|
||||
<script src="/scripts/lib/js-dos/js-dos.js"></script>
|
||||
|
||||
<script>
|
||||
Dos(document.getElementById("jsChimDb"), {
|
||||
pathPrefix: '/scripts/lib/js-dos/',
|
||||
theme: 'dark',
|
||||
thinSidebar: true,
|
||||
url: "./chim.jsdos",
|
||||
});
|
||||
</script>
|
||||
|