Commit Graph
9 Commits
Author SHA1 Message Date
Stefan Arentz 75bce7aec8 --tty-telnet: proactive echo negotiation (fix telnet double-echo) (#305) 2026-07-19 19:57:11 -04:00
Stefan ArentzandClaude Fable 5 25f59cc451 scripts/systemd/README.md: the telnet Apple 1 build & setup guide (#304)
The first real deployment surfaced everything a header comment
couldn't hold: SDL's Linux build dependencies (and the XTEST error a
partial set produces), the stale-CMake-cache gotcha after a failed
configure (cargo clean -p sdl3-sys), what sdl-static-headless actually
builds and its --tty-only caveat, the install paths the units expect,
how to watch sessions (systemctl list-units / journalctl), operating
knobs (machine, port, limits, banner), the security posture, and a
troubleshooting section written from the actual failures.

The guide lives next to the units as scripts/systemd/README.md; the
socket header shrinks to a pointer (one source of truth), and the main
README's Experimental bullet and notes/APPLE1.md link to it.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 18:33:23 -04:00
Stefan ArentzandClaude Fable 5 f28879bf7f sdl-static-headless: the telnet server build, plus the install checklist (#303)
Deploying the telnet Apple 1 hit two gaps. First, the default build
links SDL3 dynamically and sdl-static compiles SDL with full video —
which demands X11 dev packages (XTEST et al) that a headless server
neither has nor needs. The new sdl-static-headless feature stacks
sdl3's build-from-source-unix-console on sdl-static: a static SDL
console build with no X11/Wayland at all. Only --tty runs on such a
binary (documented); it builds in a fraction of the time and links no
dynamic SDL.

Second, ewm-one.socket's header said "install both units" without
saying how much more there is: it now carries the full checklist —
the headless build command, binary/banner/unit installs,
daemon-reload, enable, and where the per-instance logs live.

Verified: the headless binary builds, serves a banner + monitor
session over a pipe, and carries no dynamic SDL reference.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 17:31:30 -04:00
Stefan ArentzandClaude Fable 5 60a161ecee --tty-banner: greet telnet visitors with instructions (T3) (#302)
Phase T3 of plans/20260719-04-apple1-telnet.md (added after T2): a
--tty-banner <path> text file prints to the session before the machine
says anything — where the operator puts the instructions a bare Woz
Monitor prompt doesn't offer. Line endings are CRLF-normalized for raw
terminals; a missing file fails loud at startup (a systemd misconfig
should be visible in the journal, not silently banner-less).

The flag is tty-session tooling, not machine description — it lives
with --tty, outside the config document, like the debug flags do.
scripts/systemd/banner.txt ships as the example (monitor and BASIC
starters, the reset chord, how to leave telnet) and the service unit
mounts it from /usr/local/share/ewm — readable under
ProtectSystem=strict.

Test: the banner precedes the machine's prompt, CRLF-normalized, and
the flag without a value falls into usage. Verified live: piped
session shows banner then prompt; a bad path exits 1 with the error.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 17:05:51 -04:00
Stefan ArentzandClaude Fable 5 3e177a8bb6 Telnet negotiation, BREAK reset, systemd units (T2) (#301)
Phase T2, closing plans/20260719-04-apple1-telnet.md.

The tty session gains a hand-rolled RFC 854 subset: a state-machine
filter that stays dormant until the first inbound IAC — nc and local
terminals never see a protocol byte — then announces WILL ECHO + WILL
SGA (character-at-a-time, remote echo), refuses every other
negotiation, swallows subnegotiations, drops IAC IAC (a literal 0xFF
is not an Apple 1 key), and maps BRK/IP — telnet's `send brk`, the
serial-terminal attention — to the RESET button: immediate, flushing
typed-ahead, like the real thing.

scripts/systemd/ carries the inetd-style units: ewm-one.socket
(ListenStream=6502, Accept=yes, MaxConnectionsPerSource) and
ewm-one@.service (StandardInput=socket, DynamicUser, ProtectSystem=
strict, MemoryMax, RuntimeMaxSec) — the sandbox is tight because the
binary needs no filesystem; configs and ROMs are embedded. README's
Experimental section gains the entry; notes/APPLE1.md records the
tty/telnet design as built; the plan is complete.

Tests: the filter unit-tested byte for byte (activation volley, the
no-reply-to-DO-ECHO loop guard, WONT/DONT refusals, subnegotiation
swallowing, BRK, IAC IAC); a session-level test where a staged reader
delivers the volley, enters BASIC, then BREAKs back to the monitor —
staged because BREAK is deliberately out-of-band. Verified live:
piping an IAC volley plus a command through `ewm one --tty` yields
prompt, WILLs, echo, and the dump in one stream.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 17:01:50 -04:00
Stefan ArentzandClaude Fable 5 3bb74324c0 Package EWM as a native Mac application (MAC_APP.md Phase 1)
scripts/make-app.sh assembles dist/EWM.app, a self-contained
double-clickable bundle:

- SDL3 is compiled from source and linked statically (a new sdl-static
  cargo feature; dev/CI builds keep the Homebrew pkg-config path as the
  default feature). Verified: otool -L shows only system frameworks.
- The icon is "][" rendered by the emulator's own Apple ][ character
  generator (examples/icon.rs), green phosphor on a dark bezel, drawn at
  integer scales per icon size and written as PNGs by a hand-rolled
  ~40-line PNG encoder (flate2 as a dev-dependency for the zlib stream);
  iconutil turns the set into EWM.icns at bundle time, so no binary icon
  is committed.
- Info.plist declares CFBundleDocumentTypes for .dsk/.do/.po/.nib/.woz
  and .hdv at Alternate rank, ad-hoc codesign for local use (real
  signing/notarization is Phase 2).

Opening a disk image from the Finder arrives as an SDL drop event, which
also buys drag-and-drop: the boo menu boots the ][+ with a dropped floppy
in drive 1 (or .hdv on slot 7), and dropping a floppy on a running
machine swaps drive 1. The new media module classifies images -- the one
subtlety is .po, which is a floppy at exactly 143,360 bytes and a ProDOS
hard-drive volume when larger.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 23:24:56 -04:00
Stefan ArentzandClaude Fable 5 d05006ec3a Phase 9: remove the C, promote Rust to the root (#199)
* Phase 9: remove the C tree, promote the Rust workspace to the root

Pure git mv / git rm plus the mechanical path fixes:

- Delete src/*.c, src/*.h, src/Makefile, src/CMakeLists.txt, the Lua
  scripts, .travis.yml, and scripts/gen-golden-trace.* (the golden
  trace regeneration needed the C tree; the checked-in golden file is
  now frozen — regenerating requires the C from git history).
- git mv src/rom -> rom and rust/* -> the repo root.
- Fix include_bytes! and test paths for the new layout (src/rom ->
  rom, one directory level less). No other code changes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Phase 9: CI drops the C job; ignore /target

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Phase 9: rewrite README for the Rust build; REWRITE.md complete

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Phase 9: rustfmt after the path shortening

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 11:23:52 -04:00
Stefan ArentzandClaude Fable 5 8c158618d5 Phase 2: 65C02, disassembler, and golden-trace harness (#192)
Completes the CPU core port:

- ins.rs: the 65C02 override handlers ((zp) modes, BRA, STZ, PHX/PHY/
  PLX/PLY, TRB/TSB, RMB/SMB, BBR/BBS, INC/DEC A, BIT imm/zpgx/absx,
  JMP (abs,X)) and the override table transcribed verbatim from
  instructions_65C02 — including its 1-cycle NOPs and the stray 0x03
  opcode fields. The table is overlaid onto the 6502 table once, the
  Rust version of cpu_initialize()'s back-fill. C's arity-cast NOPs
  become explicit nop_byte/nop_word wrappers.
- fmt.rs: cpu_format_state, cpu_format_stack, and the disassembler
  from fmt.c, bugs preserved (0x9c prints JMP; BBR/BBS targets are
  computed from pc+2).
- tests/dormann.rs: dormann_65c02 passes at $24a8 after 65,094,140
  cycles — exactly the C emulator's count.
- Golden-trace harness: scripts/gen-golden-trace.{c,sh} builds a
  capture program against the unmodified C sources and records the
  first 100k instructions of the functional test as normalized
  'PC A X Y SP P' lines; checked in gzipped. trace_compare.rs replays
  it on the Rust core and reports the first divergent instruction
  (currently: zero divergence). flate2 is a dev-dependency only.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 09:16:20 -04:00
Stefan Arentz de9212a47f Script for Burger Time cheat 2017-09-20 18:06:30 -04:00