Bad Apple · Volume 3

Bad Apple!! — Notable Ports

The ports below are grouped by what kind of display they drive, because that is what determines the interesting part of the work. Every entry here has a published project writeup, a source repository, or coverage in a publication that examined it. Ports known only from a video title are discussed separately in volume four.

3.1 Vector displays: drawing outlines, not pixels

A vector display has no pixels. A beam is steered directly to trace lines, and an image is a list of strokes. For a silhouette animation this is either ideal or absurd depending on how one looks at it, because the source is filled regions and the display draws edges.

The Vectrex — a 1982 games console notable for shipping with its own vector monitor — received a Bad Apple demo delivered on a multicart with sixteen megabytes of flash, covered by Hackaday in April 2015. The conversion pipeline is the interesting part: individual frames were exported as bitmaps, run through Potrace to convert filled raster shapes into vector outlines, and a custom script then translated those outlines into the relative vector format the Vectrex hardware consumes. Timing was synchronised against a modified emulator before the result was committed to the cartridge.

Figure 1 — The Vectrex, released in 1982 with an integral vector monitor. It has no pixels and no framebuffer; an image is a list of strokes for the beam to trace, which is why the port's first step was conve…
Figure 1 — The Vectrex, released in 1982 with an integral vector monitor. It has no pixels and no framebuffer; an image is a list of strokes for the beam to trace, which is why the port's first step was converting every frame to outlines. — File:Vectrex-Console-Set.jpg by Evan-Amos. License: CC BY-SA 3.0. Via Wikimedia Commons.

The same principle drives the oscilloscope ports, which are the most widely reproduced of all. An analogue oscilloscope in XY mode uses one input to deflect the beam horizontally and the other vertically, so a stereo audio signal becomes a pair of coordinates. Convert each frame to a path, encode the path as left and right channel waveforms, and play the file: the instrument draws the animation. Several independent implementations exist as public repositories, and general-purpose libraries for rendering graphics to vector displays through audio are maintained for the same reason.

3.2 Character displays: no pixels to address

More constrained again are displays that cannot address pixels at all. An HD44780-compatible alphanumeric LCD shows characters from a fixed font in a fixed grid. Its one loophole is a handful of user-definable characters, which can be reprogrammed on the fly — so a coarse bitmap can be smuggled in by continuously redefining the glyph set.

Hackaday covered a 16-by-2 character LCD implementation in June 2022, which its author documents at length, and a related project in February 2022 in which a 32-kilobyte EPROM drives an HD44780-compatible display with no processor in the circuit at all: the address counter walks the ROM and the ROM’s outputs are the display’s inputs. The author’s own account sets out the circuit.

Figure 2 — A 16-by-2 alphanumeric LCD of the HD44780 pattern, on a breadboard. It has no addressable pixels — only a fixed grid of character cells and a small number of redefinable glyphs, which is the entire…
Figure 2 — A 16-by-2 alphanumeric LCD of the HD44780 pattern, on a breadboard. It has no addressable pixels — only a fixed grid of character cells and a small number of redefinable glyphs, which is the entire loophole these ports exploit. — File:MELT 16x2 LCD alphanumeric display 10(DXO).jpg by Retired electrician. License: CC0. Via Wikimedia Commons.

3.3 No CPU at all

The breadboard implementation is the most instructive project in the whole field. It generates PAL composite video from standard CMOS logic — a pair of 4040 binary counters dividing a 16 MHz master clock, shift registers serialising sync pulses, assorted gates, and an EPROM holding the encoded stream. There is no CPU and no RAM. There is no framebuffer: the picture is generated pixel by pixel at exactly the rate the television consumes it, with dedicated logic performing the decompression that software would ordinarily do. The author describes the project as taking a 6502 homebrew computer and removing the processor and the memory, keeping only the video output circuit.

3.4 Eight-bit home computers

These are the ports where storage and streaming dominate.

The Commodore 64 demo Bad Apple 64, by Onslaught, released 29 June 2014, is the best documented. More than two thousand frames at about seventy bytes each fit into roughly 170 kilobytes on one disk, playing at twelve frames per second streamed continuously from the drive on a 1 MHz machine.

Figure 3 — The Commodore 64. The 1 MHz processor is not the binding constraint in the 2014 demo; the disk drive is, because the frames stream from it continuously rather than being held in memory.
Figure 3 — The Commodore 64. The 1 MHz processor is not the binding constraint in the 2014 demo; the disk drive is, because the frames stream from it continuously rather than being held in memory. — File:Commodore-64-Computer-FL.jpg by Evan-Amos. Public domain. Via Wikimedia Commons.

The Apple II+ implementation takes a different and in some ways harder path. ProDOS is removed entirely to free memory, which is then given over to Huffman decompression tables and eight-by-eight tile storage. The encoding pipeline computes inter-frame deltas, divides them into tiles, uses k-means clustering to reduce the distinct tile count across the whole animation, run-length encodes runs of tiles into stripes, and applies a Huffman-style dictionary to the stripes. Data is written to raw disk sectors. Because the Apple II has no timer, playback is clocked by the rotation speed of the floppy drive, and sector reads — which block the processor — are interleaved with drawing so that the animation does not hitch.

Figure 4 — The Apple II. With no hardware timer available, the documented port uses the rotation of the floppy drive as its time base — a constraint that shapes the entire playback loop.
Figure 4 — The Apple II. With no hardware timer available, the documented port uses the rotation of the floppy drive as its time base — a constraint that shapes the entire playback loop. — File:Apple II at Musée Bolo.jpg. License: CC BY-SA 2.0 fr. Via Wikimedia Commons.

3.5 Microcontrollers and small embedded targets

This is the largest and least individually notable category, which is itself the point: by now, getting the animation onto a microcontroller with a small display is a weekend exercise rather than an achievement.

Hackaday covered an Arduino Mega 2560 implementation in January 2019, storing the video at one bit per pixel, and its author’s own writeup sets out the encoding. A PineTime smartwatch port followed in October 2021, with its source published alongside a separate video-processing tool. Implementations for ESP32 boards driving SSD1306 OLED modules exist as public repositories, typically combining run-length encoding with a general-purpose compression library. The CHIP-8 virtual machine — or more precisely its XO-CHIP extension — has a port, which is a target with no hardware of its own at all. The Arduboy community produced several iterations specifically as compression exercises, a first in 2017 and a more aggressive successor four years later.

Figure 5 — An Arduino MEGA 2560 board. The documented 2019 port stores the animation at one bit per pixel; the platform is unremarkable, which is precisely what makes it a useful baseline.
Figure 5 — An Arduino MEGA 2560 board. The documented 2019 port stores the animation at one bit per pixel; the platform is unremarkable, which is precisely what makes it a useful baseline. — File:Arduino MEGA 2560, front side.jpg by Dsimic. License: CC BY-SA 4.0. Via Wikimedia Commons.
Figure 6 — The PineTime, an open-source smartwatch. A 2021 port put the animation on its display — a reminder that the interesting constraint on modern small hardware is usually power and storage rather than …
Figure 6 — The PineTime, an open-source smartwatch. A 2021 port put the animation on its display — a reminder that the interesting constraint on modern small hardware is usually power and storage rather than raw capability. — File:PineTime smartwatch.jpg. License: CC0. Via Wikimedia Commons.

The outlier in this group is badderapple, targeting a CH32V006 — a very cheap RISC-V part with 62 kilobytes of flash and 8 kilobytes of RAM — which fits all 6,570 frames plus audio plus code into 64.5 kilobytes at thirty frames per second, as described in volume two.

3.6 Software targets, and deliberate abuse

The last group does not involve hardware constraints at all. These are ports into software environments that were never meant to display video, and the achievement is finding the mechanism rather than fitting the data.

Minecraft, in an implementation published in October 2024, renders the animation at 512 by 384 and twenty frames per second — the platform’s tick rate — in six levels of grey, using nothing but structure blocks triggered by redstone. No command blocks and no datapacks were used, which is a self-imposed constraint that makes the project considerably harder. Roughly 192 chunks must be updated at 20 Hz, and the author reports that the bottleneck turned out to be neither redstone nor lighting but plain block updates and event handling.

Inside a font file is the most pointed example. HarfBuzz, the text shaping engine used across most of the software people read text in, introduced an experimental WebAssembly shaper in version 8.0, allowing a font to carry its own shaping program embedded in the file. A font was duly built that plays the animation in any editable text area. The idea is credited to Valdemar Erk; a public implementation exists, alongside a collection of other demonstrations of the same mechanism. This is best understood as a security-adjacent demonstration of what an embedded WebAssembly shaper can do, dressed as a joke.

Hackaday has also covered ports to a Yamaha PSR-E433 keyboard delivered over MIDI in January 2025, for which the author’s account runs from JTAG to shellcode; to a Vim session driven by roughly 6,500 regular-expression searches in January 2025, written up with source published; and to a karaoke machine using the CD+G graphics format in July 2026, documented by its author.

Comments (0)

  1. Loading…

Comments are held for moderation — nothing appears until approved.