The original BASIC oneliner Link to heading

There is a simple one-liner in Commodore 64 BASIC that is so well-known that a book has been written about it. The program code is so short that it is used as the title for the book:

10 PRINT CHR$(205.5 + RND(1)); : GOTO 10, A whole book about a single line of code. By ten authors.

When run, the code starts outputting a pseudo-random maze that goes on forever:

Animated screenshot of a maze being built up

This is achieved by repeatedly outputting, at random, either character 205 or character 206 of the standard Commodore 64 character set. It takes up 26 bytes of memory.

The assembler language equivalent Link to heading

I saw a toot on mastodon by @ShaunBebbington with a version of this effect in Commodore 64 assembler language. After a few toots back and forth, I managed to shave some bytes off and ended up with this minimal version:

loop: lda #205
      lsr $d012
      adc #0
      jsr $ffd2
      bne loop

This takes up 12 bytes of memory and runs a bit faster than the original:

Animated screenshot of a similar maze being built up, but much faster

How it works:

  • lda #205 loads the accumulator with the value 205 (LoaD Accumulator)
  • lsr $d012 does a Logical Shift Right of the $d012 address. This address is used by the graphics chip (VIC) and contains the y-position of the rasterbeam that is drawing the screen. By doing a shift right of this 8-bit value, the rightmost bit ‘falls off’ and ends up in the special carry flag (C), which is a 1-bit flag that is set when calculations overflow. We’re hoping here that the rightmost bit of $d012 is enough random-looking, so that C now holds a pseudo-random bit
  • adc #0 adds 0 plus the carry bit (C) to the accumulator (ADd with Carry). The accumulator now has value 205 or 206, depending on the value of the carry bit.
  • jsr $ffd2 does a Jump to SubRoutine to the kernal routine called CHROUT that is hard coded into ROM. It prints out the character corresponding to the value loaded in the accumulator.
  • bne loop jumps back to the beginning. This should really be a jmp loop because we want to jump back always, unconditionally. But, we use Branch when Not Equal here because this takes up 2 bytes in memory while jmp loop takes up 3. Because we know the condition is always true here, we can get away with this optimization here.