25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

9.7KB


name: powerc description: > Use this skill when writing, compiling, linking, or running C programs with Spinnaker's Power C on the Commodore 64 (reference/POWERc.d81 under VICE). Covers the C dialect limits (K&R style, 2-byte int, 5-byte float, no bit fields), the library, the Shell, the ed/ced editors, the cc/trim/link toolchain, PETSCII source files, calling machine language with sys(), and how to automate the whole build in VICE. Source: Power C Instruction Manual (Spinnaker, 1986); verified in VICE 3.10.

Power C on the Commodore 64

Power C is a disk-based native-code C compiler. Everything runs from a Shell ($ prompt) on the disk image reference/POWERc.d81. For emulator mechanics (keybuf, warp, screenshots) load skills/vice-emulator/SKILL.md; this skill is the C side.

Language: what to write

Power C is K&R C, not ANSI C. Write code that way or it will not compile.

#include <stdio.h>

main()
{
    int i;
    for (i = 1; i <= 5; i++)
        printf("%d squared is %d\n", i, i * i);
}
  • K&R function definitions: parameter types go after the parameter list (add3(a, b, c) int a, b, c; { ... }). No prototypes, no void.
  • Functions returning anything other than int must be declared in the calling file (char *malloc(); float atof();).
  • Type sizes: char 1, short/int/long/unsigned/pointer 2, float/double 5 (BASIC float format). short, int, long are synonyms; so are float and double.
  • Integers are stored low byte first. Chars are not sign-extended; >> does not sign-fill (vacated bits are always 0).
  • Identifiers are significant to 8 characters (goto labels to 7).
  • Not supported: bit fields (use shifts and masks), static pointer initialisers other than strings (static char *s = "x"; is fine, static int *p = &x; is not), multi-character constants (only the first char is used).
  • Conditional operator does not unify operand types: cast explicitly (x = a == b ? f : (float) i;).
  • ||, ?:, = and , inside subscripts/constant expressions need parentheses: a[(i > j ? i : j)].
  • String constants are limited to 255 characters.
  • register is ignored; the first 32 bytes of a function's ints/chars/pointers live in zero page, so declare hot variables first.
  • Use unsigned for values that are never negative (especially array indices); it is faster.
  • #include <x> and #include "x" are identical, and the header must be on the same disk as the source (copy stdio.h, math.h etc. to your work disk).
  • Large sources can overflow the compiler: split into several .c files, compile each, and give all the .o files to the linker.
  • Keyboard EOF is a . on an otherwise blank line.

Typing special characters (real C64 keyboard / in ced)

Char Keys
{ } Shift++, Shift+-
\ | English pound key |
~ Logo+P
_ Logo+@
\| Logo+*

Source file format on disk

Source files are SEQ files in PETSCII with CR line endings. When writing them from the host (e.g. with c1541 -write), convert:

  • ASCII a-z -> $41-$5A, ASCII A-Z -> $C1-$DA
  • { -> $DB, } -> $DD
  • newline -> $0D
c1541 work.d81 -write src.c "squares.c,s"
c1541 work.d81 -read "hello.c,s" out.c      # inspect an existing source

Filenames end in .c; compiler output ends in .o; Shell programs end in .sh.

The Shell (C64)

Run it with load"*",8 + run (or autostart shell). Prompt is $.

Command Meaning
bye exit to BASIC
l [pat] / ls [pat] list work disk / system disk
rm file scratch a file on the work disk
mv a b rename
pr file / pr >> file list a file to screen / to printer (device 4)
disk cmd send a DOS command (disk n0:name,id formats)
work [dev drive] show or set the work disk
load cmd load a command without running it
ed [file], ced [file] editor / syntax-checking editor
cc [-p] file.c compile
trim file.o optimise the object file (3-8% smaller)
link [-s [addr]] link

Programs named X.sh run under the Shell by typing X plus arguments; stdin/stdout can be redirected to disk files like UNIX. Included utilities: sort [-n], find [-x] [-n] [-f] pattern [files], wfreq, format, print, trim.

Editor (ed / ced)

ced = ed plus a CHeck command that checks C syntax. Start it with ced file.c.

Edit mode: cursor keys move; F1/F2 page down/up; F3/F4 search down/up; F5 cut (Shift+Run/Stop starts select mode, cursor keys set the range, Return accepts); F6 paste; F7/F8 end/start of line; Clr/Home bottom of buffer; Shift+Clr/Home top; Shift+Return opens a line; Run/Stop enters command mode.

Command mode: dir, disk cmd, GEt file, PUt file, PRint, GOto buf, List, CHeck (ced only), QUIT, CLEAR [buf], /str<F3> (search), /dog/cat<F3> (replace next), /dog/cat/<F3> (replace all). Return goes back to edit mode.

Saving: Run/Stop, then PUt filename.c, Return, then QUIT.

Build pipeline

$ cc squares.c            -> squares.o     (name must end in .c)
$ trim squares.o          (optional)
$ link -s                 (BASIC-runnable)  or  link   (Shell program, name must end .sh)
> squares.o               object file(s), one per line
> ^                       up-arrow: link stdlib.l + syslib.l automatically
>                         empty RETURN = done
output file name: squares
  • cc prompts “insert source/compiler/object disk”: with a single image just press RETURN.
  • link -s with no address links at the start of BASIC, so load"squares",8 + run works. With an address (link -s $c000 or decimal) you must load"x",8,1 and SYS the address.
  • link takes no filename argument; names are entered at the > prompt. x + RETURN aborts.
  • The linker only accepts .o, .obj, .l names. Maths functions need math.l too (>math.l) and #include <math.h>.
  • “unresolved external references” (printf, c$start, ...) = you forgot the ^ library step.
  • “63, file exists” = scratch the old output first (rm squares, or c1541 -delete).
  • The up-arrow key is ^ in VICE -keybuf.

Library quick reference

Link stdlib.l and syslib.l via ^; math.l by name.

  • stdio.h: printf fprintf sprintf scanf fscanf sscanf getchar putchar gets puts fgets fputs getc putc fgetc fputc getw putw fopen freopen fclose fread fwrite feof ferror. EOF is -1, NULL 0, stdin 1, stdout 2; FILE is an int.
  • printf conversions: %d %u %o %x %f %s %c %%, with -, width, .precision, *. Max width 64.
  • scanf conversions: %d %x %o %f %s %c, * suppress, width.
  • fopen modes "r"/"w"; program files "name,p"; replace with "@0:name,p". Always check ferror() after fopen.
  • BASIC-style I/O: open(fileno, device, secaddr, name), close(fileno); use file numbers 5-9 alongside fopen.
  • Strings (#include <strings.h>): strcat strncat strcmp strncmp strcpy strncpy strlen index rindex.
  • Memory: malloc calloc realloc free (declare char *malloc();); bcopy bcmp bzero ffs.
  • Classification: isalpha isupper islower isdigit isalnum isspace ispunct isprint iscntrl isascii.
  • Convert: atoi atof abs fabs. Random: random(), srandom(seed). Sort: qsort(base, n, size, cmp).
  • Control: exit() abort() setjmp longjmp (#include <setjmp.h>), highmem(addr).
  • Directory (#include <dir.h>): opendir readdir rewinddir closedir.
  • Math (#include <math.h>, link math.l): sin cos tan asin acos atan atan2 sinh cosh tanh exp log log10 pow sqrt floor ceil modf frexp ldexp hypot cabs.

Memory and machine-language interface (C64)

  • Compiled programs and the heap/stack end at $D000 by default (highest usable address $CFFF). highmem(0xffff) lets a program use all RAM; call highmem(0xc000) if you place machine code at $C000.
  • Zero page 20-33, 43-74, 253-254 (decimal) are reserved by the system; 34-42, 75-96, 251-252 are scratch and safe for your ML routines.
  • The tape buffer $033C-$03FB is used by the system; do not touch it.
  • Call machine code on the C64 with sys(address, &a, &x, &y) -- no bank argument. The manual's library page shows the C128 form sys(bank, address, ...) (bank 15); used on a C64 it jumps to address 15 and warm-starts the machine (verified in VICE). A/X/Y are loaded from the pointers and written back afterwards; it returns the carry flag. Example: char a, x, y; a = 147; sys(0xffd2, &a, &x, &y); clears the screen via CHROUT.
  • Pass multiple args to an ML routine by declaring one float args; parameter so they stay contiguous, and hand the routine the address of that block in X/Y.

Running and testing under VICE

rem compile
powerc-build.bat "cc squares.c\n"
rem link (delete any old output first: c1541 work.d81 -delete squares)
powerc-build.bat "link -s\nsquares.o\n^\n\nsquares\n"
rem run
x64sc -autostart "work.d81:squares" -autostart-warp

Work on a copy of reference/POWERc.d81 (examples/powerc-work.d81); VICE writes persist. Scripts: examples/powerc-ced.bat, examples/powerc-build.bat. Full emulator details are in skills/vice-emulator/SKILL.md (“Automating Disk-Based Tools”).

Pitfalls checklist

  1. ANSI syntax (prototypes, void, // comments) will fail; use K&R and /* */.
  2. cc needs the .c extension; link needs the ^ step and a fresh output name.
  3. \r in -keybuf types a literal r; use \n.
  4. Headers missing from the work disk give compile errors.
  5. The 8-character identifier limit can make two long names collide.
  6. int is 16-bit and right shifts do not sign-fill; do not rely on sign extension.
  7. Source files are PETSCII, so host text files must be converted before use.

Powered by TurnKey Linux.