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,807 @@
|
|
|
1
|
+
---
|
|
2
|
+
recipe: actor-activation-window
|
|
3
|
+
toolchain: oscar64
|
|
4
|
+
output_format: PRG
|
|
5
|
+
region: both
|
|
6
|
+
techniques: [actor_activation_window, object_pool]
|
|
7
|
+
file_formats: [PRG]
|
|
8
|
+
uses_registers: [DC04, DC05, DC0E, D000, D001, D010, D011, D015, D020, D021, D027]
|
|
9
|
+
uses_kernal: []
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<!-- doc-type: recipe -->
|
|
13
|
+
|
|
14
|
+
# Oscar64 actor activation window: level-placed actors that wake near the view and keep their state
|
|
15
|
+
|
|
16
|
+
## Synopsis
|
|
17
|
+
|
|
18
|
+
Thirty-two actors are placed in a level 256 columns (2,048 pixels) wide.
|
|
19
|
+
Each has an entry in a level table: column, row, hit points and a flag
|
|
20
|
+
byte (facing, live, dead). A camera scrolls to the far end at 16 pixels a
|
|
21
|
+
tick and back at 8. Every tick the program examines eight table entries,
|
|
22
|
+
round robin, and wakes any that lie inside the view plus a margin of 8
|
|
23
|
+
columns into one of eight live slots. A live actor that leaves the view
|
|
24
|
+
plus margin plus 2 columns is written back to its entry and its slot is
|
|
25
|
+
freed. At camera 560 the script kills actors 9 and 11 and takes actor 10
|
|
26
|
+
down to 1 hit point. The program checks that the dead actors never wake
|
|
27
|
+
again, that actor 10 wakes on the way back where it was left and with 1
|
|
28
|
+
hit point, and that no living actor was ever inside the view while
|
|
29
|
+
dormant. It compares a checksum of the final table with a Python model,
|
|
30
|
+
prints PASS or FAIL, the peak live count and the cycle cost of each part
|
|
31
|
+
(CIA1 timer A), and draws the live actors at camera 0 as sprites. It
|
|
32
|
+
implements `actor_activation_window` (`techniques/logic.md`); the live
|
|
33
|
+
slots are an `object_pool`.
|
|
34
|
+
|
|
35
|
+
## Source
|
|
36
|
+
|
|
37
|
+
```c
|
|
38
|
+
// actor-activation-window.c
|
|
39
|
+
// Actors placed in the level data wake up when they come within a window
|
|
40
|
+
// around the view and go back to the level table when they leave it, so
|
|
41
|
+
// their position, hit points and direction survive. Killed actors are
|
|
42
|
+
// marked dead in the table and never wake again. A camera scrolls out to
|
|
43
|
+
// the far end of a 256-column level at 16 pixels a tick and back at 8;
|
|
44
|
+
// the level table is scanned 8 entries a tick, round robin. The program
|
|
45
|
+
// checks the result against a Python model, prints PASS or FAIL, the peak
|
|
46
|
+
// live count and the cycle cost of the scan, and draws the actors live at
|
|
47
|
+
// the end as sprites relative to the camera.
|
|
48
|
+
#include <c64/vic.h>
|
|
49
|
+
#include <c64/cia.h>
|
|
50
|
+
|
|
51
|
+
#define SCREEN ((char *)0x0400)
|
|
52
|
+
#define COLOUR ((char *)0xd800)
|
|
53
|
+
#define SPRDATA ((char *)0x0340) // sprite block 13
|
|
54
|
+
|
|
55
|
+
#define NLVL 32 // placed actors; a power of two for the wrap
|
|
56
|
+
#define NSLOT 8 // live slots, one hardware sprite each
|
|
57
|
+
#define SCAN_K 8 // level entries examined per tick
|
|
58
|
+
#define VIEW 40 // view width in columns
|
|
59
|
+
#define HYST 2 // extra columns before a live actor is dropped
|
|
60
|
+
#define NO_SLOT 0xff
|
|
61
|
+
|
|
62
|
+
#define LF_DIRL 0x01 // persistent: facing left
|
|
63
|
+
#define LF_LIVE 0x40 // in a slot now
|
|
64
|
+
#define LF_DEAD 0x80 // killed: never wakes again
|
|
65
|
+
|
|
66
|
+
#define EXPECT_CHK 0x1D54 // Python fold over the final level table
|
|
67
|
+
|
|
68
|
+
// ---- the level table: persistent, one byte per field per actor ----------
|
|
69
|
+
char lvl_x[NLVL]; // column (8-pixel block) in the level
|
|
70
|
+
char lvl_row[NLVL]; // character row
|
|
71
|
+
char lvl_hp[NLVL];
|
|
72
|
+
char lvl_flags[NLVL];
|
|
73
|
+
char lvl_home[NLVL]; // patrol centre, level data, never written
|
|
74
|
+
|
|
75
|
+
// ---- the live slots ------------------------------------------------------
|
|
76
|
+
char slot_lvl[NSLOT]; // level index, or NO_SLOT
|
|
77
|
+
unsigned slot_px[NSLOT]; // world x in pixels
|
|
78
|
+
char slot_hp[NSLOT];
|
|
79
|
+
char slot_dir[NSLOT]; // 1 = moving left
|
|
80
|
+
|
|
81
|
+
// ---- window state, set once per tick -------------------------------------
|
|
82
|
+
char win_lo, win_top; // wake window: win_lo <= column <= win_top
|
|
83
|
+
char drop_lo, drop_top; // drop window: keep while drop_lo <= column <= drop_top
|
|
84
|
+
char scan_pos;
|
|
85
|
+
char margin;
|
|
86
|
+
unsigned cam_px;
|
|
87
|
+
|
|
88
|
+
// ---- counters the scenario reads back ------------------------------------
|
|
89
|
+
char live_n, peak_n, refused;
|
|
90
|
+
unsigned wakes, popin;
|
|
91
|
+
char wake_n[NLVL];
|
|
92
|
+
bool hit_done;
|
|
93
|
+
char out_col = 0xff, out_hp; // actor 10 when it went back to the table
|
|
94
|
+
unsigned back_px = 0xffff; // actor 10 when it woke again
|
|
95
|
+
char back_hp;
|
|
96
|
+
|
|
97
|
+
__noinline void activate(char i)
|
|
98
|
+
{
|
|
99
|
+
char s = 0;
|
|
100
|
+
while (slot_lvl[s] != NO_SLOT)
|
|
101
|
+
{
|
|
102
|
+
if (++s == NSLOT)
|
|
103
|
+
{
|
|
104
|
+
refused++;
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
slot_lvl[s] = i;
|
|
109
|
+
slot_px[s] = (unsigned)lvl_x[i] << 3;
|
|
110
|
+
slot_hp[s] = lvl_hp[i];
|
|
111
|
+
slot_dir[s] = lvl_flags[i] & LF_DIRL;
|
|
112
|
+
lvl_flags[i] |= LF_LIVE;
|
|
113
|
+
if (++live_n > peak_n)
|
|
114
|
+
peak_n = live_n;
|
|
115
|
+
wakes++;
|
|
116
|
+
wake_n[i]++;
|
|
117
|
+
if (i == 10 && out_col != 0xff && back_px == 0xffff)
|
|
118
|
+
{
|
|
119
|
+
back_px = slot_px[s];
|
|
120
|
+
back_hp = slot_hp[s];
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Write the live state back to the level table and free the slot.
|
|
125
|
+
__noinline void deactivate(char s)
|
|
126
|
+
{
|
|
127
|
+
char i = slot_lvl[s];
|
|
128
|
+
lvl_x[i] = (char)(slot_px[s] >> 3);
|
|
129
|
+
lvl_hp[i] = slot_hp[s];
|
|
130
|
+
lvl_flags[i] = (lvl_flags[i] & ~(LF_LIVE | LF_DIRL)) | slot_dir[s];
|
|
131
|
+
if (i == 10 && hit_done && out_col == 0xff)
|
|
132
|
+
{
|
|
133
|
+
out_col = lvl_x[i];
|
|
134
|
+
out_hp = lvl_hp[i];
|
|
135
|
+
}
|
|
136
|
+
slot_lvl[s] = NO_SLOT;
|
|
137
|
+
live_n--;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Kill: mark the entry dead so no scan wakes it, and free the slot.
|
|
141
|
+
static void kill(char s)
|
|
142
|
+
{
|
|
143
|
+
char i = slot_lvl[s];
|
|
144
|
+
lvl_flags[i] = (lvl_flags[i] & ~LF_LIVE) | LF_DEAD;
|
|
145
|
+
lvl_hp[i] = 0;
|
|
146
|
+
slot_lvl[s] = NO_SLOT;
|
|
147
|
+
live_n--;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Both windows as inclusive column bounds clamped to 0..255, so every
|
|
151
|
+
// compare in the scan and the drop pass is one byte.
|
|
152
|
+
__noinline void set_window(void)
|
|
153
|
+
{
|
|
154
|
+
int cc = cam_px >> 3;
|
|
155
|
+
int lo = cc - margin;
|
|
156
|
+
int hi = cc + VIEW + margin; // first column past the wake window
|
|
157
|
+
win_lo = lo < 0 ? 0 : lo;
|
|
158
|
+
win_top = hi > 256 ? 255 : hi - 1;
|
|
159
|
+
drop_lo = lo - HYST < 0 ? 0 : lo - HYST;
|
|
160
|
+
drop_top = hi + HYST > 256 ? 255 : hi + HYST - 1;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Examine SCAN_K entries from where the last tick stopped.
|
|
164
|
+
__noinline void scan_step(void)
|
|
165
|
+
{
|
|
166
|
+
char i = scan_pos;
|
|
167
|
+
for (char k = 0; k < SCAN_K; k++)
|
|
168
|
+
{
|
|
169
|
+
if (!(lvl_flags[i] & (LF_LIVE | LF_DEAD)))
|
|
170
|
+
{
|
|
171
|
+
char c = lvl_x[i];
|
|
172
|
+
if (c >= win_lo && c <= win_top)
|
|
173
|
+
activate(i);
|
|
174
|
+
}
|
|
175
|
+
i = (i + 1) & (NLVL - 1);
|
|
176
|
+
}
|
|
177
|
+
scan_pos = i;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// The same test over the whole table, for comparison.
|
|
181
|
+
__noinline void scan_all(void)
|
|
182
|
+
{
|
|
183
|
+
for (char i = 0; i < NLVL; i++)
|
|
184
|
+
{
|
|
185
|
+
if (!(lvl_flags[i] & (LF_LIVE | LF_DEAD)))
|
|
186
|
+
{
|
|
187
|
+
char c = lvl_x[i];
|
|
188
|
+
if (c >= win_lo && c <= win_top)
|
|
189
|
+
activate(i);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// The game's own actor logic, a stand-in: patrol three columns each
|
|
195
|
+
// side of home, one pixel a tick.
|
|
196
|
+
__noinline void move_live(void)
|
|
197
|
+
{
|
|
198
|
+
for (char s = 0; s < NSLOT; s++)
|
|
199
|
+
{
|
|
200
|
+
char i = slot_lvl[s];
|
|
201
|
+
if (i == NO_SLOT)
|
|
202
|
+
continue;
|
|
203
|
+
unsigned p = slot_px[s];
|
|
204
|
+
if (slot_dir[s])
|
|
205
|
+
p--;
|
|
206
|
+
else
|
|
207
|
+
p++;
|
|
208
|
+
slot_px[s] = p;
|
|
209
|
+
char c = p >> 3;
|
|
210
|
+
if (c >= lvl_home[i] + 3)
|
|
211
|
+
slot_dir[s] = 1;
|
|
212
|
+
else if (c + 3 <= lvl_home[i])
|
|
213
|
+
slot_dir[s] = 0;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Drop every live actor outside the drop window back into the table.
|
|
218
|
+
__noinline void drop_pass(void)
|
|
219
|
+
{
|
|
220
|
+
for (char s = 0; s < NSLOT; s++)
|
|
221
|
+
{
|
|
222
|
+
if (slot_lvl[s] == NO_SLOT)
|
|
223
|
+
continue;
|
|
224
|
+
char c = slot_px[s] >> 3;
|
|
225
|
+
if (c < drop_lo || c > drop_top)
|
|
226
|
+
deactivate(s);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// The technique's work per tick: window, scan slice, drop pass.
|
|
231
|
+
__noinline void window_tick(void)
|
|
232
|
+
{
|
|
233
|
+
set_window();
|
|
234
|
+
scan_step();
|
|
235
|
+
drop_pass();
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
static void tick_logic(void)
|
|
239
|
+
{
|
|
240
|
+
set_window();
|
|
241
|
+
scan_step();
|
|
242
|
+
move_live();
|
|
243
|
+
drop_pass();
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Harness only: a dormant, living entry inside the view is a pop-in.
|
|
247
|
+
static void check_popin(void)
|
|
248
|
+
{
|
|
249
|
+
char cc = cam_px >> 3;
|
|
250
|
+
for (char i = 0; i < NLVL; i++)
|
|
251
|
+
{
|
|
252
|
+
if (!(lvl_flags[i] & (LF_LIVE | LF_DEAD)))
|
|
253
|
+
{
|
|
254
|
+
char c = lvl_x[i];
|
|
255
|
+
if (c >= cc && c < cc + VIEW)
|
|
256
|
+
popin++;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
static char slot_of(char i)
|
|
262
|
+
{
|
|
263
|
+
for (char s = 0; s < NSLOT; s++)
|
|
264
|
+
if (slot_lvl[s] == i)
|
|
265
|
+
return s;
|
|
266
|
+
return NO_SLOT;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
static void level_reset(void)
|
|
270
|
+
{
|
|
271
|
+
for (char i = 0; i < NLVL; i++)
|
|
272
|
+
{
|
|
273
|
+
lvl_x[i] = lvl_home[i] = 4 + (i << 3);
|
|
274
|
+
lvl_row[i] = 19 + (i & 3);
|
|
275
|
+
lvl_hp[i] = 3;
|
|
276
|
+
lvl_flags[i] = i & 1;
|
|
277
|
+
wake_n[i] = 0;
|
|
278
|
+
}
|
|
279
|
+
for (char s = 0; s < NSLOT; s++)
|
|
280
|
+
slot_lvl[s] = NO_SLOT;
|
|
281
|
+
scan_pos = live_n = peak_n = refused = 0;
|
|
282
|
+
wakes = popin = 0;
|
|
283
|
+
hit_done = false;
|
|
284
|
+
out_col = 0xff;
|
|
285
|
+
back_px = 0xffff;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Out to the far end at 16 px a tick, a scripted fight at camera 560,
|
|
289
|
+
// then back to 0 at 8 px a tick.
|
|
290
|
+
static bool kill_ok;
|
|
291
|
+
static char w9, w11;
|
|
292
|
+
static void scenario(char m)
|
|
293
|
+
{
|
|
294
|
+
level_reset();
|
|
295
|
+
margin = m;
|
|
296
|
+
kill_ok = true;
|
|
297
|
+
for (cam_px = 0; cam_px <= 1728; cam_px += 16)
|
|
298
|
+
{
|
|
299
|
+
tick_logic();
|
|
300
|
+
check_popin();
|
|
301
|
+
if (cam_px == 560)
|
|
302
|
+
{
|
|
303
|
+
char s = slot_of(9);
|
|
304
|
+
if (s == NO_SLOT) kill_ok = false; else kill(s);
|
|
305
|
+
s = slot_of(11);
|
|
306
|
+
if (s == NO_SLOT) kill_ok = false; else kill(s);
|
|
307
|
+
s = slot_of(10);
|
|
308
|
+
if (s == NO_SLOT) kill_ok = false; else slot_hp[s] = 1;
|
|
309
|
+
hit_done = true;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
w9 = wake_n[9];
|
|
313
|
+
w11 = wake_n[11];
|
|
314
|
+
cam_px = 1728;
|
|
315
|
+
for (;;)
|
|
316
|
+
{
|
|
317
|
+
tick_logic();
|
|
318
|
+
check_popin();
|
|
319
|
+
if (cam_px == 0)
|
|
320
|
+
break;
|
|
321
|
+
cam_px -= 8;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// ---- timing ---------------------------------------------------------------
|
|
326
|
+
|
|
327
|
+
__noinline void nothing(void)
|
|
328
|
+
{
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
__noinline void wake_and_drop(void)
|
|
332
|
+
{
|
|
333
|
+
activate(0);
|
|
334
|
+
deactivate(0);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// The worst tick: every slot free and the whole slice inside the wake
|
|
338
|
+
// window, so all 8 entries wake, then the drop pass runs over 8 live.
|
|
339
|
+
// Timed with the reset, less the reset alone.
|
|
340
|
+
__noinline void reset_slots(void)
|
|
341
|
+
{
|
|
342
|
+
for (char s = 0; s < NSLOT; s++)
|
|
343
|
+
{
|
|
344
|
+
slot_lvl[s] = NO_SLOT;
|
|
345
|
+
lvl_flags[s] = 0;
|
|
346
|
+
}
|
|
347
|
+
live_n = 0;
|
|
348
|
+
scan_pos = 0;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
__noinline void reset_only(void)
|
|
352
|
+
{
|
|
353
|
+
reset_slots();
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
__noinline void worst_tick(void)
|
|
357
|
+
{
|
|
358
|
+
reset_slots();
|
|
359
|
+
window_tick();
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// CIA1 timer A: force-load $FFFF, count phi2 while fn runs 20 times. The
|
|
363
|
+
// largest subject stays under 65,535 cycles in total, so the 16-bit timer
|
|
364
|
+
// does not wrap; a first build with 50 calls wrapped on the actor update.
|
|
365
|
+
static unsigned time_loop(void (*fn)(void))
|
|
366
|
+
{
|
|
367
|
+
cia1.cra = 0x00;
|
|
368
|
+
cia1.ta = 0xffff;
|
|
369
|
+
cia1.cra = 0x11;
|
|
370
|
+
char i = 20;
|
|
371
|
+
do
|
|
372
|
+
{
|
|
373
|
+
fn();
|
|
374
|
+
} while (--i);
|
|
375
|
+
cia1.cra = 0x00;
|
|
376
|
+
return 0xffff - cia1.ta;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// ---- screen ----------------------------------------------------------------
|
|
380
|
+
|
|
381
|
+
static void put_str(char row, char col, const char *s)
|
|
382
|
+
{
|
|
383
|
+
char *p = SCREEN + 40 * row + col;
|
|
384
|
+
while (*s)
|
|
385
|
+
{
|
|
386
|
+
char c = *s++;
|
|
387
|
+
*p++ = (c >= 'a' && c <= 'z') ? c - 'a' + 1 : c;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
static void put_dec(char row, char col, unsigned v, char width)
|
|
392
|
+
{
|
|
393
|
+
char *p = SCREEN + 40 * row + col + width;
|
|
394
|
+
do
|
|
395
|
+
{
|
|
396
|
+
*--p = '0' + v % 10;
|
|
397
|
+
v /= 10;
|
|
398
|
+
} while (--width);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
static const char hex_glyph[16] = {
|
|
402
|
+
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 1, 2, 3, 4, 5, 6 };
|
|
403
|
+
|
|
404
|
+
static void put_hex16(char row, char col, unsigned v)
|
|
405
|
+
{
|
|
406
|
+
char *p = SCREEN + 40 * row + col;
|
|
407
|
+
p[0] = hex_glyph[(v >> 12) & 15];
|
|
408
|
+
p[1] = hex_glyph[(v >> 8) & 15];
|
|
409
|
+
p[2] = hex_glyph[(v >> 4) & 15];
|
|
410
|
+
p[3] = hex_glyph[v & 15];
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// Net cycles per call to two decimals: (t - t0) / 20 calls.
|
|
414
|
+
static void put_per_call(char row, char col, unsigned t, unsigned t0)
|
|
415
|
+
{
|
|
416
|
+
unsigned long n = (unsigned long)(t - t0) * 5; // hundredths per call
|
|
417
|
+
put_dec(row, col, (unsigned)(n / 100), 4);
|
|
418
|
+
SCREEN[40 * row + col + 4] = '.';
|
|
419
|
+
put_dec(row, col + 5, (unsigned)(n % 100), 2);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
static unsigned fold(unsigned cs, unsigned v)
|
|
423
|
+
{
|
|
424
|
+
return (cs ^ v) * 5 + 1;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
int main(void)
|
|
428
|
+
{
|
|
429
|
+
for (unsigned i = 0; i < 1000; i++)
|
|
430
|
+
{
|
|
431
|
+
SCREEN[i] = 0x20;
|
|
432
|
+
COLOUR[i] = VCOL_WHITE;
|
|
433
|
+
}
|
|
434
|
+
vic.color_back = VCOL_BLACK;
|
|
435
|
+
vic.color_border = VCOL_BLACK;
|
|
436
|
+
|
|
437
|
+
// Demonstration first: a margin of 1 column is too small at 16 px a tick.
|
|
438
|
+
scenario(1);
|
|
439
|
+
unsigned popin1 = popin;
|
|
440
|
+
|
|
441
|
+
// The real run: margin 8 columns.
|
|
442
|
+
scenario(8);
|
|
443
|
+
|
|
444
|
+
unsigned chk = 0;
|
|
445
|
+
for (char i = 0; i < NLVL; i++)
|
|
446
|
+
{
|
|
447
|
+
chk = fold(chk, lvl_x[i]);
|
|
448
|
+
chk = fold(chk, lvl_hp[i]);
|
|
449
|
+
chk = fold(chk, lvl_flags[i]);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
put_str(0, 0, "actor window 32 placed 8 slots");
|
|
453
|
+
put_str(1, 0, "margin 8 scan 8/tick cam 16 out 8 back");
|
|
454
|
+
put_str(2, 0, "kill 9 11 hit 10 at cam 560");
|
|
455
|
+
put_str(3, 0, "wakes 9 before after");
|
|
456
|
+
put_dec(3, 17, w9, 1);
|
|
457
|
+
put_dec(3, 26, wake_n[9], 1);
|
|
458
|
+
put_str(4, 0, "wakes 11 before after");
|
|
459
|
+
put_dec(4, 17, w11, 1);
|
|
460
|
+
put_dec(4, 26, wake_n[11], 1);
|
|
461
|
+
put_str(5, 0, "10 out col hp in px hp");
|
|
462
|
+
put_dec(5, 11, out_col, 3);
|
|
463
|
+
put_dec(5, 18, out_hp, 1);
|
|
464
|
+
put_dec(5, 27, back_px, 4);
|
|
465
|
+
put_dec(5, 35, back_hp, 1);
|
|
466
|
+
put_str(6, 0, "popin refused peak wakes");
|
|
467
|
+
put_dec(6, 6, popin, 2);
|
|
468
|
+
put_dec(6, 17, refused, 2);
|
|
469
|
+
put_dec(6, 25, peak_n, 1);
|
|
470
|
+
put_dec(6, 33, wakes, 3);
|
|
471
|
+
put_str(7, 0, "chk exp margin 1 popin");
|
|
472
|
+
put_hex16(7, 4, chk);
|
|
473
|
+
put_hex16(7, 13, EXPECT_CHK);
|
|
474
|
+
put_dec(7, 34, popin1, 3);
|
|
475
|
+
|
|
476
|
+
bool pass = kill_ok && w9 == 1 && w11 == 1 && wake_n[9] == 1 &&
|
|
477
|
+
wake_n[11] == 1 && wake_n[10] == 2 && wake_n[12] == 2 &&
|
|
478
|
+
out_col == 86 && out_hp == 1 && back_px == 688 && back_hp == 1 &&
|
|
479
|
+
popin == 0 && refused == 0 && peak_n == 8 && wakes == 56 &&
|
|
480
|
+
chk == EXPECT_CHK && popin1 != 0;
|
|
481
|
+
|
|
482
|
+
// Save the final table: the timing below overwrites it.
|
|
483
|
+
char sv_lvl[NSLOT];
|
|
484
|
+
unsigned sv_px[NSLOT];
|
|
485
|
+
for (char s = 0; s < NSLOT; s++)
|
|
486
|
+
{
|
|
487
|
+
sv_lvl[s] = slot_lvl[s];
|
|
488
|
+
sv_px[s] = slot_px[s];
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
// Cycle costs. Interrupts off and DEN off so nothing steals cycles.
|
|
492
|
+
__asm { sei }
|
|
493
|
+
vic.ctrl1 = 0x0b;
|
|
494
|
+
vic_waitFrame();
|
|
495
|
+
unsigned t0 = time_loop(nothing);
|
|
496
|
+
|
|
497
|
+
// Scans with every entry dormant and an empty wake window.
|
|
498
|
+
for (char i = 0; i < NLVL; i++)
|
|
499
|
+
lvl_flags[i] = 0;
|
|
500
|
+
win_lo = 1;
|
|
501
|
+
win_top = 0;
|
|
502
|
+
unsigned t_scan8 = time_loop(scan_step);
|
|
503
|
+
unsigned t_scan32 = time_loop(scan_all);
|
|
504
|
+
|
|
505
|
+
// Eight live actors (entries 0 to 7, columns 4 to 60), camera 0 and a
|
|
506
|
+
// margin of 22: the drop window, columns 0 to 63, holds every patrol,
|
|
507
|
+
// and the wake window, 0 to 61, holds no dormant entry.
|
|
508
|
+
for (char s = 0; s < NSLOT; s++)
|
|
509
|
+
{
|
|
510
|
+
slot_lvl[s] = s;
|
|
511
|
+
slot_px[s] = (unsigned)lvl_home[s] << 3;
|
|
512
|
+
slot_dir[s] = 0;
|
|
513
|
+
lvl_flags[s] = LF_LIVE;
|
|
514
|
+
}
|
|
515
|
+
cam_px = 0;
|
|
516
|
+
margin = 22;
|
|
517
|
+
set_window();
|
|
518
|
+
unsigned t_drop = time_loop(drop_pass);
|
|
519
|
+
unsigned t_tick = time_loop(window_tick); // 20 calls: 5 laps of the table
|
|
520
|
+
unsigned t_move = time_loop(move_live);
|
|
521
|
+
|
|
522
|
+
// One wake into the free slot 0 and one drop back.
|
|
523
|
+
slot_lvl[0] = NO_SLOT;
|
|
524
|
+
live_n = 7;
|
|
525
|
+
unsigned t_wd = time_loop(wake_and_drop);
|
|
526
|
+
|
|
527
|
+
// Entries 0 to 7 sit in columns 4 to 60 after the run, inside the
|
|
528
|
+
// wake window 0 to 61, so all 8 wake; worst_ok checks that they did.
|
|
529
|
+
unsigned t_ro = time_loop(reset_only);
|
|
530
|
+
unsigned t_worst = time_loop(worst_tick);
|
|
531
|
+
bool worst_ok = live_n == 8 && refused == 0;
|
|
532
|
+
vic.ctrl1 = 0x1b;
|
|
533
|
+
|
|
534
|
+
put_str(9, 0, "cycles x20 total per call");
|
|
535
|
+
put_str(10, 0, "empty call");
|
|
536
|
+
put_dec(10, 22, t0, 5);
|
|
537
|
+
put_str(11, 0, "scan 8, none wakes");
|
|
538
|
+
put_dec(11, 22, t_scan8, 5);
|
|
539
|
+
put_per_call(11, 30, t_scan8, t0);
|
|
540
|
+
put_str(12, 0, "scan all 32");
|
|
541
|
+
put_dec(12, 22, t_scan32, 5);
|
|
542
|
+
put_per_call(12, 30, t_scan32, t0);
|
|
543
|
+
put_str(13, 0, "drop pass, 8 live");
|
|
544
|
+
put_dec(13, 22, t_drop, 5);
|
|
545
|
+
put_per_call(13, 30, t_drop, t0);
|
|
546
|
+
put_str(14, 0, "window+scan 8+drop");
|
|
547
|
+
put_dec(14, 22, t_tick, 5);
|
|
548
|
+
put_per_call(14, 30, t_tick, t0);
|
|
549
|
+
put_str(15, 0, "patrol 8 (payload)");
|
|
550
|
+
put_dec(15, 22, t_move, 5);
|
|
551
|
+
put_per_call(15, 30, t_move, t0);
|
|
552
|
+
put_str(16, 0, "wake + drop back");
|
|
553
|
+
put_dec(16, 22, t_wd, 5);
|
|
554
|
+
put_per_call(16, 30, t_wd, t0);
|
|
555
|
+
|
|
556
|
+
put_str(17, 0, "scan 8 all wake+drop");
|
|
557
|
+
put_dec(17, 22, t_worst, 5);
|
|
558
|
+
put_per_call(17, 30, t_worst, t_ro);
|
|
559
|
+
|
|
560
|
+
pass = pass && worst_ok;
|
|
561
|
+
put_str(18, 0, pass ? "pass" : "fail");
|
|
562
|
+
vic.color_border = pass ? VCOL_GREEN : VCOL_RED;
|
|
563
|
+
|
|
564
|
+
// Draw the actors live at the end, camera 0, as sprites.
|
|
565
|
+
for (char k = 0; k < 63; k++)
|
|
566
|
+
SPRDATA[k] = 0xff;
|
|
567
|
+
char en = 0, msb = 0;
|
|
568
|
+
for (char s = 0; s < NSLOT; s++)
|
|
569
|
+
{
|
|
570
|
+
((char *)0x07f8)[s] = 13;
|
|
571
|
+
vic.spr_color[s] = VCOL_YELLOW;
|
|
572
|
+
if (sv_lvl[s] == NO_SLOT || sv_px[s] >= VIEW * 8)
|
|
573
|
+
continue;
|
|
574
|
+
unsigned sx = sv_px[s] + 24;
|
|
575
|
+
vic.spr_pos[s].x = (char)sx;
|
|
576
|
+
vic.spr_pos[s].y = 50 + (lvl_row[sv_lvl[s]] << 3);
|
|
577
|
+
if (sx & 0x100)
|
|
578
|
+
msb |= 1 << s;
|
|
579
|
+
en |= 1 << s;
|
|
580
|
+
}
|
|
581
|
+
vic.spr_msbx = msb;
|
|
582
|
+
vic.spr_enable = en;
|
|
583
|
+
for (;;)
|
|
584
|
+
;
|
|
585
|
+
return 0;
|
|
586
|
+
}
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
## Build
|
|
590
|
+
|
|
591
|
+
```
|
|
592
|
+
oscar64 -tm=c64 -O2 -o=actor-activation-window.prg actor-activation-window.c
|
|
593
|
+
GSETTINGS_SCHEMA_DIR=/opt/homebrew/share/glib-2.0/schemas timeout 180 x64sc -default -minimized -warp +sound +autostart-delay-random -autostartprgmode 1 -limitcycles 8000000 -exitscreenshot actor-activation-window.png -autostart actor-activation-window.prg
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
Add `-model ntsc` for the NTSC picture. 8,000,000 cycles is the pinned
|
|
597
|
+
run. The screen was complete at 6,000,000 on both models (measured).
|
|
598
|
+
A build without the worst-tick row was blank at 5,000,000 (measured,
|
|
599
|
+
PAL).
|
|
600
|
+
|
|
601
|
+
## Expected output
|
|
602
|
+
|
|
603
|
+
Black screen, green border, five yellow sprites in the lower part of the
|
|
604
|
+
screen. Decoded from `screenshots/actor-activation-window.png` (PAL) with
|
|
605
|
+
the character ROM; rows 8 and 19 to 24 hold no text:
|
|
606
|
+
|
|
607
|
+
```text
|
|
608
|
+
ACTOR WINDOW 32 PLACED 8 SLOTS
|
|
609
|
+
MARGIN 8 SCAN 8/TICK CAM 16 OUT 8 BACK
|
|
610
|
+
KILL 9 11 HIT 10 AT CAM 560
|
|
611
|
+
WAKES 9 BEFORE 1 AFTER 1
|
|
612
|
+
WAKES 11 BEFORE 1 AFTER 1
|
|
613
|
+
10 OUT COL 086 HP 1 IN PX 0688 HP 1
|
|
614
|
+
POPIN 00 REFUSED 00 PEAK 8 WAKES 056
|
|
615
|
+
CHK 1D54 EXP 1D54 MARGIN 1 POPIN 037
|
|
616
|
+
|
|
617
|
+
CYCLES X20 TOTAL PER CALL
|
|
618
|
+
EMPTY CALL 00749
|
|
619
|
+
SCAN 8, NONE WAKES 09149 0420.00
|
|
620
|
+
SCAN ALL 32 23809 1153.00
|
|
621
|
+
DROP PASS, 8 LIVE 11329 0529.00
|
|
622
|
+
WINDOW+SCAN 8+DROP 22269 1076.00
|
|
623
|
+
PATROL 8 (PAYLOAD) 25249 1225.00
|
|
624
|
+
WAKE + DROP BACK 06029 0264.00
|
|
625
|
+
SCAN 8 ALL WAKE+DROP 60529 2809.00
|
|
626
|
+
PASS
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
`screenshots/actor-activation-window-ntsc.png` (`-model ntsc`) decodes to
|
|
630
|
+
the same text, and the cycle counts are identical on both models (the CIA
|
|
631
|
+
counts phi2 cycles with the screen blanked). Each model's pinned run was
|
|
632
|
+
made twice and gave byte-identical PNGs (measured in VICE x64sc 3.10).
|
|
633
|
+
|
|
634
|
+
The sprites, measured with PIL on both pictures. Screenshot x is world
|
|
635
|
+
pixel x plus 32, because the camera is at 0 and sprite X is world x plus
|
|
636
|
+
24; the top raster line is the character row's top line, one below the
|
|
637
|
+
sprite Y register:
|
|
638
|
+
|
|
639
|
+
| Level entry | World x (px) | Screenshot x | Raster lines | Text row, 19 + (entry AND 3) |
|
|
640
|
+
|---|---|---|---|---|
|
|
641
|
+
| 0 | 54 | 86 to 109 | 203 to 223 | 19 |
|
|
642
|
+
| 1 | 96 | 128 to 151 | 211 to 231 | 20 |
|
|
643
|
+
| 2 | 162 | 194 to 217 | 219 to 239 | 21 |
|
|
644
|
+
| 3 | 242 | 274 to 297 | 227 to 247 | 22 |
|
|
645
|
+
| 4 | 284 | 316 to 339 | 203 to 223 | 19 |
|
|
646
|
+
|
|
647
|
+
Entry 4 is at sprite X 308, past 255, so it needs its bit in `$D010`
|
|
648
|
+
(`sprite_x_high_bit_wrong_register`). Entry 5 is live at world x 358, in
|
|
649
|
+
the margin and outside the view, so it has no sprite. The world positions
|
|
650
|
+
are the Python model's; none of the five is at its placed position
|
|
651
|
+
(32 + 64 × entry) because each has patrolled since it woke.
|
|
652
|
+
|
|
653
|
+
What each row states:
|
|
654
|
+
|
|
655
|
+
- Rows 3 and 4: actors 9 and 11 each woke once on the way out; after the
|
|
656
|
+
kill the count is still 1, so the dead flag kept them asleep while the
|
|
657
|
+
camera passed them again.
|
|
658
|
+
- Row 5: actor 10 went back to the table at column 86 with 1 hit point
|
|
659
|
+
(it was placed at column 84 with 3), and woke on the way back at pixel
|
|
660
|
+
688 = 86 × 8 with 1 hit point.
|
|
661
|
+
- Row 6: no dormant, living entry was ever inside the view; no wake was
|
|
662
|
+
refused for want of a slot; at most 8 slots were live at once; 56 wakes
|
|
663
|
+
in all.
|
|
664
|
+
- Row 7: the fold over the 96 bytes of `lvl_x`, `lvl_hp` and `lvl_flags`
|
|
665
|
+
is $1D54 on the 6510 and in Python. The same scenario run first with a
|
|
666
|
+
margin of 1 column had 37 pop-ins (tick-entry pairs where a living
|
|
667
|
+
actor was in view but dormant).
|
|
668
|
+
- Rows 10 to 17: CIA1 timer A over 20 calls, total and net per call.
|
|
669
|
+
Row 17 is the worst tick: all slots free, and all 8 entries of the
|
|
670
|
+
slice inside the wake window, so the tick wakes 8 and then runs the
|
|
671
|
+
drop pass over 8 live. It is timed with a slot reset in each call; the
|
|
672
|
+
net figure subtracts a call that only resets. The program checks that
|
|
673
|
+
all 8 woke; PASS includes that check.
|
|
674
|
+
|
|
675
|
+
The Python model of the scenario. The C code clamps the window bounds to
|
|
676
|
+
0 to 255 and compares one byte; the model compares unclamped integers and
|
|
677
|
+
gives the same table:
|
|
678
|
+
|
|
679
|
+
```python
|
|
680
|
+
NLVL, NSLOT, K, VIEW, HYST = 32, 8, 8, 40, 2
|
|
681
|
+
LIVE, DEAD = 0x40, 0x80
|
|
682
|
+
home = [4 + 8 * i for i in range(NLVL)]
|
|
683
|
+
|
|
684
|
+
def run(margin):
|
|
685
|
+
lx, hp, fl = list(home), [3] * NLVL, [i & 1 for i in range(NLVL)]
|
|
686
|
+
sl, px, shp, sd = [None] * NSLOT, [0] * NSLOT, [0] * NSLOT, [0] * NSLOT
|
|
687
|
+
st = dict(scan=0, live=0, peak=0, wakes=0, popin=0, hit=False, out=None, back=None)
|
|
688
|
+
wn = [0] * NLVL
|
|
689
|
+
|
|
690
|
+
def wake(i):
|
|
691
|
+
if None not in sl:
|
|
692
|
+
return
|
|
693
|
+
s = sl.index(None)
|
|
694
|
+
sl[s], px[s], shp[s], sd[s] = i, lx[i] * 8, hp[i], fl[i] & 1
|
|
695
|
+
fl[i] |= LIVE
|
|
696
|
+
st['live'] += 1; st['peak'] = max(st['peak'], st['live'])
|
|
697
|
+
st['wakes'] += 1; wn[i] += 1
|
|
698
|
+
if i == 10 and st['out'] and not st['back']:
|
|
699
|
+
st['back'] = (px[s], shp[s])
|
|
700
|
+
|
|
701
|
+
def drop(s):
|
|
702
|
+
i = sl[s]
|
|
703
|
+
lx[i], hp[i] = px[s] >> 3, shp[s]
|
|
704
|
+
fl[i] = (fl[i] & ~(LIVE | 1)) | sd[s]
|
|
705
|
+
if i == 10 and st['hit'] and not st['out']:
|
|
706
|
+
st['out'] = (lx[i], hp[i])
|
|
707
|
+
sl[s] = None; st['live'] -= 1
|
|
708
|
+
|
|
709
|
+
def kill(i):
|
|
710
|
+
s = sl.index(i)
|
|
711
|
+
fl[i] = (fl[i] & ~LIVE) | DEAD; hp[i] = 0
|
|
712
|
+
sl[s] = None; st['live'] -= 1
|
|
713
|
+
|
|
714
|
+
def tick(cam):
|
|
715
|
+
cc = cam >> 3
|
|
716
|
+
lo, hi = cc - margin, cc + VIEW + margin
|
|
717
|
+
i = st['scan']
|
|
718
|
+
for _ in range(K):
|
|
719
|
+
if not fl[i] & (LIVE | DEAD) and lo <= lx[i] < hi:
|
|
720
|
+
wake(i)
|
|
721
|
+
i = (i + 1) % NLVL
|
|
722
|
+
st['scan'] = i
|
|
723
|
+
for s in range(NSLOT):
|
|
724
|
+
if sl[s] is None:
|
|
725
|
+
continue
|
|
726
|
+
px[s] += -1 if sd[s] else 1
|
|
727
|
+
c = px[s] >> 3
|
|
728
|
+
if c >= home[sl[s]] + 3: sd[s] = 1
|
|
729
|
+
elif c + 3 <= home[sl[s]]: sd[s] = 0
|
|
730
|
+
for s in range(NSLOT):
|
|
731
|
+
if sl[s] is not None and not lo - HYST <= px[s] >> 3 < hi + HYST:
|
|
732
|
+
drop(s)
|
|
733
|
+
st['popin'] += sum(1 for i in range(NLVL)
|
|
734
|
+
if not fl[i] & (LIVE | DEAD) and cc <= lx[i] < cc + VIEW)
|
|
735
|
+
|
|
736
|
+
for cam in range(0, 1729, 16):
|
|
737
|
+
tick(cam)
|
|
738
|
+
if cam == 560:
|
|
739
|
+
kill(9); kill(11)
|
|
740
|
+
shp[sl.index(10)] = 1
|
|
741
|
+
st['hit'] = True
|
|
742
|
+
for cam in range(1728, -1, -8):
|
|
743
|
+
tick(cam)
|
|
744
|
+
chk = 0
|
|
745
|
+
for i in range(NLVL):
|
|
746
|
+
for v in (lx[i], hp[i], fl[i]):
|
|
747
|
+
chk = ((chk ^ v) * 5 + 1) & 0xFFFF
|
|
748
|
+
return st, wn, hex(chk), [(sl[s], px[s]) for s in range(NSLOT) if sl[s] is not None]
|
|
749
|
+
|
|
750
|
+
st, wn, chk, live = run(8)
|
|
751
|
+
print(wn[9], wn[11], wn[10], wn[12], st['out'], st['back'])
|
|
752
|
+
print(st['popin'], st['peak'], st['wakes'], chk)
|
|
753
|
+
print(sorted(live))
|
|
754
|
+
print([run(m)[0]['popin'] for m in range(1, 9)])
|
|
755
|
+
```
|
|
756
|
+
|
|
757
|
+
It prints `1 1 2 2 (86, 1) (688, 1)`, `0 8 56 0x1d54`, the six live
|
|
758
|
+
slots with their pixel positions, and the pop-in count for margins 1 to
|
|
759
|
+
8: `[37, 25, 3, 3, 0, 0, 0, 0]`.
|
|
760
|
+
|
|
761
|
+
## Why this works
|
|
762
|
+
|
|
763
|
+
The level table is the only record of an actor while it is off screen. A
|
|
764
|
+
slot holds a copy while the actor is near the view, and the copy goes
|
|
765
|
+
back on the way out: column, hit points and facing. Sub-column position
|
|
766
|
+
is lost: the table stores `px >> 3`, and the actor wakes at `column × 8`.
|
|
767
|
+
Actor 10 was left somewhere between pixel 688 and 695 and woke at
|
|
768
|
+
688; a finer table entry costs a byte per actor. A dead entry is never deleted, only flagged, so
|
|
769
|
+
the scan skips it for the rest of the level with one `AND` of the flag
|
|
770
|
+
byte.
|
|
771
|
+
|
|
772
|
+
The margin is what hides the scan's latency. Eight entries a tick means
|
|
773
|
+
each entry is looked at every 4 ticks, and at 16 pixels a tick the camera
|
|
774
|
+
moves 8 columns in 4 ticks. An entry examined one column outside the
|
|
775
|
+
window can be 8 columns closer when it is next examined, so a margin of 8
|
|
776
|
+
columns is safe for any layout (arithmetic). It is not the least. The
|
|
777
|
+
scan runs before the pop-in check in the same tick, so an entry is
|
|
778
|
+
examined again on the tick it would first be in view; that leaves 3
|
|
779
|
+
ticks, 6 columns, to cover, and a margin of 6 is enough. A Python model
|
|
780
|
+
of the scan alone over adversarial layouts (every entry on one column,
|
|
781
|
+
every scan phase, and random layouts) gives worst pop-in counts of 15
|
|
782
|
+
at margin 5 and 0 at margins 6 to 9 (rung 3, a model; not run in VICE).
|
|
783
|
+
The measured run: 0 pop-ins with 8, 37 with 1. The recipe's Python model
|
|
784
|
+
shows this layout gets by with 5, because its actors are 8 columns
|
|
785
|
+
apart. The
|
|
786
|
+
drop window is 2 columns wider than the wake window, so an actor
|
|
787
|
+
patrolling on the edge is not dropped and woken on alternate ticks.
|
|
788
|
+
|
|
789
|
+
The costs are Oscar64 -O2 code and are larger than hand-written assembly
|
|
790
|
+
would be. The scan examines an entry in about 52 cycles when it slices
|
|
791
|
+
eight (420 per call) and about 36 when it walks all 32 in one loop (1,153
|
|
792
|
+
per call): the round-robin wrap costs an `AND` and a zero-page reload per
|
|
793
|
+
entry. The drop pass costs 529 cycles for 8 live actors, most of it the
|
|
794
|
+
16-bit shift from pixel to column. The window set-up, a scan slice and
|
|
795
|
+
the drop pass together cost 1,076 cycles a tick, an average over the 20
|
|
796
|
+
timed calls (five laps of the table) with entries 0 to 7 live, when
|
|
797
|
+
nothing wakes or drops. One wake and one drop add 264. The worst tick,
|
|
798
|
+
8 wakes and the drop pass over 8 live, costs 2,809 cycles, 14.3% of a
|
|
799
|
+
19,656-cycle PAL frame (arithmetic from the measured figure). A tick can
|
|
800
|
+
wake at most K entries, and wakes plus drops in one tick cannot exceed
|
|
801
|
+
the 8 slots, because a woken actor is inside the drop window. A variant
|
|
802
|
+
of this listing that drops all 8 in one tick, and wakes none, measured
|
|
803
|
+
1,850 cycles, so waking is the heavier case (VICE x64sc, PAL). The patrol row is
|
|
804
|
+
the demonstration's own actor logic and is not part of the technique.
|
|
805
|
+
Timing uses 20 calls per subject: a first build with 50 calls read 176.6
|
|
806
|
+
cycles for the update pass, a fraction from a loop that does the same
|
|
807
|
+
work every call, which is the 16-bit timer wrapping at 65,536.
|