How cc65 works

cc65 is command line program. You will write your code in a text editor, and save it. Then you would open a command prompt (terminal) and compile the program by tying in a series of instructions. There are 3 apps we are interested in — cc65 (the compiler), ca65 (the assembler), and ld65 (the linker). I wrote a batch file (compile.bat) to automate the process. (I later added a makefile, which does the same thing… for Linux users).

You should have downloaded cc65 from here

First, you will write your source code in C (with a text editor). cc65 will compile it into 6502 assembly code. Then ca65 will assemble it into an object file. Then ld65 will link your object files (using a configuration file .cfg) into a completed .nes file. All these steps will be written in the batch file, so in the end, you will be double clicking on a .bat file to do all these steps for you. Here is an example.

@echo off
set name="hello"
set path=%path%;..\bin\
set CC65_HOME=..\

cc65 -Oirs %name%.c --add-source
ca65 crt0.s
ca65 %name%.s -g
ld65 -C nrom_32k_vert.cfg -o %name%.nes crt0.o %name%.o nes.lib -Ln labels.txt

del *.o
move /Y labels.txt BUILD\ 
move /Y %name%.s BUILD\ 
move /Y %name%.nes BUILD\

Quick explanation…you would edit the name=”” to match your .c filename. Anywhere there is a %name% it will replace it with the actual filename. Then, it runs the cc65 (compiler) and ca65 (assembler) and ld65 (linker) programs. Then, it deletes object files and moves the output into a BUILD folder. The last line tries to run the final .nes file.

I tried to make this as pain free as possible, so I “#include” all the C source files into one .c file and “.include” or “.incbin” all assembly source files in crt0.s. The only thing you need to change in the .bat file is the “name” of the main .c file (if it changes).

More about cc65…

The 6502 processor that runs the NES is an 8 bit system. It doesn’t have an easy way to access variables larger than 8 bit, so it is preferred to use ‘unsigned char’ for most variables. Addresses are 16 bit, but nearly everything else is processed 8 bit. And, the only math it knows is adding, subtraction, and bit shifting for some multiplication/division (x 2 is the same as << 1).

You may have to write your C code a bit differently, to get it to run smoothly.

1. Most variables should be defined as unsigned char (8 bit, assumed to have a value 0-255).
2. Everything is global (or static local)
3. I also try to avoid/reduce the number of values passed to a function*

*return values are ok, they are passed via registers

The main slowdown for C code is moving things back and forth from the C stack. Local variables and passed variables use the C stack, which can be up to 5x slower than a global variable. The alternative to a function argument is to store the values to temporary global variables, just before the function call. This is the kind of thing that could easily cause bugs, so be very careful.

4. use ++g instead of g++

cc65 doesn’t optimize very well. It uses “inc g” for ++g, but always uses “lda g, clc, adc #1, sta g” for the post-increment (4x longer). So if you want to do this…
z = g++;

you should instead do…
z = g;

5. don’t use anything that requires a heap. malloc() and free(), etc.

Here’s some more suggestions for cc65 coding…


Or… you can just write the code the way you are used to, and worry about optimization if things start to run too slowly.


I’m using a slightly different version of neslib that Shiru originally wrote. There are many different version floating around. Such as this fork…

and you could cut and paste some of the alternate functions (both .c and .s / .sinc code) into the version used on my code, if you want to use them.


I have been putting each project folder directly inside the main cc65 folder. The relative path in the batch file will go up one folder to look for the bin folder holding all the .exe files. If you have problems, you can change the path to the bin folder from relative to an absolute path in the compile.bat file… or perhaps you can put the cc65/bin folder in “environmental variables” so that your system always knows where the cc65 program is.


One thought on “How cc65 works

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s