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,277 @@
1
+ # platformer: a side-scrolling platformer starter
2
+
3
+ A small game that plays: a level 2,048 pixels wide scrolls through a
4
+ 38-column window as you run; you jump with 8.8 fixed-point physics, walk
5
+ up 45-degree and 1-in-2 slopes, land on blocks and one-way ledges, stomp
6
+ enemies that wake as they come near the screen, collect coins, and have
7
+ three lives. A HUD sits under the playfield and an original two-voice tune
8
+ plays. Title, fire to start, game over back to the title. PAL and NTSC,
9
+ Oscar64 C with a KickAssembler part.
10
+
11
+ Start a game from it in c64-kb:
12
+ `npm run new-project -- platformer ~/c64/mygame`.
13
+
14
+ ## Playing
15
+
16
+ `make run` opens VICE; give it a joystick device for port 2 ("Driving it
17
+ headless" below says how). Left and right run,
18
+ fire jumps, down + fire drops through a ledge. Land on an enemy from
19
+ above to squash it (100); a coin is 10; the flag at the far end is 1,000
20
+ and starts the level again.
21
+
22
+ ## Files
23
+
24
+ | File | Holds |
25
+ |---|---|
26
+ | `src/main.c` | The frame loop, the states (title, play, dying, game over, level clear), lives |
27
+ | `src/game.h` | Every shared constant, variable and function, in one place |
28
+ | `src/level.c` | The level as ten lines of text, the 2 x 2 metatiles, cell lookups, the slope height table |
29
+ | `src/art.c` | Every picture as text: playfield glyphs, sprite shapes, hit boxes |
30
+ | `src/player.c` | The physics every body shares (walk, fall, land) and the player on top |
31
+ | `src/actors.c` | Enemies: the activation window, five live slots, walker and hopper, hit boxes by group |
32
+ | `src/view.c` | VIC-II: bank 3, the camera, the three-page scroll, sprite shadows |
33
+ | `src/anim.c` | Animation sequences (frame, duration, loop or hold) |
34
+ | `src/hud.c`, `src/sound.c` | Score digits and HUD text; sound effects on SID voice 3 |
35
+ | `src/engine.asm` | KickAssembler: the slice copy for the scroll, the two raster IRQs, the tune and its player |
36
+ | `src/autopilot.h`, `src/verdict.h` | AUTOPILOT builds only: the scripted joystick and the self-check |
37
+ | `tools/tearcheck.py` | Renders the level from `src/` and proves no picture tears (`make tearcheck`) |
38
+ | `expect.json`, `stage-expect.json`, `PLAN.md` | The screenshot checks, the crowded-level checks (`make stage`); the plan with the c64-kb tool output |
39
+
40
+ ## How a frame runs
41
+
42
+ The main loop waits for the IRQ at raster line 251, then writes the
43
+ sprites, plays the tune and the effects, runs the player, the enemies and
44
+ the camera, and publishes the next picture's `$D018` and `$D016` as one
45
+ pair. Two raster IRQs in `engine.asm` own those registers: at line 212,
46
+ inside the blank character row 20, the HUD gets 40 columns, hires and its
47
+ own screen page; at line 251 the playfield gets the published pair back.
48
+ A frame whose work runs long therefore shows the last picture again,
49
+ never a half-set one.
50
+
51
+ The scroll never shifts or redraws the page on display; a taken coin's
52
+ cells and the sprite pointers are the only writes to it, and a level
53
+ restart redraws all three pages at a cut. XSCROLL moves the picture a
54
+ pixel; a column crossing is only a `$D018` flip, because three pages are
55
+ kept: the one on display, the one the camera just left, and one prepared
56
+ for the next column in the direction of travel, five rows a frame, by a
57
+ KickAssembler copy one column over plus the new column's cells from the
58
+ level. The camera moves at most 2 pixels a frame, so the next crossing is
59
+ at least 4 frames off and 4 slices are enough. A frame never carries a
60
+ whole 20-row shift (an earlier draft of this starter did: 9,457 cycles in
61
+ one frame, measured with `PROF=3`).
62
+
63
+ Memory: VIC bank 3. Pages at `$C000`, `$C400` and `$E800`, the HUD page at
64
+ `$C800`, sprites at `$CC00`, the character set at `$E000` (the ROM's
65
+ glyphs 0-63 copied in, so text and the meter read). BASIC and KERNAL are
66
+ banked out (`$01` = `$35`). Colour RAM is never scrolled: the playfield's
67
+ four colours are `$D021`, `$D022`, `$D023` and the colour RAM's green.
68
+
69
+ ## The measured frame
70
+
71
+ The harness meter (CIA2 timer A) over the first 255 play frames of the
72
+ autopilot run, VICE x64sc 3.10, `make shot check`:
73
+
74
+ | Model | Worst | Typical (median) | Frame |
75
+ |---|---|---|---|
76
+ | PAL | 11,758 | 6,212 | 19,656 |
77
+ | NTSC | 12,216 | 6,573 | 17,095 |
78
+
79
+ Per subsystem, built with `-dPROF=n` (worst / typical, PAL; NTSC within
80
+ 400 cycles of each):
81
+
82
+ | n | Subsystem | Worst | Typical |
83
+ |---|---|---|---|
84
+ | 1 | player physics, coins | 4,237 | 1,686 |
85
+ | 2 | enemies: window, AI, hit boxes | 3,682 | 2,269 |
86
+ | 3 | camera and scroll slice | 4,001 | 240 |
87
+ | 4 | sprites to the VIC, tune, effects | 925 | 706 |
88
+ | 5 | HUD, sprite shadows, publish | 1,346 | 915 |
89
+
90
+ The meter covers play frames 1-255 of about 835. A review of an earlier
91
+ build metered two later windows (from frames 275 and 560): their worst was
92
+ below the first window's, their typical about 1,000 cycles above it. Not
93
+ re-measured on this build.
94
+
95
+ The worst frames of the parts do not fall together: the whole frame's
96
+ worst is 11,758, not their sum. Every figure is wall time, so badline and
97
+ sprite DMA are in it, and so is the split IRQ when it lands inside the
98
+ bracket (work past line 212; about 56 cycles by arithmetic). The IRQ at
99
+ 251 falls just before the bracket opens and is not counted: about 66
100
+ cycles by arithmetic.
101
+
102
+ Against `plan-budget` (PLAN.md): it gave 10,167 to 10,765 cycles plus
103
+ 1,432 fixed, 11,599 to 12,197 in all, verdict undetermined, with the
104
+ scroll left out (its only figure was the old recipe's 74,041-cycle shift,
105
+ issue #18) and six techniques unknown. The measured worst is 11,758 on PAL,
106
+ inside that range, and 12,216 on NTSC, 19 cycles above its top (an earlier build, before the walker
107
+ and HUD cuts below, was 356 and 785 cycles above its top). The parts disagree more than
108
+ the total: the budget charges per-frame-hitbox 3,693 and decimal-print
109
+ 1,361 from their recipes, where this game tests a few box pairs and adds
110
+ score digits without division. For the player physics it charges only
111
+ slope_collision's 455, with no figure for fixed_point_8_8 or
112
+ jump_arc_table; measured, the player is 4,237 worst. The measured typical
113
+ frame, 6,212, is far under the budget's low end, because most frames have
114
+ no column slice and no HUD change.
115
+
116
+ ## Enemies on screen
117
+
118
+ The stock level never fills every slot, but a level an agent writes can. `make stage` builds the run with row 7 crowded (ten
119
+ enemies in the first view, `STAGE_CROWD` in `src/level.c`), so every slot
120
+ is live from the first play frame, and wants no late frame in the whole run
121
+ and the meter's worst inside one frame on each model.
122
+
123
+ | Build | NSLOT | Worst PAL | Worst NTSC | Late frames |
124
+ |---|---|---|---|---|
125
+ | walkers probing every step, HUD redrawn whole | 6 | 17,105 | 17,262 | yes |
126
+ | walker judges the column ahead once; HUD figures only | 6 | 15,632 | 15,977 in frames 1-255; 17,618 from frame 400 | on NTSC |
127
+ | the same | 5 | 14,523 | 14,829 in frames 1-255; 15,353 from frame 400 (measured once; no target re-measures that window) | none, either model |
128
+
129
+ So `NSLOT` is 5: sprites 1-5 are enemies, sprite 6 is free. Six live
130
+ enemies overran an NTSC frame by about 520 cycles; a sixth needs about
131
+ 1,000 more cycles cut from the enemy loop first (`-dPROF=2`). The walker
132
+ cut: a walker judges the column 6 pixels ahead once, when it first reaches
133
+ it (edge, step or wall), and each step is one ground snap; odd and even
134
+ slots step on alternate frames.
135
+
136
+ ## Proving it
137
+
138
+ | Command | What it proves | Last result |
139
+ |---|---|---|
140
+ | `make shot check` | 23 checks: the verdict, the HUD text (so the split's 40 columns and XSCROLL 0), the player sprite where arithmetic puts it, the hopper where the run leaves it, the scrolled playfield's brick, grass and pit at camera 576, the blank row 20, PAL and NTSC identical, the meter | 23 of 23 passed |
141
+ | `make selftest` | FORCE_FAULT makes a coin worth 20: the verdict fails, the HUD score reads 000200 | check.py rejected the build |
142
+ | `make tearcheck` | 16 shots a model mid-play, each matched pixel for pixel against a render of the level | 32 of 32 whole or two-frame composites; the TEAR_DEMO build: 2 of 32 torn (the count moves with the code; one is enough) |
143
+ | `make stage` | Every enemy slot live from the first play frame: no late frame, the meter inside one frame | 4 of 4 passed (worst 14,523 PAL, 14,829 NTSC) |
144
+ | `make claims` | Every store the run makes, title to verdict, against CLAIMS_ARGS | 0 violations |
145
+ | `make disk` | `build/platformer.d64`; it boots to the title | |
146
+
147
+ The self-check (`src/verdict.h`) grades the game's own state after the
148
+ script: every event seen (jump, landing, slope, ledge, coin, stomp, hit,
149
+ respawn, wake, sleep, both scroll directions, a wall), the score equal to
150
+ coins x 10 + stomps x 100, the lives, the player stopped by the brick at
151
+ x 716 and the camera at 576 (both arithmetic), every ready page equal to
152
+ the level at its column, the activation window's rules, the player's
153
+ sprite registers against the model, and no late frame.
154
+
155
+ After every play frame it also checks four invariants, each with its own
156
+ bit, so a fault that heals before the end still fails the run:
157
+
158
+ | Bit | Invariant | Mutation that trips it (PAL run) |
159
+ |---|---|---|
160
+ | `0800` | no dormant, living enemy inside the view (a pop-in) | wake window cut to the middle 24 columns: `FAIL 0880` |
161
+ | `1000` | every live enemy inside the drop window it was judged against | the drop never happens: `FAIL 1181` |
162
+ | `2000` | a grounded player stands exactly on its cell's surface | `surface_walk` reads every slope at column 0: `FAIL 223D` (tearcheck still 32 of 32: only this bit sees it) |
163
+ | `4000` | the page to show is the camera's column, and whole | left crossings ignored: `FAIL 4001`; tearcheck 28 of 32 |
164
+
165
+ Hits use boxes per animation frame with a group and a mask (c64-kb
166
+ `per_frame_hitbox`). The falling frame (`SH_FALL`, from the jump table's
167
+ apex on) carries two boxes, the body and the feet; only the feet are in the
168
+ stomp group, so a stomp is the feet reaching an enemy, not a height test.
169
+ Boxes are bytes relative to the player's foot; an enemy more than 40 pixels
170
+ away is not listed. Mutation: the feet box put in the player group turns
171
+ the scripted stomp into a hit, and the run ends in GAME OVER with the
172
+ verdict failed.
173
+
174
+ How the tear check works: VICE's exit screenshot is taken mid-frame, so a
175
+ shot can hold two frames, split at the beam. `tools/tearcheck.py` finds,
176
+ line by line, the camera positions at which the level render matches the
177
+ shot, and allows one seam between parts at most 2 pixels (one frame of
178
+ camera) apart, and only if the lower part, the older frame, is exactly
179
+ the camera the program printed on HUD row 23 ("CAM 0576") for that frame.
180
+ The same number must match the playfield in every shot: a page flipped
181
+ without its XSCROLL is 8 pixels off. A mid-picture XSCROLL write also
182
+ splits a shot into parts 1-2 pixels apart; the review's mutation (XSCROLL
183
+ written again at line 150) passed four shots as two frames until the
184
+ lower-part rule was added, and is now caught. Rows that are all sky match
185
+ every camera, so a tear inside them cannot be seen, by this check or by
186
+ eye. The TEAR_DEMO build
187
+ shifts the page on display in place, the old way; the check catches it
188
+ (off by 8, or torn), so the check can see a tear.
189
+
190
+ ## Extending it
191
+
192
+ 1. **A second level, or longer ones.** Edit the text in `src/level.c`;
193
+ keep the metatile keys. For more than fits in memory, compress it with
194
+ c64-kb `level-rle-decoder` (`docs/recipes/oscar64/level-rle-decoder.md`)
195
+ or load levels from disk (`kernal_file_read_seq`,
196
+ `docs/techniques/file-io.md`). `tools/tearcheck.py` renders the
197
+ `LEVEL` text block, so a compressed level needs it changed too. Then re-time `src/autopilot.h` with
198
+ `-dDEBUG_AT=n` builds: the script is a timeline, so a changed level
199
+ changes the run.
200
+ 2. **More enemies on screen than five.** One sprite per live slot is the
201
+ limit here. A multiplexer lifts it: `sprite_multiplex_8`
202
+ (`docs/recipes/oscar64/sprite-multiplex-8.md`) or the game multiplexer
203
+ `sprite_multiplex_game` (`docs/recipes/kickassembler/sprite-multiplex-game.md`).
204
+ The activation window already hands out slots; raising `NSLOT` is the
205
+ easy part. The multiplexer's IRQs must join `engine.asm`'s `$FFFE`
206
+ chain around lines 212 and 251, and it replaces `view_apply`.
207
+ 3. **Parallax or a vertical component.** `charset_parallax`
208
+ (`docs/recipes/oscar64/charset-parallax.md`) moves reserved glyphs for
209
+ a background layer at no screen cost. Vertical scrolling needs
210
+ `eight_way_scroll_double_buffer` (`docs/recipes/kickassembler/eight-way-scroll.md`),
211
+ whose redraw and colour bands this three-page scheme would replace.
212
+
213
+ Smaller steps: a high-score table on disk (`high-score-persist`,
214
+ `docs/recipes/oscar64/high-score-persist.md`; the harness's `SHOT_DISK=1`
215
+ attaches the image during `make shot`), a variable jump height (cut
216
+ `pjump` to `JUMP_APEX` when fire is released while rising), more tiles
217
+ (add a key, four glyphs and their art).
218
+
219
+ ## Driving it headless
220
+
221
+ `make joy` builds the normal game with its port byte read from `$02FE`
222
+ instead of `$DC00`; `tools/drive.py` (from the action-puzzle starter) plays
223
+ it over VICE's binary monitor, at real speed (no warp; the monitor port is
224
+ DRIVE_PORT or a free one), and reads the HUD page. Measured: title,
225
+ fire, LIVES 3, holding right loses all three lives, GAME OVER, the title
226
+ with HI 000030, fire, a new game at LIVES 3.
227
+
228
+ ```bash
229
+ make joy
230
+ python3 tools/drive.py build/platformer-joy.prg "until:PRESS FIRE" tap:fire \
231
+ "until:LIVES 3" hold:right "until:GAME OVER" "until:PRESS FIRE" print
232
+ ```
233
+
234
+ `make run` starts the windowed VICE with no joystick device chosen: pick
235
+ one for port 2 in its settings, or pass one, e.g.
236
+ `make run X64SC_WINDOWED="x64sc -joydev2 1"` (1 is the numeric keypad,
237
+ from `x64sc -help`; not tried here).
238
+
239
+ ## Which Oscar64
240
+
241
+ It builds and passes on both the local build named in c64-kb's CLAUDE.md
242
+ (1.32.271 plus c1270bc) and the released v1.32.273: `make shot check`,
243
+ `selftest` and `stage` pass on each (v1.32.273: worst 11,756 PAL, 12,204
244
+ NTSC). Two workarounds make that so, both for faults of the released
245
+ compiler that the local build does not have:
246
+
247
+ - `surface_at` (`src/level.c`) is `__noinline`. Inlined into
248
+ `surface_walk`, v1.32.273 and upstream 9a902f6 compile
249
+ `heights[((a & A_SLOPE) >> 1) | (x & 7)]` as `ORA heights,x` with X as
250
+ `cell_attr` left it, and never compute the index: the player stops a few
251
+ pixels up the first 45-degree slope and the run ends at LIVES 0. Issue
252
+ #30 holds the fault.
253
+ - `hud_draw` writes the score through `put_digits`. A loop storing
254
+ `HUD22[6 + i]` kept only the first digit on v1.32.273 (the HUD read
255
+ `SCORE 0`); not reduced or filed.
256
+
257
+ ## Left out on purpose
258
+
259
+ - The high score is not saved: it lives until power-off.
260
+ - No sprite multiplexer: at most five enemies live (see "Enemies on screen").
261
+ - No vertical scroll; the playfield is 20 rows, the level 10 tiles high.
262
+ - Colour RAM does not scroll: four colours for the whole playfield.
263
+ - NTSC runs the same per-frame steps at 60 Hz, so the game and the tune
264
+ are 6/5 as fast there (c64-kb `pal_ntsc_tempo_mismatch`), and the tune's
265
+ pitches, tabled for the PAL clock, about 4% sharp (arithmetic).
266
+ - One effect at a time on voice 3; a new one cuts the last.
267
+
268
+ ## Not established
269
+
270
+ - A real `$DC00` joystick: the normal game was played through `make joy`
271
+ (a RAM port byte), not through the CIA.
272
+ - Real hardware: everything was measured in VICE x64sc 3.10.
273
+ - The tune was never listened to; its note table is arithmetic.
274
+ - The tear check samples 32 moments of one run; it does not prove every
275
+ frame. The three-page rule (the scroll never writes the page shown) is
276
+ the design reason; the self-check compares every ready page with the
277
+ level, and row 20 of every page with the sky.
@@ -0,0 +1,32 @@
1
+ {
2
+ "checks": [
3
+ { "name": "own verdict (border)", "type": "verdict" },
4
+ { "name": "verdict line", "type": "text", "row": 21, "col": 0, "text": "RESULT 01 PASS" },
5
+ { "name": "HUD: score, coins, lives (40 columns, XSCROLL 0 after the split)", "type": "text", "row": 22, "col": 0, "text": "SCORE 000150 COINS 05 LIVES 2" },
6
+ { "name": "HUD: high score", "type": "text", "row": 23, "col": 0, "text": "HI 000000" },
7
+ {
8
+ "name": "player at the wall: x 716, feet on line 179 (sprite X 163, Y 157; stand art columns 3-13)",
9
+ "type": "sprite",
10
+ "colour": 1,
11
+ "vic_x": 166,
12
+ "line": 158,
13
+ "width": 11,
14
+ "height": 21
15
+ },
16
+ {
17
+ "name": "hopper where the scripted run leaves it (pinned from the run; the program checks its own sprite registers)",
18
+ "type": "sprite",
19
+ "colour": 3,
20
+ "vic_x": 32,
21
+ "line": 167,
22
+ "width": 14,
23
+ "height": 12
24
+ },
25
+ { "name": "scrolled playfield: brick tile 46 top row at camera 576 (VIC X 191, line 147)", "type": "rect", "colour": 7, "vic_x": 191, "line": 147, "width": 16, "height": 1 },
26
+ { "name": "scrolled playfield: grass on tiles 43-44 (VIC X 143-174, lines 179-180)", "type": "rect", "colour": 5, "vic_x": 143, "line": 179, "width": 32, "height": 2 },
27
+ { "name": "scrolled playfield: the pit at tiles 41-42 is sky (VIC X 111-142)", "type": "rect", "colour": 6, "vic_x": 111, "line": 179, "width": 32, "height": 16 },
28
+ { "name": "row 20, between playfield and HUD, is blank", "type": "rect", "colour": 6, "vic_x": 31, "line": 211, "width": 304, "height": 8 },
29
+ { "name": "display the same on both models", "type": "same", "cells": [0, 0, 23, 39] },
30
+ { "name": "frame meter, the first 255 play frames", "type": "meter", "row": 24, "col": 20, "frames": 255 }
31
+ ]
32
+ }
@@ -0,0 +1,289 @@
1
+ // actors.c: enemies placed in the level wake when they come within a
2
+ // window around the view, and go back to the level table when they leave
3
+ // it, so a patrol survives off screen and a stomped enemy stays dead
4
+ // (c64-kb actor_activation_window). The live ones sit in NSLOT slots, one
5
+ // sprite each (object_pool). Hits are tested box against box, each box
6
+ // from the animation frame on show (per_frame_hitbox).
7
+ #include "game.h"
8
+
9
+ #define MARGIN 4 // wake window: the view plus 4 columns each side
10
+ #define HYST 2 // live actors are kept 2 columns further out
11
+ #define SCAN_K 8 // level entries examined a frame, round robin
12
+ #define HOP_WAIT 70 // frames a hopper sits between hops
13
+ #define HOP_START 8 // vy_tab entry a hop starts from: a lower arc than a jump
14
+ #define ENEMY_H 15 // enemy feet to head
15
+
16
+ char lvl_count;
17
+ char lvl_col[NLVL], lvl_ty[NLVL], lvl_type[NLVL], lvl_flags[NLVL];
18
+
19
+ char slot_lvl[NSLOT];
20
+ unsigned slot_x[NSLOT], slot_y[NSLOT];
21
+ char slot_type[NSLOT], slot_jump[NSLOT], slot_timer[NSLOT];
22
+ static char slot_probe[NSLOT]; // the column ahead the walker last judged
23
+ static bool slot_turn[NSLOT]; // and whether it turns there
24
+ bool slot_left[NSLOT], slot_squashed[NSLOT];
25
+ struct Anim slot_anim[NSLOT];
26
+
27
+ static char scan_pos, win_lo, win_top, tick;
28
+ char drop_lo, drop_top; // this frame's drop window, in columns
29
+
30
+ void actors_reset(void)
31
+ {
32
+ for (char s = 0; s < NSLOT; s++)
33
+ slot_lvl[s] = NO_SLOT;
34
+ scan_pos = 0;
35
+ }
36
+
37
+ static void activate(char i)
38
+ {
39
+ char s = 0;
40
+ while (slot_lvl[s] != NO_SLOT)
41
+ if (++s == NSLOT)
42
+ return; // every slot live: it wakes on a later scan
43
+ slot_lvl[s] = i;
44
+ slot_type[s] = lvl_type[i];
45
+ slot_x[s] = lvl_col[i] * 8 + 8;
46
+ slot_y[s] = (unsigned)((lvl_ty[i] + 1) * 16) << 8;
47
+ slot_jump[s] = JUMP_APEX; // it drops onto whatever is under it
48
+ slot_left[s] = lvl_flags[i] & LF_LEFT;
49
+ slot_timer[s] = HOP_WAIT / 2 + (i & 15);
50
+ slot_squashed[s] = false;
51
+ slot_probe[s] = 0xff;
52
+ slot_anim[s].seq = nullptr;
53
+ anim_set(&slot_anim[s], lvl_type[i] == T_WALKER ? an_walk : an_hop_sit);
54
+ lvl_flags[i] |= LF_LIVE;
55
+ events |= EV_WAKE;
56
+ }
57
+
58
+ // Back to the table: where it is now, which way it faces, one tile row up
59
+ // so a wake drops it onto the surface again.
60
+ static void deactivate(char s)
61
+ {
62
+ char i = slot_lvl[s];
63
+ lvl_col[i] = (slot_x[s] - 8) >> 3;
64
+ lvl_ty[i] = (char)((slot_y[s] >> 8) >> 4) - 1;
65
+ lvl_flags[i] = (lvl_flags[i] & ~(LF_LIVE | LF_LEFT)) | (slot_left[s] ? LF_LEFT : 0);
66
+ slot_lvl[s] = NO_SLOT;
67
+ events |= EV_SLEEP;
68
+ }
69
+
70
+ static void kill(char s)
71
+ {
72
+ char i = slot_lvl[s];
73
+ lvl_flags[i] = (lvl_flags[i] & ~LF_LIVE) | LF_DEAD;
74
+ slot_lvl[s] = NO_SLOT;
75
+ }
76
+
77
+ // Both windows in columns, clamped to the level, so every compare is a byte.
78
+ static void set_window(void)
79
+ {
80
+ int cc = camx >> 3;
81
+ int lo = cc - MARGIN, hi = cc + 40 + MARGIN;
82
+ win_lo = lo < 0 ? 0 : lo;
83
+ win_top = hi > 255 ? 255 : hi;
84
+ drop_lo = lo - HYST < 0 ? 0 : lo - HYST;
85
+ drop_top = hi + HYST > 255 ? 255 : hi + HYST;
86
+ }
87
+
88
+ // Half a pixel a frame; odd and even slots take turns, so a crowd costs
89
+ // half as much on any one frame. The column WALK_AHEAD pixels in front is
90
+ // judged once, when the walker first reaches it: an edge, a step too high
91
+ // or low, or a wall there turns the walker. Each step then costs one
92
+ // surface_walk for the ground snap (about 300 cycles by the meter's PROF
93
+ // runs, against about 1,100 when every step also probed walls and the
94
+ // ground ahead; README, "Enemies on screen").
95
+ #define WALK_AHEAD 6
96
+
97
+ static void walker(char s)
98
+ {
99
+ if ((tick ^ s) & 1)
100
+ return;
101
+ signed char dx = slot_left[s] ? -1 : 1;
102
+ char fy = slot_y[s] >> 8;
103
+ unsigned nx = slot_x[s] + dx;
104
+ unsigned probe = nx + dx * WALK_AHEAD;
105
+ char pc = probe >> 3;
106
+ if (pc != slot_probe[s])
107
+ {
108
+ slot_probe[s] = pc;
109
+ char ahead = surface_walk(probe, fy);
110
+ slot_turn[s] = ahead == 0xff || (ahead > fy && ahead - fy > MAX_SNAP) ||
111
+ (ahead < fy && fy - ahead > MAX_RISE) || wall_at(probe, fy, ENEMY_H);
112
+ }
113
+ if (slot_turn[s])
114
+ {
115
+ slot_left[s] = !slot_left[s];
116
+ slot_probe[s] = 0xff; // judge the other way afresh
117
+ return;
118
+ }
119
+ char sy = surface_walk(nx, fy);
120
+ slot_x[s] = nx;
121
+ if (sy != 0xff)
122
+ slot_y[s] = (unsigned)sy << 8;
123
+ }
124
+
125
+ static void hopper(char s)
126
+ {
127
+ slot_left[s] = px < slot_x[s]; // it watches the player
128
+ if (--slot_timer[s] == 0)
129
+ {
130
+ slot_timer[s] = HOP_WAIT;
131
+ slot_jump[s] = HOP_START;
132
+ anim_set(&slot_anim[s], an_hop_up);
133
+ }
134
+ }
135
+
136
+ void actors_update(void)
137
+ {
138
+ tick++;
139
+ set_window();
140
+ char i = scan_pos;
141
+ for (char k = 0; k < SCAN_K; k++)
142
+ {
143
+ if (i < lvl_count && !(lvl_flags[i] & (LF_LIVE | LF_DEAD)))
144
+ {
145
+ char c = lvl_col[i];
146
+ if (c >= win_lo && c <= win_top)
147
+ activate(i);
148
+ }
149
+ i = (i + 1) & (NLVL - 1);
150
+ }
151
+ scan_pos = i;
152
+
153
+ for (char s = 0; s < NSLOT; s++)
154
+ {
155
+ if (slot_lvl[s] == NO_SLOT)
156
+ continue;
157
+ struct Anim *a = &slot_anim[s];
158
+ anim_step(a);
159
+ if (slot_squashed[s])
160
+ {
161
+ if (anim_done(a))
162
+ slot_lvl[s] = NO_SLOT; // already dead in the table
163
+ continue;
164
+ }
165
+ if (slot_jump[s] != 0xff)
166
+ {
167
+ if (air_step(slot_x[s], &slot_y[s], &slot_jump[s], ENEMY_H, false))
168
+ {
169
+ slot_jump[s] = 0xff;
170
+ if (slot_type[s] == T_HOPPER)
171
+ anim_set(a, an_hop_sit);
172
+ }
173
+ }
174
+ else if (slot_type[s] == T_WALKER)
175
+ walker(s);
176
+ else
177
+ hopper(s);
178
+
179
+ char fy = slot_y[s] >> 8;
180
+ char c = slot_x[s] >> 3;
181
+ if (fy > 200 && fy < 240)
182
+ kill(s); // fell into a pit
183
+ else if (c < drop_lo || c > drop_top)
184
+ deactivate(s);
185
+ }
186
+ }
187
+
188
+ bool enemy_near(unsigned x, char dist)
189
+ {
190
+ for (char s = 0; s < NSLOT; s++)
191
+ {
192
+ if (slot_lvl[s] != NO_SLOT && !slot_squashed[s])
193
+ {
194
+ unsigned e = slot_x[s];
195
+ if ((e > x ? e - x : x - e) < dist)
196
+ return true;
197
+ }
198
+ }
199
+ return false;
200
+ }
201
+
202
+ // ---- hits: boxes per animation frame, emitted where the sprites are ----
203
+ // Coordinates are bytes relative to the player's foot, placed at (BOX_O,
204
+ // BOX_O); an enemy is listed only within NEAR pixels each way, so every
205
+ // compare in the pass is one byte (16-bit world X is taken apart once per
206
+ // enemy, never per box pair). After c64-kb per_frame_hitbox.
207
+ #define BOX_O 64
208
+ #define NEAR 40
209
+ #define MAXB (2 + NSLOT)
210
+ static char nbox;
211
+ static char bl[MAXB], br[MAXB], bt[MAXB], bb[MAXB], bg[MAXB], bm[MAXB], bo[MAXB];
212
+
213
+ static void emit_boxes(char owner, char shape, char left, char top)
214
+ {
215
+ char k = hb_first[shape], e = k + hb_count[shape], i = nbox;
216
+ for (; k != e; k++, i++)
217
+ {
218
+ const struct HBox *h = &hbox[k];
219
+ bl[i] = left + h->x0;
220
+ br[i] = left + h->x1;
221
+ bt[i] = top + h->y0;
222
+ bb[i] = top + h->y1;
223
+ bg[i] = h->group;
224
+ bm[i] = h->mask;
225
+ bo[i] = owner; // 0 the player, 1 + slot an enemy
226
+ }
227
+ nbox = i;
228
+ }
229
+
230
+ // The slots the feet hit and the slots the body hit, as bit masks.
231
+ char hit_stomp, hit_body;
232
+
233
+ static void collide(void)
234
+ {
235
+ hit_stomp = hit_body = 0;
236
+ for (char i = 0; i + 1 < nbox; i++)
237
+ {
238
+ char m = bm[i];
239
+ for (char j = i + 1; j < nbox; j++)
240
+ {
241
+ if (!(m & bg[j]))
242
+ continue; // a pair that cannot hurt each other
243
+ if (bl[i] <= br[j] && bl[j] <= br[i] && bt[i] <= bb[j] && bt[j] <= bb[i])
244
+ {
245
+ char p = bo[i] ? j : i, e = bo[i] ? bo[i] : bo[j];
246
+ char bit = 1 << (e - 1);
247
+ if (bg[p] == G_STOMP)
248
+ hit_stomp |= bit;
249
+ else
250
+ hit_body |= bit;
251
+ }
252
+ }
253
+ }
254
+ }
255
+
256
+ // Any enemy the feet reach is stomped; a body touch by any other hurts.
257
+ void actors_collide(void)
258
+ {
259
+ if (pinvuln)
260
+ return;
261
+ nbox = 0;
262
+ char fy = py >> 8;
263
+ emit_boxes(0, panim.shape + (pleft && panim.shape < SH_MIRROR ? SH_MIRROR : 0), BOX_O - 8, BOX_O - 21);
264
+ for (char s = 0; s < NSLOT; s++)
265
+ {
266
+ if (slot_lvl[s] == NO_SLOT || slot_squashed[s])
267
+ continue;
268
+ int dx = (int)slot_x[s] - (int)px;
269
+ signed char dy = (char)(slot_y[s] >> 8) - fy;
270
+ if (dx > -NEAR && dx < NEAR && dy > -NEAR && dy < NEAR)
271
+ emit_boxes(1 + s, slot_anim[s].shape, (char)dx + (BOX_O - 8), (char)dy + (BOX_O - 16));
272
+ }
273
+ collide();
274
+ for (char s = 0; s < NSLOT; s++)
275
+ {
276
+ if (!(hit_stomp & (1 << s)))
277
+ continue;
278
+ slot_squashed[s] = true;
279
+ anim_set(&slot_anim[s], an_squash);
280
+ lvl_flags[slot_lvl[s]] = (lvl_flags[slot_lvl[s]] & ~LF_LIVE) | LF_DEAD;
281
+ pjump = JUMP_BOUNCE;
282
+ stomps++;
283
+ score_add(1, 0);
284
+ events |= EV_STOMP;
285
+ sfx_play(SFX_STOMP);
286
+ }
287
+ if (hit_body & ~hit_stomp)
288
+ player_hurt();
289
+ }
@@ -0,0 +1,51 @@
1
+ // anim.c: sprite animation from tables (c64-kb sprite_animation_table).
2
+ // A sequence is (shape, frames) pairs ending in AN_LOOP n (go to pair n)
3
+ // or AN_HOLD (stay on the last pair). Facing is not in the tables: the
4
+ // player adds SH_MIRROR to the shape when it faces left.
5
+ #include "game.h"
6
+
7
+ #define AN_LOOP 0xff
8
+ #define AN_HOLD 0xfe
9
+
10
+ const char an_stand[] = { SH_STAND, 1, AN_HOLD };
11
+ const char an_run[] = { SH_RUN1, 6, SH_STAND, 4, SH_RUN2, 6, SH_STAND, 4, AN_LOOP, 0 };
12
+ const char an_jump[] = { SH_JUMP, 1, AN_HOLD }; // rising
13
+ const char an_fall[] = { SH_FALL, 1, AN_HOLD }; // falling: the stomp box
14
+ const char an_hurt[] = { SH_HURT, 1, AN_HOLD };
15
+ const char an_walk[] = { SH_WALK1, 8, SH_WALK2, 8, AN_LOOP, 0 };
16
+ const char an_squash[] = { SH_SQUASH, 24, AN_HOLD };
17
+ const char an_hop_sit[] = { SH_HOP_SIT, 1, AN_HOLD };
18
+ const char an_hop_up[] = { SH_HOP_UP, 1, AN_HOLD };
19
+
20
+ void anim_set(struct Anim *a, const char *seq)
21
+ {
22
+ if (a->seq == seq)
23
+ return;
24
+ a->seq = seq;
25
+ a->pos = 0;
26
+ a->shape = seq[0];
27
+ a->count = seq[1];
28
+ }
29
+
30
+ void anim_step(struct Anim *a)
31
+ {
32
+ if (a->count == 0 || --a->count)
33
+ return; // held (0), or the pair is not over
34
+ char p = a->pos + 2;
35
+ char op = a->seq[p];
36
+ if (op == AN_LOOP)
37
+ p = a->seq[p + 1] * 2;
38
+ else if (op == AN_HOLD)
39
+ {
40
+ a->count = 0; // stays on the last pair
41
+ return;
42
+ }
43
+ a->pos = p;
44
+ a->shape = a->seq[p];
45
+ a->count = a->seq[p + 1];
46
+ }
47
+
48
+ bool anim_done(struct Anim *a)
49
+ {
50
+ return a->count == 0;
51
+ }