1
0
mirror of https://github.com/pkimpel/retro-b5500.git synced 2026-04-24 19:40:37 +00:00

Commit retro-b5500 release 1.06:

1. Redesign and simplify delay and time deviation adjustment algorithm
in global SetCallback function; reinstate alpha parameter to control
adjustment decay rate.
2. Correct memory stores during tape drive backward read.
3. Compare tape image file extensions in case-insensitive manner.
4. Detect dropouts (no flux change) in magnetic tape images.
5. Suppress printed SPO greeting after power-on.
6. Disable (for now) the ConsolePanel lamp test.
7. Update stacker progress meter and stacker-full annunciator when
emptying a stacker.
8. Supply (benign) terminating semicolons in ConsolePanel method
declarations.
9. Optimize extraction of MSCW address during Character Mode exit.
10. Miscellaneous minor additions and enhancements to scripts in tools/
directory.
This commit is contained in:
Paul Kimpel
2020-01-03 20:50:28 -08:00
parent 196175cd39
commit 1f82a16aaf
19 changed files with 1102 additions and 103 deletions

View File

@@ -12,9 +12,9 @@ The Burroughs B5500 was an innovative computer system. Released first as the B50
* Automatic memory segment overlay (what we now call virtual memory)
* Use of labeled file media and automatic assignment of labeled file media to requesting programs (what we now call automatic volume recognition)
The B5500 was the foundation for the Burroughs B6000/7000/A Series, which are still produced and sold today as Unisys ClearPath MCP systems.
The B5500 was the foundation for the Burroughs B6x00/7x00/A Series systems, which are still produced and sold today as Unisys ClearPath MCP systems.
The main goal of this project is creation of a web browser-based emulator for the B5500. A second goal is reconstruction of the source and object code for the system.
The main goal of this project is creation of a web browser-based emulator for the B5500. A second goal is reconstruction of source and object code for the system.
A complete software release (Mark XIII, 1971) is presently available from the hosting site below under liberal terms of a Unisys educational/hobbyist license.

View File

@@ -61,7 +61,7 @@ function B5500CentralControl(global) {
/**************************************/
/* Global constants */
B5500CentralControl.version = "1.05";
B5500CentralControl.version = "1.06";
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)

View File

@@ -81,7 +81,7 @@ function B5500IOUnit(ioUnitID, cc) {
B5500IOUnit.BICtoANSI = [ // Index by 6-bit BIC to get 8-bit ANSI code
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37, // 00-07, @00-07
0x38,0x39,0x23,0x40,0x3F,0x3A,0x3E,0x7D, // 08-1F, @10-17
0x38,0x39,0x23,0x40,0x3F,0x3A,0x3E,0x7D, // 08-0F, @10-17
0x2B,0x41,0x42,0x43,0x44,0x45,0x46,0x47, // 10-17, @20-27
0x48,0x49,0x2E,0x5B,0x26,0x28,0x3C,0x7E, // 18-1F, @30-37
0x7C,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50, // 20-27, @40-47
@@ -91,7 +91,7 @@ B5500IOUnit.BICtoANSI = [ // Index by 6-bit BIC to get 8-bit ANSI
B5500IOUnit.BICtoBCLANSI = [ // Index by 6-bit BIC to get 8-bit BCL-as-ANSI code
0x23,0x31,0x32,0x33,0x34,0x35,0x36,0x37, // 00-07, @00-07
0x38,0x39,0x40,0x3F,0x30,0x3A,0x3E,0x7D, // 08-1F, @10-17
0x38,0x39,0x40,0x3F,0x30,0x3A,0x3E,0x7D, // 08-0F, @10-17
0x2C,0x2F,0x53,0x54,0x55,0x56,0x57,0x58, // 10-17, @20-27
0x59,0x5A,0x25,0x21,0x20,0x3D,0x5D,0x22, // 18-1F, @30-37
0x24,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50, // 20-27, @40-47
@@ -322,6 +322,11 @@ B5500IOUnit.prototype.fetchBufferWithGM = function fetchBufferWithGM(mode, words
var table = (mode ? B5500IOUnit.BICtoANSI : B5500IOUnit.BICtoBCLANSI);
var w; // local copy of this.W
/********** DEBUG **********
var line = "";
var wx = 0;
***************************/
do { // loop through the words
if (words <= 0) {
done = true;
@@ -333,6 +338,18 @@ B5500IOUnit.prototype.fetchBufferWithGM = function fetchBufferWithGM(mode, words
done = true;
} else if (!this.fetch(addr)) { // fetch the next word from memory
w = this.W; // fill the buffer with this word's characters
/********** DEBUG **********
if (wx >= 4) {
console.log(this.mnemonic + "Mem:" + line);
wx = 0;
line = "";
}
line += " " + (w+0x1000000000000).toString(8).substring(1);
++wx;
***************************/
for (s=0; s<8; ++s) {
c = (w - (w %= 0x40000000000))/0x40000000000;
if (c == 0x1F) {
@@ -344,6 +361,7 @@ B5500IOUnit.prototype.fetchBufferWithGM = function fetchBufferWithGM(mode, words
}
} // for s
}
if (addr < 0x7FFF) {
++addr;
} else {
@@ -352,6 +370,10 @@ B5500IOUnit.prototype.fetchBufferWithGM = function fetchBufferWithGM(mode, words
}
} while (!done);
/********** DEBUG **********
console.log(this.mnemonic + "Fin:" + line);
***************************/
this.Daddress = addr;
if (this.D23F) {
this.DwordCount = words & 0x1FF;
@@ -600,12 +622,12 @@ B5500IOUnit.prototype.storeBufferBackwardWithGM = function storeBufferBackwardWi
in this.buffer will be the last (highest) one in memory.
"chars": the number of characters to store, starting at "offset" in the buffer;
"mode": 0=BCLANSI, 1=ANSI; "words": maximum number of words to transfer.
The final character stored from the buffer is followed in memory by a group-mark,
assuming the word count is not exhausted. At exit, updates this.Daddress with the
final transfer address-1.
The final character stored from the buffer is followed in memory by sufficient
BIC "?" (@14) to fill out the word, assuming the word count is not exhausted.
At exit, updates this.Daddress with the final transfer address-1.
This routine ignores this.D23F, and does NOT update this.wordCount.
Returns the number of characters stored into memory from the buffer, plus one
for the group-mark */
for each "?" stored */
var addr = this.Daddress; // local copy of memory address
var buf = this.buffer; // local pointer to buffer
var c; // current character code
@@ -648,11 +670,14 @@ B5500IOUnit.prototype.storeBufferBackwardWithGM = function storeBufferBackwardWi
}
} // while !done
w += 0x1F*power; // set group mark in register
++s;
++count;
if (s > 0 && words > 0) { // partial word left to be stored
while (s < 8) {
w += 0x0C*power; // set "?" in register
power *= 64;
++s;
++count;
}
this.W = w;
if (overflow) {
this.AOFF = 1; // for display only
@@ -661,6 +686,7 @@ B5500IOUnit.prototype.storeBufferBackwardWithGM = function storeBufferBackwardWi
} else {
this.store(addr); // store the word in memory
}
--words;
if (addr > 0) {
--addr;
@@ -876,6 +902,7 @@ B5500IOUnit.prototype.initiateDatacomIO = function initiateDatacomIO(u) {
} else { // GM-terminated write
chars = this.fetchBufferWithGM(1, 57);
}
// Restore the starting memory address -- will be adjusted in finishDatacomWrite
this.Daddress = this.D % 0x8000;
u.write(this.boundFinishDatacomWrite, this.buffer, chars, this.D21F, this.DwordCount);

View File

@@ -3908,9 +3908,7 @@ B5500Processor.prototype.exitCharacterMode = function exitCharacterMode(inline)
//this.cc.B5500DumpTape("Flag Bit: Exit-Char-Mode"); // <<< DEBUG >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
}
} else { // flag bit is set
this.S = ((this.B - this.B % 0x8000)/0x8000) % 0x8000; // get address of MSCW
this.MSFF = 0; // AKA TFFF
this.SALF = 0;
this.S = (this.B % 0x40000000) >>> 15; // get address of MSCW
this.applyRCW(this.B, inline);
this.loadBviaS(); // B = [S], fetch the MSCW
--this.S; // delete the MSCW

View File

@@ -44,7 +44,7 @@
<br>The retro-B5500 project forum. The forum is open to everyone, but you must register first.
<li><a href="./webSite/UtilityMenu.html">Emulator Utilities</a>
<br>A set of utilities that run in your web browser for setting up and inspecting the emulator environment.
<br>A set of utilities that run in your web browser for inspecting and modifying the emulator environment.
<li><a href="https://github.com/retro-software/B5500-software">B5500 Software Collection</a>
<br>A collection of B5500 source code, including version 13 of the CUBE Library from 1971.
@@ -71,7 +71,7 @@ Copyright (c) 2013, Nigel Williams and Paul Kimpel &bull; Licensed under the
<a href="LICENSE.txt">MIT License</a>
</div>
<div id=lastModDiv>Revised
2018-12-30
2019-04-12
</div>
</body>

View File

@@ -0,0 +1,7 @@
CONT=\ 00000100
E UTIL/NEATUP("SRCE/B5500/SYMBOL/MAKCAST \ 00000200
MAKE SRCE/B5500/NEATUP/MAKCAST \ 00000300
MARGIN 0 INDENT 2 BEGINOFFSET 2 DECINDENT 2 DEFINEINDENT 24 \ 00000400
PROCINDENT 2 ELSEOFFSET 0 \ 00000500
LOCKCOMMENTS SET INDENTELSEIF SET INDENTTHENIF SET") 00000600
CONT 00000900

View File

@@ -4,7 +4,7 @@
<meta name="Author" content="Nigel Williams & Paul Kimpel">
<!--
2014-08-30 Original version.
2016-03-25 P.Kimpel Add getDBName() routine to take stroage name from ?db=... query string.
2016-03-25 P.Kimpel Add getDBName() routine to take storage name from ?db=... query string.
-->
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Script-Type" content="text/javascript">

319
tools/B5500DiskDump.html Normal file
View File

@@ -0,0 +1,319 @@
<!DOCTYPE html>
<head>
<title>B5500 Disk Subsystem Dumper</title>
<meta name="Author" content="Paul Kimpel">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<meta http-equiv="Content-Style-Type" content="text/css">
<script>
/***********************************************************************
* retro-b5500/tools B5500DiskDump.html
************************************************************************
* Copyright (c) 2012, Paul Kimpel.
* Licensed under the MIT License,
* see http://www.opensource.org/licenses/mit-license.php
************************************************************************
* B5500 Disk Subsystem Dumper
*
************************************************************************
* 2012-12-29 P.Kimpel
* Original version, from B5500LibMaintExtract.html.
* 2013-12-15 T.Sirianni
* From B5500ColdLoader.html, stripped out all but disk dumper, whizzed
* the output formatting up a bit.
***********************************************************************/
"use strict";
if (!window.indexedDB) { // for Safari, mostly
window.indexedDB = window.webkitIndexedDB || window.mozIndexedDB;
}
var BICtoANSIChar = [ // Index by 6-bit BIC to get ANSI character
"0", "1", "2", "3", "4", "5", "6", "7",
"8", "9", "#", "@", "?", ":", ">", "}",
"+", "A", "B", "C", "D", "E", "F", "G",
"H", "I", ".", "[", "&", "(", "<", "~",
"|", "J", "K", "L", "M", "N", "O", "P",
"Q", "R", "$", "*", "-", ")", ";", "{",
" ", "/", "S", "T", "U", "V", "W", "X",
"Y", "Z", ",", "%", "!", "=", "]", "\""];
var BCLANSItoBIC = [ // Index by 8-bit BCL-as-ANSI to get 6-bit BIC (upcased, invalid=>"?")
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 00-0F
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 10-1F
0x1C,0x1B,0x1F,0x00,0x20,0x1A,0x3B,0x0C,0x3D,0x2D,0x2A,0x30,0x10,0x2B,0x3C,0x11, // 20-2F
0x0C,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0D,0x2E,0x3E,0x1D,0x0E,0x0B, // 30-3F
0x0A,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x21,0x22,0x23,0x24,0x25,0x26, // 40-4F
0x27,0x28,0x29,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x3A,0x0C,0x1E,0x0C,0x0C, // 50-5F
0x0C,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x21,0x22,0x23,0x24,0x25,0x26, // 60-6F
0x27,0x28,0x29,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x2F,0x2C,0x0F,0x3F,0x0C, // 70-7F
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 80-8F
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 90-9F
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // A0-AF
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // B0-BF
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // C0-CF
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // D0-DF
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // E0-EF
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C]; // F0-FF
window.addEventListener("load", function() {
var configName = "CONFIG"; // database configuration store name
var dbName = "B5500DiskUnit"; // IDB database name
var dbVersion = undefined; // current IDB database version
var euSize = 200000; // model I size (5 Storage Units: 6MW or 48MC)
var euPrefix = "EU"; // prefix for EU object store names
var config = null; // copy of CONFIG store contents
var disk = null; // the IDB database object
var panel = document.getElementById("TextPanel");
/**************************************/
function $$(id) {
return document.getElementById(id);
}
/**************************************/
function spout(text) {
/* Appends "text"+NL as a new text node to the panel DOM element */
var e = document.createTextNode(text + "\n");
panel.appendChild(e);
$$("PageBottom").scrollIntoView();
}
/**************************************/
function clearPanel() {
/* Clears the text panel */
var kid;
while (kid = panel.firstChild) {
panel.removeChild(kid);
}
}
/**************************************/
function ANSItoString(bytes, bx, bLength, asBinary) {
/* Translates a portion of an ANSI byte array to a string and returns it.
"bytes" = the Uint8Array byte array
"bx" = 0-relative offset into "bytes"
"bLength" = number of bytes to translate
"asBinary" = if truthy, then binary translation is done; otherwise
B5500 BCLANSI translation is done */
var table = (asBinary ? ANSItoBIC : BCLANSItoBIC);
var text = "";
var x;
if (bLength < 0) {
bLength = -bLength;
}
for (x=0; x<bLength; x++) {
text += BICtoANSIChar[table[bytes[bx+x]]];
}
return text;
}
/**************************************/
function cannotconfigureDatabase(ev) {
alert("Database not created. Please use B5500indexedDBinit first.");
abort();
}
/**************************************/
function genericDBError(ev) {
/* Formats a generic alert when otherwise-unhandled database errors occur */
var disk = ev.currentTarget.result;
alert("Database \"" + disk.name + "\" error: " + ev.target.result.error);
}
/**************************************/
var have_prev = false;
var prev_value = 0;
var prev_length = 0;
var skipping = false;
function printit( restart, key, value, length ){
if( restart ) have_prev = 0;
if( !have_prev ) {
prev_value = value;
prev_length = length;
have_prev = true;
skipping = false;
spout(key + ": " + ANSItoString(value, 0, length));
} else {
var differ = 0;
if ( prev_length != length ) differ = 1;
else {
for ( var i = 0; i < length; i++ ) {
if( prev_value[i] != value[i] ) differ = 1;
}
}
if( differ ) {
spout(key + ": " + ANSItoString(value, 0, length));
prev_value = value;
prev_length = length;
} else {
if ( skipping ) spout("...");
}
skipping = differ;
}
}
/**************************************/
function dumpDisk() {
spout("===== START OF DISK DUMP =====");
dumpDiskEU(0, 2); // Can't ask for more than 2 eu-s to be dumped, disk.transaction hangs in dumpDiskEU
// after the second success. Not sure why...
}
/**************************************/
function dumpDiskEU(ieu, neus) {
if( neus <= 0 ) {
spout("===== END OF DISK DUMP =====");
return;
}
/* Dumps the disk from zero through sector endKey */
var endKey = 20;
var eustring = euPrefix + ieu;
var txn = disk.transaction(eustring,"readonly");
var eu = txn.objectStore(eustring);
var range = IDBKeyRange.upperBound(endKey);
var req = eu.openCursor(range);
var lastKey = -1;
spout("===== START OF " + eustring + " =====");
req.onsuccess = function(ev) {
var cursor = ev.target.result;
var restart;
if (cursor) {
restart = 0;
if (cursor.key-lastKey > 1) {
spout("----- " + (cursor.key-lastKey-1) + " unallocated segments -----");
restart = 1;
}
printit( restart, cursor.key, cursor.value, cursor.value.length);
/* spout(cursor.key + ": " + ANSItoString(cursor.value, 0, cursor.value.length)); */
lastKey = cursor.key;
cursor.continue();
} else {
if (endKey > lastKey) {
spout("----- " + (endKey-lastKey) + " unallocated segments thru " + endKey + " -----");
}
spout("===== END OF " + eustring + " =====");
dumpDiskEU( ++ieu, --neus );
}
};
}
/**************************************/
function openDatabase(name, version) {
/* Attempts to open the disk subsystem database for the specified "name"
and "version". Stores the IDB database object in "disk" if successful, or
stores null if unsuccessful */
var db = null;
var req;
req = window.indexedDB.open(name, version);
req.onerror = function(ev) {
alert("Cannot open disk database: " + ev.target.error);
};
req.onblocked = function(ev) {
alert("Database.open is blocked -- cannot continue");
};
req.onupgradeneeded = cannotconfigureDatabase;
req.onsuccess = function(ev) {
disk = ev.target.result; // save the object reference globally for later use
disk.onerror = genericDBError;
spout("Disk database opened: " + name + " #" + disk.version);
dumpDisk();
disk.transaction("CONFIG").objectStore("CONFIG").get(0).onsuccess = function(ev) {
config = ev.target.result;
};
};
}
/**************************************/
function checkBrowser() {
/* Checks whether this browser can support the necessary stuff */
var missing = "";
if (!window.File) {missing += ", File"}
if (!window.FileReader) {missing += ", FileReader"}
if (!window.FileList) {missing += ", FileList"}
if (!window.Blob) {missing += ", Blob"}
if (!window.ArrayBuffer) {missing += ", ArrayBuffer"}
if (!window.DataView) {missing += ", DataView"}
if (!window.indexedDB) {missing += ", IndexedDB"}
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;
}
}
/********** Start of window.onload() **********/
if (!checkBrowser()) {
openDatabase(dbName, dbVersion);
}
}, false);
</script>
<style>
BODY {
font-family: Arial, Helvetica, sans-serif;
font-size: small}
TABLE {
border-collapse: collapse}
TH {
vertical-align: bottom}
DIV#DiskRangeDiv {
display: none}
TBODY#DiskRangeBody {
font-family: Courier New, Courier, monospace}
.center {
text-align: center}
.rj {
text-align: right}
</style>
</head>
<body>
<div style="position:relative; width:100%; height:4em">
<div style="position:absolute; left:0; top:0; width:auto">
<img src="../webUI/retro-B5500-Logo.png" alt="retro-B5500 Logo" style="float:left">
&nbsp;Disk SubSystem Dumper
</div>
</div>
<div id=DiskRangeDiv>
<table id=DiskRangeTable border=1 cellspacing=0 cellpadding=1>
<thead>
<tbody id=DiskRangeBody>
</table>
<br><input id=DumpBtn type=button value="Dump" accessKey=L DISABLED>
</div>
<pre id=TextPanel>
</pre>
<div id=PageBottom>
</div>
</body>
</html>

View File

@@ -27,7 +27,7 @@
window.addEventListener("load", function() {
var configName = "CONFIG"; // database configuration store name
var dbName = "B5500TESTDISK"; // IDB database name
var dbName = "B5500DiskUnit"; // IDB database name
var directoryTop = 2000; // start of directory area
var directoryEnd = 3008; // end of directory area
var euSize = 200000; // model I size (5 Storage Units: 6MW or 48MC)

View File

@@ -0,0 +1,529 @@
<!DOCTYPE html>
<head>
<title>B5500 Disk Sector 0 Fixer Utility</title>
<meta name="Author" content="Paul Kimpel">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<meta http-equiv="Content-Style-Type" content="text/css">
<script>
/***********************************************************************
* retro-b5500/tools B5500DiskSeg0Fixer.html
************************************************************************
* Copyright (c) 2018, Paul Kimpel.
* Licensed under the MIT License,
* see http://www.opensource.org/licenses/mit-license.php
************************************************************************
* B5500 Disk Sector 0 Fixer Utility.
*
* This script opens an IndexedDB database in the browser and attempts to
* treat it as a B5500 disk image, finding a specified file in the disk
* directory structure, manipulating the header, and writing the header
* back to the directory. This is intended to be a customized one-timer
* sort of program, modified as necessary for the fix-up task at hand.
************************************************************************
* 2018-05-12 P.Kimpel
* Original version, from B5500DiskDirFixer.html.
***********************************************************************/
"use strict";
if (!window.indexedDB) { // for Safari, mostly
window.indexedDB = window.webkitIndexedDB || window.mozIndexedDB;
}
window.addEventListener("load", function() {
var configName = "CONFIG"; // database configuration store name
var dbName = "B5500DiskUnit"; // IDB database name
var directoryTop; // start of directory area
var directoryEnd; // end of directory area
var euPrefix = "EU"; // prefix for EU object store names
var config = null; // copy of CONFIG store contents
var disk = null; // the IDB database object
var panel = $$("TextPanel");
var BICtoANSI = [ // Index by 6-bit BIC to get 8-bit ANSI code
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37, // 00-07, @00-07
0x38,0x39,0x23,0x40,0x3F,0x3A,0x3E,0x7D, // 08-1F, @10-17
0x2B,0x41,0x42,0x43,0x44,0x45,0x46,0x47, // 10-17, @20-27
0x48,0x49,0x2E,0x5B,0x26,0x28,0x3C,0x7E, // 18-1F, @30-37
0x7C,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50, // 20-27, @40-47
0x51,0x52,0x24,0x2A,0x2D,0x29,0x3B,0x7B, // 28-2F, @50-57
0x20,0x2F,0x53,0x54,0x55,0x56,0x57,0x58, // 30-37, @60-67
0x59,0x5A,0x2C,0x25,0x21,0x3D,0x5D,0x22]; // 38-3F, @70-77
var BICtoBCLANSI = [ // Index by 6-bit BIC to get 8-bit BCL-as-ANSI code
0x23,0x31,0x32,0x33,0x34,0x35,0x36,0x37, // 00-07, @00-07
0x38,0x39,0x40,0x3F,0x30,0x3A,0x3E,0x7D, // 08-1F, @10-17
0x2C,0x2F,0x53,0x54,0x55,0x56,0x57,0x58, // 10-17, @20-27
0x59,0x5A,0x25,0x21,0x20,0x3D,0x5D,0x22, // 18-1F, @30-37
0x24,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50, // 20-27, @40-47
0x51,0x52,0x2A,0x2D,0x7C,0x29,0x3B,0x7B, // 28-2F, @50-57
0x2B,0x41,0x42,0x43,0x44,0x45,0x46,0x47, // 30-37, @60-67
0x48,0x49,0x5B,0x26,0x2E,0x28,0x3C,0x7E]; // 38-3F, @70-77
var ANSItoBIC = [ // Index by 8-bit ANSI to get 6-bit BIC (upcased, invalid=>"?")
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 00-0F
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 10-1F
0x30,0x3C,0x3F,0x0A,0x2A,0x3B,0x1C,0x0C,0x1D,0x2D,0x2B,0x10,0x3A,0x2C,0x1A,0x31, // 20-2F
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0D,0x2E,0x1E,0x3D,0x0E,0x0C, // 30-3F
0x0B,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x21,0x22,0x23,0x24,0x25,0x26, // 40-4F
0x27,0x28,0x29,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x1B,0x0C,0x3E,0x0C,0x0C, // 50-5F
0x0C,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x21,0x22,0x23,0x24,0x25,0x26, // 60-6F
0x27,0x28,0x29,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x2F,0x20,0x0F,0x1F,0x0C, // 70-7F
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 80-8F
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 90-9F
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // A0-AF
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // B0-BF
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // C0-CF
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // D0-DF
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // E0-EF
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C]; // F0-FF
var BCLANSItoBIC = [ // Index by 8-bit BCL-as-ANSI to get 6-bit BIC (upcased, invalid=>"?")
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 00-0F
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 10-1F
0x1C,0x1B,0x1F,0x00,0x20,0x1A,0x3B,0x0C,0x3D,0x2D,0x2A,0x30,0x10,0x2B,0x3C,0x11, // 20-2F
0x0C,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0D,0x2E,0x3E,0x1D,0x0E,0x0B, // 30-3F
0x0A,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x21,0x22,0x23,0x24,0x25,0x26, // 40-4F
0x27,0x28,0x29,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x3A,0x0C,0x1E,0x0C,0x0C, // 50-5F
0x0C,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x21,0x22,0x23,0x24,0x25,0x26, // 60-6F
0x27,0x28,0x29,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x2F,0x2C,0x0F,0x3F,0x0C, // 70-7F
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 80-8F
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 90-9F
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // A0-AF
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // B0-BF
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // C0-CF
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // D0-DF
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // E0-EF
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C]; // F0-FF
var pow2 = [ // powers of 2 from 0 to 52
0x1, 0x2, 0x4, 0x8,
0x10, 0x20, 0x40, 0x80,
0x100, 0x200, 0x400, 0x800,
0x1000, 0x2000, 0x4000, 0x8000,
0x10000, 0x20000, 0x40000, 0x80000,
0x100000, 0x200000, 0x400000, 0x800000,
0x1000000, 0x2000000, 0x4000000, 0x8000000,
0x10000000, 0x20000000, 0x40000000, 0x80000000,
0x100000000, 0x200000000, 0x400000000, 0x800000000,
0x1000000000, 0x2000000000, 0x4000000000, 0x8000000000,
0x10000000000, 0x20000000000, 0x40000000000, 0x80000000000,
0x100000000000, 0x200000000000, 0x400000000000, 0x800000000000,
0x1000000000000, 0x2000000000000, 0x4000000000000, 0x8000000000000,
0x10000000000000];
/**************************************/
function $$(id) {
return document.getElementById(id);
}
/**************************************/
function bitTest(word, bit) {
/* Extracts and returns the specified bit from the word */
var e = 47-bit; // word lower power exponent
var p; // bottom portion of word power of 2
if (e > 0) {
return ((word - word % (p = pow2[e]))/p) % 2;
} else {
return word % 2;
}
}
/**************************************/
function fieldIsolate(word, start, width) {
/* Extracts a bit field [start:width] from word and returns the field */
var le = 48-start-width; // lower power exponent
var p; // bottom portion of word power of 2
return (le == 0 ? word : (word - word % (p = pow2[le]))/p) % pow2[width];
}
/**************************************/
function spout(text) {
/* Appends "text"+NL as a new text node to the panel DOM element */
var e = document.createTextNode(text + "\n");
panel.appendChild(e);
$$("PageBottom").scrollIntoView();
}
/**************************************/
function clearPanel() {
/* Clears the text panel */
var kid;
while (kid = panel.firstChild) {
panel.removeChild(kid);
}
}
/**************************************/
function rtrim(s) {
/* Trims trailing spaces from "s" and returns the resulting string */
var m = s.match(/^(.*?) *$/);
return m[1];
}
/**************************************/
function padToLength(text, len) {
/* Converts the input string "text" to exactly "len" characters,
truncating or padding on the right with spaces as necessary */
var x = text.length;
if (x > len) {
return text.substring(0, len);
} else {
x = len-x;
while (x-- > 0) {
text += " ";
}
return text;
}
}
/**************************************/
function stringToANSI(text, bytes, bx, asBinary) {
/* Translates the characters in a string to upper case, and then to ANSI
byte-array format. "text" is the input string, "bytes" is the Uint8Array
output buffer, and "bx" is the offset into that output buffer. If "asBinary" is
truthy, the translation is binary, otherwise it is done as BCLANSI */
var len = text.length;
var table1 = (asBinary ? BICtoANSI : BICtoBCLANSI);
var utxt = text.toUpperCase();
var x;
bx = bx || 0;
for (x=0; x<len; x++) {
bytes[bx++] = table1[ANSItoBIC[utxt.charCodeAt(x) & 0xFF]];
}
}
/**************************************/
function wordsToANSI(words, wx, wLength, bytes, bx, asBinary) {
/* Translates an array of B5500 words to ANSI byte-array format.
"words" = the array of words
"wx" = the starting index in "words"
"wLength" = the number of words to translate
"bytes" = a Uint8Array array
"bx" = the starting index in "bytes" to store the translated data
"asBinary" = if truthy, then binary translation is done; otherwise
B5500 BCLANSI translation is done */
var c;
var table = (asBinary ? BICtoANSI : BICtoBCLANSI);
var w;
var x;
var y;
var z;
bx = bx || 0;
if (wLength < 0) {
wLength = -wLength;
}
for (x=0; x<wLength; x++) {
w = words[wx+x] || 0;
for (y=0; y<8; y++) {
z = w % 0x40000000000;
c = (w-z)/0x40000000000;
bytes[bx++] = table[c];
w = z*64;
}
}
}
/**************************************/
function wordsToString(words, wx, wLength, asBinary) {
/* Translates an array of B5500 words to a string and returns the string.
"words" = the array of words
"wx" = the starting index in "words"
"wLength" = the number of words to translate
"asBinary" = if truthy, then binary translation is done; otherwise
B5500 BCLANSI translation is done */
var c;
var table = (asBinary ? BICtoANSI : BICtoBCLANSI);
var text = "";
var w;
var x;
var y;
var z;
if (wLength < 0) {
wLength = -wLength;
}
for (x=0; x<wLength; x++) {
w = words[wx+x] || 0;
for (y=0; y<8; y++) {
z = w % 0x40000000000;
c = (w-z)/0x40000000000;
text += String.fromCharCode(table[c]);
w = z*64;
}
}
return text;
}
/**************************************/
function ANSItoWords(bytes, bx, bLength, words, wx, asBinary) {
/* Translates a portion of an ANSI byte array to a sequence of B5500 words.
"bytes" = the Uint8Array byte array
"bx" = 0-relative offset into "bytes"
"bLength" = number of bytes to translate
"words" = the word array
"wx" = 0-relative offset into "words" to store the translated data
"asBinary" = if truthy, then binary translation is done; otherwise
B5500 BCLANSI translation is done */
var cx = 0;
var w = 0;
var table = (asBinary ? ANSItoBIC : BCLANSItoBIC);
var x;
wx = wx || 0;
if (bLength < 0) {
bLength = -bLength;
}
for (x=0; x<bLength; x++) {
if (cx >= 8) {
words[wx++] = w;
w = cx = 0;
}
w = w*64 + table[bytes[bx+x]];
cx++;
}
while (cx++ < 8) {
w *= 64;
}
words[wx++] = w;
}
/**************************************/
function readDiskBlock(addr, segs, block, callback) {
/* Reads a block from the disk "eu" at "addr" for "segs" segments, translates
it to words in the "block" array, then calls "callback" passing the address
and block */
var bx = 0;
var eu;
var euAddr = addr % 1000000;
var euNr = (addr % 10000000 - euAddr)/1000000;
var euName = euPrefix + euNr.toString();
var endAddr = euAddr + segs - 1;
var nextAddr = euAddr;
var range = IDBKeyRange.bound(euAddr, endAddr);
var req;
var txn;
var x;
txn = disk.transaction(euName);
eu = txn.objectStore(euName);
req = eu.openCursor(range);
req.onsuccess = function(ev) {
var cursor = ev.target.result;
if (cursor) {
while (cursor.key > nextAddr) {
for (x=0; x<30; x++) {
block[bx++] = 0;
}
nextAddr++;
}
ANSItoWords(cursor.value, 0, 240, block, bx);
bx += 30;
nextAddr++;
cursor.continue();
} else {
while (nextAddr <= endAddr) {
for (x=0; x<30; x++) {
block[bx++] = 0;
}
nextAddr++;
}
callback(addr, block);
}
};
}
/**************************************/
function normalizeName(name) {
/* Normalizes the name string to match the way file names are stored
in the B5500 directory, i.e., with a leading zero and trailing spaces
to a length of 8 */
var s = "0" + name;
if (s.length > 8) {
s = s.substring(0, 8);
} else {
while (s.length < 8) {
s += " ";
}
}
return s;
}
/**************************************/
function genericDBError(ev) {
/* Formats a generic alert when otherwise-unhandled database errors occur */
var disk = ev.currentTarget.result;
alert("Database \"" + disk.name + "\" error: " + ev.target.result.error);
}
/**************************************/
function openDatabase(name, successor) {
/* Attempts to open the disk subsystem database for the specified "name".
Stores the IDB database object in "disk" if successful, or stores null
if unsuccessful. Also gets directoryTop from seg 0 */
var block = new Array(30);
var db = null;
var req;
req = window.indexedDB.open(name); // open current version
req.onerror = function(ev) {
alert("Cannot open disk database: " + ev.target.error);
};
req.onblocked = function(ev) {
alert("Database.open is blocked -- cannot continue");
};
req.onsuccess = function(ev) {
disk = ev.target.result; // save the object reference globally for later use
disk.onerror = genericDBError;
// alert("Disk database opened: " + name + " #" + disk.version);
disk.transaction("CONFIG").objectStore("CONFIG").get(0).onsuccess = function(ev) {
config = ev.target.result;
readDiskBlock(0, 1, block, function(addr, block) {
directoryTop = block[1];
directoryEnd = block[4];
successor();
});
};
};
}
/**************************************/
function getDBName(defaultName) {
/* Parses the URL query string for a "db=name" parameter. If "db" is
found, returns the corresponding name; if not found, returns "defaultName" */
var args;
var i;
var name;
var search = location.search.substring(1); // drop the "?"
var value = defaultName;
var x;
args = search.split("&");
for (x=args.length-1; x>=0; --x) {
i = args[x].indexOf("=");
if (i > 0 ) {
name = decodeURIComponent(args[x].substring(0, i));
if (name.toLowerCase() == "db") {
value = decodeURIComponent(args[x].substring(i+1));
break; // out of for loop
}
}
}
return value;
}
/**************************************/
function checkBrowser() {
/* Checks whether this browser can support the necessary stuff */
var missing = "";
if (!window.File) {missing += ", File"}
if (!window.FileReader) {missing += ", FileReader"}
if (!window.FileList) {missing += ", FileList"}
if (!window.Blob) {missing += ", Blob"}
if (!window.ArrayBuffer) {missing += ", ArrayBuffer"}
if (!window.DataView) {missing += ", DataView"}
if (!window.indexedDB) {missing += ", IndexedDB"}
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;
}
}
/********** Start of window.onload() **********/
if (!checkBrowser()) {
dbName = getDBName(dbName);
openDatabase(dbName, function callback() {
var block = new Array(30);
var buffer = new Uint8Array(240);
var eu;
var euName = euPrefix + "0";
var txn;
var x;
for (x=block.length-1; x>=0; --x) {
block[x] = 0;
}
block[ 0] = 1; // sys number
block[ 1] = 2000; // DRCTRYTP
block[ 4] = 3604; // DIRECT
block[12] = 8610; // MCP disk address
wordsToANSI(block, 0, 30, buffer, 0);
stringToANSI("0MCP 0DISK ", buffer, 10*8);
stringToANSI("0INT 0DISK ", buffer, 13*8);
txn = disk.transaction([euName], "readwrite");
txn.oncomplete = function(ev) {
alert("Seg 0 fix-up completed successfully");
};
eu = txn.objectStore(euName);
eu.put(buffer, 0);
});
}
}, false);
</script>
<style>
BODY {
font-family: Arial, Helvetica, sans-serif;
font-size: small}
TABLE {
border-collapse: collapse}
TH {
vertical-align: bottom}
.center {
text-align: center}
.rj {
text-align: right}
.mono {
font-family: Courier New, Courier, monospace}
</style>
</head>
<body>
<div style="position:relative; width:100%; height:3em">
<div style="position:absolute; left:0; top:0; width:auto">
<img src="../webUI/resources/retro-B5500-Logo.png" alt="retro-B5500 Logo" style="float:left">
&nbsp;Disk Sector 0 Fixer Utility
</div>
</div>
<pre id=TextPanel>
</pre>
<div id=PageBottom>
</div>
</body>
</html>

View File

@@ -14,7 +14,7 @@
* Licensed under the MIT License,
* see http://www.opensource.org/licenses/mit-license.php
************************************************************************
* B5500 Library Maintenance tape file direectory list.
* B5500 Library Maintenance tape file directory list.
*
* This script reads a Burroughs B5500 Library/Maintenance tape as one
* large blob and outputs directory information for all files.
@@ -34,11 +34,14 @@
************************************************************************
* 2013-06-06 P.Kimpel
* Original version, from B5500LibMaintMapper.html and B5500DiskDirList.html.
* 2018-05-14 P.Kimpel
* Add "ShowRows=1" URL parameter to optionally show row addresses.
***********************************************************************/
"use strict";
window.onload = function() {
var panel = document.getElementById("TextPanel");
var showRows = false;
var tapeMark = 0x8F;
var tapeDir = [];
@@ -437,14 +440,17 @@ window.onload = function() {
appendCell(row, formatJulianDate(header.logCreationDate), "rj");
appendCell(row, formatB5500Time(header.logCreationTime), "rj");
text = "";
for (rx=header.maxRows-1; rx>=0; rx--) {
if (text || header.rowAddress[rx]) {
text = header.rowAddress[rx].toFixed(0) + " " + text;
if (showRows) {
text = "";
for (rx=header.maxRows-1; rx>=0; rx--) {
if (text || header.rowAddress[rx]) {
text = header.rowAddress[rx].toFixed(0) + " " + text;
}
}
appendCell(row, text);
}
appendCell(row, text);
body.appendChild(row);
}
@@ -535,6 +541,35 @@ window.onload = function() {
reader.readAsArrayBuffer(f);
}
function getOptions() {
/* Parses the URL query string for parameters and sets their global variables */
var args;
var i;
var name;
var search = location.search.substring(1); // drop the "?"
var value;
var x;
args = search.split("&");
for (x=args.length-1; x>=0; --x) {
i = args[x].indexOf("=");
if (i <= 0 ) {
name = decodeURIComponent(args[x]);
value = "";
} else {
name = decodeURIComponent(args[x].substring(0, i));
value = decodeURIComponent(args[x].substring(i+1));
}
if (name.toLowerCase() == "showrows") {
showRows = true;
break; // out of for loop
}
}
return value;
}
function checkBrowser() {
/* Checks whether this browser can support the necessary stuff */
var missing = "";
@@ -558,7 +593,14 @@ window.onload = function() {
if (checkBrowser()) {
return;
}
getOptions();
document.getElementById("FileSelector").addEventListener("change", fileSelector_onChange, false);
if (showRows) {
var cell = document.createElement("th");
cell.appendChild(document.createTextNode("Row Addresses"));
document.getElementById("header1").appendChild(cell);
}
}
</script>
@@ -579,7 +621,7 @@ TR TH {
<div style="position:relative; width:100%; height:3em">
<div style="position:absolute; left:0; top:0; width:auto">
retro-B5500 LibMaint Tape Extract Utility
retro-B5500 LibMaint Tape Directory Utility
</div>
<div style="position:absolute; top:0; right:0; width:auto">
<input id=FileSelector type=file size=60>
@@ -592,7 +634,7 @@ TR TH {
<table id=DirListTable border=1 cellspacing=0 cellpadding=1>
<thead>
<tr>
<tr id=header1>
<th>Tape File
<th>Disk Name
<th>Class
@@ -609,7 +651,6 @@ TR TH {
<th>Last Access
<th>Log Date
<th>Log Time
<th>Row Addresses
<tbody id=DirListBody>
</table>

57
tools/DUMPTAP-XIII.card Normal file
View File

@@ -0,0 +1,57 @@
14M90+KI$|#0|00MM)290+JI"000000D4*342L05000V10JI18JI0)0)000S0QKI000W0HKI000,08KI000]=/1V082I08JI0417+E0M16+E[)|/EV+EBV+E}V+E?V*)*/}V000M16+E:)B/1VB),/4V4J1>50JI
000000004J8#8QSI002(0-83290000BI0H84MJ2*08/I4(8,0?/I4:5|0+/I0431042(|62(01000160
00000000082(|0000?2(4(000+2(0000000000000Q/I0000000000000 /I00000U/I000001000170
00000000000000000000000000000000000000000000000000000000000000000000000001000200
00000000000000000000000000000000000000000000000000000000000000000000000001000210
0000000000000000042(000000000000000000000000000000000000000000000000000001000220
00000000000000000000000000000000000000000000000000000000000000000000000001000230
00000000000000000000000000000000000000000000000000000000000000000000000001000240
00000000000000000000000000000000000000000000000000000000000000000000000001000250
00000000000000000000000000000000000000000000000000000000000000000000000001000260
00000000000000000000000000000000000000000000000000000000000000000000000001000270
00000000000000000000000000000000000000000000000000000000000000000000000001000300
00000000000000000000000000000000000000000000000000000000000000000000000001000310
00000000000000000000000000000000000000000000000000000000000000000000000001000320
00000000000000000000000000000000000000000000000000000000000000000000000001000330
00000000Q000000000000000= E0006(00000000000000000000000000000000Q |0003C01000340
00000000Q <0003TQ }0004AQ C0004|= 20004T= 40004V00000000000000000000000001000350
00000000" 30004Z= 70004!= 300053= @00056= .0005A]S.0002.= 30005*= 80005;01000360
00000000= >0005W= I000648&+A0?AJ88+A@#0)4J9O,)3/4V1J8?8A0!R)#/AV8+4A8>0401000370
00000000=)H/1V8D8A04=)&/1V8H4A4J8.960R4J009K4J009>4J00009.4J149>4J08|09.01000400
000000004J289>4J0+@>0)9.4J0!00@B0)@F0)831J924J3?9>4J0008@.0)H&8@924J0H@<01000410
000000000)9.@K0)0 SI0)0)0H150000000000+0000000"/000000]A000000&|000000H001000420
00000000000000|04J000|8]6031048@924J008]9.8]|0118!8A:60)2E0DAI:#0)8!JA4J01000430
00000000000|8]048@924J8S0+2I8]8I8!JA4J008]9.8]00KE0H2I:60)8]318!JA8]|01101000440
000000008!KA008E?E2|1I4J049K4J8.960R4J8M+A001J10MJ2*14}510000?AJ0008AJ?001000450
00000000/I0)0)0)000000Y000000100000000000000000000000000000000000000000001000460
00000000000000000000000000000000000000000000000000000000000000000000000001000470
00000000000000000000000000000000000000000000000000000000000000000000000001000500
00000000000000000000000000000000000000000000000000000000000000000000000001000510
00000000000000000000000000000000000000000000000000000000000000000000000001000520
00000000000000000000000000000000000000000000000000000000000000000000000001000530
00000000000000000000000000000000000000000000000000000000000000000000000001000540
00000000000000000000000000000000000000000000000000000000000000000000000001000550
00000000000000004J041{4A1{0008M9290?JI0)J)#N00ME0 1I1 0UMJ142*35102&JI0)01000560
000000000S1?JI0)0W1&JI0)0,1-JI0)0]1!JI0)R|00PY204J8410MJ2*14+$!5!50R10D901000570
00000000WHICH TAPE?~0000COULDNT WRITE-TRY AGAIN~COULDNT READ-FORGET IT ~01000600
00000000ABCDEFHJKLMNPRST LABEL 000000000MDUMP 00199365019936500000640001000610
00000000000640000000051300513000002900|44A|62(000016184A4J8;|44A1>184A|601000620
000000002(ITE-TR2*143L3$|5|50R4L05004A|600Y7M94J8;8YKA004E0|1I8,8X1J+AK)01000630
00000000CN|44A|60D4:00ME1M1I|62(4JY68$1J9600ME08AI4(1I8,004J86Y61188+AMJ01000640
000000002B8W104J88+A <1J96004E0+BI|60411|4KA381E1?1I4J0D9#000?1I4(0)0)0)01000650
000000001QQ0K+0000000MKI4J8B964J8F9611|44A4JY68>1J96|48A004E4Y2I|6,)@N8,01000660
000000008X1J+A:)8N1:4:8,8X1J+A2)@N4:1:3M2I|#0411|88A0 1E0 AI4J8.96|44AY601000670
00000000044E2H2I4J089#048@0Q8$8E4A080?SI8,8@008E4A8,04118Y8A1+2E0?AI8>0Q01000700
00000000S)#/#V8?4A4J049B9FKI4(00Y#8@Y68E4A4JY#9B4(9611|48>00()#/IV8?4A0001000710
000000008@00=!S)2/#V8E4A4J009B8> #$)#/+V8?4A4(0)00000815Y61H2I4J1+008|+A01000720
00000000041J88+A928>1+S)#/#V8?4A4J009B4J9<4J0Q008$0Q1J88+A928>0QS)#/#V8?01000730
000000004A4J009B8>|4S)#/#V8?4A4J9<4(4J8.004J009#4J88+A/<1J9600ME08AI0)0001000740
000000004J88+A8|+A001J8$0|1JMJ3* D2N1I4{24E$8! 0R244>1!0<~E9N<E2N01000750
000000001"4P1}1/1N1}@{2*5I14MD2N1I1P}PTD2N1I1P#P1K+$1 2N0O3P1|1H0R5J108Y01000760
00000000KA002E8,14KE4:5|1I8,0431|4JA|62(7|00|0008&+A0?AJ8Q+A F1J8Q4A88+A01000770
00000000MI"!S)#/#V884A1?0!KI0)0)7|0000008,831J1#8E4A8,04118Y8A1H2E0?AI1-01001000
000000000DSI0)0)8,831J8,2011831J1#8E8A8E4A8,04118Y8A302E0DAI0-831J8U4A4J01001010
000000000H84MJ2*8X104(8,00000000000000000000000000000000000000000000000001001020
00000000000000000000000000000000000000000000000000000000000000000000000001001030
00000000000000000000000000000000000000000000000000000000000000000000000001001040
00000000=000000#04*)H/}VY6044A4("000000:2*14"$"50R004J0O4J70100S0|JI000001000011

View File

@@ -97,6 +97,16 @@ B5500CardPunch.prototype.copyStacker = function copyStacker(ev) {
});
this.emptyStacker(stacker);
if (stacker == this.stacker1) {
this.stacker1Count = 0;
this.$$("CPStacker1Bar").value = 0;
this.$$("CPStacker1Full").classList.remove("annunciatorLit");
} else if (stacker == this.stacker2) {
this.stacker2Count = 0;
this.$$("CPStacker2Bar").value = 0;
this.$$("CPStacker2Full").classList.remove("annunciatorLit");
}
ev.preventDefault();
ev.stopPropagation();
};

View File

@@ -34,6 +34,7 @@ function B5500ConsolePanel(global, autoPowerUp, shutDown) {
this.cc; // B5500CentralControl object
this.ccLatches = [0, 0, 0]; // I/O- & interrupt-reporting latches
this.ccLightsMap = new Array(6); // Misc annunciator DOM objects
this.enableLampTest = false; // Perform lamp test at power-on
this.global = global; // Global window object
this.intLightsMap = new Array(48); // Interrupt annunciator DOM objects
this.lastInterruptMask = 0; // Prior mask of interrupt annunciator lights
@@ -67,7 +68,7 @@ B5500ConsolePanel.annOffColor = "#333"; // annunciator lamp off color
/**************************************/
B5500ConsolePanel.prototype.$$ = function $$(id) {
return this.doc.getElementById(id);
}
};
/**************************************/
B5500ConsolePanel.prototype.setAnnunciators = function setAnnunciators(showEm) {
@@ -78,7 +79,7 @@ B5500ConsolePanel.prototype.setAnnunciators = function setAnnunciators(showEm) {
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) {
@@ -87,7 +88,7 @@ B5500ConsolePanel.prototype.evaluateNotReady = function evaluateNotReady(config)
var lampClass = "whiteButton";
switch (false) {
case config.PA.enabled || config.PA.enabled:
case config.PA.enabled || config.PB.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:
@@ -97,7 +98,7 @@ B5500ConsolePanel.prototype.evaluateNotReady = function evaluateNotReady(config)
}
this.$$("NotReadyBtn").className = lampClass;
}
};
/**************************************/
B5500ConsolePanel.prototype.focusConsole = function focusConsole() {
@@ -105,7 +106,7 @@ B5500ConsolePanel.prototype.focusConsole = function focusConsole() {
this.window.focus();
this.$$("LoadBtn").focus();
}
};
/**************************************/
B5500ConsolePanel.prototype.BurroughsLogo_Click = function BurroughsLogo_Click(ev) {
@@ -113,7 +114,7 @@ B5500ConsolePanel.prototype.BurroughsLogo_Click = function BurroughsLogo_Click(e
this.showAnnunciators = !this.showAnnunciators;
this.setAnnunciators(this.showAnnunciators);
}
};
/**************************************/
B5500ConsolePanel.prototype.B5500Logo_Click = function B5500Logo_Click(ev) {
@@ -127,7 +128,7 @@ B5500ConsolePanel.prototype.B5500Logo_Click = function B5500Logo_Click(ev) {
this.$$("ConfigLabel").style.display = "none";
sysConfig.openConfigUI();
}
}
};
/**************************************/
B5500ConsolePanel.prototype.PowerOnBtn_Click = function PowerOnBtn_Click(ev) {
@@ -159,7 +160,7 @@ B5500ConsolePanel.prototype.PowerOnBtn_Click = function PowerOnBtn_Click(ev) {
that.$$("PowerOnBtn").className = "greenButton greenLit";
that.$$("SysConfigName").textContent = config.configName;
that.$$("StorageName").textContent = config.units.DKA.storageName;
if (that.showAnnunciators) {
if (that.enableLampTest && that.showAnnunciators) {
that.lampTest(applyPower.bind(that), config);
} else {
applyPower(config);
@@ -169,7 +170,7 @@ B5500ConsolePanel.prototype.PowerOnBtn_Click = function PowerOnBtn_Click(ev) {
sysConfig.getSystemConfig(null, youMayPowerOnWhenReady_Gridley); // get current system config
return true;
}
};
/**************************************/
B5500ConsolePanel.prototype.PowerOffBtn_Click = function PowerOffBtn_Click(ev) {
@@ -198,7 +199,7 @@ B5500ConsolePanel.prototype.PowerOffBtn_Click = function PowerOffBtn_Click(ev) {
this.timer = 0;
}
return true;
}
};
/**************************************/
B5500ConsolePanel.prototype.HaltBtn_Click = function HaltBtn_Click(ev) {
@@ -213,7 +214,7 @@ B5500ConsolePanel.prototype.HaltBtn_Click = function HaltBtn_Click(ev) {
clearInterval(this.timer);
this.timer = 0;
}
}
};
/**************************************/
B5500ConsolePanel.prototype.LoadBtn_Click = function LoadBtn_Click(ev) {
@@ -250,7 +251,7 @@ B5500ConsolePanel.prototype.LoadBtn_Click = function LoadBtn_Click(ev) {
this.window.alert("cc.load() result = " + result);
break;
}
}
};
/**************************************/
B5500ConsolePanel.prototype.LoadSelectBtn_Click = function LoadSelectBtn_Click(ev) {
@@ -263,7 +264,7 @@ B5500ConsolePanel.prototype.LoadSelectBtn_Click = function LoadSelectBtn_Click(e
this.cc.cardLoadSelect = 1;
this.$$("LoadSelectBtn").className = "yellowButton yellowLit";
}
}
};
/**************************************/
B5500ConsolePanel.prototype.dumpState = function dumpState(caption) {
@@ -354,7 +355,7 @@ B5500ConsolePanel.prototype.dumpState = function dumpState(caption) {
B5500Util.openPopup(this.window, "./B5500FramePaper.html", "",
"location=no,resizable,scrollbars,status",
this, dumpStateOnLoad);
}
};
/**************************************/
B5500ConsolePanel.prototype.dumpTape = function dumpTape(caption) {
@@ -430,7 +431,7 @@ B5500ConsolePanel.prototype.dumpTape = function dumpTape(caption) {
B5500Util.openPopup(this.window, "./B5500FramePaper.html", "",
"location=no,resizable,scrollbars,status",
this, dumpTapeOnLoad);
}
};
/**************************************/
B5500ConsolePanel.prototype.displayCallbackState = function displayCallbackState() {
@@ -487,7 +488,7 @@ B5500ConsolePanel.prototype.displayCallbackState = function displayCallbackState
body.id = oldBody.id;
oldBody.parentNode.replaceChild(body, oldBody);
}
};
/**************************************/
B5500ConsolePanel.prototype.displayCentralControl = function displayCentralControl() {
@@ -550,7 +551,7 @@ B5500ConsolePanel.prototype.displayCentralControl = function displayCentralContr
unitBusyChange >>>= 1;
x--;
}
}
};
/**************************************/
B5500ConsolePanel.prototype.dasBlinkenlichten = function dasBlinkenlichten() {
@@ -706,7 +707,7 @@ B5500ConsolePanel.prototype.dasBlinkenlichten = function dasBlinkenlichten() {
this.displayCentralControl();
}
//this.displayCallbackState();
}
};
/**************************************/
B5500ConsolePanel.prototype.buildLightMaps = function buildLightMaps() {
@@ -730,7 +731,7 @@ B5500ConsolePanel.prototype.buildLightMaps = function buildLightMaps() {
spec = B5500CentralControl.unitSpecs[mnem];
this.perLightsMap[spec.unitIndex] = this.$$(mnem);
}
}
};
/**************************************/
B5500ConsolePanel.prototype.lampTest = function lampTest(callback, callbackParam) {
@@ -780,7 +781,7 @@ B5500ConsolePanel.prototype.lampTest = function lampTest(callback, callbackParam
this.$$("CentralControl").style.display = "block"; // overrides if !this.cc.poweredUp
switchEm(1);
setCallback(null, this, 2000, switchEm, 0);
}
};
/**************************************/
B5500ConsolePanel.prototype.beforeUnload = function beforeUnload(ev) {
@@ -819,7 +820,7 @@ B5500ConsolePanel.prototype.clearStatusLabel = function clearStatusLabel(inSecon
this.$$("StatusLabel").textContent = "";
this.statusLabelTimer = 0;
});
}
};
/**************************************/
B5500ConsolePanel.prototype.consoleOnload = function consoleOnload(ev) {

View File

@@ -376,7 +376,7 @@ B5500MagTapeDrive.prototype.loadTape = function loadTape() {
file = ev.target.files[0];
fileName = file.name;
x = fileName.lastIndexOf(".");
fileExt = (x > 0 ? fileName.substring(x) : "");
fileExt = (x > 0 ? fileName.substring(x) : "").toLowerCase();
writeRingCheck.checked = false;
tapeLengthSelect.disabled = true;
@@ -977,8 +977,8 @@ B5500MagTapeDrive.prototype.bcdReadForward = function bcdReadForward(oddParity)
var buffer = this.buffer; // IOUnit buffer
var bufLength = this.bufLength // IOUnit buffer length
var bufIndex = 0; // current IOUnit buffer offset
var c; // current character (tape image frame)
var cx; // current character translated to ASCII
var c = 0; // current character (tape image frame)
var cx = 0; // current character translated to ASCII
var image = this.image; // tape image
var imgLength = this.imgLength; // tape image length
var imgIndex = this.imgIndex; // current tape image offset
@@ -998,6 +998,10 @@ B5500MagTapeDrive.prototype.bcdReadForward = function bcdReadForward(oddParity)
c &= 0x7F; // zap the start-of-block bit
do {
if (c == 0x00) {
if (bufIndex > 0) {
this.errorMask |= 0x10; // dropout detected: no flux change
}
if (++blankCount > this.maxBlankFrames) {
this.errorMask |= 0x100000; // blank tape timeout
break; // kill the read loop
@@ -1057,8 +1061,8 @@ B5500MagTapeDrive.prototype.bcdReadBackward = function bcdReadBackward(oddParity
var buffer = this.buffer; // IOUnit buffer
var bufLength = this.bufLength // IOUnit buffer length
var bufIndex = 0; // current IOUnit buffer offset
var c; // current character (tape image frame)
var cx; // current character translated to ASCII
var c = 0; // current character (tape image frame)
var cx = 0; // current character translated to ASCII
var image = this.image; // tape image
var imgLength = this.imgLength; // tape image length
var imgIndex = this.imgIndex; // current tape image offset
@@ -1081,13 +1085,17 @@ B5500MagTapeDrive.prototype.bcdReadBackward = function bcdReadBackward(oddParity
} else {
do {
if (c == 0x00) {
if (bufIndex > 0) {
this.errorMask |= 0x10; // dropout detected: no flux change
}
if (++blankCount > this.maxBlankFrames) {
this.errorMask |= 0x100000; // blank tape timeout
break; // kill the read loop
} else if (imgIndex > 0) {
c = image[--imgIndex]; // get next char frame
} else {
break; // at end of tape, kill the read loop
break; // at beginning of tape, kill the read loop
}
} else {
blankCount = 0;
@@ -1137,6 +1145,7 @@ B5500MagTapeDrive.prototype.bcdWrite = function bcdWrite(oddParity) {
var buffer = this.buffer; // IOUnit buffer
var bufLength = this.bufLength // IOUnit buffer length
var bufIndex = 0; // current IOUnit buffer offset
var c = 0; // current tape character code
var image = this.image; // tape image
var imgLength = this.imgLength; // tape image length
var imgIndex = this.imgIndex; // current tape image offset
@@ -1148,13 +1157,24 @@ B5500MagTapeDrive.prototype.bcdWrite = function bcdWrite(oddParity) {
if (this.atBOT) {
this.setAtBOT(false);
}
image[imgIndex++] = xlate[buffer[bufIndex++] & 0x7F] | 0x80;
c = xlate[buffer[bufIndex++] & 0x7F];
if (c == 0) {
this.errorMask |= 0x10; // dropout detected: attempt to write no flux changes
}
image[imgIndex++] = c | 0x80;
while (bufIndex < bufLength) {
if (imgIndex >= imgLength) {
this.errorMask |= 0x04; // report not ready beyond end of tape
break;
} else {
image[imgIndex++] = xlate[buffer[bufIndex++] & 0x7F];
c = xlate[buffer[bufIndex++] & 0x7F];
if (c == 0) {
this.errorMask |= 0x10; // dropout detected: attempt to write no flux changes
}
image[imgIndex++] = c;
}
} // while
}

View File

@@ -24,6 +24,7 @@ function B5500SPOUnit(mnemonic, unitIndex, designate, statusChange, signal, opti
this.maxScrollLines = 5000; // Maximum amount of printer scrollback
this.charPeriod = 100; // Printer speed, milliseconds per character
this.printGreeting = false; // Print initial greeting message
this.mnemonic = mnemonic; // Unit mnemonic
this.unitIndex = unitIndex; // Ready-mask bit number
@@ -471,6 +472,16 @@ B5500SPOUnit.prototype.printText = function printText(msg, finish) {
this.endOfPaper.scrollIntoView();
};
/**************************************/
B5500SPOUnit.prototype.spoInitialize = function spoInitialize() {
/* Initializes the SPO after power-on */
this.setRemote();
this.appendEmptyLine("\xA0");
this.endOfPaper.scrollIntoView();
this.signal(-1); // re-focus the Console window
};
/**************************************/
B5500SPOUnit.prototype.spoOnload = function spoOnload(ev) {
/* Initializes the SPO window and user interface */
@@ -513,19 +524,14 @@ B5500SPOUnit.prototype.spoOnload = function spoOnload(ev) {
B5500SPOUnit.prototype.SPOAlgolGlyphsBtn_onclick.bind(this), false);
this.window.focus();
this.printText("retro-B5500 Emulator Version " + B5500CentralControl.version,
function initFinish() {
this.setRemote();
this.appendEmptyLine("\xA0");
this.endOfPaper.scrollIntoView();
this.signal(-1); // re-focus the Console window
}.bind(this));
// Kludge for Chrome window.outerWidth/Height timing bug
setCallback(null, this, 100, function chromeBug() {
this.window.moveTo(screen.availWidth-this.window.outerWidth,
screen.availHeight-this.window.outerHeight);
});
this.window.moveTo(screen.availWidth-this.window.outerWidth,
screen.availHeight-this.window.outerHeight);
if (this.printGreeting) {
this.printText("retro-B5500 Emulator Version " + B5500CentralControl.version,
B5500SPOUnit.prototype.spoInitialize);
} else {
this.spoInitialize();
}
};
/**************************************/

View File

@@ -86,12 +86,13 @@
* Redesign yet again the delay adjustment mechanism with one from the
* retro-205 project. Replace window.postMessage yield mechanism with one
* from the retro-220 project based on Promise().
* 2018-07-05 P.Kimpel
* Simplify delay and deviation adjustment algorithm.
***********************************************************************/
"use strict";
(function (global) {
/* Define a closure for the setCallback() mechanism */
var alpha = 0.25; // decay factor for delay deviation adjustment
var delayDev = {NUL: 0}; // hash of delay time deviations by category
var minTimeout = 4; // minimum setTimeout() threshold, milliseconds
var lastTokenNr = 0; // last setCallback token return value
@@ -151,11 +152,10 @@
to "fcn". If the delay is less than "minTimeout", a setImmediate-like mechanism
based on DOM Promise() will be used; otherwise the environment's standard
setTimeout mechanism will be used */
var adj = 0; // adjustment to delay and delayDev[]
var categoryName = (category || "NUL").toString();
var delay = callbackDelay || 0; // actual delay to be generated
var delayBias; // current amount of delay deviation
var thisCallback; // call-back object to be used
var delayBias = 0; // current amount of delay deviation
var thisCallback = null; // call-back object to be used
var token = ++lastTokenNr; // call-back token number
var tokenName = token.toString(); // call-back token ID
@@ -167,7 +167,14 @@
pool[poolLength] = null;
}
// Fill in the call-back object and tank it in pendingCallbacks.
thisCallback.startStamp = perf.now();
thisCallback.category = categoryName;
thisCallback.delay = delay;
thisCallback.context = context || this;
thisCallback.fcn = fcn;
thisCallback.arg = arg;
pendingCallbacks[tokenName] = thisCallback;
// Adjust the requested delay based on the current delay deviation
// for this category.
@@ -177,42 +184,19 @@
} else {
if (delayBias > 0) {
// We are delaying too much and should try to delay less.
if (delay < 0) {
adj = 0; // don't make delay any more negative
} else {
adj = -Math.min(delay, delayBias, minTimeout)*alpha;
if (delay > 0) { // don't make a negative delay any more so
delay -= Math.min(delay, delayBias, minTimeout);
}
} else { // delayBias < 0
} else { // delayBias <= 0
// We are delaying too little and should try to delay more.
if (delay < 0) {
if (delay - minTimeout < delayBias) {
adj = -delayBias;
} else {
adj = minTimeout - delay;
}
delay -= Math.max(delay, delayBias);
} else {
if (delay > minTimeout) {
adj = 0;
} else if (delay - minTimeout < delayBias) {
adj = -delayBias;
} else {
adj = minTimeout - delay;
}
delay += Math.min(-delayBias, minTimeout);
}
}
delay += adj;
delayDev[categoryName] += adj;
}
// Fill in the call-back object and tank it in pendingCallbacks.
thisCallback.category = categoryName;
thisCallback.delay = delay;
thisCallback.context = context || this;
thisCallback.fcn = fcn;
thisCallback.arg = arg;
pendingCallbacks[tokenName] = thisCallback;
// Decide whether to do a time wait or just a yield.
if (delay > minTimeout) {
thisCallback.cancelToken = global.setTimeout(activateCallback, delay, token);

Binary file not shown.

After

Width:  |  Height:  |  Size: 892 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 532 B

After

Width:  |  Height:  |  Size: 618 B