Introduction to C64 programming

Before you start, there are a couple of things that we need to get out of the way. In order to learn how to program for the Commodore 64 (or any other old type of computer), you need a couple of things:

Some required prerequisites are as follows:

  • You should know how bits and bytes, binary and hexadecimal representations work. If you don’t, check out the web. It’s huge!
  • You should have an idea how to code, ideally you know some modern programming langauges (C#/Python) etc

The good & the bad

The bad news is that you will be working on an old, slow microprocessor in a programming with absolutely no types, no structures, no object-oriented design. If your program crashes, the computer will freeze and you will manually have to debug using a monitor. No protected mode, direct access to all hardware at any time.

The good news is that you will be working on an old, slow microprocessor in a programming language with absolutely no types, no structures, and no object-oriented design. You will swiflty learn how to access the hardware directly, and finally be able to understand and master almost every single piece of the computer. Not because you have to be exceptionally smart, but rather because the C64 is so easy to understand and work with. As soon as you have grasped the basics, that is. So let’s start with the basics.

The C64: An Overview & let’s get started

The Commodore 64 uses a MOS technologies 8-bit 6502 microprocessor clocked in at 0.985 MHz (PAL version). It has a 16 bit address register allowing for 2^16 = 65535 = $FFFF = 64kb of memory, but actually has a bit more than this when ROM (read-only-memory) is included. The “GPU” (graphics chip) of the C64 is called the Video Interface Chip (VIC), and shares the same RAM/ROM as the C64. This means that the data feeding the signal that the VIC chip is producing is directly accessible by the CPU.

When the computer starts up, the VIC screen points to memory address $0400. When you run a TRSE program, the default memory location for the program is at $800, but the BASIC is overloaded and told to execute your program (starting at $810) instead. Let’s create a TRSE program that changes a byte on the screen:

program MostBasic;
begin
	poke(^$0400,0,1);
	Loop();
end.

“Poke” means “Set byte at memory address”. Poke(^$0400,0,1) therefore translates to “Set the value of memory address $0400+0 to be “1”. Then loop the program ad infinitum. Incidentally, $0400 is the beginning of screen space, and therefore represents the character in the upper-left corner of the screen. Value “1” corresponds to the ROM screen character for “A”.

The VIC addressing is somewhat skewed, since it can only access 16kb of ram. This means that the VIC address space is evenly divided into 4 “banks” on the c64: from $0000-$3FFF, $4000-$7FFF, $8000-$BFFF and finally $C000-$FFFF. When you tell the VIC chip to “use bank 2”, what you are doing is telling it to access and use memory from $8000-$BFFF.