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,502 @@
1
+ # Plan: beat-em-up
2
+
3
+ The side-on brawler starter for c64-kb issue #39. The tool output below was
4
+ produced on 2026-09-23 by c64-kb 0.15.0 and pasted whole.
5
+
6
+ ## Concept
7
+
8
+ A side-on street brawler: a street 128 characters long scrolls to the right
9
+ through a 38-column window in three stages, and each stage locks the camera
10
+ until its waves of enemies are beaten. The player and up to three enemies
11
+ walk on a depth plane; the nearest fighter is drawn in front. The player and
12
+ the thugs are two multicolour sprites each; the brute is drawn in character
13
+ cells, and a sprite farther away than he is goes behind him. Punch, kick and a jump kick land only on the
14
+ animation frames that carry a hit box and only on a fighter in the same
15
+ lane. Enemies approach, line up in the lane, attack and back off; a kick or
16
+ a third punch knocks a fighter down and he gets up again. Health bars and
17
+ faces in a HUD, a two-voice tune with hit effects on the third. Title, fire
18
+ to start, game over back to the title. PAL and NTSC.
19
+
20
+ ## Briefing
21
+
22
+ Command: `npx tsx src/cli.ts game-briefing "A side-on street brawler in the Double Dragon style: the street scrolls horizontally in stages that lock until the wave of enemies is cleared; fighters are several sprites each and move in depth lanes, sorted by Y for priority; punch, kick and jump attack with per-frame hitboxes; enemies approach, align in the lane, attack and retreat; knockdown and recovery; health bars in a HUD; a SID tune with hit effects. PAL and NTSC." --archetype beat-em-up`
23
+
24
+ Kept from its 16 proposals: lane_depth_engine, multi_sprite_object,
25
+ lane_pursuit_ai (the state names: approach, alongside, attack, back off),
26
+ wave_director (waves start at a scroll position), soft_scroll_h,
27
+ sid_play_routine_pattern, mob_priority ($D01B for a fighter behind the
28
+ brute). Its sprite_multiplex_24 becomes sprite_multiplex_game (the KB's game
29
+ multiplexer: double-buffered tables written by IRQs, $D010 precalculated).
30
+ mixed_sprite_char_actors was not proposed; it came in with the #39 review,
31
+ ported from the other beat-em-up draft (the brute in characters).
32
+
33
+ Dropped: `vector_balls_sprites` and `dypp_sprite_sine_scroller` (the word
34
+ "scrolls" matched demo effects), `char_scroll_buffer_h` (one buffer shifted
35
+ in place: visible while it runs, issue #18; the platformer's three pages
36
+ replace it), `self_modifying_code` and `zero_page_burst` (not needed as
37
+ named; the IRQ patches its pointer page once a frame), `stable_raster_irq`
38
+ (no split here needs a stable cycle), `sprite_collision_detect` (hits are
39
+ software boxes gated by depth, which $D01E cannot see).
40
+
41
+ Added, not proposed: screen_double_buffer_d018, tile_map_render,
42
+ raster_split_modes (the HUD needs its own $D016 and $D018),
43
+ per_frame_hitbox, sprite_animation_table, jump_arc_table, object_pool,
44
+ sfx_engine_beside_music, frame_sync_loop, joystick_edge_detect,
45
+ decimal_print, raster_profile_bars (the meter).
46
+
47
+ Pitfalls the briefing and `pitfalls-for` name that this program meets:
48
+ sprite_dma_overflow (a reused sprite needs its last use finished: the
49
+ multiplexer reuses a sprite only across bands 5 or more lines apart),
50
+ sprite_x_high_bit_wrong_register and sprite_x_range_hidden_and_seam (world
51
+ X is 16 bits; a part outside the window is switched off),
52
+ xscroll_applies_to_all_rows and d016_unmasked_rmw_clobbers_csel_mcm (the
53
+ HUD split writes whole values), vic_bank_visibility_collision (bank 3 has
54
+ no ROM font: glyphs are copied), full_field_redraw_exceeds_vblank (the
55
+ scroll prepares a hidden page in slices), decimal_mode_in_irq_handler (the
56
+ IRQs do no arithmetic that depends on D), pal_ntsc_tempo_mismatch (one step
57
+ a frame: 6/5 as fast on NTSC), signed_compare_bmi_overflow (distances are
58
+ computed as ints), vic_colour_register_upper_nibble_reads_set (the verdict
59
+ masks colour reads with 15).
60
+
61
+ ## Techniques
62
+
63
+ | Technique | Why | Recipe it starts from | Pitfalls read (`pitfalls-for`) |
64
+ |---|---|---|---|
65
+ | tile_map_render | 2 x 2 metatiles from the street text; one new column per coarse step | oscar64-tile-map-render | full_field_redraw_exceeds_vblank, colour_ram_index_past_last_cell_hits_cia1 |
66
+ | soft_scroll_h | XSCROLL for the pixel; the column step is a page flip | the platformer starter's view.c | xscroll_applies_to_all_rows, d016_unmasked_rmw_clobbers_csel_mcm |
67
+ | screen_double_buffer_d018 | two pages: one shown, the other prepared four rows a frame | the platformer starter's view.c | full_field_redraw_exceeds_vblank, vic_bank_visibility_collision |
68
+ | raster_split_modes | the HUD under the street gets 40 columns, hires and its own page at line 212 | the platformer starter's engine.asm | xscroll_applies_to_all_rows, raster_irq_first_line_jitter, idle_fetch_byte_shows_in_gaps |
69
+ | lane_depth_engine | plane Y is depth: sorted every frame, nearest fighter in the lowest sprites, hits gated by a 6-line window | oscar64-beat-em-up-lanes | sprite_x_high_bit_wrong_register, sprite_x_range_hidden_and_seam |
70
+ | multi_sprite_object | a fighter is two parts at per-pose offsets from his feet | oscar64-multi-sprite-object | sprite_registers_persist_across_state_change, sprite_x_range_hidden_and_seam |
71
+ | mixed_sprite_char_actors | the brute in 5 x 6 character cells, pre-shifted, built a row a frame into the character set not shown | oscar64-mixed-fighters (and the other #39 draft's actors.h) | dirty_cell_skip_leaves_overlay_trail, full_field_redraw_exceeds_vblank, vic_bank_visibility_collision |
72
+ | mob_priority | $D01B for every sprite of a fighter farther away than the brute; the street keeps to bit pairs 00 and 01 | kickassembler-sprite-priority-classes | sprite_registers_persist_across_state_change, sprite_priority_collision_silent |
73
+ | sprite_multiplex_game | three bands a frame (sign, fighters, HUD faces) from double-buffered tables the IRQs write | kickassembler-sprite-multiplex-game | sprite_dma_overflow, decimal_mode_in_irq_handler, d012_wrap_around |
74
+ | per_frame_hitbox | an attack frame carries a hit box; every pose a hurt box | oscar64-per-frame-hitbox | sprite_x_high_bit_wrong_register |
75
+ | sprite_animation_table | fighter moves as (pose, frames, box) tables | oscar64-sprite-animation-table | vic_bank_visibility_collision |
76
+ | jump_arc_table | the jump and the knock-down flight from one height table | oscar64-fixed-point-jump-velocity | pal_ntsc_tempo_mismatch |
77
+ | lane_pursuit_ai | enemy states: approach, line up, attack, back off, wait for a turn | oscar64-lane-pursuit | signed_compare_bmi_overflow, pal_ntsc_tempo_mismatch |
78
+ | wave_director | each stage's waves start when the camera reaches the stage's lock | oscar64-wave-director | sprite_x_high_bit_wrong_register |
79
+ | object_pool | three enemy slots | oscar64-object-pool | sprite_x_range_hidden_and_seam |
80
+ | sid_play_routine_pattern | an original two-voice tune, init and play in KickAssembler | the platformer starter's engine.asm | pal_ntsc_tempo_mismatch, sid_write_only_registers |
81
+ | sfx_engine_beside_music | punch, hit, knock-down, jump on voice 3, which the tune leaves alone | oscar64-sfx-engine | sid_adsr_bug_8580, sid_write_only_registers |
82
+ | frame_sync_loop | one pass a frame, started by the IRQ at line 251 | oscar64-frame-sync-loop | d012_wrap_around, badline_cycle_loss |
83
+ | joystick_edge_detect | an attack starts on the fire press | oscar64-joystick-input | joystick2_scan_phantom_press, cia1_ddr_cleared_kills_keyboard |
84
+ | decimal_print | six score digits added digit by digit | oscar64-print-number | petscii_written_to_screen_ram |
85
+ | raster_profile_bars | the harness meter, CIA2 timer A; the IRQs time themselves on timer B | oscar64-raster-profile-bars | badline_cycle_loss, vic_bus_takeover_on_dma |
86
+
87
+ ## Compatibility
88
+
89
+ Command: `npx tsx src/cli.ts check-compatibility tile_map_render soft_scroll_h screen_double_buffer_d018 raster_split_modes lane_depth_engine multi_sprite_object mixed_sprite_char_actors mob_priority sprite_multiplex_game per_frame_hitbox sprite_animation_table jump_arc_table lane_pursuit_ai wave_director object_pool sid_play_routine_pattern sfx_engine_beside_music frame_sync_loop joystick_edge_detect decimal_print raster_profile_bars`
90
+
91
+ ```text
92
+ # Compatibility: tile_map_render + soft_scroll_h + screen_double_buffer_d018 + raster_split_modes + lane_depth_engine + multi_sprite_object + mixed_sprite_char_actors + mob_priority + sprite_multiplex_game + per_frame_hitbox + sprite_animation_table + jump_arc_table + lane_pursuit_ai + wave_director + object_pool + sid_play_routine_pattern + sfx_engine_beside_music + frame_sync_loop + joystick_edge_detect + decimal_print + raster_profile_bars
93
+
94
+ **Verdict:** INCOMPATIBLE — not as combined; each hard conflict below says how to separate them.
95
+
96
+ Checked with 4 implied prerequisite(s): fixed_point_8_8, screen_ram_relocation, sid_voice_setup, tile_grid_collision.
97
+
98
+ Unit claims are stated for 6 of 21 techniques; a unit conflict cannot be ruled out for: tile_map_render, soft_scroll_h, screen_double_buffer_d018, lane_depth_engine, multi_sprite_object, mixed_sprite_char_actors, mob_priority, per_frame_hitbox, sprite_animation_table, jump_arc_table, wave_director, object_pool, frame_sync_loop, decimal_print, raster_profile_bars, fixed_point_8_8 (prerequisite), screen_ram_relocation (prerequisite), sid_voice_setup (prerequisite), tile_grid_collision (prerequisite). The zero-page bytes and interrupt vectors a recipe chooses are not checked yet (issue #22, step 8).
99
+
100
+ ## shared_register (soft): soft_scroll_h × raster_split_modes
101
+ **Shared:** SCROLX
102
+ Both techniques touch register(s) SCROLX. 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 × raster_split_modes
105
+ **Shared:** VMCSB, SCROLY
106
+ 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.
107
+
108
+ ## shared_register (soft): screen_double_buffer_d018 × mixed_sprite_char_actors
109
+ **Shared:** VMCSB
110
+ 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.
111
+
112
+ ## shared_register (soft): screen_double_buffer_d018 × frame_sync_loop
113
+ **Shared:** SCROLY
114
+ 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.
115
+
116
+ ## shared_register (soft): raster_split_modes × mixed_sprite_char_actors
117
+ **Shared:** VMCSB
118
+ 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.
119
+
120
+ ## unit_contention (hard): raster_split_modes × sprite_multiplex_game
121
+ **Shared:** vic_raster_irq
122
+ Both raster_split_modes and sprite_multiplex_game own vic_raster_irq: each writes or holds it every frame and expects no one else to.
123
+ **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.
124
+
125
+ ## shared_register (soft): raster_split_modes × frame_sync_loop
126
+ **Shared:** SCROLY
127
+ 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.
128
+
129
+ ## shared_register (soft): lane_depth_engine × multi_sprite_object
130
+ **Shared:** SP0COL, MSIGX, M0Y, M0X
131
+ Both techniques touch register(s) SP0COL, MSIGX, M0Y, M0X. 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.
132
+
133
+ ## shared_register (soft): lane_depth_engine × mixed_sprite_char_actors
134
+ **Shared:** MSIGX, M0Y, M0X
135
+ Both techniques touch register(s) MSIGX, M0Y, M0X. 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.
136
+
137
+ ## shared_register (soft): lane_depth_engine × sprite_multiplex_game
138
+ **Shared:** SP0COL, MSIGX, M0Y, M0X
139
+ Both techniques touch register(s) SP0COL, MSIGX, M0Y, M0X. 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.
140
+
141
+ ## shared_register (soft): lane_depth_engine × per_frame_hitbox
142
+ **Shared:** MSIGX
143
+ 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.
144
+
145
+ ## shared_register (soft): multi_sprite_object × mixed_sprite_char_actors
146
+ **Shared:** MSIGX, M0Y, M0X
147
+ Both techniques touch register(s) MSIGX, M0Y, M0X. 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.
148
+
149
+ ## shared_register (soft): multi_sprite_object × sprite_multiplex_game
150
+ **Shared:** SP0COL, SPENA, MSIGX, M0Y, M0X
151
+ Both techniques touch register(s) SP0COL, SPENA, MSIGX, M0Y, M0X. 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.
152
+
153
+ ## shared_register (soft): multi_sprite_object × per_frame_hitbox
154
+ **Shared:** MSIGX
155
+ 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.
156
+
157
+ ## shared_register (soft): mixed_sprite_char_actors × mob_priority
158
+ **Shared:** SPBGPR
159
+ Both techniques touch register(s) SPBGPR. 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.
160
+
161
+ ## shared_register (soft): mixed_sprite_char_actors × sprite_multiplex_game
162
+ **Shared:** MSIGX, M0Y, M0X
163
+ Both techniques touch register(s) MSIGX, M0Y, M0X. 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.
164
+
165
+ ## shared_register (soft): mixed_sprite_char_actors × per_frame_hitbox
166
+ **Shared:** MSIGX
167
+ 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.
168
+
169
+ ## shared_register (soft): sprite_multiplex_game × per_frame_hitbox
170
+ **Shared:** MSIGX
171
+ 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.
172
+
173
+ ## shared_register (soft): sprite_multiplex_game × frame_sync_loop
174
+ **Shared:** RASTER
175
+ 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.
176
+
177
+ ## unit_shared (soft): sid_play_routine_pattern × sfx_engine_beside_music
178
+ **Shared:** sid_voice_2
179
+ sid_play_routine_pattern owns sid_voice_2; sfx_engine_beside_music writes it under sid_play_routine_pattern's protocol.
180
+ **Resolution:** sfx_engine_beside_music must follow sid_play_routine_pattern's protocol: write after sid_play_routine_pattern's write in the frame, or run inside sid_play_routine_pattern's interrupt chain.
181
+
182
+ ## shared_register (soft): sid_play_routine_pattern × sfx_engine_beside_music
183
+ **Shared:** SIGVOL, SUREL3, ATDCY3, VCREG3, PWHI3, PWLO3, FREHI3, FRELO3, SUREL2, ATDCY2, VCREG2, PWHI2, PWLO2, FREHI2, FRELO2, SUREL1, ATDCY1, VCREG1, PWHI1, PWLO1, FREHI1, FRELO1
184
+ Both techniques touch register(s) SIGVOL, 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.
185
+
186
+ ## shared_register (soft): frame_sync_loop × raster_profile_bars
187
+ **Shared:** EXTCOL
188
+ Both techniques touch register(s) EXTCOL. 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.
189
+
190
+
191
+ ## Not covered
192
+ - **tile_map_render**: the graph has no registers, KERNAL routines or demands for it; the verdict says nothing about it.
193
+ - **sprite_animation_table**: the graph has no registers, KERNAL routines or demands for it; the verdict says nothing about it.
194
+ - **jump_arc_table**: the graph has no registers, KERNAL routines or demands for it; the verdict says nothing about it.
195
+ - **wave_director**: the graph has no registers, KERNAL routines or demands for it; the verdict says nothing about it.
196
+ - **object_pool**: the graph has no registers, KERNAL routines or demands for it; the verdict says nothing about it.
197
+ - **decimal_print**: the graph has no registers, KERNAL routines or demands for it; the verdict says nothing about it.
198
+ - **fixed_point_8_8** (prerequisite of jump_arc_table, lane_pursuit_ai): the graph has no registers, KERNAL routines or demands for it.
199
+ - **tile_grid_collision** (prerequisite of lane_pursuit_ai): the graph has no registers, KERNAL routines or demands for it.
200
+
201
+ ## Shared Infrastructure (info)
202
+ - **fixed_point_8_8** (prerequisite, not in the set): required by jump_arc_table, lane_pursuit_ai; included in the check as implied. Set it up first.
203
+ - **screen_ram_relocation** (prerequisite, not in the set): required by screen_double_buffer_d018; included in the check as implied. Set it up first.
204
+ - **sid_voice_setup** (prerequisite, not in the set): required by sfx_engine_beside_music, sid_play_routine_pattern; included in the check as implied. Set it up first.
205
+ - **tile_grid_collision** (prerequisite, not in the set): required by lane_pursuit_ai; included in the check as implied. Set it up first.
206
+ - **DC0E** (Register) shared via recipe(s): oscar64-wave-director, oscar64-flip-screen-rooms, oscar64-falling-blocks
207
+ - **DC05** (Register) shared via recipe(s): oscar64-wave-director, oscar64-flip-screen-rooms, oscar64-falling-blocks
208
+ - **DC04** (Register) shared via recipe(s): oscar64-wave-director, oscar64-flip-screen-rooms, oscar64-falling-blocks
209
+ - **SP0COL** (Register) shared via recipe(s): oscar64-wave-director, oscar64-mixed-fighters, oscar64-flip-screen-rooms, oscar64-platformer-scaffold
210
+ - **BGCOL0** (Register) shared via recipe(s): oscar64-wave-director, kickassembler-cracktro-template, oscar64-mixed-fighters, kickassembler-eight-way-scroll, oscar64-flip-screen-rooms, oscar64-platformer-scaffold, oscar64-falling-blocks
211
+ - **EXTCOL** (Register) shared via recipe(s): oscar64-wave-director, kickassembler-cracktro-template, oscar64-mixed-fighters, kickassembler-eight-way-scroll, oscar64-flip-screen-rooms, oscar64-platformer-scaffold, oscar64-falling-blocks
212
+ - **SPENA** (Register) shared via recipe(s): oscar64-wave-director, oscar64-mixed-fighters, oscar64-flip-screen-rooms, oscar64-platformer-scaffold
213
+ - **RASTER** (Register) shared via recipe(s): oscar64-wave-director, kickassembler-cracktro-template, kickassembler-eight-way-scroll, oscar64-flip-screen-rooms, oscar64-platformer-scaffold, oscar64-falling-blocks
214
+ - **SCROLY** (Register) shared via recipe(s): oscar64-wave-director, kickassembler-cracktro-template, oscar64-mixed-fighters, kickassembler-eight-way-scroll, oscar64-flip-screen-rooms, oscar64-platformer-scaffold, oscar64-falling-blocks
215
+ - **MSIGX** (Register) shared via recipe(s): oscar64-wave-director, oscar64-mixed-fighters, oscar64-flip-screen-rooms, oscar64-platformer-scaffold
216
+ - **M0Y** (Register) shared via recipe(s): oscar64-wave-director, oscar64-mixed-fighters, oscar64-flip-screen-rooms, oscar64-platformer-scaffold
217
+ - **M0X** (Register) shared via recipe(s): oscar64-wave-director, oscar64-mixed-fighters, oscar64-flip-screen-rooms, oscar64-platformer-scaffold
218
+ - **DC0D** (Register) shared via recipe(s): kickassembler-cracktro-template, kickassembler-eight-way-scroll
219
+ - **IRQMSK** (Register) shared via recipe(s): kickassembler-cracktro-template, kickassembler-eight-way-scroll, oscar64-platformer-scaffold
220
+ - **VICIRQ** (Register) shared via recipe(s): kickassembler-cracktro-template, kickassembler-eight-way-scroll, oscar64-platformer-scaffold
221
+ - **VMCSB** (Register) shared via recipe(s): kickassembler-cracktro-template, oscar64-mixed-fighters, kickassembler-eight-way-scroll
222
+ - **SCROLX** (Register) shared via recipe(s): kickassembler-cracktro-template, oscar64-mixed-fighters, kickassembler-eight-way-scroll
223
+ - **SIGVOL** (Register) shared via recipe(s): kickassembler-cracktro-template, oscar64-platformer-scaffold
224
+ - **DC00** (Register) shared via recipe(s): kickassembler-cracktro-template, oscar64-flip-screen-rooms, oscar64-platformer-scaffold, oscar64-falling-blocks
225
+ - **DC0F** (Register) shared via recipe(s): oscar64-mixed-fighters, kickassembler-eight-way-scroll, oscar64-flip-screen-rooms, oscar64-platformer-scaffold
226
+ - **DC07** (Register) shared via recipe(s): oscar64-mixed-fighters, kickassembler-eight-way-scroll, oscar64-flip-screen-rooms, oscar64-platformer-scaffold
227
+ - **DC06** (Register) shared via recipe(s): oscar64-mixed-fighters, kickassembler-eight-way-scroll, oscar64-flip-screen-rooms, oscar64-platformer-scaffold
228
+ - **SP3COL** (Register) shared via recipe(s): oscar64-mixed-fighters, oscar64-platformer-scaffold
229
+ - **SP2COL** (Register) shared via recipe(s): oscar64-mixed-fighters, oscar64-platformer-scaffold
230
+ - **SP1COL** (Register) shared via recipe(s): oscar64-mixed-fighters, oscar64-platformer-scaffold
231
+ - **SPMC1** (Register) shared via recipe(s): oscar64-mixed-fighters
232
+ - **SPMC0** (Register) shared via recipe(s): oscar64-mixed-fighters
233
+ - **BGCOL2** (Register) shared via recipe(s): oscar64-mixed-fighters
234
+ - **BGCOL1** (Register) shared via recipe(s): oscar64-mixed-fighters
235
+ - **XXPAND** (Register) shared via recipe(s): oscar64-mixed-fighters, oscar64-flip-screen-rooms
236
+ - **SPMC** (Register) shared via recipe(s): oscar64-mixed-fighters, oscar64-flip-screen-rooms
237
+ - **SPBGPR** (Register) shared via recipe(s): oscar64-mixed-fighters
238
+ - **YXPAND** (Register) shared via recipe(s): oscar64-mixed-fighters, oscar64-flip-screen-rooms
239
+ - **M3Y** (Register) shared via recipe(s): oscar64-mixed-fighters
240
+ - **M3X** (Register) shared via recipe(s): oscar64-mixed-fighters
241
+ - **M2Y** (Register) shared via recipe(s): oscar64-mixed-fighters
242
+ - **M2X** (Register) shared via recipe(s): oscar64-mixed-fighters
243
+ - **M1Y** (Register) shared via recipe(s): oscar64-mixed-fighters
244
+ - **M1X** (Register) shared via recipe(s): oscar64-mixed-fighters
245
+ - **DD0D** (Register) shared via recipe(s): kickassembler-eight-way-scroll
246
+ - **CHRIN** (KernalRoutine) shared via recipe(s): oscar64-platformer-scaffold
247
+ - **CHROUT** (KernalRoutine) shared via recipe(s): oscar64-platformer-scaffold
248
+ - **CLRCHN** (KernalRoutine) shared via recipe(s): oscar64-platformer-scaffold
249
+ - **CHKOUT** (KernalRoutine) shared via recipe(s): oscar64-platformer-scaffold
250
+ - **CHKIN** (KernalRoutine) shared via recipe(s): oscar64-platformer-scaffold
251
+ - **CLOSE** (KernalRoutine) shared via recipe(s): oscar64-platformer-scaffold
252
+ - **OPEN** (KernalRoutine) shared via recipe(s): oscar64-platformer-scaffold
253
+ - **SETNAM** (KernalRoutine) shared via recipe(s): oscar64-platformer-scaffold
254
+ - **SETLFS** (KernalRoutine) shared via recipe(s): oscar64-platformer-scaffold
255
+ - **DC03** (Register) shared via recipe(s): oscar64-platformer-scaffold
256
+ - **DC02** (Register) shared via recipe(s): oscar64-platformer-scaffold
257
+ - **SP6COL** (Register) shared via recipe(s): oscar64-platformer-scaffold
258
+ - **SP5COL** (Register) shared via recipe(s): oscar64-platformer-scaffold
259
+ - **SP4COL** (Register) shared via recipe(s): oscar64-platformer-scaffold
260
+ - **RANDOM** (Register) shared via recipe(s): oscar64-platformer-scaffold
261
+ - **SUREL3** (Register) shared via recipe(s): oscar64-platformer-scaffold
262
+ - **ATDCY3** (Register) shared via recipe(s): oscar64-platformer-scaffold
263
+ - **VCREG3** (Register) shared via recipe(s): oscar64-platformer-scaffold
264
+ - **PWHI3** (Register) shared via recipe(s): oscar64-platformer-scaffold
265
+ - **PWLO3** (Register) shared via recipe(s): oscar64-platformer-scaffold
266
+ - **FREHI3** (Register) shared via recipe(s): oscar64-platformer-scaffold
267
+ - **FRELO3** (Register) shared via recipe(s): oscar64-platformer-scaffold
268
+ - **SUREL2** (Register) shared via recipe(s): oscar64-platformer-scaffold
269
+ - **ATDCY2** (Register) shared via recipe(s): oscar64-platformer-scaffold
270
+ - **VCREG2** (Register) shared via recipe(s): oscar64-platformer-scaffold
271
+ - **PWHI2** (Register) shared via recipe(s): oscar64-platformer-scaffold
272
+ - **PWLO2** (Register) shared via recipe(s): oscar64-platformer-scaffold
273
+ - **FREHI2** (Register) shared via recipe(s): oscar64-platformer-scaffold
274
+ - **FRELO2** (Register) shared via recipe(s): oscar64-platformer-scaffold
275
+ - **SUREL1** (Register) shared via recipe(s): oscar64-platformer-scaffold
276
+ - **ATDCY1** (Register) shared via recipe(s): oscar64-platformer-scaffold
277
+ - **VCREG1** (Register) shared via recipe(s): oscar64-platformer-scaffold
278
+ - **PWHI1** (Register) shared via recipe(s): oscar64-platformer-scaffold
279
+ - **PWLO1** (Register) shared via recipe(s): oscar64-platformer-scaffold
280
+ - **FREHI1** (Register) shared via recipe(s): oscar64-platformer-scaffold
281
+ - **FRELO1** (Register) shared via recipe(s): oscar64-platformer-scaffold
282
+ - **READST** (KernalRoutine) shared via recipe(s): oscar64-platformer-scaffold
283
+ - **raster_discipline**: Multiple raster-discipline techniques present. Verify IRQ stack ordering and timing budget.
284
+ ```
285
+
286
+ What the warnings mean for this program:
287
+
288
+ - The hard conflict, raster_split_modes x sprite_multiplex_game over
289
+ vic_raster_irq: its resolution is followed. One chain in engine.asm owns
290
+ $D012: line 251 (playfield registers, the sign band), line 76 (the fighter
291
+ band), line 212 (the HUD split and the face band). Each handler sets the
292
+ next. Adding irq_chain_table to the set to say so makes the verdict worse
293
+ (it reports irq_chain_table against both as new hard conflicts), so it is
294
+ not in the set.
295
+ - SCROLX, VMCSB, SCROLY shared by the scroll, the split and the frame loop:
296
+ $D016 and $D018 are written only by the IRQs at 251 and 212, from a pair C
297
+ publishes once a frame. $D011 is written once at start.
298
+ - The sprite registers shared by lane_depth_engine, multi_sprite_object,
299
+ mixed_sprite_char_actors, mob_priority, sprite_multiplex_game and
300
+ per_frame_hitbox: only the IRQs write them. C builds the band tables; the
301
+ depth sort decides which parts go to which sprite and which have $D01B.
302
+ - VMCSB and SCROLY shared by mixed_sprite_char_actors, the double buffer and
303
+ the split: the brute's character set is a bit of the $D018 C publishes with
304
+ the page flip; the IRQ at 251 writes it, the one at 212 the HUD's.
305
+ - sid_voice_2 shared by the tune and the effects: the tune plays voices 1
306
+ and 2; the effects own voice 3. The tool's "sid_voice_2" is its own label,
307
+ not this program's split.
308
+ - EXTCOL: only the start and the verdict write $D020.
309
+
310
+ ## Budget
311
+
312
+ Command: `npx tsx src/cli.ts plan-budget tile_map_render soft_scroll_h screen_double_buffer_d018 raster_split_modes lane_depth_engine multi_sprite_object mixed_sprite_char_actors mob_priority sprite_multiplex_game per_frame_hitbox sprite_animation_table jump_arc_table lane_pursuit_ai wave_director object_pool sid_play_routine_pattern sfx_engine_beside_music frame_sync_loop joystick_edge_detect decimal_print raster_profile_bars --region both --sprites 8 --sprite-lines 42`
313
+
314
+ ```text
315
+ # Budget plan: undetermined
316
+
317
+ Techniques: tile_map_render, soft_scroll_h, screen_double_buffer_d018, raster_split_modes, lane_depth_engine, multi_sprite_object, mixed_sprite_char_actors, mob_priority, sprite_multiplex_game, per_frame_hitbox, sprite_animation_table, jump_arc_table, lane_pursuit_ai, wave_director, object_pool, sid_play_routine_pattern, sfx_engine_beside_music, frame_sync_loop, joystick_edge_detect, decimal_print, raster_profile_bars
318
+
319
+ ## play (PAL, 19656 cycles a frame): undetermined
320
+
321
+ Range 43027-49976 + 1873 fixed cycles; floor 0; weakest basis arithmetic; IRQ slots 19.
322
+
323
+ Summed:
324
+ - tile_map_render: 268 (arithmetic, on oscar64-tile-map-render (one column edge, 11 metatiles))
325
+ - lane_depth_engine: 1413 (measured-vice, on oscar64-beat-em-up-lanes (four actors: sort, priority draw and hit test in one step, screen on))
326
+ - multi_sprite_object: 1342 (measured-vice, on oscar64-multi-sprite-object (worst frame, six parts, in the vertical blank))
327
+ - mixed_sprite_char_actors: 6108 (measured-vice, on oscar64-mixed-fighters (worst tick of the whole actor update, PAL))
328
+ - sprite_multiplex_game: 16600 (arithmetic, on kickassembler-sprite-multiplex-game (worst frame: a reversed sort))
329
+ - per_frame_hitbox: 3693 (measured-vice, on oscar64-per-frame-hitbox (eight boxes, 28 pairs))
330
+ - sprite_animation_table: 357-747 (measured-vice, on oscar64-sprite-animation-table (six actors, the scenario's worst frame))
331
+ - lane_pursuit_ai: 9871-14204 (measured-vice, on oscar64-lane-pursuit (worst frame: the spawn table's two same-frame spawns, then four cars on the ram path, one in contact, each with an eight-probe swept span and both room scans, screen blanked; typical: worst frame of the 780-step run, screen blanked))
332
+ - wave_director: 1170-3188 (measured-vice, on oscar64-wave-director (worst frame, screen blanked))
333
+ - sid_play_routine_pattern: 327 (measured-vice, on oscar64-sfx-engine (the recipe's stub tune; a real player costs several times more))
334
+ - sfx_engine_beside_music: 50-258 (measured-vice, on oscar64-sfx-engine (a frame the engine owns the voice))
335
+ - decimal_print: 1361 (measured-vice, on oscar64-print-number (one call, worst decimal case))
336
+ - raster_profile_bars: 467 (measured-vice, on oscar64-raster-profile-bars (worst frame, screen blanked))
337
+
338
+ Left out:
339
+ - object_pool: not added, inside wave_director's figure (Cost includes)
340
+ - soft_scroll_h: 74041 cycles, above one frame: a multi-frame operation, not summed (measured on oscar64-soft-scroll-h)
341
+
342
+ To measure:
343
+ - screen_double_buffer_d018: no **Cost:** line; measure it on kickassembler-eight-way-scroll
344
+ - raster_split_modes: no **Cost:** line; no recipe yet
345
+ - mob_priority: no **Cost:** line; measure it on kickassembler-sprite-priority-classes
346
+ - jump_arc_table: no **Cost:** line; measure it on oscar64-fixed-point-jump
347
+ - frame_sync_loop: the Cost line has no cycles_per_frame (nor cycles_per_line with lines_active); measure it on oscar64-frame-sync-loop
348
+ - joystick_edge_detect: no **Cost:** line; measure it on oscar64-attract-replay
349
+
350
+ Notes:
351
+ - Fixed losses 1873 cycles (badlines 25 × 43 = 1075, lines 51-243 every eighth with YSCROLL 3, sprite DMA 798; arithmetic) charged because tile_map_render, multi_sprite_object, mixed_sprite_char_actors, sprite_multiplex_game, per_frame_hitbox, sprite_animation_table, lane_pursuit_ai, wave_director, sid_play_routine_pattern, sfx_engine_beside_music, decimal_print, raster_profile_bars 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: lane_depth_engine 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.
352
+ - The low end, 43027 + 1873, passes the 19656-cycle frame, but it is not a floor: the figures of tile_map_render, lane_depth_engine, multi_sprite_object, mixed_sprite_char_actors, sprite_multiplex_game, per_frame_hitbox, sprite_animation_table, lane_pursuit_ai, wave_director, sid_play_routine_pattern, sfx_engine_beside_music, decimal_print, raster_profile_bars are a common frame or a real run's worst, and those frames need not fall together. tile_map_render, lane_depth_engine, multi_sprite_object, mixed_sprite_char_actors, sprite_multiplex_game, per_frame_hitbox, sid_play_routine_pattern, decimal_print, raster_profile_bars 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.
353
+ - Unknown is not zero: screen_double_buffer_d018, raster_split_modes, mob_priority, jump_arc_table, frame_sync_loop, joystick_edge_detect have no cycles figure, so the verdict cannot be fits.
354
+ - Multi-frame: soft_scroll_h (74041) is above one PAL frame of 19656 and not summed; spread the work over frames or budget it as its own phase.
355
+
356
+ ## play (NTSC, 17095 cycles a frame): undetermined
357
+
358
+ Range 43027-49976 + 1873 fixed cycles; floor 0; weakest basis arithmetic; IRQ slots 19.
359
+
360
+ Summed:
361
+ - tile_map_render: 268 (arithmetic, on oscar64-tile-map-render (one column edge, 11 metatiles))
362
+ - lane_depth_engine: 1413 (measured-vice, on oscar64-beat-em-up-lanes (four actors: sort, priority draw and hit test in one step, screen on))
363
+ - multi_sprite_object: 1342 (measured-vice, on oscar64-multi-sprite-object (worst frame, six parts, in the vertical blank))
364
+ - mixed_sprite_char_actors: 6108 (measured-vice, on oscar64-mixed-fighters (worst tick of the whole actor update, PAL))
365
+ - sprite_multiplex_game: 16600 (arithmetic, on kickassembler-sprite-multiplex-game (worst frame: a reversed sort))
366
+ - per_frame_hitbox: 3693 (measured-vice, on oscar64-per-frame-hitbox (eight boxes, 28 pairs))
367
+ - sprite_animation_table: 357-747 (measured-vice, on oscar64-sprite-animation-table (six actors, the scenario's worst frame))
368
+ - lane_pursuit_ai: 9871-14204 (measured-vice, on oscar64-lane-pursuit (worst frame: the spawn table's two same-frame spawns, then four cars on the ram path, one in contact, each with an eight-probe swept span and both room scans, screen blanked; typical: worst frame of the 780-step run, screen blanked))
369
+ - wave_director: 1170-3188 (measured-vice, on oscar64-wave-director (worst frame, screen blanked))
370
+ - sid_play_routine_pattern: 327 (measured-vice, on oscar64-sfx-engine (the recipe's stub tune; a real player costs several times more))
371
+ - sfx_engine_beside_music: 50-258 (measured-vice, on oscar64-sfx-engine (a frame the engine owns the voice))
372
+ - decimal_print: 1361 (measured-vice, on oscar64-print-number (one call, worst decimal case))
373
+ - raster_profile_bars: 467 (measured-vice, on oscar64-raster-profile-bars (worst frame, screen blanked))
374
+
375
+ Left out:
376
+ - object_pool: not added, inside wave_director's figure (Cost includes)
377
+ - soft_scroll_h: 74041 cycles, above one frame: a multi-frame operation, not summed (measured on oscar64-soft-scroll-h)
378
+
379
+ To measure:
380
+ - screen_double_buffer_d018: no **Cost:** line; measure it on kickassembler-eight-way-scroll
381
+ - raster_split_modes: no **Cost:** line; no recipe yet
382
+ - mob_priority: no **Cost:** line; measure it on kickassembler-sprite-priority-classes
383
+ - jump_arc_table: no **Cost:** line; measure it on oscar64-fixed-point-jump
384
+ - frame_sync_loop: the Cost line has no cycles_per_frame (nor cycles_per_line with lines_active); measure it on oscar64-frame-sync-loop
385
+ - joystick_edge_detect: no **Cost:** line; measure it on oscar64-attract-replay
386
+
387
+ Notes:
388
+ - Fixed losses 1873 cycles (badlines 25 × 43 = 1075, lines 51-243 every eighth with YSCROLL 3, sprite DMA 798; arithmetic) charged because tile_map_render, multi_sprite_object, mixed_sprite_char_actors, sprite_multiplex_game, per_frame_hitbox, sprite_animation_table, lane_pursuit_ai, wave_director, sid_play_routine_pattern, sfx_engine_beside_music, decimal_print, raster_profile_bars 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: lane_depth_engine 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.
389
+ - The low end, 43027 + 1873, passes the 17095-cycle frame, but it is not a floor: the figures of tile_map_render, lane_depth_engine, multi_sprite_object, mixed_sprite_char_actors, sprite_multiplex_game, per_frame_hitbox, sprite_animation_table, lane_pursuit_ai, wave_director, sid_play_routine_pattern, sfx_engine_beside_music, decimal_print, raster_profile_bars are a common frame or a real run's worst, and those frames need not fall together. tile_map_render, lane_depth_engine, multi_sprite_object, mixed_sprite_char_actors, sprite_multiplex_game, per_frame_hitbox, sid_play_routine_pattern, decimal_print, raster_profile_bars 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.
390
+ - Unknown is not zero: screen_double_buffer_d018, raster_split_modes, mob_priority, jump_arc_table, frame_sync_loop, joystick_edge_detect have no cycles figure, so the verdict cannot be fits.
391
+ - Multi-frame: soft_scroll_h (74041) is above one NTSC frame of 17095 and not summed; spread the work over frames or budget it as its own phase.
392
+ - 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.
393
+
394
+ ## Bytes
395
+
396
+ No member states a byte figure that can be summed.
397
+ - frame_sync_loop: 985 bytes left out, the whole program, not the technique
398
+
399
+ ## Assumptions
400
+
401
+ - Region PAL and NTSC: PAL 19656, NTSC 17095 cycles a frame.
402
+ - 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.
403
+ - 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.
404
+ - Each figure is the technique's own Cost line, measured on the recipe it names: another implementation can cost more or less.
405
+ - Claims, zero page and memory are not judged here; c64_check_compatibility judges claims and zero page.
406
+ - Sprites: 8 a line on 42 lines, (3 + 2 × 8) × 42 = 798 cycles of DMA a frame (3 + 2n measured in VICE x64sc for sprites numbered without gaps).
407
+ ```
408
+
409
+ The budget's range, 43,027 to 49,976 plus 1,873 fixed, is over two frames
410
+ (it was 36,919 to 43,868 before the brute; mixed_sprite_char_actors adds the
411
+ recipe's 6,108, a whole actor update in one tick). Most
412
+ of it is other programs' worst cases: sprite_multiplex_game's 16,600 is a
413
+ reversed sort of 24 actors (here: four fighters, and the bands need no
414
+ sort across them), lane_pursuit_ai's 9,871 to 14,204 is four cars probing a
415
+ tile map (here: three enemies comparing distances), per_frame_hitbox's
416
+ 3,693 is 28 pairs (here: at most 3 attacker-target pairs a frame). The
417
+ scroll and the split have no figure. The meter measures the whole frame,
418
+ the IRQs included; README.md, "The measured frame", compares the two.
419
+
420
+ ## Memory and screen
421
+
422
+ VIC bank 3 ($DD00 bits 0-1 = 0). $C000 and $C400: the two street pages
423
+ (rows 0-19; row 20 blank); $C800: the HUD page (rows 21-24);
424
+ $E000-$E7FF and $E800-$EFFF: two character sets, alike but for the brute's
425
+ 30 glyphs (codes 128-157); the ROM's glyphs 0-63 copied in, so text and the
426
+ meter decode; street glyphs from 64. $F000-$FFBF: 63 sprite blocks
427
+ (192-254). BASIC and KERNAL are banked out ($01 = $35), so $FFFE
428
+ and $FFFA point at the IRQ chain and an RTI. Code from $1000; the
429
+ KickAssembler blob (scroll slice copy, the IRQ chain and band writers, the
430
+ brute's glyph builder, the tune) at $0880-$0FFF. Colour RAM is never scrolled. In AUTOPILOT builds
431
+ the meter owns HUD row 24, columns 20 to 39; CIA2 timer A is the meter's,
432
+ and CIA2 timer B times the IRQs that land outside the meter's brackets.
433
+
434
+ Sprites: three bands a frame. Band 0 (from line 251): the GO sign, lines
435
+ 53-73. Band 1 (IRQ at line 76): the sprite fighters, two parts each, at most
436
+ eight parts, tops no higher than line 91; with the brute on the street, six. Band 2 (IRQ at line 212): two
437
+ faces in the HUD, lines 219-239. Within a band no sprite is reused, so a
438
+ band never drops a part; the multiplexer reuses all eight sprites between
439
+ bands.
440
+
441
+ ## Autopilot and checks
442
+
443
+ A bot, not a timeline: in AUTOPILOT builds the joystick byte is computed
444
+ from the game state each frame (fire on the title; in play, line up with
445
+ the nearest enemy, close in, then punch, punch, punch, kick, jump kick;
446
+ walk right when a stage is clear). In stage 2 it stands still from the
447
+ first wave until a life is lost, so the hero's knock-down, KO and respawn
448
+ run. At three crowded moments (four fighters in view within 24 ground
449
+ lines), two in stage 2 and one in stage 3, it holds the game still for 64
450
+ frames and prints the fighters' state on the HUD, so
451
+ `tools/flickercheck.py` can build the eight parts itself and match the
452
+ picture pixel for pixel.
453
+
454
+ The verdict, after stage 3's first wave: every event seen (punch, kick
455
+ and jump-kick hits, a knock-down, a get-up, a KO, the hero hit and down, a
456
+ life lost, the locks, a stage clear, a scroll, a lane change, a cross-lane
457
+ miss), the score equal to the sum of the hits and KOs counted, one life
458
+ lost, the band IRQ never late, no part dropped, both pages equal to the
459
+ street and the brute's cells at their columns, the hero's parts in the band
460
+ the IRQ shows, the camera at the last lock, no late play frame, three photo
461
+ stops, the brute's cell moves before his top row and two brutes beaten,
462
+ every hit's lane and boxes recomputed apart, and the fighter band read back
463
+ from the VIC every frame against an independent sort. make gameover runs a
464
+ build that never fights and checks the GAME OVER message. expect.json checks the
465
+ border, the HUD text, a health-bar cell, the hero's face in band 2, the
466
+ hero's two parts in band 1, the scrolled street at the final camera, the
467
+ kerb, the blank row 20, PAL and NTSC alike, and the meter.
468
+
469
+ ## Decisions and open questions
470
+
471
+ - Two parts a fighter, four fighters: eight sprites in the fighter band,
472
+ so no reuse inside it and nothing to drop. A third part per fighter (a
473
+ fist or a foot sprite) was the first idea; with four fighters on one
474
+ line it needs 12 sprites on those lines, which no multiplexer can give,
475
+ so reach is drawn inside the 24-pixel parts instead.
476
+ - Sprite priority follows the depth sort, not the raster order: the
477
+ nearest fighter's parts are sprites 0 and 1. (lane_depth_engine's page
478
+ says a multiplexer's slot order and the depth order "agree because both
479
+ are Y"; a Y-sorted multiplexer fills slots from the top, so the nearer
480
+ fighter would get the higher sprite and be drawn behind. Not used here.)
481
+ - The scroll is the platformer's scheme with two pages, not three: the
482
+ camera only moves right, so the page just left is never needed again. It
483
+ moves a pixel a frame and prepares four rows a frame, to fit the brute.
484
+ - The brute in characters (the review's port): two character sets switched
485
+ by $D018, so his picture changes with no cell writes; his cells are
486
+ rewritten only when he moves a whole cell. Built in C at first it took
487
+ 18,000 cycles a frame; built in KickAssembler, a row a frame, about 1,300.
488
+ - The frame had to shrink for him and for the VIC check: the AI thinks for
489
+ one enemy a frame, the HUD redraws only what changed, the photo stops
490
+ restore the HUD by copy. The meter's default window is the run's worst.
491
+ - The meter records the crowded fight (from the second stage's lock);
492
+ `-dMETER_WINDOW=1` records the walk that scrolls. README.md has both.
493
+ - Oscar64 #30 fault 8: an int loaded from an unsigned of 32,768 or more is
494
+ compared as not negative against another non-constant int, at every level,
495
+ on the local build and v1.32.273. World x is kept below 32,768 and
496
+ compared as unsigned; an enemy spawned at x -24 walked the wrong way before.
497
+ - v1.32.273 also indexed page_d018 with X before loading X in
498
+ view_publish's one-expression $D018 (read in its .asm); two statements
499
+ work on both compilers.
500
+ - NTSC runs the same per-frame steps at 60 Hz: 6/5 as fast. Not corrected.
501
+ - No disk persistence: the high score lives until power-off.
502
+ - Oscar64: the local build named in c64-kb's CLAUDE.md.