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:
@@ -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.
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 • Licensed under the
|
||||
<a href="LICENSE.txt">MIT License</a>
|
||||
</div>
|
||||
<div id=lastModDiv>Revised
|
||||
2018-12-30
|
||||
2019-04-12
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
7
source/E-mode/utilities/NEATUP.DO.wfl_m
Normal file
7
source/E-mode/utilities/NEATUP.DO.wfl_m
Normal 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
|
||||
@@ -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
319
tools/B5500DiskDump.html
Normal 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">
|
||||
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>
|
||||
@@ -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)
|
||||
|
||||
529
tools/B5500DiskSeg0Fixer.html
Normal file
529
tools/B5500DiskSeg0Fixer.html
Normal 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">
|
||||
Disk Sector 0 Fixer Utility
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<pre id=TextPanel>
|
||||
</pre>
|
||||
|
||||
<div id=PageBottom>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -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
57
tools/DUMPTAP-XIII.card
Normal 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
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
};
|
||||
|
||||
/**************************************/
|
||||
|
||||
@@ -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);
|
||||
|
||||
BIN
webUI/resources/B-NORMAL.png
Normal file
BIN
webUI/resources/B-NORMAL.png
Normal file
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 |
Reference in New Issue
Block a user