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,723 @@
|
|
|
1
|
+
---
|
|
2
|
+
recipe: bfs-distance-map
|
|
3
|
+
toolchain: oscar64
|
|
4
|
+
output_format: PRG
|
|
5
|
+
region: both
|
|
6
|
+
techniques: [bfs_distance_map]
|
|
7
|
+
file_formats: [PRG]
|
|
8
|
+
uses_registers: [D011, D020, D021, DC04, DC05, DC06, DC07, DC0E, DC0F]
|
|
9
|
+
uses_kernal: []
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<!-- doc-type: recipe -->
|
|
13
|
+
|
|
14
|
+
# Oscar64 BFS Distance Map: one time-sliced flood from the player, four chasers stepping downhill
|
|
15
|
+
|
|
16
|
+
## Synopsis
|
|
17
|
+
|
|
18
|
+
A 40 by 22 tile maze, a player that follows a scripted route, and four
|
|
19
|
+
chasers that never search. A breadth-first flood from the player's cell
|
|
20
|
+
gives every open cell its distance in one byte (255 for a wall or an
|
|
21
|
+
unvisited cell). The flood runs from a ring queue, 32 cells per frame,
|
|
22
|
+
into a second map; when the queue empties the two maps swap, so the
|
|
23
|
+
chasers always read a complete map. A new flood starts when the player
|
|
24
|
+
has changed cell since the last one began. Each chaser steps to the
|
|
25
|
+
neighbour with the lowest distance every fourth frame, ties broken up,
|
|
26
|
+
left, down, right. With `SHOW_DIST 1` every cell shows its distance's
|
|
27
|
+
units digit in a colour band as the flood reaches it. The verdict
|
|
28
|
+
compares the live map byte for byte with a map computed in Python and
|
|
29
|
+
compiled in, then requires all four chasers to reach the player's cell
|
|
30
|
+
within a bounded number of frames with no step onto a wall. `$02FF` =
|
|
31
|
+
`01` and a green border on pass, `02` and red on fail. This is the
|
|
32
|
+
`bfs_distance_map` technique in `docs/techniques/logic.md`; the
|
|
33
|
+
result-byte contract is `headless-verify.md`.
|
|
34
|
+
|
|
35
|
+
## Source
|
|
36
|
+
|
|
37
|
+
```c
|
|
38
|
+
// bfs-distance-map.c
|
|
39
|
+
//
|
|
40
|
+
// A breadth-first flood over a 40 by 22 tile maze gives every open cell
|
|
41
|
+
// its distance from the player, one byte per cell, 255 for a wall or an
|
|
42
|
+
// unvisited cell. The flood runs from a ring queue, SLICE cells per
|
|
43
|
+
// frame, into a work map; when the queue empties the work map becomes
|
|
44
|
+
// the live map the chasers read. A new flood starts when the player has
|
|
45
|
+
// changed cell since the last one began. Four chasers step to the
|
|
46
|
+
// neighbour with the lowest distance every CHASE_EVERY frames, ties
|
|
47
|
+
// broken up, left, down, right. The player follows a scripted route,
|
|
48
|
+
// one cell every PLAYER_EVERY frames, then stops.
|
|
49
|
+
// Verdict: after the player stops and the next flood completes, the
|
|
50
|
+
// live map is compared byte for byte with a map computed in Python and
|
|
51
|
+
// compiled in, and its checksum shown; then all four chasers must reach
|
|
52
|
+
// the player's cell within MAX_WAIT frames, and no chaser may ever stand
|
|
53
|
+
// on a wall. $02FF = 01 and a green border on pass, 02 and red on fail.
|
|
54
|
+
// Row 0: worst slice, last full flood, frames per flood, worst chaser
|
|
55
|
+
// pass, all CIA1 cycles. Row 1: checksum, mismatches, wall steps,
|
|
56
|
+
// frames from the stop to the last arrival, result. Row 2: floods run
|
|
57
|
+
// and the worst whole iteration (must stay under one frame).
|
|
58
|
+
// SHOW_DIST 1 draws each cell's distance as a digit (units) in a colour
|
|
59
|
+
// band as the flood reaches it; 0 leaves the floor as dots.
|
|
60
|
+
// Build: oscar64 -tm=c64 -O2 -o=bfs-distance-map.prg bfs-distance-map.c
|
|
61
|
+
#include <c64/vic.h>
|
|
62
|
+
#include <c64/cia.h>
|
|
63
|
+
#include <string.h>
|
|
64
|
+
|
|
65
|
+
#define SCREEN ((char *)0x0400)
|
|
66
|
+
#define COLOUR ((char *)0xd800)
|
|
67
|
+
#define RESULT (*(volatile char *)0x02ff)
|
|
68
|
+
#define CODE_PASS 0x01
|
|
69
|
+
#define CODE_FAIL 0x02
|
|
70
|
+
|
|
71
|
+
#define SHOW_DIST 1
|
|
72
|
+
#define SLICE 32 // cells expanded per frame
|
|
73
|
+
#define PLAYER_EVERY 2 // frames per player cell
|
|
74
|
+
#define CHASE_EVERY 4 // frames per chaser cell
|
|
75
|
+
#define MAX_WAIT 400 // frames allowed after the player stops
|
|
76
|
+
#define NCHASE 4
|
|
77
|
+
|
|
78
|
+
// Map rows 0-21 are screen rows 3-24. '#' wall, '.' open.
|
|
79
|
+
#define MAP_ROW0 3
|
|
80
|
+
#define MW 40
|
|
81
|
+
#define MH 22
|
|
82
|
+
#define UNSEEN 255
|
|
83
|
+
const char maze[MH][MW + 1] = {
|
|
84
|
+
"########################################", // 0
|
|
85
|
+
"#........#........#..........#........##", // 1
|
|
86
|
+
"#.######.#.######.#.########.#.######.##", // 2
|
|
87
|
+
"#.#......#.#....#.#........#.#.#......##", // 3
|
|
88
|
+
"#.#.########.##.#.########.#.#.#.###.###", // 4
|
|
89
|
+
"#.#..........#..#..........#...#...#...#", // 5
|
|
90
|
+
"#.##########.#.###########.#####.#.#####", // 6
|
|
91
|
+
"#............#.............#.....#.....#", // 7
|
|
92
|
+
"######.#######.###########.#.#####.###.#", // 8
|
|
93
|
+
"#......#.......#...........#.#.......#.#", // 9
|
|
94
|
+
"#.######.#####.#.#########.#.#.#####.#.#", // 10
|
|
95
|
+
"#........#.....#.#.......#...#.#...#...#", // 11
|
|
96
|
+
"#.########.#####.#.#####.#####.#.#.###.#", // 12
|
|
97
|
+
"#.#........#.....#.#...#.......#.#.....#", // 13
|
|
98
|
+
"#.#.########.#####.#.#.#########.#####.#", // 14
|
|
99
|
+
"#.#........#.......#.#...........#.....#", // 15
|
|
100
|
+
"#.########.#########.#.#########.#.###.#", // 16
|
|
101
|
+
"#..........#.........#.........#.#...#.#", // 17
|
|
102
|
+
"#.#########.#########...#######.#.....##", // 18
|
|
103
|
+
"#.........#...........#.......#...#.#..#", // 19
|
|
104
|
+
"#.#######.#.#########.#######.#####.####", // 20
|
|
105
|
+
"########################################", // 21
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
// The player's route: one letter per cell moved.
|
|
109
|
+
#define START_X 1
|
|
110
|
+
#define START_Y 1
|
|
111
|
+
const char route[] = "DDDDDDRRRRRRRRRRRUUUURRRDDLDDRRRRRRRRRRRRDDLLLLLLLLLL";
|
|
112
|
+
|
|
113
|
+
// Chaser start cells.
|
|
114
|
+
const char start_cx[NCHASE] = { 37, 1, 38, 14 };
|
|
115
|
+
const char start_cy[NCHASE] = { 1, 20, 19, 11 };
|
|
116
|
+
|
|
117
|
+
// Expected distance map from the player's final cell (16, 9), computed
|
|
118
|
+
// by bfs_model.py (Python, plain BFS). Checksum $C077.
|
|
119
|
+
#define EXP_SUM 0xc077
|
|
120
|
+
const char exp_map[MH * MW] = {
|
|
121
|
+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
122
|
+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
123
|
+
255, 53, 54, 55, 56, 55, 54, 53, 52, 255, 34, 33, 32, 31, 30, 29, 28, 27, 255, 25,
|
|
124
|
+
26, 27, 28, 29, 30, 31, 32, 33, 34, 255, 40, 39, 38, 37, 36, 35, 34, 33, 255, 255,
|
|
125
|
+
255, 52, 255, 255, 255, 255, 255, 255, 51, 255, 35, 255, 255, 255, 255, 255, 255, 26, 255, 24,
|
|
126
|
+
255, 255, 255, 255, 255, 255, 255, 255, 35, 255, 41, 255, 255, 255, 255, 255, 255, 32, 255, 255,
|
|
127
|
+
255, 51, 255, 45, 46, 47, 48, 49, 50, 255, 36, 255, 32, 31, 30, 29, 255, 25, 255, 23,
|
|
128
|
+
22, 21, 20, 19, 18, 17, 16, 255, 36, 255, 42, 255, 26, 27, 28, 29, 30, 31, 255, 255,
|
|
129
|
+
255, 50, 255, 44, 255, 255, 255, 255, 255, 255, 255, 255, 33, 255, 255, 28, 255, 24, 255, 255,
|
|
130
|
+
255, 255, 255, 255, 255, 255, 15, 255, 37, 255, 41, 255, 25, 255, 255, 255, 31, 255, 255, 255,
|
|
131
|
+
255, 49, 255, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 255, 26, 27, 255, 23, 22, 21,
|
|
132
|
+
20, 19, 18, 17, 16, 15, 14, 255, 38, 39, 40, 255, 24, 25, 26, 255, 32, 33, 34, 255,
|
|
133
|
+
255, 48, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 35, 255, 25, 255, 255, 255, 255, 255,
|
|
134
|
+
255, 255, 255, 255, 255, 255, 13, 255, 255, 255, 255, 255, 23, 255, 27, 255, 255, 255, 255, 255,
|
|
135
|
+
255, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 255, 24, 23, 22, 21, 20, 19,
|
|
136
|
+
18, 17, 16, 15, 14, 13, 12, 255, 18, 19, 20, 21, 22, 255, 28, 29, 30, 31, 32, 255,
|
|
137
|
+
255, 255, 255, 255, 255, 255, 43, 255, 255, 255, 255, 255, 255, 255, 25, 255, 255, 255, 255, 255,
|
|
138
|
+
255, 255, 255, 255, 255, 255, 11, 255, 17, 255, 255, 255, 255, 255, 29, 255, 255, 255, 33, 255,
|
|
139
|
+
255, 43, 44, 45, 46, 45, 44, 255, 32, 31, 30, 29, 28, 27, 26, 255, 0, 1, 2, 3,
|
|
140
|
+
4, 5, 6, 7, 8, 9, 10, 255, 16, 255, 34, 33, 32, 31, 30, 31, 32, 255, 34, 255,
|
|
141
|
+
255, 42, 255, 255, 255, 255, 255, 255, 33, 255, 255, 255, 255, 255, 27, 255, 1, 255, 255, 255,
|
|
142
|
+
255, 255, 255, 255, 255, 255, 11, 255, 15, 255, 35, 255, 255, 255, 255, 255, 33, 255, 35, 255,
|
|
143
|
+
255, 41, 40, 39, 38, 37, 36, 35, 34, 255, 32, 31, 30, 29, 28, 255, 2, 255, 20, 21,
|
|
144
|
+
22, 23, 24, 25, 26, 255, 12, 13, 14, 255, 36, 255, 46, 45, 44, 255, 34, 35, 36, 255,
|
|
145
|
+
255, 42, 255, 255, 255, 255, 255, 255, 255, 255, 33, 255, 255, 255, 255, 255, 3, 255, 19, 255,
|
|
146
|
+
255, 255, 255, 255, 27, 255, 255, 255, 255, 255, 35, 255, 47, 255, 43, 255, 255, 255, 37, 255,
|
|
147
|
+
255, 43, 255, 41, 40, 39, 38, 37, 36, 35, 34, 255, 8, 7, 6, 5, 4, 255, 18, 255,
|
|
148
|
+
64, 63, 62, 255, 28, 29, 30, 31, 32, 33, 34, 255, 48, 255, 42, 41, 40, 39, 38, 255,
|
|
149
|
+
255, 44, 255, 42, 255, 255, 255, 255, 255, 255, 255, 255, 9, 255, 255, 255, 255, 255, 17, 255,
|
|
150
|
+
65, 255, 61, 255, 255, 255, 255, 255, 255, 255, 255, 255, 49, 255, 255, 255, 255, 255, 39, 255,
|
|
151
|
+
255, 45, 255, 43, 44, 45, 46, 47, 48, 49, 50, 255, 10, 11, 12, 13, 14, 15, 16, 255,
|
|
152
|
+
66, 255, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 255, 44, 43, 42, 41, 40, 255,
|
|
153
|
+
255, 46, 255, 255, 255, 255, 255, 255, 255, 255, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
154
|
+
67, 255, 61, 255, 255, 255, 255, 255, 255, 255, 255, 255, 51, 255, 45, 255, 255, 255, 41, 255,
|
|
155
|
+
255, 47, 48, 49, 50, 51, 52, 53, 54, 53, 52, 255, 76, 75, 74, 73, 72, 71, 70, 69,
|
|
156
|
+
68, 255, 62, 63, 64, 65, 66, 67, 68, 69, 70, 255, 52, 255, 46, 47, 48, 255, 42, 255,
|
|
157
|
+
255, 48, 255, 255, 255, 255, 255, 255, 255, 255, 255, 76, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
158
|
+
255, 64, 63, 64, 255, 255, 255, 255, 255, 255, 255, 52, 255, 48, 47, 48, 49, 50, 255, 255,
|
|
159
|
+
255, 49, 50, 51, 52, 53, 54, 55, 56, 57, 255, 75, 74, 73, 72, 71, 70, 69, 68, 67,
|
|
160
|
+
66, 65, 255, 65, 66, 67, 68, 69, 70, 71, 255, 51, 50, 49, 255, 49, 255, 51, 52, 255,
|
|
161
|
+
255, 50, 255, 255, 255, 255, 255, 255, 255, 58, 255, 76, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
162
|
+
255, 66, 255, 255, 255, 255, 255, 255, 255, 72, 255, 255, 255, 255, 255, 50, 255, 255, 255, 255,
|
|
163
|
+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
164
|
+
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
// --- distance maps and the ring queue ---------------------------------------
|
|
168
|
+
char solid[MH * MW]; // 1 where the maze has a wall
|
|
169
|
+
char map_a[MH * MW], map_b[MH * MW];
|
|
170
|
+
char *live = map_a; // complete map the chasers read
|
|
171
|
+
char *work = map_b; // map the flood is writing
|
|
172
|
+
unsigned row_off[MH];
|
|
173
|
+
|
|
174
|
+
char qx[256], qy[256]; // ring queue; byte indices wrap
|
|
175
|
+
char qhead, qtail;
|
|
176
|
+
bool flood_on;
|
|
177
|
+
char flood_px, flood_py; // player cell the flood started from
|
|
178
|
+
char flood_frames;
|
|
179
|
+
unsigned long flood_cycles;
|
|
180
|
+
|
|
181
|
+
unsigned clear_pos; // bytes of work cleared so far
|
|
182
|
+
#define CLEAR_CHUNK 440 // per frame; two frames for the map
|
|
183
|
+
|
|
184
|
+
// A flood starts with the clear of its work map, CLEAR_CHUNK bytes per
|
|
185
|
+
// frame, so the 880-byte clear never shares a frame with a full slice.
|
|
186
|
+
// The seed cell is written when the clear is complete.
|
|
187
|
+
void flood_begin(char px, char py)
|
|
188
|
+
{
|
|
189
|
+
clear_pos = 0;
|
|
190
|
+
flood_px = px; flood_py = py;
|
|
191
|
+
flood_on = true;
|
|
192
|
+
flood_frames = 0;
|
|
193
|
+
flood_cycles = 0;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Digit and colour per distance, built at start: units digit, colour by
|
|
197
|
+
// band of eight, 255 shown as a dot in dark grey.
|
|
198
|
+
char dig_ch[256], dig_col[256];
|
|
199
|
+
const char band_col[8] = { VCOL_WHITE, VCOL_YELLOW, VCOL_LT_GREEN, VCOL_CYAN,
|
|
200
|
+
VCOL_LT_BLUE, VCOL_PURPLE, VCOL_LT_RED, VCOL_ORANGE };
|
|
201
|
+
|
|
202
|
+
static inline void try_cell(char x, char y, unsigned o, char d)
|
|
203
|
+
{
|
|
204
|
+
if (!solid[o] && work[o] == UNSEEN) {
|
|
205
|
+
work[o] = d;
|
|
206
|
+
qx[qtail] = x; qy[qtail] = y;
|
|
207
|
+
qtail++;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Expand up to SLICE queued cells. Returns true when the flood finished.
|
|
212
|
+
bool flood_slice(void)
|
|
213
|
+
{
|
|
214
|
+
if (clear_pos < MH * MW) {
|
|
215
|
+
memset(work + clear_pos, UNSEEN, CLEAR_CHUNK);
|
|
216
|
+
clear_pos += CLEAR_CHUNK;
|
|
217
|
+
if (clear_pos == MH * MW) {
|
|
218
|
+
work[row_off[flood_py] + flood_px] = 0;
|
|
219
|
+
qx[0] = flood_px; qy[0] = flood_py;
|
|
220
|
+
qhead = 0; qtail = 1;
|
|
221
|
+
}
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
char n = 0;
|
|
225
|
+
while (qhead != qtail && n < SLICE) {
|
|
226
|
+
char x = qx[qhead], y = qy[qhead];
|
|
227
|
+
qhead++;
|
|
228
|
+
unsigned o = row_off[y] + x;
|
|
229
|
+
char d = work[o] + 1;
|
|
230
|
+
try_cell(x, y - 1, o - MW, d);
|
|
231
|
+
try_cell(x - 1, y, o - 1, d);
|
|
232
|
+
try_cell(x, y + 1, o + MW, d);
|
|
233
|
+
try_cell(x + 1, y, o + 1, d);
|
|
234
|
+
#if SHOW_DIST
|
|
235
|
+
SCREEN[o + MAP_ROW0 * 40] = dig_ch[d - 1];
|
|
236
|
+
COLOUR[o + MAP_ROW0 * 40] = dig_col[d - 1];
|
|
237
|
+
#endif
|
|
238
|
+
n++;
|
|
239
|
+
}
|
|
240
|
+
if (qhead != qtail)
|
|
241
|
+
return false;
|
|
242
|
+
char *t = live; live = work; work = t;
|
|
243
|
+
flood_on = false;
|
|
244
|
+
return true;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// --- CIA1 timer B: cycles between start and stop ------------------------------
|
|
248
|
+
static inline void timer_start(void)
|
|
249
|
+
{
|
|
250
|
+
cia1.crb = 0x00;
|
|
251
|
+
cia1.tb = 0xffff;
|
|
252
|
+
cia1.crb = 0x11;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
static inline unsigned timer_stop(void)
|
|
256
|
+
{
|
|
257
|
+
cia1.crb = 0x00;
|
|
258
|
+
return 0xffff - cia1.tb;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// --- actors -------------------------------------------------------------------
|
|
262
|
+
char px, py;
|
|
263
|
+
char cx[NCHASE], cy[NCHASE];
|
|
264
|
+
char under_ch[NCHASE + 1], under_col[NCHASE + 1];
|
|
265
|
+
const char actor_col[NCHASE + 1] = { VCOL_WHITE, VCOL_CYAN, VCOL_LT_RED, VCOL_LT_GREEN, VCOL_YELLOW };
|
|
266
|
+
unsigned wall_steps;
|
|
267
|
+
|
|
268
|
+
// One downhill step: the neighbour with the lowest live distance, only
|
|
269
|
+
// if lower than the chaser's own; ties go up, left, down, right.
|
|
270
|
+
void chaser_step(char i)
|
|
271
|
+
{
|
|
272
|
+
char x = cx[i], y = cy[i];
|
|
273
|
+
unsigned o = row_off[y] + x;
|
|
274
|
+
char best = live[o], bx = x, by = y, d;
|
|
275
|
+
d = live[o - MW]; if (d < best) { best = d; bx = x; by = y - 1; }
|
|
276
|
+
d = live[o - 1]; if (d < best) { best = d; bx = x - 1; by = y; }
|
|
277
|
+
d = live[o + MW]; if (d < best) { best = d; bx = x; by = y + 1; }
|
|
278
|
+
d = live[o + 1]; if (d < best) { best = d; bx = x + 1; by = y; }
|
|
279
|
+
cx[i] = bx; cy[i] = by;
|
|
280
|
+
if (solid[row_off[by] + bx])
|
|
281
|
+
wall_steps++;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
static inline unsigned cell_off(char x, char y)
|
|
285
|
+
{
|
|
286
|
+
return row_off[y] + x + MAP_ROW0 * 40;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
void actors_lift(void)
|
|
290
|
+
{
|
|
291
|
+
for (char i = 0; i < NCHASE; i++) {
|
|
292
|
+
unsigned o = cell_off(cx[i], cy[i]);
|
|
293
|
+
SCREEN[o] = under_ch[i]; COLOUR[o] = under_col[i];
|
|
294
|
+
}
|
|
295
|
+
unsigned o = cell_off(px, py);
|
|
296
|
+
SCREEN[o] = under_ch[NCHASE]; COLOUR[o] = under_col[NCHASE];
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
void actors_draw(void)
|
|
300
|
+
{
|
|
301
|
+
unsigned o = cell_off(px, py);
|
|
302
|
+
under_ch[NCHASE] = SCREEN[o]; under_col[NCHASE] = COLOUR[o];
|
|
303
|
+
SCREEN[o] = 0x53; COLOUR[o] = actor_col[NCHASE]; // heart
|
|
304
|
+
for (char i = 0; i < NCHASE; i++) {
|
|
305
|
+
o = cell_off(cx[i], cy[i]);
|
|
306
|
+
under_ch[i] = SCREEN[o]; under_col[i] = COLOUR[o];
|
|
307
|
+
SCREEN[o] = 0x51; COLOUR[o] = actor_col[i]; // ball
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// --- HUD ----------------------------------------------------------------------
|
|
312
|
+
// Indexed on purpose: with the pointer-walking form (*p++ = *s++) Oscar64
|
|
313
|
+
// 1.32.271 at -O2 inlined the first call of this program without
|
|
314
|
+
// clearing Y, so its label landed 40-odd cells away (seen in the listing:
|
|
315
|
+
// no LDY #0 before the first STA (zp),y loop; the second call had one).
|
|
316
|
+
void put_str(char *p, const char *s)
|
|
317
|
+
{
|
|
318
|
+
for (char i = 0; s[i]; i++)
|
|
319
|
+
p[i] = s[i];
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
void put_dec(char *p, unsigned long v, char digits)
|
|
323
|
+
{
|
|
324
|
+
for (char i = digits; i > 0; i--) {
|
|
325
|
+
p[i - 1] = 0x30 + (char)(v % 10);
|
|
326
|
+
v /= 10;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
void put_hex(char *p, unsigned v)
|
|
331
|
+
{
|
|
332
|
+
for (char i = 4; i > 0; i--) {
|
|
333
|
+
char n = v & 15;
|
|
334
|
+
p[i - 1] = n < 10 ? 0x30 + n : 0x01 + n - 10;
|
|
335
|
+
v >>= 4;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
unsigned checksum(const char *m)
|
|
340
|
+
{
|
|
341
|
+
char a = 0, c = 0;
|
|
342
|
+
for (unsigned i = 0; i < MH * MW; i++) {
|
|
343
|
+
a += m[i];
|
|
344
|
+
c += a;
|
|
345
|
+
}
|
|
346
|
+
return ((unsigned)c << 8) | a;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
int main(void)
|
|
350
|
+
{
|
|
351
|
+
__asm { sei }
|
|
352
|
+
vic.color_border = VCOL_BLACK;
|
|
353
|
+
vic.color_back = VCOL_BLACK;
|
|
354
|
+
memset(SCREEN, 0x20, 1000);
|
|
355
|
+
memset(COLOUR, VCOL_LT_GREY, 1000);
|
|
356
|
+
for (char y = 0; y < MH; y++)
|
|
357
|
+
row_off[y] = (unsigned)y * MW;
|
|
358
|
+
for (unsigned i = 0; i < 256; i++) {
|
|
359
|
+
dig_ch[i] = 0x30 + (char)(i % 10);
|
|
360
|
+
dig_col[i] = band_col[(i >> 3) & 7];
|
|
361
|
+
}
|
|
362
|
+
dig_ch[UNSEEN] = 0x2e; dig_col[UNSEEN] = VCOL_DARK_GREY;
|
|
363
|
+
memset(map_a, UNSEEN, MH * MW);
|
|
364
|
+
for (char y = 0; y < MH; y++)
|
|
365
|
+
for (char x = 0; x < MW; x++) {
|
|
366
|
+
unsigned o = cell_off(x, y);
|
|
367
|
+
bool wall = maze[y][x] == '#';
|
|
368
|
+
solid[row_off[y] + x] = wall;
|
|
369
|
+
if (wall) { SCREEN[o] = 0xa0; COLOUR[o] = VCOL_BLUE; }
|
|
370
|
+
else { SCREEN[o] = 0x2e; COLOUR[o] = VCOL_DARK_GREY; }
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
put_str(SCREEN, s"sl fl fr ch");
|
|
374
|
+
put_str(SCREEN + 40, s"sum mis wall t r");
|
|
375
|
+
put_str(SCREEN + 80, s"floods it");
|
|
376
|
+
|
|
377
|
+
px = START_X; py = START_Y;
|
|
378
|
+
for (char i = 0; i < NCHASE; i++) { cx[i] = start_cx[i]; cy[i] = start_cy[i]; }
|
|
379
|
+
actors_draw();
|
|
380
|
+
|
|
381
|
+
unsigned frame = 0, t_slice = 0, t_chase = 0, floods = 0, wait = 0, t_it = 0;
|
|
382
|
+
unsigned long t_flood = 0;
|
|
383
|
+
char fr_flood = 0, ri = 0, fault = 0;
|
|
384
|
+
unsigned mismatch = 0, sum = 0;
|
|
385
|
+
bool stopped = false, checked = false, done = false, hud = false;
|
|
386
|
+
|
|
387
|
+
for (;;) {
|
|
388
|
+
vic_waitFrame();
|
|
389
|
+
if (done)
|
|
390
|
+
continue;
|
|
391
|
+
frame++;
|
|
392
|
+
cia1.cra = 0x00; cia1.ta = 0xffff; cia1.cra = 0x11; // timer A: whole iteration
|
|
393
|
+
actors_lift();
|
|
394
|
+
|
|
395
|
+
// Flood: continue the slice in progress, or start one if the
|
|
396
|
+
// player has moved since the last began.
|
|
397
|
+
if (!flood_on && (px != flood_px || py != flood_py || floods == 0)) {
|
|
398
|
+
flood_begin(px, py);
|
|
399
|
+
floods++;
|
|
400
|
+
}
|
|
401
|
+
if (flood_on) {
|
|
402
|
+
flood_frames++;
|
|
403
|
+
timer_start();
|
|
404
|
+
bool fin = flood_slice();
|
|
405
|
+
unsigned t = timer_stop();
|
|
406
|
+
if (t > t_slice) t_slice = t;
|
|
407
|
+
flood_cycles += t;
|
|
408
|
+
if (fin) {
|
|
409
|
+
t_flood = flood_cycles;
|
|
410
|
+
fr_flood = flood_frames;
|
|
411
|
+
hud = true;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// Player along the route, then stop.
|
|
416
|
+
if (!stopped && (frame % PLAYER_EVERY) == 0) {
|
|
417
|
+
char c = route[ri];
|
|
418
|
+
if (c == 0)
|
|
419
|
+
stopped = true;
|
|
420
|
+
else {
|
|
421
|
+
if (c == 'U') py--;
|
|
422
|
+
else if (c == 'D') py++;
|
|
423
|
+
else if (c == 'L') px--;
|
|
424
|
+
else px++;
|
|
425
|
+
ri++;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// Chasers downhill on the live map.
|
|
430
|
+
if ((frame % CHASE_EVERY) == 0) {
|
|
431
|
+
timer_start();
|
|
432
|
+
for (char i = 0; i < NCHASE; i++)
|
|
433
|
+
chaser_step(i);
|
|
434
|
+
unsigned t = timer_stop();
|
|
435
|
+
if (t > t_chase) t_chase = t;
|
|
436
|
+
}
|
|
437
|
+
actors_draw();
|
|
438
|
+
cia1.cra = 0x00;
|
|
439
|
+
unsigned t_this = 0xffff - cia1.ta;
|
|
440
|
+
if (t_this > t_it) t_it = t_this;
|
|
441
|
+
|
|
442
|
+
// HUD, outside the timed work; the 32-bit decimal print is slow.
|
|
443
|
+
if (hud) {
|
|
444
|
+
hud = false;
|
|
445
|
+
put_dec(SCREEN + 3, t_slice, 5);
|
|
446
|
+
put_dec(SCREEN + 12, t_flood, 7);
|
|
447
|
+
put_dec(SCREEN + 23, fr_flood, 2);
|
|
448
|
+
put_dec(SCREEN + 29, t_chase, 4);
|
|
449
|
+
put_dec(SCREEN + 87, floods, 3);
|
|
450
|
+
put_dec(SCREEN + 94, t_it, 5);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// Verdict.
|
|
454
|
+
if (stopped) {
|
|
455
|
+
wait++;
|
|
456
|
+
if (!checked && !flood_on && flood_px == px && flood_py == py) {
|
|
457
|
+
checked = true;
|
|
458
|
+
for (unsigned i = 0; i < MH * MW; i++)
|
|
459
|
+
if (live[i] != exp_map[i]) mismatch++;
|
|
460
|
+
sum = checksum(live);
|
|
461
|
+
put_hex(SCREEN + 44, sum);
|
|
462
|
+
put_dec(SCREEN + 53, mismatch, 3);
|
|
463
|
+
}
|
|
464
|
+
char here = 0;
|
|
465
|
+
for (char i = 0; i < NCHASE; i++)
|
|
466
|
+
if (cx[i] == px && cy[i] == py) here++;
|
|
467
|
+
if (checked && (here == NCHASE || wait > MAX_WAIT)) {
|
|
468
|
+
done = true;
|
|
469
|
+
if (mismatch || sum != EXP_SUM) fault = 1;
|
|
470
|
+
else if (wall_steps) fault = 2;
|
|
471
|
+
else if (here != NCHASE) fault = 3;
|
|
472
|
+
put_dec(SCREEN + 62, wall_steps, 3);
|
|
473
|
+
put_dec(SCREEN + 68, wait, 4);
|
|
474
|
+
char code = fault ? CODE_FAIL : CODE_PASS;
|
|
475
|
+
RESULT = code;
|
|
476
|
+
vic.color_border = fault ? VCOL_RED : VCOL_GREEN;
|
|
477
|
+
SCREEN[75] = 0x30 + code;
|
|
478
|
+
SCREEN[76] = 0x30 + fault;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
return 0;
|
|
483
|
+
}
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
## Build
|
|
487
|
+
|
|
488
|
+
```bash
|
|
489
|
+
oscar64 -tm=c64 -O2 -o=bfs-distance-map.prg bfs-distance-map.c
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
Oscar64 1.32.271 builds it with no warnings; the PRG is 4,952 bytes.
|
|
493
|
+
|
|
494
|
+
The expected map and its checksum come from this script (Python 3),
|
|
495
|
+
which floods the same maze from the route's last cell with a plain
|
|
496
|
+
queue. It prints `route 53 steps, ends at (16, 9); open cells 404,
|
|
497
|
+
popped 404`, `max distance 76; checksum $C077`, the four chasers' start
|
|
498
|
+
distances (33, 50, 52, 28) and the `exp_map` initialiser the listing
|
|
499
|
+
compiles in.
|
|
500
|
+
|
|
501
|
+
```text
|
|
502
|
+
# bfs_model.py: the reference for bfs-distance-map.c. Same maze, same
|
|
503
|
+
# route, a plain breadth-first flood from the player's final cell. Prints
|
|
504
|
+
# the expected distance map as C initialisers and its checksum.
|
|
505
|
+
from collections import deque
|
|
506
|
+
|
|
507
|
+
MAZE = [
|
|
508
|
+
"########################################", # 0
|
|
509
|
+
"#........#........#..........#........##", # 1
|
|
510
|
+
"#.######.#.######.#.########.#.######.##", # 2
|
|
511
|
+
"#.#......#.#....#.#........#.#.#......##", # 3
|
|
512
|
+
"#.#.########.##.#.########.#.#.#.###.###", # 4
|
|
513
|
+
"#.#..........#..#..........#...#...#...#", # 5
|
|
514
|
+
"#.##########.#.###########.#####.#.#####", # 6
|
|
515
|
+
"#............#.............#.....#.....#", # 7
|
|
516
|
+
"######.#######.###########.#.#####.###.#", # 8
|
|
517
|
+
"#......#.......#...........#.#.......#.#", # 9
|
|
518
|
+
"#.######.#####.#.#########.#.#.#####.#.#", # 10
|
|
519
|
+
"#........#.....#.#.......#...#.#...#...#", # 11
|
|
520
|
+
"#.########.#####.#.#####.#####.#.#.###.#", # 12
|
|
521
|
+
"#.#........#.....#.#...#.......#.#.....#", # 13
|
|
522
|
+
"#.#.########.#####.#.#.#########.#####.#", # 14
|
|
523
|
+
"#.#........#.......#.#...........#.....#", # 15
|
|
524
|
+
"#.########.#########.#.#########.#.###.#", # 16
|
|
525
|
+
"#..........#.........#.........#.#...#.#", # 17
|
|
526
|
+
"#.#########.#########...#######.#.....##", # 18
|
|
527
|
+
"#.........#...........#.......#...#.#..#", # 19
|
|
528
|
+
"#.#######.#.#########.#######.#####.####", # 20
|
|
529
|
+
"########################################", # 21
|
|
530
|
+
]
|
|
531
|
+
W, H = 40, 22
|
|
532
|
+
UNSEEN = 255
|
|
533
|
+
|
|
534
|
+
# The player's scripted route: start cell, then one letter per cell moved.
|
|
535
|
+
START = (1, 1)
|
|
536
|
+
ROUTE = "DDDDDDRRRRRRRRRRRUUUURRRDDLDDRRRRRRRRRRRRDDLLLLLLLLLL"
|
|
537
|
+
CHASERS = [(37, 1), (1, 20), (38, 19), (14, 11)]
|
|
538
|
+
DIRS = [(0, -1), (-1, 0), (0, 1), (1, 0)] # up, left, down, right (tie order)
|
|
539
|
+
|
|
540
|
+
|
|
541
|
+
def check_maze():
|
|
542
|
+
assert len(MAZE) == H
|
|
543
|
+
for r in MAZE:
|
|
544
|
+
assert len(r) == W, (len(r), r)
|
|
545
|
+
assert set(r) <= {"#", "."}
|
|
546
|
+
assert r[0] == "#" and r[-1] == "#"
|
|
547
|
+
assert MAZE[0] == "#" * W and MAZE[-1] == "#" * W
|
|
548
|
+
|
|
549
|
+
|
|
550
|
+
def walk(start, route):
|
|
551
|
+
x, y = start
|
|
552
|
+
cells = [(x, y)]
|
|
553
|
+
for c in route:
|
|
554
|
+
dx, dy = {"U": (0, -1), "L": (-1, 0), "D": (0, 1), "R": (1, 0)}[c]
|
|
555
|
+
x, y = x + dx, y + dy
|
|
556
|
+
assert MAZE[y][x] == ".", ("route hits wall at", x, y)
|
|
557
|
+
cells.append((x, y))
|
|
558
|
+
return cells
|
|
559
|
+
|
|
560
|
+
|
|
561
|
+
def flood(px, py):
|
|
562
|
+
d = [[UNSEEN] * W for _ in range(H)]
|
|
563
|
+
d[py][px] = 0
|
|
564
|
+
q = deque([(px, py)])
|
|
565
|
+
popped = 0
|
|
566
|
+
while q:
|
|
567
|
+
x, y = q.popleft()
|
|
568
|
+
popped += 1
|
|
569
|
+
for dx, dy in DIRS:
|
|
570
|
+
nx, ny = x + dx, y + dy
|
|
571
|
+
if MAZE[ny][nx] == "." and d[ny][nx] == UNSEEN:
|
|
572
|
+
d[ny][nx] = d[y][x] + 1
|
|
573
|
+
q.append((nx, ny))
|
|
574
|
+
return d, popped
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
def checksum(d):
|
|
578
|
+
# two running byte sums: a += byte, c += a, both mod 256; result c:a
|
|
579
|
+
a = c = 0
|
|
580
|
+
for y in range(H):
|
|
581
|
+
for x in range(W):
|
|
582
|
+
a = (a + d[y][x]) & 0xFF
|
|
583
|
+
c = (c + a) & 0xFF
|
|
584
|
+
return (c << 8) | a
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
def main():
|
|
588
|
+
check_maze()
|
|
589
|
+
cells = walk(START, ROUTE)
|
|
590
|
+
px, py = cells[-1]
|
|
591
|
+
d, popped = flood(px, py)
|
|
592
|
+
open_cells = sum(r.count(".") for r in MAZE)
|
|
593
|
+
print(f"route {len(ROUTE)} steps, ends at ({px}, {py}); open cells {open_cells}, popped {popped}")
|
|
594
|
+
print(f"max distance {max(v for r in d for v in r if v != UNSEEN)}; checksum ${checksum(d):04X}")
|
|
595
|
+
for cx, cy in CHASERS:
|
|
596
|
+
assert MAZE[cy][cx] == "."
|
|
597
|
+
print(f"chaser ({cx}, {cy}) distance {d[cy][cx]}")
|
|
598
|
+
print("const char exp_map[MH * MW] = {")
|
|
599
|
+
for y in range(H):
|
|
600
|
+
for half in (0, 20):
|
|
601
|
+
print(" " + ", ".join(f"{v:3d}" for v in d[y][half:half + 20]) + ",")
|
|
602
|
+
print("};")
|
|
603
|
+
|
|
604
|
+
|
|
605
|
+
if __name__ == "__main__":
|
|
606
|
+
main()
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
One Oscar64 fault shaped the listing. With `put_str` written as
|
|
610
|
+
`while (*s) *p++ = *s++;`, Oscar64 1.32.271 at `-O2` inlined the first
|
|
611
|
+
call in `main` without an `LDY #0` before its `STA (zp),y` loop, so the
|
|
612
|
+
first HUD label landed wherever the maze loop had left Y; the second and
|
|
613
|
+
third calls got the `LDY`. The listing's indexed form
|
|
614
|
+
(`p[i] = s[i]`) compiles correctly. Seen in the `.asm` listing and on
|
|
615
|
+
screen; not reduced to a minimal case here.
|
|
616
|
+
|
|
617
|
+
## Expected output
|
|
618
|
+
|
|
619
|
+
Black background, blue wall blocks, and after the first flood every open
|
|
620
|
+
cell shows a digit, the units digit of its distance from the player,
|
|
621
|
+
coloured by band of eight: white 0 to 7, yellow 8 to 15, light green,
|
|
622
|
+
cyan, light blue, purple, light red, orange, then white again from 64.
|
|
623
|
+
The player is a yellow heart, the chasers are balls in white, cyan,
|
|
624
|
+
light red and light green. Rows 0 to 2 are the HUD.
|
|
625
|
+
|
|
626
|
+
At the pinned 6,500,000 cycles the player has finished its route and
|
|
627
|
+
stands at (16, 9) (screen row 12, column 16); the last flood is complete
|
|
628
|
+
and the chasers are closing in, one of them already on the player's
|
|
629
|
+
cell on NTSC. The HUD reads (measured in VICE x64sc 3.10, decoded
|
|
630
|
+
against the character ROM):
|
|
631
|
+
|
|
632
|
+
| Row | PAL | NTSC |
|
|
633
|
+
|---|---|---|
|
|
634
|
+
| 0 | `SL 10655 FL 0140341 FR 15 CH 1220` | `SL 10915 FL 0144026 FR 15 CH 1220` |
|
|
635
|
+
| 1 | `SUM C077 MIS 000 WALL T R` | same |
|
|
636
|
+
| 2 | `FLOODS 009 IT 13196` | `FLOODS 009 IT 13456` |
|
|
637
|
+
|
|
638
|
+
`SL` is the worst flood slice in CIA1 cycles (32 cells expanded and
|
|
639
|
+
drawn), `FL` the last complete flood (the sum of its slices), `FR` the
|
|
640
|
+
frames it took (two clearing the work map, thirteen expanding), `CH` the
|
|
641
|
+
worst pass of four chaser steps, `IT` the worst whole iteration (lift
|
|
642
|
+
actors, flood slice, player, chasers, draw; the HUD prints are outside
|
|
643
|
+
it). `SUM` is the live map's checksum, equal to the model's `$C077`, and
|
|
644
|
+
`MIS 000` says no byte of the 880 differs from `exp_map`. `WALL`, `T`
|
|
645
|
+
and `R` are filled in at the verdict.
|
|
646
|
+
|
|
647
|
+
Screenshots at 6,500,000 cycles, each identical over two runs:
|
|
648
|
+
`screenshots/bfs-distance-map.png` (PAL) and
|
|
649
|
+
`screenshots/bfs-distance-map-ntsc.png` (NTSC). Measured with PIL
|
|
650
|
+
against the character ROM: every open cell not under an actor shows the
|
|
651
|
+
units digit of the model's distance (399 cells on PAL, 400 on NTSC,
|
|
652
|
+
none wrong), the actor glyphs cover the rest (five cells on PAL, four on
|
|
653
|
+
NTSC where one chaser has arrived), and all 476 wall cells are reverse
|
|
654
|
+
blocks. The script:
|
|
655
|
+
|
|
656
|
+
```text
|
|
657
|
+
from PIL import Image
|
|
658
|
+
import bfs_model as m
|
|
659
|
+
rom = open('chargen-901225-01.bin', 'rb').read()
|
|
660
|
+
G = {tuple(rom[c*8:c*8+8]): c for c in range(128)}
|
|
661
|
+
def check(png, ntsc):
|
|
662
|
+
top = 23 if ntsc else 35 # PNG row of text row 0
|
|
663
|
+
px = Image.open(png).convert('RGB').load()
|
|
664
|
+
d, _ = m.flood(*m.walk(m.START, m.ROUTE)[-1])
|
|
665
|
+
ok = bad = 0
|
|
666
|
+
for y in range(22):
|
|
667
|
+
for x in range(40):
|
|
668
|
+
bits = tuple(sum((px[32+8*x+i, top+8*(y+3)+j] != (0, 0, 0)) << (7-i)
|
|
669
|
+
for i in range(8)) for j in range(8))
|
|
670
|
+
c = G.get(bits)
|
|
671
|
+
if d[y][x] == 255 or c in (0x51, 0x53):
|
|
672
|
+
continue # wall, or an actor on top
|
|
673
|
+
if c == 0x30 + d[y][x] % 10: ok += 1
|
|
674
|
+
else: bad += 1
|
|
675
|
+
return ok, bad
|
|
676
|
+
assert check('bfs-distance-map.png', False) == (399, 0)
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
The verdict comes 145 frames after the player stops, at about
|
|
680
|
+
8,200,000 cycles on PAL. At 9,000,000 cycles both models show
|
|
681
|
+
`WALL 000 T 0145 R 10` and a green border, (98, 213, 50) on PAL and
|
|
682
|
+
(114, 189, 103) on NTSC, with `$02FF` = `01`: the map matched, no chaser
|
|
683
|
+
ever stood on a wall, and all four reached the player's cell.
|
|
684
|
+
|
|
685
|
+
A build with `SHOW_DIST 0` (no digit drawing) reads `SL 08710 FL
|
|
686
|
+
0115912 IT 11246` on PAL and `SL 09010 FL 0119513 IT 11503` on NTSC,
|
|
687
|
+
with the same verdict. The NTSC slice is higher on both builds because
|
|
688
|
+
the iteration runs past the vertical blank into the badlines, and the
|
|
689
|
+
CIA counts the stolen cycles (arithmetic, rung 3; the two models'
|
|
690
|
+
figures differ by 260 on the digit build).
|
|
691
|
+
|
|
692
|
+
## Why this works
|
|
693
|
+
|
|
694
|
+
One flood serves every chaser. Breadth-first order visits cells in
|
|
695
|
+
non-decreasing distance, so the first time a cell is reached its
|
|
696
|
+
distance is final and it never needs revisiting: 404 open cells cost
|
|
697
|
+
404 pops and at most four neighbour tests each. Every chaser then makes
|
|
698
|
+
one decision from four byte reads, 1,220 cycles for all four including
|
|
699
|
+
the timer. A per-enemy search would cost the flood again for each one.
|
|
700
|
+
|
|
701
|
+
Two maps make the slicing safe. The flood writes the work map over
|
|
702
|
+
fifteen frames while the chasers read the live map from the previous
|
|
703
|
+
flood; the swap is one pointer exchange in the frame the queue empties.
|
|
704
|
+
The player moves one cell every two frames, so the live map is at most
|
|
705
|
+
about eight cells stale, and a chaser stepping downhill on a slightly
|
|
706
|
+
old map still moves toward where the player was, then corrects when the
|
|
707
|
+
next map lands. The 880-byte clear of the work map is the first two
|
|
708
|
+
frames of each flood, 440 bytes each, so it never shares a frame with
|
|
709
|
+
a full 32-cell slice; when it did, the worst iteration was 19,226
|
|
710
|
+
cycles, over an NTSC frame.
|
|
711
|
+
|
|
712
|
+
The ring queue is 256 entries of x and y with byte indices that wrap
|
|
713
|
+
on their own. A breadth-first frontier on a 40 by 22 grid stays far
|
|
714
|
+
below 256 cells (the whole open set is 404 and the frontier is one or
|
|
715
|
+
two rings of it), so no overflow test is needed. Walls are never queued
|
|
716
|
+
because `solid` is tested before `work`; walls stay 255 in the map, and
|
|
717
|
+
a chaser only moves to a strictly lower value, so it can never pick a
|
|
718
|
+
wall or dither between equal cells. The tie order up, left, down, right
|
|
719
|
+
is fixed, so two runs make the same picture.
|
|
720
|
+
|
|
721
|
+
Distances are drawn as the flood pops each cell, one character and one
|
|
722
|
+
colour byte per cell, spread over the same frames as the flood; the
|
|
723
|
+
field is never redrawn whole.
|