Updated calcRemainingTime() to compensate for large time anomalies (usually caused by external debuggers)
This commit is contained in:
parent
d3e29eb851
commit
a08fcab276
4 changed files with 120 additions and 113 deletions
|
|
@ -775,28 +775,28 @@ g[1],!0);break}Jr(a,g);break;case "m":if("mouse"==g[0]){var wi=g[1],zg=g[2];if(a
|
|||
Oa)wc=!1,Oa=null;else{"keys"==Oa&&(Oa="key");"kbd"==Oa&&(Oa="keyboard");for(vc in Bb)if(Oa==vc){td=Bb[vc];wc=!!(a.wc&td);break}if(!td){a.O("unknown message category: "+Oa);break a}}td&&("on"==g[2]?(a.wc|=td,wc=!0):"off"==g[2]&&(a.wc&=~td,wc=!1))}var os=0,Vc="";for(vc in Bb)if(!Oa||Oa==vc){var ps=!!(a.wc&Bb[vc]);if(null===wc||wc==ps)Vc&&(Vc+=","),++os%10||(Vc+="\n\t"),"key"==vc&&(vc="keys"),Vc+=vc}void 0===Oa&&a.O("message commands:\n\tm [category] [on|off]\tturn categories on/off");a.O((null!==wc?
|
||||
wc?"messages on: ":"messages off: ":"message categories:\n\t")+(Vc||"none"));lq(a)}break;case "o":var xi=g[1],qs=g[2];if(xi&&"?"!=xi){var yi=Eq(a,xi,"port #"),zi=Eq(a,qs);void 0!==yi&&void 0!==zi&&(qc(a.ga,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]){Kr(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=jq(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:Uq(a,lb,1);Ag=!0;break;case 204:case 206:a.N=fe;Uq(a,lb,1);break;case 205:case 224:case 225:case 226:a.N=fe;Uq(a,lb,lb.Rb?4:2);break;case 232:a.N=fe;Uq(a,lb,lb.Rb?5:3);break;case 154:a.N=fe;Uq(a,lb,lb.Rb?7:5);break;case 255:var Yn=a.tb(lb)&14591;if(4351==Yn||6399==Yn)a.N=fe,rr(a,lb);break;case 243:case 242:Uq(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,Uq(a,lb,1))}while(Ag);a.N?(a.Td(a.A,lb,!0),a.Le()||(a.X&&a.X.yd(),a.N=0)):Mr(a,Wn?"tr":"t")}break;case "r":if("reset"==b){a.X&&a.X.reset();break}jr(a,g);break;case "t":Mr(a,g[0],g[1]);break;case "u":kr(a,g[1],g[2],8);break;case "v":if("var"==g[0]){Hr(a,b.substr(3))||(d=!1);break}a.O("PCx86 version 1.24.1 ("+a.F.ja+",RELEASE,NOPREFETCH"+(xb?",TYPEDARRAYS":",LONGARRAYS")+",NOBACKTRACK)");a.O(za());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=
|
||||
(a.N=fe,Uq(a,lb,1))}while(Ag);a.N?(a.Td(a.A,lb,!0),a.Le()||(a.X&&a.X.yd(),a.N=0)):Mr(a,Wn?"tr":"t")}break;case "r":if("reset"==b){a.X&&a.X.reset();break}jr(a,g);break;case "t":Mr(a,g[0],g[1]);break;case "u":kr(a,g[1],g[2],8);break;case "v":if("var"==g[0]){Hr(a,b.substr(3))||(d=!1);break}a.O("PCx86 version 1.24.2 ("+a.F.ja+",RELEASE,NOPREFETCH"+(xb?",TYPEDARRAYS":",LONGARRAYS")+",NOBACKTRACK)");a.O(za());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&&Tc(a.F);a.O("checksums "+(a.F.la.Ze?"enabled":"disabled"));break;case "sp":void 0!==g[2]&&($c(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]){Kr(a,b.substr(1));break}var cf="commands:",Ai;for(Ai in qq)cf+="\n"+ma(Ai,7)+qq[Ai];Wf(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 nq(a,b,c){b=cr(a,b,c);for(var d in b)if(!qr(a,b[d]))return!1;return!0}
|
||||
Sa(function(){for(var a=pb(document,"pcx86","debugger"),b=0;b<a.length;b++){var c=a[b],d=mb(c),d=new iq(d);ob(d,c)}});
|
||||
function Or(a,b,c){Wa.call(this,"Computer",a,Or,67108864);this.la.cc=!1;Pr(this,b);this.fa=Qc(this,"autoPower",a);this.N=0;this.ra=a.busWidth||a.buswidth;this.A=Qr;this.aa=null;this.V=this.pa=!1;this.ua=Qc(this,"url")||"";this.ya=(Math.random()+.1).toString(36).substr(2,12);this.B=Rr(this);if(this.F=kb("CPU",this.id)){this.ha=kb("Debugger",this.id);this.L=[];for(b=null;b=Hb(this,"Video",b);)this.L.push(b);this.ga=new Ob({id:this.fe+".bus",busWidth:this.ra},this.F,this.ha);var d,e=ib(this.id);if((this.C=
|
||||
kb("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.1\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.ga,this.F,this.ha);b=null;d=a.resume;void 0!==d&&(1<d.length?b=this.W=d:this.A=parseInt(d,10));var f;if(a=Qc(this,"state")||(f=!0,a.state))b=this.ia=a,f||(this.V=!0,this.A=Qr),this.A&&(this.ea=new lf(this,
|
||||
"1.24.1"),this.ea.load()?b=null:delete this.ea);!b&&this.A&&(b=Sr(this))&&(this.V=!0);if(b){var g=this;xa(b,null,!0,function(a,b,c){c?(g.W=null,g.V=!1,g.Na("Unable to load machine state from server (error "+c+(b?": "+na(b):"")+")")):(g.aa=b,g.pa=!0);ub(g)})}else ub(this);this.qa.power||(this.fa=!0);!c&&this.fa&&Tr(this,this.ag)}else w("Unable to find CPU component")}fb(Or);var Qr=0;m=Or.prototype;m.gf=function(){return this.ya};
|
||||
kb("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.2\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.ga,this.F,this.ha);b=null;d=a.resume;void 0!==d&&(1<d.length?b=this.W=d:this.A=parseInt(d,10));var f;if(a=Qc(this,"state")||(f=!0,a.state))b=this.ia=a,f||(this.V=!0,this.A=Qr),this.A&&(this.ea=new lf(this,
|
||||
"1.24.2"),this.ea.load()?b=null:delete this.ea);!b&&this.A&&(b=Sr(this))&&(this.V=!0);if(b){var g=this;xa(b,null,!0,function(a,b,c){c?(g.W=null,g.V=!1,g.Na("Unable to load machine state from server (error "+c+(b?": "+na(b):"")+")")):(g.aa=b,g.pa=!0);ub(g)})}else ub(this);this.qa.power||(this.fa=!0);!c&&this.fa&&Tr(this,this.ag)}else w("Unable to find CPU component")}fb(Or);var Qr=0;m=Or.prototype;m.gf=function(){return this.ya};
|
||||
function Pr(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 Qc(a,b,c){var d=b.toLowerCase(),d=$a[b]||$a[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.le=function(){return this.B||""};function Tr(a,b,c){for(var d=ib(a.id),e=0;e<=d.length;e++){var f=e<d.length?d[e]:a;if(!vb(f)){vb(f,function(){Tr(a,b,c)});return}}b.call(a,c)}
|
||||
function Ur(a,b){var c=new lf(a,"1.24.1","validate");if(c.load()&&Vr(c)){var d=Wr(c,"timestamp"),e=b?Wr(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:Qr));if(!this.N){this.N++;var b=!1,c=!1;this.ka=!1;var d=this.ea||new lf(this,"1.24.1");if(-1==a)b=!0;else if(a>Qr){if(d.load(this.aa)){this.X=new lf(this,"1.24.1","failsafe");this.X.load()&&(Xr(this,d),a=2,Yr(this.X));N(this.X,"timestamp",ra());Zr(this.X);var e=this.A&&!this.V;if(1==a||Aa("Click OK to restore the previous PCx86 machine state, or CANCEL to reset the machine.")){if(c=Vr(d)){var f=Wr(d,"code"),g=Wr(d,"data");f&&("ok"==f?d.load(g):("error"==
|
||||
function Ur(a,b){var c=new lf(a,"1.24.2","validate");if(c.load()&&Vr(c)){var d=Wr(c,"timestamp"),e=b?Wr(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:Qr));if(!this.N){this.N++;var b=!1,c=!1;this.ka=!1;var d=this.ea||new lf(this,"1.24.2");if(-1==a)b=!0;else if(a>Qr){if(d.load(this.aa)){this.X=new lf(this,"1.24.2","failsafe");this.X.load()&&(Xr(this,d),a=2,Yr(this.X));N(this.X,"timestamp",ra());Zr(this.X);var e=this.A&&!this.V;if(1==a||Aa("Click OK to restore the previous PCx86 machine state, or CANCEL to reset the machine.")){if(c=Vr(d)){var f=Wr(d,"code"),g=Wr(d,"data");f&&("ok"==f?d.load(g):("error"==
|
||||
f&&"no machine state"!=g?(this.Na("Error: "+g),"unable to verify user"==g&&(Ga("user",""),this.B=null)):this.O(f+": "+g),Yr(d),d.load()?(c=Vr(d),e=!0):c=!1))}e&&Ur(this,c?d:null)}else 2==a&&d.clear()}else Ur(this);delete this.aa;delete this.ea}e=ib(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?Tr(this,this.Ki,b):this.Ki(b)}};
|
||||
function $r(a,b,c,d,e){if(!b.la.cc){b.la.cc=!0;if(b.ic){var f=null;e&&((f=Wr(c,b.id))||(f=Wr(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=Qr,window&&window.location.reload()):a.ka=!0,b.ic(null),e=!1)}if(!d&&b.wk)for(a=b.wk.split("|"),c=0;c<a.length;c++)b.status(a[c])}return e}
|
||||
m.Ki=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),Xc(this.F));this.ka&&(Xr(this,b),b.clear());!c&&this.X&&(this.X.clear(),delete this.X);this.N=0};
|
||||
function Xr(a,b){if(Aa("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.le(),d=b.toString(),e={app:"PCx86",ver:"1.24.1"};e.url=a.ua;e.user=c;e.type="bug";e.data=d;xa("http://www.pcjs.org/api/v1/report",e,!0)}}
|
||||
function Nr(a,b,c){var d,e="none";if(a.N)return null;a.N--;var f=new lf(a,"1.24.1"),g=new lf(a,"1.24.1","validate"),h=ra();N(g,"timestamp",h);N(f,"timestamp",h);N(f,"version","1.24.1");N(f,"url",window?window.location.href:null);N(f,"browser",za());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=ib(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&&
|
||||
function Xr(a,b){if(Aa("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.le(),d=b.toString(),e={app:"PCx86",ver:"1.24.2"};e.url=a.ua;e.user=c;e.type="bug";e.data=d;xa("http://www.pcjs.org/api/v1/report",e,!0)}}
|
||||
function Nr(a,b,c){var d,e="none";if(a.N)return null;a.N--;var f=new lf(a,"1.24.2"),g=new lf(a,"1.24.2","validate"),h=ra();N(g,"timestamp",h);N(f,"timestamp",h);N(f,"version","1.24.2");N(f,"url",window?window.location.href:null);N(f,"browser",za());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=ib(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()),Zr(g)&&Zr(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.ga&&this.ga.reset&&(y(this,"Resetting "+this.ga.type),this.ga.reset());for(var a=ib(this.id),b=0;b<a.length;b++){var c=a[b];c!==this&&c!==this.ga&&c.reset&&(y(this,"Resetting "+c.type),c.reset())}};
|
||||
m.start=function(a,b){for(var c=ib(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=ib(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?Nr(d,!1,!0):Tr(d,d.ag))},!0;case "reset":return this.qa[b]=c,c.onclick=function(){if(d.la.cc&&!d.N)if(d.A&&!d.W){var a=Aa("Click OK to save changes to this PCx86 machine.\n\nWARNING: If you CANCEL, all disk changes will be discarded.");Nr(d,a,!0);!a&&d.ia?window&&window.location.reload():(a||(d.fh=!0),d.ag(Qr),d.fh=!1)}else d.reset(),d.F&&Xc(d.F)},!0;case "save":if(ha(ya(),"pcjs.org")){c.parentNode.removeChild(c);
|
||||
break}this.qa[b]=c;c.onclick=function(){var a=Rr(d,!0);if(a){var b=!!(d.A&&!d.W||d.ia),c=Nr(d,b);b?as(d,a,c):d.Na("Resume disabled, machine state not saved")}};return!0}return!1};
|
||||
function Rr(a,b){var c=a.B;c||(c=Fa("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=xa(ya()+"/api/v1/user?req=verify&user="+b),d=c[1];if(!c[0]&&d)try{c=eval("("+d+")"),c.code&&"ok"==c.code&&(Ga("user",c.data),a.B=c.data)}catch(e){w(e.message+" ("+d+")")}return a.B}function Sr(a){var b=null;a.B&&(b=ya()+"/api/v1/user?req=load&user="+a.B+"&state="+cs(a,"1.24.1"));return b}
|
||||
function as(a,b,c){if(c){var d={req:"store"};d.user=b;d.state=cs(a,"1.24.1");d.data=c;b=xa(ya()+"/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),Ga("user",""),a.B=null)}}
|
||||
function bs(a,b){a.B=null;var c=xa(ya()+"/api/v1/user?req=verify&user="+b),d=c[1];if(!c[0]&&d)try{c=eval("("+d+")"),c.code&&"ok"==c.code&&(Ga("user",c.data),a.B=c.data)}catch(e){w(e.message+" ("+d+")")}return a.B}function Sr(a){var b=null;a.B&&(b=ya()+"/api/v1/user?req=load&user="+a.B+"&state="+cs(a,"1.24.2"));return b}
|
||||
function as(a,b,c){if(c){var d={req:"store"};d.user=b;d.state=cs(a,"1.24.2");d.data=c;b=xa(ya()+"/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),Ga("user",""),a.B=null)}}
|
||||
function Hb(a,b,c){a=ib(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.X&&d.X.focus();a&&window&&window.scrollTo(b,c)}};m.qd=function(a){this.F&&this.F.qd(a);this.C&&this.C.qd(a)};
|
||||
function fd(a,b){for(var c=0;c<a.L.length;c++)un(a.L[c],b);if(a.C&&(c=a.C,c.Ja)){Lb(c,18,c.aa,c.Ga);if(c.gb){var d=c.ga,e=c.A,f,g;null==f&&(f=0);null==g&&(g=d.W-f|0);null==e&&(e={bh:0,Vd:0,Tg:[]});var h=f>>>d.La;f=f+g-1>>>d.La;e.bh=0;for(e.Vd=0;h<=f;)g=d.sa[h],e.bh+=g.size,g.size&&(e.Tg.push(ta(Kb,h,0,0,g.type)),e.Vd++),h++;c.A=e;c.ya=c.A.Vd*c.ga.Sb/691200;d=0;c.A.Ci=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.Tg[f];g=ua(Kb.type,l);l=ua(Kb.ck,l);if(g!=e||l!=k+1)(k=f-h)&&
|
||||
(d+=Nb(c,h,k,e)),e=g,h=f;k=l}d+=Nb(c,h,f-h,e);e=c.A.Nk!=d;c.A.Nk=d;if(e){e=new Fb(0,0,c.aa.width,c.aa.height);c.A.Qe=[];h=c.A.Vd;for(d=0;d<c.A.Ci;d++)f=c.A.Bf[d].Vd,c.A.Qe.push(Gb(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.Ga,(k=Ac[e.type])||(k=new Db),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.fa=h.ua,h.W=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,
|
||||
|
|
@ -811,9 +811,9 @@ h=null;if("<"==a.charAt(0))try{e||(a=a.replace(/<!DOCTYPE(.|[\r\n])*]>\s*/g,""))
|
|||
function rs(a,b,c){var d;if(d=/<([a-z]+)\s+ref="(.*?)"(.*?)\/>/g.exec(a)){var e=d[2];b("Loading "+e+"...");xa(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]*/,
|
||||
"");a=a.replace(d[0],g);rs(a,b,c)}})}else c(a,null)}
|
||||
function ss(a,b,c,d){function e(a){if(void 0===h){var b=g&&pb(g,"machine-warning");h=b&&b[0]||g}h&&(h.innerHTML=la(a))}function f(a){e("Error: "+a);k&&(--ds||Ua(!0));k=!1}var g,h,k=!0;ds++;gb[a]={};try{if(g=document.getElementById(a)){var l;if("object"==typeof resources&&(l=resources.css)){var n=document.head||document.getElementsByTagName("head")[0],q=document.createElement("style");q.type="text/css";q.styleSheet?q.styleSheet.cssText=l:q.appendChild(document.createTextNode(l));n.appendChild(q)}c||
|
||||
(c="/versions/pcx86/1.24.1/components.xsl");l=function(d,h){h?es(c,null,null,!1,e,function(d,k){if(k)if(hb(a,c,d),e("Processing "+b+"..."),window.ActiveXObject||"ActiveXObject"in window){var l=h.transformNode(k);l?(g.outerHTML=l,--ds||Ua(!0)):f("transformNodeToObject failed")}else document.implementation&&document.implementation.createDocument?(l=new XSLTProcessor,l.importStylesheet(k),(l=l.transformToFragment(h,document))?g.parentNode?(g.parentNode.replaceChild(l,g),--ds||Ua(!0)):f("invalid machine element: "+
|
||||
(c="/versions/pcx86/1.24.2/components.xsl");l=function(d,h){h?es(c,null,null,!1,e,function(d,k){if(k)if(hb(a,c,d),e("Processing "+b+"..."),window.ActiveXObject||"ActiveXObject"in window){var l=h.transformNode(k);l?(g.outerHTML=l,--ds||Ua(!0)):f("transformNodeToObject failed")}else document.implementation&&document.implementation.createDocument?(l=new XSLTProcessor,l.importStylesheet(k),(l=l.transformToFragment(h,document))?g.parentNode?(g.parentNode.replaceChild(l,g),--ds||Ua(!0)):f("invalid machine element: "+
|
||||
a):f("transformToFragment failed")):f("unable to transform XML: unsupported browser");else f(d)}):f(d)};"<"!=b.charAt(0)?es(b,a,d,!0,e,l):fs(b,null,a,d,!1,e,l)}else f("missing machine element: "+a)}catch(p){f(p.message)}return k}function ts(a,b,c,d){Ua(!1);return ss(a,b,c,d)}window.embedPC=ts;window.embedPCx86=ts;window.enableEvents=Ua;window.sendEvent=Va;
|
||||
function us(a,b,c,d){if(!c&&b){d.push(b);a=gb[d[0]];b=null;for(var e in a)if(ha(e,"components.xsl")){b=e.replace(".xsl",".css");break}b?xa(b,null,!0,function(a,b){vs(b,d)}):vs(null,d)}else w("Error ("+c+") requesting "+a)}
|
||||
function vs(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=gb[f],k={},l;for(l in h){var n=h[l],q=ga(l);if("xml"==q){for(q=/[ \t]*<disk [^>]*path=(['"])(.*?)\1.*?<\/disk>\n?/g;d=q.exec(h[l]);){var p=d[2];p&&(h[p]||(n=n.replace(d[0],"")))}d=l=fa(l)}else"xsl"==q&&(e=l=fa(l));k[l]=n}a&&(k[l="css"]=a);b[2]&&(k[l="parms"]=b[2]);b[3]&&(k[l="state"]=b[3]);d&&e?(l=JSON.stringify(k),g+=".js",c=c[1]+"var resources="+l+";"+c[2]+c[3],c=c.replace(/\u00A9/g,
|
||||
"©"),c=Ja(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.",w(c)):w("Missing XML/XSL resources")}
|
||||
window.savePC=function(a,b,c){var d=kb("Computer",a),e=kb("Debugger",a);if(d){var f=Nr(d,!0),g=d.U?JSON.stringify(d.U):null;b||(b="/versions/pcjs/1.24.1/pc"+(e?"-dbg":"")+".js");if(c&&c({state:f,jk:g}))return!0;xa(b,null,!0,function(c,d,e){us(c,d,e,[a,fa(b,!0),g,f])});return!0}w("Unable to identify machine '"+a+"'");return!1};})();
|
||||
window.savePC=function(a,b,c){var d=kb("Computer",a),e=kb("Debugger",a);if(d){var f=Nr(d,!0),g=d.U?JSON.stringify(d.U):null;b||(b="/versions/pcjs/1.24.2/pc"+(e?"-dbg":"")+".js");if(c&&c({state:f,jk:g}))return!0;xa(b,null,!0,function(c,d,e){us(c,d,e,[a,fa(b,!0),g,f])});return!0}w("Unable to identify machine '"+a+"'");return!1};})();
|
||||
|
|
|
|||
|
|
@ -600,23 +600,23 @@ function Zm(a,b){if(a.errorCode)return-1;do{if(a.Wa&&a.ta.write(a.Wa,a.Ua++,b))b
|
|||
var Pm={800:Z.prototype.Rk,801:Z.prototype.Sk,802:Z.prototype.Qk},Om={496:Z.prototype.xj,497:Z.prototype.Xj,498:Z.prototype.Zj,499:Z.prototype.$j,500:Z.prototype.Vj,501:Z.prototype.Uj,502:Z.prototype.Wj,503:Z.prototype.ak},Rm={800:Z.prototype.Zl,801:Z.prototype.bm,802:Z.prototype.am,803:Z.prototype.$l,807:Z.prototype.jh,811:Z.prototype.jh,815:Z.prototype.jh},Qm={496:Z.prototype.jl,497:Z.prototype.ol,498:Z.prototype.ml,499:Z.prototype.nl,500:Z.prototype.il,501:Z.prototype.hl,502:Z.prototype.kl,503:Z.prototype.gl,
|
||||
1014:Z.prototype.ll};Ha(function(){for(var a=bb(document,"pcx86","hdc"),b=0;b<a.length;b++){var c=a[b],d=Za(c),d=new Z(d);ab(d,c)}});
|
||||
function ln(a,b,c){La.call(this,"Computer",a,ln);this.ea.Sb=!1;mn(this,b);this.ba=mc(this,"autoPower",a);this.G=0;this.da=a.busWidth||a.buswidth;this.B=nn;this.R=null;this.K=this.Z=!1;this.ha=mc(this,"url")||"";this.ma=(Math.random()+.1).toString(36).substr(2,12);this.C=on(this);if(this.A=Ya("CPU",this.id)){this.Ia=Ya("Debugger",this.id);this.I=[];for(b=null;b=nb(this,"Video",b);)this.I.push(b);this.ia=new ub({id:this.Fe+".bus",busWidth:this.da},this.A,this.Ia);var d,e=Wa(this.id);if((this.D=Ya("Panel",
|
||||
this.id))&&this.D.ig)for(b=0;b<e.length;b++)d=e[b],d.Ba=this.D.Ba,d.rc=this.D.rc,d.ig=this.D.ig;this.rc("PCx86 v1.24.1\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.ia,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=mc(this,"state")||(f=!0,a.state))b=this.W=a,f||(this.K=!0,this.B=nn),this.B&&(this.P=new ee(this,"1.24.1"),
|
||||
this.id))&&this.D.ig)for(b=0;b<e.length;b++)d=e[b],d.Ba=this.D.Ba,d.rc=this.D.rc,d.ig=this.D.ig;this.rc("PCx86 v1.24.2\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.ia,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=mc(this,"state")||(f=!0,a.state))b=this.W=a,f||(this.K=!0,this.B=nn),this.B&&(this.P=new ee(this,"1.24.2"),
|
||||
this.P.load()?b=null:delete this.P);!b&&this.B&&(b=pn(this))&&(this.K=!0);if(b){var g=this;ra(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?": "+ka(b):"")+")")):(g.R=b,g.Z=!0);db(g)})}else db(this);this.la.power||(this.ba=!0);!c&&this.ba&&qn(this,this.gf)}else p("Unable to find CPU component")}Ta(ln);var nn=0;l=ln.prototype;l.te=function(){return this.ma};
|
||||
function mn(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 mc(a,b,c){var d=b.toLowerCase(),d=Oa[b]||Oa[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 qn(a,b,c){for(var d=Wa(a.id),e=0;e<=d.length;e++){var f=e<d.length?d[e]:a;if(!eb(f)){eb(f,function(){qn(a,b,c)});return}}b.call(a,c)}
|
||||
function rn(a,b){var c=new ee(a,"1.24.1","validate");if(c.load()&&sn(c)){var d=tn(c,"timestamp"),e=b?tn(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.gf=function(a){void 0===a&&(a=this.B||(this.R?1:nn));if(!this.G){this.G++;var b=!1,c=!1;this.Y=!1;var d=this.P||new ee(this,"1.24.1");if(-1==a)b=!0;else if(a>nn){if(d.load(this.R)){this.H=new ee(this,"1.24.1","failsafe");this.H.load()&&(un(this,d),a=2,vn(this.H));C(this.H,"timestamp",na());wn(this.H);var e=this.B&&!this.K;if(1==a||ta("Click OK to restore the previous PCx86 machine state, or CANCEL to reset the machine.")){if(c=sn(d)){var f=tn(d,"code"),g=tn(d,"data");f&&("ok"==f?d.load(g):("error"==
|
||||
function rn(a,b){var c=new ee(a,"1.24.2","validate");if(c.load()&&sn(c)){var d=tn(c,"timestamp"),e=b?tn(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.gf=function(a){void 0===a&&(a=this.B||(this.R?1:nn));if(!this.G){this.G++;var b=!1,c=!1;this.Y=!1;var d=this.P||new ee(this,"1.24.2");if(-1==a)b=!0;else if(a>nn){if(d.load(this.R)){this.H=new ee(this,"1.24.2","failsafe");this.H.load()&&(un(this,d),a=2,vn(this.H));C(this.H,"timestamp",na());wn(this.H);var e=this.B&&!this.K;if(1==a||ta("Click OK to restore the previous PCx86 machine state, or CANCEL to reset the machine.")){if(c=sn(d)){var f=tn(d,"code"),g=tn(d,"data");f&&("ok"==f?d.load(g):("error"==
|
||||
f&&"no machine state"!=g?(this.Ba("Error: "+g),"unable to verify user"==g&&(za("user",""),this.C=null)):this.rc(f+": "+g),vn(d),d.load()?(c=sn(d),e=!0):c=!1))}e&&rn(this,c?d:null)}else 2==a&&d.clear()}else rn(this);delete this.R;delete this.P}e=Wa(this.id);for(f=0;f<e.length;f++)g=e[f],g!==this&&g!=this.A&&(c=xn(this,g,d,b,c));b=[d,a,c];-1!=a?qn(this,this.Ph,b):this.Ph(b)}};
|
||||
function xn(a,b,c,d,e){if(!b.ea.Sb){b.ea.Sb=!0;if(b.Vb){var f=null;e&&((f=tn(c,b.id))||(f=tn(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=nn,window&&window.location.reload()):a.Y=!0,b.Vb(null),e=!1)}if(!d&&b.Bh)for(a=b.Bh.split("|"),c=0;c<a.length;c++)b.status(a[c])}return e}
|
||||
l.Ph=function(a){var b=a[0],c=0>a[1];a=a[2];this.ka=!0;this.ea.Sb=!0;var d=this.la.power;d&&(d.textContent="Shutdown");this.A&&(xn(this,this.A,b,c,a),qc(this.A));this.Y&&(un(this,b),b.clear());!c&&this.H&&(this.H.clear(),delete this.H);this.G=0};
|
||||
function un(a,b){if(ta("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.1"};e.url=a.ha;e.user=c;e.type="bug";e.data=d;ra("http://www.pcjs.org/api/v1/report",e,!0)}}
|
||||
function yn(a,b,c){var d,e="none";if(a.G)return null;a.G--;var f=new ee(a,"1.24.1"),g=new ee(a,"1.24.1","validate"),h=na();C(g,"timestamp",h);C(f,"timestamp",h);C(f,"version","1.24.1");C(f,"url",window?window.location.href:null);C(f,"browser",window?window.navigator.userAgent:"");a.A&&a.A.Ub&&(c&&rc(a.A),d=a.A.Ub(b,c),"object"===typeof d&&C(f,a.A.id,d),c&&(a.A.ea.Sb=!1,!1===d&&(e=null)));for(var h=Wa(a.id),k=0;k<h.length;k++){var m=h[k];m.ea.Sb&&(m.Ub&&(d=m.Ub(b,c),"object"===typeof d&&C(f,m.id,d)),
|
||||
function un(a,b){if(ta("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.2"};e.url=a.ha;e.user=c;e.type="bug";e.data=d;ra("http://www.pcjs.org/api/v1/report",e,!0)}}
|
||||
function yn(a,b,c){var d,e="none";if(a.G)return null;a.G--;var f=new ee(a,"1.24.2"),g=new ee(a,"1.24.2","validate"),h=na();C(g,"timestamp",h);C(f,"timestamp",h);C(f,"version","1.24.2");C(f,"url",window?window.location.href:null);C(f,"browser",window?window.navigator.userAgent:"");a.A&&a.A.Ub&&(c&&rc(a.A),d=a.A.Ub(b,c),"object"===typeof d&&C(f,a.A.id,d),c&&(a.A.ea.Sb=!1,!1===d&&(e=null)));for(var h=Wa(a.id),k=0;k<h.length;k++){var m=h[k];m.ea.Sb&&(m.Ub&&(d=m.Ub(b,c),"object"===typeof d&&C(f,m.id,d)),
|
||||
c&&(m.ea.Sb=!1,!1===d&&(e=null)))}e&&(c?(h=d=!1,b?(a.C&&zn(a,a.C,f.toString()),wn(g)&&wn(f)||(e=null,d=h=!0)):a.B&&(d=!0,h=3==a.B),d&&f.clear(h)):e=f.toString());c&&(a.ea.Sb=!1,b=a.la.power)&&(b.textContent="Power");a.G=0;return e}l.reset=function(){this.ia&&this.ia.reset&&this.ia.reset();for(var a=Wa(this.id),b=0;b<a.length;b++){var c=a[b];c!==this&&c!==this.ia&&c.reset&&c.reset()}};
|
||||
l.start=function(a,b){for(var c=Wa(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=Wa(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.la[b]=c,c.onclick=function(){d.G||(d.ea.Sb?yn(d,!1,!0):qn(d,d.gf))},!0;case "reset":return this.la[b]=c,c.onclick=function(){if(d.ea.Sb&&!d.G)if(d.B&&!d.S){var a=ta("Click OK to save changes to this PCx86 machine.\n\nWARNING: If you CANCEL, all disk changes will be discarded.");yn(d,a,!0);!a&&d.W?window&&window.location.reload():(a||(d.lg=!0),d.gf(nn),d.lg=!1)}else d.reset(),d.A&&qc(d.A)},!0;case "save":if(ha(sa(),"pcjs.org")){c.parentNode.removeChild(c);
|
||||
break}this.la[b]=c;c.onclick=function(){var a=on(d,!0);if(a){var b=!!(d.B&&!d.S||d.W),c=yn(d,b);b?zn(d,a,c):d.Ba("Resume disabled, machine state not saved")}};return!0}return!1};
|
||||
function on(a,b){var c=a.C;c||(c=ya("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=An(a,c))||a.Ba("The user ID is invalid."))):b&&a.Ba("Browser local storage is not available"));return c}
|
||||
function An(a,b){a.C=null;var c=ra(sa()+"/api/v1/user?req=verify&user="+b),d=c[1];if(!c[0]&&d)try{c=eval("("+d+")"),c.code&&"ok"==c.code&&(za("user",c.data),a.C=c.data)}catch(e){p(e.message+" ("+d+")")}return a.C}function pn(a){var b=null;a.C&&(b=sa()+"/api/v1/user?req=load&user="+a.C+"&state="+Bn(a,"1.24.1"));return b}
|
||||
function zn(a,b,c){if(c){var d={req:"store"};d.user=b;d.state=Bn(a,"1.24.1");d.data=c;b=ra(sa()+"/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),za("user",""),a.C=null)}}
|
||||
function An(a,b){a.C=null;var c=ra(sa()+"/api/v1/user?req=verify&user="+b),d=c[1];if(!c[0]&&d)try{c=eval("("+d+")"),c.code&&"ok"==c.code&&(za("user",c.data),a.C=c.data)}catch(e){p(e.message+" ("+d+")")}return a.C}function pn(a){var b=null;a.C&&(b=sa()+"/api/v1/user?req=load&user="+a.C+"&state="+Bn(a,"1.24.2"));return b}
|
||||
function zn(a,b,c){if(c){var d={req:"store"};d.user=b;d.state=Bn(a,"1.24.2");d.data=c;b=ra(sa()+"/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),za("user",""),a.C=null)}}
|
||||
function nb(a,b,c){a=Wa(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 xc(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.Yd=function(a){this.A&&this.A.Yd(a);this.D&&this.D.Yd(a)};
|
||||
function Ac(a,b){for(var c=0;c<a.I.length;c++)nl(a.I[c],b);if(a.D&&(c=a.D,c.ua)){rb(c,18,c.S,c.ra);if(c.Ga){var d=c.ia,e=c.B,f,g;null==f&&(f=0);null==g&&(g=d.L-f|0);null==e&&(e={hg:0,hd:0,bg:[]});var h=f>>>d.da;f=f+g-1>>>d.da;e.hg=0;for(e.hd=0;h<=f;)g=d.R[h],e.hg+=g.size,g.size&&(e.bg.push(pa(qb,h,0,0,g.type)),e.hd++),h++;c.B=e;c.ma=c.B.hd*c.ia.xb/691200;d=0;c.B.Jh=0;c.B.Ke||(c.B.Ke=[]);var e=-1,h=0,k=-1;for(f=0;f<c.B.hd;f++){var m=c.B.bg[f];g=qa(qb.type,m);m=qa(qb.ej,m);if(g!=e||m!=k+1)(k=f-h)&&
|
||||
(d+=tb(c,h,k,e)),e=g,h=f;k=m}d+=tb(c,h,f-h,e);e=c.B.Ej!=d;c.B.Ej=d;if(e){e=new lb(0,0,c.S.width,c.S.height);c.B.de=[];h=c.B.hd;for(d=0;d<c.B.Jh;d++)f=c.B.Ke[d].hd,c.B.de.push(mb(e,f,h,!d)),h-=f;for(d=0;d<c.B.de.length;d++)e=c.B.Ke[d],h=f=c.B.de[d],g=c.ra,(k=Zb[e.type])||(k=new kb),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.ha,h.L=h.ka,f=g.x+(g.Fc>>1),k=g.y+(g.A>>1),m=g.A,g.Fc<g.A&&(m=g.Fc,h.da=!0,h.G.save(),
|
||||
|
|
@ -631,9 +631,9 @@ h=null;if("<"==a.charAt(0))try{e||(a=a.replace(/<!DOCTYPE(.|[\r\n])*]>\s*/g,""))
|
|||
function Fn(a,b,c){var d;if(d=/<([a-z]+)\s+ref="(.*?)"(.*?)\/>/g.exec(a)){var e=d[2];b("Loading "+e+"...");ra(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]*/,
|
||||
"");a=a.replace(d[0],g);Fn(a,b,c)}})}else c(a,null)}
|
||||
function Gn(a,b,c,d){function e(a){if(void 0===h){var b=g&&bb(g,"machine-warning");h=b&&b[0]||g}h&&(h.innerHTML=ja(a))}function f(a){e("Error: "+a);k&&(--Cn||Ja(!0));k=!1}var g,h,k=!0;Cn++;Ua[a]={};try{if(g=document.getElementById(a)){var m;if("object"==typeof resources&&(m=resources.css)){var n=document.head||document.getElementsByTagName("head")[0],x=document.createElement("style");x.type="text/css";x.styleSheet?x.styleSheet.cssText=m:x.appendChild(document.createTextNode(m));n.appendChild(x)}c||
|
||||
(c="/versions/pcx86/1.24.1/components.xsl");m=function(d,h){h?Dn(c,null,null,!1,e,function(d,k){if(k)if(Va(a,c,d),e("Processing "+b+"..."),window.ActiveXObject||"ActiveXObject"in window){var m=h.transformNode(k);m?(g.outerHTML=m,--Cn||Ja(!0)):f("transformNodeToObject failed")}else document.implementation&&document.implementation.createDocument?(m=new XSLTProcessor,m.importStylesheet(k),(m=m.transformToFragment(h,document))?g.parentNode?(g.parentNode.replaceChild(m,g),--Cn||Ja(!0)):f("invalid machine element: "+
|
||||
(c="/versions/pcx86/1.24.2/components.xsl");m=function(d,h){h?Dn(c,null,null,!1,e,function(d,k){if(k)if(Va(a,c,d),e("Processing "+b+"..."),window.ActiveXObject||"ActiveXObject"in window){var m=h.transformNode(k);m?(g.outerHTML=m,--Cn||Ja(!0)):f("transformNodeToObject failed")}else document.implementation&&document.implementation.createDocument?(m=new XSLTProcessor,m.importStylesheet(k),(m=m.transformToFragment(h,document))?g.parentNode?(g.parentNode.replaceChild(m,g),--Cn||Ja(!0)):f("invalid machine element: "+
|
||||
a):f("transformToFragment failed")):f("unable to transform XML: unsupported browser");else f(d)}):f(d)};"<"!=b.charAt(0)?Dn(b,a,d,!0,e,m):En(b,null,a,d,!1,e,m)}else f("missing machine element: "+a)}catch(r){f(r.message)}return k}function Hn(a,b,c,d){Ja(!1);return Gn(a,b,c,d)}window.embedPC=Hn;window.embedPCx86=Hn;window.enableEvents=Ja;window.sendEvent=Ka;
|
||||
function In(a,b,c,d){if(!c&&b){d.push(b);a=Ua[d[0]];b=null;for(var e in a)if(ha(e,"components.xsl")){b=e.replace(".xsl",".css");break}b?ra(b,null,!0,function(a,b){Jn(b,d)}):Jn(null,d)}else p("Error ("+c+") requesting "+a)}
|
||||
function Jn(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=Ua[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,
|
||||
"©"),c=Ba(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=Ya("Computer",a),e=Ya("Debugger",a);if(d){var f=yn(d,!0),g=d.L?JSON.stringify(d.L):null;b||(b="/versions/pcjs/1.24.1/pc"+(e?"-dbg":"")+".js");if(c&&c({state:f,ij:g}))return!0;ra(b,null,!0,function(c,d,e){In(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=Ya("Computer",a),e=Ya("Debugger",a);if(d){var f=yn(d,!0),g=d.L?JSON.stringify(d.L):null;b||(b="/versions/pcjs/1.24.2/pc"+(e?"-dbg":"")+".js");if(c&&c({state:f,ij:g}))return!0;ra(b,null,!0,function(c,d,e){In(c,d,e,[a,fa(b,!0),g,f])});return!0}p("Unable to identify machine '"+a+"'");return!1};})();
|
||||
|
|
|
|||
|
|
@ -79,20 +79,19 @@ function CPU8080(parmsCPU, nCyclesDefault)
|
|||
|
||||
var nMultiplier = parmsCPU['multiplier'] || 1;
|
||||
|
||||
this.counts = {};
|
||||
this.counts.nCyclesPerSecond = nCycles;
|
||||
this.nCyclesPerSecond = nCycles;
|
||||
|
||||
/*
|
||||
* nCyclesMultiplier replaces the old "speed" variable (0, 1, 2) and eliminates the need for
|
||||
* the constants (SPEED_SLOW, SPEED_FAST and SPEED_MAX). The UI simply doubles the multiplier
|
||||
* until we've exceeded the host's speed limit and then starts the multiplier over at 1.
|
||||
*/
|
||||
this.counts.nCyclesMultiplier = nMultiplier;
|
||||
this.counts.mhzDefault = Math.round(this.counts.nCyclesPerSecond / 10000) / 100;
|
||||
this.nCyclesMultiplier = nMultiplier;
|
||||
this.mhzDefault = Math.round(this.nCyclesPerSecond / 10000) / 100;
|
||||
/*
|
||||
* TODO: Take care of this with an initial setSpeed() call instead?
|
||||
*/
|
||||
this.counts.mhzTarget = this.counts.mhzDefault * this.counts.nCyclesMultiplier;
|
||||
this.mhzTarget = this.mhzDefault * this.nCyclesMultiplier;
|
||||
|
||||
/*
|
||||
* We add a number of flags to the set initialized by Component
|
||||
|
|
@ -116,10 +115,10 @@ function CPU8080(parmsCPU, nCyclesDefault)
|
|||
* and call resetChecksum().
|
||||
*/
|
||||
this.flags.fChecksum = false;
|
||||
this.counts.nChecksum = this.counts.nCyclesChecksumNext = 0;
|
||||
this.counts.nCyclesChecksumStart = parmsCPU["csStart"];
|
||||
this.counts.nCyclesChecksumInterval = parmsCPU["csInterval"];
|
||||
this.counts.nCyclesChecksumStop = parmsCPU["csStop"];
|
||||
this.nChecksum = this.nCyclesChecksumNext = 0;
|
||||
this.nCyclesChecksumStart = parmsCPU["csStart"];
|
||||
this.nCyclesChecksumInterval = parmsCPU["csInterval"];
|
||||
this.nCyclesChecksumStop = parmsCPU["csStop"];
|
||||
|
||||
/*
|
||||
* Array of countdown timers managed by addTimer() and setTimer().
|
||||
|
|
@ -140,12 +139,12 @@ Component.subclass(CPU8080);
|
|||
* calcCycles(), which uses the nCyclesPerSecond passed to the constructor as a starting
|
||||
* point and computes the following variables:
|
||||
*
|
||||
* this.counts.nCyclesPerYield: (this.counts.nCyclesPerSecond / CPU8080.YIELDS_PER_SECOND)
|
||||
* this.nCyclesPerYield: (this.nCyclesPerSecond / CPU8080.YIELDS_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:
|
||||
*
|
||||
* this.counts.nCyclesNextYield: this.counts.nCyclesPerYield
|
||||
* this.nCyclesNextYield: this.nCyclesPerYield
|
||||
*/
|
||||
CPU8080.YIELDS_PER_SECOND = 30; // just a gut feeling for the MINIMUM number of yields per second
|
||||
CPU8080.YIELDS_PER_STATUS = 15; // every 15 yields (ie, twice per second), perform CPU status updates
|
||||
|
|
@ -362,16 +361,16 @@ CPU8080.prototype.getChecksum = function()
|
|||
*/
|
||||
CPU8080.prototype.resetChecksum = function()
|
||||
{
|
||||
if (this.counts.nCyclesChecksumStart === undefined) this.counts.nCyclesChecksumStart = 0;
|
||||
if (this.counts.nCyclesChecksumInterval === undefined) this.counts.nCyclesChecksumInterval = -1;
|
||||
if (this.counts.nCyclesChecksumStop === undefined) this.counts.nCyclesChecksumStop = -1;
|
||||
this.flags.fChecksum = (this.counts.nCyclesChecksumStart >= 0 && this.counts.nCyclesChecksumInterval > 0);
|
||||
if (this.nCyclesChecksumStart === undefined) this.nCyclesChecksumStart = 0;
|
||||
if (this.nCyclesChecksumInterval === undefined) this.nCyclesChecksumInterval = -1;
|
||||
if (this.nCyclesChecksumStop === undefined) this.nCyclesChecksumStop = -1;
|
||||
this.flags.fChecksum = (this.nCyclesChecksumStart >= 0 && this.nCyclesChecksumInterval > 0);
|
||||
if (this.flags.fChecksum) {
|
||||
this.counts.nChecksum = 0;
|
||||
this.counts.nCyclesChecksumNext = this.counts.nCyclesChecksumStart - this.nTotalCycles;
|
||||
this.nChecksum = 0;
|
||||
this.nCyclesChecksumNext = this.nCyclesChecksumStart - this.nTotalCycles;
|
||||
/*
|
||||
* this.counts.nCyclesChecksumNext = this.counts.nCyclesChecksumStart + this.counts.nCyclesChecksumInterval -
|
||||
* (this.nTotalCycles % this.counts.nCyclesChecksumInterval);
|
||||
* this.nCyclesChecksumNext = this.nCyclesChecksumStart + this.nCyclesChecksumInterval -
|
||||
* (this.nTotalCycles % this.nCyclesChecksumInterval);
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
|
@ -396,15 +395,15 @@ CPU8080.prototype.updateChecksum = function(nCycles)
|
|||
* Get a 32-bit summation of the current CPU state and add it to our running 32-bit checksum
|
||||
*/
|
||||
var fDisplay = false;
|
||||
this.counts.nChecksum = (this.counts.nChecksum + this.getChecksum())|0;
|
||||
this.counts.nCyclesChecksumNext -= nCycles;
|
||||
if (this.counts.nCyclesChecksumNext <= 0) {
|
||||
this.counts.nCyclesChecksumNext += this.counts.nCyclesChecksumInterval;
|
||||
this.nChecksum = (this.nChecksum + this.getChecksum())|0;
|
||||
this.nCyclesChecksumNext -= nCycles;
|
||||
if (this.nCyclesChecksumNext <= 0) {
|
||||
this.nCyclesChecksumNext += this.nCyclesChecksumInterval;
|
||||
fDisplay = true;
|
||||
}
|
||||
if (this.counts.nCyclesChecksumStop >= 0) {
|
||||
if (this.counts.nCyclesChecksumStop <= this.getCycles()) {
|
||||
this.counts.nCyclesChecksumInterval = this.counts.nCyclesChecksumStop = -1;
|
||||
if (this.nCyclesChecksumStop >= 0) {
|
||||
if (this.nCyclesChecksumStop <= this.getCycles()) {
|
||||
this.nCyclesChecksumInterval = this.nCyclesChecksumStop = -1;
|
||||
this.resetChecksum();
|
||||
this.stopCPU();
|
||||
fDisplay = true;
|
||||
|
|
@ -425,7 +424,7 @@ CPU8080.prototype.updateChecksum = function(nCycles)
|
|||
*/
|
||||
CPU8080.prototype.displayChecksum = function()
|
||||
{
|
||||
this.println(this.getCycles() + " cycles: " + "checksum=" + str.toHex(this.counts.nChecksum));
|
||||
this.println(this.getCycles() + " cycles: " + "checksum=" + str.toHex(this.nChecksum));
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -514,7 +513,7 @@ CPU8080.prototype.setBinding = function(sHTMLType, sBinding, control, sValue)
|
|||
case "setSpeed":
|
||||
this.bindings[sBinding] = control;
|
||||
control.onclick = function onClickSetSpeed() {
|
||||
cpu.setSpeed(cpu.counts.nCyclesMultiplier << 1, true);
|
||||
cpu.setSpeed(cpu.nCyclesMultiplier << 1, true);
|
||||
};
|
||||
control.textContent = this.getSpeedTarget();
|
||||
fBound = true;
|
||||
|
|
@ -597,21 +596,21 @@ CPU8080.prototype.calcCycles = function(fRecalc)
|
|||
*/
|
||||
var vMultiplier = 1;
|
||||
if (fRecalc) {
|
||||
if (this.counts.nCyclesMultiplier > 1 && this.counts.mhz) {
|
||||
vMultiplier = (this.counts.mhz / this.counts.mhzDefault);
|
||||
if (this.nCyclesMultiplier > 1 && this.mhz) {
|
||||
vMultiplier = (this.mhz / this.mhzDefault);
|
||||
}
|
||||
}
|
||||
|
||||
this.counts.msPerYield = Math.round(1000 / CPU8080.YIELDS_PER_SECOND);
|
||||
this.counts.nCyclesPerYield = Math.floor(this.counts.nCyclesPerSecond / CPU8080.YIELDS_PER_SECOND * vMultiplier);
|
||||
this.msPerYield = Math.round(1000 / CPU8080.YIELDS_PER_SECOND);
|
||||
this.nCyclesPerYield = Math.floor(this.nCyclesPerSecond / CPU8080.YIELDS_PER_SECOND * vMultiplier);
|
||||
|
||||
/*
|
||||
* And initialize "next" yield values to the "per" values.
|
||||
*/
|
||||
if (!fRecalc) {
|
||||
this.counts.nCyclesNextYield = this.counts.nCyclesPerYield;
|
||||
this.nCyclesNextYield = this.nCyclesPerYield;
|
||||
}
|
||||
this.counts.nCyclesRecalc = 0;
|
||||
this.nCyclesRecalc = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -634,11 +633,11 @@ CPU8080.prototype.calcCycles = function(fRecalc)
|
|||
CPU8080.prototype.getCycles = function(fScaled)
|
||||
{
|
||||
var nCycles = this.nTotalCycles + this.nRunCycles + this.nBurstCycles - this.nStepCycles;
|
||||
if (fScaled && this.counts.nCyclesMultiplier > 1 && this.counts.mhz > this.counts.mhzDefault) {
|
||||
if (fScaled && this.nCyclesMultiplier > 1 && this.mhz > this.mhzDefault) {
|
||||
/*
|
||||
* We could scale the current cycle count by the current effective speed (this.counts.mhz); eg:
|
||||
* We could scale the current cycle count by the current effective speed (this.mhz); eg:
|
||||
*
|
||||
* nCycles = Math.round(nCycles / (this.counts.mhz / this.counts.mhzDefault));
|
||||
* nCycles = Math.round(nCycles / (this.mhz / this.mhzDefault));
|
||||
*
|
||||
* but that speed will fluctuate somewhat: large fluctuations at first, but increasingly smaller
|
||||
* fluctuations after each burst of instructions that runCPU() executes.
|
||||
|
|
@ -653,7 +652,7 @@ CPU8080.prototype.getCycles = function(fScaled)
|
|||
* interface allows any value, as does the CPU "multiplier" parmsCPU property (from the machine's
|
||||
* XML file).
|
||||
*/
|
||||
nCycles = Math.round(nCycles / this.counts.nCyclesMultiplier);
|
||||
nCycles = Math.round(nCycles / this.nCyclesMultiplier);
|
||||
}
|
||||
return nCycles;
|
||||
};
|
||||
|
|
@ -668,7 +667,7 @@ CPU8080.prototype.getCycles = function(fScaled)
|
|||
*/
|
||||
CPU8080.prototype.getCyclesPerSecond = function()
|
||||
{
|
||||
return this.counts.nCyclesPerSecond;
|
||||
return this.nCyclesPerSecond;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -682,8 +681,8 @@ CPU8080.prototype.getCyclesPerSecond = function()
|
|||
*/
|
||||
CPU8080.prototype.resetCycles = function()
|
||||
{
|
||||
this.counts.mhz = 0;
|
||||
this.counts.nYieldsSinceStatusUpdate = 0;
|
||||
this.mhz = 0;
|
||||
this.nYieldsSinceStatusUpdate = 0;
|
||||
this.nTotalCycles = this.nRunCycles = this.nBurstCycles = this.nStepCycles = 0;
|
||||
this.resetChecksum();
|
||||
this.setSpeed(1);
|
||||
|
|
@ -697,7 +696,7 @@ CPU8080.prototype.resetCycles = function()
|
|||
*/
|
||||
CPU8080.prototype.getSpeed = function()
|
||||
{
|
||||
return this.counts.nCyclesMultiplier;
|
||||
return this.nCyclesMultiplier;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -711,7 +710,7 @@ CPU8080.prototype.getSpeedCurrent = function()
|
|||
/*
|
||||
* TODO: Has toFixed() been "fixed" in all browsers (eg, IE) to return a rounded value now?
|
||||
*/
|
||||
return ((this.flags.fRunning && this.counts.mhz)? (this.counts.mhz.toFixed(2) + "Mhz") : "Stopped");
|
||||
return ((this.flags.fRunning && this.mhz)? (this.mhz.toFixed(2) + "Mhz") : "Stopped");
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -725,7 +724,7 @@ CPU8080.prototype.getSpeedTarget = function()
|
|||
/*
|
||||
* TODO: Has toFixed() been "fixed" in all browsers (eg, IE) to return a rounded value now?
|
||||
*/
|
||||
return this.counts.mhzTarget.toFixed(2) + "Mhz";
|
||||
return this.mhzTarget.toFixed(2) + "Mhz";
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -749,15 +748,15 @@ CPU8080.prototype.setSpeed = function(nMultiplier, fUpdateFocus)
|
|||
/*
|
||||
* If we haven't reached 80% (0.8) of the current target speed, revert to a multiplier of one (1).
|
||||
*/
|
||||
if (this.counts.mhz / this.counts.mhzTarget < 0.8) {
|
||||
if (this.mhz / this.mhzTarget < 0.8) {
|
||||
nMultiplier = 1;
|
||||
} else {
|
||||
fSuccess = true;
|
||||
}
|
||||
this.counts.nCyclesMultiplier = nMultiplier;
|
||||
var mhz = this.counts.mhzDefault * this.counts.nCyclesMultiplier;
|
||||
if (this.counts.mhzTarget != mhz) {
|
||||
this.counts.mhzTarget = mhz;
|
||||
this.nCyclesMultiplier = nMultiplier;
|
||||
var mhz = this.mhzDefault * this.nCyclesMultiplier;
|
||||
if (this.mhzTarget != mhz) {
|
||||
this.mhzTarget = mhz;
|
||||
var sSpeed = this.getSpeedTarget();
|
||||
var controlSpeed = this.bindings["setSpeed"];
|
||||
if (controlSpeed) controlSpeed.textContent = sSpeed;
|
||||
|
|
@ -767,8 +766,8 @@ CPU8080.prototype.setSpeed = function(nMultiplier, fUpdateFocus)
|
|||
}
|
||||
this.addCycles(this.nRunCycles);
|
||||
this.nRunCycles = 0;
|
||||
this.counts.msStartRun = usr.getTime();
|
||||
this.counts.msEndThisRun = 0;
|
||||
this.msStartRun = usr.getTime();
|
||||
this.msEndThisRun = 0;
|
||||
this.calcCycles();
|
||||
return fSuccess;
|
||||
};
|
||||
|
|
@ -783,7 +782,7 @@ CPU8080.prototype.setSpeed = function(nMultiplier, fUpdateFocus)
|
|||
CPU8080.prototype.calcSpeed = function(nCycles, msElapsed)
|
||||
{
|
||||
if (msElapsed) {
|
||||
this.counts.mhz = Math.round(nCycles / (msElapsed * 10)) / 100;
|
||||
this.mhz = Math.round(nCycles / (msElapsed * 10)) / 100;
|
||||
if (msElapsed >= 86400000) {
|
||||
this.nTotalCycles = 0;
|
||||
this.setSpeed(); // reset all counters once per day so that we never have to worry about overflow
|
||||
|
|
@ -798,11 +797,11 @@ CPU8080.prototype.calcSpeed = function(nCycles, msElapsed)
|
|||
*/
|
||||
CPU8080.prototype.calcStartTime = function()
|
||||
{
|
||||
if (this.counts.nCyclesRecalc >= this.counts.nCyclesPerSecond) {
|
||||
if (this.nCyclesRecalc >= this.nCyclesPerSecond) {
|
||||
this.calcCycles(true);
|
||||
}
|
||||
this.counts.nCyclesThisRun = 0;
|
||||
this.counts.msStartThisRun = usr.getTime();
|
||||
this.nCyclesThisRun = 0;
|
||||
this.msStartThisRun = usr.getTime();
|
||||
|
||||
/*
|
||||
* Try to detect situations where the browser may have throttled us, such as when the user switches
|
||||
|
|
@ -829,19 +828,19 @@ CPU8080.prototype.calcStartTime = function()
|
|||
* to hit its target speed, since you would expect any instruction that displays a message to be an
|
||||
* EXTREMELY slow instruction.
|
||||
*/
|
||||
if (this.counts.msEndThisRun) {
|
||||
var msDelta = this.counts.msStartThisRun - this.counts.msEndThisRun;
|
||||
if (msDelta > this.counts.msPerYield) {
|
||||
if (this.msEndThisRun) {
|
||||
var msDelta = this.msStartThisRun - this.msEndThisRun;
|
||||
if (msDelta > this.msPerYield) {
|
||||
if (MAXDEBUG) this.println("large time delay: " + msDelta + "ms");
|
||||
this.counts.msStartRun += msDelta;
|
||||
this.msStartRun += msDelta;
|
||||
/*
|
||||
* Bumping msStartRun forward should NEVER cause it to exceed msStartThisRun; however, just
|
||||
* in case, I make absolutely sure it cannot happen, since doing so could result in negative
|
||||
* speed calculations.
|
||||
*/
|
||||
this.assert(this.counts.msStartRun <= this.counts.msStartThisRun);
|
||||
if (this.counts.msStartRun > this.counts.msStartThisRun) {
|
||||
this.counts.msStartRun = this.counts.msStartThisRun;
|
||||
this.assert(this.msStartRun <= this.msStartThisRun);
|
||||
if (this.msStartRun > this.msStartThisRun) {
|
||||
this.msStartRun = this.msStartThisRun;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -855,47 +854,55 @@ CPU8080.prototype.calcStartTime = function()
|
|||
*/
|
||||
CPU8080.prototype.calcRemainingTime = function()
|
||||
{
|
||||
this.counts.msEndThisRun = usr.getTime();
|
||||
this.msEndThisRun = usr.getTime();
|
||||
|
||||
var msYield = this.counts.msPerYield;
|
||||
if (this.counts.nCyclesThisRun) {
|
||||
var msYield = this.msPerYield;
|
||||
if (this.nCyclesThisRun) {
|
||||
/*
|
||||
* Normally, we would assume we executed a full quota of work over msPerYield, but since the CPU
|
||||
* now has the option of calling yieldCPU(), that might not be true. If nCyclesThisRun is correct, then
|
||||
* the ratio of nCyclesThisRun/nCyclesPerYield should represent the percentage of work we performed,
|
||||
* and so applying that percentage to msPerYield should give us a better estimate of work vs. time.
|
||||
*/
|
||||
msYield = Math.round(msYield * this.counts.nCyclesThisRun / this.counts.nCyclesPerYield);
|
||||
msYield = Math.round(msYield * this.nCyclesThisRun / this.nCyclesPerYield);
|
||||
}
|
||||
|
||||
var msElapsedThisRun = this.counts.msEndThisRun - this.counts.msStartThisRun;
|
||||
var msElapsedThisRun = this.msEndThisRun - this.msStartThisRun;
|
||||
var msRemainsThisRun = msYield - msElapsedThisRun;
|
||||
|
||||
/*
|
||||
* We could pass only "this run" results to calcSpeed():
|
||||
*
|
||||
* nCycles = this.counts.nCyclesThisRun;
|
||||
* nCycles = this.nCyclesThisRun;
|
||||
* msElapsed = msElapsedThisRun;
|
||||
*
|
||||
* but it seems preferable to use longer time periods and hopefully get a more accurate speed.
|
||||
*
|
||||
* Also, if msRemainsThisRun >= 0 && this.counts.nCyclesMultiplier == 1, we could pass these results instead:
|
||||
* Also, if msRemainsThisRun >= 0 && this.nCyclesMultiplier == 1, we could pass these results instead:
|
||||
*
|
||||
* nCycles = this.counts.nCyclesThisRun;
|
||||
* msElapsed = this.counts.msPerYield;
|
||||
* nCycles = this.nCyclesThisRun;
|
||||
* msElapsed = this.msPerYield;
|
||||
*
|
||||
* to insure that we display a smooth, constant N Mhz. But for now, I prefer seeing any fluctuations.
|
||||
*/
|
||||
var nCycles = this.nRunCycles;
|
||||
var msElapsed = this.counts.msEndThisRun - this.counts.msStartRun;
|
||||
var msElapsed = this.msEndThisRun - this.msStartRun;
|
||||
|
||||
if (MAXDEBUG && msRemainsThisRun < 0 && this.counts.nCyclesMultiplier > 1) {
|
||||
if (MAXDEBUG && msRemainsThisRun < 0 && this.nCyclesMultiplier > 1) {
|
||||
this.println("warning: updates @" + msElapsedThisRun + "ms (prefer " + Math.round(msYield) + "ms)");
|
||||
}
|
||||
|
||||
this.calcSpeed(nCycles, msElapsed);
|
||||
|
||||
if (msRemainsThisRun < 0 || this.counts.mhz < this.counts.mhzTarget) {
|
||||
if (msRemainsThisRun < 0 || this.mhz < this.mhzTarget) {
|
||||
/*
|
||||
* Try "throwing out" the effects of large anomalies, by moving the overall run start time up;
|
||||
* ordinarily, this should only happen when the someone is using an external Debugger or some other
|
||||
* tool or feature that is interfering with our overall execution.
|
||||
*/
|
||||
if (msRemainsThisRun < -1000) {
|
||||
this.msStartRun -= msRemainsThisRun;
|
||||
}
|
||||
/*
|
||||
* If the last burst took MORE time than we allotted (ie, it's taking more than 1 second to simulate
|
||||
* nCyclesPerSecond), all we can do is yield for as little time as possible (ie, 0ms) and hope that the
|
||||
|
|
@ -908,13 +915,13 @@ CPU8080.prototype.calcRemainingTime = function()
|
|||
* Last but not least, update nCyclesRecalc, so that when runCPU() starts up again and calls calcStartTime(),
|
||||
* it'll be ready to decide if calcCycles() should be called again.
|
||||
*/
|
||||
this.counts.nCyclesRecalc += this.counts.nCyclesThisRun;
|
||||
this.nCyclesRecalc += this.nCyclesThisRun;
|
||||
|
||||
if (DEBUG && this.messageEnabled(Messages8080.LOG) && msRemainsThisRun) {
|
||||
this.log("calcRemainingTime: " + msRemainsThisRun + "ms to sleep after " + this.counts.msEndThisRun + "ms");
|
||||
this.log("calcRemainingTime: " + msRemainsThisRun + "ms to sleep after " + this.msEndThisRun + "ms");
|
||||
}
|
||||
|
||||
this.counts.msEndThisRun += msRemainsThisRun;
|
||||
this.msEndThisRun += msRemainsThisRun;
|
||||
return msRemainsThisRun;
|
||||
};
|
||||
|
||||
|
|
@ -981,7 +988,7 @@ CPU8080.prototype.setTimer = function(iTimer, ms)
|
|||
*/
|
||||
CPU8080.prototype.getMSCycles = function(ms)
|
||||
{
|
||||
return (this.counts.nCyclesPerSecond * this.counts.nCyclesMultiplier) / 1000 * ms;
|
||||
return (this.nCyclesPerSecond * this.nCyclesMultiplier) / 1000 * ms;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -1057,7 +1064,7 @@ CPU8080.prototype.runCPU = function(fUpdateFocus)
|
|||
* be as HIGH as nCyclesPerYield, but it may be significantly less. getBurstCycles() will adjust
|
||||
* nCyclesPerBurst downward if any CPU timers need to fire during the next burst.
|
||||
*/
|
||||
var nCyclesPerBurst = this.getBurstCycles(this.flags.fChecksum? 1 : this.counts.nCyclesPerYield);
|
||||
var nCyclesPerBurst = this.getBurstCycles(this.flags.fChecksum? 1 : this.nCyclesPerYield);
|
||||
|
||||
/*
|
||||
* Execute the burst.
|
||||
|
|
@ -1077,17 +1084,17 @@ CPU8080.prototype.runCPU = function(fUpdateFocus)
|
|||
/*
|
||||
* Add nCycles to nCyclesThisRun, as well as nRunCycles (the cycle count since the CPU first started).
|
||||
*/
|
||||
this.counts.nCyclesThisRun += nCycles;
|
||||
this.nCyclesThisRun += nCycles;
|
||||
this.nRunCycles += nCycles;
|
||||
this.addCycles(0, true);
|
||||
this.updateChecksum(nCycles);
|
||||
|
||||
this.counts.nCyclesNextYield -= nCycles;
|
||||
if (this.counts.nCyclesNextYield <= 0) {
|
||||
this.counts.nCyclesNextYield += this.counts.nCyclesPerYield;
|
||||
if (++this.counts.nYieldsSinceStatusUpdate >= CPU8080.YIELDS_PER_STATUS) {
|
||||
this.nCyclesNextYield -= nCycles;
|
||||
if (this.nCyclesNextYield <= 0) {
|
||||
this.nCyclesNextYield += this.nCyclesPerYield;
|
||||
if (++this.nYieldsSinceStatusUpdate >= CPU8080.YIELDS_PER_STATUS) {
|
||||
if (this.cmp) this.cmp.updateStatus();
|
||||
this.counts.nYieldsSinceStatusUpdate = 0;
|
||||
this.nYieldsSinceStatusUpdate = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -1122,7 +1129,7 @@ CPU8080.prototype.startCPU = function(fUpdateFocus)
|
|||
* threshold counter.
|
||||
*/
|
||||
this.setSpeed();
|
||||
if (this.cmp) this.cmp.start(this.counts.msStartRun, this.getCycles());
|
||||
if (this.cmp) this.cmp.start(this.msStartRun, this.getCycles());
|
||||
this.flags.fRunning = true;
|
||||
this.flags.fStarting = true;
|
||||
if (this.chipset) this.chipset.start();
|
||||
|
|
@ -1205,7 +1212,7 @@ CPU8080.prototype.updateCPU = function(fForce)
|
|||
*/
|
||||
CPU8080.prototype.yieldCPU = function()
|
||||
{
|
||||
this.counts.nCyclesNextYield = 0; // this will break us out of runCPU(), once we break out of stepCPU()
|
||||
this.nCyclesNextYield = 0; // this will break us out of runCPU(), once we break out of stepCPU()
|
||||
this.nBurstCycles -= this.nStepCycles;
|
||||
this.nStepCycles = 0; // this will break us out of stepCPU()
|
||||
// if (DEBUG) this.nSnapCycles = this.nBurstCycles;
|
||||
|
|
|
|||
|
|
@ -2465,7 +2465,7 @@ if (DEBUGGER) {
|
|||
sLine += (nSequence != null? '=' + nSequence.toString() : "");
|
||||
} else {
|
||||
var nCycles = this.cpu.getCycles();
|
||||
sLine += "cycles=" + nCycles.toString() + " cs=" + str.toHex(this.cpu.counts.nChecksum);
|
||||
sLine += "cycles=" + nCycles.toString() + " cs=" + str.toHex(this.cpu.nChecksum);
|
||||
}
|
||||
}
|
||||
return sLine;
|
||||
|
|
@ -3719,8 +3719,8 @@ if (DEBUGGER) {
|
|||
Debugger8080.prototype.doInfo = function(asArgs)
|
||||
{
|
||||
if (DEBUG) {
|
||||
this.println("msPerYield: " + this.cpu.counts.msPerYield);
|
||||
this.println("nCyclesPerYield: " + this.cpu.counts.nCyclesPerYield);
|
||||
this.println("msPerYield: " + this.cpu.msPerYield);
|
||||
this.println("nCyclesPerYield: " + this.cpu.nCyclesPerYield);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
@ -3971,13 +3971,13 @@ if (DEBUGGER) {
|
|||
if (asArgs[3] !== undefined) nCycles = +asArgs[3]; // warning: decimal instead of hex conversion
|
||||
switch (asArgs[2]) {
|
||||
case "int":
|
||||
this.cpu.counts.nCyclesChecksumInterval = nCycles;
|
||||
this.cpu.nCyclesChecksumInterval = nCycles;
|
||||
break;
|
||||
case "start":
|
||||
this.cpu.counts.nCyclesChecksumStart = nCycles;
|
||||
this.cpu.nCyclesChecksumStart = nCycles;
|
||||
break;
|
||||
case "stop":
|
||||
this.cpu.counts.nCyclesChecksumStop = nCycles;
|
||||
this.cpu.nCyclesChecksumStop = nCycles;
|
||||
break;
|
||||
default:
|
||||
this.println("unknown cs option");
|
||||
|
|
|
|||
Loading…
Reference in a new issue