Everything below was verified on this machine (GTK3VICE 3.10, reference/POWERc.d81),
mostly by first getting it wrong. Read this before touching the build or the
keyboard code.
Compile every unit, link, then bye out of the Power C shell, then load and
run from BASIC — all typed into one emulator session from one -keybuf
string:
cc vim.c <RETURN><RETURN><RETURN> ... padding
cc vscreen.c <RETURN><RETURN><RETURN> ... padding
link -s
vim.o
vscreen.o
^ up-arrow: stdlib.l + syslib.l
empty RETURN: done
vim output name
bye
load"vim",8,1
run
.d81. Both hold the whole image
in memory and write it back on exit, so the second one's exit silently erases
what the first wrote. Symptoms: a compile that “produced nothing”, a linker
that “found no object”, a directory that changes between two c1541 -list
calls.Start-Process -Wait (or .NET Process + WaitForExit) so a step cannot
overlap the next.-keybuf-delay is wall-clock milliseconds per keystroke while the machine
runs at warp, so 900 ms per key is plenty for the machine.cc clears the keyboard buffer when it starts, so its three disk-prompt
answers have to arrive after the prompts appear, not before. That is why a
300 ms burst of RETURNs fails: the answers are eaten and cc sits at “insert
object disk” forever. 900 ms plus ~20 spare RETURNs after each cc works.
Spare RETURNs at the shell prompt are harmless.> prompts are line-based and it loads each object before
asking again, so no padding RETURNs may sit between the object names — an
empty line means “end of object list”. ^ is the up-arrow key and pulls in
the libraries; forget it and you get “unresolved external references”
(Main, SYS, MALLOC, ...).-exitscreenshot will not overwrite an existing file, and -limitcycles
is what ends the session (VICE exits with status 1 and prints “cycle limit
reached” — that is normal).image:file autostart argument on a colon, so a full path is ambiguous.Start-Process -ArgumentList joins the array with spaces and quotes
nothing. "-keybuf", "cc vim.c\n" therefore arrived as two arguments and
VICE silently never started (no window, no screenshot). Build the command
line yourself and hand it to System.Diagnostics.ProcessStartInfo.Arguments,
escaping inner " as \" (see build.ps1).\n in a double-quoted string, so
"cc $u.c\n" really is backslash-n — which is what VICE wants.cc name.c → name.o; it prompts for source disk / compiler disk / object
disk. The Shell prompt is $; bye returns to BASIC.link -s with no address links at the start of BASIC: the file begins
01 08, holds 10 SYS 2062, and $080E is a JMP to the C runtime, so
load"name",8,1 + run works.a-z → $41-$5A,
A-Z → $C1-$DA, CRLF → CR, { | } ~ → $DB $DC $DD $DE (ASCII $7B-$7F plus
$60).||. It needs | = LOGO+* = PETSCII $DC, and cc dies
with “*** illegal character” part-way through the file. Use nested ifs.
(&& is fine.)EOF is not declared unless you #include <stdio.h>; test
if (ch < 0) break; instead.void, no // comments, identifiers significant
to 8 characters, int is 16 bits, chars are unsigned and not sign-extended.
Functions returning int need no declaration; declare char *malloc();.peek()/poke() are C128-only — use pointer casts.malloc() (declared char *malloc();) happily gives 19000 bytes. Compiled
programs and the heap end at $D000 by default..c authoritative and .pet derived. In one bad
session the converted PETSCII copy ended up written over the host .c file
(every letter uppercased, CR line endings). It still compiled — the
conversion round-trips — but the source was gone.sys(bank, address, &a, &x, &y) is documented as
int bank; unsigned address; char *aptr, *xptr, *yptr; with bank from 0 to
15 (BASIC 7 style). Calling KERNAL GETIN through it crashed the program;
the crash warm-starts the C64, which clears the screen, so the only evidence
was a blank blue screen and READY..getchar() is line buffered: it echoes through the KERNAL's
screen editor and only hands the characters over after RETURN. Useless for an
editor.$C6 holds how many
characters are queued and they sit from $0277. The KERNAL's IRQ handler
scans the matrix and fills that buffer, so this gets every real press as it
happens, with no line buffering and no echo. Pop by shifting the rest down and
decrementing $C6.$91 at startup. Bit 7 is the RUN/STOP flag and it can already be
set when the program starts; treating that as “Esc” made the editor's first
keypress a phantom and swallowed the filename.-keybuf feeds that same buffer, so a program reading $C6 can be
driven from the command line — but the keys race the program's start: type a
filename and it can be eaten by BASIC before the program runs.$0400, colour RAM $D800 (both directly writable).$D018 = $17 → screen at $0400, character set at $1800 (lower/upper case),
so PETSCII $41-$5A draws as real lowercase and $C1-$DA as uppercase.
Default is $15 (uppercase/graphics at $1000) — restore it on exit.$20-$3F unchanged, $40-$5F minus $40,
$60-$7F minus $20, $A0-$BF minus $40, $C0-$FF minus $80.+ $80. That is the cursor block
and the status row.$00CC = 0 stops the KERNAL cursor blinking over the editor's own cursor.$11 down, $91 up, $1D right, $9D left;
RETURN $0D, DEL $14.-exitscreenshot + -limitcycles gives one png per run; read it directly.READY., evidence gone.
So probe in steps — write a marker to $0400 (p[0] = 2 shows as B) and
end with for (;;) { } instead of going on. Whatever is on screen when it
hangs is the last step that worked.shots\cc-*.png, link.png) and make
the script fail per step (“cc vim.c produced no object”) instead of at the
end, or a compile failure looks like a linker failure.Powered by TurnKey Linux.