Commodore 64 Puzzle

My college professor posted this image with the question

What is the output when enter is pressed?

Commodore 64 screen with a BASIC program

I recognized this as a Commodore 64 and decided to dive deeper into what happens when SYS 49152 is run.

Some Basics

PEEK(<address>) is used to look at the memory for the specified address.

POKE <address>,<value> writes the value to the specified address.

The Main Program

We can start by loading the program into a Commodore 64 Emulator.

10 X=49152
15 PRINT X
20 Y=11
30 FOR M=0 TO Y
40 PRINT PEEK(X+M);
50 PRINT " ";
60 NEXT M
Commodore 64 screen with bad output from the main program

The output doesn't match the output from the original picture. According to the C64 wiki, the 49152 address is the location of the MONITOR$C000. So the BASIC program is printing the bytes of the machine code program located in MONITOR$C000.

Matching the Contents

We can attempt to match the contents of the 49152-49164 memory block by manually poking bytes into memory.

10 POKE 49152,169
11 POKE 49153,83
12 POKE 49154,141
13 POKE 49155,244
14 POKE 49156,5
15 POKE 49157,169
16 POKE 49158,2
17 POKE 49159,141
18 POKE 49160,244
19 POKE 49161,217
20 POKE 49162,96
21 POKE 49163,0
Commodore 64 screen with matching output from the original program

Success?

Now when running SYS 49152 we get a nice red heart.

Commodore 64 screen with a red heart in the middle of the screen

But Why?

How does 169 83 141 244 5 169 2 141 244 217 96 0 result in a red heart on the screen?

The bytes are machine code for the Commodore 64. So we can look up the opcodes to convert them to assembly.

Decoding

Converting the bytes into hex:

A9 53 8D F4 05 A9 02 8D F4 D9 60 00

Using the Opcode lookup table we can decode the bytes:

  • A9: LDA #nn (LoaD Accumulator)
  • 53(83 dec): Value loaded into the accumulator
  • 8D: STA nnnn (STore Accumulator)
  • 05F4(1524 dec): Address to store the value from the accumulator
  • A9: LDA #nn
  • 02(2 dec): Value loaded into the accumulator
  • 8D: STA nnnn
  • D9F4(55796 dec): Address to store the value from the accumulator
  • 60: RTS (ReTurn from Subroutine)

Here is the full assembly code:

LDA #53
STA 05F4
LDA #02
STA D9F4
RTS

If we convert this to a BASIC program it would be:

10 POKE 1524,83
20 POKE 55796,2

What is it doing?

So we have figured out that the machine code is writing two values to two different memory addresses.

POKE 1524,83

The 1524 address is used by the C64 for Screen RAM allowing you to write characters directly to the screen. The value 83 is the character code for the heart in the C64's character set.

POKE 55796,2

The 55796 address is used to specify the color of the character on the screen using Color RAM. The value 2 is red on the color lookup table.

For more information on the C64's memory map you can look here.

Having Some Fun

Now that we understand how this works we can write our own colorful characters to the screen.

Commodore 64 screen with a red heart, a teal heart, and a green spade