Preface#

Old good times - when most user manuals were about programming - first Basic, then Assembly. So to use your machine, you would need to be a programmer to some extent.

When I was a kid, I wanted to write in Assembly; however, making progress was hard - I never mastered it to the level I wanted. Maybe because I didn’t have Assembly Language For Kids: Commodore 64 by William Sanders xD.

Assembly Language For Kids: Commodore 64

But now I want to go back to programming for my beloved C64, yeah nostalgia :D. So the basic options on the table are BASIC and Assembly for 6502. Programming in assembly would take time to master. I played with it a bit but decided to try something else.

BASIC, my first language, is slow and won’t meet my requirements for why I started this journey.

And then I discovered cc65 and because C was my third language (Do you remember #firstseven languages, by the way? ;), I decided to give it a try, expecting satisfying program execution speed, fluency in the language, and still having access to the hardware level.

Introduction#

Our goal is to write a simple program that will run on the Commodore 64 and display the classic “Hello, World!” message on the screen. To achieve this, we will utilize the cc65 package, a versatile compiler suite designed specifically for developing software for the Commodore 64.

So, let’s get started and embark on this exciting journey into the world of retro programming on the Commodore 64!

Preparation#

First, you should set up the cc65 environment for your machine (and yes, you can use a machine of your preference: Mac, Linux, and Windows).

If you prefer the console approach, use the following command for Mac:

brew install cc65

For Ubuntu, use the following command:

sudo apt install cc65

And for Windows, use the following command:

choco install cc65-compiler

You can also install it manually or even build the cc65 compiler from source, depending on your preference. See the Getting started with cc65 documentation for more information.

Once everything is set up, you can check the version of cc65 by running the following command:

cc65 --version

You will also need an emulator to see the results on your machine, which will make development easier. I personally prefer using Vice, which is available for the aforementioned systems. You can refer to the documentation or website of Vice to learn how to install it on your machine. For Mac users, it is available via the brew command. Don’t hesitate to explore similar tools for Linux and Windows as well. And, someday, we will run this on a real C64! :D

Let’s cook something#

So let’s write our first program, classic Hello World!

You can use Notepad (on Windows) or TextEdit (on Mac) to write code, just for the sake of simplicity. For Linux, try ViM. ;) I know some of you might miss syntax coloring, but it’s good enough for our purpose at the moment. We will shift to VS Code in the near future.

Here is the code:

#include <stdio.h>

void main(void)
{
    printf("Hello, world!\n");
    return 0;
}

As you can see, there is no difference from the classic “Hello, World!” program in The C Programming Language written by Brian W. Kernighan and Dennis M. Ritchie.

As you probably expect, it will print the Hello, world text on the Commodore screen. Save this program in any text editor, and we are ready to compile it with cc65.

cc65 hello.c

As a result, you should get a hello.s file with content similar to this. It may not seem like our program for the Commodore, but surprisingly, it is human-readable.

;
; File generated by cc65 v 2.18 - Git 037a806
;
    .fopt       compiler,"cc65 v 2.18 - Git 037a806"
    .setcpu     "6502"
    .smart      on
    .autoimport on
    .case       on
    .debuginfo  off
    .importzp   sp, sreg, regsave, regbank
    .importzp   tmp1, tmp2, tmp3, tmp4, ptr1, ptr2, ptr3, ptr4
    .macpack    longbranch
    .forceimport    __STARTUP__
    .import     _printf
    .export     _main

.segment    "RODATA"

S0001:
    .byte   $48,$65,$6C,$6C,$6F,$2C,$20,$77,$6F,$72,$6C,$64,$21,$0A,$00

; ---------------------------------------------------------------
; void __near__ main (void)
; ---------------------------------------------------------------

.segment    "CODE"

.proc   _main: near

.segment    "CODE"

    lda     #<(S0001)
    ldx     #>(S0001)
    jsr     pushax
    ldy     #$02
    jsr     _printf
    rts

.endproc

Some of you may recognize this assembly code, which can be used for creating machine code for the C64. This file requires further preprocessing, but if you would like to see how the generated assembly looks for further inspection, you know how to generate it.

The whole process requires more steps and is a bit complex, especially for those without a C and C++ background. You can refer to the article Translation phases if you’d like to dive deeper into it.

Fortunately, there’s a command that simplifies the entire process called “cl65”. Let’s use it:

cl65 -t c64 hello.c

Finally, we have our long-awaited executable program for the Commodore 64 (file name: hello)! It’s worth mentioning that cc65 is capable of preparing code for many 8-bit machines based on the 6502 processor, so the “-t c64” option is not included here by accident. You can find the full list of supported machines in the Overview article.

The last step is to run our program. Let’s use VICE:

x64sc hello

The program will be automatically loaded and run.

And voila! We have our first running program on the C64! :D

Assembly Language For Kids: Commodore 64

Summary#

We have our development environment ready, we managed to prepare our first program for C64 and run it. I would say that’s quite a lot :D

What we could do next:

  • We will write more simple code and explore the basics of cc65. This time, we’ll start using Visual Studio Code to improve our development experience.
  • We can try running our programs on a C64 built with the Ultimate64 motherboard, which provides hardware emulation of the C64. If you’re interested in the hardware, check out the page about Ultimate64 for more information.
  • We attempt to create a floppy disk and try running our program on a real Commodore 64. Fortunately, I recently acquired a working C64 with a 1541-II drive, so it should bring even more fun to the experience.

Stay retro, stay inspired!

PS: If you want to see my Commodore 64 build using the Ultimate64 motherboard, check out this tweet.

Feel free to get in touch with me through Programmer’s Log, and please share the feedback as well.