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,569 @@
1
+ # Plan: shmup-vertical
2
+
3
+ A vertically scrolling shoot-em-up starter. The tool output below was
4
+ produced on 2026-09-23 by c64-kb 0.14.0 (KB data 760) and pasted whole.
5
+
6
+ ## Concept
7
+
8
+ A river scrolls down one line a frame through all eight YSCROLL phases above
9
+ a fixed five-row score panel. The ship is a multicolour sprite on joystick
10
+ port 2; it fires character bullets. Enemies come in waves keyed to how far
11
+ the river has scrolled, fly bytecode paths, and go through a sprite
12
+ multiplexer, so eleven or more sprites share the screen. Hits are boxes per
13
+ sprite frame. A three-voice tune plays with the effects inside it. Three
14
+ lives, a score, a high score saved to drive 8. Title, play, game over, back
15
+ to the title. PAL and NTSC.
16
+
17
+ ## Briefing
18
+
19
+ Command: `npx tsx src/cli.ts game-briefing "vertically scrolling shoot-em-up: playfield scrolls down over a fixed score panel, player ship sprite, more than 8 enemy sprites via multiplexer, waves triggered by scroll distance, character bullets, hitbox collisions, sound effects over a SID tune, lives and score" --archetype vertical_shmup`
20
+
21
+ What it proposed and what this plan did with it:
22
+
23
+ - Kept: `scroll_panel_split`, `soft_scroll_v`, `wave_director`, `object_pool`,
24
+ `sfx_in_player`, `sid_play_routine_pattern` (its SID group), `per_frame_hitbox`
25
+ (named in the brief, not proposed).
26
+ - Replaced: `sprite_multiplex_24` and `sprite_multiplex_8` by
27
+ `sprite_multiplex_game`, the recipe built for a game (sort, double-buffered
28
+ table, zone IRQs, late guard). `double_irq`, `stable_raster_irq` and
29
+ `raster_bars`: the panel split polls and uses a delay table instead of a
30
+ stable raster, as its recipe does.
31
+ - Added: `screen_double_buffer_d018` (a downward scroll cannot move rows
32
+ ahead of the beam), `char_bullets` (in the brief, not proposed),
33
+ `joystick_edge_detect` (fire on the title).
34
+ - Dropped: `text_mode_overlay_render` (a falling-block renderer),
35
+ `mixed_sprite_char_actors`, `multi_sprite_object`,
36
+ `sprite_collision_detect` (boxes are tested in software),
37
+ `goattracker_player_api` and `sfx_engine_beside_music` (the player here is
38
+ our own with the effects inside it).
39
+ - Its header said "Compatibility: incompatible" while its Compatibility
40
+ section listed only soft shared-register notes (a tool finding).
41
+ - Pitfalls it named that this program meets: `badline_cycle_loss`,
42
+ `scroll_phase_breaks_panel_split`, `d016_unmasked_rmw_clobbers_csel_mcm`,
43
+ `vic_bank_visibility_collision`, `sprite_dma_overflow`,
44
+ `sprite_x_high_bit_wrong_register`, `pal_ntsc_tempo_mismatch`,
45
+ `sid_write_only_registers`, `decimal_mode_in_irq_handler`,
46
+ `raster_irq_during_serial_io`.
47
+
48
+ ## Techniques
49
+
50
+ | Technique | Why | Recipe it starts from | Pitfalls read (`pitfalls-for`) |
51
+ |---|---|---|---|
52
+ | scroll_panel_split | the score panel under a playfield that scrolls through every YSCROLL phase | kickassembler-scroll-panel-split | scroll_phase_breaks_panel_split, badline_cycle_loss, d016_unmasked_rmw_clobbers_csel_mcm, vic_bank_visibility_collision, idle_fetch_byte_shows_in_gaps, xscroll_applies_to_all_rows |
53
+ | soft_scroll_v | one line a frame through YSCROLL 0-7 | kickassembler-scroll-panel-split | badline_cycle_loss, full_field_redraw_exceeds_vblank, scroll_phase_breaks_panel_split |
54
+ | screen_double_buffer_d018 | the rows move down at the carry: draw the next screen hidden, flip with $D018 | kickassembler-eight-way-scroll (the idea), level.c | full_field_redraw_exceeds_vblank, vic_bank_visibility_collision, charset_blit_overruns_grown_code |
55
+ | screen_ram_relocation | prerequisite of the above: screens at $8000, $8400, $8800 in VIC bank 2 | oscar64-double-buffer | vic_bank_visibility_collision |
56
+ | sprite_multiplex_game | the ship and up to twelve enemies on eight sprites | kickassembler-sprite-multiplex-game | sprite_dma_overflow, decimal_mode_in_irq_handler, sprite_x_high_bit_wrong_register, sprite_x_range_hidden_and_seam, vic_bus_takeover_on_dma, sprite_registers_persist_across_state_change |
57
+ | wave_director | waves start at map rows, not frame counts; path bytecode | oscar64-wave-director | sprite_x_high_bit_wrong_register |
58
+ | object_pool | twelve enemy slots | oscar64-object-pool (inside wave-director) | sprite_x_range_hidden_and_seam |
59
+ | char_bullets | the ship's bolts and the enemies' dots as characters, merged into reserved glyphs (or a ready-made glyph over open water) | oscar64-char-bullets | charset_blit_overruns_grown_code, full_field_redraw_exceeds_vblank, petscii_written_to_screen_ram |
60
+ | per_frame_hitbox | a box per sprite frame; only pairs that can hurt each other | oscar64-per-frame-hitbox | sprite_dma_overflow, sprite_x_high_bit_wrong_register |
61
+ | sfx_in_player | effects take voice 3 inside the player and hand it back | kickassembler-sfx-in-player | sid_adsr_bug_8580, sid_write_only_registers, sid_voice3_disable_silent_bit |
62
+ | sid_play_routine_pattern | init + play, once a frame from the raster IRQ | oscar64-sid-music-player | pal_ntsc_tempo_mismatch, sid_filter_chip_variation |
63
+ | sid_voice_setup | prerequisite of the two above | oscar64-sid-music-player | sid_adsr_bug_8580 |
64
+ | joystick_edge_detect | fire starts the game once per press | oscar64-joystick-input, oscar64-headless-verify | cia1_ddr_cleared_kills_keyboard, joystick2_scan_phantom_press |
65
+
66
+ ## Compatibility
67
+
68
+ Command: `npx tsx src/cli.ts check-compatibility scroll_panel_split soft_scroll_v screen_double_buffer_d018 sprite_multiplex_game wave_director object_pool char_bullets per_frame_hitbox sfx_in_player sid_play_routine_pattern joystick_edge_detect`
69
+
70
+ ```text
71
+ # Compatibility: scroll_panel_split + soft_scroll_v + screen_double_buffer_d018 + sprite_multiplex_game + wave_director + object_pool + char_bullets + per_frame_hitbox + sfx_in_player + sid_play_routine_pattern + joystick_edge_detect
72
+
73
+ **Verdict:** INCOMPATIBLE — not as combined; each hard conflict below says how to separate them.
74
+
75
+ Checked with 2 implied prerequisite(s): screen_ram_relocation, sid_voice_setup.
76
+
77
+ Unit claims are stated for 4 of 11 techniques; a unit conflict cannot be ruled out for: soft_scroll_v, screen_double_buffer_d018, wave_director, object_pool, char_bullets, per_frame_hitbox, sfx_in_player, screen_ram_relocation (prerequisite), sid_voice_setup (prerequisite). The zero-page bytes and interrupt vectors a recipe chooses are not checked yet (issue #22, step 8).
78
+
79
+ ## shared_register (soft): scroll_panel_split × soft_scroll_v
80
+ **Shared:** SCROLY
81
+ Both techniques touch register(s) SCROLY. This says they write the same registers, not that they fight: keep each one's writes in its own raster region, or have one of them own the register and the other read a shadow copy.
82
+
83
+ ## shared_register (soft): scroll_panel_split × screen_double_buffer_d018
84
+ **Shared:** VMCSB, SCROLY
85
+ Both techniques touch register(s) VMCSB, SCROLY. This says they write the same registers, not that they fight: keep each one's writes in its own raster region, or have one of them own the register and the other read a shadow copy.
86
+
87
+ ## unit_contention (hard): scroll_panel_split × sprite_multiplex_game
88
+ **Shared:** vic_raster_irq
89
+ Both scroll_panel_split and sprite_multiplex_game own vic_raster_irq: each writes or holds it every frame and expects no one else to.
90
+ **Resolution:** There is one raster compare. Run both as handlers in one interrupt chain (irq_chain_table): one technique owns $D012 and the other's handler becomes a chain entry that shares it.
91
+
92
+ ## shared_register (soft): scroll_panel_split × sprite_multiplex_game
93
+ **Shared:** RASTER
94
+ Both techniques touch register(s) RASTER. This says they write the same registers, not that they fight: keep each one's writes in its own raster region, or have one of them own the register and the other read a shadow copy.
95
+
96
+ ## shared_register (soft): scroll_panel_split × char_bullets
97
+ **Shared:** VMCSB
98
+ Both techniques touch register(s) VMCSB. This says they write the same registers, not that they fight: keep each one's writes in its own raster region, or have one of them own the register and the other read a shadow copy.
99
+
100
+ ## shared_register (soft): soft_scroll_v × screen_double_buffer_d018
101
+ **Shared:** SCROLY
102
+ Both techniques touch register(s) SCROLY. This says they write the same registers, not that they fight: keep each one's writes in its own raster region, or have one of them own the register and the other read a shadow copy.
103
+
104
+ ## shared_register (soft): screen_double_buffer_d018 × char_bullets
105
+ **Shared:** VMCSB
106
+ Both techniques touch register(s) VMCSB. This says they write the same registers, not that they fight: keep each one's writes in its own raster region, or have one of them own the register and the other read a shadow copy.
107
+
108
+ ## shared_register (soft): sprite_multiplex_game × per_frame_hitbox
109
+ **Shared:** MSIGX
110
+ Both techniques touch register(s) MSIGX. This says they write the same registers, not that they fight: keep each one's writes in its own raster region, or have one of them own the register and the other read a shadow copy.
111
+
112
+ ## shared_register (soft): sfx_in_player × sid_play_routine_pattern
113
+ **Shared:** SIGVOL, RESON, CUTHI, CUTLO, SUREL3, ATDCY3, VCREG3, PWHI3, PWLO3, FREHI3, FRELO3, SUREL2, ATDCY2, VCREG2, PWHI2, PWLO2, FREHI2, FRELO2, SUREL1, ATDCY1, VCREG1, PWHI1, PWLO1, FREHI1, FRELO1
114
+ Both techniques touch register(s) SIGVOL, RESON, CUTHI, CUTLO, SUREL3, ATDCY3, VCREG3, PWHI3, PWLO3, FREHI3, FRELO3, SUREL2, ATDCY2, VCREG2, PWHI2, PWLO2, FREHI2, FRELO2, SUREL1, ATDCY1, VCREG1, PWHI1, PWLO1, FREHI1, FRELO1. This says they write the same registers, not that they fight: keep each one's writes in its own raster region, or have one of them own the register and the other read a shadow copy.
115
+
116
+
117
+ ## Not covered
118
+ - **wave_director**: the graph has no registers, KERNAL routines or demands for it; the verdict says nothing about it.
119
+ - **object_pool**: the graph has no registers, KERNAL routines or demands for it; the verdict says nothing about it.
120
+
121
+ ## Shared Infrastructure (info)
122
+ - **screen_ram_relocation** (prerequisite, not in the set): required by screen_double_buffer_d018; included in the check as implied. Set it up first.
123
+ - **sid_voice_setup** (prerequisite, not in the set): required by sfx_in_player, sid_play_routine_pattern; included in the check as implied. Set it up first.
124
+ - **CHRIN** (KernalRoutine) shared via recipe(s): oscar64-platformer-scaffold
125
+ - **CHROUT** (KernalRoutine) shared via recipe(s): oscar64-platformer-scaffold
126
+ - **CLRCHN** (KernalRoutine) shared via recipe(s): oscar64-platformer-scaffold
127
+ - **CHKOUT** (KernalRoutine) shared via recipe(s): oscar64-platformer-scaffold
128
+ - **CHKIN** (KernalRoutine) shared via recipe(s): oscar64-platformer-scaffold
129
+ - **CLOSE** (KernalRoutine) shared via recipe(s): oscar64-platformer-scaffold
130
+ - **OPEN** (KernalRoutine) shared via recipe(s): oscar64-platformer-scaffold
131
+ - **SETNAM** (KernalRoutine) shared via recipe(s): oscar64-platformer-scaffold
132
+ - **SETLFS** (KernalRoutine) shared via recipe(s): oscar64-platformer-scaffold
133
+ - **DC0F** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-vehicle-control, kickassembler-eight-way-scroll
134
+ - **DC07** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-vehicle-control, kickassembler-eight-way-scroll
135
+ - **DC06** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-vehicle-control, kickassembler-eight-way-scroll
136
+ - **SP6COL** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup
137
+ - **SP5COL** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup
138
+ - **SP4COL** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup
139
+ - **SP3COL** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup
140
+ - **SP2COL** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup
141
+ - **SP1COL** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup
142
+ - **SP0COL** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup, oscar64-vehicle-control, oscar64-wave-director
143
+ - **DC03** (Register) shared via recipe(s): oscar64-platformer-scaffold
144
+ - **BGCOL0** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-vehicle-control, kickassembler-eight-way-scroll, kickassembler-scroll-panel-split, oscar64-wave-director
145
+ - **EXTCOL** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-vehicle-control, kickassembler-eight-way-scroll, kickassembler-scroll-panel-split, oscar64-wave-director
146
+ - **IRQMSK** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup, kickassembler-eight-way-scroll, kickassembler-scroll-panel-split
147
+ - **VICIRQ** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup, kickassembler-eight-way-scroll, kickassembler-scroll-panel-split
148
+ - **SPENA** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup, oscar64-vehicle-control, oscar64-wave-director
149
+ - **RASTER** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup, kickassembler-eight-way-scroll, kickassembler-scroll-panel-split, oscar64-wave-director
150
+ - **SCROLY** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup, oscar64-vehicle-control, kickassembler-eight-way-scroll, kickassembler-scroll-panel-split, oscar64-wave-director
151
+ - **MSIGX** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup, oscar64-vehicle-control, oscar64-wave-director
152
+ - **M0Y** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup, oscar64-vehicle-control, oscar64-wave-director
153
+ - **M0X** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup, oscar64-vehicle-control, oscar64-wave-director
154
+ - **RANDOM** (Register) shared via recipe(s): oscar64-platformer-scaffold
155
+ - **SIGVOL** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup
156
+ - **SUREL3** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup
157
+ - **ATDCY3** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup
158
+ - **VCREG3** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup
159
+ - **PWHI3** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup
160
+ - **PWLO3** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup
161
+ - **FREHI3** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup
162
+ - **FRELO3** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup
163
+ - **SUREL2** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup
164
+ - **ATDCY2** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup
165
+ - **VCREG2** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup
166
+ - **PWHI2** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup
167
+ - **PWLO2** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup
168
+ - **FREHI2** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup
169
+ - **FRELO2** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup
170
+ - **SUREL1** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup
171
+ - **ATDCY1** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup
172
+ - **DC02** (Register) shared via recipe(s): oscar64-platformer-scaffold
173
+ - **DC00** (Register) shared via recipe(s): oscar64-platformer-scaffold
174
+ - **VCREG1** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup
175
+ - **PWHI1** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup
176
+ - **PWLO1** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup
177
+ - **FREHI1** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup
178
+ - **FRELO1** (Register) shared via recipe(s): oscar64-platformer-scaffold, oscar64-simple-shmup
179
+ - **READST** (KernalRoutine) shared via recipe(s): oscar64-platformer-scaffold
180
+ - **SP7COL** (Register) shared via recipe(s): oscar64-simple-shmup
181
+ - **SPBGCL** (Register) shared via recipe(s): oscar64-simple-shmup
182
+ - **SPSPCL** (Register) shared via recipe(s): oscar64-simple-shmup
183
+ - **SCROLX** (Register) shared via recipe(s): oscar64-simple-shmup, kickassembler-eight-way-scroll, kickassembler-scroll-panel-split
184
+ - **RESON** (Register) shared via recipe(s): oscar64-simple-shmup
185
+ - **CUTHI** (Register) shared via recipe(s): oscar64-simple-shmup
186
+ - **CUTLO** (Register) shared via recipe(s): oscar64-simple-shmup
187
+ - **DD0E** (Register) shared via recipe(s): oscar64-vehicle-control
188
+ - **DD05** (Register) shared via recipe(s): oscar64-vehicle-control
189
+ - **DD04** (Register) shared via recipe(s): oscar64-vehicle-control
190
+ - **BGCOL3** (Register) shared via recipe(s): oscar64-vehicle-control
191
+ - **BGCOL2** (Register) shared via recipe(s): oscar64-vehicle-control
192
+ - **BGCOL1** (Register) shared via recipe(s): oscar64-vehicle-control
193
+ - **VMCSB** (Register) shared via recipe(s): oscar64-vehicle-control, kickassembler-eight-way-scroll, kickassembler-scroll-panel-split
194
+ - **DD0D** (Register) shared via recipe(s): kickassembler-eight-way-scroll, kickassembler-scroll-panel-split
195
+ - **DC0D** (Register) shared via recipe(s): kickassembler-eight-way-scroll, kickassembler-scroll-panel-split
196
+ - **DC0E** (Register) shared via recipe(s): oscar64-wave-director
197
+ - **DC05** (Register) shared via recipe(s): oscar64-wave-director
198
+ - **DC04** (Register) shared via recipe(s): oscar64-wave-director
199
+ - **raster_discipline**: Multiple raster-discipline techniques present. Verify IRQ stack ordering and timing budget.
200
+
201
+ ```
202
+
203
+ What the warnings mean for this program:
204
+
205
+ - `unit_contention (hard)` scroll_panel_split x sprite_multiplex_game on
206
+ `vic_raster_irq`: resolved as the tool says, one chain. kernel.asm owns
207
+ `$D012`: the frame IRQ (line 252) arms the multiplexer's zones, the last
208
+ zone arms the split (line 212), the split arms the frame IRQ. Adding
209
+ `irq_chain_table` to the list, the tool's own resolution, adds two more
210
+ hard conflicts instead of clearing this one (a tool finding), so it is
211
+ not listed; the verdict stays INCOMPATIBLE for the combination as named.
212
+ - `shared_register` SCROLY and VMCSB between the scroll, the split and the
213
+ double buffer: the frame IRQ writes the playfield's `$D011` and `$D018`
214
+ from two bytes C sets; the split writes the panel's. No other writer.
215
+ - `shared_register` VMCSB with char_bullets: the bullets never write
216
+ `$D018`; they write the character set's reserved glyphs.
217
+ - `shared_register` MSIGX (sprite_multiplex_game x per_frame_hitbox): only
218
+ the multiplexer writes `$D010`; the boxes are in half X and never need it.
219
+ - SID registers (sfx_in_player x sid_play_routine_pattern): one player
220
+ writes a shadow and copies it to `$D400-$D418` once a frame.
221
+ - wave_director and object_pool: the graph holds nothing for them.
222
+
223
+ ## Budget
224
+
225
+ Command: `npx tsx src/cli.ts plan-budget scroll_panel_split soft_scroll_v screen_double_buffer_d018 sprite_multiplex_game wave_director object_pool char_bullets per_frame_hitbox sfx_in_player sid_play_routine_pattern joystick_edge_detect --region both --sprites 5 --sprite-lines 63`
226
+
227
+ ```text
228
+ # Budget plan: undetermined
229
+
230
+ Techniques: scroll_panel_split, soft_scroll_v, screen_double_buffer_d018, sprite_multiplex_game, wave_director, object_pool, char_bullets, per_frame_hitbox, sfx_in_player, sid_play_routine_pattern, joystick_edge_detect
231
+
232
+ ## play (PAL, 19656 cycles a frame): undetermined
233
+
234
+ Range 26691-28709 + 1894 fixed cycles; floor 0; weakest basis arithmetic; IRQ slots 20.
235
+
236
+ Summed:
237
+ - scroll_panel_split: 413 (measured-vice, on kickassembler-scroll-panel-split (two IRQs, screen on; not the carry frame))
238
+ - sprite_multiplex_game: 16600 (arithmetic, on kickassembler-sprite-multiplex-game (worst frame: a reversed sort))
239
+ - wave_director: 1170-3188 (measured-vice, on oscar64-wave-director (worst frame, screen blanked))
240
+ - char_bullets: 3995 (measured-vice, on oscar64-char-bullets (eight bullets, worst frame))
241
+ - per_frame_hitbox: 3693 (measured-vice, on oscar64-per-frame-hitbox (eight boxes, 28 pairs))
242
+ - sfx_in_player: 493 (arithmetic, on kickassembler-sfx-in-player (increment over the player, worst effect frame))
243
+ - sid_play_routine_pattern: 327 (measured-vice, on oscar64-sfx-engine (the recipe's stub tune; a real player costs several times more))
244
+
245
+ Left out:
246
+ - object_pool: not added, inside wave_director's figure (Cost includes)
247
+
248
+ To measure:
249
+ - soft_scroll_v: no **Cost:** line; measure it on kickassembler-eight-way-scroll
250
+ - screen_double_buffer_d018: no **Cost:** line; measure it on kickassembler-eight-way-scroll
251
+ - joystick_edge_detect: no **Cost:** line; measure it on oscar64-attract-replay
252
+
253
+ Notes:
254
+ - Fixed losses 1894 cycles (badlines 25 × 43 = 1075, lines 51-243 every eighth with YSCROLL 3, sprite DMA 819; arithmetic) charged because sprite_multiplex_game, wave_director, char_bullets, per_frame_hitbox, sfx_in_player, sid_play_routine_pattern are not stated as measured with the screen on. A stall takes its cycles wherever the code runs, so the charge is exact unless a figure already holds stalls: scroll_panel_split was measured with the screen on and already holds the stalls that fell inside it, so the charge is too high by that much and the over test counts 0.
255
+ - The low end, 26691 + 1894, passes the 19656-cycle frame, but it is not a floor: the figures of scroll_panel_split, sprite_multiplex_game, wave_director, char_bullets, per_frame_hitbox, sfx_in_player, sid_play_routine_pattern are a common frame or a real run's worst, and those frames need not fall together. scroll_panel_split, sprite_multiplex_game, char_bullets, per_frame_hitbox, sfx_in_player, sid_play_routine_pattern have no typical frame, so their low end is a worst frame. The floor, work every frame plus the loss no figure can hold, is 0 and fits. A frame measured whole, with every member running, would settle it.
256
+ - Unknown is not zero: soft_scroll_v, screen_double_buffer_d018, joystick_edge_detect have no cycles figure, so the verdict cannot be fits.
257
+
258
+ ## play (NTSC, 17095 cycles a frame): undetermined
259
+
260
+ Range 26691-28709 + 1894 fixed cycles; floor 0; weakest basis arithmetic; IRQ slots 20.
261
+
262
+ Summed:
263
+ - scroll_panel_split: 413 (measured-vice, on kickassembler-scroll-panel-split (two IRQs, screen on; not the carry frame))
264
+ - sprite_multiplex_game: 16600 (arithmetic, on kickassembler-sprite-multiplex-game (worst frame: a reversed sort))
265
+ - wave_director: 1170-3188 (measured-vice, on oscar64-wave-director (worst frame, screen blanked))
266
+ - char_bullets: 3995 (measured-vice, on oscar64-char-bullets (eight bullets, worst frame))
267
+ - per_frame_hitbox: 3693 (measured-vice, on oscar64-per-frame-hitbox (eight boxes, 28 pairs))
268
+ - sfx_in_player: 493 (arithmetic, on kickassembler-sfx-in-player (increment over the player, worst effect frame))
269
+ - sid_play_routine_pattern: 327 (measured-vice, on oscar64-sfx-engine (the recipe's stub tune; a real player costs several times more))
270
+
271
+ Left out:
272
+ - object_pool: not added, inside wave_director's figure (Cost includes)
273
+
274
+ To measure:
275
+ - soft_scroll_v: no **Cost:** line; measure it on kickassembler-eight-way-scroll
276
+ - screen_double_buffer_d018: no **Cost:** line; measure it on kickassembler-eight-way-scroll
277
+ - joystick_edge_detect: no **Cost:** line; measure it on oscar64-attract-replay
278
+
279
+ Notes:
280
+ - Fixed losses 1894 cycles (badlines 25 × 43 = 1075, lines 51-243 every eighth with YSCROLL 3, sprite DMA 819; arithmetic) charged because sprite_multiplex_game, wave_director, char_bullets, per_frame_hitbox, sfx_in_player, sid_play_routine_pattern are not stated as measured with the screen on. A stall takes its cycles wherever the code runs, so the charge is exact unless a figure already holds stalls: scroll_panel_split was measured with the screen on and already holds the stalls that fell inside it, so the charge is too high by that much and the over test counts 0.
281
+ - The low end, 26691 + 1894, passes the 17095-cycle frame, but it is not a floor: the figures of scroll_panel_split, sprite_multiplex_game, wave_director, char_bullets, per_frame_hitbox, sfx_in_player, sid_play_routine_pattern are a common frame or a real run's worst, and those frames need not fall together. scroll_panel_split, sprite_multiplex_game, char_bullets, per_frame_hitbox, sfx_in_player, sid_play_routine_pattern have no typical frame, so their low end is a worst frame. The floor, work every frame plus the loss no figure can hold, is 0 and fits. A frame measured whole, with every member running, would settle it.
282
+ - Unknown is not zero: soft_scroll_v, screen_double_buffer_d018, joystick_edge_detect have no cycles figure, so the verdict cannot be fits.
283
+ - Cycles per frame are the pages' figures, most measured on PAL; the same code takes about the same cycles on NTSC, against a 17,095-cycle frame.
284
+
285
+ ## Bytes
286
+
287
+ No member states a byte figure that can be summed.
288
+
289
+ ## Assumptions
290
+
291
+ - Region PAL and NTSC: PAL 19656, NTSC 17095 cycles a frame.
292
+ - Screen on: unless every summed figure says it was measured with the screen on, the 25 badlines × 43 cycles outside any band charge are charged.
293
+ - Low end: each member's cycles_per_frame_typical where the page states one (a common frame, or a real run's worst frame), else its worst frame. It is not a floor. Over is judged on the floor: band and per-line charges, which run every frame, plus the badline loss no summed figure can already hold.
294
+ - Each figure is the technique's own Cost line, measured on the recipe it names: another implementation can cost more or less.
295
+ - Claims, zero page and memory are not judged here; c64_check_compatibility judges claims and zero page.
296
+ - Sprites: 5 a line on 63 lines, (3 + 2 × 5) × 63 = 819 cycles of DMA a frame (3 + 2n measured in VICE x64sc for sprites numbered without gaps).
297
+
298
+ ```
299
+
300
+ Measured by the meter (`make shot check`, VICE x64sc 3.10, the script's
301
+ 240 play frames): worst 11,681 cycles and typical (the median) 8,374 on
302
+ PAL; worst 11,875 and typical 8,733 on NTSC. The bracket is the C main
303
+ loop's whole frame (CIA2 timer A) plus every IRQ outside it (CIA2 timer B,
304
+ summed by kernel.asm); badlines and sprite DMA inside either are in the
305
+ figures. The split IRQ starts timer B only after its panel writes, so C
306
+ adds its first 289 cycles on PAL, 296 on NTSC (the largest of 245-289 and
307
+ 246-296 measured under the VICE monitor from the IRQ sequence to the start
308
+ write). Not in the figures: about 45 cycles per other IRQ taken outside the
309
+ main loop's bracket (the entry before timer B starts and the exit after it
310
+ stops; arithmetic from kernel.asm), one to four a frame, nor the loop's
311
+ head (the wait, `level_frame`, the stick) and `meter_open`'s own
312
+ bookkeeping. A frame can therefore be lost with the meter below the frame:
313
+ at 7974a7a the staged run lost one on NTSC with its worst at 16,122. A frame
314
+ far past the frame reads about 65,524, because timer A counts down from
315
+ 65,535 and wraps: that reading is a wrap, not a size. The meter's
316
+ readout is printed only after the freeze: printed every frame it cost up
317
+ to 3,404 cycles outside the bracket (measured in the review) and made the
318
+ autopilot build drop frames the game does not.
319
+
320
+ Enemy fire (ported from the other #39 version's design, in this code's
321
+ structure) raised the typical frame by about 2,400 cycles and the staged
322
+ worst past the NTSC frame at first (17,882). Four changes brought it back,
323
+ each measured with `make stage`: the bullet draw list in `glyph.asm`, the
324
+ enemies' dots stepped there too, `hit.asm` for the enemy boxes, `step.asm`
325
+ for the path step, ready-made glyphs for shots over open water (no merge),
326
+ and a three-row copy of 32 cycles a column (the other version's copy3).
327
+
328
+ Lost frames are counted by `wait_frame` (main.c) before it waits: a frame
329
+ flag already set means the work ended after the next frame IRQ. The first
330
+ version counted at wake-up, when the frame IRQ count had moved by more
331
+ than one, which a single lost frame never does: the review's mutation M8a
332
+ (one play frame about 2,400 cycles late) passed with `OVERRUNS 00`. The
333
+ count is `overruns` in the verdict and `LOST_FRAMES` at `$02FD` in every
334
+ build, which `make joytest` and `make longplay` read.
335
+
336
+ With that count, play on NTSC lost frames at 7974a7a where the staged run
337
+ never looked: held fire and a sweep of the ship (the review's drive: 6 of
338
+ 15 games, at play frame 465 in 5; a build with `-dWORKEND=1`, 4 of 4, at
339
+ play frames 282-321 and 454-477), when the row-48 saucers and row-56 darts
340
+ are on the screen with bolts, dots and kills. The staged run records play
341
+ frames 150-399. The heaviest play frame, 464, measured by `-dPROFILE=1`
342
+ (each step with IRQs held off, NTSC): 15,385 cycles of steps at 7974a7a
343
+ (bullets 4,925, collide 2,387, waves 3,252, actors 3,035, render 1,572),
344
+ 13,357-13,395 after these cuts, each checked by `make check`:
345
+
346
+ - The bolts' loop moved from C to `glyph.asm` (`bb_run`, with their boxes):
347
+ bullets at frame 464 from 4,925 to 4,491 (PROFILE).
348
+ - `cb_draw` takes glyph addresses from two 256-byte tables: 35 cycles less
349
+ a merge (arithmetic). It notes the map's code under a bullet only when
350
+ `cb_keep` is set, in AUTOPILOT builds, whose verdict checks it: about 40
351
+ cycles a draw (arithmetic).
352
+ - The dots against the ship moved to `hit.asm` (`dot_scan`); a dot that
353
+ hits still takes the ship's box off before the enemies are tested.
354
+ - The path bytecode runs in `step.asm` (`en_paths`, `en_fetch`, with the
355
+ explosions' timers); C calls `on_enemy_fire` for each enemy it lists.
356
+ The scan and reads in C cost about 330 cycles an enemy that needed a new
357
+ MOVE (PROFILE).
358
+ - `hit_scan` passes over an enemy whose lines miss every box that is on,
359
+ and walks a list of the boxes that are on; a box spent by an earlier
360
+ enemy is checked only on a hit.
361
+ - The score's digits change once a frame (`panel_update`), not once a kill.
362
+ - The spawner reads its wave through a pointer and adds the formation step
363
+ to X, where it indexed the table and multiplied.
364
+ - The SID copy is unrolled: 200 cycles against 350 (arithmetic).
365
+ - The multiplexer takes 13 actors, not 16 (3 were never used), and its
366
+ build loop keeps the write place in X: about 20 cycles an actor less
367
+ (arithmetic).
368
+ - `eb_run` takes the dot's ready-made glyph from a table: 14 cycles a dot
369
+ less (arithmetic).
370
+ - The frame IRQ skips the meter's hand-over in builds without the meter:
371
+ about 60 cycles a frame (arithmetic).
372
+
373
+ One change was tried and taken out: drawing the hidden screen in pieces
374
+ wherever a frame had time left, instead of three rows on each of YSCROLL
375
+ 0-6. In the heaviest stretch no frame had time left, so the pieces piled
376
+ onto the last frames before the flip, and the extra calls cost more: 20 to
377
+ 56 lost frames in 40 s where the fixed schedule lost 2 to 4 (NTSC, the
378
+ same runs).
379
+
380
+ After the cuts, with `-dWORKEND=1` (the raster when a frame's work ended,
381
+ counted in lines after line 252): in 4 games of 40 s with a ship that is
382
+ never lost (`-dGOD=1`), the latest end on NTSC was line 254-256 of 263, at
383
+ play frames 464-472, and no frame was lost; on PAL 230-243 of 312. The
384
+ staged run's latest end on NTSC is line 249. `make joytest`: 16 of 16 NTSC
385
+ games and 16 of 16 PAL lost no frame; `make longplay`: 4 games a model of
386
+ about 39,000 (PAL) and 44,000 (NTSC) play frames, none lost.
387
+
388
+ Against the plan: the tool's range, 26,691-28,709 plus 1,894 fixed, is
389
+ well above the worst frame measured. Where they differ:
390
+
391
+ - sprite_multiplex_game, 16,600 (arithmetic): its recipe's worst case, 24
392
+ actors with the sort order reversed. Here 13 actors, and the persistent
393
+ sort sees a few swaps a frame: sort and build 2,800-3,300 with DMA
394
+ (PROFILE builds, IRQs off, the staged frame and play's heaviest).
395
+ - char_bullets, 3,995: eight bullets. Here up to 3 bolts and 6 dots: the
396
+ erase, the restore check and the draw, 2,300 on the staged frame, 4,000
397
+ on play's heaviest.
398
+ - per_frame_hitbox, 3,693: 28 pairs of every kind. Here 12 enemies x 5
399
+ boxes in `hit.asm` plus 6 dots against the ship: 1,500-2,600.
400
+ - wave_director, 1,170-3,188: here 2,000-3,000, twelve slots.
401
+ - Not in the tool at all: drawing three rows of the hidden screen (about
402
+ 1,700-1,900) and the actor hand-off to the multiplexer.
403
+ - soft_scroll_v, screen_double_buffer_d018, joystick_edge_detect have no
404
+ Cost line; the meter covers them.
405
+
406
+ The graded script's worst frame is not the game's worst case. `make stage`
407
+ (-dSTAGE=1) plays a script that brings 12 enemies onto the screen at once
408
+ (the parade and the row-32 swoop), waits, and fires up a parade column, so
409
+ bolts, dots and a kill share those frames, and meters play frames 150-399.
410
+ Swept over 16 timings (-dSD=0,8,16,24 x -dSX=8,16,24,32), its worst frame
411
+ is 15,064 cycles on PAL and 15,237 on NTSC, typical 9,280 and 9,967 (SD 24,
412
+ SX 16, which `make stage` runs), and no run lost a frame. At 7974a7a the
413
+ same sweep gave 15,991 and 16,136. It is not play's heaviest frame (above):
414
+ `make longplay` covers that. Its verdict fails on an overrun or an unrestored bullet cell,
415
+ and stage-expect.json on a worst over the frame. Before enemy fire the
416
+ review's sweep found 14,575 and 15,066. Two things the first version of
417
+ this plan got wrong: four bolts never fly at once (one shot per 7 frames,
418
+ a bolt lives at most 16: three, arithmetic), and the carry frame (YSCROLL
419
+ 7) is the cheapest phase, because `level_render` does nothing on it.
420
+
421
+ The bullet draw must end before the beam reaches each cell it changes.
422
+ `-dDRAWEND=1` records the smallest number of lines between the raster
423
+ and the first line of each cell drawn, read after all the bolts and again
424
+ after all the dots (a lower bound: the bolts are drawn in `glyph.asm` now):
425
+ on NTSC 19 for a dot in the graded run and 25 in the staged run, 26 for the
426
+ bolts in both; on PAL the bolts were all drawn before line 0 and the dots
427
+ had 69 or more. At 7974a7a, read after each cell: 17 and 28. Frames that start
428
+ late for the harness (the first, the one after a meter_init, the ones where
429
+ the median is found) are left out; the enemy fire window, sprite Y 72-140,
430
+ is what keeps the dots below the draw.
431
+
432
+ ## Memory and screen
433
+
434
+ - `$0801-$087F` Oscar64 startup; `$0880-$1FFF` the KickAssembler blob
435
+ (`src/kernel.asm` with `mux.asm`, `sound.asm`, `glyph.asm`, `hit.asm`
436
+ and `step.asm`: 5,162 bytes, to `$1CA9`); `$2000-$7FFF` C code, data and
437
+ stack (code and data end at `$3D0C` in the release build).
438
+ - VIC bank 2 (`$DD00` bits 0-1 = 01): playfield screens at `$8000` and
439
+ `$8400`, the panel screen at `$8800`, sprite shapes from `$A000` (block
440
+ 128), characters at `$B800`. The VIC sees the character ROM at
441
+ `$9000-$9FFF`, so the level map (98 rows of 40 codes) lives there.
442
+ - `$8C00` row 13: the meter's scratch readout in AUTOPILOT builds, copied
443
+ onto the playfield after the verdict.
444
+ - Characters: `$C0-$CF` a dot, `$D0-$D3` a bolt, over open water (no
445
+ merge); `$F2-$F7` the dots' and `$F8-$FB` the bolts' reserved glyphs;
446
+ `$FF` blank (the idle byte).
447
+ - Colour RAM: every playfield cell `$0F` (multicolour, yellow), panel rows
448
+ white; text on the playfield sets its cells below 8 (hires).
449
+ - Zero page: Oscar64's `$02-$56` (measured by claims-watch); the kernel
450
+ uses none. `$02FF` the verdict byte. CIA2 timer A the meter, timer B the
451
+ IRQ time.
452
+
453
+ ## Autopilot and checks
454
+
455
+ Script (frames, port byte): 2 idle, 2 fire (the title starts the game);
456
+ 24 left + fire, 10 fire, 30 right, 24 still (the first dart's dot hits the
457
+ ship: one life lost); 16 left, 32 right, 16 left, all firing (the weave of
458
+ saucers); 20 still; 40 fire through the gap between two parade columns;
459
+ 24 left, 3 down. 240 play frames (the second fire frame on the title is
460
+ play frame 0), then still. The meter records the first 240.
461
+
462
+ The game freezes on the first frame after that with YSCROLL 3 (play frame
463
+ 243, 30 rows scrolled), then saves the high score to drive 8, loads it
464
+ back, and grades 18 facts (main.c `first_fail`): the showing screen equals
465
+ the map; one loss and two lives left; score = the points of what was shot;
466
+ score 450 and 5 kills; every wave the scroll reached has started; the frame
467
+ IRQ applied YSCROLL 3 and the right screen (read from `$D011` and
468
+ `$D018`); the multiplexer shows 11 sprites; the ten parade bugs are where
469
+ their paths end; the ship is where the script leaves it (X 120, Y 176, by
470
+ arithmetic); effects ran; the HISCORE round trip returned 45; no play frame
471
+ ran into the next; every bullet cell the last draw changed held the map's
472
+ code again after every erase (`bullets_restored`, each frame); 10 dots
473
+ fired (5 darts at Y 72, 5 saucers at Y 88, from the paths); and the loss
474
+ was a dot, not a ram. By play frame, from the `-dEVENTLOG=1` build, the
475
+ same on PAL and NTSC: a dart shot at 37, the dot at 71, saucers shot at 94,
476
+ 113, 121 and 128. Before enemy fire the review's Python model matched the
477
+ same kills frame for frame, with a ram at 71.
478
+
479
+ Mutations, each run through its target (the review's are in its report):
480
+
481
+ | Mutation | Target | Result |
482
+ |---|---|---|
483
+ | The split's phase-5 delay 5 to 7 | `make check` | phases fail YSCROLL 5, PAL and NTSC; the graded shot alone passed |
484
+ | One play frame about 2,400 cycles late (M8a) | `make check` | verdict red, `OVERRUNS 02` PAL, `03` NTSC; the first count passed it with `00` |
485
+ | The same late frame in the joy build (M8b) | `make joytest` | lost frames counted, joytest fails |
486
+ | The erase skips the first cell (`if (p && i)` before, now `beq` after `dey` in cb_erase) | `make check` | verdict red (fact 16) |
487
+ | Enemies never fire (`on_enemy_fire` removed) | `make check` | verdict red, LIVES 3, the ship's end moves |
488
+ | Dots never hurt the ship (`on_ship_shot` removed) | `make check` | verdict red, LIVES 3 |
489
+ | The stage meter's hold back to PLAY_FRAMES | `make stage` | "Integer constant truncated", frames 144 not 250 |
490
+ | The stage leaves sprites over the readout | `make stage` | the meter check cannot read row 13 |
491
+ | The save writes no record | `make joytest` | the reboot never shows HI 000600 |
492
+ | No `hold_screen()` before the start-up read | a release shot at 6,000,000 cycles | the title text is gone (it was there) |
493
+
494
+ `make check` first runs `make phases`: the game frozen on each of the eight
495
+ YSCROLL phases, PAL and NTSC, with panel lines 215-250 compared to the
496
+ graded phase-3 shot.
497
+
498
+ `expect.json` checks the border and four text rows, the meter (240 frames,
499
+ worst within a frame), the ship's and all ten bugs' bounding boxes (so the
500
+ multiplexer shows eleven sprites), four pixels that place the river's banks
501
+ at 30 rows scrolled, the split (line 214 playfield, line 216 panel grey),
502
+ the panel's rule, background and two lives, and the panel and playfield
503
+ identical on PAL and NTSC. FORCE_FAULT starts the ship 16 pixels right: it
504
+ shoots 4 instead of 5 (400 points), is rammed instead of shot, ends at X
505
+ 136, and check.py fails the verdict, the text and the ship's box.
506
+
507
+ `make joytest` plays the normal game (the `$02FE` joy build) headless on
508
+ PAL and NTSC: a fresh disk's title shows HI 000000, a game with fire held
509
+ and the ship swept left and right runs to GAME OVER and saves, and a reboot
510
+ on the same disk shows that score as HI; then 15 more games a model, 4
511
+ machines at once. Every game fails on a lost frame (`LOST_FRAMES`). Scores
512
+ vary from run to run (the drive steps in wall-clock time). `make longplay`
513
+ plays a `-dGOD=1` build, whose ship is never lost, for 40 s of warp a game,
514
+ 4 games a model, through the level's later loops, and fails on a lost
515
+ frame.
516
+
517
+ ## Decisions and open questions
518
+
519
+ - Oscar64 with a KickAssembler blob, not KickAssembler alone: the raster
520
+ chain, the split's delay table, the multiplexer and the row copy need
521
+ exact cycles and no zero page; waves, paths, bullets, collisions, states
522
+ and the disk file are logic an agent extends, and the KB's recipes for
523
+ them are Oscar64.
524
+ - The playfield scrolls down, so the carry moves every row down. In place,
525
+ bottom row first, that is 20 rows at about 560 cycles each (the recipe's
526
+ row copy), some 11,000 cycles, while the beam reaches the top row about
527
+ 4,300 cycles after line 252 on NTSC (arithmetic, not measured): the top
528
+ rows would tear. Two screens and a `$D018` flip in the frame IRQ avoid
529
+ it. Colour RAM cannot flip, so the map is characters only, every cell
530
+ one colour RAM value.
531
+ - The panel split is the recipe's code and delays, with a multicolour
532
+ 40-column playfield, and two changes found by measuring. Entered through
533
+ the common IRQ entry, its poll started about 30 cycles late; at YSCROLL 5
534
+ on PAL the writes then reached cycle 1 of line 215 in 4 frames of every
535
+ 12 and the panel's first row showed playfield characters. The split now
536
+ has its own vector entry, as short as the recipe's pushes. Its writes
537
+ then start between cycle 58 of line 214 and cycle 0 of line 215 (PAL; 58
538
+ to 64 on NTSC), and `$D016` goes last so `$D018` lands four cycles
539
+ earlier. Freezing the game on each of the eight phases gave panel lines
540
+ 215-250 pixel-identical to YSCROLL 3 on PAL and NTSC, and 14 consecutive
541
+ frames of each phase on each model showed a clean panel row.
542
+ - Sprites stop at Y 187 (last line 208). Measured in the review of this
543
+ starter (VICE x64sc 3.10, eight sprites pinned at one Y, scrolling, 16
544
+ shots a Y spread over the phases): sprites ending on line 213 (Y 192)
545
+ left the panel clean, 0 of 16 on each model; sprites on line 214 (Y 193)
546
+ broke its first row, 16 of 16 on PAL and 4 of 16 on NTSC (one sprite
547
+ there: 8 of 16 PAL, 0 NTSC). Their DMA moves the split's `$D011` store
548
+ from cycles 58-0 to cycles 5-11 of line 215. So line 214 is the hazard;
549
+ 187 keeps 5 lines of margin. Enemies that fly lower vanish at line 208.
550
+ The same run showed the panel clean at every phase met while scrolling.
551
+ - Bullets move up 7 lines a frame while the playfield moves down 1, so a
552
+ bolt stays on rows 2-5 of its cell at every phase: one glyph per bullet.
553
+ - The meter cannot be read in the panel: check.py reads text on the
554
+ YSCROLL 3 grid, and the panel is on YSCROLL 7 (a harness finding). The
555
+ readout goes to the playfield after the freeze.
556
+ - Enemy fire is `P_FIRE` in the path bytecode, from the other #39
557
+ version's design: a 6-dot pool, dots drifting towards where the ship was,
558
+ and a fire window of sprite Y 72-140, so a dot's first cell starts on
559
+ line 77 or lower and the draw is done before the beam gets there
560
+ (measured margins above). The work that runs for every enemy or bullet
561
+ every frame moved into KickAssembler (`glyph.asm`, `hit.asm`, `step.asm`)
562
+ to keep the staged frame inside NTSC; C keeps the rules.
563
+ - Disk I/O stops the raster chain ($D01A = 0) and turns sprites off. With
564
+ sprites on, the KERNAL's serial transfers hung (NTSC 3 of 3 runs, PAL 1
565
+ of 3); the review isolated the cause with a minimal program: sprite DMA
566
+ on badline lines during the transfer (hiscore.c has the detail). The
567
+ start-up read shows the title first (`hold_screen`).
568
+ - A splat HISCORE (drive reply 60, a save cut off) is scratched and
569
+ written again, like a missing one.