Since my last post I’ve revisited the CC65 cross compiler which you can use to write C programs on 6502 based systems such as the Commodore 64, Apple II and Atari 8bit.
I had been using CC65 for a few months, sketching out the beginnings of a C64 CRPG but had run into problems managing the memory configuration required for custom graphics. I’d moved onto using CBM PRG Studio and programming in 6502 assembly code which meant my code ran very quick but I was finding was slowing down my development time compared to using C in the past.
Now I’m not much of a programmer in any sense of the word but I probably have the most experience of using the C language overall so I was finding 6502 assembly language time consuming to use and my game development time is very limited and I’m not really trying to do anything fancy technically by the standards of C64 games.
There is a lot of documentation online for CC65 but I was lacking an example of how to do a simple custom character set and use code overlays for swapping code in and out of the C64’s 64K of memory from disk. Most of the famous CRPGs I grew up with such as Ultima and Alternate Reality use this method to make the most of the machine’s limited memory by modern standards. I just couldn’t get this to work and gave up frustrated.
I noticed this week that CC65 had been used to create some of the code in Ultima IV Remastered for the C64. After this I came across a CC65 example online that included both a custom character set and code overlays and worked out how to compile it with a custom linker file. This determines how the memory map for the program is set up and where any external data files or graphic data should go. Once I had this working it was relatively easy to load in my modified character set and recreate my map code in C, display it on the screen and have a player marker move around the example map. I also was able to automate my compilation process with a single key press from within Notepad++ and run the resulting program in the Vice emulator which felt pretty smooth.
The main reason I was originally attracted to CC65 was that I love the idea of using C and being able to then reuse the code on other 6502 based platforms as well as modern PCs and operating systems. CC65 also has special support for some systems including the C64 so that you reference the C64 hardware directly within your C code. As CC65 includes a full assembler in its tool chain, you still have the option of using assembly language within your C program where extra performance is needed and tweaking the generated code. I’ll post more about CC65 in a future post; where to get it and provide a brief example and possibly a video of how to do the things I was struggling with in the hope they help others get started.
Ugh, I hate that they require a new account to comment (and it has ludicrous password requirements)!
Just found your blog thanks to a google image search on Bard’s Tale as I was trying to gather some image data in preparation for a C64 RPG project. I backtracked here and since I too just tried CC65 I wanted to contrast to your experience.
First of all I found there is no information on how to use TGI. Not that it is the best way to go, but I couldn’t even run the sample mandelbrot program because it utilized TGI and it couldn’t find a driver when I put the program onto VICE. I searched the internet for a day and came up with nothing. Fine, I wasn’t going to use TGI for my project anyway so I took the version I wrote in BASIC 2.0 and converted it to work in CC65 (ironically the BASIC version came from converting a C version long ago, but then I made many enhancements). There were quite a few surprises, and direct memory access was really tricky since it really didn’t like me setting pointers to values like 0xD800 (told me that number in both decimal and hex was too large for a constant)!
After a few hours of trying my program worked. Then I was surprised. The simple monochrome text mode program was 19 blocks. The BASIC file was only 7 blocks. My assembled ASM version was only 4 blocks. That’s a lot of bloat. Then I compared speeds. The C version runs 4.2x faster, but given the BASIC version is interpreted and uses only floating point while the C version is compiled and uses only 16b integers, I expected a lot larger speedup. Finally was the headache of getting the compiled program onto VICE. Since I use Linux and not Windows there were no good tools for dealing with .d64 files so the process was a nasty chain of cryptic command lines: cc65, ca65, cl65, rename file as .prg, move to where my emulators can access the file, open dosbox to run Star Commander to insert the .prg into a .d64, open VICE, attach .d64 as #8. I can script the 3-step cc65 process but dealing with other emulators in the flow is a huge headache. Overall I’d give the CC65-on-Linux experience a 2/5. Very disappointing.
Hi Alex, Thanks for your comments. I had to put the registration and capture on for the comments as I was getting thousands of spam comments at one point but I’ll take another look.
Regarding TGI – I just managed to get this working recently but I’ve decided not to use it as it’s only 2 colours and requires a driver that needs to be on a D64 image (at least that’s how I got it working). I can share a disk image if you’re still interested in it.
Part of the reason I like the idea of CC65 is the portability between systems and also that I could also port any code easily to native Windows and Linux projects too. I’ve pretty much abandoned use of the CC65 linker to load binary files into my default program file and just changed to loading them into memory at run time from the D64 image – they are going to be swapped out of memory anyway for different map and graphics files.
I’ve also relocated all of my graphics and character sets to the top 8K of memory starting at E000. This means CC65 can use all the first 50K of memory for code and other data structures as one contiguous space. My .PRG file is currently showing around 15K used. I have thought about moving to pure 6502 several times for simplicity but I think this might slow me down a lot as I find 6502 that bit more complicated. My CC65 project uses some assembly routines for speed though – the routine that prints a wall section to a temporary display buffer is in pure assembly language.
One other complaint I had with coding in CC65 was debuggability. In converting my BASIC program to C I naturally introduced several bugs. In BASIC I can stop execution, print or change values, or GOSUB specific subroutines to try them out on their own. In ASM I know exactly what every instruction is for because I planned it out and wrote it, so I can use a monitor to do what I do in BASIC. But when I tried C what I wrote was converted to ASM that was completely unfamiliar to me making the monitor essentially useless, and as C is not native on C64 I couldn’t do any of my BASIC debugging techniques. Hence it took a few hours to get a small program I’m quite familiar with to work. How are you debugging a large and complex program like your RPG which surely resides in multiple source files and has tons of functions and variables?
I should firstly say that I’m not a professional programmer. I’ve been watching some of Ben Eater’s videos recently about creating a 6502 computer and Javidx9’s NES emulator videos which have both made me think about doing more straight 6502 coding.
https://www.youtube.com/watch?v=LnzuMJLZRdU
https://www.youtube.com/watch?v=F8kx56OZQhg
Assembly language is attractive as you say because you can control every byte, know exactly how you’re using the memory and presumably with sensible use of assembler macros I could address some of the ease of use issues I’ve mentioned.
In terms of debugging I tend to make small changes and test that particular piece of functionality out. I’ve not made a lot of use of debuggers over the years so it’s really something I should get to grips with. Typically I will write values to the screen or to a console window. For the C64 I could use the monitor but what my testing to date this seems more limited in Linux Vice than in Windows Vice. In terms of CC65 I have totally stopped using a custom .CFG file for memory segments – I was constantly having to edit it. I’m now loading data from a .D64 disk image at startup by using some Vice command line flags.