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,229 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Shoot a run mid-scroll and prove every picture is whole.
|
|
3
|
+
|
|
4
|
+
usage: tearcheck.py --x64sc X --harness DIR --src DIR --expect whole|torn PRG CYCLES...
|
|
5
|
+
|
|
6
|
+
Renders the level from the program's own sources (src/level.c, src/art.c,
|
|
7
|
+
src/game.h) into one picture 2,048 pixels wide, runs PRG headless in VICE
|
|
8
|
+
once per cycle count on PAL and on NTSC, and matches each exit screenshot's
|
|
9
|
+
playfield (character rows 0-19, the 38-column window) against that render:
|
|
10
|
+
which camera positions give exactly these pixels, row by row.
|
|
11
|
+
|
|
12
|
+
A whole picture is one camera for all 160 lines. VICE's exit screenshot is
|
|
13
|
+
taken mid-frame, so a picture may also be two frames: lines above the beam
|
|
14
|
+
from the frame being drawn, lines below from the one before. The two parts
|
|
15
|
+
then differ by one frame of camera movement, at most CAM_SPEED (2) pixels,
|
|
16
|
+
and the lower part must be exactly the camera the HUD shows (below).
|
|
17
|
+
A torn picture has a part a whole column (8 pixels) off, or more than one
|
|
18
|
+
seam. Sprite colours (white, light red, cyan) are masked; a coin cell may
|
|
19
|
+
show the coin or the sky (it may have been taken).
|
|
20
|
+
|
|
21
|
+
The phase test. The AUTOPILOT build prints on HUD row 23 ("CAM 0576") the
|
|
22
|
+
camera of the picture the IRQ at line 251 has just set up. The lowest part
|
|
23
|
+
of the playfield must be at that camera, give or take one frame's
|
|
24
|
+
movement: a page and an XSCROLL that disagree put the whole picture 8
|
|
25
|
+
pixels off, which the seam test alone cannot see.
|
|
26
|
+
|
|
27
|
+
--expect whole: exit 0 when every shot is whole or a two-frame composite.
|
|
28
|
+
--expect torn: exit 0 when at least one shot is torn (the TEAR_DEMO build:
|
|
29
|
+
the check can see a tear). Exit 1 otherwise, 2 on a setup
|
|
30
|
+
error.
|
|
31
|
+
"""
|
|
32
|
+
import argparse
|
|
33
|
+
import importlib.util
|
|
34
|
+
import os
|
|
35
|
+
import re
|
|
36
|
+
import subprocess
|
|
37
|
+
import sys
|
|
38
|
+
import tempfile
|
|
39
|
+
|
|
40
|
+
import numpy as np
|
|
41
|
+
from PIL import Image
|
|
42
|
+
|
|
43
|
+
CAM_SPEED = 2
|
|
44
|
+
SPRITE_COLOURS = {1, 10, 3} # player, walker, hopper (src/game.h COL_*)
|
|
45
|
+
VCOL = ["BLACK", "WHITE", "RED", "CYAN", "PURPLE", "GREEN", "BLUE", "YELLOW",
|
|
46
|
+
"ORANGE", "BROWN", "LT_RED", "DARK_GREY", "MED_GREY", "LT_GREEN", "LT_BLUE", "LT_GREY"]
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def unescape(s):
|
|
50
|
+
return s.encode().decode("unicode_escape")
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def block(text, name):
|
|
54
|
+
m = re.search(rf"// {name}-BEGIN\n(.*?)// {name}-END", text, re.S)
|
|
55
|
+
if not m:
|
|
56
|
+
raise SystemExit(f"tearcheck: no {name}-BEGIN/END block")
|
|
57
|
+
return m.group(1)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def load_model(src):
|
|
61
|
+
game = open(os.path.join(src, "game.h")).read()
|
|
62
|
+
level = open(os.path.join(src, "level.c")).read()
|
|
63
|
+
art = open(os.path.join(src, "art.c")).read()
|
|
64
|
+
ch = {k: int(v) for k, v in re.findall(r"#define (CH_\w+)\s+(\d+)", game)}
|
|
65
|
+
col = {k: VCOL.index(v) for k, v in re.findall(r"#define (COL_\w+)\s+VCOL_(\w+)", game)}
|
|
66
|
+
rows = [unescape(s) for s in re.findall(r'"((?:[^"\\]|\\.)*)"', block(level, "LEVEL"))]
|
|
67
|
+
tiles = block(level, "TILES")
|
|
68
|
+
key = unescape(re.search(r'tile_key\[\] = "((?:[^"\\]|\\.)*)"', tiles).group(1))
|
|
69
|
+
quads = [[ch[n] for n in q] for q in re.findall(r"\{\s*(CH_\w+),\s*(CH_\w+),\s*(CH_\w+),\s*(CH_\w+)\s*\}", tiles)]
|
|
70
|
+
hbody = re.search(r"heights\[64\] = \{(.*?)\};", level, re.S).group(1)
|
|
71
|
+
heights = [int(v) for v in re.findall(r"^\s*([\d, ]+),?\s*//", hbody, re.M) for v in v.split(",") if v.strip()]
|
|
72
|
+
ga = block(art, "GLYPH-ART")
|
|
73
|
+
codes = [ch[n] for n in re.findall(r"CH_\w+", re.search(r"glyph_code\[\] = \{(.*?)\};", ga, re.S).group(1))]
|
|
74
|
+
strs = re.findall(r'"([.byg]{4})"', re.search(r"glyph_art\[\]\[8\]\[5\] = \{(.*?)\};", ga, re.S).group(1))
|
|
75
|
+
if len(rows) != 10 or len(heights) != 64 or len(strs) != 8 * len(codes) or len(quads) != len(key):
|
|
76
|
+
raise SystemExit(f"tearcheck: could not read the model (rows {len(rows)}, heights {len(heights)}, "
|
|
77
|
+
f"art {len(strs)}/{8 * len(codes)}, tiles {len(quads)}/{len(key)})")
|
|
78
|
+
# glyph -> 8 rows of 4 multicolour pixel values
|
|
79
|
+
glyph = {ch["CH_SKY"]: [[0] * 4 for _ in range(8)]}
|
|
80
|
+
val = {".": 0, "b": 1, "y": 2, "g": 3}
|
|
81
|
+
for i, code in enumerate(codes):
|
|
82
|
+
glyph[code] = [[val[c] for c in strs[i * 8 + r]] for r in range(8)]
|
|
83
|
+
for t in range(1, 7): # art.c slope_glyph: the higher of each pixel's two columns
|
|
84
|
+
h = heights[t * 8:t * 8 + 8]
|
|
85
|
+
g = []
|
|
86
|
+
for r in range(8):
|
|
87
|
+
row = []
|
|
88
|
+
for k in range(4):
|
|
89
|
+
s = min(h[2 * k], h[2 * k + 1])
|
|
90
|
+
row.append(0 if r < s else 3 if r == s else 1)
|
|
91
|
+
g.append(row)
|
|
92
|
+
glyph[ch["CH_SLOPE1"] - 1 + t] = g
|
|
93
|
+
palette = [col["COL_SKY"], col["COL_EARTH"], col["COL_GOLD"], col["COL_GRASS"]]
|
|
94
|
+
coin = key.index("o")
|
|
95
|
+
|
|
96
|
+
def render(with_coins):
|
|
97
|
+
img = np.zeros((160, len(rows[0]) * 16), dtype=np.uint8)
|
|
98
|
+
for ty, line in enumerate(rows):
|
|
99
|
+
for tx, k in enumerate(line):
|
|
100
|
+
t = key.index(k) if k in key else 0
|
|
101
|
+
if t == coin and not with_coins:
|
|
102
|
+
t = 0
|
|
103
|
+
for q, code in enumerate(quads[t]):
|
|
104
|
+
g = glyph[code]
|
|
105
|
+
y0, x0 = ty * 16 + (q >> 1) * 8, tx * 16 + (q & 1) * 8
|
|
106
|
+
for r in range(8):
|
|
107
|
+
for k4 in range(4):
|
|
108
|
+
img[y0 + r, x0 + 2 * k4:x0 + 2 * k4 + 2] = palette[g[r][k4]]
|
|
109
|
+
return img
|
|
110
|
+
|
|
111
|
+
return render(True), render(False)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def load_check(harness):
|
|
115
|
+
spec = importlib.util.spec_from_file_location("check", os.path.join(harness, "check.py"))
|
|
116
|
+
mod = importlib.util.module_from_spec(spec)
|
|
117
|
+
spec.loader.exec_module(mod)
|
|
118
|
+
return mod
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def shot_indices(path, model, chk):
|
|
122
|
+
im = Image.open(path).convert("RGB")
|
|
123
|
+
g = chk.GEOMETRY[model]
|
|
124
|
+
pal = {tuple(c): i for i, c in enumerate(chk.PALETTE[model])}
|
|
125
|
+
y0 = 51 - g["line_offset"]
|
|
126
|
+
a = np.array(im)[y0:y0 + 160, 31 + 8:335 + 8] # VIC X 31-334, lines 51-210
|
|
127
|
+
out = np.full(a.shape[:2], 255, dtype=np.uint8)
|
|
128
|
+
for rgb, i in pal.items():
|
|
129
|
+
out[np.all(a == rgb, axis=2)] = i
|
|
130
|
+
return out
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def row_candidates(row, w1, w0):
|
|
134
|
+
"""Camera positions at which this 304-pixel row matches the render."""
|
|
135
|
+
mask = np.isin(row, list(SPRITE_COLOURS)) | (row == 255)
|
|
136
|
+
ok = (w1 == row) | (w0 == row) | mask
|
|
137
|
+
return np.nonzero(ok.all(axis=1))[0]
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def segments(img, world1, world0):
|
|
141
|
+
from numpy.lib.stride_tricks import sliding_window_view
|
|
142
|
+
segs, cur, start = [], None, 0
|
|
143
|
+
for y in range(160):
|
|
144
|
+
w1 = sliding_window_view(world1[y], 304)
|
|
145
|
+
w0 = sliding_window_view(world0[y], 304)
|
|
146
|
+
c = set(row_candidates(img[y], w1, w0).tolist())
|
|
147
|
+
nxt = c if cur is None else cur & c
|
|
148
|
+
if not nxt:
|
|
149
|
+
segs.append((start, y - 1, cur))
|
|
150
|
+
start, nxt = y, c
|
|
151
|
+
cur = nxt
|
|
152
|
+
segs.append((start, 159, cur))
|
|
153
|
+
return segs
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def hud_camera(png, model, chk):
|
|
157
|
+
text = chk.read_text(chk.Shot(png, model), chk.load_glyphs(), 23, 30, 8)
|
|
158
|
+
return int(text[4:]) if text.startswith("CAM ") and text[4:].isdigit() else None
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def judge(segs, cam):
|
|
162
|
+
if any(not s[2] for s in segs):
|
|
163
|
+
return "no camera matches a part: not the level", None
|
|
164
|
+
if len(segs) > 2:
|
|
165
|
+
return f"TORN: {len(segs)} parts, seams at lines {[51 + s[0] for s in segs[1:]]}", None
|
|
166
|
+
what = "whole"
|
|
167
|
+
if len(segs) == 2:
|
|
168
|
+
a, b = segs[0][2], segs[1][2]
|
|
169
|
+
d = min(abs(x - y) for x in a for y in b)
|
|
170
|
+
if d > CAM_SPEED:
|
|
171
|
+
return f"TORN at line {51 + segs[1][0]}: parts {d} pixels apart", None
|
|
172
|
+
what = f"two frames, seam at line {51 + segs[1][0]}, cameras {min(a)} / {min(b)}"
|
|
173
|
+
low = segs[-1][2]
|
|
174
|
+
# In a real two-frame shot the lower part is the older frame, the one the
|
|
175
|
+
# HUD row (drawn after the playfield) belongs to: exactly its camera. A
|
|
176
|
+
# mid-picture XSCROLL write also makes two parts 1-2 pixels apart, but
|
|
177
|
+
# then the lower part is not the HUD camera (review mutation, line 150).
|
|
178
|
+
if len(segs) == 2 and cam is not None and cam not in low:
|
|
179
|
+
return f"SEAM NOT A FRAME BOUNDARY: lower part {sorted(low)[:3]} is not the HUD camera {cam}", None
|
|
180
|
+
if cam is None:
|
|
181
|
+
return what + "; HUD camera unreadable (the beam was on it)", low
|
|
182
|
+
off = min(abs(c - cam) for c in low)
|
|
183
|
+
if off > CAM_SPEED:
|
|
184
|
+
return f"OFF PHASE: the picture is {off} pixels from the HUD camera {cam}", None
|
|
185
|
+
return what + f", HUD camera {cam}", low
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def main():
|
|
189
|
+
ap = argparse.ArgumentParser()
|
|
190
|
+
ap.add_argument("--x64sc", required=True)
|
|
191
|
+
ap.add_argument("--harness", required=True)
|
|
192
|
+
ap.add_argument("--src", required=True)
|
|
193
|
+
ap.add_argument("--expect", choices=["whole", "torn"], required=True)
|
|
194
|
+
ap.add_argument("--timeout", default="180")
|
|
195
|
+
ap.add_argument("prg")
|
|
196
|
+
ap.add_argument("cycles", nargs="+")
|
|
197
|
+
a = ap.parse_args()
|
|
198
|
+
chk = load_check(a.harness)
|
|
199
|
+
world1, world0 = load_model(a.src)
|
|
200
|
+
torn = bad = 0
|
|
201
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
202
|
+
for model in ("pal", "ntsc"):
|
|
203
|
+
for cyc in a.cycles:
|
|
204
|
+
png = os.path.join(tmp, f"{model}-{cyc}.png")
|
|
205
|
+
cmd = ["timeout", a.timeout, a.x64sc, "-default", "-warp", "+sound", "+autostart-delay-random",
|
|
206
|
+
"-autostartprgmode", "1", "-limitcycles", cyc]
|
|
207
|
+
if model == "ntsc":
|
|
208
|
+
cmd += ["-model", "ntsc"]
|
|
209
|
+
subprocess.run(cmd + ["-exitscreenshot", png, "-autostart", a.prg],
|
|
210
|
+
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
211
|
+
if not os.path.exists(png):
|
|
212
|
+
print(f"tearcheck: no screenshot for {model} {cyc}", file=sys.stderr)
|
|
213
|
+
sys.exit(2)
|
|
214
|
+
cam = hud_camera(png, model, chk)
|
|
215
|
+
verdict, cams = judge(segments(shot_indices(png, model, chk), world1, world0), cam)
|
|
216
|
+
if cams is None:
|
|
217
|
+
torn += 1
|
|
218
|
+
bad += 1
|
|
219
|
+
print(f"{'TORN' if cams is None else 'ok '} {model.upper():4s} {int(cyc):>10,} cycles: {verdict}")
|
|
220
|
+
n = 2 * len(a.cycles)
|
|
221
|
+
if a.expect == "whole":
|
|
222
|
+
print(f"tearcheck: {n - bad} of {n} shots whole or two-frame composites")
|
|
223
|
+
sys.exit(0 if bad == 0 else 1)
|
|
224
|
+
print(f"tearcheck: {torn} of {n} shots torn; the check {'sees' if torn else 'does NOT see'} the tear")
|
|
225
|
+
sys.exit(0 if torn else 1)
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
if __name__ == "__main__":
|
|
229
|
+
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,137 @@
|
|
|
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: shmup-vertical
|
|
15
|
+
|
|
16
|
+
A vertically scrolling shoot-em-up: a river scrolls down over a fixed
|
|
17
|
+
score panel, the ship and the enemies fire character bullets, waves of
|
|
18
|
+
enemies keyed to the scroll go through a sprite multiplexer, effects play
|
|
19
|
+
inside the tune,
|
|
20
|
+
and the high score is saved to drive 8. `README.md` has the file map and
|
|
21
|
+
the first three things to extend. Start a program from it with
|
|
22
|
+
`npm run new-project -- shmup-vertical <dir>` in c64-kb. `PLAN.md` here is
|
|
23
|
+
a plan filled from real tool output; new-project keeps it as
|
|
24
|
+
`PLAN-shmup-vertical-example.md` and gives the new program a blank one.
|
|
25
|
+
|
|
26
|
+
What will bite you here:
|
|
27
|
+
|
|
28
|
+
- `src/kernel.asm` owns the raster IRQ (`$FFFE`, KERNAL banked out). Add a
|
|
29
|
+
split as a new body in its chain; do not install a second handler.
|
|
30
|
+
- No sprite may reach raster line 214 (sprites stop at Y 187, last line
|
|
31
|
+
208): a sprite there delays the panel split's writes (measured: 16 of
|
|
32
|
+
16 PAL shots broken with eight sprites on it; lines 209-213 were clean).
|
|
33
|
+
`make check` runs `make phases`, which compares the panel at all eight
|
|
34
|
+
YSCROLL phases; keep it passing after touching the split.
|
|
35
|
+
- NTSC has little time to spare. `make stage` meters a staged heavy
|
|
36
|
+
stretch (worst 15,237 of 17,095 cycles on NTSC), but play reaches
|
|
37
|
+
heavier frames: `make joytest` and `make longplay` play the game with
|
|
38
|
+
fire held and a sweep and fail on any lost frame (`LOST_FRAMES`, `$02FD`).
|
|
39
|
+
In play's heaviest frames the work ended 7 lines before the frame IRQ
|
|
40
|
+
(`-dWORKEND=1`). Re-run all three after adding work to a frame. Work that
|
|
41
|
+
runs for every enemy or bullet every frame lives in `glyph.asm`,
|
|
42
|
+
`hit.asm` and `step.asm` for that reason.
|
|
43
|
+
- Enemy dots are drawn before the beam reaches them only because enemies
|
|
44
|
+
fire from sprite Y 72-140 (`bullets.c`); `-dDRAWEND=1` measures the
|
|
45
|
+
margin. Keep new shots inside a window like it.
|
|
46
|
+
- The two playfield screens are drawn from the map; write game text to
|
|
47
|
+
`level_screen()` and give its cells colour RAM below 8 (hires).
|
|
48
|
+
- Oscar64's zero page reached `$56` here; the kernel uses none. Pass values
|
|
49
|
+
to the blob through its own bytes (`ASM_<LABEL>` in `build/asm.h`).
|
|
50
|
+
- Disk calls go through `src/hiscore.c`, which stops the chain and turns
|
|
51
|
+
sprites off around them (sprite DMA on badlines hangs the KERNAL's serial
|
|
52
|
+
transfers). `make joytest` proves the save and the reboot.
|
|
53
|
+
- `-dPROFILE=1` times each step of `play_frame` into `$0340` (CIA1 timer B,
|
|
54
|
+
IRQs held off per step); `-dWORKEND=1` records how late a frame's work
|
|
55
|
+
ended, at `$0370`; `-dLOOP_TEST=1` plays to GAME OVER and back to the
|
|
56
|
+
title; `-dEVENTLOG=1` logs each kill, hit and lost frame with its frame;
|
|
57
|
+
`-dGOD=1` keeps the ship; `make joy` with `tools/drive.py` drives the
|
|
58
|
+
normal game.
|
|
59
|
+
|
|
60
|
+
## Before any code
|
|
61
|
+
|
|
62
|
+
1. Brief: `npx tsx src/cli.ts game-briefing "<concept>" --archetype <name>`
|
|
63
|
+
(or `demo-briefing`), in the c64-kb checkout. Read what it proposes.
|
|
64
|
+
2. For each technique you keep: `technique-lookup <name>` and
|
|
65
|
+
`pitfalls-for <name>`. Start from the recipe it names (`recipe-lookup`).
|
|
66
|
+
3. Fill `PLAN.md`: paste the whole output of `check-compatibility` and of
|
|
67
|
+
`plan-budget` (same techniques) into their sections, list every technique
|
|
68
|
+
in its table, and replace every `FILL:` line.
|
|
69
|
+
|
|
70
|
+
Until `PLAN.md` passes, a hook blocks Edit and Write under `src/`, and every
|
|
71
|
+
make target that builds stops (`make plan-gate` says what is missing). With
|
|
72
|
+
C64KB set, `make` re-runs `check-compatibility` and wants the pasted Verdict.
|
|
73
|
+
The gate cannot see writes made through a shell command, or outputs edited
|
|
74
|
+
into shape by hand: do neither. `make PLAN_GATE=off` overrides it; say why in
|
|
75
|
+
`PLAN.md` if you do.
|
|
76
|
+
|
|
77
|
+
## The loop
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
make # build build/<name>.prg
|
|
81
|
+
make shot check # autopilot build, headless PAL and NTSC, graded by expect.json
|
|
82
|
+
make selftest # the FORCE_FAULT build must fail the same checks
|
|
83
|
+
make disk # build/<name>.d64
|
|
84
|
+
make claims # every store the program makes, against what it declares
|
|
85
|
+
make run # windowed VICE, for a human
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Rules
|
|
89
|
+
|
|
90
|
+
- Build before claiming. Code that has not built is not done.
|
|
91
|
+
- Measure screenshots with `check.py` through `expect.json`, never by eye.
|
|
92
|
+
Every visible claim gets a check. Add one before you trust a change.
|
|
93
|
+
- PAL and NTSC: both shots pass, or it is not done.
|
|
94
|
+
- Name the rung for every number: measured here (`make shot`, the meter, the
|
|
95
|
+
VICE monitor), taken from a c64-kb page (say which), arithmetic, or not
|
|
96
|
+
measured. Never call something verified that was not run.
|
|
97
|
+
- Frame cost comes from the meter: CIA2 timer A, printed as
|
|
98
|
+
`F<frames> W<worst> T<typical>` at row 24, columns 20 to 39, in AUTOPILOT
|
|
99
|
+
builds. It records the first `hold` frames: make that the autopilot
|
|
100
|
+
script's play frames. Typical is the median of those frames, the KB's
|
|
101
|
+
`cycles_per_frame_typical`. Keep grading, logging and printing outside the
|
|
102
|
+
bracket; work split between the main loop and IRQs is summed with
|
|
103
|
+
`METER_PAUSE` / `METER_START`.
|
|
104
|
+
- Do not invent a register, routine or address. Look it up:
|
|
105
|
+
`lookup-register`, `lookup-kernal`, `memory-map`.
|
|
106
|
+
- Lint every source you change: `npx tsx src/cli.ts lint <file>`.
|
|
107
|
+
- Commit named paths only. Never `git add -A` or `git add .`. `build/`,
|
|
108
|
+
`shots/` and `local.mk` are never committed.
|
|
109
|
+
|
|
110
|
+
## Harness facts you will need
|
|
111
|
+
|
|
112
|
+
- `AUTOPILOT=1` builds read a scripted joystick byte instead of `$DC00` and
|
|
113
|
+
grade themselves: `$02FF` = `$01` and a green border on pass, `$02` and red
|
|
114
|
+
on fail. `FORCE_FAULT=1` must turn the verdict red and move something a
|
|
115
|
+
screenshot check can see.
|
|
116
|
+
- Screenshot geometry (c64-kb `docs/runtime/vice-reference.md`): PAL 384 x 272,
|
|
117
|
+
row = raster line - 16; NTSC 384 x 247, row = line - 28; x = VIC X + 8. A
|
|
118
|
+
sprite at Y register y is drawn from line y + 1.
|
|
119
|
+
- `check.py` reads text in the ROM character set unless a check names a
|
|
120
|
+
`charset` file; the meter's cells need 0-9, F, W and T in the set on screen.
|
|
121
|
+
- A KickAssembler part called from C is a raw blob at its own `* =` address,
|
|
122
|
+
`$0880` or above; `build/asm.h` gives C its labels as `ASM_<LABEL>`
|
|
123
|
+
(`ASM_<SCOPE>_<LABEL>` inside a scope). Pass arguments through bytes in the
|
|
124
|
+
blob, not Oscar64's zero page (`$02` up; the top depends on the program:
|
|
125
|
+
`make zp` lists what the build's code touches).
|
|
126
|
+
- The meter takes CIA2 timer A. Do not open RS-232 (device 2) while it runs.
|
|
127
|
+
- The KERNAL serial routines end in `CLI` (ROM bytes `58 60` / `58 18` at
|
|
128
|
+
`$EDAB`, `$EDB5`, `$EDDB`, `$EE82`). After any disk call, `SEI` again if
|
|
129
|
+
the program runs with the KERNAL IRQ off: otherwise that IRQ lands inside
|
|
130
|
+
the meter's brackets and rewrites `$DC00`.
|
|
131
|
+
|
|
132
|
+
## Calling c64-kb
|
|
133
|
+
|
|
134
|
+
- CLI, from the c64-kb checkout (`C64KB` in `local.mk`):
|
|
135
|
+
`npx tsx src/cli.ts <command>`; `npx tsx src/cli.ts --help` lists them.
|
|
136
|
+
- MCP: `.mcp.json` starts `node <c64-kb>/dist/cli.js serve` (run
|
|
137
|
+
`npm run build` in c64-kb first).
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# shmup-vertical: a vertically scrolling shoot-em-up starter. Every target
|
|
2
|
+
# but phases, stage and joy comes from the harness:
|
|
3
|
+
# make build build/shmup-vertical.prg (after the PLAN.md gate)
|
|
4
|
+
# make run windowed VICE, joystick in port 2
|
|
5
|
+
# make shot headless PAL and NTSC exit screenshots of the autopilot build
|
|
6
|
+
# make check make phases, then grade shots/pal.png and shots/ntsc.png against expect.json
|
|
7
|
+
# make phases the panel split frozen on each of the eight YSCROLL phases, PAL and NTSC,
|
|
8
|
+
# compared with the graded phase-3 shot (tools/phases.py)
|
|
9
|
+
# make selftest prove check fails on the FORCE_FAULT=1 build
|
|
10
|
+
# make stage the heaviest frame the game makes (-dSTAGE=1): the meter's readout, PAL and NTSC
|
|
11
|
+
# make joy the normal game reading its port byte from $02FE, for tools/drive.py
|
|
12
|
+
# make joytest the joy build played to GAME OVER and rebooted: the saved HI must show
|
|
13
|
+
# make disk build/shmup-vertical.d64
|
|
14
|
+
# make claims c64-kb's claims-watch over the autopilot build, when available
|
|
15
|
+
# make clean
|
|
16
|
+
NAME := shmup-vertical
|
|
17
|
+
C_MAIN := src/main.c
|
|
18
|
+
KICK_SRC := src/kernel.asm
|
|
19
|
+
|
|
20
|
+
# Pinned after the verdict. Its disk round trip ends with the $02FF store at
|
|
21
|
+
# about 21,700,000 cycles (PAL) and 21,600,000 (NTSC), under the VICE monitor
|
|
22
|
+
# on a fresh disk. After it nothing on screen changes: PAL at 30,000,000 and
|
|
23
|
+
# 34,000,000 cycles and NTSC at 30,000,000 and 36,000,000 gave byte-identical
|
|
24
|
+
# pictures.
|
|
25
|
+
SHOT_CYCLES_PAL := 30000000
|
|
26
|
+
SHOT_CYCLES_NTSC := 30000000
|
|
27
|
+
|
|
28
|
+
# Drive 8 is attached during make shot: the autopilot writes and reads
|
|
29
|
+
# HISCORE on a fresh copy of build/shmup-vertical.d64 each run (the harness).
|
|
30
|
+
# A save cut off leaves a splat file; the program scratches and rewrites one
|
|
31
|
+
# (drive reply 60).
|
|
32
|
+
SHOT_DISK := 1
|
|
33
|
+
|
|
34
|
+
# What the program may write, for make claims, found by claims-watch on the
|
|
35
|
+
# autopilot build (30,000,000 cycles, drive 8 attached). zero_page $02-$56:
|
|
36
|
+
# Oscar64's registers ($02-$52) and main's callee-saved temporaries, which
|
|
37
|
+
# reached $56 in this build ($55 before the review's fixes grew main); a
|
|
38
|
+
# bigger main reaches further. The $DC0D stores
|
|
39
|
+
# that mask CIA1 count against all its units. The KERNAL routines are the
|
|
40
|
+
# disk calls of src/hiscore.c (kernalio.h) and the KERNAL IRQ that runs
|
|
41
|
+
# during the first load. CIA2 timers A and B are the frame meter's. $02FD
|
|
42
|
+
# is LOST_FRAMES (main.c), which make joytest reads.
|
|
43
|
+
CLAIMS_ARGS = --cycles 30000000 --disk $(abspath $(D64)) \
|
|
44
|
+
--claim 'zero_page $$02-$$56, sprite_0-7, vic_raster_irq, irq_vector_fffe, nmi_vector_fffa, sid_voice_1-3, sid_filter_volume, cia1_port_a, cia1_timer_a, cia1_timer_b, cia1_tod, cia2_vic_bank' \
|
|
45
|
+
--range 'colour=$$D800-$$DBE7,result=$$02FF,lost_frames=$$02FD' \
|
|
46
|
+
--harness 'cia2_timer_a, cia2_timer_b, cia2_tod' \
|
|
47
|
+
--kernal 'SETNAM,SETLFS,OPEN,CLOSE,CHKIN,CHKOUT,CLRCHN,CHRIN,CHROUT,READST,IRQ'
|
|
48
|
+
|
|
49
|
+
# The harness sits beside the starter in c64-kb (../_harness) or is vendored
|
|
50
|
+
# into ./harness when the starter is copied out on its own.
|
|
51
|
+
# Proof targets `npm run verify:templates -- --selftest` runs after selftest.
|
|
52
|
+
VERIFY_TARGETS := stage joytest longplay
|
|
53
|
+
|
|
54
|
+
HARNESS ?= $(firstword $(wildcard harness) ../_harness)
|
|
55
|
+
$(if $(wildcard $(HARNESS)/harness.mk),,$(error No harness at '$(HARNESS)'. Copy c64-kb's templates/_harness to ./harness, or make the project with npm run new-project in c64-kb))
|
|
56
|
+
include $(HARNESS)/harness.mk
|
|
57
|
+
|
|
58
|
+
# claims runs the autopilot build with the disk attached.
|
|
59
|
+
claims: $(D64)
|
|
60
|
+
|
|
61
|
+
# ---- phases: the split at every YSCROLL phase ----------------------------------------
|
|
62
|
+
# The graded shot freezes on YSCROLL 3 only, so a broken entry in the split's
|
|
63
|
+
# delay table (kernel.asm delay_tbl) for any other phase passes make shot
|
|
64
|
+
# check. Each build here freezes on one phase; tools/phases.py shoots all
|
|
65
|
+
# eight on both models and wants panel lines 215-250 identical to phase 3.
|
|
66
|
+
PHASES := 0 1 2 3 4 5 6 7
|
|
67
|
+
PRG_PHASES := $(foreach k,$(PHASES),build/$(NAME)-ph$(k).prg)
|
|
68
|
+
build/$(NAME)-ph%.prg: $(C_DEPS) $(ASM_OUT) $(METER_DEPS) | plan-gate
|
|
69
|
+
@mkdir -p build
|
|
70
|
+
$(OSCAR64_BUILD) -d$(AUTOPILOT_DEFINE)=1 -dFREEZE_Y=$* -o=$@ $(C_MAIN)
|
|
71
|
+
|
|
72
|
+
.PHONY: phases
|
|
73
|
+
phases: $(PRG_PHASES) $(D64)
|
|
74
|
+
$(PYTHON) tools/phases.py --x64sc $(X64SC) --d64 $(D64) --pal $(SHOT_CYCLES_PAL) --ntsc $(SHOT_CYCLES_NTSC) $(PRG_PHASES)
|
|
75
|
+
|
|
76
|
+
check: phases
|
|
77
|
+
|
|
78
|
+
# ---- stage: the heaviest frame ------------------------------------------------------
|
|
79
|
+
# -dSTAGE=1 plays a script that puts 12 enemies, bolts, enemy dots and a kill
|
|
80
|
+
# in the same frames and meters play frames 150-399. Its verdict grades no
|
|
81
|
+
# overrun and every bullet cell restored; stage-expect.json adds the meter's
|
|
82
|
+
# worst inside a frame on both models. STAGE_DEFS='-dSD=24 -dSX=16' moves
|
|
83
|
+
# the script (the worst of a 4 x 4 sweep; see PLAN.md). Re-run it after
|
|
84
|
+
# adding work to a frame.
|
|
85
|
+
STAGE_DEFS ?= -dSD=24 -dSX=16
|
|
86
|
+
PRG_STAGE := build/$(NAME)-stage.prg
|
|
87
|
+
$(PRG_STAGE): $(C_DEPS) $(ASM_OUT) $(METER_DEPS) $(STARTER_MAKEFILE) | plan-gate
|
|
88
|
+
@mkdir -p build
|
|
89
|
+
$(OSCAR64_BUILD) -d$(AUTOPILOT_DEFINE)=1 -dSTAGE=1 $(STAGE_DEFS) -o=$@ $(C_MAIN)
|
|
90
|
+
|
|
91
|
+
.PHONY: stage
|
|
92
|
+
stage: $(PRG_STAGE) $(D64)
|
|
93
|
+
$(call vice_shot,$(PRG_STAGE),40000000,,shots/stage-pal.png)
|
|
94
|
+
$(call vice_shot,$(PRG_STAGE),40000000,-model ntsc,shots/stage-ntsc.png)
|
|
95
|
+
$(PYTHON) tools/meter.py $(HARNESS_DIR) shots/stage-pal.png pal shots/stage-ntsc.png ntsc
|
|
96
|
+
$(PYTHON) $(HARNESS_DIR)/check.py stage-expect.json shots/stage-pal.png shots/stage-ntsc.png
|
|
97
|
+
|
|
98
|
+
# ---- joy: the normal game driven headless ------------------------------------------
|
|
99
|
+
# The port byte comes from $02FE instead of $DC00, so a VICE monitor can
|
|
100
|
+
# drive it (tools/drive.py).
|
|
101
|
+
PRG_JOY := build/$(NAME)-joy.prg
|
|
102
|
+
$(PRG_JOY): $(C_DEPS) $(ASM_OUT) $(METER_DEPS) | plan-gate
|
|
103
|
+
@mkdir -p build
|
|
104
|
+
$(OSCAR64_BUILD) -dJOY_SOURCE=0x02fe -o=$@ $(C_MAIN)
|
|
105
|
+
|
|
106
|
+
.PHONY: joy
|
|
107
|
+
joy: $(PRG_JOY)
|
|
108
|
+
|
|
109
|
+
# joytest: the joy build played on PAL and NTSC, fire held and the ship
|
|
110
|
+
# swept, to GAME OVER; its save, and a reboot on the same fresh disk showing
|
|
111
|
+
# that score as HI; then JOYTEST_SOAK more games a model, each graded on
|
|
112
|
+
# LOST_FRAMES (tools/joytest.py). Any lost frame fails.
|
|
113
|
+
JOYTEST_SOAK ?= 15
|
|
114
|
+
.PHONY: joytest
|
|
115
|
+
joytest: $(PRG_JOY) $(D64)
|
|
116
|
+
X64SC=$(X64SC) $(PYTHON) tools/joytest.py $(PRG_JOY) $(D64) --soak $(JOYTEST_SOAK)
|
|
117
|
+
|
|
118
|
+
# longplay: a joy build whose ship is never lost (-dGOD=1), so fire held and
|
|
119
|
+
# a sweep run through the level's later loops, where the waves come closer
|
|
120
|
+
# together: LONGPLAY_GAMES games a model at once, LONGPLAY_SECONDS of warp
|
|
121
|
+
# each, and any lost frame fails.
|
|
122
|
+
LONGPLAY_SECONDS ?= 40
|
|
123
|
+
LONGPLAY_GAMES ?= 4
|
|
124
|
+
PRG_GOD := build/$(NAME)-god.prg
|
|
125
|
+
$(PRG_GOD): $(C_DEPS) $(ASM_OUT) $(METER_DEPS) | plan-gate
|
|
126
|
+
@mkdir -p build
|
|
127
|
+
$(OSCAR64_BUILD) -dJOY_SOURCE=0x02fe -dGOD=1 -o=$@ $(C_MAIN)
|
|
128
|
+
|
|
129
|
+
.PHONY: longplay
|
|
130
|
+
longplay: $(PRG_GOD) $(D64)
|
|
131
|
+
X64SC=$(X64SC) $(PYTHON) tools/joytest.py $(PRG_GOD) $(D64) --long $(LONGPLAY_SECONDS) --soak $$(( $(LONGPLAY_GAMES) - 1 )) --jobs $(LONGPLAY_GAMES)
|