Monday, 18 January 2016

Developing for C64

This is an idiot's guide for developing C64 software on Linux. (That idiot is me.) I need these instructions each time I get a new linux computer in which I want to install the development software.

This means that using a compiler within a PC/Linux environment, the code is tested on a C64-emulator and then transferred to a real machine. cc65 is the compiler and I'll go through how it has been set up.

Why not assembler/machine code? Although using C is quite problematic for C64, it is handy for planning and testing ideas. The program can be first written in C which is easier to grasp, then later the code can be changed into in-line assembler (supported by cc65) and further optimized.

Installing the cc65 cross-compiler

It's a bit depressing that the first step in coding for c64 is to compile the cc65 compiler for your system. But it's not a big deal.

It's possible to download the cc65 packages and compile them, but Subversion also works here. (for example sudo apt-get install subversion)

Then copy the SVN-link from and svn checkout [link].

Edit: Just get the, extract it and continue.

Then make. (If for some reason there's no such command then sudo apt-get install make it is)

After the binaries have been created, the commands only work from the folder they are in. A simplistic solution: go to the directory with the compilers (ar65 ca65 cc65 and so on) and copy the compiler binaries to "bin" folder, for example sudo cp * /bin. (Might be /etc/bin or something different also.) (Edit: usr/local/bin should do.) Check the file permissions too, chmod +x filename.

Now command cc65 ought to bring a response "cc65: No input files" even when not in the folder where the binaries are.

So far, so good...
The additional include files go to the include folder under the cc65-master folder. This is also where the usual stdio.h, string.h etc. are found.

Setting the C64 emulator

You need a C64-emulator for running the code, and Vice emulator is the most comprehensive and also the most universally available.

sudo apt-get install vice.

Note that the Vice will need ROMs and Kernal files and ROMs for the Floppy Drives too (1541). You can download a different Vice package that contains the files and copy them to the respective directories. If you only want to code for C64 you can copy just that one directory contents.

After a successful installation


...ought to bring up the emulator window, and x64 programname.prg should run an emulator file in that format.

From Vice, it is wise to disable the "confirm quiting VICE" parameter, disable saving parameters on exit (and then save these parameters manually.)

Which editor for code?

Some kind of text editor is needed for writing the C code. Both Gedit and Kate handle code and matching bracket highlighting well enough and are pretty user-friendly. Komodo Edit has a handy sidebar for easily adjustable direct terminal command sets, but it's not as readily available for all Linux distributions.

If you decide on Kate, then it's possible you have to fix the kdelibs too and install the oxygen icon theme.

sudo apt-get install kate
sudo apt-get install -y kdelibs-bin kdelibs5-data kdelibs5-plugins
sudo apt-get install oxygen-icon-theme

You need to Settings/Configure Kate and display the build plugin in "plugins". Display the Build Output at the bottom of the editor window and insert "make run" for the default target. From now on the Build Default Target will run the project, and the menu can be assigned a key shortcut such as CTRL+R.

The main thing is that you get whatever editor to do the compilation with a simple keypress, otherwise it becomes a chore. I use Control-R in Kate, because it is also used in Processing. Especially for a beginner it's useful to have a rapid trial-and-error cycle. Some might vouch for better pre-planning, but they are wrong.

Edit: I've learned to use xed and make from a terminal window, it's nearly as fast. Kate just seemed to need more and more effort to work.

Compilation and Makefile

The sources could be compiled with cc65 from the commandline (cc65 test.c and then cl65 test.s) but a Makefile comes in handy. Any text editor can be simply told to employ the "make" command in the project folder.  The Makefile becomes sort of glue between the different programs: whatever compilers and text editors are always invoked in the same way.

The image below shows an example directory tree for locating your c64 sources, in this case two different projects, test and game. Note that the .c files have the same base name as the folders.
Good makefiles can be pretty daunting to do if you're simply interested in doing c64 code. It's also easy to create a makefile that fails to work in someone else's system. I'm hardly an expert so I've tried to keep the makefile simple. I've worked with the one below, ripping off stuff from here and there.

Edit: The indentations need to be real TABs, so copy/pasting from this blog won't work directly :(



# Project basename extracted from the current directory name
PROJ = $(shell basename `pwd`)

# Sources
OBJ = $(PROJ).o

$(PROJ).prg: $(OBJ)
 cl65 $(OBJ) $(LDFLAGS) 
 cp $(PROJ) $(PROJ).prg

%.o: %.c
 cl65 $(CFLAGS) -c $< -o $@ $(LDFLAGS) 

%.o: %.s
 cl65 -c $< -o $@ $(LDFLAGS) 

run:  $(PROJ).prg
 x64 $(PROJ).prg

 -rm *.o $(PROJ) *.prg

As long as the Makefile is positioned in a correctly-named folder with a correctly-named source all should be ok when running make.  make clean will remove all previous compilation outcomes and make run will compile and run the Vice emulator. (x64) These will need to be "teached" to the text editor. In my example I've not included any libraries or linked files so the LDFLAGS is left empty.

Added assembler sources (not inline) can be added to the source line, e.g. if you have sourcea.s and sourceb.s then add sourcea.o sourceb.o after OBJ = $(PROJ).o and so on. (Apparently it's not very simple to have make generally link all sources present.)

So, if I have the following test.c source inside a folder called test, and my Makefile is also there, I can make run and have the emulator run the resulting program. It only turns the border black (using inline assembler) and the background red (using C).

void main()
__asm__("lda #$00");
__asm__("sta $d020");