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,1071 @@
1
+ ---
2
+ recipe: sprite-cache-flip
3
+ toolchain: kickassembler
4
+ output_format: PRG
5
+ region: both
6
+ techniques: [sprite_cache_flip]
7
+ file_formats: [PRG]
8
+ uses_registers: [D000, D001, D002, D003, D004, D005, D006, D007, D008, D009, D00A, D00B, D00C, D00D, D00E, D00F, D010, D011, D015, D017, D01C, D01D, D020, D025, D026, D027, D028, D029, D02A, D02B, D02C, D02D, D02E, DD04, DD05, DD06, DD07, DD0E, DD0F]
9
+ uses_kernal: [CHROUT]
10
+ ---
11
+
12
+ <!-- doc-type: recipe -->
13
+
14
+ # KickAssembler — Sprite Cache with Frames Mirrored at Run Time
15
+
16
+ ## Synopsis
17
+
18
+ Stores five sprite frames facing right only, packed as a row mask plus
19
+ the non-empty rows, and depacks them on demand into an 8-slot sprite
20
+ cache in the VIC bank, mirrored when a request asks for the left-facing
21
+ version. Both mirror tables, bit-reversed for hires and pair-reversed
22
+ for multicolour, are built on the machine at start. The program checks
23
+ the tables against tables the assembler computed, checks every mirrored
24
+ frame against a frame the assembler mirrored by reversing its pixel
25
+ strings, checks that mirroring twice gives the frame back, counts cache
26
+ misses, hits and evictions, and times each step with the CIA2 timers.
27
+ Eight sprites show two hires and two multicolour frames, each beside its
28
+ mirror. This is the `sprite_cache_flip` technique; use it when a game's
29
+ frames facing both ways do not fit the VIC bank.
30
+
31
+ Verified in VICE x64sc 3.10: the text on screen is identical on PAL and
32
+ NTSC, and on both pictures every left-facing sprite is the exact pixel
33
+ mirror of its neighbour and matches the frame definitions in the
34
+ listing, pixel for pixel.
35
+
36
+ ## Source
37
+
38
+ ```asm
39
+ // sprite-cache-flip.asm
40
+ // Sprite frames are stored facing right only and packed: a 21-bit mask of
41
+ // the rows that are not empty, then 3 bytes per non-empty row. A cache of
42
+ // 8 sprite blocks at $2000 (pointers $80-$87) is filled on demand by
43
+ // depacking a frame, mirrored or not, into the next slot round-robin.
44
+ // Mirroring uses a 256-byte table built at start: bit order reversed for
45
+ // a hires frame (HFLIP), bit PAIRS reversed for a multicolour frame
46
+ // (MFLIP), and bytes 0 and 2 of each row swapped.
47
+ // Checks, all printed on screen:
48
+ // TABLES BAD entries of HFLIP and MFLIP that differ from tables the
49
+ // assembler computed another way (bit arithmetic on i)
50
+ // MIRROR BAD bytes of each depacked left-facing frame that differ from
51
+ // the frame the assembler mirrored by reversing its strings
52
+ // ROUND BAD bytes where flip(flip(frame)) differs from the frame
53
+ // MISS/HIT/EVICT counters of the cache over a fixed request sequence
54
+ // Cycles (CIA2 timers, screen blanked, IRQs off) for table generation, a
55
+ // flip of one 63-byte sprite, a cache fill and a cache hit.
56
+ // Verdict: $02FF = $01, green border and PASS when every check holds;
57
+ // $02FF = $02, red border and FAIL otherwise.
58
+ // The eight sprites show keys 0-7 of the cache: frame 0 right, frame 0
59
+ // left, frame 1 right, ... frame 3 left. Frames 0-1 hires, 2-3 multicolour.
60
+
61
+ BasicUpstart2(start)
62
+
63
+ .const CHROUT = $ffd2
64
+ .const RESULT = $02ff
65
+ .const BORDER = $d020
66
+ .const SCREEN = $0400
67
+
68
+ .const CACHE = $2000 // 8 slots of 64 bytes, VIC bank 0
69
+ .const CACHE_PTR = CACHE / 64 // sprite pointer of slot 0 ($80)
70
+ .const SLOTS = 8
71
+ .const HFLIP = $3000 // built at start, page-aligned
72
+ .const MFLIP = $3100
73
+ .const HREF = $3200 // computed by the assembler
74
+ .const MREF = $3300
75
+ .const BUF_A = $3600 // depacked right-facing frame
76
+ .const BUF_B = $3640 // depacked left-facing frame
77
+ .const BUF_C = $3680 // BUF_B flipped again
78
+ .const FRAMES = 5
79
+ .const KEYS = FRAMES * 2 // key = frame * 2 + facing (1 = left)
80
+
81
+ .const sp = $fb // flip63 source pointer
82
+ .const dp = $fd // destination pointer (flip63, depack)
83
+ .const pk = $02 // packed frame pointer
84
+ .const ptr = $04 // puts pointer
85
+ .const cp = $06 // compare pointer
86
+ .const m0 = $08 // row mask, 3 bytes
87
+ .const tmp = $0b
88
+ .const res = $0c
89
+ .const so = $0d // offset into the packed rows
90
+ .const yr = $0e
91
+ .const b0 = $0f // one packed row, 3 bytes
92
+ .const face = $12
93
+ .const key = $13
94
+
95
+ // ---------------------------------------------------------------------------
96
+ // Frame definitions, assembled into packed data and a mirrored reference.
97
+ // Hires rows are 24 characters, '#' set; multicolour rows 12 characters,
98
+ // '.' or a colour 1-3 per double-wide pixel.
99
+ // ---------------------------------------------------------------------------
100
+ .function rowval(s) {
101
+ .var v = 0
102
+ .if (s.size() == 24) {
103
+ .for (var i = 0; i < 24; i++) {
104
+ .eval v = v * 2
105
+ .if (s.charAt(i) == '#') .eval v = v + 1
106
+ }
107
+ } else {
108
+ .for (var i = 0; i < 12; i++) {
109
+ .eval v = v * 4
110
+ .if (s.charAt(i) != '.') .eval v = v + (s.charAt(i) - '0')
111
+ }
112
+ }
113
+ .return v
114
+ }
115
+ .function mirror(s) { // reverse the characters: a mirrored row
116
+ .var r = ""
117
+ .for (var i = s.size() - 1; i >= 0; i--) .eval r = r + s.charAt(i)
118
+ .return r
119
+ }
120
+ .macro Packed(rows) { // 3 mask bytes, then the non-empty rows
121
+ .var mask = 0
122
+ .for (var r = 0; r < 21; r++) {
123
+ .if (rowval(rows.get(r)) != 0) .eval mask = mask | (1 << r)
124
+ }
125
+ .byte mask & $ff, (mask >> 8) & $ff, mask >> 16
126
+ .for (var r = 0; r < 21; r++) {
127
+ .var v = rowval(rows.get(r))
128
+ .if (v != 0) .byte v >> 16, (v >> 8) & $ff, v & $ff
129
+ }
130
+ }
131
+ .macro Mirrored(rows) { // 63 bytes, the frame facing left
132
+ .for (var r = 0; r < 21; r++) {
133
+ .var v = rowval(mirror(rows.get(r)))
134
+ .byte v >> 16, (v >> 8) & $ff, v & $ff
135
+ }
136
+ }
137
+ .function rev8(x) { // bit i goes to bit 7 - i
138
+ .var v = 0
139
+ .for (var i = 0; i < 8; i++) .eval v = v * 2 + ((x >> i) & 1)
140
+ .return v
141
+ }
142
+ .function revpairs(x) { // pair i goes to pair 3 - i
143
+ .var v = 0
144
+ .for (var i = 0; i < 4; i++) .eval v = v * 4 + ((x >> (2 * i)) & 3)
145
+ .return v
146
+ }
147
+
148
+ .var E = "........................"
149
+ .var e = "............"
150
+ .var f0 = List().add(E, E, E, E, // hires arrow pointing right
151
+ "..............#.........",
152
+ "..............##........",
153
+ "..............###.......",
154
+ "..............####......",
155
+ "###############.###.....",
156
+ "###############.####....",
157
+ "####################....",
158
+ "#####################...",
159
+ "######################..",
160
+ "#####################...",
161
+ "####################....",
162
+ ".............######.....",
163
+ ".............#####......",
164
+ ".............####.......",
165
+ ".............###........",
166
+ E, E)
167
+ .var f1 = List() // hires staircase with a dotted edge
168
+ .for (var r = 0; r < 21; r++) {
169
+ .var s = ""
170
+ .for (var c = 0; c < 24; c++) {
171
+ .if (c <= r || (c == 23 && (r & 1) == 0)) .eval s = s + "#"
172
+ else .eval s = s + "."
173
+ }
174
+ .eval f1.add(s)
175
+ }
176
+ .var f2 = List().add(e, e, e, // multicolour fish facing right
177
+ "......111...",
178
+ "....1111111.",
179
+ "3..111111211",
180
+ "33111111111.",
181
+ "331122222111",
182
+ "33112222221.",
183
+ "3311111111..",
184
+ "3..1111111..",
185
+ "....11111...",
186
+ "......1.....",
187
+ e, e, e, e, e, e, e, e)
188
+ .var f3 = List() // multicolour ramp: colour by column
189
+ .for (var r = 0; r < 21; r++) {
190
+ .var s = ""
191
+ .for (var c = 0; c < 12; c++) {
192
+ .if (c * 2 <= r) .eval s = s + toIntString(1 + mod(c, 3))
193
+ else .eval s = s + "."
194
+ }
195
+ .eval f3.add(s)
196
+ }
197
+ .var f4 = List() // hires flag, used only to be evicted
198
+ .for (var r = 0; r < 21; r++) {
199
+ .if (r < 8) .eval f4.add("##########..............")
200
+ else .eval f4.add("#.......................")
201
+ }
202
+
203
+ start:
204
+ sei
205
+ lda #0
206
+ sta $dd0e // stop both CIA2 timers, latches $FFFF
207
+ sta $dd0f
208
+ lda #$ff
209
+ sta $dd04
210
+ sta $dd05
211
+ sta $dd06
212
+ sta $dd07
213
+ lda $d011 // blank the screen: no badlines while timing
214
+ and #$ef
215
+ sta $d011
216
+ !: lda $d011 // DEN is sampled on line $30: wait a frame
217
+ bpl !-
218
+ !: lda $d011
219
+ bmi !-
220
+
221
+ ldx #KEYS - 1 // empty cache
222
+ lda #$ff
223
+ !: sta slot_of,x
224
+ dex
225
+ bpl !-
226
+ ldx #SLOTS - 1
227
+ !: sta key_of,x
228
+ dex
229
+ bpl !-
230
+
231
+ Time(nothing, t_empty)
232
+ Time(gen_h, t_genh)
233
+ Time(gen_m, t_genm)
234
+
235
+ // one 63-byte flip each way, from the depacked frame 0 into BUF_C
236
+ lda #0
237
+ sta face
238
+ lda #0
239
+ jsr setframe
240
+ Set16(dp, BUF_A)
241
+ jsr depack
242
+ Set16(sp, BUF_A)
243
+ Set16(dp, BUF_C)
244
+ lda #>HFLIP
245
+ jsr settbl
246
+ Time(flip63, t_fliph)
247
+ lda #>MFLIP
248
+ jsr settbl
249
+ Time(flip63, t_flipm)
250
+
251
+ // the request sequence: 9 misses (the last evicts frame 4), 8 hits
252
+ Req(8, t_scratch) // frame 4 right, into slot 0
253
+ Req(0, t_fill0r)
254
+ Req(2, t_fill1r)
255
+ Req(4, t_scratch)
256
+ Req(6, t_scratch)
257
+ Req(1, t_fill0l)
258
+ Req(3, t_fill1l)
259
+ Req(5, t_scratch)
260
+ Req(7, t_scratch) // slot 0 again: frame 4 is evicted
261
+ Req(0, t_scratch)
262
+ Req(1, t_hit)
263
+ Req(2, t_scratch)
264
+ Req(3, t_scratch)
265
+ Req(4, t_scratch)
266
+ Req(5, t_scratch)
267
+ Req(6, t_scratch)
268
+ Req(7, t_scratch)
269
+
270
+ Net(t_genh)
271
+ Net(t_genm)
272
+ Net(t_fliph)
273
+ Net(t_flipm)
274
+ Net(t_fill0r)
275
+ Net(t_fill0l)
276
+ Net(t_fill1l)
277
+ Net(t_fill1r)
278
+ Net(t_hit)
279
+
280
+ // the flip tables against the assembler's tables
281
+ ldx #0
282
+ !: lda HFLIP,x
283
+ cmp HREF,x
284
+ beq ok_h
285
+ inc bad_tab
286
+ ok_h:
287
+ lda MFLIP,x
288
+ cmp MREF,x
289
+ beq ok_m
290
+ inc bad_tab
291
+ ok_m:
292
+ inx
293
+ bne !-
294
+
295
+ // every frame: left against the assembler's mirror, flip(flip) = frame
296
+ lda #0
297
+ sta frame
298
+ chk:
299
+ lda frame
300
+ jsr setframe
301
+ lda #0
302
+ sta face
303
+ Set16(dp, BUF_A)
304
+ jsr depack
305
+ lda #1
306
+ sta face
307
+ Set16(dp, BUF_B)
308
+ jsr depack
309
+ ldx frame
310
+ lda mir_lo,x
311
+ sta cp
312
+ lda mir_hi,x
313
+ sta cp+1
314
+ Set16(sp, BUF_B)
315
+ jsr compare // BUF_B against the mirrored reference
316
+ clc
317
+ adc bad_mir
318
+ sta bad_mir
319
+ Set16(dp, BUF_C)
320
+ jsr flip63 // BUF_C = flip(BUF_B)
321
+ Set16(cp, BUF_A)
322
+ Set16(sp, BUF_C)
323
+ jsr compare
324
+ clc
325
+ adc bad_round
326
+ sta bad_round
327
+ inc frame
328
+ lda frame
329
+ cmp #FRAMES
330
+ bne chk
331
+
332
+ lda $d011 // screen back on
333
+ ora #$10
334
+ sta $d011
335
+ cli
336
+
337
+ lda bad_tab // verdict
338
+ ora bad_mir
339
+ ora bad_round
340
+ bne fail
341
+ lda misses
342
+ cmp #9
343
+ bne fail
344
+ lda hits
345
+ cmp #8
346
+ bne fail
347
+ lda evicts
348
+ cmp #1
349
+ bne fail
350
+ lda slot_of + 8 // frame 4 must no longer be cached
351
+ bpl fail
352
+ lda #$01
353
+ ldy #5 // green
354
+ bne verdict
355
+ fail:
356
+ lda #$02
357
+ ldy #2 // red
358
+ verdict:
359
+ sta RESULT
360
+ sty BORDER
361
+
362
+ lda #$93
363
+ jsr CHROUT
364
+ Line2(t_genh_txt, t_genh, t_genm_txt, t_genm)
365
+ Line2(t_flip_txt, t_fliph, t_flipm_txt, t_flipm)
366
+ Line2(t_fill_txt, t_fill0r, t_fill0l_txt, t_fill0l)
367
+ Line2(t_fill1_txt, t_fill1r, t_fill1l_txt, t_fill1l)
368
+ Line2(t_hit_txt, t_hit, t_miss_txt, misses)
369
+ Line2(t_hits_txt, hits, t_evict_txt, evicts)
370
+ Line2(t_tab_txt, bad_tab, t_mir_txt, bad_mir)
371
+ Line1(t_round_txt, bad_round)
372
+ ldx #<t_res_txt
373
+ ldy #>t_res_txt
374
+ jsr puts
375
+ lda RESULT
376
+ jsr hexbyte
377
+ ldx #<t_pass_txt
378
+ ldy #>t_pass_txt
379
+ lda RESULT
380
+ cmp #$01
381
+ beq !+
382
+ ldx #<t_fail_txt
383
+ ldy #>t_fail_txt
384
+ !: jsr puts
385
+
386
+ // sprite n shows cache key n
387
+ ldx #7
388
+ spr:
389
+ lda slot_of,x
390
+ clc
391
+ adc #CACHE_PTR
392
+ sta SCREEN + $3f8,x
393
+ lda xpos,x
394
+ ldy pairs,x
395
+ sta $d000,y
396
+ lda #170
397
+ sta $d001,y
398
+ lda #1 // white; the multicolour ones use it too
399
+ sta $d027,x
400
+ dex
401
+ bpl spr
402
+ lda #0
403
+ sta $d010
404
+ sta $d017
405
+ sta $d01d
406
+ lda #%11110000 // sprites 4-7 are frames 2 and 3
407
+ sta $d01c
408
+ lda #10 // %01 light red
409
+ sta $d025
410
+ lda #7 // %11 yellow; %10 is the sprite colour
411
+ sta $d026
412
+ lda #$ff
413
+ sta $d015
414
+ jmp *
415
+
416
+ nothing:
417
+ rts
418
+
419
+ // ---------------------------------------------------------------------------
420
+ // gen_h: HFLIP[x] = x with its 8 bits in reverse order
421
+ // ---------------------------------------------------------------------------
422
+ gen_h:
423
+ ldx #0
424
+ gh:
425
+ stx tmp
426
+ ldy #8
427
+ !: lsr tmp // bit 0 out first ...
428
+ rol // ... ends at bit 7 after 8 rotates
429
+ dey
430
+ bne !-
431
+ sta HFLIP,x
432
+ inx
433
+ bne gh
434
+ rts
435
+
436
+ // ---------------------------------------------------------------------------
437
+ // gen_m: MFLIP[x] = x with its 4 bit pairs in reverse order; each pair
438
+ // keeps its own bit order, so a pixel keeps its colour
439
+ // ---------------------------------------------------------------------------
440
+ gen_m:
441
+ ldx #0
442
+ gm:
443
+ stx tmp
444
+ lda #0
445
+ ldy #4
446
+ !: asl
447
+ asl
448
+ sta res
449
+ lda tmp
450
+ and #%00000011 // lowest pair of what is left
451
+ ora res
452
+ lsr tmp
453
+ lsr tmp
454
+ dey
455
+ bne !-
456
+ sta MFLIP,x
457
+ inx
458
+ bne gm
459
+ rts
460
+
461
+ // ---------------------------------------------------------------------------
462
+ // settbl: A = high byte of the flip table used by flip63 and depack
463
+ // ---------------------------------------------------------------------------
464
+ settbl:
465
+ sta fa + 2
466
+ sta fb + 2
467
+ sta fc + 2
468
+ sta da + 2
469
+ sta db + 2
470
+ sta dc + 2
471
+ rts
472
+
473
+ // ---------------------------------------------------------------------------
474
+ // flip63: (dp) = mirror of the 63 bytes at (sp). Row r: dst[r] = T[src[r+2]],
475
+ // dst[r+1] = T[src[r+1]], dst[r+2] = T[src[r]]. Source and destination
476
+ // must not overlap: dst[r] is written before src[r] is read.
477
+ // ---------------------------------------------------------------------------
478
+ .align $100 // flip63 and depack in one page: no
479
+ // branch crosses a page, so the cycle
480
+ // counts do not move when code grows
481
+ flip63:
482
+ ldy #0
483
+ frow:
484
+ sty yr
485
+ iny
486
+ iny
487
+ lda (sp),y
488
+ tax
489
+ fa: lda HFLIP,x
490
+ ldy yr
491
+ sta (dp),y
492
+ iny
493
+ lda (sp),y
494
+ tax
495
+ fb: lda HFLIP,x
496
+ sta (dp),y
497
+ dey
498
+ lda (sp),y
499
+ tax
500
+ fc: lda HFLIP,x
501
+ iny
502
+ iny
503
+ sta (dp),y
504
+ iny
505
+ cpy #63
506
+ bne frow
507
+ rts
508
+
509
+ // ---------------------------------------------------------------------------
510
+ // setframe: A = frame; points pk at its packed data, selects its table
511
+ // ---------------------------------------------------------------------------
512
+ setframe:
513
+ tax
514
+ lda pk_lo,x
515
+ sta pk
516
+ lda pk_hi,x
517
+ sta pk+1
518
+ lda is_mc,x
519
+ beq !+
520
+ lda #>MFLIP
521
+ jmp settbl
522
+ !: lda #>HFLIP
523
+ jmp settbl
524
+
525
+ // ---------------------------------------------------------------------------
526
+ // depack: 63 bytes at (dp) from the packed frame at (pk), mirrored when
527
+ // face = 1. An empty row costs 3 stores; a present row 3 reads, 3 stores,
528
+ // and 3 table lookups when mirrored.
529
+ // ---------------------------------------------------------------------------
530
+ depack:
531
+ ldy #0
532
+ lda (pk),y
533
+ sta m0
534
+ iny
535
+ lda (pk),y
536
+ sta m0+1
537
+ iny
538
+ lda (pk),y
539
+ sta m0+2
540
+ iny
541
+ sty so // rows start after the mask
542
+ ldy #0
543
+ drow:
544
+ lsr m0+2 // next row's bit into carry
545
+ ror m0+1
546
+ ror m0
547
+ bcc dempty
548
+ sty yr
549
+ ldy so
550
+ lda (pk),y
551
+ sta b0
552
+ iny
553
+ lda (pk),y
554
+ sta b0+1
555
+ iny
556
+ lda (pk),y
557
+ sta b0+2
558
+ iny
559
+ sty so
560
+ ldy yr
561
+ lda face
562
+ beq dcopy
563
+ ldx b0+2
564
+ da: lda HFLIP,x
565
+ sta (dp),y
566
+ iny
567
+ ldx b0+1
568
+ db: lda HFLIP,x
569
+ sta (dp),y
570
+ iny
571
+ ldx b0
572
+ dc: lda HFLIP,x
573
+ sta (dp),y
574
+ iny
575
+ bne dnext // always: y <= 63
576
+ dcopy:
577
+ lda b0
578
+ sta (dp),y
579
+ iny
580
+ lda b0+1
581
+ sta (dp),y
582
+ iny
583
+ lda b0+2
584
+ sta (dp),y
585
+ iny
586
+ bne dnext
587
+ dempty:
588
+ lda #0
589
+ sta (dp),y
590
+ iny
591
+ sta (dp),y
592
+ iny
593
+ sta (dp),y
594
+ iny
595
+ dnext:
596
+ cpy #63
597
+ bne drow
598
+ rts
599
+
600
+ // ---------------------------------------------------------------------------
601
+ // request: A = key (frame * 2 + facing). Returns the slot in A. On a miss
602
+ // the next slot round-robin is taken; its old key is forgotten and the
603
+ // frame is depacked into it.
604
+ // ---------------------------------------------------------------------------
605
+ req_cur:
606
+ lda key
607
+ request:
608
+ sta key
609
+ tax
610
+ lda slot_of,x
611
+ bmi miss
612
+ inc hits
613
+ rts
614
+ miss:
615
+ inc misses
616
+ ldx next_slot
617
+ lda key_of,x
618
+ bmi free
619
+ tay
620
+ lda #$ff // evict: the old key has no slot now
621
+ sta slot_of,y
622
+ inc evicts
623
+ free:
624
+ lda key
625
+ sta key_of,x
626
+ tay
627
+ txa
628
+ sta slot_of,y
629
+ lsr // dp = CACHE + slot * 64
630
+ lsr
631
+ clc
632
+ adc #>CACHE
633
+ sta dp+1
634
+ txa
635
+ and #3
636
+ lsr
637
+ ror
638
+ ror
639
+ sta dp
640
+ inx
641
+ txa
642
+ and #SLOTS - 1
643
+ sta next_slot
644
+ lda key
645
+ and #1
646
+ sta face
647
+ lda key
648
+ lsr
649
+ jsr setframe
650
+ jsr depack
651
+ ldx key
652
+ lda slot_of,x
653
+ rts
654
+
655
+ // ---------------------------------------------------------------------------
656
+ // compare: A = number of the 63 bytes at (sp) that differ from (cp)
657
+ // ---------------------------------------------------------------------------
658
+ compare:
659
+ ldx #0
660
+ ldy #62
661
+ !: lda (sp),y
662
+ cmp (cp),y
663
+ beq !+
664
+ inx
665
+ !: dey
666
+ bpl !--
667
+ txa
668
+ rts
669
+
670
+ puts: // print the zero-terminated string at Y:X
671
+ stx ptr
672
+ sty ptr+1
673
+ ldy #0
674
+ !: lda (ptr),y
675
+ beq !+
676
+ jsr CHROUT
677
+ iny
678
+ bne !-
679
+ !: rts
680
+
681
+ putdec: // print the 24-bit value in num, decimal
682
+ ldx #0
683
+ stx lead
684
+ digit:
685
+ lda #'0' - 1
686
+ sta dig
687
+ !: inc dig
688
+ sec
689
+ lda num
690
+ sbc pow10,x
691
+ sta num
692
+ lda num+1
693
+ sbc pow10+1,x
694
+ sta num+1
695
+ lda num+2
696
+ sbc pow10+2,x
697
+ sta num+2
698
+ bcs !-
699
+ lda num // undo the last subtraction
700
+ adc pow10,x
701
+ sta num
702
+ lda num+1
703
+ adc pow10+1,x
704
+ sta num+1
705
+ lda num+2
706
+ adc pow10+2,x
707
+ sta num+2
708
+ lda dig
709
+ cmp #'0'
710
+ bne show
711
+ cpx #6 * 3 // the last digit always prints
712
+ beq show
713
+ lda lead
714
+ beq skip // suppress a leading zero
715
+ lda #'0'
716
+ show:
717
+ jsr CHROUT
718
+ inc lead
719
+ skip:
720
+ inx
721
+ inx
722
+ inx
723
+ cpx #7 * 3
724
+ bne digit
725
+ rts
726
+
727
+ hexbyte: // print A as two hex digits
728
+ pha
729
+ lsr
730
+ lsr
731
+ lsr
732
+ lsr
733
+ jsr hexdigit
734
+ pla
735
+ and #$0f
736
+ hexdigit:
737
+ cmp #10
738
+ bcc !+
739
+ adc #6 // carry set: +7 lands on 'A'
740
+ !: adc #'0'
741
+ jmp CHROUT
742
+
743
+ // ---------------------------------------------------------------------------
744
+ .macro Set16(zp, value) {
745
+ lda #<value
746
+ sta zp
747
+ lda #>value
748
+ sta zp+1
749
+ }
750
+
751
+ // Time(routine, slot): CIA2 timer A counts phi2, timer B its underflows;
752
+ // the 24-bit count lands in slot
753
+ .macro Time(routine, slot) {
754
+ lda #$51
755
+ sta $dd0f
756
+ lda #$11
757
+ sta $dd0e
758
+ jsr routine
759
+ lda #0
760
+ sta $dd0e
761
+ sta $dd0f
762
+ sec
763
+ lda #$ff
764
+ sbc $dd04
765
+ sta slot
766
+ lda #$ff
767
+ sbc $dd05
768
+ sta slot+1
769
+ lda #$ff
770
+ sbc $dd06
771
+ sta slot+2
772
+ }
773
+
774
+ .macro Net(slot) { // slot -= the cost of an empty timed call
775
+ sec
776
+ lda slot
777
+ sbc t_empty
778
+ sta slot
779
+ lda slot+1
780
+ sbc t_empty+1
781
+ sta slot+1
782
+ lda slot+2
783
+ sbc t_empty+2
784
+ sta slot+2
785
+ }
786
+
787
+ .macro Req(k, slot) { // a timed cache request for key k
788
+ lda #k
789
+ sta key
790
+ Time(req_cur, slot)
791
+ }
792
+
793
+ .macro Line2(label1, v1, label2, v2) { // "LABEL1 n LABEL2 n"
794
+ ldx #<label1
795
+ ldy #>label1
796
+ jsr puts
797
+ lda v1
798
+ sta num
799
+ lda v1+1
800
+ sta num+1
801
+ lda v1+2
802
+ sta num+2
803
+ jsr putdec
804
+ ldx #<label2
805
+ ldy #>label2
806
+ jsr puts
807
+ lda v2
808
+ sta num
809
+ lda v2+1
810
+ sta num+1
811
+ lda v2+2
812
+ sta num+2
813
+ jsr putdec
814
+ lda #$0d
815
+ jsr CHROUT
816
+ }
817
+
818
+ .macro Line1(label, v) { // "LABEL n"
819
+ ldx #<label
820
+ ldy #>label
821
+ jsr puts
822
+ lda v
823
+ sta num
824
+ lda v+1
825
+ sta num+1
826
+ lda v+2
827
+ sta num+2
828
+ jsr putdec
829
+ lda #$0d
830
+ jsr CHROUT
831
+ }
832
+
833
+ pow10: .byte <1000000, >1000000, 1000000 >> 16
834
+ .byte <100000, >100000, 100000 >> 16
835
+ .byte <10000, >10000, 0
836
+ .byte <1000, >1000, 0
837
+ .byte <100, >100, 0
838
+ .byte <10, >10, 0
839
+ .byte <1, >1, 0
840
+
841
+ t_empty: .byte 0, 0, 0
842
+ t_genh: .byte 0, 0, 0
843
+ t_genm: .byte 0, 0, 0
844
+ t_fliph: .byte 0, 0, 0
845
+ t_flipm: .byte 0, 0, 0
846
+ t_fill0r: .byte 0, 0, 0
847
+ t_fill0l: .byte 0, 0, 0
848
+ t_fill1l: .byte 0, 0, 0
849
+ t_fill1r: .byte 0, 0, 0
850
+ t_hit: .byte 0, 0, 0
851
+ t_scratch: .byte 0, 0, 0
852
+ misses: .byte 0, 0, 0 // counters are 24-bit for Line2
853
+ hits: .byte 0, 0, 0
854
+ evicts: .byte 0, 0, 0
855
+ bad_tab: .byte 0, 0, 0
856
+ bad_mir: .byte 0, 0, 0
857
+ bad_round: .byte 0, 0, 0
858
+ num: .byte 0, 0, 0
859
+ dig: .byte 0
860
+ lead: .byte 0
861
+ frame: .byte 0
862
+ next_slot: .byte 0
863
+ slot_of: .fill KEYS, $ff // key -> slot, $FF = not cached
864
+ key_of: .fill SLOTS, $ff // slot -> key, $FF = free
865
+
866
+ pairs: .byte 0, 2, 4, 6, 8, 10, 12, 14
867
+ xpos: .byte 32, 60, 96, 124, 160, 188, 224, 252 // all < 256: $D010 stays 0
868
+
869
+ pk_lo: .byte <p0, <p1, <p2, <p3, <p4
870
+ pk_hi: .byte >p0, >p1, >p2, >p3, >p4
871
+ is_mc: .byte 0, 0, 1, 1, 0
872
+ mir_lo: .byte <r0, <r1, <r2, <r3, <r4
873
+ mir_hi: .byte >r0, >r1, >r2, >r3, >r4
874
+
875
+ p0: Packed(f0)
876
+ p1: Packed(f1)
877
+ p2: Packed(f2)
878
+ p3: Packed(f3)
879
+ p4: Packed(f4)
880
+
881
+ .encoding "petscii_upper"
882
+ t_genh_txt: .text "GEN H "
883
+ .byte 0
884
+ t_genm_txt: .text " M "
885
+ .byte 0
886
+ t_flip_txt: .text "FLIP63 H "
887
+ .byte 0
888
+ t_flipm_txt: .text " M "
889
+ .byte 0
890
+ t_fill_txt: .text "FILL 0R "
891
+ .byte 0
892
+ t_fill0l_txt: .text " 0L "
893
+ .byte 0
894
+ t_fill1_txt: .text "FILL 1R "
895
+ .byte 0
896
+ t_fill1l_txt: .text " 1L "
897
+ .byte 0
898
+ t_hit_txt: .text "HIT "
899
+ .byte 0
900
+ t_miss_txt: .text " MISS "
901
+ .byte 0
902
+ t_hits_txt: .text "HITS "
903
+ .byte 0
904
+ t_evict_txt: .text " EVICT "
905
+ .byte 0
906
+ t_tab_txt: .text "TABLES BAD "
907
+ .byte 0
908
+ t_mir_txt: .text " MIRROR BAD "
909
+ .byte 0
910
+ t_round_txt: .text "ROUND BAD "
911
+ .byte 0
912
+ t_res_txt: .text "RESULT "
913
+ .byte 0
914
+ t_pass_txt: .text " PASS"
915
+ .byte 0
916
+ t_fail_txt: .text " FAIL"
917
+ .byte 0
918
+
919
+ *= HREF "reference tables"
920
+ .fill 256, rev8(i)
921
+ .fill 256, revpairs(i)
922
+
923
+ *= $3400 "mirrored frames"
924
+ r0: Mirrored(f0)
925
+ r1: Mirrored(f1)
926
+ r2: Mirrored(f2)
927
+ r3: Mirrored(f3)
928
+ r4: Mirrored(f4)
929
+ ```
930
+
931
+ ## Build
932
+
933
+ ```bash
934
+ java -jar KickAss.jar sprite-cache-flip.asm -o sprite-cache-flip.prg
935
+ ```
936
+
937
+ Run headless (PAL shown; add `-model ntsc` for NTSC):
938
+
939
+ ```bash
940
+ GSETTINGS_SCHEMA_DIR=/opt/homebrew/share/glib-2.0/schemas x64sc -default -minimized -warp +sound \
941
+ +autostart-delay-random -autostartprgmode 1 -limitcycles 8000000 \
942
+ -exitscreenshot sprite-cache-flip.png -autostart sprite-cache-flip.prg
943
+ ```
944
+
945
+ ## Expected output
946
+
947
+ Blue screen, green border. Nine lines of light-blue text at the top,
948
+ decoded from the exit screenshot against the character ROM, the same on
949
+ PAL and NTSC:
950
+
951
+ ```text
952
+ GEN H 28161 M 34817
953
+ FLIP63 H 1597 M 1597
954
+ FILL 0R 2099 0L 2264
955
+ FILL 1R 2441 1L 2672
956
+ HIT 20 MISS 9
957
+ HITS 8 EVICT 1
958
+ TABLES BAD 0 MIRROR BAD 0
959
+ ROUND BAD 0
960
+ RESULT 01 PASS
961
+ ```
962
+
963
+ Below the text, one row of eight sprites with their top row on raster
964
+ line 171 (Y register 170): a white arrow pointing right, the same arrow
965
+ pointing left, a white staircase, its mirror, a multicolour fish facing
966
+ right, the fish facing left, a multicolour ramp and its mirror.
967
+
968
+ Screenshots from the pinned run, 8,000,000 cycles, both models:
969
+ `screenshots/sprite-cache-flip.png` and
970
+ `screenshots/sprite-cache-flip-ntsc.png`. Two runs of each gave
971
+ byte-identical files.
972
+
973
+ | Line | Meaning |
974
+ |---|---|
975
+ | GEN H, M | cycles to build HFLIP and MFLIP, 256 entries each |
976
+ | FLIP63 H, M | cycles to mirror one 63-byte sprite into another buffer with each table |
977
+ | FILL 0R, 0L | a cache miss for frame 0 (15 of 21 rows present), right and left |
978
+ | FILL 1R, 1L | a cache miss for frame 1 (all 21 rows present), right and left |
979
+ | HIT | a cache hit |
980
+ | MISS, HITS, EVICT | counters over the 17 requests: 9 misses, 8 hits, 1 eviction |
981
+ | TABLES BAD | table entries that differ from the assembler's tables |
982
+ | MIRROR BAD | bytes of the five left-facing frames that differ from the assembler's mirrors |
983
+ | ROUND BAD | bytes where mirroring a left-facing frame again does not give the right-facing one |
984
+ | RESULT | `01` PASS and a green border, `02` FAIL and a red border; also stored at $02FF |
985
+
986
+ Every cycle figure is less the cost of an empty timed call, and the fill
987
+ and hit figures include the call through `request`. Mirroring during a
988
+ fill costs 11 cycles a row over a plain copy: 2,672 - 2,441 = 231 for 21
989
+ rows, 2,264 - 2,099 = 165 for 15 (arithmetic from the screen). The
990
+ verdict also requires the evicted frame's key to read as not cached.
991
+
992
+ ### Reading the sprites off the picture
993
+
994
+ The sprites sit at X 32, 60, 96, 124, 160, 188, 224 and 252, so their
995
+ boxes start at screenshot column X + 8; the top row is screenshot row 155
996
+ on PAL and 143 on NTSC (line 171 less 16 or 28). A PIL script mapped
997
+ every pixel of each 24 by 21 box to a palette index with the model's
998
+ table in `runtime/vice-reference.md`, rebuilt the five frame definitions
999
+ from the listing independently in Python, and compared:
1000
+
1001
+ | Check | PAL | NTSC |
1002
+ |---|---|---|
1003
+ | Pixels differing from the expected frame, all 8 sprites | 0 | 0 |
1004
+ | Pixels where a left sprite differs from the mirror of its right neighbour, 4 pairs | 0 | 0 |
1005
+ | Set pixels in the rows just above and below the boxes | 0 | 0 |
1006
+
1007
+ A hires pixel is white (index 1); a multicolour pixel is two screen
1008
+ pixels wide, %01 light red ($D025 = 10), %10 white (the sprite colour),
1009
+ %11 yellow ($D026 = 7).
1010
+
1011
+ **Negative run.** The same listing with `is_mc` set to 0 for every
1012
+ frame, so the multicolour frames are mirrored with the hires table,
1013
+ prints `MIRROR BAD 62`, `ROUND BAD 0` and `RESULT 02 FAIL` on a red
1014
+ border. On the picture the fish and the ramp facing left keep their
1015
+ shape but 136 and 176 of their screen pixels change colour, %01 and %10
1016
+ swapped. The round trip still passes because HFLIP is its own inverse
1017
+ too: only a comparison with an independently mirrored frame catches the
1018
+ wrong table.
1019
+
1020
+ ## Why this works
1021
+
1022
+ **The tables.** `gen_h` shifts each index out to the right eight times
1023
+ and rotates the bits into the accumulator from the right, so bit 0 ends
1024
+ in bit 7. `gen_m` shifts the result left two places and ORs in the
1025
+ lowest pair of what is left of the index, four times, so pair 0 ends in
1026
+ pair 3 with its two bits in their original order. The references are
1027
+ `.fill 256, rev8(i)` and `.fill 256, revpairs(i)`, computed by the
1028
+ assembler from the bit arithmetic, a different path to the same table.
1029
+
1030
+ **The mirror.** `flip63` and the mirrored branch of `depack` write
1031
+ `T[b2], T[b1], T[b0]` for each row. The source and destination must not
1032
+ overlap: `flip63` writes byte `r` of a row before reading byte `r` of
1033
+ the source. The table's page is patched into the six `lda table,x`
1034
+ operands by `settbl`, so one routine serves both modes. The two
1035
+ routines share one page (`.align $100`); an earlier build in which the
1036
+ loop branch of `flip63` crossed a page measured `FLIP63 1617`, 20 cycles
1037
+ more, one per taken branch.
1038
+
1039
+ **The packing.** The assembler turns each frame's pixel strings into
1040
+ three mask bytes, one bit per row, and emits 3 bytes for each row whose
1041
+ value is not zero. `depack` shifts the 24-bit mask right once per row;
1042
+ the carry says whether to read a row or store three zeros. Byte 63 of a
1043
+ slot is never written.
1044
+
1045
+ **The cache.** `request` takes a key, `frame * 2 + facing`. A hit
1046
+ returns `slot_of[key]`. A miss takes `next_slot`, clears `slot_of` for
1047
+ the key the slot held, depacks the frame into `$2000 + slot * 64`,
1048
+ records both mappings and advances `next_slot` modulo 8. The sequence
1049
+ requests frame 4 first (key 8), then keys 0, 2, 4, 6, 1, 3, 5 and 7, so
1050
+ key 7 lands in slot 0 and evicts frame 4; the second pass over keys 0 to 7 is all hits. The
1051
+ sprite pointer for key `n` is `$80 + slot_of[n]`, because the cache
1052
+ starts at $2000 in VIC bank 0, 128 blocks in.
1053
+
1054
+ **The measurement.** CIA2 timer A counts phi2 and timer B counts its
1055
+ underflows, the harness of `sine-table-runtime.md`. All timed work runs
1056
+ under `SEI` with the screen blanked a frame early, since DEN is sampled
1057
+ once, on line $30, so no badline steals cycles.
1058
+
1059
+ **The positions.** Every X is below 256, so $D010 stays 0. A first
1060
+ draft placed the last pair at X 256 and 288 with $D010 clear; the
1061
+ sprites appeared at X 0 and 32, one hidden in the border and one on top
1062
+ of the first arrow (`sprite_x_high_bit_wrong_register`).
1063
+
1064
+ ## What this recipe does not show
1065
+
1066
+ Protection of on-screen frames from eviction: the recipe never has more
1067
+ distinct frames on screen than slots, so plain round-robin is enough
1068
+ here and is not enough in a game (see the technique's Eviction
1069
+ paragraph). A cache under the I/O area, which needs $01 banking with
1070
+ IRQs off during the fill. Depacking inside a running game loop with a
1071
+ multiplexer; every fill here runs before the display starts.