Просмотр исходного кода

Add Power C skill and VICE disk-automation notes

- skills/powerc: K&R dialect limits, shell/editor, cc/link pipeline, library, ML interface
- vice-emulator skill: keybuf rules, warp, c1541 PETSCII source files, Power C workflow
- examples: powerc-ced.bat, powerc-build.bat

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
main
Daniel Covington 1 неделю назад
Родитель
Сommit
559f491744
5 измененных файлов: 318 добавлений и 0 удалений
  1. +1
    -0
      AGENTS.md
  2. +8
    -0
      examples/powerc-build.bat
  3. +14
    -0
      examples/powerc-ced.bat
  4. +227
    -0
      skills/powerc/SKILL.md
  5. +68
    -0
      skills/vice-emulator/SKILL.md

+ 1
- 0
AGENTS.md Просмотреть файл

@@ -25,6 +25,7 @@ This repository contains structured skills and reference material for developing
| `skills/interrupts/` | IRQ, NMI, CIA timers, raster interrupts | Interrupt-driven code, timing | | `skills/interrupts/` | IRQ, NMI, CIA timers, raster interrupts | Interrupt-driven code, timing |
| `skills/compiler-design/` | Compiler & assembler construction for C64/128 | Writing compilers, assemblers, parsers | | `skills/compiler-design/` | Compiler & assembler construction for C64/128 | Writing compilers, assemblers, parsers |
| `skills/vice-emulator/` | VICE emulator, autostart, monitor, snapshots, automation | Running, testing, and debugging C64 software in VICE | | `skills/vice-emulator/` | VICE emulator, autostart, monitor, snapshots, automation | Running, testing, and debugging C64 software in VICE |
| `skills/powerc/` | Power C compiler on the C64 | Writing, compiling, linking, and running C programs (reference/POWERc.d81) |


### Reference Files ### Reference Files




+ 8
- 0
examples/powerc-build.bat Просмотреть файл

@@ -0,0 +1,8 @@
@echo off
setlocal
REM Usage: powerc-build.bat "shell commands" (use \n for RETURN)
set "VICE_EXE=C:\Program Files\GTK3VICE-3.10-win64\bin\x64sc.exe"
set "D81=%~dp0powerc-work.d81"
set "CMDS=%~1"
if "%CMDS%"=="" set "CMDS=cc squares\n"
"%VICE_EXE%" -8 "%D81%" -autostart "%D81%:shell" -autostart-warp -warp -keybuf "%CMDS%"

+ 14
- 0
examples/powerc-ced.bat Просмотреть файл

@@ -0,0 +1,14 @@
@echo off
setlocal

set "VICE_EXE=C:\Program Files\GTK3VICE-3.10-win64\bin\x64sc.exe"
set "D81=%~dp0..\reference\POWERc.d81"

if not exist "%VICE_EXE%" (
echo x64sc.exe not found at "%VICE_EXE%"
exit /b 1
)

REM Mount POWERc.d81 in drive 8, autostart "shell", then type "ced" at the shell prompt.
REM -keybuf is fed after autostart completes; \n = RETURN (\r is typed literally as "r").
"%VICE_EXE%" -8 "%D81%" -autostart "%D81%:shell" -autostart-warp -keybuf "ced\n"

+ 227
- 0
skills/powerc/SKILL.md Просмотреть файл

@@ -0,0 +1,227 @@
---
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.

```c
#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 with `sys(bank, address, &a, &x, &y)` (the manual's example
uses bank 15); A/X/Y are loaded from the pointers and written back afterwards;
it returns the carry flag. Example:
`while (*s++) sys(15, 0xffd2, s, &x, &y);` prints via KERNAL 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

```bat
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.

+ 68
- 0
skills/vice-emulator/SKILL.md Просмотреть файл

@@ -363,3 +363,71 @@ For this repository:
5. Stepping without choosing between `step`, `next`, and `return` can waste a lot of time in KERNAL code 5. Stepping without choosing between `step`, `next`, and `return` can waste a lot of time in KERNAL code
6. Forgetting `device 8:` vs `device c:` can make you debug the wrong CPU when true drive emulation is involved 6. Forgetting `device 8:` vs `device c:` can make you debug the wrong CPU when true drive emulation is involved
7. Snapshots are convenient, but the manual warns against treating them as stable long-term artifacts 7. Snapshots are convenient, but the manual warns against treating them as stable long-term artifacts

---

## Automating Disk-Based Tools (Power C example)

Learned while driving Power C (`reference/POWERc.d81`) end to end: write source, compile, link, run. Scripts: `examples/powerc-ced.bat`, `examples/powerc-build.bat`. Manual: `reference/Power_C_Instruction_Manual.pdf`.

### Mounting and autostarting a disk

```bat
x64sc.exe -8 "disk.d81" -autostart "disk.d81:shell" -autostart-warp -warp -keybuf "ced\n"
```

- `-8 <img>` mounts in drive 8; `-autostart "<img>:<prgname>"` loads and runs a named file from the image.
- `-autostart-warp` only lasts until autostart finishes. Add `-warp` to stay in warp for slow compile/link steps (about 14x, shown as ~1400% cpu in the status bar).
- Run a built program with `-autostart "work.d81:squares"`.

### `-keybuf` rules

- `\n` is RETURN. `\r` is typed as a literal `r` (you get `cedr`).
- `^` produces the C64 up-arrow character (PETSCII `$5E`), needed by the Power C linker.
- Keybuf is fed after autostart completes, so it works for the first shell command and for follow-up input queued in the same string (e.g. linker prompts).
- Pass the string as one quoted argument. From PowerShell use `Start-Process cmd -ArgumentList '/c',$bat,'"link\nfoo.o\n"'`; nested quoting through `cmd //c` from bash silently failed to launch.
- Do not edit these strings with `sed` (`\n` becomes a real newline); rewrite the file instead.

### Do not type into the window with SendKeys

`SendKeys` to the VICE window drops and repeats characters (`link squares` became `lk quaes`), especially in warp. Use `-keybuf` for anything scripted. SendKeys with a 250-400 ms delay per character is only a fallback for answering a prompt that arrives mid-run, such as the final Return or a file name.

### Seeing what happened

There is no console output from the emulated machine. Capture the VICE window with a PowerShell `CopyFromScreen` of its `GetWindowRect`, then read the PNG. Sleep long enough first (compile about 60 s at 100%, much less in warp).

### Do not modify the reference image

Copy it first (`cp reference/POWERc.d81 examples/powerc-work.d81`). Writes made inside VICE persist in the `.d81`.

### Putting a source file on the disk without the editor

`ced` is an interactive full-screen editor; scripting it through keybuf is fragile. Instead write the file with `c1541` as a SEQ file in the format Power C expects:

- PETSCII, CR (`$0D`) line endings.
- ASCII `a-z` -> `$41-$5A`, ASCII `A-Z` -> `$C1-$DA`, `{` -> `$DB`, `}` -> `$DD`.
- `c1541 work.d81 -write src.c "squares.c,s"`. Read existing files back with `-read "hello.c,s" out`.

### Power C workflow (C64, single drive)

1. `cc squares.c` - the full name with `.c` is required (`cc squares` gives "not a C source file"). Produces `squares.o`. The compiler asks "insert compiler disk / object disk"; with one image just press RETURN.
2. `link -s` - `-s` links to run from BASIC (no `-s` makes a Shell program, name must end in `.sh`). `link` takes no filename argument.
3. Linker prompts `>`: enter `squares.o`, then `^` (up arrow) to pull in the libraries (`stdlib.l`, `syslib.l`, which are on the same d81), then an empty RETURN to finish. Then answer `output file name:` with `squares`.
4. The linker fails with "63, file exists" if the output name already exists. Scratch it first: `c1541 work.d81 -delete squares`.
5. Unresolved references such as `printf` or `c$start` mean the `^` library step was skipped.
6. Run it: `-autostart "work.d81:squares"`, or `bye` in the Shell, then `load"squares",8` and `run`.

One-shot build (after deleting any old output):

```bat
powerc-build.bat "link -s\nsquares.o\n^\n\nsquares\n"
```

Compile step: `powerc-build.bat "cc squares.c\n"` (then press RETURN at the disk prompts).

### Power C quirks worth remembering

- No bit fields; static pointers can only be initialised with strings.
- `int`, `short`, `long` are all 2 bytes; `float` is 5 bytes (BASIC format); identifiers are significant to 8 characters.
- Standard headers (`stdio.h`) must be on the same disk as the source.
- Shell commands: `l` (list work disk), `ls` (system disk), `rm`, `mv`, `pr`, `disk`, `work`, `bye`; `ed`/`ced` editors, `cc`, `link`, `trim`.

Загрузка…
Отмена
Сохранить

Powered by TurnKey Linux.