1
0
mirror of https://github.com/pkimpel/retro-220.git synced 2026-04-14 07:49:53 +00:00

Commit retro-220 emulator version 0.05:

1. Remove Application Cache mechanism (has been deprecated as a web standard).
2. Replace internal bindMethod() utility function with standard Javascript object.bind().
3. Automatically reset Digit Check Alarm when bits are corrected in registers.
4. Correct setting of Overflow Toggle in IFL.
5. Terminate magnetic tape data transfer if AST toggle gets reset.
6. Correct way Processor was released by magnetic tape TCU.
7. Correct construction of preface word in memory for mag tape MRR.
8. Correct determination of mag tape "remote" status to allow tape to be unloaded immediately after a rewind.
9. Fix bug in BCS detecting the switch setting.
10. Modify behavior of Reset/Transfer switch to allow recovery after a tape malfunction.
11. Correct formatting of HIGH lamp on Control Console.
12. Remove extraneous whitespace from B220FramePaper sub-window markup.
This commit is contained in:
Paul Kimpel
2018-01-12 08:40:49 -08:00
parent f288264276
commit 936aadf6ee
19 changed files with 264 additions and 326 deletions

View File

@@ -256,7 +256,7 @@ function B220Processor(config, devices) {
* Global Constants *
***********************************************************************/
B220Processor.version = "0.04";
B220Processor.version = "0.05";
B220Processor.tick = 1000/200000; // milliseconds per clock cycle (200KHz)
B220Processor.cyclesPerMilli = 1/B220Processor.tick;
@@ -324,22 +324,21 @@ B220Processor.emptyFunction = function emptyFunction() {
/**************************************/
B220Processor.bcdBinary = function bcdBinary(v) {
/* Converts the BCD value "v" to a binary number and returns it. If the
BCD value is not decimal, returns NaN instead */
/* Converts the BCD value "v" to a binary number and returns it. If a
BCD digit is not decimal, coerces it to an 8 or 9 instead */
var d;
var power = 1;
var result = 0;
while(v) {
d = v % 0x10;
v = (v-d)/0x10;
if (d > 9) {
result = Number.NaN;
break;
} else {
result += d*power;
power *= 10;
v = (v-d)/0x10;
d &= 0x09; // turn off the middle 2 bits
}
result += d*power;
power *= 10;
}
return result;
};
@@ -566,93 +565,122 @@ B220Processor.prototype.clear = function clear() {
this.scheduler = 0;
}
this.updateGlow(1); // initialize the lamp states
this.updateLampGlow(1); // initialize the lamp states
};
/**************************************/
B220Processor.prototype.updateGlow = function updateGlow(beta) {
B220Processor.prototype.validateDigitCheck = function validateDigitCheck() {
/* Steps through all of the properties of the Processor object, isolating
the Register() objects and determining if any of them have a Forbidden
Combination condition. If not, turns off the Digit Check alarm */
var alarm = false; // true if any register has FC
var name = ""; // current property name
var reg = null; // current Register object
for (name in this) {
reg = this[name];
if (reg instanceof B220Processor.Register) {
if (reg.hasFC) {
alarm = true;
break; // out of for loop
}
}
} // for name
if (!alarm) {
this.digitCheckAlarm.set(0);
}
};
/**************************************/
B220Processor.prototype.updateLampGlow = function updateLampGlow(beta) {
/* Updates the lamp glow for all registers and flip-flops in the
system. Beta is a bias in the range (0,1). For normal update use 0;
to freeze the current state in the lamps use 1 */
var gamma = (this.RUT.value ? beta || 0 : 1);
// First, check whether a Digit Check alarm exists and if the condition has resolved.
if (this.digitCheckAlarm.value) {
this.validateDigitCheck();
}
// Primary Registers
this.A.updateGlow(gamma);
this.B.updateGlow(gamma);
this.C.updateGlow(gamma);
this.D.updateGlow(gamma);
this.E.updateGlow(gamma);
this.P.updateGlow(gamma);
this.R.updateGlow(gamma);
this.S.updateGlow(gamma);
this.IB.updateGlow(gamma);
this.A.updateLampGlow(gamma);
this.B.updateLampGlow(gamma);
this.C.updateLampGlow(gamma);
this.D.updateLampGlow(gamma);
this.E.updateLampGlow(gamma);
this.P.updateLampGlow(gamma);
this.R.updateLampGlow(gamma);
this.S.updateLampGlow(gamma);
this.IB.updateLampGlow(gamma);
// Control Console Lamps
this.digitCheckAlarm.updateGlow(gamma);
this.digitCheckAlarm.updateLampGlow(gamma);
this.systemNotReady.updateGlow(gamma);
this.computerNotReady.updateGlow(gamma);
this.systemNotReady.updateLampGlow(gamma);
this.computerNotReady.updateLampGlow(gamma);
this.compareLowLamp.updateGlow(gamma);
this.compareEqualLamp.updateGlow(gamma);
this.compareHighLamp.updateGlow(gamma);
this.compareLowLamp.updateLampGlow(gamma);
this.compareEqualLamp.updateLampGlow(gamma);
this.compareHighLamp.updateLampGlow(gamma);
// Left-Hand Maintenance Panel Registers & Flip-Flops
if (this.leftPanelOpen) {
this.CI.updateGlow(gamma);
this.DC.updateGlow(gamma);
this.SC.updateGlow(gamma);
this.SI.updateGlow(gamma);
this.X.updateGlow(gamma);
this.Y.updateGlow(gamma);
this.Z.updateGlow(gamma);
this.CI.updateLampGlow(gamma);
this.DC.updateLampGlow(gamma);
this.SC.updateLampGlow(gamma);
this.SI.updateLampGlow(gamma);
this.X.updateLampGlow(gamma);
this.Y.updateLampGlow(gamma);
this.Z.updateLampGlow(gamma);
this.C10.updateGlow(gamma);
this.DST.updateGlow(gamma);
this.LT1.updateGlow(gamma);
this.LT2.updateGlow(gamma);
this.LT3.updateGlow(gamma);
this.SCI.updateGlow(gamma);
this.SGT.updateGlow(gamma);
this.SUT.updateGlow(gamma);
this.TBT.updateGlow(gamma);
this.TCT.updateGlow(gamma);
this.TPT.updateGlow(gamma);
this.TWT.updateGlow(gamma);
this.C10.updateLampGlow(gamma);
this.DST.updateLampGlow(gamma);
this.LT1.updateLampGlow(gamma);
this.LT2.updateLampGlow(gamma);
this.LT3.updateLampGlow(gamma);
this.SCI.updateLampGlow(gamma);
this.SGT.updateLampGlow(gamma);
this.SUT.updateLampGlow(gamma);
this.TBT.updateLampGlow(gamma);
this.TCT.updateLampGlow(gamma);
this.TPT.updateLampGlow(gamma);
this.TWT.updateLampGlow(gamma);
}
// Right-Hand Maintenance Panel Registers & Flip-Flops
this.ALT.updateGlow(gamma);
this.MET.updateGlow(gamma);
this.TAT.updateGlow(gamma);
this.PAT.updateGlow(gamma);
this.CRT.updateGlow(gamma);
this.HAT.updateGlow(gamma);
this.ALT.updateLampGlow(gamma);
this.MET.updateLampGlow(gamma);
this.TAT.updateLampGlow(gamma);
this.PAT.updateLampGlow(gamma);
this.CRT.updateLampGlow(gamma);
this.HAT.updateLampGlow(gamma);
this.EXT.updateGlow(gamma);
this.OFT.updateGlow(gamma);
this.RPT.updateGlow(gamma);
this.RUT.updateGlow(gamma);
this.EXT.updateLampGlow(gamma);
this.OFT.updateLampGlow(gamma);
this.RPT.updateLampGlow(gamma);
this.RUT.updateLampGlow(gamma);
if (this.rightPanelOpen) {
this.AX.updateGlow(gamma);
this.BI.updateGlow(gamma);
this.DX.updateGlow(gamma);
this.PA.updateGlow(gamma);
this.AX.updateLampGlow(gamma);
this.BI.updateLampGlow(gamma);
this.DX.updateLampGlow(gamma);
this.PA.updateLampGlow(gamma);
this.AST.updateGlow(gamma);
this.CCT.updateGlow(gamma);
this.CRT.updateGlow(gamma);
this.DPT.updateGlow(gamma);
this.EWT.updateGlow(gamma);
this.HCT.updateGlow(gamma);
this.HIT.updateGlow(gamma);
this.MAT.updateGlow(gamma);
this.MNT.updateGlow(gamma);
this.PRT.updateGlow(gamma);
this.PZT.updateGlow(gamma);
this.SST.updateGlow(gamma);
this.UET.updateGlow(gamma);
this.AST.updateLampGlow(gamma);
this.CCT.updateLampGlow(gamma);
this.CRT.updateLampGlow(gamma);
this.DPT.updateLampGlow(gamma);
this.EWT.updateLampGlow(gamma);
this.HCT.updateLampGlow(gamma);
this.HIT.updateLampGlow(gamma);
this.MAT.updateLampGlow(gamma);
this.MNT.updateLampGlow(gamma);
this.PRT.updateLampGlow(gamma);
this.PZT.updateLampGlow(gamma);
this.SST.updateLampGlow(gamma);
this.UET.updateLampGlow(gamma);
}
};
@@ -683,6 +711,7 @@ B220Processor.Register = function Register(bits, p, invisible) {
this.bits = bits; // number of bits in register
this.visible = (invisible ? false : true);
this.hasFC = false; // true if Forbidden Combination (A-F digit) detected
this.lastExecClock = 0; // time register was last set
this.p = p; // processor instance
this.value = 0; // binary value of register: read-only externally
@@ -696,27 +725,32 @@ B220Processor.Register.prototype.checkFC = function checkFC() {
least one exists, sets the Digit Check alarm and returns true. The bit mask
operations are done 28 bits at a time to avoid problems with the 32-bit
2s-complement arithmetic used by Javascript for bit operations */
var hasFC = false; // true if register has Forbidden Combination
var v1 = this.value; // high-order digits (eventually)
var v2 = v1%0x10000000; // low-order 7 digits
v1 = (v1-v2)/0x10000000;
if (((v2 & 0x8888888) >>> 3) & (((v2 & 0x4444444) >>> 2) | ((v2 & 0x2222222) >>> 1))) {
this.p.setDigitCheck(1);
return 1;
} else if (v1 <= 9) {
hasFC = true;
} else if (v1 > 9) {
if (((v1 & 0x8888888) >>> 3) & (((v1 & 0x4444444) >>> 2) | ((v1 & 0x2222222) >>> 1))) {
hasFC = true;
}
}
this.hasFC = hasFC;
if (!hasFC) {
return 0;
} else if (((v1 & 0x8888888) >>> 3) & (((v1 & 0x4444444) >>> 2) | ((v1 & 0x2222222) >>> 1))) {
this.p.setDigitCheck(1);
return 1;
} else {
return 0;
this.p.setDigitCheck(1);
return 1;
}
};
/**************************************/
B220Processor.Register.prototype.updateGlow = function updateGlow(beta) {
B220Processor.Register.prototype.updateLampGlow = function updateLampGlow(beta) {
/* Updates the lamp glow averages based on this.p.execClock. Note that the
glow is always aged by at least one clock tick. Beta is a bias in the
range (0,1). For normal update, use 0; to freeze the current state, use 1 */
@@ -752,11 +786,13 @@ B220Processor.Register.prototype.set = function set(value) {
this.value = value;
if (this.visible) {
this.updateGlow(0);
this.updateLampGlow(0);
}
if (value > 9) {
this.checkFC();
} else {
this.hasFC = false;
}
return value;
};
@@ -926,7 +962,7 @@ B220Processor.FlipFlop = function FlopFlop(p, invisible) {
};
/**************************************/
B220Processor.FlipFlop.prototype.updateGlow = function updateGlow(beta) {
B220Processor.FlipFlop.prototype.updateLampGlow = function updateLampGlow(beta) {
/* Updates the average glow for the flip flop. Note that the glow is
always aged by at least one clock tick. Beta is a bias in the
range (0,1). For normal update, use 0; to freeze the current state, use 1.
@@ -949,7 +985,7 @@ B220Processor.FlipFlop.prototype.set = function set(value) {
this.value = (value ? 1 : 0);
if (this.visible) {
this.updateGlow(0);
this.updateLampGlow(0);
}
return value;
@@ -1294,8 +1330,8 @@ B220Processor.prototype.integerExtract = function integerExtract() {
return; // exit to Operation Complete
}
// Loop through the 11 digits including signs (which were set to zero in am and dm)
var dm = this.IB.value;
// Loop through the 11 digits including signs
dm = this.IB.value;
for (x=0; x<11; ++x) {
// shift low-order value digit right into the adder
ad = am % 0x10;
@@ -2073,7 +2109,9 @@ B220Processor.prototype.increaseFieldLocation = function increaseFieldLocation()
this.D.set(dw);
this.IB.set(dw);
this.C10.set(carry); // set carry toggle
this.OFT.set(carry); // set overflow if there's a carry
if (carry) {
this.OFT.set(1); // set overflow if there's a carry
}
this.CCONTROL = ((s%10)*0x10 + L)*0x100 + this.CCONTROL%0x100;
this.C.set((this.CCONTROL*0x100 + this.COP)*0x10000 + this.CADDR);
@@ -2861,32 +2899,36 @@ B220Processor.prototype.cardatronReceiveWord = function cardatronReceiveWord(wor
/**************************************/
B220Processor.prototype.magTapeComplete = function magTapeComplete(control, word) {
/* Call-back routine to signal completion of a magnetic tape operation. If
"control" is true, the contents of "word" are processed as a tape control
word and an appropriate branch is set up. Unconditionally terminates the
tape I/O instruction */
var aaaa;
var bbbb;
/* Call-back routine to signal completion of a magnetic tape operation.
If this.AST is false, does nothing, as we have probably either been cleared
or the Reset/Transfer switch has been activated. Otherwsie, if "control" is
true, the contents of "word" are processed as a tape control word and an
appropriate branch is set up. Unconditionally terminates the tape I/O
instruction */
var aaaa = 0; // address where C & P will be stored
var bbbb = 0; // address to load into P
if (control) {
this.D.set(word);
bbbb = word%0x10000;
aaaa = ((word - bbbb)/0x10000)%0x10000;
if (word%0x20000000000 >= 0x10000000000) { // if sign bit is 1,
bbbb = this.bcdAdd(bbbb, this.B.value, 4); // B-adjust the low-order 4 digits
if (this.AST.value) { // if false, we've probably been cleared
if (control) {
this.D.set(word);
bbbb = word%0x10000;
aaaa = ((word - bbbb)/0x10000)%0x10000;
if (word%0x20000000000 >= 0x10000000000) { // if sign bit is 1,
bbbb = this.bcdAdd(bbbb, this.B.value, 4); // B-adjust the low-order 4 digits
}
this.E.set(aaaa);
this.readMemory();
if (!this.MET.value) {
this.IB.set(this.IB.value - this.IB.value%0x100000000 +
(this.C.value%0x10000)*0x10000 + this.P.value%0x10000);
this.writeMemory();
this.P.set(bbbb);
}
}
this.E.set(aaaa);
this.readMemory();
if (!this.MET.value) {
this.IB.set(this.IB.value - this.IB.value%0x100000000 +
(this.C.value%0x10000)*0x10000 + this.P.value%0x10000);
this.writeMemory();
this.P.set(bbbb);
}
Promise.resolve(true).then(this.boundIoComplete);
}
Promise.resolve(true).then(this.boundIoComplete);
};
/**************************************/
@@ -3428,7 +3470,7 @@ B220Processor.prototype.execute = function execute() {
case 0x38: //--------------------- BCS Branch, control switch
this.opTime = 0.015; // minimum instruction timing
d = (this.CCONTROL - this.CCONTROL%0x1000)/0x1000;
if (this["PCS" + d.toString() + "SW"]) {
if (this["PC" + d.toString() + "SW"]) {
this.opTime += 0.020;
this.P.set(this.CADDR);
}
@@ -3973,7 +4015,7 @@ B220Processor.prototype.ioInitiate = function ioInitiate() {
/* Initiates asynchronous mode of the processor for I/O */
this.AST.set(1);
this.updateGlow(1); // update the console lamps
this.updateLampGlow(1); // update the console lamps
this.execLimit = 0; // kill the run() loop
};
@@ -4105,7 +4147,7 @@ B220Processor.prototype.start = function start() {
this.runTimer -= stamp;
}
this.updateGlow(1);
this.updateLampGlow(1);
this.schedule();
}
};
@@ -4130,7 +4172,7 @@ B220Processor.prototype.stop = function stop() {
this.runTimer += stamp;
}
this.updateGlow(1); // freeze state in the lamps
this.updateLampGlow(1); // freeze state in the lamps
if (this.scheduler) {
clearCallback(this.scheduler);
this.scheduler = 0;
@@ -4230,7 +4272,12 @@ B220Processor.prototype.resetTransfer = function resetTransfer() {
(this.C.value % 0x10000)*0x10000 + this.P.value % 0x10000);
this.writeMemory();
this.P.set(0x0001);
this.EXT.set(0); // set to Fetch cycle
if (this.AST.value) { // I/O in progress -- cancel it
this.ioComplete(true);
} else {
this.EXT.set(0); // set to Fetch cycle
}
if (!this.RUT.value) {
this.start();
}
@@ -4263,7 +4310,7 @@ B220Processor.prototype.powerUp = function powerUp() {
this.cardatron = this.devices.CardatronControl;
this.magTape = this.devices.MagTapeControl;
this.computerNotReady.set(1); // initial state after power-up
this.updateGlow(1);
this.updateLampGlow(1);
}
};
@@ -4275,7 +4322,7 @@ B220Processor.prototype.powerDown = function powerDown() {
this.stop();
this.clear();
this.poweredOn = 0;
this.updateGlow(1);
this.updateLampGlow(1);
this.cardatron = null;
this.console = null;

View File

@@ -1,5 +1,5 @@
<!DOCTYPE html>
<html manifest="B220Manifest.appcache">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>retro-220 Emulator</title>
@@ -15,6 +15,8 @@
************************************************************************
* 2017-01-01 P.Kimpel
* Original version, from retro-205 D205.html.
* 2018-01-04 P.Kimpel
* Remove deprecated Application Cache (appcache) configuration.
***********************************************************************/
-->
<meta name="Author" content="Paul Kimpel">

View File

@@ -9,6 +9,8 @@
************************************************************************
* 2017-01-01 P.Kimpel
* Original version, from retro-205/D205.js.
* 2018-01-04 P.Kimpel
* Remove deprecated Application Cache (appcache) configuration.
***********************************************************************/
"use strict";
@@ -134,45 +136,14 @@ window.addEventListener("load", function() {
document.getElementById("StartUpBtn").disabled = true;
document.getElementById("EmulatorVersion").textContent = B220Processor.version;
if (checkBrowser()) {
document.getElementById("Retro220Logo").addEventListener("dblclick", openDiagPanel);
document.getElementById("Retro220Logo").addEventListener("dblclick", openDiagPanel, false);
document.getElementById("StartUpBtn").disabled = false;
document.getElementById("StartUpBtn").addEventListener("click", systemStartup);
document.getElementById("StartUpBtn").addEventListener("click", systemStartup, false);
document.getElementById("StartUpBtn").focus();
document.getElementById("ConfigureBtn").disabled = false;
document.getElementById("ConfigureBtn").addEventListener("click", configureSystem);
document.getElementById("ConfigureBtn").addEventListener("click", configureSystem, false);
window.applicationCache.addEventListener("checking", function(ev) {
document.getElementById("StatusMsg").textContent = "Checking for emulator update...";
clearStatusMsg(15);
});
window.applicationCache.addEventListener("noupdate", function(ev) {
document.getElementById("StatusMsg").textContent = "Emulator version is current.";
clearStatusMsg(15);
});
window.applicationCache.addEventListener("obsolete", function(ev) {
document.getElementById("StatusMsg").textContent = "Emulator off-line installation has been disabled.";
clearStatusMsg(15);
});
window.applicationCache.addEventListener("downloading", function(ev) {
document.getElementById("StatusMsg").textContent = "Initiating download for emulator update...";
clearStatusMsg(15);
});
window.applicationCache.addEventListener("progress", function(ev) {
var text = (ev.loaded && ev.total ? ev.loaded.toString() + "/" + ev.total.toString() : "Unknown number of");
document.getElementById("StatusMsg").textContent = text + " resources downloaded thus far...";
clearStatusMsg(15);
});
window.applicationCache.addEventListener("updateready", function(ev) {
document.getElementById("StatusMsg").textContent = "Emulator update completed. Reload this page to activate the new version.";
clearStatusMsg(15);
});
window.applicationCache.addEventListener("cached", function(ev) {
document.getElementById("StatusMsg").textContent = "Emulator is now installed for off-line use.";
clearStatusMsg(15);
});
window.applicationCache.addEventListener("error", function(ev) {
document.getElementById("StatusMsg").textContent = "Browser reported error during emulator version check.";
clearStatusMsg(15);
});
document.getElementById("StatusMsg").textContent = "The Application Cache feature has been deimplemented";
clearStatusMsg(30);
}
});
}, false);

View File

@@ -30,7 +30,7 @@ function B220CardatronControl(p) {
"location=no,scrollbars=no,resizable,width=140,height=140,left=" + left +
",top=" + (screen.availHeight-140));
this.window.addEventListener("load",
B220Util.bindMethod(this, B220CardatronControl.prototype.cardatronOnLoad));
B220CardatronControl.prototype.cardatronOnLoad.bind(this), false);
// Set up the I/O devices from the system configuration
this.inputUnit = [
@@ -166,7 +166,7 @@ B220CardatronControl.prototype.cardatronOnLoad = function cardatronOnLoad() {
this.window.addEventListener("beforeunload", B220CardatronControl.prototype.beforeUnload, false);
this.$$("ClearBtn").addEventListener("click",
B220Util.bindMethod(this, B220CardatronControl.prototype.ClearBtn_onClick), false);
B220CardatronControl.prototype.ClearBtn_onClick.bind(this), false);
this.clear();

View File

@@ -68,7 +68,7 @@ function B220CardatronInput(mnemonic, unitIndex, config) {
",left=" + ((unitIndex-1)*32) +
",top=" + (screen.availHeight - h - (unitIndex-1)*32));
this.window.addEventListener("load",
B220Util.bindMethod(this, B220CardatronInput.prototype.readerOnLoad), false);
B220CardatronInput.prototype.readerOnLoad.bind(this), false);
}
/**************************************/
@@ -617,19 +617,19 @@ B220CardatronInput.prototype.readerOnLoad = function readerOnLoad() {
this.window.addEventListener("beforeunload",
B220CardatronInput.prototype.beforeUnload, false);
this.$$("CIFileSelector").addEventListener("change",
B220Util.bindMethod(this, B220CardatronInput.prototype.fileSelector_onChange), false);
B220CardatronInput.prototype.fileSelector_onChange.bind(this), false);
this.$$("FormatColumn").addEventListener("change",
B220Util.bindMethod(this, B220CardatronInput.prototype.format_onChange), false);
B220CardatronInput.prototype.format_onChange.bind(this), false);
this.$$("FormatSelect").addEventListener("change",
B220Util.bindMethod(this, B220CardatronInput.prototype.format_onChange), false);
B220CardatronInput.prototype.format_onChange.bind(this), false);
this.$$("CIStartBtn").addEventListener("click",
B220Util.bindMethod(this, B220CardatronInput.prototype.CIStartBtn_onClick), false);
B220CardatronInput.prototype.CIStartBtn_onClick.bind(this), false);
this.$$("CIStopBtn").addEventListener("click",
B220Util.bindMethod(this, B220CardatronInput.prototype.CIStopBtn_onClick), false);
B220CardatronInput.prototype.CIStopBtn_onClick.bind(this), false);
this.$$("ClearBtn").addEventListener("click",
B220Util.bindMethod(this, B220CardatronInput.prototype.ClearBtn_onClick), false);
B220CardatronInput.prototype.ClearBtn_onClick.bind(this), false);
this.hopperBar.addEventListener("click",
B220Util.bindMethod(this, B220CardatronInput.prototype.CIHopperBar_onClick), false);
B220CardatronInput.prototype.CIHopperBar_onClick.bind(this), false);
this.window.resizeBy(de.scrollWidth - this.window.innerWidth + 4, // kludge for right-padding/margin
de.scrollHeight - this.window.innerHeight);

View File

@@ -70,7 +70,7 @@ function B220CardatronOutput(mnemonic, unitIndex, config) {
",left=" + (screen.availWidth - w) +
",top=" + (screen.availHeight - h - (unitIndex-3)*32));
this.window.addEventListener("load",
B220Util.bindMethod(this, B220CardatronOutput.prototype.deviceOnLoad), false);
B220CardatronOutput.prototype.deviceOnLoad.bind(this), false);
}
/**************************************/
@@ -259,7 +259,7 @@ B220CardatronOutput.prototype.copySupply = function copySupply(ev) {
doc = win.document;
doc.title = title;
doc.getElementById("Paper").textContent = text;
});
}, false);
this.runoutSupply();
ev.preventDefault();
@@ -758,21 +758,21 @@ B220CardatronOutput.prototype.deviceOnLoad = function deviceOnLoad() {
this.window.addEventListener("beforeunload",
B220CardatronOutput.prototype.beforeUnload, false);
this.supply.addEventListener("dblclick",
B220Util.bindMethod(this, B220CardatronOutput.prototype.copySupply), false);
B220CardatronOutput.prototype.copySupply.bind(this), false);
this.$$("COStopBtn").addEventListener("click",
B220Util.bindMethod(this, B220CardatronOutput.prototype.COStopBtn_onClick), false);
B220CardatronOutput.prototype.COStopBtn_onClick.bind(this), false);
this.$$("COStartBtn").addEventListener("click",
B220Util.bindMethod(this, B220CardatronOutput.prototype.COStartBtn_onClick), false);
B220CardatronOutput.prototype.COStartBtn_onClick.bind(this), false);
this.$$("COEndOfSupplyBtn").addEventListener("click",
B220Util.bindMethod(this, B220CardatronOutput.prototype.COEndOfSupplyBtn_onClick), false);
B220CardatronOutput.prototype.COEndOfSupplyBtn_onClick.bind(this), false);
this.$$("CORunoutSupplyBtn").addEventListener("click",
B220Util.bindMethod(this, B220CardatronOutput.prototype.CORunoutSupplyBtn_onClick), false);
B220CardatronOutput.prototype.CORunoutSupplyBtn_onClick.bind(this), false);
this.$$("COAlgolGlyphsCheck").addEventListener("click",
B220Util.bindMethod(this, B220CardatronOutput.prototype.COAlgolGlyphsCheck_onClick), false);
B220CardatronOutput.prototype.COAlgolGlyphsCheck_onClick.bind(this), false);
this.$$("COSetZSBtn").addEventListener("click",
B220Util.bindMethod(this, B220CardatronOutput.prototype.COSetZSBtn_onClick), false);
B220CardatronOutput.prototype.COSetZSBtn_onClick.bind(this), false);
this.$$("ClearBtn").addEventListener("click",
B220Util.bindMethod(this, B220CardatronOutput.prototype.ClearBtn_onClick), false);
B220CardatronOutput.prototype.ClearBtn_onClick.bind(this), false);
if (!this.isPrinter) {
this.$$("COEndOfSupplyBtn").innerHTML = "OUT OF<br>CARDS";
@@ -784,7 +784,7 @@ B220CardatronOutput.prototype.deviceOnLoad = function deviceOnLoad() {
this.$$("CORunoutSupplyBtn").innerHTML = "FORM<br>FEED";
this.$$("COGreenbarSpan").style.display = "inline";
this.$$("COGreenbarCheck").addEventListener("click",
B220Util.bindMethod(this, B220CardatronOutput.prototype.COGreenbarCheck_onClick), false);
B220CardatronOutput.prototype.COGreenbarCheck_onClick.bind(this), false);
}
this.window.moveTo(screen.availWidth - this.window.outerWidth,

View File

@@ -23,10 +23,10 @@ function B220ConsoleKeyboard(p) {
this.window = null; // window object, null if not displayed
this.enabled = false; // true if keyboard is active
this.boundKeypress = B220Util.bindMethod(this, B220ConsoleKeyboard.prototype.keypress);
this.boundButton_Click = B220Util.bindMethod(this, B220ConsoleKeyboard.prototype.button_Click);
this.boundKeyboard_OnLoad = B220Util.bindMethod(this, B220ConsoleKeyboard.prototype.keyboardOnLoad);
this.boundKeyboard_Unload = B220Util.bindMethod(this, B220ConsoleKeyboard.prototype.keyboardUnload);
this.boundKeypress = B220ConsoleKeyboard.prototype.keypress.bind(this);
this.boundButton_Click = B220ConsoleKeyboard.prototype.button_Click.bind(this);
this.boundKeyboard_OnLoad = B220ConsoleKeyboard.prototype.keyboardOnLoad.bind(this);
this.boundKeyboard_Unload = B220ConsoleKeyboard.prototype.keyboardUnload.bind(this);
this.clear();
}

View File

@@ -51,8 +51,8 @@ function B220ConsolePrinter(mnemonic, unitIndex, config) {
this.window = window.open("../webUI/B220ConsolePrinter.html", mnemonic,
"location=no,scrollbars=no,resizable,width=640,height=240," +
"left=" + left + ",top=" + top);
this.window.addEventListener("load", B220Util.bindMethod(this,
B220ConsolePrinter.prototype.printerOnLoad));
this.window.addEventListener("load",
B220ConsolePrinter.prototype.printerOnLoad.bind(this), false);
}
/**************************************/
@@ -216,7 +216,7 @@ B220ConsolePrinter.prototype.copyPaper = function copyPaper(ev) {
doc = win.document;
doc.title = title;
doc.getElementById("Paper").textContent = text;
});
}, false);
this.emptyPaper();
this.emptyLine();
@@ -441,9 +441,9 @@ B220ConsolePrinter.prototype.printerOnLoad = function printerOnLoad() {
this.window.addEventListener("beforeunload",
B220ConsolePrinter.prototype.beforeUnload, false);
this.window.addEventListener("resize",
B220Util.bindMethod(this, B220ConsolePrinter.prototype.resizeWindow), false);
B220ConsolePrinter.prototype.resizeWindow.bind(this), false);
this.paper.addEventListener("dblclick",
B220Util.bindMethod(this, B220ConsolePrinter.prototype.copyPaper), false);
B220ConsolePrinter.prototype.copyPaper.bind(this), false);
this.$$("OpenPanelBtn").addEventListener("click", this.boundButton_Click);
this.$$("ClosePanelBtn").addEventListener("click", this.boundButton_Click);

View File

@@ -99,7 +99,7 @@ function B220ControlConsole(p, systemShutdown) {
"location=no,scrollbars,resizable,width=" + w + ",height=" + h +
",top=0,left=" + (screen.availWidth - w));
this.window.addEventListener("load",
B220Util.bindMethod(this, B220ControlConsole.prototype.consoleOnLoad));
B220ControlConsole.prototype.consoleOnLoad.bind(this), false);
}
/**************************************/
@@ -301,7 +301,7 @@ B220ControlConsole.prototype.meatballMemdump = function meatballMemdump() {
if (p.computerNotReady.value) {s += " CNR"}
if (p.compareLowLamp.value) {s += " LOW"}
if (p.compareEqualLamp.value) {s += " EQUAL"}
if (p.compareLowLamp.value) {s += " HIGH"}
if (p.compareHighLamp.value) {s += " HIGH"}
if (p.C10.value) {s += " C10"}
if (p.DST.value) {s += " DST"}
if (p.LT1.value) {s += " LT1"}
@@ -469,18 +469,18 @@ B220ControlConsole.prototype.updatePanel = function updatePanel() {
text = (timer/1000 + 10000).toFixed(1);
this.intervalTimer.textContent = text.substring(text.length-6);
p.updateGlow(0);
p.updateLampGlow(0);
eLevel = (p.RUT.value ? p.EXT.glow : p.EXT.value);
// Primary Registers
this.regA.updateGlow(p.A.glow);
this.regB.updateGlow(p.B.glow);
this.regC.updateGlow(p.C.glow);
this.regD.updateGlow(p.D.glow);
this.regE.updateGlow(p.E.glow);
this.regP.updateGlow(p.P.glow);
this.regR.updateGlow(p.R.glow);
this.regS.updateGlow(p.S.glow);
this.regA.updateLampGlow(p.A.glow);
this.regB.updateLampGlow(p.B.glow);
this.regC.updateLampGlow(p.C.glow);
this.regD.updateLampGlow(p.D.glow);
this.regE.updateLampGlow(p.E.glow);
this.regP.updateLampGlow(p.P.glow);
this.regR.updateLampGlow(p.R.glow);
this.regS.updateLampGlow(p.S.glow);
// Alarm Panel
this.digitCheckLamp.set(p.digitCheckAlarm.glow);
@@ -984,9 +984,9 @@ B220ControlConsole.prototype.consoleOnLoad = function consoleOnLoad() {
this.resetTransferSwitch.addEventListener("click", this.boundSwitch_Click);
this.tcuClearSwitch.addEventListener("click", this.boundSwitch_Click);
this.$$("BurroughsMeatball").addEventListener("click", this.boundMeatballMemdump);
this.$$("IntervalTimerResetBtn").addEventListener("click", this.boundResetTimer);
this.$$("PowerOffBtn").addEventListener("click", this.boundPowerBtn_Click);
this.$$("BurroughsMeatball").addEventListener("click", this.boundMeatballMemdump, false);
this.$$("IntervalTimerResetBtn").addEventListener("click", this.boundResetTimer, false);
this.$$("PowerOffBtn").addEventListener("dblclick", this.boundPowerBtn_Click, false);
this.window.addEventListener("beforeunload", B220ControlConsole.prototype.beforeUnload);

View File

@@ -41,8 +41,6 @@ DIV.greenBar {
</style>
</head>
<body>
<div id=Paper class=paper></div>
<div id=EndOfPaper></div>
</body>
<!-- Don't add any additional whitespace to the BODY! -->
<body><div id=Paper class=paper></div><div id=EndOfPaper></div></body>
</html>

View File

@@ -32,7 +32,7 @@ function B220MagTapeControl(p) {
"location=no,scrollbars=no,resizable,width=712,height=144,top=" +
(screen.availHeight - top) + ",left=" + left);
this.window.addEventListener("load",
B220Util.bindMethod(this, B220MagTapeControl.prototype.magTapeOnLoad));
B220MagTapeControl.prototype.magTapeOnLoad.bind(this), false);
this.boundReleaseControl = B220MagTapeControl.prototype.releaseControl.bind(this);
this.boundCancelIO = B220MagTapeControl.prototype.cancelIO.bind(this);
@@ -423,7 +423,7 @@ B220MagTapeControl.prototype.loadCommand = function loadCommand(dReg, callee, ar
this.unitIndex = ux = this.findDesignate(this.unitNr);
if (ux < 0) {
this.reportStatus(this.driveState.driveNotReady); // drive not ready, not present
this.releaseProcessor(false, 0);
this.queuePendingOperation(callee, args);
} else {
this.currentUnit = this.tapeUnit[ux];
if (this.currentUnit.busy || this.currentUnit.rewindLock) {
@@ -465,11 +465,11 @@ B220MagTapeControl.prototype.releaseControl = function releaseControl(param) {
/**************************************/
B220MagTapeControl.prototype.cancelIO = function cancelIO(param) {
/* Terminates the current I/O operation by releasing the Processor, tape
unit, and tape control unit. Returns but does not use its parameter so it
can be used with Promise.then() */
/* Terminates the current I/O operation by releasing tape unit, and tape
control unit. Returns but does not use its parameter so it can be used
with Promise.then() */
this.releaseProcessor(false, 0);
//this.releaseProcessor(false, 0); // disabled 2017-12-21
this.currentUnit.releaseUnit();
this.releaseControl();
return param;

View File

@@ -243,6 +243,7 @@ B220MagTapeDrive.prototype.setUnitDesignate = function setUnitDesignate(index) {
} else {
this.unitDesignate = 0; // unit 10
}
this.remote = true;
this.setTapeReady(true);
}
@@ -330,16 +331,12 @@ B220MagTapeDrive.prototype.setTapeReady = function setTapeReady(makeReady) {
this.ready = this.remote & makeReady && enabled;
this.notReadyLamp.set(this.ready ? 0 : 1);
if (!this.ready) {
if (this.ready) {
this.tapeState = this.tapeRemote;
} else {
this.busy = false; // forced reset
this.designatedLamp.set(0);
}
if (enabled) {
if (this.remote) {
this.tapeState = this.tapeRemote;
} else {
this.busy = false; // forced reset
if (this.tapeState == this.tapeRemote) {
this.tapeState = this.tapeLocal;
}
}
@@ -758,8 +755,8 @@ B220MagTapeDrive.prototype.loadTape = function loadTape() {
for (mt.laneNr=0; mt.laneNr<2; ++mt.laneNr) {
lane = mt.image[mt.laneNr];
mt.imgIndex = lx[mt.laneNr];
for (x=0; x<mt.startOfBlockWords*2; ++x) {
lane[mt.imgIndex+x] = mt.markerGap;
for (wx=0; wx<mt.startOfBlockWords*2; ++wx) {
lane[mt.imgIndex+wx] = mt.markerGap;
}
lx[mt.laneNr] = mt.imgIndex + mt.startOfBlockWords*2;
} // for tx (lane number)
@@ -1701,7 +1698,7 @@ B220MagTapeDrive.prototype.readNextBlock = function readNextBlock(driveState, re
}
if (record) { // store the preface word (with keyword sign if a control block)
sign = ((sign*0x10 + (preface%100 - preface%10)/10)*0x10 + preface%10)*0x100000000;
sign = ((sign*0x100 + (preface%100 - preface%10)/10)*0x10 + preface%10)*0x100000000;
if (storeWord(firstWord, sign) < 0) {
state = 10; // memory error storing preface word
driveState.state = driveState.driveMemoryError;

View File

@@ -1,70 +0,0 @@
CACHE MANIFEST
# retro-220 emulator 0.04, 2017-11-19 15:00
CACHE:
../emulator/B220Processor.js
B220.css
B220.html
B220.js
B220CardatronControl.css
B220CardatronControl.html
B220CardatronControl.js
B220CardatronInput.css
B220CardatronInput.html
B220CardatronInput.js
B220CardatronOutput.css
B220CardatronOutput.html
B220CardatronOutput.js
B220CardatronZeroSuppressPanel.html
B220Common.css
B220ConsoleKeyboard.css
B220ConsoleKeyboard.html
B220ConsoleKeyboard.js
B220ConsolePrinter.css
B220ConsolePrinter.html
B220ConsolePrinter.js
B220ControlConsole.css
B220ControlConsole.html
B220ControlConsole.js
#B220DataFile.css
#B220DataFile.html
#B220DataFile.js
B220DiagMonitor.html
B220FramePaper.html
B220MagTapeControl.css
B220MagTapeControl.html
B220MagTapeControl.js
B220MagTapeDrive.css
B220MagTapeDrive.html
B220MagTapeDrive.js
B220MagTapeLoadPanel.html
B220PanelUtil.js
B220PaperTapePunch.css
B220PaperTapePunch.html
B220PaperTapePunch.js
B220PaperTapeReader.css
B220PaperTapeReader.html
B220PaperTapeReader.js
B220SetCallback.js
B220SystemConfig.css
B220SystemConfig.html
B220SystemConfig.js
B220Util.js
resources/B220-Logo.jpg
resources/B220-Site.jpg
resources/Burroughs-Logo.png
resources/Burroughs-Meatball.png
#resources/DataFileTapeHead.png
resources/DejaVuSans-Bold-webfont.ttf
resources/DejaVuSans-Bold-webfont.woff
resources/DejaVuSans-webfont.ttf
resources/DejaVuSans-webfont.woff
resources/DejaVuSansMono-webfont.ttf
resources/DejaVuSansMono-webfont.woff
resources/MagTapeReel.jpg
resources/Organ-Switch-Down.png
resources/Organ-Switch-Up.png
resources/retro-220-Logo.png
resources/retro-Logo.png
resources/ToggleDown.png
resources/ToggleMid.png
resources/ToggleUp.png

View File

@@ -897,7 +897,7 @@ PanelRegister.prototype.update = function update(value) {
};
/**************************************/
PanelRegister.prototype.updateGlow = function updateGlow(glow) {
PanelRegister.prototype.updateLampGlow = function updateLampGlow(glow) {
/* Update the register lamps from the bitwise intensity values in "glow" */
var bitNr;

View File

@@ -26,9 +26,9 @@ function B220PaperTapePunch(mnemonic, unitIndex, config) {
this.nextCharTime = 0; // next time a character can be punched
this.unitMask = 0; // unit selection mask
this.boundFlipSwitch = B220Util.bindMethod(this, B220PaperTapePunch.prototype.flipSwitch);
this.boundReceiveSign = B220Util.bindMethod(this, B220PaperTapePunch.prototype.receiveSign);
this.boundReceiveChar = B220Util.bindMethod(this, B220PaperTapePunch.prototype.receiveChar);
this.boundFlipSwitch = B220PaperTapePunch.prototype.flipSwitch.bind(this);
this.boundReceiveSign = B220PaperTapePunch.prototype.receiveSign.bind(this);
this.boundReceiveChar = B220PaperTapePunch.prototype.receiveChar.bind(this);
this.clear();
@@ -39,8 +39,8 @@ function B220PaperTapePunch(mnemonic, unitIndex, config) {
this.window = window.open("../webUI/B220PaperTapePunch.html", mnemonic,
"location=no,scrollbars=no,resizable,width=240,height=160," +
"left=" + left + ",top=" + top);
this.window.addEventListener("load", B220Util.bindMethod(this,
B220PaperTapePunch.prototype.punchOnLoad));
this.window.addEventListener("load",
B220PaperTapePunch.prototype.punchOnLoad.bind(this), false);
}
/**************************************/
@@ -246,11 +246,11 @@ B220PaperTapePunch.prototype.punchOnLoad = function punchOnLoad() {
// Events
this.window.addEventListener("beforeunload",
B220PaperTapePunch.prototype.beforeUnload);
B220PaperTapePunch.prototype.beforeUnload, false);
this.window.addEventListener("resize",
B220Util.bindMethod(this, B220PaperTapePunch.prototype.resizeWindow));
B220PaperTapePunch.prototype.resizeWindow.bind(this), false);
this.punchTape.addEventListener("dblclick",
B220Util.bindMethod(this, B220PaperTapePunch.prototype.punchCopyTape));
B220PaperTapePunch.prototype.punchCopyTape.bind(this), false);
this.remoteSwitch.addEventListener("click", this.boundFlipSwitch);
this.unitDesignateKnob.addEventListener("change", this.boundFlipSwitch);
@@ -323,7 +323,8 @@ B220PaperTapePunch.prototype.shutDown = function shutDown() {
}
if (this.window) {
this.window.removeEventListener("beforeunload", B220PaperTapePunch.prototype.beforeUnload);
this.window.removeEventListener("beforeunload",
B220PaperTapePunch.prototype.beforeUnload, this);
this.window.close();
this.window = null;
}

View File

@@ -31,8 +31,8 @@ function B220PaperTapeReader(mnemonic, unitIndex, config) {
this.nextCharTime = 0; // next time a character can be read
this.unitMask = 0; // unit selection mask
this.boundFlipSwitch = B220Util.bindMethod(this, B220PaperTapeReader.prototype.flipSwitch);
this.boundReadTapeChar = B220Util.bindMethod(this, B220PaperTapeReader.prototype.readTapeChar);
this.boundFlipSwitch = B220PaperTapeReader.prototype.flipSwitch.bind(this);
this.boundReadTapeChar = B220PaperTapeReader.prototype.readTapeChar.bind(this);
this.readResult = { // object passed back to Processor for each read
code: 0,
@@ -48,7 +48,7 @@ function B220PaperTapeReader(mnemonic, unitIndex, config) {
this.window = window.open("../webUI/B220PaperTapeReader.html", mnemonic,
"location=no,scrollbars=no,resizable,width=420,height=160,left=" + left + ",top=" + top);
this.window.addEventListener("load",
B220Util.bindMethod(this, B220PaperTapeReader.prototype.readerOnload), false);
B220PaperTapeReader.prototype.readerOnload.bind(this), false);
}
/**************************************/
@@ -279,9 +279,9 @@ B220PaperTapeReader.prototype.readerOnload = function readerOnload() {
this.window.addEventListener("beforeunload",
B220PaperTapeReader.prototype.beforeUnload, false);
this.fileSelector.addEventListener("change",
B220Util.bindMethod(this, B220PaperTapeReader.prototype.fileSelector_onChange));
B220PaperTapeReader.prototype.fileSelector_onChange.bind(this), false);
this.tapeSupplyBar.addEventListener("click",
B220Util.bindMethod(this, B220PaperTapeReader.prototype.PRTapeSupplyBar_onclick));
B220PaperTapeReader.prototype.PRTapeSupplyBar_onclick.bind(this), false);
this.remoteSwitch.addEventListener("click", this.boundFlipSwitch);
this.speedSwitch.addEventListener("click", this.boundFlipSwitch);
this.unitDesignateKnob.addEventListener("change", this.boundFlipSwitch);
@@ -399,7 +399,8 @@ B220PaperTapeReader.prototype.shutDown = function shutDown() {
}
if (this.window) {
this.window.removeEventListener("beforeunload", B220PaperTapeReader.prototype.beforeUnload, false);
this.window.removeEventListener("beforeunload",
B220PaperTapeReader.prototype.beforeUnload, false);
this.window.close();
this.window = null;
}

View File

@@ -76,7 +76,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.
* Redesign yet again the delay adjustment mechanism with one from the
* retro-205 project.
* 2017-10-16 P.Kimpel
* Replace window.postMessage yield mechanism with one based on Promise().
***********************************************************************/
@@ -84,6 +85,7 @@
(function (global) {
/* Define a closure for the setCallback() mechanism */
var alpha = 0.25; // decay factor for delay deviation adjustment
var delayDev = {NUL: 0}; // hash of delay time deviations by category
var minTimeout = 4; // minimum setTimeout() threshold, milliseconds
var lastTokenNr = 0; // last setCallback token return value
@@ -172,11 +174,7 @@
if (delay < 0) {
adj = 0; // don't make delay any more negative
} else {
if (delay > delayBias) {
adj = -delayBias;
} else {
adj = -delay;
}
adj = -Math.min(delay, delayBias, minTimeout)*alpha;
}
} else { // delayBias < 0
// We are delaying too little and should try to delay more.

View File

@@ -62,7 +62,7 @@ B220SystemConfig.defaultConfig = {
ConsoleInput: {
units: [
null, // unit[0] not used
{type: "PTRA", unitMask: 0x002, remote: 1, speed: 0},
{type: "PTRA", unitMask: 0x002, remote: 0, speed: 0},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"},
@@ -107,8 +107,8 @@ B220SystemConfig.defaultConfig = {
hasMagTape: true,
units: [
null, // unit[0] not used
{type: "MTA", designate: 1},
{type: "MTB", designate: 2},
{type: "MTA", designate: 0},
{type: "MTB", designate: 1},
{type: "NONE"},
{type: "NONE"},
{type: "NONE"},
@@ -544,16 +544,16 @@ B220SystemConfig.prototype.openConfigUI = function openConfigUI() {
function configUI_Load(ev) {
this.$$("SaveBtn").addEventListener("click",
B220Util.bindMethod(this, this.saveConfigDialog));
this.saveConfigDialog.bind(this), false);
this.$$("CancelBtn").addEventListener("click",
B220Util.bindMethod(this, function(ev) {this.window.close()}));
function(ev) {this.window.close()}.bind(this), false);
this.$$("DefaultsBtn").addEventListener("click",
B220Util.bindMethod(this, function(ev) {
function(ev) {
this.createConfigData();
this.loadConfigDialog();
}));
}.bind(this), false);
this.window.addEventListener("unload",
B220Util.bindMethod(this, this.closeConfigUI), false);
this.closeConfigUI.bind(this), false);
this.loadConfigDialog();
}
@@ -565,5 +565,5 @@ B220SystemConfig.prototype.openConfigUI = function openConfigUI() {
this.window.focus();
this.alertWin = this.window;
this.window.addEventListener("load",
B220Util.bindMethod(this, configUI_Load), false);
configUI_Load.bind(this), false);
};

View File

@@ -62,13 +62,6 @@ B220Util.removeClass = function removeClass(e, name) {
e.classList.remove(name);
};
/**************************************/
B220Util.bindMethod = function bindMethod(context, f) {
/* Returns a new function that binds the function "f" to the object "context" */
return function bindMethodAnon() {return f.apply(context, arguments)};
};
/**************************************/
B220Util.deepCopy = function deepCopy(source, dest) {
/* Performs a deep copy of the object "source" into the object "dest".