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,609 @@
|
|
|
1
|
+
---
|
|
2
|
+
recipe: cave-scan
|
|
3
|
+
toolchain: oscar64
|
|
4
|
+
output_format: PRG
|
|
5
|
+
region: both
|
|
6
|
+
techniques: [cave_scan_engine, frame_sync_loop]
|
|
7
|
+
file_formats: [PRG]
|
|
8
|
+
uses_registers: [D012, D019, D01A, D020, D021, DC04, DC05, DC06, DC07, DC0E, DC0F]
|
|
9
|
+
uses_kernal: []
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<!-- doc-type: recipe -->
|
|
13
|
+
|
|
14
|
+
# Oscar64 Cave Scan: a Boulder Dash style cave updated by one scan per cave frame
|
|
15
|
+
|
|
16
|
+
## Synopsis
|
|
17
|
+
|
|
18
|
+
A 40x22 cave of one-byte cells, updated by a single top-to-bottom,
|
|
19
|
+
left-to-right scan once every four display frames. Boulders and diamonds
|
|
20
|
+
fall and roll, Rockford digs and collects on a scripted path, and one
|
|
21
|
+
firefly follows the wall on its left. An object that moves down or right
|
|
22
|
+
gets the scanned bit (bit 7), so the scan skips it when it reaches the
|
|
23
|
+
cell it moved into. After 40 cave frames the program folds the cave into
|
|
24
|
+
a 16-bit checksum and compares it with the value a Python model of the
|
|
25
|
+
same rules produced, then prints PASS or FAIL and the cycle cost of a
|
|
26
|
+
scan: the scans of the game and three synthetic fills, one of them 380
|
|
27
|
+
falling boulders. The cave layout is original; it is not Boulder Dash
|
|
28
|
+
data. Left out: amoeba, magic wall, explosions, pushing boulders, the
|
|
29
|
+
exit and the cave timer. It implements `cave_scan_engine`
|
|
30
|
+
(`techniques/logic.md`). Build `-dSCAN_FLAG=0` to see the double-move bug.
|
|
31
|
+
|
|
32
|
+
## Source
|
|
33
|
+
|
|
34
|
+
```c
|
|
35
|
+
// cave-scan.c
|
|
36
|
+
// A 40x22 cave updated by one top-to-bottom, left-to-right scan per cave
|
|
37
|
+
// frame, with a "scanned" bit so that an object moved down or right is
|
|
38
|
+
// not processed a second time in the same scan. Boulders and diamonds
|
|
39
|
+
// fall and roll, Rockford digs and collects on a scripted path, one
|
|
40
|
+
// firefly follows the wall on its left. Amoeba, magic wall, explosions,
|
|
41
|
+
// pushing and the exit are left out. After K_FRAMES cave frames the fold
|
|
42
|
+
// of every cave frame is compared with the value a Python model of the
|
|
43
|
+
// same rules produced, and the scan's cycle cost is printed.
|
|
44
|
+
// SCAN_FLAG=0 builds the same program without the scanned bit.
|
|
45
|
+
#include <c64/vic.h>
|
|
46
|
+
#include <c64/cia.h>
|
|
47
|
+
#include <c64/rasterirq.h>
|
|
48
|
+
|
|
49
|
+
#ifndef SCAN_FLAG
|
|
50
|
+
#define SCAN_FLAG 1 // 0: show the double-move bug
|
|
51
|
+
#endif
|
|
52
|
+
|
|
53
|
+
#define SCREEN ((char *)0x0400)
|
|
54
|
+
#define COLOUR ((char *)0xd800)
|
|
55
|
+
#define W 40 // cave width in cells, steel border included
|
|
56
|
+
#define H 22 // cave height
|
|
57
|
+
#define K_FRAMES 40 // cave frames run before the check
|
|
58
|
+
#define SCAN_EVERY 4 // display frames per cave frame
|
|
59
|
+
#define EXPECT 0xe130 // Python model: fold of the cave after 40 frames
|
|
60
|
+
|
|
61
|
+
// Element codes. Bit 7 is the scanned bit; it is never set on SPACE.
|
|
62
|
+
#define SPACE 0
|
|
63
|
+
#define DIRT 1
|
|
64
|
+
#define WALL 2 // brick: round, things roll off it
|
|
65
|
+
#define STEEL 3 // not round
|
|
66
|
+
#define BOULDER 4
|
|
67
|
+
#define BOULDER_F 5 // falling: the code one above the resting one
|
|
68
|
+
#define DIAMOND 6
|
|
69
|
+
#define DIAMOND_F 7
|
|
70
|
+
#define ROCKFORD 8
|
|
71
|
+
#define FIREFLY 12 // 12..15, low two bits = heading
|
|
72
|
+
#define SCANNED 0x80
|
|
73
|
+
|
|
74
|
+
// Headings in clockwise order: left, up, right, down. Turning left is
|
|
75
|
+
// heading + 3, turning right heading + 1, both modulo 4.
|
|
76
|
+
static const signed char step[4] = { -1, -W, 1, W };
|
|
77
|
+
|
|
78
|
+
// Screen code and colour per element code 0..15.
|
|
79
|
+
static const char glyph[16] = {
|
|
80
|
+
0x20, 0x66, 0xa0, 0xa0, 0x51, 0x51, 0x5a, 0x5a,
|
|
81
|
+
0x00, 0x20, 0x20, 0x20, 0x57, 0x57, 0x57, 0x57 };
|
|
82
|
+
static const char tint[16] = {
|
|
83
|
+
VCOL_BLACK, VCOL_BROWN, VCOL_RED, VCOL_MED_GREY, VCOL_LT_GREY, VCOL_LT_GREY,
|
|
84
|
+
VCOL_CYAN, VCOL_CYAN, VCOL_YELLOW, VCOL_BLACK, VCOL_BLACK, VCOL_BLACK,
|
|
85
|
+
VCOL_ORANGE, VCOL_ORANGE, VCOL_ORANGE, VCOL_ORANGE };
|
|
86
|
+
|
|
87
|
+
// The cave's 38x20 interior, one string per row, padded with dirt.
|
|
88
|
+
// ' ' dirt, '_' space, '#' brick, 'O' boulder, 'd' diamond, 'R' Rockford,
|
|
89
|
+
// 'F' firefly heading left. An original layout, not a Boulder Dash cave.
|
|
90
|
+
static const char * const rows[20] = {
|
|
91
|
+
"",
|
|
92
|
+
" OOO d",
|
|
93
|
+
" OOO O",
|
|
94
|
+
" OdO",
|
|
95
|
+
" R",
|
|
96
|
+
"",
|
|
97
|
+
" ___O__ O_",
|
|
98
|
+
" _d_#__ #_",
|
|
99
|
+
" _###__ #_",
|
|
100
|
+
"",
|
|
101
|
+
" ########",
|
|
102
|
+
" #______#",
|
|
103
|
+
" #_F##__#",
|
|
104
|
+
" #__##__#",
|
|
105
|
+
" #______#",
|
|
106
|
+
" ########",
|
|
107
|
+
"", "", "", ""
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
// Rockford's autopilot: one move per cave frame, L U R D, '-' stands still;
|
|
111
|
+
// past the end of the string he stands still.
|
|
112
|
+
static const char script[] = "RRRRRRRRRDDDDUUUURRRUD";
|
|
113
|
+
|
|
114
|
+
static char cave[W * H];
|
|
115
|
+
static char move; // heading for this cave frame, or 0xff
|
|
116
|
+
static char dead, got;
|
|
117
|
+
|
|
118
|
+
// Cells changed by a scan, for the renderer. On overflow, redraw all.
|
|
119
|
+
#define DIRTY_MAX 64
|
|
120
|
+
static unsigned dirty[DIRTY_MAX];
|
|
121
|
+
static char ndirty, overflow;
|
|
122
|
+
|
|
123
|
+
static void mark(char *q)
|
|
124
|
+
{
|
|
125
|
+
if (ndirty < DIRTY_MAX) dirty[ndirty++] = q - cave;
|
|
126
|
+
else overflow = 1;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Put v at dst for an object leaving src. A move to a later cell in scan
|
|
130
|
+
// order sets the scanned bit, so the scan skips the object when it gets there.
|
|
131
|
+
static void put(char *dst, char v, char *src)
|
|
132
|
+
{
|
|
133
|
+
#if SCAN_FLAG
|
|
134
|
+
if (dst > src) v |= SCANNED;
|
|
135
|
+
#endif
|
|
136
|
+
*dst = v;
|
|
137
|
+
*src = SPACE;
|
|
138
|
+
mark(dst);
|
|
139
|
+
mark(src);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Roll off a round object: left first, then right. Needs the side cell
|
|
143
|
+
// and the cell below it empty. The object leaves falling.
|
|
144
|
+
static char roll(char *p, char fall)
|
|
145
|
+
{
|
|
146
|
+
if (p[-1] == SPACE && p[W - 1] == SPACE) { put(p - 1, fall, p); return 1; }
|
|
147
|
+
if (p[1] == SPACE && p[W + 1] == SPACE) { put(p + 1, fall, p); return 1; }
|
|
148
|
+
return 0;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
static char is_round(char t)
|
|
152
|
+
{
|
|
153
|
+
return t == BOULDER || t == DIAMOND || t == WALL;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// One object's turn. Called only for codes BOULDER and up.
|
|
157
|
+
__noinline void cell(char *p, char v)
|
|
158
|
+
{
|
|
159
|
+
if (v & SCANNED) { *p = v & 0x7f; return; } // moved here this scan
|
|
160
|
+
if (v == BOULDER || v == DIAMOND)
|
|
161
|
+
{
|
|
162
|
+
char b = p[W];
|
|
163
|
+
if (b == SPACE) put(p + W, v + 1, p); // start falling
|
|
164
|
+
else if (is_round(b & 0x7f)) roll(p, v + 1);
|
|
165
|
+
}
|
|
166
|
+
else if (v == BOULDER_F || v == DIAMOND_F)
|
|
167
|
+
{
|
|
168
|
+
char b = p[W];
|
|
169
|
+
char bt = b & 0x7f;
|
|
170
|
+
if (b == SPACE) put(p + W, v, p); // keep falling
|
|
171
|
+
else if (bt == ROCKFORD) { p[W] = SPACE; mark(p + W); dead = 1; }
|
|
172
|
+
else if (bt == BOULDER_F || bt == DIAMOND_F) ; // wait for it to move
|
|
173
|
+
else if (!(is_round(bt) && roll(p, v))) *p = v - 1; // land
|
|
174
|
+
}
|
|
175
|
+
else if (v == ROCKFORD)
|
|
176
|
+
{
|
|
177
|
+
if (move < 4)
|
|
178
|
+
{
|
|
179
|
+
char *t = p + step[move];
|
|
180
|
+
char tv = *t;
|
|
181
|
+
if (tv == SPACE || tv == DIRT || tv == DIAMOND)
|
|
182
|
+
{
|
|
183
|
+
if (tv == DIAMOND) got++;
|
|
184
|
+
put(t, ROCKFORD, p);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
else // firefly, heading in the low bits
|
|
189
|
+
{
|
|
190
|
+
char d = v & 3, k;
|
|
191
|
+
char hit = 0;
|
|
192
|
+
for (k = 0; k < 4; k++)
|
|
193
|
+
{
|
|
194
|
+
char *n = p + step[k];
|
|
195
|
+
if ((*n & 0x7f) == ROCKFORD) { *n = SPACE; mark(n); hit = 1; }
|
|
196
|
+
}
|
|
197
|
+
if (hit) { dead = 1; return; }
|
|
198
|
+
char dl = (d + 3) & 3;
|
|
199
|
+
if (p[step[dl]] == SPACE) put(p + step[dl], FIREFLY + dl, p);
|
|
200
|
+
else if (p[step[d]] == SPACE) put(p + step[d], FIREFLY + d, p);
|
|
201
|
+
else *p = FIREFLY + ((d + 1) & 3);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// One cave frame: every interior cell once, top to bottom, left to right.
|
|
206
|
+
// The loop only reads and compares; space, dirt and walls cost nothing more.
|
|
207
|
+
__noinline void cave_scan(void)
|
|
208
|
+
{
|
|
209
|
+
ndirty = 0; overflow = 0;
|
|
210
|
+
char *row = cave + W;
|
|
211
|
+
for (char y = 1; y < H - 1; y++, row += W)
|
|
212
|
+
for (char x = 1; x < W - 1; x++)
|
|
213
|
+
{
|
|
214
|
+
char v = row[x];
|
|
215
|
+
if (v >= BOULDER) cell(row + x, v);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// --- the demonstration: build, draw, check, time ---------------------------
|
|
220
|
+
|
|
221
|
+
static void cave_build(void)
|
|
222
|
+
{
|
|
223
|
+
for (char y = 0; y < H; y++)
|
|
224
|
+
for (char x = 0; x < W; x++)
|
|
225
|
+
{
|
|
226
|
+
char e = STEEL;
|
|
227
|
+
if (y > 0 && y < H - 1 && x > 0 && x < W - 1)
|
|
228
|
+
{
|
|
229
|
+
const char *r = rows[y - 1];
|
|
230
|
+
char c = ' ', j = 0;
|
|
231
|
+
while (r[j] && j < x - 1) j++;
|
|
232
|
+
if (j == x - 1 && r[j]) c = r[j];
|
|
233
|
+
e = c == '_' ? SPACE : c == '#' ? WALL : c == 'O' ? BOULDER :
|
|
234
|
+
c == 'd' ? DIAMOND : c == 'R' ? ROCKFORD : c == 'F' ? FIREFLY : DIRT;
|
|
235
|
+
}
|
|
236
|
+
cave[y * W + x] = e;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
static void draw_cell(unsigned i)
|
|
241
|
+
{
|
|
242
|
+
char t = cave[i] & 0x0f;
|
|
243
|
+
SCREEN[i] = glyph[t];
|
|
244
|
+
COLOUR[i] = tint[t];
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
static void draw_all(void)
|
|
248
|
+
{
|
|
249
|
+
for (unsigned i = 0; i < W * H; i++) draw_cell(i);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
static unsigned fold_cave(unsigned chk)
|
|
253
|
+
{
|
|
254
|
+
for (unsigned i = 0; i < W * H; i++)
|
|
255
|
+
{
|
|
256
|
+
unsigned t = chk ^ (cave[i] & 0x7f);
|
|
257
|
+
chk = (t << 2) + t + 1; // (chk ^ v) * 5 + 1, no multiply call
|
|
258
|
+
}
|
|
259
|
+
return chk;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
static void put_text(char row, char col, const char *s)
|
|
263
|
+
{
|
|
264
|
+
char *p = SCREEN + W * row + col;
|
|
265
|
+
char *q = COLOUR + W * row + col;
|
|
266
|
+
while (*s)
|
|
267
|
+
{
|
|
268
|
+
char c = *s++;
|
|
269
|
+
if (c >= 'A' && c <= 'Z') c -= 64;
|
|
270
|
+
*p++ = c; *q++ = VCOL_WHITE;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// v as n decimal digits (n = 1..6), leading zeros shown.
|
|
275
|
+
static void put_dec(char row, char col, unsigned long v, char n)
|
|
276
|
+
{
|
|
277
|
+
static const unsigned long pw[6] = { 100000, 10000, 1000, 100, 10, 1 };
|
|
278
|
+
char *p = SCREEN + W * row + col;
|
|
279
|
+
for (char i = 6 - n; i < 6; i++)
|
|
280
|
+
{
|
|
281
|
+
char d = 0x30;
|
|
282
|
+
while (v >= pw[i]) { v -= pw[i]; d++; }
|
|
283
|
+
*p++ = d;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
static void put_hex16(char row, char col, unsigned v)
|
|
288
|
+
{
|
|
289
|
+
static const char hx[16] = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
|
290
|
+
0x38, 0x39, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
|
|
291
|
+
char *p = SCREEN + W * row + col;
|
|
292
|
+
for (char i = 0; i < 4; i++)
|
|
293
|
+
{
|
|
294
|
+
p[i] = hx[(v >> (12 - 4 * i)) & 15];
|
|
295
|
+
COLOUR[W * row + col + i] = VCOL_WHITE;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// CIA1 timer A counts phi2 from $FFFF; timer B counts A's underflows,
|
|
300
|
+
// so a scan longer than 65,535 cycles is still read correctly.
|
|
301
|
+
static void t_start(void)
|
|
302
|
+
{
|
|
303
|
+
cia1.cra = 0; cia1.crb = 0;
|
|
304
|
+
cia1.ta = 0xffff; cia1.tb = 0xffff;
|
|
305
|
+
cia1.crb = 0x51; // force load, start, count A underflows
|
|
306
|
+
cia1.cra = 0x11; // force load, start, count phi2
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
static unsigned long t_stop(void)
|
|
310
|
+
{
|
|
311
|
+
cia1.cra = 0; cia1.crb = 0; // stop both before reading
|
|
312
|
+
return ((unsigned long)(0xffff - cia1.tb) << 16) + (0xffff - cia1.ta);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
static unsigned long time_scan(void)
|
|
316
|
+
{
|
|
317
|
+
t_start();
|
|
318
|
+
cave_scan();
|
|
319
|
+
return t_stop();
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// A synthetic fill of the interior for the worst-case timing: a is the
|
|
323
|
+
// element on odd interior rows, b on even ones, c on every other cell of
|
|
324
|
+
// the odd rows (0xff: same as a).
|
|
325
|
+
static void fill(char a, char b, char c)
|
|
326
|
+
{
|
|
327
|
+
for (char y = 1; y < H - 1; y++)
|
|
328
|
+
for (char x = 1; x < W - 1; x++)
|
|
329
|
+
cave[y * W + x] = (y & 1) ? ((x & 1) || c == 0xff ? a : c) : b;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
RIRQCode frame_irq;
|
|
333
|
+
volatile char ticks;
|
|
334
|
+
|
|
335
|
+
__interrupt void on_frame(void) { ticks++; }
|
|
336
|
+
|
|
337
|
+
int main(void)
|
|
338
|
+
{
|
|
339
|
+
__asm { sei }
|
|
340
|
+
vic.color_border = VCOL_BLACK;
|
|
341
|
+
vic.color_back = VCOL_BLACK;
|
|
342
|
+
for (unsigned i = 0; i < 1000; i++) { SCREEN[i] = 0x20; COLOUR[i] = VCOL_WHITE; }
|
|
343
|
+
|
|
344
|
+
// Worst-case timing first, interrupts off, display on (badlines in).
|
|
345
|
+
// Each fill is built again before its scan, so every scan has work.
|
|
346
|
+
unsigned long c_idle, c_fall, c_fly, c_null;
|
|
347
|
+
move = 0xff;
|
|
348
|
+
cave_build(); fill(DIRT, DIRT, 0xff); c_idle = time_scan();
|
|
349
|
+
cave_build(); fill(BOULDER_F, SPACE, 0xff); c_fall = time_scan();
|
|
350
|
+
cave_build(); fill(FIREFLY, SPACE, SPACE); c_fly = time_scan();
|
|
351
|
+
t_start(); c_null = t_stop();
|
|
352
|
+
|
|
353
|
+
// The game: one cave frame every SCAN_EVERY display frames.
|
|
354
|
+
cave_build();
|
|
355
|
+
draw_all();
|
|
356
|
+
rirq_init(true);
|
|
357
|
+
rirq_build(&frame_irq, 1);
|
|
358
|
+
rirq_call(&frame_irq, 0, on_frame);
|
|
359
|
+
rirq_set(0, 250, &frame_irq);
|
|
360
|
+
rirq_sort();
|
|
361
|
+
rirq_start();
|
|
362
|
+
|
|
363
|
+
unsigned chk = 0;
|
|
364
|
+
unsigned long cmin = 0xffffff, cmax = 0;
|
|
365
|
+
char next = ticks, start = ticks, late = 0;
|
|
366
|
+
for (char f = 0; f < K_FRAMES; f++)
|
|
367
|
+
{
|
|
368
|
+
next += SCAN_EVERY;
|
|
369
|
+
if (!((char)(ticks - next) & 0x80)) late++; // no wait: the last frame overran
|
|
370
|
+
while ((char)(ticks - next) & 0x80) ; // wait for the cave frame
|
|
371
|
+
char m = f < sizeof(script) - 1 ? script[f] : '-';
|
|
372
|
+
move = m == 'L' ? 0 : m == 'U' ? 1 : m == 'R' ? 2 : m == 'D' ? 3 : 0xff;
|
|
373
|
+
unsigned long c = time_scan() - c_null;
|
|
374
|
+
if (c < cmin) cmin = c;
|
|
375
|
+
if (c > cmax) cmax = c;
|
|
376
|
+
if (overflow) draw_all();
|
|
377
|
+
else for (char n = 0; n < ndirty; n++) draw_cell(dirty[n]);
|
|
378
|
+
}
|
|
379
|
+
char spent = ticks - start; // display frames for K_FRAMES cave frames
|
|
380
|
+
chk = fold_cave(0);
|
|
381
|
+
|
|
382
|
+
put_text(22, 0, "CAVE 40 TICKS LATE GOT RF ");
|
|
383
|
+
put_dec(22, 14, spent, 3); put_dec(22, 23, late, 2); put_dec(22, 30, got, 1);
|
|
384
|
+
put_text(22, 35, dead ? "DEAD" : "OK ");
|
|
385
|
+
put_text(23, 0, "CHK / ");
|
|
386
|
+
put_hex16(23, 4, chk); put_hex16(23, 9, EXPECT);
|
|
387
|
+
put_text(23, 14, chk == EXPECT ? "PASS SCAN" : "FAIL SCAN");
|
|
388
|
+
put_dec(23, 24, cmin, 6); put_text(23, 30, "-"); put_dec(23, 31, cmax, 6);
|
|
389
|
+
put_text(24, 0, "IDLE FALL FLY");
|
|
390
|
+
put_dec(24, 5, c_idle - c_null, 6); put_dec(24, 17, c_fall - c_null, 6); put_dec(24, 28, c_fly - c_null, 6);
|
|
391
|
+
vic.color_border = chk == EXPECT ? VCOL_GREEN : VCOL_RED;
|
|
392
|
+
for (;;) ;
|
|
393
|
+
return 0;
|
|
394
|
+
}
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
## Build
|
|
398
|
+
|
|
399
|
+
```bash
|
|
400
|
+
oscar64 -tm=c64 -O2 -o=cave-scan.prg cave-scan.c
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
Run headless (PAL; add `-model ntsc` for NTSC):
|
|
404
|
+
|
|
405
|
+
```bash
|
|
406
|
+
timeout 180 x64sc -default -warp +sound +autostart-delay-random -autostartprgmode 1 -limitcycles 12000000 -exitscreenshot cave-scan.png -autostart cave-scan.prg
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
The report is on screen between 8,000,000 and 9,000,000 cycles on PAL
|
|
410
|
+
(measured by bisecting `-limitcycles`); 12,000,000 leaves a margin.
|
|
411
|
+
|
|
412
|
+
## Expected output
|
|
413
|
+
|
|
414
|
+
`screenshots/cave-scan.png` (PAL) and `screenshots/cave-scan-ntsc.png`
|
|
415
|
+
(NTSC). Black screen, green border. The cave fills rows 0 to 21, one cell
|
|
416
|
+
per character: brown checker dirt, red brick, grey steel border, light
|
|
417
|
+
grey ball boulders, cyan diamonds, orange ring firefly. Rockford is dead,
|
|
418
|
+
so no yellow `@` remains. Rows 22 to 24, PAL:
|
|
419
|
+
|
|
420
|
+
```text
|
|
421
|
+
CAVE 40 TICKS 160 LATE 00 GOT 1 RF DEAD
|
|
422
|
+
CHK E130/E130 PASS SCAN 016609-018175
|
|
423
|
+
IDLE 014206 FALL 137818 FLY 130451
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
NTSC reads `TICKS 161`, `SCAN 017115-018559` and
|
|
427
|
+
`IDLE 014421 FALL 138892 FLY 131531`; the rest is the same.
|
|
428
|
+
|
|
429
|
+
- `TICKS` is the display frames the 40 cave frames took, counted by a
|
|
430
|
+
raster IRQ on line 250. `LATE` counts cave frames that found their
|
|
431
|
+
frame already gone. 160 and 0 mean the cadence of one scan per four
|
|
432
|
+
frames held.
|
|
433
|
+
- `GOT 1 RF DEAD`: one diamond collected, then Rockford killed by the
|
|
434
|
+
boulder he dug out from under, as the script intends.
|
|
435
|
+
- `CHK` is the program's fold of the 880 cells after the last cave
|
|
436
|
+
frame, then the model's value.
|
|
437
|
+
- `SCAN` is the fewest and most cycles one scan of this cave took in the
|
|
438
|
+
game, CIA1 timer A cascaded into timer B, display on.
|
|
439
|
+
- `IDLE`, `FALL` and `FLY` are single scans of synthetic interiors, run
|
|
440
|
+
before the game with interrupts off and the display on: all dirt; odd
|
|
441
|
+
rows of falling boulders over empty rows (380 movers); odd rows of
|
|
442
|
+
fireflies on alternate cells over empty rows (190 movers). The FALL
|
|
443
|
+
scan overflows the 64-entry dirty list, so after the first 32 moves it
|
|
444
|
+
records nothing, which makes it slightly cheaper than a scan that
|
|
445
|
+
records every change.
|
|
446
|
+
|
|
447
|
+
The model, the rules of the listing written again in Python:
|
|
448
|
+
|
|
449
|
+
```python
|
|
450
|
+
SPACE, DIRT, WALL, STEEL, BOULDER, BOULDER_F, DIAMOND, DIAMOND_F, ROCKFORD = range(9)
|
|
451
|
+
FIREFLY, SCANNED, W, H = 12, 0x80, 40, 22
|
|
452
|
+
OFF = [-1, -W, 1, W] # left, up, right, down
|
|
453
|
+
ROWS = ["", " OOO d", " OOO O", " OdO", " R", "",
|
|
454
|
+
" ___O__ O_", " _d_#__ #_", " _###__ #_", "",
|
|
455
|
+
" ########", " #______#",
|
|
456
|
+
" #_F##__#", " #__##__#",
|
|
457
|
+
" #______#", " ########",
|
|
458
|
+
"", "", "", ""]
|
|
459
|
+
CODE = {' ': DIRT, '_': SPACE, '#': WALL, 'O': BOULDER, 'd': DIAMOND,
|
|
460
|
+
'R': ROCKFORD, 'F': FIREFLY}
|
|
461
|
+
SCRIPT = "RRRRRRRRRDDDDUUUURRRUD"
|
|
462
|
+
|
|
463
|
+
def run(frames=40, flag=True):
|
|
464
|
+
c = [STEEL] * (W * H)
|
|
465
|
+
for y, r in enumerate(ROWS, 1):
|
|
466
|
+
for x, ch in enumerate(r.ljust(38), 1):
|
|
467
|
+
c[y * W + x] = CODE[ch]
|
|
468
|
+
def put(d, v, s):
|
|
469
|
+
c[d] = v | (SCANNED if flag and d > s else 0); c[s] = SPACE
|
|
470
|
+
def roll(i, fall):
|
|
471
|
+
for o in (-1, 1):
|
|
472
|
+
if c[i + o] == SPACE and c[i + W + o] == SPACE:
|
|
473
|
+
put(i + o, fall, i); return True
|
|
474
|
+
return False
|
|
475
|
+
rnd = lambda t: t in (BOULDER, DIAMOND, WALL)
|
|
476
|
+
for f in range(frames):
|
|
477
|
+
m = "LURD".find(SCRIPT[f]) if f < len(SCRIPT) else -1
|
|
478
|
+
for y in range(1, H - 1):
|
|
479
|
+
for x in range(1, W - 1):
|
|
480
|
+
i = y * W + x; v = c[i]
|
|
481
|
+
if v < BOULDER: continue
|
|
482
|
+
if v & SCANNED: c[i] = v & 0x7f; continue
|
|
483
|
+
if v in (BOULDER, DIAMOND):
|
|
484
|
+
if c[i + W] == SPACE: put(i + W, v + 1, i)
|
|
485
|
+
elif rnd(c[i + W] & 0x7f): roll(i, v + 1)
|
|
486
|
+
elif v in (BOULDER_F, DIAMOND_F):
|
|
487
|
+
b = c[i + W]; bt = b & 0x7f
|
|
488
|
+
if b == SPACE: put(i + W, v, i)
|
|
489
|
+
elif bt == ROCKFORD: c[i + W] = SPACE
|
|
490
|
+
elif bt in (BOULDER_F, DIAMOND_F): pass
|
|
491
|
+
elif not (rnd(bt) and roll(i, v)): c[i] = v - 1
|
|
492
|
+
elif v == ROCKFORD:
|
|
493
|
+
if m >= 0 and c[i + OFF[m]] in (SPACE, DIRT, DIAMOND):
|
|
494
|
+
put(i + OFF[m], ROCKFORD, i)
|
|
495
|
+
else:
|
|
496
|
+
d = v & 3
|
|
497
|
+
near = [i + o for o in OFF if c[i + o] & 0x7f == ROCKFORD]
|
|
498
|
+
for n in near: c[n] = SPACE
|
|
499
|
+
if near: continue
|
|
500
|
+
dl = (d + 3) & 3
|
|
501
|
+
if c[i + OFF[dl]] == SPACE: put(i + OFF[dl], FIREFLY + dl, i)
|
|
502
|
+
elif c[i + OFF[d]] == SPACE: put(i + OFF[d], FIREFLY + d, i)
|
|
503
|
+
else: c[i] = FIREFLY + ((d + 1) & 3)
|
|
504
|
+
assert not any(v & SCANNED for v in c)
|
|
505
|
+
chk = 0
|
|
506
|
+
for v in c:
|
|
507
|
+
chk = ((chk ^ (v & 0x7f)) * 5 + 1) & 0xffff
|
|
508
|
+
return chk
|
|
509
|
+
|
|
510
|
+
print(hex(run()), hex(run(flag=False))) # 0xe130 0x262f
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
## Why this works
|
|
514
|
+
|
|
515
|
+
`cave_scan` walks the 38x20 interior with a row pointer and a byte
|
|
516
|
+
index, so the common case, a cell of space, dirt or wall, costs one
|
|
517
|
+
indexed load, one compare and the loop step: 14,206 cycles for 760 cells
|
|
518
|
+
of dirt on PAL, about 19 a cell with badline stalls in. Every code from
|
|
519
|
+
`BOULDER` up, and every code with bit 7 set, goes to `cell()`. Keeping
|
|
520
|
+
the object rules out of the loop body matters in Oscar64: a first
|
|
521
|
+
version with the rules inline computed the cell pointer before the test
|
|
522
|
+
and took about 48,000 cycles for the same dirt scan (47,731 in a rebuild).
|
|
523
|
+
|
|
524
|
+
`put()` is the one place an object moves. It sets bit 7 on the
|
|
525
|
+
destination when the destination is later in scan order, that is to the
|
|
526
|
+
right or below. A move left or up lands on a cell the scan has passed,
|
|
527
|
+
so it needs no mark. When the scan reaches a marked cell, `cell()`
|
|
528
|
+
clears the bit and does nothing else, so every mark is gone by the end
|
|
529
|
+
of the scan without a second pass; the model asserts this after every
|
|
530
|
+
frame. Bit 7 is never set on `SPACE`, so the rules can compare a
|
|
531
|
+
neighbour with `SPACE` directly.
|
|
532
|
+
|
|
533
|
+
A resting boulder or diamond with space below starts falling and moves
|
|
534
|
+
down at once. One resting on a round object (boulder, diamond, brick)
|
|
535
|
+
rolls: left if the left cell and the cell below it are empty, otherwise
|
|
536
|
+
right under the same test. A falling one keeps falling into space, kills
|
|
537
|
+
Rockford if he is below it, waits if the object below is itself falling,
|
|
538
|
+
tries to roll off a round object, and otherwise lands, becoming the
|
|
539
|
+
resting code one below. A resting boulder above Rockford stays where it
|
|
540
|
+
is; that is why Rockford can stand under one, step away, step back and
|
|
541
|
+
be killed by it one cave frame after it starts to fall. The firefly
|
|
542
|
+
turns left if it can, goes on if it cannot, and turns right on the spot
|
|
543
|
+
if both are blocked. Any firefly next to Rockford kills him.
|
|
544
|
+
|
|
545
|
+
**The double-move bug, run.** The same listing built with
|
|
546
|
+
`-dSCAN_FLAG=0` and run with the pinned PAL command printed
|
|
547
|
+
`CHK 262F/E130 FAIL`, `GOT 0 RF OK`, `LATE 01` and a slowest game scan
|
|
548
|
+
of 30,620 cycles. 262F is the value the Python model gives with the flag
|
|
549
|
+
off, and all 880 cells of the picture match that model. The model shows
|
|
550
|
+
what happened in cave frame 1: Rockford, told to step right once, was
|
|
551
|
+
processed again in every cell he entered and tunnelled from column 2 to
|
|
552
|
+
column 38 in one scan. The
|
|
553
|
+
boulder that rolls right off the brick at column 18 fell two more cells
|
|
554
|
+
in the same scan, and the firefly moved several times. From there the
|
|
555
|
+
script walks a different cave, collects nothing and never meets the
|
|
556
|
+
boulder. The unflagged build is not pinned.
|
|
557
|
+
|
|
558
|
+
The cadence is a raster IRQ on line 250 that counts frames, the
|
|
559
|
+
`frame_sync_loop` pattern. The main loop waits for the count to pass the
|
|
560
|
+
next multiple of four, scans, then redraws only the cells in the dirty
|
|
561
|
+
list. At 16,609 to 18,175 cycles a scan of this cave fits in one PAL
|
|
562
|
+
frame of 19,656 cycles (on NTSC, 17,115 to 18,559, it does not fit the
|
|
563
|
+
17,095-cycle frame), with little room for anything else in that
|
|
564
|
+
frame. That is why the game scans once per four frames. The full-cave
|
|
565
|
+
fold that the check needs is about three frames on its own, so it runs
|
|
566
|
+
once, after the last cave frame: a first version folded after every cave
|
|
567
|
+
frame and ran 178 frames for 40 cave frames, 39 of them late.
|
|
568
|
+
|
|
569
|
+
The whole cave fits the screen, because a cell is one character. Boulder
|
|
570
|
+
Dash drew each object as a 2x2-character block and scrolled a window of
|
|
571
|
+
about 19.5 by 11.5 objects over the cave (elmerproductions, below).
|
|
572
|
+
|
|
573
|
+
## Verification
|
|
574
|
+
|
|
575
|
+
VICE x64sc 3.10, windowless build, Oscar64 as installed on 2026-09-23.
|
|
576
|
+
|
|
577
|
+
**Every cell against the model.** A script read each of the 880 cave
|
|
578
|
+
cells of both pictures, matched the 8x8 pixels against
|
|
579
|
+
`chargen-901225-01.bin` and the foreground colour against VICE's palette
|
|
580
|
+
triples for the model (`runtime/vice-reference.md`, "The default
|
|
581
|
+
palette"), and compared them with the element the Python model holds
|
|
582
|
+
after 40 frames. 0 mismatches on PAL and on NTSC. The same script on the
|
|
583
|
+
`SCAN_FLAG=0` picture: 0 mismatches against the model with the flag
|
|
584
|
+
off, 47 against the model with it on.
|
|
585
|
+
|
|
586
|
+
**Text and border.** Rows 22 to 24 were decoded the same way and read
|
|
587
|
+
as quoted above; the border pixel is (98, 213, 50) on PAL and
|
|
588
|
+
(114, 189, 103) on NTSC, colour 5 on each.
|
|
589
|
+
|
|
590
|
+
**Reproducibility.** The pinned command was run twice per model; the
|
|
591
|
+
PNG bytes were identical each time.
|
|
592
|
+
|
|
593
|
+
## Sources
|
|
594
|
+
|
|
595
|
+
- https://www.elmerproductions.com/sp/peterb/rawCaveData.html (Peter
|
|
596
|
+
Broadribb's Boulder Dash I cave format): the 40x22 cave with a steel
|
|
597
|
+
border and a 38x20 play area, the visible area of 19.5 by 11.5
|
|
598
|
+
objects, and object codes with separate "scanned this frame" variants
|
|
599
|
+
for fireflies, boulders, diamonds, butterflies, Rockford and amoeba,
|
|
600
|
+
there to stop an object being scanned twice in one frame. Falling
|
|
601
|
+
boulders kill Rockford; stationary ones do not.
|
|
602
|
+
- https://www.boulder-dash.nl/forum/viewtopic.php?t=652 ("Cave Scanning
|
|
603
|
+
Order" thread): the cave is scanned row by row, top to bottom, each
|
|
604
|
+
row left to right; an element that moves or grows gets a delay state
|
|
605
|
+
and is not scanned again in that frame; the states reset at the end of
|
|
606
|
+
the frame. Forum report, not measured here.
|
|
607
|
+
- `frame-sync-loop.md`: the raster IRQ tick counter, reused in shape.
|
|
608
|
+
- `print-number.md` and `difficulty-tables.md`: the CIA1 timing harness
|
|
609
|
+
and the cascaded timer B, reused in shape.
|