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,179 @@
|
|
|
1
|
+
// verdict.asm: AUTOPILOT only. Once the main part has frozen, the main loop
|
|
2
|
+
// reads the demo's real state back and grades it against what the assembler
|
|
3
|
+
// predicts from config.asm. $02FF = $01 and a green border on pass, $02 and
|
|
4
|
+
// red on fail; "RESULT 01 PASS" or "RESULT 02 FAIL" on row 24.
|
|
5
|
+
|
|
6
|
+
.const EXP_PX = (FREEZE_UPDATES * CHAIN_SX) & 255 // the frozen phases
|
|
7
|
+
.const EXP_PY = (FREEZE_UPDATES * CHAIN_SY) & 255
|
|
8
|
+
.const EXP_PB = (FREEZE_UPDATES * BAR_SPEED) & 255
|
|
9
|
+
.const EXP_SHIFTS = floor(FREEZE_UPDATES / 8) // XSCROLL 7 - (k mod 8)
|
|
10
|
+
.const EXP_XSCROLL = 7 - mod(FREEZE_UPDATES, 8)
|
|
11
|
+
|
|
12
|
+
.function SinR(amp, step) { .return round(amp * sin(toRadians(step * 360 / 256))) }
|
|
13
|
+
.function ExpX(n) { .return CHAIN_X0 + n * CHAIN_DX + SinR(CHAIN_AX, (EXP_PX + n * CHAIN_PX) & 255) }
|
|
14
|
+
.function ExpY(n) { .return CHAIN_Y0 + SinR(CHAIN_AY, (EXP_PY + n * CHAIN_PY) & 255) }
|
|
15
|
+
|
|
16
|
+
.var msb_bits = 0
|
|
17
|
+
.for (var n = 0; n < 8; n++) {
|
|
18
|
+
.if (ExpX(n) > 255) .eval msb_bits = msb_bits | (1 << n)
|
|
19
|
+
}
|
|
20
|
+
.const exp_msb = msb_bits
|
|
21
|
+
|
|
22
|
+
// A failed check jumps to vfail; the checks are too long for one branch.
|
|
23
|
+
.macro FailNe() {
|
|
24
|
+
beq !+
|
|
25
|
+
jmp vfail
|
|
26
|
+
!:
|
|
27
|
+
}
|
|
28
|
+
.macro FailEq() {
|
|
29
|
+
bne !+
|
|
30
|
+
jmp vfail
|
|
31
|
+
!:
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
verdict:
|
|
35
|
+
jsr hard_cut // no part in the table names hard_cut, so the
|
|
36
|
+
bcs !+ // verdict runs it: it must end a part (carry set)
|
|
37
|
+
jmp vfail
|
|
38
|
+
!:
|
|
39
|
+
lda part // the transition happened: the main part plays,
|
|
40
|
+
cmp #MAIN_PART // the wipe cleared all 40 columns, the
|
|
41
|
+
FailNe() // title's teardown ran
|
|
42
|
+
lda seq_state
|
|
43
|
+
cmp #PLAY
|
|
44
|
+
FailNe()
|
|
45
|
+
lda tr_step
|
|
46
|
+
cmp #40
|
|
47
|
+
FailNe()
|
|
48
|
+
lda title_done
|
|
49
|
+
FailEq()
|
|
50
|
+
.for (var n = 0; n < 8; n++) { // the chain against the sine formula
|
|
51
|
+
lda $d000 + 2 * n
|
|
52
|
+
cmp #<ExpX(n)
|
|
53
|
+
FailNe()
|
|
54
|
+
lda $d001 + 2 * n
|
|
55
|
+
cmp #ExpY(n)
|
|
56
|
+
FailNe()
|
|
57
|
+
}
|
|
58
|
+
lda $d010
|
|
59
|
+
cmp #exp_msb
|
|
60
|
+
FailNe()
|
|
61
|
+
lda xscroll // the scroller: phase, read pointer, row 22
|
|
62
|
+
cmp #EXP_XSCROLL
|
|
63
|
+
FailNe()
|
|
64
|
+
lda msg_read+1
|
|
65
|
+
cmp #<(message + MSG_START + EXP_SHIFTS)
|
|
66
|
+
FailNe()
|
|
67
|
+
lda msg_read+2
|
|
68
|
+
cmp #>(message + MSG_START + EXP_SHIFTS)
|
|
69
|
+
FailNe()
|
|
70
|
+
ldx #37
|
|
71
|
+
!: lda SCREEN + SCROLL_ROW * 40 + 1,x
|
|
72
|
+
cmp message + EXP_SHIFTS + 1,x
|
|
73
|
+
FailNe()
|
|
74
|
+
dex
|
|
75
|
+
bpl !-
|
|
76
|
+
ldx #BARS_LINES - 1 // the bar table the kernel draws
|
|
77
|
+
!: lda bar_colours,x
|
|
78
|
+
cmp exp_bars,x
|
|
79
|
+
FailNe()
|
|
80
|
+
dex
|
|
81
|
+
bpl !-
|
|
82
|
+
lda music_calls // every frame slot played or (NTSC) skipped
|
|
83
|
+
clc
|
|
84
|
+
adc music_skips
|
|
85
|
+
tax
|
|
86
|
+
lda music_calls+1
|
|
87
|
+
adc music_skips+1
|
|
88
|
+
cmp frames+1
|
|
89
|
+
FailNe()
|
|
90
|
+
cpx frames
|
|
91
|
+
FailNe()
|
|
92
|
+
lda music_skips // PAL never skips; NTSC skips one in six
|
|
93
|
+
ora music_skips+1
|
|
94
|
+
ldx model
|
|
95
|
+
beq !pal+
|
|
96
|
+
cmp #0
|
|
97
|
+
FailEq()
|
|
98
|
+
jmp !pass+
|
|
99
|
+
!pal: cmp #0
|
|
100
|
+
FailNe()
|
|
101
|
+
!pass:
|
|
102
|
+
lda irq_late // every IRQ on its line, every chain whole,
|
|
103
|
+
ora irq_bad // every frame slot done before the next chain
|
|
104
|
+
ora frame_late
|
|
105
|
+
FailNe()
|
|
106
|
+
// The player's place against its call count: after c calls the
|
|
107
|
+
// tick is c mod STEP_FRAMES and the step (c div STEP_FRAMES) mod
|
|
108
|
+
// STEPS. Read together, with the IRQ that advances them held off.
|
|
109
|
+
sei
|
|
110
|
+
lda music_calls
|
|
111
|
+
sta v_calls
|
|
112
|
+
lda music_calls+1
|
|
113
|
+
sta v_calls+1
|
|
114
|
+
lda m_tick
|
|
115
|
+
sta v_tick
|
|
116
|
+
lda m_step
|
|
117
|
+
sta v_step
|
|
118
|
+
cli
|
|
119
|
+
ldx #0 // v_calls div STEP_FRAMES, low byte in X
|
|
120
|
+
!: lda v_calls
|
|
121
|
+
sec
|
|
122
|
+
sbc #STEP_FRAMES
|
|
123
|
+
tay
|
|
124
|
+
lda v_calls+1
|
|
125
|
+
sbc #0
|
|
126
|
+
bcc !+
|
|
127
|
+
sta v_calls+1
|
|
128
|
+
sty v_calls
|
|
129
|
+
inx
|
|
130
|
+
jmp !-
|
|
131
|
+
!: lda v_calls // the remainder
|
|
132
|
+
cmp v_tick
|
|
133
|
+
FailNe()
|
|
134
|
+
txa
|
|
135
|
+
and #STEPS - 1
|
|
136
|
+
cmp v_step
|
|
137
|
+
FailNe()
|
|
138
|
+
lda #1
|
|
139
|
+
ldy #5
|
|
140
|
+
ldx #0
|
|
141
|
+
jmp !say+
|
|
142
|
+
vfail: lda #2
|
|
143
|
+
ldy #2
|
|
144
|
+
ldx #pass_end - pass
|
|
145
|
+
!say: sta RESULT
|
|
146
|
+
sty border_colour // the bar kernel writes it after the last bar
|
|
147
|
+
sty $d020
|
|
148
|
+
ldy #0
|
|
149
|
+
!: lda pass,x
|
|
150
|
+
sta SCREEN + 24 * 40 + 1,y
|
|
151
|
+
lda #1
|
|
152
|
+
sta COLOUR + 24 * 40 + 1,y
|
|
153
|
+
inx
|
|
154
|
+
iny
|
|
155
|
+
cpy #pass_end - pass
|
|
156
|
+
bne !-
|
|
157
|
+
lda #1
|
|
158
|
+
sta verdict_done
|
|
159
|
+
rts
|
|
160
|
+
|
|
161
|
+
// The bar table at the frozen phase, drawn as fill_bars draws it.
|
|
162
|
+
.var expected = List()
|
|
163
|
+
.for (var i = 0; i < BARS_LINES; i++) .eval expected.add(0)
|
|
164
|
+
.for (var b = 0; b < 4; b++) {
|
|
165
|
+
.var top = BARS_CENTRE + SinR(BARS_AMP, (EXP_PB + b * BAR_STEP) & 255)
|
|
166
|
+
.for (var i = 0; i < BAR_H; i++) .eval expected.set(top + i, bar_ramps.get(b).get(i))
|
|
167
|
+
}
|
|
168
|
+
exp_bars:
|
|
169
|
+
.for (var i = 0; i < BARS_LINES; i++) .byte expected.get(i)
|
|
170
|
+
|
|
171
|
+
.encoding "screencode_upper"
|
|
172
|
+
pass: .text "RESULT 01 PASS"
|
|
173
|
+
pass_end:
|
|
174
|
+
.text "RESULT 02 FAIL"
|
|
175
|
+
verdict_done: .byte 0
|
|
176
|
+
v_calls: .word 0
|
|
177
|
+
v_tick: .byte 0
|
|
178
|
+
v_step: .byte 0
|
|
179
|
+
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Grade the tune by the stores it makes to the SID, from a VICE store trace.
|
|
3
|
+
|
|
4
|
+
usage: audio.py --c64kb DIR --x64sc PATH [--cycles N] build/demo-auto.prg
|
|
5
|
+
|
|
6
|
+
The demo cannot read its own sound back: under the harness's `+sound`,
|
|
7
|
+
VICE returns values from $D41B and $D41C that do not follow the voice
|
|
8
|
+
(measured here: they change with no SID write at all), so the verdict
|
|
9
|
+
cannot hear a silent player. This check runs c64-kb's claims-watch over the
|
|
10
|
+
AUTOPILOT PRG on PAL and counts the program's stores to each SID unit:
|
|
11
|
+
|
|
12
|
+
- voice 2 (the arpeggio) is written twice every play call, and the tune is
|
|
13
|
+
played every PAL frame from the chain's start. So its stores, less the
|
|
14
|
+
twelve of init, over two, must match the frames from its first store to
|
|
15
|
+
the end of the trace, within SLACK (measured: 447 calls in 451 frames).
|
|
16
|
+
- voice 1 (bass) and voice 3 (drums) change on steps, so each must have at
|
|
17
|
+
least one store per step of seven frames; the volume at least one.
|
|
18
|
+
|
|
19
|
+
Exit 0 when all hold, 1 when one fails, 2 when the trace cannot be run.
|
|
20
|
+
"""
|
|
21
|
+
import argparse
|
|
22
|
+
import json
|
|
23
|
+
import os
|
|
24
|
+
import subprocess
|
|
25
|
+
import sys
|
|
26
|
+
import tempfile
|
|
27
|
+
|
|
28
|
+
PAL_FRAME = 19656
|
|
29
|
+
STEP_FRAMES = 7
|
|
30
|
+
INIT_V2 = 12 # m_init: 7 in its clearing loop, 5 to set the voice up
|
|
31
|
+
SLACK = 6 # frames between init and the first play call:
|
|
32
|
+
# measured 4 (the meter's calibration and the
|
|
33
|
+
# title's init run between them)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def main():
|
|
37
|
+
ap = argparse.ArgumentParser()
|
|
38
|
+
ap.add_argument("--c64kb", required=True)
|
|
39
|
+
ap.add_argument("--x64sc", required=True)
|
|
40
|
+
ap.add_argument("--cycles", type=int, default=12000000)
|
|
41
|
+
ap.add_argument("prg")
|
|
42
|
+
a = ap.parse_args()
|
|
43
|
+
with tempfile.TemporaryDirectory() as t:
|
|
44
|
+
out = os.path.join(t, "claims.json")
|
|
45
|
+
r = subprocess.run(
|
|
46
|
+
["node", "scripts/claims-watch.ts", os.path.abspath(a.prg),
|
|
47
|
+
"--claim", "sid_voice_1, sid_voice_2, sid_voice_3, sid_filter_volume",
|
|
48
|
+
"--cycles", str(a.cycles), "--json", out],
|
|
49
|
+
cwd=a.c64kb, env={**os.environ, "X64SC_BIN": a.x64sc}, capture_output=True, text=True)
|
|
50
|
+
if not os.path.exists(out):
|
|
51
|
+
print(r.stdout[-2000:], r.stderr[-2000:])
|
|
52
|
+
print("audio: claims-watch wrote no trace")
|
|
53
|
+
return 2
|
|
54
|
+
with open(out) as f:
|
|
55
|
+
tallies = json.load(f)["tallies"]
|
|
56
|
+
units = {t["target"]: t for t in tallies if t["source"] == "program" and t["target"].startswith("sid_")}
|
|
57
|
+
ok = True
|
|
58
|
+
v2 = units.get("sid_voice_2")
|
|
59
|
+
if not v2:
|
|
60
|
+
print("FAIL audio: no store to voice 2 at all")
|
|
61
|
+
return 1
|
|
62
|
+
calls = (a.cycles - v2["first"]["clock"]) // PAL_FRAME + 1
|
|
63
|
+
played = (v2["count"] - INIT_V2) // 2
|
|
64
|
+
line = f"voice 2: {v2['count']} stores = {played} play calls; {calls} frames from its first store"
|
|
65
|
+
if abs(played - calls) > SLACK:
|
|
66
|
+
print(f"FAIL audio: {line}")
|
|
67
|
+
ok = False
|
|
68
|
+
else:
|
|
69
|
+
print(f"PASS audio: {line}")
|
|
70
|
+
for unit, least in (("sid_voice_1", calls // STEP_FRAMES), ("sid_voice_3", calls // STEP_FRAMES),
|
|
71
|
+
("sid_filter_volume", 1)):
|
|
72
|
+
n = units.get(unit, {}).get("count", 0)
|
|
73
|
+
print(f"{'PASS' if n >= least else 'FAIL'} audio: {unit}: {n} stores, want at least {least}")
|
|
74
|
+
ok = ok and n >= least
|
|
75
|
+
print("audio: " + ("the tune writes the SID every frame" if ok else "FAILED"))
|
|
76
|
+
return 0 if ok else 1
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
if __name__ == "__main__":
|
|
80
|
+
sys.exit(main())
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Write expect.json for the demo starter from src/config.asm.
|
|
3
|
+
|
|
4
|
+
usage: python3 tools/gen_expect.py > expect.json (or: make expect)
|
|
5
|
+
|
|
6
|
+
The numbers (lines, amplitudes, speeds, the freeze) are read from the plain
|
|
7
|
+
`.const NAME = number` lines of src/config.asm; the picture is computed here
|
|
8
|
+
again, in Python, not taken from the assembler: where the eight sprites
|
|
9
|
+
sit, which colour every bar line has, where row 22's ink falls at the
|
|
10
|
+
frozen XSCROLL (from the character ROM).
|
|
11
|
+
KickAssembler's round() is Java's Math.round, floor(x + 0.5), and so is
|
|
12
|
+
rnd() below.
|
|
13
|
+
"""
|
|
14
|
+
import json
|
|
15
|
+
import math
|
|
16
|
+
import os
|
|
17
|
+
import re
|
|
18
|
+
|
|
19
|
+
HERE = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
20
|
+
with open(os.path.join(HERE, "src", "config.asm")) as f:
|
|
21
|
+
CONFIG = f.read()
|
|
22
|
+
C = {m.group(1): int(m.group(2), 0) for m in re.finditer(r"^\.const (\w+)\s*=\s*(\d+)\b", CONFIG, re.M)}
|
|
23
|
+
|
|
24
|
+
# The ramps and the message, from their source lines.
|
|
25
|
+
RAMPS = [[int(v) for v in m.group(1).split(",")]
|
|
26
|
+
for m in re.finditer(r"List\(\)\.add\(([\d, ]+)\)", CONFIG)]
|
|
27
|
+
with open(os.path.join(HERE, "src", "tables.asm")) as f:
|
|
28
|
+
TABLES = f.read()
|
|
29
|
+
MESSAGE = "".join(re.findall(r'\.text "([^"]*)"', TABLES[TABLES.index("message:"):]))
|
|
30
|
+
SUBTITLE = re.search(r'subtitle:\s*\.text "([^"]*)"', TABLES).group(1)
|
|
31
|
+
# scroll_colours: ".byte a, b, c / .fill n, v / .byte ..." read in order.
|
|
32
|
+
SCROLL_COLOURS = []
|
|
33
|
+
for kind, args in re.findall(r"\.(byte|fill) ([\d, ]+)", TABLES[TABLES.index("scroll_colours:"):TABLES.index(".encoding")]):
|
|
34
|
+
vals = [int(v) for v in args.split(",")]
|
|
35
|
+
SCROLL_COLOURS += vals if kind == "byte" else [vals[1]] * vals[0]
|
|
36
|
+
|
|
37
|
+
# The power-on character set, for where the scroller's ink falls (the same
|
|
38
|
+
# ROM check.py decodes text with).
|
|
39
|
+
CHARGEN_PATHS = [
|
|
40
|
+
os.environ.get("C64_CHARGEN", ""),
|
|
41
|
+
"/opt/homebrew/opt/vice/share/vice/C64/chargen-901225-01.bin",
|
|
42
|
+
"/usr/local/share/vice/C64/chargen-901225-01.bin",
|
|
43
|
+
"/usr/share/vice/C64/chargen-901225-01.bin",
|
|
44
|
+
"/usr/lib/vice/C64/chargen-901225-01.bin",
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
BORDER_PASS = 5
|
|
48
|
+
BLACK = 0
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def rnd(x):
|
|
52
|
+
return math.floor(x + 0.5)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def sin256(amp, step):
|
|
56
|
+
return rnd(amp * math.sin(2 * math.pi * (step & 255) / 256))
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def sprites(k):
|
|
60
|
+
px, py = (k * C["CHAIN_SX"]) & 255, (k * C["CHAIN_SY"]) & 255
|
|
61
|
+
out = []
|
|
62
|
+
for n in range(8):
|
|
63
|
+
x = C["CHAIN_X0"] + n * C["CHAIN_DX"] + sin256(C["CHAIN_AX"], px + n * C["CHAIN_PX"])
|
|
64
|
+
y = C["CHAIN_Y0"] + sin256(C["CHAIN_AY"], py + n * C["CHAIN_PY"])
|
|
65
|
+
out.append((x, y, C["CHAIN_COL_A"] if n % 2 == 0 else C["CHAIN_COL_B"]))
|
|
66
|
+
return out
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def bar_lines(k):
|
|
70
|
+
pb = (k * C["BAR_SPEED"]) & 255
|
|
71
|
+
lines = [BLACK] * C["BARS_LINES"]
|
|
72
|
+
for b, ramp in enumerate(RAMPS):
|
|
73
|
+
top = C["BARS_CENTRE"] + sin256(C["BARS_AMP"], pb + b * C["BAR_STEP"])
|
|
74
|
+
lines[top:top + C["BAR_H"]] = ramp
|
|
75
|
+
return lines
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def screen_code(ch):
|
|
79
|
+
"""KickAssembler's screencode_upper for the characters the message uses."""
|
|
80
|
+
return ord(ch) - 64 if "A" <= ch <= "Z" else ord(ch)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def scroller_checks(k, rom):
|
|
84
|
+
"""Row 22 at the freeze: 38 columns, XSCROLL 7 - (k mod 8), after k // 8 shifts.
|
|
85
|
+
For each visible cell, the leftmost ink pixel of its first inked glyph row
|
|
86
|
+
and the pixel just left of it. A missing or wrong $D016 write moves them."""
|
|
87
|
+
shifts, xs = k // 8, 7 - k % 8
|
|
88
|
+
row = MESSAGE[shifts:shifts + 40]
|
|
89
|
+
line0 = 51 + 8 * C["SCROLL_ROW"]
|
|
90
|
+
|
|
91
|
+
def colour_at(vic_x, r):
|
|
92
|
+
cell, bit = divmod(vic_x - 24 - xs, 8)
|
|
93
|
+
if not 0 <= cell < 40:
|
|
94
|
+
return BLACK
|
|
95
|
+
glyph = rom[screen_code(row[cell]) * 8 + r]
|
|
96
|
+
return SCROLL_COLOURS[cell] if glyph & (0x80 >> bit) else BLACK
|
|
97
|
+
|
|
98
|
+
out = []
|
|
99
|
+
for c in range(1, 38):
|
|
100
|
+
code = screen_code(row[c])
|
|
101
|
+
glyph = rom[code * 8: code * 8 + 8]
|
|
102
|
+
r = next((r for r in range(8) if glyph[r]), None)
|
|
103
|
+
if r is None:
|
|
104
|
+
continue
|
|
105
|
+
bit = next(b for b in range(8) if glyph[r] & (0x80 >> b))
|
|
106
|
+
x = 24 + 8 * c + xs + bit
|
|
107
|
+
for vx, what in ((x, "ink"), (x - 1, "left of it")):
|
|
108
|
+
out.append({"name": f"scroller cell {c} '{row[c]}', XSCROLL {xs}: {what} at X {vx}, line {line0 + r}",
|
|
109
|
+
"type": "pixel", "vic_x": vx, "line": line0 + r, "colour": colour_at(vx, r)})
|
|
110
|
+
# 38 columns: the border covers X 24-30 and 335-343 on the scroller's lines only.
|
|
111
|
+
out.append({"name": "scroller in 38 columns: left border X 24-30", "type": "rect", "colour": BORDER_PASS,
|
|
112
|
+
"vic_x": 24, "line": line0, "width": 7, "height": 8})
|
|
113
|
+
out.append({"name": "scroller in 38 columns: right border X 335-343", "type": "rect", "colour": BORDER_PASS,
|
|
114
|
+
"vic_x": 335, "line": line0, "width": 9, "height": 8})
|
|
115
|
+
return out
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def main():
|
|
119
|
+
k = C["FREEZE_UPDATES"]
|
|
120
|
+
top = C["BARS_TOP"]
|
|
121
|
+
checks = [
|
|
122
|
+
{"name": "own verdict (border)", "type": "verdict"},
|
|
123
|
+
{"name": "verdict line", "type": "text", "row": 24, "col": 1, "text": "RESULT 01 PASS"},
|
|
124
|
+
{"name": "subtitle under the logo (row 5)", "type": "text", "row": 5, "col": 0, "text": SUBTITLE},
|
|
125
|
+
]
|
|
126
|
+
# The logo: two cells of the D's stem and one gap, rows 0 to 4.
|
|
127
|
+
for row, colour in enumerate([4, 10, 7, 10, 4]):
|
|
128
|
+
checks.append({"name": f"logo row {row}: the D's stem", "type": "pixel", "row": row, "col": 7, "colour": colour})
|
|
129
|
+
checks.append({"name": "logo: the gap between D and E", "type": "pixel", "row": 2, "col": 13, "colour": BLACK})
|
|
130
|
+
|
|
131
|
+
for n, (x, y, colour) in enumerate(sprites(k)):
|
|
132
|
+
checks.append({
|
|
133
|
+
"name": f"sprite {n} at X {x}, Y {y} (lines {y + 1}-{y + 21}), from the sine formula",
|
|
134
|
+
"type": "sprite", "colour": colour, "vic_x": x, "line": y + 1, "width": 24, "height": 21,
|
|
135
|
+
"search": {"vic_x": x - 16, "line": y - 7, "width": 56, "height": 37},
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
# Every bar line, left border to right border, one colour: runs of equal
|
|
139
|
+
# colour become one rect each. The title card's rows 13, 15 and 17 lie in
|
|
140
|
+
# these lines, so these checks also prove the wipe cleared it.
|
|
141
|
+
lines = bar_lines(k)
|
|
142
|
+
i = 0
|
|
143
|
+
while i < len(lines):
|
|
144
|
+
j = i
|
|
145
|
+
while j + 1 < len(lines) and lines[j + 1] == lines[i]:
|
|
146
|
+
j += 1
|
|
147
|
+
checks.append({
|
|
148
|
+
"name": f"bar lines {top + i}-{top + j}: colour {lines[i]} across the whole line",
|
|
149
|
+
"type": "rect", "colour": lines[i], "vic_x": -8, "line": top + i, "width": 384, "height": j - i + 1,
|
|
150
|
+
})
|
|
151
|
+
i = j + 1
|
|
152
|
+
for line, what in ((top - 1, "above"), (top + len(lines), "below")):
|
|
153
|
+
checks.append({"name": f"line {line}, {what} the bars: border", "type": "rect", "colour": BORDER_PASS,
|
|
154
|
+
"vic_x": -8, "line": line, "width": 32, "height": 1})
|
|
155
|
+
checks.append({"name": f"line {line}, {what} the bars: background", "type": "rect", "colour": BLACK,
|
|
156
|
+
"vic_x": 24, "line": line, "width": 320, "height": 1})
|
|
157
|
+
|
|
158
|
+
rom = next(open(p, "rb").read() for p in CHARGEN_PATHS if p and os.path.exists(p))
|
|
159
|
+
checks += scroller_checks(k, rom)
|
|
160
|
+
checks.append({"name": "rows 0 to 23 the same on PAL and NTSC", "type": "same", "cells": [0, 0, 23, 39]})
|
|
161
|
+
checks.append({"name": f"frame meter, {C['HOLD']} frames: title, wipe and main part", "type": "meter",
|
|
162
|
+
"row": 24, "col": 20, "frames": C["HOLD"]})
|
|
163
|
+
print(json.dumps({"checks": checks}, indent=2))
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
if __name__ == "__main__":
|
|
167
|
+
main()
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Where the bar kernel's colour stores land, read off the PROBE build's shots.
|
|
3
|
+
|
|
4
|
+
usage: probe.py probe-pal-*.png probe-ntsc-*.png (at least 8 shots a model)
|
|
5
|
+
|
|
6
|
+
The PROBE build delays the whole kernel by 20 cycles, so the second store
|
|
7
|
+
of each line ($D021, the background) lands inside the visible line instead
|
|
8
|
+
of in the horizontal blank. On every bar line whose colour differs from the
|
|
9
|
+
line above, the first pixel of the new colour inside the display window is
|
|
10
|
+
that store. One column on every line, in every shot, means the entry is
|
|
11
|
+
stable and every badline chunk has the right length. Taking the 20 cycles
|
|
12
|
+
(160 pixels) back off says how far the real stores sit from the visible
|
|
13
|
+
edges: the $D020 store is 4 cycles (32 pixels) before the $D021 store.
|
|
14
|
+
|
|
15
|
+
Exit 0 when each model shows one column, PROBE_COLUMN from config.asm,
|
|
16
|
+
over all its shots, and the stores
|
|
17
|
+
of every chunk fall in the horizontal blank without the probe; 1 otherwise.
|
|
18
|
+
Geometry from c64-kb docs/runtime/vice-reference.md: row = line - 16 (PAL),
|
|
19
|
+
line - 28 (NTSC); a PAL line is 504 pixels (63 cycles), an NTSC one 520.
|
|
20
|
+
"""
|
|
21
|
+
import os
|
|
22
|
+
import re
|
|
23
|
+
import sys
|
|
24
|
+
|
|
25
|
+
from PIL import Image
|
|
26
|
+
|
|
27
|
+
HERE = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
28
|
+
with open(os.path.join(HERE, "src", "config.asm")) as f:
|
|
29
|
+
CONST = {m.group(1): int(m.group(2)) for m in re.finditer(r"^\.const (\w+)\s*=\s*(\d+)\b", f.read(), re.M)}
|
|
30
|
+
SHIFT_PX = 20 * 8
|
|
31
|
+
MIN_SHOTS = 8 # the review saw wrong pads show one column in 16 of 16 single shots
|
|
32
|
+
GREY_DOT = (205, 205, 205) # light grey, the same triple on both models
|
|
33
|
+
MODELS = {"pal": (16, 504), "ntsc": (28, 520)}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def columns(path, offset):
|
|
37
|
+
"""(line, x) of the first new-colour pixel in the display, per changing line."""
|
|
38
|
+
im = Image.open(path).convert("RGB")
|
|
39
|
+
top, n = CONST["BARS_TOP"], CONST["BARS_LINES"]
|
|
40
|
+
out = []
|
|
41
|
+
for line in range(top, top + n + 1):
|
|
42
|
+
y = line - offset
|
|
43
|
+
new, old = im.getpixel((383, y)), im.getpixel((0, y))
|
|
44
|
+
# VICE's PAL default, a C64C, draws the grey dot: one light grey pixel
|
|
45
|
+
# where a colour register changes. A change to or from light grey is
|
|
46
|
+
# skipped, so the column is always the first pixel of the new colour.
|
|
47
|
+
if new == old or GREY_DOT in (new, old):
|
|
48
|
+
continue
|
|
49
|
+
out.append((line, next((x for x in range(32, 352) if im.getpixel((x, y)) == new), None)))
|
|
50
|
+
return out
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def main():
|
|
54
|
+
shots = {"pal": [], "ntsc": []}
|
|
55
|
+
for path in sys.argv[1:]:
|
|
56
|
+
shots["ntsc" if "ntsc" in os.path.basename(path) else "pal"].append(path)
|
|
57
|
+
last_line = CONST["BARS_TOP"] + CONST["BARS_LINES"]
|
|
58
|
+
ok = True
|
|
59
|
+
for model, paths in shots.items():
|
|
60
|
+
offset, line_px = MODELS[model]
|
|
61
|
+
body, last = set(), set()
|
|
62
|
+
for p in paths:
|
|
63
|
+
for line, x in columns(p, offset):
|
|
64
|
+
(last if line == last_line else body).add(x)
|
|
65
|
+
print(f"{model}: {len(paths)} shot(s), $D021 store column(s) {sorted(body, key=str)}")
|
|
66
|
+
if len(paths) < MIN_SHOTS:
|
|
67
|
+
print(f"{model}: FAIL, {len(paths)} shot(s); a wrong SYNC_PAD can look right in fewer than {MIN_SHOTS}")
|
|
68
|
+
ok = False
|
|
69
|
+
continue
|
|
70
|
+
if len(body) != 1 or None in body:
|
|
71
|
+
print(f"{model}: FAIL, the stores do not line up")
|
|
72
|
+
ok = False
|
|
73
|
+
continue
|
|
74
|
+
if body != {CONST["PROBE_COLUMN"]}:
|
|
75
|
+
print(f"{model}: FAIL, the stores line up at x {next(iter(body))}, not PROBE_COLUMN "
|
|
76
|
+
f"{CONST['PROBE_COLUMN']} (config.asm): the entry moved")
|
|
77
|
+
ok = False
|
|
78
|
+
continue
|
|
79
|
+
x2 = next(iter(body)) - SHIFT_PX # the real $D021 store, relative to x = 0
|
|
80
|
+
x1 = x2 - 32 # the $D020 store, four cycles earlier
|
|
81
|
+
# The last chunk's $D021 store writes black over black, so it never
|
|
82
|
+
# shows; it is two cycles later than the others by the code.
|
|
83
|
+
xl = x2 + 16
|
|
84
|
+
after = x1 + line_px - 383 # pixels past the line above's last visible pixel
|
|
85
|
+
print(f"{model}: without the probe, $D020 at x {x1} and $D021 at x {x2} (the last chunk's "
|
|
86
|
+
f"$D021 at {xl} by the code, not measured), x 0 being the line's first visible pixel; "
|
|
87
|
+
f"the $D020 store is {after} pixels after the line above leaves the picture")
|
|
88
|
+
if not (xl < 0 and after > 0):
|
|
89
|
+
print(f"{model}: FAIL, a store would land in the visible line")
|
|
90
|
+
ok = False
|
|
91
|
+
return 0 if ok else 1
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
if __name__ == "__main__":
|
|
95
|
+
sys.exit(main())
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/claude-code-settings.json",
|
|
3
|
+
"hooks": {
|
|
4
|
+
"PreToolUse": [
|
|
5
|
+
{
|
|
6
|
+
"matcher": "Edit|MultiEdit|Write|NotebookEdit",
|
|
7
|
+
"hooks": [
|
|
8
|
+
{
|
|
9
|
+
"type": "command",
|
|
10
|
+
"command": "h=\"$CLAUDE_PROJECT_DIR/harness/hooks/plan-gate.py\"; [ -f \"$h\" ] || h=\"$CLAUDE_PROJECT_DIR/../_harness/hooks/plan-gate.py\"; exec python3 \"$h\"",
|
|
11
|
+
"timeout": 10
|
|
12
|
+
}
|
|
13
|
+
]
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Rules for an agent working on this C64 program
|
|
2
|
+
|
|
3
|
+
This program runs on a stock Commodore 64, PAL and NTSC. It is built on the
|
|
4
|
+
c64-kb harness (`./harness`, vendored from c64-kb's `templates/_harness`).
|
|
5
|
+
c64-kb is the reference: its pages give the registers, timings, techniques,
|
|
6
|
+
pitfalls and recipes this program is built from. A wrong number becomes a torn
|
|
7
|
+
screen or a crash, so every claim here is measured or says it is not.
|
|
8
|
+
|
|
9
|
+
A new program starts in c64-kb with `npm run new-project -- <starter> <dir>`.
|
|
10
|
+
That copies the starter and the harness, points `.mcp.json` and `local.mk`
|
|
11
|
+
at the c64-kb checkout, proves the copy with `make shot check`, and leaves a
|
|
12
|
+
blank `PLAN.md`.
|
|
13
|
+
|
|
14
|
+
## This starter: hello
|
|
15
|
+
|
|
16
|
+
The smallest program that uses every harness target. `src/main.c` (Oscar64)
|
|
17
|
+
runs the loop; `src/sprite.asm` (KickAssembler) places sprite 0; the meter
|
|
18
|
+
times each frame. Start a program from it with
|
|
19
|
+
`npm run new-project -- hello <dir>` in c64-kb. `PLAN.md` here is a plan
|
|
20
|
+
filled from real tool output; new-project keeps it as
|
|
21
|
+
`PLAN-hello-example.md` and gives the new program a blank one.
|
|
22
|
+
|
|
23
|
+
## Before any code
|
|
24
|
+
|
|
25
|
+
1. Brief: `npx tsx src/cli.ts game-briefing "<concept>" --archetype <name>`
|
|
26
|
+
(or `demo-briefing`), in the c64-kb checkout. Read what it proposes.
|
|
27
|
+
2. For each technique you keep: `technique-lookup <name>` and
|
|
28
|
+
`pitfalls-for <name>`. Start from the recipe it names (`recipe-lookup`).
|
|
29
|
+
3. Fill `PLAN.md`: paste the whole output of `check-compatibility` and of
|
|
30
|
+
`plan-budget` (same techniques) into their sections, list every technique
|
|
31
|
+
in its table, and replace every `FILL:` line.
|
|
32
|
+
|
|
33
|
+
Until `PLAN.md` passes, a hook blocks Edit and Write under `src/`, and every
|
|
34
|
+
make target that builds stops (`make plan-gate` says what is missing). With
|
|
35
|
+
C64KB set, `make` re-runs `check-compatibility` and wants the pasted Verdict.
|
|
36
|
+
The gate cannot see writes made through a shell command, or outputs edited
|
|
37
|
+
into shape by hand: do neither. `make PLAN_GATE=off` overrides it; say why in
|
|
38
|
+
`PLAN.md` if you do.
|
|
39
|
+
|
|
40
|
+
## The loop
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
make # build build/<name>.prg
|
|
44
|
+
make shot check # autopilot build, headless PAL and NTSC, graded by expect.json
|
|
45
|
+
make selftest # the FORCE_FAULT build must fail the same checks
|
|
46
|
+
make disk # build/<name>.d64
|
|
47
|
+
make claims # every store the program makes, against what it declares
|
|
48
|
+
make run # windowed VICE, for a human
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Rules
|
|
52
|
+
|
|
53
|
+
- Build before claiming. Code that has not built is not done.
|
|
54
|
+
- Measure screenshots with `check.py` through `expect.json`, never by eye.
|
|
55
|
+
Every visible claim gets a check. Add one before you trust a change.
|
|
56
|
+
- PAL and NTSC: both shots pass, or it is not done.
|
|
57
|
+
- Name the rung for every number: measured here (`make shot`, the meter, the
|
|
58
|
+
VICE monitor), taken from a c64-kb page (say which), arithmetic, or not
|
|
59
|
+
measured. Never call something verified that was not run.
|
|
60
|
+
- Frame cost comes from the meter: CIA2 timer A, printed as
|
|
61
|
+
`F<frames> W<worst> T<typical>` at row 24, columns 20 to 39, in AUTOPILOT
|
|
62
|
+
builds. It records the first `hold` frames: make that the autopilot
|
|
63
|
+
script's play frames. Typical is the median of those frames, the KB's
|
|
64
|
+
`cycles_per_frame_typical`. Keep grading, logging and printing outside the
|
|
65
|
+
bracket; work split between the main loop and IRQs is summed with
|
|
66
|
+
`METER_PAUSE` / `METER_START`.
|
|
67
|
+
- Do not invent a register, routine or address. Look it up:
|
|
68
|
+
`lookup-register`, `lookup-kernal`, `memory-map`.
|
|
69
|
+
- Lint every source you change: `npx tsx src/cli.ts lint <file>`.
|
|
70
|
+
- Commit named paths only. Never `git add -A` or `git add .`. `build/`,
|
|
71
|
+
`shots/` and `local.mk` are never committed.
|
|
72
|
+
|
|
73
|
+
## Harness facts you will need
|
|
74
|
+
|
|
75
|
+
- `AUTOPILOT=1` builds read a scripted joystick byte instead of `$DC00` and
|
|
76
|
+
grade themselves: `$02FF` = `$01` and a green border on pass, `$02` and red
|
|
77
|
+
on fail. `FORCE_FAULT=1` must turn the verdict red and move something a
|
|
78
|
+
screenshot check can see.
|
|
79
|
+
- Screenshot geometry (c64-kb `docs/runtime/vice-reference.md`): PAL 384 x 272,
|
|
80
|
+
row = raster line - 16; NTSC 384 x 247, row = line - 28; x = VIC X + 8. A
|
|
81
|
+
sprite at Y register y is drawn from line y + 1.
|
|
82
|
+
- `check.py` reads text in the ROM character set unless a check names a
|
|
83
|
+
`charset` file; the meter's cells need 0-9, F, W and T in the set on screen.
|
|
84
|
+
- A KickAssembler part called from C is a raw blob at its own `* =` address,
|
|
85
|
+
`$0880` or above; `build/asm.h` gives C its labels as `ASM_<LABEL>`
|
|
86
|
+
(`ASM_<SCOPE>_<LABEL>` inside a scope). Pass arguments through bytes in the
|
|
87
|
+
blob, not Oscar64's zero page (`$02` up; the top depends on the program:
|
|
88
|
+
`make zp` lists what the build's code touches).
|
|
89
|
+
- The meter takes CIA2 timer A. Do not open RS-232 (device 2) while it runs.
|
|
90
|
+
- The KERNAL serial routines end in `CLI` (ROM bytes `58 60` / `58 18` at
|
|
91
|
+
`$EDAB`, `$EDB5`, `$EDDB`, `$EE82`). After any disk call, `SEI` again if
|
|
92
|
+
the program runs with the KERNAL IRQ off: otherwise that IRQ lands inside
|
|
93
|
+
the meter's brackets and rewrites `$DC00`.
|
|
94
|
+
|
|
95
|
+
## Calling c64-kb
|
|
96
|
+
|
|
97
|
+
- CLI, from the c64-kb checkout (`C64KB` in `local.mk`):
|
|
98
|
+
`npx tsx src/cli.ts <command>`; `npx tsx src/cli.ts --help` lists them.
|
|
99
|
+
- MCP: `.mcp.json` starts `node <c64-kb>/dist/cli.js serve` (run
|
|
100
|
+
`npm run build` in c64-kb first).
|