The Cube is A Lie - Atari ST 256 bytes

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 top


