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,367 @@
|
|
|
1
|
+
---
|
|
2
|
+
recipe: print-number
|
|
3
|
+
toolchain: oscar64
|
|
4
|
+
output_format: PRG
|
|
5
|
+
region: both
|
|
6
|
+
techniques: [decimal_print]
|
|
7
|
+
file_formats: [PRG]
|
|
8
|
+
uses_registers: [DC04, DC05, DC0E, D011, D012]
|
|
9
|
+
uses_kernal: []
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<!-- doc-type: recipe -->
|
|
13
|
+
|
|
14
|
+
# Oscar64 Print Number: binary to decimal and hex in screen RAM
|
|
15
|
+
|
|
16
|
+
## Synopsis
|
|
17
|
+
|
|
18
|
+
Turns a 16-bit binary value into five screen codes, right-aligned with
|
|
19
|
+
leading zeros shown as spaces, and an 8-bit value into `$xx`, and writes
|
|
20
|
+
them straight into screen RAM with no KERNAL call. Two decimal routes are
|
|
21
|
+
given: subtract-powers (`fmt_dec_sub`, the one to use from C) and a plain
|
|
22
|
+
C double-dabble (`fmt_dec_dab`, for comparison). Both are run over all
|
|
23
|
+
65,536 values and the hex route over all 256, each field folded into a
|
|
24
|
+
16-bit checksum shown with `PASS` or `FAIL` against the value Python
|
|
25
|
+
computed. A CIA1 timer A harness then prints the cycle cost of each
|
|
26
|
+
route, so the screenshot proves the digits and the figures. Use it for a
|
|
27
|
+
HUD score, timer, coordinate readout or a debugging display. It
|
|
28
|
+
implements `decimal_print` (`techniques/text.md`); the design-level notes
|
|
29
|
+
are in `game-design/game-design-patterns.md` under "Printing numbers".
|
|
30
|
+
|
|
31
|
+
## Source
|
|
32
|
+
|
|
33
|
+
```c
|
|
34
|
+
// print-number.c
|
|
35
|
+
// Binary to decimal and hexadecimal for a text HUD, written straight into
|
|
36
|
+
// screen RAM as screen codes with no KERNAL call. Two 16-bit decimal
|
|
37
|
+
// routes (subtract-powers and double-dabble) are run over all 65,536
|
|
38
|
+
// values and the 8-bit hex route over all 256, each folded into a 16-bit
|
|
39
|
+
// checksum shown with PASS or FAIL against the value Python computed.
|
|
40
|
+
// A CIA1 timer A harness then prints the cycle cost of each route.
|
|
41
|
+
#include <c64/vic.h>
|
|
42
|
+
#include <c64/cia.h>
|
|
43
|
+
|
|
44
|
+
#define SCREEN ((char *)0x0400) // default text screen
|
|
45
|
+
|
|
46
|
+
// Expected checksums, computed by the same fold in Python (page text).
|
|
47
|
+
#define EXPECT_DEC 0x0EB2 // fold over str(n).rjust(5), n = 0..65535
|
|
48
|
+
#define EXPECT_HEX 0x263C // fold over the 4-char hex field, n = 0..255
|
|
49
|
+
|
|
50
|
+
// Screen codes: digits are $30-$39 as in PETSCII; 'A'-'F' are $01-$06.
|
|
51
|
+
static const char hex_glyph[16] = {
|
|
52
|
+
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
|
53
|
+
0x38, 0x39, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
// --- the routines under test ------------------------------------------------
|
|
57
|
+
|
|
58
|
+
// Subtract-powers. Writes five screen codes to dst: the value right-aligned,
|
|
59
|
+
// leading zeros as spaces, so 0 becomes " 0" and 65535 fills the field.
|
|
60
|
+
__noinline void fmt_dec_sub(unsigned v, char *dst)
|
|
61
|
+
{
|
|
62
|
+
static const unsigned pow10[4] = { 10000, 1000, 100, 10 };
|
|
63
|
+
char lead = 1;
|
|
64
|
+
for (char i = 0; i < 4; i++)
|
|
65
|
+
{
|
|
66
|
+
unsigned p = pow10[i];
|
|
67
|
+
char d = 0x30;
|
|
68
|
+
while (v >= p) { v -= p; d++; }
|
|
69
|
+
if (d != 0x30 || !lead) { dst[i] = d; lead = 0; }
|
|
70
|
+
else dst[i] = 0x20;
|
|
71
|
+
}
|
|
72
|
+
dst[4] = 0x30 + v; // v is 0..9 here
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Double-dabble in plain C. Shifts the 16 bits into three packed BCD bytes,
|
|
76
|
+
// adding 3 to any nibble that is 5 or more before each shift, then unpacks
|
|
77
|
+
// with the same zero suppression as fmt_dec_sub. Same output bytes.
|
|
78
|
+
__noinline void fmt_dec_dab(unsigned v, char *dst)
|
|
79
|
+
{
|
|
80
|
+
char b0 = 0, b1 = 0, b2 = 0; // b2 ten-thousands, b1 thousands|hundreds, b0 tens|units
|
|
81
|
+
for (char i = 0; i < 16; i++)
|
|
82
|
+
{
|
|
83
|
+
if ((b0 & 0x0f) >= 0x05) b0 += 0x03;
|
|
84
|
+
if ((b0 & 0xf0) >= 0x50) b0 += 0x30;
|
|
85
|
+
if ((b1 & 0x0f) >= 0x05) b1 += 0x03;
|
|
86
|
+
if ((b1 & 0xf0) >= 0x50) b1 += 0x30;
|
|
87
|
+
if (b2 >= 0x05) b2 += 0x03;
|
|
88
|
+
b2 = (b2 << 1) | (b1 >> 7);
|
|
89
|
+
b1 = (b1 << 1) | (b0 >> 7);
|
|
90
|
+
b0 = (b0 << 1) | (char)(v >> 15);
|
|
91
|
+
v <<= 1;
|
|
92
|
+
}
|
|
93
|
+
char n[5];
|
|
94
|
+
n[0] = b2 & 0x0f; n[1] = b1 >> 4; n[2] = b1 & 0x0f; n[3] = b0 >> 4; n[4] = b0 & 0x0f;
|
|
95
|
+
char lead = 1;
|
|
96
|
+
for (char i = 0; i < 4; i++)
|
|
97
|
+
{
|
|
98
|
+
if (n[i] != 0 || !lead) { dst[i] = 0x30 + n[i]; lead = 0; }
|
|
99
|
+
else dst[i] = 0x20;
|
|
100
|
+
}
|
|
101
|
+
dst[4] = 0x30 + n[4];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Hex byte for debugging: "$" and two digits, right-aligned in four cells.
|
|
105
|
+
__noinline void fmt_hex8(char v, char *dst)
|
|
106
|
+
{
|
|
107
|
+
dst[0] = 0x20;
|
|
108
|
+
dst[1] = 0x24; // '$'
|
|
109
|
+
dst[2] = hex_glyph[v >> 4];
|
|
110
|
+
dst[3] = hex_glyph[v & 0x0f];
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
__noinline void fmt_null(unsigned v, char *dst)
|
|
114
|
+
{
|
|
115
|
+
// timing control: same call shape, empty body
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// --- helpers ---------------------------------------------------------------
|
|
119
|
+
|
|
120
|
+
static void put_text(char row, char col, const char *s)
|
|
121
|
+
{
|
|
122
|
+
char *p = SCREEN + 40 * row + col;
|
|
123
|
+
while (*s)
|
|
124
|
+
{
|
|
125
|
+
char c = *s++;
|
|
126
|
+
if (c >= 'A' && c <= 'Z') c -= 64; // ASCII upper case to screen code
|
|
127
|
+
else if (c == '[') c = 0x1b; // brackets: screen codes $1B, $1D
|
|
128
|
+
else if (c == ']') c = 0x1d;
|
|
129
|
+
*p++ = c;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
static void put_hex16(char row, char col, unsigned v)
|
|
134
|
+
{
|
|
135
|
+
char *p = SCREEN + 40 * row + col;
|
|
136
|
+
p[0] = hex_glyph[(v >> 12) & 15]; p[1] = hex_glyph[(v >> 8) & 15];
|
|
137
|
+
p[2] = hex_glyph[(v >> 4) & 15]; p[3] = hex_glyph[v & 15];
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
static unsigned fold(unsigned chk, char value)
|
|
141
|
+
{
|
|
142
|
+
return (chk ^ value) * 5 + 1;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// --- timing harness: CIA1 timer A, force-loaded from $FFFF, phi2 ----------
|
|
146
|
+
|
|
147
|
+
static char tbuf[8];
|
|
148
|
+
static volatile unsigned tval = 65535; // volatile: the call cannot be folded
|
|
149
|
+
static volatile unsigned tval2 = 59999; // worst case for subtract-powers (5+9+9+9 steps)
|
|
150
|
+
|
|
151
|
+
static void t_start(void)
|
|
152
|
+
{
|
|
153
|
+
cia1.cra = 0x00; // stop timer A
|
|
154
|
+
cia1.ta = 0xffff; // latch $FFFF
|
|
155
|
+
cia1.cra = 0x11; // force load, start, count phi2
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
static unsigned t_stop(void)
|
|
159
|
+
{
|
|
160
|
+
cia1.cra = 0x00; // stop before reading, so the two
|
|
161
|
+
return 0xffff - cia1.ta; // byte reads cannot straddle a borrow
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
static unsigned time_sub(void) { unsigned v = tval; t_start(); fmt_dec_sub(v, tbuf); return t_stop(); }
|
|
165
|
+
static unsigned time_sub2(void) { unsigned v = tval2; t_start(); fmt_dec_sub(v, tbuf); return t_stop(); }
|
|
166
|
+
static unsigned time_dab(void) { unsigned v = tval; t_start(); fmt_dec_dab(v, tbuf); return t_stop(); }
|
|
167
|
+
static unsigned time_hex(void) { unsigned v = tval; t_start(); fmt_hex8((char)v, tbuf); return t_stop(); }
|
|
168
|
+
static unsigned time_null(void) { unsigned v = tval; t_start(); fmt_null(v, tbuf); return t_stop(); }
|
|
169
|
+
|
|
170
|
+
static void show_cycles(char row, const char *label, unsigned raw, unsigned base)
|
|
171
|
+
{
|
|
172
|
+
put_text(row, 0, label);
|
|
173
|
+
fmt_dec_sub(raw - base, SCREEN + 40 * row + 12);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
int main(void)
|
|
177
|
+
{
|
|
178
|
+
__asm { sei } // no KERNAL IRQ during the checks
|
|
179
|
+
for (unsigned i = 0; i < 1000; i++) SCREEN[i] = 0x20;
|
|
180
|
+
|
|
181
|
+
put_text(0, 0, "PRINT NUMBER");
|
|
182
|
+
|
|
183
|
+
// The four demonstration fields, each shown inside brackets.
|
|
184
|
+
put_text(2, 0, "DEC 0 [ ]");
|
|
185
|
+
fmt_dec_sub(0, SCREEN + 2 * 40 + 12);
|
|
186
|
+
put_text(3, 0, "DEC 7 [ ]");
|
|
187
|
+
fmt_dec_sub(7, SCREEN + 3 * 40 + 12);
|
|
188
|
+
put_text(4, 0, "DEC 65535 [ ]");
|
|
189
|
+
fmt_dec_sub(65535, SCREEN + 4 * 40 + 12);
|
|
190
|
+
put_text(5, 0, "HEX $A5 [ ]");
|
|
191
|
+
fmt_hex8(0xa5, SCREEN + 5 * 40 + 12);
|
|
192
|
+
|
|
193
|
+
// Cycle costs for the value 65535, body only: the empty call is subtracted.
|
|
194
|
+
// Display off while timing so no badline stalls the CPU. The VIC-II
|
|
195
|
+
// samples DEN once per frame, on line $30 (VIC-II documentation, not
|
|
196
|
+
// measured here), so wait for the next frame to start before timing;
|
|
197
|
+
// what was measured is that without this wait the NTSC run read 9% higher.
|
|
198
|
+
vic.ctrl1 &= ~0x10;
|
|
199
|
+
while (vic.raster != 0x80) ;
|
|
200
|
+
while (vic.raster != 0x00) ;
|
|
201
|
+
unsigned base = time_null();
|
|
202
|
+
unsigned c_sub = time_sub();
|
|
203
|
+
unsigned c_sub2 = time_sub2();
|
|
204
|
+
unsigned c_dab = time_dab();
|
|
205
|
+
unsigned c_hex = time_hex();
|
|
206
|
+
vic.ctrl1 |= 0x10;
|
|
207
|
+
|
|
208
|
+
put_text(11, 0, "CYCLES, BODY ONLY (CIA1 TIMER A)");
|
|
209
|
+
show_cycles(12, "SUB16 65535", c_sub, base);
|
|
210
|
+
show_cycles(13, "SUB16 59999", c_sub2, base);
|
|
211
|
+
show_cycles(14, "DAB16 65535", c_dab, base);
|
|
212
|
+
show_cycles(15, "HEX8 $FF ", c_hex, base);
|
|
213
|
+
show_cycles(16, "NULL CALL ", base, 0);
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
// Exhaustive checks: every value through both decimal routes, all 256
|
|
217
|
+
// bytes through the hex route, each field folded into a checksum.
|
|
218
|
+
unsigned chk_sub = 0, chk_dab = 0, chk_hex = 0;
|
|
219
|
+
char buf[5];
|
|
220
|
+
unsigned n = 0;
|
|
221
|
+
do
|
|
222
|
+
{
|
|
223
|
+
fmt_dec_sub(n, buf);
|
|
224
|
+
for (char i = 0; i < 5; i++) chk_sub = fold(chk_sub, buf[i]);
|
|
225
|
+
fmt_dec_dab(n, buf);
|
|
226
|
+
for (char i = 0; i < 5; i++) chk_dab = fold(chk_dab, buf[i]);
|
|
227
|
+
} while (++n != 0);
|
|
228
|
+
for (unsigned h = 0; h < 256; h++)
|
|
229
|
+
{
|
|
230
|
+
fmt_hex8((char)h, buf);
|
|
231
|
+
for (char i = 0; i < 4; i++) chk_hex = fold(chk_hex, buf[i]);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
put_text(7, 0, "SUB 0-65535 CHK EXP ");
|
|
235
|
+
put_hex16(7, 16, chk_sub); put_hex16(7, 25, EXPECT_DEC);
|
|
236
|
+
put_text(7, 30, chk_sub == EXPECT_DEC ? "PASS" : "FAIL");
|
|
237
|
+
put_text(8, 0, "DAB 0-65535 CHK EXP ");
|
|
238
|
+
put_hex16(8, 16, chk_dab); put_hex16(8, 25, EXPECT_DEC);
|
|
239
|
+
put_text(8, 30, chk_dab == EXPECT_DEC ? "PASS" : "FAIL");
|
|
240
|
+
put_text(9, 0, "HEX 0-255 CHK EXP ");
|
|
241
|
+
put_hex16(9, 16, chk_hex); put_hex16(9, 25, EXPECT_HEX);
|
|
242
|
+
put_text(9, 30, chk_hex == EXPECT_HEX ? "PASS" : "FAIL");
|
|
243
|
+
|
|
244
|
+
for (;;) ;
|
|
245
|
+
return 0;
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## Build
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
oscar64 -tm=c64 -O2 -o=print-number.prg print-number.c
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Then run headless (PAL; add `-model ntsc` for NTSC):
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
GSETTINGS_SCHEMA_DIR=/opt/homebrew/share/glib-2.0/schemas timeout 120 x64sc -default -warp +sound +autostart-delay-random -autostartprgmode 1 -limitcycles 400000000 -exitscreenshot print-number.png -autostart print-number.prg
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
The cycle limit is 400,000,000 because the exhaustive loop runs both
|
|
262
|
+
decimal routes 65,536 times, about 4,000 cycles a pass with the checksum
|
|
263
|
+
folds (rung 3, from the measured routine costs); at 300,000,000 a first
|
|
264
|
+
version, which blanked the display for the whole check, exited with the
|
|
265
|
+
screen still blank.
|
|
266
|
+
|
|
267
|
+
## Expected output
|
|
268
|
+
|
|
269
|
+
`screenshots/print-number.png` (PAL) and `screenshots/print-number-ntsc.png`
|
|
270
|
+
(NTSC), both read cell by cell against the character ROM. Light blue
|
|
271
|
+
text on the default blue screen:
|
|
272
|
+
|
|
273
|
+
```
|
|
274
|
+
PRINT NUMBER
|
|
275
|
+
|
|
276
|
+
DEC 0 [ 0]
|
|
277
|
+
DEC 7 [ 7]
|
|
278
|
+
DEC 65535 [65535]
|
|
279
|
+
HEX $A5 [ $A5]
|
|
280
|
+
|
|
281
|
+
SUB 0-65535 CHK 0EB2 EXP 0EB2 PASS
|
|
282
|
+
DAB 0-65535 CHK 0EB2 EXP 0EB2 PASS
|
|
283
|
+
HEX 0-255 CHK 263C EXP 263C PASS
|
|
284
|
+
|
|
285
|
+
CYCLES, BODY ONLY (CIA1 TIMER A)
|
|
286
|
+
SUB16 65535 957
|
|
287
|
+
SUB16 59999 1361
|
|
288
|
+
DAB16 65535 2537
|
|
289
|
+
HEX8 $FF 74
|
|
290
|
+
NULL CALL 17
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
The three checksums are the fold `chk = ((chk ^ byte) * 5 + 1) & 0xFFFF`
|
|
294
|
+
over every byte of every field, in order. In Python:
|
|
295
|
+
|
|
296
|
+
```python
|
|
297
|
+
def fold(chk, v): return ((chk ^ v) * 5 + 1) & 0xffff
|
|
298
|
+
chk = 0
|
|
299
|
+
for n in range(65536):
|
|
300
|
+
for b in str(n).rjust(5).encode('ascii'):
|
|
301
|
+
chk = fold(chk, b)
|
|
302
|
+
print(hex(chk)) # 0xeb2
|
|
303
|
+
hexg = [0x30 + i for i in range(10)] + [1, 2, 3, 4, 5, 6]
|
|
304
|
+
chk = 0
|
|
305
|
+
for n in range(256):
|
|
306
|
+
for b in [0x20, 0x24, hexg[n >> 4], hexg[n & 15]]:
|
|
307
|
+
chk = fold(chk, b)
|
|
308
|
+
print(hex(chk)) # 0x263c
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
The decimal fold works on the ASCII bytes of `str(n).rjust(5)` because
|
|
312
|
+
screen codes for `0`-`9` and space are `$30`-`$39` and `$20`, the same
|
|
313
|
+
as ASCII. The hex fold has to spell the screen codes out, because `A`-`F`
|
|
314
|
+
are `$01`-`$06` on screen and not their ASCII values. Both decimal routes
|
|
315
|
+
reach the same checksum, which is the point of running two: they agree on
|
|
316
|
+
all 327,680 output bytes.
|
|
317
|
+
|
|
318
|
+
The cycle figures are the value of CIA1 timer A after each call, less
|
|
319
|
+
the 17 cycles of the same sequence around an empty function, so they are
|
|
320
|
+
the body of the routine without its `JSR` and `RTS`. The PAL and NTSC
|
|
321
|
+
runs give identical figures (rung 1, VICE x64sc 3.10). 59999 is the
|
|
322
|
+
worst case for subtract-powers (digit sum 5 + 9 + 9 + 9, thirty-two
|
|
323
|
+
subtractions); the double-dabble's cost does not depend on the value.
|
|
324
|
+
A build with different code placement read 953 and 2,533 for the first
|
|
325
|
+
and third lines, so treat the last few cycles as layout, not routine.
|
|
326
|
+
|
|
327
|
+
## Why this works
|
|
328
|
+
|
|
329
|
+
`fmt_dec_sub` walks the powers 10000, 1000, 100, 10 and counts how many
|
|
330
|
+
times each can be taken from the value; the count plus `$30` is the
|
|
331
|
+
digit's screen code, and what is left after the last power is the units
|
|
332
|
+
digit. `lead` stays set until the first non-zero digit, and while it is
|
|
333
|
+
set a zero writes `$20` instead of `$30`, which gives zero suppression and
|
|
334
|
+
right alignment in one move because the field width is fixed. The last
|
|
335
|
+
digit is written unconditionally so that 0 prints as `0`. For an
|
|
336
|
+
arcade-style score with leading zeros, drop the `lead` test.
|
|
337
|
+
|
|
338
|
+
`fmt_dec_dab` is the textbook double-dabble: shift the bits in from the
|
|
339
|
+
top, and before each shift add 3 to any BCD nibble that is 5 or more so
|
|
340
|
+
that the shift carries a 10 out of it. On the 6502 the same algorithm is
|
|
341
|
+
much cheaper in assembly with `SED`, where `adc` of a byte to itself
|
|
342
|
+
doubles a packed BCD pair and adjusts it for free; C cannot set decimal
|
|
343
|
+
mode, so the nibble version pays for every test and lands at 2.6 times
|
|
344
|
+
the cost of subtract-powers. Use `fmt_dec_sub` from C, and if a fixed
|
|
345
|
+
cost matters more than the average, call an assembly double-dabble
|
|
346
|
+
through `__asm` (the KickAssembler `dab_u16` listing under "Printing
|
|
347
|
+
numbers" in `game-design/game-design-patterns.md` measured 875 cycles for
|
|
348
|
+
any value).
|
|
349
|
+
|
|
350
|
+
The timing harness stops timer A, writes `$FFFF` to the latch, and
|
|
351
|
+
restarts it with a force load (`cra = $11`), so the count starts from a
|
|
352
|
+
known value; it stops the timer again before reading the two bytes so
|
|
353
|
+
the read cannot straddle a borrow from low to high. The display is
|
|
354
|
+
blanked during the timing, and the program then waits for the next frame
|
|
355
|
+
before starting, because the VIC-II samples the DEN bit once per frame,
|
|
356
|
+
on line `$30` (VIC-II documentation, not measured here; what was measured
|
|
357
|
+
is that the wait closes the 9 per cent NTSC gap): a first version that
|
|
358
|
+
blanked and timed at once read 9 per cent higher on NTSC, where the run
|
|
359
|
+
happened to start mid-frame and the badlines of that frame were still
|
|
360
|
+
stealing cycles. With the wait, PAL and NTSC agree to the cycle.
|
|
361
|
+
|
|
362
|
+
Everything is written as screen codes at `$0400` with no KERNAL call:
|
|
363
|
+
`put_text` folds ASCII upper case to screen codes by subtracting 64 and
|
|
364
|
+
maps `[` and `]` to `$1B` and `$1D`; digits and `$` need no translation.
|
|
365
|
+
The KERNAL IRQ is switched off with `sei` so the jiffy handler does not
|
|
366
|
+
run inside the timed region or reprogram the timer (the KERNAL uses CIA1
|
|
367
|
+
timer A for its 60 Hz tick).
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
---
|
|
2
|
+
recipe: raster-bars
|
|
3
|
+
toolchain: oscar64
|
|
4
|
+
output_format: PRG
|
|
5
|
+
region: both
|
|
6
|
+
techniques: [raster_bars, stable_raster_irq]
|
|
7
|
+
file_formats: [PRG]
|
|
8
|
+
uses_registers: [D012, D019, D020, D021]
|
|
9
|
+
uses_kernal: []
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<!-- doc-type: recipe -->
|
|
13
|
+
|
|
14
|
+
# Oscar64 Raster Color Bars
|
|
15
|
+
|
|
16
|
+
## Synopsis
|
|
17
|
+
|
|
18
|
+
Fifteen color bars cycling down the screen, one per raster split, using
|
|
19
|
+
`rasterirq.h`. Each bar changes both the border color (`$D020`) and the
|
|
20
|
+
background color (`$D021`) for its band. The bars shift upward by one slot
|
|
21
|
+
every two frames, producing a smooth rainbow animation. This recipe builds
|
|
22
|
+
directly on `stable-raster-irq.md` and shows how multiple `RIRQCode` slots
|
|
23
|
+
compose into a full multi-split raster effect.
|
|
24
|
+
|
|
25
|
+
## Source
|
|
26
|
+
|
|
27
|
+
```c
|
|
28
|
+
// raster-bars.c
|
|
29
|
+
#include <c64/vic.h>
|
|
30
|
+
#include <c64/rasterirq.h>
|
|
31
|
+
|
|
32
|
+
// 16 C64 palette entries in rainbow order. Names match Oscar64's c64/vic.h
|
|
33
|
+
// enum exactly — note PURPLE (not VIOLET) and DARK_GREY (no plain GREY).
|
|
34
|
+
// Index 16 duplicates index 0; the animation loop indexes with `& 15`, so
|
|
35
|
+
// the sentinel is never read and is kept only for a plain-loop variant.
|
|
36
|
+
static const byte rainbow[17] = {
|
|
37
|
+
VCOL_BLACK, VCOL_BROWN, VCOL_RED, VCOL_ORANGE,
|
|
38
|
+
VCOL_YELLOW, VCOL_LT_GREEN, VCOL_GREEN, VCOL_CYAN,
|
|
39
|
+
VCOL_LT_BLUE, VCOL_BLUE, VCOL_PURPLE, VCOL_LT_RED,
|
|
40
|
+
VCOL_DARK_GREY, VCOL_MED_GREY, VCOL_LT_GREY, VCOL_WHITE,
|
|
41
|
+
VCOL_BLACK // sentinel wrap
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// Number of visible bars. Each bar is one rirq slot that writes D020 + D021.
|
|
45
|
+
// 15 bars plus the reset slot below = 16 slots, the library's NUM_IRQS.
|
|
46
|
+
#define NUM_BARS 15
|
|
47
|
+
|
|
48
|
+
// Bar height in raster lines: 15 bars * 13 lines = 195 of the 200 visible.
|
|
49
|
+
#define BAR_HEIGHT 13
|
|
50
|
+
|
|
51
|
+
// First raster line for the top bar (just below the top border on PAL).
|
|
52
|
+
#define FIRST_LINE 51
|
|
53
|
+
|
|
54
|
+
// One RIRQCode per bar. Each struct holds two writes (border + background).
|
|
55
|
+
RIRQCode bars[NUM_BARS];
|
|
56
|
+
|
|
57
|
+
// A final slot that resets both registers after the last bar, so the
|
|
58
|
+
// area below the bars returns to black before the next frame begins.
|
|
59
|
+
RIRQCode reset_slot;
|
|
60
|
+
|
|
61
|
+
int main(void)
|
|
62
|
+
{
|
|
63
|
+
// Standard rasterirq init: route through KERNAL vector, CIA disabled.
|
|
64
|
+
rirq_init(true);
|
|
65
|
+
|
|
66
|
+
// Build each bar slot with two writes: D020 (border) and D021 (background).
|
|
67
|
+
for (char i = 0; i < NUM_BARS; i++) {
|
|
68
|
+
rirq_build(&bars[i], 2);
|
|
69
|
+
rirq_write(&bars[i], 0, &vic.color_border, rainbow[i]);
|
|
70
|
+
rirq_write(&bars[i], 1, &vic.color_back, rainbow[i]);
|
|
71
|
+
// Fire one line before the start of this bar's visible region.
|
|
72
|
+
rirq_set(i, FIRST_LINE + (char)(i * BAR_HEIGHT) - 1, &bars[i]);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// The reset slot fires after the last bar and sets both colors to black,
|
|
76
|
+
// so the area between the last bar and the frame bottom is clean. Same
|
|
77
|
+
// "one line early" rule as the bars: without the -1 the last bar is 14
|
|
78
|
+
// lines tall, which is what the earlier version of this recipe drew.
|
|
79
|
+
rirq_build(&reset_slot, 2);
|
|
80
|
+
rirq_write(&reset_slot, 0, &vic.color_border, VCOL_BLACK);
|
|
81
|
+
rirq_write(&reset_slot, 1, &vic.color_back, VCOL_BLACK);
|
|
82
|
+
rirq_set(NUM_BARS, FIRST_LINE + NUM_BARS * BAR_HEIGHT - 1, &reset_slot);
|
|
83
|
+
|
|
84
|
+
rirq_sort();
|
|
85
|
+
rirq_start();
|
|
86
|
+
|
|
87
|
+
// Animation: shift the color palette index each frame so the bars appear
|
|
88
|
+
// to scroll upward. 'offset' cycles through 0..15.
|
|
89
|
+
char offset = 0;
|
|
90
|
+
char frame = 0;
|
|
91
|
+
|
|
92
|
+
for (;;) {
|
|
93
|
+
// Wait until all raster IRQs for this frame have fired, then update
|
|
94
|
+
// the palette before rirq_sort re-arms for the next frame.
|
|
95
|
+
rirq_wait();
|
|
96
|
+
|
|
97
|
+
// Advance the color offset every two frames (25 Hz on PAL, 30 Hz NTSC).
|
|
98
|
+
frame++;
|
|
99
|
+
if (frame >= 2) {
|
|
100
|
+
frame = 0;
|
|
101
|
+
offset = (offset + 1) & 15;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Repatch each bar's color data in-place using rirq_data.
|
|
105
|
+
// rirq_data only writes the data byte of an existing slot — it does
|
|
106
|
+
// not touch the target address or rebuild the slot. This is the
|
|
107
|
+
// fastest way to animate raster IRQ content.
|
|
108
|
+
for (char i = 0; i < NUM_BARS; i++) {
|
|
109
|
+
byte c = rainbow[(offset + i) & 15];
|
|
110
|
+
rirq_data(&bars[i], 0, c); // border
|
|
111
|
+
rirq_data(&bars[i], 1, c); // background
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Re-sort is not needed here because no slot has moved.
|
|
115
|
+
// rirq_sort() would be required if rirq_move() had been called.
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return 0;
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Build
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
oscar64 -o=raster-bars.prg -tf=prg raster-bars.c
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Produces `raster-bars.prg` plus the usual `.map`, `.asm`, and `.lbl` side files.
|
|
129
|
+
Load with `LOAD"RASTER-BARS",8,1 : RUN` or via VICE autostart.
|
|
130
|
+
|
|
131
|
+
## Expected output
|
|
132
|
+
|
|
133
|
+
Fifteen horizontal color bands fill the display area, each 13 raster lines
|
|
134
|
+
tall, cycling through the C64 16-color palette. The entire stack of bars
|
|
135
|
+
drifts upward smoothly at half the frame rate (one color step every two
|
|
136
|
+
frames). Below the bar stack the border and background are black. The color
|
|
137
|
+
boundaries are straight horizontal lines, with two exceptions: the bars that
|
|
138
|
+
begin on lines 51 and 155 start on badlines, and on those two lines the
|
|
139
|
+
background write (sometimes the border write too) lands after the display
|
|
140
|
+
window has been drawn, so that one row keeps the previous bar's colour under
|
|
141
|
+
an already-changed border. See "Badline interaction" below. The program does
|
|
142
|
+
not clear the screen, so the BASIC start-up text stays visible in light blue
|
|
143
|
+
on top of the bars.
|
|
144
|
+
|
|
145
|
+
Verified with Oscar64 (build 2026-05-19) and VICE x64sc after the slot-count
|
|
146
|
+
fix described below. Measured on the PAL render of 2026-09-22: fifteen bands
|
|
147
|
+
on lines 51-245, each 13 lines (the earlier listing set the reset slot one
|
|
148
|
+
line late and drew the last bar 14 lines tall, 233-246), black from line 246
|
|
149
|
+
down, line 155 showing a cyan border over a still-green display row.
|
|
150
|
+
|
|
151
|
+
On PAL (50 Hz) the palette completes one full cycle in 32 frames (0.64 seconds).
|
|
152
|
+
On NTSC (60 Hz) the same 32-frame cycle completes in 0.53 seconds, running
|
|
153
|
+
slightly faster.
|
|
154
|
+
|
|
155
|
+
## Why this works
|
|
156
|
+
|
|
157
|
+
### Foundation: stable raster IRQ
|
|
158
|
+
|
|
159
|
+
This recipe is a direct extension of `stable-raster-irq.md`. Every slot in the
|
|
160
|
+
`bars` array is entered on the line above its target and spins on `CMP $D012`
|
|
161
|
+
until the target line begins. The loop exits within the first 1-7 cycles of
|
|
162
|
+
the target line, the first write (`STY $D020`) completes by about cycle 12
|
|
163
|
+
and the second (`STX $D021`) by about cycle 16, per the cycle comment above
|
|
164
|
+
`rirq_build` in `rasterirq.c` and the opcodes it emits; both are before the display window opens, and
|
|
165
|
+
the rendered edges are straight on every non-badline boundary. (This text
|
|
166
|
+
used to say both writes complete by about cycle 12; that is only the first
|
|
167
|
+
one.) See that recipe for what the library does and does not guarantee. The `rirq_init(true)` call disables CIA timer interrupts and
|
|
168
|
+
installs the dispatcher through the KERNAL vector. Without the polling loop,
|
|
169
|
+
each bar boundary would show a step two-thirds of the way across its first
|
|
170
|
+
line.
|
|
171
|
+
|
|
172
|
+
### Multiple slots: the rirq slot table
|
|
173
|
+
|
|
174
|
+
`rasterirq.h` maintains a sorted table of `NUM_IRQS` IRQ slots, 16 by
|
|
175
|
+
default. After `rirq_sort()`, the dispatcher walks this table on every frame,
|
|
176
|
+
firing each slot when the raster beam reaches the programmed line. Oscar64's
|
|
177
|
+
own `colorbars.c` sample uses exactly this pattern with 15 slots. This recipe
|
|
178
|
+
uses 15 bars plus a reset slot: 16, the whole table.
|
|
179
|
+
|
|
180
|
+
The earlier version of this recipe used 16 bars plus the reset slot.
|
|
181
|
+
`rirq_set(16, ...)` wrote one entry past a 16-entry table, the program fell
|
|
182
|
+
back to BASIC with no bars drawn, and nothing reported an error: there is no
|
|
183
|
+
bounds check in `rirq_set`. A `#define NUM_IRQS 17` at the top of the main
|
|
184
|
+
file does not fix it either, and that was tried: `rasterirq.c` is compiled
|
|
185
|
+
as its own translation unit through the header's `#pragma compile`, so it
|
|
186
|
+
sees the default 16 while the main file believes 17. To change the table
|
|
187
|
+
size, pass `-dNUM_IRQS=17` on the command line so every unit agrees, or stay
|
|
188
|
+
within 16.
|
|
189
|
+
|
|
190
|
+
Each `RIRQCode` holds two write slots (border and background). Two writes per
|
|
191
|
+
slot consume 8 cycles (`STY abs` then `STX abs`, 4 cycles each). With
|
|
192
|
+
`BAR_HEIGHT = 13`, there are 13 raster lines between each consecutive pair of
|
|
193
|
+
slots (this section said 12 while the listing said 13; 13 is what the code
|
|
194
|
+
builds and what the render shows), giving the dispatcher ample time to exit
|
|
195
|
+
one IRQ and enter the next. The minimum safe gap between two slots is
|
|
196
|
+
approximately 4-5 raster lines on PAL, accounting for IRQ entry/exit
|
|
197
|
+
overhead; that figure is an estimate and was not measured here.
|
|
198
|
+
|
|
199
|
+
### `rirq_data` for animation without rebuilding
|
|
200
|
+
|
|
201
|
+
`rirq_data(&bars[i], slot, byte)` patches only the data byte of write slot
|
|
202
|
+
`slot` inside an existing `RIRQCode`. This is cheaper than calling `rirq_write`
|
|
203
|
+
because it does not touch the target address. For animation where only the color
|
|
204
|
+
value changes each frame — as in the cycling palette here — `rirq_data` is the
|
|
205
|
+
correct tool. The address half of each slot (pointing at `$D020` and `$D021`)
|
|
206
|
+
never changes; only the color index rotates.
|
|
207
|
+
|
|
208
|
+
### D020 vs D021: border and background
|
|
209
|
+
|
|
210
|
+
$D020 is the border color. It governs the colored region outside the active
|
|
211
|
+
display window. $D021 is background color 0, which fills the background of
|
|
212
|
+
each character cell in standard text mode (and all cells in blank/space
|
|
213
|
+
characters). Writing both registers to the same color makes the entire visible
|
|
214
|
+
area — border and display — appear as a solid horizontal band. Writing only
|
|
215
|
+
$D020 would color the border stripe while leaving the display interior at its
|
|
216
|
+
previous background color, useful for thinner decorative bars. Writing only
|
|
217
|
+
$D021 would change the display area interior without touching the border.
|
|
218
|
+
|
|
219
|
+
### Badline interaction
|
|
220
|
+
|
|
221
|
+
Badlines occur every 8 raster lines on PAL (when the low 3 bits of the raster
|
|
222
|
+
counter match YSCROLL, default 3). On a badline the VIC-II takes the bus for
|
|
223
|
+
cycles 15-54 and pulls BA low on cycle 12, so the CPU loses 40-43 cycles;
|
|
224
|
+
plan on 43 (this text said a flat 40; see `docs/pitfalls/raster-and-badline.md`).
|
|
225
|
+
For this recipe the poll loop exits in cycles 1-7 of the target line and the
|
|
226
|
+
6510 is halted at its first read after BA has been low for three cycles, so
|
|
227
|
+
a write that has not completed by cycle 14 waits until cycle 55 or later —
|
|
228
|
+
after the display window, and in the right border. The standard defense is
|
|
229
|
+
to target splits at non-badline rows. With `FIRST_LINE = 51` and
|
|
230
|
+
`BAR_HEIGHT = 13` that is not fully possible: 13 is coprime to 8, so the
|
|
231
|
+
fifteen boundaries cover every residue and two of them are badlines whatever
|
|
232
|
+
`FIRST_LINE` is chosen — with 51, the bars starting on lines 51 and 155
|
|
233
|
+
(this text used to say
|
|
234
|
+
`BAR_HEIGHT = 12` and "the visual result is clean"; the render shows the
|
|
235
|
+
background write landing late on both lines, and on line 51 the border
|
|
236
|
+
write too in one of two runs). A bar height that is a multiple of 8 keeps
|
|
237
|
+
every boundary on one residue so a single `FIRST_LINE` clears them all. For
|
|
238
|
+
pixel-perfect bar boundaries on any line, use the cycle-exact double-IRQ
|
|
239
|
+
technique described in `docs/techniques/raster.md`.
|