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,875 @@
1
+ ---
2
+ recipe: tape-turbo-loader
3
+ toolchain: kickassembler
4
+ output_format: PRG
5
+ region: both
6
+ techniques: [tape_turbo_loader]
7
+ file_formats: [PRG, TAP]
8
+ uses_registers: [D011, D012, D020, DC06, DC07, DC0D, DC0F, DD04, DD05, DD06, DD07, DD0E, DD0F]
9
+ uses_kernal: [CHROUT]
10
+ ---
11
+
12
+ <!-- doc-type: recipe -->
13
+
14
+ # KickAssembler Tape Turbo Loader
15
+
16
+ ## Synopsis
17
+
18
+ Read a block from tape at one pulse per bit, without the KERNAL's tape
19
+ routines. A Python script writes a TAP file whose stream is a lead-in of
20
+ 1 bits, a sync byte, a two-byte length, 500 bytes of known data and an
21
+ XOR checksum, with a 256-cycle pulse for a 0 and a 512-cycle pulse for
22
+ a 1. The loader turns the motor on through `$01`, polls the FLAG bit of
23
+ `$DC0D` for each falling edge of the cassette read line, times the gap
24
+ between edges with a free-running CIA 1 Timer B, sorts each gap against
25
+ a threshold of 384 cycles, waits for sixty-four 1 bits and the 0 that
26
+ opens the sync byte, and then assembles the bytes. It prints the lead-in
27
+ pulses it saw, the length, its own checksum beside the tape's, the CIA 2
28
+ cycle count over the timed span and the bytes per second that gives on
29
+ the detected model, and the shortest and longest pulse it measured for
30
+ each bit value. The verdict at `$02FF` is `01` and the border turns
31
+ green when the length, both checksums and every byte match the
32
+ compiled-in expectation, else `02` and red. The technique is
33
+ `tape_turbo_loader` on `../../techniques/file-io.md`; the KERNAL's own
34
+ pulse-pair encoding, which this deliberately is not, is measured in
35
+ `../../formats/c64-file-formats.md` under "KERNAL bit encoding".
36
+
37
+ ## Source
38
+
39
+ ```asm
40
+ // tape-turbo-loader.asm
41
+ // Read a one-pulse-per-bit turbo block from tape without the KERNAL's tape
42
+ // routines: motor on through $01, FLAG edges polled in $DC0D, each pulse
43
+ // timed by a free-running CIA 1 Timer B, bits sorted by a threshold.
44
+ // Prints the lead-in count, the block's checksum, the cycles and bytes per
45
+ // second over the block and the pulse lengths seen for each bit value.
46
+ BasicUpstart2(start)
47
+
48
+ .const CHROUT = $ffd2
49
+ .const VERDICT = $02ff
50
+ .const PORT = $01 // 6510 port: bit 4 sense (0 = PLAY down), bit 5 motor (0 = on)
51
+ .const ICR = $dc0d // CIA 1 interrupt control: bit 4 is the FLAG edge
52
+ .const TBLO = $dc06
53
+ .const TBHI = $dc07
54
+ .const CRB = $dc0f
55
+ .const C2TALO = $dd04 // CIA 2 timers cascaded as a 32-bit stopwatch
56
+ .const C2TAHI = $dd05
57
+ .const C2TBLO = $dd06
58
+ .const C2TBHI = $dd07
59
+ .const C2CRA = $dd0e
60
+ .const C2CRB = $dd0f
61
+ .const BORDER = $d020
62
+ .const SCRCTL = $d011
63
+ .const RASTER = $d012
64
+
65
+ .const THRESH = 384 // cycles: a 0 is 256 cycles, a 1 is 512, on the tape written by make_tap.py
66
+ .const SYNC = $5a // first bit 0, so it also ends the lead-in of 1 bits
67
+ .const LEADIN_MIN = 64 // consecutive 1 bits before a 0 counts as sync
68
+ .const EXPECT_LEN = 500
69
+ .const EXPECT_CHK = $40 // XOR of the 500 bytes (i*7+3)&255, printed by make_tap.py
70
+ .const BUF = $4000
71
+ .const PAL_CLOCK = 985248
72
+ .const NTSC_CLOCK = 1022727
73
+
74
+ // zero page
75
+ .const last = $fb // Timer B at the previous edge
76
+ .const now = $fd
77
+ .const pulse = $02 // length of the last pulse, cycles
78
+ .const byte = $04
79
+ .const ptr = $05 // 2 bytes
80
+ .const remain = $07 // 2 bytes: bytes still to read
81
+ .const chk = $09
82
+ .const n = $0a // 4 bytes: dividend / value to print
83
+ .const d = $0e // 2 bytes: divisor
84
+ .const rem = $10 // 3 bytes
85
+ .const cnt = $13
86
+ .const tmp = $14 // 2 bytes
87
+
88
+ start:
89
+ lda #$93
90
+ jsr CHROUT
91
+ ldx #0
92
+ !: lda title,x
93
+ beq !+
94
+ jsr CHROUT
95
+ inx
96
+ bne !-
97
+ !:
98
+ sei
99
+ lda #$7f
100
+ sta ICR // no CIA 1 interrupts while we poll the ICR
101
+ lda ICR // clear anything pending
102
+ lda #$00
103
+ sta CRB // Timer B stopped
104
+ lda #$ff
105
+ sta TBLO
106
+ sta TBHI // latch $FFFF
107
+ lda #$11 // force load and run continuously from the system clock
108
+ sta CRB
109
+
110
+ wait_play:
111
+ lda PORT
112
+ and #$10
113
+ bne wait_play // bit 4 low: PLAY is down
114
+ lda PORT
115
+ and #$df
116
+ sta PORT // bit 5 low: motor on
117
+ lda SCRCTL
118
+ and #$ef
119
+ sta SCRCTL // screen off: no badline steals the poll
120
+
121
+ lda #0
122
+ sta leadin
123
+ sta leadin+1
124
+ sta ones
125
+ jsr read_pulse // prime 'last'
126
+
127
+ // lead-in: wait for LEADIN_MIN consecutive 1 bits, then the first 0 is bit 7 of SYNC
128
+ sync_loop:
129
+ jsr read_bit
130
+ inc leadin
131
+ bne !+
132
+ inc leadin+1
133
+ !: bcc got_zero
134
+ lda ones
135
+ cmp #LEADIN_MIN
136
+ bcs sync_loop
137
+ inc ones
138
+ bne sync_loop
139
+ got_zero:
140
+ lda ones
141
+ cmp #LEADIN_MIN
142
+ bcc reset_ones // a 0 too early: start counting again
143
+ lda #0
144
+ sta byte
145
+ lda #7
146
+ sta cnt
147
+ !: jsr read_bit // read_bit leaves X as the stats slot, so count in memory
148
+ rol byte
149
+ dec cnt
150
+ bne !-
151
+ lda byte
152
+ cmp #SYNC
153
+ beq synced
154
+ reset_ones:
155
+ lda #0
156
+ sta ones
157
+ beq sync_loop
158
+
159
+ synced:
160
+ jsr stats_reset // set up now: a 0 pulse is short and the next edge will not wait
161
+ jsr stopwatch_start
162
+ jsr read_byte
163
+ sta remain
164
+ sta length
165
+ jsr read_byte
166
+ sta remain+1
167
+ sta length+1
168
+ lda #<BUF
169
+ sta ptr
170
+ lda #>BUF
171
+ sta ptr+1
172
+ lda #0
173
+ sta chk
174
+ ldy #0
175
+ block_loop:
176
+ lda remain
177
+ ora remain+1
178
+ beq block_done
179
+ jsr read_byte
180
+ sta (ptr),y
181
+ eor chk
182
+ sta chk
183
+ inc ptr
184
+ bne !+
185
+ inc ptr+1
186
+ !: lda remain
187
+ bne !+
188
+ dec remain+1
189
+ !: dec remain
190
+ jmp block_loop
191
+ block_done:
192
+ jsr read_byte
193
+ sta tapechk
194
+ jsr stopwatch_stop // timed: length, block and checksum, EXPECT_LEN + 3 bytes
195
+
196
+ lda PORT
197
+ ora #$20
198
+ sta PORT // motor off
199
+ lda SCRCTL
200
+ ora #$10
201
+ sta SCRCTL
202
+ lda #$81
203
+ sta ICR // Timer A interrupt back on for the KERNAL
204
+ cli
205
+
206
+ // verdict: length, checksum and every byte against the generating formula
207
+ lda #2
208
+ sta verdict
209
+ lda length
210
+ cmp #<EXPECT_LEN
211
+ bne judged
212
+ lda length+1
213
+ cmp #>EXPECT_LEN
214
+ bne judged
215
+ lda chk
216
+ cmp #EXPECT_CHK
217
+ bne judged
218
+ cmp tapechk
219
+ bne judged
220
+ jsr check_bytes
221
+ bcs judged
222
+ lda #1
223
+ sta verdict
224
+ judged:
225
+
226
+ // report
227
+ jsr detect_model
228
+ lda #<t_leadin
229
+ ldy #>t_leadin
230
+ jsr print
231
+ lda leadin
232
+ sta n
233
+ lda leadin+1
234
+ sta n+1
235
+ lda #0
236
+ sta n+2
237
+ sta n+3
238
+ jsr print_dec
239
+ lda #<t_len
240
+ ldy #>t_len
241
+ jsr print
242
+ lda length
243
+ sta n
244
+ lda length+1
245
+ sta n+1
246
+ jsr print_dec
247
+ lda #<t_chk
248
+ ldy #>t_chk
249
+ jsr print
250
+ lda chk
251
+ jsr print_hex
252
+ lda #<t_tapechk
253
+ ldy #>t_tapechk
254
+ jsr print
255
+ lda tapechk
256
+ jsr print_hex
257
+ lda #13
258
+ jsr CHROUT
259
+
260
+ lda #<t_cycles
261
+ ldy #>t_cycles
262
+ jsr print
263
+ ldx #3
264
+ !: lda cycles,x
265
+ sta n,x
266
+ dex
267
+ bpl !-
268
+ jsr print_dec
269
+ lda #<t_bps
270
+ ldy #>t_bps
271
+ jsr print
272
+ // bytes per second = clock / (cycles / length)
273
+ ldx #3
274
+ !: lda cycles,x
275
+ sta n,x
276
+ dex
277
+ bpl !-
278
+ lda #<[EXPECT_LEN + 3]
279
+ sta d
280
+ lda #>[EXPECT_LEN + 3]
281
+ sta d+1
282
+ jsr div32 // n = cycles per byte
283
+ lda n
284
+ sta d
285
+ lda n+1
286
+ sta d+1
287
+ lda model
288
+ bne !+
289
+ lda #<PAL_CLOCK
290
+ sta n
291
+ lda #>PAL_CLOCK
292
+ sta n+1
293
+ lda #[PAL_CLOCK >> 16]
294
+ sta n+2
295
+ bne !++
296
+ !: lda #<NTSC_CLOCK
297
+ sta n
298
+ lda #>NTSC_CLOCK
299
+ sta n+1
300
+ lda #[NTSC_CLOCK >> 16]
301
+ sta n+2
302
+ !: lda #0
303
+ sta n+3
304
+ jsr div32
305
+ jsr print_dec
306
+ lda #<t_model
307
+ ldy #>t_model
308
+ jsr print
309
+ lda model
310
+ beq !+
311
+ lda #<t_ntsc
312
+ ldy #>t_ntsc
313
+ bne !++
314
+ !: lda #<t_pal
315
+ ldy #>t_pal
316
+ !: jsr print
317
+
318
+ lda #<t_bit0
319
+ ldy #>t_bit0
320
+ jsr print
321
+ ldx #0
322
+ jsr print_range
323
+ lda #<t_bit1
324
+ ldy #>t_bit1
325
+ jsr print
326
+ ldx #4
327
+ jsr print_range
328
+ lda #13
329
+ jsr CHROUT
330
+
331
+ lda verdict
332
+ sta VERDICT
333
+ cmp #1
334
+ beq good
335
+ lda #2
336
+ sta BORDER
337
+ lda #<t_bad
338
+ ldy #>t_bad
339
+ jmp print
340
+ good:
341
+ lda #5
342
+ sta BORDER
343
+ lda #<t_ok
344
+ ldy #>t_ok
345
+ jmp print
346
+
347
+ // ---------------------------------------------------------------- tape input
348
+
349
+ // Wait for a FLAG edge and measure the time since the previous one.
350
+ // Timer B free-runs down from $FFFF, so the length is last - now.
351
+ read_pulse:
352
+ lda ICR
353
+ and #$10
354
+ beq read_pulse
355
+ lda TBHI
356
+ sta now+1
357
+ lda TBLO
358
+ sta now
359
+ lda TBHI
360
+ cmp now+1 // the low byte wrapped between the reads: take both again
361
+ beq !+
362
+ sta now+1
363
+ lda TBLO
364
+ sta now
365
+ !: sec
366
+ lda last
367
+ sbc now
368
+ sta pulse
369
+ lda last+1
370
+ sbc now+1
371
+ sta pulse+1
372
+ lda now
373
+ sta last
374
+ lda now+1
375
+ sta last+1
376
+ rts
377
+
378
+ // One bit into the carry: 0 below THRESH cycles, 1 at or above it.
379
+ read_bit:
380
+ jsr read_pulse
381
+ lda pulse+1
382
+ cmp #>THRESH
383
+ bne !+
384
+ lda pulse
385
+ cmp #<THRESH
386
+ !: php
387
+ bcc !+
388
+ ldx #4 // stats slot for a 1
389
+ bne !++
390
+ !: ldx #0
391
+ !: jsr stats_update
392
+ plp
393
+ rts
394
+
395
+ // Eight bits, most significant first.
396
+ read_byte:
397
+ lda #8
398
+ sta cnt
399
+ !: jsr read_bit
400
+ rol byte
401
+ dec cnt
402
+ bne !-
403
+ lda byte
404
+ rts
405
+
406
+ // min and max pulse length per bit value: min0, max0 at stats+0..3, min1, max1 at +4..7
407
+ stats_reset:
408
+ ldx #1
409
+ !: lda #$ff
410
+ sta stats,x // minima start at $FFFF
411
+ sta stats+4,x
412
+ lda #0
413
+ sta stats+2,x // maxima at 0
414
+ sta stats+6,x
415
+ dex
416
+ bpl !-
417
+ rts
418
+
419
+ stats_update:
420
+ lda pulse+1
421
+ cmp stats+1,x
422
+ bne !+
423
+ lda pulse
424
+ cmp stats,x
425
+ !: bcs !+
426
+ lda pulse
427
+ sta stats,x
428
+ lda pulse+1
429
+ sta stats+1,x
430
+ !: lda stats+3,x
431
+ cmp pulse+1
432
+ bne !+
433
+ lda stats+2,x
434
+ cmp pulse
435
+ !: bcs !+
436
+ lda pulse
437
+ sta stats+2,x
438
+ lda pulse+1
439
+ sta stats+3,x
440
+ !: rts
441
+
442
+ // ---------------------------------------------------------------- stopwatch
443
+
444
+ stopwatch_start:
445
+ lda #0
446
+ sta C2CRA
447
+ sta C2CRB
448
+ lda #$ff
449
+ sta C2TALO
450
+ sta C2TAHI
451
+ sta C2TBLO
452
+ sta C2TBHI
453
+ lda #$51 // B counts A underflows, force load, start
454
+ sta C2CRB
455
+ lda #$11 // A counts the clock, force load, start
456
+ sta C2CRA
457
+ rts
458
+
459
+ stopwatch_stop:
460
+ lda #0
461
+ sta C2CRA
462
+ sta C2CRB
463
+ sec
464
+ lda #$ff
465
+ sbc C2TALO
466
+ sta cycles
467
+ lda #$ff
468
+ sbc C2TAHI
469
+ sta cycles+1
470
+ sec
471
+ lda #$ff
472
+ sbc C2TBLO
473
+ sta cycles+2
474
+ lda #$ff
475
+ sbc C2TBHI
476
+ sta cycles+3
477
+ rts
478
+
479
+ // ---------------------------------------------------------------- checks
480
+
481
+ // C=0 when every byte of the block is (i*7+3)&255.
482
+ check_bytes:
483
+ lda #<BUF
484
+ sta ptr
485
+ lda #>BUF
486
+ sta ptr+1
487
+ lda #3
488
+ sta byte
489
+ lda #<EXPECT_LEN
490
+ sta remain
491
+ lda #>EXPECT_LEN
492
+ sta remain+1
493
+ ldy #0
494
+ !: lda (ptr),y
495
+ cmp byte
496
+ bne bad_byte
497
+ lda byte
498
+ clc
499
+ adc #7
500
+ sta byte
501
+ inc ptr
502
+ bne !+
503
+ inc ptr+1
504
+ !: lda remain
505
+ bne !+
506
+ dec remain+1
507
+ !: dec remain
508
+ lda remain
509
+ ora remain+1
510
+ bne !--
511
+ clc
512
+ rts
513
+ bad_byte:
514
+ sec
515
+ rts
516
+
517
+ // model = 0 for PAL, 1 for NTSC: a raster line at or past 288 exists only on PAL.
518
+ // 4096 reads of about 20 cycles cover four frames on either model.
519
+ detect_model:
520
+ lda #1
521
+ sta model
522
+ ldx #0
523
+ ldy #16
524
+ dm_loop:
525
+ lda SCRCTL
526
+ bpl dm_next
527
+ lda RASTER
528
+ cmp #$20
529
+ bcc dm_next
530
+ lda #0
531
+ sta model
532
+ rts
533
+ dm_next:
534
+ dex
535
+ bne dm_loop
536
+ dey
537
+ bne dm_loop
538
+ rts
539
+
540
+ // ---------------------------------------------------------------- output
541
+
542
+ print:
543
+ sta ptr
544
+ sty ptr+1
545
+ ldy #0
546
+ !: lda (ptr),y
547
+ beq !+
548
+ jsr CHROUT
549
+ iny
550
+ bne !-
551
+ !: rts
552
+
553
+ print_hex:
554
+ pha
555
+ lsr
556
+ lsr
557
+ lsr
558
+ lsr
559
+ jsr print_nibble
560
+ pla
561
+ and #$0f
562
+ print_nibble:
563
+ ora #$30
564
+ cmp #$3a
565
+ bcc !+
566
+ adc #6
567
+ !: jmp CHROUT
568
+
569
+ // print stats slot X as "min-max"
570
+ print_range:
571
+ lda stats,x
572
+ sta n
573
+ lda stats+1,x
574
+ sta n+1
575
+ lda #0
576
+ sta n+2
577
+ sta n+3
578
+ lda stats+2,x
579
+ sta tmp
580
+ lda stats+3,x
581
+ sta tmp+1
582
+ jsr print_dec
583
+ lda #'-'
584
+ jsr CHROUT
585
+ lda tmp
586
+ sta n
587
+ lda tmp+1
588
+ sta n+1
589
+ jmp print_dec
590
+
591
+ // n (32-bit) in decimal, by repeated division by ten
592
+ print_dec:
593
+ lda #0
594
+ sta cnt
595
+ !: lda #10
596
+ sta d
597
+ lda #0
598
+ sta d+1
599
+ jsr div32
600
+ lda rem
601
+ pha
602
+ inc cnt
603
+ lda n
604
+ ora n+1
605
+ ora n+2
606
+ ora n+3
607
+ bne !-
608
+ !: pla
609
+ ora #$30
610
+ jsr CHROUT
611
+ dec cnt
612
+ bne !-
613
+ rts
614
+
615
+ // n = n / d, rem = n mod d; shift-and-subtract, 32 steps
616
+ div32:
617
+ lda #0
618
+ sta rem
619
+ sta rem+1
620
+ sta rem+2
621
+ ldx #32
622
+ !: asl n
623
+ rol n+1
624
+ rol n+2
625
+ rol n+3
626
+ rol rem
627
+ rol rem+1
628
+ rol rem+2
629
+ sec
630
+ lda rem
631
+ sbc d
632
+ tay
633
+ lda rem+1
634
+ sbc d+1
635
+ pha
636
+ lda rem+2
637
+ sbc #0
638
+ bcc !+
639
+ sta rem+2
640
+ pla
641
+ sta rem+1
642
+ sty rem
643
+ inc n
644
+ bne !++
645
+ !: pla
646
+ !: dex
647
+ bne !---
648
+ rts
649
+
650
+ // ---------------------------------------------------------------- data
651
+
652
+ title: .text "TAPE TURBO LOADER"
653
+ .byte 13, 0
654
+ t_leadin: .text "LEADIN "
655
+ .byte 0
656
+ t_len: .text " LEN "
657
+ .byte 0
658
+ t_chk: .text " CHK "
659
+ .byte 0
660
+ t_tapechk: .text "/"
661
+ .byte 0
662
+ t_cycles: .text "CYCLES "
663
+ .byte 0
664
+ t_bps: .text " B/S "
665
+ .byte 0
666
+ t_model: .text " "
667
+ .byte 0
668
+ t_pal: .text "PAL"
669
+ .byte 13, 0
670
+ t_ntsc: .text "NTSC"
671
+ .byte 13, 0
672
+ t_bit0: .text "BIT0 "
673
+ .byte 0
674
+ t_bit1: .text " BIT1 "
675
+ .byte 0
676
+ t_ok: .text "OK"
677
+ .byte 13, 0
678
+ t_bad: .text "BAD"
679
+ .byte 13, 0
680
+
681
+ leadin: .word 0
682
+ ones: .byte 0
683
+ length: .word 0
684
+ tapechk: .byte 0
685
+ verdict: .byte 0
686
+ model: .byte 0
687
+ cycles: .byte 0, 0, 0, 0
688
+ stats: .fill 8, 0
689
+ ```
690
+
691
+ ## Build
692
+
693
+ The tape first. This script is not part of the listing; save it as
694
+ `make_tap.py` beside the source and run it once:
695
+
696
+ ```text
697
+ #!/usr/bin/env python3
698
+ """Write a TAP v1 file for the tape-turbo-loader recipe.
699
+
700
+ One pulse per bit: a short pulse is a 0, a long pulse is a 1. The
701
+ stream is a lead-in of 1 bits, a sync byte, a two-byte length, the data
702
+ block and an XOR checksum, most significant bit first inside each byte.
703
+ """
704
+ import struct
705
+ import sys
706
+
707
+ SHORT = 0x20 # 0 bit: 32 TAP units = 256 cycles
708
+ LONG = 0x40 # 1 bit: 64 TAP units = 512 cycles
709
+ LEADIN = 12000 # 1 bits before the sync byte: about 6 s, the tape runs from power-on
710
+ SYNC = 0x5A
711
+ LENGTH = 500
712
+
713
+
714
+ def data_byte(i):
715
+ return (i * 7 + 3) & 0xFF
716
+
717
+
718
+ def bits_of(byte):
719
+ return [(byte >> (7 - k)) & 1 for k in range(8)]
720
+
721
+
722
+ def main(path):
723
+ pulses = []
724
+ pulses += [LONG] * LEADIN
725
+ data = bytes(data_byte(i) for i in range(LENGTH))
726
+ check = 0
727
+ for b in data:
728
+ check ^= b
729
+ stream = bytes([SYNC, LENGTH & 0xFF, LENGTH >> 8]) + data + bytes([check])
730
+ for byte in stream:
731
+ for bit in bits_of(byte):
732
+ pulses.append(LONG if bit else SHORT)
733
+ # a trailer of long pulses so the last data edge is followed by another
734
+ pulses += [LONG] * 3000
735
+ body = bytes(pulses)
736
+ header = b"C64-TAPE-RAW" + bytes([1, 0, 0, 0]) + struct.pack("<I", len(body))
737
+ with open(path, "wb") as f:
738
+ f.write(header + body)
739
+ cycles = sum(p * 8 for p in pulses[LEADIN + 8:LEADIN + 8 * (3 + LENGTH + 1)])
740
+ print(f"wrote {path}: {len(body)} pulses, checksum ${check:02X}, "
741
+ f"timed span {cycles} cycles")
742
+
743
+
744
+ if __name__ == "__main__":
745
+ main(sys.argv[1] if len(sys.argv) > 1 else "turbo.tap")
746
+ ```
747
+
748
+ It prints `wrote turbo.tap: 19032 pulses, checksum $40, timed span
749
+ 1540608 cycles`. Every TAP entry is one pulse of `value * 8` cycles, so
750
+ the file is 20 bytes of header and 19,032 bytes of pulses. The checksum
751
+ `$40` is the `EXPECT_CHK` constant in the listing; change `LENGTH` or
752
+ `data_byte` and the constant must follow. Then:
753
+
754
+ ```bash
755
+ java -jar $KICKASS_JAR tape-turbo-loader.asm -o tape-turbo-loader.prg
756
+ printf 'tapectrl 1\n' > play.mon
757
+ x64sc -default -warp +sound +autostart-delay-random -autostartprgmode 1 \
758
+ -limitcycles 12000000 +dsresetwithcpu \
759
+ -dstapewobbleamp 0 -dstapewobblefreq 0 -dsspeedtuning 0 -dstapeerror 0 \
760
+ -1 turbo.tap -moncommands play.mon \
761
+ -exitscreenshot tape-turbo-loader.png -autostart tape-turbo-loader.prg
762
+ ```
763
+
764
+ Add `-model ntsc` for the NTSC run. Three of those options matter and
765
+ were found by running without them. `-1` attaches the TAP, and
766
+ `tapectrl 1` in the monitor command file presses PLAY at power-on
767
+ (`help tapectrl` lists 0 stop, 1 start, 2 forward, 3 rewind, 4 record,
768
+ 5 reset, 6 reset counter). `+dsresetwithcpu` keeps that press through
769
+ the reset autostart performs after the monitor commands have run;
770
+ without it the loader sat at its PLAY wait for the whole run. The four
771
+ `-ds` options turn off VICE's tape speed error and wobble so that two
772
+ runs give the same picture; with them at their defaults the block still
773
+ loaded and verified, but the pulse ranges widened (see below). The
774
+ program presses nothing itself: it waits for bit 4 of `$01` to go low,
775
+ then drives bit 5 low for the motor.
776
+
777
+ ## Expected output
778
+
779
+ ```
780
+ TAPE TURBO LOADER
781
+ LEADIN 10195 LEN 500 CHK 40/40
782
+ CYCLES 1540498 B/S 321 PAL
783
+ BIT0 248-264 BIT1 506-520
784
+ OK
785
+ ```
786
+
787
+ Line by line: the number of lead-in pulses the loader saw before the
788
+ sync byte (the tape has been running since the KERNAL saw PLAY at
789
+ power-on, so the loader joins the lead-in part way through); the length
790
+ read from the tape; the loader's XOR of the block beside the checksum
791
+ byte from the tape; the CIA 2 cycle count from the end of the sync byte
792
+ to the end of the checksum byte, the 503 bytes of length, data and
793
+ checksum, and the bytes per second that count gives on the detected
794
+ model; and the shortest and longest pulse measured for a 0 and for a 1,
795
+ in cycles. `OK` and a green border mean `$02FF` holds `01`.
796
+
797
+ Measured on the windowless x64sc build of VICE 3.10 with the command
798
+ above (rung 1); two runs per model gave byte-identical screenshots, and
799
+ every character cell was decoded against the character ROM. The
800
+ pictures are `../../figures/tape-turbo-loader-pal.png` and
801
+ `../../figures/tape-turbo-loader-ntsc.png`. The NTSC picture reads
802
+ `LEADIN 9957`, `CYCLES 1540502 B/S 334 NTSC` and the same `BIT0 248-264
803
+ BIT1 506-520`: the TAP stores pulses in cycles, so the block costs the
804
+ same cycles on either model and the faster NTSC clock turns them into
805
+ more bytes per second. The 1,540,498 cycles the loader timed are 110
806
+ less than the 1,540,608 the script summed for the same span, which is
807
+ the poll's position inside the first and last pulse. The measured pulses
808
+ sit within 8 cycles of the 256 and 512 the file holds: that is the
809
+ polling loop's own granularity, `LDA`, `AND`, `BEQ`, nine cycles round.
810
+
811
+ With the four `-ds` options left out, so VICE's default tape speed
812
+ error and wobble apply, the PAL run read `LEADIN 10201`, `CYCLES
813
+ 1547961 B/S 320`, `BIT0 231-283 BIT1 487-542` and still `OK`; NTSC gave
814
+ `CYCLES 1547864 B/S 332`, `BIT0 231-283 BIT1 490-539`. The spread grew
815
+ from 16 cycles to 52 on either bit and the block took 0.5 % longer. The
816
+ threshold of 384 had at least 101 cycles to spare on either side (101
817
+ below, 103 and 106 above), which is why the checksum survived; a real
818
+ Datasette's speed error is not measured here.
819
+
820
+ **Not pinned.** The listing gate assembles the source, but the
821
+ verifier's run cannot be pinned in `runs.json`: it formats a blank disk
822
+ and attaches nothing else, and this program needs the TAP on `-1`, the
823
+ `tapectrl 1` command file and `+dsresetwithcpu`. The pictures therefore
824
+ live under `docs/figures/` rather than `screenshots/`, and the command
825
+ above is the one that made them. A verifier run without the TAP leaves
826
+ the loader at its PLAY wait, so `--update` must not be run on this page:
827
+ the picture it would freeze shows nothing but that wait.
828
+
829
+ ## Why this works
830
+
831
+ A Datasette turbo is a different stream from the KERNAL's, not a faster
832
+ reading of it. The KERNAL writes a bit as a pair of pulses drawn from
833
+ three lengths, twenty pulses to a byte and every block twice; this
834
+ stream has one pulse per bit and two lengths, eight pulses to a byte and
835
+ one copy. The C64 sees each pulse as one falling edge on the cassette
836
+ read line, which is wired to CIA 1's FLAG input, so `read_pulse` waits
837
+ for bit 4 of `$DC0D` and then reads Timer B, which was started once with
838
+ `$11` in `$DC0F` and runs down from `$FFFF` continuously. The length of
839
+ a pulse is the previous reading less this one, in cycles, with no timer
840
+ restart and nothing lost between pulses. Reading the timer takes two
841
+ instructions, and the low byte can wrap between them, so the high byte
842
+ is read again and both bytes taken afresh if it moved; a first version
843
+ that only re-read when the low byte was `$FF` mismeasured one pulse in
844
+ about sixty by 256 cycles, because the two reads are seven cycles apart
845
+ and any wrap inside that window is missed. `read_bit` compares the
846
+ 16-bit length against 384 and returns the bit in the carry.
847
+
848
+ The sync scheme is what lets the loader start anywhere. The lead-in is
849
+ all 1 bits, so a run of sixty-four of them proves the loader is inside
850
+ it, and the first 0 after that run is, by construction, bit 7 of `$5A`.
851
+ Seven more bits are rotated in behind it; if the byte is not `$5A` the
852
+ count starts again. Because the tape has been running since the
853
+ KERNAL's interrupt saw PLAY at power-on, the loader joins the lead-in
854
+ late and the count printed is what was left. Everything after the sync
855
+ byte is plain: two length bytes, the block into `BUF`, one checksum.
856
+ The loader runs with interrupts off and CIA 1's interrupt sources
857
+ masked (`$7F` to `$DC0D`, then a read to clear what was pending),
858
+ because reading `$DC0D` clears every bit in it, and a KERNAL interrupt
859
+ that read it first would steal FLAG edges; the KERNAL's own tape code
860
+ uses the same register and is left out for the same reason. Timer A's
861
+ interrupt is re-enabled afterwards so the KERNAL's clock and keyboard
862
+ scan resume.
863
+
864
+ The 256-cycle 0 pulse is not arbitrary. An earlier build of this recipe
865
+ used 208 and 416 cycles with the threshold at 312, and its checksum
866
+ came out `C0` against the tape's `40`: the first data byte read `83`
867
+ for `03`, a 0 read as 376 cycles. The loader had spent about 170
868
+ cycles between the last length bit and the first data bit resetting its
869
+ statistics and starting the stopwatch, so it polled that edge late, and
870
+ its per-bit path (the poll, the double timer read, the subtraction, the
871
+ compare and the minimum and maximum bookkeeping) is about 175 cycles,
872
+ which leaves a 208-cycle pulse no room to absorb the debt. Moving the
873
+ setup ahead of the length bytes and widening the pulses to 256 and 512
874
+ cured it. A loader without the statistics can run shorter pulses; how
875
+ short, on this build, is not measured here.