Smoothed out PCx86 dynamic CPU speed recalculation by no longer truncating the current cycle multiplier
This commit is contained in:
parent
591d6b85d5
commit
7f973a03b9
23 changed files with 1351 additions and 1308 deletions
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
|
|
@ -7345,12 +7345,15 @@ Messages.CATEGORIES = {
|
|||
"computer": Messages.COMPUTER,
|
||||
"dos": Messages.DOS,
|
||||
"data": Messages.DATA,
|
||||
"log": Messages.LOG,
|
||||
"warn": Messages.WARN,
|
||||
/*
|
||||
* Now we turn to message actions rather than message types; for example, setting "halt"
|
||||
* on or off doesn't enable "halt" messages, but rather halts the CPU on any message above.
|
||||
*
|
||||
* Similarly, "m log on" turns on message logging, deferring the display of all messages
|
||||
* until "m log off" is issued.
|
||||
*/
|
||||
"log": Messages.LOG,
|
||||
"warn": Messages.WARN,
|
||||
"halt": Messages.HALT
|
||||
};
|
||||
|
||||
|
|
@ -12314,7 +12317,7 @@ class CPU extends Component {
|
|||
*/
|
||||
calcCycles()
|
||||
{
|
||||
var nMultiplier = (this.counts.mhzCurrent / this.counts.mhzBase)|0;
|
||||
var nMultiplier = this.counts.mhzCurrent / this.counts.mhzBase;
|
||||
if (!nMultiplier || nMultiplier > this.counts.nTargetMultiplier) nMultiplier = this.counts.nTargetMultiplier;
|
||||
this.counts.msPerYield = Math.round(1000 / CPU.YIELDS_PER_SECOND);
|
||||
this.counts.nCyclesPerYield = Math.floor(this.counts.nBaseCyclesPerSecond / CPU.YIELDS_PER_SECOND * nMultiplier);
|
||||
|
|
@ -12457,9 +12460,9 @@ class CPU extends Component {
|
|||
var fSuccess = true;
|
||||
if (nMultiplier !== undefined) {
|
||||
/*
|
||||
* If we haven't reached 80% (0.8) of the current target speed, revert to the default multiplier.
|
||||
* If we haven't reached 90% (0.9) of the current target speed, revert to the default multiplier.
|
||||
*/
|
||||
if (this.counts.mhzCurrent > 0 && this.counts.mhzCurrent / this.counts.mhzTarget < 0.8) {
|
||||
if (this.counts.mhzCurrent > 0 && this.counts.mhzCurrent < this.counts.mhzTarget * 0.9) {
|
||||
nMultiplier = this.counts.nBaseMultiplier;
|
||||
fSuccess = false;
|
||||
}
|
||||
|
|
@ -12599,7 +12602,7 @@ class CPU extends Component {
|
|||
|
||||
this.calcSpeed(nCycles, msElapsed);
|
||||
|
||||
if (msRemainsThisRun < 0 || this.counts.mhzCurrent < this.counts.mhzTarget) {
|
||||
if (msRemainsThisRun < 0) {
|
||||
/*
|
||||
* 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
|
||||
|
|
@ -12610,14 +12613,17 @@ class CPU extends Component {
|
|||
}
|
||||
/*
|
||||
* If the last burst took MORE time than we allotted (ie, it's taking more than 1 second to simulate
|
||||
* nCyclesActual), all we can do is yield for as little time as possible (ie, 0ms) and hope that the
|
||||
* simulation is at least usable.
|
||||
* nBaseCyclesPerSecond), all we can do is yield for as little time as possible (ie, 0ms) and hope
|
||||
* that the simulation is at least usable.
|
||||
*/
|
||||
msRemainsThisRun = 0;
|
||||
}
|
||||
else if (this.counts.mhzCurrent < this.counts.mhzTarget) {
|
||||
msRemainsThisRun = 0;
|
||||
}
|
||||
|
||||
if (DEBUG && this.messageEnabled(Messages.LOG) && msRemainsThisRun) {
|
||||
this.log("calcRemainingTime: " + msRemainsThisRun + "ms to sleep after " + this.counts.msEndThisRun + "ms");
|
||||
if (DEBUG && this.messageEnabled(Messages.CPU)) {
|
||||
this.printMessage("calcRemainingTime: sleep " + msRemainsThisRun + "ms after " + (this.counts.msEndThisRun - this.counts.msStartThisRun) + "ms burst");
|
||||
}
|
||||
|
||||
this.counts.msEndThisRun += msRemainsThisRun;
|
||||
|
|
@ -12846,9 +12852,17 @@ class CPU extends Component {
|
|||
if (timer[1] < 0) continue;
|
||||
timer[1] -= nCycles;
|
||||
if (timer[1] <= 0) {
|
||||
if (DEBUG && this.messageEnabled(Messages.CPU)) {
|
||||
this.printMessage("updateTimer(" + nCycles + "): firing " + timer[0] + " with only " + (timer[1] + nCycles) + " cycles left");
|
||||
}
|
||||
timer[1] = -1; // zero is technically an "active" value, so ensure the timer is dormant now
|
||||
timer[3](); // safe to invoke the callback function now
|
||||
if (timer[2] >= 0) this.setTimer(iTimer, timer[2]);
|
||||
if (timer[2] >= 0) {
|
||||
this.setTimer(iTimer, timer[2]);
|
||||
if (DEBUG && this.messageEnabled(Messages.CPU)) {
|
||||
this.printMessage("updateTimer(" + nCycles + "): rearming " + timer[0] + " for " + timer[2] + "ms (" + timer[1] + " cycles)");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -55283,7 +55297,7 @@ class SerialPort extends Component {
|
|||
if (this.connection) {
|
||||
var exports = this.connection['exports'];
|
||||
if (exports) {
|
||||
var fnConnect = exports['connect'];
|
||||
var fnConnect = /** @function */ (exports['connect']);
|
||||
if (fnConnect) fnConnect.call(this.connection, this.fNullModem);
|
||||
this.sendData = exports['receiveData'];
|
||||
if (this.sendData) {
|
||||
|
|
@ -67050,8 +67064,8 @@ class DebuggerX86 extends Debugger {
|
|||
this.sInitCommands = parmsDbg['commands'];
|
||||
|
||||
/*
|
||||
* Make it easier to access Debugger commands from an external REPL (eg, the WebStorm
|
||||
* "live" console window); eg:
|
||||
* Make it easier to access Debugger commands from an external REPL, like the WebStorm "live" console
|
||||
* window; eg:
|
||||
*
|
||||
* pcx86('r')
|
||||
* pcx86('dw 0:0')
|
||||
|
|
@ -68980,6 +68994,7 @@ class DebuggerX86 extends Debugger {
|
|||
this.dbg = this;
|
||||
this.bitsMessage = this.bitsWarning = Messages.WARN;
|
||||
this.sMessagePrev = null;
|
||||
this.aMessageLog = [];
|
||||
/*
|
||||
* Internally, we use "key" instead of "keys", since the latter is a method on JavasScript objects,
|
||||
* but externally, we allow the user to specify "keys"; "kbd" is also allowed as shorthand for "keyboard".
|
||||
|
|
@ -69328,6 +69343,11 @@ class DebuggerX86 extends Debugger {
|
|||
sMessage += " at " + this.toHexAddr(this.newAddr(this.cpu.getIP(), this.cpu.getCS())) + " (%" + Str.toHex(this.cpu.regLIP) + ")";
|
||||
}
|
||||
|
||||
if (this.bitsMessage & Messages.LOG) {
|
||||
this.aMessageLog.push(sMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.sMessagePrev && sMessage == this.sMessagePrev) return;
|
||||
this.sMessagePrev = sMessage;
|
||||
|
||||
|
|
@ -72268,6 +72288,12 @@ class DebuggerX86 extends Debugger {
|
|||
else if (asArgs[2] == "off") {
|
||||
this.bitsMessage &= ~bitsMessage;
|
||||
fCriteria = false;
|
||||
if (bitsMessage == Messages.LOG) {
|
||||
for (var i = 0; i < this.aMessageLog.length; i++) {
|
||||
this.println(this.aMessageLog[i]);
|
||||
}
|
||||
this.aMessageLog = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,14 +117,14 @@ l.kc=function(a,b,c,d){this.pa=a;this.na=b;this.Da=d;for(b=0;b<Ec.length;b++)(d=
|
|||
l.Rb=function(a,b){if(!b){if(a&&this.restore){Ic(this);if(!this.restore(a))return!1;Jc(this)}else this.reset();this.tb("No debugger detected")}Lc(this);return!0};l.Qb=function(a,b){var c=this.X.cb;b&&Mc(this);return a?this.save(c):!0};l.Fd=function(){return this.X.cb?!0:this.X.Fd||void 0===this.ia.run?Nc(this):!1};l.li=function(){return 0};
|
||||
function Jc(a){void 0===a.V.If&&(a.V.If=0);void 0===a.V.Ke&&(a.V.Ke=-1);void 0===a.V.Le&&(a.V.Le=-1);a.X.zf=0<=a.V.If&&0<a.V.Ke;a.X.zf&&(a.V.Hf=0,a.V.se=a.V.If-a.Ic)}
|
||||
l.Ab=function(a,b,c){var d=this;a=!1;switch(b){case "power":case "reset":this.ia[b]=c;a=!0;break;case "run":this.ia[b]=c;c.onclick=function(){var a=d.X.cb,b;if(b=d.pa)if(b=d.pa,b.X.Xd&&(b.X.Xd=!1,b.X.Ie&&!b.X.Sb&&b.ue(Oc)),b.X.Sb)b=!0;else{var c=null,h,k=db(b.id);for(h=0;h<k.length&&(c=k[h],c===b||c.X.ready);h++);if(h==k.length)for(h=0;h<k.length&&(c=k[h],c===b||c.X.Sb);h++);h==k.length&&(c=b);q("The "+c.type+" component ("+c.id+") is not "+(c.X.ready?"powered yet":"ready yet"+(c.Df?" (waiting for notification)":
|
||||
""))+".");b=!1}b&&a==d.X.cb&&(d.X.cb?Mc(d,!0):Nc(d,!0))};a=!0;break;case "speed":this.ia[b]=c;a=!0;break;case "setSpeed":this.ia[b]=c,c.onclick=function(){Pc(d,d.V.md<<1,!0)},c.textContent=this.V.re.toFixed(2)+"Mhz",a=!0}return a};function Qc(a,b){a.X.cb&&(b=a.A-b,a.A-=b,a.Sc-=b)}function Rc(a){var b=a.V.hd/a.V.Gf|0;if(!b||b>a.V.md)b=a.V.md;a.V.yi=Math.round(1E3/Hc);a.V.Ml=Math.floor(a.V.xd/Hc*b);a.V.rg=b}
|
||||
""))+".");b=!1}b&&a==d.X.cb&&(d.X.cb?Mc(d,!0):Nc(d,!0))};a=!0;break;case "speed":this.ia[b]=c;a=!0;break;case "setSpeed":this.ia[b]=c,c.onclick=function(){Pc(d,d.V.md<<1,!0)},c.textContent=this.V.re.toFixed(2)+"Mhz",a=!0}return a};function Qc(a,b){a.X.cb&&(b=a.A-b,a.A-=b,a.Sc-=b)}function Rc(a){var b=a.V.hd/a.V.Gf;if(!b||b>a.V.md)b=a.V.md;a.V.yi=Math.round(1E3/Hc);a.V.Ml=Math.floor(a.V.xd/Hc*b);a.V.rg=b}
|
||||
function Sc(a,b){var c=a.Ic+a.Tc+a.Sc-a.A;b&&1<a.V.md&&a.V.hd>a.V.Gf&&(c=Math.round(c/a.V.md));return c}function Ic(a){a.Ic=a.Tc=a.Sc=a.A=0;Jc(a);Pc(a,a.V.zi)}
|
||||
function Pc(a,b,c){if(void 0!==b){0<a.V.hd&&.8>a.V.hd/a.V.re&&(b=a.V.zi);a.V.hd=0;a.V.md=b;b=a.V.Gf*a.V.md;if(a.V.re!=b){a.V.re=b;b=a.V.re.toFixed(2)+"Mhz";var d=a.ia.setSpeed;d&&(d.textContent=b);a.tb("target speed: "+b)}c&&a.pa&&Tc(a.pa)}a.Ic+=a.Tc;a.Tc=0;a.V.Zc=a.V.Nd=0;Rc(a);for(c=a.qa.length-1;0<=c;c--)b=a.qa[c],0<=b[2]&&Uc(a,c,b[2],!0)}function Gc(a,b,c,d){d=void 0===d?-1:d;var e=a.qa.length;a.qa.push([b,-1,d,c]);0<=d&&Uc(a,e,d)}
|
||||
function Pc(a,b,c){if(void 0!==b){0<a.V.hd&&a.V.hd<.9*a.V.re&&(b=a.V.zi);a.V.hd=0;a.V.md=b;b=a.V.Gf*a.V.md;if(a.V.re!=b){a.V.re=b;b=a.V.re.toFixed(2)+"Mhz";var d=a.ia.setSpeed;d&&(d.textContent=b);a.tb("target speed: "+b)}c&&a.pa&&Tc(a.pa)}a.Ic+=a.Tc;a.Tc=0;a.V.Zc=a.V.Nd=0;Rc(a);for(c=a.qa.length-1;0<=c;c--)b=a.qa[c],0<=b[2]&&Uc(a,c,b[2],!0)}function Gc(a,b,c,d){d=void 0===d?-1:d;var e=a.qa.length;a.qa.push([b,-1,d,c]);0<=d&&Uc(a,e,d)}
|
||||
function Uc(a,b,c,d){0<=b&&b<a.qa.length&&(b=a.qa[b],d||0>b[1])&&(c=a.V.xd*a.V.rg/1E3*c|0,a.X.cb&&(c+=Vc(a)),b[1]=c)}function Wc(a){for(var b=[],c=0;c<a.qa.length;c++){var d=a.qa[c];b.push([d[0],d[1],d[2]])}return b}function Vc(a,b){var c=a.Sc-=a.A;a.A=0;b&&(a.Sc=0);return c}
|
||||
l.kn=function(){if(this.X.cb){Rc(this);this.V.Jf=0;this.V.Je=ua();this.V.Zc||(this.V.Zc=this.V.Je);if(this.V.Nd){var a=this.V.Je-this.V.Nd;a>this.V.yi&&(this.V.Zc+=a,this.V.Zc>this.V.Je&&(this.V.Zc=this.V.Je))}try{this.X.Zf=!1;do{for(var b,c=this.X.zf?1:this.V.xd*this.V.rg|0,d=this.qa.length-1;0<=d;d--){var e=this.qa[d];0>e[1]||c>e[1]&&(c=e[1])}b=c;if(this.U){Xc(this.U);var f=this.U,a=b,g=f.qa[0];if(g.Kd){var h=(Sc(f.R,f.N)-g.jd)/f.Aa|0,k=Yc(f,0)-h;g.mode==Zc&&(k-=h);var m=k*f.Aa|0;g.mode==Zc&&(m>>=
|
||||
1);a>m&&(a=m)}b=a;var r=this.U,a=b;if(r.A&&r.A[$c]&ad){var y=r.W-Sc(r.R,r.N);0<y&&a>y&&(a=y)}b=a}try{this.th(b)}catch(N){if("number"!=typeof N)throw N;}b=Vc(this,!0);this.V.Jf+=b;this.Tc+=b;a=b;if(this.X.zf){var t=!1;this.V.Hf=this.V.Hf+this.li()|0;this.V.se-=a;0>=this.V.se&&(this.V.se+=this.V.Ke,t=!0);0<=this.V.Le&&this.V.Le<=Sc(this)&&(this.V.Ke=this.V.Le=-1,Jc(this),Mc(this),t=!0);t&&this.tb(Sc(this)+" cycles: checksum="+ia(this.V.Hf))}for(var a=b,z=this.qa.length-1;0<=z;z--){var B=this.qa[z];
|
||||
0>B[1]||(B[1]-=a,0>=B[1]&&(B[1]=-1,B[3](),0<=B[2]&&Uc(this,z,B[2])))}}while(this.X.cb&&!this.X.Zf)}catch(N){Mc(this);Lc(this);this.pa&&this.pa.stop(ua(),Sc(this));mb(this,N.stack||N.message);return}if(this.X.cb){b=setTimeout;c=this.pi;this.V.Nd=ua();d=this.V.yi;this.V.Jf&&(d=Math.round(d*this.V.Jf/this.V.Ml));d-=this.V.Nd-this.V.Je;if(e=this.V.Nd-this.V.Zc)this.V.hd=Math.round(this.Tc/(10*e))/100,864E5<=e&&(this.Ic=0,this.U&&Xc(this.U,!0),Pc(this));if(0>d||this.V.hd<this.V.re)-1E3>d&&(this.V.Zc-=
|
||||
d),d=0;this.V.Nd+=d;b(c,d)}}};function Nc(a,b){var c;a.X.error?(a.tb(a.toString()+" error"),c=!0):c=!1;if(c)return!1;if(a.X.cb)return a.tb(a.toString()+" busy"),!1;Pc(a);a.X.cb=!0;a.X.Pj=!0;a.U&&a.U.start();if(c=a.ia.run)c.textContent="Halt";a.pa&&(bd(a.pa,!0),b&&Tc(a.pa,!0),a.pa.start(a.V.Zc,Sc(a)));setTimeout(a.pi,0);return!0}l.th=function(){return 0};
|
||||
0>B[1]||(B[1]-=a,0>=B[1]&&(B[1]=-1,B[3](),0<=B[2]&&Uc(this,z,B[2])))}}while(this.X.cb&&!this.X.Zf)}catch(N){Mc(this);Lc(this);this.pa&&this.pa.stop(ua(),Sc(this));mb(this,N.stack||N.message);return}if(this.X.cb){b=setTimeout;c=this.pi;this.V.Nd=ua();d=this.V.yi;this.V.Jf&&(d=Math.round(d*this.V.Jf/this.V.Ml));d-=this.V.Nd-this.V.Je;if(e=this.V.Nd-this.V.Zc)this.V.hd=Math.round(this.Tc/(10*e))/100,864E5<=e&&(this.Ic=0,this.U&&Xc(this.U,!0),Pc(this));0>d?(-1E3>d&&(this.V.Zc-=d),d=0):this.V.hd<this.V.re&&
|
||||
(d=0);this.V.Nd+=d;b(c,d)}}};function Nc(a,b){var c;a.X.error?(a.tb(a.toString()+" error"),c=!0):c=!1;if(c)return!1;if(a.X.cb)return a.tb(a.toString()+" busy"),!1;Pc(a);a.X.cb=!0;a.X.Pj=!0;a.U&&a.U.start();if(c=a.ia.run)c.textContent="Halt";a.pa&&(bd(a.pa,!0),b&&Tc(a.pa,!0),a.pa.start(a.V.Zc,Sc(a)));setTimeout(a.pi,0);return!0}l.th=function(){return 0};
|
||||
function Mc(a,b){if(a.X.cb){Vc(a);a.Ic+=a.Tc;a.Tc=0;a.X.cb=!1;a.U&&a.U.stop();var c=a.ia.run;c&&(c.textContent="Run");a.pa&&(a.pa.stop(Date.now()||+new Date,Sc(a)),bd(a.pa,!0));a.Da||a.status("Stopped")}a.X.complete=b}function Lc(a){a.pa&&bd(a.pa,void 0)}var Hc=30,Ec=["power","reset"];
|
||||
function cd(a,b,c,d){this.A=a;this.Da=a.Da;this.id=b;this.Xf=c||"";this.ha=0;this.jb=65535;this.C=this.jb+1;this.rb=this.jc=this.ext=this.nb=this.type=this.va=0;this.cc=-1;this.T=this.Jc=2;this.O=this.sa=65535;this.J=this.wi;this.I=this.H=this.xf;this.B={ha:-1,va:0,jb:0,nb:0,type:0,ext:0,cc:-1};1==this.id&&(this.Xe=0,this.D=null,this.ne=!1,this.G=Array(32),this.F=[]);dd(this,!0,d);this.id||(this.Jb=this.qb=this.ai)}l=cd.prototype;l.wi=function(a){this.ha=a&65535;return this.va=this.ha<<4};
|
||||
l.Ff=function(a,b){var c,d,e=this.A;a&=65535;a&4?(c=e.mc.va,d=c+e.mc.jb|0):(c=e.Ob,d=e.Oc);if(c){c=c+(a&65528)|0;if(d-c|0)return e.A-=15,ed(this,c,a,b);this.id<fd&&w.call(e,b&&this.id==gd?10:13,a&65532)}return-1};l.Gl=function(a){var b=this.A;a=b.Xb+(a<<2);var c=b.ga(a);b.N&=-769;return this.load(b.ga(a+2))+c|0};l.Fl=function(a){var b=this.A;a<<=3;var c=b.Xb+a|0;if(7<=(b.Qc-c|0))return this.D=!0,a=ed(this,c,a),-1!==a&&(a+=this.Xe),a;w.call(b,13,a|2);return-1};l.ai=function(a){return this.va+a|0};
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue