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,620 @@
|
|
|
1
|
+
---
|
|
2
|
+
recipe: level-rle-decoder
|
|
3
|
+
toolchain: oscar64
|
|
4
|
+
output_format: PRG
|
|
5
|
+
region: both
|
|
6
|
+
techniques: [tile_map_render]
|
|
7
|
+
file_formats: [PRG]
|
|
8
|
+
uses_registers: [D011, D020, D021, DC06, DC07, DC0F]
|
|
9
|
+
uses_kernal: []
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<!-- doc-type: recipe -->
|
|
13
|
+
|
|
14
|
+
# Oscar64 Level RLE Decoder: three rooms compressed on the host, decoded and measured on the machine
|
|
15
|
+
|
|
16
|
+
## Synopsis
|
|
17
|
+
|
|
18
|
+
Puts numbers on the claim that run-length coding is enough for a tile
|
|
19
|
+
level. Three 40 x 22 rooms are authored as tile arrays in a Python script
|
|
20
|
+
(a platform room, a maze, a sparse room), run-length encoded on the host
|
|
21
|
+
with the stream format of `tile-map-render.md` (run byte `0x80 | n`,
|
|
22
|
+
literal count, `0` at the end of each row), and compiled in as byte arrays.
|
|
23
|
+
On the machine each room is decoded into RAM twice, once by a C decoder
|
|
24
|
+
and once by the same decoder written by hand in `__asm`, and each decode
|
|
25
|
+
is checksummed against the value the host computed from the source arrays
|
|
26
|
+
and timed with CIA1 timer B. Rows 0 to 2 print one line per room: packed
|
|
27
|
+
bytes, ratio, C cycles, hand-written cycles, PASS or FAIL. Row 0 also
|
|
28
|
+
carries the verdict code, which is mirrored to `$02FF` and the border
|
|
29
|
+
colour in the manner of `headless-verify.md`. Rows 3 to 24 draw the
|
|
30
|
+
decoded platform room. The decoders' code sizes come from the `.map` file
|
|
31
|
+
Oscar64 writes next to the `.prg`. This is the decode half of the
|
|
32
|
+
`tile_map_render` technique in `docs/techniques/scroll.md`; the figures
|
|
33
|
+
replace the unmeasured ratio and decoder-size sentences that
|
|
34
|
+
`docs/game-design/game-design-patterns.md` used to carry.
|
|
35
|
+
|
|
36
|
+
## Source
|
|
37
|
+
|
|
38
|
+
```c
|
|
39
|
+
// level-rle-decoder.c
|
|
40
|
+
//
|
|
41
|
+
// Decodes three RLE-compressed 40 x 22 rooms into RAM, checksums each
|
|
42
|
+
// against a value computed on the host from the source tile arrays,
|
|
43
|
+
// and measures the decode cost with CIA1 timer B. Rows 0-2 print one
|
|
44
|
+
// line per room: packed bytes, ratio, cycles, PASS or FAIL. Row 0 also
|
|
45
|
+
// carries the overall RESULT code, which is mirrored to $02FF and the
|
|
46
|
+
// border colour. Rows 3-24 draw the decoded platform room.
|
|
47
|
+
//
|
|
48
|
+
// Stream format (the tile-map-render format): control byte c
|
|
49
|
+
// c & 0x80 : run, the next byte repeated (c & 0x7f) times
|
|
50
|
+
// c < 0x80 : c literal bytes follow
|
|
51
|
+
// 0x00 : end of row
|
|
52
|
+
// Each of the 22 rows is its own stream; a run never crosses a row.
|
|
53
|
+
//
|
|
54
|
+
#include <c64/vic.h>
|
|
55
|
+
#include <c64/cia.h>
|
|
56
|
+
|
|
57
|
+
#define Screen ((char *)0x0400)
|
|
58
|
+
#define Color ((char *)0xd800)
|
|
59
|
+
|
|
60
|
+
#define ROOM_W 40
|
|
61
|
+
#define ROOM_H 22
|
|
62
|
+
#define ROOM_SIZE (ROOM_W * ROOM_H)
|
|
63
|
+
|
|
64
|
+
#define RESULT (*(volatile char *)0x02ff)
|
|
65
|
+
#define CODE_PASS 0x01
|
|
66
|
+
#define CODE_FAIL 0x02
|
|
67
|
+
|
|
68
|
+
// --- compressed rooms, emitted by rle_rooms.py ------------------------
|
|
69
|
+
// platform: 880 bytes -> 213 bytes, ratio 4.13, checksum 0xce8a
|
|
70
|
+
const char rle_platform[] = {
|
|
71
|
+
0xa8, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x05, 0x01, 0x00, 0x00, 0x04, 0x04, 0xa2, 0x00, 0x01, 0x01, 0x00, 0x02, 0x01, 0x00,
|
|
72
|
+
0x86, 0x02, 0x9d, 0x00, 0x03, 0x06, 0x00, 0x01, 0x00, 0x01, 0x01, 0x9a, 0x00, 0x88, 0x02, 0x05, 0x00, 0x00, 0x05, 0x05, 0x01, 0x00, 0x01, 0x01,
|
|
73
|
+
0xa4, 0x00, 0x03, 0x05, 0x05, 0x01, 0x00, 0x01, 0x01, 0x8c, 0x00, 0x85, 0x02, 0x93, 0x00, 0x03, 0x05, 0x05, 0x01, 0x00, 0x01, 0x01, 0x9e, 0x00,
|
|
74
|
+
0x88, 0x05, 0x01, 0x01, 0x00, 0x01, 0x01, 0x85, 0x00, 0x88, 0x03, 0x99, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x05,
|
|
75
|
+
0x01, 0x00, 0x00, 0x05, 0x05, 0x8d, 0x00, 0x87, 0x02, 0x8e, 0x00, 0x01, 0x01, 0x00, 0x05, 0x01, 0x00, 0x00, 0x05, 0x05, 0xa2, 0x00, 0x01, 0x01,
|
|
76
|
+
0x00, 0x05, 0x01, 0x00, 0x00, 0x05, 0x05, 0x86, 0x00, 0x02, 0x04, 0x04, 0x9a, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x99, 0x02, 0x8d, 0x00, 0x01,
|
|
77
|
+
0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x9d, 0x00, 0x89, 0x02, 0x01, 0x01,
|
|
78
|
+
0x00, 0x01, 0x01, 0x8a, 0x00, 0x86, 0x02, 0x96, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x04, 0x01, 0x00, 0x04, 0x04,
|
|
79
|
+
0x92, 0x00, 0x8c, 0x03, 0x85, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x91, 0x02, 0x84, 0x00, 0x92, 0x01, 0x00, 0xa8, 0x01, 0x00,
|
|
80
|
+
};
|
|
81
|
+
// maze: 880 bytes -> 629 bytes, ratio 1.40, checksum 0xf439
|
|
82
|
+
const char rle_maze[] = {
|
|
83
|
+
0xa8, 0x01, 0x00, 0x01, 0x01, 0x83, 0x00, 0x01, 0x01, 0x87, 0x00, 0x01, 0x01, 0x85, 0x00, 0x01, 0x01, 0x85, 0x00, 0x01, 0x01, 0x83, 0x00, 0x01,
|
|
84
|
+
0x01, 0x8a, 0x00, 0x01, 0x01, 0x00, 0x06, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x85, 0x01, 0x03, 0x00, 0x01, 0x00, 0x83, 0x01, 0x03, 0x00, 0x01,
|
|
85
|
+
0x00, 0x83, 0x01, 0x07, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x88, 0x01, 0x02, 0x00, 0x01, 0x00, 0x03, 0x01, 0x00, 0x01, 0x83, 0x00, 0x01,
|
|
86
|
+
0x01, 0x83, 0x00, 0x01, 0x01, 0x83, 0x00, 0x01, 0x01, 0x83, 0x00, 0x01, 0x01, 0x83, 0x00, 0x01, 0x01, 0x83, 0x00, 0x05, 0x01, 0x00, 0x01, 0x00,
|
|
87
|
+
0x01, 0x86, 0x00, 0x03, 0x01, 0x00, 0x01, 0x00, 0x02, 0x01, 0x00, 0x85, 0x01, 0x03, 0x00, 0x01, 0x00, 0x85, 0x01, 0x01, 0x00, 0x85, 0x01, 0x01,
|
|
88
|
+
0x00, 0x85, 0x01, 0x05, 0x00, 0x01, 0x00, 0x01, 0x00, 0x84, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x87, 0x00, 0x01, 0x01, 0x87,
|
|
89
|
+
0x00, 0x01, 0x01, 0x89, 0x00, 0x01, 0x01, 0x83, 0x00, 0x01, 0x01, 0x84, 0x00, 0x01, 0x01, 0x83, 0x00, 0x01, 0x01, 0x00, 0x02, 0x01, 0x00, 0x89,
|
|
90
|
+
0x01, 0x01, 0x00, 0x83, 0x01, 0x03, 0x00, 0x01, 0x00, 0x87, 0x01, 0x01, 0x00, 0x85, 0x01, 0x04, 0x00, 0x01, 0x01, 0x00, 0x83, 0x01, 0x02, 0x00,
|
|
91
|
+
0x01, 0x00, 0x03, 0x01, 0x00, 0x01, 0x87, 0x00, 0x03, 0x01, 0x00, 0x01, 0x83, 0x00, 0x03, 0x01, 0x00, 0x01, 0x85, 0x00, 0x01, 0x01, 0x85, 0x00,
|
|
92
|
+
0x04, 0x01, 0x00, 0x00, 0x01, 0x83, 0x00, 0x03, 0x01, 0x00, 0x01, 0x00, 0x04, 0x01, 0x00, 0x01, 0x00, 0x85, 0x01, 0x05, 0x00, 0x01, 0x00, 0x01,
|
|
93
|
+
0x00, 0x83, 0x01, 0x03, 0x00, 0x01, 0x00, 0x83, 0x01, 0x01, 0x00, 0x85, 0x01, 0x04, 0x00, 0x01, 0x01, 0x00, 0x83, 0x01, 0x04, 0x00, 0x01, 0x00,
|
|
94
|
+
0x01, 0x00, 0x01, 0x01, 0x83, 0x00, 0x01, 0x01, 0x83, 0x00, 0x01, 0x01, 0x83, 0x00, 0x03, 0x01, 0x00, 0x01, 0x83, 0x00, 0x01, 0x01, 0x83, 0x00,
|
|
95
|
+
0x01, 0x01, 0x85, 0x00, 0x01, 0x01, 0x84, 0x00, 0x01, 0x01, 0x83, 0x00, 0x03, 0x01, 0x00, 0x01, 0x00, 0x83, 0x01, 0x05, 0x00, 0x01, 0x00, 0x01,
|
|
96
|
+
0x00, 0x85, 0x01, 0x03, 0x00, 0x01, 0x00, 0x85, 0x01, 0x01, 0x00, 0x85, 0x01, 0x01, 0x00, 0x86, 0x01, 0x06, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
|
|
97
|
+
0x00, 0x01, 0x01, 0x83, 0x00, 0x03, 0x01, 0x00, 0x01, 0x87, 0x00, 0x01, 0x01, 0x87, 0x00, 0x01, 0x01, 0x85, 0x00, 0x01, 0x01, 0x86, 0x00, 0x01,
|
|
98
|
+
0x01, 0x83, 0x00, 0x01, 0x01, 0x00, 0x02, 0x01, 0x00, 0x83, 0x01, 0x01, 0x00, 0x89, 0x01, 0x01, 0x00, 0x87, 0x01, 0x01, 0x00, 0x83, 0x01, 0x03,
|
|
99
|
+
0x00, 0x01, 0x00, 0x88, 0x01, 0x02, 0x00, 0x01, 0x00, 0x03, 0x01, 0x00, 0x01, 0x83, 0x00, 0x01, 0x01, 0x87, 0x00, 0x03, 0x01, 0x00, 0x01, 0x85,
|
|
100
|
+
0x00, 0x03, 0x01, 0x00, 0x01, 0x83, 0x00, 0x03, 0x01, 0x00, 0x01, 0x86, 0x00, 0x03, 0x01, 0x00, 0x01, 0x00, 0x04, 0x01, 0x00, 0x01, 0x00, 0x83,
|
|
101
|
+
0x01, 0x01, 0x00, 0x85, 0x01, 0x05, 0x00, 0x01, 0x00, 0x01, 0x00, 0x83, 0x01, 0x05, 0x00, 0x01, 0x00, 0x01, 0x00, 0x83, 0x01, 0x03, 0x00, 0x01,
|
|
102
|
+
0x00, 0x84, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, 0x00, 0x03, 0x01, 0x00, 0x01, 0x85, 0x00, 0x01, 0x01, 0x83, 0x00, 0x01, 0x01, 0x83, 0x00, 0x01,
|
|
103
|
+
0x01, 0x83, 0x00, 0x07, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x83, 0x00, 0x01, 0x01, 0x84, 0x00, 0x01, 0x01, 0x83, 0x00, 0x01, 0x01, 0x00,
|
|
104
|
+
0x02, 0x01, 0x00, 0x87, 0x01, 0x03, 0x00, 0x01, 0x00, 0x87, 0x01, 0x09, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x86, 0x01, 0x01,
|
|
105
|
+
0x00, 0x85, 0x01, 0x00, 0x01, 0x01, 0x89, 0x00, 0x01, 0x01, 0x89, 0x00, 0x01, 0x01, 0x83, 0x00, 0x03, 0x01, 0x00, 0x01, 0x88, 0x00, 0x01, 0x01,
|
|
106
|
+
0x83, 0x00, 0x01, 0x01, 0x00, 0x02, 0x01, 0x00, 0x87, 0x01, 0x01, 0x00, 0x8b, 0x01, 0x01, 0x00, 0x83, 0x01, 0x01, 0x00, 0x8a, 0x01, 0x04, 0x00,
|
|
107
|
+
0x01, 0x00, 0x01, 0x00, 0x03, 0x01, 0x00, 0x01, 0x85, 0x00, 0x01, 0x01, 0x8b, 0x00, 0x01, 0x01, 0x85, 0x00, 0x01, 0x01, 0x8a, 0x00, 0x03, 0x01,
|
|
108
|
+
0x00, 0x01, 0x00, 0x04, 0x01, 0x00, 0x01, 0x00, 0x83, 0x01, 0x01, 0x00, 0x8b, 0x01, 0x01, 0x00, 0x87, 0x01, 0x01, 0x00, 0x8a, 0x01, 0x02, 0x00,
|
|
109
|
+
0x01, 0x00, 0xa8, 0x01, 0x00,
|
|
110
|
+
};
|
|
111
|
+
// sparse: 880 bytes -> 82 bytes, ratio 10.73, checksum 0xaad9
|
|
112
|
+
const char rle_sparse[] = {
|
|
113
|
+
0xa8, 0x00, 0x00, 0xa8, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x8a, 0x00, 0x01, 0x04, 0x9d, 0x00, 0x00, 0xa8, 0x00, 0x00, 0xa8, 0x00, 0x00, 0xa8, 0x00,
|
|
114
|
+
0x00, 0x9b, 0x00, 0x01, 0x04, 0x8c, 0x00, 0x00, 0xa8, 0x00, 0x00, 0xa8, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x84, 0x00, 0x01, 0x04, 0xa3, 0x00, 0x00,
|
|
115
|
+
0xa8, 0x00, 0x00, 0xa8, 0x00, 0x00, 0xa8, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x92, 0x00, 0x01, 0x04, 0x95, 0x00, 0x00, 0xa8, 0x00, 0x00, 0xa8, 0x00,
|
|
116
|
+
0x00, 0xa8, 0x00, 0x00, 0xa8, 0x00, 0x00, 0xa8, 0x07, 0x00,
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// Host checksums, printed by rle_rooms.py from the source tile arrays.
|
|
120
|
+
#define EXPECT_PLATFORM 0xce8a
|
|
121
|
+
#define EXPECT_MAZE 0xf439
|
|
122
|
+
#define EXPECT_SPARSE 0xaad9
|
|
123
|
+
|
|
124
|
+
// One screen code per tile id, for drawing the platform room.
|
|
125
|
+
const char glyph[8] = { 0x20, 0xa0, 0x63, 0x66, 0x51, 0x5f, 0x5b, 0xe6 };
|
|
126
|
+
|
|
127
|
+
char room[ROOM_SIZE];
|
|
128
|
+
|
|
129
|
+
// --- the decoder -----------------------------------------------------
|
|
130
|
+
// Expands ROOM_H row streams into dst. Returns the decoded length.
|
|
131
|
+
unsigned rle_room(const char *src, char *dst)
|
|
132
|
+
{
|
|
133
|
+
unsigned n = 0;
|
|
134
|
+
for (char y = 0; y < ROOM_H; y++) {
|
|
135
|
+
for (;;) {
|
|
136
|
+
char c = *src++;
|
|
137
|
+
if (c == 0)
|
|
138
|
+
break;
|
|
139
|
+
if (c & 0x80) {
|
|
140
|
+
char v = *src++;
|
|
141
|
+
char k = c & 0x7f;
|
|
142
|
+
do { dst[n++] = v; } while (--k);
|
|
143
|
+
} else {
|
|
144
|
+
do { dst[n++] = *src++; } while (--c);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return n;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// --- the same decoder by hand ----------------------------------------
|
|
152
|
+
// Six zero-page bytes: source and destination pointers, a count and a
|
|
153
|
+
// row counter. Y indexes the destination within the row; the source is
|
|
154
|
+
// read through (zsrc,x) with X = 0 and the pointer stepped by hand.
|
|
155
|
+
__zeropage const char *zsrc;
|
|
156
|
+
__zeropage char *zdst;
|
|
157
|
+
__zeropage char zcnt;
|
|
158
|
+
__zeropage char zrows;
|
|
159
|
+
|
|
160
|
+
__noinline void rle_room_asm(void)
|
|
161
|
+
{
|
|
162
|
+
__asm volatile
|
|
163
|
+
{
|
|
164
|
+
lda #ROOM_H
|
|
165
|
+
sta zrows
|
|
166
|
+
nextrow:
|
|
167
|
+
ldy #0
|
|
168
|
+
ctl:
|
|
169
|
+
ldx #0
|
|
170
|
+
lda (zsrc,x)
|
|
171
|
+
inc zsrc
|
|
172
|
+
bne c1
|
|
173
|
+
inc zsrc + 1
|
|
174
|
+
c1: tax
|
|
175
|
+
beq rowend
|
|
176
|
+
bmi run
|
|
177
|
+
stx zcnt
|
|
178
|
+
lit:
|
|
179
|
+
ldx #0
|
|
180
|
+
lda (zsrc,x)
|
|
181
|
+
inc zsrc
|
|
182
|
+
bne l1
|
|
183
|
+
inc zsrc + 1
|
|
184
|
+
l1: sta (zdst),y
|
|
185
|
+
iny
|
|
186
|
+
dec zcnt
|
|
187
|
+
bne lit
|
|
188
|
+
beq ctl
|
|
189
|
+
run:
|
|
190
|
+
and #0x7f
|
|
191
|
+
sta zcnt
|
|
192
|
+
ldx #0
|
|
193
|
+
lda (zsrc,x)
|
|
194
|
+
inc zsrc
|
|
195
|
+
bne r1
|
|
196
|
+
inc zsrc + 1
|
|
197
|
+
r1: sta (zdst),y
|
|
198
|
+
iny
|
|
199
|
+
dec zcnt
|
|
200
|
+
bne r1
|
|
201
|
+
beq ctl
|
|
202
|
+
rowend:
|
|
203
|
+
tya
|
|
204
|
+
clc
|
|
205
|
+
adc zdst
|
|
206
|
+
sta zdst
|
|
207
|
+
bcc r2
|
|
208
|
+
inc zdst + 1
|
|
209
|
+
r2: dec zrows
|
|
210
|
+
bne nextrow
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// --- CIA1 timer B harness --------------------------------------------
|
|
215
|
+
static inline void timer_start(void)
|
|
216
|
+
{
|
|
217
|
+
cia1.crb = 0x00;
|
|
218
|
+
cia1.tb = 0xffff;
|
|
219
|
+
cia1.crb = 0x11; // force load, start, count phi2
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
static inline unsigned timer_stop(void)
|
|
223
|
+
{
|
|
224
|
+
cia1.crb = 0x00;
|
|
225
|
+
return 0xffff - cia1.tb;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// --- checksum fold, the same as rle_rooms.py -------------------------
|
|
229
|
+
static inline unsigned fold(unsigned chk, unsigned v)
|
|
230
|
+
{
|
|
231
|
+
return (chk ^ v) * 5 + 1;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
unsigned room_checksum(unsigned len)
|
|
235
|
+
{
|
|
236
|
+
unsigned chk = 0;
|
|
237
|
+
for (unsigned i = 0; i < len; i++)
|
|
238
|
+
chk = fold(chk, room[i]);
|
|
239
|
+
return fold(chk, len);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// --- text helpers (screen codes) -------------------------------------
|
|
243
|
+
void put_str(char *p, const char *s)
|
|
244
|
+
{
|
|
245
|
+
while (*s)
|
|
246
|
+
*p++ = *s++;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
void put_dec(char *p, unsigned v, char digits)
|
|
250
|
+
{
|
|
251
|
+
for (char i = digits; i > 0; i--) {
|
|
252
|
+
p[i - 1] = 0x30 + v % 10;
|
|
253
|
+
v /= 10;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// One report line: NAME PACKED RATIO C-CYCLES ASM-CYCLES PASS/FAIL.
|
|
258
|
+
// Returns 1 when both decoders reproduce the host checksum.
|
|
259
|
+
char report(char row, const char *name, const char *src, unsigned packed,
|
|
260
|
+
unsigned expect)
|
|
261
|
+
{
|
|
262
|
+
char *p = Screen + row * 40;
|
|
263
|
+
|
|
264
|
+
__asm { sei }
|
|
265
|
+
timer_start();
|
|
266
|
+
unsigned overhead = timer_stop();
|
|
267
|
+
|
|
268
|
+
// The C decoder.
|
|
269
|
+
timer_start();
|
|
270
|
+
unsigned len = rle_room(src, room);
|
|
271
|
+
unsigned cycles_c = timer_stop() - overhead;
|
|
272
|
+
char ok = (len == ROOM_SIZE && room_checksum(len) == expect);
|
|
273
|
+
|
|
274
|
+
// The hand-written decoder, into a buffer first filled with 0xff so
|
|
275
|
+
// a short decode cannot pass on the C decoder's leftovers.
|
|
276
|
+
for (unsigned i = 0; i < ROOM_SIZE; i++)
|
|
277
|
+
room[i] = 0xff;
|
|
278
|
+
zsrc = src;
|
|
279
|
+
zdst = room;
|
|
280
|
+
timer_start();
|
|
281
|
+
rle_room_asm();
|
|
282
|
+
unsigned cycles_asm = timer_stop() - overhead;
|
|
283
|
+
__asm { cli }
|
|
284
|
+
ok &= (room_checksum(ROOM_SIZE) == expect);
|
|
285
|
+
|
|
286
|
+
// ratio x 100, in 32 bits because 88000 does not fit in 16.
|
|
287
|
+
unsigned r100 = (unsigned)(((unsigned long)ROOM_SIZE * 100 + packed / 2) / packed);
|
|
288
|
+
|
|
289
|
+
put_str(p, name);
|
|
290
|
+
put_dec(p + 5, packed, 4);
|
|
291
|
+
put_dec(p + 10, r100 / 100, 2);
|
|
292
|
+
p[12] = 0x2e;
|
|
293
|
+
put_dec(p + 13, r100 % 100, 2);
|
|
294
|
+
put_dec(p + 16, cycles_c, 5);
|
|
295
|
+
put_dec(p + 22, cycles_asm, 5);
|
|
296
|
+
put_str(p + 28, ok ? s"pass" : s"fail");
|
|
297
|
+
if (p[10] == 0x30)
|
|
298
|
+
p[10] = 0x20;
|
|
299
|
+
return ok;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
void draw_room(void)
|
|
303
|
+
{
|
|
304
|
+
char *s = Screen + 3 * 40;
|
|
305
|
+
for (unsigned i = 0; i < ROOM_SIZE; i++)
|
|
306
|
+
s[i] = glyph[room[i]];
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
int main(void)
|
|
310
|
+
{
|
|
311
|
+
vic.color_border = 0;
|
|
312
|
+
vic.color_back = 0;
|
|
313
|
+
for (unsigned i = 0; i < 1000; i++) {
|
|
314
|
+
Screen[i] = 0x20;
|
|
315
|
+
Color[i] = 1;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Blank the display so no badline lands in the timed regions; DEN
|
|
319
|
+
// is sampled on line $30, so wait two frames for it to take effect.
|
|
320
|
+
vic.ctrl1 = 0x0b;
|
|
321
|
+
vic_waitFrame();
|
|
322
|
+
vic_waitFrame();
|
|
323
|
+
|
|
324
|
+
char ok = 1;
|
|
325
|
+
ok &= report(1, s"maze", rle_maze, sizeof(rle_maze), EXPECT_MAZE);
|
|
326
|
+
ok &= report(2, s"spar", rle_sparse, sizeof(rle_sparse), EXPECT_SPARSE);
|
|
327
|
+
// The platform room is decoded last so it is the one left in RAM.
|
|
328
|
+
ok &= report(0, s"plat", rle_platform, sizeof(rle_platform), EXPECT_PLATFORM);
|
|
329
|
+
draw_room();
|
|
330
|
+
|
|
331
|
+
char code = ok ? CODE_PASS : CODE_FAIL;
|
|
332
|
+
RESULT = code;
|
|
333
|
+
vic.color_border = ok ? 5 : 2;
|
|
334
|
+
put_str(Screen + 34, s"r 0");
|
|
335
|
+
Screen[37] = 0x30 + code;
|
|
336
|
+
|
|
337
|
+
vic.ctrl1 = 0x1b;
|
|
338
|
+
|
|
339
|
+
for (;;)
|
|
340
|
+
;
|
|
341
|
+
return 0;
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
The three `rle_*` arrays and the three `EXPECT_*` values are the output of
|
|
346
|
+
this host script. Each room is drawn as 22 strings of 40 characters and
|
|
347
|
+
turned into tile ids by the `TILES` table, so the source array is the
|
|
348
|
+
picture. The encoder emits a run for three or more equal tiles, a literal
|
|
349
|
+
group otherwise, and a zero after every row; runs never cross a row. The
|
|
350
|
+
script decodes its own output and asserts it matches before printing.
|
|
351
|
+
|
|
352
|
+
```text
|
|
353
|
+
# rle_rooms.py -- author three 40x22 rooms, RLE-encode them, print C arrays.
|
|
354
|
+
# Format (same as tile-map-render.md): control byte c
|
|
355
|
+
# c & 0x80 : run, next byte repeated (c & 0x7f) times (1..127)
|
|
356
|
+
# c < 0x80 : c literal bytes follow (1..127)
|
|
357
|
+
# 0x00 : end of row
|
|
358
|
+
# Each of the 22 rows is its own stream; a run never crosses a row.
|
|
359
|
+
|
|
360
|
+
TILES = {'.': 0, '#': 1, '=': 2, 'X': 3, 'o': 4, 'L': 5, 'D': 6, 'W': 7}
|
|
361
|
+
|
|
362
|
+
PLATFORM = [
|
|
363
|
+
"########################################",
|
|
364
|
+
"#......................................#",
|
|
365
|
+
"#..oo..................................#",
|
|
366
|
+
"#.======.............................D.#",
|
|
367
|
+
"#..........................========..LL#",
|
|
368
|
+
"#....................................LL#",
|
|
369
|
+
"#............=====...................LL#",
|
|
370
|
+
"#..............................LLLLLLLL#",
|
|
371
|
+
"#.....XXXXXXXX.........................#",
|
|
372
|
+
"#......................................#",
|
|
373
|
+
"#..LL.............=======..............#",
|
|
374
|
+
"#..LL..................................#",
|
|
375
|
+
"#..LL......oo..........................#",
|
|
376
|
+
"#=========================.............#",
|
|
377
|
+
"#......................................#",
|
|
378
|
+
"#......................................#",
|
|
379
|
+
"#.............................=========#",
|
|
380
|
+
"#..........======......................#",
|
|
381
|
+
"#......................................#",
|
|
382
|
+
"#.oo..................XXXXXXXXXXXX.....#",
|
|
383
|
+
"#=================....##################",
|
|
384
|
+
"########################################",
|
|
385
|
+
]
|
|
386
|
+
|
|
387
|
+
MAZE = [
|
|
388
|
+
"########################################",
|
|
389
|
+
"#...#.......#.....#.....#...#..........#",
|
|
390
|
+
"#.#.#.#####.#.###.#.###.#.#.#.########.#",
|
|
391
|
+
"#.#...#...#...#...#...#...#.#.#......#.#",
|
|
392
|
+
"#.#####.#.#####.#####.#####.#.#.####.#.#",
|
|
393
|
+
"#.......#.......#.........#...#....#...#",
|
|
394
|
+
"#.#########.###.#.#######.#####.##.###.#",
|
|
395
|
+
"#.#.......#.#...#.#.....#.....#..#...#.#",
|
|
396
|
+
"#.#.#####.#.#.###.#.###.#####.##.###.#.#",
|
|
397
|
+
"#...#...#...#.#...#...#.....#....#...#.#",
|
|
398
|
+
"###.#.#.#####.#.#####.#####.######.#.#.#",
|
|
399
|
+
"#...#.#.......#.......#.....#......#...#",
|
|
400
|
+
"#.###.#########.#######.###.#.########.#",
|
|
401
|
+
"#.#...#.......#.#.....#.#...#.#......#.#",
|
|
402
|
+
"#.#.###.#####.#.#.###.#.#.###.#.####.#.#",
|
|
403
|
+
"#.#.....#...#...#...#.#.#.#...#....#...#",
|
|
404
|
+
"#.#######.#.#######.#.#.#.#.######.#####",
|
|
405
|
+
"#.........#.........#...#.#........#...#",
|
|
406
|
+
"#.#######.###########.###.##########.#.#",
|
|
407
|
+
"#.#.....#...........#.....#..........#.#",
|
|
408
|
+
"#.#.###.###########.#######.##########.#",
|
|
409
|
+
"########################################",
|
|
410
|
+
]
|
|
411
|
+
|
|
412
|
+
SPARSE = [
|
|
413
|
+
"........................................",
|
|
414
|
+
"........................................",
|
|
415
|
+
"........................................",
|
|
416
|
+
"..........o.............................",
|
|
417
|
+
"........................................",
|
|
418
|
+
"........................................",
|
|
419
|
+
"........................................",
|
|
420
|
+
"...........................o............",
|
|
421
|
+
"........................................",
|
|
422
|
+
"........................................",
|
|
423
|
+
"........................................",
|
|
424
|
+
"....o...................................",
|
|
425
|
+
"........................................",
|
|
426
|
+
"........................................",
|
|
427
|
+
"........................................",
|
|
428
|
+
"........................................",
|
|
429
|
+
"..................o.....................",
|
|
430
|
+
"........................................",
|
|
431
|
+
"........................................",
|
|
432
|
+
"........................................",
|
|
433
|
+
"........................................",
|
|
434
|
+
"WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW",
|
|
435
|
+
]
|
|
436
|
+
|
|
437
|
+
def tiles(room):
|
|
438
|
+
assert len(room) == 22 and all(len(r) == 40 for r in room)
|
|
439
|
+
return [[TILES[ch] for ch in r] for r in room]
|
|
440
|
+
|
|
441
|
+
def encode_row(row):
|
|
442
|
+
out, lit, i = [], [], 0
|
|
443
|
+
def flush():
|
|
444
|
+
if lit:
|
|
445
|
+
out.append(len(lit)); out.extend(lit); lit.clear()
|
|
446
|
+
while i < len(row):
|
|
447
|
+
j = i
|
|
448
|
+
while j < len(row) and row[j] == row[i] and j - i < 127:
|
|
449
|
+
j += 1
|
|
450
|
+
if j - i >= 3:
|
|
451
|
+
flush(); out.append(0x80 | (j - i)); out.append(row[i]); i = j
|
|
452
|
+
else:
|
|
453
|
+
lit.append(row[i]); i += 1
|
|
454
|
+
if len(lit) == 127: flush()
|
|
455
|
+
flush(); out.append(0)
|
|
456
|
+
return out
|
|
457
|
+
|
|
458
|
+
def decode(stream):
|
|
459
|
+
out, i, rows = [], 0, 0
|
|
460
|
+
while rows < 22:
|
|
461
|
+
c = stream[i]; i += 1
|
|
462
|
+
if c == 0: rows += 1
|
|
463
|
+
elif c & 0x80: out.extend([stream[i]] * (c & 0x7f)); i += 1
|
|
464
|
+
else: out.extend(stream[i:i + c]); i += c
|
|
465
|
+
return out, i
|
|
466
|
+
|
|
467
|
+
def fold(chk, v):
|
|
468
|
+
return ((chk ^ v) * 5 + 1) & 0xffff
|
|
469
|
+
|
|
470
|
+
def checksum(data):
|
|
471
|
+
chk = 0
|
|
472
|
+
for v in data: chk = fold(chk, v)
|
|
473
|
+
return fold(chk, len(data))
|
|
474
|
+
|
|
475
|
+
for name, room in (("platform", PLATFORM), ("maze", MAZE), ("sparse", SPARSE)):
|
|
476
|
+
grid = tiles(room)
|
|
477
|
+
flat = [t for r in grid for t in r]
|
|
478
|
+
stream = [b for r in grid for b in encode_row(r)]
|
|
479
|
+
back, used = decode(stream)
|
|
480
|
+
assert back == flat and used == len(stream)
|
|
481
|
+
print("// %s: %d bytes -> %d bytes, ratio %.2f, checksum 0x%04x"
|
|
482
|
+
% (name, len(flat), len(stream), len(flat) / len(stream), checksum(flat)))
|
|
483
|
+
print("const char rle_%s[] = {" % name)
|
|
484
|
+
for k in range(0, len(stream), 24):
|
|
485
|
+
print(" " + ", ".join("0x%02x" % b for b in stream[k:k + 24]) + ",")
|
|
486
|
+
print("};")
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
## Build
|
|
490
|
+
|
|
491
|
+
```bash
|
|
492
|
+
python3 rle_rooms.py # prints the rle_* arrays and the checksums
|
|
493
|
+
oscar64 -tm=c64 -O2 -o=level-rle-decoder.prg level-rle-decoder.c
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
Produces `level-rle-decoder.prg`, 3,030 bytes (Oscar64 build 2026-05-19),
|
|
497
|
+
plus `level-rle-decoder.map`, `.asm` and `.lbl`. Then run headless in
|
|
498
|
+
VICE (PAL):
|
|
499
|
+
|
|
500
|
+
```bash
|
|
501
|
+
GSETTINGS_SCHEMA_DIR=/opt/homebrew/share/glib-2.0/schemas x64sc -default -warp +sound \
|
|
502
|
+
+autostart-delay-random -autostartprgmode 1 -limitcycles 6000000 \
|
|
503
|
+
-exitscreenshot level-rle-decoder.png -autostart level-rle-decoder.prg
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
Add `-model ntsc` for the NTSC picture.
|
|
507
|
+
|
|
508
|
+
## Expected output
|
|
509
|
+
|
|
510
|
+
Green border, black background, white text. Rows 0 to 2 read:
|
|
511
|
+
|
|
512
|
+
```text
|
|
513
|
+
PLAT 0213 4.13 33562 19158 PASS R 01
|
|
514
|
+
MAZE 0629 1.40 50447 27673 PASS
|
|
515
|
+
SPAR 0082 10.73 28193 16470 PASS
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
The columns are: room, packed bytes, ratio (880 bytes over packed bytes,
|
|
519
|
+
rounded to two places), cycles for the C decoder, cycles for the
|
|
520
|
+
hand-written decoder, and PASS when both decoders reproduce the host
|
|
521
|
+
checksum. `R 01` is the verdict code, `01` for pass and `02` for fail;
|
|
522
|
+
the same byte is at `$02FF` and the border is green (5) or red (2).
|
|
523
|
+
Rows 3 to 24 are the platform room: a solid frame, eight platform runs
|
|
524
|
+
drawn as bars, ladder tiles in two columns and one horizontal run, two
|
|
525
|
+
rows of spikes, a door at the upper right and three pairs of coins.
|
|
526
|
+
|
|
527
|
+
The same text and the same cycle counts appear on PAL and NTSC (measured
|
|
528
|
+
in VICE x64sc 3.10, both models; the timed regions run with interrupts
|
|
529
|
+
masked and the display blanked, so only CPU cycles are counted).
|
|
530
|
+
|
|
531
|
+
Screenshots at 6,000,000 cycles: `screenshots/level-rle-decoder.png` (PAL)
|
|
532
|
+
and `screenshots/level-rle-decoder-ntsc.png` (NTSC).
|
|
533
|
+
|
|
534
|
+
The figures, all read off the picture or the `.map` file:
|
|
535
|
+
|
|
536
|
+
| Room | Source bytes | Packed bytes | Ratio | C decoder cycles | Hand-written cycles |
|
|
537
|
+
|---|---|---|---|---|---|
|
|
538
|
+
| Platform | 880 | 213 | 4.13 : 1 | 33,562 (38.1 per byte) | 19,158 (21.8 per byte) |
|
|
539
|
+
| Maze | 880 | 629 | 1.40 : 1 | 50,447 (57.3 per byte) | 27,673 (31.4 per byte) |
|
|
540
|
+
| Sparse | 880 | 82 | 10.73 : 1 | 28,193 (32.0 per byte) | 16,470 (18.7 per byte) |
|
|
541
|
+
|
|
542
|
+
| Decoder | Bytes of code | Source |
|
|
543
|
+
|---|---|---|
|
|
544
|
+
| `rle_room` (C, `-O2`) | 149 | `.map`, `objects by size`: `rle_room, NATIVE_CODE:code (0095)` |
|
|
545
|
+
| `rle_room_asm` (hand-written) | 80 | `.map`: `rle_room_asm, NATIVE_CODE:code (0050)`, including the `rts` |
|
|
546
|
+
|
|
547
|
+
The hand-written decoder also uses six zero-page bytes (`$F7` to `$FC`
|
|
548
|
+
in the `.map`). Both cycle figures are net of the harness's own
|
|
549
|
+
start/stop cost, which the program measures once with an empty timed
|
|
550
|
+
region and subtracts. The per-byte figures are arithmetic from the
|
|
551
|
+
cycle counts.
|
|
552
|
+
|
|
553
|
+
## Why this works
|
|
554
|
+
|
|
555
|
+
The stream format is the one `tile-map-render.md` established, so a
|
|
556
|
+
level built for that recipe decodes here unchanged. The C decoder is that
|
|
557
|
+
recipe's `rle_row` with the row loop folded in: it returns the total
|
|
558
|
+
decoded length, and the caller checks that it is 880 before it trusts the
|
|
559
|
+
checksum. The hand-written decoder does the same work with Y as the
|
|
560
|
+
destination index within a row and the source read through `(zsrc,x)`
|
|
561
|
+
with X held at zero, which is the 6502's only way to read through a
|
|
562
|
+
pointer without spending Y. After each row `tya` adds the row's length
|
|
563
|
+
to the destination pointer, so a row that decodes short or long shifts
|
|
564
|
+
every later row and the checksum catches it. The two `beq ctl` branches
|
|
565
|
+
after `bne` are unconditional in effect: `dec zcnt` has just left Z set.
|
|
566
|
+
|
|
567
|
+
The three rooms are chosen to span the range a game meets. The platform
|
|
568
|
+
room is long runs of floor and air broken by short features and packs
|
|
569
|
+
4.13 : 1. The maze is a wall every other cell, which defeats a
|
|
570
|
+
three-byte run threshold on most rows, and packs 1.40 : 1; a tile-pair
|
|
571
|
+
dictionary would do better on it (not measured here). The sparse room is nearly empty and packs 10.73 : 1. The
|
|
572
|
+
ratio a game sees depends on its rooms, and a design document that quotes
|
|
573
|
+
one figure should say which room it came from.
|
|
574
|
+
|
|
575
|
+
The cycle counts depend on the mix of runs and literals, not only on the
|
|
576
|
+
output size: the maze costs the most because every control byte does
|
|
577
|
+
little work. The hand-written decoder is a little under twice as fast as
|
|
578
|
+
the C one at `-O2` and about half its size. A 20 to 30 byte decoder is
|
|
579
|
+
possible only by dropping the row structure and the 16-bit pointer
|
|
580
|
+
arithmetic, and neither of the decoders here is one; the smallest
|
|
581
|
+
decoder for this exact format is not measured here.
|
|
582
|
+
|
|
583
|
+
The timing harness is the CIA1 timer B pattern of `tile-map-render.md`:
|
|
584
|
+
the timer is stopped before it is read so the two-byte read cannot
|
|
585
|
+
straddle a decrement, interrupts are masked around the timed region, and
|
|
586
|
+
the display is blanked two frames earlier because DEN is sampled once
|
|
587
|
+
per frame on line `$30`. The checksum fold `(chk ^ v) * 5 + 1` in 16
|
|
588
|
+
bits is order-sensitive, so a decoder that produced the right bytes in
|
|
589
|
+
the wrong order would fail. The hand-written decoder writes into a buffer
|
|
590
|
+
filled with `0xff` first, so it cannot pass on the C decoder's output.
|
|
591
|
+
|
|
592
|
+
## Verification
|
|
593
|
+
|
|
594
|
+
Three instruments, run against the committed PNGs (VICE x64sc 3.10,
|
|
595
|
+
Oscar64 build 2026-05-19).
|
|
596
|
+
|
|
597
|
+
**Text, room and border.** A script matched every cell of rows 0 to 2
|
|
598
|
+
against the glyphs of `chargen-901225-01.bin` and read the border pixel
|
|
599
|
+
at (2, 100). Both pictures give the three lines quoted above and the
|
|
600
|
+
border RGB VICE emits for colour 5 on each model, (98, 213, 50) on PAL
|
|
601
|
+
and (114, 189, 103) on NTSC. The same script then took the platform
|
|
602
|
+
room's 22 strings from `rle_rooms.py`, mapped each character through
|
|
603
|
+
`TILES` and `glyph`, and compared the 8 x 8 ink pattern of each of the
|
|
604
|
+
880 cells on rows 3 to 24 with the char ROM glyph: 880 compared, 0
|
|
605
|
+
differing, on both pictures. The `.map` of the same build gives
|
|
606
|
+
`rle_room` 149 bytes and `rle_room_asm` 80 bytes.
|
|
607
|
+
|
|
608
|
+
**Checksums.** The host script computed `0xCE8A`, `0xF439` and `0xAAD9`
|
|
609
|
+
from the source arrays; the machine folds 880 decoded bytes and the
|
|
610
|
+
length the same way and prints PASS three times for each decoder, on
|
|
611
|
+
both models. This is rung 1 for these three streams and says nothing
|
|
612
|
+
about streams these rooms do not exercise (no row here has a run of more
|
|
613
|
+
than 40, and a run count of zero is undefined by the format).
|
|
614
|
+
|
|
615
|
+
**Reproducibility.** The pinned command was run twice per model and the
|
|
616
|
+
PNG bytes were identical each time.
|
|
617
|
+
|
|
618
|
+
The first build printed the maze ratio as `1.39` where the host said
|
|
619
|
+
`1.40`: the machine truncated where Python rounded. The ratio now adds
|
|
620
|
+
half the divisor before dividing, and the two agree on all three rooms.
|