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
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,2082 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Versions are in `VERSION` (data, schema, tool surface) and `package.json`.
|
|
4
|
+
Entries below start at the first public audit; earlier history is in git.
|
|
5
|
+
|
|
6
|
+
## Unreleased
|
|
7
|
+
|
|
8
|
+
Data 771, schema 31, tools 2.3.1, package 0.17.0.
|
|
9
|
+
|
|
10
|
+
**Licence pass before npm publishing (data 771).** A measured check of
|
|
11
|
+
`docs/` found no copied prose (runs of 25 or more words shared with 108
|
|
12
|
+
cited sources and the classic references are number tables only) and no
|
|
13
|
+
substantial third-party code. Four fixes. `wireframe-ships` reproduced
|
|
14
|
+
Elite's 32 two-letter name tokens (QQ16), commercial game data; it now
|
|
15
|
+
uses its own table of the same shape, so its systems print GUBUDUIS ...
|
|
16
|
+
NEYA instead of TIBEDIED ... LAVE; seeds, coordinates and every cycle
|
|
17
|
+
count are unchanged, re-verified in VICE on both models (0 pixels from
|
|
18
|
+
the model). Three examples in `kickassembler-reference.md` (the SID
|
|
19
|
+
player, `ClearScreen`, `mov`) followed the KickAssembler manual line for
|
|
20
|
+
line; they are rewritten and now share no 8-word run with it, and the
|
|
21
|
+
new SID player was run in VICE against a test tune (one `play` per PAL
|
|
22
|
+
frame). `oscar64-headers-reference.md` said `license: MIT`; Oscar64 is
|
|
23
|
+
GPL-3.0. The SID ADSR table now names its source.
|
|
24
|
+
|
|
25
|
+
**npm package (package 0.17.0).** An installed package could not do
|
|
26
|
+
anything useful: batch ingest existed only as an npm script in a clone,
|
|
27
|
+
`docker-compose.yml` was not shipped, and state was written inside the
|
|
28
|
+
package folder. `c64-kb ingest` and `c64-kb services up|down|status` now
|
|
29
|
+
exist, and state goes to `$XDG_DATA_HOME/c64-kb` (or
|
|
30
|
+
`~/.local/share/c64-kb`, or `C64_KB_DATA_DIR`) when the package is under
|
|
31
|
+
`node_modules`; a clone still uses `data/`. CI installs the packed
|
|
32
|
+
tarball into an empty folder and runs services, ingest and a lookup. A
|
|
33
|
+
release workflow publishes on a `v*` tag; the first publish and the
|
|
34
|
+
licence check are open in #52.
|
|
35
|
+
|
|
36
|
+
**A routed game briefing names its starter (tools 2.3.1, package
|
|
37
|
+
0.16.1).** `c64_game_briefing` with no `archetype` routes by the brief's
|
|
38
|
+
words, but its query did not select `a.starter`, so a routed briefing
|
|
39
|
+
never printed the `new-project` command. Naming the archetype did. The
|
|
40
|
+
route now carries the starter, and a test in `test/briefings.test.ts`
|
|
41
|
+
failed before the fix.
|
|
42
|
+
|
|
43
|
+
**Every #39 starter is named by its archetype.** `**Starter:**` lines for
|
|
44
|
+
`text_adventure` (adventure), `beat_em_up` (beat-em-up) and `demo_intro`
|
|
45
|
+
(demo), now that those starters are on main; `c64_game_briefing` and
|
|
46
|
+
`c64_demo_briefing` print their `new-project` command.
|
|
47
|
+
|
|
48
|
+
**Issue #39: `shmup-vertical` loses no frames on NTSC.**
|
|
49
|
+
- The lost-frame counter could not see a single late frame: it counted
|
|
50
|
+
frame-counter steps other than 1. It now checks the frame flag before
|
|
51
|
+
waiting.
|
|
52
|
+
- With it, NTSC play lost frames at play frames 282-321 and 454-477,
|
|
53
|
+
which the staged run never reached. The heaviest steps moved to
|
|
54
|
+
KickAssembler, and the latest end of work is now line 256 of 263 on
|
|
55
|
+
NTSC.
|
|
56
|
+
- `make joytest` plays 16 games per model with fire held and sweeping,
|
|
57
|
+
and fails on any lost frame. `make longplay` plays about 40,000 frames
|
|
58
|
+
per model with an invulnerable ship. Both run 0 lost.
|
|
59
|
+
|
|
60
|
+
**Issue #39: the `beat-em-up` starter lands; `lane_depth_engine`
|
|
61
|
+
corrected (data 769).**
|
|
62
|
+
- `templates/beat-em-up` is a three-stage street brawler in Oscar64 plus
|
|
63
|
+
KickAssembler:
|
|
64
|
+
- fighters of two sprites each in a band written near to far;
|
|
65
|
+
- a brute drawn in characters, with `$D01B` behind bits;
|
|
66
|
+
- attacks gated by lane and per-frame boxes;
|
|
67
|
+
- round-robin AI, and a tune with effects.
|
|
68
|
+
- It checks itself with a flicker check that renders every part from the
|
|
69
|
+
art, a VIC register read-back every frame, an independent hit re-check
|
|
70
|
+
and a game-over check. It passes on the local Oscar64 and on v1.32.273.
|
|
71
|
+
- Measured worst 14,960 / 9,359 PAL and 16,464 / 9,897 NTSC.
|
|
72
|
+
- The review measured that a Y-sorted multiplexer draws the farther
|
|
73
|
+
actor in front. `techniques/logic.md` `lane_depth_engine` said the
|
|
74
|
+
depth and raster orders agree; step 3 and "More actors" now say they
|
|
75
|
+
are opposite, with a correction clause.
|
|
76
|
+
|
|
77
|
+
**agent-harness: counting lost frames.** The meter reports cost, not
|
|
78
|
+
lateness, and the page did not say how to count a dropped frame. A check
|
|
79
|
+
at wake-up for a frame counter that moved by more than one misses every
|
|
80
|
+
single overrun (shmup-vertical 7974a7a: a frame made ~2,400 cycles late
|
|
81
|
+
left `OVERRUNS 00`); the page now says to test the next frame's flag when
|
|
82
|
+
the work ends.
|
|
83
|
+
|
|
84
|
+
**Issue #39: `shmup-vertical` gets enemy fire and a per-frame bullet
|
|
85
|
+
check.**
|
|
86
|
+
- Darts, weaves and swoops fire dots that drift towards the ship, from
|
|
87
|
+
a 6-dot pool in a fire window at Y 72-140. The dots' step, the
|
|
88
|
+
bullet draw list, the enemy boxes and the path step moved to
|
|
89
|
+
KickAssembler: the staged worst had reached 17,882 NTSC cycles, over
|
|
90
|
+
the frame.
|
|
91
|
+
- Staged worst now 15,991 PAL / 16,136 NTSC, with no frame lost; graded
|
|
92
|
+
run 12,912 / 13,015.
|
|
93
|
+
- Each bullet cell is read back against the map after every erase.
|
|
94
|
+
- `make joytest` plays to game over, reboots on the same disk and
|
|
95
|
+
requires the saved high score.
|
|
96
|
+
- It passes on the released Oscar64 v1.32.273.
|
|
97
|
+
|
|
98
|
+
**`verify:templates --selftest` runs each starter's own proof targets
|
|
99
|
+
(#42).** Several #39 fixes are proved only by a starter's own target: the
|
|
100
|
+
adventure's save validation by `disktest`, the platformer's scroll timing
|
|
101
|
+
by `tearcheck`, the demo's stable entry by `probe`. A starter lists them in
|
|
102
|
+
`VERIFY_TARGETS`; `--selftest` runs each after `make selftest`. Seven
|
|
103
|
+
starters with their targets: 7 of 7.
|
|
104
|
+
|
|
105
|
+
**Issue #39: `platformer` hardened after the other session's
|
|
106
|
+
comparison.**
|
|
107
|
+
- It builds and passes on the released Oscar64 v1.32.273, with
|
|
108
|
+
`surface_at` kept out of line (#30) and the score printed through
|
|
109
|
+
`put_digits`. v1.32.273 dropped digits from a loop; that fault is not
|
|
110
|
+
reduced yet.
|
|
111
|
+
- The live-enemy limit is 5: six live enemies overran the NTSC frame
|
|
112
|
+
(17,618 cycles staged). `make stage` fills every slot.
|
|
113
|
+
- `check_frame` checks four invariants every frame, each with its own
|
|
114
|
+
fault bit. The slope bit caught a mutation that the tear check missed.
|
|
115
|
+
- Hitboxes come per animation frame, with a group and a mask; the stomp
|
|
116
|
+
is a feet box on the falling frame.
|
|
117
|
+
- `tools/drive.py` runs at real speed and on a free port.
|
|
118
|
+
|
|
119
|
+
**Issue #39: `action-puzzle` hardened after the other session's
|
|
120
|
+
comparison.**
|
|
121
|
+
- The redraw is bounded. An overflowing dirty list used to redraw 280
|
|
122
|
+
cells in one frame (55,305 cycles); rows are now queued, two a frame.
|
|
123
|
+
- The right roll, the restart path over three lives, the high-score
|
|
124
|
+
read-back and the once-per-scan check are all gated. Each is proved
|
|
125
|
+
by a mutation.
|
|
126
|
+
- Dropped frames are counted from the `$D019` raster latch.
|
|
127
|
+
- It builds and passes on the released Oscar64 v1.32.273.
|
|
128
|
+
- Staged worst frame (16 boulders falling in one slice): 13,619 PAL /
|
|
129
|
+
13,832 NTSC cycles.
|
|
130
|
+
|
|
131
|
+
**Issue #39: the `demo` starter lands, and the two stub skeletons are
|
|
132
|
+
removed.** `templates/demo` is pure KickAssembler:
|
|
133
|
+
- a part table with init, update, out step and teardown, and a
|
|
134
|
+
table-driven IRQ chain;
|
|
135
|
+
- a stable double-IRQ raster-bar kernel, a sprite sine chain, a
|
|
136
|
+
scroller, and an original tune with NTSC tempo skips.
|
|
137
|
+
|
|
138
|
+
It checks itself on PAL and NTSC with 229 screenshot checks, 8
|
|
139
|
+
jittered probe shots of the bar kernel, dispatcher counters (late and
|
|
140
|
+
bad frames), a deadline test on the frame slot, and a SID store trace
|
|
141
|
+
(`make audio`). Measured worst 7,332 / typical 6,586 cycles on PAL.
|
|
142
|
+
`templates/c64-demo-starter` and `templates/c64-game-starter` are
|
|
143
|
+
removed. The game starter fed a `.prg` to Oscar64 as source, which
|
|
144
|
+
Oscar64 ignores.
|
|
145
|
+
|
|
146
|
+
**Issue #39: the `adventure` starter, STARWATCH.** It is a 12-room text
|
|
147
|
+
adventure in Oscar64:
|
|
148
|
+
- the world is data in `tools/world.py`, and a Python model checks the
|
|
149
|
+
game line by line;
|
|
150
|
+
- a two-word parser with synonyms;
|
|
151
|
+
- text packed by byte-pair coding, 40% smaller;
|
|
152
|
+
- picture strips coded row by row;
|
|
153
|
+
- one window line printed per frame;
|
|
154
|
+
- SAVE and LOAD on drive 8, with the record versioned from the world.
|
|
155
|
+
|
|
156
|
+
Measured in VICE x64sc 3.10:
|
|
157
|
+
- worst 15,272 / typical 8,543 cycles on PAL; 15,488 / 8,842 on NTSC;
|
|
158
|
+
- `make disktest` saves, cold-resets and loads under true 1541
|
|
159
|
+
emulation, and refuses three bad saves.
|
|
160
|
+
|
|
161
|
+
Its review found a picture that overran the frame. `gen.py` now refuses
|
|
162
|
+
a script that does not show every picture. The other #39 session's
|
|
163
|
+
comparator chose this version as the base and its disk extras were
|
|
164
|
+
ported.
|
|
165
|
+
|
|
166
|
+
**Harness: `make released`, and the keypad joystick on `make run` (#39).**
|
|
167
|
+
The starters are verified with a patched Oscar64 (#25) while a downstream
|
|
168
|
+
agent has a release. `make released OSCAR64_RELEASED=<path>` builds the
|
|
169
|
+
autopilot program with that compiler and grades its PAL and NTSC shots
|
|
170
|
+
with the starter's own `expect.json`. On v1.32.273 it found the platformer
|
|
171
|
+
graded 7 of 23: `surface_at` inlined into `surface_walk` reads the slope
|
|
172
|
+
table with a stale X (listings on #30; `__noinline` passes 23 of 23).
|
|
173
|
+
action-puzzle graded 41 of 41. `make run` now passes `-joydev2 1`, so the
|
|
174
|
+
numeric keypad is joystick 2.
|
|
175
|
+
|
|
176
|
+
**Issue #39: one harness, and the briefing names the starter.** Two
|
|
177
|
+
sessions built #39 in parallel; the maintainer asked for one harness, the
|
|
178
|
+
best of both. Main's harness stays; four #42 items from the other build
|
|
179
|
+
are now in it:
|
|
180
|
+
- text and meter checks take `"dy"` (0-7 pixels) for a panel under a
|
|
181
|
+
scrolled playfield, which the YSCROLL-3 grid could not read;
|
|
182
|
+
- with `SHOT_DISK = 1` each headless run gets its own copy of the D64,
|
|
183
|
+
since VICE writes a save back into the image and the next run then
|
|
184
|
+
started from another disk (hello: two shots byte-identical, the release
|
|
185
|
+
D64 unchanged);
|
|
186
|
+
- `make zp` lists the zero page a build's C touches, from Oscar64's
|
|
187
|
+
listing. The pages said Oscar64 owns `$02`-`$52`; its temporaries run
|
|
188
|
+
from `$43` up by each function's temp count, and hello reaches `$55`,
|
|
189
|
+
platformer `$5B`, shmup-vertical `$5D`. hello's claim `$02`-`$52` failed
|
|
190
|
+
`make claims` (309 stores to `$53`-`$55`, KERNAL IRQ undeclared); it is
|
|
191
|
+
now `$02`-`$55` with `--kernal IRQ` and passes;
|
|
192
|
+
- `check.py` finds the character ROM in the repo's headless VICE, the
|
|
193
|
+
only copy on a CI runner.
|
|
194
|
+
|
|
195
|
+
A `**Starter:**` line under an archetype becomes the Archetype's
|
|
196
|
+
`starter` property (schema 31). `c64_game_briefing` and
|
|
197
|
+
`c64_demo_briefing` return it as `archetype.starter` and print the
|
|
198
|
+
`npm run new-project` command (tools 2.3.0: an added output field). A
|
|
199
|
+
test fails when a page names a starter with no Makefile and expect.json.
|
|
200
|
+
Lines for vertical_shmup, scrolling_platformer and puzzle.
|
|
201
|
+
|
|
202
|
+
`mixed_sprite_char_actors` had a measured Cost line and no
|
|
203
|
+
`**Cost measured on:**` line, so `plan-budget` printed "recipe not
|
|
204
|
+
stated"; it names `oscar64-mixed-fighters` now.
|
|
205
|
+
|
|
206
|
+
**Issue #39: the `shmup-vertical` starter.** It is a vertical shooter:
|
|
207
|
+
- Oscar64 game logic, with a KickAssembler IRQ chain, panel split,
|
|
208
|
+
multiplexer, row copy and music player;
|
|
209
|
+
- the playfield scrolls through all eight YSCROLL phases above a fixed
|
|
210
|
+
panel;
|
|
211
|
+
- waves on paths, character bullets, hitboxes per sprite frame, effects
|
|
212
|
+
on voice 3, and a disk high score.
|
|
213
|
+
|
|
214
|
+
Measured in VICE x64sc 3.10:
|
|
215
|
+
- worst 12,472 / typical 7,103 cycles on PAL; 12,721 / 7,293 on NTSC;
|
|
216
|
+
- the staged heaviest frame (`make stage`) is 14,073 PAL / 14,740 NTSC;
|
|
217
|
+
- `make phases` compares the panel at all eight phases.
|
|
218
|
+
|
|
219
|
+
Its review found that sprites on badlines during KERNAL serial I/O hang
|
|
220
|
+
a save in VICE (#43).
|
|
221
|
+
|
|
222
|
+
**Candidate list, batch 17, two of four: the tech-tech wobbler and DYSP,
|
|
223
|
+
from fixed designs with measured write-cycle sweeps (data 764).** The
|
|
224
|
+
tech-tech wobbler: a badline forced on every line of a six-row logo band
|
|
225
|
+
after the cycle-14 RC check, so the VIC refetches the video matrix each
|
|
226
|
+
line from whichever of eight pre-shifted screens `$D018` names, plus
|
|
227
|
+
XSCROLL for the remainder; the logo's left edge moves 62 pixels across
|
|
228
|
+
the band exactly as the sine table says, on both models; the sweep over
|
|
229
|
+
five write placements shows the one-early case resetting RC on every
|
|
230
|
+
line and the late cases losing one cell per cycle; the FLI-bug strip's
|
|
231
|
+
three cells and their colour are tabled; the XSCROLL-only control swings
|
|
232
|
+
seven pixels; 3,405 cycles a frame for the band. DYSP: four sprites at
|
|
233
|
+
different heights inside the opened right side border, each on its own
|
|
234
|
+
sine, with the border-opening write timed per line from a table indexed
|
|
235
|
+
by the SET of sprites active on that line; the border stays open on all
|
|
236
|
+
150 band lines and every write lands on the same cycle whatever the set.
|
|
237
|
+
A table indexed by the COUNT of active sprites cannot do it, measured:
|
|
238
|
+
two cycles a sprite closes the border from the first line with a
|
|
239
|
+
non-zero sprite alone, three and four cycles close it earlier, and the
|
|
240
|
+
plain side-border timing closes all 150 lines. Pins byte-identical on two
|
|
241
|
+
runs per model, both reproduced by reviewers who also confirmed the
|
|
242
|
+
effect in their own pictures. Linecrunch and Kefrens bars, the other two
|
|
243
|
+
of the batch, stalled six times each on the workflow's watchdog and are
|
|
244
|
+
being rebuilt as standalone runs.
|
|
245
|
+
|
|
246
|
+
**Issue #39: the `platformer` starter.** It is a side-scrolling game in
|
|
247
|
+
Oscar64 with a KickAssembler part:
|
|
248
|
+
- a 2,048 px tile level with three screen pages;
|
|
249
|
+
- the next page is prepared five rows a frame and flipped in the
|
|
250
|
+
vertical blank;
|
|
251
|
+
- slopes, ledges and 8.8 jumps;
|
|
252
|
+
- walkers and hoppers wake in an activation window;
|
|
253
|
+
- a HUD under a raster split, and a tune.
|
|
254
|
+
|
|
255
|
+
Measured in VICE x64sc 3.10:
|
|
256
|
+
- worst frame 12,564 / typical 7,042 cycles on PAL; 12,991 / 7,443 on
|
|
257
|
+
NTSC;
|
|
258
|
+
- `make tearcheck` compares mid-play shots with the level and catches a
|
|
259
|
+
torn build.
|
|
260
|
+
|
|
261
|
+
Its review found Oscar64 fault 7 (#30; now in CLAUDE.md and
|
|
262
|
+
`oscar64-reference`). The harness also changed:
|
|
263
|
+
- claims-watch now recognises a JSR push logged after an IRQ entry;
|
|
264
|
+
- the meter finds its median by selection, not by sorting.
|
|
265
|
+
|
|
266
|
+
**Issue #39: the `action-puzzle` starter, CAVE RUN.** It is a Boulder
|
|
267
|
+
Dash-style game in Oscar64:
|
|
268
|
+
- the cave scan runs a quarter per frame;
|
|
269
|
+
- two RLE caves are decoded between levels;
|
|
270
|
+
- enemies follow walls;
|
|
271
|
+
- a two-voice tune plays, with effects on voice 3;
|
|
272
|
+
- a high-score table is saved to drive 8.
|
|
273
|
+
|
|
274
|
+
Measured in VICE x64sc 3.10:
|
|
275
|
+
- worst frame 10,033 cycles and typical 6,340 on PAL; 10,292 and 6,598
|
|
276
|
+
on NTSC;
|
|
277
|
+
- `make disktest` saves twice under true 1541 emulation, then cold-boots
|
|
278
|
+
and loads the table back, on PAL and NTSC;
|
|
279
|
+
- `make joy` with `tools/drive.py` plays the normal build headless.
|
|
280
|
+
|
|
281
|
+
**Candidate list, batch 16: four items from fixed designs, each a
|
|
282
|
+
technique entry and a pinned KickAssembler recipe (data 763).** The
|
|
283
|
+
sprites-only screen mode: the display enable bit held clear through line
|
|
284
|
+
48 so no badline occurs all frame, set for line 51 so the vertical
|
|
285
|
+
border flip-flop resets, and the select bit toggled around line 251 so
|
|
286
|
+
it never sets again; eight sprites drawn at every height from line 8 to
|
|
287
|
+
the frame wrap, a free-CPU meter reading 904 iterations of a 20-cycle
|
|
288
|
+
loop per PAL frame against 847 with a normal display (the badline and
|
|
289
|
+
border cost by subtraction), the closed-border control hiding three
|
|
290
|
+
sprites and the display-off-only control showing none. BASIC ROM
|
|
291
|
+
floating-point routines called from machine code, every entry point
|
|
292
|
+
read from the 901226-01 ROM image with the monitor before it was used:
|
|
293
|
+
square root of two, 355 over 113, 0.1 plus 0.2 and the five bytes of
|
|
294
|
+
one tenth printed and compared against asserted strings, FMULT 1,079
|
|
295
|
+
cycles, FDIV 2,409, FSQR 43,752 and FOUT 7,412 with the display off, the
|
|
296
|
+
zero-page bytes the sequence changes listed, and the same calls with
|
|
297
|
+
BASIC banked out as the control. Depth-sorted sprite vector balls: eight
|
|
298
|
+
balls on a tilted ring, a single bubble pass per frame assigning sprite
|
|
299
|
+
numbers by depth so the hardware's fixed priority draws the nearer ball
|
|
300
|
+
on top (1,318 cycles a frame, the order unsorted only on the first six
|
|
301
|
+
frames), and a control without the sort drawing the farther ball over
|
|
302
|
+
the nearer one at the same overlap. Shade bobs: a blob adding one shade
|
|
303
|
+
step to a colour-RAM shade buffer under a luminance-ordered palette with
|
|
304
|
+
a decay pass every fourth frame, 590 cycles for the add, 26,514 for the
|
|
305
|
+
decay pass (over a frame, so it cannot fit the blank), and the buffer
|
|
306
|
+
dumped from memory matching colour RAM through the palette in all 1,000
|
|
307
|
+
cells. Eight pins byte-identical on two runs per model, each reproduced
|
|
308
|
+
by a reviewer from the page listing.
|
|
309
|
+
|
|
310
|
+
**The pseudo-3D road, with its per-line shift measured to work (data
|
|
311
|
+
762).** A coarse layer of thirteen multicolour character rows redrawn in
|
|
312
|
+
the vertical blank from a Z table and an 8.8 fixed-point centre
|
|
313
|
+
accumulator, and a fine layer that writes one `$D016` value per road
|
|
314
|
+
raster line from a cycle-locked loop entered by the double-IRQ stable
|
|
315
|
+
raster method, with the write at cycle 11 of each line, a 23-cycle
|
|
316
|
+
iteration on badline rows in place of 63, and separate PAL and NTSC loops
|
|
317
|
+
chosen by region detection at boot. The first build's fine layer had no
|
|
318
|
+
effect because a spin-wait put the writes at cycles 20 to 28, past the
|
|
319
|
+
latch; the recipe records that and the fix. Measured: coarse redraw 6,332
|
|
320
|
+
cycles PAL and 6,162 NTSC, fine chain 6,523 and 6,729; the kerb's left
|
|
321
|
+
edge in the pinned picture moves by one to seven pixels between adjacent
|
|
322
|
+
lines where the first build moved only at row boundaries; rows seven and
|
|
323
|
+
eight of the road now carry their own scroll values. Pinned on both
|
|
324
|
+
models. The page says what one scroll value per line cannot do, that the
|
|
325
|
+
grass is not cleared per frame, and that the geometry is this recipe's,
|
|
326
|
+
not a game's.
|
|
327
|
+
|
|
328
|
+
**Issue #38: a game brief routes to its archetype (data 761, schema 30,
|
|
329
|
+
tools 2.2.0, package 0.15.0).** `c64_game_briefing` with no `archetype`
|
|
330
|
+
used to run as a demo plan with a "Demo Briefing" heading. For a Spy
|
|
331
|
+
Hunter brief it proposed horizontal scrolls and RAM-banking techniques
|
|
332
|
+
("enemy cars ram"), and it missed the multiplexer, the hitboxes and
|
|
333
|
+
`vehicle_control`.
|
|
334
|
+
|
|
335
|
+
Each game archetype now has a `**Brief words:**` line
|
|
336
|
+
(`Archetype.brief_words`). A brief routes to the archetype whose words it
|
|
337
|
+
contains most; a tie routes nowhere. `vertical_shmup`'s fingerprint was
|
|
338
|
+
`sprite_multiplex_24` and `raster_bars`; it is now the panel split, the
|
|
339
|
+
game multiplexer, hitboxes and the wave director.
|
|
340
|
+
|
|
341
|
+
Five faults in discovery are fixed:
|
|
342
|
+
- techniques that match no word of the brief were proposed on their
|
|
343
|
+
recipe bonus alone;
|
|
344
|
+
- stop words matched name and title words;
|
|
345
|
+
- the verb "ram" matched the acronym RAM;
|
|
346
|
+
- H3 vector hits lost their technique name;
|
|
347
|
+
- a horizontal technique was proposed for a vertical brief.
|
|
348
|
+
|
|
349
|
+
Output gains an optional `archetype.inferred_from`. Run `ingest:clean`
|
|
350
|
+
after updating.
|
|
351
|
+
|
|
352
|
+
**Issue #39, part H: a real template harness (data 760).** The two
|
|
353
|
+
starters in `templates/` were stubs. The game starter's KickAssembler
|
|
354
|
+
step was skipped even with a working assembler, and when it did run it
|
|
355
|
+
fed a `.prg` to Oscar64 as source. Neither starter had a headless run, a
|
|
356
|
+
check, an NTSC run or a measured frame.
|
|
357
|
+
|
|
358
|
+
`templates/_harness/` now gives every starter these targets:
|
|
359
|
+
- `make`, which links KickAssembler code into Oscar64 through a
|
|
360
|
+
generated header;
|
|
361
|
+
- `make shot check`, headless on PAL and NTSC with the autopilot,
|
|
362
|
+
grading the pictures against `expect.json`;
|
|
363
|
+
- `make selftest`, which proves the check fails on a faulted build;
|
|
364
|
+
- `make disk` and `make claims`;
|
|
365
|
+
- a frame meter on CIA2 timer A, printing the worst frame and the
|
|
366
|
+
median frame on screen;
|
|
367
|
+
- a plan gate: no build and no write under `src/` until `PLAN.md` holds
|
|
368
|
+
the real `check-compatibility` and `plan-budget` output.
|
|
369
|
+
|
|
370
|
+
There are two minimal starters, `hello` (C plus asm) and `hello-kick`.
|
|
371
|
+
`npm run new-project` makes a working project outside the repo, and
|
|
372
|
+
`npm run verify:templates` runs every starter. The loop is explained in
|
|
373
|
+
`docs/workflow/agent-harness.md`. The per-archetype starters follow.
|
|
374
|
+
|
|
375
|
+
**Issue #38: vehicle control, car contact and lane-pursuit AI (data
|
|
376
|
+
759).** There are three new techniques in `techniques/logic.md`:
|
|
377
|
+
`vehicle_control`, `car_contact_response` and `lane_pursuit_ai`. Each has
|
|
378
|
+
an Oscar64 recipe (`vehicle-control`, `car-contact`, `lane-pursuit`)
|
|
379
|
+
that matches a Python model frame by frame and is pinned on PAL and
|
|
380
|
+
NTSC.
|
|
381
|
+
|
|
382
|
+
Review changed code on each:
|
|
383
|
+
- `vehicle_control`: holding the throttle on the verge barely slowed
|
|
384
|
+
the car, so acceleration now stops at the surface limit.
|
|
385
|
+
- `car_contact_response`: a truck scene now exercises the cooling rule
|
|
386
|
+
and the truck's share of the push.
|
|
387
|
+
- `lane_pursuit_ai`: two fork rules were measured and dropped. When
|
|
388
|
+
the road splits, pursuers take the other channel in 375 of 452
|
|
389
|
+
car-frames, and the page says why.
|
|
390
|
+
|
|
391
|
+
Oscar64 fault 6 is in CLAUDE.md and `toolchains/oscar64-reference.md`,
|
|
392
|
+
with its repro on #30. `soft_scroll_v` lists the vehicle-control
|
|
393
|
+
recipe.
|
|
394
|
+
|
|
395
|
+
**Issue #22, steps 4 to 6: game designs, machine variants and the
|
|
396
|
+
claims watch; #36 decided (data 758, schema 29, tools 2.1.0, package
|
|
397
|
+
0.14.0).** One bump over main's data 757, schema 27, tools 2.0.0, package
|
|
398
|
+
0.13.0. Two shape changes land together, so the schema moves two: 28 is
|
|
399
|
+
GameDesign, 29 is MachineVariant. Step 6 changes seed values, not shape.
|
|
400
|
+
Tools 2.1.0 is a minor: every change to the surface is additive (a new
|
|
401
|
+
optional input, new output fields, and `position`, a field new in this
|
|
402
|
+
release, with a value no shipped consumer has seen). The package moves
|
|
403
|
+
with the tools minor.
|
|
404
|
+
|
|
405
|
+
GameDesign (schema 28). A new doc type, `docs/game-design/designs/*.md`
|
|
406
|
+
(`CONVENTIONS-game-designs.md`), makes a whole game a node: the archetype
|
|
407
|
+
it is an instance of (`INSTANCE_OF`), the recipe that builds it
|
|
408
|
+
(`REALISED_BY`), the techniques it runs in each phase (`COMPOSES`, with a
|
|
409
|
+
`phase` of play, init or transition) and what its frame measured
|
|
410
|
+
(`**Measured frame:**`, stored as `measured`). Three pages, one per
|
|
411
|
+
scaffold; the phases were read from each listing's `main()`, not its
|
|
412
|
+
frontmatter. `c64_plan_budget` takes `design` (CLI `--design`): the
|
|
413
|
+
design's members are budgeted by phase, and each measured frame is set
|
|
414
|
+
beside the prediction for its phase and region, with where it falls and
|
|
415
|
+
which members had no figure. `techniques` is now optional. `c64_game_briefing`
|
|
416
|
+
lists the resolved archetype's designs in `designs[]`.
|
|
417
|
+
|
|
418
|
+
What the validation showed, play phase, scratch graph:
|
|
419
|
+
|
|
420
|
+
| Design | Predicted (low-high + badlines) | Measured worst, PAL / NTSC | Members with no figure |
|
|
421
|
+
|---|---|---|---|
|
|
422
|
+
| `platformer_scaffold_oscar64` | 4,477-4,685 + 1,075 | 8,693 / 10,287, above by 2,933 / 4,527 | 5 |
|
|
423
|
+
| `falling_blocks_oscar64` | 5,902 + 1,075 | 6,276 / 6,491, within_incomplete | 4 |
|
|
424
|
+
| `simple_shmup_oscar64` | 5,628 + 1,075 | not timed | 1 |
|
|
425
|
+
|
|
426
|
+
Re-run on a scratch graph of the merged tree; the figures held. The
|
|
427
|
+
platformer's typical PAL frame (4,966, one frame's reading) lies within
|
|
428
|
+
its range. The falling-block agreement is partial: its one large
|
|
429
|
+
figure, `falling_block_rules`' 5,888, is a constructed upper bound, and
|
|
430
|
+
the render has no Cost line.
|
|
431
|
+
|
|
432
|
+
Corrections found on the way: the `falling-blocks` frontmatter named four
|
|
433
|
+
of the seven techniques its listing runs; the #22 design put
|
|
434
|
+
`tile_map_render` in the platformer's play phase, where it runs once at
|
|
435
|
+
init; the platformer's timer is CIA1 timer B, not CIA2.
|
|
436
|
+
|
|
437
|
+
MachineVariant (schema 29). Seven seeds, one per VICE `-model` word the
|
|
438
|
+
harness needs or the pages name (`c64`, `c64c`, `c64old`, `ntsc`,
|
|
439
|
+
`newntsc`, `oldntsc`, `drean`), with their chips, line length and lines.
|
|
440
|
+
`VERIFIED_ON` (Recipe to MachineVariant) is rebuilt after every ingest
|
|
441
|
+
from `docs/recipes/runs.json`, as `verify:recipes` runs each page, and
|
|
442
|
+
only where the committed screenshot exists: 242 edges on a scratch graph
|
|
443
|
+
of this merged tree (data 757), 0 problems; 131 recipes run on the c64c. `c64_recipe_lookup`
|
|
444
|
+
returns `verified_on[]`; `c64_recipes_for` takes `verified_on` (a variant
|
|
445
|
+
or PAL / NTSC). The R56A and the Drean are variants, not Regions, which
|
|
446
|
+
answers #8's question.
|
|
447
|
+
|
|
448
|
+
Review fixes, steps 4 and 5. `verified_on[]` applies a run's chip flags:
|
|
449
|
+
`cia-revision-detect` runs the c64c with `-ciamodel 0`, so its CIA is the
|
|
450
|
+
6526, and `overrides[]` says so (it listed the c64c's 8521).
|
|
451
|
+
`c64_plan_budget` gives `within_incomplete` when the measured worst lies
|
|
452
|
+
inside the range while members have no figure; it said `within`. A typical
|
|
453
|
+
frame's excess is a share of the typical, not of the worst. `simple-shmup`
|
|
454
|
+
is an instance of `vertical_shmup` only (the listing scrolls vertically).
|
|
455
|
+
A runs.json page with `skip` (main's tape-turbo-loader) gets no
|
|
456
|
+
`VERIFIED_ON` edge; it was reported as a missing screenshot.
|
|
457
|
+
|
|
458
|
+
Claims watch (step 6). `scripts/claims-watch.ts` runs a PRG in the
|
|
459
|
+
windowless x64sc with a store trace and judges every store against the
|
|
460
|
+
claims its techniques declare, their REQUIRES closure, a harness list and
|
|
461
|
+
the KERNAL routines it names. Exit 1 on a store outside them. Validated on
|
|
462
|
+
four recipes: each fails on its page's declarations alone and passes once
|
|
463
|
+
its RAM, harness timers and missing units are declared; a multiplexer
|
|
464
|
+
with `sta $d40b` and `sta $fb` added fails on exactly those two stores.
|
|
465
|
+
The CIA timer and TOD units now own their bit of the interrupt control
|
|
466
|
+
register ($DC0D/$DD0D bits 0, 1, 2). `vice-reference.md` says how to run
|
|
467
|
+
it.
|
|
468
|
+
|
|
469
|
+
#36: VICE's default machine is the `c64c` configuration (VIC-II 8565, SID
|
|
470
|
+
8580, CIA 8521), not the 6569 that `vice-reference.md`, `pal-ntsc-detect.md`,
|
|
471
|
+
CLAUDE.md, the README and twenty page statements said. `x64sc -default
|
|
472
|
+
-dumpconfig` is identical to `-model c64c`. Re-run for this entry:
|
|
473
|
+
`cia-revision-detect` with no `-ciamodel` reads the new CIA on the default,
|
|
474
|
+
`c64c` and `newntsc`, the old one on `c64` and `ntsc`; `palette-cells`
|
|
475
|
+
under `-model c64` differs from the default in eleven of sixteen entries.
|
|
476
|
+
The maintainer's decision: keep the default, say c64c. No screenshot is
|
|
477
|
+
re-baselined; every page that called the VICE PAL run a 6569 now names the
|
|
478
|
+
C64C with a clause saying what it said; `-model c64` is the check for the
|
|
479
|
+
older machine.
|
|
480
|
+
|
|
481
|
+
**Candidate list, Tier B batch 15: four more items from fixed designs,
|
|
482
|
+
each a technique entry and a pinned KickAssembler recipe (data 757).**
|
|
483
|
+
A sprite text scroller in the opened lower border: eight glyph sprites
|
|
484
|
+
at Y 254 under a border opened by the top-and-bottom recipe's method,
|
|
485
|
+
829 cycles a typical frame and 1,586 on a hand-off frame, every sprite
|
|
486
|
+
row inside the PAL frame and the control build with the border left
|
|
487
|
+
closed showing no sprite pixel below line 251. A twister: a 64-pixel
|
|
488
|
+
column whose four faces come from one sine, its 64 phase images built at
|
|
489
|
+
assembly time so the frame loop is a 128-line copy of 13,001 cycles
|
|
490
|
+
blanked, the pinned edges matching the edge table at three rows and a
|
|
491
|
+
straight control with one row pattern on every line. The `$D017` sprite
|
|
492
|
+
stretcher, which this KB had marked unverified, reproduced in VICE: a
|
|
493
|
+
setting write on any cycle from 48 to 55 (cleared four cycles earlier)
|
|
494
|
+
makes a 21-row sprite 91 lines tall over 81 toggled lines, each row held
|
|
495
|
+
for eight lines, while cycle 56 gives 24 lines and cycles 57 to 62 give
|
|
496
|
+
44, 50, 47 and 94; the fifteen-build sweep is on the page, the pinned
|
|
497
|
+
build is cycle 52, and the control with the stores aimed at RAM is the
|
|
498
|
+
plain 21 lines. An LFSR-ordered screen dissolve to finish the transitions
|
|
499
|
+
family: a maximal 10-bit register visiting each of 1,000 cells once, 20
|
|
500
|
+
cells a frame, 3,203 cycles on the worst frame, half the cells landed at
|
|
501
|
+
frame 25 and the last on frame 50, beside a sequential control that is a
|
|
502
|
+
wipe. Eight pins byte-identical on two runs per model, each reproduced
|
|
503
|
+
by a reviewer from the page listing.
|
|
504
|
+
|
|
505
|
+
**Candidate list, Tier B batch 14: four demo effects, each a technique
|
|
506
|
+
entry and a pinned KickAssembler recipe (data 756).** Multicolour
|
|
507
|
+
interlace: two multicolour bitmaps in two VIC banks alternated at the
|
|
508
|
+
frame with a one-hires-pixel shift on the odd frame, the diagonal one
|
|
509
|
+
pixel further right in the second field at every row measured, a PIL
|
|
510
|
+
average of the two fields showing four distinct columns per pixel pair
|
|
511
|
+
where one field shows two, and a frame loop of 34 or 32 cycles (the
|
|
512
|
+
brief's single-bank layout did not fit, 18,000 bytes into 16,384, and the
|
|
513
|
+
page says so). Dot flag: a 16 by 8 grid on two sines plotted and erased
|
|
514
|
+
through the hires plot, 119 cycles a dot, 15,233 a frame blanked and up
|
|
515
|
+
to 16,098 with the display on, exactly 128 lit pixels in the pinned
|
|
516
|
+
picture and 3,570 without the erase pass. Fire: a colour-RAM heat map
|
|
517
|
+
over a solid glyph with a luminance-ordered palette, 53,479 cycles for
|
|
518
|
+
the whole screen and 27,301 for the larger half, so the screen refreshes
|
|
519
|
+
every four frames; the pinned picture's colour census is on the page.
|
|
520
|
+
DYPP: a text scroller of eight sprites, each column on its own sine,
|
|
521
|
+
1,147 cycles a frame for the position update and 715 for a character
|
|
522
|
+
re-render, the two sprites past X 255 drawn at 14 and 62 instead of 270
|
|
523
|
+
and 318 when the high-bit write is left out. Eight pins, byte-identical
|
|
524
|
+
on two runs per model, each reproduced by a reviewer from the page's own
|
|
525
|
+
listing; the three new anchors went on the pitfalls whose mechanism the
|
|
526
|
+
code meets.
|
|
527
|
+
|
|
528
|
+
**The isometric tile engine, built from a fixed specification (data
|
|
529
|
+
756).** Two earlier attempts stalled on the open design; this one was
|
|
530
|
+
handed the map, the projection, the draw order and the depth rule and
|
|
531
|
+
built exactly that: an 8 by 8 room of 2:1 diamond tiles four characters
|
|
532
|
+
wide, blocks one and two tiles tall drawn back to front so nearer cells
|
|
533
|
+
overdraw, a hardware-sprite player whose one priority bit is set when a
|
|
534
|
+
block in front of it overlaps its character box, and a scripted walk.
|
|
535
|
+
Measured: a full room redraw of 42,034 cycles, one block of 527, the
|
|
536
|
+
depth bit set at three of the six positions (the specification predicted
|
|
537
|
+
one; the recipe says why the character box catches two more), and a
|
|
538
|
+
negative control with the painter's order reversed that fails the
|
|
539
|
+
verdict. Pinned on both models. The entry says what one priority bit
|
|
540
|
+
cannot do.
|
|
541
|
+
|
|
542
|
+
**Four more measured pitfalls, and a logic pitfall page (data 755).** A
|
|
543
|
+
one-byte breadth-first distance map that uses 255 for "unreached" wraps
|
|
544
|
+
on a path longer than 254 cells: on a serpentine corridor the live map
|
|
545
|
+
read 1, 0, 1, 2 across true distances 255 to 258, a chaser at 254 walked
|
|
546
|
+
two cells away from the player and every far chaser gathered on a false
|
|
547
|
+
zero; saturating at 254 and a two-byte map are both measured as fixes,
|
|
548
|
+
and the recipe's own maze, whose longest path is 76, cannot show it.
|
|
549
|
+
Asserting ATN from the C64 pulls the drive's DATA line low through the
|
|
550
|
+
1541's ATNA gate whatever a resident drive program writes: DATA IN read
|
|
551
|
+
released with ATN released and low with it asserted under ATNA clear,
|
|
552
|
+
the mirror image under ATNA set, controls with DATA OUT held low, the
|
|
553
|
+
drive's own port read at each phase, a drive that leaves interrupts
|
|
554
|
+
enabled behaving the same, and the fix, a drive loop that copies ATN IN
|
|
555
|
+
into ATNA every pass, leaving DATA free in all three phases. Sprite
|
|
556
|
+
registers persist across a game-state change: a play state that enables
|
|
557
|
+
only its own sprite inherited the title's pointer, expansion, multicolour
|
|
558
|
+
and a latched collision on both models, a game-over screen kept the
|
|
559
|
+
player across its banner, and a per-state VIC baseline routine clears all
|
|
560
|
+
of it. A CharPad `.ctm` embedded whole puts its header on glyph 0 and
|
|
561
|
+
shifts every glyph by 18 bytes on a version 8 file, identically under
|
|
562
|
+
Oscar64 and KickAssembler; the offset-and-length forms of both embeds and
|
|
563
|
+
the raw export are the fixes. Follow-ups from those measurements: the IEC
|
|
564
|
+
page's VIA table now says that ATN IN reads 1 when ATN is asserted, and
|
|
565
|
+
that its snapshot rows were taken under ATN; the drive-upload technique
|
|
566
|
+
records a 34-byte `M-W` as measured; the pitfall conventions list the
|
|
567
|
+
maths and logic categories; the text-mode render page's intro no longer
|
|
568
|
+
numbers its entries.
|
|
569
|
+
|
|
570
|
+
**The deferred raster anchors (data 754).** `badline_cycle_loss` gains
|
|
571
|
+
sprite_color_swap_mid_line, solid_vector_3d, mode7_lookalike and
|
|
572
|
+
vsp_glitch, and `raster_irq_first_line_jitter` gains mode7_lookalike and
|
|
573
|
+
vsp_glitch, each on the sentence of the technique that meets the
|
|
574
|
+
mechanism (a colour split placed by write cycle inside the badline's
|
|
575
|
+
stolen span; a filler that budgets forty cycles a badline row; a
|
|
576
|
+
per-line register chain with no stabilisation in its budget; a trick
|
|
577
|
+
whose write cycle is the effect). The techniques still without a pitfall
|
|
578
|
+
are the two loader notes and three logic entries the triage judged to
|
|
579
|
+
need none. The two-bit fast loader candidate was attempted and not
|
|
580
|
+
landed: its transfer never ran, so its pages were not merged and the
|
|
581
|
+
attempt is kept as a private experiment record.
|
|
582
|
+
|
|
583
|
+
**Every technique a pitfall can reach now has one, bar seven (data
|
|
584
|
+
753).** A read-only triage of the techniques no pitfall named sorted each
|
|
585
|
+
into an existing pitfall its text meets, a new measured pitfall, or none
|
|
586
|
+
with the reason. Eighteen anchors were added to existing entries on seven
|
|
587
|
+
pitfall pages, each checked against the technique sentence that meets the
|
|
588
|
+
mechanism, and `ram_under_rom_traps` gained cartridge ROM at `$8000` to
|
|
589
|
+
`$BFFF` as a fourth ROM-mapped range. Five new pitfall entries, each
|
|
590
|
+
measured first: a bank or mode write executed from the cartridge window
|
|
591
|
+
it switches hands the very next opcode fetch to the new bank (traced at
|
|
592
|
+
the cycle; the fix runs the switch from RAM or makes the switch site
|
|
593
|
+
identical in every bank); setting ECM while MCM is still on selects an
|
|
594
|
+
invalid mode that draws the whole window black while sprite collisions
|
|
595
|
+
and priority still work against the invisible field, on both models,
|
|
596
|
+
with ECM plus BMM tabled beside it; a new maths pitfall page with a sine
|
|
597
|
+
table of amplitude 128 that peaks at 256 and wraps seven entries to zero
|
|
598
|
+
under both toolchains, and a shift-and-subtract divide whose missing
|
|
599
|
+
carry guard is a 16/8 fault only, wrong for divisors of `$81` and above
|
|
600
|
+
(24,400 misses over the recipe's sweep) while the 8/8 and 16/16 loops
|
|
601
|
+
pass with the guard deleted; and Oscar64's assembler optimiser at `-O2`
|
|
602
|
+
rewriting a non-volatile inline block and duplicating it, so a store into
|
|
603
|
+
an operand byte lands in a copy that never runs (the executed and the
|
|
604
|
+
dead listings quoted; `volatile`, `#pragma optimize(noasm)` and a
|
|
605
|
+
data-patch form each measured as fixes). The divide measurement
|
|
606
|
+
corrected the technique page and the divide-check recipe, which had said
|
|
607
|
+
the guardless loop fails for divisors of `$80` or `$8000` and above; the
|
|
608
|
+
multiply technique's account of what the mis-optimised routine computes
|
|
609
|
+
was corrected from the executed listing. The seven techniques still
|
|
610
|
+
without an anchor are two loader notes and three logic entries the triage
|
|
611
|
+
judged to need none, and two whose anchors wait on the raster pitfall
|
|
612
|
+
page another agent is writing.
|
|
613
|
+
|
|
614
|
+
**Four pitfalls met while landing the night's recipes, each measured
|
|
615
|
+
before it was written (data 752).** A VIC colour register reads back as
|
|
616
|
+
the colour plus 240, so `IF PEEK(53280)=2` after `POKE 53280,2` is
|
|
617
|
+
silently false: every register from `$D020` to `$D02E` measured 0 to 15
|
|
618
|
+
on both models, with the other unused VIC bits (`$D016`, `$D018`,
|
|
619
|
+
`$D019`, `$D01A`) tabled beside them and the audited hardware page
|
|
620
|
+
agreeing on each. A self-extracting decruncher that runs from the zero
|
|
621
|
+
page leaves the KERNAL's variables full of its own code: Dali `--small`
|
|
622
|
+
and bitfire's stub both silenced a payload that prints through CHROUT,
|
|
623
|
+
and the zero-page diff at entry names the bytes, `$9A` set to the RS-232
|
|
624
|
+
device under one and to a serial device under the other, the editor's
|
|
625
|
+
line pointer at `$4CBA` under the second; Dali's standard stub and
|
|
626
|
+
pucrunch save what they clobber, and a prologue that banks the KERNAL in
|
|
627
|
+
and calls IOINIT and CINT prints under both. A colour RAM index of 1,024
|
|
628
|
+
or more writes CIA1's registers, with the sixteen bytes before and after
|
|
629
|
+
a fill to 1,040 (timer A stopped, the jiffy clock frozen, the port A
|
|
630
|
+
direction register left at the fill value) and the row-by-row fill that
|
|
631
|
+
leaves them untouched; the 24 spare bytes past cell 999 measured as
|
|
632
|
+
nibble RAM. One read of `$DC0D` or `$DD0D` clears every pending flag: a
|
|
633
|
+
FLAG poll took a timer underflow on its way past and the timer's own
|
|
634
|
+
check read `$00`, the copy-into-RAM pattern kept it, and a main-program
|
|
635
|
+
read racing CIA2's NMI lost the interrupt itself at one phase on NTSC
|
|
636
|
+
and on the old CIA model.
|
|
637
|
+
|
|
638
|
+
**Candidate list, Tier B batch 9, two of four (data 751).** A tape
|
|
639
|
+
mastering workflow page: a host writer that turns a PRG into a
|
|
640
|
+
KERNAL-format TAP (the three pulse lengths, the pair rule, the countdowns,
|
|
641
|
+
the two copies and the checksum the formats page measured), which a plain
|
|
642
|
+
LOAD then RUN accepts on both models; a decode-back checker that also
|
|
643
|
+
reads the TAP the KERNAL itself recorded; the turbo route, the turbo
|
|
644
|
+
loader mastered in KERNAL format as the stub with the turbo block
|
|
645
|
+
appended, loading from one image; timings by bisecting the cycle limit
|
|
646
|
+
(a 202-byte payload runs 33 seconds after LOAD on PAL, of which the FOUND
|
|
647
|
+
pause is a third; the KERNAL format costs 18,890 cycles a payload byte,
|
|
648
|
+
the turbo block 7.6 times less for the same 500 bytes); and the finding
|
|
649
|
+
that the jiffy clock is not a tape load timer, since both models printed
|
|
650
|
+
770 jiffies for a load of over thirty seconds. The PSID header
|
|
651
|
+
corrected: the bytes at `$7A` and `$7B` are the second and third SID
|
|
652
|
+
addresses in versions 3 and 4, the flags bits 6 to 9 their models, the
|
|
653
|
+
RSID rules in one paragraph; headers written by hand round-trip, VICE's
|
|
654
|
+
windowless vsid accepts versions 2, 3 and 4 and logs the chip addresses,
|
|
655
|
+
rejects odd or out-of-range addresses as no second SID, reads `$7B` from
|
|
656
|
+
a version-3 file where the document reserves it, and gives every chip the
|
|
657
|
+
first SID's model; a census of the HVSC corpus gave the version counts
|
|
658
|
+
and the address ranges seen. The isometric tile engine and the pseudo-3D
|
|
659
|
+
road did not land: both writers stalled six times on the design, and they
|
|
660
|
+
wait for a fixed specification like the scroller's.
|
|
661
|
+
|
|
662
|
+
**Candidate list, Tier B batch 8 (data 750).** The 1541's VIA registers
|
|
663
|
+
and memory map measured through the command channel and a probe recipe:
|
|
664
|
+
the density bits follow the requested track's zone even when the head
|
|
665
|
+
did not step, the stepper bits move one half-step per write from the
|
|
666
|
+
DOS's routine every 14,848 drive cycles, the motor bit and the
|
|
667
|
+
write-protect sense read as the states say (the latter checked with a
|
|
668
|
+
read-only attach), the LED bit was set only during an auto-initialise,
|
|
669
|
+
byte-ready reaches the CPU only with the port-control register's CA2
|
|
670
|
+
line high, and the first job after power-up does not step. A tape turbo
|
|
671
|
+
loader with a TAP written on the host: one pulse per bit at 256 and 512
|
|
672
|
+
cycles, 321 bytes a second on PAL and 334 on NTSC against the KERNAL's
|
|
673
|
+
own rate, the pulse spread under VICE's default wobble, a 208-cycle bit
|
|
674
|
+
that failed and why, and a timer-read race that mismeasured one pulse in
|
|
675
|
+
sixty until the read was done high, low, high; the recipe cannot be
|
|
676
|
+
pinned by the verifier, which now honours a `"skip"` key in `runs.json`
|
|
677
|
+
with the reason, reports the page as skipped rather than failed, and
|
|
678
|
+
the conventions say so. The CharPad CTM v8 and SpritePad SPD v5 headers
|
|
679
|
+
decoded from the sample files Oscar64 ships and checked against what
|
|
680
|
+
its embed forms produce (v9 read from Oscar64's structures only, not
|
|
681
|
+
measured here); Oscar64's reader checks neither signature nor version,
|
|
682
|
+
so an old v5 file embeds silently and wrongly. The two-bit fast-loader
|
|
683
|
+
transfer did not land: its writer stalled six times on the protocol
|
|
684
|
+
design and runs again alone from a fixed specification.
|
|
685
|
+
|
|
686
|
+
**Candidate list, Tier B batch 7 (data 749).** A cc65 cartridge recipe
|
|
687
|
+
built through the verifier's cartridge path: the linker configuration
|
|
688
|
+
writes the .CRT container itself from a header segment and the result
|
|
689
|
+
is byte-identical to cartconv's, DATA is copied from ROM to RAM at
|
|
690
|
+
start (55 bytes, checksums equal), the runtime from CINT to main costs
|
|
691
|
+
2,281 cycles, and the negative control with DATA left in ROM boots,
|
|
692
|
+
prints nothing and hits a BRK 1,049 cycles into the first print; a
|
|
693
|
+
Cartridge builds section on the cc65 page. The IEC bit timing measured
|
|
694
|
+
from the KERNAL's own port accesses under the monitor: the device-present
|
|
695
|
+
look 1,103 cycles after ATN, a send bit cell of 94 to 96 cycles stretched
|
|
696
|
+
to 136 to 139 by a badline, the listener's EOI acknowledge 539 cycles
|
|
697
|
+
after DATA is released, and the drive's replies as VICE's 1541 gives
|
|
698
|
+
them; the receive-side timer count is `$01FF` not `$0100` because the
|
|
699
|
+
KERNAL writes only timer B's high byte, and the page's older "about
|
|
700
|
+
1,024 cycles" is flagged. `drive_code_upload_and_job_queue` on the
|
|
701
|
+
file-io page with a recipe: 68 bytes uploaded in three M-W commands and
|
|
702
|
+
read back, executed by M-E, a seek job then a read job of track 18
|
|
703
|
+
sector 0 through the queue returning the BAM, a read before any seek
|
|
704
|
+
failing with result `$0B` and a read of track 40 with `$03`, drive-side
|
|
705
|
+
durations by the drive's own clock; a job queue and buffers table on the
|
|
706
|
+
IEC page. A Spindle toolchain page (3.1 built from source with xa65):
|
|
707
|
+
two parts packaged with mkpef and linked with pefchain, the join between
|
|
708
|
+
parts measured at 55 cycles and accounted for instruction by instruction,
|
|
709
|
+
part timings on both models, the D64 layout, and pefchain's page-clash
|
|
710
|
+
warning; the pictures live under docs/figures because the verifier cannot
|
|
711
|
+
boot a prepared disk. Left open: the device-not-present timeout as a
|
|
712
|
+
firing timeout (no run without a responding device could be made under
|
|
713
|
+
VICE); the write, verify, bump and execute job codes; where Spindle's
|
|
714
|
+
drive code lives on the disk.
|
|
715
|
+
|
|
716
|
+
**Candidate list, Tier B batch 6 (data 748).** `basic_extension_wedge`
|
|
717
|
+
on the text page with a KickAssembler recipe: an IGONE wedge that adds
|
|
718
|
+
prefixed commands and falls through to the ROM, exercised after a colon,
|
|
719
|
+
inside IF THEN and on an unknown letter (the ROM's error still appears),
|
|
720
|
+
costing 10.2 cycles a statement on PAL and 10.4 on NTSC against 10 by
|
|
721
|
+
the instruction table; the ROM's own paths through `$0308` and `$0300`
|
|
722
|
+
read from the BASIC image at the addresses the page quotes.
|
|
723
|
+
`lane_depth_engine` on the logic page with an Oscar64 recipe for the
|
|
724
|
+
beat-em-up archetype: Y as depth, an insertion sort over the actors
|
|
725
|
+
setting both draw order and hit order (157 to 269 cycles a frame), a hit
|
|
726
|
+
window in Y and X keyed to the attack's active frames; the whole step
|
|
727
|
+
1,413 cycles at its worst; the technique added to the archetype's
|
|
728
|
+
fingerprint. Sprite priority measured per pixel class in a recipe: a
|
|
729
|
+
multicolour sprite's own bit pair makes no difference to the priority
|
|
730
|
+
bit, the playfield's pattern decides (hires 1 bits and multicolour pairs
|
|
731
|
+
10 and 11 are foreground; 0 bits and pairs 00 and 01 background whatever
|
|
732
|
+
colour they draw in), `$D01F` follows the same classes and ignores the
|
|
733
|
+
priority bit, and sprite order is decided before the playfield; the
|
|
734
|
+
mob_priority entry extended in place, and the VIC-II reference's layer
|
|
735
|
+
diagram, which the measurement contradicts, is reported on the
|
|
736
|
+
hardware-verification issue rather than edited. A unit-testing toolchain
|
|
737
|
+
page with sim6502 as its tool node and a KickAssembler test-driver
|
|
738
|
+
recipe: fourteen cases through a case table with the verdict in `$02FF`,
|
|
739
|
+
the same driver run in sim6502 in 0.12 s of host time against 0.4 s in
|
|
740
|
+
VICE, 64spec assembling unchanged with KickAssembler 5.25, and sim65's
|
|
741
|
+
exit-code channel measured. Left open: the 418-cycle residue between the
|
|
742
|
+
wedge's measured and arithmetic cost; sprite priority with both
|
|
743
|
+
overlapping sprites set; multicolour bitmap and ECM pixel classes.
|
|
744
|
+
|
|
745
|
+
**Candidate list, Tier B batch 5 (data 747).** The GCR encoding on the
|
|
746
|
+
formats page, measured: the sixteen code words derived from a G64 image
|
|
747
|
+
c1541 wrote and confirmed byte for byte against the 1541 ROM's encode
|
|
748
|
+
table at `$F77F` (the F code is `10101`; the writer's own memory said
|
|
749
|
+
otherwise and the ROM corrected it), the header and data block layouts
|
|
750
|
+
decoded with their checksums, the sync and gap as written, the four zone
|
|
751
|
+
track lengths and their bit cells as arithmetic, the zone tables at
|
|
752
|
+
`$FED1` and `$FED7`; the "4 bytes to 5" sentence corrected with a
|
|
753
|
+
clause; c1541 3.10 writes `$A0 $A0` as the header ID while the BAM holds
|
|
754
|
+
the command-line ID, and the drive ROM loads the disk anyway. A cc1541
|
|
755
|
+
toolchain page (4.2 built from source): how the directory-art tricks are
|
|
756
|
+
stored in the entry bytes (a DEL entry is type `$80`, an art line has no
|
|
757
|
+
blocks, a name's first `$A0` closes the quote in the listing), what a
|
|
758
|
+
LIST shows of them, decoded against the character ROM, and interleave and
|
|
759
|
+
placement options measured on the sector chain. `two_word_parser` on the
|
|
760
|
+
text page with an Oscar64 recipe for the text-adventure archetype (ten
|
|
761
|
+
scripted commands through the KERNAL buffer, parse cost 569 to 2,036
|
|
762
|
+
cycles a command, the end state checked), and the technique added to the
|
|
763
|
+
archetype's fingerprint. The .VSF section rewritten from a snapshot the
|
|
764
|
+
emulator wrote: the previous text claimed a 15-byte module header and
|
|
765
|
+
module names the file does not contain; measured, the header is 22 bytes,
|
|
766
|
+
twenty-six modules in a stated order, the 64 KiB RAM at byte 209 in
|
|
767
|
+
address order, colour RAM at offset 761 of the VIC-II module, and two
|
|
768
|
+
runs of the same program differ in 946 bytes of RAM the program never
|
|
769
|
+
wrote. Left open: which ID character c1541 should have written; the
|
|
770
|
+
meaning of the snapshot's unlabelled bytes; LOAD of a DEL entry.
|
|
771
|
+
|
|
772
|
+
**Candidate list, Tier B batch 4 (data 746).** A cartconv toolchain page
|
|
773
|
+
with the .CRT header and chip packets decoded from files cartconv wrote,
|
|
774
|
+
and what each type does when booted in VICE: the generic 8K type ignores a
|
|
775
|
+
bank-register write, Magic Desk switches an 8K bank at `$8000` through
|
|
776
|
+
`$DE00`, Ocean switches the same bank mirrored at `$A000`, and cartconv's
|
|
777
|
+
EasyFlash made from a Magic Desk layout checks clean and does not boot;
|
|
778
|
+
byte `$1A` of the header is the hardware revision, not reserved; a
|
|
779
|
+
two-bank Magic Desk recipe pinned through the verifier's cartridge path;
|
|
780
|
+
KickAssembler has no cartridge directive and Oscar64's three cartridge
|
|
781
|
+
targets are decoded. REL files: the directory entry, the side-sector block
|
|
782
|
+
and the data chain decoded from a disk image the recipe wrote (a one-byte
|
|
783
|
+
write to record 125 of a 254-byte-record file allocates 125 data blocks and
|
|
784
|
+
two side sectors), the P command's byte order, the record padding, and the
|
|
785
|
+
DOS replies for a record that does not fit; the file-io technique's side-
|
|
786
|
+
sector rule corrected. `zx0_lzsa_decrunchers` on the memory-banking page
|
|
787
|
+
beside pucrunch: ZX0 v2.2, bitfire's ZX0 packer, Dali 0.3.5, ZX02 and
|
|
788
|
+
LZSA 1.4.1 built from source; on the two pucrunch inputs Dali's
|
|
789
|
+
self-extractor is 1,041 bytes and 114,369 cycles against Exomizer's 1,103
|
|
790
|
+
and 189,276, and bitfire's 1,035 and 99,422; Dali's small mode and
|
|
791
|
+
bitfire's stub overwrite the KERNAL's zero page and the subject does not
|
|
792
|
+
run or prints nothing, measured; the candidate list credited Dali to the
|
|
793
|
+
wrong author (it is Bitbreaker's). `bfs_distance_map` on the logic page
|
|
794
|
+
with a recipe: one flood serves four chasers, 404 open cells in 115,912
|
|
795
|
+
cycles over fifteen frames at 32 cells a frame, the map equal to a host
|
|
796
|
+
BFS byte for byte, every chaser reaching the player in 145 frames; an
|
|
797
|
+
Oscar64 -O2 fault met on the way (the first inlined call of a
|
|
798
|
+
pointer-walking copy loop) is reported on the gotcha issue. Left open:
|
|
799
|
+
raw-mode decrunch times for the ZX0 family; record lengths 0 and 255; the
|
|
800
|
+
EasyFlash registers on the tool page are the memory-banking page's, not
|
|
801
|
+
measured here.
|
|
802
|
+
|
|
803
|
+
**Tier A, the eight-way scroller (data 745).** `eight_way_scroll_double_buffer`
|
|
804
|
+
on the scroll page with a KickAssembler recipe, after three attempts and
|
|
805
|
+
three reviews. A 64 by 48 tile world through a 40 by 25 window along an
|
|
806
|
+
eight-leg camera path, two screen matrices flipped by `$D018` in the
|
|
807
|
+
blank, the redraw spread over fields in bands of at most seven rows, and
|
|
808
|
+
colour RAM, which cannot be paged, rewritten in four calls after the flip.
|
|
809
|
+
The first design redrew seventeen rows a field from raster 152 and
|
|
810
|
+
overran the field about one apply in four, which stalled the camera and
|
|
811
|
+
showed a whole field of stale colours; its verdict could not see it
|
|
812
|
+
because its checks compared raster numbers inside a field. The shipped
|
|
813
|
+
version caps every band, runs the camera at one pixel every two fields so
|
|
814
|
+
a crossing gap of six fields covers the five-field redraw, and its verdict
|
|
815
|
+
counts late applies, skipped preps and a first colour band finishing after
|
|
816
|
+
row 6's badline, all zero over a full loop on both models. Worst field
|
|
817
|
+
13,111 cycles on PAL and 13,152 on NTSC. Stated plainly on the page and in
|
|
818
|
+
the technique entry: after each tile crossing the rows not yet rewritten
|
|
819
|
+
show the previous position's colours for three displayed fields, about
|
|
820
|
+
one field in four over the path; the pin sits in the clean window. The
|
|
821
|
+
one-pixel-a-frame form is not shipped: on diagonals its crossing gap is
|
|
822
|
+
three fields against the five the redraw needs.
|
|
823
|
+
|
|
824
|
+
**Candidate list, Tier B batch 3 (data 745).** `light_pen_read` on
|
|
825
|
+
the input page with a KickAssembler recipe: the latch, the one trigger a
|
|
826
|
+
frame, the interrupt at 94 cycles through the KERNAL vector and the
|
|
827
|
+
two-pixel conversion checked on synthetic latch values; VICE 3.10's light
|
|
828
|
+
pen never triggers headlessly (no host mouse), and the fire-line route
|
|
829
|
+
through joystick autofire breaks the autostart before the program runs, so
|
|
830
|
+
the resting registers are measured and the moving pen is not, and the page
|
|
831
|
+
says so. A petcat toolchain page: tokenise and de-tokenise measured
|
|
832
|
+
against a hand count of tokens (a four-line stub is 64 bytes), the control
|
|
833
|
+
macros mapped to their PETSCII bytes, the round trip identical apart from
|
|
834
|
+
line-number padding, an unknown keyword accepted silently and failing on
|
|
835
|
+
the machine, upper-case keywords stored as text rather than tokens, and
|
|
836
|
+
the `-w2` against `-w3` difference on one keyword. `pucrunch_decruncher`
|
|
837
|
+
on the memory-banking page: pucrunch 1.14 built from source, its four
|
|
838
|
+
modes and Exomizer 3.1.3b0 measured on the same two inputs for size and
|
|
839
|
+
decrunch time (on a 4,519-byte mixed program pucrunch's default is 1,084
|
|
840
|
+
bytes and 349,505 cycles against Exomizer's 1,103 bytes and 189,276
|
|
841
|
+
cycles), the decruncher's footprint at `$F7` and `$0200`, and the
|
|
842
|
+
candidate list's claim that pucrunch decrunches faster not borne out on
|
|
843
|
+
either input. `text_window_and_menu` on the text page with an Oscar64
|
|
844
|
+
recipe: save-under of screen and colour RAM, a PETSCII frame matched glyph
|
|
845
|
+
by glyph against the character ROM, a five-item menu moved by joystick and
|
|
846
|
+
by the cursor keys through the KERNAL buffer, the restore exact byte for
|
|
847
|
+
byte; open 14,923 cycles and close 5,759 on PAL. Left open: what VICE
|
|
848
|
+
latches when its pen does trigger; the raw pucrunch decruncher was not
|
|
849
|
+
assembled; the anchor for the window technique on the text-mode-render
|
|
850
|
+
pitfall page waits for the eight-way scroll to release that page.
|
|
851
|
+
|
|
852
|
+
**Issue #22, step 3: the honest budget (schema 27, tools 2.0.0, package
|
|
853
|
+
0.13.0).** Tools 2.0.0 is a major bump because the briefing's output
|
|
854
|
+
changes in a way a client can break on: `cycles_verdict` gains
|
|
855
|
+
`undetermined`, and it no longer says `under` when a figure is missing.
|
|
856
|
+
VERSION's rule makes a breaking output change a major. The package is
|
|
857
|
+
still 0.x, where a minor is the breaking step, so it goes to 0.13.0 as
|
|
858
|
+
every tools minor before it moved the package minor; 1.0.0 is a
|
|
859
|
+
maintainer's call, not a side effect.
|
|
860
|
+
|
|
861
|
+
New tool `c64_plan_budget` (CLI `plan-budget`) adds a list of techniques
|
|
862
|
+
up against a frame, each in a phase (`name`, `name:transition`,
|
|
863
|
+
`name:init`), on PAL, NTSC or both. The rules are in `src/domain/budget.ts`
|
|
864
|
+
and came from design 2.1, where summing Cost lines erred from −96 % to
|
|
865
|
+
about 10× over on built recipes:
|
|
866
|
+
|
|
867
|
+
- A missing figure is never zero. A member with no cycles figure is
|
|
868
|
+
listed as unknown, with the recipe to measure it on, and the verdict is
|
|
869
|
+
`undetermined`.
|
|
870
|
+
- A figure above one frame (19,656 PAL, 17,095 NTSC) is a multi-frame
|
|
871
|
+
operation and is not summed. It holds nothing in the frame, so a member
|
|
872
|
+
it includes is budgeted as itself.
|
|
873
|
+
- A new Cost key, `cycles_per_frame_typical`, gives a range: the low end
|
|
874
|
+
sums typical frames, the high end worst frames. The low end is not a
|
|
875
|
+
floor. The key may hold a common frame or a real run's worst frame
|
|
876
|
+
(`ghost_target_tile_ai`'s 4,171 and `game_tree_search`'s 5,325 are the
|
|
877
|
+
second kind), and two members' such frames need not coincide. So `over`
|
|
878
|
+
is judged on the floor alone: band and per-line charges, which run
|
|
879
|
+
every frame, plus the badline loss no summed figure can already hold.
|
|
880
|
+
This departs from the design, which said `over` whenever low plus
|
|
881
|
+
losses passed the frame; on NTSC that called `sprite_multiplex_game`'s
|
|
882
|
+
built 16,600-cycle reversal frame over, while the recipe runs on NTSC
|
|
883
|
+
with every actor drawn.
|
|
884
|
+
- New `**Cost includes:**` line: a member whose work is inside another's
|
|
885
|
+
figure is counted once. Includes are followed through the graph, and of
|
|
886
|
+
two pages that include each other the first listed is kept. A technique
|
|
887
|
+
with `cycles_per_line=63` and a line band is charged band lines × line
|
|
888
|
+
length, and its REQUIRES closure is not added again.
|
|
889
|
+
- New `**Cost measured on:**` line names the recipe and its conditions.
|
|
890
|
+
With the screen on, the badlines (lines 51-243, every eighth, 43 cycles
|
|
891
|
+
each) outside any band charge are charged unless every summed figure is
|
|
892
|
+
a band charge or says it was measured with the screen on. A stall takes
|
|
893
|
+
its cycles wherever the code runs, so the charge is exact when no
|
|
894
|
+
summed figure already holds stalls, and too high by what a screen-on
|
|
895
|
+
figure holds. Bytes flagged `whole PRG` are not summed, and a member
|
|
896
|
+
inside another's figure that states bytes is not summed either.
|
|
897
|
+
- A name listed twice in one phase is counted once and the repeat is
|
|
898
|
+
listed in `refused`. A region other than pal, ntsc or both is refused.
|
|
899
|
+
PAL-locked and NTSC-locked members in one set are named.
|
|
900
|
+
|
|
901
|
+
Review corrections before release, each found by running the tool on the
|
|
902
|
+
shipped pages: the badline charge was 1,075 even when `fli_image`'s band
|
|
903
|
+
45-251 already held all 25 badlines, and was called "a ceiling: code that
|
|
904
|
+
runs in the border meets no badline", which is wrong (a stall takes its
|
|
905
|
+
cycles wherever the code runs). With `ghost_target_tile_ai`,
|
|
906
|
+
`wave_director` and `sprite_animation_table` beside it, that made a low
|
|
907
|
+
end of 18,739 into 19,814 and called the set over. `soft_scroll_h`, left
|
|
908
|
+
out as multi-frame, still hid `char_scroll_buffer_h`'s missing figure.
|
|
909
|
+
|
|
910
|
+
The briefing budget now calls the same planner, every proposed technique
|
|
911
|
+
in one play frame. Its `cycles_verdict` gains `undetermined` and it gains
|
|
912
|
+
`cycles_low`, `fixed_loss_cycles`, `excluded`, `unknown` and
|
|
913
|
+
`to_measure`. `c64_timing_budget` is unchanged. It answers a different
|
|
914
|
+
question, the cycles left on one raster line, and its README row no
|
|
915
|
+
longer claims per-frame math. Ingest now warns about, and counts, a
|
|
916
|
+
measured-on recipe that is no Recipe and an included name that is no
|
|
917
|
+
Technique.
|
|
918
|
+
|
|
919
|
+
Content: 68 Cost lines gained a measured-on line, five of them on the #21
|
|
920
|
+
pages merged from main. Five pages do not say where their figure came
|
|
921
|
+
from, so they got none. Eight gained a measured
|
|
922
|
+
typical frame, each one the page already stated: `wave_director`,
|
|
923
|
+
`dig_and_refill`, `difficulty_ramp_tables`, `ghost_target_tile_ai`,
|
|
924
|
+
`sprite_animation_table`, `sfx_engine_beside_music`, `sprite_cache_flip`
|
|
925
|
+
and `game_tree_search` (its worst measured four-node slice, 5,325, beside
|
|
926
|
+
the 9,316 bound). Three gained an includes line: `wave_director`
|
|
927
|
+
includes `object_pool`, `soft_scroll_h` includes `char_scroll_buffer_h`,
|
|
928
|
+
and `fli_image` includes its stable double-IRQ entry.
|
|
929
|
+
|
|
930
|
+
Four corrections:
|
|
931
|
+
|
|
932
|
+
- `fli_image` charged 200 lines (12,600). Its band, 45-251, is 207 lines,
|
|
933
|
+
so the figure is 13,041.
|
|
934
|
+
- `fli_image` said `bytes_code=3277` and `bytes_data=16384`: 3.2 KB and
|
|
935
|
+
16 KB times 1,024. KickAssembler's `-showmem` for the recipe gives
|
|
936
|
+
3,488 and 16,001, and the basis is now `arithmetic`, not `estimated`.
|
|
937
|
+
- `decimal_print` said `bytes_code=0`, a figure the page never measured,
|
|
938
|
+
and a budget summed it as zero bytes. The key is gone.
|
|
939
|
+
- `platformer-scaffold` plays a three-voice stub tune every frame but did
|
|
940
|
+
not list `sid_play_routine_pattern`; it does now, and the page says so.
|
|
941
|
+
|
|
942
|
+
Validation on PAL. "Old sum" is the previous briefing arithmetic over the same pages: every `cycles_per_frame` added, with a missing figure counted as zero.
|
|
943
|
+
|
|
944
|
+
| Composition | Old sum | New | Measured |
|
|
945
|
+
|---|---|---|---|
|
|
946
|
+
| platformer-scaffold | 4,953, "under" | [4,731, 4,939] + 1,075, undetermined, 5 unknowns | 4,966 one frame; peak 8,693 |
|
|
947
|
+
| simple-shmup | 5,628, "under" | 5,628 + 1,075, undetermined, `soft_scroll_v` unknown | not measured whole |
|
|
948
|
+
| cracktro-template | 75,358, "over" | 1,317 + 1,075, undetermined, `soft_scroll_h` multi-frame, `char_scroll_buffer_h` unknown | fits (about 7,000 in the blank) |
|
|
949
|
+
| fli-image | 12,884, "under" | 13,041, fits | 13,041 by arithmetic |
|
|
950
|
+
| scroll-panel-split | 413, "under" | 413, undetermined, 2 unknowns | carry frame 11,613 by arithmetic |
|
|
951
|
+
| sprite-multiplex-game | 16,600, "under" | 16,600 + 1,075, fits (NTSC undetermined) | parts measured in play: about 7,100-8,000 |
|
|
952
|
+
| wave-director | 3,568, "under" | [1,170, 3,188] + 1,075, fits | 3,188 worst, screen blanked |
|
|
953
|
+
| falling-blocks | 5,902, "under" | 5,902 + 1,075, undetermined, 2 unknowns | 6,276 dearest frame of the run |
|
|
954
|
+
|
|
955
|
+
`test/plan-budget.test.ts` rebuilds every row from the shipped pages.
|
|
956
|
+
|
|
957
|
+
Data 742, schema 26, tools 1.31.0, package 0.11.0.
|
|
958
|
+
**Candidate list, Tier B batch 2 (data 743).** Four measured items.
|
|
959
|
+
`irq_keyboard_own_scan` on the input page with a KickAssembler recipe: an
|
|
960
|
+
eight-column matrix scan in the game's interrupt with per-key age
|
|
961
|
+
counters, 252 cycles for the scan and 781 for scan, edge pass and ageing
|
|
962
|
+
with the matrix empty; the KERNAL's exit points read from the ROM (the
|
|
963
|
+
candidate list's phrasing of `$EA7B` was inverted and the page states the
|
|
964
|
+
measured one); port 2's fire line does not leak into the matrix image and
|
|
965
|
+
port 1's reads as row 4 closed in every column, both measured; no key was
|
|
966
|
+
pressed, since VICE's keyboard feed writes the KERNAL buffer, and the page
|
|
967
|
+
says so. `directory_read_and_select` on the file-io page with an Oscar64
|
|
968
|
+
recipe that writes three files, streams the "$" channel, parses the
|
|
969
|
+
listing and lets a selector pick one: 160 bytes with status `$40`, the
|
|
970
|
+
transfer 515,635 cycles on PAL and the parse 13,821; the disk name prints
|
|
971
|
+
as graphics glyphs because c1541 stores it as shifted PETSCII, explained
|
|
972
|
+
on the page. `hires_plot` and `bresenham_line` on the bitmap page with a
|
|
973
|
+
recipe: 63 cycles a plot, 136 a further line pixel, a 320-pixel line
|
|
974
|
+
43,606 cycles with the display off and about 47,000 with it on, the
|
|
975
|
+
badline stalls counted by the CIA; the eleven lines set 2,056 pixels,
|
|
976
|
+
matching a host Bresenham and the sum of the endpoints' spans.
|
|
977
|
+
`seeded_level_fill` on the logic page with a recipe: a 40 by 22 field from
|
|
978
|
+
a 16-bit seed against three thresholds and a five-object list, regenerated
|
|
979
|
+
byte for byte, a second seed giving a different checksum, 97,643 cycles a
|
|
980
|
+
generation; a flood-fill solvability check is described and not built, and
|
|
981
|
+
none of the three levels is claimed solvable. Left open: the steep-loop
|
|
982
|
+
line cost is from the instruction table; the standing disagreement between
|
|
983
|
+
the high-score-persist and file-io pages about a bare OPEN 15 with no
|
|
984
|
+
drive, which the lint still records.
|
|
985
|
+
|
|
986
|
+
**Issue #21, the last items.** `mixed_sprite_char_actors` (a sprite
|
|
987
|
+
fighter and a character fighter, priority per frame), a reference page on
|
|
988
|
+
which game and engine sources may be adapted and which are facts only
|
|
989
|
+
(`game-design/reference-game-sources.md`; the Oscar64 GPL question is
|
|
990
|
+
#31), and tool pages for `sidreloc` and `png2prg`, both run here.
|
|
991
|
+
Corrected, each with a clause: `vic-ii-reference.md` defined sprite
|
|
992
|
+
priority and `$D01F` background by colour register (multicolour pairs 00
|
|
993
|
+
and 01 are background; Bauer 3.8.2 and measured); `asset-pipelines.md`
|
|
994
|
+
had the Koala bit pairs swapped; `bitmap-koala-viewer.md` gave an
|
|
995
|
+
`#embed` form that does not compile and offsets two bytes late.
|
|
996
|
+
|
|
997
|
+
**Issue #21, GR-05/10, GR-06, GR-07, GR-11.** Engines for games at the
|
|
998
|
+
scale of Elite and Lemmings, each self-checked against a Python model:
|
|
999
|
+
`wireframe_pipeline` and `procedural_seed_universe` (pixel-exact
|
|
1000
|
+
wireframes; Elite's galaxy names reproduced), `adventure_database_engine`,
|
|
1001
|
+
`game_tree_search` (with a time-sliced form that misses no frame), and
|
|
1002
|
+
`destructible_char_terrain` with `creature_state_machine`. Two more
|
|
1003
|
+
Oscar64 faults recorded with their upstream status (#30).
|
|
1004
|
+
|
|
1005
|
+
Data 740, schema 26, tools 1.31.0, package 0.11.0 (step 2, below).
|
|
1006
|
+
|
|
1007
|
+
**Issue #22, step 2: the zero page each KERNAL routine writes (schema 26,
|
|
1008
|
+
tools 1.31.0, package 0.11.0).** A `CLOBBERS_ZP` edge from each
|
|
1009
|
+
KernalRoutine to the `zero_page` unit, from new `**Clobbers zero page:**`
|
|
1010
|
+
lines on `hardware/kernal-routines-reference.md`. A `may` line per
|
|
1011
|
+
jump-table routine is a static walk of the 901227-03 ROM through the
|
|
1012
|
+
power-on vectors (`scripts/kernal-zp-walk.ts`; `npm test` fails when the
|
|
1013
|
+
page and the walk disagree). `must` lines, 18 calls of 17 routines, are
|
|
1014
|
+
what a VICE x64sc store trace saw with every interrupt masked
|
|
1015
|
+
(`scripts/kernal-zp-trace.ts`); every traced byte lies inside its may
|
|
1016
|
+
set. `c64_check_compatibility` has a new soft kind, `kernal_clobbers_zp`:
|
|
1017
|
+
a technique's KERNAL calls may write bytes a technique claims. It also
|
|
1018
|
+
runs inside one input's own chain, the technique against itself and its
|
|
1019
|
+
own prerequisites.
|
|
1020
|
+
|
|
1021
|
+
The design's sets were too small. It put CHROUT, OPEN and the other large
|
|
1022
|
+
routines at 49-55 bytes; the walk gives 88-94. A tape routine installs
|
|
1023
|
+
one of four IRQ handlers at `$0314` (table at `$FD9B`) that runs inside
|
|
1024
|
+
the call, and those handlers write `$92`, `$96`, `$A7`, `$B1` and `$BF`.
|
|
1025
|
+
SCNKEY dispatches through `$028F`, a vector RESTOR does not set; the walk
|
|
1026
|
+
follows it to `$EB48`, the value CINT stores, which adds `$F5-$F6`. The
|
|
1027
|
+
IRQ entry's BRK branch (`JMP ($0316)` at `$FF55`) is not followed: the
|
|
1028
|
+
tape code's fake IRQ through `$FF43` never takes it, and following it ran
|
|
1029
|
+
the warm start and counted all of zero page. The traced CHROUT, scrolling
|
|
1030
|
+
the screen, wrote `$D9-$F4`, the line-link table, so Krill's default
|
|
1031
|
+
zero page `$E0-$EF` is inside what printing writes.
|
|
1032
|
+
|
|
1033
|
+
`krill_loader_integration`'s `**Uses kernal:**` said LOAD, CHKIN, CHKOUT.
|
|
1034
|
+
The v194 source calls no LOAD; the line now lists the fifteen routines
|
|
1035
|
+
`install` calls and the fallback's TKSA. Every check naming Krill now
|
|
1036
|
+
carries a soft `kernal_clobbers_zp` of Krill against itself (a lead to
|
|
1037
|
+
trace, on #22). The `serial_bus_busy` rule listed CIOUT and ACPTR, names
|
|
1038
|
+
no KernalRoutine node has; it now uses IECOUT and IECIN. The trace ran
|
|
1039
|
+
only on the windowed x64sc; it now runs on the windowless build too.
|
|
1040
|
+
|
|
1041
|
+
**Issue #21, GR-01 to GR-04.** Four small complete games, each a
|
|
1042
|
+
technique plus a self-playing recipe checked against a Python model of
|
|
1043
|
+
the same rules: `falling_block_rules` (NES tables per region, scoring at
|
|
1044
|
+
the level after the clear), `ghost_target_tile_ai` (the Pac-Man Dossier's
|
|
1045
|
+
target tiles), `cave_scan_engine` (the scanned flag that stops the double
|
|
1046
|
+
move) and `dig_and_refill` (Lode Runner's holes and guards; four guards
|
|
1047
|
+
overrun a frame). A third Oscar64 1.32.271 miscompile, reproduced: at -O2
|
|
1048
|
+
a loop-invariant `array + signed char` is zero-extended (#30).
|
|
1049
|
+
|
|
1050
|
+
|
|
1051
|
+
**Issue #22, steps 0 and 1: hardware claims (schema 25, tools 1.30.0, package 0.10.0).**
|
|
1052
|
+
`HardwareUnit` nodes (SID voices, sprites, CIA timers, TOD and ports, the
|
|
1053
|
+
VIC bank, the serial bus, the raster IRQ, the four vectors, the expansion
|
|
1054
|
+
pages, zero page) and `CLAIMS` edges from a technique's new `**Claims:**`
|
|
1055
|
+
line, in four modes: owns, shares, reads, init. `c64_check_compatibility`
|
|
1056
|
+
now names the unit two techniques contend for (`unit_contention`,
|
|
1057
|
+
`zero_page_overlap`, `unit_shared`, `unit_read_while_driven`,
|
|
1058
|
+
`init_order`, the last at a new `info` severity that leaves the verdict
|
|
1059
|
+
alone). Before, two raster-IRQ owners or two players on the same voices
|
|
1060
|
+
drew at most a soft shared-register warning. A technique with no Claims line reads as unknown,
|
|
1061
|
+
never as claiming nothing, and the text says a unit conflict with it
|
|
1062
|
+
cannot be ruled out. A `prerequisite_conflict` now carries the rule that
|
|
1063
|
+
fired in `underlying_kind`; it was reported as hard whatever the rule.
|
|
1064
|
+
Recipe-chosen zero page and vectors are not checked yet (step 8).
|
|
1065
|
+
|
|
1066
|
+
A first cut made every raster technique own the raster IRQ, and set
|
|
1067
|
+
techniques that the KB's own VICE-verified recipes run together against
|
|
1068
|
+
each other as hard conflicts (fli-image, sideborder-open, fld,
|
|
1069
|
+
stable-raster-irq, the Oscar64 raster-bars). `stable_raster_irq` and
|
|
1070
|
+
`double_irq` are ways into a handler, so they now `share` the raster
|
|
1071
|
+
compare and the effect run from the handler owns it. A technique is not
|
|
1072
|
+
set against a prerequisite it runs inside its own handler. A test now
|
|
1073
|
+
checks every recipe's technique set and fails naming any recipe with a
|
|
1074
|
+
hard unit conflict. The Kick `sprite-multiplex-24` recipe also named
|
|
1075
|
+
`sprite_multiplex_8`, a second multiplexer it does not contain. `fli_image`
|
|
1076
|
+
claims the VIC bank and requires `vic_bank_select`: its layout needs bank
|
|
1077
|
+
1 or 3, because banks 0 and 2 show character ROM where four of the eight
|
|
1078
|
+
screens go. A resident Krill loader beside a VIC bank owner now says not
|
|
1079
|
+
to write `$DD00` raw while the loader is armed; it said Krill should
|
|
1080
|
+
follow the bank owner. `irq_chain_table` against a raster effect names
|
|
1081
|
+
the table as the host. `sid_play_routine_pattern`'s claims rest on the
|
|
1082
|
+
player contract, not a listing: basis `estimated`.
|
|
1083
|
+
|
|
1084
|
+
Step 0: `sprite_multiplex_8`'s Cost held the recipe's demo payload
|
|
1085
|
+
(9,162); the three multiplexer calls measure at most 5,301. `simple-shmup`
|
|
1086
|
+
named `soft_scroll_h` and `sprite_collision_detect`, which it does not
|
|
1087
|
+
implement.
|
|
1088
|
+
**Candidate list, Tier B batch 1 (data 737).** Four measured items.
|
|
1089
|
+
`high_score_table_insert` on the text page with a KickAssembler recipe:
|
|
1090
|
+
a BCD compare from the most significant byte, a bounded shift and the
|
|
1091
|
+
tie rule, four inserts checked against an expected table byte for byte,
|
|
1092
|
+
the worst insert 481 cycles by CIA timer and by the instruction count;
|
|
1093
|
+
it realises the "table re-sorted" check on the front-end pattern, which
|
|
1094
|
+
the complete-game build of the night before skipped. The CIA revision:
|
|
1095
|
+
VICE 3.10 models the one-cycle difference between the old 6526 and the
|
|
1096
|
+
6526A or 8521, measured as an alternating latency pair of `$12`/`$11`
|
|
1097
|
+
under `-ciamodel 0` and `$10`/`$11` under model 1, the default behaving
|
|
1098
|
+
as the new part; new pitfall `cia_revision_irq_one_cycle_late` with a
|
|
1099
|
+
detection recipe pinned under the old model on both regions. The
|
|
1100
|
+
time-of-day alarm: `tod_alarm_interrupt` with a recipe that sets the
|
|
1101
|
+
clock, arms an alarm three seconds ahead and reads the time in the
|
|
1102
|
+
handler; it fired after 149 PAL and 179 NTSC frames against 150 and 180
|
|
1103
|
+
expected, the one-frame shortfall being the mains tick's phase, and with
|
|
1104
|
+
the 50/60 Hz bit the wrong way the same alarm took 180 PAL frames and 149
|
|
1105
|
+
NTSC, the drift the page quotes. `isqrt_16bit` and `atan2_8bit` on the
|
|
1106
|
+
maths page: the root exact on 35 cases and within bounds on all 65,536
|
|
1107
|
+
inputs (869 cycles worst), the angle within one unit of 256 on 36 cases
|
|
1108
|
+
on the machine and on all 65,536 pairs in the host model (381 cycles
|
|
1109
|
+
worst). The VICE reference now says that the exit screenshot is the
|
|
1110
|
+
draw buffer at the cycle the limit hits, rows above the beam new and
|
|
1111
|
+
rows below from the previous field, measured on the eight-way scroll
|
|
1112
|
+
recipe while its pin was chosen. Left open: the PAL alarm's arrival
|
|
1113
|
+
varying by about fifty cycles between identical runs; the machine sweep
|
|
1114
|
+
of every atan2 pair; every CIA figure is VICE's, none from silicon.
|
|
1115
|
+
|
|
1116
|
+
**Issue #21, ES-19 to ES-22.** `reu_dma` (one cycle a byte blanked;
|
|
1117
|
+
badlines and sprites slow it with the screen on), `four_player_read`
|
|
1118
|
+
(the user-port adapter; directions under the select are from the sources,
|
|
1119
|
+
since VICE cannot drive them headless), `cartridge_save` (EasyFlash flash
|
|
1120
|
+
writes need Ultimax mode; a save survives across two runs) and
|
|
1121
|
+
`raster_profile_bars` (border bars and a CIA table agree within a line),
|
|
1122
|
+
each with a recipe pinned on PAL and NTSC. `verify:recipes` now runs
|
|
1123
|
+
cartridge recipes: a `cartridge` key in runs.json boots the `.crt` the
|
|
1124
|
+
listing writes, once or several times on the same copy. A new Oscar64
|
|
1125
|
+
gotcha: `#define A()` with an empty parameter list is refused.
|
|
1126
|
+
**Design layer, slice 4 (data 735).** Four Oscar64 recipes that realise
|
|
1127
|
+
the pattern pages, each with a technique entry, a pinned verdict on both
|
|
1128
|
+
models and its name on the pattern's Realised-by line.
|
|
1129
|
+
`attract_mode_input_replay` (`oscar64/attract-replay`): the demo is the
|
|
1130
|
+
game fed from a recorded input stream through the same input byte, with
|
|
1131
|
+
the random generator reseeded; the reseeded build ends its 285-frame
|
|
1132
|
+
replay at the recorded position and the unseeded build 210 pixels away,
|
|
1133
|
+
both agreeing with a host model; the replay step costs 68 cycles a frame.
|
|
1134
|
+
`difficulty_ramp_tables` (`oscar64/difficulty-tables`): a six-row level
|
|
1135
|
+
table read at level start with a region scaler from the detection
|
|
1136
|
+
routine; compensated, level 3 arrives at 22,500 ms on PAL and 22,586 ms
|
|
1137
|
+
on NTSC; uncompensated, at the same frame count on both and 18,839 ms on
|
|
1138
|
+
NTSC, the 50:60 ratio. `two_player_state_swap` (`oscar64/two-player`):
|
|
1139
|
+
alternating play swaps an 8-byte block per player on death (206 cycles),
|
|
1140
|
+
simultaneous play reads both ports each frame; with `$DC00` set to `$FF`
|
|
1141
|
+
before the port-1 read, none of 40 reads was column-selected, without it
|
|
1142
|
+
all 40 were; the phantom press itself is not measured because VICE's
|
|
1143
|
+
keyboard feed writes the KERNAL buffer, not the matrix.
|
|
1144
|
+
`flip_screen_rooms` (`oscar64/flip-screen-rooms`): room records with edge
|
|
1145
|
+
exits and RLE tiles, five rooms, a scripted walk through all of them;
|
|
1146
|
+
the worst full-room redraw is 42,141 cycles, about two PAL frames, so the
|
|
1147
|
+
screen is blanked for two frames on PAL and three on NTSC rather than
|
|
1148
|
+
drawn in one vertical blank, and the pattern page's sentence saying
|
|
1149
|
+
otherwise is corrected. A defect met on the way and worth a pitfall: a
|
|
1150
|
+
colour-RAM index past 1,000 lands in the CIA1 register mirror at `$DC00`.
|
|
1151
|
+
|
|
1152
|
+
**Candidate list, Tier A batch 5 (data 734).** Four corrections and one
|
|
1153
|
+
new technique, each measured with a tool built or driven here. The
|
|
1154
|
+
KERNAL tape encoding: the TAP section said two pulse lengths; a TAP that
|
|
1155
|
+
the windowless VICE recorded from a real SAVE shows three (modes 376,
|
|
1156
|
+
536 and 704 cycles), a bit as a pulse pair, a byte marker, twenty pulses
|
|
1157
|
+
a byte with odd parity, the countdown from `$89` and from `$09`, two
|
|
1158
|
+
copies of every block and the XOR checksum, all decoded with no parity
|
|
1159
|
+
failure over 448 bytes; new pitfall `tape_bit_is_a_pulse_pair_not_a_pulse`.
|
|
1160
|
+
GoatTracker: the asset-pipelines page named a converter, `gt2asm`, that
|
|
1161
|
+
the 2.77 distribution does not contain (it ships five executables, and
|
|
1162
|
+
the export path is the relocator, `gt2reloc`, measured: 1,786 bytes at
|
|
1163
|
+
`$1000` for one example song, byte-identical when imported into
|
|
1164
|
+
KickAssembler); the five wrong invocations are corrected and a `.SNG`
|
|
1165
|
+
field table joins the formats page, checked by parsing the distribution's
|
|
1166
|
+
fourteen example songs. `pwm_digi` on the SID page with a recipe: the
|
|
1167
|
+
sample rides the pulse width under a fixed carrier; measured from a WAV
|
|
1168
|
+
VICE wrote, the carrier at 3,848.6 Hz and the recovered tone at 240.5 Hz
|
|
1169
|
+
against a synthesised 240.54 Hz, 128 cycles a sample kept exactly on
|
|
1170
|
+
both models, reSID's 8580 at 0.74 of the 6581's level; the page's
|
|
1171
|
+
TEST-bit paragraph now says it was not Harsfalvi's method. Nobody
|
|
1172
|
+
listened. Exomizer 3.1.3b0 built from source: the default stream is
|
|
1173
|
+
`-P39`, `-P0` differs in 86 bytes, and the shipped decruncher at its
|
|
1174
|
+
defaults decrunches `-P39` and crashes on `-P0`, `-P7` and `-P55` (the
|
|
1175
|
+
`-P0` case ran its output pointer below the destination and overwrote its
|
|
1176
|
+
own data), while a single-bit mismatch completes silently with wrong
|
|
1177
|
+
bytes; new pitfall `exomizer3_proto_flags_mismatch`, `exomizer_basics`
|
|
1178
|
+
corrected in place. Left open: the PWM loop's true floor between 36 and
|
|
1179
|
+
128 cycles a sample; the GoatTracker GTS2 to GTS4 layouts; an Exomizer 2
|
|
1180
|
+
decruncher against a 3.x stream.
|
|
1181
|
+
|
|
1182
|
+
**Code quality, phases C–F (tools 1.29.0, package 0.9.0).** Every MCP
|
|
1183
|
+
tool now has a `title` and `annotations` (read-only, destructive,
|
|
1184
|
+
idempotent), per the MCP spec; names, descriptions and schemas are
|
|
1185
|
+
unchanged. Search returned a different top five on repeated identical
|
|
1186
|
+
queries: Qdrant orders RRF-tied points arbitrarily. Ties now break by
|
|
1187
|
+
point id. The code was restructured without changing output: 20 CLI
|
|
1188
|
+
commands, text and JSON, are identical to the previous tree; a clean
|
|
1189
|
+
ingest into a throwaway graph gives the same 717 nodes, 2903 edges and
|
|
1190
|
+
3555 points. `extractGraphEntities` (cognitive complexity 291),
|
|
1191
|
+
`checkCompatibility` (150), `buildBriefing` (97) and ingest's `main`
|
|
1192
|
+
(81) are now tables of small functions, each under 15. The compatibility
|
|
1193
|
+
rules are a pure function with their own tests, and its per-technique
|
|
1194
|
+
queries are batched. ESLint (typescript-eslint strict, a complexity
|
|
1195
|
+
budget), Prettier and knip are gates: 848 lint findings to 0. The
|
|
1196
|
+
type check adds `noUncheckedIndexedAccess` and
|
|
1197
|
+
`exactOptionalPropertyTypes`. `health` reported an unreachable graph as
|
|
1198
|
+
healthy with zero nodes; it now fails. The CLI rejects out-of-set
|
|
1199
|
+
values for `--region`, `--toolchain`, `--language`; `pal-ntsc-diff`
|
|
1200
|
+
fell back to "both" silently. `verify:recipes --jobs` ran jobs one at a
|
|
1201
|
+
time; it now runs them in parallel. CI runs the gates (the VICE
|
|
1202
|
+
screenshots included: a Linux build of the headless VICE matched every
|
|
1203
|
+
pinned PNG it could run). Oscar64 recipes pass only with a locally
|
|
1204
|
+
patched compiler; that is #25.
|
|
1205
|
+
|
|
1206
|
+
**Design layer, slice 1 (data 733).** Four pages above the mechanics
|
|
1207
|
+
layer, written as original prose from public sources by people who
|
|
1208
|
+
shipped, facts and names only: `game-design/game-structure.md` (the
|
|
1209
|
+
state machine, level end conditions, level transitions, the front end
|
|
1210
|
+
and attract mode), `game-design/enemy-behaviour-and-difficulty.md`
|
|
1211
|
+
(interaction patterns, personality by target, attack pattern tables, the
|
|
1212
|
+
difficulty ramp, a playtest protocol), `game-design/production-planning.md`
|
|
1213
|
+
(build order, memory budget first, scope and region, tooling and editors,
|
|
1214
|
+
where the surviving documents are) and `demo-design/demo-composition.md`
|
|
1215
|
+
(the part lifecycle, transition conditions, pacing and length, music
|
|
1216
|
+
continuity across parts, the composition workflow). Each pattern is an
|
|
1217
|
+
H2 in the technique style with `Kind`, `Applies to` (archetypes that
|
|
1218
|
+
exist), `Realised by` (techniques and recipes that exist), `Sources` and
|
|
1219
|
+
a `Checks` list of statements a headless harness can test on a build.
|
|
1220
|
+
The extractor reads these pages as prose only; the metadata lines are
|
|
1221
|
+
laid out so a later extractor can read them without a rewrite (issue 24
|
|
1222
|
+
has the plan for Pattern nodes and a Structure section in the briefing).
|
|
1223
|
+
The pages exist because every game generated from the base on
|
|
1224
|
+
2026-09-22 shared three faults they describe: levels ending on a frame
|
|
1225
|
+
counter, sprites and score digits left on the title after game over, no
|
|
1226
|
+
working restart. Nothing on them was measured in VICE; every figure is
|
|
1227
|
+
its source's or arithmetic, and each page says what its sources did not
|
|
1228
|
+
say. Not found in the sweep and therefore not on the pages: attract-mode
|
|
1229
|
+
construction from an original developer, music direction from a
|
|
1230
|
+
composer, first-person design retrospectives of the major demos.
|
|
1231
|
+
|
|
1232
|
+
**Issue #21, ES-15 to ES-18.** `iffl_single_file` (the KERNAL skip
|
|
1233
|
+
fallback, measured; drive-side scan described, not built),
|
|
1234
|
+
`runtime_relocation` (two-origin diff, 855 cycles for 19 bytes),
|
|
1235
|
+
`sfx_in_player` and `goattracker_player_api`, and
|
|
1236
|
+
`irq_owns_processor_port` (18 cycles a handler), each with a recipe
|
|
1237
|
+
pinned on PAL and NTSC.
|
|
1238
|
+
|
|
1239
|
+
**Issue #20, corrections.** The Sparkle section is rewritten from its
|
|
1240
|
+
manual (by Sparta, PAL and NTSC, blocking calls, 72 cycles a byte); the
|
|
1241
|
+
`$DD00`/`$DD02` rule is scoped per loader; the VSP crash paragraph follows
|
|
1242
|
+
lft's article (no detection method); GoatTracker 2 has one SID model
|
|
1243
|
+
setting; a new pitfall for SID replacements that cannot read `$D41B`;
|
|
1244
|
+
`c64-file-formats` now says a last sector stores the index of the last
|
|
1245
|
+
used byte. Each carries a correction clause.
|
|
1246
|
+
|
|
1247
|
+
|
|
1248
|
+
**Candidate list, Tier A batch 4 (data 731).** Three of the four items
|
|
1249
|
+
landed. `mouse_1351_read` on the input page with a KickAssembler recipe:
|
|
1250
|
+
the 1351's proportional mode is a six-bit position counter in bits 1 to
|
|
1251
|
+
6 of the pot registers, not the quadrature the SID page still describes.
|
|
1252
|
+
Measured in VICE's 1351 model: the masked counter read 32 on both axes on
|
|
1253
|
+
every one of 250 frames on PAL and NTSC, raw bit 0 changed between
|
|
1254
|
+
consecutive frames over a hundred times per run, so the picture prints
|
|
1255
|
+
the masked value only; the signed modulo-64 delta is checked on ten
|
|
1256
|
+
compiled-in samples including both wraps and both half-turn cases; one
|
|
1257
|
+
read of both axes costs 104 cycles by the instruction count and 103 by
|
|
1258
|
+
the CIA timer, a one-cycle gap the page leaves open. The buttons' lines
|
|
1259
|
+
(fire and up) are from the documentation, not pressed here. The SID
|
|
1260
|
+
page's quadrature sentence is reported, not edited (see issue 9).
|
|
1261
|
+
`fld_flexible_line_distance` on the raster page with a recipe that
|
|
1262
|
+
bounces the display by rewriting YSCROLL each line: the top text row sat
|
|
1263
|
+
exactly N lines lower on both models, the first badline landed on line
|
|
1264
|
+
51 plus N on every frame, and every gap line showed the idle fetch of
|
|
1265
|
+
`$3FFF`, which is the new pitfall `idle_fetch_byte_shows_in_gaps`; a
|
|
1266
|
+
YSCROLL value that matches the next line only at its first cycle moves
|
|
1267
|
+
the display one line, not N. The sideborder recipe's dangling `fld` and
|
|
1268
|
+
`vsp` links now point at real techniques. `d64_error_byte_is_a_controller_code`
|
|
1269
|
+
on the loader page, with the D64 section of the file-formats page
|
|
1270
|
+
corrected in place: the per-sector byte is the controller's job code,
|
|
1271
|
+
and read back through the drive's error channel under VICE 3.10 the codes
|
|
1272
|
+
`$02`, `$03`, `$04`, `$05`, `$09` and `$0B` are honoured and `$07`, `$08`
|
|
1273
|
+
and `$0F` ignored; a lone sector flagged `$03` or `$0B` reads 20, and
|
|
1274
|
+
only a whole track carrying the code reads 21 or 29. The IEC page's
|
|
1275
|
+
"not measured here" sentence on that point now cites the measurement.
|
|
1276
|
+
The eight-way scroller did not land: its writer stalled six times in the
|
|
1277
|
+
reading phase and runs again alone.
|
|
1278
|
+
|
|
1279
|
+
**Runtime fixes, phase B (tools 1.28.1, package 0.8.1).** Nothing
|
|
1280
|
+
listened for the FalkorDB client's `error` event, so a FalkorDB restart
|
|
1281
|
+
would throw and end the MCP server; it now logs to stderr and the
|
|
1282
|
+
client reconnects. Two tool calls on a cold server each opened a
|
|
1283
|
+
connection; the connection promise is now shared. The server ignored
|
|
1284
|
+
stdin closing, the MCP spec's shutdown signal; it now closes its
|
|
1285
|
+
connections and exits (6 ms after stdin closed, measured by the new
|
|
1286
|
+
`test/mcp-stdio.test.ts`, which also asserts stdout carries only
|
|
1287
|
+
JSON-RPC). It reported version 0.1.0; it reports the package version.
|
|
1288
|
+
`c64_ingest_doc` indexed new content without writing it when the file
|
|
1289
|
+
existed, and kept a page's old chunks, so removed sections stayed
|
|
1290
|
+
searchable; it now writes the file and replaces the chunks.
|
|
1291
|
+
`c64_run_game` and the memorization check returned failures without
|
|
1292
|
+
`isError`; the memorization tool is registered only where `analyzer/`
|
|
1293
|
+
exists, which is not this repository. `c64_run_game` killed every
|
|
1294
|
+
`x64sc` on the machine; it kills only the one on its monitor port.
|
|
1295
|
+
`ensureSchema` swallowed every error, not only "already indexed" and
|
|
1296
|
+
"Constraint already exists" (messages measured on FalkorDB 4.18.7).
|
|
1297
|
+
Gap logging ran select-then-insert without a transaction across two
|
|
1298
|
+
processes. CLI commands ended in `process.exit()`, which can truncate
|
|
1299
|
+
piped `--json`; they now close their connections and set the exit code.
|
|
1300
|
+
A malformed environment variable stops start-up with its name instead of
|
|
1301
|
+
becoming `NaN`.
|
|
1302
|
+
|
|
1303
|
+
**Issue #21, ES-11 to ES-14.** `nav_area_pathfinding` (a next-hop table
|
|
1304
|
+
over platform areas; 0 of 160 hops differ from a Python model),
|
|
1305
|
+
`multi_sprite_object` (a boss from six sprites across the X 255 seam,
|
|
1306
|
+
registers checked every frame), `charset_parallax` (background glyphs
|
|
1307
|
+
rolled at half the foreground's speed; 0 of 55,936 pixels differ from a
|
|
1308
|
+
model), `world_state_bits` and `password_encoding` (every single-letter
|
|
1309
|
+
typo and every neighbour swap caught for all 2^20 states). A new Oscar64
|
|
1310
|
+
gotcha, measured: at -O1 to -O3, `c == 255 ? 255 : a[c]` with `a`
|
|
1311
|
+
shorter than 256 loses its guard and reads `a[255]`.
|
|
1312
|
+
|
|
1313
|
+
|
|
1314
|
+
**Tooling, phase A (no tool surface change).** `tsc --noEmit` checked
|
|
1315
|
+
`src/` only, so `scripts/` and `test/` were never type-checked; three
|
|
1316
|
+
errors in `test/config.test.ts` and six unused symbols had gone unseen.
|
|
1317
|
+
`tsconfig.json` now checks all three and emits nothing;
|
|
1318
|
+
`tsconfig.build.json` builds `dist/` and leaves tests out. Relative
|
|
1319
|
+
imports end in `.ts`, so Node 24.12+ runs the sources directly and `tsx`
|
|
1320
|
+
is gone (`node src/cli.ts`, `npm run health`, `npm run typecheck`). `npm
|
|
1321
|
+
pack` shipped no `dist/` (`.gitignore` excluded it and there was no
|
|
1322
|
+
`files` list), so a published `bin` would not have run; `files` and
|
|
1323
|
+
`prepack` fix that. Removed four dependencies nothing imported (`yaml`,
|
|
1324
|
+
`js-yaml`, `@types/js-yaml`, `@anthropic-ai/vertex-sdk`). Qdrant and
|
|
1325
|
+
FalkorDB are pinned by digest instead of `:latest`. Tests split into a
|
|
1326
|
+
`unit` project (no services, parallel) and an `integration` project. The
|
|
1327
|
+
Claude Code hooks match `Edit|Write` (`MultiEdit` no longer exists), call
|
|
1328
|
+
the project's own `tsc` (`npx tsc` without `node_modules` fetched an
|
|
1329
|
+
unrelated package), and a new Stop hook builds `dist/` and runs the unit
|
|
1330
|
+
tests once per turn instead of rebuilding after every edit.
|
|
1331
|
+
|
|
1332
|
+
**Candidate list, Tier A, batch 3.** The start-up hang a blind build hit is
|
|
1333
|
+
now a pitfall with a measured table behind it,
|
|
1334
|
+
`first_open_after_reset_hangs_on_pal`: on PAL a program whose first OPEN
|
|
1335
|
+
follows the autostart by ten frames hung three times out of three while
|
|
1336
|
+
zero, five, twenty and fifty frames ran, so the wait is not the cure it
|
|
1337
|
+
looked like; NTSC never hung; loading the program through the drive
|
|
1338
|
+
instead of injecting it ran to game over; the monitor at the hang shows
|
|
1339
|
+
the C64 waiting for CLK with the drive a few dozen cycles from TALK, and
|
|
1340
|
+
why it never arrives unperturbed is still open. `level-rle-decoder` (Oscar64)
|
|
1341
|
+
compresses three real-shaped rooms, decodes them on the machine against a
|
|
1342
|
+
host checksum and shows ratio, cycles and decoder bytes per room; the
|
|
1343
|
+
patterns page's unmeasured ratio and decoder-size sentences now carry the
|
|
1344
|
+
measured figures. `paddle_read` on the input page with the KickAssembler
|
|
1345
|
+
recipe `paddle-read`: the port-select dance, the settle measured on both
|
|
1346
|
+
models (within 480 cycles at six of eight phases, 544 at two) and the
|
|
1347
|
+
keyboard scan's interference counted; positions and buttons are not
|
|
1348
|
+
measured because a headless host cannot move a paddle. The eight-way
|
|
1349
|
+
scroller planned for this batch did not land: its writer stalled and will
|
|
1350
|
+
run again on its own.
|
|
1351
|
+
|
|
1352
|
+
**Issue #21, engine subsystems ES-01 to ES-10.** Ten techniques from an
|
|
1353
|
+
online sweep of how shipped games were built, each with a recipe pinned on
|
|
1354
|
+
PAL and NTSC: `sprite_multiplex_game` (an assembly multiplexer with the
|
|
1355
|
+
sort kept between frames and a late-IRQ guard; 611 cycles for 24 sorted
|
|
1356
|
+
actors), `scroll_panel_split` with the pitfall
|
|
1357
|
+
`scroll_phase_breaks_panel_split` (a naive split breaks at one YSCROLL
|
|
1358
|
+
phase, the split line mod 8, measured at all eight), `logic_rate_decoupling`,
|
|
1359
|
+
`actor_activation_window`, `wave_director`, `per_frame_hitbox`,
|
|
1360
|
+
`char_bullets`, `sprite_cache_flip`, `sprite_animation_table` and
|
|
1361
|
+
`slope_collision`. Each Cost line is the measured worst frame of the
|
|
1362
|
+
technique's own work. Facts from Cadaver's articles and c64gameframework
|
|
1363
|
+
(MIT), codebase64 and Corescape (GPL); the code is original.
|
|
1364
|
+
|
|
1365
|
+
**Ontology from #21 (schema 24, tools 1.28.0).** A `**Raster band:**` line
|
|
1366
|
+
on techniques: `c64_check_compatibility` no longer reports two
|
|
1367
|
+
every-line techniques as a conflict when their stated bands are disjoint,
|
|
1368
|
+
and lists such pairs in `band_separated`; FLI, AFLI and IFLI state
|
|
1369
|
+
45-251, the side border `movable`. `c64_timing_budget` subtracts sprite
|
|
1370
|
+
DMA (3 + 2 per sprite, the minimum for sprites numbered without gaps;
|
|
1371
|
+
input `sprites_per_line`); it did not before. The Demands word
|
|
1372
|
+
`serial_bus_exclusive` on the Krill loader, with a hard conflict
|
|
1373
|
+
`serial_bus_busy` against techniques that call KERNAL serial routines.
|
|
1374
|
+
Tool nodes carry `version_verified` from the toolchain pages. Corrections:
|
|
1375
|
+
`multi_load_sequencing` said `Uses kernal: LOAD`, but it loads through
|
|
1376
|
+
Krill; the ontology's Tool table listed a `category` the code never
|
|
1377
|
+
wrote. `dd00_plain_stores` was not added: it is Bitfire's rule and false
|
|
1378
|
+
for Krill.
|
|
1379
|
+
|
|
1380
|
+
|
|
1381
|
+
**Candidate list, Tier A, batch 2.** `charset_copy_rom_to_ram` on the
|
|
1382
|
+
banking page, with the KickAssembler recipe `charset-copy-rom-to-ram`: the
|
|
1383
|
+
2 KB copy under the I/O window costs 19,733 cycles with the display off
|
|
1384
|
+
and about a thousand more with it on, the copy is checked against the
|
|
1385
|
+
ROM image's checksum, and the same program makes the copy once with
|
|
1386
|
+
interrupts enabled and shows what happens: the KERNAL interrupt fires
|
|
1387
|
+
into the mapped ROM and the loop never finishes, caught by a timer NMI
|
|
1388
|
+
watchdog. That is the new pitfall `irq_during_charen_window`.
|
|
1389
|
+
`nmi_handler_and_restore_key` on the CPU page, with the recipe
|
|
1390
|
+
`nmi-timer-tick`: the vectors, the RTI stub that disarms RESTORE, the
|
|
1391
|
+
`$DD0D` acknowledge and the lock without it, measured with a CIA2 timer
|
|
1392
|
+
standing in for the key the rig cannot press; a new pitfall
|
|
1393
|
+
`kernal_nmi_handler_runs_stop_check`. `software_sprite_preshifted` on the
|
|
1394
|
+
sprite page, with the recipe `software-sprite-preshifted`: a 24x21 masked
|
|
1395
|
+
object pre-shifted for eight positions in a character back buffer, 1,428
|
|
1396
|
+
cycles a blit at every shift, against the multiplexer for when each wins.
|
|
1397
|
+
A new pitfall `sprite_x_range_hidden_and_seam` with the visible window
|
|
1398
|
+
measured column by column on both models (X 24 to 343 visible, 23 and
|
|
1399
|
+
344 not) and the PAL seam pinned between $1F7 and $200. The autopilot
|
|
1400
|
+
pattern from the same tier is covered by the headless-verify recipe's
|
|
1401
|
+
autopilot section.
|
|
1402
|
+
|
|
1403
|
+
**Candidate list, Tier A, batch 1: four things every agent reaches for
|
|
1404
|
+
and the KB did not have.** `petscii_screen_code_conversion` (text page):
|
|
1405
|
+
the PETSCII to screen-code rule measured over all 224 printable codes by
|
|
1406
|
+
writing each with CHROUT and reading screen RAM back, the reverse-video
|
|
1407
|
+
bit, the shifted set through `$D018`, the colour RAM consequence, and where
|
|
1408
|
+
in the KERNAL the fold lives, with the Oscar64 recipe `petscii-screen-codes`
|
|
1409
|
+
proving the rule both ways on screen; a new pitfall
|
|
1410
|
+
`petscii_written_to_screen_ram` for the letters-come-out-as-graphics
|
|
1411
|
+
symptom. `compare_16bit_and_signed` (maths page): unsigned 16-bit compare
|
|
1412
|
+
high byte first, the signed idiom with the overflow flag and why a bare
|
|
1413
|
+
BMI fails across the boundary, ranged compares, and what Oscar64 emits,
|
|
1414
|
+
with the KickAssembler recipe `compare-16bit-signed` sweeping the boundary
|
|
1415
|
+
pairs and counting the bad form's failures (16,384 of them); a new pitfall
|
|
1416
|
+
`signed_compare_bmi_overflow`. `division_8_16bit` (maths page):
|
|
1417
|
+
shift-and-subtract division in three widths, reciprocal multiply with its
|
|
1418
|
+
error bound, divide by ten against the subtract-powers route, with the
|
|
1419
|
+
Oscar64 recipe `divide-check` checking quotient and remainder over the
|
|
1420
|
+
full 8-bit range and timing every route. `sine_table_generation` (CPU
|
|
1421
|
+
page): quarter-wave, second-difference and parabola generation with the
|
|
1422
|
+
worst and mean error of each against a host table and the cycles to build
|
|
1423
|
+
256 entries, with the KickAssembler recipe `sine-table-runtime` driving a
|
|
1424
|
+
visible sprite sine from the table it just built. Every new technique is
|
|
1425
|
+
anchored on the pitfalls its code meets.
|
|
1426
|
+
|
|
1427
|
+
**The recipe lookup carries the listing.** `c64_recipe_lookup` and the
|
|
1428
|
+
CLI's `recipe-lookup` returned a recipe's Build, Synopsis and Expected
|
|
1429
|
+
output sections and never its Source listing, so a caller with no file
|
|
1430
|
+
access, an MCP client on another machine or a model that will not open a
|
|
1431
|
+
page, could not copy the code. Nine builds of one game showed it: the two
|
|
1432
|
+
strong models that read the page file shipped the recipe; the one that
|
|
1433
|
+
trusted the answer built from prose. The answer now ends with the page's
|
|
1434
|
+
Source fence, the one the listing gate builds and the pinned screenshot was
|
|
1435
|
+
made from, and the structured output carries it as `source_code`. Tools
|
|
1436
|
+
1.27.0.
|
|
1437
|
+
|
|
1438
|
+
**Batch 9c: transitions, disk work and a release disk.** The transitions
|
|
1439
|
+
page is complete: `colour_cycling` (one step over eight rows of colour RAM,
|
|
1440
|
+
3,265 cycles on either model) and `screen_wipe` (a row written out in 491
|
|
1441
|
+
cycles, in at 708 or 709), each with a KickAssembler recipe pinned mid-
|
|
1442
|
+
effect and checked pixel by pixel against its own formula; both recipes
|
|
1443
|
+
record a first draft whose single-compare busy-wait fell through the
|
|
1444
|
+
raster line twice a frame and double-counted. `load-asset-runtime`
|
|
1445
|
+
(Oscar64) builds a charset, saves it, loads it back to an address of its
|
|
1446
|
+
own choosing and shows it, with the KERNAL's LOAD measured to leave the
|
|
1447
|
+
raster interrupt armed and `$D011` alone; the technique page gained the
|
|
1448
|
+
secondary-address facts and the header page's `krnio_load` note. The new
|
|
1449
|
+
technique `kernal_relative_file_io` and its recipe `relative-file-records`
|
|
1450
|
+
create a REL file with 32-byte records, position with the P command, and
|
|
1451
|
+
quote what the drive says, including the 50 and 51 replies provoked in
|
|
1452
|
+
VICE for the first time here. `toolchains/release-disk.md` builds a D64
|
|
1453
|
+
from the platformer scaffold with c1541, lists it, autostarts the disk
|
|
1454
|
+
itself headless and shows the game running from it, with the block
|
|
1455
|
+
arithmetic and a Makefile target; two screenshots of that boot ride with
|
|
1456
|
+
the scaffold recipe. The verifier still only formats a disk; a `files` key
|
|
1457
|
+
to place a built PRG on it is proposed on the page and not built.
|
|
1458
|
+
For a few hours the verifier and the pages carried `-minimized` on every
|
|
1459
|
+
headless VICE command to stop a batch of runs taking the desktop's focus;
|
|
1460
|
+
it was withdrawn the same night because a window that opens and then
|
|
1461
|
+
minimises is worse than one that opens, and the pictures were byte-identical
|
|
1462
|
+
either way. The fix landed the same night: VICE 3.10 built with
|
|
1463
|
+
`--enable-headlessui` has no window at all and its exit screenshots are
|
|
1464
|
+
byte-identical to the pins (four recipes, both models, and the disk-backed
|
|
1465
|
+
ones); `npm run vice:headless` builds one into `.tools/` from the pinned
|
|
1466
|
+
tarball, and every emulator launch in the repository (the verifier, the
|
|
1467
|
+
run tool) prefers it when present, with `X64SC_BIN` as an override; the
|
|
1468
|
+
VICE page says how it works and the one flag-order trap.
|
|
1469
|
+
|
|
1470
|
+
**Pitfalls reached through a technique's registers, and a graph report.**
|
|
1471
|
+
A technique also meets every pitfall that a register or KERNAL routine it
|
|
1472
|
+
declares triggers. Both ends of that join are exact declarations on the
|
|
1473
|
+
pages, so the edge is derived rather than guessed, which is the one kind
|
|
1474
|
+
of graph edge the literature on retrieval finds worth having. The
|
|
1475
|
+
pitfalls tool now adds those pitfalls after the direct ones and names the
|
|
1476
|
+
register that carried each; `ecm_mode` went from no answer to four
|
|
1477
|
+
pitfalls, and thirteen techniques with no direct anchor now reach one.
|
|
1478
|
+
`npm run graph:report` prints the graph's shape: node and edge counts,
|
|
1479
|
+
technique degree, connected components and the largest one's share,
|
|
1480
|
+
isolated nodes, techniques without a recipe or without any pitfall by any
|
|
1481
|
+
route, and per-archetype feature, risk and scaffold counts. Its first
|
|
1482
|
+
reading, in the commit that added it, said the largest component held two
|
|
1483
|
+
thirds of the nodes and the rest were isolated memory regions, and that
|
|
1484
|
+
fourteen techniques had no pitfall by any route. Those are the numbers to
|
|
1485
|
+
watch before expecting the graph to pull ahead of the text.
|
|
1486
|
+
|
|
1487
|
+
**Source lints compiled from the pitfalls (tools 1.26.0).** A new MCP
|
|
1488
|
+
tool, `c64_lint_source`, and CLI subcommand, `lint <file>`, run the
|
|
1489
|
+
knowledge base's rules over an agent's own C or assembly source with no
|
|
1490
|
+
graph or vector store involved. Eight rules, each named after the
|
|
1491
|
+
pitfall it compiles and pointing at its page: `sid_write_only_registers`,
|
|
1492
|
+
`cia1_ddr_cleared_kills_keyboard`, `empty_name_open_15_hangs_on_read`
|
|
1493
|
+
(from the high-score recipe's warning), `raster_poll_with_kernal_irq_live`
|
|
1494
|
+
(anchored on `raster_irq_first_line_jitter` and the frame-sync recipe),
|
|
1495
|
+
`lfsr_zero_state_lockup`, `decimal_mode_in_irq_handler`,
|
|
1496
|
+
`d016_unmasked_rmw_clobbers_csel_mcm` and `jmp_indirect_page_boundary_bug`.
|
|
1497
|
+
Every finding carries a certainty (`definite`, `likely`, `heuristic`) and
|
|
1498
|
+
the message uses the page's own words for the mechanism and the fix. The
|
|
1499
|
+
test runs the linter over the two platformer builds from the 2026-09-22
|
|
1500
|
+
three-arm test, copied into `test/fixtures/`: on the build made without
|
|
1501
|
+
the knowledge base it reports the SID read-modify-write, the DDR clear,
|
|
1502
|
+
the empty-name OPEN and the raster poll at their lines; on the build made
|
|
1503
|
+
with it, no definite finding. The first draft flagged
|
|
1504
|
+
`#include <c64/sid.h>` as a SID read; preprocessor lines are now skipped.
|
|
1505
|
+
Review of the first draft against every listing in `docs/` changed four
|
|
1506
|
+
rules. The decimal-mode rule had the pitfall backwards (it flagged a SED
|
|
1507
|
+
that reaches RTI, where the page's fault is a handler that reaches ADC
|
|
1508
|
+
or SBC before any CLD); it now follows an installed handler from its
|
|
1509
|
+
label and has no C form, since in C the arithmetic is the compiler's.
|
|
1510
|
+
Read that way it fires on the KB's own `stable-raster-irq`,
|
|
1511
|
+
`cracktro-template`, `dycp-scroller` and `sine-scroller` handlers, none
|
|
1512
|
+
of which CLD; none of those programs executes SED either, so those are
|
|
1513
|
+
heuristic, and the pitfall page and the recipes are left to be
|
|
1514
|
+
reconciled. The `$D016` rule read the first `lda #` in its window
|
|
1515
|
+
rather than the one that feeds the store, which flagged
|
|
1516
|
+
`sideborder-open` and missed a bad store; it walks back to the load
|
|
1517
|
+
now. The empty-name OPEN rule is `heuristic`, not `likely`: the
|
|
1518
|
+
high-score recipe measured a bare OPEN of channel 15 returning success
|
|
1519
|
+
with no drive, while `techniques/file-io.md` opens the channel bare and
|
|
1520
|
+
expects the carry set, and the message names both rather than pick one.
|
|
1521
|
+
Language detection strips comments and tests for assembler signatures
|
|
1522
|
+
first, so a KickAssembler `.for` block no longer reads as C. The package
|
|
1523
|
+
version follows at release.
|
|
1524
|
+
|
|
1525
|
+
**Schema 23: the scaffold is an edge.** A recipe page may now carry
|
|
1526
|
+
`scaffolds: [vertical_shmup, horizontal_shmup]` in its frontmatter, an
|
|
1527
|
+
array of Archetype names; the ingest links `Recipe -[:SCAFFOLDS]->
|
|
1528
|
+
Archetype` in pass 2 with both ends matched, drops a name that matches
|
|
1529
|
+
no Archetype with a warning, and reports `scaffolds … dropped` on the
|
|
1530
|
+
summary line beside the other relations. `c64_game_briefing` reads that
|
|
1531
|
+
edge for its first build step in place of matching the string "shmup"
|
|
1532
|
+
against the archetype name and offering `oscar64-simple-shmup` by name;
|
|
1533
|
+
the step's text now also names the recipe's page so an agent knows which
|
|
1534
|
+
file to copy. The fallback tables, used only by a graph with no
|
|
1535
|
+
Archetype nodes, still offer the shmup scaffold by name. The shmup
|
|
1536
|
+
recipe carries the key for both shmup archetypes. `ONTOLOGY.md` and
|
|
1537
|
+
`CONVENTIONS-recipes.md` document the edge and the key.
|
|
1538
|
+
|
|
1539
|
+
**Batch 9b: text and demo effects the gap map still owed.** Four new
|
|
1540
|
+
techniques, each with a pinned, measured recipe. `big_font_2x2` on the
|
|
1541
|
+
text page: a 2x2 charset built from the ROM font at start (about 58,000
|
|
1542
|
+
cycles once) and a two-row scroller whose rotate costs 708 cycles on
|
|
1543
|
+
either model, with the KickAssembler recipe `big-font-scroller`.
|
|
1544
|
+
`charset_animation` on the render page: rewriting a glyph's eight bytes
|
|
1545
|
+
in place against flipping whole charsets with `$D018`, 196 cycles a frame
|
|
1546
|
+
for the rewrite, with the Oscar64 recipe `charset-animation`; the writer
|
|
1547
|
+
found and fixed an NTSC ordering fault of its own on the way, a HUD write
|
|
1548
|
+
that spilled past the shorter vertical blank. `speedcode_generation` on
|
|
1549
|
+
the CPU page: a generator that emits unrolled load and store pairs into
|
|
1550
|
+
RAM from address tables, measured against a loop for the same copy, with
|
|
1551
|
+
the KickAssembler recipe `speedcode-generator`, whose text records that
|
|
1552
|
+
its first verdict was placed after the timed loop and passed a red case
|
|
1553
|
+
until it was moved. `dycp_scroller` on the scroll page: letters on a sine
|
|
1554
|
+
wave by copying glyph rows into per-column charset strips, with the
|
|
1555
|
+
KickAssembler recipe `dycp-scroller` pinned at nine million cycles and
|
|
1556
|
+
its PAL and NTSC timer readings as a clean illustration of the badline
|
|
1557
|
+
cost. Every new technique is anchored on the pitfalls its code meets.
|
|
1558
|
+
|
|
1559
|
+
**Batch 9a: what the three-arm build test said was missing.** A new
|
|
1560
|
+
technique page, `techniques/logic.md`, opens with `tile_grid_collision`
|
|
1561
|
+
(requires `tile_map_render`; 2,345 cycles on its worst frame, measured
|
|
1562
|
+
with the CIA timer inside the vertical blank) and `object_pool` (the
|
|
1563
|
+
update pass over eight live slots, 380 cycles, from the object-pool
|
|
1564
|
+
recipe's own harness); both platformer fingerprints now name the
|
|
1565
|
+
collision, so a platformer briefing proposes it. The recipe
|
|
1566
|
+
`tile-grid-collision` walks a scripted sprite through a landing, a wall,
|
|
1567
|
+
a ceiling bump, a ladder and a pit with an assert every frame, and found
|
|
1568
|
+
on the way that side probes must sit no further apart than a tile. The
|
|
1569
|
+
recipe `fixed-point-jump-velocity` jumps from two different heights with
|
|
1570
|
+
one velocity table, which the fixed-ground table on the older recipe
|
|
1571
|
+
cannot do. `headless-verify` gained an autopilot input (one define swaps
|
|
1572
|
+
the joystick read for a scripted port byte through the same edge
|
|
1573
|
+
detector) and a self-test (a forced-fault build must make the same
|
|
1574
|
+
verify script exit 1 before its green is trusted), and the VICE page a
|
|
1575
|
+
palette-safe border grading by channel dominance. Measured, a raster
|
|
1576
|
+
IRQ left armed through a 2 KB file write and read back corrupts nothing
|
|
1577
|
+
on either model, but its handler enters up to about 240 lines late while
|
|
1578
|
+
the bus is busy, so a border split wanders; `rirq_stop()` is a bare
|
|
1579
|
+
`sei` that the KERNAL's own `cli` cancels, so wrapping the calls in it
|
|
1580
|
+
changes nothing, and clearing `$D01A` is what actually keeps the
|
|
1581
|
+
interrupt out. That is the new pitfall `raster_irq_during_serial_io` and
|
|
1582
|
+
a section on the high-score recipe. The PAL start-up hang a blind build
|
|
1583
|
+
hit is located but not explained: the KERNAL waits with no timeout for
|
|
1584
|
+
the drive to pull CLK at the talk turnaround, and why the emulated 1541
|
|
1585
|
+
does not is open. Two lines elsewhere were wrong and are corrected: the
|
|
1586
|
+
IEC page's "approximately 64 ms" timeout (the only timeout is about
|
|
1587
|
+
1,024 cycles around the acknowledge wait, and a stalled turnaround never
|
|
1588
|
+
returns) and the Oscar64 header page's `rirq_stop()` "disables it".
|
|
1589
|
+
Three more pitfall anchors on the KERNAL page for the decimal-mode,
|
|
1590
|
+
IRQ-chain and text-input techniques.
|
|
1591
|
+
|
|
1592
|
+
**The briefing proposer, measured against a real brief.** The three-arm
|
|
1593
|
+
build test handed the game briefing a nine-part platformer brief and it
|
|
1594
|
+
proposed eight techniques the brief did not need while missing eight of
|
|
1595
|
+
its nouns. Four causes, each fixed and tested on the fixture graph. The
|
|
1596
|
+
keyword scorer matched substrings, so "budget bar" proposed raster bars
|
|
1597
|
+
and "tile map" reached every bitmap technique through the category word;
|
|
1598
|
+
it matches whole words now. It kept ten candidates whatever the brief's
|
|
1599
|
+
length, so the LFSR fell off the end; the limit scales with the brief.
|
|
1600
|
+
The vector supplement filled every remaining slot with guesses; it adds
|
|
1601
|
+
at most four when the brief's own words already found most of the plan.
|
|
1602
|
+
And the toolchain handoff sent stable raster IRQs, raster bars and the
|
|
1603
|
+
multiplexer to KickAssembler although this knowledge base carries an
|
|
1604
|
+
Oscar64 recipe for each; a cycle-tight technique with a recipe in the
|
|
1605
|
+
primary toolchain now stays there and is named as kept, and only one
|
|
1606
|
+
that needs every cycle of the line, is scene-tier, or has no Oscar64
|
|
1607
|
+
recipe is handed off. Every plan now ends with a headless verification
|
|
1608
|
+
step naming the Oscar64 harness recipe, because a brief that asks for a
|
|
1609
|
+
harness had no technique node to reach it through. Two nouns that
|
|
1610
|
+
existed only as recipes have technique nodes: `decimal_print` in
|
|
1611
|
+
`techniques/text.md`, with the print-number recipe's measured cycle
|
|
1612
|
+
figures as its cost line, and `memory_layout_plan` in
|
|
1613
|
+
`techniques/memory-banking.md`, implemented by the memory-layout recipe.
|
|
1614
|
+
On the same brief the proposal now carries the LFSR, the file read, the
|
|
1615
|
+
fixed-point and jump-table techniques and the decimal print it missed,
|
|
1616
|
+
and the handoff is one technique instead of three.
|
|
1617
|
+
|
|
1618
|
+
**Pitfall anchors for the new techniques.** A briefing agent asked
|
|
1619
|
+
`pitfalls-for frame_sync_loop` and got nothing, although the badline,
|
|
1620
|
+
raster-jitter, `$D012` wrap and PAL/NTSC pitfalls all apply to it: the
|
|
1621
|
+
techniques added this month had no pitfall naming them, so the graph had
|
|
1622
|
+
no edge to follow. Twenty-seven pitfall entries now name the techniques
|
|
1623
|
+
whose code meets their mechanism, added only where the pitfall's own text
|
|
1624
|
+
supports it; a double buffer is listed as a mitigation of the full-field
|
|
1625
|
+
redraw overrun rather than a trigger of it. One pitfall is new,
|
|
1626
|
+
`cia1_ddr_cleared_kills_keyboard`: clearing `$DC02` to read joystick 2
|
|
1627
|
+
leaves the KERNAL keyboard scan driving nothing, which a blind build did
|
|
1628
|
+
today and no headless run can see. `npm run check:pitfall-anchors`
|
|
1629
|
+
reports the techniques still without an anchor and fails on a dangling
|
|
1630
|
+
name; the ones that remain are mostly effects and packers for which no
|
|
1631
|
+
written pitfall applies yet.
|
|
1632
|
+
|
|
1633
|
+
**Two tool faults from the blind build test.** An agent that built a
|
|
1634
|
+
game from the knowledge base alone logged what got in its way; two of
|
|
1635
|
+
the items were the tools, not the pages. Every CLI lookup now honours
|
|
1636
|
+
the global `--json` flag and prints the same structured object the MCP
|
|
1637
|
+
server returns; only the briefings did before. And a briefing given a
|
|
1638
|
+
partial archetype name resolves it when exactly one archetype contains
|
|
1639
|
+
every word of it (`racing`, `cracktro`), reports the candidates when
|
|
1640
|
+
several do (`platformer` names two, `shmup` two), and only then falls
|
|
1641
|
+
back to listing every known name; the builder had spent a call learning
|
|
1642
|
+
that `platformer` was not a name. Tools 1.25.1.
|
|
1643
|
+
|
|
1644
|
+
**A cost line per technique, so a briefing can add a plan up (#17).** A
|
|
1645
|
+
technique page may now carry `**Cost:**` with integer pairs from a fixed
|
|
1646
|
+
vocabulary (`cycles_per_line`, `cycles_per_frame`, `lines_active`,
|
|
1647
|
+
`bytes_code`, `bytes_data`, `zp_bytes`, `irq_slots`) and a companion
|
|
1648
|
+
`**Cost basis:**` line that says how the figures were obtained, one word
|
|
1649
|
+
from `measured-vice`, `derived-listing`, `arithmetic` or `estimated`.
|
|
1650
|
+
The extractor skips an unknown key or a non-integer value with a
|
|
1651
|
+
warning and drops the whole line for a basis word outside the set or a
|
|
1652
|
+
missing basis line; the values land on the `Technique` node as
|
|
1653
|
+
`cost_<key>` and `cost_basis` (schema 22), cleared again when a page
|
|
1654
|
+
drops the line. `c64_technique_lookup` returns them as `cost`.
|
|
1655
|
+
`c64_demo_briefing` and `c64_game_briefing` gain a `budget` block: the
|
|
1656
|
+
sum of `cycles_per_frame` over the proposed set against the region's
|
|
1657
|
+
frame (PAL 19,656; NTSC 17,095) and the sum of code and data bytes
|
|
1658
|
+
against a stated 38,911-byte budget, with the techniques that have no
|
|
1659
|
+
cost line named so the sums read as floors, an over or under verdict,
|
|
1660
|
+
and the weakest basis word among the contributors. The techniques
|
|
1661
|
+
whose recipe pages state figures carry a line, each figure taking the
|
|
1662
|
+
basis its page supports and no more; a figure the page measured in VICE is `measured-vice`, one
|
|
1663
|
+
read off a build's segment listing is `derived-listing`, one worked
|
|
1664
|
+
from settled constants is `arithmetic`, and a judgement is `estimated`.
|
|
1665
|
+
`cycles_per_frame` is the worst frame the technique produces, not an
|
|
1666
|
+
average, and it is the technique's own work: the soft scroller states
|
|
1667
|
+
its carry frame as the shipped listing measured it, the frame-sync loop
|
|
1668
|
+
does not state its demonstration's stand-in payload, and a level-start
|
|
1669
|
+
map expand states nothing per frame.
|
|
1670
|
+
`c64_timing_budget` no longer reads `t.irq_overhead`, a property nothing
|
|
1671
|
+
ever wrote; the read always fell through to the 36-cycle default and
|
|
1672
|
+
the constant now stands alone.
|
|
1673
|
+
|
|
1674
|
+
|
|
1675
|
+
**The text monitor for debugging, and cc65 symbols in it (#15).** The
|
|
1676
|
+
VICE reference gained a section written from real sessions: how to reach
|
|
1677
|
+
the monitor prompt headless (the `-console` route fails on this build,
|
|
1678
|
+
measured; the remote monitor works), the stop and register lines and
|
|
1679
|
+
what their columns mean, step, next and until, break, watch and
|
|
1680
|
+
conditional breaks with their transcripts, measuring cycles between two
|
|
1681
|
+
breakpoints from two register lines and cross-checking the delta against
|
|
1682
|
+
sim6502 and arithmetic, memory dump and save, and what `-limitcycles`
|
|
1683
|
+
does to a stopped machine. The cc65 page gained "Debugging with VICE":
|
|
1684
|
+
build with the label-file flag, load the labels, break on `_main`, the
|
|
1685
|
+
hit quoted. The symbol-file table names the cc65 route.
|
|
1686
|
+
|
|
1687
|
+
**Demo forms are archetypes too (#17).** The cracktro pattern page is now
|
|
1688
|
+
an archetype reference of kind `demo`: the crack intro, the demo intro,
|
|
1689
|
+
the pack intro, the dentro and the 4K party intro are each an `Archetype`
|
|
1690
|
+
node with the same `FEATURES` and `RISKS` edges the game page has, every
|
|
1691
|
+
name taken from the page's own text and checklist and resolving in the
|
|
1692
|
+
graph. Demo parts are not a node type; a form is one node. `c64_demo_briefing`
|
|
1693
|
+
gains an optional `archetype` input and the path `c64_game_briefing`
|
|
1694
|
+
already had: the form's fingerprint is forced into the plan past the
|
|
1695
|
+
three-per-category cap, its pitfalls join the pitfalls, and the output
|
|
1696
|
+
carries `archetype` or `archetype_not_found` with every known name across
|
|
1697
|
+
both kinds. A demo form has no built-in fallback table. The CLI's
|
|
1698
|
+
`demo-briefing` gains `--archetype` and honours `--json`. Tools 1.24.0
|
|
1699
|
+
for the input; data 717 for the page.
|
|
1700
|
+
|
|
1701
|
+
**Batch seven: multi-file projects and error tables on the toolchain
|
|
1702
|
+
pages, a sprite sine chain, a luminance fade.** Each toolchain page has
|
|
1703
|
+
a "Multi-file projects" section with a real two-file project built and
|
|
1704
|
+
the failing forms provoked (Oscar64 pulls a library's source in through
|
|
1705
|
+
`#pragma compile` from its header; one positional file with an extern
|
|
1706
|
+
fails with 3022; KickAssembler's `.import source` without a namespace
|
|
1707
|
+
clashes), and a "Reading the errors" table whose every message was
|
|
1708
|
+
provoked against the installed tool and quoted verbatim, the minimal
|
|
1709
|
+
sources kept under `toolchains/error-sources/`. `sprite_sine_chain` on
|
|
1710
|
+
the sprite page with the `sprite-sine-chain` recipe: eight sprites
|
|
1711
|
+
phased along one table across the full width with the $D010 wrap on the
|
|
1712
|
+
picture; the cracktro pattern page had named a multiplexer for this. A
|
|
1713
|
+
new `techniques/transitions.md` with `colour_fade` and the `colour-fade`
|
|
1714
|
+
recipe: a sixteen-step luminance-ordered fade, pinned mid-way on both
|
|
1715
|
+
models with every bar's colour checked against the table's formula; the
|
|
1716
|
+
first listing had an index overflow at the last step that the review
|
|
1717
|
+
caught. Colour cycling and the screen wipe are still to be written on
|
|
1718
|
+
that page.
|
|
1719
|
+
|
|
1720
|
+
**The 1541 DOS error codes (#14).** The IEC disk reference gained a
|
|
1721
|
+
table of every channel-15 code the 1541 DOS 2.6 ROM can produce, with the
|
|
1722
|
+
message text as the ROM spells it, the cause, and a class for an agent
|
|
1723
|
+
(retry, media, user error, program bug), read from the drive ROM image on
|
|
1724
|
+
this machine with the offsets cited, plus the mapping from D64 error
|
|
1725
|
+
bytes to DOS codes, which are not the same numbers. Four codes are
|
|
1726
|
+
provoked against a fresh disk by the `dos-error-codes` recipe and the
|
|
1727
|
+
replies pinned on both models; the codes that come only from the ROM text
|
|
1728
|
+
are marked as such. The file I/O page's two "not measured here" notes on
|
|
1729
|
+
message length and on codes 74 and 01 are closed by this and by the
|
|
1730
|
+
persistence recipe.
|
|
1731
|
+
|
|
1732
|
+
**Game archetypes are graph nodes (#17).** The archetype page had a
|
|
1733
|
+
technique fingerprint and a pitfall list for every archetype, and
|
|
1734
|
+
`c64_game_briefing` read none of them: it widened the search from a four-word table in code,
|
|
1735
|
+
forced techniques from a two-entry table and seeded a recipe for the one
|
|
1736
|
+
string "shmup". The page is now the source of truth. Each H2 with an
|
|
1737
|
+
`**Archetype:**` line is an `Archetype` node; its fingerprint becomes
|
|
1738
|
+
`FEATURES` edges to techniques and its common-pitfalls line `RISKS` edges
|
|
1739
|
+
to pitfalls, both MATCHed at both ends so a misspelt name is warned about
|
|
1740
|
+
and counted in the ingest summary, never dropped in silence
|
|
1741
|
+
(`docs/CONVENTIONS-archetypes.md`). The briefing looks the archetype up,
|
|
1742
|
+
forces every `FEATURES` target into the plan (exempt from the
|
|
1743
|
+
three-per-category cap), adds every `RISKS` target to the pitfalls and
|
|
1744
|
+
searches on the archetype's title; the output gains an `archetype` field
|
|
1745
|
+
repeating what the graph held, and a name the graph does not have returns
|
|
1746
|
+
`archetype_not_found` with the known names instead of doing nothing. The
|
|
1747
|
+
built-in tables survive only for a graph with no Archetype nodes, which
|
|
1748
|
+
is what the test fixtures build. Schema 21 for the label and two edge
|
|
1749
|
+
types; tools 1.23.0 for the two output fields; data 714 for the page.
|
|
1750
|
+
|
|
1751
|
+
**Two ontology repairs from the gap map (#17).** The briefing's toolchain
|
|
1752
|
+
handoff now decides by what a technique demands of the machine, read from
|
|
1753
|
+
the DEMANDS edges the compatibility checker already uses, instead of by
|
|
1754
|
+
category name: a technique that needs the CPU every line, raster
|
|
1755
|
+
interrupts inside the display, interrupts all frame, a badline-free
|
|
1756
|
+
region or a changing sprite set goes to KickAssembler, as does anything
|
|
1757
|
+
scene-tier. By category, starfield (effect) was handed to assembly and
|
|
1758
|
+
sprite_multiplex_24 (sprite) to C. And the recipe-to-tool link the
|
|
1759
|
+
ingester had always written now carries the ontology's name,
|
|
1760
|
+
`REQUIRES_TOOL`; it had been written as `USES`, which is why the
|
|
1761
|
+
ontology listed `REQUIRES_TOOL` as populated by nothing while the fact
|
|
1762
|
+
sat in the graph under the wrong label. Only `BUILDS_ON` remains
|
|
1763
|
+
unpopulated. Tools 1.22.2 for the handoff change (no surface change).
|
|
1764
|
+
|
|
1765
|
+
**Batch five: save-file policy, a sound-effect engine, memory layout in
|
|
1766
|
+
three toolchains, headless verification.** A "Save-file policy" section
|
|
1767
|
+
on the game-design page with the `high-score-persist` recipe: first run
|
|
1768
|
+
with no file, scratch-then-write with the scratch reply read, a version
|
|
1769
|
+
byte, and what the KERNAL reports with no disk (74) and with no drive
|
|
1770
|
+
emulated at all (the OPEN never returns in VICE; a real empty bus is not
|
|
1771
|
+
measured). Two things it measured that the file I/O page had marked as
|
|
1772
|
+
not measured: the drive's 74 reply and the command channel's "01, FILES
|
|
1773
|
+
SCRATCHED" reply, which is lost if channel 15 is closed before it is
|
|
1774
|
+
read. `sfx_engine_beside_music` on the SID page with the `sfx-engine`
|
|
1775
|
+
recipe: a table-driven effect with priority, borrowing a voice from a
|
|
1776
|
+
tune that writes all three and giving it back, verified at register
|
|
1777
|
+
level with a checksum over the writes; the page says nobody has listened
|
|
1778
|
+
to it. A new page `toolchains/memory-layout-planning.md`: the constraints
|
|
1779
|
+
that decide a layout and one worked layout expressed in KickAssembler,
|
|
1780
|
+
Oscar64 and cc65, each confirmed from its map output and each with a
|
|
1781
|
+
`memory-layout` recipe pinned on both models; the cc65 one needed a
|
|
1782
|
+
linker configuration, so `check:listings` and `verify:recipes` now pass
|
|
1783
|
+
a config a cc65 page carries in a fence tagged `cfg`, which is what let
|
|
1784
|
+
that recipe land instead of being held back. "Verifying a run without a
|
|
1785
|
+
human" on the VICE reference with two `headless-verify` recipes: a
|
|
1786
|
+
result byte at $02FF and the border colour, read back either from the
|
|
1787
|
+
exit screenshot or over the monitor, returning a shell exit code; both
|
|
1788
|
+
routes run on the green and the red case.
|
|
1789
|
+
|
|
1790
|
+
**Batch four: double buffer, Oscar64 save and load, text input, the IRQ
|
|
1791
|
+
chain.** `screen_double_buffer_d018` on the banking page with the
|
|
1792
|
+
`double-buffer` recipe and a companion built without the sprite-pointer
|
|
1793
|
+
mirror, whose corrupted sprite is identified byte for byte; the
|
|
1794
|
+
game-design page's "2 KB per page" corrected to 1 KB. The
|
|
1795
|
+
`save-load-seq-file` recipe: Oscar64's kernalio.h writing a score table,
|
|
1796
|
+
reading it back with the library status after every step and the drive's
|
|
1797
|
+
own reply, and a provoked 62 FILE NOT FOUND. A new page
|
|
1798
|
+
`techniques/text.md` (category `text`) with `text_input_line` and the
|
|
1799
|
+
`text-input` recipe, driven headless through VICE's keyboard buffer with
|
|
1800
|
+
the escape syntax that actually works quoted. `irq_chain_table` on the
|
|
1801
|
+
raster page with the `irq-chain` recipe: a three-slot table walked by one
|
|
1802
|
+
dispatcher, band boundaries measured from the picture and the frame
|
|
1803
|
+
counter predicted and matched. The verifier now switches the emulated
|
|
1804
|
+
drive's RPM wobble off for disk recipes: with it on, a disk run's elapsed
|
|
1805
|
+
cycles moved by a digit between runs and the NTSC round-trip picture
|
|
1806
|
+
failed to repeat.
|
|
1807
|
+
|
|
1808
|
+
**Batch three: object pool, KERNAL file I/O, and the instrument itself
|
|
1809
|
+
documented.** An "Object pool" section on the game-design patterns page
|
|
1810
|
+
with the `object-pool` recipe: slot table, spawn scan and free list,
|
|
1811
|
+
wave-table byte layout, despawn, per-slot timers, iterating active slots
|
|
1812
|
+
only, each timed, and the scripted scenario checksummed on the 6502. A
|
|
1813
|
+
new page `techniques/file-io.md` under the `io` category with
|
|
1814
|
+
`kernal_file_write_seq`, `kernal_file_read_seq`, `error_channel_check`
|
|
1815
|
+
and `kernal_load_to_address`, linked from three existing pitfalls, and
|
|
1816
|
+
the `file-io-roundtrip` recipe, which writes a file to a fresh disk,
|
|
1817
|
+
reads it back, checks the error channel before and after and prints the
|
|
1818
|
+
match and checksum; the verifier formats that disk with c1541 before
|
|
1819
|
+
every run. The VICE reference gained rows for every flag the KB's own
|
|
1820
|
+
protocol uses, each confirmed against `x64sc -help` and the
|
|
1821
|
+
autostart modes measured, and a section "Reading the exit screenshot"
|
|
1822
|
+
with the pixel geometry for both models, the sixteen palette RGB triples
|
|
1823
|
+
measured by the new `palette-cells` recipe, and a decode snippet; the
|
|
1824
|
+
recipe conventions, CLAUDE.md and the screenshot READMEs now point at it
|
|
1825
|
+
instead of carrying their own copies.
|
|
1826
|
+
|
|
1827
|
+
**Game foundations, batch two: tile maps, printing numbers, random
|
|
1828
|
+
numbers, lookup tables.** Four more gap-map items (#13, #16), same
|
|
1829
|
+
writer, reviewer and reviser shape. `tile_map_render` on the scroll page
|
|
1830
|
+
with the `tile-map-render` recipe: a hand-written RLE-compressed metatile
|
|
1831
|
+
map decoded to screen and colour RAM, every one of its 880 cells compared
|
|
1832
|
+
against a Python render of the same source data with zero differences,
|
|
1833
|
+
and the decoder's cost measured. A "Printing numbers" section on the
|
|
1834
|
+
game-design patterns page with the `print-number` recipe: subtract-powers
|
|
1835
|
+
and double-dabble in C and in assembly, every value from 0 to 65535
|
|
1836
|
+
rendered on the 6502 and folded into a checksum that matches Python, and
|
|
1837
|
+
the routes timed, which corrected the page's earlier "about 300 cycles"
|
|
1838
|
+
for double-dabble. `lfsr_random` on the maths page with the
|
|
1839
|
+
`lfsr-random` recipe and a fixed-seed companion: 8- and 16-bit LFSRs
|
|
1840
|
+
with measured periods and a histogram, seeding from SID voice 3 noise
|
|
1841
|
+
with the output muted, the CIA timer and player timing, and a new
|
|
1842
|
+
pitfall `lfsr_zero_state_lockup` with its MITIGATED_BY edge.
|
|
1843
|
+
`table_generation` on the CPU tricks page: sine, reciprocal and multiply
|
|
1844
|
+
tables at KickAssembler assembly time and in Oscar64, with the table bytes
|
|
1845
|
+
dumped from the built PRG and diffed to zero against Python for two
|
|
1846
|
+
scalings. Cross-links added from the pages that already used these
|
|
1847
|
+
things without naming them (the scroll pattern, the CharPad section, the
|
|
1848
|
+
sine scroller, the `.fill` row, the perspective divide, the $D41B
|
|
1849
|
+
paragraph).
|
|
1850
|
+
|
|
1851
|
+
**Game foundations, batch one: input, the frame loop, fixed-point
|
|
1852
|
+
movement.** The first additive batch from the gap map (#12, #13),
|
|
1853
|
+
written by one writer, one reviewer and one reviser per item. Two new
|
|
1854
|
+
technique pages and one new entry: `techniques/input.md` with
|
|
1855
|
+
`joystick_edge_detect`, `joystick_autorepeat` and `keyboard_matrix_scan`
|
|
1856
|
+
(category `input`); `techniques/maths.md` with `fixed_point_8_8`,
|
|
1857
|
+
`table_multiply_8x8` and `jump_arc_table` (category `maths`); and
|
|
1858
|
+
`frame_sync_loop` on the raster page, with the seven `vic_wait*`
|
|
1859
|
+
functions documented on the Oscar64 headers page from the header and its
|
|
1860
|
+
source. Each has an Oscar64 recipe with pinned, measured screenshots on
|
|
1861
|
+
PAL and NTSC: `joystick-input`, `frame-sync-loop` (plus a deliberate
|
|
1862
|
+
overrun build that shows the budget bar wrap and the dropped-frame
|
|
1863
|
+
counter climb), and `fixed-point-jump`. The arithmetic is checked
|
|
1864
|
+
exhaustively on the 6502 itself: the edge and repeat logic over all
|
|
1865
|
+
65,536 previous/current port pairs, the tick arithmetic over all 65,536
|
|
1866
|
+
counter pairs, the multiply and signed add over all 65,536 operand
|
|
1867
|
+
pairs, each folded to a checksum that matches the same computation in
|
|
1868
|
+
Python and is quoted on the page. What could not be done headless is
|
|
1869
|
+
said plainly: no joystick or key was pressed in any run, so the live
|
|
1870
|
+
counters prove the no-input state and the logic is proven by the
|
|
1871
|
+
exhaustive checks.
|
|
1872
|
+
|
|
1873
|
+
**Every recipe, toolchain and runtime page audited against the installed
|
|
1874
|
+
tools, and every recipe now has a reproducible screenshot.** The seven
|
|
1875
|
+
toolchain and runtime references went through the same auditor, three
|
|
1876
|
+
refuters and fixer procedure as the earlier waves: 95 corrections, among
|
|
1877
|
+
them x64sc 3.10 options that do not exist, Oscar64 API names and
|
|
1878
|
+
signatures checked against the headers on disk, KickAssembler behaviour
|
|
1879
|
+
measured on 5.25, the cc65 CPU flag for illegal mnemonics, and the
|
|
1880
|
+
binary-monitor claims. The twenty recipe pages went through a lean pass
|
|
1881
|
+
instead, one instrument-backed agent per page with no refuter fleet,
|
|
1882
|
+
because the maintainer asked for the token spend to come down: 102
|
|
1883
|
+
corrections, 60 claims qualified as not measured here. Among the
|
|
1884
|
+
corrections: the KERNAL's full interrupt service costs about 190 cycles
|
|
1885
|
+
idle and about 1,600 with a key held, not "about a thousand" (raster-bars
|
|
1886
|
+
and the pages that quoted it); the FLI entry pad was one cycle late and
|
|
1887
|
+
the committed picture showed the symptom on line 52; the side-border
|
|
1888
|
+
recipe's sixth sprite had the wrong MSB and sat invisible; the Oscar64
|
|
1889
|
+
soft-scroller wrote PETSCII where screen codes were needed and never
|
|
1890
|
+
showed its message; the Koala viewer cleared CSEL while enabling
|
|
1891
|
+
multicolour and embedded a zero-filled stub, and now draws a computed
|
|
1892
|
+
test image; `vspr_init` does not call `rirq_init`, so two recipes ran
|
|
1893
|
+
without an IRQ dispatcher; PSID header offsets were shifted by a word;
|
|
1894
|
+
the filter-cutoff byte split was backwards; `joy_poll(1)` read port 1
|
|
1895
|
+
where port 2 was documented. Then `verify:recipes` re-ran all twenty
|
|
1896
|
+
recipes at pinned cycles and every baseline was looked at against its
|
|
1897
|
+
page before adoption: nine recipes that had no committed picture have one,
|
|
1898
|
+
six unpinned or wrong-path baselines were replaced, and the NTSC playfield
|
|
1899
|
+
picture is now taken at the same cycle count as the PAL one. The
|
|
1900
|
+
soft-scroller's coarse shift still takes about four frames and tears;
|
|
1901
|
+
that is issue #18. Two cross-page debts the agents flagged were closed by
|
|
1902
|
+
hand: the raster technique page's KERNAL figure and the stable-raster
|
|
1903
|
+
recipe's register list. Clean ingest afterwards: 2,605 chunks from 79
|
|
1904
|
+
files, 574 nodes, 1,308 edges, 0 dropped references, no category refused.
|
|
1905
|
+
|
|
1906
|
+
**Schema 20: technique categories for game and application foundations,
|
|
1907
|
+
and the category set is enforced.** `input`, `logic`, `maths`, `text` and
|
|
1908
|
+
`io` join the Technique category set, and `render`, which the text-mode
|
|
1909
|
+
page had used since it was written without ever being listed, is now
|
|
1910
|
+
listed. The extractor refuses a technique doc whose category is outside
|
|
1911
|
+
the set, with a warning, the way it already refused an unknown Demands
|
|
1912
|
+
word; before this a typo would have created a category the briefing
|
|
1913
|
+
tools do not know. Briefings place input and maths in the memory-layout
|
|
1914
|
+
step, logic and text in the rendering step, io in the loader step, and
|
|
1915
|
+
give each a reason string. This is item ONTO-01 of the gap map (#12,
|
|
1916
|
+
#17) and lands first because the game-foundation pages file under
|
|
1917
|
+
categories that did not exist. Tools 1.22.1: the `c64_timing_budget`
|
|
1918
|
+
description said 23 badline cycles and a 14-cycle default IRQ overhead
|
|
1919
|
+
while the tool computed 43 and 36; the description now matches the
|
|
1920
|
+
computation and its worked example is the tool's actual output.
|
|
1921
|
+
|
|
1922
|
+
**Every technique and pitfall page audited against the instruments.** The
|
|
1923
|
+
same procedure as the hardware pages — one auditor per page, three
|
|
1924
|
+
refuters per finding, majority-upheld corrections only — over all 22
|
|
1925
|
+
pages: 259 corrections landed, each with the earlier wrong statement named
|
|
1926
|
+
beside it. The largest: the stable-raster polling loop bounds jitter to
|
|
1927
|
+
one iteration and does not remove it (`double_irq` does); the KERNAL's IRQ
|
|
1928
|
+
path never executes CLD; a `$0314` handler that ends in RTI pops the
|
|
1929
|
+
dispatcher's registers as its return frame, and four listings did; the
|
|
1930
|
+
`$D017` "double-write" trick does nothing and the sprite crunch is one
|
|
1931
|
+
cycle, one shot and lengthens the sprite; sprite DMA is 2 cycles per
|
|
1932
|
+
sprite plus 3 per group, never 4; badlines cost 40-43 cycles, plan on 43;
|
|
1933
|
+
the main-loop joystick "phantom press" race cannot happen; Krill v194
|
|
1934
|
+
hooks no KERNAL vector; ByteBoozer 2's depacker is about 200 bytes, not
|
|
1935
|
+
85; every depacker time quoted in milliseconds was under one cycle per
|
|
1936
|
+
byte; the Oscar64 vspr multiplexer costs about 250 cycles a slot, not 25;
|
|
1937
|
+
a 1000-cell text redraw does not fit a frame; PSID header offsets were
|
|
1938
|
+
shifted by a word; the filter cannot be observed from software, so the
|
|
1939
|
+
ENV3 chip-detect probe never worked. Sixteen findings nothing on this
|
|
1940
|
+
machine can reach are listed for follow-up. Metadata lines changed on
|
|
1941
|
+
eight pages, so the graph was rebuilt clean: 2,597 chunks from 78 files,
|
|
1942
|
+
574 nodes, 1,296 edges, 0 dropped references.
|
|
1943
|
+
|
|
1944
|
+
**Every hardware reference page audited against the instruments.** Nine
|
|
1945
|
+
pages (6510, VIC-II, PAL/NTSC, registers, KERNAL routines, CIA, SID,
|
|
1946
|
+
memory map, illegal opcodes): one auditor per page, three independent
|
|
1947
|
+
refuters per finding, majority-upheld corrections only. 193 corrections
|
|
1948
|
+
landed, each with the earlier wrong statement named beside it — among
|
|
1949
|
+
them the KERNAL's ~60 Hz jiffy on PAL as well as NTSC, the region flag at
|
|
1950
|
+
$02A6, the last default badline at 243, the TOD latch on hours, RESTORE
|
|
1951
|
+
outside CIA2, the SID's held bus byte, $EA7E as an exit rather than a
|
|
1952
|
+
shortcut, and the rebuilt KERNAL/BASIC ROM sub-maps. Twelve findings the
|
|
1953
|
+
refuters could not settle with anything on this machine are left as
|
|
1954
|
+
they stand and listed for follow-up. VICE on this machine is 3.10, and
|
|
1955
|
+
the instrument table says so.
|
|
1956
|
+
|
|
1957
|
+
**Two relations the graph could not state.** `REQUIRES` (Technique →
|
|
1958
|
+
Technique, schema 19): "this technique presupposes that one is set up or
|
|
1959
|
+
running underneath it", authored with a `**Requires:**` line. Twelve
|
|
1960
|
+
entries carry one, each from its own text — `text_zoom` requires
|
|
1961
|
+
`stable_raster_irq` ("a stable raster IRQ set to fire on every scanline"),
|
|
1962
|
+
`infinite_scroll_h` requires `soft_scroll_h` and `char_scroll_buffer_h`,
|
|
1963
|
+
`sideborder_open` requires `double_irq`, `ifli_image` requires `fli_image`,
|
|
1964
|
+
the SID filter, play-routine and hard-restart digi entries require
|
|
1965
|
+
`sid_voice_setup` (`digi_4bit` does not: it drives the $D418 volume DAC
|
|
1966
|
+
with every voice gated off, and a line only another entry's text supports
|
|
1967
|
+
is not authored — an earlier draft had it). `double_irq` is a variant of
|
|
1968
|
+
`stable_raster_irq`, not a prerequisite, and has no REQUIRES edge to or
|
|
1969
|
+
from it; it is the target of `sideborder_open`'s REQUIRES and of
|
|
1970
|
+
`raster_irq_first_line_jitter`'s MITIGATED_BY. `MITIGATED_BY` (Pitfall →
|
|
1971
|
+
Technique): "applying this
|
|
1972
|
+
technique is the Fix", authored with `**Mitigated by techniques:**`, which
|
|
1973
|
+
separates the remedy from the trigger the one vocabulary used to carry —
|
|
1974
|
+
`sprite_dma_overflow` is triggered by a naive multiplexer and mitigated by
|
|
1975
|
+
a correct one, `raster_irq_first_line_jitter` by `stable_raster_irq` and
|
|
1976
|
+
`double_irq`, the three region-timing pitfalls by `pal_ntsc_detection`,
|
|
1977
|
+
which had no edge to any of them, and `jmp_indirect_page_boundary_bug` by
|
|
1978
|
+
`jump_table_dispatch`'s store-then-jump form. Both edges MATCH both ends
|
|
1979
|
+
(no stubs from typos), are counted in the ingest summary, and a REQUIRES
|
|
1980
|
+
line that would close a cycle is refused. `BUILDS_ON` is still listed and
|
|
1981
|
+
still emitted by nothing; the ontology now says so.
|
|
1982
|
+
|
|
1983
|
+
**Tools (1.22.0, additive).** `c64_technique_lookup` gains `requires`,
|
|
1984
|
+
`required_by` and `mitigates`; `c64_techniques_for` gains a `requires`
|
|
1985
|
+
filter that follows the chain; `c64_pitfalls_for` answers for a technique
|
|
1986
|
+
that is only a remedy and reports `mitigated_by[]` apart from
|
|
1987
|
+
`triggered_by[]`; `c64_check_compatibility` takes each technique's
|
|
1988
|
+
REQUIRES closure and runs its hard rules between one technique's
|
|
1989
|
+
prerequisites and the other, reporting `prerequisite_conflict` (with the
|
|
1990
|
+
implied techniques in `via`) and a `missing_prerequisite` note for every
|
|
1991
|
+
technique the set leans on without naming — never against a prerequisite
|
|
1992
|
+
the technique declared itself, and without changing any technique's
|
|
1993
|
+
demands. `c64_suggest_links` proposes `pitfall_mitigated_by_technique`
|
|
1994
|
+
for a technique named in a Fix section instead of misfiling it as a
|
|
1995
|
+
trigger. `text_zoom` also gains `**Demands:** midframe_raster_irqs` from
|
|
1996
|
+
its own text, so `fli_image + text_zoom` is refused directly (cpu_vs_irq)
|
|
1997
|
+
rather than through a closure that both techniques' shared prerequisite
|
|
1998
|
+
would silence. Single-file ingest (`ingest-doc`) now applies `DEMANDS`
|
|
1999
|
+
edges too; it had skipped them — and `OCCUPIES` (a recipe's load
|
|
2000
|
+
addresses), which an exhaustiveness guard added to its switch found
|
|
2001
|
+
skipped as well; the next omission is a compile error, not a silent skip.
|
|
2002
|
+
|
|
2003
|
+
**RESTORE is not a CIA2 interrupt source.** Three pages said the RESTORE
|
|
2004
|
+
key reached the CPU through CIA2's /FLAG pin as `$DD0D` bit 4 and that
|
|
2005
|
+
`$DD0D = $10` switched it off; the key drives the 6510's /NMI pin directly,
|
|
2006
|
+
in parallel with CIA2's /IRQ, and no `$DD0D` write affects it. The KERNAL
|
|
2007
|
+
handler at `$FE43` is `SEI : JMP ($0318)` with the register pushes at
|
|
2008
|
+
`$FE47` *after* the vector, no BRK test, and a `BMI` on `$DD0D` bit 7 —
|
|
2009
|
+
it recognises RESTORE by finding *no* CIA2 flag (ROM bytes of 901227-03).
|
|
2010
|
+
New pitfall `restore_nmi_not_maskable` in `pitfalls/kernal-and-io.md`,
|
|
2011
|
+
triggered by `DD0D`, `RESTOR`, `VECTOR`: taking `$0318` costs 20 cycles a
|
|
2012
|
+
press (7 + 2 + 5 + 6), and an unacknowledged CIA2 NMI locks the
|
|
2013
|
+
edge-triggered input (two Timer A underflows, one NMI) — both measured in
|
|
2014
|
+
VICE x64sc 3.10. `cia-reference.md`'s NMI-vector list and its
|
|
2015
|
+
"re-entered immediately because the 555 still holds the line low" bullet
|
|
2016
|
+
rewritten; `c64-registers-reference.md` and `c64-memory-map.md` wiring
|
|
2017
|
+
lines corrected; the reset table's `$DC00 = $7F` now reads "column 7 low".
|
|
2018
|
+
|
|
2019
|
+
**Source catalogs removed from `docs/`.** `docs/catalogs/` held two
|
|
2020
|
+
manifests — `source-catalog.json` (137 entries) and
|
|
2021
|
+
`source-corpus-catalog.json` (71 entries) — plus their two readmes. They
|
|
2022
|
+
listed third-party C64 sources, per-author repository inventories, and
|
|
2023
|
+
in-repo path fingerprints (`pattern_signals`) for code this project never
|
|
2024
|
+
ingested, and the readmes cross-referenced unrelated projects of the
|
|
2025
|
+
author's. None of it fed the knowledge base: the ingest reads `*.md` only,
|
|
2026
|
+
so the two JSON manifests were never indexed at all, and the two readmes
|
|
2027
|
+
carried no frontmatter and no metadata lines, so they extracted zero graph
|
|
2028
|
+
entities. The measured impact is 18 Qdrant chunks and the `catalogs` bucket
|
|
2029
|
+
in `c64-kb health`, whose entry in `C64_BUCKETS` (`src/services/qdrant.ts`)
|
|
2030
|
+
is dropped with them. No graph node, edge, tool, recipe, listing or test
|
|
2031
|
+
referenced the directory. Doc counts in `README.md` and `CLAUDE.md` drop
|
|
2032
|
+
from 75/69 markdown files to 73/67.
|
|
2033
|
+
|
|
2034
|
+
**README chunk figure re-measured.** It read 2,422 and was stale: neither
|
|
2035
|
+
`36d1843` nor the 6510 audit in `5526a80` updated it, and the 6510 page
|
|
2036
|
+
alone went 258 -> 264 chunks. Running `chunkMarkdown` over all 73 files at
|
|
2037
|
+
this commit gives 2,516, which is what a clean ingest would upsert. The
|
|
2038
|
+
table now says it is a chunker measurement, not a live collection reading.
|
|
2039
|
+
|
|
2040
|
+
Note: the files remain in git history from `fac663a` onward and in the
|
|
2041
|
+
public fork. Removing them here removes them from the working tree, not
|
|
2042
|
+
from the record.
|
|
2043
|
+
|
|
2044
|
+
## 0.8.0 — 2026-09-22
|
|
2045
|
+
|
|
2046
|
+
Data 702, schema 18, tools 1.21.1.
|
|
2047
|
+
|
|
2048
|
+
**Recipes: assembled, run, rewritten.** None of the eight KickAssembler
|
|
2049
|
+
recipes had been assembled before this release: six did not assemble, one
|
|
2050
|
+
ran and did nothing, one was a plain raster IRQ named "stable". All eight
|
|
2051
|
+
are rewritten, built with KickAssembler 5.25, run headless in VICE x64sc
|
|
2052
|
+
and measured from the screenshot, with the pictures kept in
|
|
2053
|
+
`docs/recipes/kickassembler/screenshots/`. Four Oscar64 recipes fixed
|
|
2054
|
+
(compiler crash on a const function pointer, unreferenced stub array
|
|
2055
|
+
dropped by the linker, IRQ slot table overflow, GCC attribute syntax).
|
|
2056
|
+
`npm run check:listings` builds every listing and is part of `npm test`.
|
|
2057
|
+
|
|
2058
|
+
**Technique text corrected.** Badline budget is 20 cycles guaranteed
|
|
2059
|
+
(23 optimistic), not 23 flat. FLI is a forced badline per line with the
|
|
2060
|
+
$D011 write on cycle 15. The side border is one write cycle (56) with no
|
|
2061
|
+
left-border toggle. VSP is a late-$D011 DMA delay, not a CSEL toggle. The
|
|
2062
|
+
KERNAL dispatcher is at $FF48 (29 cycles); $EA31 is the full service
|
|
2063
|
+
routine, $EA81 the bare exit. DEN is sampled once per frame on line $30.
|
|
2064
|
+
|
|
2065
|
+
**Compatibility checker can say no.** Technique entries carry a
|
|
2066
|
+
`**Demands:**` line from a fixed vocabulary; `c64_check_compatibility`
|
|
2067
|
+
derives hard conflicts (cpu_exclusive, cpu_vs_irq, sprite_set,
|
|
2068
|
+
kernal_banked_out, region_mismatch) with a resolution each, keeps shared
|
|
2069
|
+
register / KERNAL as soft warnings, and reports per technique what the
|
|
2070
|
+
graph does not know instead of clearing it. `timing-budget` uses 43 cycles
|
|
2071
|
+
lost per badline and 36 of IRQ overhead.
|
|
2072
|
+
|
|
2073
|
+
**Graph and ingest.** New `Resource` node label and `DEMANDS`, `IN_REGION`,
|
|
2074
|
+
`OCCUPIES` edges (schema 18). Ingest deletes a file's old chunks before
|
|
2075
|
+
upserting, `--clean`/`--force` recreate the vector collection, unresolved
|
|
2076
|
+
references are warned about and counted, and eight that had been dropped
|
|
2077
|
+
silently are fixed in the docs.
|
|
2078
|
+
|
|
2079
|
+
**Hardening.** `npm test` runs against a throwaway graph and collection.
|
|
2080
|
+
README, ARCHITECTURE and ONTOLOGY rewritten to match the code: 23 tools,
|
|
2081
|
+
12 resources, 12 node labels, 15 edge types, Node 24, root `.mcp.json`.
|
|
2082
|
+
Eight npm scripts pointing at files not in this repository removed.
|