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,620 @@
1
+ ---
2
+ recipe: level-rle-decoder
3
+ toolchain: oscar64
4
+ output_format: PRG
5
+ region: both
6
+ techniques: [tile_map_render]
7
+ file_formats: [PRG]
8
+ uses_registers: [D011, D020, D021, DC06, DC07, DC0F]
9
+ uses_kernal: []
10
+ ---
11
+
12
+ <!-- doc-type: recipe -->
13
+
14
+ # Oscar64 Level RLE Decoder: three rooms compressed on the host, decoded and measured on the machine
15
+
16
+ ## Synopsis
17
+
18
+ Puts numbers on the claim that run-length coding is enough for a tile
19
+ level. Three 40 x 22 rooms are authored as tile arrays in a Python script
20
+ (a platform room, a maze, a sparse room), run-length encoded on the host
21
+ with the stream format of `tile-map-render.md` (run byte `0x80 | n`,
22
+ literal count, `0` at the end of each row), and compiled in as byte arrays.
23
+ On the machine each room is decoded into RAM twice, once by a C decoder
24
+ and once by the same decoder written by hand in `__asm`, and each decode
25
+ is checksummed against the value the host computed from the source arrays
26
+ and timed with CIA1 timer B. Rows 0 to 2 print one line per room: packed
27
+ bytes, ratio, C cycles, hand-written cycles, PASS or FAIL. Row 0 also
28
+ carries the verdict code, which is mirrored to `$02FF` and the border
29
+ colour in the manner of `headless-verify.md`. Rows 3 to 24 draw the
30
+ decoded platform room. The decoders' code sizes come from the `.map` file
31
+ Oscar64 writes next to the `.prg`. This is the decode half of the
32
+ `tile_map_render` technique in `docs/techniques/scroll.md`; the figures
33
+ replace the unmeasured ratio and decoder-size sentences that
34
+ `docs/game-design/game-design-patterns.md` used to carry.
35
+
36
+ ## Source
37
+
38
+ ```c
39
+ // level-rle-decoder.c
40
+ //
41
+ // Decodes three RLE-compressed 40 x 22 rooms into RAM, checksums each
42
+ // against a value computed on the host from the source tile arrays,
43
+ // and measures the decode cost with CIA1 timer B. Rows 0-2 print one
44
+ // line per room: packed bytes, ratio, cycles, PASS or FAIL. Row 0 also
45
+ // carries the overall RESULT code, which is mirrored to $02FF and the
46
+ // border colour. Rows 3-24 draw the decoded platform room.
47
+ //
48
+ // Stream format (the tile-map-render format): control byte c
49
+ // c & 0x80 : run, the next byte repeated (c & 0x7f) times
50
+ // c < 0x80 : c literal bytes follow
51
+ // 0x00 : end of row
52
+ // Each of the 22 rows is its own stream; a run never crosses a row.
53
+ //
54
+ #include <c64/vic.h>
55
+ #include <c64/cia.h>
56
+
57
+ #define Screen ((char *)0x0400)
58
+ #define Color ((char *)0xd800)
59
+
60
+ #define ROOM_W 40
61
+ #define ROOM_H 22
62
+ #define ROOM_SIZE (ROOM_W * ROOM_H)
63
+
64
+ #define RESULT (*(volatile char *)0x02ff)
65
+ #define CODE_PASS 0x01
66
+ #define CODE_FAIL 0x02
67
+
68
+ // --- compressed rooms, emitted by rle_rooms.py ------------------------
69
+ // platform: 880 bytes -> 213 bytes, ratio 4.13, checksum 0xce8a
70
+ const char rle_platform[] = {
71
+ 0xa8, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x05, 0x01, 0x00, 0x00, 0x04, 0x04, 0xa2, 0x00, 0x01, 0x01, 0x00, 0x02, 0x01, 0x00,
72
+ 0x86, 0x02, 0x9d, 0x00, 0x03, 0x06, 0x00, 0x01, 0x00, 0x01, 0x01, 0x9a, 0x00, 0x88, 0x02, 0x05, 0x00, 0x00, 0x05, 0x05, 0x01, 0x00, 0x01, 0x01,
73
+ 0xa4, 0x00, 0x03, 0x05, 0x05, 0x01, 0x00, 0x01, 0x01, 0x8c, 0x00, 0x85, 0x02, 0x93, 0x00, 0x03, 0x05, 0x05, 0x01, 0x00, 0x01, 0x01, 0x9e, 0x00,
74
+ 0x88, 0x05, 0x01, 0x01, 0x00, 0x01, 0x01, 0x85, 0x00, 0x88, 0x03, 0x99, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x05,
75
+ 0x01, 0x00, 0x00, 0x05, 0x05, 0x8d, 0x00, 0x87, 0x02, 0x8e, 0x00, 0x01, 0x01, 0x00, 0x05, 0x01, 0x00, 0x00, 0x05, 0x05, 0xa2, 0x00, 0x01, 0x01,
76
+ 0x00, 0x05, 0x01, 0x00, 0x00, 0x05, 0x05, 0x86, 0x00, 0x02, 0x04, 0x04, 0x9a, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x99, 0x02, 0x8d, 0x00, 0x01,
77
+ 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x9d, 0x00, 0x89, 0x02, 0x01, 0x01,
78
+ 0x00, 0x01, 0x01, 0x8a, 0x00, 0x86, 0x02, 0x96, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0xa6, 0x00, 0x01, 0x01, 0x00, 0x04, 0x01, 0x00, 0x04, 0x04,
79
+ 0x92, 0x00, 0x8c, 0x03, 0x85, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x91, 0x02, 0x84, 0x00, 0x92, 0x01, 0x00, 0xa8, 0x01, 0x00,
80
+ };
81
+ // maze: 880 bytes -> 629 bytes, ratio 1.40, checksum 0xf439
82
+ const char rle_maze[] = {
83
+ 0xa8, 0x01, 0x00, 0x01, 0x01, 0x83, 0x00, 0x01, 0x01, 0x87, 0x00, 0x01, 0x01, 0x85, 0x00, 0x01, 0x01, 0x85, 0x00, 0x01, 0x01, 0x83, 0x00, 0x01,
84
+ 0x01, 0x8a, 0x00, 0x01, 0x01, 0x00, 0x06, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x85, 0x01, 0x03, 0x00, 0x01, 0x00, 0x83, 0x01, 0x03, 0x00, 0x01,
85
+ 0x00, 0x83, 0x01, 0x07, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x88, 0x01, 0x02, 0x00, 0x01, 0x00, 0x03, 0x01, 0x00, 0x01, 0x83, 0x00, 0x01,
86
+ 0x01, 0x83, 0x00, 0x01, 0x01, 0x83, 0x00, 0x01, 0x01, 0x83, 0x00, 0x01, 0x01, 0x83, 0x00, 0x01, 0x01, 0x83, 0x00, 0x05, 0x01, 0x00, 0x01, 0x00,
87
+ 0x01, 0x86, 0x00, 0x03, 0x01, 0x00, 0x01, 0x00, 0x02, 0x01, 0x00, 0x85, 0x01, 0x03, 0x00, 0x01, 0x00, 0x85, 0x01, 0x01, 0x00, 0x85, 0x01, 0x01,
88
+ 0x00, 0x85, 0x01, 0x05, 0x00, 0x01, 0x00, 0x01, 0x00, 0x84, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x87, 0x00, 0x01, 0x01, 0x87,
89
+ 0x00, 0x01, 0x01, 0x89, 0x00, 0x01, 0x01, 0x83, 0x00, 0x01, 0x01, 0x84, 0x00, 0x01, 0x01, 0x83, 0x00, 0x01, 0x01, 0x00, 0x02, 0x01, 0x00, 0x89,
90
+ 0x01, 0x01, 0x00, 0x83, 0x01, 0x03, 0x00, 0x01, 0x00, 0x87, 0x01, 0x01, 0x00, 0x85, 0x01, 0x04, 0x00, 0x01, 0x01, 0x00, 0x83, 0x01, 0x02, 0x00,
91
+ 0x01, 0x00, 0x03, 0x01, 0x00, 0x01, 0x87, 0x00, 0x03, 0x01, 0x00, 0x01, 0x83, 0x00, 0x03, 0x01, 0x00, 0x01, 0x85, 0x00, 0x01, 0x01, 0x85, 0x00,
92
+ 0x04, 0x01, 0x00, 0x00, 0x01, 0x83, 0x00, 0x03, 0x01, 0x00, 0x01, 0x00, 0x04, 0x01, 0x00, 0x01, 0x00, 0x85, 0x01, 0x05, 0x00, 0x01, 0x00, 0x01,
93
+ 0x00, 0x83, 0x01, 0x03, 0x00, 0x01, 0x00, 0x83, 0x01, 0x01, 0x00, 0x85, 0x01, 0x04, 0x00, 0x01, 0x01, 0x00, 0x83, 0x01, 0x04, 0x00, 0x01, 0x00,
94
+ 0x01, 0x00, 0x01, 0x01, 0x83, 0x00, 0x01, 0x01, 0x83, 0x00, 0x01, 0x01, 0x83, 0x00, 0x03, 0x01, 0x00, 0x01, 0x83, 0x00, 0x01, 0x01, 0x83, 0x00,
95
+ 0x01, 0x01, 0x85, 0x00, 0x01, 0x01, 0x84, 0x00, 0x01, 0x01, 0x83, 0x00, 0x03, 0x01, 0x00, 0x01, 0x00, 0x83, 0x01, 0x05, 0x00, 0x01, 0x00, 0x01,
96
+ 0x00, 0x85, 0x01, 0x03, 0x00, 0x01, 0x00, 0x85, 0x01, 0x01, 0x00, 0x85, 0x01, 0x01, 0x00, 0x86, 0x01, 0x06, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
97
+ 0x00, 0x01, 0x01, 0x83, 0x00, 0x03, 0x01, 0x00, 0x01, 0x87, 0x00, 0x01, 0x01, 0x87, 0x00, 0x01, 0x01, 0x85, 0x00, 0x01, 0x01, 0x86, 0x00, 0x01,
98
+ 0x01, 0x83, 0x00, 0x01, 0x01, 0x00, 0x02, 0x01, 0x00, 0x83, 0x01, 0x01, 0x00, 0x89, 0x01, 0x01, 0x00, 0x87, 0x01, 0x01, 0x00, 0x83, 0x01, 0x03,
99
+ 0x00, 0x01, 0x00, 0x88, 0x01, 0x02, 0x00, 0x01, 0x00, 0x03, 0x01, 0x00, 0x01, 0x83, 0x00, 0x01, 0x01, 0x87, 0x00, 0x03, 0x01, 0x00, 0x01, 0x85,
100
+ 0x00, 0x03, 0x01, 0x00, 0x01, 0x83, 0x00, 0x03, 0x01, 0x00, 0x01, 0x86, 0x00, 0x03, 0x01, 0x00, 0x01, 0x00, 0x04, 0x01, 0x00, 0x01, 0x00, 0x83,
101
+ 0x01, 0x01, 0x00, 0x85, 0x01, 0x05, 0x00, 0x01, 0x00, 0x01, 0x00, 0x83, 0x01, 0x05, 0x00, 0x01, 0x00, 0x01, 0x00, 0x83, 0x01, 0x03, 0x00, 0x01,
102
+ 0x00, 0x84, 0x01, 0x04, 0x00, 0x01, 0x00, 0x01, 0x00, 0x03, 0x01, 0x00, 0x01, 0x85, 0x00, 0x01, 0x01, 0x83, 0x00, 0x01, 0x01, 0x83, 0x00, 0x01,
103
+ 0x01, 0x83, 0x00, 0x07, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x83, 0x00, 0x01, 0x01, 0x84, 0x00, 0x01, 0x01, 0x83, 0x00, 0x01, 0x01, 0x00,
104
+ 0x02, 0x01, 0x00, 0x87, 0x01, 0x03, 0x00, 0x01, 0x00, 0x87, 0x01, 0x09, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x86, 0x01, 0x01,
105
+ 0x00, 0x85, 0x01, 0x00, 0x01, 0x01, 0x89, 0x00, 0x01, 0x01, 0x89, 0x00, 0x01, 0x01, 0x83, 0x00, 0x03, 0x01, 0x00, 0x01, 0x88, 0x00, 0x01, 0x01,
106
+ 0x83, 0x00, 0x01, 0x01, 0x00, 0x02, 0x01, 0x00, 0x87, 0x01, 0x01, 0x00, 0x8b, 0x01, 0x01, 0x00, 0x83, 0x01, 0x01, 0x00, 0x8a, 0x01, 0x04, 0x00,
107
+ 0x01, 0x00, 0x01, 0x00, 0x03, 0x01, 0x00, 0x01, 0x85, 0x00, 0x01, 0x01, 0x8b, 0x00, 0x01, 0x01, 0x85, 0x00, 0x01, 0x01, 0x8a, 0x00, 0x03, 0x01,
108
+ 0x00, 0x01, 0x00, 0x04, 0x01, 0x00, 0x01, 0x00, 0x83, 0x01, 0x01, 0x00, 0x8b, 0x01, 0x01, 0x00, 0x87, 0x01, 0x01, 0x00, 0x8a, 0x01, 0x02, 0x00,
109
+ 0x01, 0x00, 0xa8, 0x01, 0x00,
110
+ };
111
+ // sparse: 880 bytes -> 82 bytes, ratio 10.73, checksum 0xaad9
112
+ const char rle_sparse[] = {
113
+ 0xa8, 0x00, 0x00, 0xa8, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x8a, 0x00, 0x01, 0x04, 0x9d, 0x00, 0x00, 0xa8, 0x00, 0x00, 0xa8, 0x00, 0x00, 0xa8, 0x00,
114
+ 0x00, 0x9b, 0x00, 0x01, 0x04, 0x8c, 0x00, 0x00, 0xa8, 0x00, 0x00, 0xa8, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x84, 0x00, 0x01, 0x04, 0xa3, 0x00, 0x00,
115
+ 0xa8, 0x00, 0x00, 0xa8, 0x00, 0x00, 0xa8, 0x00, 0x00, 0xa8, 0x00, 0x00, 0x92, 0x00, 0x01, 0x04, 0x95, 0x00, 0x00, 0xa8, 0x00, 0x00, 0xa8, 0x00,
116
+ 0x00, 0xa8, 0x00, 0x00, 0xa8, 0x00, 0x00, 0xa8, 0x07, 0x00,
117
+ };
118
+
119
+ // Host checksums, printed by rle_rooms.py from the source tile arrays.
120
+ #define EXPECT_PLATFORM 0xce8a
121
+ #define EXPECT_MAZE 0xf439
122
+ #define EXPECT_SPARSE 0xaad9
123
+
124
+ // One screen code per tile id, for drawing the platform room.
125
+ const char glyph[8] = { 0x20, 0xa0, 0x63, 0x66, 0x51, 0x5f, 0x5b, 0xe6 };
126
+
127
+ char room[ROOM_SIZE];
128
+
129
+ // --- the decoder -----------------------------------------------------
130
+ // Expands ROOM_H row streams into dst. Returns the decoded length.
131
+ unsigned rle_room(const char *src, char *dst)
132
+ {
133
+ unsigned n = 0;
134
+ for (char y = 0; y < ROOM_H; y++) {
135
+ for (;;) {
136
+ char c = *src++;
137
+ if (c == 0)
138
+ break;
139
+ if (c & 0x80) {
140
+ char v = *src++;
141
+ char k = c & 0x7f;
142
+ do { dst[n++] = v; } while (--k);
143
+ } else {
144
+ do { dst[n++] = *src++; } while (--c);
145
+ }
146
+ }
147
+ }
148
+ return n;
149
+ }
150
+
151
+ // --- the same decoder by hand ----------------------------------------
152
+ // Six zero-page bytes: source and destination pointers, a count and a
153
+ // row counter. Y indexes the destination within the row; the source is
154
+ // read through (zsrc,x) with X = 0 and the pointer stepped by hand.
155
+ __zeropage const char *zsrc;
156
+ __zeropage char *zdst;
157
+ __zeropage char zcnt;
158
+ __zeropage char zrows;
159
+
160
+ __noinline void rle_room_asm(void)
161
+ {
162
+ __asm volatile
163
+ {
164
+ lda #ROOM_H
165
+ sta zrows
166
+ nextrow:
167
+ ldy #0
168
+ ctl:
169
+ ldx #0
170
+ lda (zsrc,x)
171
+ inc zsrc
172
+ bne c1
173
+ inc zsrc + 1
174
+ c1: tax
175
+ beq rowend
176
+ bmi run
177
+ stx zcnt
178
+ lit:
179
+ ldx #0
180
+ lda (zsrc,x)
181
+ inc zsrc
182
+ bne l1
183
+ inc zsrc + 1
184
+ l1: sta (zdst),y
185
+ iny
186
+ dec zcnt
187
+ bne lit
188
+ beq ctl
189
+ run:
190
+ and #0x7f
191
+ sta zcnt
192
+ ldx #0
193
+ lda (zsrc,x)
194
+ inc zsrc
195
+ bne r1
196
+ inc zsrc + 1
197
+ r1: sta (zdst),y
198
+ iny
199
+ dec zcnt
200
+ bne r1
201
+ beq ctl
202
+ rowend:
203
+ tya
204
+ clc
205
+ adc zdst
206
+ sta zdst
207
+ bcc r2
208
+ inc zdst + 1
209
+ r2: dec zrows
210
+ bne nextrow
211
+ }
212
+ }
213
+
214
+ // --- CIA1 timer B harness --------------------------------------------
215
+ static inline void timer_start(void)
216
+ {
217
+ cia1.crb = 0x00;
218
+ cia1.tb = 0xffff;
219
+ cia1.crb = 0x11; // force load, start, count phi2
220
+ }
221
+
222
+ static inline unsigned timer_stop(void)
223
+ {
224
+ cia1.crb = 0x00;
225
+ return 0xffff - cia1.tb;
226
+ }
227
+
228
+ // --- checksum fold, the same as rle_rooms.py -------------------------
229
+ static inline unsigned fold(unsigned chk, unsigned v)
230
+ {
231
+ return (chk ^ v) * 5 + 1;
232
+ }
233
+
234
+ unsigned room_checksum(unsigned len)
235
+ {
236
+ unsigned chk = 0;
237
+ for (unsigned i = 0; i < len; i++)
238
+ chk = fold(chk, room[i]);
239
+ return fold(chk, len);
240
+ }
241
+
242
+ // --- text helpers (screen codes) -------------------------------------
243
+ void put_str(char *p, const char *s)
244
+ {
245
+ while (*s)
246
+ *p++ = *s++;
247
+ }
248
+
249
+ void put_dec(char *p, unsigned v, char digits)
250
+ {
251
+ for (char i = digits; i > 0; i--) {
252
+ p[i - 1] = 0x30 + v % 10;
253
+ v /= 10;
254
+ }
255
+ }
256
+
257
+ // One report line: NAME PACKED RATIO C-CYCLES ASM-CYCLES PASS/FAIL.
258
+ // Returns 1 when both decoders reproduce the host checksum.
259
+ char report(char row, const char *name, const char *src, unsigned packed,
260
+ unsigned expect)
261
+ {
262
+ char *p = Screen + row * 40;
263
+
264
+ __asm { sei }
265
+ timer_start();
266
+ unsigned overhead = timer_stop();
267
+
268
+ // The C decoder.
269
+ timer_start();
270
+ unsigned len = rle_room(src, room);
271
+ unsigned cycles_c = timer_stop() - overhead;
272
+ char ok = (len == ROOM_SIZE && room_checksum(len) == expect);
273
+
274
+ // The hand-written decoder, into a buffer first filled with 0xff so
275
+ // a short decode cannot pass on the C decoder's leftovers.
276
+ for (unsigned i = 0; i < ROOM_SIZE; i++)
277
+ room[i] = 0xff;
278
+ zsrc = src;
279
+ zdst = room;
280
+ timer_start();
281
+ rle_room_asm();
282
+ unsigned cycles_asm = timer_stop() - overhead;
283
+ __asm { cli }
284
+ ok &= (room_checksum(ROOM_SIZE) == expect);
285
+
286
+ // ratio x 100, in 32 bits because 88000 does not fit in 16.
287
+ unsigned r100 = (unsigned)(((unsigned long)ROOM_SIZE * 100 + packed / 2) / packed);
288
+
289
+ put_str(p, name);
290
+ put_dec(p + 5, packed, 4);
291
+ put_dec(p + 10, r100 / 100, 2);
292
+ p[12] = 0x2e;
293
+ put_dec(p + 13, r100 % 100, 2);
294
+ put_dec(p + 16, cycles_c, 5);
295
+ put_dec(p + 22, cycles_asm, 5);
296
+ put_str(p + 28, ok ? s"pass" : s"fail");
297
+ if (p[10] == 0x30)
298
+ p[10] = 0x20;
299
+ return ok;
300
+ }
301
+
302
+ void draw_room(void)
303
+ {
304
+ char *s = Screen + 3 * 40;
305
+ for (unsigned i = 0; i < ROOM_SIZE; i++)
306
+ s[i] = glyph[room[i]];
307
+ }
308
+
309
+ int main(void)
310
+ {
311
+ vic.color_border = 0;
312
+ vic.color_back = 0;
313
+ for (unsigned i = 0; i < 1000; i++) {
314
+ Screen[i] = 0x20;
315
+ Color[i] = 1;
316
+ }
317
+
318
+ // Blank the display so no badline lands in the timed regions; DEN
319
+ // is sampled on line $30, so wait two frames for it to take effect.
320
+ vic.ctrl1 = 0x0b;
321
+ vic_waitFrame();
322
+ vic_waitFrame();
323
+
324
+ char ok = 1;
325
+ ok &= report(1, s"maze", rle_maze, sizeof(rle_maze), EXPECT_MAZE);
326
+ ok &= report(2, s"spar", rle_sparse, sizeof(rle_sparse), EXPECT_SPARSE);
327
+ // The platform room is decoded last so it is the one left in RAM.
328
+ ok &= report(0, s"plat", rle_platform, sizeof(rle_platform), EXPECT_PLATFORM);
329
+ draw_room();
330
+
331
+ char code = ok ? CODE_PASS : CODE_FAIL;
332
+ RESULT = code;
333
+ vic.color_border = ok ? 5 : 2;
334
+ put_str(Screen + 34, s"r 0");
335
+ Screen[37] = 0x30 + code;
336
+
337
+ vic.ctrl1 = 0x1b;
338
+
339
+ for (;;)
340
+ ;
341
+ return 0;
342
+ }
343
+ ```
344
+
345
+ The three `rle_*` arrays and the three `EXPECT_*` values are the output of
346
+ this host script. Each room is drawn as 22 strings of 40 characters and
347
+ turned into tile ids by the `TILES` table, so the source array is the
348
+ picture. The encoder emits a run for three or more equal tiles, a literal
349
+ group otherwise, and a zero after every row; runs never cross a row. The
350
+ script decodes its own output and asserts it matches before printing.
351
+
352
+ ```text
353
+ # rle_rooms.py -- author three 40x22 rooms, RLE-encode them, print C arrays.
354
+ # Format (same as tile-map-render.md): control byte c
355
+ # c & 0x80 : run, next byte repeated (c & 0x7f) times (1..127)
356
+ # c < 0x80 : c literal bytes follow (1..127)
357
+ # 0x00 : end of row
358
+ # Each of the 22 rows is its own stream; a run never crosses a row.
359
+
360
+ TILES = {'.': 0, '#': 1, '=': 2, 'X': 3, 'o': 4, 'L': 5, 'D': 6, 'W': 7}
361
+
362
+ PLATFORM = [
363
+ "########################################",
364
+ "#......................................#",
365
+ "#..oo..................................#",
366
+ "#.======.............................D.#",
367
+ "#..........................========..LL#",
368
+ "#....................................LL#",
369
+ "#............=====...................LL#",
370
+ "#..............................LLLLLLLL#",
371
+ "#.....XXXXXXXX.........................#",
372
+ "#......................................#",
373
+ "#..LL.............=======..............#",
374
+ "#..LL..................................#",
375
+ "#..LL......oo..........................#",
376
+ "#=========================.............#",
377
+ "#......................................#",
378
+ "#......................................#",
379
+ "#.............................=========#",
380
+ "#..........======......................#",
381
+ "#......................................#",
382
+ "#.oo..................XXXXXXXXXXXX.....#",
383
+ "#=================....##################",
384
+ "########################################",
385
+ ]
386
+
387
+ MAZE = [
388
+ "########################################",
389
+ "#...#.......#.....#.....#...#..........#",
390
+ "#.#.#.#####.#.###.#.###.#.#.#.########.#",
391
+ "#.#...#...#...#...#...#...#.#.#......#.#",
392
+ "#.#####.#.#####.#####.#####.#.#.####.#.#",
393
+ "#.......#.......#.........#...#....#...#",
394
+ "#.#########.###.#.#######.#####.##.###.#",
395
+ "#.#.......#.#...#.#.....#.....#..#...#.#",
396
+ "#.#.#####.#.#.###.#.###.#####.##.###.#.#",
397
+ "#...#...#...#.#...#...#.....#....#...#.#",
398
+ "###.#.#.#####.#.#####.#####.######.#.#.#",
399
+ "#...#.#.......#.......#.....#......#...#",
400
+ "#.###.#########.#######.###.#.########.#",
401
+ "#.#...#.......#.#.....#.#...#.#......#.#",
402
+ "#.#.###.#####.#.#.###.#.#.###.#.####.#.#",
403
+ "#.#.....#...#...#...#.#.#.#...#....#...#",
404
+ "#.#######.#.#######.#.#.#.#.######.#####",
405
+ "#.........#.........#...#.#........#...#",
406
+ "#.#######.###########.###.##########.#.#",
407
+ "#.#.....#...........#.....#..........#.#",
408
+ "#.#.###.###########.#######.##########.#",
409
+ "########################################",
410
+ ]
411
+
412
+ SPARSE = [
413
+ "........................................",
414
+ "........................................",
415
+ "........................................",
416
+ "..........o.............................",
417
+ "........................................",
418
+ "........................................",
419
+ "........................................",
420
+ "...........................o............",
421
+ "........................................",
422
+ "........................................",
423
+ "........................................",
424
+ "....o...................................",
425
+ "........................................",
426
+ "........................................",
427
+ "........................................",
428
+ "........................................",
429
+ "..................o.....................",
430
+ "........................................",
431
+ "........................................",
432
+ "........................................",
433
+ "........................................",
434
+ "WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW",
435
+ ]
436
+
437
+ def tiles(room):
438
+ assert len(room) == 22 and all(len(r) == 40 for r in room)
439
+ return [[TILES[ch] for ch in r] for r in room]
440
+
441
+ def encode_row(row):
442
+ out, lit, i = [], [], 0
443
+ def flush():
444
+ if lit:
445
+ out.append(len(lit)); out.extend(lit); lit.clear()
446
+ while i < len(row):
447
+ j = i
448
+ while j < len(row) and row[j] == row[i] and j - i < 127:
449
+ j += 1
450
+ if j - i >= 3:
451
+ flush(); out.append(0x80 | (j - i)); out.append(row[i]); i = j
452
+ else:
453
+ lit.append(row[i]); i += 1
454
+ if len(lit) == 127: flush()
455
+ flush(); out.append(0)
456
+ return out
457
+
458
+ def decode(stream):
459
+ out, i, rows = [], 0, 0
460
+ while rows < 22:
461
+ c = stream[i]; i += 1
462
+ if c == 0: rows += 1
463
+ elif c & 0x80: out.extend([stream[i]] * (c & 0x7f)); i += 1
464
+ else: out.extend(stream[i:i + c]); i += c
465
+ return out, i
466
+
467
+ def fold(chk, v):
468
+ return ((chk ^ v) * 5 + 1) & 0xffff
469
+
470
+ def checksum(data):
471
+ chk = 0
472
+ for v in data: chk = fold(chk, v)
473
+ return fold(chk, len(data))
474
+
475
+ for name, room in (("platform", PLATFORM), ("maze", MAZE), ("sparse", SPARSE)):
476
+ grid = tiles(room)
477
+ flat = [t for r in grid for t in r]
478
+ stream = [b for r in grid for b in encode_row(r)]
479
+ back, used = decode(stream)
480
+ assert back == flat and used == len(stream)
481
+ print("// %s: %d bytes -> %d bytes, ratio %.2f, checksum 0x%04x"
482
+ % (name, len(flat), len(stream), len(flat) / len(stream), checksum(flat)))
483
+ print("const char rle_%s[] = {" % name)
484
+ for k in range(0, len(stream), 24):
485
+ print(" " + ", ".join("0x%02x" % b for b in stream[k:k + 24]) + ",")
486
+ print("};")
487
+ ```
488
+
489
+ ## Build
490
+
491
+ ```bash
492
+ python3 rle_rooms.py # prints the rle_* arrays and the checksums
493
+ oscar64 -tm=c64 -O2 -o=level-rle-decoder.prg level-rle-decoder.c
494
+ ```
495
+
496
+ Produces `level-rle-decoder.prg`, 3,030 bytes (Oscar64 build 2026-05-19),
497
+ plus `level-rle-decoder.map`, `.asm` and `.lbl`. Then run headless in
498
+ VICE (PAL):
499
+
500
+ ```bash
501
+ GSETTINGS_SCHEMA_DIR=/opt/homebrew/share/glib-2.0/schemas x64sc -default -warp +sound \
502
+ +autostart-delay-random -autostartprgmode 1 -limitcycles 6000000 \
503
+ -exitscreenshot level-rle-decoder.png -autostart level-rle-decoder.prg
504
+ ```
505
+
506
+ Add `-model ntsc` for the NTSC picture.
507
+
508
+ ## Expected output
509
+
510
+ Green border, black background, white text. Rows 0 to 2 read:
511
+
512
+ ```text
513
+ PLAT 0213 4.13 33562 19158 PASS R 01
514
+ MAZE 0629 1.40 50447 27673 PASS
515
+ SPAR 0082 10.73 28193 16470 PASS
516
+ ```
517
+
518
+ The columns are: room, packed bytes, ratio (880 bytes over packed bytes,
519
+ rounded to two places), cycles for the C decoder, cycles for the
520
+ hand-written decoder, and PASS when both decoders reproduce the host
521
+ checksum. `R 01` is the verdict code, `01` for pass and `02` for fail;
522
+ the same byte is at `$02FF` and the border is green (5) or red (2).
523
+ Rows 3 to 24 are the platform room: a solid frame, eight platform runs
524
+ drawn as bars, ladder tiles in two columns and one horizontal run, two
525
+ rows of spikes, a door at the upper right and three pairs of coins.
526
+
527
+ The same text and the same cycle counts appear on PAL and NTSC (measured
528
+ in VICE x64sc 3.10, both models; the timed regions run with interrupts
529
+ masked and the display blanked, so only CPU cycles are counted).
530
+
531
+ Screenshots at 6,000,000 cycles: `screenshots/level-rle-decoder.png` (PAL)
532
+ and `screenshots/level-rle-decoder-ntsc.png` (NTSC).
533
+
534
+ The figures, all read off the picture or the `.map` file:
535
+
536
+ | Room | Source bytes | Packed bytes | Ratio | C decoder cycles | Hand-written cycles |
537
+ |---|---|---|---|---|---|
538
+ | Platform | 880 | 213 | 4.13 : 1 | 33,562 (38.1 per byte) | 19,158 (21.8 per byte) |
539
+ | Maze | 880 | 629 | 1.40 : 1 | 50,447 (57.3 per byte) | 27,673 (31.4 per byte) |
540
+ | Sparse | 880 | 82 | 10.73 : 1 | 28,193 (32.0 per byte) | 16,470 (18.7 per byte) |
541
+
542
+ | Decoder | Bytes of code | Source |
543
+ |---|---|---|
544
+ | `rle_room` (C, `-O2`) | 149 | `.map`, `objects by size`: `rle_room, NATIVE_CODE:code (0095)` |
545
+ | `rle_room_asm` (hand-written) | 80 | `.map`: `rle_room_asm, NATIVE_CODE:code (0050)`, including the `rts` |
546
+
547
+ The hand-written decoder also uses six zero-page bytes (`$F7` to `$FC`
548
+ in the `.map`). Both cycle figures are net of the harness's own
549
+ start/stop cost, which the program measures once with an empty timed
550
+ region and subtracts. The per-byte figures are arithmetic from the
551
+ cycle counts.
552
+
553
+ ## Why this works
554
+
555
+ The stream format is the one `tile-map-render.md` established, so a
556
+ level built for that recipe decodes here unchanged. The C decoder is that
557
+ recipe's `rle_row` with the row loop folded in: it returns the total
558
+ decoded length, and the caller checks that it is 880 before it trusts the
559
+ checksum. The hand-written decoder does the same work with Y as the
560
+ destination index within a row and the source read through `(zsrc,x)`
561
+ with X held at zero, which is the 6502's only way to read through a
562
+ pointer without spending Y. After each row `tya` adds the row's length
563
+ to the destination pointer, so a row that decodes short or long shifts
564
+ every later row and the checksum catches it. The two `beq ctl` branches
565
+ after `bne` are unconditional in effect: `dec zcnt` has just left Z set.
566
+
567
+ The three rooms are chosen to span the range a game meets. The platform
568
+ room is long runs of floor and air broken by short features and packs
569
+ 4.13 : 1. The maze is a wall every other cell, which defeats a
570
+ three-byte run threshold on most rows, and packs 1.40 : 1; a tile-pair
571
+ dictionary would do better on it (not measured here). The sparse room is nearly empty and packs 10.73 : 1. The
572
+ ratio a game sees depends on its rooms, and a design document that quotes
573
+ one figure should say which room it came from.
574
+
575
+ The cycle counts depend on the mix of runs and literals, not only on the
576
+ output size: the maze costs the most because every control byte does
577
+ little work. The hand-written decoder is a little under twice as fast as
578
+ the C one at `-O2` and about half its size. A 20 to 30 byte decoder is
579
+ possible only by dropping the row structure and the 16-bit pointer
580
+ arithmetic, and neither of the decoders here is one; the smallest
581
+ decoder for this exact format is not measured here.
582
+
583
+ The timing harness is the CIA1 timer B pattern of `tile-map-render.md`:
584
+ the timer is stopped before it is read so the two-byte read cannot
585
+ straddle a decrement, interrupts are masked around the timed region, and
586
+ the display is blanked two frames earlier because DEN is sampled once
587
+ per frame on line `$30`. The checksum fold `(chk ^ v) * 5 + 1` in 16
588
+ bits is order-sensitive, so a decoder that produced the right bytes in
589
+ the wrong order would fail. The hand-written decoder writes into a buffer
590
+ filled with `0xff` first, so it cannot pass on the C decoder's output.
591
+
592
+ ## Verification
593
+
594
+ Three instruments, run against the committed PNGs (VICE x64sc 3.10,
595
+ Oscar64 build 2026-05-19).
596
+
597
+ **Text, room and border.** A script matched every cell of rows 0 to 2
598
+ against the glyphs of `chargen-901225-01.bin` and read the border pixel
599
+ at (2, 100). Both pictures give the three lines quoted above and the
600
+ border RGB VICE emits for colour 5 on each model, (98, 213, 50) on PAL
601
+ and (114, 189, 103) on NTSC. The same script then took the platform
602
+ room's 22 strings from `rle_rooms.py`, mapped each character through
603
+ `TILES` and `glyph`, and compared the 8 x 8 ink pattern of each of the
604
+ 880 cells on rows 3 to 24 with the char ROM glyph: 880 compared, 0
605
+ differing, on both pictures. The `.map` of the same build gives
606
+ `rle_room` 149 bytes and `rle_room_asm` 80 bytes.
607
+
608
+ **Checksums.** The host script computed `0xCE8A`, `0xF439` and `0xAAD9`
609
+ from the source arrays; the machine folds 880 decoded bytes and the
610
+ length the same way and prints PASS three times for each decoder, on
611
+ both models. This is rung 1 for these three streams and says nothing
612
+ about streams these rooms do not exercise (no row here has a run of more
613
+ than 40, and a run count of zero is undefined by the format).
614
+
615
+ **Reproducibility.** The pinned command was run twice per model and the
616
+ PNG bytes were identical each time.
617
+
618
+ The first build printed the maze ratio as `1.39` where the host said
619
+ `1.40`: the machine truncated where Python rounded. The ratio now adds
620
+ half the divisor before dividing, and the two agree on all three rooms.