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,277 @@
|
|
|
1
|
+
# platformer: a side-scrolling platformer starter
|
|
2
|
+
|
|
3
|
+
A small game that plays: a level 2,048 pixels wide scrolls through a
|
|
4
|
+
38-column window as you run; you jump with 8.8 fixed-point physics, walk
|
|
5
|
+
up 45-degree and 1-in-2 slopes, land on blocks and one-way ledges, stomp
|
|
6
|
+
enemies that wake as they come near the screen, collect coins, and have
|
|
7
|
+
three lives. A HUD sits under the playfield and an original two-voice tune
|
|
8
|
+
plays. Title, fire to start, game over back to the title. PAL and NTSC,
|
|
9
|
+
Oscar64 C with a KickAssembler part.
|
|
10
|
+
|
|
11
|
+
Start a game from it in c64-kb:
|
|
12
|
+
`npm run new-project -- platformer ~/c64/mygame`.
|
|
13
|
+
|
|
14
|
+
## Playing
|
|
15
|
+
|
|
16
|
+
`make run` opens VICE; give it a joystick device for port 2 ("Driving it
|
|
17
|
+
headless" below says how). Left and right run,
|
|
18
|
+
fire jumps, down + fire drops through a ledge. Land on an enemy from
|
|
19
|
+
above to squash it (100); a coin is 10; the flag at the far end is 1,000
|
|
20
|
+
and starts the level again.
|
|
21
|
+
|
|
22
|
+
## Files
|
|
23
|
+
|
|
24
|
+
| File | Holds |
|
|
25
|
+
|---|---|
|
|
26
|
+
| `src/main.c` | The frame loop, the states (title, play, dying, game over, level clear), lives |
|
|
27
|
+
| `src/game.h` | Every shared constant, variable and function, in one place |
|
|
28
|
+
| `src/level.c` | The level as ten lines of text, the 2 x 2 metatiles, cell lookups, the slope height table |
|
|
29
|
+
| `src/art.c` | Every picture as text: playfield glyphs, sprite shapes, hit boxes |
|
|
30
|
+
| `src/player.c` | The physics every body shares (walk, fall, land) and the player on top |
|
|
31
|
+
| `src/actors.c` | Enemies: the activation window, five live slots, walker and hopper, hit boxes by group |
|
|
32
|
+
| `src/view.c` | VIC-II: bank 3, the camera, the three-page scroll, sprite shadows |
|
|
33
|
+
| `src/anim.c` | Animation sequences (frame, duration, loop or hold) |
|
|
34
|
+
| `src/hud.c`, `src/sound.c` | Score digits and HUD text; sound effects on SID voice 3 |
|
|
35
|
+
| `src/engine.asm` | KickAssembler: the slice copy for the scroll, the two raster IRQs, the tune and its player |
|
|
36
|
+
| `src/autopilot.h`, `src/verdict.h` | AUTOPILOT builds only: the scripted joystick and the self-check |
|
|
37
|
+
| `tools/tearcheck.py` | Renders the level from `src/` and proves no picture tears (`make tearcheck`) |
|
|
38
|
+
| `expect.json`, `stage-expect.json`, `PLAN.md` | The screenshot checks, the crowded-level checks (`make stage`); the plan with the c64-kb tool output |
|
|
39
|
+
|
|
40
|
+
## How a frame runs
|
|
41
|
+
|
|
42
|
+
The main loop waits for the IRQ at raster line 251, then writes the
|
|
43
|
+
sprites, plays the tune and the effects, runs the player, the enemies and
|
|
44
|
+
the camera, and publishes the next picture's `$D018` and `$D016` as one
|
|
45
|
+
pair. Two raster IRQs in `engine.asm` own those registers: at line 212,
|
|
46
|
+
inside the blank character row 20, the HUD gets 40 columns, hires and its
|
|
47
|
+
own screen page; at line 251 the playfield gets the published pair back.
|
|
48
|
+
A frame whose work runs long therefore shows the last picture again,
|
|
49
|
+
never a half-set one.
|
|
50
|
+
|
|
51
|
+
The scroll never shifts or redraws the page on display; a taken coin's
|
|
52
|
+
cells and the sprite pointers are the only writes to it, and a level
|
|
53
|
+
restart redraws all three pages at a cut. XSCROLL moves the picture a
|
|
54
|
+
pixel; a column crossing is only a `$D018` flip, because three pages are
|
|
55
|
+
kept: the one on display, the one the camera just left, and one prepared
|
|
56
|
+
for the next column in the direction of travel, five rows a frame, by a
|
|
57
|
+
KickAssembler copy one column over plus the new column's cells from the
|
|
58
|
+
level. The camera moves at most 2 pixels a frame, so the next crossing is
|
|
59
|
+
at least 4 frames off and 4 slices are enough. A frame never carries a
|
|
60
|
+
whole 20-row shift (an earlier draft of this starter did: 9,457 cycles in
|
|
61
|
+
one frame, measured with `PROF=3`).
|
|
62
|
+
|
|
63
|
+
Memory: VIC bank 3. Pages at `$C000`, `$C400` and `$E800`, the HUD page at
|
|
64
|
+
`$C800`, sprites at `$CC00`, the character set at `$E000` (the ROM's
|
|
65
|
+
glyphs 0-63 copied in, so text and the meter read). BASIC and KERNAL are
|
|
66
|
+
banked out (`$01` = `$35`). Colour RAM is never scrolled: the playfield's
|
|
67
|
+
four colours are `$D021`, `$D022`, `$D023` and the colour RAM's green.
|
|
68
|
+
|
|
69
|
+
## The measured frame
|
|
70
|
+
|
|
71
|
+
The harness meter (CIA2 timer A) over the first 255 play frames of the
|
|
72
|
+
autopilot run, VICE x64sc 3.10, `make shot check`:
|
|
73
|
+
|
|
74
|
+
| Model | Worst | Typical (median) | Frame |
|
|
75
|
+
|---|---|---|---|
|
|
76
|
+
| PAL | 11,758 | 6,212 | 19,656 |
|
|
77
|
+
| NTSC | 12,216 | 6,573 | 17,095 |
|
|
78
|
+
|
|
79
|
+
Per subsystem, built with `-dPROF=n` (worst / typical, PAL; NTSC within
|
|
80
|
+
400 cycles of each):
|
|
81
|
+
|
|
82
|
+
| n | Subsystem | Worst | Typical |
|
|
83
|
+
|---|---|---|---|
|
|
84
|
+
| 1 | player physics, coins | 4,237 | 1,686 |
|
|
85
|
+
| 2 | enemies: window, AI, hit boxes | 3,682 | 2,269 |
|
|
86
|
+
| 3 | camera and scroll slice | 4,001 | 240 |
|
|
87
|
+
| 4 | sprites to the VIC, tune, effects | 925 | 706 |
|
|
88
|
+
| 5 | HUD, sprite shadows, publish | 1,346 | 915 |
|
|
89
|
+
|
|
90
|
+
The meter covers play frames 1-255 of about 835. A review of an earlier
|
|
91
|
+
build metered two later windows (from frames 275 and 560): their worst was
|
|
92
|
+
below the first window's, their typical about 1,000 cycles above it. Not
|
|
93
|
+
re-measured on this build.
|
|
94
|
+
|
|
95
|
+
The worst frames of the parts do not fall together: the whole frame's
|
|
96
|
+
worst is 11,758, not their sum. Every figure is wall time, so badline and
|
|
97
|
+
sprite DMA are in it, and so is the split IRQ when it lands inside the
|
|
98
|
+
bracket (work past line 212; about 56 cycles by arithmetic). The IRQ at
|
|
99
|
+
251 falls just before the bracket opens and is not counted: about 66
|
|
100
|
+
cycles by arithmetic.
|
|
101
|
+
|
|
102
|
+
Against `plan-budget` (PLAN.md): it gave 10,167 to 10,765 cycles plus
|
|
103
|
+
1,432 fixed, 11,599 to 12,197 in all, verdict undetermined, with the
|
|
104
|
+
scroll left out (its only figure was the old recipe's 74,041-cycle shift,
|
|
105
|
+
issue #18) and six techniques unknown. The measured worst is 11,758 on PAL,
|
|
106
|
+
inside that range, and 12,216 on NTSC, 19 cycles above its top (an earlier build, before the walker
|
|
107
|
+
and HUD cuts below, was 356 and 785 cycles above its top). The parts disagree more than
|
|
108
|
+
the total: the budget charges per-frame-hitbox 3,693 and decimal-print
|
|
109
|
+
1,361 from their recipes, where this game tests a few box pairs and adds
|
|
110
|
+
score digits without division. For the player physics it charges only
|
|
111
|
+
slope_collision's 455, with no figure for fixed_point_8_8 or
|
|
112
|
+
jump_arc_table; measured, the player is 4,237 worst. The measured typical
|
|
113
|
+
frame, 6,212, is far under the budget's low end, because most frames have
|
|
114
|
+
no column slice and no HUD change.
|
|
115
|
+
|
|
116
|
+
## Enemies on screen
|
|
117
|
+
|
|
118
|
+
The stock level never fills every slot, but a level an agent writes can. `make stage` builds the run with row 7 crowded (ten
|
|
119
|
+
enemies in the first view, `STAGE_CROWD` in `src/level.c`), so every slot
|
|
120
|
+
is live from the first play frame, and wants no late frame in the whole run
|
|
121
|
+
and the meter's worst inside one frame on each model.
|
|
122
|
+
|
|
123
|
+
| Build | NSLOT | Worst PAL | Worst NTSC | Late frames |
|
|
124
|
+
|---|---|---|---|---|
|
|
125
|
+
| walkers probing every step, HUD redrawn whole | 6 | 17,105 | 17,262 | yes |
|
|
126
|
+
| walker judges the column ahead once; HUD figures only | 6 | 15,632 | 15,977 in frames 1-255; 17,618 from frame 400 | on NTSC |
|
|
127
|
+
| the same | 5 | 14,523 | 14,829 in frames 1-255; 15,353 from frame 400 (measured once; no target re-measures that window) | none, either model |
|
|
128
|
+
|
|
129
|
+
So `NSLOT` is 5: sprites 1-5 are enemies, sprite 6 is free. Six live
|
|
130
|
+
enemies overran an NTSC frame by about 520 cycles; a sixth needs about
|
|
131
|
+
1,000 more cycles cut from the enemy loop first (`-dPROF=2`). The walker
|
|
132
|
+
cut: a walker judges the column 6 pixels ahead once, when it first reaches
|
|
133
|
+
it (edge, step or wall), and each step is one ground snap; odd and even
|
|
134
|
+
slots step on alternate frames.
|
|
135
|
+
|
|
136
|
+
## Proving it
|
|
137
|
+
|
|
138
|
+
| Command | What it proves | Last result |
|
|
139
|
+
|---|---|---|
|
|
140
|
+
| `make shot check` | 23 checks: the verdict, the HUD text (so the split's 40 columns and XSCROLL 0), the player sprite where arithmetic puts it, the hopper where the run leaves it, the scrolled playfield's brick, grass and pit at camera 576, the blank row 20, PAL and NTSC identical, the meter | 23 of 23 passed |
|
|
141
|
+
| `make selftest` | FORCE_FAULT makes a coin worth 20: the verdict fails, the HUD score reads 000200 | check.py rejected the build |
|
|
142
|
+
| `make tearcheck` | 16 shots a model mid-play, each matched pixel for pixel against a render of the level | 32 of 32 whole or two-frame composites; the TEAR_DEMO build: 2 of 32 torn (the count moves with the code; one is enough) |
|
|
143
|
+
| `make stage` | Every enemy slot live from the first play frame: no late frame, the meter inside one frame | 4 of 4 passed (worst 14,523 PAL, 14,829 NTSC) |
|
|
144
|
+
| `make claims` | Every store the run makes, title to verdict, against CLAIMS_ARGS | 0 violations |
|
|
145
|
+
| `make disk` | `build/platformer.d64`; it boots to the title | |
|
|
146
|
+
|
|
147
|
+
The self-check (`src/verdict.h`) grades the game's own state after the
|
|
148
|
+
script: every event seen (jump, landing, slope, ledge, coin, stomp, hit,
|
|
149
|
+
respawn, wake, sleep, both scroll directions, a wall), the score equal to
|
|
150
|
+
coins x 10 + stomps x 100, the lives, the player stopped by the brick at
|
|
151
|
+
x 716 and the camera at 576 (both arithmetic), every ready page equal to
|
|
152
|
+
the level at its column, the activation window's rules, the player's
|
|
153
|
+
sprite registers against the model, and no late frame.
|
|
154
|
+
|
|
155
|
+
After every play frame it also checks four invariants, each with its own
|
|
156
|
+
bit, so a fault that heals before the end still fails the run:
|
|
157
|
+
|
|
158
|
+
| Bit | Invariant | Mutation that trips it (PAL run) |
|
|
159
|
+
|---|---|---|
|
|
160
|
+
| `0800` | no dormant, living enemy inside the view (a pop-in) | wake window cut to the middle 24 columns: `FAIL 0880` |
|
|
161
|
+
| `1000` | every live enemy inside the drop window it was judged against | the drop never happens: `FAIL 1181` |
|
|
162
|
+
| `2000` | a grounded player stands exactly on its cell's surface | `surface_walk` reads every slope at column 0: `FAIL 223D` (tearcheck still 32 of 32: only this bit sees it) |
|
|
163
|
+
| `4000` | the page to show is the camera's column, and whole | left crossings ignored: `FAIL 4001`; tearcheck 28 of 32 |
|
|
164
|
+
|
|
165
|
+
Hits use boxes per animation frame with a group and a mask (c64-kb
|
|
166
|
+
`per_frame_hitbox`). The falling frame (`SH_FALL`, from the jump table's
|
|
167
|
+
apex on) carries two boxes, the body and the feet; only the feet are in the
|
|
168
|
+
stomp group, so a stomp is the feet reaching an enemy, not a height test.
|
|
169
|
+
Boxes are bytes relative to the player's foot; an enemy more than 40 pixels
|
|
170
|
+
away is not listed. Mutation: the feet box put in the player group turns
|
|
171
|
+
the scripted stomp into a hit, and the run ends in GAME OVER with the
|
|
172
|
+
verdict failed.
|
|
173
|
+
|
|
174
|
+
How the tear check works: VICE's exit screenshot is taken mid-frame, so a
|
|
175
|
+
shot can hold two frames, split at the beam. `tools/tearcheck.py` finds,
|
|
176
|
+
line by line, the camera positions at which the level render matches the
|
|
177
|
+
shot, and allows one seam between parts at most 2 pixels (one frame of
|
|
178
|
+
camera) apart, and only if the lower part, the older frame, is exactly
|
|
179
|
+
the camera the program printed on HUD row 23 ("CAM 0576") for that frame.
|
|
180
|
+
The same number must match the playfield in every shot: a page flipped
|
|
181
|
+
without its XSCROLL is 8 pixels off. A mid-picture XSCROLL write also
|
|
182
|
+
splits a shot into parts 1-2 pixels apart; the review's mutation (XSCROLL
|
|
183
|
+
written again at line 150) passed four shots as two frames until the
|
|
184
|
+
lower-part rule was added, and is now caught. Rows that are all sky match
|
|
185
|
+
every camera, so a tear inside them cannot be seen, by this check or by
|
|
186
|
+
eye. The TEAR_DEMO build
|
|
187
|
+
shifts the page on display in place, the old way; the check catches it
|
|
188
|
+
(off by 8, or torn), so the check can see a tear.
|
|
189
|
+
|
|
190
|
+
## Extending it
|
|
191
|
+
|
|
192
|
+
1. **A second level, or longer ones.** Edit the text in `src/level.c`;
|
|
193
|
+
keep the metatile keys. For more than fits in memory, compress it with
|
|
194
|
+
c64-kb `level-rle-decoder` (`docs/recipes/oscar64/level-rle-decoder.md`)
|
|
195
|
+
or load levels from disk (`kernal_file_read_seq`,
|
|
196
|
+
`docs/techniques/file-io.md`). `tools/tearcheck.py` renders the
|
|
197
|
+
`LEVEL` text block, so a compressed level needs it changed too. Then re-time `src/autopilot.h` with
|
|
198
|
+
`-dDEBUG_AT=n` builds: the script is a timeline, so a changed level
|
|
199
|
+
changes the run.
|
|
200
|
+
2. **More enemies on screen than five.** One sprite per live slot is the
|
|
201
|
+
limit here. A multiplexer lifts it: `sprite_multiplex_8`
|
|
202
|
+
(`docs/recipes/oscar64/sprite-multiplex-8.md`) or the game multiplexer
|
|
203
|
+
`sprite_multiplex_game` (`docs/recipes/kickassembler/sprite-multiplex-game.md`).
|
|
204
|
+
The activation window already hands out slots; raising `NSLOT` is the
|
|
205
|
+
easy part. The multiplexer's IRQs must join `engine.asm`'s `$FFFE`
|
|
206
|
+
chain around lines 212 and 251, and it replaces `view_apply`.
|
|
207
|
+
3. **Parallax or a vertical component.** `charset_parallax`
|
|
208
|
+
(`docs/recipes/oscar64/charset-parallax.md`) moves reserved glyphs for
|
|
209
|
+
a background layer at no screen cost. Vertical scrolling needs
|
|
210
|
+
`eight_way_scroll_double_buffer` (`docs/recipes/kickassembler/eight-way-scroll.md`),
|
|
211
|
+
whose redraw and colour bands this three-page scheme would replace.
|
|
212
|
+
|
|
213
|
+
Smaller steps: a high-score table on disk (`high-score-persist`,
|
|
214
|
+
`docs/recipes/oscar64/high-score-persist.md`; the harness's `SHOT_DISK=1`
|
|
215
|
+
attaches the image during `make shot`), a variable jump height (cut
|
|
216
|
+
`pjump` to `JUMP_APEX` when fire is released while rising), more tiles
|
|
217
|
+
(add a key, four glyphs and their art).
|
|
218
|
+
|
|
219
|
+
## Driving it headless
|
|
220
|
+
|
|
221
|
+
`make joy` builds the normal game with its port byte read from `$02FE`
|
|
222
|
+
instead of `$DC00`; `tools/drive.py` (from the action-puzzle starter) plays
|
|
223
|
+
it over VICE's binary monitor, at real speed (no warp; the monitor port is
|
|
224
|
+
DRIVE_PORT or a free one), and reads the HUD page. Measured: title,
|
|
225
|
+
fire, LIVES 3, holding right loses all three lives, GAME OVER, the title
|
|
226
|
+
with HI 000030, fire, a new game at LIVES 3.
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
make joy
|
|
230
|
+
python3 tools/drive.py build/platformer-joy.prg "until:PRESS FIRE" tap:fire \
|
|
231
|
+
"until:LIVES 3" hold:right "until:GAME OVER" "until:PRESS FIRE" print
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
`make run` starts the windowed VICE with no joystick device chosen: pick
|
|
235
|
+
one for port 2 in its settings, or pass one, e.g.
|
|
236
|
+
`make run X64SC_WINDOWED="x64sc -joydev2 1"` (1 is the numeric keypad,
|
|
237
|
+
from `x64sc -help`; not tried here).
|
|
238
|
+
|
|
239
|
+
## Which Oscar64
|
|
240
|
+
|
|
241
|
+
It builds and passes on both the local build named in c64-kb's CLAUDE.md
|
|
242
|
+
(1.32.271 plus c1270bc) and the released v1.32.273: `make shot check`,
|
|
243
|
+
`selftest` and `stage` pass on each (v1.32.273: worst 11,756 PAL, 12,204
|
|
244
|
+
NTSC). Two workarounds make that so, both for faults of the released
|
|
245
|
+
compiler that the local build does not have:
|
|
246
|
+
|
|
247
|
+
- `surface_at` (`src/level.c`) is `__noinline`. Inlined into
|
|
248
|
+
`surface_walk`, v1.32.273 and upstream 9a902f6 compile
|
|
249
|
+
`heights[((a & A_SLOPE) >> 1) | (x & 7)]` as `ORA heights,x` with X as
|
|
250
|
+
`cell_attr` left it, and never compute the index: the player stops a few
|
|
251
|
+
pixels up the first 45-degree slope and the run ends at LIVES 0. Issue
|
|
252
|
+
#30 holds the fault.
|
|
253
|
+
- `hud_draw` writes the score through `put_digits`. A loop storing
|
|
254
|
+
`HUD22[6 + i]` kept only the first digit on v1.32.273 (the HUD read
|
|
255
|
+
`SCORE 0`); not reduced or filed.
|
|
256
|
+
|
|
257
|
+
## Left out on purpose
|
|
258
|
+
|
|
259
|
+
- The high score is not saved: it lives until power-off.
|
|
260
|
+
- No sprite multiplexer: at most five enemies live (see "Enemies on screen").
|
|
261
|
+
- No vertical scroll; the playfield is 20 rows, the level 10 tiles high.
|
|
262
|
+
- Colour RAM does not scroll: four colours for the whole playfield.
|
|
263
|
+
- NTSC runs the same per-frame steps at 60 Hz, so the game and the tune
|
|
264
|
+
are 6/5 as fast there (c64-kb `pal_ntsc_tempo_mismatch`), and the tune's
|
|
265
|
+
pitches, tabled for the PAL clock, about 4% sharp (arithmetic).
|
|
266
|
+
- One effect at a time on voice 3; a new one cuts the last.
|
|
267
|
+
|
|
268
|
+
## Not established
|
|
269
|
+
|
|
270
|
+
- A real `$DC00` joystick: the normal game was played through `make joy`
|
|
271
|
+
(a RAM port byte), not through the CIA.
|
|
272
|
+
- Real hardware: everything was measured in VICE x64sc 3.10.
|
|
273
|
+
- The tune was never listened to; its note table is arithmetic.
|
|
274
|
+
- The tear check samples 32 moments of one run; it does not prove every
|
|
275
|
+
frame. The three-page rule (the scroll never writes the page shown) is
|
|
276
|
+
the design reason; the self-check compares every ready page with the
|
|
277
|
+
level, and row 20 of every page with the sky.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"checks": [
|
|
3
|
+
{ "name": "own verdict (border)", "type": "verdict" },
|
|
4
|
+
{ "name": "verdict line", "type": "text", "row": 21, "col": 0, "text": "RESULT 01 PASS" },
|
|
5
|
+
{ "name": "HUD: score, coins, lives (40 columns, XSCROLL 0 after the split)", "type": "text", "row": 22, "col": 0, "text": "SCORE 000150 COINS 05 LIVES 2" },
|
|
6
|
+
{ "name": "HUD: high score", "type": "text", "row": 23, "col": 0, "text": "HI 000000" },
|
|
7
|
+
{
|
|
8
|
+
"name": "player at the wall: x 716, feet on line 179 (sprite X 163, Y 157; stand art columns 3-13)",
|
|
9
|
+
"type": "sprite",
|
|
10
|
+
"colour": 1,
|
|
11
|
+
"vic_x": 166,
|
|
12
|
+
"line": 158,
|
|
13
|
+
"width": 11,
|
|
14
|
+
"height": 21
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"name": "hopper where the scripted run leaves it (pinned from the run; the program checks its own sprite registers)",
|
|
18
|
+
"type": "sprite",
|
|
19
|
+
"colour": 3,
|
|
20
|
+
"vic_x": 32,
|
|
21
|
+
"line": 167,
|
|
22
|
+
"width": 14,
|
|
23
|
+
"height": 12
|
|
24
|
+
},
|
|
25
|
+
{ "name": "scrolled playfield: brick tile 46 top row at camera 576 (VIC X 191, line 147)", "type": "rect", "colour": 7, "vic_x": 191, "line": 147, "width": 16, "height": 1 },
|
|
26
|
+
{ "name": "scrolled playfield: grass on tiles 43-44 (VIC X 143-174, lines 179-180)", "type": "rect", "colour": 5, "vic_x": 143, "line": 179, "width": 32, "height": 2 },
|
|
27
|
+
{ "name": "scrolled playfield: the pit at tiles 41-42 is sky (VIC X 111-142)", "type": "rect", "colour": 6, "vic_x": 111, "line": 179, "width": 32, "height": 16 },
|
|
28
|
+
{ "name": "row 20, between playfield and HUD, is blank", "type": "rect", "colour": 6, "vic_x": 31, "line": 211, "width": 304, "height": 8 },
|
|
29
|
+
{ "name": "display the same on both models", "type": "same", "cells": [0, 0, 23, 39] },
|
|
30
|
+
{ "name": "frame meter, the first 255 play frames", "type": "meter", "row": 24, "col": 20, "frames": 255 }
|
|
31
|
+
]
|
|
32
|
+
}
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
// actors.c: enemies placed in the level wake when they come within a
|
|
2
|
+
// window around the view, and go back to the level table when they leave
|
|
3
|
+
// it, so a patrol survives off screen and a stomped enemy stays dead
|
|
4
|
+
// (c64-kb actor_activation_window). The live ones sit in NSLOT slots, one
|
|
5
|
+
// sprite each (object_pool). Hits are tested box against box, each box
|
|
6
|
+
// from the animation frame on show (per_frame_hitbox).
|
|
7
|
+
#include "game.h"
|
|
8
|
+
|
|
9
|
+
#define MARGIN 4 // wake window: the view plus 4 columns each side
|
|
10
|
+
#define HYST 2 // live actors are kept 2 columns further out
|
|
11
|
+
#define SCAN_K 8 // level entries examined a frame, round robin
|
|
12
|
+
#define HOP_WAIT 70 // frames a hopper sits between hops
|
|
13
|
+
#define HOP_START 8 // vy_tab entry a hop starts from: a lower arc than a jump
|
|
14
|
+
#define ENEMY_H 15 // enemy feet to head
|
|
15
|
+
|
|
16
|
+
char lvl_count;
|
|
17
|
+
char lvl_col[NLVL], lvl_ty[NLVL], lvl_type[NLVL], lvl_flags[NLVL];
|
|
18
|
+
|
|
19
|
+
char slot_lvl[NSLOT];
|
|
20
|
+
unsigned slot_x[NSLOT], slot_y[NSLOT];
|
|
21
|
+
char slot_type[NSLOT], slot_jump[NSLOT], slot_timer[NSLOT];
|
|
22
|
+
static char slot_probe[NSLOT]; // the column ahead the walker last judged
|
|
23
|
+
static bool slot_turn[NSLOT]; // and whether it turns there
|
|
24
|
+
bool slot_left[NSLOT], slot_squashed[NSLOT];
|
|
25
|
+
struct Anim slot_anim[NSLOT];
|
|
26
|
+
|
|
27
|
+
static char scan_pos, win_lo, win_top, tick;
|
|
28
|
+
char drop_lo, drop_top; // this frame's drop window, in columns
|
|
29
|
+
|
|
30
|
+
void actors_reset(void)
|
|
31
|
+
{
|
|
32
|
+
for (char s = 0; s < NSLOT; s++)
|
|
33
|
+
slot_lvl[s] = NO_SLOT;
|
|
34
|
+
scan_pos = 0;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
static void activate(char i)
|
|
38
|
+
{
|
|
39
|
+
char s = 0;
|
|
40
|
+
while (slot_lvl[s] != NO_SLOT)
|
|
41
|
+
if (++s == NSLOT)
|
|
42
|
+
return; // every slot live: it wakes on a later scan
|
|
43
|
+
slot_lvl[s] = i;
|
|
44
|
+
slot_type[s] = lvl_type[i];
|
|
45
|
+
slot_x[s] = lvl_col[i] * 8 + 8;
|
|
46
|
+
slot_y[s] = (unsigned)((lvl_ty[i] + 1) * 16) << 8;
|
|
47
|
+
slot_jump[s] = JUMP_APEX; // it drops onto whatever is under it
|
|
48
|
+
slot_left[s] = lvl_flags[i] & LF_LEFT;
|
|
49
|
+
slot_timer[s] = HOP_WAIT / 2 + (i & 15);
|
|
50
|
+
slot_squashed[s] = false;
|
|
51
|
+
slot_probe[s] = 0xff;
|
|
52
|
+
slot_anim[s].seq = nullptr;
|
|
53
|
+
anim_set(&slot_anim[s], lvl_type[i] == T_WALKER ? an_walk : an_hop_sit);
|
|
54
|
+
lvl_flags[i] |= LF_LIVE;
|
|
55
|
+
events |= EV_WAKE;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Back to the table: where it is now, which way it faces, one tile row up
|
|
59
|
+
// so a wake drops it onto the surface again.
|
|
60
|
+
static void deactivate(char s)
|
|
61
|
+
{
|
|
62
|
+
char i = slot_lvl[s];
|
|
63
|
+
lvl_col[i] = (slot_x[s] - 8) >> 3;
|
|
64
|
+
lvl_ty[i] = (char)((slot_y[s] >> 8) >> 4) - 1;
|
|
65
|
+
lvl_flags[i] = (lvl_flags[i] & ~(LF_LIVE | LF_LEFT)) | (slot_left[s] ? LF_LEFT : 0);
|
|
66
|
+
slot_lvl[s] = NO_SLOT;
|
|
67
|
+
events |= EV_SLEEP;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
static void kill(char s)
|
|
71
|
+
{
|
|
72
|
+
char i = slot_lvl[s];
|
|
73
|
+
lvl_flags[i] = (lvl_flags[i] & ~LF_LIVE) | LF_DEAD;
|
|
74
|
+
slot_lvl[s] = NO_SLOT;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Both windows in columns, clamped to the level, so every compare is a byte.
|
|
78
|
+
static void set_window(void)
|
|
79
|
+
{
|
|
80
|
+
int cc = camx >> 3;
|
|
81
|
+
int lo = cc - MARGIN, hi = cc + 40 + MARGIN;
|
|
82
|
+
win_lo = lo < 0 ? 0 : lo;
|
|
83
|
+
win_top = hi > 255 ? 255 : hi;
|
|
84
|
+
drop_lo = lo - HYST < 0 ? 0 : lo - HYST;
|
|
85
|
+
drop_top = hi + HYST > 255 ? 255 : hi + HYST;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Half a pixel a frame; odd and even slots take turns, so a crowd costs
|
|
89
|
+
// half as much on any one frame. The column WALK_AHEAD pixels in front is
|
|
90
|
+
// judged once, when the walker first reaches it: an edge, a step too high
|
|
91
|
+
// or low, or a wall there turns the walker. Each step then costs one
|
|
92
|
+
// surface_walk for the ground snap (about 300 cycles by the meter's PROF
|
|
93
|
+
// runs, against about 1,100 when every step also probed walls and the
|
|
94
|
+
// ground ahead; README, "Enemies on screen").
|
|
95
|
+
#define WALK_AHEAD 6
|
|
96
|
+
|
|
97
|
+
static void walker(char s)
|
|
98
|
+
{
|
|
99
|
+
if ((tick ^ s) & 1)
|
|
100
|
+
return;
|
|
101
|
+
signed char dx = slot_left[s] ? -1 : 1;
|
|
102
|
+
char fy = slot_y[s] >> 8;
|
|
103
|
+
unsigned nx = slot_x[s] + dx;
|
|
104
|
+
unsigned probe = nx + dx * WALK_AHEAD;
|
|
105
|
+
char pc = probe >> 3;
|
|
106
|
+
if (pc != slot_probe[s])
|
|
107
|
+
{
|
|
108
|
+
slot_probe[s] = pc;
|
|
109
|
+
char ahead = surface_walk(probe, fy);
|
|
110
|
+
slot_turn[s] = ahead == 0xff || (ahead > fy && ahead - fy > MAX_SNAP) ||
|
|
111
|
+
(ahead < fy && fy - ahead > MAX_RISE) || wall_at(probe, fy, ENEMY_H);
|
|
112
|
+
}
|
|
113
|
+
if (slot_turn[s])
|
|
114
|
+
{
|
|
115
|
+
slot_left[s] = !slot_left[s];
|
|
116
|
+
slot_probe[s] = 0xff; // judge the other way afresh
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
char sy = surface_walk(nx, fy);
|
|
120
|
+
slot_x[s] = nx;
|
|
121
|
+
if (sy != 0xff)
|
|
122
|
+
slot_y[s] = (unsigned)sy << 8;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
static void hopper(char s)
|
|
126
|
+
{
|
|
127
|
+
slot_left[s] = px < slot_x[s]; // it watches the player
|
|
128
|
+
if (--slot_timer[s] == 0)
|
|
129
|
+
{
|
|
130
|
+
slot_timer[s] = HOP_WAIT;
|
|
131
|
+
slot_jump[s] = HOP_START;
|
|
132
|
+
anim_set(&slot_anim[s], an_hop_up);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
void actors_update(void)
|
|
137
|
+
{
|
|
138
|
+
tick++;
|
|
139
|
+
set_window();
|
|
140
|
+
char i = scan_pos;
|
|
141
|
+
for (char k = 0; k < SCAN_K; k++)
|
|
142
|
+
{
|
|
143
|
+
if (i < lvl_count && !(lvl_flags[i] & (LF_LIVE | LF_DEAD)))
|
|
144
|
+
{
|
|
145
|
+
char c = lvl_col[i];
|
|
146
|
+
if (c >= win_lo && c <= win_top)
|
|
147
|
+
activate(i);
|
|
148
|
+
}
|
|
149
|
+
i = (i + 1) & (NLVL - 1);
|
|
150
|
+
}
|
|
151
|
+
scan_pos = i;
|
|
152
|
+
|
|
153
|
+
for (char s = 0; s < NSLOT; s++)
|
|
154
|
+
{
|
|
155
|
+
if (slot_lvl[s] == NO_SLOT)
|
|
156
|
+
continue;
|
|
157
|
+
struct Anim *a = &slot_anim[s];
|
|
158
|
+
anim_step(a);
|
|
159
|
+
if (slot_squashed[s])
|
|
160
|
+
{
|
|
161
|
+
if (anim_done(a))
|
|
162
|
+
slot_lvl[s] = NO_SLOT; // already dead in the table
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
if (slot_jump[s] != 0xff)
|
|
166
|
+
{
|
|
167
|
+
if (air_step(slot_x[s], &slot_y[s], &slot_jump[s], ENEMY_H, false))
|
|
168
|
+
{
|
|
169
|
+
slot_jump[s] = 0xff;
|
|
170
|
+
if (slot_type[s] == T_HOPPER)
|
|
171
|
+
anim_set(a, an_hop_sit);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
else if (slot_type[s] == T_WALKER)
|
|
175
|
+
walker(s);
|
|
176
|
+
else
|
|
177
|
+
hopper(s);
|
|
178
|
+
|
|
179
|
+
char fy = slot_y[s] >> 8;
|
|
180
|
+
char c = slot_x[s] >> 3;
|
|
181
|
+
if (fy > 200 && fy < 240)
|
|
182
|
+
kill(s); // fell into a pit
|
|
183
|
+
else if (c < drop_lo || c > drop_top)
|
|
184
|
+
deactivate(s);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
bool enemy_near(unsigned x, char dist)
|
|
189
|
+
{
|
|
190
|
+
for (char s = 0; s < NSLOT; s++)
|
|
191
|
+
{
|
|
192
|
+
if (slot_lvl[s] != NO_SLOT && !slot_squashed[s])
|
|
193
|
+
{
|
|
194
|
+
unsigned e = slot_x[s];
|
|
195
|
+
if ((e > x ? e - x : x - e) < dist)
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return false;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// ---- hits: boxes per animation frame, emitted where the sprites are ----
|
|
203
|
+
// Coordinates are bytes relative to the player's foot, placed at (BOX_O,
|
|
204
|
+
// BOX_O); an enemy is listed only within NEAR pixels each way, so every
|
|
205
|
+
// compare in the pass is one byte (16-bit world X is taken apart once per
|
|
206
|
+
// enemy, never per box pair). After c64-kb per_frame_hitbox.
|
|
207
|
+
#define BOX_O 64
|
|
208
|
+
#define NEAR 40
|
|
209
|
+
#define MAXB (2 + NSLOT)
|
|
210
|
+
static char nbox;
|
|
211
|
+
static char bl[MAXB], br[MAXB], bt[MAXB], bb[MAXB], bg[MAXB], bm[MAXB], bo[MAXB];
|
|
212
|
+
|
|
213
|
+
static void emit_boxes(char owner, char shape, char left, char top)
|
|
214
|
+
{
|
|
215
|
+
char k = hb_first[shape], e = k + hb_count[shape], i = nbox;
|
|
216
|
+
for (; k != e; k++, i++)
|
|
217
|
+
{
|
|
218
|
+
const struct HBox *h = &hbox[k];
|
|
219
|
+
bl[i] = left + h->x0;
|
|
220
|
+
br[i] = left + h->x1;
|
|
221
|
+
bt[i] = top + h->y0;
|
|
222
|
+
bb[i] = top + h->y1;
|
|
223
|
+
bg[i] = h->group;
|
|
224
|
+
bm[i] = h->mask;
|
|
225
|
+
bo[i] = owner; // 0 the player, 1 + slot an enemy
|
|
226
|
+
}
|
|
227
|
+
nbox = i;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// The slots the feet hit and the slots the body hit, as bit masks.
|
|
231
|
+
char hit_stomp, hit_body;
|
|
232
|
+
|
|
233
|
+
static void collide(void)
|
|
234
|
+
{
|
|
235
|
+
hit_stomp = hit_body = 0;
|
|
236
|
+
for (char i = 0; i + 1 < nbox; i++)
|
|
237
|
+
{
|
|
238
|
+
char m = bm[i];
|
|
239
|
+
for (char j = i + 1; j < nbox; j++)
|
|
240
|
+
{
|
|
241
|
+
if (!(m & bg[j]))
|
|
242
|
+
continue; // a pair that cannot hurt each other
|
|
243
|
+
if (bl[i] <= br[j] && bl[j] <= br[i] && bt[i] <= bb[j] && bt[j] <= bb[i])
|
|
244
|
+
{
|
|
245
|
+
char p = bo[i] ? j : i, e = bo[i] ? bo[i] : bo[j];
|
|
246
|
+
char bit = 1 << (e - 1);
|
|
247
|
+
if (bg[p] == G_STOMP)
|
|
248
|
+
hit_stomp |= bit;
|
|
249
|
+
else
|
|
250
|
+
hit_body |= bit;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Any enemy the feet reach is stomped; a body touch by any other hurts.
|
|
257
|
+
void actors_collide(void)
|
|
258
|
+
{
|
|
259
|
+
if (pinvuln)
|
|
260
|
+
return;
|
|
261
|
+
nbox = 0;
|
|
262
|
+
char fy = py >> 8;
|
|
263
|
+
emit_boxes(0, panim.shape + (pleft && panim.shape < SH_MIRROR ? SH_MIRROR : 0), BOX_O - 8, BOX_O - 21);
|
|
264
|
+
for (char s = 0; s < NSLOT; s++)
|
|
265
|
+
{
|
|
266
|
+
if (slot_lvl[s] == NO_SLOT || slot_squashed[s])
|
|
267
|
+
continue;
|
|
268
|
+
int dx = (int)slot_x[s] - (int)px;
|
|
269
|
+
signed char dy = (char)(slot_y[s] >> 8) - fy;
|
|
270
|
+
if (dx > -NEAR && dx < NEAR && dy > -NEAR && dy < NEAR)
|
|
271
|
+
emit_boxes(1 + s, slot_anim[s].shape, (char)dx + (BOX_O - 8), (char)dy + (BOX_O - 16));
|
|
272
|
+
}
|
|
273
|
+
collide();
|
|
274
|
+
for (char s = 0; s < NSLOT; s++)
|
|
275
|
+
{
|
|
276
|
+
if (!(hit_stomp & (1 << s)))
|
|
277
|
+
continue;
|
|
278
|
+
slot_squashed[s] = true;
|
|
279
|
+
anim_set(&slot_anim[s], an_squash);
|
|
280
|
+
lvl_flags[slot_lvl[s]] = (lvl_flags[slot_lvl[s]] & ~LF_LIVE) | LF_DEAD;
|
|
281
|
+
pjump = JUMP_BOUNCE;
|
|
282
|
+
stomps++;
|
|
283
|
+
score_add(1, 0);
|
|
284
|
+
events |= EV_STOMP;
|
|
285
|
+
sfx_play(SFX_STOMP);
|
|
286
|
+
}
|
|
287
|
+
if (hit_body & ~hit_stomp)
|
|
288
|
+
player_hurt();
|
|
289
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// anim.c: sprite animation from tables (c64-kb sprite_animation_table).
|
|
2
|
+
// A sequence is (shape, frames) pairs ending in AN_LOOP n (go to pair n)
|
|
3
|
+
// or AN_HOLD (stay on the last pair). Facing is not in the tables: the
|
|
4
|
+
// player adds SH_MIRROR to the shape when it faces left.
|
|
5
|
+
#include "game.h"
|
|
6
|
+
|
|
7
|
+
#define AN_LOOP 0xff
|
|
8
|
+
#define AN_HOLD 0xfe
|
|
9
|
+
|
|
10
|
+
const char an_stand[] = { SH_STAND, 1, AN_HOLD };
|
|
11
|
+
const char an_run[] = { SH_RUN1, 6, SH_STAND, 4, SH_RUN2, 6, SH_STAND, 4, AN_LOOP, 0 };
|
|
12
|
+
const char an_jump[] = { SH_JUMP, 1, AN_HOLD }; // rising
|
|
13
|
+
const char an_fall[] = { SH_FALL, 1, AN_HOLD }; // falling: the stomp box
|
|
14
|
+
const char an_hurt[] = { SH_HURT, 1, AN_HOLD };
|
|
15
|
+
const char an_walk[] = { SH_WALK1, 8, SH_WALK2, 8, AN_LOOP, 0 };
|
|
16
|
+
const char an_squash[] = { SH_SQUASH, 24, AN_HOLD };
|
|
17
|
+
const char an_hop_sit[] = { SH_HOP_SIT, 1, AN_HOLD };
|
|
18
|
+
const char an_hop_up[] = { SH_HOP_UP, 1, AN_HOLD };
|
|
19
|
+
|
|
20
|
+
void anim_set(struct Anim *a, const char *seq)
|
|
21
|
+
{
|
|
22
|
+
if (a->seq == seq)
|
|
23
|
+
return;
|
|
24
|
+
a->seq = seq;
|
|
25
|
+
a->pos = 0;
|
|
26
|
+
a->shape = seq[0];
|
|
27
|
+
a->count = seq[1];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
void anim_step(struct Anim *a)
|
|
31
|
+
{
|
|
32
|
+
if (a->count == 0 || --a->count)
|
|
33
|
+
return; // held (0), or the pair is not over
|
|
34
|
+
char p = a->pos + 2;
|
|
35
|
+
char op = a->seq[p];
|
|
36
|
+
if (op == AN_LOOP)
|
|
37
|
+
p = a->seq[p + 1] * 2;
|
|
38
|
+
else if (op == AN_HOLD)
|
|
39
|
+
{
|
|
40
|
+
a->count = 0; // stays on the last pair
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
a->pos = p;
|
|
44
|
+
a->shape = a->seq[p];
|
|
45
|
+
a->count = a->seq[p + 1];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
bool anim_done(struct Anim *a)
|
|
49
|
+
{
|
|
50
|
+
return a->count == 0;
|
|
51
|
+
}
|