mirror of
https://github.com/pkimpel/retro-b5500.git
synced 2026-04-18 10:06:01 +00:00
Commit Release 1.01:
1. Split operator Control Panel from B5500Console and make it a small, separate window. 2. Implement emulator home page in what remains of B5500Console page, with Start buttons for emulator. 3. Implement improvements to setCallback() mechanism, copied from Datatron 205 project. 4. Increase scrollback for SPO and Datacom windows from 1500 to 5000 lines. 5. Correct application of green-bar styling in B5500LinePrinter (apparent in Chrome). 6. Improve initial positioning of Magnetic Tape unit windows; add "B" to mag tape reel image. 7. Minor optimizations to bit-field isolate/insert routines in CentralControl. 8. Miscellaneous enhancements to UI appearance. 9. Minor changes to hosting website pages.
This commit is contained in:
@@ -61,7 +61,7 @@ function B5500CentralControl(global) {
|
||||
/**************************************/
|
||||
|
||||
/* Global constants */
|
||||
B5500CentralControl.version = "1.00";
|
||||
B5500CentralControl.version = "1.01";
|
||||
|
||||
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)
|
||||
@@ -83,7 +83,7 @@ B5500CentralControl.pow2 = [ // powers of 2 from 0 to 52
|
||||
0x1000000000000, 0x2000000000000, 0x4000000000000, 0x8000000000000,
|
||||
0x10000000000000];
|
||||
|
||||
B5500CentralControl.mask2 = [ // (2**n)-1 For n From 0 to 52
|
||||
B5500CentralControl.mask2 = [ // (2**n)-1 for n from 0 to 52
|
||||
0x0, 0x1, 0x3, 0x7,
|
||||
0x0F, 0x1F, 0x3F, 0x7F,
|
||||
0x0FF, 0x1FF, 0x3FF, 0x7FF,
|
||||
@@ -240,11 +240,12 @@ B5500CentralControl.prototype.bitSet = function bitSet(word, bit) {
|
||||
/* Sets the specified bit in word and returns the updated word */
|
||||
var ue = 48-bit; // word upper power exponent
|
||||
var le = ue-1; // word lower power exponent
|
||||
var bpower = 1; // bottom portion of word power of 2
|
||||
var bpower = // bottom portion of word power of 2
|
||||
B5500CentralControl.pow2[le];
|
||||
var bottom = // unaffected bottom portion of word
|
||||
(le == 0 ? 0 : (word % (bpower = B5500CentralControl.pow2[le])));
|
||||
(le <= 0 ? 0 : (word % bpower));
|
||||
var top = // unaffected top portion of word
|
||||
(bit == 0 ? 0 : (word - (word % B5500CentralControl.pow2[ue])));
|
||||
(bit <= 0 ? 0 : (word - (word % B5500CentralControl.pow2[ue])));
|
||||
|
||||
return bpower + top + bottom;
|
||||
};
|
||||
@@ -255,9 +256,9 @@ B5500CentralControl.prototype.bitReset = function bitReset(word, bit) {
|
||||
var ue = 48-bit; // word upper power exponent
|
||||
var le = ue-1; // word lower power exponent
|
||||
var bottom = // unaffected bottom portion of word
|
||||
(le == 0 ? 0 : (word % B5500CentralControl.pow2[le]));
|
||||
(le <= 0 ? 0 : (word % B5500CentralControl.pow2[le]));
|
||||
var top = // unaffected top portion of word
|
||||
(bit == 0 ? 0 : (word - (word % B5500CentralControl.pow2[ue])));
|
||||
(bit <= 0 ? 0 : (word - (word % B5500CentralControl.pow2[ue])));
|
||||
|
||||
return top + bottom;
|
||||
};
|
||||
@@ -268,7 +269,7 @@ B5500CentralControl.prototype.fieldIsolate = function fieldIsolate(word, start,
|
||||
var le = 48-start-width; // lower power exponent
|
||||
var p; // bottom portion of word power of 2
|
||||
|
||||
return (le == 0 ? word :
|
||||
return (le <= 0 ? word :
|
||||
(word - word % (p = B5500CentralControl.pow2[le]))/p
|
||||
) % B5500CentralControl.pow2[width];
|
||||
};
|
||||
@@ -279,11 +280,12 @@ B5500CentralControl.prototype.fieldInsert = function fieldInsert(word, start, wi
|
||||
into word.[start:width] and returns the updated word */
|
||||
var ue = 48-start; // word upper power exponent
|
||||
var le = ue-width; // word lower power exponent
|
||||
var bpower = 1; // bottom portion of word power of 2
|
||||
var bpower = // bottom portion of word power of 2
|
||||
B5500CentralControl.pow2[le];
|
||||
var bottom = // unaffected bottom portion of word
|
||||
(le == 0 ? 0 : (word % (bpower = B5500CentralControl.pow2[le])));
|
||||
(le <= 0 ? 0 : (word % bpower));
|
||||
var top = // unaffected top portion of word
|
||||
(ue == 0 ? 0 : (word - (word % B5500CentralControl.pow2[ue])));
|
||||
(ue <= 0 ? 0 : (word - (word % B5500CentralControl.pow2[ue])));
|
||||
|
||||
return (value % B5500CentralControl.pow2[width])*bpower + top + bottom;
|
||||
};
|
||||
@@ -296,13 +298,14 @@ B5500CentralControl.prototype.fieldTransfer = function fieldTransfer(word, wstar
|
||||
var le = ue-width; // word lower power exponent
|
||||
var ve = 48-vstart-width; // value lower power exponent
|
||||
var vpower; // bottom port of value power of 2
|
||||
var bpower = 1; // bottom portion of word power of 2
|
||||
var bpower = // bottom portion of word power of 2
|
||||
B5500CentralControl.pow2[le];
|
||||
var bottom = // unaffected bottom portion of word
|
||||
(le == 0 ? 0 : (word % (bpower = B5500CentralControl.pow2[le])));
|
||||
(le <= 0 ? 0 : (word % bpower));
|
||||
var top = // unaffected top portion of word
|
||||
(ue == 0 ? 0 : (word - (word % B5500CentralControl.pow2[ue])));
|
||||
(ue <= 0 ? 0 : (word - (word % B5500CentralControl.pow2[ue])));
|
||||
|
||||
return ((ve == 0 ? value :
|
||||
return ((ve <= 0 ? value :
|
||||
(value - value % (vpower = B5500CentralControl.pow2[ve]))/vpower
|
||||
) % B5500CentralControl.pow2[width]
|
||||
)*bpower + top + bottom;
|
||||
|
||||
@@ -3137,7 +3137,7 @@ B5500Processor.prototype.indexDescriptor = function indexDescriptor() {
|
||||
var xt; // index exponent sign
|
||||
|
||||
this.adjustABFull();
|
||||
aw = this.A;
|
||||
aw = this.A;
|
||||
bw = this.B;
|
||||
xm = (bw % 0x8000000000);
|
||||
xe = (bw - xm)/0x8000000000;
|
||||
@@ -3510,7 +3510,7 @@ B5500Processor.prototype.operandCall = function operandCall() {
|
||||
if (this.A >= 0x800000000000 && this.NCSF) {// Flag bit is set
|
||||
this.I = (this.I & 0x0F) | 0x80; // set I08: flag-bit interrupt
|
||||
this.cc.signalInterrupt();
|
||||
dumpState("Flag Bit: OPDC"); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< DEBUG >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
// B5500DumpState("Flag Bit: OPDC"); // <<< DEBUG >>>
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
11
index.html
11
index.html
@@ -18,7 +18,7 @@
|
||||
Burroughs B5500 Emulator Hosting Site
|
||||
</h1>
|
||||
|
||||
<p>This site hosts the current version of the retro-B5500 emulator, an implementation of the legendary Burroughs B5500 that runs in a web-browser.
|
||||
<p>This site hosts the current version of the retro-B5500 emulator, an implementation of the legendary Burroughs B5500 that runs in a web browser.
|
||||
|
||||
<p class=center>
|
||||
<img src="./webSite/b5500.jpg" alt="Typical B5500 installation">
|
||||
@@ -27,8 +27,8 @@
|
||||
<h2>Main Links</h2>
|
||||
|
||||
<ul>
|
||||
<li><a href="./webUI/B5500Console.html">B5500 Console</a>
|
||||
<br>The B5500 operations console from which you run the emulator.
|
||||
<li><a href="./webUI/B5500Console.html">B5500 Home Page</a>
|
||||
<br>The home page from which you can start the emulator and open the B5500 Operations Console.
|
||||
|
||||
<li><a href="./webSite/HelpMenu.html">Help & Getting Started</a>
|
||||
<br>A menu of information resources to assist you in setting up and operating the emulator.
|
||||
@@ -50,6 +50,9 @@
|
||||
|
||||
<li><a href="./webSite/SoftwareRequest.html">B5500 System Software</a>
|
||||
<br>Tape images of B5500 system software for the Mark XIII (1971) software release. You must download at least the SYSTEM tape image in order to set up the emulator in your browser.
|
||||
|
||||
<li><a href="http://bitsavers.org/pdf/burroughs/B5000_5500_5700/">Burroughs Documents at bitsavers.org</a>
|
||||
<br>A collection of scanned copies of original Burroughs manuals and other reference materials for the B5500 system.
|
||||
</ul>
|
||||
|
||||
|
||||
@@ -59,7 +62,7 @@
|
||||
Copyright (c) 2013, Nigel Williams and Paul Kimpel • Licensed under the MIT License
|
||||
</div>
|
||||
<div id=lastModDiv>Revised
|
||||
2014-07-19
|
||||
2015-02-08
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
@@ -28,15 +28,15 @@ You can read the story of how this came about in the
|
||||
|
||||
<p>As a result of that design approach more than 50 years ago, having a B5500 emulator today is not all that interesting unless you also have the associated system software to make it do something. Alas, software was maintained in those days on punched cards and 7-track, open-reel magnetic tape, neither of which have seen much use in the last 30 years. Open-reel magnetic tape, in particular, is not known for having long-term archival qualities.
|
||||
|
||||
<p>Fortunately for us, Sid McHarg of Seattle, Washington (US) had preserved a set Burroughs 7-track release tapes for the B5500 Mark XIII (October 1971) version of the system software. Even more fortunately, Sid was able to work with Paul Pierce of Portland, Oregon (US) to recover the data from those tapes. We are indebted to Sid and Paul for their work in recovering those tapes and making the resulting data available.
|
||||
<p>Fortunately for us, Sid McHarg of Seattle, Washington (US) had preserved a set Burroughs 7-track release tapes for the B5500 Mark XIII (October 1971) version of the system software. Even more fortunately, Sid was able to work with Paul Pierce of Portland, Oregon (US) to recover the data from those tapes. We are indebted to Sid and Paul for their work on those tapes and making the resulting data available.
|
||||
|
||||
<p>Burroughs became part of Unisys Corporation in 1986. Unisys still owns and holds copyrights on the B5500 system software, so Sid worked with Bob Supnik, VP of Engineering and Supply Chain at Unisys, to arrange an educational/hobbyist license for this software. We have acquired such a license, and are thus indebted to Bob and Unisys for generously allowing us to use the B5500 Mark XIII software under the
|
||||
<p>Burroughs became part of Unisys Corporation in 1986. Unisys still owns and holds copyrights on the B5500 system software, so Sid worked with Bob Supnik, then VP of Engineering and Supply Chain at Unisys, to arrange an educational/hobbyist license for this software. We have acquired such a license, and are thus indebted to Bob and Unisys for generously allowing us to use the B5500 Mark XIII software under the
|
||||
<a href="./Unisys-B5500-Software-License.pdf">terms of that license</a>.
|
||||
|
||||
|
||||
<h2>Downloading the Tape Images</h2>
|
||||
|
||||
<p>Our license with Unisys allows us to make the Mark XIII software available to others under the terms of that license. There are three tape images, as enumerated below. To download one of the images, please click its corresponding link below. The resulting page will display the applicable terms of the Unisys license and a directory of the files on that image. Confirm your acceptance of the license terms to begin the download. You will need to download at least the <b>SYSTEM</b> image in order to run the emulator.
|
||||
<p>Our license with Unisys allows us to make the Mark XIII software available to others under the terms of that license. There are three tape images, as enumerated below. To download one of the images, please click its corresponding link. The resulting page will display the applicable terms of the Unisys license and a directory of the files on that image. Confirm your acceptance of the license terms to begin the download. You will need to download at least the <b>SYSTEM</b> image in order to run the emulator.
|
||||
|
||||
<dl>
|
||||
<dt><a href="./TapeImage-SYSTEM.html"><b>SYSTEM</b></a> image (2.6MiB <code>.zip</code>)
|
||||
@@ -70,7 +70,7 @@ in the /tools directory.
|
||||
Copyright (c) 2013, Nigel Williams and Paul Kimpel • Licensed under the MIT License
|
||||
</div>
|
||||
<div id=lastModDiv>Revised
|
||||
2013-07-20
|
||||
2014-10-24
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
@@ -113,7 +113,7 @@ B5500CardReader.prototype.armEOF = function armEOF(armed) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CardReader.prototype.CRStartBtn_onclick = function CRStartBtn_onclick(ev) {
|
||||
B5500CardReader.prototype.CRStartBtn_onClick = function CRStartBtn_onClick(ev) {
|
||||
/* Handle the click event for the START button */
|
||||
|
||||
if (!this.ready) {
|
||||
@@ -124,7 +124,7 @@ B5500CardReader.prototype.CRStartBtn_onclick = function CRStartBtn_onclick(ev) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CardReader.prototype.CRStopBtn_onclick = function CRStopBtn_onclick(ev) {
|
||||
B5500CardReader.prototype.CRStopBtn_onClick = function CRStopBtn_onClick(ev) {
|
||||
/* Handle the click event for the STOP button */
|
||||
|
||||
this.$$("CRFileSelector").value = null; // reset the control so the same file can be reloaded
|
||||
@@ -136,19 +136,19 @@ B5500CardReader.prototype.CRStopBtn_onclick = function CRStopBtn_onclick(ev) {
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CardReader.prototype.CREOFBtn_onclick = function CREOFBtn_onclick(ev) {
|
||||
B5500CardReader.prototype.CREOFBtn_onClick = function CREOFBtn_onClick(ev) {
|
||||
/* Handle the click event for the EOF button */
|
||||
|
||||
this.armEOF(!this.eofArmed);
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500CardReader.prototype.CRHopperBar_onclick = function CRHopperBar_onclick(ev) {
|
||||
B5500CardReader.prototype.CRHopperBar_onClick = function CRHopperBar_onClick(ev) {
|
||||
/* Handle the click event for the "input hopper" meter bar */
|
||||
|
||||
if (this.bufIndex < this.bufLength && !this.ready) {
|
||||
if (this.window.confirm((this.bufLength-this.bufIndex).toString() + " of " + this.bufLength.toString() +
|
||||
" characters remaining to read.\nDo you want to clear the reader input hopper?")) {
|
||||
" characters remaining to read.\nDo you want to clear the input hopper?")) {
|
||||
this.buffer = "";
|
||||
this.bufLength = 0;
|
||||
this.bufIndex = 0;
|
||||
@@ -324,13 +324,13 @@ B5500CardReader.prototype.readerOnload = function readerOnload() {
|
||||
this.$$("CRFileSelector").addEventListener("change",
|
||||
B5500CentralControl.bindMethod(this, B5500CardReader.prototype.fileSelector_onChange), false);
|
||||
this.$$("CRStartBtn").addEventListener("click",
|
||||
B5500CentralControl.bindMethod(this, B5500CardReader.prototype.CRStartBtn_onclick), false);
|
||||
B5500CentralControl.bindMethod(this, B5500CardReader.prototype.CRStartBtn_onClick), false);
|
||||
this.$$("CRStopBtn").addEventListener("click",
|
||||
B5500CentralControl.bindMethod(this, B5500CardReader.prototype.CRStopBtn_onclick), false);
|
||||
B5500CentralControl.bindMethod(this, B5500CardReader.prototype.CRStopBtn_onClick), false);
|
||||
this.$$("CREOFBtn").addEventListener("click",
|
||||
B5500CentralControl.bindMethod(this, B5500CardReader.prototype.CREOFBtn_onclick), false);
|
||||
B5500CentralControl.bindMethod(this, B5500CardReader.prototype.CREOFBtn_onClick), false);
|
||||
this.hopperBar.addEventListener("click",
|
||||
B5500CentralControl.bindMethod(this, B5500CardReader.prototype.CRHopperBar_onclick), false);
|
||||
B5500CentralControl.bindMethod(this, B5500CardReader.prototype.CRHopperBar_onClick), false);
|
||||
|
||||
this.window.resizeBy(de.scrollWidth - this.window.innerWidth + 4, // kludge for right-padding/margin
|
||||
de.scrollHeight - this.window.innerHeight);
|
||||
|
||||
@@ -8,151 +8,74 @@
|
||||
************************************************************************
|
||||
* 2012-12-14 P.Kimpel
|
||||
* Original version, from B5500DistributionAndDisplay.css.
|
||||
* 2015-01-24 P.Kimpel
|
||||
* Strip down to new, minimal home page sans console panel.
|
||||
***********************************************************************/
|
||||
|
||||
#ConsoleDiv {
|
||||
BODY {
|
||||
font-family: DejaVuSansWeb, sans-serif;
|
||||
font-size: 10pt;
|
||||
background-color: white;
|
||||
color: black;
|
||||
height: 100%;
|
||||
margin: 4px;
|
||||
padding: 4px}
|
||||
|
||||
H1 {
|
||||
margin-top: 1em;
|
||||
margin-bottom: 0.5em;
|
||||
font-size: 14pt;
|
||||
font-weight: bold}
|
||||
|
||||
#VersionDiv {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 1125px;
|
||||
height: 136px;
|
||||
border-radius: 16px;
|
||||
margin: 4px}
|
||||
|
||||
#StatusLabel {
|
||||
position: absolute;
|
||||
left: 32px;
|
||||
top: 8px;
|
||||
font-size: 7pt}
|
||||
|
||||
#ConfigLabel {
|
||||
position: absolute;
|
||||
display: none;
|
||||
right: 32px;
|
||||
top: 8px;
|
||||
font-size: 7pt}
|
||||
|
||||
#BurroughsLogo {
|
||||
position: absolute;
|
||||
background-color: black;
|
||||
top: 32px;
|
||||
right: 32px;
|
||||
border-top: 3px solid #EEE;
|
||||
border-bottom: 3px solid #EEE}
|
||||
|
||||
#B5500Logo {
|
||||
background-color: #EEE;
|
||||
color: #333333;
|
||||
font-size: 6pt;
|
||||
position: absolute;
|
||||
top: 72px;
|
||||
right: 32px;
|
||||
z-index: 15}
|
||||
|
||||
#B5500LogoImage {
|
||||
margin-left: 2px;
|
||||
margin-right: 2px;
|
||||
margin-bottom: 2px;
|
||||
width: 64px;
|
||||
vertical-align: bottom;
|
||||
display: none}
|
||||
|
||||
#RetroLogoImage {
|
||||
vertical-align: bottom;
|
||||
margin: 4px}
|
||||
|
||||
#RetroVersion {
|
||||
position: absolute;
|
||||
top: 80px;
|
||||
right: 170px;
|
||||
font-size: 7pt}
|
||||
|
||||
#BurroughsLogoImage {
|
||||
width: 150px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
padding-top: 3px;
|
||||
padding-bottom: 3px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px}
|
||||
|
||||
#HaltBtn {
|
||||
position: absolute;
|
||||
top: 31px;
|
||||
left: 32px}
|
||||
|
||||
#NotReadyBtn {
|
||||
position: absolute;
|
||||
top: 31px;
|
||||
left: 132px}
|
||||
|
||||
#MemoryCheckBtn {
|
||||
position: absolute;
|
||||
top: 31px;
|
||||
left: 202px}
|
||||
|
||||
#LoadBtn {
|
||||
position: absolute;
|
||||
top: 31px;
|
||||
left: 272px}
|
||||
|
||||
#LoadSelectBtn {
|
||||
position: absolute;
|
||||
line-height: 100%;
|
||||
top: 31px;
|
||||
left: 372px}
|
||||
|
||||
#ANormalBtn {
|
||||
position: absolute;
|
||||
top: 31px;
|
||||
left: 442px}
|
||||
|
||||
#AControlBtn {
|
||||
position: absolute;
|
||||
top: 31px;
|
||||
left: 512px}
|
||||
|
||||
#BNormalBtn {
|
||||
position: absolute;
|
||||
top: 31px;
|
||||
left: 582px}
|
||||
|
||||
#BControlBtn {
|
||||
position: absolute;
|
||||
top: 31px;
|
||||
left: 652px}
|
||||
|
||||
#PowerOnBtn {
|
||||
position: absolute;
|
||||
top: 31px;
|
||||
left: 752px}
|
||||
|
||||
#PowerOffBtn {
|
||||
position: absolute;
|
||||
top: 31px;
|
||||
left: 822px}
|
||||
|
||||
#CentralControl {
|
||||
position: absolute;
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
display: none;
|
||||
left: 32px;
|
||||
right: 32px;
|
||||
bottom: 8px}
|
||||
|
||||
#CentralControl TD {
|
||||
padding-left: 1px;
|
||||
padding-right: 1px;
|
||||
vertical-align: bottom}
|
||||
|
||||
COL.AnnunciatorCol {
|
||||
width: 32px}
|
||||
|
||||
#procDelay, TD#procSlack {
|
||||
visibility: visible;
|
||||
width: 60px;
|
||||
top: 4px;
|
||||
right: 4px;
|
||||
text-align: right}
|
||||
TD.statLabel {
|
||||
visibility: visible;
|
||||
text-align: left}
|
||||
#StatusMsg {
|
||||
text-align: center;
|
||||
font-size: 85%;
|
||||
color: blue}
|
||||
#InfoTable {
|
||||
margin-top: 0;
|
||||
width: 100%}
|
||||
#CenteredBody {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
top: 25%;
|
||||
bottom: 25%;
|
||||
left: 0;
|
||||
right: 0}
|
||||
#B5500Image {
|
||||
box-shadow: 12px 12px 12px gray;
|
||||
height: 80%}
|
||||
#StartUpPoweredBtn,
|
||||
#StartUpNoPowerBtn {
|
||||
margin-top: 2em;
|
||||
background-color: #246;
|
||||
color: white;
|
||||
font-family: DejaVuSansWeb, sans-serif;
|
||||
font-weight: normal;
|
||||
font-size: 12pt;
|
||||
width: auto;
|
||||
height: auto;
|
||||
padding: 0.5em;
|
||||
border-radius: 12px;
|
||||
border: 2px solid #999}
|
||||
#StartUpPoweredBtn[disabled],
|
||||
#StartUpNoPowerBtn[disabled] {
|
||||
background-color: #468;
|
||||
color: #999;
|
||||
border-color: #666}
|
||||
#CallbackTable {
|
||||
position: absolute;
|
||||
top: 1ex;
|
||||
visibility: hidden;
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0}
|
||||
#PageFooter {
|
||||
position: absolute;
|
||||
font-size: 75%;
|
||||
bottom: 4px;
|
||||
text-align: center;
|
||||
width: 100%}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<html manifest="B5500Manifest.appcache">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>retro-B5500 Emulator Operator Console</title>
|
||||
<title>retro-B5500 Emulator</title>
|
||||
<!--
|
||||
/***********************************************************************
|
||||
* retro-b5500/emulator B5500Console.html
|
||||
@@ -20,6 +20,8 @@
|
||||
* Original version, from thin air and a PowerPoint mockup.
|
||||
* 2014-07-20 P.Kimpel
|
||||
* Split off Javascript code into a separate script.
|
||||
* 2015-01-24 P.Kimpel
|
||||
* Strip down to new, minimal home page sans console panel.
|
||||
***********************************************************************/
|
||||
-->
|
||||
<meta name="Author" content="Nigel Williams & Paul Kimpel">
|
||||
@@ -48,115 +50,46 @@
|
||||
<script src="../emulator/B5500Processor.js"></script>
|
||||
<script src="../emulator/B5500IOUnit.js"></script>
|
||||
|
||||
<script src="./B5500ConsolePanel.js"></script>
|
||||
<script src="./B5500Console.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id=VersionDiv>
|
||||
<img id=RetroB5500Logo src="./resources/retro-B5500-Logo.png" alt="retro-B5500 Logo">
|
||||
<div id=EmulatorVersion></div>
|
||||
</div>
|
||||
<h1>Burroughs B5500 Emulator</h1>
|
||||
<hr>
|
||||
<table id=InfoTable>
|
||||
<tr>
|
||||
<td><a href="https://code.google.com/p/retro-b5500/" target="_blank">
|
||||
Open-Source Project</a>
|
||||
<td id=StatusMsg>
|
||||
<td class=rj><a href="http://retro-b5500.blogspot.com/" target="_blank">
|
||||
Project Blog</a>
|
||||
<tr>
|
||||
<td><a href="http://code.google.com/p/retro-b5500/wiki/WebUIGettingStarted" target="_blank">
|
||||
Getting Started Wiki</a>
|
||||
<td>
|
||||
<td class=rj><a href="http://www.phkimpel.us/B5500/" target="_blank">
|
||||
Resources</a>
|
||||
</table>
|
||||
|
||||
<div id=ConsoleDiv class=devicePanel>
|
||||
<button id=HaltBtn class="redButton" DISABLED>HALT</button>
|
||||
|
||||
<button id=NotReadyBtn class=whiteButton>NOT<br>READY</button>
|
||||
<button id=MemoryCheckBtn class=redButton DISABLED>MEMORY<br>CHECK</button>
|
||||
<button id=LoadBtn class="blackButton blackLit" DISABLED>LOAD</button>
|
||||
|
||||
<button id=LoadSelectBtn class="yellowButton" DISABLED>CARD<br>LOAD<br>SELECT</button>
|
||||
<button id=ANormalBtn class=yellowButton>A<br>NORMAL</button>
|
||||
<button id=AControlBtn class=yellowButton>A<br>CONTROL</button>
|
||||
<button id=BNormalBtn class=yellowButton>B<br>NORMAL</button>
|
||||
<button id=BControlBtn class=yellowButton>B<br>CONTROL</button>
|
||||
|
||||
<button id=PowerOnBtn class=greenButton>POWER<br>ON</button>
|
||||
<button id=PowerOffBtn class="blackButton blackLit" DISABLED>POWER<br>OFF</button>
|
||||
|
||||
<div id=StatusLabel></div>
|
||||
<div id=ConfigLabel>
|
||||
Using <span id=SysConfigName class=data>(none)</span>+<span id=StorageName class=data>(none)</span>
|
||||
</div>
|
||||
|
||||
<div id=BurroughsLogo>
|
||||
<img id=BurroughsLogoImage src="./resources/Burroughs-Logo-Neg.jpg" alt="Burroughs logo"
|
||||
title="Click to toggle display of the white annunciator lights">
|
||||
</div>
|
||||
<div id=RetroVersion title="retro-B5500 emulator version">
|
||||
?.??
|
||||
</div>
|
||||
<div id=B5500Logo title="Click to open the System Configuration dialog">
|
||||
<img id=RetroLogoImage src="./resources/retro-B5500-Logo.png" alt="retro-B5500 logo">
|
||||
<img id=B5500LogoImage src="./resources/B5500Logo.jpg" alt="B5500 original logo">
|
||||
</div>
|
||||
|
||||
<table id=CentralControl>
|
||||
<colgroup>
|
||||
<col span=31 class=AnnunciatorCol>
|
||||
<col span=3>
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr id=CCInterruptRow>
|
||||
<td id=AD1F class=annunciator title="I/O Unit 1 busy">IOU1
|
||||
<td id=AD2F class=annunciator title="I/O Unit 2 busy">IOU2
|
||||
<td id=AD3F class=annunciator title="I/O Unit 3 busy">IOU3
|
||||
<td id=AD4F class=annunciator title="I/O Unit 4 busy">IOU4
|
||||
<td id=CCI03F class=annunciator title="Interval Timer interrupt">TIMR
|
||||
<td id=CCI04F class=annunciator title="I/O Busy interrupt">IOBZ
|
||||
<td id=CCI05F class=annunciator title="Keyboard Request interrupt">KBD
|
||||
<td id=CCI06F class=annunciator title="Printer 1 Finished interrupt">PR1F
|
||||
<td id=CCI07F class=annunciator title="Printer 2 Finished interrupt">PR2F
|
||||
<td id=CCI08F class=annunciator title="I/O Unit 1 Finished interrupt (RD in @14)">IO1F
|
||||
<td id=CCI09F class=annunciator title="I/O Unit 2 Finished interrupt (RD in @15)">IO2F
|
||||
<td id=CCI10F class=annunciator title="I/O Unit 3 Finished interrupt (RD in @16)">IO3F
|
||||
<td id=CCI11F class=annunciator title="I/O Unit 4 Finished interrupt (RD in @17)">IO4F
|
||||
<td id=CCI12F class=annunciator title="P2 Busy interrupt">P2BZ
|
||||
<td id=CCI13F class=annunciator title="Remote Inquiry Request interrupt">INQ
|
||||
<td id=CCI14F class=annunciator title="Special Interrupt #1 (not used)">SPEC
|
||||
<td id=CCI15F class=annunciator title="Disk File #1 Read check finished">DK1F
|
||||
<td id=CCI16F class=annunciator title="Disk File #2 Read check finished">DK2F
|
||||
<td colspan=9>
|
||||
<td id=P2BF class=annunciator title="Processor 2 Busy FF">P2BF
|
||||
<td id=HP2F class=annunciator title="Halt Processor 2 FF">HP2F
|
||||
<td colspan=2>
|
||||
<td id=procSlack class=annunciator>
|
||||
<td class="annunciator statLabel">%
|
||||
<td class="annunciator statLabel" title="Percentage of time Processor A is throttling its performance">P1 Slack
|
||||
<tr id=CCPeripheralRow>
|
||||
<td id=DRA class=annunciator title="Drum A">DRA <!-- Unit 31 -->
|
||||
<td id=DRB class=annunciator title="Drum B">DRB <!-- Unit 30 -->
|
||||
<td id=DKA class=annunciator title="Disk File Control A">DKA <!-- Unit 29 -->
|
||||
<td id=DKB class=annunciator title="Disk File Control B">DKB <!-- Unit 28 -->
|
||||
<td id=SPO class=annunciator title="Supervisory Printer/Keyboard">SPO <!-- Unit 22 -->
|
||||
<td id=CPA class=annunciator title="Card Punch A">CPA <!-- Unit 25 -->
|
||||
<td id=CRA class=annunciator title="Card Reader A">CRA <!-- Unit 24 -->
|
||||
<td id=CRB class=annunciator title="Card Reader B">CRB <!-- Unit 23 -->
|
||||
<td id=LPA class=annunciator title="Line Printer A">LPA <!-- Unit 27 -->
|
||||
<td id=LPB class=annunciator title="Line Printer B">LPB <!-- Unit 26 -->
|
||||
<td id=DCA class=annunciator title="Datacommunications Control A">DCA <!-- Unit 17 -->
|
||||
<td id=PRA class=annunciator title="Paper Tape Reader A">PRA <!-- Unit 20 -->
|
||||
<td id=PRB class=annunciator title="Paper Tape Reader B">PRB <!-- Unit 19 -->
|
||||
<td id=PPA class=annunciator title="Paper Tape Punch A">PPA <!-- Unit 21 -->
|
||||
<td id=PPB class=annunciator title="Paper Tape Punch B">PPB <!-- Unit 18 -->
|
||||
<td id=MTA class=annunciator title="Magnetic Tape Drive A">MTA <!-- Unit 47 -->
|
||||
<td id=MTB class=annunciator title="Magnetic Tape Drive B">MTB <!-- Unit 46 -->
|
||||
<td id=MTC class=annunciator title="Magnetic Tape Drive C">MTC <!-- Unit 45 -->
|
||||
<td id=MTD class=annunciator title="Magnetic Tape Drive D">MTD <!-- Unit 44 -->
|
||||
<td id=MTE class=annunciator title="Magnetic Tape Drive E">MTE <!-- Unit 43 -->
|
||||
<td id=MTF class=annunciator title="Magnetic Tape Drive F">MTF <!-- Unit 42 -->
|
||||
<td id=MTH class=annunciator title="Magnetic Tape Drive H">MTH <!-- Unit 41 -->
|
||||
<td id=MTJ class=annunciator title="Magnetic Tape Drive J">MTJ <!-- Unit 40 -->
|
||||
<td id=MTK class=annunciator title="Magnetic Tape Drive K">MTK <!-- Unit 39 -->
|
||||
<td id=MTL class=annunciator title="Magnetic Tape Drive L">MTL <!-- Unit 38 -->
|
||||
<td id=MTM class=annunciator title="Magnetic Tape Drive M">MTM <!-- Unit 37 -->
|
||||
<td id=MTN class=annunciator title="Magnetic Tape Drive N">MTN <!-- Unit 36 -->
|
||||
<td id=MTP class=annunciator title="Magnetic Tape Drive P">MTP <!-- Unit 35 -->
|
||||
<td id=MTR class=annunciator title="Magnetic Tape Drive R">MTR <!-- Unit 34 -->
|
||||
<td id=MTS class=annunciator title="Magnetic Tape Drive S">MTS <!-- Unit 33 -->
|
||||
<td id=MTT class=annunciator title="Magnetic Tape Drive T">MTT <!-- Unit 32 -->
|
||||
<td id=procDelay class=annunciator>
|
||||
<td class="annunciator statLabel">ms
|
||||
<td class="annunciator statLabel" title="Average excess throttling delay for Processor A (ms)">P1 Delay
|
||||
</table>
|
||||
<div id=CenteredBody>
|
||||
<img id=B5500Image src="./resources/Burroughs-B5500-102646215-05-01-06.jpg"
|
||||
alt="Burroughs B5500 System, ca. 1966">
|
||||
<br>
|
||||
<button id=StartUpPoweredBtn title="Start the emulator and automatically power it on">
|
||||
Start & Power On
|
||||
</button>
|
||||
|
||||
<button id=StartUpNoPowerBtn title="Start the emulator in a power-off state">
|
||||
Start – Powered Off
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<table cellspacing=0 cellpadding=1 border=1 style="position:absolute; top:2in; visibility:hidden">
|
||||
<table id=CallbackTable>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID
|
||||
@@ -168,5 +101,9 @@
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div id=PageFooter>
|
||||
<i>(Note: Closing or minimizing this window may cause the emulator to run very slowly)</i>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -17,683 +17,111 @@
|
||||
"use strict";
|
||||
|
||||
window.addEventListener("load", function() {
|
||||
var aControl; // A-Control button/light
|
||||
var aNormal; // A-Normal button/light
|
||||
var bControl; // B-Control button/light
|
||||
var bNormal; // B-Normal button/light
|
||||
var cc; // B5500CentralControl object
|
||||
var ccLatches = [0, 0, 0]; // I/O- & interrupt-reporting latches
|
||||
var ccLightsMap = new Array(6); // Misc annunciator DOM objects
|
||||
var intLightsMap = new Array(48); // Interrupt annunciator DOM objects
|
||||
var lastInterruptMask = 0; // Prior mask of interrupt annunciator lights
|
||||
var lastCCMask = 0; // Prior mask of misc annunciator lights
|
||||
var lastUnitBusyMask = 0; // Prior mask of unit-busy annunciator lights
|
||||
var lastPANormalRate = -1; // Prior PA normal-state busy rate
|
||||
var lastPAControlRate = -1; // Prior PA control-state busy rate
|
||||
var lastPBNormalRate = -1; // Prior PB normal-state busy rate
|
||||
var lastPBControlRate = -1; // Prior PB normal-state busy rate
|
||||
var perf = performance; // (it's faster if locally cached)
|
||||
var perLightsMap = new Array(48); // Peripheral I/O annunciator DOM objects
|
||||
var procDelay; // Current average P1 delay [ms]
|
||||
var procSlack; // Current average P1 slack time [%]
|
||||
var showAnnunciators = true; // Display non-purist console mode (annunciators)
|
||||
var timer = 0; // Console display update timer control cookie
|
||||
var timerInterval = 50; // Console display update interval [ms]
|
||||
var consolePanel = null; // the ConsolePanel object
|
||||
var statusMsgTimer = 0; // status message timer control token
|
||||
|
||||
function $$(id) {
|
||||
return document.getElementById(id);
|
||||
/**************************************/
|
||||
function systemShutDown() {
|
||||
/* Re-enables the startup buttons on the home page */
|
||||
|
||||
consolePanel = null;
|
||||
document.getElementById("StartUpPoweredBtn").disabled = false;
|
||||
document.getElementById("StartUpNoPowerBtn").disabled = false;
|
||||
window.focus();
|
||||
}
|
||||
|
||||
function setAnnunciators(showEm) {
|
||||
$$("CentralControl").style.display = (showEm && cc.poweredUp ? "block" : "none");
|
||||
$$("RetroVersion").style.visibility = (showEm ? "visible" : "hidden");
|
||||
$$("RetroLogoImage").style.display = (showEm ? "inline" : "none");
|
||||
$$("B5500LogoImage").style.display = (showEm ? "none" : "inline");
|
||||
$$("ConfigLabel").style.display = (showEm ? "inline" : "none");
|
||||
/**************************************/
|
||||
function systemStartup(ev) {
|
||||
/* Establishes the system components */
|
||||
var powerUp = (ev.target.id == "StartUpPoweredBtn" ? 1 : 0);
|
||||
|
||||
consolePanel = new B5500ConsolePanel(window, powerUp, systemShutDown);
|
||||
document.getElementById("StartUpPoweredBtn").disabled = true;
|
||||
document.getElementById("StartUpNoPowerBtn").disabled = true;
|
||||
}
|
||||
|
||||
function evaluateNotReady(config) {
|
||||
/* Evaluates the system configuration to determine whether the
|
||||
NOT READY lamp should be illuminated */
|
||||
var lampClass = "whiteButton";
|
||||
/**************************************/
|
||||
function clearStatusMsg(inSeconds) {
|
||||
/* Delays for "inSeconds" seconds, then clears the StatusMsg element */
|
||||
|
||||
switch (false) {
|
||||
case config.PA.enabled || config.PA.enabled:
|
||||
case (config.PA.enabled && !config.PB1L) || (config.PB.enabled && config.PB1L):
|
||||
case config.IO1.enabled || config.IO2.enabled || config.IO3.enabled || config.IO4.enabled:
|
||||
case config.memMod[0].enabled:
|
||||
case config.units.SPO.enabled:
|
||||
case config.units.DKA.enabled:
|
||||
lampClass += " whiteLit";
|
||||
if (statusMsgTimer) {
|
||||
clearTimeout(statusMsgTimer);
|
||||
}
|
||||
|
||||
$$("NotReadyBtn").className = lampClass;
|
||||
}
|
||||
|
||||
function BurroughsLogo_Click(ev) {
|
||||
showAnnunciators = !showAnnunciators;
|
||||
setAnnunciators(showAnnunciators);
|
||||
}
|
||||
|
||||
function B5500Logo_Click(ev) {
|
||||
var sysConfig = new B5500SystemConfig();
|
||||
|
||||
if (cc.poweredUp) {
|
||||
alert("System configuration changes are\nnot allowed while power is on.");
|
||||
} else {
|
||||
$$("ConfigLabel").style.display = "none";
|
||||
sysConfig.openConfigUI();
|
||||
}
|
||||
}
|
||||
|
||||
function PowerOnBtn_Click(ev) {
|
||||
var sysConfig = new B5500SystemConfig();
|
||||
|
||||
function applyPower(config) {
|
||||
$$("HaltBtn").className = "redButton redLit";
|
||||
$$("PowerOnBtn").disabled = true;
|
||||
$$("PowerOffBtn").disabled = false;
|
||||
$$("LoadSelectBtn").disabled = false;
|
||||
$$("LoadBtn").disabled = false;
|
||||
$$("HaltBtn").disabled = true;
|
||||
$$("MemoryCheckBtn").disabled = false;
|
||||
cc.powerOn(config);
|
||||
$$("LoadSelectBtn").className = "yellowButton" + (cc.cardLoadSelect ? " yellowLit" : "");
|
||||
evaluateNotReady(config);
|
||||
setAnnunciators(showAnnunciators);
|
||||
}
|
||||
|
||||
function youMayPowerOnWhenReady_Gridley(config) {
|
||||
/* Called-back by sysConfig.getSystemConfig with the requested configuration */
|
||||
|
||||
if (!config) {
|
||||
alert("No System Configuration found\nCANNOT POWER ON.");
|
||||
} else {
|
||||
$$("PowerOnBtn").className = "greenButton greenLit";
|
||||
$$("SysConfigName").textContent = config.configName;
|
||||
$$("StorageName").textContent = config.units.DKA.storageName;
|
||||
if (showAnnunciators) {
|
||||
lampTest(applyPower, config);
|
||||
} else {
|
||||
applyPower(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sysConfig.getSystemConfig(null, youMayPowerOnWhenReady_Gridley); // get current system config
|
||||
return true;
|
||||
}
|
||||
|
||||
function PowerOffBtn_Click(ev) {
|
||||
$$("PowerOnBtn").className = "greenButton";
|
||||
$$("ANormalBtn").className = "yellowButton";
|
||||
$$("AControlBtn").className = "yellowButton";
|
||||
$$("BNormalBtn").className = "yellowButton";
|
||||
$$("BControlBtn").className = "yellowButton";
|
||||
$$("LoadSelectBtn").className = "yellowButton";
|
||||
$$("MemoryCheckBtn").className = "redButton";
|
||||
$$("NotReadyBtn").className = "whiteButton";
|
||||
$$("HaltBtn").className = "redButton";
|
||||
cc.powerOff();
|
||||
$$("PowerOnBtn").disabled = false;
|
||||
$$("PowerOffBtn").disabled = true;
|
||||
$$("LoadSelectBtn").disabled = true;
|
||||
$$("LoadBtn").disabled = true;
|
||||
$$("HaltBtn").disabled = true;
|
||||
$$("MemoryCheckBtn").disabled = true;
|
||||
$$("CentralControl").style.display = "none";
|
||||
if (timer) {
|
||||
clearInterval(timer);
|
||||
timer = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function HaltBtn_Click(ev) {
|
||||
$$("HaltBtn").className = "redButton redLit";
|
||||
cc.halt();
|
||||
$$("HaltBtn").disabled = true;
|
||||
$$("LoadBtn").disabled = false;
|
||||
dasBlinkenlicht();
|
||||
if (timer) {
|
||||
clearInterval(timer);
|
||||
timer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function LoadBtn_Click(ev) {
|
||||
var result;
|
||||
|
||||
window.open("", "SPO").focus(); // re-focus the SPO window
|
||||
result = cc.load(false);
|
||||
switch (result) {
|
||||
case 0: // load initiated successfully
|
||||
$$("HaltBtn").className = "redButton";
|
||||
$$("HaltBtn").disabled = false;
|
||||
$$("LoadBtn").disabled = true;
|
||||
timer = setInterval(dasBlinkenlicht, timerInterval);
|
||||
break;
|
||||
case 1:
|
||||
alert("P1 busy or not available");
|
||||
break;
|
||||
case 2:
|
||||
alert("SPO is not ready");
|
||||
break;
|
||||
case 3:
|
||||
alert("SPO is busy");
|
||||
break;
|
||||
case 4:
|
||||
alert("DKA is not ready");
|
||||
break;
|
||||
case 5:
|
||||
alert("DKA is busy");
|
||||
break;
|
||||
default:
|
||||
alert("cc.load() result = " + result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function LoadSelectBtn_Click(ev) {
|
||||
if (cc.cardLoadSelect) {
|
||||
cc.cardLoadSelect = 0;
|
||||
$$("LoadSelectBtn").className = "yellowButton";
|
||||
} else {
|
||||
cc.cardLoadSelect = 1;
|
||||
$$("LoadSelectBtn").className = "yellowButton yellowLit";
|
||||
}
|
||||
}
|
||||
|
||||
function dumpState(caption) {
|
||||
/* Generates a dump of the processor states and all of memory */
|
||||
var doc;
|
||||
var lastPhase = -2;
|
||||
var win = window.open("", "", "location=no,resizable,scrollbars,status");
|
||||
var x;
|
||||
|
||||
var htmlMatch = /[<>&"]/g; // regular expression for escaping HTML text
|
||||
|
||||
function htmlFilter(c) {
|
||||
/* Used to escape HTML-sensitive characters in a string */
|
||||
switch (c) {
|
||||
case "&":
|
||||
return "&";
|
||||
case "<":
|
||||
return "<";
|
||||
case ">":
|
||||
return ">";
|
||||
case "\"":
|
||||
return """;
|
||||
default:
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
function escapeHTML(text) {
|
||||
/* Returns "text" as escaped HTML */
|
||||
|
||||
return text.replace(htmlMatch, htmlFilter);
|
||||
}
|
||||
|
||||
function writer(phase, text) {
|
||||
/* Call-back function for cc.dumpSystemState */
|
||||
|
||||
switch (phase) {
|
||||
case 0:
|
||||
lastPhase = phase;
|
||||
doc.writeln(escapeHTML(text));
|
||||
doc.writeln("User Agent: " + navigator.userAgent);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case 2:
|
||||
if (phase == lastPhase) {
|
||||
doc.writeln(escapeHTML(text));
|
||||
} else {
|
||||
lastPhase = phase;
|
||||
doc.writeln();
|
||||
doc.writeln(escapeHTML(text));
|
||||
doc.writeln();
|
||||
}
|
||||
break;
|
||||
|
||||
case 32:
|
||||
if (phase != lastPhase) {
|
||||
lastPhase = phase;
|
||||
doc.writeln();
|
||||
}
|
||||
doc.writeln();
|
||||
doc.writeln(escapeHTML(text));
|
||||
break;
|
||||
|
||||
case -1:
|
||||
break;
|
||||
} // switch
|
||||
}
|
||||
|
||||
doc = win.document;
|
||||
doc.open();
|
||||
doc.writeln("<html><head><title>retro-B5500 Console State Dump</title>");
|
||||
doc.writeln("</head><body>");
|
||||
doc.write("<pre>");
|
||||
|
||||
cc.dumpSystemState(caption, writer);
|
||||
|
||||
doc.writeln("</pre></body></html>")
|
||||
doc.close();
|
||||
win.focus();
|
||||
}
|
||||
|
||||
function displayCallbacks() {
|
||||
/* Builds a table of outstanding callbacks */
|
||||
var cb;
|
||||
var cbs = clearCallback(0);
|
||||
var cookie;
|
||||
var e;
|
||||
var body = document.createElement("tbody");
|
||||
var oldBody = $$("CallbackBody");
|
||||
var row;
|
||||
|
||||
for (cookie in cbs) {
|
||||
cb = cbs[cookie];
|
||||
row = document.createElement("tr");
|
||||
|
||||
e = document.createElement("td");
|
||||
e.appendChild(document.createTextNode(cookie.toString()));
|
||||
row.appendChild(e);
|
||||
|
||||
e = document.createElement("td");
|
||||
e.appendChild(document.createTextNode(cb.delay.toFixed(2)));
|
||||
row.appendChild(e);
|
||||
|
||||
e = document.createElement("td");
|
||||
e.appendChild(document.createTextNode(cb.context.mnemonic || "??"));
|
||||
row.appendChild(e);
|
||||
|
||||
e = document.createElement("td");
|
||||
e.appendChild(document.createTextNode((cb.args ? cb.args.length : 0).toString()));
|
||||
row.appendChild(e);
|
||||
body.appendChild(row);
|
||||
}
|
||||
|
||||
body.id = oldBody.id;
|
||||
oldBody.parentNode.replaceChild(body, oldBody);
|
||||
}
|
||||
|
||||
function displayCentralControl() {
|
||||
/* Displays the I/O and interrupt status in CentralControl */
|
||||
var cells;
|
||||
var s;
|
||||
var interruptMask;
|
||||
var interruptChange;
|
||||
var ccMask;
|
||||
var ccChange;
|
||||
var unitBusyMask;
|
||||
var unitBusyChange;
|
||||
var x;
|
||||
|
||||
cc.fetchCCLatches(ccLatches);
|
||||
ccMask = ccLatches[0];
|
||||
ccChange = lastCCMask ^ ccMask;
|
||||
lastCCMask = ccMask;
|
||||
|
||||
interruptMask = ccLatches[1] % 0x4000;
|
||||
interruptChange = lastInterruptMask ^ interruptMask;
|
||||
lastInterruptMask = interruptMask;
|
||||
|
||||
unitBusyMask = ccLatches[2];
|
||||
unitBusyChange = lastUnitBusyMask ^ unitBusyMask;
|
||||
lastUnitBusyMask = unitBusyMask;
|
||||
|
||||
x = 0;
|
||||
while (ccChange) {
|
||||
if (ccChange & 0x01) {
|
||||
if (ccLightsMap[x]) {
|
||||
ccLightsMap[x].style.visibility = (ccMask & 0x01 ? "visible" : "hidden");
|
||||
}
|
||||
}
|
||||
ccMask >>>= 1;
|
||||
ccChange >>>= 1;
|
||||
x++;
|
||||
}
|
||||
|
||||
x = 47;
|
||||
while (interruptChange) {
|
||||
if (interruptChange & 0x01) {
|
||||
if (intLightsMap[x]) {
|
||||
intLightsMap[x].style.visibility = (interruptMask & 0x01 ? "visible" : "hidden");
|
||||
}
|
||||
}
|
||||
interruptMask >>>= 1;
|
||||
interruptChange >>>= 1;
|
||||
x--;
|
||||
}
|
||||
|
||||
x = 47;
|
||||
while (unitBusyChange) {
|
||||
if (unitBusyChange & 0x01) {
|
||||
if (perLightsMap[x]) {
|
||||
perLightsMap[x].style.visibility = (unitBusyMask & 0x01 ? "visible" : "hidden");
|
||||
}
|
||||
}
|
||||
unitBusyMask >>>= 1;
|
||||
unitBusyChange >>>= 1;
|
||||
x--;
|
||||
}
|
||||
}
|
||||
|
||||
function dasBlinkenlicht() {
|
||||
var cycles;
|
||||
var pa = cc.PA;
|
||||
var pb = cc.PB;
|
||||
var p1 = cc.P1;
|
||||
var stateRate;
|
||||
|
||||
cycles = p1.normalCycles+p1.controlCycles;
|
||||
|
||||
if (pa) {
|
||||
if (pa.normalCycles+pa.controlCycles <= 0) {
|
||||
if (lastPAControlRate != -1) {
|
||||
lastPAControlRate = -1;
|
||||
aControl.className = "yellowButton";
|
||||
aNormal.className = "yellowButton";
|
||||
}
|
||||
} else {
|
||||
stateRate = Math.round(pa.normalCycles/cycles*6 + 0.25);
|
||||
if (stateRate != lastPANormalRate) {
|
||||
lastPANormalRate = stateRate;
|
||||
switch (stateRate) {
|
||||
case 0:
|
||||
aNormal.className = "yellowButton";
|
||||
break;
|
||||
case 1:
|
||||
//aNormal.className = "yellowButton yellowLit1";
|
||||
//break;
|
||||
case 2:
|
||||
aNormal.className = "yellowButton yellowLit2";
|
||||
break;
|
||||
case 3:
|
||||
//aNormal.className = "yellowButton yellowLit3";
|
||||
//break;
|
||||
case 4:
|
||||
aNormal.className = "yellowButton yellowLit4";
|
||||
break;
|
||||
case 5:
|
||||
//aNormal.className = "yellowButton yellowLit5";
|
||||
//break;
|
||||
default:
|
||||
aNormal.className = "yellowButton yellowLit";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
stateRate = Math.round(pa.controlCycles/cycles*6 + 0.25);
|
||||
if (stateRate != lastPAControlRate) {
|
||||
lastPAControlRate = stateRate;
|
||||
switch (stateRate) {
|
||||
case 0:
|
||||
aControl.className = "yellowButton";
|
||||
break;
|
||||
case 1:
|
||||
//aControl.className = "yellowButton yellowLit1";
|
||||
//break;
|
||||
case 2:
|
||||
aControl.className = "yellowButton yellowLit2";
|
||||
break;
|
||||
case 3:
|
||||
//aControl.className = "yellowButton yellowLit3";
|
||||
//break;
|
||||
case 4:
|
||||
aControl.className = "yellowButton yellowLit4";
|
||||
break;
|
||||
case 5:
|
||||
//aControl.className = "yellowButton yellowLit5";
|
||||
//break;
|
||||
default:
|
||||
aControl.className = "yellowButton yellowLit";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pa.controlCycles = pa.normalCycles = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (pb) {
|
||||
if (pb.normalCycles+pb.controlCycles <= 0) {
|
||||
if (lastPBControlRate != -1) {
|
||||
bControl.className = "yellowButton";
|
||||
bNormal.className = "yellowButton";
|
||||
lastPBControlRate = -1;
|
||||
}
|
||||
} else {
|
||||
stateRate = Math.round(pb.normalCycles/cycles*6 + 0.25);
|
||||
if (stateRate != lastPBNormalRate) {
|
||||
lastPBNormalRate = stateRate;
|
||||
switch (stateRate) {
|
||||
case 0:
|
||||
bNormal.className = "yellowButton";
|
||||
break;
|
||||
case 1:
|
||||
//bNormal.className = "yellowButton yellowLit1";
|
||||
//break;
|
||||
case 2:
|
||||
bNormal.className = "yellowButton yellowLit2";
|
||||
break;
|
||||
case 3:
|
||||
//bNormal.className = "yellowButton yellowLit3";
|
||||
//break;
|
||||
case 4:
|
||||
bNormal.className = "yellowButton yellowLit4";
|
||||
break;
|
||||
case 5:
|
||||
//bNormal.className = "yellowButton yellowLit5";
|
||||
//break;
|
||||
default:
|
||||
bNormal.className = "yellowButton yellowLit";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
stateRate = Math.round(pb.controlCycles/cycles*6 + 0.25);
|
||||
if (stateRate != lastPBControlRate) {
|
||||
lastPBControlRate = stateRate;
|
||||
switch (stateRate) {
|
||||
case 0:
|
||||
bControl.className = "yellowButton";
|
||||
break;
|
||||
case 1:
|
||||
//bControl.className = "yellowButton yellowLit1";
|
||||
//break;
|
||||
case 2:
|
||||
bControl.className = "yellowButton yellowLit2";
|
||||
break;
|
||||
case 3:
|
||||
//bControl.className = "yellowButton yellowLit3";
|
||||
//break;
|
||||
case 4:
|
||||
bControl.className = "yellowButton yellowLit4";
|
||||
break;
|
||||
case 5:
|
||||
//bControl.className = "yellowButton yellowLit5";
|
||||
//break;
|
||||
default:
|
||||
bControl.className = "yellowButton yellowLit";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pb.controlCycles = pb.normalCycles = 0;
|
||||
}
|
||||
}
|
||||
|
||||
procDelay.innerHTML = p1.delayDeltaAvg.toFixed(1);
|
||||
procSlack.innerHTML = (p1.procSlackAvg/p1.procRunAvg*100).toFixed(1);
|
||||
|
||||
if (showAnnunciators) {
|
||||
displayCentralControl();
|
||||
}
|
||||
// displayCallbacks();
|
||||
}
|
||||
|
||||
function buildLightMaps() {
|
||||
/* Builds tables of the DOM entries for the annunciator lights, for efficient access */
|
||||
var mnem;
|
||||
var spec;
|
||||
var x;
|
||||
|
||||
ccLightsMap[0] = $$("AD1F");
|
||||
ccLightsMap[1] = $$("AD2F");
|
||||
ccLightsMap[2] = $$("AD3F");
|
||||
ccLightsMap[3] = $$("AD4F");
|
||||
ccLightsMap[4] = $$("P2BF");
|
||||
ccLightsMap[5] = $$("HP2F");
|
||||
|
||||
for (x=3; x<=16; x++) {
|
||||
intLightsMap[50-x] = $$("CCI" + (x+100).toString().substring(1) + "F");
|
||||
}
|
||||
|
||||
for (mnem in B5500CentralControl.unitSpecs) {
|
||||
spec = B5500CentralControl.unitSpecs[mnem];
|
||||
perLightsMap[spec.unitIndex] = $$(mnem);
|
||||
}
|
||||
}
|
||||
|
||||
function lampTest(callback, callbackParam) {
|
||||
/* Lights up the operator console, waits a bit, then turns everything
|
||||
off and calls the "callback" function, passing "callbackParam".
|
||||
The Power On lamp is not affected */
|
||||
|
||||
function switchEm(mode) {
|
||||
var visibility = (mode ? "visible" : "hidden");
|
||||
var x;
|
||||
|
||||
$$("ANormalBtn").className = "yellowButton" + (mode ? " yellowLit" : "");
|
||||
$$("AControlBtn").className = "yellowButton" + (mode ? " yellowLit" : "");
|
||||
$$("BNormalBtn").className = "yellowButton" + (mode ? " yellowLit" : "");
|
||||
$$("BControlBtn").className = "yellowButton" + (mode ? " yellowLit" : "");
|
||||
$$("LoadSelectBtn").className = "yellowButton" + (mode ? " yellowLit" : "");
|
||||
$$("MemoryCheckBtn").className = "redButton" + (mode ? " redLit" : "");
|
||||
$$("NotReadyBtn").className = "whiteButton" + (mode ? " whiteLit" : "");
|
||||
$$("HaltBtn").className = "redButton" + (mode ? " redLit" : "");
|
||||
|
||||
for (x in ccLightsMap) {
|
||||
if (ccLightsMap[x]) {
|
||||
ccLightsMap[x].style.visibility = visibility;
|
||||
}
|
||||
}
|
||||
|
||||
for (x in intLightsMap) {
|
||||
if (intLightsMap[x]) {
|
||||
intLightsMap[x].style.visibility = visibility;
|
||||
}
|
||||
}
|
||||
|
||||
for (x in perLightsMap) {
|
||||
if (perLightsMap[x]) {
|
||||
perLightsMap[x].style.visibility = visibility;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mode) {
|
||||
setAnnunciators(showAnnunciators);
|
||||
setTimeout(callback, 1000, callbackParam);
|
||||
}
|
||||
}
|
||||
|
||||
setAnnunciators(true);
|
||||
$$("CentralControl").style.display = "block"; // overrides if !cc.poweredUp
|
||||
switchEm(1);
|
||||
setTimeout(switchEm, 2000, 0);
|
||||
}
|
||||
|
||||
function clearStatus(inSeconds) {
|
||||
/* Delays for "inSeconds" seconds, then clears the StatusLabel element */
|
||||
|
||||
setTimeout(function(ev) {
|
||||
$$("StatusLabel").textContent = "";
|
||||
statusMsgTimer = setTimeout(function(ev) {
|
||||
document.getElementById("StatusMsg").textContent = "";
|
||||
statusMsgTimer = 0;
|
||||
}, inSeconds*1000);
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function checkBrowser() {
|
||||
/* Checks whether this browser can support the necessary stuff */
|
||||
var missing = "";
|
||||
|
||||
if (!window.indexedDB) {missing += ", IndexedDB"}
|
||||
if (!window.ArrayBuffer) {missing += ", ArrayBuffer"}
|
||||
if (!window.DataView) {missing += ", DataView"}
|
||||
if (!window.Blob) {missing += ", Blob"}
|
||||
if (!window.File) {missing += ", File"}
|
||||
if (!window.FileReader) {missing += ", FileReader"}
|
||||
if (!window.FileList) {missing += ", FileList"}
|
||||
if (!window.indexedDB) {missing += ", IndexedDB"}
|
||||
if (!window.postMessage) {missing += ", window.postMessage"}
|
||||
if (!(window.performance && "now" in performance)) {missing += ", performance.now"}
|
||||
|
||||
if (missing.length == 0) {
|
||||
return false;
|
||||
} else {
|
||||
alert("No can do... your browser does not support the following features:\n" +
|
||||
missing.substring(2));
|
||||
return true;
|
||||
} else {
|
||||
alert("The emulator cannot run...\n" +
|
||||
"your browser does not support the following features:\n\n" +
|
||||
missing.substring(2));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/***** window.onload() outer block *****/
|
||||
|
||||
$$("RetroVersion").innerHTML = B5500CentralControl.version;
|
||||
if (!checkBrowser()) {
|
||||
window.name = "B5500Console";
|
||||
$$("BurroughsLogo").addEventListener("click", BurroughsLogo_Click, false);
|
||||
$$("B5500Logo").addEventListener("click", B5500Logo_Click, false);
|
||||
$$("PowerOnBtn").addEventListener("click", PowerOnBtn_Click, false);
|
||||
$$("PowerOffBtn").addEventListener("click", PowerOffBtn_Click, false);
|
||||
$$("HaltBtn").addEventListener("click", HaltBtn_Click, false);
|
||||
$$("LoadBtn").addEventListener("click", LoadBtn_Click, false);
|
||||
$$("LoadSelectBtn").addEventListener("click", LoadSelectBtn_Click, false);
|
||||
$$("MemoryCheckBtn").addEventListener("click", function(ev) {
|
||||
dumpState("Memory-Check Button");
|
||||
}, false);
|
||||
document.getElementById("StartUpPoweredBtn").disabled = true;
|
||||
document.getElementById("StartUpNoPowerBtn").disabled = true;
|
||||
document.getElementById("EmulatorVersion").textContent = B5500CentralControl.version;
|
||||
if (checkBrowser()) {
|
||||
document.getElementById("StartUpPoweredBtn").disabled = false;
|
||||
document.getElementById("StartUpPoweredBtn").addEventListener("click", systemStartup);
|
||||
document.getElementById("StartUpNoPowerBtn").disabled = false;
|
||||
document.getElementById("StartUpNoPowerBtn").addEventListener("click", systemStartup);
|
||||
|
||||
window.applicationCache.addEventListener("checking", function(ev) {
|
||||
$$("StatusLabel").textContent = "Checking for emulator update...";
|
||||
}, false);
|
||||
document.getElementById("StatusMsg").textContent = "Checking for emulator update...";
|
||||
clearStatusMsg(15);
|
||||
});
|
||||
window.applicationCache.addEventListener("noupdate", function(ev) {
|
||||
$$("StatusLabel").textContent = "Emulator version is current.";
|
||||
clearStatus(5);
|
||||
}, false);
|
||||
document.getElementById("StatusMsg").textContent = "Emulator version is current.";
|
||||
clearStatusMsg(15);
|
||||
});
|
||||
window.applicationCache.addEventListener("obsolete", function(ev) {
|
||||
$$("StatusLabel").textContent = "Emulator off-line installation has been disabled.";
|
||||
clearStatus(15);
|
||||
}, false);
|
||||
document.getElementById("StatusMsg").textContent = "Emulator off-line installation has been disabled.";
|
||||
clearStatusMsg(15);
|
||||
});
|
||||
window.applicationCache.addEventListener("downloading", function(ev) {
|
||||
$$("StatusLabel").textContent = "Initiating download for emulator update...";
|
||||
}, false);
|
||||
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");
|
||||
$$("StatusLabel").textContent = text + " resources downloaded thus far...";
|
||||
}, false);
|
||||
document.getElementById("StatusMsg").textContent = text + " resources downloaded thus far...";
|
||||
clearStatusMsg(15);
|
||||
});
|
||||
window.applicationCache.addEventListener("updateready", function(ev) {
|
||||
$$("StatusLabel").textContent = "Emulator update completed. Reload this page to activate the new version.";
|
||||
clearStatus(10);
|
||||
}, false);
|
||||
document.getElementById("StatusMsg").textContent = "Emulator update completed. Reload this page to activate the new version.";
|
||||
clearStatusMsg(15);
|
||||
});
|
||||
window.applicationCache.addEventListener("cached", function(ev) {
|
||||
$$("StatusLabel").textContent = "Emulator is now installed for off-line use.";
|
||||
clearStatus(10);
|
||||
}, false);
|
||||
document.getElementById("StatusMsg").textContent = "Emulator is now installed for off-line use.";
|
||||
clearStatusMsg(15);
|
||||
});
|
||||
window.applicationCache.addEventListener("error", function(ev) {
|
||||
$$("StatusLabel").textContent = "Unable to check for emulator update.";
|
||||
clearStatus(10);
|
||||
}, false);
|
||||
|
||||
aControl = $$("AControlBtn");
|
||||
aNormal = $$("ANormalBtn");
|
||||
bControl = $$("BControlBtn");
|
||||
bNormal = $$("BNormalBtn");
|
||||
procDelay = $$("procDelay");
|
||||
procSlack = $$("procSlack");
|
||||
buildLightMaps();
|
||||
|
||||
cc = new B5500CentralControl(window);
|
||||
window.dumpState = dumpState;
|
||||
document.getElementById("StatusMsg").textContent = "Browser reported error during emulator version check.";
|
||||
clearStatusMsg(15);
|
||||
});
|
||||
}
|
||||
}, false);
|
||||
});
|
||||
|
||||
162
webUI/B5500ConsolePanel.css
Normal file
162
webUI/B5500ConsolePanel.css
Normal file
@@ -0,0 +1,162 @@
|
||||
/***********************************************************************
|
||||
* retro-b5500/emulator B5500ConsolePanel.css
|
||||
************************************************************************
|
||||
* Copyright (c) 2015, Nigel Williams and Paul Kimpel.
|
||||
* Licensed under the MIT License, see
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
************************************************************************
|
||||
* B5500 emulator Operator Console Panel web interface style sheet.
|
||||
************************************************************************
|
||||
* 2015-01-24 P.Kimpel
|
||||
* Original version, split off from B5500Console.css.
|
||||
***********************************************************************/
|
||||
|
||||
HTML {
|
||||
height: auto}
|
||||
|
||||
#ConsoleDiv {
|
||||
position: relative;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 1125px;
|
||||
height: 136px;
|
||||
border-radius: 16px;
|
||||
margin: 0}
|
||||
|
||||
#StatusLabel {
|
||||
position: absolute;
|
||||
left: 32px;
|
||||
top: 8px;
|
||||
font-size: 7pt}
|
||||
|
||||
#ConfigLabel {
|
||||
position: absolute;
|
||||
display: none;
|
||||
right: 32px;
|
||||
top: 8px;
|
||||
font-size: 7pt}
|
||||
|
||||
#BurroughsLogo {
|
||||
position: absolute;
|
||||
background-color: black;
|
||||
top: 32px;
|
||||
right: 32px;
|
||||
border-top: 3px solid #EEE;
|
||||
border-bottom: 3px solid #EEE}
|
||||
|
||||
#B5500Logo {
|
||||
background-color: #EEE;
|
||||
color: #333333;
|
||||
font-size: 6pt;
|
||||
position: absolute;
|
||||
top: 72px;
|
||||
right: 32px;
|
||||
z-index: 15}
|
||||
|
||||
#B5500LogoImage {
|
||||
margin-left: 2px;
|
||||
margin-right: 2px;
|
||||
margin-bottom: 2px;
|
||||
width: 64px;
|
||||
vertical-align: bottom;
|
||||
display: none}
|
||||
|
||||
#RetroLogoImage {
|
||||
vertical-align: bottom;
|
||||
margin: 4px}
|
||||
|
||||
#RetroVersion {
|
||||
position: absolute;
|
||||
top: 80px;
|
||||
right: 170px;
|
||||
font-size: 7pt}
|
||||
|
||||
#BurroughsLogoImage {
|
||||
width: 150px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
padding-top: 3px;
|
||||
padding-bottom: 3px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px}
|
||||
|
||||
#HaltBtn {
|
||||
position: absolute;
|
||||
top: 31px;
|
||||
left: 32px}
|
||||
|
||||
#NotReadyBtn {
|
||||
position: absolute;
|
||||
top: 31px;
|
||||
left: 132px}
|
||||
|
||||
#MemoryCheckBtn {
|
||||
position: absolute;
|
||||
top: 31px;
|
||||
left: 202px}
|
||||
|
||||
#LoadBtn {
|
||||
position: absolute;
|
||||
top: 31px;
|
||||
left: 272px}
|
||||
|
||||
#LoadSelectBtn {
|
||||
position: absolute;
|
||||
line-height: 100%;
|
||||
top: 31px;
|
||||
left: 372px}
|
||||
|
||||
#ANormalBtn {
|
||||
position: absolute;
|
||||
top: 31px;
|
||||
left: 442px}
|
||||
|
||||
#AControlBtn {
|
||||
position: absolute;
|
||||
top: 31px;
|
||||
left: 512px}
|
||||
|
||||
#BNormalBtn {
|
||||
position: absolute;
|
||||
top: 31px;
|
||||
left: 582px}
|
||||
|
||||
#BControlBtn {
|
||||
position: absolute;
|
||||
top: 31px;
|
||||
left: 652px}
|
||||
|
||||
#PowerOnBtn {
|
||||
position: absolute;
|
||||
top: 31px;
|
||||
left: 752px}
|
||||
|
||||
#PowerOffBtn {
|
||||
position: absolute;
|
||||
top: 31px;
|
||||
left: 822px}
|
||||
|
||||
#CentralControl {
|
||||
position: absolute;
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
display: none;
|
||||
left: 32px;
|
||||
right: 32px;
|
||||
bottom: 8px}
|
||||
|
||||
#CentralControl TD {
|
||||
padding-left: 1px;
|
||||
padding-right: 1px;
|
||||
vertical-align: bottom}
|
||||
|
||||
COL.AnnunciatorCol {
|
||||
width: 32px}
|
||||
|
||||
#procDelay, TD#procSlack {
|
||||
visibility: visible;
|
||||
width: 60px;
|
||||
text-align: right}
|
||||
TD.statLabel {
|
||||
visibility: visible;
|
||||
text-align: left}
|
||||
135
webUI/B5500ConsolePanel.html
Normal file
135
webUI/B5500ConsolePanel.html
Normal file
@@ -0,0 +1,135 @@
|
||||
<!DOCTYPE html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>retro-B5500 Emulator Operator Console</title>
|
||||
<!--
|
||||
/***********************************************************************
|
||||
* retro-b5500/emulator B5500ConsolePanel.html
|
||||
************************************************************************
|
||||
* Copyright (c) 2015, Nigel Williams and Paul Kimpel.
|
||||
* Licensed under the MIT License, see
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
************************************************************************
|
||||
* B5500 Operator Console Panel page.
|
||||
*
|
||||
* Implements the B5500 emulator operations console display.
|
||||
*
|
||||
************************************************************************
|
||||
* 2015-01-24 P.Kimpel
|
||||
* Original version, split off from B5500Console.html.
|
||||
***********************************************************************/
|
||||
-->
|
||||
<meta name="Author" content="Nigel Williams & Paul Kimpel">
|
||||
<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="B5500Common.css">
|
||||
<link id=consoleStyleSheet rel=stylesheet type="text/css" href="B5500ConsolePanel.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id=ConsoleDiv class=devicePanel>
|
||||
<button id=HaltBtn class="redButton" DISABLED>HALT</button>
|
||||
|
||||
<button id=NotReadyBtn class=whiteButton>NOT<br>READY</button>
|
||||
<button id=MemoryCheckBtn class=redButton DISABLED>MEMORY<br>CHECK</button>
|
||||
<button id=LoadBtn class="blackButton blackLit" DISABLED>LOAD</button>
|
||||
|
||||
<button id=LoadSelectBtn class="yellowButton" DISABLED>CARD<br>LOAD<br>SELECT</button>
|
||||
<button id=ANormalBtn class=yellowButton>A<br>NORMAL</button>
|
||||
<button id=AControlBtn class=yellowButton>A<br>CONTROL</button>
|
||||
<button id=BNormalBtn class=yellowButton>B<br>NORMAL</button>
|
||||
<button id=BControlBtn class=yellowButton>B<br>CONTROL</button>
|
||||
|
||||
<button id=PowerOnBtn class=greenButton>POWER<br>ON</button>
|
||||
<button id=PowerOffBtn class="blackButton blackLit" DISABLED>POWER<br>OFF</button>
|
||||
|
||||
<div id=StatusLabel></div>
|
||||
<div id=ConfigLabel>
|
||||
Using <span id=SysConfigName class=data>(none)</span>+<span id=StorageName class=data>(none)</span>
|
||||
</div>
|
||||
|
||||
<div id=BurroughsLogo>
|
||||
<img id=BurroughsLogoImage src="./resources/Burroughs-Logo-Neg.jpg" alt="Burroughs logo"
|
||||
title="Click to toggle display of the white annunciator lights">
|
||||
</div>
|
||||
<div id=RetroVersion title="retro-B5500 emulator version">
|
||||
?.??
|
||||
</div>
|
||||
<div id=B5500Logo title="Click to open the System Configuration dialog">
|
||||
<img id=RetroLogoImage src="./resources/retro-B5500-Logo.png" alt="retro-B5500 logo">
|
||||
<img id=B5500LogoImage src="./resources/B5500Logo.jpg" alt="B5500 original logo">
|
||||
</div>
|
||||
|
||||
<table id=CentralControl>
|
||||
<colgroup>
|
||||
<col span=31 class=AnnunciatorCol>
|
||||
<col span=3>
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr id=CCInterruptRow>
|
||||
<td id=AD1F class=annunciator title="I/O Unit 1 busy">IOU1
|
||||
<td id=AD2F class=annunciator title="I/O Unit 2 busy">IOU2
|
||||
<td id=AD3F class=annunciator title="I/O Unit 3 busy">IOU3
|
||||
<td id=AD4F class=annunciator title="I/O Unit 4 busy">IOU4
|
||||
<td id=CCI03F class=annunciator title="Interval Timer interrupt">TIMR
|
||||
<td id=CCI04F class=annunciator title="I/O Busy interrupt">IOBZ
|
||||
<td id=CCI05F class=annunciator title="Keyboard Request interrupt">KBD
|
||||
<td id=CCI06F class=annunciator title="Printer 1 Finished interrupt">PR1F
|
||||
<td id=CCI07F class=annunciator title="Printer 2 Finished interrupt">PR2F
|
||||
<td id=CCI08F class=annunciator title="I/O Unit 1 Finished interrupt (RD in @14)">IO1F
|
||||
<td id=CCI09F class=annunciator title="I/O Unit 2 Finished interrupt (RD in @15)">IO2F
|
||||
<td id=CCI10F class=annunciator title="I/O Unit 3 Finished interrupt (RD in @16)">IO3F
|
||||
<td id=CCI11F class=annunciator title="I/O Unit 4 Finished interrupt (RD in @17)">IO4F
|
||||
<td id=CCI12F class=annunciator title="P2 Busy interrupt">P2BZ
|
||||
<td id=CCI13F class=annunciator title="Remote Inquiry Request interrupt">INQ
|
||||
<td id=CCI14F class=annunciator title="Special Interrupt #1 (not used)">SPEC
|
||||
<td id=CCI15F class=annunciator title="Disk File #1 Read check finished">DK1F
|
||||
<td id=CCI16F class=annunciator title="Disk File #2 Read check finished">DK2F
|
||||
<td colspan=9>
|
||||
<td id=P2BF class=annunciator title="Processor 2 Busy FF">P2BF
|
||||
<td id=HP2F class=annunciator title="Halt Processor 2 FF">HP2F
|
||||
<td colspan=2>
|
||||
<td id=procSlack class=annunciator>
|
||||
<td class="annunciator statLabel">%
|
||||
<td class="annunciator statLabel" title="Percentage of time Processor A is throttling its performance">P1 Slack
|
||||
<tr id=CCPeripheralRow>
|
||||
<td id=DRA class=annunciator title="Drum A">DRA <!-- Unit 31 -->
|
||||
<td id=DRB class=annunciator title="Drum B">DRB <!-- Unit 30 -->
|
||||
<td id=DKA class=annunciator title="Disk File Control A">DKA <!-- Unit 29 -->
|
||||
<td id=DKB class=annunciator title="Disk File Control B">DKB <!-- Unit 28 -->
|
||||
<td id=SPO class=annunciator title="Supervisory Printer/Keyboard">SPO <!-- Unit 22 -->
|
||||
<td id=CPA class=annunciator title="Card Punch A">CPA <!-- Unit 25 -->
|
||||
<td id=CRA class=annunciator title="Card Reader A">CRA <!-- Unit 24 -->
|
||||
<td id=CRB class=annunciator title="Card Reader B">CRB <!-- Unit 23 -->
|
||||
<td id=LPA class=annunciator title="Line Printer A">LPA <!-- Unit 27 -->
|
||||
<td id=LPB class=annunciator title="Line Printer B">LPB <!-- Unit 26 -->
|
||||
<td id=DCA class=annunciator title="Datacommunications Control A">DCA <!-- Unit 17 -->
|
||||
<td id=PRA class=annunciator title="Paper Tape Reader A">PRA <!-- Unit 20 -->
|
||||
<td id=PRB class=annunciator title="Paper Tape Reader B">PRB <!-- Unit 19 -->
|
||||
<td id=PPA class=annunciator title="Paper Tape Punch A">PPA <!-- Unit 21 -->
|
||||
<td id=PPB class=annunciator title="Paper Tape Punch B">PPB <!-- Unit 18 -->
|
||||
<td id=MTA class=annunciator title="Magnetic Tape Drive A">MTA <!-- Unit 47 -->
|
||||
<td id=MTB class=annunciator title="Magnetic Tape Drive B">MTB <!-- Unit 46 -->
|
||||
<td id=MTC class=annunciator title="Magnetic Tape Drive C">MTC <!-- Unit 45 -->
|
||||
<td id=MTD class=annunciator title="Magnetic Tape Drive D">MTD <!-- Unit 44 -->
|
||||
<td id=MTE class=annunciator title="Magnetic Tape Drive E">MTE <!-- Unit 43 -->
|
||||
<td id=MTF class=annunciator title="Magnetic Tape Drive F">MTF <!-- Unit 42 -->
|
||||
<td id=MTH class=annunciator title="Magnetic Tape Drive H">MTH <!-- Unit 41 -->
|
||||
<td id=MTJ class=annunciator title="Magnetic Tape Drive J">MTJ <!-- Unit 40 -->
|
||||
<td id=MTK class=annunciator title="Magnetic Tape Drive K">MTK <!-- Unit 39 -->
|
||||
<td id=MTL class=annunciator title="Magnetic Tape Drive L">MTL <!-- Unit 38 -->
|
||||
<td id=MTM class=annunciator title="Magnetic Tape Drive M">MTM <!-- Unit 37 -->
|
||||
<td id=MTN class=annunciator title="Magnetic Tape Drive N">MTN <!-- Unit 36 -->
|
||||
<td id=MTP class=annunciator title="Magnetic Tape Drive P">MTP <!-- Unit 35 -->
|
||||
<td id=MTR class=annunciator title="Magnetic Tape Drive R">MTR <!-- Unit 34 -->
|
||||
<td id=MTS class=annunciator title="Magnetic Tape Drive S">MTS <!-- Unit 33 -->
|
||||
<td id=MTT class=annunciator title="Magnetic Tape Drive T">MTT <!-- Unit 32 -->
|
||||
<td id=procDelay class=annunciator>
|
||||
<td class="annunciator statLabel">ms
|
||||
<td class="annunciator statLabel" title="Average excess throttling delay for Processor A (ms)">P1 Delay
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
780
webUI/B5500ConsolePanel.js
Normal file
780
webUI/B5500ConsolePanel.js
Normal file
@@ -0,0 +1,780 @@
|
||||
/***********************************************************************
|
||||
* retro-b5500/emulator B5500ConsolePanel.js
|
||||
************************************************************************
|
||||
* Copyright (c) 2015, Nigel Williams and Paul Kimpel.
|
||||
* Licensed under the MIT License, see
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
************************************************************************
|
||||
* B5500 Operations Console Panel Javascript module.
|
||||
*
|
||||
* Implements event handlers and control functions for the B5500 emulator
|
||||
* operations console.
|
||||
*
|
||||
************************************************************************
|
||||
* 2015-01-24 P.Kimpel
|
||||
* Original version, split off from B5500Console.js.
|
||||
***********************************************************************/
|
||||
"use strict";
|
||||
|
||||
/**************************************/
|
||||
function B5500ConsolePanel(global, autoPowerUp, shutDown) {
|
||||
/* Constructor for the Console Panel object. "global" must be the
|
||||
global window object; "autoPowerUp" indicates whether the system should
|
||||
be powered on automatically; "shutDown" is a function to be called back
|
||||
when the window closes */
|
||||
var height = 144;
|
||||
var width = 1133;
|
||||
var left = screen.availWidth - width;
|
||||
|
||||
this.autoPowerUp = autoPowerUp; // Automatically power on during onload event
|
||||
this.aControl; // A-Control button/light
|
||||
this.aNormal; // A-Normal button/light
|
||||
this.bControl; // B-Control button/light
|
||||
this.bNormal; // B-Normal button/light
|
||||
this.cc; // B5500CentralControl object
|
||||
this.ccLatches = [0, 0, 0]; // I/O- & interrupt-reporting latches
|
||||
this.ccLightsMap = new Array(6); // Misc annunciator DOM objects
|
||||
this.global = global; // Global window object
|
||||
this.intLightsMap = new Array(48); // Interrupt annunciator DOM objects
|
||||
this.lastInterruptMask = 0; // Prior mask of interrupt annunciator lights
|
||||
this.lastCCMask = 0; // Prior mask of misc annunciator lights
|
||||
this.lastUnitBusyMask = 0; // Prior mask of unit-busy annunciator lights
|
||||
this.lastPANormalRate = -1; // Prior PA normal-state busy rate
|
||||
this.lastPAControlRate = -1; // Prior PA control-state busy rate
|
||||
this.lastPBNormalRate = -1; // Prior PB normal-state busy rate
|
||||
this.lastPBControlRate = -1; // Prior PB normal-state busy rate
|
||||
this.perf = performance; // (it's faster if locally cached)
|
||||
this.perLightsMap = new Array(48); // Peripheral I/O annunciator DOM objects
|
||||
this.procDelay; // Current average P1 delay [ms]
|
||||
this.procSlack; // Current average P1 slack time [%]
|
||||
this.showAnnunciators = true; // Display non-purist console mode (annunciators)
|
||||
this.shutDown = shutDown; // Function to be called back when the panel closes
|
||||
this.statusLabelTimer = 0; // Status label display timer control token
|
||||
this.timer = 0; // Console display update timer control token
|
||||
this.timerInterval = 50; // Console display update interval [ms]
|
||||
|
||||
this.window = window.open("", "B5500Console");
|
||||
if (this.window) {
|
||||
this.window.close();
|
||||
this.window = null;
|
||||
}
|
||||
|
||||
this.doc = null;
|
||||
this.window = window.open("../webUI/B5500ConsolePanel.html", "B5500Console",
|
||||
"location=no,scrollbars=no,resizable,top=0,left=" + left +
|
||||
",width=" + width + ",height=" + height);
|
||||
this.window.addEventListener("load",
|
||||
B5500CentralControl.bindMethod(this, B5500ConsolePanel.prototype.consoleOnload));
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
B5500ConsolePanel.prototype.$$ = function $$(id) {
|
||||
return this.doc.getElementById(id);
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
B5500ConsolePanel.prototype.setAnnunciators = function setAnnunciators(showEm) {
|
||||
/* Sets the visibility of the annunciators based on "showEm" */
|
||||
|
||||
this.$$("CentralControl").style.display = (showEm && this.cc.poweredUp ? "block" : "none");
|
||||
this.$$("RetroVersion").style.visibility = (showEm ? "visible" : "hidden");
|
||||
this.$$("RetroLogoImage").style.display = (showEm ? "inline" : "none");
|
||||
this.$$("B5500LogoImage").style.display = (showEm ? "none" : "inline");
|
||||
this.$$("ConfigLabel").style.display = (showEm ? "inline" : "none");
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
B5500ConsolePanel.prototype.evaluateNotReady = function evaluateNotReady(config) {
|
||||
/* Evaluates the system configuration to determine whether the
|
||||
NOT READY lamp should be illuminated */
|
||||
var lampClass = "whiteButton";
|
||||
|
||||
switch (false) {
|
||||
case config.PA.enabled || config.PA.enabled:
|
||||
case (config.PA.enabled && !config.PB1L) || (config.PB.enabled && config.PB1L):
|
||||
case config.IO1.enabled || config.IO2.enabled || config.IO3.enabled || config.IO4.enabled:
|
||||
case config.memMod[0].enabled:
|
||||
case config.units.SPO.enabled:
|
||||
case config.units.DKA.enabled:
|
||||
lampClass += " whiteLit";
|
||||
}
|
||||
|
||||
this.$$("NotReadyBtn").className = lampClass;
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
B5500ConsolePanel.prototype.BurroughsLogo_Click = function BurroughsLogo_Click(ev) {
|
||||
/* Toggles the annunciator display state on the panel */
|
||||
|
||||
this.showAnnunciators = !this.showAnnunciators;
|
||||
this.setAnnunciators(this.showAnnunciators);
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
B5500ConsolePanel.prototype.B5500Logo_Click = function B5500Logo_Click(ev) {
|
||||
/* Opens the configuration window if the system is powered off */
|
||||
var sysConfig = new B5500SystemConfig();
|
||||
|
||||
if (this.cc.poweredUp) {
|
||||
this.$$("StatusLabel").textContent = "System configuration changes are not allowed while power is on.";
|
||||
this.clearStatusLabel(15);
|
||||
} else {
|
||||
this.$$("ConfigLabel").style.display = "none";
|
||||
sysConfig.openConfigUI();
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
B5500ConsolePanel.prototype.PowerOnBtn_Click = function PowerOnBtn_Click(ev) {
|
||||
/* Powers on the system */
|
||||
var sysConfig = new B5500SystemConfig();
|
||||
var that = this;
|
||||
|
||||
function applyPower(config) {
|
||||
that.$$("HaltBtn").className = "redButton redLit";
|
||||
that.$$("PowerOnBtn").disabled = true;
|
||||
that.$$("PowerOffBtn").disabled = false;
|
||||
that.$$("LoadSelectBtn").disabled = false;
|
||||
that.$$("LoadBtn").disabled = false;
|
||||
that.$$("HaltBtn").disabled = true;
|
||||
that.$$("MemoryCheckBtn").disabled = false;
|
||||
that.cc.powerOn(config);
|
||||
that.$$("LoadSelectBtn").className = "yellowButton" + (that.cc.cardLoadSelect ? " yellowLit" : "");
|
||||
that.evaluateNotReady(config);
|
||||
that.setAnnunciators(that.showAnnunciators);
|
||||
that.window.addEventListener("beforeunload", that.beforeUnload);
|
||||
}
|
||||
|
||||
function youMayPowerOnWhenReady_Gridley(config) {
|
||||
/* Called-back by sysConfig.getSystemConfig with the requested configuration */
|
||||
|
||||
if (!config) {
|
||||
that.window.alert("No System Configuration found\nCANNOT POWER ON.");
|
||||
} else {
|
||||
that.$$("PowerOnBtn").className = "greenButton greenLit";
|
||||
that.$$("SysConfigName").textContent = config.configName;
|
||||
that.$$("StorageName").textContent = config.units.DKA.storageName;
|
||||
if (that.showAnnunciators) {
|
||||
that.lampTest(B5500CentralControl.bindMethod(that, applyPower), config);
|
||||
} else {
|
||||
applyPower(config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sysConfig.getSystemConfig(null, youMayPowerOnWhenReady_Gridley); // get current system config
|
||||
return true;
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
B5500ConsolePanel.prototype.PowerOffBtn_Click = function PowerOffBtn_Click(ev) {
|
||||
/* Powers off the system, halting it first if necessary */
|
||||
|
||||
this.$$("PowerOnBtn").className = "greenButton";
|
||||
this.$$("ANormalBtn").className = "yellowButton";
|
||||
this.$$("AControlBtn").className = "yellowButton";
|
||||
this.$$("BNormalBtn").className = "yellowButton";
|
||||
this.$$("BControlBtn").className = "yellowButton";
|
||||
this.$$("LoadSelectBtn").className = "yellowButton";
|
||||
this.$$("MemoryCheckBtn").className = "redButton";
|
||||
this.$$("NotReadyBtn").className = "whiteButton";
|
||||
this.$$("HaltBtn").className = "redButton";
|
||||
this.cc.powerOff();
|
||||
this.$$("PowerOnBtn").disabled = false;
|
||||
this.$$("PowerOffBtn").disabled = true;
|
||||
this.$$("LoadSelectBtn").disabled = true;
|
||||
this.$$("LoadBtn").disabled = true;
|
||||
this.$$("HaltBtn").disabled = true;
|
||||
this.$$("MemoryCheckBtn").disabled = true;
|
||||
this.$$("CentralControl").style.display = "none";
|
||||
this.window.removeEventListener("beforeunload", this.beforeUnload);
|
||||
if (this.timer) {
|
||||
clearInterval(this.timer);
|
||||
this.timer = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
B5500ConsolePanel.prototype.HaltBtn_Click = function HaltBtn_Click(ev) {
|
||||
/* Halts the system */
|
||||
|
||||
this.$$("HaltBtn").className = "redButton redLit";
|
||||
this.cc.halt();
|
||||
this.$$("HaltBtn").disabled = true;
|
||||
this.$$("LoadBtn").disabled = false;
|
||||
this.dasBlinkenlichten();
|
||||
if (this.timer) {
|
||||
clearInterval(this.timer);
|
||||
this.timer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
B5500ConsolePanel.prototype.LoadBtn_Click = function LoadBtn_Click(ev) {
|
||||
/* Initiates a program load for the system */
|
||||
var result;
|
||||
|
||||
window.open("", "SPO").focus(); // re-focus the SPO window
|
||||
result = this.cc.load(false);
|
||||
switch (result) {
|
||||
case 0: // load initiated successfully
|
||||
this.$$("HaltBtn").className = "redButton";
|
||||
this.$$("HaltBtn").disabled = false;
|
||||
this.$$("LoadBtn").disabled = true;
|
||||
this.timer = setInterval(
|
||||
B5500CentralControl.bindMethod(this, B5500ConsolePanel.prototype.dasBlinkenlichten),
|
||||
this.timerInterval);
|
||||
break;
|
||||
case 1:
|
||||
this.window.alert("P1 busy or not available");
|
||||
break;
|
||||
case 2:
|
||||
this.window.alert("SPO is not ready");
|
||||
break;
|
||||
case 3:
|
||||
this.window.alert("SPO is busy");
|
||||
break;
|
||||
case 4:
|
||||
this.window.alert("DKA is not ready");
|
||||
break;
|
||||
case 5:
|
||||
this.window.alert("DKA is busy");
|
||||
break;
|
||||
default:
|
||||
this.window.alert("cc.load() result = " + result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
B5500ConsolePanel.prototype.LoadSelectBtn_Click = function LoadSelectBtn_Click(ev) {
|
||||
/* Toggles the Card Load Select button state */
|
||||
|
||||
if (this.cc.cardLoadSelect) {
|
||||
this.cc.cardLoadSelect = 0;
|
||||
this.$$("LoadSelectBtn").className = "yellowButton";
|
||||
} else {
|
||||
this.cc.cardLoadSelect = 1;
|
||||
this.$$("LoadSelectBtn").className = "yellowButton yellowLit";
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
B5500ConsolePanel.prototype.dumpState = function dumpState(caption) {
|
||||
/* Generates a dump of the processor states and all of memory */
|
||||
var doc;
|
||||
var lastPhase = -2;
|
||||
var win = window.open("", "", "location=no,resizable,scrollbars,status");
|
||||
var x;
|
||||
|
||||
var htmlMatch = /[<>&"]/g; // regular expression for escaping HTML text
|
||||
|
||||
function htmlFilter(c) {
|
||||
/* Used to escape HTML-sensitive characters in a string */
|
||||
switch (c) {
|
||||
case "&":
|
||||
return "&";
|
||||
case "<":
|
||||
return "<";
|
||||
case ">":
|
||||
return ">";
|
||||
case "\"":
|
||||
return """;
|
||||
default:
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
function escapeHTML(text) {
|
||||
/* Returns "text" as escaped HTML */
|
||||
|
||||
return text.replace(htmlMatch, htmlFilter);
|
||||
}
|
||||
|
||||
function writer(phase, text) {
|
||||
/* Call-back function for cc.dumpSystemState */
|
||||
|
||||
switch (phase) {
|
||||
case 0:
|
||||
lastPhase = phase;
|
||||
doc.writeln(escapeHTML(text));
|
||||
doc.writeln("User Agent: " + navigator.userAgent);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case 2:
|
||||
if (phase == lastPhase) {
|
||||
doc.writeln(escapeHTML(text));
|
||||
} else {
|
||||
lastPhase = phase;
|
||||
doc.writeln();
|
||||
doc.writeln(escapeHTML(text));
|
||||
doc.writeln();
|
||||
}
|
||||
break;
|
||||
|
||||
case 32:
|
||||
if (phase != lastPhase) {
|
||||
lastPhase = phase;
|
||||
doc.writeln();
|
||||
}
|
||||
doc.writeln();
|
||||
doc.writeln(escapeHTML(text));
|
||||
break;
|
||||
|
||||
case -1:
|
||||
break;
|
||||
} // switch
|
||||
}
|
||||
|
||||
doc = win.document;
|
||||
doc.open();
|
||||
doc.writeln("<html><head><title>retro-B5500 Console State Dump</title>");
|
||||
doc.writeln("</head><body>");
|
||||
doc.write("<pre>");
|
||||
|
||||
this.cc.dumpSystemState(caption, writer);
|
||||
|
||||
doc.writeln("</pre></body></html>")
|
||||
doc.close();
|
||||
win.focus();
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
B5500ConsolePanel.prototype.displayCallbackState = function displayCallbackState() {
|
||||
/* Builds a table of outstanding callback state */
|
||||
var cb;
|
||||
var cbs;
|
||||
var e;
|
||||
var body = document.createElement("tbody");
|
||||
var oldBody = document.getElementById("CallbackBody");
|
||||
var row;
|
||||
var state = getCallbackState(0x03);
|
||||
var token;
|
||||
|
||||
cbs = state.delayDev;
|
||||
for (token in cbs) {
|
||||
row = document.createElement("tr");
|
||||
|
||||
e = document.createElement("td");
|
||||
e.appendChild(document.createTextNode(token));
|
||||
row.appendChild(e);
|
||||
|
||||
e = document.createElement("td");
|
||||
e.appendChild(document.createTextNode((cbs[token]||0).toFixed(2)));
|
||||
row.appendChild(e);
|
||||
|
||||
e = document.createElement("td");
|
||||
e.colSpan = 2;
|
||||
row.appendChild(e);
|
||||
body.appendChild(row);
|
||||
}
|
||||
|
||||
cbs = state.pendingCallbacks;
|
||||
for (token in cbs) {
|
||||
cb = cbs[token];
|
||||
row = document.createElement("tr");
|
||||
|
||||
e = document.createElement("td");
|
||||
e.appendChild(document.createTextNode(token.toString()));
|
||||
row.appendChild(e);
|
||||
|
||||
e = document.createElement("td");
|
||||
e.appendChild(document.createTextNode(cb.delay.toFixed(2)));
|
||||
row.appendChild(e);
|
||||
|
||||
e = document.createElement("td");
|
||||
e.appendChild(document.createTextNode((cb.context && cb.context.mnemonic) || "??"));
|
||||
row.appendChild(e);
|
||||
|
||||
e = document.createElement("td");
|
||||
e.appendChild(document.createTextNode((cb.args ? cb.args.length : 0).toString()));
|
||||
row.appendChild(e);
|
||||
body.appendChild(row);
|
||||
}
|
||||
|
||||
body.id = oldBody.id;
|
||||
oldBody.parentNode.replaceChild(body, oldBody);
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
B5500ConsolePanel.prototype.displayCentralControl = function displayCentralControl() {
|
||||
/* Displays the I/O and interrupt status in CentralControl */
|
||||
var cells;
|
||||
var s;
|
||||
var interruptMask;
|
||||
var interruptChange;
|
||||
var ccMask;
|
||||
var ccChange;
|
||||
var unitBusyMask;
|
||||
var unitBusyChange;
|
||||
var x;
|
||||
|
||||
this.cc.fetchCCLatches(this.ccLatches);
|
||||
ccMask = this.ccLatches[0];
|
||||
ccChange = this.lastCCMask ^ ccMask;
|
||||
this.lastCCMask = ccMask;
|
||||
|
||||
interruptMask = this.ccLatches[1] % 0x4000;
|
||||
interruptChange = this.lastInterruptMask ^ interruptMask;
|
||||
this.lastInterruptMask = interruptMask;
|
||||
|
||||
unitBusyMask = this.ccLatches[2];
|
||||
unitBusyChange = this.lastUnitBusyMask ^ unitBusyMask;
|
||||
this.lastUnitBusyMask = unitBusyMask;
|
||||
|
||||
x = 0;
|
||||
while (ccChange) {
|
||||
if (ccChange & 0x01) {
|
||||
if (this.ccLightsMap[x]) {
|
||||
this.ccLightsMap[x].style.visibility = (ccMask & 0x01 ? "visible" : "hidden");
|
||||
}
|
||||
}
|
||||
ccMask >>>= 1;
|
||||
ccChange >>>= 1;
|
||||
x++;
|
||||
}
|
||||
|
||||
x = 47;
|
||||
while (interruptChange) {
|
||||
if (interruptChange & 0x01) {
|
||||
if (this.intLightsMap[x]) {
|
||||
this.intLightsMap[x].style.visibility = (interruptMask & 0x01 ? "visible" : "hidden");
|
||||
}
|
||||
}
|
||||
interruptMask >>>= 1;
|
||||
interruptChange >>>= 1;
|
||||
x--;
|
||||
}
|
||||
|
||||
x = 47;
|
||||
while (unitBusyChange) {
|
||||
if (unitBusyChange & 0x01) {
|
||||
if (this.perLightsMap[x]) {
|
||||
this.perLightsMap[x].style.visibility = (unitBusyMask & 0x01 ? "visible" : "hidden");
|
||||
}
|
||||
}
|
||||
unitBusyMask >>>= 1;
|
||||
unitBusyChange >>>= 1;
|
||||
x--;
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
B5500ConsolePanel.prototype.dasBlinkenlichten = function dasBlinkenlichten() {
|
||||
/* Updates the panel display from current system state */
|
||||
var cycles;
|
||||
var pa = this.cc.PA;
|
||||
var pb = this.cc.PB;
|
||||
var p1 = this.cc.P1;
|
||||
var stateRate;
|
||||
|
||||
cycles = p1.normalCycles+p1.controlCycles;
|
||||
|
||||
if (pa) {
|
||||
if (pa.normalCycles+pa.controlCycles <= 0) {
|
||||
if (this.lastPAControlRate != -1) {
|
||||
this.lastPAControlRate = -1;
|
||||
this.aControl.className = "yellowButton";
|
||||
this.aNormal.className = "yellowButton";
|
||||
}
|
||||
} else {
|
||||
stateRate = Math.round(pa.normalCycles/cycles*6 + 0.25);
|
||||
if (stateRate != this.lastPANormalRate) {
|
||||
this.lastPANormalRate = stateRate;
|
||||
switch (stateRate) {
|
||||
case 0:
|
||||
this.aNormal.className = "yellowButton";
|
||||
break;
|
||||
case 1:
|
||||
this.aNormal.className = "yellowButton yellowLit1";
|
||||
break;
|
||||
case 2:
|
||||
this.aNormal.className = "yellowButton yellowLit2";
|
||||
break;
|
||||
case 3:
|
||||
this.aNormal.className = "yellowButton yellowLit3";
|
||||
break;
|
||||
case 4:
|
||||
this.aNormal.className = "yellowButton yellowLit4";
|
||||
break;
|
||||
case 5:
|
||||
this.aNormal.className = "yellowButton yellowLit5";
|
||||
break;
|
||||
default:
|
||||
this.aNormal.className = "yellowButton yellowLit";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
stateRate = Math.round(pa.controlCycles/cycles*6 + 0.25);
|
||||
if (stateRate != this.lastPAControlRate) {
|
||||
this.lastPAControlRate = stateRate;
|
||||
switch (stateRate) {
|
||||
case 0:
|
||||
this.aControl.className = "yellowButton";
|
||||
break;
|
||||
case 1:
|
||||
this.aControl.className = "yellowButton yellowLit1";
|
||||
break;
|
||||
case 2:
|
||||
this.aControl.className = "yellowButton yellowLit2";
|
||||
break;
|
||||
case 3:
|
||||
this.aControl.className = "yellowButton yellowLit3";
|
||||
break;
|
||||
case 4:
|
||||
this.aControl.className = "yellowButton yellowLit4";
|
||||
break;
|
||||
case 5:
|
||||
this.aControl.className = "yellowButton yellowLit5";
|
||||
break;
|
||||
default:
|
||||
this.aControl.className = "yellowButton yellowLit";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pa.controlCycles = pa.normalCycles = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (pb) {
|
||||
if (pb.normalCycles+pb.controlCycles <= 0) {
|
||||
if (this.lastPBControlRate != -1) {
|
||||
this.bControl.className = "yellowButton";
|
||||
this.bNormal.className = "yellowButton";
|
||||
this.lastPBControlRate = -1;
|
||||
}
|
||||
} else {
|
||||
stateRate = Math.round(pb.normalCycles/cycles*6 + 0.25);
|
||||
if (stateRate != this.lastPBNormalRate) {
|
||||
this.lastPBNormalRate = stateRate;
|
||||
switch (stateRate) {
|
||||
case 0:
|
||||
this.bNormal.className = "yellowButton";
|
||||
break;
|
||||
case 1:
|
||||
this.bNormal.className = "yellowButton yellowLit1";
|
||||
break;
|
||||
case 2:
|
||||
this.bNormal.className = "yellowButton yellowLit2";
|
||||
break;
|
||||
case 3:
|
||||
this.bNormal.className = "yellowButton yellowLit3";
|
||||
break;
|
||||
case 4:
|
||||
this.bNormal.className = "yellowButton yellowLit4";
|
||||
break;
|
||||
case 5:
|
||||
this.bNormal.className = "yellowButton yellowLit5";
|
||||
break;
|
||||
default:
|
||||
this.bNormal.className = "yellowButton yellowLit";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
stateRate = Math.round(pb.controlCycles/cycles*6 + 0.25);
|
||||
if (stateRate != this.lastPBControlRate) {
|
||||
this.lastPBControlRate = stateRate;
|
||||
switch (stateRate) {
|
||||
case 0:
|
||||
this.bControl.className = "yellowButton";
|
||||
break;
|
||||
case 1:
|
||||
this.bControl.className = "yellowButton yellowLit1";
|
||||
break;
|
||||
case 2:
|
||||
this.bControl.className = "yellowButton yellowLit2";
|
||||
break;
|
||||
case 3:
|
||||
this.bControl.className = "yellowButton yellowLit3";
|
||||
break;
|
||||
case 4:
|
||||
this.bControl.className = "yellowButton yellowLit4";
|
||||
break;
|
||||
case 5:
|
||||
this.bControl.className = "yellowButton yellowLit5";
|
||||
break;
|
||||
default:
|
||||
this.bControl.className = "yellowButton yellowLit";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pb.controlCycles = pb.normalCycles = 0;
|
||||
}
|
||||
}
|
||||
|
||||
this.procDelay.textContent = p1.delayDeltaAvg.toFixed(1);
|
||||
this.procSlack.textContent = (p1.procSlackAvg/p1.procRunAvg*100).toFixed(1);
|
||||
|
||||
if (this.showAnnunciators) {
|
||||
this.displayCentralControl();
|
||||
}
|
||||
//this.displayCallbackState();
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
B5500ConsolePanel.prototype.buildLightMaps = function buildLightMaps() {
|
||||
/* Builds tables of the DOM entries for the annunciator lights, for efficient access */
|
||||
var mnem;
|
||||
var spec;
|
||||
var x;
|
||||
|
||||
this.ccLightsMap[0] = this.$$("AD1F");
|
||||
this.ccLightsMap[1] = this.$$("AD2F");
|
||||
this.ccLightsMap[2] = this.$$("AD3F");
|
||||
this.ccLightsMap[3] = this.$$("AD4F");
|
||||
this.ccLightsMap[4] = this.$$("P2BF");
|
||||
this.ccLightsMap[5] = this.$$("HP2F");
|
||||
|
||||
for (x=3; x<=16; x++) {
|
||||
this.intLightsMap[50-x] = this.$$("CCI" + (x+100).toString().substring(1) + "F");
|
||||
}
|
||||
|
||||
for (mnem in B5500CentralControl.unitSpecs) {
|
||||
spec = B5500CentralControl.unitSpecs[mnem];
|
||||
this.perLightsMap[spec.unitIndex] = this.$$(mnem);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
B5500ConsolePanel.prototype.lampTest = function lampTest(callback, callbackParam) {
|
||||
/* Lights up the operator console, waits a bit, then turns everything
|
||||
off and calls the "callback" function, passing "callbackParam".
|
||||
The Power On lamp is not affected */
|
||||
var that = this;
|
||||
|
||||
function switchEm(mode) {
|
||||
var visibility = (mode ? "visible" : "hidden");
|
||||
var x;
|
||||
|
||||
that.$$("ANormalBtn").className = "yellowButton" + (mode ? " yellowLit" : "");
|
||||
that.$$("AControlBtn").className = "yellowButton" + (mode ? " yellowLit" : "");
|
||||
that.$$("BNormalBtn").className = "yellowButton" + (mode ? " yellowLit" : "");
|
||||
that.$$("BControlBtn").className = "yellowButton" + (mode ? " yellowLit" : "");
|
||||
that.$$("LoadSelectBtn").className = "yellowButton" + (mode ? " yellowLit" : "");
|
||||
that.$$("MemoryCheckBtn").className = "redButton" + (mode ? " redLit" : "");
|
||||
that.$$("NotReadyBtn").className = "whiteButton" + (mode ? " whiteLit" : "");
|
||||
that.$$("HaltBtn").className = "redButton" + (mode ? " redLit" : "");
|
||||
|
||||
for (x in that.ccLightsMap) {
|
||||
if (that.ccLightsMap[x]) {
|
||||
that.ccLightsMap[x].style.visibility = visibility;
|
||||
}
|
||||
}
|
||||
|
||||
for (x in that.intLightsMap) {
|
||||
if (that.intLightsMap[x]) {
|
||||
that.intLightsMap[x].style.visibility = visibility;
|
||||
}
|
||||
}
|
||||
|
||||
for (x in that.perLightsMap) {
|
||||
if (that.perLightsMap[x]) {
|
||||
that.perLightsMap[x].style.visibility = visibility;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mode) {
|
||||
that.setAnnunciators(that.showAnnunciators);
|
||||
setCallback(null, that, 250, callback, callbackParam);
|
||||
}
|
||||
}
|
||||
|
||||
this.setAnnunciators(true);
|
||||
this.$$("CentralControl").style.display = "block"; // overrides if !this.cc.poweredUp
|
||||
switchEm(1);
|
||||
setCallback(null, this, 2000, switchEm, 0);
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
B5500ConsolePanel.prototype.beforeUnload = function beforeUnload(ev) {
|
||||
var msg = "Closing this window will make the emulator unusable.\n" +
|
||||
"Suggest you stay on the page and minimize this window instead";
|
||||
|
||||
ev.preventDefault();
|
||||
ev.returnValue = msg;
|
||||
return msg;
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500ConsolePanel.prototype.consoleUnload = function consoleUnload(ev) {
|
||||
/* Called when the ConsolePanel window unloads or is closed */
|
||||
|
||||
if (this.cc && this.cc.poweredUp) {
|
||||
this.cc.powerOff();
|
||||
if (this.timer) {
|
||||
clearInterval(this.timer);
|
||||
this.timer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
this.shutDown();
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500ConsolePanel.prototype.clearStatusLabel = function clearStatusLabel(inSeconds) {
|
||||
/* Delays for "inSeconds" seconds, then clears the StatusLabel element */
|
||||
|
||||
if (this.statusLabelTimer) {
|
||||
clearTimeout(this.statusLabelTimer);
|
||||
}
|
||||
|
||||
this.statusLabelTimer = setCallback(null, this, inSeconds*1000, function(ev) {
|
||||
this.$$("StatusLabel").textContent = "";
|
||||
this.statusLabelTimer = 0;
|
||||
});
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
B5500ConsolePanel.prototype.consoleOnload = function consoleOnload(ev) {
|
||||
/* Initialization function called when window finishes loading */
|
||||
|
||||
this.doc = this.window.document;
|
||||
this.$$("RetroVersion").textContent = B5500CentralControl.version;
|
||||
this.window.name = "B5500Console";
|
||||
this.window.addEventListener("unload",
|
||||
B5500CentralControl.bindMethod(this, B5500ConsolePanel.prototype.consoleUnload));
|
||||
this.$$("BurroughsLogo").addEventListener("click",
|
||||
B5500CentralControl.bindMethod(this, B5500ConsolePanel.prototype.BurroughsLogo_Click));
|
||||
this.$$("B5500Logo").addEventListener("click",
|
||||
B5500CentralControl.bindMethod(this, B5500ConsolePanel.prototype.B5500Logo_Click));
|
||||
this.$$("PowerOnBtn").addEventListener("click",
|
||||
B5500CentralControl.bindMethod(this, B5500ConsolePanel.prototype.PowerOnBtn_Click));
|
||||
this.$$("PowerOffBtn").addEventListener("click",
|
||||
B5500CentralControl.bindMethod(this, B5500ConsolePanel.prototype.PowerOffBtn_Click));
|
||||
this.$$("HaltBtn").addEventListener("click",
|
||||
B5500CentralControl.bindMethod(this, B5500ConsolePanel.prototype.HaltBtn_Click));
|
||||
this.$$("LoadBtn").addEventListener("click",
|
||||
B5500CentralControl.bindMethod(this, B5500ConsolePanel.prototype.LoadBtn_Click));
|
||||
this.$$("LoadSelectBtn").addEventListener("click",
|
||||
B5500CentralControl.bindMethod(this, B5500ConsolePanel.prototype.LoadSelectBtn_Click));
|
||||
this.$$("MemoryCheckBtn").addEventListener("click",
|
||||
B5500CentralControl.bindMethod(this, function(ev) {
|
||||
this.dumpState("Memory-Check Button");
|
||||
}));
|
||||
|
||||
this.aControl = this.$$("AControlBtn");
|
||||
this.aNormal = this.$$("ANormalBtn");
|
||||
this.bControl = this.$$("BControlBtn");
|
||||
this.bNormal = this.$$("BNormalBtn");
|
||||
this.procDelay = this.$$("procDelay");
|
||||
this.procSlack = this.$$("procSlack");
|
||||
this.buildLightMaps();
|
||||
|
||||
this.cc = new B5500CentralControl(this.global);
|
||||
this.global.B5500DumpState = this.dumpState;
|
||||
this.window.resizeTo(this.doc.documentElement.scrollWidth + this.window.outerWidth - this.window.innerWidth + 2, // kludge +2, dunno why
|
||||
this.doc.documentElement.scrollHeight + this.window.outerHeight - this.window.innerHeight);
|
||||
this.window.moveTo(screen.availWidth - this.window.outerWidth, 0);
|
||||
this.window.focus();
|
||||
this.setAnnunciators(this.showAnnunciators);
|
||||
|
||||
if (this.autoPowerUp) {
|
||||
setCallback(null, this, 1000, this.PowerOnBtn_Click, ev);
|
||||
}
|
||||
};
|
||||
@@ -27,7 +27,7 @@
|
||||
function B5500DatacomUnit(mnemonic, unitIndex, designate, statusChange, signal, options) {
|
||||
/* Constructor for the DatacomUnit object */
|
||||
|
||||
this.maxScrollLines = 1500; // Maximum amount of printer scrollback
|
||||
this.maxScrollLines = 5000; // Maximum amount of printer scrollback
|
||||
this.charPeriod = 100; // Printer speed, milliseconds per character
|
||||
this.bufferSize = 112; // 4 28-character B487 buffer segments
|
||||
|
||||
@@ -107,9 +107,9 @@ B5500DatacomUnit.prototype.clear = function clear() {
|
||||
B5500DatacomUnit.prototype.showBufferIndex = function showBufferIndex() {
|
||||
/* Formats the buffer index and length, and the column counter, for display */
|
||||
|
||||
this.$$("BufferOffset").innerHTML = this.bufIndex.toString();
|
||||
this.$$("BufferLength").innerHTML = this.bufLength.toString();
|
||||
this.$$("PrintColumn").innerHTML = (this.printCol+1).toString();
|
||||
this.$$("BufferOffset").textContent = this.bufIndex.toString();
|
||||
this.$$("BufferLength").textContent = this.bufLength.toString();
|
||||
this.$$("PrintColumn").textContent = (this.printCol+1).toString();
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
@@ -333,7 +333,7 @@ B5500DatacomUnit.prototype.keyAction = function keyAction(ev, c) {
|
||||
var nextTime; // next character output time, ms
|
||||
var stamp; // current timestamp, ms
|
||||
|
||||
//this.$$("CharCode").innerHTML = c.toString() + ":0x" + c.toString(16);
|
||||
//this.$$("CharCode").textContent = c.toString() + ":0x" + c.toString(16);
|
||||
|
||||
if (this.connected) {
|
||||
stamp = performance.now();
|
||||
|
||||
@@ -52,9 +52,10 @@ function B5500LinePrinter(mnemonic, unitIndex, designate, statusChange, signal,
|
||||
this.window.addEventListener("load",
|
||||
B5500CentralControl.bindMethod(this, B5500LinePrinter.prototype.printerOnload), false);
|
||||
}
|
||||
|
||||
B5500LinePrinter.prototype.linesPerMinute = 1040; // B329 line printer
|
||||
B5500LinePrinter.prototype.maxPaperLines = 150000; // maximum printer scrollback (about a box of paper)
|
||||
B5500LinePrinter.prototype.rtrimRex = /\s+$/g; // regular expression for right-trimming lines
|
||||
B5500LinePrinter.prototype.rtrimRex = /\s+$/; // regular expression for right-trimming lines
|
||||
B5500LinePrinter.prototype.theColorGreen = "#CFC"; // for greenbar shading
|
||||
|
||||
/**************************************/
|
||||
@@ -203,7 +204,7 @@ B5500LinePrinter.prototype.setGreenbar = function setGreenbar(useGreen) {
|
||||
// Next, search through the rules for the one that controls greenbar shading.
|
||||
for (x=rules.length-1; x>=0; --x) {
|
||||
rule = rules[x];
|
||||
if (rule.selectorText == "PRE.greenBar") {
|
||||
if (rule.selectorText.toLowerCase() == "pre.greenbar") {
|
||||
// Found it: now flip the background color.
|
||||
rule.style.backgroundColor = (useGreen ? this.theColorGreen : "white");
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
/**************************************/
|
||||
function B5500MagTapeDrive(mnemonic, unitIndex, designate, statusChange, signal, options) {
|
||||
/* Constructor for the MagTapeDrive object */
|
||||
var y = ((mnemonic.charCodeAt(2) - "A".charCodeAt(0))*30);
|
||||
|
||||
this.mnemonic = mnemonic; // Unit mnemonic
|
||||
this.unitIndex = unitIndex; // Ready-mask bit number
|
||||
@@ -53,7 +54,7 @@ function B5500MagTapeDrive(mnemonic, unitIndex, designate, statusChange, signal,
|
||||
}
|
||||
this.doc = null;
|
||||
this.window = window.open("../webUI/B5500MagTapeDrive.html", mnemonic,
|
||||
"location=no,scrollbars=no,resizable,width=560,height=120,left=280,top=0");
|
||||
"location=no,scrollbars=no,resizable,width=560,height=120,left=280,top=" + y);
|
||||
this.window.addEventListener("load",
|
||||
B5500CentralControl.bindMethod(this, B5500MagTapeDrive.prototype.tapeDriveOnload), false);
|
||||
}
|
||||
@@ -1137,7 +1138,6 @@ B5500MagTapeDrive.prototype.beforeUnload = function beforeUnload(ev) {
|
||||
B5500MagTapeDrive.prototype.tapeDriveOnload = function tapeDriveOnload() {
|
||||
/* Initializes the reader window and user interface */
|
||||
var de;
|
||||
var y = ((this.mnemonic.charCodeAt(2) - "A".charCodeAt(0))*30);
|
||||
|
||||
this.doc = this.window.document;
|
||||
de = this.doc.documentElement;
|
||||
@@ -1167,7 +1167,6 @@ B5500MagTapeDrive.prototype.tapeDriveOnload = function tapeDriveOnload() {
|
||||
|
||||
this.window.resizeBy(de.scrollWidth - this.window.innerWidth + 4, // kludge for right-padding/margin
|
||||
de.scrollHeight - this.window.innerHeight);
|
||||
this.window.moveTo(280, y);
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
CACHE MANIFEST
|
||||
# retro-B5500 emulator 1.00, 2014-09-27
|
||||
# retro-B5500 emulator 1.01, 2015-02-08 17:30
|
||||
|
||||
CACHE:
|
||||
../emulator/B5500CentralControl.js
|
||||
@@ -18,6 +18,9 @@ B5500Common.css
|
||||
B5500Console.css
|
||||
B5500Console.html
|
||||
B5500Console.js
|
||||
B5500ConsolePanel.css
|
||||
B5500ConsolePanel.html
|
||||
B5500ConsolePanel.js
|
||||
B5500DatacomUnit.css
|
||||
B5500DatacomUnit.html
|
||||
B5500DatacomUnit.js
|
||||
@@ -44,6 +47,7 @@ B5500SystemConfig.html
|
||||
B5500SystemConfig.js
|
||||
B5500Util.js
|
||||
resources/B5500Logo.jpg
|
||||
resources/Burroughs-B5500-102646215-05-01-06.jpg
|
||||
resources/Burroughs-Logo-Neg.jpg
|
||||
resources/DejaVuSans-Bold-webfont.ttf
|
||||
resources/DejaVuSans-Bold-webfont.woff
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
function B5500SPOUnit(mnemonic, unitIndex, designate, statusChange, signal, options) {
|
||||
/* Constructor for the SPOUnit object */
|
||||
|
||||
this.maxScrollLines = 1500; // Maximum amount of printer scrollback
|
||||
this.maxScrollLines = 5000; // Maximum amount of printer scrollback
|
||||
this.charPeriod = 100; // Printer speed, milliseconds per character
|
||||
|
||||
this.mnemonic = mnemonic; // Unit mnemonic
|
||||
@@ -173,7 +173,7 @@ B5500SPOUnit.prototype.setAlgolGlyphs = function setAlgolGlyphs(makeItPretty) {
|
||||
/**************************************/
|
||||
B5500SPOUnit.prototype.appendEmptyLine = function appendEmptyLine(text) {
|
||||
/* Removes excess lines already printed, then appends a new text node
|
||||
to the <pre> element within the <iframe> */
|
||||
to the <pre> element within the paper element */
|
||||
var count = this.paper.childNodes.length;
|
||||
var line = text || "";
|
||||
|
||||
|
||||
@@ -25,17 +25,17 @@
|
||||
* sooner than requested, and that due to either other activity or browser
|
||||
* limitations the delay may be longer than requested, the timing behavior of
|
||||
* setCallback() may be divided into "categories." For each category, a separate
|
||||
* record is kept of the exponential-moving-average difference between the
|
||||
* requested delay and the actual delay. This difference is used to adjust the
|
||||
* record is kept of the exponential-moving-average deviation between the
|
||||
* requested delay and the actual delay. This deviation is used to adjust the
|
||||
* requested delay on subsequent calls in an attempt to smooth out the differences.
|
||||
* We are going for good average behavior here, and 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.
|
||||
*
|
||||
* The SetCallback mechanism defines two functions, which become members of the
|
||||
* The SetCallback mechanism defines three functions that become members of the
|
||||
* global (window) object:
|
||||
*
|
||||
* cookie = setCallback(category, context, delay, fcn[, arg])
|
||||
* token = setCallback(category, context, delay, fcn[, arg])
|
||||
*
|
||||
* Requests that the function "fcn" be called after "delay" milliseconds.
|
||||
* The function will be called as a method of "context", passing a
|
||||
@@ -47,10 +47,22 @@
|
||||
* with clearCallback(). Note that passing a string in lieu of a function
|
||||
* object is not permitted.
|
||||
*
|
||||
* clearCallBack(cookie)
|
||||
* clearCallBack(token)
|
||||
*
|
||||
* Cancels a pending call-back event, if in fact it is still pending.
|
||||
* The "cookie" parameter is a value returned from setCallback().
|
||||
* The "token" parameter is a value returned from setCallback().
|
||||
*
|
||||
* object = getCallbackState(optionMask)
|
||||
*
|
||||
* This is a diagnostic function intended for use in monitoring the callback
|
||||
* mechanism. It returns an object that, depending upon bits set in its mask
|
||||
* parameter, contains copies of the nextTokenNr value, poolLength
|
||||
* value, current delayDev hash, pendingCallbacks hash, and pool array:
|
||||
* bit 0x01: delayDev hash
|
||||
* bit 0x02: pendingCallbacks hash
|
||||
* bit 0x04: pool array
|
||||
* The nextTokenNr and poolLength values are always returned. If no mask
|
||||
* is supplied, no additional items are returned.
|
||||
*
|
||||
* This implementation has been inspired by Domenic Denicola's shim for the
|
||||
* setImmediate() API at https://github.com/NobleJS/setImmediate, and
|
||||
@@ -65,6 +77,8 @@
|
||||
* 2014-04-05 P.Kimpel
|
||||
* Change calling sequence to add "category" parameter; reorder setCallback
|
||||
* parameters into a more reasonable sequence; implement call-back pooling.
|
||||
* 2014-12-14 P.Kimpel
|
||||
* Added getCallbackState() diagnostic function, changed "cookie" to "token".
|
||||
***********************************************************************/
|
||||
"use strict";
|
||||
|
||||
@@ -73,27 +87,27 @@
|
||||
var delayAlpha = 0.99; // exponential-moving-average decay factor
|
||||
var delayDev = {NUL: 0}; // hash of average delay time deviations by category
|
||||
var minTimeout = 4; // minimum setTimeout() threshold, milliseconds
|
||||
var nextCookieNr = 1; // next setCallback cookie return value
|
||||
var pendingCallbacks = {}; // hash of pending callbacks, indexed by cookie as a string
|
||||
var nextTokenNr = 1; // next setCallback token return value
|
||||
var pendingCallbacks = {}; // hash of pending callbacks, indexed by token as a string
|
||||
var perf = global.performance; // cached window.performance object
|
||||
var pool = []; // pool of reusable callback objects
|
||||
var poolLength = 0; // length of active entries in pool
|
||||
var secretPrefix = "com.google.code.p.retro-b5500.webUI." + Date.now().toString(16);
|
||||
var secretPrefix = "retro-b5500.webUI." + Date.now().toString(16);
|
||||
|
||||
/**************************************/
|
||||
function activateCallback(cookie) {
|
||||
function activateCallback(token) {
|
||||
/* Activates a callback after its delay period has expired */
|
||||
var category;
|
||||
var cookieName = cookie.toString();
|
||||
var endStamp = perf.now();
|
||||
var thisCallback;
|
||||
var tokenName = token.toString();
|
||||
|
||||
thisCallback = pendingCallbacks[cookieName];
|
||||
thisCallback = pendingCallbacks[tokenName];
|
||||
if (thisCallback) {
|
||||
delete pendingCallbacks[cookieName];
|
||||
delete pendingCallbacks[tokenName];
|
||||
category = thisCallback.category;
|
||||
if (category) {
|
||||
delayDev[category] = (delayDev[category] || 0) +
|
||||
delayDev[category] = (delayDev[category] || 0)*delayAlpha +
|
||||
(endStamp - thisCallback.startStamp - thisCallback.delay)*(1.0-delayAlpha);
|
||||
}
|
||||
try {
|
||||
@@ -109,14 +123,14 @@
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function clearCallback(cookie) {
|
||||
function clearCallback(token) {
|
||||
/* Disables a pending callback, if it still exists and is still pending */
|
||||
var cookieName = cookie.toString();
|
||||
var thisCallback;
|
||||
var tokenName = token.toString();
|
||||
|
||||
thisCallback = pendingCallbacks[cookieName];
|
||||
thisCallback = pendingCallbacks[tokenName];
|
||||
if (thisCallback) {
|
||||
delete pendingCallbacks[cookieName];
|
||||
delete pendingCallbacks[tokenName];
|
||||
if (thisCallback.isTimeout) {
|
||||
if (thisCallback.cancelToken) {
|
||||
global.clearTimeout(thisCallback.cancelToken);
|
||||
@@ -129,45 +143,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function _setCallback_Old(fcn, context, callbackDelay, arg) {
|
||||
/* Sets up and schedules a callback for function "fcn", called with context
|
||||
"context", after a delay of "delay" ms. An optional "arg" value will be passed
|
||||
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 delay = callbackDelay || 0;
|
||||
var cookie = nextCookieNr++;
|
||||
var cookieName = cookie.toString();
|
||||
var thisCallback;
|
||||
|
||||
if (poolLength > 0) {
|
||||
thisCallback = pool[--poolLength];
|
||||
pool[poolLength] = null;
|
||||
} else {
|
||||
thisCallback = {};
|
||||
}
|
||||
|
||||
thisCallback.startStamp = perf.now();
|
||||
thisCallback.category = "NUL";
|
||||
thisCallback.context = context || this;
|
||||
thisCallback.delay = delay;
|
||||
thisCallback.fcn = fcn;
|
||||
thisCallback.arg = arg;
|
||||
pendingCallbacks[cookieName] = thisCallback;
|
||||
|
||||
if (delay < minTimeout) {
|
||||
thisCallback.isTimeout = false;
|
||||
global.postMessage(secretPrefix + cookieName, "*");
|
||||
thisCallback.cancelToken = 0;
|
||||
} else {
|
||||
thisCallback.isTimeout = true;
|
||||
thisCallback.cancelToken = global.setTimeout(activateCallback, delay, cookie);
|
||||
}
|
||||
|
||||
return cookie;
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function setCallback(category, context, callbackDelay, fcn, arg) {
|
||||
/* Sets up and schedules a callback for function "fcn", called with context
|
||||
@@ -176,10 +151,10 @@
|
||||
based on window.postsMessage() will be used; otherwise the environment's standard
|
||||
setTimeout mechanism will be used */
|
||||
var categoryName = (category || "NUL").toString();
|
||||
var cookie = nextCookieNr++;
|
||||
var cookieName = cookie.toString();
|
||||
var delay = callbackDelay || 0;
|
||||
var thisCallback;
|
||||
var token = nextTokenNr++;
|
||||
var tokenName = token.toString();
|
||||
|
||||
// Allocate a call-back object from the pool.
|
||||
if (poolLength <= 0) {
|
||||
@@ -193,24 +168,24 @@
|
||||
thisCallback.startStamp = perf.now();
|
||||
thisCallback.category = categoryName;
|
||||
thisCallback.context = context || this;
|
||||
thisCallback.delay = (delay < 0 ? 0 : delay);
|
||||
thisCallback.delay = delay;
|
||||
thisCallback.fcn = fcn;
|
||||
thisCallback.arg = arg;
|
||||
|
||||
pendingCallbacks[cookieName] = thisCallback;
|
||||
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 - (delayDev[categoryName] || 0), cookie);
|
||||
} else {
|
||||
delay -= (delayDev[categoryName] || 0); // bias by the current avg. deviation
|
||||
if (delay < minTimeout) {
|
||||
thisCallback.isTimeout = false;
|
||||
global.postMessage(secretPrefix + cookieName, "*");
|
||||
thisCallback.cancelToken = 0;
|
||||
global.postMessage(secretPrefix + tokenName, "*");
|
||||
} else {
|
||||
thisCallback.isTimeout = true;
|
||||
thisCallback.cancelToken = global.setTimeout(activateCallback, delay, token);
|
||||
}
|
||||
|
||||
return cookie;
|
||||
return token;
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
@@ -218,12 +193,49 @@
|
||||
/* Handler for the global.onmessage event. Activates the callback */
|
||||
var payload;
|
||||
|
||||
// if (ev.source === global) {
|
||||
if (ev.source === global) {
|
||||
payload = ev.data.toString();
|
||||
if (payload.substring(0, secretPrefix.length) === secretPrefix) {
|
||||
activateCallback(payload.substring(secretPrefix.length));
|
||||
}
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
function getCallbackState(optionMask) {
|
||||
/* Diagnostic function. Returns an object that, depending upon bits in
|
||||
the option mask, contains copies of the nextTokenNr value, poolLength
|
||||
value, current delayDev hash, pendingCallbacks hash, and pool array.
|
||||
bit 0x01: delayDev hash
|
||||
bit 0x02: pendingCallbacks hash
|
||||
bit 0x04: pool array
|
||||
If no mask is supplied, no additional items are returned */
|
||||
var e;
|
||||
var mask = optionMask || 0;
|
||||
var state = {
|
||||
nextTokenNr: nextTokenNr,
|
||||
poolLength: poolLength,
|
||||
delayDev: {},
|
||||
pendingCallbacks: {},
|
||||
pool: []};
|
||||
|
||||
if (mask & 0x01) {
|
||||
for (e in delayDev) {
|
||||
state.delayDev[e] = delayDev[e];
|
||||
}
|
||||
}
|
||||
if (mask & 0x02) {
|
||||
for (e in pendingCallbacks) {
|
||||
state.pendingCallbacks[e] = pendingCallbacks[e];
|
||||
}
|
||||
}
|
||||
if (mask & 0x04) {
|
||||
for (e=0; e<poolLength; ++e) {
|
||||
state.pool[e] = pool[e];
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
/********** Outer block of anonymous closure **********/
|
||||
@@ -242,5 +254,6 @@
|
||||
global.addEventListener("message", onMessage, false);
|
||||
attachee.setCallback = setCallback;
|
||||
attachee.clearCallback = clearCallback;
|
||||
attachee.getCallbackState = getCallbackState;
|
||||
}
|
||||
}(typeof global === "object" && global ? global : this));
|
||||
|
||||
@@ -707,116 +707,6 @@ function displaySystemState() {
|
||||
//window.focus();
|
||||
}
|
||||
|
||||
function dumpState__OLD(caption) {
|
||||
/* Generates a dump of the processor states and all of memory */
|
||||
var addr;
|
||||
var bic;
|
||||
var doc;
|
||||
var dupCount = 0;
|
||||
var lastLine = "";
|
||||
var line;
|
||||
var lineAddr;
|
||||
var mod;
|
||||
var win = window.open("", "", "resizable,scrollbars,status");
|
||||
var x;
|
||||
|
||||
function convertWordtoANSI(value) {
|
||||
/* Converts the "value" as a B5500 word to an eight character string and returns it */
|
||||
var c; // current character
|
||||
var s = ""; // working string value
|
||||
var w = value; // working word value
|
||||
var x; // character counter
|
||||
|
||||
for (x=0; x<8; x++) {
|
||||
c = w % 64;
|
||||
w = (w-c)/64;
|
||||
s = BICtoANSI[c] + s;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
function dumpProcessorState(px) {
|
||||
/* Dumps the register state for the specified processor */
|
||||
var procNr = (px === cc.P1 ? "1" : "2");
|
||||
|
||||
doc.writeln();
|
||||
doc.writeln("Processor P" + procNr + " = " + px.mnemonic + ":");
|
||||
|
||||
doc.writeln();
|
||||
doc.writeln("NCSF=" + px.NCSF + " CWMF=" + px.CWMF + " MSFF=" + px.MSFF + " SALF=" + px.SALF +
|
||||
" VARF=" + px.VARF);
|
||||
doc.writeln("C=" + padOctal(px.C, 5) + " L=" + px.L + " P=" + padOctal(px.P, 16) + " PROF=" + px.TROF +
|
||||
" T=" + padOctal(px.T, 4) + " TROF=" + px.TROF);
|
||||
doc.writeln("I=" + padLeft(px.I.toString(2), 8, "0") + " E=" + padLeft(px.E.toString(2), 6, "0") +
|
||||
" Q=" + padLeft(px.Q.toString(2), 12, "0") + " [bit masks]");
|
||||
doc.writeln("M=" + padOctal(px.M, 5) + " G=" + px.G + " H=" + px.H);
|
||||
doc.writeln("S=" + padOctal(px.S, 5) + " K=" + px.K + " V=" + px.V);
|
||||
doc.writeln("F=" + padOctal(px.F, 5) + " R=" + padOctal(px.R, 3));
|
||||
doc.writeln();
|
||||
doc.writeln("X= " + padOctal(px.X, 13) + " Y=" + padOctal(px.Y, 2) + " Z=" + padOctal(px.Z, 2) +
|
||||
" N=" + px.N);
|
||||
doc.writeln("A=" + padOctal(px.A, 16) + " AROF=" + px.AROF);
|
||||
doc.writeln("B=" + padOctal(px.B, 16) + " BROF=" + px.BROF);
|
||||
}
|
||||
|
||||
doc = win.document;
|
||||
doc.open();
|
||||
doc.writeln("<html><head><title>B5500 Syllable Debugger State Dump</title>");
|
||||
doc.writeln("</head><body>");
|
||||
doc.writeln("<pre>Dump by " + escapeHTML(caption || "(unknown)") + " : " + new Date().toString());
|
||||
|
||||
dumpProcessorState(cc.P1);
|
||||
if (cc.P2) {
|
||||
dumpProcessorState(cc.P2);
|
||||
}
|
||||
|
||||
doc.writeln();
|
||||
for (mod=0; mod<0x8000; mod+=0x1000) {
|
||||
for (addr=0; addr<0x1000; addr+=4) {
|
||||
lineAddr = mod+addr;
|
||||
line = bic = "";
|
||||
for (x=0; x<4; x++) {
|
||||
accessor.addr = lineAddr+x;
|
||||
cc.fetch(accessor);
|
||||
if (accessor.MAIL) {
|
||||
line += escapeHTML(" << ADDR INH >> ");
|
||||
bic += "????????";
|
||||
} else if (accessor.MPED) {
|
||||
line += escapeHTML(" << PARITY >> ");
|
||||
bic += "????????";
|
||||
} else if (accessor.MAED) {
|
||||
line += escapeHTML(" << INV ADDR >> ");
|
||||
bic += "????????";
|
||||
} else {
|
||||
line += " " + padOctal(accessor.word, 16);
|
||||
bic += convertWordtoANSI(accessor.word);
|
||||
}
|
||||
} // for x
|
||||
|
||||
if (line == lastLine && lineAddr < 0x7FFC) {
|
||||
dupCount++;
|
||||
} else {
|
||||
if (dupCount > 0) {
|
||||
doc.writeln();
|
||||
doc.writeln("..... ................ for " + dupCount*4 + " words");
|
||||
dupCount = 0;
|
||||
}
|
||||
doc.writeln();
|
||||
doc.write(padOctal(lineAddr, 5));
|
||||
doc.write(" ");
|
||||
doc.write(line);
|
||||
doc.write(" ");
|
||||
doc.writeln(escapeHTML(bic));
|
||||
lastLine = line;
|
||||
}
|
||||
} // for addr
|
||||
} // for mod
|
||||
|
||||
doc.writeln("</pre></body></html>")
|
||||
doc.close();
|
||||
win.focus();
|
||||
}
|
||||
|
||||
function dumpState(caption) {
|
||||
/* Generates a dump of the processor states and all of memory */
|
||||
var doc;
|
||||
|
||||
28
webUI/prototypes/B5500DDPanel.js
vendored
28
webUI/prototypes/B5500DDPanel.js
vendored
@@ -1,4 +1,4 @@
|
||||
/***********************************************************************
|
||||
/***********************************************************************
|
||||
* retro-b5500/emulator B5500DDPanel.js
|
||||
************************************************************************
|
||||
* Copyright (c) 2012, Nigel Williams and Paul Kimpel.
|
||||
@@ -29,8 +29,8 @@ function B5500DDLamp(x, y) {
|
||||
|
||||
/**************************************/
|
||||
|
||||
B5500DDLamp.onColor = "#FF9900";
|
||||
B5500DDLamp.offColor = "#999999";
|
||||
B5500DDLamp.lampClass = "ddLamp";
|
||||
B5500DDLamp.litClass = "ddLamp ddLampLit";
|
||||
|
||||
/**************************************/
|
||||
B5500DDLamp.prototype.set = function(v) {
|
||||
@@ -39,19 +39,19 @@ B5500DDLamp.prototype.set = function(v) {
|
||||
var newState = v & 1;
|
||||
|
||||
if (this.state ^ newState) { // the state has changed
|
||||
this.element.style.backgroundColor = (newState ? B5500DDLamp.onColor : B5500DDLamp.offColor);
|
||||
this.element.className = (newState ? B5500Lamp.litClass : B5500Lamp.lampClass);
|
||||
this.state = newState;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DDLamp.prototype.flip = function() {
|
||||
/* Complements the visible state of the lamp */
|
||||
var newState = this.state ^ 1;
|
||||
|
||||
this.element.style.backgroundColor = (newState ? B5500DDLamp.onColor : B5500DDLamp.offColor);
|
||||
this.element.className = (newState ? B5500Lamp.litClass : B5500Lamp.lampClass);
|
||||
this.state = newState;
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DDLamp.prototype.setCaption = function(caption) {
|
||||
@@ -61,7 +61,7 @@ B5500DDLamp.prototype.setCaption = function(caption) {
|
||||
e.className = "ddLampCaption";
|
||||
e.appendChild(document.createTextNode(caption));
|
||||
this.element.appendChild(e);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
@@ -137,14 +137,14 @@ B5500DDRegister.prototype.xCoord = function(col) {
|
||||
/* Returns the horizontal lamp coordinate in "px" format */
|
||||
|
||||
return String((col-1)*B5500DDRegister.hSpacing + B5500DDRegister.hOffset) + "px";
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DDRegister.prototype.yCoord = function(row) {
|
||||
/* Returns the vertical lamp coordinate in "px" format */
|
||||
|
||||
return String((row-1)*B5500DDRegister.vSpacing + B5500DDRegister.vOffset) + "px";
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DDRegister.prototype.YYupdate = function(value) {
|
||||
@@ -169,7 +169,7 @@ B5500DDRegister.prototype.YYupdate = function(value) {
|
||||
high >>>= 1;
|
||||
}
|
||||
this.lastValue = value;
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DDRegister.prototype.XXupdate = function(value) {
|
||||
@@ -184,7 +184,7 @@ B5500DDRegister.prototype.XXupdate = function(value) {
|
||||
this.lamps[bitNr].set(bit);
|
||||
mask = (mask-bit)/2;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DDRegister.prototype.update = function(value) {
|
||||
@@ -196,7 +196,7 @@ B5500DDRegister.prototype.update = function(value) {
|
||||
while (bitNr < this.bits) {
|
||||
bitNr++;
|
||||
bit = mask % 2;
|
||||
this.lamps[bitNr].element.style.backgroundColor = (bit ? B5500DDLamp.onColor : B5500DDLamp.offColor);
|
||||
this.lamps[bitNr].element.className = (bit ? B5500DDLamp.litClass : B5500DDLamp.lampClass);
|
||||
mask = (mask-bit)/2;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -88,10 +88,15 @@ DIV.ddLamp {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
font-size: 4px;
|
||||
background-color: #FFCC33;
|
||||
background-image: radial-gradient(circle, #999999, #333333);
|
||||
background-color: #999;
|
||||
border-radius: 8px;
|
||||
border: 1px solid black}
|
||||
|
||||
DIV.ddLampLit {
|
||||
background-image: radial-gradient(circle, #FF9933, #999999);
|
||||
background-color: #FF9900}
|
||||
|
||||
DIV.ddLampCaption {
|
||||
position: absolute;
|
||||
width: 16px;
|
||||
@@ -143,7 +148,7 @@ IMG#BurroughsLogoImage {
|
||||
.data {
|
||||
font-family: Courier New, Courier, monospace;
|
||||
text-align: left}
|
||||
|
||||
|
||||
.number {
|
||||
font-family: Courier New, Courier, monospace;
|
||||
text-align: right}
|
||||
|
||||
10
webUI/prototypes/B5500DistributionAndDisplay.js
vendored
10
webUI/prototypes/B5500DistributionAndDisplay.js
vendored
@@ -45,10 +45,10 @@ B5500DistributionAndDisplay.prototype.clear = function() {
|
||||
this.nextTimeStamp = new Date().getTime() + this.refreshPeriod;
|
||||
this.timer = setTimeout(this.tock, this.refreshPeriod);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DistributionAndDisplay.prototype.openProcessorPanel(p, caption) {
|
||||
B5500DistributionAndDisplay.prototype.openProcessorPanel = function(p, caption) {
|
||||
/* Creates a D&D panel window for a processor */
|
||||
var x;
|
||||
var panel = this.panels[caption];
|
||||
@@ -61,7 +61,7 @@ B5500DistributionAndDisplay.prototype.openProcessorPanel(p, caption) {
|
||||
panel = {module:p, window:win, caption:caption};
|
||||
this.panels[caption] = panel;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
B5500DistributionAndDisplay.prototype.updateDisplay = function updateDisplay() {
|
||||
@@ -74,6 +74,4 @@ B5500DistributionAndDisplay.prototype.updateDisplay = function updateDisplay() {
|
||||
that.nextRefresh += that.refreshPeriod;
|
||||
delayTime = that.nextRefresh - thisTime;
|
||||
that.timer = setTimeout(that.updateDisplay, (delayTime < 0 ? 1 : delayTime);
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
BIN
webUI/resources/Burroughs-B5500-102646215-05-01-06.jpg
Normal file
BIN
webUI/resources/Burroughs-B5500-102646215-05-01-06.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 92 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 12 KiB |
Reference in New Issue
Block a user