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,926 @@
1
+ ---
2
+ recipe: light-pen-read
3
+ toolchain: kickassembler
4
+ output_format: PRG
5
+ region: both
6
+ techniques: [light_pen_read]
7
+ file_formats: [PRG]
8
+ uses_registers: [D013, D014, D019, D01A, D011, D012, DC00, DC01, DC0D, DD04, DD05, DD0E, D020, D021]
9
+ uses_kernal: []
10
+ ---
11
+
12
+ <!-- doc-type: recipe -->
13
+
14
+ # KickAssembler — Read the light pen latch on control port 1, count its interrupts, and convert the latch to a text cell
15
+
16
+ ## Synopsis
17
+
18
+ Enables the VIC's light pen interrupt (`$D01A` bit 3), reads the latched
19
+ `$D013` and `$D014` once per frame for 300 frames, counts the pen
20
+ interrupts and how often the latch moved, and prints the port's switch
21
+ byte and the interrupt flag register at the end. It then runs eight
22
+ synthetic latch values through the pen-delay correction and the
23
+ two-pixel-unit conversion to a text column and row, and times the
24
+ interrupt handler with a CIA2 timer. It writes `$01` to `$02FF` and turns
25
+ the border green when every synthetic row matches and the register
26
+ readings are consistent, `$02` and red otherwise. The technique is
27
+ `light_pen_read` in `techniques/input.md`.
28
+
29
+ A headless VICE run has no host mouse, and VICE's light pen follows the
30
+ host mouse, so the pen never triggers here: the run measures the resting
31
+ registers, the count of zero and the flag, and says so. The handler's
32
+ cost is measured by entering the same handler from a raster interrupt,
33
+ because nothing in software can pull the pen line low.
34
+
35
+ ## Source
36
+
37
+ ```asm
38
+ // light-pen-read.asm
39
+ // Enables the VIC's light pen interrupt, records the latched LPX/LPY
40
+ // ($D013/$D014) once per frame over NFRAMES frames, counts the pen
41
+ // interrupts, runs a table of synthetic latch values through the
42
+ // pen-delay correction and the two-pixel-unit conversion to a text cell,
43
+ // times the interrupt handler with a CIA2 timer, and reports a verdict at
44
+ // $02FF and in the border colour.
45
+ //
46
+ // The pen is on control port 1: its trigger is the port's FIRE line, CIA1
47
+ // PB4, which is also the VIC's LP input. The KERNAL IRQ is turned off so
48
+ // the keyboard scan cannot drive $DC00 while the port is read.
49
+ .encoding "screencode_upper"
50
+
51
+ .const SCREEN = $0400
52
+ .const RESULT = $02ff
53
+ .const NFRAMES = 300 // frames sampled at rest
54
+ .const READ_LINE = $fa // raster line 250: below the text area, inside both models' frames
55
+ .const PEN_DELAY = 0 // the pen's own latch delay in LPX units; per pen, 0 here
56
+ .const NTESTS = 8 // rows in the synthetic table
57
+ .const COST_LINE = 25 // the raster line that drives the handler for the cost measurement
58
+ .const OFF = $ff // "outside the text area" in the expected columns
59
+
60
+ .const zp_val = $fb // 16-bit value for the decimal printer
61
+ .const zp_row = $fd // screen pointer for the printers
62
+ .const zp_lbl = $f7 // pointer into the label table
63
+ .const zp_fail = $f9
64
+ .const zp_tmp = $fa
65
+
66
+ BasicUpstart2(start)
67
+
68
+ * = $0900 "code"
69
+
70
+ start:
71
+ sei
72
+ lda #$7f
73
+ sta $dc0d // CIA1 interrupts off: no keyboard scan on $DC00
74
+ lda $dc0d // drop a pending one
75
+ lda #$00
76
+ sta $d020
77
+ sta $d021
78
+ sta zp_fail
79
+ jsr clear_screen
80
+ jsr draw_labels
81
+
82
+ lda #<irq
83
+ sta $0314
84
+ lda #>irq
85
+ sta $0315
86
+ lda #$ff
87
+ sta $d019 // acknowledge anything pending
88
+ lda #$08
89
+ sta $d01a // ELP only: the light pen is the one VIC source
90
+ cli
91
+
92
+ // --- part A: NFRAMES frames at rest, the latch read once per frame ------
93
+ lda $d013
94
+ sta first_x
95
+ sta min_x
96
+ sta max_x
97
+ sta last_x
98
+ lda $d014
99
+ sta first_y
100
+ sta min_y
101
+ sta max_y
102
+ sta last_y
103
+ lda #0
104
+ sta chg_x
105
+ sta chg_y
106
+ sta frames
107
+ sta frames+1
108
+ frameloop:
109
+ jsr wait_read_line
110
+ lda $d013
111
+ cmp last_x
112
+ beq !+
113
+ inc chg_x
114
+ !: sta last_x
115
+ cmp min_x
116
+ bcs !+
117
+ sta min_x
118
+ !: lda last_x
119
+ cmp max_x
120
+ bcc !+
121
+ sta max_x
122
+ !: lda $d014
123
+ cmp last_y
124
+ beq !+
125
+ inc chg_y
126
+ !: sta last_y
127
+ cmp min_y
128
+ bcs !+
129
+ sta min_y
130
+ !: lda last_y
131
+ cmp max_y
132
+ bcc !+
133
+ sta max_y
134
+ !: inc frames
135
+ bne !+
136
+ inc frames+1
137
+ !: lda frames
138
+ cmp #<NFRAMES
139
+ bne frameloop
140
+ lda frames+1
141
+ cmp #>NFRAMES
142
+ bne frameloop
143
+
144
+ sei
145
+ lda #$00
146
+ sta $d01a // pen IRQ off; the count is final
147
+ lda irq_count
148
+ sta pen_irqs
149
+ lda irq_count+1
150
+ sta pen_irqs+1
151
+ lda $d019
152
+ sta d019_end // bit 3 set here means a trigger since the last acknowledge
153
+
154
+ lda #<NFRAMES
155
+ sta zp_val
156
+ lda #>NFRAMES
157
+ sta zp_val+1
158
+ ldy #2
159
+ ldx #19
160
+ jsr print_dec5
161
+ lda pen_irqs
162
+ sta zp_val
163
+ lda pen_irqs+1
164
+ sta zp_val+1
165
+ ldy #3
166
+ ldx #19
167
+ jsr print_dec5
168
+ lda first_x
169
+ ldy #4
170
+ ldx #19
171
+ jsr print_hex
172
+ lda min_x
173
+ ldy #4
174
+ ldx #23
175
+ jsr print_hex
176
+ lda max_x
177
+ ldy #4
178
+ ldx #27
179
+ jsr print_hex
180
+ lda first_y
181
+ ldy #5
182
+ ldx #19
183
+ jsr print_hex
184
+ lda min_y
185
+ ldy #5
186
+ ldx #23
187
+ jsr print_hex
188
+ lda max_y
189
+ ldy #5
190
+ ldx #27
191
+ jsr print_hex
192
+ lda chg_x
193
+ ldy #6
194
+ ldx #19
195
+ jsr print_hex
196
+ lda chg_y
197
+ ldy #6
198
+ ldx #27
199
+ jsr print_hex
200
+ lda d019_end
201
+ ldy #7
202
+ ldx #6
203
+ jsr print_hex
204
+ lda $dc01
205
+ ldy #7
206
+ ldx #19
207
+ jsr print_hex
208
+ lda $dc00
209
+ ldy #7
210
+ ldx #32
211
+ jsr print_hex
212
+
213
+ // the consistency rule: the latch does not move at rest, and the pen
214
+ // interrupt count is either the frame count (one trigger a frame, within
215
+ // one) or zero with the flag clear (no trigger at all). Anything between
216
+ // is a pen that triggers on some frames only, and the rule fails.
217
+ lda min_x
218
+ cmp max_x
219
+ bne rest_bad
220
+ lda min_y
221
+ cmp max_y
222
+ bne rest_bad
223
+ lda pen_irqs+1
224
+ ora pen_irqs
225
+ bne count_some
226
+ lda d019_end
227
+ and #$08
228
+ beq rest_ok // zero triggers and no flag: consistent
229
+ bne rest_bad
230
+ count_some:
231
+ sec
232
+ lda #<NFRAMES
233
+ sbc pen_irqs
234
+ sta zp_tmp
235
+ lda #>NFRAMES
236
+ sbc pen_irqs+1
237
+ bne rest_bad // more than 255 apart, or the count exceeds the frames
238
+ lda zp_tmp
239
+ cmp #2
240
+ bcc rest_ok // 0 or 1 frames short: one trigger a frame
241
+ rest_bad:
242
+ inc zp_fail
243
+ rest_ok:
244
+
245
+ // --- part B: synthetic latch values through the conversion ---------------
246
+ ldx #0
247
+ testloop:
248
+ stx tidx
249
+ lda test_lpx,x
250
+ jsr test_row_y
251
+ ldx #2
252
+ jsr print_hex
253
+ ldx tidx
254
+ lda test_lpy,x
255
+ jsr test_row_y
256
+ ldx #7
257
+ jsr print_hex
258
+ ldx tidx
259
+ lda test_lpx,x
260
+ jsr lpx_to_col // A = column or OFF
261
+ sta got_col
262
+ jsr test_row_y
263
+ ldx #12
264
+ jsr print_cell
265
+ ldx tidx
266
+ lda test_lpy,x
267
+ jsr lpy_to_row // A = row or OFF
268
+ sta got_row
269
+ jsr test_row_y
270
+ ldx #16
271
+ jsr print_cell
272
+ ldx tidx
273
+ lda exp_col,x
274
+ jsr test_row_y
275
+ ldx #21
276
+ jsr print_cell
277
+ ldx tidx
278
+ lda exp_row,x
279
+ jsr test_row_y
280
+ ldx #25
281
+ jsr print_cell
282
+ ldx tidx
283
+ lda got_col
284
+ cmp exp_col,x
285
+ bne test_bad
286
+ lda got_row
287
+ cmp exp_row,x
288
+ bne test_bad
289
+ lda #<txt_ok
290
+ ldy #>txt_ok
291
+ bne test_show
292
+ test_bad:
293
+ inc zp_fail
294
+ lda #<txt_bad
295
+ ldy #>txt_bad
296
+ test_show:
297
+ sta zp_lbl
298
+ sty zp_lbl+1
299
+ jsr test_row_y
300
+ ldx #29
301
+ jsr print_str
302
+ ldx tidx
303
+ inx
304
+ cpx #NTESTS
305
+ beq tests_done
306
+ jmp testloop
307
+ tests_done:
308
+
309
+ // --- part C: the handler's cost, measured with CIA2 timer A --------------
310
+ // The pen line cannot be pulsed from software, so the same handler is
311
+ // entered from a raster interrupt on COST_LINE instead: the entry, the
312
+ // KERNAL dispatch, the handler's reads and stores and the exit through
313
+ // $EA81 are the same instructions whichever $D019 bit set. A fixed loop is
314
+ // timed twice from raster line 5 in the top border, where no badline can
315
+ // stretch it: once with no interrupt armed, once with the raster interrupt
316
+ // armed inside the loop's span. The difference is the interrupt's cost.
317
+ lda #$00
318
+ sta $dd0e
319
+ lda #$ff
320
+ sta $dd04
321
+ sta $dd05
322
+ lda #5
323
+ jsr wait_line
324
+ lda #$11 // start, force load, continuous
325
+ sta $dd0e
326
+ jsr fixed_loop
327
+ lda #$00
328
+ sta $dd0e
329
+ sec
330
+ lda #$ff
331
+ sbc $dd04
332
+ sta base_lo
333
+ lda #$ff
334
+ sbc $dd05
335
+ sta base_hi
336
+
337
+ lda #$ff
338
+ sta $dd04
339
+ sta $dd05
340
+ lda #COST_LINE
341
+ sta $d012
342
+ lda $d011
343
+ and #$7f
344
+ sta $d011
345
+ lda #$ff
346
+ sta $d019
347
+ lda #$01
348
+ sta $d01a // ERST: the raster interrupt drives the handler once
349
+ lda #5
350
+ jsr wait_line
351
+ cli
352
+ lda #$11
353
+ sta $dd0e
354
+ jsr fixed_loop
355
+ lda #$00
356
+ sta $dd0e
357
+ sei
358
+ lda #$00
359
+ sta $d01a
360
+ sec
361
+ lda #$ff
362
+ sbc $dd04
363
+ sta cost_lo
364
+ lda #$ff
365
+ sbc $dd05
366
+ sta cost_hi
367
+
368
+ lda base_lo
369
+ sta zp_val
370
+ lda base_hi
371
+ sta zp_val+1
372
+ ldy #21
373
+ ldx #9
374
+ jsr print_dec5
375
+ lda cost_lo
376
+ sta zp_val
377
+ lda cost_hi
378
+ sta zp_val+1
379
+ ldy #21
380
+ ldx #24
381
+ jsr print_dec5
382
+ sec
383
+ lda cost_lo
384
+ sbc base_lo
385
+ sta zp_val
386
+ lda cost_hi
387
+ sbc base_hi
388
+ sta zp_val+1
389
+ ldy #20
390
+ ldx #13
391
+ jsr print_dec5
392
+
393
+ // --- verdict --------------------------------------------------------------
394
+ lda zp_fail
395
+ bne fail
396
+ lda #$01
397
+ sta RESULT
398
+ lda #$05
399
+ sta $d020
400
+ lda #<txt_pass
401
+ ldy #>txt_pass
402
+ jmp verdict
403
+ fail:
404
+ lda #$02
405
+ sta RESULT
406
+ lda #$02
407
+ sta $d020
408
+ lda #<txt_fail
409
+ ldy #>txt_fail
410
+ verdict:
411
+ sta zp_lbl
412
+ sty zp_lbl+1
413
+ ldy #23
414
+ ldx #8
415
+ jsr print_str
416
+ forever:
417
+ jmp forever
418
+
419
+ // --- the handler ------------------------------------------------------------
420
+ // Entered through $0314 after the KERNAL's $FF48 has pushed A, X and Y.
421
+ // Acknowledge every set bit by writing $D019's own value back, copy the
422
+ // latch, count, and leave through the KERNAL's bare exit.
423
+ irq:
424
+ lda $d019
425
+ sta $d019
426
+ lda $d013
427
+ sta pen_x
428
+ lda $d014
429
+ sta pen_y
430
+ inc irq_count
431
+ bne !+
432
+ inc irq_count+1
433
+ !: jmp $ea81
434
+
435
+ // --- the conversion ---------------------------------------------------------
436
+ // lpx_to_col: A = LPX. Subtract the pen's delay, then the latch is X/2 and
437
+ // the text area starts at X = 24, so column = (LPX - 12) / 4. Below 12 or
438
+ // at 40 or more the point is outside the text area and OFF comes back.
439
+ lpx_to_col:
440
+ sec
441
+ sbc #PEN_DELAY
442
+ bcc lpx_off
443
+ sec
444
+ sbc #12
445
+ bcc lpx_off
446
+ lsr
447
+ lsr
448
+ cmp #40
449
+ bcs lpx_off
450
+ rts
451
+ lpx_off:
452
+ lda #OFF
453
+ rts
454
+
455
+ // lpy_to_row: A = LPY, the raster line. The text area is lines 51 to 250,
456
+ // so row = (LPY - 51) / 8; outside that range OFF comes back.
457
+ lpy_to_row:
458
+ sec
459
+ sbc #51
460
+ bcc lpy_off
461
+ cmp #200
462
+ bcs lpy_off
463
+ lsr
464
+ lsr
465
+ lsr
466
+ rts
467
+ lpy_off:
468
+ lda #OFF
469
+ rts
470
+
471
+ // fixed_loop: a loop of fixed length, long enough to span COST_LINE from
472
+ // line 5 on both models. Its own length cancels out of the measurement.
473
+ fixed_loop:
474
+ ldx #2
475
+ ldy #0
476
+ !: dey
477
+ bne !-
478
+ dex
479
+ bne !-
480
+ rts
481
+
482
+ // test_row_y: Y = 11 + tidx, the screen row of the current table entry.
483
+ test_row_y:
484
+ pha
485
+ lda tidx
486
+ clc
487
+ adc #11
488
+ tay
489
+ pla
490
+ rts
491
+
492
+ // wait_read_line: spin until the raster reaches READ_LINE, having first
493
+ // left it, so consecutive calls land in consecutive frames.
494
+ wait_read_line:
495
+ lda #READ_LINE
496
+ wait_line:
497
+ !: cmp $d012
498
+ beq !-
499
+ !: cmp $d012
500
+ bne !-
501
+ rts
502
+
503
+ // --- printers -------------------------------------------------------------
504
+ set_row:
505
+ lda #<SCREEN
506
+ sta zp_row
507
+ lda #>SCREEN
508
+ sta zp_row+1
509
+ tya
510
+ beq set_row_col
511
+ set_row_next:
512
+ lda zp_row
513
+ clc
514
+ adc #40
515
+ sta zp_row
516
+ bcc set_row_dey
517
+ inc zp_row+1
518
+ set_row_dey:
519
+ dey
520
+ bne set_row_next
521
+ set_row_col:
522
+ txa
523
+ clc
524
+ adc zp_row
525
+ sta zp_row
526
+ bcc set_row_done
527
+ inc zp_row+1
528
+ set_row_done:
529
+ rts
530
+
531
+ // print_hex: A = byte, row Y, column X.
532
+ print_hex:
533
+ pha
534
+ jsr set_row
535
+ pla
536
+ pha
537
+ lsr
538
+ lsr
539
+ lsr
540
+ lsr
541
+ tax
542
+ lda hexdigits,x
543
+ ldy #0
544
+ sta (zp_row),y
545
+ pla
546
+ and #$0f
547
+ tax
548
+ lda hexdigits,x
549
+ iny
550
+ sta (zp_row),y
551
+ rts
552
+
553
+ // print_cell: A = 0..99 or OFF, row Y, column X: two digits, or "--".
554
+ print_cell:
555
+ cmp #OFF
556
+ bne print_dec2
557
+ jsr set_row
558
+ lda #$2d
559
+ ldy #0
560
+ sta (zp_row),y
561
+ iny
562
+ sta (zp_row),y
563
+ rts
564
+
565
+ // print_dec2: A = 0..99, row Y, column X: two digits, leading zero.
566
+ print_dec2:
567
+ pha
568
+ jsr set_row
569
+ pla
570
+ ldx #0
571
+ !: cmp #10
572
+ bcc !+
573
+ sbc #10
574
+ inx
575
+ bne !-
576
+ !: pha
577
+ txa
578
+ ora #$30
579
+ ldy #0
580
+ sta (zp_row),y
581
+ pla
582
+ ora #$30
583
+ iny
584
+ sta (zp_row),y
585
+ rts
586
+
587
+ // print_dec5: zp_val = 16-bit value, row Y, column X: five digits.
588
+ print_dec5:
589
+ jsr set_row
590
+ ldy #0
591
+ ldx #0
592
+ dec5_digit:
593
+ lda #$30
594
+ sta digit
595
+ dec5_sub:
596
+ sec
597
+ lda zp_val
598
+ sbc pow10_lo,x
599
+ pha
600
+ lda zp_val+1
601
+ sbc pow10_hi,x
602
+ bcc dec5_next
603
+ sta zp_val+1
604
+ pla
605
+ sta zp_val
606
+ inc digit
607
+ jmp dec5_sub
608
+ dec5_next:
609
+ pla
610
+ lda digit
611
+ sta (zp_row),y
612
+ iny
613
+ inx
614
+ cpx #5
615
+ bne dec5_digit
616
+ rts
617
+
618
+ // print_str: zp_lbl -> zero-terminated screen-code text, row Y, column X.
619
+ print_str:
620
+ jsr set_row
621
+ ldy #0
622
+ !: lda (zp_lbl),y
623
+ beq !+
624
+ sta (zp_row),y
625
+ iny
626
+ bne !-
627
+ !: rts
628
+
629
+ // draw_labels: walk the label table: row, column, text, 0; a row of $ff ends it.
630
+ draw_labels:
631
+ lda #<labels
632
+ sta zp_lbl
633
+ lda #>labels
634
+ sta zp_lbl+1
635
+ label_next:
636
+ ldy #0
637
+ lda (zp_lbl),y
638
+ cmp #$ff
639
+ beq label_done
640
+ iny
641
+ lda (zp_lbl),y
642
+ tax // X = column
643
+ dey
644
+ lda (zp_lbl),y
645
+ tay // Y = row
646
+ lda zp_lbl
647
+ clc
648
+ adc #2
649
+ sta zp_lbl
650
+ bcc !+
651
+ inc zp_lbl+1
652
+ !: jsr print_str
653
+ ldy #0
654
+ !: lda (zp_lbl),y
655
+ beq !+
656
+ iny
657
+ bne !-
658
+ !: iny
659
+ tya
660
+ clc
661
+ adc zp_lbl
662
+ sta zp_lbl
663
+ bcc label_next
664
+ inc zp_lbl+1
665
+ jmp label_next
666
+ label_done:
667
+ rts
668
+
669
+ clear_screen:
670
+ ldx #0
671
+ lda #$20
672
+ !: sta SCREEN,x
673
+ sta SCREEN+$100,x
674
+ sta SCREEN+$200,x
675
+ sta SCREEN+$300,x
676
+ inx
677
+ bne !-
678
+ rts
679
+
680
+ // --- data -----------------------------------------------------------------
681
+ labels:
682
+ .byte 0, 0
683
+ .text "LIGHT PEN READ, CONTROL PORT 1"
684
+ .byte 0
685
+ .byte 2, 0
686
+ .text "FRAMES SAMPLED"
687
+ .byte 0
688
+ .byte 3, 0
689
+ .text "PEN IRQS COUNTED"
690
+ .byte 0
691
+ .byte 4, 0
692
+ .text "LPX FIRST MIN MAX"
693
+ .byte 0
694
+ .byte 5, 0
695
+ .text "LPY FIRST MIN MAX"
696
+ .byte 0
697
+ .byte 6, 0
698
+ .text "FRAMES LPX MOVED"
699
+ .byte 0
700
+ .byte 6, 23
701
+ .text "LPY"
702
+ .byte 0
703
+ .byte 7, 0
704
+ .text "$D019"
705
+ .byte 0
706
+ .byte 7, 13
707
+ .text "$DC01"
708
+ .byte 0
709
+ .byte 7, 26
710
+ .text "$DC00"
711
+ .byte 0
712
+ .byte 9, 0
713
+ .text "SYNTHETIC LATCH TO TEXT CELL"
714
+ .byte 0
715
+ .byte 10, 0
716
+ .text " LPX LPY COL ROW EXPECTED"
717
+ .byte 0
718
+ .byte 20, 0
719
+ .text "IRQ COST"
720
+ .byte 0
721
+ .byte 20, 19
722
+ .text "CYCLES VIA RASTER"
723
+ .byte 0
724
+ .byte 21, 0
725
+ .text "BASELINE"
726
+ .byte 0
727
+ .byte 21, 15
728
+ .text "WITH IRQ"
729
+ .byte 0
730
+ .byte 23, 0
731
+ .text "RESULT"
732
+ .byte 0
733
+ .byte $ff
734
+
735
+ txt_ok: .text "OK"
736
+ .byte 0
737
+ txt_bad: .text "BAD"
738
+ .byte 0
739
+ txt_pass: .text "PASS"
740
+ .byte 0
741
+ txt_fail: .text "FAIL"
742
+ .byte 0
743
+ hexdigits: .text "0123456789ABCDEF"
744
+ pow10_lo: .byte <10000, <1000, <100, <10, <1
745
+ pow10_hi: .byte >10000, >1000, >100, >10, >1
746
+
747
+ // the synthetic table: latch values and the cell each should land in.
748
+ // $0C,$33 is the top-left corner of the text area; $AB,$FA the bottom-right;
749
+ // $AC,$FB one step past it; $0B,$32 one step before it; $00,$00 the value a
750
+ // pen that never triggered leaves in the registers.
751
+ test_lpx: .byte $0c, $0f, $10, $5c, $ab, $ac, $0b, $00
752
+ test_lpy: .byte $33, $3a, $3b, $95, $fa, $fb, $32, $00
753
+ exp_col: .byte 0, 0, 1, 20, 39, OFF, OFF, OFF
754
+ exp_row: .byte 0, 0, 1, 12, 24, OFF, OFF, OFF
755
+
756
+ digit: .byte 0
757
+ tidx: .byte 0
758
+ got_col: .byte 0
759
+ got_row: .byte 0
760
+ irq_count: .word 0
761
+ pen_irqs: .word 0
762
+ frames: .word 0
763
+ pen_x: .byte 0
764
+ pen_y: .byte 0
765
+ first_x: .byte 0
766
+ min_x: .byte 0
767
+ max_x: .byte 0
768
+ last_x: .byte 0
769
+ first_y: .byte 0
770
+ min_y: .byte 0
771
+ max_y: .byte 0
772
+ last_y: .byte 0
773
+ chg_x: .byte 0
774
+ chg_y: .byte 0
775
+ d019_end: .byte 0
776
+ base_lo: .byte 0
777
+ base_hi: .byte 0
778
+ cost_lo: .byte 0
779
+ cost_hi: .byte 0
780
+ ```
781
+
782
+ ## Build
783
+
784
+ ```bash
785
+ java -jar $KICKASS_JAR light-pen-read.asm -o light-pen-read.prg
786
+ ```
787
+
788
+ KickAssembler 5.25 produces a 1,785-byte PRG; the code segment runs
789
+ `$0900` to `$0EF7`.
790
+
791
+ Pinned VICE run (both models, `docs/recipes/runs.json`):
792
+
793
+ ```bash
794
+ GSETTINGS_SCHEMA_DIR=/opt/homebrew/share/glib-2.0/schemas \
795
+ x64sc -default -warp +sound +autostart-delay-random -autostartprgmode 1 \
796
+ -limitcycles 12000000 -controlport1device 11 \
797
+ -exitscreenshot light-pen-read.png -autostart light-pen-read.prg
798
+ ```
799
+
800
+ Add `-model ntsc` for the second picture. `-controlport1device 11` is
801
+ VICE's "Light Pen (up trigger)" on control port 1; `x64sc -help` (VICE
802
+ 3.10) lists six pen and gun devices for port 1, numbers 11 to 16, and
803
+ none for port 2. Nothing is attached to port 2.
804
+
805
+ ## Expected output
806
+
807
+ Green border, black background, light blue text. The screen is:
808
+
809
+ ```text
810
+ row 0 LIGHT PEN READ, CONTROL PORT 1
811
+ row 2 FRAMES SAMPLED 00300
812
+ row 3 PEN IRQS COUNTED 00000
813
+ row 4 LPX FIRST MIN MAX 00 00 00
814
+ row 5 LPY FIRST MIN MAX 00 00 00
815
+ row 6 FRAMES LPX MOVED 00 LPY 00
816
+ row 7 $D019 71 $DC01 FF $DC00 7F
817
+ row 9 SYNTHETIC LATCH TO TEXT CELL
818
+ row 10 LPX LPY COL ROW EXPECTED
819
+ row 11 0C 33 00 00 00 00 OK
820
+ row 12 0F 3A 00 00 00 00 OK
821
+ row 13 10 3B 01 01 01 01 OK
822
+ row 14 5C 95 20 12 20 12 OK
823
+ row 15 AB FA 39 24 39 24 OK
824
+ row 16 AC FB -- -- -- -- OK
825
+ row 17 0B 32 -- -- -- -- OK
826
+ row 18 00 00 -- -- -- -- OK
827
+ row 20 IRQ COST 00094 CYCLES VIA RASTER
828
+ row 21 BASELINE 02588 WITH IRQ 02682
829
+ row 23 RESULT PASS
830
+ ```
831
+
832
+ `recipes/kickassembler/screenshots/light-pen-read.png` (PAL, 384 by
833
+ 272) and `light-pen-read-ntsc.png` (NTSC, 384 by 247) were each produced
834
+ twice by the pinned command with identical bytes, and decoded by
835
+ matching every 8 by 8 cell against `chargen-901225-01.bin` (measured in
836
+ VICE x64sc 3.10, rung 1). Every row is the same on both models except
837
+ row 7, where NTSC reads `$D019 70`.
838
+
839
+ What each line shows:
840
+
841
+ - Rows 3 to 6: over 300 frames the pen interrupt fired zero times and
842
+ `$D013` and `$D014` read `$00` on every frame, first, lowest and
843
+ highest, on both models. VICE's light pen takes its position from the
844
+ host mouse, and a headless run has none to move, so the emulated pen
845
+ never triggers. The same zeros came from device 11, the Datel pen
846
+ (13), the Magnum Light Phaser (14) and the Inkwell pen (16) in a
847
+ diagnostic build, PAL and NTSC. What a triggering pen latches, and the
848
+ spread of the latch from frame to frame, is not measured here.
849
+ - Row 7: `$D019` reads `$71` on PAL and `$70` on NTSC after the pen
850
+ interrupt was disabled. Bit 3, the pen flag, is clear on both: no
851
+ trigger happened since the handler's last acknowledge, which agrees
852
+ with the count. Bit 0 is the raster flag; it reads set on PAL and
853
+ clear on NTSC in these runs, nothing in this program arms it before
854
+ that read, and why the two models differ is not established here.
855
+ Bits 4 to 6 are unused and read as ones. `$DC01` is port 1's
856
+ switch byte and reads `$FF`: bit 4, FIRE, is the pen's trigger line
857
+ and is high, not pressed. `$DC00` reads `$7F`, the column pattern the
858
+ KERNAL's last scan left before the CIA1 interrupt was turned off.
859
+ - Rows 11 to 18: the synthetic table, compiled in, so these rows would
860
+ be the same with no pen attached. Each row is an LPX and LPY value,
861
+ the column and row `lpx_to_col` and `lpy_to_row` computed, the
862
+ expected pair, and `OK` when they match. `--` is outside the text
863
+ area. Rows 11 and 15 are the two corners of the 40 by 25 area; rows 16
864
+ and 17 are one step outside each; row 18 is what a pen that never
865
+ triggered leaves, and it lands outside, so a program that converts
866
+ blindly still draws nothing.
867
+ - Rows 20 and 21: the interrupt's whole cost, 94 cycles on both models,
868
+ as the difference between two CIA2 timer A readings around the same
869
+ fixed loop started on raster line 5, once with no interrupt armed
870
+ (2,588) and once with a raster interrupt on line 25 entering the same
871
+ handler (2,682). The figure matches the instruction arithmetic: 7 for
872
+ the interrupt sequence, 29 for the KERNAL's dispatcher from `$FF48`
873
+ to the `$0314` vector, 36 for the handler's nine instructions and 22
874
+ for the exit through `$EA81` (rung 3, agreeing with the rung 1
875
+ measurement). The loop runs in the top border, so no badline is inside
876
+ either window.
877
+
878
+ The pass needs all eight table rows to match and the consistency rule to
879
+ hold: the lowest and highest latch on each axis are equal, and the pen
880
+ interrupt count is either the frame count within one, or zero with bit 3
881
+ of `$D019` clear. A count between those, a pen that triggers on some
882
+ frames only, fails it, and so does a latch that moved.
883
+
884
+ The trigger could not be driven by another route. VICE's joystick
885
+ autofire on port 1 (`-joystick1autofire -joystick1autofiremode 1`) pulls
886
+ the same FIRE line, but it starts at power-up: the KERNAL's keyboard scan
887
+ reads PB4 low as a key in matrix row 4, the autostart's typed `RUN` never
888
+ arrives, and the screen fills with `>` characters at 50 presses a second
889
+ and shows one at 1 per second. The program did not run in either case,
890
+ so whether VICE latches the beam position for a joystick fire press is
891
+ not measured here.
892
+
893
+ ## Why this works
894
+
895
+ The VIC latches its horizontal counter, divided by two, into `$D013` and
896
+ the low eight bits of its raster counter into `$D014` when the LP pin
897
+ goes low, and sets bit 3 of `$D019`; with bit 3 of `$D01A` set that
898
+ raises an interrupt. The LP pin is CIA1 PB4, control port 1's FIRE line,
899
+ which is why the pen goes in port 1 and why a joystick fire press there
900
+ latches a position too. The latch takes the first edge of a frame only
901
+ and is reset in the vertical blank, so one read per frame sees
902
+ everything there is (`hardware/vic-ii-reference.md`, "Light pen
903
+ latch"). The handler here acknowledges by writing `$D019`'s own value
904
+ back, which clears every bit that was set and nothing else, copies the
905
+ two registers and counts.
906
+
907
+ The conversion is arithmetic on the hardware page's statements. LPX is
908
+ X/2, the text area starts at X = 24 (sprite coordinates), and a column
909
+ is eight pixels wide, so the column is (LPX - 12) / 4 once the pen's own
910
+ delay has been subtracted; the text area's 200 lines start at raster
911
+ line 51, so the row is (LPY - 51) / 8. A pen reports the beam a little
912
+ after the beam lit the phosphor under it, which shows as a constant
913
+ added to LPX; `PEN_DELAY` is that constant in LPX units, set per pen by
914
+ asking the user to touch a known cell, and left at zero here because no
915
+ pen was available to calibrate. Both routines return `$FF` for a point
916
+ outside the area, and the row-18 case shows why that matters.
917
+
918
+ The CIA1 interrupt is turned off first, so the KERNAL's keyboard scan
919
+ never drives `$DC00` while the port is read: a held key in a driven
920
+ column pulls a row line low on `$DC01`, and the pen's trigger is one of
921
+ those row lines (`pitfalls/input.md`, `joystick2_scan_phantom_press`,
922
+ for the port-1 form of the hazard). The cost measurement uses a raster
923
+ interrupt because the pen line cannot be pulled low by software; the
924
+ entry, the dispatcher, the handler and the exit are the same
925
+ instructions whichever bit of `$D019` set, so the 94 cycles are the
926
+ pen interrupt's cost too.