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,1014 @@
|
|
|
1
|
+
---
|
|
2
|
+
recipe: sqrt-atan2
|
|
3
|
+
toolchain: kickassembler
|
|
4
|
+
output_format: PRG
|
|
5
|
+
region: both
|
|
6
|
+
techniques: [isqrt_16bit, atan2_8bit]
|
|
7
|
+
file_formats: [PRG]
|
|
8
|
+
uses_registers: [DC04, DC05, DC0D, DC0E, D011, D012, D020, D021]
|
|
9
|
+
uses_kernal: []
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<!-- doc-type: recipe -->
|
|
13
|
+
|
|
14
|
+
# KickAssembler — Integer square root and 8-bit atan2, checked against a host model and timed over every input
|
|
15
|
+
|
|
16
|
+
## Synopsis
|
|
17
|
+
|
|
18
|
+
Two routines a game needs for distance and aim: `isqrt16`, the integer
|
|
19
|
+
square root of a 16-bit value with an 8-bit result, by restoring
|
|
20
|
+
shift-and-subtract; and `atan2_8`, the angle of a signed 8-bit `(dx, dy)`
|
|
21
|
+
in 256ths of a turn, by folding to the first octant, an eight-pass divide
|
|
22
|
+
for the ratio and a 256-byte arctangent table. The program checks 35
|
|
23
|
+
square roots (0, 1, 65535, perfect squares and their neighbours) and 36
|
|
24
|
+
angles (both axes in both directions, every octant, the diagonals, the
|
|
25
|
+
three worst pairs the host model found) against expected values compiled
|
|
26
|
+
in from the Python script below, then times every one of the 65,536
|
|
27
|
+
inputs of each routine with CIA1 timer A and prints the worst body cost
|
|
28
|
+
and the input that produced it. For the square root it also checks
|
|
29
|
+
`rem <= 2 * root` on every input, which is `n < (root + 1)^2`. It writes
|
|
30
|
+
`$01` to `$02FF` and turns the border green when every case is within
|
|
31
|
+
tolerance (0 for the root, 1 angle unit for atan2), `$02` and red
|
|
32
|
+
otherwise. The techniques are `isqrt_16bit` and `atan2_8bit` in
|
|
33
|
+
`techniques/maths.md`.
|
|
34
|
+
|
|
35
|
+
Angle convention: 0 is `+dx` (right), 64 is `+dy` (down on a screen whose
|
|
36
|
+
y grows downward), 128 is `-dx`, 192 is `-dy`; the exact value is
|
|
37
|
+
`round(atan2(dy, dx) * 256 / 2pi) mod 256`.
|
|
38
|
+
|
|
39
|
+
## Source
|
|
40
|
+
|
|
41
|
+
```asm
|
|
42
|
+
// sqrt-atan2.asm
|
|
43
|
+
// Integer square root of a 16-bit value (8-bit result) by shift-and-subtract,
|
|
44
|
+
// and an 8-bit atan2 (signed 8-bit dx, dy in; angle 0-255 out) by octant
|
|
45
|
+
// folding, an 8-pass divide for the ratio and a 256-byte arctangent table.
|
|
46
|
+
// Both are checked against compiled-in expected values from a Python model
|
|
47
|
+
// (the generator is quoted on the page), every input of each routine is timed
|
|
48
|
+
// with CIA1 timer A, and the largest body cost of each routine is printed.
|
|
49
|
+
// Verdict: $02FF = $01 and a green border when every case is within
|
|
50
|
+
// tolerance, $02 and red otherwise.
|
|
51
|
+
//
|
|
52
|
+
// Angle convention: 0 = +dx (right), 64 = +dy (down on a screen whose y grows
|
|
53
|
+
// downward), 128 = -dx, 192 = -dy. Exact value = round(atan2(dy, dx) * 256 / 2pi).
|
|
54
|
+
.encoding "screencode_upper"
|
|
55
|
+
|
|
56
|
+
.const SCREEN = $0400
|
|
57
|
+
.const COLRAM = $d800
|
|
58
|
+
.const RESULT = $02ff
|
|
59
|
+
.const SQ_TOL = 0 // isqrt must be exact
|
|
60
|
+
.const AT_TOL = 1 // atan2 within one angle unit (1/256 turn)
|
|
61
|
+
.const NSQ = 35 // check cases, from the generator
|
|
62
|
+
.const NAT = 36
|
|
63
|
+
|
|
64
|
+
// zero page scratch; the program never returns to BASIC
|
|
65
|
+
.const num = $f7 // isqrt input, shifted out (2 bytes)
|
|
66
|
+
.const rem = $f9 // isqrt remainder (2 bytes)
|
|
67
|
+
.const root = $fb // isqrt result
|
|
68
|
+
.const trial = $fc // isqrt trial subtrahend (2 bytes)
|
|
69
|
+
.const arg_dx = $02 // atan2 inputs
|
|
70
|
+
.const arg_dy = $03
|
|
71
|
+
.const ax = $04 // |dx|, |dy|
|
|
72
|
+
.const ay = $05
|
|
73
|
+
.const quo = $06 // divide quotient / table index
|
|
74
|
+
.const angle = $07 // atan2 result
|
|
75
|
+
.const tmp = $08
|
|
76
|
+
.const zp_val = $09 // 16-bit value for the decimal printer
|
|
77
|
+
.const zp_row = $0b // screen pointer for the printers (2 bytes)
|
|
78
|
+
.const cyc = $0d // last measured cycle count (2 bytes)
|
|
79
|
+
.const str_ptr = $0f // string pointer for print_str (2 bytes)
|
|
80
|
+
.const chk = $11 // 2 * root for the remainder invariant (2 bytes)
|
|
81
|
+
.const n_cnt = $13 // sweep counter (2 bytes)
|
|
82
|
+
|
|
83
|
+
BasicUpstart2(start)
|
|
84
|
+
|
|
85
|
+
start:
|
|
86
|
+
sei
|
|
87
|
+
lda #$7f
|
|
88
|
+
sta $dc0d // no CIA1 interrupts
|
|
89
|
+
lda $dc0d
|
|
90
|
+
lda #0
|
|
91
|
+
sta $d020
|
|
92
|
+
sta $d021
|
|
93
|
+
jsr clear_screen
|
|
94
|
+
lda $d011
|
|
95
|
+
and #%11101111 // DEN off: VIC samples it on line $30, so the
|
|
96
|
+
sta $d011 // badlines stop from the next frame on
|
|
97
|
+
jsr wait_line255
|
|
98
|
+
jsr wait_line255
|
|
99
|
+
jsr time_empty // jsr/rts and timer overhead, measured once
|
|
100
|
+
|
|
101
|
+
ldy #0
|
|
102
|
+
ldx #<txt_hdr
|
|
103
|
+
lda #>txt_hdr
|
|
104
|
+
jsr print_str
|
|
105
|
+
|
|
106
|
+
// ---------- isqrt cases ----------
|
|
107
|
+
lda #0
|
|
108
|
+
sta sq_fail
|
|
109
|
+
sta sq_maxerr
|
|
110
|
+
ldx #0
|
|
111
|
+
sq_loop:
|
|
112
|
+
stx case_idx
|
|
113
|
+
lda sq_in_lo,x
|
|
114
|
+
sta num
|
|
115
|
+
lda sq_in_hi,x
|
|
116
|
+
sta num+1
|
|
117
|
+
jsr isqrt16
|
|
118
|
+
ldx case_idx
|
|
119
|
+
lda root
|
|
120
|
+
sec
|
|
121
|
+
sbc sq_exp,x
|
|
122
|
+
bcs !+
|
|
123
|
+
eor #$ff // negate: |root - expected|
|
|
124
|
+
adc #1
|
|
125
|
+
!: cmp sq_maxerr
|
|
126
|
+
bcc !+
|
|
127
|
+
sta sq_maxerr
|
|
128
|
+
!: cmp #SQ_TOL+1
|
|
129
|
+
bcc !+
|
|
130
|
+
inc sq_fail
|
|
131
|
+
!: inx
|
|
132
|
+
cpx #NSQ
|
|
133
|
+
bne sq_loop
|
|
134
|
+
|
|
135
|
+
// ---------- atan2 cases ----------
|
|
136
|
+
lda #0
|
|
137
|
+
sta at_fail
|
|
138
|
+
sta at_maxerr
|
|
139
|
+
ldx #0
|
|
140
|
+
at_loop:
|
|
141
|
+
stx case_idx
|
|
142
|
+
lda at_dx,x
|
|
143
|
+
sta arg_dx
|
|
144
|
+
lda at_dy,x
|
|
145
|
+
sta arg_dy
|
|
146
|
+
jsr atan2_8
|
|
147
|
+
ldx case_idx
|
|
148
|
+
lda angle
|
|
149
|
+
sec
|
|
150
|
+
sbc at_exp,x // difference modulo 256
|
|
151
|
+
cmp #$80
|
|
152
|
+
bcc !+
|
|
153
|
+
eor #$ff // wrap: 255 -> 1
|
|
154
|
+
clc
|
|
155
|
+
adc #1
|
|
156
|
+
!: cmp at_maxerr
|
|
157
|
+
bcc !+
|
|
158
|
+
sta at_maxerr
|
|
159
|
+
!: cmp #AT_TOL+1
|
|
160
|
+
bcc !+
|
|
161
|
+
inc at_fail
|
|
162
|
+
!: inx
|
|
163
|
+
cpx #NAT
|
|
164
|
+
bne at_loop
|
|
165
|
+
|
|
166
|
+
// ---------- isqrt sweep: every input, timed, remainder invariant ----------
|
|
167
|
+
lda #0
|
|
168
|
+
sta n_cnt
|
|
169
|
+
sta n_cnt+1
|
|
170
|
+
sta sq_maxcyc
|
|
171
|
+
sta sq_maxcyc+1
|
|
172
|
+
sta inv_fail
|
|
173
|
+
sta inv_fail+1
|
|
174
|
+
sw_sq:
|
|
175
|
+
lda n_cnt
|
|
176
|
+
sta num
|
|
177
|
+
lda n_cnt+1
|
|
178
|
+
sta num+1
|
|
179
|
+
jsr time_isqrt
|
|
180
|
+
lda cyc+1
|
|
181
|
+
cmp sq_maxcyc+1
|
|
182
|
+
bcc sw_sq_inv
|
|
183
|
+
bne sw_sq_new
|
|
184
|
+
lda cyc
|
|
185
|
+
cmp sq_maxcyc
|
|
186
|
+
bcc sw_sq_inv
|
|
187
|
+
beq sw_sq_inv // keep the first input that reached the max
|
|
188
|
+
sw_sq_new:
|
|
189
|
+
lda cyc
|
|
190
|
+
sta sq_maxcyc
|
|
191
|
+
lda cyc+1
|
|
192
|
+
sta sq_maxcyc+1
|
|
193
|
+
lda n_cnt
|
|
194
|
+
sta sq_maxarg
|
|
195
|
+
lda n_cnt+1
|
|
196
|
+
sta sq_maxarg+1
|
|
197
|
+
sw_sq_inv:
|
|
198
|
+
lda root // n < (root + 1)^2 <=> rem <= 2 * root
|
|
199
|
+
asl
|
|
200
|
+
sta chk
|
|
201
|
+
lda #0
|
|
202
|
+
rol
|
|
203
|
+
sta chk+1
|
|
204
|
+
lda chk
|
|
205
|
+
cmp rem
|
|
206
|
+
lda chk+1
|
|
207
|
+
sbc rem+1
|
|
208
|
+
bcs !+
|
|
209
|
+
inc inv_fail
|
|
210
|
+
bne !+
|
|
211
|
+
inc inv_fail+1
|
|
212
|
+
!: inc n_cnt
|
|
213
|
+
bne sw_sq
|
|
214
|
+
inc n_cnt+1
|
|
215
|
+
bne sw_sq
|
|
216
|
+
|
|
217
|
+
// ---------- atan2 sweep: every (dx, dy) pair, timed ----------
|
|
218
|
+
lda #0
|
|
219
|
+
sta at_maxcyc
|
|
220
|
+
sta at_maxcyc+1
|
|
221
|
+
sta arg_dx
|
|
222
|
+
sw_at_x:
|
|
223
|
+
lda #0
|
|
224
|
+
sta arg_dy
|
|
225
|
+
sw_at_y:
|
|
226
|
+
jsr time_atan2
|
|
227
|
+
lda cyc+1
|
|
228
|
+
cmp at_maxcyc+1
|
|
229
|
+
bcc sw_at_next
|
|
230
|
+
bne sw_at_new
|
|
231
|
+
lda cyc
|
|
232
|
+
cmp at_maxcyc
|
|
233
|
+
bcc sw_at_next
|
|
234
|
+
beq sw_at_next
|
|
235
|
+
sw_at_new:
|
|
236
|
+
lda cyc
|
|
237
|
+
sta at_maxcyc
|
|
238
|
+
lda cyc+1
|
|
239
|
+
sta at_maxcyc+1
|
|
240
|
+
lda arg_dx
|
|
241
|
+
sta at_maxarg
|
|
242
|
+
lda arg_dy
|
|
243
|
+
sta at_maxarg+1
|
|
244
|
+
sw_at_next:
|
|
245
|
+
inc arg_dy
|
|
246
|
+
bne sw_at_y
|
|
247
|
+
inc arg_dx
|
|
248
|
+
bne sw_at_x
|
|
249
|
+
|
|
250
|
+
// ---------- report ----------
|
|
251
|
+
ldy #2
|
|
252
|
+
ldx #<txt_sq
|
|
253
|
+
lda #>txt_sq
|
|
254
|
+
jsr print_str
|
|
255
|
+
lda #NSQ
|
|
256
|
+
ldx #12
|
|
257
|
+
ldy #2
|
|
258
|
+
jsr print_dec3
|
|
259
|
+
lda sq_maxerr
|
|
260
|
+
ldx #25
|
|
261
|
+
ldy #2
|
|
262
|
+
jsr print_dec3
|
|
263
|
+
lda sq_fail
|
|
264
|
+
ldx #35
|
|
265
|
+
ldy #2
|
|
266
|
+
jsr print_dec3
|
|
267
|
+
|
|
268
|
+
ldy #3
|
|
269
|
+
ldx #<txt_at
|
|
270
|
+
lda #>txt_at
|
|
271
|
+
jsr print_str
|
|
272
|
+
lda #NAT
|
|
273
|
+
ldx #12
|
|
274
|
+
ldy #3
|
|
275
|
+
jsr print_dec3
|
|
276
|
+
lda at_maxerr
|
|
277
|
+
ldx #25
|
|
278
|
+
ldy #3
|
|
279
|
+
jsr print_dec3
|
|
280
|
+
lda at_fail
|
|
281
|
+
ldx #35
|
|
282
|
+
ldy #3
|
|
283
|
+
jsr print_dec3
|
|
284
|
+
|
|
285
|
+
ldy #5
|
|
286
|
+
ldx #<txt_cyc
|
|
287
|
+
lda #>txt_cyc
|
|
288
|
+
jsr print_str
|
|
289
|
+
ldy #6
|
|
290
|
+
ldx #<txt_cyc_sq
|
|
291
|
+
lda #>txt_cyc_sq
|
|
292
|
+
jsr print_str
|
|
293
|
+
lda sq_maxcyc
|
|
294
|
+
sta zp_val
|
|
295
|
+
lda sq_maxcyc+1
|
|
296
|
+
sta zp_val+1
|
|
297
|
+
ldx #20
|
|
298
|
+
ldy #6
|
|
299
|
+
jsr print_dec5
|
|
300
|
+
lda sq_maxarg
|
|
301
|
+
sta zp_val
|
|
302
|
+
lda sq_maxarg+1
|
|
303
|
+
sta zp_val+1
|
|
304
|
+
ldx #30
|
|
305
|
+
ldy #6
|
|
306
|
+
jsr print_dec5
|
|
307
|
+
ldy #7
|
|
308
|
+
ldx #<txt_cyc_at
|
|
309
|
+
lda #>txt_cyc_at
|
|
310
|
+
jsr print_str
|
|
311
|
+
lda at_maxcyc
|
|
312
|
+
sta zp_val
|
|
313
|
+
lda at_maxcyc+1
|
|
314
|
+
sta zp_val+1
|
|
315
|
+
ldx #20
|
|
316
|
+
ldy #7
|
|
317
|
+
jsr print_dec5
|
|
318
|
+
lda at_maxarg
|
|
319
|
+
ldx #30
|
|
320
|
+
ldy #7
|
|
321
|
+
jsr print_hex2
|
|
322
|
+
lda at_maxarg+1
|
|
323
|
+
ldx #34
|
|
324
|
+
ldy #7
|
|
325
|
+
jsr print_hex2
|
|
326
|
+
ldy #8
|
|
327
|
+
ldx #<txt_inv
|
|
328
|
+
lda #>txt_inv
|
|
329
|
+
jsr print_str
|
|
330
|
+
lda inv_fail
|
|
331
|
+
sta zp_val
|
|
332
|
+
lda inv_fail+1
|
|
333
|
+
sta zp_val+1
|
|
334
|
+
ldx #30
|
|
335
|
+
ldy #8
|
|
336
|
+
jsr print_dec5
|
|
337
|
+
|
|
338
|
+
// sample results on one line each: sqrt(65535), atan2(10,3)
|
|
339
|
+
ldy #9
|
|
340
|
+
ldx #<txt_s1
|
|
341
|
+
lda #>txt_s1
|
|
342
|
+
jsr print_str
|
|
343
|
+
lda #$ff
|
|
344
|
+
sta num
|
|
345
|
+
sta num+1
|
|
346
|
+
jsr isqrt16
|
|
347
|
+
lda root
|
|
348
|
+
ldx #20
|
|
349
|
+
ldy #9
|
|
350
|
+
jsr print_dec3
|
|
351
|
+
ldy #10
|
|
352
|
+
ldx #<txt_s2
|
|
353
|
+
lda #>txt_s2
|
|
354
|
+
jsr print_str
|
|
355
|
+
lda #10
|
|
356
|
+
sta arg_dx
|
|
357
|
+
lda #3
|
|
358
|
+
sta arg_dy
|
|
359
|
+
jsr atan2_8
|
|
360
|
+
lda angle
|
|
361
|
+
ldx #20
|
|
362
|
+
ldy #10
|
|
363
|
+
jsr print_dec3
|
|
364
|
+
|
|
365
|
+
lda $d011
|
|
366
|
+
ora #%00010000 // DEN back on for the picture
|
|
367
|
+
sta $d011
|
|
368
|
+
|
|
369
|
+
// ---------- verdict ----------
|
|
370
|
+
lda sq_fail
|
|
371
|
+
ora at_fail
|
|
372
|
+
bne fail
|
|
373
|
+
lda #1
|
|
374
|
+
sta RESULT
|
|
375
|
+
lda #5
|
|
376
|
+
sta $d020
|
|
377
|
+
ldy #12
|
|
378
|
+
ldx #<txt_pass
|
|
379
|
+
lda #>txt_pass
|
|
380
|
+
jsr print_str
|
|
381
|
+
jmp forever
|
|
382
|
+
fail:
|
|
383
|
+
lda #2
|
|
384
|
+
sta RESULT
|
|
385
|
+
sta $d020
|
|
386
|
+
ldy #12
|
|
387
|
+
ldx #<txt_fail
|
|
388
|
+
lda #>txt_fail
|
|
389
|
+
jsr print_str
|
|
390
|
+
forever:
|
|
391
|
+
jmp forever
|
|
392
|
+
|
|
393
|
+
// ============================================================
|
|
394
|
+
// isqrt16: root = floor(sqrt(num)), num is destroyed, rem = num - root*root.
|
|
395
|
+
// Restoring shift-and-subtract, two input bits per pass, eight passes.
|
|
396
|
+
// Both routines sit in one page so no taken branch pays a page-crossing
|
|
397
|
+
// cycle; the assert below fails the build if a change pushes them over.
|
|
398
|
+
// ============================================================
|
|
399
|
+
.align $100
|
|
400
|
+
isqrt16:
|
|
401
|
+
lda #0
|
|
402
|
+
sta root
|
|
403
|
+
sta rem
|
|
404
|
+
sta rem+1
|
|
405
|
+
ldx #8
|
|
406
|
+
sq_pass:
|
|
407
|
+
asl num // bring down the next two bits of num
|
|
408
|
+
rol num+1
|
|
409
|
+
rol rem
|
|
410
|
+
rol rem+1
|
|
411
|
+
asl num
|
|
412
|
+
rol num+1
|
|
413
|
+
rol rem
|
|
414
|
+
rol rem+1
|
|
415
|
+
lda root // trial = 4 * root + 1; root = 2 * root
|
|
416
|
+
asl
|
|
417
|
+
sta root
|
|
418
|
+
asl
|
|
419
|
+
ora #1
|
|
420
|
+
sta trial
|
|
421
|
+
lda #0
|
|
422
|
+
rol // carry out of the second asl is bit 8 of trial
|
|
423
|
+
sta trial+1
|
|
424
|
+
lda rem+1 // if rem >= trial: rem -= trial, root |= 1
|
|
425
|
+
cmp trial+1
|
|
426
|
+
bcc sq_next
|
|
427
|
+
bne sq_sub
|
|
428
|
+
lda rem
|
|
429
|
+
cmp trial
|
|
430
|
+
bcc sq_next
|
|
431
|
+
sq_sub:
|
|
432
|
+
lda rem
|
|
433
|
+
sbc trial // carry is set on both paths into sq_sub
|
|
434
|
+
sta rem
|
|
435
|
+
lda rem+1
|
|
436
|
+
sbc trial+1
|
|
437
|
+
sta rem+1
|
|
438
|
+
inc root
|
|
439
|
+
sq_next:
|
|
440
|
+
dex
|
|
441
|
+
bne sq_pass
|
|
442
|
+
rts
|
|
443
|
+
|
|
444
|
+
// ============================================================
|
|
445
|
+
// atan2_8: angle = atan2(arg_dy, arg_dx) in 1/256 turn, 0 for (0, 0).
|
|
446
|
+
// Fold to the first octant on the sign bits and a magnitude compare,
|
|
447
|
+
// index the table with floor(min * 256 / max) from an 8-pass divide,
|
|
448
|
+
// then unfold: 64 - a across the diagonal, 128 - a for dx < 0, -a for dy < 0.
|
|
449
|
+
// ============================================================
|
|
450
|
+
atan2_8:
|
|
451
|
+
lda arg_dx
|
|
452
|
+
bpl !+ // sign from bit 7 of the input, no subtract involved
|
|
453
|
+
eor #$ff
|
|
454
|
+
clc
|
|
455
|
+
adc #1
|
|
456
|
+
!: sta ax // 0..128 as an unsigned byte
|
|
457
|
+
lda arg_dy
|
|
458
|
+
bpl !+
|
|
459
|
+
eor #$ff
|
|
460
|
+
clc
|
|
461
|
+
adc #1
|
|
462
|
+
!: sta ay
|
|
463
|
+
ora ax
|
|
464
|
+
bne !+
|
|
465
|
+
sta angle // both zero: angle 0, nothing to divide by
|
|
466
|
+
rts
|
|
467
|
+
!: lda ay
|
|
468
|
+
cmp ax
|
|
469
|
+
beq at_diag
|
|
470
|
+
bcc at_low // ay < ax: first octant, ratio ay / ax
|
|
471
|
+
lda ax // ay > ax: second octant, ratio ax / ay
|
|
472
|
+
ldx ay
|
|
473
|
+
jsr ratio_div
|
|
474
|
+
lda #64
|
|
475
|
+
sec
|
|
476
|
+
sbc quo
|
|
477
|
+
jmp at_fold
|
|
478
|
+
at_diag:
|
|
479
|
+
lda #32
|
|
480
|
+
bne at_fold
|
|
481
|
+
at_low:
|
|
482
|
+
lda ay
|
|
483
|
+
ldx ax
|
|
484
|
+
jsr ratio_div
|
|
485
|
+
lda quo
|
|
486
|
+
at_fold:
|
|
487
|
+
bit arg_dx
|
|
488
|
+
bpl !+
|
|
489
|
+
eor #$ff // 128 - a == -(a) + 128 == (a ^ $ff) + 129
|
|
490
|
+
clc
|
|
491
|
+
adc #129
|
|
492
|
+
!: bit arg_dy
|
|
493
|
+
bpl !+
|
|
494
|
+
eor #$ff // 256 - a == (a ^ $ff) + 1
|
|
495
|
+
clc
|
|
496
|
+
adc #1
|
|
497
|
+
!: sta angle
|
|
498
|
+
rts
|
|
499
|
+
|
|
500
|
+
// ratio_div: quo = atan_tab[ floor(A * 256 / X) ], A < X <= 128.
|
|
501
|
+
// Eight shift-and-subtract passes; the remainder starts as A and stays below
|
|
502
|
+
// X, so its doubled value fits a byte and no ninth-bit test is needed.
|
|
503
|
+
ratio_div:
|
|
504
|
+
stx tmp
|
|
505
|
+
sta rem // remainder starts at the numerator
|
|
506
|
+
lda #0
|
|
507
|
+
sta quo
|
|
508
|
+
ldx #8
|
|
509
|
+
rd_pass:
|
|
510
|
+
asl quo // shift a zero dividend bit up into the remainder
|
|
511
|
+
rol rem
|
|
512
|
+
lda rem
|
|
513
|
+
cmp tmp
|
|
514
|
+
bcc rd_next
|
|
515
|
+
sbc tmp // carry set by the compare
|
|
516
|
+
sta rem
|
|
517
|
+
inc quo
|
|
518
|
+
rd_next:
|
|
519
|
+
dex
|
|
520
|
+
bne rd_pass
|
|
521
|
+
ldx quo
|
|
522
|
+
lda atan_tab,x
|
|
523
|
+
sta quo
|
|
524
|
+
rts
|
|
525
|
+
routines_end:
|
|
526
|
+
.assert "isqrt16 and atan2_8 share one page", >isqrt16, >routines_end
|
|
527
|
+
|
|
528
|
+
// ============================================================
|
|
529
|
+
// timing: CIA1 timer A, one-shot, force-loaded from $FFFF, display off so
|
|
530
|
+
// no badline steals cycles. cyc = body cycles: jsr, rts and the timer
|
|
531
|
+
// start/stop overhead are measured with an empty routine and subtracted.
|
|
532
|
+
// ============================================================
|
|
533
|
+
time_isqrt:
|
|
534
|
+
lda #$ff
|
|
535
|
+
sta $dc04
|
|
536
|
+
sta $dc05
|
|
537
|
+
lda #%00011001 // load, one-shot, start
|
|
538
|
+
sta $dc0e
|
|
539
|
+
jsr isqrt16
|
|
540
|
+
lda #0
|
|
541
|
+
sta $dc0e
|
|
542
|
+
jmp time_finish
|
|
543
|
+
|
|
544
|
+
time_atan2:
|
|
545
|
+
lda #$ff
|
|
546
|
+
sta $dc04
|
|
547
|
+
sta $dc05
|
|
548
|
+
lda #%00011001
|
|
549
|
+
sta $dc0e
|
|
550
|
+
jsr atan2_8
|
|
551
|
+
lda #0
|
|
552
|
+
sta $dc0e
|
|
553
|
+
jmp time_finish
|
|
554
|
+
|
|
555
|
+
time_empty:
|
|
556
|
+
lda #$ff
|
|
557
|
+
sta $dc04
|
|
558
|
+
sta $dc05
|
|
559
|
+
lda #%00011001
|
|
560
|
+
sta $dc0e
|
|
561
|
+
jsr empty_rts
|
|
562
|
+
lda #0
|
|
563
|
+
sta $dc0e
|
|
564
|
+
lda $dc04
|
|
565
|
+
sta empty_lo
|
|
566
|
+
lda $dc05
|
|
567
|
+
sta empty_hi
|
|
568
|
+
rts
|
|
569
|
+
|
|
570
|
+
empty_rts:
|
|
571
|
+
rts
|
|
572
|
+
|
|
573
|
+
time_finish:
|
|
574
|
+
// cyc = ($FFFF - timer) - ($FFFF - empty) = empty - timer
|
|
575
|
+
lda empty_lo
|
|
576
|
+
sec
|
|
577
|
+
sbc $dc04
|
|
578
|
+
sta cyc
|
|
579
|
+
lda empty_hi
|
|
580
|
+
sbc $dc05
|
|
581
|
+
sta cyc+1
|
|
582
|
+
rts
|
|
583
|
+
|
|
584
|
+
// wait_line255: returns just after raster line 255 has passed, so two calls
|
|
585
|
+
// span a whole frame and the VIC has seen DEN clear on line $30.
|
|
586
|
+
wait_line255:
|
|
587
|
+
lda #$ff
|
|
588
|
+
!: cmp $d012
|
|
589
|
+
bne !-
|
|
590
|
+
!: cmp $d012
|
|
591
|
+
beq !-
|
|
592
|
+
rts
|
|
593
|
+
|
|
594
|
+
// ============================================================
|
|
595
|
+
// screen helpers
|
|
596
|
+
// ============================================================
|
|
597
|
+
clear_screen:
|
|
598
|
+
ldx #0
|
|
599
|
+
lda #$20
|
|
600
|
+
!: sta SCREEN,x
|
|
601
|
+
sta SCREEN+$100,x
|
|
602
|
+
sta SCREEN+$200,x
|
|
603
|
+
sta SCREEN+$300,x
|
|
604
|
+
inx
|
|
605
|
+
bne !-
|
|
606
|
+
lda #1
|
|
607
|
+
!: sta COLRAM,x
|
|
608
|
+
sta COLRAM+$100,x
|
|
609
|
+
sta COLRAM+$200,x
|
|
610
|
+
sta COLRAM+$300,x
|
|
611
|
+
inx
|
|
612
|
+
bne !-
|
|
613
|
+
rts
|
|
614
|
+
|
|
615
|
+
// set_row: Y = row; zp_row = SCREEN + 40 * Y. Preserves X and A.
|
|
616
|
+
set_row:
|
|
617
|
+
pha
|
|
618
|
+
lda row_lo,y
|
|
619
|
+
sta zp_row
|
|
620
|
+
lda row_hi,y
|
|
621
|
+
sta zp_row+1
|
|
622
|
+
pla
|
|
623
|
+
rts
|
|
624
|
+
|
|
625
|
+
// print_str: X/A = string address (lo/hi), Y = row, zero-terminated, column 0
|
|
626
|
+
print_str:
|
|
627
|
+
stx str_ptr
|
|
628
|
+
sta str_ptr+1
|
|
629
|
+
jsr set_row
|
|
630
|
+
ldy #0
|
|
631
|
+
!: lda (str_ptr),y
|
|
632
|
+
beq !+
|
|
633
|
+
sta (zp_row),y
|
|
634
|
+
iny
|
|
635
|
+
bne !-
|
|
636
|
+
!: rts
|
|
637
|
+
|
|
638
|
+
// print_hex2: A = byte, X = column, Y = row. Two hex digits.
|
|
639
|
+
print_hex2:
|
|
640
|
+
pha
|
|
641
|
+
jsr set_row
|
|
642
|
+
txa
|
|
643
|
+
clc
|
|
644
|
+
adc zp_row
|
|
645
|
+
sta zp_row
|
|
646
|
+
bcc !+
|
|
647
|
+
inc zp_row+1
|
|
648
|
+
!: pla
|
|
649
|
+
pha
|
|
650
|
+
lsr
|
|
651
|
+
lsr
|
|
652
|
+
lsr
|
|
653
|
+
lsr
|
|
654
|
+
tax
|
|
655
|
+
lda hex_scr,x
|
|
656
|
+
ldy #0
|
|
657
|
+
sta (zp_row),y
|
|
658
|
+
pla
|
|
659
|
+
and #15
|
|
660
|
+
tax
|
|
661
|
+
lda hex_scr,x
|
|
662
|
+
iny
|
|
663
|
+
sta (zp_row),y
|
|
664
|
+
rts
|
|
665
|
+
hex_scr: .byte $30, $31, $32, $33, $34, $35, $36, $37, $38, $39, 1, 2, 3, 4, 5, 6
|
|
666
|
+
|
|
667
|
+
// print_dec3: A = byte, X = column, Y = row. Three digits, leading zeros.
|
|
668
|
+
print_dec3:
|
|
669
|
+
sta zp_val
|
|
670
|
+
lda #0
|
|
671
|
+
sta zp_val+1
|
|
672
|
+
jsr set_row
|
|
673
|
+
txa
|
|
674
|
+
clc
|
|
675
|
+
adc zp_row
|
|
676
|
+
sta zp_row
|
|
677
|
+
bcc !+
|
|
678
|
+
inc zp_row+1
|
|
679
|
+
!: ldx #2 // start at the hundreds
|
|
680
|
+
jmp dec_digits
|
|
681
|
+
|
|
682
|
+
// print_dec5: zp_val = 16-bit value, X = column, Y = row. Five digits.
|
|
683
|
+
print_dec5:
|
|
684
|
+
jsr set_row
|
|
685
|
+
txa
|
|
686
|
+
clc
|
|
687
|
+
adc zp_row
|
|
688
|
+
sta zp_row
|
|
689
|
+
bcc !+
|
|
690
|
+
inc zp_row+1
|
|
691
|
+
!: ldx #0
|
|
692
|
+
dec_digits:
|
|
693
|
+
ldy #0
|
|
694
|
+
dd_loop:
|
|
695
|
+
lda #$30
|
|
696
|
+
sta tmp
|
|
697
|
+
dd_sub:
|
|
698
|
+
lda zp_val
|
|
699
|
+
cmp pow_lo,x
|
|
700
|
+
lda zp_val+1
|
|
701
|
+
sbc pow_hi,x
|
|
702
|
+
bcc dd_put
|
|
703
|
+
lda zp_val
|
|
704
|
+
sbc pow_lo,x
|
|
705
|
+
sta zp_val
|
|
706
|
+
lda zp_val+1
|
|
707
|
+
sbc pow_hi,x
|
|
708
|
+
sta zp_val+1
|
|
709
|
+
inc tmp
|
|
710
|
+
bne dd_sub
|
|
711
|
+
dd_put:
|
|
712
|
+
lda tmp
|
|
713
|
+
sta (zp_row),y
|
|
714
|
+
iny
|
|
715
|
+
inx
|
|
716
|
+
cpx #5
|
|
717
|
+
bne dd_loop
|
|
718
|
+
rts
|
|
719
|
+
|
|
720
|
+
pow_lo: .byte <10000, <1000, <100, <10, <1
|
|
721
|
+
pow_hi: .byte >10000, >1000, >100, >10, >1
|
|
722
|
+
|
|
723
|
+
row_lo: .fill 25, <(SCREEN + 40 * i)
|
|
724
|
+
row_hi: .fill 25, >(SCREEN + 40 * i)
|
|
725
|
+
|
|
726
|
+
case_idx: .byte 0
|
|
727
|
+
sq_fail: .byte 0
|
|
728
|
+
sq_maxerr: .byte 0
|
|
729
|
+
sq_maxcyc: .word 0
|
|
730
|
+
sq_maxarg: .word 0
|
|
731
|
+
inv_fail: .word 0
|
|
732
|
+
at_fail: .byte 0
|
|
733
|
+
at_maxerr: .byte 0
|
|
734
|
+
at_maxcyc: .word 0
|
|
735
|
+
at_maxarg: .word 0
|
|
736
|
+
empty_lo: .byte 0
|
|
737
|
+
empty_hi: .byte 0
|
|
738
|
+
|
|
739
|
+
txt_hdr: .text "ISQRT16 AND ATAN2 8-BIT CHECK"
|
|
740
|
+
.byte 0
|
|
741
|
+
txt_sq: .text "SQRT CASES MAX ERR FAIL"
|
|
742
|
+
.byte 0
|
|
743
|
+
txt_at: .text "ATAN2 CASES MAX ERR FAIL"
|
|
744
|
+
.byte 0
|
|
745
|
+
txt_cyc: .text "WORST BODY CYCLES OVER EVERY INPUT:"
|
|
746
|
+
.byte 0
|
|
747
|
+
txt_cyc_sq: .text " ISQRT16 N="
|
|
748
|
+
.byte 0
|
|
749
|
+
txt_cyc_at: .text " ATAN2 $ $"
|
|
750
|
+
.byte 0
|
|
751
|
+
txt_inv: .text " REM<=2*ROOT FAILS OF 65536"
|
|
752
|
+
.byte 0
|
|
753
|
+
txt_s1: .text "SQRT(65535) ="
|
|
754
|
+
.byte 0
|
|
755
|
+
txt_s2: .text "ATAN2(10,3) ="
|
|
756
|
+
.byte 0
|
|
757
|
+
txt_pass: .text "RESULT: PASS"
|
|
758
|
+
.byte 0
|
|
759
|
+
txt_fail: .text "RESULT: FAIL"
|
|
760
|
+
.byte 0
|
|
761
|
+
|
|
762
|
+
// ---- generated by the Python script on the page ----
|
|
763
|
+
sq_in_lo:
|
|
764
|
+
.byte $00, $01, $02, $03, $04, $08, $09, $0f, $10, $11, $18, $19, $3f, $40, $41, $63
|
|
765
|
+
.byte $64, $79, $90, $ff, $00, $01, $e8, $00, $ff, $00, $10, $00, $ff, $00, $00, $01
|
|
766
|
+
.byte $02, $fe, $ff
|
|
767
|
+
sq_in_hi:
|
|
768
|
+
.byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
|
|
769
|
+
.byte $00, $00, $00, $00, $01, $01, $03, $04, $0f, $10, $27, $40, $7f, $80, $fe, $fe
|
|
770
|
+
.byte $fe, $ff, $ff
|
|
771
|
+
sq_exp:
|
|
772
|
+
.byte $00, $01, $01, $01, $02, $02, $03, $03, $04, $04, $04, $05, $07, $08, $08, $09
|
|
773
|
+
.byte $0a, $0b, $0c, $0f, $10, $10, $1f, $20, $3f, $40, $64, $80, $b5, $b5, $fe, $ff
|
|
774
|
+
.byte $ff, $ff, $ff
|
|
775
|
+
at_dx:
|
|
776
|
+
.byte $01, $00, $ff, $00, $7f, $00, $80, $00, $0a, $03, $fd, $f6, $f6, $fd, $03, $0a
|
|
777
|
+
.byte $05, $fb, $fb, $05, $7f, $80, $7f, $80, $01, $02, $01, $ff, $64, $c0, $2d, $88
|
|
778
|
+
.byte $00, $81, $81, $81
|
|
779
|
+
at_dy:
|
|
780
|
+
.byte $00, $01, $00, $ff, $00, $7f, $00, $80, $03, $0a, $0a, $03, $fd, $f6, $f6, $fd
|
|
781
|
+
.byte $05, $05, $fb, $fb, $7f, $80, $80, $7f, $01, $01, $02, $fe, $db, $14, $a6, $f9
|
|
782
|
+
.byte $00, $84, $8a, $95
|
|
783
|
+
at_exp:
|
|
784
|
+
.byte $00, $40, $80, $c0, $00, $40, $80, $c0, $0c, $34, $4c, $74, $8c, $b4, $cc, $f4
|
|
785
|
+
.byte $20, $60, $a0, $e0, $20, $a0, $e0, $60, $20, $13, $2d, $ad, $f2, $74, $d3, $82
|
|
786
|
+
.byte $00, $a0, $9f, $9d
|
|
787
|
+
.align $100
|
|
788
|
+
atan_tab:
|
|
789
|
+
.byte $00, $00, $00, $00, $01, $01, $01, $01, $01, $01, $02, $02, $02, $02, $02, $02
|
|
790
|
+
.byte $03, $03, $03, $03, $03, $03, $03, $04, $04, $04, $04, $04, $04, $05, $05, $05
|
|
791
|
+
.byte $05, $05, $05, $06, $06, $06, $06, $06, $06, $06, $07, $07, $07, $07, $07, $07
|
|
792
|
+
.byte $08, $08, $08, $08, $08, $08, $08, $09, $09, $09, $09, $09, $09, $0a, $0a, $0a
|
|
793
|
+
.byte $0a, $0a, $0a, $0a, $0b, $0b, $0b, $0b, $0b, $0b, $0b, $0c, $0c, $0c, $0c, $0c
|
|
794
|
+
.byte $0c, $0c, $0d, $0d, $0d, $0d, $0d, $0d, $0d, $0e, $0e, $0e, $0e, $0e, $0e, $0e
|
|
795
|
+
.byte $0f, $0f, $0f, $0f, $0f, $0f, $0f, $10, $10, $10, $10, $10, $10, $10, $11, $11
|
|
796
|
+
.byte $11, $11, $11, $11, $11, $11, $12, $12, $12, $12, $12, $12, $12, $13, $13, $13
|
|
797
|
+
.byte $13, $13, $13, $13, $13, $14, $14, $14, $14, $14, $14, $14, $14, $15, $15, $15
|
|
798
|
+
.byte $15, $15, $15, $15, $15, $15, $16, $16, $16, $16, $16, $16, $16, $16, $17, $17
|
|
799
|
+
.byte $17, $17, $17, $17, $17, $17, $17, $18, $18, $18, $18, $18, $18, $18, $18, $18
|
|
800
|
+
.byte $19, $19, $19, $19, $19, $19, $19, $19, $19, $19, $1a, $1a, $1a, $1a, $1a, $1a
|
|
801
|
+
.byte $1a, $1a, $1a, $1b, $1b, $1b, $1b, $1b, $1b, $1b, $1b, $1b, $1b, $1c, $1c, $1c
|
|
802
|
+
.byte $1c, $1c, $1c, $1c, $1c, $1c, $1c, $1c, $1d, $1d, $1d, $1d, $1d, $1d, $1d, $1d
|
|
803
|
+
.byte $1d, $1d, $1d, $1e, $1e, $1e, $1e, $1e, $1e, $1e, $1e, $1e, $1e, $1e, $1f, $1f
|
|
804
|
+
.byte $1f, $1f, $1f, $1f, $1f, $1f, $1f, $1f, $1f, $1f, $20, $20, $20, $20, $20, $20
|
|
805
|
+
```
|
|
806
|
+
|
|
807
|
+
## Build
|
|
808
|
+
|
|
809
|
+
```bash
|
|
810
|
+
java -jar $KICKASS_JAR sqrt-atan2.asm -o sqrt-atan2.prg
|
|
811
|
+
```
|
|
812
|
+
|
|
813
|
+
The table and the case bytes at the end of the listing were printed by
|
|
814
|
+
this script (Python 3, standard library). It also holds the integer model
|
|
815
|
+
of each routine and measures the model against `math.isqrt` and
|
|
816
|
+
`math.atan2` over every input; that measurement is what fixes the
|
|
817
|
+
tolerances and picks the three worst atan2 pairs for the case list.
|
|
818
|
+
|
|
819
|
+
```text
|
|
820
|
+
#!/usr/bin/env python3
|
|
821
|
+
# gen.py -- builds the atan table, models both routines exactly in integers,
|
|
822
|
+
# measures their error against math.isqrt / math.atan2 over every input, and
|
|
823
|
+
# prints the KickAssembler .byte lines for the table and the check cases.
|
|
824
|
+
import math
|
|
825
|
+
|
|
826
|
+
# ---- atan table: 256 entries, index r = floor(min * 256 / max), 0..255 ----
|
|
827
|
+
# value = round(atan(r / 256) * 256 / (2 pi)), 0..32
|
|
828
|
+
atan_tab = [round(math.atan(r / 256) * 256 / (2 * math.pi)) for r in range(256)]
|
|
829
|
+
assert max(atan_tab) <= 32 and min(atan_tab) == 0
|
|
830
|
+
|
|
831
|
+
# ---- integer model of the machine routine ----
|
|
832
|
+
def atan2_model(dx, dy):
|
|
833
|
+
ax, ay = abs(dx), abs(dy)
|
|
834
|
+
if ax == 0 and ay == 0:
|
|
835
|
+
return 0
|
|
836
|
+
if ay == ax:
|
|
837
|
+
a = 32
|
|
838
|
+
elif ay < ax:
|
|
839
|
+
a = atan_tab[(ay << 8) // ax]
|
|
840
|
+
else:
|
|
841
|
+
a = 64 - atan_tab[(ax << 8) // ay]
|
|
842
|
+
if dx < 0:
|
|
843
|
+
a = 128 - a
|
|
844
|
+
if dy < 0:
|
|
845
|
+
a = (256 - a) & 255
|
|
846
|
+
return a & 255
|
|
847
|
+
|
|
848
|
+
def atan2_exact(dx, dy):
|
|
849
|
+
return round(math.atan2(dy, dx) * 256 / (2 * math.pi)) % 256
|
|
850
|
+
|
|
851
|
+
def isqrt_model(n):
|
|
852
|
+
root = rem = 0
|
|
853
|
+
for i in range(8):
|
|
854
|
+
rem = (rem << 2) | ((n >> 14) & 3)
|
|
855
|
+
n = (n << 2) & 0xFFFF
|
|
856
|
+
trial = (root << 2) | 1
|
|
857
|
+
root <<= 1
|
|
858
|
+
if rem >= trial:
|
|
859
|
+
rem -= trial
|
|
860
|
+
root |= 1
|
|
861
|
+
return root
|
|
862
|
+
|
|
863
|
+
# ---- exhaustive error sweep ----
|
|
864
|
+
worst = 0
|
|
865
|
+
worst_pairs = []
|
|
866
|
+
for dx in range(-128, 128):
|
|
867
|
+
for dy in range(-128, 128):
|
|
868
|
+
e = (atan2_model(dx, dy) - atan2_exact(dx, dy)) % 256
|
|
869
|
+
if e > 128:
|
|
870
|
+
e = 256 - e
|
|
871
|
+
if e > worst:
|
|
872
|
+
worst, worst_pairs = e, [(dx, dy)]
|
|
873
|
+
elif e == worst:
|
|
874
|
+
worst_pairs.append((dx, dy))
|
|
875
|
+
print(f"atan2 max error over 65536 pairs: {worst}; {len(worst_pairs)} pairs at the max")
|
|
876
|
+
print("first worst pairs:", worst_pairs[:8])
|
|
877
|
+
|
|
878
|
+
sq_bad = [n for n in range(65536) if isqrt_model(n) != math.isqrt(n)]
|
|
879
|
+
print(f"isqrt model mismatches vs math.isqrt over 65536: {len(sq_bad)}")
|
|
880
|
+
|
|
881
|
+
# ---- check cases ----
|
|
882
|
+
sqrt_cases = [0, 1, 2, 3, 4, 8, 9, 15, 16, 17, 24, 25, 63, 64, 65, 99, 100,
|
|
883
|
+
121, 144, 255, 256, 257, 1000, 1024, 4095, 4096, 10000, 16384,
|
|
884
|
+
32767, 32768, 65024, 65025, 65026, 65534, 65535]
|
|
885
|
+
atan_cases = [(1, 0), (0, 1), (-1, 0), (0, -1), (127, 0), (0, 127), (-128, 0), (0, -128),
|
|
886
|
+
(10, 3), (3, 10), (-3, 10), (-10, 3), (-10, -3), (-3, -10), (3, -10), (10, -3),
|
|
887
|
+
(5, 5), (-5, 5), (-5, -5), (5, -5), (127, 127), (-128, -128), (127, -128), (-128, 127),
|
|
888
|
+
(1, 1), (2, 1), (1, 2), (-1, -2), (100, -37), (-64, 20), (45, -90), (-120, -7),
|
|
889
|
+
(0, 0)] + worst_pairs[:3]
|
|
890
|
+
|
|
891
|
+
def bytes_line(label, vals):
|
|
892
|
+
out = []
|
|
893
|
+
for i in range(0, len(vals), 16):
|
|
894
|
+
out.append(" .byte " + ", ".join(f"${v & 255:02x}" for v in vals[i:i + 16]))
|
|
895
|
+
return f"{label}:\n" + "\n".join(out)
|
|
896
|
+
|
|
897
|
+
print()
|
|
898
|
+
print(f"// {len(sqrt_cases)} isqrt cases, {len(atan_cases)} atan2 cases")
|
|
899
|
+
print(bytes_line("sq_in_lo", [n & 255 for n in sqrt_cases]))
|
|
900
|
+
print(bytes_line("sq_in_hi", [n >> 8 for n in sqrt_cases]))
|
|
901
|
+
print(bytes_line("sq_exp", [math.isqrt(n) for n in sqrt_cases]))
|
|
902
|
+
print(bytes_line("at_dx", [dx for dx, dy in atan_cases]))
|
|
903
|
+
print(bytes_line("at_dy", [dy for dx, dy in atan_cases]))
|
|
904
|
+
print(bytes_line("at_exp", [atan2_exact(dx, dy) for dx, dy in atan_cases]))
|
|
905
|
+
print(bytes_line("atan_tab", atan_tab))
|
|
906
|
+
print(f".const NSQ = {len(sqrt_cases)}")
|
|
907
|
+
print(f".const NAT = {len(atan_cases)}")
|
|
908
|
+
# model result on the cases, for the record
|
|
909
|
+
print("model atan2 on cases:", [atan2_model(dx, dy) for dx, dy in atan_cases])
|
|
910
|
+
print("exact atan2 on cases:", [atan2_exact(dx, dy) for dx, dy in atan_cases])
|
|
911
|
+
```
|
|
912
|
+
|
|
913
|
+
Its output, the part that is a claim: `atan2 max error over 65536 pairs:
|
|
914
|
+
1; 3968 pairs at the max` and `isqrt model mismatches vs math.isqrt over
|
|
915
|
+
65536: 0`. The model is the same integer arithmetic as the listing; the
|
|
916
|
+
program is what shows the listing agrees with the model.
|
|
917
|
+
|
|
918
|
+
## Expected output
|
|
919
|
+
|
|
920
|
+
Border green, text area black (the program clears the screen and never
|
|
921
|
+
returns to BASIC), decoded from the PNG with the character ROM:
|
|
922
|
+
|
|
923
|
+
```
|
|
924
|
+
ISQRT16 AND ATAN2 8-BIT CHECK
|
|
925
|
+
|
|
926
|
+
SQRT CASES 035 MAX ERR 000 FAIL 000
|
|
927
|
+
ATAN2 CASES 036 MAX ERR 001 FAIL 000
|
|
928
|
+
|
|
929
|
+
WORST BODY CYCLES OVER EVERY INPUT:
|
|
930
|
+
ISQRT16 00869 N=65025
|
|
931
|
+
ATAN2 00381 $81 $80
|
|
932
|
+
REM<=2*ROOT FAILS OF 65536 00000
|
|
933
|
+
SQRT(65535) = 255
|
|
934
|
+
ATAN2(10,3) = 012
|
|
935
|
+
|
|
936
|
+
RESULT: PASS
|
|
937
|
+
```
|
|
938
|
+
|
|
939
|
+
Screenshots from the pinned run, 120,000,000 cycles:
|
|
940
|
+
`screenshots/sqrt-atan2.png` (PAL) and `screenshots/sqrt-atan2-ntsc.png`
|
|
941
|
+
(NTSC). Both decode to the text above; border pixel (2, 100) is
|
|
942
|
+
(98, 213, 50) on PAL and (114, 189, 103) on NTSC, palette index 5 in
|
|
943
|
+
`runtime/vice-reference.md`. The pinned command was run twice per model
|
|
944
|
+
and the two PNGs were identical bytes each time. The two sweeps are
|
|
945
|
+
about 90 million cycles; a limit under 100 million exits before the
|
|
946
|
+
report is drawn.
|
|
947
|
+
|
|
948
|
+
The figures, all measured in VICE x64sc 3.10 and identical on PAL and
|
|
949
|
+
NTSC:
|
|
950
|
+
|
|
951
|
+
- `isqrt16` body: 869 cycles at worst, first reached at n = 65025
|
|
952
|
+
(255 squared), root exact on every case, `rem <= 2 * root` on all
|
|
953
|
+
65,536 inputs.
|
|
954
|
+
- `atan2_8` body: 381 cycles at worst, first reached at
|
|
955
|
+
dx = -127, dy = -128; largest error 1 angle unit over the 36 cases,
|
|
956
|
+
which matches the model's 1 over every pair.
|
|
957
|
+
- Body means net of the `JSR`, `RTS` and timer stores, which are
|
|
958
|
+
measured once with an empty routine and subtracted.
|
|
959
|
+
|
|
960
|
+
## Why this works
|
|
961
|
+
|
|
962
|
+
The square root brings down two bits of `n` per pass into a remainder,
|
|
963
|
+
and per pass doubles the root and tries to subtract `4 * root + 1`,
|
|
964
|
+
which is `(2 * root + 1)^2 - (2 * root)^2`. If the subtract fits, the new
|
|
965
|
+
root bit is 1. After eight passes the root is 8 bits and the remainder is
|
|
966
|
+
`n - root^2`, at most `2 * root`. The trial value reaches 509, so the
|
|
967
|
+
remainder and the trial are two bytes; the compare tests the high bytes
|
|
968
|
+
first and falls through to the low bytes only when they are equal. The
|
|
969
|
+
`SBC` at `sq_sub` is reached on two paths and the carry is set on both
|
|
970
|
+
(from `BNE` after a `CMP` that did not borrow, or from the low-byte
|
|
971
|
+
`CMP`). The worst input is 255 squared rather than 65535: both take
|
|
972
|
+
the subtract on every pass, but 65025 goes once more through the
|
|
973
|
+
equal-high-byte path of the compare, which is seven cycles longer. An
|
|
974
|
+
instruction-table model of the loop (rung 3) gives 862 for 65535, 869
|
|
975
|
+
for 65025 and 869 as its maximum over all 65,536 inputs, the figure the
|
|
976
|
+
sweep measured.
|
|
977
|
+
|
|
978
|
+
`atan2_8` takes the absolute values with `BPL` on the input byte itself,
|
|
979
|
+
not after a subtract, so -128 becomes 128 and the octant compare is a
|
|
980
|
+
plain unsigned `CMP`. When `|dy| < |dx|` the angle is
|
|
981
|
+
`atan(|dy| / |dx|)`; when greater, it is 64 minus `atan(|dx| / |dy|)`;
|
|
982
|
+
when equal, exactly 32, which is tested for because the ratio 256 does
|
|
983
|
+
not fit the table index. The ratio index is `floor(min * 256 / max)`, an
|
|
984
|
+
eight-pass divide whose remainder starts as `min` and stays below `max`;
|
|
985
|
+
`max` is at most 128, so the doubled remainder never needs a ninth bit
|
|
986
|
+
and the loop has no `BCS` guard (`division_8_16bit` explains the guard
|
|
987
|
+
the general loop needs). The table entry is `round(atan(i / 256) * 256 /
|
|
988
|
+
2pi)`, 0 to 32. Unfolding is two conditional negations: `128 - a` for
|
|
989
|
+
`dx < 0`, then `256 - a` for `dy < 0`, each written as `EOR #$FF` plus
|
|
990
|
+
an add. The error is at most 1 unit because the table is rounded and
|
|
991
|
+
the index truncates a ratio step of 1/256, which moves the angle by
|
|
992
|
+
less than 0.2 units.
|
|
993
|
+
|
|
994
|
+
Timing uses CIA1 timer A force-loaded from `$FFFF` in one-shot mode;
|
|
995
|
+
the count read after the stop, subtracted from the same reading for an
|
|
996
|
+
empty call, is the body cost. DEN is cleared before the sweeps and the
|
|
997
|
+
program waits for two passes of raster line 255 first, because the VIC
|
|
998
|
+
reads DEN once per frame on line `$30` and clearing it mid-frame does
|
|
999
|
+
not stop that frame's badlines. Both routines are placed in one page by
|
|
1000
|
+
`.align $100` and an `.assert`: in an earlier layout the square root's
|
|
1001
|
+
loop branch crossed a page and the same input measured 876, seven
|
|
1002
|
+
taken branches at one extra cycle each (`pitfalls/cpu.md`,
|
|
1003
|
+
`branch_page_cross_extra_cycle`).
|
|
1004
|
+
|
|
1005
|
+
## What this recipe does not show
|
|
1006
|
+
|
|
1007
|
+
No signed `dx` from two positions: the program feeds `dx` and `dy`
|
|
1008
|
+
directly. A game that forms them with `SEC / SBC` on 8-bit positions
|
|
1009
|
+
more than 127 apart gets a wrapped sign, and the fold then answers for
|
|
1010
|
+
the wrong half of the circle (`pitfalls/cpu.md`,
|
|
1011
|
+
`signed_compare_bmi_overflow`). Clamp the difference or compute it in
|
|
1012
|
+
16 bits and take the high byte. The routines are not unrolled; an
|
|
1013
|
+
unrolled root is about a fifth faster by the instruction table and was
|
|
1014
|
+
not measured here.
|