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,660 @@
1
+ ---
2
+ category: region
3
+ ---
4
+
5
+ <!-- doc-type: pitfall-reference -->
6
+
7
+ # Region Timing Pitfalls
8
+
9
+ All three pitfalls in this file stem from the same root: the C64 shipped in two
10
+ incompatible clock domains. PAL runs at 985,248 Hz with 312 raster lines per
11
+ frame; NTSC runs at 1,022,727 Hz with 263 lines per frame. Any hard-coded
12
+ assumption about frame rate, clock speed, or line count breaks when code crosses
13
+ regions. The fix in every case is to detect the region at boot — 36 bytes of
14
+ 6502 and just over one frame of waiting at worst, usually much less — and
15
+ branch on it.
16
+
17
+ ---
18
+
19
+ ## pal_ntsc_tempo_mismatch — Music written for 50 Hz PAL plays 20% fast on 60 Hz NTSC
20
+
21
+ **Severity:** high
22
+ **Region:** both
23
+ **Triggered by techniques:** sid_play_routine_pattern, sid_voice_setup, frame_sync_loop, sfx_engine_beside_music, colour_fade, colour_cycling, screen_wipe, logic_rate_decoupling, difficulty_ramp_tables, falling_block_rules, ghost_target_tile_ai, cave_scan_engine, jump_arc_table, vehicle_control, lane_pursuit_ai
24
+ **Mitigated by techniques:** pal_ntsc_detection
25
+
26
+ ### Symptom
27
+
28
+ Music that sounds correct on a PAL machine plays noticeably faster on NTSC —
29
+ the tempo is roughly 20% too high, giving ballads a frantic quality and
30
+ fast-paced tracks an unintended frenzy. The pitch of each note is correct (the
31
+ SID frequency registers produce slightly different Hz but the difference is a
32
+ fraction of a semitone); only the rhythm is wrong. On an NTSC machine running a
33
+ PAL-authored music driver, a track meant to run at 120 BPM plays at roughly 144
34
+ BPM.
35
+
36
+ The inverse problem — NTSC-authored music played on PAL — produces a tempo about
37
+ 16% too slow (50.125 / 59.826 = 0.838, the inverse of the 19.4% below; an
38
+ earlier version said 17%). Energetic chiptunes become sluggish. This is rarer in practice because
39
+ most C64 music was authored in Europe on PAL machines.
40
+
41
+ ### Mechanism
42
+
43
+ Tracker-based music drivers call a `play` subroutine once per video frame from a
44
+ raster or CIA IRQ handler. The play routine advances the tracker pattern by one
45
+ tick. The composer sets note durations in ticks, so the audible tempo is directly
46
+ proportional to the tick rate, which equals the frame rate.
47
+
48
+ PAL frame rate is 50.125 Hz (one frame every 19.95 ms). NTSC frame rate is
49
+ 59.826 Hz (one frame every 16.71 ms). If the play routine fires once per frame
50
+ unconditionally, the NTSC tick rate is 59.826 / 50.125 = 1.194× the PAL rate —
51
+ a 19.4% tempo increase. Rounded to the nearest whole number, this is the "20%
52
+ too fast" figure that has followed European C64 ports to U.S. machines for
53
+ decades.
54
+
55
+ The problem is compounded by tempo subdivision: a speed value of N ticks per
56
+ note step scales the tempo by the same 20% ratio on NTSC.
57
+
58
+ ### Fix
59
+
60
+ Two approaches cover all cases:
61
+
62
+ **Approach 1 — 5-of-6 frame skip on NTSC.** Call the play routine every frame
63
+ on PAL. On NTSC, call it every frame *except* every 6th frame (5 calls out of 6).
64
+ The effective NTSC tick rate becomes 59.826 × (5/6) = 49.855 Hz — within 0.54%
65
+ of the 50.125 Hz PAL rate. Tempo error drops from 19.4% to under 1%, which is
66
+ inaudible. Implement this with a single frame counter and a conditional skip:
67
+
68
+ ```kick
69
+ // Region-detect at boot (Method 2 from pal-ntsc-reference.md; technique
70
+ // pal_ntsc_detection). On exit: region_flag = 0 for PAL, 1 for NTSC.
71
+ detect_region:
72
+ sei
73
+ wait_lo:
74
+ bit $d011
75
+ bmi wait_lo // If already inside the RST8 band, let it finish
76
+ wait_hi:
77
+ bit $d011
78
+ bpl wait_hi // RST8 rises: raster line 256 on every chip
79
+ track:
80
+ lda $d012 // Sample the low byte...
81
+ bit $d011
82
+ bpl band_over // ...kept only if RST8 was still set
83
+ tax
84
+ jmp track
85
+ band_over:
86
+ lda #0 // Last line seen: PAL $37, NTSC $06 or $05
87
+ cpx #$10
88
+ bcs set_flag // $10 or more exists only on PAL: flag 0
89
+ lda #1 // Below $10: NTSC, flag 1
90
+ set_flag:
91
+ sta region_flag
92
+ cli
93
+ rts
94
+
95
+ // Per-frame IRQ handler calling music play. Installed at $0314, so the
96
+ // KERNAL dispatcher at $FF48 has already pushed A, X, Y; the handler exits
97
+ // through $EA81 (PLA/TAY/PLA/TAX/PLA/RTI), which pops them. Use $EA31
98
+ // instead if the KERNAL's jiffy clock and keyboard scan are wanted.
99
+ frame_irq:
100
+ asl $d019 // Ack VIC raster IRQ
101
+ lda region_flag
102
+ beq call_play // PAL: always call play
103
+ // NTSC: skip every 6th frame.
104
+ inc ntsc_frame_counter
105
+ lda ntsc_frame_counter
106
+ cmp #6
107
+ bne call_play
108
+ lda #0
109
+ sta ntsc_frame_counter
110
+ jmp skip_play // Skip this frame's tick
111
+ call_play:
112
+ jsr music_play
113
+ skip_play:
114
+ jmp $ea81 // Not rti: the dispatcher's A, X, Y are still on the stack
115
+
116
+ region_flag: .byte 0
117
+ ntsc_frame_counter: .byte 0
118
+ ```
119
+
120
+ **Correction (2026-09-22).** `frame_irq` used to end in a bare `rti`. From a
121
+ `$0314` handler that pops the dispatcher's saved Y, X and A as P, PCL and
122
+ PCH, so the first interrupt returns to whatever address the interrupted
123
+ code's A:X happened to form (measured in VICE x64sc 3.10: the verbatim
124
+ listing warm-starts on the first frame; with A:X pointed at a label,
125
+ execution lands on that label). It is not a 3-byte-per-frame stack leak.
126
+ The same change applies to the three `irq_reset_*` handlers in the third
127
+ pitfall below, which also write `$0314`.
128
+
129
+ **Correction (2026-09-21).** The `detect_region` above replaces one that had
130
+ two faults. It read `$D012` once, immediately after RST8 rose — that read is
131
+ line 256, the first line of the band, and returns `$00` on every chip, so
132
+ its `cmp #$10` always failed. And its PAL path ran `lda #0` / `sta
133
+ region_flag` / `bne done_detect`: `lda #0` sets Z, so the `bne` never
134
+ branched and execution fell through into `is_ntsc`, leaving `region_flag`
135
+ at 1 whichever way the compare had gone. Measured in VICE x64sc 3.10: the old
136
+ fragment, unchanged, in a wrapper that paints `region_flag` to the border,
137
+ reported NTSC on the default PAL model both when entered from raster line 100
138
+ and when entered from line 288 — inside the band, where the single read was
139
+ `$20` and the compare passed, which isolates the second fault. The fragment
140
+ above reported PAL when entered from lines 100, 300 and 311 on the PAL model,
141
+ and NTSC when entered from lines 100 and 262 with `-model ntsc` and from 100
142
+ with `-model oldntsc`.
143
+
144
+ **Approach 2 — Ship two tempo tables.** Some music drivers (GoatTracker,
145
+ SID-Wizard) support a per-region speed table embedded in the music data. The
146
+ driver reads the active table based on a region flag set at boot. This is the
147
+ cleanest solution when the music driver already has the infrastructure — no
148
+ frame-skipping artefacts, no timing drift. Approach 1 is preferable when
149
+ modifying the driver is not an option (e.g., a pre-built binary player).
150
+
151
+ **A 50 Hz CIA tick is a valid third approach for the music alone.** Set CIA1
152
+ Timer A to one tick per 20 ms of the *local* φ2 clock — latch $4FE5 (20,454
153
+ cycles) on NTSC R8, $4CE5 (19,686) on PAL — and call the play routine from its
154
+ IRQ; CIA-timed and multi-speed tunes already run this way (see music-sid.md,
155
+ `sid_play_routine_pattern` Variations). Measured in VICE x64sc 3.10: on the
156
+ NTSC model that latch fired 251 times in 300 frames (300 × 17,095 / 20,454 =
157
+ 250.7), a 50.0 Hz tick, so the tempo is correct without frame-skipping. Two
158
+ costs come with it. The latch must be region-corrected — the same NTSC latch
159
+ on PAL fired 289 times in 300 frames, 3.8% slow (see
160
+ `cia_timer_phi2_difference` below) — and the IRQ is not locked to the frame:
161
+ across those 300 frames it entered on every raster line ($D012 min 0, max
162
+ 255), so any screen update placed in the same handler lands mid-frame and
163
+ drifts against the display, and a long play routine in it can delay a raster
164
+ IRQ it collides with. Keep the music IRQ to the play call, or re-enable IRQs
165
+ around it, and do screen work from the raster IRQ. **What not to do** is run
166
+ one per-frame latch or one per-frame raster tick unchanged on both regions.
167
+ An earlier version of this paragraph forbade a 50 Hz CIA tick on NTSC and
168
+ claimed it caused tearing and audio artefacts; a music tick does not draw,
169
+ and no instrument or independent page supported the claim.
170
+
171
+ ### Worked example
172
+
173
+ The full dispatcher in **Fix** above covers both detection and skipping. When
174
+ the region flag is set elsewhere at boot, reduce it to the skip logic alone:
175
+ check `region_flag`, increment a 0-5 counter, call `music_play` unless counter
176
+ just reached 6 (then reset it and return without calling play).
177
+
178
+ ### Cross-references
179
+
180
+ - Technique: `sid_play_routine_pattern` — the canonical per-frame SID player
181
+ structure that this pitfall affects.
182
+ - Technique: `sid_voice_setup` — voice envelope setup is unaffected by tempo
183
+ mismatch, but pitch tables must also be region-adjusted (a separate concern;
184
+ see pal-ntsc-reference.md SID frequency section).
185
+ - Technique: `pal_ntsc_detection` — the region-detect sub-technique used in
186
+ the fix.
187
+ - Reference: `pal-ntsc-reference.md` — canonical clock rates, frame rates, and
188
+ the music-tempo section.
189
+
190
+ ---
191
+
192
+ ## cia_timer_phi2_difference — CIA timers count φ2 cycles; 3.8% clock drift between PAL and NTSC
193
+
194
+ **Severity:** high
195
+ **Region:** both
196
+ **Triggered by registers:** DC04, DC05, DC06, DC07
197
+ **Triggered by techniques:** frame_sync_loop, pwm_digi, difficulty_ramp_tables, digi_4bit
198
+ **Mitigated by techniques:** pal_ntsc_detection
199
+
200
+ ### Symptom
201
+
202
+ A CIA timer calibrated for one second on PAL fires after 0.963 s on NTSC
203
+ (985,248 counts at 1,022,727 Hz — about 37 ms early per intended second; a
204
+ PAL-calibrated software clock reads 1.038 s after one real NTSC second, and
205
+ the error accumulates without bound; an earlier version had the direction
206
+ backwards, "fires after 1.038 seconds"). A digi sample played via a
207
+ CIA-timed loop pitches 3.8% sharp on NTSC — well above the ~20-cent audibility
208
+ threshold. RS-232 via CIA2 is the most immediately obvious failure: wrong baud-
209
+ rate timer values cause framing errors on every byte, making the user port
210
+ non-functional.
211
+
212
+ ### Mechanism
213
+
214
+ CIA timers (Timer A: $DC04/$DC05, Timer B: $DC06/$DC07 for CIA1; same offsets
215
+ at $DD04-$DD07 for CIA2) are 16-bit down-counters driven by the CPU's φ2 clock.
216
+ They count one tick per φ2 rising edge. φ2 is the CPU clock — the same signal
217
+ that clocks the 6510 through each instruction.
218
+
219
+ The φ2 clock frequency differs by region:
220
+
221
+ - **PAL:** 985,248.444 Hz (derived from 17.734472 MHz crystal ÷ 18; an earlier
222
+ version paired this quotient with a 17.734475 MHz crystal, which gives
223
+ 985,248.61 Hz)
224
+ - **NTSC R8:** 1,022,727.143 Hz (derived from 14.31818 MHz crystal ÷ 14)
225
+
226
+ The ratio is 1,022,727 / 985,248 = 1.03804. Any timer reload value calibrated on
227
+ PAL fires 3.8% too soon on NTSC, and vice versa.
228
+
229
+ For a 1-second interval on PAL, the reload value is 985,248 ($F08A0, not the
230
+ $F0960 an earlier version gave — but CIA
231
+ timers are 16-bit, so the maximum interval is 65,536 cycles, i.e., 66.5 ms on
232
+ PAL or 64.1 ms on NTSC). Long intervals require a software counter to chain
233
+ multiple timer underflows. Each hardware underflow fires 64.1 ms apart on NTSC
234
+ vs 66.5 ms on PAL — a 2.4 ms difference per underflow that accumulates linearly.
235
+
236
+ Common affected uses: 1-second countdown timers (about 37 ms short per second,
237
+ visible in under 10 seconds), CIA-driven music ticks (3.8% fast, not 20%: a
238
+ CIA tick is insulated from the frame-rate difference but not from the φ2
239
+ clock difference; measured in VICE x64sc 3.10 as 217 CIA underflows of the
240
+ PAL latch $4CC6 per 250 NTSC frames versus 250 per 250 PAL frames — an
241
+ earlier version claimed the "same 20% tempo jump" as the frame-rate pitfall,
242
+ which only a per-frame latch set for the wrong region gives), $D418 digi via
243
+ CIA (3.8% pitch shift — ≈ 65 cents, clearly audible; 1200 × log2(1.03804) =
244
+ 64.6, not the 63 given earlier), and RS-232 baud-rate timers (wrong baud
245
+ fails immediately with framing errors on every byte).
246
+
247
+ The pal-ntsc-reference.md CIA timer section gives the once-per-frame timer
248
+ latches: PAL $4CC7 (19,655) for a 19,656-cycle frame, NTSC R8 $42C6 (17,094)
249
+ for 17,095. Latch = cycles − 1, because a continuous timer with latch N
250
+ repeats every N + 1 cycles. An earlier version of this page gave $4CC6 /
251
+ $42C5 and attributed them to the reference; those are one cycle short of a
252
+ frame (63 × 312 = 19,656; 65 × 263 = 17,095) and the reference measured them
253
+ drifting one cycle per frame — in VICE x64sc a continuous $4CC7 timer holds
254
+ the same PAL raster line indefinitely while $4CC6 walks one raster line every
255
+ 63 frames; $42C6 / $42C5 behave the same way on the 6567R8 (one line every 65
256
+ frames).
257
+
258
+ ### Fix
259
+
260
+ Detect the region at boot and apply the appropriate reload constant. Provide
261
+ both constants as named symbols and branch on the region flag:
262
+
263
+ ```kick
264
+ // CIA1 Timer A configured for once-per-frame, region-adaptive.
265
+ // Must be called after detect_region (sets region_flag).
266
+
267
+ .const CIA1_TA_LO = $DC04
268
+ .const CIA1_TA_HI = $DC05
269
+ .const CIA1_CRA = $DC0E
270
+
271
+ // Timer A latch values for once-per-frame IRQ (latch = cycles - 1).
272
+ // PAL: latch $4CC7 = 19,655. Timer fires after $4CC7+1 = 19,656 cycles = 63 x 312.
273
+ // NTSC: latch $42C6 = 17,094. Timer fires after $42C6+1 = 17,095 cycles = 65 x 263.
274
+ // (An earlier version used $4CC6 / $42C5, one cycle short of a frame.)
275
+ .const PAL_FRAME_LATCH_LO = $C7
276
+ .const PAL_FRAME_LATCH_HI = $4C
277
+ .const NTSC_FRAME_LATCH_LO = $C6
278
+ .const NTSC_FRAME_LATCH_HI = $42
279
+
280
+ setup_frame_timer:
281
+ lda region_flag
282
+ bne setup_ntsc
283
+
284
+ setup_pal:
285
+ lda #PAL_FRAME_LATCH_LO
286
+ sta CIA1_TA_LO
287
+ lda #PAL_FRAME_LATCH_HI
288
+ sta CIA1_TA_HI
289
+ bne timer_go // Always taken
290
+
291
+ setup_ntsc:
292
+ lda #NTSC_FRAME_LATCH_LO
293
+ sta CIA1_TA_LO
294
+ lda #NTSC_FRAME_LATCH_HI
295
+ sta CIA1_TA_HI
296
+
297
+ timer_go:
298
+ // Enable Timer A IRQ (bit 0), start timer in continuous mode (bit 0 of CRA).
299
+ lda #$81
300
+ sta $DC0D // Enable Timer A IRQ source
301
+ lda #$11 // Start, phi2 input, continuous
302
+ sta CIA1_CRA
303
+ cli
304
+ rts
305
+ ```
306
+
307
+ For arbitrary intervals, compute: `reload = round(interval_sec * cpu_hz) - 1`.
308
+ For digi or RS-232 timers: `timer_ntsc = round(timer_pal * 1.03804)`.
309
+ Custom RS-232 code that bypasses the KERNAL must apply the same ratio — the
310
+ KERNAL handles its own baud-rate constants, but custom code does not inherit
311
+ those corrections.
312
+
313
+ ### Worked example
314
+
315
+ ```kick
316
+ // BAD: hard-coded PAL latch value used on both regions.
317
+ // On NTSC, timer fires after 19,656 phi2 cycles ($4CC7+1).
318
+ // NTSC phi2 = 1,022,727 Hz, so interval = 19656 / 1022727 = 19.22 ms.
319
+ // PAL frame = 19.95 ms. Delta = 0.73 ms per frame — visible in seconds.
320
+ lda #$C7
321
+ sta $DC04 // $4CC7 = PAL frame latch (WRONG on NTSC)
322
+ lda #$4C
323
+ sta $DC05
324
+
325
+ // GOOD: region-conditional latch selection.
326
+ lda region_flag
327
+ bne !+
328
+ lda #$C7 // PAL lo
329
+ sta $DC04
330
+ lda #$4C // PAL hi
331
+ sta $DC05
332
+ bne !++ // Always taken: A = $4C, Z clear (same idiom as
333
+ // setup_frame_timer's bne timer_go); jmp also works
334
+ !: lda #$C6 // NTSC lo
335
+ sta $DC04
336
+ lda #$42 // NTSC hi
337
+ sta $DC05
338
+ !: // timer latch is now correct for both regions
339
+
340
+ // For CIA2 (DD04/DD05/DD06/DD07): identical arithmetic, different addresses.
341
+ // The 3.8% drift applies equally to CIA2 because both chips are clocked
342
+ // from the same phi2 source.
343
+ ```
344
+
345
+ **Correction (2026-09-22).** The GOOD block above used to leave the PAL path
346
+ with `beq !++`. `lda #$4C` clears Z, so that branch was never taken and the
347
+ PAL path fell straight through into the NTSC stores. Measured in VICE x64sc
348
+ 3.10 on the PAL model: with the block assembled verbatim and `region_flag` =
349
+ 0, stopping Timer A and force-loading the latch (`$DC0E` = $10) read
350
+ `$DC04`/`$DC05` = $C5/$42 — the NTSC value — and the same with
351
+ `region_flag` = 1. The same run confirmed that `setup_frame_timer`'s `bne
352
+ timer_go` is always taken (PAL gave $C6/$4C, NTSC $C5/$42, before the latch
353
+ constants themselves were corrected to $4CC7 / $42C6 as noted above).
354
+
355
+ ### Cross-references
356
+
357
+ - Registers: `DC04`, `DC05` (CIA1 Timer A latch/counter), `DC06`, `DC07`
358
+ (CIA1 Timer B latch/counter). CIA2 equivalents at `DD04`, `DD05`, `DD06`,
359
+ `DD07` — same arithmetic, different base address.
360
+ - Reference: `pal-ntsc-reference.md` CIA timer values table — canonical
361
+ once-per-frame latch constants for PAL ($4CC7) and NTSC R8 ($42C6), with
362
+ the latch = cycles − 1 rule and the drift measurement for $4CC6.
363
+ - Pitfall: `pal_ntsc_tempo_mismatch` — the music-tempo problem; closely
364
+ related when a CIA timer drives the music tick instead of the VIC raster IRQ.
365
+
366
+ ---
367
+
368
+ ## raster_line_count_difference — PAL has 312 lines per frame; NTSC has 263; loops that hard-code 312 break
369
+
370
+ **Severity:** medium
371
+ **Region:** both
372
+ **Triggered by registers:** D012, D011
373
+ **Triggered by techniques:** stable_raster_irq, frame_sync_loop, irq_chain_table, raster_split_modes, sideborder_open
374
+ **Mitigated by techniques:** pal_ntsc_detection
375
+
376
+ ### Symptom
377
+
378
+ A raster table loop that walks through IRQ entries for lines 0-311 appears to
379
+ work on PAL. On NTSC the same loop reaches line 263 and then either:
380
+
381
+ - **Fires at the wrong line** — the raster compare is a 9-bit equality against
382
+ the counter; nothing is reduced modulo the line count. A hard-coded target
383
+ of 280 with RST8 clear is the low byte alone: 280 → $18 → line 24, inside
384
+ the NTSC vertical blank / PAL top border (measured in VICE x64sc 3.10, both
385
+ models: RST8 clear + $D012 = $18 fires at $D012 = $18 = 24) instead of the
386
+ expected bottom area. An earlier version said the target "wraps" to 280 −
387
+ 263 = 17; the VIC does no such reduction.
388
+ - **Never fires** — if the code sets RST8 and $D012 = $18 (the 9-bit value
389
+ 280), the NTSC counter never reaches 280. The IRQ chain halts and the screen
390
+ freezes. (280 cannot be written to $D012 at all; it is RST8 = 1 with low
391
+ byte $18. An earlier version described this as "280 + 256 = 536".)
392
+ - **Stalls, or wraps on both chips** — a target at line 250 is inside the
393
+ valid range on both PAL (250 < 312) and NTSC (250 < 263), but a chain that
394
+ then steps to 264 behaves in one of two ways, neither of them "wrap to line
395
+ 1 on NTSC" as an earlier version said. A chain that sets RST8 for 264 stalls
396
+ on NTSC (0 fires) and fires at 264 on PAL — a region difference. A chain
397
+ that steps only $D012 and never sets RST8 arms $08 and fires at line 8 on
398
+ BOTH chips (measured: RST8 clear + $08 → line 8 on PAL and NTSC); that is
399
+ the 8-bit wrap covered by `d012_wrap_around`, not a region difference.
400
+
401
+ More subtly: PAL has 64 lines past the badline window (248-311, where no
402
+ badline can steal cycles: the window is $30-$F7); NTSC has only 15 (248-262).
403
+ A sprite multiplexer that updates Y positions in that range has enough cycles
404
+ on PAL; on NTSC it runs into the next frame's visible area. These lines are
405
+ not blanking, as an earlier version called them: on PAL, 248-250 are the last
406
+ three lines of the 25-row display window, 251-299 are visible lower border
407
+ and only 300-311 (12 lines) are in vertical blank; on NTSC all of 248-262 is
408
+ display or border and visible (NTSC vertical blank is 13-40). A $D020/$D021 or
409
+ sprite write in that range is visible in the border on both regions.
410
+
411
+ ### Mechanism
412
+
413
+ The VIC-II's internal raster counter is 9 bits wide (0-511, though not all
414
+ values are used). $D012 holds the low 8 bits of the current counter value; bit 7
415
+ of $D011 (RST8) holds the 9th bit. The counter increments once per scanline and
416
+ wraps at the frame boundary.
417
+
418
+ The wrap point is chip-specific:
419
+
420
+ | Chip | Lines/frame | $D012 at wrap |
421
+ |---|---|---|
422
+ | 6569 (PAL) | 312 | $37 (55) |
423
+ | 6567R8 (NTSC) | 263 | $06 (6) |
424
+ | 6567R56A (rare) | 262 | $05 (5) |
425
+
426
+ Code that hard-codes the line count fails in two ways:
427
+
428
+ 1. **Table sized for 312 entries.** A raster effect that allocates one byte per
429
+ raster line and walks the whole table runs off the end of the usable NTSC
430
+ range. Entries for lines 263-311 are NTSC dead zones — those raster lines do
431
+ not exist. The table-walker runs past valid data.
432
+
433
+ 2. **IRQ target lines above 262.** Any line number above 262 is outside the
434
+ NTSC frame. Writing such a value to $D012 with the appropriate RST8 state
435
+ creates a compare that the NTSC VIC never reaches. The IRQ chain stalls. The
436
+ program hangs or loses its raster chain permanently.
437
+
438
+ PAL has 64 lines past the badline window (248-311). NTSC has 15 (248-262).
439
+ The practical consequence: NTSC end-of-frame work must complete in 15 × 65 =
440
+ 975 cycles vs PAL's 64 × 63 = 4,032 cycles — a 4× cycle-budget reduction that
441
+ makes some PAL effects impossible on NTSC without redesign. (Anchored on the
442
+ last badline, line 243, pal-ntsc-reference.md counts 68 and 19 lines after
443
+ it: 4,284 vs 1,235 cycles; the ratio is the same. Most of those lines are
444
+ visible border, not blanking — see the Symptom above.)
445
+
446
+ ### Fix
447
+
448
+ Two strategies:
449
+
450
+ **Strategy 1 — Clamp line targets to the safe range.** The "safe" raster
451
+ lines that exist on both PAL and NTSC are 0-262. Schedule all raster IRQs and
452
+ table-driven effects within this range. Accept that the bottom-of-frame window
453
+ past the badlines for NTSC-targeted code is only 15 lines (248-262) rather
454
+ than 64 lines.
455
+
456
+ **Strategy 2 — Region-conditional line tables.** Maintain two versions of any
457
+ raster-table structure — one parameterized for PAL (lines 0-311) and one for
458
+ NTSC (lines 0-262). Select the active table at boot based on the detected region.
459
+ This is the pattern used by production demos that target both regions.
460
+
461
+ The region-detect waits for $D011 bit 7 (RST8) to clear and then set, keeps
462
+ the last $D012 seen while it stays set, and compares that value against $10
463
+ once it clears: PAL ends its frame at $37, NTSC at $06 or $05. The
464
+ three-way form is `detect_region` in `pal-ntsc-reference.md` (Method 1);
465
+ the flag-store form is `detect_region` in the first pitfall above (36 bytes).
466
+
467
+ ```kick
468
+ // BROKEN: raster table loop hard-coded for 312 lines.
469
+ // On NTSC, entries for lines 263-311 don't exist — IRQs misfire or stall.
470
+ // Illustrative only: KickAssembler 5.25 assembles `cpx #312` as `cpx #$38`
471
+ // (the immediate is truncated to 8 bits, no error), and an 8-bit X cannot
472
+ // count to 312 anyway. The fault shown is the hard-coded constant.
473
+ .const NUM_LINES_PAL = 312
474
+ setup_irq_table:
475
+ ldx #0
476
+ loop_irq:
477
+ lda raster_lo,x
478
+ sta $d012
479
+ lda raster_hi,x // 0 or 1: the 9th bit of the target
480
+ lsr // ... into carry
481
+ lda $d011
482
+ and #%01111111
483
+ bcc !+
484
+ ora #%10000000 // Set RST8 for targets >= 256
485
+ !: sta $d011
486
+ // ... install handler ...
487
+ inx
488
+ cpx #NUM_LINES_PAL // Hard-coded 312 — WRONG on NTSC (and truncated to $38)
489
+ bne loop_irq
490
+ rts
491
+
492
+ // FIXED: walk a table of NUM_ENTRIES 9-bit targets (two bytes each) and skip
493
+ // any entry at or above num_lines_active, a 16-bit line count set at boot.
494
+ .const NUM_ENTRIES = 8 // Table length (< 256) — not the frame's line count
495
+ setup_irq_table_fixed:
496
+ ldx #0
497
+ loop_irq_fixed:
498
+ cpx #NUM_ENTRIES
499
+ beq done_loop
500
+ // 16-bit compare: target (hi:lo) against num_lines_active; skip if >=.
501
+ lda raster_hi,x
502
+ cmp num_lines_active+1
503
+ bcc install_entry // hi below: target is in range
504
+ bne skip_entry // hi above: target is past the frame
505
+ lda raster_lo,x
506
+ cmp num_lines_active
507
+ bcs skip_entry // hi equal, lo at or above: past the frame
508
+ install_entry:
509
+ lda raster_lo,x
510
+ sta $d012
511
+ lda raster_hi,x
512
+ lsr // 9th bit into carry
513
+ lda $d011
514
+ and #%01111111
515
+ bcc !+
516
+ ora #%10000000 // Set RST8 for targets >= 256
517
+ !: sta $d011
518
+ // ... install handler ...
519
+ skip_entry:
520
+ inx
521
+ bne loop_irq_fixed
522
+ done_loop:
523
+ rts
524
+
525
+ num_lines_active: .word 0 // set to 312 (PAL) or 263 (NTSC) at boot
526
+ raster_lo: .fill NUM_ENTRIES, <(50 + i * 30) // example targets 50, 80, ... 260
527
+ raster_hi: .fill NUM_ENTRIES, >(50 + i * 30)
528
+ ```
529
+
530
+ **Correction (2026-09-22).** An earlier FIXED listing kept `num_lines_active`
531
+ as one byte "set to 56 (low byte of 312) PAL, 7 (263) NTSC" and compared
532
+ 8-bit targets against it. 312 & 255 = 56 and 263 & 255 = 7, so `cpx
533
+ num_lines_active` stopped the walk after 56 entries on PAL and 7 on NTSC, and
534
+ `cmp num_lines_active / bcs skip_entry` skipped every target at or above 56
535
+ (PAL) or 7 (NTSC) — nearly the whole frame. Neither listing installed RST8,
536
+ so a 9-bit target could not be armed. Both now carry two-byte targets, and
537
+ the FIXED one loops on the table length and compares 16 bits (arithmetic;
538
+ the truncation of `cpx #312` was confirmed by assembling it: `E0 38`).
539
+
540
+ For most effects the simplest fix is to cap all IRQ line targets at 262 and
541
+ avoid scheduling work in the PAL-only lines (263-311; visible lower border up
542
+ to 299, vertical blank from 300). This sacrifices 49 lines of end-of-frame CPU
543
+ time on PAL but produces code that works unmodified on both regions.
544
+
545
+ ### Worked example
546
+
547
+ ```kick
548
+ // Scenario: raster bar effect that colors every other scanline
549
+ // from line 50 to line 250, then resets at the start of each frame.
550
+ // The reset IRQ is placed at line 280 — PAL lower border, outside NTSC frame.
551
+ // All three handlers are installed at $0314 and exit via $EA81, which pops
552
+ // the A, X, Y that the KERNAL dispatcher at $FF48 pushed.
553
+
554
+ // BAD: reset IRQ targets line 280.
555
+ // On PAL: fires in the lower border — the line exists, so the chain runs;
556
+ // any colour/sprite change there is visible.
557
+ // On NTSC: line 280 doesn't exist. With RST8 cleared as below the compare
558
+ // is the low byte alone, $18 = line 24 (inside the NTSC vertical
559
+ // blank) — the reset runs during the next frame's top and corrupts
560
+ // the display. (The VIC does not reduce 280 modulo 263 to 17, as an
561
+ // earlier comment said; measured in VICE x64sc 3.10, both models.)
562
+ irq_reset_bad:
563
+ asl $d019
564
+ lda $d011
565
+ and #%01111111 // Clear RST8
566
+ sta $d011
567
+ lda #<280 // $18 — RST8 must be set for 280, but it's cleared above
568
+ sta $d012 // Target = line 24 on NTSC (RST8 clear), not 280
569
+ lda #<irq_color
570
+ sta $0314
571
+ lda #>irq_color
572
+ sta $0315
573
+ jmp $ea81
574
+
575
+ // GOOD: reset IRQ targets line 255 (safe on both PAL and NTSC).
576
+ // Both regions have raster lines 0-254 inside the active / border area.
577
+ irq_reset_good:
578
+ asl $d019
579
+ lda $d011
580
+ and #%01111111 // Clear RST8 (line 255 < 256, RST8 not needed)
581
+ sta $d011
582
+ lda #255
583
+ sta $d012 // Line 255 exists on both PAL (< 312) and NTSC (< 263)
584
+ lda #<irq_color
585
+ sta $0314
586
+ lda #>irq_color
587
+ sta $0315
588
+ jmp $ea81
589
+
590
+ // When you need region-specific end-of-frame lines, select at runtime:
591
+ irq_reset_region_aware:
592
+ asl $d019
593
+ lda region_flag
594
+ bne !+
595
+ // PAL: line 280 (lower border; 64 lines past the badline window)
596
+ lda $d011
597
+ ora #%10000000 // Set RST8 — line 280 >= 256
598
+ sta $d011
599
+ lda #<280
600
+ sta $d012
601
+ jmp done_reset_irq // Not a conditional branch: <280 = $18 leaves Z clear
602
+ !: // NTSC: line 253 (lower border; 15 lines past the badline window)
603
+ lda $d011
604
+ and #%01111111 // Clear RST8
605
+ sta $d011
606
+ lda #253
607
+ sta $d012
608
+ done_reset_irq:
609
+ lda #<irq_color
610
+ sta $0314
611
+ lda #>irq_color
612
+ sta $0315
613
+ jmp $ea81
614
+ ```
615
+
616
+ **Correction (2026-09-22).** The PAL path of `irq_reset_region_aware` ended
617
+ `lda #<280` / `sta $d012` / `beq done_reset_irq`; `<280` is $18, so Z was
618
+ clear, the branch never taken, and the code fell through into the NTSC
619
+ branch — clearing RST8 and arming line 253. Measured in VICE x64sc 3.10 on
620
+ the PAL model with `region_flag` = 0: the next raster IRQ read $D012 = $FD,
621
+ $D011 = $1B; with the branch replaced by `jmp done_reset_irq` it read $D012 =
622
+ $18, $D011 = $9B (9-bit line 280). `jmp` rather than `bne` because `bne`
623
+ would only work while the low byte happens to be non-zero — a target of 256
624
+ or 512 would silently break it again, the same failure the `detect_region`
625
+ correction in the first pitfall records. All three handlers also ended in a
626
+ bare `rti`, which from a `$0314` handler pops the dispatcher's saved
627
+ registers as the return frame (see the `frame_irq` correction above); they
628
+ exit through `$EA81` now.
629
+
630
+ ### Cross-references
631
+
632
+ - Technique: `stable_raster_irq` — the double-IRQ pattern this pitfall
633
+ affects (its NTSC notes cover the per-line budget only; the narrower
634
+ post-display window is in pal-ntsc-reference.md, Badline range).
635
+ - Registers: `D012` (RASTER — low 8 bits of raster counter and compare
636
+ target), `D011` (SCROLY — bit 7 is RST8, the 9th raster bit).
637
+ - Reference: `pal-ntsc-reference.md` — quick-reference table for lines per
638
+ frame and $D012 wrap values; its "Badline range" section gives the lines
639
+ after the last badline (68 PAL, 19 NTSC R8) and its "Visible region"
640
+ section the vertical blank (300-15 PAL, 13-40 NTSC). It does not give the
641
+ "post-display blanking" counts an earlier version of this entry cited.
642
+ - Pitfall: `d012_wrap_around` — the complementary pitfall about RST8 and the
643
+ 9-bit raster counter; the two pitfalls often co-occur.
644
+
645
+ ## Sources
646
+
647
+ - VICE 3.10, `x64sc`, models `default`, `ntsc`, `oldntsc` — the instrument
648
+ behind every "measured" figure on this page (the `detect_region`
649
+ correction and the entry-line runs; the 2026-09-22 corrections' latch
650
+ reads, raster-compare targets, CIA tick counts and handler-exit runs).
651
+ https://vice-emu.sourceforge.io/
652
+ - KickAssembler 5.25 — assembled every `kick` fragment here; the 36-byte
653
+ count is its.
654
+ - Christian Bauer, "The MOS 6567/6569 video controller (VIC-II) and its
655
+ application in the Commodore 64", https://www.cebix.net/VIC-Article.txt —
656
+ §3.2 (RST8 as bit 8 of the raster register), §3.4 (lines per frame for
657
+ the 6569, 6567R8 and 6567R56A).
658
+ - This repository: `hardware/pal-ntsc-reference.md` (clock rates, frame
659
+ rates, CIA latch table, Method 2), `techniques/raster.md`
660
+ (`pal_ntsc_detection`, with the duration and race measurements).