It reads your
handwriting.

A neural network on a stock 1982 Vectrex. No frame buffer. 1 KB of RAM.

The machine

CPU
6809
Motorola, 1.5 MHz, 8-bit. The same chip that ran the BIOS in 1982.
RAM
1 KB
874 bytes for the program: strokes, grid, 64 sums, the stack. The BIOS has the rest.
Frame buffer
NONE
There is no picture in memory. Every line is the electron beam steered from point to point, redrawn 50 times a second.
Cartridge
12 KB
10 KB of it are the network’s weights, as 8-bit integers.
Network
144›64›10
The first layer is additions only: every input is a grid cell, on or off.
Division
ZERO
The drawing is scaled by a reciprocal table: one MUL per point.
MNIST test
93.2%
On the 10,000 test digits, through the exact integer arithmetic the 6809 runs.
Proof
400/400
The cartridge’s answers and all ten scores equal a Python twin, byte for byte, in MAME.

Stock hardware. Nothing added.

Plenty of Vectrex projects run modern code on a modern processor and use the Vectrex as a display. This one runs entirely on the console’s own 6809, from an ordinary 12 KB cartridge image.

Watch it

The demo draws a 1, a 7, a 0 and a 4 with a scripted joystick, and the cartridge reads each one. It was recorded frame by frame in MAME. The glow is a phosphor-decay filter: a real vector tube glows, and MAME’s 60 Hz capture of a 50 Hz console needs it to look whole.

The colours come from the overlay: Vectrex games came with a printed plastic film over the screen, and VecNIST has one too (overlay/vecnist.png).

Get the ROM

Download vecnist.bin
12,254 bytes · md5 857a5285ac59c64ded7ebcad4223b208
A standard Vectrex cartridge image. Tested in MAME; not yet tested on a real Vectrex.

No Vectrex? Try it in MAME.

If you don’t have a Vectrex, try it for yourself in MAME. It needs the Vectrex BIOS (vectrex.zip) in its ROM path.

mame vectrex -cart vecnist.bin

The BIOS shows its own screen for about ten seconds, then the title, then the game. The joystick is the arrow keys (or a gamepad); MAME’s buttons 1–4 are the Vectrex’s.

Button 1
INK
hold it and draw
Button 2
READ
read it now (it also reads each time a stroke ends)
Button 3
CLEAR
start again
Button 4
PEN
light-pen mode: experimental, see the README

How it reads

  1. The joystick moves a cursor, and every move is kept as a point: up to 220 of them in the 1 KB, as strokes. Each frame the Vectrex steers the beam along them again, because there is no frame buffer to keep them in.
  2. When a stroke ends, the drawing’s bounding box is fitted into 9 cells. A reciprocal table does the scaling, so it’s one MUL per point and no division. The box is centred in a 12×12 grid of bits, and consecutive points are joined cell by cell.
  3. Layer 1: every inked cell adds its row of 64 weights into 64 sums. It’s only additions, because the inputs are 0 or 1.
  4. Layer 2: each of the ten scores sums 64 activations times their weights, each product one MUL, into 24 bits. The highest score is the answer.
  5. On the PC, MNIST’s thick scanned digits are thinned to one-pixel strokes and pushed through the very same integer steps, so the network trains on what a joystick draws.

Build it yourself

git clone https://github.com/magneato/vecnist
cd vecnist
./setup.sh      # lwasm, MAME, Python + numpy (and checks for the Vectrex BIOS)
./build.sh      # build/vecnist.bin, checked against Vide's own assembler if Vide is installed
./run.sh        # play it in MAME   (./run.sh --video vecnist.mp4 records the demo)

The folder is also a Vide project (VecNISTProjectProperty.xml). Link it into Vide’s projects folder and assemble it there; the bytes are the same as lwasm’s. To retrain, run ./get_mnist.sh and then python3 train/vecnist.py train (about 40 seconds on a PC).