c64-kb 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2082 -0
- package/LICENSE +29 -0
- package/README.md +559 -0
- package/VERSION +25 -0
- package/dist/cli/setup.js +66 -0
- package/dist/cli/setup.js.map +1 -0
- package/dist/cli-memorize-audit.js +97 -0
- package/dist/cli-memorize-audit.js.map +1 -0
- package/dist/cli.js +335 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.js +83 -0
- package/dist/config.js.map +1 -0
- package/dist/context.js +53 -0
- package/dist/context.js.map +1 -0
- package/dist/domain/budget-notes.js +104 -0
- package/dist/domain/budget-notes.js.map +1 -0
- package/dist/domain/budget.js +417 -0
- package/dist/domain/budget.js.map +1 -0
- package/dist/domain/game-design.js +77 -0
- package/dist/domain/game-design.js.map +1 -0
- package/dist/domain/timing.js +39 -0
- package/dist/domain/timing.js.map +1 -0
- package/dist/graph/apply.js +132 -0
- package/dist/graph/apply.js.map +1 -0
- package/dist/graph/claims.js +231 -0
- package/dist/graph/claims.js.map +1 -0
- package/dist/graph/extract/archetype.js +118 -0
- package/dist/graph/extract/archetype.js.map +1 -0
- package/dist/graph/extract/common.js +69 -0
- package/dist/graph/extract/common.js.map +1 -0
- package/dist/graph/extract/failure.js +37 -0
- package/dist/graph/extract/failure.js.map +1 -0
- package/dist/graph/extract/game-design.js +189 -0
- package/dist/graph/extract/game-design.js.map +1 -0
- package/dist/graph/extract/hardware.js +124 -0
- package/dist/graph/extract/hardware.js.map +1 -0
- package/dist/graph/extract/pitfall.js +62 -0
- package/dist/graph/extract/pitfall.js.map +1 -0
- package/dist/graph/extract/raster-band.js +56 -0
- package/dist/graph/extract/raster-band.js.map +1 -0
- package/dist/graph/extract/recipe.js +71 -0
- package/dist/graph/extract/recipe.js.map +1 -0
- package/dist/graph/extract/technique-entities.js +180 -0
- package/dist/graph/extract/technique-entities.js.map +1 -0
- package/dist/graph/extract/technique.js +179 -0
- package/dist/graph/extract/technique.js.map +1 -0
- package/dist/graph/extract/toolchain.js +67 -0
- package/dist/graph/extract/toolchain.js.map +1 -0
- package/dist/graph/extract/types.js +3 -0
- package/dist/graph/extract/types.js.map +1 -0
- package/dist/graph/extract/vocabulary.js +65 -0
- package/dist/graph/extract/vocabulary.js.map +1 -0
- package/dist/graph/extract.js +43 -0
- package/dist/graph/extract.js.map +1 -0
- package/dist/graph/kernal-clobbers.js +64 -0
- package/dist/graph/kernal-clobbers.js.map +1 -0
- package/dist/graph/machine-variants.js +208 -0
- package/dist/graph/machine-variants.js.map +1 -0
- package/dist/ingest/files.js +99 -0
- package/dist/ingest/files.js.map +1 -0
- package/dist/ingest/passes.js +104 -0
- package/dist/ingest/passes.js.map +1 -0
- package/dist/ingest/points.js +50 -0
- package/dist/ingest/points.js.map +1 -0
- package/dist/ingest/report.js +140 -0
- package/dist/ingest/report.js.map +1 -0
- package/dist/ingest/tally.js +81 -0
- package/dist/ingest/tally.js.map +1 -0
- package/dist/ingest/verified-on.js +43 -0
- package/dist/ingest/verified-on.js.map +1 -0
- package/dist/ingest.js +135 -0
- package/dist/ingest.js.map +1 -0
- package/dist/schemas/cost-basis.js +5 -0
- package/dist/schemas/cost-basis.js.map +1 -0
- package/dist/schemas/machine-variant.js +25 -0
- package/dist/schemas/machine-variant.js.map +1 -0
- package/dist/schemas/plan-budget.js +121 -0
- package/dist/schemas/plan-budget.js.map +1 -0
- package/dist/schemas/tool-outputs.js +526 -0
- package/dist/schemas/tool-outputs.js.map +1 -0
- package/dist/server/define-tool.js +52 -0
- package/dist/server/define-tool.js.map +1 -0
- package/dist/server/defined-only.js +9 -0
- package/dist/server/defined-only.js.map +1 -0
- package/dist/server/tools-briefings.js +70 -0
- package/dist/server/tools-briefings.js.map +1 -0
- package/dist/server/tools-lookup.js +180 -0
- package/dist/server/tools-lookup.js.map +1 -0
- package/dist/server/tools-maintenance.js +116 -0
- package/dist/server/tools-maintenance.js.map +1 -0
- package/dist/server/tools-pitfalls.js +89 -0
- package/dist/server/tools-pitfalls.js.map +1 -0
- package/dist/server/tools-recipes.js +296 -0
- package/dist/server/tools-recipes.js.map +1 -0
- package/dist/server/tools-runtime.js +48 -0
- package/dist/server/tools-runtime.js.map +1 -0
- package/dist/server/tools.js +43 -0
- package/dist/server/tools.js.map +1 -0
- package/dist/server.js +95 -0
- package/dist/server.js.map +1 -0
- package/dist/services/analytics/schema.js +78 -0
- package/dist/services/analytics/schema.js.map +1 -0
- package/dist/services/analytics/statements.js +99 -0
- package/dist/services/analytics/statements.js.map +1 -0
- package/dist/services/analytics.js +195 -0
- package/dist/services/analytics.js.map +1 -0
- package/dist/services/bm25.js +158 -0
- package/dist/services/bm25.js.map +1 -0
- package/dist/services/chunker.js +81 -0
- package/dist/services/chunker.js.map +1 -0
- package/dist/services/embeddings.js +58 -0
- package/dist/services/embeddings.js.map +1 -0
- package/dist/services/falkor/base.js +85 -0
- package/dist/services/falkor/base.js.map +1 -0
- package/dist/services/falkor/links.js +361 -0
- package/dist/services/falkor/links.js.map +1 -0
- package/dist/services/falkor/nodes.js +183 -0
- package/dist/services/falkor/nodes.js.map +1 -0
- package/dist/services/falkor/params.js +45 -0
- package/dist/services/falkor/params.js.map +1 -0
- package/dist/services/falkor/schema.js +77 -0
- package/dist/services/falkor/schema.js.map +1 -0
- package/dist/services/falkor.js +100 -0
- package/dist/services/falkor.js.map +1 -0
- package/dist/services/qdrant.js +238 -0
- package/dist/services/qdrant.js.map +1 -0
- package/dist/services/versions.js +73 -0
- package/dist/services/versions.js.map +1 -0
- package/dist/services/vice-bin.js +51 -0
- package/dist/services/vice-bin.js.map +1 -0
- package/dist/tools/briefings/archetype.js +174 -0
- package/dist/tools/briefings/archetype.js.map +1 -0
- package/dist/tools/briefings/budget.js +177 -0
- package/dist/tools/briefings/budget.js.map +1 -0
- package/dist/tools/briefings/build-order.js +135 -0
- package/dist/tools/briefings/build-order.js.map +1 -0
- package/dist/tools/briefings/build.js +185 -0
- package/dist/tools/briefings/build.js.map +1 -0
- package/dist/tools/briefings/discovery.js +290 -0
- package/dist/tools/briefings/discovery.js.map +1 -0
- package/dist/tools/briefings/plan-pitfalls.js +69 -0
- package/dist/tools/briefings/plan-pitfalls.js.map +1 -0
- package/dist/tools/briefings/render.js +151 -0
- package/dist/tools/briefings/render.js.map +1 -0
- package/dist/tools/briefings/rows.js +41 -0
- package/dist/tools/briefings/rows.js.map +1 -0
- package/dist/tools/briefings/toolchain.js +63 -0
- package/dist/tools/briefings/toolchain.js.map +1 -0
- package/dist/tools/briefings/why-proposed.js +69 -0
- package/dist/tools/briefings/why-proposed.js.map +1 -0
- package/dist/tools/briefings.js +44 -0
- package/dist/tools/briefings.js.map +1 -0
- package/dist/tools/feedback.js +97 -0
- package/dist/tools/feedback.js.map +1 -0
- package/dist/tools/hydrate.js +75 -0
- package/dist/tools/hydrate.js.map +1 -0
- package/dist/tools/intelligence.js +67 -0
- package/dist/tools/intelligence.js.map +1 -0
- package/dist/tools/lint/asm-decimal.js +86 -0
- package/dist/tools/lint/asm-decimal.js.map +1 -0
- package/dist/tools/lint/asm-rules.js +221 -0
- package/dist/tools/lint/asm-rules.js.map +1 -0
- package/dist/tools/lint/asm-shared.js +3 -0
- package/dist/tools/lint/asm-shared.js.map +1 -0
- package/dist/tools/lint/c-rules.js +215 -0
- package/dist/tools/lint/c-rules.js.map +1 -0
- package/dist/tools/lint/text.js +122 -0
- package/dist/tools/lint/text.js.map +1 -0
- package/dist/tools/lint/types.js +40 -0
- package/dist/tools/lint/types.js.map +1 -0
- package/dist/tools/lint.js +76 -0
- package/dist/tools/lint.js.map +1 -0
- package/dist/tools/memorization-mcp.js +111 -0
- package/dist/tools/memorization-mcp.js.map +1 -0
- package/dist/tools/pitfalls/bm25.js +53 -0
- package/dist/tools/pitfalls/bm25.js.map +1 -0
- package/dist/tools/pitfalls/format.js +58 -0
- package/dist/tools/pitfalls/format.js.map +1 -0
- package/dist/tools/pitfalls/graph.js +124 -0
- package/dist/tools/pitfalls/graph.js.map +1 -0
- package/dist/tools/pitfalls.js +134 -0
- package/dist/tools/pitfalls.js.map +1 -0
- package/dist/tools/prompts.js +81 -0
- package/dist/tools/prompts.js.map +1 -0
- package/dist/tools/query/compatibility/closure.js +62 -0
- package/dist/tools/query/compatibility/closure.js.map +1 -0
- package/dist/tools/query/compatibility/facts.js +28 -0
- package/dist/tools/query/compatibility/facts.js.map +1 -0
- package/dist/tools/query/compatibility/fetch.js +164 -0
- package/dist/tools/query/compatibility/fetch.js.map +1 -0
- package/dist/tools/query/compatibility/hard-rules.js +159 -0
- package/dist/tools/query/compatibility/hard-rules.js.map +1 -0
- package/dist/tools/query/compatibility/index.js +27 -0
- package/dist/tools/query/compatibility/index.js.map +1 -0
- package/dist/tools/query/compatibility/kernal-zp-rule.js +90 -0
- package/dist/tools/query/compatibility/kernal-zp-rule.js.map +1 -0
- package/dist/tools/query/compatibility/render.js +106 -0
- package/dist/tools/query/compatibility/render.js.map +1 -0
- package/dist/tools/query/compatibility/rules.js +337 -0
- package/dist/tools/query/compatibility/rules.js.map +1 -0
- package/dist/tools/query/compatibility/unit-rules.js +253 -0
- package/dist/tools/query/compatibility/unit-rules.js.map +1 -0
- package/dist/tools/query/game-design.js +83 -0
- package/dist/tools/query/game-design.js.map +1 -0
- package/dist/tools/query/lookups.js +220 -0
- package/dist/tools/query/lookups.js.map +1 -0
- package/dist/tools/query/plan-budget.js +266 -0
- package/dist/tools/query/plan-budget.js.map +1 -0
- package/dist/tools/query/recipes.js +214 -0
- package/dist/tools/query/recipes.js.map +1 -0
- package/dist/tools/query/retrieval.js +128 -0
- package/dist/tools/query/retrieval.js.map +1 -0
- package/dist/tools/query/shared.js +121 -0
- package/dist/tools/query/shared.js.map +1 -0
- package/dist/tools/query/techniques.js +331 -0
- package/dist/tools/query/techniques.js.map +1 -0
- package/dist/tools/query/timing.js +106 -0
- package/dist/tools/query/timing.js.map +1 -0
- package/dist/tools/query/types.js +11 -0
- package/dist/tools/query/types.js.map +1 -0
- package/dist/tools/query.js +21 -0
- package/dist/tools/query.js.map +1 -0
- package/dist/tools/resources.js +186 -0
- package/dist/tools/resources.js.map +1 -0
- package/dist/tools/run-game.js +249 -0
- package/dist/tools/run-game.js.map +1 -0
- package/dist/tools/selfimprovement.js +367 -0
- package/dist/tools/selfimprovement.js.map +1 -0
- package/docker-compose.yml +35 -0
- package/docs/ARCHITECTURE.md +164 -0
- package/docs/CONVENTIONS-archetypes.md +158 -0
- package/docs/CONVENTIONS-failures.md +46 -0
- package/docs/CONVENTIONS-game-designs.md +75 -0
- package/docs/CONVENTIONS-hardware-reference.md +184 -0
- package/docs/CONVENTIONS-pitfalls.md +91 -0
- package/docs/CONVENTIONS-recipes.md +106 -0
- package/docs/CONVENTIONS-techniques.md +309 -0
- package/docs/CONVENTIONS-toolchain-reference.md +89 -0
- package/docs/ONTOLOGY.md +655 -0
- package/docs/art/art-production-reference.md +157 -0
- package/docs/art/asset-pipelines.md +586 -0
- package/docs/c64-failure-patterns.md +693 -0
- package/docs/demo-design/demo-composition.md +349 -0
- package/docs/demo-design/demo-design-philosophy.md +320 -0
- package/docs/demo-design/intro-cracktro-patterns.md +435 -0
- package/docs/figures/ctm-spd-embed-probe.png +0 -0
- package/docs/figures/dot-flag-mid-5000000.png +0 -0
- package/docs/figures/dot-flag-no-erase-12000000.png +0 -0
- package/docs/figures/edges.json +1 -0
- package/docs/figures/fig6-architecture.png +0 -0
- package/docs/figures/fig7-ontology.png +0 -0
- package/docs/figures/screen-dissolve-mid-frame25.png +0 -0
- package/docs/figures/screen-dissolve-wipe-frame25.png +0 -0
- package/docs/figures/spindle-two-parts-part1.png +0 -0
- package/docs/figures/spindle-two-parts-part2.png +0 -0
- package/docs/figures/starters/action-puzzle.png +0 -0
- package/docs/figures/starters/adventure.png +0 -0
- package/docs/figures/starters/beat-em-up.png +0 -0
- package/docs/figures/starters/demo.png +0 -0
- package/docs/figures/starters/platformer.png +0 -0
- package/docs/figures/starters/shmup-vertical.png +0 -0
- package/docs/figures/tape-kernal-master-ntsc.png +0 -0
- package/docs/figures/tape-kernal-master-pal.png +0 -0
- package/docs/figures/tape-turbo-loader-ntsc.png +0 -0
- package/docs/figures/tape-turbo-loader-pal.png +0 -0
- package/docs/figures/tape-turbo-master-ntsc.png +0 -0
- package/docs/figures/tape-turbo-master-pal.png +0 -0
- package/docs/figures/tech-tech-pad2-12000000.png +0 -0
- package/docs/figures/tech-tech-pad4-12000000.png +0 -0
- package/docs/figures/tech-tech-seven-12000000.png +0 -0
- package/docs/figures/twister-mid-5000000.png +0 -0
- package/docs/figures/twister-straight-12000000.png +0 -0
- package/docs/figures/vector-balls-nosort-ntsc.png +0 -0
- package/docs/figures/vector-balls-nosort.png +0 -0
- package/docs/formats/c64-file-formats.md +1212 -0
- package/docs/formats/iec-disk-reference.md +754 -0
- package/docs/game-design/c64-game-archetypes.md +273 -0
- package/docs/game-design/designs/falling-blocks.md +54 -0
- package/docs/game-design/designs/platformer-scaffold.md +48 -0
- package/docs/game-design/designs/simple-shmup.md +27 -0
- package/docs/game-design/enemy-behaviour-and-difficulty.md +349 -0
- package/docs/game-design/game-design-patterns.md +1189 -0
- package/docs/game-design/game-structure.md +354 -0
- package/docs/game-design/production-planning.md +349 -0
- package/docs/game-design/reference-game-sources.md +90 -0
- package/docs/hardware/6502-illegal-opcodes.md +1353 -0
- package/docs/hardware/6510-cpu-reference.md +2112 -0
- package/docs/hardware/c64-memory-map.md +3184 -0
- package/docs/hardware/c64-registers-reference.md +996 -0
- package/docs/hardware/cia-reference.md +1281 -0
- package/docs/hardware/kernal-routines-reference.md +1836 -0
- package/docs/hardware/pal-ntsc-reference.md +813 -0
- package/docs/hardware/sid-reference.md +1137 -0
- package/docs/hardware/vic-ii-reference.md +1714 -0
- package/docs/music/music-production-reference.md +403 -0
- package/docs/pitfalls/banking.md +1067 -0
- package/docs/pitfalls/cia.md +1147 -0
- package/docs/pitfalls/cpu.md +874 -0
- package/docs/pitfalls/input.md +282 -0
- package/docs/pitfalls/kernal-and-io.md +1615 -0
- package/docs/pitfalls/loader.md +1191 -0
- package/docs/pitfalls/logic.md +94 -0
- package/docs/pitfalls/maths.md +187 -0
- package/docs/pitfalls/raster-and-badline.md +721 -0
- package/docs/pitfalls/region-timing.md +660 -0
- package/docs/pitfalls/scroll.md +207 -0
- package/docs/pitfalls/sid.md +738 -0
- package/docs/pitfalls/sprite.md +979 -0
- package/docs/pitfalls/text-mode-render.md +1172 -0
- package/docs/recipes/cc65/cartridge-8k.md +398 -0
- package/docs/recipes/cc65/hello-world-conio.md +76 -0
- package/docs/recipes/cc65/memory-layout.md +312 -0
- package/docs/recipes/cc65/screenshots/README.md +14 -0
- package/docs/recipes/cc65/screenshots/cartridge-8k-ntsc.png +0 -0
- package/docs/recipes/cc65/screenshots/cartridge-8k.png +0 -0
- package/docs/recipes/cc65/screenshots/hello-world-conio.png +0 -0
- package/docs/recipes/cc65/screenshots/memory-layout-ntsc.png +0 -0
- package/docs/recipes/cc65/screenshots/memory-layout.png +0 -0
- package/docs/recipes/kickassembler/basic-float-calls.md +578 -0
- package/docs/recipes/kickassembler/basic-wedge.md +398 -0
- package/docs/recipes/kickassembler/big-font-scroller.md +620 -0
- package/docs/recipes/kickassembler/charset-copy-rom-to-ram.md +623 -0
- package/docs/recipes/kickassembler/cia-revision-detect.md +366 -0
- package/docs/recipes/kickassembler/colour-cycling.md +343 -0
- package/docs/recipes/kickassembler/colour-fade.md +303 -0
- package/docs/recipes/kickassembler/compare-16bit-signed.md +1007 -0
- package/docs/recipes/kickassembler/cracktro-template.md +526 -0
- package/docs/recipes/kickassembler/crt-banked.md +276 -0
- package/docs/recipes/kickassembler/dos-error-codes.md +466 -0
- package/docs/recipes/kickassembler/dot-flag.md +576 -0
- package/docs/recipes/kickassembler/drive-job-queue.md +667 -0
- package/docs/recipes/kickassembler/drive-via-probe.md +690 -0
- package/docs/recipes/kickassembler/dycp-scroller.md +568 -0
- package/docs/recipes/kickassembler/dypp-sprite-scroller.md +681 -0
- package/docs/recipes/kickassembler/dysp.md +670 -0
- package/docs/recipes/kickassembler/easyflash-save.md +800 -0
- package/docs/recipes/kickassembler/eight-way-scroll.md +1484 -0
- package/docs/recipes/kickassembler/file-io-roundtrip.md +546 -0
- package/docs/recipes/kickassembler/fire-effect.md +420 -0
- package/docs/recipes/kickassembler/fld.md +414 -0
- package/docs/recipes/kickassembler/fli-image.md +336 -0
- package/docs/recipes/kickassembler/four-player-read.md +672 -0
- package/docs/recipes/kickassembler/headless-verify.md +228 -0
- package/docs/recipes/kickassembler/hello-world.md +98 -0
- package/docs/recipes/kickassembler/high-score-insert.md +660 -0
- package/docs/recipes/kickassembler/hires-plot-line.md +723 -0
- package/docs/recipes/kickassembler/irq-chain.md +316 -0
- package/docs/recipes/kickassembler/irq-owns-port.md +668 -0
- package/docs/recipes/kickassembler/isometric-room.md +1145 -0
- package/docs/recipes/kickassembler/light-pen-read.md +926 -0
- package/docs/recipes/kickassembler/logic-rate-decoupling.md +670 -0
- package/docs/recipes/kickassembler/mci-interlace.md +543 -0
- package/docs/recipes/kickassembler/memory-layout.md +277 -0
- package/docs/recipes/kickassembler/mouse-1351-read.md +801 -0
- package/docs/recipes/kickassembler/nmi-timer-tick.md +562 -0
- package/docs/recipes/kickassembler/own-keyscan.md +881 -0
- package/docs/recipes/kickassembler/paddle-read.md +751 -0
- package/docs/recipes/kickassembler/palette-cells.md +219 -0
- package/docs/recipes/kickassembler/pseudo-3d-road.md +930 -0
- package/docs/recipes/kickassembler/pwm-digi.md +463 -0
- package/docs/recipes/kickassembler/raster-bars.md +264 -0
- package/docs/recipes/kickassembler/reu-dma.md +1019 -0
- package/docs/recipes/kickassembler/runtime-relocation.md +743 -0
- package/docs/recipes/kickassembler/screen-dissolve.md +545 -0
- package/docs/recipes/kickassembler/screen-wipe.md +408 -0
- package/docs/recipes/kickassembler/screenshots/README.md +72 -0
- package/docs/recipes/kickassembler/screenshots/basic-float-calls-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/basic-float-calls.png +0 -0
- package/docs/recipes/kickassembler/screenshots/basic-wedge-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/basic-wedge.png +0 -0
- package/docs/recipes/kickassembler/screenshots/big-font-scroller-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/big-font-scroller.png +0 -0
- package/docs/recipes/kickassembler/screenshots/charset-copy-rom-to-ram-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/charset-copy-rom-to-ram.png +0 -0
- package/docs/recipes/kickassembler/screenshots/cia-revision-detect-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/cia-revision-detect.png +0 -0
- package/docs/recipes/kickassembler/screenshots/colour-cycling-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/colour-cycling.png +0 -0
- package/docs/recipes/kickassembler/screenshots/colour-fade-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/colour-fade.png +0 -0
- package/docs/recipes/kickassembler/screenshots/compare-16bit-signed-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/compare-16bit-signed.png +0 -0
- package/docs/recipes/kickassembler/screenshots/cracktro-template.png +0 -0
- package/docs/recipes/kickassembler/screenshots/crt-banked-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/crt-banked.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dos-error-codes-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dos-error-codes.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dot-flag-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dot-flag.png +0 -0
- package/docs/recipes/kickassembler/screenshots/drive-job-queue-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/drive-job-queue.png +0 -0
- package/docs/recipes/kickassembler/screenshots/drive-via-probe-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/drive-via-probe.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dycp-scroller-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dycp-scroller.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dypp-sprite-scroller-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dypp-sprite-scroller.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dysp-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dysp.png +0 -0
- package/docs/recipes/kickassembler/screenshots/easyflash-save-ntsc-run2.png +0 -0
- package/docs/recipes/kickassembler/screenshots/easyflash-save-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/easyflash-save-run2.png +0 -0
- package/docs/recipes/kickassembler/screenshots/easyflash-save.png +0 -0
- package/docs/recipes/kickassembler/screenshots/eight-way-scroll-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/eight-way-scroll.png +0 -0
- package/docs/recipes/kickassembler/screenshots/file-io-roundtrip-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/file-io-roundtrip.png +0 -0
- package/docs/recipes/kickassembler/screenshots/fire-effect-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/fire-effect.png +0 -0
- package/docs/recipes/kickassembler/screenshots/fld-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/fld.png +0 -0
- package/docs/recipes/kickassembler/screenshots/fli-image.png +0 -0
- package/docs/recipes/kickassembler/screenshots/four-player-read-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/four-player-read.png +0 -0
- package/docs/recipes/kickassembler/screenshots/headless-verify-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/headless-verify.png +0 -0
- package/docs/recipes/kickassembler/screenshots/hello-world.png +0 -0
- package/docs/recipes/kickassembler/screenshots/high-score-insert-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/high-score-insert.png +0 -0
- package/docs/recipes/kickassembler/screenshots/hires-plot-line-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/hires-plot-line.png +0 -0
- package/docs/recipes/kickassembler/screenshots/irq-chain-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/irq-chain.png +0 -0
- package/docs/recipes/kickassembler/screenshots/irq-owns-port-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/irq-owns-port.png +0 -0
- package/docs/recipes/kickassembler/screenshots/isometric-room-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/isometric-room.png +0 -0
- package/docs/recipes/kickassembler/screenshots/light-pen-read-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/light-pen-read.png +0 -0
- package/docs/recipes/kickassembler/screenshots/logic-rate-decoupling-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/logic-rate-decoupling.png +0 -0
- package/docs/recipes/kickassembler/screenshots/mci-interlace-average.png +0 -0
- package/docs/recipes/kickassembler/screenshots/mci-interlace-frame-b.png +0 -0
- package/docs/recipes/kickassembler/screenshots/mci-interlace-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/mci-interlace.png +0 -0
- package/docs/recipes/kickassembler/screenshots/memory-layout-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/memory-layout.png +0 -0
- package/docs/recipes/kickassembler/screenshots/mouse-1351-read-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/mouse-1351-read.png +0 -0
- package/docs/recipes/kickassembler/screenshots/nmi-timer-tick-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/nmi-timer-tick.png +0 -0
- package/docs/recipes/kickassembler/screenshots/own-keyscan-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/own-keyscan.png +0 -0
- package/docs/recipes/kickassembler/screenshots/paddle-read-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/paddle-read.png +0 -0
- package/docs/recipes/kickassembler/screenshots/palette-cells-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/palette-cells.png +0 -0
- package/docs/recipes/kickassembler/screenshots/pseudo-3d-road-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/pseudo-3d-road.png +0 -0
- package/docs/recipes/kickassembler/screenshots/pwm-digi-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/pwm-digi.png +0 -0
- package/docs/recipes/kickassembler/screenshots/raster-bars.png +0 -0
- package/docs/recipes/kickassembler/screenshots/reu-dma-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/reu-dma.png +0 -0
- package/docs/recipes/kickassembler/screenshots/runtime-relocation-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/runtime-relocation.png +0 -0
- package/docs/recipes/kickassembler/screenshots/screen-dissolve-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/screen-dissolve.png +0 -0
- package/docs/recipes/kickassembler/screenshots/screen-wipe-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/screen-wipe.png +0 -0
- package/docs/recipes/kickassembler/screenshots/scroll-panel-split-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/scroll-panel-split.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sfx-in-player-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sfx-in-player.png +0 -0
- package/docs/recipes/kickassembler/screenshots/shadebobs-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/shadebobs.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sideborder-open.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sine-scroller.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sine-table-runtime-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sine-table-runtime.png +0 -0
- package/docs/recipes/kickassembler/screenshots/software-sprite-preshifted-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/software-sprite-preshifted.png +0 -0
- package/docs/recipes/kickassembler/screenshots/speedcode-generator-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/speedcode-generator.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-border-scroller-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-border-scroller.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-cache-flip-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-cache-flip.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-multiplex-24.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-multiplex-game-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-multiplex-game.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-priority-classes-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-priority-classes.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-sine-chain-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-sine-chain.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-stretcher-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-stretcher.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprites-only-screen-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprites-only-screen.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sqrt-atan2-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sqrt-atan2.png +0 -0
- package/docs/recipes/kickassembler/screenshots/stable-raster-irq-control.png +0 -0
- package/docs/recipes/kickassembler/screenshots/stable-raster-irq.png +0 -0
- package/docs/recipes/kickassembler/screenshots/tech-tech-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/tech-tech.png +0 -0
- package/docs/recipes/kickassembler/screenshots/tod-alarm-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/tod-alarm.png +0 -0
- package/docs/recipes/kickassembler/screenshots/topbottom-border-open.png +0 -0
- package/docs/recipes/kickassembler/screenshots/twister-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/twister.png +0 -0
- package/docs/recipes/kickassembler/screenshots/unit-test-driver-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/unit-test-driver.png +0 -0
- package/docs/recipes/kickassembler/screenshots/vector-balls-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/vector-balls.png +0 -0
- package/docs/recipes/kickassembler/screenshots/wireframe-ships-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/wireframe-ships.png +0 -0
- package/docs/recipes/kickassembler/scroll-panel-split.md +381 -0
- package/docs/recipes/kickassembler/sfx-in-player.md +907 -0
- package/docs/recipes/kickassembler/shadebobs.md +522 -0
- package/docs/recipes/kickassembler/sideborder-open.md +338 -0
- package/docs/recipes/kickassembler/sine-scroller.md +321 -0
- package/docs/recipes/kickassembler/sine-table-runtime.md +815 -0
- package/docs/recipes/kickassembler/software-sprite-preshifted.md +725 -0
- package/docs/recipes/kickassembler/speedcode-generator.md +606 -0
- package/docs/recipes/kickassembler/sprite-border-scroller.md +696 -0
- package/docs/recipes/kickassembler/sprite-cache-flip.md +1071 -0
- package/docs/recipes/kickassembler/sprite-multiplex-24.md +326 -0
- package/docs/recipes/kickassembler/sprite-multiplex-game.md +986 -0
- package/docs/recipes/kickassembler/sprite-priority-classes.md +463 -0
- package/docs/recipes/kickassembler/sprite-sine-chain.md +338 -0
- package/docs/recipes/kickassembler/sprite-stretcher.md +501 -0
- package/docs/recipes/kickassembler/sprites-only-screen.md +550 -0
- package/docs/recipes/kickassembler/sqrt-atan2.md +1014 -0
- package/docs/recipes/kickassembler/stable-raster-irq.md +360 -0
- package/docs/recipes/kickassembler/tape-turbo-loader.md +875 -0
- package/docs/recipes/kickassembler/tech-tech.md +679 -0
- package/docs/recipes/kickassembler/tod-alarm.md +754 -0
- package/docs/recipes/kickassembler/topbottom-border-open.md +407 -0
- package/docs/recipes/kickassembler/twister.md +518 -0
- package/docs/recipes/kickassembler/unit-test-driver.md +314 -0
- package/docs/recipes/kickassembler/vector-balls.md +545 -0
- package/docs/recipes/kickassembler/wireframe-ships.md +2324 -0
- package/docs/recipes/oscar64/actor-activation-window.md +807 -0
- package/docs/recipes/oscar64/adventure-engine.md +1094 -0
- package/docs/recipes/oscar64/attract-replay.md +465 -0
- package/docs/recipes/oscar64/beat-em-up-lanes.md +563 -0
- package/docs/recipes/oscar64/bfs-distance-map.md +723 -0
- package/docs/recipes/oscar64/bitmap-koala-viewer.md +355 -0
- package/docs/recipes/oscar64/car-contact.md +950 -0
- package/docs/recipes/oscar64/cave-scan.md +609 -0
- package/docs/recipes/oscar64/char-bullets.md +477 -0
- package/docs/recipes/oscar64/charset-animation.md +383 -0
- package/docs/recipes/oscar64/charset-parallax.md +401 -0
- package/docs/recipes/oscar64/destructible-terrain.md +1099 -0
- package/docs/recipes/oscar64/difficulty-tables.md +654 -0
- package/docs/recipes/oscar64/dig-and-guards.md +975 -0
- package/docs/recipes/oscar64/directory-reader.md +535 -0
- package/docs/recipes/oscar64/divide-check.md +581 -0
- package/docs/recipes/oscar64/double-buffer-nomirror.md +205 -0
- package/docs/recipes/oscar64/double-buffer.md +255 -0
- package/docs/recipes/oscar64/falling-blocks.md +874 -0
- package/docs/recipes/oscar64/fixed-point-jump-velocity.md +289 -0
- package/docs/recipes/oscar64/fixed-point-jump.md +210 -0
- package/docs/recipes/oscar64/flip-screen-rooms.md +793 -0
- package/docs/recipes/oscar64/frame-sync-loop-overrun.md +214 -0
- package/docs/recipes/oscar64/frame-sync-loop.md +254 -0
- package/docs/recipes/oscar64/game-tree-search.md +743 -0
- package/docs/recipes/oscar64/ghost-targeting.md +867 -0
- package/docs/recipes/oscar64/headless-verify.md +345 -0
- package/docs/recipes/oscar64/hello-world.md +83 -0
- package/docs/recipes/oscar64/high-score-persist.md +772 -0
- package/docs/recipes/oscar64/iffl-kernal-skip.md +421 -0
- package/docs/recipes/oscar64/joystick-input.md +358 -0
- package/docs/recipes/oscar64/lane-pursuit.md +1028 -0
- package/docs/recipes/oscar64/level-rle-decoder.md +620 -0
- package/docs/recipes/oscar64/lfsr-random-seed2.md +338 -0
- package/docs/recipes/oscar64/lfsr-random.md +403 -0
- package/docs/recipes/oscar64/load-asset-runtime.md +492 -0
- package/docs/recipes/oscar64/memory-layout.md +232 -0
- package/docs/recipes/oscar64/mixed-fighters.md +781 -0
- package/docs/recipes/oscar64/multi-sprite-object.md +533 -0
- package/docs/recipes/oscar64/nav-area-pathfinding.md +881 -0
- package/docs/recipes/oscar64/object-pool.md +572 -0
- package/docs/recipes/oscar64/pal-ntsc-detect.md +257 -0
- package/docs/recipes/oscar64/password-state.md +532 -0
- package/docs/recipes/oscar64/per-frame-hitbox.md +651 -0
- package/docs/recipes/oscar64/petscii-screen-codes.md +428 -0
- package/docs/recipes/oscar64/platformer-scaffold.md +1467 -0
- package/docs/recipes/oscar64/print-number.md +367 -0
- package/docs/recipes/oscar64/raster-bars.md +239 -0
- package/docs/recipes/oscar64/raster-profile-bars.md +404 -0
- package/docs/recipes/oscar64/rel-side-sectors.md +391 -0
- package/docs/recipes/oscar64/relative-file-records.md +378 -0
- package/docs/recipes/oscar64/save-load-seq-file.md +365 -0
- package/docs/recipes/oscar64/screenshots/README.md +99 -0
- package/docs/recipes/oscar64/screenshots/actor-activation-window-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/actor-activation-window.png +0 -0
- package/docs/recipes/oscar64/screenshots/adventure-engine-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/adventure-engine.png +0 -0
- package/docs/recipes/oscar64/screenshots/attract-replay-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/attract-replay.png +0 -0
- package/docs/recipes/oscar64/screenshots/beat-em-up-lanes-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/beat-em-up-lanes.png +0 -0
- package/docs/recipes/oscar64/screenshots/bfs-distance-map-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/bfs-distance-map.png +0 -0
- package/docs/recipes/oscar64/screenshots/bitmap-koala-viewer.png +0 -0
- package/docs/recipes/oscar64/screenshots/car-contact-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/car-contact.png +0 -0
- package/docs/recipes/oscar64/screenshots/cave-scan-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/cave-scan.png +0 -0
- package/docs/recipes/oscar64/screenshots/char-bullets-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/char-bullets.png +0 -0
- package/docs/recipes/oscar64/screenshots/charset-animation-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/charset-animation.png +0 -0
- package/docs/recipes/oscar64/screenshots/charset-parallax-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/charset-parallax.png +0 -0
- package/docs/recipes/oscar64/screenshots/destructible-terrain-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/destructible-terrain.png +0 -0
- package/docs/recipes/oscar64/screenshots/difficulty-tables-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/difficulty-tables.png +0 -0
- package/docs/recipes/oscar64/screenshots/dig-and-guards-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/dig-and-guards.png +0 -0
- package/docs/recipes/oscar64/screenshots/directory-reader-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/directory-reader.png +0 -0
- package/docs/recipes/oscar64/screenshots/divide-check-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/divide-check.png +0 -0
- package/docs/recipes/oscar64/screenshots/double-buffer-nomirror.png +0 -0
- package/docs/recipes/oscar64/screenshots/double-buffer-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/double-buffer.png +0 -0
- package/docs/recipes/oscar64/screenshots/falling-blocks-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/falling-blocks.png +0 -0
- package/docs/recipes/oscar64/screenshots/fixed-point-jump-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/fixed-point-jump-velocity-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/fixed-point-jump-velocity.png +0 -0
- package/docs/recipes/oscar64/screenshots/fixed-point-jump.png +0 -0
- package/docs/recipes/oscar64/screenshots/flip-screen-rooms-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/flip-screen-rooms.png +0 -0
- package/docs/recipes/oscar64/screenshots/frame-sync-loop-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/frame-sync-loop-overrun.png +0 -0
- package/docs/recipes/oscar64/screenshots/frame-sync-loop.png +0 -0
- package/docs/recipes/oscar64/screenshots/game-tree-search-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/game-tree-search.png +0 -0
- package/docs/recipes/oscar64/screenshots/ghost-targeting-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/ghost-targeting.png +0 -0
- package/docs/recipes/oscar64/screenshots/headless-verify-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/headless-verify.png +0 -0
- package/docs/recipes/oscar64/screenshots/hello-world.png +0 -0
- package/docs/recipes/oscar64/screenshots/high-score-persist-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/high-score-persist.png +0 -0
- package/docs/recipes/oscar64/screenshots/iffl-kernal-skip-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/iffl-kernal-skip.png +0 -0
- package/docs/recipes/oscar64/screenshots/joystick-input-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/joystick-input.png +0 -0
- package/docs/recipes/oscar64/screenshots/lane-pursuit-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/lane-pursuit.png +0 -0
- package/docs/recipes/oscar64/screenshots/level-rle-decoder-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/level-rle-decoder.png +0 -0
- package/docs/recipes/oscar64/screenshots/lfsr-random-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/lfsr-random-seed2.png +0 -0
- package/docs/recipes/oscar64/screenshots/lfsr-random.png +0 -0
- package/docs/recipes/oscar64/screenshots/load-asset-runtime-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/load-asset-runtime.png +0 -0
- package/docs/recipes/oscar64/screenshots/memory-layout-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/memory-layout.png +0 -0
- package/docs/recipes/oscar64/screenshots/mixed-fighters-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/mixed-fighters.png +0 -0
- package/docs/recipes/oscar64/screenshots/multi-sprite-object-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/multi-sprite-object.png +0 -0
- package/docs/recipes/oscar64/screenshots/nav-area-pathfinding-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/nav-area-pathfinding.png +0 -0
- package/docs/recipes/oscar64/screenshots/object-pool-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/object-pool.png +0 -0
- package/docs/recipes/oscar64/screenshots/pal-ntsc-detect-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/pal-ntsc-detect-oldntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/pal-ntsc-detect-pal.png +0 -0
- package/docs/recipes/oscar64/screenshots/password-state-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/password-state.png +0 -0
- package/docs/recipes/oscar64/screenshots/per-frame-hitbox-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/per-frame-hitbox.png +0 -0
- package/docs/recipes/oscar64/screenshots/petscii-screen-codes-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/petscii-screen-codes.png +0 -0
- package/docs/recipes/oscar64/screenshots/platformer-scaffold-d64-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/platformer-scaffold-d64.png +0 -0
- package/docs/recipes/oscar64/screenshots/platformer-scaffold-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/platformer-scaffold.png +0 -0
- package/docs/recipes/oscar64/screenshots/print-number-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/print-number.png +0 -0
- package/docs/recipes/oscar64/screenshots/raster-bars.png +0 -0
- package/docs/recipes/oscar64/screenshots/raster-profile-bars-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/raster-profile-bars.png +0 -0
- package/docs/recipes/oscar64/screenshots/rel-side-sectors-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/rel-side-sectors.png +0 -0
- package/docs/recipes/oscar64/screenshots/relative-file-records-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/relative-file-records.png +0 -0
- package/docs/recipes/oscar64/screenshots/save-load-seq-file-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/save-load-seq-file.png +0 -0
- package/docs/recipes/oscar64/screenshots/seeded-level-fill-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/seeded-level-fill.png +0 -0
- package/docs/recipes/oscar64/screenshots/sfx-engine-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/sfx-engine.png +0 -0
- package/docs/recipes/oscar64/screenshots/sid-music-player.png +0 -0
- package/docs/recipes/oscar64/screenshots/simple-shmup.png +0 -0
- package/docs/recipes/oscar64/screenshots/slope-collision-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/slope-collision.png +0 -0
- package/docs/recipes/oscar64/screenshots/soft-scroll-h.png +0 -0
- package/docs/recipes/oscar64/screenshots/sprite-animation-table-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/sprite-animation-table.png +0 -0
- package/docs/recipes/oscar64/screenshots/sprite-multiplex-8.png +0 -0
- package/docs/recipes/oscar64/screenshots/stable-raster-irq.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-input-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-input.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-overlay-playfield-gameover.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-overlay-playfield-notrail-control.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-overlay-playfield-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-overlay-playfield-ungated-control.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-overlay-playfield.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-window-menu-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-window-menu.png +0 -0
- package/docs/recipes/oscar64/screenshots/tile-grid-collision-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/tile-grid-collision.png +0 -0
- package/docs/recipes/oscar64/screenshots/tile-map-render-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/tile-map-render.png +0 -0
- package/docs/recipes/oscar64/screenshots/two-player-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/two-player.png +0 -0
- package/docs/recipes/oscar64/screenshots/two-word-parser-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/two-word-parser.png +0 -0
- package/docs/recipes/oscar64/screenshots/vehicle-control-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/vehicle-control.png +0 -0
- package/docs/recipes/oscar64/screenshots/wave-director-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/wave-director.png +0 -0
- package/docs/recipes/oscar64/seeded-level-fill.md +364 -0
- package/docs/recipes/oscar64/sfx-engine.md +514 -0
- package/docs/recipes/oscar64/sid-music-player.md +441 -0
- package/docs/recipes/oscar64/simple-shmup.md +1000 -0
- package/docs/recipes/oscar64/slope-collision.md +610 -0
- package/docs/recipes/oscar64/soft-scroll-h.md +261 -0
- package/docs/recipes/oscar64/sprite-animation-table.md +671 -0
- package/docs/recipes/oscar64/sprite-multiplex-8.md +314 -0
- package/docs/recipes/oscar64/stable-raster-irq.md +236 -0
- package/docs/recipes/oscar64/text-input.md +274 -0
- package/docs/recipes/oscar64/text-overlay-playfield.md +617 -0
- package/docs/recipes/oscar64/text-window-menu.md +551 -0
- package/docs/recipes/oscar64/tile-grid-collision.md +563 -0
- package/docs/recipes/oscar64/tile-map-render.md +395 -0
- package/docs/recipes/oscar64/two-player.md +528 -0
- package/docs/recipes/oscar64/two-word-parser.md +510 -0
- package/docs/recipes/oscar64/vehicle-control.md +771 -0
- package/docs/recipes/oscar64/wave-director.md +787 -0
- package/docs/recipes/runs.json +1606 -0
- package/docs/runtime/sim6502-reference.md +466 -0
- package/docs/runtime/vice-mcp-reference.md +351 -0
- package/docs/runtime/vice-reference.md +1393 -0
- package/docs/techniques/bitmap-modes.md +685 -0
- package/docs/techniques/cpu-cycle-tricks.md +1570 -0
- package/docs/techniques/effects-vector-3d.md +1431 -0
- package/docs/techniques/file-io.md +1427 -0
- package/docs/techniques/input.md +1072 -0
- package/docs/techniques/loaders-packers.md +768 -0
- package/docs/techniques/logic.md +3091 -0
- package/docs/techniques/maths.md +1524 -0
- package/docs/techniques/memory-banking.md +1686 -0
- package/docs/techniques/music-sid.md +1144 -0
- package/docs/techniques/raster.md +1543 -0
- package/docs/techniques/scroll.md +1292 -0
- package/docs/techniques/sprite.md +2566 -0
- package/docs/techniques/text-mode-render.md +717 -0
- package/docs/techniques/text.md +1095 -0
- package/docs/techniques/transitions.md +405 -0
- package/docs/toolchains/cartconv-reference.md +262 -0
- package/docs/toolchains/cc1541-reference.md +316 -0
- package/docs/toolchains/cc65-reference.md +667 -0
- package/docs/toolchains/error-sources/cc65/README.md +1 -0
- package/docs/toolchains/error-sources/cc65/missing-setcpu.s +4 -0
- package/docs/toolchains/error-sources/cc65/range-error.s +4 -0
- package/docs/toolchains/error-sources/cc65/segment-overflow.c +6 -0
- package/docs/toolchains/error-sources/cc65/unresolved-external.c +6 -0
- package/docs/toolchains/error-sources/kickassembler/README.md +1 -0
- package/docs/toolchains/error-sources/kickassembler/branch-out-of-range.asm +4 -0
- package/docs/toolchains/error-sources/kickassembler/failed-assert.asm +3 -0
- package/docs/toolchains/error-sources/kickassembler/flat-lib.asm +4 -0
- package/docs/toolchains/error-sources/kickassembler/import-source-no-namespace.asm +5 -0
- package/docs/toolchains/error-sources/kickassembler/macro-without-parentheses.asm +6 -0
- package/docs/toolchains/error-sources/kickassembler/memory-block-overlap.asm +4 -0
- package/docs/toolchains/error-sources/kickassembler/symbol-clash-lib.asm +5 -0
- package/docs/toolchains/error-sources/kickassembler/symbol-clash-main.asm +6 -0
- package/docs/toolchains/error-sources/kickassembler/unknown-symbol.asm +4 -0
- package/docs/toolchains/error-sources/oscar64/README.md +1 -0
- package/docs/toolchains/error-sources/oscar64/asm-addressing-mode.c +7 -0
- package/docs/toolchains/error-sources/oscar64/region-overflow.c +6 -0
- package/docs/toolchains/error-sources/oscar64/undefined-extern-var.c +5 -0
- package/docs/toolchains/error-sources/oscar64/undefined-extern.c +6 -0
- package/docs/toolchains/error-sources/oscar64/unknown-vic-field.c +6 -0
- package/docs/toolchains/error-sources/oscar64/void-main.c +3 -0
- package/docs/toolchains/kickassembler-reference.md +1020 -0
- package/docs/toolchains/memory-layout-planning.md +362 -0
- package/docs/toolchains/oscar64-headers-reference.md +583 -0
- package/docs/toolchains/oscar64-reference.md +892 -0
- package/docs/toolchains/petcat-reference.md +290 -0
- package/docs/toolchains/png2prg.md +188 -0
- package/docs/toolchains/release-disk.md +314 -0
- package/docs/toolchains/sidreloc.md +236 -0
- package/docs/toolchains/spindle-reference.md +487 -0
- package/docs/toolchains/tape-mastering.md +592 -0
- package/docs/toolchains/unit-testing-6502.md +281 -0
- package/docs/workflow/agent-harness.md +478 -0
- package/package.json +105 -0
- package/templates/_harness/CLAUDE.md.template +91 -0
- package/templates/_harness/PLAN.md.template +72 -0
- package/templates/_harness/check.py +442 -0
- package/templates/_harness/claude/settings.json +17 -0
- package/templates/_harness/gen-asm-header.py +96 -0
- package/templates/_harness/harness.mk +273 -0
- package/templates/_harness/hooks/plan-gate.py +185 -0
- package/templates/_harness/meter/frame_meter.asm +311 -0
- package/templates/_harness/meter/frame_meter.c +155 -0
- package/templates/_harness/meter/frame_meter.h +80 -0
- package/templates/_harness/zp-used.py +104 -0
- package/templates/action-puzzle/.claude/settings.json +17 -0
- package/templates/action-puzzle/.mcp.json +10 -0
- package/templates/action-puzzle/CLAUDE.md +120 -0
- package/templates/action-puzzle/Makefile +125 -0
- package/templates/action-puzzle/PLAN.md +388 -0
- package/templates/action-puzzle/README.md +240 -0
- package/templates/action-puzzle/expect.json +25 -0
- package/templates/action-puzzle/src/cave.c +280 -0
- package/templates/action-puzzle/src/cave.h +80 -0
- package/templates/action-puzzle/src/gen_autopilot.h +20 -0
- package/templates/action-puzzle/src/gen_caves.h +59 -0
- package/templates/action-puzzle/src/gen_notes.h +16 -0
- package/templates/action-puzzle/src/hiscore.c +152 -0
- package/templates/action-puzzle/src/hiscore.h +41 -0
- package/templates/action-puzzle/src/level.c +64 -0
- package/templates/action-puzzle/src/level.h +24 -0
- package/templates/action-puzzle/src/main.c +599 -0
- package/templates/action-puzzle/src/render.c +239 -0
- package/templates/action-puzzle/src/render.h +31 -0
- package/templates/action-puzzle/src/sound.c +158 -0
- package/templates/action-puzzle/src/sound.h +22 -0
- package/templates/action-puzzle/tools/disk_check.py +77 -0
- package/templates/action-puzzle/tools/drive.py +106 -0
- package/templates/action-puzzle/tools/gen.py +454 -0
- package/templates/action-puzzle/tools/model_check.py +49 -0
- package/templates/action-puzzle/tools/verdict_codes.py +24 -0
- package/templates/adventure/.claude/settings.json +17 -0
- package/templates/adventure/.mcp.json +10 -0
- package/templates/adventure/CLAUDE.md +118 -0
- package/templates/adventure/Makefile +113 -0
- package/templates/adventure/PLAN.md +396 -0
- package/templates/adventure/README.md +277 -0
- package/templates/adventure/expect.json +25 -0
- package/templates/adventure/src/engine.c +543 -0
- package/templates/adventure/src/engine.h +48 -0
- package/templates/adventure/src/gen_script.h +141 -0
- package/templates/adventure/src/gen_world.h +511 -0
- package/templates/adventure/src/main.c +439 -0
- package/templates/adventure/src/picture.c +83 -0
- package/templates/adventure/src/picture.h +16 -0
- package/templates/adventure/src/save.c +159 -0
- package/templates/adventure/src/save.h +25 -0
- package/templates/adventure/src/sound.c +71 -0
- package/templates/adventure/src/sound.h +16 -0
- package/templates/adventure/src/text.c +349 -0
- package/templates/adventure/src/text.h +40 -0
- package/templates/adventure/tools/disk_check.py +128 -0
- package/templates/adventure/tools/drive.py +119 -0
- package/templates/adventure/tools/gen.py +1033 -0
- package/templates/adventure/tools/world.py +356 -0
- package/templates/beat-em-up/.claude/settings.json +17 -0
- package/templates/beat-em-up/.mcp.json +10 -0
- package/templates/beat-em-up/CLAUDE.md +136 -0
- package/templates/beat-em-up/Makefile +96 -0
- package/templates/beat-em-up/PLAN.md +502 -0
- package/templates/beat-em-up/README.md +315 -0
- package/templates/beat-em-up/expect-gameover.json +8 -0
- package/templates/beat-em-up/expect.json +29 -0
- package/templates/beat-em-up/src/anim.c +70 -0
- package/templates/beat-em-up/src/art.c +344 -0
- package/templates/beat-em-up/src/autopilot.h +154 -0
- package/templates/beat-em-up/src/brute.c +273 -0
- package/templates/beat-em-up/src/enemy.c +281 -0
- package/templates/beat-em-up/src/engine.asm +512 -0
- package/templates/beat-em-up/src/fighter.c +384 -0
- package/templates/beat-em-up/src/game.h +269 -0
- package/templates/beat-em-up/src/hud.c +135 -0
- package/templates/beat-em-up/src/main.c +341 -0
- package/templates/beat-em-up/src/sound.c +44 -0
- package/templates/beat-em-up/src/street.c +93 -0
- package/templates/beat-em-up/src/verdict.h +523 -0
- package/templates/beat-em-up/src/view.c +362 -0
- package/templates/beat-em-up/tools/drive.py +105 -0
- package/templates/beat-em-up/tools/flickercheck.py +273 -0
- package/templates/demo/.claude/settings.json +17 -0
- package/templates/demo/.mcp.json +10 -0
- package/templates/demo/CLAUDE.md +129 -0
- package/templates/demo/Makefile +66 -0
- package/templates/demo/PLAN.md +401 -0
- package/templates/demo/README.md +322 -0
- package/templates/demo/expect.json +945 -0
- package/templates/demo/src/config.asm +80 -0
- package/templates/demo/src/framework.asm +390 -0
- package/templates/demo/src/main.asm +139 -0
- package/templates/demo/src/music.asm +197 -0
- package/templates/demo/src/part_main.asm +279 -0
- package/templates/demo/src/part_title.asm +79 -0
- package/templates/demo/src/parts.asm +43 -0
- package/templates/demo/src/tables.asm +73 -0
- package/templates/demo/src/verdict.asm +179 -0
- package/templates/demo/tools/audio.py +80 -0
- package/templates/demo/tools/gen_expect.py +167 -0
- package/templates/demo/tools/probe.py +95 -0
- package/templates/hello/.claude/settings.json +17 -0
- package/templates/hello/.mcp.json +10 -0
- package/templates/hello/CLAUDE.md +100 -0
- package/templates/hello/Makefile +38 -0
- package/templates/hello/PLAN.md +200 -0
- package/templates/hello/expect.json +20 -0
- package/templates/hello/src/main.c +161 -0
- package/templates/hello/src/sprite.asm +27 -0
- package/templates/hello-kick/.claude/settings.json +17 -0
- package/templates/hello-kick/.mcp.json +10 -0
- package/templates/hello-kick/CLAUDE.md +100 -0
- package/templates/hello-kick/Makefile +17 -0
- package/templates/hello-kick/PLAN.md +199 -0
- package/templates/hello-kick/expect.json +20 -0
- package/templates/hello-kick/src/main.asm +233 -0
- package/templates/platformer/.claude/settings.json +17 -0
- package/templates/platformer/.mcp.json +10 -0
- package/templates/platformer/CLAUDE.md +125 -0
- package/templates/platformer/Makefile +86 -0
- package/templates/platformer/PLAN.md +360 -0
- package/templates/platformer/README.md +277 -0
- package/templates/platformer/expect.json +32 -0
- package/templates/platformer/src/actors.c +289 -0
- package/templates/platformer/src/anim.c +51 -0
- package/templates/platformer/src/art.c +212 -0
- package/templates/platformer/src/autopilot.h +30 -0
- package/templates/platformer/src/engine.asm +253 -0
- package/templates/platformer/src/game.h +248 -0
- package/templates/platformer/src/hud.c +90 -0
- package/templates/platformer/src/level.c +184 -0
- package/templates/platformer/src/main.c +306 -0
- package/templates/platformer/src/player.c +268 -0
- package/templates/platformer/src/sound.c +42 -0
- package/templates/platformer/src/verdict.h +206 -0
- package/templates/platformer/src/view.c +331 -0
- package/templates/platformer/stage-expect.json +6 -0
- package/templates/platformer/tools/drive.py +112 -0
- package/templates/platformer/tools/tearcheck.py +229 -0
- package/templates/shmup-vertical/.claude/settings.json +17 -0
- package/templates/shmup-vertical/.mcp.json +10 -0
- package/templates/shmup-vertical/CLAUDE.md +137 -0
- package/templates/shmup-vertical/Makefile +131 -0
- package/templates/shmup-vertical/PLAN.md +569 -0
- package/templates/shmup-vertical/README.md +189 -0
- package/templates/shmup-vertical/expect.json +38 -0
- package/templates/shmup-vertical/src/bullets.c +158 -0
- package/templates/shmup-vertical/src/bullets.h +35 -0
- package/templates/shmup-vertical/src/display.c +239 -0
- package/templates/shmup-vertical/src/display.h +40 -0
- package/templates/shmup-vertical/src/game.h +85 -0
- package/templates/shmup-vertical/src/glyph.asm +358 -0
- package/templates/shmup-vertical/src/hiscore.c +141 -0
- package/templates/shmup-vertical/src/hiscore.h +16 -0
- package/templates/shmup-vertical/src/hit.asm +180 -0
- package/templates/shmup-vertical/src/hitbox.c +59 -0
- package/templates/shmup-vertical/src/hitbox.h +25 -0
- package/templates/shmup-vertical/src/kernel.asm +330 -0
- package/templates/shmup-vertical/src/level.c +174 -0
- package/templates/shmup-vertical/src/level.h +27 -0
- package/templates/shmup-vertical/src/main.c +824 -0
- package/templates/shmup-vertical/src/mux.asm +321 -0
- package/templates/shmup-vertical/src/sound.asm +255 -0
- package/templates/shmup-vertical/src/step.asm +169 -0
- package/templates/shmup-vertical/src/waves.c +195 -0
- package/templates/shmup-vertical/src/waves.h +33 -0
- package/templates/shmup-vertical/stage-expect.json +6 -0
- package/templates/shmup-vertical/tools/drive.py +152 -0
- package/templates/shmup-vertical/tools/joytest.py +159 -0
- package/templates/shmup-vertical/tools/meter.py +15 -0
- package/templates/shmup-vertical/tools/phases.py +73 -0
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
---
|
|
2
|
+
recipe: sfx-engine
|
|
3
|
+
toolchain: oscar64
|
|
4
|
+
output_format: PRG
|
|
5
|
+
region: both
|
|
6
|
+
techniques: [sfx_engine_beside_music]
|
|
7
|
+
file_formats: [PRG]
|
|
8
|
+
uses_registers: [D400, D401, D402, D403, D404, D405, D406, D407, D408, D409, D40A, D40B, D40C, D40D, D40E, D40F, D410, D411, D412, D413, D414, D418, DC04, DC05, DC0E]
|
|
9
|
+
uses_kernal: []
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<!-- doc-type: recipe -->
|
|
13
|
+
|
|
14
|
+
# Oscar64 sound-effect engine beside a three-voice tune
|
|
15
|
+
|
|
16
|
+
## Synopsis
|
|
17
|
+
|
|
18
|
+
A table-driven sound-effect engine that borrows SID voice 2 from a music
|
|
19
|
+
play routine and hands it back when the effect ends. The "tune" is a stub
|
|
20
|
+
that writes every register of all three voices and `$D418` on every frame,
|
|
21
|
+
which is what a real player does, so the engine has to run after the play
|
|
22
|
+
call and re-poke the voice each frame while an effect owns it. Two effects
|
|
23
|
+
with different priorities are fired from a scripted cue list so that every
|
|
24
|
+
case is exercised: a free voice, a higher-priority effect cutting a lower
|
|
25
|
+
one, a lower-priority request refused, and an equal-priority restart. The
|
|
26
|
+
screen shows the counters, a checksum over every byte the engine wrote to
|
|
27
|
+
`$D408-$D40B` matched against a Python model, and the cost per call of the
|
|
28
|
+
tune and the engine from CIA1 timer A. The technique is
|
|
29
|
+
`sfx_engine_beside_music` in `techniques/music-sid.md`. Nobody on this
|
|
30
|
+
machine has listened to the result; the verification is register-level.
|
|
31
|
+
|
|
32
|
+
## Source
|
|
33
|
+
|
|
34
|
+
```c
|
|
35
|
+
// sfx-engine.c
|
|
36
|
+
// A table-driven sound-effect engine running beside a music play routine.
|
|
37
|
+
// The "tune" is a stub that writes all three voices and $D418 every frame,
|
|
38
|
+
// like a real player would. Effects borrow voice 2 ($D407-$D40D): the engine
|
|
39
|
+
// runs AFTER the play call each frame and re-pokes the voice while an effect
|
|
40
|
+
// owns it; when the effect's table hits its terminator the engine stops
|
|
41
|
+
// writing and the tune's own values stand again from the next frame.
|
|
42
|
+
// A priority byte per effect decides what happens when two collide.
|
|
43
|
+
// Counters on screen: effects started, effects refused, frames borrowed,
|
|
44
|
+
// a checksum over every byte the engine wrote to $D408-$D40B, and the cost
|
|
45
|
+
// per frame of the tune and of the engine, from CIA1 timer A.
|
|
46
|
+
// Nobody has listened to this; the check is register-level.
|
|
47
|
+
#include <c64/vic.h>
|
|
48
|
+
#include <c64/sid.h>
|
|
49
|
+
#include <c64/cia.h>
|
|
50
|
+
|
|
51
|
+
#define SCREEN ((char *)0x0400)
|
|
52
|
+
#define SFX_REGS ((volatile char *)0xd407) // voice 2: freq lo/hi, pw lo/hi, ctrl, AD, SR
|
|
53
|
+
#define EXPECT_CHK 0xF2B4 // from the Python model of the same tables and cues
|
|
54
|
+
|
|
55
|
+
// ---- effect tables ---------------------------------------------------------
|
|
56
|
+
// One row per frame: frequency, pulse width, control byte. ADSR is per effect,
|
|
57
|
+
// written when it starts (and re-poked each frame, because the tune writes
|
|
58
|
+
// AD/SR too). The row with ctrl == SFX_END ends the effect and frees the voice.
|
|
59
|
+
struct SfxFrame { unsigned freq; unsigned pw; char ctrl; };
|
|
60
|
+
#define SFX_END 0xff
|
|
61
|
+
|
|
62
|
+
struct Sfx { char prio; char attdec; char susrel; const struct SfxFrame *frames; };
|
|
63
|
+
|
|
64
|
+
// Laser: pulse wave, pitch falling over 8 frames. First row is the TEST+GATE
|
|
65
|
+
// ($09) frame of the classic hard restart in sid-reference, so the attack
|
|
66
|
+
// starts from a reset oscillator; the row after it is the real waveform
|
|
67
|
+
// with GATE. Last row drops GATE.
|
|
68
|
+
static const struct SfxFrame laser_frames[] = {
|
|
69
|
+
{ 0x3800, 0x0800, SID_CTRL_TEST | SID_CTRL_GATE },
|
|
70
|
+
{ 0x3400, 0x0800, SID_CTRL_RECT | SID_CTRL_GATE },
|
|
71
|
+
{ 0x2e00, 0x0880, SID_CTRL_RECT | SID_CTRL_GATE },
|
|
72
|
+
{ 0x2600, 0x0900, SID_CTRL_RECT | SID_CTRL_GATE },
|
|
73
|
+
{ 0x1e00, 0x0980, SID_CTRL_RECT | SID_CTRL_GATE },
|
|
74
|
+
{ 0x1600, 0x0a00, SID_CTRL_RECT | SID_CTRL_GATE },
|
|
75
|
+
{ 0x1000, 0x0a80, SID_CTRL_RECT | SID_CTRL_GATE },
|
|
76
|
+
{ 0x0c00, 0x0b00, SID_CTRL_RECT },
|
|
77
|
+
{ 0x0000, 0x0000, SFX_END }
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// Explosion: noise, 24 frames, pitch falling, gate released for the tail.
|
|
81
|
+
static const struct SfxFrame boom_frames[] = {
|
|
82
|
+
{ 0x2000, 0x0000, SID_CTRL_TEST | SID_CTRL_GATE },
|
|
83
|
+
{ 0x1e00, 0x0000, SID_CTRL_NOISE | SID_CTRL_GATE },
|
|
84
|
+
{ 0x1c00, 0x0000, SID_CTRL_NOISE | SID_CTRL_GATE },
|
|
85
|
+
{ 0x1a00, 0x0000, SID_CTRL_NOISE | SID_CTRL_GATE },
|
|
86
|
+
{ 0x1800, 0x0000, SID_CTRL_NOISE | SID_CTRL_GATE },
|
|
87
|
+
{ 0x1600, 0x0000, SID_CTRL_NOISE | SID_CTRL_GATE },
|
|
88
|
+
{ 0x1400, 0x0000, SID_CTRL_NOISE | SID_CTRL_GATE },
|
|
89
|
+
{ 0x1200, 0x0000, SID_CTRL_NOISE | SID_CTRL_GATE },
|
|
90
|
+
{ 0x1000, 0x0000, SID_CTRL_NOISE | SID_CTRL_GATE },
|
|
91
|
+
{ 0x0e00, 0x0000, SID_CTRL_NOISE | SID_CTRL_GATE },
|
|
92
|
+
{ 0x0c00, 0x0000, SID_CTRL_NOISE | SID_CTRL_GATE },
|
|
93
|
+
{ 0x0a00, 0x0000, SID_CTRL_NOISE | SID_CTRL_GATE },
|
|
94
|
+
{ 0x0900, 0x0000, SID_CTRL_NOISE },
|
|
95
|
+
{ 0x0800, 0x0000, SID_CTRL_NOISE },
|
|
96
|
+
{ 0x0700, 0x0000, SID_CTRL_NOISE },
|
|
97
|
+
{ 0x0600, 0x0000, SID_CTRL_NOISE },
|
|
98
|
+
{ 0x0500, 0x0000, SID_CTRL_NOISE },
|
|
99
|
+
{ 0x0480, 0x0000, SID_CTRL_NOISE },
|
|
100
|
+
{ 0x0400, 0x0000, SID_CTRL_NOISE },
|
|
101
|
+
{ 0x0380, 0x0000, SID_CTRL_NOISE },
|
|
102
|
+
{ 0x0300, 0x0000, SID_CTRL_NOISE },
|
|
103
|
+
{ 0x0280, 0x0000, SID_CTRL_NOISE },
|
|
104
|
+
{ 0x0200, 0x0000, SID_CTRL_NOISE },
|
|
105
|
+
{ 0x0180, 0x0000, SID_CTRL_NOISE },
|
|
106
|
+
{ 0x0000, 0x0000, SFX_END }
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
static const struct Sfx laser = { 1, SID_ATK_2 | SID_DKY_48, 0xa0 | SID_DKY_204, laser_frames };
|
|
110
|
+
static const struct Sfx boom = { 3, SID_ATK_2 | SID_DKY_114, 0xf0 | SID_DKY_750, boom_frames };
|
|
111
|
+
|
|
112
|
+
// ---- effect engine ---------------------------------------------------------
|
|
113
|
+
static const struct Sfx *sfx_cur; // effect that owns voice 2, or 0
|
|
114
|
+
static const struct SfxFrame *sfx_pos;
|
|
115
|
+
static unsigned sfx_started, sfx_refused, sfx_borrowed, sfx_chk;
|
|
116
|
+
static char sfx_last[4]; // last $D408-$D40B bytes written
|
|
117
|
+
static bool sfx_wrote;
|
|
118
|
+
|
|
119
|
+
static unsigned fold(unsigned chk, char value)
|
|
120
|
+
{
|
|
121
|
+
return (chk ^ value) * 5 + 1;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Start an effect. A running effect of higher priority keeps the voice;
|
|
125
|
+
// equal or lower priority is cut and the new effect starts from its first row.
|
|
126
|
+
static bool sfx_play(const struct Sfx *fx)
|
|
127
|
+
{
|
|
128
|
+
if (sfx_cur && fx->prio < sfx_cur->prio)
|
|
129
|
+
{
|
|
130
|
+
sfx_refused++;
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
sfx_cur = fx;
|
|
134
|
+
sfx_pos = fx->frames;
|
|
135
|
+
sfx_started++;
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Call once per frame, after the tune's play routine.
|
|
140
|
+
static void sfx_update(void)
|
|
141
|
+
{
|
|
142
|
+
if (!sfx_cur)
|
|
143
|
+
return;
|
|
144
|
+
if (sfx_pos->ctrl == SFX_END)
|
|
145
|
+
{
|
|
146
|
+
sfx_cur = nullptr; // hand the voice back: no more writes
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
SFX_REGS[5] = sfx_cur->attdec; // $D40C, re-poked: the tune wrote it
|
|
150
|
+
SFX_REGS[6] = sfx_cur->susrel; // $D40D
|
|
151
|
+
SFX_REGS[0] = (char)sfx_pos->freq; // $D407
|
|
152
|
+
SFX_REGS[1] = sfx_pos->freq >> 8; // $D408 } these four bytes are
|
|
153
|
+
SFX_REGS[2] = (char)sfx_pos->pw; // $D409 } folded into the
|
|
154
|
+
SFX_REGS[3] = sfx_pos->pw >> 8; // $D40A } checksum, in this
|
|
155
|
+
SFX_REGS[4] = sfx_pos->ctrl; // $D40B } order
|
|
156
|
+
sfx_last[0] = sfx_pos->freq >> 8; // copy for the checksum, folded by
|
|
157
|
+
sfx_last[1] = (char)sfx_pos->pw; // the caller outside the timed region
|
|
158
|
+
sfx_last[2] = sfx_pos->pw >> 8;
|
|
159
|
+
sfx_last[3] = sfx_pos->ctrl;
|
|
160
|
+
sfx_wrote = true;
|
|
161
|
+
sfx_borrowed++;
|
|
162
|
+
sfx_pos++;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// ---- stub tune: writes every register of all three voices each frame -----
|
|
166
|
+
static unsigned tune_frame;
|
|
167
|
+
static const unsigned tune_base[3] = { 0x0800, 0x0c00, 0x1200 };
|
|
168
|
+
|
|
169
|
+
static void tune_play(void)
|
|
170
|
+
{
|
|
171
|
+
char step = tune_frame & 31;
|
|
172
|
+
char gate = (tune_frame & 8) ? SID_CTRL_GATE : 0;
|
|
173
|
+
volatile char *r = (volatile char *)0xd400;
|
|
174
|
+
for (char v = 0; v < 3; v++)
|
|
175
|
+
{
|
|
176
|
+
unsigned f = tune_base[v] + (unsigned)step * 16;
|
|
177
|
+
r[0] = (char)f;
|
|
178
|
+
r[1] = f >> 8;
|
|
179
|
+
r[2] = 0x00; // pulse width $0400
|
|
180
|
+
r[3] = 0x04;
|
|
181
|
+
r[4] = SID_CTRL_TRI | gate;
|
|
182
|
+
r[5] = SID_ATK_8 | SID_DKY_168;
|
|
183
|
+
r[6] = 0x80 | SID_DKY_300;
|
|
184
|
+
r += 7;
|
|
185
|
+
}
|
|
186
|
+
sid.fmodevol = 0x0f;
|
|
187
|
+
tune_frame++;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// ---- cue script ------------------------------------------------------------
|
|
191
|
+
struct Cue { unsigned frame; const struct Sfx *fx; };
|
|
192
|
+
static const struct Cue script[] = {
|
|
193
|
+
{ 40, &laser }, // voice free: starts
|
|
194
|
+
{ 44, &boom }, // prio 3 over 1: cuts the laser after 4 frames
|
|
195
|
+
{ 50, &laser }, // refused, boom still owns the voice
|
|
196
|
+
{ 60, &laser }, // refused
|
|
197
|
+
{ 90, &laser }, // boom ended at frame 68: starts
|
|
198
|
+
{ 94, &laser }, // equal priority: restarts from row 0
|
|
199
|
+
{ 140, &boom }, // starts
|
|
200
|
+
{ 150, &laser }, // refused
|
|
201
|
+
{ 0, 0 }
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
// ---- timing harness: CIA1 timer A, force-loaded from $FFFF, phi2 ----------
|
|
205
|
+
static void timer_start(void)
|
|
206
|
+
{
|
|
207
|
+
cia1.cra = 0x00;
|
|
208
|
+
cia1.ta = 0xffff;
|
|
209
|
+
cia1.cra = 0x11;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
static unsigned timer_stop(void)
|
|
213
|
+
{
|
|
214
|
+
cia1.cra = 0x00;
|
|
215
|
+
return 0xffff - cia1.ta;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// ---- screen helpers --------------------------------------------------------
|
|
219
|
+
static const char hex_glyph[16] = { 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,1,2,3,4,5,6 };
|
|
220
|
+
|
|
221
|
+
static void put_text(char row, char col, const char *s)
|
|
222
|
+
{
|
|
223
|
+
char *p = SCREEN + 40 * row + col;
|
|
224
|
+
while (*s)
|
|
225
|
+
{
|
|
226
|
+
char c = *s++;
|
|
227
|
+
if (c >= 'A' && c <= 'Z') c -= 64;
|
|
228
|
+
*p++ = c;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
static void put_hex16(char row, char col, unsigned v)
|
|
233
|
+
{
|
|
234
|
+
char *p = SCREEN + 40 * row + col;
|
|
235
|
+
p[0] = hex_glyph[(v >> 12) & 15]; p[1] = hex_glyph[(v >> 8) & 15];
|
|
236
|
+
p[2] = hex_glyph[(v >> 4) & 15]; p[3] = hex_glyph[v & 15];
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
int main(void)
|
|
240
|
+
{
|
|
241
|
+
__asm { sei } // no KERNAL IRQ: CIA1 timer A is ours
|
|
242
|
+
vic.color_border = 0;
|
|
243
|
+
vic.color_back = 0;
|
|
244
|
+
for (unsigned i = 0; i < 1000; i++) { SCREEN[i] = 0x20; ((char *)0xd800)[i] = 1; }
|
|
245
|
+
|
|
246
|
+
put_text(0, 0, "SFX ENGINE BESIDE A THREE-VOICE TUNE");
|
|
247
|
+
put_text(2, 0, "STARTED");
|
|
248
|
+
put_text(3, 0, "REFUSED");
|
|
249
|
+
put_text(4, 0, "BORROWED");
|
|
250
|
+
put_text(6, 0, "CHK EXP");
|
|
251
|
+
put_text(8, 0, "CYCLES PER CALL (CIA1 TIMER A)");
|
|
252
|
+
put_text(9, 0, "TUNE");
|
|
253
|
+
put_text(10, 0, "SFX ON");
|
|
254
|
+
put_text(11, 0, "SFX OFF");
|
|
255
|
+
put_text(12, 0, "EMPTY");
|
|
256
|
+
put_text(14, 0, "VOICE 2 OWNER");
|
|
257
|
+
|
|
258
|
+
unsigned frame = 0, cue = 0;
|
|
259
|
+
unsigned t_tune = 0, t_on = 0, t_off = 0, t_empty;
|
|
260
|
+
|
|
261
|
+
timer_start(); t_empty = timer_stop();
|
|
262
|
+
put_hex16(12, 9, t_empty);
|
|
263
|
+
|
|
264
|
+
for (;;)
|
|
265
|
+
{
|
|
266
|
+
vic_waitFrame();
|
|
267
|
+
|
|
268
|
+
while (script[cue].fx && script[cue].frame == frame)
|
|
269
|
+
sfx_play(script[cue++].fx);
|
|
270
|
+
|
|
271
|
+
timer_start(); tune_play(); unsigned t = timer_stop();
|
|
272
|
+
if (t > t_tune) t_tune = t;
|
|
273
|
+
|
|
274
|
+
bool owned = sfx_cur != 0;
|
|
275
|
+
timer_start(); sfx_update(); t = timer_stop();
|
|
276
|
+
if (owned) { if (t > t_on) t_on = t; }
|
|
277
|
+
else { if (t > t_off) t_off = t; }
|
|
278
|
+
if (sfx_wrote)
|
|
279
|
+
{
|
|
280
|
+
for (char i = 0; i < 4; i++) sfx_chk = fold(sfx_chk, sfx_last[i]);
|
|
281
|
+
sfx_wrote = false;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
put_hex16(2, 9, sfx_started);
|
|
285
|
+
put_hex16(3, 9, sfx_refused);
|
|
286
|
+
put_hex16(4, 9, sfx_borrowed);
|
|
287
|
+
put_hex16(6, 4, sfx_chk);
|
|
288
|
+
put_hex16(6, 13, EXPECT_CHK);
|
|
289
|
+
put_text(6, 18, sfx_chk == EXPECT_CHK ? "PASS" : "FAIL");
|
|
290
|
+
put_hex16(9, 9, t_tune);
|
|
291
|
+
put_hex16(10, 9, t_on);
|
|
292
|
+
put_hex16(11, 9, t_off);
|
|
293
|
+
put_text(14, 14, sfx_cur ? "SFX " : "TUNE");
|
|
294
|
+
frame++;
|
|
295
|
+
}
|
|
296
|
+
return 0;
|
|
297
|
+
}
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
## Build
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
oscar64 -tm=c64 -O2 -o=sfx-engine.prg sfx-engine.c
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
Oscar64 build 2026-05-19. One warning from an earlier draft is worth
|
|
307
|
+
knowing: `sfx_cur = 0;` produces `warning 2014: Numeric 0 used for nullptr`;
|
|
308
|
+
the listing uses `nullptr`.
|
|
309
|
+
|
|
310
|
+
## Expected output
|
|
311
|
+
|
|
312
|
+
Black border and background, white text. Every figure below was measured in
|
|
313
|
+
VICE x64sc 3.10 (rung 1) from the exit screenshot of the pinned run:
|
|
314
|
+
|
|
315
|
+
```
|
|
316
|
+
x64sc -default -warp +sound +autostart-delay-random -autostartprgmode 1 \
|
|
317
|
+
-limitcycles 8000000 [-model ntsc] -exitscreenshot out.png -autostart sfx-engine.prg
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
decoding the text cells against the `chargen-901225-01.bin` glyphs (PAL
|
|
321
|
+
text row 0 at PNG y = 35, NTSC at y = 23). PAL (`screenshots/sfx-engine.png`)
|
|
322
|
+
and NTSC (`screenshots/sfx-engine-ntsc.png`) show the same text, because
|
|
323
|
+
the whole cue list is over by frame 164 and both runs go well past it:
|
|
324
|
+
about 250 frames on PAL and 290 on NTSC (arithmetic from the first traced
|
|
325
|
+
store at cycle 3,043,377 and the settled 19,656 and 17,095 cycles per
|
|
326
|
+
frame; an earlier draft of this sentence said 400, which was the Python
|
|
327
|
+
model's loop bound, not the run):
|
|
328
|
+
|
|
329
|
+
```
|
|
330
|
+
SFX ENGINE BESIDE A THREE-VOICE TUNE
|
|
331
|
+
|
|
332
|
+
STARTED 0005
|
|
333
|
+
REFUSED 0003
|
|
334
|
+
BORROWED 0040
|
|
335
|
+
|
|
336
|
+
CHK F2B4 EXP F2B4 PASS
|
|
337
|
+
|
|
338
|
+
CYCLES PER CALL (CIA1 TIMER A)
|
|
339
|
+
TUNE 014C
|
|
340
|
+
SFX ON 0107
|
|
341
|
+
SFX OFF 0037
|
|
342
|
+
EMPTY 0005
|
|
343
|
+
|
|
344
|
+
VOICE 2 OWNER TUNE
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
Reading the counters against the cue list: eight cues, five started, three
|
|
348
|
+
refused. The laser at frame 40 starts on a free voice; the explosion at 44
|
|
349
|
+
(priority 3) cuts it after four frames; the lasers at 50 and 60 are refused
|
|
350
|
+
while the explosion (24 rows, frames 44 to 67) owns the voice; the laser at
|
|
351
|
+
90 starts, the one at 94 restarts it at equal priority; the explosion at 140
|
|
352
|
+
starts and the laser at 150 is refused. Frames borrowed: 4 + 24 + 4 + 8 + 24
|
|
353
|
+
= 64 = `$0040`. The Python model below computes the same three counters and
|
|
354
|
+
the checksum `$F2B4` from the tables:
|
|
355
|
+
|
|
356
|
+
```python
|
|
357
|
+
def fold(chk, v): return ((chk ^ v) * 5 + 1) & 0xffff
|
|
358
|
+
# rows = list of (freq, pw, ctrl) per effect, cues = [(frame, name)], prio per effect
|
|
359
|
+
cur = None; pos = 0; chk = 0
|
|
360
|
+
for frame in range(400):
|
|
361
|
+
for f, name in cues:
|
|
362
|
+
if f == frame:
|
|
363
|
+
if cur and prio[name] < prio[cur]: refused += 1
|
|
364
|
+
else: cur, pos = name, 0; started += 1
|
|
365
|
+
if cur:
|
|
366
|
+
if pos == len(rows[cur]): cur = None
|
|
367
|
+
else:
|
|
368
|
+
freq, pw, ctrl = rows[cur][pos]
|
|
369
|
+
for b in (freq >> 8, pw & 0xff, pw >> 8, ctrl): chk = fold(chk, b)
|
|
370
|
+
borrowed += 1; pos += 1
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
The cycle figures are the largest value of CIA1 timer A seen over the run
|
|
374
|
+
for each call, in hex: the tune's play routine `$014C` = 332 cycles, the
|
|
375
|
+
engine with an effect running `$0107` = 263 cycles, the engine idle `$0037`
|
|
376
|
+
= 55 cycles, and an empty timed region `$0005` = 5 cycles, which is the
|
|
377
|
+
harness's own start/stop overhead and is included in the other three. Net of
|
|
378
|
+
it, the engine costs 258 cycles on a frame it owns the voice and 50 when it
|
|
379
|
+
does not, against a PAL frame of 19,656 cycles (about 1.3 % and 0.25 %,
|
|
380
|
+
arithmetic from the settled 63 cycles per line). The checksum fold runs
|
|
381
|
+
outside the timed region; an earlier build folded inside `sfx_update` and
|
|
382
|
+
measured `$01B2` = 434 cycles for the same seven stores, so 171 cycles of
|
|
383
|
+
that figure were the four 16-bit multiplies of the instrument, not the
|
|
384
|
+
engine.
|
|
385
|
+
|
|
386
|
+
### Register-level trace of the borrow and the hand-back
|
|
387
|
+
|
|
388
|
+
The claim that the engine's values land after the tune's, and that the
|
|
389
|
+
tune's values stand again once the effect ends, was checked with a VICE
|
|
390
|
+
trace checkpoint on the four bytes rather than by ear. `wp.mon` holds two
|
|
391
|
+
lines:
|
|
392
|
+
|
|
393
|
+
```
|
|
394
|
+
tr store d408 d40b
|
|
395
|
+
x
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
and the run was
|
|
399
|
+
|
|
400
|
+
```
|
|
401
|
+
x64sc -default -warp +sound +autostart-delay-random -autostartprgmode 1 \
|
|
402
|
+
-limitcycles 5000000 -moncommands wp.mon -monlog -monlogname trace.log \
|
|
403
|
+
-exitscreenshot tr.png -autostart sfx-engine.prg
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
Three things about that command were found by running it, not read. With
|
|
407
|
+
`-moncommands` the monitor plays the file and resumes on its own: a run
|
|
408
|
+
with the `x` line and a run without it both produced 553-store logs with
|
|
409
|
+
the same first stamp, and both exit screenshots show the program screen.
|
|
410
|
+
The `x` line is harmless and is kept. (An earlier version of this page said
|
|
411
|
+
the program never started without it; that run was short of cycles, not
|
|
412
|
+
short of an `x`.) `-limitcycles 2500000` was too few: the autostart
|
|
413
|
+
sequence takes about 3.0 million cycles before the program's first frame
|
|
414
|
+
(the first traced store is at cycle 3,043,377), so 5,000,000 gives about
|
|
415
|
+
100 frames. And `-monlogname` appends to an existing file; delete it
|
|
416
|
+
between runs. A `tr` (trace) checkpoint logs and continues; a `watch`
|
|
417
|
+
would stop in the monitor and hang a headless run, which was not tried.
|
|
418
|
+
|
|
419
|
+
The log has one `#1 (Trace store ...)` line and one disassembly line per
|
|
420
|
+
store, with the stored value in A for `STA` and in X for `STX`. The 100
|
|
421
|
+
frames logged 553 stores. Frame 39 (tune only) and frame 40 (the first
|
|
422
|
+
laser row) read, with the log's own cycle stamps on the right:
|
|
423
|
+
|
|
424
|
+
```
|
|
425
|
+
#1 (Trace store d408) 259/$103, 36/$24
|
|
426
|
+
.C:0d80 9D 01 D4 STA $D401,X - A:0C X:07 Y:02 SP:f2 ..-..I.. 3809961
|
|
427
|
+
#1 (Trace store d409) 259/$103, 43/$2b
|
|
428
|
+
.C:0d85 9D 02 D4 STA $D402,X - A:00 X:07 Y:02 SP:f2 ..-..IZ. 3809968
|
|
429
|
+
#1 (Trace store d40a) 259/$103, 50/$32
|
|
430
|
+
.C:0d8a 9D 03 D4 STA $D403,X - A:04 X:07 Y:02 SP:f2 ..-..I.. 3809975
|
|
431
|
+
#1 (Trace store d40b) 259/$103, 58/$3a
|
|
432
|
+
.C:0d8f 9D 04 D4 STA $D404,X - A:10 X:07 Y:02 SP:f2 ..-..I.. 3809983
|
|
433
|
+
|
|
434
|
+
#1 (Trace store d408) 261/$105, 50/$32
|
|
435
|
+
.C:0d80 9D 01 D4 STA $D401,X - A:0C X:07 Y:02 SP:f2 ..-..I.. 3829757
|
|
436
|
+
#1 (Trace store d409) 261/$105, 57/$39
|
|
437
|
+
.C:0d85 9D 02 D4 STA $D402,X - A:00 X:07 Y:02 SP:f2 ..-..IZ. 3829764
|
|
438
|
+
#1 (Trace store d40a) 262/$106, 1/$01
|
|
439
|
+
.C:0d8a 9D 03 D4 STA $D403,X - A:04 X:07 Y:02 SP:f2 ..-..I.. 3829771
|
|
440
|
+
#1 (Trace store d40b) 262/$106, 9/$09
|
|
441
|
+
.C:0d8f 9D 04 D4 STA $D404,X - A:11 X:07 Y:02 SP:f2 ..-..I.. 3829779
|
|
442
|
+
#1 (Trace store d408) 267/$10b, 50/$32
|
|
443
|
+
.C:0e13 8D 08 D4 STA $D408 - A:38 X:00 Y:02 SP:f2 ..-..I.. 3830135
|
|
444
|
+
#1 (Trace store d409) 267/$10b, 54/$36
|
|
445
|
+
.C:0e16 8E 09 D4 STX $D409 - A:38 X:00 Y:02 SP:f2 ..-..I.. 3830139
|
|
446
|
+
#1 (Trace store d40a) 267/$10b, 61/$3d
|
|
447
|
+
.C:0e1b 8D 0A D4 STA $D40A - A:08 X:00 Y:02 SP:f2 ..-..I.. 3830146
|
|
448
|
+
#1 (Trace store d40b) 268/$10c, 40/$28
|
|
449
|
+
.C:0e35 8E 0B D4 STX $D40B - A:08 X:09 Y:03 SP:f2 ..-..I.. 3830188
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
The tune's four stores come from one indexed loop (`STA $D401,X` with
|
|
453
|
+
X = 7 is `$D408`; Oscar64 turned the pointer walk into indexed stores) and
|
|
454
|
+
carry the tune's values `$0C $00 $04` and control `$10` or `$11`. In frame
|
|
455
|
+
40 the engine follows six raster lines later with `$38 $00 $08 $09`: row 0
|
|
456
|
+
of the laser table, frequency `$3800`, pulse width `$0800`, control
|
|
457
|
+
TEST+GATE. Frames 41 to 43 carry rows 1 to 3 (`$34`, `$2E`, `$26`); in
|
|
458
|
+
frame 44 the engine's first byte is `$20`, row 0 of the explosion, which
|
|
459
|
+
is the priority cut. The explosion's last row (`$01 $00 $00 $80`) is in
|
|
460
|
+
frame 67; frame 68 has the tune's four stores and nothing else. The voice
|
|
461
|
+
was handed back by the engine falling silent, not by writing anything. The
|
|
462
|
+
frames are one PAL frame apart (19,656 cycles); the first-store stamps of
|
|
463
|
+
consecutive frames differ by that give or take up to about 150 cycles
|
|
464
|
+
(19,506 to 19,809 across the 100 logged frames), because the loop's work
|
|
465
|
+
before the tune's store varies from frame to frame. All writes sit on
|
|
466
|
+
raster lines 259 to 268, below the display window, because the loop waits
|
|
467
|
+
on `vic_waitFrame()`.
|
|
468
|
+
|
|
469
|
+
## Why this works
|
|
470
|
+
|
|
471
|
+
The SID has no register latch: the last write to a register is what the
|
|
472
|
+
chip runs with. So a tune that writes voice 2 every frame and an engine that
|
|
473
|
+
writes voice 2 every frame do not fight if they run in a fixed order. The
|
|
474
|
+
tune goes first, the engine second, and whichever wrote last owns the
|
|
475
|
+
voice. Handing the voice back needs no code at all: the engine stops
|
|
476
|
+
writing, and the tune's next frame stands. That is why the terminator row
|
|
477
|
+
is the whole hand-back. The one cost of this arrangement is that the
|
|
478
|
+
effect's ADSR cannot be written "once at start" in the literal sense,
|
|
479
|
+
because the tune overwrites `$D40C`/`$D40D` every frame; the engine keeps
|
|
480
|
+
them in the effect header and re-pokes them with the row. AD and SR are
|
|
481
|
+
rate settings, so rewriting the same value should not disturb a running
|
|
482
|
+
envelope; that is rung 4, not measured here as audio. A player that
|
|
483
|
+
honours a voice mask lets the engine skip the
|
|
484
|
+
AD/SR re-poke and write them once; see the technique entry.
|
|
485
|
+
|
|
486
|
+
The priority rule is two comparisons: a request is refused only if an
|
|
487
|
+
effect is running and the request's priority is lower. Equal priority
|
|
488
|
+
restarts, which is what a repeated gun shot wants. The effect's first row
|
|
489
|
+
sets TEST+GATE (`$09`): the TEST+GATE frame of the classic hard restart in
|
|
490
|
+
`hardware/sid-reference.md`, followed a frame later by the real waveform
|
|
491
|
+
with GATE, which are that sequence's last two frames without the AD=0/SR=$F0
|
|
492
|
+
frame before them. (The SID page's own "test-bit restart" variant is a
|
|
493
|
+
different thing: TEST alone, cleared on the gate frame; this recipe does not
|
|
494
|
+
use it.) So the oscillator restarts from zero whatever
|
|
495
|
+
the tune left in it; the last gated row drops GATE so the tune's next
|
|
496
|
+
gate-on begins a fresh attack rather than inheriting a sustain. Whether
|
|
497
|
+
those choices sound right is not established here: nothing on this machine
|
|
498
|
+
can listen. What is established is that the bytes reach the registers in
|
|
499
|
+
the order the table says, and that the tune's bytes return the frame after
|
|
500
|
+
the terminator.
|
|
501
|
+
|
|
502
|
+
The tune stub is deliberately dull: a triangle wave on each voice, pitch
|
|
503
|
+
stepping through 32 values, gate toggling every eight frames, fixed pulse
|
|
504
|
+
width and ADSR, volume 15. It exists to write all 22 registers each frame
|
|
505
|
+
so the engine's re-poke is tested against the same load a real player
|
|
506
|
+
gives it. Replace `tune_play()` with a real player's play call and the
|
|
507
|
+
engine is unchanged; keep the order.
|
|
508
|
+
|
|
509
|
+
The timing harness stops CIA1 timer A before reading it so the two byte
|
|
510
|
+
reads cannot straddle a borrow, and the program runs with interrupts off
|
|
511
|
+
(`sei`) so the KERNAL's 60 Hz use of the same timer cannot land inside a
|
|
512
|
+
measurement. The main loop runs once per frame on `vic_waitFrame()`, which
|
|
513
|
+
is a poll, not an interrupt; a game would call `tune_play()` then
|
|
514
|
+
`sfx_update()` from its raster IRQ in the same order.
|