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,651 @@
|
|
|
1
|
+
---
|
|
2
|
+
recipe: per-frame-hitbox
|
|
3
|
+
toolchain: oscar64
|
|
4
|
+
output_format: PRG
|
|
5
|
+
region: both
|
|
6
|
+
techniques: [per_frame_hitbox]
|
|
7
|
+
file_formats: [PRG]
|
|
8
|
+
uses_registers: [D000, D001, D010, D011, D015, D01C, D01E, D020, D021, D025, D026, D027, DC06, DC07, DC0F]
|
|
9
|
+
uses_kernal: []
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<!-- doc-type: recipe -->
|
|
13
|
+
|
|
14
|
+
# Oscar64 Per-Frame Hitboxes: boxes from the animation frame, pairs from group bits
|
|
15
|
+
|
|
16
|
+
## Synopsis
|
|
17
|
+
|
|
18
|
+
A player sprite takes three poses, stand, crouch and attack, and each
|
|
19
|
+
pose's animation frame carries its own collision box. The attack frame
|
|
20
|
+
carries two: a body in the player group and a blade in the player-bullet
|
|
21
|
+
group. Every frame the draw appends each actor's boxes to one list at the
|
|
22
|
+
position the sprite is drawn at, and the collision pass tests only the
|
|
23
|
+
pairs whose groups can hurt each other. Two enemies and four bullets from
|
|
24
|
+
both sides run a scripted scenario of three 64-frame stages, one per
|
|
25
|
+
pose. The same enemy bullet hits the standing player and passes over the
|
|
26
|
+
crouching one at the same position; enemy bullets fly through enemies
|
|
27
|
+
without an event; the blade hits an enemy the body does not touch; a
|
|
28
|
+
player bullet 256 pixels to the left of an enemy is a miss that a
|
|
29
|
+
low-byte X test reports as a hit. The screen prints expected and actual
|
|
30
|
+
events per stage, the `$D01E` value the hardware latched, and CIA1 timer B
|
|
31
|
+
cycles per pair and per frame. The last stage holds with every box drawn
|
|
32
|
+
as a yellow outline inside its sprite. `$02FF` = `01` and a green border
|
|
33
|
+
on a pass, `02` and red otherwise (`headless-verify.md`). This is the
|
|
34
|
+
`per_frame_hitbox` technique from `docs/techniques/sprite.md`.
|
|
35
|
+
|
|
36
|
+
## Source
|
|
37
|
+
|
|
38
|
+
```c
|
|
39
|
+
// per-frame-hitbox.c
|
|
40
|
+
//
|
|
41
|
+
// Collision boxes per animation frame, emitted at draw time, tested in
|
|
42
|
+
// pairs chosen by group bits. A player sprite takes three poses (stand,
|
|
43
|
+
// crouch, attack), each with its own box table entry; the attack pose
|
|
44
|
+
// emits two boxes, a body and a blade in the player-bullet group. Two
|
|
45
|
+
// enemies and four bullets from both sides move through a scripted
|
|
46
|
+
// scenario of three 64-frame stages, one per pose. Each stage's hit
|
|
47
|
+
// events are compared with the expected set. The last stage then holds
|
|
48
|
+
// with the boxes drawn as yellow outlines inside the sprites.
|
|
49
|
+
// Row 0: stage and frame. Row 1: the verdict. Rows 2-5: expected and
|
|
50
|
+
// actual events per stage and the $D01E value the hardware latched.
|
|
51
|
+
// Rows 7-12: pairs, CIA1 timer B cycles, the false hits of a low-byte X
|
|
52
|
+
// test, and the player's first box. $02FF = 01 and a green border when
|
|
53
|
+
// every stage matched and the low-byte test was caught; 02 and red
|
|
54
|
+
// otherwise.
|
|
55
|
+
//
|
|
56
|
+
#include <c64/vic.h>
|
|
57
|
+
#include <c64/cia.h>
|
|
58
|
+
#include <c64/sprites.h>
|
|
59
|
+
|
|
60
|
+
#define Screen ((char *)0x0400)
|
|
61
|
+
#define Color ((char *)0xd800)
|
|
62
|
+
#define SprData ((char *)0x3000) // blocks 192..197
|
|
63
|
+
#define SPR_BLK 192
|
|
64
|
+
#define RESULT (*(volatile char *)0x02ff)
|
|
65
|
+
|
|
66
|
+
// Groups, one bit each. box_mask (below) holds, for each box, the
|
|
67
|
+
// groups it is tested against; the relation is symmetric: player with
|
|
68
|
+
// enemy and enemy bullet, player bullet with enemy, and nothing else.
|
|
69
|
+
#define G_PLAYER 0x01
|
|
70
|
+
#define G_PSHOT 0x02
|
|
71
|
+
#define G_ENEMY 0x04
|
|
72
|
+
#define G_ESHOT 0x08
|
|
73
|
+
|
|
74
|
+
// --- animation frames and their boxes --------------------------------
|
|
75
|
+
// Offsets from the sprite's top-left, in pixels, even so they fit the
|
|
76
|
+
// 2-pixel columns of a multicolour sprite. A frame owns box_count boxes
|
|
77
|
+
// from box_first on.
|
|
78
|
+
#define F_STAND 0
|
|
79
|
+
#define F_CROUCH 1
|
|
80
|
+
#define F_ATTACK 2
|
|
81
|
+
#define F_ENEMY 3
|
|
82
|
+
#define F_ESHOT 4
|
|
83
|
+
#define F_PSHOT 5
|
|
84
|
+
#define FRAMES 6
|
|
85
|
+
|
|
86
|
+
struct Rect { char x, y, w, h; };
|
|
87
|
+
|
|
88
|
+
const struct Rect figure[FRAMES] = { // drawn pixels, sprite colour
|
|
89
|
+
{ 6, 0, 12, 21 }, { 6, 10, 12, 11 }, { 4, 0, 12, 21 },
|
|
90
|
+
{ 0, 0, 24, 21 }, { 6, 6, 12, 8 }, { 6, 6, 12, 8 }
|
|
91
|
+
};
|
|
92
|
+
const char box_first[FRAMES] = { 0, 1, 2, 4, 5, 6 };
|
|
93
|
+
const char box_count[FRAMES] = { 1, 1, 2, 1, 1, 1 };
|
|
94
|
+
|
|
95
|
+
const struct Rect box_rect[7] = {
|
|
96
|
+
{ 8, 2, 8, 19 }, // stand: body
|
|
97
|
+
{ 8, 12, 8, 9 }, // crouch: lower half
|
|
98
|
+
{ 6, 2, 8, 19 }, { 14, 6, 10, 4 }, // attack: body, blade
|
|
99
|
+
{ 4, 2, 16, 18 }, // enemy
|
|
100
|
+
{ 8, 8, 8, 4 }, // enemy bullet
|
|
101
|
+
{ 8, 8, 8, 4 } // player bullet
|
|
102
|
+
};
|
|
103
|
+
const char box_group[7] = {
|
|
104
|
+
G_PLAYER, G_PLAYER, G_PLAYER, G_PSHOT, G_ENEMY, G_ESHOT, G_PSHOT
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
// The groups each box is tested against.
|
|
108
|
+
const char box_mask[7] = {
|
|
109
|
+
G_ENEMY | G_ESHOT, G_ENEMY | G_ESHOT, G_ENEMY | G_ESHOT, G_ENEMY,
|
|
110
|
+
G_PLAYER | G_PSHOT, G_PLAYER, G_ENEMY
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
// --- actors ------------------------------------------------------------
|
|
114
|
+
// One hardware sprite each. X is the 9-bit sprite X, Y the sprite Y.
|
|
115
|
+
// Bullets take the low sprite numbers so they are drawn in front.
|
|
116
|
+
#define A_EB1 0
|
|
117
|
+
#define A_EB2 1
|
|
118
|
+
#define A_PB1 2
|
|
119
|
+
#define A_PB2 3
|
|
120
|
+
#define A_P 4
|
|
121
|
+
#define A_E1 5
|
|
122
|
+
#define A_E2 6
|
|
123
|
+
#define ACTORS 7
|
|
124
|
+
|
|
125
|
+
int ax[ACTORS];
|
|
126
|
+
char ay[ACTORS];
|
|
127
|
+
char aframe[ACTORS];
|
|
128
|
+
const char acol[ACTORS] = { 10, 10, 3, 3, 1, 2, 2 };
|
|
129
|
+
|
|
130
|
+
// Event bits: which actor's box hit which. Bits 1, 4 and 5 must never
|
|
131
|
+
// be set: body contact that is not an overlap, an enemy bullet in an
|
|
132
|
+
// enemy, and a player bullet whose X differs from the enemy's by 256.
|
|
133
|
+
#define EV_EB1_P 0x01
|
|
134
|
+
#define EV_E1_P 0x02
|
|
135
|
+
#define EV_BLADE_E1 0x04
|
|
136
|
+
#define EV_PB1_E2 0x08
|
|
137
|
+
#define EV_EB2_E2 0x10
|
|
138
|
+
#define EV_PB2_E2 0x20
|
|
139
|
+
|
|
140
|
+
#define PAIR(a, b) ((1 << (a)) | (1 << (b)))
|
|
141
|
+
|
|
142
|
+
char event_bit(char a, char b)
|
|
143
|
+
{
|
|
144
|
+
switch (PAIR(a, b)) {
|
|
145
|
+
case PAIR(A_P, A_EB1): return EV_EB1_P;
|
|
146
|
+
case PAIR(A_P, A_E1): return EV_E1_P; // body or blade, split below
|
|
147
|
+
case PAIR(A_E2, A_PB1): return EV_PB1_E2;
|
|
148
|
+
case PAIR(A_E2, A_EB2): return EV_EB2_E2;
|
|
149
|
+
case PAIR(A_E2, A_PB2): return EV_PB2_E2;
|
|
150
|
+
default: return 0;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// --- the box list, refilled every frame by the draw ---------------------
|
|
155
|
+
#define MAXB 8
|
|
156
|
+
char nbox;
|
|
157
|
+
char bll[MAXB], blh[MAXB]; // left X, 9 bits as low and high byte
|
|
158
|
+
char brl[MAXB], brh[MAXB]; // right X, exclusive
|
|
159
|
+
char bt[MAXB], bb[MAXB]; // Y, bottom edge exclusive
|
|
160
|
+
char bhl[MAXB], bhr[MAXB]; // X / 2, for the 8-bit variant
|
|
161
|
+
char bg[MAXB], bm[MAXB], bo[MAXB]; // group bit, pair mask, owner
|
|
162
|
+
|
|
163
|
+
// Draw one actor's boxes: append its current frame's boxes to the list
|
|
164
|
+
// at the position the sprite is drawn at.
|
|
165
|
+
void emit_boxes(char a)
|
|
166
|
+
{
|
|
167
|
+
unsigned x = ax[a];
|
|
168
|
+
char y = ay[a], f = aframe[a];
|
|
169
|
+
char k = box_first[f], e = k + box_count[f];
|
|
170
|
+
char i = nbox;
|
|
171
|
+
do {
|
|
172
|
+
unsigned l = x + box_rect[k].x, rr = l + box_rect[k].w;
|
|
173
|
+
bll[i] = (char)l;
|
|
174
|
+
blh[i] = l >> 8;
|
|
175
|
+
brl[i] = (char)rr;
|
|
176
|
+
brh[i] = rr >> 8;
|
|
177
|
+
bhl[i] = l >> 1;
|
|
178
|
+
bhr[i] = rr >> 1;
|
|
179
|
+
char t = y + box_rect[k].y;
|
|
180
|
+
bt[i] = t;
|
|
181
|
+
bb[i] = t + box_rect[k].h;
|
|
182
|
+
bg[i] = box_group[k];
|
|
183
|
+
bm[i] = box_mask[k];
|
|
184
|
+
bo[i] = a;
|
|
185
|
+
i++;
|
|
186
|
+
k++;
|
|
187
|
+
} while (k != e);
|
|
188
|
+
nbox = i;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// The sprite half of the draw: X is 9 bits, spr_move sets the $D010 bit.
|
|
192
|
+
void draw_sprite(char a)
|
|
193
|
+
{
|
|
194
|
+
spr_move(a, ax[a], ay[a]);
|
|
195
|
+
spr_image(a, SPR_BLK + aframe[a]);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// 9-bit "left of i is left of right of j": high bytes first.
|
|
199
|
+
static inline bool xlt(char i, char j)
|
|
200
|
+
{
|
|
201
|
+
return blh[i] < brh[j] || (blh[i] == brh[j] && bll[i] < brl[j]);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// The AABB test. Y first: it is one byte and in a side-scrolling
|
|
205
|
+
// scene most pairs are apart in Y. Each compare can end the test.
|
|
206
|
+
static inline bool overlap9(char i, char j)
|
|
207
|
+
{
|
|
208
|
+
return bt[i] < bb[j] && bt[j] < bb[i] && xlt(i, j) && xlt(j, i);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// The same test on X / 2: every coordinate one byte, 2-pixel precision.
|
|
212
|
+
static inline bool overlap8(char i, char j)
|
|
213
|
+
{
|
|
214
|
+
return bt[i] < bb[j] && bt[j] < bb[i] && bhl[i] < bhr[j] && bhl[j] < bhr[i];
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// The broken variant: only the low byte of X, as when $D010's bit is
|
|
218
|
+
// ignored. Used only to count its false hits.
|
|
219
|
+
static inline bool overlap_lo(char i, char j)
|
|
220
|
+
{
|
|
221
|
+
return bt[i] < bb[j] && bt[j] < bb[i] && bll[i] < brl[j] && bll[j] < brl[i];
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
char pairs_all, pairs_tested, frame_events;
|
|
225
|
+
|
|
226
|
+
void collide(void)
|
|
227
|
+
{
|
|
228
|
+
pairs_all = 0;
|
|
229
|
+
pairs_tested = 0;
|
|
230
|
+
for (char i = 0; i + 1 < nbox; i++) {
|
|
231
|
+
char m = bm[i];
|
|
232
|
+
for (char j = i + 1; j < nbox; j++) {
|
|
233
|
+
pairs_all++;
|
|
234
|
+
if (!(m & bg[j]))
|
|
235
|
+
continue; // friendly or irrelevant pair
|
|
236
|
+
pairs_tested++;
|
|
237
|
+
if (overlap9(i, j)) {
|
|
238
|
+
char e = event_bit(bo[i], bo[j]);
|
|
239
|
+
if (e == EV_E1_P && (bg[i] == G_PSHOT || bg[j] == G_PSHOT))
|
|
240
|
+
e = EV_BLADE_E1;
|
|
241
|
+
frame_events |= e;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// --- CIA1 timer B harness (as tile-grid-collision.md) --------------------
|
|
248
|
+
static inline void timer_start(void)
|
|
249
|
+
{
|
|
250
|
+
cia1.crb = 0x00;
|
|
251
|
+
cia1.tb = 0xffff;
|
|
252
|
+
cia1.crb = 0x11;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
static inline unsigned timer_stop(void)
|
|
256
|
+
{
|
|
257
|
+
cia1.crb = 0x00;
|
|
258
|
+
return 0xffff - cia1.tb;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Per-pair timing: each is called 100 times through a pointer and the
|
|
262
|
+
// empty call is subtracted, so the figure is the test alone.
|
|
263
|
+
char gi, gj, gk;
|
|
264
|
+
volatile bool sink;
|
|
265
|
+
__noinline void nothing(void) { }
|
|
266
|
+
__noinline void pair_hit(void) { sink = overlap9(gi, gj); }
|
|
267
|
+
__noinline void pair_miss(void) { sink = overlap9(gi, gk); }
|
|
268
|
+
__noinline void pair_hit8(void) { sink = overlap8(gi, gj); }
|
|
269
|
+
__noinline void pair_miss8(void) { sink = overlap8(gi, gk); }
|
|
270
|
+
|
|
271
|
+
unsigned time100(void (*fn)(void))
|
|
272
|
+
{
|
|
273
|
+
__asm { sei }
|
|
274
|
+
timer_start();
|
|
275
|
+
for (char n = 0; n < 100; n++)
|
|
276
|
+
fn();
|
|
277
|
+
unsigned t = timer_stop();
|
|
278
|
+
__asm { cli }
|
|
279
|
+
return t;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// --- sprite images: figure in the sprite colour, boxes outlined in MC1 --
|
|
283
|
+
void mc_px(char *img, char cx, char row, char v)
|
|
284
|
+
{
|
|
285
|
+
char *p = img + row * 3 + (cx >> 2);
|
|
286
|
+
char s = (3 - (cx & 3)) * 2;
|
|
287
|
+
*p = (*p & ~(3 << s)) | (v << s);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
void make_images(void)
|
|
291
|
+
{
|
|
292
|
+
for (unsigned i = 0; i < FRAMES * 64; i++)
|
|
293
|
+
SprData[i] = 0;
|
|
294
|
+
for (char f = 0; f < FRAMES; f++) {
|
|
295
|
+
char *img = SprData + f * 64;
|
|
296
|
+
const struct Rect *r = figure + f;
|
|
297
|
+
for (char y = r->y; y < r->y + r->h; y++)
|
|
298
|
+
for (char x = r->x >> 1; x < (r->x + r->w) >> 1; x++)
|
|
299
|
+
mc_px(img, x, y, 2);
|
|
300
|
+
if (f == F_ATTACK) // the blade is drawn too
|
|
301
|
+
for (char y = 6; y < 10; y++)
|
|
302
|
+
for (char x = 7; x < 12; x++)
|
|
303
|
+
mc_px(img, x, y, 2);
|
|
304
|
+
for (char k = box_first[f]; k < box_first[f] + box_count[f]; k++) {
|
|
305
|
+
const struct Rect *b = box_rect + k;
|
|
306
|
+
char x0 = b->x >> 1, x1 = ((b->x + b->w) >> 1) - 1;
|
|
307
|
+
char y0 = b->y, y1 = b->y + b->h - 1;
|
|
308
|
+
for (char x = x0; x <= x1; x++) {
|
|
309
|
+
mc_px(img, x, y0, 3);
|
|
310
|
+
mc_px(img, x, y1, 3);
|
|
311
|
+
}
|
|
312
|
+
for (char y = y0; y <= y1; y++) {
|
|
313
|
+
mc_px(img, x0, y, 3);
|
|
314
|
+
mc_px(img, x1, y, 3);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// --- text helpers (screen codes) ------------------------------------------
|
|
321
|
+
void put_str(char *p, const char *s)
|
|
322
|
+
{
|
|
323
|
+
while (*s)
|
|
324
|
+
*p++ = *s++;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
void put_dec(char *p, unsigned v, char digits)
|
|
328
|
+
{
|
|
329
|
+
for (char i = digits; i > 0; i--) {
|
|
330
|
+
p[i - 1] = 0x30 + v % 10;
|
|
331
|
+
v /= 10;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
void put_hex2(char *p, char v)
|
|
336
|
+
{
|
|
337
|
+
char d = v >> 4;
|
|
338
|
+
p[0] = d < 10 ? 0x30 + d : d - 9;
|
|
339
|
+
d = v & 15;
|
|
340
|
+
p[1] = d < 10 ? 0x30 + d : d - 9;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// --- scenario --------------------------------------------------------------
|
|
344
|
+
#define STAGE_FRAMES 64
|
|
345
|
+
#define HOLD_T 36
|
|
346
|
+
|
|
347
|
+
const char stage_pose[3] = { F_STAND, F_CROUCH, F_ATTACK };
|
|
348
|
+
const char stage_expect[3] = {
|
|
349
|
+
EV_EB1_P | EV_PB1_E2, // stand: shot in the head
|
|
350
|
+
EV_PB1_E2, // crouch: the shot passes over
|
|
351
|
+
EV_EB1_P | EV_BLADE_E1 | EV_PB1_E2 // attack: body hit, blade hits E1
|
|
352
|
+
};
|
|
353
|
+
const char *stage_name[3] = { s"stand ", s"crouch", s"attack" };
|
|
354
|
+
|
|
355
|
+
// Positions at frame t of a stage: bullets move 2 pixels a frame.
|
|
356
|
+
void place(char pose, char t)
|
|
357
|
+
{
|
|
358
|
+
ax[A_P] = 100; ay[A_P] = 200; aframe[A_P] = pose;
|
|
359
|
+
ax[A_E1] = 116; ay[A_E1] = 200; aframe[A_E1] = F_ENEMY;
|
|
360
|
+
ax[A_E2] = 300; ay[A_E2] = 160; aframe[A_E2] = F_ENEMY;
|
|
361
|
+
ax[A_EB1] = 164 - 2 * t; ay[A_EB1] = 196; aframe[A_EB1] = F_ESHOT;
|
|
362
|
+
ax[A_EB2] = 380 - 2 * t; ay[A_EB2] = 164; aframe[A_EB2] = F_ESHOT;
|
|
363
|
+
ax[A_PB1] = 220 + 2 * t; ay[A_PB1] = 156; aframe[A_PB1] = F_PSHOT;
|
|
364
|
+
ax[A_PB2] = 20 + 2 * t; ay[A_PB2] = 160; aframe[A_PB2] = F_PSHOT;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
int main(void)
|
|
368
|
+
{
|
|
369
|
+
vic.color_border = 0;
|
|
370
|
+
vic.color_back = 0;
|
|
371
|
+
for (unsigned i = 0; i < 1000; i++) {
|
|
372
|
+
Screen[i] = 0x20;
|
|
373
|
+
Color[i] = 1;
|
|
374
|
+
}
|
|
375
|
+
make_images();
|
|
376
|
+
|
|
377
|
+
spr_init(Screen);
|
|
378
|
+
for (char a = 0; a < ACTORS; a++)
|
|
379
|
+
spr_set(a, false, 0, 0, SPR_BLK, acol[a], true, false, false);
|
|
380
|
+
vic.spr_mcolor0 = 0;
|
|
381
|
+
vic.spr_mcolor1 = 7; // box outlines: yellow
|
|
382
|
+
|
|
383
|
+
put_str(Screen + 0, s"per-frame hitbox stage frame");
|
|
384
|
+
put_str(Screen + 2 * 40, s"pose exp got d01e");
|
|
385
|
+
put_str(Screen + 7 * 40, s"pairs tested boxes");
|
|
386
|
+
put_str(Screen + 8 * 40, s"emit max collide max");
|
|
387
|
+
put_str(Screen + 9 * 40, s"pair 9-bit hit miss");
|
|
388
|
+
put_str(Screen + 10 * 40, s"pair 8-bit hit miss");
|
|
389
|
+
put_str(Screen + 11 * 40, s"low-byte-x false hits");
|
|
390
|
+
put_str(Screen + 12 * 40, s"p box l r t b");
|
|
391
|
+
|
|
392
|
+
// Per-pair cost, before the scenario: box 0 and 1 overlap, box 0 and
|
|
393
|
+
// 2 fail the first compare. 100 calls each, less 100 empty calls,
|
|
394
|
+
// with the screen blanked so no badline steals a cycle.
|
|
395
|
+
nbox = 0;
|
|
396
|
+
place(F_STAND, 32);
|
|
397
|
+
emit_boxes(A_P); // box 0
|
|
398
|
+
emit_boxes(A_EB1); // box 1: overlaps it
|
|
399
|
+
emit_boxes(A_E2); // box 2: apart in Y
|
|
400
|
+
gi = 0; gj = 1; gk = 2;
|
|
401
|
+
vic.ctrl1 &= ~VIC_CTRL1_DEN;
|
|
402
|
+
vic_waitFrame();
|
|
403
|
+
vic_waitFrame();
|
|
404
|
+
unsigned t_none = time100(nothing);
|
|
405
|
+
unsigned c_hit = (time100(pair_hit) - t_none) / 100;
|
|
406
|
+
unsigned c_miss = (time100(pair_miss) - t_none) / 100;
|
|
407
|
+
unsigned c_hit8 = (time100(pair_hit8) - t_none) / 100;
|
|
408
|
+
unsigned c_miss8 = (time100(pair_miss8) - t_none) / 100;
|
|
409
|
+
vic.ctrl1 |= VIC_CTRL1_DEN;
|
|
410
|
+
put_dec(Screen + 9 * 40 + 15, c_hit, 3);
|
|
411
|
+
put_dec(Screen + 9 * 40 + 25, c_miss, 3);
|
|
412
|
+
put_dec(Screen + 10 * 40 + 15, c_hit8, 3);
|
|
413
|
+
put_dec(Screen + 10 * 40 + 25, c_miss8, 3);
|
|
414
|
+
|
|
415
|
+
// Put every sprite at its first position before enabling them, or
|
|
416
|
+
// they meet at 0, 0 for a frame and $D01E latches that.
|
|
417
|
+
place(stage_pose[0], 0);
|
|
418
|
+
for (char a = 0; a < ACTORS; a++)
|
|
419
|
+
draw_sprite(a);
|
|
420
|
+
nbox = 0; // nothing drawn yet
|
|
421
|
+
vic.spr_enable = (1 << ACTORS) - 1;
|
|
422
|
+
char stage = 0, t = 0, fault = 0, lo_false = 0;
|
|
423
|
+
bool done = false;
|
|
424
|
+
unsigned frame = 0, d_max = 0, c_max = 0;
|
|
425
|
+
char stage_events = 0;
|
|
426
|
+
vic_waitFrame();
|
|
427
|
+
vic.spr_sprcol; // clear the latch
|
|
428
|
+
|
|
429
|
+
for (;;) {
|
|
430
|
+
vic_waitFrame();
|
|
431
|
+
|
|
432
|
+
// Collide first, on the boxes the last frame's draw emitted, so
|
|
433
|
+
// the test runs at the top of the blank on both models.
|
|
434
|
+
__asm { sei }
|
|
435
|
+
frame_events = 0;
|
|
436
|
+
timer_start();
|
|
437
|
+
collide();
|
|
438
|
+
unsigned tc = timer_stop();
|
|
439
|
+
place(stage_pose[stage], done ? HOLD_T : t);
|
|
440
|
+
timer_start();
|
|
441
|
+
nbox = 0;
|
|
442
|
+
for (char a = 0; a < ACTORS; a++)
|
|
443
|
+
emit_boxes(a);
|
|
444
|
+
unsigned td = timer_stop();
|
|
445
|
+
__asm { cli }
|
|
446
|
+
for (char a = 0; a < ACTORS; a++)
|
|
447
|
+
draw_sprite(a);
|
|
448
|
+
if (td > d_max) d_max = td;
|
|
449
|
+
if (tc > c_max) c_max = tc;
|
|
450
|
+
stage_events |= frame_events;
|
|
451
|
+
|
|
452
|
+
// The low-byte test on the pair that differs by 256 in X.
|
|
453
|
+
for (char i = 0; i < nbox; i++)
|
|
454
|
+
for (char j = 0; j < nbox; j++)
|
|
455
|
+
if (bo[i] == A_E2 && bo[j] == A_PB2 && overlap_lo(i, j))
|
|
456
|
+
lo_false++;
|
|
457
|
+
|
|
458
|
+
put_dec(Screen + 24, stage + 1, 1);
|
|
459
|
+
put_dec(Screen + 32, frame, 5);
|
|
460
|
+
put_dec(Screen + 7 * 40 + 6, pairs_all, 2);
|
|
461
|
+
put_dec(Screen + 7 * 40 + 16, pairs_tested, 2);
|
|
462
|
+
put_dec(Screen + 7 * 40 + 25, nbox, 1);
|
|
463
|
+
put_dec(Screen + 8 * 40 + 9, d_max, 5);
|
|
464
|
+
put_dec(Screen + 8 * 40 + 27, c_max, 5);
|
|
465
|
+
put_dec(Screen + 11 * 40 + 22, lo_false, 3);
|
|
466
|
+
char p = 0;
|
|
467
|
+
while (bo[p] != A_P)
|
|
468
|
+
p++; // the player's first box
|
|
469
|
+
put_dec(Screen + 12 * 40 + 8, bll[p] + 256 * blh[p], 3);
|
|
470
|
+
put_dec(Screen + 12 * 40 + 13, brl[p] + 256 * brh[p], 3);
|
|
471
|
+
put_dec(Screen + 12 * 40 + 18, bt[p], 3);
|
|
472
|
+
put_dec(Screen + 12 * 40 + 23, bb[p], 3);
|
|
473
|
+
frame++;
|
|
474
|
+
|
|
475
|
+
if (!done && ++t == STAGE_FRAMES) {
|
|
476
|
+
char hw = vic.spr_sprcol; // read once per stage, clears it
|
|
477
|
+
char *row = Screen + (3 + stage) * 40;
|
|
478
|
+
put_str(row, stage_name[stage]);
|
|
479
|
+
put_hex2(row + 8, stage_expect[stage]);
|
|
480
|
+
put_hex2(row + 12, stage_events);
|
|
481
|
+
put_hex2(row + 16, hw);
|
|
482
|
+
bool ok = stage_events == stage_expect[stage];
|
|
483
|
+
put_str(row + 20, ok ? s"pass" : s"fail");
|
|
484
|
+
if (!ok) fault = stage + 1;
|
|
485
|
+
stage_events = 0;
|
|
486
|
+
t = 0;
|
|
487
|
+
if (stage == 2) {
|
|
488
|
+
done = true;
|
|
489
|
+
if (lo_false == 0) fault = 4; // the 8-bit trap must fire
|
|
490
|
+
RESULT = fault ? 2 : 1;
|
|
491
|
+
vic.color_border = fault ? 2 : 5;
|
|
492
|
+
put_str(Screen + 40, fault ? s"result fail" : s"result pass");
|
|
493
|
+
Screen[40 + 12] = 0x30 + fault;
|
|
494
|
+
} else
|
|
495
|
+
stage++;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
return 0;
|
|
499
|
+
}
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
## Build
|
|
503
|
+
|
|
504
|
+
```bash
|
|
505
|
+
oscar64 -tm=c64 -O2 -o=per-frame-hitbox.prg per-frame-hitbox.c
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
Produces `per-frame-hitbox.prg`, 3,711 bytes. The sprite images are
|
|
509
|
+
built at run time at `$3000`, blocks 192 to 197, above the program. Then
|
|
510
|
+
run headless in VICE (PAL):
|
|
511
|
+
|
|
512
|
+
```bash
|
|
513
|
+
GSETTINGS_SCHEMA_DIR=/opt/homebrew/share/glib-2.0/schemas x64sc -default -warp +sound \
|
|
514
|
+
+autostart-delay-random -autostartprgmode 1 -limitcycles 8000000 \
|
|
515
|
+
-exitscreenshot per-frame-hitbox.png -autostart per-frame-hitbox.prg
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
Add `-model ntsc` for the NTSC picture. The three stages take 192 frames;
|
|
519
|
+
at 8,000,000 cycles the verdict is posted on both models.
|
|
520
|
+
|
|
521
|
+
## Expected output
|
|
522
|
+
|
|
523
|
+
The scene, in sprite coordinates (Y is the sprite Y register):
|
|
524
|
+
|
|
525
|
+
| Actor | Sprite | Position | Moves | Group of its box |
|
|
526
|
+
|---|---|---|---|---|
|
|
527
|
+
| enemy bullet EB1 | 0 | Y 196, X 164 at stage frame 0 | left 2 px a frame | enemy bullet |
|
|
528
|
+
| enemy bullet EB2 | 1 | Y 164, X 380 | left 2 px a frame | enemy bullet |
|
|
529
|
+
| player bullet PB1 | 2 | Y 156, X 220 | right 2 px a frame | player bullet |
|
|
530
|
+
| player bullet PB2 | 3 | Y 160, X 20 | right 2 px a frame | player bullet |
|
|
531
|
+
| player P | 4 | X 100, Y 200 | pose per stage | player (and blade: player bullet) |
|
|
532
|
+
| enemy E1 | 5 | X 116, Y 200 | still | enemy |
|
|
533
|
+
| enemy E2 | 6 | X 300, Y 160 | still | enemy |
|
|
534
|
+
|
|
535
|
+
Event bits, set when a tested pair overlaps: `01` EB1 hits the player,
|
|
536
|
+
`02` E1 touches the player's body, `04` the blade hits E1, `08` PB1 hits
|
|
537
|
+
E2, `10` EB2 hits E2, `20` PB2 hits E2. Bits `02`, `10` and `20` must
|
|
538
|
+
never be set: E1's box never reaches the body, enemy bullet against enemy
|
|
539
|
+
is not a tested pair, and PB2's X differs from E2's by 256.
|
|
540
|
+
|
|
541
|
+
Measured in VICE x64sc 3.10 with the pinned command, text decoded
|
|
542
|
+
against the character ROM (rows 0 to 12, PAL):
|
|
543
|
+
|
|
544
|
+
```text
|
|
545
|
+
PER-FRAME HITBOX STAGE 3 FRAME 00237
|
|
546
|
+
RESULT PASS 0
|
|
547
|
+
POSE EXP GOT D01E
|
|
548
|
+
STAND 09 09 77 PASS
|
|
549
|
+
CROUCH 08 08 77 PASS
|
|
550
|
+
ATTACK 0D 0D 77 PASS
|
|
551
|
+
|
|
552
|
+
PAIRS 28 TESTED 10 BOXES 8
|
|
553
|
+
EMIT MAX 02148 COLLIDE MAX 02037
|
|
554
|
+
PAIR 9-BIT HIT 096 MISS 028
|
|
555
|
+
PAIR 8-BIT HIT 059 MISS 025
|
|
556
|
+
LOW-BYTE-X FALSE HITS 033
|
|
557
|
+
P BOX L 106R 114T 202B 221
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
NTSC reads the same except `FRAME 00266` and `EMIT MAX 02234`. The
|
|
561
|
+
border is palette index 5, (98, 213, 50) on PAL and (114, 189, 103) on
|
|
562
|
+
NTSC.
|
|
563
|
+
|
|
564
|
+
What the numbers say:
|
|
565
|
+
|
|
566
|
+
- Stand and crouch differ only in the player's frame. EB1 crosses the
|
|
567
|
+
player at the same X and Y in both; its box (Y 204 to 207) meets the
|
|
568
|
+
stand box (Y 202 to 220) and passes over the crouch box (Y 212 to 220).
|
|
569
|
+
- In the attack stage the blade's box (X 114 to 123) reaches E1's box
|
|
570
|
+
(X 120 to 135); the body's box (X 106 to 113) does not, so the event is
|
|
571
|
+
`04`, never `02`.
|
|
572
|
+
- `D01E` is `77` in every stage: sprites 0, 1, 2, 4, 5 and 6 touched
|
|
573
|
+
something, and sprite 3, PB2, touched nothing. In the crouch stage the
|
|
574
|
+
player's bit is set by its pixels touching E1's (the figures share X
|
|
575
|
+
116 to 117), though no box of the player's overlaps anything; EB2's bit
|
|
576
|
+
is set by E2, a pair the game ignores. The register gives no pair and
|
|
577
|
+
no group.
|
|
578
|
+
- The low-byte test found 33 frames in which PB2 and E2 "overlap": PB2's
|
|
579
|
+
X low byte passes E2's (304 to 319, low bytes 48 to 63). The 9-bit test
|
|
580
|
+
found none.
|
|
581
|
+
- `PAIRS 28 TESTED 10`: eight boxes make 28 pairs, and the group masks
|
|
582
|
+
leave 10 to test.
|
|
583
|
+
|
|
584
|
+
Cycle figures, CIA1 timer B, interrupts masked. The per-pair figures are
|
|
585
|
+
100 calls of a test through a function pointer, less 100 calls of an
|
|
586
|
+
empty function, divided by 100 and rounded down, with the screen blanked
|
|
587
|
+
(`$D011` bit 4 clear) so no badline steals a cycle. A hit runs all four
|
|
588
|
+
compares; a miss fails the first one. `COLLIDE MAX` is the worst frame of
|
|
589
|
+
the whole pass over the list and `EMIT MAX` the worst frame of filling it,
|
|
590
|
+
eight boxes. Both run straight after `vic_waitFrame()` returns at line
|
|
591
|
+
256. The collide pass fits the vertical blank on both models and reads
|
|
592
|
+
2,037 on both. The emit runs after it and on NTSC crosses into the first
|
|
593
|
+
badlines of the next frame, which is why NTSC reads 86 cycles more; the
|
|
594
|
+
PAL figure is the cost.
|
|
595
|
+
|
|
596
|
+
The pictures: `screenshots/per-frame-hitbox.png` (PAL) and
|
|
597
|
+
`screenshots/per-frame-hitbox-ntsc.png` (NTSC), the hold state at stage
|
|
598
|
+
frame 36 in the attack pose. Measured with PIL on both: every one of the
|
|
599
|
+
eight boxes has its outline in yellow (MC1, (255, 255, 70) on PAL,
|
|
600
|
+
(255, 248, 141) on NTSC) at exactly the pixels its box list entry names,
|
|
601
|
+
X + 8 across and Y + 1 − 16 down on PAL (− 28 on NTSC). Four pixels
|
|
602
|
+
sampled one step outside each box are not yellow, except the one left of
|
|
603
|
+
the blade, which is the body's right edge.
|
|
604
|
+
The four bullet outlines are complete (20 of 20 pixels each). Pixels
|
|
605
|
+
missing from the others are covered by a sprite in front: 7 of the
|
|
606
|
+
body's 50 by EB1 (light red), 2 of E1's 64 by the player's blade
|
|
607
|
+
(white), 17 of E2's 64 by PB1 (cyan) and EB2 (light red). The + 1 is the
|
|
608
|
+
sprite's first line, which is one raster line below its Y register, as
|
|
609
|
+
`sprite_sine_chain` measured. Each model run twice gives byte-identical
|
|
610
|
+
PNGs.
|
|
611
|
+
|
|
612
|
+
## Why this works
|
|
613
|
+
|
|
614
|
+
The box belongs to the animation frame, not to the actor.
|
|
615
|
+
`box_first[f]` and `box_count[f]` pick a frame's entries in `box_rect`,
|
|
616
|
+
each an offset from the sprite's top-left corner plus a width and a
|
|
617
|
+
height, and a group bit in `box_group`. Changing the pose changes the
|
|
618
|
+
sprite pointer and the boxes together, so the collision shape can never
|
|
619
|
+
disagree with the picture: crouching lowers the box's top by 10 pixels,
|
|
620
|
+
and the attack frame adds a second box in another group.
|
|
621
|
+
|
|
622
|
+
`emit_boxes` runs where the sprite is positioned and writes screen-space
|
|
623
|
+
edges into parallel byte arrays: left and right X as a low and a high
|
|
624
|
+
byte (9 bits, right edge exclusive), top and bottom Y (one byte; a box
|
|
625
|
+
must end above Y 256), the group bit, the mask of groups it is tested
|
|
626
|
+
against and the owning actor. An actor that is not drawn emits nothing
|
|
627
|
+
and costs nothing in the collision pass. `collide` walks the pairs
|
|
628
|
+
`i < j` once; `bm[i] & bg[j]` is zero for friendly and irrelevant pairs,
|
|
629
|
+
which is how enemy bullets pass through enemies and a player's blade
|
|
630
|
+
cannot hit the player. The masks are symmetric, so each pair is tested
|
|
631
|
+
once.
|
|
632
|
+
|
|
633
|
+
`overlap9` tests Y first because it is one byte, then the two X
|
|
634
|
+
conditions, each with the high bytes compared first. `xlt(i, j)` is
|
|
635
|
+
"i's left edge is left of j's right edge". The broken variant that
|
|
636
|
+
compares only the low bytes wraps at 256: 304 has low byte 48, so a
|
|
637
|
+
bullet at X 52 lands "inside" an enemy at 304. That is the mechanism of
|
|
638
|
+
`sprite_x_high_bit_wrong_register` moved from the VIC to the game's own
|
|
639
|
+
arithmetic. `overlap8` halves every X at emit time, so all four compares
|
|
640
|
+
are one byte, at 2-pixel precision; it is 37 cycles cheaper per hit
|
|
641
|
+
here.
|
|
642
|
+
|
|
643
|
+
The per-pose events come out right because the draw that emits the boxes
|
|
644
|
+
is the draw that sets the sprite pointer. The collision pass runs at the
|
|
645
|
+
top of the next frame on the list the last draw left, so it tests what
|
|
646
|
+
was on screen.
|
|
647
|
+
|
|
648
|
+
Verified: compiled with Oscar64, run headless in VICE x64sc 3.10 with the
|
|
649
|
+
pinned command on PAL and NTSC, each twice with byte-identical PNGs; the
|
|
650
|
+
text was decoded against the character ROM and the box outlines located
|
|
651
|
+
by colour with PIL, not by eye.
|