The museum had a big event a few weeks ago, celebrating the 45th anniversary of the 1st “Intergalactic Spacewar Olympics.” Just a couple of weeks before said event, the museum acquired a beautiful Digital Equipment Corporation Lab-8/e minicomputer and I thought it would be an interesting challenge to get the system restored and running Spacewar in time for the event.
As is fairly obvious to you DEC-heads out there, the Lab-8/e was a PDP-8/e minicomputer in a snazzy green outfit. It came equipped with scads of analog hardware for capturing and replaying laboratory data, and a small Tektronix scope for displaying information. What makes this machine perfect for the PDP-8 version of Spacewar is the inclusion of the VC8E Point Plotting controller and the KE8E Extended Arithmetic Element (or EAE). The VC8E is used by Spacewar to draw the game’s graphics on a display; the EAE is used to make the various rotations and translations done by the game’s code fast enough to be fun.
The restoration was an incredibly painless process. I started with the power supply which worked wonderfully after replacing 40+ year old capacitors, and from there it was a matter of testing and debugging the CPU and analog hardware. There were a few minor faults but in a few days everything was looking good, so I moved on to getting Spacewar running.
But which version to choose? There are a number of Spacewar variants for the PDP-8, but I decided upon this version, helpfully archived on David Gesswein’s lovely PDP-8 site. It has the advantage of being fairly advanced with lots of interesting options, and the source code is adaptable for a variety of different configurations — it’ll run on everything from a PDP-12 with a VR12 to a PDP-8/e with a VC8E.
I was able to assemble the source file into a binary tape image suited for our Lab-8/e’s hardware using the Palbart assembler. The Lab-8/e has a VC8E display and the DK8-EP programmable clock installed. (The clock is used to keep the game running at a constant frame-rate, without it the game speed would vary depending on how much stuff was onscreen and how much work the CPU has to do.) These are selected by defining VC8E=1 and DKEP=1 in the source file
Loading and running the program yielded an empty display, though the CPU was running *something*. This was disappointing, but did I really think it’d be that easy? After some futzing about I noticed that if I hit a key on the Lab-8/e’s terminal, the Tektronix screen would light up briefly for a single frame of the game, and then go dark again. Very puzzling.
My immediate suspicion was that the DK8-EP programmable clock wasn’t interrupting the CPU. The DK8-EP’s clock can be set to interrupt after a specified interval has elapsed, and Spacewar uses this functionality to keep the game running at a steady speed — every time the clock interrupts, the screen is redrawn and the game’s state is updated. (Technically, due to the way interrupts are handled by the Spacewar code, an interrupt from any device will cause the screen to be redrawn — which is why input from the terminal was causing the screen flash.)
I dug out the DK8-EP diagnostics and loaded them onto the Lab-8/e. The DK8-EP passed with flying colors, but Spacewar was still a no go. I decided to take a closer look at the Spacewar code, specifically the code that sets up the DK8-EP. That code looks like this (with PDP-12 conditional code elided):
/SUBROUTINE TO START UP CLOCK /MAY BE HARDWARE DEPENDENT /THIS IS FOR KW12A CLOCK - PDP12 /OR PROGRAMABLE PDP8E CLOCK DK8EP CLSK=6131 /SKIP IF CLOCK CLLR=6132 /LOAD CONTROL CLAB=6133 /AC TO BUFFER PRESET CLEN=6134 /LOAD ENABLE CLSA=6135 /BIT RESET FLAGS STCLK, 0 CLA CLL /JUST IN CASE TAD (-40 /ABOUT 30CPS CLAB /LOAD PRSET CLA CLL TAD (5300 /INTR ON CLOCK - 1KC CLLR CLA CLL JMP I STCLK
The bit relevant to our issue is in bold above; the CLLR IOT instruction is used to load the DK8-EP’s clock control register with the contents of the 8’s Accumulator register (in this case, loaded with the value 5300 octal by the previous instruction). The comments suggest that this sets a 1 Khz clock rate, with an interrupt every time the clock overflows.
I dug out the a copy of the programming manual for the DK8-EP from the 1972 edition of the “PDP-8 Small Computer Handbook” (which you can find here if you’re so inclined). Pages 7-28 and 7-29 reveal the following information:
The instruction we’re interested in is the CLDE (octal 6132) instruction: (the Spacewar code defines this as CLLR) “Set Clock Enable Register Per AC.” The value set in the AC by the Spacewar code (from the octal value 5300) decodes as:
- Bit 0 set: Enables clock overflow to cause an interrupt.
- Bits 1&2 set to 01: Counter runs at selected rate.
- Bits 3,4&5 set to 001: 1Khz clock rate.
(Keep in mind that the PDP-8, like many minicomputers from the era, numbers its bits in the opposite order of today’s convention, so the MSB is bit 0, and the LSB is bit 11.) So the comments in the code appear to be correct: the code sets up the clock to interrupt, and it should be enabled and running at a 1Khz rate. Why wasn’t it interrupting? I wrote a simple test program to verify the behavior outside of Spacewar, just in case it was doing something unexpected that was affecting the clock. It behaved identically. At this point I was beyond confused.
But wait: The diagnostic was passing — what was it doing to make interrupts happen?
The above is a snippet of code from the DK8E family diagnostic listing, used to test whether a clock overflow causes an interrupt as expected. The JMS I XIOTF instruction at location 2431 jumps to a subroutine that executes a CLOE IOT to set the Clock Enable Register with the contents in AC calculated in the preceding instruction. (Wait, CLOE? I thought the mnemonic was supposed to be CLDE?) The three TAD instructions at locations 2426-2430 define the Clock Enable Register bits. The total sum is 4610 octal, which means (again referring to the 1972 Small Computer Handbook):
- Bit 0 set: Enables clock overflow to cause an interrupt
- Bits 1+2 unset: Counter runs at selected rate, and overflows every 4096 counts.
- Bit 3, 4+5 set to 110: 1Mhz clock rate
- Bit 8 set: Events in Channels 1, 2, or 3 cause an interrupt request and overflow.
So this seems pretty similar to what the Spacewar code does (at a different clock rate) with one major difference: Bit 8 is set. Based on the description in the Small Computer Handbook having bit 8 set doesn’t make a lot of sense — this test isn’t testing channels 1, 2, or 3 and this code doesn’t configure these channels either. Also, the CLOE vs CLDE mnemonic difference is odd.
All the same, the bit is set and the diagnostic does pass. What happens if I set that Clock Enable Register bit in the Spacewar code? Changing the TAD (5300 instruction to TAD (5310 is a simple enough matter (why, I don’t even need to reassemble it, I can just toggle the new bits in via the front panel!) and lo and behold… it works.
But why doesn’t the code make any sense? I thought perhaps there might have been a different revision of the hardware or a different set of documentation so I took a look around and finally found the following at the end of the DK8-EP engineering drawings:
Oh hey look at that why don’t you. Bit 8’s description is a bit more elaborate here: “Enabled events in channels 1, 2, or 3 or an enabled overflow (bit 0) cause an interrupt request when bit 0 is set to a one.” And per this manual, setting bit 0 doesn’t enable interrupts at all! To add insult to injury, on the very next page we have this:
That’s definitely CLOE, not CLDE. The engineering drawings date from January 1972 (first revision in 1971), while the 1972 edition of the PDP-8 Small Computer Handbook has a copyright of 1971, so they’re from approximately the same time period. I suspect that the programming information given in the Small Computer Handbook was simply poorly transcribed from the engineering documentation… and then Spacewar was written using it as a reference. There is a good chance given that this version of Spacewar supports a multitude of different hardware (including four different kinds of programmable clocks) that it was never actually tested with a DK8-EP. Or perhaps there actually was a hardware change removing the requirement for bit 8 being set, though I can find no evidence of one.
So with that bug fixed, all’s well and our hero can ride off into the sunset in the general direction of the 2017 Intergalactic Spacewar Olympics, playing Spacewar all the way. Right? Not so fast, we’re not out of the woods yet. Stay tuned for PART TWO!