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,2324 @@
|
|
|
1
|
+
---
|
|
2
|
+
recipe: wireframe-ships
|
|
3
|
+
toolchain: kickassembler
|
|
4
|
+
output_format: PRG
|
|
5
|
+
region: both
|
|
6
|
+
techniques: [wireframe_pipeline, procedural_seed_universe]
|
|
7
|
+
file_formats: [PRG]
|
|
8
|
+
uses_registers: [D011, D016, D018, D020, D021, DD00, DC04, DC05, DC06, DC07, DC0D, DC0E, DC0F, DD04, DD05, DD06, DD07, DD0D, DD0E, DD0F]
|
|
9
|
+
uses_kernal: []
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<!-- doc-type: recipe -->
|
|
13
|
+
|
|
14
|
+
# KickAssembler — Rotating wireframe ships with back-face culling and clipping, and an Elite-style seeded galaxy, checked against a host model
|
|
15
|
+
|
|
16
|
+
## Synopsis
|
|
17
|
+
|
|
18
|
+
Three convex wireframe objects (a cube, a square pyramid and a ship hull
|
|
19
|
+
of this recipe's own design) rotate in a 160 x 120 pixel window of a
|
|
20
|
+
hires bitmap. Each update builds a 3x3 fixed-point rotation matrix per
|
|
21
|
+
object from a sine table and quarter-square multiplies, transforms and
|
|
22
|
+
projects every vertex through a reciprocal table, culls back faces by
|
|
23
|
+
the winding of the projected face, rejects lines wholly outside the
|
|
24
|
+
window by outcodes, and draws the rest with Bresenham and EOR. A line
|
|
25
|
+
that crosses the window edge is clipped pixel by pixel. The previous
|
|
26
|
+
update's lines are erased by drawing them again. The ship crosses the
|
|
27
|
+
right edge and the cube the top edge.
|
|
28
|
+
|
|
29
|
+
The program runs 48 updates twice. Pass 1 counts lines and sums their
|
|
30
|
+
endpoints, times every line call with CIA2, and checks the counts and a
|
|
31
|
+
checksum of the bitmap against the Python model below. Pass 2 erases,
|
|
32
|
+
rewinds and runs the same 48 updates with the counters off, timing each
|
|
33
|
+
object with CIA1, and checks the bitmap again. It then times one matrix
|
|
34
|
+
build and one ship transform, generates the first eight systems of
|
|
35
|
+
Elite's first galaxy from its three 16-bit seeds (named from this recipe's
|
|
36
|
+
own letter pairs), checks the names and coordinates against the model, and prints everything under the window.
|
|
37
|
+
It writes `$01` to `$02FF` and turns the border green when every check
|
|
38
|
+
matches, `$02` and red otherwise. The techniques are
|
|
39
|
+
`wireframe_pipeline` in `techniques/effects-vector-3d.md` and
|
|
40
|
+
`procedural_seed_universe` in `techniques/maths.md`.
|
|
41
|
+
|
|
42
|
+
Coordinates: the program works in a virtual 256 x 256 screen with its
|
|
43
|
+
centre at (128, 128). The window is x 32-191, y 68-187; bitmap x is
|
|
44
|
+
virtual x + 32 and bitmap y is virtual y - 68, so the window fills
|
|
45
|
+
character rows 0-14, columns 8-27. Camera space has x right, y down and
|
|
46
|
+
z into the screen, with the camera at the origin.
|
|
47
|
+
|
|
48
|
+
## Source
|
|
49
|
+
|
|
50
|
+
```asm
|
|
51
|
+
// wireframe-ships.asm
|
|
52
|
+
// Three rotating convex wireframe objects (a cube, a pyramid, a ship hull)
|
|
53
|
+
// in a hires bitmap: 3x3 fixed-point rotation from a sine table and
|
|
54
|
+
// quarter-square multiplies, projection through a reciprocal table,
|
|
55
|
+
// back-face culling by the winding of the projected face, outcode reject,
|
|
56
|
+
// a per-pixel clip for lines that cross the window edge, Bresenham lines
|
|
57
|
+
// plotted with EOR and erased by drawing the previous frame's lines again.
|
|
58
|
+
// Pass 1 runs NF updates with counters on and CIA2 gated around every line
|
|
59
|
+
// call, then checks the line count, an endpoint sum and a bitmap checksum
|
|
60
|
+
// against a Python model of the same integer arithmetic (the generator is
|
|
61
|
+
// on the page). Pass 2 erases, rewinds and runs the same NF updates with
|
|
62
|
+
// the counters off, timing each object with CIA1, and checks the bitmap
|
|
63
|
+
// again. Then the program times a matrix build and a vertex transform,
|
|
64
|
+
// generates the first eight systems of Elite's first galaxy from three
|
|
65
|
+
// 16-bit seeds, and prints everything into the bitmap below the window.
|
|
66
|
+
// Verdict: $02FF = $01 and a green border when every check matches,
|
|
67
|
+
// $02 and red otherwise.
|
|
68
|
+
.encoding "screencode_upper"
|
|
69
|
+
|
|
70
|
+
.const NF = 48 // updates before the picture is frozen
|
|
71
|
+
.const XMIN = 32 // view window, virtual coordinates
|
|
72
|
+
.const XMAX = 191 // (bitmap x = vx + 32, bitmap y = vy - 68)
|
|
73
|
+
.const YMIN = 68
|
|
74
|
+
.const YMAX = 187
|
|
75
|
+
.const BITMAP = $6000 // VIC bank 1: bitmap at $6000
|
|
76
|
+
.const MATRIX = $4400 // video matrix at $4400
|
|
77
|
+
.const RESULT = $02ff
|
|
78
|
+
.const NSYS = 8
|
|
79
|
+
|
|
80
|
+
// expected values from gen.py
|
|
81
|
+
.const EXP_LAST = 19
|
|
82
|
+
.const EXP_TOTAL = 1005
|
|
83
|
+
.const EXP_SUM = $84ea
|
|
84
|
+
.const EXP_S1 = $8c
|
|
85
|
+
.const EXP_S2 = $99
|
|
86
|
+
|
|
87
|
+
// ---- zero page (the program never returns to BASIC) ----
|
|
88
|
+
.const ma = $02 // signed multiply operands
|
|
89
|
+
.const mb = $03
|
|
90
|
+
.const ua = $04 // unsigned multiply operands
|
|
91
|
+
.const ub = $05
|
|
92
|
+
.const prod = $06 // 16-bit product
|
|
93
|
+
.const acc = $08 // 16-bit dot-product accumulator
|
|
94
|
+
.const m = $0a // 3x3 matrix, row-major, 9 bytes $0a-$12
|
|
95
|
+
.const vxx = $13 // vertex being transformed
|
|
96
|
+
.const vyy = $14
|
|
97
|
+
.const vzz = $15
|
|
98
|
+
.const rowi = $16
|
|
99
|
+
.const obj = $17 // current object 0-2
|
|
100
|
+
.const tmp = $18
|
|
101
|
+
.const sgn = $19
|
|
102
|
+
.const zc = $1a
|
|
103
|
+
.const recf = $1b
|
|
104
|
+
.const vis = $1c // visible-face mask of the current object
|
|
105
|
+
.const cnt = $1d
|
|
106
|
+
.const idx = $1e
|
|
107
|
+
.const t1 = $1f // 16-bit
|
|
108
|
+
.const lx0 = $21 // line endpoints and clip flag
|
|
109
|
+
.const ly0 = $22
|
|
110
|
+
.const lx1 = $23
|
|
111
|
+
.const ly1 = $24
|
|
112
|
+
.const lclip = $25
|
|
113
|
+
.const ddx = $26
|
|
114
|
+
.const ddy = $27
|
|
115
|
+
.const err = $28
|
|
116
|
+
.const cy = $29
|
|
117
|
+
.const sy = $2a
|
|
118
|
+
.const ptr = $2b // 2 bytes
|
|
119
|
+
.const oc0 = $2d
|
|
120
|
+
.const hbase = $2e // heap slot base for the current object
|
|
121
|
+
.const upd = $2f // update counter
|
|
122
|
+
.const t0 = $30 // CIA1 32-bit reading, 4 bytes $30-$33
|
|
123
|
+
.const u24 = $34 // 24-bit accumulator for one update, 3 bytes
|
|
124
|
+
.const s0 = $37 // galaxy seeds, 6 bytes $37-$3c
|
|
125
|
+
.const s1 = $39
|
|
126
|
+
.const s2 = $3b
|
|
127
|
+
.const gt = $3d // 2 bytes
|
|
128
|
+
.const num = $3f // 24-bit number for the printers, 3 bytes
|
|
129
|
+
.const dig = $42
|
|
130
|
+
.const prow = $43 // print cursor: text row, column
|
|
131
|
+
.const pcol = $44
|
|
132
|
+
.const sptr = $45 // 2 bytes
|
|
133
|
+
.const dst = $47 // 2 bytes
|
|
134
|
+
.const src = $49 // 2 bytes
|
|
135
|
+
.const dvs = $4b // 16-bit divisor
|
|
136
|
+
.const rmd = $4d // 16-bit remainder
|
|
137
|
+
.const fail = $4f
|
|
138
|
+
.const lng = $50
|
|
139
|
+
.const pcount = $51
|
|
140
|
+
.const sysn = $52
|
|
141
|
+
.const gcol = $53
|
|
142
|
+
.const nx = $54
|
|
143
|
+
|
|
144
|
+
BasicUpstart2(start)
|
|
145
|
+
|
|
146
|
+
start:
|
|
147
|
+
sei
|
|
148
|
+
lda #$7f
|
|
149
|
+
sta $dc0d // no CIA1 interrupts
|
|
150
|
+
sta $dd0d // no CIA2 NMIs
|
|
151
|
+
lda $dc0d
|
|
152
|
+
lda $dd0d
|
|
153
|
+
lda #0
|
|
154
|
+
sta $d020
|
|
155
|
+
sta $d021
|
|
156
|
+
sta fail
|
|
157
|
+
jsr clear_all
|
|
158
|
+
lda $dd00
|
|
159
|
+
and #%11111100
|
|
160
|
+
ora #%00000010 // VIC bank 1 ($4000-$7fff)
|
|
161
|
+
sta $dd00
|
|
162
|
+
lda #$18 // matrix $4400, bitmap $6000
|
|
163
|
+
sta $d018
|
|
164
|
+
lda #$08
|
|
165
|
+
sta $d016
|
|
166
|
+
lda #$3b // bitmap mode, display on, 25 rows
|
|
167
|
+
sta $d011
|
|
168
|
+
|
|
169
|
+
// cycle harness: CIA2 A+B chained, paused except while a line draws
|
|
170
|
+
lda #0
|
|
171
|
+
sta $dd0e
|
|
172
|
+
sta $dd0f
|
|
173
|
+
lda #$ff
|
|
174
|
+
sta $dd04
|
|
175
|
+
sta $dd05
|
|
176
|
+
sta $dd06
|
|
177
|
+
sta $dd07
|
|
178
|
+
lda #$10
|
|
179
|
+
sta $dd0e // A: force load, stopped
|
|
180
|
+
lda #$51
|
|
181
|
+
sta $dd0f // B: counts A underflows, force load, start
|
|
182
|
+
jsr time_empty // CIA1 start/stop overhead
|
|
183
|
+
jsr pause_empty // CIA2 resume/pause overhead
|
|
184
|
+
|
|
185
|
+
lda #0
|
|
186
|
+
sta tot_lines
|
|
187
|
+
sta tot_lines+1
|
|
188
|
+
sta ep_sum
|
|
189
|
+
sta ep_sum+1
|
|
190
|
+
sta hcount
|
|
191
|
+
sta hcount+1
|
|
192
|
+
sta hcount+2
|
|
193
|
+
sta calls
|
|
194
|
+
sta calls+1
|
|
195
|
+
|
|
196
|
+
// pass 1, checked: counters and the CIA2 line gate are on
|
|
197
|
+
lda #$80
|
|
198
|
+
sta harness
|
|
199
|
+
jsr run_pass
|
|
200
|
+
clc
|
|
201
|
+
lda hcount
|
|
202
|
+
adc hcount+1
|
|
203
|
+
adc hcount+2
|
|
204
|
+
sta last_lines
|
|
205
|
+
jsr check_model
|
|
206
|
+
// line cycles: CIA2 total less the pause/resume overhead per call
|
|
207
|
+
jsr cia2_read // t0..t0+3 = cycles counted
|
|
208
|
+
jsr mul_ovh_sub // t0 -= calls * povh
|
|
209
|
+
lda t0
|
|
210
|
+
sta linecyc
|
|
211
|
+
lda t0+1
|
|
212
|
+
sta linecyc+1
|
|
213
|
+
lda t0+2
|
|
214
|
+
sta linecyc+2
|
|
215
|
+
// pass 2, timed: erase, rewind, run the same updates with the
|
|
216
|
+
// harness off; the picture must come out the same
|
|
217
|
+
lda #0
|
|
218
|
+
sta harness
|
|
219
|
+
jsr rewind
|
|
220
|
+
jsr run_pass
|
|
221
|
+
jsr check_bitmap
|
|
222
|
+
jmp bench
|
|
223
|
+
|
|
224
|
+
// ================= the animation =================
|
|
225
|
+
run_pass:
|
|
226
|
+
ldx #2
|
|
227
|
+
!: lda ang_a0,x
|
|
228
|
+
sta ang_a,x
|
|
229
|
+
lda ang_b0,x
|
|
230
|
+
sta ang_b,x
|
|
231
|
+
dex
|
|
232
|
+
bpl !-
|
|
233
|
+
lda #0
|
|
234
|
+
sta upd
|
|
235
|
+
sta worst
|
|
236
|
+
sta worst+1
|
|
237
|
+
sta worst+2
|
|
238
|
+
frame:
|
|
239
|
+
lda #0
|
|
240
|
+
sta u24
|
|
241
|
+
sta u24+1
|
|
242
|
+
sta u24+2
|
|
243
|
+
ldx #0
|
|
244
|
+
obj_loop:
|
|
245
|
+
stx obj
|
|
246
|
+
jsr timer_start
|
|
247
|
+
jsr do_object
|
|
248
|
+
jsr timer_stop
|
|
249
|
+
ldx obj // keep this object's cost for the readout
|
|
250
|
+
lda t0
|
|
251
|
+
sta ocyc_lo,x
|
|
252
|
+
lda t0+1
|
|
253
|
+
sta ocyc_mid,x
|
|
254
|
+
lda t0+2
|
|
255
|
+
sta ocyc_hi,x
|
|
256
|
+
clc
|
|
257
|
+
lda u24
|
|
258
|
+
adc t0
|
|
259
|
+
sta u24
|
|
260
|
+
lda u24+1
|
|
261
|
+
adc t0+1
|
|
262
|
+
sta u24+1
|
|
263
|
+
lda u24+2
|
|
264
|
+
adc t0+2
|
|
265
|
+
sta u24+2
|
|
266
|
+
ldx obj
|
|
267
|
+
inx
|
|
268
|
+
cpx #3
|
|
269
|
+
bne obj_loop
|
|
270
|
+
// worst update so far
|
|
271
|
+
lda u24+2
|
|
272
|
+
cmp worst+2
|
|
273
|
+
bcc !keep+
|
|
274
|
+
bne !new+
|
|
275
|
+
lda u24+1
|
|
276
|
+
cmp worst+1
|
|
277
|
+
bcc !keep+
|
|
278
|
+
bne !new+
|
|
279
|
+
lda u24
|
|
280
|
+
cmp worst
|
|
281
|
+
bcc !keep+
|
|
282
|
+
!new: lda u24
|
|
283
|
+
sta worst
|
|
284
|
+
lda u24+1
|
|
285
|
+
sta worst+1
|
|
286
|
+
lda u24+2
|
|
287
|
+
sta worst+2
|
|
288
|
+
!keep:
|
|
289
|
+
inc upd
|
|
290
|
+
lda upd
|
|
291
|
+
cmp #NF
|
|
292
|
+
beq !+
|
|
293
|
+
jmp frame
|
|
294
|
+
!: rts
|
|
295
|
+
|
|
296
|
+
// erase every object's heap: the bitmap returns to blank
|
|
297
|
+
rewind:
|
|
298
|
+
ldx #0
|
|
299
|
+
!: stx obj
|
|
300
|
+
jsr erase_heap
|
|
301
|
+
ldx obj
|
|
302
|
+
lda #0
|
|
303
|
+
sta hcount,x
|
|
304
|
+
inx
|
|
305
|
+
cpx #3
|
|
306
|
+
bne !-
|
|
307
|
+
rts
|
|
308
|
+
|
|
309
|
+
// ================= checks against the model =================
|
|
310
|
+
check_model:
|
|
311
|
+
lda last_lines
|
|
312
|
+
cmp #EXP_LAST
|
|
313
|
+
beq !+
|
|
314
|
+
inc fail
|
|
315
|
+
!: lda tot_lines
|
|
316
|
+
cmp #<EXP_TOTAL
|
|
317
|
+
bne !bad+
|
|
318
|
+
lda tot_lines+1
|
|
319
|
+
cmp #>EXP_TOTAL
|
|
320
|
+
bne !bad+
|
|
321
|
+
lda ep_sum
|
|
322
|
+
cmp #<EXP_SUM
|
|
323
|
+
bne !bad+
|
|
324
|
+
lda ep_sum+1
|
|
325
|
+
cmp #>EXP_SUM
|
|
326
|
+
beq !+
|
|
327
|
+
!bad: inc fail
|
|
328
|
+
!:
|
|
329
|
+
check_bitmap:
|
|
330
|
+
jsr fletcher // bitmap rows 0-15, memory order
|
|
331
|
+
lda fl1
|
|
332
|
+
cmp #EXP_S1
|
|
333
|
+
bne !bad+
|
|
334
|
+
lda fl2
|
|
335
|
+
cmp #EXP_S2
|
|
336
|
+
beq !+
|
|
337
|
+
!bad: inc fail
|
|
338
|
+
!: rts
|
|
339
|
+
|
|
340
|
+
// ================= micro-benchmarks (bitmap untouched) =================
|
|
341
|
+
bench:
|
|
342
|
+
lda #2
|
|
343
|
+
sta obj
|
|
344
|
+
jsr timer_start
|
|
345
|
+
jsr build_matrix
|
|
346
|
+
jsr timer_stop
|
|
347
|
+
lda t0
|
|
348
|
+
sta mcyc
|
|
349
|
+
lda t0+1
|
|
350
|
+
sta mcyc+1
|
|
351
|
+
jsr timer_start
|
|
352
|
+
jsr xform_all
|
|
353
|
+
jsr timer_stop
|
|
354
|
+
lda t0
|
|
355
|
+
sta vcyc
|
|
356
|
+
lda t0+1
|
|
357
|
+
sta vcyc+1
|
|
358
|
+
|
|
359
|
+
// ================= galaxy =================
|
|
360
|
+
jsr galaxy
|
|
361
|
+
|
|
362
|
+
// ================= readout =================
|
|
363
|
+
jsr print_all
|
|
364
|
+
lda fail
|
|
365
|
+
bne !bad+
|
|
366
|
+
lda #1
|
|
367
|
+
sta RESULT
|
|
368
|
+
lda #5
|
|
369
|
+
sta $d020
|
|
370
|
+
jmp *
|
|
371
|
+
!bad: lda #2
|
|
372
|
+
sta RESULT
|
|
373
|
+
lda #2
|
|
374
|
+
sta $d020
|
|
375
|
+
jmp *
|
|
376
|
+
|
|
377
|
+
// ---------------------------------------------------------------
|
|
378
|
+
// one object: advance angles, matrix, transform and project every
|
|
379
|
+
// vertex, cull faces, erase the old lines, draw and store the new
|
|
380
|
+
do_object:
|
|
381
|
+
ldx obj
|
|
382
|
+
clc
|
|
383
|
+
lda ang_a,x
|
|
384
|
+
adc stp_a,x
|
|
385
|
+
sta ang_a,x
|
|
386
|
+
clc
|
|
387
|
+
lda ang_b,x
|
|
388
|
+
adc stp_b,x
|
|
389
|
+
sta ang_b,x
|
|
390
|
+
jsr build_matrix
|
|
391
|
+
jsr xform_all
|
|
392
|
+
jsr cull
|
|
393
|
+
jsr erase_heap
|
|
394
|
+
// new lines
|
|
395
|
+
ldx obj
|
|
396
|
+
lda #0
|
|
397
|
+
sta hcount,x
|
|
398
|
+
lda o_en,x
|
|
399
|
+
sta cnt
|
|
400
|
+
lda o_est,x
|
|
401
|
+
sta idx
|
|
402
|
+
ed_loop:
|
|
403
|
+
ldy idx
|
|
404
|
+
lda ef0,y
|
|
405
|
+
tax
|
|
406
|
+
lda bit_of,x
|
|
407
|
+
and vis
|
|
408
|
+
bne ed_vis
|
|
409
|
+
lda ef1,y
|
|
410
|
+
tax
|
|
411
|
+
lda bit_of,x
|
|
412
|
+
and vis
|
|
413
|
+
bne ed_vis
|
|
414
|
+
jmp ed_next
|
|
415
|
+
ed_vis:
|
|
416
|
+
lda e0,y
|
|
417
|
+
tax
|
|
418
|
+
lda px,x
|
|
419
|
+
sta lx0
|
|
420
|
+
lda py,x
|
|
421
|
+
sta ly0
|
|
422
|
+
lda e1,y
|
|
423
|
+
tax
|
|
424
|
+
lda px,x
|
|
425
|
+
sta lx1
|
|
426
|
+
lda py,x
|
|
427
|
+
sta ly1
|
|
428
|
+
ldx lx0
|
|
429
|
+
ldy ly0
|
|
430
|
+
jsr outcode
|
|
431
|
+
sta oc0
|
|
432
|
+
ldx lx1
|
|
433
|
+
ldy ly1
|
|
434
|
+
jsr outcode
|
|
435
|
+
tax
|
|
436
|
+
and oc0
|
|
437
|
+
beq !+
|
|
438
|
+
jmp ed_next // both ends beyond one edge: reject
|
|
439
|
+
!:
|
|
440
|
+
txa
|
|
441
|
+
ora oc0
|
|
442
|
+
sta lclip // non-zero: crosses an edge, clip per pixel
|
|
443
|
+
// store in the heap
|
|
444
|
+
ldx obj
|
|
445
|
+
lda hslot,x
|
|
446
|
+
clc
|
|
447
|
+
adc hcount,x
|
|
448
|
+
tay
|
|
449
|
+
inc hcount,x
|
|
450
|
+
lda lx0
|
|
451
|
+
sta hx0,y
|
|
452
|
+
lda ly0
|
|
453
|
+
sta hy0,y
|
|
454
|
+
lda lx1
|
|
455
|
+
sta hx1,y
|
|
456
|
+
lda ly1
|
|
457
|
+
sta hy1,y
|
|
458
|
+
lda lclip
|
|
459
|
+
sta hcl,y
|
|
460
|
+
// bookkeeping for the model check, pass 1 only
|
|
461
|
+
bit harness
|
|
462
|
+
bpl ed_draw
|
|
463
|
+
inc tot_lines
|
|
464
|
+
bne !+
|
|
465
|
+
inc tot_lines+1
|
|
466
|
+
!: lda lx0
|
|
467
|
+
jsr add_sum
|
|
468
|
+
lda ly0
|
|
469
|
+
jsr add_sum
|
|
470
|
+
lda lx1
|
|
471
|
+
jsr add_sum
|
|
472
|
+
lda ly1
|
|
473
|
+
jsr add_sum
|
|
474
|
+
ed_draw:
|
|
475
|
+
jsr line_timed
|
|
476
|
+
ed_next:
|
|
477
|
+
inc idx
|
|
478
|
+
dec cnt
|
|
479
|
+
beq !+
|
|
480
|
+
jmp ed_loop
|
|
481
|
+
!: rts
|
|
482
|
+
|
|
483
|
+
// draw the object's stored lines again: EOR takes them off the bitmap
|
|
484
|
+
erase_heap:
|
|
485
|
+
ldx obj
|
|
486
|
+
lda hslot,x
|
|
487
|
+
sta hbase
|
|
488
|
+
lda hcount,x
|
|
489
|
+
sta cnt
|
|
490
|
+
beq er_done
|
|
491
|
+
ldy hbase
|
|
492
|
+
er_loop:
|
|
493
|
+
sty idx
|
|
494
|
+
lda hx0,y
|
|
495
|
+
sta lx0
|
|
496
|
+
lda hy0,y
|
|
497
|
+
sta ly0
|
|
498
|
+
lda hx1,y
|
|
499
|
+
sta lx1
|
|
500
|
+
lda hy1,y
|
|
501
|
+
sta ly1
|
|
502
|
+
lda hcl,y
|
|
503
|
+
sta lclip
|
|
504
|
+
jsr line_timed
|
|
505
|
+
ldy idx
|
|
506
|
+
iny
|
|
507
|
+
dec cnt
|
|
508
|
+
bne er_loop
|
|
509
|
+
er_done:
|
|
510
|
+
rts
|
|
511
|
+
|
|
512
|
+
add_sum:
|
|
513
|
+
clc
|
|
514
|
+
adc ep_sum
|
|
515
|
+
sta ep_sum
|
|
516
|
+
bcc !+
|
|
517
|
+
inc ep_sum+1
|
|
518
|
+
!: rts
|
|
519
|
+
|
|
520
|
+
// outcode of (X, Y): bit 0 left, 1 right, 2 above, 3 below
|
|
521
|
+
outcode:
|
|
522
|
+
lda #0
|
|
523
|
+
cpx #XMIN
|
|
524
|
+
bcs !+
|
|
525
|
+
ora #1
|
|
526
|
+
!: cpx #XMAX+1
|
|
527
|
+
bcc !+
|
|
528
|
+
ora #2
|
|
529
|
+
!: cpy #YMIN
|
|
530
|
+
bcs !+
|
|
531
|
+
ora #4
|
|
532
|
+
!: cpy #YMAX+1
|
|
533
|
+
bcc !+
|
|
534
|
+
ora #8
|
|
535
|
+
!: rts
|
|
536
|
+
|
|
537
|
+
// ---------------------------------------------------------------
|
|
538
|
+
// rotation matrix for object obj from angles a (about y) and b (about x)
|
|
539
|
+
// | ca 0 sa |
|
|
540
|
+
// | sa*sb>>6 cb -(ca*sb>>6) |
|
|
541
|
+
// | -(sa*cb>>6) sb ca*cb>>6 |
|
|
542
|
+
build_matrix:
|
|
543
|
+
ldx obj
|
|
544
|
+
ldy ang_a,x
|
|
545
|
+
lda sintab,y
|
|
546
|
+
sta m+2 // sa
|
|
547
|
+
lda costab,y
|
|
548
|
+
sta m+0 // ca
|
|
549
|
+
ldy ang_b,x
|
|
550
|
+
lda costab,y
|
|
551
|
+
sta m+4 // cb
|
|
552
|
+
lda sintab,y
|
|
553
|
+
sta m+7 // sb
|
|
554
|
+
lda #0
|
|
555
|
+
sta m+1
|
|
556
|
+
lda m+2
|
|
557
|
+
sta ma
|
|
558
|
+
lda m+7
|
|
559
|
+
sta mb
|
|
560
|
+
jsr smuls
|
|
561
|
+
jsr shr6
|
|
562
|
+
sta m+3 // sa*sb>>6
|
|
563
|
+
lda m+0
|
|
564
|
+
sta ma
|
|
565
|
+
jsr smuls // mb still sb
|
|
566
|
+
jsr shr6
|
|
567
|
+
eor #$ff
|
|
568
|
+
clc
|
|
569
|
+
adc #1
|
|
570
|
+
sta m+5 // -(ca*sb>>6)
|
|
571
|
+
lda m+2
|
|
572
|
+
sta ma
|
|
573
|
+
lda m+4
|
|
574
|
+
sta mb
|
|
575
|
+
jsr smuls
|
|
576
|
+
jsr shr6
|
|
577
|
+
eor #$ff
|
|
578
|
+
clc
|
|
579
|
+
adc #1
|
|
580
|
+
sta m+6 // -(sa*cb>>6)
|
|
581
|
+
lda m+0
|
|
582
|
+
sta ma
|
|
583
|
+
jsr smuls // mb still cb
|
|
584
|
+
jsr shr6
|
|
585
|
+
sta m+8 // ca*cb>>6
|
|
586
|
+
rts
|
|
587
|
+
|
|
588
|
+
// prod >> 6 as a signed byte: the high byte of prod << 2
|
|
589
|
+
shr6:
|
|
590
|
+
asl prod
|
|
591
|
+
rol prod+1
|
|
592
|
+
asl prod
|
|
593
|
+
rol prod+1
|
|
594
|
+
lda prod+1
|
|
595
|
+
rts
|
|
596
|
+
|
|
597
|
+
// signed 8x8 -> 16, valid while |ma + mb| and |ma - mb| <= 128
|
|
598
|
+
smuls:
|
|
599
|
+
lda ma
|
|
600
|
+
clc
|
|
601
|
+
adc mb
|
|
602
|
+
tax
|
|
603
|
+
lda ma
|
|
604
|
+
sec
|
|
605
|
+
sbc mb
|
|
606
|
+
tay
|
|
607
|
+
lda qslo,x
|
|
608
|
+
sec
|
|
609
|
+
sbc qslo,y
|
|
610
|
+
sta prod
|
|
611
|
+
lda qshi,x
|
|
612
|
+
sbc qshi,y
|
|
613
|
+
sta prod+1
|
|
614
|
+
rts
|
|
615
|
+
|
|
616
|
+
// unsigned 8x8 -> 16 by quarter squares, 512-entry tables
|
|
617
|
+
umul:
|
|
618
|
+
lda ua
|
|
619
|
+
clc
|
|
620
|
+
adc ub
|
|
621
|
+
tax
|
|
622
|
+
bcs um_hi
|
|
623
|
+
lda ua
|
|
624
|
+
sec
|
|
625
|
+
sbc ub
|
|
626
|
+
bcs !+
|
|
627
|
+
eor #$ff
|
|
628
|
+
adc #1 // carry is clear here: |ua - ub|
|
|
629
|
+
!: tay
|
|
630
|
+
lda sqlo,x
|
|
631
|
+
sec
|
|
632
|
+
sbc sqlo,y
|
|
633
|
+
sta prod
|
|
634
|
+
lda sqhi,x
|
|
635
|
+
sbc sqhi,y
|
|
636
|
+
sta prod+1
|
|
637
|
+
rts
|
|
638
|
+
um_hi: lda ua
|
|
639
|
+
sec
|
|
640
|
+
sbc ub
|
|
641
|
+
bcs !+
|
|
642
|
+
eor #$ff
|
|
643
|
+
adc #1
|
|
644
|
+
!: tay
|
|
645
|
+
lda sqlo+256,x
|
|
646
|
+
sec
|
|
647
|
+
sbc sqlo,y
|
|
648
|
+
sta prod
|
|
649
|
+
lda sqhi+256,x
|
|
650
|
+
sbc sqhi,y
|
|
651
|
+
sta prod+1
|
|
652
|
+
rts
|
|
653
|
+
|
|
654
|
+
// signed 8x8 -> 16 for any |ma|, |mb| <= 127: magnitudes, then the sign
|
|
655
|
+
smulg:
|
|
656
|
+
lda ma
|
|
657
|
+
eor mb
|
|
658
|
+
sta sgn
|
|
659
|
+
lda ma
|
|
660
|
+
bpl !+
|
|
661
|
+
eor #$ff
|
|
662
|
+
clc
|
|
663
|
+
adc #1
|
|
664
|
+
!: sta ua
|
|
665
|
+
lda mb
|
|
666
|
+
bpl !+
|
|
667
|
+
eor #$ff
|
|
668
|
+
clc
|
|
669
|
+
adc #1
|
|
670
|
+
!: sta ub
|
|
671
|
+
jsr umul
|
|
672
|
+
lda sgn
|
|
673
|
+
bpl !+
|
|
674
|
+
sec
|
|
675
|
+
lda #0
|
|
676
|
+
sbc prod
|
|
677
|
+
sta prod
|
|
678
|
+
lda #0
|
|
679
|
+
sbc prod+1
|
|
680
|
+
sta prod+1
|
|
681
|
+
!: rts
|
|
682
|
+
|
|
683
|
+
// row X (0, 3, 6) of the matrix times the vertex, >> 6
|
|
684
|
+
dot_row:
|
|
685
|
+
stx rowi
|
|
686
|
+
lda m,x
|
|
687
|
+
sta ma
|
|
688
|
+
lda vxx
|
|
689
|
+
sta mb
|
|
690
|
+
jsr smuls
|
|
691
|
+
lda prod
|
|
692
|
+
sta acc
|
|
693
|
+
lda prod+1
|
|
694
|
+
sta acc+1
|
|
695
|
+
ldx rowi
|
|
696
|
+
lda m+1,x
|
|
697
|
+
sta ma
|
|
698
|
+
lda vyy
|
|
699
|
+
sta mb
|
|
700
|
+
jsr smuls
|
|
701
|
+
clc
|
|
702
|
+
lda acc
|
|
703
|
+
adc prod
|
|
704
|
+
sta acc
|
|
705
|
+
lda acc+1
|
|
706
|
+
adc prod+1
|
|
707
|
+
sta acc+1
|
|
708
|
+
ldx rowi
|
|
709
|
+
lda m+2,x
|
|
710
|
+
sta ma
|
|
711
|
+
lda vzz
|
|
712
|
+
sta mb
|
|
713
|
+
jsr smuls
|
|
714
|
+
clc
|
|
715
|
+
lda acc
|
|
716
|
+
adc prod
|
|
717
|
+
sta acc
|
|
718
|
+
lda acc+1
|
|
719
|
+
adc prod+1
|
|
720
|
+
asl acc // (sum << 2) >> 8 = sum >> 6
|
|
721
|
+
rol
|
|
722
|
+
asl acc
|
|
723
|
+
rol
|
|
724
|
+
rts
|
|
725
|
+
|
|
726
|
+
// transform and project every vertex of obj into px[], py[]
|
|
727
|
+
xform_all:
|
|
728
|
+
ldx obj
|
|
729
|
+
lda o_vn,x
|
|
730
|
+
sta cnt
|
|
731
|
+
lda o_vst,x
|
|
732
|
+
sta idx
|
|
733
|
+
lda #0
|
|
734
|
+
sta tmp // local vertex index
|
|
735
|
+
xf_loop:
|
|
736
|
+
ldy idx
|
|
737
|
+
lda vx,y
|
|
738
|
+
sta vxx
|
|
739
|
+
lda vy,y
|
|
740
|
+
sta vyy
|
|
741
|
+
lda vz,y
|
|
742
|
+
sta vzz
|
|
743
|
+
ldx #6
|
|
744
|
+
jsr dot_row // z
|
|
745
|
+
ldx obj
|
|
746
|
+
clc
|
|
747
|
+
adc o_z,x
|
|
748
|
+
tay
|
|
749
|
+
lda rectab,y
|
|
750
|
+
sta ub
|
|
751
|
+
ldx #0
|
|
752
|
+
jsr dot_row // x
|
|
753
|
+
ldx obj
|
|
754
|
+
clc
|
|
755
|
+
adc o_x,x
|
|
756
|
+
jsr project
|
|
757
|
+
ldx tmp
|
|
758
|
+
sta px,x
|
|
759
|
+
ldx #3
|
|
760
|
+
jsr dot_row // y
|
|
761
|
+
ldx obj
|
|
762
|
+
clc
|
|
763
|
+
adc o_y,x
|
|
764
|
+
jsr project
|
|
765
|
+
ldx tmp
|
|
766
|
+
sta py,x
|
|
767
|
+
inc tmp
|
|
768
|
+
inc idx
|
|
769
|
+
dec cnt
|
|
770
|
+
bne xf_loop
|
|
771
|
+
rts
|
|
772
|
+
|
|
773
|
+
// A = signed camera coordinate, ub = reciprocal factor: A = 128 +- (|A|*f)>>8
|
|
774
|
+
project:
|
|
775
|
+
cmp #$80
|
|
776
|
+
bcs pr_neg
|
|
777
|
+
sta ua
|
|
778
|
+
jsr umul
|
|
779
|
+
lda prod+1
|
|
780
|
+
clc
|
|
781
|
+
adc #128
|
|
782
|
+
rts
|
|
783
|
+
pr_neg: eor #$ff
|
|
784
|
+
clc
|
|
785
|
+
adc #1
|
|
786
|
+
sta ua
|
|
787
|
+
jsr umul
|
|
788
|
+
lda #128
|
|
789
|
+
sec
|
|
790
|
+
sbc prod+1
|
|
791
|
+
rts
|
|
792
|
+
|
|
793
|
+
// visible faces: the projected winding (dx1*dy2 - dy1*dx2) is negative
|
|
794
|
+
cull:
|
|
795
|
+
lda #0
|
|
796
|
+
sta vis
|
|
797
|
+
ldx obj
|
|
798
|
+
lda o_fn,x
|
|
799
|
+
sta cnt
|
|
800
|
+
lda o_fst,x
|
|
801
|
+
sta idx
|
|
802
|
+
lda #0
|
|
803
|
+
sta sysn // local face number
|
|
804
|
+
cu_loop:
|
|
805
|
+
ldy idx
|
|
806
|
+
ldx fa,y
|
|
807
|
+
lda px,x
|
|
808
|
+
sta lx0
|
|
809
|
+
lda py,x
|
|
810
|
+
sta ly0
|
|
811
|
+
ldx fb,y
|
|
812
|
+
lda px,x
|
|
813
|
+
sec
|
|
814
|
+
sbc lx0
|
|
815
|
+
sta ddx // dx1
|
|
816
|
+
lda py,x
|
|
817
|
+
sec
|
|
818
|
+
sbc ly0
|
|
819
|
+
sta ddy // dy1
|
|
820
|
+
ldx fc,y
|
|
821
|
+
lda px,x
|
|
822
|
+
sec
|
|
823
|
+
sbc lx0
|
|
824
|
+
sta lx1 // dx2
|
|
825
|
+
lda py,x
|
|
826
|
+
sec
|
|
827
|
+
sbc ly0
|
|
828
|
+
sta ly1 // dy2
|
|
829
|
+
lda ddx
|
|
830
|
+
sta ma
|
|
831
|
+
lda ly1
|
|
832
|
+
sta mb
|
|
833
|
+
jsr smulg
|
|
834
|
+
lda prod
|
|
835
|
+
sta t1
|
|
836
|
+
lda prod+1
|
|
837
|
+
sta t1+1
|
|
838
|
+
lda ddy
|
|
839
|
+
sta ma
|
|
840
|
+
lda lx1
|
|
841
|
+
sta mb
|
|
842
|
+
jsr smulg
|
|
843
|
+
sec
|
|
844
|
+
lda t1
|
|
845
|
+
sbc prod
|
|
846
|
+
lda t1+1
|
|
847
|
+
sbc prod+1
|
|
848
|
+
bpl !+
|
|
849
|
+
ldx sysn
|
|
850
|
+
lda bit_of,x
|
|
851
|
+
ora vis
|
|
852
|
+
sta vis
|
|
853
|
+
!: inc sysn
|
|
854
|
+
inc idx
|
|
855
|
+
dec cnt
|
|
856
|
+
bne cu_loop
|
|
857
|
+
rts
|
|
858
|
+
|
|
859
|
+
// ---------------------------------------------------------------
|
|
860
|
+
// line with CIA2 running only while it draws
|
|
861
|
+
line_timed:
|
|
862
|
+
bit harness
|
|
863
|
+
bpl line // pass 2: no gate
|
|
864
|
+
inc calls
|
|
865
|
+
bne !+
|
|
866
|
+
inc calls+1
|
|
867
|
+
!: lda #$01
|
|
868
|
+
sta $dd0e // resume timer A
|
|
869
|
+
jsr line
|
|
870
|
+
lda #$00
|
|
871
|
+
sta $dd0e // pause
|
|
872
|
+
rts
|
|
873
|
+
|
|
874
|
+
// Bresenham from (lx0,ly0) to (lx1,ly1), EOR plot; lclip != 0 tests
|
|
875
|
+
// every pixel against the window
|
|
876
|
+
line:
|
|
877
|
+
lda lx1
|
|
878
|
+
sec
|
|
879
|
+
sbc lx0
|
|
880
|
+
bcs !+
|
|
881
|
+
eor #$ff
|
|
882
|
+
adc #1
|
|
883
|
+
!: sta ddx
|
|
884
|
+
lda ly1
|
|
885
|
+
sec
|
|
886
|
+
sbc ly0
|
|
887
|
+
bcs !+
|
|
888
|
+
eor #$ff
|
|
889
|
+
adc #1
|
|
890
|
+
!: sta ddy
|
|
891
|
+
cmp ddx
|
|
892
|
+
bcc x_major
|
|
893
|
+
beq x_major
|
|
894
|
+
jmp y_major
|
|
895
|
+
|
|
896
|
+
x_major:
|
|
897
|
+
lda lx1 // step x upward: swap if x0 > x1
|
|
898
|
+
cmp lx0
|
|
899
|
+
bcs !+
|
|
900
|
+
ldx lx0
|
|
901
|
+
sta lx0
|
|
902
|
+
stx lx1
|
|
903
|
+
lda ly0
|
|
904
|
+
ldx ly1
|
|
905
|
+
sta ly1
|
|
906
|
+
stx ly0
|
|
907
|
+
!: lda #1
|
|
908
|
+
ldx ly1
|
|
909
|
+
cpx ly0
|
|
910
|
+
bcs !+
|
|
911
|
+
lda #$ff
|
|
912
|
+
!: sta sy
|
|
913
|
+
lda ddx
|
|
914
|
+
lsr
|
|
915
|
+
sta err
|
|
916
|
+
ldy ly0
|
|
917
|
+
sty cy
|
|
918
|
+
lda ylo,y
|
|
919
|
+
sta ptr
|
|
920
|
+
lda yhi,y
|
|
921
|
+
sta ptr+1
|
|
922
|
+
ldx lx0
|
|
923
|
+
lda lclip
|
|
924
|
+
bne !+
|
|
925
|
+
XMAJOR(false)
|
|
926
|
+
rts
|
|
927
|
+
!: XMAJOR(true)
|
|
928
|
+
rts
|
|
929
|
+
|
|
930
|
+
y_major:
|
|
931
|
+
lda ly1 // step y downward on screen: swap if y0 > y1
|
|
932
|
+
cmp ly0
|
|
933
|
+
bcs !+
|
|
934
|
+
ldx ly0
|
|
935
|
+
sta ly0
|
|
936
|
+
stx ly1
|
|
937
|
+
lda lx0
|
|
938
|
+
ldx lx1
|
|
939
|
+
sta lx1
|
|
940
|
+
stx lx0
|
|
941
|
+
!: lda #1
|
|
942
|
+
ldx lx1
|
|
943
|
+
cpx lx0
|
|
944
|
+
bcs !+
|
|
945
|
+
lda #$ff
|
|
946
|
+
!: sta sy // x step
|
|
947
|
+
lda ddy
|
|
948
|
+
lsr
|
|
949
|
+
sta err
|
|
950
|
+
lda ly0
|
|
951
|
+
sta cy
|
|
952
|
+
ldx lx0
|
|
953
|
+
lda lclip
|
|
954
|
+
bne !+
|
|
955
|
+
YMAJOR(false)
|
|
956
|
+
rts
|
|
957
|
+
!: YMAJOR(true)
|
|
958
|
+
rts
|
|
959
|
+
|
|
960
|
+
.macro XMAJOR(clip) {
|
|
961
|
+
loop:
|
|
962
|
+
.if (clip) {
|
|
963
|
+
cpx #XMIN
|
|
964
|
+
bcc skip
|
|
965
|
+
cpx #XMAX+1
|
|
966
|
+
bcs skip
|
|
967
|
+
lda cy
|
|
968
|
+
cmp #YMIN
|
|
969
|
+
bcc skip
|
|
970
|
+
cmp #YMAX+1
|
|
971
|
+
bcs skip
|
|
972
|
+
}
|
|
973
|
+
ldy xcol,x
|
|
974
|
+
lda (ptr),y
|
|
975
|
+
eor xmask,x
|
|
976
|
+
sta (ptr),y
|
|
977
|
+
skip:
|
|
978
|
+
cpx lx1
|
|
979
|
+
beq done
|
|
980
|
+
inx
|
|
981
|
+
lda err
|
|
982
|
+
sec
|
|
983
|
+
sbc ddy
|
|
984
|
+
bcs nostep
|
|
985
|
+
adc ddx // carry clear: err - dy + dx
|
|
986
|
+
sta err
|
|
987
|
+
lda cy
|
|
988
|
+
clc
|
|
989
|
+
adc sy
|
|
990
|
+
sta cy
|
|
991
|
+
tay
|
|
992
|
+
lda ylo,y
|
|
993
|
+
sta ptr
|
|
994
|
+
lda yhi,y
|
|
995
|
+
sta ptr+1
|
|
996
|
+
jmp loop
|
|
997
|
+
nostep:
|
|
998
|
+
sta err
|
|
999
|
+
jmp loop
|
|
1000
|
+
done:
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
.macro YMAJOR(clip) {
|
|
1004
|
+
loop:
|
|
1005
|
+
ldy cy
|
|
1006
|
+
lda ylo,y
|
|
1007
|
+
sta ptr
|
|
1008
|
+
lda yhi,y
|
|
1009
|
+
sta ptr+1
|
|
1010
|
+
.if (clip) {
|
|
1011
|
+
cpx #XMIN
|
|
1012
|
+
bcc skip
|
|
1013
|
+
cpx #XMAX+1
|
|
1014
|
+
bcs skip
|
|
1015
|
+
cpy #YMIN
|
|
1016
|
+
bcc skip
|
|
1017
|
+
cpy #YMAX+1
|
|
1018
|
+
bcs skip
|
|
1019
|
+
}
|
|
1020
|
+
ldy xcol,x
|
|
1021
|
+
lda (ptr),y
|
|
1022
|
+
eor xmask,x
|
|
1023
|
+
sta (ptr),y
|
|
1024
|
+
skip:
|
|
1025
|
+
lda cy
|
|
1026
|
+
cmp ly1
|
|
1027
|
+
beq done
|
|
1028
|
+
inc cy
|
|
1029
|
+
lda err
|
|
1030
|
+
sec
|
|
1031
|
+
sbc ddx
|
|
1032
|
+
bcs nostep
|
|
1033
|
+
adc ddy
|
|
1034
|
+
sta err
|
|
1035
|
+
txa
|
|
1036
|
+
clc
|
|
1037
|
+
adc sy
|
|
1038
|
+
tax
|
|
1039
|
+
jmp loop
|
|
1040
|
+
nostep:
|
|
1041
|
+
sta err
|
|
1042
|
+
jmp loop
|
|
1043
|
+
done:
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
// ---------------------------------------------------------------
|
|
1047
|
+
// CIA1 timers A and B chained as a 32-bit down-counter
|
|
1048
|
+
timer_start:
|
|
1049
|
+
lda #0
|
|
1050
|
+
sta $dc0e
|
|
1051
|
+
sta $dc0f
|
|
1052
|
+
lda #$ff
|
|
1053
|
+
sta $dc04
|
|
1054
|
+
sta $dc05
|
|
1055
|
+
sta $dc06
|
|
1056
|
+
sta $dc07
|
|
1057
|
+
lda #$51
|
|
1058
|
+
sta $dc0f
|
|
1059
|
+
lda #$11
|
|
1060
|
+
sta $dc0e
|
|
1061
|
+
rts
|
|
1062
|
+
// stop, read, subtract the measured empty overhead: t0 = cycles
|
|
1063
|
+
timer_stop:
|
|
1064
|
+
lda #0
|
|
1065
|
+
sta $dc0e
|
|
1066
|
+
lda $dc04
|
|
1067
|
+
eor #$ff
|
|
1068
|
+
sta t0
|
|
1069
|
+
lda $dc05
|
|
1070
|
+
eor #$ff
|
|
1071
|
+
sta t0+1
|
|
1072
|
+
lda $dc06
|
|
1073
|
+
eor #$ff
|
|
1074
|
+
sta t0+2
|
|
1075
|
+
lda $dc07
|
|
1076
|
+
eor #$ff
|
|
1077
|
+
sta t0+3
|
|
1078
|
+
sec
|
|
1079
|
+
lda t0
|
|
1080
|
+
sbc ovh
|
|
1081
|
+
sta t0
|
|
1082
|
+
lda t0+1
|
|
1083
|
+
sbc #0
|
|
1084
|
+
sta t0+1
|
|
1085
|
+
lda t0+2
|
|
1086
|
+
sbc #0
|
|
1087
|
+
sta t0+2
|
|
1088
|
+
rts
|
|
1089
|
+
time_empty:
|
|
1090
|
+
lda #0
|
|
1091
|
+
sta ovh
|
|
1092
|
+
jsr timer_start
|
|
1093
|
+
jsr timer_stop
|
|
1094
|
+
lda t0
|
|
1095
|
+
sta ovh
|
|
1096
|
+
rts
|
|
1097
|
+
// CIA2: time one empty resume/pause pair
|
|
1098
|
+
pause_empty:
|
|
1099
|
+
lda #$01
|
|
1100
|
+
sta $dd0e
|
|
1101
|
+
lda #$00
|
|
1102
|
+
sta $dd0e
|
|
1103
|
+
jsr cia2_read
|
|
1104
|
+
lda t0
|
|
1105
|
+
sta povh
|
|
1106
|
+
lda #$10 // reload $ffff, stopped
|
|
1107
|
+
sta $dd0e
|
|
1108
|
+
lda #$51
|
|
1109
|
+
sta $dd0f
|
|
1110
|
+
rts
|
|
1111
|
+
cia2_read:
|
|
1112
|
+
lda $dd04
|
|
1113
|
+
eor #$ff
|
|
1114
|
+
sta t0
|
|
1115
|
+
lda $dd05
|
|
1116
|
+
eor #$ff
|
|
1117
|
+
sta t0+1
|
|
1118
|
+
lda $dd06
|
|
1119
|
+
eor #$ff
|
|
1120
|
+
sta t0+2
|
|
1121
|
+
lda $dd07
|
|
1122
|
+
eor #$ff
|
|
1123
|
+
sta t0+3
|
|
1124
|
+
rts
|
|
1125
|
+
// t0 (24 bits) -= calls * povh, by repeated subtraction
|
|
1126
|
+
mul_ovh_sub:
|
|
1127
|
+
lda calls
|
|
1128
|
+
sta dvs
|
|
1129
|
+
lda calls+1
|
|
1130
|
+
sta dvs+1
|
|
1131
|
+
!loop: lda dvs
|
|
1132
|
+
ora dvs+1
|
|
1133
|
+
beq !done+
|
|
1134
|
+
sec
|
|
1135
|
+
lda t0
|
|
1136
|
+
sbc povh
|
|
1137
|
+
sta t0
|
|
1138
|
+
lda t0+1
|
|
1139
|
+
sbc #0
|
|
1140
|
+
sta t0+1
|
|
1141
|
+
lda t0+2
|
|
1142
|
+
sbc #0
|
|
1143
|
+
sta t0+2
|
|
1144
|
+
lda dvs
|
|
1145
|
+
bne !+
|
|
1146
|
+
dec dvs+1
|
|
1147
|
+
!: dec dvs
|
|
1148
|
+
jmp !loop-
|
|
1149
|
+
!done: rts
|
|
1150
|
+
|
|
1151
|
+
// ---------------------------------------------------------------
|
|
1152
|
+
// Fletcher-style sums over bitmap rows 0-15 in memory order
|
|
1153
|
+
fletcher:
|
|
1154
|
+
lda #<BITMAP
|
|
1155
|
+
sta ptr
|
|
1156
|
+
lda #>BITMAP
|
|
1157
|
+
sta ptr+1
|
|
1158
|
+
lda #0
|
|
1159
|
+
sta fl1
|
|
1160
|
+
sta fl2
|
|
1161
|
+
ldx #20 // 20 pages = 5120 bytes = 16 cell rows
|
|
1162
|
+
ldy #0
|
|
1163
|
+
!: lda (ptr),y
|
|
1164
|
+
clc
|
|
1165
|
+
adc fl1
|
|
1166
|
+
sta fl1
|
|
1167
|
+
clc
|
|
1168
|
+
adc fl2
|
|
1169
|
+
sta fl2
|
|
1170
|
+
iny
|
|
1171
|
+
bne !-
|
|
1172
|
+
inc ptr+1
|
|
1173
|
+
dex
|
|
1174
|
+
bne !-
|
|
1175
|
+
rts
|
|
1176
|
+
|
|
1177
|
+
// ---------------------------------------------------------------
|
|
1178
|
+
// galaxy: s0' = s1, s1' = s2, s2' = s0 + s1 + s2 (16-bit), four twists
|
|
1179
|
+
// a system; the name takes a letter pair from bits 0-4 of s2_hi before
|
|
1180
|
+
// each of the first three twists (four when bit 6 of s0_lo is set)
|
|
1181
|
+
galaxy:
|
|
1182
|
+
lda #$4a
|
|
1183
|
+
sta s0
|
|
1184
|
+
lda #$5a
|
|
1185
|
+
sta s0+1
|
|
1186
|
+
lda #$48
|
|
1187
|
+
sta s1
|
|
1188
|
+
lda #$02
|
|
1189
|
+
sta s1+1
|
|
1190
|
+
lda #$53
|
|
1191
|
+
sta s2
|
|
1192
|
+
lda #$b7
|
|
1193
|
+
sta s2+1
|
|
1194
|
+
lda #0
|
|
1195
|
+
sta sysn
|
|
1196
|
+
sta gworst
|
|
1197
|
+
sta gworst+1
|
|
1198
|
+
gx_sys: jsr timer_start
|
|
1199
|
+
jsr make_system
|
|
1200
|
+
jsr timer_stop
|
|
1201
|
+
lda t0+1
|
|
1202
|
+
cmp gworst+1
|
|
1203
|
+
bcc !+
|
|
1204
|
+
bne !new+
|
|
1205
|
+
lda t0
|
|
1206
|
+
cmp gworst
|
|
1207
|
+
bcc !+
|
|
1208
|
+
!new: lda t0
|
|
1209
|
+
sta gworst
|
|
1210
|
+
lda t0+1
|
|
1211
|
+
sta gworst+1
|
|
1212
|
+
!: inc sysn
|
|
1213
|
+
lda sysn
|
|
1214
|
+
cmp #NSYS
|
|
1215
|
+
bne gx_sys
|
|
1216
|
+
rts
|
|
1217
|
+
|
|
1218
|
+
// one system: coordinates, eight name bytes at gname + 8*sysn, then
|
|
1219
|
+
// the seeds are left twisted four times: the next system
|
|
1220
|
+
make_system:
|
|
1221
|
+
lda sysn
|
|
1222
|
+
asl
|
|
1223
|
+
asl
|
|
1224
|
+
asl
|
|
1225
|
+
tax
|
|
1226
|
+
stx gcol
|
|
1227
|
+
ldy sysn
|
|
1228
|
+
lda s1+1
|
|
1229
|
+
sta gx,y // x = s1_hi
|
|
1230
|
+
lda s0+1
|
|
1231
|
+
lsr
|
|
1232
|
+
sta gy,y // y = s0_hi >> 1
|
|
1233
|
+
lda s0
|
|
1234
|
+
and #$40
|
|
1235
|
+
sta lng
|
|
1236
|
+
lda #0
|
|
1237
|
+
sta pcount
|
|
1238
|
+
ms_pair:
|
|
1239
|
+
lda s2+1
|
|
1240
|
+
and #31
|
|
1241
|
+
sta tmp
|
|
1242
|
+
jsr twist
|
|
1243
|
+
lda pcount
|
|
1244
|
+
cmp #3
|
|
1245
|
+
bcc !+
|
|
1246
|
+
lda lng
|
|
1247
|
+
beq ms_skip
|
|
1248
|
+
!: lda tmp
|
|
1249
|
+
beq ms_skip // pair 0 prints nothing
|
|
1250
|
+
asl
|
|
1251
|
+
tay
|
|
1252
|
+
ldx gcol
|
|
1253
|
+
lda pairs,y
|
|
1254
|
+
sta gname,x
|
|
1255
|
+
inx
|
|
1256
|
+
lda pairs+1,y
|
|
1257
|
+
cmp #'.'
|
|
1258
|
+
beq !+ // '.' is the silent second letter
|
|
1259
|
+
sta gname,x
|
|
1260
|
+
inx
|
|
1261
|
+
!: stx gcol
|
|
1262
|
+
ms_skip:
|
|
1263
|
+
inc pcount
|
|
1264
|
+
lda pcount
|
|
1265
|
+
cmp #4
|
|
1266
|
+
bne ms_pair
|
|
1267
|
+
rts
|
|
1268
|
+
|
|
1269
|
+
twist:
|
|
1270
|
+
clc
|
|
1271
|
+
lda s0
|
|
1272
|
+
adc s1
|
|
1273
|
+
sta gt
|
|
1274
|
+
lda s0+1
|
|
1275
|
+
adc s1+1
|
|
1276
|
+
sta gt+1 // gt = s0 + s1
|
|
1277
|
+
lda s1
|
|
1278
|
+
sta s0
|
|
1279
|
+
lda s1+1
|
|
1280
|
+
sta s0+1
|
|
1281
|
+
lda s2
|
|
1282
|
+
sta s1
|
|
1283
|
+
lda s2+1
|
|
1284
|
+
sta s1+1
|
|
1285
|
+
clc
|
|
1286
|
+
lda gt
|
|
1287
|
+
adc s1
|
|
1288
|
+
sta s2
|
|
1289
|
+
lda gt+1
|
|
1290
|
+
adc s1+1
|
|
1291
|
+
sta s2+1 // s2 = s0 + s1 + old s2
|
|
1292
|
+
rts
|
|
1293
|
+
|
|
1294
|
+
// ---------------------------------------------------------------
|
|
1295
|
+
// readout, printed into bitmap rows 16-24
|
|
1296
|
+
print_all:
|
|
1297
|
+
// galaxy check: names, x, y
|
|
1298
|
+
ldx #0
|
|
1299
|
+
!: lda gname,x
|
|
1300
|
+
cmp exp_names,x
|
|
1301
|
+
beq ok1
|
|
1302
|
+
inc gfail
|
|
1303
|
+
ok1: inx
|
|
1304
|
+
cpx #NSYS*8
|
|
1305
|
+
bne !-
|
|
1306
|
+
ldx #0
|
|
1307
|
+
!: lda gx,x
|
|
1308
|
+
cmp exp_gx,x
|
|
1309
|
+
bne gbad
|
|
1310
|
+
lda gy,x
|
|
1311
|
+
cmp exp_gy,x
|
|
1312
|
+
beq gok
|
|
1313
|
+
gbad: inc gfail
|
|
1314
|
+
gok: inx
|
|
1315
|
+
cpx #NSYS
|
|
1316
|
+
bne !-
|
|
1317
|
+
lda #16
|
|
1318
|
+
ldx #0
|
|
1319
|
+
jsr at
|
|
1320
|
+
ldx #<t_wire
|
|
1321
|
+
ldy #>t_wire
|
|
1322
|
+
jsr str
|
|
1323
|
+
lda fail // wireframe checks only, so far
|
|
1324
|
+
jsr passfail
|
|
1325
|
+
ldx #<t_upd
|
|
1326
|
+
ldy #>t_upd
|
|
1327
|
+
jsr str
|
|
1328
|
+
lda #NF
|
|
1329
|
+
jsr num8
|
|
1330
|
+
ldx #<t_lines
|
|
1331
|
+
ldy #>t_lines
|
|
1332
|
+
jsr str
|
|
1333
|
+
lda last_lines
|
|
1334
|
+
jsr num8
|
|
1335
|
+
|
|
1336
|
+
lda #17
|
|
1337
|
+
ldx #0
|
|
1338
|
+
jsr at
|
|
1339
|
+
ldx #<t_worst
|
|
1340
|
+
ldy #>t_worst
|
|
1341
|
+
jsr str
|
|
1342
|
+
lda worst
|
|
1343
|
+
sta num
|
|
1344
|
+
lda worst+1
|
|
1345
|
+
sta num+1
|
|
1346
|
+
lda worst+2
|
|
1347
|
+
sta num+2
|
|
1348
|
+
jsr num24
|
|
1349
|
+
ldx #<t_last
|
|
1350
|
+
ldy #>t_last
|
|
1351
|
+
jsr str
|
|
1352
|
+
lda u24
|
|
1353
|
+
sta num
|
|
1354
|
+
lda u24+1
|
|
1355
|
+
sta num+1
|
|
1356
|
+
lda u24+2
|
|
1357
|
+
sta num+2
|
|
1358
|
+
jsr num24
|
|
1359
|
+
|
|
1360
|
+
lda #18
|
|
1361
|
+
ldx #0
|
|
1362
|
+
jsr at
|
|
1363
|
+
ldx #<t_calls
|
|
1364
|
+
ldy #>t_calls
|
|
1365
|
+
jsr str
|
|
1366
|
+
lda calls
|
|
1367
|
+
sta num
|
|
1368
|
+
lda calls+1
|
|
1369
|
+
sta num+1
|
|
1370
|
+
lda #0
|
|
1371
|
+
sta num+2
|
|
1372
|
+
jsr num24
|
|
1373
|
+
ldx #<t_cpl
|
|
1374
|
+
ldy #>t_cpl
|
|
1375
|
+
jsr str
|
|
1376
|
+
lda linecyc
|
|
1377
|
+
sta num
|
|
1378
|
+
lda linecyc+1
|
|
1379
|
+
sta num+1
|
|
1380
|
+
lda linecyc+2
|
|
1381
|
+
sta num+2
|
|
1382
|
+
lda calls
|
|
1383
|
+
sta dvs
|
|
1384
|
+
lda calls+1
|
|
1385
|
+
sta dvs+1
|
|
1386
|
+
jsr div24
|
|
1387
|
+
jsr num24
|
|
1388
|
+
|
|
1389
|
+
lda #19
|
|
1390
|
+
ldx #0
|
|
1391
|
+
jsr at
|
|
1392
|
+
ldx #<t_mat
|
|
1393
|
+
ldy #>t_mat
|
|
1394
|
+
jsr str
|
|
1395
|
+
lda mcyc
|
|
1396
|
+
sta num
|
|
1397
|
+
lda mcyc+1
|
|
1398
|
+
sta num+1
|
|
1399
|
+
lda #0
|
|
1400
|
+
sta num+2
|
|
1401
|
+
jsr num24
|
|
1402
|
+
ldx #<t_vtx
|
|
1403
|
+
ldy #>t_vtx
|
|
1404
|
+
jsr str
|
|
1405
|
+
lda vcyc
|
|
1406
|
+
sta num
|
|
1407
|
+
lda vcyc+1
|
|
1408
|
+
sta num+1
|
|
1409
|
+
lda #0
|
|
1410
|
+
sta num+2
|
|
1411
|
+
lda #7 // the ship has 7 vertices
|
|
1412
|
+
sta dvs
|
|
1413
|
+
lda #0
|
|
1414
|
+
sta dvs+1
|
|
1415
|
+
jsr div24
|
|
1416
|
+
jsr num24
|
|
1417
|
+
|
|
1418
|
+
ldx #<t_ship
|
|
1419
|
+
ldy #>t_ship
|
|
1420
|
+
jsr str
|
|
1421
|
+
lda ocyc_lo+2
|
|
1422
|
+
sta num
|
|
1423
|
+
lda ocyc_mid+2
|
|
1424
|
+
sta num+1
|
|
1425
|
+
lda ocyc_hi+2
|
|
1426
|
+
sta num+2
|
|
1427
|
+
jsr num24
|
|
1428
|
+
|
|
1429
|
+
lda #20
|
|
1430
|
+
ldx #0
|
|
1431
|
+
jsr at
|
|
1432
|
+
ldx #<t_gal
|
|
1433
|
+
ldy #>t_gal
|
|
1434
|
+
jsr str
|
|
1435
|
+
lda gfail
|
|
1436
|
+
jsr passfail
|
|
1437
|
+
ldx #<t_sys
|
|
1438
|
+
ldy #>t_sys
|
|
1439
|
+
jsr str
|
|
1440
|
+
lda gworst
|
|
1441
|
+
sta num
|
|
1442
|
+
lda gworst+1
|
|
1443
|
+
sta num+1
|
|
1444
|
+
lda #0
|
|
1445
|
+
sta num+2
|
|
1446
|
+
jsr num24
|
|
1447
|
+
|
|
1448
|
+
// eight systems, two to a row
|
|
1449
|
+
lda #0
|
|
1450
|
+
sta sysn
|
|
1451
|
+
sy_loop:
|
|
1452
|
+
lda sysn
|
|
1453
|
+
lsr
|
|
1454
|
+
clc
|
|
1455
|
+
adc #21
|
|
1456
|
+
pha
|
|
1457
|
+
lda sysn
|
|
1458
|
+
and #1
|
|
1459
|
+
beq !+
|
|
1460
|
+
lda #20
|
|
1461
|
+
!: tax
|
|
1462
|
+
pla
|
|
1463
|
+
jsr at
|
|
1464
|
+
lda sysn
|
|
1465
|
+
asl
|
|
1466
|
+
asl
|
|
1467
|
+
asl
|
|
1468
|
+
sta idx
|
|
1469
|
+
lda #8
|
|
1470
|
+
sta cnt
|
|
1471
|
+
!: ldx idx
|
|
1472
|
+
lda gname,x
|
|
1473
|
+
jsr chr
|
|
1474
|
+
inc idx
|
|
1475
|
+
dec cnt
|
|
1476
|
+
bne !-
|
|
1477
|
+
lda #' '
|
|
1478
|
+
jsr chr
|
|
1479
|
+
ldx sysn
|
|
1480
|
+
lda gx,x
|
|
1481
|
+
jsr num8
|
|
1482
|
+
lda #','
|
|
1483
|
+
jsr chr
|
|
1484
|
+
ldx sysn
|
|
1485
|
+
lda gy,x
|
|
1486
|
+
jsr num8
|
|
1487
|
+
inc sysn
|
|
1488
|
+
lda sysn
|
|
1489
|
+
cmp #NSYS
|
|
1490
|
+
bne sy_loop
|
|
1491
|
+
lda gfail
|
|
1492
|
+
beq !+
|
|
1493
|
+
inc fail
|
|
1494
|
+
!: ldx #39 // status row colour: green PASS, red FAIL
|
|
1495
|
+
lda fail
|
|
1496
|
+
beq !+
|
|
1497
|
+
lda #$20
|
|
1498
|
+
.byte $2c // bit abs: skip the next lda
|
|
1499
|
+
!: lda #$50
|
|
1500
|
+
!: sta MATRIX+16*40,x
|
|
1501
|
+
dex
|
|
1502
|
+
bpl !-
|
|
1503
|
+
rts
|
|
1504
|
+
|
|
1505
|
+
passfail:
|
|
1506
|
+
cmp #0
|
|
1507
|
+
bne !+
|
|
1508
|
+
ldx #<t_pass
|
|
1509
|
+
ldy #>t_pass
|
|
1510
|
+
jmp str
|
|
1511
|
+
!: ldx #<t_fail
|
|
1512
|
+
ldy #>t_fail
|
|
1513
|
+
jmp str
|
|
1514
|
+
|
|
1515
|
+
// cursor to text row A, column X
|
|
1516
|
+
at: sta prow
|
|
1517
|
+
stx pcol
|
|
1518
|
+
rts
|
|
1519
|
+
|
|
1520
|
+
str: stx sptr
|
|
1521
|
+
sty sptr+1
|
|
1522
|
+
ldy #0
|
|
1523
|
+
!: lda (sptr),y
|
|
1524
|
+
beq !+
|
|
1525
|
+
sty tmp
|
|
1526
|
+
jsr chr
|
|
1527
|
+
ldy tmp
|
|
1528
|
+
iny
|
|
1529
|
+
bne !-
|
|
1530
|
+
!: rts
|
|
1531
|
+
|
|
1532
|
+
// copy the ROM glyph of screen code A into the bitmap cell at the cursor
|
|
1533
|
+
chr: sta src
|
|
1534
|
+
lda #0
|
|
1535
|
+
sta src+1
|
|
1536
|
+
asl src
|
|
1537
|
+
rol src+1
|
|
1538
|
+
asl src
|
|
1539
|
+
rol src+1
|
|
1540
|
+
asl src
|
|
1541
|
+
rol src+1
|
|
1542
|
+
lda src+1
|
|
1543
|
+
ora #$d0
|
|
1544
|
+
sta src+1
|
|
1545
|
+
ldx prow
|
|
1546
|
+
lda rowlo,x
|
|
1547
|
+
sta dst
|
|
1548
|
+
lda rowhi,x
|
|
1549
|
+
sta dst+1
|
|
1550
|
+
lda pcol
|
|
1551
|
+
asl
|
|
1552
|
+
asl
|
|
1553
|
+
asl
|
|
1554
|
+
php
|
|
1555
|
+
clc
|
|
1556
|
+
adc dst
|
|
1557
|
+
sta dst
|
|
1558
|
+
lda dst+1
|
|
1559
|
+
adc #0
|
|
1560
|
+
plp
|
|
1561
|
+
adc #0 // column * 8 carries past 255 from column 32
|
|
1562
|
+
sta dst+1
|
|
1563
|
+
lda #$33 // character ROM in, I/O out; IRQs are off
|
|
1564
|
+
sta $01
|
|
1565
|
+
ldy #7
|
|
1566
|
+
!: lda (src),y
|
|
1567
|
+
sta (dst),y
|
|
1568
|
+
dey
|
|
1569
|
+
bpl !-
|
|
1570
|
+
lda #$37
|
|
1571
|
+
sta $01
|
|
1572
|
+
inc pcol
|
|
1573
|
+
rts
|
|
1574
|
+
|
|
1575
|
+
// A as 3 digits, no leading zeros
|
|
1576
|
+
num8: sta num
|
|
1577
|
+
lda #0
|
|
1578
|
+
sta num+1
|
|
1579
|
+
sta num+2
|
|
1580
|
+
// fall through
|
|
1581
|
+
// 24-bit num in decimal, no leading zeros
|
|
1582
|
+
num24: lda #0
|
|
1583
|
+
sta lng // a digit has been printed
|
|
1584
|
+
ldx #0
|
|
1585
|
+
n_dig: lda #0
|
|
1586
|
+
sta dig
|
|
1587
|
+
n_sub: sec
|
|
1588
|
+
lda num
|
|
1589
|
+
sbc p10_0,x
|
|
1590
|
+
sta tmp
|
|
1591
|
+
lda num+1
|
|
1592
|
+
sbc p10_1,x
|
|
1593
|
+
sta t1
|
|
1594
|
+
lda num+2
|
|
1595
|
+
sbc p10_2,x
|
|
1596
|
+
bcc n_out
|
|
1597
|
+
sta num+2
|
|
1598
|
+
lda t1
|
|
1599
|
+
sta num+1
|
|
1600
|
+
lda tmp
|
|
1601
|
+
sta num
|
|
1602
|
+
inc dig
|
|
1603
|
+
jmp n_sub
|
|
1604
|
+
n_out: lda dig
|
|
1605
|
+
ora lng
|
|
1606
|
+
bne !+
|
|
1607
|
+
cpx #7
|
|
1608
|
+
bne n_next // leading zero, not the last digit
|
|
1609
|
+
!: sta lng
|
|
1610
|
+
lda dig
|
|
1611
|
+
ora #$30
|
|
1612
|
+
stx nx
|
|
1613
|
+
jsr chr
|
|
1614
|
+
ldx nx
|
|
1615
|
+
n_next: inx
|
|
1616
|
+
cpx #8
|
|
1617
|
+
bne n_dig
|
|
1618
|
+
rts
|
|
1619
|
+
|
|
1620
|
+
// num (24 bits) /= dvs (16 bits), shift and subtract
|
|
1621
|
+
div24: lda #0
|
|
1622
|
+
sta rmd
|
|
1623
|
+
sta rmd+1
|
|
1624
|
+
ldx #24
|
|
1625
|
+
!: asl num
|
|
1626
|
+
rol num+1
|
|
1627
|
+
rol num+2
|
|
1628
|
+
rol rmd
|
|
1629
|
+
rol rmd+1
|
|
1630
|
+
sec
|
|
1631
|
+
lda rmd
|
|
1632
|
+
sbc dvs
|
|
1633
|
+
tay
|
|
1634
|
+
lda rmd+1
|
|
1635
|
+
sbc dvs+1
|
|
1636
|
+
bcc !+
|
|
1637
|
+
sta rmd+1
|
|
1638
|
+
sty rmd
|
|
1639
|
+
inc num
|
|
1640
|
+
!: dex
|
|
1641
|
+
bne !--
|
|
1642
|
+
rts
|
|
1643
|
+
|
|
1644
|
+
// ---------------------------------------------------------------
|
|
1645
|
+
clear_all:
|
|
1646
|
+
lda #0
|
|
1647
|
+
tay
|
|
1648
|
+
ldx #>BITMAP
|
|
1649
|
+
stx ptr+1
|
|
1650
|
+
sta ptr
|
|
1651
|
+
ldx #32 // $6000-$7fff
|
|
1652
|
+
!: sta (ptr),y
|
|
1653
|
+
iny
|
|
1654
|
+
bne !-
|
|
1655
|
+
inc ptr+1
|
|
1656
|
+
dex
|
|
1657
|
+
bne !-
|
|
1658
|
+
ldx #0 // white on black everywhere
|
|
1659
|
+
lda #$10
|
|
1660
|
+
!: sta MATRIX,x
|
|
1661
|
+
sta MATRIX+$100,x
|
|
1662
|
+
sta MATRIX+$200,x
|
|
1663
|
+
sta MATRIX+$2e8,x
|
|
1664
|
+
inx
|
|
1665
|
+
bne !-
|
|
1666
|
+
rts
|
|
1667
|
+
|
|
1668
|
+
// ---------------------------------------------------------------
|
|
1669
|
+
// data
|
|
1670
|
+
ovh: .byte 0
|
|
1671
|
+
harness: .byte 0
|
|
1672
|
+
povh: .byte 0
|
|
1673
|
+
calls: .word 0
|
|
1674
|
+
tot_lines: .word 0
|
|
1675
|
+
ep_sum: .word 0
|
|
1676
|
+
last_lines: .byte 0
|
|
1677
|
+
worst: .byte 0, 0, 0
|
|
1678
|
+
linecyc: .byte 0, 0, 0
|
|
1679
|
+
mcyc: .word 0
|
|
1680
|
+
vcyc: .word 0
|
|
1681
|
+
gworst: .word 0
|
|
1682
|
+
gfail: .byte 0
|
|
1683
|
+
fl1: .byte 0
|
|
1684
|
+
fl2: .byte 0
|
|
1685
|
+
ocyc_lo: .byte 0, 0, 0
|
|
1686
|
+
ocyc_mid: .byte 0, 0, 0
|
|
1687
|
+
ocyc_hi: .byte 0, 0, 0
|
|
1688
|
+
hslot: .byte 0, 16, 32 // heap slots per object
|
|
1689
|
+
hcount: .byte 0, 0, 0
|
|
1690
|
+
bit_of: .byte 1, 2, 4, 8, 16, 32, 64, 128
|
|
1691
|
+
px: .fill 16, 0
|
|
1692
|
+
py: .fill 16, 0
|
|
1693
|
+
hx0: .fill 48, 0
|
|
1694
|
+
hy0: .fill 48, 0
|
|
1695
|
+
hx1: .fill 48, 0
|
|
1696
|
+
hy1: .fill 48, 0
|
|
1697
|
+
hcl: .fill 48, 0
|
|
1698
|
+
gx: .fill NSYS, 0
|
|
1699
|
+
gy: .fill NSYS, 0
|
|
1700
|
+
gname: .fill NSYS*8, $20
|
|
1701
|
+
p10_0: .byte <10000000, <1000000, <100000, <10000, <1000, <100, <10, <1
|
|
1702
|
+
p10_1: .byte >10000000, >1000000, >100000, >10000, >1000, >100, >10, >1
|
|
1703
|
+
p10_2: .byte (10000000 >> 16), (1000000 >> 16), (100000 >> 16), 0, 0, 0, 0, 0
|
|
1704
|
+
rowlo: .fill 25, <(BITMAP + i*320)
|
|
1705
|
+
rowhi: .fill 25, >(BITMAP + i*320)
|
|
1706
|
+
// this recipe's own two-letter tokens, 0 prints nothing ('.' = silent letter)
|
|
1707
|
+
pairs: .text "..VOKARUZEMOTINAORULPISAEKDUWEO.FEJALOBUHINEYAGUISTAMIROCUALPEXI"
|
|
1708
|
+
t_wire: .text "WIREFRAME @"
|
|
1709
|
+
t_lines: .text " LINES @"
|
|
1710
|
+
t_upd: .text " UPDATES @"
|
|
1711
|
+
t_worst: .text "WORST UPDATE @"
|
|
1712
|
+
t_last: .text " LAST @"
|
|
1713
|
+
t_calls: .text "LINE CALLS @"
|
|
1714
|
+
t_cpl: .text " CYC/LINE @"
|
|
1715
|
+
t_mat: .text "MATRIX @"
|
|
1716
|
+
t_vtx: .text " CYC/VERTEX @"
|
|
1717
|
+
t_ship: .text " SHIP @"
|
|
1718
|
+
t_gal: .text "GALAXY @"
|
|
1719
|
+
t_sys: .text " CYC/SYSTEM @"
|
|
1720
|
+
t_pass: .text "PASS@"
|
|
1721
|
+
t_fail: .text "FAIL@"
|
|
1722
|
+
|
|
1723
|
+
// object model and expected values, from gen.py
|
|
1724
|
+
vx: .byte -30, 30, 30, -30, -30, 30, 30, -30, -32, 32, 32, -32, 0, 0, -44, -16, 16, 44, 16, -16
|
|
1725
|
+
vy: .byte -30, -30, 30, 30, -30, -30, 30, 30, 24, 24, 24, 24, -40, 0, 0, -12, -12, 0, 10, 10
|
|
1726
|
+
vz: .byte -30, -30, -30, -30, 30, 30, 30, 30, -32, -32, 32, 32, 0, 52, -20, -20, -20, -20, -20, -20
|
|
1727
|
+
fa: .byte 3, 6, 7, 2, 0, 7, 1, 2, 3, 0, 3, 1, 2, 3, 4, 5, 6, 6
|
|
1728
|
+
fb: .byte 2, 7, 3, 6, 1, 6, 4, 4, 4, 4, 2, 2, 3, 4, 5, 6, 1, 5
|
|
1729
|
+
fc: .byte 1, 4, 0, 5, 5, 2, 0, 1, 2, 3, 1, 0, 0, 0, 0, 0, 0, 4
|
|
1730
|
+
e0: .byte 0, 0, 0, 1, 1, 2, 2, 3, 4, 4, 5, 6, 0, 0, 0, 1, 1, 2, 2, 3, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 4, 5
|
|
1731
|
+
e1: .byte 1, 3, 4, 2, 5, 3, 6, 7, 5, 7, 6, 7, 1, 3, 4, 2, 4, 3, 4, 4, 1, 2, 3, 4, 5, 6, 2, 6, 3, 4, 5, 6
|
|
1732
|
+
ef0: .byte 0, 0, 2, 0, 3, 0, 3, 2, 1, 1, 1, 1, 0, 3, 0, 1, 0, 2, 1, 2, 0, 0, 1, 2, 3, 4, 0, 5, 1, 2, 3, 4
|
|
1733
|
+
ef1: .byte 4, 2, 4, 3, 4, 5, 5, 5, 4, 2, 3, 5, 4, 4, 3, 4, 1, 4, 2, 3, 5, 1, 2, 3, 4, 5, 6, 6, 6, 6, 6, 6
|
|
1734
|
+
o_vst: .byte 0, 8, 13
|
|
1735
|
+
o_vn: .byte 8, 5, 7
|
|
1736
|
+
o_fst: .byte 0, 6, 11
|
|
1737
|
+
o_fn: .byte 6, 5, 7
|
|
1738
|
+
o_est: .byte 0, 12, 20
|
|
1739
|
+
o_en: .byte 12, 8, 12
|
|
1740
|
+
o_x: .byte -58, -44, 72
|
|
1741
|
+
o_y: .byte -52, 44, 6
|
|
1742
|
+
o_z: .byte 196, 200, 192
|
|
1743
|
+
ang_a: .byte 0, 40, 100
|
|
1744
|
+
ang_b: .byte 20, 0, 60
|
|
1745
|
+
ang_a0: .byte 0, 40, 100
|
|
1746
|
+
ang_b0: .byte 20, 0, 60
|
|
1747
|
+
stp_a: .byte 3, -2, 2
|
|
1748
|
+
stp_b: .byte 2, 3, -3
|
|
1749
|
+
exp_names: .text "GUBUDUISMIBU VOVOFE TIPIRU KAMIFEEKGUHITA HIBUDUHINEYA "
|
|
1750
|
+
exp_gx: .byte 2, 152, 77, 83, 180, 172, 69, 20
|
|
1751
|
+
exp_gy: .byte 45, 102, 121, 104, 65, 88, 124, 86
|
|
1752
|
+
|
|
1753
|
+
// ---------------------------------------------------------------
|
|
1754
|
+
// tables, page aligned, all below the VIC bank at $4000
|
|
1755
|
+
.align $100
|
|
1756
|
+
sqlo: .fill 512, <floor(i*i/4) // unsigned quarter squares, n = 0-511
|
|
1757
|
+
sqhi: .fill 512, >floor(i*i/4)
|
|
1758
|
+
qslo: .fill 256, <floor(sv(i)*sv(i)/4) // signed index: floor(s*s/4)
|
|
1759
|
+
qshi: .fill 256, >floor(sv(i)*sv(i)/4)
|
|
1760
|
+
sintab: .fill 256, floor(64*sin(toRadians(i*360/256)) + 0.5)
|
|
1761
|
+
costab: .fill 256, floor(64*sin(toRadians((i+64)*360/256)) + 0.5)
|
|
1762
|
+
rectab: .fill 256, recip(i) // floor(32768 / z), 255 below 129
|
|
1763
|
+
ylo: .fill 256, <rowaddr(i)
|
|
1764
|
+
yhi: .fill 256, >rowaddr(i)
|
|
1765
|
+
xcol: .fill 256, xcolof(i)
|
|
1766
|
+
xmask: .fill 256, $80 >> ((i + 32) & 7)
|
|
1767
|
+
.assert "tables end below the VIC bank", * <= $4000, true
|
|
1768
|
+
|
|
1769
|
+
.function sv(i) {
|
|
1770
|
+
.if (i < 128) .return i
|
|
1771
|
+
.return i - 256
|
|
1772
|
+
}
|
|
1773
|
+
.function recip(z) {
|
|
1774
|
+
.if (z < 129) .return 255
|
|
1775
|
+
.return floor(32768 / z)
|
|
1776
|
+
}
|
|
1777
|
+
.function rowaddr(vy) { // bitmap address of line vy, column 0
|
|
1778
|
+
.if (vy < YMIN || vy > YMAX) .return BITMAP
|
|
1779
|
+
.var by = vy - YMIN
|
|
1780
|
+
.return BITMAP + floor(by / 8) * 320 + mod(by, 8)
|
|
1781
|
+
}
|
|
1782
|
+
.function xcolof(vx) { // byte offset of column vx in its line
|
|
1783
|
+
.if (vx < XMIN || vx > XMAX) .return 0
|
|
1784
|
+
.return (vx + 32) & $f8
|
|
1785
|
+
}
|
|
1786
|
+
```
|
|
1787
|
+
|
|
1788
|
+
## Build
|
|
1789
|
+
|
|
1790
|
+
```bash
|
|
1791
|
+
java -jar $KICKASS_JAR wireframe-ships.asm -o wireframe-ships.prg
|
|
1792
|
+
```
|
|
1793
|
+
|
|
1794
|
+
The object tables, the start angles and the expected values in the
|
|
1795
|
+
listing were printed by this script (Python 3; Pillow only for the
|
|
1796
|
+
optional picture). It is an integer model of the whole program: the
|
|
1797
|
+
same sine and reciprocal tables, the same matrix, shift and truncation
|
|
1798
|
+
rules, the same winding test, outcodes and Bresenham, with the same
|
|
1799
|
+
endpoint swap and error term, and EOR plotting. It also checks every
|
|
1800
|
+
face decision against a floating-point normal test. The sine,
|
|
1801
|
+
reciprocal and both square tables that KickAssembler builds were read
|
|
1802
|
+
back out of the PRG and are identical to the model's.
|
|
1803
|
+
|
|
1804
|
+
```python
|
|
1805
|
+
#!/usr/bin/env python3
|
|
1806
|
+
# gen.py -- integer model of wireframe-ships.asm and its galaxy readout.
|
|
1807
|
+
# Mirrors the machine code step for step: sine table, rotation matrix,
|
|
1808
|
+
# transform, reciprocal projection, screen-space winding cull, outcodes,
|
|
1809
|
+
# Bresenham with the same endpoint swap and error term, EOR plotting.
|
|
1810
|
+
# Prints the KickAssembler lines for the expected values and writes
|
|
1811
|
+
# model.png, the expected bitmap window, for the screenshot comparison.
|
|
1812
|
+
import math, sys
|
|
1813
|
+
|
|
1814
|
+
NF = 48 # updates the program runs
|
|
1815
|
+
XMIN, XMAX, YMIN, YMAX = 32, 191, 68, 187 # view window in virtual coordinates
|
|
1816
|
+
|
|
1817
|
+
SIN = [math.floor(64 * math.sin(2 * math.pi * i / 256) + 0.5) for i in range(256)]
|
|
1818
|
+
def sn(a): return SIN[a & 255]
|
|
1819
|
+
def cs(a): return SIN[(a + 64) & 255]
|
|
1820
|
+
REC = [255 if z < 129 else 32768 // z for z in range(256)]
|
|
1821
|
+
|
|
1822
|
+
# ---- objects: vertices, faces (first three vertices set the winding), edges ----
|
|
1823
|
+
def edges_of(faces):
|
|
1824
|
+
e = {}
|
|
1825
|
+
for fi, f in enumerate(faces):
|
|
1826
|
+
for k in range(len(f)):
|
|
1827
|
+
a, b = f[k], f[(k + 1) % len(f)]
|
|
1828
|
+
key = (min(a, b), max(a, b))
|
|
1829
|
+
e.setdefault(key, []).append(fi)
|
|
1830
|
+
out = []
|
|
1831
|
+
for (a, b), fl in sorted(e.items()):
|
|
1832
|
+
assert len(fl) == 2, (a, b, fl)
|
|
1833
|
+
out.append((a, b, fl[0], fl[1]))
|
|
1834
|
+
return out
|
|
1835
|
+
|
|
1836
|
+
C = 30
|
|
1837
|
+
cube_v = [(-C,-C,-C),(C,-C,-C),(C,C,-C),(-C,C,-C),(-C,-C,C),(C,-C,C),(C,C,C),(-C,C,C)]
|
|
1838
|
+
cube_f = [(0,1,2,3),(5,4,7,6),(4,0,3,7),(1,5,6,2),(4,5,1,0),(3,2,6,7)]
|
|
1839
|
+
pyr_v = [(-32,24,-32),(32,24,-32),(32,24,32),(-32,24,32),(0,-40,0)]
|
|
1840
|
+
pyr_f = [(0,4,1),(1,4,2),(2,4,3),(3,4,0),(0,1,2,3)]
|
|
1841
|
+
# ship: a nose over a flat hexagonal stern (original design)
|
|
1842
|
+
ship_v = [(0,0,52),(-44,0,-20),(-16,-12,-20),(16,-12,-20),(44,0,-20),(16,10,-20),(-16,10,-20)]
|
|
1843
|
+
ship_f = [(0,2,1),(0,3,2),(0,4,3),(0,5,4),(0,6,5),(0,1,6),(1,2,3,4,5,6)]
|
|
1844
|
+
|
|
1845
|
+
OBJS = [ # vertices, faces, position (ox, oy, oz), start angles (a, b), steps (da, db)
|
|
1846
|
+
dict(v=cube_v, f=cube_f, pos=(-58,-52,196), ang=(0,20), step=(3,2)),
|
|
1847
|
+
dict(v=pyr_v, f=pyr_f, pos=(-44,44,200), ang=(40,0), step=(-2,3)),
|
|
1848
|
+
dict(v=ship_v, f=ship_f, pos=(72,6,192), ang=(100,60), step=(2,-3)),
|
|
1849
|
+
]
|
|
1850
|
+
|
|
1851
|
+
def fix_winding():
|
|
1852
|
+
# Order each face so that the machine's rule (cross > 0 = visible) holds
|
|
1853
|
+
# for a face whose outward normal points at the camera: tested once at
|
|
1854
|
+
# angle 0 in float, face by face.
|
|
1855
|
+
for o in OBJS:
|
|
1856
|
+
cx = sum(p[0] for p in o['v']) / len(o['v'])
|
|
1857
|
+
cy = sum(p[1] for p in o['v']) / len(o['v'])
|
|
1858
|
+
cz = sum(p[2] for p in o['v']) / len(o['v'])
|
|
1859
|
+
nf = []
|
|
1860
|
+
for f in o['f']:
|
|
1861
|
+
a, b, c = (o['v'][i] for i in f[:3])
|
|
1862
|
+
u = [b[i]-a[i] for i in range(3)]; w = [c[i]-a[i] for i in range(3)]
|
|
1863
|
+
n = [u[1]*w[2]-u[2]*w[1], u[2]*w[0]-u[0]*w[2], u[0]*w[1]-u[1]*w[0]]
|
|
1864
|
+
m = [sum(o['v'][i][k] for i in f)/len(f) for k in range(3)]
|
|
1865
|
+
out = (m[0]-cx)*n[0] + (m[1]-cy)*n[1] + (m[2]-cz)*n[2]
|
|
1866
|
+
nf.append(tuple(f) if out > 0 else tuple(reversed(f)))
|
|
1867
|
+
o['f'] = nf
|
|
1868
|
+
o['e'] = edges_of(nf)
|
|
1869
|
+
|
|
1870
|
+
def matrix(a, b):
|
|
1871
|
+
sa, ca, sb, cb = sn(a), cs(a), sn(b), cs(b)
|
|
1872
|
+
return [[ca, 0, sa],
|
|
1873
|
+
[(sa*sb) >> 6, cb, -((ca*sb) >> 6)],
|
|
1874
|
+
[-((sa*cb) >> 6), sb, (ca*cb) >> 6]]
|
|
1875
|
+
|
|
1876
|
+
def project(o, M):
|
|
1877
|
+
ox, oy, oz = o['pos']
|
|
1878
|
+
pts = []
|
|
1879
|
+
for (x, y, z) in o['v']:
|
|
1880
|
+
r = [(M[i][0]*x + M[i][1]*y + M[i][2]*z) >> 6 for i in range(3)]
|
|
1881
|
+
for i in range(3): assert -128 <= r[i] <= 127
|
|
1882
|
+
xc, yc, zc = ox + r[0], oy + r[1], oz + r[2]
|
|
1883
|
+
assert -127 <= xc <= 127 and -127 <= yc <= 127 and 129 <= zc <= 255, (xc, yc, zc)
|
|
1884
|
+
f = REC[zc]
|
|
1885
|
+
px = (abs(xc) * f) >> 8; py = (abs(yc) * f) >> 8
|
|
1886
|
+
pts.append((128 + (px if xc >= 0 else -px), 128 + (py if yc >= 0 else -py), (xc, yc, zc)))
|
|
1887
|
+
return pts
|
|
1888
|
+
|
|
1889
|
+
def faces_visible(o, pts, M):
|
|
1890
|
+
mask = 0
|
|
1891
|
+
for fi, f in enumerate(o['f']):
|
|
1892
|
+
p0, p1, p2 = (pts[i] for i in f[:3])
|
|
1893
|
+
dx1, dy1, dx2, dy2 = p1[0]-p0[0], p1[1]-p0[1], p2[0]-p0[0], p2[1]-p0[1]
|
|
1894
|
+
for d in (dx1, dy1, dx2, dy2): assert -127 <= d <= 127, d
|
|
1895
|
+
c = dx1*dy2 - dy1*dx2
|
|
1896
|
+
assert -32768 <= c <= 32767
|
|
1897
|
+
if c < 0: mask |= 1 << fi
|
|
1898
|
+
return mask
|
|
1899
|
+
|
|
1900
|
+
def outcode(x, y):
|
|
1901
|
+
return (1 if x < XMIN else 0) | (2 if x > XMAX else 0) | (4 if y < YMIN else 0) | (8 if y > YMAX else 0)
|
|
1902
|
+
|
|
1903
|
+
def line_pixels(x0, y0, x1, y1):
|
|
1904
|
+
dx, dy = abs(x1-x0), abs(y1-y0)
|
|
1905
|
+
px = []
|
|
1906
|
+
if dx >= dy:
|
|
1907
|
+
if x0 > x1: x0, y0, x1, y1 = x1, y1, x0, y0
|
|
1908
|
+
sy = 1 if y1 >= y0 else -1
|
|
1909
|
+
err, x, y = dx >> 1, x0, y0
|
|
1910
|
+
while True:
|
|
1911
|
+
px.append((x, y))
|
|
1912
|
+
if x == x1: break
|
|
1913
|
+
err -= dy
|
|
1914
|
+
if err < 0: err += dx; y += sy
|
|
1915
|
+
x += 1
|
|
1916
|
+
else:
|
|
1917
|
+
if y0 > y1: x0, y0, x1, y1 = x1, y1, x0, y0
|
|
1918
|
+
sx = 1 if x1 >= x0 else -1
|
|
1919
|
+
err, x, y = dy >> 1, x0, y0
|
|
1920
|
+
while True:
|
|
1921
|
+
px.append((x, y))
|
|
1922
|
+
if y == y1: break
|
|
1923
|
+
err -= dx
|
|
1924
|
+
if err < 0: err += dy; x += sx
|
|
1925
|
+
y += 1
|
|
1926
|
+
return px
|
|
1927
|
+
|
|
1928
|
+
def lines_for(o, a, b):
|
|
1929
|
+
M = matrix(a, b)
|
|
1930
|
+
pts = project(o, M)
|
|
1931
|
+
vis = faces_visible(o, pts, M)
|
|
1932
|
+
out = []
|
|
1933
|
+
for (v0, v1, fa, fb) in o['e']:
|
|
1934
|
+
if not (vis >> fa & 1 or vis >> fb & 1): continue
|
|
1935
|
+
x0, y0 = pts[v0][:2]; x1, y1 = pts[v1][:2]
|
|
1936
|
+
c0, c1 = outcode(x0, y0), outcode(x1, y1)
|
|
1937
|
+
if c0 & c1: continue # trivial reject
|
|
1938
|
+
out.append((x0, y0, x1, y1, 1 if (c0 | c1) else 0))
|
|
1939
|
+
return out, vis, pts, M
|
|
1940
|
+
|
|
1941
|
+
def float_cull(o, a, b):
|
|
1942
|
+
# reference: outward normal . (face point - camera) < 0, in float
|
|
1943
|
+
ra, rb = 2*math.pi*a/256, 2*math.pi*b/256
|
|
1944
|
+
def rot(p):
|
|
1945
|
+
x, y, z = p
|
|
1946
|
+
x1, z1 = x*math.cos(ra) + z*math.sin(ra), -x*math.sin(ra) + z*math.cos(ra)
|
|
1947
|
+
return (x1, y*math.cos(rb) - z1*math.sin(rb), y*math.sin(rb) + z1*math.cos(rb))
|
|
1948
|
+
mask, margin = 0, []
|
|
1949
|
+
for fi, f in enumerate(o['f']):
|
|
1950
|
+
P = [rot(o['v'][i]) for i in f[:3]]
|
|
1951
|
+
u = [P[1][k]-P[0][k] for k in range(3)]; w = [P[2][k]-P[0][k] for k in range(3)]
|
|
1952
|
+
n = [u[1]*w[2]-u[2]*w[1], u[2]*w[0]-u[0]*w[2], u[0]*w[1]-u[1]*w[0]]
|
|
1953
|
+
q = [P[0][k] + o['pos'][k] for k in range(3)]
|
|
1954
|
+
d = sum(n[k]*q[k] for k in range(3)) / (math.sqrt(sum(t*t for t in n)) * math.sqrt(sum(t*t for t in q)))
|
|
1955
|
+
if d < 0: mask |= 1 << fi
|
|
1956
|
+
margin.append(abs(d))
|
|
1957
|
+
return mask, margin
|
|
1958
|
+
|
|
1959
|
+
def run():
|
|
1960
|
+
fix_winding()
|
|
1961
|
+
bm = {}
|
|
1962
|
+
total_lines = 0; ck = 0; line_calls = 0
|
|
1963
|
+
heaps = [[] for _ in OBJS]
|
|
1964
|
+
ang = [list(o['ang']) for o in OBJS]
|
|
1965
|
+
cull_mismatch = 0
|
|
1966
|
+
per_frame = []
|
|
1967
|
+
for fr in range(NF):
|
|
1968
|
+
frame_lines = 0; frame_pix = 0
|
|
1969
|
+
for i, o in enumerate(OBJS):
|
|
1970
|
+
ang[i][0] = (ang[i][0] + o['step'][0]) & 255
|
|
1971
|
+
ang[i][1] = (ang[i][1] + o['step'][1]) & 255
|
|
1972
|
+
new, vis, pts, M = lines_for(o, *ang[i])
|
|
1973
|
+
fm, margin = float_cull(o, *ang[i])
|
|
1974
|
+
if fm != vis:
|
|
1975
|
+
bad = [k for k in range(len(o['f'])) if (fm ^ vis) >> k & 1]
|
|
1976
|
+
if any(margin[k] > 0.02 for k in bad): cull_mismatch += 1 # beyond 0.02 of edge-on
|
|
1977
|
+
for L in heaps[i] + new: # erase old, draw new
|
|
1978
|
+
line_calls += 1
|
|
1979
|
+
for (x, y) in line_pixels(*L[:4]):
|
|
1980
|
+
frame_pix += 1
|
|
1981
|
+
if XMIN <= x <= XMAX and YMIN <= y <= YMAX:
|
|
1982
|
+
bm[(x, y)] = bm.get((x, y), 0) ^ 1
|
|
1983
|
+
heaps[i] = new
|
|
1984
|
+
for L in new:
|
|
1985
|
+
total_lines += 1; ck = (ck + L[0] + L[1] + L[2] + L[3]) & 0xFFFF
|
|
1986
|
+
frame_lines += len(new)
|
|
1987
|
+
per_frame.append((frame_lines, frame_pix))
|
|
1988
|
+
return bm, heaps, total_lines, ck, cull_mismatch, per_frame, line_calls, ang
|
|
1989
|
+
|
|
1990
|
+
def fletcher(bm):
|
|
1991
|
+
# bitmap bytes of rows 0-15 (cells), in memory order, as the program sums them
|
|
1992
|
+
s1 = s2 = 0; pop = 0
|
|
1993
|
+
for row in range(16):
|
|
1994
|
+
for col in range(40):
|
|
1995
|
+
for ln in range(8):
|
|
1996
|
+
by = row*8 + ln; byte = 0
|
|
1997
|
+
for bit in range(8):
|
|
1998
|
+
bx = col*8 + bit; vx, vy = bx - 32, by + 68
|
|
1999
|
+
if bm.get((vx, vy), 0): byte |= 0x80 >> bit; pop += 1
|
|
2000
|
+
s1 = (s1 + byte) & 255; s2 = (s2 + s1) & 255
|
|
2001
|
+
return s1, s2, pop
|
|
2002
|
+
|
|
2003
|
+
# ---- galaxy ----
|
|
2004
|
+
PAIRS = "..VOKARUZEMOTINAORULPISAEKDUWEO.FEJALOBUHINEYAGUISTAMIROCUALPEXI"
|
|
2005
|
+
def twist(s): return [s[1], s[2], (s[0] + s[1] + s[2]) & 0xFFFF]
|
|
2006
|
+
def galaxy(n):
|
|
2007
|
+
s = [0x5A4A, 0x0248, 0xB753]; out = []
|
|
2008
|
+
for _ in range(n):
|
|
2009
|
+
long_ = s[0] & 0x40; t = list(s); name = ""
|
|
2010
|
+
for k in range(4):
|
|
2011
|
+
p = (t[2] >> 8) & 31; t = twist(t)
|
|
2012
|
+
if (k < 3 or long_) and p: name += PAIRS[2*p:2*p+2].replace('.', '')
|
|
2013
|
+
out.append((name, s[1] >> 8, (s[0] >> 8) >> 1, list(s)))
|
|
2014
|
+
s = t
|
|
2015
|
+
return out
|
|
2016
|
+
|
|
2017
|
+
def emit_data():
|
|
2018
|
+
fix_winding()
|
|
2019
|
+
def row(label, vals): print("%-8s .byte %s" % (label + ":", ", ".join(str(v) for v in vals)))
|
|
2020
|
+
vs, fs, es = [], [], []
|
|
2021
|
+
row("vx", [p[0] for o in OBJS for p in o['v']])
|
|
2022
|
+
row("vy", [p[1] for o in OBJS for p in o['v']])
|
|
2023
|
+
row("vz", [p[2] for o in OBJS for p in o['v']])
|
|
2024
|
+
row("fa", [f[0] for o in OBJS for f in o['f']])
|
|
2025
|
+
row("fb", [f[1] for o in OBJS for f in o['f']])
|
|
2026
|
+
row("fc", [f[2] for o in OBJS for f in o['f']])
|
|
2027
|
+
row("e0", [e[0] for o in OBJS for e in o['e']])
|
|
2028
|
+
row("e1", [e[1] for o in OBJS for e in o['e']])
|
|
2029
|
+
row("ef0", [e[2] for o in OBJS for e in o['e']])
|
|
2030
|
+
row("ef1", [e[3] for o in OBJS for e in o['e']])
|
|
2031
|
+
acc = [0, 0, 0]; st = [[], [], []]
|
|
2032
|
+
for o in OBJS:
|
|
2033
|
+
for k, key in enumerate(('v', 'f', 'e')):
|
|
2034
|
+
st[k].append(acc[k]); acc[k] += len(o[key])
|
|
2035
|
+
row("o_vst", st[0]); row("o_vn", [len(o['v']) for o in OBJS])
|
|
2036
|
+
row("o_fst", st[1]); row("o_fn", [len(o['f']) for o in OBJS])
|
|
2037
|
+
row("o_est", st[2]); row("o_en", [len(o['e']) for o in OBJS])
|
|
2038
|
+
row("o_x", [o['pos'][0] for o in OBJS]); row("o_y", [o['pos'][1] for o in OBJS]); row("o_z", [o['pos'][2] for o in OBJS])
|
|
2039
|
+
row("ang_a", [o['ang'][0] for o in OBJS]); row("ang_b", [o['ang'][1] for o in OBJS])
|
|
2040
|
+
row("ang_a0", [o['ang'][0] for o in OBJS]); row("ang_b0", [o['ang'][1] for o in OBJS])
|
|
2041
|
+
row("stp_a", [o['step'][0] for o in OBJS]); row("stp_b", [o['step'][1] for o in OBJS])
|
|
2042
|
+
g = galaxy(8)
|
|
2043
|
+
print('exp_names: .text "%s"' % "".join(n.ljust(8) for n, x, y, s in g))
|
|
2044
|
+
row("exp_gx", [x for n, x, y, s in g]); row("exp_gy", [y for n, x, y, s in g])
|
|
2045
|
+
|
|
2046
|
+
if __name__ == "__main__":
|
|
2047
|
+
bm, heaps, total, ck, mism, pf, calls, ang = run()
|
|
2048
|
+
s1, s2, pop = fletcher(bm)
|
|
2049
|
+
last = sum(len(h) for h in heaps)
|
|
2050
|
+
print("// model: %d lines in the last update, %d over the run, "
|
|
2051
|
+
"cull mismatches beyond 0.02 of edge-on %d" % (last, total, mism))
|
|
2052
|
+
print("// model: %d line calls, %d pixels visited, %d set in the window" % (calls, sum(p for l, p in pf), pop))
|
|
2053
|
+
print(".const EXP_LAST = %d" % last)
|
|
2054
|
+
print(".const EXP_TOTAL = %d" % total)
|
|
2055
|
+
print(".const EXP_SUM = $%04x" % ck)
|
|
2056
|
+
print(".const EXP_S1 = $%02x" % s1)
|
|
2057
|
+
print(".const EXP_S2 = $%02x" % s2)
|
|
2058
|
+
emit_data()
|
|
2059
|
+
for name, x, y, s in galaxy(8):
|
|
2060
|
+
print("// %-8s x=%3d y=%3d seeds %s" % (name, x, y, " ".join("%04X" % v for v in s)))
|
|
2061
|
+
if len(sys.argv) > 1: # expected bitmap rows 0-15, 320 x 128
|
|
2062
|
+
from PIL import Image
|
|
2063
|
+
im = Image.new("L", (320, 128), 0)
|
|
2064
|
+
for (x, y), v in bm.items():
|
|
2065
|
+
if v: im.putpixel((x + 32, y - 68), 255)
|
|
2066
|
+
im.save(sys.argv[1])
|
|
2067
|
+
```
|
|
2068
|
+
|
|
2069
|
+
`python3 gen.py model.png` prints:
|
|
2070
|
+
|
|
2071
|
+
```text
|
|
2072
|
+
// model: 19 lines in the last update, 1005 over the run, cull mismatches beyond 0.02 of edge-on 0
|
|
2073
|
+
// model: 1991 line calls, 64728 pixels visited, 575 set in the window
|
|
2074
|
+
.const EXP_LAST = 19
|
|
2075
|
+
.const EXP_TOTAL = 1005
|
|
2076
|
+
.const EXP_SUM = $84ea
|
|
2077
|
+
.const EXP_S1 = $8c
|
|
2078
|
+
.const EXP_S2 = $99
|
|
2079
|
+
```
|
|
2080
|
+
|
|
2081
|
+
then the data lines of the listing, then the eight systems:
|
|
2082
|
+
|
|
2083
|
+
```text
|
|
2084
|
+
// GUBUDUIS x= 2 y= 45 seeds 5A4A 0248 B753
|
|
2085
|
+
// MIBU x=152 y=102 seeds CD80 98B8 7A1D
|
|
2086
|
+
// VOVOFE x= 77 y=121 seeds F32A 4D9C 211B
|
|
2087
|
+
// TIPIRU x= 83 y=104 seeds D098 5394 860D
|
|
2088
|
+
// KAMIFEEK x=180 y= 65 seeds 83DA B420 E233
|
|
2089
|
+
// GUHITA x=172 y= 88 seeds B080 ACE0 778D
|
|
2090
|
+
// HIBUDUHI x= 69 y=124 seeds F95A 45D4 141B
|
|
2091
|
+
// NEYA x= 20 y= 86 seeds AD38 149C 151D
|
|
2092
|
+
```
|
|
2093
|
+
|
|
2094
|
+
The screenshot check compares bitmap rows 0-15 of the exit screenshot
|
|
2095
|
+
with `model.png` pixel by pixel and decodes the readout with the
|
|
2096
|
+
character ROM:
|
|
2097
|
+
|
|
2098
|
+
```python
|
|
2099
|
+
#!/usr/bin/env python3
|
|
2100
|
+
# check_shot.py -- compare the exit screenshot's bitmap rows 0-15 with the
|
|
2101
|
+
# model picture from gen.py, and decode the readout rows with the char ROM.
|
|
2102
|
+
# usage: check_shot.py shot.png model.png pal|ntsc chargen-901225-01.bin
|
|
2103
|
+
import sys
|
|
2104
|
+
from PIL import Image
|
|
2105
|
+
shot, model, region, romfile = sys.argv[1:5]
|
|
2106
|
+
top = 35 if region == "pal" else 23 # screenshot row of raster line 51
|
|
2107
|
+
im = Image.open(shot).convert("RGB"); md = Image.open(model)
|
|
2108
|
+
bad = sum((im.getpixel((32 + x, top + y)) != (0, 0, 0)) != (md.getpixel((x, y)) > 0)
|
|
2109
|
+
for y in range(128) for x in range(320))
|
|
2110
|
+
print("pixels differing from the model:", bad)
|
|
2111
|
+
rom = open(romfile, "rb").read()
|
|
2112
|
+
glyph = {tuple(rom[c*8:c*8+8]): c for c in range(64)}
|
|
2113
|
+
for row in range(16, 25):
|
|
2114
|
+
line = ""
|
|
2115
|
+
for col in range(40):
|
|
2116
|
+
cell = tuple(sum(0x80 >> b for b in range(8)
|
|
2117
|
+
if im.getpixel((32 + col*8 + b, top + row*8 + n)) != (0, 0, 0))
|
|
2118
|
+
for n in range(8))
|
|
2119
|
+
c = glyph.get(cell, 63) if any(cell) else 32
|
|
2120
|
+
line += chr(64 + c) if 1 <= c <= 26 else chr(c) if c >= 32 else "@"
|
|
2121
|
+
print(line.rstrip())
|
|
2122
|
+
```
|
|
2123
|
+
|
|
2124
|
+
## Expected output
|
|
2125
|
+
|
|
2126
|
+
Border green. The window shows the three objects in white on black;
|
|
2127
|
+
below it, decoded from the PNG with the character ROM (the status row is
|
|
2128
|
+
green, the rest white):
|
|
2129
|
+
|
|
2130
|
+
```text
|
|
2131
|
+
WIREFRAME PASS UPDATES 48 LINES 19
|
|
2132
|
+
WORST UPDATE 155708 LAST 131620
|
|
2133
|
+
LINE CALLS 1991 CYC/LINE 2350
|
|
2134
|
+
MATRIX 523 CYC/VERTEX 1179 SHIP 47467
|
|
2135
|
+
GALAXY PASS CYC/SYSTEM 733
|
|
2136
|
+
GUBUDUIS 2,45 MIBU 152,102
|
|
2137
|
+
VOVOFE 77,121 TIPIRU 83,104
|
|
2138
|
+
KAMIFEEK 180,65 GUHITA 172,88
|
|
2139
|
+
HIBUDUHI 69,124 NEYA 20,86
|
|
2140
|
+
```
|
|
2141
|
+
|
|
2142
|
+
That is the PAL screen. The NTSC screen differs only in the timings:
|
|
2143
|
+
`WORST UPDATE 157212 LAST 133169`, `CYC/LINE 2370`,
|
|
2144
|
+
`MATRIX 522 CYC/VERTEX 1228 SHIP 48152`, `CYC/SYSTEM 733`.
|
|
2145
|
+
|
|
2146
|
+
Screenshots from the pinned run, 20,000,000 cycles:
|
|
2147
|
+
`screenshots/wireframe-ships.png` (PAL) and
|
|
2148
|
+
`screenshots/wireframe-ships-ntsc.png` (NTSC). In both, bitmap rows
|
|
2149
|
+
0-15 match `model.png` with 0 differing pixels, and 575 pixels are set,
|
|
2150
|
+
the model's count. The border pixel (5, 5) is (98, 213, 50) on PAL and
|
|
2151
|
+
(114, 189, 103) on NTSC, palette index 5 in `runtime/vice-reference.md`.
|
|
2152
|
+
The pinned command was run twice per model and the two PNGs were
|
|
2153
|
+
identical bytes each time. At 17,000,000 cycles the PAL readout is not
|
|
2154
|
+
yet complete.
|
|
2155
|
+
|
|
2156
|
+
The figures, measured in VICE x64sc 3.10 with the display on, so every
|
|
2157
|
+
figure includes the cycles badlines take:
|
|
2158
|
+
|
|
2159
|
+
| Figure | PAL | NTSC | What was timed |
|
|
2160
|
+
|---|---|---|---|
|
|
2161
|
+
| Worst update of pass 2 | 155,708 | 157,212 | all three objects, CIA1 per object, summed |
|
|
2162
|
+
| Last update of pass 2 | 131,620 | 133,169 | the frozen picture's update |
|
|
2163
|
+
| Cycles per line call | 2,350 | 2,370 | CIA2 total over the 1,991 erase and draw calls of pass 1, gate overhead removed |
|
|
2164
|
+
| Matrix build | 523 | 522 | one `build_matrix` |
|
|
2165
|
+
| Transform and project, per vertex | 1,179 | 1,228 | `xform_all` on the ship's 7 vertices, divided by 7 |
|
|
2166
|
+
| Ship, last update | 47,467 | 48,152 | matrix, 7 vertices, 7 faces, erase and draw |
|
|
2167
|
+
| One galaxy system, worst of 8 | 733 | 733 | coordinates, name, four twists |
|
|
2168
|
+
|
|
2169
|
+
Derived by arithmetic from those: the worst update is 7.9 PAL frames
|
|
2170
|
+
(19,656 cycles) and 9.2 NTSC frames (17,095 cycles), so this code
|
|
2171
|
+
animates at about 6 updates a second. The model visits 64,728 pixels in
|
|
2172
|
+
the 1,991 line calls, 32.5 a line, so a line costs about 72 cycles a
|
|
2173
|
+
pixel with its set-up spread over it. Line calls average 97,500 cycles
|
|
2174
|
+
an update (1,991 calls at 2,350 cycles over 48 updates): 74% of the last
|
|
2175
|
+
update and 63% of the worst.
|
|
2176
|
+
|
|
2177
|
+
## Why this works
|
|
2178
|
+
|
|
2179
|
+
**Rotation.** The sine table holds `round(64 * sin)`, so a matrix entry
|
|
2180
|
+
is a signed byte from -64 to 64. The matrix is rotation about y by
|
|
2181
|
+
angle `a` followed by rotation about x by angle `b`; its four products
|
|
2182
|
+
of two sines are shifted right 6. A row times a vertex is three signed
|
|
2183
|
+
products summed in 16 bits; shifting the sum left twice and taking the
|
|
2184
|
+
high byte is the sum shifted right 6, rounded down. The signed multiply
|
|
2185
|
+
is `sq[a + b] - sq[a - b]` with `sq[s] = floor(s * s / 4)` indexed by
|
|
2186
|
+
the signed byte `s`. It needs no sign handling, provided `a + b` and
|
|
2187
|
+
`a - b` stay within -128 to 128. Matrix entries are at most 64 and
|
|
2188
|
+
vertex coordinates at most 52, so they do; `s = 128` wraps to -128, and
|
|
2189
|
+
both have the same square. The two floors cancel because `a + b` and
|
|
2190
|
+
`a - b` have the same parity.
|
|
2191
|
+
|
|
2192
|
+
**Projection.** Camera z runs from 129 to 255 by placement (the model
|
|
2193
|
+
asserts it on every vertex of every update), and
|
|
2194
|
+
`rectab[z] = floor(32768 / z)` fits a byte there. Screen x is
|
|
2195
|
+
`128 + (|x| * rectab[z]) >> 8` with the sign of x put back afterwards,
|
|
2196
|
+
so the result truncates towards zero on both sides. That product uses
|
|
2197
|
+
the unsigned quarter-square tables of 512 entries, because
|
|
2198
|
+
`|x| + rectab[z]` reaches 382.
|
|
2199
|
+
|
|
2200
|
+
**Culling.** A face is drawn when its first three projected vertices
|
|
2201
|
+
turn one way on the screen (`dx1 * dy2 - dy1 * dx2 < 0`). The model
|
|
2202
|
+
orders every face's vertices so that this holds for a face whose outward
|
|
2203
|
+
normal points at the camera. With perspective this test is exact apart
|
|
2204
|
+
from rounding: over the 864 face tests of the run it disagreed with a
|
|
2205
|
+
floating-point normal test 5 times. In each, the cosine between the face
|
|
2206
|
+
normal and the line of sight was within 0.018 of 0, about 1 degree from
|
|
2207
|
+
edge-on. The model counts a disagreement only beyond 0.02 of edge-on,
|
|
2208
|
+
and there were none. That check is in the Python model only; the listing
|
|
2209
|
+
does not do it. An edge is drawn when either of its two faces is
|
|
2210
|
+
visible, and only once. That matters with EOR, because an edge drawn
|
|
2211
|
+
twice would cancel itself.
|
|
2212
|
+
|
|
2213
|
+
**Clipping.** Each endpoint gets an outcode (left, right, above, below).
|
|
2214
|
+
If the two outcodes share a bit, the line is wholly outside and is
|
|
2215
|
+
dropped. If both are 0, the line is drawn with the loop that does not
|
|
2216
|
+
test pixels. Otherwise it is drawn with the loop that skips pixels
|
|
2217
|
+
outside the window. Bresenham then yields the same inside pixels as a
|
|
2218
|
+
line cut at the edge, so the model needs no intersection arithmetic.
|
|
2219
|
+
All coordinates fit a byte because the window is smaller than the
|
|
2220
|
+
virtual screen.
|
|
2221
|
+
|
|
2222
|
+
**Lines.** The line steps along its longer axis, swapping the ends so
|
|
2223
|
+
that the step is +1. The error term starts at half the long delta. Each
|
|
2224
|
+
step subtracts the short delta; when that borrows, the long delta is
|
|
2225
|
+
added back and the short axis steps. The subtract and the add-back are
|
|
2226
|
+
8-bit, and the borrow is the carry flag, so no 9-bit error is needed.
|
|
2227
|
+
The plot is `ptr = ylo/yhi[y]` for the row, then
|
|
2228
|
+
`LDY xcol,X / LDA (ptr),Y / EOR xmask,X / STA (ptr),Y`. The window's
|
|
2229
|
+
bitmap x never passes 255, so the column offset fits Y. The x-major
|
|
2230
|
+
loop reloads `ptr` only when y steps.
|
|
2231
|
+
|
|
2232
|
+
**Why the line drawer is slow.** This is a correct, fully measured
|
|
2233
|
+
first recipe, not a fast plotter. The figures below are arithmetic from
|
|
2234
|
+
the instruction table over the listing's loops, and the pixel counts
|
|
2235
|
+
come from the model; only the totals were measured. An x-major pixel
|
|
2236
|
+
without a y step costs about 43 cycles: the plot itself
|
|
2237
|
+
(`LDY xcol,X / LDA (ptr),Y / EOR xmask,X / STA (ptr),Y`) is about 19,
|
|
2238
|
+
and the rest is the error term in zero page and the `JMP` back to the
|
|
2239
|
+
loop, every pixel. An x-major pixel with a y step costs about 72,
|
|
2240
|
+
because the row pointer is reloaded. A y-major pixel costs about 66 to
|
|
2241
|
+
77, because the row pointer (17 cycles) is reloaded on every pixel. The
|
|
2242
|
+
clip tests add about 19 cycles to each pixel of a line that needs them,
|
|
2243
|
+
32% of the pixels visited, and 9% of the pixels visited are outside the
|
|
2244
|
+
window and are walked for nothing. The loops account for about 4.4
|
|
2245
|
+
million of the 4.68 million measured line cycles; set-up is about 140
|
|
2246
|
+
cycles a call, about 6%. The two biggest costs are the row-pointer
|
|
2247
|
+
reload on every y-major pixel and the read-modify-write on every pixel
|
|
2248
|
+
with the error term and `cy` kept in zero page, not in registers.
|
|
2249
|
+
|
|
2250
|
+
**Erase by redraw.** Each object keeps the lines it drew (four bytes and
|
|
2251
|
+
the clip flag each) in a heap. The next update draws them again with EOR
|
|
2252
|
+
before drawing the new ones, and that erases them exactly, even where
|
|
2253
|
+
they cross other objects' lines. EOR has one visible cost: a pixel
|
|
2254
|
+
where an even number of lines meet is clear. The frozen picture has 9
|
|
2255
|
+
such pixels, all at or beside vertices: 8 at shared endpoints, 1 where
|
|
2256
|
+
two shallow edges leave a vertex along the same pixel. The model has the
|
|
2257
|
+
same 9.
|
|
2258
|
+
|
|
2259
|
+
**Screen.** VIC bank 1: `$DD00` bits 0-1 = `%10`, `$D018 = $18` puts the
|
|
2260
|
+
matrix at `$4400` and the bitmap at `$6000`. Code and tables stay below
|
|
2261
|
+
`$4000` (an `.assert` checks it), so the bitmap never overlaps them. The
|
|
2262
|
+
readout copies glyphs from the character ROM into the bitmap with `$01 =
|
|
2263
|
+
$33`. That is safe here because interrupts are off for the whole program
|
|
2264
|
+
(`pitfalls/banking.md`, `charset_under_io_invisible_to_cpu` and
|
|
2265
|
+
`irq_during_charen_window`).
|
|
2266
|
+
|
|
2267
|
+
**Timing.** CIA1 timers A and B, chained, are a 32-bit down-counter
|
|
2268
|
+
started and stopped around each object; an empty start/stop pair is
|
|
2269
|
+
timed once and subtracted. CIA2 is chained the same way but only runs
|
|
2270
|
+
between the `STA $DD0E` that resumes it and the one that pauses it
|
|
2271
|
+
around each line; an empty resume/pause pair is timed and subtracted
|
|
2272
|
+
per call. Pass 2 keeps only a `BIT harness` and a taken `BPL` per line
|
|
2273
|
+
call and per stored line (7 cycles each by the instruction table, about
|
|
2274
|
+
400 cycles in an update of 20 lines), so its update figures are the
|
|
2275
|
+
technique's own work.
|
|
2276
|
+
|
|
2277
|
+
**Galaxy.** One twist sets `s0 = s1`, `s1 = s2`, `s2 = s0 + s1 + s2`
|
|
2278
|
+
(16-bit, carries dropped). A system's x is `s1` high byte, its y is `s0`
|
|
2279
|
+
high byte shifted right once. Its name takes bits 0-4 of `s2` high byte
|
|
2280
|
+
before each of four twists; the pair is used for the first three twists,
|
|
2281
|
+
and for the fourth only when bit 6 of `s0` low byte is set. Pair 0 adds
|
|
2282
|
+
nothing, and a `.` in the pair table is a silent second letter. After
|
|
2283
|
+
the four twists the seeds are the next system's. The rule is Elite's, as
|
|
2284
|
+
Moxon documents it; the code is this recipe's. The 32 letter pairs are
|
|
2285
|
+
this recipe's own, so the names are not Elite's; the seeds and
|
|
2286
|
+
coordinates are. The table keeps Elite's shape, index 0 unused (`..`)
|
|
2287
|
+
and a silent second letter at index 15 (`O.`), so every name has the
|
|
2288
|
+
length Elite's has and the cycle counts are unchanged. An earlier
|
|
2289
|
+
version used Elite's own token string (QQ16), which is game data this
|
|
2290
|
+
repository cannot redistribute; it printed TIBEDIED, QUBE, ... LAVE.
|
|
2291
|
+
Moxon's worked example gives Lave's seeds as `s0 = $AD38`,
|
|
2292
|
+
`s1 = $149C`, `s2 = $151D` and coordinates x = 20 and y = 86. The
|
|
2293
|
+
program's eighth system (NEYA here) has those seeds (model) and
|
|
2294
|
+
coordinates (screen).
|
|
2295
|
+
|
|
2296
|
+
## What this recipe does not show
|
|
2297
|
+
|
|
2298
|
+
No double buffer: the objects are erased and redrawn in the displayed
|
|
2299
|
+
bitmap, so a line is missing from the screen between its erase and its
|
|
2300
|
+
redraw. The technique page describes the two-bank alternative. The
|
|
2301
|
+
recipe does not clip by intersection: a line that crosses the edge walks
|
|
2302
|
+
its outside pixels too. That costs time on long lines, and it would not
|
|
2303
|
+
work for coordinates beyond a byte. There is no near-plane test: camera
|
|
2304
|
+
z is kept at 129 or more by placement, and a game must reject or clip
|
|
2305
|
+
anything nearer. Objects do not hide each other. The plotter recomputes
|
|
2306
|
+
the row pointer on every y step; an incremental plotter that steps the
|
|
2307
|
+
byte address and the bit mask is faster, and was not measured here. Only
|
|
2308
|
+
the first galaxy is generated; the other seven come from rotating each
|
|
2309
|
+
seed byte left by one bit (Moxon, not run here).
|
|
2310
|
+
|
|
2311
|
+
## Sources
|
|
2312
|
+
|
|
2313
|
+
- Mark Moxon, "Twisting the system seeds":
|
|
2314
|
+
https://elite.bbcelite.com/deep_dives/twisting_the_system_seeds.html
|
|
2315
|
+
(the twist, four twists a system, the Tibedied seeds, 8 galaxies of 256).
|
|
2316
|
+
- Mark Moxon, "Generating system names":
|
|
2317
|
+
https://elite.bbcelite.com/deep_dives/generating_system_names.html
|
|
2318
|
+
(bits 0-4 of `s2_hi`, bit 6 of `s0_lo`, the Lave example).
|
|
2319
|
+
- Mark Moxon, "Generating system data":
|
|
2320
|
+
https://elite.bbcelite.com/deep_dives/generating_system_data.html
|
|
2321
|
+
(x = `s1_hi`, y = `s0_hi` shifted right once).
|
|
2322
|
+
- Mark Moxon, C64 Elite variable QQ16:
|
|
2323
|
+
https://elite.bbcelite.com/c64/main/variable/qq16.html (Elite's 32
|
|
2324
|
+
two-letter tokens, 128-159; not reproduced here).
|