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,996 @@
|
|
|
1
|
+
# C64 Registers Quick Reference
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This document is a single-page index of every memory-mapped I/O register
|
|
6
|
+
visible to the 6510 in the $D000-$DFFF window of a stock Commodore 64.
|
|
7
|
+
It exists so an agent (or a human) who knows only an address — "what
|
|
8
|
+
lives at $D012?" — can land on the right chip without first guessing
|
|
9
|
+
which datasheet to open.
|
|
10
|
+
|
|
11
|
+
It is intentionally **tabular only**. Each chip's registers are listed
|
|
12
|
+
in a name + address + R/W + one-line description grid. The full
|
|
13
|
+
per-register detail — bit layouts, side effects, timing notes, code
|
|
14
|
+
snippets — lives in the per-chip reference documents:
|
|
15
|
+
|
|
16
|
+
- [VIC-II reference](vic-ii-reference.md) — $D000-$D02F
|
|
17
|
+
- [SID reference](sid-reference.md) — $D400-$D41C
|
|
18
|
+
- [CIA reference](cia-reference.md) — $DC00-$DC0F (CIA1) and $DD00-$DD0F (CIA2)
|
|
19
|
+
|
|
20
|
+
**Why no register H3s in this file.** The graph extractor in
|
|
21
|
+
`src/graph/extract.ts` pulls one `Register` node per H3 of the form
|
|
22
|
+
`### $XXXX — NAME — Description (RW)`. Duplicating those H3s here and
|
|
23
|
+
in the per-chip docs would create double-counted nodes and ambiguous
|
|
24
|
+
ownership edges. The Phase-1 plan (Task 8) calls out this choice
|
|
25
|
+
explicitly: H3s live in the per-chip docs; this composite is purely an
|
|
26
|
+
index. The doc-type marker at the foot of the file tells the extractor
|
|
27
|
+
this is hardware-reference content so it is parsed and validated, but
|
|
28
|
+
since there are no register-shaped H3s in it, no `Register` nodes are
|
|
29
|
+
created from this file.
|
|
30
|
+
|
|
31
|
+
Wherever you see an unusual addressing range — the $D040-$D3FF VIC-II
|
|
32
|
+
mirror, the $D420-$D7FF SID mirror, the per-CIA $xx10-$xxFF mirrors —
|
|
33
|
+
this doc is also the single place that documents the **shadow regions**.
|
|
34
|
+
Those mirrors are real hardware behaviour, not aliases bolted on by
|
|
35
|
+
software. Touching them counts as touching the underlying register and
|
|
36
|
+
can cause every side effect the real register causes.
|
|
37
|
+
|
|
38
|
+
## Conventions used in this doc
|
|
39
|
+
|
|
40
|
+
- All addresses are hex, dollar-prefixed: `$D012`.
|
|
41
|
+
- Register tables use the canonical name from the per-chip reference docs.
|
|
42
|
+
These are the same short symbolic names that appear in the MOS data sheets
|
|
43
|
+
and in the C64 Programmer's Reference Guide ("MSIGX", "SCROLY", "VMCSB",
|
|
44
|
+
"FRELO1", etc.). Some sources use different mnemonics for the same
|
|
45
|
+
register; the per-chip doc is authoritative.
|
|
46
|
+
- "R", "W", "RW" describe what the CPU can do at that address.
|
|
47
|
+
- "Latching" / "destructive" notes mean the act of reading or writing that
|
|
48
|
+
address changes hidden state in the chip beyond the visible data byte —
|
|
49
|
+
see the bit-level treatment in the per-chip doc.
|
|
50
|
+
- "Mirror" / "shadow" mean the same physical register responds to multiple
|
|
51
|
+
CPU addresses because the chip only decodes the low bits of the address.
|
|
52
|
+
This is not aliasing for convenience; it is the actual decode.
|
|
53
|
+
|
|
54
|
+
## I/O window layout
|
|
55
|
+
|
|
56
|
+
The $D000-$DFFF window is what appears to the CPU when the I/O area is
|
|
57
|
+
banked in (the default state after RESET: HIRAM/LORAM/CHAREN = `%111`,
|
|
58
|
+
which gives BASIC + KERNAL + I/O). The window is divided as follows.
|
|
59
|
+
|
|
60
|
+
| Range | Owner | Size | Notes |
|
|
61
|
+
|---------------|------------------|------------|--------------------------------------------------------------|
|
|
62
|
+
| $D000-$D02F | VIC-II | 48 bytes | 47 registers + 1 unused ($D02F reads $FF) |
|
|
63
|
+
| $D030-$D03F | VIC-II "unused" | 16 bytes | Read as $FF; writes ignored |
|
|
64
|
+
| $D040-$D3FF | VIC-II shadow | 960 bytes | $D000-$D03F mirror, repeats every $40 bytes |
|
|
65
|
+
| $D400-$D41C | SID | 29 bytes | 25 W + 4 R; full register set |
|
|
66
|
+
| $D41D-$D41F | SID "unused" | 3 bytes | Not decoded. Reads return the byte the SID last drove on its bus (last SID write, or last $D419-$D41C read), on either chip model — not $FF, not $00; see the SID registers section below |
|
|
67
|
+
| $D420-$D7FF | SID shadow | 992 bytes | $D400-$D41F mirror, repeats every $20 bytes |
|
|
68
|
+
| $D800-$DBFF | Color RAM | 1024 bytes | 4-bit-wide static RAM (nybble-wide) |
|
|
69
|
+
| $DC00-$DC0F | CIA1 | 16 bytes | Keyboard / joystick / IRQ source |
|
|
70
|
+
| $DC10-$DCFF | CIA1 shadow | 240 bytes | $DC00-$DC0F mirror, repeats every $10 bytes |
|
|
71
|
+
| $DD00-$DD0F | CIA2 | 16 bytes | VIC bank / serial bus / user port / NMI source |
|
|
72
|
+
| $DD10-$DDFF | CIA2 shadow | 240 bytes | $DD00-$DD0F mirror, repeats every $10 bytes |
|
|
73
|
+
| $DE00-$DEFF | I/O-1 expansion | 256 bytes | Cartridge I/O page 1 (open bus if no cart) |
|
|
74
|
+
| $DF00-$DFFF | I/O-2 expansion | 256 bytes | Cartridge I/O page 2 (open bus if no cart) |
|
|
75
|
+
|
|
76
|
+
The window only appears at all because CHAREN (bit 2 of $01) and the
|
|
77
|
+
HIRAM/LORAM bits decide whether the area maps to I/O, to character
|
|
78
|
+
ROM, or to RAM. With CHAREN = 1 (and LORAM or HIRAM = 1) the CPU sees
|
|
79
|
+
I/O; with CHAREN = 0 (and LORAM or HIRAM = 1) the CPU sees the 4 KB
|
|
80
|
+
character ROM at $D000-$DFFF instead — this is how programs copy the
|
|
81
|
+
ROM font ($01 = $33, SEI first, because the KERNAL IRQ handler's
|
|
82
|
+
LDA $DC0D would read font bytes instead of the CIA). To reach the RAM
|
|
83
|
+
under $D000-$DFFF clear both LORAM and HIRAM ($01 = $30 or $34); CHAREN
|
|
84
|
+
alone never exposes RAM. The VIC-II ignores CHAREN and the rest of $01
|
|
85
|
+
entirely: it sees the character ROM at $1000-$1FFF of bank 0 and
|
|
86
|
+
$9000-$9FFF of bank 2 regardless of what the CPU has banked in. See
|
|
87
|
+
[c64-memory-map.md](c64-memory-map.md) modes 25-27 for the full
|
|
88
|
+
bank-switching treatment.
|
|
89
|
+
|
|
90
|
+
(An earlier version of this page said the character ROM was visible to
|
|
91
|
+
the VIC-II only and never to the CPU, and that clearing CHAREN exposed
|
|
92
|
+
RAM; both were wrong — measured in VICE x64sc: with $01 = $33 the CPU
|
|
93
|
+
reads $3C/$66/$18 at $D000/$D001/$DBE8, bytes 0, 1 and $BE8 of the
|
|
94
|
+
chargen ROM, and with $01 = $30 it reads back RAM.)
|
|
95
|
+
|
|
96
|
+
## VIC-II registers ($D000-$D02F)
|
|
97
|
+
|
|
98
|
+
The video chip exposes 47 active registers in a 48-byte page (the final
|
|
99
|
+
$D02F always reads $FF). All addresses are CPU-visible only when the
|
|
100
|
+
I/O area is banked in. For bit-level detail, mode-by-mode behaviour, and
|
|
101
|
+
race-condition notes, see [vic-ii-reference.md](vic-ii-reference.md).
|
|
102
|
+
|
|
103
|
+
| Address | Name | R/W | Description |
|
|
104
|
+
|---------|--------|-----|------------------------------------------|
|
|
105
|
+
| $D000 | M0X | RW | Sprite 0 X position (low 8 bits) |
|
|
106
|
+
| $D001 | M0Y | RW | Sprite 0 Y position |
|
|
107
|
+
| $D002 | M1X | RW | Sprite 1 X position (low 8 bits) |
|
|
108
|
+
| $D003 | M1Y | RW | Sprite 1 Y position |
|
|
109
|
+
| $D004 | M2X | RW | Sprite 2 X position (low 8 bits) |
|
|
110
|
+
| $D005 | M2Y | RW | Sprite 2 Y position |
|
|
111
|
+
| $D006 | M3X | RW | Sprite 3 X position (low 8 bits) |
|
|
112
|
+
| $D007 | M3Y | RW | Sprite 3 Y position |
|
|
113
|
+
| $D008 | M4X | RW | Sprite 4 X position (low 8 bits) |
|
|
114
|
+
| $D009 | M4Y | RW | Sprite 4 Y position |
|
|
115
|
+
| $D00A | M5X | RW | Sprite 5 X position (low 8 bits) |
|
|
116
|
+
| $D00B | M5Y | RW | Sprite 5 Y position |
|
|
117
|
+
| $D00C | M6X | RW | Sprite 6 X position (low 8 bits) |
|
|
118
|
+
| $D00D | M6Y | RW | Sprite 6 Y position |
|
|
119
|
+
| $D00E | M7X | RW | Sprite 7 X position (low 8 bits) |
|
|
120
|
+
| $D00F | M7Y | RW | Sprite 7 Y position |
|
|
121
|
+
| $D010 | MSIGX | RW | Sprite X position MSBs (bit n = sprite n) |
|
|
122
|
+
| $D011 | SCROLY | RW | Screen control register 1 / raster MSB / Y-scroll |
|
|
123
|
+
| $D012 | RASTER | RW | Raster line counter (R) / compare (W), low 8 bits |
|
|
124
|
+
| $D013 | LPENX | R | Light pen X position (latched at trigger) |
|
|
125
|
+
| $D014 | LPENY | R | Light pen Y position (latched at trigger) |
|
|
126
|
+
| $D015 | SPENA | RW | Sprite enable (bit n = sprite n) |
|
|
127
|
+
| $D016 | SCROLX | RW | Screen control register 2 / X-scroll / MCM / 38-col |
|
|
128
|
+
| $D017 | YXPAND | RW | Sprite Y expansion (bit n = sprite n) |
|
|
129
|
+
| $D018 | VMCSB | RW | Memory pointers (video matrix + character base) |
|
|
130
|
+
| $D019 | VICIRQ | RW | Interrupt status / latch (write 1 to ack) |
|
|
131
|
+
| $D01A | IRQMSK | RW | Interrupt mask / enable |
|
|
132
|
+
| $D01B | SPBGPR | RW | Sprite-to-background priority (bit n = sprite n) |
|
|
133
|
+
| $D01C | SPMC | RW | Sprite multicolor enable (bit n = sprite n) |
|
|
134
|
+
| $D01D | XXPAND | RW | Sprite X expansion (bit n = sprite n) |
|
|
135
|
+
| $D01E | SPSPCL | R | Sprite-sprite collision (clears on read) |
|
|
136
|
+
| $D01F | SPBGCL | R | Sprite-background collision (clears on read) |
|
|
137
|
+
| $D020 | EXTCOL | RW | Border color (low nibble) |
|
|
138
|
+
| $D021 | BGCOL0 | RW | Background color 0 (low nibble) |
|
|
139
|
+
| $D022 | BGCOL1 | RW | Background color 1 (low nibble) — MCM / ECM |
|
|
140
|
+
| $D023 | BGCOL2 | RW | Background color 2 (low nibble) — MCM / ECM |
|
|
141
|
+
| $D024 | BGCOL3 | RW | Background color 3 (low nibble) — ECM only |
|
|
142
|
+
| $D025 | SPMC0 | RW | Sprite multicolor 0 (shared) |
|
|
143
|
+
| $D026 | SPMC1 | RW | Sprite multicolor 1 (shared) |
|
|
144
|
+
| $D027 | SP0COL | RW | Sprite 0 individual color (low nibble) |
|
|
145
|
+
| $D028 | SP1COL | RW | Sprite 1 individual color (low nibble) |
|
|
146
|
+
| $D029 | SP2COL | RW | Sprite 2 individual color (low nibble) |
|
|
147
|
+
| $D02A | SP3COL | RW | Sprite 3 individual color (low nibble) |
|
|
148
|
+
| $D02B | SP4COL | RW | Sprite 4 individual color (low nibble) |
|
|
149
|
+
| $D02C | SP5COL | RW | Sprite 5 individual color (low nibble) |
|
|
150
|
+
| $D02D | SP6COL | RW | Sprite 6 individual color (low nibble) |
|
|
151
|
+
| $D02E | SP7COL | RW | Sprite 7 individual color (low nibble) |
|
|
152
|
+
| $D02F | UNUSED | R | Unused on stock VIC-II; reads $FF |
|
|
153
|
+
|
|
154
|
+
Quick groupings:
|
|
155
|
+
|
|
156
|
+
| Function | Addresses |
|
|
157
|
+
|---------------------------|-------------------------------------------------------------|
|
|
158
|
+
| Sprite positions | $D000-$D00F (low) + $D010 (MSBs) |
|
|
159
|
+
| Screen control | $D011 (SCROLY), $D016 (SCROLX), $D018 (VMCSB) |
|
|
160
|
+
| Raster / IRQ | $D011 bit 7, $D012, $D019, $D01A |
|
|
161
|
+
| Sprite enable + flags | $D015, $D017, $D01B, $D01C, $D01D |
|
|
162
|
+
| Collisions | $D01E (sprite-sprite), $D01F (sprite-background) |
|
|
163
|
+
| Colors (screen) | $D020, $D021, $D022, $D023, $D024 |
|
|
164
|
+
| Colors (sprites) | $D025, $D026, $D027-$D02E |
|
|
165
|
+
| Light pen | $D013, $D014 |
|
|
166
|
+
|
|
167
|
+
The remaining bytes in $D030-$D03F all read $FF on a stock VIC-II and
|
|
168
|
+
ignore writes. They are reserved by Commodore and are used on later
|
|
169
|
+
chips: the VIC-IIe (8564/8566) in the C128 uses $D02F for the three
|
|
170
|
+
extra keyboard lines (bits 0-2 are stored; the upper five read 1) and
|
|
171
|
+
$D030 for the 2 MHz clock select (bit 0) and the test bit (bit 1; the
|
|
172
|
+
upper six read 1). On a stock 64 both addresses are dead. An earlier
|
|
173
|
+
revision of this page put the key port at "$D02F-$D030", which was
|
|
174
|
+
wrong: $D030 holds no keyboard bit. The register widths and the clock
|
|
175
|
+
bit were measured in VICE x128 3.10, in native and C64 mode with
|
|
176
|
+
identical results; which keyboard lines the $D02F bits drive is from
|
|
177
|
+
the C128 documentation and was not measured here.
|
|
178
|
+
|
|
179
|
+
## VIC-II shadow registers ($D040-$D3FF)
|
|
180
|
+
|
|
181
|
+
The VIC-II decodes only the bottom 6 bits of the address for register
|
|
182
|
+
selection. The chip's chip-select responds to the whole page $D000-$D3FF,
|
|
183
|
+
so the visible 64-byte page repeats sixteen times across that range.
|
|
184
|
+
|
|
185
|
+
| Mirror base | Mirrors |
|
|
186
|
+
|-------------|-------------------|
|
|
187
|
+
| $D040-$D07F | $D000-$D03F |
|
|
188
|
+
| $D080-$D0BF | $D000-$D03F |
|
|
189
|
+
| $D0C0-$D0FF | $D000-$D03F |
|
|
190
|
+
| $D100-$D13F | $D000-$D03F |
|
|
191
|
+
| $D140-$D17F | $D000-$D03F |
|
|
192
|
+
| $D180-$D1BF | $D000-$D03F |
|
|
193
|
+
| $D1C0-$D1FF | $D000-$D03F |
|
|
194
|
+
| $D200-$D23F | $D000-$D03F |
|
|
195
|
+
| $D240-$D27F | $D000-$D03F |
|
|
196
|
+
| $D280-$D2BF | $D000-$D03F |
|
|
197
|
+
| $D2C0-$D2FF | $D000-$D03F |
|
|
198
|
+
| $D300-$D33F | $D000-$D03F |
|
|
199
|
+
| $D340-$D37F | $D000-$D03F |
|
|
200
|
+
| $D380-$D3BF | $D000-$D03F |
|
|
201
|
+
| $D3C0-$D3FF | $D000-$D03F |
|
|
202
|
+
|
|
203
|
+
So `LDA $D012`, `LDA $D052`, `LDA $D092`, ..., `LDA $D3D2` all read the
|
|
204
|
+
same raster counter; `STA $D020`, `STA $D060`, ..., `STA $D3E0` all
|
|
205
|
+
write the border color. The mapping is `effective = ((addr - $D000) AND
|
|
206
|
+
$003F) + $D000`.
|
|
207
|
+
|
|
208
|
+
Code seen in the wild that uses shadow addresses (for example writing
|
|
209
|
+
$D420 instead of $D400, or addressing the raster counter as $D052 in a
|
|
210
|
+
relocatable loop) is correct hardware-level code, but it's rare. Most
|
|
211
|
+
of the time, an address outside $D000-$D02F is a bug — a missing zero
|
|
212
|
+
in the literal, a stale pointer, a `STA absolute,Y` whose Y register
|
|
213
|
+
walked past 47.
|
|
214
|
+
|
|
215
|
+
The 16x mirror is the same effect that lets the VIC-IIe revision
|
|
216
|
+
re-use those addresses for new functions without breaking software:
|
|
217
|
+
old software won't be writing $D030 on purpose, and if it does, it
|
|
218
|
+
already expected the write to be a no-op.
|
|
219
|
+
|
|
220
|
+
### VIC-II quick lookup by function
|
|
221
|
+
|
|
222
|
+
When you know the visual effect you want but not the register:
|
|
223
|
+
|
|
224
|
+
| You want to ... | Register(s) |
|
|
225
|
+
|-------------------------------------------------------------|---------------------------|
|
|
226
|
+
| Move sprite N horizontally | $D000 + 2N, $D010 bit N |
|
|
227
|
+
| Move sprite N vertically | $D001 + 2N |
|
|
228
|
+
| Turn sprite N on / off | $D015 bit N |
|
|
229
|
+
| Change sprite N's individual color | $D027 + N |
|
|
230
|
+
| Stretch sprite N horizontally | $D01D bit N |
|
|
231
|
+
| Stretch sprite N vertically | $D017 bit N |
|
|
232
|
+
| Put sprite N "behind" character cells | $D01B bit N (set) |
|
|
233
|
+
| Detect sprite-sprite overlap | $D01E (read, clears) |
|
|
234
|
+
| Detect sprite-background overlap | $D01F (read, clears) |
|
|
235
|
+
| Read the current raster line | $D012 (low), $D011 bit 7 (MSB) |
|
|
236
|
+
| Arm a raster interrupt at line L | $D012 + $D011 bit 7, $D01A bit 0 |
|
|
237
|
+
| Acknowledge a raster interrupt | $D019 (write 1 to bit 0) |
|
|
238
|
+
| Switch screen mode (text / bitmap / MCM / ECM) | $D011 bits 5,6; $D016 bit 4 |
|
|
239
|
+
| Smooth-scroll vertically | $D011 bits 0-2 (YSCROLL) |
|
|
240
|
+
| Smooth-scroll horizontally | $D016 bits 0-2 (XSCROLL) |
|
|
241
|
+
| Switch to 38-column mode (open side borders) | $D016 bit 3 = 0 |
|
|
242
|
+
| Switch to 24-row mode (open top/bottom borders) | $D011 bit 3 = 0 |
|
|
243
|
+
| Set border color | $D020 |
|
|
244
|
+
| Set background color (mode 0) | $D021 |
|
|
245
|
+
| Point video matrix at screen RAM base | $D018 bits 4-7 |
|
|
246
|
+
| Point video matrix at character base | $D018 bits 1-3 |
|
|
247
|
+
|
|
248
|
+
## SID registers ($D400-$D41C)
|
|
249
|
+
|
|
250
|
+
The SID (MOS 6581 or its later 8580 successor) exposes 29 registers in a
|
|
251
|
+
32-byte page. The first 25 are write-only and the last 4 read-only, so
|
|
252
|
+
you cannot recover state from the first 25 by reading them back.
|
|
253
|
+
Reading a write-only SID register ($D400-$D418),
|
|
254
|
+
or one of the undecoded addresses $D41D-$D41F (and their mirrors
|
|
255
|
+
through $D7FF), returns the byte the SID last drove on its data bus:
|
|
256
|
+
the last value WRITTEN to any SID register, or the last value READ from
|
|
257
|
+
$D419-$D41C — a read of ENV3 or OSC3 refreshes it too. It is not $FF,
|
|
258
|
+
not $00, and not the CPU's last fetched byte, on either chip model.
|
|
259
|
+
Measured in VICE 3.10 x64sc with reSID (`-sound -sounddev dummy
|
|
260
|
+
-sidengine 1`, both `-sidmodel 0` and `1`): after STA $D400,#$AA the
|
|
261
|
+
reads of $D401 and $D41D-$D41F all return $AA; after LDA $D41C (=$00)
|
|
262
|
+
a read of $D41D returns $00. The held byte fades to $00 — in reSID
|
|
263
|
+
after about 7k cycles on the 6581 model and about 660k on the 8580
|
|
264
|
+
model, measured on [sid-reference.md](sid-reference.md) ("Write-only
|
|
265
|
+
registers"); an earlier version of this paragraph said the byte was
|
|
266
|
+
still there 1.3 M cycles later, which the SID page's measurement and
|
|
267
|
+
reSID's own time-to-live constants contradict. Real chips fade too;
|
|
268
|
+
the rates are not measured here. Never use these addresses
|
|
269
|
+
as a constant source or for read-modify-write; keep a software shadow.
|
|
270
|
+
Earlier versions of this page gave $FF, $00-on-8580 and the CPU's last
|
|
271
|
+
fetch; none matched the instrument. Harness note: with sound disabled
|
|
272
|
+
(`+sound`, the command line in CLAUDE.md) VICE substitutes a stand-in
|
|
273
|
+
SID that returns $00 for every write-only/undecoded read, so a $00 seen
|
|
274
|
+
that way is the emulator, not the chip. For bit-level detail on each register, the
|
|
275
|
+
ADSR rate table, filter routing, and the well-known oddities (the
|
|
276
|
+
$D418 master-volume click, the ADSR-bug, voice 3 mute, the absent
|
|
277
|
+
test pin readback), see [sid-reference.md](sid-reference.md).
|
|
278
|
+
|
|
279
|
+
| Address | Name | R/W | Description |
|
|
280
|
+
|---------|---------|-----|----------------------------------------------|
|
|
281
|
+
| $D400 | FRELO1 | W | Voice 1 frequency, low byte |
|
|
282
|
+
| $D401 | FREHI1 | W | Voice 1 frequency, high byte |
|
|
283
|
+
| $D402 | PWLO1 | W | Voice 1 pulse width, low byte |
|
|
284
|
+
| $D403 | PWHI1 | W | Voice 1 pulse width, high nibble (bits 0-3) |
|
|
285
|
+
| $D404 | VCREG1 | W | Voice 1 control: gate / sync / ring / test / waveform |
|
|
286
|
+
| $D405 | ATDCY1 | W | Voice 1 attack (hi nibble) / decay (lo nibble) |
|
|
287
|
+
| $D406 | SUREL1 | W | Voice 1 sustain (hi nibble) / release (lo nibble) |
|
|
288
|
+
| $D407 | FRELO2 | W | Voice 2 frequency, low byte |
|
|
289
|
+
| $D408 | FREHI2 | W | Voice 2 frequency, high byte |
|
|
290
|
+
| $D409 | PWLO2 | W | Voice 2 pulse width, low byte |
|
|
291
|
+
| $D40A | PWHI2 | W | Voice 2 pulse width, high nibble (bits 0-3) |
|
|
292
|
+
| $D40B | VCREG2 | W | Voice 2 control: gate / sync / ring / test / waveform |
|
|
293
|
+
| $D40C | ATDCY2 | W | Voice 2 attack / decay |
|
|
294
|
+
| $D40D | SUREL2 | W | Voice 2 sustain / release |
|
|
295
|
+
| $D40E | FRELO3 | W | Voice 3 frequency, low byte |
|
|
296
|
+
| $D40F | FREHI3 | W | Voice 3 frequency, high byte |
|
|
297
|
+
| $D410 | PWLO3 | W | Voice 3 pulse width, low byte |
|
|
298
|
+
| $D411 | PWHI3 | W | Voice 3 pulse width, high nibble (bits 0-3) |
|
|
299
|
+
| $D412 | VCREG3 | W | Voice 3 control: gate / sync / ring / test / waveform |
|
|
300
|
+
| $D413 | ATDCY3 | W | Voice 3 attack / decay |
|
|
301
|
+
| $D414 | SUREL3 | W | Voice 3 sustain / release |
|
|
302
|
+
| $D415 | CUTLO | W | Filter cutoff frequency, low 3 bits |
|
|
303
|
+
| $D416 | CUTHI | W | Filter cutoff frequency, high 8 bits |
|
|
304
|
+
| $D417 | RESON | W | Filter resonance (hi nibble) + voice routing (lo nibble) |
|
|
305
|
+
| $D418 | SIGVOL | W | Filter mode select / voice-3 mute / master volume |
|
|
306
|
+
| $D419 | POTX | R | Paddle X — A/D converter result |
|
|
307
|
+
| $D41A | POTY | R | Paddle Y — A/D converter result |
|
|
308
|
+
| $D41B | RANDOM | R | Voice 3 oscillator output, high 8 bits |
|
|
309
|
+
| $D41C | ENV3 | R | Voice 3 envelope generator output |
|
|
310
|
+
|
|
311
|
+
$D41D, $D41E, and $D41F are not decoded. Reads return the held bus byte
|
|
312
|
+
described above — the last SID write or the last $D419-$D41C read, on
|
|
313
|
+
either chip model (VICE 3.10 x64sc, reSID, both `-sidmodel` values:
|
|
314
|
+
$AA after STA $D400,#$AA; $00 after LDA $D41C). Writes are discarded.
|
|
315
|
+
An earlier version of this paragraph said floating bus on a 6581 and
|
|
316
|
+
$00 on an 8580; neither matched the instrument.
|
|
317
|
+
|
|
318
|
+
Quick groupings:
|
|
319
|
+
|
|
320
|
+
| Voice | Frequency | Pulse width | Control | Attack/Decay | Sustain/Release |
|
|
321
|
+
|-------|-----------------|------------------|---------|--------------|-----------------|
|
|
322
|
+
| 1 | $D400 / $D401 | $D402 / $D403 | $D404 | $D405 | $D406 |
|
|
323
|
+
| 2 | $D407 / $D408 | $D409 / $D40A | $D40B | $D40C | $D40D |
|
|
324
|
+
| 3 | $D40E / $D40F | $D410 / $D411 | $D412 | $D413 | $D414 |
|
|
325
|
+
|
|
326
|
+
| Function | Addresses |
|
|
327
|
+
|-------------------|--------------------------|
|
|
328
|
+
| Filter | $D415, $D416, $D417, $D418 |
|
|
329
|
+
| Volume / mode | $D418 |
|
|
330
|
+
| Paddles | $D419, $D41A |
|
|
331
|
+
| Voice 3 readback | $D41B (oscillator), $D41C (envelope) |
|
|
332
|
+
|
|
333
|
+
The voice-3 readbacks at $D41B (RANDOM / oscillator high byte) and $D41C
|
|
334
|
+
(ENV3) are the only way to read state out of an oscillator/envelope.
|
|
335
|
+
They are wired to voice 3 specifically. Code that wants a noise source
|
|
336
|
+
or an LFO routes voice 3 to an arbitrary frequency/waveform, optionally
|
|
337
|
+
disconnects it from the audio output via $D418 bit 7, and samples
|
|
338
|
+
$D41B or $D41C as needed.
|
|
339
|
+
|
|
340
|
+
## SID shadow registers ($D420-$D7FF)
|
|
341
|
+
|
|
342
|
+
The SID, like the VIC-II, decodes only the bottom 5 bits of the
|
|
343
|
+
address. Its chip-select responds to the whole 1 KB at $D400-$D7FF, so
|
|
344
|
+
the 32-byte register page repeats 31 times.
|
|
345
|
+
|
|
346
|
+
| Mirror base | Mirrors |
|
|
347
|
+
|-------------|-------------------|
|
|
348
|
+
| $D420-$D43F | $D400-$D41F |
|
|
349
|
+
| $D440-$D45F | $D400-$D41F |
|
|
350
|
+
| $D460-$D47F | $D400-$D41F |
|
|
351
|
+
| ... | ... |
|
|
352
|
+
| $D7C0-$D7DF | $D400-$D41F |
|
|
353
|
+
| $D7E0-$D7FF | $D400-$D41F |
|
|
354
|
+
|
|
355
|
+
`effective = ((addr - $D400) AND $001F) + $D400`.
|
|
356
|
+
|
|
357
|
+
A write to $D420 hits FRELO1. A write to $D7E0 hits FRELO1. A write to
|
|
358
|
+
$D7E0+$18 = $D7F8 hits SIGVOL ($D418) — that means a stray store to a
|
|
359
|
+
"safe-looking" high address in the I/O range can pop the speaker just
|
|
360
|
+
as loudly as a direct write to $D418, and it can do so in code that
|
|
361
|
+
never mentions $D418 by name. See the [Pitfalls](#pitfalls) section
|
|
362
|
+
below.
|
|
363
|
+
|
|
364
|
+
Second-SID boards decode a second chip at $D420 or $D500 (or another
|
|
365
|
+
base inside this shadow window), gating the original SID's chip-select
|
|
366
|
+
— which products, and at which base, is not verified here (an earlier
|
|
367
|
+
version named "SID-Wizard 8-bit DAC", which is a tracker, not a board).
|
|
368
|
+
On stock hardware, however, the entire $D420-$D7FF range is one
|
|
369
|
+
chip — the same SID, mirrored.
|
|
370
|
+
|
|
371
|
+
### SID quick lookup by function
|
|
372
|
+
|
|
373
|
+
| You want to ... | Register(s) |
|
|
374
|
+
|-------------------------------------------------------|----------------------------|
|
|
375
|
+
| Set voice N pitch | $D400 + 7(N-1), $D401 + 7(N-1) |
|
|
376
|
+
| Set voice N pulse width | $D402 + 7(N-1), $D403 + 7(N-1) |
|
|
377
|
+
| Gate / release voice N | $D404 + 7(N-1) bit 0 |
|
|
378
|
+
| Pick waveform for voice N | $D404 + 7(N-1) bits 4-7 |
|
|
379
|
+
| Set voice N attack/decay | $D405 + 7(N-1) |
|
|
380
|
+
| Set voice N sustain/release | $D406 + 7(N-1) |
|
|
381
|
+
| Enable ring modulation on voice N | $D404 + 7(N-1) bit 2 |
|
|
382
|
+
| Enable hard sync on voice N | $D404 + 7(N-1) bit 1 |
|
|
383
|
+
| Reset voice N oscillator (test bit) | $D404 + 7(N-1) bit 3 = 1 |
|
|
384
|
+
| Set filter cutoff frequency | $D415, $D416 |
|
|
385
|
+
| Set filter resonance | $D417 bits 4-7 |
|
|
386
|
+
| Route voice N through filter | $D417 bit (N-1) |
|
|
387
|
+
| Route external audio in through filter | $D417 bit 3 |
|
|
388
|
+
| Select filter mode (LP / BP / HP / BR) | $D418 bits 4-6 |
|
|
389
|
+
| Mute voice 3 from audio output (keep oscillator) | $D418 bit 7 |
|
|
390
|
+
| Set master volume | $D418 bits 0-3 |
|
|
391
|
+
| Read paddle X / Y | $D419, $D41A |
|
|
392
|
+
| Read voice 3 oscillator output (random source) | $D41B |
|
|
393
|
+
| Read voice 3 envelope output (LFO source) | $D41C |
|
|
394
|
+
| Reset SID completely | Write 0 to $D404, $D40B, $D412, $D418; then re-init |
|
|
395
|
+
|
|
396
|
+
Word-of-warning patterns:
|
|
397
|
+
|
|
398
|
+
- A common "fade out" routine writes $00..$0F to $D418 over time.
|
|
399
|
+
But writing $D418 also reconfigures filter mode and voice-3 mute
|
|
400
|
+
— so the standard idiom is to OR with the current $D418 value
|
|
401
|
+
cached in zero page, not to write a raw nibble. Writing a raw
|
|
402
|
+
nibble silently un-mutes voice 3 and switches the filter to "no
|
|
403
|
+
filter" mode.
|
|
404
|
+
- How completely $D418 bit 7 (3OFF) silences voice 3 on real silicon
|
|
405
|
+
is reported differently for the two chips in different sources, and
|
|
406
|
+
is not measured here (an earlier version of this bullet asserted
|
|
407
|
+
that the 6581's mixer leaks; `pitfalls/sid.md` asserts the reverse).
|
|
408
|
+
In reSID both models drop voice 3 from the direct path. Do not rely
|
|
409
|
+
on 3OFF for silence on either chip — set the voice's volume to zero
|
|
410
|
+
through its envelope instead.
|
|
411
|
+
|
|
412
|
+
## Color RAM ($D800-$DBFF)
|
|
413
|
+
|
|
414
|
+
Color RAM is a 1 KB block of static RAM dedicated to the per-character
|
|
415
|
+
foreground color. Unlike RAM elsewhere in the C64, it is **4 bits wide**:
|
|
416
|
+
each address stores only the low nibble (0-15). The high nibble is not
|
|
417
|
+
stored anywhere: on a 6510 read it is whatever was last left on the
|
|
418
|
+
data bus, and on a C64 that is the byte the VIC-II fetched in the phi1
|
|
419
|
+
half-cycle just before the CPU's read — glyph or bitmap data inside the
|
|
420
|
+
display window, sprite pointers and sprite data, the DRAM-refresh bytes
|
|
421
|
+
from $3Fxx, and the idle fetch from $3FFF (or $39FF with ECM) in the
|
|
422
|
+
borders. It therefore changes with raster position, screen contents and
|
|
423
|
+
the VIC bank, and it is not the address high byte $D8 as this page
|
|
424
|
+
previously said — the CPU's operand fetch of $D8 is overwritten by the
|
|
425
|
+
VIC's fetch before the read cycle. Measured in VICE x64sc 3.10 (PAL):
|
|
426
|
+
with $3FFF=$A5, $3F00-$3FFE=$C3 and the sprite pointers set to $B0, a
|
|
427
|
+
cell holding 5 read $A5 in 77 of 100 border samples, $B5, $C5 and $05
|
|
428
|
+
in the rest, and $55 once $3FFF was changed to $5A — never $D5. Code
|
|
429
|
+
that needs a byte-clean value must mask with `AND #$0F`.
|
|
430
|
+
|
|
431
|
+
| Range | Description |
|
|
432
|
+
|---------------|------------------------------------------------------------|
|
|
433
|
+
| $D800-$DBE7 | Foreground color for each of the 1000 text cells (40 x 25). Byte n corresponds to character at $0400+n in the default screen RAM. |
|
|
434
|
+
| $D800-$DBFF | Used as additional color storage by multicolor bitmap mode |
|
|
435
|
+
| $DBE8-$DBFF | Unused by stock screen modes; on 4-bit chip, reads as undefined nibble high, low nibble is RAM |
|
|
436
|
+
|
|
437
|
+
Color RAM is always at $D800-$DBFF regardless of which VIC-II video
|
|
438
|
+
bank is selected by CIA2 $DD00 bits 0-1, because the VIC-II has a
|
|
439
|
+
dedicated wire to the color RAM that bypasses the normal address
|
|
440
|
+
multiplexer. The VIC-II reads the low nibble of color RAM in parallel
|
|
441
|
+
with each character matrix fetch — the chip pin is the same pin used
|
|
442
|
+
to provide the high 4 bits of the character matrix, and on display
|
|
443
|
+
fetch the color RAM's data is multiplexed on top.
|
|
444
|
+
|
|
445
|
+
Practical consequences:
|
|
446
|
+
|
|
447
|
+
- **Always writable — through the I/O window.** Colour RAM never
|
|
448
|
+
write-protects, but the CPU only reaches it while I/O is mapped at
|
|
449
|
+
$D000. A write made with I/O banked out lands in the DRAM underneath
|
|
450
|
+
$D800 and the VIC never sees it (measured in VICE x64sc: colour RAM
|
|
451
|
+
seeded 5, then `LDA #$34 / STA $01 / LDA #9 / STA $D800` — the cell
|
|
452
|
+
still displays colour 5 and reads back 5 once I/O is restored).
|
|
453
|
+
- **High nibble undefined.** Reads of $D800+n only contain meaningful
|
|
454
|
+
data in bits 0-3.
|
|
455
|
+
- **Reachable only through the I/O window.** The VIC always sees colour
|
|
456
|
+
RAM, whatever $01 or $DD00 say. The CPU sees it only while I/O is
|
|
457
|
+
banked in — $01 bits 0-2 = %101, %110 or %111 ($35/$36/$37). With
|
|
458
|
+
CHAREN = 0 and LORAM or HIRAM set (%001-%011, $31-$33) the CPU reads
|
|
459
|
+
character ROM at $D800-$DBFF instead; with LORAM = HIRAM = 0
|
|
460
|
+
(%000/%100, $30/$34) it reads and writes the plain RAM underneath, and
|
|
461
|
+
CHAREN makes no difference. All eight modes measured in VICE x64sc.
|
|
462
|
+
An earlier version of this page said only CHAREN mattered; it does
|
|
463
|
+
not — code in the all-RAM configuration ($34) must bank I/O back in
|
|
464
|
+
($35) before touching colour RAM.
|
|
465
|
+
- **Power-on contents are random.** Most programs `LDA #col / STA $D800,X`
|
|
466
|
+
in a loop before turning on the screen. If you switch into a screen mode
|
|
467
|
+
before initializing color RAM, the visible glyphs will use whatever
|
|
468
|
+
random nibble is in RAM as their foreground color.
|
|
469
|
+
|
|
470
|
+
For multicolor character mode, bit 3 of color RAM toggles per-cell
|
|
471
|
+
whether that character uses the multicolor palette ($D021/$D022/$D023
|
|
472
|
+
+ low 3 bits of color RAM) or the standard hi-res palette ($D021 +
|
|
473
|
+
color RAM low nibble). See [vic-ii-reference.md](vic-ii-reference.md)
|
|
474
|
+
multicolor text mode section.
|
|
475
|
+
|
|
476
|
+
## CIA1 registers ($DC00-$DC0F)
|
|
477
|
+
|
|
478
|
+
CIA1 is the 6526 Complex Interface Adapter wired to the keyboard
|
|
479
|
+
matrix, the two control-port joysticks, the paddles (multiplexed with
|
|
480
|
+
joystick port 1), and the system IRQ line. It is the source of the
|
|
481
|
+
jiffy-clock IRQ that drives most KERNAL timing. The KERNAL programs it
|
|
482
|
+
to ~60 Hz on BOTH regions, not 60/50: the timer-load tail of IOINIT
|
|
483
|
+
($FDDD-$FDF8), which CINT ($FF5B) re-enters once it has detected the
|
|
484
|
+
region into $02A6 (the VIC init table sets raster compare 311, a line
|
|
485
|
+
only a PAL frame reaches), writes Timer A latch $4025 on PAL
|
|
486
|
+
(985,248 / 16,422 = 59.996 Hz) and $4295 on NTSC (1,022,727 / 17,046 =
|
|
487
|
+
59.998 Hz). One jiffy is 1/60 s everywhere; only the video frame rate
|
|
488
|
+
differs (50.12 Hz PAL, 59.83 Hz NTSC 6567R8). An earlier version of
|
|
489
|
+
this page said 50 Hz on PAL; the ROM bytes at $FDE2-$FDF5 of
|
|
490
|
+
kernal-901227-03 say otherwise, and a VICE x64sc count gives 299
|
|
491
|
+
jiffies in 250 PAL frames, not 250.
|
|
492
|
+
|
|
493
|
+
For bit-level detail on each register — including the keyboard scan
|
|
494
|
+
matrix, the joystick bit-to-pin mapping, the TOD clock's BCD
|
|
495
|
+
encoding, and how the timer control bits interact — see
|
|
496
|
+
[cia-reference.md](cia-reference.md).
|
|
497
|
+
|
|
498
|
+
| Address | Name | R/W | Description |
|
|
499
|
+
|---------|------|-----|--------------------------------------------------------|
|
|
500
|
+
| $DC00 | DC00 | RW | Data Port A — keyboard column drive / joystick port 2 |
|
|
501
|
+
| $DC01 | DC01 | RW | Data Port B — keyboard row read / joystick port 1 |
|
|
502
|
+
| $DC02 | DC02 | RW | Data Direction Register A |
|
|
503
|
+
| $DC03 | DC03 | RW | Data Direction Register B |
|
|
504
|
+
| $DC04 | DC04 | RW | Timer A low byte (latch on write, current on read) |
|
|
505
|
+
| $DC05 | DC05 | RW | Timer A high byte (latch on write, current on read) |
|
|
506
|
+
| $DC06 | DC06 | RW | Timer B low byte |
|
|
507
|
+
| $DC07 | DC07 | RW | Timer B high byte |
|
|
508
|
+
| $DC08 | DC08 | RW | Time-of-day tenths-of-second (BCD) |
|
|
509
|
+
| $DC09 | DC09 | RW | Time-of-day seconds (BCD) |
|
|
510
|
+
| $DC0A | DC0A | RW | Time-of-day minutes (BCD) |
|
|
511
|
+
| $DC0B | DC0B | RW | Time-of-day hours (BCD, bit 7 = AM/PM) |
|
|
512
|
+
| $DC0C | DC0C | RW | Serial shift register |
|
|
513
|
+
| $DC0D | DC0D | RW | Interrupt control register — drives /IRQ |
|
|
514
|
+
| $DC0E | DC0E | RW | Control register A (Timer A run / mode / TOD freq) |
|
|
515
|
+
| $DC0F | DC0F | RW | Control register B (Timer B run / mode / TOD set) |
|
|
516
|
+
|
|
517
|
+
Quick groupings:
|
|
518
|
+
|
|
519
|
+
| Function | Addresses |
|
|
520
|
+
|--------------------|--------------------------------------|
|
|
521
|
+
| Ports | $DC00, $DC01, $DC02, $DC03 |
|
|
522
|
+
| Timer A | $DC04, $DC05, $DC0E |
|
|
523
|
+
| Timer B | $DC06, $DC07, $DC0F |
|
|
524
|
+
| Time-of-day clock | $DC08, $DC09, $DC0A, $DC0B; $DC0E bit 7 (50/60 Hz input), $DC0F bit 7 (clock/alarm write select) |
|
|
525
|
+
| Serial port | $DC0C |
|
|
526
|
+
| Interrupts | $DC0D only (write: mask, bit 7 = set/clear; read: flags, and the read clears them). An earlier revision listed $DC0E bit 7 and $DC0F bit 7 here; they are TOD controls, not interrupt bits (measured in VICE x64sc). |
|
|
527
|
+
|
|
528
|
+
The system jiffy IRQ comes from Timer A on CIA1, programmed by the
|
|
529
|
+
KERNAL at boot to fire ~60 times per second on both PAL and NTSC
|
|
530
|
+
(latch $4025 PAL / $4295 NTSC, $DC0D=$81, $DC0E=$11) and to invoke the
|
|
531
|
+
IRQ vector via $0314/$0315. Programs that want their
|
|
532
|
+
own raster IRQ usually disable CIA1's Timer A IRQ at $DC0D (and
|
|
533
|
+
re-enable VIC-II's raster IRQ at $D01A bit 0) so the only interrupt
|
|
534
|
+
source is the video chip.
|
|
535
|
+
|
|
536
|
+
### CIA1 quick lookup by function
|
|
537
|
+
|
|
538
|
+
| You want to ... | Register(s) |
|
|
539
|
+
|--------------------------------------------------|---------------------------|
|
|
540
|
+
| Scan the keyboard | $DC00 (drive col), $DC01 (read row), $DC02/$DC03 (DDR) |
|
|
541
|
+
| Read joystick port 2 | $DC00 bits 0-4 (low = pressed) |
|
|
542
|
+
| Read joystick port 1 | $DC01 bits 0-4 (low = pressed) |
|
|
543
|
+
| Read paddle buttons | $DC00 (port 2) / $DC01 (port 1) bits 2 and 3 — paddle A and paddle B buttons appear on the joystick LEFT and RIGHT lines, not on FIRE (bit 4). From the Programmer's Reference Guide's paddle section, not measured here: a headless VICE cannot press a paddle button. An earlier version of this row said bit 4 |
|
|
544
|
+
| Switch which paddle pair is multiplexed in | $DC00 bits 6-7 (%01 = port 1, %10 = port 2; $DC02 bits 6-7 must be outputs, which the KERNAL leaves them). Measured in VICE x64sc; an earlier revision of this row said $DD00, whose bits 6-7 are IEC CLK IN / DATA IN and have nothing to do with paddles. The KERNAL keyboard scan rewrites $DC00 every jiffy IRQ, so select the pair with IRQs masked or re-select before each read, and allow the ~512-cycle settle |
|
|
545
|
+
| Program Timer A as a one-shot | $DC04, $DC05, $DC0E bit 3 = 1 |
|
|
546
|
+
| Program Timer A as continuous | $DC04, $DC05, $DC0E bit 3 = 0 |
|
|
547
|
+
| Start Timer A | $DC0E bit 0 = 1 |
|
|
548
|
+
| Enable Timer A underflow IRQ | $DC0D = $81 |
|
|
549
|
+
| Disable all CIA1 IRQs (e.g. for raster work) | $DC0D = $7F (clear all) |
|
|
550
|
+
| Acknowledge any pending CIA1 IRQ | Read $DC0D |
|
|
551
|
+
| Read the TOD clock | Read $DC0B first (latches), then $DC0A, $DC09, $DC08 |
|
|
552
|
+
| Set the TOD clock | $DC0F bit 7 = 0, then write $DC0B (hours; stops the clock), $DC0A, $DC09, $DC08 (tenths; restarts it). With bit 7 = 1 the same four writes program the ALARM and leave the clock untouched — this row used to say bit 7 = 1 (measured in VICE x64sc). Write the alarm while the clock cannot equal any intermediate alarm value: a partially written alarm that matches the running clock sets $DC0D bit 2 at once (observed in VICE). Both rules and the probe behind them: `pitfalls/cia.md` → `tod_read_order_latch` |
|
|
553
|
+
| Toggle TOD source frequency (50 vs 60 Hz) | $DC0E bit 7 |
|
|
554
|
+
|
|
555
|
+
## CIA1 shadow registers ($DC10-$DCFF)
|
|
556
|
+
|
|
557
|
+
CIA1 decodes only the bottom 4 bits of the address. Its chip-select
|
|
558
|
+
responds to all of $DC00-$DCFF, so the 16-byte register page repeats
|
|
559
|
+
15 times.
|
|
560
|
+
|
|
561
|
+
| Mirror base | Mirrors |
|
|
562
|
+
|-------------|----------------|
|
|
563
|
+
| $DC10-$DC1F | $DC00-$DC0F |
|
|
564
|
+
| $DC20-$DC2F | $DC00-$DC0F |
|
|
565
|
+
| $DC30-$DC3F | $DC00-$DC0F |
|
|
566
|
+
| $DC40-$DC4F | $DC00-$DC0F |
|
|
567
|
+
| $DC50-$DC5F | $DC00-$DC0F |
|
|
568
|
+
| $DC60-$DC6F | $DC00-$DC0F |
|
|
569
|
+
| $DC70-$DC7F | $DC00-$DC0F |
|
|
570
|
+
| $DC80-$DC8F | $DC00-$DC0F |
|
|
571
|
+
| $DC90-$DC9F | $DC00-$DC0F |
|
|
572
|
+
| $DCA0-$DCAF | $DC00-$DC0F |
|
|
573
|
+
| $DCB0-$DCBF | $DC00-$DC0F |
|
|
574
|
+
| $DCC0-$DCCF | $DC00-$DC0F |
|
|
575
|
+
| $DCD0-$DCDF | $DC00-$DC0F |
|
|
576
|
+
| $DCE0-$DCEF | $DC00-$DC0F |
|
|
577
|
+
| $DCF0-$DCFF | $DC00-$DC0F |
|
|
578
|
+
|
|
579
|
+
`effective = ((addr - $DC00) AND $000F) + $DC00`.
|
|
580
|
+
|
|
581
|
+
The shadow has the same destructive properties as the real registers —
|
|
582
|
+
notably, **a read of $DCnD with the low nibble = D acknowledges and
|
|
583
|
+
clears all pending IRQ source bits**. A loop that walks `LDA $DC00,X`
|
|
584
|
+
across a wide range of X will, on every 16th byte, silently
|
|
585
|
+
acknowledge CIA1's IRQ register and lose any pending interrupt source
|
|
586
|
+
bits. Well-behaved C64 software does not walk $D000-$DFFF with a
|
|
587
|
+
generic loop for exactly this reason: the area is hostile to careless
|
|
588
|
+
reads. A memory test or copy that needs those 4 KB either skips them or
|
|
589
|
+
banks the I/O area out first and reads the RAM underneath (see the I/O
|
|
590
|
+
window layout section above and c64-memory-map.md). An earlier revision
|
|
591
|
+
of this sentence had lost its negation and read as though software
|
|
592
|
+
walks the I/O area deliberately. The hazard is measured, not assumed:
|
|
593
|
+
in VICE x64sc 3.10, with a Timer A underflow pending, a `LDA $DC00,X`
|
|
594
|
+
walk over X = 0..255 left $DC0D reading $00, while a walk over
|
|
595
|
+
X = 0..12 that never touched an $xD address left it reading $81.
|
|
596
|
+
|
|
597
|
+
## CIA2 registers ($DD00-$DD0F)
|
|
598
|
+
|
|
599
|
+
CIA2 is the second 6526. It owns the VIC-II's two bank-select bits
|
|
600
|
+
(the high two address bits the chip uses to choose its 16 KB window),
|
|
601
|
+
the serial bus to peripherals like the 1541, the RS-232 lines, the
|
|
602
|
+
user port's data lines, and the system NMI line.
|
|
603
|
+
|
|
604
|
+
| Address | Name | R/W | Description |
|
|
605
|
+
|---------|------|-----|------------------------------------------------------------|
|
|
606
|
+
| $DD00 | DD00 | RW | Data Port A — VIC bank select (bits 0-1) + IEC serial bus |
|
|
607
|
+
| $DD01 | DD01 | RW | Data Port B — user port data |
|
|
608
|
+
| $DD02 | DD02 | RW | Data Direction Register A |
|
|
609
|
+
| $DD03 | DD03 | RW | Data Direction Register B |
|
|
610
|
+
| $DD04 | DD04 | RW | Timer A low byte |
|
|
611
|
+
| $DD05 | DD05 | RW | Timer A high byte |
|
|
612
|
+
| $DD06 | DD06 | RW | Timer B low byte |
|
|
613
|
+
| $DD07 | DD07 | RW | Timer B high byte |
|
|
614
|
+
| $DD08 | DD08 | RW | Time-of-day tenths-of-second |
|
|
615
|
+
| $DD09 | DD09 | RW | Time-of-day seconds |
|
|
616
|
+
| $DD0A | DD0A | RW | Time-of-day minutes |
|
|
617
|
+
| $DD0B | DD0B | RW | Time-of-day hours |
|
|
618
|
+
| $DD0C | DD0C | RW | Serial shift register (RS-232 receive) |
|
|
619
|
+
| $DD0D | DD0D | RW | Interrupt control register — drives /NMI |
|
|
620
|
+
| $DD0E | DD0E | RW | Control register A (Timer A) |
|
|
621
|
+
| $DD0F | DD0F | RW | Control register B (Timer B) |
|
|
622
|
+
|
|
623
|
+
Quick groupings:
|
|
624
|
+
|
|
625
|
+
| Function | Addresses |
|
|
626
|
+
|----------------------------|--------------------------------------|
|
|
627
|
+
| Ports + VIC bank + serial | $DD00, $DD01, $DD02, $DD03 |
|
|
628
|
+
| Timer A | $DD04, $DD05, $DD0E |
|
|
629
|
+
| Timer B | $DD06, $DD07, $DD0F |
|
|
630
|
+
| Time-of-day | $DD08-$DD0B |
|
|
631
|
+
| RS-232 receive | $DD0C |
|
|
632
|
+
| NMI source | $DD0D |
|
|
633
|
+
|
|
634
|
+
Key wiring points (the per-pin table is in
|
|
635
|
+
[cia-reference.md](cia-reference.md)):
|
|
636
|
+
|
|
637
|
+
- **$DD00 bits 0-1** — VIC-II bank select. Inverted: `00 = $C000-$FFFF`,
|
|
638
|
+
`01 = $8000-$BFFF`, `10 = $4000-$7FFF`, `11 = $0000-$3FFF` (default
|
|
639
|
+
after RESET).
|
|
640
|
+
- **$DD00 bit 2** — user-port PA2, the KERNAL's RS-232 TXD output (idle
|
|
641
|
+
high; the NMI transmit code masks it with `AND #$FB` at `$FE7E` before
|
|
642
|
+
the store at `$FE82`).
|
|
643
|
+
- **$DD00 bits 3-5** — IEC outputs: ATN OUT, CLK OUT, DATA OUT. Writing 1
|
|
644
|
+
pulls the bus line low (the KERNAL's CLKLO at `$EE8E` is `ORA #$10`,
|
|
645
|
+
CLKHI at `$EE85` is `AND #$EF`).
|
|
646
|
+
- **$DD00 bits 6-7** — IEC inputs: CLK IN, DATA IN. These are *not*
|
|
647
|
+
inverted: 1 = line released (high), 0 = line pulled low by some device.
|
|
648
|
+
Measured in VICE x64sc 3.10: with all outputs released $DD00 reads $C7;
|
|
649
|
+
with a 1541 answering ATN, bit 7 reads 0; and the KERNAL's
|
|
650
|
+
device-not-present test at `$ED47` is `BCS` on bit 7. The KERNAL's DDR
|
|
651
|
+
of $3F (`$FDD0`) makes exactly bits 0-5 outputs. (An earlier version of
|
|
652
|
+
this list put the inputs inside "bits 2-5".)
|
|
653
|
+
- **$DD0D** — write with bit 7 = 1 plus bit n to enable NMI source n
|
|
654
|
+
(bit 7 = 0 plus bit n to disable it); a read returns the pending flags
|
|
655
|
+
and clears them. RESTORE is **not** a CIA2 source: the key reaches the
|
|
656
|
+
6510's /NMI pin through its own one-shot timer, in parallel with CIA2's
|
|
657
|
+
/IRQ output (wiring in [cia-reference.md](cia-reference.md)). The
|
|
658
|
+
KERNAL handler at $FE47 masks $DD0D with $7F, reads it, and goes to the
|
|
659
|
+
RS-232 code only if a CIA2 bit is set; with none set it checks for a
|
|
660
|
+
cartridge (CBM80 → JMP ($8002)), then the STOP key, and warm-starts
|
|
661
|
+
BASIC through ($A002) only when RUN/STOP is held — RESTORE alone
|
|
662
|
+
returns. That is why RUN/STOP+RESTORE is "almost a reset". (An earlier
|
|
663
|
+
version of this page said RESTORE came in on /FLAG, bit 4, and that the
|
|
664
|
+
KERNAL armed it; IOINIT at $FDA3 writes $7F to $DD0D, which disables
|
|
665
|
+
FLAG, and the only KERNAL code that enables FLAG is RS-232 receive at
|
|
666
|
+
$EF7E — read from kernal-901227-03.bin.) The dispatch table, the
|
|
667
|
+
20-cycle cost of taking $0318 and the NMI lock are in
|
|
668
|
+
`pitfalls/kernal-and-io.md` → `restore_nmi_not_maskable`.
|
|
669
|
+
|
|
670
|
+
### CIA2 quick lookup by function
|
|
671
|
+
|
|
672
|
+
| You want to ... | Register(s) |
|
|
673
|
+
|--------------------------------------------------|---------------------------|
|
|
674
|
+
| Switch VIC-II to bank N (0-3) | $DD00 bits 0-1 = NOT N |
|
|
675
|
+
| Drive the IEC serial bus (1541 etc.) | $DD00 bits 3,4,5 (ATN, CLK, DATA out) |
|
|
676
|
+
| Read IEC serial bus status | $DD00 bits 6,7 + $DD01 (user-port-routed) |
|
|
677
|
+
| Set up an RS-232 receive | $DD0C, $DD04, $DD05, $DD0E |
|
|
678
|
+
| Use Timer A for music IRQ via NMI | $DD04, $DD05, $DD0E, $DD0D bit 0 |
|
|
679
|
+
| Neutralise the RESTORE key | Point $0318/$0319 at an RTI or your own handler ($FE43 does SEI / JMP ($0318) with nothing pushed, so a bare RTI is valid). No $DD0D value masks it — an earlier revision of this row said $DD0D = $10, which clears an already-clear bit and leaves RESTORE armed. Pitfall: `restore_nmi_not_maskable` |
|
|
680
|
+
| Acknowledge any pending CIA2 NMI | Read $DD0D |
|
|
681
|
+
| Use the user port as 8 GPIO lines | $DD01, $DD03 (DDR) |
|
|
682
|
+
|
|
683
|
+
## CIA2 shadow registers ($DD10-$DDFF)
|
|
684
|
+
|
|
685
|
+
Same 4-bit decode rule as CIA1: the 16-byte page mirrors 15 times.
|
|
686
|
+
|
|
687
|
+
| Mirror base | Mirrors |
|
|
688
|
+
|-------------|----------------|
|
|
689
|
+
| $DD10-$DD1F | $DD00-$DD0F |
|
|
690
|
+
| $DD20-$DD2F | $DD00-$DD0F |
|
|
691
|
+
| $DD30-$DD3F | $DD00-$DD0F |
|
|
692
|
+
| $DD40-$DD4F | $DD00-$DD0F |
|
|
693
|
+
| $DD50-$DD5F | $DD00-$DD0F |
|
|
694
|
+
| $DD60-$DD6F | $DD00-$DD0F |
|
|
695
|
+
| $DD70-$DD7F | $DD00-$DD0F |
|
|
696
|
+
| $DD80-$DD8F | $DD00-$DD0F |
|
|
697
|
+
| $DD90-$DD9F | $DD00-$DD0F |
|
|
698
|
+
| $DDA0-$DDAF | $DD00-$DD0F |
|
|
699
|
+
| $DDB0-$DDBF | $DD00-$DD0F |
|
|
700
|
+
| $DDC0-$DDCF | $DD00-$DD0F |
|
|
701
|
+
| $DDD0-$DDDF | $DD00-$DD0F |
|
|
702
|
+
| $DDE0-$DDEF | $DD00-$DD0F |
|
|
703
|
+
| $DDF0-$DDFF | $DD00-$DD0F |
|
|
704
|
+
|
|
705
|
+
`effective = ((addr - $DD00) AND $000F) + $DD00`.
|
|
706
|
+
|
|
707
|
+
Like CIA1, reads of $DDnD with low nibble = D ack and clear CIA2's
|
|
708
|
+
pending NMI source bits. Most of the time NMIs are not enabled and
|
|
709
|
+
the shadow does no harm, but if a program is using a CIA2 timer NMI
|
|
710
|
+
(common for fast loaders and SoundMonitor-style audio) the same hazard
|
|
711
|
+
applies.
|
|
712
|
+
|
|
713
|
+
## I/O expansion ($DE00-$DFFF)
|
|
714
|
+
|
|
715
|
+
These two 256-byte pages are reserved for cartridges. They are wired
|
|
716
|
+
to the expansion-port pins /IO1 and /IO2, which a cartridge can use to
|
|
717
|
+
decode its own registers.
|
|
718
|
+
|
|
719
|
+
| Range | Pin | Notes |
|
|
720
|
+
|---------------|-------|-------------------------------------------------------------------------|
|
|
721
|
+
| $DE00-$DEFF | /IO1 | Cartridge I/O page 1. No internal devices. |
|
|
722
|
+
| $DF00-$DFFF | /IO2 | Cartridge I/O page 2. No internal devices. |
|
|
723
|
+
|
|
724
|
+
Behaviour with no cartridge present:
|
|
725
|
+
|
|
726
|
+
- Reads return open bus: the byte the VIC-II fetched in the preceding
|
|
727
|
+
phi1 half-cycle, all eight bits — in the border the idle byte at $3FFF
|
|
728
|
+
of the current VIC bank, on screen glyph/bitmap data, plus sprite
|
|
729
|
+
pointers and $3Fxx refresh bytes. It is not the address high byte, and
|
|
730
|
+
the CPU drives nothing during a read (this page previously said
|
|
731
|
+
$DE/$DF; the operand byte the CPU fetched is overwritten by the VIC's
|
|
732
|
+
fetch before the read cycle). Measured in VICE x64sc 3.10: $DE00 and
|
|
733
|
+
$DF00 both returned $A5/$B0/$C3/$00, tracking $3FFF, the sprite
|
|
734
|
+
pointers, $3Fxx and the last display line's glyph rows — never $DE or
|
|
735
|
+
$DF. Board-revision differences are not measured here. Do not detect a
|
|
736
|
+
cartridge by reading these addresses; write a pattern and read it back
|
|
737
|
+
(see c64-memory-map.md).
|
|
738
|
+
- Writes are discarded.
|
|
739
|
+
|
|
740
|
+
Behaviour with a cartridge present is entirely cartridge-defined.
|
|
741
|
+
Common conventions:
|
|
742
|
+
|
|
743
|
+
| Cartridge family | $DE00 use | $DF00 use |
|
|
744
|
+
|---------------------------|--------------------------------------------------------------|----------------------------------------------------|
|
|
745
|
+
| Action Replay / Final Cartridge / Retro Replay | Control register: write controls ROM bank, mode select, freeze release | RAM mirror or alt control |
|
|
746
|
+
| EasyFlash | Bank select / mode register at $DE00 / $DE02 | EasyFlash LED + I/O |
|
|
747
|
+
| Magic Desk | $DE00 bit-mapped bank select (8x8 KB) | Unused |
|
|
748
|
+
| KCS Power Cartridge | $DF00 control | $DF00 control |
|
|
749
|
+
| GeoRAM / NeoRAM | $DE00 window into a 256-byte RAM page; $DFFE/$DFFF select page | Page register |
|
|
750
|
+
| Reu (1700/1750/1764) | $DF00-$DF0A: full REC register set (status, command, base, target, length) | (same) |
|
|
751
|
+
| MMC64 / MMC Replay | $DF10-$DF13: SD card SPI port | |
|
|
752
|
+
|
|
753
|
+
Software written to be cartridge-agnostic must avoid touching $DE00-$DFFF
|
|
754
|
+
unless it knows what cartridge is plugged in. A spurious write here can
|
|
755
|
+
freeze the machine (Action Replay freeze trigger), swap RAM banks
|
|
756
|
+
underneath the running program (EasyFlash), or — for fast loaders that
|
|
757
|
+
use a REU detection routine — silently mis-detect and lose data.
|
|
758
|
+
|
|
759
|
+
## Address-to-chip dispatch table
|
|
760
|
+
|
|
761
|
+
This is the inverse table to the per-chip lists above: given any
|
|
762
|
+
address in $D000-$DFFF, find the chip and the effective canonical
|
|
763
|
+
register it resolves to. The intent is that an agent can land here
|
|
764
|
+
from an arbitrary literal seen in disassembly and figure out what
|
|
765
|
+
the program is touching.
|
|
766
|
+
|
|
767
|
+
| If address is in ... | The chip is ... | The effective register is ... |
|
|
768
|
+
|------------------------|--------------------|--------------------------------------------------------------------------------------------|
|
|
769
|
+
| $D000-$D02F | VIC-II | The literal address. |
|
|
770
|
+
| $D030-$D03F | VIC-II ("unused") | Reads $FF, writes ignored. Do not write — VIC-IIe uses these. |
|
|
771
|
+
| $D040-$D3FF | VIC-II shadow | `((addr - $D000) AND $3F) + $D000`. Watch for $D019 (IRQ ack) and $D01E/$D01F (clear-on-read). |
|
|
772
|
+
| $D400-$D41C | SID | The literal address. |
|
|
773
|
+
| $D41D-$D41F | SID ("unused") | Not decoded. Reads return the byte the SID last drove on its bus (last SID write or last $D419-$D41C read), either chip model — not $FF, not $00 (VICE reSID; see SID registers above); writes discarded. |
|
|
774
|
+
| $D420-$D7FF | SID shadow | `((addr - $D400) AND $1F) + $D400`. Watch for $D418 (master vol pop) and write-only registers — a read returns the SID's last bus byte, not the register's contents. |
|
|
775
|
+
| $D800-$DBFF | Color RAM | The literal address. 4-bit-wide RAM; mask reads with `AND #$0F`. |
|
|
776
|
+
| $DC00-$DC0F | CIA1 | The literal address. |
|
|
777
|
+
| $DC10-$DCFF | CIA1 shadow | `((addr - $DC00) AND $0F) + $DC00`. Any read of $DCxD ($DC0D, $DC1D, ..., $DCFD) acks/clears IRQ source bits. |
|
|
778
|
+
| $DD00-$DD0F | CIA2 | The literal address. |
|
|
779
|
+
| $DD10-$DDFF | CIA2 shadow | `((addr - $DD00) AND $0F) + $DD00`. Any read of $DDxD acks/clears NMI source bits. |
|
|
780
|
+
| $DE00-$DEFF | Cartridge /IO1 | Cartridge-defined. Open bus if no cartridge. |
|
|
781
|
+
| $DF00-$DFFF | Cartridge /IO2 | Cartridge-defined. Open bus if no cartridge. |
|
|
782
|
+
|
|
783
|
+
## Power-on / reset state
|
|
784
|
+
|
|
785
|
+
After RESET, the KERNAL initializes a subset of these registers to
|
|
786
|
+
known values before turning on the screen. The chips themselves do
|
|
787
|
+
not all power-up in a defined state — the per-chip docs list which
|
|
788
|
+
bits are guaranteed and which are floating.
|
|
789
|
+
|
|
790
|
+
Highlights of the KERNAL-set state. Two columns, because they differ:
|
|
791
|
+
what the KERNAL stores (ROM 901227-03, IOINIT $FDA3 and the VIC table
|
|
792
|
+
at $ECB9) and what the register reads back afterwards (measured in VICE
|
|
793
|
+
x64sc 3.10). An earlier version of this table mixed the two in one
|
|
794
|
+
column, called $7F in $DC00 "all columns high", and said $DD0D left
|
|
795
|
+
FLAG enabled for RESTORE; all three were wrong.
|
|
796
|
+
|
|
797
|
+
| Address | KERNAL writes | Reads back | What it means |
|
|
798
|
+
|---------|---------------|------------|---------------|
|
|
799
|
+
| $D011 | $9B | $1B (raster < 256; $9B on lines 256+) | RSEL=1, DEN=1, YSCROLL=3, BMM/ECM=0; bit 7 is the raster-compare MSB — with $D012=$37 the compare line is $137 |
|
|
800
|
+
| $D016 | $08 | $C8 | CSEL=1, MCM=0, XSCROLL=0; bits 6-7 always read 1 |
|
|
801
|
+
| $D018 | $14 | $15 | Video matrix $0400, character base $1000 (char ROM); bit 0 reads 1 |
|
|
802
|
+
| $D019 | $0F | $71 PAL / $70 NTSC | Write-1-to-ack of every latch; bits 4-6 read 1, and on PAL the raster latch is already set again because compare line 311 exists in a 312-line frame and not in NTSC's 263 |
|
|
803
|
+
| $D01A | $00 | $F0 | All VIC-II IRQ sources disabled; bits 4-7 read 1 |
|
|
804
|
+
| $D020 | $0E | $FE | Border light blue; high nibble reads 1 |
|
|
805
|
+
| $D021 | $06 | $F6 | Background blue; high nibble reads 1 |
|
|
806
|
+
| $D418 | $00 | (write-only) | Volume 0, filter off. The only SID register the KERNAL touches ($FDC4). $D400-$D417 are not written by software; the 6581 datasheet says the chip's own /RES clears them, which cannot be measured here because they are write-only |
|
|
807
|
+
| $DC00 | $7F | $7F | Column 7 driven low, the other seven high. UDTIM's STOP-key test ($F6BC) reads $DC01 bit 7 against this without re-selecting a column, and SCNKEY exits with the same $7F |
|
|
808
|
+
| $DC0D | $81 | $00 (pending flags; the mask cannot be read) | Timer A IRQ enabled (the jiffy clock) |
|
|
809
|
+
| $DC0E | $11 | $01 | Timer A running, continuous; bit 4 (LOAD) is a strobe and reads 0 |
|
|
810
|
+
| $DD00 | $07 | $97 | VIC bank 0 ($0000-$3FFF), TXD high, serial lines released; bits 6-7 are CLK IN / DATA IN and read 1 with the bus idle |
|
|
811
|
+
| $DD0D | $7F | $00 | All five CIA2 NMI sources disabled, FLAG included. RESTORE reaches /NMI directly, not through this register (see cia-reference.md); RS-232 OPEN enables FLAG and the timers later |
|
|
812
|
+
|
|
813
|
+
RUN/STOP+RESTORE is not a hardware reset, but it re-initialises far
|
|
814
|
+
more than an earlier version of this page said (it claimed the VIC-II
|
|
815
|
+
kept its display mode and colour RAM was untouched; both are wrong,
|
|
816
|
+
read from the 901227-03 ROM and measured in VICE x64sc). The KERNAL NMI
|
|
817
|
+
handler ($FE47) reads $DD0D; when no CIA2 source fired it checks for a
|
|
818
|
+
cartridge, scans the STOP key, and with STOP held runs RESTOR ($FD15 —
|
|
819
|
+
the RAM vectors $0314-$0333 go back to the KERNAL defaults, so a custom
|
|
820
|
+
IRQ or NMI handler is gone too), IOINIT ($FDA3 — both CIAs
|
|
821
|
+
re-programmed, $DD00 = $07, $01 = $E7, and $D418 = 0, the KERNAL's only
|
|
822
|
+
SID write) and CINT ($E518 — all 47 VIC-II registers rewritten from the
|
|
823
|
+
$ECB9 table: $D011 $1B, $D016 $C8 as read back ($08 is written), $D018
|
|
824
|
+
$14, $D020 $0E, $D021 $06, sprite colours 1-7 and grey for sprite 7 —
|
|
825
|
+
then screen RAM filled with spaces and colour RAM with $0E), and
|
|
826
|
+
finally jumps through ($A002) to the BASIC warm start. Only the SID's
|
|
827
|
+
$D400-$D417 keep their values, muted by volume 0: a note that was
|
|
828
|
+
sounding keeps oscillating and comes back the moment $D418 is written
|
|
829
|
+
again (POKE 54296,15). A plain RESTORE without RUN/STOP leaves screen,
|
|
830
|
+
colour RAM and SID alone: the handler finds no CIA2 source, sees STOP
|
|
831
|
+
up and RTIs; its only side effect is writing $7F to $DD0D, reading it
|
|
832
|
+
back (which acknowledges any CIA2 source), and restoring the mask from
|
|
833
|
+
the RS-232 enable byte $02A1.
|
|
834
|
+
|
|
835
|
+
## Pitfalls
|
|
836
|
+
|
|
837
|
+
- **Shadow-register confusion.** A "wrong" address that happens to fall
|
|
838
|
+
inside the I/O area very often does the same thing as the matching
|
|
839
|
+
base address, not nothing. Writing $D420 is writing $D400 (FRELO1);
|
|
840
|
+
writing $D7F8 is writing $D418 (SIGVOL — speaker pop); writing $D052
|
|
841
|
+
is writing $D012 (raster compare — your raster IRQ moves). A null
|
|
842
|
+
pointer plus a small offset can hit live hardware. See the per-chip
|
|
843
|
+
shadow sections above for the exact modulo rules.
|
|
844
|
+
|
|
845
|
+
- **$D7FF SID side-effects.** The very last byte of the SID shadow
|
|
846
|
+
region, $D7FF, mirrors $D41F, which is technically unused on a stock
|
|
847
|
+
SID. But $D7F8 mirrors $D418, $D7E5 mirrors $D405, $D7E0 mirrors
|
|
848
|
+
$D400. A program that uses $D700-$D7FF as scratchpad RAM because
|
|
849
|
+
"those addresses look free" is in fact writing every single SID
|
|
850
|
+
register on every store. This is one of the more common causes of
|
|
851
|
+
random clicks, mysterious sustained tones after a tune ends, and
|
|
852
|
+
paddle-readback corruption.
|
|
853
|
+
|
|
854
|
+
- **Color RAM high nibble is garbage.** `LDA $D800` returns `$?n` where
|
|
855
|
+
`?` is the byte the VIC fetched in the preceding phi1 cycle (idle byte
|
|
856
|
+
$3FFF in the border, glyph/bitmap data on screen, sprite pointers,
|
|
857
|
+
$3Fxx refresh) — not $D8, as this page once said. VICE x64sc:
|
|
858
|
+
$A5/$B5/$C5/$05 for a cell holding 5 with $3FFF=$A5. Always mask with
|
|
859
|
+
`AND #$0F` before comparing.
|
|
860
|
+
|
|
861
|
+
- **$DC0D / $DD0D destructive read.** Reading the interrupt control
|
|
862
|
+
register of either CIA acknowledges and clears every pending source
|
|
863
|
+
bit. Code that wants to inspect IRQ state without losing pending
|
|
864
|
+
interrupts has to mask interrupts (SEI), latch the read, and then
|
|
865
|
+
re-enable. The same hazard applies to every shadow address ending
|
|
866
|
+
in $D inside CIA1 or CIA2 — there are 16 such addresses per CIA in
|
|
867
|
+
the $xx00-$xxFF page.
|
|
868
|
+
|
|
869
|
+
- **$DE00 / $DF00 cartridge clobbering.** A naive memory test or RAM
|
|
870
|
+
copy that walks $D000-$DFFF will, on a machine with an Action
|
|
871
|
+
Replay or Final Cartridge plugged in, trigger the cartridge's
|
|
872
|
+
freeze logic or swap its RAM banks under the program. The standard
|
|
873
|
+
C64 KERNAL avoids $DE00 / $DF00 entirely. Software that needs to
|
|
874
|
+
detect free RAM should treat $DE00-$DFFF as off-limits unless it
|
|
875
|
+
has positively identified the cartridge (or absence thereof).
|
|
876
|
+
|
|
877
|
+
- **$D02F / $D030-$D03F are not always idle.** On a stock C64 these
|
|
878
|
+
read $FF and writes are ignored. On a C128 in C64 mode (with the
|
|
879
|
+
C128's VIC-IIe chip) $D02F is the extra-keyboard scan and $D030 is
|
|
880
|
+
the test-bit / 2 MHz clock select. Writing $D030 on a C128 will
|
|
881
|
+
drop the machine into 2 MHz mode and corrupt the display. Code that
|
|
882
|
+
targets "the C64" should still treat $D030-$D03F as untouchable.
|
|
883
|
+
|
|
884
|
+
- **VIC-II $D019 acknowledge.** Writing $D019 acknowledges interrupts
|
|
885
|
+
by writing a 1 to each source bit. Programs that do `LDA $D019 / STA
|
|
886
|
+
$D019` to "ack all sources" rely on the fact that $D019 reads only
|
|
887
|
+
meaningful bits and the latch+ack pattern works. The shadow
|
|
888
|
+
registers $D059, $D099, ..., $D3D9 work the same way — but again,
|
|
889
|
+
a stray write that happens to land on one of these is a real
|
|
890
|
+
acknowledgement.
|
|
891
|
+
|
|
892
|
+
- **Color RAM extra bytes ($DBE8-$DBFF).** These 24 bytes are RAM but
|
|
893
|
+
are unused by any standard screen mode. Some games use them as
|
|
894
|
+
free RAM for sprite multiplexers or scratch. Their contents survive
|
|
895
|
+
any bank switch (the chip is separate and is not written through
|
|
896
|
+
while I/O is out), but like the rest of colour RAM the CPU can only
|
|
897
|
+
read or write them while I/O is mapped — and they are still
|
|
898
|
+
nibble-wide, so do not use them for byte storage.
|
|
899
|
+
|
|
900
|
+
- **SID write-only registers do not read back.** Code that wants to
|
|
901
|
+
modify a single bit of, say, $D404 (voice 1 control) cannot
|
|
902
|
+
`LDA $D404 / ORA #$01 / STA $D404` — the read returns the SID's
|
|
903
|
+
last bus byte (see the SID registers section), not the register's
|
|
904
|
+
contents, so the OR result is wrong. The standard idiom is to keep a
|
|
905
|
+
shadow copy of every SID register in zero page or low RAM and to
|
|
906
|
+
read/modify/write the shadow, then `STA $D404`. The same applies
|
|
907
|
+
to every $D400-$D418 register. Player libraries (Hubbard's, Galway's,
|
|
908
|
+
SoundMonitor, GoatTracker's player) all maintain shadow tables for
|
|
909
|
+
this reason.
|
|
910
|
+
|
|
911
|
+
- **TOD clock latching ($DC08-$DC0B).** Reading $DC0B (hours) latches
|
|
912
|
+
the entire TOD value into the read register so that minutes, seconds,
|
|
913
|
+
and tenths can be read coherently. The latch is released by reading
|
|
914
|
+
$DC08 (tenths). Reading hours and then never reading tenths leaves
|
|
915
|
+
the clock frozen in the read register — although the underlying
|
|
916
|
+
counter keeps running, subsequent reads of seconds/minutes return
|
|
917
|
+
the latched value until tenths is read. Code that "peeks" at the
|
|
918
|
+
hour without intending to read the rest of the clock will silently
|
|
919
|
+
freeze its own view of the time. The write side has the mirror rule
|
|
920
|
+
— writing $DC0B stops the clock until $DC08 is written — and $DC0F
|
|
921
|
+
bit 7 must be 0 for those writes to reach the clock rather than the
|
|
922
|
+
alarm; `pitfalls/cia.md` → `tod_read_order_latch` carries both rules
|
|
923
|
+
and the VICE measurement behind them.
|
|
924
|
+
|
|
925
|
+
- **$DD00 bits are inverted for VIC bank select.** Bits 0-1 of $DD00
|
|
926
|
+
drive the high two address pins of the VIC-II, but they are
|
|
927
|
+
inverted. `LDA #$00 / STA $DD00` (with DDR set appropriately) puts
|
|
928
|
+
the VIC into bank 3 ($C000-$FFFF), not bank 0. To put the VIC into
|
|
929
|
+
bank 0 you must write `%11` to bits 0-1. Confusingly, the KERNAL's
|
|
930
|
+
default leaves the VIC in bank 0 ($0000-$3FFF) by writing $07 to
|
|
931
|
+
$DD00 (DDR = $3F).
|
|
932
|
+
|
|
933
|
+
- **Invalid display modes are black; $D016 bit 5 is inert.** Bit 5 of
|
|
934
|
+
$D016 is the datasheet's RES bit and has no function on the 6567/6569
|
|
935
|
+
(Bauer's VIC-II article, not measured on hardware here; in VICE x64sc
|
|
936
|
+
it reads back as written and the display is unchanged with it set).
|
|
937
|
+
The all-black screens are the three *invalid* mode combinations —
|
|
938
|
+
ECM+BMM, ECM+MCM and ECM+BMM+MCM, i.e. $D011 bit 6 (ECM) and bit 5
|
|
939
|
+
(BMM) together with $D016 bit 4 (MCM); see
|
|
940
|
+
[Illegal display modes](vic-ii-reference.md#illegal-display-modes).
|
|
941
|
+
Measured in VICE x64sc, each turns all 64,000 display-window pixels
|
|
942
|
+
black while the border keeps its colour and sprites and
|
|
943
|
+
sprite-foreground collisions ($D01F) still work. That is not the same
|
|
944
|
+
as clearing DEN, which paints the whole frame in the border colour and
|
|
945
|
+
stops badlines; and it has nothing to do with opening the side
|
|
946
|
+
borders, which is the CSEL ($D016 bit 3) 1→0 write on cycle 56. Code
|
|
947
|
+
that lands on one of these combinations during initialization looks
|
|
948
|
+
crashed when the chip is just drawing black. (An earlier version of
|
|
949
|
+
this entry attributed the black modes to $D016 bit 5 and to "bits 4
|
|
950
|
+
and 5 of $D011", called them equivalent to disabling the screen, and
|
|
951
|
+
said demos used them to open the side borders; none of that is so.)
|
|
952
|
+
|
|
953
|
+
- **Reading $DC04 / $DC05 while Timer A is running IS racy.** An earlier
|
|
954
|
+
version of this note claimed a "hidden read latch" made the two-byte
|
|
955
|
+
read atomic; there is none — the 6526 latches only the TOD (a read of
|
|
956
|
+
the hours freezes it, a read of the tenths releases it). Timer reads
|
|
957
|
+
return the live counter, so a borrow out of the low byte between the
|
|
958
|
+
two reads leaves the pair one page off (measured in VICE x64sc 3.10
|
|
959
|
+
with the KERNAL's Timer A running: 5 of 100 back-to-back low/high
|
|
960
|
+
pairs read 256 low, and a high byte read 1,297 cycles after a low-byte
|
|
961
|
+
read had moved five pages, not zero). Read high, low, high and retry
|
|
962
|
+
when the two high bytes differ, or stop the timer ($DC0E bit 0) around
|
|
963
|
+
the read — the idioms in cia-reference.md. Writes are the other half:
|
|
964
|
+
they go to the latch, and the counter takes the value only on
|
|
965
|
+
underflow, on force-load ($DC0E bit 4), or on a high-byte write while
|
|
966
|
+
the timer is stopped — so "set timer, then read back to confirm" on a
|
|
967
|
+
running timer sees the old count.
|
|
968
|
+
|
|
969
|
+
## Sources
|
|
970
|
+
|
|
971
|
+
Primary:
|
|
972
|
+
|
|
973
|
+
- [C64-Wiki: Memory Map](https://www.c64-wiki.com/wiki/Memory_Map)
|
|
974
|
+
- [C64-Wiki: I/O area](https://www.c64-wiki.com/wiki/I/O_area)
|
|
975
|
+
- [Codebase64 reference](https://codebase64.org/doku.php?id=base:c64_memory_map)
|
|
976
|
+
- MOS Technology 6567/6569 (VIC-II) datasheet
|
|
977
|
+
- MOS Technology 6581 (SID) datasheet, and revision notes for 8580
|
|
978
|
+
- MOS Technology 6526 (CIA) datasheet
|
|
979
|
+
- C64 Programmer's Reference Guide (Commodore Business Machines, 1982),
|
|
980
|
+
chapters on VIC-II, SID, and I/O
|
|
981
|
+
- *The MOS 6567 / 6569 video controller (VIC-II) and its application
|
|
982
|
+
in the Commodore 64* — Christian Bauer, January 1996
|
|
983
|
+
([pagetable.com mirror](https://www.pagetable.com/?p=189))
|
|
984
|
+
- [pagetable.com c64ref](https://www.pagetable.com/c64ref/c64disasm/) —
|
|
985
|
+
annotated KERNAL & memory-map disassembly
|
|
986
|
+
|
|
987
|
+
Cross-checked against the per-chip references in this repository,
|
|
988
|
+
which carry the bit-level register detail this index intentionally
|
|
989
|
+
omits:
|
|
990
|
+
|
|
991
|
+
- [vic-ii-reference.md](vic-ii-reference.md)
|
|
992
|
+
- [sid-reference.md](sid-reference.md)
|
|
993
|
+
- [cia-reference.md](cia-reference.md)
|
|
994
|
+
- [c64-memory-map.md](c64-memory-map.md)
|
|
995
|
+
|
|
996
|
+
<!-- doc-type: hardware-reference -->
|