1
0
mirror of https://github.com/pkimpel/retro-b5500.git synced 2026-04-25 11:51:49 +00:00

1. Release emulator version 0.14.

2. Fix normalization and rounding problems in Processor.
3. Fix Card-Load-Select -- emulator now boots from cards.
4. Commit LDCNTRL label and end cards to source CONTROL.DECK.job
5. Delete unused activeIOUnit property in all I/O drivers.
6. Change CardReader to reset file selector control when hopper becomes empty, instead of when START button is clicked.
7. Minor adjustments to CentralControl annunciator layout and behavior on Console.
8. Increase SPO paper scroll-back to 1500 lines (was 500).
9. Correct Card-Load-Select behavior in SyllableDebugger.
10. Implement setCallback() to replace setImmediate() in SyllableDebugger.
This commit is contained in:
paul.kimpel@digm.com
2013-10-06 18:26:47 +00:00
parent d1e59a2f7c
commit 72fca54c23
17 changed files with 210 additions and 154 deletions

View File

@@ -61,7 +61,7 @@ function B5500CentralControl() {
/**************************************/
/* Global constants */
B5500CentralControl.version = "0.13";
B5500CentralControl.version = "0.14";
B5500CentralControl.memReadCycles = 2; // assume 2 µs memory read cycle time (the other option was 3 µs)
B5500CentralControl.memWriteCycles = 4; // assume 4 µs memory write cycle time (the other option was 6 µs)
@@ -770,6 +770,7 @@ B5500CentralControl.prototype.loadComplete = function loadComplete(dontStart) {
}
if (completed) {
this.signalInterrupt(); // reset the pending I/O complete interrupt
this.LOFF = 0;
this.P1.preset(0x10); // start execution at C=@20
if (!dontStart) {
@@ -785,7 +786,7 @@ B5500CentralControl.prototype.load = function load(dontStart) {
var result;
var boundLoadComplete = (function boundLoadComplete(that, dontStart) {
return function boundLoadCompleteAnon() {return that.loadComplete(dontStart)}
})(this, dontStart);
}(this, dontStart));
if (!this.P1 || this.P1.busy) { // P1 is busy or not available
result = 1;

View File

@@ -846,7 +846,7 @@ B5500IOUnit.prototype.initiate = function initiate() {
to run asynchronously. Then we exit back through CC and into P1, thus allowing the
actual I/O operation to run asynchronously from the processor. Of course, in a browser
environment, all of the Javascript action occurs on one thread, so this allows us to
multiplex what are supposed to be asynchronous operations on that thread */
multiplex what normally would be asynchronous operations on that thread */
this.initiateStamp = new Date().getTime();
this.clearD();

View File

@@ -1611,10 +1611,9 @@ B5500Processor.prototype.singlePrecisionAdd = function singlePrecisionAdd(adding
d = mb % 8;
mb = (mb - d)/8; // shift right into extension
xb = (xb - xb%8)/8 + d*0x1000000000;
if (mb) {
eb++;
} else {
eb = ea; // if B=0, result will have exponent of A
eb++;
if (mb == 0 && ea != eb) {
eb = ea; // if B=0, kill the scaling loop: result will have exponent of A
xb = 0; // prevent rounding of result
}
}
@@ -1631,9 +1630,8 @@ B5500Processor.prototype.singlePrecisionAdd = function singlePrecisionAdd(adding
d = ma % 8;
ma = (ma - d)/8; // shift right into extension
xa = (xa - xa%8)/8 + d*0x1000000000;
if (ma) {
ea++;
} else {
ea++;
if (ma == 0 && eb != ea) {
ea = eb; // if A=0, kill the scaling loop
xa = 0; // prevent rounding of result
}
@@ -1646,68 +1644,72 @@ B5500Processor.prototype.singlePrecisionAdd = function singlePrecisionAdd(adding
xb = (sb ? -xb : xb) + (sa ? -xa : xa); // compute the extension
if (xb < 0) {
xb += 0x8000000000; // adjust for underflow in the extension
mb += (sb ? 1 : -1); // adjust B for borrow into extension
d = -1; // adjust B for borrow into extension
} else if (xb > 0x8000000000) {
xb -= 0x8000000000; // adjust for overflow in the extension
mb += (sb? -1 : 1); // adjust B for carry from extension
d = 1; // adjust B for carry from extension
} else {
d = 0; // no adjustment
}
mb = (sb ? -mb : mb) + (sa ? -ma : ma); // compute the mantissa
mb = (sb ? -mb : mb) + (sa ? -ma : ma) + d; // compute the mantissa
if (mb >= 0) { // if non-negative...
sb = 0; // reset the B sign bit
} else { // if negative...
sb = 1; // set the B sign bit
mb = -mb; // negate the B mantissa
if (xb) { // if non-zero octades have been shifted into X (and ONLY if... learned THAT the hard way...)
xb = 0x8000000000 - xb; // negate the extension in X
mb--; // and adjust for borrow into X
}
}
// Normalize and round as necessary
if (mb < 0x1000000000) { // Normalization can be required for subtract
if (xb < 0x800000000) { // if first two octades in X < @04 then
d = 0; // no rounding will take place
} else {
this.cycleCount++;
d = (xb - xb%0x1000000000)/0x1000000000; // get the high-order digit from X
xb = (xb%0x1000000000)*8; // shift B and X left together
mb = mb*8 + d;
eb--;
d = (xb - xb%0x1000000000)/0x1000000000; // get the rounding digit from X
}
} else if (mb >= 0x8000000000) { // Scaling can be required for add
this.cycleCount++;
d = mb % 8; // get the rounding digit from B
mb = (mb - d)/8; // shift right due to overflow
eb++;
} else {
d = (xb - xb%0x1000000000)/0x1000000000; // another hard-earned lesson...
}
// Note: the Training Manual does not say that rounding is suppressed
// for add/subtract when the mantissa is all ones, but it does say so
// for multiply/divide, so we assume it's also the case here.
if (d & 0x04) { // if the guard digit >= 4
if (mb < 0x7FFFFFFFFF) { // and rounding would not cause overflow
this.cycleCount++;
mb++; // round up the result
}
}
// Check for exponent overflow
if (eb > 63) {
eb %= 64;
if (this.NCSF) {
this.I = (this.I & 0x0F) | 0xB0; // set I05/6/8: exponent-overflow
this.cc.signalInterrupt();
}
} else if (eb < 0) {
eb = (-eb) | 0x40; // set the exponent sign bit
}
this.X = xb; // for display purposes only
if (mb == 0) { // if the mantissa is zero...
this.B = 0; // the whole result is zero, and we're done
} else { // otherwise, determine the resulting sign
if (mb > 0) { // if positive...
sb = 0; // reset the B sign bit
} else { // if negative...
sb = 1; // set the B sign bit
mb = -mb; // negate the B mantissa
if (xb) { // if non-zero octades have been shifted into X (and ONLY if... learned THAT the hard way...)
xb = 0x8000000000 - xb; // negate the extension in X
mb--; // and adjust for borrow into X
}
}
// Normalize and round as necessary
if (mb < 0x1000000000) { // Normalization can be required for subtract
if (xb < 0x800000000) { // if first two octades in X < @04 then
d = 0; // no rounding will take place
} else {
this.cycleCount++;
d = (xb - xb%0x1000000000)/0x1000000000; // get the rounding digit from X
xb = (xb%0x1000000000)*8; // shift B and X left together
mb = mb*8 + d;
eb--;
d = (xb - xb%0x1000000000)/0x1000000000; // get the next rounding digit from X
}
} else if (mb >= 0x8000000000) { // Scaling can be required for add
this.cycleCount++;
d = mb % 8; // get the rounding digit from B
mb = (mb - d)/8; // shift right due to overflow
eb++;
}
// Note: the Training Manual does not say that rounding is suppressed
// for add/subtract when the mantissa is all ones, but it does say so
// for multiply/divide, so we assume it's also the case here.
if (d & 0x04) { // if the guard digit >= 4
if (mb < 0x7FFFFFFFFF) {// and rounding would not cause overflow
this.cycleCount++;
mb++; // round up the result
}
}
// Check for exponent overflow
if (eb > 63) {
eb %= 64;
if (this.NCSF) {
this.I = (this.I & 0x0F) | 0xB0; // set I05/6/8: exponent-overflow
this.cc.signalInterrupt();
}
} else if (eb < 0) {
eb = (-eb) | 0x40; // set the exponent sign bit
}
this.X = xb; // for display purposes only
this.B = (sb*128 + eb)*0x8000000000 + mb; // Final Answer
}
}
@@ -1792,6 +1794,7 @@ B5500Processor.prototype.singlePrecisionMultiply = function singlePrecisionMulti
// Normalize the result
if (this.Q & 0x10 && mb == 0) { // if it's integer multiply (Q05F) with integer result
mb = mx; // just use the low-order 39 bits
mx = 0;
eb = 0; // and don't normalize
} else {
eb += ea+13; // compute resulting exponent from multiply

1
tools/CONTROL.DECK.job Normal file
View File

@@ -0,0 +1 @@
?LABEL 0CONTROL0DECK 0018317900

1
tools/END.CONTROL.job Normal file
View File

@@ -0,0 +1 @@
? END CONTROL

View File

@@ -62,7 +62,6 @@ B5500CardPunch.prototype.clear = function clear() {
this.ready = false; // ready status
this.busy = false; // busy status
this.activeIOUnit = 0; // I/O unit currently using this device
this.errorMask = 0; // error mask for finish()
this.finish = null; // external function to call for I/O completion

View File

@@ -73,7 +73,6 @@ B5500CardReader.prototype.clear = function clear() {
this.ready = false; // ready status
this.busy = false; // busy status
this.activeIOUnit = 0; // I/O unit currently using this device
this.errorMask = 0; // error mask for finish()
this.finish = null; // external function to call for I/O completion
@@ -148,7 +147,6 @@ B5500CardReader.prototype.CRStartBtn_onclick = function CRStartBtn_onclick(ev) {
var that = this;
if (!this.ready) {
this.$$("CRFileSelector").value = null; // reset the control so the same file can be reloaded
if (this.bufIndex < this.bufLength) {
this.setReaderReady(true);
}
@@ -185,6 +183,9 @@ B5500CardReader.prototype.CRProgressBar_onclick = function CRProgressBar_onclick
this.bufLength = 0;
this.bufIndex = 0;
this.$$("CRProgressBar").value = 0;
while (this.outHopper.childNodes.length > 0) {
this.outHopper.removeChild(this.outHopper.firstChild);
}
}
}
};
@@ -392,6 +393,7 @@ B5500CardReader.prototype.read = function read(finish, buffer, length, mode, con
this.bufLength = 0;
this.bufIndex = 0;
this.setReaderReady(false);
this.$$("CRFileSelector").value = null; // reset the control so the same file can be reloaded
}
this.timer = setTimeout(function readDelay() {

View File

@@ -15,15 +15,17 @@ BODY {
margin: 4px}
DIV#consoleDiv {
position: relative;
width: 1052px;
height: 72px;
padding: 32px;
position: absolute;
left: 0;
top: 0;
width: 1125px;
height: 140px;
border-radius: 8px;
background-color: #666}
DIV#BurroughsLogo {
background-color: black;
position: absolute;
background-color: black;
top: 32px;
right: 32px;
border-top: 3px solid #EEE;
@@ -202,17 +204,17 @@ BUTTON#PowerOffBtn {
TABLE#CentralControl {
position: absolute;
bottom: 0;
width: 100%;
color: #666;
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
font-size: 7pt;
font-weight: bold}
COL.AnnunciatorCol {
width: 2.9%}
width: 28px}
TD#procDelay, TD#procSlack {
color: white;
width: 64px;
text-align: right}
TD.statLabel {
color: white;

View File

@@ -47,7 +47,7 @@ window.addEventListener("load", function() {
var perLightsMap = new Array(48);
var procDelay;
var procSlack;
var showAnnunciators = false;
var showAnnunciators = true;
var timer;
var timerInterval = 50; // milliseconds
@@ -77,8 +77,10 @@ window.addEventListener("load", function() {
$$("LoadBtn").disabled = false;
$$("HaltBtn").disabled = true;
boundBlinkenlicht();
BurroughsLogo_Click(); // turn on the annunciators
window.focus();
if (showAnnunciators) {
$$("CentralControl").style.visibility = "visible";
}
return true;
}
@@ -92,6 +94,7 @@ window.addEventListener("load", function() {
$$("MemoryCheckBtn").className = "redButton";
$$("NotReadyBtn").className = "whiteButton";
$$("HaltBtn").className = "redButton";
$$("CentralControl").style.visibility = "hidden";
cc.powerOff();
$$("PowerOnBtn").disabled = false;
$$("PowerOffBtn").disabled = true;

View File

@@ -97,7 +97,6 @@ B5500DiskUnit.prototype.clear = function clear() {
this.ready = false; // ready status
this.busy = false; // busy status
this.activeIOUnit = 0; // I/O unit currently using this device
this.errorMask = 0; // error mask for finish()
this.finish = null; // external function to call for I/O completion

View File

@@ -65,7 +65,6 @@ B5500DummyPrinter.prototype.clear = function clear() {
this.ready = false; // ready status
this.busy = false; // busy status
this.activeIOUnit = 0; // I/O unit currently using this device
this.errorMask = 0; // error mask for finish()
this.finish = null; // external function to call for I/O completion

View File

@@ -40,7 +40,6 @@ B5500DummyUnit.prototype.clear = function clear() {
this.ready = false; // ready status
this.busy = false; // busy status
this.activeIOUnit = 0; // I/O unit currently using this device
this.errorMask = 0; // error mask for finish()
this.finish = null; // external function to call for I/O completion

View File

@@ -20,7 +20,7 @@
function B5500SPOUnit(mnemonic, unitIndex, designate, statusChange, signal) {
/* Constructor for the SPOUnit object */
this.maxScrollLines = 500; // Maximum amount of printer scrollback
this.maxScrollLines = 1500; // Maximum amount of printer scrollback
this.charPeriod = 100; // Printer speed, milliseconds per character
this.mnemonic = mnemonic; // Unit mnemonic
@@ -76,7 +76,6 @@ B5500SPOUnit.prototype.clear = function clear() {
this.ready = false; // ready status
this.busy = false; // busy status
this.activeIOUnit = 0; // I/O unit currently using this device
this.errorMask = 0; // error mask for finish()
this.finish = null; // external function to call for I/O completion

View File

@@ -7,7 +7,7 @@
<meta http-equiv="Content-Style-Type" content="text/css">
<link id=defaultStyleSheet rel=stylesheet type="text/css" href="B5500SyllableDebugger.css">
<script src="./setImmediate.js"></script>
<script src="./B5500SetCallback.js"></script>
<script src="./B5500DummyUnit.js"></script>
<script src="./B5500SPOUnit.js"></script>
@@ -714,8 +714,47 @@ function runIt(ev) {
var stopAddr = $$("StopAddr");
function syllabicate() {
var addr;
var prt;
var word;
do {
cc.P1.step();
if (false) { // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< DEBUG <<<<<<<<<<
addr = cc.memMod[0][149] % 0x8000 + 1; // MCP PRT @225: addr of PRT[1,*] DD
word = cc.memMod[addr >>> 12][addr & 0xFFF]; // PRT[2,*] DD
if (word > 0xA00000000000) {
prt = word % 0x8000
if (false) { // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< DEBUG <<<<<<<<<<
addr = prt + 70; // addr of STACKHEAD DD
word = cc.memMod[addr >>> 12][addr & 0xFFF]; // STACKHEAD DD
if (word > 0xA00000000000) {
addr = word % 0x8000 + 66; // addr of STACKHEAD[66]
word = cc.memMod[addr >>> 12][addr & 0xFFF];
if (word == 2) {
alert("STACKHEAD[66]==2");
stopAddress = 0;
}
}
} // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
addr = prt + 204; // addr of NEXTINFO
word = cc.memMod[addr >>> 12][addr & 0xFFF]; // NEXTINFO
if (window.uglyLatch) {
if (word <= 2) {
alert("NEXTINFO==1");
stopAddress = 0;
}
} else {
if (word > 255) {
window.uglyLatch = true;
}
}
}
} // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
if (cc.P1.S > 0x7FFF) {
alert("P1.S out of range");
stopAddress = 0;
@@ -740,7 +779,7 @@ function runIt(ev) {
} while (runSilently && stopAddress && cc.P1.C != stopAddress);
if (stopAddress && cc.P1.C != stopAddress) {
setImmediate(syllabicate);
setCallback(syllabicate, this, 0);
if (!runSilently) {
displaySystemState();
}
@@ -884,11 +923,11 @@ function hardwareLoad_onClick(ev) {
var result;
cc.clear();
cc.P1.clear();
cc.cardLoadSelect = $$("CardLoadSelect").checked;
result = cc.load(true);
switch (result) {
case 0: // load initiated successfully
cc.P1.clear();
cc.cardLoadSelect = $$("CardLoadSelect").checked;
displaySystemState();
break;
case 1:
@@ -1103,6 +1142,7 @@ function initialize() {
displaySystemState();
displayOctal("StopAddr", stopAddress, 5);
establishSilence(runSilently);
$$("StepBtn").disabled = false;
}
window.onload = function() {

View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<title>B5500 Emulator SPO Paper Prototype</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Author" content="Nigel Williams & Paul Kimpel">
<!-- 2013-07-25 Orignal version -->
<meta http-equiv="Content-Script-Type" content="text/javascript">
<meta http-equiv="Content-Style-Type" content="text/css">
<link id=defaultStyleSheet rel=stylesheet type="text/css" href="B5500SPOPrototype.css">
</head>
<body class="SPOUT">
TEST TEST
</body>
</html>

View File

@@ -14,46 +14,52 @@ BODY {
position: relative;
background-color: black;
margin: 4px}
PRE {
font-family: Lucida Sans Typewriter, Courier New, Courier, monospace;
font-size: 10pt;
font-size: xx-small;
margin: 0}
DIV#SPODiv {
position: relative;
width: 800px;
width: 660px;
height: 500px;
background-color: #FDA;
border-radius: 32px;
padding: 2em;
border-radius: 16px;
text-align: left}
IFRAME#SPOUT {
width: 620px;
height: 475px;
border: 2px solid black;
position: absolute;
left: 16px;
bottom: 16px;
height: 468px;
width: 470px;
border: 1px solid black}
BODY.SPOUT {
background-color: #FFE;
font-family: Lucida Sans Typewriter, Courier New, Courier, monospace;
font-size: 10pt}
font-size: xx-small}
DIV#SPOControlsDiv {
position: absolute;
text-align: center;
width: 136px;
left: 690px;
top: 32px}
right: 16px;
bottom: 16px}
IMG#TeletypeLogo {
left: auto;
right: auto}
position: absolute;
top: 16px;
left: 66px}
BUTTON.whiteButton {
position: absolute;
background-color: #CCC;
color: black;
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
font-size: 10px;
font-size: xx-small;
font-weight: bold;
width: 60px;
height: 40px;
@@ -65,7 +71,7 @@ BUTTON.blackButton {
background-color: black;
color: white;
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
font-size: 10px;
font-size: xx-small;
font-weight: bold;
width: 60px;
height: 40px;
@@ -77,7 +83,7 @@ BUTTON.yellowButton {
background-color: #990;
color: black;
font-family: Arial Rounded, Arial, Helvetica, sans-serif;
font-size: 10px;
font-size: xx-small;
font-weight: bold;
width: 60px;
height: 40px;
@@ -89,48 +95,48 @@ BUTTON.whiteLit {
BUTTON.yellowLit {
background-color: #FF0}
BUTTON.blackBorder {
border: 1px solid black}
BUTTON#SPOReadyBtn {
top: 187px;
bottom: 224px;
left: 0px}
BUTTON#SPOPowerBtn {
top: 187px;
bottom: 224px;
right: 0px}
BUTTON#SPORemoteBtn {
top: 243px;
bottom: 168px;
left: 0px}
BUTTON#SPOLocalBtn {
top: 243px;
bottom: 168px;
right: 0px}
BUTTON#SPOInputRequestBtn {
top: 299px;
bottom: 112px;
left: 0px}
BUTTON#SPOEndOfMessageBtn {
top: 299px;
bottom: 112px;
right: 0px}
BUTTON#SPOBlank1Btn {
top: 355px;
bottom: 56px;
left: 0px}
BUTTON#SPOErrorBtn {
top: 355px;
bottom: 56px;
right: 0px}
BUTTON#SPOBlank2Btn {
top: 411px;
bottom: 0px;
left: 0px}
BUTTON#SPOBlank3Btn {
top: 411px;
bottom: 0px;
right: 0px}
.center {
@@ -139,7 +145,7 @@ BUTTON#SPOBlank3Btn {
.data {
font-family: Courier New, Courier, monospace;
text-align: left}
.number {
font-family: Courier New, Courier, monospace;
text-align: right}

View File

@@ -1,4 +1,5 @@
<!DOCTYPE html>
<html>
<head>
<title>B5500 Emulator SPO Unit Prototype</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
@@ -10,8 +11,7 @@
<script>
"use strict";
window.onload = function() {
const spoNotReady = 0;
window.addEventListener("load", function() {
const spoLocal = 1;
const spoRemote = 2;
const spoInput = 3;
@@ -19,7 +19,7 @@ window.onload = function() {
var $$ = function(e) {return document.getElementById(e)};
var msgTank = [];
var spoState = spoNotReady;
var spoState = spoLocal;
var spoLocalRequested = false;
var spoInputActive = false;
var spoInputRequested = false;
@@ -74,7 +74,7 @@ window.onload = function() {
frame.contentDocument.head.innerHTML += "<style>" +
"BODY {background-color: #FFE} " +
"PRE {margin: 0; font-size: 10pt; font-family: Lucida Sans Typewriter, Courier New, Courier, monospace}" +
"PRE {margin: 0; font-size: x-small; font-family: Lucida Sans Typewriter, Courier New, Courier, monospace}" +
"</style>";
};
@@ -94,10 +94,10 @@ window.onload = function() {
};
var accept = function() {
var inputBtn = $$("SPOInputRequestBtn");
spoState = spoInput;
addClass(inputBtn, "yellowLit");
removeClass($$("SPOInputRequestBtn"), "yellowLit");
addClass($$("SPOReadyBtn"), "yellowLit")
window.focus();
msgCtl.buffer = new Uint8Array(80);
@@ -218,20 +218,6 @@ window.onload = function() {
}
};
var setReady = function(ready) {
/* Sets the ready status of the SPO based on the truth of "ready" */
var readyBtn = $$("SPOReadyBtn");
if (ready && spoState == spoNotReady) {
addClass(readyBtn, "yellowLit");
spoState = spoLocal;
setRemote(true);
} else if (!ready && spoState != spoNotReady) {
spoState = spoNotReady;
removeClass(readyBtn, "yellowLit");
}
};
var setRemote = function(remote) {
/* Sets the remote status of the SPO based on the truth of "remote" */
var localBtn = $$("SPOLocalBtn");
@@ -252,6 +238,7 @@ window.onload = function() {
var initiateInput = function(ev) {
/* Handles a successful Input Request event and enables the keyboard */
addClass($$("SPOInputRequestBtn"), "yellowLit");
if (spoState == spoRemote) {
accept();
} else if (spoState == spoOutput) {
@@ -269,7 +256,7 @@ window.onload = function() {
} else {
spoState = spoRemote;
}
removeClass($$("SPOInputRequestBtn"), "yellowLit");
removeClass($$("SPOReadyBtn"), "yellowLit");
text = String.fromCharCode.apply(null, msgCtl.buffer.subarray(0, msgCtl.length));
printChar();
printText("YOU ENTERED: " + text);
@@ -286,7 +273,7 @@ window.onload = function() {
} else {
spoState = spoRemote;
}
removeClass($$("SPOInputRequestBtn"), "yellowLit");
removeClass($$("SPOReadyBtn"), "yellowLit");
printChar();
printText("**ERROR");
}
@@ -425,19 +412,18 @@ window.onload = function() {
};
addFrameStyles($$("SPOUT"));
appendEmptyLine(32);
setReady(true);
appendEmptyLine(100);
setRemote(true);
doTests();
};
}, false);
</script>
</head>
<body>
<div id=SPODiv>
<iframe id=SPOUT scrolling=auto></iframe>
<iframe id=SPOUT data-type-src="./B5500SPOPaperPrototype.html" scrolling=auto></iframe>
<div id=SPOControlsDiv>
<img id=TeletypeLogo src="TeletypeLogo.gif">
<button id=SPOReadyBtn class="yellowButton blackBorder">READY</button>