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,874 @@
|
|
|
1
|
+
---
|
|
2
|
+
recipe: falling-blocks
|
|
3
|
+
toolchain: oscar64
|
|
4
|
+
output_format: PRG
|
|
5
|
+
region: both
|
|
6
|
+
techniques: [falling_block_rules, joystick_edge_detect, joystick_autorepeat, lfsr_random, text_mode_overlay_render, frame_sync_loop, pal_ntsc_detection]
|
|
7
|
+
file_formats: [PRG]
|
|
8
|
+
uses_registers: [D011, D012, D020, D021, DC00, DC04, DC05, DC0E]
|
|
9
|
+
uses_kernal: []
|
|
10
|
+
scaffolds: [action_puzzle]
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
<!-- doc-type: recipe -->
|
|
14
|
+
|
|
15
|
+
# Oscar64 Falling Blocks: a playable game with its rules checked against a model
|
|
16
|
+
|
|
17
|
+
## Synopsis
|
|
18
|
+
|
|
19
|
+
A falling-block game in character mode, written in C: seven pieces,
|
|
20
|
+
clockwise rotation with a three-try kick, gravity and delayed auto-shift
|
|
21
|
+
from the NES Tetris tables for the region the program finds, soft drop,
|
|
22
|
+
lock on landing, line clear with collapse, scoring by lines at once, a
|
|
23
|
+
level every 10 lines, a 7-bag randomiser on a 16-bit LFSR, and game over
|
|
24
|
+
when a piece cannot spawn. The rules are `falling_block_rules` in
|
|
25
|
+
`techniques/logic.md`. The default build (`AUTOPILOT=1`) starts from a
|
|
26
|
+
fixed garbage board and plays five scripted pieces through the same
|
|
27
|
+
input path a joystick uses: a single, a double, a triple, a four-line
|
|
28
|
+
clear that takes the level to 1, DAS moves to both walls, and a J that
|
|
29
|
+
kicks one cell left when rotated against the right wall. It then checks
|
|
30
|
+
the board, score, lines, level, clear counts, kick count, ten bags and a
|
|
31
|
+
blocked spawn against values from the Python model below, checks every
|
|
32
|
+
well cell on screen against the board, runs a probe that moves a piece
|
|
33
|
+
on the frame it locks, prints PASS or FAIL, and prints the cycles of its
|
|
34
|
+
dearest frames and of a worst-frame subject, rules and render timed
|
|
35
|
+
apart. `-dAUTOPILOT=0` builds the game for a player: joystick in port
|
|
36
|
+
2, fire rotates, down soft-drops, fire starts and restarts. Use it as
|
|
37
|
+
the starting point for any Tetris-like game; the autopilot pattern is
|
|
38
|
+
`headless-verify.md`.
|
|
39
|
+
|
|
40
|
+
## Source
|
|
41
|
+
|
|
42
|
+
```c
|
|
43
|
+
// falling-blocks.c
|
|
44
|
+
// A falling-block game in character mode: seven pieces, a clockwise
|
|
45
|
+
// rotation with a three-try kick, gravity from a frames-per-row table
|
|
46
|
+
// chosen by region, delayed auto-shift, soft drop, lock on landing, line
|
|
47
|
+
// clear and collapse, scoring by lines at once, a level every 10 lines,
|
|
48
|
+
// and a 7-bag randomiser on a 16-bit LFSR.
|
|
49
|
+
// AUTOPILOT=1 (default) starts from a fixed garbage board, plays five
|
|
50
|
+
// scripted pieces through the same input path a joystick uses, and
|
|
51
|
+
// checks the board, score, lines, level, clears, kick, bag and spawn
|
|
52
|
+
// test against a Python model, and the screen against the board.
|
|
53
|
+
// AUTOPILOT=0 is the game: joystick port 2, fire rotates, down
|
|
54
|
+
// soft-drops, fire starts and restarts.
|
|
55
|
+
// Every game frame is timed with CIA1 timer A (KERNAL IRQ off).
|
|
56
|
+
#include <c64/vic.h>
|
|
57
|
+
#include <c64/cia.h>
|
|
58
|
+
|
|
59
|
+
#ifndef AUTOPILOT
|
|
60
|
+
#define AUTOPILOT 1
|
|
61
|
+
#endif
|
|
62
|
+
|
|
63
|
+
#define W 10
|
|
64
|
+
#define H 20
|
|
65
|
+
#define BX 15 // board's left column on screen
|
|
66
|
+
#define BY 2 // board's top row on screen
|
|
67
|
+
#define SCR ((char *)0x0400)
|
|
68
|
+
#define CRAM ((char *)0xd800)
|
|
69
|
+
#define RESULT (*(volatile char *)0x02ff)
|
|
70
|
+
|
|
71
|
+
#define J_DOWN 0x02
|
|
72
|
+
#define J_LEFT 0x04
|
|
73
|
+
#define J_RIGHT 0x08
|
|
74
|
+
#define J_FIRE 0x10
|
|
75
|
+
|
|
76
|
+
// --- rules data ---------------------------------------------------------
|
|
77
|
+
// Cells of each piece in a 4x4 box, clockwise rotations 0-3.
|
|
78
|
+
// Order I O T S Z J L; I, S, Z repeat their two states, O its one.
|
|
79
|
+
static const char cx[7][4][4] = {
|
|
80
|
+
{{0,1,2,3},{2,2,2,2},{0,1,2,3},{2,2,2,2}},
|
|
81
|
+
{{1,2,1,2},{1,2,1,2},{1,2,1,2},{1,2,1,2}},
|
|
82
|
+
{{0,1,2,1},{1,0,1,1},{1,0,1,2},{1,1,2,1}},
|
|
83
|
+
{{1,2,0,1},{1,1,2,2},{1,2,0,1},{1,1,2,2}},
|
|
84
|
+
{{0,1,1,2},{2,1,2,1},{0,1,1,2},{2,1,2,1}},
|
|
85
|
+
{{0,1,2,2},{1,1,0,1},{0,0,1,2},{1,2,1,1}},
|
|
86
|
+
{{0,1,2,0},{0,1,1,1},{2,0,1,2},{1,1,1,2}}
|
|
87
|
+
};
|
|
88
|
+
static const char cy[7][4][4] = {
|
|
89
|
+
{{1,1,1,1},{0,1,2,3},{1,1,1,1},{0,1,2,3}},
|
|
90
|
+
{{0,0,1,1},{0,0,1,1},{0,0,1,1},{0,0,1,1}},
|
|
91
|
+
{{1,1,1,2},{0,1,1,2},{0,1,1,1},{0,1,1,2}},
|
|
92
|
+
{{1,1,2,2},{0,1,1,2},{1,1,2,2},{0,1,1,2}},
|
|
93
|
+
{{1,1,2,2},{0,1,1,2},{1,1,2,2},{0,1,1,2}},
|
|
94
|
+
{{1,1,1,2},{0,1,2,2},{0,1,1,1},{0,0,1,2}},
|
|
95
|
+
{{1,1,1,2},{0,0,1,2},{0,1,1,1},{0,1,2,2}}
|
|
96
|
+
};
|
|
97
|
+
static const signed char kick[3] = { 0, 1, -1 };
|
|
98
|
+
static const unsigned points[4] = { 40, 100, 300, 1200 };
|
|
99
|
+
// NES Tetris frames per row by level, 0-29 (tetris.wiki); 29+ holds.
|
|
100
|
+
static const char grav_ntsc[30] = { 48,43,38,33,28,23,18,13,8,6, 5,5,5,4,4,4,3,3,3,
|
|
101
|
+
2,2,2,2,2,2,2,2,2,2, 1 };
|
|
102
|
+
static const char grav_pal[30] = { 36,32,29,25,22,18,15,11,7,5, 4,4,4,3,3,3,2,2,2,
|
|
103
|
+
1,1,1,1,1,1,1,1,1,1, 1 };
|
|
104
|
+
static const char colours[9] = { 0, 3, 7, 4, 5, 2, 14, 8, 11 };
|
|
105
|
+
|
|
106
|
+
// --- state --------------------------------------------------------------
|
|
107
|
+
static char board[H * W]; // 0 empty, 1-7 piece, 8 garbage
|
|
108
|
+
static char rowfill[H]; // filled cells per row
|
|
109
|
+
static char rowoff[H]; // y * 10
|
|
110
|
+
static unsigned scroff[H]; // screen offset of board row y
|
|
111
|
+
static char piece, rot, nextp;
|
|
112
|
+
static signed char px, py, ox, oy;
|
|
113
|
+
static char orot;
|
|
114
|
+
static char fall, das_l, das_r, prev_joy = 0xff;
|
|
115
|
+
static char level, lines, next_at, pal;
|
|
116
|
+
static const char *grav;
|
|
117
|
+
static char das_delay, das_rate;
|
|
118
|
+
static unsigned long score;
|
|
119
|
+
static char clears[4], kicks, dirty;
|
|
120
|
+
static char ev_lines; // lines cleared this frame, 0 if none
|
|
121
|
+
static char locked; // a piece locked this frame
|
|
122
|
+
static char lk_p, lk_r; // where it locked
|
|
123
|
+
static signed char lk_x, lk_y;
|
|
124
|
+
static char top; // highest row holding a cell, H if none
|
|
125
|
+
static char redraw_a, redraw_b; // board rows to redraw when dirty
|
|
126
|
+
|
|
127
|
+
// --- 7-bag on a 16-bit Galois LFSR, taps $B400 ------------------------
|
|
128
|
+
static unsigned lfsr = 0xace1;
|
|
129
|
+
static char bag[7], bag_n;
|
|
130
|
+
|
|
131
|
+
static unsigned rnd(void)
|
|
132
|
+
{
|
|
133
|
+
char lsb = lfsr & 1;
|
|
134
|
+
lfsr >>= 1;
|
|
135
|
+
if (lsb) lfsr ^= 0xb400;
|
|
136
|
+
return lfsr;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
static char bag_next(void)
|
|
140
|
+
{
|
|
141
|
+
if (bag_n == 0) {
|
|
142
|
+
for (char i = 0; i < 7; i++) bag[i] = i;
|
|
143
|
+
for (char i = 6; i > 0; i--) { // Fisher-Yates
|
|
144
|
+
char j = rnd() % (i + 1);
|
|
145
|
+
char t = bag[i]; bag[i] = bag[j]; bag[j] = t;
|
|
146
|
+
}
|
|
147
|
+
bag_n = 7;
|
|
148
|
+
}
|
|
149
|
+
return bag[7 - bag_n--];
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
static void draw_piece(char p, char r, signed char x, signed char y, char v);
|
|
153
|
+
|
|
154
|
+
// --- the rules ----------------------------------------------------------
|
|
155
|
+
static char fits(char p, char r, signed char x, signed char y)
|
|
156
|
+
{
|
|
157
|
+
const char *xs = cx[p][r], *ys = cy[p][r];
|
|
158
|
+
for (char i = 0; i < 4; i++) {
|
|
159
|
+
char bx = (char)(x + xs[i]), by = (char)(y + ys[i]);
|
|
160
|
+
if (bx >= W || by >= H) return 0; // unsigned: catches < 0
|
|
161
|
+
if (board[rowoff[by] + bx]) return 0;
|
|
162
|
+
}
|
|
163
|
+
return 1;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
static char spawn(char p)
|
|
167
|
+
{
|
|
168
|
+
piece = p; rot = 0; px = 3; py = 0; fall = 0;
|
|
169
|
+
return fits(piece, rot, px, py);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
static void rotate(void)
|
|
173
|
+
{
|
|
174
|
+
char nr = (rot + 1) & 3;
|
|
175
|
+
for (char k = 0; k < 3; k++)
|
|
176
|
+
if (fits(piece, nr, px + kick[k], py)) {
|
|
177
|
+
rot = nr; px += kick[k];
|
|
178
|
+
if (k) kicks++;
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
static void clear_lines(void)
|
|
184
|
+
{
|
|
185
|
+
char n = 0;
|
|
186
|
+
signed char low = -1;
|
|
187
|
+
for (char i = 0; i < 4; i++) { // only the rows the piece touched
|
|
188
|
+
char y = py + cy[piece][rot][i];
|
|
189
|
+
if (rowfill[y] == W) {
|
|
190
|
+
if ((signed char)y > low) low = y;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (low < 0) return;
|
|
194
|
+
signed char dst = low, t = top; // rows above top are empty
|
|
195
|
+
for (signed char src = low; src >= t; src--) { // collapse, lowest full row up
|
|
196
|
+
if (rowfill[src] == W) { n++; continue; }
|
|
197
|
+
if (dst != src) {
|
|
198
|
+
char *d = board + rowoff[dst], *s = board + rowoff[src];
|
|
199
|
+
#pragma unroll(full)
|
|
200
|
+
for (char x = 0; x < W; x++) d[x] = s[x];
|
|
201
|
+
rowfill[dst] = rowfill[src];
|
|
202
|
+
}
|
|
203
|
+
dst--;
|
|
204
|
+
}
|
|
205
|
+
for (; dst >= t; dst--) { // the n rows vacated at the top
|
|
206
|
+
char *d = board + rowoff[dst];
|
|
207
|
+
#pragma unroll(full)
|
|
208
|
+
for (char x = 0; x < W; x++) d[x] = 0;
|
|
209
|
+
rowfill[dst] = 0;
|
|
210
|
+
}
|
|
211
|
+
redraw_a = top; redraw_b = low; // only these rows changed
|
|
212
|
+
top += n;
|
|
213
|
+
clears[n - 1]++;
|
|
214
|
+
lines += n;
|
|
215
|
+
if (lines >= next_at) { level++; next_at += 10; }
|
|
216
|
+
for (char l = 0; l <= level; l++) score += points[n - 1]; // level after the clear, as NES
|
|
217
|
+
ev_lines = n;
|
|
218
|
+
dirty = 1;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
static void lock_piece(void)
|
|
222
|
+
{
|
|
223
|
+
for (char i = 0; i < 4; i++) {
|
|
224
|
+
char y = py + cy[piece][rot][i];
|
|
225
|
+
char x = px + cx[piece][rot][i]; // in a char first: px can be -2
|
|
226
|
+
board[rowoff[y] + x] = piece + 1;
|
|
227
|
+
rowfill[y]++;
|
|
228
|
+
if (y < top) top = y;
|
|
229
|
+
}
|
|
230
|
+
lk_p = piece; lk_r = rot; lk_x = px; lk_y = py; // for render: spawn moves piece
|
|
231
|
+
clear_lines();
|
|
232
|
+
locked = 1;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// DAS: first step on the press, the second DELAY frames later, then every RATE.
|
|
236
|
+
static char das(char *age, char held)
|
|
237
|
+
{
|
|
238
|
+
if (!held) { *age = 0; return 0; }
|
|
239
|
+
char a = *age + 1;
|
|
240
|
+
if (a == das_delay + 1 + das_rate) a = das_delay + 1;
|
|
241
|
+
*age = a;
|
|
242
|
+
return a == 1 || a == das_delay + 1;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// One game frame. joy is active low, as $DC00 reads it.
|
|
246
|
+
static void game_step(char joy)
|
|
247
|
+
{
|
|
248
|
+
char pressed = ~joy;
|
|
249
|
+
ev_lines = 0; locked = 0;
|
|
250
|
+
if ((pressed & J_FIRE) && (prev_joy & J_FIRE)) rotate();
|
|
251
|
+
prev_joy = joy;
|
|
252
|
+
if (das(&das_l, pressed & J_LEFT) && fits(piece, rot, px - 1, py)) px--;
|
|
253
|
+
if (das(&das_r, pressed & J_RIGHT) && fits(piece, rot, px + 1, py)) px++;
|
|
254
|
+
char lim = grav[level < 29 ? level : 29];
|
|
255
|
+
if ((pressed & J_DOWN) && lim > 2) lim = 2; // soft drop, 1/2 G
|
|
256
|
+
if (++fall >= lim) {
|
|
257
|
+
fall = 0;
|
|
258
|
+
if (fits(piece, rot, px, py + 1)) py++;
|
|
259
|
+
else lock_piece(); // no lock delay
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// --- drawing ------------------------------------------------------------
|
|
264
|
+
static void cell(char x, char y, char v)
|
|
265
|
+
{
|
|
266
|
+
unsigned o = scroff[y] + x;
|
|
267
|
+
SCR[o] = v ? 160 : 32;
|
|
268
|
+
CRAM[o] = colours[v];
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
static void draw_piece(char p, char r, signed char x, signed char y, char v)
|
|
272
|
+
{
|
|
273
|
+
for (char i = 0; i < 4; i++)
|
|
274
|
+
cell(x + cx[p][r][i], y + cy[p][r][i], v);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
static const char glyph[9] = { 32, 160, 160, 160, 160, 160, 160, 160, 160 };
|
|
278
|
+
|
|
279
|
+
static void redraw_rows(char a, char b)
|
|
280
|
+
{
|
|
281
|
+
for (char y = a; y <= b; y++) {
|
|
282
|
+
char *s = SCR + scroff[y], *c = CRAM + scroff[y];
|
|
283
|
+
const char *bp = board + rowoff[y];
|
|
284
|
+
#pragma unroll(full)
|
|
285
|
+
for (char x = 0; x < W; x++) {
|
|
286
|
+
char v = bp[x];
|
|
287
|
+
s[x] = glyph[v];
|
|
288
|
+
c[x] = colours[v];
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// Erase the piece where it was drawn and draw it where it is. On a lock
|
|
294
|
+
// frame that is the locked piece, which may have moved or rotated in the
|
|
295
|
+
// same frame; then redraw the rows a clear changed, then the new piece.
|
|
296
|
+
static void render(void)
|
|
297
|
+
{
|
|
298
|
+
if (locked) {
|
|
299
|
+
draw_piece(lk_p, orot, ox, oy, 0);
|
|
300
|
+
draw_piece(lk_p, lk_r, lk_x, lk_y, lk_p + 1);
|
|
301
|
+
} else draw_piece(piece, orot, ox, oy, 0);
|
|
302
|
+
if (dirty) { redraw_rows(redraw_a, redraw_b); dirty = 0; }
|
|
303
|
+
draw_piece(piece, rot, px, py, piece + 1);
|
|
304
|
+
ox = px; oy = py; orot = rot;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// --- text, timing, frame --------------------------------------------------
|
|
308
|
+
static void put_text(char col, char row, const char *s)
|
|
309
|
+
{
|
|
310
|
+
char *d = SCR + 40 * row + col;
|
|
311
|
+
char *c = CRAM + 40 * row + col;
|
|
312
|
+
while (*s) {
|
|
313
|
+
char ch = *s++;
|
|
314
|
+
*d++ = (ch >= 'A' && ch <= 'Z') ? ch - 64 : ch;
|
|
315
|
+
*c++ = 1;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
static void put_num(char col, char row, unsigned long v, char digits)
|
|
320
|
+
{
|
|
321
|
+
char *d = SCR + 40 * row + col + digits;
|
|
322
|
+
char *c = CRAM + 40 * row + col;
|
|
323
|
+
for (char i = 0; i < digits; i++) { *--d = '0' + (char)(v % 10); v /= 10; c[i] = 1; }
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
static void put_hex(char col, char row, unsigned v)
|
|
327
|
+
{
|
|
328
|
+
static const char hx[] = "0123456789ABCDEF";
|
|
329
|
+
char s[5];
|
|
330
|
+
for (char i = 0; i < 4; i++) { s[3 - i] = hx[v & 15]; v >>= 4; }
|
|
331
|
+
s[4] = 0;
|
|
332
|
+
put_text(col, row, s);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
static void t_start(void) { cia1.cra = 0x00; cia1.ta = 0xffff; cia1.cra = 0x11; }
|
|
336
|
+
static unsigned t_stop(void) { cia1.cra = 0x00; return 0xffff - cia1.ta; }
|
|
337
|
+
|
|
338
|
+
static void wait_frame(void)
|
|
339
|
+
{
|
|
340
|
+
while (vic.raster == 250) ;
|
|
341
|
+
while (vic.raster != 250) ;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
static char detect_pal(void) // does raster line 280 exist?
|
|
345
|
+
{
|
|
346
|
+
for (unsigned n = 0; n < 20000; n++)
|
|
347
|
+
if ((vic.ctrl1 & 0x80) && vic.raster == 280 - 256) return 1;
|
|
348
|
+
return 0;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
static void hud(void)
|
|
352
|
+
{
|
|
353
|
+
put_text(27, 3, "SCORE"); put_num(27, 4, score, 6);
|
|
354
|
+
put_text(27, 6, "LINES"); put_num(27, 7, lines, 3);
|
|
355
|
+
put_text(27, 9, "LEVEL"); put_num(27, 10, level, 2);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
static void setup_screen(void)
|
|
359
|
+
{
|
|
360
|
+
vic.color_border = 12; vic.color_back = 0;
|
|
361
|
+
for (unsigned i = 0; i < 1000; i++) { SCR[i] = 32; CRAM[i] = 1; }
|
|
362
|
+
for (char y = 0; y < H; y++) {
|
|
363
|
+
rowoff[y] = y * W;
|
|
364
|
+
scroff[y] = (BY + y) * 40 + BX;
|
|
365
|
+
SCR[scroff[y] - 1] = 160; CRAM[scroff[y] - 1] = 12; // walls
|
|
366
|
+
SCR[scroff[y] + W] = 160; CRAM[scroff[y] + W] = 12;
|
|
367
|
+
}
|
|
368
|
+
for (char x = 0; x < W + 2; x++) {
|
|
369
|
+
SCR[(BY + H) * 40 + BX - 1 + x] = 160; CRAM[(BY + H) * 40 + BX - 1 + x] = 12;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
static void new_game(void)
|
|
374
|
+
{
|
|
375
|
+
for (char i = 0; i < H * W; i++) board[i] = 0;
|
|
376
|
+
for (char y = 0; y < H; y++) rowfill[y] = 0;
|
|
377
|
+
score = 0; lines = 0; level = 0; next_at = 10; kicks = 0;
|
|
378
|
+
for (char i = 0; i < 4; i++) clears[i] = 0;
|
|
379
|
+
grav = pal ? grav_pal : grav_ntsc;
|
|
380
|
+
das_delay = pal ? 12 : 16; // NES PAL / NTSC (tetris.wiki)
|
|
381
|
+
das_rate = pal ? 4 : 6;
|
|
382
|
+
das_l = das_r = 0; bag_n = 0; dirty = 0; top = H;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// --- autopilot: a planner that presses the same bits a player would ------
|
|
386
|
+
#if AUTOPILOT
|
|
387
|
+
struct Plan { char p, r1; signed char x; char r2; };
|
|
388
|
+
static const struct Plan plan[5] = {
|
|
389
|
+
{ 0, 0, 6, 0 }, // I flat, three right: single
|
|
390
|
+
{ 1, 0, 1, 0 }, // O, two left: double
|
|
391
|
+
{ 0, 1, -2, 1 }, // I upright, five left to the wall: triple
|
|
392
|
+
{ 0, 1, 7, 1 }, // I upright, four right into the well: four lines, level 1
|
|
393
|
+
{ 5, 1, 8, 2 }, // J, five right to the wall, rotate: kicked one left
|
|
394
|
+
};
|
|
395
|
+
static const char *const garbage[11] = { // rows 9-19
|
|
396
|
+
"######....", "##..######", "##..######", ".#########", ".#########",
|
|
397
|
+
".#########", "#########.", "#########.", "#########.", "#########.",
|
|
398
|
+
"#########."
|
|
399
|
+
};
|
|
400
|
+
#define EXPECT_BOARD 0xecb5 // from the Python model on the page
|
|
401
|
+
#define EXPECT_SCORE 2840
|
|
402
|
+
#define EXPECT_BAG 0x808a
|
|
403
|
+
static char ap_n, ap_phase, ap_tog;
|
|
404
|
+
|
|
405
|
+
static char autopilot(void)
|
|
406
|
+
{
|
|
407
|
+
const struct Plan *p = plan + ap_n;
|
|
408
|
+
char out = 0xff;
|
|
409
|
+
if (ap_phase == 0 || ap_phase == 2) {
|
|
410
|
+
char want = ap_phase ? p->r2 : p->r1;
|
|
411
|
+
if (rot != want) { ap_tog ^= 1; if (ap_tog) out &= ~J_FIRE; }
|
|
412
|
+
else { ap_phase++; ap_tog = 0; }
|
|
413
|
+
}
|
|
414
|
+
if (ap_phase == 1) {
|
|
415
|
+
if (px < p->x) out &= ~J_RIGHT;
|
|
416
|
+
else if (px > p->x) out &= ~J_LEFT;
|
|
417
|
+
else ap_phase = 2;
|
|
418
|
+
}
|
|
419
|
+
if (ap_phase == 3) out &= ~J_DOWN;
|
|
420
|
+
return out;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
static void load_garbage(void)
|
|
424
|
+
{
|
|
425
|
+
for (char r = 0; r < 11; r++)
|
|
426
|
+
for (char x = 0; x < W; x++)
|
|
427
|
+
if (garbage[r][x] == '#') { board[rowoff[9 + r] + x] = 8; rowfill[9 + r]++; }
|
|
428
|
+
top = 9;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
static unsigned fold(unsigned c, char v) { return (c ^ v) * 5 + 1; }
|
|
432
|
+
|
|
433
|
+
// Well cells on screen that differ from the board, glyph or colour, with
|
|
434
|
+
// the live piece written into the board for the comparison when live.
|
|
435
|
+
static char screen_bad(char live)
|
|
436
|
+
{
|
|
437
|
+
char bad = 0;
|
|
438
|
+
if (live) for (char i = 0; i < 4; i++) {
|
|
439
|
+
char y = py + cy[piece][rot][i], x = px + cx[piece][rot][i];
|
|
440
|
+
board[rowoff[y] + x] = piece + 1;
|
|
441
|
+
}
|
|
442
|
+
for (char y = 0; y < H; y++) {
|
|
443
|
+
const char *s = SCR + scroff[y], *c = CRAM + scroff[y];
|
|
444
|
+
const char *bp = board + rowoff[y];
|
|
445
|
+
for (char x = 0; x < W; x++) {
|
|
446
|
+
char v = bp[x];
|
|
447
|
+
if (s[x] != glyph[v] || (c[x] & 15) != colours[v]) bad++;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
if (live) for (char i = 0; i < 4; i++) {
|
|
451
|
+
char y = py + cy[piece][rot][i], x = px + cx[piece][rot][i];
|
|
452
|
+
board[rowoff[y] + x] = 0;
|
|
453
|
+
}
|
|
454
|
+
return bad;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// Worst-frame subject: a full-height stack, every row open in column 9,
|
|
458
|
+
// an upright I locking into the bottom four with fire, left and right
|
|
459
|
+
// held, so the three rotation tries and both moves are tested and fail.
|
|
460
|
+
// Lock, four-line clear, collapse of sixteen rows and spawn are timed as
|
|
461
|
+
// the rules; the redraw of all twenty rows is timed apart as the render.
|
|
462
|
+
static unsigned subj_rules, subj_render;
|
|
463
|
+
static char worst_subject(void)
|
|
464
|
+
{
|
|
465
|
+
new_game();
|
|
466
|
+
for (char y = 0; y < H; y++) {
|
|
467
|
+
for (char x = 0; x < W - 1; x++) board[rowoff[y] + x] = 8;
|
|
468
|
+
rowfill[y] = W - 1;
|
|
469
|
+
}
|
|
470
|
+
top = 0;
|
|
471
|
+
piece = 0; rot = 1; px = 7; py = 16; ox = px; oy = py; orot = rot;
|
|
472
|
+
fall = grav[0] - 1; // gravity runs out this frame
|
|
473
|
+
prev_joy = 0xff;
|
|
474
|
+
wait_frame();
|
|
475
|
+
t_start();
|
|
476
|
+
game_step(0xff & ~(J_FIRE | J_LEFT | J_RIGHT)); // all refused, then lock
|
|
477
|
+
spawn(0);
|
|
478
|
+
subj_rules = t_stop();
|
|
479
|
+
t_start();
|
|
480
|
+
render();
|
|
481
|
+
subj_render = t_stop();
|
|
482
|
+
return ev_lines == 4 && top == 4 && screen_bad(1) == 0;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
// Lock-frame move: an upright I in column 8 is held right on the frame
|
|
486
|
+
// gravity locks it, so it moves to column 9 and locks there, completing
|
|
487
|
+
// row 16. Rows 17-19 are below the cleared row and are not redrawn; the
|
|
488
|
+
// cells drawn in column 8 must still be erased.
|
|
489
|
+
static char lock_move_probe(void)
|
|
490
|
+
{
|
|
491
|
+
new_game();
|
|
492
|
+
for (char y = 16; y < H; y++) {
|
|
493
|
+
char n = y == 16 ? 9 : 8;
|
|
494
|
+
for (char x = 0; x < n; x++) board[rowoff[y] + x] = 8;
|
|
495
|
+
rowfill[y] = n;
|
|
496
|
+
}
|
|
497
|
+
top = 16;
|
|
498
|
+
redraw_rows(0, H - 1);
|
|
499
|
+
piece = 0; rot = 1; px = 6; py = 16; ox = px; oy = py; orot = rot;
|
|
500
|
+
locked = 0;
|
|
501
|
+
render(); // drawn in column 8
|
|
502
|
+
fall = grav[0] - 1; prev_joy = 0xff;
|
|
503
|
+
game_step(0xff & ~J_RIGHT); // moves to column 9, then locks
|
|
504
|
+
spawn(0);
|
|
505
|
+
render();
|
|
506
|
+
return locked && ev_lines == 1 && screen_bad(1) == 0;
|
|
507
|
+
}
|
|
508
|
+
#endif
|
|
509
|
+
|
|
510
|
+
int main(void)
|
|
511
|
+
{
|
|
512
|
+
__asm { sei } // KERNAL IRQ off: timer A is ours
|
|
513
|
+
pal = detect_pal();
|
|
514
|
+
setup_screen();
|
|
515
|
+
unsigned worst_lock = 0, worst_move = 0, four = 0;
|
|
516
|
+
|
|
517
|
+
#if AUTOPILOT
|
|
518
|
+
// Randomiser check: ten bags from seed $ACE1, each a permutation.
|
|
519
|
+
unsigned bchk = 0; char bag_ok = 1;
|
|
520
|
+
for (char b = 0; b < 10; b++) {
|
|
521
|
+
char seen = 0;
|
|
522
|
+
for (char i = 0; i < 7; i++) { char v = bag_next(); seen |= 1 << v; bchk = fold(bchk, v); }
|
|
523
|
+
if (seen != 0x7f) bag_ok = 0;
|
|
524
|
+
}
|
|
525
|
+
char subject_ok = worst_subject();
|
|
526
|
+
char probe_ok = lock_move_probe();
|
|
527
|
+
new_game();
|
|
528
|
+
load_garbage();
|
|
529
|
+
spawn(plan[0].p);
|
|
530
|
+
#else
|
|
531
|
+
for (;;) {
|
|
532
|
+
new_game();
|
|
533
|
+
put_text(1, 12, "FIRE TO PLAY");
|
|
534
|
+
for (;;) { // seed from the frames the player took
|
|
535
|
+
wait_frame(); rnd();
|
|
536
|
+
cia1.pra = 0xff;
|
|
537
|
+
if (!(cia1.pra & J_FIRE)) break;
|
|
538
|
+
}
|
|
539
|
+
put_text(1, 12, " ");
|
|
540
|
+
prev_joy = 0; // the start press is not a rotate
|
|
541
|
+
spawn(bag_next()); nextp = bag_next();
|
|
542
|
+
#endif
|
|
543
|
+
redraw_rows(0, H - 1); hud();
|
|
544
|
+
for (;;) {
|
|
545
|
+
wait_frame();
|
|
546
|
+
#if AUTOPILOT
|
|
547
|
+
char joy = autopilot();
|
|
548
|
+
#else
|
|
549
|
+
cia1.pra = 0xff;
|
|
550
|
+
char joy = cia1.pra;
|
|
551
|
+
#endif
|
|
552
|
+
t_start();
|
|
553
|
+
game_step(joy);
|
|
554
|
+
char next_ok = 1;
|
|
555
|
+
if (locked) {
|
|
556
|
+
#if AUTOPILOT
|
|
557
|
+
ap_n++; ap_phase = 0; ap_tog = 0;
|
|
558
|
+
if (ap_n < 5) next_ok = spawn(plan[ap_n].p);
|
|
559
|
+
#else
|
|
560
|
+
next_ok = spawn(nextp); nextp = bag_next();
|
|
561
|
+
#endif
|
|
562
|
+
}
|
|
563
|
+
render();
|
|
564
|
+
unsigned t = t_stop();
|
|
565
|
+
if (locked) { if (t > worst_lock) worst_lock = t; }
|
|
566
|
+
else if (t > worst_move) worst_move = t;
|
|
567
|
+
if (ev_lines == 4) four = t;
|
|
568
|
+
if (locked) hud();
|
|
569
|
+
if (ev_lines) {
|
|
570
|
+
static const char *const names[4] = { "SINGLE", "DOUBLE", "TRIPLE", "FOUR " };
|
|
571
|
+
put_text(1, 3 + ev_lines, names[ev_lines - 1]);
|
|
572
|
+
}
|
|
573
|
+
if (kicks) put_text(1, 9, "KICK");
|
|
574
|
+
if (level) put_text(1, 10, "LEVEL UP");
|
|
575
|
+
#if AUTOPILOT
|
|
576
|
+
if (ap_n == 5) break;
|
|
577
|
+
#endif
|
|
578
|
+
if (!next_ok) break;
|
|
579
|
+
}
|
|
580
|
+
#if AUTOPILOT
|
|
581
|
+
// Spawn test: a cell under the spawn box refuses the next piece.
|
|
582
|
+
board[rowoff[1] + 4] = 8;
|
|
583
|
+
char spawn_ok = !spawn(0);
|
|
584
|
+
board[rowoff[1] + 4] = 0;
|
|
585
|
+
unsigned chk = 0;
|
|
586
|
+
for (char i = 0; i < H * W; i++) chk = fold(chk, board[i]);
|
|
587
|
+
char pass = chk == EXPECT_BOARD && score == EXPECT_SCORE && lines == 10
|
|
588
|
+
&& level == 1 && clears[0] == 1 && clears[1] == 1 && clears[2] == 1
|
|
589
|
+
&& clears[3] == 1 && kicks == 1 && bchk == EXPECT_BAG && bag_ok
|
|
590
|
+
&& spawn_ok && subject_ok && probe_ok && screen_bad(0) == 0;
|
|
591
|
+
put_text(1, 13, "BOARD"); put_hex(7, 13, chk);
|
|
592
|
+
put_text(1, 14, "BAG"); put_hex(7, 14, bchk);
|
|
593
|
+
put_text(27, 13, pal ? "PAL" : "NTSC");
|
|
594
|
+
put_text(27, 15, "LOCK MAX"); put_num(27, 16, worst_lock, 5);
|
|
595
|
+
put_text(27, 17, "FOUR"); put_num(27, 18, four, 5);
|
|
596
|
+
put_text(27, 19, "MOVE MAX"); put_num(27, 20, worst_move, 5);
|
|
597
|
+
put_text(27, 21, "RULES"); put_num(27, 22, subj_rules, 5);
|
|
598
|
+
put_text(27, 23, "RENDER"); put_num(27, 24, subj_render, 5);
|
|
599
|
+
put_text(1, 16, pass ? "PASS" : "FAIL");
|
|
600
|
+
RESULT = pass ? 1 : 2;
|
|
601
|
+
vic.color_border = pass ? 5 : 2;
|
|
602
|
+
for (;;) ;
|
|
603
|
+
#else
|
|
604
|
+
put_text(1, 12, "GAME OVER");
|
|
605
|
+
for (char f = 0; f < 100; f++) wait_frame();
|
|
606
|
+
put_text(1, 12, " ");
|
|
607
|
+
for (char i = 1; i < 11; i++) put_text(1, i, " ");
|
|
608
|
+
}
|
|
609
|
+
#endif
|
|
610
|
+
return 0;
|
|
611
|
+
}
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
## Build
|
|
615
|
+
|
|
616
|
+
```bash
|
|
617
|
+
oscar64 -tm=c64 -O2 -n -o=falling-blocks.prg falling-blocks.c # 5,348 bytes, autopilot
|
|
618
|
+
oscar64 -tm=c64 -O2 -dAUTOPILOT=0 -o=falling-blocks-play.prg falling-blocks.c # 3,697 bytes, the game
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
The expected values in the listing come from this model of the same
|
|
622
|
+
rules at the level of placements (rotate, move, rotate, drop). The
|
|
623
|
+
autopilot aims at a rotation and a column, so the result does not
|
|
624
|
+
depend on how many frames gravity or DAS take, and the same values hold
|
|
625
|
+
on PAL and NTSC.
|
|
626
|
+
|
|
627
|
+
```python
|
|
628
|
+
W, H = 10, 20
|
|
629
|
+
# Cells of each piece in a 4x4 box, (x, y), per rotation 0-3, clockwise.
|
|
630
|
+
# Order I O T S Z J L; I, S, Z repeat their two states, O its one.
|
|
631
|
+
P = {
|
|
632
|
+
0: [[(0,1),(1,1),(2,1),(3,1)], [(2,0),(2,1),(2,2),(2,3)]] * 2,
|
|
633
|
+
1: [[(1,0),(2,0),(1,1),(2,1)]] * 4,
|
|
634
|
+
2: [[(0,1),(1,1),(2,1),(1,2)], [(1,0),(0,1),(1,1),(1,2)],
|
|
635
|
+
[(1,0),(0,1),(1,1),(2,1)], [(1,0),(1,1),(2,1),(1,2)]],
|
|
636
|
+
3: [[(1,1),(2,1),(0,2),(1,2)], [(1,0),(1,1),(2,1),(2,2)]] * 2,
|
|
637
|
+
4: [[(0,1),(1,1),(1,2),(2,2)], [(2,0),(1,1),(2,1),(1,2)]] * 2,
|
|
638
|
+
5: [[(0,1),(1,1),(2,1),(2,2)], [(1,0),(1,1),(0,2),(1,2)],
|
|
639
|
+
[(0,0),(0,1),(1,1),(2,1)], [(1,0),(2,0),(1,1),(1,2)]],
|
|
640
|
+
6: [[(0,1),(1,1),(2,1),(0,2)], [(0,0),(1,0),(1,1),(1,2)],
|
|
641
|
+
[(2,0),(0,1),(1,1),(2,1)], [(1,0),(1,1),(1,2),(2,2)]],
|
|
642
|
+
}
|
|
643
|
+
KICKS = (0, 1, -1)
|
|
644
|
+
POINTS = (40, 100, 300, 1200)
|
|
645
|
+
GARBAGE = {9: "######....", 10: "##..######", 11: "##..######",
|
|
646
|
+
12: ".#########", 13: ".#########", 14: ".#########",
|
|
647
|
+
15: "#########.", 16: "#########.", 17: "#########.",
|
|
648
|
+
18: "#########.", 19: "#########."}
|
|
649
|
+
PLAN = [(0, 0, 6, 0), (1, 0, 1, 0), (0, 1, -2, 1), (0, 1, 7, 1), (5, 1, 8, 2)]
|
|
650
|
+
|
|
651
|
+
board = [[8 if GARBAGE.get(y, "." * W)[x] == "#" else 0 for x in range(W)]
|
|
652
|
+
for y in range(H)]
|
|
653
|
+
|
|
654
|
+
def fits(p, r, x, y):
|
|
655
|
+
for cx, cy in P[p][r]:
|
|
656
|
+
if not (0 <= x + cx < W and 0 <= y + cy < H) or board[y + cy][x + cx]:
|
|
657
|
+
return False
|
|
658
|
+
return True
|
|
659
|
+
|
|
660
|
+
score = lines = level = kicks = 0
|
|
661
|
+
clears = [0, 0, 0, 0]
|
|
662
|
+
for p, r1, tx, r2 in PLAN:
|
|
663
|
+
r, x, y = 0, 3, 0
|
|
664
|
+
assert fits(p, r, x, y), "game over"
|
|
665
|
+
def rotate_to(want):
|
|
666
|
+
global r, x, kicks
|
|
667
|
+
while r != want:
|
|
668
|
+
nr = (r + 1) & 3
|
|
669
|
+
for k in KICKS:
|
|
670
|
+
if fits(p, nr, x + k, y):
|
|
671
|
+
r, x = nr, x + k
|
|
672
|
+
kicks += k != 0
|
|
673
|
+
break
|
|
674
|
+
else:
|
|
675
|
+
raise SystemExit("rotation refused")
|
|
676
|
+
rotate_to(r1)
|
|
677
|
+
while x != tx:
|
|
678
|
+
step = 1 if tx > x else -1
|
|
679
|
+
assert fits(p, r, x + step, y), "move blocked"
|
|
680
|
+
x += step
|
|
681
|
+
rotate_to(r2)
|
|
682
|
+
while fits(p, r, x, y + 1):
|
|
683
|
+
y += 1
|
|
684
|
+
for cx, cy in P[p][r]:
|
|
685
|
+
board[y + cy][x + cx] = p + 1
|
|
686
|
+
full = [row for row in board if all(row)]
|
|
687
|
+
n = len(full)
|
|
688
|
+
if n:
|
|
689
|
+
board = [[0] * W for _ in range(n)] + [row for row in board if not all(row)]
|
|
690
|
+
lines += n
|
|
691
|
+
clears[n - 1] += 1
|
|
692
|
+
if lines >= (level + 1) * 10:
|
|
693
|
+
level += 1
|
|
694
|
+
score += POINTS[n - 1] * (level + 1) # level after the clear, as NES
|
|
695
|
+
|
|
696
|
+
chk = 0
|
|
697
|
+
for row in board:
|
|
698
|
+
for v in row:
|
|
699
|
+
chk = ((chk ^ v) * 5 + 1) & 0xFFFF
|
|
700
|
+
print("BOARD %04X SCORE %d LINES %d LEVEL %d CLEARS %s KICKS %d"
|
|
701
|
+
% (chk, score, lines, level, clears, kicks))
|
|
702
|
+
for row in board[15:]:
|
|
703
|
+
print("".join(".IOTSZJLG"[v] for v in row))
|
|
704
|
+
|
|
705
|
+
# 7-bag from a 16-bit Galois LFSR, taps $B400, seed $ACE1: ten bags.
|
|
706
|
+
s = 0xACE1
|
|
707
|
+
def rnd():
|
|
708
|
+
global s
|
|
709
|
+
lsb = s & 1
|
|
710
|
+
s >>= 1
|
|
711
|
+
if lsb:
|
|
712
|
+
s ^= 0xB400
|
|
713
|
+
return s
|
|
714
|
+
seq, bchk = [], 0
|
|
715
|
+
for _ in range(10):
|
|
716
|
+
bag = list(range(7))
|
|
717
|
+
for i in range(6, 0, -1):
|
|
718
|
+
j = rnd() % (i + 1)
|
|
719
|
+
bag[i], bag[j] = bag[j], bag[i]
|
|
720
|
+
seq += bag
|
|
721
|
+
for v in seq:
|
|
722
|
+
bchk = ((bchk ^ v) * 5 + 1) & 0xFFFF
|
|
723
|
+
print("BAG %04X" % bchk, "".join("IOTSZJL"[v] for v in seq[:14]))
|
|
724
|
+
```
|
|
725
|
+
|
|
726
|
+
It prints:
|
|
727
|
+
|
|
728
|
+
```text
|
|
729
|
+
BOARD ECB5 SCORE 2840 LINES 10 LEVEL 1 CLEARS [1, 1, 1, 1] KICKS 1
|
|
730
|
+
..........
|
|
731
|
+
..........
|
|
732
|
+
.......J..
|
|
733
|
+
I......JJJ
|
|
734
|
+
GGGGGGGGG.
|
|
735
|
+
BAG 808A ILSJTZOSZTOJLI
|
|
736
|
+
```
|
|
737
|
+
|
|
738
|
+
## Expected output
|
|
739
|
+
|
|
740
|
+
Pinned run: `x64sc -default -warp +sound +autostart-delay-random
|
|
741
|
+
-autostartprgmode 1 -limitcycles 12500000 [-model ntsc] -exitscreenshot
|
|
742
|
+
out.png -autostart falling-blocks.prg`. Screenshots
|
|
743
|
+
`screenshots/falling-blocks.png` (PAL) and
|
|
744
|
+
`screenshots/falling-blocks-ntsc.png` (NTSC). The exit screenshot is
|
|
745
|
+
already the final one at 8,250,000 cycles on PAL and 8,750,000 on NTSC,
|
|
746
|
+
and differs at 8,000,000 and 8,500,000; after that the program holds the
|
|
747
|
+
result screen.
|
|
748
|
+
|
|
749
|
+
Border green (PAL RGB 98, 213, 50; NTSC 114, 189, 103), background
|
|
750
|
+
black. Screen rows 2-24 of the PAL shot, decoded cell by cell against
|
|
751
|
+
the character ROM (`#` is a reverse-space cell: walls, garbage and
|
|
752
|
+
pieces):
|
|
753
|
+
|
|
754
|
+
```text
|
|
755
|
+
# #
|
|
756
|
+
# # SCORE
|
|
757
|
+
SINGLE # # 002840
|
|
758
|
+
DOUBLE # #
|
|
759
|
+
TRIPLE # # LINES
|
|
760
|
+
FOUR # # 010
|
|
761
|
+
# #
|
|
762
|
+
KICK # # LEVEL
|
|
763
|
+
LEVEL UP # # 01
|
|
764
|
+
# #
|
|
765
|
+
# #
|
|
766
|
+
BOARD ECB5 # # PAL
|
|
767
|
+
BAG 808A # #
|
|
768
|
+
# # LOCK MAX
|
|
769
|
+
PASS # # 06276
|
|
770
|
+
# # FOUR
|
|
771
|
+
# # 06276
|
|
772
|
+
# # # MOVE MAX
|
|
773
|
+
## #### 02113
|
|
774
|
+
########## # RULES
|
|
775
|
+
############ 05717
|
|
776
|
+
RENDER
|
|
777
|
+
09311
|
|
778
|
+
```
|
|
779
|
+
|
|
780
|
+
On NTSC the same, with `NTSC` on row 13 and 06491, 06491, 02113, 05888
|
|
781
|
+
and 09394 in the five figures.
|
|
782
|
+
|
|
783
|
+
The well is screen columns 15-24, rows 2-21, with medium grey (colour
|
|
784
|
+
12) walls in columns 14 and 25 and a floor on row 22. All 200 board
|
|
785
|
+
cells were measured with PIL on both shots against the model's board,
|
|
786
|
+
each 8x8 cell required to be one colour: empty cells black, row 19
|
|
787
|
+
columns 0-8 dark grey (colour 11, garbage) with column 9 black, row 18
|
|
788
|
+
column 0 cyan (colour 3, the I left by the triple), row 18 columns 7-9
|
|
789
|
+
and row 17 column 7 light blue (colour 14, the J). No cell differed on
|
|
790
|
+
either model. Each model was run twice and gave byte-identical PNGs.
|
|
791
|
+
|
|
792
|
+
## Why this works
|
|
793
|
+
|
|
794
|
+
`game_step` is the whole rule set and takes one joystick byte, active
|
|
795
|
+
low as `$DC00` reads it. The autopilot builds that byte from a plan of
|
|
796
|
+
(piece, first rotation, column, second rotation): it taps fire every
|
|
797
|
+
other frame until the rotation matches, holds left or right until the
|
|
798
|
+
column matches, taps fire again, then holds down until the piece locks.
|
|
799
|
+
Holding a direction is what drives `das`, so the moves across the board
|
|
800
|
+
exercise the delay and repeat exactly as a held stick would. The J is
|
|
801
|
+
moved to the right wall in its upright state and rotated there; its flat
|
|
802
|
+
state does not fit in place or one cell right, so the kick table's third
|
|
803
|
+
entry moves it one left, and the program counts that kick.
|
|
804
|
+
|
|
805
|
+
The board rows start at 9 with garbage built so that each piece clears
|
|
806
|
+
the rows above the next well first: the flat I completes row 9, the O
|
|
807
|
+
rows 10-11, the upright I at the left wall rows 12-14, and the upright I
|
|
808
|
+
in column 9 rows 16-19, with row 15 dropping into row 19 afterwards. The
|
|
809
|
+
four clears total 10 lines, so the level goes to 1 on the four-line
|
|
810
|
+
clear. As on the NES, a clear is scored at the level after it:
|
|
811
|
+
40 + 100 + 300 at level 0 and 1200 x 2 at level 1, 2840.
|
|
812
|
+
|
|
813
|
+
Every game frame is timed with CIA1 timer A from `t_start` to `t_stop`,
|
|
814
|
+
the method of `print-number.md`, with the KERNAL IRQ off (`sei`) so the
|
|
815
|
+
jiffy handler neither runs inside the timed code nor reloads the timer.
|
|
816
|
+
The screen stays on and each frame starts at raster line 250, so badline
|
|
817
|
+
stalls are in the figures. HUD printing runs after `t_stop` and is not
|
|
818
|
+
counted. `worst_subject` builds a stack the game cannot reach, twenty
|
|
819
|
+
rows high with column 9 open, and times the frame in which an upright I
|
|
820
|
+
locks into the bottom four with fire, left and right all held: three
|
|
821
|
+
rotation tries and both moves are tested and refused, then the lock, a
|
|
822
|
+
four-line clear, sixteen rows collapsed and a spawn. Holding left and
|
|
823
|
+
right together cannot happen on a real stick, so this is an upper bound.
|
|
824
|
+
That rules part took 5,717 cycles on PAL and 5,888 on NTSC. The render
|
|
825
|
+
of the same frame, timed apart, erases and redraws the locked piece,
|
|
826
|
+
redraws all twenty rows and draws the new piece: 9,311 on PAL and 9,394
|
|
827
|
+
on NTSC. That is `text_mode_overlay_render`'s work, not the rules'. The
|
|
828
|
+
scripted game's own four-line clear, rules and render together with six
|
|
829
|
+
rows to redraw, took 6,276 on PAL and 6,491 on NTSC and was its dearest
|
|
830
|
+
frame. The whole subject frame, 15,028 cycles on PAL and 15,282 on NTSC,
|
|
831
|
+
runs about 240 and 235 raster lines from line 250 (divided by 63 and 65,
|
|
832
|
+
arithmetic), well past the start of the next frame's display, so the
|
|
833
|
+
collapse frame can tear the field once (`full_field_redraw_exceeds_vblank`
|
|
834
|
+
in `pitfalls/text-mode-render.md`). A game that cares redraws only the
|
|
835
|
+
rows that moved over two frames, or builds the next field in a second
|
|
836
|
+
screen (`screen_double_buffer_d018`).
|
|
837
|
+
|
|
838
|
+
`render` erases the piece where it was last drawn and draws it where it
|
|
839
|
+
is on every frame, including the frame it locks. A lock frame can also
|
|
840
|
+
carry a move or a rotation, and a clear redraws only the rows from the
|
|
841
|
+
old stack top down to the lowest cleared row, so rows below that row
|
|
842
|
+
keep whatever the erase left. `lock_piece` records where the piece
|
|
843
|
+
locked (`lk_p`, `lk_r`, `lk_x`, `lk_y`) because the spawn that follows
|
|
844
|
+
overwrites `piece` and `px`. `lock_move_probe` builds that case: an
|
|
845
|
+
upright I drawn in column 8, held right on the frame gravity locks it,
|
|
846
|
+
completing row 16 while its lower three cells sit in rows 17-19. It then
|
|
847
|
+
requires every well cell on screen, glyph and colour, to match the board
|
|
848
|
+
with the new piece on it (`screen_bad`). With the erase skipped on a
|
|
849
|
+
lock that clears lines, the probe fails and the program prints FAIL
|
|
850
|
+
(measured in VICE). The same screen check runs on the worst-frame
|
|
851
|
+
subject and on the final board.
|
|
852
|
+
|
|
853
|
+
`detect_pal` polls for raster line 280, which exists only on PAL, and
|
|
854
|
+
selects the NES PAL gravity and DAS tables there. The rules then run at
|
|
855
|
+
the speed the NES tables intend on both regions; the scripted result is
|
|
856
|
+
the same on both because the autopilot aims at positions, not frames.
|
|
857
|
+
|
|
858
|
+
The lock writes `char x = px + cx[...]` before indexing the board.
|
|
859
|
+
Summing `rowoff[y] + px + cx[...]` inline instead loses a cell locked at
|
|
860
|
+
column 0 with `px` = -2 (board fold `04AC` instead of `ECB5`, the
|
|
861
|
+
model's board less that cell). Oscar64 1.32.271 at `-O2` hoists
|
|
862
|
+
`board + px` out of the loop as a 16-bit pointer and zero-extends the
|
|
863
|
+
signed `px` (`CLC`, `LDA #<board`, `ADC px`, `LDA #>board`, `ADC #$00`),
|
|
864
|
+
so `px` = -2 (`$FE`) lands 256 bytes above the cell. A 20-line test
|
|
865
|
+
reproduces it (border red, none of the four cells in the board);
|
|
866
|
+
there is no diagnostic. Computing the column in a `char` first, as the
|
|
867
|
+
listing does, compiles correctly.
|
|
868
|
+
|
|
869
|
+
The 7-bag check deals ten bags from seed `$ACE1`, requires each to hold
|
|
870
|
+
all seven pieces, and folds the 70 pieces into `808A`, the model's
|
|
871
|
+
value. The spawn check puts one cell under the spawn box, requires
|
|
872
|
+
`spawn` to refuse, and removes it. In the joystick build the bag is
|
|
873
|
+
seeded by stepping the LFSR once per frame until fire is pressed, the
|
|
874
|
+
player-input seed of `lfsr_random`.
|