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,617 @@
|
|
|
1
|
+
---
|
|
2
|
+
recipe: text-overlay-playfield
|
|
3
|
+
toolchain: oscar64
|
|
4
|
+
output_format: PRG
|
|
5
|
+
region: both
|
|
6
|
+
techniques: [text_mode_overlay_render]
|
|
7
|
+
file_formats: [PRG]
|
|
8
|
+
uses_registers: [D011, D012, D020, D021]
|
|
9
|
+
uses_kernal: []
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<!-- doc-type: recipe -->
|
|
13
|
+
|
|
14
|
+
# Oscar64 Text-Mode Playfield with a Moving-Piece Overlay
|
|
15
|
+
|
|
16
|
+
## Synopsis
|
|
17
|
+
|
|
18
|
+
A 10×20 playfield in text mode, drawn two characters wide per cell, with
|
|
19
|
+
one falling tetromino on top of it. The piece is never in the playfield
|
|
20
|
+
array: each frame the program repaints the piece's previous cells from
|
|
21
|
+
`field[][]` and then draws its current cells, eight cells in all. The whole
|
|
22
|
+
field is repainted only at start and when a piece locks. The program measures
|
|
23
|
+
both costs itself and prints them on the bottom row in raster lines, next to
|
|
24
|
+
a tick counter, so the budget argument in `text_mode_overlay_render` is on
|
|
25
|
+
the screen rather than in a comment; the KERNAL's 60 Hz interrupt is
|
|
26
|
+
switched off first, so that the two numbers are the paint and the overlay
|
|
27
|
+
and nothing else. There is no input and no random number generator: the
|
|
28
|
+
piece sequence is fixed, so the screen at any tick is predictable, which is
|
|
29
|
+
how the page was verified. Use it as the render shell for a Tetris-,
|
|
30
|
+
Sokoban- or board-game-shaped project; the game logic is a stub (spawn,
|
|
31
|
+
fall, lock, game over) and is meant to be replaced.
|
|
32
|
+
|
|
33
|
+
## Source
|
|
34
|
+
|
|
35
|
+
```c
|
|
36
|
+
// text-overlay-playfield.c
|
|
37
|
+
//
|
|
38
|
+
// A 10x20 text-mode playfield with one falling tetromino drawn as an
|
|
39
|
+
// overlay. Each frame repaints only the piece's previous cells (from
|
|
40
|
+
// field[][]) and its current cells. The whole field is repainted once at
|
|
41
|
+
// start and once per lock. Both costs are measured in raster lines and
|
|
42
|
+
// shown on the bottom row, next to a tick counter on the top row. The
|
|
43
|
+
// KERNAL's 60 Hz IRQ is switched off first: left running, its service
|
|
44
|
+
// routine lands inside the timed paths and adds four or five raster lines
|
|
45
|
+
// to whichever number it happens to hit.
|
|
46
|
+
//
|
|
47
|
+
// Deterministic: fixed piece sequence, no input, no RNG. The screen at any
|
|
48
|
+
// tick is predictable, which is how the recipe was verified.
|
|
49
|
+
//
|
|
50
|
+
// Build: oscar64 -tm=c64 -O2 -o=text-overlay-playfield.prg text-overlay-playfield.c
|
|
51
|
+
#include <c64/vic.h>
|
|
52
|
+
|
|
53
|
+
#define Screen ((char *)0x0400)
|
|
54
|
+
#define Color ((char *)0xD800)
|
|
55
|
+
#define COLS 40
|
|
56
|
+
|
|
57
|
+
#define FIELD_W 10
|
|
58
|
+
#define FIELD_H 20
|
|
59
|
+
#define FIELD_COL0 10 // screen column of field x = 0; each cell is 2 chars
|
|
60
|
+
#define FIELD_ROW0 2 // screen row of field y = 0
|
|
61
|
+
#define GRAVITY 8 // ticks (frames) per row of fall
|
|
62
|
+
#define LINES_PER_FRAME 312 // PAL 6569; 263 for NTSC 6567R8 (timer display only)
|
|
63
|
+
|
|
64
|
+
#define ST_PLAY 0
|
|
65
|
+
#define ST_OVER 1
|
|
66
|
+
|
|
67
|
+
// Persistent playfield: 0 = empty, otherwise piece type + 1.
|
|
68
|
+
static char field[FIELD_H][FIELD_W];
|
|
69
|
+
|
|
70
|
+
// Seven tetrominoes, one orientation each: four (dx, dy) pairs in a 4x2 box.
|
|
71
|
+
static const char piece_cells[7][8] = {
|
|
72
|
+
{ 0,1, 1,1, 2,1, 3,1 }, // I
|
|
73
|
+
{ 1,0, 2,0, 1,1, 2,1 }, // O
|
|
74
|
+
{ 1,0, 0,1, 1,1, 2,1 }, // T
|
|
75
|
+
{ 2,0, 0,1, 1,1, 2,1 }, // L
|
|
76
|
+
{ 0,0, 0,1, 1,1, 2,1 }, // J
|
|
77
|
+
{ 1,0, 2,0, 0,1, 1,1 }, // S
|
|
78
|
+
{ 0,0, 1,0, 1,1, 2,1 }, // Z
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
// Colour per field value; index 0 is the empty cell (a space, colour unused).
|
|
82
|
+
static const char piece_color[8] = {
|
|
83
|
+
VCOL_BLACK, VCOL_CYAN, VCOL_YELLOW, VCOL_PURPLE,
|
|
84
|
+
VCOL_ORANGE, VCOL_LT_BLUE, VCOL_GREEN, VCOL_RED
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// Fixed spawn sequence (type, x), repeated until a piece cannot spawn.
|
|
88
|
+
#define SEQ_LEN 8
|
|
89
|
+
static const char seq_type[SEQ_LEN] = { 1, 0, 2, 3, 4, 5, 6, 0 };
|
|
90
|
+
static const char seq_x[SEQ_LEN] = { 0, 2, 6, 3, 0, 6, 3, 6 };
|
|
91
|
+
|
|
92
|
+
// The active piece, and where render_piece last drew it.
|
|
93
|
+
static char cur_type, cur_x, cur_y;
|
|
94
|
+
static char prev_type, prev_x, prev_y;
|
|
95
|
+
static bool have_prev;
|
|
96
|
+
static char seq_pos, gravity, state;
|
|
97
|
+
|
|
98
|
+
static char tick_digits[5]; // tick counter, shown on row 0
|
|
99
|
+
static unsigned paint_lines; // raster lines the last render_field took
|
|
100
|
+
|
|
101
|
+
// ----------------------------------------------------------------- timing
|
|
102
|
+
|
|
103
|
+
// Current raster line, 0..LINES_PER_FRAME-1, from $D012 and RST8 in $D011.
|
|
104
|
+
// Re-reads once if RST8 changed between the two reads.
|
|
105
|
+
static unsigned raster_line(void)
|
|
106
|
+
{
|
|
107
|
+
char hi = vic.ctrl1;
|
|
108
|
+
char lo = vic.raster;
|
|
109
|
+
if ((vic.ctrl1 ^ hi) & VIC_CTRL1_RST8) {
|
|
110
|
+
hi = vic.ctrl1;
|
|
111
|
+
lo = vic.raster;
|
|
112
|
+
}
|
|
113
|
+
return (hi & VIC_CTRL1_RST8) ? 256 + lo : lo;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// ---------------------------------------------------------------- drawing
|
|
117
|
+
|
|
118
|
+
// Paint one field cell (two screen columns) from a field value.
|
|
119
|
+
static void paint_cell(char x, char y, char v)
|
|
120
|
+
{
|
|
121
|
+
unsigned o = (unsigned)(FIELD_ROW0 + y) * COLS + FIELD_COL0 + 2 * x;
|
|
122
|
+
char code = v ? 0xA0 : 0x20;
|
|
123
|
+
char col = piece_color[v];
|
|
124
|
+
Screen[o] = code; Screen[o + 1] = code;
|
|
125
|
+
Color[o] = col; Color[o + 1] = col;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Full paint of the persistent field: 200 cells, row pointers. Start and
|
|
129
|
+
// lock only. The raster is sampled once per row so a frame wrap during the
|
|
130
|
+
// paint is counted instead of folding the result back into 0..311.
|
|
131
|
+
static void render_field(void)
|
|
132
|
+
{
|
|
133
|
+
char *s = Screen + FIELD_ROW0 * COLS + FIELD_COL0;
|
|
134
|
+
char *c = Color + FIELD_ROW0 * COLS + FIELD_COL0;
|
|
135
|
+
const char *f = field[0];
|
|
136
|
+
unsigned start = raster_line(), last = start, wraps = 0;
|
|
137
|
+
|
|
138
|
+
for (char y = 0; y < FIELD_H; y++) {
|
|
139
|
+
for (char x = 0; x < 2 * FIELD_W; x += 2) {
|
|
140
|
+
char v = *f++;
|
|
141
|
+
char code = v ? 0xA0 : 0x20;
|
|
142
|
+
char col = piece_color[v];
|
|
143
|
+
s[x] = code; s[x + 1] = code;
|
|
144
|
+
c[x] = col; c[x + 1] = col;
|
|
145
|
+
}
|
|
146
|
+
s += COLS; c += COLS;
|
|
147
|
+
|
|
148
|
+
unsigned now = raster_line();
|
|
149
|
+
if (now < last)
|
|
150
|
+
wraps++;
|
|
151
|
+
last = now;
|
|
152
|
+
}
|
|
153
|
+
paint_lines = last - start + wraps * LINES_PER_FRAME;
|
|
154
|
+
have_prev = false; // nothing left on screen that is not in field[][]
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Per-frame overlay: erase the previous position from field[][], then
|
|
158
|
+
// draw the current one. Eight cells, whatever the field size.
|
|
159
|
+
static void render_piece(void)
|
|
160
|
+
{
|
|
161
|
+
if (have_prev) {
|
|
162
|
+
const char *q = piece_cells[prev_type];
|
|
163
|
+
for (char i = 0; i < 8; i += 2) {
|
|
164
|
+
char x = prev_x + q[i], y = prev_y + q[i + 1];
|
|
165
|
+
paint_cell(x, y, field[y][x]);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
const char *p = piece_cells[cur_type];
|
|
169
|
+
for (char i = 0; i < 8; i += 2)
|
|
170
|
+
paint_cell(cur_x + p[i], cur_y + p[i + 1], cur_type + 1);
|
|
171
|
+
prev_type = cur_type; prev_x = cur_x; prev_y = cur_y;
|
|
172
|
+
have_prev = true;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// White text at (col, row). The S"" prefix makes the literal screen codes;
|
|
176
|
+
// with lowercase s the letters come out as the shifted glyphs instead.
|
|
177
|
+
static void put_text(char col, char row, const char *s)
|
|
178
|
+
{
|
|
179
|
+
unsigned o = (unsigned)row * COLS + col;
|
|
180
|
+
while (*s) {
|
|
181
|
+
Screen[o] = *s++;
|
|
182
|
+
Color[o] = VCOL_WHITE;
|
|
183
|
+
o++;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Grey walls around the field so the empty cells read as a board.
|
|
188
|
+
static void draw_walls(void)
|
|
189
|
+
{
|
|
190
|
+
char c0 = FIELD_COL0 - 1, c1 = FIELD_COL0 + 2 * FIELD_W;
|
|
191
|
+
for (char r = FIELD_ROW0; r <= FIELD_ROW0 + FIELD_H; r++) {
|
|
192
|
+
unsigned o = (unsigned)r * COLS;
|
|
193
|
+
if (r == FIELD_ROW0 + FIELD_H) {
|
|
194
|
+
for (char c = c0; c <= c1; c++) { Screen[o + c] = 0xA0; Color[o + c] = VCOL_MED_GREY; }
|
|
195
|
+
} else {
|
|
196
|
+
Screen[o + c0] = 0xA0; Color[o + c0] = VCOL_MED_GREY;
|
|
197
|
+
Screen[o + c1] = 0xA0; Color[o + c1] = VCOL_MED_GREY;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Advance and show the tick counter (row 0, columns 5..9).
|
|
203
|
+
static void show_tick(void)
|
|
204
|
+
{
|
|
205
|
+
char i = 4;
|
|
206
|
+
while (++tick_digits[i] == 10) {
|
|
207
|
+
tick_digits[i] = 0;
|
|
208
|
+
if (i == 0) break;
|
|
209
|
+
i--;
|
|
210
|
+
}
|
|
211
|
+
for (char d = 0; d < 5; d++)
|
|
212
|
+
Screen[5 + d] = 48 + tick_digits[d];
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Decimal digits of n, right-aligned in `width` cells at screen offset o.
|
|
216
|
+
static void show_number(unsigned o, char width, unsigned n)
|
|
217
|
+
{
|
|
218
|
+
while (width--) {
|
|
219
|
+
Screen[o + width] = 48 + (char)(n % 10);
|
|
220
|
+
n /= 10;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
#define PAINT_DIGITS (24 * COLS + 11) // row 24: "FULL PAINT nnnn LINES"
|
|
225
|
+
#define OVERLAY_DIGITS (24 * COLS + 32) // row 24: "OVERLAY nn LINES"
|
|
226
|
+
|
|
227
|
+
// ------------------------------------------------------------------- game
|
|
228
|
+
|
|
229
|
+
static bool fits(char type, char x, char y)
|
|
230
|
+
{
|
|
231
|
+
const char *p = piece_cells[type];
|
|
232
|
+
for (char i = 0; i < 8; i += 2) {
|
|
233
|
+
char cy = y + p[i + 1];
|
|
234
|
+
if (cy >= FIELD_H || field[cy][x + p[i]])
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
237
|
+
return true;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
static void spawn(void)
|
|
241
|
+
{
|
|
242
|
+
cur_type = seq_type[seq_pos];
|
|
243
|
+
cur_x = seq_x[seq_pos];
|
|
244
|
+
cur_y = 0;
|
|
245
|
+
gravity = GRAVITY;
|
|
246
|
+
if (++seq_pos == SEQ_LEN)
|
|
247
|
+
seq_pos = 0;
|
|
248
|
+
if (!fits(cur_type, cur_x, cur_y)) {
|
|
249
|
+
state = ST_OVER;
|
|
250
|
+
put_text(FIELD_COL0 + 5, FIELD_ROW0 + 1, S"GAME OVER");
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// The piece enters field[][]; that is the one persistent-state change,
|
|
255
|
+
// so it is the one place the full paint runs.
|
|
256
|
+
static void lock_piece(void)
|
|
257
|
+
{
|
|
258
|
+
const char *p = piece_cells[cur_type];
|
|
259
|
+
for (char i = 0; i < 8; i += 2)
|
|
260
|
+
field[cur_y + p[i + 1]][cur_x + p[i]] = cur_type + 1;
|
|
261
|
+
render_field();
|
|
262
|
+
show_number(PAINT_DIGITS, 4, paint_lines);
|
|
263
|
+
spawn();
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
static void tick(void)
|
|
267
|
+
{
|
|
268
|
+
if (--gravity)
|
|
269
|
+
return;
|
|
270
|
+
gravity = GRAVITY;
|
|
271
|
+
if (fits(cur_type, cur_x, cur_y + 1))
|
|
272
|
+
cur_y++;
|
|
273
|
+
else
|
|
274
|
+
lock_piece();
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
int main(void)
|
|
278
|
+
{
|
|
279
|
+
__asm { sei } // KERNAL IRQ off; see "Why this works"
|
|
280
|
+
vic.color_border = VCOL_BLACK;
|
|
281
|
+
vic.color_back = VCOL_BLACK;
|
|
282
|
+
for (unsigned i = 0; i < 1000; i++) {
|
|
283
|
+
Screen[i] = 0x20;
|
|
284
|
+
Color[i] = VCOL_BLACK;
|
|
285
|
+
}
|
|
286
|
+
draw_walls();
|
|
287
|
+
put_text(0, 0, S"TICK 00000");
|
|
288
|
+
put_text(0, 24, S"FULL PAINT ---- LINES");
|
|
289
|
+
put_text(24, 24, S"OVERLAY -- LINES");
|
|
290
|
+
|
|
291
|
+
render_field(); // initial paint of the (empty) field
|
|
292
|
+
show_number(PAINT_DIGITS, 4, paint_lines);
|
|
293
|
+
spawn();
|
|
294
|
+
|
|
295
|
+
for (;;) {
|
|
296
|
+
vic_waitFrame(); // returns when RST8 sets: line 256
|
|
297
|
+
show_tick();
|
|
298
|
+
if (state == ST_PLAY) {
|
|
299
|
+
tick(); // may lock, repaint, spawn, or end the game
|
|
300
|
+
if (state == ST_PLAY) { // gate the overlay on the state AFTER tick()
|
|
301
|
+
unsigned t0 = raster_line();
|
|
302
|
+
render_piece();
|
|
303
|
+
show_number(OVERLAY_DIGITS, 2,
|
|
304
|
+
(raster_line() + LINES_PER_FRAME - t0) % LINES_PER_FRAME);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return 0;
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
## Build
|
|
313
|
+
|
|
314
|
+
```bash
|
|
315
|
+
oscar64 -tm=c64 -O2 -o=text-overlay-playfield.prg text-overlay-playfield.c
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
Oscar64 build 2026-05-19, zero diagnostics; the PRG is 1,769 bytes. `-O2`
|
|
319
|
+
matters for the numbers below: the page's measurements were taken at that
|
|
320
|
+
level and nowhere else.
|
|
321
|
+
|
|
322
|
+
## Expected output
|
|
323
|
+
|
|
324
|
+
Black border and background. A medium-grey wall in the shape of a U: columns
|
|
325
|
+
9 and 30 from screen row 2 to 21, and a floor across columns 9–30 on row 22.
|
|
326
|
+
Inside it the playfield, 20 columns by 20 rows, starts empty. Row 0 reads
|
|
327
|
+
`TICK nnnnn` in white and counts up once per frame. Row 24 reads
|
|
328
|
+
`FULL PAINT 0275 LINES OVERLAY 33 LINES` until the first lock at tick 152,
|
|
329
|
+
`FULL PAINT 0272 LINES` after it, `0273` after the second, third and fourth
|
|
330
|
+
locks, and `0277` when the board is full at the end. The overlay figure is
|
|
331
|
+
`33` on every frame except the first one and the frame of each lock, which
|
|
332
|
+
have no previous position to erase and read `17` (rung 1: a probe build of
|
|
333
|
+
this listing that keeps the minimum, the maximum and a histogram of the
|
|
334
|
+
overlay figure read, over its first 654 frames, 33 in 649 and 17 in 5, no
|
|
335
|
+
other value).
|
|
336
|
+
|
|
337
|
+
Pieces fall one field row every 8 frames and lock when they cannot fall
|
|
338
|
+
further. The sequence is fixed: O (yellow, column 0), I (cyan, column 2),
|
|
339
|
+
T (purple, column 6), L (orange, column 3), J (light blue, column 0),
|
|
340
|
+
S (green, column 6), Z (red, column 3), I (cyan, column 6), then repeats.
|
|
341
|
+
The first lock is at tick 152, the thirtieth at tick 2368; the piece that
|
|
342
|
+
should follow it cannot spawn, `GAME OVER` appears in white across field
|
|
343
|
+
row 1 (screen row 3, columns 15–23) and the overlay stops. The tick counter
|
|
344
|
+
keeps going.
|
|
345
|
+
|
|
346
|
+

|
|
347
|
+
|
|
348
|
+
The picture is the 16,000,000-cycle capture, tick 654. Verified in VICE
|
|
349
|
+
x64sc 3.10 (PAL, the default C64C: 8565, 8580, 8521; an earlier version said
|
|
350
|
+
6569), headless, warp, with `+autostart-delay-random`.
|
|
351
|
+
That switch is not in the usual invocation and it matters here: without it
|
|
352
|
+
three identical runs at `-limitcycles 8000000` read ticks 249, 238 and 240,
|
|
353
|
+
because VICE adds a random delay before the autostart `RUN` by default;
|
|
354
|
+
with it, three runs read 250, 250, 250. Read the counter, never the cycle
|
|
355
|
+
count, to know which frame a capture shows.
|
|
356
|
+
|
|
357
|
+
Measured (rung 1, script over the PNG, not by eye): every one of the 40×25
|
|
358
|
+
cells was decoded by matching its 8×8 block against the glyphs of
|
|
359
|
+
`chargen-901225-01.bin`, with the 16 colours taken from a calibration run of
|
|
360
|
+
the same VICE build (a PRG that shows the 16 colours as reverse spaces), and
|
|
361
|
+
compared with a Python model of this listing run for the number of ticks on
|
|
362
|
+
screen. The cell origin was measured too: text row 0 begins at PNG row 35 and
|
|
363
|
+
column 0 at x 32, so a cell is the block at `(32 + 8·col, 35 + 8·row)`; the
|
|
364
|
+
grey wall's first pixel row is 51 and its first column x 104. The display
|
|
365
|
+
window's 200 lines therefore occupy PNG rows 35–234, which is raster 51–250
|
|
366
|
+
minus 16, not minus 14; the committed `kickassembler/screenshots/raster-bars.png`
|
|
367
|
+
has its window at the same rows. On the 384×247 NTSC capture text row 0
|
|
368
|
+
begins at PNG row 23 (raster 51 minus 28), column 0 at the same x 32.
|
|
369
|
+
|
|
370
|
+
| `-limitcycles` | tick | on screen | locked cells | cells matching the model |
|
|
371
|
+
|---|---|---|---|---|
|
|
372
|
+
| 5,000,000 | 99 | O (yellow) at field row 12, nothing locked yet; row 24 reads `0275` | 0 | 994 of 994 |
|
|
373
|
+
| 8,000,000 | 250 | I (cyan) at field row 12 after one lock (the O) | 4 | 994 of 994 |
|
|
374
|
+
| 16,000,000 | 654 | J (light blue) at field row 10 after four locks — the picture above | 16 | 994 of 994 |
|
|
375
|
+
| 60,000,000 | 2867 | `GAME OVER`, all nine characters intact, 30 locks — `screenshots/text-overlay-playfield-gameover.png` | 120 | 994 of 994 |
|
|
376
|
+
| 8,000,000, `-model ntsc` | 281 | as the 8 M PAL row; row 24 reads `0315` and `81` (see below) — `screenshots/text-overlay-playfield-ntsc.png` | 4 | 994 of 994 |
|
|
377
|
+
|
|
378
|
+
994 is 1,000 cells minus the six digit cells of the two on-screen
|
|
379
|
+
measurements, which are read from the picture rather than modelled. Per
|
|
380
|
+
capture the script asserts that (a) the four piece cells are solid `$A0` in
|
|
381
|
+
the piece's colour, (b) the cells of the piece's previous position hold
|
|
382
|
+
whatever `field[][]` holds there, (c) every locked cell is still on screen,
|
|
383
|
+
(d) nothing outside the field differs from the model, (e) every other field
|
|
384
|
+
cell is empty, and (f) every cell decodes to a character-ROM glyph. All pass
|
|
385
|
+
in all five. A capture that landed mid-frame while the piece moved would
|
|
386
|
+
fail (e) or (f); none did, and the piece had not moved on any captured tick
|
|
387
|
+
anyway (99, 250, 654 and 281 are not multiples of 8). One capture did land
|
|
388
|
+
mid-write: a 16 M NTSC run (tick 745) caught `show_number` between the two
|
|
389
|
+
overlay digits and the decoder refused that cell. It is not in the table,
|
|
390
|
+
and it is the reason the counter, not the cycle count, names a frame.
|
|
391
|
+
(Audit note, 2026-09-22, rung 1: `docs/recipes/runs.json` pins this
|
|
392
|
+
recipe at 16,000,000 cycles for *both* models, so `verify-recipes` renders
|
|
393
|
+
that same tick-745 NTSC frame — `OVERLAY 8?` with the units digit
|
|
394
|
+
half-written — and reports it as differing from the committed NTSC picture,
|
|
395
|
+
which is the 8 M capture at tick 281. The PAL arm matches pixel for pixel
|
|
396
|
+
at 16 M. Until the NTSC pin is 8,000,000 that mismatch is the pin, not the
|
|
397
|
+
listing.)
|
|
398
|
+
|
|
399
|
+
The two numbers on row 24 (rung 1, read from the same captures):
|
|
400
|
+
|
|
401
|
+
- `FULL PAINT 0272 LINES` with 4 cells filled, `0273` with 8 to 16, `0277`
|
|
402
|
+
with 120, and `0275` for the empty field painted from `main` before the
|
|
403
|
+
loop starts. At 63 cycles a line that is 17,100–17,450 cycles for 200
|
|
404
|
+
cells, about 86 cycles a cell; badline stalls inside the paint are counted
|
|
405
|
+
in, since this is wall time. (The spread is consistent with the
|
|
406
|
+
`v ? 0xA0 : 0x20` branch costing a cycle more per filled cell, and with
|
|
407
|
+
the first paint starting wherever `main` had got to rather than at line
|
|
408
|
+
256 and so meeting a different number of badlines; neither was measured
|
|
409
|
+
on its own.) It is nearly five times the 56 lines between the RST8 rise
|
|
410
|
+
at line 256 and the wrap, and 2.5 times the 107 lines before the display
|
|
411
|
+
window resumes at raster 51.
|
|
412
|
+
- `OVERLAY 33 LINES`, 2,079 cycles, for the eight `paint_cell` calls plus
|
|
413
|
+
the two raster reads that bracket them. `render_piece` alone is 1,998
|
|
414
|
+
cycles on CIA 2's timer A in a probe build; the two reads are the rest.
|
|
415
|
+
|
|
416
|
+
**Correction.** The first version of this page had no `sei`, and its row-24
|
|
417
|
+
figures — `FULL PAINT 0277` at 4 and at 16 cells, `0285` at 120,
|
|
418
|
+
`OVERLAY 33` — were the paint plus the KERNAL's interrupt. Oscar64's C64
|
|
419
|
+
start-up leaves the 60 Hz IRQ running (the one `sei` in its `crt.c` is under
|
|
420
|
+
the NES target, and the assembly it generated for that listing contained
|
|
421
|
+
none), and the service routine, four to five raster lines each time, landed
|
|
422
|
+
once or twice inside every paint and inside about one overlay in eight: the
|
|
423
|
+
same histogram probe with the interrupt on read 33 in 569 of 654 frames, 37
|
|
424
|
+
in 12, 17 in 3, and some other value in the remaining 70. The paint figure
|
|
425
|
+
also depended on where the interrupt fell — 277 in runs with
|
|
426
|
+
`+autostart-delay-random`, 281 in a run without it at tick 244, same lock,
|
|
427
|
+
same picture otherwise — and that page's "277 for the empty field" was
|
|
428
|
+
wrong twice over: 277 was the 4-cell paint after the first lock, and the
|
|
429
|
+
empty-field paint had never been captured (it is 275, tick 99 above). The
|
|
430
|
+
cycle figures derived from those numbers (17,450–17,950 cycles, 88 a cell)
|
|
431
|
+
were high by the same amount. With the interrupt off nothing else moves:
|
|
432
|
+
the 8 M, 16 M and 60 M captures land on the same ticks as before (250, 654,
|
|
433
|
+
2867) with the same 994 cells matching, so the lost frame per lock below
|
|
434
|
+
never depended on it.
|
|
435
|
+
|
|
436
|
+
And one number the counter gives for free: between the 8 M and 16 M captures
|
|
437
|
+
the emulated C64 ran 8,000,000 cycles, 407.0 PAL frames, and the counter
|
|
438
|
+
advanced 404. Three locks lie between those ticks (288, 440, 568), and 10 M
|
|
439
|
+
and 12 M captures (ticks 351 and 452) agree: one lock, one lost frame. The
|
|
440
|
+
lock frame is well over 312 lines of work counted from line 256: 272 of
|
|
441
|
+
paint, 19 for the four-digit display, 17 of overlay and 23 for its own
|
|
442
|
+
display come to 331 before the field writes, `spawn` and the wrap
|
|
443
|
+
arithmetic, and a probe bracket around the whole frame, with its own
|
|
444
|
+
instrumentation inside it, read 371 (each part on CIA 2's timer A in a
|
|
445
|
+
probe build). So it runs past line 256 of the following frame and
|
|
446
|
+
`vic_waitFrame` waits for the frame after that. The two controls below were measured the same way; their
|
|
447
|
+
pictures are in the same directory, and the digits on their row 24
|
|
448
|
+
(`OVERLAY 16` and `18`) are those builds' own numbers, not this listing's.
|
|
449
|
+
|
|
450
|
+
On NTSC (`-model ntsc`, 6567R8, 8,000,000 cycles, the same switches) the
|
|
451
|
+
capture is 384×247, the tick is 281, all 994 modelled cells match, and row
|
|
452
|
+
24 reads `FULL PAINT 0315 LINES OVERLAY 81 LINES`. Both are 49 too high,
|
|
453
|
+
312 − 263, because `LINES_PER_FRAME` is still 312: the paint wraps once and
|
|
454
|
+
the wrap is counted as 312 lines, and the overlay begins after line 256 and
|
|
455
|
+
crosses the wrap, so the modulo adds a frame's worth. The true values are
|
|
456
|
+
266 and 32 lines — 17,290 and 2,080 cycles at 65 a line, against 17,136 and
|
|
457
|
+
2,079 on PAL — and the overlay itself has no region dependence. Set
|
|
458
|
+
`LINES_PER_FRAME` to 263 for a build whose display is right on NTSC. The
|
|
459
|
+
first version of this page said it had not been run on NTSC; the shipped
|
|
460
|
+
build of that version reads `0319` and `81` there, the interrupt inside the
|
|
461
|
+
paint again.
|
|
462
|
+
|
|
463
|
+
## Why this works
|
|
464
|
+
|
|
465
|
+
### Two passes and one invariant
|
|
466
|
+
|
|
467
|
+
`render_piece` does what `text_mode_overlay_render` prescribes: pass one
|
|
468
|
+
repaints the four cells the piece occupied last frame *from `field[][]`*,
|
|
469
|
+
pass two writes `$A0` in the piece's colour at the four cells it occupies
|
|
470
|
+
now. Nothing on screen is ever anything but `field[][]` plus the current
|
|
471
|
+
piece, and the erase pass needs no memory of what was under the piece
|
|
472
|
+
because the field array is that memory. When the piece locks it is written
|
|
473
|
+
into `field[][]` and `have_prev` is cleared, so the erase pass is skipped on
|
|
474
|
+
that frame and the new piece starts clean. `prev_type` is carried as well as
|
|
475
|
+
`prev_x, prev_y` for the general form of the technique, where the shape can
|
|
476
|
+
change between frames — a rotation, or a lock that does not repaint — and
|
|
477
|
+
erasing the new shape's cells at the old position would leave the old
|
|
478
|
+
shape's cells behind. In this listing it is redundant: `cur_type` changes
|
|
479
|
+
only in `spawn()`, which is reached only through `render_field()`, which
|
|
480
|
+
clears `have_prev`, so whenever the erase pass runs `prev_type == cur_type`.
|
|
481
|
+
|
|
482
|
+
### Why the full paint is not per frame
|
|
483
|
+
|
|
484
|
+
`render_field` is the honest cost of "just redraw everything": 272 raster
|
|
485
|
+
lines for this loop, which is already the fast form, with row pointers,
|
|
486
|
+
unrolled two-column stores and no per-cell multiply. The first draft of this
|
|
487
|
+
page routed the 200 cells through `paint_cell` and measured 707 lines, 2.3
|
|
488
|
+
frames, and lost two frames at every lock. The generated `paint_cell` is
|
|
489
|
+
about 60 instructions — shift-and-add for `(2 + y) × 40`, the `2·x` offset,
|
|
490
|
+
four indirect stores — and an opcode tally of the body Oscar64 emitted comes
|
|
491
|
+
to 173–175 cycles before the `JSR`/`RTS` and the caller's argument setup
|
|
492
|
+
(rung 3, from the rung-1 listing). Measured, it is about 250 cycles a call
|
|
493
|
+
as `render_piece` runs it (1,998 cycles for eight) and 707 × 63 / 200 ≈ 220
|
|
494
|
+
in that first draft's loop, interrupt included. The first version of this
|
|
495
|
+
page said "about 50 instructions, roughly 100 cycles a call", which its own
|
|
496
|
+
numbers contradicted. Fine eight times a frame, ruinous two hundred times.
|
|
497
|
+
That draft also displayed `83`, because the timer took the difference of two
|
|
498
|
+
raster reads modulo 312 and the true value was 83 + 2 × 312. The counter
|
|
499
|
+
caught it: the run lost 58 ticks over 29 locks. The `render_field` above
|
|
500
|
+
samples the raster after every row and counts the wraps, so its number
|
|
501
|
+
cannot alias unless a single row takes a whole frame.
|
|
502
|
+
|
|
503
|
+
The whole per-frame path — `show_tick`, `tick`, `render_piece` and the
|
|
504
|
+
overlay's own number display — measures 57 lines (rung 1: a probe build of
|
|
505
|
+
this listing that brackets the loop body instead of the overlay alone, tick
|
|
506
|
+
250, same VICE run parameters; 41 on the first frame, whose overlay is the
|
|
507
|
+
17-line kind, and up to 63 on some others — every eighth frame `tick` runs
|
|
508
|
+
`fits()` and moves the piece, which is the likely extra, not separately
|
|
509
|
+
measured). The parts, on CIA 2's timer A in the same
|
|
510
|
+
probe: `show_tick` 123 cycles, `tick` 22 on a frame with no move,
|
|
511
|
+
`render_piece` 1,998, and the display 1,445 — two raster reads at 57 each,
|
|
512
|
+
the two digits at 522, and 809 for the `% LINES_PER_FRAME`, which is a
|
|
513
|
+
16-bit division in Oscar64's runtime because 312 does not fit a byte. The
|
|
514
|
+
first version of this page gave 43 lines here, which is what the bracket
|
|
515
|
+
reads when that modulo falls outside it; the display is a real cost of this
|
|
516
|
+
listing and belongs inside. The eight cell writes are done within the first
|
|
517
|
+
35 of the 57 lines, inside the 56 between `vic_waitFrame`'s return and the
|
|
518
|
+
wrap; the digit arithmetic runs a line past the wrap and stores into row 24
|
|
519
|
+
while the beam is in the top border. The display window does not resume
|
|
520
|
+
until raster 51, so there are 107 lines of race-free time and the per-frame
|
|
521
|
+
work uses 53 % of them. The full paint at 272 lines cannot fit, and that is
|
|
522
|
+
the whole point of the technique: the redraw is reserved for the events that
|
|
523
|
+
change `field[][]`.
|
|
524
|
+
|
|
525
|
+
On the lock frame in this listing the paint is invisible: the overlay had
|
|
526
|
+
already drawn the piece where it locked, in the same code and colour, so
|
|
527
|
+
the 200 writes change nothing on screen. The one-frame stall is the only
|
|
528
|
+
symptom. A line clear, which this stub does not implement, would shift the
|
|
529
|
+
field and make the paint visible for one frame; the technique page calls
|
|
530
|
+
that tear acceptable, and it is, once per clear.
|
|
531
|
+
|
|
532
|
+
### The three pitfalls, by name
|
|
533
|
+
|
|
534
|
+
- `dirty_cell_skip_leaves_overlay_trail` — the trail appears whenever the
|
|
535
|
+
cells the piece just left are not rewritten. Here they are rewritten
|
|
536
|
+
unconditionally by the erase pass, from the field array. The control
|
|
537
|
+
build with that pass deleted (`if (false)` in place of `if (have_prev)`)
|
|
538
|
+
shows, at tick 250, the cyan I piece smeared over its twelve previous
|
|
539
|
+
rows: 96 cells differ from the correct model, and zero differ from a
|
|
540
|
+
model with the erase pass removed. Picture:
|
|
541
|
+
`screenshots/text-overlay-playfield-notrail-control.png`.
|
|
542
|
+
- `render_during_state_transition_clobbers_banner` — `tick()` can flip
|
|
543
|
+
`state` to `ST_OVER` and draw the banner in the same iteration; the
|
|
544
|
+
overlay is gated on `state` *after* `tick()` returns, so the frame that
|
|
545
|
+
ends the game draws nothing over the banner. The control build with that
|
|
546
|
+
inner `if` removed paints the un-spawnable red Z over the banner on that
|
|
547
|
+
one frame: four of the nine characters (`E OV`) become red cells and stay
|
|
548
|
+
that way, since nothing repaints them, and the piece's upper two cells
|
|
549
|
+
land on four empty cells of field row 0 above them — eight cells differ
|
|
550
|
+
from the correct model, zero from a model with the gate removed. Picture:
|
|
551
|
+
`screenshots/text-overlay-playfield-ungated-control.png`.
|
|
552
|
+
- `full_field_redraw_exceeds_vblank` — measured above: 272 lines against a
|
|
553
|
+
56-line blank, one lost frame per lock even with the paint at its
|
|
554
|
+
fastest. Call `render_field` per frame and every frame is that frame.
|
|
555
|
+
The technique page's figure of about 18,400 cycles for this size of
|
|
556
|
+
field came from a different program; this listing's 17,100–17,450 is
|
|
557
|
+
the same number by a different instrument.
|
|
558
|
+
|
|
559
|
+
### Oscar64 details that cost time
|
|
560
|
+
|
|
561
|
+
- The KERNAL's IRQ is live in an Oscar64 program until you stop it. The
|
|
562
|
+
C64 start-up in `crt.c` never executes `sei` (its one `sei` is under
|
|
563
|
+
`OSCAR_TARGET_NES`), so without the `__asm { sei }` at the top of `main`
|
|
564
|
+
the 60 Hz service routine — four to five raster lines each time — lands
|
|
565
|
+
inside anything longer than a frame, and inside a 33-line bracket about
|
|
566
|
+
one time in eight, and a raster-line timer reports it as the cost of
|
|
567
|
+
whatever it interrupted. `__asm { sei }` is the spelling the `sprmux32.c`
|
|
568
|
+
sample uses. A game built on this shell that needs the keyboard reads the
|
|
569
|
+
matrix itself (`<c64/keyboard.h>`, `keyb_poll`) or installs its own
|
|
570
|
+
interrupt; this listing needs neither.
|
|
571
|
+
- `% LINES_PER_FRAME` on an `unsigned` costs about 810 cycles, thirteen
|
|
572
|
+
raster lines (rung 1, CIA 2 timer A): 312 does not fit a byte, so the
|
|
573
|
+
expression goes through the runtime's 16-by-16-bit `divmod` loop. The
|
|
574
|
+
two-digit `show_number` is 522 cycles by the same route on a smaller
|
|
575
|
+
scale, one `divmod` per digit, and the four-digit one 1,209. None of it
|
|
576
|
+
matters once a frame; all of it would in a loop of two hundred.
|
|
577
|
+
- `S"GAME OVER"` gives screen codes 7, 1, 13, 5, 32, 15, 22, 5, 18. The
|
|
578
|
+
lowercase prefix `s"GAME OVER"` does not: it case-flips letters before the
|
|
579
|
+
PETSCII-to-screen-code step, so uppercase ASCII becomes the shifted
|
|
580
|
+
glyphs (`$47, $41, …`, graphics in the default font) and only `s"game
|
|
581
|
+
over"` would give the letters. Capital `S` folds both cases to the
|
|
582
|
+
unshifted letters. That is in the compiler's scanner, and the first build
|
|
583
|
+
of this page printed its labels as graphics glyphs because of it.
|
|
584
|
+
- `vic_waitFrame()` from `<c64/vic.h>` spins on bit 7 of `$D011` twice:
|
|
585
|
+
until RST8 is clear, then until it is set. It returns at the start of
|
|
586
|
+
line 256, which is why the per-frame budget above is counted from there.
|
|
587
|
+
`raster_line()` reads `$D011` and `$D012` itself, once more if RST8
|
|
588
|
+
changed between the two reads; that is why those two registers are in
|
|
589
|
+
the frontmatter, and `$D020`/`$D021` because `main` writes them.
|
|
590
|
+
- `bool`, `true` and `false` are built in; no `<stdbool.h>` is needed or
|
|
591
|
+
included.
|
|
592
|
+
- The `Screen`/`Color` macros and the `Screen[40 * y + x]` idiom are the
|
|
593
|
+
ones the Oscar64 game samples use; they read the same source, not the
|
|
594
|
+
same code.
|
|
595
|
+
|
|
596
|
+
## Sources
|
|
597
|
+
|
|
598
|
+
- `docs/techniques/text-mode-render.md` (`text_mode_overlay_render`: the
|
|
599
|
+
two-pass design, the erase-prev/draw-current variant, the frame-budget
|
|
600
|
+
trap) and `docs/pitfalls/text-mode-render.md` (the three pitfalls named
|
|
601
|
+
above), this repository.
|
|
602
|
+
- `docs/hardware/vic-ii-reference.md`, this repository, for the 25-row
|
|
603
|
+
display window at raster 51–250 and the RST8 bit.
|
|
604
|
+
- Oscar64 (build 2026-05-19): `include/c64/vic.h` and `vic.c` for
|
|
605
|
+
`vic_waitFrame`, `VIC_CTRL1_RST8` and the `vic` struct; `include/crt.c`
|
|
606
|
+
for what the C64 start-up does and does not do about interrupts;
|
|
607
|
+
`include/c64/cia.h` for the `cia2` struct the probe builds timed with;
|
|
608
|
+
`oscar64.md`, section on PETSCII and string prefixes; `oscar64/Scanner.cpp`,
|
|
609
|
+
the string-literal mode switch, for what `s` and `S` do to letter case;
|
|
610
|
+
`samples/games/snake.c` for the screen/colour macro idiom and
|
|
611
|
+
`samples/sprites/sprmux32.c` for `__asm { sei }`, read not copied.
|
|
612
|
+
- VICE 3.10, `x64sc -help`, for `+autostart-delay-random` and
|
|
613
|
+
`-model ntsc`; the C64 character ROM `chargen-901225-01.bin` shipped
|
|
614
|
+
with it, for the glyph matching; a 16-colour calibration PRG run in the
|
|
615
|
+
same build for the palette.
|
|
616
|
+
- `docs/recipes/oscar64/simple-shmup.md`, this repository, for the recipe
|
|
617
|
+
shape and the `Screen`/`Color` define style.
|