Successfully running PCx86 and PC8080 machines on the same page now

This commit is contained in:
Jeff Parsons 2016-08-18 10:29:24 -07:00
commit f0509bc5d1
30 changed files with 2773 additions and 3118 deletions

View file

@ -6,7 +6,7 @@ one of several JavaScript Machines in the [PCjs Project](https://github.com/jeff
includes:
* [PCx86](/docs/pcx86/), an x86-based IBM PC and PC-compatible emulator
* [PC8080](/modules/pc8080/), a 8080-based machine emulator (e.g., [Space Invaders](/devices/pc8080/machine/invaders/), [VT100 Terminal](/devices/pc8080/machine/vt100/))
* [PC8080](/modules/pc8080/), an 8080-based machine emulator (e.g., [Space Invaders](/devices/pc8080/machine/invaders/), [VT100 Terminal](/devices/pc8080/machine/vt100/))
* [C1Pjs](/docs/c1pjs/), a 6502-based emulation of the Ohio Scientific [Challenger 1P](/devices/c1p/)
All PCjs computer simulations are written entirely in [JavaScript](/modules/). No Flash, Java or other plugins are

View file

@ -1,6 +1,6 @@
---
layout: page
title: IBM PC AT (Model 5170, 2Mb20Mb Hard Disk) with EGA Display and Debugger
title: IBM PC AT (Model 5170, 2Mb, 20Mb Hard Disk) with EGA Display and Debugger
permalink: /devices/pcx86/machine/5170/ega/2048kb/rev3/debugger/
redirect_from:
- /devices/pc/machine/5170/ega/2048kb/rev3/debugger/

View file

@ -0,0 +1,17 @@
---
layout: page
title: IBM PC AT (Model 5170, 2Mb, 20Mb Hard Disk) with EGA Display and VT100 Debugger
permalink: /devices/pcx86/machine/5170/ega/2048kb/rev3/debugger/vt100/
machines:
- id: ibm5170
type: pcx86
debugger: true
- id: vt100
type: pc8080
debugger: true
config: /devices/pc8080/machine/vt100/machine.xml
---
{% include machine.html id="ibm5170" %}
{% include machine.html id="vt100" %}

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/versions/pcx86/1.24.0/machine.xsl"?>
<machine id="ibm5170" class="pcx86" border="1" pos="center" background="#FAEBD7">
<name>IBM PC AT (8Mhz), 128Kb EGA, 2Mb RAM, 20Mb Hard Disk</name>
<computer id="at-ega-2048k" name="IBM PC AT" buswidth="24"/>
<cpu id="cpu286" model="80286" cycles="8000000" autostart="true"/>
<ram id="ramLow" addr="0x00000" test="false" size="0xa0000" comment="ROM BIOS memory test has been disabled"/>
<ram id="ramExt" addr="0x100000" size="0x160000" comment=""/>
<rom id="romBIOS" addr="0xf0000" size="0x10000" alias="0xff0000" file="/devices/pcx86/rom/5170/1985-11-15/ATBIOS-REV3.json"/>
<video ref="/devices/pcx86/video/ibm/ega/1984-09-13/128kb-lockfs.xml"/>
<fdc ref="/disks/pcx86/compiled/library.xml" automount='{A:{name:"PC-DOS 3.30 (Disk 1)",path:"/disks/pcx86/dos/ibm/3.30/PCDOS330-DISK1.json"}, B:{name:"PC-DOS 3.30 (Disk 2)",path:"/disks/pcx86/dos/ibm/3.30/PCDOS330-DISK2.json"}}'/>
<keyboard ref="/devices/pcx86/keyboard/us84-buttons-arrows.xml"/>
<debugger id="debugger" messages="fault" commands=""/>
<panel ref="/devices/pcx86/panel/wide.xml"/>
<hdc ref="/disks/pcx86/fixed/20mb/pcdos330-empty.xml"/>
<chipset id="chipset" model="5170" floppies="[1440,1200]"/>
<serial id="com1" adapter="1"/>
<serial id="com2" adapter="2" binding="print" tabsize="8" charbol="9"/>
<mouse serial="com1"/>
</machine>

View file

@ -12,11 +12,11 @@ function Ea(a){var b;if(window)try{b=window.localStorage.getItem(a)}catch(c){}re
function Ia(a,b,c,d){var e=null;b="data:application/"+b+(c?";base64":"")+",";b=Ga("Firefox")?b+(c?a:encodeURIComponent(a)):b+(c?a:encodeURI(a));d&&(e=document.createElement("a"),"string"!=typeof e.download&&(e=null));e?(e.href=b,e.download=d,document.body.appendChild(e),e.click(),document.body.removeChild(e),a="Check your Downloads folder for "+d+"."):(window.open(b),a="Check your browser for a new window/tab containing the requested data"+(d?" ("+d+")":"")+".");return a}
function Ja(a,b,c){function d(){--a;0<=a&&(b()||(a=0));0<a?setTimeout(d,0):c()}d()}function Ka(a,b){function c(){b(100===d)&&(e=setTimeout(c,d),d=100)}var d=0,e=null,f=!1;a.onmousedown=function(){f||e||(d=500,c())};a.ontouchstart=function(){e||(d=500,c())};a.onmouseup=a.onmouseout=function(){e&&(clearTimeout(e),e=null)};a.ontouchend=a.ontouchcancel=function(){e&&(clearTimeout(e),e=null);f=!0}}var La={init:[],show:[],exit:[]},Ma=!1,Na=!0;
function Pa(a,b){if(window){var c=window[a];window[a]="function"!==typeof c?b:function(){c&&c();b()}}}function Qa(a){La.init.push(a)}function Ra(a){if(Na)try{for(var b=0;b<a.length;b++)a[b]()}catch(c){w(""+("An unexpected exception occurred:\n\n"+c.message+"\n\nPlease send this information to support@pcjs.org. Thanks."))}}function Sa(a){!Na&&a?(Na=!0,Ma&&Ta("init")):Na=a}function Ta(a){La[a]&&Ra(La[a])}Pa("onload",function(){Ma=!0;Ra(La.init)});Pa("onpageshow",function(){Ra(La.show)});
Pa(Ga("Opera")||Ga("iOS")?"onunload":"onbeforeunload",function(){Ra(La.exit)});function Ua(a,b,c,d){this.type=a;b||(b={id:"",name:""});this.id=b.id;this.name=b.name;this.uk=b.comment;this.hk=b;void 0===this.id&&(this.id="");b=this.id.indexOf(".");0<b?(this.ve=this.id.substr(0,b),this.Rd=this.id.substr(b+1)):this.Rd=this.id;this[a]=c;this.la={bf:!1,bd:!1,bh:!1,cc:!1,ud:!1};this.tg=null;this.la.ud=!1;this.qa={};this.ha=null;this.wc=d||0;Va.push(this)}var Wa=void 0,Ya={};
Pa(Ga("Opera")||Ga("iOS")?"onunload":"onbeforeunload",function(){Ra(La.exit)});function Ua(a,b,c,d){this.type=a;b||(b={id:"",name:""});this.id=b.id||"";this.name=b.name;this.uk=b.comment;this.hk=b;b=this.id.indexOf(".");0>b?this.Rd=this.id:(this.ve=this.id.substr(0,b),this.Rd=this.id.substr(b+1));this[a]=c;this.la={bf:!1,bd:!1,bh:!1,cc:!1,ud:!1};this.tg=null;this.la.ud=!1;this.qa={};this.ha=null;this.wc=d||0;Va.push(this)}var Wa=void 0,Ya={};
if(window){Wa||(Wa=window.location.search.substr(1));for(var Za,$a=/\+/g,ab=/([^&=]+)=?([^&]*)/g;Za=ab.exec(Wa);)Ya[decodeURIComponent(Za[1].replace($a," "))]=decodeURIComponent(Za[2].replace($a," "))}function cb(a){function b(){}if(window){if(!a)throw new TypeError;if(Object.create)return Object.create(a);var c=typeof a;if("object"!==c&&"function"!==c)throw new TypeError;}b.prototype=a;return new b}
function db(a,b){b||(b=Ua);a.prototype=cb(b.prototype);a.prototype.constructor=a;a.prototype.parent=b.prototype}var Va=[],eb={};function fb(a,b,c){eb[a]&&b&&(eb[a][b]=c)}function gb(a){var b,c=[];a&&(a=0<(b=a.indexOf("."))?a.substr(0,b+1):"");for(b=0;b<Va.length;b++){var d=Va[b];a&&d.id.indexOf(a)||c.push(d)}return c}function hb(a,b){if(void 0!==a){var c;b&&0<(c=b.indexOf("."))&&(a=b.substr(0,c+1)+a);for(c=0;c<Va.length;c++)if(Va[c].id===a)return Va[c]}return null}
function ib(a,b){var c;if(void 0!==a){var d;b&&(b=0<(d=b.indexOf("."))?b.substr(0,d+1):"");for(d=0;d<Va.length;d++)if(c)c==Va[d]&&(c=null);else if(!(a!=Va[d].type||b&&Va[d].id.indexOf(b)))return Va[d]}return null}function jb(a){var b=null;if(a=a.getAttribute("data-value"))try{b=eval("("+a+")")}catch(c){w(c.message+" ("+a+")")}return b}function kb(a,b,c){var d;b&&(void 0===d&&(d="Panel"),(d=ib(d,a.id))&&(b=d.qa[b])&&a.Pb(null,c,b))}
function mb(a,b){for(var c=nb(b.parentNode,"pcx86-control"),d=0;d<c.length;d++)for(var e=c[d].childNodes,f=0;f<e.length;f++){var g=e[f];if(1===g.nodeType){var h=g.getAttribute("class");if(h)for(var k=h.split(" "),l=0;l<k.length;l++)switch(h=k[l],h){case "pcx86-binding":(h=jb(g))&&h.binding&&a.Pb(h.type,h.binding,g,h.value),l=k.length}}}}
function db(a,b){b||(b=Ua);a.prototype=cb(b.prototype);a.prototype.constructor=a;a.prototype.parent=b.prototype}if(window){window.PCjs||(window.PCjs={Machines:{},Components:[]});var eb=window.PCjs.Machines,Va=window.PCjs.Components}else eb={},Va=[];function fb(a,b,c){eb[a]&&b&&(eb[a][b]=c)}function gb(a){var b,c=[];a&&(a=0<(b=a.indexOf("."))?a.substr(0,b+1):"");for(b=0;b<Va.length;b++){var d=Va[b];a&&d.id.indexOf(a)||c.push(d)}return c}
function hb(a,b){if(void 0!==a){var c;b&&0<(c=b.indexOf("."))&&(a=b.substr(0,c+1)+a);for(c=0;c<Va.length;c++)if(Va[c].id===a)return Va[c]}return null}function ib(a,b){var c;if(void 0!==a){var d;b&&(b=0<(d=b.indexOf("."))?b.substr(0,d+1):"");for(d=0;d<Va.length;d++)if(c)c==Va[d]&&(c=null);else if(!(a!=Va[d].type||b&&Va[d].id.indexOf(b)))return Va[d]}return null}function jb(a){var b=null;if(a=a.getAttribute("data-value"))try{b=eval("("+a+")")}catch(c){w(c.message+" ("+a+")")}return b}
function kb(a,b,c){var d;b&&(void 0===d&&(d="Panel"),(d=ib(d,a.id))&&(b=d.qa[b])&&a.Pb(null,c,b))}function mb(a,b){for(var c=nb(b.parentNode,"pcx86-control"),d=0;d<c.length;d++)for(var e=c[d].childNodes,f=0;f<e.length;f++){var g=e[f];if(1===g.nodeType){var h=g.getAttribute("class");if(h)for(var k=h.split(" "),l=0;l<k.length;l++)switch(h=k[l],h){case "pcx86-binding":(h=jb(g))&&h.binding&&a.Pb(h.type,h.binding,g,h.value),l=k.length}}}}
function nb(a,b,c){c&&(b+="-"+c+"-object");if(a.getElementsByClassName)return a.getElementsByClassName(b);var d;c=[];a=a.getElementsByTagName("*");var e=new RegExp("(^| )"+b+"( |$)");b=0;for(d=a.length;b<d;b++)e.test(a[b].className)&&c.push(a[b]);return c}
Ua.prototype={constructor:Ua,parent:null,toString:function(){return this.name?this.name:this.id||this.type},Pb:function(a,b,c){switch(b){case "clear":return this.qa[b]||(this.qa[b]=c,c.onclick=function(a){return function(){a.qa.print&&(a.qa.print.value="")}}(this)),!0;case "print":return this.qa[b]||(this.Ef=this.qa[b]=c,c.value="",this.O=function(a){return function(b,c){8192<a.value.length&&(a.value=a.value.substr(a.value.length-4096));a.value+=(void 0!==c?c+": ":"")+(b||"")+"\n";a.scrollTop=a.scrollHeight}}(c),
this.Na=function(a){this.O(a,this.Rd)}),!0;default:return!1}},log:function(){},O:function(){},status:function(a){this.O(this.Rd+": "+a)},Na:function(a,b,c){c=c||this.type;b||w((c?c+": ":"")+a)},ic:function(){return this.la.cc=!0},hc:function(a,b){b&&(this.la.cc=!1);return!0}};function x(a,b,c,d,e,f,g){a.ha&&(!0===g?g=0:null==g&&(g=a.wc),ob(a.ha,a,b,c,d,e,f,g))}function y(a,b,c,d){a.ha&&(!0===c||A(a,c|0))&&a.ha.message(b,d)}
@ -35,7 +35,7 @@ rj:25,oj:20,qj:28,Oj:13,Qj:21,Nj:16,Pj:24,tj:13,vj:21,sj:16,uj:24,Tf:2,Sf:7,Qh:5
80:"set current PSP @BX",81:"get current PSP (bx)",82:"get system variables (ES:BX)",83:"translate BPB @DS:@SI to DPB (ES:BP)",84:"get verify flag (AL)",85:"create child PSP at segment @DX",86:"rename file $@DS:@DX to $@ES:@DI",87:"get(0)/set(1) file @BX date @DX and time @CX (@AL)",88:"get(0)/set(1) memory allocation strategy (@AL)",89:"get extended error information",90:"create temporary file $@DS:@DX with attributes @CX",91:"create file $@DS:@DX with attributes @CX",92:"lock(0)/unlock(1) file @BX region @CX:@DX length @SI:@DI (@AL)",
93:"critical error information (@AL)",96:"get fully-qualified filename from $@DS:@SI",99:"get lead byte table (@AL)",108:"extended open file $@DS:@SI"},65:{79:"check debugger loaded"}};function zb(a){Ua.call(this,"Panel",a,zb);this.L=this.W=this.fa=-1}db(zb);function Ab(a,b,c,d){this.A=[a,b,c,d];this.B=null;void 0===a&&(this.A[0]=256*Math.random()|0,this.A[1]=256*Math.random()|0,this.A[2]=256*Math.random()|0,this.A[3]=255,this.B=null)}
Ab.prototype.toString=function(){this.B||(this.B="#"+r(this.A[0],2)+r(this.A[1],2)+r(this.A[2],2));return this.B};function Bb(a,b,c,d){this.x=a;this.y=b;this.ad=c;this.A=d}Bb.prototype.contains=function(a,b){return a>=this.x&&a<this.x+this.ad&&b>=this.y&&b<this.y+this.A};function Cb(a,b,c,d){void 0===d&&(d=b>=c>>2);d?(b=new Bb(a.x,a.y,a.ad,a.A*b/c|0),a.y+=b.A,a.A-=b.A):(b=new Bb(a.x,a.y,a.ad*b/c|0,a.A),a.x+=b.ad,a.ad-=b.ad);return b}m=zb.prototype;
m.Pb=function(a,b,c,d){return this.V&&this.V.Pb(a,b,c,d)||this.F&&this.F.Pb(a,b,c,d)||this.B&&this.B.Pb(a,b,c,d)||this.ha&&this.ha.Pb(a,b,c,d)?!0:this.parent.Pb.call(this,a,b,c,d)};m.Ic=function(a,b,c,d){this.V=a;this.ea=b;this.F=c;this.ha=d;this.B=Eb(a,"Keyboard")};m.ic=function(a,b){b||Fb();return!0};m.hc=function(){return!0};m.je=function(a,b){a.button||(this.fa=b?0:-1,Gb(this,a,b))};m.If=function(a){Gb(this,a)};
m.Pb=function(a,b,c,d){return this.V&&this.V.Pb(a,b,c,d)||this.F&&this.F.Pb(a,b,c,d)||this.B&&this.B.Pb(a,b,c,d)||this.ha&&this.ha.Pb(a,b,c,d)?!0:this.parent.Pb.call(this,a,b,c,d)};m.Ic=function(a,b,c,d){this.V=a;this.ea=b;this.F=c;this.ha=d;this.B=Db(a,"Keyboard")};m.ic=function(a,b){b||Fb();return!0};m.hc=function(){return!0};m.je=function(a,b){a.button||(this.fa=b?0:-1,Gb(this,a,b))};m.If=function(a){Gb(this,a)};
function Gb(a,b,c){var d=1280/null.offsetWidth,e=720/null.offsetHeight,f=null.getBoundingClientRect(),d=(b.clientX-f.left)*d|0;b=(b.clientY-f.top)*e|0;null==c&&(a.fa||(a.fa=Math.abs(a.L-d)>Math.abs(a.W-b)?1:2),1==a.fa?b=a.W:2==a.fa&&(d=a.L));a.L=d;a.W=b;if(0<=d&&1280>d&&0<=b&&720>b){a:{c=d;if(960>c&&a.A&&a.A.Qe)for(f=0;f<a.A.Qe.length;f++)if(e=a.A.Qe[f],e.contains(c,b)){c-=e.x;b-=e.y;var d=a.A.Bf[f],g=ta(Hb.ak,a.A.Sg[d.Rk]),f=g*a.ea.Sb,d=(g+d.Vd)*a.ea.Sb-1;0<b&&(f+=e.ad*(b-1)*a.ya);f+=c*a.ya;f|=0;
f>d&&(f=d);c=f;break a}c=-1}if(-1!==c&&(c&=-16,c!=a.Ca)){b=c;if(a.context&&a.ia&&a.ka){e=a.ia.width;a.ka.fillStyle="black";a.ka.fillRect(0,360,e,360);Ib(a,378,a.ia,a.ka);a.pa=a.Ea.width/24|0;if(null==b)Jb(a,"Mouse over memory to dump");else for(Jb(a,"0x"+r(b),null,0,1),f=1;16>=f;f++){d="";for(g=1;8>=g;g++){var h;h=a.ea;var k=b++;h=h.sa[(k&h.Hb)>>>h.La].se(k&h.A,k);Jb(a,r(h,2),null,1);d+=32<=h&&128>h?String.fromCharCode(h):"."}Jb(a,d,null,0,1)}a.context.drawImage(a.ia,0,360,e,360,a.rb,a.Db,a.Pa,a.cb)}a.Ca=
c}}}m.qd=function(){};function Kb(a,b,c,d){a.A.Bf[a.A.Bi++]={Rk:b,Vd:c,type:d};return sa(Hb,b,c,0,d)}function Ib(a,b,c,d){var e,f=null.style.color,g=a.Oa=10;a.C=g;a.U=b;a.X=a.wa=18;e||(e=a.ua||a.wa+"px Monaco, Lucida Console, Courier New");a.ga=a.ua=e;c&&(a.Ea=c);d&&(a.N=d,a.Fa=f||"white")}
@ -68,7 +68,7 @@ function Gc(a,b){b?0===--a.Ve&&(a.sc=a.N?a.L:a.xf,a.zf=a.N?a.X:a.pi,a.yf=a.N?a.U
function Zb(a,b,c){b||(b=5==a.type?Hc:6==a.type?Ic:Jc);zc(a,b,c);Bc(a,b,c)}var Jc=[],ec=[B.prototype.Fa,B.prototype.sb,B.prototype.$a,B.prototype.Rd,B.prototype.Dd,B.prototype.Xc],Ac=[B.prototype.Ea,B.prototype.rb,B.prototype.Pa,B.prototype.tc,B.prototype.td,B.prototype.Wc],Ic=[B.prototype.Ja,B.prototype.Jb,B.prototype.fb,B.prototype.Cc,B.prototype.Hd,B.prototype.ve],Hc=[B.prototype.Ka,B.prototype.Ub,B.prototype.gb,B.prototype.Uc,B.prototype.Id,B.prototype.kd];
if(vb)var dc=[B.prototype.Ca,B.prototype.Tb,B.prototype.Oa,B.prototype.bc,B.prototype.rd,B.prototype.Vc],cc=[B.prototype.aa,B.prototype.pa,B.prototype.ga,B.prototype.ra,B.prototype.ya,B.prototype.wa],Kc=[B.prototype.Ia,B.prototype.Db,B.prototype.cb,B.prototype.uc,B.prototype.Gd,B.prototype.jd];
function Lc(a,b){Ua.call(this,"CPU",a,Lc,1);var c=a.cycles||b,d=a.multiplier||1;this.Y={};this.Y.Jd=c;this.Y.Zd=d;this.Y.vg=Math.round(this.Y.Jd/1E4)/100;this.Y.Fe=this.Y.vg*this.Y.Zd;this.la.Fb=!1;this.la.fh=!1;this.la.Li=a.autoStart;this.la.Pi=!1;this.la.Ze=!1;this.Y.Jf=this.Y.lf=0;this.Y.Kf=a.csStart;this.Y.kf=a.csInterval;this.Y.mf=a.csStop;this.ri=this.Le.bind(this);rb(this)}db(Lc);var Mc=["power","reset"];m=Lc.prototype;
m.Ic=function(a,b,c,d){this.V=a;this.ea=b;this.ha=d;for(b=0;b<Mc.length;b++)(c=this.qa[Mc[b]])&&this.V.Pb(null,Mc[b],c);this.Tb=Eb(a,"FPU");this.N=Eb(a,"ChipSet");a=Nc(a,"autoStart");null!=a&&(this.la.Li="true"==a?!0:"false"==a?!1:!!a);rb(this)};m.reset=function(){};m.save=function(){return null};m.restore=function(){return!1};
m.Ic=function(a,b,c,d){this.V=a;this.ea=b;this.ha=d;for(b=0;b<Mc.length;b++)(c=this.qa[Mc[b]])&&this.V.Pb(null,Mc[b],c);this.Tb=Db(a,"FPU");this.N=Db(a,"ChipSet");a=Nc(a,"autoStart");null!=a&&(this.la.Li="true"==a?!0:"false"==a?!1:!!a);rb(this)};m.reset=function(){};m.save=function(){return null};m.restore=function(){return!1};
m.ic=function(a,b){if(!b){if(a&&this.restore){Oc(this);if(!this.restore(a))return!1;Pc(this)}else this.reset();this.ha?this.ha.ih():this.O("No debugger detected")}Rc(this);return!0};m.hc=function(a){return a?this.save():!0};function Uc(a){(a.la.Li||!a.ha&&void 0===a.qa.run)&&a.Le(!0)}m.Ri=function(){return 0};function Pc(a){void 0===a.Y.Kf&&(a.Y.Kf=0);void 0===a.Y.kf&&(a.Y.kf=-1);void 0===a.Y.mf&&(a.Y.mf=-1);a.la.Ze=0<=a.Y.Kf&&0<a.Y.kf;a.la.Ze&&(a.Y.Jf=0,a.Y.lf=a.Y.Kf-a.uc)}
function Vc(a,b){if(a.la.Ze){var c=!1;a.Y.Jf=a.Y.Jf+a.Ri()|0;a.Y.lf-=b;0>=a.Y.lf&&(a.Y.lf+=a.Y.kf,c=!0);0<=a.Y.mf&&a.Y.mf<=Wc(a)&&(a.Y.kf=a.Y.mf=-1,Pc(a),a.Wb(),c=!0);c&&a.O(Wc(a)+" cycles: checksum="+r(a.Y.Jf))}}
m.Pb=function(a,b,c){var d=this;a=!1;switch(b){case "power":case "reset":this.qa[b]=c;a=!0;break;case "run":this.qa[b]=c;c.onclick=function(){var a;if(a=d.V)if(a=d.V,a.la.cc)a=!0;else{var b=null,c,h=gb(a.id);for(c=0;c<h.length&&(b=h[c],b===a||b.la.bf);c++);if(c==h.length)for(c=0;c<h.length&&(b=h[c],b===a||b.la.cc);c++);c==h.length&&(b=a);w("The "+b.type+" component ("+b.id+") is not "+(b.la.bf?"powered yet":"ready yet"+(b.tg?" (waiting for notification)":""))+".");a=!1}a&&(d.la.Fb?d.Wb(!0):d.Le(!0))};
@ -95,7 +95,7 @@ d.oa(h+g)));c&&d.jb(h+0,f);d.Za|=8;return!0}m.save=function(){return[this.Z,this
function ed(a,b,c,d){void 0===c&&(c=!!(a.F.Za&1));a.cd=!1;if(c)if(a.load=a.ug,a.Xi=a.gm,a.mc=a.Di,a.nc=a.Fi,void 0===d&&(d=!!(a.F.ca&131072)),d)a.load=a.V,a.mc=a.ea,a.nc=a.qa,a.Lb=a.Gc=3,a.ba=a.Oc=2,a.R=a.Ba=65535,a.Ta=65535,a.Zb=a.Ta+1,a.Oc=a.ba,a.Xb=-1,a.df=!1;else{if(!(a.Z&-4))a.mc=a.pg,a.nc=a.qg;else if(a.type&4096){6144==(a.type&6656)&&(a.mc=a.pg);if(a.type&2048||!(a.type&512))a.nc=a.qg;1024==(a.type&3072)&&(a.mc==a.Di&&(a.mc=a.Jk),a.nc==a.Fi&&(a.nc=a.Kk),a.cd=!0);b&&6>a.id&&a.Z&-4&&-1!==a.Xb&&
(c=a.Xb+5,d=a.F.Qa(c),d&1||a.F.qc(c,d|1))}b&&(a.Lb=a.Z&3,a.Gc=(a.wb&24576)>>13,80386>a.F.ja||!(a.ext&64)?(a.ba=2,a.R=65535):(a.ba=4,a.R=-1),a.Oc=a.ba,a.Ba=a.R)}else a.load=a.mh,a.Xi=a.hm,a.mc=a.Ei,a.nc=a.Gi,a.Lb=a.Gc=0,a.Xb=-1,a.df=!1}
function Ad(a){this.ja=+a.model||8088;var b=a.stepping;this.Uc=this.ja+(b?ca(b,16):0);b=0;switch(this.ja){default:b=4772727;break;case 80286:b=6E6;break;case 80386:b=16E6}Lc.call(this,a,b);this.Zf=61442;this.Cc=1792;this.Xf=28672;this.Dd=4;this.ra=255;this.B=80286<=this.ja?xb:wb;this.X=Bd;this.cg=Cd;this.hg=Dd;this.ig=Ed;if(80186<=this.ja&&(this.X=Bd.slice(),this.cg=Cd.slice(),this.hg=Dd.slice(),this.ra=31,this.X[15]=Fd,this.X[96]=Gd,this.X[97]=Hd,this.X[98]=Id,this.X[99]=Fd,this.X[100]=Fd,this.X[101]=
Fd,this.X[102]=Fd,this.X[103]=Fd,this.X[104]=Jd,this.X[105]=Kd,this.X[106]=Ld,this.X[107]=Md,this.X[108]=Nd,this.X[109]=Od,this.X[110]=Pd,this.X[111]=Qd,this.X[192]=Rd,this.X[193]=Sd,this.X[200]=Td,this.X[201]=Xd,this.X[241]=Yd,this.cg[7]=Zd,this.hg[7]=Zd,80286<=this.ja)){this.Zf=2;this.Cc|=28672;this.Dd=0;this.X[15]=$d;this.tc=fe.slice();for(a=0;a<this.tc.length;a++)this.tc[a]||(this.tc[a]=ge);this.X[84]=he;this.X[99]=ie;if(80386<=this.ja){var c;this.Xf=0;this.Cc|=196608;this.X[100]=je;this.X[101]=
Fd,this.X[102]=Fd,this.X[103]=Fd,this.X[104]=Jd,this.X[105]=Kd,this.X[106]=Ld,this.X[107]=Md,this.X[108]=Nd,this.X[109]=Od,this.X[110]=Pd,this.X[111]=Qd,this.X[192]=Rd,this.X[193]=Sd,this.X[200]=Td,this.X[201]=Ud,this.X[241]=Yd,this.cg[7]=Zd,this.hg[7]=Zd,80286<=this.ja)){this.Zf=2;this.Cc|=28672;this.Dd=0;this.X[15]=$d;this.tc=ae.slice();for(a=0;a<this.tc.length;a++)this.tc[a]||(this.tc[a]=ge);this.X[84]=he;this.X[99]=ie;if(80386<=this.ja){var c;this.Xf=0;this.Cc|=196608;this.X[100]=je;this.X[101]=
ke;this.X[102]=le;this.X[103]=me;for(c in M)this.tc[+c]=M[c];80546<=this.Uc&&80562>=this.Uc&&(this.tc[166]=ne,this.tc[167]=oe)}}this.Id=[];this.le=[];this.ne=0;Oc(this);this.la.Xd=this.la.Ni=!1;this.Qg=0;this.ld=this.sa=[];this.La=this.Sb=this.Fa=this.Gd=this.jd=this.Hb=this.Db=0;pe(this)}db(Ad,Lc);function qe(a,b,c,d){Gc((d?a.ld:a.sa)[b>>>a.La],c);d&&Ub(a)}
function re(a){var b;if(a.sa===a.ld){a.sa=Array(a.Gd);a.me=new B(null,0,0,5,null,a);Mb(a.me,a.ha);for(b=0;b<a.Gd;b++)a.sa[b]=a.me;a.kd=new B;a.bg=Array(512);a.oe=0}else for(var c=0;c<a.Hd.length;c++){b=a.Hd[c];var d=a.sa[b];512>a.oe&&(a.bg[a.oe++]=d);a.sa[b]=a.me}a.Hd=[]}function Ub(a){a.Za&-2147483648&&re(a)}
function Fc(a,b,c,d){var e=(b&-4194304)>>>20,f=a.ld[(a.Pd+e&a.Hb)>>>a.La],g=f.Nd(e);if(!(g&1))return d||se.call(a,b,!1,c),a.kd;if(!(g&4)&&3==a.pa)return d||se.call(a,b,!0,c),a.kd;var h=(b&4190208)>>>10,g=a.ld[((g&-4096)+h&a.Hb)>>>a.La],k=g.Nd(h);if(!(k&1))return d||se.call(a,b,!1,c),a.kd;if(!(k&4)&&3==a.pa)return d||se.call(a,b,!0,c),a.kd;c=a.ld[((k&-4096)+(b&4095)&a.Hb)>>>a.La];if(d)return c;d=b>>>a.La;k=a.sa[d];b=b&-4096;var l;0<a.oe?(l=a.bg[--a.oe],l.ih(b)):l=new B(b,0,0,6);b=l;b.Cd=c;b.yb=f;b.A=
@ -133,7 +133,7 @@ m.qd=function(a){this.Qg&&(a||!this.la.Fb||this.la.Pi)&&(Sf(this,"EAX",this.G),S
m.wf=function(a){this.la.Xd=!0;var b=this.la.Ni=this.ha&&Tf(this.ha),c=a?this.la.fh?0:1:-1;this.la.fh=!1;this.fb=this.A=a;this.N&&!a&&ad(this.N);a||A(this,1024)||(this.S|=4);do{var d=this.S&3312;if(d)this.Ha|=d;else if(this.re=this.Ga,this.ka=this.vb,this.Ka=this.ta,this.D=this.C=-1,this.Ha&3072&&Se(this),this.Ha=this.S&256,this.ua){a:{if(!(this.S&4))for(var d=80286>this.ja?0:1,e=0;2>e;e++){switch(d){case 0:if(this.ua&1&&this.ca&512){var f=Uf(this.N);if(-1<=f&&(this.ua&=-2,0<=f)){this.ua&=-5;Vf.call(this,
f);d=!0;break a}}break;case 1:if(this.ua&2){this.ua&=-3;80386<=this.ja&&(this.Ja[6]|=16384);Vf.call(this,1);d=!0;break a}}d=1-d}d=!1}if(d&&!a){this.O("interrupt dispatched");this.S=0;break}if(this.ua&4){this.S=this.A=0;break}}if(b){if(Wf(this.ha,this.Ga,c)){this.Wb();break}c=1}this.S=0;this.X[this.xa()].call(this)}while(0<this.A);return this.la.Xd?this.fb-this.A:void 0===this.la.Xd?0:-1};Qa(function(){for(var a=nb(document,"pcx86","cpu"),b=0;b<a.length;b++){var c=a[b],d=jb(c),d=new Ad(d);mb(d,c)}});
function Xf(a){Ua.call(this,"FPU",a,Xf);this.ja=a.model||8087;(a=a.stepping)&&ca(a,16);this.V=new Float64Array(8);this.aa=new Int32Array(this.V.buffer);this.pa=new Float32Array(1);this.ua=new Int32Array(this.pa.buffer);this.X=new Float64Array(1);this.L=new Int32Array(this.X.buffer);this.ea=Array(3);this.fa=this.ga=-1;this.W=this.U=this.ia=this.A=0;this.ka=new Float64Array(1);this.ra=new Int32Array(this.ka.buffer);this.ra[0]=0;this.ra[1]=268402688;Yf(this)}db(Xf);m=Xf.prototype;
m.Ic=function(a,b,c){this.F=c;this.N=Eb(a,"ChipSet");rb(this)};m.ic=function(a,b){if(!b)if(!a||!this.restore)Yf(this);else if(!this.restore(a))return!1;return!0};m.hc=function(a){return a?this.save():!0};m.save=function(){var a=new hf(this),b=[],c=0;b[c++]=this.jc;b[c++]=Zf(this);b[c++]=$f(this);for(var d=0;d<this.V.length;d++)b[c++]=this.V[d];N(a,0,b);return a.data()};
m.Ic=function(a,b,c){this.F=c;this.N=Db(a,"ChipSet");rb(this)};m.ic=function(a,b){if(!b)if(!a||!this.restore)Yf(this);else if(!this.restore(a))return!1;return!0};m.hc=function(a){return a?this.save():!0};m.save=function(){var a=new hf(this),b=[],c=0;b[c++]=this.jc;b[c++]=Zf(this);b[c++]=$f(this);for(var d=0;d<this.V.length;d++)b[c++]=this.V[d];N(a,0,b);return a.data()};
m.restore=function(a){a=a[0];var b=0;this.jc=a[b++]&-57409;var c=a[b++];this.ma=c&-14337;this.B=(c&14336)>>11;ag(this);bg(this,a[b++]);for(c=0;c<this.V.length;c++)this.V[c]=a[b++];return!0};function Yf(a){a.C=0;a.jc=959;a.ma=0;a.B=0;a.N&&(a=a.N,a.ja>=cg&&dg(a,13))}function ag(a){a.ma&=-129;a.ma&~a.jc&63&&(a.ma|=128);if(a.ma&128&&!(a.jc&128))return a=a.N,a.ja>=cg?eg(a,13):a.ya&0||Vf.call(a.F,2),!0;a=a.N;a.ja>=cg&&dg(a,13);return!1}function fg(a,b){80387<=a.ja||(b&=-65);a.ma|=b;return ag(a)}
function Zf(a){return a.ma|a.B<<11}function gg(a,b){return isFinite(b)?!0:!fg(a,Infinity===b?8:16)}function hg(a,b,c){var d=null;null!=b&&null!=c&&(d=b+c,gg(a,d)||(d=null));return d}function ig(a,b,c){var d=null;null!=b&&null!=c&&(d=b-c,gg(a,d)||(d=null));return d}function jg(a,b,c){var d=null;null!=b&&null!=c&&(d=b*c,gg(a,d)||(d=null));return d}function kg(a,b,c){var d=null;null==b||null==c||!c&&fg(a,2)||(d=b/c,gg(a,d)||(d=null));return d}
function lg(a,b,c){if(null!=b&&null!=c){var d=0;isNaN(b)||isNaN(c)?d=17664:(b-=c,0>b?d=256:0===b&&(d=16384));a.ma=a.ma&-18177|d;return!0}return!1}function mg(a,b,c){if(null==b)return null;var d=a.jc&3072;0==d?(d=Math.round(b),.5===d-b&&d%2&&d--):d=1024==d||3072==d&&0<b?Math.floor(b):Math.ceil(b);if(c){if(d>=c){if(fg(a,1))return null;d=-c}else if(d<-c){if(fg(a,1))return null;d=-c}a.L[0]=d|0;2147483648<c&&(a.L[1]=d/4294967296|0,!a.L[1]&&0>d&&(a.L[1]=-1))}return d}
@ -288,7 +288,7 @@ function Ij(){var a=this.T();pf(this)||sf(this)?(O(this,K(this)+a),this.A-=this.
function Nj(){var a=this.T();qf(this)?this.A-=this.B.bb:(O(this,K(this)+a),this.A-=this.B.ab)}function Oj(){var a=this.T();!tf(this)!=!uf(this)?(O(this,K(this)+a),this.A-=this.B.ab):this.A-=this.B.bb}function Pj(){var a=this.T();!tf(this)==!uf(this)?(O(this,K(this)+a),this.A-=this.B.ab):this.A-=this.B.bb}function Qj(){var a=this.T();sf(this)||!tf(this)!=!uf(this)?(O(this,K(this)+a),this.A-=this.B.ab):this.A-=this.B.bb}
function Rj(){var a=this.T();sf(this)||!tf(this)!=!uf(this)?this.A-=this.B.bb:(O(this,K(this)+a),this.A-=this.B.ab)}function Sj(){this.Jb.call(this,Tj,this.xa);this.A-=-1===this.C?1:this.B.Eg}function Uj(){this.S|=1;this.$a.call(this,bi)}function Vj(){this.S|=1;this.fa.call(this,bi)}function Wj(){this.Oa.call(this,bi)}function Xj(){this.W.call(this,bi)}function Rd(){this.Jb.call(this,Yj,tj)}function Sd(){this.ya.call(this,2==this.ba?Zj:ak,tj)}
function bk(){var a=Rf(this),b=D(this);O(this,b);a&&G(this,I(this)+a);this.A-=this.B.Yj}function ck(){var a=D(this);O(this,a);this.A-=this.B.Vj}function Td(){this.U=this.ga;var a=Rf(this),b=this.xa()&31;this.A-=11;J(this,this.P);var c=I(this)&this.R;if(0<b){for(this.A-=(b<<2)+(1<b?1:0);--b;)this.P=this.P&~this.R|this.P-this.ba&this.R,J(this,nd(this,this.ta,this.P&this.R));J(this,c)}this.P=this.P&~this.R|c;G(this,I(this)&~this.ta.Ba|I(this)-a&this.ta.Ba);this.U=-1}
function Xd(){this.U=this.ga;G(this,I(this)&~this.ta.Ba|this.P&this.ta.Ba);this.P=this.P&~this.R|D(this)&this.R;this.A-=5;this.U=-1}function dk(){yj.call(this,Rf(this));this.A-=this.B.Xj}function ek(){yj.call(this,0);this.A-=this.B.Wj}function fk(a){this.jg=a;this.W.call(this,Lh)}function gk(){this.S|=36;this.A-=this.B.od}function Yd(){ge.call(this)}function Fd(){C.call(this,6)}
function Ud(){this.U=this.ga;G(this,I(this)&~this.ta.Ba|this.P&this.ta.Ba);this.P=this.P&~this.R|D(this)&this.R;this.A-=5;this.U=-1}function dk(){yj.call(this,Rf(this));this.A-=this.B.Xj}function ek(){yj.call(this,0);this.A-=this.B.Wj}function fk(a){this.jg=a;this.W.call(this,Lh)}function gk(){this.S|=36;this.A-=this.B.od}function Yd(){ge.call(this)}function Fd(){C.call(this,6)}
function ge(){O(this,this.re-this.va.Aa);ub(this,"Undefined opcode "+t(this.Qa(this.Ga))+" at "+("0x"+r(this.Ga)));this.Wb()}
var Bd=[function(){this.$a.call(this,th)},function(){this.fa.call(this,uh)},function(){this.Oa.call(this,th)},function(){this.W.call(this,uh)},function(){this.G=this.G&-256|th.call(this,this.G&255,this.xa());this.A--},function(){this.G=this.G&~this.R|uh.call(this,this.G&this.R,this.Ma());this.A--},function(){od(this,this.Xa.Z,this.ba,2);this.A-=this.B.Ie},function(){this.U=this.ga;vd(this,D(this));this.A-=this.B.zc;this.U=-1},function(){this.$a.call(this,gi)},function(){this.fa.call(this,hi)},function(){this.Oa.call(this,
gi)},function(){this.W.call(this,hi)},function(){this.G=this.G&-256|gi.call(this,this.G&255,this.xa());this.A--},function(){this.G=this.G&~this.R|hi.call(this,this.G&this.R,this.Ma());this.A--},function(){od(this,this.va.Z,this.ba,2);this.A-=this.B.Ie},function(){kf(this,D(this));this.A-=this.B.zc},function(){this.$a.call(this,rh)},function(){this.fa.call(this,sh)},function(){this.Oa.call(this,rh)},function(){this.W.call(this,sh)},function(){this.G=this.G&-256|rh.call(this,this.G&255,this.xa());this.A--},
@ -338,9 +338,9 @@ a,this.G),c=this.wa!=this.ia>>31);c?(wf(this),yf(this)):(xf(this),zf(this));this
a;var c=a<<16>>16,d=(b=this.M<<16|this.G&65535)/c|0;if(d!=d<<16>>16||8086==this.ja&&-32768==d)return Aj.call(this),a;this.ia=d&65535;this.wa=b%c&65535}else{var c=this.G,d=this.M,e=a,f=0,g=0;0>e&&(e=-e|0,f=1-f);0>d&&(c=-c|0,d=~d+(c?0:1)|0,g=1,f=1-f);!nj.call(this,c,d,e)||this.ia>2147483647+f||this.wa>2147483647+g?c=!1:(f&&(this.ia=-this.ia),g&&(this.wa=-this.wa),c=!0);if(!c)return Aj.call(this),a;this.ia|=0;this.wa|=0}this.cb=!0;this.A-=-1===this.D?this.B.rj:this.B.qj;this.S|=2;return a}],Cd=[function(a){var b=
a+1|0;of(this,a,1,b,190);this.A-=-1===this.D?this.B.Rf:this.B.Qf;return b&255},function(a){var b=a-1|0;of(this,a,1,b,190,!0);this.A-=-1===this.D?this.B.Rf:this.B.Qf;return b&255},Nh,Nh,Nh,Nh,Nh,Nh],Dd=[function(a){var b=a+1|0;of(this,a,1,b,this.Ia|62);this.A-=-1===this.D?this.B.Rf:this.B.Qf;return b&this.R},function(a){var b=a-1|0;of(this,a,1,b,this.Ia|62,!0);this.A-=-1===this.D?this.B.Rf:this.B.Qf;return b&this.R},function(a){J(this,K(this));O(this,a);this.A-=-1===this.D?this.B.jj:this.B.ij;this.S|=
2;return a},function(a){if(-1===this.D)return Nh.call(this,a);this.U=this.ga;wj.call(this,a,this.na(this.D+this.ba));this.A-=this.B.gj;this.S|=2;this.U=-1;return a},function(a){O(this,a);this.A-=-1===this.D?this.B.Ej:this.B.Dj;this.S|=2;return a},function(a){if(-1===this.D)return Nh.call(this,a);yd(this,a,this.na(this.D+this.ba));this.A-=this.B.Bj;this.S|=2;return a},function(a){var b=a;this.S&512&&(a=a-2&65535,80286>this.ja&&(b=a));J(this,b);this.A-=-1===this.D?this.B.Sc:this.B.Uj;this.S|=2;return a},
Nh];function ne(){this.W.call(this,gj);this.A-=-1===this.D?6:13}function oe(){this.fa.call(this,fj);this.A-=-1===this.D?12:19}var fe=Array(256);fe[0]=function(){16>(this.Qa(this.Ga)&56)&&(this.S|=1);this.ya.call(this,this.ig,uj)};fe[1]=function(){this.Qa(this.Ga)&16||(this.S|=1);this.ya.call(this,nk,uj)};fe[2]=function(){!(this.Za&1)||this.ca&131072?C.call(this,6):this.W.call(this,Uh)};fe[3]=function(){!(this.Za&1)||this.ca&131072?C.call(this,6):this.W.call(this,$h)};
fe[5]=function(){this.pa?C.call(this,13,0,0,!0):(Gf(this,this.na(2054)),this.J=this.na(2086),this.K=this.na(2088),this.P=this.na(2090),this.H=this.na(2094),this.M=this.na(2096),this.I=this.na(2098),this.G=this.na(2100),id(this.Xa,2102,this.na(2084)),id(this.va,2108,this.na(2082)),id(this.ta,2114,this.na(2080)),id(this.vb,2120,this.na(2078)),xd(this,this.na(2072)),O(this,this.na(2074)),G(this,this.na(2092)),this.Ec=this.na(2126)|this.Qa(2128)<<16,this.Ad=this.Ec+this.na(2130),this.Mc=this.na(2138)|
this.Qa(2140)<<16,this.Ud=this.Mc+this.na(2142),id(this.Bc,2132,this.na(2076)),id(this.Sa,2144,this.na(2070)),this.A-=195)};fe[6]=function(){this.pa?C.call(this,13,0):(this.Za&=-9,this.A-=2)};fe[11]=Fd;fe[166]=Fd;fe[255]=Fd;var M=[];M[5]=Fd;
Nh];function ne(){this.W.call(this,gj);this.A-=-1===this.D?6:13}function oe(){this.fa.call(this,fj);this.A-=-1===this.D?12:19}var ae=Array(256);ae[0]=function(){16>(this.Qa(this.Ga)&56)&&(this.S|=1);this.ya.call(this,this.ig,uj)};ae[1]=function(){this.Qa(this.Ga)&16||(this.S|=1);this.ya.call(this,nk,uj)};ae[2]=function(){!(this.Za&1)||this.ca&131072?C.call(this,6):this.W.call(this,Uh)};ae[3]=function(){!(this.Za&1)||this.ca&131072?C.call(this,6):this.W.call(this,$h)};
ae[5]=function(){this.pa?C.call(this,13,0,0,!0):(Gf(this,this.na(2054)),this.J=this.na(2086),this.K=this.na(2088),this.P=this.na(2090),this.H=this.na(2094),this.M=this.na(2096),this.I=this.na(2098),this.G=this.na(2100),id(this.Xa,2102,this.na(2084)),id(this.va,2108,this.na(2082)),id(this.ta,2114,this.na(2080)),id(this.vb,2120,this.na(2078)),xd(this,this.na(2072)),O(this,this.na(2074)),G(this,this.na(2092)),this.Ec=this.na(2126)|this.Qa(2128)<<16,this.Ad=this.Ec+this.na(2130),this.Mc=this.na(2138)|
this.Qa(2140)<<16,this.Ud=this.Mc+this.na(2142),id(this.Bc,2132,this.na(2076)),id(this.Sa,2144,this.na(2070)),this.A-=195)};ae[6]=function(){this.pa?C.call(this,13,0):(this.Za&=-9,this.A-=2)};ae[11]=Fd;ae[166]=Fd;ae[255]=Fd;var M=[];M[5]=Fd;
M[7]=function(){if(this.pa)C.call(this,13,0,0,!0);else{var a=this.Xa.mc(this.J&this.Ba,204);if(-1!==a){pj.call(this,this.oa(a));var b=this.oa(a+168),c=(b&24576)>>13;xd(this,this.oa(a+4),c);this.Ec=this.oa(a+112);this.Ad=this.Ec+this.oa(a+116);this.Mc=this.oa(a+100);this.Ud=this.Mc+this.oa(a+104);hd(this.Bc,this.oa(a+56),this.oa(a+120),this.oa(a+124),this.oa(a+128));hd(this.Sa,this.oa(a+52),this.oa(a+84),this.oa(a+88),this.oa(a+92));this.J=this.oa(a+12);this.K=this.oa(a+16);this.P=this.oa(a+20);this.H=
this.oa(a+28);this.M=this.oa(a+32);this.I=this.oa(a+36);this.G=this.oa(a+40);hd(this.Ob,this.oa(a+60),this.oa(a+132),this.oa(a+136),this.oa(a+140));hd(this.Nb,this.oa(a+64),this.oa(a+144),this.oa(a+148),this.oa(a+152));hd(this.vb,this.oa(a+68),this.oa(a+156),this.oa(a+160),this.oa(a+164));hd(this.ta,this.oa(a+72),b,this.oa(a+172),this.oa(a+176));hd(this.va,this.oa(a+76),this.oa(a+180),this.oa(a+184),this.oa(a+188));hd(this.Xa,this.oa(a+80),this.oa(a+192),this.oa(a+196),this.oa(a+200));O(this,this.oa(a+
8));G(this,this.oa(a+24))}this.A-=122<<(a&3?1:0)}};M[16]=Uj;M[17]=Vj;M[18]=Wj;M[19]=Xj;M[32]=function(){if(this.pa)C.call(this,13,0);else{var a,b=this.xa();switch((b&56)>>3){case 0:a=this.Za;break;case 2:a=this.te;break;case 3:a=this.Pd;break;default:ge.call(this);return}ve(this,b&7,a);this.A-=6}};M[33]=function(){if(this.pa)C.call(this,13,0);else{var a=this.xa(),b=(a&56)>>3;4==b||5==b?ge.call(this):(ve(this,a&7,this.Ja[b]),this.A-=22)}};
@ -367,7 +367,7 @@ window.webkitAudioContext),this.sb&&(this.Fa=new this.sb));this.reset(!0);rb(thi
Ak[5150][0][wk]={Lc:48,hd:{0:0,1:16,2:32,3:48,none:0,tv:16,color:32,cga:32,mda:48,mono:48,ega:0,vga:0},Qd:"Monitor Type"};Ak[5150][0][5]={Lc:12,hd:{16:0,32:4,48:8,64:12},Qd:"Base Memory (16Kb Increments)"};Ak[5150][1][6]={Lc:31,hd:{0:0,32:1,64:2,96:3,128:4,160:5,192:6,224:7,256:8,288:9,320:10,352:11,384:12,416:13,448:14,480:15,512:16,544:17,576:18},Qd:"Expansion Memory (32Kb Increments)"};Ak[5160]=[{},{}];Ak[5160][0][vk]=Ak[5150][0][vk];Ak[5160][0][3]=Ak[5150][0][3];Ak[5160][0][wk]=Ak[5150][0][wk];
Ak[5160][0][5]={Lc:12,hd:{64:0,128:4,192:8,256:12},Qd:"Base Memory (64Kb Increments)"};Ak[5160][1][6]=Ak[5150][1][6];Ak[5160.101]=[{},{}];Ak[5160.101][0][5]={Lc:143,hd:{128:1,256:130,512:8,640:141},Qd:"Base Memory (128Kb Increments)"};Ak[5160.101][0][3]={Lc:16,hd:{0:0,1:16},Qd:"Coprocessor"};Ak[5160.101][1][2]={Lc:1,hd:{0:0,1:1},Qd:"Floppy Type"};Ak[5160.101][1][vk]=Ak[5150][0][vk];Ak[5160.101][1][wk]=Ak[5150][0][wk];m=pk.prototype;
m.Pb=function(a,b,c){switch(b){case tk:return this.qa[b]=c,Bk(this,0,b),!0;case xk:if(5150==(this.ja|0)||5160.101==this.ja)return this.qa[b]=c,Bk(this,1,b),!0;break;case "swdesc":return this.qa[b]=c,!0}return!1};
m.Ic=function(a,b,c,d){this.ea=b;this.F=c;this.ha=d;this.V=a;this.Tb=Eb(a,"FPU");uk(this,3,this.Tb?1:0,!0);this.B=Eb(a,"Keyboard");this.gb=c.Y.Jd/1193181;ic(b,this,Ck);mc(b,this,Dk);this.ja<cg?5160.101!=this.ja?(ic(b,this,Ek),mc(b,this,Fk)):(ic(b,this,Gk),mc(b,this,Hk)):(ic(b,this,Ik),mc(b,this,Jk),5180==(this.ja|0)&&(ic(b,this,Kk),mc(b,this,Lk)));if(d){var e=this;Mk(d,1024,function(){for(var a=0;a<e.vc.length;a++){for(var b=e.vc[a],c="PIC"+a+":",d=0;d<b.Yc.length;d++)c+=" IC"+(d+1)+"="+t(b.Yc[d]);
m.Ic=function(a,b,c,d){this.ea=b;this.F=c;this.ha=d;this.V=a;this.Tb=Db(a,"FPU");uk(this,3,this.Tb?1:0,!0);this.B=Db(a,"Keyboard");this.gb=c.Y.Jd/1193181;ic(b,this,Ck);mc(b,this,Dk);this.ja<cg?5160.101!=this.ja?(ic(b,this,Ek),mc(b,this,Fk)):(ic(b,this,Gk),mc(b,this,Hk)):(ic(b,this,Ik),mc(b,this,Jk),5180==(this.ja|0)&&(ic(b,this,Kk),mc(b,this,Lk)));if(d){var e=this;Mk(d,1024,function(){for(var a=0;a<e.vc.length;a++){for(var b=e.vc[a],c="PIC"+a+":",d=0;d<b.Yc.length;d++)c+=" IC"+(d+1)+"="+t(b.Yc[d]);
c+=" IMR="+t(b.Bd)+" IRR="+t(b.lc)+" ISR="+t(b.Pc)+" DELAY="+b.of;e.ha.O(c)}});Mk(d,2048,function(a){a=(a=a[0])?+a:null;for(var b=0;b<e.W.length;b++)if(null==a||b==a){Nk(e,b);var c=e.W[b],d="TIMER"+b+":",l=0;if(null!=c.nd)for(var n=0;n<=c.nd;n++)l|=c.Ab[n]<<8*n;d+=" mode="+(c.mode>>1)+" bytes="+c.nd+" count="+u(l);e.ha.O(d)}});Mk(d,4096,function(){for(var a="",b=0;64>b;b++){var c=13>=b?Ok(e,b):e.A[b];a&&(a+="\n");a+="CMOS["+t(b)+"]: "+t(c)}e.ha.O(a)})}Te(c,26,this.bm.bind(this))};
m.ic=function(a,b){if(!b)if(!a)this.reset();else if(!this.restore(a))return!1;return!0};m.hc=function(a){return a?this.save():!0};
m.reset=function(a){var b;Pk(this);this.L=Array(this.cb);for(b=0;b<this.cb;b++)Qk(this,b);this.vc=Array(this.Ea);Rk(this,0,32);1<this.Ea&&Rk(this,1,160);this.Pa=this.Oa=null;this.W=Array(5180==(this.ja|0)?6:3);for(b=0;b<this.W.length;b++)Sk(this,b);this.Ca=this.rb=this.X=this.$a=null;this.ya=0;5160.101==this.ja&&(this.wa=0);if(this.ja>=cg){this.N=16;this.fa=0;this.aa=16;this.Ja=0;this.ga=160;512<=Tk(this)&&(this.ga|=16);3==+Uk(this,wk,void 0)&&(this.ga|=64);5180==(this.ja|0)&&(this.ga|=12);this.Ka=
@ -431,7 +431,7 @@ Zl.prototype.ic=function(){this.Sd&&(this.ha&&bm(this.ha,this.id,0,this.V>>>4,0,
function $l(a,b,c,d){if(d)a.Na("Unable to load system ROM (error "+d+": "+b+")");else{fb(a.ve,b,c);if("["==c.charAt(0)||"{"==c.charAt(0))try{var e=eval("("+c+")"),f=e.bytes,g=e.data;if(f)a.A=f;else if(g)for(a.A=Array(4*g.length),d=c=0;c<g.length;c++)a.A[d++]=g[c]&255,a.A[d++]=g[c]>>8&255,a.A[d++]=g[c]>>16&255,a.A[d++]=g[c]>>24&255;else a.A=e;a.Sd=e.symbols;if(!a.A.length){w("Empty ROM: "+b);return}if(1==a.A.length){w(a.A[0]);return}}catch(h){a.Na("ROM data error: "+h.message);return}else for(b=c.replace(/\n/gm,
" ").replace(/ +$/,"").split(" "),a.A=Array(b.length),e=0;e<b.length;e++)a.A[e]=ca(b[e],16);am(a)}}
function am(a){if(!sb(a))if(!a.L)rb(a);else if(a.A&&a.ea){a.C||(a.C=a.A.length);if(a.A.length!=a.C)ub(a,"ROM size (0x"+r(a.A.length)+") does not match specified size ("+("0x"+r(a.C))+")");else{var b;b=a.V;if(Sb(a.ea,b,a.C,ac)){for(var c=0;c<a.A.length;c++){var d=a.ea,e=b+c;d.sa[(e&d.Hb)>>>d.La].xf(e&d.A,a.A[c]&255,e)}b=!0}else b=!1;if(b){b=[];"number"==typeof a.N?b.push(a.N):null!=a.N&&a.N.length&&(b=a.N);for(c=0;c<b.length;c++){var d=a,e=b[c],f=Yb(d.ea,d.V,d.C);Xb(d.ea,e,d.C,f)}a.B&&((b=hb(a.B,a.id))?
(c=a.A,d=a.W,5==b.Ua?cm(b,c,d||[12640,8752],8):b.Ua==dm&&cm(b,c,d||[14221,16269],8),rb(b)):a.Na("Unable to find component: "+a.B));delete a.A}}rb(a)}}Qa(function(){for(var a=nb(document,"pcx86","rom"),b=0;b<a.length;b++){var c=a[b],d=jb(c),d=new Zl(d);mb(d,c)}});function em(a){Ua.call(this,"RAM",a,em);this.B=a.addr;this.A=a.size;this.L=a.test;this.V=!!this.A;this.C=!1}db(em);m=em.prototype;m.Ic=function(a,b,c,d){this.ea=b;this.F=c;this.ha=d;this.N=Eb(a,"ChipSet");rb(this)};
(c=a.A,d=a.W,5==b.Ua?cm(b,c,d||[12640,8752],8):b.Ua==dm&&cm(b,c,d||[14221,16269],8),rb(b)):a.Na("Unable to find component: "+a.B));delete a.A}}rb(a)}}Qa(function(){for(var a=nb(document,"pcx86","rom"),b=0;b<a.length;b++){var c=a[b],d=jb(c),d=new Zl(d);mb(d,c)}});function em(a){Ua.call(this,"RAM",a,em);this.B=a.addr;this.A=a.size;this.L=a.test;this.V=!!this.A;this.C=!1}db(em);m=em.prototype;m.Ic=function(a,b,c,d){this.ea=b;this.F=c;this.ha=d;this.N=Db(a,"ChipSet");rb(this)};
m.ic=function(a,b){return!b&&(this.reset(),a&&this.controller&&!this.restore(a))?!1:!0};m.hc=function(a){return a&&this.controller?this.save():!0};
m.reset=function(){if(!this.B&&!this.V&&this.N){var a=1024*Tk(this.N);this.A&&a!=this.A&&($b(this.ea,this.B,this.A),this.C=!1);this.A=a}!this.C&&this.A&&Sb(this.ea,this.B,this.A,1)&&(this.C=!0,"ramCPQ"==this.Rd&&(this.controller=new fm(this),Sb(this.ea,gm,4,4,this.controller)));if(this.C){if(this.L||gc(this.ea,1138,4660),"ramCPQ"!=this.Rd&&this.N&&(a=this.N,a.A)){var b=1048576>this.B?21:23,c=a.A[b]|a.A[b+1]<<8,c=c+(this.A>>10);a.A[b]=c&255;a.A[b+1]=c>>8;Xk(a)}}else w("No RAM allocated")};
m.save=function(){var a=new hf(this);this.controller&&N(a,0,this.controller.save());return a.data()};m.restore=function(a){return this.controller?this.controller.restore(a[0]):!0};function fm(a){this.N=a;this.C=hm;this.ha=im;this.B=jm;this.A=null}var gm=-2134900736,hm=65535,im=2575,jm=2,km=[null,0],lm=[function(a){return this.controller.Qa(a)},null,null,function(a,b){this.controller.qc(a,b)},null,null];m=fm.prototype;m.save=function(){return[this.C,this.B]};
@ -448,7 +448,7 @@ Y[107]=37;Y[75]=10789;Y[108]=38;Y[76]=10790;Y[X[";"]]=39;Y[X[":"]]=10791;Y[X["'"
Y[1115]=62;Y[1116]=63;Y[1117]=64;Y[1118]=65;Y[1119]=66;Y[1120]=67;Y[1121]=68;Y[1144]=69;Y[1145]=70;Y[1036]=71;Y[1038]=72;Y[1033]=73;Y[1109]=74;Y[1037]=75;Y[1101]=76;Y[1039]=77;Y[1107]=78;Y[1035]=79;Y[1040]=80;Y[1034]=81;Y[1045]=82;Y[1046]=83;Y[4027]=84;Y[1122]=87;Y[1123]=88;Y[1091]=91;Y[1093]=93;Y[1224]=91;Y[4003]=7470;Y[4008]=7494;Y[4046]=3677523;Y[4045]=3677522;Y[4013]=3677468;m=mm.prototype;
m.Pb=function(a,b,c,d){var e=this,f=a+"-"+b;if(void 0===this.qa[f])switch(b){case "kbd":return c.onkeydown=function(a){return vm(e,a,!0)},c.onkeypress=function(a){a=a||window.event;a=a.which||a.keyCode;e.L="";var b=!Y[a]||!!(e.xc&128);b||wm(e,a,!0);return b},c.onkeyup=function(a){return vm(e,a,!1)},!0;case "caps-lock":return this.qa[f]=c,c.onclick=function(){e.V&&e.V.yd();wm(e,1020,!0)},!0;case "num-lock":return this.qa[f]=c,c.onclick=function(){e.V&&e.V.yd();wm(e,1144,!0)},!0;case "scroll-lock":return this.qa[f]=
c,c.onclick=function(){e.V&&e.V.yd();wm(e,1145,!0)},!0;default:var g=b.toUpperCase().replace(/-/g,"_");if(void 0!==sm[g]&&"button"==a)return this.qa[f]=c,c.onclick=function(a,b,c){return function(){a.V&&a.V.yd();xm(a,c,!0);wm(a,c,!0)}}(this,g,sm[g]),!0;if(void 0!==tm[b])return this.ga++,this.qa[f]=c,a=function(a,b,c){return function(){wm(a,c)}}(this,b,tm[b]),b=function(a,b,c){return function(){ym(a,c)}}(this,b,tm[b]),"ontouchstart"in window?(c.ontouchstart=a,c.ontouchend=b):(c.onmousedown=a,c.onmouseup=
c.onmouseout=b),!0;if(d)return this.qa[f]=c,c.onclick=function(){e.V&&e.V.yd();d&&!e.L&&(e.L=d,zm(e,300))},!0}return!1};function Am(a,b,c){if(a.ga){for(var d in qm)if(b==qm[d]){b=+d;(d=pm[d])&&(b=d);break}for(var e in tm)if((d=tm[e]==b)||(d=b,97<=d&&122>=d&&(d-=32),d=tm[e]==d),d){(a=a.qa["key-"+e])&&void 0!==c&&(a.style.color=c?"#ffffff":"#000000",a.style.backgroundColor=c?"#000000":"#ffffff");break}}}m.Ic=function(a,b,c,d){this.V=a;this.ea=b;this.F=c;this.ha=d;this.N=Eb(a,"ChipSet")};
c.onmouseout=b),!0;if(d)return this.qa[f]=c,c.onclick=function(){e.V&&e.V.yd();d&&!e.L&&(e.L=d,zm(e,300))},!0}return!1};function Am(a,b,c){if(a.ga){for(var d in qm)if(b==qm[d]){b=+d;(d=pm[d])&&(b=d);break}for(var e in tm)if((d=tm[e]==b)||(d=b,97<=d&&122>=d&&(d-=32),d=tm[e]==d),d){(a=a.qa["key-"+e])&&void 0!==c&&(a.style.color=c?"#ffffff":"#000000",a.style.backgroundColor=c?"#000000":"#ffffff");break}}}m.Ic=function(a,b,c,d){this.V=a;this.ea=b;this.F=c;this.ha=d;this.N=Db(a,"ChipSet")};
function nm(a,b){var c=0;a.ja=null;"string"==typeof b&&(a.ja=b.toUpperCase(),c=om.indexOf(a.ja),0>c&&(c=0));if(b=om[c])a.ra=parseInt(b.substr(2),10)}function Tl(a){y(a,"keyboard reset",65792);a.A=[];Ul(a,170)}function Pl(a,b,c){a.aa!==c&&(a.aa=a.fa=c)&&(a.U=!0);a.X!==b&&(a.X=b)&&!a.fa&&Xl(a,!0);a.X&&a.fa&&(Tl(a),a.fa=!1)}function Ul(a,b){a.N&&(a.A.unshift(b),a.U=!0,Wl(a.N,b))}
function Ql(a){var b=0;a.A.length&&a.U&&(b=a.A[0],a.N&&Wl(a.N,b));A(a)&&y(a,b?"scan code "+t(b)+" available":"no scan codes available")}function Nl(a){var b=0;a.A.length&&(b=a.A[0]);A(a)&&y(a,"scan code "+t(b)+" delivered");return b}function Xl(a,b){0<a.A.length&&(a.A.shift(),(a.U=b)&&(a.A.length&&a.N?Wl(a.N,a.A[0]):b=!1),A(a)&&y(a,"scan codes shifted, notify "+(b?"true":"false")))}m.ic=function(a,b){return!b&&(this.reset(),a&&this.restore&&!this.restore(a))?!1:!0};
m.hc=function(a){return a?this.save():!0};m.reset=function(){if(!this.ja&&this.N)switch(this.N.ja){case 5150:case 5160:nm(this,om[0]);break;default:nm(this,om[1])}Bm(this);this.xc=this.C=0;this.A=[];this.U=!0;this.L=""};m.save=function(){var a=new hf(this),b=0,c=[];c[b++]=this.aa;c[b]=this.X;N(a,0,c);return a.data()};m.restore=function(a){return Bm(this,a[0])};function Bm(a,b){var c=0;void 0===b&&(b=[]);a.aa=a.U=b[c++];a.X=b[c];a.W=0;return!0}
@ -492,8 +492,8 @@ function gn(a,b){var c=a.mb[b];if(null!=c&&5<=a.Ua){var d=0,e=0,f=0;switch(b){ca
m=Z.prototype;
m.Ic=function(a,b,c,d){this.ea=b;this.F=c;this.ha=d;c=(c=Fm[this.ja])&&c[0];3!==c&&(ic(b,this,hn),mc(b,this,jn));1!==c&&(ic(b,this,kn),mc(b,this,ln));5<=this.Ua&&(ic(b,this,mn),mc(b,this,nn));this.Ua==dm&&(ic(b,this,on),mc(b,this,pn));if(d){var e=this;Mk(d,262144,function(a){if(e.C)if(a[0]){var b=e.C;if(b.sd){var c,d,f,q=!1,p=8,z=8,F=-1,v=b.video.L>>3;for(c=0;c<a.length;c++){var E=a[c];if(c){var H=E.charAt(0);d=ca(E.substr(1));switch(H){case "l":p=d;break;case "n":1<=d&&8>=d&&(z=d,q=!0);break;case "p":0<=
d&&3>=d&&(F=d);break;case "w":d<v&&(v=d);break;default:b.ha.O("unrecognized argument: "+E)}}else f=ca(E)}void 0===f?f=b.B||0:f>=b.ob&&(f-=b.ob);a="";for(c=0;c<p;c++){E=r(b.ob+f)+":";for(d=0;d<z&&f<b.sd.length;d++)H=b.sd[f++],E+=" "+(0>F?r(H):da(H>>(F<<3),8));q&&(f+=v-z);a&&(a+="\n");a+=E}a&&b.ha.O(a);b.B=f}else b.ha.O("no buffer")}else e.ha.O("BIOSMODE: "+t(e.Ia)),b=e.C,fn(b,"CRTC",b.Ac,b.mb,b.lg),5<=b.Ua&&(fn(b," GRC",b.ce,b.be,b.Vg),fn(b," SEQ",b.de,b.Ke,b.Wg),fn(b," ATC",b.Od,b.Tc,b.Ug),fn(b," ATCINDX",
b.Od),b.ha.O(" ATCDATA: "+b.Ye),fn(b," FEAT",b.eg),fn(b," MISC",b.vf),fn(b," STATUS0",b.Ng)),fn(b," STATUS1",b.ma),1!=b.Ua&&3!=b.Ua||fn(b," MODEREG",b.gd),3==b.Ua&&fn(b," COLOR",b.tf),5<=b.Ua&&(b.ha.O(" LATCHES: "+r(b.Gb)),b.ha.O(" ACCESS: "+r(b.xg,4)),b.ha.O("Use 'dump video [addr]' to dump video memory"));else e.ha.O("no active video card")})}if((this.B=Eb(a,"Keyboard"))&&this.ka){for(var f in this.qa)0<f.indexOf("lock")&&this.B.Pb("led",f,this.qa[f]);this.B.Pb(this.wk?"textarea":"canvas",
"kbd",this.V)}this.Vc=9;(this.N=Eb(a,"ChipSet"))&&this.cg&&5==this.Ua&&(this.Vc=sk(this.cg,this.Vc));"mouse"==this.hg?(this.W=Eb(a,"Mouse"))&&qn(this,2):"keygrid"==this.hg&&this.B&&qn(this,1)};
b.Od),b.ha.O(" ATCDATA: "+b.Ye),fn(b," FEAT",b.eg),fn(b," MISC",b.vf),fn(b," STATUS0",b.Ng)),fn(b," STATUS1",b.ma),1!=b.Ua&&3!=b.Ua||fn(b," MODEREG",b.gd),3==b.Ua&&fn(b," COLOR",b.tf),5<=b.Ua&&(b.ha.O(" LATCHES: "+r(b.Gb)),b.ha.O(" ACCESS: "+r(b.xg,4)),b.ha.O("Use 'dump video [addr]' to dump video memory"));else e.ha.O("no active video card")})}if((this.B=Db(a,"Keyboard"))&&this.ka){for(var f in this.qa)0<f.indexOf("lock")&&this.B.Pb("led",f,this.qa[f]);this.B.Pb(this.wk?"textarea":"canvas",
"kbd",this.V)}this.Vc=9;(this.N=Db(a,"ChipSet"))&&this.cg&&5==this.Ua&&(this.Vc=sk(this.cg,this.Vc));"mouse"==this.hg?(this.W=Db(a,"Mouse"))&&qn(this,2):"keygrid"==this.hg&&this.B&&qn(this,1)};
m.Pb=function(a,b,c){var d=this;if(!this.qa[b])switch(this.qa[b]=c,b){case "fullScreen":return this.ia&&this.ia.Xe?c.onclick=function(){d.Xe()}:c.parentNode.removeChild(c),!0;case "lockPointer":return this.vk=c.textContent,this.V&&this.V.De?c.onclick=function(){d.De(!0)}:c.parentNode.removeChild(c),!0;case "refresh":return c.onclick=function(){rn(d,!0)},!0}return!1};
m.Xe=function(){var a=!1;if(this.ia){if(this.ia.Xe){a="100%";if(screen&&screen.width&&screen.height){var b=screen.width/screen.height,c=this.ra/this.Ea;b>c&&(a=Math.round(c/b*100)+"%")}this.rf?(this.ka.style.width=a,this.ka.style.width=a,this.ka.style.display="block",this.ka.style.margin="auto"):(this.ia.style.width=a,this.ia.style.height="auto");this.ia.style.backgroundColor="black";this.ia.Xe();a=!0}this.V&&this.V.focus()}return a};
function Im(a,b){!b&&a.ia&&(a.rf?a.ka.style.width=a.ka.style.height="":a.ia.style.width=a.ia.style.height="");y(a,"notifyFullScreen("+b+")",!0);a.B&&(a.B.dh=b)}m.De=function(a){var b=!1;this.V&&(a?this.V.De&&(this.V.De(),this.W&&this.W.Wf(!0),b=!0):this.V.tk&&(this.V.tk(),this.W&&this.W.Wf(!1),b=!0),this.V&&this.V.focus());return b};m.Wf=function(a){this.W&&(this.W.Wf(a),this.B&&(this.B.dh=a));var b=this.qa.lockPointer;b&&(b.textContent=a?"Press Esc to Unlock Pointer":this.vk)};
@ -508,7 +508,7 @@ function zn(a,b){if(1==b)return a.Ca[0]=Om[0],a.Ca[1]=Om[7],a.Ca;if(2==b){var c=
(c.Tc[20]&12)<<4,c.Tc[16]&128&&(g&=-49,g|=(c.Tc[20]&3)<<4),g=d[g],h=g<<2&252,k=g>>4&252,g=g>>10&252):(h=(g&4?170:0)|(g&32?85:0),k=(g&2?170:0)|(g&16?85:0),g=(g&1?170:0)|(g&8?85:0)),a.Ca[f]=[h,k,g,255]}a.rb=!0}return a.Ca}function cm(a,b,c,d){a.Uc=b;a.Jb=c;a.Tb=d}
function vn(a,b){var c=!1;if(window&&a.Uc&&(!b||a.U)){var d=0,e=a.Tb?a.Tb:8,f=zn(a);null!=a.Jb[0]&&An(a,3,a.Jb[0],d,e,8,a.Uc,f)&&(c=!0);d=a.Tb?0:2048;e=a.Tb?a.Tb:9;null!=a.Jb[1]&&(An(a,1,a.Jb[1],d,e,14,a.Uc,Mm,Nm)&&(c=!0),a.Tb&&An(a,a.Ua,a.Jb[1],0,a.Tb,14,a.Uc,f)&&(c=!0))}return c}function An(a,b,c,d,e,f,g,h,k){var l=!1;null!=c&&(Bn(a,b,c,d,e,f,g,h,k)&&(l=!0),a.un&&Bn(a,b<<1,c,d,e,f,g,h,k)&&(l=!0));return l}
function Bn(a,b,c,d,e,f,g,h,k){var l=!1,n=b&1?0:1,q=a.Oa[b],p=16>h.length?h.length:16;q||(q={Qc:e<<n,Rc:f<<n,Pe:Array(p),ti:h.slice(0,p),Af:k,Tg:Array(p)});for(k=0;k<p;k++){var z=h[k],F=q.Pe[k]?q.ti[k]:[];if(z[0]!==F[0]||z[1]!==F[1]||z[2]!==F[2]){var l=q,F=k,v=n,E=c,H=d,L=e,V=f,P=g,bb=[0,0,0,0],ia=document.createElement("canvas");ia.width=l.Qc<<4;ia.height=l.Rc<<4;for(var ja=ia.getContext("2d"),Ha=void 0,Xa=void 0,Ba=void 0,Vb=8>V||!H?V:8,wa=ja.createImageData(l.Qc,l.Rc),Ha=0;256>Ha;Ha++){for(Ba=
0;Ba<V;Ba++)for(var Ud=l.Af&&F&1&&Ba>=V-2,Qc=P[Ba<Vb?E+Ha*Vb+Ba:H+Ha*Vb+Ba-Vb],Vd=0;Vd<=v;Vd++)for(Xa=0;Xa<L;Xa++){var Je=Xa<<v,Wd=(Ba<<v)+Vd,Ke=Ud||Qc&128>>(8<=Xa&&192<=Ha&&223>=Ha?7:Xa)?z:bb;Cn(wa,Je,Wd,Ke);v&&Cn(wa,Je+1,Wd,Ke)}ja.putImageData(wa,(Ha&15)*l.Qc,(Ha>>4)*l.Rc)}l.Pe[F]="#"+r(z[0],2)+r(z[1],2)+r(z[2],2);l.ti[F]=z;l.Tg[F]=ia;l=!0}}a.Oa[b]=q;return l}function $n(a){0<a.Pa||0<=a.ua?0>a.cb&&(a.cb=0):a.cb=-1}
0;Ba<V;Ba++)for(var Vd=l.Af&&F&1&&Ba>=V-2,Qc=P[Ba<Vb?E+Ha*Vb+Ba:H+Ha*Vb+Ba-Vb],Wd=0;Wd<=v;Wd++)for(Xa=0;Xa<L;Xa++){var Je=Xa<<v,Xd=(Ba<<v)+Wd,Ke=Vd||Qc&128>>(8<=Xa&&192<=Ha&&223>=Ha?7:Xa)?z:bb;Cn(wa,Je,Xd,Ke);v&&Cn(wa,Je+1,Xd,Ke)}ja.putImageData(wa,(Ha&15)*l.Qc,(Ha>>4)*l.Rc)}l.Pe[F]="#"+r(z[0],2)+r(z[1],2)+r(z[2],2);l.ti[F]=z;l.Tg[F]=ia;l=!0}}a.Oa[b]=q;return l}function $n(a){0<a.Pa||0<=a.ua?0>a.cb&&(a.cb=0):a.cb=-1}
function yn(a){if(a.U){for(var b=10;15>=b;b++)if(null==a.C.mb[b])return;var c=a.C.mb[10],b=c&31,d=a.C.mb[11]&31,e=a.C.mb[9]&31,f=!1;a.C===a.A&&(f=!0,7!=e||4!=b||d||(d=7));if(c&32||b>d&&!f||b>e)ao(a);else{c=a.C.mb[15]+((a.C.mb[14]&63)<<8);a.ua!=c&&(ao(a),a.ua=c);d=d-b+1;if(a.jg!=b||a.Ce!=d)a.jg=b,a.Ce=d;a.$a=e+1;$n(a)}}}
function ao(a){if(0<=a.ua){if(void 0!==a.ga){var b=a.ga[a.ua];if(b&131072){var b=b&-131073,c=a.ua%a.L,d=a.ua/a.L|0;a.U&&a.Oa[a.U]&&(a.gb&&bo(a,c,d,b,a.gb),bo(a,c,d,b));a.ga[a.ua]=b}}a.ua=-1}}
function co(a){var b,c=a.C;a.hf=!1;var d=c.be[5];if(null!=d){b=1024;var e=0,f=c.be[3]&31;switch(d&3){case 0:if(f){e=32;switch(f&24){case 8:e=96;break;case 16:e=160;break;case 24:e=224}c.dd=f&7}break;case 1:e=1;break;case 2:switch(f&24){default:e=2;break;case 8:e=98;break;case 16:e=162;break;case 24:e=226}break;case 3:a.Ua==dm&&(e=3,c.dd=f&7)}d&8&&(b=1280);c=c.Ke[4];null!=c&&(c&4||(b|=4096,e|=16),d&64&&(c&8&&(b|=16384,e|=4),a.hf=!0));b|=e}return b}
@ -543,13 +543,13 @@ var hn={948:Z.prototype.Hl,949:Z.prototype.Gl,952:Z.prototype.Il,954:Z.prototype
Qa(function(){for(var a=nb(document,"pcx86","video"),b=0;b<a.length;b++){var c=a[b],d=jb(c),e=document.createElement("canvas");if(void 0===e||!e.getContext){c.innerHTML="<br/>Missing &lt;canvas&gt; support. Please try a newer web browser.";break}e.setAttribute("class","pcjs-canvas");e.setAttribute("width",d.screenWidth);e.setAttribute("height",d.screenHeight);e.style.backgroundColor=d.screenColor;e.style.height="auto";0<=ya().indexOf("MSIE")&&(c.onresize=function(a,b,c,d){return function(){b.style.height=
(a.clientWidth*d/c|0)+"px"}}(c,e,d.screenWidth,d.screenHeight),c.onresize());var f=+(d.aspect||Ya.aspect);f&&.3<=f&&3.33>=f&&(Pa("onresize",function(a,b,c){return function(){b.style.height=(a.clientWidth/c|0)+"px"}}(c,e,f)),window.onresize());c.appendChild(e);f=document.createElement("textarea");Ga("iOS")&&(f.setAttribute("autocapitalize","off"),f.setAttribute("autocorrect","off"));c.appendChild(f);var g=e.getContext("2d"),d=new Z(d,e,g,f,c);mb(d,c)}});
function no(a){this.W=a.adapter;switch(this.W){case 1:this.V=956;this.C=7;break;case 2:this.V=888;this.C=7;break;case 3:this.V=632;this.C=5;break;default:w("Unrecognized parallel adapter #"+this.W);return}this.A=this.B=null;Ua.call(this,"ParallelPort",a,no,4194304);a=a.binding;"console"==a?this.B="":kb(this,a,oo)}db(no);var oo="buffer";m=no.prototype;m.Pb=function(a,b,c){switch(b){case oo:return this.qa[b]=this.A=c,!0}return!1};
m.Ic=function(a,b,c,d){this.ea=b;this.F=c;this.ha=d;this.N=Eb(a,"ChipSet");ic(b,this,po,this.V);mc(b,this,qo,this.V);rb(this)};m.ic=function(a,b){if(!b)if(!a||!this.restore)this.reset();else if(!this.restore(a))return!1;return!0};m.hc=function(a){return a?this.save():!0};m.reset=function(){ro(this)};m.save=function(){var a=new hf(this),b=0,c=[];c[b++]=this.L;c[b++]=this.Yb;c[b]=this.Cf;N(a,0,c);return a.data()};m.restore=function(a){return ro(this,a[0])};
m.Ic=function(a,b,c,d){this.ea=b;this.F=c;this.ha=d;this.N=Db(a,"ChipSet");ic(b,this,po,this.V);mc(b,this,qo,this.V);rb(this)};m.ic=function(a,b){if(!b)if(!a||!this.restore)this.reset();else if(!this.restore(a))return!1;return!0};m.hc=function(a){return a?this.save():!0};m.reset=function(){ro(this)};m.save=function(){var a=new hf(this),b=0,c=[];c[b++]=this.L;c[b++]=this.Yb;c[b]=this.Cf;N(a,0,c);return a.data()};m.restore=function(a){return ro(this,a[0])};
function ro(a,b){var c=0;void 0===b&&(b=[0,0,0]);a.L=b[c++];a.Yb=b[c++];a.Cf=b[c];return!0}m.ul=function(a,b){var c=this.L;x(this,a,null,b,"DATA",c);return c};m.Sl=function(a,b){var c=this.Yb;x(this,a,null,b,"STAT",c);return c};m.ql=function(a,b){var c=this.Cf;x(this,a,null,b,"CTRL",c);return c};
m.Om=function(a,b,c){x(this,a,b,c,"DATA");this.L=b;this.Yb|=64;if(this.A)8==b?this.A.value=this.A.value.slice(0,-1):(this.A.value+=String.fromCharCode(b),this.A.scrollTop=this.A.scrollHeight),a=!0;else if(null!=this.B){if(10==b||1024<=this.B.length)this.O(this.B),this.B="";10!=b&&(this.B+=String.fromCharCode(b));a=!0}else a=!1;a&&(this.Yb&=-65);so(this)};m.Jm=function(a,b,c){x(this,a,b,c,"CTRL");this.Cf=b;so(this)};function so(a){a.N&&a.C&&(a.Cf&16&&!(a.Yb&64)?eg(a.N,a.C):dg(a.N,a.C))}
var po={0:no.prototype.ul,1:no.prototype.Sl,2:no.prototype.ql},qo={0:no.prototype.Om,2:no.prototype.Jm};Qa(function(){for(var a=nb(document,"pcx86","parallel"),b=0;b<a.length;b++){var c=a[b],d=jb(c),d=new no(d);mb(d,c)}});
function to(a){this.ra=a.adapter;switch(this.ra){case 1:this.ka=1016;this.fa=4;break;case 2:this.ka=760;this.fa=3;break;default:w("Unrecognized serial adapter #"+this.ra);return}this.V=this.U=null;this.Ca=a.tabSize;this.ya=a.charBOL;this.X=0;Ua.call(this,"SerialPort",a,to,8388608);a=a.binding;"console"==a?this.U="":kb(this,a,uo)}db(to);var uo="buffer";m=to.prototype;m.xi=function(a,b){return a==this.Rd?(this.W=b,this):null};
m.Pb=function(a,b,c){var d=this;switch(b){case uo:return this.qa[b]=this.V=c,c.onkeydown=function(a){a=a||window.event;var b=a.keyCode;if(8===b||a.ctrlKey&&65<=b&&90>=b)a.preventDefault&&a.preventDefault(),64<b&&(b-=64),vo(d,[b]);return!0},c.onkeypress=function(a){a=a||window.event;vo(d,[a.which||a.keyCode]);a.preventDefault&&a.preventDefault();return!0},c.removeAttribute("readonly"),!0}return!1};
m.Ic=function(a,b,c,d){this.ea=b;this.F=c;this.ha=d;this.N=Eb(a,"ChipSet");ic(b,this,wo,this.ka);mc(b,this,xo,this.ka);rb(this)};m.ic=function(a,b){if(!b)if(!a||!this.restore)this.reset();else if(!this.restore(a))return!1;return!0};m.hc=function(a){return a?this.save():!0};m.reset=function(){yo(this)};
m.Ic=function(a,b,c,d){this.ea=b;this.F=c;this.ha=d;this.N=Db(a,"ChipSet");ic(b,this,wo,this.ka);mc(b,this,xo,this.ka);rb(this)};m.ic=function(a,b){if(!b)if(!a||!this.restore)this.reset();else if(!this.restore(a))return!1;return!0};m.hc=function(a){return a?this.save():!0};m.reset=function(){yo(this)};
m.save=function(){var a=new hf(this),b=0,c=[];c[b++]=this.pa;c[b++]=this.wa;c[b++]=this.aa;c[b++]=this.ia;c[b++]=this.L;c[b++]=this.B;c[b++]=this.C;c[b++]=this.A;c[b++]=this.ua;c[b]=this.ga;N(a,0,c);return a.data()};m.restore=function(a){return yo(this,a[0])};function yo(a,b){var c=0;void 0===b&&(b=[0,0,384,0,1,0,0,96,48,[]]);a.pa=b[c++];a.wa=b[c++];a.aa=b[c++];a.ia=b[c++];a.L=b[c++];a.B=b[c++];a.C=b[c++];a.A=b[c++];a.ua=b[c++];a.ga=b[c];return!0}function vo(a,b){a.ga=a.ga.concat(b);zo(a)}
function zo(a){0<a.ga.length&&!(a.A&1)&&(a.pa=a.ga.shift(),a.A|=1);var b=-1;a.A&1&&a.ia&1&&(b=4);0<=b?(a.L&=-8,a.L|=b,a.N&&a.fa&&eg(a.N,a.fa,100)):(a.L|=1,a.N&&a.fa&&dg(a.N,a.fa))}m.Pl=function(a,b){var c=this.B&128?this.aa&255:this.pa;x(this,a,null,b,this.B&128?"DLL":"RBR",c);this.A&=-2;zo(this);return c};m.Bl=function(a,b){var c=this.B&128?this.aa>>8:this.ia;x(this,a,null,b,this.B&128?"DLM":"IER",c);return c};m.Cl=function(a,b){var c=this.L;x(this,a,null,b,"IIR",c);return c};
m.Dl=function(a,b){var c=this.B;x(this,a,null,b,"LCR",c);return c};m.Fl=function(a,b){var c=this.C;x(this,a,null,b,"MCR",c);return c};m.El=function(a,b){var c=this.A;x(this,a,null,b,"LSR",c);return c};m.Kl=function(a,b){var c=this.ua;x(this,a,null,b,"MSR",c);return c};
@ -557,7 +557,7 @@ m.mn=function(a,b,c){x(this,a,b,c,this.B&128?"DLL":"THR");if(this.B&128)this.aa=
"";10!=b&&(this.U+=String.fromCharCode(b));b=!0}else b=!1;b&&(this.A|=96)}};m.Ym=function(a,b,c){x(this,a,b,c,this.B&128?"DLM":"IER");this.B&128?this.aa=this.aa&255|b<<8:this.ia=b};m.Zm=function(a,b,c){x(this,a,b,c,"LCR");this.B=b};
m.$m=function(a,b,c){var d=this.C;x(this,a,b,c,"MCR");this.C=b;this.W&&(d^b)&3&&(a=this.W,b=this.C,(c=3==(b&3))?a.Hc||(d=!1,a.C&2||(a.reset(),y(a,"serial mouse reset"),d=!0),a.C&1||(y(a,"serial mouse ID requested"),d=!0),d&&(vo(a.N,[77,77]),y(a,"serial mouse ID sent")),Ao(a),a.Hc=c):a.Hc&&(y(a,"serial mouse inactive"),Bo(a),a.Hc=c),a.C=b)};
var wo={0:to.prototype.Pl,1:to.prototype.Bl,2:to.prototype.Cl,3:to.prototype.Dl,4:to.prototype.Fl,5:to.prototype.El,6:to.prototype.Kl},xo={0:to.prototype.mn,1:to.prototype.Ym,3:to.prototype.Zm,4:to.prototype.$m};Qa(function(){for(var a=nb(document,"pcx86","serial"),b=0;b<a.length;b++){var c=a[b],d=jb(c),d=new to(d);mb(d,c)}});function Co(a){Ua.call(this,"Mouse",a,Co,16777216);if(this.ka=a.serial)this.pa="SerialPort";this.ia=this.ga=this.Hc=!1;this.B=[];this.A=[];rb(this)}db(Co);var tn=0;m=Co.prototype;
m.Ic=function(a,b,c,d){this.V=a;this.ea=b;this.F=c;this.ha=d;for(b=null;b=Eb(a,"Video",b);)this.B.push(b)};m.ic=function(a,b){if(!b){if(!a||!this.restore)this.reset();else if(!this.restore(a))return!1;if(this.pa&&!this.N){for(var c=null;(c=Eb(this.V,this.pa,c))&&(!c.xi||!(this.N=c.xi(this.ka,this))););if(this.N)for(this.A=[],c=0;c<this.B.length;c++){var d;d=this.B[c];d.W=this;(d=d.V)&&this.A.push(d)}else w(this.id+": "+this.pa+" "+this.ka+" unavailable")}this.Hc?Ao(this):Bo(this)}return!0};
m.Ic=function(a,b,c,d){this.V=a;this.ea=b;this.F=c;this.ha=d;for(b=null;b=Db(a,"Video",b);)this.B.push(b)};m.ic=function(a,b){if(!b){if(!a||!this.restore)this.reset();else if(!this.restore(a))return!1;if(this.pa&&!this.N){for(var c=null;(c=Db(this.V,this.pa,c))&&(!c.xi||!(this.N=c.xi(this.ka,this))););if(this.N)for(this.A=[],c=0;c<this.B.length;c++){var d;d=this.B[c];d.W=this;(d=d.V)&&this.A.push(d)}else w(this.id+": "+this.pa+" "+this.ka+" unavailable")}this.Hc?Ao(this):Bo(this)}return!0};
m.hc=function(a){return a?this.save():!0};m.reset=function(){Do(this)};m.save=function(){var a=new hf(this),b=0,c=[];c[b++]=this.Hc;c[b++]=this.L;c[b++]=this.W;c[b++]=this.U;c[b++]=this.X;c[b++]=this.aa;c[b++]=this.fa;c[b]=this.C;N(a,0,c);return a.data()};m.restore=function(a){return Do(this,a[0])};function Do(a,b){var c=0;void 0===b&&(b=[!1,-1,-1,0,0,!1,!1,0]);var d=b[c++];a.Hc=d;a.L=b[c++];a.W=b[c++];a.U=b[c++];a.X=b[c++];a.aa=b[c++];a.fa=b[c++];a.C=b[c];return!0}m.Wf=function(a){this.ga=a};
function Ao(a){if(!a.ia)for(var b=0;b<a.A.length;b++)Eo(a,a.A[b])&&(a.ia=!0)}function Bo(a){if(a.ia)for(var b=0;b<a.A.length;b++){var c=a.A[b];c&&(c.style.cursor="auto")}}function Eo(a,b){return b?(b.addEventListener("mousemove",function(b){Fo(a,b)},!1),b.addEventListener("mousedown",function(b){Fo(a,b,!0)},!1),b.addEventListener("mouseup",function(b){Fo(a,b,!1)},!1),b.style.cursor="none",!0):!1}
function Fo(a,b,c){if(void 0!==c){var d;!(d=!1!==a.ga)&&(d=a.B.length)&&(d=a.B[0],d=d.ri?d.De(!0):!1);d||(a.ga=null);a.je(b.button,c)}else{if(0>a.L||0>a.W)a.L=b.clientX,a.W=b.clientY;a.ga?(c=b.movementX||b.mozMovementX||b.webkitMovementX||0,d=b.movementY||b.mozMovementY||b.webkitMovementY||0):(c=b.clientX-a.L,d=b.clientY-a.W);a.L=b.clientX;a.W=b.clientY;a.If(c,d,a.L,a.W)}}
@ -598,7 +598,7 @@ var sp={3:{Wd:3,ie:0,name:aa.$n},4:{Wd:2,ie:1,name:aa.Yn},5:{Wd:9,ie:7,name:aa.j
m.Pb=function(a,b,c){var d=this;switch(b){case "listDisks":this.qa[b]=c;if(this.ga){b=[];for(a=0;a<c.options.length;a++)b.push(c.options[a]);b.sort(function(a,b){return"path"!=d.ga?a.text.localeCompare(b.text):a.value.localeCompare(b.value)});for(a=0;a<b.length;a++)c.options[a]=b[a]}c.onchange=function(){var a=d.qa.descDisk,b=c.options[c.selectedIndex];if(a&&b){var g={};if(b=b.getAttribute("data-value"))try{g=eval("("+b+")")}catch(h){w("FDC option error: "+h.message)}b=g.desc;void 0===b&&(b="");g=
g.href;void 0!==g&&(b='<a href="'+g+'" target="_blank">'+b+"</a>");a.innerHTML=b}};return!0;case "descDisk":case "listDrives":return this.qa[b]=c,c.onchange=function(){var a=ca(c.value,10);null!=a&&tp(d,a)},!0;case "loadDrive":return this.qa[b]=c,c.onclick=function(){var a=d.qa.listDisks;a&&up(d,a.options[a.selectedIndex].text,a.value)},!0;case "saveDrive":if(!this.ia){c.parentNode.removeChild(c);break}this.qa[b]=c;c.onclick=function(){var a=d.qa.listDrives;a&&a.options&&d.A&&(a=ca(a.value,10),(a=
d.A[a])?(a=a.za)?(a=Ia(pp(a),"octet-stream",!0,a.Og.replace(".json",".img")),w(a)):d.Na("No diskette loaded in drive."):d.Na("No diskette drive selected."))};return!0;case "mountDrive":if(!this.ia){c.parentNode.removeChild(c);break}this.qa[b]=c;c.addEventListener("change",function(){var a=c.children[0];a.children[1].disabled=!a.children[0].files.length});c.onsubmit=function(a){if(a=a.currentTarget[1].files[0]){var b=a.name;up(d,fa(b,!0),b,a)}return!1};return!0}return!1};
m.Ic=function(a,b,c,d){this.ea=b;this.F=c;this.ha=d;this.V=a;this.N=Eb(a,"ChipSet");if((this.U=Nc(this.V,"autoMount")||this.U)&&"string"==typeof this.U)try{this.U=eval("("+this.U+")")}catch(e){w("FDC auto-mount error: "+e.message+" ("+this.U+")"),this.U=null}vp(this);ic(b,this,wp);mc(b,this,xp);yp(this,"None","",!0);this.ia&&yp(this,"Local Disk","?");yp(this,"Remote Disk","??");zp(this)||rb(this)};
m.Ic=function(a,b,c,d){this.ea=b;this.F=c;this.ha=d;this.V=a;this.N=Db(a,"ChipSet");if((this.U=Nc(this.V,"autoMount")||this.U)&&"string"==typeof this.U)try{this.U=eval("("+this.U+")")}catch(e){w("FDC auto-mount error: "+e.message+" ("+this.U+")"),this.U=null}vp(this);ic(b,this,wp);mc(b,this,xp);yp(this,"None","",!0);this.ia&&yp(this,"Local Disk","?");yp(this,"Remote Disk","??");zp(this)||rb(this)};
m.ic=function(a,b){if(!b){if(!a||!this.restore){if(this.reset(),this.V.eh){this.B=[];for(var c=0;c<this.A.length;c++)Ap(this,c,!0);zp(this,!0)}}else if(!this.restore(a))return!1;if(c=this.qa.listDrives){for(;c.firstChild;)c.removeChild(c.firstChild);c.value="";for(var d=0;d<this.ka;d++){var e=document.createElement("option");e.value=d;e.text=String.fromCharCode(65+d)+":";c.appendChild(e)}0<this.ka&&(c.value="0",tp(this,0))}}return!0};m.hc=function(a){return a?this.save():!0};m.reset=function(){vp(this)};
m.save=function(){var a=new hf(this),b=0,c=[];c[b++]=this.hb;c[b++]=0;c[b++]=this.ma;c[b++]=this.W;c[b++]=this.L;c[b++]=this.C;c[b++]=this.aa;for(var d=b++,e=0,f=[],g=0;g<this.A.length;g++){var h=e++,k=this.A[g],l=0,n=[];n[l++]=k.Cb;n[l++]=[k.name,k.Bb,k.ub,k.lb,k.Va,k.cf,k.Ag,k.Of,k.Pf];n[l++]=k.kb;n[l++]=k.ge+100;n[l++]=k.Qb;n[l++]=k.xb;n[l++]=k.he;n[l++]=k.Ib;n[l++]=k.eb;n[l++]=k.af;n[l++]=k.lk;n[l]=k.Me;f[h]=n}c[d]=f;d=b++;for(e=0;e<this.A.length;e++)f=this.A[e],f.za&&Bp(this,f.Me,f.za);c[d]=
this.B;c[b++]=this.X;c[b]=this.jc;N(a,0,c);return a.data()};m.restore=function(a){return vp(this,a[0])};
@ -625,7 +625,7 @@ Qa(function(){for(var a=nb(document,"pcx86","fdc"),b=0;b<a.length;b++){var c=a[b
var Lp=["XTC","ATC","COMPAQ"],Mp=[{0:[306,2],1:[375,8],2:[306,6],3:[306,4]},{1:[306,4],2:[615,4],3:[615,6],4:[940,8],5:[940,6],6:[615,4],7:[462,8],8:[733,5],9:[900,15],10:[820,3],11:[855,5],12:[855,7],13:[306,8],14:[733,7],16:[612,4],17:[977,5],18:[977,7],19:[1024,7],20:[733,5],21:[733,7],22:[733,5],23:[306,4]},{1:[306,4],2:[615,4],3:[615,6],4:[1023,8],5:[940,6],6:[697,5],7:[462,8],8:[925,5],9:[900,15],10:[980,5],11:[925,7],12:[925,9],13:[612,8],14:[980,4],16:[612,4],17:[980,5],18:[966,6],19:[1023,
8],20:[733,5],21:[733,7],22:[524,4,40],23:[924,8],24:[966,14],25:[966,16],26:[1023,14],27:[832,6,33],28:[1222,15,34],29:[1240,7,34],30:[615,4,25],31:[615,8,25],32:[905,9,25],33:[832,8,33],34:[966,7,34],35:[966,8,34],36:[966,9,34],37:[966,5,34],38:[612,16,63],39:[1023,11,33],40:[1023,15,34],41:[1630,15,52],42:[1023,16,63],43:[805,4,26],44:[805,2,26],45:[748,8,33],46:[748,6,33],47:[966,5,25]}];m=Kp.prototype;
m.Pb=function(a,b,c){var d=this;switch(b){case "saveHD0":case "saveHD1":return this.qa[b]=c,c.onclick=function(a){return function(){var b=d.A&&d.A[a];b&&b.za?(b=b.za,b=Ia(pp(b),"octet-stream",!0,b.Og.replace(".json",".img")),w(b)):d.Na("Hard drive "+a+" is not available.")}}(+b.slice(-1)),!0}return!1};
m.Ic=function(a,b,c,d){this.ea=b;this.F=c;this.ha=d;this.V=a;if(d=Nc(a,"drives"))this.ua=d;else if(this.Fa)try{this.ua=eval("("+this.Fa+")")}catch(e){w("HDC drive configuration error: "+e.message+" ("+this.Fa+")")}this.N=Eb(a,"ChipSet");this.U=0;this.Ia=3;ic(b,this,this.ia?Np:Op);mc(b,this,this.ia?Pp:Qp);this.ia&&(this.U++,this.N&&5180==this.N.ja&&this.U++,this.Ia=2,b.aa[496]=2,b.fa[496]=2);Te(c,19,this.$l.bind(this));Te(c,64,this.am.bind(this));this.reset();Rp(this)||rb(this)};
m.Ic=function(a,b,c,d){this.ea=b;this.F=c;this.ha=d;this.V=a;if(d=Nc(a,"drives"))this.ua=d;else if(this.Fa)try{this.ua=eval("("+this.Fa+")")}catch(e){w("HDC drive configuration error: "+e.message+" ("+this.Fa+")")}this.N=Db(a,"ChipSet");this.U=0;this.Ia=3;ic(b,this,this.ia?Np:Op);mc(b,this,this.ia?Pp:Qp);this.ia&&(this.U++,this.N&&5180==this.N.ja&&this.U++,this.Ia=2,b.aa[496]=2,b.fa[496]=2);Te(c,19,this.$l.bind(this));Te(c,64,this.am.bind(this));this.reset();Rp(this)||rb(this)};
m.ic=function(a,b){if(!b)if(!a||!this.restore)Sp(this),this.V.eh&&Rp(this,!0);else if(!this.restore(a))return!1;return!0};m.hc=function(a){return a?this.save():!0};m.gf=function(){return this.V?this.V.gf():""};m.ke=function(){return this.V?this.V.ke():""};m.reset=function(){Sp(this,null,!0)};
m.save=function(){var a=new hf(this),b=0,c=[];this.ia?(c[b++]=this.X,c[b++]=this.Pa,c[b++]=this.aa,c[b++]=this.Ca,c[b++]=this.ya,c[b++]=this.wa,c[b++]=this.ra,c[b++]=this.ma,c[b++]=this.Ea,c[b++]=[this.ga,this.hb]):(c[b++]=this.pa,c[b++]=this.ma,c[b++]=this.W,c[b++]=this.L,c[b++]=this.C,c[b++]=this.Oa,c[b++]=this.Ka,c[b++]=this.Ja,c[b++]=this.ka);for(var d=0,e=[],f=0;f<this.A.length;f++){var g=d++,h=this.A[f],k=0,l=[];l[k++]=h.errorCode;l[k++]=h.nk;l[k++]=h.cf;l[k++]=h.Re;l[k++]=h.Se;l[k++]=h.kb;
l[k++]=h.ub;l[k++]=h.ee;l[k++]=h.xb;l[k++]=h.he;l[k++]=h.Ib;l[k++]=h.eb;l[k]=h.za?h.za.save():null;e[g]=l}c[b]=e;N(a,0,c);return a.data()};m.restore=function(a){return Sp(this,a[0])};
@ -676,7 +676,7 @@ bus:64,mem:128,port:256,dma:512,pic:1024,timer:2048,cmos:4096,rtc:8192,8042:1638
[116,12417,4113],[109,12417,4113],[110,12417,4113],[140,12417,4113],[142,12417,4113],wq,[119,12417,4113]],[[115,12420,4113],[116,12420,4113],[109,12420,4113],[110,12420,4113],[140,12420,4113],[142,12420,4113],wq,[119,12420,4113]],[[115,12417,4449],[116,12417,4449],[109,12417,4449],[110,12417,4449],[140,12417,4449],[142,12417,4449],wq,[119,12417,4449]],[[115,12420,4449],[116,12420,4449],[109,12420,4449],[110,12420,4449],[140,12420,4449],[142,12420,4449],wq,[119,12420,4449]],[[155,4225,4097],wq,[98,
12417],[96,12417],[95,4225],[42,12417],[32,4225],[41,12417]],[[155,4228,4100],wq,[98,12420],[96,12420],[95,4228],[42,12420],[32,4228],[41,12420]],[[44,12417],[31,12417],wq,wq,wq,wq,wq,wq],[[44,12420],[31,12420],[17,4228],[17,4231],[57,4228],[57,4231],[108,4228],wq],[],[[145,41091],[153,41091],[78,36995],[89,36995],[156,36995],[157,36995],wq,wq],[[139,41091],[144,41091],[75,36995],[77,36995],[146,41091],wq,[79,36995],wq],[wq,wq,wq,wq,[13,53380,4097],[16,57476,4097],[15,57476,4097],[14,57476,4097]]];
m=gq.prototype;
m.Ic=function(a,b,c,d){this.ea=b;this.F=c;this.V=a;this.tc=Eb(a,"FDC");this.Jb=Eb(a,"HDC");this.Tb=Eb(a,"FPU");this.W=Eb(a,"Mouse");(a=Nc(a,"messages"))&&kq(this,a);this.Ca=b.N>>2;this.Ba=b.yg;this.bc=new dd(this.F,7,"DBG");this.Ia=yq;80186<=this.F.ja&&(this.Ia=yq.slice(),this.Ia[15]=wq,80286<=this.F.ja&&(this.Ia[15]=xq,80386<=this.F.ja&&(this.Ja=8)));Mk(this,64,function(a){Cq(d,d.F.ld,a[0])});Mk(this,4,function(a){if(a=a[0]){var b=Dq(d,a);if(void 0===b)d.O("invalid selector: "+a);else if(a=Eq(d,
m.Ic=function(a,b,c,d){this.ea=b;this.F=c;this.V=a;this.tc=Db(a,"FDC");this.Jb=Db(a,"HDC");this.Tb=Db(a,"FPU");this.W=Db(a,"Mouse");(a=Nc(a,"messages"))&&kq(this,a);this.Ca=b.N>>2;this.Ba=b.yg;this.bc=new dd(this.F,7,"DBG");this.Ia=yq;80186<=this.F.ja&&(this.Ia=yq.slice(),this.Ia[15]=wq,80286<=this.F.ja&&(this.Ia[15]=xq,80386<=this.F.ja&&(this.Ja=8)));Mk(this,64,function(a){Cq(d,d.F.ld,a[0])});Mk(this,4,function(a){if(a=a[0]){var b=Dq(d,a);if(void 0===b)d.O("invalid selector: "+a);else if(a=Eq(d,
b,2),d.O("dumpSel("+u(a?a.Z:b)+"): %"+r(a?a.Xb:null,d.Ca)),a){var c,b=!1;if(a.type&4096)a.type&2048?(c="code"+(a.type&512?",readable":",execonly"),a.type&1024&&(c+=",conforming")):(c="data"+(a.type&512?",writable":",readonly"),a.type&1024&&(c+=",expdown")),a.type&256&&(c+=",accessed");else{var h=Fq[a.type];h&&(c=h[0],b=h[1])}!c||a.wb&32768||(c+=",not present");d.O((b?"seg="+u(a.Aa&65535)+" off="+u(a.Ta):"base="+r(a.Aa,d.Ca)+" limit="+Gq(a.Ta))+" type="+t(a.type>>8)+" ("+c+") ext="+u(a.ext&-65296)+
" dpl="+t(a.Gc))}}else d.O("no selector")});Mk(this,134217728,function(a){var b;(a=a[0])&&(b=Dq(d,a));if(void 0===b)d.O("invalid MCB");else for(d.O("dumpMCB("+u(b)+")");b;){a=hq(d,0,b);var c=d.Qa(a,1),h=d.na(a,2),k=d.na(a,5);if(77!=c&&90!=c)break;d.O(Hq(0,b)+": '"+String.fromCharCode(c)+"' PID="+u(h)+" LEN="+u(k)+' "'+Iq(d,a,8)+'"');b+=1+k}});Mk(this,128,function(a){Cq(d,d.F.sa,a[0],d.F.sa!==d.F.ld)});Mk(this,8,function(a){a:{if(a=a[0]){var b=Dq(d,a);if(void 0===b){d.O("invalid task selector: "+a);
break a}a=Eq(d,b,2)}else a=d.F.Sa;d.O("dumpTSS("+u(a?a.Z:b)+"): %"+r(a?a.Aa:null,d.Ca));if(a){var b="",c=a.type&-513,h=256==c?4:8,k=256==c?Jq:Kq,l,n,q,p;for(p in k)l=k[p],n=a.Aa+l,q=If(d.F,n,2),2304==c&&(q|=If(d.F,n+2,2)<<16),b&&(b+="\n"),b+=u(l)+" "+ma(p+":",11)+r(q,h);if(2304==c)for(p=0,l=q>>>16;l<a.Zb&&1023>p;)n=a.Aa+l,q=If(d.F,n,2),b+="\n"+u(l)+" ports "+u(p)+"-"+u(p+15)+": "+ea(q,2),p+=16,l+=2;d.O(b)}}});this.C=null;this.rb=0;this.cb=!1;Te(this.F,48,this.cm.bind(this));Te(this.F,65,this.dm.bind(this));
@ -701,7 +701,7 @@ function Cq(a,b,c,d){var e=0,f=0,g=b.length;if(c){e=a.dc(Yq(a,c));if(-1===e){a.O
wc&&5!=c&&(c=-1),h=0),e+=a.F.Sb,f++}function cr(a,b,c){a=r(a)+" "+r(b)+" ";a=a+(c&&b&64?"D":"-")+(b&32?"A":"-");a+=b&4?"U":"S";a+=b&2?"W":"R";return a+=b&1?"P":"N"}
var Fq={256:["tss286",!1],512:["ldt",!1],768:["busy tss286",!1],1024:["call gate",!0],1280:["task gate",!0],1536:["int gate286",!0],1792:["trap gate286",!0],2304:["tss386",!1],2816:["busy tss386",!1],3072:["call gate386",!0],3584:["int gate386",!0],3840:["trap gate386",!0]},Jq={PREV_TSS:0,CPL0_SP:2,CPL0_SS:4,CPL1_SP:6,CPL1_SS:8,CPL2_SP:10,CPL2_SS:12,TASK_IP:14,TASK_PS:16,TASK_AX:18,TASK_CX:20,TASK_DX:22,TASK_BX:24,TASK_SP:26,TASK_BP:28,TASK_SI:30,TASK_DI:32,TASK_ES:34,TASK_CS:36,TASK_SS:38,TASK_DS:40,
TASK_LDT:42},Kq={PREV_TSS:0,CPL0_ESP:4,CPL0_SS:8,CPL1_ESP:12,CPL1_SS:16,CPL2_ESP:20,CPL2_SS:24,TASK_CR3:28,TASK_EIP:32,TASK_PS:36,TASK_EAX:40,TASK_ECX:44,TASK_EDX:48,TASK_EBX:52,TASK_ESP:56,TASK_EBP:60,TASK_ESI:64,TASK_EDI:68,TASK_ES:72,TASK_CS:76,TASK_SS:80,TASK_DS:84,TASK_FS:88,TASK_GS:92,TASK_LDT:96,TASK_IOPM:100};
function Mq(a,b,c){var d=[],e;for(e=null;e=Eb(a.V,"Disk",e);){var f=e,g=b,h=c,d=[];if(f.C)for(var k=0;k<f.C.length;k++){var l=f.C[k];if(l.gg==g&&(l=l.zd[h])){for(var n in l.we)f=l.we[n],d[f[1]]=f[0];break}}if(d.length)break}return d}function kq(a,b){a.ha=a;a.wc=a.Hk=1073741824;a.Pa=null;var c=br(a,b.replace("keys","key").replace("kbd","keyboard"),!1,"|");if(c.length)for(var d in vq)0<=ua(c,d)&&(a.wc|=vq[d],a.O(d+" messages enabled"));jq(a)}
function Mq(a,b,c){var d=[],e;for(e=null;e=Db(a.V,"Disk",e);){var f=e,g=b,h=c,d=[];if(f.C)for(var k=0;k<f.C.length;k++){var l=f.C[k];if(l.gg==g&&(l=l.zd[h])){for(var n in l.we)f=l.we[n],d[f[1]]=f[0];break}}if(d.length)break}return d}function kq(a,b){a.ha=a;a.wc=a.Hk=1073741824;a.Pa=null;var c=br(a,b.replace("keys","key").replace("kbd","keyboard"),!1,"|");if(c.length)for(var d in vq)0<=ua(c,d)&&(a.wc|=vq[d],a.O(d+" messages enabled"));jq(a)}
function Mk(a,b,c){for(var d in vq)if(b==vq[d]){a.$a[d]=c;break}}function dr(a,b){var c;a=a.toUpperCase();null==b?c=ua(tq,a):(c=ua(tq,a.substr(b,3)),0>c&&(c=ua(tq,a.substr(b,2))));return c}
function er(a,b){var c=0,d=fr(a,b);if(void 0!==d)switch(b){case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7:c=2;break;case 8:case 9:case 10:case 11:case 12:case 13:case 14:case 15:case 22:case 16:case 17:case 18:case 19:case 20:case 21:c=4;break;case 24:case 25:case 26:case 27:case 28:case 29:case 30:case 31:case 32:case 33:case 34:case 35:case 56:c=8;break;case 23:c=a.Ja}return c?r(d,c):"??"}
function fr(a,b){var c;if(0<=b){var d=a.F;switch(b){case 0:c=d.G&255;break;case 1:c=d.I&255;break;case 2:c=d.M&255;break;case 3:c=d.H&255;break;case 4:c=d.G>>8&255;break;case 5:c=d.I>>8&255;break;case 6:c=d.M>>8&255;break;case 7:c=d.H>>8&255;break;case 8:c=d.G&65535;break;case 9:c=d.I&65535;break;case 10:c=d.M&65535;break;case 11:c=d.H&65535;break;case 12:c=I(d)&65535;break;case 13:c=d.P&65535;break;case 14:c=d.K&65535;break;case 15:c=d.J&65535;break;case 22:c=K(d)&65535;break;case 23:c=wd(d);break;
@ -760,50 +760,51 @@ Yq(a,g[1],!0);if(q)if(a.ua=q,void 0===g[2])a.O("begin assemble at "+Rq(q)),a.Ea=
a.O("\tbc [a]\tclear breakpoint at addr [a]"),a.O("\tbl\tlist all breakpoints"),a.O("\tbn [n]\tbreak after [n] instruction(s)");else{var H=F.charAt(1);if("l"==H){var L=0,L=L+or(a,a.A),L=L+or(a,a.ra);(L+=or(a,a.ga))||a.O("no breakpoints")}else if("n"==H)a.Oa=Dq(a,v),a.O("break after "+a.Oa+" instruction(s)");else if(void 0===v)a.O("missing breakpoint address");else{var V={};if("*"!=v&&(V=Yq(a,v,!0,!0),!V))break a;v=null==V.Ra?v:u(V.Ra);"c"==H?null==V.Ra?(iq(a),a.O("all breakpoints cleared")):Qq(a,
a.A,V)||Qq(a,a.ra,V)||Qq(a,a.ga,V)||a.O("breakpoint missing: "+Rq(V)):"i"==H?a.O("breakpoint "+(hc(a.ea,V.Ra)?"enabled":"cleared")+": port "+v+" (input)"):"o"==H?a.O("breakpoint "+(lc(a.ea,V.Ra)?"enabled":"cleared")+": port "+v+" (output)"):null!=V.Ra&&(ar(a,V,E),"p"==H?a.Td(a.A,V):"r"==H?a.Td(a.ra,V):"w"==H?a.Td(a.ga,V):a.O("unknown breakpoint command: "+H))}}}break;case "c":Er(a);break;case "d":a:{var P=g,bb,ia=P[0],ja=P[1],Ha=P[2],Xa=P[3];if("?"==ja){var Ba="";for(bb in vq)a.$a[bb]&&(Ba&&(Ba+=
","),Ba+=bb);Ba+=",state,symbols";a.O("dump memory commands:");a.O("\tdb [a] [#] dump # bytes at address a");a.O("\tdw [a] [#] dump # words at address a");a.O("\tdd [a] [#] dump # dwords at address a");a.O("\tdh [#] [#] dump # instructions from history");a.O("\tdi [#] dump descriptor info for IDT #");a.O("\tds [#] dump descriptor info for selector #");Ba.length&&a.O("dump extension commands:\n\t"+Ba)}else if("state"==ja){var Vb=Mr(a.V,!0);"console"==Ha?console.log(Vb):(Er(a),
a.O(Vb))}else if("symbols"==ja)for(var wa=0;wa<a.B.length;wa++){var Ud=a.B[wa],Qc;for(Qc in Ud.Sd)if("."!=Qc.charAt(0)){var Vd=Ud.Sd[Qc],Je=Vd.o;if(void 0!==Je){var Wd=Vd.s;void 0===Wd&&(Wd=Ud.Z);var Ke=Ud.Sd[Qc].l;Ke&&(Qc=Ke);a.O(Hq(Je,Wd)+" "+Qc)}}}else{if("ds"==ia||"dg"==ia||"dl"==ia)ia="d",P=[ia,"desc",ja];"d"==ia&&"page"==ja&&(ia="dp",P.shift());if("dp"==ia){P.shift();var ki=P[0];if(ki){var Ue=a.dc(Yq(a,ki));if(-1===Ue)a.O("invalid address: "+ki);else{var ae,Da=null;if(80386<=a.F.ja){var be=
a.ea,Da={};Da.ck=(Ue&-4194304)>>>20;Da.vi=a.F.Pd+Da.ck;Da.yb=be.sa[(Da.vi&be.Hb)>>>be.La];Da.Vi=Da.yb.Nd(Da.ck);Da.dk=(Ue&4190208)>>>10;Da.wi=(Da.Vi&-4096)+Da.dk;Da.zb=be.sa[(Da.wi&be.Hb)>>>be.La];Da.Wi=Da.zb.Nd(Da.dk);Da.Gk=(Da.Wi&-4096)+(Ue&4095)}if(ae=Da){a.O("linear PDE addr PDE PTE addr PTE physical");a.O("--------- ---------- -------- ---------- -------- ----------");var pd="%"+r(Ue),pd=pd+(" %%"+cr(ae.vi,ae.Vi)),pd=pd+(" %%"+cr(ae.wi,ae.Wi,!0)),
pd=pd+(" %%"+r(ae.Gk));a.O(pd)}else a.O("unsupported operation")}}else a.O("missing address")}else{if("d"==ia){if("disk"==ja){P[0]="l";P[1]="json";Ir(a,P);break a}for(bb in vq)if(P[1]==bb){var Dn=a.$a[bb];Dn?(P.shift(),P.shift(),Dn(P)):a.O("no dump registered for "+ja);break a}ja||(ia=a.Cc||"db")}else a.Cc=ia;if("dh"==ia){var En=ja,Fn=Ha,Gn="",Hn=0,tb=a.Fa,sc=a.ia;if(sc.length){var Db=+En||a.Ub,ce=+Fn||10;isNaN(Db)?Db=ce:Gn="more ";Db>sc.length&&(a.O("note: only "+sc.length+" available"),Db=sc.length);
tb-=Db;0>tb&&(null==sc[sc.length-1].Z?(Db=tb+Db,tb=0):tb+=sc.length);var li=[];"call"==Fn&&(ce=1E5,li=["CALL"]);for(void 0!==En&&a.O(Db+" instructions earlier:");0<ce&&tb!=a.Fa;){var qd=sc[tb++];if(null==qd.Z)break;var Ve=hq(a,qd.Ra,qd.Z,qd.Da,qd.type,qd.Rb,qd.oc),fs=Db--,In=qr(a,Ve,"history",fs);(!li.length||0<=In.indexOf(li[0]))&&a.O(In);Ve.Te&&(tb+=Ve.Te,ce-=Ve.Te,Db-=Ve.Te);tb>=sc.length&&(tb=0);a.Ub=Db;Hn++;ce--}}Hn||(a.O("no "+Gn+"history available"),a.Ub=void 0)}else if("di"==ia){P.shift();
var mi=P[0];if(mi){var We=Dq(a,mi);if(void 0===We||0>We||255<We)a.O("invalid vector: "+mi);else{var Jn="&",Kn=!!(a.F.Za&1),Ln=!1,pg=a.F.Mc+(We<<(Kn?3:2)),ni=a.F.na(pg+0),gs=a.F.na(pg+2);Kn&&(Jn="#",a.F.na(pg+4)&2048&&(Ln=!0,ni|=a.F.na(pg+6)<<16));a.O("dumpIDT("+u(We)+"): "+Jn+r(gs,4)+":"+r(ni,Ln?8:4))}}else a.O("no IDT vector")}else if("dt"==ia)P.shift(),a.O("no information");else{var de=Yq(a,ja);if(de&&(null!=de.Z||null!=de.Da)){var qg=0;Ha&&("l"==Ha.charAt(0)&&(Ha=Ha.substr(1)||Xa),qg=Dq(a,Ha)>>>
0,65536<qg&&(qg=65536));for(var rd="",rg="dd"==ia?4:"dw"==ia?2:1,sg=rg*qg||128,hs=sg+15>>4||1;hs--&&0<sg;){var tg=0,oi=0,Xe,Ye="",pi="",ja=Rq(de);for(Xe=16;0<Xe&&0<sg;Xe--){var ug=a.Qa(de,1),tg=tg|ug<<(oi++<<3);oi==rg&&(Ye+=r(tg,2*rg),Ye+=1==rg?9==Xe?"-":" ":" ",tg=oi=0);pi+=32<=ug&&128>ug?String.fromCharCode(ug):".";sg--}rd&&(rd+="\n");rd+=ja+" "+Ye+(0==Xe?" "+pi:"")}rd&&a.O(rd);a.Db=de}}}}}break;case "e":if("else"==g[0])break;var vg=1,Mn=255,Nn=a.Qa,On=a.qc;"ew"==g[0]&&(vg=2,Mn=65535,Nn=a.na,
a.O(Vb))}else if("symbols"==ja)for(var wa=0;wa<a.B.length;wa++){var Vd=a.B[wa],Qc;for(Qc in Vd.Sd)if("."!=Qc.charAt(0)){var Wd=Vd.Sd[Qc],Je=Wd.o;if(void 0!==Je){var Xd=Wd.s;void 0===Xd&&(Xd=Vd.Z);var Ke=Vd.Sd[Qc].l;Ke&&(Qc=Ke);a.O(Hq(Je,Xd)+" "+Qc)}}}else{if("ds"==ia||"dg"==ia||"dl"==ia)ia="d",P=[ia,"desc",ja];"d"==ia&&"page"==ja&&(ia="dp",P.shift());if("dp"==ia){P.shift();var ki=P[0];if(ki){var Ue=a.dc(Yq(a,ki));if(-1===Ue)a.O("invalid address: "+ki);else{var be,Da=null;if(80386<=a.F.ja){var ce=
a.ea,Da={};Da.ck=(Ue&-4194304)>>>20;Da.vi=a.F.Pd+Da.ck;Da.yb=ce.sa[(Da.vi&ce.Hb)>>>ce.La];Da.Vi=Da.yb.Nd(Da.ck);Da.dk=(Ue&4190208)>>>10;Da.wi=(Da.Vi&-4096)+Da.dk;Da.zb=ce.sa[(Da.wi&ce.Hb)>>>ce.La];Da.Wi=Da.zb.Nd(Da.dk);Da.Gk=(Da.Wi&-4096)+(Ue&4095)}if(be=Da){a.O("linear PDE addr PDE PTE addr PTE physical");a.O("--------- ---------- -------- ---------- -------- ----------");var pd="%"+r(Ue),pd=pd+(" %%"+cr(be.vi,be.Vi)),pd=pd+(" %%"+cr(be.wi,be.Wi,!0)),
pd=pd+(" %%"+r(be.Gk));a.O(pd)}else a.O("unsupported operation")}}else a.O("missing address")}else{if("d"==ia){if("disk"==ja){P[0]="l";P[1]="json";Ir(a,P);break a}for(bb in vq)if(P[1]==bb){var Dn=a.$a[bb];Dn?(P.shift(),P.shift(),Dn(P)):a.O("no dump registered for "+ja);break a}ja||(ia=a.Cc||"db")}else a.Cc=ia;if("dh"==ia){var En=ja,Fn=Ha,Gn="",Hn=0,tb=a.Fa,sc=a.ia;if(sc.length){var Eb=+En||a.Ub,de=+Fn||10;isNaN(Eb)?Eb=de:Gn="more ";Eb>sc.length&&(a.O("note: only "+sc.length+" available"),Eb=sc.length);
tb-=Eb;0>tb&&(null==sc[sc.length-1].Z?(Eb=tb+Eb,tb=0):tb+=sc.length);var li=[];"call"==Fn&&(de=1E5,li=["CALL"]);for(void 0!==En&&a.O(Eb+" instructions earlier:");0<de&&tb!=a.Fa;){var qd=sc[tb++];if(null==qd.Z)break;var Ve=hq(a,qd.Ra,qd.Z,qd.Da,qd.type,qd.Rb,qd.oc),fs=Eb--,In=qr(a,Ve,"history",fs);(!li.length||0<=In.indexOf(li[0]))&&a.O(In);Ve.Te&&(tb+=Ve.Te,de-=Ve.Te,Eb-=Ve.Te);tb>=sc.length&&(tb=0);a.Ub=Eb;Hn++;de--}}Hn||(a.O("no "+Gn+"history available"),a.Ub=void 0)}else if("di"==ia){P.shift();
var mi=P[0];if(mi){var We=Dq(a,mi);if(void 0===We||0>We||255<We)a.O("invalid vector: "+mi);else{var Jn="&",Kn=!!(a.F.Za&1),Ln=!1,pg=a.F.Mc+(We<<(Kn?3:2)),ni=a.F.na(pg+0),gs=a.F.na(pg+2);Kn&&(Jn="#",a.F.na(pg+4)&2048&&(Ln=!0,ni|=a.F.na(pg+6)<<16));a.O("dumpIDT("+u(We)+"): "+Jn+r(gs,4)+":"+r(ni,Ln?8:4))}}else a.O("no IDT vector")}else if("dt"==ia)P.shift(),a.O("no information");else{var ee=Yq(a,ja);if(ee&&(null!=ee.Z||null!=ee.Da)){var qg=0;Ha&&("l"==Ha.charAt(0)&&(Ha=Ha.substr(1)||Xa),qg=Dq(a,Ha)>>>
0,65536<qg&&(qg=65536));for(var rd="",rg="dd"==ia?4:"dw"==ia?2:1,sg=rg*qg||128,hs=sg+15>>4||1;hs--&&0<sg;){var tg=0,oi=0,Xe,Ye="",pi="",ja=Rq(ee);for(Xe=16;0<Xe&&0<sg;Xe--){var ug=a.Qa(ee,1),tg=tg|ug<<(oi++<<3);oi==rg&&(Ye+=r(tg,2*rg),Ye+=1==rg?9==Xe?"-":" ":" ",tg=oi=0);pi+=32<=ug&&128>ug?String.fromCharCode(ug):".";sg--}rd&&(rd+="\n");rd+=ja+" "+Ye+(0==Xe?" "+pi:"")}rd&&a.O(rd);a.Db=ee}}}}}break;case "e":if("else"==g[0])break;var vg=1,Mn=255,Nn=a.Qa,On=a.qc;"ew"==g[0]&&(vg=2,Mn=65535,Nn=a.na,
On=a.jb);var Pn=vg<<1,Qn=g[1];if(null==Qn)a.O("edit memory commands:"),a.O("\teb [a] [...] edit bytes at address a"),a.O("\tew [a] [...] edit words at address a");else{var wg=Yq(a,Qn);if(wg)for(var xg=2;xg<g.length;xg++){var Ze=$q(a,g[xg]);if(void 0===Ze){a.O("unrecognized value: "+g[xg]);break}Ze&~Mn&&a.O("warning: "+r(Ze)+" exceeds "+vg+"-byte value");var is=Nn.call(a,wg);a.O("changing "+Rq(wg)+" from 0x"+r(is,Pn)+" to 0x"+r(Ze,Pn));On.call(a,wg,Ze,vg)}}break;case "f":Fr(a,g[1]);break;case "g":a:{var Rn=
g[1],js=b;"gt"==g[0]&&(a.cb=!0);if(void 0!==Rn){var qi=Yq(a,Rn,!0);if(!qi)break a;ar(a,qi,js);a.Td(a.A,qi,!0)}a.Le(!0)||c||a.O("cpu busy or unavailable, run command ignored")}break;case "h":a:{var ri;if(a.la.Fb)ri="halting",a.Wb();else{if(qb(a,!0))break a;ri="already halted"}c||a.O(ri)}break;case "i":if("if"==g[0]){var si;var $e=b.substr(2),$e=na($e);$q(a,$e)?(c||a.O("true: "+$e),si=!0):(c||a.O("false: "+$e),si=!1);si||(d=!1);break}if("int"==g[0]){var yg;a:switch(Dq(a,g[1])){case 19:kk(a,19,a.F.Ga,
!0);a.ya=a.pa;yg=!0;break a;case 33:kk(a,33,a.F.Ga,!0);a.ya=a.pa;yg=!0;break a;default:yg=!1}yg||(d=!1);break}var ti=g[1];if(ti&&"?"!=ti){var ui=Dq(a,ti);if(void 0!==ui){var ks=jc(a.ea,ui,1);a.O(u(ui)+": "+t(ks))}}else a.O("input commands:"),a.O("\ti [p]\tread port [p]"),a.O("warning: port accesses can affect hardware state");break;case "k":var ls=g[0];if("?"==g[1])a.O("stack trace commands:"),a.O("\tk\tshow frame addresses"),a.O("\tks\tshow symbol information");else{var vi=0,Sn=a.F.va.Z,af=hq(a),
Sc=hq(a,I(a.F),a.F.ta.Z);for(a.O("stack trace for "+Rq(Sc));10>vi;){for(var tc=null,ms=256;Sc.Ra>>>0<a.F.Mg>>>0;){af.Ra=a.tb(Sc,!0);if(null==Sc.Da||!ms--)break;af.Z=Sn;if(tc=Kr(a,af))break;af.Z=a.tb(Sc);if(tc=Kr(a,af,!0)){Sn=a.tb(Sc,!0);0<tc.indexOf("INT")&&a.tb(Sc,!0);break}}if(!tc||null==tc)break;var Tn=null;if("ks"==ls){var Un=tc.match(/[0-9A-F]+$/);Un&&(Tn=Hr(a,Un[0]))}tc=ma(tc,50)+" ;"+(Tn||"stack="+Rq(Sc));a.O(tc);vi++}vi||a.O("no return addresses found")}break;case "l":if("ln"==g[0]){Hr(a,
g[1],!0);break}Ir(a,g);break;case "m":if("mouse"==g[0]){var wi=g[1],zg=g[2];if(a.W){var Vn=1;"-"==zg.charAt(0)&&(Vn=-1,zg=zg.substr(1));var sd=Dq(a,zg,wi);if(void 0!==sd)switch(sd=sd*Vn|0,wi){case "x":a.W.If(sd,0);break;case "y":a.W.If(0,sd);break;case "click":a.W.je(sd,!0);a.W.je(sd,!1);break;default:a.O("unknown action: "+wi)}}else a.O("no mouse");break}a:{var uc,vc=null,Oa=g[1];"?"==Oa&&(Oa=void 0);if(void 0!==Oa){var td=0;if("all"==Oa)td=1610481663,Oa=null;else if("on"==Oa)vc=!0,Oa=null;else if("off"==
Oa)vc=!1,Oa=null;else{"keys"==Oa&&(Oa="key");"kbd"==Oa&&(Oa="keyboard");for(uc in vq)if(Oa==uc){td=vq[uc];vc=!!(a.wc&td);break}if(!td){a.O("unknown message category: "+Oa);break a}}td&&("on"==g[2]?(a.wc|=td,vc=!0):"off"==g[2]&&(a.wc&=~td,vc=!1))}var ns=0,Tc="";for(uc in vq)if(!Oa||Oa==uc){var os=!!(a.wc&vq[uc]);if(null===vc||vc==os)Tc&&(Tc+=","),++ns%10||(Tc+="\n\t"),"key"==uc&&(uc="keys"),Tc+=uc}void 0===Oa&&a.O("message commands:\n\tm [category] [on|off]\tturn categories on/off");a.O((null!==vc?
vc?"messages on: ":"messages off: ":"message categories:\n\t")+(Tc||"none"));jq(a)}break;case "o":var xi=g[1],ps=g[2];if(xi&&"?"!=xi){var yi=Dq(a,xi,"port #"),zi=Dq(a,ps);void 0!==yi&&void 0!==zi&&(nc(a.ea,yi,1,zi),a.O(u(yi)+": "+t(zi)))}else a.O("output commands:"),a.O("\to [p] [b]\twrite byte [b] to port [p]"),a.O("warning: port accesses can affect hardware state");break;case "p":if("print"==g[0]){Jr(a,b.substr(5));break}var Wn="pr"==g[0]?1:0,ee=1+Wn;if(a.N)a.O("step in progress");else{var Ag,
Xn=!1,lb=hq(a,K(a.F),a.F.va.Z);do switch(Ag=!1,a.Qa(lb)){case 38:case 46:case 54:case 62:case 100:case 101:case 102:case 103:case 240:Tq(a,lb,1);Ag=!0;break;case 204:case 206:a.N=ee;Tq(a,lb,1);break;case 205:case 224:case 225:case 226:a.N=ee;Tq(a,lb,lb.Rb?4:2);break;case 232:a.N=ee;Tq(a,lb,lb.Rb?5:3);break;case 154:a.N=ee;Tq(a,lb,lb.Rb?7:5);break;case 255:var Yn=a.tb(lb)&14591;if(4351==Yn||6399==Yn)a.N=ee,qr(a,lb);break;case 243:case 242:Tq(a,lb,1);Xn=Ag=!0;break;case 108:case 109:case 110:case 111:case 164:case 165:case 166:case 167:case 170:case 171:case 172:case 173:case 174:case 175:Xn&&
(a.N=ee,Tq(a,lb,1))}while(Ag);a.N?(a.Td(a.A,lb,!0),a.Le()||(a.V&&a.V.yd(),a.N=0)):Lr(a,Wn?"tr":"t")}break;case "r":if("reset"==b){a.V&&a.V.reset();break}ir(a,g);break;case "t":Lr(a,g[0],g[1]);break;case "u":jr(a,g[1],g[2],8);break;case "v":if("var"==g[0]){Gr(a,b.substr(3))||(d=!1);break}a.O("PCx86 version 1.24.0 ("+a.F.ja+",RELEASE,NOPREFETCH"+(vb?",TYPEDARRAYS":",LONGARRAYS")+",NOBACKTRACK)");a.O(ya());break;case "x":a:if(g[1]&&"?"!=g[1])switch(g[1]){case "cs":var bf;void 0!==g[3]&&(bf=+g[3]);switch(g[2]){case "int":a.F.Y.kf=
vc?"messages on: ":"messages off: ":"message categories:\n\t")+(Tc||"none"));jq(a)}break;case "o":var xi=g[1],ps=g[2];if(xi&&"?"!=xi){var yi=Dq(a,xi,"port #"),zi=Dq(a,ps);void 0!==yi&&void 0!==zi&&(nc(a.ea,yi,1,zi),a.O(u(yi)+": "+t(zi)))}else a.O("output commands:"),a.O("\to [p] [b]\twrite byte [b] to port [p]"),a.O("warning: port accesses can affect hardware state");break;case "p":if("print"==g[0]){Jr(a,b.substr(5));break}var Wn="pr"==g[0]?1:0,fe=1+Wn;if(a.N)a.O("step in progress");else{var Ag,
Xn=!1,lb=hq(a,K(a.F),a.F.va.Z);do switch(Ag=!1,a.Qa(lb)){case 38:case 46:case 54:case 62:case 100:case 101:case 102:case 103:case 240:Tq(a,lb,1);Ag=!0;break;case 204:case 206:a.N=fe;Tq(a,lb,1);break;case 205:case 224:case 225:case 226:a.N=fe;Tq(a,lb,lb.Rb?4:2);break;case 232:a.N=fe;Tq(a,lb,lb.Rb?5:3);break;case 154:a.N=fe;Tq(a,lb,lb.Rb?7:5);break;case 255:var Yn=a.tb(lb)&14591;if(4351==Yn||6399==Yn)a.N=fe,qr(a,lb);break;case 243:case 242:Tq(a,lb,1);Xn=Ag=!0;break;case 108:case 109:case 110:case 111:case 164:case 165:case 166:case 167:case 170:case 171:case 172:case 173:case 174:case 175:Xn&&
(a.N=fe,Tq(a,lb,1))}while(Ag);a.N?(a.Td(a.A,lb,!0),a.Le()||(a.V&&a.V.yd(),a.N=0)):Lr(a,Wn?"tr":"t")}break;case "r":if("reset"==b){a.V&&a.V.reset();break}ir(a,g);break;case "t":Lr(a,g[0],g[1]);break;case "u":jr(a,g[1],g[2],8);break;case "v":if("var"==g[0]){Gr(a,b.substr(3))||(d=!1);break}a.O("PCx86 version 1.24.0 ("+a.F.ja+",RELEASE,NOPREFETCH"+(vb?",TYPEDARRAYS":",LONGARRAYS")+",NOBACKTRACK)");a.O(ya());break;case "x":a:if(g[1]&&"?"!=g[1])switch(g[1]){case "cs":var bf;void 0!==g[3]&&(bf=+g[3]);switch(g[2]){case "int":a.F.Y.kf=
bf;break;case "start":a.F.Y.Kf=bf;break;case "stop":a.F.Y.mf=bf;break;default:a.O("unknown cs option");break a}void 0!==bf&&Pc(a.F);a.O("checksums "+(a.F.la.Ze?"enabled":"disabled"));break;case "sp":void 0!==g[2]&&(Xc(a.F,+g[2])||a.O("warning: using 1x multiplier, previous target not reached"));a.O("target speed: "+(a.F.Y.Fe.toFixed(2)+"Mhz")+" ("+a.F.Y.Zd+"x)");break;default:a.O("unknown option: "+g[1])}else a.O("execution options:"),a.O("\tcs int #\tset checksum cycle interval to #"),a.O("\tcs start #\tset checksum cycle start count to #"),
a.O("\tcs stop #\tset checksum cycle stop count to #"),a.O("\tsp #\t\tset speed multiplier to #");break;case "?":if(g[1]){Jr(a,b.substr(1));break}var cf="commands:",Ai;for(Ai in oq)cf+="\n"+ma(Ai,7)+oq[Ai];Tf(a)||(cf+="\nnote: frequency/history disabled if no exec breakpoints");a.O(cf);break;default:a.O("unknown command: "+b),d=!1}}}catch(Zn){a.O("debugger error: "+(Zn.stack||Zn.message)),d=!1}return d}function lq(a,b,c){b=br(a,b,c);for(var d in b)if(!pr(a,b[d]))return!1;return!0}
Qa(function(){for(var a=nb(document,"pcx86","debugger"),b=0;b<a.length;b++){var c=a[b],d=jb(c),d=new gq(d);mb(d,c)}});function hf(a,b,c){this.id=a.id;this.key=Nr(a,b,c);this.ha=a.ha;Or(this,a.hk)}function Nr(a,b,c){a=a.id;if(b){var d=b.indexOf(".");0<d&&(a+=".v"+b.substr(0,d))}c&&(a+="."+c);return a}
hf.prototype={constructor:hf,value:function(){return this[this.id]},data:function(){return this[this.id]},load:function(a){return a?(this[this.id]=a,this.A=!0):this.A?!0:Ca()&&(a=Ea(this.key))?(this[this.id]=a,this.A=!0):!1},toString:function(){var a=this[this.id];return"string"==typeof a?a:JSON.stringify(a)},clear:function(a){Or(this);var b=[];try{for(var c=0,d=window.localStorage.length;c<d;c++)b.push(window.localStorage.key(c))}catch(e){}for(c=0;c<b.length;c++)if((d=b[c])&&(a||d.substr(0,this.key.length)==
this.key)){try{window.localStorage.removeItem(d)}catch(e){}b.splice(c,1);c=0}}};function Or(a,b){a[a.id]={};b&&N(a,"parms",b);a.A=!1}function Pr(a){var b=!0;if(Ca()){var c=JSON.stringify(a[a.id]);Fa(a.key,c)||(w("Unable to store "+c.length+" bytes in browser local storage"),b=!1)}return b}function Qr(a){var b=!0;try{a[a.id]=JSON.parse(a[a.id])}catch(c){w(c.message||c),b=!1}return b}function Rr(a,b){return a[a.id][b]||null}function N(a,b,c){try{a[a.id][b]=c}catch(d){}}
function Sr(a,b,c){Ua.call(this,"Computer",a,Sr,67108864);this.la.cc=!1;Tr(this,b);this.ga=Nc(this,"autoPower",a);this.N=0;this.ra=a.busWidth||a.buswidth;this.A=Ur;this.aa=null;this.W=this.pa=!1;this.ua=Nc(this,"url")||"";this.ya=(Math.random()+.1).toString(36).substr(2,12);this.B=Vr(this);if(this.F=ib("CPU",this.id)){this.ha=ib("Debugger",this.id);this.L=[];for(b=null;b=Eb(this,"Video",b);)this.L.push(b);this.ea=new Lb({id:this.ve+".bus",busWidth:this.ra},this.F,this.ha);var d,e=gb(this.id);if((this.C=
ib("Panel",this.id))&&this.C.Ef)for(b=0;b<e.length;b++)d=e[b],d.Na=this.C.Na,d.O=this.C.O,d.Ef=this.C.Ef;this.O("PCx86 v1.24.0\nCopyright \u00a9 2012-2016 Jeff Parsons <Jeff@pcjs.org>\nLicense: GPL version 3 or later <http://gnu.org/licenses/gpl.html>");for(b=0;b<e.length;b++)d=e[b],d.Ic&&d.Ic(this,this.ea,this.F,this.ha);b=null;d=a.resume;void 0!==d&&(1<d.length?b=this.X=d:this.A=parseInt(d,10));var f;if(a=Nc(this,"state")||(f=!0,a.state))b=this.ia=a,f||(this.W=!0,this.A=Ur),this.A&&(this.fa=new hf(this,
"1.24.0"),this.fa.load()?b=null:delete this.fa);!b&&this.A&&(b=Wr(this))&&(this.W=!0);if(b){var g=this;va(b,null,!0,function(a,b,c){c?(g.X=null,g.W=!1,g.Na("Unable to load machine state from server (error "+c+(b?": "+na(b):"")+")")):(g.aa=b,g.pa=!0);rb(g)})}else rb(this);this.qa.power||(this.ga=!0);!c&&this.ga&&Xr(this,this.ag)}else w("Unable to find CPU component")}db(Sr);var Ur=0;m=Sr.prototype;m.gf=function(){return this.ya};
function Tr(a,b){if(!b){var c;if("object"==typeof resources&&(c=resources.parms))try{b=eval("("+c+")")}catch(d){w(d.message+" ("+c+")")}}a.U=b}function Nc(a,b,c){var d=b.toLowerCase(),d=Ya[b]||Ya[d];void 0===d&&a.U&&(d=a.U[b]);void 0===d&&c&&(d=c[b]);void 0===d&&"object"==typeof resources&&resources[b]&&(d=b);return d}m.ke=function(){return this.B||""};function Xr(a,b,c){for(var d=gb(a.id),e=0;e<=d.length;e++){var f=e<d.length?d[e]:a;if(!sb(f)){sb(f,function(){Xr(a,b,c)});return}}b.call(a,c)}
function Yr(a,b){var c=new hf(a,"1.24.0","validate");if(c.load()&&Qr(c)){var d=Rr(c,"timestamp"),e=b?Rr(b,"timestamp"):"unknown";d!=e&&(a.Na("Machine state may be out-of-date\n("+d+" vs. "+e+")\nCheck your browser's local storage limits"),b||c.clear())}}
m.ag=function(a){void 0===a&&(a=this.A||(this.aa?1:Ur));if(!this.N){this.N++;var b=!1,c=!1;this.ka=!1;var d=this.fa||new hf(this,"1.24.0");if(-1==a)b=!0;else if(a>Ur){if(d.load(this.aa)){this.V=new hf(this,"1.24.0","failsafe");this.V.load()&&(Zr(this,d),a=2,Or(this.V));N(this.V,"timestamp",qa());Pr(this.V);var e=this.A&&!this.W;if(1==a||za("Click OK to restore the previous PCx86 machine state, or CANCEL to reset the machine.")){if(c=Qr(d)){var f=Rr(d,"code"),g=Rr(d,"data");f&&("ok"==f?d.load(g):("error"==
f&&"no machine state"!=g?(this.Na("Error: "+g),"unable to verify user"==g&&(Fa("user",""),this.B=null)):this.O(f+": "+g),Or(d),d.load()?(c=Qr(d),e=!0):c=!1))}e&&Yr(this,c?d:null)}else 2==a&&d.clear()}else Yr(this);delete this.aa;delete this.fa}e=gb(this.id);for(f=0;f<e.length;f++)g=e[f],g!==this&&g!=this.F&&(c=$r(this,g,d,b,c));b=[d,a,c];-1!=a?Xr(this,this.Ji,b):this.Ji(b)}};
function $r(a,b,c,d,e){if(!b.la.cc){b.la.cc=!0;if(b.ic){var f=null;e&&((f=Rr(c,b.id))||(f=Rr(c,b.id.replace(/[a-z0-9]\./i,"."))));"string"===typeof f&&(f=null);!b.ic(f,d)&&f&&(w("Unable to restore state for "+b.type),a.ia&&!a.pa?(c.clear(),a.A=Ur,window&&window.location.reload()):a.ka=!0,b.ic(null),e=!1)}if(!d&&b.uk)for(a=b.uk.split("|"),c=0;c<a.length;c++)b.status(a[c])}return e}
m.Ji=function(a){var b=a[0],c=0>a[1];a=a[2];this.wa=!0;this.la.cc=!0;var d=this.qa.power;d&&(d.textContent="Shutdown");this.F&&($r(this,this.F,b,c,a),Uc(this.F));this.ka&&(Zr(this,b),b.clear());!c&&this.V&&(this.V.clear(),delete this.V);this.N=0};
function Zr(a,b){if(za("There may be a problem with your PCx86 machine.\n\nTo help us diagnose it, click OK to send this PCx86 machine state to http://www.pcjs.org.")){var c=a.ke(),d=b.toString(),e={app:"PCx86",ver:"1.24.0"};e.url=a.ua;e.user=c;e.type="bug";e.data=d;va("http://www.pcjs.org/api/v1/report",e,!0)}}
Qa(function(){for(var a=nb(document,"pcx86","debugger"),b=0;b<a.length;b++){var c=a[b],d=jb(c),d=new gq(d);mb(d,c)}});
function Nr(a,b,c){Ua.call(this,"Computer",a,Nr,67108864);this.la.cc=!1;Or(this,b);this.ga=Nc(this,"autoPower",a);this.N=0;this.ra=a.busWidth||a.buswidth;this.A=Pr;this.aa=null;this.W=this.pa=!1;this.ua=Nc(this,"url")||"";this.ya=(Math.random()+.1).toString(36).substr(2,12);this.B=Qr(this);if(this.F=ib("CPU",this.id)){this.ha=ib("Debugger",this.id);this.L=[];for(b=null;b=Db(this,"Video",b);)this.L.push(b);this.ea=new Lb({id:this.ve+".bus",busWidth:this.ra},this.F,this.ha);var d,e=gb(this.id);if((this.C=
ib("Panel",this.id))&&this.C.Ef)for(b=0;b<e.length;b++)d=e[b],d.Na=this.C.Na,d.O=this.C.O,d.Ef=this.C.Ef;this.O("PCx86 v1.24.0\nCopyright \u00a9 2012-2016 Jeff Parsons <Jeff@pcjs.org>\nLicense: GPL version 3 or later <http://gnu.org/licenses/gpl.html>");for(b=0;b<e.length;b++)d=e[b],d.Ic&&d.Ic(this,this.ea,this.F,this.ha);b=null;d=a.resume;void 0!==d&&(1<d.length?b=this.X=d:this.A=parseInt(d,10));var f;if(a=Nc(this,"state")||(f=!0,a.state))b=this.ia=a,f||(this.W=!0,this.A=Pr),this.A&&(this.fa=new hf(this,
"1.24.0"),this.fa.load()?b=null:delete this.fa);!b&&this.A&&(b=Rr(this))&&(this.W=!0);if(b){var g=this;va(b,null,!0,function(a,b,c){c?(g.X=null,g.W=!1,g.Na("Unable to load machine state from server (error "+c+(b?": "+na(b):"")+")")):(g.aa=b,g.pa=!0);rb(g)})}else rb(this);this.qa.power||(this.ga=!0);!c&&this.ga&&Sr(this,this.ag)}else w("Unable to find CPU component")}db(Nr);var Pr=0;m=Nr.prototype;m.gf=function(){return this.ya};
function Or(a,b){if(!b){var c;if("object"==typeof resources&&(c=resources.parms))try{b=eval("("+c+")")}catch(d){w(d.message+" ("+c+")")}}a.U=b}function Nc(a,b,c){var d=b.toLowerCase(),d=Ya[b]||Ya[d];void 0===d&&a.U&&(d=a.U[b]);void 0===d&&c&&(d=c[b]);void 0===d&&"object"==typeof resources&&resources[b]&&(d=b);return d}m.ke=function(){return this.B||""};function Sr(a,b,c){for(var d=gb(a.id),e=0;e<=d.length;e++){var f=e<d.length?d[e]:a;if(!sb(f)){sb(f,function(){Sr(a,b,c)});return}}b.call(a,c)}
function Tr(a,b){var c=new hf(a,"1.24.0","validate");if(c.load()&&Ur(c)){var d=Vr(c,"timestamp"),e=b?Vr(b,"timestamp"):"unknown";d!=e&&(a.Na("Machine state may be out-of-date\n("+d+" vs. "+e+")\nCheck your browser's local storage limits"),b||c.clear())}}
m.ag=function(a){void 0===a&&(a=this.A||(this.aa?1:Pr));if(!this.N){this.N++;var b=!1,c=!1;this.ka=!1;var d=this.fa||new hf(this,"1.24.0");if(-1==a)b=!0;else if(a>Pr){if(d.load(this.aa)){this.V=new hf(this,"1.24.0","failsafe");this.V.load()&&(Wr(this,d),a=2,Xr(this.V));N(this.V,"timestamp",qa());Yr(this.V);var e=this.A&&!this.W;if(1==a||za("Click OK to restore the previous PCx86 machine state, or CANCEL to reset the machine.")){if(c=Ur(d)){var f=Vr(d,"code"),g=Vr(d,"data");f&&("ok"==f?d.load(g):("error"==
f&&"no machine state"!=g?(this.Na("Error: "+g),"unable to verify user"==g&&(Fa("user",""),this.B=null)):this.O(f+": "+g),Xr(d),d.load()?(c=Ur(d),e=!0):c=!1))}e&&Tr(this,c?d:null)}else 2==a&&d.clear()}else Tr(this);delete this.aa;delete this.fa}e=gb(this.id);for(f=0;f<e.length;f++)g=e[f],g!==this&&g!=this.F&&(c=Zr(this,g,d,b,c));b=[d,a,c];-1!=a?Sr(this,this.Ji,b):this.Ji(b)}};
function Zr(a,b,c,d,e){if(!b.la.cc){b.la.cc=!0;if(b.ic){var f=null;e&&((f=Vr(c,b.id))||(f=Vr(c,b.id.replace(/[a-z0-9]\./i,"."))));"string"===typeof f&&(f=null);!b.ic(f,d)&&f&&(w("Unable to restore state for "+b.type),a.ia&&!a.pa?(c.clear(),a.A=Pr,window&&window.location.reload()):a.ka=!0,b.ic(null),e=!1)}if(!d&&b.uk)for(a=b.uk.split("|"),c=0;c<a.length;c++)b.status(a[c])}return e}
m.Ji=function(a){var b=a[0],c=0>a[1];a=a[2];this.wa=!0;this.la.cc=!0;var d=this.qa.power;d&&(d.textContent="Shutdown");this.F&&(Zr(this,this.F,b,c,a),Uc(this.F));this.ka&&(Wr(this,b),b.clear());!c&&this.V&&(this.V.clear(),delete this.V);this.N=0};
function Wr(a,b){if(za("There may be a problem with your PCx86 machine.\n\nTo help us diagnose it, click OK to send this PCx86 machine state to http://www.pcjs.org.")){var c=a.ke(),d=b.toString(),e={app:"PCx86",ver:"1.24.0"};e.url=a.ua;e.user=c;e.type="bug";e.data=d;va("http://www.pcjs.org/api/v1/report",e,!0)}}
function Mr(a,b,c){var d,e="none";if(a.N)return null;a.N--;var f=new hf(a,"1.24.0"),g=new hf(a,"1.24.0","validate"),h=qa();N(g,"timestamp",h);N(f,"timestamp",h);N(f,"version","1.24.0");N(f,"url",window?window.location.href:null);N(f,"browser",ya());a.F&&a.F.hc&&(c&&a.F.Wb(),d=a.F.hc(b,c),"object"===typeof d&&N(f,a.F.id,d),c&&(a.F.la.cc=!1,!1===d&&(e=null)));for(var h=gb(a.id),k=0;k<h.length;k++){var l=h[k];l.la.cc&&(l.hc&&(d=l.hc(b,c),"object"===typeof d&&N(f,l.id,d)),c&&(l.la.cc=!1,!1===d&&(e=null)))}e&&
(c?(h=d=!1,b?(a.B&&as(a,a.B,f.toString()),Pr(g)&&Pr(f)||(e=null,d=h=!0)):a.A&&(d=!0,h=3==a.A),d&&f.clear(h)):e=f.toString());c&&(a.la.cc=!1,b=a.qa.power)&&(b.textContent="Power");a.N=0;return e}m.reset=function(){this.ea&&this.ea.reset&&(y(this,"Resetting "+this.ea.type),this.ea.reset());for(var a=gb(this.id),b=0;b<a.length;b++){var c=a[b];c!==this&&c!==this.ea&&c.reset&&(y(this,"Resetting "+c.type),c.reset())}};
(c?(h=d=!1,b?(a.B&&$r(a,a.B,f.toString()),Yr(g)&&Yr(f)||(e=null,d=h=!0)):a.A&&(d=!0,h=3==a.A),d&&f.clear(h)):e=f.toString());c&&(a.la.cc=!1,b=a.qa.power)&&(b.textContent="Power");a.N=0;return e}m.reset=function(){this.ea&&this.ea.reset&&(y(this,"Resetting "+this.ea.type),this.ea.reset());for(var a=gb(this.id),b=0;b<a.length;b++){var c=a[b];c!==this&&c!==this.ea&&c.reset&&(y(this,"Resetting "+c.type),c.reset())}};
m.start=function(a,b){for(var c=gb(this.id),d=0;d<c.length;d++){var e=c[d];"CPU"!=e.type&&e!==this&&e.start&&e.start(a,b)}};m.stop=function(a,b){for(var c=gb(this.id),d=0;d<c.length;d++){var e=c[d];"CPU"!=e.type&&e!==this&&e.stop&&e.stop(a,b)}};
m.Pb=function(a,b,c){var d=this;switch(b){case "power":return this.qa[b]=c,c.onclick=function(){d.N||(d.la.cc?Mr(d,!1,!0):Xr(d,d.ag))},!0;case "reset":return this.qa[b]=c,c.onclick=function(){if(d.la.cc&&!d.N)if(d.A&&!d.X){var a=za("Click OK to save changes to this PCx86 machine.\n\nWARNING: If you CANCEL, all disk changes will be discarded.");Mr(d,a,!0);!a&&d.ia?window&&window.location.reload():(a||(d.eh=!0),d.ag(Ur),d.eh=!1)}else d.reset(),d.F&&Uc(d.F)},!0;case "save":if(ha(xa(),"pcjs.org")){c.parentNode.removeChild(c);
break}this.qa[b]=c;c.onclick=function(){var a=Vr(d,!0);if(a){var b=!!(d.A&&!d.X||d.ia),c=Mr(d,b);b?as(d,a,c):d.Na("Resume disabled, machine state not saved")}};return!0}return!1};
function Vr(a,b){var c=a.B;c||(c=Ea("user"),void 0!==c?!c&&b&&(c=null,window&&(c=window.prompt("Saving machine states on the pcjs.org server is currently unsupported.\n\nIf you're running your own server, enter your user ID below.","")),c&&((c=bs(a,c))||a.Na("The user ID is invalid."))):b&&a.Na("Browser local storage is not available"));return c}
function bs(a,b){a.B=null;var c=va(xa()+"/api/v1/user?req=verify&user="+b),d=c[1];if(!c[0]&&d)try{c=eval("("+d+")"),c.code&&"ok"==c.code&&(Fa("user",c.data),a.B=c.data)}catch(e){w(e.message+" ("+d+")")}return a.B}function Wr(a){var b=null;a.B&&(b=xa()+"/api/v1/user?req=load&user="+a.B+"&state="+Nr(a,"1.24.0"));return b}
function as(a,b,c){if(c){var d={req:"store"};d.user=b;d.state=Nr(a,"1.24.0");d.data=c;b=va(xa()+"/api/v1/user",d);d=b[0];if(b[1]){if(d){var e=d.indexOf("\n");0<e&&(d=d.substr(0,e));d.indexOf("Error: ")||(d=d.substr(7))}d='{"code":'+b[1]+',"data":"'+d+'"}'}b=JSON.parse(d);b&&"ok"==b.code?a.Na("Machine state saved to server"):c&&(c=b&&b.data||"unable to save machine state",c="error"==b.code?"Error: "+c:"Error "+b.code+": "+c,a.Na(c),Fa("user",""),a.B=null)}}
function Eb(a,b,c){a=gb(a.id);for(var d=0;d<a.length;d++){var e=a[d];if(c)c==e&&(c=null);else if(e.type==b)return e}return null}m.yd=function(a){if(this.L.length){var b=0,c=0;a&&window&&(b=window.scrollX,c=window.scrollY);var d=this.L[0];d.V&&d.V.focus();a&&window&&window.scrollTo(b,c)}};m.qd=function(a){this.F&&this.F.qd(a);this.C&&this.C.qd(a)};
m.Pb=function(a,b,c){var d=this;switch(b){case "power":return this.qa[b]=c,c.onclick=function(){d.N||(d.la.cc?Mr(d,!1,!0):Sr(d,d.ag))},!0;case "reset":return this.qa[b]=c,c.onclick=function(){if(d.la.cc&&!d.N)if(d.A&&!d.X){var a=za("Click OK to save changes to this PCx86 machine.\n\nWARNING: If you CANCEL, all disk changes will be discarded.");Mr(d,a,!0);!a&&d.ia?window&&window.location.reload():(a||(d.eh=!0),d.ag(Pr),d.eh=!1)}else d.reset(),d.F&&Uc(d.F)},!0;case "save":if(ha(xa(),"pcjs.org")){c.parentNode.removeChild(c);
break}this.qa[b]=c;c.onclick=function(){var a=Qr(d,!0);if(a){var b=!!(d.A&&!d.X||d.ia),c=Mr(d,b);b?$r(d,a,c):d.Na("Resume disabled, machine state not saved")}};return!0}return!1};
function Qr(a,b){var c=a.B;c||(c=Ea("user"),void 0!==c?!c&&b&&(c=null,window&&(c=window.prompt("Saving machine states on the pcjs.org server is currently unsupported.\n\nIf you're running your own server, enter your user ID below.","")),c&&((c=as(a,c))||a.Na("The user ID is invalid."))):b&&a.Na("Browser local storage is not available"));return c}
function as(a,b){a.B=null;var c=va(xa()+"/api/v1/user?req=verify&user="+b),d=c[1];if(!c[0]&&d)try{c=eval("("+d+")"),c.code&&"ok"==c.code&&(Fa("user",c.data),a.B=c.data)}catch(e){w(e.message+" ("+d+")")}return a.B}function Rr(a){var b=null;a.B&&(b=xa()+"/api/v1/user?req=load&user="+a.B+"&state="+bs(a,"1.24.0"));return b}
function $r(a,b,c){if(c){var d={req:"store"};d.user=b;d.state=bs(a,"1.24.0");d.data=c;b=va(xa()+"/api/v1/user",d);d=b[0];if(b[1]){if(d){var e=d.indexOf("\n");0<e&&(d=d.substr(0,e));d.indexOf("Error: ")||(d=d.substr(7))}d='{"code":'+b[1]+',"data":"'+d+'"}'}b=JSON.parse(d);b&&"ok"==b.code?a.Na("Machine state saved to server"):c&&(c=b&&b.data||"unable to save machine state",c="error"==b.code?"Error: "+c:"Error "+b.code+": "+c,a.Na(c),Fa("user",""),a.B=null)}}
function Db(a,b,c){a=gb(a.id);for(var d=0;d<a.length;d++){var e=a[d];if(c)c==e&&(c=null);else if(e.type==b)return e}return null}m.yd=function(a){if(this.L.length){var b=0,c=0;a&&window&&(b=window.scrollX,c=window.scrollY);var d=this.L[0];d.V&&d.V.focus();a&&window&&window.scrollTo(b,c)}};m.qd=function(a){this.F&&this.F.qd(a);this.C&&this.C.qd(a)};
function cd(a,b){for(var c=0;c<a.L.length;c++)rn(a.L[c],b);if(a.C&&(c=a.C,c.Ja)){Ib(c,18,c.aa,c.Ia);if(c.gb){var d=c.ea,e=c.A,f,g;null==f&&(f=0);null==g&&(g=d.X-f|0);null==e&&(e={ah:0,Vd:0,Sg:[]});var h=f>>>d.La;f=f+g-1>>>d.La;e.ah=0;for(e.Vd=0;h<=f;)g=d.sa[h],e.ah+=g.size,g.size&&(e.Sg.push(sa(Hb,h,0,0,g.type)),e.Vd++),h++;c.A=e;c.ya=c.A.Vd*c.ea.Sb/691200;d=0;c.A.Bi=0;c.A.Bf||(c.A.Bf=[]);var e=-1,h=0,k=-1;for(f=0;f<c.A.Vd;f++){var l=c.A.Sg[f];g=ta(Hb.type,l);l=ta(Hb.ak,l);if(g!=e||l!=k+1)(k=f-h)&&
(d+=Kb(c,h,k,e)),e=g,h=f;k=l}d+=Kb(c,h,f-h,e);e=c.A.Lk!=d;c.A.Lk=d;if(e){e=new Bb(0,0,c.aa.width,c.aa.height);c.A.Qe=[];h=c.A.Vd;for(d=0;d<c.A.Bi;d++)f=c.A.Bf[d].Vd,c.A.Qe.push(Cb(e,f,h,!d)),h-=f;for(d=0;d<c.A.Qe.length;d++)e=c.A.Bf[d],h=f=c.A.Qe[d],g=c.Ia,(k=xc[e.type])||(k=new Ab),g.strokeStyle="black",g.strokeRect(h.x,h.y,h.ad,h.A),g.fillStyle="string"==typeof k?k:k.toString(),g.fillRect(h.x,h.y,h.ad,h.A),h=c,g=f,h.ga=h.ua,h.X=h.wa,f=g.x+(g.ad>>1),k=g.y+(g.A>>1),l=g.A,g.ad<g.A&&(l=g.ad,h.ra=!0,
h.N.save(),h.N.translate(f,k),h.N.rotate(-Math.PI/2),f=k=0),l<h.X&&(h.X=l,h.ga=h.X+"px Monaco, Lucida Console, Courier New"),g=k,h.C=f,h.U=g,h=c,e=Wb[e.type]+" ("+(e.Vd*c.ea.Sb/1024|0)+"Kb)",h.N.font=h.ga,h.C-=h.N.measureText(e).width>>1,h.U+=(h.X>>1)-2,Jb(h,e),h.ra&&(h.N.restore(),h.ra=!1)}}else Jb(c,"This space intentionally left blank");c.context.drawImage(c.aa,0,0,c.aa.width,c.aa.height,c.sb,c.Jb,c.$a,c.fb);c.Ja=!1}}
Qa(function(){for(var a=nb(document,"pcx86-machine"),b=0;b<a.length;b++)for(var c=a[b],d=jb(c),c=nb(c,"pcx86","computer"),e=0;e<c.length;e++){var f=c[e],g=jb(f),g=new Sr(g,d,!0);mb(g,f);g.ga&&Xr(g,g.ag)}});La.show.push(function(){for(var a=nb(document,"pcx86","computer"),b=0;b<a.length;b++){var c=jb(a[b]);(c=ib("Computer",c.id))&&c.wa&&!c.la.cc&&c.ag(-1)}});
La.exit.push(function(){for(var a=nb(document,"pcx86","computer"),b=0;b<a.length;b++){var c=jb(a[b]);(c=ib("Computer",c.id))&&c.la.cc&&Mr(c,!(!c.A||c.X),!0)}});var cs=0;function ds(a,b,c,d,e,f){e("Loading "+a+"...");va(a,null,!0,function(g,h,k){k?(h||(h="unable to load "+a+" ("+k+")"),f(h,null)):es(h,a,b,c,d,e,f)})}
Qa(function(){for(var a=nb(document,"pcx86-machine"),b=0;b<a.length;b++)for(var c=a[b],d=jb(c),c=nb(c,"pcx86","computer"),e=0;e<c.length;e++){var f=c[e],g=jb(f),g=new Nr(g,d,!0);mb(g,f);g.ga&&Sr(g,g.ag)}});La.show.push(function(){for(var a=nb(document,"pcx86","computer"),b=0;b<a.length;b++){var c=jb(a[b]);(c=ib("Computer",c.id))&&c.wa&&!c.la.cc&&c.ag(-1)}});
La.exit.push(function(){for(var a=nb(document,"pcx86","computer"),b=0;b<a.length;b++){var c=jb(a[b]);(c=ib("Computer",c.id))&&c.la.cc&&Mr(c,!(!c.A||c.X),!0)}});function hf(a,b,c){this.id=a.id;this.key=bs(a,b,c);this.ha=a.ha;Xr(this,a.hk)}function bs(a,b,c){a=a.id;if(b){var d=b.indexOf(".");0<d&&(a+=".v"+b.substr(0,d))}c&&(a+="."+c);return a}
hf.prototype={constructor:hf,value:function(){return this[this.id]},data:function(){return this[this.id]},load:function(a){return a?(this[this.id]=a,this.A=!0):this.A?!0:Ca()&&(a=Ea(this.key))?(this[this.id]=a,this.A=!0):!1},toString:function(){var a=this[this.id];return"string"==typeof a?a:JSON.stringify(a)},clear:function(a){Xr(this);var b=[];try{for(var c=0,d=window.localStorage.length;c<d;c++)b.push(window.localStorage.key(c))}catch(e){}for(c=0;c<b.length;c++)if((d=b[c])&&(a||d.substr(0,this.key.length)==
this.key)){try{window.localStorage.removeItem(d)}catch(e){}b.splice(c,1);c=0}}};function Xr(a,b){a[a.id]={};b&&N(a,"parms",b);a.A=!1}function Yr(a){var b=!0;if(Ca()){var c=JSON.stringify(a[a.id]);Fa(a.key,c)||(w("Unable to store "+c.length+" bytes in browser local storage"),b=!1)}return b}function Ur(a){var b=!0;try{a[a.id]=JSON.parse(a[a.id])}catch(c){w(c.message||c),b=!1}return b}function Vr(a,b){return a[a.id][b]||null}function N(a,b,c){try{a[a.id][b]=c}catch(d){}}var cs=0;
function ds(a,b,c,d,e,f){e("Loading "+a+"...");va(a,null,!0,function(g,h,k){k?(h||(h="unable to load "+a+" ("+k+")"),f(h,null)):es(h,a,b,c,d,e,f)})}
function es(a,b,c,d,e,f,g){function h(a,f){if(f)g(f,null);else{if(c){fb(c,b,a);var h=b;h&&0>h.indexOf("/")&&"/"==window.location.pathname.slice(-1)&&(h=window.location.pathname+h);d?"}"==d.slice(-1)?(d=d.slice(0,-1),1<d.length&&(d+=",")):d='{state:"'+d+'",':d="{";d+='url:"'+h+'"}';"object"==typeof resources&&(h=null);a=a.replace(/(<machine[^>]*\sid=)(['"]).*?\2/,"$1$2"+c+"$2"+(d?" parms='"+d+"'":"")+(h?' url="'+h+'"':""))}e||(a=a.replace(/(<xsl:variable name="APPCLASS">).*?(<\/xsl:variable>)/,"$1pcx86$2"));
h=null;if("<"==a.charAt(0))try{e||(a=a.replace(/<!DOCTYPE(.|[\r\n])*]>\s*/g,"")),window.ActiveXObject||"ActiveXObject"in window?(h=new window.ActiveXObject("Microsoft.XMLDOM"),h.async=!1,h.loadXML(a)):h=(new window.DOMParser).parseFromString(a,"text/xml")}catch(q){h=null,a=q.message}else a="unrecognized XML: "+(255<a.length?a.substr(0,255)+"...":a);g(a,h)}}a?e?qs(a,f,h):h(a,null):g("no data"+(b?" for file: "+b:""),null)}
function qs(a,b,c){var d;if(d=/<([a-z]+)\s+ref="(.*?)"(.*?)\/>/g.exec(a)){var e=d[2];b("Loading "+e+"...");va(e,null,!0,function(f,g,h){if(h||!g)c(a,"unable to resolve XML reference: "+d[0]+" ("+h+")");else{if(f=d[3])if(h=g.match(new RegExp("<"+d[1]+"[^>]*>"))){for(var k=h[0],l,n=/( [a-z]+=)(['"])(.*?)\2/g;l=n.exec(f);)k=0>k.indexOf(l[1])?k.replace(">",l[0]+">"):k.replace(new RegExp(l[1]+"(['\"])(.*?)\\1"),l[0]);h[0]!=k&&(g=g.replace(h[0],k))}else{c(a,"missing <"+d[1]+"> in "+e);return}g=g.replace(/<\?xml[^>]*>[\r\n]*/,

View file

@ -9,11 +9,11 @@ function p(a){window&&window.alert(a)}function ra(a){var b=!1;window&&(b=window.
function xa(a,b){try{return window.localStorage.setItem(a,b),!0}catch(c){}return!1}function ya(a){if(window){var b=window?window.navigator.userAgent:"";return"iOS"==a&&b.match(/(iPod|iPhone|iPad)/)&&b.match(/AppleWebKit/)||"MSIE"==a&&b.match(/(MSIE|Trident)/)||0<=b.indexOf(a)?!0:!1}return!1}
function za(a,b,c,d){var e=null;b="data:application/"+b+(c?";base64":"")+",";b=ya("Firefox")?b+(c?a:encodeURIComponent(a)):b+(c?a:encodeURI(a));d&&(e=document.createElement("a"),"string"!=typeof e.download&&(e=null));e?(e.href=b,e.download=d,document.body.appendChild(e),e.click(),document.body.removeChild(e),a="Check your Downloads folder for "+d+"."):(window.open(b),a="Check your browser for a new window/tab containing the requested data"+(d?" ("+d+")":"")+".");return a}
var Aa={init:[],show:[],exit:[]},Ba=!1,Ca=!0;function Da(a,b){if(window){var c=window[a];window[a]="function"!==typeof c?b:function(){c&&c();b()}}}function Ea(a){Aa.init.push(a)}function Fa(a){if(Ca)try{for(var b=0;b<a.length;b++)a[b]()}catch(c){p(""+("An unexpected exception occurred:\n\n"+c.message+"\n\nPlease send this information to support@pcjs.org. Thanks."))}}function Ga(a){!Ca&&a?(Ca=!0,Ba&&Ha("init")):Ca=a}function Ha(a){Aa[a]&&Fa(Aa[a])}Da("onload",function(){Ba=!0;Fa(Aa.init)});
Da("onpageshow",function(){Fa(Aa.show)});Da(ya("Opera")||ya("iOS")?"onunload":"onbeforeunload",function(){Fa(Aa.exit)});function Ia(a,b,c){this.type=a;b||(b={id:"",name:""});this.id=b.id;this.name=b.name;this.Ah=b.comment;this.gj=b;void 0===this.id&&(this.id="");b=this.id.indexOf(".");0<b?(this.mf=this.id.substr(0,b),this.ye=this.id.substr(b+1)):this.ye=this.id;this[a]=c;this.da={ne:!1,Qc:!1,ig:!1,Sb:!1,Yc:!1};this.Cf=null;this.da.Yc=!1;this.ka={};this.Ia=null;Ja.push(this)}var Ka=void 0,La={};
Da("onpageshow",function(){Fa(Aa.show)});Da(ya("Opera")||ya("iOS")?"onunload":"onbeforeunload",function(){Fa(Aa.exit)});function Ia(a,b,c){this.type=a;b||(b={id:"",name:""});this.id=b.id||"";this.name=b.name;this.Ah=b.comment;this.gj=b;b=this.id.indexOf(".");0>b?this.ye=this.id:(this.mf=this.id.substr(0,b),this.ye=this.id.substr(b+1));this[a]=c;this.da={ne:!1,Qc:!1,ig:!1,Sb:!1,Yc:!1};this.Cf=null;this.da.Yc=!1;this.ka={};this.Ia=null;Ja.push(this)}var Ka=void 0,La={};
if(window){Ka||(Ka=window.location.search.substr(1));for(var Ma,Na=/\+/g,Oa=/([^&=]+)=?([^&]*)/g;Ma=Oa.exec(Ka);)La[decodeURIComponent(Ma[1].replace(Na," "))]=decodeURIComponent(Ma[2].replace(Na," "))}function Pa(a){function b(){}if(window){if(!a)throw new TypeError;if(Object.create)return Object.create(a);var c=typeof a;if("object"!==c&&"function"!==c)throw new TypeError;}b.prototype=a;return new b}
function Qa(a,b){b||(b=Ia);a.prototype=Pa(b.prototype);a.prototype.constructor=a;a.prototype.parent=b.prototype}var Ja=[],Ra={};function Sa(a,b,c){Ra[a]&&b&&(Ra[a][b]=c)}function Ta(a){var b,c=[];a&&(a=0<(b=a.indexOf("."))?a.substr(0,b+1):"");for(b=0;b<Ja.length;b++){var d=Ja[b];a&&d.id.indexOf(a)||c.push(d)}return c}function Ua(a,b){if(void 0!==a){var c;b&&0<(c=b.indexOf("."))&&(a=b.substr(0,c+1)+a);for(c=0;c<Ja.length;c++)if(Ja[c].id===a)return Ja[c]}return null}
function Va(a,b){var c;if(void 0!==a){var d;b&&(b=0<(d=b.indexOf("."))?b.substr(0,d+1):"");for(d=0;d<Ja.length;d++)if(c)c==Ja[d]&&(c=null);else if(!(a!=Ja[d].type||b&&Ja[d].id.indexOf(b)))return Ja[d]}return null}function Wa(a){var b=null;if(a=a.getAttribute("data-value"))try{b=eval("("+a+")")}catch(c){p(c.message+" ("+a+")")}return b}function Xa(a,b,c){var d;b&&(void 0===d&&(d="Panel"),(d=Va(d,a.id))&&(b=d.ka[b])&&a.zb(null,c,b))}
function Ya(a,b){for(var c=Za(b.parentNode,"pcx86-control"),d=0;d<c.length;d++)for(var e=c[d].childNodes,f=0;f<e.length;f++){var g=e[f];if(1===g.nodeType){var h=g.getAttribute("class");if(h)for(var k=h.split(" "),m=0;m<k.length;m++)switch(h=k[m],h){case "pcx86-binding":(h=Wa(g))&&h.binding&&a.zb(h.type,h.binding,g,h.value),m=k.length}}}}
function Qa(a,b){b||(b=Ia);a.prototype=Pa(b.prototype);a.prototype.constructor=a;a.prototype.parent=b.prototype}if(window){window.PCjs||(window.PCjs={Machines:{},Components:[]});var Ra=window.PCjs.Machines,Ja=window.PCjs.Components}else Ra={},Ja=[];function Sa(a,b,c){Ra[a]&&b&&(Ra[a][b]=c)}function Ta(a){var b,c=[];a&&(a=0<(b=a.indexOf("."))?a.substr(0,b+1):"");for(b=0;b<Ja.length;b++){var d=Ja[b];a&&d.id.indexOf(a)||c.push(d)}return c}
function Ua(a,b){if(void 0!==a){var c;b&&0<(c=b.indexOf("."))&&(a=b.substr(0,c+1)+a);for(c=0;c<Ja.length;c++)if(Ja[c].id===a)return Ja[c]}return null}function Va(a,b){var c;if(void 0!==a){var d;b&&(b=0<(d=b.indexOf("."))?b.substr(0,d+1):"");for(d=0;d<Ja.length;d++)if(c)c==Ja[d]&&(c=null);else if(!(a!=Ja[d].type||b&&Ja[d].id.indexOf(b)))return Ja[d]}return null}function Wa(a){var b=null;if(a=a.getAttribute("data-value"))try{b=eval("("+a+")")}catch(c){p(c.message+" ("+a+")")}return b}
function Xa(a,b,c){var d;b&&(void 0===d&&(d="Panel"),(d=Va(d,a.id))&&(b=d.ka[b])&&a.zb(null,c,b))}function Ya(a,b){for(var c=Za(b.parentNode,"pcx86-control"),d=0;d<c.length;d++)for(var e=c[d].childNodes,f=0;f<e.length;f++){var g=e[f];if(1===g.nodeType){var h=g.getAttribute("class");if(h)for(var k=h.split(" "),m=0;m<k.length;m++)switch(h=k[m],h){case "pcx86-binding":(h=Wa(g))&&h.binding&&a.zb(h.type,h.binding,g,h.value),m=k.length}}}}
function Za(a,b,c){c&&(b+="-"+c+"-object");if(a.getElementsByClassName)return a.getElementsByClassName(b);var d;c=[];a=a.getElementsByTagName("*");var e=new RegExp("(^| )"+b+"( |$)");b=0;for(d=a.length;b<d;b++)e.test(a[b].className)&&c.push(a[b]);return c}
Ia.prototype={constructor:Ia,parent:null,toString:function(){return this.name?this.name:this.id||this.type},zb:function(a,b,c){switch(b){case "clear":return this.ka[b]||(this.ka[b]=c,c.onclick=function(a){return function(){a.ka.print&&(a.ka.print.value="")}}(this)),!0;case "print":return this.ka[b]||(this.hg=this.ka[b]=c,c.value="",this.rc=function(a){return function(b,c){8192<a.value.length&&(a.value=a.value.substr(a.value.length-4096));a.value+=(void 0!==c?c+": ":"")+(b||"")+"\n";a.scrollTop=a.scrollHeight}}(c),
this.Ba=function(a){this.rc(a,this.ye)}),!0;default:return!1}},log:function(){},rc:function(){},status:function(a){this.rc(this.ye+": "+a)},Ba:function(a,b,c){c=c||this.type;b||p((c?c+": ":"")+a)},Vb:function(){return this.da.Sb=!0},Ub:function(a,b){b&&(this.da.Sb=!1);return!0}};function $a(a,b){if(a.da.ig)return a.da.Qc&&(a.da.Qc=!1),a.da.ig=!1;if(a.da.Yc)return a.rc(a.toString()+" error"),!1;a.da.Qc=b;return a.da.Qc}
@ -74,8 +74,8 @@ z&&(n=a.sb,W=b==e.Ab+c,E<=J&&(!W||0<=e.fc||n<=J))){b=k&65535;h&2048&&(f=x|m<<16)
Ic(e,e.Xa.ja,4,2),e.Xa.load(0),Ic(e,e.Ta.ja,4,2),e.Ta.load(0),Ic(e,e.xa.ja,4,2),Jc(e,0),Ic(e,e.pa.ja,4,2),Kc(e,0));Ic(e,r,e.U,2);for(y(e,g);f;)y(e,a.H[--f]);a.pe=!0}return a.ya}if(0!=z)return t.call(e,13,c&65532|(W?2:0)),-1;if(!(g&32768))return t.call(e,11,c&65532|(W?2:0)),-1;break;case 2:if(n){if(4096>h||2048==(h&2560))return t.call(e,13,c&65532),-1;if(!(g&32768))return t.call(e,11,c&65532),-1}break;case 3:if(!n||4096>h||512!=(h&2560))return t.call(e,13,c&65532),-1;if(!(g&32768))return t.call(e,
12,c&65532),-1;break;case 4:r=h&-513;if(!n||256!=r&&2304!=r)return t.call(e,13,c&65532),-1;2304==r&&(a.Eh=k+e.ga(k+100+2)|0,a.zj=k+a.Za|0);break;case 6:if(!(h&4096)&&768<h&&2304!=h&&2816!=h)return-1}d?(a.B.ja=c,a.B.ya=k,a.B.Za=f,a.B.lb=g,a.B.type=h,a.B.ext=m,a.B.hc=b):(a.ja=c,a.ya=k,a.Za=f,a.C=(f>>>0)+1,a.lb=g,a.type=h,a.ext=m,a.hc=b,zc(a,!0,!0,!1));return k}
function Ec(a,b,c){var d=a.A,e=a.sb,f=d.ia.ja,g=d.ia.ya;if(!c){if(!(d.ia.type&512))return t.call(d,13,b&65532),!1;d.bb(d.ia.hc+4,d.ia.lb&=-513)}if(-1===d.ia.load(b))return!1;var h=d.ia.ya;if(!1!==c){if(d.ia.type&512)return t.call(d,13,b&65532),!1;d.bb(d.ia.hc+4,d.ia.lb|=512)}d.ia.type=d.ia.type&-513|d.ia.lb&512;256==d.ia.type||768==d.ia.type?(d.bb(g+14,A(d)),d.bb(g+16,Lc(d)),d.bb(g+18,d.J),d.bb(g+20,d.G),d.bb(g+22,d.M),d.bb(g+24,d.D),d.bb(g+26,w(d)),d.bb(g+28,d.K),d.bb(g+30,d.I),d.bb(g+32,d.H),d.bb(g+
34,d.pa.ja),d.bb(g+36,d.Ca.ja),d.bb(g+38,d.P.ja),d.bb(g+40,d.xa.ja),d.Zb.load(d.ga(h+42)),Mc(d,d.ga(h+16)|(c?16384:0)),d.J=d.ga(h+18),d.G=d.ga(h+20),d.M=d.ga(h+22),d.D=d.ga(h+24),d.K=d.ga(h+28),d.I=d.ga(h+30),d.H=d.ga(h+32),d.pa.load(d.ga(h+34)),d.xa.load(d.ga(h+40)),Oc(d,d.ga(h+14),d.ga(h+36)),b=38,g=26,a.sb<e&&(g=(a.sb<<2)+2,b=g+2),Dc(d,d.ga(h+b),!0),v(d,d.ga(h+g))):(d.Va(g+28,d.dd),d.Va(g+32,A(d)),d.Va(g+36,Lc(d)),d.Va(g+40,d.J),d.Va(g+44,d.G),d.Va(g+48,d.M),d.Va(g+52,d.D),d.Va(g+56,w(d)),d.Va(g+
60,d.K),d.Va(g+64,d.I),d.Va(g+68,d.H),d.Va(g+72,d.pa.ja),d.Va(g+76,d.Ca.ja),d.Va(g+80,d.P.ja),d.Va(g+84,d.xa.ja),d.Va(g+88,d.Ta.ja),d.Va(g+92,d.Xa.ja),Pc.call(d,d.fa(h+28)),d.Zb.load(d.ga(h+96)),Mc(d,d.fa(h+36)|(c?16384:0)),d.J=d.fa(h+40),d.G=d.fa(h+44),d.M=d.fa(h+48),d.D=d.fa(h+52),d.K=d.fa(h+60),d.I=d.fa(h+64),d.H=d.fa(h+68),d.pa.load(d.ga(h+72)),d.xa.load(d.ga(h+84)),d.Ta.load(d.ga(h+88)),d.Xa.load(d.ga(h+92)),Oc(d,d.fa(h+32),d.ga(h+76)),b=80,g=56,a.sb<e&&(g=(a.sb<<3)+4,b=g+4),Dc(d,d.ga(h+b),!0),
34,d.pa.ja),d.bb(g+36,d.Ca.ja),d.bb(g+38,d.P.ja),d.bb(g+40,d.xa.ja),d.Zb.load(d.ga(h+42)),Mc(d,d.ga(h+16)|(c?16384:0)),d.J=d.ga(h+18),d.G=d.ga(h+20),d.M=d.ga(h+22),d.D=d.ga(h+24),d.K=d.ga(h+28),d.I=d.ga(h+30),d.H=d.ga(h+32),d.pa.load(d.ga(h+34)),d.xa.load(d.ga(h+40)),Nc(d,d.ga(h+14),d.ga(h+36)),b=38,g=26,a.sb<e&&(g=(a.sb<<2)+2,b=g+2),Dc(d,d.ga(h+b),!0),v(d,d.ga(h+g))):(d.Va(g+28,d.dd),d.Va(g+32,A(d)),d.Va(g+36,Lc(d)),d.Va(g+40,d.J),d.Va(g+44,d.G),d.Va(g+48,d.M),d.Va(g+52,d.D),d.Va(g+56,w(d)),d.Va(g+
60,d.K),d.Va(g+64,d.I),d.Va(g+68,d.H),d.Va(g+72,d.pa.ja),d.Va(g+76,d.Ca.ja),d.Va(g+80,d.P.ja),d.Va(g+84,d.xa.ja),d.Va(g+88,d.Ta.ja),d.Va(g+92,d.Xa.ja),Pc.call(d,d.fa(h+28)),d.Zb.load(d.ga(h+96)),Mc(d,d.fa(h+36)|(c?16384:0)),d.J=d.fa(h+40),d.G=d.fa(h+44),d.M=d.fa(h+48),d.D=d.fa(h+52),d.K=d.fa(h+60),d.I=d.fa(h+64),d.H=d.fa(h+68),d.pa.load(d.ga(h+72)),d.xa.load(d.ga(h+84)),d.Ta.load(d.ga(h+88)),d.Xa.load(d.ga(h+92)),Nc(d,d.fa(h+32),d.ga(h+76)),b=80,g=56,a.sb<e&&(g=(a.sb<<3)+4,b=g+4),Dc(d,d.ga(h+b),!0),
v(d,d.fa(h+g)));c&&d.bb(h+0,f);d.Pa|=8;return!0}l.save=function(){return[this.ja,this.ya,this.Za,this.lb,this.id,this.Uf,this.sb,this.nc,this.hc,this.Nc,this.sa,this.U,this.N,this.type,this.C]};l.restore=function(a){"number"==typeof a?this.load(a):(this.ja=a[0],this.ya=a[1],this.Za=a[2],this.lb=a[3],this.id=a[4],this.Uf=a[5],this.sb=a[6],this.nc=a[7],this.hc=a[8],this.Nc=a[9]||2,this.sa=a[10]||65535,this.U=a[11]||2,this.N=a[12]||65535,this.type=a[13]||this.lb&7936,this.C=a[14]||(this.Za>>>0)+1)};
function zc(a,b,c,d){void 0===c&&(c=!!(a.A.Pa&1));a.zd=!1;if(c)if(a.load=a.Df,a.Xh=a.Uk,a.Qb=a.Jh,a.Rb=a.Lh,void 0===d&&(d=!!(a.A.X&131072)),d)a.load=a.L,a.Qb=a.I,a.Rb=a.K,a.sb=a.nc=3,a.U=a.Nc=2,a.N=a.sa=65535,a.Za=65535,a.C=a.Za+1,a.Nc=a.U,a.hc=-1,a.pe=!1;else{if(!(a.ja&-4))a.Qb=a.xf,a.Rb=a.yf;else if(a.type&4096){6144==(a.type&6656)&&(a.Qb=a.xf);if(a.type&2048||!(a.type&512))a.Rb=a.yf;1024==(a.type&3072)&&(a.Qb==a.Jh&&(a.Qb=a.Aj),a.Rb==a.Lh&&(a.Rb=a.Bj),a.zd=!0);b&&6>a.id&&a.ja&-4&&-1!==a.hc&&(c=
a.hc+5,d=a.A.Kb(c),d&1||a.A.Mc(c,d|1))}b&&(a.sb=a.ja&3,a.nc=(a.lb&24576)>>13,80386>a.A.ca||!(a.ext&64)?(a.U=2,a.N=65535):(a.U=4,a.N=-1),a.Nc=a.U,a.sa=a.N)}else a.load=a.Yh,a.Xh=a.Vk,a.Qb=a.Kh,a.Rb=a.Mh,a.sb=a.nc=0,a.hc=-1,a.pe=!1}
@ -87,7 +87,7 @@ function Zb(a,b,c,d){var e=(b&-4194304)>>>20,f=a.vc[(a.dd+e&a.Fa)>>>a.ea],g=f.Gd
e>>2;b.C=g;b.G=h>>2;db&&Ib&&c.V&&!c.controller&&!c.ge&&!c.he?(b.Ka=c.Ka,b.vd=c.vd,b.V=c.V,Fb(b,gc)):(b.K=c?Xb(32):0,b.P=c?Xb(96):0,Fb(b,ec));sb(b,a.Ia,k);a.R[d]=b;a.of.push(d);return b}function Ad(a){a.R!==a.vc&&(a.R=a.vc,a.qf=null,a.of=null,a.Zd=null)}l=Qc.prototype;l.reset=function(){this.da.Jb&&oc(this);yd(this);kc(this);this.da.Yc=!1};
function Bd(a,b){var c;switch(b){case 0:c=a.J;break;case 1:c=a.G;break;case 2:c=a.M;break;case 3:c=a.D;break;case 4:c=w(a);break;case 5:c=a.K;break;case 6:c=a.I;break;case 7:c=a.H}return c}function Cd(a,b,c){switch(b){case 0:a.J=c;break;case 1:a.G=c;break;case 2:a.M=c;break;case 3:a.D=c;break;case 4:v(a,c);break;case 5:a.K=c;break;case 6:a.I=c;break;case 7:a.H=c}}
function yd(a){a.J=0;a.D=0;a.G=0;a.M=0;a.Ob=0;a.K=0;a.I=0;a.H=0;a.Hb=!1;a.ua=a.Ga=0;a.oa=0;a.yh=0;a.W=0;a.Pa=65520;a.Ab=0;a.xc=1023;a.X=a.Cb=0;a.td=a.Kd=a.sd=a.Id=0;a.fc=-1;a.Gc=a.ic=-1;a.Ed=a.la=-1;a.Ca=new yc(a,1,"CS");a.xa=new yc(a,2,"DS");a.pa=new yc(a,2,"ES");a.P=new yc(a,3,"SS");v(a,0);Dc(a,0);if(80386<=a.ca){switch(a.pd){case 80562:case 80563:a.M=771;break;case 80578:a.M=772;break;case 80594:a.M=773;break;case 80595:case 80596:a.M=776}a.Pa=16;a.Ch=0;a.rd=0;a.dd=0;a.qb=[0,0,0,0,null,null,0,
0];a.sf=[null,null,null,null,null,null,0,0];a.Ta=new yc(a,2,"FS");a.Xa=new yc(a,2,"GS");Ad(a)}a.Zf=new yc(a,0,"NULL");a.va=a.xa;a.rb=a.P;a.L=a.wa=0;a.F=a.C=-1;a.Eb=a.Zf;a.Ea=0;if(80286>a.ca)Oc(a,0,65535);else{a.ub=0;a.wc=65535;a.Zb=new yc(a,5,"LDT",!0);a.ia=new yc(a,4,"TSS",!0);a.Oa=new yc(a,6,"VER",!0);Oc(a,65520,61440);var b,c=A(a);b=a.Ca;var d=-65536;80386>b.A.ca&&(d&=16777215);b=b.ya=d;a.Y=b+c|0;a.Xf=(b>>>0)+(a.Ca.Za>>>0)+1}Mc(a,0);Fc(a)}
0];a.sf=[null,null,null,null,null,null,0,0];a.Ta=new yc(a,2,"FS");a.Xa=new yc(a,2,"GS");Ad(a)}a.Zf=new yc(a,0,"NULL");a.va=a.xa;a.rb=a.P;a.L=a.wa=0;a.F=a.C=-1;a.Eb=a.Zf;a.Ea=0;if(80286>a.ca)Nc(a,0,65535);else{a.ub=0;a.wc=65535;a.Zb=new yc(a,5,"LDT",!0);a.ia=new yc(a,4,"TSS",!0);a.Oa=new yc(a,6,"VER",!0);Nc(a,65520,61440);var b,c=A(a);b=a.Ca;var d=-65536;80386>b.A.ca&&(d&=16777215);b=b.ya=d;a.Y=b+c|0;a.Xf=(b>>>0)+(a.Ca.Za>>>0)+1}Mc(a,0);Fc(a)}
function Dd(a){2==a.Nc?(a.Bh=a.ga,a.Bb=Ed,a.Gb=Fd,a.yc=Gd,2==a.U?(a.Z=Hd,a.qa=Id,a.Ja=Jd):(a.Z=Kd,a.qa=Ld,a.Ja=Md)):(a.Bh=a.fa,a.Bb=Nd,a.Gb=Od,a.yc=Pd,2==a.U?(a.Z=Qd,a.qa=Rd,a.Ja=Sd):(a.Z=Td,a.qa=Ud,a.Ja=Vd))}function Gc(a,b){a.U!=b&&(a.wa|=1024,a.U=b,a.N=2==b?65535:-1,Wd(a))}function Wd(a){2==a.U?(a.fb=32768,a.Tb=a.ga,a.Xb=a.bb,2==a.Nc?(a.Z=Hd,a.qa=Id,a.Ja=Jd):(a.Z=Qd,a.qa=Rd,a.Ja=Sd)):(a.fb=-2147483648,a.Tb=a.fa,a.Xb=a.Va,2==a.Nc?(a.Z=Kd,a.qa=Ld,a.Ja=Md):(a.Z=Td,a.qa=Ud,a.Ja=Vd))}
function Xd(a){a.Nc=a.Ca.Nc;a.sa=a.Ca.sa;Dd(a);a.U=a.Ca.U;a.N=a.Ca.N;Wd(a);a.wa&=-3073}l.Uh=function(){var a=this.J+this.D+this.G+this.M+w(this)+this.K+this.I+this.H|0;return a=a+A(this)+this.Ca.ja+this.xa.ja+this.P.ja+this.pa.ja+Lc(this)|0};function Yd(a,b,c){void 0===a.pf[b]&&(a.pf[b]=[]);a.pf[b].push(c)}function Zd(a,b){var c=a.uh[b];null!=c&&(c(--a.Wf),delete a.uh[b])}
function $d(a,b){for(var c=a.qb[7],d=c>>16,e=0;4>e;e++){if(c&3){var f=!!(d&1),g=a.qb[e],g=g&~(d>>2&3);if(b){var g=a.R[g>>>a.ea],h=a;f?0===g.he++&&(h&&(g.A=h),cc(g,bc,!1)):0===g.ge++&&(h&&(g.A=h),ac(g,bc,!1))}else g=a.R[g>>>a.ea],f?0===--g.he&&(f=g,f.Yb=f.I?f.ha:f.lf,f.He=f.I?f.ba:f.qh,f.Ge=f.I?f.ka:f.oa):0===--g.ge&&(f=g,f.Wb=f.Fd,f.Ae=f.gf,f.Gd=f.jh)}c>>=2;d>>=4}}
@ -95,9 +95,9 @@ function Yb(a,b,c,d){if(!(a.L&8192)&&a.qb[7]&255){c--;var e=a.qb[7],f=e>>16;d=d?
l.save=function(){var a=new be(this);C(a,0,[this.J,this.D,this.G,this.M,w(this),this.K,this.I,this.H]);var b=A(this),c=this.Ca.save(),d=this.xa.save(),e=this.P.save(),f=this.pa.save(),g;null!=this.ub?(g=[this.Pa,this.ub,this.wc,this.Ab,this.xc,this.Zb.save(),this.ia.save(),this.Cb],80386<=this.ca&&(g.push(this.Ch),g.push(this.rd),g.push(this.dd),g.push(this.qb),g.push(this.sf))):g=null;b=[b,c,d,e,f,g,Lc(this)];80386<=this.ca&&(b.push(this.Ta.save()),b.push(this.Xa.save()));C(a,1,b);C(a,2,[this.va.Uf,
this.rb.Uf,this.L,this.wa,this.Ea,this.F,this.C]);C(a,3,[0,this.$c,this.T.Cd]);b=this.ha;c=!!(this.Pa&-2147483648);d=0;e=[];(f=!b.G&&b.ba==b.Fa)||xb(b,!0);for(g=0;g<b.H;g++){var h=b.R[g];if(c&&h.type!=Hb||h.Ha||h.Qh){e[d++]=g;var k=d++;a:if(h=h.save()){for(var m=0,n=0,x=[];m<h.length;){for(var r=h[m],z=m+1;z<h.length&&h[z]===r;)z++;x[n++]=z-m;x[n++]=r;m=z}if(x.length<h.length){h=x;break a}}e[k]=h}}f||xb(b,!1);e[d]=f;C(a,4,e);return a.data()};
l.restore=function(a){var b=a[0];this.J=b[0];this.D=b[1];this.G=b[2];this.M=b[3];var c=b[4];this.K=b[5];this.I=b[6];this.H=b[7];b=a[1];this.Ca.restore(b[1]);this.xa.restore(b[2]);this.P.restore(b[3]);this.pa.restore(b[4]);var d=b[5];d&&d.length&&(this.Pa=d[0],this.ub=d[1],this.wc=d[2],this.Ab=d[3],this.xc=d[4],this.Zb.restore(d[5]),this.ia.restore(d[6]),this.Cb=d[7],80386<=this.ca&&(this.Ch=d[8],this.rd=d[9],this.dd=d[10],this.qb=d[11],this.sf=d[12]),Fc(this));Mc(this,b[6]);var d=!1,e;a:{e=this.ha;
var f=a[4],g;for(g=0;g<f.length-1;g+=2){var h=f[g],k=f[g+1];if(k&&k.length<e.ha){for(var m=0,n=Array(e.ha),x=0;x<k.length-1;)for(var r=k[x++],z=k[x++];r--;)n[m++]=z;k=n}m=e.R[h];if(!m||!m.restore(k)){p("Unable to restore memory block "+h);e=!1;break a}}void 0!==f[g]&&xb(e,f[g]);e=!0}e&&(Oc(this,b[0],this.Ca.ja),v(this,c),Dc(this,this.P.ja),80386<=this.ca&&(this.Ta.restore(b[7]),this.Xa.restore(b[8])),d=!0);b=a[2];this.va=null!=b[0]&&ce(this,b[0])||this.xa;this.rb=null!=b[1]&&ce(this,b[1])||this.P;
this.L=b[2];this.wa=b[3];this.Ea=b[4];this.F=b[5];this.C=b[6];b=a[3];this.$c=b[1];pc(this,b[2]);return d};function ce(a,b){switch(b){case "CS":return a.Ca;case "DS":return a.xa;case "SS":return a.P;case "ES":return a.pa;case "NULL":return a.Zf;default:return[0,b,0,0,""]}}function de(a,b){null!=Oc(a,A(a),b)&&(a.L|=a.ae)}function Jc(a,b){-1!==a.xa.load(b)&&(a.L|=a.ae)}
function Dc(a,b,c){var d=w(a);-1!==a.P.load(b)&&(v(a,d),a.P.zd?(a.Yf=a.P.ya+a.P.sa|0,a.$d=a.P.ya+a.P.Za|0):(a.Yf=a.P.ya+a.P.Za|0,a.$d=a.P.ya),c||(a.L|=4))}function Kc(a,b){-1!==a.pa.load(b)&&(a.L|=a.ae)}function A(a){return a.Y-a.Ca.ya|0}function D(a,b){a.Y=a.Ca.ya+(b&a.N)|0}function ee(a,b){a.Y=b;a.Xf=(a.Ca.ya>>>0)+(a.Ca.Za>>>0)+1;a.za=a.Ca.sb;Xd(a)}function Oc(a,b,c,d){var e=a.Ca;e.ef=b;e.D=d;b=e.load(c);return-1!==b?(ee(a,b+(a.Ca.ef&a.Ca.N)),a.Ca.pe):null}
var f=a[4],g;for(g=0;g<f.length-1;g+=2){var h=f[g],k=f[g+1];if(k&&k.length<e.ha){for(var m=0,n=Array(e.ha),x=0;x<k.length-1;)for(var r=k[x++],z=k[x++];r--;)n[m++]=z;k=n}m=e.R[h];if(!m||!m.restore(k)){p("Unable to restore memory block "+h);e=!1;break a}}void 0!==f[g]&&xb(e,f[g]);e=!0}e&&(Nc(this,b[0],this.Ca.ja),v(this,c),Dc(this,this.P.ja),80386<=this.ca&&(this.Ta.restore(b[7]),this.Xa.restore(b[8])),d=!0);b=a[2];this.va=null!=b[0]&&ce(this,b[0])||this.xa;this.rb=null!=b[1]&&ce(this,b[1])||this.P;
this.L=b[2];this.wa=b[3];this.Ea=b[4];this.F=b[5];this.C=b[6];b=a[3];this.$c=b[1];pc(this,b[2]);return d};function ce(a,b){switch(b){case "CS":return a.Ca;case "DS":return a.xa;case "SS":return a.P;case "ES":return a.pa;case "NULL":return a.Zf;default:return[0,b,0,0,""]}}function de(a,b){null!=Nc(a,A(a),b)&&(a.L|=a.ae)}function Jc(a,b){-1!==a.xa.load(b)&&(a.L|=a.ae)}
function Dc(a,b,c){var d=w(a);-1!==a.P.load(b)&&(v(a,d),a.P.zd?(a.Yf=a.P.ya+a.P.sa|0,a.$d=a.P.ya+a.P.Za|0):(a.Yf=a.P.ya+a.P.Za|0,a.$d=a.P.ya),c||(a.L|=4))}function Kc(a,b){-1!==a.pa.load(b)&&(a.L|=a.ae)}function A(a){return a.Y-a.Ca.ya|0}function D(a,b){a.Y=a.Ca.ya+(b&a.N)|0}function ee(a,b){a.Y=b;a.Xf=(a.Ca.ya>>>0)+(a.Ca.Za>>>0)+1;a.za=a.Ca.sb;Xd(a)}function Nc(a,b,c,d){var e=a.Ca;e.ef=b;e.D=d;b=e.load(c);return-1!==b?(ee(a,b+(a.Ca.ef&a.Ca.N)),a.Ca.pe):null}
function fe(a,b){var c=(a.Y>>>0)+b;c>a.Xf&&(8088>=a.ca||a.Ca.Za==a.Ca.sa?c=a.Ca.ya+(c-a.Xf&a.N):t.call(a,13,0));return c|0}function ge(a){a.Y=a.Ed}function w(a){return a.Ob&~a.P.sa|a.ra-a.P.ya}function v(a,b){a.Ob=b;a.ra=a.P.ya+(b&a.P.sa)|0}function he(a,b,c,d,e,f){if(63!=(e&63)&&e!=a.resultType){var g=(e^a.resultType)&a.resultType;g&&(g&1&&ie(a),g&2&&je(a),g&4&&ke(a),g&8&&le(a),g&16&&me(a),g&32&&ne(a))}f?(a.td=d,a.sd=b):(a.td=b,a.sd=d);a.Kd=c;a.Id=d;a.resultType=e}
function F(a,b,c,d,e){a.resultType=c|26;a.Id=b;d?oe(a):pe(a);e?qe(a):re(a);return b}function se(a,b,c,d){c&d?oe(a):pe(a);(b^c)&d?qe(a):re(a)}function ve(a){return ie(a)?1:0}function ie(a){a.resultType&1&&(a.X&=-2,(a.td^(a.td^a.Kd)&(a.Kd^a.sd))&a.resultType&-2147450752&&(a.X|=1),a.resultType&=-2);return a.X&1}function je(a){a.resultType&2&&(a.X&=-5,38505>>((a.Id^a.Id>>4)&15)&1&&(a.X|=4),a.resultType&=-3);return a.X&4}
function ke(a){a.resultType&4&&(a.X&=-17,(a.sd^a.td^a.Kd)&16&&(a.X|=16),a.resultType&=-5);return a.X&16}function le(a){a.resultType&8&&(a.X&=-65,a.Id&((a.resultType&-2147450752)-1|a.resultType&-2147450752)||(a.X|=64),a.resultType&=-9);return a.X&64}function me(a){a.resultType&16&&(a.X&=-129,a.Id&a.resultType&-2147450752&&(a.X|=128),a.resultType&=-17);return a.X&128}
@ -170,8 +170,8 @@ function vh(a,b){var c=a^b;F(this,c,128);this.A-=-1===this.C?-1===this.F?this.B.
function zh(a,b,c){c>>>=0;if(!c||c<=b>>>0)return!1;var d=0,e=1;c=[c>>>0,0];for(a=[a>>>0,b>>>0];0<xh(a,c);){var f=b=c;b[0]+=f[0];b[1]+=f[1];4294967295<b[0]&&(b[0]>>>=0,b[1]++);e+=e}do 0<=xh(a,c)&&(b=a,f=c,b[0]-=f[0],b[1]-=f[1],0>b[0]&&(b[0]>>>=0,b[1]--),d+=e),b=c,b[0]>>>=1,b[1]&1&&(b[0]=(b[0]|2147483648)>>>0),b[1]>>>=1,e/=2;while(1<=e);this.ua=d;this.Ga=a[0];return!0}function Ah(a){var b=a+1|0;he(this,a,1,b,this.fb|62);this.A-=2;return a&~this.N|b&this.N}
function Pc(a){this.dd=a;this.Pa&-2147483648&&Bb(this)}function Bh(a){this.L|=1;this.Gb.call(this,a);this.A-=-1===this.F?4:5}function ch(a,b,c){if(c){16<c&&(a=b,c-=16);var d=a<<c-1;a=(d<<1|b>>>16-c)&65535;F(this,a,32768,d&32768)}return a}function eh(a,b,c){if(c){var d=a<<c-1;a=d<<1|b>>>32-c;F(this,a,-2147483648,d&-2147483648)}return a}function ih(a,b,c){if(c){16<c&&(a=b,c-=16);var d=a>>>c-1;a=(d>>>1|b<<16-c)&65535;F(this,a,32768,d&1)}return a}
function kh(a,b,c){if(c){var d=a>>>c-1;a=d>>>1|b<<32-c;F(this,a,-2147483648,d&1)}return a}function Ch(){this.A-=-1===this.F?2:this.B.aj;return 1}function Dh(){var a=this.G&255;this.A-=(-1===this.F?this.B.Wg:this.B.Vg)+(a<<this.B.Xg);return a}function Eh(){var a=this.na();this.A-=(-1===this.F?this.B.Wg:this.B.Vg)+(a<<this.B.Xg);return a}function Fh(){return null}function Gh(){return this.oa}
function Hh(a,b){this.Gc=this.Ca.ja;this.ic=this.P.ja;this.la=this.ra;var c=A(this),d=this.U;null!=Oc(this,a,b,!0)&&(Ic(this,this.Gc,d,2),Ic(this,c,d,d));this.Gc=this.ic=this.la=-1}function Ih(a,b,c){this.A-=this.B.zi+(c||0);c=Lc(this);var d=this.Ca.ja,e=A(this);a=this.Ca.Xh(a);-1!==a&&(y(this,c),y(this,d),y(this,e),null!=b&&y(this,b),this.fc=-1,ee(this,a))}
function Jh(a){this.ic=this.P.ja;this.la=this.ra;var b=u(this),c=u(this);a&&v(this,w(this)+a);Oc(this,b,c,!1)&&(a&&v(this,w(this)+a),Kh.call(this,this.xa),Kh.call(this,this.pa),80386<=this.ca&&(Kh.call(this,this.Ta),Kh.call(this,this.Xa)));2==a&&this.Wf&&Zd(this,this.Y);this.ic=this.la=-1}function Lh(){8086==this.ca?(this.fc=-1,Ih.call(this,0,null,2)):t.call(this,0,null,2)}function Ke(a,b){this.fc=a;void 0===b&&(b=11);Ih.call(this,a,null,b)}
function Hh(a,b){this.Gc=this.Ca.ja;this.ic=this.P.ja;this.la=this.ra;var c=A(this),d=this.U;null!=Nc(this,a,b,!0)&&(Ic(this,this.Gc,d,2),Ic(this,c,d,d));this.Gc=this.ic=this.la=-1}function Ih(a,b,c){this.A-=this.B.zi+(c||0);c=Lc(this);var d=this.Ca.ja,e=A(this);a=this.Ca.Xh(a);-1!==a&&(y(this,c),y(this,d),y(this,e),null!=b&&y(this,b),this.fc=-1,ee(this,a))}
function Jh(a){this.ic=this.P.ja;this.la=this.ra;var b=u(this),c=u(this);a&&v(this,w(this)+a);Nc(this,b,c,!1)&&(a&&v(this,w(this)+a),Kh.call(this,this.xa),Kh.call(this,this.pa),80386<=this.ca&&(Kh.call(this,this.Ta),Kh.call(this,this.Xa)));2==a&&this.Wf&&Zd(this,this.Y);this.ic=this.la=-1}function Lh(){8086==this.ca?(this.fc=-1,Ih.call(this,0,null,2)):t.call(this,0,null,2)}function Ke(a,b){this.fc=a;void 0===b&&(b=11);Ih.call(this,a,null,b)}
function t(a,b,c,d){var e=!1;this.da.Ne?80186<=this.ca&&(e=!0,0>this.fc?(-1!=this.Gc&&(this.Gc!==this.Ca.ja&&(this.Ca.sb=this.Gc&3,de(this,this.Gc)),this.Gc=-1),this.Ed!==this.Y&&ee(this,this.Ed),-1!=this.ic&&(this.ic!==this.P.ja&&Dc(this,this.ic),this.ic=-1),-1!==this.la&&(this.la!==this.ra&&v(this,this.Ob&~this.P.sa|this.la-this.P.ya),this.la=-1)):8!=this.fc?(b=0,a=8):(b=0,a=-1,yd(this),e=d=!1)):ee(this,this.Ed);var f=a,g=b,h=Ce(this,this.Y);204!=h||this.xc||(d=!1);this.X&131072&&(6==f&&99==h||
13==f&&205==h)&&(d=!1);983040<=this.Y&&1048575>=this.Y&&(d=!1);if(d){var k=this.da.Jb,f="Fault 0x"+ea(f,2)+(null!=g?" (0x"+ea(g,4)+")":"")+" on opcode "+("0x"+ea(h,2));d&&k&&(f+=" (blocked)");this.Ba(f);oc(this)}if(d&&e)throw-1;if(e)throw this.fc=a,Ih.call(this,a,b,c),this.Ed=this.Y,this.L=1==a?this.L|8192:this.L|4096,a;}function zd(a,b,c){this.rd=a;a=0;b&&(a|=1);c&&(a|=2);3==this.za&&(a|=4);t.call(this,14,a)}
function Kh(a){var b=a.lb&7680;a.ja&65528&&(6144==b||7168==b||7168>b&&a.nc<this.za&&a.nc<(a.ja&3))&&a.load(0)}
@ -302,11 +302,11 @@ function(){var a=1,b=0,c=this.sa,d=this.B.Sg;this.wa&192&&(a=this.G&c,b=1,d=this
-256|this.na();this.A-=this.B.Nb},function(){this.D=this.D&-256|this.na();this.A-=this.B.Nb},function(){this.J=this.J&-65281|this.na()<<8;this.A-=this.B.Nb},function(){this.G=this.G&-65281|this.na()<<8;this.A-=this.B.Nb},function(){this.M=this.M&-65281|this.na()<<8;this.A-=this.B.Nb},function(){this.D=this.D&-65281|this.na()<<8;this.A-=this.B.Nb},function(){this.J=this.J&~this.N|this.Aa();this.A-=this.B.Nb},function(){this.G=this.G&~this.N|this.Aa();this.A-=this.B.Nb},function(){this.M=this.M&~this.N|
this.Aa();this.A-=this.B.Nb},function(){this.D=this.D&~this.N|this.Aa();this.A-=this.B.Nb},function(){v(this,w(this)&~this.N|this.Aa());this.A-=this.B.Nb},function(){this.K=this.K&~this.N|this.Aa();this.A-=this.B.Nb},function(){this.I=this.I&~this.N|this.Aa();this.A-=this.B.Nb},function(){this.H=this.H&~this.N|this.Aa();this.A-=this.B.Nb},li,mi,li,mi,function(){this.Z.call(this,zg)},function(){this.Z.call(this,xg)},function(){this.L|=1;this.yc.call(this,ti,this.na)},function(){this.L|=1;this.Ja.call(this,
ti,this.Aa)},ni,oi,ni,oi,function(){if(this.X&131072&&3>this.Cb)t.call(this,13,0);else{var a=this.B.Ai;this.fc=-1;Ih.call(this,3,null,a)}},function(){var a=this.na();if(this.X&131072&&3>this.Cb)t.call(this,13,0);else{var b;a:{b=this.pf[a];if(void 0!==b)for(var c=0;c<b.length;c++)if(!b[c](this.Y)){b=!1;break a}b=!0}b?(this.fc=-1,Ih.call(this,a,null,0)):this.A--}},function(){if(ne(this))if(this.X&131072&&3>this.Cb)t.call(this,13,0);else{var a=this.B.Bi;this.fc=-1;Ih.call(this,4,null,a)}else this.A-=
this.B.Ci},function(){if(this.X&131072&&3>this.Cb)t.call(this,13,0);else{this.ic=this.P.ja;this.la=this.ra;this.A-=this.B.yi;if(this.Pa&1&&this.X&16384){var a=this.ga(this.ia.ya+0);Ec(this.Ca,a,!1)}else{var a=this.za,b=u(this),c=u(this),d=u(this);if(this.X&131072)d=d&131071|this.X&-131072;else if(d&131072){var e=u(this),f=u(this),g=u(this),h=u(this),k=u(this),m=u(this);Fc(this,!0,!0);Dc(this,f);v(this,e);Kc(this,g);Jc(this,h);this.Ta.load(k);this.Xa.load(m)}null!=Oc(this,b,c,!1)&&(Mc(this,d,a),this.Wf&&
this.B.Ci},function(){if(this.X&131072&&3>this.Cb)t.call(this,13,0);else{this.ic=this.P.ja;this.la=this.ra;this.A-=this.B.yi;if(this.Pa&1&&this.X&16384){var a=this.ga(this.ia.ya+0);Ec(this.Ca,a,!1)}else{var a=this.za,b=u(this),c=u(this),d=u(this);if(this.X&131072)d=d&131071|this.X&-131072;else if(d&131072){var e=u(this),f=u(this),g=u(this),h=u(this),k=u(this),m=u(this);Fc(this,!0,!0);Dc(this,f);v(this,e);Kc(this,g);Jc(this,h);this.Ta.load(k);this.Xa.load(m)}null!=Nc(this,b,c,!1)&&(Mc(this,d,a),this.Wf&&
Zd(this,this.Y))}this.ic=this.la=-1}},function(){this.yc.call(this,ii,Ch)},function(){this.Ja.call(this,2==this.U?ji:ki,Ch)},function(){this.yc.call(this,ii,Dh)},function(){this.Ja.call(this,2==this.U?ji:ki,Dh)},function(){var a=this.na();if(a){var b=this.J&255;this.J=this.J&-65536|b/a<<8|b%a;F(this,this.J,128);this.A-=this.B.ci}else Lh.call(this)},function(){var a=this.J&255,b=(this.J>>8&255)*this.na()|0,c=a+b|0;this.J=this.J&-65536|c&255;he(this,a,b,c,191);this.A-=this.B.bi},function(){this.J=this.J&
-256|(ie(this)?255:0);this.A-=2},function(){this.J=this.J&-256|De(this,this.va,this.D+(this.J&255));this.A-=this.B.bj},function(){pi.call(this,216)},function(){pi.call(this,217)},function(){pi.call(this,218)},function(){pi.call(this,219)},function(){pi.call(this,220)},function(){pi.call(this,221)},function(){pi.call(this,222)},function(){pi.call(this,223)},function(){var a=this.O(),b=this.G-1&this.sa;this.G=this.G&~this.sa|b;b&&!le(this)?(D(this,A(this)+a),this.A-=this.B.Ji):this.A-=this.B.Ig},function(){var a=
this.O(),b=this.G-1&this.sa;this.G=this.G&~this.sa|b;b&&le(this)?(D(this,A(this)+a),this.A-=this.B.Jg):this.A-=this.B.Kg},function(){var a=this.O(),b=this.G-1&this.sa;this.G=this.G&~this.sa|b;b?(D(this,A(this)+a),this.A-=this.B.Ii):this.A-=this.B.Ig},function(){var a=this.O();this.G&this.sa?this.A-=this.B.Kg:(D(this,A(this)+a),this.A-=this.B.Jg)},function(){var a=this.na();Be(this,a,1)&&(this.J=this.J&-256|Pb(this.ha,a,1,this.Y-2)&255,this.A-=this.B.Dg)},function(){var a=this.na();Be(this,a,this.U)&&
(this.J=this.J&~this.N|Pb(this.ha,a,this.U,this.Y-2)&this.N,this.A-=this.B.Dg)},function(){var a=this.na();Be(this,a,1)&&(Rb(this.ha,a,1,this.J&255,this.Y-2),this.A-=this.B.Rg)},function(){var a=this.na();Be(this,a,this.U)&&(Rb(this.ha,a,this.U,this.J&this.N,this.Y-2),this.A-=this.B.Rg)},function(){var a=this.Aa(),b=A(this),a=b+a;y(this,b);D(this,a);this.A-=this.B.gi},function(){var a=this.Aa();D(this,A(this)+a);this.A-=this.B.Eg},function(){Oc(this,this.Aa(),Ie(this));this.A-=this.B.Ei},function(){var a=
(this.J=this.J&~this.N|Pb(this.ha,a,this.U,this.Y-2)&this.N,this.A-=this.B.Dg)},function(){var a=this.na();Be(this,a,1)&&(Rb(this.ha,a,1,this.J&255,this.Y-2),this.A-=this.B.Rg)},function(){var a=this.na();Be(this,a,this.U)&&(Rb(this.ha,a,this.U,this.J&this.N,this.Y-2),this.A-=this.B.Rg)},function(){var a=this.Aa(),b=A(this),a=b+a;y(this,b);D(this,a);this.A-=this.B.gi},function(){var a=this.Aa();D(this,A(this)+a);this.A-=this.B.Eg},function(){Nc(this,this.Aa(),Ie(this));this.A-=this.B.Ei},function(){var a=
this.O();D(this,A(this)+a);this.A-=this.B.Eg},function(){var a=this.M&65535;Be(this,a,1)&&(this.J=this.J&-256|Pb(this.ha,a,1,this.Y-1)&255,this.A-=this.B.Cg)},function(){var a=this.M&65535;Be(this,a,this.U)&&(this.J=this.J&~this.N|Pb(this.ha,a,this.U,this.Y-1)&this.N,this.A-=this.B.Cg)},function(){var a=this.M&65535;Be(this,a,1)&&(Rb(this.ha,a,1,this.J&255,this.Y-1),this.A-=this.B.Qg)},function(){var a=this.M&65535;Be(this,a,2)&&(Rb(this.ha,a,this.U,this.J&this.N,this.Y-1),this.A-=this.B.Qg)},qi,
qi,function(){this.L|=132;this.A-=this.B.Rc},function(){this.L|=68;this.A-=this.B.Rc},function(){this.X&131072?t.call(this,13,0):(this.Ea|=4,this.A-=2,this.X&512||oc(this))},function(){ie(this)?pe(this):oe(this);this.A-=2},function(){this.Hb=!1;this.yc.call(this,ui,Fh);this.Hb&&(this.J=this.J&~this.N|this.ua&this.N)},function(){this.Hb=!1;this.Ja.call(this,vi,Fh);this.Hb&&(this.J=this.J&~this.N|this.ua&this.N,this.M=this.M&~this.N|this.Ga&this.N)},function(){pe(this);this.A-=2},function(){oe(this);
this.A-=2},function(){this.za>this.Cb?t.call(this,13,0):(this.X&=-513,this.A-=this.B.ei)},function(){this.za>this.Cb?t.call(this,13,0):(this.X|=512,this.L|=4,this.A-=2)},function(){this.X&=-1025;this.A-=2},function(){this.X|=1024;this.A-=2},function(){this.yc.call(this,Sc,Fh)},function(){this.Ja.call(this,Tc,Fh)}],di=[Xf,Jg,Vf,Lg,Zf,nh,vh,mg],ri=[Yf,Kg,Wf,Mg,$f,oh,wh,ng],si=[function(a,b){this.A-=-1===this.C?this.B.ec:this.B.Ui;return b},pg,pg,pg,pg,pg,pg,pg],ti=[function(a,b){this.A-=-1===this.C?
@ -322,7 +322,7 @@ qe(this)):(pe(this),re(this));this.Hb=!0;this.A-=-1===this.F?this.B.Si:this.B.Ri
c)return Lh.call(this),a;this.ua=c&65535;this.Ga=b%a&65535}else{if(!zh.call(this,this.J,this.M,a))return Lh.call(this),a;this.ua|=0;this.Ga|=0}this.Hb=!0;this.A-=-1===this.F?this.B.oi:this.B.ni;this.L|=2;return a},function(a,b){if(2==this.U){if(!a)return Lh.call(this),a;var c=a<<16>>16,d=(b=this.M<<16|this.J&65535)/c|0;if(d!=d<<16>>16||8086==this.ca&&-32768==d)return Lh.call(this),a;this.ua=d&65535;this.Ga=b%c&65535}else{var c=this.J,d=this.M,e=a,f=0,g=0;0>e&&(e=-e|0,f=1-f);0>d&&(c=-c|0,d=~d+(c?0:
1)|0,g=1,f=1-f);!zh.call(this,c,d,e)||this.ua>2147483647+f||this.Ga>2147483647+g?c=!1:(f&&(this.ua=-this.ua),g&&(this.Ga=-this.Ga),c=!0);if(!c)return Lh.call(this),a;this.ua|=0;this.Ga|=0}this.Hb=!0;this.A-=-1===this.F?this.B.ti:this.B.si;this.L|=2;return a}],Sc=[function(a){var b=a+1|0;he(this,a,1,b,190);this.A-=-1===this.F?this.B.Ze:this.B.Ye;return b&255},function(a){var b=a-1|0;he(this,a,1,b,190,!0);this.A-=-1===this.F?this.B.Ze:this.B.Ye;return b&255},R,R,R,R,R,R],Tc=[function(a){var b=a+1|0;
he(this,a,1,b,this.fb|62);this.A-=-1===this.F?this.B.Ze:this.B.Ye;return b&this.N},function(a){var b=a-1|0;he(this,a,1,b,this.fb|62,!0);this.A-=-1===this.F?this.B.Ze:this.B.Ye;return b&this.N},function(a){y(this,A(this));D(this,a);this.A-=-1===this.F?this.B.ki:this.B.ji;this.L|=2;return a},function(a){if(-1===this.F)return R.call(this,a);this.la=this.ra;Hh.call(this,a,this.ga(this.F+this.U));this.A-=this.B.hi;this.L|=2;this.la=-1;return a},function(a){D(this,a);this.A-=-1===this.F?this.B.Gi:this.B.Fi;
this.L|=2;return a},function(a){if(-1===this.F)return R.call(this,a);Oc(this,a,this.ga(this.F+this.U));this.A-=this.B.Di;this.L|=2;return a},function(a){var b=a;this.L&512&&(a=a-2&65535,80286>this.ca&&(b=a));y(this,b);this.A-=-1===this.F?this.B.Ac:this.B.Wi;this.L|=2;return a},R];function wd(){this.Z.call(this,sh);this.A-=-1===this.F?6:13}function xd(){this.qa.call(this,rh);this.A-=-1===this.F?12:19}var nd=Array(256);
this.L|=2;return a},function(a){if(-1===this.F)return R.call(this,a);Nc(this,a,this.ga(this.F+this.U));this.A-=this.B.Di;this.L|=2;return a},function(a){var b=a;this.L&512&&(a=a-2&65535,80286>this.ca&&(b=a));y(this,b);this.A-=-1===this.F?this.B.Ac:this.B.Wi;this.L|=2;return a},R];function wd(){this.Z.call(this,sh);this.A-=-1===this.F?6:13}function xd(){this.qa.call(this,rh);this.A-=-1===this.F?12:19}var nd=Array(256);
nd[0]=function(){16>(this.Kb(this.Y)&56)&&(this.L|=1);this.Ja.call(this,this.xh,Fh)};nd[1]=function(){this.Kb(this.Y)&16||(this.L|=1);this.Ja.call(this,wi,Fh)};nd[2]=function(){!(this.Pa&1)||this.X&131072?t.call(this,6):this.Z.call(this,wg)};nd[3]=function(){!(this.Pa&1)||this.X&131072?t.call(this,6):this.Z.call(this,Cg)};
nd[5]=function(){this.za?t.call(this,13,0,0,!0):(Ae(this,this.ga(2054)),this.H=this.ga(2086),this.I=this.ga(2088),this.K=this.ga(2090),this.D=this.ga(2094),this.M=this.ga(2096),this.G=this.ga(2098),this.J=this.ga(2100),Cc(this.pa,2102,this.ga(2084)),Cc(this.Ca,2108,this.ga(2082)),Cc(this.P,2114,this.ga(2080)),Cc(this.xa,2120,this.ga(2078)),Mc(this,this.ga(2072)),D(this,this.ga(2074)),v(this,this.ga(2092)),this.ub=this.ga(2126)|this.Kb(2128)<<16,this.wc=this.ub+this.ga(2130),this.Ab=this.ga(2138)|
this.Kb(2140)<<16,this.xc=this.Ab+this.ga(2142),Cc(this.Zb,2132,this.ga(2076)),Cc(this.ia,2144,this.ga(2070)),this.A-=195)};nd[6]=function(){this.za?t.call(this,13,0):(this.Pa&=-9,this.A-=2)};nd[11]=Vc;nd[166]=Vc;nd[255]=Vc;var B=[];B[5]=Vc;
@ -473,8 +473,8 @@ function Jk(a,b,c,d){if(d)a.Ba("Unable to load font ROM (error "+d+": "+b+")");e
function sl(a,b){if(1==b)return a.oa[0]=Ok[0],a.oa[1]=Ok[7],a.oa;if(2==b){var c=a.D.hf;if(a.D===a.B){var d=a.B.Kc[0],c=d&7;d&16&&(c|=8);18!=a.B.Kc[1]&&(c|=32)}a.oa[0]=Ok[c&15];c=c&32?Qk:Pk;for(d=0;d<c.length;d++)a.oa[d+1]=Ok[c[d]];return a.oa}if(a.R===a.Cb)return Ok;a.La&&b&&!a.oa[16]&&(a.La=!1);if(!a.La){var c=a.B,d=c.Be,e,f,g,h,k;if(8==b)for(f=0;256>f;f++)g=d[f]||0,h=g<<2&252,k=g>>4&252,g=g>>10&252,a.oa[f]=[h,k,g,255];else{var m=d&&d[255];e=null!=c.Kc[15]?c.Kc:Rk;for(f=0;16>f;f++)g=e[f]&63,m?(g|=
(c.Kc[20]&12)<<4,c.Kc[16]&128&&(g&=-49,g|=(c.Kc[20]&3)<<4),g=d[g],h=g<<2&252,k=g>>4&252,g=g>>10&252):(h=(g&4?170:0)|(g&32?85:0),k=(g&2?170:0)|(g&16?85:0),g=(g&1?170:0)|(g&8?85:0)),a.oa[f]=[h,k,g,255]}a.La=!0}return a.oa}function dk(a,b,c,d){a.Ab=b;a.Xa=c;a.Ja=d}
function ol(a,b){var c=!1;if(window&&a.Ab&&(!b||a.I)){var d=0,e=a.Ja?a.Ja:8,f=sl(a);null!=a.Xa[0]&&tl(a,3,a.Xa[0],d,e,8,a.Ab,f)&&(c=!0);d=a.Ja?0:2048;e=a.Ja?a.Ja:9;null!=a.Xa[1]&&(tl(a,1,a.Xa[1],d,e,14,a.Ab,Mk,Nk)&&(c=!0),a.Ja&&tl(a,a.Ra,a.Xa[1],0,a.Ja,14,a.Ab,f)&&(c=!0))}return c}function tl(a,b,c,d,e,f,g,h,k){var m=!1;null!=c&&(ul(a,b,c,d,e,f,g,h,k)&&(m=!0),a.Zd&&ul(a,b<<1,c,d,e,f,g,h,k)&&(m=!0));return m}
function ul(a,b,c,d,e,f,g,h,k){var m=!1,n=b&1?0:1,x=a.xa[b],r=16>h.length?h.length:16;x||(x={tc:e<<n,uc:f<<n,be:Array(r),Dh:h.slice(0,r),Ie:k,bg:Array(r)});for(k=0;k<r;k++){var z=h[k],E=x.be[k]?x.Dh[k]:[];if(z[0]!==E[0]||z[1]!==E[1]||z[2]!==E[2]){var m=x,E=k,J=n,W=c,da=d,ua=e,va=f,qd=g,an=[0,0,0,0],te=document.createElement("canvas");te.width=m.tc<<4;te.height=m.uc<<4;for(var sj=te.getContext("2d"),zb=void 0,Nc=void 0,$b=void 0,ue=8>va||!da?va:8,Ff=sj.createImageData(m.tc,m.uc),zb=0;256>zb;zb++){for($b=
0;$b<va;$b++)for(var bn=m.Ie&&E&1&&$b>=va-2,cn=qd[$b<ue?W+zb*ue+$b:da+zb*ue+$b-ue],Gf=0;Gf<=J;Gf++)for(Nc=0;Nc<ua;Nc++){var tj=Nc<<J,uj=($b<<J)+Gf,vj=bn||cn&128>>(8<=Nc&&192<=zb&&223>=zb?7:Nc)?z:an;vl(Ff,tj,uj,vj);J&&vl(Ff,tj+1,uj,vj)}sj.putImageData(Ff,(zb&15)*m.tc,(zb>>4)*m.uc)}m.be[E]="#"+ea(z[0],2)+ea(z[1],2)+ea(z[2],2);m.Dh[E]=z;m.bg[E]=te;m=!0}}a.xa[b]=x;return m}function wl(a){0<a.za||0<=a.ia?0>a.Ea&&(a.Ea=0):a.Ea=-1}
function ul(a,b,c,d,e,f,g,h,k){var m=!1,n=b&1?0:1,x=a.xa[b],r=16>h.length?h.length:16;x||(x={tc:e<<n,uc:f<<n,be:Array(r),Dh:h.slice(0,r),Ie:k,bg:Array(r)});for(k=0;k<r;k++){var z=h[k],E=x.be[k]?x.Dh[k]:[];if(z[0]!==E[0]||z[1]!==E[1]||z[2]!==E[2]){var m=x,E=k,J=n,W=c,da=d,ua=e,va=f,qd=g,an=[0,0,0,0],te=document.createElement("canvas");te.width=m.tc<<4;te.height=m.uc<<4;for(var sj=te.getContext("2d"),zb=void 0,Oc=void 0,$b=void 0,ue=8>va||!da?va:8,Ff=sj.createImageData(m.tc,m.uc),zb=0;256>zb;zb++){for($b=
0;$b<va;$b++)for(var bn=m.Ie&&E&1&&$b>=va-2,cn=qd[$b<ue?W+zb*ue+$b:da+zb*ue+$b-ue],Gf=0;Gf<=J;Gf++)for(Oc=0;Oc<ua;Oc++){var tj=Oc<<J,uj=($b<<J)+Gf,vj=bn||cn&128>>(8<=Oc&&192<=zb&&223>=zb?7:Oc)?z:an;vl(Ff,tj,uj,vj);J&&vl(Ff,tj+1,uj,vj)}sj.putImageData(Ff,(zb&15)*m.tc,(zb>>4)*m.uc)}m.be[E]="#"+ea(z[0],2)+ea(z[1],2)+ea(z[2],2);m.Dh[E]=z;m.bg[E]=te;m=!0}}a.xa[b]=x;return m}function wl(a){0<a.za||0<=a.ia?0>a.Ea&&(a.Ea=0):a.Ea=-1}
function rl(a){if(a.I){for(var b=10;15>=b;b++)if(null==a.D.ab[b])return;var c=a.D.ab[10],b=c&31,d=a.D.ab[11]&31,e=a.D.ab[9]&31,f=!1;a.D===a.B&&(f=!0,7!=e||4!=b||d||(d=7));if(c&32||b>d&&!f||b>e)xl(a);else{c=a.D.ab[15]+((a.D.ab[14]&63)<<8);a.ia!=c&&(xl(a),a.ia=c);d=d-b+1;if(a.td!=b||a.Gc!=d)a.td=b,a.Gc=d;a.Da=e+1;wl(a)}}}
function xl(a){if(0<=a.ia){if(void 0!==a.ba){var b=a.ba[a.ia];if(b&131072){var b=b&-131073,c=a.ia%a.H,d=a.ia/a.H|0;a.I&&a.xa[a.I]&&(a.Ga&&yl(a,c,d,b,a.Ga),yl(a,c,d,b));a.ba[a.ia]=b}}a.ia=-1}}
function zl(a){var b,c=a.D;a.Zc=!1;var d=c.Hd[5];if(null!=d){b=1024;var e=0,f=c.Hd[3]&31;switch(d&3){case 0:if(f){e=32;switch(f&24){case 8:e=96;break;case 16:e=160;break;case 24:e=224}c.Hc=f&7}break;case 1:e=1;break;case 2:switch(f&24){default:e=2;break;case 8:e=98;break;case 16:e=162;break;case 24:e=226}break;case 3:a.Ra==ek&&(e=3,c.Hc=f&7)}d&8&&(b=1280);c=c.De[4];null!=c&&(c&4||(b|=4096,e|=16),d&64&&(c&8&&(b|=16384,e|=4),a.Zc=!0));b|=e}return b}
@ -595,33 +595,34 @@ function gn(a,b,c){b.errorCode=4;b.ee&&b.ee.length==b.vb||(b.ee=Array(b.vb));b.U
l.ze=function(a,b,c){var d=-1,e=null,f=0;if(a.errorCode)return b&&b(d,!1,e,f),d;var g=!1!==c?1:0;if(a.Wa&&(f=a.Ua,d=a.ta.read(a.Wa,a.Ua),a.Ua+=g,0<=d))return e=a.Wa,b&&b(d,!1,e,f),d;if(b){if(a.ta)return a.ta.seek(a.Jd,a.Ya,a.mb+a.vf,!1,function(c,k){(a.Wa=c)?(e=c,f=a.Ua=0,hn(a),d=a.ta.read(a.Wa,a.Ua),a.Ua+=g):a.errorCode=20;b(d,k,e,f)}),d;a.errorCode=20;b(d,!1,e,f)}return d};
function Xm(a,b){if(a.errorCode)return-1;do{if(a.Wa&&a.ta.write(a.Wa,a.Ua++,b))break;a.ta&&a.ta.seek(a.Jd,a.Ya,a.mb+a.vf,!0,function(b){a.Wa=b});if(!a.Wa){a.errorCode=20;b=-1;break}a.Ua=0;hn(a)}while(1);return b}function hn(a){a.mb++;var b=1-a.vf;a.mb>=a.eb+b&&(a.mb=b,a.Ya++,a.Ya>=a.jb&&(a.Ya=0,a.Jd++))}l.Sk=function(){var a=this.A.M&255;!(this.A.J>>8)&&128<a&&(this.Y=a-128);return!0};l.Tk=function(){var a;(a=this.A.J>>8||!this.S)||(a=!(this.S.gc[0].Vc&64));return a?!0:!1};
var Nm={800:Z.prototype.Pk,801:Z.prototype.Qk,802:Z.prototype.Ok},Mm={496:Z.prototype.vj,497:Z.prototype.Vj,498:Z.prototype.Xj,499:Z.prototype.Yj,500:Z.prototype.Tj,501:Z.prototype.Sj,502:Z.prototype.Uj,503:Z.prototype.Zj},Pm={800:Z.prototype.Xl,801:Z.prototype.$l,802:Z.prototype.Zl,803:Z.prototype.Yl,807:Z.prototype.ih,811:Z.prototype.ih,815:Z.prototype.ih},Om={496:Z.prototype.hl,497:Z.prototype.ml,498:Z.prototype.kl,499:Z.prototype.ll,500:Z.prototype.gl,501:Z.prototype.fl,502:Z.prototype.il,503:Z.prototype.el,
1014:Z.prototype.jl};Ea(function(){for(var a=Za(document,"pcx86","hdc"),b=0;b<a.length;b++){var c=a[b],d=Wa(c),d=new Z(d);Ya(d,c)}});function be(a,b,c){this.id=a.id;this.key=jn(a,b,c);this.Ia=a.Ia;kn(this,a.gj)}function jn(a,b,c){a=a.id;if(b){var d=b.indexOf(".");0<d&&(a+=".v"+b.substr(0,d))}c&&(a+="."+c);return a}
be.prototype={constructor:be,value:function(){return this[this.id]},data:function(){return this[this.id]},load:function(a){return a?(this[this.id]=a,this.A=!0):this.A?!0:ta()&&(a=wa(this.key))?(this[this.id]=a,this.A=!0):!1},toString:function(){var a=this[this.id];return"string"==typeof a?a:JSON.stringify(a)},clear:function(a){kn(this);var b=[];try{for(var c=0,d=window.localStorage.length;c<d;c++)b.push(window.localStorage.key(c))}catch(e){}for(c=0;c<b.length;c++)if((d=b[c])&&(a||d.substr(0,this.key.length)==
this.key)){try{window.localStorage.removeItem(d)}catch(e){}b.splice(c,1);c=0}}};function kn(a,b){a[a.id]={};b&&C(a,"parms",b);a.A=!1}function ln(a){var b=!0;if(ta()){var c=JSON.stringify(a[a.id]);xa(a.key,c)||(p("Unable to store "+c.length+" bytes in browser local storage"),b=!1)}return b}function mn(a){var b=!0;try{a[a.id]=JSON.parse(a[a.id])}catch(c){p(c.message||c),b=!1}return b}function nn(a,b){return a[a.id][b]||null}function C(a,b,c){try{a[a.id][b]=c}catch(d){}}
function on(a,b,c){Ia.call(this,"Computer",a,on);this.da.Sb=!1;pn(this,b);this.ba=jc(this,"autoPower",a);this.G=0;this.ea=a.busWidth||a.buswidth;this.B=qn;this.R=null;this.K=this.Z=!1;this.ia=jc(this,"url")||"";this.ma=(Math.random()+.1).toString(36).substr(2,12);this.C=rn(this);if(this.A=Va("CPU",this.id)){this.Ia=Va("Debugger",this.id);this.I=[];for(b=null;b=kb(this,"Video",b);)this.I.push(b);this.ha=new rb({id:this.mf+".bus",busWidth:this.ea},this.A,this.Ia);var d,e=Ta(this.id);if((this.D=Va("Panel",
this.id))&&this.D.hg)for(b=0;b<e.length;b++)d=e[b],d.Ba=this.D.Ba,d.rc=this.D.rc,d.hg=this.D.hg;this.rc("PCx86 v1.24.0\nCopyright \u00a9 2012-2016 Jeff Parsons <Jeff@pcjs.org>\nLicense: GPL version 3 or later <http://gnu.org/licenses/gpl.html>");for(b=0;b<e.length;b++)d=e[b],d.pc&&d.pc(this,this.ha,this.A,this.Ia);b=null;d=a.resume;void 0!==d&&(1<d.length?b=this.S=d:this.B=parseInt(d,10));var f;if(a=jc(this,"state")||(f=!0,a.state))b=this.W=a,f||(this.K=!0,this.B=qn),this.B&&(this.P=new be(this,"1.24.0"),
this.P.load()?b=null:delete this.P);!b&&this.B&&(b=sn(this))&&(this.K=!0);if(b){var g=this;pa(b,null,!0,function(a,b,c){c?(g.S=null,g.K=!1,g.Ba("Unable to load machine state from server (error "+c+(b?": "+(String.prototype.trim?b.trim():b.replace(/^\s+|\s+$/g,"")):"")+")")):(g.R=b,g.Z=!0);ab(g)})}else ab(this);this.ka.power||(this.ba=!0);!c&&this.ba&&tn(this,this.ff)}else p("Unable to find CPU component")}Qa(on);var qn=0;l=on.prototype;l.se=function(){return this.ma};
function pn(a,b){if(!b){var c;if("object"==typeof resources&&(c=resources.parms))try{b=eval("("+c+")")}catch(d){p(d.message+" ("+c+")")}}a.L=b}function jc(a,b,c){var d=b.toLowerCase(),d=La[b]||La[d];void 0===d&&a.L&&(d=a.L[b]);void 0===d&&c&&(d=c[b]);void 0===d&&"object"==typeof resources&&resources[b]&&(d=b);return d}l.Ad=function(){return this.C||""};function tn(a,b,c){for(var d=Ta(a.id),e=0;e<=d.length;e++){var f=e<d.length?d[e]:a;if(!bb(f)){bb(f,function(){tn(a,b,c)});return}}b.call(a,c)}
function un(a,b){var c=new be(a,"1.24.0","validate");if(c.load()&&mn(c)){var d=nn(c,"timestamp"),e=b?nn(b,"timestamp"):"unknown";d!=e&&(a.Ba("Machine state may be out-of-date\n("+d+" vs. "+e+")\nCheck your browser's local storage limits"),b||c.clear())}}
l.ff=function(a){void 0===a&&(a=this.B||(this.R?1:qn));if(!this.G){this.G++;var b=!1,c=!1;this.Y=!1;var d=this.P||new be(this,"1.24.0");if(-1==a)b=!0;else if(a>qn){if(d.load(this.R)){this.H=new be(this,"1.24.0","failsafe");this.H.load()&&(vn(this,d),a=2,kn(this.H));C(this.H,"timestamp",la());ln(this.H);var e=this.B&&!this.K;if(1==a||ra("Click OK to restore the previous PCx86 machine state, or CANCEL to reset the machine.")){if(c=mn(d)){var f=nn(d,"code"),g=nn(d,"data");f&&("ok"==f?d.load(g):("error"==
f&&"no machine state"!=g?(this.Ba("Error: "+g),"unable to verify user"==g&&(xa("user",""),this.C=null)):this.rc(f+": "+g),kn(d),d.load()?(c=mn(d),e=!0):c=!1))}e&&un(this,c?d:null)}else 2==a&&d.clear()}else un(this);delete this.R;delete this.P}e=Ta(this.id);for(f=0;f<e.length;f++)g=e[f],g!==this&&g!=this.A&&(c=wn(this,g,d,b,c));b=[d,a,c];-1!=a?tn(this,this.Oh,b):this.Oh(b)}};
function wn(a,b,c,d,e){if(!b.da.Sb){b.da.Sb=!0;if(b.Vb){var f=null;e&&((f=nn(c,b.id))||(f=nn(c,b.id.replace(/[a-z0-9]\./i,"."))));"string"===typeof f&&(f=null);!b.Vb(f,d)&&f&&(p("Unable to restore state for "+b.type),a.W&&!a.Z?(c.clear(),a.B=qn,window&&window.location.reload()):a.Y=!0,b.Vb(null),e=!1)}if(!d&&b.Ah)for(a=b.Ah.split("|"),c=0;c<a.length;c++)b.status(a[c])}return e}
l.Oh=function(a){var b=a[0],c=0>a[1];a=a[2];this.la=!0;this.da.Sb=!0;var d=this.ka.power;d&&(d.textContent="Shutdown");this.A&&(wn(this,this.A,b,c,a),nc(this.A));this.Y&&(vn(this,b),b.clear());!c&&this.H&&(this.H.clear(),delete this.H);this.G=0};
function vn(a,b){if(ra("There may be a problem with your PCx86 machine.\n\nTo help us diagnose it, click OK to send this PCx86 machine state to http://www.pcjs.org.")){var c=a.Ad(),d=b.toString(),e={app:"PCx86",ver:"1.24.0"};e.url=a.ia;e.user=c;e.type="bug";e.data=d;pa("http://www.pcjs.org/api/v1/report",e,!0)}}
function xn(a,b,c){var d,e="none";if(a.G)return null;a.G--;var f=new be(a,"1.24.0"),g=new be(a,"1.24.0","validate"),h=la();C(g,"timestamp",h);C(f,"timestamp",h);C(f,"version","1.24.0");C(f,"url",window?window.location.href:null);C(f,"browser",window?window.navigator.userAgent:"");a.A&&a.A.Ub&&(c&&oc(a.A),d=a.A.Ub(b,c),"object"===typeof d&&C(f,a.A.id,d),c&&(a.A.da.Sb=!1,!1===d&&(e=null)));for(var h=Ta(a.id),k=0;k<h.length;k++){var m=h[k];m.da.Sb&&(m.Ub&&(d=m.Ub(b,c),"object"===typeof d&&C(f,m.id,d)),
c&&(m.da.Sb=!1,!1===d&&(e=null)))}e&&(c?(h=d=!1,b?(a.C&&yn(a,a.C,f.toString()),ln(g)&&ln(f)||(e=null,d=h=!0)):a.B&&(d=!0,h=3==a.B),d&&f.clear(h)):e=f.toString());c&&(a.da.Sb=!1,b=a.ka.power)&&(b.textContent="Power");a.G=0;return e}l.reset=function(){this.ha&&this.ha.reset&&this.ha.reset();for(var a=Ta(this.id),b=0;b<a.length;b++){var c=a[b];c!==this&&c!==this.ha&&c.reset&&c.reset()}};
1014:Z.prototype.jl};Ea(function(){for(var a=Za(document,"pcx86","hdc"),b=0;b<a.length;b++){var c=a[b],d=Wa(c),d=new Z(d);Ya(d,c)}});
function jn(a,b,c){Ia.call(this,"Computer",a,jn);this.da.Sb=!1;kn(this,b);this.ba=jc(this,"autoPower",a);this.G=0;this.ea=a.busWidth||a.buswidth;this.B=ln;this.R=null;this.K=this.Z=!1;this.ia=jc(this,"url")||"";this.ma=(Math.random()+.1).toString(36).substr(2,12);this.C=mn(this);if(this.A=Va("CPU",this.id)){this.Ia=Va("Debugger",this.id);this.I=[];for(b=null;b=kb(this,"Video",b);)this.I.push(b);this.ha=new rb({id:this.mf+".bus",busWidth:this.ea},this.A,this.Ia);var d,e=Ta(this.id);if((this.D=Va("Panel",
this.id))&&this.D.hg)for(b=0;b<e.length;b++)d=e[b],d.Ba=this.D.Ba,d.rc=this.D.rc,d.hg=this.D.hg;this.rc("PCx86 v1.24.0\nCopyright \u00a9 2012-2016 Jeff Parsons <Jeff@pcjs.org>\nLicense: GPL version 3 or later <http://gnu.org/licenses/gpl.html>");for(b=0;b<e.length;b++)d=e[b],d.pc&&d.pc(this,this.ha,this.A,this.Ia);b=null;d=a.resume;void 0!==d&&(1<d.length?b=this.S=d:this.B=parseInt(d,10));var f;if(a=jc(this,"state")||(f=!0,a.state))b=this.W=a,f||(this.K=!0,this.B=ln),this.B&&(this.P=new be(this,"1.24.0"),
this.P.load()?b=null:delete this.P);!b&&this.B&&(b=nn(this))&&(this.K=!0);if(b){var g=this;pa(b,null,!0,function(a,b,c){c?(g.S=null,g.K=!1,g.Ba("Unable to load machine state from server (error "+c+(b?": "+(String.prototype.trim?b.trim():b.replace(/^\s+|\s+$/g,"")):"")+")")):(g.R=b,g.Z=!0);ab(g)})}else ab(this);this.ka.power||(this.ba=!0);!c&&this.ba&&on(this,this.ff)}else p("Unable to find CPU component")}Qa(jn);var ln=0;l=jn.prototype;l.se=function(){return this.ma};
function kn(a,b){if(!b){var c;if("object"==typeof resources&&(c=resources.parms))try{b=eval("("+c+")")}catch(d){p(d.message+" ("+c+")")}}a.L=b}function jc(a,b,c){var d=b.toLowerCase(),d=La[b]||La[d];void 0===d&&a.L&&(d=a.L[b]);void 0===d&&c&&(d=c[b]);void 0===d&&"object"==typeof resources&&resources[b]&&(d=b);return d}l.Ad=function(){return this.C||""};function on(a,b,c){for(var d=Ta(a.id),e=0;e<=d.length;e++){var f=e<d.length?d[e]:a;if(!bb(f)){bb(f,function(){on(a,b,c)});return}}b.call(a,c)}
function pn(a,b){var c=new be(a,"1.24.0","validate");if(c.load()&&qn(c)){var d=rn(c,"timestamp"),e=b?rn(b,"timestamp"):"unknown";d!=e&&(a.Ba("Machine state may be out-of-date\n("+d+" vs. "+e+")\nCheck your browser's local storage limits"),b||c.clear())}}
l.ff=function(a){void 0===a&&(a=this.B||(this.R?1:ln));if(!this.G){this.G++;var b=!1,c=!1;this.Y=!1;var d=this.P||new be(this,"1.24.0");if(-1==a)b=!0;else if(a>ln){if(d.load(this.R)){this.H=new be(this,"1.24.0","failsafe");this.H.load()&&(sn(this,d),a=2,tn(this.H));C(this.H,"timestamp",la());un(this.H);var e=this.B&&!this.K;if(1==a||ra("Click OK to restore the previous PCx86 machine state, or CANCEL to reset the machine.")){if(c=qn(d)){var f=rn(d,"code"),g=rn(d,"data");f&&("ok"==f?d.load(g):("error"==
f&&"no machine state"!=g?(this.Ba("Error: "+g),"unable to verify user"==g&&(xa("user",""),this.C=null)):this.rc(f+": "+g),tn(d),d.load()?(c=qn(d),e=!0):c=!1))}e&&pn(this,c?d:null)}else 2==a&&d.clear()}else pn(this);delete this.R;delete this.P}e=Ta(this.id);for(f=0;f<e.length;f++)g=e[f],g!==this&&g!=this.A&&(c=vn(this,g,d,b,c));b=[d,a,c];-1!=a?on(this,this.Oh,b):this.Oh(b)}};
function vn(a,b,c,d,e){if(!b.da.Sb){b.da.Sb=!0;if(b.Vb){var f=null;e&&((f=rn(c,b.id))||(f=rn(c,b.id.replace(/[a-z0-9]\./i,"."))));"string"===typeof f&&(f=null);!b.Vb(f,d)&&f&&(p("Unable to restore state for "+b.type),a.W&&!a.Z?(c.clear(),a.B=ln,window&&window.location.reload()):a.Y=!0,b.Vb(null),e=!1)}if(!d&&b.Ah)for(a=b.Ah.split("|"),c=0;c<a.length;c++)b.status(a[c])}return e}
l.Oh=function(a){var b=a[0],c=0>a[1];a=a[2];this.la=!0;this.da.Sb=!0;var d=this.ka.power;d&&(d.textContent="Shutdown");this.A&&(vn(this,this.A,b,c,a),nc(this.A));this.Y&&(sn(this,b),b.clear());!c&&this.H&&(this.H.clear(),delete this.H);this.G=0};
function sn(a,b){if(ra("There may be a problem with your PCx86 machine.\n\nTo help us diagnose it, click OK to send this PCx86 machine state to http://www.pcjs.org.")){var c=a.Ad(),d=b.toString(),e={app:"PCx86",ver:"1.24.0"};e.url=a.ia;e.user=c;e.type="bug";e.data=d;pa("http://www.pcjs.org/api/v1/report",e,!0)}}
function wn(a,b,c){var d,e="none";if(a.G)return null;a.G--;var f=new be(a,"1.24.0"),g=new be(a,"1.24.0","validate"),h=la();C(g,"timestamp",h);C(f,"timestamp",h);C(f,"version","1.24.0");C(f,"url",window?window.location.href:null);C(f,"browser",window?window.navigator.userAgent:"");a.A&&a.A.Ub&&(c&&oc(a.A),d=a.A.Ub(b,c),"object"===typeof d&&C(f,a.A.id,d),c&&(a.A.da.Sb=!1,!1===d&&(e=null)));for(var h=Ta(a.id),k=0;k<h.length;k++){var m=h[k];m.da.Sb&&(m.Ub&&(d=m.Ub(b,c),"object"===typeof d&&C(f,m.id,d)),
c&&(m.da.Sb=!1,!1===d&&(e=null)))}e&&(c?(h=d=!1,b?(a.C&&xn(a,a.C,f.toString()),un(g)&&un(f)||(e=null,d=h=!0)):a.B&&(d=!0,h=3==a.B),d&&f.clear(h)):e=f.toString());c&&(a.da.Sb=!1,b=a.ka.power)&&(b.textContent="Power");a.G=0;return e}l.reset=function(){this.ha&&this.ha.reset&&this.ha.reset();for(var a=Ta(this.id),b=0;b<a.length;b++){var c=a[b];c!==this&&c!==this.ha&&c.reset&&c.reset()}};
l.start=function(a,b){for(var c=Ta(this.id),d=0;d<c.length;d++){var e=c[d];"CPU"!=e.type&&e!==this&&e.start&&e.start(a,b)}};l.stop=function(a,b){for(var c=Ta(this.id),d=0;d<c.length;d++){var e=c[d];"CPU"!=e.type&&e!==this&&e.stop&&e.stop(a,b)}};
l.zb=function(a,b,c){var d=this;switch(b){case "power":return this.ka[b]=c,c.onclick=function(){d.G||(d.da.Sb?xn(d,!1,!0):tn(d,d.ff))},!0;case "reset":return this.ka[b]=c,c.onclick=function(){if(d.da.Sb&&!d.G)if(d.B&&!d.S){var a=ra("Click OK to save changes to this PCx86 machine.\n\nWARNING: If you CANCEL, all disk changes will be discarded.");xn(d,a,!0);!a&&d.W?window&&window.location.reload():(a||(d.kg=!0),d.ff(qn),d.kg=!1)}else d.reset(),d.A&&nc(d.A)},!0;case "save":if(ha(qa(),"pcjs.org")){c.parentNode.removeChild(c);
break}this.ka[b]=c;c.onclick=function(){var a=rn(d,!0);if(a){var b=!!(d.B&&!d.S||d.W),c=xn(d,b);b?yn(d,a,c):d.Ba("Resume disabled, machine state not saved")}};return!0}return!1};
function rn(a,b){var c=a.C;c||(c=wa("user"),void 0!==c?!c&&b&&(c=null,window&&(c=window.prompt("Saving machine states on the pcjs.org server is currently unsupported.\n\nIf you're running your own server, enter your user ID below.","")),c&&((c=zn(a,c))||a.Ba("The user ID is invalid."))):b&&a.Ba("Browser local storage is not available"));return c}
function zn(a,b){a.C=null;var c=pa(qa()+"/api/v1/user?req=verify&user="+b),d=c[1];if(!c[0]&&d)try{c=eval("("+d+")"),c.code&&"ok"==c.code&&(xa("user",c.data),a.C=c.data)}catch(e){p(e.message+" ("+d+")")}return a.C}function sn(a){var b=null;a.C&&(b=qa()+"/api/v1/user?req=load&user="+a.C+"&state="+jn(a,"1.24.0"));return b}
function yn(a,b,c){if(c){var d={req:"store"};d.user=b;d.state=jn(a,"1.24.0");d.data=c;b=pa(qa()+"/api/v1/user",d);d=b[0];if(b[1]){if(d){var e=d.indexOf("\n");0<e&&(d=d.substr(0,e));d.indexOf("Error: ")||(d=d.substr(7))}d='{"code":'+b[1]+',"data":"'+d+'"}'}b=JSON.parse(d);b&&"ok"==b.code?a.Ba("Machine state saved to server"):c&&(c=b&&b.data||"unable to save machine state",c="error"==b.code?"Error: "+c:"Error "+b.code+": "+c,a.Ba(c),xa("user",""),a.C=null)}}
l.zb=function(a,b,c){var d=this;switch(b){case "power":return this.ka[b]=c,c.onclick=function(){d.G||(d.da.Sb?wn(d,!1,!0):on(d,d.ff))},!0;case "reset":return this.ka[b]=c,c.onclick=function(){if(d.da.Sb&&!d.G)if(d.B&&!d.S){var a=ra("Click OK to save changes to this PCx86 machine.\n\nWARNING: If you CANCEL, all disk changes will be discarded.");wn(d,a,!0);!a&&d.W?window&&window.location.reload():(a||(d.kg=!0),d.ff(ln),d.kg=!1)}else d.reset(),d.A&&nc(d.A)},!0;case "save":if(ha(qa(),"pcjs.org")){c.parentNode.removeChild(c);
break}this.ka[b]=c;c.onclick=function(){var a=mn(d,!0);if(a){var b=!!(d.B&&!d.S||d.W),c=wn(d,b);b?xn(d,a,c):d.Ba("Resume disabled, machine state not saved")}};return!0}return!1};
function mn(a,b){var c=a.C;c||(c=wa("user"),void 0!==c?!c&&b&&(c=null,window&&(c=window.prompt("Saving machine states on the pcjs.org server is currently unsupported.\n\nIf you're running your own server, enter your user ID below.","")),c&&((c=yn(a,c))||a.Ba("The user ID is invalid."))):b&&a.Ba("Browser local storage is not available"));return c}
function yn(a,b){a.C=null;var c=pa(qa()+"/api/v1/user?req=verify&user="+b),d=c[1];if(!c[0]&&d)try{c=eval("("+d+")"),c.code&&"ok"==c.code&&(xa("user",c.data),a.C=c.data)}catch(e){p(e.message+" ("+d+")")}return a.C}function nn(a){var b=null;a.C&&(b=qa()+"/api/v1/user?req=load&user="+a.C+"&state="+zn(a,"1.24.0"));return b}
function xn(a,b,c){if(c){var d={req:"store"};d.user=b;d.state=zn(a,"1.24.0");d.data=c;b=pa(qa()+"/api/v1/user",d);d=b[0];if(b[1]){if(d){var e=d.indexOf("\n");0<e&&(d=d.substr(0,e));d.indexOf("Error: ")||(d=d.substr(7))}d='{"code":'+b[1]+',"data":"'+d+'"}'}b=JSON.parse(d);b&&"ok"==b.code?a.Ba("Machine state saved to server"):c&&(c=b&&b.data||"unable to save machine state",c="error"==b.code?"Error: "+c:"Error "+b.code+": "+c,a.Ba(c),xa("user",""),a.C=null)}}
function kb(a,b,c){a=Ta(a.id);for(var d=0;d<a.length;d++){var e=a[d];if(c)c==e&&(c=null);else if(e.type==b)return e}return null}function uc(a,b){if(a.I.length){var c=0,d=0;b&&window&&(c=window.scrollX,d=window.scrollY);var e=a.I[0];e.G&&e.G.focus();b&&window&&window.scrollTo(c,d)}}l.Xd=function(a){this.A&&this.A.Xd(a);this.D&&this.D.Xd(a)};
function xc(a,b){for(var c=0;c<a.I.length;c++)kl(a.I[c],b);if(a.D&&(c=a.D,c.ua)){ob(c,18,c.S,c.ra);if(c.Ga){var d=c.ha,e=c.B,f,g;null==f&&(f=0);null==g&&(g=d.L-f|0);null==e&&(e={gg:0,hd:0,ag:[]});var h=f>>>d.ea;f=f+g-1>>>d.ea;e.gg=0;for(e.hd=0;h<=f;)g=d.R[h],e.gg+=g.size,g.size&&(e.ag.push(na(nb,h,0,0,g.type)),e.hd++),h++;c.B=e;c.ma=c.B.hd*c.ha.xb/691200;d=0;c.B.Ih=0;c.B.Je||(c.B.Je=[]);var e=-1,h=0,k=-1;for(f=0;f<c.B.hd;f++){var m=c.B.ag[f];g=oa(nb.type,m);m=oa(nb.cj,m);if(g!=e||m!=k+1)(k=f-h)&&
(d+=qb(c,h,k,e)),e=g,h=f;k=m}d+=qb(c,h,f-h,e);e=c.B.Cj!=d;c.B.Cj=d;if(e){e=new ib(0,0,c.S.width,c.S.height);c.B.ce=[];h=c.B.hd;for(d=0;d<c.B.Ih;d++)f=c.B.Je[d].hd,c.B.ce.push(jb(e,f,h,!d)),h-=f;for(d=0;d<c.B.ce.length;d++)e=c.B.Je[d],h=f=c.B.ce[d],g=c.ra,(k=Wb[e.type])||(k=new hb),g.strokeStyle="black",g.strokeRect(h.x,h.y,h.Fc,h.A),g.fillStyle="string"==typeof k?k:k.toString(),g.fillRect(h.x,h.y,h.Fc,h.A),h=c,g=f,h.P=h.ia,h.L=h.la,f=g.x+(g.Fc>>1),k=g.y+(g.A>>1),m=g.A,g.Fc<g.A&&(m=g.Fc,h.ea=!0,h.G.save(),
h.G.translate(f,k),h.G.rotate(-Math.PI/2),f=k=0),m<h.L&&(h.L=m,h.P=h.L+"px Monaco, Lucida Console, Courier New"),g=k,h.D=f,h.K=g,h=c,e=Cb[e.type]+" ("+(e.hd*c.ha.xb/1024|0)+"Kb)",h.G.font=h.P,h.D-=h.G.measureText(e).width>>1,h.K+=(h.L>>1)-2,pb(h,e),h.ea&&(h.G.restore(),h.ea=!1)}}else pb(c,"This space intentionally left blank");c.context.drawImage(c.S,0,0,c.S.width,c.S.height,c.Oa,c.Xa,c.Da,c.Fa);c.ua=!1}}
Ea(function(){for(var a=Za(document,"pcx86-machine"),b=0;b<a.length;b++)for(var c=a[b],d=Wa(c),c=Za(c,"pcx86","computer"),e=0;e<c.length;e++){var f=c[e],g=Wa(f),g=new on(g,d,!0);Ya(g,f);g.ba&&tn(g,g.ff)}});Aa.show.push(function(){for(var a=Za(document,"pcx86","computer"),b=0;b<a.length;b++){var c=Wa(a[b]);(c=Va("Computer",c.id))&&c.la&&!c.da.Sb&&c.ff(-1)}});
Aa.exit.push(function(){for(var a=Za(document,"pcx86","computer"),b=0;b<a.length;b++){var c=Wa(a[b]);(c=Va("Computer",c.id))&&c.da.Sb&&xn(c,!(!c.B||c.S),!0)}});var An=0;function Bn(a,b,c,d,e,f){e("Loading "+a+"...");pa(a,null,!0,function(g,h,k){k?(h||(h="unable to load "+a+" ("+k+")"),f(h,null)):Cn(h,a,b,c,d,e,f)})}
Ea(function(){for(var a=Za(document,"pcx86-machine"),b=0;b<a.length;b++)for(var c=a[b],d=Wa(c),c=Za(c,"pcx86","computer"),e=0;e<c.length;e++){var f=c[e],g=Wa(f),g=new jn(g,d,!0);Ya(g,f);g.ba&&on(g,g.ff)}});Aa.show.push(function(){for(var a=Za(document,"pcx86","computer"),b=0;b<a.length;b++){var c=Wa(a[b]);(c=Va("Computer",c.id))&&c.la&&!c.da.Sb&&c.ff(-1)}});
Aa.exit.push(function(){for(var a=Za(document,"pcx86","computer"),b=0;b<a.length;b++){var c=Wa(a[b]);(c=Va("Computer",c.id))&&c.da.Sb&&wn(c,!(!c.B||c.S),!0)}});function be(a,b,c){this.id=a.id;this.key=zn(a,b,c);this.Ia=a.Ia;tn(this,a.gj)}function zn(a,b,c){a=a.id;if(b){var d=b.indexOf(".");0<d&&(a+=".v"+b.substr(0,d))}c&&(a+="."+c);return a}
be.prototype={constructor:be,value:function(){return this[this.id]},data:function(){return this[this.id]},load:function(a){return a?(this[this.id]=a,this.A=!0):this.A?!0:ta()&&(a=wa(this.key))?(this[this.id]=a,this.A=!0):!1},toString:function(){var a=this[this.id];return"string"==typeof a?a:JSON.stringify(a)},clear:function(a){tn(this);var b=[];try{for(var c=0,d=window.localStorage.length;c<d;c++)b.push(window.localStorage.key(c))}catch(e){}for(c=0;c<b.length;c++)if((d=b[c])&&(a||d.substr(0,this.key.length)==
this.key)){try{window.localStorage.removeItem(d)}catch(e){}b.splice(c,1);c=0}}};function tn(a,b){a[a.id]={};b&&C(a,"parms",b);a.A=!1}function un(a){var b=!0;if(ta()){var c=JSON.stringify(a[a.id]);xa(a.key,c)||(p("Unable to store "+c.length+" bytes in browser local storage"),b=!1)}return b}function qn(a){var b=!0;try{a[a.id]=JSON.parse(a[a.id])}catch(c){p(c.message||c),b=!1}return b}function rn(a,b){return a[a.id][b]||null}function C(a,b,c){try{a[a.id][b]=c}catch(d){}}var An=0;
function Bn(a,b,c,d,e,f){e("Loading "+a+"...");pa(a,null,!0,function(g,h,k){k?(h||(h="unable to load "+a+" ("+k+")"),f(h,null)):Cn(h,a,b,c,d,e,f)})}
function Cn(a,b,c,d,e,f,g){function h(a,f){if(f)g(f,null);else{if(c){Sa(c,b,a);var h=b;h&&0>h.indexOf("/")&&"/"==window.location.pathname.slice(-1)&&(h=window.location.pathname+h);d?"}"==d.slice(-1)?(d=d.slice(0,-1),1<d.length&&(d+=",")):d='{state:"'+d+'",':d="{";d+='url:"'+h+'"}';"object"==typeof resources&&(h=null);a=a.replace(/(<machine[^>]*\sid=)(['"]).*?\2/,"$1$2"+c+"$2"+(d?" parms='"+d+"'":"")+(h?' url="'+h+'"':""))}e||(a=a.replace(/(<xsl:variable name="APPCLASS">).*?(<\/xsl:variable>)/,"$1pcx86$2"));
h=null;if("<"==a.charAt(0))try{e||(a=a.replace(/<!DOCTYPE(.|[\r\n])*]>\s*/g,"")),window.ActiveXObject||"ActiveXObject"in window?(h=new window.ActiveXObject("Microsoft.XMLDOM"),h.async=!1,h.loadXML(a)):h=(new window.DOMParser).parseFromString(a,"text/xml")}catch(x){h=null,a=x.message}else a="unrecognized XML: "+(255<a.length?a.substr(0,255)+"...":a);g(a,h)}}a?e?Dn(a,f,h):h(a,null):g("no data"+(b?" for file: "+b:""),null)}
function Dn(a,b,c){var d;if(d=/<([a-z]+)\s+ref="(.*?)"(.*?)\/>/g.exec(a)){var e=d[2];b("Loading "+e+"...");pa(e,null,!0,function(f,g,h){if(h||!g)c(a,"unable to resolve XML reference: "+d[0]+" ("+h+")");else{if(f=d[3])if(h=g.match(new RegExp("<"+d[1]+"[^>]*>"))){for(var k=h[0],m,n=/( [a-z]+=)(['"])(.*?)\2/g;m=n.exec(f);)k=0>k.indexOf(m[1])?k.replace(">",m[0]+">"):k.replace(new RegExp(m[1]+"(['\"])(.*?)\\1"),m[0]);h[0]!=k&&(g=g.replace(h[0],k))}else{c(a,"missing <"+d[1]+"> in "+e);return}g=g.replace(/<\?xml[^>]*>[\r\n]*/,
@ -632,4 +633,4 @@ a):f("transformToFragment failed")):f("unable to transform XML: unsupported brow
function Gn(a,b,c,d){if(!c&&b){d.push(b);a=Ra[d[0]];b=null;for(var e in a)if(ha(e,"components.xsl")){b=e.replace(".xsl",".css");break}b?pa(b,null,!0,function(a,b){Hn(b,d)}):Hn(null,d)}else p("Error ("+c+") requesting "+a)}
function Hn(a,b){var c,d,e,f=b[0],g=b[1];c=b[4];c=c.match(/^(\s*\(function\(\)\{)([\s\S]*)(}\)\(\);\s*)$/);var h=Ra[f],k={},m;for(m in h){var n=h[m],x=ga(m);if("xml"==x){for(x=/[ \t]*<disk [^>]*path=(['"])(.*?)\1.*?<\/disk>\n?/g;d=x.exec(h[m]);){var r=d[2];r&&(h[r]||(n=n.replace(d[0],"")))}d=m=fa(m)}else"xsl"==x&&(e=m=fa(m));k[m]=n}a&&(k[m="css"]=a);b[2]&&(k[m="parms"]=b[2]);b[3]&&(k[m="state"]=b[3]);d&&e?(m=JSON.stringify(k),g+=".js",c=c[1]+"var resources="+m+";"+c[2]+c[3],c=c.replace(/\u00A9/g,
"&#xA9;"),c=za(c,"javascript",!1,g),c=c+(', copy it to your web server as "'+g+'", and then add the following to your web page:\n\n')+('<div id="'+f+'"></div>\n'),c+="...\n",c+='<script type="text/javascript" src="'+g+'">\x3c/script>\n',c+='<script type="text/javascript">embedPC("'+f+'","'+d+'","'+e+'");\x3c/script>\n\n',c+="The machine should appear where the <div> is located.",p(c)):p("Missing XML/XSL resources")}
window.savePC=function(a,b,c){var d=Va("Computer",a),e=Va("Debugger",a);if(d){var f=xn(d,!0),g=d.L?JSON.stringify(d.L):null;b||(b="/versions/pcjs/1.24.0/pc"+(e?"-dbg":"")+".js");if(c&&c({state:f,gj:g}))return!0;pa(b,null,!0,function(c,d,e){Gn(c,d,e,[a,fa(b,!0),g,f])});return!0}p("Unable to identify machine '"+a+"'");return!1};})();
window.savePC=function(a,b,c){var d=Va("Computer",a),e=Va("Debugger",a);if(d){var f=wn(d,!0),g=d.L?JSON.stringify(d.L):null;b||(b="/versions/pcjs/1.24.0/pc"+(e?"-dbg":"")+".js");if(c&&c({state:f,gj:g}))return!0;pa(b,null,!0,function(c,d,e){Gn(c,d,e,[a,fa(b,!0),g,f])});return!0}p("Unable to identify machine '"+a+"'");return!1};})();

View file

@ -150,6 +150,7 @@ var sTemplateFile = "./modules/shared/templates/common.html";
* HTML template file; sMachineXMLFile is a fallback file to look for when sReadMeFile doesn't exist.
*/
var sReadMeFile = "README.md";
var sMachineMDFile = "machine.md";
var sMachineXMLFile = "machine.xml";
var sManifestXMLFile = "manifest.xml";
@ -1713,12 +1714,20 @@ HTMLOut.prototype.getMarkdownFile = function(sFile, sToken, sIndent, aParms, sPr
{
var obj = this;
sFile = path.join(this.sDir, sFile);
var sFilePath = path.join(this.sDir, sFile);
HTMLOut.logConsole('HTMLOut.getMarkdownFile("' + sFile + '")');
HTMLOut.logConsole('HTMLOut.getMarkdownFile("' + sFilePath + '")');
fs.readFile(sFile, {encoding: "utf8"}, function doneMarkdownFile(err, s) {
fs.readFile(sFilePath, {encoding: "utf8"}, function doneMarkdownFile(err, s) {
if (err) {
/*
* HACK to look for a "machine.md" if our attempt to load a "README.md" failed.
*/
if (sFile.indexOf(sReadMeFile) >= 0) {
sFile = sFile.replace(sReadMeFile, sMachineMDFile);
obj.getMarkdownFile(sFile, sToken, sIndent, aParms, sPrevious, sMachineFile);
return;
}
/*
* Instead of displaying a cryptic error message inside our beautiful HTML template, eg:
*

View file

@ -33,5 +33,4 @@ PC8080 is comprised of the following non-shared components, as listed in [packag
* [video.js](/modules/pc8080/lib/video.js)
* [serialport.js](/modules/pc8080/lib/serialport.js)
* [debugger.js](/modules/pc8080/lib/debugger.js)
* [state.js](/modules/pc8080/lib/state.js)
* [computer.js](/modules/pc8080/lib/computer.js)

View file

@ -35,23 +35,23 @@ if (NODE) {
var str = require("../../shared/lib/strlib");
var usr = require("../../shared/lib/usrlib");
var Component = require("../../shared/lib/component");
var Memory = require("./memory");
var Messages = require("./messages");
var State = require("./state");
var Memory8080 = require("./memory");
var Messages8080= require("./messages");
var State8080 = require("./state");
}
/**
* Bus(cpu, dbg)
* Bus8080(cpu, dbg)
*
* The Bus component manages physical memory and I/O address spaces.
* The Bus8080 component manages physical memory and I/O address spaces.
*
* The Bus component has no UI elements, so it does not require an init() handler,
* The Bus8080 component has no UI elements, so it does not require an init() handler,
* but it still inherits from the Component class and must be allocated like any
* other device component. It's currently allocated by the Computer's init() handler,
* which then calls the initBus() method of all the other components.
*
* For memory beyond the simple needs of the ROM and RAM components (ie, memory-mapped
* devices), the address space must still be allocated through the Bus component via
* devices), the address space must still be allocated through the Bus8080 component via
* addMemory(). If the component needs something more than simple read/write storage,
* it must provide a custom controller.
*
@ -63,12 +63,12 @@ if (NODE) {
* @constructor
* @extends Component
* @param {Object} parmsBus
* @param {CPUState} cpu
* @param {Debugger} dbg
* @param {CPUState8080} cpu
* @param {Debugger8080} dbg
*/
function Bus(parmsBus, cpu, dbg)
function Bus8080(parmsBus, cpu, dbg)
{
Component.call(this, "Bus", parmsBus, Bus);
Component.call(this, "Bus", parmsBus, Bus8080);
this.cpu = cpu;
this.dbg = dbg;
@ -76,7 +76,7 @@ function Bus(parmsBus, cpu, dbg)
this.nBusWidth = parmsBus['busWidth'] || 16;
/*
* Compute all Bus memory block parameters, based on the width of the bus.
* Compute all Bus8080 memory block parameters, based on the width of the bus.
*
* Regarding blockTotal, we want to avoid using block overflow expressions like:
*
@ -121,7 +121,7 @@ function Bus(parmsBus, cpu, dbg)
this.nBlockLimit = this.nBlockSize - 1;
this.nBlockTotal = (this.addrTotal / this.nBlockSize) | 0;
this.nBlockMask = this.nBlockTotal - 1;
this.assert(this.nBlockMask <= Bus.BlockInfo.num.mask);
this.assert(this.nBlockMask <= Bus8080.BlockInfo.num.mask);
/*
* Lists of I/O notification functions: aPortInputNotify and aPortOutputNotify are arrays, indexed by
@ -164,9 +164,9 @@ function Bus(parmsBus, cpu, dbg)
this.setReady();
}
Component.subclass(Bus);
Component.subclass(Bus8080);
Bus.ERROR = {
Bus8080.ERROR = {
ADD_MEM_INUSE: 1,
ADD_MEM_BADRANGE: 2,
SET_MEM_BADRANGE: 4,
@ -188,10 +188,10 @@ var BlockInfo;
* type: BitField
* }}
*/
Bus.BlockInfo = usr.defineBitFields({num:20, count:8, btmod:1, type:3});
Bus8080.BlockInfo = usr.defineBitFields({num:20, count:8, btmod:1, type:3});
/**
* BusInfo object definition (returned by scanMemory())
* Bus8080Info object definition (returned by scanMemory())
*
* cbTotal: total bytes allocated
* cBlocks: total Memory blocks allocated
@ -203,18 +203,18 @@ Bus.BlockInfo = usr.defineBitFields({num:20, count:8, btmod:1, type:3});
* aBlocks: Array.<BlockInfo>
* }}
*/
var BusInfo;
var Bus8080Info;
/**
* initMemory()
*
* Allocate enough (empty) Memory blocks to span the entire physical address space.
*
* @this {Bus}
* @this {Bus8080}
*/
Bus.prototype.initMemory = function()
Bus8080.prototype.initMemory = function()
{
var block = new Memory();
var block = new Memory8080();
block.copyBreakpoints(this.dbg);
this.aMemBlocks = new Array(this.nBlockTotal);
for (var iBlock = 0; iBlock < this.nBlockTotal; iBlock++) {
@ -225,9 +225,9 @@ Bus.prototype.initMemory = function()
/**
* reset()
*
* @this {Bus}
* @this {Bus8080}
*/
Bus.prototype.reset = function()
Bus8080.prototype.reset = function()
{
};
@ -243,12 +243,12 @@ Bus.prototype.reset = function()
* TODO: Perhaps Computer should be smarter: if there's no powerUp() handler, then fallback to the reset() handler.
* In that case, however, we'd either need to remove the powerUp() stub in Component, or detect the existence of the stub.
*
* @this {Bus}
* @this {Bus8080}
* @param {Object|null} data (always null because we supply no powerDown() handler)
* @param {boolean} [fRepower]
* @return {boolean} true if successful, false if failure
*/
Bus.prototype.powerUp = function(data, fRepower)
Bus8080.prototype.powerUp = function(data, fRepower)
{
if (!fRepower) this.reset();
return true;
@ -267,7 +267,7 @@ Bus.prototype.powerUp = function(data, fRepower)
* because machines with large block sizes can make it impossible to load certain ROMs at
* their required addresses. Every allocation still allocates a whole number of blocks.
*
* Even so, Bus memory management does NOT provide a general-purpose heap. Most memory
* Even so, Bus8080 memory management does NOT provide a general-purpose heap. Most memory
* allocations occur during machine initialization and never change. In particular, there
* is NO support for removing partial-block allocations.
*
@ -277,13 +277,13 @@ Bus.prototype.powerUp = function(data, fRepower)
* space. However, any holes that might have existed between the original allocation and an
* extension are subsumed by the extension.
*
* @this {Bus}
* @this {Bus8080}
* @param {number} addr is the starting physical address of the request
* @param {number} size of the request, in bytes
* @param {number} type is one of the Memory.TYPE constants
* @param {number} type is one of the Memory8080.TYPE constants
* @return {boolean} true if successful, false if not
*/
Bus.prototype.addMemory = function(addr, size, type)
Bus8080.prototype.addMemory = function(addr, size, type)
{
var addrNext = addr;
var sizeLeft = size;
@ -319,10 +319,10 @@ Bus.prototype.addMemory = function(addr, size, type)
continue;
}
}
return this.reportError(Bus.ERROR.ADD_MEM_INUSE, addrNext, sizeLeft);
return this.reportError(Bus8080.ERROR.ADD_MEM_INUSE, addrNext, sizeLeft);
}
var blockNew = new Memory(addrNext, sizeBlock, this.nBlockSize, type);
var blockNew = new Memory8080(addrNext, sizeBlock, this.nBlockSize, type);
blockNew.copyBreakpoints(this.dbg, block);
this.aMemBlocks[iBlock++] = blockNew;
@ -331,22 +331,22 @@ Bus.prototype.addMemory = function(addr, size, type)
}
if (sizeLeft <= 0) {
this.status(Math.floor(size / 1024) + "Kb " + Memory.TYPE.NAMES[type] + " at " + str.toHexWord(addr));
this.status(Math.floor(size / 1024) + "Kb " + Memory8080.TYPE.NAMES[type] + " at " + str.toHexWord(addr));
return true;
}
return this.reportError(Bus.ERROR.ADD_MEM_BADRANGE, addr, size);
return this.reportError(Bus8080.ERROR.ADD_MEM_BADRANGE, addr, size);
};
/**
* cleanMemory(addr, size)
*
* @this {Bus}
* @this {Bus8080}
* @param {number} addr
* @param {number} size
* @return {boolean} true if all blocks were clean, false if dirty; all blocks are cleaned in the process
*/
Bus.prototype.cleanMemory = function(addr, size)
Bus8080.prototype.cleanMemory = function(addr, size)
{
var fClean = true;
var iBlock = addr >>> this.nBlockShift;
@ -364,15 +364,15 @@ Bus.prototype.cleanMemory = function(addr, size)
/**
* scanMemory(info, addr, size)
*
* Returns a BusInfo object for the specified address range.
* Returns a Bus8080Info object for the specified address range.
*
* @this {Bus}
* @param {Object} [info] previous BusInfo, if any
* @this {Bus8080}
* @param {Object} [info] previous Bus8080Info, if any
* @param {number} [addr] starting address of range (0 if none provided)
* @param {number} [size] size of range, in bytes (up to end of address space if none provided)
* @return {Object} updated info (or new info if no previous info provided)
*/
Bus.prototype.scanMemory = function(info, addr, size)
Bus8080.prototype.scanMemory = function(info, addr, size)
{
if (addr == null) addr = 0;
if (size == null) size = (this.addrTotal - addr) | 0;
@ -387,7 +387,7 @@ Bus.prototype.scanMemory = function(info, addr, size)
var block = this.aMemBlocks[iBlock];
info.cbTotal += block.size;
if (block.size) {
info.aBlocks.push(usr.initBitFields(Bus.BlockInfo, iBlock, 0, 0, block.type));
info.aBlocks.push(usr.initBitFields(Bus8080.BlockInfo, iBlock, 0, 0, block.type));
info.cBlocks++
}
iBlock++;
@ -398,10 +398,10 @@ Bus.prototype.scanMemory = function(info, addr, size)
/**
* getWidth()
*
* @this {Bus}
* @this {Bus8080}
* @return {number}
*/
Bus.prototype.getWidth = function()
Bus8080.prototype.getWidth = function()
{
return this.nBusWidth;
};
@ -413,18 +413,18 @@ Bus.prototype.getWidth = function()
*
* TODO: Update the removeMemory() interface to reflect the relaxed requirements of the addMemory() interface.
*
* @this {Bus}
* @this {Bus8080}
* @param {number} addr
* @param {number} size
* @return {boolean} true if successful, false if not
*/
Bus.prototype.removeMemory = function(addr, size)
Bus8080.prototype.removeMemory = function(addr, size)
{
if (!(addr & this.nBlockLimit) && size && !(size & this.nBlockLimit)) {
var iBlock = addr >>> this.nBlockShift;
while (size > 0) {
var blockOld = this.aMemBlocks[iBlock];
var blockNew = new Memory(addr);
var blockNew = new Memory8080(addr);
blockNew.copyBreakpoints(this.dbg, blockOld);
this.aMemBlocks[iBlock++] = blockNew;
addr = iBlock * this.nBlockSize;
@ -432,18 +432,18 @@ Bus.prototype.removeMemory = function(addr, size)
}
return true;
}
return this.reportError(Bus.ERROR.REM_MEM_BADRANGE, addr, size);
return this.reportError(Bus8080.ERROR.REM_MEM_BADRANGE, addr, size);
};
/**
* getMemoryBlocks(addr, size)
*
* @this {Bus}
* @this {Bus8080}
* @param {number} addr is the starting physical address
* @param {number} size of the request, in bytes
* @return {Array} of Memory blocks
*/
Bus.prototype.getMemoryBlocks = function(addr, size)
Bus8080.prototype.getMemoryBlocks = function(addr, size)
{
var aBlocks = [];
var iBlock = addr >>> this.nBlockShift;
@ -463,13 +463,13 @@ Bus.prototype.getMemoryBlocks = function(addr, size)
* Otherwise, new blocks are allocated with the specified type; the underlying memory from the
* provided blocks is still used, but the new blocks may have different access to that memory.
*
* @this {Bus}
* @this {Bus8080}
* @param {number} addr is the starting physical address
* @param {number} size of the request, in bytes
* @param {Array} aBlocks as returned by getMemoryBlocks()
* @param {number} [type] is one of the Memory.TYPE constants
* @param {number} [type] is one of the Memory8080.TYPE constants
*/
Bus.prototype.setMemoryBlocks = function(addr, size, aBlocks, type)
Bus8080.prototype.setMemoryBlocks = function(addr, size, aBlocks, type)
{
var i = 0;
var iBlock = addr >>> this.nBlockShift;
@ -478,7 +478,7 @@ Bus.prototype.setMemoryBlocks = function(addr, size, aBlocks, type)
this.assert(block);
if (!block) break;
if (type !== undefined) {
var blockNew = new Memory(addr);
var blockNew = new Memory8080(addr);
blockNew.clone(block, type, this.dbg);
block = blockNew;
}
@ -490,11 +490,11 @@ Bus.prototype.setMemoryBlocks = function(addr, size, aBlocks, type)
/**
* getByte(addr)
*
* @this {Bus}
* @this {Bus8080}
* @param {number} addr is a physical address
* @return {number} byte (8-bit) value at that address
*/
Bus.prototype.getByte = function(addr)
Bus8080.prototype.getByte = function(addr)
{
return this.aMemBlocks[(addr & this.nBusMask) >>> this.nBlockShift].readByte(addr & this.nBlockLimit, addr);
};
@ -504,11 +504,11 @@ Bus.prototype.getByte = function(addr)
*
* This is useful for the Debugger and other components that want to bypass getByte() breakpoint detection.
*
* @this {Bus}
* @this {Bus8080}
* @param {number} addr is a physical address
* @return {number} byte (8-bit) value at that address
*/
Bus.prototype.getByteDirect = function(addr)
Bus8080.prototype.getByteDirect = function(addr)
{
return this.aMemBlocks[(addr & this.nBusMask) >>> this.nBlockShift].readByteDirect(addr & this.nBlockLimit, addr);
};
@ -516,11 +516,11 @@ Bus.prototype.getByteDirect = function(addr)
/**
* getShort(addr)
*
* @this {Bus}
* @this {Bus8080}
* @param {number} addr is a physical address
* @return {number} word (16-bit) value at that address
*/
Bus.prototype.getShort = function(addr)
Bus8080.prototype.getShort = function(addr)
{
var off = addr & this.nBlockLimit;
var iBlock = (addr & this.nBusMask) >>> this.nBlockShift;
@ -535,11 +535,11 @@ Bus.prototype.getShort = function(addr)
*
* This is useful for the Debugger and other components that want to bypass getShort() breakpoint detection.
*
* @this {Bus}
* @this {Bus8080}
* @param {number} addr is a physical address
* @return {number} word (16-bit) value at that address
*/
Bus.prototype.getShortDirect = function(addr)
Bus8080.prototype.getShortDirect = function(addr)
{
var off = addr & this.nBlockLimit;
var iBlock = (addr & this.nBusMask) >>> this.nBlockShift;
@ -552,11 +552,11 @@ Bus.prototype.getShortDirect = function(addr)
/**
* setByte(addr, b)
*
* @this {Bus}
* @this {Bus8080}
* @param {number} addr is a physical address
* @param {number} b is the byte (8-bit) value to write (we truncate it to 8 bits to be safe)
*/
Bus.prototype.setByte = function(addr, b)
Bus8080.prototype.setByte = function(addr, b)
{
this.aMemBlocks[(addr & this.nBusMask) >>> this.nBlockShift].writeByte(addr & this.nBlockLimit, b & 0xff, addr);
};
@ -567,11 +567,11 @@ Bus.prototype.setByte = function(addr, b)
* This is useful for the Debugger and other components that want to bypass breakpoint detection AND read-only
* memory protection (for example, this is an interface the ROM component could use to initialize ROM contents).
*
* @this {Bus}
* @this {Bus8080}
* @param {number} addr is a physical address
* @param {number} b is the byte (8-bit) value to write (we truncate it to 8 bits to be safe)
*/
Bus.prototype.setByteDirect = function(addr, b)
Bus8080.prototype.setByteDirect = function(addr, b)
{
this.aMemBlocks[(addr & this.nBusMask) >>> this.nBlockShift].writeByteDirect(addr & this.nBlockLimit, b & 0xff, addr);
};
@ -579,11 +579,11 @@ Bus.prototype.setByteDirect = function(addr, b)
/**
* setShort(addr, w)
*
* @this {Bus}
* @this {Bus8080}
* @param {number} addr is a physical address
* @param {number} w is the word (16-bit) value to write (we truncate it to 16 bits to be safe)
*/
Bus.prototype.setShort = function(addr, w)
Bus8080.prototype.setShort = function(addr, w)
{
var off = addr & this.nBlockLimit;
var iBlock = (addr & this.nBusMask) >>> this.nBlockShift;
@ -601,11 +601,11 @@ Bus.prototype.setShort = function(addr, w)
* This is useful for the Debugger and other components that want to bypass breakpoint detection AND read-only
* memory protection (for example, this is an interface the ROM component could use to initialize ROM contents).
*
* @this {Bus}
* @this {Bus8080}
* @param {number} addr is a physical address
* @param {number} w is the word (16-bit) value to write (we truncate it to 16 bits to be safe)
*/
Bus.prototype.setShortDirect = function(addr, w)
Bus8080.prototype.setShortDirect = function(addr, w)
{
var off = addr & this.nBlockLimit;
var iBlock = (addr & this.nBusMask) >>> this.nBlockShift;
@ -620,11 +620,11 @@ Bus.prototype.setShortDirect = function(addr, w)
/**
* addMemBreak(addr, fWrite)
*
* @this {Bus}
* @this {Bus8080}
* @param {number} addr
* @param {boolean} fWrite is true for a memory write breakpoint, false for a memory read breakpoint
*/
Bus.prototype.addMemBreak = function(addr, fWrite)
Bus8080.prototype.addMemBreak = function(addr, fWrite)
{
if (DEBUGGER) {
var iBlock = addr >>> this.nBlockShift;
@ -635,11 +635,11 @@ Bus.prototype.addMemBreak = function(addr, fWrite)
/**
* removeMemBreak(addr, fWrite)
*
* @this {Bus}
* @this {Bus8080}
* @param {number} addr
* @param {boolean} fWrite is true for a memory write breakpoint, false for a memory read breakpoint
*/
Bus.prototype.removeMemBreak = function(addr, fWrite)
Bus8080.prototype.removeMemBreak = function(addr, fWrite)
{
if (DEBUGGER) {
var iBlock = addr >>> this.nBlockShift;
@ -672,11 +672,11 @@ Bus.prototype.removeMemBreak = function(addr, fWrite)
* that it's compressed, since we'll only store them in compressed form if they actually shrank, and we'll use State
* helper methods compress() and decompress() to create and expand the compressed data arrays.
*
* @this {Bus}
* @this {Bus8080}
* @param {boolean} [fAll] (true to save all non-ROM memory blocks, regardless of their dirty flags)
* @return {Array} a
*/
Bus.prototype.saveMemory = function(fAll)
Bus8080.prototype.saveMemory = function(fAll)
{
var i = 0;
var a = [];
@ -688,7 +688,7 @@ Bus.prototype.saveMemory = function(fAll)
* the memory blocks (eg, video memory), and while cleanMemory() will clear a dirty block's fDirty flag,
* it also sets the dirty block's fDirtyEver flag, which is left set for the lifetime of the machine.
*/
if (fAll && block.type != Memory.TYPE.ROM || block.fDirty || block.fDirtyEver) {
if (fAll && block.type != Memory8080.TYPE.ROM || block.fDirty || block.fDirtyEver) {
a[i++] = iBlock;
a[i++] = State.compress(block.save());
}
@ -710,11 +710,11 @@ Bus.prototype.saveMemory = function(fAll)
*
* See saveMemory() for more information on how the memory block contents are saved.
*
* @this {Bus}
* @this {Bus8080}
* @param {Array} a
* @return {boolean} true if successful, false if not
*/
Bus.prototype.restoreMemory = function(a)
Bus8080.prototype.restoreMemory = function(a)
{
var i;
for (i = 0; i < a.length - 1; i += 2) {
@ -740,11 +740,11 @@ Bus.prototype.restoreMemory = function(a)
/**
* addPortInputBreak(port)
*
* @this {Bus}
* @this {Bus8080}
* @param {number} [port]
* @return {boolean} true if break on port input enabled, false if disabled
*/
Bus.prototype.addPortInputBreak = function(port)
Bus8080.prototype.addPortInputBreak = function(port)
{
if (port === undefined) {
this.fPortInputBreakAll = !this.fPortInputBreakAll;
@ -762,12 +762,12 @@ Bus.prototype.addPortInputBreak = function(port)
*
* Add a port input-notification handler to the list of such handlers.
*
* @this {Bus}
* @this {Bus8080}
* @param {number} start port address
* @param {number} end port address
* @param {function(number,number)} fn is called with the port and IP values at the time of the input
*/
Bus.prototype.addPortInputNotify = function(start, end, fn)
Bus8080.prototype.addPortInputNotify = function(start, end, fn)
{
if (fn !== undefined) {
for (var port = start; port <= end; port++) {
@ -786,12 +786,12 @@ Bus.prototype.addPortInputNotify = function(start, end, fn)
*
* Add port input-notification handlers from the specified table (a batch version of addPortInputNotify)
*
* @this {Bus}
* @this {Bus8080}
* @param {Component} component
* @param {Object} table
* @param {number} [offset] is an optional port offset
*/
Bus.prototype.addPortInputTable = function(component, table, offset)
Bus8080.prototype.addPortInputTable = function(component, table, offset)
{
if (offset === undefined) offset = 0;
if (table) {
@ -806,11 +806,11 @@ Bus.prototype.addPortInputTable = function(component, table, offset)
*
* By default, all input ports are 1 byte wide; ports that are wider must call this function.
*
* @this {Bus}
* @this {Bus8080}
* @param {number} port
* @param {number} size (1, 2 or 4)
*/
Bus.prototype.addPortInputWidth = function(port, size)
Bus8080.prototype.addPortInputWidth = function(port, size)
{
this.aPortInputWidth[port] = size;
};
@ -818,7 +818,7 @@ Bus.prototype.addPortInputWidth = function(port, size)
/**
* checkPortInputNotify(port, size, addrIP)
*
* @this {Bus}
* @this {Bus8080}
* @param {number} port
* @param {number} size (1, 2 or 4)
* @param {number} [addrIP] is the IP value at the time of the input
@ -827,7 +827,7 @@ Bus.prototype.addPortInputWidth = function(port, size)
* NOTE: It seems that parts of the ROM BIOS (like the RS-232 probes around F000:E5D7 in the 5150 BIOS)
* assume that ports for non-existent hardware return 0xff rather than 0x00, hence my new default (0xff) below.
*/
Bus.prototype.checkPortInputNotify = function(port, size, addrIP)
Bus8080.prototype.checkPortInputNotify = function(port, size, addrIP)
{
var data = 0, shift = 0;
@ -882,11 +882,11 @@ Bus.prototype.checkPortInputNotify = function(port, size, addrIP)
*
* Remove port input-notification handler(s) (to be ENABLED later if needed)
*
* @this {Bus}
* @this {Bus8080}
* @param {number} start address
* @param {number} end address
*
Bus.prototype.removePortInputNotify = function(start, end)
Bus8080.prototype.removePortInputNotify = function(start, end)
{
for (var port = start; port < end; port++) {
if (this.aPortInputNotify[port]) {
@ -899,11 +899,11 @@ Bus.prototype.removePortInputNotify = function(start, end)
/**
* addPortOutputBreak(port)
*
* @this {Bus}
* @this {Bus8080}
* @param {number} [port]
* @return {boolean} true if break on port output enabled, false if disabled
*/
Bus.prototype.addPortOutputBreak = function(port)
Bus8080.prototype.addPortOutputBreak = function(port)
{
if (port === undefined) {
this.fPortOutputBreakAll = !this.fPortOutputBreakAll;
@ -921,12 +921,12 @@ Bus.prototype.addPortOutputBreak = function(port)
*
* Add a port output-notification handler to the list of such handlers.
*
* @this {Bus}
* @this {Bus8080}
* @param {number} start port address
* @param {number} end port address
* @param {function(number,number)} fn is called with the port and IP values at the time of the output
*/
Bus.prototype.addPortOutputNotify = function(start, end, fn)
Bus8080.prototype.addPortOutputNotify = function(start, end, fn)
{
if (fn !== undefined) {
for (var port = start; port <= end; port++) {
@ -945,12 +945,12 @@ Bus.prototype.addPortOutputNotify = function(start, end, fn)
*
* Add port output-notification handlers from the specified table (a batch version of addPortOutputNotify)
*
* @this {Bus}
* @this {Bus8080}
* @param {Component} component
* @param {Object} table
* @param {number} [offset] is an optional port offset
*/
Bus.prototype.addPortOutputTable = function(component, table, offset)
Bus8080.prototype.addPortOutputTable = function(component, table, offset)
{
if (offset === undefined) offset = 0;
if (table) {
@ -965,11 +965,11 @@ Bus.prototype.addPortOutputTable = function(component, table, offset)
*
* By default, all output ports are 1 byte wide; ports that are wider must call this function.
*
* @this {Bus}
* @this {Bus8080}
* @param {number} port
* @param {number} size (1, 2 or 4)
*/
Bus.prototype.addPortOutputWidth = function(port, size)
Bus8080.prototype.addPortOutputWidth = function(port, size)
{
this.aPortOutputWidth[port] = size;
};
@ -977,13 +977,13 @@ Bus.prototype.addPortOutputWidth = function(port, size)
/**
* checkPortOutputNotify(port, size, data, addrIP)
*
* @this {Bus}
* @this {Bus8080}
* @param {number} port
* @param {number} size
* @param {number} data
* @param {number} [addrIP] is the IP value at the time of the output
*/
Bus.prototype.checkPortOutputNotify = function(port, size, data, addrIP)
Bus8080.prototype.checkPortOutputNotify = function(port, size, data, addrIP)
{
var shift = 0;
@ -1030,11 +1030,11 @@ Bus.prototype.checkPortOutputNotify = function(port, size, data, addrIP)
*
* Remove port output-notification handler(s) (to be ENABLED later if needed)
*
* @this {Bus}
* @this {Bus8080}
* @param {number} start address
* @param {number} end address
*
Bus.prototype.removePortOutputNotify = function(start, end)
Bus8080.prototype.removePortOutputNotify = function(start, end)
{
for (var port = start; port < end; port++) {
if (this.aPortOutputNotify[port]) {
@ -1047,14 +1047,14 @@ Bus.prototype.removePortOutputNotify = function(start, end)
/**
* reportError(op, addr, size, fQuiet)
*
* @this {Bus}
* @this {Bus8080}
* @param {number} op
* @param {number} addr
* @param {number} size
* @param {boolean} [fQuiet] (true if any error should be quietly logged)
* @return {boolean} false
*/
Bus.prototype.reportError = function(op, addr, size, fQuiet)
Bus8080.prototype.reportError = function(op, addr, size, fQuiet)
{
var sError = "Memory block error (" + op + ": " + str.toHex(addr) + "," + str.toHex(size) + ")";
if (fQuiet) {
@ -1069,4 +1069,4 @@ Bus.prototype.reportError = function(op, addr, size, fQuiet)
return false;
};
if (NODE) module.exports = Bus;
if (NODE) module.exports = Bus8080;

View file

@ -36,34 +36,34 @@ if (NODE) {
var usr = require("../../shared/lib/usrlib");
var web = require("../../shared/lib/weblib");
var Component = require("../../shared/lib/component");
var Messages = require("./messages");
var State = require("./state");
var CPUDef = require("./cpudef");
var CPUDef8080 = require("./cpudef");
var Messages8080= require("./messages");
var State8080 = require("./state");
}
/**
* ChipSet(parmsChipSet)
* ChipSet8080(parmsChipSet)
*
* The ChipSet component has the following component-specific (parmsChipSet) properties:
* The ChipSet8080 component has the following component-specific (parmsChipSet) properties:
*
* model: eg, "SI1978" (should be a member of ChipSet.MODELS)
* model: eg, "SI1978" (should be a member of ChipSet8080.MODELS)
* swDIP: eg, "00000000", where swDIP[0] is DIP0, swDIP[1] is DIP1, etc.
*
* @constructor
* @extends Component
* @param {Object} parmsChipSet
*/
function ChipSet(parmsChipSet)
function ChipSet8080(parmsChipSet)
{
Component.call(this, "ChipSet", parmsChipSet, ChipSet, Messages.CHIPSET);
Component.call(this, "ChipSet", parmsChipSet, ChipSet8080, Messages8080.CHIPSET);
var model = parmsChipSet['model'];
if (model && !ChipSet.MODELS[model]) {
if (model && !ChipSet8080.MODELS[model]) {
Component.notice("Unrecognized ChipSet model: " + model);
}
this.config = ChipSet.MODELS[model] || {};
this.config = ChipSet8080.MODELS[model] || {};
this.bSwitches = this.parseDIPSwitches(parmsChipSet['swDIP']);
@ -98,7 +98,7 @@ function ChipSet(parmsChipSet)
this.setReady();
}
Component.subclass(ChipSet);
Component.subclass(ChipSet8080);
/*
* NOTE: The STATUS1 port could have been handled entirely by the Keyboard component, but it was just as easy
@ -106,7 +106,7 @@ Component.subclass(ChipSet);
* button press or release. It's a six-of-one, half-a-dozen-of-another choice, since technically, Space Invaders
* doesn't have a keyboard.
*/
ChipSet.SI1978 = {
ChipSet8080.SI1978 = {
MODEL: 1978.1,
STATUS0: { // NOTE: STATUS0 not used by the SI1978 ROMs; refer to STATUS1 instead
PORT: 0,
@ -218,7 +218,7 @@ ChipSet.SI1978 = {
* but some are more appropriately handled by other components; eg, port 0x82 is handled by the Keyboard component,
* so it's defined there instead of here.
*/
ChipSet.VT100 = {
ChipSet8080.VT100 = {
MODEL: 100.0,
FLAGS: {
PORT: 0x42, // read-only
@ -363,20 +363,20 @@ ChipSet.VT100 = {
/*
* Supported models and their configurations
*/
ChipSet.MODELS = {
"SI1978": ChipSet.SI1978,
"VT100": ChipSet.VT100
ChipSet8080.MODELS = {
"SI1978": ChipSet8080.SI1978,
"VT100": ChipSet8080.VT100
};
/**
* parseDIPSwitches(sBits, bDefault)
*
* @this {ChipSet}
* @this {ChipSet8080}
* @param {string} sBits describing switch settings
* @param {number} [bDefault]
* @return {number|undefined}
*/
ChipSet.prototype.parseDIPSwitches = function(sBits, bDefault)
ChipSet8080.prototype.parseDIPSwitches = function(sBits, bDefault)
{
var b = bDefault;
if (sBits) {
@ -396,14 +396,14 @@ ChipSet.prototype.parseDIPSwitches = function(sBits, bDefault)
/**
* setBinding(sHTMLType, sBinding, control, sValue)
*
* @this {ChipSet}
* @this {ChipSet8080}
* @param {string|null} sHTMLType is the type of the HTML control (eg, "button", "list", "text", "submit", "textarea", "canvas")
* @param {string} sBinding is the value of the 'binding' parameter stored in the HTML control's "data-value" attribute (eg, "sw1")
* @param {Object} control is the HTML control DOM object (eg, HTMLButtonElement)
* @param {string} [sValue] optional data value
* @return {boolean} true if binding was successful, false if unrecognized binding request
*/
ChipSet.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
ChipSet8080.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
{
return false;
};
@ -411,21 +411,21 @@ ChipSet.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
/**
* initBus(cmp, bus, cpu, dbg)
*
* @this {ChipSet}
* @param {Computer} cmp
* @param {Bus} bus
* @param {CPUState} cpu
* @param {Debugger} dbg
* @this {ChipSet8080}
* @param {Computer8080} cmp
* @param {Bus8080} bus
* @param {CPUState8080} cpu
* @param {Debugger8080} dbg
*/
ChipSet.prototype.initBus = function(cmp, bus, cpu, dbg)
ChipSet8080.prototype.initBus = function(cmp, bus, cpu, dbg)
{
this.bus = bus;
this.cpu = cpu;
this.dbg = dbg;
this.cmp = cmp;
this.kbd = /** @type {Keyboard} */ (cmp.getMachineComponent("Keyboard"));
this.serial = /** @type {SerialPort} */ (cmp.getMachineComponent("SerialPort"));
this.video = /** @type {Video} */ (cmp.getMachineComponent("Video"));
this.kbd = /** @type {Keyboard8080} */ (cmp.getMachineComponent("Keyboard"));
this.serial = /** @type {SerialPort8080} */ (cmp.getMachineComponent("SerialPort"));
this.video = /** @type {Video8080} */ (cmp.getMachineComponent("Video"));
bus.addPortInputTable(this, this.config.portsInput);
bus.addPortOutputTable(this, this.config.portsOutput);
};
@ -433,12 +433,12 @@ ChipSet.prototype.initBus = function(cmp, bus, cpu, dbg)
/**
* powerUp(data, fRepower)
*
* @this {ChipSet}
* @this {ChipSet8080}
* @param {Object|null} data
* @param {boolean} [fRepower]
* @return {boolean} true if successful, false if failure
*/
ChipSet.prototype.powerUp = function(data, fRepower)
ChipSet8080.prototype.powerUp = function(data, fRepower)
{
if (!fRepower) {
if (!data) {
@ -453,39 +453,39 @@ ChipSet.prototype.powerUp = function(data, fRepower)
/**
* powerDown(fSave, fShutdown)
*
* @this {ChipSet}
* @this {ChipSet8080}
* @param {boolean} [fSave]
* @param {boolean} [fShutdown]
* @return {Object|boolean} component state if fSave; otherwise, true if successful, false if failure
*/
ChipSet.prototype.powerDown = function(fSave, fShutdown)
ChipSet8080.prototype.powerDown = function(fSave, fShutdown)
{
return fSave? this.save() : true;
};
ChipSet.SI1978.INIT = [
ChipSet8080.SI1978.INIT = [
[
ChipSet.SI1978.STATUS0.ALWAYS_SET,
ChipSet.SI1978.STATUS1.ALWAYS_SET,
ChipSet.SI1978.STATUS2.ALWAYS_SET,
ChipSet8080.SI1978.STATUS0.ALWAYS_SET,
ChipSet8080.SI1978.STATUS1.ALWAYS_SET,
ChipSet8080.SI1978.STATUS2.ALWAYS_SET,
0, 0, 0, 0
]
];
ChipSet.VT100.INIT = [
ChipSet8080.VT100.INIT = [
[
ChipSet.VT100.BRIGHTNESS.INIT,
ChipSet.VT100.FLAGS.NO_AVO | ChipSet.VT100.FLAGS.NO_GFX
ChipSet8080.VT100.BRIGHTNESS.INIT,
ChipSet8080.VT100.FLAGS.NO_AVO | ChipSet8080.VT100.FLAGS.NO_GFX
],
[
ChipSet.VT100.DC011.INITCOLS,
ChipSet.VT100.DC011.INITRATE
ChipSet8080.VT100.DC011.INITCOLS,
ChipSet8080.VT100.DC011.INITRATE
],
[
ChipSet.VT100.DC012.INITSCROLL,
ChipSet.VT100.DC012.INITBLINK,
ChipSet.VT100.DC012.INITREVERSE,
ChipSet.VT100.DC012.INITATTR
ChipSet8080.VT100.DC012.INITSCROLL,
ChipSet8080.VT100.DC012.INITBLINK,
ChipSet8080.VT100.DC012.INITREVERSE,
ChipSet8080.VT100.DC012.INITATTR
],
[
0, 0, 0, 0,
@ -507,9 +507,9 @@ ChipSet.VT100.INIT = [
/**
* reset()
*
* @this {ChipSet}
* @this {ChipSet8080}
*/
ChipSet.prototype.reset = function()
ChipSet8080.prototype.reset = function()
{
if (this.config.INIT && !this.restore(this.config.INIT)) {
this.notice("reset error");
@ -521,17 +521,17 @@ ChipSet.prototype.reset = function()
*
* This implements save support for the ChipSet component.
*
* @this {ChipSet}
* @this {ChipSet8080}
* @return {Object}
*/
ChipSet.prototype.save = function()
ChipSet8080.prototype.save = function()
{
var state = new State(this);
switch(this.config.MODEL) {
case ChipSet.SI1978.MODEL:
case ChipSet8080.SI1978.MODEL:
state.set(0, [this.bStatus0, this.bStatus1, this.bStatus2, this.wShiftData, this.bShiftCount, this.bSound1, this.bSound2]);
break;
case ChipSet.VT100.MODEL:
case ChipSet8080.VT100.MODEL:
state.set(0, [this.bBrightness, this.bFlags]);
state.set(1, [this.bDC011Cols, this.bDC011Rate]);
state.set(2, [this.bDC012Scroll, this.bDC012Blink, this.bDC012Reverse, this.bDC012Attr]);
@ -546,16 +546,16 @@ ChipSet.prototype.save = function()
*
* This implements restore support for the ChipSet component.
*
* @this {ChipSet}
* @this {ChipSet8080}
* @param {Object} data
* @return {boolean} true if successful, false if failure
*/
ChipSet.prototype.restore = function(data)
ChipSet8080.prototype.restore = function(data)
{
var a;
if (data && (a = data[0]) && a.length) {
switch(this.config.MODEL) {
case ChipSet.SI1978.MODEL:
case ChipSet8080.SI1978.MODEL:
this.bStatus0 = a[0];
this.bStatus1 = a[1];
this.bStatus2 = a[2];
@ -564,7 +564,7 @@ ChipSet.prototype.restore = function(data)
this.bSound1 = a[5];
this.bSound2 = a[6];
return true;
case ChipSet.VT100.MODEL:
case ChipSet8080.VT100.MODEL:
this.bBrightness = a[0];
this.bFlags = a[1];
a = data[1];
@ -592,9 +592,9 @@ ChipSet.prototype.restore = function(data)
*
* Notification from the CPU that it's starting.
*
* @this {ChipSet}
* @this {ChipSet8080}
*/
ChipSet.prototype.start = function()
ChipSet8080.prototype.start = function()
{
/*
* Currently, all we (may) do with this notification is allow the speaker to make noise.
@ -606,9 +606,9 @@ ChipSet.prototype.start = function()
*
* Notification from the CPU that it's stopping.
*
* @this {ChipSet}
* @this {ChipSet8080}
*/
ChipSet.prototype.stop = function()
ChipSet8080.prototype.stop = function()
{
/*
* Currently, all we (may) do with this notification is prevent the speaker from making noise.
@ -618,11 +618,11 @@ ChipSet.prototype.stop = function()
/**
* updateStatus0(bit, fSet)
*
* @this {ChipSet}
* @this {ChipSet8080}
* @param {number} bit
* @param {boolean} fSet
*/
ChipSet.prototype.updateStatus0 = function(bit, fSet)
ChipSet8080.prototype.updateStatus0 = function(bit, fSet)
{
this.bStatus0 &= ~bit;
if (fSet) this.bStatus0 |= bit;
@ -631,11 +631,11 @@ ChipSet.prototype.updateStatus0 = function(bit, fSet)
/**
* updateStatus1(bit, fSet)
*
* @this {ChipSet}
* @this {ChipSet8080}
* @param {number} bit
* @param {boolean} fSet
*/
ChipSet.prototype.updateStatus1 = function(bit, fSet)
ChipSet8080.prototype.updateStatus1 = function(bit, fSet)
{
this.bStatus1 &= ~bit;
if (fSet) this.bStatus1 |= bit;
@ -644,11 +644,11 @@ ChipSet.prototype.updateStatus1 = function(bit, fSet)
/**
* updateStatus2(bit, fSet)
*
* @this {ChipSet}
* @this {ChipSet8080}
* @param {number} bit
* @param {boolean} fSet
*/
ChipSet.prototype.updateStatus2 = function(bit, fSet)
ChipSet8080.prototype.updateStatus2 = function(bit, fSet)
{
this.bStatus2 &= ~bit;
if (fSet) this.bStatus2 |= bit;
@ -657,12 +657,12 @@ ChipSet.prototype.updateStatus2 = function(bit, fSet)
/**
* inSIStatus0(port, addrFrom)
*
* @this {ChipSet}
* @this {ChipSet8080}
* @param {number} port (0x00)
* @param {number} [addrFrom] (not defined if the Debugger is trying to read the specified port)
* @return {number} simulated port value
*/
ChipSet.prototype.inSIStatus0 = function(port, addrFrom)
ChipSet8080.prototype.inSIStatus0 = function(port, addrFrom)
{
var b = this.bStatus0;
this.printMessageIO(port, null, addrFrom, "STATUS0", b, true);
@ -672,12 +672,12 @@ ChipSet.prototype.inSIStatus0 = function(port, addrFrom)
/**
* inSIStatus1(port, addrFrom)
*
* @this {ChipSet}
* @this {ChipSet8080}
* @param {number} port (0x01)
* @param {number} [addrFrom] (not defined if the Debugger is trying to read the specified port)
* @return {number} simulated port value
*/
ChipSet.prototype.inSIStatus1 = function(port, addrFrom)
ChipSet8080.prototype.inSIStatus1 = function(port, addrFrom)
{
var b = this.bStatus1;
this.printMessageIO(port, null, addrFrom, "STATUS1", b, true);
@ -687,12 +687,12 @@ ChipSet.prototype.inSIStatus1 = function(port, addrFrom)
/**
* inSIStatus2(port, addrFrom)
*
* @this {ChipSet}
* @this {ChipSet8080}
* @param {number} port (0x02)
* @param {number} [addrFrom] (not defined if the Debugger is trying to read the specified port)
* @return {number} simulated port value
*/
ChipSet.prototype.inSIStatus2 = function(port, addrFrom)
ChipSet8080.prototype.inSIStatus2 = function(port, addrFrom)
{
var b = this.bStatus2;
this.printMessageIO(port, null, addrFrom, "STATUS2", b, true);
@ -702,12 +702,12 @@ ChipSet.prototype.inSIStatus2 = function(port, addrFrom)
/**
* inSIShiftResult(port, addrFrom)
*
* @this {ChipSet}
* @this {ChipSet8080}
* @param {number} port (0x03)
* @param {number} [addrFrom] (not defined if the Debugger is trying to read the specified port)
* @return {number} simulated port value
*/
ChipSet.prototype.inSIShiftResult = function(port, addrFrom)
ChipSet8080.prototype.inSIShiftResult = function(port, addrFrom)
{
var b = (this.wShiftData >> (8 - this.bShiftCount)) & 0xff;
this.printMessageIO(port, null, addrFrom, "SHIFT.RESULT", b, true);
@ -717,12 +717,12 @@ ChipSet.prototype.inSIShiftResult = function(port, addrFrom)
/**
* outSIShiftCount(port, b, addrFrom)
*
* @this {ChipSet}
* @this {ChipSet8080}
* @param {number} port (0x02)
* @param {number} b
* @param {number} [addrFrom] (not defined if the Debugger is trying to write the specified port)
*/
ChipSet.prototype.outSIShiftCount = function(port, b, addrFrom)
ChipSet8080.prototype.outSIShiftCount = function(port, b, addrFrom)
{
this.printMessageIO(port, b, addrFrom, "SHIFT.COUNT", null, true);
this.bShiftCount = b;
@ -731,12 +731,12 @@ ChipSet.prototype.outSIShiftCount = function(port, b, addrFrom)
/**
* outSISound1(port, b, addrFrom)
*
* @this {ChipSet}
* @this {ChipSet8080}
* @param {number} port (0x03)
* @param {number} b
* @param {number} [addrFrom] (not defined if the Debugger is trying to write the specified port)
*/
ChipSet.prototype.outSISound1 = function(port, b, addrFrom)
ChipSet8080.prototype.outSISound1 = function(port, b, addrFrom)
{
this.printMessageIO(port, b, addrFrom, "SOUND1", null, true);
this.bSound1 = b;
@ -745,12 +745,12 @@ ChipSet.prototype.outSISound1 = function(port, b, addrFrom)
/**
* outSIShiftData(port, b, addrFrom)
*
* @this {ChipSet}
* @this {ChipSet8080}
* @param {number} port (0x04)
* @param {number} b
* @param {number} [addrFrom] (not defined if the Debugger is trying to write the specified port)
*/
ChipSet.prototype.outSIShiftData = function(port, b, addrFrom)
ChipSet8080.prototype.outSIShiftData = function(port, b, addrFrom)
{
this.printMessageIO(port, b, addrFrom, "SHIFT.DATA", null, true);
this.wShiftData = (b << 8) | (this.wShiftData >> 8);
@ -759,12 +759,12 @@ ChipSet.prototype.outSIShiftData = function(port, b, addrFrom)
/**
* outSISound2(port, b, addrFrom)
*
* @this {ChipSet}
* @this {ChipSet8080}
* @param {number} port (0x05)
* @param {number} b
* @param {number} [addrFrom] (not defined if the Debugger is trying to write the specified port)
*/
ChipSet.prototype.outSISound2 = function(port, b, addrFrom)
ChipSet8080.prototype.outSISound2 = function(port, b, addrFrom)
{
this.printMessageIO(port, b, addrFrom, "SOUND2", null, true);
this.bSound2 = b;
@ -773,12 +773,12 @@ ChipSet.prototype.outSISound2 = function(port, b, addrFrom)
/**
* outSIWatchdog(port, b, addrFrom)
*
* @this {ChipSet}
* @this {ChipSet8080}
* @param {number} port (0x06)
* @param {number} b
* @param {number} [addrFrom] (not defined if the Debugger is trying to write the specified port)
*/
ChipSet.prototype.outSIWatchdog = function(port, b, addrFrom)
ChipSet8080.prototype.outSIWatchdog = function(port, b, addrFrom)
{
this.printMessageIO(port, b, addrFrom, "WATCHDOG", null, true);
};
@ -796,7 +796,7 @@ ChipSet.prototype.outSIWatchdog = function(port, b, addrFrom)
* @param {number} iBit
* @return {number}
*/
ChipSet.prototype.getVT100LBA = function(iBit)
ChipSet8080.prototype.getVT100LBA = function(iBit)
{
return (this.cpu.getCycles() & (1 << (iBit - 1))) << 1;
};
@ -806,7 +806,7 @@ ChipSet.prototype.getVT100LBA = function(iBit)
*
* @return {number}
*/
ChipSet.prototype.getNVRAddr = function()
ChipSet8080.prototype.getNVRAddr = function()
{
var i;
var tens = 0, ones = 0;
@ -827,54 +827,54 @@ ChipSet.prototype.getNVRAddr = function()
/**
* doNVRCommand()
*/
ChipSet.prototype.doNVRCommand = function()
ChipSet8080.prototype.doNVRCommand = function()
{
var addr, data;
var bit = this.bNVRLatch & 0x1;
var bCmd = (this.bNVRLatch >> 1) & 0x7;
switch(bCmd) {
case ChipSet.VT100.NVR.CMD.STANDBY:
case ChipSet8080.VT100.NVR.CMD.STANDBY:
break;
case ChipSet.VT100.NVR.CMD.ACCEPT_ADDR:
case ChipSet8080.VT100.NVR.CMD.ACCEPT_ADDR:
this.dNVRAddr = (this.dNVRAddr << 1) | bit;
break;
case ChipSet.VT100.NVR.CMD.ERASE:
case ChipSet8080.VT100.NVR.CMD.ERASE:
addr = this.getNVRAddr();
this.aNVRWords[addr] = ChipSet.VT100.NVR.WORDMASK;
this.aNVRWords[addr] = ChipSet8080.VT100.NVR.WORDMASK;
this.printMessage("doNVRCommand(): erase data at addr " + str.toHexWord(addr));
break;
case ChipSet.VT100.NVR.CMD.ACCEPT_DATA:
case ChipSet8080.VT100.NVR.CMD.ACCEPT_DATA:
this.wNVRData = (this.wNVRData << 1) | bit;
break;
case ChipSet.VT100.NVR.CMD.WRITE:
case ChipSet8080.VT100.NVR.CMD.WRITE:
addr = this.getNVRAddr();
data = this.wNVRData & ChipSet.VT100.NVR.WORDMASK;
data = this.wNVRData & ChipSet8080.VT100.NVR.WORDMASK;
this.aNVRWords[addr] = data;
this.printMessage("doNVRCommand(): write data " + str.toHexWord(data) + " to addr " + str.toHexWord(addr));
break;
case ChipSet.VT100.NVR.CMD.READ:
case ChipSet8080.VT100.NVR.CMD.READ:
addr = this.getNVRAddr();
data = this.aNVRWords[addr];
/*
* If we don't explicitly initialize aNVRWords[], pretend any uninitialized words contains WORDMASK.
*/
if (data == null) data = ChipSet.VT100.NVR.WORDMASK;
if (data == null) data = ChipSet8080.VT100.NVR.WORDMASK;
this.wNVRData = data;
this.printMessage("doNVRCommand(): read data " + str.toHexWord(data) + " from addr " + str.toHexWord(addr));
break;
case ChipSet.VT100.NVR.CMD.SHIFT_OUT:
case ChipSet8080.VT100.NVR.CMD.SHIFT_OUT:
this.wNVRData <<= 1;
/*
* Since WORDMASK is 0x3fff, this will mask the shifted data with 0x4000, which is the bit we want to isolate.
*/
this.bNVROut = this.wNVRData & (ChipSet.VT100.NVR.WORDMASK + 1);
this.bNVROut = this.wNVRData & (ChipSet8080.VT100.NVR.WORDMASK + 1);
break;
default:
@ -886,35 +886,35 @@ ChipSet.prototype.doNVRCommand = function()
/**
* inVT100Flags(port, addrFrom)
*
* @this {ChipSet}
* @this {ChipSet8080}
* @param {number} port (0x42)
* @param {number} [addrFrom] (not defined if the Debugger is trying to read the specified port)
* @return {number} simulated port value
*/
ChipSet.prototype.inVT100Flags = function(port, addrFrom)
ChipSet8080.prototype.inVT100Flags = function(port, addrFrom)
{
/*
* The NVR_CLK bit is driven by LBA7 (ie, bit 7 from Line Buffer Address generation); see the DC011 discussion above.
*/
var b = this.bFlags;
b &= ~ChipSet.VT100.FLAGS.NVR_CLK;
b &= ~ChipSet8080.VT100.FLAGS.NVR_CLK;
if (this.getVT100LBA(7)) {
b |= ChipSet.VT100.FLAGS.NVR_CLK;
b |= ChipSet8080.VT100.FLAGS.NVR_CLK;
if (b != this.bFlags) {
this.doNVRCommand();
}
}
b &= ~ChipSet.VT100.FLAGS.NVR_DATA;
b &= ~ChipSet8080.VT100.FLAGS.NVR_DATA;
if (this.bNVROut) {
b |= ChipSet.VT100.FLAGS.NVR_DATA;
b |= ChipSet8080.VT100.FLAGS.NVR_DATA;
}
b &= ~ChipSet.VT100.FLAGS.KBD_XMIT;
b &= ~ChipSet8080.VT100.FLAGS.KBD_XMIT;
if (this.kbd && this.kbd.isTransmitterReady()) {
b |= ChipSet.VT100.FLAGS.KBD_XMIT;
b |= ChipSet8080.VT100.FLAGS.KBD_XMIT;
}
b &= ~ChipSet.VT100.FLAGS.UART_XMIT;
b &= ~ChipSet8080.VT100.FLAGS.UART_XMIT;
if (this.serial && this.serial.isTransmitterReady()) {
b |= ChipSet.VT100.FLAGS.UART_XMIT;
b |= ChipSet8080.VT100.FLAGS.UART_XMIT;
}
this.bFlags = b;
this.printMessageIO(port, null, addrFrom, "FLAGS", b);
@ -924,12 +924,12 @@ ChipSet.prototype.inVT100Flags = function(port, addrFrom)
/**
* outVT100Brightness(port, b, addrFrom)
*
* @this {ChipSet}
* @this {ChipSet8080}
* @param {number} port (0x42)
* @param {number} b
* @param {number} [addrFrom] (not defined if the Debugger is trying to write the specified port)
*/
ChipSet.prototype.outVT100Brightness = function(port, b, addrFrom)
ChipSet8080.prototype.outVT100Brightness = function(port, b, addrFrom)
{
this.printMessageIO(port, b, addrFrom, "BRIGHTNESS");
this.bBrightness = b;
@ -938,12 +938,12 @@ ChipSet.prototype.outVT100Brightness = function(port, b, addrFrom)
/**
* outVT100NVRLatch(port, b, addrFrom)
*
* @this {ChipSet}
* @this {ChipSet8080}
* @param {number} port (0x62)
* @param {number} b
* @param {number} [addrFrom] (not defined if the Debugger is trying to write the specified port)
*/
ChipSet.prototype.outVT100NVRLatch = function(port, b, addrFrom)
ChipSet8080.prototype.outVT100NVRLatch = function(port, b, addrFrom)
{
this.printMessageIO(port, b, addrFrom, "NVR.LATCH");
this.bNVRLatch = b;
@ -955,12 +955,12 @@ ChipSet.prototype.outVT100NVRLatch = function(port, b, addrFrom)
* TODO: Consider whether we should disable any interrupts (eg, vertical retrace) until
* this port is initialized at runtime.
*
* @this {ChipSet}
* @this {ChipSet8080}
* @param {number} port (0xA2)
* @param {number} b
* @param {number} [addrFrom] (not defined if the Debugger is trying to write the specified port)
*/
ChipSet.prototype.outVT100DC012 = function(port, b, addrFrom)
ChipSet8080.prototype.outVT100DC012 = function(port, b, addrFrom)
{
this.printMessageIO(port, b, addrFrom, "DC012");
@ -997,29 +997,29 @@ ChipSet.prototype.outVT100DC012 = function(port, b, addrFrom)
/**
* outVT100DC011(port, b, addrFrom)
*
* @this {ChipSet}
* @this {ChipSet8080}
* @param {number} port (0xC2)
* @param {number} b
* @param {number} [addrFrom] (not defined if the Debugger is trying to write the specified port)
*/
ChipSet.prototype.outVT100DC011 = function(port, b, addrFrom)
ChipSet8080.prototype.outVT100DC011 = function(port, b, addrFrom)
{
this.printMessageIO(port, b, addrFrom, "DC011");
if (b & ChipSet.VT100.DC011.RATE60) {
b &= ChipSet.VT100.DC011.RATE50;
if (b & ChipSet8080.VT100.DC011.RATE60) {
b &= ChipSet8080.VT100.DC011.RATE50;
if (this.bDC011Rate != b) {
this.bDC011Rate = b;
if (this.video) {
this.video.updateRate(this.bDC011Rate == ChipSet.VT100.DC011.RATE50? 50 : 60);
this.video.updateRate(this.bDC011Rate == ChipSet8080.VT100.DC011.RATE50? 50 : 60);
}
}
} else {
b &= ChipSet.VT100.DC011.COLS132;
b &= ChipSet8080.VT100.DC011.COLS132;
if (this.bDC011Cols != b) {
this.bDC011Cols = b;
if (this.video) {
var nCols = (this.bDC011Cols == ChipSet.VT100.DC011.COLS132? 132 : 80);
var nRows = (nCols > 80 && (this.bFlags & ChipSet.VT100.FLAGS.NO_AVO)? 14 : 24);
var nCols = (this.bDC011Cols == ChipSet8080.VT100.DC011.COLS132? 132 : 80);
var nRows = (nCols > 80 && (this.bFlags & ChipSet8080.VT100.FLAGS.NO_AVO)? 14 : 24);
this.video.updateDimensions(nCols, nRows);
}
}
@ -1029,47 +1029,47 @@ ChipSet.prototype.outVT100DC011 = function(port, b, addrFrom)
/*
* Port notification tables
*/
ChipSet.SI1978.portsInput = {
0x00: ChipSet.prototype.inSIStatus0,
0x01: ChipSet.prototype.inSIStatus1,
0x02: ChipSet.prototype.inSIStatus2,
0x03: ChipSet.prototype.inSIShiftResult
ChipSet8080.SI1978.portsInput = {
0x00: ChipSet8080.prototype.inSIStatus0,
0x01: ChipSet8080.prototype.inSIStatus1,
0x02: ChipSet8080.prototype.inSIStatus2,
0x03: ChipSet8080.prototype.inSIShiftResult
};
ChipSet.SI1978.portsOutput = {
0x02: ChipSet.prototype.outSIShiftCount,
0x03: ChipSet.prototype.outSISound1,
0x04: ChipSet.prototype.outSIShiftData,
0x05: ChipSet.prototype.outSISound2,
0x06: ChipSet.prototype.outSIWatchdog
ChipSet8080.SI1978.portsOutput = {
0x02: ChipSet8080.prototype.outSIShiftCount,
0x03: ChipSet8080.prototype.outSISound1,
0x04: ChipSet8080.prototype.outSIShiftData,
0x05: ChipSet8080.prototype.outSISound2,
0x06: ChipSet8080.prototype.outSIWatchdog
};
ChipSet.VT100.portsInput = {
0x42: ChipSet.prototype.inVT100Flags
ChipSet8080.VT100.portsInput = {
0x42: ChipSet8080.prototype.inVT100Flags
};
ChipSet.VT100.portsOutput = {
0x42: ChipSet.prototype.outVT100Brightness,
0x62: ChipSet.prototype.outVT100NVRLatch,
0xA2: ChipSet.prototype.outVT100DC012,
0xC2: ChipSet.prototype.outVT100DC011
ChipSet8080.VT100.portsOutput = {
0x42: ChipSet8080.prototype.outVT100Brightness,
0x62: ChipSet8080.prototype.outVT100NVRLatch,
0xA2: ChipSet8080.prototype.outVT100DC012,
0xC2: ChipSet8080.prototype.outVT100DC011
};
/**
* ChipSet.init()
* ChipSet8080.init()
*
* This function operates on every HTML element of class "chipset", extracting the
* JSON-encoded parameters for the ChipSet constructor from the element's "data-value"
* attribute, invoking the constructor to create a ChipSet component, and then binding
* any associated HTML controls to the new component.
*/
ChipSet.init = function()
ChipSet8080.init = function()
{
var aeChipSet = Component.getElementsByClass(document, PC8080.APPCLASS, "chipset");
for (var iChip = 0; iChip < aeChipSet.length; iChip++) {
var eChipSet = aeChipSet[iChip];
var parmsChipSet = Component.getComponentParms(eChipSet);
var chipset = new ChipSet(parmsChipSet);
var chipset = new ChipSet8080(parmsChipSet);
Component.bindComponentControls(chipset, eChipSet, PC8080.APPCLASS);
}
};
@ -1077,6 +1077,6 @@ ChipSet.init = function()
/*
* Initialize every ChipSet module on the page.
*/
web.onInit(ChipSet.init);
web.onInit(ChipSet8080.init);
if (NODE) module.exports = ChipSet;
if (NODE) module.exports = ChipSet8080;

View file

@ -42,13 +42,13 @@ if (NODE) {
* TODO: I'm confused why WebStorm complains if the following require() is missing in THIS file but not other files.
*/
var PC8080 = require("./defines");
var Messages = require("./messages");
var Bus = require("./bus");
var State = require("./state");
var Bus8080 = require("./bus");
var Messages8080= require("./messages");
var State8080 = require("./state");
}
/**
* Computer(parmsComputer, parmsMachine, fSuspended)
* Computer8080(parmsComputer, parmsMachine, fSuspended)
*
* @constructor
* @extends Component
@ -56,7 +56,7 @@ if (NODE) {
* @param {Object} [parmsMachine]
* @param {boolean} [fSuspended]
*
* The Computer component has no required (parmsComputer) properties, but it does
* The Computer8080 component has no required (parmsComputer) properties, but it does
* support the following:
*
* autoPower: true to automatically power the computer (default), false to wait;
@ -67,7 +67,7 @@ if (NODE) {
* while 24 is required for 80286 protected-mode addressing. This value is passed
* directly through to the Bus component; see that component for more details.
*
* resume: one of the Computer.RESUME constants, which are as follows:
* resume: one of the Computer8080.RESUME constants, which are as follows:
* '0' if resume disabled (default)
* '1' if enabled without prompting
* '2' if enabled with prompting
@ -81,13 +81,13 @@ if (NODE) {
* autoMount: if set, this should override any 'autoMount' property in the FDC's
* parmsFDC object.
*
* autoPower: if set, this should override any 'autoPower' property in the Computer's
* autoPower: if set, this should override any 'autoPower' property in the Computer8080's
* parmsComputer object.
*
* messages: if set, this should override any 'messages' property in the Debugger's
* parmsDbg object.
*
* state: if set, this should override any 'state' property in the Computer's
* state: if set, this should override any 'state' property in the Computer8080's
* parmsComputer object.
*
* url: the location of the machine XML file
@ -109,9 +109,9 @@ if (NODE) {
* function (if it has one--it's optional). We call the CPU's powerUp() function last,
* so that the CPU is assured that all other components are ready and "powered".
*/
function Computer(parmsComputer, parmsMachine, fSuspended) {
function Computer8080(parmsComputer, parmsMachine, fSuspended) {
Component.call(this, "Computer", parmsComputer, Computer, Messages.COMPUTER);
Component.call(this, "Computer", parmsComputer, Computer8080, Messages8080.COMPUTER);
this.flags.fPowered = false;
@ -130,7 +130,7 @@ function Computer(parmsComputer, parmsMachine, fSuspended) {
*/
this.nBusWidth = parmsComputer['busWidth'] || parmsComputer['buswidth'];
this.resume = Computer.RESUME_NONE;
this.resume = Computer8080.RESUME_NONE;
this.sStateData = null;
this.fStateData = false; // remembers if sStateData was loaded
this.fServerState = false;
@ -151,12 +151,12 @@ function Computer(parmsComputer, parmsMachine, fSuspended) {
* where we know getComponentByType() will only return an CPUState object or null), wrap the expression
* in parentheses. I never knew this until I stumbled across it in "Closure: The Definitive Guide".
*/
this.cpu = /** @type {CPUState} */ (Component.getComponentByType("CPU", this.id));
this.cpu = /** @type {CPUState8080} */ (Component.getComponentByType("CPU", this.id));
if (!this.cpu) {
Component.error("Unable to find CPU component");
return;
}
this.dbg = /** @type {Debugger} */ (Component.getComponentByType("Debugger", this.id));
this.dbg = /** @type {Debugger8080} */ (Component.getComponentByType("Debugger", this.id));
/*
* Enumerate all Video components for future updateVideo() calls.
@ -169,14 +169,14 @@ function Computer(parmsComputer, parmsMachine, fSuspended) {
/*
* Initialize the Bus component
*/
this.bus = new Bus({'id': this.idMachine + '.bus', 'busWidth': this.nBusWidth}, this.cpu, this.dbg);
this.bus = new Bus8080({'id': this.idMachine + '.bus', 'busWidth': this.nBusWidth}, this.cpu, this.dbg);
/*
* Iterate through all the components and connect them to the Control Panel, if any
*/
var iComponent, component;
var aComponents = Component.getComponents(this.id);
this.panel = /** @type {Panel} */ (Component.getComponentByType("Panel", this.id));
this.panel = /** @type {Panel8080} */ (Component.getComponentByType("Panel", this.id));
if (this.panel && this.panel.controlPrint) {
for (iComponent = 0; iComponent < aComponents.length; iComponent++) {
@ -240,7 +240,7 @@ function Computer(parmsComputer, parmsMachine, fSuspended) {
sStatePath = this.sStatePath = sState;
if (!fAllowResume) {
this.fServerState = true;
this.resume = Computer.RESUME_NONE;
this.resume = Computer8080.RESUME_NONE;
}
if (this.resume) {
this.stateComputer = new State(this, PC8080.APPVERSION);
@ -278,33 +278,33 @@ function Computer(parmsComputer, parmsMachine, fSuspended) {
if (!fSuspended && this.fAutoPower) this.wait(this.powerOn);
}
Component.subclass(Computer);
Component.subclass(Computer8080);
Computer.STATE_FAILSAFE = "failsafe";
Computer.STATE_VALIDATE = "validate";
Computer.STATE_TIMESTAMP = "timestamp";
Computer.STATE_VERSION = "version";
Computer.STATE_HOSTURL = "url";
Computer.STATE_BROWSER = "browser";
Computer.STATE_USERID = "user";
Computer8080.STATE_FAILSAFE = "failsafe";
Computer8080.STATE_VALIDATE = "validate";
Computer8080.STATE_TIMESTAMP = "timestamp";
Computer8080.STATE_VERSION = "version";
Computer8080.STATE_HOSTURL = "url";
Computer8080.STATE_BROWSER = "browser";
Computer8080.STATE_USERID = "user";
/*
* The following constants define all the resume options. Negative values (eg, RESUME_REPOWER) are for
* internal use only, and RESUME_DELETE is not documented (it provides a way of deleting ALL saved states
* whenever a resume is declined). As a result, the only "end-user" values are 0, 1 and 2.
*/
Computer.RESUME_REPOWER = -1; // resume without changing any state (for internal use only)
Computer.RESUME_NONE = 0; // default (no resume)
Computer.RESUME_AUTO = 1; // automatically save/restore state
Computer.RESUME_PROMPT = 2; // automatically save but conditionally restore (WARNING: if restore is declined, any state is discarded)
Computer.RESUME_DELETE = 3; // same as RESUME_PROMPT but discards ALL machines states whenever ANY machine restore is declined (undocumented)
Computer8080.RESUME_REPOWER = -1; // resume without changing any state (for internal use only)
Computer8080.RESUME_NONE = 0; // default (no resume)
Computer8080.RESUME_AUTO = 1; // automatically save/restore state
Computer8080.RESUME_PROMPT = 2; // automatically save but conditionally restore (WARNING: if restore is declined, any state is discarded)
Computer8080.RESUME_DELETE = 3; // same as RESUME_PROMPT but discards ALL machines states whenever ANY machine restore is declined (undocumented)
/**
* getMachineID()
*
* @return {string}
*/
Computer.prototype.getMachineID = function()
Computer8080.prototype.getMachineID = function()
{
return this.sMachineID;
};
@ -316,7 +316,7 @@ Computer.prototype.getMachineID = function()
*
* @param {Object} [parmsMachine]
*/
Computer.prototype.setMachineParms = function(parmsMachine)
Computer8080.prototype.setMachineParms = function(parmsMachine)
{
if (!parmsMachine) {
var sParms;
@ -345,7 +345,7 @@ Computer.prototype.setMachineParms = function(parmsMachine)
* @param {Object} [parmsComponent]
* @return {string|undefined}
*/
Computer.prototype.getMachineParm = function(sParm, parmsComponent)
Computer8080.prototype.getMachineParm = function(sParm, parmsComponent)
{
/*
* When checking parmsURL, the check is allowed be a bit looser, because URL parameters are
@ -373,7 +373,7 @@ Computer.prototype.getMachineParm = function(sParm, parmsComponent)
*
* @return {string|null}
*/
Computer.prototype.saveMachineParms = function()
Computer8080.prototype.saveMachineParms = function()
{
return this.parmsMachine? JSON.stringify(this.parmsMachine) : null;
};
@ -383,7 +383,7 @@ Computer.prototype.saveMachineParms = function()
*
* @return {string}
*/
Computer.prototype.getUserID = function()
Computer8080.prototype.getUserID = function()
{
return this.sUserID || "";
};
@ -391,12 +391,12 @@ Computer.prototype.getUserID = function()
/**
* doneLoad(sURL, sStateData, nErrorCode)
*
* @this {Computer}
* @this {Computer8080}
* @param {string} sURL
* @param {string} sStateData
* @param {number} nErrorCode
*/
Computer.prototype.doneLoad = function(sURL, sStateData, nErrorCode)
Computer8080.prototype.doneLoad = function(sURL, sStateData, nErrorCode)
{
if (!nErrorCode) {
this.sStateData = sStateData;
@ -426,11 +426,11 @@ Computer.prototype.doneLoad = function(sURL, sStateData, nErrorCode)
*
* param {function(this:Computer, (number|Array|undefined)): undefined} fn
*
* @this {Computer}
* @this {Computer8080}
* @param {function(...)} fn
* @param {number|Array} [parms] optional parameters
*/
Computer.prototype.wait = function(fn, parms)
Computer8080.prototype.wait = function(fn, parms)
{
var computer = this;
var aComponents = Component.getComponents(this.id);
@ -443,7 +443,7 @@ Computer.prototype.wait = function(fn, parms)
return;
}
}
if (DEBUG && this.messageEnabled()) this.printMessage("Computer.wait(ready)");
if (DEBUG && this.messageEnabled()) this.printMessage("Computer8080.wait(ready)");
fn.call(this, parms);
};
@ -452,17 +452,17 @@ Computer.prototype.wait = function(fn, parms)
*
* NOTE: We clear() stateValidate only when there's no stateComputer.
*
* @this {Computer}
* @this {Computer8080}
* @param {State|null} [stateComputer]
* @return {boolean} true if state passes validation, false if not
*/
Computer.prototype.validateState = function(stateComputer)
Computer8080.prototype.validateState = function(stateComputer)
{
var fValid = true;
var stateValidate = new State(this, PC8080.APPVERSION, Computer.STATE_VALIDATE);
var stateValidate = new State(this, PC8080.APPVERSION, Computer8080.STATE_VALIDATE);
if (stateValidate.load() && stateValidate.parse()) {
var sTimestampValidate = stateValidate.get(Computer.STATE_TIMESTAMP);
var sTimestampComputer = stateComputer ? stateComputer.get(Computer.STATE_TIMESTAMP) : "unknown";
var sTimestampValidate = stateValidate.get(Computer8080.STATE_TIMESTAMP);
var sTimestampComputer = stateComputer? stateComputer.get(Computer8080.STATE_TIMESTAMP) : "unknown";
if (sTimestampValidate != sTimestampComputer) {
this.notice("Machine state may be out-of-date\n(" + sTimestampValidate + " vs. " + sTimestampComputer + ")\nCheck your browser's local storage limits");
fValid = false;
@ -481,17 +481,17 @@ Computer.prototype.validateState = function(stateComputer)
*
* Power every component "up", applying any previously available state information.
*
* @this {Computer}
* @this {Computer8080}
* @param {number} [resume] is a valid RESUME value; default is this.resume
*/
Computer.prototype.powerOn = function(resume)
Computer8080.prototype.powerOn = function(resume)
{
if (resume === undefined) {
resume = this.resume || (this.sStateData? Computer.RESUME_AUTO : Computer.RESUME_NONE);
resume = this.resume || (this.sStateData? Computer8080.RESUME_AUTO : Computer8080.RESUME_NONE);
}
if (DEBUG && this.messageEnabled()) {
this.printMessage("Computer.powerOn(" + (resume == Computer.RESUME_REPOWER ? "repower" : (resume ? "resume" : "")) + ")");
this.printMessage("Computer8080.powerOn(" + (resume == Computer8080.RESUME_REPOWER ? "repower" : (resume ? "resume" : "")) + ")");
}
if (this.nPowerChange) {
@ -504,10 +504,10 @@ Computer.prototype.powerOn = function(resume)
this.fRestoreError = false;
var stateComputer = this.stateComputer || new State(this, PC8080.APPVERSION);
if (resume == Computer.RESUME_REPOWER) {
if (resume == Computer8080.RESUME_REPOWER) {
fRepower = true;
}
else if (resume > Computer.RESUME_NONE) {
else if (resume > Computer8080.RESUME_NONE) {
if (stateComputer.load(this.sStateData)) {
/*
* Since we're resuming something (either a predefined state or a state from localStorage), let's
@ -515,7 +515,7 @@ Computer.prototype.powerOn = function(resume)
* Which means, of course, that if a previous "failsafe" checkpoint already exists, something bad
* may have happened the last time around.
*/
this.stateFailSafe = new State(this, PC8080.APPVERSION, Computer.STATE_FAILSAFE);
this.stateFailSafe = new State(this, PC8080.APPVERSION, Computer8080.STATE_FAILSAFE);
if (this.stateFailSafe.load()) {
this.powerReport(stateComputer);
/*
@ -523,7 +523,7 @@ Computer.prototype.powerOn = function(resume)
* all the way to RESUME_PROMPT, so that the user will be prompted, and if the user declines to
* restore, the state will be removed.
*/
resume = Computer.RESUME_PROMPT;
resume = Computer8080.RESUME_PROMPT;
/*
* To ensure that the set() below succeeds, we need to call unload(), otherwise it may fail
* with a "read only" error (eg, "TypeError: Cannot assign to read only property 'timestamp'").
@ -531,11 +531,11 @@ Computer.prototype.powerOn = function(resume)
this.stateFailSafe.unload();
}
this.stateFailSafe.set(Computer.STATE_TIMESTAMP, usr.getTimestamp());
this.stateFailSafe.set(Computer8080.STATE_TIMESTAMP, usr.getTimestamp());
this.stateFailSafe.store();
var fValidate = this.resume && !this.fServerState;
if (resume == Computer.RESUME_AUTO || web.confirmUser("Click OK to restore the previous " + PC8080.APPNAME + " machine state, or CANCEL to reset the machine.")) {
if (resume == Computer8080.RESUME_AUTO || web.confirmUser("Click OK to restore the previous " + PC8080.APPNAME + " machine state, or CANCEL to reset the machine.")) {
fRestore = stateComputer.parse();
if (fRestore) {
var sCode = stateComputer.get(UserAPI.RES.CODE);
@ -578,7 +578,7 @@ Computer.prototype.powerOn = function(resume)
/*
* RESUME_PROMPT indicates we should delete the state if they clicked Cancel to confirm() above.
*/
if (resume == Computer.RESUME_PROMPT) stateComputer.clear();
if (resume == Computer8080.RESUME_PROMPT) stateComputer.clear();
}
} else {
/*
@ -610,7 +610,7 @@ Computer.prototype.powerOn = function(resume)
*/
var aParms = [stateComputer, resume, fRestore];
if (resume != Computer.RESUME_REPOWER) {
if (resume != Computer8080.RESUME_REPOWER) {
this.wait(this.donePowerOn, aParms);
return;
}
@ -620,14 +620,14 @@ Computer.prototype.powerOn = function(resume)
/**
* powerRestore(component, stateComputer, fRepower, fRestore)
*
* @this {Computer}
* @this {Computer8080}
* @param {Component} component
* @param {State} stateComputer
* @param {boolean} fRepower
* @param {boolean} fRestore
* @return {boolean} true if restore should continue, false if not
*/
Computer.prototype.powerRestore = function(component, stateComputer, fRepower, fRestore)
Computer8080.prototype.powerRestore = function(component, stateComputer, fRepower, fRestore)
{
if (!component.flags.fPowered) {
@ -685,7 +685,7 @@ Computer.prototype.powerRestore = function(component, stateComputer, fRepower, f
*/
if (this.sStatePath && !this.fStateData) {
stateComputer.clear();
this.resume = Computer.RESUME_NONE;
this.resume = Computer8080.RESUME_NONE;
web.reloadPage();
} else {
/*
@ -725,17 +725,17 @@ Computer.prototype.powerRestore = function(component, stateComputer, fRepower, f
*
* This is nothing more than a continuation of powerOn(), giving us the option of calling wait() one more time.
*
* @this {Computer}
* @this {Computer8080}
* @param {Array} aParms containing [stateComputer, resume, fRestore]
*/
Computer.prototype.donePowerOn = function(aParms)
Computer8080.prototype.donePowerOn = function(aParms)
{
var stateComputer = aParms[0];
var fRepower = (aParms[1] < 0);
var fRestore = aParms[2];
if (DEBUG && this.flags.fPowered && this.messageEnabled()) {
this.printMessage("Computer.donePowerOn(): redundant");
this.printMessage("Computer8080.donePowerOn(): redundant");
}
this.fInitialized = true;
@ -775,10 +775,10 @@ Computer.prototype.donePowerOn = function(aParms)
/**
* checkPower()
*
* @this {Computer}
* @this {Computer8080}
* @return {boolean} true if the computer is fully powered, false otherwise
*/
Computer.prototype.checkPower = function()
Computer8080.prototype.checkPower = function()
{
if (this.flags.fPowered) return true;
@ -803,10 +803,10 @@ Computer.prototype.checkPower = function()
/**
* powerReport(stateComputer)
*
* @this {Computer}
* @this {Computer8080}
* @param {State} stateComputer
*/
Computer.prototype.powerReport = function(stateComputer)
Computer8080.prototype.powerReport = function(stateComputer)
{
if (web.confirmUser("There may be a problem with your " + PC8080.APPNAME + " machine.\n\nTo help us diagnose it, click OK to send this " + PC8080.APPNAME + " machine state to http://" + SITEHOST + ".")) {
web.sendReport(PC8080.APPNAME, PC8080.APPVERSION, this.url, this.getUserID(), ReportAPI.TYPE.BUG, stateComputer.toString());
@ -839,18 +839,18 @@ Computer.prototype.powerReport = function(stateComputer)
* As it stands, the worst that happens is any manually mounted disk images might have to be manually remounted,
* which doesn't seem like a huge problem.
*
* @this {Computer}
* @this {Computer8080}
* @param {boolean} [fSave] is true to request a saved state
* @param {boolean} [fShutdown] is true if the machine is being shut down
* @return {string|null} string representing the saved state (or null if error)
*/
Computer.prototype.powerOff = function(fSave, fShutdown)
Computer8080.prototype.powerOff = function(fSave, fShutdown)
{
var data;
var sState = "none";
if (DEBUG && this.messageEnabled()) {
this.printMessage("Computer.powerOff(" + (fSave ? "save" : "nosave") + (fShutdown ? ",shutdown" : "") + ")");
this.printMessage("Computer8080.powerOff(" + (fSave ? "save" : "nosave") + (fShutdown ? ",shutdown" : "") + ")");
}
if (this.nPowerChange) {
@ -859,14 +859,14 @@ Computer.prototype.powerOff = function(fSave, fShutdown)
this.nPowerChange--;
var stateComputer = new State(this, PC8080.APPVERSION);
var stateValidate = new State(this, PC8080.APPVERSION, Computer.STATE_VALIDATE);
var stateValidate = new State(this, PC8080.APPVERSION, Computer8080.STATE_VALIDATE);
var sTimestamp = usr.getTimestamp();
stateValidate.set(Computer.STATE_TIMESTAMP, sTimestamp);
stateComputer.set(Computer.STATE_TIMESTAMP, sTimestamp);
stateComputer.set(Computer.STATE_VERSION, APPVERSION);
stateComputer.set(Computer.STATE_HOSTURL, web.getHostURL());
stateComputer.set(Computer.STATE_BROWSER, web.getUserAgent());
stateValidate.set(Computer8080.STATE_TIMESTAMP, sTimestamp);
stateComputer.set(Computer8080.STATE_TIMESTAMP, sTimestamp);
stateComputer.set(Computer8080.STATE_VERSION, APPVERSION);
stateComputer.set(Computer8080.STATE_HOSTURL, web.getHostURL());
stateComputer.set(Computer8080.STATE_BROWSER, web.getUserAgent());
/*
* Always power the CPU "down" first, just to help insure it doesn't ask other components to do anything
@ -932,7 +932,7 @@ Computer.prototype.powerOff = function(fSave, fShutdown)
*/
if (this.resume) {
fClear = true;
fClearAll = (this.resume == Computer.RESUME_DELETE);
fClearAll = (this.resume == Computer8080.RESUME_DELETE);
}
}
if (fClear) {
@ -963,9 +963,9 @@ Computer.prototype.powerOff = function(fSave, fShutdown)
* allocated the Bus object ourselves, after all the other components were allocated, it ends
* up near the end of Component's list of components. Hence the special case for this.bus below.
*
* @this {Computer}
* @this {Computer8080}
*/
Computer.prototype.reset = function()
Computer8080.prototype.reset = function()
{
if (this.bus && this.bus.reset) {
/*
@ -993,11 +993,11 @@ Computer.prototype.reset = function()
* Note that we're called by runCPU(), which is why we exclude the CPU component,
* as well as ourselves.
*
* @this {Computer}
* @this {Computer8080}
* @param {number} ms
* @param {number} nCycles
*/
Computer.prototype.start = function(ms, nCycles)
Computer8080.prototype.start = function(ms, nCycles)
{
var aComponents = Component.getComponents(this.id);
for (var iComponent = 0; iComponent < aComponents.length; iComponent++) {
@ -1017,11 +1017,11 @@ Computer.prototype.start = function(ms, nCycles)
* Note that we're called by runCPU(), which is why we exclude the CPU component,
* as well as ourselves.
*
* @this {Computer}
* @this {Computer8080}
* @param {number} ms
* @param {number} nCycles
*/
Computer.prototype.stop = function(ms, nCycles)
Computer8080.prototype.stop = function(ms, nCycles)
{
var aComponents = Component.getComponents(this.id);
for (var iComponent = 0; iComponent < aComponents.length; iComponent++) {
@ -1036,14 +1036,14 @@ Computer.prototype.stop = function(ms, nCycles)
/**
* setBinding(sHTMLType, sBinding, control, sValue)
*
* @this {Computer}
* @this {Computer8080}
* @param {string|null} sHTMLType is the type of the HTML control (eg, "button", "list", "text", "submit", "textarea", "canvas")
* @param {string} sBinding is the value of the 'binding' parameter stored in the HTML control's "data-value" attribute (eg, "reset")
* @param {Object} control is the HTML control DOM object (eg, HTMLButtonElement)
* @param {string} [sValue] optional data value
* @return {boolean} true if binding was successful, false if unrecognized binding request
*/
Computer.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
Computer8080.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
{
var computer = this;
@ -1130,9 +1130,9 @@ Computer.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
/**
* resetUserID()
*/
Computer.prototype.resetUserID = function()
Computer8080.prototype.resetUserID = function()
{
web.setLocalStorageItem(Computer.STATE_USERID, "");
web.setLocalStorageItem(Computer8080.STATE_USERID, "");
this.sUserID = null;
};
@ -1142,11 +1142,11 @@ Computer.prototype.resetUserID = function()
* @param {boolean} [fPrompt]
* @returns {string|null|undefined}
*/
Computer.prototype.queryUserID = function(fPrompt)
Computer8080.prototype.queryUserID = function(fPrompt)
{
var sUserID = this.sUserID;
if (!sUserID) {
sUserID = web.getLocalStorageItem(Computer.STATE_USERID);
sUserID = web.getLocalStorageItem(Computer8080.STATE_USERID);
if (sUserID !== undefined) {
if (!sUserID && fPrompt) {
/*
@ -1170,11 +1170,11 @@ Computer.prototype.queryUserID = function(fPrompt)
/**
* verifyUserID(sUserID)
*
* @this {Computer}
* @this {Computer8080}
* @param {string} sUserID
* @return {string} validated user ID, or null if error
*/
Computer.prototype.verifyUserID = function(sUserID)
Computer8080.prototype.verifyUserID = function(sUserID)
{
this.sUserID = null;
var fMessages = DEBUG && this.messageEnabled();
@ -1187,8 +1187,8 @@ Computer.prototype.verifyUserID = function(sUserID)
try {
response = eval("(" + sResponse + ")");
if (response.code && response.code == UserAPI.CODE.OK) {
web.setLocalStorageItem(Computer.STATE_USERID, response.data);
if (fMessages) this.printMessage(Computer.STATE_USERID + " updated: " + response.data);
web.setLocalStorageItem(Computer8080.STATE_USERID, response.data);
if (fMessages) this.printMessage(Computer8080.STATE_USERID + " updated: " + response.data);
this.sUserID = response.data;
} else {
if (fMessages) this.printMessage(response.code + ": " + response.data);
@ -1205,20 +1205,20 @@ Computer.prototype.verifyUserID = function(sUserID)
/**
* getServerStatePath()
*
* @this {Computer}
* @this {Computer8080}
* @return {string|null} sStatePath (null if no localStorage or no USERID stored in localStorage)
*/
Computer.prototype.getServerStatePath = function()
Computer8080.prototype.getServerStatePath = function()
{
var sStatePath = null;
if (this.sUserID) {
if (DEBUG && this.messageEnabled()) {
this.printMessage(Computer.STATE_USERID + " for load: " + this.sUserID);
this.printMessage(Computer8080.STATE_USERID + " for load: " + this.sUserID);
}
sStatePath = web.getHost() + UserAPI.ENDPOINT + '?' + UserAPI.QUERY.REQ + '=' + UserAPI.REQ.LOAD + '&' + UserAPI.QUERY.USER + '=' + this.sUserID + '&' + UserAPI.QUERY.STATE + '=' + State.key(this, PC8080.APPVERSION);
} else {
if (DEBUG && this.messageEnabled()) {
this.printMessage(Computer.STATE_USERID + " unavailable");
this.printMessage(Computer8080.STATE_USERID + " unavailable");
}
}
return sStatePath;
@ -1230,7 +1230,7 @@ Computer.prototype.getServerStatePath = function()
* @param {string} sUserID
* @param {string|null} sState
*/
Computer.prototype.saveServerState = function(sUserID, sState)
Computer8080.prototype.saveServerState = function(sUserID, sState)
{
/*
* We must pass fSync == true, because (as I understand it) browsers will blow off any async
@ -1265,16 +1265,16 @@ Computer.prototype.saveServerState = function(sUserID, sState)
/**
* storeServerState(sUserID, sState, fSync)
*
* @this {Computer}
* @this {Computer8080}
* @param {string} sUserID
* @param {string} sState
* @param {boolean} [fSync] is true if we're powering down and should perform a synchronous request (default is async)
* @return {*} server response if fSync is true and a response was received; otherwise null
*/
Computer.prototype.storeServerState = function(sUserID, sState, fSync)
Computer8080.prototype.storeServerState = function(sUserID, sState, fSync)
{
if (DEBUG && this.messageEnabled()) {
this.printMessage(Computer.STATE_USERID + " for store: " + sUserID);
this.printMessage(Computer8080.STATE_USERID + " for store: " + sUserID);
}
/*
* TODO: Determine whether or not any browsers cancel our request if we're called during a browser "shutdown" event,
@ -1310,9 +1310,9 @@ Computer.prototype.storeServerState = function(sUserID, sState, fSync)
*
* This handles UI requests to toggle the computer's power (eg, see the "power" button binding).
*
* @this {Computer}
* @this {Computer8080}
*/
Computer.prototype.onPower = function()
Computer8080.prototype.onPower = function()
{
if (!this.nPowerChange) {
if (!this.flags.fPowered) {
@ -1328,9 +1328,9 @@ Computer.prototype.onPower = function()
*
* This handles UI requests to reset the computer's state (eg, see the "reset" button binding).
*
* @this {Computer}
* @this {Computer8080}
*/
Computer.prototype.onReset = function()
Computer8080.prototype.onReset = function()
{
/*
* I'm going to start with the presumption that it makes little sense for an "unpowered" computer to be "reset";
@ -1349,10 +1349,10 @@ Computer.prototype.onReset = function()
*/
if (this.resume && !this.sResumePath) {
/*
* I used to bypass the prompt if this.resume == Computer.RESUME_AUTO, setting fSave to true automatically,
* I used to bypass the prompt if this.resume == Computer8080.RESUME_AUTO, setting fSave to true automatically,
* but that gives the user no means of resetting a resumable machine that contains errors in its resume state.
*/
var fSave = (/* this.resume == Computer.RESUME_AUTO || */ web.confirmUser("Click OK to save changes to this " + PC8080.APPNAME + " machine.\n\nWARNING: If you CANCEL, all disk changes will be discarded."));
var fSave = (/* this.resume == Computer8080.RESUME_AUTO || */ web.confirmUser("Click OK to save changes to this " + PC8080.APPNAME + " machine.\n\nWARNING: If you CANCEL, all disk changes will be discarded."));
this.powerOff(fSave, true);
/*
* Forcing the page to reload is an expedient option, but ugly. It's preferable to call powerOn()
@ -1371,7 +1371,7 @@ Computer.prototype.onReset = function()
return;
}
if (!fSave) this.fReload = true;
this.powerOn(Computer.RESUME_NONE);
this.powerOn(Computer8080.RESUME_NONE);
this.fReload = false;
} else {
this.reset();
@ -1382,13 +1382,14 @@ Computer.prototype.onReset = function()
/**
* getMachineComponent(sType, componentPrev)
*
* @this {Computer}
* @this {Computer8080}
* @param {string} sType
* @param {Component|null} [componentPrev] of previously returned component, if any
* @return {Component|null}
*/
Computer.prototype.getMachineComponent = function(sType, componentPrev)
Computer8080.prototype.getMachineComponent = function(sType, componentPrev)
{
var componentLast = componentPrev;
var aComponents = Component.getComponents(this.id);
for (var iComponent = 0; iComponent < aComponents.length; iComponent++) {
var component = aComponents[iComponent];
@ -1398,6 +1399,7 @@ Computer.prototype.getMachineComponent = function(sType, componentPrev)
}
if (component.type == sType) return component;
}
if (!componentLast) Component.log("Machine component type '" + sType + "' not found", "warning");
return null;
};
@ -1407,10 +1409,10 @@ Computer.prototype.getMachineComponent = function(sType, componentPrev)
* NOTE: When soft keyboard buttons call us to return focus to the machine (and away from the button),
* the scroll feature has annoying effect on iOS, so we no longer do it by default (fScroll must be true).
*
* @this {Computer}
* @this {Computer8080}
* @param {boolean} [fScroll]
*/
Computer.prototype.updateFocus = function(fScroll)
Computer8080.prototype.updateFocus = function(fScroll)
{
if (this.aVideo.length) {
/*
@ -1450,10 +1452,10 @@ Computer.prototype.updateFocus = function(fScroll)
* knows the names, number, sizes, etc, of all the active registers. The Panel component is the logical candidate,
* but Panel is an optional component; generally, only machines that include Debugger also include Panel.
*
* @this {Computer}
* @this {Computer8080}
* @param {boolean} [fForce] (true will display registers even if the CPU is running and "live" registers are not enabled)
*/
Computer.prototype.updateStatus = function(fForce)
Computer8080.prototype.updateStatus = function(fForce)
{
/*
* fForce is generally set to true whenever the CPU is transitioning to/from a running state, in which case
@ -1473,10 +1475,10 @@ Computer.prototype.updateStatus = function(fForce)
*
* Any high-frequency updates should be performed here (avoid updating DOM elements).
*
* @this {Computer}
* @this {Computer8080}
* @param {number} n (where 0 <= n < VIDEO_UPDATES_PER_SECOND for a normal update, or -1 for a forced update)
*/
Computer.prototype.updateVideo = function(n)
Computer8080.prototype.updateVideo = function(n)
{
for (var i = 0; i < this.aVideo.length; i++) {
this.aVideo[i].updateScreen(n);
@ -1484,14 +1486,14 @@ Computer.prototype.updateVideo = function(n)
};
/**
* Computer.init()
* Computer8080.init()
*
* For every machine represented by an HTML element of class "pcjs-machine", this function
* locates the HTML element of class "computer", extracting the JSON-encoded parameters for the
* Computer constructor from the element's "data-value" attribute, invoking the constructor to
* create a Computer component, and then binding any associated HTML controls to the new component.
*/
Computer.init = function()
Computer8080.init = function()
{
/*
* In non-COMPILED builds, embedMachine() may have set XMLVERSION.
@ -1516,7 +1518,7 @@ Computer.init = function()
* We set fSuspended in the Computer constructor because we want to "power up" the
* computer ourselves, after any/all bindings are in place.
*/
var computer = new Computer(parmsComputer, parmsMachine, true);
var computer = new Computer8080(parmsComputer, parmsMachine, true);
if (DEBUG && computer.messageEnabled()) {
computer.printMessage("onInit(" + computer.flags.fPowered + ")");
@ -1538,7 +1540,7 @@ Computer.init = function()
};
/**
* Computer.show()
* Computer8080.show()
*
* When exit() is using an "onbeforeunload" handler, this "onpageshow" handler allows us to repower everything,
* without either resetting or restoring. We call powerOn() with a special resume value (RESUME_REPOWER) if the
@ -1546,13 +1548,13 @@ Computer.init = function()
* should be very quick, essentially just marking all components as powered again (so that, for example, the Video
* component will start drawing again) and firing the CPU up again.
*/
Computer.show = function()
Computer8080.show = function()
{
var aeComputers = Component.getElementsByClass(document, PC8080.APPCLASS, "computer");
for (var iComputer = 0; iComputer < aeComputers.length; iComputer++) {
var eComputer = aeComputers[iComputer];
var parmsComputer = Component.getComponentParms(eComputer);
var computer = /** @type {Computer} */ (Component.getComponentByType("Computer", parmsComputer['id']));
var computer = /** @type {Computer8080} */ (Component.getComponentByType("Computer", parmsComputer['id']));
if (computer) {
if (DEBUG && computer.messageEnabled()) {
@ -1563,14 +1565,14 @@ Computer.show = function()
/**
* Repower the computer, notifying every component to continue running as-is.
*/
computer.powerOn(Computer.RESUME_REPOWER);
computer.powerOn(Computer8080.RESUME_REPOWER);
}
}
}
};
/**
* Computer.exit()
* Computer8080.exit()
*
* The Computer is currently the only component that uses an "exit" handler, which web.onExit() defines as
* either an "unload" or "onbeforeunload" handler. This gives us the opportunity to save the machine state,
@ -1586,7 +1588,7 @@ Computer.show = function()
* presence of an "onunload" handler generally causes a browser to throw the page away once the handler returns.
*
* However, in order to safely use "onbeforeunload", we must add yet another handler ("onpageshow") to repower
* everything, without either resetting or restoring. Hence, the Computer.show() function, which calls powerOn()
* everything, without either resetting or restoring. Hence, the Computer8080.show() function, which calls powerOn()
* with a special resume value (RESUME_REPOWER) if the computer is already marked as "ready", meaning the browser
* didn't change anything. This "repower" process should be very quick, essentially just marking all components as
* powered again (so that, for example, the Video component will start drawing again) and firing the CPU up again.
@ -1595,13 +1597,13 @@ Computer.show = function()
* "unload" instead. But even when the page must be rebuilt from scratch, the combination of browser cache and
* localStorage means the simulation should be restored and become operational almost immediately.
*/
Computer.exit = function()
Computer8080.exit = function()
{
var aeComputers = Component.getElementsByClass(document, PC8080.APPCLASS, "computer");
for (var iComputer = 0; iComputer < aeComputers.length; iComputer++) {
var eComputer = aeComputers[iComputer];
var parmsComputer = Component.getComponentParms(eComputer);
var computer = /** @type {Computer} */ (Component.getComponentByType("Computer", parmsComputer['id']));
var computer = /** @type {Computer8080} */ (Component.getComponentByType("Computer", parmsComputer['id']));
if (computer) {
if (DEBUG && computer.messageEnabled()) {
@ -1623,8 +1625,8 @@ Computer.exit = function()
/*
* Initialize every Computer on the page.
*/
web.onInit(Computer.init);
web.onShow(Computer.show);
web.onExit(Computer.exit);
web.onInit(Computer8080.init);
web.onShow(Computer8080.show);
web.onExit(Computer8080.exit);
if (NODE) module.exports = Computer;
if (NODE) module.exports = Computer8080;

View file

@ -35,15 +35,15 @@ if (NODE) {
var str = require("../../shared/lib/strlib");
var usr = require("../../shared/lib/usrlib");
var Component = require("../../shared/lib/component");
var Messages = require("./messages");
var Messages8080= require("./messages");
}
/**
* CPU(parmsCPU, nCyclesDefault)
* CPU8080(parmsCPU, nCyclesDefault)
*
* The CPU class supports the following (parmsCPU) properties:
* The CPU8080 class supports the following (parmsCPU) properties:
*
* cycles: the machine's base cycles per second; the CPUState constructor will
* cycles: the machine's base cycles per second; the CPUState8080 constructor will
* provide us with a default (based on the CPU model) to use as a fallback.
*
* multiplier: base cycle multiplier; default is 1.
@ -64,16 +64,16 @@ if (NODE) {
* This component is primarily responsible for interfacing the CPU with the outside
* world (eg, Panel and Debugger components), and managing overall CPU operation.
*
* It is extended by the CPUState component, where the simulation control logic resides.
* It is extended by the CPUState8080 component, where the simulation control logic resides.
*
* @constructor
* @extends Component
* @param {Object} parmsCPU
* @param {number} nCyclesDefault
*/
function CPU(parmsCPU, nCyclesDefault)
function CPU8080(parmsCPU, nCyclesDefault)
{
Component.call(this, "CPU", parmsCPU, CPU, Messages.CPU);
Component.call(this, "CPU", parmsCPU, CPU8080, Messages8080.CPU);
var nCycles = parmsCPU['cycles'] || nCyclesDefault;
@ -132,7 +132,7 @@ function CPU(parmsCPU, nCyclesDefault)
this.setReady();
}
Component.subclass(CPU);
Component.subclass(CPU8080);
/*
* Constants that control the frequency at which various updates should occur.
@ -141,9 +141,9 @@ Component.subclass(CPU);
* calcCycles(), which uses the nCyclesPerSecond passed to the constructor as a starting
* point and computes the following variables:
*
* this.aCounts.nCyclesPerYield (this.aCounts.nCyclesPerSecond / CPU.YIELDS_PER_SECOND)
* this.aCounts.nCyclesPerVideoUpdate (this.aCounts.nCyclesPerSecond / CPU.VIDEO_UPDATES_PER_SECOND)
* this.aCounts.nCyclesPerStatusUpdate (this.aCounts.nCyclesPerSecond / CPU.STATUS_UPDATES_PER_SECOND)
* this.aCounts.nCyclesPerYield (this.aCounts.nCyclesPerSecond / CPU8080.YIELDS_PER_SECOND)
* this.aCounts.nCyclesPerVideoUpdate (this.aCounts.nCyclesPerSecond / CPU8080.VIDEO_UPDATES_PER_SECOND)
* this.aCounts.nCyclesPerStatusUpdate (this.aCounts.nCyclesPerSecond / CPU8080.STATUS_UPDATES_PER_SECOND)
*
* The above variables are also multiplied by any cycle multiplier in effect, via setSpeed(),
* and then they're used to initialize another set of variables for each runCPU() iteration:
@ -152,42 +152,42 @@ Component.subclass(CPU);
* this.aCounts.nCyclesNextVideoUpdate <= this.aCounts.nCyclesPerVideoUpdate
* this.aCounts.nCyclesNextStatusUpdate <= this.aCounts.nCyclesPerStatusUpdate
*/
CPU.YIELDS_PER_SECOND = 30;
CPU.VIDEO_UPDATES_PER_SECOND = 60;
CPU.STATUS_UPDATES_PER_SECOND = 2;
CPU8080.YIELDS_PER_SECOND = 30;
CPU8080.VIDEO_UPDATES_PER_SECOND = 60;
CPU8080.STATUS_UPDATES_PER_SECOND = 2;
CPU.BUTTONS = ["power", "reset"];
CPU8080.BUTTONS = ["power", "reset"];
/**
* initBus(cmp, bus, cpu, dbg)
*
* @this {CPU}
* @param {Computer} cmp
* @param {Bus} bus
* @param {CPU} cpu
* @param {Debugger} dbg
* @this {CPU8080}
* @param {Computer8080} cmp
* @param {Bus8080} bus
* @param {CPU8080} cpu
* @param {Debugger8080} dbg
*/
CPU.prototype.initBus = function(cmp, bus, cpu, dbg)
CPU8080.prototype.initBus = function(cmp, bus, cpu, dbg)
{
this.cmp = cmp;
this.bus = bus;
this.dbg = dbg;
for (var i = 0; i < CPU.BUTTONS.length; i++) {
var control = this.bindings[CPU.BUTTONS[i]];
if (control) this.cmp.setBinding(null, CPU.BUTTONS[i], control);
for (var i = 0; i < CPU8080.BUTTONS.length; i++) {
var control = this.bindings[CPU8080.BUTTONS[i]];
if (control) this.cmp.setBinding(null, CPU8080.BUTTONS[i], control);
}
/*
* We need to know the refresh rate (and corresponding interrupt rate, if any) of the Video component.
*/
var video = /** @type {Video} */ (cmp.getMachineComponent("Video"));
this.refreshRate = video && video.getRefreshRate() || CPU.VIDEO_UPDATES_PER_SECOND;
var video = /** @type {Video8080} */ (cmp.getMachineComponent("Video"));
this.refreshRate = video && video.getRefreshRate() || CPU8080.VIDEO_UPDATES_PER_SECOND;
/*
* Attach the ChipSet component to the CPU so that it can be notified whenever the CPU stops and starts.
*/
this.chipset = /** @type {ChipSet} */ (cmp.getMachineComponent("ChipSet"));
this.chipset = /** @type {ChipSet8080} */ (cmp.getMachineComponent("ChipSet"));
/*
* We've already saved the parmsCPU 'autoStart' setting, but there may be a machine (or URL) override.
@ -203,9 +203,9 @@ CPU.prototype.initBus = function(cmp, bus, cpu, dbg)
/**
* reset()
*
* @this {CPU}
* @this {CPU8080}
*/
CPU.prototype.reset = function()
CPU8080.prototype.reset = function()
{
this.aCounts.nVideoUpdates = 0;
};
@ -215,10 +215,10 @@ CPU.prototype.reset = function()
*
* This is a placeholder for save support (overridden by the CPUState component).
*
* @this {CPU}
* @this {CPU8080}
* @return {Object|null}
*/
CPU.prototype.save = function()
CPU8080.prototype.save = function()
{
return null;
};
@ -228,11 +228,11 @@ CPU.prototype.save = function()
*
* This is a placeholder for restore support (overridden by the CPUState component).
*
* @this {CPU}
* @this {CPU8080}
* @param {Object} data
* @return {boolean} true if restore successful, false if not
*/
CPU.prototype.restore = function(data)
CPU8080.prototype.restore = function(data)
{
return false;
};
@ -240,12 +240,12 @@ CPU.prototype.restore = function(data)
/**
* powerUp(data, fRepower)
*
* @this {CPU}
* @this {CPU8080}
* @param {Object|null} data
* @param {boolean} [fRepower]
* @return {boolean} true if successful, false if failure
*/
CPU.prototype.powerUp = function(data, fRepower)
CPU8080.prototype.powerUp = function(data, fRepower)
{
if (!fRepower) {
if (!data || !this.restore) {
@ -286,12 +286,12 @@ CPU.prototype.powerUp = function(data, fRepower)
/**
* powerDown(fSave, fShutdown)
*
* @this {CPU}
* @this {CPU8080}
* @param {boolean} [fSave]
* @param {boolean} [fShutdown]
* @return {Object|boolean} component state if fSave; otherwise, true if successful, false if failure
*/
CPU.prototype.powerDown = function(fSave, fShutdown)
CPU8080.prototype.powerDown = function(fSave, fShutdown)
{
/*
* The Computer component (which is responsible for all powerDown and powerUp notifications)
@ -305,10 +305,10 @@ CPU.prototype.powerDown = function(fSave, fShutdown)
/**
* autoStart()
*
* @this {CPU}
* @this {CPU8080}
* @return {boolean} true if started, false if not
*/
CPU.prototype.autoStart = function()
CPU8080.prototype.autoStart = function()
{
/*
* Start running automatically on power-up, assuming there's no Debugger and no "Run" button
@ -327,10 +327,10 @@ CPU.prototype.autoStart = function()
/**
* isPowered()
*
* @this {CPU}
* @this {CPU8080}
* @return {boolean}
*/
CPU.prototype.isPowered = function()
CPU8080.prototype.isPowered = function()
{
if (!this.flags.fPowered) {
this.println(this.toString() + " not powered");
@ -342,10 +342,10 @@ CPU.prototype.isPowered = function()
/**
* isRunning()
*
* @this {CPU}
* @this {CPU8080}
* @return {boolean}
*/
CPU.prototype.isRunning = function()
CPU8080.prototype.isRunning = function()
{
return this.flags.fRunning;
};
@ -355,10 +355,10 @@ CPU.prototype.isRunning = function()
*
* This will be implemented by the CPUState component.
*
* @this {CPU}
* @this {CPU8080}
* @return {number} a 32-bit summation of key elements of the current CPU state (used by the CPU checksum code)
*/
CPU.prototype.getChecksum = function()
CPU8080.prototype.getChecksum = function()
{
return 0;
};
@ -370,10 +370,10 @@ CPU.prototype.getChecksum = function()
* cycle counter that will trigger the next displayChecksum(); called by resetCycles(), which is called whenever
* the CPU is reset or restored.
*
* @this {CPU}
* @this {CPU8080}
* @return {boolean} true if checksum generation enabled, false if not
*/
CPU.prototype.resetChecksum = function()
CPU8080.prototype.resetChecksum = function()
{
if (this.aCounts.nCyclesChecksumStart === undefined) this.aCounts.nCyclesChecksumStart = 0;
if (this.aCounts.nCyclesChecksumInterval === undefined) this.aCounts.nCyclesChecksumInterval = -1;
@ -399,10 +399,10 @@ CPU.prototype.resetChecksum = function()
* the exact number cycles that were actually executed. This should give us instruction-granular checksums
* at precise intervals that are 100% repeatable.
*
* @this {CPU}
* @this {CPU8080}
* @param {number} nCycles
*/
CPU.prototype.updateChecksum = function(nCycles)
CPU8080.prototype.updateChecksum = function(nCycles)
{
if (this.flags.fChecksum) {
/*
@ -434,9 +434,9 @@ CPU.prototype.updateChecksum = function(nCycles)
* checksums generated at the specified cycle intervals, as specified by the "csStart" and "csInterval" parmsCPU
* properties).
*
* @this {CPU}
* @this {CPU8080}
*/
CPU.prototype.displayChecksum = function()
CPU8080.prototype.displayChecksum = function()
{
this.println(this.getCycles() + " cycles: " + "checksum=" + str.toHex(this.aCounts.nChecksum));
};
@ -447,12 +447,12 @@ CPU.prototype.displayChecksum = function()
* This is principally for displaying register values, but in reality, it can be used to display any
* numeric (hex) value bound to the given label.
*
* @this {CPU}
* @this {CPU8080}
* @param {string} sLabel
* @param {number} nValue
* @param {number} cch
*/
CPU.prototype.displayValue = function(sLabel, nValue, cch)
CPU8080.prototype.displayValue = function(sLabel, nValue, cch)
{
if (this.bindings[sLabel]) {
if (nValue === undefined) {
@ -478,14 +478,14 @@ CPU.prototype.displayValue = function(sLabel, nValue, cch)
/**
* setBinding(sHTMLType, sBinding, control, sValue)
*
* @this {CPU}
* @this {CPU8080}
* @param {string|null} sHTMLType is the type of the HTML control (eg, "button", "list", "text", "submit", "textarea", "canvas")
* @param {string} sBinding is the value of the 'binding' parameter stored in the HTML control's "data-value" attribute (eg, "run")
* @param {Object} control is the HTML control DOM object (eg, HTMLButtonElement)
* @param {string} [sValue] optional data value
* @return {boolean} true if binding was successful, false if unrecognized binding request
*/
CPU.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
CPU8080.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
{
var cpu = this;
var fBound = false;
@ -544,11 +544,11 @@ CPU.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
* NOTE: In this context, "timer" refers to a timer chip (eg, an Intel 8253) being emulated by
* by the ChipSet component, not the timers managed by the CPU (eg, addTimer(), setTimer(), etc).
*
* @this {CPU}
* @this {CPU8080}
* @param {number} nCycles is the target number of cycles to drop the current burst to
* @return {boolean}
*/
CPU.prototype.setBurstCycles = function(nCycles)
CPU8080.prototype.setBurstCycles = function(nCycles)
{
if (this.flags.fRunning) {
var nDelta = this.nStepCycles - nCycles;
@ -571,11 +571,11 @@ CPU.prototype.setBurstCycles = function(nCycles)
/**
* addCycles(nCycles, fEndStep)
*
* @this {CPU}
* @this {CPU8080}
* @param {number} nCycles
* @param {boolean} [fEndStep]
*/
CPU.prototype.addCycles = function(nCycles, fEndStep)
CPU8080.prototype.addCycles = function(nCycles, fEndStep)
{
this.nTotalCycles += nCycles;
if (fEndStep) {
@ -589,9 +589,9 @@ CPU.prototype.addCycles = function(nCycles, fEndStep)
* Calculate the number of cycles to process for each "burst" of CPU activity. The size of a burst
* is driven by the following values:
*
* CPU.YIELDS_PER_SECOND (eg, 30)
* CPU.VIDEO_UPDATES_PER_SECOND (eg, 60)
* CPU.STATUS_UPDATES_PER_SECOND (eg, 5)
* CPU8080.YIELDS_PER_SECOND (eg, 30)
* CPU8080.VIDEO_UPDATES_PER_SECOND (eg, 60)
* CPU8080.STATUS_UPDATES_PER_SECOND (eg, 5)
*
* The largest of the above values forces the size of the burst to its smallest value. Let's say that
* largest value is 30. Assuming nCyclesPerSecond is 1,000,000, that results in bursts of 33,333 cycles.
@ -604,18 +604,18 @@ CPU.prototype.addCycles = function(nCycles, fEndStep)
* Similarly, whenever the "next video update" cycle counter goes to (or below) zero, we call updateVideo(),
* and whenever the "next status update" cycle counter goes to (or below) zero, we call updateStatus().
*
* @this {CPU}
* @this {CPU8080}
* @param {boolean} [fRecalc] is true if the caller wants to recalculate thresholds based on the most recent
* speed calculation (see calcSpeed).
*/
CPU.prototype.calcCycles = function(fRecalc)
CPU8080.prototype.calcCycles = function(fRecalc)
{
/*
* Calculate the most cycles we're allowed to execute in a single "burst"
*/
var nMostUpdatesPerSecond = CPU.YIELDS_PER_SECOND;
var nMostUpdatesPerSecond = CPU8080.YIELDS_PER_SECOND;
if (nMostUpdatesPerSecond < this.refreshRate) nMostUpdatesPerSecond = this.refreshRate;
if (nMostUpdatesPerSecond < CPU.STATUS_UPDATES_PER_SECOND) nMostUpdatesPerSecond = CPU.STATUS_UPDATES_PER_SECOND;
if (nMostUpdatesPerSecond < CPU8080.STATUS_UPDATES_PER_SECOND) nMostUpdatesPerSecond = CPU8080.STATUS_UPDATES_PER_SECOND;
/*
* Calculate cycle "per" values for the yield, video update, and status update cycle counters
@ -627,11 +627,11 @@ CPU.prototype.calcCycles = function(fRecalc)
}
}
this.aCounts.msPerYield = Math.round(1000 / CPU.YIELDS_PER_SECOND);
this.aCounts.msPerYield = Math.round(1000 / CPU8080.YIELDS_PER_SECOND);
this.aCounts.nCyclesPerBurst = Math.floor(this.aCounts.nCyclesPerSecond / nMostUpdatesPerSecond * vMultiplier);
this.aCounts.nCyclesPerYield = Math.floor(this.aCounts.nCyclesPerSecond / CPU.YIELDS_PER_SECOND * vMultiplier);
this.aCounts.nCyclesPerYield = Math.floor(this.aCounts.nCyclesPerSecond / CPU8080.YIELDS_PER_SECOND * vMultiplier);
this.aCounts.nCyclesPerVideoUpdate = Math.floor(this.aCounts.nCyclesPerSecond / this.refreshRate * vMultiplier);
this.aCounts.nCyclesPerStatusUpdate = Math.floor(this.aCounts.nCyclesPerSecond / CPU.STATUS_UPDATES_PER_SECOND * vMultiplier);
this.aCounts.nCyclesPerStatusUpdate = Math.floor(this.aCounts.nCyclesPerSecond / CPU8080.STATUS_UPDATES_PER_SECOND * vMultiplier);
/*
* And initialize "next" yield, video update, and status update cycle "threshold" counters to those "per" values
@ -657,11 +657,11 @@ CPU.prototype.calcCycles = function(fRecalc)
* nTotalCycles eventually get reset by calcSpeed(), to avoid overflow, so components that rely on
* getCycles() returning steadily increasing values should also be prepared for a reset at any time.
*
* @this {CPU}
* @this {CPU8080}
* @param {boolean} [fScaled] is true if the caller wants a cycle count relative to a multiplier of 1
* @return {number}
*/
CPU.prototype.getCycles = function(fScaled)
CPU8080.prototype.getCycles = function(fScaled)
{
var nCycles = this.nTotalCycles + this.nRunCycles + this.nBurstCycles - this.nStepCycles;
if (fScaled && this.aCounts.nCyclesMultiplier > 1 && this.aCounts.mhz > this.aCounts.mhzDefault) {
@ -693,10 +693,10 @@ CPU.prototype.getCycles = function(fScaled)
*
* This returns the CPU's "base" speed (ie, the original cycles per second defined for the machine)
*
* @this {CPU}
* @this {CPU8080}
* @return {number}
*/
CPU.prototype.getCyclesPerSecond = function()
CPU8080.prototype.getCyclesPerSecond = function()
{
return this.aCounts.nCyclesPerSecond;
};
@ -708,9 +708,9 @@ CPU.prototype.getCyclesPerSecond = function()
* It's important that this be called BEFORE the actual restore() call, because restore() may want to call setSpeed(),
* which in turn assumes that all the cycle counts have been initialized to sensible values.
*
* @this {CPU}
* @this {CPU8080}
*/
CPU.prototype.resetCycles = function()
CPU8080.prototype.resetCycles = function()
{
this.aCounts.mhz = 0;
this.nTotalCycles = this.nRunCycles = this.nBurstCycles = this.nStepCycles = 0;
@ -721,10 +721,10 @@ CPU.prototype.resetCycles = function()
/**
* getSpeed()
*
* @this {CPU}
* @this {CPU8080}
* @return {number} the current speed multiplier
*/
CPU.prototype.getSpeed = function()
CPU8080.prototype.getSpeed = function()
{
return this.aCounts.nCyclesMultiplier;
};
@ -732,10 +732,10 @@ CPU.prototype.getSpeed = function()
/**
* getSpeedCurrent()
*
* @this {CPU}
* @this {CPU8080}
* @return {string} the current speed, in mhz, as a string formatted to two decimal places
*/
CPU.prototype.getSpeedCurrent = function()
CPU8080.prototype.getSpeedCurrent = function()
{
/*
* TODO: Has toFixed() been "fixed" in all browsers (eg, IE) to return a rounded value now?
@ -746,10 +746,10 @@ CPU.prototype.getSpeedCurrent = function()
/**
* getSpeedTarget()
*
* @this {CPU}
* @this {CPU8080}
* @return {string} the target speed, in mhz, as a string formatted to two decimal places
*/
CPU.prototype.getSpeedTarget = function()
CPU8080.prototype.getSpeedTarget = function()
{
/*
* TODO: Has toFixed() been "fixed" in all browsers (eg, IE) to return a rounded value now?
@ -766,12 +766,12 @@ CPU.prototype.getSpeedTarget = function()
* so that the next effective speed calculation obtains sensible results. In fact, when runCPU() initially calls
* setSpeed() with no parameters, that's all this function does (it doesn't change the current speed setting).
*
* @this {CPU}
* @this {CPU8080}
* @param {number} [nMultiplier] is the new proposed multiplier (reverts to 1 if the target was too high)
* @param {boolean} [fUpdateFocus] is true to update Computer focus
* @return {boolean} true if successful, false if not
*/
CPU.prototype.setSpeed = function(nMultiplier, fUpdateFocus)
CPU8080.prototype.setSpeed = function(nMultiplier, fUpdateFocus)
{
var fSuccess = false;
if (nMultiplier !== undefined) {
@ -805,11 +805,11 @@ CPU.prototype.setSpeed = function(nMultiplier, fUpdateFocus)
/**
* calcSpeed(nCycles, msElapsed)
*
* @this {CPU}
* @this {CPU8080}
* @param {number} nCycles
* @param {number} msElapsed
*/
CPU.prototype.calcSpeed = function(nCycles, msElapsed)
CPU8080.prototype.calcSpeed = function(nCycles, msElapsed)
{
if (msElapsed) {
this.aCounts.mhz = Math.round(nCycles / (msElapsed * 10)) / 100;
@ -823,9 +823,9 @@ CPU.prototype.calcSpeed = function(nCycles, msElapsed)
/**
* calcStartTime()
*
* @this {CPU}
* @this {CPU8080}
*/
CPU.prototype.calcStartTime = function()
CPU8080.prototype.calcStartTime = function()
{
if (this.aCounts.nCyclesRecalc >= this.aCounts.nCyclesPerSecond) {
this.calcCycles(true);
@ -879,10 +879,10 @@ CPU.prototype.calcStartTime = function()
/**
* calcRemainingTime()
*
* @this {CPU}
* @this {CPU8080}
* @return {number}
*/
CPU.prototype.calcRemainingTime = function()
CPU8080.prototype.calcRemainingTime = function()
{
this.aCounts.msEndThisRun = usr.getTime();
@ -939,7 +939,7 @@ CPU.prototype.calcRemainingTime = function()
*/
this.aCounts.nCyclesRecalc += this.aCounts.nCyclesThisRun;
if (DEBUG && this.messageEnabled(Messages.LOG) && msRemainsThisRun) {
if (DEBUG && this.messageEnabled(Messages8080.LOG) && msRemainsThisRun) {
this.log("calcRemainingTime: " + msRemainsThisRun + "ms to sleep after " + this.aCounts.msEndThisRun + "ms");
}
@ -960,11 +960,11 @@ CPU.prototype.calcRemainingTime = function()
*
* Why not use JavaScript's setTimeout() instead? Good question. For a good answer, see setTimer() below.
*
* @this {CPU}
* @this {CPU8080}
* @param {function()} callBack
* @return {number} timer index
*/
CPU.prototype.addTimer = function(callBack)
CPU8080.prototype.addTimer = function(callBack)
{
var iTimer = this.aTimers.length;
this.aTimers.push([-1, callBack]);
@ -986,12 +986,12 @@ CPU.prototype.addTimer = function(callBack)
* use setTimer(); however, due to legacy code (ie, code that predates these functions) and/or laziness,
* that's currently not the case. TODO: Fix.
*
* @this {CPU}
* @this {CPU8080}
* @param {number} iTimer
* @param {number} ms (converted into a cycle countdown internally)
* @return {number} (number of cycles used to arm timer, or -1 if error)
*/
CPU.prototype.setTimer = function(iTimer, ms)
CPU8080.prototype.setTimer = function(iTimer, ms)
{
var nCycles = -1;
if (iTimer >= 0 && iTimer < this.aTimers.length) {
@ -1006,11 +1006,11 @@ CPU.prototype.setTimer = function(iTimer, ms)
*
* Used by runCPU() to either accept or shorten the current burst if any timers need to fire soon.
*
* @this {CPU}
* @this {CPU8080}
* @param {number} nCycles (number of cycles about to execute)
* @return {number} (either nCycles or less if a timer needs to fire)
*/
CPU.prototype.getTimerBurst = function(nCycles)
CPU8080.prototype.getTimerBurst = function(nCycles)
{
for (var i = 0; i < this.aTimers.length; i++) {
var timer = this.aTimers[i];
@ -1029,10 +1029,10 @@ CPU.prototype.getTimerBurst = function(nCycles)
* this is the function that actually "fires" any timer(s) whose countdown has reached (or dropped below)
* zero, invoking their callback function.
*
* @this {CPU}
* @this {CPU8080}
* @param {number} nCycles (number of cycles actually executed)
*/
CPU.prototype.updateTimers = function(nCycles)
CPU8080.prototype.updateTimers = function(nCycles)
{
for (var i = 0; i < this.aTimers.length; i++) {
var timer = this.aTimers[i];
@ -1048,10 +1048,10 @@ CPU.prototype.updateTimers = function(nCycles)
/**
* runCPU(fUpdateFocus)
*
* @this {CPU}
* @this {CPU8080}
* @param {boolean} [fUpdateFocus] is true to update Computer focus
*/
CPU.prototype.runCPU = function(fUpdateFocus)
CPU8080.prototype.runCPU = function(fUpdateFocus)
{
if (!this.setBusy(true)) {
this.updateCPU();
@ -1140,7 +1140,7 @@ CPU.prototype.runCPU = function(fUpdateFocus)
*
* @param {boolean} [fUpdateFocus]
*/
CPU.prototype.startCPU = function(fUpdateFocus)
CPU8080.prototype.startCPU = function(fUpdateFocus)
{
if (!this.flags.fRunning) {
/*
@ -1168,11 +1168,11 @@ CPU.prototype.startCPU = function(fUpdateFocus)
*
* This will be implemented by the CPUState component.
*
* @this {CPU}
* @this {CPU8080}
* @param {number} nMinCycles (0 implies a single-step, and therefore breakpoints should be ignored)
* @return {number} of cycles executed; 0 indicates that the last instruction was not executed
*/
CPU.prototype.stepCPU = function(nMinCycles)
CPU8080.prototype.stepCPU = function(nMinCycles)
{
return 0;
};
@ -1185,10 +1185,10 @@ CPU.prototype.stepCPU = function(nMinCycles)
* This similar to yieldCPU(), but it doesn't need to zero nCyclesNextYield to break out of runCPU();
* it simply needs to clear fRunning (well, "simply" may be oversimplifying a bit....)
*
* @this {CPU}
* @this {CPU8080}
* @param {boolean} [fComplete]
*/
CPU.prototype.stopCPU = function(fComplete)
CPU8080.prototype.stopCPU = function(fComplete)
{
this.isBusy(true);
this.nBurstCycles -= this.nStepCycles;
@ -1212,10 +1212,10 @@ CPU.prototype.stopCPU = function(fComplete)
* other callers of stepCPU(), such as the Debugger, the combination of stepCPU() + updateCPU()
* provides the old behavior.
*
* @this {CPU}
* @this {CPU8080}
* @param {boolean} [fForce] (true to force a video update; used by the Debugger)
*/
CPU.prototype.updateCPU = function(fForce)
CPU8080.prototype.updateCPU = function(fForce)
{
if (this.cmp) {
this.cmp.updateVideo(-1);
@ -1229,9 +1229,9 @@ CPU.prototype.updateCPU = function(fForce)
* Similar to stopCPU() with regard to how it resets various cycle countdown values, but the CPU
* remains in a "running" state.
*
* @this {CPU}
* @this {CPU8080}
*/
CPU.prototype.yieldCPU = function()
CPU8080.prototype.yieldCPU = function()
{
this.aCounts.nCyclesNextYield = 0; // this will break us out of runCPU(), once we break out of stepCPU()
this.nBurstCycles -= this.nStepCycles;
@ -1245,4 +1245,4 @@ CPU.prototype.yieldCPU = function()
this.updateCPU();
};
if (NODE) module.exports = CPU;
if (NODE) module.exports = CPU8080;

View file

@ -31,7 +31,7 @@
"use strict";
var CPUDef = {
var CPUDef8080 = {
/*
* CPU model numbers (supported)
*/
@ -114,17 +114,17 @@ var CPUDef = {
* These are the internal PS bits (outside of PS.MASK) that getPS() and setPS() can get and set,
* but which cannot be seen with any of the documented instructions.
*/
CPUDef.PS.INTERNAL = (CPUDef.PS.IF);
CPUDef8080.PS.INTERNAL = (CPUDef8080.PS.IF);
/*
* PS "arithmetic" flags are NOT stored in regPS; they are maintained across separate result registers,
* hence the RESULT designation.
*/
CPUDef.PS.RESULT = (CPUDef.PS.CF | CPUDef.PS.PF | CPUDef.PS.AF | CPUDef.PS.ZF | CPUDef.PS.SF);
CPUDef8080.PS.RESULT = (CPUDef8080.PS.CF | CPUDef8080.PS.PF | CPUDef8080.PS.AF | CPUDef8080.PS.ZF | CPUDef8080.PS.SF);
/*
* These are the "always set" PS bits for the 8080.
*/
CPUDef.PS.SET = (CPUDef.PS.BIT1);
CPUDef8080.PS.SET = (CPUDef8080.PS.BIT1);
if (NODE) module.exports = CPUDef;
if (NODE) module.exports = CPUDef8080;

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -68,7 +68,7 @@ var BYTEARRAYS = false;
/**
* TYPEDARRAYS enables use of typed arrays for Memory blocks. This used to be a compile-time-only option, but I've
* added Memory access functions for typed arrays (see Memory.afnTypedArray), so support can be enabled dynamically now.
* added Memory access functions for typed arrays (see Memory8080.afnTypedArray), so support can be enabled dynamically now.
*
* See the Memory component for details.
*/

View file

@ -35,39 +35,39 @@ if (NODE) {
var str = require("../../shared/lib/strlib");
var web = require("../../shared/lib/weblib");
var Component = require("../../shared/lib/component");
var Messages = require("./messages");
var ChipSet = require("./chipset");
var ChipSet8080 = require("./chipset");
var Messages8080= require("./messages");
}
/**
* Keyboard(parmsKbd)
* Keyboard8080(parmsKbd)
*
* The Keyboard component has the following component-specific (parmsKbd) properties:
* The Keyboard8080 component has the following component-specific (parmsKbd) properties:
*
* model: eg, "VT100" (should be a member of Keyboard.MODELS)
* model: eg, "VT100" (should be a member of Keyboard8080.MODELS)
*
* @constructor
* @extends Component
* @param {Object} parmsKbd
*/
function Keyboard(parmsKbd)
function Keyboard8080(parmsKbd)
{
Component.call(this, "Keyboard", parmsKbd, Keyboard, Messages.KEYBOARD);
Component.call(this, "Keyboard", parmsKbd, Keyboard8080, Messages8080.KEYBOARD);
var model = parmsKbd['model'];
if (model && !Keyboard.MODELS[model]) {
Component.notice("Unrecognized Keyboard model: " + model);
if (model && !Keyboard8080.MODELS[model]) {
Component.notice("Unrecognized Keyboard8080 model: " + model);
}
this.config = Keyboard.MODELS[model] || {};
this.config = Keyboard8080.MODELS[model] || {};
this.reset();
this.setReady();
}
Component.subclass(Keyboard);
Component.subclass(Keyboard8080);
/**
* Alphanumeric and other common (printable) ASCII codes.
@ -78,7 +78,7 @@ Component.subclass(Keyboard);
*
* @enum {number}
*/
Keyboard.ASCII = {
Keyboard8080.ASCII = {
CTRL_A: 1, CTRL_C: 3, CTRL_Z: 26,
' ': 32, '!': 33, '"': 34, '#': 35, '$': 36, '%': 37, '&': 38, "'": 39,
'(': 40, ')': 41, '*': 42, '+': 43, ',': 44, '-': 45, '.': 46, '/': 47,
@ -106,7 +106,7 @@ Keyboard.ASCII = {
*
* @enum {number}
*/
Keyboard.KEYCODE = {
Keyboard8080.KEYCODE = {
/* 0x08 */ BS: 8,
/* 0x09 */ TAB: 9,
/* 0x0A */ LF: 10, // TODO: Determine if any key actually generates this (I suspect there is none)
@ -227,26 +227,26 @@ Keyboard.KEYCODE = {
/*
* Check the event object's 'location' property for a non-zero value for the following ONRIGHT keys.
*/
Keyboard.KEYCODE.NUM_CR = Keyboard.KEYCODE.CR + Keyboard.KEYCODE.ONRIGHT;
Keyboard8080.KEYCODE.NUM_CR = Keyboard8080.KEYCODE.CR + Keyboard8080.KEYCODE.ONRIGHT;
/*
* Maps "stupid" keyCodes to their "non-stupid" counterparts
*/
Keyboard.STUPID_KEYCODES = {};
Keyboard.STUPID_KEYCODES[Keyboard.KEYCODE.SEMI] = Keyboard.ASCII[';']; // 186 -> 59
Keyboard.STUPID_KEYCODES[Keyboard.KEYCODE.EQUALS] = Keyboard.ASCII['=']; // 187 -> 61
Keyboard.STUPID_KEYCODES[Keyboard.KEYCODE.COMMA] = Keyboard.ASCII[',']; // 188 -> 44
Keyboard.STUPID_KEYCODES[Keyboard.KEYCODE.DASH] = Keyboard.ASCII['-']; // 189 -> 45
Keyboard.STUPID_KEYCODES[Keyboard.KEYCODE.PERIOD] = Keyboard.ASCII['.']; // 190 -> 46
Keyboard.STUPID_KEYCODES[Keyboard.KEYCODE.SLASH] = Keyboard.ASCII['/']; // 191 -> 47
Keyboard.STUPID_KEYCODES[Keyboard.KEYCODE.BQUOTE] = Keyboard.ASCII['`']; // 192 -> 96
Keyboard.STUPID_KEYCODES[Keyboard.KEYCODE.LBRACK] = Keyboard.ASCII['[']; // 219 -> 91
Keyboard.STUPID_KEYCODES[Keyboard.KEYCODE.BSLASH] = Keyboard.ASCII['\\']; // 220 -> 92
Keyboard.STUPID_KEYCODES[Keyboard.KEYCODE.RBRACK] = Keyboard.ASCII[']']; // 221 -> 93
Keyboard.STUPID_KEYCODES[Keyboard.KEYCODE.QUOTE] = Keyboard.ASCII["'"]; // 222 -> 39
Keyboard.STUPID_KEYCODES[Keyboard.KEYCODE.FF_DASH] = Keyboard.ASCII['-'];
Keyboard8080.STUPID_KEYCODES = {};
Keyboard8080.STUPID_KEYCODES[Keyboard8080.KEYCODE.SEMI] = Keyboard8080.ASCII[';']; // 186 -> 59
Keyboard8080.STUPID_KEYCODES[Keyboard8080.KEYCODE.EQUALS] = Keyboard8080.ASCII['=']; // 187 -> 61
Keyboard8080.STUPID_KEYCODES[Keyboard8080.KEYCODE.COMMA] = Keyboard8080.ASCII[',']; // 188 -> 44
Keyboard8080.STUPID_KEYCODES[Keyboard8080.KEYCODE.DASH] = Keyboard8080.ASCII['-']; // 189 -> 45
Keyboard8080.STUPID_KEYCODES[Keyboard8080.KEYCODE.PERIOD] = Keyboard8080.ASCII['.']; // 190 -> 46
Keyboard8080.STUPID_KEYCODES[Keyboard8080.KEYCODE.SLASH] = Keyboard8080.ASCII['/']; // 191 -> 47
Keyboard8080.STUPID_KEYCODES[Keyboard8080.KEYCODE.BQUOTE] = Keyboard8080.ASCII['`']; // 192 -> 96
Keyboard8080.STUPID_KEYCODES[Keyboard8080.KEYCODE.LBRACK] = Keyboard8080.ASCII['[']; // 219 -> 91
Keyboard8080.STUPID_KEYCODES[Keyboard8080.KEYCODE.BSLASH] = Keyboard8080.ASCII['\\']; // 220 -> 92
Keyboard8080.STUPID_KEYCODES[Keyboard8080.KEYCODE.RBRACK] = Keyboard8080.ASCII[']']; // 221 -> 93
Keyboard8080.STUPID_KEYCODES[Keyboard8080.KEYCODE.QUOTE] = Keyboard8080.ASCII["'"]; // 222 -> 39
Keyboard8080.STUPID_KEYCODES[Keyboard8080.KEYCODE.FF_DASH] = Keyboard8080.ASCII['-'];
Keyboard.MINPRESSTIME = 100; // 100ms
Keyboard8080.MINPRESSTIME = 100; // 100ms
/**
* Alternate keyCode mappings to support popular "WASD"-style directional-key mappings.
@ -254,36 +254,36 @@ Keyboard.MINPRESSTIME = 100; // 100ms
* TODO: ES6 computed property name support may now be in all mainstream browsers, allowing us to use
* a simple object literal for this and all other object initializations.
*/
Keyboard.WASDCODES = {};
Keyboard.WASDCODES[Keyboard.ASCII.A] = Keyboard.KEYCODE.LEFT;
Keyboard.WASDCODES[Keyboard.ASCII.D] = Keyboard.KEYCODE.RIGHT;
Keyboard.WASDCODES[Keyboard.ASCII.L] = Keyboard.KEYCODE.SPACE;
Keyboard8080.WASDCODES = {};
Keyboard8080.WASDCODES[Keyboard8080.ASCII.A] = Keyboard8080.KEYCODE.LEFT;
Keyboard8080.WASDCODES[Keyboard8080.ASCII.D] = Keyboard8080.KEYCODE.RIGHT;
Keyboard8080.WASDCODES[Keyboard8080.ASCII.L] = Keyboard8080.KEYCODE.SPACE;
/*
* Supported configurations
*/
Keyboard.SI1978 = {
Keyboard8080.SI1978 = {
MODEL: 1978.1,
KEYMAP: {},
ALTCODES: Keyboard.WASDCODES,
ALTCODES: Keyboard8080.WASDCODES,
LEDCODES: {},
SOFTCODES: {
'1p': Keyboard.KEYCODE.ONE,
'2p': Keyboard.KEYCODE.TWO,
'coin': Keyboard.KEYCODE.THREE,
'left': Keyboard.KEYCODE.LEFT,
'right': Keyboard.KEYCODE.RIGHT,
'fire': Keyboard.KEYCODE.SPACE
'1p': Keyboard8080.KEYCODE.ONE,
'2p': Keyboard8080.KEYCODE.TWO,
'coin': Keyboard8080.KEYCODE.THREE,
'left': Keyboard8080.KEYCODE.LEFT,
'right': Keyboard8080.KEYCODE.RIGHT,
'fire': Keyboard8080.KEYCODE.SPACE
}
};
Keyboard.VT100 = {
Keyboard8080.VT100 = {
MODEL: 100.0,
KEYMAP: {},
ALTCODES: {},
LEDCODES: {},
SOFTCODES: {
'setup': Keyboard.KEYCODE.F9
'setup': Keyboard8080.KEYCODE.F9
},
/*
* Reading port 0x82 returns a key address from the VT100 keyboard's UART data output.
@ -328,119 +328,119 @@ Keyboard.VT100 = {
/*
* Table to map host key codes to VT100 key addresses (ie, unique 7-bit values representing key positions on the VT100)
*/
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.DEL] = 0x03;
Keyboard.VT100.KEYMAP[Keyboard.ASCII.P] = 0x05;
Keyboard.VT100.KEYMAP[Keyboard.ASCII.O] = 0x06;
Keyboard.VT100.KEYMAP[Keyboard.ASCII.Y] = 0x07;
Keyboard.VT100.KEYMAP[Keyboard.ASCII.T] = 0x08;
Keyboard.VT100.KEYMAP[Keyboard.ASCII.W] = 0x09;
Keyboard.VT100.KEYMAP[Keyboard.ASCII.Q] = 0x0A;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.RIGHT] = 0x10;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.RBRACK] = 0x14;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.LBRACK] = 0x15;
Keyboard.VT100.KEYMAP[Keyboard.ASCII.I] = 0x16;
Keyboard.VT100.KEYMAP[Keyboard.ASCII.U] = 0x17;
Keyboard.VT100.KEYMAP[Keyboard.ASCII.R] = 0x18;
Keyboard.VT100.KEYMAP[Keyboard.ASCII.E] = 0x19;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.ONE] = 0x1A;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.LEFT] = 0x20;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.DOWN] = 0x22;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.F6] = 0x23; // aka BREAK
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.PAUSE] = 0x23; // aka BREAK
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.BQUOTE] = 0x24;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.DASH] = 0x25;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.NINE] = 0x26;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.SEVEN] = 0x27;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.FOUR] = 0x28;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.THREE] = 0x29;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.ESC] = 0x2A;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.UP] = 0x30;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.F3] = 0x31; // aka PF3
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.F1] = 0x32; // aka PF1
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.BS] = 0x33;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.EQUALS] = 0x34;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.ZERO] = 0x35;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.EIGHT] = 0x36;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.SIX] = 0x37;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.FIVE] = 0x38;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.TWO] = 0x39;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.TAB] = 0x3A;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.NUM_7] = 0x40;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.F4] = 0x41; // aka PF4
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.F2] = 0x42; // aka PF2
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.NUM_0] = 0x43;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.F7] = 0x44; // aka LINE FEED
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.BSLASH] = 0x45;
Keyboard.VT100.KEYMAP[Keyboard.ASCII.L] = 0x46;
Keyboard.VT100.KEYMAP[Keyboard.ASCII.K] = 0x47;
Keyboard.VT100.KEYMAP[Keyboard.ASCII.G] = 0x48;
Keyboard.VT100.KEYMAP[Keyboard.ASCII.F] = 0x49;
Keyboard.VT100.KEYMAP[Keyboard.ASCII.A] = 0x4A;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.NUM_8] = 0x50;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.NUM_CR] = 0x51;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.NUM_2] = 0x52;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.NUM_1] = 0x53;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.QUOTE] = 0x55;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.SEMI] = 0x56;
Keyboard.VT100.KEYMAP[Keyboard.ASCII.J] = 0x57;
Keyboard.VT100.KEYMAP[Keyboard.ASCII.H] = 0x58;
Keyboard.VT100.KEYMAP[Keyboard.ASCII.D] = 0x59;
Keyboard.VT100.KEYMAP[Keyboard.ASCII.S] = 0x5A;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.NUM_DEL] = 0x60; // keypad period
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.F5] = 0x61; // aka KEYPAD COMMA
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.NUM_5] = 0x62;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.NUM_4] = 0x63;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.CR] = 0x64; // TODO: Figure out why the Technical Manual lists CR at both 0x04 and 0x64
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.PERIOD] = 0x65;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.COMMA] = 0x66;
Keyboard.VT100.KEYMAP[Keyboard.ASCII.N] = 0x67;
Keyboard.VT100.KEYMAP[Keyboard.ASCII.B] = 0x68;
Keyboard.VT100.KEYMAP[Keyboard.ASCII.X] = 0x69;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.F8] = 0x6A; // aka NO SCROLL
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.NUM_9] = 0x70;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.NUM_3] = 0x71;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.NUM_6] = 0x72;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.NUM_SUB] = 0x73; // aka KEYPAD MINUS
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.SLASH] = 0x75;
Keyboard.VT100.KEYMAP[Keyboard.ASCII.M] = 0x76;
Keyboard.VT100.KEYMAP[Keyboard.ASCII[' ']] = 0x77;
Keyboard.VT100.KEYMAP[Keyboard.ASCII.V] = 0x78;
Keyboard.VT100.KEYMAP[Keyboard.ASCII.C] = 0x79;
Keyboard.VT100.KEYMAP[Keyboard.ASCII.Z] = 0x7A;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.F9] = 0x7B; // aka SET-UP
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.CTRL] = 0x7C;
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.SHIFT] = 0x7D; // either shift key (doesn't matter)
Keyboard.VT100.KEYMAP[Keyboard.KEYCODE.CAPSLOCK]= 0x7E;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.DEL] = 0x03;
Keyboard8080.VT100.KEYMAP[Keyboard8080.ASCII.P] = 0x05;
Keyboard8080.VT100.KEYMAP[Keyboard8080.ASCII.O] = 0x06;
Keyboard8080.VT100.KEYMAP[Keyboard8080.ASCII.Y] = 0x07;
Keyboard8080.VT100.KEYMAP[Keyboard8080.ASCII.T] = 0x08;
Keyboard8080.VT100.KEYMAP[Keyboard8080.ASCII.W] = 0x09;
Keyboard8080.VT100.KEYMAP[Keyboard8080.ASCII.Q] = 0x0A;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.RIGHT] = 0x10;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.RBRACK] = 0x14;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.LBRACK] = 0x15;
Keyboard8080.VT100.KEYMAP[Keyboard8080.ASCII.I] = 0x16;
Keyboard8080.VT100.KEYMAP[Keyboard8080.ASCII.U] = 0x17;
Keyboard8080.VT100.KEYMAP[Keyboard8080.ASCII.R] = 0x18;
Keyboard8080.VT100.KEYMAP[Keyboard8080.ASCII.E] = 0x19;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.ONE] = 0x1A;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.LEFT] = 0x20;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.DOWN] = 0x22;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.F6] = 0x23; // aka BREAK
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.PAUSE] = 0x23; // aka BREAK
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.BQUOTE] = 0x24;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.DASH] = 0x25;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.NINE] = 0x26;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.SEVEN] = 0x27;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.FOUR] = 0x28;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.THREE] = 0x29;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.ESC] = 0x2A;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.UP] = 0x30;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.F3] = 0x31; // aka PF3
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.F1] = 0x32; // aka PF1
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.BS] = 0x33;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.EQUALS] = 0x34;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.ZERO] = 0x35;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.EIGHT] = 0x36;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.SIX] = 0x37;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.FIVE] = 0x38;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.TWO] = 0x39;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.TAB] = 0x3A;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.NUM_7] = 0x40;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.F4] = 0x41; // aka PF4
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.F2] = 0x42; // aka PF2
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.NUM_0] = 0x43;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.F7] = 0x44; // aka LINE FEED
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.BSLASH] = 0x45;
Keyboard8080.VT100.KEYMAP[Keyboard8080.ASCII.L] = 0x46;
Keyboard8080.VT100.KEYMAP[Keyboard8080.ASCII.K] = 0x47;
Keyboard8080.VT100.KEYMAP[Keyboard8080.ASCII.G] = 0x48;
Keyboard8080.VT100.KEYMAP[Keyboard8080.ASCII.F] = 0x49;
Keyboard8080.VT100.KEYMAP[Keyboard8080.ASCII.A] = 0x4A;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.NUM_8] = 0x50;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.NUM_CR] = 0x51;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.NUM_2] = 0x52;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.NUM_1] = 0x53;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.QUOTE] = 0x55;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.SEMI] = 0x56;
Keyboard8080.VT100.KEYMAP[Keyboard8080.ASCII.J] = 0x57;
Keyboard8080.VT100.KEYMAP[Keyboard8080.ASCII.H] = 0x58;
Keyboard8080.VT100.KEYMAP[Keyboard8080.ASCII.D] = 0x59;
Keyboard8080.VT100.KEYMAP[Keyboard8080.ASCII.S] = 0x5A;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.NUM_DEL] = 0x60; // keypad period
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.F5] = 0x61; // aka KEYPAD COMMA
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.NUM_5] = 0x62;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.NUM_4] = 0x63;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.CR] = 0x64; // TODO: Figure out why the Technical Manual lists CR at both 0x04 and 0x64
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.PERIOD] = 0x65;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.COMMA] = 0x66;
Keyboard8080.VT100.KEYMAP[Keyboard8080.ASCII.N] = 0x67;
Keyboard8080.VT100.KEYMAP[Keyboard8080.ASCII.B] = 0x68;
Keyboard8080.VT100.KEYMAP[Keyboard8080.ASCII.X] = 0x69;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.F8] = 0x6A; // aka NO SCROLL
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.NUM_9] = 0x70;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.NUM_3] = 0x71;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.NUM_6] = 0x72;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.NUM_SUB] = 0x73; // aka KEYPAD MINUS
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.SLASH] = 0x75;
Keyboard8080.VT100.KEYMAP[Keyboard8080.ASCII.M] = 0x76;
Keyboard8080.VT100.KEYMAP[Keyboard8080.ASCII[' ']] = 0x77;
Keyboard8080.VT100.KEYMAP[Keyboard8080.ASCII.V] = 0x78;
Keyboard8080.VT100.KEYMAP[Keyboard8080.ASCII.C] = 0x79;
Keyboard8080.VT100.KEYMAP[Keyboard8080.ASCII.Z] = 0x7A;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.F9] = 0x7B; // aka SET-UP
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.CTRL] = 0x7C;
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.SHIFT] = 0x7D; // either shift key (doesn't matter)
Keyboard8080.VT100.KEYMAP[Keyboard8080.KEYCODE.CAPSLOCK]= 0x7E;
Keyboard.VT100.LEDCODES = {
'l4': Keyboard.VT100.STATUS.LED4,
'l3': Keyboard.VT100.STATUS.LED3,
'l2': Keyboard.VT100.STATUS.LED2,
'l1': Keyboard.VT100.STATUS.LED1,
'locked': Keyboard.VT100.STATUS.LOCKED,
'local': Keyboard.VT100.STATUS.LOCAL,
'online': ~Keyboard.VT100.STATUS.LOCAL
Keyboard8080.VT100.LEDCODES = {
'l4': Keyboard8080.VT100.STATUS.LED4,
'l3': Keyboard8080.VT100.STATUS.LED3,
'l2': Keyboard8080.VT100.STATUS.LED2,
'l1': Keyboard8080.VT100.STATUS.LED1,
'locked': Keyboard8080.VT100.STATUS.LOCKED,
'local': Keyboard8080.VT100.STATUS.LOCAL,
'online': ~Keyboard8080.VT100.STATUS.LOCAL
};
/*
* Supported models and their configurations
*/
Keyboard.MODELS = {
"SI1978": Keyboard.SI1978,
"VT100": Keyboard.VT100
Keyboard8080.MODELS = {
"SI1978": Keyboard8080.SI1978,
"VT100": Keyboard8080.VT100
};
/**
* setBinding(sHTMLType, sBinding, control, sValue)
*
* @this {Keyboard}
* @this {Keyboard8080}
* @param {string|null} sHTMLType is the type of the HTML control (eg, "button", "list", "text", "submit", "textarea", "canvas")
* @param {string} sBinding is the value of the 'binding' parameter stored in the HTML control's "data-value" attribute (eg, "esc")
* @param {Object} control is the HTML control DOM object (eg, HTMLButtonElement)
* @param {string} [sValue] optional data value
* @return {boolean} true if binding was successful, false if unrecognized binding request
*/
Keyboard.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
Keyboard8080.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
{
/*
* There's a special binding that the Video component uses ("kbd") to effectively bind its
@ -528,18 +528,18 @@ Keyboard.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
/**
* initBus(cmp, bus, cpu, dbg)
*
* @this {Keyboard}
* @param {Computer} cmp
* @param {Bus} bus
* @param {CPUState} cpu
* @param {Debugger} dbg
* @this {Keyboard8080}
* @param {Computer8080} cmp
* @param {Bus8080} bus
* @param {CPUState8080} cpu
* @param {Debugger8080} dbg
*/
Keyboard.prototype.initBus = function(cmp, bus, cpu, dbg)
Keyboard8080.prototype.initBus = function(cmp, bus, cpu, dbg)
{
this.cmp = cmp;
this.cpu = cpu;
this.dbg = dbg; // NOTE: The "dbg" property must be set for the message functions to work
this.chipset = /** @type {ChipSet} */ (cmp.getMachineComponent("ChipSet"));
this.chipset = /** @type {ChipSet8080} */ (cmp.getMachineComponent("ChipSet"));
bus.addPortInputTable(this, this.config.portsInput);
bus.addPortOutputTable(this, this.config.portsOutput);
};
@ -547,12 +547,12 @@ Keyboard.prototype.initBus = function(cmp, bus, cpu, dbg)
/**
* powerUp(data, fRepower)
*
* @this {Keyboard}
* @this {Keyboard8080}
* @param {Object|null} data
* @param {boolean} [fRepower]
* @return {boolean} true if successful, false if failure
*/
Keyboard.prototype.powerUp = function(data, fRepower)
Keyboard8080.prototype.powerUp = function(data, fRepower)
{
if (!fRepower) {
if (!data) {
@ -567,20 +567,20 @@ Keyboard.prototype.powerUp = function(data, fRepower)
/**
* powerDown(fSave, fShutdown)
*
* @this {Keyboard}
* @this {Keyboard8080}
* @param {boolean} [fSave]
* @param {boolean} [fShutdown]
* @return {Object|boolean} component state if fSave; otherwise, true if successful, false if failure
*/
Keyboard.prototype.powerDown = function(fSave, fShutdown)
Keyboard8080.prototype.powerDown = function(fSave, fShutdown)
{
return fSave? this.save() : true;
};
Keyboard.VT100.INIT = [
Keyboard8080.VT100.INIT = [
[
Keyboard.VT100.STATUS.INIT, // bVT100Status
Keyboard.VT100.ADDRESS.INIT, // bVT100Address
Keyboard8080.VT100.STATUS.INIT, // bVT100Status
Keyboard8080.VT100.ADDRESS.INIT, // bVT100Address
-1 // iKeyNext
]
];
@ -588,9 +588,9 @@ Keyboard.VT100.INIT = [
/**
* reset()
*
* @this {Keyboard}
* @this {Keyboard8080}
*/
Keyboard.prototype.reset = function()
Keyboard8080.prototype.reset = function()
{
/*
* As keyDown events are encountered, a corresponding "softCode" is looked up. If one is found,
@ -614,16 +614,16 @@ Keyboard.prototype.reset = function()
*
* This implements save support for the Keyboard component.
*
* @this {Keyboard}
* @this {Keyboard8080}
* @return {Object}
*/
Keyboard.prototype.save = function()
Keyboard8080.prototype.save = function()
{
var state = new State(this);
switch(this.config.MODEL) {
case Keyboard.SI1978.MODEL:
case Keyboard8080.SI1978.MODEL:
break;
case Keyboard.VT100.MODEL:
case Keyboard8080.VT100.MODEL:
state.set(0, [this.bVT100Status, this.bVT100Address, -1]);
break;
}
@ -635,21 +635,21 @@ Keyboard.prototype.save = function()
*
* This implements restore support for the Keyboard component.
*
* @this {Keyboard}
* @this {Keyboard8080}
* @param {Object} data
* @return {boolean} true if successful, false if failure
*/
Keyboard.prototype.restore = function(data)
Keyboard8080.prototype.restore = function(data)
{
var a;
if (data && (a = data[0]) && a.length) {
switch(this.config.MODEL) {
case Keyboard.SI1978.MODEL:
case Keyboard8080.SI1978.MODEL:
return true;
case Keyboard.VT100.MODEL:
case Keyboard8080.VT100.MODEL:
this.bVT100Status = a[0];
this.updateLEDs(this.bVT100Status & Keyboard.VT100.STATUS.LEDS);
this.updateLEDs(this.bVT100Status & Keyboard8080.VT100.STATUS.LEDS);
this.bVT100Address = a[1];
this.iKeyNext = a[2];
return true;
@ -661,11 +661,11 @@ Keyboard.prototype.restore = function(data)
/**
* setLED(control, f)
*
* @this {Keyboard}
* @this {Keyboard8080}
* @param {Object} control is an HTML control DOM object
* @param {boolean} f is true if the LED represented by control should be "on", false if "off"
*/
Keyboard.prototype.setLED = function(control, f)
Keyboard8080.prototype.setLED = function(control, f)
{
/*
* TODO: Add support for user-definable LED colors
@ -676,10 +676,10 @@ Keyboard.prototype.setLED = function(control, f)
/**
* updateLEDs(bLEDs)
*
* @this {Keyboard}
* @this {Keyboard8080}
* @param {number} bLEDs
*/
Keyboard.prototype.updateLEDs = function(bLEDs)
Keyboard8080.prototype.updateLEDs = function(bLEDs)
{
this.bLEDs = bLEDs;
for (var sBinding in this.config.LEDCODES) {
@ -701,10 +701,10 @@ Keyboard.prototype.updateLEDs = function(bLEDs)
*
* Returns a number if the keyCode exists in the KEYMAP, or a string if the keyCode has a soft-code string.
*
* @this {Keyboard}
* @this {Keyboard8080}
* @return {string|number|null}
*/
Keyboard.prototype.getSoftCode = function(keyCode)
Keyboard8080.prototype.getSoftCode = function(keyCode)
{
keyCode = this.config.ALTCODES[keyCode] || keyCode;
if (this.config.KEYMAP[keyCode]) {
@ -721,12 +721,12 @@ Keyboard.prototype.getSoftCode = function(keyCode)
/**
* onKeyDown(event, fDown)
*
* @this {Keyboard}
* @this {Keyboard8080}
* @param {Object} event
* @param {boolean} fDown is true for a keyDown event, false for up
* @return {boolean} true to pass the event along, false to consume it
*/
Keyboard.prototype.onKeyDown = function(event, fDown)
Keyboard8080.prototype.onKeyDown = function(event, fDown)
{
var fPass = true;
var keyCode = event.keyCode;
@ -737,7 +737,7 @@ Keyboard.prototype.onKeyDown = function(event, fDown)
event.preventDefault();
}
if (!COMPILED && this.messageEnabled(Messages.KEYS)) {
if (!COMPILED && this.messageEnabled(Messages8080.KEYS)) {
this.printMessage("onKey" + (fDown? "Down" : "Up") + "(" + keyCode + "): softCode=" + softCode + ", pass=" + (fPass? "true" : "false"), true);
}
@ -747,11 +747,11 @@ Keyboard.prototype.onKeyDown = function(event, fDown)
/**
* indexOfSoftKey(softCode)
*
* @this {Keyboard}
* @this {Keyboard8080}
* @param {number|string} softCode
* @return {number} index of softCode in aKeysActive, or -1 if not found
*/
Keyboard.prototype.indexOfSoftKey = function(softCode)
Keyboard8080.prototype.indexOfSoftKey = function(softCode)
{
var i;
for (i = 0; i < this.aKeysActive.length; i++) {
@ -763,12 +763,12 @@ Keyboard.prototype.indexOfSoftKey = function(softCode)
/**
* onSoftKeyDown(softCode, fDown)
*
* @this {Keyboard}
* @this {Keyboard8080}
* @param {number|string} softCode
* @param {boolean} fDown is true for a down event, false for up
* @return {boolean} true to pass the event along, false to consume it
*/
Keyboard.prototype.onSoftKeyDown = function(softCode, fDown)
Keyboard8080.prototype.onSoftKeyDown = function(softCode, fDown)
{
var i = this.indexOfSoftKey(softCode);
if (fDown) {
@ -789,7 +789,7 @@ Keyboard.prototype.onSoftKeyDown = function(softCode, fDown)
var msDown = this.aKeysActive[i].msDown;
if (msDown) {
var msElapsed = Date.now() - msDown;
if (msElapsed < Keyboard.MINPRESSTIME) {
if (msElapsed < Keyboard8080.MINPRESSTIME) {
// this.println(softCode + " released after only " + msElapsed + "ms");
this.aKeysActive[i].fAutoRelease = true;
this.checkSoftKeysToRelease();
@ -806,22 +806,22 @@ Keyboard.prototype.onSoftKeyDown = function(softCode, fDown)
var bit = 0;
switch(softCode) {
case '1p':
bit = ChipSet.SI1978.STATUS1.P1;
bit = ChipSet8080.SI1978.STATUS1.P1;
break;
case '2p':
bit = ChipSet.SI1978.STATUS1.P2;
bit = ChipSet8080.SI1978.STATUS1.P2;
break;
case 'coin':
bit = ChipSet.SI1978.STATUS1.CREDIT;
bit = ChipSet8080.SI1978.STATUS1.CREDIT;
break;
case 'left':
bit = ChipSet.SI1978.STATUS1.P1_LEFT;
bit = ChipSet8080.SI1978.STATUS1.P1_LEFT;
break;
case 'right':
bit = ChipSet.SI1978.STATUS1.P1_RIGHT;
bit = ChipSet8080.SI1978.STATUS1.P1_RIGHT;
break;
case 'fire':
bit = ChipSet.SI1978.STATUS1.P1_FIRE;
bit = ChipSet8080.SI1978.STATUS1.P1_FIRE;
break;
}
if (bit) {
@ -834,9 +834,9 @@ Keyboard.prototype.onSoftKeyDown = function(softCode, fDown)
/**
* checkSoftKeysToRelease()
*
* @this {Keyboard}
* @this {Keyboard8080}
*/
Keyboard.prototype.checkSoftKeysToRelease = function()
Keyboard8080.prototype.checkSoftKeysToRelease = function()
{
var i = 0;
var msDelayMin = -1;
@ -845,7 +845,7 @@ Keyboard.prototype.checkSoftKeysToRelease = function()
var softCode = this.aKeysActive[i].softCode;
var msDown = this.aKeysActive[i].msDown;
var msElapsed = Date.now() - msDown;
var msDelay = Keyboard.MINPRESSTIME - msElapsed;
var msDelay = Keyboard8080.MINPRESSTIME - msElapsed;
if (msDelay > 0) {
if (msDelayMin < 0 || msDelayMin > msDelay) {
msDelayMin = msDelay;
@ -875,10 +875,10 @@ Keyboard.prototype.checkSoftKeysToRelease = function()
* Called whenever a ChipSet circuit needs the Keyboard UART's transmitter status.
* Currently, we have no busy conditions (our virtual keyboard transmitter is infinitely fast).
*
* @this {Keyboard}
* @this {Keyboard8080}
* @return {boolean} (true if ready, false if not)
*/
Keyboard.prototype.isTransmitterReady = function()
Keyboard8080.prototype.isTransmitterReady = function()
{
return true;
};
@ -888,15 +888,15 @@ Keyboard.prototype.isTransmitterReady = function()
*
* We take our cue from iKeyNext. If it's -1 (default), we simply return the last value latched
* in bVT100Address. Otherwise, if iKeyNext is a valid index into aKeysActive, we look up the key
* in the VT100.KEYMAP, latch it, and increment iKeyNext. Failing that, we latch Keyboard.VT100.KEYLAST
* in the VT100.KEYMAP, latch it, and increment iKeyNext. Failing that, we latch Keyboard8080.VT100.KEYLAST
* and reset iKeyNext to -1.
*
* @this {Keyboard}
* @this {Keyboard8080}
* @param {number} port (0x82)
* @param {number} [addrFrom] (not defined if the Debugger is trying to write the specified port)
* @return {number} simulated port value
*/
Keyboard.prototype.inVT100UARTAddress = function(port, addrFrom)
Keyboard8080.prototype.inVT100UARTAddress = function(port, addrFrom)
{
var b = this.bVT100Address;
if (this.iKeyNext >= 0) {
@ -913,7 +913,7 @@ Keyboard.prototype.inVT100UARTAddress = function(port, addrFrom)
*/
this.aKeysActive.splice(this.iKeyNext, 1);
}
b = Keyboard.VT100.KEYMAP[key.softCode];
b = Keyboard8080.VT100.KEYMAP[key.softCode];
if (b & 0x80) {
/*
* TODO: This code is supposed to be accompanied by a SHIFT key; make sure that it is.
@ -922,7 +922,7 @@ Keyboard.prototype.inVT100UARTAddress = function(port, addrFrom)
}
} else {
this.iKeyNext = -1;
b = Keyboard.VT100.KEYLAST;
b = Keyboard8080.VT100.KEYLAST;
}
this.bVT100Address = b;
this.cpu.requestINTR(1);
@ -934,17 +934,17 @@ Keyboard.prototype.inVT100UARTAddress = function(port, addrFrom)
/**
* outVT100UARTStatus(port, b, addrFrom)
*
* @this {Keyboard}
* @this {Keyboard8080}
* @param {number} port (0x82)
* @param {number} b
* @param {number} [addrFrom] (not defined if the Debugger is trying to write the specified port)
*/
Keyboard.prototype.outVT100UARTStatus = function(port, b, addrFrom)
Keyboard8080.prototype.outVT100UARTStatus = function(port, b, addrFrom)
{
this.printMessageIO(port, b, addrFrom, "KBDUART.STATUS");
this.bVT100Status = b;
this.updateLEDs(b & Keyboard.VT100.STATUS.LEDS);
if (b & Keyboard.VT100.STATUS.START) {
this.updateLEDs(b & Keyboard8080.VT100.STATUS.LEDS);
if (b & Keyboard8080.VT100.STATUS.START) {
this.iKeyNext = 0;
this.cpu.requestINTR(1);
}
@ -953,29 +953,29 @@ Keyboard.prototype.outVT100UARTStatus = function(port, b, addrFrom)
/*
* Port notification tables
*/
Keyboard.VT100.portsInput = {
0x82: Keyboard.prototype.inVT100UARTAddress
Keyboard8080.VT100.portsInput = {
0x82: Keyboard8080.prototype.inVT100UARTAddress
};
Keyboard.VT100.portsOutput = {
0x82: Keyboard.prototype.outVT100UARTStatus
Keyboard8080.VT100.portsOutput = {
0x82: Keyboard8080.prototype.outVT100UARTStatus
};
/**
* Keyboard.init()
* Keyboard8080.init()
*
* This function operates on every HTML element of class "keyboard", extracting the
* JSON-encoded parameters for the Keyboard constructor from the element's "data-value"
* attribute, invoking the constructor to create a Keyboard component, and then binding
* any associated HTML controls to the new component.
*/
Keyboard.init = function()
Keyboard8080.init = function()
{
var aeKbd = Component.getElementsByClass(document, PC8080.APPCLASS, "keyboard");
for (var iKbd = 0; iKbd < aeKbd.length; iKbd++) {
var eKbd = aeKbd[iKbd];
var parmsKbd = Component.getComponentParms(eKbd);
var kbd = new Keyboard(parmsKbd);
var kbd = new Keyboard8080(parmsKbd);
Component.bindComponentControls(kbd, eKbd, PC8080.APPCLASS);
}
};
@ -983,6 +983,6 @@ Keyboard.init = function()
/*
* Initialize every Keyboard module on the page.
*/
web.onInit(Keyboard.init);
web.onInit(Keyboard8080.init);
if (NODE) module.exports = Keyboard;
if (NODE) module.exports = Keyboard8080;

View file

@ -34,8 +34,8 @@
if (NODE) {
var str = require("../../shared/lib/strlib");
var Component = require("../../shared/lib/component");
var Messages = require("./messages");
var CPUDef = require("./cpudef");
var CPUDef8080 = require("./cpudef");
var Messages8080= require("./messages");
}
/**
@ -55,20 +55,20 @@ var littleEndian = (TYPEDARRAYS? (function() {
})() : false);
/**
* Memory(addr, used, size, type)
* Memory8080(addr, used, size, type)
*
* The Bus component allocates Memory objects so that each has a memory buffer with a
* The Bus component allocates Memory8080 objects so that each has a memory buffer with a
* block-granular starting address and an address range equal to bus.nBlockSize; however,
* the size of any given Memory object's underlying buffer can be either zero or bus.nBlockSize;
* the size of any given Memory8080 object's underlying buffer can be either zero or bus.nBlockSize;
* memory read/write functions for empty (buffer-less) blocks are mapped to readNone/writeNone.
*
* The Bus allocates empty blocks for the entire address space during initialization, so that
* any reads/writes to undefined addresses will have no effect. Later, the ROM and RAM
* components will ask the Bus to allocate memory for specific ranges, and the Bus will allocate
* as many new blockSize Memory objects as the ranges require. Partial Memory blocks could
* as many new blockSize Memory8080 objects as the ranges require. Partial Memory8080 blocks could
* also be supported in theory, but in practice, they're not.
*
* Because Memory blocks now allow us to have a "sparse" address space, we could choose to
* Because Memory8080 blocks now allow us to have a "sparse" address space, we could choose to
* take the memory hit of allocating 4K arrays per block, where each element stores only one byte,
* instead of the more frugal but slightly slower approach of allocating arrays of 32-bit dwords
* (LONGARRAYS) and shifting/masking bytes/words to/from dwords; in theory, byte accesses would
@ -82,7 +82,7 @@ var littleEndian = (TYPEDARRAYS? (function() {
* size at this point. Also, not all JavaScript implementations support TYPEDARRAYS (IE9 is probably
* the only real outlier: it lacks typed arrays but otherwise has all the necessary HTML5 support).
*
* WARNING: Since Memory blocks are low-level objects that have no UI requirements, they
* WARNING: Since Memory8080 blocks are low-level objects that have no UI requirements, they
* do not inherit from the Component class, so if you want to use any Component class methods,
* such as Component.assert(), use the corresponding Debugger methods instead (assuming a debugger
* is available).
@ -91,19 +91,19 @@ var littleEndian = (TYPEDARRAYS? (function() {
* @param {number|null} [addr] of lowest used address in block
* @param {number} [used] portion of block in bytes (0 for none); must be a multiple of 4
* @param {number} [size] of block's buffer in bytes (0 for none); must be a multiple of 4
* @param {number} [type] is one of the Memory.TYPE constants (default is Memory.TYPE.NONE)
* @param {number} [type] is one of the Memory8080.TYPE constants (default is Memory8080.TYPE.NONE)
*/
function Memory(addr, used, size, type)
function Memory8080(addr, used, size, type)
{
var i;
this.id = (Memory.idBlock += 2);
this.id = (Memory8080.idBlock += 2);
this.adw = null;
this.offset = 0;
this.addr = addr;
this.used = used;
this.size = size || 0;
this.type = type || Memory.TYPE.NONE;
this.fReadOnly = (type == Memory.TYPE.ROM);
this.type = type || Memory8080.TYPE.NONE;
this.fReadOnly = (type == Memory8080.TYPE.ROM);
this.copyBreakpoints(); // initialize the block's Debugger info; the caller will reinitialize
/*
@ -146,7 +146,7 @@ function Memory(addr, used, size, type)
this.ab = new Uint8Array(this.buffer, 0, size);
this.aw = new Uint16Array(this.buffer, 0, size >> 1);
this.adw = new Int32Array(this.buffer, 0, size >> 2);
this.setAccess(littleEndian? Memory.afnArrayLE : Memory.afnArrayBE);
this.setAccess(littleEndian? Memory8080.afnArrayLE : Memory8080.afnArrayBE);
} else {
if (BYTEARRAYS) {
this.ab = new Array(size);
@ -160,7 +160,7 @@ function Memory(addr, used, size, type)
this.adw = new Array(size >> 2);
for (i = 0; i < this.adw.length; i++) this.adw[i] = 0;
}
this.setAccess(Memory.afnMemory);
this.setAccess(Memory8080.afnMemory);
}
}
@ -171,7 +171,7 @@ function Memory(addr, used, size, type)
* 'little endian") storage. ROM is equally conventional, except that the fReadOnly property is set,
* disabling writes. VIDEO is treated exactly like RAM, unless a controller is provided. Both RAM and
* VIDEO memory are always considered writable, and even ROM can be written using the Bus setByteDirect()
* interface (which in turn uses the Memory writeByteDirect() interface), allowing the ROM component to
* interface (which in turn uses the Memory8080 writeByteDirect() interface), allowing the ROM component to
* initialize its own memory. The CTRL type is used to identify memory-mapped devices that do not need
* any default storage and always provide their own controller.
*
@ -186,7 +186,7 @@ function Memory(addr, used, size, type)
* read-only memory), but the larger purpose of these types is to help document the caller's intent and to
* provide the Control Panel with the ability to highlight memory regions accordingly.
*/
Memory.TYPE = {
Memory8080.TYPE = {
NONE: 0,
RAM: 1,
ROM: 2,
@ -199,7 +199,7 @@ Memory.TYPE = {
/*
* Last used block ID (used for debugging only)
*/
Memory.idBlock = 0;
Memory8080.idBlock = 0;
/**
* adjustEndian(dw)
@ -207,22 +207,22 @@ Memory.idBlock = 0;
* @param {number} dw
* @return {number}
*/
Memory.adjustEndian = function(dw) {
Memory8080.adjustEndian = function(dw) {
if (TYPEDARRAYS && !littleEndian) {
dw = (dw << 24) | ((dw << 8) & 0x00ff0000) | ((dw >> 8) & 0x0000ff00) | (dw >>> 24);
}
return dw;
};
Memory.prototype = {
constructor: Memory,
Memory8080.prototype = {
constructor: Memory8080,
parent: null,
/**
* init(addr)
*
* Quick reinitializer when reusing a Memory block.
* Quick reinitializer when reusing a Memory8080 block.
*
* @this {Memory}
* @this {Memory8080}
* @param {number} addr
*/
init: function(addr) {
@ -231,13 +231,13 @@ Memory.prototype = {
/**
* clone(mem, type)
*
* Converts the current Memory block (this) into a clone of the given Memory block (mem),
* Converts the current Memory8080 block (this) into a clone of the given Memory8080 block (mem),
* and optionally overrides the current block's type with the specified type.
*
* @this {Memory}
* @param {Memory} mem
* @this {Memory8080}
* @param {Memory8080} mem
* @param {number} [type]
* @param {Debugger} [dbg]
* @param {Debugger8080} [dbg]
*/
clone: function(mem, type, dbg) {
/*
@ -250,7 +250,7 @@ Memory.prototype = {
this.size = mem.size;
if (type) {
this.type = type;
this.fReadOnly = (type == Memory.TYPE.ROM);
this.fReadOnly = (type == Memory8080.TYPE.ROM);
}
if (TYPEDARRAYS) {
this.buffer = mem.buffer;
@ -258,27 +258,27 @@ Memory.prototype = {
this.ab = mem.ab;
this.aw = mem.aw;
this.adw = mem.adw;
this.setAccess(littleEndian? Memory.afnArrayLE : Memory.afnArrayBE);
this.setAccess(littleEndian? Memory8080.afnArrayLE : Memory8080.afnArrayBE);
} else {
if (BYTEARRAYS) {
this.ab = mem.ab;
} else {
this.adw = mem.adw;
}
this.setAccess(Memory.afnMemory);
this.setAccess(Memory8080.afnMemory);
}
this.copyBreakpoints(dbg, mem);
},
/**
* save()
*
* This gets the contents of a Memory block as an array of 32-bit values; used by Bus.saveMemory(),
* This gets the contents of a Memory8080 block as an array of 32-bit values; used by Bus8080.saveMemory(),
* which in turn is called by CPUState.save().
*
* Memory blocks with custom memory controllers do NOT save their contents; that's the responsibility
* Memory8080 blocks with custom memory controllers do NOT save their contents; that's the responsibility
* of the controller component.
*
* @this {Memory}
* @this {Memory8080}
* @return {Array|Int32Array|null}
*/
save: function() {
@ -315,12 +315,12 @@ Memory.prototype = {
/**
* restore(adw)
*
* This restores the contents of a Memory block from an array of 32-bit values;
* used by Bus.restoreMemory(), which is called by CPUState.restore(), after all other
* components have been restored and thus all Memory blocks have been allocated
* This restores the contents of a Memory8080 block from an array of 32-bit values;
* used by Bus8080.restoreMemory(), which is called by CPUState.restore(), after all other
* components have been restored and thus all Memory8080 blocks have been allocated
* by their respective components.
*
* @this {Memory}
* @this {Memory8080}
* @param {Array|null} adw
* @return {boolean} true if successful, false if block size mismatch
*/
@ -360,16 +360,16 @@ Memory.prototype = {
/**
* setAccess(afn, fDirect)
*
* If no function table is specified, a default is selected based on the Memory type.
* If no function table is specified, a default is selected based on the Memory8080 type.
*
* @this {Memory}
* @this {Memory8080}
* @param {Array.<function()>} [afn] function table
* @param {boolean} [fDirect] (true to update direct access functions as well; default is true)
*/
setAccess: function(afn, fDirect) {
if (!afn) {
Component.assert(this.type == Memory.TYPE.NONE);
afn = Memory.afnNone;
Component.assert(this.type == Memory8080.TYPE.NONE);
afn = Memory8080.afnNone;
}
this.setReadAccess(afn, fDirect);
this.setWriteAccess(afn, fDirect);
@ -377,7 +377,7 @@ Memory.prototype = {
/**
* setReadAccess(afn, fDirect)
*
* @this {Memory}
* @this {Memory8080}
* @param {Array.<function()>} afn
* @param {boolean} [fDirect]
*/
@ -394,7 +394,7 @@ Memory.prototype = {
/**
* setWriteAccess(afn, fDirect)
*
* @this {Memory}
* @this {Memory8080}
* @param {Array.<function()>} afn
* @param {boolean} [fDirect]
*/
@ -411,7 +411,7 @@ Memory.prototype = {
/**
* resetReadAccess()
*
* @this {Memory}
* @this {Memory8080}
*/
resetReadAccess: function() {
this.readByte = this.readByteDirect;
@ -420,7 +420,7 @@ Memory.prototype = {
/**
* resetWriteAccess()
*
* @this {Memory}
* @this {Memory8080}
*/
resetWriteAccess: function() {
this.writeByte = this.fReadOnly? this.writeNone : this.writeByteDirect;
@ -429,31 +429,31 @@ Memory.prototype = {
/**
* printAddr(sMessage)
*
* @this {Memory}
* @this {Memory8080}
* @param {string} sMessage
*/
printAddr: function(sMessage) {
if (DEBUG && this.dbg && this.dbg.messageEnabled(Messages.MEM)) {
if (DEBUG && this.dbg && this.dbg.messageEnabled(Messages8080.MEM)) {
this.dbg.printMessage(sMessage + ' ' + (this.addr != null? ('%' + str.toHex(this.addr)) : '#' + this.id), true);
}
},
/**
* addBreakpoint(off, fWrite)
*
* @this {Memory}
* @this {Memory8080}
* @param {number} off
* @param {boolean} fWrite
*/
addBreakpoint: function(off, fWrite) {
if (!fWrite) {
if (this.cReadBreakpoints++ === 0) {
this.setReadAccess(Memory.afnChecked, false);
this.setReadAccess(Memory8080.afnChecked, false);
}
if (DEBUG) this.printAddr("read breakpoint added to memory block");
}
else {
if (this.cWriteBreakpoints++ === 0) {
this.setWriteAccess(Memory.afnChecked, false);
this.setWriteAccess(Memory8080.afnChecked, false);
}
if (DEBUG) this.printAddr("write breakpoint added to memory block");
}
@ -461,7 +461,7 @@ Memory.prototype = {
/**
* removeBreakpoint(off, fWrite)
*
* @this {Memory}
* @this {Memory8080}
* @param {number} off
* @param {boolean} fWrite
*/
@ -484,19 +484,19 @@ Memory.prototype = {
/**
* copyBreakpoints(dbg, mem)
*
* @this {Memory}
* @param {Debugger} [dbg]
* @param {Memory} [mem] (outgoing Memory block to copy breakpoints from, if any)
* @this {Memory8080}
* @param {Debugger8080} [dbg]
* @param {Memory8080} [mem] (outgoing Memory8080 block to copy breakpoints from, if any)
*/
copyBreakpoints: function(dbg, mem) {
this.dbg = dbg;
this.cReadBreakpoints = this.cWriteBreakpoints = 0;
if (mem) {
if ((this.cReadBreakpoints = mem.cReadBreakpoints)) {
this.setReadAccess(Memory.afnChecked, false);
this.setReadAccess(Memory8080.afnChecked, false);
}
if ((this.cWriteBreakpoints = mem.cWriteBreakpoints)) {
this.setWriteAccess(Memory.afnChecked, false);
this.setWriteAccess(Memory8080.afnChecked, false);
}
}
},
@ -513,15 +513,15 @@ Memory.prototype = {
* that a system would require nonexistent memory locations to return ALL bits set.
*
* Also, I'm reluctant to address that potential issue by simply returning -1, because to date, the above
* Memory interfaces have always returned values that are properly masked to 8, 16 or 32 bits, respectively.
* Memory8080 interfaces have always returned values that are properly masked to 8, 16 or 32 bits, respectively.
*
* @this {Memory}
* @this {Memory8080}
* @param {number} off
* @param {number} addr
* @return {number}
*/
readNone: function readNone(off, addr) {
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(Messages.CPU | Messages.MEM) /* && !off */) {
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(Messages8080.CPU | Messages8080.MEM) /* && !off */) {
this.dbg.message("attempt to read invalid block %" + str.toHex(this.addr), true);
}
return 0xff;
@ -529,20 +529,20 @@ Memory.prototype = {
/**
* writeNone(off, v, addr)
*
* @this {Memory}
* @this {Memory8080}
* @param {number} off
* @param {number} v (could be either a byte or word value, since we use the same handler for both kinds of accesses)
* @param {number} addr
*/
writeNone: function writeNone(off, v, addr) {
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(Messages.CPU | Messages.MEM) /* && !off */) {
if (DEBUGGER && this.dbg && this.dbg.messageEnabled(Messages8080.CPU | Messages8080.MEM) /* && !off */) {
this.dbg.message("attempt to write " + str.toHexWord(v) + " to invalid block %" + str.toHex(this.addr), true);
}
},
/**
* readShortDefault(off, addr)
*
* @this {Memory}
* @this {Memory8080}
* @param {number} off
* @param {number} addr
* @return {number}
@ -553,7 +553,7 @@ Memory.prototype = {
/**
* writeShortDefault(off, w, addr)
*
* @this {Memory}
* @this {Memory8080}
* @param {number} off
* @param {number} w
* @param {number} addr
@ -565,7 +565,7 @@ Memory.prototype = {
/**
* readByteMemory(off, addr)
*
* @this {Memory}
* @this {Memory8080}
* @param {number} off
* @param {number} addr
* @return {number}
@ -579,7 +579,7 @@ Memory.prototype = {
/**
* readShortMemory(off, addr)
*
* @this {Memory}
* @this {Memory8080}
* @param {number} off
* @param {number} addr
* @return {number}
@ -602,7 +602,7 @@ Memory.prototype = {
/**
* writeByteMemory(off, b, addr)
*
* @this {Memory}
* @this {Memory8080}
* @param {number} off
* @param {number} b
* @param {number} addr
@ -620,7 +620,7 @@ Memory.prototype = {
/**
* writeShortMemory(off, w, addr)
*
* @this {Memory}
* @this {Memory8080}
* @param {number} off
* @param {number} w
* @param {number} addr
@ -645,7 +645,7 @@ Memory.prototype = {
/**
* readByteChecked(off, addr)
*
* @this {Memory}
* @this {Memory8080}
* @param {number} off
* @param {number} addr
* @return {number}
@ -659,7 +659,7 @@ Memory.prototype = {
/**
* readShortChecked(off, addr)
*
* @this {Memory}
* @this {Memory8080}
* @param {number} off
* @param {number} addr
* @return {number}
@ -673,7 +673,7 @@ Memory.prototype = {
/**
* writeByteChecked(off, b, addr)
*
* @this {Memory}
* @this {Memory8080}
* @param {number} off
* @param {number} addr
* @param {number} b
@ -687,7 +687,7 @@ Memory.prototype = {
/**
* writeShortChecked(off, w, addr)
*
* @this {Memory}
* @this {Memory8080}
* @param {number} off
* @param {number} addr
* @param {number} w
@ -701,7 +701,7 @@ Memory.prototype = {
/**
* readByteBE(off, addr)
*
* @this {Memory}
* @this {Memory8080}
* @param {number} off
* @param {number} addr
* @return {number}
@ -712,7 +712,7 @@ Memory.prototype = {
/**
* readByteLE(off, addr)
*
* @this {Memory}
* @this {Memory8080}
* @param {number} off
* @param {number} addr
* @return {number}
@ -723,7 +723,7 @@ Memory.prototype = {
/**
* readShortBE(off, addr)
*
* @this {Memory}
* @this {Memory8080}
* @param {number} off
* @param {number} addr
* @return {number}
@ -734,7 +734,7 @@ Memory.prototype = {
/**
* readShortLE(off, addr)
*
* @this {Memory}
* @this {Memory8080}
* @param {number} off
* @param {number} addr
* @return {number}
@ -749,7 +749,7 @@ Memory.prototype = {
/**
* writeByteBE(off, b, addr)
*
* @this {Memory}
* @this {Memory8080}
* @param {number} off
* @param {number} b
* @param {number} addr
@ -761,7 +761,7 @@ Memory.prototype = {
/**
* writeByteLE(off, b, addr)
*
* @this {Memory}
* @this {Memory8080}
* @param {number} off
* @param {number} addr
* @param {number} b
@ -773,7 +773,7 @@ Memory.prototype = {
/**
* writeShortBE(off, w, addr)
*
* @this {Memory}
* @this {Memory8080}
* @param {number} off
* @param {number} addr
* @param {number} w
@ -785,7 +785,7 @@ Memory.prototype = {
/**
* writeShortLE(off, w, addr)
*
* @this {Memory}
* @this {Memory8080}
* @param {number} off
* @param {number} addr
* @param {number} w
@ -809,16 +809,16 @@ Memory.prototype = {
* This is the effective definition of afnNone, but we need not fully define it, because setAccess()
* uses these defaults when any of the 6 handlers (ie, 3 read handlers and 3 write handlers) are undefined.
*
Memory.afnNone = [Memory.prototype.readNone, Memory.prototype.readShortDefault, Memory.prototype.writeNone, Memory.prototype.writeShortDefault];
Memory8080.afnNone = [Memory8080.prototype.readNone, Memory8080.prototype.readShortDefault, Memory8080.prototype.writeNone, Memory8080.prototype.writeShortDefault];
*/
Memory.afnNone = [];
Memory.afnMemory = [Memory.prototype.readByteMemory, Memory.prototype.readShortMemory, Memory.prototype.writeByteMemory, Memory.prototype.writeShortMemory];
Memory.afnChecked = [Memory.prototype.readByteChecked, Memory.prototype.readShortChecked, Memory.prototype.writeByteChecked, Memory.prototype.writeShortChecked];
Memory8080.afnNone = [];
Memory8080.afnMemory = [Memory8080.prototype.readByteMemory, Memory8080.prototype.readShortMemory, Memory8080.prototype.writeByteMemory, Memory8080.prototype.writeShortMemory];
Memory8080.afnChecked = [Memory8080.prototype.readByteChecked, Memory8080.prototype.readShortChecked, Memory8080.prototype.writeByteChecked, Memory8080.prototype.writeShortChecked];
if (TYPEDARRAYS) {
Memory.afnArrayBE = [Memory.prototype.readByteBE, Memory.prototype.readShortBE, Memory.prototype.writeByteBE, Memory.prototype.writeShortBE];
Memory.afnArrayLE = [Memory.prototype.readByteLE, Memory.prototype.readShortLE, Memory.prototype.writeByteLE, Memory.prototype.writeShortLE];
Memory8080.afnArrayBE = [Memory8080.prototype.readByteBE, Memory8080.prototype.readShortBE, Memory8080.prototype.writeByteBE, Memory8080.prototype.writeShortBE];
Memory8080.afnArrayLE = [Memory8080.prototype.readByteLE, Memory8080.prototype.readShortLE, Memory8080.prototype.writeByteLE, Memory8080.prototype.writeShortLE];
}
if (NODE) module.exports = Memory;
if (NODE) module.exports = Memory8080;

View file

@ -31,7 +31,7 @@
"use strict";
var Messages = {
var Messages8080 = {
CPU: 0x00000001,
BUS: 0x00000040,
MEM: 0x00000080,
@ -51,4 +51,4 @@ var Messages = {
HALT: 0x80000000|0
};
if (NODE) module.exports = Messages;
if (NODE) module.exports = Messages8080;

View file

@ -36,26 +36,26 @@ if (NODE) {
var usr = require("../../shared/lib/usrlib");
var web = require("../../shared/lib/weblib");
var Component = require("../../shared/lib/component");
var Bus = require("./bus");
var Memory = require("./memory");
var CPUDef = require("./cpudef");
var Bus8080 = require("./bus");
var CPUDef8080 = require("./cpudef");
var Memory8080 = require("./memory");
}
/**
* Panel(parmsPanel)
* Panel8080(parmsPanel)
*
* The Panel component has no required (parmsPanel) properties.
* The Panel8080 component has no required (parmsPanel) properties.
*
* @constructor
* @extends Component
* @param {Object} parmsPanel
*/
function Panel(parmsPanel)
function Panel8080(parmsPanel)
{
Component.call(this, "Panel", parmsPanel, Panel);
Component.call(this, "Panel", parmsPanel, Panel8080);
}
Component.subclass(Panel);
Component.subclass(Panel8080);
/**
* setBinding(sHTMLType, sBinding, control, sValue)
@ -64,14 +64,14 @@ Component.subclass(Panel);
* Computer, CPU, Keyboard and Debugger components first. The order shouldn't matter, since any component
* that doesn't recognize the specified binding should simply ignore it.
*
* @this {Panel}
* @this {Panel8080}
* @param {string|null} sHTMLType is the type of the HTML control (eg, "button", "list", "text", "submit", "textarea", "canvas")
* @param {string} sBinding is the value of the 'binding' parameter stored in the HTML control's "data-value" attribute (eg, "reset")
* @param {Object} control is the HTML control DOM object (eg, HTMLButtonElement)
* @param {string} [sValue] optional data value
* @return {boolean} true if binding was successful, false if unrecognized binding request
*/
Panel.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
Panel8080.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
{
if (this.cmp && this.cmp.setBinding(sHTMLType, sBinding, control, sValue)) return true;
if (this.cpu && this.cpu.setBinding(sHTMLType, sBinding, control, sValue)) return true;
@ -83,44 +83,44 @@ Panel.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
/**
* initBus(cmp, bus, cpu, dbg)
*
* @this {Panel}
* @param {Computer} cmp
* @param {Bus} bus
* @param {CPUState} cpu
* @param {Debugger} dbg
* @this {Panel8080}
* @param {Computer8080} cmp
* @param {Bus8080} bus
* @param {CPUState8080} cpu
* @param {Debugger8080} dbg
*/
Panel.prototype.initBus = function(cmp, bus, cpu, dbg)
Panel8080.prototype.initBus = function(cmp, bus, cpu, dbg)
{
this.cmp = cmp;
this.bus = bus;
this.cpu = cpu;
this.dbg = dbg;
this.kbd = /** @type {Keyboard} */ (cmp.getMachineComponent("Keyboard"));
this.kbd = /** @type {Keyboard8080} */ (cmp.getMachineComponent("Keyboard"));
};
/**
* powerUp(data, fRepower)
*
* @this {Panel}
* @this {Panel8080}
* @param {Object|null} data
* @param {boolean} [fRepower]
* @return {boolean} true if successful, false if failure
*/
Panel.prototype.powerUp = function(data, fRepower)
Panel8080.prototype.powerUp = function(data, fRepower)
{
if (!fRepower) Panel.init();
if (!fRepower) Panel8080.init();
return true;
};
/**
* powerDown(fSave, fShutdown)
*
* @this {Panel}
* @this {Panel8080}
* @param {boolean} [fSave]
* @param {boolean} [fShutdown]
* @return {Object|boolean} component state if fSave; otherwise, true if successful, false if failure
*/
Panel.prototype.powerDown = function(fSave, fShutdown)
Panel8080.prototype.powerDown = function(fSave, fShutdown)
{
return true;
};
@ -135,19 +135,19 @@ Panel.prototype.powerDown = function(fSave, fShutdown)
*
* The Computer's updateStatus() handler is currently responsible for calling both our handler and the CPU's handler.
*
* @this {Panel}
* @this {Panel8080}
* @param {boolean} [fForce] (true will display registers even if the CPU is running and "live" registers are not enabled)
*/
Panel.prototype.updateStatus = function(fForce)
Panel8080.prototype.updateStatus = function(fForce)
{
};
/**
* Panel.init()
* Panel8080.init()
*
* This function operates on every HTML element of class "panel", extracting the
* JSON-encoded parameters for the Panel constructor from the element's "data-value"
* attribute, invoking the constructor to create a Panel component, and then binding
* JSON-encoded parameters for the Panel8080 constructor from the element's "data-value"
* attribute, invoking the constructor to create a Panel8080 component, and then binding
* any associated HTML controls to the new component.
*
* NOTE: Unlike most other component init() functions, this one is designed to be
@ -159,7 +159,7 @@ Panel.prototype.updateStatus = function(fForce)
* that might care (eg, CPU, Keyboard, and Debugger) that we have some controls they
* might want to use.
*/
Panel.init = function()
Panel8080.init = function()
{
var fReady = false;
var aePanels = Component.getElementsByClass(document, PC8080.APPCLASS, "panel");
@ -169,7 +169,7 @@ Panel.init = function()
var panel = Component.getComponentByID(parmsPanel['id']);
if (!panel) {
fReady = true;
panel = new Panel(parmsPanel);
panel = new Panel8080(parmsPanel);
}
Component.bindComponentControls(panel, ePanel, PC8080.APPCLASS);
if (fReady) panel.setReady();
@ -179,6 +179,6 @@ Panel.init = function()
/*
* Initialize every Panel module on the page.
*/
web.onInit(Panel.init);
web.onInit(Panel8080.init);
if (NODE) module.exports = Panel;
if (NODE) module.exports = Panel8080;

View file

@ -35,15 +35,15 @@ if (NODE) {
var str = require("../../shared/lib/strlib");
var web = require("../../shared/lib/weblib");
var Component = require("../../shared/lib/component");
var Memory = require("./memory");
var ROM = require("./rom");
var State = require("./state");
var Memory8080 = require("./memory");
var ROM8080 = require("./rom");
var State8080 = require("./state");
}
/**
* RAM(parmsRAM)
* RAM8080(parmsRAM)
*
* The RAM component expects the following (parmsRAM) properties:
* The RAM8080 component expects the following (parmsRAM) properties:
*
* addr: starting physical address of RAM (default is 0)
* size: amount of RAM, in bytes (default is 0, which means defer to motherboard switch settings)
@ -55,9 +55,9 @@ if (NODE) {
* @extends Component
* @param {Object} parmsRAM
*/
function RAM(parmsRAM)
function RAM8080(parmsRAM)
{
Component.call(this, "RAM", parmsRAM, RAM);
Component.call(this, "RAM", parmsRAM, RAM8080);
this.addrRAM = parmsRAM['addr'];
this.sizeRAM = parmsRAM['size'];
@ -65,18 +65,18 @@ function RAM(parmsRAM)
this.fAllocated = false;
}
Component.subclass(RAM);
Component.subclass(RAM8080);
/**
* initBus(cmp, bus, cpu, dbg)
*
* @this {RAM}
* @param {Computer} cmp
* @param {Bus} bus
* @param {CPUState} cpu
* @param {Debugger} dbg
* @this {RAM8080}
* @param {Computer8080} cmp
* @param {Bus8080} bus
* @param {CPUState8080} cpu
* @param {Debugger8080} dbg
*/
RAM.prototype.initBus = function(cmp, bus, cpu, dbg)
RAM8080.prototype.initBus = function(cmp, bus, cpu, dbg)
{
this.bus = bus;
this.cpu = cpu;
@ -87,12 +87,12 @@ RAM.prototype.initBus = function(cmp, bus, cpu, dbg)
/**
* powerUp(data, fRepower)
*
* @this {RAM}
* @this {RAM8080}
* @param {Object|null} data
* @param {boolean} [fRepower]
* @return {boolean} true if successful, false if failure
*/
RAM.prototype.powerUp = function(data, fRepower)
RAM8080.prototype.powerUp = function(data, fRepower)
{
if (!fRepower) {
/*
@ -109,12 +109,12 @@ RAM.prototype.powerUp = function(data, fRepower)
/**
* powerDown(fSave, fShutdown)
*
* @this {RAM}
* @this {RAM8080}
* @param {boolean} [fSave]
* @param {boolean} [fShutdown]
* @return {Object|boolean} component state if fSave; otherwise, true if successful, false if failure
*/
RAM.prototype.powerDown = function(fSave, fShutdown)
RAM8080.prototype.powerDown = function(fSave, fShutdown)
{
/*
* The Computer powers down the CPU first, at which point CPUState state is saved,
@ -128,12 +128,12 @@ RAM.prototype.powerDown = function(fSave, fShutdown)
/**
* reset()
*
* @this {RAM}
* @this {RAM8080}
*/
RAM.prototype.reset = function()
RAM8080.prototype.reset = function()
{
if (!this.fAllocated && this.sizeRAM) {
if (this.bus.addMemory(this.addrRAM, this.sizeRAM, Memory.TYPE.RAM)) {
if (this.bus.addMemory(this.addrRAM, this.sizeRAM, Memory8080.TYPE.RAM)) {
this.fAllocated = true;
}
}
@ -145,12 +145,12 @@ RAM.prototype.reset = function()
/**
* save()
*
* This implements save support for the RAM component.
* This implements save support for the RAM8080 component.
*
* @this {RAM}
* @this {RAM8080}
* @return {Object}
*/
RAM.prototype.save = function()
RAM8080.prototype.save = function()
{
return null;
};
@ -158,39 +158,39 @@ RAM.prototype.save = function()
/**
* restore(data)
*
* This implements restore support for the RAM component.
* This implements restore support for the RAM8080 component.
*
* @this {RAM}
* @this {RAM8080}
* @param {Object} data
* @return {boolean} true if successful, false if failure
*/
RAM.prototype.restore = function(data)
RAM8080.prototype.restore = function(data)
{
return true;
};
/**
* RAM.init()
* RAM8080.init()
*
* This function operates on every HTML element of class "ram", extracting the
* JSON-encoded parameters for the RAM constructor from the element's "data-value"
* attribute, invoking the constructor to create a RAM component, and then binding
* JSON-encoded parameters for the RAM8080 constructor from the element's "data-value"
* attribute, invoking the constructor to create a RAM8080 component, and then binding
* any associated HTML controls to the new component.
*/
RAM.init = function()
RAM8080.init = function()
{
var aeRAM = Component.getElementsByClass(document, PC8080.APPCLASS, "ram");
for (var iRAM = 0; iRAM < aeRAM.length; iRAM++) {
var eRAM = aeRAM[iRAM];
var parmsRAM = Component.getComponentParms(eRAM);
var ram = new RAM(parmsRAM);
var ram = new RAM8080(parmsRAM);
Component.bindComponentControls(ram, eRAM, PC8080.APPCLASS);
}
};
/*
* Initialize all the RAM modules on the page.
* Initialize all the RAM8080 modules on the page.
*/
web.onInit(RAM.init);
web.onInit(RAM8080.init);
if (NODE) module.exports = RAM;
if (NODE) module.exports = RAM8080;

View file

@ -36,14 +36,14 @@ if (NODE) {
var web = require("../../shared/lib/weblib");
var DumpAPI = require("../../shared/lib/dumpapi");
var Component = require("../../shared/lib/component");
var Memory = require("./memory");
var CPUDef = require("./cpudef");
var CPUDef8080 = require("./cpudef");
var Memory8080 = require("./memory");
}
/**
* ROM(parmsROM)
* ROM8080(parmsROM)
*
* The ROM component expects the following (parmsROM) properties:
* The ROM8080 component expects the following (parmsROM) properties:
*
* addr: physical address of ROM
* size: amount of ROM, in bytes
@ -68,9 +68,9 @@ if (NODE) {
* @extends Component
* @param {Object} parmsROM
*/
function ROM(parmsROM)
function ROM8080(parmsROM)
{
Component.call(this, "ROM", parmsROM, ROM);
Component.call(this, "ROM", parmsROM, ROM8080);
this.abROM = null;
this.addrROM = parmsROM['addr'];
@ -112,9 +112,9 @@ function ROM(parmsROM)
}
}
Component.subclass(ROM);
Component.subclass(ROM8080);
ROM.CPM = {
ROM8080.CPM = {
BIOS: {
VECTOR: 0x0000
},
@ -136,7 +136,7 @@ ROM.CPM = {
}
};
ROM.CPM.VECTORS = [ROM.CPM.BIOS.VECTOR, ROM.CPM.BDOS.VECTOR];
ROM8080.CPM.VECTORS = [ROM8080.CPM.BIOS.VECTOR, ROM8080.CPM.BDOS.VECTOR];
/*
* NOTE: There's currently no need for this component to have a reset() function, since
@ -154,13 +154,13 @@ ROM.CPM.VECTORS = [ROM.CPM.BIOS.VECTOR, ROM.CPM.BDOS.VECTOR];
/**
* initBus(cmp, bus, cpu, dbg)
*
* @this {ROM}
* @param {Computer} cmp
* @param {Bus} bus
* @param {CPUState} cpu
* @param {Debugger} dbg
* @this {ROM8080}
* @param {Computer8080} cmp
* @param {Bus8080} bus
* @param {CPUState8080} cpu
* @param {Debugger8080} dbg
*/
ROM.prototype.initBus = function(cmp, bus, cpu, dbg)
ROM8080.prototype.initBus = function(cmp, bus, cpu, dbg)
{
this.bus = bus;
this.cpu = cpu;
@ -171,12 +171,12 @@ ROM.prototype.initBus = function(cmp, bus, cpu, dbg)
/**
* powerUp(data, fRepower)
*
* @this {ROM}
* @this {ROM8080}
* @param {Object|null} data
* @param {boolean} [fRepower]
* @return {boolean} true if successful, false if failure
*/
ROM.prototype.powerUp = function(data, fRepower)
ROM8080.prototype.powerUp = function(data, fRepower)
{
if (this.aSymbols) {
if (this.dbg) {
@ -199,12 +199,12 @@ ROM.prototype.powerUp = function(data, fRepower)
* useful down the road, like user-defined symbols (ie, symbols that the Debugger may have
* created, above and beyond those symbols we automatically loaded, if any, along with the ROM).
*
* @this {ROM}
* @this {ROM8080}
* @param {boolean} [fSave]
* @param {boolean} [fShutdown]
* @return {Object|boolean} component state if fSave; otherwise, true if successful, false if failure
*/
ROM.prototype.powerDown = function(fSave, fShutdown)
ROM8080.prototype.powerDown = function(fSave, fShutdown)
{
return true;
};
@ -212,12 +212,12 @@ ROM.prototype.powerDown = function(fSave, fShutdown)
/**
* doneLoad(sURL, sROMData, nErrorCode)
*
* @this {ROM}
* @this {ROM8080}
* @param {string} sURL
* @param {string} sROMData
* @param {number} nErrorCode (response from server if anything other than 200)
*/
ROM.prototype.doneLoad = function(sURL, sROMData, nErrorCode)
ROM8080.prototype.doneLoad = function(sURL, sROMData, nErrorCode)
{
if (nErrorCode) {
this.notice("Unable to load system ROM (error " + nErrorCode + ": " + sURL + ")");
@ -291,9 +291,9 @@ ROM.prototype.doneLoad = function(sURL, sROMData, nErrorCode)
* until after initBus() has received the Bus component AND doneLoad() has received the abROM data. When both
* those criteria are satisfied, the component becomes "ready".
*
* @this {ROM}
* @this {ROM8080}
*/
ROM.prototype.copyROM = function()
ROM8080.prototype.copyROM = function()
{
if (!this.isReady()) {
if (!this.sFilePath) {
@ -346,13 +346,13 @@ ROM.prototype.copyROM = function()
/**
* addROM(addr)
*
* @this {ROM}
* @this {ROM8080}
* @param {number} addr
* @return {boolean}
*/
ROM.prototype.addROM = function(addr)
ROM8080.prototype.addROM = function(addr)
{
if (this.bus.addMemory(addr, this.sizeROM, this.fWritable? Memory.TYPE.RAM : Memory.TYPE.ROM)) {
if (this.bus.addMemory(addr, this.sizeROM, this.fWritable? Memory8080.TYPE.RAM : Memory8080.TYPE.ROM)) {
if (DEBUG) this.log("addROM(): copying ROM to " + str.toHexLong(addr) + " (" + str.toHexLong(this.abROM.length) + " bytes)");
var i;
for (i = 0; i < this.abROM.length; i++) {
@ -365,8 +365,8 @@ ROM.prototype.addROM = function(addr)
* (namely, 0x0000, which is the CP/M reset vector, and 0x0005, which is the CP/M system call vector) and
* then telling the CPU to call us whenever a HLT occurs, so we can check PC for one of these addresses.
*/
for (i = 0; i < ROM.CPM.VECTORS.length; i++) {
this.bus.setByteDirect(ROM.CPM.VECTORS[i], CPUDef.OPCODE.HLT);
for (i = 0; i < ROM8080.CPM.VECTORS.length; i++) {
this.bus.setByteDirect(ROM8080.CPM.VECTORS[i], CPUDef8080.OPCODE.HLT);
}
this.cpu.addHaltCheck(function(rom) {
@ -388,24 +388,24 @@ ROM.prototype.addROM = function(addr)
/**
* checkCPMVector(addr)
*
* @this {ROM}
* @this {ROM8080}
* @param {number} addr (of the HLT opcode)
* @return {boolean} true if special processing performed, false if not
*/
ROM.prototype.checkCPMVector = function(addr)
ROM8080.prototype.checkCPMVector = function(addr)
{
var i = ROM.CPM.VECTORS.indexOf(addr);
var i = ROM8080.CPM.VECTORS.indexOf(addr);
if (i >= 0) {
var fCPM = false;
var cpu = this.cpu;
var dbg = this.dbg;
if (addr == ROM.CPM.BDOS.VECTOR) {
if (addr == ROM8080.CPM.BDOS.VECTOR) {
fCPM = true;
switch(cpu.regC) {
case ROM.CPM.BDOS.FUNC.CON_WRITE:
case ROM8080.CPM.BDOS.FUNC.CON_WRITE:
this.writeCPMString(this.getCPMChar(cpu.regE));
break;
case ROM.CPM.BDOS.FUNC.STR_WRITE:
case ROM8080.CPM.BDOS.FUNC.STR_WRITE:
this.writeCPMString(this.getCPMString(cpu.getDE(), '$'));
break;
default:
@ -414,7 +414,7 @@ ROM.prototype.checkCPMVector = function(addr)
}
}
if (fCPM) {
CPUDef.opRET.call(cpu); // for recognized calls, automatically return
CPUDef8080.opRET.call(cpu); // for recognized calls, automatically return
}
else if (dbg) {
this.println("\nCP/M vector " + str.toHexWord(addr));
@ -430,11 +430,11 @@ ROM.prototype.checkCPMVector = function(addr)
/**
* getCPMChar(ch)
*
* @this {ROM}
* @this {ROM8080}
* @param {number} ch
* @return {string}
*/
ROM.prototype.getCPMChar = function(ch)
ROM8080.prototype.getCPMChar = function(ch)
{
return String.fromCharCode(ch);
};
@ -442,12 +442,12 @@ ROM.prototype.getCPMChar = function(ch)
/**
* getCPMString(addr, chEnd)
*
* @this {ROM}
* @this {ROM8080}
* @param {number} addr (of a string)
* @param {string|number} [chEnd] (terminating character, default is 0)
* @return {string}
*/
ROM.prototype.getCPMString = function(addr, chEnd)
ROM8080.prototype.getCPMString = function(addr, chEnd)
{
var s = "";
var cchMax = 255;
@ -463,10 +463,10 @@ ROM.prototype.getCPMString = function(addr, chEnd)
/**
* writeCPMString(s)
*
* @this {ROM}
* @this {ROM8080}
* @param {string} s
*/
ROM.prototype.writeCPMString = function(s)
ROM8080.prototype.writeCPMString = function(s)
{
s = s.replace(/\r/g, '');
if (this.controlPrint) {
@ -485,37 +485,37 @@ ROM.prototype.writeCPMString = function(s)
* Now that the Bus component provides low-level getMemoryBlocks() and setMemoryBlocks() methods
* to manually get and set the blocks of any memory range, it is now possible to create true aliases.
*
* @this {ROM}
* @this {ROM8080}
* @param {number} addr
*/
ROM.prototype.cloneROM = function(addr)
ROM8080.prototype.cloneROM = function(addr)
{
var aBlocks = this.bus.getMemoryBlocks(this.addrROM, this.sizeROM);
this.bus.setMemoryBlocks(addr, this.sizeROM, aBlocks);
};
/**
* ROM.init()
* ROM8080.init()
*
* This function operates on every HTML element of class "rom", extracting the
* JSON-encoded parameters for the ROM constructor from the element's "data-value"
* attribute, invoking the constructor to create a ROM component, and then binding
* JSON-encoded parameters for the ROM8080 constructor from the element's "data-value"
* attribute, invoking the constructor to create a ROM8080 component, and then binding
* any associated HTML controls to the new component.
*/
ROM.init = function()
ROM8080.init = function()
{
var aeROM = Component.getElementsByClass(document, PC8080.APPCLASS, "rom");
for (var iROM = 0; iROM < aeROM.length; iROM++) {
var eROM = aeROM[iROM];
var parmsROM = Component.getComponentParms(eROM);
var rom = new ROM(parmsROM);
var rom = new ROM8080(parmsROM);
Component.bindComponentControls(rom, eROM, PC8080.APPCLASS);
}
};
/*
* Initialize all the ROM modules on the page.
* Initialize all the ROM8080 modules on the page.
*/
web.onInit(ROM.init);
web.onInit(ROM8080.init);
if (NODE) module.exports = ROM;
if (NODE) module.exports = ROM8080;

View file

@ -35,14 +35,14 @@ if (NODE) {
var str = require("../../shared/lib/strlib");
var web = require("../../shared/lib/weblib");
var Component = require("../../shared/lib/component");
var Messages = require("./messages");
var State = require("./state");
var Messages8080= require("./messages");
var State8080 = require("./state");
}
/**
* SerialPort(parmsSerial)
* SerialPort8080(parmsSerial)
*
* The SerialPort component has the following component-specific (parmsSerial) properties:
* The SerialPort8080 component has the following component-specific (parmsSerial) properties:
*
* adapter: 0 if not defined
*
@ -62,7 +62,7 @@ if (NODE) {
* @extends Component
* @param {Object} parmsSerial
*/
function SerialPort(parmsSerial) {
function SerialPort8080(parmsSerial) {
this.iAdapter = +parmsSerial['adapter'];
@ -103,7 +103,7 @@ function SerialPort(parmsSerial) {
this.charBOL = parmsSerial['charBOL'];
this.iLogicalCol = 0;
Component.call(this, "SerialPort", parmsSerial, SerialPort, Messages.SERIAL);
Component.call(this, "SerialPort", parmsSerial, SerialPort8080, Messages8080.SERIAL);
var sBinding = parmsSerial['binding'];
if (sBinding == "console") {
@ -112,7 +112,7 @@ function SerialPort(parmsSerial) {
/*
* NOTE: If sBinding is not the name of a valid Control Panel DOM element, this call does nothing.
*/
Component.bindExternalControl(this, sBinding, SerialPort.sIOBuffer);
Component.bindExternalControl(this, sBinding, SerialPort8080.sIOBuffer);
}
/*
@ -130,7 +130,7 @@ function SerialPort(parmsSerial) {
}
/*
* class SerialPort
* class SerialPort8080
* property {number} iAdapter
* property {number} portBase
* property {number} nIRQ
@ -146,9 +146,9 @@ function SerialPort(parmsSerial) {
* for third-party apps.
*/
Component.subclass(SerialPort);
Component.subclass(SerialPort8080);
SerialPort.UART8251 = {
SerialPort8080.UART8251 = {
/*
* Format of MODE byte written to CONTROL port 0x1
*/
@ -212,6 +212,8 @@ SerialPort.UART8251 = {
* 0xD 36 4800
* 0xE 18 9600 (default)
* 0xF 9 19200
*
* NOTE: This is a VT100-specific port and baud rate table.
*/
BAUDRATES: {
RECV_RATE: 0x0F,
@ -223,20 +225,20 @@ SerialPort.UART8251 = {
]
};
SerialPort.UART8251.INIT = [
SerialPort8080.UART8251.INIT = [
false,
0,
0,
SerialPort.UART8251.STATUS.INIT,
SerialPort.UART8251.MODE.INIT,
SerialPort.UART8251.COMMAND.INIT,
SerialPort.UART8251.BAUDRATES.INIT
SerialPort8080.UART8251.STATUS.INIT,
SerialPort8080.UART8251.MODE.INIT,
SerialPort8080.UART8251.COMMAND.INIT,
SerialPort8080.UART8251.BAUDRATES.INIT
];
/*
* Internal name used for the I/O buffer control, if any, that we bind to the SerialPort.
* Internal name used for the I/O buffer control, if any, that we bind to a SerialPort8080.
*
* Alternatively, if SerialPort wants to use another component's control (eg, the Panel's
* Alternatively, if SerialPort8080 wants to use another component's control (eg, the Panel's
* "print" control), it can specify the name of that control with the 'binding' property.
*
* For that binding to succeed, we also need to know the target component; for now, that's
@ -244,24 +246,24 @@ SerialPort.UART8251.INIT = [
* upon initializing before we do, but it would be a simple matter to include a component type
* or ID as part of the 'binding' property as well, if we need more flexibility later.
*/
SerialPort.sIOBuffer = "buffer";
SerialPort8080.sIOBuffer = "buffer";
/**
* setBinding(sHTMLType, sBinding, control, sValue)
*
* @this {SerialPort}
* @this {SerialPort8080}
* @param {string|null} sHTMLType is the type of the HTML control (eg, "button", "list", "text", "submit", "textarea", "canvas")
* @param {string} sBinding is the value of the 'binding' parameter stored in the HTML control's "data-value" attribute (eg, "buffer")
* @param {Object} control is the HTML control DOM object (eg, HTMLButtonElement)
* @param {string} [sValue] optional data value
* @return {boolean} true if binding was successful, false if unrecognized binding request
*/
SerialPort.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
SerialPort8080.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
{
var serial = this;
switch (sBinding) {
case SerialPort.sIOBuffer:
case SerialPort8080.sIOBuffer:
this.bindings[sBinding] = this.controlIOBuffer = control;
/*
@ -368,13 +370,13 @@ SerialPort.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
/**
* initBus(cmp, bus, cpu, dbg)
*
* @this {SerialPort}
* @param {Computer} cmp
* @param {Bus} bus
* @param {CPUState} cpu
* @param {Debugger} dbg
* @this {SerialPort8080}
* @param {Computer8080} cmp
* @param {Bus8080} bus
* @param {CPUState8080} cpu
* @param {Debugger8080} dbg
*/
SerialPort.prototype.initBus = function(cmp, bus, cpu, dbg)
SerialPort8080.prototype.initBus = function(cmp, bus, cpu, dbg)
{
this.cmp = cmp;
this.bus = bus;
@ -389,10 +391,10 @@ SerialPort.prototype.initBus = function(cmp, bus, cpu, dbg)
serial.transmitData();
});
this.chipset = /** @type {ChipSet} */ (cmp.getMachineComponent("ChipSet"));
this.chipset = /** @type {ChipSet8080} */ (cmp.getMachineComponent("ChipSet"));
bus.addPortInputTable(this, SerialPort.aPortInput, this.portBase);
bus.addPortOutputTable(this, SerialPort.aPortOutput, this.portBase);
bus.addPortInputTable(this, SerialPort8080.aPortInput, this.portBase);
bus.addPortOutputTable(this, SerialPort8080.aPortOutput, this.portBase);
this.initConnection();
@ -413,9 +415,9 @@ SerialPort.prototype.initBus = function(cmp, bus, cpu, dbg)
* performs its own initConnection(), it will find our receiveByte(b) function, at which point communication in both
* directions should be established.
*
* @this {SerialPort}
* @this {SerialPort8080}
*/
SerialPort.prototype.initConnection = function()
SerialPort8080.prototype.initConnection = function()
{
var sConnection = this.cmp.getMachineParm("connection");
if (sConnection) {
@ -439,12 +441,12 @@ SerialPort.prototype.initConnection = function()
/**
* powerUp(data, fRepower)
*
* @this {SerialPort}
* @this {SerialPort8080}
* @param {Object|null} data
* @param {boolean} [fRepower]
* @return {boolean} true if successful, false if failure
*/
SerialPort.prototype.powerUp = function(data, fRepower)
SerialPort8080.prototype.powerUp = function(data, fRepower)
{
if (!fRepower) {
if (!data || !this.restore) {
@ -459,12 +461,12 @@ SerialPort.prototype.powerUp = function(data, fRepower)
/**
* powerDown(fSave, fShutdown)
*
* @this {SerialPort}
* @this {SerialPort8080}
* @param {boolean} [fSave]
* @param {boolean} [fShutdown]
* @return {Object|boolean} component state if fSave; otherwise, true if successful, false if failure
*/
SerialPort.prototype.powerDown = function(fSave, fShutdown)
SerialPort8080.prototype.powerDown = function(fSave, fShutdown)
{
return fSave? this.save() : true;
};
@ -472,9 +474,9 @@ SerialPort.prototype.powerDown = function(fSave, fShutdown)
/**
* reset()
*
* @this {SerialPort}
* @this {SerialPort8080}
*/
SerialPort.prototype.reset = function()
SerialPort8080.prototype.reset = function()
{
this.initState();
};
@ -482,12 +484,12 @@ SerialPort.prototype.reset = function()
/**
* save()
*
* This implements save support for the SerialPort component.
* This implements save support for the SerialPort8080 component.
*
* @this {SerialPort}
* @this {SerialPort8080}
* @return {Object}
*/
SerialPort.prototype.save = function()
SerialPort8080.prototype.save = function()
{
var state = new State(this);
state.set(0, this.saveRegisters());
@ -497,13 +499,13 @@ SerialPort.prototype.save = function()
/**
* restore(data)
*
* This implements restore support for the SerialPort component.
* This implements restore support for the SerialPort8080 component.
*
* @this {SerialPort}
* @this {SerialPort8080}
* @param {Object} data
* @return {boolean} true if successful, false if failure
*/
SerialPort.prototype.restore = function(data)
SerialPort8080.prototype.restore = function(data)
{
return this.initState(data[0]);
};
@ -511,15 +513,15 @@ SerialPort.prototype.restore = function(data)
/**
* initState(data)
*
* @this {SerialPort}
* @this {SerialPort8080}
* @param {Array} [data]
* @return {boolean} true if successful, false if failure
*/
SerialPort.prototype.initState = function(data)
SerialPort8080.prototype.initState = function(data)
{
var i = 0;
if (data === undefined) {
data = SerialPort.UART8251.INIT;
data = SerialPort8080.UART8251.INIT;
}
this.fReady = data[i++];
this.bDataIn = data[i++];
@ -534,10 +536,10 @@ SerialPort.prototype.initState = function(data)
/**
* saveRegisters()
*
* @this {SerialPort}
* @this {SerialPort8080}
* @return {Array}
*/
SerialPort.prototype.saveRegisters = function()
SerialPort8080.prototype.saveRegisters = function()
{
var i = 0;
var data = [];
@ -554,18 +556,18 @@ SerialPort.prototype.saveRegisters = function()
/**
* getBaudTimeout(maskRate)
*
* @this {SerialPort}
* @param {number} maskRate (either SerialPort.UART8251.BAUDRATES.RECV_RATE or SerialPort.UART8251.BAUDRATES.XMIT_RATE)
* @this {SerialPort8080}
* @param {number} maskRate (either SerialPort8080.UART8251.BAUDRATES.RECV_RATE or SerialPort8080.UART8251.BAUDRATES.XMIT_RATE)
* @return {number} (number of milliseconds per byte)
*/
SerialPort.prototype.getBaudTimeout = function(maskRate)
SerialPort8080.prototype.getBaudTimeout = function(maskRate)
{
var indexRate = (this.bBaudRates & maskRate);
if (!(maskRate & 0xf)) indexRate >>= 4;
var nBaud = SerialPort.UART8251.BAUDTABLE[indexRate];
var nBits = ((this.bMode & SerialPort.UART8251.MODE.DATA_BITS) >> 2) + 6; // includes an extra +1 for start bit
if (this.bMode & SerialPort.UART8251.MODE.PARITY_ENABLE) nBits++;
nBits += ((((this.bMode & SerialPort.UART8251.MODE.STOP_BITS) >> 6) + 1) >> 1);
var nBaud = SerialPort8080.UART8251.BAUDTABLE[indexRate];
var nBits = ((this.bMode & SerialPort8080.UART8251.MODE.DATA_BITS) >> 2) + 6; // includes an extra +1 for start bit
if (this.bMode & SerialPort8080.UART8251.MODE.PARITY_ENABLE) nBits++;
nBits += ((((this.bMode & SerialPort8080.UART8251.MODE.STOP_BITS) >> 6) + 1) >> 1);
var nBytesPerSecond = Math.round(nBaud / nBits);
return 1000 / nBytesPerSecond;
};
@ -573,16 +575,16 @@ SerialPort.prototype.getBaudTimeout = function(maskRate)
/**
* receiveByte(b)
*
* @this {SerialPort}
* @this {SerialPort8080}
* @param {number} b
* @return {boolean}
*/
SerialPort.prototype.receiveByte = function(b)
SerialPort8080.prototype.receiveByte = function(b)
{
this.printMessage("receiveByte(" + str.toHexByte(b) + "), status=" + str.toHexByte(this.bStatus));
if (!(this.bStatus & SerialPort.UART8251.STATUS.RECV_FULL)) {
if (!(this.bStatus & SerialPort8080.UART8251.STATUS.RECV_FULL)) {
this.bDataIn = b;
this.bStatus |= SerialPort.UART8251.STATUS.RECV_FULL;
this.bStatus |= SerialPort8080.UART8251.STATUS.RECV_FULL;
this.cpu.requestINTR(this.nIRQ);
return true;
}
@ -598,10 +600,10 @@ SerialPort.prototype.receiveByte = function(b)
* of a string. When we're called by another component, data will typically be a number (ie, byte). If no
* data is specified at all, then all we do is "clock" any remaining data into the receiver.
*
* @this {SerialPort}
* @this {SerialPort8080}
* @param {number|string|undefined} [data]
*/
SerialPort.prototype.receiveData = function(data)
SerialPort8080.prototype.receiveData = function(data)
{
if (data != null) {
if (typeof data != "number") {
@ -615,7 +617,7 @@ SerialPort.prototype.receiveData = function(data)
this.sDataReceived = this.sDataReceived.substr(1);
}
if (this.sDataReceived && this.cpu) {
this.cpu.setTimer(this.timerReceiveNext, this.getBaudTimeout(SerialPort.UART8251.BAUDRATES.RECV_RATE));
this.cpu.setTimer(this.timerReceiveNext, this.getBaudTimeout(SerialPort8080.UART8251.BAUDRATES.RECV_RATE));
}
}
};
@ -623,11 +625,11 @@ SerialPort.prototype.receiveData = function(data)
/**
* transmitByte(b)
*
* @this {SerialPort}
* @this {SerialPort8080}
* @param {number} b
* @return {boolean} true if transmitted, false if not
*/
SerialPort.prototype.transmitByte = function(b)
SerialPort8080.prototype.transmitByte = function(b)
{
var fTransmitted = false;
@ -688,51 +690,51 @@ SerialPort.prototype.transmitByte = function(b)
* When timerTransmitNext fires, we have honored the programmed XMIT_RATE period, so we can
* set XMIT_READY (and XMIT_EMPTY), which signals the firmware that another byte can be transmitted.
*
* @this {SerialPort}
* @this {SerialPort8080}
*/
SerialPort.prototype.transmitData = function()
SerialPort8080.prototype.transmitData = function()
{
this.bStatus |= (SerialPort.UART8251.STATUS.XMIT_READY | SerialPort.UART8251.STATUS.XMIT_EMPTY);
this.bStatus |= (SerialPort8080.UART8251.STATUS.XMIT_READY | SerialPort8080.UART8251.STATUS.XMIT_EMPTY);
};
/**
* isTransmitterReady()
*
* Called whenever a ChipSet circuit needs the SerialPort UART's transmitter status.
* Called whenever a ChipSet circuit needs the SerialPort8080 UART's transmitter status.
*
* @this {SerialPort}
* @this {SerialPort8080}
* @return {boolean} (true if ready, false if not)
*/
SerialPort.prototype.isTransmitterReady = function()
SerialPort8080.prototype.isTransmitterReady = function()
{
return !!(this.bStatus & SerialPort.UART8251.STATUS.XMIT_READY);
return !!(this.bStatus & SerialPort8080.UART8251.STATUS.XMIT_READY);
};
/**
* inData(port, addrFrom)
*
* @this {SerialPort}
* @this {SerialPort8080}
* @param {number} port (0x0)
* @param {number} [addrFrom] (not defined whenever the Debugger tries to read the specified port)
* @return {number} simulated port value
*/
SerialPort.prototype.inData = function(port, addrFrom)
SerialPort8080.prototype.inData = function(port, addrFrom)
{
var b = this.bDataIn;
this.printMessageIO(port, null, addrFrom, "DATA", b);
this.bStatus &= ~SerialPort.UART8251.STATUS.RECV_FULL;
this.bStatus &= ~SerialPort8080.UART8251.STATUS.RECV_FULL;
return b;
};
/**
* inControl(port, addrFrom)
*
* @this {SerialPort}
* @this {SerialPort8080}
* @param {number} port (0x1)
* @param {number} [addrFrom] (not defined whenever the Debugger tries to read the specified port)
* @return {number} simulated port value
*/
SerialPort.prototype.inControl = function(port, addrFrom)
SerialPort8080.prototype.inControl = function(port, addrFrom)
{
var b = this.bStatus;
this.printMessageIO(port, null, addrFrom, "STATUS", b);
@ -742,22 +744,22 @@ SerialPort.prototype.inControl = function(port, addrFrom)
/**
* outData(port, bOut, addrFrom)
*
* @this {SerialPort}
* @this {SerialPort8080}
* @param {number} port (0x0)
* @param {number} bOut
* @param {number} [addrFrom] (not defined whenever the Debugger tries to write the specified port)
*/
SerialPort.prototype.outData = function(port, bOut, addrFrom)
SerialPort8080.prototype.outData = function(port, bOut, addrFrom)
{
this.printMessageIO(port, bOut, addrFrom, "DATA");
this.bDataOut = bOut;
this.bStatus &= ~(SerialPort.UART8251.STATUS.XMIT_READY | SerialPort.UART8251.STATUS.XMIT_EMPTY);
this.bStatus &= ~(SerialPort8080.UART8251.STATUS.XMIT_READY | SerialPort8080.UART8251.STATUS.XMIT_EMPTY);
/*
* If we're transmitting to a virtual device that has no measurable delay, this code may clear XMIT_READY
* too quickly.
*
* if (this.transmitByte(bOut)) {
* this.bStatus |= (SerialPort.UART8251.STATUS.XMIT_READY | SerialPort.UART8251.STATUS.XMIT_EMPTY);
* this.bStatus |= (SerialPort8080.UART8251.STATUS.XMIT_READY | SerialPort8080.UART8251.STATUS.XMIT_EMPTY);
* }
*
* A better solution is to arm a timer based on the XMIT_RATE baud rate, and clear the above bits when that
@ -765,7 +767,7 @@ SerialPort.prototype.outData = function(port, bOut, addrFrom)
*/
this.transmitByte(bOut);
if (this.cpu) {
this.cpu.setTimer(this.timerTransmitNext, this.getBaudTimeout(SerialPort.UART8251.BAUDRATES.XMIT_RATE));
this.cpu.setTimer(this.timerTransmitNext, this.getBaudTimeout(SerialPort8080.UART8251.BAUDRATES.XMIT_RATE));
}
};
@ -777,12 +779,12 @@ SerialPort.prototype.outData = function(port, bOut, addrFrom)
* has received that initial byte, the device is marked "ready", and all further bytes are
* interpreted as COMMAND bytes (until/unless a COMMAND byte with the INTERNAL_RESET bit is set).
*
* @this {SerialPort}
* @this {SerialPort8080}
* @param {number} port (0x1)
* @param {number} bOut
* @param {number} [addrFrom] (not defined whenever the Debugger tries to write the specified port)
*/
SerialPort.prototype.outControl = function(port, bOut, addrFrom)
SerialPort8080.prototype.outControl = function(port, bOut, addrFrom)
{
this.printMessageIO(port, bOut, addrFrom, "CONTROL");
if (!this.fReady) {
@ -790,7 +792,7 @@ SerialPort.prototype.outControl = function(port, bOut, addrFrom)
this.fReady = true;
} else {
this.bCommand = bOut;
if (this.bCommand & SerialPort.UART8251.COMMAND.INTERNAL_RESET) {
if (this.bCommand & SerialPort8080.UART8251.COMMAND.INTERNAL_RESET) {
this.fReady = false;
}
}
@ -799,12 +801,12 @@ SerialPort.prototype.outControl = function(port, bOut, addrFrom)
/**
* outBaudRates(port, bOut, addrFrom)
*
* @this {SerialPort}
* @this {SerialPort8080}
* @param {number} port (0x2)
* @param {number} bOut
* @param {number} [addrFrom] (not defined whenever the Debugger tries to write the specified port)
*/
SerialPort.prototype.outBaudRates = function(port, bOut, addrFrom)
SerialPort8080.prototype.outBaudRates = function(port, bOut, addrFrom)
{
this.printMessageIO(port, bOut, addrFrom, "BAUDRATES");
this.bBaudRates = bOut;
@ -813,43 +815,43 @@ SerialPort.prototype.outBaudRates = function(port, bOut, addrFrom)
/*
* Port input notification table
*/
SerialPort.aPortInput = {
0x0: SerialPort.prototype.inData,
0x1: SerialPort.prototype.inControl
SerialPort8080.aPortInput = {
0x0: SerialPort8080.prototype.inData,
0x1: SerialPort8080.prototype.inControl
};
/*
* Port output notification table
*/
SerialPort.aPortOutput = {
0x0: SerialPort.prototype.outData,
0x1: SerialPort.prototype.outControl,
0x2: SerialPort.prototype.outBaudRates
SerialPort8080.aPortOutput = {
0x0: SerialPort8080.prototype.outData,
0x1: SerialPort8080.prototype.outControl,
0x2: SerialPort8080.prototype.outBaudRates
};
/**
* SerialPort.init()
* SerialPort8080.init()
*
* This function operates on every HTML element of class "serial", extracting the
* JSON-encoded parameters for the SerialPort constructor from the element's "data-value"
* attribute, invoking the constructor to create a SerialPort component, and then binding
* JSON-encoded parameters for the SerialPort8080 constructor from the element's "data-value"
* attribute, invoking the constructor to create a SerialPort8080 component, and then binding
* any associated HTML controls to the new component.
*/
SerialPort.init = function()
SerialPort8080.init = function()
{
var aeSerial = Component.getElementsByClass(document, PC8080.APPCLASS, "serial");
for (var iSerial = 0; iSerial < aeSerial.length; iSerial++) {
var eSerial = aeSerial[iSerial];
var parmsSerial = Component.getComponentParms(eSerial);
var serial = new SerialPort(parmsSerial);
var serial = new SerialPort8080(parmsSerial);
Component.bindComponentControls(serial, eSerial, PC8080.APPCLASS);
}
};
/*
* Initialize every SerialPort module on the page.
* Initialize every SerialPort8080 module on the page.
*/
web.onInit(SerialPort.init);
web.onInit(SerialPort8080.init);
if (NODE) module.exports = SerialPort;
if (NODE) module.exports = SerialPort8080;

View file

@ -1,396 +0,0 @@
/**
* @fileoverview The State class used by PCjs machines.
* @author <a href="mailto:Jeff@pcjs.org">Jeff Parsons</a>
* @version 1.0
* Created 2016-Apr-19
*
* Copyright © 2012-2016 Jeff Parsons <Jeff@pcjs.org>
*
* This file is part of PCjs, a computer emulation software project at <http://pcjs.org/>.
*
* PCjs is free software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* PCjs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCjs. If not,
* see <http://www.gnu.org/licenses/gpl.html>.
*
* You are required to include the above copyright notice in every source code file of every
* copy or modified version of this work, and to display that copyright notice on every screen
* that loads or runs any version of this software (see COPYRIGHT in /modules/shared/lib/defines.js).
*
* Some PCjs files also attempt to load external resource files, such as character-image files,
* ROM files, and disk image files. Those external resource files are not considered part of PCjs
* for purposes of the GNU General Public License, and the author does not claim any copyright
* as to their contents.
*/
"use strict";
if (NODE) {
var web = require("./../../shared/lib/weblib");
var Component = require("./../../shared/lib/component");
var Messages = require("./messages");
}
/**
* State(component, sVersion, sSuffix)
*
* State objects are used by components to save/restore their state.
*
* During a save operation, components add data to a State object via set(),
* and then return the resulting data using data().
*
* During a restore operation, the Computer component passes the results of each
* data() call back to the originating component.
*
* WARNING: Since State objects are low-level objects that have no UI requirements,
* they do not inherit from the Component class, so you should only use class methods
* of Component, such as Component.assert(), or Debugger methods if the Debugger
* is available.
*
* @constructor
* @param {Component} component
* @param {string} [sVersion] is used to append a major version number to the key
* @param {string} [sSuffix] is used to append any additional suffixes to the key
*/
function State(component, sVersion, sSuffix) {
this.id = component.id;
this.key = State.key(component, sVersion, sSuffix);
this.dbg = component.dbg;
this.unload(component.parms);
}
/**
* State.key(component, sVersion, sSuffix)
*
* This encapsulates the key generation code.
*
* @param {Component} component
* @param {string} [sVersion] is used to append a major version number to the key
* @param {string} [sSuffix] is used to append any additional suffixes to the key
* @return {string} key
*/
State.key = function(component, sVersion, sSuffix) {
var key = component.id;
if (sVersion) {
var i = sVersion.indexOf('.');
if (i > 0) key += ".v" + sVersion.substr(0, i);
}
if (sSuffix) {
key += "." + sSuffix;
}
return key;
};
/**
* State.compress(aSrc)
*
* @param {Array.<number>|null} aSrc
* @return {Array.<number>|null} is either the original array (aSrc), or a smaller array of "count, value" pairs (aComp)
*/
State.compress = function(aSrc) {
if (aSrc) {
var iSrc = 0;
var iComp = 0;
var aComp = [];
while (iSrc < aSrc.length) {
var n = aSrc[iSrc];
Component.assert(n !== undefined);
var iCompare = iSrc + 1;
while (iCompare < aSrc.length && aSrc[iCompare] === n) iCompare++;
aComp[iComp++] = iCompare - iSrc;
aComp[iComp++] = n;
iSrc = iCompare;
}
if (aComp.length < aSrc.length) return aComp;
}
return aSrc;
};
/**
* State.decompress(aComp)
*
* @param {Array.<number>} aComp
* @param {number} nLength is expected length of decompressed data
* @return {Array.<number>}
*/
State.decompress = function(aComp, nLength) {
var iDst = 0;
var aDst = new Array(nLength);
var iComp = 0;
while (iComp < aComp.length - 1) {
var c = aComp[iComp++];
var n = aComp[iComp++];
while (c--) {
aDst[iDst++] = n;
}
}
Component.assert(aDst.length == nLength);
return aDst;
};
/**
* State.compressEvenOdd(aSrc)
*
* This is a very simple variation on compress() that compresses all the EVEN elements of aSrc first,
* followed by all the ODD elements. This tends to work better on EGA video memory, because when odd/even
* addressing is enabled (eg, for text modes), the DWORD values tend to alternate, which is the worst case
* for compress(), but the best case for compressEvenOdd().
*
* One wrinkle we support: if the first element is uninitialized, then we assume the entire array is undefined,
* and return an empty compressed array. Conversely, decompressEvenOdd() will take an empty compressed array
* and return an uninitialized array.
*
* @param {Array.<number>|null} aSrc
* @return {Array.<number>|null} is either the original array (aSrc), or a smaller array of "count, value" pairs (aComp)
*/
State.compressEvenOdd = function(aSrc) {
if (aSrc) {
var iComp = 0, aComp = [];
if (aSrc[0] !== undefined) {
for (var off = 0; off < 2; off++) {
var iSrc = off;
while (iSrc < aSrc.length) {
var n = aSrc[iSrc];
var iCompare = iSrc + 2;
while (iCompare < aSrc.length && aSrc[iCompare] === n) iCompare += 2;
aComp[iComp++] = (iCompare - iSrc) >> 1;
aComp[iComp++] = n;
iSrc = iCompare;
}
}
}
if (aComp.length < aSrc.length) return aComp;
}
return aSrc;
};
/**
* State.decompressEvenOdd(aComp, nLength)
*
* This is the counterpart to compressEvenOdd(). Note that because there's nothing in the compressed sequence
* that differentiates a compress() sequence from a compressEvenOdd() sequence, you simply have to be consistent:
* if you used even/odd compression, then you must use even/odd decompression.
*
* @param {Array.<number>} aComp
* @param {number} nLength is expected length of decompressed data
* @return {Array.<number>}
*/
State.decompressEvenOdd = function(aComp, nLength) {
var iDst = 0;
var aDst = new Array(nLength);
var iComp = 0;
while (iComp < aComp.length - 1) {
var c = aComp[iComp++];
var n = aComp[iComp++];
while (c--) {
aDst[iDst] = n;
iDst += 2;
}
/*
* The output of a "count,value" pair will never exceed the end of the output array, so as soon as we reach it
* the first time, we know it's time to switch to ODD elements, and as soon as we reach it again, we should be
* done.
*/
Component.assert(iDst <= nLength || iComp == aComp.length);
if (iDst == nLength) iDst = 1;
}
Component.assert(aDst.length == nLength);
return aDst;
};
State.prototype = {
constructor: State,
/**
* set(id, data)
*
* @this {State}
* @param {number|string} id
* @param {Object|string} data
*/
set: function(id, data) {
try {
this[this.id][id] = data;
} catch(e) {
Component.log(e.message);
}
},
/**
* get(id)
*
* @this {State}
* @param {number|string} id
* @return {Object|string|null}
*/
get: function(id) {
return this[this.id][id] || null;
},
/**
* value()
*
* Use this instead of data() if you haven't called parse() yet.
*
* @this {State}
* @return {string}
*/
value: function() {
return this[this.id];
},
/**
* data()
*
* @this {State}
* @return {Object}
*/
data: function() {
return this[this.id];
},
/**
* load(s)
*
* WARNING: Make sure you follow this call with either a call to parse() or unload(),
* because any stringified data that we've loaded isn't usable until it's been parsed.
*
* @this {State}
* @param {Object|string|null} [s]
* @return {boolean} true if state exists in localStorage, false if not
*/
load: function(s) {
if (s) {
this[this.id] = s;
this.fLoaded = true;
return true;
}
if (this.fLoaded) {
/*
* This is assumed to be a redundant load().
*/
return true;
}
if (web.hasLocalStorage()) {
s = web.getLocalStorageItem(this.key);
if (s) {
this[this.id] = s;
this.fLoaded = true;
if (DEBUG) this.printString("localStorage(" + this.key + "): " + s.length + " bytes loaded");
return true;
}
}
return false;
},
/**
* parse()
*
* This completes the load() operation, by parsing what was loaded, on the assumption there
* might be some benefit to deferring parsing until we've given the user a chance to confirm.
* Otherwise, load() could have just as easily done this, too.
*
* @this {State}
* @return {boolean} true if successful, false if error
*/
parse: function() {
var fSuccess = true;
try {
this[this.id] = JSON.parse(this[this.id]);
} catch (e) {
Component.error(e.message || e);
fSuccess = false;
}
return fSuccess;
},
/**
* store()
*
* @this {State}
* @return {boolean} true if successful, false if error
*/
store: function() {
var fSuccess = true;
if (web.hasLocalStorage()) {
var s = JSON.stringify(this[this.id]);
if (web.setLocalStorageItem(this.key, s)) {
if (DEBUG) this.printString("localStorage(" + this.key + "): " + s.length + " bytes stored");
} else {
/*
* WARNING: Because browsers tend to disable all alerts() during an "unload" operation,
* it's unlikely anyone will ever see the "quota" errors that occur at this point. Need to
* think of some way to notify the user that there's a problem, and offer a way of cleaning
* up old states.
*/
Component.error("Unable to store " + s.length + " bytes in browser local storage");
fSuccess = false;
}
}
return fSuccess;
},
/**
* toString()
*
* We can't know whether this might be called before parse() or after parse(), so we check.
* If before, then this[this.id] will still be in string form; if after, it will be an Object.
*
* @this {State}
* @return {string} JSON-encoded state
*/
toString: function() {
var value = this[this.id];
return (typeof value == "string"? value : JSON.stringify(value));
},
/**
* unload(parms)
*
* This discards any data saved via set() or loaded via load(), creating an empty State object.
* Note that you have to follow this call with an explicit call to store() if you want to remove
* the state from localStorage as well.
*
* @this {State}
* @param {Object} [parms]
*/
unload: function(parms) {
this[this.id] = {};
if (parms) this.set("parms", parms);
this.fLoaded = false;
},
/**
* clear(fAll)
*
* This unloads the current state, and then clears ALL localStorage for the current machine,
* independent of version, to reduce the chance of orphaned states wasting part of our limited allocation.
*
* @this {State}
* @param {boolean} [fAll] true to unconditionally clear ALL localStorage for the current domain
*/
clear: function(fAll) {
this.unload();
var aKeys = web.getLocalStorageKeys();
for (var i = 0; i < aKeys.length; i++) {
var sKey = aKeys[i];
if (sKey && (fAll || sKey.substr(0, this.key.length) == this.key)) {
web.removeLocalStorageItem(sKey);
if (DEBUG) this.printString("localStorage(" + sKey + ") removed");
aKeys.splice(i, 1);
i = 0;
}
}
},
/**
* printString(s)
*
* @this {State}
* @param {string} s is any caller-defined string
*/
printString: function(s) {
if (DEBUG && DEBUGGER && this.dbg) {
if (this.dbg.messageEnabled(Messages.LOG)) {
this.dbg.message(s);
}
}
}
};
if (NODE) module.exports = State;

View file

@ -36,16 +36,16 @@ if (NODE) {
var web = require("../../shared/lib/weblib");
var DumpAPI = require("../../shared/lib/dumpapi");
var Component = require("../../shared/lib/component");
var ChipSet = require("./chipset");
var Memory = require("./memory");
var Messages = require("./messages");
var State = require("./state");
var ChipSet8080 = require("./chipset");
var Memory8080 = require("./memory");
var Messages8080= require("./messages");
var State8080 = require("./state");
}
/**
* Video(parmsVideo, canvas, context, textarea, container)
* Video8080(parmsVideo, canvas, context, textarea, container)
*
* The Video component can be configured with the following (parmsVideo) properties:
* The Video8080 component can be configured with the following (parmsVideo) properties:
*
* screenWidth: width of the screen canvas, in pixels
* screenHeight: height of the screen canvas, in pixels
@ -54,7 +54,7 @@ if (NODE) {
* aspectRatio (eg, 1.33)
* bufferAddr: the starting address of the frame buffer (eg, 0x2400)
* bufferRAM: true to use existing RAM (default is false)
* bufferFormat: if defined, one of the recognized formats in Video.FORMATS (eg, "vt100")
* bufferFormat: if defined, one of the recognized formats in Video8080.FORMATS (eg, "vt100")
* bufferCols: the width of a single frame buffer row, in pixels (eg, 256)
* bufferRows: the number of frame buffer rows (eg, 224)
* bufferBits: the number of bits per column (default is 1)
@ -94,13 +94,13 @@ if (NODE) {
* @param {Object} [textarea]
* @param {Object} [container]
*/
function Video(parmsVideo, canvas, context, textarea, container)
function Video8080(parmsVideo, canvas, context, textarea, container)
{
var video = this;
this.fGecko = web.isUserAgent("Gecko/");
var i, sEvent, asWebPrefixes = ['', 'moz', 'ms', 'webkit'];
Component.call(this, "Video", parmsVideo, Video, Messages.VIDEO);
Component.call(this, "Video", parmsVideo, Video8080, Messages8080.VIDEO);
this.cxScreen = parmsVideo['screenWidth'];
this.cyScreen = parmsVideo['screenHeight'];
@ -109,7 +109,7 @@ function Video(parmsVideo, canvas, context, textarea, container)
this.fUseRAM = parmsVideo['bufferRAM'];
var sFormat = parmsVideo['bufferFormat'];
this.nFormat = sFormat && Video.FORMATS[sFormat.toUpperCase()] || Video.FORMAT.UNKNOWN;
this.nFormat = sFormat && Video8080.FORMATS[sFormat.toUpperCase()] || Video8080.FORMAT.UNKNOWN;
this.nColsBuffer = parmsVideo['bufferCols'];
this.nRowsBuffer = parmsVideo['bufferRows'];
@ -252,27 +252,27 @@ function Video(parmsVideo, canvas, context, textarea, container)
if (DEBUG) this.nCyclesPrev = 0;
}
Component.subclass(Video);
Component.subclass(Video8080);
Video.COLORS = {
Video8080.COLORS = {
OVERLAY_TOP: 0,
OVERLAY_BOTTOM: 1,
OVERLAY_TOTAL: 2
};
Video.FORMAT = {
Video8080.FORMAT = {
UNKNOWN: 0,
SI1978: 1,
VT100: 2
};
Video.FORMATS = {
"SI1978": Video.FORMAT.SI1978,
"VT100": Video.FORMAT.VT100
Video8080.FORMATS = {
"SI1978": Video8080.FORMAT.SI1978,
"VT100": Video8080.FORMAT.VT100
};
Video.VT100 = {
Video8080.VT100 = {
/*
* The following font IDs are nothing more than all the possible LINEATTR values masked with FONTMASK;
* also, note that double-high implies double-wide; the VT100 doesn't support a double-high single-wide font.
@ -297,10 +297,10 @@ Video.VT100 = {
/**
* initBuffers()
*
* @this {Video}
* @this {Video8080}
* @return {boolean}
*/
Video.prototype.initBuffers = function()
Video8080.prototype.initBuffers = function()
{
/*
* Allocate off-screen buffers now
@ -318,7 +318,7 @@ Video.prototype.initBuffers = function()
this.sizeBuffer = 0;
if (!this.fUseRAM) {
this.sizeBuffer = ((this.cxBuffer * this.nBitsPerPixel) >> 3) * this.cyBuffer;
if (!this.bus.addMemory(this.addrBuffer, this.sizeBuffer, Memory.TYPE.VIDEO)) {
if (!this.bus.addMemory(this.addrBuffer, this.sizeBuffer, Memory8080.TYPE.VIDEO)) {
return false;
}
}
@ -346,7 +346,7 @@ Video.prototype.initBuffers = function()
this.aFonts = {};
this.initColors();
if (this.nFormat == Video.FORMAT.VT100) {
if (this.nFormat == Video8080.FORMAT.VT100) {
/*
* Beyond fonts, VT100 support requires that we maintain a number of additional properties:
*
@ -397,13 +397,13 @@ Video.prototype.initBuffers = function()
/**
* initBus(cmp, bus, cpu, dbg)
*
* @this {Video}
* @param {Computer} cmp
* @param {Bus} bus
* @param {CPUState} cpu
* @param {Debugger} dbg
* @this {Video8080}
* @param {Computer8080} cmp
* @param {Bus8080} bus
* @param {CPUState8080} cpu
* @param {Debugger8080} dbg
*/
Video.prototype.initBus = function(cmp, bus, cpu, dbg)
Video8080.prototype.initBus = function(cmp, bus, cpu, dbg)
{
this.cmp = cmp;
this.bus = bus;
@ -419,7 +419,7 @@ Video.prototype.initBus = function(cmp, bus, cpu, dbg)
* If we have an associated keyboard, then ensure that the keyboard will be notified
* whenever the canvas gets focus and receives input.
*/
this.kbd = /** @type {Keyboard} */ (cmp.getMachineComponent("Keyboard"));
this.kbd = /** @type {Keyboard8080} */ (cmp.getMachineComponent("Keyboard"));
if (this.kbd) {
for (var s in this.ledBindings) {
this.kbd.setBinding("led", s, this.ledBindings[s]);
@ -435,12 +435,12 @@ Video.prototype.initBus = function(cmp, bus, cpu, dbg)
/**
* doneLoad(sURL, sFontData, nErrorCode)
*
* @this {Video}
* @this {Video8080}
* @param {string} sURL
* @param {string} sFontData
* @param {number} nErrorCode (response from server if anything other than 200)
*/
Video.prototype.doneLoad = function(sURL, sFontData, nErrorCode)
Video8080.prototype.doneLoad = function(sURL, sFontData, nErrorCode)
{
if (nErrorCode) {
this.notice("Unable to load font ROM (error " + nErrorCode + ": " + sURL + ")");
@ -496,25 +496,25 @@ Video.prototype.doneLoad = function(sURL, sFontData, nErrorCode)
/**
* createFonts()
*
* @this {Video}
* @this {Video8080}
* @return {boolean}
*/
Video.prototype.createFonts = function()
Video8080.prototype.createFonts = function()
{
/*
* We retain abFontData in case we have to rebuild the fonts (eg, when we switch from 80 to 132 columns)
*/
if (this.abFontData) {
this.fDotStretcher = (this.nFormat == Video.FORMAT.VT100);
this.aFonts[Video.VT100.FONT.NORML] = [
this.fDotStretcher = (this.nFormat == Video8080.FORMAT.VT100);
this.aFonts[Video8080.VT100.FONT.NORML] = [
this.createFontVariation(this.cxCell, this.cyCell),
this.createFontVariation(this.cxCell, this.cyCell, this.fUnderline)
];
this.aFonts[Video.VT100.FONT.DWIDE] = [
this.aFonts[Video8080.VT100.FONT.DWIDE] = [
this.createFontVariation(this.cxCell*2, this.cyCell),
this.createFontVariation(this.cxCell*2, this.cyCell, this.fUnderline)
];
this.aFonts[Video.VT100.FONT.DHIGH] = this.aFonts[Video.VT100.FONT.DHIGH_BOT] = [
this.aFonts[Video8080.VT100.FONT.DHIGH] = this.aFonts[Video8080.VT100.FONT.DHIGH_BOT] = [
this.createFontVariation(this.cxCell*2, this.cyCell*2),
this.createFontVariation(this.cxCell*2, this.cyCell*2, this.fUnderline)
];
@ -533,13 +533,13 @@ Video.prototype.createFonts = function()
* 3) double-high double-wide characters (cell size is this.cxCell*2 x this.cyCell*2)
* 4) any of the above with either reverse video or underline enabled (default is neither)
*
* @this {Video}
* @this {Video8080}
* @param {number} cxCell is the target width of each character in the grid
* @param {number} cyCell is the target height of each character in the grid
* @param {boolean} [fUnderline] (null for unmodified font, false for reverse video, true for underline)
* @return {Object}
*/
Video.prototype.createFontVariation = function(cxCell, cyCell, fUnderline)
Video8080.prototype.createFontVariation = function(cxCell, cyCell, fUnderline)
{
/*
* On a VT100, cxCell,cyCell is initially 10,10, but may change to 9,10 for 132-column mode.
@ -606,12 +606,12 @@ Video.prototype.createFontVariation = function(cxCell, cyCell, fUnderline)
/**
* powerUp(data, fRepower)
*
* @this {Video}
* @this {Video8080}
* @param {Object|null} data
* @param {boolean} [fRepower]
* @return {boolean} true if successful, false if failure
*/
Video.prototype.powerUp = function(data, fRepower)
Video8080.prototype.powerUp = function(data, fRepower)
{
/*
* Because the VT100 frame buffer can be located anywhere in RAM (above 0x2000), we must defer this
@ -619,7 +619,7 @@ Video.prototype.powerUp = function(data, fRepower)
*
* TODO: Remove this display test code once the VT100 is fully operational.
*/
if (this.nFormat == Video.FORMAT.VT100) {
if (this.nFormat == Video8080.FORMAT.VT100) {
/*
* Build a test screen in the VT100 frame buffer; we'll mimic the "SET-UP A" screen, since it uses
* all the font variations. The process involves iterating over 0-based row numbers -2 (or -5 if 50Hz
@ -629,10 +629,10 @@ Video.prototype.powerUp = function(data, fRepower)
* default character attribute for subsequent strings. An empty array ends the screen build process.
*/
var aLineData = {
0: [Video.VT100.FONT.DHIGH, 'SET-UP A'],
2: [Video.VT100.FONT.DWIDE, 'TO EXIT PRESS "SET-UP"'],
22: [Video.VT100.FONT.NORML, ' T T T T T T T T T'],
23: [Video.VT100.FONT.NORML, '1234567890', '1234567890', '1234567890', '1234567890', '1234567890', '1234567890', '1234567890', '1234567890'],
0: [Video8080.VT100.FONT.DHIGH, 'SET-UP A'],
2: [Video8080.VT100.FONT.DWIDE, 'TO EXIT PRESS "SET-UP"'],
22: [Video8080.VT100.FONT.NORML, ' T T T T T T T T T'],
23: [Video8080.VT100.FONT.NORML, '1234567890', '1234567890', '1234567890', '1234567890', '1234567890', '1234567890', '1234567890', '1234567890'],
24: []
};
var addr = this.addrBuffer;
@ -644,9 +644,9 @@ Video.prototype.powerUp = function(data, fRepower)
var fBreak = false;
addrNext = addr + 2;
if (!lineData) {
if (font == Video.VT100.FONT.DHIGH) {
if (font == Video8080.VT100.FONT.DHIGH) {
lineData = aLineData[iRow-1];
font = Video.VT100.FONT.DHIGH_BOT;
font = Video8080.VT100.FONT.DHIGH_BOT;
}
}
else {
@ -657,7 +657,7 @@ Video.prototype.powerUp = function(data, fRepower)
fBreak = true;
}
}
b = (font & Video.VT100.LINEATTR.FONTMASK) | ((addrNext >> 8) & Video.VT100.LINEATTR.ADDRMASK) | Video.VT100.LINEATTR.ADDRBIAS;
b = (font & Video8080.VT100.LINEATTR.FONTMASK) | ((addrNext >> 8) & Video8080.VT100.LINEATTR.ADDRMASK) | Video8080.VT100.LINEATTR.ADDRBIAS;
this.bus.setByteDirect(addr++, b);
this.bus.setByteDirect(addr++, addrNext & 0xff);
if (fBreak) break;
@ -672,7 +672,7 @@ Video.prototype.powerUp = function(data, fRepower)
attr ^= 0x80;
}
}
this.bus.setByteDirect(addr++, Video.VT100.LINETERM);
this.bus.setByteDirect(addr++, Video8080.VT100.LINETERM);
addrNext = addr;
}
/*
@ -686,14 +686,14 @@ Video.prototype.powerUp = function(data, fRepower)
/**
* setBinding(sHTMLType, sBinding, control, sValue)
*
* @this {Video}
* @this {Video8080}
* @param {string|null} sHTMLType is the type of the HTML control (eg, "button", "list", "text", "submit", "textarea", "canvas")
* @param {string} sBinding is the value of the 'binding' parameter stored in the HTML control's "data-value" attribute (eg, "refresh")
* @param {Object} control is the HTML control DOM object (eg, HTMLButtonElement)
* @param {string} [sValue] optional data value
* @return {boolean} true if binding was successful, false if unrecognized binding request
*/
Video.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
Video8080.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
{
var video = this;
@ -730,11 +730,11 @@ Video.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
*
* Called from the ChipSet component whenever the screen dimensions have been dynamically altered.
*
* @this {Video}
* @this {Video8080}
* @param {number} nCols (should be either 80 or 132; 80 is the default)
* @param {number} nRows (should be either 24 or 14; 24 is the default)
*/
Video.prototype.updateDimensions = function(nCols, nRows)
Video8080.prototype.updateDimensions = function(nCols, nRows)
{
this.printMessage("updateDimensions(" + nCols + "," + nRows + ")");
this.nColsBuffer = nCols;
@ -757,10 +757,10 @@ Video.prototype.updateDimensions = function(nCols, nRows)
*
* Called from the ChipSet component whenever the monitor refresh rate has been dynamically altered.
*
* @this {Video}
* @this {Video8080}
* @param {number} nRate (should be either 50 or 60; 60 is the default)
*/
Video.prototype.updateRate = function(nRate)
Video8080.prototype.updateRate = function(nRate)
{
this.printMessage("updateRate(" + nRate + ")");
this.rateMonitor = nRate;
@ -771,10 +771,10 @@ Video.prototype.updateRate = function(nRate)
*
* Called from the ChipSet component whenever the screen scroll offset has been dynamically altered.
*
* @this {Video}
* @this {Video8080}
* @param {number} bScroll
*/
Video.prototype.updateScrollOffset = function(bScroll)
Video8080.prototype.updateScrollOffset = function(bScroll)
{
this.printMessage("updateScrollOffset(" + bScroll + ")");
if (this.bScrollOffset !== bScroll) {
@ -805,10 +805,10 @@ Video.prototype.updateScrollOffset = function(bScroll)
/**
* doFullScreen()
*
* @this {Video}
* @this {Video8080}
* @return {boolean} true if request successful, false if not (eg, failed OR not supported)
*/
Video.prototype.doFullScreen = function()
Video8080.prototype.doFullScreen = function()
{
var fSuccess = false;
if (this.container) {
@ -874,10 +874,10 @@ Video.prototype.doFullScreen = function()
/**
* notifyFullScreen(fFullScreen)
*
* @this {Video}
* @this {Video8080}
* @param {boolean|null} fFullScreen (null if there was a full-screen error)
*/
Video.prototype.notifyFullScreen = function(fFullScreen)
Video8080.prototype.notifyFullScreen = function(fFullScreen)
{
if (!fFullScreen && this.container) {
if (!this.fGecko) {
@ -892,9 +892,9 @@ Video.prototype.notifyFullScreen = function(fFullScreen)
/**
* setFocus()
*
* @this {Video}
* @this {Video8080}
*/
Video.prototype.setFocus = function()
Video8080.prototype.setFocus = function()
{
if (this.inputScreen) this.inputScreen.focus();
};
@ -902,10 +902,10 @@ Video.prototype.setFocus = function()
/**
* getRefreshRate()
*
* @this {Video}
* @this {Video8080}
* @return {number}
*/
Video.prototype.getRefreshRate = function()
Video8080.prototype.getRefreshRate = function()
{
return Math.max(this.rateRefresh, this.rateInterrupt);
};
@ -915,10 +915,10 @@ Video.prototype.getRefreshRate = function()
*
* Initializes the contents of our internal cell cache.
*
* @this {Video}
* @this {Video8080}
* @param {number} nCells
*/
Video.prototype.initCellCache = function(nCells)
Video8080.prototype.initCellCache = function(nCells)
{
this.nCellCache = nCells;
this.fCellCacheValid = false;
@ -932,35 +932,35 @@ Video.prototype.initCellCache = function(nCells)
*
* This creates an array of nColors, with additional OVERLAY_TOTAL colors tacked on to the end of the array.
*
* @this {Video}
* @this {Video8080}
*/
Video.prototype.initColors = function()
Video8080.prototype.initColors = function()
{
var rgbBlack = [0x00, 0x00, 0x00, 0xff];
var rgbWhite = [0xff, 0xff, 0xff, 0xff];
this.nColors = (1 << this.nBitsPerPixel);
this.aRGB = new Array(this.nColors + Video.COLORS.OVERLAY_TOTAL);
this.aRGB = new Array(this.nColors + Video8080.COLORS.OVERLAY_TOTAL);
this.aRGB[0] = rgbBlack;
this.aRGB[1] = rgbWhite;
if (this.nFormat == Video.FORMAT.SI1978) {
if (this.nFormat == Video8080.FORMAT.SI1978) {
var rgbGreen = [0x00, 0xff, 0x00, 0xff];
//noinspection UnnecessaryLocalVariableJS
var rgbYellow = [0xff, 0xff, 0x00, 0xff];
this.aRGB[this.nColors + Video.COLORS.OVERLAY_TOP] = rgbYellow;
this.aRGB[this.nColors + Video.COLORS.OVERLAY_BOTTOM] = rgbGreen;
this.aRGB[this.nColors + Video8080.COLORS.OVERLAY_TOP] = rgbYellow;
this.aRGB[this.nColors + Video8080.COLORS.OVERLAY_BOTTOM] = rgbGreen;
}
};
/**
* setPixel(image, x, y, bPixel)
*
* @this {Video}
* @this {Video8080}
* @param {Object} image
* @param {number} x
* @param {number} y
* @param {number} bPixel (ie, an index into aRGB)
*/
Video.prototype.setPixel = function(image, x, y, bPixel)
Video8080.prototype.setPixel = function(image, x, y, bPixel)
{
var index;
if (!this.rotateBuffer) {
@ -968,12 +968,12 @@ Video.prototype.setPixel = function(image, x, y, bPixel)
} else {
index = (image.height - x - 1) * image.width + y;
}
if (bPixel && this.nFormat == Video.FORMAT.SI1978) {
if (bPixel && this.nFormat == Video8080.FORMAT.SI1978) {
if (x >= 208 && x < 236) {
bPixel = this.nColors + Video.COLORS.OVERLAY_TOP;
bPixel = this.nColors + Video8080.COLORS.OVERLAY_TOP;
}
else if (x >= 28 && x < 72) {
bPixel = this.nColors + Video.COLORS.OVERLAY_BOTTOM;
bPixel = this.nColors + Video8080.COLORS.OVERLAY_BOTTOM;
}
}
var rgb = this.aRGB[bPixel];
@ -989,14 +989,14 @@ Video.prototype.setPixel = function(image, x, y, bPixel)
*
* Updates a particular character cell (row,col) in the associated window.
*
* @this {Video}
* @this {Video8080}
* @param {number} idFont
* @param {number} col
* @param {number} row
* @param {number} data
* @param {Object} [context]
*/
Video.prototype.updateChar = function(idFont, col, row, data, context)
Video8080.prototype.updateChar = function(idFont, col, row, data, context)
{
var bChar = data & 0x7f;
var font = this.aFonts[idFont][(data & 0x80)? 1 : 0];
@ -1037,7 +1037,7 @@ Video.prototype.updateChar = function(idFont, col, row, data, context)
* of the character should be drawn.
*/
if (font.cyCell > this.cyCell) {
if (idFont == Video.VT100.FONT.DHIGH_BOT) ySrc += this.cyCell;
if (idFont == Video8080.VT100.FONT.DHIGH_BOT) ySrc += this.cyCell;
cySrc = this.cyCell;
this.assert(font.cyCell == this.cyCell * 2);
}
@ -1054,10 +1054,10 @@ Video.prototype.updateChar = function(idFont, col, row, data, context)
/**
* updateVT100(fForced)
*
* @this {Video}
* @this {Video8080}
* @param {boolean} [fForced]
*/
Video.prototype.updateVT100 = function(fForced)
Video8080.prototype.updateVT100 = function(fForced)
{
var addrNext = this.addrBuffer, fontNext = -1;
@ -1075,14 +1075,14 @@ Video.prototype.updateVT100 = function(fForced)
var addr = addrNext;
var font = fontNext;
var nColsVisible = this.nColsBuffer;
if (font != Video.VT100.FONT.NORML) nColsVisible >>= 1;
if (font != Video8080.VT100.FONT.NORML) nColsVisible >>= 1;
while (true) {
var data = this.bus.getByteDirect(addr++);
if ((data & Video.VT100.LINETERM) == Video.VT100.LINETERM) {
if ((data & Video8080.VT100.LINETERM) == Video8080.VT100.LINETERM) {
var b = this.bus.getByteDirect(addr++);
fontNext = b & Video.VT100.LINEATTR.FONTMASK;
addrNext = ((b & Video.VT100.LINEATTR.ADDRMASK) << 8) | this.bus.getByteDirect(addr);
addrNext += (b & Video.VT100.LINEATTR.ADDRBIAS)? Video.VT100.ADDRBIAS_LO : Video.VT100.ADDRBIAS_HI;
fontNext = b & Video8080.VT100.LINEATTR.FONTMASK;
addrNext = ((b & Video8080.VT100.LINEATTR.ADDRMASK) << 8) | this.bus.getByteDirect(addr);
addrNext += (b & Video8080.VT100.LINEATTR.ADDRBIAS)? Video8080.VT100.ADDRBIAS_LO : Video8080.VT100.ADDRBIAS_HI;
break;
}
if (nCols < nColsVisible) {
@ -1192,10 +1192,10 @@ Video.prototype.updateVT100 = function(fForced)
* and then update the cell cache to match. Since initCellCache() sets every cell in the cell cache to an
* invalid value, we're assured that the next call to updateScreen() will redraw the entire (visible) video buffer.
*
* @this {Video}
* @this {Video8080}
* @param {number} n (where 0 <= n < getRefreshRate() for a normal update, or -1 for a forced update)
*/
Video.prototype.updateScreen = function(n)
Video8080.prototype.updateScreen = function(n)
{
var fClean;
var fUpdate = true;
@ -1259,13 +1259,13 @@ Video.prototype.updateScreen = function(n)
/**
* updateScreenText(fForced)
*
* @this {Video}
* @this {Video8080}
* @param {boolean} [fForced]
*/
Video.prototype.updateScreenText = function(fForced)
Video8080.prototype.updateScreenText = function(fForced)
{
switch(this.nFormat) {
case Video.FORMAT.VT100:
case Video8080.FORMAT.VT100:
this.updateVT100(fForced);
break;
}
@ -1274,10 +1274,10 @@ Video.prototype.updateScreenText = function(fForced)
/**
* updateScreenGraphics(fForced)
*
* @this {Video}
* @this {Video8080}
* @param {boolean} [fForced]
*/
Video.prototype.updateScreenGraphics = function(fForced)
Video8080.prototype.updateScreenGraphics = function(fForced)
{
var addr = this.addrBuffer;
var addrLimit = addr + this.sizeBuffer;
@ -1359,14 +1359,14 @@ Video.prototype.updateScreenGraphics = function(fForced)
};
/**
* Video.init()
* Video8080.init()
*
* This function operates on every HTML element of class "video", extracting the
* JSON-encoded parameters for the Video constructor from the element's "data-value"
* attribute, invoking the constructor to create a Video component, and then binding
* any associated HTML controls to the new component.
*/
Video.init = function()
Video8080.init = function()
{
var aeVideo = Component.getElementsByClass(document, PC8080.APPCLASS, "video");
for (var iVideo = 0; iVideo < aeVideo.length; iVideo++) {
@ -1486,7 +1486,7 @@ Video.init = function()
* Now we can create the Video object, record it, and wire it up to the associated document elements.
*/
var eContext = eCanvas.getContext("2d");
var video = new Video(parmsVideo, eCanvas, eContext, eTextArea /* || eInput */, eVideo);
var video = new Video8080(parmsVideo, eCanvas, eContext, eTextArea /* || eInput */, eVideo);
/*
* Bind any video-specific controls (eg, the Refresh button). There are no essential controls, however;
@ -1499,6 +1499,6 @@ Video.init = function()
/*
* Initialize every Video module on the page.
*/
web.onInit(Video.init);
web.onInit(Video8080.init);
if (NODE) module.exports = Video;
if (NODE) module.exports = Video8080;

View file

@ -69,8 +69,8 @@ At the time of this writing, the recommended order is:
* [pcx86/fdc.js](lib/fdc.js)
* [pcx86/hdc.js](lib/hdc.js)
* [pcx86/debugger.js](lib/debugger.js)
* [pcx86/state.js](lib/state.js)
* [pcx86/computer.js](lib/computer.js)
* [shared/state.js](../shared/lib/state.js)
* [shared/embed.js](../shared/lib/embed.js)
* [shared/save.js](../shared/lib/save.js)

View file

@ -85,18 +85,17 @@ function Component(type, parms, constructor, bitsMessage)
if (!parms) parms = {'id': "", 'name': ""};
this.id = parms['id'];
this.id = parms['id'] || "";
this.name = parms['name'];
this.comment = parms['comment'];
this.parms = parms;
if (this.id === undefined) this.id = "";
var i = this.id.indexOf('.');
if (i > 0) {
if (i < 0) {
this.idComponent = this.id;
} else {
this.idMachine = this.id.substr(0, i);
this.idComponent = this.id.substr(i + 1);
} else {
this.idComponent = this.id;
}
/*
@ -219,12 +218,35 @@ Component.subclass = function(subclass, superclass, methods, statics)
};
/*
* Every component created on the current page is recorded in this array (see Component.add()).
*
* This enables any component to locate another component by ID (see Component.getComponentByID())
* Every component created on the current page is recorded in this array (see Component.add()),
* enabling any component to locate another component by ID (see Component.getComponentByID())
* or by type (see Component.getComponentByType()).
*
* Every machine on the page are now recorded as well, by their machine ID. We then record the
* various resources used by that machine.
*/
Component.components = [];
if (window) {
if (!window['PCjs']) {
window['PCjs'] = {
'Machines': {},
'Components': []
};
}
/*
* Alias the new global objects above to their original property names, to minimize code changes.
*/
Component.machines = window['PCjs']['Machines'];
Component.components = window['PCjs']['Components'];
}
else {
/*
* Fallback for non-browser-based environments (ie, Node). TODO: This will need to be
* tailored to Node, probably using the global object instead of the window object, if we
* ever want to support multi-machine configs in that environment.
*/
Component.machines = {};
Component.components = [];
}
/**
* Component.add(component)
@ -241,12 +263,6 @@ Component.add = function(component)
Component.components.push(component);
};
/*
* Every machine on the page are now recorded as well, by their machine ID. We then record the various resources
* used by that machine.
*/
Component.machines = {};
/**
* Component.addMachine(idMachine)
*
@ -316,7 +332,6 @@ Component.log = function(s, type)
* Verifies conditions that must be true (for DEBUG builds only).
*
* The Closure Compiler should automatically remove all references to Component.assert() in non-DEBUG builds.
*
* TODO: Add a task to the build process that "asserts" there are no instances of "assertion failure" in RELEASE builds.
*
* @param {boolean} f is the expression we are asserting to be true

View file

@ -1,5 +1,5 @@
/**
* @fileoverview The State class used by C1Pjs and PCx86.
* @fileoverview The State class used by PCjs machines.
* @author <a href="mailto:Jeff@pcjs.org">Jeff Parsons</a>
* @version 1.0
* Created 2012-May-14
@ -34,7 +34,6 @@
if (NODE) {
var web = require("./../../shared/lib/weblib");
var Component = require("./../../shared/lib/component");
var Messages = require("./messages");
}
/**
@ -50,7 +49,7 @@ if (NODE) {
*
* WARNING: Since State objects are low-level objects that have no UI requirements, they do not
* inherit from the Component class, so you should only use class methods of Component, such as
* Component.assert(), or Debugger methods if the Debugger is available.
* Component.assert() (or Debugger methods if the Debugger is available).
*
* NOTE: 1.01 is the first version to provide limited save/restore support using localStorage.
* From that point on, care must be taken to insure that any new version that's incompatible with
@ -281,7 +280,7 @@ State.prototype = {
if (s) {
this[this.id] = s;
this.fLoaded = true;
if (DEBUG) this.printString("localStorage(" + this.key + "): " + s.length + " bytes loaded");
if (DEBUG) Component.log("localStorage(" + this.key + "): " + s.length + " bytes loaded");
return true;
}
}
@ -318,7 +317,7 @@ State.prototype = {
if (web.hasLocalStorage()) {
var s = JSON.stringify(this[this.id]);
if (web.setLocalStorageItem(this.key, s)) {
if (DEBUG) this.printString("localStorage(" + this.key + "): " + s.length + " bytes stored");
if (DEBUG) Component.log("localStorage(" + this.key + "): " + s.length + " bytes stored");
} else {
/*
* WARNING: Because browsers tend to disable all alerts() during an "unload" operation,
@ -376,24 +375,11 @@ State.prototype = {
var sKey = aKeys[i];
if (sKey && (fAll || sKey.substr(0, this.key.length) == this.key)) {
web.removeLocalStorageItem(sKey);
if (DEBUG) this.printString("localStorage(" + sKey + ") removed");
if (DEBUG) Component.log("localStorage(" + sKey + ") removed");
aKeys.splice(i, 1);
i = 0;
}
}
},
/**
* printString(s)
*
* @this {State}
* @param {string} s is any caller-defined string
*/
printString: function(s) {
if (DEBUG && DEBUGGER && this.dbg) {
if (this.dbg.messageEnabled(Messages.LOG)) {
this.dbg.message(s);
}
}
}
};

View file

@ -126,8 +126,8 @@
"./modules/pcx86/lib/fdc.js",
"./modules/pcx86/lib/hdc.js",
"./modules/pcx86/lib/debugger.js",
"./modules/pcx86/lib/state.js",
"./modules/pcx86/lib/computer.js",
"./modules/shared/lib/state.js",
"./modules/shared/lib/embed.js",
"./modules/shared/lib/save.js"
],
@ -156,9 +156,8 @@
"./modules/pc8080/lib/video.js",
"./modules/pc8080/lib/serialport.js",
"./modules/pc8080/lib/debugger.js",
"./modules/pc8080/lib/state.js",
"./modules/pc8080/lib/computer.js",
"./modules/shared/lib/embed.js",
"./modules/shared/lib/save.js"
"./modules/shared/lib/state.js",
"./modules/shared/lib/embed.js"
]
}