diff --git a/build-release.cmd b/build-release.cmd index 297dbc1..bf02a77 100644 --- a/build-release.cmd +++ b/build-release.cmd @@ -1 +1 @@ -"%ProgramFiles%\7-Zip\7z.exe" a -tzip releases\retro-b5500-%1.zip build-release.cmd emulator\ webui\ -x!webui\tools\* -x!webui\prototypes\* tools\*.html tools\*.job \ No newline at end of file +"%ProgramFiles%\7-Zip\7z.exe" a -tzip releases\retro-b5500-%1.zip build-release.cmd emulator\ webui\ -x!webui\prototypes\* tools\*.html tools\*.js tools\*.card \ No newline at end of file diff --git a/emulator/B5500CentralControl.js b/emulator/B5500CentralControl.js index a0565bb..7f45774 100644 --- a/emulator/B5500CentralControl.js +++ b/emulator/B5500CentralControl.js @@ -18,6 +18,7 @@ function B5500CentralControl(global) { this.mnemonic = "CC"; // Unit mnemonic this.global = global; // Javascript global object (e.g., "window" for browsers) + this.sysConfig = null; // System configuration object /* Global system modules */ this.DD = null; // Distribution & Display unit @@ -45,8 +46,7 @@ function B5500CentralControl(global) { // Instance variables and flags this.poweredUp = 0; // System power indicator - - this.unitStatusMask = 0; // Peripheral unit ready-status bitmask + this.unitStatusMask = 0; // Peripheral unit ready-status bitmask [must not be in clear()] this.PB1L = 0; // 0=> PA is P1, 1=> PB is P1 this.inhCCI03F = 0; // 0=> allow timer interrupts; 1=> inhibit 'em @@ -61,7 +61,7 @@ function B5500CentralControl(global) { /**************************************/ /* Global constants */ -B5500CentralControl.version = "0.20"; +B5500CentralControl.version = "1.00"; 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) @@ -113,7 +113,7 @@ B5500CentralControl.unitIndex = [ [null, 47,null, 46, 31, 45, 29, 44, 30, 43, 24, 42, 28, 41, 23, 40, 17, 39, 20, 38, 19, 37,null, 36,null, 35,null, 34,null, 33, 22, 32]]; -// The following object maps the unit mnemonics from B5500SystemConfiguration.units +// The following object maps the unit mnemonics from this.sysConfig.units // to the attributes needed to configure the CC unit[] array. B5500CentralControl.unitSpecs = { @@ -126,8 +126,8 @@ B5500CentralControl.unitSpecs = { CRB: {unitIndex: 23, designate: 14, unitClass: "B5500CardReader"}, CRA: {unitIndex: 24, designate: 10, unitClass: "B5500CardReader"}, CPA: {unitIndex: 25, designate: 10, unitClass: "B5500CardPunch"}, - LPB: {unitIndex: 26, designate: 26, unitClass: "B5500DummyPrinter"}, - LPA: {unitIndex: 27, designate: 22, unitClass: "B5500DummyPrinter"}, + LPB: {unitIndex: 26, designate: 26, unitClass: "B5500LinePrinter"}, + LPA: {unitIndex: 27, designate: 22, unitClass: "B5500LinePrinter"}, DKB: {unitIndex: 28, designate: 12, unitClass: "B5500DiskUnit"}, DKA: {unitIndex: 29, designate: 6, unitClass: "B5500DiskUnit"}, DRB: {unitIndex: 30, designate: 8, unitClass: null}, @@ -151,7 +151,7 @@ B5500CentralControl.unitSpecs = { /**************************************/ -B5500CentralControl.bindMethod = function bindMethod(f, context) { +B5500CentralControl.bindMethod = function bindMethod(context, f) { /* Returns a new function that binds the function "f" to the object "context". Note that this is a static constructor property function, NOT an instance method of the CC object */ @@ -205,7 +205,7 @@ B5500CentralControl.prototype.clear = function clear() { this.P2BF = 0; // Processor 2 busy FF this.HP2F = 0; // Halt processor 2 FF - this.ccLatch = 0x20; // I/O Unit busy & P2 latched status (reset by console UI) + this.ccLatch = 0; // I/O Unit busy & P2 latched status (reset by console UI) this.interruptMask = 0; // Interrupt status mask this.interruptLatch = 0; // Interrupt latched status (reset by console UI) this.iouMask = 0; // I/O Unit busy status mask @@ -214,10 +214,6 @@ B5500CentralControl.prototype.clear = function clear() { this.P1 = (this.PB1L ? this.PB : this.PA); this.P2 = (this.PB1L ? this.PA : this.PB); - if (!this.P2) { - this.P2BF = 1; // mark non-existent P2 as busy - this.ccLatch |= 0x10; - } if (this.PA) { this.PA.clear(); } @@ -624,23 +620,23 @@ B5500CentralControl.prototype.initiateIO = function initiateIO() { if (this.IO1 && this.IO1.REMF && !this.AD1F) { this.AD1F = 1; - this.iouMask |= 0x1; - this.ccLatch |= 0x1; + this.iouMask |= 0x01; + this.ccLatch |= 0x01; this.IO1.initiate(); } else if (this.IO2 && this.IO2.REMF && !this.AD2F) { this.AD2F = 1; - this.iouMask |= 0x2; - this.ccLatch |= 0x2; + this.iouMask |= 0x02; + this.ccLatch |= 0x02; this.IO2.initiate(); } else if (this.IO3 && this.IO3.REMF && !this.AD3F) { this.AD3F = 1; - this.iouMask |= 0x4; - this.ccLatch |= 0x4; + this.iouMask |= 0x04; + this.ccLatch |= 0x04; this.IO3.initiate(); } else if (this.IO4 && this.IO4.REMF && !this.AD4F) { this.AD4F = 1; - this.iouMask |= 0x8; - this.ccLatch |= 0x8; + this.iouMask |= 0x08; + this.ccLatch |= 0x08; this.IO4.initiate(); } else { this.CCI04F = 1; // set I/O busy interrupt @@ -785,33 +781,42 @@ B5500CentralControl.prototype.load = function load(dontStart) { this.clear(); // initialize P1/P2 configuration if (!this.P1 || this.P1.busy) { // P1 is busy or not available result = 1; - } else if (!this.testUnitReady(22)) { // SPO not ready - result = 2; - } else if (this.testUnitBusy(22)) { // SPO is busy - result = 3; + } else if (!this.testUnitReady(22)) { + result = 2; // SPO not ready + } else if (this.testUnitBusy(22)) { + result = 3; // SPO is busy + } else if (!(this.cardLoadSelect || this.testUnitReady(29))) { + result = 4; // DKA not ready + } else if (!this.cardLoadSelect && this.testUnitBusy(29)) { + result = 5; // DKA is busy } else { // ready to rock 'n roll + if (!this.P2) { + this.P2BF = 1; // mark non-existent P2 as busy + this.ccLatch |= 0x10; + } + this.nextTimeStamp = performance.now(); this.tock(); this.LOFF = 1; // set the Load FF if (this.IO1 && this.IO1.REMF && !this.AD1F) { this.AD1F = 1; - this.iouMask |= 0x1; - this.ccLatch |= 0x1; + this.iouMask |= 0x01; + this.ccLatch |= 0x01; this.IO1.initiateLoad(this.cardLoadSelect, boundLoadComplete); } else if (this.IO2 && this.IO2.REMF && !this.AD2F) { this.AD2F = 1; - this.iouMask |= 0x2; - this.ccLatch |= 0x2; + this.iouMask |= 0x02; + this.ccLatch |= 0x02; this.IO2.initiateLoad(this.cardLoadSelect, boundLoadComplete); } else if (this.IO3 && this.IO3.REMF && !this.AD3F) { this.AD3F = 1; - this.iouMask |= 0x4; - this.ccLatch |= 0x4; + this.iouMask |= 0x04; + this.ccLatch |= 0x04; this.IO3.initiateLoad(this.cardLoadSelect, boundLoadComplete); } else if (this.IO4 && this.IO4.REMF && !this.AD4F) { this.AD4F = 1; - this.iouMask |= 0x8; - this.ccLatch |= 0x8; + this.iouMask |= 0x08; + this.ccLatch |= 0x08; this.IO4.initiateLoad(this.cardLoadSelect, boundLoadComplete); } else { this.CCI04F = 1; // set I/O busy interrupt @@ -831,7 +836,7 @@ B5500CentralControl.prototype.loadTest = function loadTest(buf, loadAddr) { should not be used to load ESPOL "DECK" files */ var addr = loadAddr; // starting B5500 memory address var bytes = buf.byteLength; - var data = new DataView(buf); // use DataView() to avoid problems with littleendians. + var data = new DataView(buf); // use DataView() to avoid problems with little-endians. var power = 0x10000000000; var word = 0; var x = 0; @@ -987,7 +992,7 @@ B5500CentralControl.prototype.dumpSystemState = function dumpSystemState(caption writer(nr, "B=" + padOctal(px.B, 16) + " BROF=" + px.BROF); } - writer(0, "B5500 State Dump by " + (caption || "(unknown)") + " : " + new Date().toString()); + writer(0, "retro-B5500 State Dump by \"" + (caption || "(unknown)") + "\" : " + new Date().toString()); // Dump the processor states dumpProcessorState(this.P1, 1); @@ -1033,10 +1038,9 @@ B5500CentralControl.prototype.dumpSystemState = function dumpSystemState(caption }; /**************************************/ -B5500CentralControl.prototype.configureSystem = function configureSystem() { - /* Establishes the hardware module configuration from the - B5500SystemConfiguration module */ - var cfg = B5500SystemConfiguration; +B5500CentralControl.prototype.configureSystem = function configureSystem(cfg) { + /* Establishes the hardware module configuration from the system configuration + object "cfg" */ var mnem; var signal = null; var specs; @@ -1097,38 +1101,37 @@ B5500CentralControl.prototype.configureSystem = function configureSystem() { } } - // ***** !! inhibit for now ***** // this.DD = new B5500DistributionAndDisplay(this); - // Configure the processors - if (cfg.PA) {this.PA = new B5500Processor("A", this)} - if (cfg.PB) {this.PB = new B5500Processor("B", this)} + if (cfg.PA.enabled) {this.PA = new B5500Processor("A", this)} + if (cfg.PB.enabled) {this.PB = new B5500Processor("B", this)} // Determine P1/P2 this.PB1L = (cfg.PB1L ? 1 : 0); // Configure the I/O Units - if (cfg.IO1) {this.IO1 = new B5500IOUnit("1", this)} - if (cfg.IO2) {this.IO2 = new B5500IOUnit("2", this)} - if (cfg.IO3) {this.IO3 = new B5500IOUnit("3", this)} - if (cfg.IO4) {this.IO4 = new B5500IOUnit("4", this)} + if (cfg.IO1.enabled) {this.IO1 = new B5500IOUnit("1", this)} + if (cfg.IO2.enabled) {this.IO2 = new B5500IOUnit("2", this)} + if (cfg.IO3.enabled) {this.IO3 = new B5500IOUnit("3", this)} + if (cfg.IO4.enabled) {this.IO4 = new B5500IOUnit("4", this)} // Configure memory for (x=0; x<8; ++x) { - if (cfg.memMod[x]) { - this.addressSpace[x] = new ArrayBuffer(32768); // 4K B5500 words @ 8 bytes each + if (cfg.memMod[x].enabled) { + this.addressSpace[x] = new ArrayBuffer(4096*8); // 4K B5500 words @ 8 bytes each this.memMod[x] = new Float64Array(this.addressSpace[x]); } } // Configure the peripheral units for (mnem in cfg.units) { - if (cfg.units[mnem]) { + if (cfg.units[mnem].enabled) { specs = B5500CentralControl.unitSpecs[mnem]; if (specs) { unitClass = this.global[specs.unitClass || "B5500DummyUnit"]; if (unitClass) { u = new unitClass(mnem, specs.unitIndex, specs.designate, - makeChange(this, specs.unitIndex), makeSignal(this, mnem)); + makeChange(this, specs.unitIndex), makeSignal(this, mnem), + cfg.units[mnem]); this.unit[specs.unitIndex] = u; } } @@ -1139,12 +1142,13 @@ B5500CentralControl.prototype.configureSystem = function configureSystem() { }; /**************************************/ -B5500CentralControl.prototype.powerOn = function powerOn() { +B5500CentralControl.prototype.powerOn = function powerOn(config) { /* Powers up the system and establishes the hardware module configuration. - Redundant power-ons are ignored. */ + "config" is the system configuration object. Redundant power-ons are ignored. */ if (!this.poweredUp) { - this.configureSystem(); + this.sysConfig = config; + this.configureSystem(config); this.poweredUp = 1; } }; @@ -1154,7 +1158,7 @@ B5500CentralControl.prototype.powerOff = function powerOff() { /* Powers down the system and deallocates the hardware modules. Redundant power-offs are ignored. */ - function shutDown() { + function systemShutDown() { var x; if (this.timer) { @@ -1182,12 +1186,13 @@ B5500CentralControl.prototype.powerOff = function powerOff() { this.addressSpace[x] = null; } + this.clear(); this.poweredUp = 0; } if (this.poweredUp) { this.halt(); // Wait a little while for I/Os, etc., to finish - setCallback(this.mnemonic, this, 500, shutDown); + setCallback(this.mnemonic, this, 500, systemShutDown); } }; diff --git a/emulator/B5500IOUnit.js b/emulator/B5500IOUnit.js index 26fa7c5..d3aa4ae 100644 --- a/emulator/B5500IOUnit.js +++ b/emulator/B5500IOUnit.js @@ -106,7 +106,7 @@ B5500IOUnit.ANSItoBIC = [ // Index by 8-bit ANSI to get 6-bit BIC 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 + 0x27,0x28,0x29,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x1B,0x0C,0x3E,0x0C,0x1F, // 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 diff --git a/emulator/B5500Processor.js b/emulator/B5500Processor.js index c85cc04..c9d8a04 100644 --- a/emulator/B5500Processor.js +++ b/emulator/B5500Processor.js @@ -55,7 +55,7 @@ function B5500Processor(procID, cc) { /**************************************/ B5500Processor.cyclesPerMilli = 1000; // clock cycles per millisecond (1000 => 1.0 MHz) -B5500Processor.timeSlice = 4000; // this.run() timeslice, clocks +B5500Processor.timeSlice = 4000; // this.run() time-slice, clocks B5500Processor.delayAlpha = 0.999; // decay factor for exponential weighted average delay B5500Processor.slackAlpha = 0.9999; // decay factor for exponential weighted average slack @@ -2813,7 +2813,6 @@ B5500Processor.prototype.doublePrecisionMultiply = function doublePrecisionMulti this.I = (this.I & 0x0F) | 0xB0; // set I05/6/8: exponent-overflow this.cc.signalInterrupt(); } - /********** dumpState("Exponent Overflow in DLM"); ************************************/ } else if (eb < 0) { if (eb >= -63) { eb = (-eb) | 0x40; // set the exponent sign bit @@ -3059,8 +3058,10 @@ B5500Processor.prototype.computeRelativeAddr = function computeRelativeAddr(offs Manual. "cEnable" determines whether C-relative addressing is permitted. This offset must be in (0..1023) */ - if (this.SALF) { - this.cycleCount += 2; // approximate the timing + this.cycleCount += 2; // approximate the timing + if (!this.SALF) { + this.M = this.R*64 + (offset % 0x400); + } else { switch ((offset % 0x400) >>> 7) { case 0: case 1: @@ -3095,8 +3096,6 @@ B5500Processor.prototype.computeRelativeAddr = function computeRelativeAddr(offs } break; } // switch - } else { - this.M = this.R*64 + (offset % 0x400); } // Reset variant-mode R-relative addressing, if enabled @@ -3128,7 +3127,7 @@ B5500Processor.prototype.indexDescriptor = function indexDescriptor() { /* Indexes a descriptor and, if successful leaves the indexed value in the A register. Returns 1 if an interrupt is set and the syllable is to be exited */ - var aw = this.A; // local copy of A reg + var aw; // local copy of A reg var bw; // local copy of B reg var interrupted = 0; // fatal error, interrupt set var xe; // index exponent @@ -3137,7 +3136,8 @@ B5500Processor.prototype.indexDescriptor = function indexDescriptor() { var xs; // index mantissa sign var xt; // index exponent sign - this.adjustBFull(); + this.adjustABFull(); + aw = this.A; bw = this.B; xm = (bw % 0x8000000000); xe = (bw - xm)/0x8000000000; @@ -3173,21 +3173,24 @@ B5500Processor.prototype.indexDescriptor = function indexDescriptor() { // Now we have an integerized index value in xm if (!interrupted) { - if (xs && xm) { // oops... negative index + if (xs && xm) { + // Oops... index is negative interrupted = 1; if (this.NCSF) { this.I = (this.I & 0x0F) | 0x90; // set I05/8: invalid-index this.cc.signalInterrupt(); } - } else if (xm % 0x0400 >= (aw % 0x10000000000 - aw % 0x40000000)/0x40000000) { - interrupted = 1; // oops... index out of bounds + } else if (xm % 0x0400 < (aw % 0x10000000000 - aw % 0x40000000)/0x40000000) { + // We finally have a valid index + this.A = aw - aw % 0x8000 + (xm % 0x400 + aw)%0x8000; + this.BROF = 0; + } else { + // Oops... index not less than size + interrupted = 1; if (this.NCSF) { this.I = (this.I & 0x0F) | 0x90; // set I05/8: invalid-index this.cc.signalInterrupt(); } - } else { // we finally have a valid index - this.A = this.cc.fieldInsert(aw, 33, 15, aw % 0x8000 + xm % 0x400); - this.BROF = 0; } } @@ -3490,12 +3493,13 @@ B5500Processor.prototype.operandCall = function operandCall() { var aw = this.A; // local copy of A reg value var interrupted = 0; // interrupt occurred + // If A contains a simple operand, just leave it there, otherwise... if (aw >= 0x800000000000) { // It's not a simple operand switch ((aw % 0x800000000000 - aw % 0x100000000000)/0x100000000000) { // aw.[1:3] case 2: case 3: - // Present data descriptor + // Present data descriptor: see if it must be indexed if ((aw % 0x10000000000 - aw % 0x40000000)/0x40000000) { // aw.[8:10] interrupted = this.indexDescriptor(); // else descriptor is already indexed (word count 0) @@ -3503,10 +3507,10 @@ B5500Processor.prototype.operandCall = function operandCall() { if (!interrupted) { this.M = this.A % 0x8000; this.loadAviaM(); // A = [M] - if (this.A >= 0x800000000000 && this.NCSF) { - // Flag bit is set + if (this.A >= 0x800000000000 && this.NCSF) {// Flag bit is set this.I = (this.I & 0x0F) | 0x80; // set I08: flag-bit interrupt this.cc.signalInterrupt(); + dumpState("Flag Bit: OPDC"); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< DEBUG >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> } } break; @@ -3527,7 +3531,7 @@ B5500Processor.prototype.operandCall = function operandCall() { } break; - default: + default: // cases 4, 6 // Miscellaneous control word -- leave as is break; } @@ -3551,10 +3555,12 @@ B5500Processor.prototype.descriptorCall = function descriptorCall() { switch ((aw % 0x800000000000 - aw % 0x100000000000)/0x100000000000) { // aw.[1:3] case 2: case 3: - // Present data descriptor + // Present data descriptor: see if it must be indexed if ((aw % 0x10000000000 - aw % 0x40000000)/0x40000000) { // aw.[8:10] interrupted = this.indexDescriptor(); - this.A = this.cc.fieldInsert(this.A, 8, 10, 0); // set word count to zero + if (!interrupted) { + this.A = this.cc.fieldInsert(this.A, 8, 10, 0); // set word count to zero + } // else descriptor is already indexed (word count 0) } break; @@ -3575,7 +3581,7 @@ B5500Processor.prototype.descriptorCall = function descriptorCall() { } break; - default: + default: // cases 4, 6 // Miscellaneous control word this.A = this.M + 0xA00000000000; break; @@ -4278,7 +4284,7 @@ B5500Processor.prototype.run = function run() { this.adjustAEmpty(); this.computeRelativeAddr(opcode >>> 2, 1); this.loadAviaM(); - if (this.A >= 0x800000000000) { // if it's a control word, + if (this.A >= 0x800000000000) { // optimization: if it's a control word, this.operandCall(); // evaluate it } // otherwise, just leave it in A break; diff --git a/emulator/B5500SystemConfiguration.js b/emulator/B5500SystemConfiguration.js index 7499bb6..258bd94 100644 --- a/emulator/B5500SystemConfiguration.js +++ b/emulator/B5500SystemConfiguration.js @@ -1,72 +1,117 @@ /*********************************************************************** * retro-b5500/emulator B5500SystemConfiguration.js ************************************************************************ -* Copyright (c) 2012, Nigel Williams and Paul Kimpel. +* Copyright (c) 2012, 2014, Nigel Williams and Paul Kimpel. * Licensed under the MIT License, * see http://www.opensource.org/licenses/mit-license.php ************************************************************************ -* B5500 System Configuration module. +* B5500 System Configuration definition module. * -* This is presently a static Javascript object describing the hardware -* modules and peripherals attached to the system. +* This class defines the system configuration properties for the B5500 +* emulator. This is not used directly by the emulator, but serves as a +* central definition of the configuration properties and as a template +* from which actual configuration instances can be cloned. ************************************************************************ * 2012-06-30 P.Kimpel * Original version, from thin air. +* 2014-08-27 P.Kimpel +* Revise and implement as a constructor with prototype to support the +* new dynamic configuration mechanism. ***********************************************************************/ "use strict"; -var B5500SystemConfiguration = { +/**************************************/ +function B5500SystemConfiguration() { + /* Constructor for the global SystemConfiguration definition object */ + // ...nothing to construct at present... everything's in the prototype. +} - PA: true, // Processor A available - PB: false, // Processor B available +/**************************************/ +B5500SystemConfiguration.prototype.configLevel = 1; // configuration object version +B5500SystemConfiguration.prototype.sysDefaultConfigName = "Default"; +B5500SystemConfiguration.prototype.sysDefaultStorageName = "B5500DiskUnit"; - PB1L: false, // PA is P1 (false) | PB is P1 (true) +// Template for Datacom terminal unit (B487) definition object +B5500SystemConfiguration.prototype.sysDefaultTerminalUnit = { + enabled: true, // available in system + adapters: 1, // number of terminal interface adapters + buffers: 2, // number of 28-character buffers/adapter + pingPong: false // use ping-pong buffer management +}; - IO1: true, // I/O Unit 1 available - IO2: true, // I/O Unit 2 available - IO3: true, // I/O Unit 3 available - IO4: false, // I/O Unit 4 available +// Template for the global system configuration definition object +B5500SystemConfiguration.prototype.systemConfig = { + configLevel: B5500SystemConfiguration.prototype.configLevel, + configName: B5500SystemConfiguration.prototype.sysDefaultConfigName, - memMod: [ - true, // Memory module 0 available (4KW) - true, // Memory module 1 available (4KW) - true, // Memory module 2 available (4KW) - true, // Memory module 3 available (4KW) - true, // Memory module 4 available (4KW) - true, // Memory module 5 available (4KW) - true, // Memory module 6 available (4KW) - true], // Memory module 7 available (4KW) + PA: {enabled: true}, // Processor A available + PB: {enabled: false}, // Processor B available + + PB1L: false, // PA is P1 (false) | PB is P1 (true) + + IO1: {enabled: true}, // I/O Unit 1 available + IO2: {enabled: true}, // I/O Unit 2 available + IO3: {enabled: true}, // I/O Unit 3 available + IO4: {enabled: false}, // I/O Unit 4 available + + memMod: [ {enabled: true}, // Memory module 0 available (4KW) + {enabled: true}, // Memory module 1 available (4KW) + {enabled: true}, // Memory module 2 available (4KW) + {enabled: true}, // Memory module 3 available (4KW) + {enabled: true}, // Memory module 4 available (4KW) + {enabled: true}, // Memory module 5 available (4KW) + {enabled: true}, // Memory module 6 available (4KW) + {enabled: true}], // Memory module 7 available (4KW) units: { - SPO: true, // SPO keyboard/printer - DKA: true, // Disk File Control A - DKB: true, // Disk File Control B - CRA: true, // Card Reader A - CRB: false, // Card Reader B - CPA: true, // Card Punch A - LPA: true, // Line Printer A - LPB: false, // Line Printer B - PRA: false, // Paper Tape Reader A - PRB: false, // Paper Tape Reader B - PPA: false, // Paper Tape Punch A - PPB: false, // Paper Tape Punch A - DCA: true, // Data Communications Control A - DRA: false, // Drum/Auxmem A - DRB: false, // Drum/Auxmem B - MTA: true, // Magnetic Tape Unit A - MTB: true, // Magnetic Tape Unit B - MTC: true, // Magnetic Tape Unit C - MTD: true, // Magnetic Tape Unit D - MTE: false, // Magnetic Tape Unit E - MTF: false, // Magnetic Tape Unit F - MTH: false, // Magnetic Tape Unit H - MTJ: false, // Magnetic Tape Unit J - MTK: false, // Magnetic Tape Unit K - MTL: false, // Magnetic Tape Unit L - MTM: false, // Magnetic Tape Unit M - MTN: false, // Magnetic Tape Unit N - MTP: false, // Magnetic Tape Unit P - MTR: false, // Magnetic Tape Unit R - MTS: false, // Magnetic Tape Unit S - MTT: false} // Magnetic Tape Unit X + SPO: {enabled: true, // SPO keyboard/printer + algolGlyphs: false}, + + DKA: {enabled: true, // Disk File Control A + DFX: true, FPM: false, + storageName: B5500SystemConfiguration.prototype.sysDefaultStorageName}, + DKB: {enabled: false, // Disk File Control B + DFX: true, FPM: false, + storageName: B5500SystemConfiguration.prototype.sysDefaultStorageName}, + + CRA: {enabled: true}, // Card Reader A + CRB: {enabled: false}, // Card Reader B + CPA: {enabled: true, // Card Punch A + algolGlyphs: true}, + + LPA: {enabled: true, // Line Printer A + algolGlyphs: true}, + LPB: {enabled: false, // Line Printer B + algolGlyphs: true}, + + PRA: {enabled: false}, // Paper Tape Reader A + PRB: {enabled: false}, // Paper Tape Reader B + PPA: {enabled: false}, // Paper Tape Punch A + PPB: {enabled: false}, // Paper Tape Punch A + + DCA: {enabled: true, // Data Communications Control A + terminalUnits: { + TU1: B5500SystemConfiguration.prototype.sysDefaultTerminalUnit + }}, + + DRA: {enabled: false}, // Drum/Auxmem A + DRB: {enabled: false}, // Drum/Auxmem B + + MTA: {enabled: true}, // Magnetic Tape Unit A + MTB: {enabled: false}, // Magnetic Tape Unit B + MTC: {enabled: false}, // Magnetic Tape Unit C + MTD: {enabled: false}, // Magnetic Tape Unit D + MTE: {enabled: false}, // Magnetic Tape Unit E + MTF: {enabled: false}, // Magnetic Tape Unit F + MTH: {enabled: false}, // Magnetic Tape Unit H + MTJ: {enabled: false}, // Magnetic Tape Unit J + MTK: {enabled: false}, // Magnetic Tape Unit K + MTL: {enabled: false}, // Magnetic Tape Unit L + MTM: {enabled: false}, // Magnetic Tape Unit M + MTN: {enabled: false}, // Magnetic Tape Unit N + MTP: {enabled: false}, // Magnetic Tape Unit P + MTR: {enabled: false}, // Magnetic Tape Unit R + MTS: {enabled: false}, // Magnetic Tape Unit S + MTT: {enabled: false} // Magnetic Tape Unit T + } }; diff --git a/index.html b/index.html index 98c16c9..6c89be8 100644 --- a/index.html +++ b/index.html @@ -1,6 +1,6 @@ -retro-B5500 Emulator Test Site +retro-B5500 Emulator Hosting Site @@ -10,37 +10,44 @@ - retro A-CONTROL logo + retro A-CONTROL logo -

retro logo +

retro logo
- Burroughs B5500 Emulator Test Site + Burroughs B5500 Emulator Hosting Site

-

This site hosts the current test version of the retro-B5500 emulator, a web-browser based implementation of the legendary Burroughs B5500. +

This site hosts the current version of the retro-B5500 emulator, an implementation of the legendary Burroughs B5500 that runs in a web-browser. + +

+ Typical B5500 installation +

Main Links

@@ -52,7 +59,7 @@ Copyright (c) 2013, Nigel Williams and Paul Kimpel • Licensed under the MIT License
Revised - 2013-07-21 + 2014-07-19
diff --git a/tools/B5500.POWTEN.alg_m b/source/E-mode/utilities/B5500.POWTEN.alg_m similarity index 100% rename from tools/B5500.POWTEN.alg_m rename to source/E-mode/utilities/B5500.POWTEN.alg_m diff --git a/tools/BICTOEBCDIC.alg_m b/source/E-mode/utilities/BICTOEBCDIC.alg_m similarity index 100% rename from tools/BICTOEBCDIC.alg_m rename to source/E-mode/utilities/BICTOEBCDIC.alg_m diff --git a/tools/CODEDUMP55.alg_m b/source/E-mode/utilities/CODEDUMP55.alg_m similarity index 100% rename from tools/CODEDUMP55.alg_m rename to source/E-mode/utilities/CODEDUMP55.alg_m diff --git a/tools/EMODE.POWTEN.dat_m b/source/E-mode/utilities/EMODE.POWTEN.dat_m similarity index 100% rename from tools/EMODE.POWTEN.dat_m rename to source/E-mode/utilities/EMODE.POWTEN.dat_m diff --git a/tools/INCL2OMIT.alg_m b/source/E-mode/utilities/INCL2OMIT.alg_m similarity index 100% rename from tools/INCL2OMIT.alg_m rename to source/E-mode/utilities/INCL2OMIT.alg_m diff --git a/tools/NEATUP-ESPOLXEM.wfl_m b/source/E-mode/utilities/NEATUP-ESPOLXEM.wfl_m similarity index 100% rename from tools/NEATUP-ESPOLXEM.wfl_m rename to source/E-mode/utilities/NEATUP-ESPOLXEM.wfl_m diff --git a/tools/NEATUP.alg_m b/source/E-mode/utilities/NEATUP.alg_m similarity index 100% rename from tools/NEATUP.alg_m rename to source/E-mode/utilities/NEATUP.alg_m diff --git a/tools/NEATUP55.alg_m b/source/E-mode/utilities/NEATUP55.alg_m similarity index 100% rename from tools/NEATUP55.alg_m rename to source/E-mode/utilities/NEATUP55.alg_m diff --git a/tools/NEATUPINFO.alg_m b/source/E-mode/utilities/NEATUPINFO.alg_m similarity index 100% rename from tools/NEATUPINFO.alg_m rename to source/E-mode/utilities/NEATUPINFO.alg_m diff --git a/tools/xem/ALGOLXEM.alg_m b/source/E-mode/xem/ALGOLXEM.alg_m similarity index 100% rename from tools/xem/ALGOLXEM.alg_m rename to source/E-mode/xem/ALGOLXEM.alg_m diff --git a/tools/xem/ESPOLXEM.alg_m b/source/E-mode/xem/ESPOLXEM.alg_m similarity index 100% rename from tools/xem/ESPOLXEM.alg_m rename to source/E-mode/xem/ESPOLXEM.alg_m diff --git a/tests/ALGOLXEM/YUSPARA2.alg_m b/tests/ALGOLXEM/YUSPARA2.alg_m new file mode 100644 index 0000000..09dc0bb --- /dev/null +++ b/tests/ALGOLXEM/YUSPARA2.alg_m @@ -0,0 +1,355 @@ +$ SET LIST $ PRT DEBUGN 00000100120418PK +% YUSPARA 00336000 +% FREE STANDING YU/SPARROW ROUTINE -- 3/5/70 -- P H KIMPEL 00337000 +% TEST OF ALGEBRAIC "G" AND "DG" FUNCTIONS -- 8/8/70 -- PHK 00338000 +BEGIN 00339000 +FILE IN YUSPAR (1,10); 00340000 +FILE OUT OUTPUT 1 (2,17); 00341000120816PK +FORMAT 00342000 + F1 (//X10"H/R = "F4.1,X15"MU1/MU2 = "I5), 00343000 + F2 (2("A[J]"X16"B[J]"X20)/8(2(2(I3,E14.5,X3)X5)X5,2A6"="E13.5/), 00344000 + 2(I3,E14.5,X3)X55"Q1/Q2"X7"="E13.5), 00345000 + F3 (X19"YU/SPARROW ANALYSIS -- ALGEBRAIC """G""" FUNCTIONS"X8,I2, 00346000 + 2("/"A2)X11"PAGE:"I4), 00347000 + FE (//"RUN TOTALS:"), 00348000 + FT (/X9"PROCESSOR TIME: "R8.2,X15"ELAPSED TIME: "R8.2" SEC"); 00349000 +INTEGER 00350000 + I, J, % INDICIES. 00351000 + PT, % PROCESSOR TIME [1/64-S SEC] 00352000 + ET, % ELAPSED TIME [SAME]. 00353000 + PAG, % SET NUMBER. 00354000 + MO, % MONTH-OF-YEAR OF RUN. 00355000 + NPOINTS, % TOTAL # POINTS FOR APPROXIMATION. 00356000 + NA, % NUMBER OF A-PHASE COEFFICIENTS. 00357000 + NB, % NUMBER OF B-PHASE COEFFICIENTS. 00358000 + NAB, % NA + NB. 00359000 + N1 , % NUMBER OF POINTS ON ARC C1. 00360000 + N2, % NUMBER OF POINTS ON ARC C2. 00361000 + N12, % NUMBER OF POINTS ON ARC C12. 00362000 + KUSTAR, % COUNTER FOR "USTAR" 00363000 + NUSTAR, % COUNT LIMITS FOR USTAR. 00364000 + NSUSTAR; % DITTO. 00365000 +REAL 00366000 + H, % INTERFACE DISTANCE FROM PIPE CENTER. 00370000 + R, % PIPE RADIUS (= 1.0) 00371000 + MU1, % VISCOSITY OF THE MOST VISCOUS PHASE. 00372000 + MU2, % VISCOSITY OF THE LESS VISCOUS PHASE. 00373000 + PI, % USUAL MEANING: 3.14159... 00375000 + MU12, % MU1/MU2. 00376000 + ISUM, % USED BY "INTEGRALUSTAR". 00377000 + YSTRT, % DITTO 00378000 + YSTEP, % DITTO 00379000 + YEND, % DITTO 00380000 + XSTEP, % DITTO 00381000 + XEND, % DITTO 00382000 + XX, % COORDINATE WORKING VARIABLES. 00383000 + YY, % DITTO 00384000 + USUM, % WORKING VARIABLE VOR "INTEGRALUSTAR" 00385000 + Q1Q2, % Q1/Q2. 00386000 + X, Y, % WORKING VARIABLES. 00387000 + THETA1, % INTERFACE ANGLE FROM VERTICAL DIAMETER. 00388000 + ARCC1, % LENGTH OF ARC C1. 00388100 + ARCC2, % LENGTH OF ARC C2. 00388200 + ARCC12, % LENGTH OF ARC C12. 00388300 + DS1, % LENGTH OF ARC BETWEEN POINTS ON C1. 00388400 + DS2, % LENGTH OF ARC BETWEEN POINTS ON C2. 00388500 + DS12, % LENGTH OF ARC BETWEEN POINTS ON C12. 00388600 + TOTALARC; % ARCC1 + ARCC2 + ACRR12. 00388700 +LABEL JMP; 00389000 +ALPHA DA, YR; % DAY AND YEAR-OF-RUN. 00390000 +INTEGER ARRAY NDX1, NDX2, NAME1, NAME2 [0:7]; 00391000 +ARRAY CALC[0:7]; 00392000 +DEFINE Q1Q1FULL = CALC[0]#, Q2Q2FULL = CALC[1]#, Q1STARQ1FULL=CALC[2]#, 00393000 + Q2STARQ2FULL = CALC[3]#, TAB22 = CALC[4]#, QMU12 = CALC[5]#, 00394000 + Q1Q1STAR = CALC[6]#, Q2Q2STAR = CALC[7]#; 00395000 + % BEGIN EXECUTION IN OUTER BLOCK. 00396000 +FILL NDX1[*] WITH 1, 3, 4, 7, 8, 11, 12, 15; 00397000 +FILL NDX2[*] WITH 2, 5, 6, 9, 10, 13, 14, 17; 00398000 +FILL NAME1[*] WITH "Q1/Q1F", "Q2/Q2F", "Q1*/Q1", "Q2*/Q2", "TABLE ", 00399000 + "QMU12 ", "Q1/Q1*", "Q2/Q2*"; 00400000 +FILL NAME2[*] WITH "ULL ", "ULL ", "FULL ", "FULL ", "2.2 ", 00401000 + " ", " ", " "; 00402000 + PI:= 3.141592653589793; 00403000 + NPOINTS:= 100; NA:= NB:= 17; NAB:= NA + NB; 00404000 + R:= 1; PAG:= 2; 00405000 + DA:= TIME(0); YR:= DA.[29:12]; 00406000 + DA:= DA.[17:6]|100 + DA.[11:6]|10 + DA.[5:6]; 00407000120816PK + FOR I:= 31, IF (YR.[11:6]|10 + YR.[5:6])MOD 4 = 0 THEN 29 ELSE 28, 31,00408000120816PK + 30, 31, 30, 31, 31, 30, 31, 30, 31 DO 00409000 + BEGIN 00410000 + MO:= MO + 1; 00411000 + IF DA = I THEN DA:= DA-I ELSE GO TO JMP; 00412000 + END; 00413000 +JMP: DA:= (DA DIV 10)*64 + DA MOD 10; 00414000120816PK + 00415000 +FOR H:= -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8 DO 00416000 + FOR MU12:= 1, 2, 4, 10, 25, 100, 250, 1000 DO 00417000 + 00418000 +BEGIN % ***** INNER BLOCK ***** 00419000 + REAL ARRAY 00420000 + W[1:NPOINTS], 00421000 + Y[1:1, 1:NPOINTS+NAB], 00422000 + Z[1:NAB, 1:NPOINTS+NAB], 00423000 + COF[1:1, 1:NAB]; 00424000 + 00425000 +%***********************************************************************00426000 +REAL PROCEDURE G (I, X, Y); 00427000 + VALUE I, X, Y; REAL X, Y; INTEGER I; 00428000 + CASE (I - 1) OF 00429000 + BEGIN 00430000 + G:= 1; % 100431000 + G:= X; % 200432000 + G:= Y; % 300433000 + G:= X*2 - Y*2; % 400434000120816PK + G:= 2.0 | X | Y; % 500435000120816PK + G:= X*3 - 3.0 | X | Y*2; % 600436000120816PK + G:= 3.0 | X*2 | Y - Y*3; % 700437000120816PK + G:= X*4 + Y*4 - 6.0 | X*2 | Y*2; % 800438000120816PK + G:= 4.0 | X*3 | Y - 4.0 | X | Y*3; % 900439000120816PK + G:= X*5 - 10.0 | X*3 | Y*2 + 5.0 | X | Y*4; %1000440000120816PK + G:= Y*5 - 10.0 | Y*3 | X*2 + 5.0 | Y | X*4; %1100441000120816PK + G:= X*6 - 15.0 | X*4 | Y*2 + 15.0 | X*2 | Y*4 - Y*6; %1200442000120816PK + G:= 6.0 | X*5 | Y + 6.0 | X | Y*5 - 20.0 | X*3 | Y*3; %1300443000120816PK + G:= X*7 - 21.0|X*5 | Y*2 + 35.0|X*3 | Y*4 - 7.0|X | Y*6; %1400444000120816PK + G:= 7.0 |X*6 | Y - 35.0 | X*4 | Y*3 + 21.0 | X*2 | Y*5 - Y*7; %1500445000120816PK + G:= X*8 + Y*8 - 28.0 |X*6 | Y*2 + 70.0 | X*4 | Y*4 - 28.0 00446000120816PK + | X*2 | Y*6; %1600447000120816PK + G:= 8.0 | X*7 |Y - 56.0 | X*5 | Y*3 + 56.0 | X*3 | Y*5 00448000120816PK + - 8.0 |X | Y*7; %1700449000120816PK + END G; 00450000 + 00451000 +%***********************************************************************00452000 +REAL PROCEDURE DG (I, X, Y); 00453000 + VALUE I, X, Y; INTEGER I; REAL X, Y; 00454000 + CASE (I - 1) OF 00455000 + BEGIN 00456000 + DG:= 0.0; % 100457000 + DG:= 0.0; % 200458000 + DG:= 1.0; % 300459000 + DG:= -2.0 | Y; % 400460000120816PK + DG:= 2.0 | X; % 500461000120816PK + DG:= -6.0 | X |Y; % 600462000120816PK + DG:= 3.0 | X*2 - 3.0 | Y*2; % 700463000120816PK + DG:= 4.0 | Y*3 - 12.0 |X*2 | Y; % 800464000120816PK + DG:= 4.0 | X*3 - 12.0 | X | Y*2; % 900465000120816PK + DG:= -20.0 |X*3 | Y + 20.0 | X | Y*3; %1000466000120816PK + DG:= 5.0 | Y*4 - 30.0 | Y*2 |X*2 + 5.0 | X*4; %1100467000120816PK + DG:= -30.0 | X*4 |Y + 60.0 | X*2 | Y*3 - 6.0 | Y*5; %1200468000120816PK + DG:= 6.0 | X*5 + 30.0 | X | Y*4 - 60.0 | X*3 | Y*2; %1300469000120816PK + DG:= -42.0 | X*5 | Y + 140.0 | X*3 | Y*3 - 42.0 | X | Y*5; %1400470000120816PK + DG:= 7.0 | X*6 - 105.0 | X*4 | Y*2 + 105.0 | X*2 | Y*4 00471000120816PK + - 7.0 | Y*6; %1500472000120816PK + DG:= 8.0 |Y*7 - 56.0 | X*6 | Y + 280.0 | X*4 | Y*3 00473000120816PK + - 168.0 | X*2 | Y*5; %1600474000120816PK + DG:= 8.0 | X*7 - 168.0 | X*5 | Y*2 + 280.0 | X*3 | Y*4 00475000120816PK + - 56.0 | X | Y*6; %1700476000120816PK + END DG; 00477000 + 00478000 +%***********************************************************************00479000 +REAL PROCEDURE USTAR (I, X, Y); 00480000 + VALUE I, X, Y; INTEGER I; REAL X, Y; 00481000 + BEGIN 00482000 + NUSTAR:= IF I = 1 THEN NA ELSE NA + NB; 00483000 + NSUSTAR:= IF I = 1 THEN 1 ELSE NA + 1; 00484000 + USUM:= 0.0; 00485000 + FOR KUSTAR:= NSUSTAR STEP 1 UNTIL NUSTAR DO 00486000 + USUM:= USUM + COF[1,KUSTAR] | G(KUSTAR-NSUSTAR+1, X, Y); 00487000120816PK + USTAR:= USUM; 00488000 + END USTAR; 00489000 + 00490000 +%***********************************************************************00491000 +REAL PROCEDURE INTEGRALUSTAR (I); 00492000 + VALUE I; INTEGER I; 00493000 + BEGIN 00494000 + ISUM:= 0.0; 00495000 + IF I = 1 THEN BEGIN YSTRT:= H; YEND:= 0.9999; END 00496000 + ELSE BEGIN YSTRT:= -0.9999; YEND:= H; END; 00497000 + YSTEP:= (YEND - YSTRT)/30.00; 00498000 + FOR YY:= YSTRT STEP YSTEP UNTIL YEND DO 00499000 + BEGIN XSTEP:= (XX:= SQRT(1.0 - YY*2))/15.0; 00500000120816PK + FOR XX:= -XX STEP XSTEP UNTIL 0.0 DO 00501000 + ISUM:= ISUM + XSTEP | YSTEP | (USTAR (I, XX, YY) 00502000120816PK + - (XX*2 + YY*2)/4); 00503000120816PK + END; 00504000 + INTEGRALUSTAR:= 2.0 | ISUM; 00505000120816PK + END INTEGRALUSTAR; 00506000 + 00507000 +%***********************************************************************00508000 +REAL PROCEDURE ARCSIN (X); 00509000 + VALUE X; REAL X; 00510000 + ARCSIN:= ARCTAN(X/SQRT(1.0 - X*2)); 00511000120816PK + 00512000 +%***********************************************************************00513000 +REAL PROCEDURE EQUATION23 (A); 00514000 + VALUE A; REAL A; 00515000 + EQUATION23:= 0.5 - 2.0/3.0/PI | (A | (1.0 - A*2)*1.5 00516000120816PK + + 1.5 | A |SQRT(1.0 - A*2) + 1.5 | ARCSIN(A)); 00517000120816PK + 00518000 +%***********************************************************************00519000 + 00520000 +PROCEDURE ORTHO (W, Y, Z, N, M, P, COF); 00521000 +VALUE N, M, P; 00522000 +REAL ARRAY COF, W[1]; 00523000 +REAL ARRAY Y, Z [1, 1]; 00524000 +INTEGER N, M, P; 00525000 +% 00526000 +%COMMENT 00527000 +% -ORTHO- IS TAKEN FROM ACM ALGORITHM 127 [COMM. ACM, VOL.5, 00528000 +% OCTOBER 1962, P. 511, AUTHOR: PHILIP J. WALSH], 00529000 +% AND INCORPORATES THE SUGGESTIONS IN BARRODALE-S 00530000 +% CERTIFICATION [COMM. ACM, VOL.13, #2, FEB.1970, 122] 00531000 +% CODE REDUCED TO ONLY THAT NEEDED TO PERFORM LEAST-SQUARES 00532000 +% DETERMINATION OF COEFFICIENTS [4/70]. 00533000 +% .... P H KIMPEL 3/25/70 U OF DELAWARE 00534000 +% 00535000 +BEGIN 00536000 +INTEGER NPP, M1, N2, M2, R1, RBAR, P2, BEI, I, J, K, THI, ALI, 00537000 + OMI, R; 00538000 +REAL ARRAY PK, XP [1:N+P], QK[1:M+1], X[1:M+1, 1:N+P]; 00539000 +REAL SUM, DK2, DK; 00540000 +LABEL BOX1, BOX2, BOX3, BOX4, BOX5, BOX6, BOX7, OM1, OM2, BOX8, BOX9, 00541000 + TH1, TH2, TH3, BOX10, AL1, AL2, BOX12, BE1, BE2, BOX14, FINAL; 00542000 +SWITCH BE:= BE1, BE2; 00543000 +SWITCH TH:= TH1, TH2, TH3; SWITCH AL:= AL1, AL2; 00544000 +SWITCH OM:= OM1, OM2; 00545000 + NPP:= N + P; R:= 1; M1:= M-1; N2:= N+1; M2:= M+1; 00546000 + R1:= 0; RBAR:= R; P2:= P+1; BEI:= 1; 00547000 +BOX1: FOR I:= 1 STEP 1 UNTIL M DO BEGIN 00548000 + FOR J:= 1 STEP 1 UNTIL N DO 00549000 + X[I,J]:= Z[I,J] END; 00550000 +BOX2: FOR I:= 1 STEP 1 UNTIL M DO BEGIN 00551000 + FOR J:= N2 STEP 1 UNTIL NPP DO 00552000 + X[I,J]:= 0.0; X[I,N+I]:= 1.0 END; GO TO BOX3; 00553000 +BOX3: K:= 1; 00554000 +BOX4: THI:= 1; 00555000 +BOX5: ALI:= OMI:= 1; 00556000 + FOR J:= 1 STEP 1 UNTIL P DO PK[N+J]:= 0.0; 00557000 +BOX6: FOR I:= 1 STEP 1 UNTIL N DO 00558000 + PK[I]:= X[K,I] | W[I]; 00559000120816PK +BOX7: GO TO OM[OMI]; 00560000 + OM1: FOR I:= 1 STEP 1 UNTIL K DO BEGIN SUM:= 0.0; 00561000 + FOR J:= 1 STEP 1 UNTIL NPP DO 00562000 + SUM:= SUM + PK[J] | X[I,J]; QK[I]:= SUM END; 00563000120816PK + GO TO BOX8; 00564000 + OM2: DK2:= 0.0; FOR I:= 1 STEP 1 UNTIL NPP DO 00565000 + DK2:= DK2 + PK[I] | X[K,I]; 00566000120816PK + DK:= SQRT(DK2); 00567000 + FOR I:= 1 STEP 1 UNTIL NPP DO 00568000 + X[K,I]:= X[K,I]/DK;; 00569000 + OMI:= 1; GO TO BOX6; 00570000 +BOX8: FOR I:= 1 STEP 1 UNTIL K-1 DO 00571000 + QK[I]:= -QK[I]; QK[K]:= 1.0; 00572000 + FOR I:= 1 STEP 1 UNTIL NPP DO BEGIN 00573000 + SUM:= 0.0; FOR J:= 1 STEP 1 UNTIL K DO 00574000 + SUM:= SUM + X[J,I] | QK[J]; 00575000120816PK + XP[I]:= SUM END; GO TO BOX9; 00576000 +BOX9: GO TO TH[THI]; 00577000 + TH1: FOR I:= 1 STEP 1 UNTIL NPP DO 00578000 + X[K,I]:= XP[I]; GO TO BOX10; 00579000 + TH2: FOR I:= 1 STEP 1 UNTIL P DO 00580000 + COF[I]:= -XP[N+I]; THI:= 3; GO TO TH1; 00581000 + TH3: GO TO BOX14; 00582000 +BOX10: GO TO AL[ALI]; 00583000 + AL1: OMI:= ALI:= 2; GO TO BOX6; 00584000 + AL2: IF K < M THEN BEGIN K:= K + 1; GO TO BOX4; END 00585000120816PK + ELSE GO TO BOX12; 00586000 +BOX12: GO TO BE[BEI]; 00587000 + BE1: BEI:= THI:= 2; K:= K + 1; GO TO BOX14; 00588000 + BE2: GO TO BOX14; 00589000 +BOX14: IF RBAR = 0 THEN GO TO FINAL ELSE RBAR:= RBAR - 1; 00590000 + R1:= R1 + 1; THI:= 2; 00591000 + FOR I:= 1 STEP 1 UNTIL N DO 00592000 + X[M2,I]:= Y[R1,I]; 00593000 + FOR I:= 1 STEP 1 UNTIL P DO 00594000 + X[M2,N+I]:= 0.0; GO TO BOX5; 00595000 +FINAL: END ORTHO ; 00596000 +%***********************************************************************00597000 + 00598000 +%***********************************************************************00599000 +% BEGIN EXECUTION (INNER BLOCK) %00600000 +%***********************************************************************00601000 + ET:= TIME(1); PT:= TIME(2); 00602000 + COMMENT INITALIZE & SET UP DATA FOR -ORTHO-; 00604000 +%% CALCULATE ARC LENGTHS OF EACH INTERFACE. 00607000 + ARCC12:= 2.0 |SQRT(1.0 - H*2); 00608000120816PK + ARCC1:= 2.0 | (THETA1:= PI/2.0 - ARCTAN(2.0|H/ARCC12)); 00609000120816PK + ARCC2:= 2.0 |PI - ARCC1; 00610000120816PK +%% CALCULATE NO. OF POINTS ON EACH ARC. 00611000 + N1:= NPOINTS | ARCC1/(TOTALARC:= ARCC1 + ARCC2 + 2|ARCC12); 00612000120816PK + N2:= NPOINTS | ARCC2 / TOTALARC; 00613000120816PK + IF (N12:= NPOINTS - N1 - N2) MOD 2 = 0 THEN 00614000 + N12:= N12 DIV 2 00615000 + ELSE BEGIN 00616000 + N12:= N12 DIV 2 + 1; 00617000 + N2:= N2 - 1; 00618000 + END; 00619000 +%% CALCULATE THE LENGTH OF LINE SEGMENTS BETWEEN POINTS ON EACH 00620000 +%% INTERFACE. 00621000 + DS1:= ARCC1/(N1 - 1); 00622000 + DS2:= ARCC2/(N2 - 1); 00623000 + DS12:= ARCC12/(N12 - 1); 00624000 + 00625000 + FOR I:= 1 STEP 1 UNTIL NAB DO 00626000 + BEGIN 00627000 + FOR J:= 1 STEP 1 UNTIL N1 DO %% DATA FOR ARC C1. 00628000 + BEGIN 00629000 + W[J]:= 1; Y[1,J]:= 0.25; 00630000 + XX:= SIN(YY:= DS1|(J-1)-THETA1); YY:= COS(YY); 00631000120816PK + Z[I,J]:= IF I { NA THEN G(I, XX, YY) ELSE 0; 00632000120816PK + END; 00633000 + FOR J:= N1+1 STEP 1 UNTIL N1+N2 DO %% DATA FOR ARC C2. 00634000 + BEGIN 00635000 + W[J]:= DS1/DS2; Y[1,J]:= 0.25; 00636000 + XX:= SIN(YY:= -THETA1 - DS2|(J-N1-1)); YY:= COS(YY); 00637000120816PK + Z[I,J]:= IF I { NA THEN 0 ELSE G(I-NA, XX, YY); 00638000120816PK + END; 00639000 + FOR J:= N1+N2+1 STEP 1 UNTIL NPOINTS-N12 DO %% DATA FOR ARC C12.00640000 + BEGIN 00641000 + W[J]:= W[J+N12]:= DS12/DS1; 00642000 + Y[1,J]:= 0.25 | ((XX:= DS12|(J-N1-N2-1)-ARCC12/2)*2 + H*2) 00643000120816PK + | (1 - MU12); 00644000120816PK + Y[1,J+N12]:= 0; 00645000 + IF I { NA THEN 00646000120816PK + BEGIN 00647000 + Z[I,J]:= G(I, XX, H); 00648000 + Z[I,J+N12]:= DG(I, XX, H); 00649000 + END ELSE 00650000 + BEGIN 00651000 + Z[I,J]:= -G(I-NA, XX, H) | MU12; 00652000120816PK + Z[I,J+N12]:= -DG(I-NA, XX, H); 00653000 + END; 00654000 + END; 00655000 + END INITIALIZATION; 00656000 + 00658000 +%%% THE NUMBER SMASHING COMMENCES. 00659000 + ORTHO (W, Y, Z, NPOINTS, NAB, NAB, COF[1,*]); %######################00660000 + 00661000 +%%% UPON EXIT FROM ORTHO, THE YU/SPARROW COEFFICIENTS, A[J], B[J], 00662000 +%%%% ARE CONTAINED IN THE VECTOR COF[1,*]. 00663000 + 00664000 + Q1Q1FULL:= 8/PI | INTEGRALUSTAR(1); 00665000120816PK + Q2Q2FULL:= 8/PI | INTEGRALUSTAR(2); 00666000120816PK + Q1STARQ1FULL:= EQUATION23(H); 00667000 + Q2STARQ2FULL:= 1 - Q1STARQ1FULL; 00668000 + TAB22:= Q2Q2FULL | PI/8; 00669000120816PK + Q1Q2:= Q1Q1FULL/Q2Q2FULL/MU12; 00670000 + QMU12:= Q1Q2 | MU12; 00670500120816PK + Q1Q1STAR:= Q1Q1FULL/Q1STARQ1FULL; Q2Q2STAR:= Q2Q2FULL/Q2STARQ2FULL;00671000 + 00672000 + 00673000 + IF (PAG:= PAG+1) MOD 3 = 0 THEN 00674000 + BEGIN 00674800 + WRITE (OUTPUT[PAGE]); 00674900 + WRITE (OUTPUT, F3, MO, DA, YR, PAG DIV 3); 00675000 + END; 00675100 + WRITE (OUTPUT[DBL], F1, H, MU12); 00676000 + WRITE (OUTPUT, F2, FOR I:= 0 STEP 1 UNTIL 7 DO 00677000 + [NDX1[I], COF[1,NDX1[I]], NDX1[I], COF[1,NDX1[I]+NA], NDX2[I], 00678000 + COF[1,NDX2[I]], NDX2[I], COF[1,NDX2[I]+NA], NAME1[I], 00679000 + NAME2[I], CALC[I]], 16, COF[1,16], 16, COF[1,16], Q1Q2); 00680000 + WRITE (OUTPUT, FT, (TIME(2) - PT)/60, (TIME(1) - ET)/60); 00681000 +END INNER BLOCK; 00682000 +WRITE (OUTPUT[DBL], FT); 00683000 +WRITE (OUTPUT[DBL], *, "TOTALS:"); 00684000 +WRITE (OUTPUT, FT, TIME(2)/60, TIME(1)/60); 00685000 +END. 00686000 diff --git a/tools/B5500DeleteStorageDB.html b/tools/B5500DeleteStorageDB.html new file mode 100644 index 0000000..da416d8 --- /dev/null +++ b/tools/B5500DeleteStorageDB.html @@ -0,0 +1,45 @@ + + +B5500 Emulator Storage DB Deletion + + + + + + + + + + +

Delete a Disk Storage Database!

+ + + \ No newline at end of file diff --git a/tools/B5500DeleteSystemConfigDB.html b/tools/B5500DeleteSystemConfigDB.html new file mode 100644 index 0000000..9e6393c --- /dev/null +++ b/tools/B5500DeleteSystemConfigDB.html @@ -0,0 +1,44 @@ + + +B5500 Emulator System Configuration DB Deletion + + + + + + + + + + +

Delete the System Configuration Database!

+ + + \ No newline at end of file diff --git a/tools/B5500DiskDirFixer.html b/tools/B5500DiskDirFixer.html index 31e8f7c..2228acf 100644 --- a/tools/B5500DiskDirFixer.html +++ b/tools/B5500DiskDirFixer.html @@ -2,7 +2,7 @@ B5500 Disk Directory Fixer Utility - + @@ -34,7 +34,7 @@ if (!window.indexedDB) { // for Safari, mostly window.addEventListener("load", function() { var configName = "CONFIG"; // database configuration store name var dbName = "B5500DiskUnit"; // IDB database name - var dbVersion = 1; // current IDB database version + var dbVersion; // current IDB database version (leave undefined) var directoryTop; // start of directory area var directoryEnd; // end of directory area var euPrefix = "EU"; // prefix for EU object store names @@ -597,7 +597,7 @@ TH {
- retro-B5500 Logo + retro-B5500 Logo  Disk Directory Fixer Utility
diff --git a/tools/B5500DiskDirList.html b/tools/B5500DiskDirList.html index 35ec250..1f5da19 100644 --- a/tools/B5500DiskDirList.html +++ b/tools/B5500DiskDirList.html @@ -2,7 +2,7 @@ B5500 Disk Directory List Utility - + @@ -32,7 +32,7 @@ if (!window.indexedDB) { // for Safari, mostly window.addEventListener("load", function() { var configName = "CONFIG"; // database configuration store name var dbName = "B5500DiskUnit"; // IDB database name - var dbVersion = 1; // current IDB database version + var dbVersion; // current IDB database version (leave undefined) var directoryTop; // start of directory area var directoryEnd; // end of directory area var euPrefix = "EU"; // prefix for EU object store names @@ -595,7 +595,7 @@ TD {
- retro-B5500 Logo + retro-B5500 Logo  Disk Directory List Utility
diff --git a/tools/B5500DiskFileList.html b/tools/B5500DiskFileList.html index aa4ad0b..f29109a 100644 --- a/tools/B5500DiskFileList.html +++ b/tools/B5500DiskFileList.html @@ -2,7 +2,7 @@ B5500 Disk File List Utility - + @@ -33,7 +33,7 @@ if (!window.indexedDB) { // for Safari, mostly window.addEventListener("load", function() { var configName = "CONFIG"; // database configuration store name var dbName = "B5500DiskUnit"; // IDB database name - var dbVersion = 1; // current IDB database version + var dbVersion; // current IDB database version (leave undefined) var directoryTop; // start of directory area var directoryEnd; // end of directory area var euPrefix = "EU"; // prefix for EU object store names @@ -741,7 +741,7 @@ TH {
- retro-B5500 Logo + retro-B5500 Logo  Disk File List Utility
diff --git a/tools/B5500DiskSystemLogFixer.html b/tools/B5500DiskSystemLogFixer.html index c6ea701..bcc513c 100644 --- a/tools/B5500DiskSystemLogFixer.html +++ b/tools/B5500DiskSystemLogFixer.html @@ -2,7 +2,7 @@ B5500 Disk SYSTEM/LOG Fixer Utility - + @@ -34,7 +34,7 @@ if (!window.indexedDB) { // for Safari, mostly window.addEventListener("load", function() { var configName = "CONFIG"; // database configuration store name var dbName = "B5500DiskUnit"; // IDB database name - var dbVersion = 1; // current IDB database version + var dbVersion; // current IDB database version (leave undefined) var directoryTop; // start of directory area var directoryEnd; // end of directory area var euPrefix = "EU"; // prefix for EU object store names @@ -583,7 +583,7 @@ TH {
- retro-B5500 Logo + retro-B5500 Logo  Disk SYSTEM/LOG Fixer Utility
diff --git a/tools/B5500FixStorageNames.html b/tools/B5500FixStorageNames.html new file mode 100644 index 0000000..b933b78 --- /dev/null +++ b/tools/B5500FixStorageNames.html @@ -0,0 +1,50 @@ + + +B5500 Emulator Fix StorageNames + + + + + + + + + + +

Fix System Config StorageNames Store!

+ + + \ No newline at end of file diff --git a/tools/B5500LibMaintDecoder.html b/tools/B5500LibMaintDecoder.html index a59acd9..17867b0 100644 --- a/tools/B5500LibMaintDecoder.html +++ b/tools/B5500LibMaintDecoder.html @@ -2,7 +2,7 @@ B5500 LibMaint Decoder - + diff --git a/tools/B5500LibMaintDir.html b/tools/B5500LibMaintDir.html index 78c06b5..6cb287a 100644 --- a/tools/B5500LibMaintDir.html +++ b/tools/B5500LibMaintDir.html @@ -2,7 +2,7 @@ B5500 LibMaint Directory - + diff --git a/tools/B5500LibMaintExtract.html b/tools/B5500LibMaintExtract.html index b80b5e8..a9189e6 100644 --- a/tools/B5500LibMaintExtract.html +++ b/tools/B5500LibMaintExtract.html @@ -2,7 +2,7 @@ B5500 LibMaint Extract - + diff --git a/tools/B5500LibMaintMapper.html b/tools/B5500LibMaintMapper.html index f4c6ba0..3892fb3 100644 --- a/tools/B5500LibMaintMapper.html +++ b/tools/B5500LibMaintMapper.html @@ -2,7 +2,7 @@ B5500 LibMaint Extract - + diff --git a/tools/COLDSTART-XIII.card b/tools/COLDSTART-XIII.card new file mode 100644 index 0000000..3ba3228 --- /dev/null +++ b/tools/COLDSTART-XIII.card @@ -0,0 +1,246 @@ +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 +00000000049DJA9YSI001J F2900SI8Y4A4(0)0)08/I00000?/I|0000+/I7Y000 +A2( B01000160 +000000000U+A2(0)0Y+A2(000!+A2(001|0000000Q/IPBT0RSMSG000AUTOUNLDRNALL00001000170 +00000000CODEOLAYCOREST00DATAOLAYHALT0000REMOTE00CEMESS00BATCHZIPNOBATCH001000200 +00000000000000000000000000000000000000000000000000000000MOD3IOS00000000001000210 +00000000OPTN0000~000000000000000000000000000000000000000000000000000000001000220 +00000000000000000000000000000000000000000000000000000000000000000000000001000230 +00000000000000000000000000000000000000000000000000000000000000000000000001000240 +00000000000000000000000000000000000000000000000000000000000000000000000001000250 +00000000000000000000000000000000000000000000000000000000000000000000000001000260 +00000000000000000000000000000000000000000000000000000000000000000000000001000270 +00000000000000000000000000000000000000000000000000000000000000000000000001000300 +00000000000000000000000000000000000000000000000000000000000000000000000001000310 +00000000000000000000000000000000000000000000000000000000000000000000000001000320 +00000000000000000000000000000000000000000000000000000000000000000000000001000330 +00000000Q00000000000000000000000000000000000000000000000000000000000000001000340 +00000000000000000000000000000000000000000000000000000000000000000000000001000350 +00000000000000000000000000000000000000000000000000000000000000000000000001000360 +0000000000000000000000000000000000000000Q ?0006SQ :0006]Q W0007@Q ?0008101000370 +00000000Q }0008:" 60008&" ?0008K= 80008;]T(0003(= .0009}= 2000#]= I0008W01000400 +00000000= &0009R= @000#5= 7000#+= 6000#G= G000#(= #000#U] B0000B400?AJ0401000410 +000000008I8&4A1Y9-JA#H+A001J0?11884A4J8#MJ8!000000001*|$|50R108#831J1!S)01000420 +00000000#/#V8U4A8#1!11884A8#8+4A8#1Y11884A8#831J1YS)#/#V8 4A8#2|11884A8#01000430 +00000000831J1YS)#/#V944A8#2|11884A8#831J&8S)#/#V904A8#&811884A8#831J1YS)01000440 +00000000#/#V984A8#2|11884A8#8?4A8#2|11884A008H4AD98#831J0QS)#/#V8Y4A8#8|01000450 +000000004A4J8K>B0)#<4J8K0Q11MJ2!%-104J9U+A#O8M8A+E11KI0&SIE-KI7HKIMQKI2Y01000460 +00000000SIA?KI2!SI+!KI4|SI5 KI1+SI30KI0QSI0)0)0)4J089"001J>F0)#+KI0)0)0)2|00|0007|0000004J#S8#8|4A5MJI4J01000500 +000000003U#>008X4J#$8E4A008W0+2E008W04KE2:0&2I008X048E4A14/I7YJI4J#$8&4A01000510 +000000008<1?118D4A8MJI0+8T0+8X4J#$8E8A8E4A9DJI4J3U#>1?8T},0)+E4J#$31}]0)01000520 +00000000H1}]0)41318E4A1?8S+20)KE0HBI1?8T+20)8E4A1-KI0)0)00000800000000+001000530 +00000000000002001?8S+F0)2E0H2I1?8T+F0)8E4A:DJI0)00000700088T4J#$8E4A54KI01000540 +000000004J#$8Q4A8$04KE8$0 2E2:1:2YAI4J34#>4J#$9?JA4J34#>4J#$8-4A8$04319S01000550 +000000009>119?JA8;0+Y100ME8;6+Y1004E8;I0Y100ME2:4:8$0?1E4:08BI9>04119?JA01000560 +000000008;6+Y1]|419>119?JA4J9}048TMJ2*8W104J3-#>C|JI4J9Y+A#O9HJA9.302E0D01000570 +000000002I9.2|319HJA0HKI304J#$319HJA9.004E4&AI049|JA080UKI0)0)0)009K2)1/01000600 +00000000;V9|JA9O04119M8A9.2E0?AI008T008S9K2:8E4A4DJI000USI0)0)0)004J008L01000610 +00000000##9|JA9K0&JE5+AI4J8K9K1 8.319O119@MJ3*2L0H8!0 7}2L0"104J9O01000620 +0000000000ME0?2I3404SI3Q#>9O04119M8A042E0UAI8<00KE0DBI4J0H9"001JD60)#<6?01000630 +00000000/I0)0)0)7|0000000M974J#$8E4A4J20#>0|974J#$8E4A4J3Q#>0?979>9>Q)+/01000640 +00000000BV4J#$S)2/#V8I8E4A0+97008E4A0M969&JA4J3-#>0424KI8#8|4A4J8KEO0)#<01000650 +000000004J9U+A#O00ME7+AI8#8|4A0M9O11974J#$8E4A4J3-#>9O04119M8A9<2E0MAI9O01000660 +0000000010KI0)0)2|00|0000M9O1197008E4A9O04119M8A1+2E0?AI0097448E4A0&970|01000670 +00000000969<4104318E4A8.08118H4A4J8F8.08H13194+A#K8.1YME0U2I4J8F98+A#K8F01000700 +0000000010118D4A008H4AO-JI0+8SG>0)KE0H2I0+8TG>0)8E4A108T0!8E4A8<00KE0HBI01000710 +000000004J0H9"001JGB0)#<9D/I0)0)000000G&7|000000048X8<8E4A008W0+2E008W0401000720 +00000000KE2:0D2I008X048E4A4J008U+A#K1 8.319@4 8E4A1U8.319@008E4A0)0)0)0)01000730 +00000000000?KI8.04118H8A008W0431JE0?BI4J8<8.318 +A#K1DJI389&JA9<8<008W3101000740 +00000000KE10BI4J9<94+AMJ2B8W109<8<008W319<319&KA3!1E0DBI4J94+A001JI60)#<01000750 +000000000DSI0)0)1|007Y004J94+A001JI<0)900000000FILE000001001030 +00000000FENCE000STOP0000ESU00000USE00000DATE0000TYPE0000OPTN0000DIRECTOR01001040 +00000000DRCTRYTPSYSTEMS0~000000000000000DRA00000DRB00000BOJ00000EOJ0000001001050 +00000000OPEN0000TERMNATEDATE0000TIME0000ONEBREAKAUTOPRNTCLEARWRSDISCONDC01001060 +00000000CMPLFILECLOSE000ERRORMSGRET00000LIBMSG00SCHEDMSGSECMSG00DSKTOG0001001070 +00000000RELTOG00PBDREL00CHECK000DISKMSG0DISKLOG0LIBERR00PBDONLY0SAVEPBT001001100 +00000000RSMSG000AUTOUNLDRNALL000CODEOLAYCOREST00DATAOLAYHALT0000REMOTE0001001110 +00000000CEMESS00BATCHZIPNOBATCH0000000000000000000000000000000000000000001001120 +0000000000000000MOD3IOS000000000OPTN0000~000000000000000000000000000000001001130 +0000000000000000DIRECTRY BUILT~ INCORRECT CARD~0 ERROR ~ DIRECTOR01001140 +00000000YTOP NOT SET~ LOADER LOADED ALREADY~ 4J041{4A1{0008M9290?JI0)01001150 +00000000J)#N00ME0 1I1 0UMJ142*35102&JI0)0S1?JI0)0W1&JI0)0,1-JI0)0]1!JI0)01001160 +00000000R|00PY204J8410MJ2*14+$!5!50R10D93*1L0H3:2*8I1|~D2N0K8P248>2?3*1L01001170 +000000000/1N}{5J00142*351*5I0; D2N1I4{"D}N1IA$1I1|"D6N2:241!0 0OBP0R0K}P01001200 +00000000A<@NA$1I1|A<1N2P0O5P0R>{2P1I1K4J2:142B150000PY20004J008L##044E0801001210 +000000002I#BKI0)Y64J8KMJ1*1H367>1/1N1K3J10082I#BKI4(1N2P00Y#Y61JY44AY7M901001220 +000000004J#.|44A|6Q)@N004E0&2I9F1:141I089DJAY#001E4+2I|6K)8N004E3U2I|6N)01001230 +000000008N|63)DN0HME4:Y#831J+A20ME4:182IY#831J008E4AY#0411831J008E4A48JI01001240 +000000001MKI|6N)8N|63)DN0QME4:Y#831J+A00ME4:082I0DKI4JY6#F5UJI4(00Y63)DN01001250 +00000000Y44AY61YME0?2I/61MKIY60QME0?2I/214KIY60HME0?2I ]0MKIY60+ME0?2I ,01001260 +0000000004KI ,|44A4J|60+9"MJ2B5I3"104J0+9"001J ;#831JY4+A831J+A8E4A4J8> K#<0)8>4JY4+A|:MJ3*8I8>5$ /1N1K0R3J1001001330 +000000000?2I4J B#F4(0)0)1|<108001|<1|8001|00000000008K831J+A008:001:ME0401001340 +00000000BI0 0DKI004J008L##|84A|#0 ME0?2I0 0&KI004J8KY4+A|##6|44A|62(1YH101001350 +000000000000004J008L##|84A0)004J|#8KMJ2L0}1?1*462L0X10|44A|62(2I004J0M8%01001360 +00000000|7MJ2*4I146>4$333$1~2N1U1P12130R0R10|62(9B0Q2I4J0M9"001J/##<000?01001370 +000000001I4J048%0M8,8)CN4J#;8Y+A1JMJ3*2L05104J8Y+A001J W#<008,008E4)4/-V01001400 +00000000004E2?1I8Y+A8!4A6!8Y+A1J8Y4A008%048E4A049+JA4J8Y+A001J F#<8!+A8Y01001410 +000000004A4(0)0)7|0000002|#0|0001|007Y004J8.9@9 +AMJ2*1I7"1!0/1I7"9!0 RE01001420 +00000000MOVED~108.9@0 8E4A4J9 +A001J ##<4(0)0)0)7|00000000#,KI|62(MJ2*1I01001430 +00000000000000000000000000000000000000000000000000000000000000000000000001001440 +00000000000000000000000000000000000000000000000000000000000000000000000001001450 +00000000=000000#04*)H/}VY6044A4("000000:2*14"$"50R004J0O4J70100S0|JI000001000011 +DRCTRYTP 2000 % START OF DIRECTORY AREA +DIRECT 3604 % END OF DIRECTORY AREA +ESU 3 % MAX NUMBER OF EUS +DATE 09/01/84 % CURRENT SYSTEM DATE +SYSTEMS = 1 % MUST BE 1 (FOR NOW) +FENCE = 16384 % USED BY TSMCP ONLY +FILE DIRCTRY/DISK, 1|1600, 999 % DIRECTORY ENTRY FOR DIRECTORY + 2004 +FILE SYSTEM/LOG, 1|5000, 999 % RESERVE SPACE FOR LOG + 3609 +FILE MCP/DISK, 1|1500, 999 % RESERVE SPACE FOR MCP CODE + 8610 +FILE DMPAREA/DISK, 1|100, 999 % RESERVE SPACE FOR MEM DUMP + 10108 +FILE RESERVE/DISK, 1|2000, 999 % RESERVE FOR NO-USER-DISK EVENT + 10208 +TYPE BOJ % PRINT BOJ MESSAGES +TYPE EOJ % PRINT EOJ MESSAGES +TYPE OPEN % PRINT FILE OPEN MESSAGES +USE TERMNATE % REMOVE TASKS FROM MEMORY AT EOJ (NORMALLY SET) +TYPE TIME % REQUIRE TIME TO BE ENTERED AT SPO AFTER HALT/LOAD +USE ONEBREAK % WRITE ALL BREAKOUTS TO A SINGLE TAPE +USE AUTOPRNT % PRINT BACKUP (SPOOLED) FILES BY DEFAULT +USE CLEARWRS % CLEAR WRITE-READY STATUS ON DATACOM STATIONS +TYPE CLOSE % PRINT FILE CLOSE MESSAGES +TYPE RET % PRINT TAPE VOLUME-RETENTION MESSAGES +TYPE LIBMSG % PRINT DUMP/LOAD/REMOVED, ETC. MESSAGES +TYPE SCHEDMSG % PRINT MESSAGE WHEN TASKS ARE SCHEDULED +TYPE SECMSG % PRINT FILE SECURITY MAINTENANCE MESSAGES +USE DSKTOG % PREVENT USER ACCESS BELOW USER DISK AREA +USE RELTOG % PREVENT USE OF ALGOL RELEASE ON DISK FILES +TYPE PBDREL % PRINT BACKUP FILE RELEASE MESSAGES IF NOT AUTOPRNT +TYPE DISKMSG % PRINT ALL DISK I/O RETRY MESSAGES +TYPE DISKLOG % DISK LOGGING(TSMCP ONLY) +TYPE LIBERR % PRINT LIB/MAINT ERROR MESSAGES (TSMCP ONLY) +USE PBDONLY % ASSIGN ALL PRINTER/PUNCH FILES TO BACKUP (SPOOLED) +USE RSMSG % PRINT MESSAGE FOR FILE-ACCESSED FLAG CHANGES +USE RNALL % RUN ALL PSEUDO-READER DECKS (SHARED SYSTEMS ONLY) +USE COREST % LOG MEMORY USAGE STATS (STATISTICS ONLY) +USE HALT % HALT SYSTEM WHEN HALT-RECOMMENDED ERRORS OCCUR +USE CEMESS % PRINT LIB/MAINT MESSAGES FOR CANDE TASKS (TSMCP ONLY) +USE BATCHZIP % ZIP DECKS TO RUN UNDER BATCH CONTROL (TSMCP ONLY) +USE MOD3IOS % ASSUME WE HAVE MODEL-III I/O CONTROL UNITS (WE DO) +000000007|SI000000000000298>7HBI04/I0000000000000?/I00000+/I00000 +A2(0001000160 +000000000U+A2(000Y+A2(000!+A2(00000000000Q/I0000000000000 /I00000U/I000001000170 +00000000000000000000000000000000000000000000000000000000000000000000000001000200 +00000000000000000000000000000000000000000000000000000000000000000000000001000210 +00000000000000005&SI000000000000000000000000000000000000000000000000000001000220 +00000000000000000000000000000000000000000000000000000000000000000000000001000230 +00000000000000000000000000000000000000000000000000000000000000000000000001000240 +00000000000000000000000000000000000000000000000000000000000000000000000001000250 +00000000000000000000000000000000000000000000000000000000000000000000000001000260 +00000000000000000000000000000000000000000000000000000000000000000000000001000270 +00000000000000000000000000000000000000000000000000000000000000000000000001000300 +00000000000000000000000000000000000000000000000000000000000000000000000001000310 +00000000000000000000000000000000000000000000000000000000000000000000000001000320 +00000000000000000000000000000000000000000000000000000000000000000000000001000330 +00000000Q0000000000000000000000000000000= 20003X] B0000B= 70003Z= ?0004001000340 +00000000400?AJ2H831J2H831J+A9#0)118E8A831J008E4A292H831J+A9>0)2E0DBI2H8301000350 +000000001J008E4A0M/I0)0)0000010000000700048?JA8++A6+1J831J"!S)#/#V884A2401000360 +00000000831J88+A*)HN8E4A24831J+A831J208E4A28831J0U8E4A4J>K0)24831J+A-E8.01000370 +0000000000ME4!2I2D831J048#4)8N8E4A24831J+A831J>O0)2D831J+A!)Q/2V8E4A4J>$01000400 +000000000)24831J+A-E8.0R24831J+A831J>;0)2D831J+A!)Q/2V8E4A4J>$0)24831J+A01000410 +00000000-E8.0R28831J28831J+A2D831J+A0D41118E4A24831J+A831J008E4A2+831J4J01000420 +0000000024831J+A>S0)1J8.8E4A2+831J+A00ME0DAI04831J088#8E4A2?831J048#8E4A01000430 +0000000028831J+A8#834A8204831J+AJE0|BI2H831J>W0)8E4A2&831J>,0)8E4A2|831J01000440 +00000000>]0)8E4A4J}20)8.0R000?1I20831J4M8E4A4J}60)2H831J+A2:8<20831J0Q8E01000450 +000000004A4J}#0)2H831J+A2:8<20831J008E4A4J}>0)2H831J+A2:8<2H831J2H831J+A01000460 +0000000020118E4A0U831J}B0)8E4A0Y831J}F0)8E4A0!831J}.0)8E4A820831834A822D01000470 +00000000831J+A!)D/2V2?831J+A!)B/2V834A040?AJ0008AJ0U831JKI0414BI0DJI0)0)01000500 +000000001|0|0000000000| 1|010000000000 1|00|800INVALID ADDRESS FOR MCP~01000510 +000000007|00000O1|00PYK(1|00PY4%1|00J+0}4J2.10MJ2*14*$"5~50R10D9008FKI|601000520 +000000002(00000000Y7M92+831J4J8B8E4A2+831J+AJ)CN|44A|60D4:00ME1|1I|62(0001000530 +000000004J8220831J+A11Y6*)HNMJ2B148W10Y6831J+A5)8N0&2IY60 Z)3/5VY44A2+8301000540 +000000001J4JY68.8E4A2+831J+A00ME101I4(000000000000000000000000000000000001000550 +00000000=000000#04*)H/}VY6044A4("000000:2*14"$"50R004J0O4J70100S0|JI000001000011 +STOP + %% THIS EXTRA CARD MUST BE HERE %% +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 +000000008YSI8D4A008T008E2900SI+A001J ]0008/I8F080?/I0?8]0+/I8F040 +A2(8]01000160 +000000000U+A2(8T0Y+A2(4A0!+A2(001J B009>0Q/I831J0Y8,8E4A0 /I0)0)0U/I080001000170 +000000001|0|0000000040001|00|8002B8W104(000009A 00000000000000000000000001000200 +00000000000000000000000000000000000000000000000000000000000000000000000001000210 +00000000000000000000000000000000000000000000000000000000000000000000000001000220 +00000000000000000000000000000000000000000000000000000000000000000000000001000230 +00000000000000000000000000000000000000000000000000000000000000000000000001000240 +00000000000000000000000000000000000000000000000000000000000000000000000001000250 +00000000000000000000000000000000000000000000000000000000000000000000000001000260 +00000000000000000000000000000000000000000000000000000000000000000000000001000270 +00000000000000000000000000000000000000000000000000000000000000000000000001000300 +00000000000000000000000000000000000000000000000000000000000000000000000001000310 +00000000000000000000000000000000000000000000000000000000000000000000000001000320 +00000000000000000000000000000000000000000000000000000000000000000000000001000330 +00000000Q00000000000000000000000000000000000000000000000000000000000000001000340 +000000000000000000000000000000000000000000000000Q <0003WQ +0004DQ 50004M01000350 +00000000= 200082= 60005-= &0005+= ?0004R= C0004V= 800058= 60005S= F0005Y01000360 +00000000= :0006>= 70006[= N0006K= H00077= L0007~] B0000B90+A0D1J831J"!S)01000370 +00000000#/#V8-4A8-+A001J8|4A8K#O0)118M4A8O#O0)11831J]|S)#/#V8 4A400?AJ4J01000400 +000000009;041?KI000000+64J00@20)8$Z)3/5V@60)9>0R8$08118Q8A1!2E0DAI041+SI01000410 +00000000000K000000000Q008-+A041J8$Z)3/5V8?4A4J8>?O0)?$0)9>K)CN00ME282I0401000420 +000000008{+A?;0)|:8I001:ME8:088{+A088]8:001:ME4:0?8{+A?S0)8:001:ME4:1:1+01000430 +000000002I4J8>?W0)?,0)9>0R8$08118Q8A1!2E18AI005|1I4J049F4J8>?O0)009>0R0401000440 +000000003 KI0)0)0}"5|00000006Q000LABEL 0FILE000000K000000000Q008$8;008]01000450 +000000008:001:ME8$04118;048]8:001:ME4:1:0DBI8$8;0 ME0?2I4J08968$08118Q8A01000460 +00000000|02E0MAI4J8$04119F4J8>>20)009>0R4J9S0M8;04311YH104118+4A040DSI0)01000470 +000000000}"5|0004J8>}>0)009>0R4J9B8$04118Q8A8B2E0+AI4J8>}B0)009>0R8#1M2I01000500 +000000004J0?8"0H8%MJ}>D! TO DEFAULT ADDRESS=2*8W1!0~9}8#104J0?964J8U+A1001000510 +00000000MJ2*D510000?AJ0008AJ>8/I0}"5|000000K00000000BI004J041{4A1{0008M901000520 +00000000290?JI0)J)#N00ME0 1I1 0UMJ142*35102&JI0)0S1?JI0)0W1&JI0)0,1-JI0)01000530 +000000000]1!JI0)R|00PY204J8410MJ2*14+$!5!50R10D900000000000000000000000001000540 +00000000000000000000000000000000000000000000000000000000000000000000000001000550 +0000000000000000000000000000000000000000DISK FAILURE~000TAPE FAILURE~00001000560 +00000000NO MCP FILE~0000MCP FILE LOADED~NOT IN DIRCTORY~LOADER ON DISK~ 01000570 +00000000CRA FAILURE~ 00000000000000000MCP 0DISK 0SYSTEM 0000000001000600 +0000000000000000000000Y>Y#2:Y84AY@M94J92|84A|#Y61:4:|?4A|>K)CN004E0+BI|>01000610 +00000000N)8N1:08BI4JY#|@9#1:0&AI|#|44A|62(DISK~ 0000/#|44A4J8K|6009>0R8O01000620 +00000000831J8K831J+A8E4A4J8O|604=)|/1V009>0R0)8K4J8OMJ3*8I8>3$S$ /1N1K0R01000630 +000000000R3J100U2I|#0411|84A|#0D2E3H1I4J00964J?08KMJ2B8%104(0)0)1;413 0001000640 +0000000000040+SI4J8> F .9>L)#N08AI|60411|48AY62E0+AI4(0)0001|0000000600001000650 +000000000000Y6Q)@N004E082I042(Y6M)9N4-2IY63)DN0-BI041&KI4J8> K O9>0RY74J01000660 +0000000000Y# <9>8E8AM)9N004E3Y2I|#0411|88A0D2E0&AI2+KI0)0003|0000000600001000670 +000000000418KI0)Y74J00Y# O9>8E8AM)9N004E1|2I|#0411|88A0D2E0DAI4JY63)DN0Q01000700 +00000000ME0?2I0H0?KIY#9)?N96|62(000020004J08Y6418%001J B009>0RY60?ME0D1I01000710 +000000004(0)0)0)7|000000004J0M8T|7MJ2*4I146>4$333$1~2N1U1P12130R0R10|62(01000720 +00000000008<0?2I4J0D964J048T0M8S8)CN4J9.8 +A1JMJ3*2L0510DI|):N0DBI4J8 +A01000730 +00000000001J # >9>0R0UKI2|#0|00000003000008T0 8E4A008S008E4)4/-V004E3M1I01000740 +000000008K|44A8 +A6!1J8|4A048&4A8K831J048E4A4J9B|68|4A4(0)004J8$0+8"MJ2*01000750 +000000001>"$ D2N1I2P0O1P0R/D3N1I?{FP=D2N6{BP7$ D3N1!0 @P/D3N1!0 6P=D3N1!01000760 +000000000 1P1"0R4:108Q4A4(8T0 8E4J9KY60|2I088"0+8]8E4A0YKI008"0+8]8E4A4J01000770 +000000009K048"0+8]8E4A4(00008T008E4A4J8 +A001J S009>0R088S|4JA0)0)0)|60+01001000 +00000000110?KI8B10118+4A044Y2I4J8C8 +AMJ2*8W104J8 +A001J >009>0R0038KI0)01001010 +000000001|00|8001|00K000(!8F318S4 8:001:ME0?2I4J0+96(!8F318S008]8:001:ME01001020 +000000000 2I<08F318S048]8:001:4E0-2I8F08118D8A1 2E0-AI5HJI0?8".!8F0!413101001030 +000000008S8E8A00ME888A0D2I0?8" B8E4A4J0?8]0Y8%MJ2B8W104(000009A DI|):N4+01001040 +000000002I8 +A001J8Q4A4J8 +A001J ]/29>0R008T+A008:001:ME04BI4J9<4J9K0+8]01001050 +00000000 S8:001:ME0?2I4J009O0+8] $8:001:ME0?2I4J049ODI|):N00ME0+8] <8:0001001060 +000000001:ME2:4+1I4J9$4(2|#0|000000030000FILE 0TAPE 0STOP 0-8{0?8]01001070 +000000008E4A0D8{+E+AMI8E4A4J8B1 8F3108H1118-+AMJ2B8W104J8-+A001J/<009>0R01001100 +00000000008T208E4A048T008E4A4J8 +A001J/B/B9>0R048S4)8N8D4A0-8F0D41118D4A01001110 +00000000008T008E4A4J8 +A001J ]009>0R8F08118T0?8]8E4A8F04118T048]8E4A8F8T01001120 +00000000008]8E4A4J8 +A001J B009>0R8K831J0Y8,8E4A4(0)0)0)1|<108001|0|000001001130 +00000000000040001|00|800009WKI|62(4A0D8{0000000000000000000000000000000001001140 +00000000000000000000000000000000000000000000000000000000000000000000000001001150 +00000000000000000000000000000000000000000000000000000000000000000000000001001160 +00000000000000000000000000000000000000000000000000000000000000000000000001001170 +00000000=000000#04*)H/}VY6044A4("000000:2*14"$"50R004J0O4J70100S0|JI000001000011 +TAPE = SYSTEM +FILE = MCP/DISK +STOP +?ADD FROM SYSTEM INT/DISK, PRNPBT/DISK, LDCNTRL/DISK - + ,ALGOL/DISK - + ,XALGOL/DISK - + ,FORTRAN/DISK - + ,COBOL/DISK - + ,LOGOUT/DISK +?END \ No newline at end of file diff --git a/tools/CONTROL.DECK.job b/tools/CONTROL.DECK.card similarity index 100% rename from tools/CONTROL.DECK.job rename to tools/CONTROL.DECK.card diff --git a/tools/END.CONTROL.job b/tools/END.CONTROL.card similarity index 100% rename from tools/END.CONTROL.job rename to tools/END.CONTROL.card diff --git a/webUI/ESPOL-Binary-Card-Loader.txt b/tools/ESPOL-Binary-Card-Loader.card similarity index 100% rename from webUI/ESPOL-Binary-Card-Loader.txt rename to tools/ESPOL-Binary-Card-Loader.card diff --git a/tools/LOG-MAKER.job b/tools/LOG-MAKER.card similarity index 100% rename from tools/LOG-MAKER.job rename to tools/LOG-MAKER.card diff --git a/tools/PDF-Listing-Column-Ruler.ppt b/tools/misc/PDF-Listing-Column-Ruler.ppt similarity index 100% rename from tools/PDF-Listing-Column-Ruler.ppt rename to tools/misc/PDF-Listing-Column-Ruler.ppt diff --git a/tools/compose.js b/tools/misc/compose.js similarity index 100% rename from tools/compose.js rename to tools/misc/compose.js diff --git a/tools/uniquewordcount b/tools/misc/uniquewordcount similarity index 100% rename from tools/uniquewordcount rename to tools/misc/uniquewordcount diff --git a/webSite/HelpMenu.html b/webSite/HelpMenu.html index dd0e9c7..dec5e39 100644 --- a/webSite/HelpMenu.html +++ b/webSite/HelpMenu.html @@ -1,7 +1,7 @@ retro-B5500 Emulator Help Menu - + @@ -10,12 +10,12 @@ - retro A-CONTROL logo + retro A-CONTROL logo -

retro logo +

retro logo
- Burroughs B5500 Emulator Help Menu + Burroughs B5500 Emulator Help & Getting Started Menu

Main Links

@@ -24,8 +24,11 @@
  • Getting Started
    Describes the resources you will need to set up and run the emulator, along with instructions for downloading the necessary files and doing the setup. +
  • Configuring the System +
    Describes how to configure system components and disk subsystems for the emulator. +
  • Running the Emulator -
    Describes how to halt/load (boot) the MCP operating system emulator using a web browser. Also describes some basic MCP operational tasks. +
    Describes how to halt/load (boot) the MCP operating system in the emulator using a web browser. Also describes some basic MCP operational tasks.
  • Using the B5500 Console
    Describes the controls and lights on the B5500 console display. @@ -46,7 +49,7 @@
    Describes how to operate magnetic tape drives within the browser-based emulator.
  • Using the Datacom Terminal -
    Describes how to operate the datacommunications terminal within the browser-based emulator. +
    Describes how to operate the data-communications terminal within the browser-based emulator.
  • Setting Up TSMCP and CANDE
    Describes how to set up and initiate the Timesharing MCP and CANDE user interface within the browser-based emulator. @@ -60,7 +63,7 @@ Copyright (c) 2013, Nigel Williams and Paul Kimpel • Licensed under the MIT License
    Revised - 2013-12-14 + 2014-09-26
    diff --git a/webSite/SoftwareRequest.html b/webSite/SoftwareRequest.html index 95be8b1..3c54451 100644 --- a/webSite/SoftwareRequest.html +++ b/webSite/SoftwareRequest.html @@ -1,7 +1,7 @@ retro-B5500 Mark XIII System Software - + @@ -12,10 +12,10 @@ - retro A-CONTROL logo + retro A-CONTROL logo -

    retro logo +

    retro logo
    Burroughs B5500 Mark XIII System Software

    diff --git a/webSite/TapeImage-SYMBOL1.html b/webSite/TapeImage-SYMBOL1.html index d43f377..dc9c619 100644 --- a/webSite/TapeImage-SYMBOL1.html +++ b/webSite/TapeImage-SYMBOL1.html @@ -1,7 +1,7 @@ Burroughs B5500 Mark XIII SYMBOL1 Tape Image - + @@ -14,10 +14,10 @@ - retro A-CONTROL logo + retro A-CONTROL logo -

    retro logo +

    retro logo
    Burroughs B5500 Mark XIII SYMBOL1 Tape Image

    @@ -35,7 +35,7 @@
    2. LICENSE; NO DELIVERY
    -2.1 UNISYS hereby grants LICENSEE a personal, internal to LICENSEE only, non-exclusive, fully-paid right and license, including the right to sublicense for use and to copy (only to the extent reasonably necessary for LICENSEE to make and support Derivative Works), compile, modify, enhance and create Derivative Works of the Program and Program Materials solely for LICENSEE’s non-commercial educational or hobbyist purposes, internal use and internal support. +2.1 UNISYS hereby grants LICENSEE a personal, internal to LICENSEE only, non-exclusive, fully-paid right and license, including the right to sublicense for use and to copy (only to the extent reasonably necessary for LICENSEE to make and support Derivative Works), compile, modify, enhance and create Derivative Works of the Program and Program Materials solely for LICENSEE's non-commercial educational or hobbyist purposes, internal use and internal support.
    2.2 LICENSEE shall reproduce all confidentiality notices, copyright notices, limited rights legends, restricted rights legends and other proprietary rights notices contained within the Source Code.
    @@ -45,7 +45,7 @@
    (b) Allow the Program to be run in simulators, or actual hardware.
    -(d) Provide the Program and Program Materials to private individuals (“LICENSEE Users”), wherein the LICENSEE Users will be subject to the responsibilities set forth in Section 2.2 and enjoy the rights granted in Sections 2.1, 2.3(a) and 2.3(b). LICENSEE will not authorize or encourage LICENSEE Users to remove confidentiality notices, copyright notices, limited rights legends, restricted rights legends and other proprietary rights notices contained within the Programs and Program Materials to which they have access. +(d) Provide the Program and Program Materials to private individuals ("LICENSEE Users"), wherein the LICENSEE Users will be subject to the responsibilities set forth in Section 2.2 and enjoy the rights granted in Sections 2.1, 2.3(a) and 2.3(b). LICENSEE will not authorize or encourage LICENSEE Users to remove confidentiality notices, copyright notices, limited rights legends, restricted rights legends and other proprietary rights notices contained within the Programs and Program Materials to which they have access. 2.4 UNISYS has no obligation to deliver the Program or Program Materials to LICENSEE; LICENSEE must collect the materials through its own resources.
    diff --git a/webSite/TapeImage-SYMBOL2.html b/webSite/TapeImage-SYMBOL2.html index f3b55d9..5b7144f 100644 --- a/webSite/TapeImage-SYMBOL2.html +++ b/webSite/TapeImage-SYMBOL2.html @@ -1,7 +1,7 @@ Burroughs B5500 Mark XIII SYMBOL2 Tape Image - + @@ -14,10 +14,10 @@ - retro A-CONTROL logo + retro A-CONTROL logo -

    retro logo +

    retro logo
    Burroughs B5500 Mark XIII SYMBOL2 Tape Image

    @@ -35,7 +35,7 @@
    2. LICENSE; NO DELIVERY
    -2.1 UNISYS hereby grants LICENSEE a personal, internal to LICENSEE only, non-exclusive, fully-paid right and license, including the right to sublicense for use and to copy (only to the extent reasonably necessary for LICENSEE to make and support Derivative Works), compile, modify, enhance and create Derivative Works of the Program and Program Materials solely for LICENSEE’s non-commercial educational or hobbyist purposes, internal use and internal support. +2.1 UNISYS hereby grants LICENSEE a personal, internal to LICENSEE only, non-exclusive, fully-paid right and license, including the right to sublicense for use and to copy (only to the extent reasonably necessary for LICENSEE to make and support Derivative Works), compile, modify, enhance and create Derivative Works of the Program and Program Materials solely for LICENSEE's non-commercial educational or hobbyist purposes, internal use and internal support.
    2.2 LICENSEE shall reproduce all confidentiality notices, copyright notices, limited rights legends, restricted rights legends and other proprietary rights notices contained within the Source Code.
    @@ -45,7 +45,7 @@
    (b) Allow the Program to be run in simulators, or actual hardware.
    -(d) Provide the Program and Program Materials to private individuals (“LICENSEE Users”), wherein the LICENSEE Users will be subject to the responsibilities set forth in Section 2.2 and enjoy the rights granted in Sections 2.1, 2.3(a) and 2.3(b). LICENSEE will not authorize or encourage LICENSEE Users to remove confidentiality notices, copyright notices, limited rights legends, restricted rights legends and other proprietary rights notices contained within the Programs and Program Materials to which they have access. +(d) Provide the Program and Program Materials to private individuals ("LICENSEE Users"), wherein the LICENSEE Users will be subject to the responsibilities set forth in Section 2.2 and enjoy the rights granted in Sections 2.1, 2.3(a) and 2.3(b). LICENSEE will not authorize or encourage LICENSEE Users to remove confidentiality notices, copyright notices, limited rights legends, restricted rights legends and other proprietary rights notices contained within the Programs and Program Materials to which they have access. 2.4 UNISYS has no obligation to deliver the Program or Program Materials to LICENSEE; LICENSEE must collect the materials through its own resources.
    diff --git a/webSite/TapeImage-SYSTEM.html b/webSite/TapeImage-SYSTEM.html index 7c0fe20..15b3381 100644 --- a/webSite/TapeImage-SYSTEM.html +++ b/webSite/TapeImage-SYSTEM.html @@ -1,7 +1,7 @@ Burroughs B5500 Mark XIII SYSTEM Tape Image - + @@ -14,10 +14,10 @@ - retro A-CONTROL logo + retro A-CONTROL logo -

    retro logo +

    retro logo
    Burroughs B5500 Mark XIII SYSTEM Tape Image

    @@ -35,7 +35,7 @@
    2. LICENSE; NO DELIVERY
    -2.1 UNISYS hereby grants LICENSEE a personal, internal to LICENSEE only, non-exclusive, fully-paid right and license, including the right to sublicense for use and to copy (only to the extent reasonably necessary for LICENSEE to make and support Derivative Works), compile, modify, enhance and create Derivative Works of the Program and Program Materials solely for LICENSEE’s non-commercial educational or hobbyist purposes, internal use and internal support. +2.1 UNISYS hereby grants LICENSEE a personal, internal to LICENSEE only, non-exclusive, fully-paid right and license, including the right to sublicense for use and to copy (only to the extent reasonably necessary for LICENSEE to make and support Derivative Works), compile, modify, enhance and create Derivative Works of the Program and Program Materials solely for LICENSEE's non-commercial educational or hobbyist purposes, internal use and internal support.
    2.2 LICENSEE shall reproduce all confidentiality notices, copyright notices, limited rights legends, restricted rights legends and other proprietary rights notices contained within the Source Code.
    @@ -45,7 +45,7 @@
    (b) Allow the Program to be run in simulators, or actual hardware.
    -(d) Provide the Program and Program Materials to private individuals (“LICENSEE Users”), wherein the LICENSEE Users will be subject to the responsibilities set forth in Section 2.2 and enjoy the rights granted in Sections 2.1, 2.3(a) and 2.3(b). LICENSEE will not authorize or encourage LICENSEE Users to remove confidentiality notices, copyright notices, limited rights legends, restricted rights legends and other proprietary rights notices contained within the Programs and Program Materials to which they have access. +(d) Provide the Program and Program Materials to private individuals ("LICENSEE Users"), wherein the LICENSEE Users will be subject to the responsibilities set forth in Section 2.2 and enjoy the rights granted in Sections 2.1, 2.3(a) and 2.3(b). LICENSEE will not authorize or encourage LICENSEE Users to remove confidentiality notices, copyright notices, limited rights legends, restricted rights legends and other proprietary rights notices contained within the Programs and Program Materials to which they have access. 2.4 UNISYS has no obligation to deliver the Program or Program Materials to LICENSEE; LICENSEE must collect the materials through its own resources.
    diff --git a/webSite/UtilityMenu.html b/webSite/UtilityMenu.html index 6e1d01f..b5a80b5 100644 --- a/webSite/UtilityMenu.html +++ b/webSite/UtilityMenu.html @@ -1,7 +1,7 @@ retro-B5500 Emulator Utilities Menu - + @@ -10,16 +10,17 @@ - retro A-CONTROL logo + retro A-CONTROL logo -

    retro logo +

    retro logo
    Burroughs B5500 Emulator Utilities Menu

    -

    This page contains links to a number of standalone utilities for the web-based B5500 emulator. These utilities all run in a web browser. They should generally not be run at the same time the emulator is running from the webUI/B5500Console.html page. +

    This page contains links to a number of standalone utilities for the web-based B5500 emulator. These utilities all run in a web browser. They should generally not be used at the same time the emulator is running from the +B5500 Console page.

    • Cold Loader @@ -53,7 +54,7 @@ Copyright (c) 2013, Nigel Williams and Paul Kimpel • Licensed under the MIT License
      Revised - 2013-10-28 + 2014-07-19
      diff --git a/webSite/b5500.jpg b/webSite/b5500.jpg new file mode 100644 index 0000000..47e7bd7 Binary files /dev/null and b/webSite/b5500.jpg differ diff --git a/webSite/website.css b/webSite/website.css index deea095..e12564f 100644 --- a/webSite/website.css +++ b/webSite/website.css @@ -1,59 +1,191 @@ /*********************************************************************** -* retro-b5500/emulator index.css +* retro-b5500/emulator website.css ************************************************************************ * Copyright (c) 2013, Nigel Williams and Paul Kimpel. * Licensed under the MIT License, see http://www.opensource.org/licenses/mit-license.php ************************************************************************ -* B5500 emulator test site home page style sheet. +* B5500 emulator test site global style sheet. ************************************************************************ * 2013-06-18 P.Kimpel * Original version, from B5500Console.css. ***********************************************************************/ +@font-face { + font-family: "DejaVuSansMonoBookWeb"; + src: url("../webUI/resources/DejaVuSansMono-webfont.ttf") format("truetype"), + url("../webUI/resources/DejaVuSansMono-webfont.woff") format("woff"); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: "DejaVuSansWeb"; + src: url("../webUI/resources/DejaVuSans-webfont.ttf") format("truetype"), + url("../webUI/resources/DejaVuSans-webfont.woff") format("woff"); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: "DejaVuSansWeb"; + src: url("../webUI/resources/DejaVuSans-Bold-webfont.ttf") format("truetype"), + url("../webUI/resources/DejaVuSans-Bold-webfont.woff") format("woff"); + font-weight: bold; + font-style: normal; +} + BODY { position: relative; max-width: 80ex; - font-family: Arial, Helvetica, sans-serif; - font-size: medium; - margin: 4px} + font-family: DejaVuSansWeb, sans-serif; + font-size: small; + margin: 1ex} H1 { - margin-top: 18pt; - margin-bottom: 6pt; + margin-top: 4ex; + margin-bottom: 1ex; vertical-align: middle; font-size: larger; font-weight: bold} H2 { - margin-top: 12pt; - margin-bottom: 0; + margin-top: 2ex; + margin-bottom: 1ex; font-size: medium; font-weight: bold} - + +HR { + color: #333399; + height: 1px} + +PRE { + font-size: small; + font-family: DejaVuSansMonoBookWeb, monospace} + +P { + margin-top: 1ex; + margin-bottom: 1ex} + +DIV.indented { + margin-left: 2em} + +BLOCKQUOTE.finePrint { + font-size: smaller} + UL { - margin-top: 6pt; - margin-bottom: 6pt} - + margin-top: 1ex; + margin-bottom: 1ex} + UL LI { - margin-top: 3pt; - margin-bottom: 3pt} - + margin-top: 0.5ex; + margin-bottom: 0.5ex} + +DL { + margin-left: 2em} + +TABLE.normal, TABLE.standard { + border-spacing: 0; + border-collapse: collapse} + +TABLE.border{ + border-color: #CCC; + border-width: 1px; + border-style: solid} + +CAPTION { + text-align: center; + padding-left: 4px; + padding-right: 4px; + font-weight: bold} + +TH { + vertical-align: bottom; + text-align: center; + padding-left: 2px; + padding-right: 2px; + font-family: DejaVuSansWeb, sans-serif; + font-weight: bold} + +TABLE.normal>TBODY>TR, TABLE.standard>TBODY>TR { + vertical-align: top} + +TABLE.normal>TBODY>TR>TD, TABLE.standard>TBODY>TR>TD { + padding-top: 1px; + padding-bottom: 1px; + padding-left: 2px; + padding-right: 2px} + +TABLE.standard>THEAD>TR>TH, TABLE.standard>TBODY>TR>TD { + font-size: 85%} + +TABLE.standard>THEAD>TR>TH, TABLE.normal>THEAD>TR>TH { + text-align: center; + padding-left: 0.5ex; + padding-right: 0.5ex; + font-weight: bold} + +TABLE.border>THEAD>TR>TH, TABLE.border>TBODY>TR>TD { + border: 1px solid #CCCCCC} + +TD.text { + font-family: DejaVuSansMonoBookWeb, monospace; + text-align: left} + +TD.number { + white-space: nowrap; + text-align: right} + +BUTTON.actionBtn { + font-family: DejaVuSansWeb, sans-serif; + font-size: 9pt; + font-weight: bold; + color: black; + background-color: #D0D0D0} + +INPUT.actionBtn { + font-family: DejaVuSansWeb, sans-serif; + font-size: 9pt; + font-weight: bold; + color: black; + background-color: #D0D0D0} + .center { text-align: center} - .data { - font-family: Courier New, Courier, monospace; - text-align: left} + font-family: DejaVuSansMonoBookWeb, monospace; + text-align: left; + white-space: nowrap} .number { - font-family: Courier New, Courier, monospace; + font-family: DejaVuSansMonoBookWeb, monospace; text-align: right} - +.lj { + text-align: left} +.rj { + text-align: right} +.larger { + font-size: larger} +.large { + font-size: 125%} +.smaller { + font-size: smaller} +.small { + font-size: 60%} + IMG#retroButton { - float: right} - + float: right; + border: none; + margin-left: 1ex} + DIV#footerDiv { - position: fixed; - bottom: 1ex; - width: 100%; - text-align: center; + position: absolute; + left: 1ex; + bottom: 0; + background-color: white; + font-size: xx-small} + +DIV#lastModDiv { + position: absolute; + right: 1ex; + bottom: 0; + background-color: white; font-size: xx-small} diff --git a/webUI/B5500BlankPaper.html b/webUI/B5500BlankPaper.html new file mode 100644 index 0000000..f6f3d37 --- /dev/null +++ b/webUI/B5500BlankPaper.html @@ -0,0 +1,62 @@ + + + + +B5500 Blank Paper Page + + + + + + + + + +
      +
       
      + +
       
      + + \ No newline at end of file diff --git a/webUI/B5500CardPunch.css b/webUI/B5500CardPunch.css index 2fa8cf6..73b48c6 100644 --- a/webUI/B5500CardPunch.css +++ b/webUI/B5500CardPunch.css @@ -10,68 +10,19 @@ * Original version, from B5500CardReader.css. ***********************************************************************/ -BODY { - position: relative; - color: white; - background-color: black; - font-family: Arial, Helventica, sans-serif; - font-size: 9pt; +#punchBody { + height: 100%; + min-height: 100%; + overflow: hidden; + padding: 0} + +#CPDiv { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; margin: 4px} - -PRE { - font-family: Lucida Sans Typewriter, Courier New, Courier, monospace} - -DIV#CPDiv { - position: relative; - color: white; - background-color: #666; - width: 550px; - height: 194px; - border: 1px solid black; - border-radius: 8px; - padding: 0; - vertical-align: top} - -BUTTON.greenButton { - background-color: #060; - color: white; - font-family: Arial Rounded, Arial, Helvetica, sans-serif; - font-size: 8pt; - font-weight: normal; - width: 60px; - height: 40px; - border: 1px solid #DDD; - border-radius: 4px} - -BUTTON.blackButton { - background-color: black; - color: white; - font-family: Arial Rounded, Arial, Helvetica, sans-serif; - font-size: 8pt; - font-weight: normal; - width: 60px; - height: 40px; - border: 1px solid #DDD; - border-radius: 4px} - -BUTTON.redButton { - background-color: #900; - color: white; - font-family: Arial Rounded, Arial, Helvetica, sans-serif; - font-size: 8pt; - font-weight: normal; - width: 60px; - height: 40px; - border: 1px solid #DDD; - border-radius: 4px} - -BUTTON.greenLit { - color: black; - background-color: #0F0} - -BUTTON.redLit { - color: black; - background-color: #F00} #CPNotReadyLight { position: absolute; @@ -91,8 +42,24 @@ BUTTON.redLit { #CPStartBtn { position: absolute; top: 8px; - left: 212px;} + left: 212px} + +#CPOptionsDiv { + position: absolute; + top: 4px; + right: 8px; + width: auto} + +#CPStacker1Full { + position: absolute; + top: 24px; + right: 8px} +#CPStacker2Full { + position: absolute; + top: 34px; + right: 8px} + #CPStacker1Div { position: absolute; top: 56px; @@ -102,20 +69,24 @@ BUTTON.redLit { font-weight: bold} #CPStacker1Bar { - border: 1px solid white; - width: 450px} + width: 100%; + height: 12px; + border: 1px solid white} + +#CPStacker1Caption { + position: absolute; + right: 4px; + top: 0; + z-index: 1; + height: 12px; + color: black} #CPStacker1Frame { width: 100%; height: 60px; - margin-top: 1px; - border: 1px solid white; - color: black; - background-color: white; - font-family: Lucida Sans Typewriter, Courier New, Courier, monospace; - font-size: 8pt; - font-weight: normal} - + margin-top: 2px; + border: 1px solid white} + #CPStacker2Div { position: absolute; top: 140px; @@ -125,17 +96,20 @@ BUTTON.redLit { font-weight: bold} #CPStacker2Bar { - border: 1px solid white; - width: 450px} + width: 100%; + height: 12px; + border: 1px solid white} + +#CPStacker2Caption { + position: absolute; + right: 4px; + top: 0; + z-index: 1; + height: 12px; + color: black} #CPStacker2Frame { width: 100%; height: 30px; - margin-top: 1px; - border: 1px solid white; - color: black; - background-color: white; - font-family: Lucida Sans Typewriter, Courier New, Courier, monospace; - font-size: 8pt; - font-weight: normal} - + margin-top: 2px; + border: 1px solid white} diff --git a/webUI/B5500CardPunch.html b/webUI/B5500CardPunch.html index 0ff5ec2..36e4236 100644 --- a/webUI/B5500CardPunch.html +++ b/webUI/B5500CardPunch.html @@ -1,30 +1,58 @@ + + B5500 Emulator Card Punch + - - - + + - + -
      - +
      + +
      + + +
      + +
      STACKER 1 FULL
      +
      STACKER 2 FULL
      +
      - Stacker 1 - + + +
      - Stacker 2 - + + +
      diff --git a/webUI/B5500CardPunch.js b/webUI/B5500CardPunch.js index f049848..c0889df 100644 --- a/webUI/B5500CardPunch.js +++ b/webUI/B5500CardPunch.js @@ -16,9 +16,8 @@ "use strict"; /**************************************/ -function B5500CardPunch(mnemonic, unitIndex, designate, statusChange, signal) { +function B5500CardPunch(mnemonic, unitIndex, designate, statusChange, signal, options) { /* Constructor for the CardPunch object */ - var that = this; this.mnemonic = mnemonic; // Unit mnemonic this.unitIndex = unitIndex; // Ready-mask bit number @@ -28,6 +27,7 @@ function B5500CardPunch(mnemonic, unitIndex, designate, statusChange, signal) { this.timer = 0; // setCallback() token this.initiateStamp = 0; // timestamp of last initiation (set by IOUnit) + this.useAlgolGlyphs = options.algolGlyphs; // format Unicode for special Algol chars this.clear(); @@ -42,14 +42,14 @@ function B5500CardPunch(mnemonic, unitIndex, designate, statusChange, signal) { this.stacker2 = null; this.endOfStacker2 = null; this.window = window.open("../webUI/B5500CardPunch.html", mnemonic, - "scrollbars=no,resizable,width=560,height=204,left=0,top=220"); - this.window.addEventListener("load", function windowLoad() { - that.punchOnload(); - }, false); + "location=no,scrollbars=no,resizable,width=560,height=204,left=0,top=220"); + this.window.addEventListener("load", + B5500CentralControl.bindMethod(this, B5500CardPunch.prototype.punchOnload), false); } B5500CardPunch.prototype.cardsPerMinute = 300; // Punch speed B5500CardPunch.prototype.maxScrollLines = 850; // Maximum punch stacker scrollback (stacker capacity) +B5500CardPunch.prototype.rtrimRex = /\s+$/g; // regular expression for right-trimming card text /**************************************/ B5500CardPunch.prototype.$$ = function $$(e) { @@ -67,59 +67,30 @@ B5500CardPunch.prototype.clear = function clear() { this.finish = null; // external function to call for I/O completion this.runoutArmed = false; // EOF button: armed state - this.stopCount = 0; // stopCount for clearing the input buffer this.stacker1Count = 0; // cards in stacker #1 this.stacker2Count = 0; // cards in stacker #2 }; -/**************************************/ -B5500CardPunch.prototype.hasClass = function hasClass(e, name) { - /* returns true if element "e" has class "name" in its class list */ - var classes = e.className; - - if (!e) { - return false; - } else if (classes == name) { - return true; - } else { - return (classes.search("\\b" + name + "\\b") >= 0); - } -}; - -/**************************************/ -B5500CardPunch.prototype.addClass = function addClass(e, name) { - /* Adds a class "name" to the element "e"s class list */ - - if (!this.hasClass(e, name)) { - e.className += (" " + name); - } -}; - -/**************************************/ -B5500CardPunch.prototype.removeClass = function removeClass(e, name) { - /* Removes the class "name" from the element "e"s class list */ - - e.className = e.className.replace(new RegExp("\\b" + name + "\\b\\s*", "g"), ""); -}; - /**************************************/ B5500CardPunch.prototype.setPunchReady = function setPunchReady(ready) { /* Controls the ready-state of the card punch */ if (ready && !this.ready) { this.statusChange(1); - this.addClass(this.$$("CPStartBtn"), "greenLit") - this.removeClass(this.$$("CPNotReadyLight"), "redLit"); + B5500Util.addClass(this.$$("CPStartBtn"), "greenLit") + B5500Util.removeClass(this.$$("CPNotReadyLight"), "whiteLit"); this.ready = true; if (this.runoutArmed) { if (this.stacker1Count || this.stacker2Count) { if (this.window.confirm("Empty both " + this.mnemonic + " stackers?")) { this.stacker1Count = this.stacker2Count = 0; this.$$("CPStacker1Bar").value = 0; - this.$$("CPStacker2Bar").value = 0; + B5500Util.removeClass(this.$$("CPStacker1Full"), "annunciatorLit"); while (this.stacker1.firstChild) { this.stacker1.removeChild(this.stacker1.firstChild); } + this.$$("CPStacker2Bar").value = 0; + B5500Util.removeClass(this.$$("CPStacker2Full"), "annunciatorLit"); while (this.stacker2.firstChild) { this.stacker2.removeChild(this.stacker2.firstChild); } @@ -129,22 +100,49 @@ B5500CardPunch.prototype.setPunchReady = function setPunchReady(ready) { } } else if (!ready && this.ready) { this.statusChange(0); - this.removeClass(this.$$("CPStartBtn"), "greenLit") - this.addClass(this.$$("CPNotReadyLight"), "redLit"); + B5500Util.removeClass(this.$$("CPStartBtn"), "greenLit") + B5500Util.addClass(this.$$("CPNotReadyLight"), "whiteLit"); this.ready = false; } }; +/**************************************/ +B5500CardPunch.prototype.setAlgolGlyphs = function setAlgolGlyphs(makeItPretty) { + /* Controls the display of Unicode glyphs for the special Algol characters */ + + if (makeItPretty) { + if (!this.useAlgolGlyphs) { + B5500Util.xlateDOMTreeText(this.stacker1, B5500Util.xlateASCIIToAlgol); + B5500Util.xlateDOMTreeText(this.stacker2, B5500Util.xlateASCIIToAlgol); + } + } else { + if (this.useAlgolGlyphs) { + B5500Util.xlateDOMTreeText(this.stacker1, B5500Util.xlateAlgolToASCII); + B5500Util.xlateDOMTreeText(this.stacker2, B5500Util.xlateAlgolToASCII); + } + } + this.$$("CPAlgolGlyphsCheck").checked = makeItPretty; + this.useAlgolGlyphs = makeItPretty; +}; + +/**************************************/ +B5500CardPunch.prototype.appendLine = function appendLine(stacker, text) { + /* Appends a new
       element to the 
      +    
      + + + + +
      diff --git a/webUI/B5500CardReader.js b/webUI/B5500CardReader.js index 714f161..d0aa436 100644 --- a/webUI/B5500CardReader.js +++ b/webUI/B5500CardReader.js @@ -16,9 +16,8 @@ "use strict"; /**************************************/ -function B5500CardReader(mnemonic, unitIndex, designate, statusChange, signal) { +function B5500CardReader(mnemonic, unitIndex, designate, statusChange, signal, options) { /* Constructor for the CardReader object */ - var that = this; var x = (mnemonic == "CRA" ? 0 : 1)*110; this.mnemonic = mnemonic; // Unit mnemonic @@ -39,12 +38,11 @@ function B5500CardReader(mnemonic, unitIndex, designate, statusChange, signal) { } this.doc = null; this.window = window.open("../webUI/B5500CardReader.html", mnemonic, - "scrollbars=no,resizable,width=560,height=160,left=0,top="+x); - this.window.addEventListener("load", function windowLoad() { - that.readerOnload(); - }, false); + "location=no,scrollbars=no,resizable,width=560,height=160,left=0,top="+x); + this.window.addEventListener("load", + B5500CentralControl.bindMethod(this, B5500CardReader.prototype.readerOnload), false); - this.progressBar = null; + this.hopperBar = null; this.outHopperFrame = null; this.outHopper = null; } @@ -59,7 +57,7 @@ B5500CardReader.prototype.cardFilter = [ // Filter ASCII character values to val 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x3F,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F, // 20-2F 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F, // 30-3F 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F, // 40-4F - 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x3F,0x5D,0x3F,0x3F, // 50-5F + 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x3F,0x5D,0x3F,0x7E, // 50-5F 0x3F,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F, // 60-6F 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x7B,0x7C,0x7D,0x7E,0x3F]; // 70-7F @@ -84,36 +82,6 @@ B5500CardReader.prototype.$$ = function $$(e) { return this.doc.getElementById(e); }; -/**************************************/ -B5500CardReader.prototype.hasClass = function hasClass(e, name) { - /* returns true if element "e" has class "name" in its class list */ - var classes = e.className; - - if (!e) { - return false; - } else if (classes == name) { - return true; - } else { - return (classes.search("\\b" + name + "\\b") >= 0); - } -}; - -/**************************************/ -B5500CardReader.prototype.addClass = function addClass(e, name) { - /* Adds a class "name" to the element "e"s class list */ - - if (!this.hasClass(e, name)) { - e.className += (" " + name); - } -}; - -/**************************************/ -B5500CardReader.prototype.removeClass = function removeClass(e, name) { - /* Removes the class "name" from the element "e"s class list */ - - e.className = e.className.replace(new RegExp("\\b" + name + "\\b\\s*", "g"), ""); -}; - /**************************************/ B5500CardReader.prototype.setReaderReady = function setReaderReady(ready) { /* Controls the ready-state of the card reader */ @@ -122,12 +90,12 @@ B5500CardReader.prototype.setReaderReady = function setReaderReady(ready) { this.ready = ready; if (ready) { this.statusChange(1); - this.addClass(this.$$("CRStartBtn"), "greenLit") - this.removeClass(this.$$("CRNotReadyLight"), "redLit"); + B5500Util.addClass(this.$$("CRStartBtn"), "greenLit") + B5500Util.removeClass(this.$$("CRNotReadyLight"), "whiteLit"); } else { this.statusChange(0); - this.removeClass(this.$$("CRStartBtn"), "greenLit") - this.addClass(this.$$("CRNotReadyLight"), "redLit"); + B5500Util.removeClass(this.$$("CRStartBtn"), "greenLit") + B5500Util.addClass(this.$$("CRNotReadyLight"), "whiteLit"); } }; @@ -138,16 +106,15 @@ B5500CardReader.prototype.armEOF = function armEOF(armed) { this.eofArmed = armed; if (armed) { - this.addClass(this.$$("CREOFBtn"), "redLit"); + B5500Util.addClass(this.$$("CREOFBtn"), "whiteLit"); } else { - this.removeClass(this.$$("CREOFBtn"), "redLit"); + B5500Util.removeClass(this.$$("CREOFBtn"), "whiteLit"); } }; /**************************************/ B5500CardReader.prototype.CRStartBtn_onclick = function CRStartBtn_onclick(ev) { /* Handle the click event for the START button */ - var that = this; if (!this.ready) { if (this.bufIndex < this.bufLength) { @@ -176,8 +143,8 @@ B5500CardReader.prototype.CREOFBtn_onclick = function CREOFBtn_onclick(ev) { }; /**************************************/ -B5500CardReader.prototype.CRProgressBar_onclick = function CRProgressBar_onclick(ev) { - /* Handle the click event for the "input hopper" progress bar */ +B5500CardReader.prototype.CRHopperBar_onclick = function CRHopperBar_onclick(ev) { + /* Handle the click event for the "input hopper" meter bar */ if (this.bufIndex < this.bufLength && !this.ready) { if (this.window.confirm((this.bufLength-this.bufIndex).toString() + " of " + this.bufLength.toString() + @@ -185,7 +152,7 @@ B5500CardReader.prototype.CRProgressBar_onclick = function CRProgressBar_onclick this.buffer = ""; this.bufLength = 0; this.bufIndex = 0; - this.progressBar.value = 0; + this.hopperBar.value = 0; this.$$("CRFileSelector").value = null; // reset the control while (this.outHopper.childNodes.length > 0) { this.outHopper.removeChild(this.outHopper.firstChild); @@ -223,8 +190,8 @@ B5500CardReader.prototype.fileSelector_onChange = function fileSelector_onChange that.bufIndex = 0; that.bufLength = that.buffer.length; - that.$$("CRProgressBar").value = that.bufLength; - that.$$("CRProgressBar").max = that.bufLength; + that.$$("CRHopperBar").value = that.bufLength; + that.$$("CRHopperBar").max = that.bufLength; } for (x=f.length-1; x>=0; x--) { @@ -260,10 +227,24 @@ B5500CardReader.prototype.readCardAlpha = function readCardAlpha(buffer, length) } for (x=0; x 0) { // an actual "?" + if (c == 0x3F) { // an actual "?" buffer[x] = 0x3F; - } else if (c > 0x7F) { // Unicode R Us -- NOT! - this.errorMask |= 0x08; + if (x == 0) { // it's an invalid char only if in first column + this.errorMask |= 0x08; + } + } else if (c > 0x7F) { // possibly a Unicode Algol glyph + switch (c) { + case 0x00A0: buffer[x] = 0x20; break; // non-breaking space + case 0x00D7: buffer[x] = 0x7C; break; // multiply + case 0x2190: buffer[x] = 0x7E; break; // left-arrow + case 0x2260: buffer[x] = 0x21; break; // not-equal + case 0x2264: buffer[x] = 0x7B; break; // less-than-or-equal + case 0x2265: buffer[x] = 0x7D; break; // greater-than-or-equal + default: + buffer[x] = 0x3F; + this.errorMask |= 0x08; + break; + } } else if ((buffer[x] = this.cardFilter[c]) == 0x3F) { // intentional assignment this.errorMask |= 0x08; } @@ -325,44 +306,34 @@ B5500CardReader.prototype.beforeUnload = function beforeUnload(ev) { /**************************************/ B5500CardReader.prototype.readerOnload = function readerOnload() { /* Initializes the reader window and user interface */ - var that = this; + var de; this.doc = this.window.document; - this.doc.title = "retro-B5500 " + this.mnemonic; + de = this.doc.documentElement; + this.doc.title = "retro-B5500 Card Reader " + this.mnemonic; - this.progressBar = this.$$("CRProgressBar"); + this.hopperBar = this.$$("CRHopperBar"); this.outHopperFrame = this.$$("CROutHopperFrame"); - this.outHopperFrame.contentDocument.head.innerHTML += ""; - this.outHopper = this.doc.createElement("pre"); - this.outHopperFrame.contentDocument.body.appendChild(this.outHopper); - - this.window.addEventListener("beforeunload", this.beforeUnload, false); + this.outHopper = this.outHopperFrame.contentDocument.getElementById("Paper"); this.armEOF(false); this.setReaderReady(false); - this.$$("CRFileSelector").addEventListener("change", function fileSelectorChange(ev) { - that.fileSelector_onChange(ev); - }, false); + this.window.addEventListener("beforeunload", + B5500CardReader.prototype.beforeUnload, false); + this.$$("CRFileSelector").addEventListener("change", + B5500CentralControl.bindMethod(this, B5500CardReader.prototype.fileSelector_onChange), false); + this.$$("CRStartBtn").addEventListener("click", + B5500CentralControl.bindMethod(this, B5500CardReader.prototype.CRStartBtn_onclick), false); + this.$$("CRStopBtn").addEventListener("click", + B5500CentralControl.bindMethod(this, B5500CardReader.prototype.CRStopBtn_onclick), false); + this.$$("CREOFBtn").addEventListener("click", + B5500CentralControl.bindMethod(this, B5500CardReader.prototype.CREOFBtn_onclick), false); + this.hopperBar.addEventListener("click", + B5500CentralControl.bindMethod(this, B5500CardReader.prototype.CRHopperBar_onclick), false); - this.$$("CRStartBtn").addEventListener("click", function startClick(ev) { - that.CRStartBtn_onclick(ev); - }, false); - - this.$$("CRStopBtn").addEventListener("click", function stopClick(ev) { - that.CRStopBtn_onclick(ev); - }, false); - - this.$$("CREOFBtn").addEventListener("click", function eofClick(ev) { - that.CREOFBtn_onclick(ev); - }, false); - - this.progressBar.addEventListener("click", function progressClick(ev) { - that.CRProgressBar_onclick(ev); - }, false); + this.window.resizeBy(de.scrollWidth - this.window.innerWidth + 4, // kludge for right-padding/margin + de.scrollHeight - this.window.innerHeight); }; /**************************************/ @@ -398,9 +369,9 @@ B5500CardReader.prototype.read = function read(finish, buffer, length, mode, con }); if (this.bufIndex < this.bufLength) { - this.progressBar.value = this.bufLength-this.bufIndex; + this.hopperBar.value = this.bufLength-this.bufIndex; } else { - this.progressBar.value = 0; + this.hopperBar.value = 0; this.buffer = ""; // discard the input buffer this.bufLength = 0; this.bufIndex = 0; @@ -472,6 +443,6 @@ B5500CardReader.prototype.shutDown = function shutDown() { if (this.timer) { clearCallback(this.timer); } - this.window.removeEventListener("beforeunload", this.beforeUnload, false); + this.window.removeEventListener("beforeunload", B5500CardReader.prototype.beforeUnload, false); this.window.close(); }; diff --git a/webUI/B5500ColdLoader.html b/webUI/B5500ColdLoader.html index e70440b..15492c8 100644 --- a/webUI/B5500ColdLoader.html +++ b/webUI/B5500ColdLoader.html @@ -1,12 +1,9 @@ + + B5500 Disk Subsystem Coldstart Loader - - - - - - + + + + + - + - - + -
      +
      - - + + - - - - - + + + + + - + + +
      +
      + Using (none)+(none) +
      ?.??
      - diff --git a/webUI/B5500Console.js b/webUI/B5500Console.js new file mode 100644 index 0000000..95a54a1 --- /dev/null +++ b/webUI/B5500Console.js @@ -0,0 +1,699 @@ +/*********************************************************************** +* retro-b5500/emulator B5500Console.js +************************************************************************ +* Copyright (c) 2012,2014, Nigel Williams and Paul Kimpel. +* Licensed under the MIT License, see +* http://www.opensource.org/licenses/mit-license.php +************************************************************************ +* B5500 Operations Console Javascript module. +* +* Implements event handlers and control functions for the B5500 emulator +* operations console. +* +************************************************************************ +* 2014-07-20 P.Kimpel +* Original version, extracted from B5500Console.html. +***********************************************************************/ +"use strict"; + +window.addEventListener("load", function() { + var aControl; // A-Control button/light + var aNormal; // A-Normal button/light + var bControl; // B-Control button/light + var bNormal; // B-Normal button/light + var cc; // B5500CentralControl object + var ccLatches = [0, 0, 0]; // I/O- & interrupt-reporting latches + var ccLightsMap = new Array(6); // Misc annunciator DOM objects + var intLightsMap = new Array(48); // Interrupt annunciator DOM objects + var lastInterruptMask = 0; // Prior mask of interrupt annunciator lights + var lastCCMask = 0; // Prior mask of misc annunciator lights + var lastUnitBusyMask = 0; // Prior mask of unit-busy annunciator lights + var lastPANormalRate = -1; // Prior PA normal-state busy rate + var lastPAControlRate = -1; // Prior PA control-state busy rate + var lastPBNormalRate = -1; // Prior PB normal-state busy rate + var lastPBControlRate = -1; // Prior PB normal-state busy rate + var perf = performance; // (it's faster if locally cached) + var perLightsMap = new Array(48); // Peripheral I/O annunciator DOM objects + var procDelay; // Current average P1 delay [ms] + var procSlack; // Current average P1 slack time [%] + var showAnnunciators = true; // Display non-purist console mode (annunciators) + var timer = 0; // Console display update timer control cookie + var timerInterval = 50; // Console display update interval [ms] + + function $$(id) { + return document.getElementById(id); + } + + function setAnnunciators(showEm) { + $$("CentralControl").style.display = (showEm && cc.poweredUp ? "block" : "none"); + $$("RetroVersion").style.visibility = (showEm ? "visible" : "hidden"); + $$("RetroLogoImage").style.display = (showEm ? "inline" : "none"); + $$("B5500LogoImage").style.display = (showEm ? "none" : "inline"); + $$("ConfigLabel").style.display = (showEm ? "inline" : "none"); + } + + function evaluateNotReady(config) { + /* Evaluates the system configuration to determine whether the + NOT READY lamp should be illuminated */ + var lampClass = "whiteButton"; + + switch (false) { + case config.PA.enabled || config.PA.enabled: + case (config.PA.enabled && !config.PB1L) || (config.PB.enabled && config.PB1L): + case config.IO1.enabled || config.IO2.enabled || config.IO3.enabled || config.IO4.enabled: + case config.memMod[0].enabled: + case config.units.SPO.enabled: + case config.units.DKA.enabled: + lampClass += " whiteLit"; + } + + $$("NotReadyBtn").className = lampClass; + } + + function BurroughsLogo_Click(ev) { + showAnnunciators = !showAnnunciators; + setAnnunciators(showAnnunciators); + } + + function B5500Logo_Click(ev) { + var sysConfig = new B5500SystemConfig(); + + if (cc.poweredUp) { + alert("System configuration changes are\nnot allowed while power is on."); + } else { + $$("ConfigLabel").style.display = "none"; + sysConfig.openConfigUI(); + } + } + + function PowerOnBtn_Click(ev) { + var sysConfig = new B5500SystemConfig(); + + function applyPower(config) { + $$("HaltBtn").className = "redButton redLit"; + $$("PowerOnBtn").disabled = true; + $$("PowerOffBtn").disabled = false; + $$("LoadSelectBtn").disabled = false; + $$("LoadBtn").disabled = false; + $$("HaltBtn").disabled = true; + $$("MemoryCheckBtn").disabled = false; + cc.powerOn(config); + $$("LoadSelectBtn").className = "yellowButton" + (cc.cardLoadSelect ? " yellowLit" : ""); + evaluateNotReady(config); + setAnnunciators(showAnnunciators); + } + + function youMayPowerOnWhenReady_Gridley(config) { + /* Called-back by sysConfig.getSystemConfig with the requested configuration */ + + if (!config) { + alert("No System Configuration found\nCANNOT POWER ON."); + } else { + $$("PowerOnBtn").className = "greenButton greenLit"; + $$("SysConfigName").textContent = config.configName; + $$("StorageName").textContent = config.units.DKA.storageName; + if (showAnnunciators) { + lampTest(applyPower, config); + } else { + applyPower(config); + } + } + } + + sysConfig.getSystemConfig(null, youMayPowerOnWhenReady_Gridley); // get current system config + return true; + } + + function PowerOffBtn_Click(ev) { + $$("PowerOnBtn").className = "greenButton"; + $$("ANormalBtn").className = "yellowButton"; + $$("AControlBtn").className = "yellowButton"; + $$("BNormalBtn").className = "yellowButton"; + $$("BControlBtn").className = "yellowButton"; + $$("LoadSelectBtn").className = "yellowButton"; + $$("MemoryCheckBtn").className = "redButton"; + $$("NotReadyBtn").className = "whiteButton"; + $$("HaltBtn").className = "redButton"; + cc.powerOff(); + $$("PowerOnBtn").disabled = false; + $$("PowerOffBtn").disabled = true; + $$("LoadSelectBtn").disabled = true; + $$("LoadBtn").disabled = true; + $$("HaltBtn").disabled = true; + $$("MemoryCheckBtn").disabled = true; + $$("CentralControl").style.display = "none"; + if (timer) { + clearInterval(timer); + timer = 0; + } + return true; + } + + function HaltBtn_Click(ev) { + $$("HaltBtn").className = "redButton redLit"; + cc.halt(); + $$("HaltBtn").disabled = true; + $$("LoadBtn").disabled = false; + dasBlinkenlicht(); + if (timer) { + clearInterval(timer); + timer = 0; + } + } + + function LoadBtn_Click(ev) { + var result; + + window.open("", "SPO").focus(); // re-focus the SPO window + result = cc.load(false); + switch (result) { + case 0: // load initiated successfully + $$("HaltBtn").className = "redButton"; + $$("HaltBtn").disabled = false; + $$("LoadBtn").disabled = true; + timer = setInterval(dasBlinkenlicht, timerInterval); + break; + case 1: + alert("P1 busy or not available"); + break; + case 2: + alert("SPO is not ready"); + break; + case 3: + alert("SPO is busy"); + break; + case 4: + alert("DKA is not ready"); + break; + case 5: + alert("DKA is busy"); + break; + default: + alert("cc.load() result = " + result); + break; + } + } + + function LoadSelectBtn_Click(ev) { + if (cc.cardLoadSelect) { + cc.cardLoadSelect = 0; + $$("LoadSelectBtn").className = "yellowButton"; + } else { + cc.cardLoadSelect = 1; + $$("LoadSelectBtn").className = "yellowButton yellowLit"; + } + } + + function dumpState(caption) { + /* Generates a dump of the processor states and all of memory */ + var doc; + var lastPhase = -2; + var win = window.open("", "", "location=no,resizable,scrollbars,status"); + var x; + + var htmlMatch = /[<>&"]/g; // regular expression for escaping HTML text + + function htmlFilter(c) { + /* Used to escape HTML-sensitive characters in a string */ + switch (c) { + case "&": + return "&"; + case "<": + return "<"; + case ">": + return ">"; + case "\"": + return """; + default: + return c; + } + } + + function escapeHTML(text) { + /* Returns "text" as escaped HTML */ + + return text.replace(htmlMatch, htmlFilter); + } + + function writer(phase, text) { + /* Call-back function for cc.dumpSystemState */ + + switch (phase) { + case 0: + lastPhase = phase; + doc.writeln(escapeHTML(text)); + doc.writeln("User Agent: " + navigator.userAgent); + break; + + case 1: + case 2: + if (phase == lastPhase) { + doc.writeln(escapeHTML(text)); + } else { + lastPhase = phase; + doc.writeln(); + doc.writeln(escapeHTML(text)); + doc.writeln(); + } + break; + + case 32: + if (phase != lastPhase) { + lastPhase = phase; + doc.writeln(); + } + doc.writeln(); + doc.writeln(escapeHTML(text)); + break; + + case -1: + break; + } // switch + } + + doc = win.document; + doc.open(); + doc.writeln("retro-B5500 Console State Dump"); + doc.writeln(""); + doc.write("
      ");
      +
      +        cc.dumpSystemState(caption, writer);
      +
      +        doc.writeln("
      ") + doc.close(); + win.focus(); + } + + function displayCallbacks() { + /* Builds a table of outstanding callbacks */ + var cb; + var cbs = clearCallback(0); + var cookie; + var e; + var body = document.createElement("tbody"); + var oldBody = $$("CallbackBody"); + var row; + + for (cookie in cbs) { + cb = cbs[cookie]; + row = document.createElement("tr"); + + e = document.createElement("td"); + e.appendChild(document.createTextNode(cookie.toString())); + row.appendChild(e); + + e = document.createElement("td"); + e.appendChild(document.createTextNode(cb.delay.toFixed(2))); + row.appendChild(e); + + e = document.createElement("td"); + e.appendChild(document.createTextNode(cb.context.mnemonic || "??")); + row.appendChild(e); + + e = document.createElement("td"); + e.appendChild(document.createTextNode((cb.args ? cb.args.length : 0).toString())); + row.appendChild(e); + body.appendChild(row); + } + + body.id = oldBody.id; + oldBody.parentNode.replaceChild(body, oldBody); + } + + function displayCentralControl() { + /* Displays the I/O and interrupt status in CentralControl */ + var cells; + var s; + var interruptMask; + var interruptChange; + var ccMask; + var ccChange; + var unitBusyMask; + var unitBusyChange; + var x; + + cc.fetchCCLatches(ccLatches); + ccMask = ccLatches[0]; + ccChange = lastCCMask ^ ccMask; + lastCCMask = ccMask; + + interruptMask = ccLatches[1] % 0x4000; + interruptChange = lastInterruptMask ^ interruptMask; + lastInterruptMask = interruptMask; + + unitBusyMask = ccLatches[2]; + unitBusyChange = lastUnitBusyMask ^ unitBusyMask; + lastUnitBusyMask = unitBusyMask; + + x = 0; + while (ccChange) { + if (ccChange & 0x01) { + if (ccLightsMap[x]) { + ccLightsMap[x].style.visibility = (ccMask & 0x01 ? "visible" : "hidden"); + } + } + ccMask >>>= 1; + ccChange >>>= 1; + x++; + } + + x = 47; + while (interruptChange) { + if (interruptChange & 0x01) { + if (intLightsMap[x]) { + intLightsMap[x].style.visibility = (interruptMask & 0x01 ? "visible" : "hidden"); + } + } + interruptMask >>>= 1; + interruptChange >>>= 1; + x--; + } + + x = 47; + while (unitBusyChange) { + if (unitBusyChange & 0x01) { + if (perLightsMap[x]) { + perLightsMap[x].style.visibility = (unitBusyMask & 0x01 ? "visible" : "hidden"); + } + } + unitBusyMask >>>= 1; + unitBusyChange >>>= 1; + x--; + } + } + + function dasBlinkenlicht() { + var cycles; + var pa = cc.PA; + var pb = cc.PB; + var p1 = cc.P1; + var stateRate; + + cycles = p1.normalCycles+p1.controlCycles; + + if (pa) { + if (pa.normalCycles+pa.controlCycles <= 0) { + if (lastPAControlRate != -1) { + lastPAControlRate = -1; + aControl.className = "yellowButton"; + aNormal.className = "yellowButton"; + } + } else { + stateRate = Math.round(pa.normalCycles/cycles*6 + 0.25); + if (stateRate != lastPANormalRate) { + lastPANormalRate = stateRate; + switch (stateRate) { + case 0: + aNormal.className = "yellowButton"; + break; + case 1: + //aNormal.className = "yellowButton yellowLit1"; + //break; + case 2: + aNormal.className = "yellowButton yellowLit2"; + break; + case 3: + //aNormal.className = "yellowButton yellowLit3"; + //break; + case 4: + aNormal.className = "yellowButton yellowLit4"; + break; + case 5: + //aNormal.className = "yellowButton yellowLit5"; + //break; + default: + aNormal.className = "yellowButton yellowLit"; + break; + } + } + + stateRate = Math.round(pa.controlCycles/cycles*6 + 0.25); + if (stateRate != lastPAControlRate) { + lastPAControlRate = stateRate; + switch (stateRate) { + case 0: + aControl.className = "yellowButton"; + break; + case 1: + //aControl.className = "yellowButton yellowLit1"; + //break; + case 2: + aControl.className = "yellowButton yellowLit2"; + break; + case 3: + //aControl.className = "yellowButton yellowLit3"; + //break; + case 4: + aControl.className = "yellowButton yellowLit4"; + break; + case 5: + //aControl.className = "yellowButton yellowLit5"; + //break; + default: + aControl.className = "yellowButton yellowLit"; + break; + } + } + + pa.controlCycles = pa.normalCycles = 0; + } + } + + if (pb) { + if (pb.normalCycles+pb.controlCycles <= 0) { + if (lastPBControlRate != -1) { + bControl.className = "yellowButton"; + bNormal.className = "yellowButton"; + lastPBControlRate = -1; + } + } else { + stateRate = Math.round(pb.normalCycles/cycles*6 + 0.25); + if (stateRate != lastPBNormalRate) { + lastPBNormalRate = stateRate; + switch (stateRate) { + case 0: + bNormal.className = "yellowButton"; + break; + case 1: + //bNormal.className = "yellowButton yellowLit1"; + //break; + case 2: + bNormal.className = "yellowButton yellowLit2"; + break; + case 3: + //bNormal.className = "yellowButton yellowLit3"; + //break; + case 4: + bNormal.className = "yellowButton yellowLit4"; + break; + case 5: + //bNormal.className = "yellowButton yellowLit5"; + //break; + default: + bNormal.className = "yellowButton yellowLit"; + break; + } + } + + stateRate = Math.round(pb.controlCycles/cycles*6 + 0.25); + if (stateRate != lastPBControlRate) { + lastPBControlRate = stateRate; + switch (stateRate) { + case 0: + bControl.className = "yellowButton"; + break; + case 1: + //bControl.className = "yellowButton yellowLit1"; + //break; + case 2: + bControl.className = "yellowButton yellowLit2"; + break; + case 3: + //bControl.className = "yellowButton yellowLit3"; + //break; + case 4: + bControl.className = "yellowButton yellowLit4"; + break; + case 5: + //bControl.className = "yellowButton yellowLit5"; + //break; + default: + bControl.className = "yellowButton yellowLit"; + break; + } + } + + pb.controlCycles = pb.normalCycles = 0; + } + } + + procDelay.innerHTML = p1.delayDeltaAvg.toFixed(1); + procSlack.innerHTML = (p1.procSlackAvg/p1.procRunAvg*100).toFixed(1); + + if (showAnnunciators) { + displayCentralControl(); + } + // displayCallbacks(); + } + + function buildLightMaps() { + /* Builds tables of the DOM entries for the annunciator lights, for efficient access */ + var mnem; + var spec; + var x; + + ccLightsMap[0] = $$("AD1F"); + ccLightsMap[1] = $$("AD2F"); + ccLightsMap[2] = $$("AD3F"); + ccLightsMap[3] = $$("AD4F"); + ccLightsMap[4] = $$("P2BF"); + ccLightsMap[5] = $$("HP2F"); + + for (x=3; x<=16; x++) { + intLightsMap[50-x] = $$("CCI" + (x+100).toString().substring(1) + "F"); + } + + for (mnem in B5500CentralControl.unitSpecs) { + spec = B5500CentralControl.unitSpecs[mnem]; + perLightsMap[spec.unitIndex] = $$(mnem); + } + } + + function lampTest(callback, callbackParam) { + /* Lights up the operator console, waits a bit, then turns everything + off and calls the "callback" function, passing "callbackParam". + The Power On lamp is not affected */ + + function switchEm(mode) { + var visibility = (mode ? "visible" : "hidden"); + var x; + + $$("ANormalBtn").className = "yellowButton" + (mode ? " yellowLit" : ""); + $$("AControlBtn").className = "yellowButton" + (mode ? " yellowLit" : ""); + $$("BNormalBtn").className = "yellowButton" + (mode ? " yellowLit" : ""); + $$("BControlBtn").className = "yellowButton" + (mode ? " yellowLit" : ""); + $$("LoadSelectBtn").className = "yellowButton" + (mode ? " yellowLit" : ""); + $$("MemoryCheckBtn").className = "redButton" + (mode ? " redLit" : ""); + $$("NotReadyBtn").className = "whiteButton" + (mode ? " whiteLit" : ""); + $$("HaltBtn").className = "redButton" + (mode ? " redLit" : ""); + + for (x in ccLightsMap) { + if (ccLightsMap[x]) { + ccLightsMap[x].style.visibility = visibility; + } + } + + for (x in intLightsMap) { + if (intLightsMap[x]) { + intLightsMap[x].style.visibility = visibility; + } + } + + for (x in perLightsMap) { + if (perLightsMap[x]) { + perLightsMap[x].style.visibility = visibility; + } + } + + if (!mode) { + setAnnunciators(showAnnunciators); + setTimeout(callback, 1000, callbackParam); + } + } + + setAnnunciators(true); + $$("CentralControl").style.display = "block"; // overrides if !cc.poweredUp + switchEm(1); + setTimeout(switchEm, 2000, 0); + } + + function clearStatus(inSeconds) { + /* Delays for "inSeconds" seconds, then clears the StatusLabel element */ + + setTimeout(function(ev) { + $$("StatusLabel").textContent = ""; + }, inSeconds*1000); + } + + function checkBrowser() { + /* Checks whether this browser can support the necessary stuff */ + var missing = ""; + + if (!window.indexedDB) {missing += ", IndexedDB"} + if (!window.ArrayBuffer) {missing += ", ArrayBuffer"} + if (!window.DataView) {missing += ", DataView"} + if (!window.Blob) {missing += ", Blob"} + if (!window.File) {missing += ", File"} + if (!window.FileReader) {missing += ", FileReader"} + if (!window.FileList) {missing += ", FileList"} + if (!window.postMessage) {missing += ", window.postMessage"} + if (!(window.performance && "now" in performance)) {missing += ", performance.now"} + + if (missing.length == 0) { + return false; + } else { + alert("No can do... your browser does not support the following features:\n" + + missing.substring(2)); + return true; + } + } + + /***** window.onload() outer block *****/ + + $$("RetroVersion").innerHTML = B5500CentralControl.version; + if (!checkBrowser()) { + window.name = "B5500Console"; + $$("BurroughsLogo").addEventListener("click", BurroughsLogo_Click, false); + $$("B5500Logo").addEventListener("click", B5500Logo_Click, false); + $$("PowerOnBtn").addEventListener("click", PowerOnBtn_Click, false); + $$("PowerOffBtn").addEventListener("click", PowerOffBtn_Click, false); + $$("HaltBtn").addEventListener("click", HaltBtn_Click, false); + $$("LoadBtn").addEventListener("click", LoadBtn_Click, false); + $$("LoadSelectBtn").addEventListener("click", LoadSelectBtn_Click, false); + $$("MemoryCheckBtn").addEventListener("click", function(ev) { + dumpState("Memory-Check Button"); + }, false); + + window.applicationCache.addEventListener("checking", function(ev) { + $$("StatusLabel").textContent = "Checking for emulator update..."; + }, false); + window.applicationCache.addEventListener("noupdate", function(ev) { + $$("StatusLabel").textContent = "Emulator version is current."; + clearStatus(5); + }, false); + window.applicationCache.addEventListener("obsolete", function(ev) { + $$("StatusLabel").textContent = "Emulator off-line installation has been disabled."; + clearStatus(15); + }, false); + window.applicationCache.addEventListener("downloading", function(ev) { + $$("StatusLabel").textContent = "Initiating download for emulator update..."; + }, false); + window.applicationCache.addEventListener("progress", function(ev) { + var text = (ev.loaded && ev.total ? ev.loaded.toString() + "/" + ev.total.toString() : "Unknown number of"); + $$("StatusLabel").textContent = text + " resources downloaded thus far..."; + }, false); + window.applicationCache.addEventListener("updateready", function(ev) { + $$("StatusLabel").textContent = "Emulator update completed. Reload this page to activate the new version."; + clearStatus(10); + }, false); + window.applicationCache.addEventListener("cached", function(ev) { + $$("StatusLabel").textContent = "Emulator is now installed for off-line use."; + clearStatus(10); + }, false); + window.applicationCache.addEventListener("error", function(ev) { + $$("StatusLabel").textContent = "Unable to check for emulator update."; + clearStatus(10); + }, false); + + aControl = $$("AControlBtn"); + aNormal = $$("ANormalBtn"); + bControl = $$("BControlBtn"); + bNormal = $$("BNormalBtn"); + procDelay = $$("procDelay"); + procSlack = $$("procSlack"); + buildLightMaps(); + + cc = new B5500CentralControl(window); + window.dumpState = dumpState; + } +}, false); diff --git a/webUI/B5500DatacomUnit.css b/webUI/B5500DatacomUnit.css index f663e13..21e45a6 100644 --- a/webUI/B5500DatacomUnit.css +++ b/webUI/B5500DatacomUnit.css @@ -2,7 +2,8 @@ * retro-b5500/emulator B5500DatacomUnit.css ************************************************************************ * Copyright (c) 2013, Nigel Williams and Paul Kimpel. -* Licensed under the MIT License, see http://www.opensource.org/licenses/mit-license.php +* Licensed under the MIT License, see +* http://www.opensource.org/licenses/mit-license.php ************************************************************************ * B5500 emulator Datacom web interface style sheet. ************************************************************************ @@ -10,49 +11,66 @@ * Original version, from B5500SPOUnit.css. ***********************************************************************/ -BODY { - position: relative; - margin: 4px} +#DatacomUnit { + height: 100%; + min-height: 100%; + overflow: hidden; + padding: 0} -PRE { - font-family: Lucida Sans Typewriter, Courier New, Courier, monospace; - font-size: 8pt; - margin: 0} - -IFRAME#TermOut { - height: 480px; - width: 560px; - border: 1px solid black} - -BODY.TermOut { - background-color: white; - font-family: Lucida Sans Typewriter, Courier New, Courier, monospace; - font-size: 8pt} - -DIV#TermControlsDiv { - margin-bottom: 2px; - text-align: left} - -BUTTON.greenButton { - background-color: #060; - color: white; - height: 24px; - font-family: Arial Rounded, Arial, Helvetica, sans-serif; - font-size: 8pt; - font-weight: bold; - border: 1px solid black; - border-radius: 4px} - -BUTTON.greenLit { +#TermOut { + position: absolute; + left: 8px; + right: 8px; + top: 40px; + bottom: 8px; + min-height: 120px; + min-width: 120px; + overflow-x: hidden; + overflow-y: scroll; color: black; - background-color: #0F0} + background-color: white; + padding: 4px; + border: 1px solid gray} -BUTTON.blackBorder { - border: 1px solid black} +#Paper { + margin-left: 0; + margin-right: 0; + margin-top: 2000px; + margin-bottom: 0; + padding: 0} + +#EndOfPaper { + display: block; + margin: 0; + padding: 0; + opacity: 0} +#EndOfPaper.hidden { + display: none} + +#InputBox { + display: none; + margin: 0; + padding: 0; + border: none; + background-color: #FF9} +#InputBox.visible { + display: block} +#InputBox:focus { + border: none; + outline: none} /* to suppress Chrome's default outline */ + +#TermControlsDiv { + white-space: nowrap; + overflow: hidden; + margin: 8px} + +#TermConnectBtn { + height: 24px} SPAN.annunciator { + width: 2em; + text-align: right; color: black; - font-family: Arial Rounded, Arial, Helvetica, sans-serif; font-size: 8pt; font-weight: bold; visibility: hidden} diff --git a/webUI/B5500DatacomUnit.html b/webUI/B5500DatacomUnit.html index 909b810..d482177 100644 --- a/webUI/B5500DatacomUnit.html +++ b/webUI/B5500DatacomUnit.html @@ -1,43 +1,79 @@ + + B5500 Emulator Datacom Unit + - - - + + - +
      - +    - NR   - IDLE   - RR   - WR   - IBZ   - OBZ   - AB   - INT   - FB   + NR   + IDLE   + RR   + WR   + IBZ   + OBZ   + AB   + INT   + FB   Offset: - 0   + 0   Length: - 0   + 0   Col: - 0   + 0  
      - +
      +
       
      + +
       
      +
      \ No newline at end of file diff --git a/webUI/B5500DatacomUnit.js b/webUI/B5500DatacomUnit.js index 7ba219f..8ca6517 100644 --- a/webUI/B5500DatacomUnit.js +++ b/webUI/B5500DatacomUnit.js @@ -24,7 +24,7 @@ "use strict"; /**************************************/ -function B5500DatacomUnit(mnemonic, unitIndex, designate, statusChange, signal) { +function B5500DatacomUnit(mnemonic, unitIndex, designate, statusChange, signal, options) { /* Constructor for the DatacomUnit object */ this.maxScrollLines = 1500; // Maximum amount of printer scrollback @@ -53,9 +53,9 @@ function B5500DatacomUnit(mnemonic, unitIndex, designate, statusChange, signal) this.paper = null; this.endOfPaper = null; this.window = window.open("../webUI/B5500DatacomUnit.html", mnemonic, - "scrollbars,resizable,width=580,height=540"); - this.window.moveTo((screen.availWidth-this.window.outerWidth)/2, (screen.availHeight-this.window.outerHeight)/2); - this.window.addEventListener("load", B5500CentralControl.bindMethod(B5500DatacomUnit.prototype.datacomOnload, this), false); + "location=no,scrollbars,resizable,width=520,height=540"); + this.window.addEventListener("load", B5500CentralControl.bindMethod(this, + B5500DatacomUnit.prototype.datacomOnload), false); } // this.bufState enumerations @@ -90,6 +90,7 @@ B5500DatacomUnit.prototype.clear = function clear() { this.abnormal = false; // buffer in abnormal state this.bufIndex = 0; // current offset into buffer + this.bufCheckPoint = 0; // last bufIndex when input overflowed a line this.bufLength = 0; // current buffer length this.connected = false; // buffer/adapter is currently connected this.errorMask = 0; // error mask for finish() @@ -102,36 +103,6 @@ B5500DatacomUnit.prototype.clear = function clear() { this.bufState = this.bufNotReady; // Current state of datacom buffer }; -/**************************************/ -B5500DatacomUnit.prototype.hasClass = function hasClass(e, name) { - /* returns true if element "e" has class "name" in its class list */ - var classes = e.className; - - if (!e) { - return false; - } else if (classes == name) { - return true; - } else { - return (classes.search("\\b" + name + "\\b") >= 0); - } -}; - -/**************************************/ -B5500DatacomUnit.prototype.addClass = function addClass(e, name) { - /* Adds a class "name" to the element "e"s class list */ - - if (!this.hasClass(e, name)) { - e.className += (" " + name); - } -}; - -/**************************************/ -B5500DatacomUnit.prototype.removeClass = function removeClass(e, name) { - /* Removes the class "name" from the element "e"s class list */ - - e.className = e.className.replace(new RegExp("\\b" + name + "\\b\\s*", "g"), ""); -}; - /**************************************/ B5500DatacomUnit.prototype.showBufferIndex = function showBufferIndex() { /* Formats the buffer index and length, and the column counter, for display */ @@ -148,63 +119,63 @@ B5500DatacomUnit.prototype.setState = function setState(newState) { this.showBufferIndex(); if (this.abnormal) { - this.addClass(this.$$("Abnormal"), "textLit") + B5500Util.addClass(this.$$("Abnormal"), "textLit") } else { - this.removeClass(this.$$("Abnormal"), "textLit"); + B5500Util.removeClass(this.$$("Abnormal"), "textLit"); } if (this.interrupt) { - this.addClass(this.$$("Interrupt"), "textLit") + B5500Util.addClass(this.$$("Interrupt"), "textLit") } else { - this.removeClass(this.$$("Interrupt"), "textLit"); + B5500Util.removeClass(this.$$("Interrupt"), "textLit"); } if (this.fullBuffer) { - this.addClass(this.$$("FullBuffer"), "textLit") + B5500Util.addClass(this.$$("FullBuffer"), "textLit") } else { - this.removeClass(this.$$("FullBuffer"), "textLit"); + B5500Util.removeClass(this.$$("FullBuffer"), "textLit"); } if (this.bufState != newState) { switch (this.bufState) { case this.bufNotReady: - this.removeClass(this.$$("NotReadyState"), "textLit"); + B5500Util.removeClass(this.$$("NotReadyState"), "textLit"); break; case this.bufIdle: - this.removeClass(this.$$("IdleState"), "textLit"); + B5500Util.removeClass(this.$$("IdleState"), "textLit"); break; case this.bufInputBusy: - this.removeClass(this.$$("InputBusyState"), "textLit"); + B5500Util.removeClass(this.$$("InputBusyState"), "textLit"); break; case this.bufReadReady: - this.removeClass(this.$$("ReadReadyState"), "textLit"); + B5500Util.removeClass(this.$$("ReadReadyState"), "textLit"); break; case this.bufOutputBusy: - this.removeClass(this.$$("OutputBusyState"), "textLit"); + B5500Util.removeClass(this.$$("OutputBusyState"), "textLit"); break; case this.bufWriteReady: - this.removeClass(this.$$("WriteReadyState"), "textLit"); + B5500Util.removeClass(this.$$("WriteReadyState"), "textLit"); break; } switch (newState) { case this.bufNotReady: - this.addClass(this.$$("NotReadyState"), "textLit"); + B5500Util.addClass(this.$$("NotReadyState"), "textLit"); break; case this.bufIdle: - this.addClass(this.$$("IdleState"), "textLit"); + B5500Util.addClass(this.$$("IdleState"), "textLit"); break; case this.bufInputBusy: - this.addClass(this.$$("InputBusyState"), "textLit"); + B5500Util.addClass(this.$$("InputBusyState"), "textLit"); break; case this.bufReadReady: - this.addClass(this.$$("ReadReadyState"), "textLit"); + B5500Util.addClass(this.$$("ReadReadyState"), "textLit"); break; case this.bufOutputBusy: - this.addClass(this.$$("OutputBusyState"), "textLit"); + B5500Util.addClass(this.$$("OutputBusyState"), "textLit"); break; case this.bufWriteReady: - this.addClass(this.$$("WriteReadyState"), "textLit"); + B5500Util.addClass(this.$$("WriteReadyState"), "textLit"); break; } @@ -219,7 +190,7 @@ B5500DatacomUnit.prototype.termDisconnect = function termDisconnect() { if (this.connected) { this.bufLength = 0; this.bufIndex = 0; - this.removeClass(this.$$("TermConnectBtn"), "greenLit"); + B5500Util.removeClass(this.$$("TermConnectBtn"), "greenLit"); this.interrupt = true; this.abnormal = true; this.setState(this.bufIdle); @@ -233,7 +204,7 @@ B5500DatacomUnit.prototype.termConnect = function termConnect() { /* Sets the status of the datacom unit to connected */ if (!this.connected) { - this.addClass(this.$$("TermConnectBtn"), "greenLit"); + B5500Util.addClass(this.$$("TermConnectBtn"), "greenLit"); this.interrupt = true; this.abnormal = true; this.setState(this.bufWriteReady); @@ -243,17 +214,17 @@ B5500DatacomUnit.prototype.termConnect = function termConnect() { }; /**************************************/ -B5500DatacomUnit.prototype.appendEmptyLine = function appendEmptyLine() { +B5500DatacomUnit.prototype.appendEmptyLine = function appendEmptyLine(text) { /* Removes excess lines already printed, then appends a new
       element
           to the 
      +
      + + + \ No newline at end of file diff --git a/webUI/B5500LinePrinter.js b/webUI/B5500LinePrinter.js new file mode 100644 index 0000000..f78ede3 --- /dev/null +++ b/webUI/B5500LinePrinter.js @@ -0,0 +1,427 @@ +/*********************************************************************** +* retro-b5500/emulator B5500LinePrinter.js +************************************************************************ +* Copyright (c) 2014, Nigel Williams and Paul Kimpel. +* Licensed under the MIT License, see +* http://www.opensource.org/licenses/mit-license.php +************************************************************************ +* B5500 Line Printer Peripheral Unit module. +* +* Defines a Line Printer peripheral unit type. +* +************************************************************************ +* 2014-08-31 P.Kimpel +* Original version, cloned from B5500DummyPrinter.js and B5500CardPunch.js. +***********************************************************************/ +"use strict"; + +/**************************************/ +function B5500LinePrinter(mnemonic, unitIndex, designate, statusChange, signal, options) { + /* Constructor for the LinePrinter object */ + var h = screen.availHeight*0.60; + var w = 900; + + this.mnemonic = mnemonic; // Unit mnemonic + this.unitIndex = unitIndex; // Ready-mask bit number + this.designate = designate; // IOD unit designate number + this.statusChange = statusChange; // external function to call for ready-status change + this.signal = signal; // external function to call for special signals (e.g,. Printer Finished) + + this.timer = 0; // setCallback() token + this.initiateStamp = 0; // timestamp of last initiation (set by IOUnit) + this.useAlgolGlyphs = options.algolGlyphs; // format Unicode for special Algol chars + this.useGreenbar = true; // format "greenbar" shading on the paper + this.lpi = 6; // lines/inch (actually, lines per greenbar group, should be even) + + this.clear(); + + this.window = window.open("", mnemonic); + if (this.window) { + this.shutDown(); // destroy the previously-existing window + this.window = null; + } + this.doc = null; + this.barGroup = null; // current greenbar line group + this.paperDoc = null; // the content document for the paper frame + this.paper = null; // the "paper" we print on + this.endOfPaper = null; // dummy element used to control scrolling + this.paperMeter = null; // element showing amount of paper remaining + this.window = window.open("../webUI/B5500LinePrinter.html", mnemonic, + "location=no,scrollbars,resizable,width=" + w + ",height=" + h + + ",left=0,top=" + (screen.availHeight - h)); + this.window.addEventListener("load", + B5500CentralControl.bindMethod(this, B5500LinePrinter.prototype.printerOnload), false); +} +B5500LinePrinter.prototype.linesPerMinute = 1040; // B329 line printer +B5500LinePrinter.prototype.maxPaperLines = 150000; // maximum printer scrollback (about a box of paper) +B5500LinePrinter.prototype.rtrimRex = /\s+$/g; // regular expression for right-trimming lines +B5500LinePrinter.prototype.theColorGreen = "#CFC"; // for greenbar shading + +/**************************************/ +B5500LinePrinter.prototype.$$ = function $$(e) { + return this.doc.getElementById(e); +}; + +/**************************************/ +B5500LinePrinter.prototype.clear = function clear() { + /* Initializes (and if necessary, creates) the printer unit state */ + + this.ready = false; // ready status + this.busy = false; // busy status + + this.errorMask = 0; // error mask for finish() + this.finish = null; // external function to call for I/O completion + + this.paperLeft = this.maxPaperLines;// lines remaining in paper supply + this.formFeedCount = 0; // counter for triple-formfeed => rip paper + this.groupLinesLeft = 0; // lines remaining in current greenbar group + this.topOfForm = false; // start new page flag +}; + +/**************************************/ +B5500LinePrinter.prototype.setPrinterReady = function setPrinterReady(ready) { + /* Controls the ready-state of the line printer */ + + this.formFeedCount = 0; + if (ready && !this.ready) { + this.statusChange(1); + B5500Util.addClass(this.$$("LPStartBtn"), "greenLit") + B5500Util.removeClass(this.$$("LPNotReadyLight"), "whiteLit"); + this.ready = true; + } else if (!ready && this.ready) { + this.statusChange(0); + B5500Util.removeClass(this.$$("LPStartBtn"), "greenLit") + B5500Util.addClass(this.$$("LPNotReadyLight"), "whiteLit"); + this.ready = false; + } +}; + +/**************************************/ +B5500LinePrinter.prototype.ripPaper = function ripPaper(ev) { + /* Handles an event to clear the "paper" from the printer */ + + this.formFeedCount = 0; + if (this.window.confirm("Do you want to clear the \"paper\" from the printer?")) { + B5500Util.removeClass(this.$$("LPEndOfPaperBtn"), "whiteLit"); + this.paperMeter.value = this.paperLeft = this.maxPaperLines; + while (this.paper.firstChild) { + this.paper.removeChild(this.paper.firstChild); + } + } +}; + +/**************************************/ +B5500LinePrinter.prototype.appendLine = function appendLine(text) { + /* Appends one line, with a trailing new-line character, to the current + greenbar group, this.barGroup. This handles top-of-form and greenbar + highlighting */ + var feed = "\n"; + + if (this.groupLinesLeft <= 0) { + // Start the green half of a greenbar group + this.barGroup = this.doc.createElement("pre"); + this.paper.appendChild(this.barGroup); + this.groupLinesLeft = this.lpi; + if (!this.atTopOfForm) { + this.barGroup.className = "paper greenBar"; + } else { + this.atTopOfForm = false; + this.barGroup.className = "paper greenBar topOfForm"; + } + } else if (this.groupLinesLeft*2 == this.lpi) { + // Start the white half of a greenbar group + this.barGroup = this.doc.createElement("pre"); + this.paper.appendChild(this.barGroup); + this.barGroup.className = "paper whiteBar"; + } else if (this.groupLinesLeft == 1) { + feed = ""; // no linefeed at end of a bar group + } else if ((this.groupLinesLeft-1)*2 == this.lpi) { + feed = ""; // ditto + } + + this.barGroup.appendChild(this.doc.createTextNode(text + feed)); + --this.groupLinesLeft; +}; + +/**************************************/ +B5500LinePrinter.prototype.printLine = function printLine(text, control) { + /* Prints one line to the "paper", handling carriage control and greenbar + group completion. For now, SPACE 0 (overprintng) is treated as single-spacing */ + var lines = 1; + + this.appendLine(text || "\xA0"); + if (control > 1) { + ++lines; + this.appendLine("\xA0"); + } else if (control < 0) { + while(this.groupLinesLeft > 0) { + ++lines; + this.appendLine("\xA0"); + } + this.atTopOfForm = true; + } + + if (this.paperLeft > 0) { + this.paperMeter.value = this.paperLeft -= lines; + } else { + this.setPrinterReady(false); + B5500Util.addClass(this.$$("LPEndOfPaperBtn"), "whiteLit"); + } +}; + +/**************************************/ +B5500LinePrinter.prototype.setAlgolGlyphs = function setAlgolGlyphs(makeItPretty) { + /* Controls the display of Unicode glyphs for the special Algol characters */ + + if (makeItPretty) { + if (!this.useAlgolGlyphs) { + B5500Util.xlateDOMTreeText(this.paper, B5500Util.xlateASCIIToAlgol); + } + } else { + if (this.useAlgolGlyphs) { + B5500Util.xlateDOMTreeText(this.paper, B5500Util.xlateAlgolToASCII); + } + } + this.$$("LPAlgolGlyphsCheck").checked = makeItPretty; + this.useAlgolGlyphs = makeItPretty; +}; + +/**************************************/ +B5500LinePrinter.prototype.setGreenbar = function setGreenbar(useGreen) { + /* Controls the display of "greenbar" shading on the paper */ + var rule = null; + var rules = null; + var sheet; + var ss = this.paperDoc.styleSheets; + var x; + + // First, find the embedded style sheet for the paper frame. + for (x=ss.length-1; x>=0; --x) { + sheet = ss[x]; + if (sheet.ownerNode.id == "PaperFrameStyles") { + rules = sheet.cssRules; + // Next, search through the rules for the one that controls greenbar shading. + for (x=rules.length-1; x>=0; --x) { + rule = rules[x]; + if (rule.selectorText == "PRE.greenBar") { + // Found it: now flip the background color. + rule.style.backgroundColor = (useGreen ? this.theColorGreen : "white"); + } + } + break; // out of for loop + } + } + this.$$("LPGreenbarCheck").checked = useGreen; + this.useGreenbar = useGreen; +}; + +/**************************************/ +B5500LinePrinter.prototype.LPStartBtn_onclick = function LPStartBtn_onclick(ev) { + /* Handle the click event for the START button */ + + if (!this.ready && this.paperLeft > 0) { + this.formFeedCount = 0; + this.setPrinterReady(true); + } +}; + +/**************************************/ +B5500LinePrinter.prototype.LPStopBtn_onclick = function LPStopBtn_onclick(ev) { + /* Handle the click event for the STOP button */ + + if (this.ready) { + this.formFeedCount = 0; + this.setPrinterReady(false); + } +}; + +/**************************************/ +B5500LinePrinter.prototype.LPSpaceBtn_onclick = function LPSpaceBtn_onclick(ev) { + /* Handle the click event for the Skip To Heading button */ + + if (!this.ready) { + this.formFeedCount = 0; + this.printLine("", 1); + this.endOfPaper.scrollIntoView(); + } +}; + +/**************************************/ +B5500LinePrinter.prototype.LPFormFeedBtn_onclick = function LPFormFeedBtn_onclick(ev) { + /* Handle the click event for the Skip To Heading button */ + + if (!this.ready) { + this.printLine("", -1); + this.endOfPaper.scrollIntoView(); + if (++this.formFeedCount >= 3) { + this.ripPaper(); + } + } +}; + +/**************************************/ +B5500LinePrinter.prototype.LPEndOfPaperBtn_onclick = function LPEndOfPaperBtn_onclick(ev) { + /* Handle the click event for the End Of Paper button. If the printer is in + and end-of-paper condition, this will make the printer ready, but it will + still be in an EOP condition. The next time a print line is received, the + EOP condition will force it not-ready again. You can print only one line + at a time (presumably to the end of the current page. The EOP condition can + be cleared by clicking Skip To Heading three times to "rip" the paper */ + + if (this.paperLeft <= 0 && !this.ready) { + this.formFeedCount = 0; + B5500Util.removeClass(this.$$("LPEndOfPaperBtn"), "whiteLit"); + this.setPrinterReady(true); + } +}; + +/**************************************/ +B5500LinePrinter.prototype.LPAlgolGlyphsCheck_onclick = function LPAlgolGlyphsCheck_onclick(ev) { + /* Handle the click event for the Algol Glyphs checkbox */ + + this.setAlgolGlyphs(ev.target.checked); +}; + +/**************************************/ +B5500LinePrinter.prototype.LPGreenbarCheck_onclick = function LPGreenbarCheck_onclick(ev) { + /* Handle the click event for the Greenbar checkbox */ + + this.setGreenbar(ev.target.checked); +}; + +/**************************************/ +B5500LinePrinter.prototype.beforeUnload = function beforeUnload(ev) { + var msg = "Closing this window will make the device unusable.\n" + + "Suggest you stay on the page and minimize this window instead"; + + ev.preventDefault(); + ev.returnValue = msg; + return msg; +}; + +/**************************************/ +B5500LinePrinter.prototype.printerOnload = function printerOnload() { + /* Initializes the line printer window and user interface */ + var newChild; + + this.doc = this.window.document; + this.doc.title = "retro-B5500 Line Printer " + this.mnemonic; + + this.paperDoc = this.$$("LPPaperFrame").contentDocument; + this.paper = this.paperDoc.getElementById("Paper"); + this.endOfPaper = this.paperDoc.getElementById("EndOfPaper"); + this.paperMeter = this.$$("LPPaperMeter"); + + newChild = this.paperDoc.createElement("div"); + newChild.id = this.paper.id; + this.paper.parentNode.replaceChild(newChild, this.paper); + this.paper = newChild; + + this.setAlgolGlyphs(this.useAlgolGlyphs); + this.setGreenbar(this.useGreenbar); + this.paperMeter.max = this.maxPaperLines; + this.paperMeter.low = this.maxPaperLines*0.1; + this.paperMeter.value = this.paperLeft = this.maxPaperLines; + this.setPrinterReady(true); + + this.window.addEventListener("beforeunload", + B5500LinePrinter.prototype.beforeUnload, false); + this.$$("LPEndOfPaperBtn").addEventListener("click", + B5500CentralControl.bindMethod(this, B5500LinePrinter.prototype.LPEndOfPaperBtn_onclick), false); + this.$$("LPFormFeedBtn").addEventListener("click", + B5500CentralControl.bindMethod(this, B5500LinePrinter.prototype.LPFormFeedBtn_onclick), false); + this.$$("LPSpaceBtn").addEventListener("click", + B5500CentralControl.bindMethod(this, B5500LinePrinter.prototype.LPSpaceBtn_onclick), false); + this.$$("LPAlgolGlyphsCheck").addEventListener("click", + B5500CentralControl.bindMethod(this, B5500LinePrinter.prototype.LPAlgolGlyphsCheck_onclick), false); + this.$$("LPGreenbarCheck").addEventListener("click", + B5500CentralControl.bindMethod(this, B5500LinePrinter.prototype.LPGreenbarCheck_onclick), false); + this.$$("LPStopBtn").addEventListener("click", + B5500CentralControl.bindMethod(this, B5500LinePrinter.prototype.LPStopBtn_onclick), false); + this.$$("LPStartBtn").addEventListener("click", + B5500CentralControl.bindMethod(this, B5500LinePrinter.prototype.LPStartBtn_onclick), false); +}; + +/**************************************/ +B5500LinePrinter.prototype.read = function read(finish, buffer, length, mode, control) { + /* Initiates a read operation on the unit */ + + finish(0x04, 0); +}; + +/**************************************/ +B5500LinePrinter.prototype.space = function space(finish, length, control) { + /* Initiates a space operation on the unit */ + + finish(0x04, 0); +}; + +/**************************************/ +B5500LinePrinter.prototype.write = function write(finish, buffer, length, mode, control) { + /* Initiates a write operation on the unit */ + var text; + + this.errorMask = 0; + if (length > 0) { + text = String.fromCharCode.apply(null, buffer.subarray(0, length)).replace(this.rtrimRex, ''); + if (this.useAlgolGlyphs) { + text = B5500Util.xlateASCIIToAlgol(text); + } + } + + if (control || length) { + this.printLine(text, control); + } + + this.timer = setCallback(this.mnemonic, this, + 60000/this.linesPerMinute + this.initiateStamp - performance.now(), + this.signal); + finish(this.errorMask, 0); + this.endOfPaper.scrollIntoView(); +}; + +/**************************************/ +B5500LinePrinter.prototype.erase = function erase(finish, length) { + /* Initiates an erase operation on the unit */ + + finish(0x04, 0); +}; + +/**************************************/ +B5500LinePrinter.prototype.rewind = function rewind(finish) { + /* Initiates a rewind operation on the unit */ + + finish(0x04, 0); +}; + +/**************************************/ +B5500LinePrinter.prototype.readCheck = function readCheck(finish, length, control) { + /* Initiates a read check operation on the unit */ + + finish(0x04, 0); +}; + +/**************************************/ +B5500LinePrinter.prototype.readInterrogate = function readInterrogate(finish, control) { + /* Initiates a read interrogate operation on the unit */ + + finish(0x04, 0); +}; + +/**************************************/ +B5500LinePrinter.prototype.writeInterrogate = function writeInterrogate(finish, control) { + /* Initiates a write interrogate operation on the unit */ + + finish(0x04, 0); +}; + +/**************************************/ +B5500LinePrinter.prototype.shutDown = function shutDown() { + /* Shuts down the device */ + + if (this.timer) { + clearCallback(this.timer); + } + this.window.removeEventListener("beforeunload", B5500LinePrinter.prototype.beforeUnload, false); + this.window.close(); +}; \ No newline at end of file diff --git a/webUI/B5500MagTapeDrive.css b/webUI/B5500MagTapeDrive.css index 6fbb94c..d4dda47 100644 --- a/webUI/B5500MagTapeDrive.css +++ b/webUI/B5500MagTapeDrive.css @@ -10,70 +10,22 @@ * Original version, from B5500CardReader.css. ***********************************************************************/ -BODY { - position: relative; - background-color: black; +#magTapeBody { + height: 100%; + min-height: 100%; + overflow: hidden; + padding: 0} + +#MTDiv { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; margin: 4px} -DIV#MTDiv { - position: relative; - background-color: #666; - width: 550px; - height: 110px; - border: 1px solid black; - border-radius: 8px; - padding: 0; - vertical-align: top} - -BUTTON.yellowButton { - background-color: #990; - color: black; - font-family: Arial Rounded, Arial, Helvetica, sans-serif; - font-size: 8pt; - font-weight: normal; - width: 60px; - height: 40px; - border: 1px solid #DDD; - border-radius: 4px} - -BUTTON.blackButton { - background-color: black; - color: white; - font-family: Arial Rounded, Arial, Helvetica, sans-serif; - font-size: 8pt; - font-weight: normal; - width: 60px; - height: 40px; - border: 1px solid #DDD; - border-radius: 4px} - -BUTTON.redButton { - background-color: #900; - color: white; - font-family: Arial Rounded, Arial, Helvetica, sans-serif; - font-size: 8pt; - font-weight: normal; - width: 60px; - height: 40px; - border: 1px solid #DDD; - border-radius: 4px} - -BUTTON.yellowLit { - background-color: #FF0} - -BUTTON.redLit { - color: black; - background-color: #F00} - SPAN.annunciator { - position: absolute; - color: #666; - font-family: Arial Rounded, Arial, Helvetica, sans-serif; - font-size: 7pt; - font-weight: bold} - -SPAN.whiteLit { - color: white} + position: absolute} #MTUnloadBtn { position: absolute; @@ -105,7 +57,7 @@ SPAN.whiteLit { top: 8px; left: 348px;} -IMG#MTReel { +#MTReel { position: absolute; height: 40px; visibility: hidden; @@ -129,36 +81,47 @@ IMG#MTReel { top: 34px; right: 8px} -#MTFileName { +#MTStatusDiv { position: absolute; - border: none; - background-color: #666; - color: white; - width: 530px; top: 58px; - left: 8px} + left: 8px; + right: 8px; + bottom: auto} -#MTProgressBar { +#MTFileName { + width: 100%; + font-family: DejaVuSansWeb, sans-serif; + color: white; + background-color: inherit; + border: none} + +#MTReelBar { + margin-top: 4px; + width: 100%; + height: 16px; + border: 1px solid white} + +#MTReelBarCaption { position: absolute; - border: 1px solid white; - width: 530px; - top: 84px; - left: 8px} + right: 4px; + top: 24px; + z-index: 1; + height: 12px; + color: black; + font-weight: bold} /* Tape Load Panel */ -DIV#MTLoaderDiv { +#MTLoaderDiv { background-color: #666; width: 480px; height: 86px; border-radius: 8px; padding: 8px; color: white; - font-family: Arial Rounded, Arial, Helvetica, sans-serif; - font-size: 8pt; - font-weight: bold} + font-size: 8pt} -DIV#MTLoaderInnerDiv { +#MTLoaderInnerDiv { position: relative; height: 100%; width: 100%} @@ -195,10 +158,12 @@ DIV#MTLoaderInnerDiv { #MTLoadCancelBtn { position: absolute; + height: 20px; bottom: 0; right: 64px} #MTLoadOKBtn { position: absolute; + height: 20px; bottom: 0; right: 0} diff --git a/webUI/B5500MagTapeDrive.html b/webUI/B5500MagTapeDrive.html index 368850d..cde9610 100644 --- a/webUI/B5500MagTapeDrive.html +++ b/webUI/B5500MagTapeDrive.html @@ -1,34 +1,54 @@ + + B5500 Emulator Magnetic Tape Drive + - - - + + - + -
      - - +
      + + - - + + - + UNLOADED AT BOT AT EOT REWINDING - - - +
      + + + +
      diff --git a/webUI/B5500MagTapeDrive.js b/webUI/B5500MagTapeDrive.js index 407d9e3..607e07b 100644 --- a/webUI/B5500MagTapeDrive.js +++ b/webUI/B5500MagTapeDrive.js @@ -28,10 +28,8 @@ "use strict"; /**************************************/ -function B5500MagTapeDrive(mnemonic, unitIndex, designate, statusChange, signal) { +function B5500MagTapeDrive(mnemonic, unitIndex, designate, statusChange, signal, options) { /* Constructor for the MagTapeDrive object */ - var that = this; - var x = ((mnemonic.charCodeAt(2) - "A".charCodeAt(0))*30); this.mnemonic = mnemonic; // Unit mnemonic this.unitIndex = unitIndex; // Ready-mask bit number @@ -44,20 +42,20 @@ function B5500MagTapeDrive(mnemonic, unitIndex, designate, statusChange, signal) this.clear(); + this.loadWindow = null; // handle for the tape loader window + this.reelBar = null; // handle for tape-full meter + this.reelIcon = null; // handle for the reel spinner + this.window = window.open("", mnemonic); if (this.window) { - this.shutDown(); // destroy the previously-existing window + this.shutDown(); // destroy any previously-existing window this.window = null; } this.doc = null; this.window = window.open("../webUI/B5500MagTapeDrive.html", mnemonic, - "scrollbars=no,resizable,width=560,height=120,left=280,top="+x); - this.window.addEventListener("load", function windowLoad() { - that.tapeDriveOnLoad(); - }, false); - - this.progressBar = null; - this.reelIcon = null; + "location=no,scrollbars=no,resizable,width=560,height=120,left=280,top=0"); + this.window.addEventListener("load", + B5500CentralControl.bindMethod(this, B5500MagTapeDrive.prototype.tapeDriveOnload), false); } // this.tapeState enumerations @@ -87,7 +85,9 @@ B5500MagTapeDrive.prototype.bcdTapeMark = 0x8F; // .bcd image EOF code B5500MagTapeDrive.prototype.reelCircumference = 10*Math.PI; // max circumference of tape [inches] -B5500MagTapeDrive.prototype.maxSpinAngle = 33; +B5500MagTapeDrive.prototype.spinUpdateInterval = 15; + // milliseconds between reel icon angle updates +B5500MagTapeDrive.prototype.maxSpinAngle = 25; // max angle to rotate reel image [degrees] B5500MagTapeDrive.prototype.bcdXlateInOdd = [ // Translate odd parity BIC to ASCII @@ -166,52 +166,76 @@ B5500MagTapeDrive.prototype.clear = function clear() { this.bufIndex = 0; // IOUnit buffer current offset }; -/**************************************/ -B5500MagTapeDrive.prototype.hasClass = function hasClass(e, name) { - /* returns true if element "e" has class "name" in its class list */ - var classes = e.className; - - if (!e) { - return false; - } else if (classes == name) { - return true; - } else { - return (classes.search("\\b" + name + "\\b") >= 0); - } -}; - -/**************************************/ -B5500MagTapeDrive.prototype.addClass = function addClass(e, name) { - /* Adds a class "name" to the element "e"s class list */ - - if (!this.hasClass(e, name)) { - e.className += (" " + name); - } -}; - -/**************************************/ -B5500MagTapeDrive.prototype.removeClass = function removeClass(e, name) { - /* Removes the class "name" from the element "e"s class list */ - - e.className = e.className.replace(new RegExp("\\b" + name + "\\b\\s*", "g"), ""); -}; - /**************************************/ B5500MagTapeDrive.prototype.spinReel = function spinReel(inches) { - /* Rotates the reel image icon an appropriate amount based on the number of - inches of tape movement. The rotation is limited to this.maxSpinAngle degrees + /* Rotates the reel image icon an appropriate amount based on the "inches" + of tape to be moved. The rotation is limited to this.maxSpinAngle degrees in either direction so that movement remains apparent to the viewer */ var circumference = this.reelCircumference*(1 - this.tapeInches/this.maxTapeLength/2); var degrees = inches/circumference*360; - if (degrees >= this.maxSpinAngle) { + if (degrees > this.maxSpinAngle) { degrees = this.maxSpinAngle; } else if (degrees < -this.maxSpinAngle) { degrees = -this.maxSpinAngle; } this.reelAngle = (this.reelAngle + degrees)%360; + this.reelIcon.style["-webkit-transform"] = "rotate(" + this.reelAngle.toFixed(0) + "deg)"; // temp for Chrome this.reelIcon.style.transform = "rotate(" + this.reelAngle.toFixed(0) + "deg)"; + + if (this.tapeInches < this.imgMaxInches) { + this.reelBar.value = this.imgMaxInches - this.tapeInches; + } else { + this.reelBar.value = 0; + } +}; + +/**************************************/ +B5500MagTapeDrive.prototype.moveTape = function moveTape(inches, delay, callBack) { + /* Delays the I/O during tape motion, during which it animates the reel image + icon. At the completion of the "delay" time in milliseconds, "callBack" is + called with no parameters. */ + var delayLeft = delay; // milliseconds left to delay + var direction = (inches < 0 ? -1 : 1); + var inchesLeft = inches; // inches left to move tape + var lastStamp = performance.now(); // last timestamp for spinDelay + + function spinFinish() { + this.timer = 0; + if (inchesLeft != 0) { + this.spinReel(inchesLeft); + } + callBack.call(this); + } + + function spinDelay() { + var motion; + var stamp = performance.now(); + var interval = stamp - lastStamp; + + if (interval <= 0) { + interval = this.spinUpdateInterval/2; + if (interval > delayLeft) { + interval = delayLeft; + } + } + + if ((delayLeft -= interval) > this.spinUpdateInterval) { + lastStamp = stamp; + this.timer = setCallback(this.mnemonic, this, this.spinUpdateInterval, spinDelay); + } else { + this.timer = setCallback(this.mnemonic, this, delayLeft, spinFinish); + } + motion = this.tapeSpeed*interval/1000*direction; + inchesLeft -= motion; + if (inchesLeft*direction < 0) { // inchesLeft crossed zero + inchesLeft = direction = 0; + } + this.spinReel(motion); + } + + spinDelay.call(this); }; /**************************************/ @@ -223,11 +247,12 @@ B5500MagTapeDrive.prototype.setAtBOT = function setAtBOT(atBOT) { if (atBOT) { this.imgIndex = 0; this.tapeInches = 0; - this.addClass(this.$$("MTAtBOTLight"), "whiteLit"); - this.progressBar.value = this.imgMaxInches; + B5500Util.addClass(this.$$("MTAtBOTLight"), "annunciator"); + this.reelBar.value = this.imgMaxInches; this.reelIcon.style.transform = "rotate(0deg)"; + this.reelIcon.style["-webkit-transform"] = "rotate(0deg)"; // temp for Chrome } else { - this.removeClass(this.$$("MTAtBOTLight"), "whiteLit"); + B5500Util.removeClass(this.$$("MTAtBOTLight"), "annunciatorLit"); } } }; @@ -239,10 +264,10 @@ B5500MagTapeDrive.prototype.setAtEOT = function setAtEOT(atEOT) { if (atEOT ^ this.atEOT) { this.atEOT = atEOT; if (atEOT) { - this.addClass(this.$$("MTAtEOTLight"), "whiteLit"); - this.progressBar.value = 0; + B5500Util.addClass(this.$$("MTAtEOTLight"), "annunciatorLit"); + this.reelBar.value = 0; } else { - this.removeClass(this.$$("MTAtEOTLight"), "whiteLit"); + B5500Util.removeClass(this.$$("MTAtEOTLight"), "annunciatorLit"); } } }; @@ -265,13 +290,13 @@ B5500MagTapeDrive.prototype.setTapeUnloaded = function setTapeUnloaded() { this.$$("MTRewindBtn").disabled = true; this.$$("MTWriteRingBtn").disabled = true; this.$$("MTFileName").value = ""; - this.removeClass(this.$$("MTRemoteBtn"), "yellowLit"); - this.addClass(this.$$("MTLocalBtn"), "yellowLit"); - this.removeClass(this.$$("MTWriteRingBtn"), "redLit"); - this.addClass(this.$$("MTUnloadedLight"), "whiteLit"); + B5500Util.removeClass(this.$$("MTRemoteBtn"), "yellowLit"); + B5500Util.addClass(this.$$("MTLocalBtn"), "yellowLit"); + B5500Util.removeClass(this.$$("MTWriteRingBtn"), "redLit"); + B5500Util.addClass(this.$$("MTUnloadedLight"), "annunciatorLit"); this.setAtBOT(false); this.setAtEOT(false); - this.progressBar.value = 0; + this.reelBar.value = 0; this.reelIcon.style.visibility = "hidden"; if (this.timer) { clearCallback(this.timer); @@ -295,13 +320,13 @@ B5500MagTapeDrive.prototype.setTapeRemote = function setTapeRemote(ready) { if (ready) { this.tapeState = this.tapeRemote; this.statusChange(1); - this.removeClass(this.$$("MTLocalBtn"), "yellowLit"); - this.addClass(this.$$("MTRemoteBtn"), "yellowLit"); + B5500Util.removeClass(this.$$("MTLocalBtn"), "yellowLit"); + B5500Util.addClass(this.$$("MTRemoteBtn"), "yellowLit"); } else { this.tapeState = this.tapeLocal; this.statusChange(0); - this.removeClass(this.$$("MTRemoteBtn"), "yellowLit"); - this.addClass(this.$$("MTLocalBtn"), "yellowLit"); + B5500Util.removeClass(this.$$("MTRemoteBtn"), "yellowLit"); + B5500Util.addClass(this.$$("MTLocalBtn"), "yellowLit"); } } }; @@ -316,7 +341,7 @@ B5500MagTapeDrive.prototype.setWriteRing = function setWriteRing(writeRing) { case this.tapeRemote: if (this.writeRing && !writeRing) { this.writeRing = false; - this.removeClass(this.$$("MTWriteRingBtn"), "redLit"); + B5500Util.removeClass(this.$$("MTWriteRingBtn"), "redLit"); } break; } @@ -337,7 +362,8 @@ B5500MagTapeDrive.prototype.loadTape = function loadTape() { var tapeInches = 0; // selected tape length in inches var tapeLengthSelect = null; // tape length list element var win = this.window.open("B5500MagTapeLoadPanel.html", this.mnemonic + "Load", - "scrollbars=no,resizable,width=508,height=112"); + "location=no,scrollbars=no,resizable,width=508,height=112,left=" + + (this.window.screenX+16) +",top=" + (this.window.screenY+16)); var writeRing = false; // true if write-enabled var writeRingCheck = null; // tape write ring checkbox element @@ -382,27 +408,27 @@ B5500MagTapeDrive.prototype.loadTape = function loadTape() { mt.tapeInches = 0; mt.imgEOTInches = eotInches; mt.imgMaxInches = tapeInches; - mt.progressBar.max = mt.imgMaxInches; - mt.progressBar.value = mt.imgMaxInches; - mt.removeClass(mt.$$("MTUnloadedLight"), "whiteLit"); + mt.reelBar.max = mt.imgMaxInches; + mt.reelBar.value = mt.imgMaxInches; mt.setAtEOT(false); mt.setAtBOT(true); mt.tapeState = mt.tapeLocal; // setTapeRemote() requires it not be unloaded mt.setTapeRemote(false); mt.reelIcon.style.visibility = "visible"; + B5500Util.removeClass(mt.$$("MTUnloadedLight"), "annunciatorLit"); mt.imgWritten = false; mt.writeRing = writeRing; if (writeRing) { - mt.addClass(mt.$$("MTWriteRingBtn"), "redLit"); + B5500Util.addClass(mt.$$("MTWriteRingBtn"), "redLit"); } else { - mt.removeClass(mt.$$("MTWriteRingBtn"), "redLit"); + B5500Util.removeClass(mt.$$("MTWriteRingBtn"), "redLit"); } win.close(); } - function bcdLoader_onLoad(ev) { + function bcdLoader_onload(ev) { /* Loads a ".bcd" tape image into the drive */ var blockLength; var image = new Uint8Array(ev.target.result); @@ -456,13 +482,13 @@ B5500MagTapeDrive.prototype.loadTape = function loadTape() { finishLoad(); } - function tapLoader_onLoad(ev) { + function tapLoader_onload(ev) { /* Loads a ".tap" tape image into the drive */ /* To be Provided */ } - function textLoader_onLoad(ev) { + function textLoader_onload(ev) { /* Loads a text image as either odd or even parity bcd data */ var block; // ANSI text of current block var blockLength; // length of current ASCII block @@ -536,17 +562,17 @@ B5500MagTapeDrive.prototype.loadTape = function loadTape() { case "aod": case "aev": tape = new FileReader(); - tape.onload = textLoader_onLoad; + tape.onload = textLoader_onload; tape.readAsText(file); break; case "bcd": tape = new FileReader(); - tape.onload = bcdLoader_onLoad; + tape.onload = bcdLoader_onload; tape.readAsArrayBuffer(file); break; case "tap": tape = new FileReader(); - tape.onload = tapLoader_onLoad; + tape.onload = tapLoader_onload; tape.readAsArrayBuffer(file); break; default: @@ -557,10 +583,13 @@ B5500MagTapeDrive.prototype.loadTape = function loadTape() { } } - function tapeLoadOnLoad (ev) { + function tapeLoadOnload (ev) { /* Driver for the tape loader window */ + var de; doc = win.document; + de = doc.documentElement; + win.focus(); $$$ = function $$$(id) { return doc.getElementById(id); }; @@ -589,19 +618,25 @@ B5500MagTapeDrive.prototype.loadTape = function loadTape() { }, false); $$$("MTLoadOKBtn").addEventListener("click", tapeLoadOK, false); - $$$("MTLoadCancelBtn").addEventListener("click", function loadCancelBtn(ev) { file = null; mt.$$("MTFileName").value = ""; win.close(); }, false); + + win.resizeBy(de.scrollWidth - win.innerWidth, + de.scrollHeight - win.innerHeight); } + // Outer block of loadTape + if (this.loadWindow && !this.loadWindow.closed) { + this.loadWindow.close(); + } + this.loadWindow = win; mt.$$("MTLoadBtn").disabled = true; - win.moveTo((screen.availWidth-win.outerWidth)/2, (screen.availHeight-win.outerHeight)/2); - win.focus(); - win.addEventListener("load", tapeLoadOnLoad, false); + win.addEventListener("load", tapeLoadOnload, false); win.addEventListener("unload", function tapeLoadUnload(ev) { + this.loadWindow = null; if (win.closed) { mt.$$("MTLoadBtn").disabled = (mt.tapeState != mt.tapeUnloaded); } @@ -614,8 +649,8 @@ B5500MagTapeDrive.prototype.unloadTape = function unloadTape() { window so the user can save or copy/paste it elsewhere */ var doc = null; // loader window.document var mt = this; // tape drive object - var win = this.window.open("", this.mnemonic + "Unload", - "scrollbars=no,resizable,width=800,height=600"); + var win = this.window.open("./B5500FramePaper.html", this.mnemonic + "-Unload", + "location=no,scrollbars=yes,resizable,width=800,height=600"); function unloadDriver() { /* Converts the tape image to ASCII once the window has displayed the @@ -627,11 +662,14 @@ B5500MagTapeDrive.prototype.unloadTape = function unloadTape() { var image = mt.image; // tape image data var imgLength = mt.imgTopIndex; // tape image active length var table; // even/odd parity translate table - var text = doc.getElementById("TapeText"); + var tape; //
       element to receive tape data
               var x = 0;                      // image data index
       
      -        while (text.firstChild) {       // delete the please-wait message
      -            text.removeChild(text.firstChild);
      +        doc = win.document;
      +        doc.title = "B5500 " + mt.mnemonic + " Unload Tape";
      +        tape = doc.getElementById("Paper");
      +        while (tape.firstChild) {               // delete any existing 
       content
      +            tape.removeChild(tape.firstChild);
               }
       
               c = image[x];
      @@ -641,7 +679,8 @@ B5500MagTapeDrive.prototype.unloadTape = function unloadTape() {
                   bufIndex = 0;
                   do {
                       if (bufIndex >= bufLength) { // ASCII block size exceeded
      -                    text.appendChild(doc.createTextNode(String.fromCharCode.apply(null, buf.subarray(0, bufIndex))));
      +                    tape.appendChild(doc.createTextNode(
      +                            String.fromCharCode.apply(null, buf.subarray(0, bufIndex))));
                           bufIndex = 0;
                       }
                       if (c > 0) {            // drop any unrecorded tape frames
      @@ -654,20 +693,26 @@ B5500MagTapeDrive.prototype.unloadTape = function unloadTape() {
                       }
                   } while (c < 0x80);
                   buf[bufIndex++] = 0x0A;
      -            text.appendChild(doc.createTextNode(String.fromCharCode.apply(null, buf.subarray(0, bufIndex))));
      +            tape.appendChild(doc.createTextNode(
      +                    String.fromCharCode.apply(null, buf.subarray(0, bufIndex))));
               } while (x < imgLength);
       
               mt.setTapeUnloaded();
           }
       
      +    function unloadSetup() {
      +        /* Loads a status message into the "paper" rendering area, then calls
      +        unloadDriver after a short wait to allow the message to appear */
      +
      +        win.document.getElementById("Paper").appendChild(
      +                win.document.createTextNode("Rendering tape image... please wait..."));
      +        setTimeout(unloadDriver, 50);
      +    }
      +
      +    // Outer block of unloadTape
           win.moveTo((screen.availWidth-win.outerWidth)/2, (screen.availHeight-win.outerHeight)/2);
           win.focus();
      -    doc = win.document;
      -    doc.open();
      -    doc.write("
      Converting... please wait...
      "); - doc.close(); - doc.title = "B5500 " + this.mnemonic + " Unload Tape"; - setCallback(this.mnemonic, this, 50, unloadDriver); // give the message time to display + win.addEventListener("load", unloadSetup, false); }; /**************************************/ @@ -677,12 +722,11 @@ B5500MagTapeDrive.prototype.tapeRewind = function tapeRewind(makeReady) { called from this.rewind()], then readies the unit again when the rewind is complete */ var inches; var lastStamp = performance.now(); - var updateInterval = 15; // ms function rewindFinish() { this.timer = 0; this.busy = false; - this.removeClass(this.$$("MTRewindingLight"), "whiteLit"); + B5500Util.removeClass(this.$$("MTRewindingLight"), "annunciatorLit"); if (makeReady && this.tapeState == this.tapeRemote) { this.ready = true; this.statusChange(1); @@ -694,15 +738,14 @@ B5500MagTapeDrive.prototype.tapeRewind = function tapeRewind(makeReady) { var interval = stamp - lastStamp; if (interval <= 0) { - interval = updateInterval/2; + interval = this.spinUpdateInterval/2; } if (this.tapeInches > 0) { inches = interval/1000*this.rewindSpeed; this.tapeInches -= inches; lastStamp = stamp; - this.timer = setCallback(this.mnemonic, this, updateInterval, rewindDelay); + this.timer = setCallback(this.mnemonic, this, this.spinUpdateInterval, rewindDelay); this.spinReel(-inches); - this.progressBar.value = this.imgMaxInches - this.tapeInches; } else { this.setAtBOT(true); this.timer = setCallback(this.mnemonic, this, 2000, rewindFinish); @@ -719,7 +762,7 @@ B5500MagTapeDrive.prototype.tapeRewind = function tapeRewind(makeReady) { this.ready = false; this.statusChange(0); this.setAtEOT(false); - this.addClass(this.$$("MTRewindingLight"), "whiteLit"); + B5500Util.addClass(this.$$("MTRewindingLight"), "annunciatorLit"); this.timer = setCallback(this.mnemonic, this, 1000, rewindDelay); } }; @@ -728,8 +771,9 @@ B5500MagTapeDrive.prototype.tapeRewind = function tapeRewind(makeReady) { B5500MagTapeDrive.prototype.MTUnloadBtn_onclick = function MTUnloadBtn_onclick(ev) { /* Handle the click event for the UNLOAD button */ - if (this.imgWritten && this.window.confirm("Do you want to save the tape image data?")) { - this.unloadTape(); // will do setTapeUnloaded() afterwards + if (this.imgWritten && this.window.confirm( + "Do you want to save the tape image data?\n(CANCEL discards the image)")) { + this.unloadTape(); // it will do setTapeUnloaded() afterwards } else { this.setTapeUnloaded(); } @@ -1080,7 +1124,7 @@ B5500MagTapeDrive.prototype.bcdWrite = function bcdWrite(oddParity) { }; /**************************************/ -B5500MagTapeDrive.prototype.tapeDriveBeforeUnload = function tapeDriveBeforeUnload(ev) { +B5500MagTapeDrive.prototype.beforeUnload = function beforeUnload(ev) { var msg = "Closing this window will make the device unusable.\n" + "Suggest you stay on the page and minimize this window instead"; @@ -1090,49 +1134,40 @@ B5500MagTapeDrive.prototype.tapeDriveBeforeUnload = function tapeDriveBeforeUnlo }; /**************************************/ -B5500MagTapeDrive.prototype.tapeDriveOnLoad = function tapeDriveOnLoad() { +B5500MagTapeDrive.prototype.tapeDriveOnload = function tapeDriveOnload() { /* Initializes the reader window and user interface */ - var that = this; + var de; + var y = ((this.mnemonic.charCodeAt(2) - "A".charCodeAt(0))*30); this.doc = this.window.document; - this.doc.title = "retro-B5500 " + this.mnemonic; + de = this.doc.documentElement; + this.doc.title = "retro-B5500 Tape Drive " + this.mnemonic; - this.progressBar = this.$$("MTProgressBar"); + this.reelBar = this.$$("MTReelBar"); this.reelIcon = this.$$("MTReel"); - this.window.addEventListener("beforeunload", this.tapeDriveBeforeUnload, false); - this.tapeState = this.tapeLocal; // setTapeUnloaded() requires it to be in local this.atBOT = true; // and also at BOT this.setTapeUnloaded(); - this.$$("MTUnloadBtn").addEventListener("click", function unloadBtn(ev) { - that.MTUnloadBtn_onclick(ev); - }, false); + this.window.addEventListener("beforeunload", + B5500MagTapeDrive.prototype.beforeUnload, false); + this.$$("MTUnloadBtn").addEventListener("click", + B5500CentralControl.bindMethod(this, B5500MagTapeDrive.prototype.MTUnloadBtn_onclick), false); + this.$$("MTLoadBtn").addEventListener("click", + B5500CentralControl.bindMethod(this, B5500MagTapeDrive.prototype.MTLoadBtn_onclick), false); + this.$$("MTRemoteBtn").addEventListener("click", + B5500CentralControl.bindMethod(this, B5500MagTapeDrive.prototype.MTRemoteBtn_onclick), false); + this.$$("MTLocalBtn").addEventListener("click", + B5500CentralControl.bindMethod(this, B5500MagTapeDrive.prototype.MTLocalBtn_onclick), false); + this.$$("MTWriteRingBtn").addEventListener("click", + B5500CentralControl.bindMethod(this, B5500MagTapeDrive.prototype.MTWriteRingBtn_onclick), false); + this.$$("MTRewindBtn").addEventListener("click", + B5500CentralControl.bindMethod(this, B5500MagTapeDrive.prototype.MTRewindBtn_onclick), false); - this.$$("MTLoadBtn").addEventListener("click", function loadBtn(ev) { - that.MTLoadBtn_onclick(ev); - }, false); - - this.$$("MTRemoteBtn").addEventListener("click", function remoteBtn(ev) { - that.MTRemoteBtn_onclick(ev); - }, false); - - this.$$("MTLocalBtn").addEventListener("click", function localBtn(ev) { - that.MTLocalBtn_onclick(ev); - }, false); - - this.$$("MTWriteRingBtn").addEventListener("click", function writeRingBtn(ev) { - that.MTWriteRingBtn_onclick(ev); - }, false); - - this.$$("MTRewindBtn").addEventListener("click", function rewindBtn(ev) { - that.MTRewindBtn_onclick(ev); - }, false); - - this.progressBar.addEventListener("click", function progressClick(ev) { - that.MTProgressBar_onclick(ev); - }, false); + this.window.resizeBy(de.scrollWidth - this.window.innerWidth + 4, // kludge for right-padding/margin + de.scrollHeight - this.window.innerHeight); + this.window.moveTo(280, y); }; /**************************************/ @@ -1179,19 +1214,13 @@ B5500MagTapeDrive.prototype.read = function read(finish, buffer, length, mode, c } this.buildErrorMask(residue); - this.timer = setCallback(this.mnemonic, this, + this.moveTape(inches, (imgCount/this.charsPerSec + this.startStopTime)*1000 + this.initiateStamp - performance.now(), function readDelay() { this.busy = false; finish(this.errorMask, count); }); - this.spinReel(inches); - if (this.tapeInches < this.imgMaxInches) { - this.progressBar.value = this.imgMaxInches - this.tapeInches; - } else { - this.progressBar.value = 0; - } this.buffer = null; } //console.log(this.mnemonic + " read: c=" + control + ", length=" + length + ", mode=" + mode + @@ -1237,19 +1266,12 @@ B5500MagTapeDrive.prototype.space = function space(finish, length, control) { } this.buildErrorMask(0); - this.timer = setCallback(this.mnemonic, this, + this.moveTape(inches, (imgCount/this.charsPerSec + this.startStopTime)*1000 + this.initiateStamp - performance.now(), function readDelay() { this.busy = false; finish(this.errorMask, 0); }); - - this.spinReel(inches); - if (this.tapeInches < this.imgMaxInches) { - this.progressBar.value = this.imgMaxInches - this.tapeInches; - } else { - this.progressBar.value = 0; - } } //console.log(this.mnemonic + " space: c=" + control + ", length=" + length + // ", count=" + imgCount + ", inches=" + this.tapeInches + @@ -1290,19 +1312,13 @@ B5500MagTapeDrive.prototype.write = function write(finish, buffer, length, mode, this.imgWritten = true; this.buildErrorMask(residue); - this.timer = setCallback(this.mnemonic, this, + this.moveTape(inches, (imgCount/this.charsPerSec + this.startStopTime)*1000 + this.initiateStamp - performance.now(), function writeDelay() { this.busy = false; finish(this.errorMask, count); }); - this.spinReel(inches); - if (this.tapeInches < this.imgMaxInches) { - this.progressBar.value = this.imgMaxInches - this.tapeInches; - } else { - this.progressBar.value = 0; - } this.buffer = null; } //console.log(this.mnemonic + " write: c=" + control + ", length=" + length + ", mode=" + mode + @@ -1338,20 +1354,13 @@ B5500MagTapeDrive.prototype.erase = function erase(finish, length) { this.imgWritten = true; this.buildErrorMask(0); - this.timer = setCallback(this.mnemonic, this, + this.moveTape(inches, (length/this.charsPerSec + this.startStopTime)*1000 + this.initiateStamp - performance.now(), function eraseDelay() { this.busy = false; finish(this.errorMask, 0); }); - - this.spinReel(inches); - if (this.tapeInches < this.imgMaxInches) { - this.progressBar.value = this.imgMaxInches - this.tapeInches; - } else { - this.progressBar.value = 0; - } - } + } //console.log(this.mnemonic + " erase: c=" + control + ", length=" + length + // ", inches=" + this.tapeInches + // ", index=" + this.imgIndex + ", mask=" + this.errorMask.toString(8)); @@ -1419,6 +1428,9 @@ B5500MagTapeDrive.prototype.shutDown = function shutDown() { if (this.timer) { clearCallback(this.timer); } - this.window.removeEventListener("beforeunload", this.tapeDriveBeforeUnload, false); + this.window.removeEventListener("beforeunload", B5500MagTapeDrive.prototype.beforeUnload, false); this.window.close(); + if (this.loadWindow && !this.loadWindow.closed) { + this.loadWindow.close(); + } }; diff --git a/webUI/B5500MagTapeLoadPanel.html b/webUI/B5500MagTapeLoadPanel.html index d68a89c..60c1043 100644 --- a/webUI/B5500MagTapeLoadPanel.html +++ b/webUI/B5500MagTapeLoadPanel.html @@ -1,17 +1,36 @@ + + B5500 Emulator Magnetic Tape Loader + - - - + + - + -
      +
      @@ -39,8 +58,8 @@
      - - + +
      diff --git a/webUI/B5500Manifest.appcache b/webUI/B5500Manifest.appcache new file mode 100644 index 0000000..013c011 --- /dev/null +++ b/webUI/B5500Manifest.appcache @@ -0,0 +1,56 @@ +CACHE MANIFEST +# retro-B5500 emulator 1.00, 2014-09-27 + +CACHE: +../emulator/B5500CentralControl.js +../emulator/B5500IOUnit.js +../emulator/B5500Processor.js +../emulator/B5500SystemConfiguration.js +B5500BlankPaper.html +B5500CardPunch.css +B5500CardPunch.html +B5500CardPunch.js +B5500CardReader.css +B5500CardReader.html +B5500CardReader.js +B5500ColdLoader.html +B5500Common.css +B5500Console.css +B5500Console.html +B5500Console.js +B5500DatacomUnit.css +B5500DatacomUnit.html +B5500DatacomUnit.js +B5500DiskStorageConfig.html +B5500DiskStorageConfig.js +B5500DiskUnit.js +B5500DummyUnit.js +B5500FramePaper.html +B5500LinePrinter.css +B5500LinePrinter.html +B5500LinePrinter.js +B5500MagTapeDrive.css +B5500MagTapeDrive.html +B5500MagTapeDrive.js +B5500MagTapeLoadPanel.html +B5500SetCallback.js +B5500SPOUnit.css +B5500SPOUnit.html +B5500SPOUnit.js +B5500SyllableDebugger.css +B5500SyllableDebugger.html +B5500SystemConfig.css +B5500SystemConfig.html +B5500SystemConfig.js +B5500Util.js +resources/B5500Logo.jpg +resources/Burroughs-Logo-Neg.jpg +resources/DejaVuSans-Bold-webfont.ttf +resources/DejaVuSans-Bold-webfont.woff +resources/DejaVuSans-webfont.ttf +resources/DejaVuSans-webfont.woff +resources/DejaVuSansMono-webfont.ttf +resources/DejaVuSansMono-webfont.woff +resources/MagTapeReel.jpg +resources/retro-B5500-Logo.png +resources/TeletypeLogo.gif diff --git a/webUI/B5500SPOUnit.css b/webUI/B5500SPOUnit.css index 435a6ee..e27e855 100644 --- a/webUI/B5500SPOUnit.css +++ b/webUI/B5500SPOUnit.css @@ -2,7 +2,8 @@ * retro-b5500/emulator B5500SPOUnit.css ************************************************************************ * Copyright (c) 2012, Nigel Williams and Paul Kimpel. -* Licensed under the MIT License, see http://www.opensource.org/licenses/mit-license.php +* Licensed under the MIT License, see +* http://www.opensource.org/licenses/mit-license.php ************************************************************************ * B5500 emulator SPO web interface style sheet. ************************************************************************ @@ -10,117 +11,125 @@ * Original version, from B5500ConsoleUnit.css. ***********************************************************************/ -BODY { - position: relative; - background-color: black; - margin: 4px} +#SPOUnit { + height: 100%; + min-height: 100%; + overflow: hidden; + padding: 0} -PRE { - font-family: Lucida Sans Typewriter, Courier New, Courier, monospace; - font-size: 8pt; - margin: 0} - - -DIV#SPODiv { - position: relative; - width: 680px; - height: 500px; +#SPODiv { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + margin: 4px; background-color: #FFC; - border-radius: 16px; - text-align: left} + border-radius: 16px} -IFRAME#SPOUT { +#SPOUT { position: absolute; left: 16px; + right: 168px; + top: 16px; bottom: 16px; - height: 468px; - width: 490px; - border: 1px solid black} - -BODY.SPOUT { + min-height: 280px; + min-width: 120px; + overflow-x: hidden; + overflow-y: scroll; + color: black; background-color: white; - font-family: Lucida Sans Typewriter, Courier New, Courier, monospace; - font-size: 8pt} + padding: 4px; + border: 1px solid gray} -DIV#SPOControlsDiv { +#Paper { + margin-left: 0; + margin-right: 0; + margin-top: 2000px; + margin-bottom: 0; + padding: 0} + +#EndOfPaper { + display: block; + margin: 0; + padding: 0; + opacity: 0} +#EndOfPaper.hidden { + display: none} + +#InputBox { + display: none; + margin: 0; + padding: 0; + border: none; + outline: none; + background-color: #FF9} +#InputBox.visible { + display: block} +#InputBox:focus { + border: none; + outline: none} /* to suppress Chrome's default outline */ + +#SPOControlsDiv { position: absolute; text-align: center; - height: 468px; - width: 136px; - right: 16px; - bottom: 16px} - -IMG#TeletypeLogo { left: auto; - right: auto} + right: 16px; + top: 16px; + bottom: 16px; + min-height: 280px; + width: 136px} -BUTTON.greenButton { +#TeletypeLogo { + margin-left: auto; + margin-right: auto} + +#SPOReadyBtn { position: absolute; - background-color: #060; - color: white; - font-family: Arial Rounded, Arial, Helvetica, sans-serif; - font-size: 8pt; - font-weight: normal; - width: 60px; - height: 40px; - border: 1px solid black; - border-radius: 4px} - -BUTTON.yellowButton { - position: absolute; - background-color: #990; - color: black; - font-family: Arial Rounded, Arial, Helvetica, sans-serif; - font-size: 8pt; - font-weight: normal; - width: 60px; - height: 40px; - border: 1px solid black; - border-radius: 4px} - -BUTTON.greenLit { - color: black; - background-color: #0F0} - -BUTTON.yellowLit { - background-color: #FF0} - -BUTTON#SPOReadyBtn { bottom: 224px; left: 0px} -BUTTON#SPOPowerBtn { +#SPOPowerBtn { + position: absolute; bottom: 224px; right: 0px} -BUTTON#SPORemoteBtn { +#SPORemoteBtn { + position: absolute; bottom: 168px; left: 0px} -BUTTON#SPOLocalBtn { +#SPOLocalBtn { + position: absolute; bottom: 168px; right: 0px} -BUTTON#SPOInputRequestBtn { +#SPOInputRequestBtn { + position: absolute; bottom: 112px; left: 0px} -BUTTON#SPOEndOfMessageBtn { +#SPOEndOfMessageBtn { + position: absolute; bottom: 112px; right: 0px} -BUTTON#SPOBlank1Btn { +#SPOBlank1Btn { + position: absolute; bottom: 56px; left: 0px} -BUTTON#SPOErrorBtn { +#SPOErrorBtn { + position: absolute; bottom: 56px; right: 0px} -BUTTON#SPOBlank2Btn { +#SPOAlgolGlyphsBtn { + position: absolute; bottom: 0px; left: 0px} -BUTTON#SPOBlank3Btn { +#SPOBlank3Btn { + position: absolute; bottom: 0px; right: 0px} diff --git a/webUI/B5500SPOUnit.html b/webUI/B5500SPOUnit.html index b2d6216..5fd4f0c 100644 --- a/webUI/B5500SPOUnit.html +++ b/webUI/B5500SPOUnit.html @@ -1,30 +1,53 @@ + + B5500 Emulator SPO Unit + - - - + + - +
      - +
      +
       
      + +
       
      +
      +
      - - - - - - - - - - - + + + + + + + + + + +
      diff --git a/webUI/B5500SPOUnit.js b/webUI/B5500SPOUnit.js index 555fba9..2ced523 100644 --- a/webUI/B5500SPOUnit.js +++ b/webUI/B5500SPOUnit.js @@ -17,7 +17,7 @@ "use strict"; /**************************************/ -function B5500SPOUnit(mnemonic, unitIndex, designate, statusChange, signal) { +function B5500SPOUnit(mnemonic, unitIndex, designate, statusChange, signal, options) { /* Constructor for the SPOUnit object */ this.maxScrollLines = 1500; // Maximum amount of printer scrollback @@ -32,6 +32,7 @@ function B5500SPOUnit(mnemonic, unitIndex, designate, statusChange, signal) { this.initiateStamp = 0; // timestamp of last initiation (set by IOUnit) this.inTimer = 0; // input setCallback() token this.outTimer = 0; // output setCallback() token + this.useAlgolGlyphs = options.algolGlyphs; // format Unicode for special Algol chars this.clear(); @@ -42,11 +43,12 @@ function B5500SPOUnit(mnemonic, unitIndex, designate, statusChange, signal) { } this.doc = null; this.paper = null; + this.inputBox = null; this.endOfPaper = null; this.window = window.open("../webUI/B5500SPOUnit.html", mnemonic, - "scrollbars,resizable,width=688,height=508"); - this.window.moveTo(screen.availWidth-this.window.outerWidth, screen.availHeight-this.window.outerHeight); - this.window.addEventListener("load", B5500CentralControl.bindMethod(B5500SPOUnit.prototype.spoOnload, this), false); + "location=no,scrollbars=no,resizable,width=688,height=508"); + this.window.addEventListener("load", B5500CentralControl.bindMethod(this, + B5500SPOUnit.prototype.spoOnload), false); } // this.spoState enumerations @@ -61,7 +63,7 @@ B5500SPOUnit.prototype.keyFilter = [ // Filter keyCode values to valid BIC on 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x3F,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F, // 20-2F 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F, // 30-3F 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F, // 40-4F - 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x3F,0x5D,0x3F,0x3F, // 50-5F + 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x3F,0x5D,0x3F,0x7E, // 50-5F 0x3F,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F, // 60-6F 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x7B,0x7C,0x7D,0x7E,0x3F]; // 70-7F @@ -81,53 +83,26 @@ B5500SPOUnit.prototype.clear = function clear() { this.finish = null; // external function to call for I/O completion this.buffer = null; this.bufLength = 0; - this.bufIndex = 0; - this.printCol = 0; + this.bufIndex = 0; // current index into I/O buffer + this.printCol = 0; // current print column (0-relative) this.nextCharTime = 0; this.spoState = this.spoLocal; // Current state of SPO interface this.spoLocalRequested = false; // LOCAL button pressed while active }; -/**************************************/ -B5500SPOUnit.prototype.hasClass = function hasClass(e, name) { - /* returns true if element "e" has class "name" in its class list */ - var classes = e.className; - - if (!e) { - return false; - } else if (classes == name) { - return true; - } else { - return (classes.search("\\b" + name + "\\b") >= 0); - } -}; - -/**************************************/ -B5500SPOUnit.prototype.addClass = function addClass(e, name) { - /* Adds a class "name" to the element "e"s class list */ - - if (!this.hasClass(e, name)) { - e.className += (" " + name); - } -}; - -/**************************************/ -B5500SPOUnit.prototype.removeClass = function removeClass(e, name) { - /* Removes the class "name" from the element "e"s class list */ - - e.className = e.className.replace(new RegExp("\\b" + name + "\\b\\s*", "g"), ""); -}; - /**************************************/ B5500SPOUnit.prototype.setLocal = function setLocal() { - /* Sets the status of the SPO to Local */ + /* Sets the status of the SPO to Local and enables the input element */ this.spoLocalRequested = false; this.spoState = this.spoLocal; - this.addClass(this.$$("SPOLocalBtn"), "yellowLit"); - this.removeClass(this.$$("SPORemoteBtn"), "yellowLit"); - this.removeClass(this.$$("SPOInputRequestBtn"), "yellowLit"); + this.endOfPaper.scrollIntoView(); + B5500Util.addClass(this.$$("SPOLocalBtn"), "yellowLit"); + B5500Util.addClass(this.inputBox, "visible"); + this.inputBox.focus(); + B5500Util.removeClass(this.$$("SPORemoteBtn"), "yellowLit"); + B5500Util.removeClass(this.$$("SPOInputRequestBtn"), "yellowLit"); this.statusChange(0); // Set up to echo characters from the keyboard @@ -138,48 +113,76 @@ B5500SPOUnit.prototype.setLocal = function setLocal() { this.finish = null; }; +/**************************************/ +B5500SPOUnit.prototype.requestLocal = function requestLocal(ev) { + /* Handler for the Local button click. If the SPO is idle and in remote + status, sets it to local; otherwise flags it to go local once the current + I/O completes */ + + if (this.spoState == this.spoRemote) { + this.setLocal(); + } else { + this.spoLocalRequested = true; + } +}; + /**************************************/ B5500SPOUnit.prototype.setRemote = function setRemote() { - /* Sets the status of the SPO to Remote */ + /* Sets the status of the SPO to Remote and disabled the input element */ + var text; if (this.spoState == this.spoLocal) { this.spoState = this.spoRemote; this.spoLocalRequested = false; - this.addClass(this.$$("SPORemoteBtn"), "yellowLit"); - this.removeClass(this.$$("SPOLocalBtn"), "yellowLit"); + B5500Util.addClass(this.$$("SPORemoteBtn"), "yellowLit"); + B5500Util.removeClass(this.$$("SPOLocalBtn"), "yellowLit"); + B5500Util.removeClass(this.inputBox, "visible"); + this.window.focus(); + text = this.inputBox.value; + if (text.length > 0) { + this.appendEmptyLine(text.substring(0, 72)); + this.inputBox.value = ""; + } + this.endOfPaper.scrollIntoView(); + this.nextCharTime = performance.now(); this.statusChange(1); } }; /**************************************/ -B5500SPOUnit.prototype.appendEmptyLine = function appendEmptyLine() { - /* Removes excess lines already printed, then appends a new text node - to the
       element within the 
           
      - + diff --git a/webUI/tools/B5500TestArithmetics.html b/webUI/prototypes/B5500TestArithmetics.html similarity index 93% rename from webUI/tools/B5500TestArithmetics.html rename to webUI/prototypes/B5500TestArithmetics.html index 9797d0a..1d047d2 100644 --- a/webUI/tools/B5500TestArithmetics.html +++ b/webUI/prototypes/B5500TestArithmetics.html @@ -1,18 +1,18 @@ B5500 Emulator Arithmetic Testbed - + + - @@ -180,7 +180,7 @@ window.onload = function() { document.getElementById("BReg").onchange = reg_onChange; cc = new B5500CentralControl(); - cc.powerOn(); + cc.powerOn(new B5500SystemConfiguration().systemConfig); cc.clear(); //cc.MemMod[0][0x10] = 0x00400C215415;// LITC 1, LITC 3, XCH, DUP @@ -204,7 +204,7 @@ window.onload = function() {
      diff --git a/webUI/tools/B5500TestLoader.html b/webUI/prototypes/B5500TestLoader.html similarity index 91% rename from webUI/tools/B5500TestLoader.html rename to webUI/prototypes/B5500TestLoader.html index 679bc1b..6abfba6 100644 --- a/webUI/tools/B5500TestLoader.html +++ b/webUI/prototypes/B5500TestLoader.html @@ -1,18 +1,18 @@ B5500 Test Loader - + + - @@ -79,7 +79,7 @@ window.onload = function() { /* Start of window.onload() */ if (checkBrowser()) { - cc.powerOn(); + cc.powerOn(new B5500SystemConfiguration().systemConfig); document.getElementById("FileSelector").addEventListener("change", fileSelector_onChange, false); document.getElementById("RunBtn").addEventListener("click", runBtn_onClick, false); diff --git a/webUI/tools/B5500Testbed.html b/webUI/prototypes/B5500Testbed.html similarity index 90% rename from webUI/tools/B5500Testbed.html rename to webUI/prototypes/B5500Testbed.html index 2a27094..7f81b53 100644 --- a/webUI/tools/B5500Testbed.html +++ b/webUI/prototypes/B5500Testbed.html @@ -1,17 +1,17 @@ B5500 Emulator Operator Console - + + - @@ -23,7 +23,7 @@ var cc; function testIt(e) { /* Simple test driver for the Processor module */ - cc.powerOn(); + cc.powerOn(new B5500SystemConfiguration().systemConfig); cc.clear(); e.style.backgroundColor = "white"; // a kludge, for now @@ -97,7 +97,7 @@ window.onload = function() {
      diff --git a/webUI/prototypes/PanelTest.html b/webUI/prototypes/PanelTest.html index 307b41d..7f44c8a 100644 --- a/webUI/prototypes/PanelTest.html +++ b/webUI/prototypes/PanelTest.html @@ -1,7 +1,7 @@ B5500 Panel Prototype tests - +