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.
Files changed (970) hide show
  1. package/CHANGELOG.md +2082 -0
  2. package/LICENSE +29 -0
  3. package/README.md +559 -0
  4. package/VERSION +25 -0
  5. package/dist/cli/setup.js +66 -0
  6. package/dist/cli/setup.js.map +1 -0
  7. package/dist/cli-memorize-audit.js +97 -0
  8. package/dist/cli-memorize-audit.js.map +1 -0
  9. package/dist/cli.js +335 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/config.js +83 -0
  12. package/dist/config.js.map +1 -0
  13. package/dist/context.js +53 -0
  14. package/dist/context.js.map +1 -0
  15. package/dist/domain/budget-notes.js +104 -0
  16. package/dist/domain/budget-notes.js.map +1 -0
  17. package/dist/domain/budget.js +417 -0
  18. package/dist/domain/budget.js.map +1 -0
  19. package/dist/domain/game-design.js +77 -0
  20. package/dist/domain/game-design.js.map +1 -0
  21. package/dist/domain/timing.js +39 -0
  22. package/dist/domain/timing.js.map +1 -0
  23. package/dist/graph/apply.js +132 -0
  24. package/dist/graph/apply.js.map +1 -0
  25. package/dist/graph/claims.js +231 -0
  26. package/dist/graph/claims.js.map +1 -0
  27. package/dist/graph/extract/archetype.js +118 -0
  28. package/dist/graph/extract/archetype.js.map +1 -0
  29. package/dist/graph/extract/common.js +69 -0
  30. package/dist/graph/extract/common.js.map +1 -0
  31. package/dist/graph/extract/failure.js +37 -0
  32. package/dist/graph/extract/failure.js.map +1 -0
  33. package/dist/graph/extract/game-design.js +189 -0
  34. package/dist/graph/extract/game-design.js.map +1 -0
  35. package/dist/graph/extract/hardware.js +124 -0
  36. package/dist/graph/extract/hardware.js.map +1 -0
  37. package/dist/graph/extract/pitfall.js +62 -0
  38. package/dist/graph/extract/pitfall.js.map +1 -0
  39. package/dist/graph/extract/raster-band.js +56 -0
  40. package/dist/graph/extract/raster-band.js.map +1 -0
  41. package/dist/graph/extract/recipe.js +71 -0
  42. package/dist/graph/extract/recipe.js.map +1 -0
  43. package/dist/graph/extract/technique-entities.js +180 -0
  44. package/dist/graph/extract/technique-entities.js.map +1 -0
  45. package/dist/graph/extract/technique.js +179 -0
  46. package/dist/graph/extract/technique.js.map +1 -0
  47. package/dist/graph/extract/toolchain.js +67 -0
  48. package/dist/graph/extract/toolchain.js.map +1 -0
  49. package/dist/graph/extract/types.js +3 -0
  50. package/dist/graph/extract/types.js.map +1 -0
  51. package/dist/graph/extract/vocabulary.js +65 -0
  52. package/dist/graph/extract/vocabulary.js.map +1 -0
  53. package/dist/graph/extract.js +43 -0
  54. package/dist/graph/extract.js.map +1 -0
  55. package/dist/graph/kernal-clobbers.js +64 -0
  56. package/dist/graph/kernal-clobbers.js.map +1 -0
  57. package/dist/graph/machine-variants.js +208 -0
  58. package/dist/graph/machine-variants.js.map +1 -0
  59. package/dist/ingest/files.js +99 -0
  60. package/dist/ingest/files.js.map +1 -0
  61. package/dist/ingest/passes.js +104 -0
  62. package/dist/ingest/passes.js.map +1 -0
  63. package/dist/ingest/points.js +50 -0
  64. package/dist/ingest/points.js.map +1 -0
  65. package/dist/ingest/report.js +140 -0
  66. package/dist/ingest/report.js.map +1 -0
  67. package/dist/ingest/tally.js +81 -0
  68. package/dist/ingest/tally.js.map +1 -0
  69. package/dist/ingest/verified-on.js +43 -0
  70. package/dist/ingest/verified-on.js.map +1 -0
  71. package/dist/ingest.js +135 -0
  72. package/dist/ingest.js.map +1 -0
  73. package/dist/schemas/cost-basis.js +5 -0
  74. package/dist/schemas/cost-basis.js.map +1 -0
  75. package/dist/schemas/machine-variant.js +25 -0
  76. package/dist/schemas/machine-variant.js.map +1 -0
  77. package/dist/schemas/plan-budget.js +121 -0
  78. package/dist/schemas/plan-budget.js.map +1 -0
  79. package/dist/schemas/tool-outputs.js +526 -0
  80. package/dist/schemas/tool-outputs.js.map +1 -0
  81. package/dist/server/define-tool.js +52 -0
  82. package/dist/server/define-tool.js.map +1 -0
  83. package/dist/server/defined-only.js +9 -0
  84. package/dist/server/defined-only.js.map +1 -0
  85. package/dist/server/tools-briefings.js +70 -0
  86. package/dist/server/tools-briefings.js.map +1 -0
  87. package/dist/server/tools-lookup.js +180 -0
  88. package/dist/server/tools-lookup.js.map +1 -0
  89. package/dist/server/tools-maintenance.js +116 -0
  90. package/dist/server/tools-maintenance.js.map +1 -0
  91. package/dist/server/tools-pitfalls.js +89 -0
  92. package/dist/server/tools-pitfalls.js.map +1 -0
  93. package/dist/server/tools-recipes.js +296 -0
  94. package/dist/server/tools-recipes.js.map +1 -0
  95. package/dist/server/tools-runtime.js +48 -0
  96. package/dist/server/tools-runtime.js.map +1 -0
  97. package/dist/server/tools.js +43 -0
  98. package/dist/server/tools.js.map +1 -0
  99. package/dist/server.js +95 -0
  100. package/dist/server.js.map +1 -0
  101. package/dist/services/analytics/schema.js +78 -0
  102. package/dist/services/analytics/schema.js.map +1 -0
  103. package/dist/services/analytics/statements.js +99 -0
  104. package/dist/services/analytics/statements.js.map +1 -0
  105. package/dist/services/analytics.js +195 -0
  106. package/dist/services/analytics.js.map +1 -0
  107. package/dist/services/bm25.js +158 -0
  108. package/dist/services/bm25.js.map +1 -0
  109. package/dist/services/chunker.js +81 -0
  110. package/dist/services/chunker.js.map +1 -0
  111. package/dist/services/embeddings.js +58 -0
  112. package/dist/services/embeddings.js.map +1 -0
  113. package/dist/services/falkor/base.js +85 -0
  114. package/dist/services/falkor/base.js.map +1 -0
  115. package/dist/services/falkor/links.js +361 -0
  116. package/dist/services/falkor/links.js.map +1 -0
  117. package/dist/services/falkor/nodes.js +183 -0
  118. package/dist/services/falkor/nodes.js.map +1 -0
  119. package/dist/services/falkor/params.js +45 -0
  120. package/dist/services/falkor/params.js.map +1 -0
  121. package/dist/services/falkor/schema.js +77 -0
  122. package/dist/services/falkor/schema.js.map +1 -0
  123. package/dist/services/falkor.js +100 -0
  124. package/dist/services/falkor.js.map +1 -0
  125. package/dist/services/qdrant.js +238 -0
  126. package/dist/services/qdrant.js.map +1 -0
  127. package/dist/services/versions.js +73 -0
  128. package/dist/services/versions.js.map +1 -0
  129. package/dist/services/vice-bin.js +51 -0
  130. package/dist/services/vice-bin.js.map +1 -0
  131. package/dist/tools/briefings/archetype.js +174 -0
  132. package/dist/tools/briefings/archetype.js.map +1 -0
  133. package/dist/tools/briefings/budget.js +177 -0
  134. package/dist/tools/briefings/budget.js.map +1 -0
  135. package/dist/tools/briefings/build-order.js +135 -0
  136. package/dist/tools/briefings/build-order.js.map +1 -0
  137. package/dist/tools/briefings/build.js +185 -0
  138. package/dist/tools/briefings/build.js.map +1 -0
  139. package/dist/tools/briefings/discovery.js +290 -0
  140. package/dist/tools/briefings/discovery.js.map +1 -0
  141. package/dist/tools/briefings/plan-pitfalls.js +69 -0
  142. package/dist/tools/briefings/plan-pitfalls.js.map +1 -0
  143. package/dist/tools/briefings/render.js +151 -0
  144. package/dist/tools/briefings/render.js.map +1 -0
  145. package/dist/tools/briefings/rows.js +41 -0
  146. package/dist/tools/briefings/rows.js.map +1 -0
  147. package/dist/tools/briefings/toolchain.js +63 -0
  148. package/dist/tools/briefings/toolchain.js.map +1 -0
  149. package/dist/tools/briefings/why-proposed.js +69 -0
  150. package/dist/tools/briefings/why-proposed.js.map +1 -0
  151. package/dist/tools/briefings.js +44 -0
  152. package/dist/tools/briefings.js.map +1 -0
  153. package/dist/tools/feedback.js +97 -0
  154. package/dist/tools/feedback.js.map +1 -0
  155. package/dist/tools/hydrate.js +75 -0
  156. package/dist/tools/hydrate.js.map +1 -0
  157. package/dist/tools/intelligence.js +67 -0
  158. package/dist/tools/intelligence.js.map +1 -0
  159. package/dist/tools/lint/asm-decimal.js +86 -0
  160. package/dist/tools/lint/asm-decimal.js.map +1 -0
  161. package/dist/tools/lint/asm-rules.js +221 -0
  162. package/dist/tools/lint/asm-rules.js.map +1 -0
  163. package/dist/tools/lint/asm-shared.js +3 -0
  164. package/dist/tools/lint/asm-shared.js.map +1 -0
  165. package/dist/tools/lint/c-rules.js +215 -0
  166. package/dist/tools/lint/c-rules.js.map +1 -0
  167. package/dist/tools/lint/text.js +122 -0
  168. package/dist/tools/lint/text.js.map +1 -0
  169. package/dist/tools/lint/types.js +40 -0
  170. package/dist/tools/lint/types.js.map +1 -0
  171. package/dist/tools/lint.js +76 -0
  172. package/dist/tools/lint.js.map +1 -0
  173. package/dist/tools/memorization-mcp.js +111 -0
  174. package/dist/tools/memorization-mcp.js.map +1 -0
  175. package/dist/tools/pitfalls/bm25.js +53 -0
  176. package/dist/tools/pitfalls/bm25.js.map +1 -0
  177. package/dist/tools/pitfalls/format.js +58 -0
  178. package/dist/tools/pitfalls/format.js.map +1 -0
  179. package/dist/tools/pitfalls/graph.js +124 -0
  180. package/dist/tools/pitfalls/graph.js.map +1 -0
  181. package/dist/tools/pitfalls.js +134 -0
  182. package/dist/tools/pitfalls.js.map +1 -0
  183. package/dist/tools/prompts.js +81 -0
  184. package/dist/tools/prompts.js.map +1 -0
  185. package/dist/tools/query/compatibility/closure.js +62 -0
  186. package/dist/tools/query/compatibility/closure.js.map +1 -0
  187. package/dist/tools/query/compatibility/facts.js +28 -0
  188. package/dist/tools/query/compatibility/facts.js.map +1 -0
  189. package/dist/tools/query/compatibility/fetch.js +164 -0
  190. package/dist/tools/query/compatibility/fetch.js.map +1 -0
  191. package/dist/tools/query/compatibility/hard-rules.js +159 -0
  192. package/dist/tools/query/compatibility/hard-rules.js.map +1 -0
  193. package/dist/tools/query/compatibility/index.js +27 -0
  194. package/dist/tools/query/compatibility/index.js.map +1 -0
  195. package/dist/tools/query/compatibility/kernal-zp-rule.js +90 -0
  196. package/dist/tools/query/compatibility/kernal-zp-rule.js.map +1 -0
  197. package/dist/tools/query/compatibility/render.js +106 -0
  198. package/dist/tools/query/compatibility/render.js.map +1 -0
  199. package/dist/tools/query/compatibility/rules.js +337 -0
  200. package/dist/tools/query/compatibility/rules.js.map +1 -0
  201. package/dist/tools/query/compatibility/unit-rules.js +253 -0
  202. package/dist/tools/query/compatibility/unit-rules.js.map +1 -0
  203. package/dist/tools/query/game-design.js +83 -0
  204. package/dist/tools/query/game-design.js.map +1 -0
  205. package/dist/tools/query/lookups.js +220 -0
  206. package/dist/tools/query/lookups.js.map +1 -0
  207. package/dist/tools/query/plan-budget.js +266 -0
  208. package/dist/tools/query/plan-budget.js.map +1 -0
  209. package/dist/tools/query/recipes.js +214 -0
  210. package/dist/tools/query/recipes.js.map +1 -0
  211. package/dist/tools/query/retrieval.js +128 -0
  212. package/dist/tools/query/retrieval.js.map +1 -0
  213. package/dist/tools/query/shared.js +121 -0
  214. package/dist/tools/query/shared.js.map +1 -0
  215. package/dist/tools/query/techniques.js +331 -0
  216. package/dist/tools/query/techniques.js.map +1 -0
  217. package/dist/tools/query/timing.js +106 -0
  218. package/dist/tools/query/timing.js.map +1 -0
  219. package/dist/tools/query/types.js +11 -0
  220. package/dist/tools/query/types.js.map +1 -0
  221. package/dist/tools/query.js +21 -0
  222. package/dist/tools/query.js.map +1 -0
  223. package/dist/tools/resources.js +186 -0
  224. package/dist/tools/resources.js.map +1 -0
  225. package/dist/tools/run-game.js +249 -0
  226. package/dist/tools/run-game.js.map +1 -0
  227. package/dist/tools/selfimprovement.js +367 -0
  228. package/dist/tools/selfimprovement.js.map +1 -0
  229. package/docker-compose.yml +35 -0
  230. package/docs/ARCHITECTURE.md +164 -0
  231. package/docs/CONVENTIONS-archetypes.md +158 -0
  232. package/docs/CONVENTIONS-failures.md +46 -0
  233. package/docs/CONVENTIONS-game-designs.md +75 -0
  234. package/docs/CONVENTIONS-hardware-reference.md +184 -0
  235. package/docs/CONVENTIONS-pitfalls.md +91 -0
  236. package/docs/CONVENTIONS-recipes.md +106 -0
  237. package/docs/CONVENTIONS-techniques.md +309 -0
  238. package/docs/CONVENTIONS-toolchain-reference.md +89 -0
  239. package/docs/ONTOLOGY.md +655 -0
  240. package/docs/art/art-production-reference.md +157 -0
  241. package/docs/art/asset-pipelines.md +586 -0
  242. package/docs/c64-failure-patterns.md +693 -0
  243. package/docs/demo-design/demo-composition.md +349 -0
  244. package/docs/demo-design/demo-design-philosophy.md +320 -0
  245. package/docs/demo-design/intro-cracktro-patterns.md +435 -0
  246. package/docs/figures/ctm-spd-embed-probe.png +0 -0
  247. package/docs/figures/dot-flag-mid-5000000.png +0 -0
  248. package/docs/figures/dot-flag-no-erase-12000000.png +0 -0
  249. package/docs/figures/edges.json +1 -0
  250. package/docs/figures/fig6-architecture.png +0 -0
  251. package/docs/figures/fig7-ontology.png +0 -0
  252. package/docs/figures/screen-dissolve-mid-frame25.png +0 -0
  253. package/docs/figures/screen-dissolve-wipe-frame25.png +0 -0
  254. package/docs/figures/spindle-two-parts-part1.png +0 -0
  255. package/docs/figures/spindle-two-parts-part2.png +0 -0
  256. package/docs/figures/starters/action-puzzle.png +0 -0
  257. package/docs/figures/starters/adventure.png +0 -0
  258. package/docs/figures/starters/beat-em-up.png +0 -0
  259. package/docs/figures/starters/demo.png +0 -0
  260. package/docs/figures/starters/platformer.png +0 -0
  261. package/docs/figures/starters/shmup-vertical.png +0 -0
  262. package/docs/figures/tape-kernal-master-ntsc.png +0 -0
  263. package/docs/figures/tape-kernal-master-pal.png +0 -0
  264. package/docs/figures/tape-turbo-loader-ntsc.png +0 -0
  265. package/docs/figures/tape-turbo-loader-pal.png +0 -0
  266. package/docs/figures/tape-turbo-master-ntsc.png +0 -0
  267. package/docs/figures/tape-turbo-master-pal.png +0 -0
  268. package/docs/figures/tech-tech-pad2-12000000.png +0 -0
  269. package/docs/figures/tech-tech-pad4-12000000.png +0 -0
  270. package/docs/figures/tech-tech-seven-12000000.png +0 -0
  271. package/docs/figures/twister-mid-5000000.png +0 -0
  272. package/docs/figures/twister-straight-12000000.png +0 -0
  273. package/docs/figures/vector-balls-nosort-ntsc.png +0 -0
  274. package/docs/figures/vector-balls-nosort.png +0 -0
  275. package/docs/formats/c64-file-formats.md +1212 -0
  276. package/docs/formats/iec-disk-reference.md +754 -0
  277. package/docs/game-design/c64-game-archetypes.md +273 -0
  278. package/docs/game-design/designs/falling-blocks.md +54 -0
  279. package/docs/game-design/designs/platformer-scaffold.md +48 -0
  280. package/docs/game-design/designs/simple-shmup.md +27 -0
  281. package/docs/game-design/enemy-behaviour-and-difficulty.md +349 -0
  282. package/docs/game-design/game-design-patterns.md +1189 -0
  283. package/docs/game-design/game-structure.md +354 -0
  284. package/docs/game-design/production-planning.md +349 -0
  285. package/docs/game-design/reference-game-sources.md +90 -0
  286. package/docs/hardware/6502-illegal-opcodes.md +1353 -0
  287. package/docs/hardware/6510-cpu-reference.md +2112 -0
  288. package/docs/hardware/c64-memory-map.md +3184 -0
  289. package/docs/hardware/c64-registers-reference.md +996 -0
  290. package/docs/hardware/cia-reference.md +1281 -0
  291. package/docs/hardware/kernal-routines-reference.md +1836 -0
  292. package/docs/hardware/pal-ntsc-reference.md +813 -0
  293. package/docs/hardware/sid-reference.md +1137 -0
  294. package/docs/hardware/vic-ii-reference.md +1714 -0
  295. package/docs/music/music-production-reference.md +403 -0
  296. package/docs/pitfalls/banking.md +1067 -0
  297. package/docs/pitfalls/cia.md +1147 -0
  298. package/docs/pitfalls/cpu.md +874 -0
  299. package/docs/pitfalls/input.md +282 -0
  300. package/docs/pitfalls/kernal-and-io.md +1615 -0
  301. package/docs/pitfalls/loader.md +1191 -0
  302. package/docs/pitfalls/logic.md +94 -0
  303. package/docs/pitfalls/maths.md +187 -0
  304. package/docs/pitfalls/raster-and-badline.md +721 -0
  305. package/docs/pitfalls/region-timing.md +660 -0
  306. package/docs/pitfalls/scroll.md +207 -0
  307. package/docs/pitfalls/sid.md +738 -0
  308. package/docs/pitfalls/sprite.md +979 -0
  309. package/docs/pitfalls/text-mode-render.md +1172 -0
  310. package/docs/recipes/cc65/cartridge-8k.md +398 -0
  311. package/docs/recipes/cc65/hello-world-conio.md +76 -0
  312. package/docs/recipes/cc65/memory-layout.md +312 -0
  313. package/docs/recipes/cc65/screenshots/README.md +14 -0
  314. package/docs/recipes/cc65/screenshots/cartridge-8k-ntsc.png +0 -0
  315. package/docs/recipes/cc65/screenshots/cartridge-8k.png +0 -0
  316. package/docs/recipes/cc65/screenshots/hello-world-conio.png +0 -0
  317. package/docs/recipes/cc65/screenshots/memory-layout-ntsc.png +0 -0
  318. package/docs/recipes/cc65/screenshots/memory-layout.png +0 -0
  319. package/docs/recipes/kickassembler/basic-float-calls.md +578 -0
  320. package/docs/recipes/kickassembler/basic-wedge.md +398 -0
  321. package/docs/recipes/kickassembler/big-font-scroller.md +620 -0
  322. package/docs/recipes/kickassembler/charset-copy-rom-to-ram.md +623 -0
  323. package/docs/recipes/kickassembler/cia-revision-detect.md +366 -0
  324. package/docs/recipes/kickassembler/colour-cycling.md +343 -0
  325. package/docs/recipes/kickassembler/colour-fade.md +303 -0
  326. package/docs/recipes/kickassembler/compare-16bit-signed.md +1007 -0
  327. package/docs/recipes/kickassembler/cracktro-template.md +526 -0
  328. package/docs/recipes/kickassembler/crt-banked.md +276 -0
  329. package/docs/recipes/kickassembler/dos-error-codes.md +466 -0
  330. package/docs/recipes/kickassembler/dot-flag.md +576 -0
  331. package/docs/recipes/kickassembler/drive-job-queue.md +667 -0
  332. package/docs/recipes/kickassembler/drive-via-probe.md +690 -0
  333. package/docs/recipes/kickassembler/dycp-scroller.md +568 -0
  334. package/docs/recipes/kickassembler/dypp-sprite-scroller.md +681 -0
  335. package/docs/recipes/kickassembler/dysp.md +670 -0
  336. package/docs/recipes/kickassembler/easyflash-save.md +800 -0
  337. package/docs/recipes/kickassembler/eight-way-scroll.md +1484 -0
  338. package/docs/recipes/kickassembler/file-io-roundtrip.md +546 -0
  339. package/docs/recipes/kickassembler/fire-effect.md +420 -0
  340. package/docs/recipes/kickassembler/fld.md +414 -0
  341. package/docs/recipes/kickassembler/fli-image.md +336 -0
  342. package/docs/recipes/kickassembler/four-player-read.md +672 -0
  343. package/docs/recipes/kickassembler/headless-verify.md +228 -0
  344. package/docs/recipes/kickassembler/hello-world.md +98 -0
  345. package/docs/recipes/kickassembler/high-score-insert.md +660 -0
  346. package/docs/recipes/kickassembler/hires-plot-line.md +723 -0
  347. package/docs/recipes/kickassembler/irq-chain.md +316 -0
  348. package/docs/recipes/kickassembler/irq-owns-port.md +668 -0
  349. package/docs/recipes/kickassembler/isometric-room.md +1145 -0
  350. package/docs/recipes/kickassembler/light-pen-read.md +926 -0
  351. package/docs/recipes/kickassembler/logic-rate-decoupling.md +670 -0
  352. package/docs/recipes/kickassembler/mci-interlace.md +543 -0
  353. package/docs/recipes/kickassembler/memory-layout.md +277 -0
  354. package/docs/recipes/kickassembler/mouse-1351-read.md +801 -0
  355. package/docs/recipes/kickassembler/nmi-timer-tick.md +562 -0
  356. package/docs/recipes/kickassembler/own-keyscan.md +881 -0
  357. package/docs/recipes/kickassembler/paddle-read.md +751 -0
  358. package/docs/recipes/kickassembler/palette-cells.md +219 -0
  359. package/docs/recipes/kickassembler/pseudo-3d-road.md +930 -0
  360. package/docs/recipes/kickassembler/pwm-digi.md +463 -0
  361. package/docs/recipes/kickassembler/raster-bars.md +264 -0
  362. package/docs/recipes/kickassembler/reu-dma.md +1019 -0
  363. package/docs/recipes/kickassembler/runtime-relocation.md +743 -0
  364. package/docs/recipes/kickassembler/screen-dissolve.md +545 -0
  365. package/docs/recipes/kickassembler/screen-wipe.md +408 -0
  366. package/docs/recipes/kickassembler/screenshots/README.md +72 -0
  367. package/docs/recipes/kickassembler/screenshots/basic-float-calls-ntsc.png +0 -0
  368. package/docs/recipes/kickassembler/screenshots/basic-float-calls.png +0 -0
  369. package/docs/recipes/kickassembler/screenshots/basic-wedge-ntsc.png +0 -0
  370. package/docs/recipes/kickassembler/screenshots/basic-wedge.png +0 -0
  371. package/docs/recipes/kickassembler/screenshots/big-font-scroller-ntsc.png +0 -0
  372. package/docs/recipes/kickassembler/screenshots/big-font-scroller.png +0 -0
  373. package/docs/recipes/kickassembler/screenshots/charset-copy-rom-to-ram-ntsc.png +0 -0
  374. package/docs/recipes/kickassembler/screenshots/charset-copy-rom-to-ram.png +0 -0
  375. package/docs/recipes/kickassembler/screenshots/cia-revision-detect-ntsc.png +0 -0
  376. package/docs/recipes/kickassembler/screenshots/cia-revision-detect.png +0 -0
  377. package/docs/recipes/kickassembler/screenshots/colour-cycling-ntsc.png +0 -0
  378. package/docs/recipes/kickassembler/screenshots/colour-cycling.png +0 -0
  379. package/docs/recipes/kickassembler/screenshots/colour-fade-ntsc.png +0 -0
  380. package/docs/recipes/kickassembler/screenshots/colour-fade.png +0 -0
  381. package/docs/recipes/kickassembler/screenshots/compare-16bit-signed-ntsc.png +0 -0
  382. package/docs/recipes/kickassembler/screenshots/compare-16bit-signed.png +0 -0
  383. package/docs/recipes/kickassembler/screenshots/cracktro-template.png +0 -0
  384. package/docs/recipes/kickassembler/screenshots/crt-banked-ntsc.png +0 -0
  385. package/docs/recipes/kickassembler/screenshots/crt-banked.png +0 -0
  386. package/docs/recipes/kickassembler/screenshots/dos-error-codes-ntsc.png +0 -0
  387. package/docs/recipes/kickassembler/screenshots/dos-error-codes.png +0 -0
  388. package/docs/recipes/kickassembler/screenshots/dot-flag-ntsc.png +0 -0
  389. package/docs/recipes/kickassembler/screenshots/dot-flag.png +0 -0
  390. package/docs/recipes/kickassembler/screenshots/drive-job-queue-ntsc.png +0 -0
  391. package/docs/recipes/kickassembler/screenshots/drive-job-queue.png +0 -0
  392. package/docs/recipes/kickassembler/screenshots/drive-via-probe-ntsc.png +0 -0
  393. package/docs/recipes/kickassembler/screenshots/drive-via-probe.png +0 -0
  394. package/docs/recipes/kickassembler/screenshots/dycp-scroller-ntsc.png +0 -0
  395. package/docs/recipes/kickassembler/screenshots/dycp-scroller.png +0 -0
  396. package/docs/recipes/kickassembler/screenshots/dypp-sprite-scroller-ntsc.png +0 -0
  397. package/docs/recipes/kickassembler/screenshots/dypp-sprite-scroller.png +0 -0
  398. package/docs/recipes/kickassembler/screenshots/dysp-ntsc.png +0 -0
  399. package/docs/recipes/kickassembler/screenshots/dysp.png +0 -0
  400. package/docs/recipes/kickassembler/screenshots/easyflash-save-ntsc-run2.png +0 -0
  401. package/docs/recipes/kickassembler/screenshots/easyflash-save-ntsc.png +0 -0
  402. package/docs/recipes/kickassembler/screenshots/easyflash-save-run2.png +0 -0
  403. package/docs/recipes/kickassembler/screenshots/easyflash-save.png +0 -0
  404. package/docs/recipes/kickassembler/screenshots/eight-way-scroll-ntsc.png +0 -0
  405. package/docs/recipes/kickassembler/screenshots/eight-way-scroll.png +0 -0
  406. package/docs/recipes/kickassembler/screenshots/file-io-roundtrip-ntsc.png +0 -0
  407. package/docs/recipes/kickassembler/screenshots/file-io-roundtrip.png +0 -0
  408. package/docs/recipes/kickassembler/screenshots/fire-effect-ntsc.png +0 -0
  409. package/docs/recipes/kickassembler/screenshots/fire-effect.png +0 -0
  410. package/docs/recipes/kickassembler/screenshots/fld-ntsc.png +0 -0
  411. package/docs/recipes/kickassembler/screenshots/fld.png +0 -0
  412. package/docs/recipes/kickassembler/screenshots/fli-image.png +0 -0
  413. package/docs/recipes/kickassembler/screenshots/four-player-read-ntsc.png +0 -0
  414. package/docs/recipes/kickassembler/screenshots/four-player-read.png +0 -0
  415. package/docs/recipes/kickassembler/screenshots/headless-verify-ntsc.png +0 -0
  416. package/docs/recipes/kickassembler/screenshots/headless-verify.png +0 -0
  417. package/docs/recipes/kickassembler/screenshots/hello-world.png +0 -0
  418. package/docs/recipes/kickassembler/screenshots/high-score-insert-ntsc.png +0 -0
  419. package/docs/recipes/kickassembler/screenshots/high-score-insert.png +0 -0
  420. package/docs/recipes/kickassembler/screenshots/hires-plot-line-ntsc.png +0 -0
  421. package/docs/recipes/kickassembler/screenshots/hires-plot-line.png +0 -0
  422. package/docs/recipes/kickassembler/screenshots/irq-chain-ntsc.png +0 -0
  423. package/docs/recipes/kickassembler/screenshots/irq-chain.png +0 -0
  424. package/docs/recipes/kickassembler/screenshots/irq-owns-port-ntsc.png +0 -0
  425. package/docs/recipes/kickassembler/screenshots/irq-owns-port.png +0 -0
  426. package/docs/recipes/kickassembler/screenshots/isometric-room-ntsc.png +0 -0
  427. package/docs/recipes/kickassembler/screenshots/isometric-room.png +0 -0
  428. package/docs/recipes/kickassembler/screenshots/light-pen-read-ntsc.png +0 -0
  429. package/docs/recipes/kickassembler/screenshots/light-pen-read.png +0 -0
  430. package/docs/recipes/kickassembler/screenshots/logic-rate-decoupling-ntsc.png +0 -0
  431. package/docs/recipes/kickassembler/screenshots/logic-rate-decoupling.png +0 -0
  432. package/docs/recipes/kickassembler/screenshots/mci-interlace-average.png +0 -0
  433. package/docs/recipes/kickassembler/screenshots/mci-interlace-frame-b.png +0 -0
  434. package/docs/recipes/kickassembler/screenshots/mci-interlace-ntsc.png +0 -0
  435. package/docs/recipes/kickassembler/screenshots/mci-interlace.png +0 -0
  436. package/docs/recipes/kickassembler/screenshots/memory-layout-ntsc.png +0 -0
  437. package/docs/recipes/kickassembler/screenshots/memory-layout.png +0 -0
  438. package/docs/recipes/kickassembler/screenshots/mouse-1351-read-ntsc.png +0 -0
  439. package/docs/recipes/kickassembler/screenshots/mouse-1351-read.png +0 -0
  440. package/docs/recipes/kickassembler/screenshots/nmi-timer-tick-ntsc.png +0 -0
  441. package/docs/recipes/kickassembler/screenshots/nmi-timer-tick.png +0 -0
  442. package/docs/recipes/kickassembler/screenshots/own-keyscan-ntsc.png +0 -0
  443. package/docs/recipes/kickassembler/screenshots/own-keyscan.png +0 -0
  444. package/docs/recipes/kickassembler/screenshots/paddle-read-ntsc.png +0 -0
  445. package/docs/recipes/kickassembler/screenshots/paddle-read.png +0 -0
  446. package/docs/recipes/kickassembler/screenshots/palette-cells-ntsc.png +0 -0
  447. package/docs/recipes/kickassembler/screenshots/palette-cells.png +0 -0
  448. package/docs/recipes/kickassembler/screenshots/pseudo-3d-road-ntsc.png +0 -0
  449. package/docs/recipes/kickassembler/screenshots/pseudo-3d-road.png +0 -0
  450. package/docs/recipes/kickassembler/screenshots/pwm-digi-ntsc.png +0 -0
  451. package/docs/recipes/kickassembler/screenshots/pwm-digi.png +0 -0
  452. package/docs/recipes/kickassembler/screenshots/raster-bars.png +0 -0
  453. package/docs/recipes/kickassembler/screenshots/reu-dma-ntsc.png +0 -0
  454. package/docs/recipes/kickassembler/screenshots/reu-dma.png +0 -0
  455. package/docs/recipes/kickassembler/screenshots/runtime-relocation-ntsc.png +0 -0
  456. package/docs/recipes/kickassembler/screenshots/runtime-relocation.png +0 -0
  457. package/docs/recipes/kickassembler/screenshots/screen-dissolve-ntsc.png +0 -0
  458. package/docs/recipes/kickassembler/screenshots/screen-dissolve.png +0 -0
  459. package/docs/recipes/kickassembler/screenshots/screen-wipe-ntsc.png +0 -0
  460. package/docs/recipes/kickassembler/screenshots/screen-wipe.png +0 -0
  461. package/docs/recipes/kickassembler/screenshots/scroll-panel-split-ntsc.png +0 -0
  462. package/docs/recipes/kickassembler/screenshots/scroll-panel-split.png +0 -0
  463. package/docs/recipes/kickassembler/screenshots/sfx-in-player-ntsc.png +0 -0
  464. package/docs/recipes/kickassembler/screenshots/sfx-in-player.png +0 -0
  465. package/docs/recipes/kickassembler/screenshots/shadebobs-ntsc.png +0 -0
  466. package/docs/recipes/kickassembler/screenshots/shadebobs.png +0 -0
  467. package/docs/recipes/kickassembler/screenshots/sideborder-open.png +0 -0
  468. package/docs/recipes/kickassembler/screenshots/sine-scroller.png +0 -0
  469. package/docs/recipes/kickassembler/screenshots/sine-table-runtime-ntsc.png +0 -0
  470. package/docs/recipes/kickassembler/screenshots/sine-table-runtime.png +0 -0
  471. package/docs/recipes/kickassembler/screenshots/software-sprite-preshifted-ntsc.png +0 -0
  472. package/docs/recipes/kickassembler/screenshots/software-sprite-preshifted.png +0 -0
  473. package/docs/recipes/kickassembler/screenshots/speedcode-generator-ntsc.png +0 -0
  474. package/docs/recipes/kickassembler/screenshots/speedcode-generator.png +0 -0
  475. package/docs/recipes/kickassembler/screenshots/sprite-border-scroller-ntsc.png +0 -0
  476. package/docs/recipes/kickassembler/screenshots/sprite-border-scroller.png +0 -0
  477. package/docs/recipes/kickassembler/screenshots/sprite-cache-flip-ntsc.png +0 -0
  478. package/docs/recipes/kickassembler/screenshots/sprite-cache-flip.png +0 -0
  479. package/docs/recipes/kickassembler/screenshots/sprite-multiplex-24.png +0 -0
  480. package/docs/recipes/kickassembler/screenshots/sprite-multiplex-game-ntsc.png +0 -0
  481. package/docs/recipes/kickassembler/screenshots/sprite-multiplex-game.png +0 -0
  482. package/docs/recipes/kickassembler/screenshots/sprite-priority-classes-ntsc.png +0 -0
  483. package/docs/recipes/kickassembler/screenshots/sprite-priority-classes.png +0 -0
  484. package/docs/recipes/kickassembler/screenshots/sprite-sine-chain-ntsc.png +0 -0
  485. package/docs/recipes/kickassembler/screenshots/sprite-sine-chain.png +0 -0
  486. package/docs/recipes/kickassembler/screenshots/sprite-stretcher-ntsc.png +0 -0
  487. package/docs/recipes/kickassembler/screenshots/sprite-stretcher.png +0 -0
  488. package/docs/recipes/kickassembler/screenshots/sprites-only-screen-ntsc.png +0 -0
  489. package/docs/recipes/kickassembler/screenshots/sprites-only-screen.png +0 -0
  490. package/docs/recipes/kickassembler/screenshots/sqrt-atan2-ntsc.png +0 -0
  491. package/docs/recipes/kickassembler/screenshots/sqrt-atan2.png +0 -0
  492. package/docs/recipes/kickassembler/screenshots/stable-raster-irq-control.png +0 -0
  493. package/docs/recipes/kickassembler/screenshots/stable-raster-irq.png +0 -0
  494. package/docs/recipes/kickassembler/screenshots/tech-tech-ntsc.png +0 -0
  495. package/docs/recipes/kickassembler/screenshots/tech-tech.png +0 -0
  496. package/docs/recipes/kickassembler/screenshots/tod-alarm-ntsc.png +0 -0
  497. package/docs/recipes/kickassembler/screenshots/tod-alarm.png +0 -0
  498. package/docs/recipes/kickassembler/screenshots/topbottom-border-open.png +0 -0
  499. package/docs/recipes/kickassembler/screenshots/twister-ntsc.png +0 -0
  500. package/docs/recipes/kickassembler/screenshots/twister.png +0 -0
  501. package/docs/recipes/kickassembler/screenshots/unit-test-driver-ntsc.png +0 -0
  502. package/docs/recipes/kickassembler/screenshots/unit-test-driver.png +0 -0
  503. package/docs/recipes/kickassembler/screenshots/vector-balls-ntsc.png +0 -0
  504. package/docs/recipes/kickassembler/screenshots/vector-balls.png +0 -0
  505. package/docs/recipes/kickassembler/screenshots/wireframe-ships-ntsc.png +0 -0
  506. package/docs/recipes/kickassembler/screenshots/wireframe-ships.png +0 -0
  507. package/docs/recipes/kickassembler/scroll-panel-split.md +381 -0
  508. package/docs/recipes/kickassembler/sfx-in-player.md +907 -0
  509. package/docs/recipes/kickassembler/shadebobs.md +522 -0
  510. package/docs/recipes/kickassembler/sideborder-open.md +338 -0
  511. package/docs/recipes/kickassembler/sine-scroller.md +321 -0
  512. package/docs/recipes/kickassembler/sine-table-runtime.md +815 -0
  513. package/docs/recipes/kickassembler/software-sprite-preshifted.md +725 -0
  514. package/docs/recipes/kickassembler/speedcode-generator.md +606 -0
  515. package/docs/recipes/kickassembler/sprite-border-scroller.md +696 -0
  516. package/docs/recipes/kickassembler/sprite-cache-flip.md +1071 -0
  517. package/docs/recipes/kickassembler/sprite-multiplex-24.md +326 -0
  518. package/docs/recipes/kickassembler/sprite-multiplex-game.md +986 -0
  519. package/docs/recipes/kickassembler/sprite-priority-classes.md +463 -0
  520. package/docs/recipes/kickassembler/sprite-sine-chain.md +338 -0
  521. package/docs/recipes/kickassembler/sprite-stretcher.md +501 -0
  522. package/docs/recipes/kickassembler/sprites-only-screen.md +550 -0
  523. package/docs/recipes/kickassembler/sqrt-atan2.md +1014 -0
  524. package/docs/recipes/kickassembler/stable-raster-irq.md +360 -0
  525. package/docs/recipes/kickassembler/tape-turbo-loader.md +875 -0
  526. package/docs/recipes/kickassembler/tech-tech.md +679 -0
  527. package/docs/recipes/kickassembler/tod-alarm.md +754 -0
  528. package/docs/recipes/kickassembler/topbottom-border-open.md +407 -0
  529. package/docs/recipes/kickassembler/twister.md +518 -0
  530. package/docs/recipes/kickassembler/unit-test-driver.md +314 -0
  531. package/docs/recipes/kickassembler/vector-balls.md +545 -0
  532. package/docs/recipes/kickassembler/wireframe-ships.md +2324 -0
  533. package/docs/recipes/oscar64/actor-activation-window.md +807 -0
  534. package/docs/recipes/oscar64/adventure-engine.md +1094 -0
  535. package/docs/recipes/oscar64/attract-replay.md +465 -0
  536. package/docs/recipes/oscar64/beat-em-up-lanes.md +563 -0
  537. package/docs/recipes/oscar64/bfs-distance-map.md +723 -0
  538. package/docs/recipes/oscar64/bitmap-koala-viewer.md +355 -0
  539. package/docs/recipes/oscar64/car-contact.md +950 -0
  540. package/docs/recipes/oscar64/cave-scan.md +609 -0
  541. package/docs/recipes/oscar64/char-bullets.md +477 -0
  542. package/docs/recipes/oscar64/charset-animation.md +383 -0
  543. package/docs/recipes/oscar64/charset-parallax.md +401 -0
  544. package/docs/recipes/oscar64/destructible-terrain.md +1099 -0
  545. package/docs/recipes/oscar64/difficulty-tables.md +654 -0
  546. package/docs/recipes/oscar64/dig-and-guards.md +975 -0
  547. package/docs/recipes/oscar64/directory-reader.md +535 -0
  548. package/docs/recipes/oscar64/divide-check.md +581 -0
  549. package/docs/recipes/oscar64/double-buffer-nomirror.md +205 -0
  550. package/docs/recipes/oscar64/double-buffer.md +255 -0
  551. package/docs/recipes/oscar64/falling-blocks.md +874 -0
  552. package/docs/recipes/oscar64/fixed-point-jump-velocity.md +289 -0
  553. package/docs/recipes/oscar64/fixed-point-jump.md +210 -0
  554. package/docs/recipes/oscar64/flip-screen-rooms.md +793 -0
  555. package/docs/recipes/oscar64/frame-sync-loop-overrun.md +214 -0
  556. package/docs/recipes/oscar64/frame-sync-loop.md +254 -0
  557. package/docs/recipes/oscar64/game-tree-search.md +743 -0
  558. package/docs/recipes/oscar64/ghost-targeting.md +867 -0
  559. package/docs/recipes/oscar64/headless-verify.md +345 -0
  560. package/docs/recipes/oscar64/hello-world.md +83 -0
  561. package/docs/recipes/oscar64/high-score-persist.md +772 -0
  562. package/docs/recipes/oscar64/iffl-kernal-skip.md +421 -0
  563. package/docs/recipes/oscar64/joystick-input.md +358 -0
  564. package/docs/recipes/oscar64/lane-pursuit.md +1028 -0
  565. package/docs/recipes/oscar64/level-rle-decoder.md +620 -0
  566. package/docs/recipes/oscar64/lfsr-random-seed2.md +338 -0
  567. package/docs/recipes/oscar64/lfsr-random.md +403 -0
  568. package/docs/recipes/oscar64/load-asset-runtime.md +492 -0
  569. package/docs/recipes/oscar64/memory-layout.md +232 -0
  570. package/docs/recipes/oscar64/mixed-fighters.md +781 -0
  571. package/docs/recipes/oscar64/multi-sprite-object.md +533 -0
  572. package/docs/recipes/oscar64/nav-area-pathfinding.md +881 -0
  573. package/docs/recipes/oscar64/object-pool.md +572 -0
  574. package/docs/recipes/oscar64/pal-ntsc-detect.md +257 -0
  575. package/docs/recipes/oscar64/password-state.md +532 -0
  576. package/docs/recipes/oscar64/per-frame-hitbox.md +651 -0
  577. package/docs/recipes/oscar64/petscii-screen-codes.md +428 -0
  578. package/docs/recipes/oscar64/platformer-scaffold.md +1467 -0
  579. package/docs/recipes/oscar64/print-number.md +367 -0
  580. package/docs/recipes/oscar64/raster-bars.md +239 -0
  581. package/docs/recipes/oscar64/raster-profile-bars.md +404 -0
  582. package/docs/recipes/oscar64/rel-side-sectors.md +391 -0
  583. package/docs/recipes/oscar64/relative-file-records.md +378 -0
  584. package/docs/recipes/oscar64/save-load-seq-file.md +365 -0
  585. package/docs/recipes/oscar64/screenshots/README.md +99 -0
  586. package/docs/recipes/oscar64/screenshots/actor-activation-window-ntsc.png +0 -0
  587. package/docs/recipes/oscar64/screenshots/actor-activation-window.png +0 -0
  588. package/docs/recipes/oscar64/screenshots/adventure-engine-ntsc.png +0 -0
  589. package/docs/recipes/oscar64/screenshots/adventure-engine.png +0 -0
  590. package/docs/recipes/oscar64/screenshots/attract-replay-ntsc.png +0 -0
  591. package/docs/recipes/oscar64/screenshots/attract-replay.png +0 -0
  592. package/docs/recipes/oscar64/screenshots/beat-em-up-lanes-ntsc.png +0 -0
  593. package/docs/recipes/oscar64/screenshots/beat-em-up-lanes.png +0 -0
  594. package/docs/recipes/oscar64/screenshots/bfs-distance-map-ntsc.png +0 -0
  595. package/docs/recipes/oscar64/screenshots/bfs-distance-map.png +0 -0
  596. package/docs/recipes/oscar64/screenshots/bitmap-koala-viewer.png +0 -0
  597. package/docs/recipes/oscar64/screenshots/car-contact-ntsc.png +0 -0
  598. package/docs/recipes/oscar64/screenshots/car-contact.png +0 -0
  599. package/docs/recipes/oscar64/screenshots/cave-scan-ntsc.png +0 -0
  600. package/docs/recipes/oscar64/screenshots/cave-scan.png +0 -0
  601. package/docs/recipes/oscar64/screenshots/char-bullets-ntsc.png +0 -0
  602. package/docs/recipes/oscar64/screenshots/char-bullets.png +0 -0
  603. package/docs/recipes/oscar64/screenshots/charset-animation-ntsc.png +0 -0
  604. package/docs/recipes/oscar64/screenshots/charset-animation.png +0 -0
  605. package/docs/recipes/oscar64/screenshots/charset-parallax-ntsc.png +0 -0
  606. package/docs/recipes/oscar64/screenshots/charset-parallax.png +0 -0
  607. package/docs/recipes/oscar64/screenshots/destructible-terrain-ntsc.png +0 -0
  608. package/docs/recipes/oscar64/screenshots/destructible-terrain.png +0 -0
  609. package/docs/recipes/oscar64/screenshots/difficulty-tables-ntsc.png +0 -0
  610. package/docs/recipes/oscar64/screenshots/difficulty-tables.png +0 -0
  611. package/docs/recipes/oscar64/screenshots/dig-and-guards-ntsc.png +0 -0
  612. package/docs/recipes/oscar64/screenshots/dig-and-guards.png +0 -0
  613. package/docs/recipes/oscar64/screenshots/directory-reader-ntsc.png +0 -0
  614. package/docs/recipes/oscar64/screenshots/directory-reader.png +0 -0
  615. package/docs/recipes/oscar64/screenshots/divide-check-ntsc.png +0 -0
  616. package/docs/recipes/oscar64/screenshots/divide-check.png +0 -0
  617. package/docs/recipes/oscar64/screenshots/double-buffer-nomirror.png +0 -0
  618. package/docs/recipes/oscar64/screenshots/double-buffer-ntsc.png +0 -0
  619. package/docs/recipes/oscar64/screenshots/double-buffer.png +0 -0
  620. package/docs/recipes/oscar64/screenshots/falling-blocks-ntsc.png +0 -0
  621. package/docs/recipes/oscar64/screenshots/falling-blocks.png +0 -0
  622. package/docs/recipes/oscar64/screenshots/fixed-point-jump-ntsc.png +0 -0
  623. package/docs/recipes/oscar64/screenshots/fixed-point-jump-velocity-ntsc.png +0 -0
  624. package/docs/recipes/oscar64/screenshots/fixed-point-jump-velocity.png +0 -0
  625. package/docs/recipes/oscar64/screenshots/fixed-point-jump.png +0 -0
  626. package/docs/recipes/oscar64/screenshots/flip-screen-rooms-ntsc.png +0 -0
  627. package/docs/recipes/oscar64/screenshots/flip-screen-rooms.png +0 -0
  628. package/docs/recipes/oscar64/screenshots/frame-sync-loop-ntsc.png +0 -0
  629. package/docs/recipes/oscar64/screenshots/frame-sync-loop-overrun.png +0 -0
  630. package/docs/recipes/oscar64/screenshots/frame-sync-loop.png +0 -0
  631. package/docs/recipes/oscar64/screenshots/game-tree-search-ntsc.png +0 -0
  632. package/docs/recipes/oscar64/screenshots/game-tree-search.png +0 -0
  633. package/docs/recipes/oscar64/screenshots/ghost-targeting-ntsc.png +0 -0
  634. package/docs/recipes/oscar64/screenshots/ghost-targeting.png +0 -0
  635. package/docs/recipes/oscar64/screenshots/headless-verify-ntsc.png +0 -0
  636. package/docs/recipes/oscar64/screenshots/headless-verify.png +0 -0
  637. package/docs/recipes/oscar64/screenshots/hello-world.png +0 -0
  638. package/docs/recipes/oscar64/screenshots/high-score-persist-ntsc.png +0 -0
  639. package/docs/recipes/oscar64/screenshots/high-score-persist.png +0 -0
  640. package/docs/recipes/oscar64/screenshots/iffl-kernal-skip-ntsc.png +0 -0
  641. package/docs/recipes/oscar64/screenshots/iffl-kernal-skip.png +0 -0
  642. package/docs/recipes/oscar64/screenshots/joystick-input-ntsc.png +0 -0
  643. package/docs/recipes/oscar64/screenshots/joystick-input.png +0 -0
  644. package/docs/recipes/oscar64/screenshots/lane-pursuit-ntsc.png +0 -0
  645. package/docs/recipes/oscar64/screenshots/lane-pursuit.png +0 -0
  646. package/docs/recipes/oscar64/screenshots/level-rle-decoder-ntsc.png +0 -0
  647. package/docs/recipes/oscar64/screenshots/level-rle-decoder.png +0 -0
  648. package/docs/recipes/oscar64/screenshots/lfsr-random-ntsc.png +0 -0
  649. package/docs/recipes/oscar64/screenshots/lfsr-random-seed2.png +0 -0
  650. package/docs/recipes/oscar64/screenshots/lfsr-random.png +0 -0
  651. package/docs/recipes/oscar64/screenshots/load-asset-runtime-ntsc.png +0 -0
  652. package/docs/recipes/oscar64/screenshots/load-asset-runtime.png +0 -0
  653. package/docs/recipes/oscar64/screenshots/memory-layout-ntsc.png +0 -0
  654. package/docs/recipes/oscar64/screenshots/memory-layout.png +0 -0
  655. package/docs/recipes/oscar64/screenshots/mixed-fighters-ntsc.png +0 -0
  656. package/docs/recipes/oscar64/screenshots/mixed-fighters.png +0 -0
  657. package/docs/recipes/oscar64/screenshots/multi-sprite-object-ntsc.png +0 -0
  658. package/docs/recipes/oscar64/screenshots/multi-sprite-object.png +0 -0
  659. package/docs/recipes/oscar64/screenshots/nav-area-pathfinding-ntsc.png +0 -0
  660. package/docs/recipes/oscar64/screenshots/nav-area-pathfinding.png +0 -0
  661. package/docs/recipes/oscar64/screenshots/object-pool-ntsc.png +0 -0
  662. package/docs/recipes/oscar64/screenshots/object-pool.png +0 -0
  663. package/docs/recipes/oscar64/screenshots/pal-ntsc-detect-ntsc.png +0 -0
  664. package/docs/recipes/oscar64/screenshots/pal-ntsc-detect-oldntsc.png +0 -0
  665. package/docs/recipes/oscar64/screenshots/pal-ntsc-detect-pal.png +0 -0
  666. package/docs/recipes/oscar64/screenshots/password-state-ntsc.png +0 -0
  667. package/docs/recipes/oscar64/screenshots/password-state.png +0 -0
  668. package/docs/recipes/oscar64/screenshots/per-frame-hitbox-ntsc.png +0 -0
  669. package/docs/recipes/oscar64/screenshots/per-frame-hitbox.png +0 -0
  670. package/docs/recipes/oscar64/screenshots/petscii-screen-codes-ntsc.png +0 -0
  671. package/docs/recipes/oscar64/screenshots/petscii-screen-codes.png +0 -0
  672. package/docs/recipes/oscar64/screenshots/platformer-scaffold-d64-ntsc.png +0 -0
  673. package/docs/recipes/oscar64/screenshots/platformer-scaffold-d64.png +0 -0
  674. package/docs/recipes/oscar64/screenshots/platformer-scaffold-ntsc.png +0 -0
  675. package/docs/recipes/oscar64/screenshots/platformer-scaffold.png +0 -0
  676. package/docs/recipes/oscar64/screenshots/print-number-ntsc.png +0 -0
  677. package/docs/recipes/oscar64/screenshots/print-number.png +0 -0
  678. package/docs/recipes/oscar64/screenshots/raster-bars.png +0 -0
  679. package/docs/recipes/oscar64/screenshots/raster-profile-bars-ntsc.png +0 -0
  680. package/docs/recipes/oscar64/screenshots/raster-profile-bars.png +0 -0
  681. package/docs/recipes/oscar64/screenshots/rel-side-sectors-ntsc.png +0 -0
  682. package/docs/recipes/oscar64/screenshots/rel-side-sectors.png +0 -0
  683. package/docs/recipes/oscar64/screenshots/relative-file-records-ntsc.png +0 -0
  684. package/docs/recipes/oscar64/screenshots/relative-file-records.png +0 -0
  685. package/docs/recipes/oscar64/screenshots/save-load-seq-file-ntsc.png +0 -0
  686. package/docs/recipes/oscar64/screenshots/save-load-seq-file.png +0 -0
  687. package/docs/recipes/oscar64/screenshots/seeded-level-fill-ntsc.png +0 -0
  688. package/docs/recipes/oscar64/screenshots/seeded-level-fill.png +0 -0
  689. package/docs/recipes/oscar64/screenshots/sfx-engine-ntsc.png +0 -0
  690. package/docs/recipes/oscar64/screenshots/sfx-engine.png +0 -0
  691. package/docs/recipes/oscar64/screenshots/sid-music-player.png +0 -0
  692. package/docs/recipes/oscar64/screenshots/simple-shmup.png +0 -0
  693. package/docs/recipes/oscar64/screenshots/slope-collision-ntsc.png +0 -0
  694. package/docs/recipes/oscar64/screenshots/slope-collision.png +0 -0
  695. package/docs/recipes/oscar64/screenshots/soft-scroll-h.png +0 -0
  696. package/docs/recipes/oscar64/screenshots/sprite-animation-table-ntsc.png +0 -0
  697. package/docs/recipes/oscar64/screenshots/sprite-animation-table.png +0 -0
  698. package/docs/recipes/oscar64/screenshots/sprite-multiplex-8.png +0 -0
  699. package/docs/recipes/oscar64/screenshots/stable-raster-irq.png +0 -0
  700. package/docs/recipes/oscar64/screenshots/text-input-ntsc.png +0 -0
  701. package/docs/recipes/oscar64/screenshots/text-input.png +0 -0
  702. package/docs/recipes/oscar64/screenshots/text-overlay-playfield-gameover.png +0 -0
  703. package/docs/recipes/oscar64/screenshots/text-overlay-playfield-notrail-control.png +0 -0
  704. package/docs/recipes/oscar64/screenshots/text-overlay-playfield-ntsc.png +0 -0
  705. package/docs/recipes/oscar64/screenshots/text-overlay-playfield-ungated-control.png +0 -0
  706. package/docs/recipes/oscar64/screenshots/text-overlay-playfield.png +0 -0
  707. package/docs/recipes/oscar64/screenshots/text-window-menu-ntsc.png +0 -0
  708. package/docs/recipes/oscar64/screenshots/text-window-menu.png +0 -0
  709. package/docs/recipes/oscar64/screenshots/tile-grid-collision-ntsc.png +0 -0
  710. package/docs/recipes/oscar64/screenshots/tile-grid-collision.png +0 -0
  711. package/docs/recipes/oscar64/screenshots/tile-map-render-ntsc.png +0 -0
  712. package/docs/recipes/oscar64/screenshots/tile-map-render.png +0 -0
  713. package/docs/recipes/oscar64/screenshots/two-player-ntsc.png +0 -0
  714. package/docs/recipes/oscar64/screenshots/two-player.png +0 -0
  715. package/docs/recipes/oscar64/screenshots/two-word-parser-ntsc.png +0 -0
  716. package/docs/recipes/oscar64/screenshots/two-word-parser.png +0 -0
  717. package/docs/recipes/oscar64/screenshots/vehicle-control-ntsc.png +0 -0
  718. package/docs/recipes/oscar64/screenshots/vehicle-control.png +0 -0
  719. package/docs/recipes/oscar64/screenshots/wave-director-ntsc.png +0 -0
  720. package/docs/recipes/oscar64/screenshots/wave-director.png +0 -0
  721. package/docs/recipes/oscar64/seeded-level-fill.md +364 -0
  722. package/docs/recipes/oscar64/sfx-engine.md +514 -0
  723. package/docs/recipes/oscar64/sid-music-player.md +441 -0
  724. package/docs/recipes/oscar64/simple-shmup.md +1000 -0
  725. package/docs/recipes/oscar64/slope-collision.md +610 -0
  726. package/docs/recipes/oscar64/soft-scroll-h.md +261 -0
  727. package/docs/recipes/oscar64/sprite-animation-table.md +671 -0
  728. package/docs/recipes/oscar64/sprite-multiplex-8.md +314 -0
  729. package/docs/recipes/oscar64/stable-raster-irq.md +236 -0
  730. package/docs/recipes/oscar64/text-input.md +274 -0
  731. package/docs/recipes/oscar64/text-overlay-playfield.md +617 -0
  732. package/docs/recipes/oscar64/text-window-menu.md +551 -0
  733. package/docs/recipes/oscar64/tile-grid-collision.md +563 -0
  734. package/docs/recipes/oscar64/tile-map-render.md +395 -0
  735. package/docs/recipes/oscar64/two-player.md +528 -0
  736. package/docs/recipes/oscar64/two-word-parser.md +510 -0
  737. package/docs/recipes/oscar64/vehicle-control.md +771 -0
  738. package/docs/recipes/oscar64/wave-director.md +787 -0
  739. package/docs/recipes/runs.json +1606 -0
  740. package/docs/runtime/sim6502-reference.md +466 -0
  741. package/docs/runtime/vice-mcp-reference.md +351 -0
  742. package/docs/runtime/vice-reference.md +1393 -0
  743. package/docs/techniques/bitmap-modes.md +685 -0
  744. package/docs/techniques/cpu-cycle-tricks.md +1570 -0
  745. package/docs/techniques/effects-vector-3d.md +1431 -0
  746. package/docs/techniques/file-io.md +1427 -0
  747. package/docs/techniques/input.md +1072 -0
  748. package/docs/techniques/loaders-packers.md +768 -0
  749. package/docs/techniques/logic.md +3091 -0
  750. package/docs/techniques/maths.md +1524 -0
  751. package/docs/techniques/memory-banking.md +1686 -0
  752. package/docs/techniques/music-sid.md +1144 -0
  753. package/docs/techniques/raster.md +1543 -0
  754. package/docs/techniques/scroll.md +1292 -0
  755. package/docs/techniques/sprite.md +2566 -0
  756. package/docs/techniques/text-mode-render.md +717 -0
  757. package/docs/techniques/text.md +1095 -0
  758. package/docs/techniques/transitions.md +405 -0
  759. package/docs/toolchains/cartconv-reference.md +262 -0
  760. package/docs/toolchains/cc1541-reference.md +316 -0
  761. package/docs/toolchains/cc65-reference.md +667 -0
  762. package/docs/toolchains/error-sources/cc65/README.md +1 -0
  763. package/docs/toolchains/error-sources/cc65/missing-setcpu.s +4 -0
  764. package/docs/toolchains/error-sources/cc65/range-error.s +4 -0
  765. package/docs/toolchains/error-sources/cc65/segment-overflow.c +6 -0
  766. package/docs/toolchains/error-sources/cc65/unresolved-external.c +6 -0
  767. package/docs/toolchains/error-sources/kickassembler/README.md +1 -0
  768. package/docs/toolchains/error-sources/kickassembler/branch-out-of-range.asm +4 -0
  769. package/docs/toolchains/error-sources/kickassembler/failed-assert.asm +3 -0
  770. package/docs/toolchains/error-sources/kickassembler/flat-lib.asm +4 -0
  771. package/docs/toolchains/error-sources/kickassembler/import-source-no-namespace.asm +5 -0
  772. package/docs/toolchains/error-sources/kickassembler/macro-without-parentheses.asm +6 -0
  773. package/docs/toolchains/error-sources/kickassembler/memory-block-overlap.asm +4 -0
  774. package/docs/toolchains/error-sources/kickassembler/symbol-clash-lib.asm +5 -0
  775. package/docs/toolchains/error-sources/kickassembler/symbol-clash-main.asm +6 -0
  776. package/docs/toolchains/error-sources/kickassembler/unknown-symbol.asm +4 -0
  777. package/docs/toolchains/error-sources/oscar64/README.md +1 -0
  778. package/docs/toolchains/error-sources/oscar64/asm-addressing-mode.c +7 -0
  779. package/docs/toolchains/error-sources/oscar64/region-overflow.c +6 -0
  780. package/docs/toolchains/error-sources/oscar64/undefined-extern-var.c +5 -0
  781. package/docs/toolchains/error-sources/oscar64/undefined-extern.c +6 -0
  782. package/docs/toolchains/error-sources/oscar64/unknown-vic-field.c +6 -0
  783. package/docs/toolchains/error-sources/oscar64/void-main.c +3 -0
  784. package/docs/toolchains/kickassembler-reference.md +1020 -0
  785. package/docs/toolchains/memory-layout-planning.md +362 -0
  786. package/docs/toolchains/oscar64-headers-reference.md +583 -0
  787. package/docs/toolchains/oscar64-reference.md +892 -0
  788. package/docs/toolchains/petcat-reference.md +290 -0
  789. package/docs/toolchains/png2prg.md +188 -0
  790. package/docs/toolchains/release-disk.md +314 -0
  791. package/docs/toolchains/sidreloc.md +236 -0
  792. package/docs/toolchains/spindle-reference.md +487 -0
  793. package/docs/toolchains/tape-mastering.md +592 -0
  794. package/docs/toolchains/unit-testing-6502.md +281 -0
  795. package/docs/workflow/agent-harness.md +478 -0
  796. package/package.json +105 -0
  797. package/templates/_harness/CLAUDE.md.template +91 -0
  798. package/templates/_harness/PLAN.md.template +72 -0
  799. package/templates/_harness/check.py +442 -0
  800. package/templates/_harness/claude/settings.json +17 -0
  801. package/templates/_harness/gen-asm-header.py +96 -0
  802. package/templates/_harness/harness.mk +273 -0
  803. package/templates/_harness/hooks/plan-gate.py +185 -0
  804. package/templates/_harness/meter/frame_meter.asm +311 -0
  805. package/templates/_harness/meter/frame_meter.c +155 -0
  806. package/templates/_harness/meter/frame_meter.h +80 -0
  807. package/templates/_harness/zp-used.py +104 -0
  808. package/templates/action-puzzle/.claude/settings.json +17 -0
  809. package/templates/action-puzzle/.mcp.json +10 -0
  810. package/templates/action-puzzle/CLAUDE.md +120 -0
  811. package/templates/action-puzzle/Makefile +125 -0
  812. package/templates/action-puzzle/PLAN.md +388 -0
  813. package/templates/action-puzzle/README.md +240 -0
  814. package/templates/action-puzzle/expect.json +25 -0
  815. package/templates/action-puzzle/src/cave.c +280 -0
  816. package/templates/action-puzzle/src/cave.h +80 -0
  817. package/templates/action-puzzle/src/gen_autopilot.h +20 -0
  818. package/templates/action-puzzle/src/gen_caves.h +59 -0
  819. package/templates/action-puzzle/src/gen_notes.h +16 -0
  820. package/templates/action-puzzle/src/hiscore.c +152 -0
  821. package/templates/action-puzzle/src/hiscore.h +41 -0
  822. package/templates/action-puzzle/src/level.c +64 -0
  823. package/templates/action-puzzle/src/level.h +24 -0
  824. package/templates/action-puzzle/src/main.c +599 -0
  825. package/templates/action-puzzle/src/render.c +239 -0
  826. package/templates/action-puzzle/src/render.h +31 -0
  827. package/templates/action-puzzle/src/sound.c +158 -0
  828. package/templates/action-puzzle/src/sound.h +22 -0
  829. package/templates/action-puzzle/tools/disk_check.py +77 -0
  830. package/templates/action-puzzle/tools/drive.py +106 -0
  831. package/templates/action-puzzle/tools/gen.py +454 -0
  832. package/templates/action-puzzle/tools/model_check.py +49 -0
  833. package/templates/action-puzzle/tools/verdict_codes.py +24 -0
  834. package/templates/adventure/.claude/settings.json +17 -0
  835. package/templates/adventure/.mcp.json +10 -0
  836. package/templates/adventure/CLAUDE.md +118 -0
  837. package/templates/adventure/Makefile +113 -0
  838. package/templates/adventure/PLAN.md +396 -0
  839. package/templates/adventure/README.md +277 -0
  840. package/templates/adventure/expect.json +25 -0
  841. package/templates/adventure/src/engine.c +543 -0
  842. package/templates/adventure/src/engine.h +48 -0
  843. package/templates/adventure/src/gen_script.h +141 -0
  844. package/templates/adventure/src/gen_world.h +511 -0
  845. package/templates/adventure/src/main.c +439 -0
  846. package/templates/adventure/src/picture.c +83 -0
  847. package/templates/adventure/src/picture.h +16 -0
  848. package/templates/adventure/src/save.c +159 -0
  849. package/templates/adventure/src/save.h +25 -0
  850. package/templates/adventure/src/sound.c +71 -0
  851. package/templates/adventure/src/sound.h +16 -0
  852. package/templates/adventure/src/text.c +349 -0
  853. package/templates/adventure/src/text.h +40 -0
  854. package/templates/adventure/tools/disk_check.py +128 -0
  855. package/templates/adventure/tools/drive.py +119 -0
  856. package/templates/adventure/tools/gen.py +1033 -0
  857. package/templates/adventure/tools/world.py +356 -0
  858. package/templates/beat-em-up/.claude/settings.json +17 -0
  859. package/templates/beat-em-up/.mcp.json +10 -0
  860. package/templates/beat-em-up/CLAUDE.md +136 -0
  861. package/templates/beat-em-up/Makefile +96 -0
  862. package/templates/beat-em-up/PLAN.md +502 -0
  863. package/templates/beat-em-up/README.md +315 -0
  864. package/templates/beat-em-up/expect-gameover.json +8 -0
  865. package/templates/beat-em-up/expect.json +29 -0
  866. package/templates/beat-em-up/src/anim.c +70 -0
  867. package/templates/beat-em-up/src/art.c +344 -0
  868. package/templates/beat-em-up/src/autopilot.h +154 -0
  869. package/templates/beat-em-up/src/brute.c +273 -0
  870. package/templates/beat-em-up/src/enemy.c +281 -0
  871. package/templates/beat-em-up/src/engine.asm +512 -0
  872. package/templates/beat-em-up/src/fighter.c +384 -0
  873. package/templates/beat-em-up/src/game.h +269 -0
  874. package/templates/beat-em-up/src/hud.c +135 -0
  875. package/templates/beat-em-up/src/main.c +341 -0
  876. package/templates/beat-em-up/src/sound.c +44 -0
  877. package/templates/beat-em-up/src/street.c +93 -0
  878. package/templates/beat-em-up/src/verdict.h +523 -0
  879. package/templates/beat-em-up/src/view.c +362 -0
  880. package/templates/beat-em-up/tools/drive.py +105 -0
  881. package/templates/beat-em-up/tools/flickercheck.py +273 -0
  882. package/templates/demo/.claude/settings.json +17 -0
  883. package/templates/demo/.mcp.json +10 -0
  884. package/templates/demo/CLAUDE.md +129 -0
  885. package/templates/demo/Makefile +66 -0
  886. package/templates/demo/PLAN.md +401 -0
  887. package/templates/demo/README.md +322 -0
  888. package/templates/demo/expect.json +945 -0
  889. package/templates/demo/src/config.asm +80 -0
  890. package/templates/demo/src/framework.asm +390 -0
  891. package/templates/demo/src/main.asm +139 -0
  892. package/templates/demo/src/music.asm +197 -0
  893. package/templates/demo/src/part_main.asm +279 -0
  894. package/templates/demo/src/part_title.asm +79 -0
  895. package/templates/demo/src/parts.asm +43 -0
  896. package/templates/demo/src/tables.asm +73 -0
  897. package/templates/demo/src/verdict.asm +179 -0
  898. package/templates/demo/tools/audio.py +80 -0
  899. package/templates/demo/tools/gen_expect.py +167 -0
  900. package/templates/demo/tools/probe.py +95 -0
  901. package/templates/hello/.claude/settings.json +17 -0
  902. package/templates/hello/.mcp.json +10 -0
  903. package/templates/hello/CLAUDE.md +100 -0
  904. package/templates/hello/Makefile +38 -0
  905. package/templates/hello/PLAN.md +200 -0
  906. package/templates/hello/expect.json +20 -0
  907. package/templates/hello/src/main.c +161 -0
  908. package/templates/hello/src/sprite.asm +27 -0
  909. package/templates/hello-kick/.claude/settings.json +17 -0
  910. package/templates/hello-kick/.mcp.json +10 -0
  911. package/templates/hello-kick/CLAUDE.md +100 -0
  912. package/templates/hello-kick/Makefile +17 -0
  913. package/templates/hello-kick/PLAN.md +199 -0
  914. package/templates/hello-kick/expect.json +20 -0
  915. package/templates/hello-kick/src/main.asm +233 -0
  916. package/templates/platformer/.claude/settings.json +17 -0
  917. package/templates/platformer/.mcp.json +10 -0
  918. package/templates/platformer/CLAUDE.md +125 -0
  919. package/templates/platformer/Makefile +86 -0
  920. package/templates/platformer/PLAN.md +360 -0
  921. package/templates/platformer/README.md +277 -0
  922. package/templates/platformer/expect.json +32 -0
  923. package/templates/platformer/src/actors.c +289 -0
  924. package/templates/platformer/src/anim.c +51 -0
  925. package/templates/platformer/src/art.c +212 -0
  926. package/templates/platformer/src/autopilot.h +30 -0
  927. package/templates/platformer/src/engine.asm +253 -0
  928. package/templates/platformer/src/game.h +248 -0
  929. package/templates/platformer/src/hud.c +90 -0
  930. package/templates/platformer/src/level.c +184 -0
  931. package/templates/platformer/src/main.c +306 -0
  932. package/templates/platformer/src/player.c +268 -0
  933. package/templates/platformer/src/sound.c +42 -0
  934. package/templates/platformer/src/verdict.h +206 -0
  935. package/templates/platformer/src/view.c +331 -0
  936. package/templates/platformer/stage-expect.json +6 -0
  937. package/templates/platformer/tools/drive.py +112 -0
  938. package/templates/platformer/tools/tearcheck.py +229 -0
  939. package/templates/shmup-vertical/.claude/settings.json +17 -0
  940. package/templates/shmup-vertical/.mcp.json +10 -0
  941. package/templates/shmup-vertical/CLAUDE.md +137 -0
  942. package/templates/shmup-vertical/Makefile +131 -0
  943. package/templates/shmup-vertical/PLAN.md +569 -0
  944. package/templates/shmup-vertical/README.md +189 -0
  945. package/templates/shmup-vertical/expect.json +38 -0
  946. package/templates/shmup-vertical/src/bullets.c +158 -0
  947. package/templates/shmup-vertical/src/bullets.h +35 -0
  948. package/templates/shmup-vertical/src/display.c +239 -0
  949. package/templates/shmup-vertical/src/display.h +40 -0
  950. package/templates/shmup-vertical/src/game.h +85 -0
  951. package/templates/shmup-vertical/src/glyph.asm +358 -0
  952. package/templates/shmup-vertical/src/hiscore.c +141 -0
  953. package/templates/shmup-vertical/src/hiscore.h +16 -0
  954. package/templates/shmup-vertical/src/hit.asm +180 -0
  955. package/templates/shmup-vertical/src/hitbox.c +59 -0
  956. package/templates/shmup-vertical/src/hitbox.h +25 -0
  957. package/templates/shmup-vertical/src/kernel.asm +330 -0
  958. package/templates/shmup-vertical/src/level.c +174 -0
  959. package/templates/shmup-vertical/src/level.h +27 -0
  960. package/templates/shmup-vertical/src/main.c +824 -0
  961. package/templates/shmup-vertical/src/mux.asm +321 -0
  962. package/templates/shmup-vertical/src/sound.asm +255 -0
  963. package/templates/shmup-vertical/src/step.asm +169 -0
  964. package/templates/shmup-vertical/src/waves.c +195 -0
  965. package/templates/shmup-vertical/src/waves.h +33 -0
  966. package/templates/shmup-vertical/stage-expect.json +6 -0
  967. package/templates/shmup-vertical/tools/drive.py +152 -0
  968. package/templates/shmup-vertical/tools/joytest.py +159 -0
  969. package/templates/shmup-vertical/tools/meter.py +15 -0
  970. 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 -->