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,1393 @@
1
+ ---
2
+ tool: vice
3
+ tool_kind: emulator
4
+ maintainer: VICE Team
5
+ license: GPL-2.0
6
+ home_url: https://vice-emu.sourceforge.io/
7
+ version_verified: "3.10"
8
+ ---
9
+ <!-- doc-type: toolchain-reference -->
10
+
11
+ # VICE — Versatile Commodore Emulator
12
+
13
+ ## Tool
14
+
15
+ VICE (Versatile Commodore Emulator) is an open-source emulator that runs software
16
+ written for the Commodore 8-bit computer family on modern hardware. For c64-kb purposes
17
+ the only relevant binary is `x64sc`, the cycle-accurate C64 emulator. VICE exposes a
18
+ TCP-based binary monitor protocol on port 6502 that allows external programs to inspect
19
+ and control the running machine — read and write memory, set breakpoints, capture the
20
+ screen, load and execute programs, and save snapshots. The vice-mcp server speaks this
21
+ protocol on behalf of agents; agents do not drive the protocol directly.
22
+
23
+ **Targets:** 6510, VIC-II, SID, CIA1, CIA2
24
+
25
+ ---
26
+
27
+ ## Quick Reference
28
+
29
+ ### Install
30
+
31
+ ```bash
32
+ # macOS — Homebrew
33
+ brew install vice
34
+
35
+ # Debian / Ubuntu
36
+ sudo apt install vice
37
+
38
+ # Fedora
39
+ sudo dnf install vice
40
+ ```
41
+
42
+ After installation, ROM images must be present. On Homebrew macOS they land in
43
+ `/opt/homebrew/share/vice/C64/`. On Linux, packages that include the ROMs place them in
44
+ `/usr/share/vice/C64/`; Debian's does not include them. VICE will refuse to start
45
+ without a valid `kernal`, `basic`, and `chargen` ROM.
46
+
47
+ ### Basic run
48
+
49
+ ```bash
50
+ # Load and auto-run a PRG directly
51
+ x64sc -autostart hello.prg
52
+
53
+ # Attach a D64 disk image and autostart the first file
54
+ x64sc -autostart mygame.d64
55
+
56
+ # Headless automated run: warp speed, quit after 5,000,000 cycles (about 5 s PAL), binary monitor on
57
+ x64sc -warp -limitcycles 5000000 -binarymonitor -binarymonitoraddress ip4://127.0.0.1:6502 \
58
+ -autostart hello.prg
59
+ ```
60
+
61
+ ---
62
+
63
+ ## Emulator Binaries
64
+
65
+ VICE ships multiple binaries, one per emulated machine.
66
+
67
+ | Binary | Machine emulated | Notes |
68
+ |--------|-----------------|-------|
69
+ | `x64sc` | Commodore 64 (cycle-accurate) | **Use this for all c64-kb work** |
70
+ | `x64` | Commodore 64 (fast) | Higher host performance; not cycle-accurate |
71
+ | `x128` | Commodore 128 | Out of scope for c64-kb |
72
+ | `xvic` | VIC-20 | Out of scope |
73
+ | `xpet` | PET series | Out of scope |
74
+ | `xplus4` | PLUS/4 | Out of scope |
75
+ | `xcbm2` | CBM-II | Out of scope |
76
+
77
+ `x64sc` uses a cycle-exact 6510/VIC-II core; both binaries offer true 1541 drive
78
+ emulation (an earlier version of this page credited it to `x64sc` alone). It is
79
+ slower than `x64` on the host but produces correct raster timing, correct CIA timer
80
+ behaviour, and correct SID timing — all of which matter when verifying demo or game
81
+ code. Always use `x64sc` for correctness. See the Pitfalls section for the consequences
82
+ of reaching for `x64` instead.
83
+
84
+ ---
85
+
86
+ ## CLI Flags
87
+
88
+ The table below covers flags relevant to build-and-test automation and basic operation.
89
+ VICE accepts many more; run `x64sc --help` for the full list.
90
+
91
+ | Flag | Argument | Effect |
92
+ |------|----------|--------|
93
+ | `-autostart <file>` | PRG, D64, T64, TAP, VSF | Load and RUN the named file or the first file on a disk/tape image; a `.vsf` is autodetected as a snapshot and restored (after the normal autostart delay — allow well over 3,000,000 cycles under `-limitcycles`) |
94
+ | `-binarymonitor` | — | Enable the TCP binary monitor |
95
+ | `-binarymonitoraddress <addr>` | `ip4://127.0.0.1:6502` | Monitor listen address and port |
96
+ | `-moncommands <file>` | path to text file | Execute text-monitor commands at startup (useful for loading labels) |
97
+ | `-warp` | — | Disable real-time throttle; run as fast as the host allows (`-help`: "Initially enable warp mode"; `+warp` is the default). The pinned run uses it so 8,000,000 cycles take seconds, not eight of them |
98
+ | `-limitcycles <n>` | cycles | Quit after n emulated cycles (985,248 per PAL second, 1,022,727 per NTSC second); VICE exits with a non-zero status when the limit fires (`-help`: "quitting with an error"), so a wrapper must not treat rc=1 alone as failure. The pinned run's exit point: the frame on screen when it fires is the one `-exitscreenshot` writes, so a recipe's cycle count is part of its identity |
99
+ | `-exitscreenshot <file>` | PNG path | Write the current frame to `<file>` when the emulator exits, including the `-limitcycles` exit. The only picture the verification protocol reads; the file is 384x272 RGBA on PAL and 384x247 on NTSC (see "Reading the exit screenshot" below) |
100
+ | `-autostartprgmode <n>` | 0, 1, 2 | How `-autostart file.prg` gets the PRG into memory (`-help`: "0: VirtualFS, 1: Inject, 2: Disk image"). 0 types `LOAD"HELLO.PRG",8,1` and expects VICE's host-directory device to answer; 1 writes the PRG into RAM once the KERNAL reaches `READY.` and types `RUN`; 2 puts the file on a disk image and loads it through the emulated drive as `LOAD"HELLO",8,1`. The protocol pins 1: it is the fastest, and under `-default` mode 0 never ran the program at all; measurements below |
101
+ | `-default` | — | "Restore default settings": start from VICE's built-in configuration rather than whatever the user last saved, so a run on another machine starts from the same settings. Without it a saved palette, model or drive setting would change the picture (the effect of a saved settings file was not measured here) |
102
+ | `+sound` | — | "Disable sound playback". No audio device is opened, so a headless run cannot stall or fail on the host's audio stack; SID emulation itself still runs |
103
+ | `+autostart-delay-random` | — | "Disable random initial autostart delay". VICE otherwise adds a random delay before autostart, so the same `-limitcycles` would land on a different frame each run; with it off the exit screenshot is reproducible pixel for pixel |
104
+ | `-console` | — | "Console mode (for music playback)": the flag under which this page's option names were confirmed (`x64sc -default -console`). The pinned run does not use it; every screenshot cited on this page was produced without it, and whether it changes the screenshot was not measured here |
105
+ | `-pal` | — | Force PAL machine model |
106
+ | `-ntsc` | — | Force NTSC machine model |
107
+ | `-model <name>` | `c64`, `c64c`, `c64old`, `ntsc`, `newntsc`, `oldntsc`, `drean`, `jap`, `c64gs`, `pet64`, `ultimax` | Select machine sub-model (list from `x64sc -help`; there is no `pal` value). With no `-model`, `-default` runs the `c64c` configuration: VIC-II 8565, SID 8580, CIA 8521 (`x64sc -default -dumpconfig` gives VICIIModel=1, SidModel=1, CIA1Model=1, identical to `-model c64c`; `-model c64` gives 0, 0, 0, the 6569, 6581 and 6526). An earlier version of this row said the default was the PAL 6569 `c64`; `recipes/kickassembler/cia-revision-detect.md` reads the new CIA on the default machine and the old one on `-model c64`, which settles it (measured 2026-09-23). Both PAL parts run 312 lines of 63 cycles. Decision (#36): the harness keeps this default. Every runs.json `pal` run and PAL screenshot is the C64C, and pages name it "PAL c64c (8565/8580/8521)"; add `-model c64` (6569, 6581, 6526) to check a listing on the older machine, which differs in the CIA timer interrupt (one cycle later on the 6526; `cia-revision-detect` reads `12 11` there and `10 11` on the default), the SID filter and `$D418` digis (not measured here), and eleven palette entries. The protocol's second run adds `-model ntsc` for the 6567R8 (with a 6581 and a 6526); that changes the frame height, the timing and eleven of the sixteen palette entries |
108
+ | `-drive8type <n>` | 1541, 1571, … | Drive type for device 8 |
109
+ | `-8 <file>` | D64, G64, … | Attach disk image to device 8 (`-help`: "Attach <name> as a disk image in unit #8"). A recipe whose `runs.json` entry carries `"disk": {"name": "TEST,01"}` gets a D64 freshly formatted with `c1541 -format "test,01" d64` attached this way before every run, so the program always sees the same empty disk |
110
+ | `-1 <file>` | T64, TAP | Attach a tape image to the datasette (unit 1) |
111
+ | `-soundvolume <n>` | 0–100 | Audio output level (0 = mute) |
112
+ | `-keymap <n>` | 0 symbolic, 1 positional, 2/3 user files | Keymap type (default 0) |
113
+ | `-keyboardmapping <n>` | 0 = US, other values select other host layouts | Host keyboard layout used to pick the `.vkm` file |
114
+ | `-cartcrt <file>` | CRT | Attach a cartridge image |
115
+ | `+cart` | — | Disable cartridge (note: plus sign, not minus) |
116
+
117
+ Flags that begin with `+` instead of `-` are boolean toggles that explicitly turn a
118
+ feature off; their `-` counterparts turn it on.
119
+
120
+ An earlier revision of this page listed `-quitafter <seconds>`, `-1541-8`,
121
+ `-tape1 <file>`, `-snapshot <file>` and `-keyboard <layout>`; x64sc 3.10 has none of
122
+ them and rejects each as an unknown (or, for `-keyboard`, ambiguous) option, aborting
123
+ startup. The rows above hold the real names (measured with `x64sc -default -console`).
124
+
125
+ Every flag in the table was checked again on 2026-09-22 against the output of
126
+ `x64sc -help` from the Homebrew VICE 3.10 on this machine (1,929 lines); the quoted
127
+ phrases in the table are that output's own wording. The ten flags the pinned
128
+ verification run uses (`-default -warp +sound +autostart-delay-random
129
+ -autostartprgmode 1 -limitcycles N [-model ntsc] [-8 disk.d64] -exitscreenshot
130
+ out.png -autostart out.prg`) all appear in it under exactly those names.
131
+
132
+ ### What `-autostartprgmode` does to a run
133
+
134
+ Measured with the committed `docs/recipes/kickassembler/hello-world.md` listing
135
+ (assembled with KickAssembler 5.25, 44-byte PRG), the pinned command with
136
+ `GSETTINGS_SCHEMA_DIR` set, PAL, one run per cell, decoding the screenshot's text
137
+ cells against the character ROM. A PNG was written in all fourteen runs and every run
138
+ exited with status 1, which is the `-limitcycles` exit, not a failure.
139
+
140
+ | Mode | 2,000,000 | 2,500,000 | 3,000,000 | 3,500,000 to 4,500,000 | 5,000,000 | 5,500,000 to 8,000,000 |
141
+ |---|---|---|---|---|---|---|
142
+ | 1 Inject | all-black frame | `READY.` only | `RUN` / `HELLO, WORLD!` / `READY.` | not run | not run | not run |
143
+ | 0 VirtualFS | not run | not run | `LOAD"HELLO.PRG",8,1` typed | `SEARCHING FOR HELLO.PRG` | not run | `?FILE NOT FOUND ERROR` at 6,000,000 and 8,000,000 |
144
+ | 2 Disk image | not run | not run | `LOAD"HELLO",8,1` typed | 4,500,000: all-black frame | `SEARCHING` / `LOADING` / `READY.` / `RUN` / `HELLO, WORLD!` / `READY.` | same as 5,000,000 |
145
+
146
+ So the smallest `-limitcycles`, to the nearest 500,000, at which the program's
147
+ output is on screen is **3,000,000 for mode 1** and **5,000,000 for mode 2**; under
148
+ `-default` **mode 0 never shows it**: the typed `LOAD` ends in
149
+ `?FILE NOT FOUND ERROR`. The likely reason is that `-default` turns true drive
150
+ emulation on, so unit 8 is an empty 1541 and the host-directory device never
151
+ answers; that is an inference, since no run was made with `+drive8truedrive` or a
152
+ virtual device enabled, and whether mode 0 works under some other configuration
153
+ was not measured here. Two runs produced a frame in which every one of the 104,448 pixels is
154
+ (0, 0, 0), border included: mode 1 at 2,000,000 and mode 2 at 4,500,000. The cause
155
+ was not established. A machine reset would blank the border like this (the VIC-II
156
+ registers read zero after reset), but the mode 2 run at 5,000,000 shows the whole
157
+ load already finished, which a reset at 4,500,000 does not leave time for. Treat an
158
+ all-black exit screenshot as a cycle count that landed somewhere the frame was not
159
+ drawn, not as evidence about the program; move `-limitcycles` and look again.
160
+
161
+ ---
162
+
163
+ ## The Binary Monitor Protocol
164
+
165
+ VICE exposes a binary remote monitor over TCP when started with `-binarymonitor`. The
166
+ default address is `ip4://127.0.0.1:6502`. The port number is a deliberate nod to the
167
+ 6502 processor.
168
+
169
+ ### Enabling the monitor
170
+
171
+ ```bash
172
+ x64sc -binarymonitor -binarymonitoraddress ip4://127.0.0.1:6502 -autostart hello.prg
173
+ ```
174
+
175
+ Once VICE is running, any TCP client can connect and send commands.
176
+
177
+ ### Frame format
178
+
179
+ Every message — command or response — shares a common wire layout:
180
+
181
+ **Request frame**
182
+
183
+ | Offset | Length | Field |
184
+ |--------|--------|-------|
185
+ | 0 | 1 | STX marker: `0x02` |
186
+ | 1 | 1 | API version: `0x02` |
187
+ | 2–5 | 4 | Payload length (little-endian, header excluded) |
188
+ | 6–9 | 4 | Request ID (little-endian, caller-chosen) |
189
+ | 10 | 1 | Command opcode |
190
+ | 11+ | varies | Command body |
191
+
192
+ **Response frame**
193
+
194
+ | Offset | Length | Field |
195
+ |--------|--------|-------|
196
+ | 0 | 1 | STX marker: `0x02` |
197
+ | 1 | 1 | API version: `0x02` |
198
+ | 2–5 | 4 | Body length (little-endian) |
199
+ | 6 | 1 | Response type |
200
+ | 7 | 1 | Error code |
201
+ | 8–11 | 4 | Request ID (`0xffffffff` = event-triggered) |
202
+ | 12+ | varies | Response body |
203
+
204
+ Error code `0x00` means success. Other codes: `0x01` object not found, `0x02` invalid
205
+ memspace, `0x80` incorrect command length, `0x81` invalid parameter, `0x82` API
206
+ version unsupported, `0x83` unknown command, `0x8f` general failure.
207
+
208
+ ### Command opcode table
209
+
210
+ | Opcode | Name | Description |
211
+ |--------|------|-------------|
212
+ | `0x01` | Memory Get | Read bytes from an address range |
213
+ | `0x02` | Memory Set | Write bytes to an address range |
214
+ | `0x11` | Checkpoint Get | Retrieve details of a checkpoint |
215
+ | `0x12` | Checkpoint Set | Create a breakpoint or watchpoint |
216
+ | `0x13` | Checkpoint Delete | Remove a checkpoint |
217
+ | `0x14` | Checkpoint List | Enumerate all checkpoints |
218
+ | `0x15` | Checkpoint Toggle | Enable or disable a checkpoint |
219
+ | `0x22` | Condition Set | Attach a condition expression to a checkpoint |
220
+ | `0x31` | Registers Get | Read current CPU register values |
221
+ | `0x32` | Registers Set | Write CPU register values |
222
+ | `0x41` | Dump | Save machine state to a VSF snapshot file |
223
+ | `0x42` | Undump | Restore machine state from a VSF snapshot file |
224
+ | `0x51` | Resource Get | Read an emulator resource/setting |
225
+ | `0x52` | Resource Set | Write an emulator resource/setting |
226
+ | `0x71` | Advance Instructions | Step over N instructions |
227
+ | `0x72` | Keyboard Feed | Inject PETSCII text into the keyboard buffer |
228
+ | `0x73` | Execute Until Return | Run until the next RTS or RTI |
229
+ | `0x81` | Ping | Connectivity test (echoes request ID) |
230
+ | `0x82` | Banks Available | List available memory banks |
231
+ | `0x83` | Registers Available | List register names and IDs |
232
+ | `0x84` | Display Get | Capture current screen buffer as pixel data |
233
+ | `0x85` | VICE Info | Return version and build information |
234
+ | `0x86` | CPU History | Return instruction execution history |
235
+ | `0x91` | Palette Get | Fetch the current color palette |
236
+ | `0xa2` | Joyport Set | Simulate joystick input |
237
+ | `0xb2` | Userport Set | Simulate user-port input |
238
+ | `0xaa` | Exit | Resume execution (release the monitor) |
239
+ | `0xbb` | Quit | Terminate VICE |
240
+ | `0xcc` | Reset | Soft or hard reset the machine or a drive |
241
+ | `0xdd` | Autostart | Load and execute a named file |
242
+
243
+ All multi-byte fields in command bodies use little-endian byte order. The memspace
244
+ parameter in memory and checkpoint commands takes `0x00` for the main C64 address space
245
+ and `0x01`–`0x04` for drives 8–11 respectively.
246
+
247
+ **Important:** agents should not drive this protocol directly. The vice-mcp server
248
+ wraps the protocol in a clean MCP tool surface; see
249
+ [vice-mcp-reference.md](vice-mcp-reference.md) for the agent-facing API.
250
+
251
+ ---
252
+
253
+ ## Disk and Tape Handling
254
+
255
+ VICE attaches disk and tape images as virtual peripheral devices. Device 8 is the
256
+ primary disk drive (1541 by default). The relevant attachment flags are `-8 <file>` for
257
+ disk images and `-1 <file>` for tape images. `-autostart` can also accept a
258
+ disk or tape image path directly and will load the first file.
259
+
260
+ ### .D64 — Single-sided 35-track 1541 disk image
261
+
262
+ The standard 1541 disk image format. A D64 file contains 35 tracks of raw sector data.
263
+ Sector count varies by zone: tracks 1–17 carry 21 sectors each, tracks 18–24 carry 19
264
+ sectors each, tracks 25–30 carry 18 each, and tracks 31–35 carry 17 each — 683 sectors
265
+ total. Each sector is 256 bytes, giving a total image size of 174,848 bytes (or 175,531
266
+ bytes with the optional per-sector error-code extension). Track 18 / sector 0 holds the
267
+ BAM (Block Availability Map) and disk name; the directory occupies track 18 sectors 1–18
268
+ and supports up to 144 file entries.
269
+
270
+ **Produced by:** c1541
271
+ **Consumed by:** vice
272
+
273
+ D64 is the go-to format for distributing finished software. It cannot represent
274
+ non-standard track layouts or copy-protection schemes; for those cases use G64.
275
+
276
+ ### .G64 — GCR-encoded 1541 disk image
277
+
278
+ G64 stores raw GCR (Group Code Recording) bitstream data — the actual flux transitions
279
+ the 1541 read head would encounter. The format supports up to 84 track slots (42 full
280
+ tracks plus 42 half-tracks), though typical 1541 media uses only 35. Because the
281
+ bitstream is preserved verbatim, G64 can represent disks with non-standard sector
282
+ interleavings, custom loaders, weak bits, and copy-protection schemes that D64 cannot
283
+ encode. Track size varies by zone, with outer tracks holding more GCR bytes than inner
284
+ tracks (approximately 7,692 bytes for tracks 1–17 down to around 6,250 bytes for track
285
+ 31+).
286
+
287
+ **Produced by:** c1541
288
+ **Consumed by:** vice
289
+
290
+ Use G64 when the software relies on a non-standard 1541 format, or when a D64 round-trip
291
+ loses copy-protection data you need to preserve for testing.
292
+
293
+ ### .T64 — Tape archive (PRG container)
294
+
295
+ T64 is a container format created for the C64s emulator. It stores one or more PRG
296
+ files in a simple 32-byte-aligned directory structure: a 64-byte file header (signature
297
+ + tape version + directory capacity + tape name), followed by 32-byte directory entries
298
+ (file type, load address, end address, data offset, filename in PETSCII), followed by
299
+ the raw file data. T64 is not a raw tape recording — it is closer to a ZIP file for
300
+ PRGs. It has no concept of tape timing or loader protocol. `c1541` can only read a T64
301
+ (its `tape` command extracts files from one); it does not write them.
302
+
303
+ **Consumed by:** vice
304
+
305
+ T64 is a convenient way to ship a single PRG for distribution via "tape" when accurate
306
+ tape timing is not required. For raw pulse-level fidelity use TAP.
307
+
308
+ ### .TAP — Raw tape pulse-width data
309
+
310
+ TAP stores the cassette signal as a sequence of bytes, each representing the time (in
311
+ hardware counter units) between successive signal transitions — the literal pulse widths
312
+ the C64 CIA timer measured. A 20-byte file header carries the signature `C64-TAPE-RAW`,
313
+ a version byte, three reserved bytes, and a 4-byte little-endian data-area size (the
314
+ length excludes the header). Version 0 encodes
315
+ each pulse as `period = (8 × byte) / 985248` seconds; a `0x00` byte signals an
316
+ overflow. Version 1 reuses `0x00` as an escape: three following bytes give the actual
317
+ cycle count for long pulses. TAP files are typically 8–16 times larger than the
318
+ equivalent PRG data because each source bit expands to one pulse-width byte.
319
+
320
+ **Produced by:** tapclk, mtap
321
+ **Consumed by:** vice
322
+
323
+ TAP is required when the software uses a custom tape loader that relies on pulse timing,
324
+ such as Turbo Tape or commercial fast loaders. For simple PRG distribution, T64 is
325
+ smaller and easier to work with.
326
+
327
+ ### The c1541 companion utility
328
+
329
+ `c1541` is a standalone command-line disk-image maintenance tool shipped with VICE. It
330
+ can create D64 and G64 images, list and extract files, write PRG files into a disk
331
+ image, validate the BAM, inspect block chains, and perform low-level block operations
332
+ (peek, poke, fill). It supports batch mode — prefix commands with `-` to chain them
333
+ non-interactively — and interactive mode with tab completion.
334
+
335
+ ```bash
336
+ # Create a fresh D64 and write a PRG into it
337
+ c1541 -format "mygame,01" d64 mygame.d64
338
+ c1541 -attach mygame.d64 -write hello.prg hello
339
+ ```
340
+
341
+ `c1541` is the right tool for assembling a releasable disk image from one or more
342
+ compiled PRG files before handing the D64 to VICE for a run.
343
+
344
+ ---
345
+
346
+ ## Symbol Files
347
+
348
+ The VICE text monitor (launched interactively or via `-moncommands`) can load symbol
349
+ tables that map label names to addresses. Two formats are relevant:
350
+
351
+ | Format | Extension | Produced by | Example entry |
352
+ |--------|-----------|-------------|---------------|
353
+ | Oscar64 label file | `.lbl` | oscar64 (written alongside the `.prg` by default; there is no flag, and `-l` is rejected) | `al 0880 .main` |
354
+ | KickAssembler vice symbol file | `.vs` | KickAssembler (`-vicesymbols`) | `al C:1000 .main` |
355
+ | cc65 VICE label file | any (`.lbl` by convention) | ld65 via `cl65 -Ln name` | `al 000840 ._main` |
356
+
357
+ Oscar64 entries carry a bare 4-digit hex address with no `C:` memspace prefix
358
+ (`al HHHH .name`, as [../formats/c64-file-formats.md](../formats/c64-file-formats.md)
359
+ describes); KickAssembler's `-vicesymbols` output uses `al C:HHHH .name`. The VICE
360
+ monitor accepts both, and `break .main` works after `ll` either way. An earlier version
361
+ of this table gave Oscar64 a `-l` flag and a `C:` prefix; neither exists. cc65's
362
+ `-Ln` file uses six hex digits, no prefix, and a leading underscore on every C
363
+ symbol (`_main`, `_cputs`); it also lists the KERNAL names the library imports
364
+ (`al 00FFD2 .BSOUT`). `break ._main` after `ll` stopped at `$0840` (measured,
365
+ cc65 V2.18, VICE 3.10; the session is in
366
+ [../toolchains/cc65-reference.md](../toolchains/cc65-reference.md)).
367
+
368
+ Load a symbol file in the monitor with:
369
+
370
+ ```
371
+ ll "build/hello.lbl"
372
+ ```
373
+
374
+ Once loaded, the disassembler, breakpoint expressions, and memory commands can use label
375
+ names instead of raw hex addresses. This makes monitor sessions with `vice-mcp` far more
376
+ readable. Load symbols at startup by putting the `ll` command in a file and passing it
377
+ via `-moncommands`.
378
+
379
+ ---
380
+
381
+ ## Snapshots
382
+
383
+ VICE can save and restore complete machine state using the `.vsf` (VICE Snapshot File)
384
+ format. A snapshot captures RAM, ROM shadow, CPU registers, CIA state, VIC-II state,
385
+ SID state, and optional drive state. ROM images are not embedded in the snapshot.
386
+ The file's layout, decoded from a snapshot the windowless x64sc 3.10 wrote (header,
387
+ module list, and where the 64 KiB RAM, the processor port and colour RAM sit inside
388
+ `C64MEM` and `VIC-II`), is the `.VSF` section of
389
+ [../formats/c64-file-formats.md](../formats/c64-file-formats.md).
390
+
391
+ Save from the text monitor:
392
+
393
+ ```
394
+ dump "checkpoint.vsf"
395
+ ```
396
+
397
+ Restore:
398
+
399
+ ```
400
+ undump "checkpoint.vsf"
401
+ ```
402
+
403
+ To restore at startup, either pass the snapshot to `-autostart file.vsf` (restored after
404
+ the autostart delay) or put `undump "file.vsf"` in a `-moncommands` file (restored
405
+ immediately, before the first instruction). There is no `-snapshot` option; an earlier
406
+ version of this page listed one, and x64sc 3.10 rejects it as unknown.
407
+
408
+ Via the binary monitor, `Dump` (opcode `0x41`) and `Undump` (opcode `0x42`) provide the
409
+ same capability programmatically. vice-mcp exposes both operations as MCP tools.
410
+
411
+ Snapshots are useful for reproducible automated testing: run to a known program counter,
412
+ save a snapshot, then restore it at the start of each test run to eliminate variable
413
+ boot-time state.
414
+
415
+ ---
416
+
417
+ ## Region Selection
418
+
419
+ VICE supports both PAL and NTSC machine configurations. The difference is significant
420
+ for cycle-accurate timing work: PAL machines run at 985,248 cycles/second with 312 scan
421
+ lines per frame (50 Hz), while NTSC machines run at 1,022,727 cycles/second with 263
422
+ scan lines per frame (60 Hz). Raster positions, raster IRQ timing, and the number of
423
+ cycles available per frame differ between regions.
424
+
425
+ Select the region at launch:
426
+
427
+ ```bash
428
+ x64sc -pal -autostart demo.prg # PAL
429
+ x64sc -ntsc -autostart demo.prg # NTSC
430
+ ```
431
+
432
+ The compiled-in default is a PAL C64 (MachineVideoStandard=1, VICIIModel=1; measured on
433
+ x64sc 3.10 with `-default -dumpconfig`, unchanged under en_US, de_DE, ja_JP and C
434
+ locales — the locale moves the keyboard mapping, not the video standard). A saved config
435
+ file (vicerc) can override it, and `-default` bypasses that file, so pass `-pal`, `-ntsc`
436
+ or `-model` explicitly in automated runs. An earlier version of this sentence said the
437
+ default depended on the system locale; it does not. If a program behaves differently
438
+ under PAL vs NTSC, a raster timing assumption is almost always the cause.
439
+
440
+ For a full treatment of the hardware differences between PAL and NTSC C64 variants, see
441
+ [../hardware/pal-ntsc-reference.md](../hardware/pal-ntsc-reference.md).
442
+
443
+ ---
444
+
445
+ ## Headless and Automated Invocation
446
+
447
+ An agent (or CI script) running VICE in a build-verify loop wants no GUI, maximum
448
+ speed, and deterministic exit. The pattern is:
449
+
450
+ 1. Compile the PRG with oscar64or KickAssembler.
451
+ 2. Launch `x64sc` in warp mode with a binary monitor and a short timeout.
452
+ 3. Connect via vice-mcp (or a raw TCP client) to set a checkpoint at the expected
453
+ success address.
454
+ 4. Autostart the PRG; wait for the checkpoint or for the timeout to fire.
455
+ 5. Optionally capture a screenshot via the `Display Get` (`0x84`) command.
456
+ 6. Inspect result state; quit VICE via the `Quit` (`0xbb`) command or let
457
+ `-limitcycles` terminate it.
458
+
459
+ Minimal headless invocation:
460
+
461
+ ```bash
462
+ x64sc \
463
+ -warp \
464
+ -limitcycles 10000000 \
465
+ -binarymonitor \
466
+ -binarymonitoraddress ip4://127.0.0.1:6502 \
467
+ -moncommands monitor-init.mon \
468
+ -pal \
469
+ -soundvolume 0 \
470
+ -autostart hello.prg
471
+ ```
472
+
473
+ `monitor-init.mon` might contain:
474
+
475
+ ```
476
+ ll "build/hello.lbl"
477
+ break .success
478
+ ```
479
+
480
+ so that vice-mcp can detect the breakpoint hit via a Checkpoint event response
481
+ (request ID `0xffffffff`).
482
+
483
+ For screenshot capture without user interaction, `Display Get` (`0x84`) returns raw
484
+ pixel data for the current frame. This lets an agent record what the screen looks like
485
+ at a given execution point without requiring a visible window.
486
+
487
+ On Linux CI, add `Xvfb` or set `SDL_VIDEODRIVER=offscreen` (SDL2 build) to suppress the
488
+ display requirement.
489
+
490
+ ---
491
+
492
+ ## Reading the exit screenshot
493
+
494
+ `-exitscreenshot` writes an 8-bit RGBA PNG (IHDR colour type 6, no interlace) of the
495
+ whole frame including borders. Everything below was measured on 2026-09-22 from the
496
+ two pictures of `docs/recipes/kickassembler/palette-cells.md` and the fourteen
497
+ `hello-world` runs above, all VICE x64sc 3.10 with `-default`.
498
+
499
+ The picture is the draw buffer at the cycle the limit hits, not a finished
500
+ frame: the rows the beam has passed in the current field are new and the
501
+ rows below it still hold the previous field. Measured 2026-09-23 on the
502
+ eight-way scroll recipe while its pin was chosen: cycle limits from
503
+ 21,000,000 to 21,014,500 gave one identical picture, 21,017,000 differed
504
+ from it only in rows 39 to 59, and 21,019,500 only in rows 59 to 98. So a
505
+ program that changes what a row shows from one field to the next can be
506
+ caught half-way by a pin that lands mid-display, and the split reads as
507
+ a fault in the program. Pin in the blank, or where consecutive fields
508
+ draw the same thing, and say which on the page.
509
+
510
+ ### Geometry
511
+
512
+ | | PAL (default `c64`) | NTSC (`-model ntsc`) |
513
+ |---|---|---|
514
+ | PNG size | 384 x 272 | 384 x 247 |
515
+ | Display rows (y) | 35 to 234 | 23 to 222 |
516
+ | Display columns (x) | 32 to 351 | 32 to 351 |
517
+ | Screenshot row from raster line | y = line - 16 | y = line - 28 |
518
+ | Border sample point | (2, 100) | (2, 100) |
519
+
520
+ The display bounds are the first and last row and column whose pixel is not the
521
+ border colour, read off the palette pictures; they agree with the bounds
522
+ `docs/pitfalls/cia.md` measured independently for its tenths-of-a-second probe. The
523
+ line offsets are `CLAUDE.md`'s figures, derived from three boundaries in
524
+ `docs/recipes/kickassembler/topbottom-border-open.md`; they were not re-measured here.
525
+ `x = 8` is VIC-II X coordinate 0 (same source, not re-measured).
526
+
527
+ A text cell is 8 x 8 pixels. Screen row `r` (0 to 24) and column `c` (0 to 39) sit
528
+ at
529
+
530
+ ```
531
+ x = 32 + 8 * c
532
+ y = 35 + 8 * r # PAL
533
+ y = 23 + 8 * r # NTSC
534
+ ```
535
+
536
+ so the centre of a cell is `(x + 4, y + 4)`, which is the safe place to sample a
537
+ colour. Any pixel in the left border (x 0 to 31) reads the border colour; (2, 100)
538
+ is used throughout the KB because it is inside the display's vertical range on both
539
+ models, well clear of the corner. `hello-world`'s `HELLO, WORLD!` at screen row 7 is
540
+ at y 91 to 98 on PAL: the decoder below finds it there, which is the check that the
541
+ arithmetic is right.
542
+
543
+ ### The default palette
544
+
545
+ With `-default` VICE 3.10 uses its internally generated palette, not one of the
546
+ `.vpl` files in its data directory: the sixteen triples below match none of the
547
+ 27 files installed under `/opt/homebrew/opt/vice/share/vice/C64/`, compared entry
548
+ for entry. The triples come from the palette recipe, one solid 32-cell band per
549
+ colour index, all 2,048 pixels of each band identical.
550
+
551
+ | Index | PAL RGB | NTSC RGB | Index | PAL RGB | NTSC RGB |
552
+ |---|---|---|---|---|---|
553
+ | 0 | (0, 0, 0) | (0, 0, 0) | 8 | (183, 99, 30) | (196, 98, 65) |
554
+ | 1 | (255, 255, 255) | (255, 255, 255) | 9 | (119, 83, 0) | (151, 64, 0) |
555
+ | 2 | (175, 60, 88) | (169, 71, 100) | 10 | (238, 123, 149) | (230, 134, 163) |
556
+ | 3 | (126, 243, 214) | (138, 230, 203) | 11 | (98, 98, 98) | (98, 98, 98) |
557
+ | 4 | (170, 64, 245) | (154, 88, 185) | 12 | (148, 148, 148) | (148, 148, 148) |
558
+ | 5 | (98, 213, 50) | (114, 189, 103) | 13 | (183, 255, 134) | (198, 255, 186) |
559
+ | 6 | (44, 61, 236) | (25, 73, 180) | 14 | (115, 133, 255) | (98, 145, 251) |
560
+ | 7 | (255, 255, 70) | (255, 248, 141) | 15 | (205, 205, 205) | (205, 205, 205) |
561
+
562
+ The PAL column is the default machine, the `c64c` (8565) configuration, not
563
+ the 6569. Under `-model c64` (6569) indices 0, 1, 11, 12 and 15 match the
564
+ default's and the other eleven differ. Measured 2026-09-23 from the
565
+ `palette-cells` listing run with `-model c64`, one triple per band (each band
566
+ uniform); its default run matched the committed PNG pixel for pixel:
567
+
568
+ | Index | `-model c64` | Index | `-model c64` |
569
+ |---|---|---|---|
570
+ | 2 | (171, 60, 101) | 8 | (183, 100, 24) |
571
+ | 3 | (135, 240, 203) | 9 | (129, 76, 0) |
572
+ | 4 | (178, 61, 239) | 10 | (234, 121, 163) |
573
+ | 5 | (94, 214, 56) | 13 | (178, 255, 141) |
574
+ | 6 | (58, 49, 255) | 14 | (129, 120, 255) |
575
+ | 7 | (255, 255, 59) | | |
576
+
577
+ An earlier version of this section did not say which PAL chip the column
578
+ was, and the next one compared index 5 only.
579
+
580
+ Indices 0, 1, 11, 12 and 15 are the same on both models; the other eleven differ,
581
+ so a script that recognises colours by exact triple needs a table per model. The
582
+ power-on screen is index 6 on index 14: PAL (44, 61, 236) text area, (115, 133, 255)
583
+ border, as every `hello-world` run above shows. A screenshot taken with a user
584
+ configuration, another VICE version or `-VICIIextpal` will not match this table;
585
+ run the palette recipe on that setup first.
586
+
587
+ ### Decoding with PIL
588
+
589
+ ```python
590
+ from PIL import Image
591
+ im = Image.open('out.png').convert('RGB')
592
+ px = im.load()
593
+ w, h = im.size # (384, 272) PAL, (384, 247) NTSC
594
+ y0 = 35 if h == 272 else 23
595
+ border = px[2, 100]
596
+ def cell_colour(row, col): # centre pixel of a text cell
597
+ return px[32 + 8*col + 4, y0 + 8*row + 4]
598
+ ```
599
+
600
+ To read text, compare each cell's 8 x 8 pattern with the character ROM. Take the
601
+ text area's most common colour as background; a pixel is "ink" if it differs from
602
+ it. Each glyph in `chargen-901225-01.bin` is eight bytes, bit 7 the leftmost pixel;
603
+ the first 2 KiB is the upper-case/graphics set the machine powers on with, codes 0
604
+ to 255. Codes 128 to 255 are the reversed forms, stored as separate glyphs: 127 of
605
+ them are the exact complement of code - 128, and one is not. Reversed `@` (code 128)
606
+ has row 6 as `$99` where the complement of `@`'s `$62` would be `$9D`, one pixel
607
+ different (ROM bytes read on this machine; the lower-case set at offset 2048 has the
608
+ same single exception). Build the lookup from the ROM bytes, not from complementing,
609
+ and match the packed rows:
610
+
611
+ ```python
612
+ rom = open('/opt/homebrew/opt/vice/share/vice/C64/chargen-901225-01.bin', 'rb').read()
613
+ glyph = {}
614
+ for code in range(256):
615
+ glyph.setdefault(tuple(rom[code*8:code*8+8]), code) # first code wins: $20 for blank, not $60
616
+ def cell_code(row, col, bg):
617
+ return glyph.get(tuple(
618
+ sum((px[32 + 8*col + xx, y0 + 8*row + yy] != bg) << (7 - xx) for xx in range(8))
619
+ for yy in range(8)))
620
+ ```
621
+
622
+ Screen codes 1 to 26 are `A` to `Z`, `$20` to `$3F` are space, punctuation and
623
+ digits as in ASCII, 0 is `@`. Two blank glyphs share the all-zero pattern (`$20`
624
+ space and `$60` shifted space); `setdefault` keeps the lower code. Reversed text
625
+ comes back as code + 128 because the ROM holds those forms; mask with `& 0x7f` to
626
+ get the character, and note the palette recipe's solid bands are `$A0`, reversed
627
+ space. A cell whose pattern is not in the table returns `None`: a sprite, a custom
628
+ character set, a colour that happens to equal the background, or a screenshot taken
629
+ mid-frame with two frames' contents in it.
630
+
631
+ ### Decoding without PIL
632
+
633
+ The PNG is small enough to decode in pure Python. Concatenate the `IDAT` chunks,
634
+ `zlib.decompress` them, and undo the per-row filter byte (0 none, 1 Sub, 2 Up,
635
+ 3 Average, 4 Paeth; the two palette PNGs use 1, 2 and 4). Each row is one filter
636
+ byte followed by `384 * 4` bytes of RGBA. A 40-line implementation of that on this
637
+ machine returned the same border pixel and the same sixteen triples as PIL from
638
+ both palette pictures. Ignore the alpha byte; every pixel VICE wrote had it at 255
639
+ in the pictures checked, but nothing here depends on that.
640
+
641
+ ---
642
+
643
+ ## Verifying a run without a human
644
+
645
+ A test program can grade itself and leave the verdict where a script can
646
+ read it. The pattern, and three routes for reading it back, were measured
647
+ on 2026-09-22 with VICE x64sc 3.10 `-default` and the two `headless-verify`
648
+ recipes (`docs/recipes/kickassembler/headless-verify.md`,
649
+ `docs/recipes/oscar64/headless-verify.md`). Every exit code quoted below
650
+ came from a run on this machine.
651
+
652
+ ### The result-byte contract
653
+
654
+ The program does its computation, then, at one checkpoint and in this
655
+ order:
656
+
657
+ 1. stores a result code at `$02FF`: `$01` pass, `$02` fail;
658
+ 2. sets the border (`$D020`) to 5 (green) on pass or 2 (red) on fail;
659
+ 3. prints the code and returns to BASIC.
660
+
661
+ `$02FF` is the last byte of the KERNAL's unused `$02A7`-`$02FF`
662
+ (`docs/hardware/c64-memory-map.md`); BASIC does not touch it after the
663
+ program returns, so the exit screenshot and a late memory read see the
664
+ same value. It is not untouched before the program runs: the KERNAL reset
665
+ clears page 2 (`STA $0200,Y` at `$FD56`, `A = 0`, cycle 5305 in the
666
+ monitor log), so `$02FF` is `00` when the program starts and a store
667
+ watchpoint on it fires once at boot. Codes therefore start at `01`, and a
668
+ harness that reads `00` has a program that never reached its checkpoint,
669
+ which is a different failure from `02`.
670
+
671
+ The harness returns the verdict as a shell exit code: 0 pass, 1 fail,
672
+ 2 no verdict. `x64sc`'s own exit status was 1 on every `-limitcycles` run
673
+ made for this section, pass or fail; it carries nothing.
674
+
675
+ ### Route 1: the exit screenshot
676
+
677
+ No monitor, no second process: run the pinned command and read the border
678
+ pixel. The palette triples are the ones in "The default palette" above,
679
+ selected by the picture's height.
680
+
681
+ ```bash
682
+ #!/bin/bash
683
+ # usage: verdict_shot.sh prog.prg [pal|ntsc] exit 0 = PASS, 1 = FAIL, 2 = no verdict
684
+ prg=$1; model=${2:-pal}; shot=$(mktemp -t verdict).png
685
+ flags=""; [ "$model" = ntsc ] && flags="-model ntsc"
686
+ GSETTINGS_SCHEMA_DIR=/opt/homebrew/share/glib-2.0/schemas timeout 180 x64sc -default -warp +sound \
687
+ +autostart-delay-random -autostartprgmode 1 -limitcycles 8000000 $flags \
688
+ -exitscreenshot "$shot" -autostart "$prg" >/dev/null 2>&1
689
+ python3 - "$shot" <<'PY'
690
+ import sys
691
+ from PIL import Image
692
+ im = Image.open(sys.argv[1]).convert('RGB')
693
+ pal = im.size[1] == 272
694
+ green = (98, 213, 50) if pal else (114, 189, 103) # index 5
695
+ red = (175, 60, 88) if pal else (169, 71, 100) # index 2
696
+ border = im.getpixel((2, 100))
697
+ verdict = {green: 0, red: 1}.get(border, 2)
698
+ print('border', border, ['PASS', 'FAIL', 'NONE'][verdict])
699
+ sys.exit(verdict)
700
+ PY
701
+ ```
702
+
703
+ Measured: the KickAssembler recipe on PAL printed `border (98, 213, 50)
704
+ PASS` and exited 0; the Oscar64 recipe built with `FORCE_FAIL 1` (the
705
+ define is now `FORCE_FAULT`, set with `-dFORCE_FAULT=1`) on NTSC
706
+ printed `border (169, 71, 100) FAIL` and exited 1. The route reads only
707
+ the border, so it tells pass from fail from "still the power-on light
708
+ blue"; it cannot read the code itself. For that, decode row 7 with the
709
+ char ROM snippet above (`RESULT 01 PASS` or `RESULT 02 FAIL` in the
710
+ recipes), or use a machine route.
711
+
712
+ **Palette-safe grading by channel dominance.** The exact-triple test
713
+ above fails closed on any picture that did not come from `-default` on
714
+ this VICE version: a `.vpl` palette, another release, a capture from a
715
+ real machine. When the program paints only index 5 or index 2, grade by
716
+ which channel dominates instead:
717
+
718
+ ```python
719
+ def is_green(c): return c[1] > c[0] + 60 and c[1] > c[2] + 60
720
+ def is_red(c): return c[0] > c[1] + 60 and c[0] > c[2] + 60
721
+ verdict = 0 if is_green(border) else 1 if is_red(border) else 2
722
+ ```
723
+
724
+ Against the triples in "The default palette": PAL green (98, 213, 50) has
725
+ G over R by 115 and over B by 163; NTSC green (114, 189, 103) by 75 and
726
+ 86. PAL red (175, 60, 88) has R over G by 115 and over B by 87; NTSC red
727
+ (169, 71, 100) by 98 and 69. The power-on border, index 14, is neither on
728
+ either model. Any margin up to 68 accepts NTSC red, whose R exceeds B by
729
+ 69; sixty leaves a little room and was the value checked. Run over all
730
+ sixteen triples of both models
731
+ (arithmetic from the table), `is_green` also accepts index 13, light
732
+ green, on PAL (G over R by 72; on NTSC only by 57, so it is rejected
733
+ there), and `is_red` also accepts 8 and 10 on both models and 9 on NTSC.
734
+ Measured on the six exit screenshots of the Oscar64 `headless-verify`
735
+ recipe (default, `-dAUTOPILOT=1` and `-dFORCE_FAULT=1`, PAL and NTSC),
736
+ the dominance test and the exact-triple test gave the same verdict on
737
+ every one.
738
+
739
+ The exact triple remains the right test when the harness must tell the
740
+ pass shade from any other green, index 13 in particular, or red from
741
+ orange and light red; a program that uses those colours elsewhere on the
742
+ screen, or a bar that grades several things by shade, keeps the table
743
+ per model. It is also the test `npm run verify:recipes` implies, since
744
+ that compares whole pictures.
745
+
746
+ ### Route 2: the machine, over `-moncommands`
747
+
748
+ A `-moncommands` file runs at startup, before the program, so it cannot
749
+ simply dump `$02FF`. It can arm a tracepoint that dumps it when the store
750
+ happens, and log everything the monitor prints to a file:
751
+
752
+ ```
753
+ logname "/tmp/verdict.log"
754
+ log on
755
+ trace store 02ff
756
+ command 1 "m 02ff 02ff"
757
+ ```
758
+
759
+ `trace` does not stop the machine; `command 1` runs the memory dump each
760
+ time checkpoint 1 hits; `-limitcycles` still ends the run. The log from
761
+ the green KickAssembler build:
762
+
763
+ ```
764
+ #1 (Trace store 02ff) 84/$054, 13/$0d
765
+ .C:fd56 99 00 02 STA $0200,Y - A:00 X:FF Y:FF SP:fd N.-..I.C 5305
766
+ Executing: m 02ff 02ff
767
+ >C:02ff 00
768
+ #1 (Trace store 02ff) 129/$081, 2/$02
769
+ .C:086f 8D FF 02 STA $02FF - A:01 X:00 Y:05 SP:f6 ..-....C 2995841
770
+ Executing: m 02ff 02ff
771
+ >C:02ff 01
772
+ ```
773
+
774
+ The first hit is the reset clearing page 2; the second is the program.
775
+ The dump runs after the store: the value on the second hit is `01`, not
776
+ the `00` that was there before it. A harness takes the last `>C:02ff`
777
+ line:
778
+
779
+ ```bash
780
+ x64sc -default -warp +sound +autostart-delay-random -autostartprgmode 1 -limitcycles 8000000 \
781
+ -moncommands verdict.mon -autostart prog.prg >/dev/null 2>&1
782
+ code=$(grep '^>C:02ff' /tmp/verdict.log | tail -1 | awk '{print $2}')
783
+ case "$code" in 01) exit 0;; 02) exit 1;; *) exit 2;; esac
784
+ ```
785
+
786
+ ### A windowless build for batch runs
787
+
788
+ The GTK build opens a window on every launch and takes the desktop's focus,
789
+ which a verifier run of sixty recipes turns into a constant interruption;
790
+ `-minimized` does not help, the window still activates before it shrinks.
791
+ VICE 3.10 ships a third front end besides GTK and SDL: configure the
792
+ source with `--enable-headlessui` and the resulting `x64sc` has no window,
793
+ no Dock tile and never registers with the window server, while the exit
794
+ screenshot still works because it is taken from the emulated frame in the
795
+ machine core. Measured 2026-09-22 on macOS: the headless build's exit
796
+ screenshots for four pinned recipes, PAL and NTSC, were byte-identical to
797
+ the pins, and the process never appeared in LaunchServices while a GTK
798
+ instance next to it was listed as the frontmost application. Two things to
799
+ know: a build that is not installed needs `-directory <vice data dir>` and
800
+ it must come after `-default`, because `-default` resets the search path;
801
+ and the exit status on the cycle limit is 1 by design in both builds. The
802
+ build takes under a minute (`brew install dos2unix xa` first; a plain
803
+ top-level `make` succeeds where `make x64sc` races). In this repository `npm run vice:headless` builds one into `.tools/` with
804
+ the tarball digest pinned and a wrapper that inserts `-directory`, and every
805
+ emulator launch (the verifier, the run tool) prefers it when present, with
806
+ `X64SC_BIN` as an override; every command on this page runs unchanged under
807
+ it.
808
+
809
+ The red Oscar64 build logged `00` then `02` with this file. Do not use
810
+ `watch` or `break` here: a stopping checkpoint enters the monitor with
811
+ nothing to type `x`, cycles stop counting, `-limitcycles` never fires and
812
+ the run hangs. Measured: `watch store 02ff` with the same `command`
813
+ line sat until `timeout 180` killed it (exit 124) and the log was empty.
814
+ The `command` text is one monitor command; whether it can chain a
815
+ continue was not measured here.
816
+
817
+ ### Route 3: the machine, over the binary monitor
818
+
819
+ A Python client that speaks the frame format in "The Binary Monitor
820
+ Protocol" above. It sets a store watchpoint on `$02FF` first and only then
821
+ autostarts the program from the monitor, because a client that connects
822
+ to an already-autostarted VICE in warp mode is too late: a first version
823
+ that passed `-autostart` on the command line missed the store on every
824
+ run and reported no verdict. Each stop is handled the same way: read
825
+ `$02FF`; if it is `01` or `02` that is the verdict, otherwise resume.
826
+
827
+ ```python
828
+ #!/usr/bin/env python3
829
+ """Run a PRG in x64sc, watch $02FF over the binary monitor, exit 0 on PASS ($01), 1 on FAIL ($02), 2 otherwise."""
830
+ import socket, struct, subprocess, sys, time, os
831
+
832
+ PRG = sys.argv[1]
833
+ PORT = 6502
834
+ env = dict(os.environ, GSETTINGS_SCHEMA_DIR='/opt/homebrew/share/glib-2.0/schemas')
835
+ vice = subprocess.Popen(['x64sc', '-default', '-warp', '+sound', '+autostart-delay-random',
836
+ '-autostartprgmode', '1', '-limitcycles', '8000000',
837
+ '-binarymonitor', '-binarymonitoraddress', 'ip4://127.0.0.1:%d' % PORT],
838
+ env=env, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
839
+
840
+ def frame(op, body=b'', rid=1):
841
+ return b'\x02\x02' + struct.pack('<II', len(body), rid) + bytes([op]) + body
842
+
843
+ def recvn(s, n):
844
+ buf = b''
845
+ while len(buf) < n:
846
+ chunk = s.recv(n - len(buf))
847
+ if not chunk:
848
+ raise EOFError
849
+ buf += chunk
850
+ return buf
851
+
852
+ def response(s):
853
+ stx, api, blen, rtype, err, rid = struct.unpack('<BBIBBI', recvn(s, 12))
854
+ return rtype, err, rid, recvn(s, blen)
855
+
856
+ def wait_for(s, rtype, rid=None):
857
+ while True:
858
+ t, e, r, body = response(s)
859
+ if t == rtype and (rid is None or r == rid):
860
+ return e, body
861
+
862
+ s = None
863
+ for _ in range(100): # VICE takes a moment to open the port
864
+ try:
865
+ s = socket.create_connection(('127.0.0.1', PORT), timeout=1)
866
+ break
867
+ except OSError:
868
+ time.sleep(0.1)
869
+ if s is None:
870
+ sys.exit(2)
871
+ s.settimeout(30)
872
+
873
+ # Checkpoint Set (0x12): start, end, stop, enabled, operation (2 = store), temporary, memspace
874
+ s.sendall(frame(0x12, struct.pack('<HHBBBBB', 0x02ff, 0x02ff, 1, 1, 2, 0, 0), rid=10))
875
+ err, info = wait_for(s, 0x11, 10)
876
+ # Autostart (0xdd) only now, so the watchpoint is in place before the program runs:
877
+ # run after load, file index, filename length, filename
878
+ name = os.path.abspath(PRG).encode()
879
+ s.sendall(frame(0xdd, struct.pack('<BHB', 1, 0, len(name)) + name, rid=11))
880
+ err, _ = wait_for(s, 0xdd, 11)
881
+ verdict = 2
882
+ try:
883
+ while True:
884
+ e, body = wait_for(s, 0x62) # Stopped event: body is the PC
885
+ pc = struct.unpack('<H', body[:2])[0]
886
+ # Memory Get (0x01): side effects, start, end, memspace, bank
887
+ s.sendall(frame(0x01, struct.pack('<BHHBH', 0, 0x02ff, 0x02ff, 0, 0), rid=20))
888
+ e, body = wait_for(s, 0x01, 20)
889
+ value = body[2] # u16 length, then the bytes
890
+ print('stopped at PC=$%04X $02FF=$%02X' % (pc, value))
891
+ if value in (1, 2):
892
+ verdict = 0 if value == 1 else 1
893
+ break
894
+ s.sendall(frame(0xaa, rid=30)) # Exit the monitor: resume
895
+ wait_for(s, 0xaa, 30)
896
+ except (EOFError, socket.timeout):
897
+ print('VICE went away before a verdict was stored')
898
+ try:
899
+ s.sendall(frame(0xbb, rid=40)) # Quit VICE
900
+ wait_for(s, 0xbb, 40)
901
+ except (EOFError, socket.timeout, OSError):
902
+ pass
903
+ vice.wait(timeout=30)
904
+ print('verdict', ['PASS', 'FAIL', 'NONE'][verdict])
905
+ sys.exit(verdict)
906
+ ```
907
+
908
+ Measured output, green KickAssembler build:
909
+
910
+ ```
911
+ stopped at PC=$FD59 $02FF=$00
912
+ stopped at PC=$0872 $02FF=$01
913
+ verdict PASS
914
+ ```
915
+
916
+ exit 0; red Oscar64 build: `PC=$FD59 $02FF=$00`, `PC=$08C6 $02FF=$02`,
917
+ `verdict FAIL`, exit 1. The stop lands after the store (the PC is the
918
+ next instruction, `$FD59` after the three-byte `STA $0200,Y` at `$FD56`),
919
+ so the read is the stored value. The body layouts in the comments are
920
+ the ones VICE 3.10 accepted; they were taken from the VICE binary monitor
921
+ documentation and confirmed only by these runs, not by a wider survey of
922
+ the protocol. The event type `0x62` (stopped) is not in the opcode table above,
923
+ which lists commands only; the reply to Checkpoint Set arrives as type
924
+ `0x11` and the Autostart reply echoes `0xdd`. If VICE exits on `-limitcycles` before a verdict is
925
+ stored the socket closes, `recvn` raises `EOFError`, and the script exits
926
+ 2.
927
+
928
+ ### Choosing a route
929
+
930
+ The screenshot route needs nothing but the pinned command and is the one
931
+ `npm run verify:recipes` already exercises; it sees the border, not the
932
+ code. The `-moncommands` route sees the byte and needs no second process,
933
+ but its output is a text log to parse. The binary monitor route sees the
934
+ byte, the PC and anything else in the machine, and ends the run itself
935
+ with `Quit` instead of waiting for the cycle limit; it is the one to grow
936
+ into a test runner. All three agree on both builds. None of them was run
937
+ against `sim6502-reference.md`'s VICE backend, which uses a different
938
+ server on port 6510.
939
+
940
+ ### Checking every store against the claims: `scripts/claims-watch.ts`
941
+
942
+ Route 2 applied to every store a program makes. The script runs a PRG
943
+ windowless with `trace store` on `$0000-$03FF`, `$D000-$DFFF` and
944
+ `$FFFA-$FFFF` (add `--all-ram` for `$0400-$CFFF` and `$E000-$FFF9`), and
945
+ checks each store against what the program declared:
946
+
947
+ ```bash
948
+ node scripts/claims-watch.ts game.prg --recipe docs/recipes/kickassembler/x.md \
949
+ --technique ram_under_kernal --claim 'zero_page $02-$39' \
950
+ --range 'screen=$0400-$07FF,colour=$D800-$DBFF' --screen 0400 \
951
+ --harness cia2_timer_a,cia2_timer_b --kernal IRQ,CHROUT --all-ram
952
+ ```
953
+
954
+ - `--technique` and a recipe's `techniques:` add each technique's
955
+ `**Claims:**` units, and those of the techniques it REQUIRES. A technique
956
+ with no Claims line is named in the output; declare its units with
957
+ `--claim`, in the Claims-line grammar.
958
+ - `--range` is the program's own RAM. The PRG's load span is always declared.
959
+ Colour RAM counts as RAM here, not as a unit.
960
+ - `--harness` names measurement timers and counters. Their stores are
961
+ listed apart and never fail the run.
962
+ - `--kernal` names the routines the program calls; `IRQ` and `NMI` name the
963
+ two services. A KERNAL zero-page store must lie inside the union of their
964
+ `(may; ...)` sets in `kernal-routines-reference.md`.
965
+
966
+ Exit 1 on a program store to a unit or byte nobody declared (or declared
967
+ `reads` only), on a KERNAL zero-page store outside the may-sets, or on a
968
+ store the watch cannot attribute (see the banking bullet below).
969
+
970
+ How it reads the log (VICE x64sc 3.10, measured):
971
+
972
+ - The register line of a store hit shows the registers after the
973
+ instruction: a PHA logged `SP:f5` and stored `$01F6`. The hit does not
974
+ log the byte written. So STA, STX and STY give the value, and a push
975
+ lands at `$0100 + SP + 1` to `+3`. Pushes are dropped; other stores to
976
+ page 1 are judged like any RAM.
977
+ - A read-modify-write logs one hit (two `DEC $01` gave two hits). On `$00`
978
+ and `$01` the watch computes the new byte from the last one: INC, DEC,
979
+ ASL, LSR, and ROR (its new bit 7 is the N flag after it). ROL's new
980
+ bit 0 is the carry it shifted in, which the log does not show, so ROL
981
+ leaves the port unknown unless Z is set.
982
+ - An I/O store counts against a unit only for the bits it changes, by the
983
+ last value stored there: `STA $D015` with `$03` over `$01` touches
984
+ sprite 1 only. The first `STA $D011` of a program usually clears bit 7
985
+ that the KERNAL's boot left set (`$9B`), which touches `vic_raster_irq`.
986
+ A read-modify-write touches every unit bit of its register.
987
+ - `$D019` and the CIA interrupt control registers `$DC0D`/`$DD0D` are read
988
+ by the value, not the change. On `$D019` a 1 bit acknowledges its source.
989
+ On an ICR, bits 0-4 name the sources whose mask bit the write sets
990
+ (bit 7 = 1) or clears (bit 7 = 0); timer A is bit 0, timer B bit 1, the
991
+ TOD alarm bit 2 (`cia-reference.md`). `lda #$7f : sta $dc0d` touches
992
+ `cia1_timer_a`, `cia1_timer_b` and `cia1_tod`. Before this rule the
993
+ write changed no unit's bits and was reported as unowned I/O.
994
+ - A store is the KERNAL's when its PC is `$E000` or above and HIRAM is set
995
+ in the last value stored to `$01`; BASIC's when `$A000-$BFFF` with LORAM and
996
+ HIRAM set; otherwise the program's. So code in RAM under a banked-out
997
+ KERNAL is attributed to the program. While `$01` is unknown (after a
998
+ ROL), a store from `$A000-$BFFF` or `$E000-$FFFF` could be either, and it
999
+ fails the run as unattributed. An earlier version assumed ROM there, and
1000
+ also left `$01` unknown after any INC or DEC: a program that banked the
1001
+ KERNAL out with `dec $01` and wrote the SID from `$E000` passed.
1002
+ - Judging starts at the `SYS` address of the BASIC stub (a `trace exec`
1003
+ there). At the first execution of BASIC's READY entry, `$A474`, with
1004
+ BASIC ROM mapped in, the watch stops judging ROM stores: the
1005
+ KickAssembler file round trip, which returns to BASIC, was flagged for
1006
+ `$9D` before this cut, because READY calls SETMSG. The program's own
1007
+ stores after READY (its IRQ or NMI handler) are still judged. An earlier
1008
+ version stopped judging everything at `$A474`, and took a jump to RAM at
1009
+ `$A474` with BASIC banked out as READY; both let a violation pass.
1010
+
1011
+ Four recipes, built and run with `--all-ram` at 8,000,000 cycles PAL (the
1012
+ file round trip at 40,000,000 with a fresh D64):
1013
+
1014
+ | Recipe | Declared from the page alone: violations | What had to be added to pass |
1015
+ |---|---|---|
1016
+ | `kickassembler/sprite-multiplex-game` | `irq_vector_fffe`, `nmi_vector_fffa`, zero page `$02-$39`, screen, colour RAM, `cia2_timer_a`, `cia2_timer_b`; since the ICR rule also `cia1_timer_a`, `cia1_timer_b`, `cia1_tod` (`sta $dc0d`) and `cia2_tod` (`sta $dd0d`) | `ram_under_kernal` (the recipe banks the KERNAL out; its `techniques:` omits it), the zero page, the screen and colour RAM, the two timers and `cia2_tod` as harness, `cia1_timer_a (init), cia1_timer_b (init), cia1_tod (init)` |
1017
+ | `kickassembler/scroll-panel-split` | `irq_vector_fffe`, screen `$0400-$0747`, panel `$0F20-$0FE7`, `$3FFF`, colour RAM | `ram_under_kernal`, the ranges; `soft_scroll_v` and `char_scroll_buffer_v` have no Claims line |
1018
+ | `oscar64/sfx-engine` | Oscar64 runtime zero page (`$0D-$56` seen), BSS, its stack at `$9FFC-$9FFF`, screen, colour RAM, `cia1_timer_a` | the zero page, the map file's BSS and stack, the screen and colour RAM, `cia1_timer_a` as harness |
1019
+ | `kickassembler/file-io-roundtrip` | `cia2_timer_a`, `cia2_timer_b` | the two timers as harness; every KERNAL zero-page store fell inside the ten routines' may-sets |
1020
+
1021
+ A variant of the multiplexer with `sta $d40b` and `sta $fb` added at its
1022
+ entry failed with exactly those two stores, `sid_voice_2` and zero page
1023
+ `$FB`. The KERNAL's serial routines in the file round trip write
1024
+ `cia1_timer_b`: `STA $DC07` and `STA $DC0F` at `$ED94`/`$ED99` and
1025
+ `$EE22`/`$EE27` (ROM bytes `8D 07 DC`, `8D 0F DC`). The count varies by
1026
+ run (212 and 314 seen). A program that owns `cia1_timer_b` loses it
1027
+ across a disk call.
1028
+
1029
+ Four probes, built with KickAssembler and run in x64sc, fail on their
1030
+ `sta $d40b`: an IRQ handler that writes it after the program returns to
1031
+ BASIC; a jump to `$A474` with BASIC banked out; `dec $01` twice, then code
1032
+ at `$E000`; `rol $01`, then code at `$A000` (unattributed).
1033
+
1034
+ What the watch does not see:
1035
+
1036
+ - Writes by DMA (an REU, a cartridge) are not CPU stores, and `trace store`
1037
+ is not expected to log them (not measured here).
1038
+ - The register mirrors (VIC `$D040-$D3FF`, SID `$D420-$D7FF`, each CIA's
1039
+ `$xx10-$xxFF`) are not mapped to units: a store to one is reported as
1040
+ unowned I/O and never fails the run.
1041
+ - ROM stores to I/O and RAM outside zero page are listed, not judged; after
1042
+ READY, ROM stores are dropped.
1043
+ - Without `--all-ram`, stores to `$0400-$CFFF` and `$E000-$FFF9` are not
1044
+ traced.
1045
+ - A read-modify-write on an I/O register is valued as unknown, so it
1046
+ touches every unit bit there.
1047
+
1048
+ ---
1049
+
1050
+ ## Text monitor for debugging
1051
+
1052
+ Everything in this section was measured on 2026-09-22 with VICE x64sc
1053
+ 3.10 `-default` (PAL) on the PRG built from
1054
+ `docs/recipes/kickassembler/stable-raster-irq.md` with `-vicesymbols`.
1055
+ Every command and output line below is quoted from those sessions.
1056
+ Disassembly from the monitor is the subject of
1057
+ [issue #3](https://github.com/bdgscotland/c64-kb/issues/3) and is not
1058
+ covered here.
1059
+
1060
+ ### Getting a prompt
1061
+
1062
+ The GTK build's `-console` flag does not put the monitor on stdio. With
1063
+ `-console`, a `-moncommands` file containing `break .start`, and stdin
1064
+ fed from a pipe or a pty, the machine stopped at the breakpoint (it never
1065
+ reached `-limitcycles`) but no stop line and no prompt ever appeared on
1066
+ stdout: `timeout 60` killed it and a `logname`/`log on` monitor log stayed
1067
+ empty. The route that works headless is the remote
1068
+ text monitor, a TCP port that speaks the same commands:
1069
+
1070
+ ```bash
1071
+ GSETTINGS_SCHEMA_DIR=/opt/homebrew/share/glib-2.0/schemas timeout 180 x64sc -default -warp +sound \
1072
+ +autostart-delay-random -autostartprgmode 1 -limitcycles 6000000 \
1073
+ -remotemonitor -remotemonitoraddress ip4://127.0.0.1:6510 \
1074
+ -moncommands session.mon -autostart stable-raster-irq.prg
1075
+ ```
1076
+
1077
+ `session.mon` loads the labels and arms the first stop before the program
1078
+ runs:
1079
+
1080
+ ```text
1081
+ ll "stable-raster-irq.vs"
1082
+ break .start
1083
+ ```
1084
+
1085
+ Connect to the port with a TCP client, and connect it before the first
1086
+ checkpoint fires. A stop with no client connected leaves the machine
1087
+ stopped with no way in: a client that connected 8 seconds after launch,
1088
+ once `break .start` had already fired, received nothing, its `r` and `x`
1089
+ got no reply, and x64sc was still stopped 20 seconds later when it was
1090
+ killed. That is the same hang as `-console`. Under `-warp` the `break
1091
+ .start` stop fired 0.40 s after launch (the client had connected at
1092
+ 0.09 s) and a boot-time watch fires sooner still, so start the client
1093
+ from the same script and poll the port from the moment x64sc is
1094
+ launched; the sessions here used a Python socket polling every 0.3 s for
1095
+ the break and every 0.01 s for the watch, which the slower poll missed
1096
+ twice. `nc 127.0.0.1 6510` by hand only works when the first stop is far
1097
+ enough out: drop `-warp`, or arm the watch from the prompt after a
1098
+ scripted first break. Once the client is connected VICE writes each stop
1099
+ to it and reads commands from it. Port 6510 is the one
1100
+ `sim6502-reference.md`'s VICE backend uses;
1101
+ choose another if both run. `-initbreak 0x900` (or `-initbreak 2304`)
1102
+ sets the same first breakpoint with no file and no labels. `-initbreak
1103
+ $0900` is refused before the emulator starts:
1104
+
1105
+ ```text
1106
+ Argument '$0900' not valid for option `-initbreak'.
1107
+ Error parsing command-line options, bailing out. For help use '-help'
1108
+ ```
1109
+
1110
+ ### The stop and the register line
1111
+
1112
+ ```text
1113
+ #1 (Stop on exec 0900) 36/$024, 59/$3b
1114
+ .C:0900 78 SEI - A:00 X:00 Y:00 SP:f6 ..-..... 2970383
1115
+ (C:$0900)
1116
+ ```
1117
+
1118
+ The first line is the checkpoint number, its kind and address, then the
1119
+ raster line and the cycle within it, each as decimal/hex. The second is
1120
+ the instruction about to execute, not yet executed: memory space and PC,
1121
+ opcode bytes, the disassembly with labels substituted, the registers, the
1122
+ flags as `NV-BDIZC` with a letter for set and `.` for clear, and the
1123
+ stopwatch, a cycle count since power-on. The prompt carries the current
1124
+ address.
1125
+
1126
+ `r` prints the same state as a table:
1127
+
1128
+ ```text
1129
+ (C:$0900) r
1130
+ ADDR A X Y SP 00 01 NV-BDIZC LIN CYC STOPWATCH
1131
+ .;0900 00 00 00 f6 2f 37 00100000 036 059 2970383
1132
+ ```
1133
+
1134
+ `00` and `01` are the 6510 port bytes at `$0000` and `$0001`. `LIN` and
1135
+ `CYC` are the raster line and the cycle within it, decimal. Two steps
1136
+ later (`SEI` then `LDA #$7F`, 2 cycles each) the line read `037 000` at
1137
+ stopwatch `2970387`: cycle 59 plus 4 is 63, which wraps to cycle 0 of the
1138
+ next line. That is the PAL 63 cycles per line, seen from the register
1139
+ line.
1140
+
1141
+ ### step, next and until
1142
+
1143
+ ```text
1144
+ (C:$0900) step
1145
+ .C:0901 A9 7F LDA #$7F - A:00 X:00 Y:00 SP:f6 ..-..I.. 2970385
1146
+ (C:$0901) step
1147
+ .C:0903 8D 0D DC STA $DC0D - A:7F X:00 Y:00 SP:f6 ..-..I.. 2970387
1148
+ (C:$0903) next
1149
+ .C:0906 AD 0D DC LDA $DC0D - A:7F X:00 Y:00 SP:f6 ..-..I.. 2970391
1150
+ ```
1151
+
1152
+ `step` (abbreviation `z`) executes one instruction and prints the next.
1153
+ `next` (`n`) does the same but runs a `JSR` through to its `RTS` as one
1154
+ instruction. Both take an optional count. `until .irq2` (`un`) sets a
1155
+ one-shot breakpoint and resumes; it printed `UNTIL: 2 C:$0976 (Stop on
1156
+ exec)`, and when another checkpoint fired first that one won and the
1157
+ one-shot stayed armed. `x` resumes.
1158
+
1159
+ ### break, watch and conditions
1160
+
1161
+ The monitor's own `help` lines:
1162
+
1163
+ ```text
1164
+ Syntax: break [load|store|exec] [address [address] [if <cond_expr>]]
1165
+ Syntax: watch [load|store|exec] [address [address] [if <cond_expr>]]
1166
+ Syntax: condition <checknum> if <cond_expr>
1167
+ ```
1168
+
1169
+ `break` defaults to `exec`; `watch` defaults to `load` and `store`
1170
+ (`watch .irq2_line` was listed as `WATCH: 2 C:$09d8 (Stop on load
1171
+ store)`). A store watchpoint on a program variable fires before the
1172
+ program runs,
1173
+ because the KERNAL reset's RAM test writes every byte. `watch store
1174
+ .irq2_line` in the `-moncommands` file stopped three times at boot:
1175
+
1176
+ ```text
1177
+ #1 (Stop on store 09d8) 24/$018, 50/$32
1178
+ .C:fd73 91 C1 STA ($C1),Y - A:55 X:00 Y:D8 SP:fd ..-..I.C 80186
1179
+ ```
1180
+
1181
+ then at `$FD7A` with `A:AB` and `$FD81` with `A:00`, and only on the
1182
+ fourth `x` at the program's own store, with the label in the operand:
1183
+
1184
+ ```text
1185
+ #1 (Stop on store 09d8) 68/$044, 23/$17
1186
+ .C:09be 8D D8 09 STA .irq2_line - A:4C X:01 Y:00 SP:f0 ..-..I.. 2972363
1187
+ ```
1188
+
1189
+ Type `x` through the boot hits, or arm the watch from the prompt after a
1190
+ breakpoint in the program.
1191
+
1192
+ A condition compares registers (`A`, `X`, `Y`, `PC`, `SP`, `FL`), `RL`
1193
+ (the raster line), `CY` (the cycle within it) or memory
1194
+ (`@io:$d020 == $f0`) with `==`, `!=`, `<`, `>`, `<=`, `>=`, and joins
1195
+ them with `&&`, `||` and arithmetic. `break .bar_line if Y == 3` in the
1196
+ `-moncommands` file stopped at:
1197
+
1198
+ ```text
1199
+ #1 (Stop on exec 098e) 64/$040, 13/$0d
1200
+ .C:098e A9 01 LDA #$01 - A:06 X:00 Y:03 SP:f0 ..-..I.. 2972101
1201
+ (C:$098e) break
1202
+ BREAK: 1 C:$098e (Stop on exec)
1203
+ Condition: Y == $03
1204
+ (C:$098e) cond 1 if Y == 1
1205
+ Setting checkpoint 1 condition to: Y == $01
1206
+ (C:$098e) x
1207
+ #1 (Stop on exec 098e) 66/$042, 13/$0d
1208
+ .C:098e A9 01 LDA #$01 - A:06 X:00 Y:01 SP:f0 ..-..I.. 2972227
1209
+ ```
1210
+
1211
+ `break` or `watch` with no argument lists the checkpoints of that kind.
1212
+ `delete 1` removes one; `delete` alone prints `Deleting all checkpoints`.
1213
+ Numbers are reused: after deleting checkpoints 1 and 2 the next `break`
1214
+ was numbered 1 again. `cond` on a number that does not exist says `#3 not
1215
+ a valid checkpoint`. A bare number in a condition is hex: `break
1216
+ .bar_line if RL == 70 && Y == 2` was echoed as `Setting checkpoint 3
1217
+ condition to: RL == $70 && Y == $02`, which is raster line 112, not 70.
1218
+ Write `RL == $c8` or `RL == c8` for line 200.
1219
+
1220
+ ### Measuring cycles between two points
1221
+
1222
+ Two register lines at the same breakpoint, one `x` apart. `.bar_line` is
1223
+ the top of the recipe's one-raster-line loop:
1224
+
1225
+ ```text
1226
+ .;098e 3c f0 06 f0 2f 37 00100100 061 013 2971912
1227
+ .;098e 06 00 05 f0 2f 37 00100100 062 013 2971975
1228
+ ```
1229
+
1230
+ 2971975 − 2971912 = 63 cycles: `LIN` went up by one and `CYC` stayed at
1231
+ 13. The third hit was at 2972038, 63 again. Cross-checked two ways.
1232
+ Arithmetic from the listing's own cycle column: 2 + 4 + 4 + 2 + 4 + 2 +
1233
+ 4 + 2 + (7 × 5 − 1) + 2 + 3 = 63. sim6502 (`--backend sim`, commit
1234
+ d6f6812) on the same PRG with `jsr([bar_line], stop_on_address = $09a8)`
1235
+ reported 129 cycles with `y = 2` and 66 with `y = 1`, a difference of 63;
1236
+ each figure carries 4 cycles beyond the loop itself, the difference does
1237
+ not.
1238
+
1239
+ The stopwatch counts only while the machine runs. Twenty seconds of real
1240
+ time at the prompt left it at `2970383`; `r` before and after read the
1241
+ same line.
1242
+
1243
+ ### Memory dump and save
1244
+
1245
+ ```text
1246
+ (C:$0906) m 0900 090f
1247
+ >C:0900 78 a9 7f 8d 0d dc ad 0d dc a9 34 8d 14 03 a9 09 X..
1248
+ (C:$0910)
1249
+ ```
1250
+
1251
+ Sixteen bytes per row, a PETSCII column after them (trimmed here), and
1252
+ the prompt moves to the byte after the dump. `m .irq2_line` with a label
1253
+ and no end address printed nine rows (`$09D8` to `$0A67`) and left the
1254
+ prompt at `(C:$0a68)`. The full syntax is
1255
+ `mem [<data_type>] [<address_opt_range>]`.
1256
+
1257
+ ```text
1258
+ (C:$0900) save "/tmp/saved.prg" 0 0900 09ff
1259
+ Saving file '/tmp/saved.prg' from $0900 to $09ff
1260
+ ```
1261
+
1262
+ Device 0 is the host file system. The file was 258 bytes: the two-byte
1263
+ load address `00 09` and the 256 bytes, a PRG that loads back where it
1264
+ came from.
1265
+
1266
+ ### `-limitcycles` and a stopped machine
1267
+
1268
+ `-limitcycles` counts emulated cycles and the monitor stops the clock.
1269
+ Three consequences, each measured:
1270
+
1271
+ - A breakpoint past the limit never fires. With `-limitcycles 1000000`
1272
+ and `break .start`, which fires at stopwatch 2,970,383 on this PRG,
1273
+ VICE exited with status 1 and printed no stop.
1274
+ - A machine left at the prompt never exits. A session that ended stopped
1275
+ at `.bar_line` was still there when `timeout` killed it. After `x` with
1276
+ no further stop ahead the remaining cycles run and the limit exit
1277
+ happens as usual, status 1.
1278
+ - Real time at the prompt costs nothing on the stopwatch (the twenty
1279
+ seconds above).
1280
+
1281
+ This is the fact behind Route 2's warning: a stopping checkpoint in a
1282
+ `-moncommands` file with no client connected hangs the run.
1283
+
1284
+ Related pages: the binary monitor for the same operations from a
1285
+ program is "The Binary Monitor Protocol" above and
1286
+ [vice-mcp-reference.md](vice-mcp-reference.md); cycle assertions without
1287
+ an emulator are [sim6502-reference.md](sim6502-reference.md); the label
1288
+ files each toolchain writes are in "Symbol Files" above and in the
1289
+ KickAssembler, Oscar64 and cc65 pages' debugging sections.
1290
+
1291
+ ---
1292
+
1293
+ ## Integration with vice-mcp
1294
+
1295
+ vice-mcp is a separate MCP server that acts as a bridge between agents and a running
1296
+ VICE instance. It maintains a TCP connection to VICE's binary monitor, translates MCP
1297
+ tool calls into binary monitor frames, and returns structured results. Agents invoke
1298
+ vice-mcp tools such as `vice_read_memory`, `vice_set_breakpoint`, `vice_screenshot`, and
1299
+ `vice_autostart`; they never send raw binary monitor frames.
1300
+
1301
+ From a deployment perspective: start `x64sc` first with `-binarymonitor
1302
+ -binarymonitoraddress ip4://127.0.0.1:6502`, then start the vice-mcp server, which
1303
+ connects to that address. Both processes run concurrently for the duration of the
1304
+ inspection session.
1305
+
1306
+ See [vice-mcp-reference.md](vice-mcp-reference.md) for the full tool surface.
1307
+
1308
+ ---
1309
+
1310
+ ## Pitfalls
1311
+
1312
+ ### x64 (fast) vs x64sc (cycle-accurate)
1313
+
1314
+ `x64` skips the cycle-exact 6510 core and uses a timing approximation. It runs faster
1315
+ but breaks any code that depends on precise cycle counts: raster IRQs, sprite
1316
+ multiplexers, SID timing, and CIA timer-based effects will behave incorrectly or
1317
+ intermittently. Always use `x64sc` when verifying code against hardware. The speed
1318
+ penalty is acceptable for automated runs with `-warp`.
1319
+
1320
+ ### Default keyboard layout
1321
+
1322
+ VICE picks the host keyboard layout from the locale (LANG/LC_ALL) at RUN time, not
1323
+ build time as an earlier version of this page said: the same x64sc 3.10 binary loads
1324
+ `gtk3_sym.vkm` under `en_US` and `gtk3_sym_de.vkm` under `de_DE.UTF-8` (measured with
1325
+ `-default`). The default keymap type is symbolic (KeymapIndex 0). Code injected via
1326
+ `Keyboard Feed` (`0x72`) sends raw PETSCII, so this does not affect monitor or
1327
+ programmatic input, but it matters when a test scenario types characters through the
1328
+ emulated keyboard. Pass `-keymap 0 -keyboardmapping 0` explicitly for a US symbolic
1329
+ keymap regardless of host locale. There is no `-keyboard` option: `-keyboard en` is
1330
+ rejected as ambiguous (it is a prefix of `-keyboardmapping`, `-keyboardtype` and
1331
+ `-keyboardstatusbar`).
1332
+
1333
+ ### ROM image licensing
1334
+
1335
+ The VICE source tarball ships the Commodore ROM images (kernal, basic, chargen) in its
1336
+ data/ tree, and the Homebrew formula installs them from that tarball into
1337
+ `/opt/homebrew/share/vice/C64/` — nothing is fetched separately (an earlier version of
1338
+ this page said the formula downloaded them from a community source; `brew cat vice` has
1339
+ no such resource). Some Linux distributions strip them for licensing reasons: Debian's
1340
+ `vice` package lives in contrib and explicitly excludes the ROMs (see its README.ROMs),
1341
+ so there you must obtain them yourself. In that case, and in any Docker or CI image
1342
+ built from such a package, supply the ROM images and point VICE at them via `-kernal`,
1343
+ `-basic`, and `-chargen`, or place them in the expected directory. Failure to provide
1344
+ ROMs produces a startup error and a blank screen.
1345
+
1346
+ ### Monitor port conflicts
1347
+
1348
+ Port 6502 may be in use if multiple VICE instances or other tools occupy it. Pass a
1349
+ different port via `-binarymonitoraddress ip4://127.0.0.1:6510` (or any free port) when
1350
+ running parallel test instances.
1351
+
1352
+ ### macOS Homebrew: g_settings_new crash on launch
1353
+
1354
+ On macOS Homebrew (`brew install vice`, 3.10 at time of writing) both `x64` and
1355
+ `x64sc` crash at launch with:
1356
+
1357
+ ```
1358
+ GLib-GIO-ERROR **: No GSettings schemas are installed on the system
1359
+ ```
1360
+
1361
+ The compiled schemas DO exist at `/opt/homebrew/share/glib-2.0/schemas/`, but
1362
+ GTK3 doesn't search that path by default. Export the schema location before
1363
+ launching:
1364
+
1365
+ ```bash
1366
+ export XDG_DATA_DIRS="/opt/homebrew/share:/usr/local/share:/usr/share:$XDG_DATA_DIRS"
1367
+ export GSETTINGS_SCHEMA_DIR="/opt/homebrew/share/glib-2.0/schemas"
1368
+ x64sc -binarymonitor -binarymonitoraddress ip4://127.0.0.1:6502 -autostart hello.prg
1369
+ ```
1370
+
1371
+ The template harness (`templates/_harness/harness.mk`) exports
1372
+ `GSETTINGS_SCHEMA_DIR` for its `run` target, which is enough on this machine. They are harmless on Linux (the
1373
+ paths just don't exist).
1374
+
1375
+ This is a packaging issue in the Homebrew GTK3 bottle, not a VICE bug.
1376
+
1377
+ ### True drive emulation and speed
1378
+
1379
+ When `-drive8type 1541` is active with true drive emulation enabled (the default in
1380
+ `x64sc`), disk access is cycle-accurate and slow even in warp mode. If load time
1381
+ dominates a test run and timing accuracy of the drive is not the subject of the test,
1382
+ disable true drive emulation for unit 8 with `+drive8truedrive` to use the faster IEC
1383
+ fast-path (the option is per unit — `+drive9truedrive` … `+drive11truedrive` likewise —
1384
+ since VICE 3.6; a bare `+truedrive`, which an earlier version of this page gave, is
1385
+ rejected as an unknown option by x64sc 3.10).
1386
+
1387
+ ---
1388
+
1389
+ ## See Also
1390
+
1391
+ - [vice-mcp-reference.md](vice-mcp-reference.md) — MCP tool surface for agent-driven VICE control
1392
+ - [../formats/c64-file-formats.md](../formats/c64-file-formats.md) — PRG, CRT, D64, and other C64 file format details
1393
+ - [../hardware/pal-ntsc-reference.md](../hardware/pal-ntsc-reference.md) — PAL vs NTSC hardware differences and timing tables