From 28d8852bbe335819d2da639a539aa9cdec095e85 Mon Sep 17 00:00:00 2001 From: Scott Duensing Date: Sat, 26 Sep 2026 21:02:41 -0500 Subject: [PATCH] Docs! Getting ready for more platforms. --- AGI-SESSION-HANDOFF.md | 217 ----------------------------------------- 1 file changed, 217 deletions(-) delete mode 100644 AGI-SESSION-HANDOFF.md diff --git a/AGI-SESSION-HANDOFF.md b/AGI-SESSION-HANDOFF.md deleted file mode 100644 index 28bb0c6..0000000 --- a/AGI-SESSION-HANDOFF.md +++ /dev/null @@ -1,217 +0,0 @@ -# AGI port — session handoff - -This document captures the state of the AGI interpreter port as of -2026-05-15. Hand it to a fresh Claude Code session to pick up where -the previous one left off. - -## Project context - -JoeyLib is a unified C game-dev library targeting Apple IIgs (perf -floor / reference), Amiga, Atari ST, MS-DOS. The AGI port is a -from-scratch reimplementation of Sierra's Adventure Game Interpreter -v2 on top of JoeyLib's surface / draw / input APIs. Written from -public AGI format specs only -- NOT derived from ScummVM / NAGI / -Sarien (those are GPL'd; JoeyLib is not). - -Test data: KQ3 v2, locally installed at -`examples/agi/gamedata/kq3/`. The user owns the game and is not -distributing it; gamedata is gitignored. - -## Current phase - -**Phase 1 sub-D** (callback-driven rendering): verified working. -Logic.0 + room 45 init paint KQ3's title screen on every supported -port. Ego sprite (VIEW 0, Graham) draws on top with priority masking, -WASD/arrow keys move him, ESC quits. - -What's next: **Phase 1 sub-E** (input + animation opcodes). The -title screen does not auto-advance because the VM still stubs ~150 -opcodes including `wait`, `set.menu`, `accept.input`, animation -timers, etc. Real KQ3 progression past the title requires implementing -enough of those to let logic.45 complete its intro and call new.room. - -Phase 2 sub-A onward: parser, NPC actors, sound (NTP / PSG). - -## What works (verified) - -- Resource loader (LOGDIR / PICDIR / VIEWDIR / SNDDIR / VOL.x) -- PIC decoder (visual + priority planes, flood fill, vector draw) -- VIEW decoder (cel parse + RLE blit + priority masking + mirror) -- LOGIC VM: 256 vars, 256 flags, 8-deep call stack - - Real handlers: arithmetic (0x00-0x11), OP_IF (0xFF), OP_GOTO - (0xFE), OP_NEW_ROOM (0x12/0x13), OP_LOAD_LOGIC (0x14/0x15), - OP_CALL (0x16/0x17), OP_LOAD_PIC (0x18), OP_DRAW_PIC (0x19), - OP_SHOW_PIC (0x1A), OP_DISCARD_PIC (0x1B), OP_OVERLAY_PIC (0x1C) - - All ~180 other action opcodes are stubs (skip their arg bytes - via `kActionArgBytes[256]` table) -- Host callbacks: fetchLogic / loadPic / drawPic / showPic / - discardPic / overlayPic -- Per-platform save-under for the ego sprite (no full-stage memcpy - per frame; IIgs uses MVN-based codegen) -- Cross-platform binary works on all 4 ports (`AGI.EXE`, - `AGI.PRG`, `Agi`, IIgs `AGI`) - -## What does NOT work - -- **Title screen never advances.** Stubs the input / timer opcodes - the title uses. Workaround: starting-room override (argv[2]). -- **No NPC actors.** animate.obj / set.cel / set.loop are stubs. -- **No parser.** said() and the word-tokenize opcodes are stubs. -- **No sound.** Phase 3 work. -- **IIgs run path for AGI** is not wired. `scripts/run-agi.sh iigs` - prints an explicit "not yet wired" message describing the missing - disk-packager work (need bigger 2mg volume + case-folded ProDOS - names + game-data argument to `package-disk.sh`). -- **ST / Amiga can't pass argv.** Hatari `--auto` and Amiga - startup-sequence don't forward args, so the starting-room override - only works on DOS. ST / Amiga AGI starts at the title screen. - Fix needs either a config-file stage (`ROOM.TXT` read at startup) - or enough title opcodes for the title to advance naturally. - -## How to test - -```bash -source toolchains/env.sh - -# Host-side parsers + VM (fast iteration, no emulator) -./scripts/test-agi.sh - -# Cross-platform binary in DOSBox -./scripts/run-agi.sh dos # title screen -./scripts/run-agi.sh dos kq3 1 # jump to room 1 -./scripts/run-agi.sh dos kq3 3 # jump to room 3 - -# Other platforms (no argv support yet, always title) -./scripts/run-agi.sh atarist -./scripts/run-agi.sh amiga -./scripts/run-agi.sh iigs # prints "not wired" message -``` - -## Files touched (this session) - -New: - -- `src/core/random.c` — xorshift32 PRNG (jlRandom / jlRandomRange / jlRandomSeed) -- `examples/agi/*.c` — agi.c, agiRes.c, agiPic.c, agiView.c, agiVm.c -- `examples/agi/agi.h` — all AGI types + public API -- `tests/agi/*.c` — testAgiRes / testAgiPic / testAgiView / testAgiVm / testAgiPipeline -- `scripts/test-agi.sh` — host-build runner for all five tests -- `scripts/run-agi.sh` — cross-platform emulator launcher (dos | amiga | atarist | iigs) - -Modified: - -- `include/joey/core.h` — random prototypes -- `include/joey/platform.h` — auto-detect from compiler defines -- `.gitignore` — examples/agi/gamedata/ -- All four make/*.mk — added agi to EXAMPLES list - -## Architectural decisions worth remembering - -### Render loop: save-under, not full stage copy - -The naive per-frame `jlSurfaceCopy(stage, gBackdrop)` is 32 KB of -memcpy + present overhead -- not acceptable on a 2.8 MHz IIgs. The -current code: - -1. `cbShowPic` paints the picture onto the stage ONCE and snapshots - it as `gBackdrop`. Sets `gPicReady = true` and invalidates any - prior ego save-under. -2. Per frame: `jlSpriteRestoreUnder` the last-frame ego rect (puts - clean backdrop bytes back), `jlSpriteSaveUnder` the new ego rect, - then `agiViewDraw` paints the cel with priority masking. -3. Placeholder sprite for save-under is 4x5 tiles = 32x40 stage - pixels, sized to cover any AGI v2 ego cel. Compiled via - `jlSpriteCompile` so save/restore use the platform's compiled - fast path (MVN block-copy on IIgs, etc.) instead of the C - interpreter fallback. - -Per-frame memory traffic: ~1.3 KB save+restore vs ~32 KB full copy. - -### VM throttling - -AGI's native cycle is ~6 Hz. Running logic.0 every frame (60 Hz) is -6800-byte switch dispatcher × 60 = ~400k opcodes/sec for nothing. -`agi.c` now runs runVmCycle once every 10 frames (~6 Hz on 60 Hz -refresh, ~5 Hz on 50 Hz PAL). Input polling, ego movement, render -still run at full refresh -- only the bytecode interp is throttled. - -Startup pumps the VM until `gPicReady` (or 32 cycles) so the user -never sees a flash of COLOR_MISSING before the first room paints. - -### VIEW mirror handling - -Sierra's encoder writes `mirror=1, src=N` on BOTH loops in a mirror -pair, where N is the lower-numbered loop. `agiView.c:resolveMirror` -must only treat a cel as mirrored when `src != current_loop`. KQ3 -view 0 hit this directly: both loop 0 (right) and loop 1 (left) had -`mirror=1, src=0`, and our original code flipped both -- so pressing -left and right both faced left. Fixed. - -### Starting-room override - -`agi.c` argv[2] = starting room number 1..255. When set, -`runVmCycle`'s NEW_ROOM handler substitutes the override for -`vm.newRoomId` on the FIRST NEW_ROOM halt only (one-shot). Lets the -user skip past KQ3's title room (45) into the actual game. Once the -override fires, subsequent transitions go through unchanged. - -`scripts/run-agi.sh` accepts ` [game] [room]` and forwards -the room to DOS via dosbox `-c "AGI.EXE . "`. ST and Amiga -can't pass argv via autostart so their AGI starts at the title. - -### Default game dir is "." not "agidemo" - -`resolveGameDir` defaults to "." (CWD). On platforms whose autostart -can't pass argv (Hatari, AmigaDOS), `run-agi.sh` stages the AGI -binary plus the v2 game data files (LOGDIR / PICDIR / etc.) flat in -a temp directory and points the emulator at it; AGI runs from CWD = -that temp dir and finds the data files relative to "./". - -## Likely next-step work - -The user's natural next ask is "implement enough title opcodes to -let KQ3's title screen auto-advance." That probably means: - -- `wait` (cycle.time gate) -- `input.line` / `accept.input` -- Animation timers: `cycle.time`, `current.loop`, etc. -- `set.menu` / `disable.item` (KQ3 title shows a menu) - -Alternative path: skip the title work and implement enough core -opcodes to make a gameplay room functional. animate.obj, -set.view.v, set.cel, set.loop, position, draw, erase. That gets us -walking around KQ3 room 1 (Manannan's house) with Graham instead -of a static title. - -The user should pick which to prioritize. - -## Memory entries you should know about - -The repo's auto-memory at -`~/.claude/projects/-home-scott-claude-joeylib/memory/` includes -JoeyLib-wide context (CMake quirks, IIgs toolchain gotchas, perf -constraints) plus `project_joeylib_agi_plan.md` which describes the -overall AGI port plan. All persist into the next session -automatically; no need to reload. - -Specifically relevant to the AGI port: - -- `project_joeylib_agi_plan.md` — overall plan, 3-4 month estimate -- AGI code uses a manual `parseArgU8` instead of atoi to keep the - IIgs link budget small. -- `project_perf_directive.md` — IIgs is the perf floor; every - other target must match or beat it -- `feedback_iigs_speed.md` — IIgs must be absolute fastest - technically possible; the save-under decision was made under - this constraint. - -## Git / user preferences - -- The user manages git themselves -- do NOT commit / push / branch - on JoeyLib without explicit ask (see memory - `feedback_git.md`). -- Always `source toolchains/env.sh` before any `make` -- the user - has added that to .claude/settings.local.json allow list. -- DJGPP / llvm-mos / vasm / m68k-atari-mint paths come from env.sh. -- The user does NOT need hand-holding -- they're an expert C dev. - Skip excessive explanation; describe what was done and move on.