June 10, 2019
For the past month, I’ve been spending the odd night experimenting with Power C. In this post, I’m going to provide some background information on what I’m trying to achieve, and introduce Power C.
I want to write a simple, arcade style game for the Commodore 64, and I want to do it using real hardware - no emulators or cross compiling on a PC. Why? Curiosity. The C64 is more than just a gaming console, people did (and still do) use it to write programs, and I want to know what that’s like.
I don’t yet know how to program in 6510 assembly language, and BASIC, while fine for simple tasks, is a clumsy tool for larger programs. So why not PROMAL, Forth, or any of the other great programming languages available for the C64? Well, the main reason is familiarity: I already know C quite well, since it was, in fact, the first programming language I learned, nearly 18 years years ago.
Unlike later home computers, like the Amiga, there aren’t many C compilers avaiable for the C64. The main contenders seem to be Power C by Spinnaker, and Super-C (link to German website) by Abacus. Even though both implement a similar subset of K&R C, they are quite different. Here’s the executive summary:
cp
, rm
, mv
, cc
, etc.Both packages have their strengths and weaknesses. On the one hand, Power C can be challenging to use. On the other hand, despite being well documented and super-easy to use, Super-C doesn’t produce very good object code. To demonstrate this, here’s a little prime number generator, shamelessly cribbed from Rosetta Code, that I built with both compilers:
#include "stdio.h"
unsigned isprime(n)
unsigned n; {
unsigned num;
if (n<2 || !(n&1)) return n==2;
for (num=3; num <= n/num; num += 2) {
if (!(n%num)) return 0;
}
return 1;
}
main() {
unsigned l,u,i,sum;
printf("enter l+u bounds: ");
scanf("%d%d", &l, &u);
sum=0;
for (i=l; i<=u; ++i) {
if (isprime(i) == 1) {
printf("\n%u", i);
++sum;
}
}
printf("\n\nprimes found: %u", sum);
}
The results of building and running this program are shown below. I also show a version cross-compiled with cc65, for comparison. All versions were run on real hardware with lower & upper bounds set to 0 and 5000, respectively.
Compiler | Program size (blocks) | Runtime (seconds) 1 |
---|---|---|
Power C | 15 | 81 |
Super-C | 39 | 139 |
cc65 | 25 | 67 |
As you can see, cc65 produces slightly faster code, while the code produced by Power C is a little smaller. Both cc65 and Power C beat Super-C quite handily.
Despite not being particularly well documented or user-friendly, Power C produces much smaller, faster code than Super-C. In my opinion, compiling C to correct, fast, and efficient machine language is the primary purpose of a C compiler, and that’s why I consider Power C to be the superior package.
Back in the day, Power C was distributed on a double-sided, double density 5 1/4″ floppy disk. Side A contained the tools, like the editor, compiler, and linker, as well as some sample code, with the C standard library and system libraries residing on side B. These days, D64 images of both disk sides, as well as many other useful libraries and utilities for Power C can be downloaded from Glenn Holmer’s website. He’s done a great job collecting material about Power C, including the manual, and some Transactor articles related to the format of Power C object files, and how to produce object files compatible with the Power C linker from an assembler.
In this article I’ve briefly touched on my motivation for wanting a C compiler that works on real C64 hardware. I’ve also introduced the main contenders, and explained my reason for preferring Power C. In the next post, I’ll walk you through the process of building programs using Power C, and how to optimize the experience.
Thanks for making it this far, and cheers.
The runtimes were measured using a stopwatch from the time RET was pressed after entering the upper bound, to the time the final results were printed.↩