1
0
mirror of https://github.com/pkimpel/retro-b5500.git synced 2026-04-17 17:52:27 +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:
paul.kimpel@digm.com
2015-02-09 06:30:43 +00:00
parent 8b0d19deba
commit 1dad7d9744
23 changed files with 1415 additions and 1134 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -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 &amp; 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 &bull; Licensed under the MIT License
</div>
<div id=lastModDiv>Revised
2014-07-19
2015-02-08
</div>
</body>

View File

@@ -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 &bull; Licensed under the MIT License
</div>
<div id=lastModDiv>Revised
2013-07-20
2014-10-24
</div>
</body>

View File

@@ -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);

View File

@@ -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%}

View File

@@ -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>&nbsp;
<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 &amp; Power On
</button>
&nbsp;&nbsp;&nbsp;
<button id=StartUpNoPowerBtn title="Start the emulator in a power-off state">
Start &ndash; 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>

View File

@@ -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 "&amp;";
case "<":
return "&lt;";
case ">":
return "&gt;";
case "\"":
return "&quot;";
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
View 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}

View 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
View 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 "&amp;";
case "<":
return "&lt;";
case ">":
return "&gt;";
case "\"":
return "&quot;";
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);
}
};

View File

@@ -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();

View File

@@ -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");
}

View File

@@ -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);
};
/**************************************/

View File

@@ -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

View File

@@ -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 || "";

View File

@@ -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));

View File

@@ -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;

View File

@@ -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;
}
}
};

View File

@@ -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}

View File

@@ -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);
}
};

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