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,793 @@
1
+ ---
2
+ recipe: flip-screen-rooms
3
+ toolchain: oscar64
4
+ output_format: PRG
5
+ region: both
6
+ techniques: [flip_screen_rooms, tile_grid_collision, tile_map_render, object_pool]
7
+ file_formats: [PRG]
8
+ uses_registers: [D000, D001, D010, D011, D012, D015, D017, D01C, D01D, D020, D021, D027, DC00, DC04, DC05, DC06, DC07, DC0E, DC0F]
9
+ uses_kernal: []
10
+ ---
11
+
12
+ <!-- doc-type: recipe -->
13
+
14
+ # Oscar64 Flip-Screen Rooms: five rooms as records, a full redraw on every edge, timed
15
+
16
+ ## Synopsis
17
+
18
+ A flip-screen world. Each room is one record: four edge exits (target
19
+ room, entry column, entry row, or none), a wall colour, an object count,
20
+ a run-length coded 40 x 22 tile stream in the format `tile-map-render.md`
21
+ and `level-rle-decoder.md` use, then the objects. Five rooms sit in a
22
+ 2 x 2 block with one dead end off the top right. A one-sprite player
23
+ walks against the decoded tile map (`tile-grid-collision.md`) and, on the
24
+ move that would take it past an edge with an exit, the sprite is hidden,
25
+ the display is blanked, the next room's record is decoded and drawn in one
26
+ pass, and the sprite is placed on the entry cell. Nothing scrolls. The
27
+ redraw is timed with CIA1 timers A and B cascaded and the last and worst
28
+ cost in cycles sit on the HUD row. An autopilot walks a scripted path
29
+ through every room and back, taking three keys; the verdict compares the
30
+ final room, cell and key count with a prediction the host script made
31
+ from the same room data, and the worst redraw with a stated budget.
32
+ `$02FF` is `01` and the border green for pass, `02` and red for fail, in
33
+ the manner of `headless-verify.md`. The room format is this page's own;
34
+ it is not any shipped game's.
35
+
36
+ ## Source
37
+
38
+ ```c
39
+ // flip-screen-rooms.c
40
+ //
41
+ // A flip-screen world of five 40 x 22 rooms. Each room is one record:
42
+ // four edge exits, a wall colour, an object count, a run-length coded
43
+ // tile stream in the tile-map-render format, then the objects. Leaving
44
+ // an edge that has an exit redraws the whole screen from the next
45
+ // room's record; nothing scrolls. The redraw is timed with CIA1 timers
46
+ // A and B cascaded, the sprite is hidden and the display blanked (DEN
47
+ // off) while it runs, and the HUD on row 0 shows the room, the player's
48
+ // cell, the last and worst redraw in cycles, the keys taken and the
49
+ // verdict. An autopilot walks a scripted path through every room and
50
+ // back; the verdict compares the final room, cell and key count with
51
+ // the host's prediction and the worst redraw with BUDGET. RESULT at
52
+ // $02FF is 01 (green border) for pass, 02 (red) for fail.
53
+ //
54
+ // Room record:
55
+ // bytes 0..11 exits up, down, left, right: target room (0xff none),
56
+ // entry column, entry row
57
+ // byte 12 wall colour
58
+ // byte 13 object count n
59
+ // then 22 row streams: c & 0x80 run of (c & 0x7f), c < 0x80
60
+ // literal count, 0 end of row
61
+ // then n objects of 3 bytes: type, column, row
62
+ //
63
+ #include <c64/vic.h>
64
+ #include <c64/cia.h>
65
+
66
+ #define Screen ((char *)0x0400)
67
+ #define Color ((char *)0xd800)
68
+ #define SprData ((char *)0x0340)
69
+ #define SprPtr ((char *)0x07f8)
70
+
71
+ #define ROOM_W 40
72
+ #define ROOM_H 22
73
+ #define ROOM_SIZE (ROOM_W * ROOM_H)
74
+ #define MAP_ROW 1 // screen row the room starts on
75
+ #define MAX_OBJ 8
76
+ #define NONE 0xff
77
+
78
+ #define RESULT (*(volatile char *)0x02ff)
79
+ #define CODE_PASS 0x01
80
+ #define CODE_FAIL 0x02
81
+
82
+ #ifndef AUTOPILOT
83
+ #define AUTOPILOT 1
84
+ #endif
85
+ #ifndef BUDGET
86
+ #define BUDGET 58968UL // three PAL frames of 19,656 cycles
87
+ #endif
88
+
89
+ enum { DIR_UP, DIR_DOWN, DIR_LEFT, DIR_RIGHT };
90
+ enum { T_FLOOR, T_WALL };
91
+
92
+ // --- world, emitted by rooms.py ------------------------------------
93
+ // room 0: 181 bytes (164 of tile stream)
94
+ const char room0[] = {
95
+ 0xff, 0x00, 0x00, 0x02, 0x14, 0x00, 0xff, 0x00, 0x00, 0x01, 0x00, 0x0a, 0x0e, 0x01, 0xa8, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00,
96
+ 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6,
97
+ 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01,
98
+ 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa7, 0x00, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00,
99
+ 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x89, 0x00, 0x01, 0x01, 0x85,
100
+ 0x00, 0x01, 0x01, 0x85, 0x00, 0x01, 0x01, 0x85, 0x00, 0x01, 0x01, 0x8a, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01,
101
+ 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00,
102
+ 0x01, 0x01, 0x00, 0x94, 0x01, 0x01, 0x00, 0x93, 0x01, 0x00, 0x01, 0x05, 0x03,
103
+ };
104
+ // room 1: 166 bytes (149 of tile stream)
105
+ const char room1[] = {
106
+ 0xff, 0x00, 0x00, 0x03, 0x26, 0x00, 0x00, 0x27, 0x0a, 0x04, 0x00, 0x05, 0x0d, 0x01, 0xa8, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00,
107
+ 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa7,
108
+ 0x00, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01,
109
+ 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0xa7, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01,
110
+ 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x83, 0x00, 0xa0, 0x01, 0x83, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01,
111
+ 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01,
112
+ 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0xa6, 0x01, 0x02, 0x00, 0x01, 0x00, 0x01, 0x1e, 0x0c,
113
+ };
114
+ // room 2: 205 bytes (188 of tile stream)
115
+ const char room2[] = {
116
+ 0x00, 0x14, 0x15, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x03, 0x00, 0x14, 0x0a, 0x01, 0x94, 0x01, 0x01, 0x00, 0x93, 0x01, 0x00, 0x01, 0x01, 0xa6,
117
+ 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01,
118
+ 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01,
119
+ 0x9d, 0x00, 0x01, 0x01, 0x88, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x9d, 0x00, 0x01, 0x01, 0x88, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x9d, 0x00,
120
+ 0x01, 0x01, 0x88, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x9d, 0x00, 0x01, 0x01, 0x88, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x9d, 0x00, 0x01, 0x01,
121
+ 0x88, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x9d, 0x00, 0x01, 0x01, 0x88, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x9d, 0x00, 0x01, 0x01, 0x88, 0x00,
122
+ 0x01, 0x01, 0x00, 0x01, 0x01, 0x9d, 0x00, 0x01, 0x01, 0x88, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x9d, 0x00, 0x01, 0x01, 0x88, 0x00, 0x01, 0x01,
123
+ 0x00, 0x01, 0x01, 0x9d, 0x00, 0x01, 0x01, 0x88, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01,
124
+ 0x01, 0x00, 0x01, 0x01, 0xa7, 0x00, 0x00, 0xa8, 0x01, 0x00, 0x01, 0x14, 0x0f,
125
+ };
126
+ // room 3: 180 bytes (163 of tile stream)
127
+ const char room3[] = {
128
+ 0x01, 0x26, 0x15, 0xff, 0x00, 0x00, 0x02, 0x27, 0x14, 0xff, 0x00, 0x00, 0x07, 0x01, 0xa6, 0x01, 0x02, 0x00, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00,
129
+ 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00,
130
+ 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x89,
131
+ 0x00, 0x01, 0x01, 0x85, 0x00, 0x01, 0x01, 0x85, 0x00, 0x01, 0x01, 0x85, 0x00, 0x01, 0x01, 0x8a, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00,
132
+ 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00,
133
+ 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6,
134
+ 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01,
135
+ 0x00, 0xa7, 0x00, 0x01, 0x01, 0x00, 0xa8, 0x01, 0x00, 0x01, 0x1e, 0x14,
136
+ };
137
+ // room 4: 201 bytes (184 of tile stream)
138
+ const char room4[] = {
139
+ 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x01, 0x27, 0x05, 0xff, 0x00, 0x00, 0x0c, 0x01, 0xa8, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00,
140
+ 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0xa7, 0x00, 0x01,
141
+ 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x8b, 0x00, 0x01, 0x01, 0x9a, 0x00,
142
+ 0x01, 0x01, 0x00, 0x01, 0x01, 0x8b, 0x00, 0x01, 0x01, 0x9a, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x8b, 0x00, 0x01, 0x01, 0x9a, 0x00, 0x01, 0x01,
143
+ 0x00, 0x01, 0x01, 0x8b, 0x00, 0x01, 0x01, 0x9a, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x8b, 0x00, 0x01, 0x01, 0x9a, 0x00, 0x01, 0x01, 0x00, 0x01,
144
+ 0x01, 0x8b, 0x00, 0x01, 0x01, 0x9a, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x8b, 0x00, 0x01, 0x01, 0x9a, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x8b,
145
+ 0x00, 0x01, 0x01, 0x9a, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x8b, 0x00, 0x01, 0x01, 0x9a, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x8b, 0x00, 0x01,
146
+ 0x01, 0x9a, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00,
147
+ 0x01, 0x01, 0x00, 0xa8, 0x01, 0x00, 0x01, 0x0a, 0x05,
148
+ };
149
+ // world: 933 bytes
150
+ const char * const rooms[5] = { room0, room1, room2, room3, room4 };
151
+ // script: direction, frames
152
+ const char script[] = {
153
+ 3, 150,
154
+ 3, 150,
155
+ 0, 20,
156
+ 3, 170,
157
+ 2, 160,
158
+ 2, 160,
159
+ 1, 20,
160
+ 2, 81,
161
+ 1, 140,
162
+ 3, 240,
163
+ 0, 180,
164
+ 2, 40,
165
+ };
166
+ // walk: 1511 frames
167
+ #define EXPECT_ROOM 1
168
+ #define EXPECT_COL 28
169
+ #define EXPECT_ROW 1
170
+ #define EXPECT_KEYS 3
171
+
172
+ // --- state ------------------------------------------------------------
173
+ char map[ROOM_SIZE]; // decoded tiles of the current room
174
+ char room; // current room index
175
+ int px, py; // player body top-left, room pixels (x reaches 312)
176
+ char room_bits[5]; // one bit per object per room: taken
177
+
178
+ // Object pool: parallel arrays, freed on every room change.
179
+ char obj_live[MAX_OBJ], obj_col[MAX_OBJ], obj_row[MAX_OBJ];
180
+ char obj_type[MAX_OBJ], obj_bit[MAX_OBJ];
181
+
182
+ unsigned long last_cost, worst_cost;
183
+ char keys;
184
+
185
+ void hud_cost(void);
186
+
187
+ const char glyph[2] = { 0x20, 0xa0 };
188
+ const char keyglyph = 0x2a;
189
+
190
+ // --- CIA1 timers A and B cascaded: B counts A underflows ----------------
191
+ static inline void timer_start(void)
192
+ {
193
+ cia1.cra = 0x00;
194
+ cia1.crb = 0x00;
195
+ cia1.ta = 0xffff;
196
+ cia1.tb = 0xffff;
197
+ cia1.crb = 0x51; // force load, start, count TA underflow
198
+ cia1.cra = 0x11; // force load, start, count phi2
199
+ }
200
+
201
+ static inline unsigned long timer_stop(void)
202
+ {
203
+ cia1.cra = 0x00;
204
+ cia1.crb = 0x00;
205
+ unsigned lo = 0xffff - cia1.ta;
206
+ unsigned hi = 0xffff - cia1.tb;
207
+ return ((unsigned long)hi << 16) | lo;
208
+ }
209
+
210
+ // --- text helpers -------------------------------------------------------
211
+ void put_str(char *p, const char *s)
212
+ {
213
+ while (*s)
214
+ *p++ = *s++;
215
+ }
216
+
217
+ // --- the record: decode and draw in one pass -------------------------
218
+ // Expands the 22 row streams at src into map and, as each byte lands,
219
+ // writes its glyph and colour to the screen. Pointers step by one row
220
+ // and a char index walks the row, which is the 6502's (zp),y shape.
221
+ // Returns the byte after the stream.
222
+ const char *rle_room(const char *src, char colour)
223
+ {
224
+ char *m = map;
225
+ char *s = Screen + MAP_ROW * 40;
226
+ char *c = Color + MAP_ROW * 40;
227
+ for (char y = 0; y < ROOM_H; y++) {
228
+ char x = 0;
229
+ for (;;) {
230
+ char ctl = *src++;
231
+ if (ctl == 0)
232
+ break;
233
+ if (ctl & 0x80) {
234
+ char v = *src++;
235
+ char g = glyph[v], k = v ? colour : 11;
236
+ ctl &= 0x7f;
237
+ do {
238
+ m[x] = v; s[x] = g; c[x] = k; x++;
239
+ } while (--ctl);
240
+ } else {
241
+ do {
242
+ char v = *src++;
243
+ m[x] = v; s[x] = glyph[v]; c[x] = v ? colour : 11; x++;
244
+ } while (--ctl);
245
+ }
246
+ }
247
+ m += ROOM_W; s += 40; c += 40;
248
+ }
249
+ return src;
250
+ }
251
+
252
+ void load_objects(const char *src, char count)
253
+ {
254
+ for (char i = 0; i < MAX_OBJ; i++)
255
+ obj_live[i] = 0;
256
+ for (char i = 0; i < count && i < MAX_OBJ; i++) {
257
+ char t = src[0], col = src[1], row = src[2];
258
+ src += 3;
259
+ if (room_bits[room] & (1 << i))
260
+ continue; // taken on an earlier visit
261
+ obj_live[i] = 1;
262
+ obj_type[i] = t;
263
+ obj_col[i] = col;
264
+ obj_row[i] = row;
265
+ obj_bit[i] = 1 << i;
266
+ unsigned at = (MAP_ROW + row) * 40 + col;
267
+ Screen[at] = keyglyph;
268
+ Color[at] = 7;
269
+ }
270
+ }
271
+
272
+ // Full redraw from the record of room r. Called at raster 251 with the
273
+ // sprite already hidden and DEN already off, so the frame that follows
274
+ // is blank and no half-drawn frame shows.
275
+ void enter_room(char r)
276
+ {
277
+ room = r;
278
+ const char *rec = rooms[r];
279
+ timer_start();
280
+ const char *p = rle_room(rec + 14, rec[12]);
281
+ load_objects(p, rec[13]);
282
+ last_cost = timer_stop();
283
+ if (last_cost > worst_cost)
284
+ worst_cost = last_cost;
285
+ }
286
+
287
+ // --- collision against the decoded map --------------------------------
288
+ // Body is the 8 x 8 block at sprite columns 8..15, rows 0..7. A point
289
+ // outside the room is solid; the edge test in move() runs first.
290
+ static inline char solid(int x, int y)
291
+ {
292
+ if (x < 0 || y < 0 || x >= ROOM_W * 8 || y >= ROOM_H * 8)
293
+ return 1;
294
+ return map[(y >> 3) * ROOM_W + (x >> 3)] == T_WALL;
295
+ }
296
+
297
+ // The edge triggers on the attempted move, not on the cell the player
298
+ // stands in, so the entry cell on the far side never fires it again.
299
+ char try_exit(char dir)
300
+ {
301
+ const char *e = rooms[room] + dir * 3;
302
+ if (e[0] == NONE)
303
+ return 0;
304
+ char target = e[0];
305
+ px = e[1] * 8;
306
+ py = e[2] * 8;
307
+ vic.spr_enable = 0;
308
+ vic.ctrl1 &= 0xef; // DEN off: next frame is blank
309
+ enter_room(target);
310
+ vic.ctrl1 |= 0x10; // DEN on before the untimed HUD work
311
+ hud_cost();
312
+ return 1;
313
+ }
314
+
315
+ void move(char dir)
316
+ {
317
+ int nx = px, ny = py;
318
+ switch (dir) {
319
+ case DIR_UP: ny -= 2; break;
320
+ case DIR_DOWN: ny += 2; break;
321
+ case DIR_LEFT: nx -= 2; break;
322
+ case DIR_RIGHT: nx += 2; break;
323
+ }
324
+ if (nx < 0 || nx > (ROOM_W - 1) * 8 || ny < 0 || ny > (ROOM_H - 1) * 8) {
325
+ try_exit(dir);
326
+ return;
327
+ }
328
+ // Leading edge, two corners: an 8-pixel edge needs no more.
329
+ char hit;
330
+ switch (dir) {
331
+ case DIR_UP: hit = solid(nx, ny) | solid(nx + 7, ny); break;
332
+ case DIR_DOWN: hit = solid(nx, ny + 7) | solid(nx + 7, ny + 7); break;
333
+ case DIR_LEFT: hit = solid(nx, ny) | solid(nx, ny + 7); break;
334
+ default: hit = solid(nx + 7, ny) | solid(nx + 7, ny + 7); break;
335
+ }
336
+ if (!hit) {
337
+ px = nx;
338
+ py = ny;
339
+ }
340
+ }
341
+
342
+ void pick_up(void)
343
+ {
344
+ char col = (char)(px >> 3), row = (char)(py >> 3);
345
+ for (char i = 0; i < MAX_OBJ; i++) {
346
+ if (obj_live[i] && obj_col[i] == col && obj_row[i] == row) {
347
+ obj_live[i] = 0;
348
+ room_bits[room] |= obj_bit[i];
349
+ Screen[(MAP_ROW + row) * 40 + col] = 0x20;
350
+ keys++;
351
+ }
352
+ }
353
+ }
354
+
355
+ // --- HUD ------------------------------------------------------------
356
+ // Row 0: R room C col,row L last redraw W worst redraw K keys V code.
357
+ // The two 32-bit fields are written only after a transition; a 32-bit
358
+ // decimal conversion every frame cost more than the frame.
359
+ void put_long(char *p, unsigned long v, char digits)
360
+ {
361
+ for (char i = digits; i > 0; i--) {
362
+ p[i - 1] = 0x30 + (char)(v % 10);
363
+ v /= 10;
364
+ }
365
+ }
366
+
367
+ void hud_cost(void)
368
+ {
369
+ put_long(Screen + 11, last_cost, 5);
370
+ put_long(Screen + 18, worst_cost, 5);
371
+ }
372
+
373
+ void hud(char code)
374
+ {
375
+ char *p = Screen;
376
+ p[1] = 0x30 + room;
377
+ char col = (char)(px >> 3), row = (char)(py >> 3);
378
+ p[4] = 0x30 + col / 10; p[5] = 0x30 + col % 10;
379
+ p[7] = 0x30 + row / 10; p[8] = 0x30 + row % 10;
380
+ p[25] = 0x30 + keys;
381
+ p[28] = 0x30 + code / 10; p[29] = 0x30 + code % 10;
382
+ }
383
+
384
+ // --- sprite ------------------------------------------------------------
385
+ void sprite_init(void)
386
+ {
387
+ for (char i = 0; i < 63; i++)
388
+ SprData[i] = 0;
389
+ for (char i = 0; i < 8; i++)
390
+ SprData[i * 3 + 1] = 0xff;
391
+ SprPtr[0] = 0x0340 / 64;
392
+ vic.spr_color[0] = 1;
393
+ vic.spr_multi = 0;
394
+ vic.spr_expand_x = 0;
395
+ vic.spr_expand_y = 0;
396
+ }
397
+
398
+ void sprite_place(void)
399
+ {
400
+ // Body columns 8..15 sit on the cell: sprite X = 24 + px - 8.
401
+ vic_sprxy(0, 16 + px, 50 + MAP_ROW * 8 + py);
402
+ vic.spr_enable = 1;
403
+ }
404
+
405
+ static inline void wait_bottom(void)
406
+ {
407
+ while (vic.raster != 251)
408
+ ;
409
+ }
410
+
411
+ // --- main ----------------------------------------------------------------
412
+ int main(void)
413
+ {
414
+ __asm { sei }
415
+ vic.color_border = 0;
416
+ vic.color_back = 0;
417
+ for (unsigned i = 0; i < 1000; i++) {
418
+ Screen[i] = 0x20;
419
+ Color[i] = 1;
420
+ }
421
+ sprite_init();
422
+ put_str(Screen, s"r c , l w k v ");
423
+ px = 5 * 8;
424
+ py = 10 * 8;
425
+ vic.ctrl1 &= 0xef;
426
+ vic_waitFrame();
427
+ vic_waitFrame();
428
+ enter_room(0);
429
+ worst_cost = 0; // the first draw is not a transition
430
+ hud_cost();
431
+ sprite_place();
432
+ vic.ctrl1 |= 0x10;
433
+
434
+ char code = 0;
435
+ #if AUTOPILOT
436
+ char step = 0;
437
+ char left = script[1];
438
+ #endif
439
+ for (;;) {
440
+ wait_bottom();
441
+ sprite_place();
442
+ hud(code);
443
+ #if AUTOPILOT
444
+ if (step < sizeof(script)) {
445
+ move(script[step]);
446
+ if (--left == 0) {
447
+ step += 2;
448
+ if (step < sizeof(script))
449
+ left = script[step + 1];
450
+ }
451
+ } else if (code == 0) {
452
+ code = CODE_PASS;
453
+ if (room != EXPECT_ROOM || (px >> 3) != EXPECT_COL ||
454
+ (py >> 3) != EXPECT_ROW || keys != EXPECT_KEYS ||
455
+ worst_cost > BUDGET)
456
+ code = CODE_FAIL;
457
+ RESULT = code;
458
+ vic.color_border = (code == CODE_PASS) ? 5 : 2;
459
+ }
460
+ #else
461
+ char j = ~cia1.pra;
462
+ if (j & 1) move(DIR_UP);
463
+ else if (j & 2) move(DIR_DOWN);
464
+ else if (j & 4) move(DIR_LEFT);
465
+ else if (j & 8) move(DIR_RIGHT);
466
+ #endif
467
+ pick_up();
468
+ }
469
+ return 0;
470
+ }
471
+ ```
472
+
473
+ ## Build
474
+
475
+ ```bash
476
+ python3 rooms.py > gen.h # the room arrays, the script and the EXPECT_* lines
477
+ oscar64 -tm=c64 -O2 -n -o=flip-screen-rooms.prg flip-screen-rooms.c
478
+ ```
479
+
480
+ Produces `flip-screen-rooms.prg`, 3,665 bytes (Oscar64 build 2026-05-19),
481
+ plus `flip-screen-rooms.map`, which puts `rle_room` at 224 bytes of code
482
+ (`0b00 - 0be0`). The listing above is the generator's output pasted in;
483
+ `rooms.py` is the script below. Then run headless in VICE (PAL):
484
+
485
+ ```bash
486
+ x64sc -default -warp +sound +autostart-delay-random -autostartprgmode 1 \
487
+ -limitcycles 34000000 -exitscreenshot flip-screen-rooms.png \
488
+ -autostart flip-screen-rooms.prg
489
+ ```
490
+
491
+ Add `-model ntsc` for the NTSC picture. The walk is 1,511 frames; at
492
+ 19,656 cycles a PAL frame that is 29.7 million cycles after the autostart,
493
+ and the limit leaves room for the transitions and the BASIC start.
494
+
495
+ `-dAUTOPILOT=0` builds the joystick version: port 2, four directions, the
496
+ same rooms, 3,482 bytes. It was built and not run here.
497
+
498
+ ### The generator
499
+
500
+ `rooms.py` authors the five rooms as character grids, opens the exit gaps
501
+ in both rooms of each link, encodes each row with the three-byte run
502
+ threshold, and walks the script pixel by pixel with the same two-corner
503
+ probe the C code uses, so its `EXPECT_*` lines are a prediction and not a
504
+ reading. An earlier version walked cells and was one cell out on the leg
505
+ after an edge crossing: a crossing costs one frame, not the four a cell
506
+ takes at 2 px per frame.
507
+
508
+ ```python
509
+ # rooms.py: authors five 40 x 22 rooms, run-length encodes them with the
510
+ # tile-map-render stream format, prints the C arrays, and predicts the
511
+ # autopilot's final state by walking the script at pixel level.
512
+ W, H = 40, 22
513
+ UP, DOWN, LEFT, RIGHT = 0, 1, 2, 3
514
+ NONE = 0xFF
515
+
516
+ def blank(colour):
517
+ g = [['#'] * W] + [['#'] + ['.'] * (W - 2) + ['#'] for _ in range(H - 2)] + [['#'] * W]
518
+ return g, colour
519
+
520
+ # World: 0 -- 1 -- 4 (dead end)
521
+ # | |
522
+ # 2 -- 3
523
+ rooms = [blank(c) for c in (14, 13, 10, 7, 12)] # wall colours per room
524
+ exits = [{} for _ in rooms]
525
+
526
+ def link(a, da, b, db, ca, ra, cb, rb):
527
+ """Open a gap at (ca, ra) in room a and (cb, rb) in room b, and set
528
+ both exits. The entry cell is the gap cell on the far side."""
529
+ rooms[a][0][ra][ca] = '.'
530
+ rooms[b][0][rb][cb] = '.'
531
+ exits[a][da] = (b, cb, rb)
532
+ exits[b][db] = (a, ca, ra)
533
+
534
+ link(0, RIGHT, 1, LEFT, 39, 10, 0, 10)
535
+ link(1, RIGHT, 4, LEFT, 39, 5, 0, 5)
536
+ link(0, DOWN, 2, UP, 20, 21, 20, 0)
537
+ link(2, RIGHT, 3, LEFT, 39, 20, 0, 20)
538
+ link(3, UP, 1, DOWN, 38, 0, 38, 21)
539
+
540
+ # A few pillars so the rooms are not all one run; none on the script path.
541
+ for x in range(10, 30, 6):
542
+ rooms[0][0][15][x] = '#'
543
+ rooms[3][0][8][x] = '#'
544
+ for y in range(8, 18):
545
+ rooms[2][0][y][30] = '#'
546
+ rooms[4][0][y][12] = '#'
547
+ for x in range(4, 36):
548
+ rooms[1][0][14][x] = '#'
549
+
550
+ # Objects: type 1 = key. (room, col, row)
551
+ objects = {0: [(1, 5, 3)], 1: [(1, 30, 12)], 2: [(1, 20, 15)],
552
+ 3: [(1, 30, 20)], 4: [(1, 10, 5)]}
553
+
554
+ def rle_row(row):
555
+ out, i = [], 0
556
+ while i < W:
557
+ j = i
558
+ while j < W and row[j] == row[i]:
559
+ j += 1
560
+ n = j - i
561
+ if n >= 3:
562
+ out += [0x80 | n, row[i]]
563
+ i = j
564
+ else:
565
+ k = i
566
+ while k < W:
567
+ m = k
568
+ while m < W and row[m] == row[k]:
569
+ m += 1
570
+ if m - k >= 3:
571
+ break
572
+ k = m
573
+ lit = row[i:k]
574
+ out += [len(lit)] + lit
575
+ i = k
576
+ return out + [0]
577
+
578
+ def encode(idx):
579
+ grid, colour = rooms[idx]
580
+ tiles = [[1 if ch == '#' else 0 for ch in row] for row in grid]
581
+ hdr = []
582
+ for d in (UP, DOWN, LEFT, RIGHT):
583
+ t = exits[idx].get(d)
584
+ hdr += list(t) if t else [NONE, 0, 0]
585
+ objs = objects[idx]
586
+ hdr += [colour, len(objs)]
587
+ body = []
588
+ for row in tiles:
589
+ body += rle_row(row)
590
+ tail = [b for o in objs for b in o]
591
+ return hdr + body + tail, len(body)
592
+
593
+ # Autopilot script: (direction, frames), 2 px per frame, one entry at most
594
+ # 255 frames. An edge crossing costs one frame, so the predictor walks
595
+ # pixels, not cells, with the same two-corner probe the C code uses.
596
+ script = [(RIGHT, 150), (RIGHT, 150), (UP, 20), (RIGHT, 170), (LEFT, 160),
597
+ (LEFT, 160), (DOWN, 20), (LEFT, 81), (DOWN, 140), (RIGHT, 240),
598
+ (UP, 180), (LEFT, 40)]
599
+ DX = {UP: 0, DOWN: 0, LEFT: -2, RIGHT: 2}
600
+ DY = {UP: -2, DOWN: 2, LEFT: 0, RIGHT: 0}
601
+
602
+ def wall(room, x, y):
603
+ if x < 0 or y < 0 or x >= W * 8 or y >= H * 8:
604
+ return True
605
+ return rooms[room][0][y >> 3][x >> 3] == '#'
606
+
607
+ def predict(room, col, row):
608
+ px, py, picked = col * 8, row * 8, set()
609
+ for d, frames in script:
610
+ for _ in range(frames):
611
+ nx, ny = px + DX[d], py + DY[d]
612
+ if nx < 0 or nx > (W - 1) * 8 or ny < 0 or ny > (H - 1) * 8:
613
+ t = exits[room].get(d)
614
+ if t:
615
+ room, px, py = t[0], t[1] * 8, t[2] * 8
616
+ else:
617
+ if d == UP: hit = wall(room, nx, ny) or wall(room, nx + 7, ny)
618
+ elif d == DOWN: hit = wall(room, nx, ny + 7) or wall(room, nx + 7, ny + 7)
619
+ elif d == LEFT: hit = wall(room, nx, ny) or wall(room, nx, ny + 7)
620
+ else: hit = wall(room, nx + 7, ny) or wall(room, nx + 7, ny + 7)
621
+ if not hit:
622
+ px, py = nx, ny
623
+ for o in objects[room]:
624
+ if (o[1], o[2]) == (px >> 3, py >> 3):
625
+ picked.add((room, o[1], o[2]))
626
+ return room, px >> 3, py >> 3, len(picked), sum(f for _, f in script)
627
+
628
+ if __name__ == '__main__':
629
+ total = 0
630
+ for i in range(len(rooms)):
631
+ data, body = encode(i)
632
+ total += len(data)
633
+ print('// room %d: %d bytes (%d of tile stream)' % (i, len(data), body))
634
+ print('const char room%d[] = {' % i)
635
+ for k in range(0, len(data), 24):
636
+ print(' ' + ', '.join('0x%02x' % b for b in data[k:k + 24]) + ',')
637
+ print('};')
638
+ print('// world: %d bytes' % total)
639
+ print('const char * const rooms[%d] = { %s };' %
640
+ (len(rooms), ', '.join('room%d' % i for i in range(len(rooms)))))
641
+ print('// script: direction, frames')
642
+ print('const char script[] = {')
643
+ for d, f in script:
644
+ print(' %d, %d,' % (d, f))
645
+ print('};')
646
+ r, c, y, k, frames = predict(0, 5, 10)
647
+ print('// walk: %d frames' % frames)
648
+ print('#define EXPECT_ROOM %d' % r)
649
+ print('#define EXPECT_COL %d' % c)
650
+ print('#define EXPECT_ROW %d' % y)
651
+ print('#define EXPECT_KEYS %d' % k)
652
+ ```
653
+
654
+ ## Expected output
655
+
656
+ Green border, black background. Row 0 reads, on both models:
657
+
658
+ ```text
659
+ R1 C28,01 L40204 W42141 K3 V01
660
+ ```
661
+
662
+ The fields are: room index, the player's cell (column, row), the last
663
+ redraw in cycles, the worst redraw in cycles, keys taken, verdict code.
664
+ Rows 1 to 22 are room 1: a light green frame with a gap in the left wall
665
+ at row 10, in the right wall at row 5 and in the bottom wall at column 38,
666
+ a bar of wall across row 14, the key at (30, 12) still in place because
667
+ the walk never crosses it, and the white 8 x 8 player at column 28 of
668
+ room row 1 (screen row 2). The picture is a room other than the first.
669
+
670
+ Measured on the committed PNGs with PIL (VICE x64sc 3.10, both models,
671
+ 34,000,000 cycles): row 0 decoded cell by cell against
672
+ `chargen-901225-01.bin` gives the line above; the border pixel (2, 100)
673
+ is (98, 213, 50) on PAL and (114, 189, 103) on NTSC, colour 5 in each
674
+ palette of `runtime/vice-reference.md`; the 24 x 24 block around the
675
+ player's cell holds exactly 64 white pixels, all inside the 8 x 8 cell at
676
+ x 256 to 263; the key cell (30, 12) has 24 lit pixels. The pinned command
677
+ was run twice per model and the PNG bytes were identical each time.
678
+
679
+ The final state matches the generator's prediction (room 1, cell 28,1,
680
+ 3 keys), and the worst redraw, 42,141 cycles, is under the 58,968-cycle
681
+ budget (`BUDGET`, three PAL frames). The worst is one of the seven
682
+ transitions the walk makes; the last, into room 1, cost 40,204. The
683
+ first draw of room 0 at start-up cost 40,941 and is excluded from the
684
+ worst by design, since it is not a transition.
685
+
686
+ The red case was seen twice while the listing was being built and is
687
+ recorded here as the shape of a failure: with the player's x held in a
688
+ `char` the position wrapped at column 32, no edge was ever reached, and
689
+ the verdict was `R0 C19,01 L40941 W00000 K0 V02` with a red border; with
690
+ the cell-level predictor the walk ended in room 0 at (28, 1) with one key
691
+ and the same red verdict. Neither picture is committed.
692
+
693
+ ## Why this works
694
+
695
+ **The record.** Fourteen header bytes, then the tile stream, then the
696
+ objects. `rle_room` returns the byte after the last row's terminator, so
697
+ the object list needs no offset field and a room with more or fewer rows
698
+ of runs still finds its objects. The exits are three bytes per edge in
699
+ the order up, down, left, right, which is the order of the direction
700
+ enum, so `try_exit` indexes the header with `dir * 3` and nothing else.
701
+
702
+ **The edge rule.** The transition fires on the attempted move that would
703
+ take the body past the room's last cell, not on the cell the player
704
+ stands in. The entry cell is the gap cell on the far side of the next
705
+ room. A rule that fired on position would fire again on the first frame
706
+ in the new room and bounce the player back; this one fires only when the
707
+ player pushes at the edge again, which is the way back.
708
+
709
+ **The redraw and the frame it spans.** The frame loop waits for raster
710
+ 251, so `move` and therefore `try_exit` run in the lower border. The
711
+ sprite is disabled and DEN is cleared before the first screen write. DEN
712
+ is sampled once per frame on line `$30`, so the frame that follows is
713
+ blank in the border colour and makes no badlines, and the writes that
714
+ land before that sample fall in the border. DEN is set again as soon as
715
+ `enter_room` returns and before the HUD's decimal conversions, so the
716
+ interval from DEN clear to DEN set is the timed redraw plus the few
717
+ cycles that start and stop the timers: 40,000 to 42,000 cycles, 2.1 PAL
718
+ frames or 2.5 NTSC frames. Arithmetic from the measured cycles, not
719
+ measured as a frame count: the screen is blank for two frames on PAL
720
+ (line `$30` falls at about 6,900, 26,500 and 46,200 cycles after raster
721
+ 251, and the redraw ends before the third sample) and three on NTSC
722
+ (3,900, 21,000, 38,100 and 55,200). The order of the two writes matters.
723
+ An earlier build ran the HUD's two 32-bit conversions between the redraw
724
+ and the DEN set, and an instrumented copy with CIA2 timers cascaded
725
+ around the whole of `try_exit` measured that interval at 55,483 cycles
726
+ from DEN clear to DEN set on both models: three blank frames on PAL, and
727
+ three or four on NTSC, because the worst case passes the fourth sample
728
+ by about 300 cycles. The frame count is a property of the whole blanked
729
+ interval, not of the timed redraw alone. No frame is ever torn, because
730
+ no visible line is drawn while screen RAM is half-written. The other
731
+ policy, leaving DEN set and accepting the torn frames, was not run here.
732
+
733
+ **One pass, per row.** The first version decoded into `map` and then
734
+ copied 880 cells to the screen in a second loop indexed by a 16-bit
735
+ counter, and cost 99,262 cycles, five PAL frames. The decoder now writes
736
+ the tile, its glyph and its colour as each byte lands, with three
737
+ pointers stepped by one row and a `char` index along the row, which
738
+ Oscar64 compiles to indexed stores. That is 40,204 to 42,141 cycles for
739
+ a room of 149 to 188 stream bytes, or 46 to 48 cycles per cell. The
740
+ `level-rle-decoder.md` figures for the decode alone, 33,562 for its
741
+ platform room in C and 19,158 by hand, show where the next factor of two
742
+ is: a hand-written decoder that writes the three destinations from one
743
+ `(zp),y` triple.
744
+
745
+ **The HUD costs most of a frame.** The first build converted the two
746
+ 32-bit cycle counts to decimal every frame and the walk crawled at about
747
+ two frames per step. The two five-digit conversions cost 13,311 cycles on
748
+ both models in the instrumented copy above, most of a PAL frame, on top
749
+ of the per-frame work and the wait for raster 251. The cost fields are
750
+ now written only after a transition, and after DEN is set, and the
751
+ per-frame HUD is `char` arithmetic.
752
+
753
+ **Objects.** Each room's list is loaded into an eight-slot pool on entry
754
+ and the pool is cleared first, so nothing carries over from the last
755
+ room. One bit per object per room in `room_bits` records what has been
756
+ taken, and `load_objects` skips those, so a key does not come back on a
757
+ second visit. The walk re-enters rooms 1 and 0 and the counts stay at
758
+ three.
759
+
760
+ **Collision.** The body is the 8 x 8 block at sprite columns 8 to 15,
761
+ rows 0 to 7, so `vic_sprxy` places the sprite at `16 + px`. The step is 2
762
+ px, under a tile, and the leading edge is probed at its two corners,
763
+ which is enough for an 8-pixel edge (`tile_grid_collision`, probe
764
+ spacing). A point outside the room is solid; the edge test in `move`
765
+ runs first, so an edge with an exit is passable and one without is a
766
+ wall.
767
+
768
+ ## Verification
769
+
770
+ Three instruments, run against the committed PNGs (VICE x64sc 3.10,
771
+ Oscar64 build 2026-05-19).
772
+
773
+ **Text, sprite and border.** A script matched every cell of row 0
774
+ against the char ROM glyphs and read the border pixel at (2, 100) on both
775
+ pictures; it counted the white pixels in the 24 x 24 block around the
776
+ player's cell (64, all in one 8 x 8 cell) and the lit pixels in the key
777
+ cell (24). The figures are quoted above.
778
+
779
+ **Prediction.** `rooms.py` walked the script over the same room data
780
+ before the machine did and printed room 1, cell (28, 1), 3 keys. The
781
+ machine printed the same and set `V01`. Room, column, row and key count
782
+ are four independent bytes; a wrong exit table, a wrong entry cell, a
783
+ wrong probe or a missed pickup each moves at least one of them.
784
+
785
+ **Reproducibility.** The pinned command was run twice per model and the
786
+ PNG bytes were identical each time.
787
+
788
+ What this does not establish: the frame counts of the blank are
789
+ arithmetic on measured cycle intervals, not a raster measurement, and
790
+ the DEN-clear-to-DEN-set interval of the committed listing was not timed
791
+ separately, only the redraw inside it; the joystick build was compiled and
792
+ not run; the redraw cost of a room with a picture in it, or with a
793
+ metatile layer, is not measured here.