From 0eccf30d3cb82b3df4c1c690ad74fcb6bdf2c7a5 Mon Sep 17 00:00:00 2001 From: Jeff Parsons Date: Mon, 2 Jan 2017 23:21:16 -0800 Subject: [PATCH] Support for sticky machines when using the Node web server (so that we have parity between the Node and Jekyll web environments) --- _posts/2017-01-03-pdp-11-tutorials.md | 56 +++++++++++++++++++++++++++ modules/htmlout/lib/htmlout.js | 7 ++++ modules/markout/lib/markout.js | 5 ++- modules/shared/{es6 => lib}/sticky.js | 36 ++++++++++------- 4 files changed, 89 insertions(+), 15 deletions(-) create mode 100644 _posts/2017-01-03-pdp-11-tutorials.md rename modules/shared/{es6 => lib}/sticky.js (69%) diff --git a/_posts/2017-01-03-pdp-11-tutorials.md b/_posts/2017-01-03-pdp-11-tutorials.md new file mode 100644 index 000000000..b33803e06 --- /dev/null +++ b/_posts/2017-01-03-pdp-11-tutorials.md @@ -0,0 +1,56 @@ +--- +layout: post +title: PDP-11 Tutorials +date: 2017-01-03 15:00:00 +permalink: /blog/2017/01/03/ +machines: + - id: test1170 + type: pdp11 + debugger: true + config: /devices/pdp11/machine/1170/vt100/debugger/machine.xml + connection: dl11->vt100.serialPort + - id: vt100 + type: pc8080 + config: /devices/pc8080/machine/vt100/machine.xml + connection: serialPort->test1170.dl11 + sticky: top +--- + +Introducing PDP-11 tutorials! + +{% include machine.html id="vt100" %} + +[PDPjs](/devices/pdp11/machine/) is the newest addition to the PCjs family of emulators, joining PCx86, PC8080, and C1Pjs. + +While PDPjs may eventually support a range of DEC PDP machines, my current focus is on the PDP-11, starting with the +PDP-11/70. From there, I'll work backwards to support other PDP-11 models, such as the PDP-11/45, until I reach the +beginning of the PDP-11 line: the PDP-11/20. + +I'm starting with the top-of-the-line PDP-11/70 largely because the core of the emulator is being adapted from the +JavaScript [PDP-11/70 Emulator (v1.3)](http://skn.noip.me/pdp11/pdp11.html) written by +Paul Nankervis, who has generously given permission to use his code in PCjs. Since his emulator is a fully functional +11/70, it made sense to start there and work backwards, factoring out features as needed. + +The code has already undergone a lot of refactoring. Opcodes are now decoded by function tables rather than a single +switch statement, and every opcode is implemented with a discrete function. Other refactoring includes flag management, +interrupt management, and device management. + +Most of the work remaining is in device management. Like other PCjs emulators, PDPjs has a Bus component, +[bus.js](/modules/pdp11/lib/bus.js), that allows separate device components to register I/O handlers for specific +UNIBUS addresses. During the initial port, I moved all of Paul's original device management code into one "catch-all" +component, [device.js](/modules/pdp11/lib/device.js), which has now been converted to the new I/O registration model. + +The first new device component is [serial.js](/modules/pdp11/lib/serial.js), which is currently the +only means PDPjs has of communicating with the outside world. So you can try +[PDPjs connected to a VT100 Terminal](/devices/pdp11/machine/1170/vt100/), by clicking the **Run** button on the test machine. +The test machine is running [custom boot code](/apps/pdp11/boot/test/), adapted from boot code written by Paul, but due to the +lack of other device support, nothing can be booted yet. + +Obviously PDPjs is very much a work-in-progress. Before I proceed much farther, I really want to put the CPU through +some rigorous testing, so I'll be on the lookout for some comprehensive PDP-11 instruction tests. Or I'll write my own, +and compare results across 1 or 2 other PDP-11 emulators. + +{% include machine.html id="test1170" %} + +*[@jeffpar](http://twitter.com/jeffpar)* +*Jan 3, 2017* diff --git a/modules/htmlout/lib/htmlout.js b/modules/htmlout/lib/htmlout.js index 56cef16af..353e2a5bc 100644 --- a/modules/htmlout/lib/htmlout.js +++ b/modules/htmlout/lib/htmlout.js @@ -879,6 +879,7 @@ HTMLOut.prototype.findTokens = function(reTokens) aParms.push(aMatch[1]); } } + //noinspection JSUnresolvedFunction fnToken.call(this, sToken, sIndent, aParms); } } @@ -1968,6 +1969,12 @@ HTMLOut.prototype.processMachines = function(aMachines, buildOptions, done) } } this.addFilesToHTML(asFiles, sScriptEmbed); + if (infoMachine['sticky']) { + asFiles = []; + asFiles.push("/modules/shared/lib/sticky.js"); + sScriptEmbed = ''; + this.addFilesToHTML(asFiles, sScriptEmbed); + } if (buildOptions.id) { asFiles = []; asFiles.push("/modules/build/lib/build.js"); diff --git a/modules/markout/lib/markout.js b/modules/markout/lib/markout.js index ad64d8524..027cbeced 100644 --- a/modules/markout/lib/markout.js +++ b/modules/markout/lib/markout.js @@ -367,7 +367,7 @@ MarkOut.aFMBooleanMachineProps = { 'autopower': "autoPower", 'autostart': "autoStart" }; -MarkOut.aFMReservedMachineProps = ['id', 'name', 'type', 'debugger', 'config', 'template', 'uncompiled', 'autoMount', 'drives', 'parms']; +MarkOut.aFMReservedMachineProps = ['id', 'name', 'type', 'debugger', 'config', 'template', 'uncompiled', 'autoMount', 'drives', 'parms', 'sticky']; /** * convertMD() @@ -1167,6 +1167,7 @@ MarkOut.prototype.convertMDMachineLinks = function(sBlock) var machine = this.aMachineDefs[sMachineID]; sMachineType = machine['type'] || "PCx86"; sMachineOptions = ((sMachineType.indexOf("-dbg") > 0 || machine['debugger'] == "true")? "debugger" : ""); + if (machine['sticky']) sMachineOptions += (sMachineOptions? "," : "") + "sticky"; sMachineType = sMachineType.replace("-dbg", ""); sMachineXMLFile = machine['config'] || this.sMachineFile || "machine.xml"; sMachineXSLFile = machine['template'] || ""; @@ -1204,6 +1205,7 @@ MarkOut.prototype.convertMDMachineLinks = function(sBlock) sMachineParms = aMachineParms[4] || ""; var aMachineOptions = sMachineOptions.split(','); var fDebugger = (aMachineOptions.indexOf("debugger") >= 0); + var fSticky = (aMachineOptions.indexOf("sticky") >= 0); /* * TODO: Consider validating the existence of this XML file and generating a more meaningful error if not found @@ -1247,6 +1249,7 @@ MarkOut.prototype.convertMDMachineLinks = function(sBlock) 'xsl': sMachineXSLFile, 'version': sMachineVersion,// eg, "1.10", "*" to select the current version, or "uncompiled"; "*" is the default 'debugger': fDebugger, // eg, true or false; false is the default + 'sticky': fSticky, // eg, true or false; false is the default 'parms': sMachineParms} ); } diff --git a/modules/shared/es6/sticky.js b/modules/shared/lib/sticky.js similarity index 69% rename from modules/shared/es6/sticky.js rename to modules/shared/lib/sticky.js index a4e0615dc..2b5c39ecb 100644 --- a/modules/shared/es6/sticky.js +++ b/modules/shared/lib/sticky.js @@ -35,31 +35,39 @@ */ function addStickyMachine(idMachine) { - var machine = document.getElementById(idMachine); - if (machine) { - var machineFooter = document.getElementById(idMachine + '.footer'); - if (machineFooter) { - var topMachine = findTop(machine); - var prevOnScroll = window.onscroll; - window.onscroll = function() { + var topMachine = -1; + var prevOnScroll = window.onscroll; + window.onscroll = function() { + /* + * TODO: Determine if/when we can cache the machine and machineSibling elements; we already + * know we can't cache them when addStickyMachine() is first called, because that currently + * happens *before* embed.js replaces the placeholder machine DIV with the *real* machine DIV. + */ + var machine = document.getElementById(idMachine); + if (machine) { + var machineSibling = machine.nextElementSibling; + if (machineSibling) { + if (topMachine < 0) { + topMachine = findTop(machine); + } if (window.pageYOffset <= topMachine) { machine.style.position = 'relative'; machine.style.zIndex = 'auto'; machine.style.backgroundColor = ''; machine.style.paddingRight = 0; - if (machineFooter) machineFooter.style.paddingTop = 0; + if (machineSibling) machineSibling.style.paddingTop = 0; } else { machine.style.position = 'fixed'; machine.style.zIndex = 1; - machine.style.backgroundColor = 'white'; - machine.style.paddingRight = '30px'; + machine.style.backgroundColor = '#404040'; + machine.style.paddingRight = '16px'; machine.style.top = 0; - if (machineFooter) machineFooter.style.paddingTop = machine.offsetHeight + 'px'; + if (machineSibling) machineSibling.style.paddingTop = machine.offsetHeight + 'px'; } - }; - if (prevOnScroll) prevOnScroll(); + if (prevOnScroll) prevOnScroll(); + } } - } + }; } /**