Skip to content

0.2.9: persistent drops (--store), headless --type/--screen, Windows port - #27

Merged
crustovsky merged 16 commits into
mainfrom
claude/pacman-install-readme-ru3a2x
Sep 27, 2026
Merged

crustovsky merged 16 commits into
mainfrom
claude/pacman-install-readme-ru3a2x

Conversation

@crustovsky

Copy link
Copy Markdown
Owner

All verified on real hardware today (firmware 1.1.0), from both a Linux and a Windows client.

Persistent image drops

  • --store FOLDER / C64U_STORE: dropped disk images are FTP-uploaded into the folder, mounted by path read-write, and autostarted by the viewer (reset, boot head start, readiness gate, typed LOAD"*",8,1 / RUN). Re-dropping the same name replaces the file. Static release curl keeps FTP.
  • Protocol facts learned: reset zeroes the zero page so the $CC gate alone can pass mid-boot (typed text got wiped); KEYB frames of exactly 10 bytes were lost twice, batches are 8 now.

Headless flags

  • --type TEXT (KEYB over the DMA channel, \n = RETURN) and --screen (40x25 text from machine:readmem $0400): every in-window action now has a one-shot flag for scripts and agents.

Windows port

  • src/compat_win32.c (Winsock, WSAPoll, GetAdaptersAddresses, GetIpNetTable, IcmpSendEcho prime), compat_sock is uintptr_t there; make TARGET=win32 cross-builds with MinGW; release ships c64uv-<tag>-windows-x86_64.zip with SDL3.dll, embedded icon and version block.
  • The ARP prime is an ICMP echo everywhere now: the firmware only learns our MAC from packets it answers, so the datagram fallback never worked.

Also

  • SDL_LoadFile for dropped files, path_base() for both separators: main.c has no POSIX call left.
  • Release workflow: manual tag input to attach packages to an existing release; file names survive a slash in the ref name.
  • tools/mkd64.py writes an autostarting test disk; tools/genicon.py also emits the .ico.
  • Version 0.2.9.

Tests: unit + integration pass; fakeultimate.py gained an FTP stub and a screen route. CI and a full release dry run (linux-static, arch-package, windows) were run on the branch.

🤖 Generated with Claude Code

https://claude.ai/code/session_01MD4jNoeKcKQc8pkZyJTepc


Generated by Claude Code

… path

Dropped disk images normally land in the firmware's temp RAM disk. With
--store (or C64U_STORE) the image is FTP-uploaded into the given folder on
the Ultimate, mounted from there read-write, and autostarted by the viewer:
machine:reset, readiness gate, LOAD"*",8,1 and RUN typed over the DMA
keyboard channel in 10-byte batches. An existing file is never overwritten
(files/<path>:info check). Static release curl keeps FTP now.

tests/fakeultimate.py grows a passive-mode FTP stub (fifth argument,
C64U_FTP_PORT) and a files:info route; integration.sh covers the store
sequence and the name-clash refusal. --verbose logs the Shift state at
drop time to settle whether Wayland reports modifiers during a drag.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MD4jNoeKcKQc8pkZyJTepc
--type TEXT puts text into the KERNAL buffer over the DMA keyboard channel
(\n = RETURN, 10-byte batches), --screen prints the 40x25 text screen from
machine:readmem $0400. Together they close the loop for scripts and agents
driving the machine without a window; the readmem request is shared with
the readiness gate.

Files now load through SDL_LoadFile and dropped paths split on both
separators, so main.c has no POSIX call left: a Windows port is
compat_win32.c plus a build recipe.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MD4jNoeKcKQc8pkZyJTepc
Winsock implementation of compat.h: WSAPoll for the waits, non-blocking
connect + select for the connect timeout (SO_SNDTIMEO does not bound
connect() on Winsock), GetAdaptersAddresses for the interface list with
OnLinkPrefixLength as the mask, GetIpNetTable for the neighbor MAC, one
datagram as the ARP prime. compat_sock is uintptr_t on Windows.

make TARGET=win32 cross-builds c64uv.exe with MinGW as a console app so
the CLI flags keep working; release.yml adds a windows job that ships the
exe with SDL3.dll from the official MinGW package and a static libcurl.
Compiles warning-free; awaiting a run on real hardware.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MD4jNoeKcKQc8pkZyJTepc
genicon.py also wraps the PNG renditions into assets/c64uv.ico; the
TARGET=win32 build compiles assets/c64uv.rc (icon + VERSIONINFO, version
taken from src/main.c) with windres and links it in. SDL picks the exe's
first icon up as the window icon on Windows.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MD4jNoeKcKQc8pkZyJTepc
…it answers

First Windows run on real hardware: stream start returned 404 "Network
Host Resolve Error" with the datagram prime. The Ultimate fills its ARP
table when it replies to us, which a UDP packet to the stream port never
makes it do. Windows now sends an ICMP echo via IcmpSendEcho (no process
spawn); the Linux no-interface fallback pings too instead of sending a
datagram. Protocol fact recorded in CLAUDE.md.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MD4jNoeKcKQc8pkZyJTepc
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MD4jNoeKcKQc8pkZyJTepc
… start

Reset zeroes the zero page, so the $CC readiness gate could pass mid-boot
and the typed LOAD/RUN landed in a keyboard buffer the KERNAL init then
wiped (seen on hardware: reset, READY, nothing typed). Now a 2.5 s head
start precedes the gate, and after typing LOAD the code waits for $CC to
go non-zero (load in progress) before waiting for READY.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MD4jNoeKcKQc8pkZyJTepc
The files:info existence check is gone; FTP STOR overwrites, which is the
wanted behaviour for dropping a fixed image again. Verified on hardware:
upload, path mount, reset with boot head start, typed LOAD/RUN, program
running.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MD4jNoeKcKQc8pkZyJTepc
Typed text in frames of exactly 10 bytes went missing on hardware twice
(the short tail batch arrived, the 10-byte one did not), so dma_type sends
8 per frame. Bump to 0.2.9.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MD4jNoeKcKQc8pkZyJTepc
@crustovsky
crustovsky merged commit e4e4fcb into main Sep 27, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants