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,721 @@
1
+ ---
2
+ category: raster
3
+ ---
4
+
5
+ <!-- doc-type: pitfall-reference -->
6
+
7
+ # Raster and Badline Pitfalls
8
+
9
+ The pitfalls in this document share a common thread: they all stem from
10
+ the VIC-II's asynchronous relationship with the CPU. The chip runs on the same
11
+ clock but does not wait for the CPU to finish what it is doing. Badlines steal
12
+ cycles without warning. The raster compare register wraps silently at line 255.
13
+ Sprite DMA freezes the CPU mid-instruction. The stable-raster polling technique
14
+ (and its two-handler `double_irq` refinement) exists precisely because the
15
+ first IRQ you enable has unpredictable entry timing. Each pitfall below has
16
+ caused demo coders and game developers to lose hours to glitches that look random but are in fact completely deterministic once
17
+ you know the mechanism.
18
+
19
+ ---
20
+
21
+ ## badline_cycle_loss — Badline DMA steals 40-43 cycles from the CPU
22
+
23
+ **Severity:** critical
24
+ **Region:** both
25
+ **Triggered by registers:** D011, D012
26
+ **Triggered by techniques:** stable_raster_irq, sprite_multiplex_8, raster_bars, frame_sync_loop, double_irq, badline_synchronization, sideborder_open, fli_image, afli_image, ifli_image, soft_scroll_v, tile_map_render, dma_steal_avoidance, speedcode_generation, big_font_2x2, dycp_scroller, sine_table_generation, scroll_panel_split, sprite_multiplex_game, software_sprite_preshifted, fld_flexible_line_distance, raster_profile_bars, reu_dma, pwm_digi, eight_way_scroll_double_buffer, sprite_color_swap_mid_line, solid_vector_3d, mode7_lookalike, vsp_glitch, pseudo_3d_road_raster, sprite_stretcher_d017, tech_tech_wobbler, dysp_side_border_sprites
27
+
28
+ ### Symptom
29
+
30
+ The raster IRQ handler runs correctly during development, then silently breaks
31
+ every 8 lines. Color bars bleed across line boundaries. Sprite Y-position writes
32
+ arrive one scanline late. A tight per-line loop that works in isolation suddenly
33
+ takes 40 extra cycles at unpredictable intervals. The glitch looks like random
34
+ jitter but repeats at exactly 8-line intervals because the underlying cause is
35
+ perfectly periodic.
36
+
37
+ ### Mechanism
38
+
39
+ A badline occurs on every raster line where `(raster_line & 7) == YSCROLL`,
40
+ where YSCROLL is the low 3 bits of $D011 (default value 3). With the default
41
+ YSCROLL, badlines fall at raster lines 51, 59, 67 ... 243 — 25 lines per frame
42
+ in both regions (the window $30-$F7 and the 25 character rows do not depend on
43
+ frame length; an earlier version of this entry said 24 on NTSC). On each
44
+ badline, the VIC-II must fetch the 40 screen code bytes for the character row
45
+ that begins on that line. The chip asserts the BA
46
+ (Bus Available) signal low 3 cycles before it needs the bus. The CPU, seeing BA
47
+ low, can still complete any instruction that has no remaining bus cycles, but
48
+ cannot issue new memory accesses. Three cycles later, the VIC takes the phi2
49
+ bus for 40 cycles of screen RAM fetch, then releases it.
50
+
51
+ The VIC takes the bus for 40 cycles (15-54) and pulls BA low three cycles
52
+ earlier, on cycle 12; the CPU can spend those three cycles only on write
53
+ cycles. So a PAL badline leaves 20 CPU cycles guaranteed (1-11 and 55-63) and
54
+ 23 at best, not 23 flat. Any raster handler that assumes a fixed 63-cycle
55
+ budget per line will slip by 40 or 43 cycles on every badline it hits. Sprite
56
+ DMA is on top of that: each active sprite takes two bus cycles at the end of
57
+ the line (cycles 58-63 for sprites 0-2, 1-10 of the next line for 3-7), with BA
58
+ dropping at cycle 55, three cycles before the first (an earlier version of this
59
+ entry put sprites 0-2 at 55-62 and then counted the BA lead-in a second time),
60
+ so a badline with all eight sprites active leaves the CPU almost nothing — one
61
+ guaranteed cycle; see `vic_bus_takeover_on_dma` below for the measurement.
62
+
63
+ ### Fix
64
+
65
+ Two approaches, often combined:
66
+
67
+ 1. **Badline avoidance:** Schedule IRQ handlers to fire on non-bad lines. Given
68
+ a fixed YSCROLL of 3, any line where `(target_line & 7) != 3` is safe. A
69
+ status bar split at line 200 (200 & 7 = 0) is safe; at line 203 (203 & 7 = 3)
70
+ it is not. Move the split by 1 line.
71
+
72
+ 2. **DEN off for the whole frame:** the VIC latches DEN once, during raster
73
+ line $30 (48); if it is clear then, no line of that frame is a badline and
74
+ the display is blank. Clearing DEN later in the frame does *not* stop the
75
+ remaining badlines — an earlier version of this entry said it did. Sprite
76
+ DMA still occurs either way.
77
+
78
+ 3. **YSCROLL steering for a region:** on each line of the region write $D011
79
+ with YSCROLL set to a value the line number cannot match (for instance
80
+ `(line + 4) & 7`, written early in the line). The badline condition is
81
+ evaluated every cycle, so no line in the region becomes bad; the character
82
+ display goes idle there (it shows the background colour). This is what
83
+ `recipes/kickassembler/sideborder-open.md` does and measures. Elsewhere,
84
+ rewrite YSCROLL only after the current line's window has passed (from
85
+ cycle 55) so the write cannot create a badline on the line it lands in.
86
+
87
+ ### Worked example
88
+
89
+ ```kick
90
+ // BAD: handler fires on a line that may be a badline.
91
+ // On badline rows, the STA $D020 arrives ~40 cycles late,
92
+ // producing a color bleed into the next line.
93
+ irq_handler:
94
+ lda #WHITE
95
+ sta $d020 // May arrive 40 cycles late on badlines
96
+ lda #(irq_handler >> 8)
97
+ sta $0315
98
+ lda #<irq_handler
99
+ sta $0314
100
+ asl $d019 // Ack VIC interrupt
101
+ rti
102
+
103
+ // GOOD: keep the split off badline rows. With YSCROLL=3 a line is bad when
104
+ // (line & 7) == 3; arm the IRQ a line early and spin to the target so the
105
+ // colour write lands in the blank, and pick a target with (line & 7) != 3.
106
+ .const SPLIT = 200 // 200 & 7 = 0: not a badline
107
+ effect_irq:
108
+ ldx #WHITE
109
+ lda #SPLIT
110
+ !: cmp $d012
111
+ bne !-
112
+ stx $d020 // cycle <= 15 of line SPLIT
113
+ // ... other work ...
114
+ asl $d019
115
+ jmp $ea81
116
+
117
+ // For a whole region with no badlines at all (blank display, all 63 cycles):
118
+ // write YSCROLL = (line + 4) & 7 on every line of the region, as
119
+ // recipes/kickassembler/sideborder-open.md does. Clearing DEN mid-frame
120
+ // does NOT do this; DEN is sampled once, on line $30.
121
+ ```
122
+
123
+ For code that must run on a potentially bad line (e.g., per-line raster bars),
124
+ subtract 43 from the available cycle count and ensure the handler body fits
125
+ within 20 cycles on PAL or 22 cycles on NTSC (23 and 25 only if the three
126
+ cycles after BA drops on cycle 12 happen to be write cycles).
127
+
128
+ ### Cross-references
129
+
130
+ - Technique: `stable_raster_irq` — the polling stable-raster technique that
131
+ this pitfall most visibly affects; the technique doc discusses badline avoidance in its
132
+ cycle budget section.
133
+ - Technique: `sprite_multiplex_8` — active sprites add 2 cycles/sprite of DMA
134
+ on top of the 40-43-cycle badline stall; together they take 62 of the 63
135
+ cycles on such a line (see `vic_bus_takeover_on_dma` below).
136
+ - Technique: `badline_synchronization` — the raster.md technique covering the
137
+ full badline accounting framework.
138
+ - Registers: `D011` (SCROLY — carries DEN bit and YSCROLL), `D012` (RASTER).
139
+
140
+ ---
141
+
142
+ ## d012_wrap_around — $D012 wraps at line 255; bit 7 of $D011 holds the 9th bit
143
+
144
+ **Severity:** high
145
+ **Region:** both
146
+ **Triggered by registers:** D011, D012
147
+ **Triggered by techniques:** stable_raster_irq, raster_bars, irq_chain_table, raster_split_modes, pal_ntsc_detection, frame_sync_loop, big_font_2x2, dycp_scroller, logic_rate_decoupling, sprite_multiplex_game, sprite_border_scroller, sprites_only_screen_mode
148
+
149
+ ### Symptom
150
+
151
+ A raster IRQ set for line 260 (a valid PAL line in the lower border area) fires
152
+ at line 4 instead, because only the low byte was written and RST8 was clear. On
153
+ a freshly booted machine the sticky bit points the other way: the KERNAL's VIC
154
+ init writes $9B to $D011, so RST8 starts SET and a bare `sta $d012` with a low
155
+ target resolves to target+256 — that exists on PAL only for targets 0-55 (NTSC
156
+ 0-6), so the IRQ usually never fires at all. In a handler chain that rewrites
157
+ only $D012, each handler inherits whatever RST8 the previous one left, so
158
+ alternate splits land 256 lines away, or the chain stalls on a target above the
159
+ last line and the frame rate appears to halve. (An earlier version of this
160
+ entry said a single stale write could fire twice per frame; it cannot — see
161
+ Mechanism.)
162
+
163
+ On NTSC the effect is more immediately visible: the frame is only 263 lines
164
+ (6567R8; 262 on the 6567R56A), so lines 256-262 are ordinary visible
165
+ bottom-border lines (the NTSC vertical blank is lines 13-40, per
166
+ `docs/hardware/pal-ntsc-reference.md`; an earlier version of this entry called
167
+ 256-262 "vertical blank"), and any bottom-border effect crosses line 255 without
168
+ deliberately targeting high line numbers — a handler that chains forward by
169
+ setting `$D012 = next_line` forgets the 9th bit and wraps to `next_line - 256`.
170
+
171
+ ### Mechanism
172
+
173
+ The VIC-II's internal raster counter is 9 bits wide. $D012 holds the low 8 bits
174
+ of the raster compare target. The 9th bit (the high bit) is bit 7 of $D011 —
175
+ the RST8 bit. When the compare target is 256 or higher, RST8 must be set. When
176
+ the compare target is 255 or lower, RST8 must be clear.
177
+
178
+ The failure mode is: code writes only `STA $D012` with the low byte of the
179
+ desired line, and never touches $D011 bit 7. On the first frame this works if
180
+ the target line is below 256. On a line at or above 256, the actual compare
181
+ target the VIC sees is `desired_line & 0xFF` with the 9th bit from whatever
182
+ $D011 bit 7 happens to be. If it is clear, the compare fires at line
183
+ `target - 256` instead of `target`. One IRQ fires per frame, at the wrong line
184
+ — the compare is a single 9-bit value, so it can never match two lines in one
185
+ frame. (An earlier version of this page said two IRQs fire per frame; measured
186
+ in VICE x64sc: RST8=0/$D012=4 gives exactly one IRQ per frame at line 4,
187
+ RST8=1/$D012=80 gives none, on both PAL and NTSC.) Two firings only occur when
188
+ a chain of handlers changes RST8 or $D012 between them.
189
+
190
+ The bit is also sticky: it remains set until explicitly cleared. Code that
191
+ handles both low and high lines must clear RST8 when switching to a target below
192
+ 256, not just omit setting it.
193
+
194
+ ### Fix
195
+
196
+ Always perform a read-modify-write on $D011 when setting or clearing RST8:
197
+
198
+ ```kick
199
+ // Set the raster compare target to TARGET_LINE (may be >= 256).
200
+ .const TARGET_LINE = 260
201
+
202
+ set_irq_line:
203
+ lda $d011
204
+ .if (TARGET_LINE >= 256) {
205
+ ora #%10000000 // Set RST8 (bit 7)
206
+ } else {
207
+ and #%01111111 // Clear RST8
208
+ }
209
+ sta $d011
210
+ lda #<TARGET_LINE // Low 8 bits
211
+ sta $d012
212
+ ```
213
+
214
+ In a dynamic context where the target line is a variable at runtime:
215
+
216
+ ```kick
217
+ // runtime: .X = target line low byte, carry = 1 if line >= 256
218
+ set_irq_dynamic:
219
+ lda $d011
220
+ and #%01111111 // Clear RST8
221
+ bcc !+ // If target < 256, leave RST8 clear
222
+ ora #%10000000 // Otherwise set RST8
223
+ !: sta $d011
224
+ stx $d012 // Write low 8 bits
225
+ ```
226
+
227
+ ### Worked example
228
+
229
+ ```kick
230
+ // BAD: only writes $D012, assumes target < 256.
231
+ // On PAL line 260, $D012 = 4, RST8 = 0,
232
+ // so the IRQ fires at line 4 instead of 260.
233
+ lda #<260 // $04
234
+ sta $d012 // Compare target = line 4 (WRONG)
235
+
236
+ // GOOD: writes both RST8 and $D012.
237
+ lda $d011
238
+ ora #%10000000 // Set RST8 for line >= 256
239
+ sta $d011
240
+ lda #<260 // $04
241
+ sta $d012 // Compare target = line 260 (correct)
242
+
243
+ // ALSO BAD: forgets to CLEAR RST8 when switching back to line 80.
244
+ // $D011 bit 7 is still set from the previous write above,
245
+ // so the compare target becomes 80 + 256 = 336 — which never fires on PAL.
246
+ lda #80
247
+ sta $d012 // Bug: RST8 still set, target = 336
248
+
249
+ // CORRECT:
250
+ lda $d011
251
+ and #%01111111 // Clear RST8 for line < 256
252
+ sta $d011
253
+ lda #80
254
+ sta $d012
255
+ ```
256
+
257
+ ### Cross-references
258
+
259
+ - Technique: `stable_raster_irq` — the technique this pitfall most directly
260
+ affects; the KickAssembler recipe keeps every target below 256 and writes
261
+ RST8=0 once via `lda #$1b`; it does not exercise the >= 256 path.
262
+ - Registers: `D012` (RASTER — low 8 bits of raster counter and compare),
263
+ `D011` (SCROLY — bit 7 is RST8, the 9th raster bit).
264
+
265
+ ---
266
+
267
+ ## raster_irq_first_line_jitter — First raster IRQ after enable has unpredictable entry timing
268
+
269
+ **Severity:** high
270
+ **Region:** both
271
+ **Triggered by registers:** D011, D012
272
+ **Triggered by techniques:** stable_raster_irq, irq_chain_table, phase_inverted_irq, frame_sync_loop, raster_split_modes, mode7_lookalike, vsp_glitch, pseudo_3d_road_raster, sprite_stretcher_d017, tech_tech_wobbler, dysp_side_border_sprites
273
+ **Mitigated by techniques:** stable_raster_irq, double_irq
274
+
275
+ ### Symptom
276
+
277
+ A raster effect that works perfectly after the first few frames is unstable on
278
+ the very first frame after IRQ enable. Color splits land 1-7 pixels to the right
279
+ on the first frame. A sprite multiplex update on the first frame puts sprites
280
+ one line too low. The symptom disappears by frame 2. Alternatively, a raster
281
+ effect coded without the stable-raster polling technique shows a permanent 0-7
282
+ cycle wobble that makes split lines look "fuzzy" — a 1-7 pixel horizontal smear
283
+ on every frame where the interrupted instruction happened to be long.
284
+
285
+ ### Mechanism
286
+
287
+ The 6510 does not sample the /IRQ line between clock cycles — it samples it at
288
+ the end of each instruction. When the VIC-II asserts the IRQ line, the CPU
289
+ finishes whatever instruction it is currently executing, then begins the 7-cycle
290
+ interrupt entry sequence (two dummy cycles, push PCH, push PCL, push P, fetch
291
+ vector low, fetch vector high; the handler's first opcode fetch is its own first
292
+ cycle — an earlier version of this entry counted it inside the 7). The number
293
+ of cycles between the VIC asserting the line and the handler's first instruction executing depends on how many cycles
294
+ were left in the interrupted instruction. A 2-cycle `NOP` interrupted on its
295
+ last cycle adds 1 cycle of delay; a 6-cycle `STA ($zp,X)` interrupted on its
296
+ first cycle adds 5 cycles of delay. The total jitter window is 0-6 cycles for
297
+ common instructions (the 7-cycle `BRK` is a pathological case that adds up to
298
+ 6 cycles, but is not found in normal runtime code).
299
+
300
+ On the very first frame after enabling IRQs (writing $D01A bit 0 = 1), the CPU
301
+ has no idea what instruction it will be executing when the first IRQ fires. The
302
+ jitter is random within the 0-6 cycle window. On subsequent frames, if the
303
+ main loop is a tight `JMP *` or a counted NOP sled, the interrupted instruction
304
+ is always the same (a 3-cycle `JMP`, leaving 0-2 cycles of jitter, or a 2-cycle
305
+ `NOP`, leaving 0-1 — an earlier version of this entry called `JMP *` a 2-cycle
306
+ branch; a taken same-page branch is itself 3 cycles), so the jitter narrows
307
+ — but it does not disappear. The polling loop bounds the jitter to one loop
308
+ iteration (0-8 cycles for the 9-cycle `LDA/CMP/BNE` form); the `double_irq`
309
+ variant then removes that residual before the cycle-tight register writes begin.
310
+ That is why `stable_raster_irq` is on both metadata lines above: the pitfall
311
+ is what a raster interrupt does before the technique is applied to it (the
312
+ naive form), and the technique's polling loop — with `double_irq` for the
313
+ last cycle — is the cure.
314
+
315
+ ### Fix
316
+
317
+ Use the stable-raster technique (`stable_raster_irq`): the polling form below
318
+ bounds jitter to one loop iteration (0-8 cycles with the 9-cycle `LDA/CMP/BNE`
319
+ loop shown); for zero jitter use the two-handler `double_irq` form described in
320
+ the technique doc and in `recipes/kickassembler/stable-raster-irq.md`. The
321
+ polling pattern:
322
+
323
+ 1. Enable raster IRQs with the IRQ line set to one line before the target line
324
+ (line N-1).
325
+ 2. In the IRQ handler for line N-1: acknowledge $D019, leave $D012 at N-1, and
326
+ poll $D012 in a tight loop until the counter increments to N. (An earlier
327
+ version of this entry said to set $D012 to N here; that re-arms the compare
328
+ for a line the handler is still polling through, latches a second IRQ that
329
+ is never acknowledged, and re-enters the handler straight after RTI — see the
330
+ worked example.)
331
+ 3. Once $D012 reads N, execute a counted NOP pad to place the writes at the
332
+ desired cycle to within the loop's residual (the pad sets the mean position
333
+ only).
334
+ 4. Perform the cycle-tight register writes.
335
+
336
+ The polling loop at step 2 bounds whatever jitter existed on entry to the
337
+ handler. By the time the loop exits ($D012 has just incremented to N), every
338
+ subsequent instruction runs within one poll iteration of the start of line N.
339
+ The initial first-frame jitter is bounded the same way — the first handler
340
+ entry may be anywhere within line N-1, but the polling loop absorbs that and
341
+ exits within one poll iteration of the start of line N regardless — but not at
342
+ one fixed cycle: the exit cycle still depends on where in the iteration the
343
+ entry fell.
344
+
345
+ ### Worked example
346
+
347
+ ```kick
348
+ // Single-IRQ approach — JITTERY. The STA $D020 can land 0-6 cycles
349
+ // late depending on what instruction was running when the IRQ fired.
350
+ irq_jittery:
351
+ lda #BLUE
352
+ sta $d020 // Horizontal seam varies by 0-6 pixels
353
+ asl $d019 // Ack
354
+ rti
355
+
356
+ // Stable-raster polling approach — jitter bounded to one 9-cycle poll
357
+ // iteration, not zero. Measured in VICE x64sc 3.10: with a frame-locked main
358
+ // loop the exit phase kept the entry spread unchanged (two phases 4 cycles
359
+ // apart over 60 frames); with a 19-cycle main loop it took three phases
360
+ // spanning 5 cycles. Zero jitter needs double_irq.
361
+ // IRQ fires at line TARGET_LINE-1. It acks, leaves the compare where it is,
362
+ // then spins until $D012 increments to TARGET_LINE.
363
+ // An earlier version of this fragment wrote TARGET_LINE to $D012 before the
364
+ // poll; that fired a second compare during the poll, left $D019 latched, and
365
+ // re-entered the handler right after RTI (measured: ~2 main-loop iterations
366
+ // per frame). Leaving $D012 at TARGET_LINE-1 needs no second ack and no re-arm.
367
+ irq_stable_setup:
368
+ asl $d019 // Ack IRQ for line TARGET_LINE-1
369
+ // Poll until raster reaches TARGET_LINE.
370
+ // Each loop iteration: LDA abs (4) + CMP imm (2) + BNE (3) = 9 cycles.
371
+ // The loop exits within 0-8 cycles of the line start, bounding jitter.
372
+ !: lda $d012
373
+ cmp #TARGET_LINE
374
+ bne !-
375
+ // Now on line TARGET_LINE. Add NOP padding to reach the desired cycle
376
+ // (to within the loop's residual).
377
+ nop // 2 cycles — tune count for the mean cycle target
378
+ nop
379
+ // Effect code lands here within one poll iteration of the line start.
380
+ lda #RED
381
+ sta $d020 // Lands within one poll iteration of the line
382
+ // start; use double_irq for a fixed cycle
383
+ rti
384
+ ```
385
+
386
+ The key insight: the `LDA $D012 / CMP / BNE` loop quantises the jitter window
387
+ to its own 9-cycle period; it does not remove it (an earlier version of this
388
+ entry said the loop "consumes" the jitter and the writes land at a fixed cycle;
389
+ measured in VICE x64sc, the exit phase spread equalled the entry spread). The
390
+ exit of the loop always happens within one loop iteration (9 cycles) of the
391
+ raster line's start. NOP pads after the loop bring the writes to the desired
392
+ cycle to within that residual. The first-frame case is no different: the
393
+ polling loop bounds any entry-time jitter, including the variable amount from
394
+ the random interrupted instruction on frame 1.
395
+
396
+ For single-cycle precision, the `double_irq` technique fires two consecutive
397
+ IRQs on lines N-1 and N, where the second IRQ's entry timing is constrained by
398
+ the known instruction in the main loop between the two handlers (typically a
399
+ 2-cycle NOP), eliminating even the 0-8 cycle polling-loop residual. "Lines N-1
400
+ and N" holds with the KERNAL out; through $0314 the first handler arms the
401
+ second IRQ two lines down (see the technique doc and the recipe's "The double
402
+ IRQ").
403
+
404
+ ### Cross-references
405
+
406
+ - Technique: `stable_raster_irq` — the complete description of the polling
407
+ stable-raster pattern, including the NOP-pad sizing and the `double_irq`
408
+ variant for single-cycle work.
409
+ - Technique: `double_irq` — scene-tier zero-jitter extension of stable_raster_irq.
410
+ - Registers: `D019` (VICIRQ — interrupt flag register; must be acked before
411
+ RTI), `D012` (RASTER — the register being polled), `D011` (SCROLY — RST8 bit
412
+ for targets >= 256).
413
+
414
+ ---
415
+
416
+ ## vic_bus_takeover_on_dma — VIC sprite DMA freezes the CPU for 5-19 cycles per scanline
417
+
418
+ **Severity:** medium
419
+ **Region:** both
420
+ **Triggered by registers:** D015
421
+ **Triggered by techniques:** sprite_multiplex_8, dma_steal_avoidance, sideborder_open, sprite_multiplex_24, sprite_sine_chain, badline_synchronization, sprite_multiplex_game, reu_dma, raster_profile_bars, sprites_only_screen_mode, dysp_side_border_sprites
422
+
423
+ ### Symptom
424
+
425
+ A raster IRQ that runs cleanly with no sprites enabled suddenly slips its timing
426
+ when sprites are turned on. The slip is not random — it is proportional to the
427
+ number of sprites active on the scanline where the IRQ handler runs. With 8
428
+ sprites active on the handler's line, the CPU appears to freeze for approximately
429
+ 19 cycles mid-instruction, then resume. Register writes that were cycle-tight
430
+ arrive late. In extreme cases, the handler misses its intended scanline
431
+ entirely and writes land on the line below.
432
+
433
+ ### Mechanism
434
+
435
+ For each sprite enabled in $D015, the VIC-II must fetch 3 bytes of sprite pixel
436
+ data (s-accesses) on every raster line covered by that sprite's 21 pixel rows.
437
+ The chip claims the bus for these fetches during specific cycles of the scanline.
438
+ Before the s-accesses begin, the VIC also issues 2 p-access cycles (pointer
439
+ fetches) for each active sprite. Not all of these accesses cost the CPU: the
440
+ p-access and one of the three s-accesses are phi1 accesses, the VIC's own bus
441
+ phase; only the two phi2 s-accesses take CPU bus cycles, which is why the cost
442
+ is two cycles per sprite and not three or five. (An earlier version of this
443
+ entry said all of them happen during phi2.)
444
+
445
+ The exact stall per sprite, per DMA scanline (an earlier version of this entry
446
+ charged 2 cycles of p-access on the first line plus 3 of s-access per line, and
447
+ its sums did not add up — 3 + 2 + 16 is 21, not 19):
448
+ - **0 cycles** for the p-access: it happens on every raster line for every
449
+ sprite regardless of enable state, in phi1, and costs the CPU nothing.
450
+ - **2 bus cycles** of s-access per sprite on every line of its 21 DMA lines.
451
+ - **3 cycles of BA lead-in** per contiguous group of sprite slots, during which
452
+ the CPU can only complete write cycles.
453
+
454
+ Measured in VICE x64sc 3.10 with an all-read loop timed by CIA1 between raster
455
+ lines 100 and 200, DEN off, sprites at Y=150 (21 DMA lines): 105/147/231/399
456
+ cycles stolen over the 21 lines of 1/2/4/8 sprites (= 21 × 5, 7, 11, 19), and
457
+ 210 for sprites 0 and 7 as two BA groups (21 × 10). The 3 lead-in cycles per
458
+ group being write-usable is from the VIC-II reference and Bauer's model, not
459
+ measured here. Sprite DMA and badline costs simply add: 8 sprites plus 5
460
+ badlines over lines 140-180 measured 614 = 399 + 5 × 43.
461
+
462
+ With all 8 sprites enabled and active on a single line, the VIC steals 3 cycles
463
+ of BA + 8 × 2 s-access = 19 cycles from the CPU on that line. On PAL, this
464
+ reduces the effective CPU budget from 63 cycles to 44 cycles. On NTSC, from 65
465
+ cycles to 46 cycles.
466
+
467
+ The CPU cannot choose when the stall happens — it is determined by the VIC's
468
+ internal DMA schedule, which runs on fixed cycle slots within each line. If an
469
+ instruction spans a DMA window, the CPU stalls mid-instruction and resumes when
470
+ the VIC releases the bus. The instruction completes correctly but takes more wall
471
+ clock cycles than its documented cycle count.
472
+
473
+ ### Fix
474
+
475
+ Account for sprite DMA in the cycle budget wherever sprites are active on the
476
+ IRQ handler's scanline:
477
+
478
+ | Active sprites on handler line (one contiguous group) | Cycles stolen | Usable cycles PAL | Usable cycles NTSC |
479
+ |---:|---:|---:|---:|
480
+ | 0 | 0 | 63 | 65 |
481
+ | 1 | 5 | 58 | 60 |
482
+ | 2 | 7 | 56 | 58 |
483
+ | 4 | 11 | 52 | 54 |
484
+ | 8 | 19 | 44 | 46 |
485
+
486
+ (Measured in VICE x64sc: 2 per sprite plus 3 lead-in per group. An earlier
487
+ version of this table gave 2/5/9 for 1/2/4 sprites, under-budgeting by 3 cycles
488
+ each; sprites in separate groups pay the lead-in once per group.)
489
+
490
+ Strategies:
491
+
492
+ 1. **Fire the handler on a line where no sprites are active.** If sprites are
493
+ enabled for display rows 50-100 and the raster handler must run on line 95,
494
+ check whether all 8 sprites are active there. If they are, move the handler
495
+ to line 101 (below the sprite zone) if the effect permits.
496
+
497
+ 2. **Account for DMA in cycle-counted code.** Add the DMA stall cycles to the
498
+ cycle count for any instruction that may execute during the DMA window. Use
499
+ VICE's cycle counter to measure actual cycle consumption rather than the
500
+ documented cycle count.
501
+
502
+ 3. **Disable sprites in the effect zone.** Write $D015 = $00 above the effect
503
+ line to disable all sprites; restore after the effect section. This is
504
+ compatible with sprite multiplexing: the multiplexer can disable sprites it
505
+ is not currently showing.
506
+
507
+ 4. **Use the sprite DMA window deliberately.** Some advanced techniques
508
+ (sprite-crunch, sprite stretching) exploit the DMA cycle slots. Out of scope
509
+ here, but the point is the DMA slots are fixed and therefore predictable.
510
+
511
+ ### Worked example
512
+
513
+ ```kick
514
+ // WRONG: assumes 63 available cycles on a line where 8 sprites are active.
515
+ // The handler body takes 54 cycles as written (8 colour writes), but sprite
516
+ // DMA steals 19, so total wall-clock consumption is 73 cycles — bleeds into
517
+ // the next line. (An earlier version of this example counted a LDA #imm /
518
+ // STA abs pair as 3 or 4 cycles; it is 2 + 4 = 6.)
519
+ sprite_irq_buggy:
520
+ asl $d019 // 6 cycles (read-modify-write)
521
+ lda #BLUE // 2 cycles
522
+ sta $d020 // 4 cycles — color write 1 (pair = 6)
523
+ lda #RED
524
+ sta $d021 // pair = 6 — color write 2
525
+ lda #GREEN
526
+ sta $d022 // pair = 6 — color write 3
527
+ // ... 5 more store pairs = 30 more cycles ...
528
+ // Total: 54 coded cycles + 19 DMA = 73 actual cycles (OVERFLOW)
529
+ rti
530
+
531
+ // CORRECT: handler is scheduled on a line where 0 sprites are active,
532
+ // OR the handler body is trimmed to fit within 44 usable cycles.
533
+ // With 8 sprites: coded body must fit in 44 cycles, not 63.
534
+ sprite_irq_correct:
535
+ asl $d019 // 6 cycles
536
+ lda #BLUE // 2 cycles
537
+ sta $d020 // 4 cycles
538
+ lda #RED // 2 cycles
539
+ sta $d021 // 4 cycles
540
+ // Only 2 color writes: 18 coded cycles + 19 DMA = 37 actual cycles (OK)
541
+ // The RTI (6) and the IRQ entry (7, plus up to 29 via the KERNAL
542
+ // dispatcher) are on top of the body.
543
+ rti
544
+ ```
545
+
546
+ ### Cross-references
547
+
548
+ - Technique: `sprite_multiplex_8` — the primary technique that enables 8+
549
+ sprites per frame; its cycle budget section discusses DMA accounting.
550
+ - Register: `D015` (SPENA — sprite enable bits; each set bit triggers DMA
551
+ on active lines for that sprite).
552
+ - Pitfall: `badline_cycle_loss` — the two cycle thieves stack, not overlap: a
553
+ badline on a line with 8 active sprites leaves the CPU one cycle on PAL
554
+ (cycle 11), plus at most the three write-only cycles 12-14 if the instruction
555
+ in flight is writing then — 4 at best, never the 20-23 an earlier version of
556
+ this entry gave. Measured in VICE x64sc: 43 (badline) + 19 (eight sprites) =
557
+ 62 of 63 cycles stolen on every line where both occur (915 - 516 - 399 = 0
558
+ over two overlapping lines; 1314 - 516 - 798 = 0 over five). The sprite
559
+ lead-in cycles 55-57 are not usable on such a line: BA is already low from
560
+ cycle 12 and does not rise again until cycle 11 of the next line, so a CPU
561
+ halted on a read at cycle 15 cannot reach them.
562
+
563
+ ---
564
+
565
+ ## scroll_phase_breaks_panel_split — A panel split with a fixed delay breaks at one YSCROLL phase
566
+
567
+ **Severity:** high
568
+ **Region:** both
569
+ **Triggered by registers:** D011, D012
570
+ **Triggered by techniques:** scroll_panel_split, soft_scroll_v, char_scroll_buffer_v
571
+ **Mitigated by techniques:** scroll_panel_split
572
+
573
+ ### Symptom
574
+
575
+ A vertically scrolling playfield sits above a fixed score panel. Seven frames
576
+ in eight the panel is clean. On the eighth, the panel's first line keeps the
577
+ playfield's blue and its 38-column left edge, and the next six lines have the
578
+ panel's grey and width but stray light-blue character pixels where the rule
579
+ row should be. The rest of the panel is correct. The flicker repeats every
580
+ eight pixels of scroll. Measured with PIL on the recipe's `USE_TABLE = 0`
581
+ build at YSCROLL 6, PAL and NTSC: line 215 x 39-351 on blue, lines 216-221
582
+ x 32-351 on grey (98, 98, 98), line 222 on identical to the reference.
583
+
584
+ ### Mechanism
585
+
586
+ The split IRQ polls for the playfield's last line and then waits a fixed
587
+ delay so its stores land in that line's right border. A line is a badline when
588
+ its low three bits equal YSCROLL. The playfield's YSCROLL takes all eight
589
+ values, so the split line is a badline at exactly one of them. At that phase
590
+ the VIC holds the CPU from cycle 12 to cycle 54 during the delay, and the
591
+ stores land about 40 cycles late, inside the panel's first line. The
592
+ panel's `$D011` then makes that line a badline too late for a normal fetch,
593
+ and the `$D016` and `$D018` changes arrive mid-line.
594
+
595
+ Measured in VICE x64sc 3.10, PAL and NTSC, with
596
+ `recipes/kickassembler/scroll-panel-split.md` and `USE_TABLE = 0` (split
597
+ line 214, the same 5-pass delay at every phase): at YSCROLL 0-5 and 7 the
598
+ panel region, lines 215-250, is pixel-identical to the reference. At YSCROLL
599
+ 6, where line 214 is a badline, lines 215-221 differ (1,108 pixels on PAL,
600
+ 1,107 on NTSC). Two forum threads name YSCROLL 7 as the bad
601
+ phase (https://www.lemon64.com/forum/viewtopic.php?t=52763 and
602
+ https://www.lemon64.com/forum/viewtopic.php?t=64112, read as search
603
+ snippets, and the site returned 403 for the second; forum reports, not
604
+ measured here); that is the phase for their split line, not a constant.
605
+
606
+ `scroll_panel_split` is on both lines above: the naive form of the split
607
+ raises the pitfall and the table-driven form cures it.
608
+
609
+ ### Fix
610
+
611
+ Index the delay by the playfield's YSCROLL and give the phase at which the
612
+ split line is a badline a short or zero delay: the badline stall is the wait.
613
+ Load every register value before the poll, so that after the stall only the
614
+ stores remain. In the recipe the table is 5, 5, 5, 5, 5, 5, 0, 5 passes of 9
615
+ cycles, and all eight phases leave the panel pixel-identical on PAL and NTSC.
616
+
617
+ A second, separate phase effect: put the panel's first line on a line that is
618
+ 7 mod 8. Elsewhere the panel's first row reads a different screen row at
619
+ different phases (measured: panel on line 216 with YSCROLL 0 read screen row
620
+ 21 at playfield YSCROLL 0 and row 20 at YSCROLL 3).
621
+
622
+ ### Worked example
623
+
624
+ ```text
625
+ // Naive: one delay for every phase. Breaks when (split line & 7) = YSCROLL.
626
+ lda #LAST_PF-1
627
+ wait: cmp $d012
628
+ bcs wait
629
+ lda #5
630
+ sta count
631
+ delay: dec count
632
+ bpl delay
633
+ sty $d016 ...
634
+
635
+ // Fixed: the delay comes from a table indexed by YSCROLL.
636
+ ldx yscroll
637
+ lda delay_tbl,x // 5, 5, 5, 5, 5, 5, 0, 5 for split line 214
638
+ sta count
639
+ ... // load the panel values, poll, dec count / bpl
640
+ ```
641
+
642
+ ### Cross-references
643
+
644
+ - Technique: `scroll_panel_split` in `techniques/scroll.md`.
645
+ - Pitfall: `badline_cycle_loss`: the 40-43 cycle stall that moves the stores.
646
+ - Recipe: `recipes/kickassembler/scroll-panel-split.md`, with the per-phase table.
647
+ - Source of the table idea: c64gameframework `raster.s`, `irq4DelayTbl`
648
+ (https://github.com/cadaver/c64gameframework, read, not run).
649
+
650
+ ---
651
+
652
+ ## idle_fetch_byte_shows_in_gaps — The byte at $3FFF is drawn wherever the VIC has no row to show
653
+
654
+ **Severity:** medium
655
+ **Region:** both
656
+ **Triggered by registers:** D011
657
+ **Triggered by techniques:** fld_flexible_line_distance, sideborder_open, topbottom_border_open, sprites_only_screen_mode, dysp_side_border_sprites
658
+
659
+ ### Symptom
660
+
661
+ A band of thin vertical stripes, or a repeated pattern, appears across the
662
+ display window where there should be plain background: in the gap an FLD
663
+ opens above the screen, in the lines a side-border loop keeps badline-free,
664
+ or in the opened top and bottom borders. On the developer's machine or in a
665
+ fresh emulator the same lines are clean. Garbage that "only shows on real
666
+ hardware", or only after another program has run, is the usual report.
667
+
668
+ ### Mechanism
669
+
670
+ When no badline has loaded the video matrix latch the VIC is in idle state,
671
+ and its g-accesses read one fixed address instead of the character
672
+ generator: `$3FFF` in VIC bank 0, `$7FFF`, `$BFFF` or `$FFFF` in banks 1-3,
673
+ and `$39FF` (or the bank equivalent) with ECM set. The byte fetched is
674
+ drawn as pixels across the whole window on every idle line, bit 1 in colour
675
+ 0, bit 0 in the background colour. VICE's RAM starts cleared, so the byte
676
+ is zero and the idle lines look like background. On hardware the byte holds
677
+ whatever was there: the power-on RAM pattern, or the tail of a previous
678
+ program's data, tables or code. Every technique that opens lines the VIC
679
+ does not fetch a row for exposes it: the FLD gap (`fld_flexible_line_distance`),
680
+ a side-border region whose YSCROLL is rewritten each line
681
+ (`sideborder_open`), and the top and bottom borders once opened
682
+ (`topbottom_border_open`). Measured in VICE x64sc 3.10: with `$3FFF` set to
683
+ `%10101010`, every line of an 18-line FLD gap on PAL and a 22-line gap on
684
+ NTSC is 160 black and 160 background pixels across x 32-351, alternating
685
+ from x = 32.
686
+
687
+ ### Fix
688
+
689
+ Own the byte. Store `$00` at the idle address of the bank in use before the
690
+ effect starts, or store a chosen pattern when the stripes are wanted; in
691
+ bank 3 the address is `$FFFF`, which is RAM to the VIC and to a CPU store
692
+ even with the KERNAL ROM banked in. Do it once at start-up and again
693
+ whenever the VIC bank changes. The address is not free memory: a table
694
+ that ends at `$3FFF` puts its last byte on the screen.
695
+
696
+ ### Worked example
697
+
698
+ From `recipes/kickassembler/fld.md`: the recipe wants the gap to be
699
+ visible, so it plants the pattern deliberately.
700
+
701
+ ```text
702
+ // Bank 0: the idle fetch reads $3FFF. Plant the stripe once at start-up.
703
+ lda #%10101010
704
+ sta $3fff
705
+
706
+ // The same program wanting a clean gap stores zero instead:
707
+ lda #0
708
+ sta $3fff
709
+
710
+ // Bank 3 ($C000-$FFFF): the equivalent address is $FFFF, RAM under the
711
+ // KERNAL for both the VIC's fetch and the CPU's store.
712
+ lda #0
713
+ sta $ffff
714
+ ```
715
+
716
+ ### Cross-references
717
+
718
+ - Technique: `fld_flexible_line_distance` in `techniques/raster.md`: the gap is idle lines by design.
719
+ - Technique: `sideborder_open` and `topbottom_border_open` in `techniques/raster.md`: idle lines as a side effect.
720
+ - Hardware: `hardware/vic-ii-reference.md`, "Idle vs display state" and the `$3FFF` phantom-pixel note.
721
+ - Recipe: `recipes/kickassembler/fld.md`, where the byte is `%10101010` and the stripes are measured.