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,824 @@
1
+ // main.c: shmup-vertical, a vertically scrolling shoot-em-up starter.
2
+ //
3
+ // The river scrolls down through all eight YSCROLL phases above a fixed
4
+ // score panel. The ship is a sprite; up to twelve enemies and the ship go
5
+ // through a sprite multiplexer; waves start at map rows; bullets are
6
+ // characters; hits are boxes; effects play inside the tune; the high score
7
+ // is kept on drive 8.
8
+ //
9
+ // Files: main.c (states, the ship, the frame loop, the autopilot and its
10
+ // verdict), level.c (map and scroll), waves.c (waves, paths, enemy pool),
11
+ // bullets.c (character bullets), hitbox.c (collision), display.c (art, text,
12
+ // panel), hiscore.c (the file), kernel.asm + mux.asm + sound.asm (IRQ chain,
13
+ // panel split, multiplexer, music and effects, in KickAssembler).
14
+ //
15
+ // AUTOPILOT=1 replaces joystick port 2 with a script and grades the end
16
+ // state; FORCE_FAULT=1 starts the ship 16 pixels to the right, so its shots,
17
+ // its score and its end position all change.
18
+ #include "game.h"
19
+ #include "display.h"
20
+ #include "level.h"
21
+ #include "waves.h"
22
+ #include "bullets.h"
23
+ #include "hitbox.h"
24
+ #include "hiscore.h"
25
+ #include "frame_meter.h" // templates/_harness/meter
26
+ #include <string.h>
27
+
28
+ // ---- the kernel blob at its own address --------------------------------------
29
+ #pragma section( asmcode, 0 )
30
+ #pragma region( asmreg, ASM_ORG, 0x2000, , , { asmcode } )
31
+ #pragma region( main, 0x2000, 0x8000, , , { code, data, bss, heap, stack } )
32
+ #pragma data( asmcode )
33
+ __export const char asm_blob[] = {
34
+ #embed "asm.bin"
35
+ };
36
+ #pragma data( data )
37
+
38
+ char state;
39
+ char lives, deaths;
40
+ unsigned score, hiscore;
41
+ unsigned play_frames;
42
+
43
+ #define JOY_UP 0x01
44
+ #define JOY_DOWN 0x02
45
+ #define JOY_LEFT 0x04
46
+ #define JOY_RIGHT 0x08
47
+ #define JOY_FIRE 0x10
48
+
49
+ // ---- the ship ------------------------------------------------------------------
50
+ #define P_START_HX (84 + 8 * FORCE_FAULT) // half X: sprite X 168
51
+ #define P_START_Y 170
52
+ #define P_MIN_HX 12
53
+ #define P_MAX_HX 160
54
+ #define P_MIN_Y 110
55
+ #define P_MAX_Y 180 // below MAX_SY (187)
56
+ #define P_SAFE 100 // frames the ship is safe after a loss
57
+ #define P_COOL 6 // frames between shots
58
+
59
+ static char p_hx, p_y, p_safe, p_cool;
60
+
61
+ static void ship_reset(void)
62
+ {
63
+ p_hx = P_START_HX;
64
+ p_y = P_START_Y;
65
+ p_cool = 0;
66
+ }
67
+
68
+ static void ship_update(char joy)
69
+ {
70
+ if (!(joy & JOY_LEFT) && p_hx > P_MIN_HX) p_hx--;
71
+ if (!(joy & JOY_RIGHT) && p_hx < P_MAX_HX) p_hx++;
72
+ if (!(joy & JOY_UP) && p_y > P_MIN_Y) p_y -= 2;
73
+ if (!(joy & JOY_DOWN) && p_y < P_MAX_Y) p_y += 2;
74
+ if (p_cool)
75
+ p_cool--;
76
+ else if (!(joy & JOY_FIRE) && bullet_fire(p_hx + 6, p_y)) {
77
+ p_cool = P_COOL;
78
+ sfx(1);
79
+ }
80
+ if (p_safe)
81
+ p_safe--;
82
+ }
83
+
84
+ // ---- hits (hitbox.c reports them) ---------------------------------------------------
85
+ #ifdef EVENTLOG
86
+ // Measuring only (-dEVENTLOG=1): each kill (1), ram (2) and shot (3) with its
87
+ // play frame, 4 bytes each from $C000 (kind, enemy or bullet, frame low, high).
88
+ static char ev_n;
89
+ static void ev_log(char kind, char who)
90
+ {
91
+ volatile char *q = (volatile char *)0xc000 + 4 * ev_n++;
92
+ q[0] = kind; q[1] = who; q[2] = (char)play_frames; q[3] = play_frames >> 8;
93
+ }
94
+ #define EV(k, w) ev_log(k, w)
95
+ #else
96
+ #define EV(k, w)
97
+ #endif
98
+
99
+ void on_enemy_shot(char e, char bullet)
100
+ {
101
+ EV(1, e);
102
+ bullet_kill(bullet);
103
+ add_score(enemy_points(e));
104
+ enemy_explode(e);
105
+ sfx(2);
106
+ }
107
+
108
+ static void ship_lost(void);
109
+
110
+ void on_player_hit(char e)
111
+ {
112
+ EV(2, e);
113
+ enemy_explode(e);
114
+ ship_lost();
115
+ }
116
+
117
+ static char ship_shots; // times an enemy dot hit the ship
118
+
119
+ void on_ship_shot(char j)
120
+ {
121
+ ship_shots++;
122
+ EV(3, j);
123
+ enemy_bullet_kill(j);
124
+ ship_lost();
125
+ }
126
+
127
+ void on_enemy_fire(char e)
128
+ {
129
+ enemy_bullet_fire(e_hx[e], e_y[e], p_hx);
130
+ }
131
+
132
+ static void ship_lost(void)
133
+ {
134
+ box_off(BOX_PLAYER); // one loss a frame at most
135
+ #ifdef GOD
136
+ // Measuring only (-dGOD=1, make longplay): the ship is never lost, so a
137
+ // driven game runs through the level's later loops, where the waves come
138
+ // closer together. play_frame mirrors play_frames at $02FB.
139
+ return;
140
+ #endif
141
+ deaths++;
142
+ lives--;
143
+ sfx(3);
144
+ if (lives == 0) {
145
+ state = ST_OVER;
146
+ return;
147
+ }
148
+ ship_reset();
149
+ p_safe = P_SAFE;
150
+ }
151
+
152
+ void add_score(char tens)
153
+ {
154
+ score += tens;
155
+ if (score > hiscore)
156
+ hiscore = score;
157
+ panel_add(tens);
158
+ }
159
+
160
+ static char sfx_arg, ntsc_arg; // globals: absolute addresses for __asm
161
+
162
+ void sfx(char n)
163
+ {
164
+ sfx_arg = n;
165
+ __asm {
166
+ php
167
+ sei
168
+ lda sfx_arg
169
+ jsr ASM_SFX_REQUEST
170
+ plp
171
+ }
172
+ }
173
+
174
+ // ---- the multiplexer's actor table, and the boxes where they are drawn -----------------
175
+ // Actor 0 is the ship; actors 1-12 are the enemies, which waves.c writes in
176
+ // place. The ship's box is emitted here, where it is handed to the display;
177
+ // collide() reads the enemies' boxes from the same table next frame, so it
178
+ // tests what was on screen.
179
+ static void actors_draw(void)
180
+ {
181
+ bool ship = state == ST_PLAY || state == ST_FROZEN;
182
+ ACT_Y[0] = ship && !(p_safe & 4) ? p_y : OFF_Y; // blinks while safe
183
+ ACT_HX[0] = p_hx;
184
+ if (ship && !p_safe)
185
+ box_ship(p_hx, p_y);
186
+ else
187
+ box_off(BOX_PLAYER);
188
+ __asm {
189
+ jsr ASM_MUX_SORT
190
+ jsr ASM_MUX_BUILD
191
+ }
192
+ }
193
+
194
+
195
+ // ---- input: joystick port 2, or the autopilot's script ---------------------------------
196
+ #if AUTOPILOT
197
+ // { frames, port byte }, active low as $DC00 reads it. The title takes the
198
+ // first fire; the rest is play. See PLAN.md "Autopilot and checks".
199
+ #define PLAY_FRAMES 240
200
+ #ifdef LOOP_TEST
201
+ // Test only (-dLOOP_TEST=1): start, then hold fire without moving, so the
202
+ // game scores, runs to GAME OVER, saves the high score and returns to the
203
+ // title. It never freezes, so there is no verdict.
204
+ static const char script[][2] = {
205
+ { 2, 0xff }, { 2, 0xef }, { 250, 0xef }, { 250, 0xef }, { 250, 0xef },
206
+ { 250, 0xef }, { 250, 0xef }, { 250, 0xef }, { 250, 0xef }, { 250, 0xef }
207
+ };
208
+ #define FREEZE_Y 8
209
+ #elif defined(STAGE)
210
+ // Measuring only (-dSTAGE=1, make stage): the heaviest frame the game makes.
211
+ // Out of the darts' way, wait for the parade and the row-32 swoop (12
212
+ // enemies flying), then fire up a parade column, so bolts, a kill and every
213
+ // enemy share frames. The meter records play frames 150-399. Taken from the
214
+ // review of this starter.
215
+ // -dSD=n waits n frames longer, -dSX=n moves n frames left: the review swept
216
+ // both to find the worst frame.
217
+ #ifndef SD
218
+ #define SD 0
219
+ #endif
220
+ #ifndef SX
221
+ #define SX 16
222
+ #endif
223
+ static const char script[][2] = {
224
+ { 2, 0xff }, { 2, 0xef },
225
+ { 56, 0xf7 }, // right to hx 140
226
+ { 190 + SD, 0xff }, // wait for the parade and the swoop
227
+ { SX, 0xfb }, // left under a parade column
228
+ { 250, 0xef }, // fire
229
+ };
230
+ #undef PLAY_FRAMES
231
+ #define PLAY_FRAMES 400
232
+ #define STAGE_FROM 150
233
+ #define METER_HOLD (PLAY_FRAMES - STAGE_FROM) // the meter's hold is a byte: 1-255
234
+ #else
235
+ static const char script[][2] = {
236
+ { 2, 0xff }, { 2, 0xef }, // title: fire starts the game
237
+ { 24, 0xeb }, { 10, 0xef }, // left and fire: shoot the darts there
238
+ { 30, 0xf7 }, { 24, 0xff }, // right, past the start, hold fire: shot
239
+ { 16, 0xeb }, { 32, 0xe7 }, { 16, 0xeb }, // fire and sweep left, right, back
240
+ { 20, 0xff }, // hold fire: the parade comes down
241
+ { 40, 0xef }, // fire through the gap between two columns
242
+ { 24, 0xfb }, { 3, 0xfd }, // move left, then down
243
+ };
244
+ #endif
245
+ #define SCRIPT_LEN (sizeof(script) / 2)
246
+ static char ap_index, ap_used;
247
+
248
+ static char port_read(void)
249
+ {
250
+ char out = 0xff;
251
+ if (ap_index < SCRIPT_LEN) {
252
+ out = script[ap_index][1];
253
+ if (++ap_used == script[ap_index][0]) { ap_used = 0; ap_index++; }
254
+ }
255
+ return out;
256
+ }
257
+ #elif defined(JOY_SOURCE)
258
+ // Headless driving of the normal game (make joy, tools/drive.py): the port
259
+ // byte comes from RAM at JOY_SOURCE, which a VICE monitor writes; the
260
+ // windowless VICE's joyport commands do not reach $DC00.
261
+ #define PLAY_FRAMES 1
262
+ static char port_read(void)
263
+ {
264
+ return *(volatile char *)JOY_SOURCE;
265
+ }
266
+ #else
267
+ #define PLAY_FRAMES 1
268
+ static char port_read(void)
269
+ {
270
+ return cia1.pra;
271
+ }
272
+ #endif
273
+
274
+ #ifndef METER_HOLD
275
+ #define METER_HOLD PLAY_FRAMES
276
+ #endif
277
+
278
+ // ---- frames ------------------------------------------------------------------------
279
+ // A play frame whose work runs past the next frame IRQ (line 252) loses a
280
+ // frame: the scroll and the hidden screen then fall a frame out of step
281
+ // (level_frame takes values the screen does not show yet, and level_render
282
+ // can draw into the screen on display). Nothing guards that; it is counted
283
+ // and the verdict (and make joytest, which reads LOST_FRAMES) wants 0. Keep
284
+ // a frame's work under the frame.
285
+ //
286
+ // The count is taken here, before waiting: a frame flag already set means
287
+ // the work ended after the next frame IRQ. The first version counted only
288
+ // when the frame IRQ count moved by more than one at wake-up, which a single
289
+ // lost frame never does (the review's mutation M8a, one frame late by about
290
+ // 2,400 cycles, passed with 0). In a meter build the count stops with the
291
+ // recording: the frame after it spends several frames finding the median,
292
+ // harness work outside the brackets. The first two play frames are not
293
+ // counted either: play_enter draws both screens (and in a meter build holds
294
+ // IRQs off for its calibration), so play frame 0 starts mid-frame.
295
+ #define LOST_FRAMES (*(volatile char *)0x02fd) // lost play frames, saturating at 255
296
+ static char last_frame_cnt;
297
+ static unsigned overruns;
298
+
299
+ static void wait_frame(void)
300
+ {
301
+ char late = K_FRAME_FLAG; // set already: the work ran into the next frame
302
+ while (!K_FRAME_FLAG) ;
303
+ K_FRAME_FLAG = 0;
304
+ char f = K_FRAME_CNT;
305
+ char lost = (char)(f - last_frame_cnt) - (late ? 0 : 1);
306
+ last_frame_cnt = f;
307
+ bool counting = state == ST_PLAY && play_frames > 1;
308
+ #if FRAME_METER
309
+ counting = counting && play_frames < PLAY_FRAMES;
310
+ #endif
311
+ #ifdef STAGE_FROM
312
+ counting = counting && play_frames != STAGE_FROM + 1; // its meter_init holds IRQs off
313
+ #endif
314
+ if (counting && lost) {
315
+ #ifdef EVENTLOG
316
+ ev_log(4, lost); // a lost frame
317
+ #endif
318
+ overruns += lost;
319
+ unsigned t = LOST_FRAMES + lost;
320
+ LOST_FRAMES = t > 255 ? 255 : t;
321
+ }
322
+ }
323
+
324
+ #if FRAME_METER
325
+ // The C main loop's bracket is timed by CIA2 timer A (the harness meter);
326
+ // IRQs outside it by timer B (kernel.asm). A frame's figure is the loop's
327
+ // bracket plus the IRQ time up to the next frame IRQ, so it is recorded one
328
+ // frame late, when that IRQ has handed its sum over.
329
+ static unsigned main_raw;
330
+ static char have_main;
331
+
332
+ // The split IRQ runs from its vector to its timer B start untimed, to keep
333
+ // the recipe's timing: 245-289 cycles on PAL and 246-296 on NTSC, from the
334
+ // IRQ sequence to the start write, measured under the VICE monitor over a
335
+ // whole autopilot run. The larger figure is added for every frame in which
336
+ // the split timed itself.
337
+ #define SPLIT_PRE_PAL 289
338
+ #define SPLIT_PRE_NTSC 296
339
+
340
+ static void meter_open(void)
341
+ {
342
+ __asm { sei }
343
+ unsigned irq = K_IRQ_CYC - K_IRQ_CNT * K_IRQ_CAL;
344
+ char split = K_SPLIT_PREV;
345
+ __asm { cli }
346
+ if (split)
347
+ irq += ntsc_arg ? SPLIT_PRE_NTSC : SPLIT_PRE_PAL;
348
+ if (have_main) {
349
+ meter_add(main_raw);
350
+ meter_add(irq + meter_zero);
351
+ meter_frame();
352
+ }
353
+ __asm { sei }
354
+ METER_START;
355
+ K_MTR_OPEN = 1;
356
+ __asm { cli }
357
+ }
358
+
359
+ static void meter_close(void)
360
+ {
361
+ __asm { sei }
362
+ main_raw = meter_read();
363
+ K_MTR_OPEN = 0;
364
+ __asm { cli }
365
+ have_main = 1;
366
+ }
367
+ #else
368
+ #define meter_open()
369
+ #define meter_close()
370
+ #endif
371
+
372
+ // ---- states -----------------------------------------------------------------------
373
+ static void title_enter(void)
374
+ {
375
+ state = ST_TITLE;
376
+ bullets_erase();
377
+ bullets_reset();
378
+ waves_reset();
379
+ level_show(0, 3);
380
+ memset(COLOUR, PF_CRAM, 21 * 40); // no text left from a game over
381
+ char *s = level_screen();
382
+ put_text(s, 6, 11, " DELTA PATROL ");
383
+ put_text(s, 9, 9, " PUSH FIRE TO START ");
384
+ put_text(s, 12, 11, " JOYSTICK PORT 2 ");
385
+ text_colour(6, 11, 15, VCOL_YELLOW);
386
+ text_colour(9, 9, 20, TEXT_CRAM);
387
+ text_colour(12, 11, 17, VCOL_LT_GREY);
388
+ }
389
+
390
+ static void play_enter(void)
391
+ {
392
+ memset(COLOUR, PF_CRAM, 21 * 40); // every playfield cell multicolour
393
+ score = 0;
394
+ lives = START_LIVES;
395
+ deaths = 0;
396
+ ship_shots = 0;
397
+ play_frames = 0;
398
+ panel_draw();
399
+ p_safe = 0;
400
+ ship_reset();
401
+ bullets_reset();
402
+ eb_fired = 0;
403
+ waves_reset();
404
+ level_show(0, 0);
405
+ state = ST_PLAY;
406
+ #if FRAME_METER
407
+ meter_init((unsigned)SCRATCH, 13, 10, PF_CRAM, METER_HOLD);
408
+ #endif
409
+ }
410
+
411
+ static char over_timer;
412
+
413
+ static unsigned disk_hi; // the high score the file holds
414
+
415
+ // The raster chain stops during file I/O, so first set one screen that
416
+ // needs no IRQ: the playfield at YSCROLL 3, 25 rows, no sprites.
417
+ static void hold_screen(void)
418
+ {
419
+ __asm { sei }
420
+ vic.ctrl1 = 0x1b;
421
+ vic.memptr = cur_front ? D018_PF1 : D018_PF0; // the screen the text went to
422
+ vic.ctrl2 = 0xd8;
423
+ vic.spr_enable = 0;
424
+ vic.color_back = PF_BG_COL;
425
+ }
426
+
427
+ static void over_enter(void)
428
+ {
429
+ char *s = level_screen();
430
+ put_text(s, 9, 14, " GAME OVER ");
431
+ text_colour(9, 14, 11, TEXT_CRAM);
432
+ if (disk_on && hiscore > disk_hi) {
433
+ put_text(s, 11, 12, " SAVING HI SCORE ");
434
+ text_colour(11, 12, 17, TEXT_CRAM);
435
+ hold_screen();
436
+ hiscore_save(); // a second or two; the chain restarts after
437
+ disk_hi = hiscore;
438
+ put_text(s, 11, 12, " ");
439
+ }
440
+ over_timer = 150;
441
+ state = ST_OVER;
442
+ }
443
+
444
+ #ifdef WORKEND
445
+ // Measuring only (-dWORKEND=1): how far past the frame IRQ (line 252) a play
446
+ // frame's work ran, in raster lines (NTSC has 263, PAL 312: past that the
447
+ // frame is lost). At $0370, words: 0 the latest end over the run, 1 its play
448
+ // frame, 2 the frames whose work ended within 8 lines of the frame's end.
449
+ // Frames that woke late (after a lost one) are left out. -dWORKEND=2 also
450
+ // reads the line after each step: words 3-10 that frame's lines when it
451
+ // woke and after each of the 7 steps, 11-17 each step's most lines in any
452
+ // frame; the reads cost about 300 cycles a frame. Any build, the joy build
453
+ // too: nothing is held off, so the timing is the game's own.
454
+ #define WE ((volatile unsigned *)0x0370)
455
+ static unsigned we_step[8];
456
+ static unsigned we_line(void)
457
+ {
458
+ char hi, lo;
459
+ do { hi = vic.ctrl1; lo = vic.raster; } while (hi != vic.ctrl1);
460
+ unsigned l = lo + ((unsigned)(hi & 0x80) << 1);
461
+ unsigned n = ntsc_arg ? 263 : 312;
462
+ return l >= 252 ? l - 252 : l + n - 252;
463
+ }
464
+ #if WORKEND > 1
465
+ #define W1(k) we_step[k + 1] = we_line()
466
+ #else
467
+ #define W1(k) if (k == 6) we_step[7] = we_line()
468
+ #endif
469
+ #else
470
+ #define W1(k)
471
+ #endif
472
+
473
+ #ifdef PROFILE
474
+ // Debug only (-dPROFILE=1): CIA1 timer B times each step of play_frame with
475
+ // IRQs held off (badline and sprite DMA stay in). At $0340, words: 0-6 the
476
+ // steps of the frame whose steps summed largest, 7 the largest IRQ time of
477
+ // a frame, 8 that frame's number, 9 its sum, 10 the latest raster line the
478
+ // bullet draw ended on (0 when it ended above line 250).
479
+ #define PROF ((volatile unsigned *)0x0340)
480
+ static unsigned prof_step[7];
481
+ #define P0 { __asm { sei } cia1.crb = 0x00; cia1.tb = 0xffff; cia1.crb = 0x11; }
482
+ #define P1(k) { cia1.crb = 0; prof_step[k] = 0xffff - cia1.tb; __asm { cli } }
483
+ #else
484
+ #define P0
485
+ #define P1(k)
486
+ #endif
487
+
488
+ // One frame of play. The order matters: bullets first, drawn into the showing
489
+ // screen before the beam reaches the playfield; collisions next, on the
490
+ // boxes of what is on screen now; then the moves that show next frame.
491
+ #if AUTOPILOT
492
+ static char bullet_fault;
493
+ #endif
494
+
495
+ static void play_frame(char joy)
496
+ {
497
+ #ifdef DRAWEND
498
+ // Frames that start late for the harness's sake are left out: the first
499
+ // (after play_enter), the one after a meter_init (STAGE), and the ones
500
+ // from the end of the recording (the median is found there).
501
+ extern char drawend_on;
502
+ drawend_on = play_frames > 1 && play_frames < PLAY_FRAMES;
503
+ #ifdef STAGE_FROM
504
+ drawend_on = drawend_on && play_frames != STAGE_FROM + 1;
505
+ #endif
506
+ #endif
507
+ #ifdef WORKEND
508
+ we_step[0] = we_line();
509
+ #endif
510
+ P0; bullets_erase();
511
+ #if AUTOPILOT
512
+ if (!bullets_restored()) { // every cell the last draw changed is the map's again
513
+ bullet_fault = 1;
514
+ }
515
+ #endif
516
+ bullets_move_draw(); P1(0); W1(0);
517
+ #ifdef DRAWEND
518
+ // Measuring only (-dDRAWEND=1): the latest raster line the bullet draw
519
+ // ended on in a play frame, at $0360 (0 while still above line 250 or
520
+ // after the wrap below line 0... i.e. in the border before the display),
521
+ // and the play frame, at $0362. Not with PROFILE, whose timing is slower.
522
+ {
523
+ char l = vic.raster;
524
+ unsigned e = (vic.ctrl1 & 0x80) || l >= 250 ? 0 : l;
525
+ volatile unsigned *d = (volatile unsigned *)0x0360;
526
+ if (play_frames > 1 && play_frames < PLAY_FRAMES && e > d[0]) { d[0] = e; d[1] = play_frames; }
527
+ }
528
+ #endif
529
+ P0; collide(); P1(1); W1(1);
530
+ P0; ship_update(joy); P1(2); W1(2);
531
+ P0; waves_update(cur_row); P1(3); W1(3);
532
+ P0; actors_draw(); P1(4); W1(4);
533
+ P0; level_render(); P1(5); W1(5);
534
+ P0; level_advance(); panel_update(); P1(6); W1(6);
535
+ #ifdef WORKEND
536
+ if (play_frames > 1 && we_step[0] < 16) { // started on time
537
+ unsigned n = ntsc_arg ? 263 : 312;
538
+ if (we_step[7] > WE[0]) {
539
+ WE[0] = we_step[7];
540
+ WE[1] = play_frames;
541
+ #if WORKEND > 1
542
+ for (char k = 0; k < 8; k++)
543
+ WE[3 + k] = we_step[k];
544
+ #endif
545
+ }
546
+ if (we_step[7] + 8 >= n)
547
+ WE[2]++;
548
+ #if WORKEND > 1
549
+ for (char k = 0; k < 7; k++) {
550
+ unsigned d = we_step[k + 1] - we_step[k];
551
+ if (d < 200 && d > WE[11 + k])
552
+ WE[11 + k] = d;
553
+ }
554
+ #endif
555
+ }
556
+ #endif
557
+ #ifdef PROFILE
558
+ if (play_frames > 1) {
559
+ unsigned t = K_IRQ_CYC - K_IRQ_CNT * K_IRQ_CAL, sum = 0;
560
+ if (t > PROF[7]) PROF[7] = t;
561
+ for (char k = 0; k < 7; k++)
562
+ sum += prof_step[k];
563
+ if (sum > PROF[9]) {
564
+ for (char k = 0; k < 7; k++)
565
+ PROF[k] = prof_step[k];
566
+ PROF[8] = play_frames;
567
+ PROF[9] = sum;
568
+ }
569
+ }
570
+ #endif
571
+ play_frames++;
572
+ #ifdef GOD
573
+ *(volatile unsigned *)0x02fb = play_frames;
574
+ #endif
575
+ }
576
+
577
+ #if AUTOPILOT
578
+ // The graded run freezes on YSCROLL 3, where playfield rows sit on the text
579
+ // grid check.py reads. -dFREEZE_Y=0..7 freezes on another phase (the verdict
580
+ // then fails check 8): the panel split was compared across all eight so.
581
+ #ifndef FREEZE_Y
582
+ #define FREEZE_Y 3
583
+ #endif
584
+
585
+ // ---- the verdict, after the script -------------------------------------------------
586
+ // What the script does, by play frame (frame 0 is the second fire frame on
587
+ // the title), from the -dEVENTLOG=1 build's log, the same on PAL and NTSC:
588
+ // 37 a dart shot (50) 71 the first dart's dot hits the ship, in a still
589
+ // segment 94, 113, 121, 128 saucers shot (100 each)
590
+ // 450 points, 5 kills, K 1 4 0; 10 dots fired: 5 darts at Y 72, 5 saucers at
591
+ // Y 88. Before enemy fire the review's Python model matched the same kills
592
+ // frame for frame, with a ram at 71 where the dot now hits. After the loss
593
+ // the ship respawns at the start and the script's last 27 frames move it 24
594
+ // left and 3 down.
595
+ #define EXPECT_DEATHS 1
596
+ #define EXPECT_SCORE 45 // 450 points: 1 dart, 4 saucers
597
+ #define EXPECT_KILLS 5
598
+ #define EXPECT_FIRED 10 // 5 darts at Y 72, 5 saucers at Y 88; none from the parade
599
+ #define EXPECT_SHOWN 11 // 10 parade bugs and the ship
600
+ #define END_HX (P_START_HX - 24) // after the loss: 24 frames left
601
+ #define END_Y (P_START_Y + 6) // and 3 frames down, 2 lines each
602
+
603
+ static char verdict_code;
604
+
605
+ static bool parade_in_place(void)
606
+ {
607
+ char n = 0;
608
+ for (char e = 0; e < NE; e++) {
609
+ if (e_state[e] != E_FLYING || e_ptr[e] != SPR_BLOCK + F_BUG)
610
+ continue;
611
+ char k = (e_hx[e] - 30) / 24;
612
+ if (e_hx[e] != 30 + 24 * k || k > 4 || (e_y[e] != 72 && e_y[e] != 102))
613
+ return false;
614
+ n++;
615
+ }
616
+ return n == 10;
617
+ }
618
+
619
+ // The number of the first check that fails, 0 when all pass. The number is
620
+ // printed after FAIL, so a red run says which fact was wrong.
621
+ #define CHECK(c) if (!(c)) return n; n++;
622
+
623
+ static char hw_d011, hw_d018; // read right after the frame IRQ, before the split
624
+ static bool disk_round_trip;
625
+
626
+ // Save the high score, clear it, load it back: drive 8 must answer 00 and
627
+ // return the same number. Runs before the checks; the screen holds still.
628
+ static void disk_test(void)
629
+ {
630
+ unsigned h = hiscore;
631
+ hiscore_save();
632
+ hiscore = 0;
633
+ hiscore_load();
634
+ disk_round_trip = disk_on && disk_code == 0 && hiscore == h && h == EXPECT_SCORE;
635
+ hiscore = h;
636
+ }
637
+
638
+ static char first_fail(void)
639
+ {
640
+ char kills = kills_by_type[0] + kills_by_type[1] + kills_by_type[2];
641
+ unsigned sum = kills_by_type[0] * 5 + kills_by_type[1] * 10 + kills_by_type[2] * 15;
642
+ char n = 1;
643
+ #ifdef STAGE
644
+ // The staged run grades only what it is for: no play frame ran into the
645
+ // next, and every bullet cell was restored every frame. stage-expect.json
646
+ // adds the meter's worst inside a frame.
647
+ CHECK(overruns == 0) // 1
648
+ CHECK(!bullet_fault) // 2
649
+ return 0;
650
+ #endif
651
+ CHECK(level_intact()) // 1 bullets restored every cell
652
+ CHECK(deaths == EXPECT_DEATHS) // 2 the script's one ram
653
+ CHECK(lives == START_LIVES - EXPECT_DEATHS) // 3
654
+ CHECK(score == sum) // 4 score = points of what was shot
655
+ CHECK(score == EXPECT_SCORE) // 5
656
+ CHECK(kills == EXPECT_KILLS) // 6
657
+ CHECK(waves_started == waves_due(cur_pos)) // 7 every wave the scroll reached
658
+ CHECK((hw_d011 & 7) == 3 && cur_y == 3) // 8 the frame IRQ applied YSCROLL 3
659
+ CHECK((hw_d018 & 0xfe) == (cur_front ? D018_PF1 : D018_PF0)) // 9 ... and the screen (bit 0 reads 1)
660
+ CHECK(K_MUX_SHOWN == EXPECT_SHOWN) // 10 the multiplexer shows 11
661
+ CHECK(parade_in_place()) // 11 ten bugs where the paths end
662
+ CHECK(p_hx == END_HX && p_y == END_Y) // 12 the ship where the script ends
663
+ CHECK(K_SFX_TAKEN != 0) // 13 effects ran in the player
664
+ CHECK(disk_round_trip) // 14 HISCORE written and read back
665
+ CHECK(overruns == 0) // 15 no play frame ran into the next
666
+ CHECK(!bullet_fault) // 16 every bullet cell restored, every frame
667
+ CHECK(eb_fired == EXPECT_FIRED) // 17 the enemies' shots
668
+ CHECK(ship_shots == EXPECT_DEATHS) // 18 the loss was a dot, not a ram
669
+ return 0;
670
+ }
671
+
672
+ static void verdict(void)
673
+ {
674
+ char fail = first_fail();
675
+ char ok = fail == 0;
676
+ verdict_code = ok ? 1 : 2;
677
+ RESULT = verdict_code;
678
+ vic.color_border = ok ? VCOL_GREEN : VCOL_RED;
679
+ char *s = level_screen();
680
+ char kills = kills_by_type[0] + kills_by_type[1] + kills_by_type[2];
681
+ put_text(s, 9, 1, ok ? "RESULT 01 PASS " : "RESULT 02 FAIL 00");
682
+ if (!ok)
683
+ put_dec(s + 9 * 40 + 16, fail, 2);
684
+ put_text(s, 10, 1, "SCORE 000000 KILLS 00 LIVES 0");
685
+ put_dec(s + 10 * 40 + 7, score, 5);
686
+ put_dec(s + 10 * 40 + 20, kills, 2);
687
+ put_dec(s + 10 * 40 + 29, lives, 1);
688
+ put_text(s, 11, 1, "SHOWN 00 WAVES 00 SHIP 000 000 K 0 0 0");
689
+ put_dec(s + 11 * 40 + 7, K_MUX_SHOWN, 2);
690
+ put_dec(s + 11 * 40 + 16, waves_started, 2);
691
+ put_dec(s + 11 * 40 + 24, p_hx, 3);
692
+ put_dec(s + 11 * 40 + 28, p_y, 3);
693
+ put_dec(s + 11 * 40 + 34, kills_by_type[0], 1); // darts, saucers, bugs
694
+ put_dec(s + 11 * 40 + 36, kills_by_type[1], 1);
695
+ put_dec(s + 11 * 40 + 38, kills_by_type[2], 1);
696
+ text_colour(9, 1, 17, TEXT_CRAM);
697
+ text_colour(10, 1, 29, TEXT_CRAM);
698
+ text_colour(11, 1, 38, TEXT_CRAM);
699
+ put_text(s, 12, 1, "FIRED 00 HIT 0 OVERRUNS 00");
700
+ put_dec(s + 12 * 40 + 7, eb_fired, 2);
701
+ put_dec(s + 12 * 40 + 14, ship_shots, 1);
702
+ put_dec(s + 12 * 40 + 25, overruns, 2);
703
+ text_colour(12, 1, 26, TEXT_CRAM);
704
+ text_colour(13, 10, 20, TEXT_CRAM);
705
+ }
706
+ #endif
707
+
708
+ // PAL has 312 lines, NTSC 263: the largest line past 255 tells them apart.
709
+ static char is_ntsc(void)
710
+ {
711
+ char top = 0;
712
+ for (unsigned i = 0; i < 20000; i++) {
713
+ if (vic.ctrl1 & 0x80) {
714
+ char l = vic.raster;
715
+ if (l > top) top = l;
716
+ }
717
+ }
718
+ return top < 0x20;
719
+ }
720
+
721
+ int main(void)
722
+ {
723
+ __asm { sei }
724
+ ntsc_arg = is_ntsc();
725
+ cia1.pra = 0xff; // no keyboard column selected
726
+ level_init();
727
+ display_init();
728
+ ACT_PTR[0] = SPR_BLOCK + F_SHIP;
729
+ ACT_COL[0] = VCOL_LT_BLUE;
730
+ title_enter();
731
+ #if !AUTOPILOT && defined(JOY_SOURCE)
732
+ *(volatile char *)JOY_SOURCE = 0xff; // nothing pressed until the monitor says so
733
+ #endif
734
+ #ifdef DRAWEND
735
+ *(volatile int *)0x0364 = 0x7fff;
736
+ *(volatile int *)0x0366 = 0x7fff;
737
+ #endif
738
+ LOST_FRAMES = 0;
739
+ hold_screen(); // show the title while the disk works: the
740
+ // kernel sets the VIC only in kernel_init
741
+ #if AUTOPILOT
742
+ hiscore_forget(); // every graded run starts from no file
743
+ #endif
744
+ hiscore_load(); // banks the KERNAL in for the calls only
745
+ disk_hi = hiscore;
746
+ panel_draw();
747
+ #if FRAME_METER
748
+ // The readout goes to a scratch row until the verdict copies it onto the
749
+ // playfield; play_enter starts the recording again.
750
+ meter_init((unsigned)SCRATCH, 13, 10, PF_CRAM, METER_HOLD);
751
+ K_MTR_OPEN = 0; // IRQs time themselves (timer B)
752
+ K_BYTE(ASM_MTR_ON) = 1; // the frame IRQ hands their sum to C
753
+ #else
754
+ K_MTR_OPEN = 1; // no meter: IRQs never touch timer B
755
+ #endif
756
+ __asm {
757
+ lda ntsc_arg
758
+ jsr ASM_KERNEL_INIT
759
+ cli
760
+ }
761
+
762
+ char prev = 0xff;
763
+ for (;;) {
764
+ wait_frame();
765
+ level_frame();
766
+ char joy = port_read();
767
+ switch (state) {
768
+ case ST_TITLE:
769
+ actors_draw();
770
+ if (!(joy & JOY_FIRE) && (prev & JOY_FIRE))
771
+ play_enter();
772
+ break;
773
+ case ST_PLAY:
774
+ #if AUTOPILOT
775
+ if (play_frames > PLAY_FRAMES && cur_y == FREEZE_Y) {
776
+ bullets_erase(); // freeze on YSCROLL 3: nothing
777
+ bullets_reset(); // moves after this frame
778
+ state = ST_FROZEN;
779
+ break;
780
+ }
781
+ #endif
782
+ #if defined(STAGE) && FRAME_METER
783
+ if (play_frames == STAGE_FROM) { // record the heavy part only
784
+ meter_init((unsigned)SCRATCH, 13, 10, PF_CRAM, METER_HOLD);
785
+ have_main = 0;
786
+ }
787
+ #endif
788
+ meter_open();
789
+ play_frame(joy);
790
+ meter_close();
791
+ if (state == ST_OVER)
792
+ over_enter();
793
+ break;
794
+ case ST_OVER:
795
+ actors_draw();
796
+ if (--over_timer == 0)
797
+ title_enter();
798
+ break;
799
+ #if AUTOPILOT
800
+ case ST_FROZEN:
801
+ if (!verdict_code) {
802
+ hw_d011 = vic.ctrl1; // the playfield's values until line 212
803
+ hw_d018 = vic.memptr;
804
+ disk_test();
805
+ verdict();
806
+ #ifdef STAGE
807
+ for (char a = 0; a < N_ACTORS; a++)
808
+ ACT_Y[a] = OFF_Y; // no sprite over the meter's readout
809
+ #endif
810
+ }
811
+ actors_draw();
812
+ memcpy(level_screen() + 13 * 40 + 10, SCRATCH + 13 * 40 + 10, 20);
813
+ break;
814
+ #endif
815
+ }
816
+ prev = joy;
817
+ // The readout is read once, after the freeze. Printing it every play
818
+ // frame cost up to 3,404 cycles outside the bracket (the review) and
819
+ // made the autopilot build drop frames the game itself does not.
820
+ if (state != ST_PLAY)
821
+ meter_print();
822
+ }
823
+ return 0;
824
+ }