Writing a Demoscene Intro for the ZX Spectrum

The techniques, tools, and culture of writing a Demoscene intro in Z80 assembly on the ZX Spectrum's extremely limited hardware.
This article covers the full picture of creating a Demoscene intro on the ZX Spectrum. It explains the Demoscene and intro concepts, why the ZX Spectrum's 3.5MHz Z80, 48KB RAM, and attribute color clash make it a classic challenge platform, and then dives into core techniques: Z80 assembly, careful memory layout, lookup-table visuals, cycle-level optimization, and beeper music that fakes multi-channel sound.

What Is a Demoscene Intro
The Demoscene is an underground digital art culture that originated in the 1980s, where programmers competed to create stunning audiovisual works on extremely limited hardware. An intro is a special form of this, usually only a few KB in size, yet it must present a combined effect of graphics, music, and scrolling text within seconds.
The ZX Spectrum, an 8-bit home computer released in 1982, features a 3.5 MHz Z80 processor and only 48 KB of RAM, making it one of the classic platforms for Demoscene creators to challenge themselves. Writing an intro on this machine means every byte and every clock cycle must be accounted for.
Why Choose the ZX Spectrum
The Creative Tension Brought by Hardware Limitations
The ZX Spectrum's display system is highly unusual: it uses an attribute memory scheme, where each 8×8 pixel block can only share two colors (foreground and background). This creates the famous "color clash" phenomenon, but it has also spawned a wealth of ingenious visual tricks.
Demoscene creators are drawn to this machine precisely because these limitations are themselves catalysts for creativity. When available resources are extremely limited, every line of assembly code a programmer writes carries a clear purpose, and this "dancing on the head of a pin" aesthetic is at the core of the Demoscene spirit.
The Specific Mechanics of Attribute Memory and Color Clash
The ZX Spectrum's screen resolution is 256×192 pixels, divided into 32×24 character cells, each 8×8 pixels. Pixel data is stored in a 6144-byte bitmap area, while the color information for each character cell is stored in the following 768-byte attribute area. The format of each attribute byte is FBPPPiii: the lowest 3 bits (iii) specify the ink color (foreground), the next 3 bits (PPP) specify the paper color (background), bit 6 (B) controls brightness, and the highest bit (F) controls flashing. This means all pixels within the same 8×8 block can only choose two of these 8 colors (plus brightness and flash combinations)—foreground and background. When adjacent graphical elements need different colors, color "bleeding" or "clash" occurs at block boundaries, the so-called color clash. Demoscene programmers often use this limitation itself as an artistic style, or avoid clashes by carefully aligning graphics with attribute block boundaries.
The Continuation of Community and Toolchain
Although the ZX Spectrum was discontinued decades ago, its enthusiast community remains active to this day. Modern developers can use cross-platform assemblers (such as SjASMPlus) and emulators (such as Fuse, ZEsarUX) to develop and test code, which greatly lowers the barrier to entry.
Core Techniques for Writing an Intro
Assembly Language and Memory Layout
Writing an intro on the ZX Spectrum almost necessarily requires Z80 assembly language. Although C compilers exist, the code they generate is far from meeting the Demoscene's stringent requirements for performance and size.
A typical memory layout requires careful planning: screen memory occupies a fixed 6912 bytes (6144 bytes of pixel data + 768 bytes of attribute data), and program code is usually placed after address 32768 to avoid conflicting with the screen area. Music data, graphics data, and code must coexist peacefully within a 48 KB space.
The Organization of the Z80 and the 48 KB Address Space
The Z80 has a 16-bit address bus and can address 64 KB of memory. The ZX Spectrum 48K model maps ROM (16 KB of system firmware) at 0x0000–0x3FFF, with RAM occupying 0x4000–0xFFFF. The screen pixel area is fixed at 0x4000–0x57FF, and the attribute area is at 0x5800–0x5AFF. This layout leaves roughly 41 KB of space from 0x5B00 to 0xFFFF for program code, data, stack, and system variables. Demoscene developers typically place code after 0x8000 to avoid the screen and system areas, while using the system variable area near 0x5B00 to store a small amount of temporary data. Precisely mastering these address boundaries is a prerequisite for avoiding overwriting the screen or corrupting system state.
Implementing Visual Effects
Common intro effects include:
- Scrolling text: achieved by directly manipulating pixel rows in screen memory for horizontal or vertical scrolling
- Plasma effect: using sine tables to generate flowing color gradients
- Raster effects: precisely timing within the screen refresh cycle to change border or attribute colors
These effects are trivial on contemporary hardware, but on the Z80 they require cycle-by-cycle optimization. A common trick is to use lookup tables instead of real-time computation to save precious CPU time.
Music and Sound Effects
The ZX Spectrum's beeper can only produce a monophonic square wave, but by rapidly switching frequencies, multi-channel music effects can be achieved. This technique is called "beeper music," and its principle is to exploit the persistence of hearing in the human ear, alternating different pitches within extremely short time intervals.
Beeper Music Driver Techniques
The ZX Spectrum's beeper is controlled by an output port bit of the ULA chip and can only produce a square wave. To simulate multi-channel effects, developers use a technique called "1-bit music" or a "beeper engine": within very short time slices (usually 1/50 second or shorter), rapidly alternate setting the beeper output high or low, approximating different volumes by adjusting the duty cycle of pulses within each time slice, and then switching pitch at extremely high frequency so that the auditory system fuses rapidly alternating notes into chords. Common engines such as Beepola generate data formats containing frequency tables, note durations, and effect commands. Since the CPU must precisely maintain switching timing, music playback often competes with raster effects for cycles, requiring careful interleaving.
Modern Development Workflow
Tool Selection
The workflow for developing a ZX Spectrum intro today is roughly as follows:
- Compile Z80 assembly code using SjASMPlus or Pasmo
- Run and debug in the Fuse or ZEsarUX emulator
- Create graphic assets using tools such as ZX Paintbrush
- Generate beeper music data with tools such as Beepola
Debugging and Optimization
The debugging features provided by emulators far surpass original hardware—developers can set breakpoints, inspect register states, and even single-step execution. Even so, true optimization still depends on a deep understanding of Z80 instruction set timing.
Every Z80 instruction has a precise clock cycle count, and in raster effects, being a few cycles off can cause screen tearing. Experienced Demoscene developers can often intuitively judge whether a piece of code is "fast enough."
Z80 Instruction Timing and Raster Synchronization
Every Z80 instruction has a fixed number of machine cycles (T-states); for example, LD A,B takes 4 T-states and LD A,(HL) takes 7 T-states. The ZX Spectrum's CPU clock is 3.5 MHz, and under the PAL standard the screen refreshes 50 times per second, giving about 69,888 T-states per frame (including vertical blanking). Raster effects require precisely changing hardware registers (such as the border color port 0xFE or attribute data) when the screen scans to a specific line, so the code must be strictly synchronized with the ULA's scan lines. Developers typically use the "HALT" instruction to wait for the frame interrupt, then align to the target scan line through precise delay loops or "no-operation" instruction padding, with a tolerance often of only a few T-states.
The Contemporary Significance of Demoscene Culture
In an era of surplus computing power, the "limitation-driven creativity" philosophy represented by the Demoscene seems all the more precious. It reminds us that technological creativity does not depend entirely on hardware specifications; understanding of underlying principles and dedication to craft are equally important.
Intro creation on the ZX Spectrum is essentially an extremely pure programming practice—no frameworks, no dependencies, no abstraction layers, just a direct dialogue between you and the hardware. This experience has almost disappeared from modern software development.
For developers who want to deeply understand how computers work at a low level, trying to write an intro for the ZX Spectrum or another retro platform may be a more effective way to learn than reading any textbook.
Frequently Asked Questions
What foundational knowledge is needed
A grasp of basic Z80 assembly language is a necessary prerequisite. In addition, understanding binary, hexadecimal arithmetic, and computer memory models will be very helpful. For developers with no assembly experience at all, it is recommended to start with simple screen output programs.
Where to get help
The World of Spectrum forums and Demoscene-related Discord servers are active places for discussion. In addition, pouet.net catalogues a large number of intro works for the ZX Spectrum platform, which can be downloaded, run, and studied for their source code (some works are open source).
How small can a minimal viable intro be
An intro containing simple scrolling text and basic sound effects can be compressed to under 256 bytes of code. Extreme size competitions (such as 256-byte intro competitions) are a highly popular category in the Demoscene community.
One-line Summary
On the ZX Spectrum's extremely limited hardware, the techniques, tools, and cultural significance of writing a Demoscene intro in Z80 assembly.
Paragraph Summary
This article systematically introduces the complete picture of creating a Demoscene intro on the ZX Spectrum. It first explains the concepts of the Demoscene and intros, and why the ZX Spectrum—with its 3.5 MHz Z80, 48 KB RAM, and attribute memory color clash—became a classic challenge platform. It then delves into the core techniques: Z80 assembly is essential, memory layout must be carefully planned, screen memory occupies a fixed 6912 bytes; visual effects rely on lookup tables and cycle-by-cycle optimization; beeper music simulates multi-channel sound by rapidly switching square wave frequencies. The modern development workflow uses cross-platform tools such as SjASMPlus, Fuse, and Beepola, with emulator debugging far surpassing original hardware. The article also discusses the cultural significance of the Demoscene in an era of surplus computing power—limitation-driven creativity—and the unique value of writing intros for retro platforms in understanding the computer at a low level.
Related articles

Why Does the Tesla Roadster Need to Fly? A Deep Dive into Musk's Wild Demo
Tesla's Roadster launch showed wall-climbing, upside-down driving, and flying stunts—but The Vergecast notes the demo car may lack a battery, the Rocket version is invite-only and not street-legal, and the website terms don't guarantee delivery. After nine years of delays, why does this car still need to exist?

AI Is Not a Replacement: Human-AI Collaboration Through the Lens of Factory Root Cause Analysis
Starting from factory root cause analysis, this article explains how AI accelerates evidence chain construction rather than replacing human experts, exploring the pragmatic implementation logic and business value of 'AI supporting people rather than replacing them.'

AI Agent Decision Auditing: Building an Evidence Chain in Regulated Workflows
Starting from a Reddit discussion, this article analyzes three core issues in AI agent decision auditing within regulated workflows: what fields audit records should contain, how to handle feedback latency for erroneous decisions, and how to continuously calibrate LLM judge consistency with human judgment.