Skip to content

Worked projects

Everything in this section is a program you can assemble and run. Here they are in one place, with what each one is worth reading for — and then two more that are not about the ACE at all.

The ones in this section

ProgramWhereWorth reading for
Hello worldHello worldThe startup stub, and how four lines print
Reading a lineConsolePolling for keys without blocking
A framed signThe screenPositioning characters, and the color byte
The graphics demosThe graphics modesSetting the card's registers yourself
A little fanfareSoundParallel tables, and frequency at build time
Reading the sticksThe keyboard and the sticksActive-low bits, and a mask table
Files both waysFilesThe three pointers, and the carry flag
The clockThe clockTwo-digit printing, and battery-backed bytes
Counting interruptsInterruptsChaining a handler without disturbing the stack
What's fittedWhat's fittedReading the hardware byte and degrading politely
Two banksBanked RAMA window, a latch, and keeping your own note
Machine code from BASICBASIC and machine codePOKE, SYS, PEEK

And the countdown from the cross-development section, which is the one the debugger and the test script work on.

A blinking light

These two are from the KIM add-on, and they are the smallest complete programs in this whole guide: eight LEDs wired to a port, and enough code to make them do something.

They matter here because they are the shape of every hardware program. Nothing is initialized, nothing is printed, nothing is checked. A value is written to an address and a wire changes.

A binary counter

Eighteen bytes.

asm
LED         = $9400             ; the latch the LEDs hang off
DELAY_CS    = 50                ; half a second
CNT         = $36               ; one byte of zero page

Start:
  stz CNT
Loop:
  lda CNT
  sta LED                       ; the whole output stage of the program
  lda #DELAY_CS
  ldx #0
  jsr SysDelay
  inc CNT                       ; wraps $FF → $00 on its own
  bra Loop

The counter is one byte, so it needs no wrap check. SysDelay is doing the timing on the VIA's timer, so the rate does not change if the machine is running at 2 MHz. And there is no exit — a program for a machine with no operating system runs until you reset it.

A KITT scanner

Thirty-eight bytes, fourteen of which are the pattern table.

asm
LED         = $9400
DELAY_CS    = 10                ; a tenth of a second per step

Start:
  ldy #0
Loop:
  lda Table,y
  sta LED
  phy                           ; SysDelay does not promise to keep Y
  lda #DELAY_CS
  ldx #0
  jsr SysDelay
  ply
  iny
  cpy #14                       ; fourteen steps, then around again
  bne Loop
  bra Start

Table:
  .byte $01,$02,$04,$08,$10,$20,$40,$80  ; left to right
  .byte $40,$20,$10,$08,$04,$02          ; and back, without repeating the ends

The whole animation is a table. Fourteen entries rather than sixteen because the two ends should not be lit twice in a row, which is the difference between a sweep and a stutter — and is the sort of thing you only notice with the LEDs in front of you.

Both want eight LEDs on $9400; a row on a breadboard is the traditional answer. The KIM chapter has cards with the bytes laid out for keying in by hand, which is worth doing once.

Where to go next

Take something apart. The ROM's own source is the best-commented 65C02 on this machine, and everything in this section is a call into it — 6502-BIOS.

Write a game. The pieces are all in this section now: a screen you can draw on, sticks you can read, sound, a clock to time with, and a card to save the score on. Start from the program template and steal from these.

Put it on a cartridge. Writing a cartridge, then Onto real hardware. A game that boots when you switch the machine on is a genuinely different feeling from one you load.

Written for BIOS v1.5. Released under the MIT License.