Skip to content
Game 0 Unit 18 of 18 1 hr learning time

The Machine Trusts You

The last unit, and the most important. There's no error message, no bounds check, no guard rail — the machine does exactly what you wrote, even when you're wrong. Learn to debug by observing, not by reading errors.

100% of Meet The Machine

Every unit so far ended with something that worked. This one ends with something that's wrong — on purpose — because the single most important thing to learn about this machine is what it does when you are wrong.

What you'll see by the end

The top eight rows of the NES screen filled solid red, far more than one row, on a light-blue field.
Eight rows, not one — the machine filled exactly 255 cells because 255 is the number we wrote; a 'mistake' only because we meant 32.

That was supposed to be one row of 32. It's eight. The machine filled precisely 255 cells — right down to the last one — because 255 is the number we wrote. It is only a "mistake" because we know we meant 32. The machine couldn't know, and didn't ask.

The bug, running

; ============================================================================
; Meet the Machine (NES) - Unit 17: The Machine Trusts You
;
; This one is wrong on purpose. It is the row-fill from Unit 12 with a single
; wrong number: cpx #255 where we meant cpx #32. The machine doesn't object -
; it fills exactly 255 cells, because 255 is the number we wrote.
; ============================================================================

.segment "HEADER"
    .byte "NES", $1a
    .byte 2
    .byte 1
    .byte $00, $00

.segment "CODE"

reset:
    sei
    cld
    ldx #$40
    stx $4017
    ldx #$ff
    txs
    inx
    stx $2000
    stx $2001
    stx $4010
warm1:
    bit $2002
    bpl warm1
warm2:
    bit $2002
    bpl warm2

    bit $2002
    lda #$3f
    sta $2006
    lda #$00
    sta $2006
    lda #$21                ; backdrop light blue
    sta $2007
    lda #$16                ; colour 1 red
    sta $2007

    bit $2002
    lda #$20
    sta $2006
    lda #$00
    sta $2006

    ldx #0
fill:
    lda #$01
    sta $2007
    inx
    cpx #255                ; BUG: we meant 32 (one row)
    bne fill

    bit $2002
    lda #$00
    sta $2006
    sta $2006
    sta $2005
    sta $2005
    lda #$1e
    sta $2001

forever:
    jmp forever

nmi:
    rti
irq:
    rti

.segment "VECTORS"
    .word nmi
    .word reset
    .word irq

.segment "CHARS"
    .byte $00,$00,$00,$00,$00,$00,$00,$00
    .byte $00,$00,$00,$00,$00,$00,$00,$00
    .byte $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff
    .byte $00,$00,$00,$00,$00,$00,$00,$00
    .res 8192 - 32, $00

This is the row-fill from The Counted Loop with one wrong number: cpx #255 where we meant cpx #32. It assembled without a murmur — a wrong count is not a wrong spelling, so the assembler had nothing to object to. Then it ran exactly as written, pouring 255 blocks across eight rows.

There is no safety net

In BASIC, mistakes were met with a friendly stop: ?SYNTAX ERROR, ?ILLEGAL QUANTITY, ?OUT OF MEMORY. The language watched over you and halted when something looked off.

The bare machine does none of that. There is no bounds check, no type check, no "are you sure," no error at all. Write past where you meant to, point at the wrong address, leave a jsr without its rts, forget the clc before an add — and the 6502 does exactly what the bytes say and carries straight on, overwriting whatever it touches, never pausing to warn you. The machine trusts you completely. That trust is the freedom that let you draw the screen, drive the heartbeat, and read the pad with nothing but stores and loads — and the responsibility that means every byte is yours to get right.

So debugging here is a different craft. It is not reading an error message, because there isn't one. It is observing the state — the register view, the memory view, the stack you watched in Call, Return, and a Stack — and reasoning about what the machine did versus what you meant. Every view you've leaned on through this Primer was you learning to debug by looking. That's the discipline the whole course rests on.

Assemble and run

ca65 oops.asm -o oops.o && ld65 -C nes.cfg oops.o -o oops.nes

Eight rows of red blocks where you wanted one — and not a word of complaint.

Try this: it was never broken — your number was

Change cpx #255 to cpx #32. One clean row. Nothing about the machine changed; only your number did. That's the whole lesson in one edit: the machine was doing its job perfectly the entire time.

Try this: break it a different way

Change the tile load lda #$01 to lda #$00 (the blank tile) and run the buggy 255 version again. Now eight rows fill with nothing visible — the same faithful execution of a different wrong intention, writing blank tiles exactly where you said. Predict what you'll see before you run it, then confirm. Again: no error, just the wrong thing done exactly.

What you've learnt

The machine has no safety net: it does exactly what you wrote, even when you're wrong, and never warns you — so you debug by observing the state, not by reading errors.

What's next — you've met the machine

That's the Primer. Look back at what stopped being magic: the build-and-link loop; the three registers; bytes with no type; the short street of memory; the screen behind the PPU window, its colour in a palette, its shapes in CHR; decisions built from test-and-branch; the NMI heartbeat; reading the joypad; the sliding index; counted loops; subroutines and the stack; arithmetic and the carry it makes you mind; setting and clearing bits; numbers bigger than a byte; the APU answering back with a tone — and now the mindset that ties it together.

You haven't built a game yet — that's the point. You've built the understanding a game needs. Next comes Dash, your first complete NES game, where this all turns into something you play — and where the two things we deliberately left open get solved: reading the whole controller at once (The Joypad in Your Hand), and the movable pointer that writes through an address you compute (Bigger Than a Byte), each resolved exactly when the game needs it.

And notice what carried you here: the chip is the same 6502 the C64 runs, so half of this Primer was the same lessons in a new setting. What was genuinely new — the PPU window, the palette, CHR, the NMI heartbeat, the controller's conveyor belt — was the console around the chip. That's the shape of every new machine you'll ever meet: a familiar processor, wrapped in hardware with its own personality. Go and write something the NES will trust you to get right.