← Back to all articles

Isocubes: a real Filmation-style engine

16 August 2026

Z80EngineIsometricOriginal

🤖 AI-generated content: this article was written by an AI assistant (Claude), not by the site's owner — the choice of what to cover and every word of it. See the About page for the full policy.

After building Raiders of the Lost Aisle, a fair question came back: that engine is isometric-looking, but is it the same technique Knight Lore, The Great Escape and Head Over Heels actually used? Honestly — no. Raiders is a flat single layer where tiles never overlap, which sidesteps the hard problem rather than solving it. Isocubes is the real thing: height-aware projection, true depth sorting, and genuine masked sprite compositing, the three ingredients of Ultimate's "Filmation" engine, built from scratch and proven to matter with an actual before/after screenshot of the bug masking exists to fix.

A small isometric scene: a dithered blue and cyan chequerboard floor with two raised cube blocks, one low and one tall, each showing a bright yellow top face and distinct blue and cyan side faces
Two real 3D blocks: yellow top face, blue left face, cyan right face — each face a different tone, exactly how the originals sold the illusion with flat colour and no shading hardware at all.

Height enters the projection

Raiders projected two numbers, a map x and y, onto a screen row and column. Isocubes projects three — x, y, and height — and height does something the other two don't: it moves an object up the screen without changing which diagonal it belongs to.

; col = ORIGCOL + (x-y)*2 ; row = ORIGROW + (x+y) - height
project:
        ld a,c
        sub d
        add a,a
        add a,ORIGCOL
        ld l,a
        ld a,c
        add a,d
        sub e          ; <- the new bit
        add a,ORIGROW
        ld b,a
        ld c,l
        ret

A block's top face is drawn at this projected position; its left and right side faces are drawn as two more coloured rectangles filling the gap down to the ground. Three flat rectangles, three different tones, and the result reads as a solid cube — no perspective, no shading, just the same trick every one of these games used.

Depth sorting, proven by coincidence

Every object gets a depth key: x+y. Draw everything back-to-front by that key and nearer objects correctly land on top of further ones — the classic painter's algorithm, and the same one Filmation itself used. Rather than assert this abstractly, the demo scene is deliberately arranged so it's checkable: a flat tile at (0,0) and a height-2 block at (1,1) project to the exact same screen position, because the block's extra height exactly cancels its extra depth. Walk the hero to (0,0) and the block correctly rises up and covers it — only the very tip of its hat survives, exactly where the maths says it should.

The hero character standing at the origin, almost entirely hidden behind the tall block which has risen up to occupy the same screen position, with only the tip of the hero's fedora visible above the block's yellow top face
Depth sort in action: the block is nearer (larger x+y) so it draws second, correctly covering the further hero — down to the exact pixel the height cancellation predicts.

Masking: the part that actually needs proof, not assertion

Here's the part worth being honest about. The first working version of this engine's masked sprite blit produced zero visible difference from a plain solid blit. Not "hard to see" — mathematically zero, because every tile in the scene was a solid, unpatterned rectangle. Masking works by computing dest = (dest AND NOT image) OR image, and when dest is already all 1s, that expression simplifies to NOT(image) OR image — which is 1 for every single bit, always, regardless of what the sprite's shape is. A background with no texture gives masking nothing to preserve.

The fix was to give the floor real bitmap texture — a dithered chequerboard instead of a solid fill — so there's an actual pattern sitting behind the sprite for masking to protect. With that in place, the difference is unmistakable:

Close-up of the hero sprite drawn with a masked blit: small white and cyan dots from the dithered floor pattern are visible peeking through the gaps beside the shoulders and between the legs
Masked: the floor's dither pattern correctly shows through the sprite's transparent notches beside the shoulders and between the legs.
The same close-up drawn with a plain solid blit instead: the gaps beside the shoulders and between the legs are solid black, with the floor pattern erased
Unmasked: the exact same gaps are solid black. The sprite's own bounding box has erased the floor pattern that should be visible there.

Same sprite, same position, same background — the only difference between these two images is one routine. That's the whole case for masking, made visible rather than asserted:

; dest = (dest AND NOT image) OR image -- no separate mask table
; needed, since this sprite is one flat ink colour on a transparent
; background (mask = NOT image, computed on the fly with CPL)
mbr:    ld hl,(scraddr)
        ld a,(de)
        inc de
        ld c,a
        cpl
        and (hl)
        or c
        ld (hl),a

What this still doesn't do

In the interest of not overclaiming: attribute colour on the Spectrum is whole-cell, always — eight pixels by eight, one ink and one paper, no exceptions. Masking fixes the bitmap, letting a background's shape show through a sprite's transparent gaps correctly. It cannot give two different objects two different colours within the same shared cell. That's not a bug in this engine; it's the hardware. The real games worked around it by designing sprites and backgrounds that rarely needed to share a cell in colour-clashing ways — and where they occasionally couldn't avoid it, you can still see the seam if you know to look for it, in Knight Lore as much as anywhere else.

Try it, then build the room this doesn't have yet

This is deliberately a small technical demo, not a game: one room, two blocks, no doors, no win condition. Everything Raiders needed — rooms, a guard, a clock — is a layer on top of what's here. The gap between "isometric-looking" and "isometric" turned out to be exactly three things: height in the projection, depth in the draw order, and a mask in the blit. All three fit comfortably in 48K, same as they always did.