Resolved a problem with the original timer implementation, where a call to setTimer() made in the middle of a CPU burst would not properly account for cycles already executed as part of the current burst
This commit is contained in:
parent
58d358b51e
commit
8bb978d7a9
7 changed files with 423 additions and 406 deletions
|
|
@ -973,7 +973,13 @@ CPU8080.prototype.setTimer = function(iTimer, ms, fReset)
|
|||
if (iTimer >= 0 && iTimer < this.aTimers.length) {
|
||||
if (fReset || this.aTimers[iTimer][0] < 0) {
|
||||
nCycles = this.getMSCycles(ms);
|
||||
this.aTimers[iTimer][0] = nCycles;
|
||||
/*
|
||||
* We must now confront the following problem: if the CPU is currently executing a burst of cycles,
|
||||
* the number of cycles it has executed in that burst so far must NOT be charged against the cycle
|
||||
* timeout we're about to set. The simplest way to resolve that is to immediately call endBurst()
|
||||
* and bias the above cycle timeout by the number of cycles that the burst executed.
|
||||
*/
|
||||
this.aTimers[iTimer][0] = nCycles + this.endBurst();
|
||||
}
|
||||
}
|
||||
return nCycles;
|
||||
|
|
@ -1036,14 +1042,18 @@ CPU8080.prototype.updateTimers = function(nCycles)
|
|||
};
|
||||
|
||||
/**
|
||||
* endBurst()
|
||||
* endBurst(fReset)
|
||||
*
|
||||
* @this {CPU8080}
|
||||
* @param {boolean} [fReset]
|
||||
* @return {number} (number of cycles executed in the most recent burst)
|
||||
*/
|
||||
CPU8080.prototype.endBurst = function()
|
||||
CPU8080.prototype.endBurst = function(fReset)
|
||||
{
|
||||
this.nBurstCycles -= this.nStepCycles;
|
||||
var nCycles = this.nBurstCycles -= this.nStepCycles;
|
||||
this.nStepCycles = 0;
|
||||
if (fReset) this.nBurstCycles = 0;
|
||||
return nCycles;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -1071,35 +1081,34 @@ CPU8080.prototype.runCPU = function(fUpdateFocus)
|
|||
try {
|
||||
do {
|
||||
/*
|
||||
* nCyclesPerBurst is how many cycles we WANT to run on each iteration of stepCPU(), and may
|
||||
* 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.
|
||||
* nCycles is how many cycles we WANT to run on each iteration of stepCPU(), and may be as
|
||||
* HIGH as nCyclesPerYield, but it may be significantly less. getBurstCycles() will adjust
|
||||
* nCycles downward if any CPU timers need to fire during the next burst.
|
||||
*/
|
||||
var nCyclesPerBurst = this.getBurstCycles(this.flags.checksum? 1 : this.nCyclesPerYield);
|
||||
var nCycles = this.getBurstCycles(this.flags.checksum? 1 : this.nCyclesPerYield);
|
||||
|
||||
/*
|
||||
* Execute the burst.
|
||||
*/
|
||||
this.stepCPU(nCyclesPerBurst);
|
||||
this.stepCPU(nCycles);
|
||||
|
||||
/*
|
||||
* nCycles is how many cycles stepCPU() actually ran (nBurstCycles less any remaining nStepCycles).
|
||||
* Terminate the burst, returning the number of cycles that stepCPU() actually ran.
|
||||
*/
|
||||
var nCycles = this.nBurstCycles - this.nStepCycles;
|
||||
|
||||
/*
|
||||
* Update any/all timers, firing those whose cycle countdowns have reached (or dropped below) zero.
|
||||
*/
|
||||
this.updateTimers(nCycles);
|
||||
nCycles = this.endBurst(true);
|
||||
|
||||
/*
|
||||
* Add nCycles to nCyclesThisRun, as well as nRunCycles (the cycle count since the CPU first started).
|
||||
*/
|
||||
this.nCyclesThisRun += nCycles;
|
||||
this.nRunCycles += nCycles;
|
||||
this.addCycles(0, true);
|
||||
this.updateChecksum(nCycles);
|
||||
|
||||
/*
|
||||
* Update any/all timers, firing those whose cycle countdowns have reached (or dropped below) zero.
|
||||
*/
|
||||
this.updateTimers(nCycles);
|
||||
|
||||
this.nCyclesNextYield -= nCycles;
|
||||
if (this.nCyclesNextYield <= 0) {
|
||||
this.nCyclesNextYield += this.nCyclesPerYield;
|
||||
|
|
|
|||
Loading…
Reference in a new issue