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,1014 @@
1
+ ---
2
+ recipe: sqrt-atan2
3
+ toolchain: kickassembler
4
+ output_format: PRG
5
+ region: both
6
+ techniques: [isqrt_16bit, atan2_8bit]
7
+ file_formats: [PRG]
8
+ uses_registers: [DC04, DC05, DC0D, DC0E, D011, D012, D020, D021]
9
+ uses_kernal: []
10
+ ---
11
+
12
+ <!-- doc-type: recipe -->
13
+
14
+ # KickAssembler — Integer square root and 8-bit atan2, checked against a host model and timed over every input
15
+
16
+ ## Synopsis
17
+
18
+ Two routines a game needs for distance and aim: `isqrt16`, the integer
19
+ square root of a 16-bit value with an 8-bit result, by restoring
20
+ shift-and-subtract; and `atan2_8`, the angle of a signed 8-bit `(dx, dy)`
21
+ in 256ths of a turn, by folding to the first octant, an eight-pass divide
22
+ for the ratio and a 256-byte arctangent table. The program checks 35
23
+ square roots (0, 1, 65535, perfect squares and their neighbours) and 36
24
+ angles (both axes in both directions, every octant, the diagonals, the
25
+ three worst pairs the host model found) against expected values compiled
26
+ in from the Python script below, then times every one of the 65,536
27
+ inputs of each routine with CIA1 timer A and prints the worst body cost
28
+ and the input that produced it. For the square root it also checks
29
+ `rem <= 2 * root` on every input, which is `n < (root + 1)^2`. It writes
30
+ `$01` to `$02FF` and turns the border green when every case is within
31
+ tolerance (0 for the root, 1 angle unit for atan2), `$02` and red
32
+ otherwise. The techniques are `isqrt_16bit` and `atan2_8bit` in
33
+ `techniques/maths.md`.
34
+
35
+ Angle convention: 0 is `+dx` (right), 64 is `+dy` (down on a screen whose
36
+ y grows downward), 128 is `-dx`, 192 is `-dy`; the exact value is
37
+ `round(atan2(dy, dx) * 256 / 2pi) mod 256`.
38
+
39
+ ## Source
40
+
41
+ ```asm
42
+ // sqrt-atan2.asm
43
+ // Integer square root of a 16-bit value (8-bit result) by shift-and-subtract,
44
+ // and an 8-bit atan2 (signed 8-bit dx, dy in; angle 0-255 out) by octant
45
+ // folding, an 8-pass divide for the ratio and a 256-byte arctangent table.
46
+ // Both are checked against compiled-in expected values from a Python model
47
+ // (the generator is quoted on the page), every input of each routine is timed
48
+ // with CIA1 timer A, and the largest body cost of each routine is printed.
49
+ // Verdict: $02FF = $01 and a green border when every case is within
50
+ // tolerance, $02 and red otherwise.
51
+ //
52
+ // Angle convention: 0 = +dx (right), 64 = +dy (down on a screen whose y grows
53
+ // downward), 128 = -dx, 192 = -dy. Exact value = round(atan2(dy, dx) * 256 / 2pi).
54
+ .encoding "screencode_upper"
55
+
56
+ .const SCREEN = $0400
57
+ .const COLRAM = $d800
58
+ .const RESULT = $02ff
59
+ .const SQ_TOL = 0 // isqrt must be exact
60
+ .const AT_TOL = 1 // atan2 within one angle unit (1/256 turn)
61
+ .const NSQ = 35 // check cases, from the generator
62
+ .const NAT = 36
63
+
64
+ // zero page scratch; the program never returns to BASIC
65
+ .const num = $f7 // isqrt input, shifted out (2 bytes)
66
+ .const rem = $f9 // isqrt remainder (2 bytes)
67
+ .const root = $fb // isqrt result
68
+ .const trial = $fc // isqrt trial subtrahend (2 bytes)
69
+ .const arg_dx = $02 // atan2 inputs
70
+ .const arg_dy = $03
71
+ .const ax = $04 // |dx|, |dy|
72
+ .const ay = $05
73
+ .const quo = $06 // divide quotient / table index
74
+ .const angle = $07 // atan2 result
75
+ .const tmp = $08
76
+ .const zp_val = $09 // 16-bit value for the decimal printer
77
+ .const zp_row = $0b // screen pointer for the printers (2 bytes)
78
+ .const cyc = $0d // last measured cycle count (2 bytes)
79
+ .const str_ptr = $0f // string pointer for print_str (2 bytes)
80
+ .const chk = $11 // 2 * root for the remainder invariant (2 bytes)
81
+ .const n_cnt = $13 // sweep counter (2 bytes)
82
+
83
+ BasicUpstart2(start)
84
+
85
+ start:
86
+ sei
87
+ lda #$7f
88
+ sta $dc0d // no CIA1 interrupts
89
+ lda $dc0d
90
+ lda #0
91
+ sta $d020
92
+ sta $d021
93
+ jsr clear_screen
94
+ lda $d011
95
+ and #%11101111 // DEN off: VIC samples it on line $30, so the
96
+ sta $d011 // badlines stop from the next frame on
97
+ jsr wait_line255
98
+ jsr wait_line255
99
+ jsr time_empty // jsr/rts and timer overhead, measured once
100
+
101
+ ldy #0
102
+ ldx #<txt_hdr
103
+ lda #>txt_hdr
104
+ jsr print_str
105
+
106
+ // ---------- isqrt cases ----------
107
+ lda #0
108
+ sta sq_fail
109
+ sta sq_maxerr
110
+ ldx #0
111
+ sq_loop:
112
+ stx case_idx
113
+ lda sq_in_lo,x
114
+ sta num
115
+ lda sq_in_hi,x
116
+ sta num+1
117
+ jsr isqrt16
118
+ ldx case_idx
119
+ lda root
120
+ sec
121
+ sbc sq_exp,x
122
+ bcs !+
123
+ eor #$ff // negate: |root - expected|
124
+ adc #1
125
+ !: cmp sq_maxerr
126
+ bcc !+
127
+ sta sq_maxerr
128
+ !: cmp #SQ_TOL+1
129
+ bcc !+
130
+ inc sq_fail
131
+ !: inx
132
+ cpx #NSQ
133
+ bne sq_loop
134
+
135
+ // ---------- atan2 cases ----------
136
+ lda #0
137
+ sta at_fail
138
+ sta at_maxerr
139
+ ldx #0
140
+ at_loop:
141
+ stx case_idx
142
+ lda at_dx,x
143
+ sta arg_dx
144
+ lda at_dy,x
145
+ sta arg_dy
146
+ jsr atan2_8
147
+ ldx case_idx
148
+ lda angle
149
+ sec
150
+ sbc at_exp,x // difference modulo 256
151
+ cmp #$80
152
+ bcc !+
153
+ eor #$ff // wrap: 255 -> 1
154
+ clc
155
+ adc #1
156
+ !: cmp at_maxerr
157
+ bcc !+
158
+ sta at_maxerr
159
+ !: cmp #AT_TOL+1
160
+ bcc !+
161
+ inc at_fail
162
+ !: inx
163
+ cpx #NAT
164
+ bne at_loop
165
+
166
+ // ---------- isqrt sweep: every input, timed, remainder invariant ----------
167
+ lda #0
168
+ sta n_cnt
169
+ sta n_cnt+1
170
+ sta sq_maxcyc
171
+ sta sq_maxcyc+1
172
+ sta inv_fail
173
+ sta inv_fail+1
174
+ sw_sq:
175
+ lda n_cnt
176
+ sta num
177
+ lda n_cnt+1
178
+ sta num+1
179
+ jsr time_isqrt
180
+ lda cyc+1
181
+ cmp sq_maxcyc+1
182
+ bcc sw_sq_inv
183
+ bne sw_sq_new
184
+ lda cyc
185
+ cmp sq_maxcyc
186
+ bcc sw_sq_inv
187
+ beq sw_sq_inv // keep the first input that reached the max
188
+ sw_sq_new:
189
+ lda cyc
190
+ sta sq_maxcyc
191
+ lda cyc+1
192
+ sta sq_maxcyc+1
193
+ lda n_cnt
194
+ sta sq_maxarg
195
+ lda n_cnt+1
196
+ sta sq_maxarg+1
197
+ sw_sq_inv:
198
+ lda root // n < (root + 1)^2 <=> rem <= 2 * root
199
+ asl
200
+ sta chk
201
+ lda #0
202
+ rol
203
+ sta chk+1
204
+ lda chk
205
+ cmp rem
206
+ lda chk+1
207
+ sbc rem+1
208
+ bcs !+
209
+ inc inv_fail
210
+ bne !+
211
+ inc inv_fail+1
212
+ !: inc n_cnt
213
+ bne sw_sq
214
+ inc n_cnt+1
215
+ bne sw_sq
216
+
217
+ // ---------- atan2 sweep: every (dx, dy) pair, timed ----------
218
+ lda #0
219
+ sta at_maxcyc
220
+ sta at_maxcyc+1
221
+ sta arg_dx
222
+ sw_at_x:
223
+ lda #0
224
+ sta arg_dy
225
+ sw_at_y:
226
+ jsr time_atan2
227
+ lda cyc+1
228
+ cmp at_maxcyc+1
229
+ bcc sw_at_next
230
+ bne sw_at_new
231
+ lda cyc
232
+ cmp at_maxcyc
233
+ bcc sw_at_next
234
+ beq sw_at_next
235
+ sw_at_new:
236
+ lda cyc
237
+ sta at_maxcyc
238
+ lda cyc+1
239
+ sta at_maxcyc+1
240
+ lda arg_dx
241
+ sta at_maxarg
242
+ lda arg_dy
243
+ sta at_maxarg+1
244
+ sw_at_next:
245
+ inc arg_dy
246
+ bne sw_at_y
247
+ inc arg_dx
248
+ bne sw_at_x
249
+
250
+ // ---------- report ----------
251
+ ldy #2
252
+ ldx #<txt_sq
253
+ lda #>txt_sq
254
+ jsr print_str
255
+ lda #NSQ
256
+ ldx #12
257
+ ldy #2
258
+ jsr print_dec3
259
+ lda sq_maxerr
260
+ ldx #25
261
+ ldy #2
262
+ jsr print_dec3
263
+ lda sq_fail
264
+ ldx #35
265
+ ldy #2
266
+ jsr print_dec3
267
+
268
+ ldy #3
269
+ ldx #<txt_at
270
+ lda #>txt_at
271
+ jsr print_str
272
+ lda #NAT
273
+ ldx #12
274
+ ldy #3
275
+ jsr print_dec3
276
+ lda at_maxerr
277
+ ldx #25
278
+ ldy #3
279
+ jsr print_dec3
280
+ lda at_fail
281
+ ldx #35
282
+ ldy #3
283
+ jsr print_dec3
284
+
285
+ ldy #5
286
+ ldx #<txt_cyc
287
+ lda #>txt_cyc
288
+ jsr print_str
289
+ ldy #6
290
+ ldx #<txt_cyc_sq
291
+ lda #>txt_cyc_sq
292
+ jsr print_str
293
+ lda sq_maxcyc
294
+ sta zp_val
295
+ lda sq_maxcyc+1
296
+ sta zp_val+1
297
+ ldx #20
298
+ ldy #6
299
+ jsr print_dec5
300
+ lda sq_maxarg
301
+ sta zp_val
302
+ lda sq_maxarg+1
303
+ sta zp_val+1
304
+ ldx #30
305
+ ldy #6
306
+ jsr print_dec5
307
+ ldy #7
308
+ ldx #<txt_cyc_at
309
+ lda #>txt_cyc_at
310
+ jsr print_str
311
+ lda at_maxcyc
312
+ sta zp_val
313
+ lda at_maxcyc+1
314
+ sta zp_val+1
315
+ ldx #20
316
+ ldy #7
317
+ jsr print_dec5
318
+ lda at_maxarg
319
+ ldx #30
320
+ ldy #7
321
+ jsr print_hex2
322
+ lda at_maxarg+1
323
+ ldx #34
324
+ ldy #7
325
+ jsr print_hex2
326
+ ldy #8
327
+ ldx #<txt_inv
328
+ lda #>txt_inv
329
+ jsr print_str
330
+ lda inv_fail
331
+ sta zp_val
332
+ lda inv_fail+1
333
+ sta zp_val+1
334
+ ldx #30
335
+ ldy #8
336
+ jsr print_dec5
337
+
338
+ // sample results on one line each: sqrt(65535), atan2(10,3)
339
+ ldy #9
340
+ ldx #<txt_s1
341
+ lda #>txt_s1
342
+ jsr print_str
343
+ lda #$ff
344
+ sta num
345
+ sta num+1
346
+ jsr isqrt16
347
+ lda root
348
+ ldx #20
349
+ ldy #9
350
+ jsr print_dec3
351
+ ldy #10
352
+ ldx #<txt_s2
353
+ lda #>txt_s2
354
+ jsr print_str
355
+ lda #10
356
+ sta arg_dx
357
+ lda #3
358
+ sta arg_dy
359
+ jsr atan2_8
360
+ lda angle
361
+ ldx #20
362
+ ldy #10
363
+ jsr print_dec3
364
+
365
+ lda $d011
366
+ ora #%00010000 // DEN back on for the picture
367
+ sta $d011
368
+
369
+ // ---------- verdict ----------
370
+ lda sq_fail
371
+ ora at_fail
372
+ bne fail
373
+ lda #1
374
+ sta RESULT
375
+ lda #5
376
+ sta $d020
377
+ ldy #12
378
+ ldx #<txt_pass
379
+ lda #>txt_pass
380
+ jsr print_str
381
+ jmp forever
382
+ fail:
383
+ lda #2
384
+ sta RESULT
385
+ sta $d020
386
+ ldy #12
387
+ ldx #<txt_fail
388
+ lda #>txt_fail
389
+ jsr print_str
390
+ forever:
391
+ jmp forever
392
+
393
+ // ============================================================
394
+ // isqrt16: root = floor(sqrt(num)), num is destroyed, rem = num - root*root.
395
+ // Restoring shift-and-subtract, two input bits per pass, eight passes.
396
+ // Both routines sit in one page so no taken branch pays a page-crossing
397
+ // cycle; the assert below fails the build if a change pushes them over.
398
+ // ============================================================
399
+ .align $100
400
+ isqrt16:
401
+ lda #0
402
+ sta root
403
+ sta rem
404
+ sta rem+1
405
+ ldx #8
406
+ sq_pass:
407
+ asl num // bring down the next two bits of num
408
+ rol num+1
409
+ rol rem
410
+ rol rem+1
411
+ asl num
412
+ rol num+1
413
+ rol rem
414
+ rol rem+1
415
+ lda root // trial = 4 * root + 1; root = 2 * root
416
+ asl
417
+ sta root
418
+ asl
419
+ ora #1
420
+ sta trial
421
+ lda #0
422
+ rol // carry out of the second asl is bit 8 of trial
423
+ sta trial+1
424
+ lda rem+1 // if rem >= trial: rem -= trial, root |= 1
425
+ cmp trial+1
426
+ bcc sq_next
427
+ bne sq_sub
428
+ lda rem
429
+ cmp trial
430
+ bcc sq_next
431
+ sq_sub:
432
+ lda rem
433
+ sbc trial // carry is set on both paths into sq_sub
434
+ sta rem
435
+ lda rem+1
436
+ sbc trial+1
437
+ sta rem+1
438
+ inc root
439
+ sq_next:
440
+ dex
441
+ bne sq_pass
442
+ rts
443
+
444
+ // ============================================================
445
+ // atan2_8: angle = atan2(arg_dy, arg_dx) in 1/256 turn, 0 for (0, 0).
446
+ // Fold to the first octant on the sign bits and a magnitude compare,
447
+ // index the table with floor(min * 256 / max) from an 8-pass divide,
448
+ // then unfold: 64 - a across the diagonal, 128 - a for dx < 0, -a for dy < 0.
449
+ // ============================================================
450
+ atan2_8:
451
+ lda arg_dx
452
+ bpl !+ // sign from bit 7 of the input, no subtract involved
453
+ eor #$ff
454
+ clc
455
+ adc #1
456
+ !: sta ax // 0..128 as an unsigned byte
457
+ lda arg_dy
458
+ bpl !+
459
+ eor #$ff
460
+ clc
461
+ adc #1
462
+ !: sta ay
463
+ ora ax
464
+ bne !+
465
+ sta angle // both zero: angle 0, nothing to divide by
466
+ rts
467
+ !: lda ay
468
+ cmp ax
469
+ beq at_diag
470
+ bcc at_low // ay < ax: first octant, ratio ay / ax
471
+ lda ax // ay > ax: second octant, ratio ax / ay
472
+ ldx ay
473
+ jsr ratio_div
474
+ lda #64
475
+ sec
476
+ sbc quo
477
+ jmp at_fold
478
+ at_diag:
479
+ lda #32
480
+ bne at_fold
481
+ at_low:
482
+ lda ay
483
+ ldx ax
484
+ jsr ratio_div
485
+ lda quo
486
+ at_fold:
487
+ bit arg_dx
488
+ bpl !+
489
+ eor #$ff // 128 - a == -(a) + 128 == (a ^ $ff) + 129
490
+ clc
491
+ adc #129
492
+ !: bit arg_dy
493
+ bpl !+
494
+ eor #$ff // 256 - a == (a ^ $ff) + 1
495
+ clc
496
+ adc #1
497
+ !: sta angle
498
+ rts
499
+
500
+ // ratio_div: quo = atan_tab[ floor(A * 256 / X) ], A < X <= 128.
501
+ // Eight shift-and-subtract passes; the remainder starts as A and stays below
502
+ // X, so its doubled value fits a byte and no ninth-bit test is needed.
503
+ ratio_div:
504
+ stx tmp
505
+ sta rem // remainder starts at the numerator
506
+ lda #0
507
+ sta quo
508
+ ldx #8
509
+ rd_pass:
510
+ asl quo // shift a zero dividend bit up into the remainder
511
+ rol rem
512
+ lda rem
513
+ cmp tmp
514
+ bcc rd_next
515
+ sbc tmp // carry set by the compare
516
+ sta rem
517
+ inc quo
518
+ rd_next:
519
+ dex
520
+ bne rd_pass
521
+ ldx quo
522
+ lda atan_tab,x
523
+ sta quo
524
+ rts
525
+ routines_end:
526
+ .assert "isqrt16 and atan2_8 share one page", >isqrt16, >routines_end
527
+
528
+ // ============================================================
529
+ // timing: CIA1 timer A, one-shot, force-loaded from $FFFF, display off so
530
+ // no badline steals cycles. cyc = body cycles: jsr, rts and the timer
531
+ // start/stop overhead are measured with an empty routine and subtracted.
532
+ // ============================================================
533
+ time_isqrt:
534
+ lda #$ff
535
+ sta $dc04
536
+ sta $dc05
537
+ lda #%00011001 // load, one-shot, start
538
+ sta $dc0e
539
+ jsr isqrt16
540
+ lda #0
541
+ sta $dc0e
542
+ jmp time_finish
543
+
544
+ time_atan2:
545
+ lda #$ff
546
+ sta $dc04
547
+ sta $dc05
548
+ lda #%00011001
549
+ sta $dc0e
550
+ jsr atan2_8
551
+ lda #0
552
+ sta $dc0e
553
+ jmp time_finish
554
+
555
+ time_empty:
556
+ lda #$ff
557
+ sta $dc04
558
+ sta $dc05
559
+ lda #%00011001
560
+ sta $dc0e
561
+ jsr empty_rts
562
+ lda #0
563
+ sta $dc0e
564
+ lda $dc04
565
+ sta empty_lo
566
+ lda $dc05
567
+ sta empty_hi
568
+ rts
569
+
570
+ empty_rts:
571
+ rts
572
+
573
+ time_finish:
574
+ // cyc = ($FFFF - timer) - ($FFFF - empty) = empty - timer
575
+ lda empty_lo
576
+ sec
577
+ sbc $dc04
578
+ sta cyc
579
+ lda empty_hi
580
+ sbc $dc05
581
+ sta cyc+1
582
+ rts
583
+
584
+ // wait_line255: returns just after raster line 255 has passed, so two calls
585
+ // span a whole frame and the VIC has seen DEN clear on line $30.
586
+ wait_line255:
587
+ lda #$ff
588
+ !: cmp $d012
589
+ bne !-
590
+ !: cmp $d012
591
+ beq !-
592
+ rts
593
+
594
+ // ============================================================
595
+ // screen helpers
596
+ // ============================================================
597
+ clear_screen:
598
+ ldx #0
599
+ lda #$20
600
+ !: sta SCREEN,x
601
+ sta SCREEN+$100,x
602
+ sta SCREEN+$200,x
603
+ sta SCREEN+$300,x
604
+ inx
605
+ bne !-
606
+ lda #1
607
+ !: sta COLRAM,x
608
+ sta COLRAM+$100,x
609
+ sta COLRAM+$200,x
610
+ sta COLRAM+$300,x
611
+ inx
612
+ bne !-
613
+ rts
614
+
615
+ // set_row: Y = row; zp_row = SCREEN + 40 * Y. Preserves X and A.
616
+ set_row:
617
+ pha
618
+ lda row_lo,y
619
+ sta zp_row
620
+ lda row_hi,y
621
+ sta zp_row+1
622
+ pla
623
+ rts
624
+
625
+ // print_str: X/A = string address (lo/hi), Y = row, zero-terminated, column 0
626
+ print_str:
627
+ stx str_ptr
628
+ sta str_ptr+1
629
+ jsr set_row
630
+ ldy #0
631
+ !: lda (str_ptr),y
632
+ beq !+
633
+ sta (zp_row),y
634
+ iny
635
+ bne !-
636
+ !: rts
637
+
638
+ // print_hex2: A = byte, X = column, Y = row. Two hex digits.
639
+ print_hex2:
640
+ pha
641
+ jsr set_row
642
+ txa
643
+ clc
644
+ adc zp_row
645
+ sta zp_row
646
+ bcc !+
647
+ inc zp_row+1
648
+ !: pla
649
+ pha
650
+ lsr
651
+ lsr
652
+ lsr
653
+ lsr
654
+ tax
655
+ lda hex_scr,x
656
+ ldy #0
657
+ sta (zp_row),y
658
+ pla
659
+ and #15
660
+ tax
661
+ lda hex_scr,x
662
+ iny
663
+ sta (zp_row),y
664
+ rts
665
+ hex_scr: .byte $30, $31, $32, $33, $34, $35, $36, $37, $38, $39, 1, 2, 3, 4, 5, 6
666
+
667
+ // print_dec3: A = byte, X = column, Y = row. Three digits, leading zeros.
668
+ print_dec3:
669
+ sta zp_val
670
+ lda #0
671
+ sta zp_val+1
672
+ jsr set_row
673
+ txa
674
+ clc
675
+ adc zp_row
676
+ sta zp_row
677
+ bcc !+
678
+ inc zp_row+1
679
+ !: ldx #2 // start at the hundreds
680
+ jmp dec_digits
681
+
682
+ // print_dec5: zp_val = 16-bit value, X = column, Y = row. Five digits.
683
+ print_dec5:
684
+ jsr set_row
685
+ txa
686
+ clc
687
+ adc zp_row
688
+ sta zp_row
689
+ bcc !+
690
+ inc zp_row+1
691
+ !: ldx #0
692
+ dec_digits:
693
+ ldy #0
694
+ dd_loop:
695
+ lda #$30
696
+ sta tmp
697
+ dd_sub:
698
+ lda zp_val
699
+ cmp pow_lo,x
700
+ lda zp_val+1
701
+ sbc pow_hi,x
702
+ bcc dd_put
703
+ lda zp_val
704
+ sbc pow_lo,x
705
+ sta zp_val
706
+ lda zp_val+1
707
+ sbc pow_hi,x
708
+ sta zp_val+1
709
+ inc tmp
710
+ bne dd_sub
711
+ dd_put:
712
+ lda tmp
713
+ sta (zp_row),y
714
+ iny
715
+ inx
716
+ cpx #5
717
+ bne dd_loop
718
+ rts
719
+
720
+ pow_lo: .byte <10000, <1000, <100, <10, <1
721
+ pow_hi: .byte >10000, >1000, >100, >10, >1
722
+
723
+ row_lo: .fill 25, <(SCREEN + 40 * i)
724
+ row_hi: .fill 25, >(SCREEN + 40 * i)
725
+
726
+ case_idx: .byte 0
727
+ sq_fail: .byte 0
728
+ sq_maxerr: .byte 0
729
+ sq_maxcyc: .word 0
730
+ sq_maxarg: .word 0
731
+ inv_fail: .word 0
732
+ at_fail: .byte 0
733
+ at_maxerr: .byte 0
734
+ at_maxcyc: .word 0
735
+ at_maxarg: .word 0
736
+ empty_lo: .byte 0
737
+ empty_hi: .byte 0
738
+
739
+ txt_hdr: .text "ISQRT16 AND ATAN2 8-BIT CHECK"
740
+ .byte 0
741
+ txt_sq: .text "SQRT CASES MAX ERR FAIL"
742
+ .byte 0
743
+ txt_at: .text "ATAN2 CASES MAX ERR FAIL"
744
+ .byte 0
745
+ txt_cyc: .text "WORST BODY CYCLES OVER EVERY INPUT:"
746
+ .byte 0
747
+ txt_cyc_sq: .text " ISQRT16 N="
748
+ .byte 0
749
+ txt_cyc_at: .text " ATAN2 $ $"
750
+ .byte 0
751
+ txt_inv: .text " REM<=2*ROOT FAILS OF 65536"
752
+ .byte 0
753
+ txt_s1: .text "SQRT(65535) ="
754
+ .byte 0
755
+ txt_s2: .text "ATAN2(10,3) ="
756
+ .byte 0
757
+ txt_pass: .text "RESULT: PASS"
758
+ .byte 0
759
+ txt_fail: .text "RESULT: FAIL"
760
+ .byte 0
761
+
762
+ // ---- generated by the Python script on the page ----
763
+ sq_in_lo:
764
+ .byte $00, $01, $02, $03, $04, $08, $09, $0f, $10, $11, $18, $19, $3f, $40, $41, $63
765
+ .byte $64, $79, $90, $ff, $00, $01, $e8, $00, $ff, $00, $10, $00, $ff, $00, $00, $01
766
+ .byte $02, $fe, $ff
767
+ sq_in_hi:
768
+ .byte $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00
769
+ .byte $00, $00, $00, $00, $01, $01, $03, $04, $0f, $10, $27, $40, $7f, $80, $fe, $fe
770
+ .byte $fe, $ff, $ff
771
+ sq_exp:
772
+ .byte $00, $01, $01, $01, $02, $02, $03, $03, $04, $04, $04, $05, $07, $08, $08, $09
773
+ .byte $0a, $0b, $0c, $0f, $10, $10, $1f, $20, $3f, $40, $64, $80, $b5, $b5, $fe, $ff
774
+ .byte $ff, $ff, $ff
775
+ at_dx:
776
+ .byte $01, $00, $ff, $00, $7f, $00, $80, $00, $0a, $03, $fd, $f6, $f6, $fd, $03, $0a
777
+ .byte $05, $fb, $fb, $05, $7f, $80, $7f, $80, $01, $02, $01, $ff, $64, $c0, $2d, $88
778
+ .byte $00, $81, $81, $81
779
+ at_dy:
780
+ .byte $00, $01, $00, $ff, $00, $7f, $00, $80, $03, $0a, $0a, $03, $fd, $f6, $f6, $fd
781
+ .byte $05, $05, $fb, $fb, $7f, $80, $80, $7f, $01, $01, $02, $fe, $db, $14, $a6, $f9
782
+ .byte $00, $84, $8a, $95
783
+ at_exp:
784
+ .byte $00, $40, $80, $c0, $00, $40, $80, $c0, $0c, $34, $4c, $74, $8c, $b4, $cc, $f4
785
+ .byte $20, $60, $a0, $e0, $20, $a0, $e0, $60, $20, $13, $2d, $ad, $f2, $74, $d3, $82
786
+ .byte $00, $a0, $9f, $9d
787
+ .align $100
788
+ atan_tab:
789
+ .byte $00, $00, $00, $00, $01, $01, $01, $01, $01, $01, $02, $02, $02, $02, $02, $02
790
+ .byte $03, $03, $03, $03, $03, $03, $03, $04, $04, $04, $04, $04, $04, $05, $05, $05
791
+ .byte $05, $05, $05, $06, $06, $06, $06, $06, $06, $06, $07, $07, $07, $07, $07, $07
792
+ .byte $08, $08, $08, $08, $08, $08, $08, $09, $09, $09, $09, $09, $09, $0a, $0a, $0a
793
+ .byte $0a, $0a, $0a, $0a, $0b, $0b, $0b, $0b, $0b, $0b, $0b, $0c, $0c, $0c, $0c, $0c
794
+ .byte $0c, $0c, $0d, $0d, $0d, $0d, $0d, $0d, $0d, $0e, $0e, $0e, $0e, $0e, $0e, $0e
795
+ .byte $0f, $0f, $0f, $0f, $0f, $0f, $0f, $10, $10, $10, $10, $10, $10, $10, $11, $11
796
+ .byte $11, $11, $11, $11, $11, $11, $12, $12, $12, $12, $12, $12, $12, $13, $13, $13
797
+ .byte $13, $13, $13, $13, $13, $14, $14, $14, $14, $14, $14, $14, $14, $15, $15, $15
798
+ .byte $15, $15, $15, $15, $15, $15, $16, $16, $16, $16, $16, $16, $16, $16, $17, $17
799
+ .byte $17, $17, $17, $17, $17, $17, $17, $18, $18, $18, $18, $18, $18, $18, $18, $18
800
+ .byte $19, $19, $19, $19, $19, $19, $19, $19, $19, $19, $1a, $1a, $1a, $1a, $1a, $1a
801
+ .byte $1a, $1a, $1a, $1b, $1b, $1b, $1b, $1b, $1b, $1b, $1b, $1b, $1b, $1c, $1c, $1c
802
+ .byte $1c, $1c, $1c, $1c, $1c, $1c, $1c, $1c, $1d, $1d, $1d, $1d, $1d, $1d, $1d, $1d
803
+ .byte $1d, $1d, $1d, $1e, $1e, $1e, $1e, $1e, $1e, $1e, $1e, $1e, $1e, $1e, $1f, $1f
804
+ .byte $1f, $1f, $1f, $1f, $1f, $1f, $1f, $1f, $1f, $1f, $20, $20, $20, $20, $20, $20
805
+ ```
806
+
807
+ ## Build
808
+
809
+ ```bash
810
+ java -jar $KICKASS_JAR sqrt-atan2.asm -o sqrt-atan2.prg
811
+ ```
812
+
813
+ The table and the case bytes at the end of the listing were printed by
814
+ this script (Python 3, standard library). It also holds the integer model
815
+ of each routine and measures the model against `math.isqrt` and
816
+ `math.atan2` over every input; that measurement is what fixes the
817
+ tolerances and picks the three worst atan2 pairs for the case list.
818
+
819
+ ```text
820
+ #!/usr/bin/env python3
821
+ # gen.py -- builds the atan table, models both routines exactly in integers,
822
+ # measures their error against math.isqrt / math.atan2 over every input, and
823
+ # prints the KickAssembler .byte lines for the table and the check cases.
824
+ import math
825
+
826
+ # ---- atan table: 256 entries, index r = floor(min * 256 / max), 0..255 ----
827
+ # value = round(atan(r / 256) * 256 / (2 pi)), 0..32
828
+ atan_tab = [round(math.atan(r / 256) * 256 / (2 * math.pi)) for r in range(256)]
829
+ assert max(atan_tab) <= 32 and min(atan_tab) == 0
830
+
831
+ # ---- integer model of the machine routine ----
832
+ def atan2_model(dx, dy):
833
+ ax, ay = abs(dx), abs(dy)
834
+ if ax == 0 and ay == 0:
835
+ return 0
836
+ if ay == ax:
837
+ a = 32
838
+ elif ay < ax:
839
+ a = atan_tab[(ay << 8) // ax]
840
+ else:
841
+ a = 64 - atan_tab[(ax << 8) // ay]
842
+ if dx < 0:
843
+ a = 128 - a
844
+ if dy < 0:
845
+ a = (256 - a) & 255
846
+ return a & 255
847
+
848
+ def atan2_exact(dx, dy):
849
+ return round(math.atan2(dy, dx) * 256 / (2 * math.pi)) % 256
850
+
851
+ def isqrt_model(n):
852
+ root = rem = 0
853
+ for i in range(8):
854
+ rem = (rem << 2) | ((n >> 14) & 3)
855
+ n = (n << 2) & 0xFFFF
856
+ trial = (root << 2) | 1
857
+ root <<= 1
858
+ if rem >= trial:
859
+ rem -= trial
860
+ root |= 1
861
+ return root
862
+
863
+ # ---- exhaustive error sweep ----
864
+ worst = 0
865
+ worst_pairs = []
866
+ for dx in range(-128, 128):
867
+ for dy in range(-128, 128):
868
+ e = (atan2_model(dx, dy) - atan2_exact(dx, dy)) % 256
869
+ if e > 128:
870
+ e = 256 - e
871
+ if e > worst:
872
+ worst, worst_pairs = e, [(dx, dy)]
873
+ elif e == worst:
874
+ worst_pairs.append((dx, dy))
875
+ print(f"atan2 max error over 65536 pairs: {worst}; {len(worst_pairs)} pairs at the max")
876
+ print("first worst pairs:", worst_pairs[:8])
877
+
878
+ sq_bad = [n for n in range(65536) if isqrt_model(n) != math.isqrt(n)]
879
+ print(f"isqrt model mismatches vs math.isqrt over 65536: {len(sq_bad)}")
880
+
881
+ # ---- check cases ----
882
+ sqrt_cases = [0, 1, 2, 3, 4, 8, 9, 15, 16, 17, 24, 25, 63, 64, 65, 99, 100,
883
+ 121, 144, 255, 256, 257, 1000, 1024, 4095, 4096, 10000, 16384,
884
+ 32767, 32768, 65024, 65025, 65026, 65534, 65535]
885
+ atan_cases = [(1, 0), (0, 1), (-1, 0), (0, -1), (127, 0), (0, 127), (-128, 0), (0, -128),
886
+ (10, 3), (3, 10), (-3, 10), (-10, 3), (-10, -3), (-3, -10), (3, -10), (10, -3),
887
+ (5, 5), (-5, 5), (-5, -5), (5, -5), (127, 127), (-128, -128), (127, -128), (-128, 127),
888
+ (1, 1), (2, 1), (1, 2), (-1, -2), (100, -37), (-64, 20), (45, -90), (-120, -7),
889
+ (0, 0)] + worst_pairs[:3]
890
+
891
+ def bytes_line(label, vals):
892
+ out = []
893
+ for i in range(0, len(vals), 16):
894
+ out.append(" .byte " + ", ".join(f"${v & 255:02x}" for v in vals[i:i + 16]))
895
+ return f"{label}:\n" + "\n".join(out)
896
+
897
+ print()
898
+ print(f"// {len(sqrt_cases)} isqrt cases, {len(atan_cases)} atan2 cases")
899
+ print(bytes_line("sq_in_lo", [n & 255 for n in sqrt_cases]))
900
+ print(bytes_line("sq_in_hi", [n >> 8 for n in sqrt_cases]))
901
+ print(bytes_line("sq_exp", [math.isqrt(n) for n in sqrt_cases]))
902
+ print(bytes_line("at_dx", [dx for dx, dy in atan_cases]))
903
+ print(bytes_line("at_dy", [dy for dx, dy in atan_cases]))
904
+ print(bytes_line("at_exp", [atan2_exact(dx, dy) for dx, dy in atan_cases]))
905
+ print(bytes_line("atan_tab", atan_tab))
906
+ print(f".const NSQ = {len(sqrt_cases)}")
907
+ print(f".const NAT = {len(atan_cases)}")
908
+ # model result on the cases, for the record
909
+ print("model atan2 on cases:", [atan2_model(dx, dy) for dx, dy in atan_cases])
910
+ print("exact atan2 on cases:", [atan2_exact(dx, dy) for dx, dy in atan_cases])
911
+ ```
912
+
913
+ Its output, the part that is a claim: `atan2 max error over 65536 pairs:
914
+ 1; 3968 pairs at the max` and `isqrt model mismatches vs math.isqrt over
915
+ 65536: 0`. The model is the same integer arithmetic as the listing; the
916
+ program is what shows the listing agrees with the model.
917
+
918
+ ## Expected output
919
+
920
+ Border green, text area black (the program clears the screen and never
921
+ returns to BASIC), decoded from the PNG with the character ROM:
922
+
923
+ ```
924
+ ISQRT16 AND ATAN2 8-BIT CHECK
925
+
926
+ SQRT CASES 035 MAX ERR 000 FAIL 000
927
+ ATAN2 CASES 036 MAX ERR 001 FAIL 000
928
+
929
+ WORST BODY CYCLES OVER EVERY INPUT:
930
+ ISQRT16 00869 N=65025
931
+ ATAN2 00381 $81 $80
932
+ REM<=2*ROOT FAILS OF 65536 00000
933
+ SQRT(65535) = 255
934
+ ATAN2(10,3) = 012
935
+
936
+ RESULT: PASS
937
+ ```
938
+
939
+ Screenshots from the pinned run, 120,000,000 cycles:
940
+ `screenshots/sqrt-atan2.png` (PAL) and `screenshots/sqrt-atan2-ntsc.png`
941
+ (NTSC). Both decode to the text above; border pixel (2, 100) is
942
+ (98, 213, 50) on PAL and (114, 189, 103) on NTSC, palette index 5 in
943
+ `runtime/vice-reference.md`. The pinned command was run twice per model
944
+ and the two PNGs were identical bytes each time. The two sweeps are
945
+ about 90 million cycles; a limit under 100 million exits before the
946
+ report is drawn.
947
+
948
+ The figures, all measured in VICE x64sc 3.10 and identical on PAL and
949
+ NTSC:
950
+
951
+ - `isqrt16` body: 869 cycles at worst, first reached at n = 65025
952
+ (255 squared), root exact on every case, `rem <= 2 * root` on all
953
+ 65,536 inputs.
954
+ - `atan2_8` body: 381 cycles at worst, first reached at
955
+ dx = -127, dy = -128; largest error 1 angle unit over the 36 cases,
956
+ which matches the model's 1 over every pair.
957
+ - Body means net of the `JSR`, `RTS` and timer stores, which are
958
+ measured once with an empty routine and subtracted.
959
+
960
+ ## Why this works
961
+
962
+ The square root brings down two bits of `n` per pass into a remainder,
963
+ and per pass doubles the root and tries to subtract `4 * root + 1`,
964
+ which is `(2 * root + 1)^2 - (2 * root)^2`. If the subtract fits, the new
965
+ root bit is 1. After eight passes the root is 8 bits and the remainder is
966
+ `n - root^2`, at most `2 * root`. The trial value reaches 509, so the
967
+ remainder and the trial are two bytes; the compare tests the high bytes
968
+ first and falls through to the low bytes only when they are equal. The
969
+ `SBC` at `sq_sub` is reached on two paths and the carry is set on both
970
+ (from `BNE` after a `CMP` that did not borrow, or from the low-byte
971
+ `CMP`). The worst input is 255 squared rather than 65535: both take
972
+ the subtract on every pass, but 65025 goes once more through the
973
+ equal-high-byte path of the compare, which is seven cycles longer. An
974
+ instruction-table model of the loop (rung 3) gives 862 for 65535, 869
975
+ for 65025 and 869 as its maximum over all 65,536 inputs, the figure the
976
+ sweep measured.
977
+
978
+ `atan2_8` takes the absolute values with `BPL` on the input byte itself,
979
+ not after a subtract, so -128 becomes 128 and the octant compare is a
980
+ plain unsigned `CMP`. When `|dy| < |dx|` the angle is
981
+ `atan(|dy| / |dx|)`; when greater, it is 64 minus `atan(|dx| / |dy|)`;
982
+ when equal, exactly 32, which is tested for because the ratio 256 does
983
+ not fit the table index. The ratio index is `floor(min * 256 / max)`, an
984
+ eight-pass divide whose remainder starts as `min` and stays below `max`;
985
+ `max` is at most 128, so the doubled remainder never needs a ninth bit
986
+ and the loop has no `BCS` guard (`division_8_16bit` explains the guard
987
+ the general loop needs). The table entry is `round(atan(i / 256) * 256 /
988
+ 2pi)`, 0 to 32. Unfolding is two conditional negations: `128 - a` for
989
+ `dx < 0`, then `256 - a` for `dy < 0`, each written as `EOR #$FF` plus
990
+ an add. The error is at most 1 unit because the table is rounded and
991
+ the index truncates a ratio step of 1/256, which moves the angle by
992
+ less than 0.2 units.
993
+
994
+ Timing uses CIA1 timer A force-loaded from `$FFFF` in one-shot mode;
995
+ the count read after the stop, subtracted from the same reading for an
996
+ empty call, is the body cost. DEN is cleared before the sweeps and the
997
+ program waits for two passes of raster line 255 first, because the VIC
998
+ reads DEN once per frame on line `$30` and clearing it mid-frame does
999
+ not stop that frame's badlines. Both routines are placed in one page by
1000
+ `.align $100` and an `.assert`: in an earlier layout the square root's
1001
+ loop branch crossed a page and the same input measured 876, seven
1002
+ taken branches at one extra cycle each (`pitfalls/cpu.md`,
1003
+ `branch_page_cross_extra_cycle`).
1004
+
1005
+ ## What this recipe does not show
1006
+
1007
+ No signed `dx` from two positions: the program feeds `dx` and `dy`
1008
+ directly. A game that forms them with `SEC / SBC` on 8-bit positions
1009
+ more than 127 apart gets a wrapped sign, and the fold then answers for
1010
+ the wrong half of the circle (`pitfalls/cpu.md`,
1011
+ `signed_compare_bmi_overflow`). Clamp the difference or compute it in
1012
+ 16 bits and take the high byte. The routines are not unrolled; an
1013
+ unrolled root is about a fifth faster by the instruction table and was
1014
+ not measured here.