The Minskytron and Other Early Graphics Demos

This is a virtual DEC PDP-1 emulated in HTML5/JavaScript running some early graphics demonstrations.

Programs available:

Explore the Test Word Switches for patterns with the Minskytron and Munching Squares!
The Minskytron must be started anew to accept fresh settings. See the button "Start".
There are various presets for the Test Word in the menu "Select a Program", listing the most common one as the main item.

Note: The Test Word Switches provide means of manual input for an 18-bit word and are located at the control console of a real PDP-1.
(Bits were counted by DEC from left to right, starting at zero for the most significant. This is also kept for the tool-tips.)

All programs are run from digital images of paper tapes to be found at
Three of these "display hacks" are combined on a single paper tape, "dpys5.rim," representing them as shown at the Computer History Museum (CHM) in Mountain View, CA. (The name "dpys5.rim" is apparently derived from "dpy", the display instruction of the PDP-1.)
The full version of Snowflake is loaded from a separate tape image named "snowflake_sa-100.bin".

Artwork and PDP-1 emulation by Norbert Landsteiner,, 2012–2015.
Based on emulation code by Barry Silverman, Brian Silverman, and Vadim Gerasimov. The original code was extended to support some additional instructions and auxilary hardware. Moreover, the shift/rotate instructions and the arithmetics were rewritten (include an emulation of the hardware multiply/divide option), and cycle counts were added for accurate timing and frame rates. Some importance was put in the recreation of the appearance of the original CRT display and the unique experience conveyed by it.

The emulator was originally conceived for running Spacewar!, the earliest known digital video game.
Play it here:


Display Characteristics

The DEC PDP-1's Type 30 Visual CRT Display was a point plotting display* with a dual P7 phospor (light blue for fresh pixels and a yellowish green long sustain — think of radar display, this is exactly what the tubes were made for). The display featured a technical resulution of 1024 x 1024 display locations at 8 intensities, but according to DEC documentation only 512 of them on any axis were visible to the human eye. Thus, the low (or standard) resolution of the emulation, rendering at this visual resolution, is closest to real thing. (Compare the images below.) The high resolution versions render the programs at the technical resolution and are scaled down to fit the appearance of the emulated screen.

*) A point plotting display is a random access display, like a vector display, but doesn't feature any memory or line drawing capabilities. Display locations are addressed individually and have to be refreshed by the program. The long sustain of the P7 phosphor helps in keeping the image stable. The spot size of an activated display location was usually bigger than the distance between display locations, thus individual blips tended to merge. Spot sizes also varied by the intensification of the blips, bright spots were bigger than those at lower intensities.


Understanding the Minskytron

The Minskytron on the PDP-1 (CHM)
The Minskytron on the PDP-1 at the CHM.
Photo by Joi Ito, 2007 (CreativeCommons)

The Minskytron is a visual synthesizer based on 3 interconnected oscillators (much like a Moog synthesizer). Each oscillator advances an x- and a y-coordinate over an elliptical function, plotting a dot at the given position at each frame. The formular is based on the ancient art of drawing a circle using additions/subtractions and bitwise right-shifts (a division by powers of 2) only:

x := x – (y >> 4)
y := y + (x >> 4)

(Note: This algorithm for drawing a circle was discovered by Marvin Minsky actually by a mistake that brought up a circle on the display rather than the expected curve:

«Here is an elegant way to draw almost circles on a point-plotting display:

NEW X = OLD X – epsilon * OLD Y
NEW Y = OLD Y + epsilon * NEW(!) X

This makes a very round ellipse centered at the origin with its size determined by the initial point. epsilon determines the angular velocity of the circulating point, and slightly affects the eccentricity. If epsilon is a power of 2, then we don't even need multiplication, let alone square roots, sines, and cosines! The "circle" will be perfectly stable because the points soon become periodic.

The circle algorithm was invented by mistake when I tried to save one register in a display hack! Ben Gurley had an amazing display hack using only about six or seven instructions, and it was a great wonder. But it was basically line-oriented. It occurred to me that it would be exciting to have curves, and I was trying to get a curve display hack with minimal instructions.»

"Item 149 (Minsky): Circle Algorithm" in HAKMEM, Programming Hacks. MIT AI Memo 239, Feb. 29, 1972)

The Minskytron varies this scheme by applying an individual number of right-shifts at each of these steps, derived from the bits of the Test Word and transformed to according shift instructions on the fly:
The first 3 bits (from the left) determine the number of bits the modifying term of the y-coordinate of the first oscillator is shifted right (sh0), while the next 3 bits give the number of shifts to be applied to the modifying term of the y-coordinate (sh1).
The next 3 bits provide the setting for the y-coordinate of the second oscillator (sh2), followed by 3 bits for its x-coordinate (sh3).
Finally, the last pair of 3 bits gives the number of shifts for the third and last oscillator (sh4, sh5).

These shifts are now applied to the oscillators in a loop:

ya := ya + ((xa + xb) >> sh0) // sh0 = 1 + Test Word bits 0..2
xa := xa – ((ya – yb) >> sh1) // sh1 = 1 + Test Word bits 3..5
display a dot at xa | ya

yb := yb + ((xb – xc) >> sh2) // sh2 = 1 + Test Word bits 6..8
xb := xb – ((yb – yc) >> sh3) // sh3 = 1 + Test Word bits 9..11
display a dot at xb | yb

yc := yc + ((xc – xa) >> sh4) // sh4 = 1 + Test Word bits 12..14
xc := xc – ((yc – ya) >> sh5) // sh5 = 1 + Test Word bits 15..17
display a dot at xc | yc


Rather than using the respective other coordinate of the individual oscillators, like we've seen it in the the basic algorithm for drawing a circle, here, the modifying term for a coordinate is based on the difference of this other coordinate to the respective coordinate of the next oscillator, thus connecting them in a daisy-chain. The shifts set up by the Test Word are applying an individual scaling (or distortion) to each of these factors.

The Minskytron - Schematic Representation

The start values for the x- and y-coordinates are fixed. The Test Word provides only the means of configuring the shift instructions that are set up at the start of the program. (There is still a shift applied, if all the respective bits are set to low. All bits zero is therefor a shift by a single bit to the right, and all three bits high corresponds to an arithmetic shift to the right by 8 bits.) Increasing or reducing shifts symmetrically for any pair of tripple bits will change the scaling of an effect. Applying asymmetrical shifts to any pair will add distortion.
Most patterns will soon "go berserk" for the limited precision of the PDP-1's 18-bit words. — Experiment!

(An annotated version of the source code is available here.)


Understanding Munching Squares

Munching Squares on the PDP-1 (CHM)
Munching Squares on the PDP-1 (CHM).
Still from a video by Ken Sumrall, © 2015.

Munching Squares is a visual excercise in binary logic: Each frame starts with a reading of the Test Word. If this were either 0 or -0 (the PDP-1 represented negative numbers in 1's complement featuring the value minus zero), the octal value 2345 is used instead. This is added to the value computed in the previous frame and the result is stored. Then, the result is split in an upper and lower half by a bitwise rotation to the left by 9 bits applied to the accumulator and the IO-register as a combined 36 bit register: The higher 9 bits are transferred to the y-coordinate of the display (IO-register), but for the special format used by the display instruction — only the highest 10 of 18 bits are used — most of these bits will come into effect only at the next frame. The lower 9 bits are shifted to the most significant positions (again, there is an interleaf with a previous frame, the frame before the last frame, as the 9 highest bits previously in IO will be transferred to the lower half of the accumulator) and an exclusive OR (xor) is applied using the stored sum as an argument. The resulting value (highest 10 bits significant only), is finally used as the x-coordinate of the display instruction. After plotting a dot at the given screen position, the program starts over for the next frame.

read testword
if testword equals +/– 0, use (octal) 2345
add last stored result (from previous frame) to it
store result
(AC, IO) << 9: rotate higher 9 bits into lower half of the other register, rotate lower 9 bits into high position
  (AC := AC9..17IO0..8 , IO := IO9..17AC0..8 ; bit0 is the most significant bit, as in DEC documentation)
xor with stored result
display at highest 10 bits of result (x) | highest 10 bits IO (y)

(As may be observed, this little program is a bit more complex than it has often been described as "a trivial computation repeatedly plotting the graph Y = X XOR T for successive values of T = time." Moreover, some of its effects are brought to life by the long sustain of the Type 30 CRT display's dual P7 phosphor only.)



Snowflake on the PDP-1 (CHM)
Snowflake on the PDP-1 (CHM).
Photo by, 2006 (CreativeCommons).

In contrast to the two previous progams, Snowflake is a fairly complex program. It displays a symmetrical pattern composed by a moving dot mirrored by 2 axis and duplicated twice with a rotation by 60 degrees. All kind of operations are applied to the plotting positions in order to provide a pleasing result. For its resulting 6-armed concentric graphics composed of 12 moving dots this kind of program is also known as a 12 point display (often also named a 6 point display for its 6 synchronized movements). The program is here presented in two similar, but slightly different versions. (The full version of the program allows the inspection of the individual movements by setting sense switches 1 and 2 to high, see the options menu options menu icon floating at the top right of the screen.)

All programs are written in PDP-1 assembler code using MIT's Macro assembler.