c64-kb 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2082 -0
- package/LICENSE +29 -0
- package/README.md +559 -0
- package/VERSION +25 -0
- package/dist/cli/setup.js +66 -0
- package/dist/cli/setup.js.map +1 -0
- package/dist/cli-memorize-audit.js +97 -0
- package/dist/cli-memorize-audit.js.map +1 -0
- package/dist/cli.js +335 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.js +83 -0
- package/dist/config.js.map +1 -0
- package/dist/context.js +53 -0
- package/dist/context.js.map +1 -0
- package/dist/domain/budget-notes.js +104 -0
- package/dist/domain/budget-notes.js.map +1 -0
- package/dist/domain/budget.js +417 -0
- package/dist/domain/budget.js.map +1 -0
- package/dist/domain/game-design.js +77 -0
- package/dist/domain/game-design.js.map +1 -0
- package/dist/domain/timing.js +39 -0
- package/dist/domain/timing.js.map +1 -0
- package/dist/graph/apply.js +132 -0
- package/dist/graph/apply.js.map +1 -0
- package/dist/graph/claims.js +231 -0
- package/dist/graph/claims.js.map +1 -0
- package/dist/graph/extract/archetype.js +118 -0
- package/dist/graph/extract/archetype.js.map +1 -0
- package/dist/graph/extract/common.js +69 -0
- package/dist/graph/extract/common.js.map +1 -0
- package/dist/graph/extract/failure.js +37 -0
- package/dist/graph/extract/failure.js.map +1 -0
- package/dist/graph/extract/game-design.js +189 -0
- package/dist/graph/extract/game-design.js.map +1 -0
- package/dist/graph/extract/hardware.js +124 -0
- package/dist/graph/extract/hardware.js.map +1 -0
- package/dist/graph/extract/pitfall.js +62 -0
- package/dist/graph/extract/pitfall.js.map +1 -0
- package/dist/graph/extract/raster-band.js +56 -0
- package/dist/graph/extract/raster-band.js.map +1 -0
- package/dist/graph/extract/recipe.js +71 -0
- package/dist/graph/extract/recipe.js.map +1 -0
- package/dist/graph/extract/technique-entities.js +180 -0
- package/dist/graph/extract/technique-entities.js.map +1 -0
- package/dist/graph/extract/technique.js +179 -0
- package/dist/graph/extract/technique.js.map +1 -0
- package/dist/graph/extract/toolchain.js +67 -0
- package/dist/graph/extract/toolchain.js.map +1 -0
- package/dist/graph/extract/types.js +3 -0
- package/dist/graph/extract/types.js.map +1 -0
- package/dist/graph/extract/vocabulary.js +65 -0
- package/dist/graph/extract/vocabulary.js.map +1 -0
- package/dist/graph/extract.js +43 -0
- package/dist/graph/extract.js.map +1 -0
- package/dist/graph/kernal-clobbers.js +64 -0
- package/dist/graph/kernal-clobbers.js.map +1 -0
- package/dist/graph/machine-variants.js +208 -0
- package/dist/graph/machine-variants.js.map +1 -0
- package/dist/ingest/files.js +99 -0
- package/dist/ingest/files.js.map +1 -0
- package/dist/ingest/passes.js +104 -0
- package/dist/ingest/passes.js.map +1 -0
- package/dist/ingest/points.js +50 -0
- package/dist/ingest/points.js.map +1 -0
- package/dist/ingest/report.js +140 -0
- package/dist/ingest/report.js.map +1 -0
- package/dist/ingest/tally.js +81 -0
- package/dist/ingest/tally.js.map +1 -0
- package/dist/ingest/verified-on.js +43 -0
- package/dist/ingest/verified-on.js.map +1 -0
- package/dist/ingest.js +135 -0
- package/dist/ingest.js.map +1 -0
- package/dist/schemas/cost-basis.js +5 -0
- package/dist/schemas/cost-basis.js.map +1 -0
- package/dist/schemas/machine-variant.js +25 -0
- package/dist/schemas/machine-variant.js.map +1 -0
- package/dist/schemas/plan-budget.js +121 -0
- package/dist/schemas/plan-budget.js.map +1 -0
- package/dist/schemas/tool-outputs.js +526 -0
- package/dist/schemas/tool-outputs.js.map +1 -0
- package/dist/server/define-tool.js +52 -0
- package/dist/server/define-tool.js.map +1 -0
- package/dist/server/defined-only.js +9 -0
- package/dist/server/defined-only.js.map +1 -0
- package/dist/server/tools-briefings.js +70 -0
- package/dist/server/tools-briefings.js.map +1 -0
- package/dist/server/tools-lookup.js +180 -0
- package/dist/server/tools-lookup.js.map +1 -0
- package/dist/server/tools-maintenance.js +116 -0
- package/dist/server/tools-maintenance.js.map +1 -0
- package/dist/server/tools-pitfalls.js +89 -0
- package/dist/server/tools-pitfalls.js.map +1 -0
- package/dist/server/tools-recipes.js +296 -0
- package/dist/server/tools-recipes.js.map +1 -0
- package/dist/server/tools-runtime.js +48 -0
- package/dist/server/tools-runtime.js.map +1 -0
- package/dist/server/tools.js +43 -0
- package/dist/server/tools.js.map +1 -0
- package/dist/server.js +95 -0
- package/dist/server.js.map +1 -0
- package/dist/services/analytics/schema.js +78 -0
- package/dist/services/analytics/schema.js.map +1 -0
- package/dist/services/analytics/statements.js +99 -0
- package/dist/services/analytics/statements.js.map +1 -0
- package/dist/services/analytics.js +195 -0
- package/dist/services/analytics.js.map +1 -0
- package/dist/services/bm25.js +158 -0
- package/dist/services/bm25.js.map +1 -0
- package/dist/services/chunker.js +81 -0
- package/dist/services/chunker.js.map +1 -0
- package/dist/services/embeddings.js +58 -0
- package/dist/services/embeddings.js.map +1 -0
- package/dist/services/falkor/base.js +85 -0
- package/dist/services/falkor/base.js.map +1 -0
- package/dist/services/falkor/links.js +361 -0
- package/dist/services/falkor/links.js.map +1 -0
- package/dist/services/falkor/nodes.js +183 -0
- package/dist/services/falkor/nodes.js.map +1 -0
- package/dist/services/falkor/params.js +45 -0
- package/dist/services/falkor/params.js.map +1 -0
- package/dist/services/falkor/schema.js +77 -0
- package/dist/services/falkor/schema.js.map +1 -0
- package/dist/services/falkor.js +100 -0
- package/dist/services/falkor.js.map +1 -0
- package/dist/services/qdrant.js +238 -0
- package/dist/services/qdrant.js.map +1 -0
- package/dist/services/versions.js +73 -0
- package/dist/services/versions.js.map +1 -0
- package/dist/services/vice-bin.js +51 -0
- package/dist/services/vice-bin.js.map +1 -0
- package/dist/tools/briefings/archetype.js +174 -0
- package/dist/tools/briefings/archetype.js.map +1 -0
- package/dist/tools/briefings/budget.js +177 -0
- package/dist/tools/briefings/budget.js.map +1 -0
- package/dist/tools/briefings/build-order.js +135 -0
- package/dist/tools/briefings/build-order.js.map +1 -0
- package/dist/tools/briefings/build.js +185 -0
- package/dist/tools/briefings/build.js.map +1 -0
- package/dist/tools/briefings/discovery.js +290 -0
- package/dist/tools/briefings/discovery.js.map +1 -0
- package/dist/tools/briefings/plan-pitfalls.js +69 -0
- package/dist/tools/briefings/plan-pitfalls.js.map +1 -0
- package/dist/tools/briefings/render.js +151 -0
- package/dist/tools/briefings/render.js.map +1 -0
- package/dist/tools/briefings/rows.js +41 -0
- package/dist/tools/briefings/rows.js.map +1 -0
- package/dist/tools/briefings/toolchain.js +63 -0
- package/dist/tools/briefings/toolchain.js.map +1 -0
- package/dist/tools/briefings/why-proposed.js +69 -0
- package/dist/tools/briefings/why-proposed.js.map +1 -0
- package/dist/tools/briefings.js +44 -0
- package/dist/tools/briefings.js.map +1 -0
- package/dist/tools/feedback.js +97 -0
- package/dist/tools/feedback.js.map +1 -0
- package/dist/tools/hydrate.js +75 -0
- package/dist/tools/hydrate.js.map +1 -0
- package/dist/tools/intelligence.js +67 -0
- package/dist/tools/intelligence.js.map +1 -0
- package/dist/tools/lint/asm-decimal.js +86 -0
- package/dist/tools/lint/asm-decimal.js.map +1 -0
- package/dist/tools/lint/asm-rules.js +221 -0
- package/dist/tools/lint/asm-rules.js.map +1 -0
- package/dist/tools/lint/asm-shared.js +3 -0
- package/dist/tools/lint/asm-shared.js.map +1 -0
- package/dist/tools/lint/c-rules.js +215 -0
- package/dist/tools/lint/c-rules.js.map +1 -0
- package/dist/tools/lint/text.js +122 -0
- package/dist/tools/lint/text.js.map +1 -0
- package/dist/tools/lint/types.js +40 -0
- package/dist/tools/lint/types.js.map +1 -0
- package/dist/tools/lint.js +76 -0
- package/dist/tools/lint.js.map +1 -0
- package/dist/tools/memorization-mcp.js +111 -0
- package/dist/tools/memorization-mcp.js.map +1 -0
- package/dist/tools/pitfalls/bm25.js +53 -0
- package/dist/tools/pitfalls/bm25.js.map +1 -0
- package/dist/tools/pitfalls/format.js +58 -0
- package/dist/tools/pitfalls/format.js.map +1 -0
- package/dist/tools/pitfalls/graph.js +124 -0
- package/dist/tools/pitfalls/graph.js.map +1 -0
- package/dist/tools/pitfalls.js +134 -0
- package/dist/tools/pitfalls.js.map +1 -0
- package/dist/tools/prompts.js +81 -0
- package/dist/tools/prompts.js.map +1 -0
- package/dist/tools/query/compatibility/closure.js +62 -0
- package/dist/tools/query/compatibility/closure.js.map +1 -0
- package/dist/tools/query/compatibility/facts.js +28 -0
- package/dist/tools/query/compatibility/facts.js.map +1 -0
- package/dist/tools/query/compatibility/fetch.js +164 -0
- package/dist/tools/query/compatibility/fetch.js.map +1 -0
- package/dist/tools/query/compatibility/hard-rules.js +159 -0
- package/dist/tools/query/compatibility/hard-rules.js.map +1 -0
- package/dist/tools/query/compatibility/index.js +27 -0
- package/dist/tools/query/compatibility/index.js.map +1 -0
- package/dist/tools/query/compatibility/kernal-zp-rule.js +90 -0
- package/dist/tools/query/compatibility/kernal-zp-rule.js.map +1 -0
- package/dist/tools/query/compatibility/render.js +106 -0
- package/dist/tools/query/compatibility/render.js.map +1 -0
- package/dist/tools/query/compatibility/rules.js +337 -0
- package/dist/tools/query/compatibility/rules.js.map +1 -0
- package/dist/tools/query/compatibility/unit-rules.js +253 -0
- package/dist/tools/query/compatibility/unit-rules.js.map +1 -0
- package/dist/tools/query/game-design.js +83 -0
- package/dist/tools/query/game-design.js.map +1 -0
- package/dist/tools/query/lookups.js +220 -0
- package/dist/tools/query/lookups.js.map +1 -0
- package/dist/tools/query/plan-budget.js +266 -0
- package/dist/tools/query/plan-budget.js.map +1 -0
- package/dist/tools/query/recipes.js +214 -0
- package/dist/tools/query/recipes.js.map +1 -0
- package/dist/tools/query/retrieval.js +128 -0
- package/dist/tools/query/retrieval.js.map +1 -0
- package/dist/tools/query/shared.js +121 -0
- package/dist/tools/query/shared.js.map +1 -0
- package/dist/tools/query/techniques.js +331 -0
- package/dist/tools/query/techniques.js.map +1 -0
- package/dist/tools/query/timing.js +106 -0
- package/dist/tools/query/timing.js.map +1 -0
- package/dist/tools/query/types.js +11 -0
- package/dist/tools/query/types.js.map +1 -0
- package/dist/tools/query.js +21 -0
- package/dist/tools/query.js.map +1 -0
- package/dist/tools/resources.js +186 -0
- package/dist/tools/resources.js.map +1 -0
- package/dist/tools/run-game.js +249 -0
- package/dist/tools/run-game.js.map +1 -0
- package/dist/tools/selfimprovement.js +367 -0
- package/dist/tools/selfimprovement.js.map +1 -0
- package/docker-compose.yml +35 -0
- package/docs/ARCHITECTURE.md +164 -0
- package/docs/CONVENTIONS-archetypes.md +158 -0
- package/docs/CONVENTIONS-failures.md +46 -0
- package/docs/CONVENTIONS-game-designs.md +75 -0
- package/docs/CONVENTIONS-hardware-reference.md +184 -0
- package/docs/CONVENTIONS-pitfalls.md +91 -0
- package/docs/CONVENTIONS-recipes.md +106 -0
- package/docs/CONVENTIONS-techniques.md +309 -0
- package/docs/CONVENTIONS-toolchain-reference.md +89 -0
- package/docs/ONTOLOGY.md +655 -0
- package/docs/art/art-production-reference.md +157 -0
- package/docs/art/asset-pipelines.md +586 -0
- package/docs/c64-failure-patterns.md +693 -0
- package/docs/demo-design/demo-composition.md +349 -0
- package/docs/demo-design/demo-design-philosophy.md +320 -0
- package/docs/demo-design/intro-cracktro-patterns.md +435 -0
- package/docs/figures/ctm-spd-embed-probe.png +0 -0
- package/docs/figures/dot-flag-mid-5000000.png +0 -0
- package/docs/figures/dot-flag-no-erase-12000000.png +0 -0
- package/docs/figures/edges.json +1 -0
- package/docs/figures/fig6-architecture.png +0 -0
- package/docs/figures/fig7-ontology.png +0 -0
- package/docs/figures/screen-dissolve-mid-frame25.png +0 -0
- package/docs/figures/screen-dissolve-wipe-frame25.png +0 -0
- package/docs/figures/spindle-two-parts-part1.png +0 -0
- package/docs/figures/spindle-two-parts-part2.png +0 -0
- package/docs/figures/starters/action-puzzle.png +0 -0
- package/docs/figures/starters/adventure.png +0 -0
- package/docs/figures/starters/beat-em-up.png +0 -0
- package/docs/figures/starters/demo.png +0 -0
- package/docs/figures/starters/platformer.png +0 -0
- package/docs/figures/starters/shmup-vertical.png +0 -0
- package/docs/figures/tape-kernal-master-ntsc.png +0 -0
- package/docs/figures/tape-kernal-master-pal.png +0 -0
- package/docs/figures/tape-turbo-loader-ntsc.png +0 -0
- package/docs/figures/tape-turbo-loader-pal.png +0 -0
- package/docs/figures/tape-turbo-master-ntsc.png +0 -0
- package/docs/figures/tape-turbo-master-pal.png +0 -0
- package/docs/figures/tech-tech-pad2-12000000.png +0 -0
- package/docs/figures/tech-tech-pad4-12000000.png +0 -0
- package/docs/figures/tech-tech-seven-12000000.png +0 -0
- package/docs/figures/twister-mid-5000000.png +0 -0
- package/docs/figures/twister-straight-12000000.png +0 -0
- package/docs/figures/vector-balls-nosort-ntsc.png +0 -0
- package/docs/figures/vector-balls-nosort.png +0 -0
- package/docs/formats/c64-file-formats.md +1212 -0
- package/docs/formats/iec-disk-reference.md +754 -0
- package/docs/game-design/c64-game-archetypes.md +273 -0
- package/docs/game-design/designs/falling-blocks.md +54 -0
- package/docs/game-design/designs/platformer-scaffold.md +48 -0
- package/docs/game-design/designs/simple-shmup.md +27 -0
- package/docs/game-design/enemy-behaviour-and-difficulty.md +349 -0
- package/docs/game-design/game-design-patterns.md +1189 -0
- package/docs/game-design/game-structure.md +354 -0
- package/docs/game-design/production-planning.md +349 -0
- package/docs/game-design/reference-game-sources.md +90 -0
- package/docs/hardware/6502-illegal-opcodes.md +1353 -0
- package/docs/hardware/6510-cpu-reference.md +2112 -0
- package/docs/hardware/c64-memory-map.md +3184 -0
- package/docs/hardware/c64-registers-reference.md +996 -0
- package/docs/hardware/cia-reference.md +1281 -0
- package/docs/hardware/kernal-routines-reference.md +1836 -0
- package/docs/hardware/pal-ntsc-reference.md +813 -0
- package/docs/hardware/sid-reference.md +1137 -0
- package/docs/hardware/vic-ii-reference.md +1714 -0
- package/docs/music/music-production-reference.md +403 -0
- package/docs/pitfalls/banking.md +1067 -0
- package/docs/pitfalls/cia.md +1147 -0
- package/docs/pitfalls/cpu.md +874 -0
- package/docs/pitfalls/input.md +282 -0
- package/docs/pitfalls/kernal-and-io.md +1615 -0
- package/docs/pitfalls/loader.md +1191 -0
- package/docs/pitfalls/logic.md +94 -0
- package/docs/pitfalls/maths.md +187 -0
- package/docs/pitfalls/raster-and-badline.md +721 -0
- package/docs/pitfalls/region-timing.md +660 -0
- package/docs/pitfalls/scroll.md +207 -0
- package/docs/pitfalls/sid.md +738 -0
- package/docs/pitfalls/sprite.md +979 -0
- package/docs/pitfalls/text-mode-render.md +1172 -0
- package/docs/recipes/cc65/cartridge-8k.md +398 -0
- package/docs/recipes/cc65/hello-world-conio.md +76 -0
- package/docs/recipes/cc65/memory-layout.md +312 -0
- package/docs/recipes/cc65/screenshots/README.md +14 -0
- package/docs/recipes/cc65/screenshots/cartridge-8k-ntsc.png +0 -0
- package/docs/recipes/cc65/screenshots/cartridge-8k.png +0 -0
- package/docs/recipes/cc65/screenshots/hello-world-conio.png +0 -0
- package/docs/recipes/cc65/screenshots/memory-layout-ntsc.png +0 -0
- package/docs/recipes/cc65/screenshots/memory-layout.png +0 -0
- package/docs/recipes/kickassembler/basic-float-calls.md +578 -0
- package/docs/recipes/kickassembler/basic-wedge.md +398 -0
- package/docs/recipes/kickassembler/big-font-scroller.md +620 -0
- package/docs/recipes/kickassembler/charset-copy-rom-to-ram.md +623 -0
- package/docs/recipes/kickassembler/cia-revision-detect.md +366 -0
- package/docs/recipes/kickassembler/colour-cycling.md +343 -0
- package/docs/recipes/kickassembler/colour-fade.md +303 -0
- package/docs/recipes/kickassembler/compare-16bit-signed.md +1007 -0
- package/docs/recipes/kickassembler/cracktro-template.md +526 -0
- package/docs/recipes/kickassembler/crt-banked.md +276 -0
- package/docs/recipes/kickassembler/dos-error-codes.md +466 -0
- package/docs/recipes/kickassembler/dot-flag.md +576 -0
- package/docs/recipes/kickassembler/drive-job-queue.md +667 -0
- package/docs/recipes/kickassembler/drive-via-probe.md +690 -0
- package/docs/recipes/kickassembler/dycp-scroller.md +568 -0
- package/docs/recipes/kickassembler/dypp-sprite-scroller.md +681 -0
- package/docs/recipes/kickassembler/dysp.md +670 -0
- package/docs/recipes/kickassembler/easyflash-save.md +800 -0
- package/docs/recipes/kickassembler/eight-way-scroll.md +1484 -0
- package/docs/recipes/kickassembler/file-io-roundtrip.md +546 -0
- package/docs/recipes/kickassembler/fire-effect.md +420 -0
- package/docs/recipes/kickassembler/fld.md +414 -0
- package/docs/recipes/kickassembler/fli-image.md +336 -0
- package/docs/recipes/kickassembler/four-player-read.md +672 -0
- package/docs/recipes/kickassembler/headless-verify.md +228 -0
- package/docs/recipes/kickassembler/hello-world.md +98 -0
- package/docs/recipes/kickassembler/high-score-insert.md +660 -0
- package/docs/recipes/kickassembler/hires-plot-line.md +723 -0
- package/docs/recipes/kickassembler/irq-chain.md +316 -0
- package/docs/recipes/kickassembler/irq-owns-port.md +668 -0
- package/docs/recipes/kickassembler/isometric-room.md +1145 -0
- package/docs/recipes/kickassembler/light-pen-read.md +926 -0
- package/docs/recipes/kickassembler/logic-rate-decoupling.md +670 -0
- package/docs/recipes/kickassembler/mci-interlace.md +543 -0
- package/docs/recipes/kickassembler/memory-layout.md +277 -0
- package/docs/recipes/kickassembler/mouse-1351-read.md +801 -0
- package/docs/recipes/kickassembler/nmi-timer-tick.md +562 -0
- package/docs/recipes/kickassembler/own-keyscan.md +881 -0
- package/docs/recipes/kickassembler/paddle-read.md +751 -0
- package/docs/recipes/kickassembler/palette-cells.md +219 -0
- package/docs/recipes/kickassembler/pseudo-3d-road.md +930 -0
- package/docs/recipes/kickassembler/pwm-digi.md +463 -0
- package/docs/recipes/kickassembler/raster-bars.md +264 -0
- package/docs/recipes/kickassembler/reu-dma.md +1019 -0
- package/docs/recipes/kickassembler/runtime-relocation.md +743 -0
- package/docs/recipes/kickassembler/screen-dissolve.md +545 -0
- package/docs/recipes/kickassembler/screen-wipe.md +408 -0
- package/docs/recipes/kickassembler/screenshots/README.md +72 -0
- package/docs/recipes/kickassembler/screenshots/basic-float-calls-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/basic-float-calls.png +0 -0
- package/docs/recipes/kickassembler/screenshots/basic-wedge-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/basic-wedge.png +0 -0
- package/docs/recipes/kickassembler/screenshots/big-font-scroller-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/big-font-scroller.png +0 -0
- package/docs/recipes/kickassembler/screenshots/charset-copy-rom-to-ram-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/charset-copy-rom-to-ram.png +0 -0
- package/docs/recipes/kickassembler/screenshots/cia-revision-detect-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/cia-revision-detect.png +0 -0
- package/docs/recipes/kickassembler/screenshots/colour-cycling-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/colour-cycling.png +0 -0
- package/docs/recipes/kickassembler/screenshots/colour-fade-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/colour-fade.png +0 -0
- package/docs/recipes/kickassembler/screenshots/compare-16bit-signed-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/compare-16bit-signed.png +0 -0
- package/docs/recipes/kickassembler/screenshots/cracktro-template.png +0 -0
- package/docs/recipes/kickassembler/screenshots/crt-banked-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/crt-banked.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dos-error-codes-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dos-error-codes.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dot-flag-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dot-flag.png +0 -0
- package/docs/recipes/kickassembler/screenshots/drive-job-queue-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/drive-job-queue.png +0 -0
- package/docs/recipes/kickassembler/screenshots/drive-via-probe-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/drive-via-probe.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dycp-scroller-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dycp-scroller.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dypp-sprite-scroller-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dypp-sprite-scroller.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dysp-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dysp.png +0 -0
- package/docs/recipes/kickassembler/screenshots/easyflash-save-ntsc-run2.png +0 -0
- package/docs/recipes/kickassembler/screenshots/easyflash-save-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/easyflash-save-run2.png +0 -0
- package/docs/recipes/kickassembler/screenshots/easyflash-save.png +0 -0
- package/docs/recipes/kickassembler/screenshots/eight-way-scroll-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/eight-way-scroll.png +0 -0
- package/docs/recipes/kickassembler/screenshots/file-io-roundtrip-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/file-io-roundtrip.png +0 -0
- package/docs/recipes/kickassembler/screenshots/fire-effect-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/fire-effect.png +0 -0
- package/docs/recipes/kickassembler/screenshots/fld-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/fld.png +0 -0
- package/docs/recipes/kickassembler/screenshots/fli-image.png +0 -0
- package/docs/recipes/kickassembler/screenshots/four-player-read-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/four-player-read.png +0 -0
- package/docs/recipes/kickassembler/screenshots/headless-verify-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/headless-verify.png +0 -0
- package/docs/recipes/kickassembler/screenshots/hello-world.png +0 -0
- package/docs/recipes/kickassembler/screenshots/high-score-insert-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/high-score-insert.png +0 -0
- package/docs/recipes/kickassembler/screenshots/hires-plot-line-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/hires-plot-line.png +0 -0
- package/docs/recipes/kickassembler/screenshots/irq-chain-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/irq-chain.png +0 -0
- package/docs/recipes/kickassembler/screenshots/irq-owns-port-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/irq-owns-port.png +0 -0
- package/docs/recipes/kickassembler/screenshots/isometric-room-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/isometric-room.png +0 -0
- package/docs/recipes/kickassembler/screenshots/light-pen-read-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/light-pen-read.png +0 -0
- package/docs/recipes/kickassembler/screenshots/logic-rate-decoupling-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/logic-rate-decoupling.png +0 -0
- package/docs/recipes/kickassembler/screenshots/mci-interlace-average.png +0 -0
- package/docs/recipes/kickassembler/screenshots/mci-interlace-frame-b.png +0 -0
- package/docs/recipes/kickassembler/screenshots/mci-interlace-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/mci-interlace.png +0 -0
- package/docs/recipes/kickassembler/screenshots/memory-layout-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/memory-layout.png +0 -0
- package/docs/recipes/kickassembler/screenshots/mouse-1351-read-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/mouse-1351-read.png +0 -0
- package/docs/recipes/kickassembler/screenshots/nmi-timer-tick-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/nmi-timer-tick.png +0 -0
- package/docs/recipes/kickassembler/screenshots/own-keyscan-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/own-keyscan.png +0 -0
- package/docs/recipes/kickassembler/screenshots/paddle-read-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/paddle-read.png +0 -0
- package/docs/recipes/kickassembler/screenshots/palette-cells-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/palette-cells.png +0 -0
- package/docs/recipes/kickassembler/screenshots/pseudo-3d-road-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/pseudo-3d-road.png +0 -0
- package/docs/recipes/kickassembler/screenshots/pwm-digi-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/pwm-digi.png +0 -0
- package/docs/recipes/kickassembler/screenshots/raster-bars.png +0 -0
- package/docs/recipes/kickassembler/screenshots/reu-dma-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/reu-dma.png +0 -0
- package/docs/recipes/kickassembler/screenshots/runtime-relocation-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/runtime-relocation.png +0 -0
- package/docs/recipes/kickassembler/screenshots/screen-dissolve-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/screen-dissolve.png +0 -0
- package/docs/recipes/kickassembler/screenshots/screen-wipe-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/screen-wipe.png +0 -0
- package/docs/recipes/kickassembler/screenshots/scroll-panel-split-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/scroll-panel-split.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sfx-in-player-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sfx-in-player.png +0 -0
- package/docs/recipes/kickassembler/screenshots/shadebobs-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/shadebobs.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sideborder-open.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sine-scroller.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sine-table-runtime-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sine-table-runtime.png +0 -0
- package/docs/recipes/kickassembler/screenshots/software-sprite-preshifted-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/software-sprite-preshifted.png +0 -0
- package/docs/recipes/kickassembler/screenshots/speedcode-generator-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/speedcode-generator.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-border-scroller-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-border-scroller.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-cache-flip-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-cache-flip.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-multiplex-24.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-multiplex-game-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-multiplex-game.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-priority-classes-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-priority-classes.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-sine-chain-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-sine-chain.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-stretcher-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-stretcher.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprites-only-screen-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprites-only-screen.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sqrt-atan2-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sqrt-atan2.png +0 -0
- package/docs/recipes/kickassembler/screenshots/stable-raster-irq-control.png +0 -0
- package/docs/recipes/kickassembler/screenshots/stable-raster-irq.png +0 -0
- package/docs/recipes/kickassembler/screenshots/tech-tech-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/tech-tech.png +0 -0
- package/docs/recipes/kickassembler/screenshots/tod-alarm-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/tod-alarm.png +0 -0
- package/docs/recipes/kickassembler/screenshots/topbottom-border-open.png +0 -0
- package/docs/recipes/kickassembler/screenshots/twister-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/twister.png +0 -0
- package/docs/recipes/kickassembler/screenshots/unit-test-driver-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/unit-test-driver.png +0 -0
- package/docs/recipes/kickassembler/screenshots/vector-balls-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/vector-balls.png +0 -0
- package/docs/recipes/kickassembler/screenshots/wireframe-ships-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/wireframe-ships.png +0 -0
- package/docs/recipes/kickassembler/scroll-panel-split.md +381 -0
- package/docs/recipes/kickassembler/sfx-in-player.md +907 -0
- package/docs/recipes/kickassembler/shadebobs.md +522 -0
- package/docs/recipes/kickassembler/sideborder-open.md +338 -0
- package/docs/recipes/kickassembler/sine-scroller.md +321 -0
- package/docs/recipes/kickassembler/sine-table-runtime.md +815 -0
- package/docs/recipes/kickassembler/software-sprite-preshifted.md +725 -0
- package/docs/recipes/kickassembler/speedcode-generator.md +606 -0
- package/docs/recipes/kickassembler/sprite-border-scroller.md +696 -0
- package/docs/recipes/kickassembler/sprite-cache-flip.md +1071 -0
- package/docs/recipes/kickassembler/sprite-multiplex-24.md +326 -0
- package/docs/recipes/kickassembler/sprite-multiplex-game.md +986 -0
- package/docs/recipes/kickassembler/sprite-priority-classes.md +463 -0
- package/docs/recipes/kickassembler/sprite-sine-chain.md +338 -0
- package/docs/recipes/kickassembler/sprite-stretcher.md +501 -0
- package/docs/recipes/kickassembler/sprites-only-screen.md +550 -0
- package/docs/recipes/kickassembler/sqrt-atan2.md +1014 -0
- package/docs/recipes/kickassembler/stable-raster-irq.md +360 -0
- package/docs/recipes/kickassembler/tape-turbo-loader.md +875 -0
- package/docs/recipes/kickassembler/tech-tech.md +679 -0
- package/docs/recipes/kickassembler/tod-alarm.md +754 -0
- package/docs/recipes/kickassembler/topbottom-border-open.md +407 -0
- package/docs/recipes/kickassembler/twister.md +518 -0
- package/docs/recipes/kickassembler/unit-test-driver.md +314 -0
- package/docs/recipes/kickassembler/vector-balls.md +545 -0
- package/docs/recipes/kickassembler/wireframe-ships.md +2324 -0
- package/docs/recipes/oscar64/actor-activation-window.md +807 -0
- package/docs/recipes/oscar64/adventure-engine.md +1094 -0
- package/docs/recipes/oscar64/attract-replay.md +465 -0
- package/docs/recipes/oscar64/beat-em-up-lanes.md +563 -0
- package/docs/recipes/oscar64/bfs-distance-map.md +723 -0
- package/docs/recipes/oscar64/bitmap-koala-viewer.md +355 -0
- package/docs/recipes/oscar64/car-contact.md +950 -0
- package/docs/recipes/oscar64/cave-scan.md +609 -0
- package/docs/recipes/oscar64/char-bullets.md +477 -0
- package/docs/recipes/oscar64/charset-animation.md +383 -0
- package/docs/recipes/oscar64/charset-parallax.md +401 -0
- package/docs/recipes/oscar64/destructible-terrain.md +1099 -0
- package/docs/recipes/oscar64/difficulty-tables.md +654 -0
- package/docs/recipes/oscar64/dig-and-guards.md +975 -0
- package/docs/recipes/oscar64/directory-reader.md +535 -0
- package/docs/recipes/oscar64/divide-check.md +581 -0
- package/docs/recipes/oscar64/double-buffer-nomirror.md +205 -0
- package/docs/recipes/oscar64/double-buffer.md +255 -0
- package/docs/recipes/oscar64/falling-blocks.md +874 -0
- package/docs/recipes/oscar64/fixed-point-jump-velocity.md +289 -0
- package/docs/recipes/oscar64/fixed-point-jump.md +210 -0
- package/docs/recipes/oscar64/flip-screen-rooms.md +793 -0
- package/docs/recipes/oscar64/frame-sync-loop-overrun.md +214 -0
- package/docs/recipes/oscar64/frame-sync-loop.md +254 -0
- package/docs/recipes/oscar64/game-tree-search.md +743 -0
- package/docs/recipes/oscar64/ghost-targeting.md +867 -0
- package/docs/recipes/oscar64/headless-verify.md +345 -0
- package/docs/recipes/oscar64/hello-world.md +83 -0
- package/docs/recipes/oscar64/high-score-persist.md +772 -0
- package/docs/recipes/oscar64/iffl-kernal-skip.md +421 -0
- package/docs/recipes/oscar64/joystick-input.md +358 -0
- package/docs/recipes/oscar64/lane-pursuit.md +1028 -0
- package/docs/recipes/oscar64/level-rle-decoder.md +620 -0
- package/docs/recipes/oscar64/lfsr-random-seed2.md +338 -0
- package/docs/recipes/oscar64/lfsr-random.md +403 -0
- package/docs/recipes/oscar64/load-asset-runtime.md +492 -0
- package/docs/recipes/oscar64/memory-layout.md +232 -0
- package/docs/recipes/oscar64/mixed-fighters.md +781 -0
- package/docs/recipes/oscar64/multi-sprite-object.md +533 -0
- package/docs/recipes/oscar64/nav-area-pathfinding.md +881 -0
- package/docs/recipes/oscar64/object-pool.md +572 -0
- package/docs/recipes/oscar64/pal-ntsc-detect.md +257 -0
- package/docs/recipes/oscar64/password-state.md +532 -0
- package/docs/recipes/oscar64/per-frame-hitbox.md +651 -0
- package/docs/recipes/oscar64/petscii-screen-codes.md +428 -0
- package/docs/recipes/oscar64/platformer-scaffold.md +1467 -0
- package/docs/recipes/oscar64/print-number.md +367 -0
- package/docs/recipes/oscar64/raster-bars.md +239 -0
- package/docs/recipes/oscar64/raster-profile-bars.md +404 -0
- package/docs/recipes/oscar64/rel-side-sectors.md +391 -0
- package/docs/recipes/oscar64/relative-file-records.md +378 -0
- package/docs/recipes/oscar64/save-load-seq-file.md +365 -0
- package/docs/recipes/oscar64/screenshots/README.md +99 -0
- package/docs/recipes/oscar64/screenshots/actor-activation-window-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/actor-activation-window.png +0 -0
- package/docs/recipes/oscar64/screenshots/adventure-engine-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/adventure-engine.png +0 -0
- package/docs/recipes/oscar64/screenshots/attract-replay-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/attract-replay.png +0 -0
- package/docs/recipes/oscar64/screenshots/beat-em-up-lanes-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/beat-em-up-lanes.png +0 -0
- package/docs/recipes/oscar64/screenshots/bfs-distance-map-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/bfs-distance-map.png +0 -0
- package/docs/recipes/oscar64/screenshots/bitmap-koala-viewer.png +0 -0
- package/docs/recipes/oscar64/screenshots/car-contact-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/car-contact.png +0 -0
- package/docs/recipes/oscar64/screenshots/cave-scan-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/cave-scan.png +0 -0
- package/docs/recipes/oscar64/screenshots/char-bullets-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/char-bullets.png +0 -0
- package/docs/recipes/oscar64/screenshots/charset-animation-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/charset-animation.png +0 -0
- package/docs/recipes/oscar64/screenshots/charset-parallax-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/charset-parallax.png +0 -0
- package/docs/recipes/oscar64/screenshots/destructible-terrain-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/destructible-terrain.png +0 -0
- package/docs/recipes/oscar64/screenshots/difficulty-tables-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/difficulty-tables.png +0 -0
- package/docs/recipes/oscar64/screenshots/dig-and-guards-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/dig-and-guards.png +0 -0
- package/docs/recipes/oscar64/screenshots/directory-reader-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/directory-reader.png +0 -0
- package/docs/recipes/oscar64/screenshots/divide-check-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/divide-check.png +0 -0
- package/docs/recipes/oscar64/screenshots/double-buffer-nomirror.png +0 -0
- package/docs/recipes/oscar64/screenshots/double-buffer-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/double-buffer.png +0 -0
- package/docs/recipes/oscar64/screenshots/falling-blocks-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/falling-blocks.png +0 -0
- package/docs/recipes/oscar64/screenshots/fixed-point-jump-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/fixed-point-jump-velocity-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/fixed-point-jump-velocity.png +0 -0
- package/docs/recipes/oscar64/screenshots/fixed-point-jump.png +0 -0
- package/docs/recipes/oscar64/screenshots/flip-screen-rooms-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/flip-screen-rooms.png +0 -0
- package/docs/recipes/oscar64/screenshots/frame-sync-loop-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/frame-sync-loop-overrun.png +0 -0
- package/docs/recipes/oscar64/screenshots/frame-sync-loop.png +0 -0
- package/docs/recipes/oscar64/screenshots/game-tree-search-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/game-tree-search.png +0 -0
- package/docs/recipes/oscar64/screenshots/ghost-targeting-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/ghost-targeting.png +0 -0
- package/docs/recipes/oscar64/screenshots/headless-verify-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/headless-verify.png +0 -0
- package/docs/recipes/oscar64/screenshots/hello-world.png +0 -0
- package/docs/recipes/oscar64/screenshots/high-score-persist-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/high-score-persist.png +0 -0
- package/docs/recipes/oscar64/screenshots/iffl-kernal-skip-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/iffl-kernal-skip.png +0 -0
- package/docs/recipes/oscar64/screenshots/joystick-input-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/joystick-input.png +0 -0
- package/docs/recipes/oscar64/screenshots/lane-pursuit-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/lane-pursuit.png +0 -0
- package/docs/recipes/oscar64/screenshots/level-rle-decoder-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/level-rle-decoder.png +0 -0
- package/docs/recipes/oscar64/screenshots/lfsr-random-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/lfsr-random-seed2.png +0 -0
- package/docs/recipes/oscar64/screenshots/lfsr-random.png +0 -0
- package/docs/recipes/oscar64/screenshots/load-asset-runtime-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/load-asset-runtime.png +0 -0
- package/docs/recipes/oscar64/screenshots/memory-layout-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/memory-layout.png +0 -0
- package/docs/recipes/oscar64/screenshots/mixed-fighters-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/mixed-fighters.png +0 -0
- package/docs/recipes/oscar64/screenshots/multi-sprite-object-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/multi-sprite-object.png +0 -0
- package/docs/recipes/oscar64/screenshots/nav-area-pathfinding-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/nav-area-pathfinding.png +0 -0
- package/docs/recipes/oscar64/screenshots/object-pool-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/object-pool.png +0 -0
- package/docs/recipes/oscar64/screenshots/pal-ntsc-detect-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/pal-ntsc-detect-oldntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/pal-ntsc-detect-pal.png +0 -0
- package/docs/recipes/oscar64/screenshots/password-state-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/password-state.png +0 -0
- package/docs/recipes/oscar64/screenshots/per-frame-hitbox-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/per-frame-hitbox.png +0 -0
- package/docs/recipes/oscar64/screenshots/petscii-screen-codes-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/petscii-screen-codes.png +0 -0
- package/docs/recipes/oscar64/screenshots/platformer-scaffold-d64-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/platformer-scaffold-d64.png +0 -0
- package/docs/recipes/oscar64/screenshots/platformer-scaffold-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/platformer-scaffold.png +0 -0
- package/docs/recipes/oscar64/screenshots/print-number-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/print-number.png +0 -0
- package/docs/recipes/oscar64/screenshots/raster-bars.png +0 -0
- package/docs/recipes/oscar64/screenshots/raster-profile-bars-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/raster-profile-bars.png +0 -0
- package/docs/recipes/oscar64/screenshots/rel-side-sectors-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/rel-side-sectors.png +0 -0
- package/docs/recipes/oscar64/screenshots/relative-file-records-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/relative-file-records.png +0 -0
- package/docs/recipes/oscar64/screenshots/save-load-seq-file-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/save-load-seq-file.png +0 -0
- package/docs/recipes/oscar64/screenshots/seeded-level-fill-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/seeded-level-fill.png +0 -0
- package/docs/recipes/oscar64/screenshots/sfx-engine-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/sfx-engine.png +0 -0
- package/docs/recipes/oscar64/screenshots/sid-music-player.png +0 -0
- package/docs/recipes/oscar64/screenshots/simple-shmup.png +0 -0
- package/docs/recipes/oscar64/screenshots/slope-collision-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/slope-collision.png +0 -0
- package/docs/recipes/oscar64/screenshots/soft-scroll-h.png +0 -0
- package/docs/recipes/oscar64/screenshots/sprite-animation-table-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/sprite-animation-table.png +0 -0
- package/docs/recipes/oscar64/screenshots/sprite-multiplex-8.png +0 -0
- package/docs/recipes/oscar64/screenshots/stable-raster-irq.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-input-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-input.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-overlay-playfield-gameover.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-overlay-playfield-notrail-control.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-overlay-playfield-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-overlay-playfield-ungated-control.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-overlay-playfield.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-window-menu-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-window-menu.png +0 -0
- package/docs/recipes/oscar64/screenshots/tile-grid-collision-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/tile-grid-collision.png +0 -0
- package/docs/recipes/oscar64/screenshots/tile-map-render-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/tile-map-render.png +0 -0
- package/docs/recipes/oscar64/screenshots/two-player-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/two-player.png +0 -0
- package/docs/recipes/oscar64/screenshots/two-word-parser-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/two-word-parser.png +0 -0
- package/docs/recipes/oscar64/screenshots/vehicle-control-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/vehicle-control.png +0 -0
- package/docs/recipes/oscar64/screenshots/wave-director-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/wave-director.png +0 -0
- package/docs/recipes/oscar64/seeded-level-fill.md +364 -0
- package/docs/recipes/oscar64/sfx-engine.md +514 -0
- package/docs/recipes/oscar64/sid-music-player.md +441 -0
- package/docs/recipes/oscar64/simple-shmup.md +1000 -0
- package/docs/recipes/oscar64/slope-collision.md +610 -0
- package/docs/recipes/oscar64/soft-scroll-h.md +261 -0
- package/docs/recipes/oscar64/sprite-animation-table.md +671 -0
- package/docs/recipes/oscar64/sprite-multiplex-8.md +314 -0
- package/docs/recipes/oscar64/stable-raster-irq.md +236 -0
- package/docs/recipes/oscar64/text-input.md +274 -0
- package/docs/recipes/oscar64/text-overlay-playfield.md +617 -0
- package/docs/recipes/oscar64/text-window-menu.md +551 -0
- package/docs/recipes/oscar64/tile-grid-collision.md +563 -0
- package/docs/recipes/oscar64/tile-map-render.md +395 -0
- package/docs/recipes/oscar64/two-player.md +528 -0
- package/docs/recipes/oscar64/two-word-parser.md +510 -0
- package/docs/recipes/oscar64/vehicle-control.md +771 -0
- package/docs/recipes/oscar64/wave-director.md +787 -0
- package/docs/recipes/runs.json +1606 -0
- package/docs/runtime/sim6502-reference.md +466 -0
- package/docs/runtime/vice-mcp-reference.md +351 -0
- package/docs/runtime/vice-reference.md +1393 -0
- package/docs/techniques/bitmap-modes.md +685 -0
- package/docs/techniques/cpu-cycle-tricks.md +1570 -0
- package/docs/techniques/effects-vector-3d.md +1431 -0
- package/docs/techniques/file-io.md +1427 -0
- package/docs/techniques/input.md +1072 -0
- package/docs/techniques/loaders-packers.md +768 -0
- package/docs/techniques/logic.md +3091 -0
- package/docs/techniques/maths.md +1524 -0
- package/docs/techniques/memory-banking.md +1686 -0
- package/docs/techniques/music-sid.md +1144 -0
- package/docs/techniques/raster.md +1543 -0
- package/docs/techniques/scroll.md +1292 -0
- package/docs/techniques/sprite.md +2566 -0
- package/docs/techniques/text-mode-render.md +717 -0
- package/docs/techniques/text.md +1095 -0
- package/docs/techniques/transitions.md +405 -0
- package/docs/toolchains/cartconv-reference.md +262 -0
- package/docs/toolchains/cc1541-reference.md +316 -0
- package/docs/toolchains/cc65-reference.md +667 -0
- package/docs/toolchains/error-sources/cc65/README.md +1 -0
- package/docs/toolchains/error-sources/cc65/missing-setcpu.s +4 -0
- package/docs/toolchains/error-sources/cc65/range-error.s +4 -0
- package/docs/toolchains/error-sources/cc65/segment-overflow.c +6 -0
- package/docs/toolchains/error-sources/cc65/unresolved-external.c +6 -0
- package/docs/toolchains/error-sources/kickassembler/README.md +1 -0
- package/docs/toolchains/error-sources/kickassembler/branch-out-of-range.asm +4 -0
- package/docs/toolchains/error-sources/kickassembler/failed-assert.asm +3 -0
- package/docs/toolchains/error-sources/kickassembler/flat-lib.asm +4 -0
- package/docs/toolchains/error-sources/kickassembler/import-source-no-namespace.asm +5 -0
- package/docs/toolchains/error-sources/kickassembler/macro-without-parentheses.asm +6 -0
- package/docs/toolchains/error-sources/kickassembler/memory-block-overlap.asm +4 -0
- package/docs/toolchains/error-sources/kickassembler/symbol-clash-lib.asm +5 -0
- package/docs/toolchains/error-sources/kickassembler/symbol-clash-main.asm +6 -0
- package/docs/toolchains/error-sources/kickassembler/unknown-symbol.asm +4 -0
- package/docs/toolchains/error-sources/oscar64/README.md +1 -0
- package/docs/toolchains/error-sources/oscar64/asm-addressing-mode.c +7 -0
- package/docs/toolchains/error-sources/oscar64/region-overflow.c +6 -0
- package/docs/toolchains/error-sources/oscar64/undefined-extern-var.c +5 -0
- package/docs/toolchains/error-sources/oscar64/undefined-extern.c +6 -0
- package/docs/toolchains/error-sources/oscar64/unknown-vic-field.c +6 -0
- package/docs/toolchains/error-sources/oscar64/void-main.c +3 -0
- package/docs/toolchains/kickassembler-reference.md +1020 -0
- package/docs/toolchains/memory-layout-planning.md +362 -0
- package/docs/toolchains/oscar64-headers-reference.md +583 -0
- package/docs/toolchains/oscar64-reference.md +892 -0
- package/docs/toolchains/petcat-reference.md +290 -0
- package/docs/toolchains/png2prg.md +188 -0
- package/docs/toolchains/release-disk.md +314 -0
- package/docs/toolchains/sidreloc.md +236 -0
- package/docs/toolchains/spindle-reference.md +487 -0
- package/docs/toolchains/tape-mastering.md +592 -0
- package/docs/toolchains/unit-testing-6502.md +281 -0
- package/docs/workflow/agent-harness.md +478 -0
- package/package.json +105 -0
- package/templates/_harness/CLAUDE.md.template +91 -0
- package/templates/_harness/PLAN.md.template +72 -0
- package/templates/_harness/check.py +442 -0
- package/templates/_harness/claude/settings.json +17 -0
- package/templates/_harness/gen-asm-header.py +96 -0
- package/templates/_harness/harness.mk +273 -0
- package/templates/_harness/hooks/plan-gate.py +185 -0
- package/templates/_harness/meter/frame_meter.asm +311 -0
- package/templates/_harness/meter/frame_meter.c +155 -0
- package/templates/_harness/meter/frame_meter.h +80 -0
- package/templates/_harness/zp-used.py +104 -0
- package/templates/action-puzzle/.claude/settings.json +17 -0
- package/templates/action-puzzle/.mcp.json +10 -0
- package/templates/action-puzzle/CLAUDE.md +120 -0
- package/templates/action-puzzle/Makefile +125 -0
- package/templates/action-puzzle/PLAN.md +388 -0
- package/templates/action-puzzle/README.md +240 -0
- package/templates/action-puzzle/expect.json +25 -0
- package/templates/action-puzzle/src/cave.c +280 -0
- package/templates/action-puzzle/src/cave.h +80 -0
- package/templates/action-puzzle/src/gen_autopilot.h +20 -0
- package/templates/action-puzzle/src/gen_caves.h +59 -0
- package/templates/action-puzzle/src/gen_notes.h +16 -0
- package/templates/action-puzzle/src/hiscore.c +152 -0
- package/templates/action-puzzle/src/hiscore.h +41 -0
- package/templates/action-puzzle/src/level.c +64 -0
- package/templates/action-puzzle/src/level.h +24 -0
- package/templates/action-puzzle/src/main.c +599 -0
- package/templates/action-puzzle/src/render.c +239 -0
- package/templates/action-puzzle/src/render.h +31 -0
- package/templates/action-puzzle/src/sound.c +158 -0
- package/templates/action-puzzle/src/sound.h +22 -0
- package/templates/action-puzzle/tools/disk_check.py +77 -0
- package/templates/action-puzzle/tools/drive.py +106 -0
- package/templates/action-puzzle/tools/gen.py +454 -0
- package/templates/action-puzzle/tools/model_check.py +49 -0
- package/templates/action-puzzle/tools/verdict_codes.py +24 -0
- package/templates/adventure/.claude/settings.json +17 -0
- package/templates/adventure/.mcp.json +10 -0
- package/templates/adventure/CLAUDE.md +118 -0
- package/templates/adventure/Makefile +113 -0
- package/templates/adventure/PLAN.md +396 -0
- package/templates/adventure/README.md +277 -0
- package/templates/adventure/expect.json +25 -0
- package/templates/adventure/src/engine.c +543 -0
- package/templates/adventure/src/engine.h +48 -0
- package/templates/adventure/src/gen_script.h +141 -0
- package/templates/adventure/src/gen_world.h +511 -0
- package/templates/adventure/src/main.c +439 -0
- package/templates/adventure/src/picture.c +83 -0
- package/templates/adventure/src/picture.h +16 -0
- package/templates/adventure/src/save.c +159 -0
- package/templates/adventure/src/save.h +25 -0
- package/templates/adventure/src/sound.c +71 -0
- package/templates/adventure/src/sound.h +16 -0
- package/templates/adventure/src/text.c +349 -0
- package/templates/adventure/src/text.h +40 -0
- package/templates/adventure/tools/disk_check.py +128 -0
- package/templates/adventure/tools/drive.py +119 -0
- package/templates/adventure/tools/gen.py +1033 -0
- package/templates/adventure/tools/world.py +356 -0
- package/templates/beat-em-up/.claude/settings.json +17 -0
- package/templates/beat-em-up/.mcp.json +10 -0
- package/templates/beat-em-up/CLAUDE.md +136 -0
- package/templates/beat-em-up/Makefile +96 -0
- package/templates/beat-em-up/PLAN.md +502 -0
- package/templates/beat-em-up/README.md +315 -0
- package/templates/beat-em-up/expect-gameover.json +8 -0
- package/templates/beat-em-up/expect.json +29 -0
- package/templates/beat-em-up/src/anim.c +70 -0
- package/templates/beat-em-up/src/art.c +344 -0
- package/templates/beat-em-up/src/autopilot.h +154 -0
- package/templates/beat-em-up/src/brute.c +273 -0
- package/templates/beat-em-up/src/enemy.c +281 -0
- package/templates/beat-em-up/src/engine.asm +512 -0
- package/templates/beat-em-up/src/fighter.c +384 -0
- package/templates/beat-em-up/src/game.h +269 -0
- package/templates/beat-em-up/src/hud.c +135 -0
- package/templates/beat-em-up/src/main.c +341 -0
- package/templates/beat-em-up/src/sound.c +44 -0
- package/templates/beat-em-up/src/street.c +93 -0
- package/templates/beat-em-up/src/verdict.h +523 -0
- package/templates/beat-em-up/src/view.c +362 -0
- package/templates/beat-em-up/tools/drive.py +105 -0
- package/templates/beat-em-up/tools/flickercheck.py +273 -0
- package/templates/demo/.claude/settings.json +17 -0
- package/templates/demo/.mcp.json +10 -0
- package/templates/demo/CLAUDE.md +129 -0
- package/templates/demo/Makefile +66 -0
- package/templates/demo/PLAN.md +401 -0
- package/templates/demo/README.md +322 -0
- package/templates/demo/expect.json +945 -0
- package/templates/demo/src/config.asm +80 -0
- package/templates/demo/src/framework.asm +390 -0
- package/templates/demo/src/main.asm +139 -0
- package/templates/demo/src/music.asm +197 -0
- package/templates/demo/src/part_main.asm +279 -0
- package/templates/demo/src/part_title.asm +79 -0
- package/templates/demo/src/parts.asm +43 -0
- package/templates/demo/src/tables.asm +73 -0
- package/templates/demo/src/verdict.asm +179 -0
- package/templates/demo/tools/audio.py +80 -0
- package/templates/demo/tools/gen_expect.py +167 -0
- package/templates/demo/tools/probe.py +95 -0
- package/templates/hello/.claude/settings.json +17 -0
- package/templates/hello/.mcp.json +10 -0
- package/templates/hello/CLAUDE.md +100 -0
- package/templates/hello/Makefile +38 -0
- package/templates/hello/PLAN.md +200 -0
- package/templates/hello/expect.json +20 -0
- package/templates/hello/src/main.c +161 -0
- package/templates/hello/src/sprite.asm +27 -0
- package/templates/hello-kick/.claude/settings.json +17 -0
- package/templates/hello-kick/.mcp.json +10 -0
- package/templates/hello-kick/CLAUDE.md +100 -0
- package/templates/hello-kick/Makefile +17 -0
- package/templates/hello-kick/PLAN.md +199 -0
- package/templates/hello-kick/expect.json +20 -0
- package/templates/hello-kick/src/main.asm +233 -0
- package/templates/platformer/.claude/settings.json +17 -0
- package/templates/platformer/.mcp.json +10 -0
- package/templates/platformer/CLAUDE.md +125 -0
- package/templates/platformer/Makefile +86 -0
- package/templates/platformer/PLAN.md +360 -0
- package/templates/platformer/README.md +277 -0
- package/templates/platformer/expect.json +32 -0
- package/templates/platformer/src/actors.c +289 -0
- package/templates/platformer/src/anim.c +51 -0
- package/templates/platformer/src/art.c +212 -0
- package/templates/platformer/src/autopilot.h +30 -0
- package/templates/platformer/src/engine.asm +253 -0
- package/templates/platformer/src/game.h +248 -0
- package/templates/platformer/src/hud.c +90 -0
- package/templates/platformer/src/level.c +184 -0
- package/templates/platformer/src/main.c +306 -0
- package/templates/platformer/src/player.c +268 -0
- package/templates/platformer/src/sound.c +42 -0
- package/templates/platformer/src/verdict.h +206 -0
- package/templates/platformer/src/view.c +331 -0
- package/templates/platformer/stage-expect.json +6 -0
- package/templates/platformer/tools/drive.py +112 -0
- package/templates/platformer/tools/tearcheck.py +229 -0
- package/templates/shmup-vertical/.claude/settings.json +17 -0
- package/templates/shmup-vertical/.mcp.json +10 -0
- package/templates/shmup-vertical/CLAUDE.md +137 -0
- package/templates/shmup-vertical/Makefile +131 -0
- package/templates/shmup-vertical/PLAN.md +569 -0
- package/templates/shmup-vertical/README.md +189 -0
- package/templates/shmup-vertical/expect.json +38 -0
- package/templates/shmup-vertical/src/bullets.c +158 -0
- package/templates/shmup-vertical/src/bullets.h +35 -0
- package/templates/shmup-vertical/src/display.c +239 -0
- package/templates/shmup-vertical/src/display.h +40 -0
- package/templates/shmup-vertical/src/game.h +85 -0
- package/templates/shmup-vertical/src/glyph.asm +358 -0
- package/templates/shmup-vertical/src/hiscore.c +141 -0
- package/templates/shmup-vertical/src/hiscore.h +16 -0
- package/templates/shmup-vertical/src/hit.asm +180 -0
- package/templates/shmup-vertical/src/hitbox.c +59 -0
- package/templates/shmup-vertical/src/hitbox.h +25 -0
- package/templates/shmup-vertical/src/kernel.asm +330 -0
- package/templates/shmup-vertical/src/level.c +174 -0
- package/templates/shmup-vertical/src/level.h +27 -0
- package/templates/shmup-vertical/src/main.c +824 -0
- package/templates/shmup-vertical/src/mux.asm +321 -0
- package/templates/shmup-vertical/src/sound.asm +255 -0
- package/templates/shmup-vertical/src/step.asm +169 -0
- package/templates/shmup-vertical/src/waves.c +195 -0
- package/templates/shmup-vertical/src/waves.h +33 -0
- package/templates/shmup-vertical/stage-expect.json +6 -0
- package/templates/shmup-vertical/tools/drive.py +152 -0
- package/templates/shmup-vertical/tools/joytest.py +159 -0
- package/templates/shmup-vertical/tools/meter.py +15 -0
- package/templates/shmup-vertical/tools/phases.py +73 -0
|
@@ -0,0 +1,478 @@
|
|
|
1
|
+
---
|
|
2
|
+
tool: agent-harness
|
|
3
|
+
tool_kind: reference-catalog
|
|
4
|
+
maintainer: bdgscotland
|
|
5
|
+
license: BSD-3-Clause
|
|
6
|
+
home_url: https://github.com/bdgscotland/c64-kb
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
<!-- doc-type: toolchain-reference -->
|
|
10
|
+
|
|
11
|
+
# The agent harness: build, run, shoot, check, measure
|
|
12
|
+
|
|
13
|
+
## Tool
|
|
14
|
+
|
|
15
|
+
`templates/_harness` is the loop every starter in `templates/` shares. A
|
|
16
|
+
starter's Makefile sets a few variables and includes `harness.mk`; from then
|
|
17
|
+
on `make shot check` builds the program, runs it headless in VICE on PAL and
|
|
18
|
+
on NTSC with scripted input, and grades both exit screenshots against the
|
|
19
|
+
expectations the starter wrote down. A frame meter prints the program's
|
|
20
|
+
measured cycle cost where the checker can read it back. `templates/hello`
|
|
21
|
+
(Oscar64 calling KickAssembler) and `templates/hello-kick` (KickAssembler
|
|
22
|
+
alone) are the smallest starters that use every target.
|
|
23
|
+
|
|
24
|
+
Every figure on this page was measured on 2026-09-23 with VICE x64sc 3.10
|
|
25
|
+
(the windowless build), KickAssembler 5.25, Oscar64 as named in `CLAUDE.md`,
|
|
26
|
+
c1541 from VICE 3.10 and GNU Make 3.81, unless it says otherwise.
|
|
27
|
+
|
|
28
|
+
## Starting a project
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm run new-project -- hello ~/c64/mygame # or hello-kick; --list names the starters
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`scripts/new-project.ts` copies the starter whole, dotfiles included,
|
|
35
|
+
vendors `templates/_harness` into `<dir>/harness`, writes `.mcp.json` with
|
|
36
|
+
this checkout's absolute `dist/cli.js`, and writes `local.mk` (read by the
|
|
37
|
+
harness first) with `C64KB` set to this checkout and the tool paths this
|
|
38
|
+
machine has. It proves the copy with `make shot check`, then renames the
|
|
39
|
+
starter's `PLAN.md` to `PLAN-<starter>-example.md` and puts a blank one in
|
|
40
|
+
its place, so the new program is held by the plan gate until its own plan
|
|
41
|
+
is filled.
|
|
42
|
+
|
|
43
|
+
## The loop
|
|
44
|
+
|
|
45
|
+
| Command | What it does |
|
|
46
|
+
|---|---|
|
|
47
|
+
| `make` | Builds `build/<name>.prg` once `PLAN.md` passes (see "The plan gate") |
|
|
48
|
+
| `make run` | The windowed x64sc with the normal build, for a human; joystick port 2 on the numeric keypad (8 2 4 6, fire 0) |
|
|
49
|
+
| `make shot` | Builds the AUTOPILOT variant and writes `shots/pal.png` and `shots/ntsc.png` at the pinned cycle counts |
|
|
50
|
+
| `make check` | `check.py expect.json shots/pal.png shots/ntsc.png`; exit 1 names each failed check |
|
|
51
|
+
| `make selftest` | Builds with FORCE_FAULT and shoots it; passes only when `check.py` exits 1 with FAIL lines |
|
|
52
|
+
| `make disk` | `build/<name>.d64` with the PRG and `DISK_FILES`, then lists it |
|
|
53
|
+
| `make claims` | c64-kb's `scripts/claims-watch.ts` over the AUTOPILOT PRG, when the checkout has it |
|
|
54
|
+
| `make released` | With `OSCAR64_RELEASED=<path>`: the autopilot build from that compiler, shot on PAL and NTSC and graded with the same `expect.json`. On v1.32.273, platformer graded 7 of 23 (a miscompile, #30) and action-puzzle 41 of 41 |
|
|
55
|
+
| `make zp` | The zero-page addresses the compiled C touches, read from Oscar64's listing; with `ZP_CLAIM='$02-$55'` a gate |
|
|
56
|
+
| `make clean` | Removes `build/` and `shots/` |
|
|
57
|
+
|
|
58
|
+
The headless runs use `-default -warp +sound +autostart-delay-random
|
|
59
|
+
-autostartprgmode 1 -limitcycles N`, add `-model ntsc` for NTSC, and are
|
|
60
|
+
wrapped in `timeout 180`. The windowless x64sc at
|
|
61
|
+
`~/Developer/c64/vice-headless/bin/x64sc` is used when it exists. A shot is
|
|
62
|
+
re-taken when the PRG, the starter's Makefile or the pin changes: the pin
|
|
63
|
+
is a stamp file named by its cycle count.
|
|
64
|
+
|
|
65
|
+
`npm run verify:templates` makes a project from each starter with an
|
|
66
|
+
`expect.json`, as new-project does, in a temporary directory, and runs
|
|
67
|
+
`make`, `make shot check` and `make disk` there (`--selftest` adds
|
|
68
|
+
`make selftest` and every target the starter lists in `VERIFY_TARGETS`,
|
|
69
|
+
`--only <name>` picks one). A starter's own proof targets (action-puzzle's
|
|
70
|
+
`disktest`, `modelcheck` and `selftest-scan`, adventure's `disktest`,
|
|
71
|
+
platformer's `tearcheck`, shmup-vertical's `stage`, demo's `probe`) prove
|
|
72
|
+
fixes that `make check` cannot see: the adventure's three save-validation
|
|
73
|
+
checks, for instance, fail only in `disktest`. Measured 2026-09-23: seven
|
|
74
|
+
starters with `--selftest` and their targets, 7 of 7, about 3.5 minutes.
|
|
75
|
+
|
|
76
|
+
## A starter's files
|
|
77
|
+
|
|
78
|
+
| File | Holds |
|
|
79
|
+
|---|---|
|
|
80
|
+
| `Makefile` | `NAME`, `C_MAIN` and/or `KICK_SRC`, `SHOT_CYCLES_PAL`, `SHOT_CYCLES_NTSC`, `CLAIMS_ARGS`, optional `DISK_FILES`, then `include $(HARNESS)/harness.mk`, with a clear error when the harness is missing |
|
|
81
|
+
| `src/` | The program. `AUTOPILOT` selects scripted input; `FORCE_FAULT` must make the program's own verdict fail and move something a screenshot check sees |
|
|
82
|
+
| `expect.json` | The checks `check.py` runs on both shots |
|
|
83
|
+
| `PLAN.md` | The plan, with the pasted output of `check-compatibility` and `plan-budget` |
|
|
84
|
+
| `CLAUDE.md` | `_harness/CLAUDE.md.template` plus a section on this starter |
|
|
85
|
+
| `.claude/settings.json` | `_harness/claude/settings.json`: the plan gate as a PreToolUse hook |
|
|
86
|
+
|
|
87
|
+
`HARNESS` is `./harness` in a project and `../_harness` inside this
|
|
88
|
+
repository. The tools come from `local.mk`, then `OSCAR64`, `KICKASS_JAR`,
|
|
89
|
+
`X64SC`, `X64SC_WINDOWED`, `C1541` and `C64KB` in the environment, then
|
|
90
|
+
PATH and this machine's default locations; `make tools` prints them.
|
|
91
|
+
|
|
92
|
+
## Reading the screenshots
|
|
93
|
+
|
|
94
|
+
`check.py` takes its geometry and palette from
|
|
95
|
+
[vice-reference](../runtime/vice-reference.md), "Reading the exit
|
|
96
|
+
screenshot": PAL 384 x 272 with screenshot row = raster line - 16; NTSC
|
|
97
|
+
384 x 247 with row = line - 28, NTSC lines 0 to 11 landing on rows 235 to
|
|
98
|
+
246; x = VIC-II X coordinate + 8; text cell (r, c) at x = 32 + 8c,
|
|
99
|
+
y = 35 + 8r on PAL and 23 + 8r on NTSC; sixteen exact RGB triples per
|
|
100
|
+
model.
|
|
101
|
+
|
|
102
|
+
One geometry fact was measured here: a sprite whose Y register holds y is
|
|
103
|
+
drawn from raster line y + 1. hello's sprite at X 188, Y 116 covered
|
|
104
|
+
screenshot x 196 to 219 and rows 101 to 121 on PAL, 89 to 109 on NTSC,
|
|
105
|
+
504 pixels each: lines 117 to 137 on both. A check written for line y
|
|
106
|
+
fails; the first draft of hello's `expect.json` did.
|
|
107
|
+
|
|
108
|
+
`check.py` validates `expect.json` before it grades: at least one check and
|
|
109
|
+
one `verdict` check, the keys each type needs, colours 0 to 15, and every
|
|
110
|
+
point and area inside the picture on each model the check names. A fault
|
|
111
|
+
is exit 2 with the check's name, never a pass and never a traceback.
|
|
112
|
+
|
|
113
|
+
| Check type | Passes when |
|
|
114
|
+
|---|---|
|
|
115
|
+
| `verdict` | The border sample point is colour 5. Colour 2 is the program's own FAIL; anything else means it never reached its verdict |
|
|
116
|
+
| `pixel` | The point has the colour index. The point is `x`/`y`, `vic_x`/`line`, or `row`/`col` (a cell's centre) |
|
|
117
|
+
| `rect` | Every pixel of an area (`vic_x`, `line`, `width`, `height`) has the colour: a raster bar, or a span with height 1 |
|
|
118
|
+
| `sprite` | The pixels of the colour inside `search` (default the expected box grown by 16) have exactly the expected bounding box |
|
|
119
|
+
| `text` | The cells from `row`, `col` read `text` |
|
|
120
|
+
| `same` | Every pixel of the `cells` rectangle, or of an `area`, has the same colour index on PAL and NTSC |
|
|
121
|
+
| `meter` | The meter's readout is there; optional `frames` must match; worst fits `max_worst` (default one frame: 19,656 cycles PAL, 17,095 NTSC); typical is at least 1 (recording has finished) |
|
|
122
|
+
|
|
123
|
+
Text is decoded against the power-on ROM set (`chargen-901225-01.bin`;
|
|
124
|
+
`C64_CHARGEN` overrides the path), or `"charset": "rom-lower"`, or a
|
|
125
|
+
2,048-byte glyph file named by the check, with or without a two-byte load
|
|
126
|
+
address. A cell's ink is every pixel that is not its majority colour, so no
|
|
127
|
+
background colour is needed; multicolour cells do not decode. The meter's
|
|
128
|
+
cells need glyphs for 0 to 9, F, W and T in the set on screen.
|
|
129
|
+
|
|
130
|
+
The verdict follows the result-byte contract in vice-reference, "Verifying
|
|
131
|
+
a run without a human": `$02FF` = `$01` and a green border on pass, `$02`
|
|
132
|
+
and red on fail.
|
|
133
|
+
|
|
134
|
+
## Linking KickAssembler into Oscar64
|
|
135
|
+
|
|
136
|
+
Oscar64 has no object linker, and a `.prg` given on its command line is
|
|
137
|
+
ignored ([oscar64-reference](../toolchains/oscar64-reference.md), "Calling
|
|
138
|
+
KickAssembler code from Oscar64"). The old `c64-game-starter`, since removed, fed
|
|
139
|
+
one in that way. The harness uses the placed-blob method that page describes, and
|
|
140
|
+
automates the addresses:
|
|
141
|
+
|
|
142
|
+
1. KickAssembler assembles `KICK_SRC` with `-binfile -symbolfile`:
|
|
143
|
+
`build/asm.bin` is the raw bytes from the lowest address, no load
|
|
144
|
+
address; `build/<src>.sym` holds every label with its scope.
|
|
145
|
+
2. `gen-asm-header.py` writes `build/asm.h`: `ASM_ORG` from KickAssembler's
|
|
146
|
+
memory map, `ASM_END` = `ASM_ORG` + the blob's size, `ASM_<LABEL>` for a
|
|
147
|
+
top-level label and `ASM_<SCOPE>_<LABEL>` inside a scope or namespace. It
|
|
148
|
+
refuses, naming both, two labels that give one name (`put_sprite` and
|
|
149
|
+
`Put_Sprite`), and a label that would redefine `ASM_ORG`, `ASM_END`,
|
|
150
|
+
`ASM_SIZE` or `ASM_H`. The `.sym` file is read, not the `-vicesymbols`
|
|
151
|
+
file, because the latter flattens scopes into `loop__0`, `loop__1`,
|
|
152
|
+
names that change with source order.
|
|
153
|
+
3. The C side places the blob and calls it. Oscar64 expands the macros
|
|
154
|
+
inside `#pragma region` and inside `__asm`, and finds `#embed "asm.bin"`
|
|
155
|
+
through `-i=build`.
|
|
156
|
+
|
|
157
|
+
hello's KickAssembler half, whole:
|
|
158
|
+
|
|
159
|
+
```asm
|
|
160
|
+
// sprite.asm: sprite 0 to (spr_x, spr_y); the parameters live in the blob.
|
|
161
|
+
* = $0900 "asm"
|
|
162
|
+
|
|
163
|
+
put_sprite:
|
|
164
|
+
lda spr_x
|
|
165
|
+
sta $d000
|
|
166
|
+
lda $d010
|
|
167
|
+
and #$fe
|
|
168
|
+
ldx spr_x+1
|
|
169
|
+
beq !+
|
|
170
|
+
ora #$01
|
|
171
|
+
!: sta $d010
|
|
172
|
+
lda spr_y
|
|
173
|
+
sta $d001
|
|
174
|
+
rts
|
|
175
|
+
|
|
176
|
+
spr_x: .word 0
|
|
177
|
+
spr_y: .byte 0
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
The header the harness wrote from it, and the C that uses it (from
|
|
181
|
+
`templates/hello/src/main.c`, which `verify:templates` builds):
|
|
182
|
+
|
|
183
|
+
```text
|
|
184
|
+
#define ASM_ORG 0x0900
|
|
185
|
+
#define ASM_END 0x091f
|
|
186
|
+
#define ASM_SIZE 31
|
|
187
|
+
#if ASM_ORG < 0x0880
|
|
188
|
+
#error "the KickAssembler blob starts below $0880, over the Oscar64 startup code: raise its * = address"
|
|
189
|
+
#endif
|
|
190
|
+
#define ASM_PUT_SPRITE 0x0900
|
|
191
|
+
#define ASM_SPR_X 0x091c
|
|
192
|
+
#define ASM_SPR_Y 0x091e
|
|
193
|
+
|
|
194
|
+
#pragma section( asmcode, 0 )
|
|
195
|
+
#pragma region( asmreg, ASM_ORG, 0x1000, , , { asmcode } )
|
|
196
|
+
#pragma region( main, 0x1000, 0xa000, , , { code, data, bss, heap, stack } )
|
|
197
|
+
#pragma data( asmcode )
|
|
198
|
+
__export const char asm_blob[] = {
|
|
199
|
+
#embed "asm.bin"
|
|
200
|
+
};
|
|
201
|
+
#pragma data( data )
|
|
202
|
+
...
|
|
203
|
+
SPR_X = x; // *(volatile unsigned *)ASM_SPR_X
|
|
204
|
+
SPR_Y = y;
|
|
205
|
+
__asm { jsr ASM_PUT_SPRITE }
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Evidence, rung 1:
|
|
209
|
+
|
|
210
|
+
- `build/hello.map`: `0900 - 1000 : 091f, 001f, asmreg` and
|
|
211
|
+
`0900 - 091f : asm_blob, DATA:asmcode`; `main` starts at `$1000`.
|
|
212
|
+
- `build/hello.asm`: `1118 : 20 00 09 JSR $0900 ; (asm_blob[0] + 0)`.
|
|
213
|
+
- The AUTOPILOT build moves the sprite through the scripted path, reads
|
|
214
|
+
`$D000`, `$D001` and `$D010` back at frame 150, and grades them; the
|
|
215
|
+
screenshots show the green border and the sprite at X 188, lines 117 to
|
|
216
|
+
137, on PAL and NTSC. Only the KickAssembler routine writes those
|
|
217
|
+
registers, so the call and its arguments arrived.
|
|
218
|
+
|
|
219
|
+
Rules the mechanism brings. The blob lives between `$0880` and `$1000`.
|
|
220
|
+
Below `$0880` it would overlap Oscar64's startup code, which the linker
|
|
221
|
+
allows in silence (a blob at `$0810` linked, and the program never
|
|
222
|
+
started); `asm.h`'s `#error` stops that build with "error 3032: the
|
|
223
|
+
KickAssembler blob starts below $0880". Past `$1000` the link fails with
|
|
224
|
+
"Could not place object". Arguments go through bytes the blob owns, not
|
|
225
|
+
Oscar64's zero page. The compiler's fixed registers start at `$02`
|
|
226
|
+
(`BC_REG_WORK_Y`) and each function's temporaries run from `$43`
|
|
227
|
+
(`BC_REG_TMP`) up by that function's own temp count, past
|
|
228
|
+
`BC_REG_TMP_SAVED` (`$53`): temps above it are saved and restored around
|
|
229
|
+
calls but still live in zero page (`MachineTypes.cpp`, `InterCode.cpp`,
|
|
230
|
+
read). So the top depends on the program; `make zp` reads it from the
|
|
231
|
+
build's listing (see "Zero page a build uses"). An earlier version of this
|
|
232
|
+
paragraph gave `$02` to `$52` as the whole range; hello's code reaches
|
|
233
|
+
`$55`, platformer's `$5B`, shmup-vertical's `$5D`.
|
|
234
|
+
The routine may change A, X and Y. A pure KickAssembler starter leaves
|
|
235
|
+
`C_MAIN` empty and `KICK_SRC` is the whole program.
|
|
236
|
+
|
|
237
|
+
## Zero page a build uses
|
|
238
|
+
|
|
239
|
+
`zp-used.py` reads the `.asm` listing Oscar64 writes beside the PRG. A
|
|
240
|
+
listed instruction two bytes long that is not immediate and not a branch
|
|
241
|
+
addresses zero page through its second byte; the BASIC stub at
|
|
242
|
+
`$0801`-`$080C`, which the listing decodes as instructions, is skipped.
|
|
243
|
+
It sees the compiled C and inline `__asm`; a KickAssembler blob is data
|
|
244
|
+
in the listing, so its zero page is what its own source says.
|
|
245
|
+
|
|
246
|
+
Measured on 2026-09-23 with the local Oscar64: hello's code touches
|
|
247
|
+
`$0D`-`$11`, `$13`, `$16`, `$19`-`$20`, `$23`-`$24` and `$43`-`$55` (plus
|
|
248
|
+
`$00` from the startup's indexed clear); platformer's reaches `$5B` and
|
|
249
|
+
shmup-vertical's `$5D`. claims-watch agreed on hello: its run stored to
|
|
250
|
+
`$53`-`$55`, outside the `$02`-`$52` it then claimed.
|
|
251
|
+
|
|
252
|
+
## Text under another YSCROLL
|
|
253
|
+
|
|
254
|
+
`text` and `meter` checks read cells on the grid a screen with YSCROLL 3
|
|
255
|
+
draws (rows start on line 51 + 8r). A panel that starts on another line,
|
|
256
|
+
as the one under a vertically scrolled playfield does (YSCROLL 7, rows on
|
|
257
|
+
line 55 + 8r), is read with `"dy": 4`: the pixel offset below that grid,
|
|
258
|
+
0 to 7. Measured on a panel at line 215 with YSCROLL 7: with `"dy": 4` the
|
|
259
|
+
score row decoded as written, without it every cell read `?`.
|
|
260
|
+
|
|
261
|
+
## A fresh disk per run
|
|
262
|
+
|
|
263
|
+
With `SHOT_DISK = 1` each headless run attaches its own copy of
|
|
264
|
+
`build/<name>.d64` (`shots/pal.d64`, `shots/ntsc.d64`), made just before the
|
|
265
|
+
run. VICE writes a save back into the image it attached, so two runs on one
|
|
266
|
+
shared image start from different disks and the pinned shot moves. Measured
|
|
267
|
+
with hello and `SHOT_DISK=1`: two `make shot` runs gave byte-identical
|
|
268
|
+
PNGs and `build/hello.d64` kept its checksum.
|
|
269
|
+
|
|
270
|
+
## The frame meter
|
|
271
|
+
|
|
272
|
+
`meter/frame_meter.h` (Oscar64) and `meter/frame_meter.asm` (KickAssembler
|
|
273
|
+
macros) implement one contract. The program brackets its frame's work with
|
|
274
|
+
`METER_START` / `METER_STOP` (`FrameMeterStart()` / `FrameMeterStop()`),
|
|
275
|
+
then prints. Work split between a main loop and IRQ handlers is summed:
|
|
276
|
+
`METER_START` ... `METER_PAUSE` as often as needed, `METER_STOP` once a
|
|
277
|
+
frame. Brackets must not nest. The readout is `F<frames> W<worst>
|
|
278
|
+
T<typical>`, five digits each, 20 cells from row 24, column 20.
|
|
279
|
+
|
|
280
|
+
- **Timer.** CIA2 timer A, counting phi2 cycles, force-loaded with `$FFFF`
|
|
281
|
+
at start and stopped before its two bytes are read, as in
|
|
282
|
+
[raster-profile-bars](../recipes/oscar64/raster-profile-bars.md). The
|
|
283
|
+
KERNAL IRQ uses CIA1 timer A and the KERNAL serial routines write CIA1
|
|
284
|
+
timer B (issue #35), so neither collides. CIA2 timer A is the KERNAL's
|
|
285
|
+
RS-232 bit timer: no device 2 while the meter runs. Init masks timer A's
|
|
286
|
+
NMI only (`$DD0D` = `$01`).
|
|
287
|
+
- **What it counts.** Wall time between the two stores: badline and sprite
|
|
288
|
+
DMA steals and any interrupt that lands inside a bracket are in the
|
|
289
|
+
figure. The empty bracket's own count is subtracted: the least of four
|
|
290
|
+
tries at raster line 0, with interrupts off, where no DMA falls. More
|
|
291
|
+
than 65,535 cycles reads 65,535 (the underflow flag in `$DD0D`).
|
|
292
|
+
- **Recording.** The meter records the first `hold` frames (1 to 255) and
|
|
293
|
+
then stops, so a pinned screenshot shows fixed figures and `check.py` can
|
|
294
|
+
require the count. Make `hold` the autopilot script's play frames, so no
|
|
295
|
+
title or idle frame counts.
|
|
296
|
+
- **Worst** is the largest recorded frame. **Typical** is the median of the
|
|
297
|
+
recorded frames, computed when recording stops (0 until then): a cost
|
|
298
|
+
some play frame took, with at least half the frames at or under it. The
|
|
299
|
+
C meter finds it by selection (Wirth's FIND). Its first version sorted
|
|
300
|
+
the samples by insertion, which held the platformer starter's main loop
|
|
301
|
+
for about 94 frames (1.85M cycles) at its 255th play frame; with the
|
|
302
|
+
selection its verdict came about 2M cycles sooner. The KickAssembler
|
|
303
|
+
meter still sorts by insertion (not re-measured here). That
|
|
304
|
+
is the `cycles_per_frame_typical` of
|
|
305
|
+
[CONVENTIONS-techniques](../CONVENTIONS-techniques.md), the frame play
|
|
306
|
+
spends most of its time on, when the recorded frames are play. An
|
|
307
|
+
earlier version used the mean of the last 16 frames: hello's figure was
|
|
308
|
+
then the mean of idle frames after its script, and an alternating load
|
|
309
|
+
read a cost no frame took.
|
|
310
|
+
- **Lost frames are not the meter's job, and are easy to count wrong.**
|
|
311
|
+
The meter reports cost, not lateness: a starter that must not drop a
|
|
312
|
+
frame counts drops itself. Count after the work: when the frame's work
|
|
313
|
+
ends, test whether the next frame's IRQ has already fired (its flag or
|
|
314
|
+
counter), and count that as a lost frame. A check at wake-up for a
|
|
315
|
+
counter that moved by more than one misses every single overrun: work
|
|
316
|
+
that ends just after the next IRQ still sees it move by exactly one.
|
|
317
|
+
Measured on shmup-vertical 7974a7a: one frame made ~2,400 cycles late
|
|
318
|
+
left the program's `wait_frame` counter at `OVERRUNS 00`, and a detector
|
|
319
|
+
that tests the frame flag when the work ends found NTSC joystick play
|
|
320
|
+
losing a frame in 6 of 15 runs. The demo's frame slot, which must end
|
|
321
|
+
before a split line, reads the raster when its work ends instead.
|
|
322
|
+
- **Build switch.** `FRAME_METER` defaults to `AUTOPILOT`. Without it every
|
|
323
|
+
macro is empty and the release carries none of the meter.
|
|
324
|
+
- **Interrupts.** The KERNAL serial routines end in `CLI`: the ROM bytes at
|
|
325
|
+
`$EDAB`, `$EDB5`, `$EDDB` and `$EE82` are `58 60` or `58 18` (read from
|
|
326
|
+
`kernal-901227-03.bin`). A program that runs with the KERNAL IRQ off must
|
|
327
|
+
`SEI` again after any disk call, or that IRQ lands inside its brackets.
|
|
328
|
+
|
|
329
|
+
Calibration, rung 1, C and KickAssembler, PAL and NTSC:
|
|
330
|
+
|
|
331
|
+
| Bracketed code | Cycles by arithmetic | Read |
|
|
332
|
+
|---|---|---|
|
|
333
|
+
| `ldx #200` / `dex` / `bne` | 2 + 199 x 5 + 4 = 1,001 | `W01001 T01001` |
|
|
334
|
+
| A 12-cycle table lookup (`lda abs`, `and #3`, `tay`, `ldx abs,y`) replacing `ldx #`, then `inc abs`: 1,017 for 200, 517 for 100, one frame in four at 200 | 1,001 - 2 + 12 + 6 = 1,017; 501 - 2 + 12 + 6 = 517 | `W01017 T00517` over 48 frames |
|
|
335
|
+
| Two brackets a frame, 1,001 and 501, untimed work between | 1,502 | `W01502 T01502` |
|
|
336
|
+
|
|
337
|
+
The C meter's `meter_init` started at raster lines `$33`, `$37`, `$60`,
|
|
338
|
+
`$91` and `$F8` (badlines among them) read the same `W01017 T00517` each
|
|
339
|
+
time. The review of this harness found that the earlier single calibration
|
|
340
|
+
could land on DMA and read 5 cycles low; that is what the line-0 minimum
|
|
341
|
+
fixes. The same review saw W move between 1,510 and 1,538 cycles, in steps
|
|
342
|
+
of 14, with code layout alone, which it put down to branches crossing pages
|
|
343
|
+
(not re-measured here): compare two builds' W knowing that.
|
|
344
|
+
|
|
345
|
+
hello's figures: worst 194, typical 172 cycles (195 and 173 since the
|
|
346
|
+
selection changed the meter's code layout); hello-kick's: worst 178,
|
|
347
|
+
typical 154; each over the script's 144 play frames and the same on PAL and
|
|
348
|
+
NTSC. Both bracket from raster line 250, below the last badline (`$F7`),
|
|
349
|
+
and the sprite is on lines 117 to 137, so no DMA falls in the bracket. The
|
|
350
|
+
grading at frame 150 runs after `METER_STOP` and is in neither figure.
|
|
351
|
+
|
|
352
|
+
## The plan gate
|
|
353
|
+
|
|
354
|
+
`hooks/plan-gate.py` passes `PLAN.md` when it has no `FILL:` line left,
|
|
355
|
+
holds check-compatibility's output (a `# Compatibility: a + b` line and its
|
|
356
|
+
`**Verdict:**` line) and plan-budget's (`# Budget plan:`, `Techniques:`, a
|
|
357
|
+
`## play (` section with its `Range` line) for the same techniques, and
|
|
358
|
+
lists each of them as a row of its Techniques table. With `C64KB`
|
|
359
|
+
reachable, `make` also re-runs check-compatibility on the pasted names and
|
|
360
|
+
wants the same Verdict line; the result is cached on `PLAN.md`'s hash.
|
|
361
|
+
|
|
362
|
+
Every PRG depends on the gate, so `make`, `shot`, `check`, `selftest`,
|
|
363
|
+
`disk`, `claims` and `run` all stop while it fails. As a PreToolUse hook it
|
|
364
|
+
blocks (exit 2) an Edit, MultiEdit, Write or NotebookEdit under `src/`,
|
|
365
|
+
after resolving the path with realpath. `make PLAN_GATE=off` is the
|
|
366
|
+
deliberate override. It replaces the old starters' `.kb-briefing-done`
|
|
367
|
+
marker, which `touch` satisfied.
|
|
368
|
+
|
|
369
|
+
Measured: two hand-typed heading lines fail it; a pasted Verdict changed
|
|
370
|
+
from WARNINGS to COMPATIBLE fails the re-run; a Write to `lib/../src/x.c`
|
|
371
|
+
and one under a `CLAUDE_PROJECT_DIR` with a trailing slash are blocked;
|
|
372
|
+
hello's plan passes. It cannot catch outputs edited by hand into the right
|
|
373
|
+
shape with the right verdict, or a write to `src/` made through a shell
|
|
374
|
+
command, which the hook never sees.
|
|
375
|
+
|
|
376
|
+
## make claims
|
|
377
|
+
|
|
378
|
+
When `$(C64KB)/scripts/claims-watch.ts` exists, `make claims` runs it from
|
|
379
|
+
the c64-kb checkout over the AUTOPILOT PRG with the starter's
|
|
380
|
+
`CLAIMS_ARGS`; otherwise it prints that the script is not available and
|
|
381
|
+
exits 0. The script lands with issue #22 step 6 and is not on this branch.
|
|
382
|
+
Run against the copy on the `onto22-watch` branch, hello first failed:
|
|
383
|
+
Oscar64's zero page and the `$FF` store to `$DC00` were undeclared, and so
|
|
384
|
+
was the meter's one `$DD0D` store, which claims-watch counts against
|
|
385
|
+
`cia2_timer_b` and `cia2_tod` as well as `cia2_timer_a`. With
|
|
386
|
+
`zero_page $02-$52` and `cia1_port_a` claimed and all three CIA2 units
|
|
387
|
+
declared as harness, hello and hello-kick both reported `PASS: 0 stores in 0
|
|
388
|
+
violation groups`. Against main's claims-watch on 2026-09-23 hello failed
|
|
389
|
+
again: 309 stores to `$53`-`$55` outside the claim, and the KERNAL IRQ's
|
|
390
|
+
zero-page stores with no routine declared. Its claim is now
|
|
391
|
+
`zero_page $02-$55` with `--kernal IRQ`, and `make claims` reports `PASS: 0
|
|
392
|
+
stores in 0 violation groups`.
|
|
393
|
+
|
|
394
|
+
## End-to-end transcript
|
|
395
|
+
|
|
396
|
+
A project made from hello outside the repository, then each target in
|
|
397
|
+
turn. The last lines of each:
|
|
398
|
+
|
|
399
|
+
```text
|
|
400
|
+
$ npm run new-project -- hello <scratch>/mygame
|
|
401
|
+
PASS PAL frame meter, the script's 144 play frames: frames 144, worst 194, typical 172 cycles (CIA2 timer A; limit 19656)
|
|
402
|
+
PASS NTSC frame meter, the script's 144 play frames: frames 144, worst 194, typical 172 cycles (CIA2 timer A; limit 17095)
|
|
403
|
+
check: 15 of 15 passed
|
|
404
|
+
new-project: ready. The starter's plan is now PLAN-hello-example.md; PLAN.md is blank.
|
|
405
|
+
$ make shot check # the blank plan
|
|
406
|
+
plan-gate: the plan does not pass, so nothing is built.
|
|
407
|
+
11 FILL: placeholder(s) left
|
|
408
|
+
$ cp PLAN-hello-example.md PLAN.md; make
|
|
409
|
+
oscar64 -tm=c64 -O2 -i=<project>/build -i=<project>/harness/meter -o=build/hello.prg src/main.c
|
|
410
|
+
$ make selftest
|
|
411
|
+
selftest: PASS, check.py rejected the FORCE_FAULT build
|
|
412
|
+
$ make disk
|
|
413
|
+
0 "hello " 01 2a
|
|
414
|
+
10 "hello" prg
|
|
415
|
+
654 blocks free.
|
|
416
|
+
$ make claims # C64KB = this branch
|
|
417
|
+
claims: not available. <c64-kb>/scripts/claims-watch.ts does not exist (it lands in c64-kb with issue #22 step 6).
|
|
418
|
+
claims: set C64KB=/path/to/c64-kb to a checkout that has it. Nothing was checked.
|
|
419
|
+
$ make claims C64KB=<a checkout of onto22-watch>
|
|
420
|
+
PASS: 0 stores in 0 violation groups
|
|
421
|
+
$ npm run verify:templates -- --selftest # from this repository
|
|
422
|
+
verify-templates: 2 of 2 starters passed
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
The FORCE_FAULT build fails four checks on both models, not only its own verdict: the
|
|
426
|
+
border and verdict text, and the sprite's box and solidity, because it ends
|
|
427
|
+
at X 189. The disk image boots: `x64sc -autostart build/hello.d64` for
|
|
428
|
+
25,000,000 cycles on PAL showed `HELLO HARNESS` on row 1. The shots are
|
|
429
|
+
stable: hello's and hello-kick's PAL pictures at 7,000,000 and 8,000,000
|
|
430
|
+
cycles, and their NTSC pictures at 8,000,000 and 12,000,000, were identical
|
|
431
|
+
pixel for pixel, because nothing on screen changes after the grade.
|
|
432
|
+
|
|
433
|
+
## Writing a starter
|
|
434
|
+
|
|
435
|
+
1. Make a project from `hello` (C with a KickAssembler part) or
|
|
436
|
+
`hello-kick` (KickAssembler alone) under `templates/<name>`, or copy one.
|
|
437
|
+
2. Fill `PLAN.md` from `game-briefing`, `check-compatibility` and
|
|
438
|
+
`plan-budget` before any code.
|
|
439
|
+
3. Give the program an AUTOPILOT script that plays from its first frame, a
|
|
440
|
+
verdict after the script that reads real state back, outside the
|
|
441
|
+
meter's bracket, and a FORCE_FAULT that turns it red and moves something
|
|
442
|
+
a check can see.
|
|
443
|
+
4. Keep row 24, columns 20 to 39 free in AUTOPILOT builds. Set the meter's
|
|
444
|
+
`hold` to the script's play frames. Bracket the whole frame's work,
|
|
445
|
+
summing IRQ work with `METER_PAUSE`.
|
|
446
|
+
5. Write `expect.json`: the verdict, the text, a `sprite` or `rect` or
|
|
447
|
+
`pixel` check for each feature, a `same` area, the meter with `frames`.
|
|
448
|
+
6. Pin `SHOT_CYCLES_*` after the verdict, where the screen no longer
|
|
449
|
+
changes; prove it with two pins.
|
|
450
|
+
7. `make shot check selftest disk`, then `npm run verify:templates --
|
|
451
|
+
--only <name> --selftest`.
|
|
452
|
+
|
|
453
|
+
## Not measured here
|
|
454
|
+
|
|
455
|
+
- The settings.json hook wrapper string was not executed by Claude Code in
|
|
456
|
+
this session; `plan-gate.py` itself was run in hook mode with sample tool
|
|
457
|
+
calls.
|
|
458
|
+
- A starter that uses `SHOT_DISK=1`, `DISK_FILES` or IRQ work inside the
|
|
459
|
+
meter's brackets. hello and hello-kick use none of them; the review ran
|
|
460
|
+
`SHOT_DISK=1` on hello and it passed.
|
|
461
|
+
- Reads of `$D41B` and `$D41C` under `+sound`. An earlier version of this
|
|
462
|
+
page repeated issue #2's claim that the dummy sound driver breaks them;
|
|
463
|
+
the review read 16 different values from a noise voice under the pinned
|
|
464
|
+
command, so the claim is withdrawn, not replaced.
|
|
465
|
+
- Any VICE other than 3.10, or a palette other than `-default`; `check.py`
|
|
466
|
+
matches exact triples and would fail closed.
|
|
467
|
+
- The released Oscar64 (issue #25): the starters were built with the
|
|
468
|
+
build `CLAUDE.md` names.
|
|
469
|
+
- Real hardware.
|
|
470
|
+
|
|
471
|
+
## See also
|
|
472
|
+
|
|
473
|
+
- [vice-reference](../runtime/vice-reference.md), "Reading the exit screenshot" and "Verifying a run without a human"
|
|
474
|
+
- [oscar64-reference](../toolchains/oscar64-reference.md), "Calling KickAssembler code from Oscar64"
|
|
475
|
+
- [release-disk](../toolchains/release-disk.md), for a release image
|
|
476
|
+
- Recipes: [oscar64/headless-verify](../recipes/oscar64/headless-verify.md),
|
|
477
|
+
[kickassembler/headless-verify](../recipes/kickassembler/headless-verify.md),
|
|
478
|
+
[oscar64/raster-profile-bars](../recipes/oscar64/raster-profile-bars.md)
|
package/package.json
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "c64-kb",
|
|
3
|
+
"version": "0.17.0",
|
|
4
|
+
"description": "Commodore 64 knowledge base — CLI + MCP server with Qdrant vectors + FalkorDB graph",
|
|
5
|
+
"license": "BSD-3-Clause",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "dist/cli.js",
|
|
8
|
+
"bin": {
|
|
9
|
+
"c64-kb": "dist/cli.js"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc -p tsconfig.build.json",
|
|
13
|
+
"dev": "node src/cli.ts",
|
|
14
|
+
"dev:serve": "node src/cli.ts serve",
|
|
15
|
+
"services": "docker compose up -d",
|
|
16
|
+
"services:stop": "docker compose down",
|
|
17
|
+
"start": "node dist/cli.js",
|
|
18
|
+
"ingest": "node src/ingest.ts",
|
|
19
|
+
"ingest:force": "node src/ingest.ts --force",
|
|
20
|
+
"ingest:clean": "node src/ingest.ts --clean",
|
|
21
|
+
"memorize:audit": "node src/cli-memorize-audit.ts",
|
|
22
|
+
"feedback:log": "node src/tools/feedback.ts",
|
|
23
|
+
"check:listings": "node scripts/check-listings.ts",
|
|
24
|
+
"check:pitfall-anchors": "node scripts/check-pitfall-anchors.ts",
|
|
25
|
+
"graph:report": "node scripts/graph-report.ts",
|
|
26
|
+
"vice:headless": "sh scripts/build-vice-headless.sh",
|
|
27
|
+
"verify:recipes": "node scripts/verify-recipes.ts",
|
|
28
|
+
"verify:templates": "node scripts/verify-templates.ts",
|
|
29
|
+
"new-project": "node scripts/new-project.ts",
|
|
30
|
+
"test": "vitest run",
|
|
31
|
+
"test:watch": "vitest",
|
|
32
|
+
"typecheck": "tsc -p tsconfig.json",
|
|
33
|
+
"prepack": "npm run build",
|
|
34
|
+
"health": "node src/cli.ts health",
|
|
35
|
+
"test:unit": "vitest run --project unit",
|
|
36
|
+
"test:integration": "vitest run --project integration",
|
|
37
|
+
"lint": "eslint --max-warnings=0 .",
|
|
38
|
+
"lint:fix": "eslint --fix .",
|
|
39
|
+
"format": "prettier --write .",
|
|
40
|
+
"format:check": "prettier --check .",
|
|
41
|
+
"knip": "knip"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
45
|
+
"@qdrant/js-client-rest": "^1.19.0",
|
|
46
|
+
"better-sqlite3": "^12.10.0",
|
|
47
|
+
"commander": "^14.0.3",
|
|
48
|
+
"falkordb": "^6.6.2",
|
|
49
|
+
"zod": "^4.4.3"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@eslint/js": "^10.0.1",
|
|
53
|
+
"@tsconfig/node24": "^24.0.5",
|
|
54
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
55
|
+
"@types/node": "^25.8.0",
|
|
56
|
+
"eslint": "^10.11.0",
|
|
57
|
+
"eslint-config-prettier": "^10.1.8",
|
|
58
|
+
"eslint-plugin-sonarjs": "^4.2.1",
|
|
59
|
+
"knip": "^6.37.0",
|
|
60
|
+
"lefthook": "^2.1.14",
|
|
61
|
+
"prettier": "^3.9.8",
|
|
62
|
+
"typescript": "^6.0.3",
|
|
63
|
+
"typescript-eslint": "^8.70.1",
|
|
64
|
+
"vitest": "^4.1.6"
|
|
65
|
+
},
|
|
66
|
+
"engines": {
|
|
67
|
+
"node": ">=24.12"
|
|
68
|
+
},
|
|
69
|
+
"files": [
|
|
70
|
+
"dist",
|
|
71
|
+
"docs",
|
|
72
|
+
"templates",
|
|
73
|
+
"VERSION",
|
|
74
|
+
"CHANGELOG.md",
|
|
75
|
+
"docker-compose.yml"
|
|
76
|
+
],
|
|
77
|
+
"exports": {
|
|
78
|
+
"./package.json": "./package.json"
|
|
79
|
+
},
|
|
80
|
+
"publishConfig": {
|
|
81
|
+
"access": "public"
|
|
82
|
+
},
|
|
83
|
+
"repository": {
|
|
84
|
+
"type": "git",
|
|
85
|
+
"url": "git+https://github.com/bdgscotland/c64-kb.git"
|
|
86
|
+
},
|
|
87
|
+
"allowScripts": {
|
|
88
|
+
"better-sqlite3": true,
|
|
89
|
+
"fsevents": false,
|
|
90
|
+
"lefthook": false
|
|
91
|
+
},
|
|
92
|
+
"keywords": [
|
|
93
|
+
"commodore-64",
|
|
94
|
+
"c64",
|
|
95
|
+
"6502",
|
|
96
|
+
"mcp",
|
|
97
|
+
"model-context-protocol",
|
|
98
|
+
"knowledge-base",
|
|
99
|
+
"retro"
|
|
100
|
+
],
|
|
101
|
+
"homepage": "https://github.com/bdgscotland/c64-kb#readme",
|
|
102
|
+
"bugs": {
|
|
103
|
+
"url": "https://github.com/bdgscotland/c64-kb/issues"
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Rules for an agent working on this C64 program
|
|
2
|
+
|
|
3
|
+
This program runs on a stock Commodore 64, PAL and NTSC. It is built on the
|
|
4
|
+
c64-kb harness (`./harness`, vendored from c64-kb's `templates/_harness`).
|
|
5
|
+
c64-kb is the reference: its pages give the registers, timings, techniques,
|
|
6
|
+
pitfalls and recipes this program is built from. A wrong number becomes a torn
|
|
7
|
+
screen or a crash, so every claim here is measured or says it is not.
|
|
8
|
+
|
|
9
|
+
A new program starts in c64-kb with `npm run new-project -- <starter> <dir>`.
|
|
10
|
+
That copies the starter and the harness, points `.mcp.json` and `local.mk`
|
|
11
|
+
at the c64-kb checkout, proves the copy with `make shot check`, and leaves a
|
|
12
|
+
blank `PLAN.md`.
|
|
13
|
+
|
|
14
|
+
## Before any code
|
|
15
|
+
|
|
16
|
+
1. Brief: `npx tsx src/cli.ts game-briefing "<concept>" --archetype <name>`
|
|
17
|
+
(or `demo-briefing`), in the c64-kb checkout. Read what it proposes.
|
|
18
|
+
2. For each technique you keep: `technique-lookup <name>` and
|
|
19
|
+
`pitfalls-for <name>`. Start from the recipe it names (`recipe-lookup`).
|
|
20
|
+
3. Fill `PLAN.md`: paste the whole output of `check-compatibility` and of
|
|
21
|
+
`plan-budget` (same techniques) into their sections, list every technique
|
|
22
|
+
in its table, and replace every `FILL:` line.
|
|
23
|
+
|
|
24
|
+
Until `PLAN.md` passes, a hook blocks Edit and Write under `src/`, and every
|
|
25
|
+
make target that builds stops (`make plan-gate` says what is missing). With
|
|
26
|
+
C64KB set, `make` re-runs `check-compatibility` and wants the pasted Verdict.
|
|
27
|
+
The gate cannot see writes made through a shell command, or outputs edited
|
|
28
|
+
into shape by hand: do neither. `make PLAN_GATE=off` overrides it; say why in
|
|
29
|
+
`PLAN.md` if you do.
|
|
30
|
+
|
|
31
|
+
## The loop
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
make # build build/<name>.prg
|
|
35
|
+
make shot check # autopilot build, headless PAL and NTSC, graded by expect.json
|
|
36
|
+
make selftest # the FORCE_FAULT build must fail the same checks
|
|
37
|
+
make disk # build/<name>.d64
|
|
38
|
+
make claims # every store the program makes, against what it declares
|
|
39
|
+
make run # windowed VICE, for a human
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Rules
|
|
43
|
+
|
|
44
|
+
- Build before claiming. Code that has not built is not done.
|
|
45
|
+
- Measure screenshots with `check.py` through `expect.json`, never by eye.
|
|
46
|
+
Every visible claim gets a check. Add one before you trust a change.
|
|
47
|
+
- PAL and NTSC: both shots pass, or it is not done.
|
|
48
|
+
- Name the rung for every number: measured here (`make shot`, the meter, the
|
|
49
|
+
VICE monitor), taken from a c64-kb page (say which), arithmetic, or not
|
|
50
|
+
measured. Never call something verified that was not run.
|
|
51
|
+
- Frame cost comes from the meter: CIA2 timer A, printed as
|
|
52
|
+
`F<frames> W<worst> T<typical>` at row 24, columns 20 to 39, in AUTOPILOT
|
|
53
|
+
builds. It records the first `hold` frames: make that the autopilot
|
|
54
|
+
script's play frames. Typical is the median of those frames, the KB's
|
|
55
|
+
`cycles_per_frame_typical`. Keep grading, logging and printing outside the
|
|
56
|
+
bracket; work split between the main loop and IRQs is summed with
|
|
57
|
+
`METER_PAUSE` / `METER_START`.
|
|
58
|
+
- Do not invent a register, routine or address. Look it up:
|
|
59
|
+
`lookup-register`, `lookup-kernal`, `memory-map`.
|
|
60
|
+
- Lint every source you change: `npx tsx src/cli.ts lint <file>`.
|
|
61
|
+
- Commit named paths only. Never `git add -A` or `git add .`. `build/`,
|
|
62
|
+
`shots/` and `local.mk` are never committed.
|
|
63
|
+
|
|
64
|
+
## Harness facts you will need
|
|
65
|
+
|
|
66
|
+
- `AUTOPILOT=1` builds read a scripted joystick byte instead of `$DC00` and
|
|
67
|
+
grade themselves: `$02FF` = `$01` and a green border on pass, `$02` and red
|
|
68
|
+
on fail. `FORCE_FAULT=1` must turn the verdict red and move something a
|
|
69
|
+
screenshot check can see.
|
|
70
|
+
- Screenshot geometry (c64-kb `docs/runtime/vice-reference.md`): PAL 384 x 272,
|
|
71
|
+
row = raster line - 16; NTSC 384 x 247, row = line - 28; x = VIC X + 8. A
|
|
72
|
+
sprite at Y register y is drawn from line y + 1.
|
|
73
|
+
- `check.py` reads text in the ROM character set unless a check names a
|
|
74
|
+
`charset` file; the meter's cells need 0-9, F, W and T in the set on screen.
|
|
75
|
+
- A KickAssembler part called from C is a raw blob at its own `* =` address,
|
|
76
|
+
`$0880` or above; `build/asm.h` gives C its labels as `ASM_<LABEL>`
|
|
77
|
+
(`ASM_<SCOPE>_<LABEL>` inside a scope). Pass arguments through bytes in the
|
|
78
|
+
blob, not Oscar64's zero page (`$02` up; the top depends on the program:
|
|
79
|
+
`make zp` lists what the build's code touches).
|
|
80
|
+
- The meter takes CIA2 timer A. Do not open RS-232 (device 2) while it runs.
|
|
81
|
+
- The KERNAL serial routines end in `CLI` (ROM bytes `58 60` / `58 18` at
|
|
82
|
+
`$EDAB`, `$EDB5`, `$EDDB`, `$EE82`). After any disk call, `SEI` again if
|
|
83
|
+
the program runs with the KERNAL IRQ off: otherwise that IRQ lands inside
|
|
84
|
+
the meter's brackets and rewrites `$DC00`.
|
|
85
|
+
|
|
86
|
+
## Calling c64-kb
|
|
87
|
+
|
|
88
|
+
- CLI, from the c64-kb checkout (`C64KB` in `local.mk`):
|
|
89
|
+
`npx tsx src/cli.ts <command>`; `npx tsx src/cli.ts --help` lists them.
|
|
90
|
+
- MCP: `.mcp.json` starts `node <c64-kb>/dist/cli.js serve` (run
|
|
91
|
+
`npm run build` in c64-kb first).
|