![]() |
Power C for the Commodore 64(last updated 2023-11-21) |
![]() |
This page is about the Power C compiler for the Commodore 64. It's one of the best high-level languages available for this machine, with an excellent editor, a compiler, and a linker. Although its dialect is K & R (pre-ANSI) C, it's very capable. An assembler is also available, making it even more useful for large projects (see the links to Transactor articles on linking C and assembly). Further down the page, you'll find a collection of add-on utilities I downloaded from Q-Link back in the day. If you have any questions, you can email me (cenbe at protonmail dot com).
The Power C Compiler (D64 images)
Power C Tips 'n' Tricks
Power C and Assembly Language
Power C Downloads
Here are D64 images of the Power C diskettes as distributed. There's also a complete copy of the documentation.
side one
(editor, compiler, linker, headers, object files)
side two
(libraries, more object files)
manual
(from DLH)
Here are some helpful things I've found while using Power C:
Remember to use old-style function declarations; you will get hard-to-find errors otherwise.
Modern function declaration:
int foo (int bar) { // clever code here }
K & R (old-style) function declaration (use for Power C):
int foo (bar) int bar; { // clever code here }
Be careful not to use the same field names in different structures; Power C will confuse them. I recommend using a prefix for each structure field, like this:
struct extMenu { int emRecno; char emFlags; int emFirst; }
In Power C, you can declare a function with no return value (instead of a void return value). However, if you need to reference the address of such a function later, the compiler won't let you. This won't work:
dispatch() { /* some code here */ } widget->wAction = &dispatch;But it will if you just change the function declaration to return
int
.The editor's multiple buffer support can be very useful. If you're working on a large source file and want to print just part of it for study, select the region, then delete it and paste it right back again. Then open another buffer (e.g. hit STOP and enter "go print"), paste the region into it, and print it by hitting STOP and entering "pr".
There appears to be a bug in the compiler: on rare occasions it will just hang during a compile and the machine will have to be restarted; the result will be a couple of splat files with names like XXXTEMP. Make sure you validate the drive your source is on if this happens!
Another rarely-seen bug in the compiler is that he sometimes shows a lower-case 'g' on a line by itself at the end of the source when the compile completes, with an "illegal character" message. Ignore it and compile again.
The trim
utility mentioned in the documentation
sounds like a great idea, and I've seen it reduce the size of object
files by 25% or more... but I've also found strange bugs that could
reliably be fixed by recompiling modules without trim
ming
them. My advice is not to use it; find other ways to optimize your
code (like writing some of the program in assembler using
C-ASSM).
For the impatient, here's the recipe for a Power C function in assembler (C-ASSM format) that takes and returns an int:
.ref c$funct_init ;linker will resolve .def funcname ;tell linker our name parmndx = $4b data = $4c c$parms = $033c funcname jsr c$funct_init stx parmndx ;index to parameters lda c$parms,x ;function parameters sta data lda c$parms+1,x sta data+1 ;do something interesting with the int... ldx parmndx lda data sta c$parms,x ;return the int lda data+1 sta c$parms+1,x rtsYou can use the temporary storage areas from $22 - $2a and $4b - $60 in your function.
C-ASSM's expression syntax is unusual compared to that of other Commodore assemblers. For example, say you have a routine to check for numeric characters, and you want to compare to '0' and then to "the character after 9". The code would be:
cmp #'0 bcc notnum cmp #['9+1] bcs notnum ...
You may be tempted to name assembler modules starting with an
underscore... don't. You'll find later on that you
can't put them into a library using the lib
utility!
Symbols starting with underscores (e.g. alternate entry points for
functions that can be called from either C or assembler) are OK,
though: lib
doesn't show them when you display the
contents of a library, but trust me, they're there.
Have you wanted to rewrite some of your C code in assembler
only to end up saying to yourself "but I'll need to call
malloc()
"? Well, you can. Just bypass the call to
c$funct_init
by calling 16 bytes into
malloc
's object code, like this:
.ref c$funct_init ;linker will resolve .ref malloc parmndx = $4b jsr c$funct_init stx parmndx ;index to parameters ;put amount of memory to allocate in memsize before calling lda memsize sta $4c lda memsize+1 sta $4d jsr malloc+16 ldx parmndx lda c$parms,x ora c$parms+1,x beq error ;oops, malloc() returned 0 ;now you can use the memory pointer at c$parms,x memsize .bss 2You can also call
free()
from assembler, by
JSR
ing to free+3
. Just bear in mind that
both routines use the temporary storage area, so you may need to save
your local variables before the call and restore them again
afterward. parmndx
($4b), however, is not disturbed when
calling them in this way. (Hint: there's a reverse assembler in the
download section below.)
And if you really want to go overboard, you could always roll your own malloc (assembler source, C test program). But of course, no one would do such an insane thing.
This is a collection of add-ons for Power C. I used to have them in ARC format, just as I downloaded them from Q-Link in the olden times, but D64 images are much easier to work with. In a few cases, I had hard copies of the original Q-Link download descriptions, and typed them in by hand.
C-Windows by Rubens Abboud (windowing utility that does a custom character set 40 in 64, or 80 columns):
C-ASSM by Mark Rinfret and David Zarling, an assembler (written in C) that creates Power C compatible object files:
D64 image (reverse assembler
source and docs, with everything compiled and linked)
original Q-Link download
description
D64 image of some source code for use with C-ASSM, including keyboard routines, a mouse driver, and a scrolling directory routine
Power C utilities
These were sent to me in early 2013 by a visitor to the site
from Italy, Pasquale Frega. Grazie mille!
This D64 image
contains:
CREF
, a cross-reference utility. Originally written in
1982 by Jeff Taylor for UNIX 4.2 BSD, it was ported to Power C in
1989 by Ben Pedersen.sysaxyc
, a replacement for Power C's sys()
function which allows the caller to set and read the carry flag as
well as the A, X, and Y registers.GRAFPAK (graphics library by Marc Rinfret/Rich Helms):
(also contributed by Pasquale)
C-Power Graphics Library (by David Kesler and David Brown):
This library is based on Mark Rinfret's GRAFPAK
(see
above).
Cmaster (a terminal with Xmodem written by W Mat Waites):
Cmaster was written using serial routines originally published
in the Transactor (February 1989, Volume 9, Issue 3).
Here's the
original article,
"Serial I/O in Power C."
(Note that the date and issue number are misprinted in the page
footers.)
Utilities and replacements for Power C by Adrian Pepper:
This D64 image
(source and docs) includes:
exec
, a "batch file" or scripting utility for the
Power C shell
newshell
, a replacement shell (with "exec" scripts)
Here's something a little more obscure... it's some code I hacked together with help from the guys on the comp.sys.cbm mailing list. It's a machine language routine, meant to be called from a Power C program, that loads and runs a BASIC program.
assembler source (ASCII, Unix-formatted)