Skip to content

Instantly share code, notes, and snippets.

@shirriff
Last active June 18, 2017 16:25
Show Gist options
  • Save shirriff/323b71e0dd24e58f3b0993ba67009515 to your computer and use it in GitHub Desktop.
Save shirriff/323b71e0dd24e58f3b0993ba67009515 to your computer and use it in GitHub Desktop.
Mandelbrot set code for the Xerox Alto, written in BCPL.
get "streams.d"
external
[
Ws;
Wns;
MulFull;
DoubleAdd;
keys;
Gets;
]
let Main() be
[
let v = vec 30705 // Pixel buffer
v = (v + 1) & -2 // Data needs to be 32-bit aligned
let dcb = vec 5 // Display control block: defines display region
dcb = (dcb + 1) & -2
dcb!0 = 0 // End of display list
dcb!1 = 38 // 38 words per line
dcb!2 = v // Data pointer
dcb!3 = 404 // # lines / 2
let lvdas = #420 // Address holds pointer to display control block
lvdas!0 = dcb
for i = 0 to 30703 do v!i = 0 // Clear display
// Values are represented as fixed point with 12 bits to right of decimal point.
let x0 = (-2) lshift 12 // Left boundary: x = -2
let x1 = 1 lshift 12 // Right boundary: x = 1
let y0 = (-1) lshift 12 // Top boundary: y = -1
let y1 = 1 lshift 12 // Bottom boundary: y = 1
let xstep = (x1 - x0) / 600 // Render 600 pixels horizontally
let ystep = (y1 - y0) / 400 // Render 400 pixels vertically
let x2 = vec 2 // double word to hold x^2
let y2 = vec 2 // double word to hold y^2
let xy = vec 2 // double word to hold x * y
let cy = y0 // Constant value, y part. I.e. the z value for this pixel
for ypos = 0 to 400 do // line count. Note "for" limits are inclusive.
[
let cx = x0 // Constant value, x part.
for h = 0 to 37 do // horizontal word count
[
for b = 0 to 15 do // horizontal bit count
[
let x = cx // The complex z value is represented as x + i*y
let y = cy
for n = 0 to 999 do // Will bail out long before 999
[
MulFull(y, y, y2) // y2 = y*y. Integer multiplication, y2 is double word.
MulFull(x, x, x2) // x2 = x*x
if x2!0 + y2!0 ge 1024 then break // Quit if x^2 + y^2 > 4
if n eq 20 then // Last iteration. Still inside set, so set pixel.
[
let adr = (200 + ypos) * 38 + h // 200 blank pixels at top, 38 words per line
v!adr = v!adr % (1 lshift (15-b))
break
]
// Convert to single precision by dropping 12 bits.
// rshift 12 = lshift top word 4
let x2sp = (x2!0 lshift 4) % (x2!1 rshift 12) // x2sp = x^2, single precision
let y2sp = (y2!0 lshift 4) % (y2!1 rshift 12) // y2sp = y^2, single precision
MulFull(x, y, xy) // xy = x*y
let xysp = (xy!0 lshift 4) % (xy!1 rshift 12) // xysp = x*y, single precision
// z = z^2 + c (complex arithmetic, z = x+iy)
// i.e. y = 2xy + cy
// x = x^2 - y2 + cx
y = xysp + xysp + cy
x = x2sp - y2sp + cx
]
cx = cx + xstep // Move to next cx value
]
]
cy = cy + ystep // Move to next cy value
]
Gets(keys) // Get a key, i.e. wait for a keypress
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment