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,1393 @@
|
|
|
1
|
+
---
|
|
2
|
+
tool: vice
|
|
3
|
+
tool_kind: emulator
|
|
4
|
+
maintainer: VICE Team
|
|
5
|
+
license: GPL-2.0
|
|
6
|
+
home_url: https://vice-emu.sourceforge.io/
|
|
7
|
+
version_verified: "3.10"
|
|
8
|
+
---
|
|
9
|
+
<!-- doc-type: toolchain-reference -->
|
|
10
|
+
|
|
11
|
+
# VICE — Versatile Commodore Emulator
|
|
12
|
+
|
|
13
|
+
## Tool
|
|
14
|
+
|
|
15
|
+
VICE (Versatile Commodore Emulator) is an open-source emulator that runs software
|
|
16
|
+
written for the Commodore 8-bit computer family on modern hardware. For c64-kb purposes
|
|
17
|
+
the only relevant binary is `x64sc`, the cycle-accurate C64 emulator. VICE exposes a
|
|
18
|
+
TCP-based binary monitor protocol on port 6502 that allows external programs to inspect
|
|
19
|
+
and control the running machine — read and write memory, set breakpoints, capture the
|
|
20
|
+
screen, load and execute programs, and save snapshots. The vice-mcp server speaks this
|
|
21
|
+
protocol on behalf of agents; agents do not drive the protocol directly.
|
|
22
|
+
|
|
23
|
+
**Targets:** 6510, VIC-II, SID, CIA1, CIA2
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Quick Reference
|
|
28
|
+
|
|
29
|
+
### Install
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# macOS — Homebrew
|
|
33
|
+
brew install vice
|
|
34
|
+
|
|
35
|
+
# Debian / Ubuntu
|
|
36
|
+
sudo apt install vice
|
|
37
|
+
|
|
38
|
+
# Fedora
|
|
39
|
+
sudo dnf install vice
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
After installation, ROM images must be present. On Homebrew macOS they land in
|
|
43
|
+
`/opt/homebrew/share/vice/C64/`. On Linux, packages that include the ROMs place them in
|
|
44
|
+
`/usr/share/vice/C64/`; Debian's does not include them. VICE will refuse to start
|
|
45
|
+
without a valid `kernal`, `basic`, and `chargen` ROM.
|
|
46
|
+
|
|
47
|
+
### Basic run
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Load and auto-run a PRG directly
|
|
51
|
+
x64sc -autostart hello.prg
|
|
52
|
+
|
|
53
|
+
# Attach a D64 disk image and autostart the first file
|
|
54
|
+
x64sc -autostart mygame.d64
|
|
55
|
+
|
|
56
|
+
# Headless automated run: warp speed, quit after 5,000,000 cycles (about 5 s PAL), binary monitor on
|
|
57
|
+
x64sc -warp -limitcycles 5000000 -binarymonitor -binarymonitoraddress ip4://127.0.0.1:6502 \
|
|
58
|
+
-autostart hello.prg
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Emulator Binaries
|
|
64
|
+
|
|
65
|
+
VICE ships multiple binaries, one per emulated machine.
|
|
66
|
+
|
|
67
|
+
| Binary | Machine emulated | Notes |
|
|
68
|
+
|--------|-----------------|-------|
|
|
69
|
+
| `x64sc` | Commodore 64 (cycle-accurate) | **Use this for all c64-kb work** |
|
|
70
|
+
| `x64` | Commodore 64 (fast) | Higher host performance; not cycle-accurate |
|
|
71
|
+
| `x128` | Commodore 128 | Out of scope for c64-kb |
|
|
72
|
+
| `xvic` | VIC-20 | Out of scope |
|
|
73
|
+
| `xpet` | PET series | Out of scope |
|
|
74
|
+
| `xplus4` | PLUS/4 | Out of scope |
|
|
75
|
+
| `xcbm2` | CBM-II | Out of scope |
|
|
76
|
+
|
|
77
|
+
`x64sc` uses a cycle-exact 6510/VIC-II core; both binaries offer true 1541 drive
|
|
78
|
+
emulation (an earlier version of this page credited it to `x64sc` alone). It is
|
|
79
|
+
slower than `x64` on the host but produces correct raster timing, correct CIA timer
|
|
80
|
+
behaviour, and correct SID timing — all of which matter when verifying demo or game
|
|
81
|
+
code. Always use `x64sc` for correctness. See the Pitfalls section for the consequences
|
|
82
|
+
of reaching for `x64` instead.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## CLI Flags
|
|
87
|
+
|
|
88
|
+
The table below covers flags relevant to build-and-test automation and basic operation.
|
|
89
|
+
VICE accepts many more; run `x64sc --help` for the full list.
|
|
90
|
+
|
|
91
|
+
| Flag | Argument | Effect |
|
|
92
|
+
|------|----------|--------|
|
|
93
|
+
| `-autostart <file>` | PRG, D64, T64, TAP, VSF | Load and RUN the named file or the first file on a disk/tape image; a `.vsf` is autodetected as a snapshot and restored (after the normal autostart delay — allow well over 3,000,000 cycles under `-limitcycles`) |
|
|
94
|
+
| `-binarymonitor` | — | Enable the TCP binary monitor |
|
|
95
|
+
| `-binarymonitoraddress <addr>` | `ip4://127.0.0.1:6502` | Monitor listen address and port |
|
|
96
|
+
| `-moncommands <file>` | path to text file | Execute text-monitor commands at startup (useful for loading labels) |
|
|
97
|
+
| `-warp` | — | Disable real-time throttle; run as fast as the host allows (`-help`: "Initially enable warp mode"; `+warp` is the default). The pinned run uses it so 8,000,000 cycles take seconds, not eight of them |
|
|
98
|
+
| `-limitcycles <n>` | cycles | Quit after n emulated cycles (985,248 per PAL second, 1,022,727 per NTSC second); VICE exits with a non-zero status when the limit fires (`-help`: "quitting with an error"), so a wrapper must not treat rc=1 alone as failure. The pinned run's exit point: the frame on screen when it fires is the one `-exitscreenshot` writes, so a recipe's cycle count is part of its identity |
|
|
99
|
+
| `-exitscreenshot <file>` | PNG path | Write the current frame to `<file>` when the emulator exits, including the `-limitcycles` exit. The only picture the verification protocol reads; the file is 384x272 RGBA on PAL and 384x247 on NTSC (see "Reading the exit screenshot" below) |
|
|
100
|
+
| `-autostartprgmode <n>` | 0, 1, 2 | How `-autostart file.prg` gets the PRG into memory (`-help`: "0: VirtualFS, 1: Inject, 2: Disk image"). 0 types `LOAD"HELLO.PRG",8,1` and expects VICE's host-directory device to answer; 1 writes the PRG into RAM once the KERNAL reaches `READY.` and types `RUN`; 2 puts the file on a disk image and loads it through the emulated drive as `LOAD"HELLO",8,1`. The protocol pins 1: it is the fastest, and under `-default` mode 0 never ran the program at all; measurements below |
|
|
101
|
+
| `-default` | — | "Restore default settings": start from VICE's built-in configuration rather than whatever the user last saved, so a run on another machine starts from the same settings. Without it a saved palette, model or drive setting would change the picture (the effect of a saved settings file was not measured here) |
|
|
102
|
+
| `+sound` | — | "Disable sound playback". No audio device is opened, so a headless run cannot stall or fail on the host's audio stack; SID emulation itself still runs |
|
|
103
|
+
| `+autostart-delay-random` | — | "Disable random initial autostart delay". VICE otherwise adds a random delay before autostart, so the same `-limitcycles` would land on a different frame each run; with it off the exit screenshot is reproducible pixel for pixel |
|
|
104
|
+
| `-console` | — | "Console mode (for music playback)": the flag under which this page's option names were confirmed (`x64sc -default -console`). The pinned run does not use it; every screenshot cited on this page was produced without it, and whether it changes the screenshot was not measured here |
|
|
105
|
+
| `-pal` | — | Force PAL machine model |
|
|
106
|
+
| `-ntsc` | — | Force NTSC machine model |
|
|
107
|
+
| `-model <name>` | `c64`, `c64c`, `c64old`, `ntsc`, `newntsc`, `oldntsc`, `drean`, `jap`, `c64gs`, `pet64`, `ultimax` | Select machine sub-model (list from `x64sc -help`; there is no `pal` value). With no `-model`, `-default` runs the `c64c` configuration: VIC-II 8565, SID 8580, CIA 8521 (`x64sc -default -dumpconfig` gives VICIIModel=1, SidModel=1, CIA1Model=1, identical to `-model c64c`; `-model c64` gives 0, 0, 0, the 6569, 6581 and 6526). An earlier version of this row said the default was the PAL 6569 `c64`; `recipes/kickassembler/cia-revision-detect.md` reads the new CIA on the default machine and the old one on `-model c64`, which settles it (measured 2026-09-23). Both PAL parts run 312 lines of 63 cycles. Decision (#36): the harness keeps this default. Every runs.json `pal` run and PAL screenshot is the C64C, and pages name it "PAL c64c (8565/8580/8521)"; add `-model c64` (6569, 6581, 6526) to check a listing on the older machine, which differs in the CIA timer interrupt (one cycle later on the 6526; `cia-revision-detect` reads `12 11` there and `10 11` on the default), the SID filter and `$D418` digis (not measured here), and eleven palette entries. The protocol's second run adds `-model ntsc` for the 6567R8 (with a 6581 and a 6526); that changes the frame height, the timing and eleven of the sixteen palette entries |
|
|
108
|
+
| `-drive8type <n>` | 1541, 1571, … | Drive type for device 8 |
|
|
109
|
+
| `-8 <file>` | D64, G64, … | Attach disk image to device 8 (`-help`: "Attach <name> as a disk image in unit #8"). A recipe whose `runs.json` entry carries `"disk": {"name": "TEST,01"}` gets a D64 freshly formatted with `c1541 -format "test,01" d64` attached this way before every run, so the program always sees the same empty disk |
|
|
110
|
+
| `-1 <file>` | T64, TAP | Attach a tape image to the datasette (unit 1) |
|
|
111
|
+
| `-soundvolume <n>` | 0–100 | Audio output level (0 = mute) |
|
|
112
|
+
| `-keymap <n>` | 0 symbolic, 1 positional, 2/3 user files | Keymap type (default 0) |
|
|
113
|
+
| `-keyboardmapping <n>` | 0 = US, other values select other host layouts | Host keyboard layout used to pick the `.vkm` file |
|
|
114
|
+
| `-cartcrt <file>` | CRT | Attach a cartridge image |
|
|
115
|
+
| `+cart` | — | Disable cartridge (note: plus sign, not minus) |
|
|
116
|
+
|
|
117
|
+
Flags that begin with `+` instead of `-` are boolean toggles that explicitly turn a
|
|
118
|
+
feature off; their `-` counterparts turn it on.
|
|
119
|
+
|
|
120
|
+
An earlier revision of this page listed `-quitafter <seconds>`, `-1541-8`,
|
|
121
|
+
`-tape1 <file>`, `-snapshot <file>` and `-keyboard <layout>`; x64sc 3.10 has none of
|
|
122
|
+
them and rejects each as an unknown (or, for `-keyboard`, ambiguous) option, aborting
|
|
123
|
+
startup. The rows above hold the real names (measured with `x64sc -default -console`).
|
|
124
|
+
|
|
125
|
+
Every flag in the table was checked again on 2026-09-22 against the output of
|
|
126
|
+
`x64sc -help` from the Homebrew VICE 3.10 on this machine (1,929 lines); the quoted
|
|
127
|
+
phrases in the table are that output's own wording. The ten flags the pinned
|
|
128
|
+
verification run uses (`-default -warp +sound +autostart-delay-random
|
|
129
|
+
-autostartprgmode 1 -limitcycles N [-model ntsc] [-8 disk.d64] -exitscreenshot
|
|
130
|
+
out.png -autostart out.prg`) all appear in it under exactly those names.
|
|
131
|
+
|
|
132
|
+
### What `-autostartprgmode` does to a run
|
|
133
|
+
|
|
134
|
+
Measured with the committed `docs/recipes/kickassembler/hello-world.md` listing
|
|
135
|
+
(assembled with KickAssembler 5.25, 44-byte PRG), the pinned command with
|
|
136
|
+
`GSETTINGS_SCHEMA_DIR` set, PAL, one run per cell, decoding the screenshot's text
|
|
137
|
+
cells against the character ROM. A PNG was written in all fourteen runs and every run
|
|
138
|
+
exited with status 1, which is the `-limitcycles` exit, not a failure.
|
|
139
|
+
|
|
140
|
+
| Mode | 2,000,000 | 2,500,000 | 3,000,000 | 3,500,000 to 4,500,000 | 5,000,000 | 5,500,000 to 8,000,000 |
|
|
141
|
+
|---|---|---|---|---|---|---|
|
|
142
|
+
| 1 Inject | all-black frame | `READY.` only | `RUN` / `HELLO, WORLD!` / `READY.` | not run | not run | not run |
|
|
143
|
+
| 0 VirtualFS | not run | not run | `LOAD"HELLO.PRG",8,1` typed | `SEARCHING FOR HELLO.PRG` | not run | `?FILE NOT FOUND ERROR` at 6,000,000 and 8,000,000 |
|
|
144
|
+
| 2 Disk image | not run | not run | `LOAD"HELLO",8,1` typed | 4,500,000: all-black frame | `SEARCHING` / `LOADING` / `READY.` / `RUN` / `HELLO, WORLD!` / `READY.` | same as 5,000,000 |
|
|
145
|
+
|
|
146
|
+
So the smallest `-limitcycles`, to the nearest 500,000, at which the program's
|
|
147
|
+
output is on screen is **3,000,000 for mode 1** and **5,000,000 for mode 2**; under
|
|
148
|
+
`-default` **mode 0 never shows it**: the typed `LOAD` ends in
|
|
149
|
+
`?FILE NOT FOUND ERROR`. The likely reason is that `-default` turns true drive
|
|
150
|
+
emulation on, so unit 8 is an empty 1541 and the host-directory device never
|
|
151
|
+
answers; that is an inference, since no run was made with `+drive8truedrive` or a
|
|
152
|
+
virtual device enabled, and whether mode 0 works under some other configuration
|
|
153
|
+
was not measured here. Two runs produced a frame in which every one of the 104,448 pixels is
|
|
154
|
+
(0, 0, 0), border included: mode 1 at 2,000,000 and mode 2 at 4,500,000. The cause
|
|
155
|
+
was not established. A machine reset would blank the border like this (the VIC-II
|
|
156
|
+
registers read zero after reset), but the mode 2 run at 5,000,000 shows the whole
|
|
157
|
+
load already finished, which a reset at 4,500,000 does not leave time for. Treat an
|
|
158
|
+
all-black exit screenshot as a cycle count that landed somewhere the frame was not
|
|
159
|
+
drawn, not as evidence about the program; move `-limitcycles` and look again.
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## The Binary Monitor Protocol
|
|
164
|
+
|
|
165
|
+
VICE exposes a binary remote monitor over TCP when started with `-binarymonitor`. The
|
|
166
|
+
default address is `ip4://127.0.0.1:6502`. The port number is a deliberate nod to the
|
|
167
|
+
6502 processor.
|
|
168
|
+
|
|
169
|
+
### Enabling the monitor
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
x64sc -binarymonitor -binarymonitoraddress ip4://127.0.0.1:6502 -autostart hello.prg
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Once VICE is running, any TCP client can connect and send commands.
|
|
176
|
+
|
|
177
|
+
### Frame format
|
|
178
|
+
|
|
179
|
+
Every message — command or response — shares a common wire layout:
|
|
180
|
+
|
|
181
|
+
**Request frame**
|
|
182
|
+
|
|
183
|
+
| Offset | Length | Field |
|
|
184
|
+
|--------|--------|-------|
|
|
185
|
+
| 0 | 1 | STX marker: `0x02` |
|
|
186
|
+
| 1 | 1 | API version: `0x02` |
|
|
187
|
+
| 2–5 | 4 | Payload length (little-endian, header excluded) |
|
|
188
|
+
| 6–9 | 4 | Request ID (little-endian, caller-chosen) |
|
|
189
|
+
| 10 | 1 | Command opcode |
|
|
190
|
+
| 11+ | varies | Command body |
|
|
191
|
+
|
|
192
|
+
**Response frame**
|
|
193
|
+
|
|
194
|
+
| Offset | Length | Field |
|
|
195
|
+
|--------|--------|-------|
|
|
196
|
+
| 0 | 1 | STX marker: `0x02` |
|
|
197
|
+
| 1 | 1 | API version: `0x02` |
|
|
198
|
+
| 2–5 | 4 | Body length (little-endian) |
|
|
199
|
+
| 6 | 1 | Response type |
|
|
200
|
+
| 7 | 1 | Error code |
|
|
201
|
+
| 8–11 | 4 | Request ID (`0xffffffff` = event-triggered) |
|
|
202
|
+
| 12+ | varies | Response body |
|
|
203
|
+
|
|
204
|
+
Error code `0x00` means success. Other codes: `0x01` object not found, `0x02` invalid
|
|
205
|
+
memspace, `0x80` incorrect command length, `0x81` invalid parameter, `0x82` API
|
|
206
|
+
version unsupported, `0x83` unknown command, `0x8f` general failure.
|
|
207
|
+
|
|
208
|
+
### Command opcode table
|
|
209
|
+
|
|
210
|
+
| Opcode | Name | Description |
|
|
211
|
+
|--------|------|-------------|
|
|
212
|
+
| `0x01` | Memory Get | Read bytes from an address range |
|
|
213
|
+
| `0x02` | Memory Set | Write bytes to an address range |
|
|
214
|
+
| `0x11` | Checkpoint Get | Retrieve details of a checkpoint |
|
|
215
|
+
| `0x12` | Checkpoint Set | Create a breakpoint or watchpoint |
|
|
216
|
+
| `0x13` | Checkpoint Delete | Remove a checkpoint |
|
|
217
|
+
| `0x14` | Checkpoint List | Enumerate all checkpoints |
|
|
218
|
+
| `0x15` | Checkpoint Toggle | Enable or disable a checkpoint |
|
|
219
|
+
| `0x22` | Condition Set | Attach a condition expression to a checkpoint |
|
|
220
|
+
| `0x31` | Registers Get | Read current CPU register values |
|
|
221
|
+
| `0x32` | Registers Set | Write CPU register values |
|
|
222
|
+
| `0x41` | Dump | Save machine state to a VSF snapshot file |
|
|
223
|
+
| `0x42` | Undump | Restore machine state from a VSF snapshot file |
|
|
224
|
+
| `0x51` | Resource Get | Read an emulator resource/setting |
|
|
225
|
+
| `0x52` | Resource Set | Write an emulator resource/setting |
|
|
226
|
+
| `0x71` | Advance Instructions | Step over N instructions |
|
|
227
|
+
| `0x72` | Keyboard Feed | Inject PETSCII text into the keyboard buffer |
|
|
228
|
+
| `0x73` | Execute Until Return | Run until the next RTS or RTI |
|
|
229
|
+
| `0x81` | Ping | Connectivity test (echoes request ID) |
|
|
230
|
+
| `0x82` | Banks Available | List available memory banks |
|
|
231
|
+
| `0x83` | Registers Available | List register names and IDs |
|
|
232
|
+
| `0x84` | Display Get | Capture current screen buffer as pixel data |
|
|
233
|
+
| `0x85` | VICE Info | Return version and build information |
|
|
234
|
+
| `0x86` | CPU History | Return instruction execution history |
|
|
235
|
+
| `0x91` | Palette Get | Fetch the current color palette |
|
|
236
|
+
| `0xa2` | Joyport Set | Simulate joystick input |
|
|
237
|
+
| `0xb2` | Userport Set | Simulate user-port input |
|
|
238
|
+
| `0xaa` | Exit | Resume execution (release the monitor) |
|
|
239
|
+
| `0xbb` | Quit | Terminate VICE |
|
|
240
|
+
| `0xcc` | Reset | Soft or hard reset the machine or a drive |
|
|
241
|
+
| `0xdd` | Autostart | Load and execute a named file |
|
|
242
|
+
|
|
243
|
+
All multi-byte fields in command bodies use little-endian byte order. The memspace
|
|
244
|
+
parameter in memory and checkpoint commands takes `0x00` for the main C64 address space
|
|
245
|
+
and `0x01`–`0x04` for drives 8–11 respectively.
|
|
246
|
+
|
|
247
|
+
**Important:** agents should not drive this protocol directly. The vice-mcp server
|
|
248
|
+
wraps the protocol in a clean MCP tool surface; see
|
|
249
|
+
[vice-mcp-reference.md](vice-mcp-reference.md) for the agent-facing API.
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## Disk and Tape Handling
|
|
254
|
+
|
|
255
|
+
VICE attaches disk and tape images as virtual peripheral devices. Device 8 is the
|
|
256
|
+
primary disk drive (1541 by default). The relevant attachment flags are `-8 <file>` for
|
|
257
|
+
disk images and `-1 <file>` for tape images. `-autostart` can also accept a
|
|
258
|
+
disk or tape image path directly and will load the first file.
|
|
259
|
+
|
|
260
|
+
### .D64 — Single-sided 35-track 1541 disk image
|
|
261
|
+
|
|
262
|
+
The standard 1541 disk image format. A D64 file contains 35 tracks of raw sector data.
|
|
263
|
+
Sector count varies by zone: tracks 1–17 carry 21 sectors each, tracks 18–24 carry 19
|
|
264
|
+
sectors each, tracks 25–30 carry 18 each, and tracks 31–35 carry 17 each — 683 sectors
|
|
265
|
+
total. Each sector is 256 bytes, giving a total image size of 174,848 bytes (or 175,531
|
|
266
|
+
bytes with the optional per-sector error-code extension). Track 18 / sector 0 holds the
|
|
267
|
+
BAM (Block Availability Map) and disk name; the directory occupies track 18 sectors 1–18
|
|
268
|
+
and supports up to 144 file entries.
|
|
269
|
+
|
|
270
|
+
**Produced by:** c1541
|
|
271
|
+
**Consumed by:** vice
|
|
272
|
+
|
|
273
|
+
D64 is the go-to format for distributing finished software. It cannot represent
|
|
274
|
+
non-standard track layouts or copy-protection schemes; for those cases use G64.
|
|
275
|
+
|
|
276
|
+
### .G64 — GCR-encoded 1541 disk image
|
|
277
|
+
|
|
278
|
+
G64 stores raw GCR (Group Code Recording) bitstream data — the actual flux transitions
|
|
279
|
+
the 1541 read head would encounter. The format supports up to 84 track slots (42 full
|
|
280
|
+
tracks plus 42 half-tracks), though typical 1541 media uses only 35. Because the
|
|
281
|
+
bitstream is preserved verbatim, G64 can represent disks with non-standard sector
|
|
282
|
+
interleavings, custom loaders, weak bits, and copy-protection schemes that D64 cannot
|
|
283
|
+
encode. Track size varies by zone, with outer tracks holding more GCR bytes than inner
|
|
284
|
+
tracks (approximately 7,692 bytes for tracks 1–17 down to around 6,250 bytes for track
|
|
285
|
+
31+).
|
|
286
|
+
|
|
287
|
+
**Produced by:** c1541
|
|
288
|
+
**Consumed by:** vice
|
|
289
|
+
|
|
290
|
+
Use G64 when the software relies on a non-standard 1541 format, or when a D64 round-trip
|
|
291
|
+
loses copy-protection data you need to preserve for testing.
|
|
292
|
+
|
|
293
|
+
### .T64 — Tape archive (PRG container)
|
|
294
|
+
|
|
295
|
+
T64 is a container format created for the C64s emulator. It stores one or more PRG
|
|
296
|
+
files in a simple 32-byte-aligned directory structure: a 64-byte file header (signature
|
|
297
|
+
+ tape version + directory capacity + tape name), followed by 32-byte directory entries
|
|
298
|
+
(file type, load address, end address, data offset, filename in PETSCII), followed by
|
|
299
|
+
the raw file data. T64 is not a raw tape recording — it is closer to a ZIP file for
|
|
300
|
+
PRGs. It has no concept of tape timing or loader protocol. `c1541` can only read a T64
|
|
301
|
+
(its `tape` command extracts files from one); it does not write them.
|
|
302
|
+
|
|
303
|
+
**Consumed by:** vice
|
|
304
|
+
|
|
305
|
+
T64 is a convenient way to ship a single PRG for distribution via "tape" when accurate
|
|
306
|
+
tape timing is not required. For raw pulse-level fidelity use TAP.
|
|
307
|
+
|
|
308
|
+
### .TAP — Raw tape pulse-width data
|
|
309
|
+
|
|
310
|
+
TAP stores the cassette signal as a sequence of bytes, each representing the time (in
|
|
311
|
+
hardware counter units) between successive signal transitions — the literal pulse widths
|
|
312
|
+
the C64 CIA timer measured. A 20-byte file header carries the signature `C64-TAPE-RAW`,
|
|
313
|
+
a version byte, three reserved bytes, and a 4-byte little-endian data-area size (the
|
|
314
|
+
length excludes the header). Version 0 encodes
|
|
315
|
+
each pulse as `period = (8 × byte) / 985248` seconds; a `0x00` byte signals an
|
|
316
|
+
overflow. Version 1 reuses `0x00` as an escape: three following bytes give the actual
|
|
317
|
+
cycle count for long pulses. TAP files are typically 8–16 times larger than the
|
|
318
|
+
equivalent PRG data because each source bit expands to one pulse-width byte.
|
|
319
|
+
|
|
320
|
+
**Produced by:** tapclk, mtap
|
|
321
|
+
**Consumed by:** vice
|
|
322
|
+
|
|
323
|
+
TAP is required when the software uses a custom tape loader that relies on pulse timing,
|
|
324
|
+
such as Turbo Tape or commercial fast loaders. For simple PRG distribution, T64 is
|
|
325
|
+
smaller and easier to work with.
|
|
326
|
+
|
|
327
|
+
### The c1541 companion utility
|
|
328
|
+
|
|
329
|
+
`c1541` is a standalone command-line disk-image maintenance tool shipped with VICE. It
|
|
330
|
+
can create D64 and G64 images, list and extract files, write PRG files into a disk
|
|
331
|
+
image, validate the BAM, inspect block chains, and perform low-level block operations
|
|
332
|
+
(peek, poke, fill). It supports batch mode — prefix commands with `-` to chain them
|
|
333
|
+
non-interactively — and interactive mode with tab completion.
|
|
334
|
+
|
|
335
|
+
```bash
|
|
336
|
+
# Create a fresh D64 and write a PRG into it
|
|
337
|
+
c1541 -format "mygame,01" d64 mygame.d64
|
|
338
|
+
c1541 -attach mygame.d64 -write hello.prg hello
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
`c1541` is the right tool for assembling a releasable disk image from one or more
|
|
342
|
+
compiled PRG files before handing the D64 to VICE for a run.
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
## Symbol Files
|
|
347
|
+
|
|
348
|
+
The VICE text monitor (launched interactively or via `-moncommands`) can load symbol
|
|
349
|
+
tables that map label names to addresses. Two formats are relevant:
|
|
350
|
+
|
|
351
|
+
| Format | Extension | Produced by | Example entry |
|
|
352
|
+
|--------|-----------|-------------|---------------|
|
|
353
|
+
| Oscar64 label file | `.lbl` | oscar64 (written alongside the `.prg` by default; there is no flag, and `-l` is rejected) | `al 0880 .main` |
|
|
354
|
+
| KickAssembler vice symbol file | `.vs` | KickAssembler (`-vicesymbols`) | `al C:1000 .main` |
|
|
355
|
+
| cc65 VICE label file | any (`.lbl` by convention) | ld65 via `cl65 -Ln name` | `al 000840 ._main` |
|
|
356
|
+
|
|
357
|
+
Oscar64 entries carry a bare 4-digit hex address with no `C:` memspace prefix
|
|
358
|
+
(`al HHHH .name`, as [../formats/c64-file-formats.md](../formats/c64-file-formats.md)
|
|
359
|
+
describes); KickAssembler's `-vicesymbols` output uses `al C:HHHH .name`. The VICE
|
|
360
|
+
monitor accepts both, and `break .main` works after `ll` either way. An earlier version
|
|
361
|
+
of this table gave Oscar64 a `-l` flag and a `C:` prefix; neither exists. cc65's
|
|
362
|
+
`-Ln` file uses six hex digits, no prefix, and a leading underscore on every C
|
|
363
|
+
symbol (`_main`, `_cputs`); it also lists the KERNAL names the library imports
|
|
364
|
+
(`al 00FFD2 .BSOUT`). `break ._main` after `ll` stopped at `$0840` (measured,
|
|
365
|
+
cc65 V2.18, VICE 3.10; the session is in
|
|
366
|
+
[../toolchains/cc65-reference.md](../toolchains/cc65-reference.md)).
|
|
367
|
+
|
|
368
|
+
Load a symbol file in the monitor with:
|
|
369
|
+
|
|
370
|
+
```
|
|
371
|
+
ll "build/hello.lbl"
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
Once loaded, the disassembler, breakpoint expressions, and memory commands can use label
|
|
375
|
+
names instead of raw hex addresses. This makes monitor sessions with `vice-mcp` far more
|
|
376
|
+
readable. Load symbols at startup by putting the `ll` command in a file and passing it
|
|
377
|
+
via `-moncommands`.
|
|
378
|
+
|
|
379
|
+
---
|
|
380
|
+
|
|
381
|
+
## Snapshots
|
|
382
|
+
|
|
383
|
+
VICE can save and restore complete machine state using the `.vsf` (VICE Snapshot File)
|
|
384
|
+
format. A snapshot captures RAM, ROM shadow, CPU registers, CIA state, VIC-II state,
|
|
385
|
+
SID state, and optional drive state. ROM images are not embedded in the snapshot.
|
|
386
|
+
The file's layout, decoded from a snapshot the windowless x64sc 3.10 wrote (header,
|
|
387
|
+
module list, and where the 64 KiB RAM, the processor port and colour RAM sit inside
|
|
388
|
+
`C64MEM` and `VIC-II`), is the `.VSF` section of
|
|
389
|
+
[../formats/c64-file-formats.md](../formats/c64-file-formats.md).
|
|
390
|
+
|
|
391
|
+
Save from the text monitor:
|
|
392
|
+
|
|
393
|
+
```
|
|
394
|
+
dump "checkpoint.vsf"
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
Restore:
|
|
398
|
+
|
|
399
|
+
```
|
|
400
|
+
undump "checkpoint.vsf"
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
To restore at startup, either pass the snapshot to `-autostart file.vsf` (restored after
|
|
404
|
+
the autostart delay) or put `undump "file.vsf"` in a `-moncommands` file (restored
|
|
405
|
+
immediately, before the first instruction). There is no `-snapshot` option; an earlier
|
|
406
|
+
version of this page listed one, and x64sc 3.10 rejects it as unknown.
|
|
407
|
+
|
|
408
|
+
Via the binary monitor, `Dump` (opcode `0x41`) and `Undump` (opcode `0x42`) provide the
|
|
409
|
+
same capability programmatically. vice-mcp exposes both operations as MCP tools.
|
|
410
|
+
|
|
411
|
+
Snapshots are useful for reproducible automated testing: run to a known program counter,
|
|
412
|
+
save a snapshot, then restore it at the start of each test run to eliminate variable
|
|
413
|
+
boot-time state.
|
|
414
|
+
|
|
415
|
+
---
|
|
416
|
+
|
|
417
|
+
## Region Selection
|
|
418
|
+
|
|
419
|
+
VICE supports both PAL and NTSC machine configurations. The difference is significant
|
|
420
|
+
for cycle-accurate timing work: PAL machines run at 985,248 cycles/second with 312 scan
|
|
421
|
+
lines per frame (50 Hz), while NTSC machines run at 1,022,727 cycles/second with 263
|
|
422
|
+
scan lines per frame (60 Hz). Raster positions, raster IRQ timing, and the number of
|
|
423
|
+
cycles available per frame differ between regions.
|
|
424
|
+
|
|
425
|
+
Select the region at launch:
|
|
426
|
+
|
|
427
|
+
```bash
|
|
428
|
+
x64sc -pal -autostart demo.prg # PAL
|
|
429
|
+
x64sc -ntsc -autostart demo.prg # NTSC
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
The compiled-in default is a PAL C64 (MachineVideoStandard=1, VICIIModel=1; measured on
|
|
433
|
+
x64sc 3.10 with `-default -dumpconfig`, unchanged under en_US, de_DE, ja_JP and C
|
|
434
|
+
locales — the locale moves the keyboard mapping, not the video standard). A saved config
|
|
435
|
+
file (vicerc) can override it, and `-default` bypasses that file, so pass `-pal`, `-ntsc`
|
|
436
|
+
or `-model` explicitly in automated runs. An earlier version of this sentence said the
|
|
437
|
+
default depended on the system locale; it does not. If a program behaves differently
|
|
438
|
+
under PAL vs NTSC, a raster timing assumption is almost always the cause.
|
|
439
|
+
|
|
440
|
+
For a full treatment of the hardware differences between PAL and NTSC C64 variants, see
|
|
441
|
+
[../hardware/pal-ntsc-reference.md](../hardware/pal-ntsc-reference.md).
|
|
442
|
+
|
|
443
|
+
---
|
|
444
|
+
|
|
445
|
+
## Headless and Automated Invocation
|
|
446
|
+
|
|
447
|
+
An agent (or CI script) running VICE in a build-verify loop wants no GUI, maximum
|
|
448
|
+
speed, and deterministic exit. The pattern is:
|
|
449
|
+
|
|
450
|
+
1. Compile the PRG with oscar64or KickAssembler.
|
|
451
|
+
2. Launch `x64sc` in warp mode with a binary monitor and a short timeout.
|
|
452
|
+
3. Connect via vice-mcp (or a raw TCP client) to set a checkpoint at the expected
|
|
453
|
+
success address.
|
|
454
|
+
4. Autostart the PRG; wait for the checkpoint or for the timeout to fire.
|
|
455
|
+
5. Optionally capture a screenshot via the `Display Get` (`0x84`) command.
|
|
456
|
+
6. Inspect result state; quit VICE via the `Quit` (`0xbb`) command or let
|
|
457
|
+
`-limitcycles` terminate it.
|
|
458
|
+
|
|
459
|
+
Minimal headless invocation:
|
|
460
|
+
|
|
461
|
+
```bash
|
|
462
|
+
x64sc \
|
|
463
|
+
-warp \
|
|
464
|
+
-limitcycles 10000000 \
|
|
465
|
+
-binarymonitor \
|
|
466
|
+
-binarymonitoraddress ip4://127.0.0.1:6502 \
|
|
467
|
+
-moncommands monitor-init.mon \
|
|
468
|
+
-pal \
|
|
469
|
+
-soundvolume 0 \
|
|
470
|
+
-autostart hello.prg
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
`monitor-init.mon` might contain:
|
|
474
|
+
|
|
475
|
+
```
|
|
476
|
+
ll "build/hello.lbl"
|
|
477
|
+
break .success
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
so that vice-mcp can detect the breakpoint hit via a Checkpoint event response
|
|
481
|
+
(request ID `0xffffffff`).
|
|
482
|
+
|
|
483
|
+
For screenshot capture without user interaction, `Display Get` (`0x84`) returns raw
|
|
484
|
+
pixel data for the current frame. This lets an agent record what the screen looks like
|
|
485
|
+
at a given execution point without requiring a visible window.
|
|
486
|
+
|
|
487
|
+
On Linux CI, add `Xvfb` or set `SDL_VIDEODRIVER=offscreen` (SDL2 build) to suppress the
|
|
488
|
+
display requirement.
|
|
489
|
+
|
|
490
|
+
---
|
|
491
|
+
|
|
492
|
+
## Reading the exit screenshot
|
|
493
|
+
|
|
494
|
+
`-exitscreenshot` writes an 8-bit RGBA PNG (IHDR colour type 6, no interlace) of the
|
|
495
|
+
whole frame including borders. Everything below was measured on 2026-09-22 from the
|
|
496
|
+
two pictures of `docs/recipes/kickassembler/palette-cells.md` and the fourteen
|
|
497
|
+
`hello-world` runs above, all VICE x64sc 3.10 with `-default`.
|
|
498
|
+
|
|
499
|
+
The picture is the draw buffer at the cycle the limit hits, not a finished
|
|
500
|
+
frame: the rows the beam has passed in the current field are new and the
|
|
501
|
+
rows below it still hold the previous field. Measured 2026-09-23 on the
|
|
502
|
+
eight-way scroll recipe while its pin was chosen: cycle limits from
|
|
503
|
+
21,000,000 to 21,014,500 gave one identical picture, 21,017,000 differed
|
|
504
|
+
from it only in rows 39 to 59, and 21,019,500 only in rows 59 to 98. So a
|
|
505
|
+
program that changes what a row shows from one field to the next can be
|
|
506
|
+
caught half-way by a pin that lands mid-display, and the split reads as
|
|
507
|
+
a fault in the program. Pin in the blank, or where consecutive fields
|
|
508
|
+
draw the same thing, and say which on the page.
|
|
509
|
+
|
|
510
|
+
### Geometry
|
|
511
|
+
|
|
512
|
+
| | PAL (default `c64`) | NTSC (`-model ntsc`) |
|
|
513
|
+
|---|---|---|
|
|
514
|
+
| PNG size | 384 x 272 | 384 x 247 |
|
|
515
|
+
| Display rows (y) | 35 to 234 | 23 to 222 |
|
|
516
|
+
| Display columns (x) | 32 to 351 | 32 to 351 |
|
|
517
|
+
| Screenshot row from raster line | y = line - 16 | y = line - 28 |
|
|
518
|
+
| Border sample point | (2, 100) | (2, 100) |
|
|
519
|
+
|
|
520
|
+
The display bounds are the first and last row and column whose pixel is not the
|
|
521
|
+
border colour, read off the palette pictures; they agree with the bounds
|
|
522
|
+
`docs/pitfalls/cia.md` measured independently for its tenths-of-a-second probe. The
|
|
523
|
+
line offsets are `CLAUDE.md`'s figures, derived from three boundaries in
|
|
524
|
+
`docs/recipes/kickassembler/topbottom-border-open.md`; they were not re-measured here.
|
|
525
|
+
`x = 8` is VIC-II X coordinate 0 (same source, not re-measured).
|
|
526
|
+
|
|
527
|
+
A text cell is 8 x 8 pixels. Screen row `r` (0 to 24) and column `c` (0 to 39) sit
|
|
528
|
+
at
|
|
529
|
+
|
|
530
|
+
```
|
|
531
|
+
x = 32 + 8 * c
|
|
532
|
+
y = 35 + 8 * r # PAL
|
|
533
|
+
y = 23 + 8 * r # NTSC
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
so the centre of a cell is `(x + 4, y + 4)`, which is the safe place to sample a
|
|
537
|
+
colour. Any pixel in the left border (x 0 to 31) reads the border colour; (2, 100)
|
|
538
|
+
is used throughout the KB because it is inside the display's vertical range on both
|
|
539
|
+
models, well clear of the corner. `hello-world`'s `HELLO, WORLD!` at screen row 7 is
|
|
540
|
+
at y 91 to 98 on PAL: the decoder below finds it there, which is the check that the
|
|
541
|
+
arithmetic is right.
|
|
542
|
+
|
|
543
|
+
### The default palette
|
|
544
|
+
|
|
545
|
+
With `-default` VICE 3.10 uses its internally generated palette, not one of the
|
|
546
|
+
`.vpl` files in its data directory: the sixteen triples below match none of the
|
|
547
|
+
27 files installed under `/opt/homebrew/opt/vice/share/vice/C64/`, compared entry
|
|
548
|
+
for entry. The triples come from the palette recipe, one solid 32-cell band per
|
|
549
|
+
colour index, all 2,048 pixels of each band identical.
|
|
550
|
+
|
|
551
|
+
| Index | PAL RGB | NTSC RGB | Index | PAL RGB | NTSC RGB |
|
|
552
|
+
|---|---|---|---|---|---|
|
|
553
|
+
| 0 | (0, 0, 0) | (0, 0, 0) | 8 | (183, 99, 30) | (196, 98, 65) |
|
|
554
|
+
| 1 | (255, 255, 255) | (255, 255, 255) | 9 | (119, 83, 0) | (151, 64, 0) |
|
|
555
|
+
| 2 | (175, 60, 88) | (169, 71, 100) | 10 | (238, 123, 149) | (230, 134, 163) |
|
|
556
|
+
| 3 | (126, 243, 214) | (138, 230, 203) | 11 | (98, 98, 98) | (98, 98, 98) |
|
|
557
|
+
| 4 | (170, 64, 245) | (154, 88, 185) | 12 | (148, 148, 148) | (148, 148, 148) |
|
|
558
|
+
| 5 | (98, 213, 50) | (114, 189, 103) | 13 | (183, 255, 134) | (198, 255, 186) |
|
|
559
|
+
| 6 | (44, 61, 236) | (25, 73, 180) | 14 | (115, 133, 255) | (98, 145, 251) |
|
|
560
|
+
| 7 | (255, 255, 70) | (255, 248, 141) | 15 | (205, 205, 205) | (205, 205, 205) |
|
|
561
|
+
|
|
562
|
+
The PAL column is the default machine, the `c64c` (8565) configuration, not
|
|
563
|
+
the 6569. Under `-model c64` (6569) indices 0, 1, 11, 12 and 15 match the
|
|
564
|
+
default's and the other eleven differ. Measured 2026-09-23 from the
|
|
565
|
+
`palette-cells` listing run with `-model c64`, one triple per band (each band
|
|
566
|
+
uniform); its default run matched the committed PNG pixel for pixel:
|
|
567
|
+
|
|
568
|
+
| Index | `-model c64` | Index | `-model c64` |
|
|
569
|
+
|---|---|---|---|
|
|
570
|
+
| 2 | (171, 60, 101) | 8 | (183, 100, 24) |
|
|
571
|
+
| 3 | (135, 240, 203) | 9 | (129, 76, 0) |
|
|
572
|
+
| 4 | (178, 61, 239) | 10 | (234, 121, 163) |
|
|
573
|
+
| 5 | (94, 214, 56) | 13 | (178, 255, 141) |
|
|
574
|
+
| 6 | (58, 49, 255) | 14 | (129, 120, 255) |
|
|
575
|
+
| 7 | (255, 255, 59) | | |
|
|
576
|
+
|
|
577
|
+
An earlier version of this section did not say which PAL chip the column
|
|
578
|
+
was, and the next one compared index 5 only.
|
|
579
|
+
|
|
580
|
+
Indices 0, 1, 11, 12 and 15 are the same on both models; the other eleven differ,
|
|
581
|
+
so a script that recognises colours by exact triple needs a table per model. The
|
|
582
|
+
power-on screen is index 6 on index 14: PAL (44, 61, 236) text area, (115, 133, 255)
|
|
583
|
+
border, as every `hello-world` run above shows. A screenshot taken with a user
|
|
584
|
+
configuration, another VICE version or `-VICIIextpal` will not match this table;
|
|
585
|
+
run the palette recipe on that setup first.
|
|
586
|
+
|
|
587
|
+
### Decoding with PIL
|
|
588
|
+
|
|
589
|
+
```python
|
|
590
|
+
from PIL import Image
|
|
591
|
+
im = Image.open('out.png').convert('RGB')
|
|
592
|
+
px = im.load()
|
|
593
|
+
w, h = im.size # (384, 272) PAL, (384, 247) NTSC
|
|
594
|
+
y0 = 35 if h == 272 else 23
|
|
595
|
+
border = px[2, 100]
|
|
596
|
+
def cell_colour(row, col): # centre pixel of a text cell
|
|
597
|
+
return px[32 + 8*col + 4, y0 + 8*row + 4]
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
To read text, compare each cell's 8 x 8 pattern with the character ROM. Take the
|
|
601
|
+
text area's most common colour as background; a pixel is "ink" if it differs from
|
|
602
|
+
it. Each glyph in `chargen-901225-01.bin` is eight bytes, bit 7 the leftmost pixel;
|
|
603
|
+
the first 2 KiB is the upper-case/graphics set the machine powers on with, codes 0
|
|
604
|
+
to 255. Codes 128 to 255 are the reversed forms, stored as separate glyphs: 127 of
|
|
605
|
+
them are the exact complement of code - 128, and one is not. Reversed `@` (code 128)
|
|
606
|
+
has row 6 as `$99` where the complement of `@`'s `$62` would be `$9D`, one pixel
|
|
607
|
+
different (ROM bytes read on this machine; the lower-case set at offset 2048 has the
|
|
608
|
+
same single exception). Build the lookup from the ROM bytes, not from complementing,
|
|
609
|
+
and match the packed rows:
|
|
610
|
+
|
|
611
|
+
```python
|
|
612
|
+
rom = open('/opt/homebrew/opt/vice/share/vice/C64/chargen-901225-01.bin', 'rb').read()
|
|
613
|
+
glyph = {}
|
|
614
|
+
for code in range(256):
|
|
615
|
+
glyph.setdefault(tuple(rom[code*8:code*8+8]), code) # first code wins: $20 for blank, not $60
|
|
616
|
+
def cell_code(row, col, bg):
|
|
617
|
+
return glyph.get(tuple(
|
|
618
|
+
sum((px[32 + 8*col + xx, y0 + 8*row + yy] != bg) << (7 - xx) for xx in range(8))
|
|
619
|
+
for yy in range(8)))
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
Screen codes 1 to 26 are `A` to `Z`, `$20` to `$3F` are space, punctuation and
|
|
623
|
+
digits as in ASCII, 0 is `@`. Two blank glyphs share the all-zero pattern (`$20`
|
|
624
|
+
space and `$60` shifted space); `setdefault` keeps the lower code. Reversed text
|
|
625
|
+
comes back as code + 128 because the ROM holds those forms; mask with `& 0x7f` to
|
|
626
|
+
get the character, and note the palette recipe's solid bands are `$A0`, reversed
|
|
627
|
+
space. A cell whose pattern is not in the table returns `None`: a sprite, a custom
|
|
628
|
+
character set, a colour that happens to equal the background, or a screenshot taken
|
|
629
|
+
mid-frame with two frames' contents in it.
|
|
630
|
+
|
|
631
|
+
### Decoding without PIL
|
|
632
|
+
|
|
633
|
+
The PNG is small enough to decode in pure Python. Concatenate the `IDAT` chunks,
|
|
634
|
+
`zlib.decompress` them, and undo the per-row filter byte (0 none, 1 Sub, 2 Up,
|
|
635
|
+
3 Average, 4 Paeth; the two palette PNGs use 1, 2 and 4). Each row is one filter
|
|
636
|
+
byte followed by `384 * 4` bytes of RGBA. A 40-line implementation of that on this
|
|
637
|
+
machine returned the same border pixel and the same sixteen triples as PIL from
|
|
638
|
+
both palette pictures. Ignore the alpha byte; every pixel VICE wrote had it at 255
|
|
639
|
+
in the pictures checked, but nothing here depends on that.
|
|
640
|
+
|
|
641
|
+
---
|
|
642
|
+
|
|
643
|
+
## Verifying a run without a human
|
|
644
|
+
|
|
645
|
+
A test program can grade itself and leave the verdict where a script can
|
|
646
|
+
read it. The pattern, and three routes for reading it back, were measured
|
|
647
|
+
on 2026-09-22 with VICE x64sc 3.10 `-default` and the two `headless-verify`
|
|
648
|
+
recipes (`docs/recipes/kickassembler/headless-verify.md`,
|
|
649
|
+
`docs/recipes/oscar64/headless-verify.md`). Every exit code quoted below
|
|
650
|
+
came from a run on this machine.
|
|
651
|
+
|
|
652
|
+
### The result-byte contract
|
|
653
|
+
|
|
654
|
+
The program does its computation, then, at one checkpoint and in this
|
|
655
|
+
order:
|
|
656
|
+
|
|
657
|
+
1. stores a result code at `$02FF`: `$01` pass, `$02` fail;
|
|
658
|
+
2. sets the border (`$D020`) to 5 (green) on pass or 2 (red) on fail;
|
|
659
|
+
3. prints the code and returns to BASIC.
|
|
660
|
+
|
|
661
|
+
`$02FF` is the last byte of the KERNAL's unused `$02A7`-`$02FF`
|
|
662
|
+
(`docs/hardware/c64-memory-map.md`); BASIC does not touch it after the
|
|
663
|
+
program returns, so the exit screenshot and a late memory read see the
|
|
664
|
+
same value. It is not untouched before the program runs: the KERNAL reset
|
|
665
|
+
clears page 2 (`STA $0200,Y` at `$FD56`, `A = 0`, cycle 5305 in the
|
|
666
|
+
monitor log), so `$02FF` is `00` when the program starts and a store
|
|
667
|
+
watchpoint on it fires once at boot. Codes therefore start at `01`, and a
|
|
668
|
+
harness that reads `00` has a program that never reached its checkpoint,
|
|
669
|
+
which is a different failure from `02`.
|
|
670
|
+
|
|
671
|
+
The harness returns the verdict as a shell exit code: 0 pass, 1 fail,
|
|
672
|
+
2 no verdict. `x64sc`'s own exit status was 1 on every `-limitcycles` run
|
|
673
|
+
made for this section, pass or fail; it carries nothing.
|
|
674
|
+
|
|
675
|
+
### Route 1: the exit screenshot
|
|
676
|
+
|
|
677
|
+
No monitor, no second process: run the pinned command and read the border
|
|
678
|
+
pixel. The palette triples are the ones in "The default palette" above,
|
|
679
|
+
selected by the picture's height.
|
|
680
|
+
|
|
681
|
+
```bash
|
|
682
|
+
#!/bin/bash
|
|
683
|
+
# usage: verdict_shot.sh prog.prg [pal|ntsc] exit 0 = PASS, 1 = FAIL, 2 = no verdict
|
|
684
|
+
prg=$1; model=${2:-pal}; shot=$(mktemp -t verdict).png
|
|
685
|
+
flags=""; [ "$model" = ntsc ] && flags="-model ntsc"
|
|
686
|
+
GSETTINGS_SCHEMA_DIR=/opt/homebrew/share/glib-2.0/schemas timeout 180 x64sc -default -warp +sound \
|
|
687
|
+
+autostart-delay-random -autostartprgmode 1 -limitcycles 8000000 $flags \
|
|
688
|
+
-exitscreenshot "$shot" -autostart "$prg" >/dev/null 2>&1
|
|
689
|
+
python3 - "$shot" <<'PY'
|
|
690
|
+
import sys
|
|
691
|
+
from PIL import Image
|
|
692
|
+
im = Image.open(sys.argv[1]).convert('RGB')
|
|
693
|
+
pal = im.size[1] == 272
|
|
694
|
+
green = (98, 213, 50) if pal else (114, 189, 103) # index 5
|
|
695
|
+
red = (175, 60, 88) if pal else (169, 71, 100) # index 2
|
|
696
|
+
border = im.getpixel((2, 100))
|
|
697
|
+
verdict = {green: 0, red: 1}.get(border, 2)
|
|
698
|
+
print('border', border, ['PASS', 'FAIL', 'NONE'][verdict])
|
|
699
|
+
sys.exit(verdict)
|
|
700
|
+
PY
|
|
701
|
+
```
|
|
702
|
+
|
|
703
|
+
Measured: the KickAssembler recipe on PAL printed `border (98, 213, 50)
|
|
704
|
+
PASS` and exited 0; the Oscar64 recipe built with `FORCE_FAIL 1` (the
|
|
705
|
+
define is now `FORCE_FAULT`, set with `-dFORCE_FAULT=1`) on NTSC
|
|
706
|
+
printed `border (169, 71, 100) FAIL` and exited 1. The route reads only
|
|
707
|
+
the border, so it tells pass from fail from "still the power-on light
|
|
708
|
+
blue"; it cannot read the code itself. For that, decode row 7 with the
|
|
709
|
+
char ROM snippet above (`RESULT 01 PASS` or `RESULT 02 FAIL` in the
|
|
710
|
+
recipes), or use a machine route.
|
|
711
|
+
|
|
712
|
+
**Palette-safe grading by channel dominance.** The exact-triple test
|
|
713
|
+
above fails closed on any picture that did not come from `-default` on
|
|
714
|
+
this VICE version: a `.vpl` palette, another release, a capture from a
|
|
715
|
+
real machine. When the program paints only index 5 or index 2, grade by
|
|
716
|
+
which channel dominates instead:
|
|
717
|
+
|
|
718
|
+
```python
|
|
719
|
+
def is_green(c): return c[1] > c[0] + 60 and c[1] > c[2] + 60
|
|
720
|
+
def is_red(c): return c[0] > c[1] + 60 and c[0] > c[2] + 60
|
|
721
|
+
verdict = 0 if is_green(border) else 1 if is_red(border) else 2
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
Against the triples in "The default palette": PAL green (98, 213, 50) has
|
|
725
|
+
G over R by 115 and over B by 163; NTSC green (114, 189, 103) by 75 and
|
|
726
|
+
86. PAL red (175, 60, 88) has R over G by 115 and over B by 87; NTSC red
|
|
727
|
+
(169, 71, 100) by 98 and 69. The power-on border, index 14, is neither on
|
|
728
|
+
either model. Any margin up to 68 accepts NTSC red, whose R exceeds B by
|
|
729
|
+
69; sixty leaves a little room and was the value checked. Run over all
|
|
730
|
+
sixteen triples of both models
|
|
731
|
+
(arithmetic from the table), `is_green` also accepts index 13, light
|
|
732
|
+
green, on PAL (G over R by 72; on NTSC only by 57, so it is rejected
|
|
733
|
+
there), and `is_red` also accepts 8 and 10 on both models and 9 on NTSC.
|
|
734
|
+
Measured on the six exit screenshots of the Oscar64 `headless-verify`
|
|
735
|
+
recipe (default, `-dAUTOPILOT=1` and `-dFORCE_FAULT=1`, PAL and NTSC),
|
|
736
|
+
the dominance test and the exact-triple test gave the same verdict on
|
|
737
|
+
every one.
|
|
738
|
+
|
|
739
|
+
The exact triple remains the right test when the harness must tell the
|
|
740
|
+
pass shade from any other green, index 13 in particular, or red from
|
|
741
|
+
orange and light red; a program that uses those colours elsewhere on the
|
|
742
|
+
screen, or a bar that grades several things by shade, keeps the table
|
|
743
|
+
per model. It is also the test `npm run verify:recipes` implies, since
|
|
744
|
+
that compares whole pictures.
|
|
745
|
+
|
|
746
|
+
### Route 2: the machine, over `-moncommands`
|
|
747
|
+
|
|
748
|
+
A `-moncommands` file runs at startup, before the program, so it cannot
|
|
749
|
+
simply dump `$02FF`. It can arm a tracepoint that dumps it when the store
|
|
750
|
+
happens, and log everything the monitor prints to a file:
|
|
751
|
+
|
|
752
|
+
```
|
|
753
|
+
logname "/tmp/verdict.log"
|
|
754
|
+
log on
|
|
755
|
+
trace store 02ff
|
|
756
|
+
command 1 "m 02ff 02ff"
|
|
757
|
+
```
|
|
758
|
+
|
|
759
|
+
`trace` does not stop the machine; `command 1` runs the memory dump each
|
|
760
|
+
time checkpoint 1 hits; `-limitcycles` still ends the run. The log from
|
|
761
|
+
the green KickAssembler build:
|
|
762
|
+
|
|
763
|
+
```
|
|
764
|
+
#1 (Trace store 02ff) 84/$054, 13/$0d
|
|
765
|
+
.C:fd56 99 00 02 STA $0200,Y - A:00 X:FF Y:FF SP:fd N.-..I.C 5305
|
|
766
|
+
Executing: m 02ff 02ff
|
|
767
|
+
>C:02ff 00
|
|
768
|
+
#1 (Trace store 02ff) 129/$081, 2/$02
|
|
769
|
+
.C:086f 8D FF 02 STA $02FF - A:01 X:00 Y:05 SP:f6 ..-....C 2995841
|
|
770
|
+
Executing: m 02ff 02ff
|
|
771
|
+
>C:02ff 01
|
|
772
|
+
```
|
|
773
|
+
|
|
774
|
+
The first hit is the reset clearing page 2; the second is the program.
|
|
775
|
+
The dump runs after the store: the value on the second hit is `01`, not
|
|
776
|
+
the `00` that was there before it. A harness takes the last `>C:02ff`
|
|
777
|
+
line:
|
|
778
|
+
|
|
779
|
+
```bash
|
|
780
|
+
x64sc -default -warp +sound +autostart-delay-random -autostartprgmode 1 -limitcycles 8000000 \
|
|
781
|
+
-moncommands verdict.mon -autostart prog.prg >/dev/null 2>&1
|
|
782
|
+
code=$(grep '^>C:02ff' /tmp/verdict.log | tail -1 | awk '{print $2}')
|
|
783
|
+
case "$code" in 01) exit 0;; 02) exit 1;; *) exit 2;; esac
|
|
784
|
+
```
|
|
785
|
+
|
|
786
|
+
### A windowless build for batch runs
|
|
787
|
+
|
|
788
|
+
The GTK build opens a window on every launch and takes the desktop's focus,
|
|
789
|
+
which a verifier run of sixty recipes turns into a constant interruption;
|
|
790
|
+
`-minimized` does not help, the window still activates before it shrinks.
|
|
791
|
+
VICE 3.10 ships a third front end besides GTK and SDL: configure the
|
|
792
|
+
source with `--enable-headlessui` and the resulting `x64sc` has no window,
|
|
793
|
+
no Dock tile and never registers with the window server, while the exit
|
|
794
|
+
screenshot still works because it is taken from the emulated frame in the
|
|
795
|
+
machine core. Measured 2026-09-22 on macOS: the headless build's exit
|
|
796
|
+
screenshots for four pinned recipes, PAL and NTSC, were byte-identical to
|
|
797
|
+
the pins, and the process never appeared in LaunchServices while a GTK
|
|
798
|
+
instance next to it was listed as the frontmost application. Two things to
|
|
799
|
+
know: a build that is not installed needs `-directory <vice data dir>` and
|
|
800
|
+
it must come after `-default`, because `-default` resets the search path;
|
|
801
|
+
and the exit status on the cycle limit is 1 by design in both builds. The
|
|
802
|
+
build takes under a minute (`brew install dos2unix xa` first; a plain
|
|
803
|
+
top-level `make` succeeds where `make x64sc` races). In this repository `npm run vice:headless` builds one into `.tools/` with
|
|
804
|
+
the tarball digest pinned and a wrapper that inserts `-directory`, and every
|
|
805
|
+
emulator launch (the verifier, the run tool) prefers it when present, with
|
|
806
|
+
`X64SC_BIN` as an override; every command on this page runs unchanged under
|
|
807
|
+
it.
|
|
808
|
+
|
|
809
|
+
The red Oscar64 build logged `00` then `02` with this file. Do not use
|
|
810
|
+
`watch` or `break` here: a stopping checkpoint enters the monitor with
|
|
811
|
+
nothing to type `x`, cycles stop counting, `-limitcycles` never fires and
|
|
812
|
+
the run hangs. Measured: `watch store 02ff` with the same `command`
|
|
813
|
+
line sat until `timeout 180` killed it (exit 124) and the log was empty.
|
|
814
|
+
The `command` text is one monitor command; whether it can chain a
|
|
815
|
+
continue was not measured here.
|
|
816
|
+
|
|
817
|
+
### Route 3: the machine, over the binary monitor
|
|
818
|
+
|
|
819
|
+
A Python client that speaks the frame format in "The Binary Monitor
|
|
820
|
+
Protocol" above. It sets a store watchpoint on `$02FF` first and only then
|
|
821
|
+
autostarts the program from the monitor, because a client that connects
|
|
822
|
+
to an already-autostarted VICE in warp mode is too late: a first version
|
|
823
|
+
that passed `-autostart` on the command line missed the store on every
|
|
824
|
+
run and reported no verdict. Each stop is handled the same way: read
|
|
825
|
+
`$02FF`; if it is `01` or `02` that is the verdict, otherwise resume.
|
|
826
|
+
|
|
827
|
+
```python
|
|
828
|
+
#!/usr/bin/env python3
|
|
829
|
+
"""Run a PRG in x64sc, watch $02FF over the binary monitor, exit 0 on PASS ($01), 1 on FAIL ($02), 2 otherwise."""
|
|
830
|
+
import socket, struct, subprocess, sys, time, os
|
|
831
|
+
|
|
832
|
+
PRG = sys.argv[1]
|
|
833
|
+
PORT = 6502
|
|
834
|
+
env = dict(os.environ, GSETTINGS_SCHEMA_DIR='/opt/homebrew/share/glib-2.0/schemas')
|
|
835
|
+
vice = subprocess.Popen(['x64sc', '-default', '-warp', '+sound', '+autostart-delay-random',
|
|
836
|
+
'-autostartprgmode', '1', '-limitcycles', '8000000',
|
|
837
|
+
'-binarymonitor', '-binarymonitoraddress', 'ip4://127.0.0.1:%d' % PORT],
|
|
838
|
+
env=env, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
839
|
+
|
|
840
|
+
def frame(op, body=b'', rid=1):
|
|
841
|
+
return b'\x02\x02' + struct.pack('<II', len(body), rid) + bytes([op]) + body
|
|
842
|
+
|
|
843
|
+
def recvn(s, n):
|
|
844
|
+
buf = b''
|
|
845
|
+
while len(buf) < n:
|
|
846
|
+
chunk = s.recv(n - len(buf))
|
|
847
|
+
if not chunk:
|
|
848
|
+
raise EOFError
|
|
849
|
+
buf += chunk
|
|
850
|
+
return buf
|
|
851
|
+
|
|
852
|
+
def response(s):
|
|
853
|
+
stx, api, blen, rtype, err, rid = struct.unpack('<BBIBBI', recvn(s, 12))
|
|
854
|
+
return rtype, err, rid, recvn(s, blen)
|
|
855
|
+
|
|
856
|
+
def wait_for(s, rtype, rid=None):
|
|
857
|
+
while True:
|
|
858
|
+
t, e, r, body = response(s)
|
|
859
|
+
if t == rtype and (rid is None or r == rid):
|
|
860
|
+
return e, body
|
|
861
|
+
|
|
862
|
+
s = None
|
|
863
|
+
for _ in range(100): # VICE takes a moment to open the port
|
|
864
|
+
try:
|
|
865
|
+
s = socket.create_connection(('127.0.0.1', PORT), timeout=1)
|
|
866
|
+
break
|
|
867
|
+
except OSError:
|
|
868
|
+
time.sleep(0.1)
|
|
869
|
+
if s is None:
|
|
870
|
+
sys.exit(2)
|
|
871
|
+
s.settimeout(30)
|
|
872
|
+
|
|
873
|
+
# Checkpoint Set (0x12): start, end, stop, enabled, operation (2 = store), temporary, memspace
|
|
874
|
+
s.sendall(frame(0x12, struct.pack('<HHBBBBB', 0x02ff, 0x02ff, 1, 1, 2, 0, 0), rid=10))
|
|
875
|
+
err, info = wait_for(s, 0x11, 10)
|
|
876
|
+
# Autostart (0xdd) only now, so the watchpoint is in place before the program runs:
|
|
877
|
+
# run after load, file index, filename length, filename
|
|
878
|
+
name = os.path.abspath(PRG).encode()
|
|
879
|
+
s.sendall(frame(0xdd, struct.pack('<BHB', 1, 0, len(name)) + name, rid=11))
|
|
880
|
+
err, _ = wait_for(s, 0xdd, 11)
|
|
881
|
+
verdict = 2
|
|
882
|
+
try:
|
|
883
|
+
while True:
|
|
884
|
+
e, body = wait_for(s, 0x62) # Stopped event: body is the PC
|
|
885
|
+
pc = struct.unpack('<H', body[:2])[0]
|
|
886
|
+
# Memory Get (0x01): side effects, start, end, memspace, bank
|
|
887
|
+
s.sendall(frame(0x01, struct.pack('<BHHBH', 0, 0x02ff, 0x02ff, 0, 0), rid=20))
|
|
888
|
+
e, body = wait_for(s, 0x01, 20)
|
|
889
|
+
value = body[2] # u16 length, then the bytes
|
|
890
|
+
print('stopped at PC=$%04X $02FF=$%02X' % (pc, value))
|
|
891
|
+
if value in (1, 2):
|
|
892
|
+
verdict = 0 if value == 1 else 1
|
|
893
|
+
break
|
|
894
|
+
s.sendall(frame(0xaa, rid=30)) # Exit the monitor: resume
|
|
895
|
+
wait_for(s, 0xaa, 30)
|
|
896
|
+
except (EOFError, socket.timeout):
|
|
897
|
+
print('VICE went away before a verdict was stored')
|
|
898
|
+
try:
|
|
899
|
+
s.sendall(frame(0xbb, rid=40)) # Quit VICE
|
|
900
|
+
wait_for(s, 0xbb, 40)
|
|
901
|
+
except (EOFError, socket.timeout, OSError):
|
|
902
|
+
pass
|
|
903
|
+
vice.wait(timeout=30)
|
|
904
|
+
print('verdict', ['PASS', 'FAIL', 'NONE'][verdict])
|
|
905
|
+
sys.exit(verdict)
|
|
906
|
+
```
|
|
907
|
+
|
|
908
|
+
Measured output, green KickAssembler build:
|
|
909
|
+
|
|
910
|
+
```
|
|
911
|
+
stopped at PC=$FD59 $02FF=$00
|
|
912
|
+
stopped at PC=$0872 $02FF=$01
|
|
913
|
+
verdict PASS
|
|
914
|
+
```
|
|
915
|
+
|
|
916
|
+
exit 0; red Oscar64 build: `PC=$FD59 $02FF=$00`, `PC=$08C6 $02FF=$02`,
|
|
917
|
+
`verdict FAIL`, exit 1. The stop lands after the store (the PC is the
|
|
918
|
+
next instruction, `$FD59` after the three-byte `STA $0200,Y` at `$FD56`),
|
|
919
|
+
so the read is the stored value. The body layouts in the comments are
|
|
920
|
+
the ones VICE 3.10 accepted; they were taken from the VICE binary monitor
|
|
921
|
+
documentation and confirmed only by these runs, not by a wider survey of
|
|
922
|
+
the protocol. The event type `0x62` (stopped) is not in the opcode table above,
|
|
923
|
+
which lists commands only; the reply to Checkpoint Set arrives as type
|
|
924
|
+
`0x11` and the Autostart reply echoes `0xdd`. If VICE exits on `-limitcycles` before a verdict is
|
|
925
|
+
stored the socket closes, `recvn` raises `EOFError`, and the script exits
|
|
926
|
+
2.
|
|
927
|
+
|
|
928
|
+
### Choosing a route
|
|
929
|
+
|
|
930
|
+
The screenshot route needs nothing but the pinned command and is the one
|
|
931
|
+
`npm run verify:recipes` already exercises; it sees the border, not the
|
|
932
|
+
code. The `-moncommands` route sees the byte and needs no second process,
|
|
933
|
+
but its output is a text log to parse. The binary monitor route sees the
|
|
934
|
+
byte, the PC and anything else in the machine, and ends the run itself
|
|
935
|
+
with `Quit` instead of waiting for the cycle limit; it is the one to grow
|
|
936
|
+
into a test runner. All three agree on both builds. None of them was run
|
|
937
|
+
against `sim6502-reference.md`'s VICE backend, which uses a different
|
|
938
|
+
server on port 6510.
|
|
939
|
+
|
|
940
|
+
### Checking every store against the claims: `scripts/claims-watch.ts`
|
|
941
|
+
|
|
942
|
+
Route 2 applied to every store a program makes. The script runs a PRG
|
|
943
|
+
windowless with `trace store` on `$0000-$03FF`, `$D000-$DFFF` and
|
|
944
|
+
`$FFFA-$FFFF` (add `--all-ram` for `$0400-$CFFF` and `$E000-$FFF9`), and
|
|
945
|
+
checks each store against what the program declared:
|
|
946
|
+
|
|
947
|
+
```bash
|
|
948
|
+
node scripts/claims-watch.ts game.prg --recipe docs/recipes/kickassembler/x.md \
|
|
949
|
+
--technique ram_under_kernal --claim 'zero_page $02-$39' \
|
|
950
|
+
--range 'screen=$0400-$07FF,colour=$D800-$DBFF' --screen 0400 \
|
|
951
|
+
--harness cia2_timer_a,cia2_timer_b --kernal IRQ,CHROUT --all-ram
|
|
952
|
+
```
|
|
953
|
+
|
|
954
|
+
- `--technique` and a recipe's `techniques:` add each technique's
|
|
955
|
+
`**Claims:**` units, and those of the techniques it REQUIRES. A technique
|
|
956
|
+
with no Claims line is named in the output; declare its units with
|
|
957
|
+
`--claim`, in the Claims-line grammar.
|
|
958
|
+
- `--range` is the program's own RAM. The PRG's load span is always declared.
|
|
959
|
+
Colour RAM counts as RAM here, not as a unit.
|
|
960
|
+
- `--harness` names measurement timers and counters. Their stores are
|
|
961
|
+
listed apart and never fail the run.
|
|
962
|
+
- `--kernal` names the routines the program calls; `IRQ` and `NMI` name the
|
|
963
|
+
two services. A KERNAL zero-page store must lie inside the union of their
|
|
964
|
+
`(may; ...)` sets in `kernal-routines-reference.md`.
|
|
965
|
+
|
|
966
|
+
Exit 1 on a program store to a unit or byte nobody declared (or declared
|
|
967
|
+
`reads` only), on a KERNAL zero-page store outside the may-sets, or on a
|
|
968
|
+
store the watch cannot attribute (see the banking bullet below).
|
|
969
|
+
|
|
970
|
+
How it reads the log (VICE x64sc 3.10, measured):
|
|
971
|
+
|
|
972
|
+
- The register line of a store hit shows the registers after the
|
|
973
|
+
instruction: a PHA logged `SP:f5` and stored `$01F6`. The hit does not
|
|
974
|
+
log the byte written. So STA, STX and STY give the value, and a push
|
|
975
|
+
lands at `$0100 + SP + 1` to `+3`. Pushes are dropped; other stores to
|
|
976
|
+
page 1 are judged like any RAM.
|
|
977
|
+
- A read-modify-write logs one hit (two `DEC $01` gave two hits). On `$00`
|
|
978
|
+
and `$01` the watch computes the new byte from the last one: INC, DEC,
|
|
979
|
+
ASL, LSR, and ROR (its new bit 7 is the N flag after it). ROL's new
|
|
980
|
+
bit 0 is the carry it shifted in, which the log does not show, so ROL
|
|
981
|
+
leaves the port unknown unless Z is set.
|
|
982
|
+
- An I/O store counts against a unit only for the bits it changes, by the
|
|
983
|
+
last value stored there: `STA $D015` with `$03` over `$01` touches
|
|
984
|
+
sprite 1 only. The first `STA $D011` of a program usually clears bit 7
|
|
985
|
+
that the KERNAL's boot left set (`$9B`), which touches `vic_raster_irq`.
|
|
986
|
+
A read-modify-write touches every unit bit of its register.
|
|
987
|
+
- `$D019` and the CIA interrupt control registers `$DC0D`/`$DD0D` are read
|
|
988
|
+
by the value, not the change. On `$D019` a 1 bit acknowledges its source.
|
|
989
|
+
On an ICR, bits 0-4 name the sources whose mask bit the write sets
|
|
990
|
+
(bit 7 = 1) or clears (bit 7 = 0); timer A is bit 0, timer B bit 1, the
|
|
991
|
+
TOD alarm bit 2 (`cia-reference.md`). `lda #$7f : sta $dc0d` touches
|
|
992
|
+
`cia1_timer_a`, `cia1_timer_b` and `cia1_tod`. Before this rule the
|
|
993
|
+
write changed no unit's bits and was reported as unowned I/O.
|
|
994
|
+
- A store is the KERNAL's when its PC is `$E000` or above and HIRAM is set
|
|
995
|
+
in the last value stored to `$01`; BASIC's when `$A000-$BFFF` with LORAM and
|
|
996
|
+
HIRAM set; otherwise the program's. So code in RAM under a banked-out
|
|
997
|
+
KERNAL is attributed to the program. While `$01` is unknown (after a
|
|
998
|
+
ROL), a store from `$A000-$BFFF` or `$E000-$FFFF` could be either, and it
|
|
999
|
+
fails the run as unattributed. An earlier version assumed ROM there, and
|
|
1000
|
+
also left `$01` unknown after any INC or DEC: a program that banked the
|
|
1001
|
+
KERNAL out with `dec $01` and wrote the SID from `$E000` passed.
|
|
1002
|
+
- Judging starts at the `SYS` address of the BASIC stub (a `trace exec`
|
|
1003
|
+
there). At the first execution of BASIC's READY entry, `$A474`, with
|
|
1004
|
+
BASIC ROM mapped in, the watch stops judging ROM stores: the
|
|
1005
|
+
KickAssembler file round trip, which returns to BASIC, was flagged for
|
|
1006
|
+
`$9D` before this cut, because READY calls SETMSG. The program's own
|
|
1007
|
+
stores after READY (its IRQ or NMI handler) are still judged. An earlier
|
|
1008
|
+
version stopped judging everything at `$A474`, and took a jump to RAM at
|
|
1009
|
+
`$A474` with BASIC banked out as READY; both let a violation pass.
|
|
1010
|
+
|
|
1011
|
+
Four recipes, built and run with `--all-ram` at 8,000,000 cycles PAL (the
|
|
1012
|
+
file round trip at 40,000,000 with a fresh D64):
|
|
1013
|
+
|
|
1014
|
+
| Recipe | Declared from the page alone: violations | What had to be added to pass |
|
|
1015
|
+
|---|---|---|
|
|
1016
|
+
| `kickassembler/sprite-multiplex-game` | `irq_vector_fffe`, `nmi_vector_fffa`, zero page `$02-$39`, screen, colour RAM, `cia2_timer_a`, `cia2_timer_b`; since the ICR rule also `cia1_timer_a`, `cia1_timer_b`, `cia1_tod` (`sta $dc0d`) and `cia2_tod` (`sta $dd0d`) | `ram_under_kernal` (the recipe banks the KERNAL out; its `techniques:` omits it), the zero page, the screen and colour RAM, the two timers and `cia2_tod` as harness, `cia1_timer_a (init), cia1_timer_b (init), cia1_tod (init)` |
|
|
1017
|
+
| `kickassembler/scroll-panel-split` | `irq_vector_fffe`, screen `$0400-$0747`, panel `$0F20-$0FE7`, `$3FFF`, colour RAM | `ram_under_kernal`, the ranges; `soft_scroll_v` and `char_scroll_buffer_v` have no Claims line |
|
|
1018
|
+
| `oscar64/sfx-engine` | Oscar64 runtime zero page (`$0D-$56` seen), BSS, its stack at `$9FFC-$9FFF`, screen, colour RAM, `cia1_timer_a` | the zero page, the map file's BSS and stack, the screen and colour RAM, `cia1_timer_a` as harness |
|
|
1019
|
+
| `kickassembler/file-io-roundtrip` | `cia2_timer_a`, `cia2_timer_b` | the two timers as harness; every KERNAL zero-page store fell inside the ten routines' may-sets |
|
|
1020
|
+
|
|
1021
|
+
A variant of the multiplexer with `sta $d40b` and `sta $fb` added at its
|
|
1022
|
+
entry failed with exactly those two stores, `sid_voice_2` and zero page
|
|
1023
|
+
`$FB`. The KERNAL's serial routines in the file round trip write
|
|
1024
|
+
`cia1_timer_b`: `STA $DC07` and `STA $DC0F` at `$ED94`/`$ED99` and
|
|
1025
|
+
`$EE22`/`$EE27` (ROM bytes `8D 07 DC`, `8D 0F DC`). The count varies by
|
|
1026
|
+
run (212 and 314 seen). A program that owns `cia1_timer_b` loses it
|
|
1027
|
+
across a disk call.
|
|
1028
|
+
|
|
1029
|
+
Four probes, built with KickAssembler and run in x64sc, fail on their
|
|
1030
|
+
`sta $d40b`: an IRQ handler that writes it after the program returns to
|
|
1031
|
+
BASIC; a jump to `$A474` with BASIC banked out; `dec $01` twice, then code
|
|
1032
|
+
at `$E000`; `rol $01`, then code at `$A000` (unattributed).
|
|
1033
|
+
|
|
1034
|
+
What the watch does not see:
|
|
1035
|
+
|
|
1036
|
+
- Writes by DMA (an REU, a cartridge) are not CPU stores, and `trace store`
|
|
1037
|
+
is not expected to log them (not measured here).
|
|
1038
|
+
- The register mirrors (VIC `$D040-$D3FF`, SID `$D420-$D7FF`, each CIA's
|
|
1039
|
+
`$xx10-$xxFF`) are not mapped to units: a store to one is reported as
|
|
1040
|
+
unowned I/O and never fails the run.
|
|
1041
|
+
- ROM stores to I/O and RAM outside zero page are listed, not judged; after
|
|
1042
|
+
READY, ROM stores are dropped.
|
|
1043
|
+
- Without `--all-ram`, stores to `$0400-$CFFF` and `$E000-$FFF9` are not
|
|
1044
|
+
traced.
|
|
1045
|
+
- A read-modify-write on an I/O register is valued as unknown, so it
|
|
1046
|
+
touches every unit bit there.
|
|
1047
|
+
|
|
1048
|
+
---
|
|
1049
|
+
|
|
1050
|
+
## Text monitor for debugging
|
|
1051
|
+
|
|
1052
|
+
Everything in this section was measured on 2026-09-22 with VICE x64sc
|
|
1053
|
+
3.10 `-default` (PAL) on the PRG built from
|
|
1054
|
+
`docs/recipes/kickassembler/stable-raster-irq.md` with `-vicesymbols`.
|
|
1055
|
+
Every command and output line below is quoted from those sessions.
|
|
1056
|
+
Disassembly from the monitor is the subject of
|
|
1057
|
+
[issue #3](https://github.com/bdgscotland/c64-kb/issues/3) and is not
|
|
1058
|
+
covered here.
|
|
1059
|
+
|
|
1060
|
+
### Getting a prompt
|
|
1061
|
+
|
|
1062
|
+
The GTK build's `-console` flag does not put the monitor on stdio. With
|
|
1063
|
+
`-console`, a `-moncommands` file containing `break .start`, and stdin
|
|
1064
|
+
fed from a pipe or a pty, the machine stopped at the breakpoint (it never
|
|
1065
|
+
reached `-limitcycles`) but no stop line and no prompt ever appeared on
|
|
1066
|
+
stdout: `timeout 60` killed it and a `logname`/`log on` monitor log stayed
|
|
1067
|
+
empty. The route that works headless is the remote
|
|
1068
|
+
text monitor, a TCP port that speaks the same commands:
|
|
1069
|
+
|
|
1070
|
+
```bash
|
|
1071
|
+
GSETTINGS_SCHEMA_DIR=/opt/homebrew/share/glib-2.0/schemas timeout 180 x64sc -default -warp +sound \
|
|
1072
|
+
+autostart-delay-random -autostartprgmode 1 -limitcycles 6000000 \
|
|
1073
|
+
-remotemonitor -remotemonitoraddress ip4://127.0.0.1:6510 \
|
|
1074
|
+
-moncommands session.mon -autostart stable-raster-irq.prg
|
|
1075
|
+
```
|
|
1076
|
+
|
|
1077
|
+
`session.mon` loads the labels and arms the first stop before the program
|
|
1078
|
+
runs:
|
|
1079
|
+
|
|
1080
|
+
```text
|
|
1081
|
+
ll "stable-raster-irq.vs"
|
|
1082
|
+
break .start
|
|
1083
|
+
```
|
|
1084
|
+
|
|
1085
|
+
Connect to the port with a TCP client, and connect it before the first
|
|
1086
|
+
checkpoint fires. A stop with no client connected leaves the machine
|
|
1087
|
+
stopped with no way in: a client that connected 8 seconds after launch,
|
|
1088
|
+
once `break .start` had already fired, received nothing, its `r` and `x`
|
|
1089
|
+
got no reply, and x64sc was still stopped 20 seconds later when it was
|
|
1090
|
+
killed. That is the same hang as `-console`. Under `-warp` the `break
|
|
1091
|
+
.start` stop fired 0.40 s after launch (the client had connected at
|
|
1092
|
+
0.09 s) and a boot-time watch fires sooner still, so start the client
|
|
1093
|
+
from the same script and poll the port from the moment x64sc is
|
|
1094
|
+
launched; the sessions here used a Python socket polling every 0.3 s for
|
|
1095
|
+
the break and every 0.01 s for the watch, which the slower poll missed
|
|
1096
|
+
twice. `nc 127.0.0.1 6510` by hand only works when the first stop is far
|
|
1097
|
+
enough out: drop `-warp`, or arm the watch from the prompt after a
|
|
1098
|
+
scripted first break. Once the client is connected VICE writes each stop
|
|
1099
|
+
to it and reads commands from it. Port 6510 is the one
|
|
1100
|
+
`sim6502-reference.md`'s VICE backend uses;
|
|
1101
|
+
choose another if both run. `-initbreak 0x900` (or `-initbreak 2304`)
|
|
1102
|
+
sets the same first breakpoint with no file and no labels. `-initbreak
|
|
1103
|
+
$0900` is refused before the emulator starts:
|
|
1104
|
+
|
|
1105
|
+
```text
|
|
1106
|
+
Argument '$0900' not valid for option `-initbreak'.
|
|
1107
|
+
Error parsing command-line options, bailing out. For help use '-help'
|
|
1108
|
+
```
|
|
1109
|
+
|
|
1110
|
+
### The stop and the register line
|
|
1111
|
+
|
|
1112
|
+
```text
|
|
1113
|
+
#1 (Stop on exec 0900) 36/$024, 59/$3b
|
|
1114
|
+
.C:0900 78 SEI - A:00 X:00 Y:00 SP:f6 ..-..... 2970383
|
|
1115
|
+
(C:$0900)
|
|
1116
|
+
```
|
|
1117
|
+
|
|
1118
|
+
The first line is the checkpoint number, its kind and address, then the
|
|
1119
|
+
raster line and the cycle within it, each as decimal/hex. The second is
|
|
1120
|
+
the instruction about to execute, not yet executed: memory space and PC,
|
|
1121
|
+
opcode bytes, the disassembly with labels substituted, the registers, the
|
|
1122
|
+
flags as `NV-BDIZC` with a letter for set and `.` for clear, and the
|
|
1123
|
+
stopwatch, a cycle count since power-on. The prompt carries the current
|
|
1124
|
+
address.
|
|
1125
|
+
|
|
1126
|
+
`r` prints the same state as a table:
|
|
1127
|
+
|
|
1128
|
+
```text
|
|
1129
|
+
(C:$0900) r
|
|
1130
|
+
ADDR A X Y SP 00 01 NV-BDIZC LIN CYC STOPWATCH
|
|
1131
|
+
.;0900 00 00 00 f6 2f 37 00100000 036 059 2970383
|
|
1132
|
+
```
|
|
1133
|
+
|
|
1134
|
+
`00` and `01` are the 6510 port bytes at `$0000` and `$0001`. `LIN` and
|
|
1135
|
+
`CYC` are the raster line and the cycle within it, decimal. Two steps
|
|
1136
|
+
later (`SEI` then `LDA #$7F`, 2 cycles each) the line read `037 000` at
|
|
1137
|
+
stopwatch `2970387`: cycle 59 plus 4 is 63, which wraps to cycle 0 of the
|
|
1138
|
+
next line. That is the PAL 63 cycles per line, seen from the register
|
|
1139
|
+
line.
|
|
1140
|
+
|
|
1141
|
+
### step, next and until
|
|
1142
|
+
|
|
1143
|
+
```text
|
|
1144
|
+
(C:$0900) step
|
|
1145
|
+
.C:0901 A9 7F LDA #$7F - A:00 X:00 Y:00 SP:f6 ..-..I.. 2970385
|
|
1146
|
+
(C:$0901) step
|
|
1147
|
+
.C:0903 8D 0D DC STA $DC0D - A:7F X:00 Y:00 SP:f6 ..-..I.. 2970387
|
|
1148
|
+
(C:$0903) next
|
|
1149
|
+
.C:0906 AD 0D DC LDA $DC0D - A:7F X:00 Y:00 SP:f6 ..-..I.. 2970391
|
|
1150
|
+
```
|
|
1151
|
+
|
|
1152
|
+
`step` (abbreviation `z`) executes one instruction and prints the next.
|
|
1153
|
+
`next` (`n`) does the same but runs a `JSR` through to its `RTS` as one
|
|
1154
|
+
instruction. Both take an optional count. `until .irq2` (`un`) sets a
|
|
1155
|
+
one-shot breakpoint and resumes; it printed `UNTIL: 2 C:$0976 (Stop on
|
|
1156
|
+
exec)`, and when another checkpoint fired first that one won and the
|
|
1157
|
+
one-shot stayed armed. `x` resumes.
|
|
1158
|
+
|
|
1159
|
+
### break, watch and conditions
|
|
1160
|
+
|
|
1161
|
+
The monitor's own `help` lines:
|
|
1162
|
+
|
|
1163
|
+
```text
|
|
1164
|
+
Syntax: break [load|store|exec] [address [address] [if <cond_expr>]]
|
|
1165
|
+
Syntax: watch [load|store|exec] [address [address] [if <cond_expr>]]
|
|
1166
|
+
Syntax: condition <checknum> if <cond_expr>
|
|
1167
|
+
```
|
|
1168
|
+
|
|
1169
|
+
`break` defaults to `exec`; `watch` defaults to `load` and `store`
|
|
1170
|
+
(`watch .irq2_line` was listed as `WATCH: 2 C:$09d8 (Stop on load
|
|
1171
|
+
store)`). A store watchpoint on a program variable fires before the
|
|
1172
|
+
program runs,
|
|
1173
|
+
because the KERNAL reset's RAM test writes every byte. `watch store
|
|
1174
|
+
.irq2_line` in the `-moncommands` file stopped three times at boot:
|
|
1175
|
+
|
|
1176
|
+
```text
|
|
1177
|
+
#1 (Stop on store 09d8) 24/$018, 50/$32
|
|
1178
|
+
.C:fd73 91 C1 STA ($C1),Y - A:55 X:00 Y:D8 SP:fd ..-..I.C 80186
|
|
1179
|
+
```
|
|
1180
|
+
|
|
1181
|
+
then at `$FD7A` with `A:AB` and `$FD81` with `A:00`, and only on the
|
|
1182
|
+
fourth `x` at the program's own store, with the label in the operand:
|
|
1183
|
+
|
|
1184
|
+
```text
|
|
1185
|
+
#1 (Stop on store 09d8) 68/$044, 23/$17
|
|
1186
|
+
.C:09be 8D D8 09 STA .irq2_line - A:4C X:01 Y:00 SP:f0 ..-..I.. 2972363
|
|
1187
|
+
```
|
|
1188
|
+
|
|
1189
|
+
Type `x` through the boot hits, or arm the watch from the prompt after a
|
|
1190
|
+
breakpoint in the program.
|
|
1191
|
+
|
|
1192
|
+
A condition compares registers (`A`, `X`, `Y`, `PC`, `SP`, `FL`), `RL`
|
|
1193
|
+
(the raster line), `CY` (the cycle within it) or memory
|
|
1194
|
+
(`@io:$d020 == $f0`) with `==`, `!=`, `<`, `>`, `<=`, `>=`, and joins
|
|
1195
|
+
them with `&&`, `||` and arithmetic. `break .bar_line if Y == 3` in the
|
|
1196
|
+
`-moncommands` file stopped at:
|
|
1197
|
+
|
|
1198
|
+
```text
|
|
1199
|
+
#1 (Stop on exec 098e) 64/$040, 13/$0d
|
|
1200
|
+
.C:098e A9 01 LDA #$01 - A:06 X:00 Y:03 SP:f0 ..-..I.. 2972101
|
|
1201
|
+
(C:$098e) break
|
|
1202
|
+
BREAK: 1 C:$098e (Stop on exec)
|
|
1203
|
+
Condition: Y == $03
|
|
1204
|
+
(C:$098e) cond 1 if Y == 1
|
|
1205
|
+
Setting checkpoint 1 condition to: Y == $01
|
|
1206
|
+
(C:$098e) x
|
|
1207
|
+
#1 (Stop on exec 098e) 66/$042, 13/$0d
|
|
1208
|
+
.C:098e A9 01 LDA #$01 - A:06 X:00 Y:01 SP:f0 ..-..I.. 2972227
|
|
1209
|
+
```
|
|
1210
|
+
|
|
1211
|
+
`break` or `watch` with no argument lists the checkpoints of that kind.
|
|
1212
|
+
`delete 1` removes one; `delete` alone prints `Deleting all checkpoints`.
|
|
1213
|
+
Numbers are reused: after deleting checkpoints 1 and 2 the next `break`
|
|
1214
|
+
was numbered 1 again. `cond` on a number that does not exist says `#3 not
|
|
1215
|
+
a valid checkpoint`. A bare number in a condition is hex: `break
|
|
1216
|
+
.bar_line if RL == 70 && Y == 2` was echoed as `Setting checkpoint 3
|
|
1217
|
+
condition to: RL == $70 && Y == $02`, which is raster line 112, not 70.
|
|
1218
|
+
Write `RL == $c8` or `RL == c8` for line 200.
|
|
1219
|
+
|
|
1220
|
+
### Measuring cycles between two points
|
|
1221
|
+
|
|
1222
|
+
Two register lines at the same breakpoint, one `x` apart. `.bar_line` is
|
|
1223
|
+
the top of the recipe's one-raster-line loop:
|
|
1224
|
+
|
|
1225
|
+
```text
|
|
1226
|
+
.;098e 3c f0 06 f0 2f 37 00100100 061 013 2971912
|
|
1227
|
+
.;098e 06 00 05 f0 2f 37 00100100 062 013 2971975
|
|
1228
|
+
```
|
|
1229
|
+
|
|
1230
|
+
2971975 − 2971912 = 63 cycles: `LIN` went up by one and `CYC` stayed at
|
|
1231
|
+
13. The third hit was at 2972038, 63 again. Cross-checked two ways.
|
|
1232
|
+
Arithmetic from the listing's own cycle column: 2 + 4 + 4 + 2 + 4 + 2 +
|
|
1233
|
+
4 + 2 + (7 × 5 − 1) + 2 + 3 = 63. sim6502 (`--backend sim`, commit
|
|
1234
|
+
d6f6812) on the same PRG with `jsr([bar_line], stop_on_address = $09a8)`
|
|
1235
|
+
reported 129 cycles with `y = 2` and 66 with `y = 1`, a difference of 63;
|
|
1236
|
+
each figure carries 4 cycles beyond the loop itself, the difference does
|
|
1237
|
+
not.
|
|
1238
|
+
|
|
1239
|
+
The stopwatch counts only while the machine runs. Twenty seconds of real
|
|
1240
|
+
time at the prompt left it at `2970383`; `r` before and after read the
|
|
1241
|
+
same line.
|
|
1242
|
+
|
|
1243
|
+
### Memory dump and save
|
|
1244
|
+
|
|
1245
|
+
```text
|
|
1246
|
+
(C:$0906) m 0900 090f
|
|
1247
|
+
>C:0900 78 a9 7f 8d 0d dc ad 0d dc a9 34 8d 14 03 a9 09 X..
|
|
1248
|
+
(C:$0910)
|
|
1249
|
+
```
|
|
1250
|
+
|
|
1251
|
+
Sixteen bytes per row, a PETSCII column after them (trimmed here), and
|
|
1252
|
+
the prompt moves to the byte after the dump. `m .irq2_line` with a label
|
|
1253
|
+
and no end address printed nine rows (`$09D8` to `$0A67`) and left the
|
|
1254
|
+
prompt at `(C:$0a68)`. The full syntax is
|
|
1255
|
+
`mem [<data_type>] [<address_opt_range>]`.
|
|
1256
|
+
|
|
1257
|
+
```text
|
|
1258
|
+
(C:$0900) save "/tmp/saved.prg" 0 0900 09ff
|
|
1259
|
+
Saving file '/tmp/saved.prg' from $0900 to $09ff
|
|
1260
|
+
```
|
|
1261
|
+
|
|
1262
|
+
Device 0 is the host file system. The file was 258 bytes: the two-byte
|
|
1263
|
+
load address `00 09` and the 256 bytes, a PRG that loads back where it
|
|
1264
|
+
came from.
|
|
1265
|
+
|
|
1266
|
+
### `-limitcycles` and a stopped machine
|
|
1267
|
+
|
|
1268
|
+
`-limitcycles` counts emulated cycles and the monitor stops the clock.
|
|
1269
|
+
Three consequences, each measured:
|
|
1270
|
+
|
|
1271
|
+
- A breakpoint past the limit never fires. With `-limitcycles 1000000`
|
|
1272
|
+
and `break .start`, which fires at stopwatch 2,970,383 on this PRG,
|
|
1273
|
+
VICE exited with status 1 and printed no stop.
|
|
1274
|
+
- A machine left at the prompt never exits. A session that ended stopped
|
|
1275
|
+
at `.bar_line` was still there when `timeout` killed it. After `x` with
|
|
1276
|
+
no further stop ahead the remaining cycles run and the limit exit
|
|
1277
|
+
happens as usual, status 1.
|
|
1278
|
+
- Real time at the prompt costs nothing on the stopwatch (the twenty
|
|
1279
|
+
seconds above).
|
|
1280
|
+
|
|
1281
|
+
This is the fact behind Route 2's warning: a stopping checkpoint in a
|
|
1282
|
+
`-moncommands` file with no client connected hangs the run.
|
|
1283
|
+
|
|
1284
|
+
Related pages: the binary monitor for the same operations from a
|
|
1285
|
+
program is "The Binary Monitor Protocol" above and
|
|
1286
|
+
[vice-mcp-reference.md](vice-mcp-reference.md); cycle assertions without
|
|
1287
|
+
an emulator are [sim6502-reference.md](sim6502-reference.md); the label
|
|
1288
|
+
files each toolchain writes are in "Symbol Files" above and in the
|
|
1289
|
+
KickAssembler, Oscar64 and cc65 pages' debugging sections.
|
|
1290
|
+
|
|
1291
|
+
---
|
|
1292
|
+
|
|
1293
|
+
## Integration with vice-mcp
|
|
1294
|
+
|
|
1295
|
+
vice-mcp is a separate MCP server that acts as a bridge between agents and a running
|
|
1296
|
+
VICE instance. It maintains a TCP connection to VICE's binary monitor, translates MCP
|
|
1297
|
+
tool calls into binary monitor frames, and returns structured results. Agents invoke
|
|
1298
|
+
vice-mcp tools such as `vice_read_memory`, `vice_set_breakpoint`, `vice_screenshot`, and
|
|
1299
|
+
`vice_autostart`; they never send raw binary monitor frames.
|
|
1300
|
+
|
|
1301
|
+
From a deployment perspective: start `x64sc` first with `-binarymonitor
|
|
1302
|
+
-binarymonitoraddress ip4://127.0.0.1:6502`, then start the vice-mcp server, which
|
|
1303
|
+
connects to that address. Both processes run concurrently for the duration of the
|
|
1304
|
+
inspection session.
|
|
1305
|
+
|
|
1306
|
+
See [vice-mcp-reference.md](vice-mcp-reference.md) for the full tool surface.
|
|
1307
|
+
|
|
1308
|
+
---
|
|
1309
|
+
|
|
1310
|
+
## Pitfalls
|
|
1311
|
+
|
|
1312
|
+
### x64 (fast) vs x64sc (cycle-accurate)
|
|
1313
|
+
|
|
1314
|
+
`x64` skips the cycle-exact 6510 core and uses a timing approximation. It runs faster
|
|
1315
|
+
but breaks any code that depends on precise cycle counts: raster IRQs, sprite
|
|
1316
|
+
multiplexers, SID timing, and CIA timer-based effects will behave incorrectly or
|
|
1317
|
+
intermittently. Always use `x64sc` when verifying code against hardware. The speed
|
|
1318
|
+
penalty is acceptable for automated runs with `-warp`.
|
|
1319
|
+
|
|
1320
|
+
### Default keyboard layout
|
|
1321
|
+
|
|
1322
|
+
VICE picks the host keyboard layout from the locale (LANG/LC_ALL) at RUN time, not
|
|
1323
|
+
build time as an earlier version of this page said: the same x64sc 3.10 binary loads
|
|
1324
|
+
`gtk3_sym.vkm` under `en_US` and `gtk3_sym_de.vkm` under `de_DE.UTF-8` (measured with
|
|
1325
|
+
`-default`). The default keymap type is symbolic (KeymapIndex 0). Code injected via
|
|
1326
|
+
`Keyboard Feed` (`0x72`) sends raw PETSCII, so this does not affect monitor or
|
|
1327
|
+
programmatic input, but it matters when a test scenario types characters through the
|
|
1328
|
+
emulated keyboard. Pass `-keymap 0 -keyboardmapping 0` explicitly for a US symbolic
|
|
1329
|
+
keymap regardless of host locale. There is no `-keyboard` option: `-keyboard en` is
|
|
1330
|
+
rejected as ambiguous (it is a prefix of `-keyboardmapping`, `-keyboardtype` and
|
|
1331
|
+
`-keyboardstatusbar`).
|
|
1332
|
+
|
|
1333
|
+
### ROM image licensing
|
|
1334
|
+
|
|
1335
|
+
The VICE source tarball ships the Commodore ROM images (kernal, basic, chargen) in its
|
|
1336
|
+
data/ tree, and the Homebrew formula installs them from that tarball into
|
|
1337
|
+
`/opt/homebrew/share/vice/C64/` — nothing is fetched separately (an earlier version of
|
|
1338
|
+
this page said the formula downloaded them from a community source; `brew cat vice` has
|
|
1339
|
+
no such resource). Some Linux distributions strip them for licensing reasons: Debian's
|
|
1340
|
+
`vice` package lives in contrib and explicitly excludes the ROMs (see its README.ROMs),
|
|
1341
|
+
so there you must obtain them yourself. In that case, and in any Docker or CI image
|
|
1342
|
+
built from such a package, supply the ROM images and point VICE at them via `-kernal`,
|
|
1343
|
+
`-basic`, and `-chargen`, or place them in the expected directory. Failure to provide
|
|
1344
|
+
ROMs produces a startup error and a blank screen.
|
|
1345
|
+
|
|
1346
|
+
### Monitor port conflicts
|
|
1347
|
+
|
|
1348
|
+
Port 6502 may be in use if multiple VICE instances or other tools occupy it. Pass a
|
|
1349
|
+
different port via `-binarymonitoraddress ip4://127.0.0.1:6510` (or any free port) when
|
|
1350
|
+
running parallel test instances.
|
|
1351
|
+
|
|
1352
|
+
### macOS Homebrew: g_settings_new crash on launch
|
|
1353
|
+
|
|
1354
|
+
On macOS Homebrew (`brew install vice`, 3.10 at time of writing) both `x64` and
|
|
1355
|
+
`x64sc` crash at launch with:
|
|
1356
|
+
|
|
1357
|
+
```
|
|
1358
|
+
GLib-GIO-ERROR **: No GSettings schemas are installed on the system
|
|
1359
|
+
```
|
|
1360
|
+
|
|
1361
|
+
The compiled schemas DO exist at `/opt/homebrew/share/glib-2.0/schemas/`, but
|
|
1362
|
+
GTK3 doesn't search that path by default. Export the schema location before
|
|
1363
|
+
launching:
|
|
1364
|
+
|
|
1365
|
+
```bash
|
|
1366
|
+
export XDG_DATA_DIRS="/opt/homebrew/share:/usr/local/share:/usr/share:$XDG_DATA_DIRS"
|
|
1367
|
+
export GSETTINGS_SCHEMA_DIR="/opt/homebrew/share/glib-2.0/schemas"
|
|
1368
|
+
x64sc -binarymonitor -binarymonitoraddress ip4://127.0.0.1:6502 -autostart hello.prg
|
|
1369
|
+
```
|
|
1370
|
+
|
|
1371
|
+
The template harness (`templates/_harness/harness.mk`) exports
|
|
1372
|
+
`GSETTINGS_SCHEMA_DIR` for its `run` target, which is enough on this machine. They are harmless on Linux (the
|
|
1373
|
+
paths just don't exist).
|
|
1374
|
+
|
|
1375
|
+
This is a packaging issue in the Homebrew GTK3 bottle, not a VICE bug.
|
|
1376
|
+
|
|
1377
|
+
### True drive emulation and speed
|
|
1378
|
+
|
|
1379
|
+
When `-drive8type 1541` is active with true drive emulation enabled (the default in
|
|
1380
|
+
`x64sc`), disk access is cycle-accurate and slow even in warp mode. If load time
|
|
1381
|
+
dominates a test run and timing accuracy of the drive is not the subject of the test,
|
|
1382
|
+
disable true drive emulation for unit 8 with `+drive8truedrive` to use the faster IEC
|
|
1383
|
+
fast-path (the option is per unit — `+drive9truedrive` … `+drive11truedrive` likewise —
|
|
1384
|
+
since VICE 3.6; a bare `+truedrive`, which an earlier version of this page gave, is
|
|
1385
|
+
rejected as an unknown option by x64sc 3.10).
|
|
1386
|
+
|
|
1387
|
+
---
|
|
1388
|
+
|
|
1389
|
+
## See Also
|
|
1390
|
+
|
|
1391
|
+
- [vice-mcp-reference.md](vice-mcp-reference.md) — MCP tool surface for agent-driven VICE control
|
|
1392
|
+
- [../formats/c64-file-formats.md](../formats/c64-file-formats.md) — PRG, CRT, D64, and other C64 file format details
|
|
1393
|
+
- [../hardware/pal-ntsc-reference.md](../hardware/pal-ntsc-reference.md) — PAL vs NTSC hardware differences and timing tables
|