1
0
mirror of https://github.com/pkimpel/retro-220.git synced 2026-05-03 06:29:43 +00:00

Emulator version 0.00b:

Initial development of memory access, Fetch/Execute, add/subtract, BUN, and Console integration.
This commit is contained in:
Paul Kimpel
2017-03-04 17:43:48 -08:00
parent ee513aec18
commit a47ea448e2
11 changed files with 1025 additions and 817 deletions

View File

@@ -8,8 +8,8 @@
* B220 emulator universal function call-back module.
*
* Implements a combination setTimeout() and setImmediate() facility for the
* B220 emulator web-based user interface. setCallback() is used the same way
* that setTimeout() is used, except that for low values of the timeout parameter,
* B220 emulator web-based user interface. setCallback() is used in a manner
* similar to setTimeout(), except that for low values of the timeout parameter
* it merely yields control to any other pending events and timers before calling
* the call-back function.
*
@@ -18,7 +18,7 @@
* minimum they use, and their precision in activating the call-back function
* once the actual delay is established varies even more. This module will use
* setTimeout() if the requested delay time is above a certain threshold, and
* a setImmediate()-like mechanism (based on window.postMessage) if the requested
* a setImmediate-like mechanism (based on window.postMessage) if the requested
* delay is below that threshold.
*
* To help compensate for the fact that the call-back function may be called
@@ -29,8 +29,8 @@
* the actual delay. A portion of this deviation is then applied to the requested
* delay on subsequent calls in an attempt to smooth out the differences. We are
* going for good average behavior here, and some too-quick call-backs are better
* than consistently too-long callbacks in this environment, so that I/Os can be
* initiated and their finish detected in finer-grained time increments.
* than consistently too-long callbacks in this environment, particularly so that
* I/Os can be initiated and their finish detected in finer-grained time increments.
*
* The SetCallback mechanism defines three functions that become members of the
* global (window) object:
@@ -75,6 +75,8 @@
************************************************************************
* 2017-01-01 P.Kimpel
* Original version, cloned from retro-205 emulator D205SetCallback.js.
* 2017-02-18 P.Kimpel
* Redesign yet again the delay adjustment mechanism -- from 205 project.
***********************************************************************/
"use strict";
@@ -92,7 +94,6 @@
/**************************************/
function activateCallback(token) {
/* Activates a callback after its delay period has expired */
var category;
var endStamp = perf.now();
var thisCallback;
var tokenName = token.toString();
@@ -100,10 +101,7 @@
thisCallback = pendingCallbacks[tokenName];
if (thisCallback) {
delete pendingCallbacks[tokenName];
category = thisCallback.category;
if (category) {
delayDev[category] += endStamp - thisCallback.startStamp - thisCallback.delay;
}
delayDev[thisCallback.category] += endStamp - thisCallback.startStamp - thisCallback.delay;
try {
thisCallback.fcn.call(thisCallback.context, thisCallback.arg);
} catch (err) {
@@ -126,10 +124,8 @@
thisCallback = pendingCallbacks[tokenName];
if (thisCallback) {
delete pendingCallbacks[tokenName];
if (thisCallback.isTimeout) {
if (thisCallback.cancelToken) {
global.clearTimeout(thisCallback.cancelToken);
}
if (thisCallback.cancelToken) {
global.clearTimeout(thisCallback.cancelToken);
}
thisCallback.context = null;
@@ -146,10 +142,10 @@
to "fcn". If the delay is less than "minTimeout", a setImmediate-like mechanism
based on window.postsMessage() will be used; otherwise the environment's standard
setTimeout mechanism will be used */
var adj = 0; // adjustment to delay and delayDev[]
var categoryName = (category || "NUL").toString();
var delay = callbackDelay || 0; // actual delay to be generated
var delayBias; // current amount of delay deviation
var ratio; // ratio of delay to delayBias
var thisCallback; // call-back object to be used
var token = ++lastTokenNr; // call-back token number
var tokenName = token.toString(); // call-back token ID
@@ -162,41 +158,60 @@
pool[poolLength] = null;
}
thisCallback.startStamp = perf.now();
// Adjust the requested delay based on the current delay deviation
// for this category.
delayBias = delayDev[categoryName];
if (!delayBias) {
delayDev[categoryName] = 0; // bias was zero, or got a new one
delayDev[categoryName] = 0; // bias was zero, or got a new one: no adjustment
} else {
ratio = delay/delayBias;
if (ratio > 1) {
delay -= delayBias;
delayDev[categoryName] = 0;
} else if (ratio > 0) {
delayDev[categoryName] -= delay;
delay = 0;
} else if (ratio < -1) {
delay += delayBias;
delayDev[categoryName] = 0;
} else {
delayDev[categoryName] += delay;
delay = 0;
if (delayBias > 0) {
// We are delaying too much and should try to delay less.
if (delay < 0) {
adj = 0; // don't make delay any more negative
} else {
if (delay > delayBias) {
adj = -delayBias;
} else {
adj = -delay;
}
}
} else { // delayBias < 0
// We are delaying too little and should try to delay more.
if (delay < 0) {
if (delay - minTimeout < delayBias) {
adj = -delayBias;
} else {
adj = minTimeout - delay;
}
} else {
if (delay > minTimeout) {
adj = 0;
} else if (delay - minTimeout < delayBias) {
adj = -delayBias;
} else {
adj = minTimeout - delay;
}
}
}
delay += adj;
delayDev[categoryName] += adj;
}
// Fill in the call-back object and tank it in pendingCallbacks.
thisCallback.startStamp = perf.now();
thisCallback.category = categoryName;
thisCallback.context = context || this;
thisCallback.delay = delay;
thisCallback.context = context || this;
thisCallback.fcn = fcn;
thisCallback.arg = arg;
pendingCallbacks[tokenName] = thisCallback;
// Decide whether to do a time wait or just a yield.
if (delay > minTimeout) {
thisCallback.isTimeout = true;
thisCallback.cancelToken = global.setTimeout(activateCallback, delay, token);
} else {
thisCallback.isTimeout = false;
thisCallback.cancelToken = 0;
global.postMessage(secretPrefix + tokenName, "*");
}