Home
Admin | Edit

The Cube is A Lie - Atari ST 256 bytes

link

A rotating pseudo cube (showing two faces at most) animated effect on bare 8 MHz Atari ST. (1985)

This one was my first work for Lovebyte 2025, probably took most of my time as i needed to get comfy with the platform / Motorola 68000 CPU which i briefly fiddled with in the past.

The effect algorithm (an iterative way to draw a cube !) came from some experiments i did with the integer circle algorithm / HAKMEM 149 in late 2024, the original idea was to exploit the square <> hexagon transition which happen when the algorithm precision is messed with, simple 2D rotation is then added and a midline is drawn to make it looks like a rotating cube.

first version of the algorithm (prototype)

early rotation with edges precision issues (prototype)

The first version was a raw port of the JS prototype, it was a mix of direct pixels plotting and Line A calls (midline was drawn using line API) with whole screen clear (terrible flickering due to this !), i discovered that the main issue on this platform / effect is speed though (this is no ARM !) so it was very slow, only was acceptable at 32 MHz... the algorithm use a lot of shifts also which is not that free on the 68000 (cycles variable) ... so the next goal after size was to bring acceptable speed at 8 MHz.

An early issue which prevented further speed optimizations was executable size, the midline call was costly in terms of speed / size requiring a condition in the cube outline loop, could have been moved out but this added more instructions.

slow early port (32 MHz) with Line A midline, multiple lines also due to precision, flickering due to that + whole screen clear

still 32 MHz and Line A midline but better timing / optimization

Main idea to bring speed / size at reasonable level was to first get rid of all Line A calls, i discovered a way to get rid of it by "collapsing the outline" which is just a fancy way to say that the cube outline is basically drawn two times with the y coordinate fixed on the second pass, this collapse the outline into a midline due to the way the algorithm works, end result is that it use the same rendering code as the outline, disadvantage is that the midline is rendered with more points than necessary and with overdraw, still acceptable with low amount of points.

Best speed improvement i made was lowering the amount of points and the removal of the screen clearing code, drawn points are stored temporarily into the stack instead and i clear them before drawing again. This brings tremendous speed and it is the favored approach on these oldschool machines. (was used by many demos with dots effects !)

Further speed improvement came by generating loop code dynamically to reduce branching etc. it is also possible to gain further bytes / speed by removing the fractional adjust (which produce the shape transition) but the animation is less smooth.

Another cheap way to gain speed is to run it at high resolution / monochrome mode, dots can be increased x2 in this case. (more bandwidth)

This algorithm is perhaps a complicated / inefficient way to draw a cube (animation could probably be precalc.), it is all iterative and without initial data though, the illusion works so i am still satisfied of pulling it off at 256 bytes (headers included) at reasonable speed on a 8 MHz 1985 ST ! (original idea was to do it in 128 bytes and with more dots but... failed !)

A possible amelioration is to have dots "trail" by stacking points until N frames then dimming them out progressively, seems doable at this size but didn't try.

with trail produced by the Dreamelt method (prototype)

Coding on the ST was painful... the ST / 68000 is okay but i am way more comfortable with early ARM and i dislike the lengthy 32 bytes executable header, huge respect to the 68000 masters though !

filled constrained version by joining ends with a line (prototype; way too slow)

A great 256 bytes (made for Atari Falcon) that i discovered while making this is Cube_256, it show a 3D cube and use Line A polygon calls to construct the cube faces :

Cube_256 by Dune

p5js prototype sources

function setup() {
  createCanvas(320, 200)
}

let ms = 140
let mc = 0
function draw() {
  background(0)
 
  // transition animation
  ms += mc >> 5
  mc -= ms >> 6
 
  let tr = ((ms >> 7) ^ ms) >> 3
 
  let xf = 0

  let x = -1
  let y = x
  loadPixels()
  for (let j = 0; j < 63; j += 1) {
    for (let i = 0; i < 7; i += 1) {
      x += y >> 6
      y -= x >> 6
      
      xf += tr
      if (xf >= 0) { // fractional adjust for smooth transition animation
        x -= 1
        xf -= 38
      }
    }

    let ix = (ms < 0) ? 63 - x : x
    let iy = (ms < 0) ? 63 - y : y

    //let y2 = y
    for (let p = 0; p < 2; p += 1) {
      // uncomment (above and below) to get rid of the conditional statement (also comment the resulting duplicata)
      //let ix = (ms < 0) ? 63 - x : x
      //let iy = (ms < 0) ? 63 - y2 : y2
      // compute final coordinates with 2D rotation
      let fx = 127 + ms + ((ix * mc - iy * ms) >> 7)
      let fy = 64 + ((ix * ms + iy * mc) >> 7)

      let index = (fx + fy * width) * 4
      pixels[index + 0] = pixels[index + 1] = pixels[index + 2] = 255
      
      // uncomment (and above) to get rid of the conditional
      //y2 = 63
      if (ms < 0) {
        iy = 0
      } else {
        iy = 63
      }
    }
  }

  updatePixels()
}

Aside : Dots on the Atari ST

Dots effect are the first demoscene effects i came across, first in my PureBasic years with plenty starfields / tunnels / oldschool effects then on Atari ST (Blood !) and other platforms, here are some of my favorite examples on the ST :

sphereST (128 bytes) by atariBDSM

atom (128 bytes) by Acid Team

Galaktyka (3D starfield; 128 bytes) by Marquee Design

Virtual Escape by Equinox

Beamdot by MJJ Prod (6492 dots !)

Glokzilla by MJJ Prod

Suretrip II - Dopecode by Checkpoint

Blood by Holocaust, plenty nice dots (tunnels, landscape etc.)

Rising Force by Holocaust

Nostalgic-O-Demo by Oxygene

back to topLicence Creative Commons