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,793 @@
|
|
|
1
|
+
---
|
|
2
|
+
recipe: flip-screen-rooms
|
|
3
|
+
toolchain: oscar64
|
|
4
|
+
output_format: PRG
|
|
5
|
+
region: both
|
|
6
|
+
techniques: [flip_screen_rooms, tile_grid_collision, tile_map_render, object_pool]
|
|
7
|
+
file_formats: [PRG]
|
|
8
|
+
uses_registers: [D000, D001, D010, D011, D012, D015, D017, D01C, D01D, D020, D021, D027, DC00, DC04, DC05, DC06, DC07, DC0E, DC0F]
|
|
9
|
+
uses_kernal: []
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<!-- doc-type: recipe -->
|
|
13
|
+
|
|
14
|
+
# Oscar64 Flip-Screen Rooms: five rooms as records, a full redraw on every edge, timed
|
|
15
|
+
|
|
16
|
+
## Synopsis
|
|
17
|
+
|
|
18
|
+
A flip-screen world. Each room is one record: four edge exits (target
|
|
19
|
+
room, entry column, entry row, or none), a wall colour, an object count,
|
|
20
|
+
a run-length coded 40 x 22 tile stream in the format `tile-map-render.md`
|
|
21
|
+
and `level-rle-decoder.md` use, then the objects. Five rooms sit in a
|
|
22
|
+
2 x 2 block with one dead end off the top right. A one-sprite player
|
|
23
|
+
walks against the decoded tile map (`tile-grid-collision.md`) and, on the
|
|
24
|
+
move that would take it past an edge with an exit, the sprite is hidden,
|
|
25
|
+
the display is blanked, the next room's record is decoded and drawn in one
|
|
26
|
+
pass, and the sprite is placed on the entry cell. Nothing scrolls. The
|
|
27
|
+
redraw is timed with CIA1 timers A and B cascaded and the last and worst
|
|
28
|
+
cost in cycles sit on the HUD row. An autopilot walks a scripted path
|
|
29
|
+
through every room and back, taking three keys; the verdict compares the
|
|
30
|
+
final room, cell and key count with a prediction the host script made
|
|
31
|
+
from the same room data, and the worst redraw with a stated budget.
|
|
32
|
+
`$02FF` is `01` and the border green for pass, `02` and red for fail, in
|
|
33
|
+
the manner of `headless-verify.md`. The room format is this page's own;
|
|
34
|
+
it is not any shipped game's.
|
|
35
|
+
|
|
36
|
+
## Source
|
|
37
|
+
|
|
38
|
+
```c
|
|
39
|
+
// flip-screen-rooms.c
|
|
40
|
+
//
|
|
41
|
+
// A flip-screen world of five 40 x 22 rooms. Each room is one record:
|
|
42
|
+
// four edge exits, a wall colour, an object count, a run-length coded
|
|
43
|
+
// tile stream in the tile-map-render format, then the objects. Leaving
|
|
44
|
+
// an edge that has an exit redraws the whole screen from the next
|
|
45
|
+
// room's record; nothing scrolls. The redraw is timed with CIA1 timers
|
|
46
|
+
// A and B cascaded, the sprite is hidden and the display blanked (DEN
|
|
47
|
+
// off) while it runs, and the HUD on row 0 shows the room, the player's
|
|
48
|
+
// cell, the last and worst redraw in cycles, the keys taken and the
|
|
49
|
+
// verdict. An autopilot walks a scripted path through every room and
|
|
50
|
+
// back; the verdict compares the final room, cell and key count with
|
|
51
|
+
// the host's prediction and the worst redraw with BUDGET. RESULT at
|
|
52
|
+
// $02FF is 01 (green border) for pass, 02 (red) for fail.
|
|
53
|
+
//
|
|
54
|
+
// Room record:
|
|
55
|
+
// bytes 0..11 exits up, down, left, right: target room (0xff none),
|
|
56
|
+
// entry column, entry row
|
|
57
|
+
// byte 12 wall colour
|
|
58
|
+
// byte 13 object count n
|
|
59
|
+
// then 22 row streams: c & 0x80 run of (c & 0x7f), c < 0x80
|
|
60
|
+
// literal count, 0 end of row
|
|
61
|
+
// then n objects of 3 bytes: type, column, row
|
|
62
|
+
//
|
|
63
|
+
#include <c64/vic.h>
|
|
64
|
+
#include <c64/cia.h>
|
|
65
|
+
|
|
66
|
+
#define Screen ((char *)0x0400)
|
|
67
|
+
#define Color ((char *)0xd800)
|
|
68
|
+
#define SprData ((char *)0x0340)
|
|
69
|
+
#define SprPtr ((char *)0x07f8)
|
|
70
|
+
|
|
71
|
+
#define ROOM_W 40
|
|
72
|
+
#define ROOM_H 22
|
|
73
|
+
#define ROOM_SIZE (ROOM_W * ROOM_H)
|
|
74
|
+
#define MAP_ROW 1 // screen row the room starts on
|
|
75
|
+
#define MAX_OBJ 8
|
|
76
|
+
#define NONE 0xff
|
|
77
|
+
|
|
78
|
+
#define RESULT (*(volatile char *)0x02ff)
|
|
79
|
+
#define CODE_PASS 0x01
|
|
80
|
+
#define CODE_FAIL 0x02
|
|
81
|
+
|
|
82
|
+
#ifndef AUTOPILOT
|
|
83
|
+
#define AUTOPILOT 1
|
|
84
|
+
#endif
|
|
85
|
+
#ifndef BUDGET
|
|
86
|
+
#define BUDGET 58968UL // three PAL frames of 19,656 cycles
|
|
87
|
+
#endif
|
|
88
|
+
|
|
89
|
+
enum { DIR_UP, DIR_DOWN, DIR_LEFT, DIR_RIGHT };
|
|
90
|
+
enum { T_FLOOR, T_WALL };
|
|
91
|
+
|
|
92
|
+
// --- world, emitted by rooms.py ------------------------------------
|
|
93
|
+
// room 0: 181 bytes (164 of tile stream)
|
|
94
|
+
const char room0[] = {
|
|
95
|
+
0xff, 0x00, 0x00, 0x02, 0x14, 0x00, 0xff, 0x00, 0x00, 0x01, 0x00, 0x0a, 0x0e, 0x01, 0xa8, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00,
|
|
96
|
+
0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6,
|
|
97
|
+
0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01,
|
|
98
|
+
0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa7, 0x00, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00,
|
|
99
|
+
0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x89, 0x00, 0x01, 0x01, 0x85,
|
|
100
|
+
0x00, 0x01, 0x01, 0x85, 0x00, 0x01, 0x01, 0x85, 0x00, 0x01, 0x01, 0x8a, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01,
|
|
101
|
+
0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00,
|
|
102
|
+
0x01, 0x01, 0x00, 0x94, 0x01, 0x01, 0x00, 0x93, 0x01, 0x00, 0x01, 0x05, 0x03,
|
|
103
|
+
};
|
|
104
|
+
// room 1: 166 bytes (149 of tile stream)
|
|
105
|
+
const char room1[] = {
|
|
106
|
+
0xff, 0x00, 0x00, 0x03, 0x26, 0x00, 0x00, 0x27, 0x0a, 0x04, 0x00, 0x05, 0x0d, 0x01, 0xa8, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00,
|
|
107
|
+
0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa7,
|
|
108
|
+
0x00, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01,
|
|
109
|
+
0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0xa7, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01,
|
|
110
|
+
0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x83, 0x00, 0xa0, 0x01, 0x83, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01,
|
|
111
|
+
0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01,
|
|
112
|
+
0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0xa6, 0x01, 0x02, 0x00, 0x01, 0x00, 0x01, 0x1e, 0x0c,
|
|
113
|
+
};
|
|
114
|
+
// room 2: 205 bytes (188 of tile stream)
|
|
115
|
+
const char room2[] = {
|
|
116
|
+
0x00, 0x14, 0x15, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x03, 0x00, 0x14, 0x0a, 0x01, 0x94, 0x01, 0x01, 0x00, 0x93, 0x01, 0x00, 0x01, 0x01, 0xa6,
|
|
117
|
+
0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01,
|
|
118
|
+
0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01,
|
|
119
|
+
0x9d, 0x00, 0x01, 0x01, 0x88, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x9d, 0x00, 0x01, 0x01, 0x88, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x9d, 0x00,
|
|
120
|
+
0x01, 0x01, 0x88, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x9d, 0x00, 0x01, 0x01, 0x88, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x9d, 0x00, 0x01, 0x01,
|
|
121
|
+
0x88, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x9d, 0x00, 0x01, 0x01, 0x88, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x9d, 0x00, 0x01, 0x01, 0x88, 0x00,
|
|
122
|
+
0x01, 0x01, 0x00, 0x01, 0x01, 0x9d, 0x00, 0x01, 0x01, 0x88, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x9d, 0x00, 0x01, 0x01, 0x88, 0x00, 0x01, 0x01,
|
|
123
|
+
0x00, 0x01, 0x01, 0x9d, 0x00, 0x01, 0x01, 0x88, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01,
|
|
124
|
+
0x01, 0x00, 0x01, 0x01, 0xa7, 0x00, 0x00, 0xa8, 0x01, 0x00, 0x01, 0x14, 0x0f,
|
|
125
|
+
};
|
|
126
|
+
// room 3: 180 bytes (163 of tile stream)
|
|
127
|
+
const char room3[] = {
|
|
128
|
+
0x01, 0x26, 0x15, 0xff, 0x00, 0x00, 0x02, 0x27, 0x14, 0xff, 0x00, 0x00, 0x07, 0x01, 0xa6, 0x01, 0x02, 0x00, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00,
|
|
129
|
+
0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00,
|
|
130
|
+
0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x89,
|
|
131
|
+
0x00, 0x01, 0x01, 0x85, 0x00, 0x01, 0x01, 0x85, 0x00, 0x01, 0x01, 0x85, 0x00, 0x01, 0x01, 0x8a, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00,
|
|
132
|
+
0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00,
|
|
133
|
+
0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6,
|
|
134
|
+
0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01,
|
|
135
|
+
0x00, 0xa7, 0x00, 0x01, 0x01, 0x00, 0xa8, 0x01, 0x00, 0x01, 0x1e, 0x14,
|
|
136
|
+
};
|
|
137
|
+
// room 4: 201 bytes (184 of tile stream)
|
|
138
|
+
const char room4[] = {
|
|
139
|
+
0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x01, 0x27, 0x05, 0xff, 0x00, 0x00, 0x0c, 0x01, 0xa8, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00,
|
|
140
|
+
0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0xa7, 0x00, 0x01,
|
|
141
|
+
0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x8b, 0x00, 0x01, 0x01, 0x9a, 0x00,
|
|
142
|
+
0x01, 0x01, 0x00, 0x01, 0x01, 0x8b, 0x00, 0x01, 0x01, 0x9a, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x8b, 0x00, 0x01, 0x01, 0x9a, 0x00, 0x01, 0x01,
|
|
143
|
+
0x00, 0x01, 0x01, 0x8b, 0x00, 0x01, 0x01, 0x9a, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x8b, 0x00, 0x01, 0x01, 0x9a, 0x00, 0x01, 0x01, 0x00, 0x01,
|
|
144
|
+
0x01, 0x8b, 0x00, 0x01, 0x01, 0x9a, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x8b, 0x00, 0x01, 0x01, 0x9a, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x8b,
|
|
145
|
+
0x00, 0x01, 0x01, 0x9a, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x8b, 0x00, 0x01, 0x01, 0x9a, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x8b, 0x00, 0x01,
|
|
146
|
+
0x01, 0x9a, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00,
|
|
147
|
+
0x01, 0x01, 0x00, 0xa8, 0x01, 0x00, 0x01, 0x0a, 0x05,
|
|
148
|
+
};
|
|
149
|
+
// world: 933 bytes
|
|
150
|
+
const char * const rooms[5] = { room0, room1, room2, room3, room4 };
|
|
151
|
+
// script: direction, frames
|
|
152
|
+
const char script[] = {
|
|
153
|
+
3, 150,
|
|
154
|
+
3, 150,
|
|
155
|
+
0, 20,
|
|
156
|
+
3, 170,
|
|
157
|
+
2, 160,
|
|
158
|
+
2, 160,
|
|
159
|
+
1, 20,
|
|
160
|
+
2, 81,
|
|
161
|
+
1, 140,
|
|
162
|
+
3, 240,
|
|
163
|
+
0, 180,
|
|
164
|
+
2, 40,
|
|
165
|
+
};
|
|
166
|
+
// walk: 1511 frames
|
|
167
|
+
#define EXPECT_ROOM 1
|
|
168
|
+
#define EXPECT_COL 28
|
|
169
|
+
#define EXPECT_ROW 1
|
|
170
|
+
#define EXPECT_KEYS 3
|
|
171
|
+
|
|
172
|
+
// --- state ------------------------------------------------------------
|
|
173
|
+
char map[ROOM_SIZE]; // decoded tiles of the current room
|
|
174
|
+
char room; // current room index
|
|
175
|
+
int px, py; // player body top-left, room pixels (x reaches 312)
|
|
176
|
+
char room_bits[5]; // one bit per object per room: taken
|
|
177
|
+
|
|
178
|
+
// Object pool: parallel arrays, freed on every room change.
|
|
179
|
+
char obj_live[MAX_OBJ], obj_col[MAX_OBJ], obj_row[MAX_OBJ];
|
|
180
|
+
char obj_type[MAX_OBJ], obj_bit[MAX_OBJ];
|
|
181
|
+
|
|
182
|
+
unsigned long last_cost, worst_cost;
|
|
183
|
+
char keys;
|
|
184
|
+
|
|
185
|
+
void hud_cost(void);
|
|
186
|
+
|
|
187
|
+
const char glyph[2] = { 0x20, 0xa0 };
|
|
188
|
+
const char keyglyph = 0x2a;
|
|
189
|
+
|
|
190
|
+
// --- CIA1 timers A and B cascaded: B counts A underflows ----------------
|
|
191
|
+
static inline void timer_start(void)
|
|
192
|
+
{
|
|
193
|
+
cia1.cra = 0x00;
|
|
194
|
+
cia1.crb = 0x00;
|
|
195
|
+
cia1.ta = 0xffff;
|
|
196
|
+
cia1.tb = 0xffff;
|
|
197
|
+
cia1.crb = 0x51; // force load, start, count TA underflow
|
|
198
|
+
cia1.cra = 0x11; // force load, start, count phi2
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
static inline unsigned long timer_stop(void)
|
|
202
|
+
{
|
|
203
|
+
cia1.cra = 0x00;
|
|
204
|
+
cia1.crb = 0x00;
|
|
205
|
+
unsigned lo = 0xffff - cia1.ta;
|
|
206
|
+
unsigned hi = 0xffff - cia1.tb;
|
|
207
|
+
return ((unsigned long)hi << 16) | lo;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// --- text helpers -------------------------------------------------------
|
|
211
|
+
void put_str(char *p, const char *s)
|
|
212
|
+
{
|
|
213
|
+
while (*s)
|
|
214
|
+
*p++ = *s++;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// --- the record: decode and draw in one pass -------------------------
|
|
218
|
+
// Expands the 22 row streams at src into map and, as each byte lands,
|
|
219
|
+
// writes its glyph and colour to the screen. Pointers step by one row
|
|
220
|
+
// and a char index walks the row, which is the 6502's (zp),y shape.
|
|
221
|
+
// Returns the byte after the stream.
|
|
222
|
+
const char *rle_room(const char *src, char colour)
|
|
223
|
+
{
|
|
224
|
+
char *m = map;
|
|
225
|
+
char *s = Screen + MAP_ROW * 40;
|
|
226
|
+
char *c = Color + MAP_ROW * 40;
|
|
227
|
+
for (char y = 0; y < ROOM_H; y++) {
|
|
228
|
+
char x = 0;
|
|
229
|
+
for (;;) {
|
|
230
|
+
char ctl = *src++;
|
|
231
|
+
if (ctl == 0)
|
|
232
|
+
break;
|
|
233
|
+
if (ctl & 0x80) {
|
|
234
|
+
char v = *src++;
|
|
235
|
+
char g = glyph[v], k = v ? colour : 11;
|
|
236
|
+
ctl &= 0x7f;
|
|
237
|
+
do {
|
|
238
|
+
m[x] = v; s[x] = g; c[x] = k; x++;
|
|
239
|
+
} while (--ctl);
|
|
240
|
+
} else {
|
|
241
|
+
do {
|
|
242
|
+
char v = *src++;
|
|
243
|
+
m[x] = v; s[x] = glyph[v]; c[x] = v ? colour : 11; x++;
|
|
244
|
+
} while (--ctl);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
m += ROOM_W; s += 40; c += 40;
|
|
248
|
+
}
|
|
249
|
+
return src;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
void load_objects(const char *src, char count)
|
|
253
|
+
{
|
|
254
|
+
for (char i = 0; i < MAX_OBJ; i++)
|
|
255
|
+
obj_live[i] = 0;
|
|
256
|
+
for (char i = 0; i < count && i < MAX_OBJ; i++) {
|
|
257
|
+
char t = src[0], col = src[1], row = src[2];
|
|
258
|
+
src += 3;
|
|
259
|
+
if (room_bits[room] & (1 << i))
|
|
260
|
+
continue; // taken on an earlier visit
|
|
261
|
+
obj_live[i] = 1;
|
|
262
|
+
obj_type[i] = t;
|
|
263
|
+
obj_col[i] = col;
|
|
264
|
+
obj_row[i] = row;
|
|
265
|
+
obj_bit[i] = 1 << i;
|
|
266
|
+
unsigned at = (MAP_ROW + row) * 40 + col;
|
|
267
|
+
Screen[at] = keyglyph;
|
|
268
|
+
Color[at] = 7;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Full redraw from the record of room r. Called at raster 251 with the
|
|
273
|
+
// sprite already hidden and DEN already off, so the frame that follows
|
|
274
|
+
// is blank and no half-drawn frame shows.
|
|
275
|
+
void enter_room(char r)
|
|
276
|
+
{
|
|
277
|
+
room = r;
|
|
278
|
+
const char *rec = rooms[r];
|
|
279
|
+
timer_start();
|
|
280
|
+
const char *p = rle_room(rec + 14, rec[12]);
|
|
281
|
+
load_objects(p, rec[13]);
|
|
282
|
+
last_cost = timer_stop();
|
|
283
|
+
if (last_cost > worst_cost)
|
|
284
|
+
worst_cost = last_cost;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// --- collision against the decoded map --------------------------------
|
|
288
|
+
// Body is the 8 x 8 block at sprite columns 8..15, rows 0..7. A point
|
|
289
|
+
// outside the room is solid; the edge test in move() runs first.
|
|
290
|
+
static inline char solid(int x, int y)
|
|
291
|
+
{
|
|
292
|
+
if (x < 0 || y < 0 || x >= ROOM_W * 8 || y >= ROOM_H * 8)
|
|
293
|
+
return 1;
|
|
294
|
+
return map[(y >> 3) * ROOM_W + (x >> 3)] == T_WALL;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// The edge triggers on the attempted move, not on the cell the player
|
|
298
|
+
// stands in, so the entry cell on the far side never fires it again.
|
|
299
|
+
char try_exit(char dir)
|
|
300
|
+
{
|
|
301
|
+
const char *e = rooms[room] + dir * 3;
|
|
302
|
+
if (e[0] == NONE)
|
|
303
|
+
return 0;
|
|
304
|
+
char target = e[0];
|
|
305
|
+
px = e[1] * 8;
|
|
306
|
+
py = e[2] * 8;
|
|
307
|
+
vic.spr_enable = 0;
|
|
308
|
+
vic.ctrl1 &= 0xef; // DEN off: next frame is blank
|
|
309
|
+
enter_room(target);
|
|
310
|
+
vic.ctrl1 |= 0x10; // DEN on before the untimed HUD work
|
|
311
|
+
hud_cost();
|
|
312
|
+
return 1;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
void move(char dir)
|
|
316
|
+
{
|
|
317
|
+
int nx = px, ny = py;
|
|
318
|
+
switch (dir) {
|
|
319
|
+
case DIR_UP: ny -= 2; break;
|
|
320
|
+
case DIR_DOWN: ny += 2; break;
|
|
321
|
+
case DIR_LEFT: nx -= 2; break;
|
|
322
|
+
case DIR_RIGHT: nx += 2; break;
|
|
323
|
+
}
|
|
324
|
+
if (nx < 0 || nx > (ROOM_W - 1) * 8 || ny < 0 || ny > (ROOM_H - 1) * 8) {
|
|
325
|
+
try_exit(dir);
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
// Leading edge, two corners: an 8-pixel edge needs no more.
|
|
329
|
+
char hit;
|
|
330
|
+
switch (dir) {
|
|
331
|
+
case DIR_UP: hit = solid(nx, ny) | solid(nx + 7, ny); break;
|
|
332
|
+
case DIR_DOWN: hit = solid(nx, ny + 7) | solid(nx + 7, ny + 7); break;
|
|
333
|
+
case DIR_LEFT: hit = solid(nx, ny) | solid(nx, ny + 7); break;
|
|
334
|
+
default: hit = solid(nx + 7, ny) | solid(nx + 7, ny + 7); break;
|
|
335
|
+
}
|
|
336
|
+
if (!hit) {
|
|
337
|
+
px = nx;
|
|
338
|
+
py = ny;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
void pick_up(void)
|
|
343
|
+
{
|
|
344
|
+
char col = (char)(px >> 3), row = (char)(py >> 3);
|
|
345
|
+
for (char i = 0; i < MAX_OBJ; i++) {
|
|
346
|
+
if (obj_live[i] && obj_col[i] == col && obj_row[i] == row) {
|
|
347
|
+
obj_live[i] = 0;
|
|
348
|
+
room_bits[room] |= obj_bit[i];
|
|
349
|
+
Screen[(MAP_ROW + row) * 40 + col] = 0x20;
|
|
350
|
+
keys++;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// --- HUD ------------------------------------------------------------
|
|
356
|
+
// Row 0: R room C col,row L last redraw W worst redraw K keys V code.
|
|
357
|
+
// The two 32-bit fields are written only after a transition; a 32-bit
|
|
358
|
+
// decimal conversion every frame cost more than the frame.
|
|
359
|
+
void put_long(char *p, unsigned long v, char digits)
|
|
360
|
+
{
|
|
361
|
+
for (char i = digits; i > 0; i--) {
|
|
362
|
+
p[i - 1] = 0x30 + (char)(v % 10);
|
|
363
|
+
v /= 10;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
void hud_cost(void)
|
|
368
|
+
{
|
|
369
|
+
put_long(Screen + 11, last_cost, 5);
|
|
370
|
+
put_long(Screen + 18, worst_cost, 5);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
void hud(char code)
|
|
374
|
+
{
|
|
375
|
+
char *p = Screen;
|
|
376
|
+
p[1] = 0x30 + room;
|
|
377
|
+
char col = (char)(px >> 3), row = (char)(py >> 3);
|
|
378
|
+
p[4] = 0x30 + col / 10; p[5] = 0x30 + col % 10;
|
|
379
|
+
p[7] = 0x30 + row / 10; p[8] = 0x30 + row % 10;
|
|
380
|
+
p[25] = 0x30 + keys;
|
|
381
|
+
p[28] = 0x30 + code / 10; p[29] = 0x30 + code % 10;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// --- sprite ------------------------------------------------------------
|
|
385
|
+
void sprite_init(void)
|
|
386
|
+
{
|
|
387
|
+
for (char i = 0; i < 63; i++)
|
|
388
|
+
SprData[i] = 0;
|
|
389
|
+
for (char i = 0; i < 8; i++)
|
|
390
|
+
SprData[i * 3 + 1] = 0xff;
|
|
391
|
+
SprPtr[0] = 0x0340 / 64;
|
|
392
|
+
vic.spr_color[0] = 1;
|
|
393
|
+
vic.spr_multi = 0;
|
|
394
|
+
vic.spr_expand_x = 0;
|
|
395
|
+
vic.spr_expand_y = 0;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
void sprite_place(void)
|
|
399
|
+
{
|
|
400
|
+
// Body columns 8..15 sit on the cell: sprite X = 24 + px - 8.
|
|
401
|
+
vic_sprxy(0, 16 + px, 50 + MAP_ROW * 8 + py);
|
|
402
|
+
vic.spr_enable = 1;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
static inline void wait_bottom(void)
|
|
406
|
+
{
|
|
407
|
+
while (vic.raster != 251)
|
|
408
|
+
;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// --- main ----------------------------------------------------------------
|
|
412
|
+
int main(void)
|
|
413
|
+
{
|
|
414
|
+
__asm { sei }
|
|
415
|
+
vic.color_border = 0;
|
|
416
|
+
vic.color_back = 0;
|
|
417
|
+
for (unsigned i = 0; i < 1000; i++) {
|
|
418
|
+
Screen[i] = 0x20;
|
|
419
|
+
Color[i] = 1;
|
|
420
|
+
}
|
|
421
|
+
sprite_init();
|
|
422
|
+
put_str(Screen, s"r c , l w k v ");
|
|
423
|
+
px = 5 * 8;
|
|
424
|
+
py = 10 * 8;
|
|
425
|
+
vic.ctrl1 &= 0xef;
|
|
426
|
+
vic_waitFrame();
|
|
427
|
+
vic_waitFrame();
|
|
428
|
+
enter_room(0);
|
|
429
|
+
worst_cost = 0; // the first draw is not a transition
|
|
430
|
+
hud_cost();
|
|
431
|
+
sprite_place();
|
|
432
|
+
vic.ctrl1 |= 0x10;
|
|
433
|
+
|
|
434
|
+
char code = 0;
|
|
435
|
+
#if AUTOPILOT
|
|
436
|
+
char step = 0;
|
|
437
|
+
char left = script[1];
|
|
438
|
+
#endif
|
|
439
|
+
for (;;) {
|
|
440
|
+
wait_bottom();
|
|
441
|
+
sprite_place();
|
|
442
|
+
hud(code);
|
|
443
|
+
#if AUTOPILOT
|
|
444
|
+
if (step < sizeof(script)) {
|
|
445
|
+
move(script[step]);
|
|
446
|
+
if (--left == 0) {
|
|
447
|
+
step += 2;
|
|
448
|
+
if (step < sizeof(script))
|
|
449
|
+
left = script[step + 1];
|
|
450
|
+
}
|
|
451
|
+
} else if (code == 0) {
|
|
452
|
+
code = CODE_PASS;
|
|
453
|
+
if (room != EXPECT_ROOM || (px >> 3) != EXPECT_COL ||
|
|
454
|
+
(py >> 3) != EXPECT_ROW || keys != EXPECT_KEYS ||
|
|
455
|
+
worst_cost > BUDGET)
|
|
456
|
+
code = CODE_FAIL;
|
|
457
|
+
RESULT = code;
|
|
458
|
+
vic.color_border = (code == CODE_PASS) ? 5 : 2;
|
|
459
|
+
}
|
|
460
|
+
#else
|
|
461
|
+
char j = ~cia1.pra;
|
|
462
|
+
if (j & 1) move(DIR_UP);
|
|
463
|
+
else if (j & 2) move(DIR_DOWN);
|
|
464
|
+
else if (j & 4) move(DIR_LEFT);
|
|
465
|
+
else if (j & 8) move(DIR_RIGHT);
|
|
466
|
+
#endif
|
|
467
|
+
pick_up();
|
|
468
|
+
}
|
|
469
|
+
return 0;
|
|
470
|
+
}
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
## Build
|
|
474
|
+
|
|
475
|
+
```bash
|
|
476
|
+
python3 rooms.py > gen.h # the room arrays, the script and the EXPECT_* lines
|
|
477
|
+
oscar64 -tm=c64 -O2 -n -o=flip-screen-rooms.prg flip-screen-rooms.c
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
Produces `flip-screen-rooms.prg`, 3,665 bytes (Oscar64 build 2026-05-19),
|
|
481
|
+
plus `flip-screen-rooms.map`, which puts `rle_room` at 224 bytes of code
|
|
482
|
+
(`0b00 - 0be0`). The listing above is the generator's output pasted in;
|
|
483
|
+
`rooms.py` is the script below. Then run headless in VICE (PAL):
|
|
484
|
+
|
|
485
|
+
```bash
|
|
486
|
+
x64sc -default -warp +sound +autostart-delay-random -autostartprgmode 1 \
|
|
487
|
+
-limitcycles 34000000 -exitscreenshot flip-screen-rooms.png \
|
|
488
|
+
-autostart flip-screen-rooms.prg
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
Add `-model ntsc` for the NTSC picture. The walk is 1,511 frames; at
|
|
492
|
+
19,656 cycles a PAL frame that is 29.7 million cycles after the autostart,
|
|
493
|
+
and the limit leaves room for the transitions and the BASIC start.
|
|
494
|
+
|
|
495
|
+
`-dAUTOPILOT=0` builds the joystick version: port 2, four directions, the
|
|
496
|
+
same rooms, 3,482 bytes. It was built and not run here.
|
|
497
|
+
|
|
498
|
+
### The generator
|
|
499
|
+
|
|
500
|
+
`rooms.py` authors the five rooms as character grids, opens the exit gaps
|
|
501
|
+
in both rooms of each link, encodes each row with the three-byte run
|
|
502
|
+
threshold, and walks the script pixel by pixel with the same two-corner
|
|
503
|
+
probe the C code uses, so its `EXPECT_*` lines are a prediction and not a
|
|
504
|
+
reading. An earlier version walked cells and was one cell out on the leg
|
|
505
|
+
after an edge crossing: a crossing costs one frame, not the four a cell
|
|
506
|
+
takes at 2 px per frame.
|
|
507
|
+
|
|
508
|
+
```python
|
|
509
|
+
# rooms.py: authors five 40 x 22 rooms, run-length encodes them with the
|
|
510
|
+
# tile-map-render stream format, prints the C arrays, and predicts the
|
|
511
|
+
# autopilot's final state by walking the script at pixel level.
|
|
512
|
+
W, H = 40, 22
|
|
513
|
+
UP, DOWN, LEFT, RIGHT = 0, 1, 2, 3
|
|
514
|
+
NONE = 0xFF
|
|
515
|
+
|
|
516
|
+
def blank(colour):
|
|
517
|
+
g = [['#'] * W] + [['#'] + ['.'] * (W - 2) + ['#'] for _ in range(H - 2)] + [['#'] * W]
|
|
518
|
+
return g, colour
|
|
519
|
+
|
|
520
|
+
# World: 0 -- 1 -- 4 (dead end)
|
|
521
|
+
# | |
|
|
522
|
+
# 2 -- 3
|
|
523
|
+
rooms = [blank(c) for c in (14, 13, 10, 7, 12)] # wall colours per room
|
|
524
|
+
exits = [{} for _ in rooms]
|
|
525
|
+
|
|
526
|
+
def link(a, da, b, db, ca, ra, cb, rb):
|
|
527
|
+
"""Open a gap at (ca, ra) in room a and (cb, rb) in room b, and set
|
|
528
|
+
both exits. The entry cell is the gap cell on the far side."""
|
|
529
|
+
rooms[a][0][ra][ca] = '.'
|
|
530
|
+
rooms[b][0][rb][cb] = '.'
|
|
531
|
+
exits[a][da] = (b, cb, rb)
|
|
532
|
+
exits[b][db] = (a, ca, ra)
|
|
533
|
+
|
|
534
|
+
link(0, RIGHT, 1, LEFT, 39, 10, 0, 10)
|
|
535
|
+
link(1, RIGHT, 4, LEFT, 39, 5, 0, 5)
|
|
536
|
+
link(0, DOWN, 2, UP, 20, 21, 20, 0)
|
|
537
|
+
link(2, RIGHT, 3, LEFT, 39, 20, 0, 20)
|
|
538
|
+
link(3, UP, 1, DOWN, 38, 0, 38, 21)
|
|
539
|
+
|
|
540
|
+
# A few pillars so the rooms are not all one run; none on the script path.
|
|
541
|
+
for x in range(10, 30, 6):
|
|
542
|
+
rooms[0][0][15][x] = '#'
|
|
543
|
+
rooms[3][0][8][x] = '#'
|
|
544
|
+
for y in range(8, 18):
|
|
545
|
+
rooms[2][0][y][30] = '#'
|
|
546
|
+
rooms[4][0][y][12] = '#'
|
|
547
|
+
for x in range(4, 36):
|
|
548
|
+
rooms[1][0][14][x] = '#'
|
|
549
|
+
|
|
550
|
+
# Objects: type 1 = key. (room, col, row)
|
|
551
|
+
objects = {0: [(1, 5, 3)], 1: [(1, 30, 12)], 2: [(1, 20, 15)],
|
|
552
|
+
3: [(1, 30, 20)], 4: [(1, 10, 5)]}
|
|
553
|
+
|
|
554
|
+
def rle_row(row):
|
|
555
|
+
out, i = [], 0
|
|
556
|
+
while i < W:
|
|
557
|
+
j = i
|
|
558
|
+
while j < W and row[j] == row[i]:
|
|
559
|
+
j += 1
|
|
560
|
+
n = j - i
|
|
561
|
+
if n >= 3:
|
|
562
|
+
out += [0x80 | n, row[i]]
|
|
563
|
+
i = j
|
|
564
|
+
else:
|
|
565
|
+
k = i
|
|
566
|
+
while k < W:
|
|
567
|
+
m = k
|
|
568
|
+
while m < W and row[m] == row[k]:
|
|
569
|
+
m += 1
|
|
570
|
+
if m - k >= 3:
|
|
571
|
+
break
|
|
572
|
+
k = m
|
|
573
|
+
lit = row[i:k]
|
|
574
|
+
out += [len(lit)] + lit
|
|
575
|
+
i = k
|
|
576
|
+
return out + [0]
|
|
577
|
+
|
|
578
|
+
def encode(idx):
|
|
579
|
+
grid, colour = rooms[idx]
|
|
580
|
+
tiles = [[1 if ch == '#' else 0 for ch in row] for row in grid]
|
|
581
|
+
hdr = []
|
|
582
|
+
for d in (UP, DOWN, LEFT, RIGHT):
|
|
583
|
+
t = exits[idx].get(d)
|
|
584
|
+
hdr += list(t) if t else [NONE, 0, 0]
|
|
585
|
+
objs = objects[idx]
|
|
586
|
+
hdr += [colour, len(objs)]
|
|
587
|
+
body = []
|
|
588
|
+
for row in tiles:
|
|
589
|
+
body += rle_row(row)
|
|
590
|
+
tail = [b for o in objs for b in o]
|
|
591
|
+
return hdr + body + tail, len(body)
|
|
592
|
+
|
|
593
|
+
# Autopilot script: (direction, frames), 2 px per frame, one entry at most
|
|
594
|
+
# 255 frames. An edge crossing costs one frame, so the predictor walks
|
|
595
|
+
# pixels, not cells, with the same two-corner probe the C code uses.
|
|
596
|
+
script = [(RIGHT, 150), (RIGHT, 150), (UP, 20), (RIGHT, 170), (LEFT, 160),
|
|
597
|
+
(LEFT, 160), (DOWN, 20), (LEFT, 81), (DOWN, 140), (RIGHT, 240),
|
|
598
|
+
(UP, 180), (LEFT, 40)]
|
|
599
|
+
DX = {UP: 0, DOWN: 0, LEFT: -2, RIGHT: 2}
|
|
600
|
+
DY = {UP: -2, DOWN: 2, LEFT: 0, RIGHT: 0}
|
|
601
|
+
|
|
602
|
+
def wall(room, x, y):
|
|
603
|
+
if x < 0 or y < 0 or x >= W * 8 or y >= H * 8:
|
|
604
|
+
return True
|
|
605
|
+
return rooms[room][0][y >> 3][x >> 3] == '#'
|
|
606
|
+
|
|
607
|
+
def predict(room, col, row):
|
|
608
|
+
px, py, picked = col * 8, row * 8, set()
|
|
609
|
+
for d, frames in script:
|
|
610
|
+
for _ in range(frames):
|
|
611
|
+
nx, ny = px + DX[d], py + DY[d]
|
|
612
|
+
if nx < 0 or nx > (W - 1) * 8 or ny < 0 or ny > (H - 1) * 8:
|
|
613
|
+
t = exits[room].get(d)
|
|
614
|
+
if t:
|
|
615
|
+
room, px, py = t[0], t[1] * 8, t[2] * 8
|
|
616
|
+
else:
|
|
617
|
+
if d == UP: hit = wall(room, nx, ny) or wall(room, nx + 7, ny)
|
|
618
|
+
elif d == DOWN: hit = wall(room, nx, ny + 7) or wall(room, nx + 7, ny + 7)
|
|
619
|
+
elif d == LEFT: hit = wall(room, nx, ny) or wall(room, nx, ny + 7)
|
|
620
|
+
else: hit = wall(room, nx + 7, ny) or wall(room, nx + 7, ny + 7)
|
|
621
|
+
if not hit:
|
|
622
|
+
px, py = nx, ny
|
|
623
|
+
for o in objects[room]:
|
|
624
|
+
if (o[1], o[2]) == (px >> 3, py >> 3):
|
|
625
|
+
picked.add((room, o[1], o[2]))
|
|
626
|
+
return room, px >> 3, py >> 3, len(picked), sum(f for _, f in script)
|
|
627
|
+
|
|
628
|
+
if __name__ == '__main__':
|
|
629
|
+
total = 0
|
|
630
|
+
for i in range(len(rooms)):
|
|
631
|
+
data, body = encode(i)
|
|
632
|
+
total += len(data)
|
|
633
|
+
print('// room %d: %d bytes (%d of tile stream)' % (i, len(data), body))
|
|
634
|
+
print('const char room%d[] = {' % i)
|
|
635
|
+
for k in range(0, len(data), 24):
|
|
636
|
+
print(' ' + ', '.join('0x%02x' % b for b in data[k:k + 24]) + ',')
|
|
637
|
+
print('};')
|
|
638
|
+
print('// world: %d bytes' % total)
|
|
639
|
+
print('const char * const rooms[%d] = { %s };' %
|
|
640
|
+
(len(rooms), ', '.join('room%d' % i for i in range(len(rooms)))))
|
|
641
|
+
print('// script: direction, frames')
|
|
642
|
+
print('const char script[] = {')
|
|
643
|
+
for d, f in script:
|
|
644
|
+
print(' %d, %d,' % (d, f))
|
|
645
|
+
print('};')
|
|
646
|
+
r, c, y, k, frames = predict(0, 5, 10)
|
|
647
|
+
print('// walk: %d frames' % frames)
|
|
648
|
+
print('#define EXPECT_ROOM %d' % r)
|
|
649
|
+
print('#define EXPECT_COL %d' % c)
|
|
650
|
+
print('#define EXPECT_ROW %d' % y)
|
|
651
|
+
print('#define EXPECT_KEYS %d' % k)
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
## Expected output
|
|
655
|
+
|
|
656
|
+
Green border, black background. Row 0 reads, on both models:
|
|
657
|
+
|
|
658
|
+
```text
|
|
659
|
+
R1 C28,01 L40204 W42141 K3 V01
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
The fields are: room index, the player's cell (column, row), the last
|
|
663
|
+
redraw in cycles, the worst redraw in cycles, keys taken, verdict code.
|
|
664
|
+
Rows 1 to 22 are room 1: a light green frame with a gap in the left wall
|
|
665
|
+
at row 10, in the right wall at row 5 and in the bottom wall at column 38,
|
|
666
|
+
a bar of wall across row 14, the key at (30, 12) still in place because
|
|
667
|
+
the walk never crosses it, and the white 8 x 8 player at column 28 of
|
|
668
|
+
room row 1 (screen row 2). The picture is a room other than the first.
|
|
669
|
+
|
|
670
|
+
Measured on the committed PNGs with PIL (VICE x64sc 3.10, both models,
|
|
671
|
+
34,000,000 cycles): row 0 decoded cell by cell against
|
|
672
|
+
`chargen-901225-01.bin` gives the line above; the border pixel (2, 100)
|
|
673
|
+
is (98, 213, 50) on PAL and (114, 189, 103) on NTSC, colour 5 in each
|
|
674
|
+
palette of `runtime/vice-reference.md`; the 24 x 24 block around the
|
|
675
|
+
player's cell holds exactly 64 white pixels, all inside the 8 x 8 cell at
|
|
676
|
+
x 256 to 263; the key cell (30, 12) has 24 lit pixels. The pinned command
|
|
677
|
+
was run twice per model and the PNG bytes were identical each time.
|
|
678
|
+
|
|
679
|
+
The final state matches the generator's prediction (room 1, cell 28,1,
|
|
680
|
+
3 keys), and the worst redraw, 42,141 cycles, is under the 58,968-cycle
|
|
681
|
+
budget (`BUDGET`, three PAL frames). The worst is one of the seven
|
|
682
|
+
transitions the walk makes; the last, into room 1, cost 40,204. The
|
|
683
|
+
first draw of room 0 at start-up cost 40,941 and is excluded from the
|
|
684
|
+
worst by design, since it is not a transition.
|
|
685
|
+
|
|
686
|
+
The red case was seen twice while the listing was being built and is
|
|
687
|
+
recorded here as the shape of a failure: with the player's x held in a
|
|
688
|
+
`char` the position wrapped at column 32, no edge was ever reached, and
|
|
689
|
+
the verdict was `R0 C19,01 L40941 W00000 K0 V02` with a red border; with
|
|
690
|
+
the cell-level predictor the walk ended in room 0 at (28, 1) with one key
|
|
691
|
+
and the same red verdict. Neither picture is committed.
|
|
692
|
+
|
|
693
|
+
## Why this works
|
|
694
|
+
|
|
695
|
+
**The record.** Fourteen header bytes, then the tile stream, then the
|
|
696
|
+
objects. `rle_room` returns the byte after the last row's terminator, so
|
|
697
|
+
the object list needs no offset field and a room with more or fewer rows
|
|
698
|
+
of runs still finds its objects. The exits are three bytes per edge in
|
|
699
|
+
the order up, down, left, right, which is the order of the direction
|
|
700
|
+
enum, so `try_exit` indexes the header with `dir * 3` and nothing else.
|
|
701
|
+
|
|
702
|
+
**The edge rule.** The transition fires on the attempted move that would
|
|
703
|
+
take the body past the room's last cell, not on the cell the player
|
|
704
|
+
stands in. The entry cell is the gap cell on the far side of the next
|
|
705
|
+
room. A rule that fired on position would fire again on the first frame
|
|
706
|
+
in the new room and bounce the player back; this one fires only when the
|
|
707
|
+
player pushes at the edge again, which is the way back.
|
|
708
|
+
|
|
709
|
+
**The redraw and the frame it spans.** The frame loop waits for raster
|
|
710
|
+
251, so `move` and therefore `try_exit` run in the lower border. The
|
|
711
|
+
sprite is disabled and DEN is cleared before the first screen write. DEN
|
|
712
|
+
is sampled once per frame on line `$30`, so the frame that follows is
|
|
713
|
+
blank in the border colour and makes no badlines, and the writes that
|
|
714
|
+
land before that sample fall in the border. DEN is set again as soon as
|
|
715
|
+
`enter_room` returns and before the HUD's decimal conversions, so the
|
|
716
|
+
interval from DEN clear to DEN set is the timed redraw plus the few
|
|
717
|
+
cycles that start and stop the timers: 40,000 to 42,000 cycles, 2.1 PAL
|
|
718
|
+
frames or 2.5 NTSC frames. Arithmetic from the measured cycles, not
|
|
719
|
+
measured as a frame count: the screen is blank for two frames on PAL
|
|
720
|
+
(line `$30` falls at about 6,900, 26,500 and 46,200 cycles after raster
|
|
721
|
+
251, and the redraw ends before the third sample) and three on NTSC
|
|
722
|
+
(3,900, 21,000, 38,100 and 55,200). The order of the two writes matters.
|
|
723
|
+
An earlier build ran the HUD's two 32-bit conversions between the redraw
|
|
724
|
+
and the DEN set, and an instrumented copy with CIA2 timers cascaded
|
|
725
|
+
around the whole of `try_exit` measured that interval at 55,483 cycles
|
|
726
|
+
from DEN clear to DEN set on both models: three blank frames on PAL, and
|
|
727
|
+
three or four on NTSC, because the worst case passes the fourth sample
|
|
728
|
+
by about 300 cycles. The frame count is a property of the whole blanked
|
|
729
|
+
interval, not of the timed redraw alone. No frame is ever torn, because
|
|
730
|
+
no visible line is drawn while screen RAM is half-written. The other
|
|
731
|
+
policy, leaving DEN set and accepting the torn frames, was not run here.
|
|
732
|
+
|
|
733
|
+
**One pass, per row.** The first version decoded into `map` and then
|
|
734
|
+
copied 880 cells to the screen in a second loop indexed by a 16-bit
|
|
735
|
+
counter, and cost 99,262 cycles, five PAL frames. The decoder now writes
|
|
736
|
+
the tile, its glyph and its colour as each byte lands, with three
|
|
737
|
+
pointers stepped by one row and a `char` index along the row, which
|
|
738
|
+
Oscar64 compiles to indexed stores. That is 40,204 to 42,141 cycles for
|
|
739
|
+
a room of 149 to 188 stream bytes, or 46 to 48 cycles per cell. The
|
|
740
|
+
`level-rle-decoder.md` figures for the decode alone, 33,562 for its
|
|
741
|
+
platform room in C and 19,158 by hand, show where the next factor of two
|
|
742
|
+
is: a hand-written decoder that writes the three destinations from one
|
|
743
|
+
`(zp),y` triple.
|
|
744
|
+
|
|
745
|
+
**The HUD costs most of a frame.** The first build converted the two
|
|
746
|
+
32-bit cycle counts to decimal every frame and the walk crawled at about
|
|
747
|
+
two frames per step. The two five-digit conversions cost 13,311 cycles on
|
|
748
|
+
both models in the instrumented copy above, most of a PAL frame, on top
|
|
749
|
+
of the per-frame work and the wait for raster 251. The cost fields are
|
|
750
|
+
now written only after a transition, and after DEN is set, and the
|
|
751
|
+
per-frame HUD is `char` arithmetic.
|
|
752
|
+
|
|
753
|
+
**Objects.** Each room's list is loaded into an eight-slot pool on entry
|
|
754
|
+
and the pool is cleared first, so nothing carries over from the last
|
|
755
|
+
room. One bit per object per room in `room_bits` records what has been
|
|
756
|
+
taken, and `load_objects` skips those, so a key does not come back on a
|
|
757
|
+
second visit. The walk re-enters rooms 1 and 0 and the counts stay at
|
|
758
|
+
three.
|
|
759
|
+
|
|
760
|
+
**Collision.** The body is the 8 x 8 block at sprite columns 8 to 15,
|
|
761
|
+
rows 0 to 7, so `vic_sprxy` places the sprite at `16 + px`. The step is 2
|
|
762
|
+
px, under a tile, and the leading edge is probed at its two corners,
|
|
763
|
+
which is enough for an 8-pixel edge (`tile_grid_collision`, probe
|
|
764
|
+
spacing). A point outside the room is solid; the edge test in `move`
|
|
765
|
+
runs first, so an edge with an exit is passable and one without is a
|
|
766
|
+
wall.
|
|
767
|
+
|
|
768
|
+
## Verification
|
|
769
|
+
|
|
770
|
+
Three instruments, run against the committed PNGs (VICE x64sc 3.10,
|
|
771
|
+
Oscar64 build 2026-05-19).
|
|
772
|
+
|
|
773
|
+
**Text, sprite and border.** A script matched every cell of row 0
|
|
774
|
+
against the char ROM glyphs and read the border pixel at (2, 100) on both
|
|
775
|
+
pictures; it counted the white pixels in the 24 x 24 block around the
|
|
776
|
+
player's cell (64, all in one 8 x 8 cell) and the lit pixels in the key
|
|
777
|
+
cell (24). The figures are quoted above.
|
|
778
|
+
|
|
779
|
+
**Prediction.** `rooms.py` walked the script over the same room data
|
|
780
|
+
before the machine did and printed room 1, cell (28, 1), 3 keys. The
|
|
781
|
+
machine printed the same and set `V01`. Room, column, row and key count
|
|
782
|
+
are four independent bytes; a wrong exit table, a wrong entry cell, a
|
|
783
|
+
wrong probe or a missed pickup each moves at least one of them.
|
|
784
|
+
|
|
785
|
+
**Reproducibility.** The pinned command was run twice per model and the
|
|
786
|
+
PNG bytes were identical each time.
|
|
787
|
+
|
|
788
|
+
What this does not establish: the frame counts of the blank are
|
|
789
|
+
arithmetic on measured cycle intervals, not a raster measurement, and
|
|
790
|
+
the DEN-clear-to-DEN-set interval of the committed listing was not timed
|
|
791
|
+
separately, only the redraw inside it; the joystick build was compiled and
|
|
792
|
+
not run; the redraw cost of a room with a picture in it, or with a
|
|
793
|
+
metatile layer, is not measured here.
|