romdev-mcp 0.1.1

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 (1247) hide show
  1. package/AGENTS.md +726 -0
  2. package/LICENSE +45 -0
  3. package/NOTICE +86 -0
  4. package/README.md +46 -0
  5. package/examples/README.md +36 -0
  6. package/examples/art-first-workflow/README.md +205 -0
  7. package/examples/atari2600/main.asm +143 -0
  8. package/examples/atari2600/templates/default.asm +183 -0
  9. package/examples/atari2600/templates/mini_invaders.asm +381 -0
  10. package/examples/atari2600/templates/music_demo.asm +322 -0
  11. package/examples/atari2600/templates/paddle.asm +345 -0
  12. package/examples/atari2600/templates/single_screen.asm +242 -0
  13. package/examples/atari7800/main.c +88 -0
  14. package/examples/atari7800/templates/default.c +183 -0
  15. package/examples/atari7800/templates/hello_sprite.c +141 -0
  16. package/examples/atari7800/templates/music_demo.c +123 -0
  17. package/examples/atari7800/templates/platformer.c +159 -0
  18. package/examples/atari7800/templates/puzzle.c +164 -0
  19. package/examples/atari7800/templates/racing.c +139 -0
  20. package/examples/atari7800/templates/shmup.c +148 -0
  21. package/examples/atari7800/templates/sports.c +207 -0
  22. package/examples/c64/main.c +63 -0
  23. package/examples/c64/templates/hello_sprite.c +117 -0
  24. package/examples/c64/templates/music_demo.c +131 -0
  25. package/examples/c64/templates/platformer.c +194 -0
  26. package/examples/c64/templates/puzzle.c +178 -0
  27. package/examples/c64/templates/racing.c +140 -0
  28. package/examples/c64/templates/shmup.c +201 -0
  29. package/examples/c64/templates/sports.c +109 -0
  30. package/examples/c64/templates/tile_engine.c +174 -0
  31. package/examples/gb/main.asm +106 -0
  32. package/examples/gb/main.c +49 -0
  33. package/examples/gb/templates/default.c +58 -0
  34. package/examples/gb/templates/hello_sprite.c +130 -0
  35. package/examples/gb/templates/music_demo.c +52 -0
  36. package/examples/gb/templates/platformer.c +178 -0
  37. package/examples/gb/templates/puzzle.c +217 -0
  38. package/examples/gb/templates/racing.c +158 -0
  39. package/examples/gb/templates/shmup.c +172 -0
  40. package/examples/gb/templates/sports.c +136 -0
  41. package/examples/gb/templates/tile_engine.c +280 -0
  42. package/examples/gba/templates/gba_hello.c +64 -0
  43. package/examples/gba/templates/maxmod_demo.c +105 -0
  44. package/examples/gba/templates/platformer.c +215 -0
  45. package/examples/gba/templates/puzzle.c +237 -0
  46. package/examples/gba/templates/racing.c +175 -0
  47. package/examples/gba/templates/shmup.c +197 -0
  48. package/examples/gba/templates/sports.c +177 -0
  49. package/examples/gba/templates/tonc_hello.c +72 -0
  50. package/examples/gba/templates/tonc_hello_sprite.c +109 -0
  51. package/examples/gbc/main.asm +123 -0
  52. package/examples/gbc/templates/default.c +61 -0
  53. package/examples/gbc/templates/hello_sprite.c +140 -0
  54. package/examples/gbc/templates/music_demo.c +63 -0
  55. package/examples/gbc/templates/platformer.c +181 -0
  56. package/examples/gbc/templates/puzzle.c +217 -0
  57. package/examples/gbc/templates/racing.c +164 -0
  58. package/examples/gbc/templates/shmup.c +188 -0
  59. package/examples/gbc/templates/sports.c +142 -0
  60. package/examples/gbc/templates/tile_engine.c +280 -0
  61. package/examples/genesis/main.s +161 -0
  62. package/examples/genesis/templates/hello_sprite.c +75 -0
  63. package/examples/genesis/templates/platformer.c +166 -0
  64. package/examples/genesis/templates/puzzle.c +240 -0
  65. package/examples/genesis/templates/racing.c +170 -0
  66. package/examples/genesis/templates/sgdk_hello.c +41 -0
  67. package/examples/genesis/templates/shmup.c +188 -0
  68. package/examples/genesis/templates/shmup_2p.c +244 -0
  69. package/examples/genesis/templates/sports.c +172 -0
  70. package/examples/genesis/templates/tile_engine.c +135 -0
  71. package/examples/genesis/templates/xgm2_demo.c +53 -0
  72. package/examples/genesis/templates/xgm2_demo_data.s +27 -0
  73. package/examples/gg/main.c +10 -0
  74. package/examples/gg/templates/default.c +156 -0
  75. package/examples/gg/templates/hello_sprite.c +90 -0
  76. package/examples/gg/templates/music_demo.c +156 -0
  77. package/examples/gg/templates/platformer.c +220 -0
  78. package/examples/gg/templates/puzzle.c +204 -0
  79. package/examples/gg/templates/racing.c +161 -0
  80. package/examples/gg/templates/shmup.c +188 -0
  81. package/examples/gg/templates/sports.c +137 -0
  82. package/examples/gg/templates/tile_engine.c +137 -0
  83. package/examples/lynx/main.c +4 -0
  84. package/examples/lynx/templates/default.c +41 -0
  85. package/examples/lynx/templates/hello_sprite.c +39 -0
  86. package/examples/lynx/templates/music_demo.c +37 -0
  87. package/examples/lynx/templates/platformer.c +72 -0
  88. package/examples/lynx/templates/puzzle.c +142 -0
  89. package/examples/lynx/templates/racing.c +94 -0
  90. package/examples/lynx/templates/shmup.c +132 -0
  91. package/examples/lynx/templates/sports.c +59 -0
  92. package/examples/nes/main.c +143 -0
  93. package/examples/nes/space-shooter/README.md +68 -0
  94. package/examples/nes/space-shooter/main.c +441 -0
  95. package/examples/nes/space-shooter/nes_runtime.c +347 -0
  96. package/examples/nes/space-shooter/nes_runtime.h +141 -0
  97. package/examples/nes/templates/default.c +41 -0
  98. package/examples/nes/templates/hello_sprite.c +104 -0
  99. package/examples/nes/templates/music_demo.c +80 -0
  100. package/examples/nes/templates/platformer.c +171 -0
  101. package/examples/nes/templates/puzzle.c +232 -0
  102. package/examples/nes/templates/racing.c +203 -0
  103. package/examples/nes/templates/shmup.c +228 -0
  104. package/examples/nes/templates/sports.c +205 -0
  105. package/examples/nes/templates/tile_engine.c +224 -0
  106. package/examples/porting-across-platforms/README.md +59 -0
  107. package/examples/sms/main.c +129 -0
  108. package/examples/sms/templates/default.c +110 -0
  109. package/examples/sms/templates/hello_sprite.c +90 -0
  110. package/examples/sms/templates/music_demo.c +151 -0
  111. package/examples/sms/templates/platformer.c +215 -0
  112. package/examples/sms/templates/puzzle.c +204 -0
  113. package/examples/sms/templates/racing.c +161 -0
  114. package/examples/sms/templates/shmup.c +167 -0
  115. package/examples/sms/templates/shmup_2p.c +219 -0
  116. package/examples/sms/templates/sports.c +147 -0
  117. package/examples/sms/templates/tile_engine.c +137 -0
  118. package/examples/snes/main.asm +70 -0
  119. package/examples/snes/templates/c-hello-data.asm +28 -0
  120. package/examples/snes/templates/c-hello.c +71 -0
  121. package/examples/snes/templates/default-data.asm +36 -0
  122. package/examples/snes/templates/default.c +74 -0
  123. package/examples/snes/templates/hello_sprite-data.asm +45 -0
  124. package/examples/snes/templates/hello_sprite.c +76 -0
  125. package/examples/snes/templates/music_demo-data.asm +20 -0
  126. package/examples/snes/templates/music_demo.c +83 -0
  127. package/examples/snes/templates/platformer-data.asm +27 -0
  128. package/examples/snes/templates/platformer.c +142 -0
  129. package/examples/snes/templates/puzzle-data.asm +14 -0
  130. package/examples/snes/templates/puzzle.c +199 -0
  131. package/examples/snes/templates/racing-data.asm +33 -0
  132. package/examples/snes/templates/racing.c +146 -0
  133. package/examples/snes/templates/shmup-data.asm +61 -0
  134. package/examples/snes/templates/shmup.c +199 -0
  135. package/examples/snes/templates/sports-data.asm +28 -0
  136. package/examples/snes/templates/sports.c +144 -0
  137. package/package.json +83 -0
  138. package/src/cli/smoke.js +283 -0
  139. package/src/cores/registry.js +95 -0
  140. package/src/host/LibretroHost.js +502 -0
  141. package/src/host/callbacks.js +444 -0
  142. package/src/host/chafa-render.js +170 -0
  143. package/src/host/coreLoader.js +57 -0
  144. package/src/host/cpu-state.js +422 -0
  145. package/src/host/dsp-state.js +188 -0
  146. package/src/host/framebuffer.js +115 -0
  147. package/src/host/gpgx-state.js +309 -0
  148. package/src/host/index.js +4 -0
  149. package/src/host/retroConstants.js +72 -0
  150. package/src/host/snes9x-state.js +35 -0
  151. package/src/host/types.js +280 -0
  152. package/src/mcp/disclosure.js +250 -0
  153. package/src/mcp/log.js +87 -0
  154. package/src/mcp/server.js +433 -0
  155. package/src/mcp/state.js +83 -0
  156. package/src/mcp/tools/address-to-symbol.js +151 -0
  157. package/src/mcp/tools/art-loaders.js +740 -0
  158. package/src/mcp/tools/assets.js +89 -0
  159. package/src/mcp/tools/audio.js +173 -0
  160. package/src/mcp/tools/cart-parts.js +649 -0
  161. package/src/mcp/tools/diff-roms.js +412 -0
  162. package/src/mcp/tools/disasm.js +980 -0
  163. package/src/mcp/tools/find-references.js +361 -0
  164. package/src/mcp/tools/font-map.js +353 -0
  165. package/src/mcp/tools/frame.js +249 -0
  166. package/src/mcp/tools/free-space.js +95 -0
  167. package/src/mcp/tools/index.js +351 -0
  168. package/src/mcp/tools/input-layout.js +215 -0
  169. package/src/mcp/tools/input.js +142 -0
  170. package/src/mcp/tools/lifecycle.js +110 -0
  171. package/src/mcp/tools/lospec.js +156 -0
  172. package/src/mcp/tools/memory.js +169 -0
  173. package/src/mcp/tools/metasprite-tools.js +261 -0
  174. package/src/mcp/tools/platform-docs.js +102 -0
  175. package/src/mcp/tools/platform-tools.js +1063 -0
  176. package/src/mcp/tools/platforms.js +86 -0
  177. package/src/mcp/tools/playtest.js +280 -0
  178. package/src/mcp/tools/preview-tile.js +360 -0
  179. package/src/mcp/tools/project.js +1885 -0
  180. package/src/mcp/tools/record.js +131 -0
  181. package/src/mcp/tools/rendering-context.js +700 -0
  182. package/src/mcp/tools/rom-id.js +256 -0
  183. package/src/mcp/tools/run-until.js +173 -0
  184. package/src/mcp/tools/snippets.js +235 -0
  185. package/src/mcp/tools/splice-chr.js +215 -0
  186. package/src/mcp/tools/sprite-pipeline.js +614 -0
  187. package/src/mcp/tools/state.js +99 -0
  188. package/src/mcp/tools/symbols.js +277 -0
  189. package/src/mcp/tools/tile-inspect.js +206 -0
  190. package/src/mcp/tools/toolchain.js +680 -0
  191. package/src/mcp/tools/watch-memory.js +212 -0
  192. package/src/mcp/tools/which-tiles.js +193 -0
  193. package/src/mcp/util.js +85 -0
  194. package/src/observer/bus.js +127 -0
  195. package/src/observer/livestream.html +589 -0
  196. package/src/observer/server.js +66 -0
  197. package/src/observer/tool-wrap.js +115 -0
  198. package/src/platforms/atari2600/MENTAL_MODEL.md +185 -0
  199. package/src/platforms/atari2600/TROUBLESHOOTING.md +155 -0
  200. package/src/platforms/atari2600/UPSTREAM_SOURCES.md +49 -0
  201. package/src/platforms/atari2600/lib/README.md +67 -0
  202. package/src/platforms/atari2600/lib/cc65-src/crt0.s +49 -0
  203. package/src/platforms/atari2600/lib/cc65-src/ctype.s +5 -0
  204. package/src/platforms/atari2600/lib/kernel_skeleton.asm +85 -0
  205. package/src/platforms/atari2600/lib/player_kernel.asm +87 -0
  206. package/src/platforms/atari2600/lib/playfield_kernel.asm +63 -0
  207. package/src/platforms/atari2600/lib/read_joystick.asm +76 -0
  208. package/src/platforms/atari2600/lib/score_kernel.asm +141 -0
  209. package/src/platforms/atari2600/lib/vcs_constants.h +97 -0
  210. package/src/platforms/atari2600/lib/vectors.asm +16 -0
  211. package/src/platforms/atari2600/tia.js +355 -0
  212. package/src/platforms/atari7800/MENTAL_MODEL.md +306 -0
  213. package/src/platforms/atari7800/TROUBLESHOOTING.md +195 -0
  214. package/src/platforms/atari7800/UPSTREAM_SOURCES.md +43 -0
  215. package/src/platforms/atari7800/lib/README.md +45 -0
  216. package/src/platforms/atari7800/lib/c/atari7800_music.c +215 -0
  217. package/src/platforms/atari7800/lib/c/atari7800_music.h +33 -0
  218. package/src/platforms/atari7800/lib/c/atari7800_sfx.c +74 -0
  219. package/src/platforms/atari7800/lib/c/atari7800_sfx.h +45 -0
  220. package/src/platforms/atari7800/lib/cc65-src/clock.s +69 -0
  221. package/src/platforms/atari7800/lib/cc65-src/clocks_per_sec.s +34 -0
  222. package/src/platforms/atari7800/lib/cc65-src/clrscr.s +27 -0
  223. package/src/platforms/atari7800/lib/cc65-src/conio.s +226 -0
  224. package/src/platforms/atari7800/lib/cc65-src/conio_font.s +278 -0
  225. package/src/platforms/atari7800/lib/cc65-src/cputc.s +139 -0
  226. package/src/platforms/atari7800/lib/cc65-src/crt0.s +71 -0
  227. package/src/platforms/atari7800/lib/cc65-src/ctype.s +5 -0
  228. package/src/platforms/atari7800/lib/cc65-src/exehdr.s +46 -0
  229. package/src/platforms/atari7800/lib/cc65-src/extra/mono.s +28 -0
  230. package/src/platforms/atari7800/lib/cc65-src/extzp.inc +15 -0
  231. package/src/platforms/atari7800/lib/cc65-src/extzp.s +15 -0
  232. package/src/platforms/atari7800/lib/cc65-src/get_tv.s +65 -0
  233. package/src/platforms/atari7800/lib/cc65-src/irq.s +36 -0
  234. package/src/platforms/atari7800/lib/cc65-src/joy/atari7800-stdjoy.s +197 -0
  235. package/src/platforms/atari7800/lib/cc65-src/joy_stat_stddrv.s +14 -0
  236. package/src/platforms/atari7800/lib/cc65-src/libref.s +8 -0
  237. package/src/platforms/atari7800/lib/cc65-src/mono_clrscr.s +27 -0
  238. package/src/platforms/atari7800/lib/cc65-src/mono_conio.s +231 -0
  239. package/src/platforms/atari7800/lib/cc65-src/mono_cputc.s +102 -0
  240. package/src/platforms/atari7800/lib/cc65-src/mono_font.s +2065 -0
  241. package/src/platforms/atari7800/lib/cc65-src/mono_setcursor.s +214 -0
  242. package/src/platforms/atari7800/lib/cc65-src/setcursor.s +214 -0
  243. package/src/platforms/atari7800/lib/cc65-src/textcolor.s +53 -0
  244. package/src/platforms/atari7800/lib/cc65-src/wherex.s +19 -0
  245. package/src/platforms/atari7800/lib/cc65-src/wherey.s +19 -0
  246. package/src/platforms/atari7800/lib/display_list.asm +53 -0
  247. package/src/platforms/atari7800/lib/maria_init.asm +48 -0
  248. package/src/platforms/atari7800/lib/maria_registers.h +61 -0
  249. package/src/platforms/atari7800/lib/palette_load.asm +53 -0
  250. package/src/platforms/atari7800/lib/read_pad.asm +57 -0
  251. package/src/platforms/atari7800/lib/vblank_wait.asm +16 -0
  252. package/src/platforms/atari7800/maria.js +220 -0
  253. package/src/platforms/c64/MENTAL_MODEL.md +175 -0
  254. package/src/platforms/c64/TROUBLESHOOTING.md +130 -0
  255. package/src/platforms/c64/UPSTREAM_SOURCES.md +35 -0
  256. package/src/platforms/c64/image-to-tilemap.js +190 -0
  257. package/src/platforms/c64/lib/README.md +52 -0
  258. package/src/platforms/c64/lib/basic_stub.s +25 -0
  259. package/src/platforms/c64/lib/c/c64_music.c +248 -0
  260. package/src/platforms/c64/lib/c/c64_music.h +36 -0
  261. package/src/platforms/c64/lib/c/c64_sfx.c +94 -0
  262. package/src/platforms/c64/lib/c/c64_sfx.h +37 -0
  263. package/src/platforms/c64/lib/c64_registers.h +108 -0
  264. package/src/platforms/c64/lib/cc65-src/_scrsize.s +12 -0
  265. package/src/platforms/c64/lib/cc65-src/acc_c128_speed.s +5 -0
  266. package/src/platforms/c64/lib/cc65-src/acc_c64dtv_speed.s +64 -0
  267. package/src/platforms/c64/lib/cc65-src/acc_c65_speed.s +69 -0
  268. package/src/platforms/c64/lib/cc65-src/acc_chameleon_speed.s +100 -0
  269. package/src/platforms/c64/lib/cc65-src/acc_detect_c128.s +33 -0
  270. package/src/platforms/c64/lib/cc65-src/acc_detect_c64dtv.s +44 -0
  271. package/src/platforms/c64/lib/cc65-src/acc_detect_c65.s +55 -0
  272. package/src/platforms/c64/lib/cc65-src/acc_detect_chameleon.s +39 -0
  273. package/src/platforms/c64/lib/cc65-src/acc_detect_scpu.s +34 -0
  274. package/src/platforms/c64/lib/cc65-src/acc_detect_turbomaster.s +45 -0
  275. package/src/platforms/c64/lib/cc65-src/acc_scpu_speed.s +59 -0
  276. package/src/platforms/c64/lib/cc65-src/acc_turbomaster_speed.s +56 -0
  277. package/src/platforms/c64/lib/cc65-src/bordercolor.s +17 -0
  278. package/src/platforms/c64/lib/cc65-src/break.s +108 -0
  279. package/src/platforms/c64/lib/cc65-src/cgetc.s +62 -0
  280. package/src/platforms/c64/lib/cc65-src/clrscr.s +11 -0
  281. package/src/platforms/c64/lib/cc65-src/color.s +24 -0
  282. package/src/platforms/c64/lib/cc65-src/conio.s +10 -0
  283. package/src/platforms/c64/lib/cc65-src/cputc.s +105 -0
  284. package/src/platforms/c64/lib/cc65-src/crt0.s +117 -0
  285. package/src/platforms/c64/lib/cc65-src/devnum.s +7 -0
  286. package/src/platforms/c64/lib/cc65-src/emd/c64-65816.s +377 -0
  287. package/src/platforms/c64/lib/cc65-src/emd/c64-c256k.s +508 -0
  288. package/src/platforms/c64/lib/cc65-src/emd/c64-dqbb.s +447 -0
  289. package/src/platforms/c64/lib/cc65-src/emd/c64-georam.s +355 -0
  290. package/src/platforms/c64/lib/cc65-src/emd/c64-isepic.s +276 -0
  291. package/src/platforms/c64/lib/cc65-src/emd/c64-kerberos.s +281 -0
  292. package/src/platforms/c64/lib/cc65-src/emd/c64-ram.s +270 -0
  293. package/src/platforms/c64/lib/cc65-src/emd/c64-ramcart.s +297 -0
  294. package/src/platforms/c64/lib/cc65-src/emd/c64-reu.s +286 -0
  295. package/src/platforms/c64/lib/cc65-src/emd/c64-rrr.s +363 -0
  296. package/src/platforms/c64/lib/cc65-src/emd/c64-vdc.s +405 -0
  297. package/src/platforms/c64/lib/cc65-src/emd/dtv-himem.s +251 -0
  298. package/src/platforms/c64/lib/cc65-src/extra/soft80.s +71 -0
  299. package/src/platforms/c64/lib/cc65-src/extra/soft80mono.s +74 -0
  300. package/src/platforms/c64/lib/cc65-src/extra/tgimousedata.s +21 -0
  301. package/src/platforms/c64/lib/cc65-src/get_ostype.s +43 -0
  302. package/src/platforms/c64/lib/cc65-src/get_tv.s +20 -0
  303. package/src/platforms/c64/lib/cc65-src/gettime.s +83 -0
  304. package/src/platforms/c64/lib/cc65-src/irq.s +49 -0
  305. package/src/platforms/c64/lib/cc65-src/joy/c64-hitjoy.s +218 -0
  306. package/src/platforms/c64/lib/cc65-src/joy/c64-numpad.s +155 -0
  307. package/src/platforms/c64/lib/cc65-src/joy/c64-ptvjoy.s +146 -0
  308. package/src/platforms/c64/lib/cc65-src/joy/c64-stdjoy.s +111 -0
  309. package/src/platforms/c64/lib/cc65-src/joy_stat_stddrv.s +14 -0
  310. package/src/platforms/c64/lib/cc65-src/joy_stddrv.s +14 -0
  311. package/src/platforms/c64/lib/cc65-src/kbhit.s +23 -0
  312. package/src/platforms/c64/lib/cc65-src/kbrepeat.s +14 -0
  313. package/src/platforms/c64/lib/cc65-src/kernal.s +53 -0
  314. package/src/platforms/c64/lib/cc65-src/kplot.s +22 -0
  315. package/src/platforms/c64/lib/cc65-src/libref.s +16 -0
  316. package/src/platforms/c64/lib/cc65-src/mainargs.s +137 -0
  317. package/src/platforms/c64/lib/cc65-src/mcbdefault.s +146 -0
  318. package/src/platforms/c64/lib/cc65-src/mcbspritedata.s +4 -0
  319. package/src/platforms/c64/lib/cc65-src/mou/c64-1351.s +467 -0
  320. package/src/platforms/c64/lib/cc65-src/mou/c64-inkwell.s +446 -0
  321. package/src/platforms/c64/lib/cc65-src/mou/c64-joy.s +451 -0
  322. package/src/platforms/c64/lib/cc65-src/mou/c64-pot.s +409 -0
  323. package/src/platforms/c64/lib/cc65-src/mouse_stat_stddrv.s +14 -0
  324. package/src/platforms/c64/lib/cc65-src/mouse_stddrv.s +14 -0
  325. package/src/platforms/c64/lib/cc65-src/mouseref.s +23 -0
  326. package/src/platforms/c64/lib/cc65-src/pencalib.c +94 -0
  327. package/src/platforms/c64/lib/cc65-src/randomize.s +18 -0
  328. package/src/platforms/c64/lib/cc65-src/revers.s +27 -0
  329. package/src/platforms/c64/lib/cc65-src/ser/c64-swlink.s +484 -0
  330. package/src/platforms/c64/lib/cc65-src/ser_stat_stddrv.s +14 -0
  331. package/src/platforms/c64/lib/cc65-src/ser_stddrv.s +13 -0
  332. package/src/platforms/c64/lib/cc65-src/settime.s +84 -0
  333. package/src/platforms/c64/lib/cc65-src/soft80.inc +46 -0
  334. package/src/platforms/c64/lib/cc65-src/soft80_cgetc.s +85 -0
  335. package/src/platforms/c64/lib/cc65-src/soft80_charset.s +182 -0
  336. package/src/platforms/c64/lib/cc65-src/soft80_color.s +159 -0
  337. package/src/platforms/c64/lib/cc65-src/soft80_conio.s +157 -0
  338. package/src/platforms/c64/lib/cc65-src/soft80_cpeekc.s +148 -0
  339. package/src/platforms/c64/lib/cc65-src/soft80_cpeekcolor.s +19 -0
  340. package/src/platforms/c64/lib/cc65-src/soft80_cpeekrevers.s +15 -0
  341. package/src/platforms/c64/lib/cc65-src/soft80_cpeeks.s +71 -0
  342. package/src/platforms/c64/lib/cc65-src/soft80_cputc.s +521 -0
  343. package/src/platforms/c64/lib/cc65-src/soft80_kclrscr.s +76 -0
  344. package/src/platforms/c64/lib/cc65-src/soft80_kplot.s +63 -0
  345. package/src/platforms/c64/lib/cc65-src/soft80_scrsize.s +14 -0
  346. package/src/platforms/c64/lib/cc65-src/soft80mono_cgetc.s +67 -0
  347. package/src/platforms/c64/lib/cc65-src/soft80mono_color.s +65 -0
  348. package/src/platforms/c64/lib/cc65-src/soft80mono_conio.s +168 -0
  349. package/src/platforms/c64/lib/cc65-src/soft80mono_cpeekcolor.s +17 -0
  350. package/src/platforms/c64/lib/cc65-src/soft80mono_cputc.s +204 -0
  351. package/src/platforms/c64/lib/cc65-src/soft80mono_kclrscr.s +63 -0
  352. package/src/platforms/c64/lib/cc65-src/soft80mono_kplot.s +52 -0
  353. package/src/platforms/c64/lib/cc65-src/status.s +15 -0
  354. package/src/platforms/c64/lib/cc65-src/sysuname.s +37 -0
  355. package/src/platforms/c64/lib/cc65-src/tgi/c64-hi.s +881 -0
  356. package/src/platforms/c64/lib/cc65-src/tgi_stat_stddrv.s +14 -0
  357. package/src/platforms/c64/lib/cc65-src/tgi_stddrv.s +13 -0
  358. package/src/platforms/c64/lib/cc65-src/tmcommon.s +67 -0
  359. package/src/platforms/c64/lib/cc65-src/waitvsync.s +18 -0
  360. package/src/platforms/c64/lib/read_joystick.s +28 -0
  361. package/src/platforms/c64/lib/sid_play.s +48 -0
  362. package/src/platforms/c64/lib/sprite_table.s +73 -0
  363. package/src/platforms/c64/lib/vic_init.s +47 -0
  364. package/src/platforms/c64/sid.js +128 -0
  365. package/src/platforms/c64/vic.js +273 -0
  366. package/src/platforms/common/default-palette.js +139 -0
  367. package/src/platforms/common/image-to-tiles.js +407 -0
  368. package/src/platforms/common/intent.js +111 -0
  369. package/src/platforms/common/metasprite-adapters.js +279 -0
  370. package/src/platforms/common/metasprite-codegen.js +192 -0
  371. package/src/platforms/common/metasprite-core.js +201 -0
  372. package/src/platforms/common/metasprite.js +89 -0
  373. package/src/platforms/common/platform-palette.js +137 -0
  374. package/src/platforms/common/registers.js +329 -0
  375. package/src/platforms/common/render-tiles.js +86 -0
  376. package/src/platforms/common/screenshot-sprite.js +153 -0
  377. package/src/platforms/common/tile-decode.js +149 -0
  378. package/src/platforms/gb/MENTAL_MODEL.md +252 -0
  379. package/src/platforms/gb/TROUBLESHOOTING.md +221 -0
  380. package/src/platforms/gb/UPSTREAM_SOURCES.md +43 -0
  381. package/src/platforms/gb/image-to-tilemap.js +173 -0
  382. package/src/platforms/gb/lib/README.md +115 -0
  383. package/src/platforms/gb/lib/c/LICENSE-HUGEDRIVER +25 -0
  384. package/src/platforms/gb/lib/c/README.md +120 -0
  385. package/src/platforms/gb/lib/c/SDCC_GOTCHAS.md +189 -0
  386. package/src/platforms/gb/lib/c/gb_crt0.s +163 -0
  387. package/src/platforms/gb/lib/c/gb_hardware.h +113 -0
  388. package/src/platforms/gb/lib/c/gb_runtime.c +284 -0
  389. package/src/platforms/gb/lib/c/gb_runtime.h +145 -0
  390. package/src/platforms/gb/lib/c/hUGEDriver.c +191 -0
  391. package/src/platforms/gb/lib/c/hUGEDriver.h +95 -0
  392. package/src/platforms/gb/lib/c/hUGEDriver.upstream.asm +1908 -0
  393. package/src/platforms/gb/lib/c/lcd_init.c +19 -0
  394. package/src/platforms/gb/lib/c/patch-header.js +154 -0
  395. package/src/platforms/gb/lib/c/song_data.c +88 -0
  396. package/src/platforms/gb/lib/c/unroll.h +52 -0
  397. package/src/platforms/gb/lib/c/wait_vblank.c +14 -0
  398. package/src/platforms/gb/lib/dma_oam.asm +51 -0
  399. package/src/platforms/gb/lib/header.asm +56 -0
  400. package/src/platforms/gb/lib/joypad_read.asm +47 -0
  401. package/src/platforms/gb/lib/lcd_init.asm +44 -0
  402. package/src/platforms/gb/lib/load_palette.asm +25 -0
  403. package/src/platforms/gb/lib/load_tiles.asm +29 -0
  404. package/src/platforms/gb/lib/vblank_wait.asm +31 -0
  405. package/src/platforms/gb/ppu.js +574 -0
  406. package/src/platforms/gba/MENTAL_MODEL.md +203 -0
  407. package/src/platforms/gba/TROUBLESHOOTING.md +250 -0
  408. package/src/platforms/gba/UPSTREAM_SOURCES.md +41 -0
  409. package/src/platforms/gba/lib/arm-archives/libc.a +0 -0
  410. package/src/platforms/gba/lib/arm-archives/libgcc.a +0 -0
  411. package/src/platforms/gba/lib/arm-archives/libnosys.a +0 -0
  412. package/src/platforms/gba/lib/c/gba_sfx.c +81 -0
  413. package/src/platforms/gba/lib/c/gba_sfx.h +48 -0
  414. package/src/platforms/gba/lib/libgba/crtbegin.o +0 -0
  415. package/src/platforms/gba/lib/libgba/crtend.o +0 -0
  416. package/src/platforms/gba/lib/libgba/crti.o +0 -0
  417. package/src/platforms/gba/lib/libgba/crtn.o +0 -0
  418. package/src/platforms/gba/lib/libgba/gba_cart.ld +319 -0
  419. package/src/platforms/gba/lib/libgba/gba_crt0.s +258 -0
  420. package/src/platforms/gba/lib/libgba/include/BoyScout.h +128 -0
  421. package/src/platforms/gba/lib/libgba/include/disc.h +36 -0
  422. package/src/platforms/gba/lib/libgba/include/disc_io.h +64 -0
  423. package/src/platforms/gba/lib/libgba/include/dldi.h +112 -0
  424. package/src/platforms/gba/lib/libgba/include/erapi.h +195 -0
  425. package/src/platforms/gba/lib/libgba/include/fade.h +76 -0
  426. package/src/platforms/gba/lib/libgba/include/gba.h +47 -0
  427. package/src/platforms/gba/lib/libgba/include/gba_affine.h +83 -0
  428. package/src/platforms/gba/lib/libgba/include/gba_base.h +122 -0
  429. package/src/platforms/gba/lib/libgba/include/gba_compression.h +66 -0
  430. package/src/platforms/gba/lib/libgba/include/gba_console.h +55 -0
  431. package/src/platforms/gba/lib/libgba/include/gba_dma.h +100 -0
  432. package/src/platforms/gba/lib/libgba/include/gba_input.h +127 -0
  433. package/src/platforms/gba/lib/libgba/include/gba_interrupt.h +146 -0
  434. package/src/platforms/gba/lib/libgba/include/gba_multiboot.h +72 -0
  435. package/src/platforms/gba/lib/libgba/include/gba_sio.h +124 -0
  436. package/src/platforms/gba/lib/libgba/include/gba_sound.h +356 -0
  437. package/src/platforms/gba/lib/libgba/include/gba_sprites.h +195 -0
  438. package/src/platforms/gba/lib/libgba/include/gba_systemcalls.h +194 -0
  439. package/src/platforms/gba/lib/libgba/include/gba_timers.h +63 -0
  440. package/src/platforms/gba/lib/libgba/include/gba_types.h +60 -0
  441. package/src/platforms/gba/lib/libgba/include/gba_video.h +307 -0
  442. package/src/platforms/gba/lib/libgba/include/mappy.h +72 -0
  443. package/src/platforms/gba/lib/libgba/include/mbv2.h +90 -0
  444. package/src/platforms/gba/lib/libgba/include/xcomms.h +93 -0
  445. package/src/platforms/gba/lib/libgba/include/xcomms_cmd.h +53 -0
  446. package/src/platforms/gba/lib/libgba/libgba.seed.a +0 -0
  447. package/src/platforms/gba/lib/libgba/libgba.seed.hash +1 -0
  448. package/src/platforms/gba/lib/libgba/src/AffineSet.c +42 -0
  449. package/src/platforms/gba/lib/libgba/src/ArcTan.s +41 -0
  450. package/src/platforms/gba/lib/libgba/src/BoyScout/BoyScout.c +1242 -0
  451. package/src/platforms/gba/lib/libgba/src/BoyScout/GBASoundRegs.h +200 -0
  452. package/src/platforms/gba/lib/libgba/src/Compression.c +84 -0
  453. package/src/platforms/gba/lib/libgba/src/CpuSet.c +41 -0
  454. package/src/platforms/gba/lib/libgba/src/Div.s +58 -0
  455. package/src/platforms/gba/lib/libgba/src/DivArm.s +50 -0
  456. package/src/platforms/gba/lib/libgba/src/InterruptDispatcher.s +113 -0
  457. package/src/platforms/gba/lib/libgba/src/IntrWait.c +35 -0
  458. package/src/platforms/gba/lib/libgba/src/MultiBoot.s +33 -0
  459. package/src/platforms/gba/lib/libgba/src/Reset.s +49 -0
  460. package/src/platforms/gba/lib/libgba/src/Sound.s +48 -0
  461. package/src/platforms/gba/lib/libgba/src/Sqrt.s +34 -0
  462. package/src/platforms/gba/lib/libgba/src/disc_io/disc.c +58 -0
  463. package/src/platforms/gba/lib/libgba/src/disc_io/dldi.c +189 -0
  464. package/src/platforms/gba/lib/libgba/src/disc_io/dldi_stub.s +78 -0
  465. package/src/platforms/gba/lib/libgba/src/disc_io/io_cf_common.c +260 -0
  466. package/src/platforms/gba/lib/libgba/src/disc_io/io_cf_common.h +72 -0
  467. package/src/platforms/gba/lib/libgba/src/disc_io/io_m3_common.c +60 -0
  468. package/src/platforms/gba/lib/libgba/src/disc_io/io_m3_common.h +48 -0
  469. package/src/platforms/gba/lib/libgba/src/disc_io/io_m3cf.c +83 -0
  470. package/src/platforms/gba/lib/libgba/src/disc_io/io_m3cf.h +45 -0
  471. package/src/platforms/gba/lib/libgba/src/disc_io/io_m3sd.c +508 -0
  472. package/src/platforms/gba/lib/libgba/src/disc_io/io_m3sd.h +45 -0
  473. package/src/platforms/gba/lib/libgba/src/disc_io/io_mpcf.c +87 -0
  474. package/src/platforms/gba/lib/libgba/src/disc_io/io_mpcf.h +42 -0
  475. package/src/platforms/gba/lib/libgba/src/disc_io/io_sc_common.c +47 -0
  476. package/src/platforms/gba/lib/libgba/src/disc_io/io_sc_common.h +43 -0
  477. package/src/platforms/gba/lib/libgba/src/disc_io/io_sccf.c +83 -0
  478. package/src/platforms/gba/lib/libgba/src/disc_io/io_sccf.h +45 -0
  479. package/src/platforms/gba/lib/libgba/src/disc_io/io_scsd.c +385 -0
  480. package/src/platforms/gba/lib/libgba/src/disc_io/io_scsd.h +48 -0
  481. package/src/platforms/gba/lib/libgba/src/disc_io/io_scsd_s.s +139 -0
  482. package/src/platforms/gba/lib/libgba/src/disc_io/io_sd_common.c +203 -0
  483. package/src/platforms/gba/lib/libgba/src/disc_io/io_sd_common.h +108 -0
  484. package/src/platforms/gba/lib/libgba/src/fade.c +185 -0
  485. package/src/platforms/gba/lib/libgba/src/input.c +127 -0
  486. package/src/platforms/gba/lib/libgba/src/interrupt.c +116 -0
  487. package/src/platforms/gba/lib/libgba/src/mappy_print.c +74 -0
  488. package/src/platforms/gba/lib/libgba/src/mb2print.c +69 -0
  489. package/src/platforms/gba/lib/libgba/src/mbv2.c +230 -0
  490. package/src/platforms/gba/lib/libgba/src/mbv2.txt +119 -0
  491. package/src/platforms/gba/lib/libgba/src/xcomms.c +203 -0
  492. package/src/platforms/gba/lib/libgba/src/xcomms_print.c +56 -0
  493. package/src/platforms/gba/lib/libgba/sysinclude/_ansi.h +82 -0
  494. package/src/platforms/gba/lib/libgba/sysinclude/_newlib_version.h +11 -0
  495. package/src/platforms/gba/lib/libgba/sysinclude/_syslist.h +41 -0
  496. package/src/platforms/gba/lib/libgba/sysinclude/alloca.h +21 -0
  497. package/src/platforms/gba/lib/libgba/sysinclude/ar.h +65 -0
  498. package/src/platforms/gba/lib/libgba/sysinclude/argz.h +33 -0
  499. package/src/platforms/gba/lib/libgba/sysinclude/assert.h +50 -0
  500. package/src/platforms/gba/lib/libgba/sysinclude/complex.h +150 -0
  501. package/src/platforms/gba/lib/libgba/sysinclude/cpio.h +30 -0
  502. package/src/platforms/gba/lib/libgba/sysinclude/ctype.h +183 -0
  503. package/src/platforms/gba/lib/libgba/sysinclude/devctl.h +78 -0
  504. package/src/platforms/gba/lib/libgba/sysinclude/dirent.h +85 -0
  505. package/src/platforms/gba/lib/libgba/sysinclude/elf.h +3147 -0
  506. package/src/platforms/gba/lib/libgba/sysinclude/envlock.h +15 -0
  507. package/src/platforms/gba/lib/libgba/sysinclude/envz.h +16 -0
  508. package/src/platforms/gba/lib/libgba/sysinclude/errno.h +11 -0
  509. package/src/platforms/gba/lib/libgba/sysinclude/fastmath.h +13 -0
  510. package/src/platforms/gba/lib/libgba/sysinclude/fcntl.h +1 -0
  511. package/src/platforms/gba/lib/libgba/sysinclude/fenv.h +42 -0
  512. package/src/platforms/gba/lib/libgba/sysinclude/float.h +631 -0
  513. package/src/platforms/gba/lib/libgba/sysinclude/fnmatch.h +55 -0
  514. package/src/platforms/gba/lib/libgba/sysinclude/ftw.h +66 -0
  515. package/src/platforms/gba/lib/libgba/sysinclude/getopt.h +185 -0
  516. package/src/platforms/gba/lib/libgba/sysinclude/glob.h +90 -0
  517. package/src/platforms/gba/lib/libgba/sysinclude/grp.h +86 -0
  518. package/src/platforms/gba/lib/libgba/sysinclude/iconv.h +63 -0
  519. package/src/platforms/gba/lib/libgba/sysinclude/ieeefp.h +295 -0
  520. package/src/platforms/gba/lib/libgba/sysinclude/inttypes.h +345 -0
  521. package/src/platforms/gba/lib/libgba/sysinclude/iso646.h +45 -0
  522. package/src/platforms/gba/lib/libgba/sysinclude/langinfo.h +332 -0
  523. package/src/platforms/gba/lib/libgba/sysinclude/libgen.h +37 -0
  524. package/src/platforms/gba/lib/libgba/sysinclude/limits.h +168 -0
  525. package/src/platforms/gba/lib/libgba/sysinclude/locale.h +96 -0
  526. package/src/platforms/gba/lib/libgba/sysinclude/machine/_arc4random.h +1 -0
  527. package/src/platforms/gba/lib/libgba/sysinclude/machine/_default_types.h +250 -0
  528. package/src/platforms/gba/lib/libgba/sysinclude/machine/_endian.h +39 -0
  529. package/src/platforms/gba/lib/libgba/sysinclude/machine/_time.h +3 -0
  530. package/src/platforms/gba/lib/libgba/sysinclude/machine/_types.h +8 -0
  531. package/src/platforms/gba/lib/libgba/sysinclude/machine/ansi.h +1 -0
  532. package/src/platforms/gba/lib/libgba/sysinclude/machine/endian.h +69 -0
  533. package/src/platforms/gba/lib/libgba/sysinclude/machine/fastmath.h +98 -0
  534. package/src/platforms/gba/lib/libgba/sysinclude/machine/ieee.h +127 -0
  535. package/src/platforms/gba/lib/libgba/sysinclude/machine/ieeefp.h +533 -0
  536. package/src/platforms/gba/lib/libgba/sysinclude/machine/malloc.h +8 -0
  537. package/src/platforms/gba/lib/libgba/sysinclude/machine/param.h +8 -0
  538. package/src/platforms/gba/lib/libgba/sysinclude/machine/setjmp-dj.h +43 -0
  539. package/src/platforms/gba/lib/libgba/sysinclude/machine/setjmp.h +524 -0
  540. package/src/platforms/gba/lib/libgba/sysinclude/machine/stdlib.h +8 -0
  541. package/src/platforms/gba/lib/libgba/sysinclude/machine/termios.h +1 -0
  542. package/src/platforms/gba/lib/libgba/sysinclude/machine/time.h +15 -0
  543. package/src/platforms/gba/lib/libgba/sysinclude/machine/types.h +13 -0
  544. package/src/platforms/gba/lib/libgba/sysinclude/malloc.h +173 -0
  545. package/src/platforms/gba/lib/libgba/sysinclude/math.h +645 -0
  546. package/src/platforms/gba/lib/libgba/sysinclude/memory.h +4 -0
  547. package/src/platforms/gba/lib/libgba/sysinclude/ndbm.h +91 -0
  548. package/src/platforms/gba/lib/libgba/sysinclude/newlib.h +427 -0
  549. package/src/platforms/gba/lib/libgba/sysinclude/paths.h +9 -0
  550. package/src/platforms/gba/lib/libgba/sysinclude/pthread.h +456 -0
  551. package/src/platforms/gba/lib/libgba/sysinclude/pwd.h +83 -0
  552. package/src/platforms/gba/lib/libgba/sysinclude/reent.h +190 -0
  553. package/src/platforms/gba/lib/libgba/sysinclude/regdef.h +7 -0
  554. package/src/platforms/gba/lib/libgba/sysinclude/regex.h +103 -0
  555. package/src/platforms/gba/lib/libgba/sysinclude/sched.h +112 -0
  556. package/src/platforms/gba/lib/libgba/sysinclude/search.h +64 -0
  557. package/src/platforms/gba/lib/libgba/sysinclude/setjmp.h +25 -0
  558. package/src/platforms/gba/lib/libgba/sysinclude/signal.h +35 -0
  559. package/src/platforms/gba/lib/libgba/sysinclude/spawn.h +111 -0
  560. package/src/platforms/gba/lib/libgba/sysinclude/ssp/ssp.h +76 -0
  561. package/src/platforms/gba/lib/libgba/sysinclude/ssp/stdio.h +101 -0
  562. package/src/platforms/gba/lib/libgba/sysinclude/ssp/stdlib.h +30 -0
  563. package/src/platforms/gba/lib/libgba/sysinclude/ssp/string.h +115 -0
  564. package/src/platforms/gba/lib/libgba/sysinclude/ssp/strings.h +55 -0
  565. package/src/platforms/gba/lib/libgba/sysinclude/ssp/unistd.h +93 -0
  566. package/src/platforms/gba/lib/libgba/sysinclude/ssp/wchar.h +97 -0
  567. package/src/platforms/gba/lib/libgba/sysinclude/stdarg.h +135 -0
  568. package/src/platforms/gba/lib/libgba/sysinclude/stdatomic.h +409 -0
  569. package/src/platforms/gba/lib/libgba/sysinclude/stdbool.h +51 -0
  570. package/src/platforms/gba/lib/libgba/sysinclude/stddef.h +463 -0
  571. package/src/platforms/gba/lib/libgba/sysinclude/stdint.h +466 -0
  572. package/src/platforms/gba/lib/libgba/sysinclude/stdio.h +807 -0
  573. package/src/platforms/gba/lib/libgba/sysinclude/stdio_ext.h +79 -0
  574. package/src/platforms/gba/lib/libgba/sysinclude/stdlib.h +345 -0
  575. package/src/platforms/gba/lib/libgba/sysinclude/string.h +183 -0
  576. package/src/platforms/gba/lib/libgba/sysinclude/strings.h +80 -0
  577. package/src/platforms/gba/lib/libgba/sysinclude/sys/_default_fcntl.h +241 -0
  578. package/src/platforms/gba/lib/libgba/sysinclude/sys/_intsup.h +199 -0
  579. package/src/platforms/gba/lib/libgba/sysinclude/sys/_locale.h +12 -0
  580. package/src/platforms/gba/lib/libgba/sysinclude/sys/_pthreadtypes.h +233 -0
  581. package/src/platforms/gba/lib/libgba/sysinclude/sys/_sigset.h +43 -0
  582. package/src/platforms/gba/lib/libgba/sysinclude/sys/_stdint.h +90 -0
  583. package/src/platforms/gba/lib/libgba/sysinclude/sys/_timespec.h +52 -0
  584. package/src/platforms/gba/lib/libgba/sysinclude/sys/_timeval.h +60 -0
  585. package/src/platforms/gba/lib/libgba/sysinclude/sys/_types.h +228 -0
  586. package/src/platforms/gba/lib/libgba/sysinclude/sys/_tz_structs.h +24 -0
  587. package/src/platforms/gba/lib/libgba/sysinclude/sys/cdefs.h +754 -0
  588. package/src/platforms/gba/lib/libgba/sysinclude/sys/config.h +314 -0
  589. package/src/platforms/gba/lib/libgba/sysinclude/sys/custom_file.h +2 -0
  590. package/src/platforms/gba/lib/libgba/sysinclude/sys/dir.h +10 -0
  591. package/src/platforms/gba/lib/libgba/sysinclude/sys/dirent.h +13 -0
  592. package/src/platforms/gba/lib/libgba/sysinclude/sys/endian.h +207 -0
  593. package/src/platforms/gba/lib/libgba/sysinclude/sys/errno.h +198 -0
  594. package/src/platforms/gba/lib/libgba/sysinclude/sys/fcntl.h +12 -0
  595. package/src/platforms/gba/lib/libgba/sysinclude/sys/features.h +551 -0
  596. package/src/platforms/gba/lib/libgba/sysinclude/sys/fenv.h +90 -0
  597. package/src/platforms/gba/lib/libgba/sysinclude/sys/file.h +2 -0
  598. package/src/platforms/gba/lib/libgba/sysinclude/sys/iconvnls.h +77 -0
  599. package/src/platforms/gba/lib/libgba/sysinclude/sys/iosupport.h +143 -0
  600. package/src/platforms/gba/lib/libgba/sysinclude/sys/lock.h +75 -0
  601. package/src/platforms/gba/lib/libgba/sysinclude/sys/param.h +35 -0
  602. package/src/platforms/gba/lib/libgba/sysinclude/sys/queue.h +919 -0
  603. package/src/platforms/gba/lib/libgba/sysinclude/sys/reent.h +913 -0
  604. package/src/platforms/gba/lib/libgba/sysinclude/sys/resource.h +24 -0
  605. package/src/platforms/gba/lib/libgba/sysinclude/sys/sched.h +69 -0
  606. package/src/platforms/gba/lib/libgba/sysinclude/sys/select.h +94 -0
  607. package/src/platforms/gba/lib/libgba/sysinclude/sys/signal.h +388 -0
  608. package/src/platforms/gba/lib/libgba/sysinclude/sys/stat.h +179 -0
  609. package/src/platforms/gba/lib/libgba/sysinclude/sys/statvfs.h +41 -0
  610. package/src/platforms/gba/lib/libgba/sysinclude/sys/stdio.h +27 -0
  611. package/src/platforms/gba/lib/libgba/sysinclude/sys/string.h +2 -0
  612. package/src/platforms/gba/lib/libgba/sysinclude/sys/syslimits.h +61 -0
  613. package/src/platforms/gba/lib/libgba/sysinclude/sys/time.h +448 -0
  614. package/src/platforms/gba/lib/libgba/sysinclude/sys/timeb.h +40 -0
  615. package/src/platforms/gba/lib/libgba/sysinclude/sys/times.h +32 -0
  616. package/src/platforms/gba/lib/libgba/sysinclude/sys/timespec.h +63 -0
  617. package/src/platforms/gba/lib/libgba/sysinclude/sys/tree.h +864 -0
  618. package/src/platforms/gba/lib/libgba/sysinclude/sys/types.h +228 -0
  619. package/src/platforms/gba/lib/libgba/sysinclude/sys/unistd.h +591 -0
  620. package/src/platforms/gba/lib/libgba/sysinclude/sys/utime.h +22 -0
  621. package/src/platforms/gba/lib/libgba/sysinclude/sys/wait.h +44 -0
  622. package/src/platforms/gba/lib/libgba/sysinclude/tar.h +43 -0
  623. package/src/platforms/gba/lib/libgba/sysinclude/termios.h +7 -0
  624. package/src/platforms/gba/lib/libgba/sysinclude/tgmath.h +127 -0
  625. package/src/platforms/gba/lib/libgba/sysinclude/threads.h +93 -0
  626. package/src/platforms/gba/lib/libgba/sysinclude/time.h +313 -0
  627. package/src/platforms/gba/lib/libgba/sysinclude/unctrl.h +42 -0
  628. package/src/platforms/gba/lib/libgba/sysinclude/unistd.h +6 -0
  629. package/src/platforms/gba/lib/libgba/sysinclude/utime.h +12 -0
  630. package/src/platforms/gba/lib/libgba/sysinclude/utmp.h +8 -0
  631. package/src/platforms/gba/lib/libgba/sysinclude/varargs.h +7 -0
  632. package/src/platforms/gba/lib/libgba/sysinclude/wchar.h +339 -0
  633. package/src/platforms/gba/lib/libgba/sysinclude/wctype.h +74 -0
  634. package/src/platforms/gba/lib/libgba/sysinclude/wordexp.h +53 -0
  635. package/src/platforms/gba/lib/libtonc/crtbegin.o +0 -0
  636. package/src/platforms/gba/lib/libtonc/crtend.o +0 -0
  637. package/src/platforms/gba/lib/libtonc/crti.o +0 -0
  638. package/src/platforms/gba/lib/libtonc/crtn.o +0 -0
  639. package/src/platforms/gba/lib/libtonc/gba_cart.ld +319 -0
  640. package/src/platforms/gba/lib/libtonc/gba_crt0.s +258 -0
  641. package/src/platforms/gba/lib/libtonc/include/tonc.h +72 -0
  642. package/src/platforms/gba/lib/libtonc/include/tonc_asminc.h +132 -0
  643. package/src/platforms/gba/lib/libtonc/include/tonc_bios.h +555 -0
  644. package/src/platforms/gba/lib/libtonc/include/tonc_core.h +573 -0
  645. package/src/platforms/gba/lib/libtonc/include/tonc_input.h +184 -0
  646. package/src/platforms/gba/lib/libtonc/include/tonc_irq.h +121 -0
  647. package/src/platforms/gba/lib/libtonc/include/tonc_legacy.h +481 -0
  648. package/src/platforms/gba/lib/libtonc/include/tonc_libgba.h +537 -0
  649. package/src/platforms/gba/lib/libtonc/include/tonc_math.h +692 -0
  650. package/src/platforms/gba/lib/libtonc/include/tonc_memdef.h +962 -0
  651. package/src/platforms/gba/lib/libtonc/include/tonc_memmap.h +583 -0
  652. package/src/platforms/gba/lib/libtonc/include/tonc_nocash.h +51 -0
  653. package/src/platforms/gba/lib/libtonc/include/tonc_oam.h +186 -0
  654. package/src/platforms/gba/lib/libtonc/include/tonc_surface.h +461 -0
  655. package/src/platforms/gba/lib/libtonc/include/tonc_text.h +270 -0
  656. package/src/platforms/gba/lib/libtonc/include/tonc_tte.h +748 -0
  657. package/src/platforms/gba/lib/libtonc/include/tonc_types.h +376 -0
  658. package/src/platforms/gba/lib/libtonc/include/tonc_video.h +615 -0
  659. package/src/platforms/gba/lib/libtonc/libtonc.seed.a +0 -0
  660. package/src/platforms/gba/lib/libtonc/libtonc.seed.hash +1 -0
  661. package/src/platforms/gba/lib/libtonc/src/asm/clr_blend_fast.s +72 -0
  662. package/src/platforms/gba/lib/libtonc/src/asm/clr_fade_fast.s +74 -0
  663. package/src/platforms/gba/lib/libtonc/src/asm/div_lut.s +54 -0
  664. package/src/platforms/gba/lib/libtonc/src/asm/sin_lut.s +90 -0
  665. package/src/platforms/gba/lib/libtonc/src/asm/tonc_bios.s +289 -0
  666. package/src/platforms/gba/lib/libtonc/src/asm/tonc_bios_ex.s +97 -0
  667. package/src/platforms/gba/lib/libtonc/src/asm/tonc_isr_master.s +92 -0
  668. package/src/platforms/gba/lib/libtonc/src/asm/tonc_isr_nest.s +98 -0
  669. package/src/platforms/gba/lib/libtonc/src/asm/tonc_memcpy.s +126 -0
  670. package/src/platforms/gba/lib/libtonc/src/asm/tonc_memset.s +123 -0
  671. package/src/platforms/gba/lib/libtonc/src/asm/tonc_nocash.s +73 -0
  672. package/src/platforms/gba/lib/libtonc/src/font/sys8.png +0 -0
  673. package/src/platforms/gba/lib/libtonc/src/font/sys8.s +46 -0
  674. package/src/platforms/gba/lib/libtonc/src/font/verdana10.png +0 -0
  675. package/src/platforms/gba/lib/libtonc/src/font/verdana10.s +293 -0
  676. package/src/platforms/gba/lib/libtonc/src/font/verdana9.png +0 -0
  677. package/src/platforms/gba/lib/libtonc/src/font/verdana9.s +167 -0
  678. package/src/platforms/gba/lib/libtonc/src/font/verdana9_b4.png +0 -0
  679. package/src/platforms/gba/lib/libtonc/src/font/verdana9_b4.s +545 -0
  680. package/src/platforms/gba/lib/libtonc/src/font/verdana9b.png +0 -0
  681. package/src/platforms/gba/lib/libtonc/src/font/verdana9b.s +167 -0
  682. package/src/platforms/gba/lib/libtonc/src/font/verdana9i.png +0 -0
  683. package/src/platforms/gba/lib/libtonc/src/font/verdana9i.s +167 -0
  684. package/src/platforms/gba/lib/libtonc/src/pre1.3/tonc_bitmap.c +289 -0
  685. package/src/platforms/gba/lib/libtonc/src/pre1.3/tonc_text.c +81 -0
  686. package/src/platforms/gba/lib/libtonc/src/pre1.3/tonc_text_bm.c +244 -0
  687. package/src/platforms/gba/lib/libtonc/src/pre1.3/tonc_text_map.c +122 -0
  688. package/src/platforms/gba/lib/libtonc/src/pre1.3/tonc_text_oam.c +113 -0
  689. package/src/platforms/gba/lib/libtonc/src/pre1.3/toncfont.s +43 -0
  690. package/src/platforms/gba/lib/libtonc/src/tonc_bg.c +61 -0
  691. package/src/platforms/gba/lib/libtonc/src/tonc_bg_affine.c +112 -0
  692. package/src/platforms/gba/lib/libtonc/src/tonc_bmp16.c +240 -0
  693. package/src/platforms/gba/lib/libtonc/src/tonc_bmp8.c +314 -0
  694. package/src/platforms/gba/lib/libtonc/src/tonc_color.c +368 -0
  695. package/src/platforms/gba/lib/libtonc/src/tonc_core.c +237 -0
  696. package/src/platforms/gba/lib/libtonc/src/tonc_input.c +118 -0
  697. package/src/platforms/gba/lib/libtonc/src/tonc_irq.c +271 -0
  698. package/src/platforms/gba/lib/libtonc/src/tonc_math.c +54 -0
  699. package/src/platforms/gba/lib/libtonc/src/tonc_oam.c +76 -0
  700. package/src/platforms/gba/lib/libtonc/src/tonc_obj_affine.c +146 -0
  701. package/src/platforms/gba/lib/libtonc/src/tonc_sbmp16.c +369 -0
  702. package/src/platforms/gba/lib/libtonc/src/tonc_sbmp8.c +405 -0
  703. package/src/platforms/gba/lib/libtonc/src/tonc_schr4c.c +588 -0
  704. package/src/platforms/gba/lib/libtonc/src/tonc_schr4r.c +462 -0
  705. package/src/platforms/gba/lib/libtonc/src/tonc_surface.c +105 -0
  706. package/src/platforms/gba/lib/libtonc/src/tonc_video.c +33 -0
  707. package/src/platforms/gba/lib/libtonc/src/tte/ase_drawg.c +83 -0
  708. package/src/platforms/gba/lib/libtonc/src/tte/bmp16_drawg.c +72 -0
  709. package/src/platforms/gba/lib/libtonc/src/tte/bmp16_drawg_b1cs.c +92 -0
  710. package/src/platforms/gba/lib/libtonc/src/tte/bmp8_drawg.c +71 -0
  711. package/src/platforms/gba/lib/libtonc/src/tte/bmp8_drawg_b1cs.c +104 -0
  712. package/src/platforms/gba/lib/libtonc/src/tte/bmp8_drawg_b1cts_fast.s +115 -0
  713. package/src/platforms/gba/lib/libtonc/src/tte/chr4c_drawg_b1cts.c +76 -0
  714. package/src/platforms/gba/lib/libtonc/src/tte/chr4c_drawg_b1cts_fast.s +128 -0
  715. package/src/platforms/gba/lib/libtonc/src/tte/chr4c_drawg_b4cts.c +67 -0
  716. package/src/platforms/gba/lib/libtonc/src/tte/chr4c_drawg_b4cts_fast.s +127 -0
  717. package/src/platforms/gba/lib/libtonc/src/tte/chr4r_drawg_b1cts.c +80 -0
  718. package/src/platforms/gba/lib/libtonc/src/tte/chr4r_drawg_b1cts_fast.s +145 -0
  719. package/src/platforms/gba/lib/libtonc/src/tte/obj_drawg.c +61 -0
  720. package/src/platforms/gba/lib/libtonc/src/tte/se_drawg.c +110 -0
  721. package/src/platforms/gba/lib/libtonc/src/tte/tte_init_ase.c +87 -0
  722. package/src/platforms/gba/lib/libtonc/src/tte/tte_init_bmp.c +118 -0
  723. package/src/platforms/gba/lib/libtonc/src/tte/tte_init_chr4c.c +86 -0
  724. package/src/platforms/gba/lib/libtonc/src/tte/tte_init_chr4r.c +87 -0
  725. package/src/platforms/gba/lib/libtonc/src/tte/tte_init_obj.c +84 -0
  726. package/src/platforms/gba/lib/libtonc/src/tte/tte_init_se.c +96 -0
  727. package/src/platforms/gba/lib/libtonc/src/tte/tte_iohook.c +264 -0
  728. package/src/platforms/gba/lib/libtonc/src/tte/tte_main.c +756 -0
  729. package/src/platforms/gba/lib/libtonc/src/tte/tte_types.s +119 -0
  730. package/src/platforms/gba/lib/maxmod/LICENSE-MAXMOD +23 -0
  731. package/src/platforms/gba/lib/maxmod/asm_include/mp_defs.inc +117 -0
  732. package/src/platforms/gba/lib/maxmod/asm_include/mp_format_mas.inc +108 -0
  733. package/src/platforms/gba/lib/maxmod/asm_include/mp_macros.inc +195 -0
  734. package/src/platforms/gba/lib/maxmod/asm_include/mp_mas.inc +40 -0
  735. package/src/platforms/gba/lib/maxmod/asm_include/mp_mas_structs.inc +189 -0
  736. package/src/platforms/gba/lib/maxmod/asm_include/mp_mixer_ds.inc +46 -0
  737. package/src/platforms/gba/lib/maxmod/asm_include/mp_mixer_gba.inc +42 -0
  738. package/src/platforms/gba/lib/maxmod/asm_include/swi_gba.inc +23 -0
  739. package/src/platforms/gba/lib/maxmod/include/maxmod.h +412 -0
  740. package/src/platforms/gba/lib/maxmod/include/mm_types.h +333 -0
  741. package/src/platforms/gba/lib/maxmod/maxmod.seed.a +0 -0
  742. package/src/platforms/gba/lib/maxmod/maxmod.seed.hash +1 -0
  743. package/src/platforms/gba/lib/maxmod/music/chiptune.xm +0 -0
  744. package/src/platforms/gba/lib/maxmod/music/chiptune_soundbank.bin +0 -0
  745. package/src/platforms/gba/lib/maxmod/music/chiptune_soundbank.h +4 -0
  746. package/src/platforms/gba/lib/maxmod/music/make_chiptune_xm.js +203 -0
  747. package/src/platforms/gba/lib/maxmod/source/mm_effect.s +767 -0
  748. package/src/platforms/gba/lib/maxmod/source/mm_main.s +115 -0
  749. package/src/platforms/gba/lib/maxmod/source/mm_mas.s +4990 -0
  750. package/src/platforms/gba/lib/maxmod/source/mm_mas_arm.s +612 -0
  751. package/src/platforms/gba/lib/maxmod/source_gba/mm_init_default.s +98 -0
  752. package/src/platforms/gba/lib/maxmod/source_gba/mm_main_gba.s +292 -0
  753. package/src/platforms/gba/lib/maxmod/source_gba/mm_mixer_gba.s +1367 -0
  754. package/src/platforms/gba/lib/sysbase/gba_iosupport.c +138 -0
  755. package/src/platforms/gbc/MENTAL_MODEL.md +165 -0
  756. package/src/platforms/gbc/TROUBLESHOOTING.md +142 -0
  757. package/src/platforms/gbc/UPSTREAM_SOURCES.md +60 -0
  758. package/src/platforms/gbc/lib/c/LICENSE-HUGEDRIVER +25 -0
  759. package/src/platforms/gbc/lib/c/README.md +120 -0
  760. package/src/platforms/gbc/lib/c/SDCC_GOTCHAS.md +189 -0
  761. package/src/platforms/gbc/lib/c/gb_crt0.s +163 -0
  762. package/src/platforms/gbc/lib/c/gb_hardware.h +113 -0
  763. package/src/platforms/gbc/lib/c/gb_runtime.c +284 -0
  764. package/src/platforms/gbc/lib/c/gb_runtime.h +145 -0
  765. package/src/platforms/gbc/lib/c/hUGEDriver.c +191 -0
  766. package/src/platforms/gbc/lib/c/hUGEDriver.h +95 -0
  767. package/src/platforms/gbc/lib/c/hUGEDriver.upstream.asm +1908 -0
  768. package/src/platforms/gbc/lib/c/lcd_init.c +19 -0
  769. package/src/platforms/gbc/lib/c/patch-header.js +154 -0
  770. package/src/platforms/gbc/lib/c/song_data.c +88 -0
  771. package/src/platforms/gbc/lib/c/unroll.h +52 -0
  772. package/src/platforms/gbc/lib/c/wait_vblank.c +14 -0
  773. package/src/platforms/genesis/MENTAL_MODEL.md +223 -0
  774. package/src/platforms/genesis/TROUBLESHOOTING.md +193 -0
  775. package/src/platforms/genesis/UPSTREAM_SOURCES.md +52 -0
  776. package/src/platforms/genesis/image-to-tilemap.js +333 -0
  777. package/src/platforms/genesis/lib/README.md +157 -0
  778. package/src/platforms/genesis/lib/c/crtbegin.o +0 -0
  779. package/src/platforms/genesis/lib/c/crtend.o +0 -0
  780. package/src/platforms/genesis/lib/c/genesis.ld +44 -0
  781. package/src/platforms/genesis/lib/c/genesis_sfx.c +51 -0
  782. package/src/platforms/genesis/lib/c/genesis_sfx.h +49 -0
  783. package/src/platforms/genesis/lib/c/libc.a +0 -0
  784. package/src/platforms/genesis/lib/c/libgcc.a +0 -0
  785. package/src/platforms/genesis/lib/c/libm.a +0 -0
  786. package/src/platforms/genesis/lib/c/sega.s +71 -0
  787. package/src/platforms/genesis/lib/header.s +96 -0
  788. package/src/platforms/genesis/lib/nmi_safe.s +79 -0
  789. package/src/platforms/genesis/lib/pad_read.s +104 -0
  790. package/src/platforms/genesis/lib/sgdk/COPYING.RUNTIME +73 -0
  791. package/src/platforms/genesis/lib/sgdk/LICENSE +12 -0
  792. package/src/platforms/genesis/lib/sgdk/include/asm.h +52 -0
  793. package/src/platforms/genesis/lib/sgdk/include/asm_mac.i +9 -0
  794. package/src/platforms/genesis/lib/sgdk/include/bmp.h +690 -0
  795. package/src/platforms/genesis/lib/sgdk/include/config.h +208 -0
  796. package/src/platforms/genesis/lib/sgdk/include/dma.h +542 -0
  797. package/src/platforms/genesis/lib/sgdk/include/ext/console.h +387 -0
  798. package/src/platforms/genesis/lib/sgdk/include/ext/everdrive.h +116 -0
  799. package/src/platforms/genesis/lib/sgdk/include/ext/fat16.h +84 -0
  800. package/src/platforms/genesis/lib/sgdk/include/ext/flash-save/flash.h +164 -0
  801. package/src/platforms/genesis/lib/sgdk/include/ext/flash-save/saveman.h +177 -0
  802. package/src/platforms/genesis/lib/sgdk/include/ext/link_cable.h +316 -0
  803. package/src/platforms/genesis/lib/sgdk/include/ext/minimusic/minimus.h +29 -0
  804. package/src/platforms/genesis/lib/sgdk/include/ext/mw/16c550.h +221 -0
  805. package/src/platforms/genesis/lib/sgdk/include/ext/mw/comm.h +93 -0
  806. package/src/platforms/genesis/lib/sgdk/include/ext/mw/gamejolt.h +541 -0
  807. package/src/platforms/genesis/lib/sgdk/include/ext/mw/jsmn.h +471 -0
  808. package/src/platforms/genesis/lib/sgdk/include/ext/mw/json.h +122 -0
  809. package/src/platforms/genesis/lib/sgdk/include/ext/mw/lsd.h +172 -0
  810. package/src/platforms/genesis/lib/sgdk/include/ext/mw/megawifi.h +984 -0
  811. package/src/platforms/genesis/lib/sgdk/include/ext/mw/mw-msg.h +392 -0
  812. package/src/platforms/genesis/lib/sgdk/include/ext/mw/ssf_ed_pro.h +38 -0
  813. package/src/platforms/genesis/lib/sgdk/include/ext/mw/ssf_ed_x7.h +73 -0
  814. package/src/platforms/genesis/lib/sgdk/include/ext/serial/buffer.h +8 -0
  815. package/src/platforms/genesis/lib/sgdk/include/ext/serial/serial.h +133 -0
  816. package/src/platforms/genesis/lib/sgdk/include/ext/stb/stb_sprintf.h +1864 -0
  817. package/src/platforms/genesis/lib/sgdk/include/genesis.h +92 -0
  818. package/src/platforms/genesis/lib/sgdk/include/joy.h +482 -0
  819. package/src/platforms/genesis/lib/sgdk/include/kdebug.h +21 -0
  820. package/src/platforms/genesis/lib/sgdk/include/map.h +409 -0
  821. package/src/platforms/genesis/lib/sgdk/include/mapper.h +186 -0
  822. package/src/platforms/genesis/lib/sgdk/include/maths.h +1071 -0
  823. package/src/platforms/genesis/lib/sgdk/include/maths3D.h +480 -0
  824. package/src/platforms/genesis/lib/sgdk/include/memory.h +346 -0
  825. package/src/platforms/genesis/lib/sgdk/include/memory_base.h +37 -0
  826. package/src/platforms/genesis/lib/sgdk/include/object.h +171 -0
  827. package/src/platforms/genesis/lib/sgdk/include/pal.h +500 -0
  828. package/src/platforms/genesis/lib/sgdk/include/pool.h +171 -0
  829. package/src/platforms/genesis/lib/sgdk/include/psg.h +153 -0
  830. package/src/platforms/genesis/lib/sgdk/include/snd/pcm/snd_dpcm2.h +79 -0
  831. package/src/platforms/genesis/lib/sgdk/include/snd/pcm/snd_pcm.h +98 -0
  832. package/src/platforms/genesis/lib/sgdk/include/snd/pcm/snd_pcm4.h +125 -0
  833. package/src/platforms/genesis/lib/sgdk/include/snd/pcm/tab_vol.h +6 -0
  834. package/src/platforms/genesis/lib/sgdk/include/snd/smp_null.h +6 -0
  835. package/src/platforms/genesis/lib/sgdk/include/snd/smp_null_dpcm.h +6 -0
  836. package/src/platforms/genesis/lib/sgdk/include/snd/sound.h +70 -0
  837. package/src/platforms/genesis/lib/sgdk/include/snd/xgm.h +399 -0
  838. package/src/platforms/genesis/lib/sgdk/include/snd/xgm2.h +389 -0
  839. package/src/platforms/genesis/lib/sgdk/include/snd/z80_def.i80 +41 -0
  840. package/src/platforms/genesis/lib/sgdk/include/snd/z80_fct.i80 +83 -0
  841. package/src/platforms/genesis/lib/sgdk/include/snd/z80_mac.i80 +1476 -0
  842. package/src/platforms/genesis/lib/sgdk/include/sprite_eng.h +1095 -0
  843. package/src/platforms/genesis/lib/sgdk/include/sprite_eng_legacy.h +1030 -0
  844. package/src/platforms/genesis/lib/sgdk/include/sram.h +110 -0
  845. package/src/platforms/genesis/lib/sgdk/include/string.h +349 -0
  846. package/src/platforms/genesis/lib/sgdk/include/sys.h +511 -0
  847. package/src/platforms/genesis/lib/sgdk/include/tab_cnv.h +19 -0
  848. package/src/platforms/genesis/lib/sgdk/include/task.h +77 -0
  849. package/src/platforms/genesis/lib/sgdk/include/task_cst.h +33 -0
  850. package/src/platforms/genesis/lib/sgdk/include/timer.h +132 -0
  851. package/src/platforms/genesis/lib/sgdk/include/tools.h +450 -0
  852. package/src/platforms/genesis/lib/sgdk/include/types.h +320 -0
  853. package/src/platforms/genesis/lib/sgdk/include/vdp.h +1150 -0
  854. package/src/platforms/genesis/lib/sgdk/include/vdp_bg.h +723 -0
  855. package/src/platforms/genesis/lib/sgdk/include/vdp_pal.h +101 -0
  856. package/src/platforms/genesis/lib/sgdk/include/vdp_spr.h +448 -0
  857. package/src/platforms/genesis/lib/sgdk/include/vdp_tile.h +1136 -0
  858. package/src/platforms/genesis/lib/sgdk/include/vram.h +270 -0
  859. package/src/platforms/genesis/lib/sgdk/include/ym2612.h +87 -0
  860. package/src/platforms/genesis/lib/sgdk/include/z80_ctrl.h +420 -0
  861. package/src/platforms/genesis/lib/sgdk/libmd.seed.a +0 -0
  862. package/src/platforms/genesis/lib/sgdk/libmd.seed.hash +1 -0
  863. package/src/platforms/genesis/lib/sgdk/md.ld +120 -0
  864. package/src/platforms/genesis/lib/sgdk/music/demo.vgm +0 -0
  865. package/src/platforms/genesis/lib/sgdk/music/demo.xgc +0 -0
  866. package/src/platforms/genesis/lib/sgdk/music/demo.xgm +0 -0
  867. package/src/platforms/genesis/lib/sgdk/res/image/font_default.png +0 -0
  868. package/src/platforms/genesis/lib/sgdk/res/image/sgdk_logo.png +0 -0
  869. package/src/platforms/genesis/lib/sgdk/res/libres.h +10 -0
  870. package/src/platforms/genesis/lib/sgdk/res/libres.res +5 -0
  871. package/src/platforms/genesis/lib/sgdk/res/libres.s +166 -0
  872. package/src/platforms/genesis/lib/sgdk/res/sound/stop_xgm.bin +0 -0
  873. package/src/platforms/genesis/lib/sgdk/rom_header.c +33 -0
  874. package/src/platforms/genesis/lib/sgdk/sega.preprocessed.s +364 -0
  875. package/src/platforms/genesis/lib/sgdk/sega.s +365 -0
  876. package/src/platforms/genesis/lib/sgdk/src/bmp.c +1539 -0
  877. package/src/platforms/genesis/lib/sgdk/src/bmp_a.s +3477 -0
  878. package/src/platforms/genesis/lib/sgdk/src/boot/rom_header.c +33 -0
  879. package/src/platforms/genesis/lib/sgdk/src/boot/sega.s +365 -0
  880. package/src/platforms/genesis/lib/sgdk/src/dma.c +782 -0
  881. package/src/platforms/genesis/lib/sgdk/src/dma_a.s +23 -0
  882. package/src/platforms/genesis/lib/sgdk/src/error_a.s +376 -0
  883. package/src/platforms/genesis/lib/sgdk/src/ext/console.c +490 -0
  884. package/src/platforms/genesis/lib/sgdk/src/ext/everdrive.c +285 -0
  885. package/src/platforms/genesis/lib/sgdk/src/ext/fat16.c +610 -0
  886. package/src/platforms/genesis/lib/sgdk/src/ext/flash-save/README.md +112 -0
  887. package/src/platforms/genesis/lib/sgdk/src/ext/flash-save/flash.c +300 -0
  888. package/src/platforms/genesis/lib/sgdk/src/ext/flash-save/saveman.c +641 -0
  889. package/src/platforms/genesis/lib/sgdk/src/ext/link_cable.c +1758 -0
  890. package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/CHANGELOG.md +31 -0
  891. package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/LICENSE.txt +17 -0
  892. package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/README.md +18 -0
  893. package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/data.z80 +148 -0
  894. package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/define.z80 +173 -0
  895. package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/doc/api-c.md +80 -0
  896. package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/doc/format.md +132 -0
  897. package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/doc/teradrive.md +33 -0
  898. package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/fm.z80 +363 -0
  899. package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/main.z80 +433 -0
  900. package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/minimus.c +129 -0
  901. package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/minimus_drv.s80 +17 -0
  902. package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/psg.z80 +231 -0
  903. package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/track.z80 +398 -0
  904. package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/util.z80 +98 -0
  905. package/src/platforms/genesis/lib/sgdk/src/ext/mw/16c550.c +84 -0
  906. package/src/platforms/genesis/lib/sgdk/src/ext/mw/README.md +849 -0
  907. package/src/platforms/genesis/lib/sgdk/src/ext/mw/comm.c +141 -0
  908. package/src/platforms/genesis/lib/sgdk/src/ext/mw/gamejolt.c +758 -0
  909. package/src/platforms/genesis/lib/sgdk/src/ext/mw/json.c +153 -0
  910. package/src/platforms/genesis/lib/sgdk/src/ext/mw/lsd.c +364 -0
  911. package/src/platforms/genesis/lib/sgdk/src/ext/mw/megawifi.c +1501 -0
  912. package/src/platforms/genesis/lib/sgdk/src/ext/mw/ssf_ed_pro.c +98 -0
  913. package/src/platforms/genesis/lib/sgdk/src/ext/mw/ssf_ed_x7.c +67 -0
  914. package/src/platforms/genesis/lib/sgdk/src/ext/serial/buffer.c +69 -0
  915. package/src/platforms/genesis/lib/sgdk/src/ext/serial/serial.c +158 -0
  916. package/src/platforms/genesis/lib/sgdk/src/joy.c +1361 -0
  917. package/src/platforms/genesis/lib/sgdk/src/kdebug.s +109 -0
  918. package/src/platforms/genesis/lib/sgdk/src/map.c +1915 -0
  919. package/src/platforms/genesis/lib/sgdk/src/mapper.c +280 -0
  920. package/src/platforms/genesis/lib/sgdk/src/maths.c +878 -0
  921. package/src/platforms/genesis/lib/sgdk/src/maths3D.c +480 -0
  922. package/src/platforms/genesis/lib/sgdk/src/maths3D_a.s +205 -0
  923. package/src/platforms/genesis/lib/sgdk/src/memory.c +760 -0
  924. package/src/platforms/genesis/lib/sgdk/src/memory_a.s +306 -0
  925. package/src/platforms/genesis/lib/sgdk/src/object.c +111 -0
  926. package/src/platforms/genesis/lib/sgdk/src/pal.c +484 -0
  927. package/src/platforms/genesis/lib/sgdk/src/pool.c +234 -0
  928. package/src/platforms/genesis/lib/sgdk/src/psg.c +82 -0
  929. package/src/platforms/genesis/lib/sgdk/src/snd/drv_null.s80 +27 -0
  930. package/src/platforms/genesis/lib/sgdk/src/snd/drv_xgm.s80 +3037 -0
  931. package/src/platforms/genesis/lib/sgdk/src/snd/pcm/drv_dpcm2.s80 +984 -0
  932. package/src/platforms/genesis/lib/sgdk/src/snd/pcm/drv_pcm.s80 +592 -0
  933. package/src/platforms/genesis/lib/sgdk/src/snd/pcm/drv_pcm4.s80 +699 -0
  934. package/src/platforms/genesis/lib/sgdk/src/snd/pcm/snd_dpcm2.c +172 -0
  935. package/src/platforms/genesis/lib/sgdk/src/snd/pcm/snd_pcm.c +152 -0
  936. package/src/platforms/genesis/lib/sgdk/src/snd/pcm/snd_pcm4.c +213 -0
  937. package/src/platforms/genesis/lib/sgdk/src/snd/pcm/tab_vol.c +277 -0
  938. package/src/platforms/genesis/lib/sgdk/src/snd/smp_null.s +22 -0
  939. package/src/platforms/genesis/lib/sgdk/src/snd/smp_null_dpcm.s +15 -0
  940. package/src/platforms/genesis/lib/sgdk/src/snd/sound.c +33 -0
  941. package/src/platforms/genesis/lib/sgdk/src/snd/xgm.c +683 -0
  942. package/src/platforms/genesis/lib/sgdk/src/snd/xgm2/drv_xgm2.s80 +993 -0
  943. package/src/platforms/genesis/lib/sgdk/src/snd/xgm2/drv_xgm2_fct.i80 +611 -0
  944. package/src/platforms/genesis/lib/sgdk/src/snd/xgm2/drv_xgm2_mac.i80 +133 -0
  945. package/src/platforms/genesis/lib/sgdk/src/snd/xgm2/drv_xgm2_pcm_fct.i80 +114 -0
  946. package/src/platforms/genesis/lib/sgdk/src/snd/xgm2/drv_xgm2_pcm_mac.i80 +1444 -0
  947. package/src/platforms/genesis/lib/sgdk/src/snd/xgm2/drv_xgm2_psg_fct.i80 +491 -0
  948. package/src/platforms/genesis/lib/sgdk/src/snd/xgm2/drv_xgm2_psg_mac.i80 +43 -0
  949. package/src/platforms/genesis/lib/sgdk/src/snd/xgm2/drv_xgm2_ym_fct.i80 +1664 -0
  950. package/src/platforms/genesis/lib/sgdk/src/snd/xgm2/drv_xgm2_ym_mac.i80 +295 -0
  951. package/src/platforms/genesis/lib/sgdk/src/snd/xgm2.c +1083 -0
  952. package/src/platforms/genesis/lib/sgdk/src/sprite_eng.c +2256 -0
  953. package/src/platforms/genesis/lib/sgdk/src/sprite_eng_legacy.c +2309 -0
  954. package/src/platforms/genesis/lib/sgdk/src/sram.c +30 -0
  955. package/src/platforms/genesis/lib/sgdk/src/sram_a.s +41 -0
  956. package/src/platforms/genesis/lib/sgdk/src/string.c +720 -0
  957. package/src/platforms/genesis/lib/sgdk/src/sys.c +1053 -0
  958. package/src/platforms/genesis/lib/sgdk/src/sys_a.s +74 -0
  959. package/src/platforms/genesis/lib/sgdk/src/tab_cnv.c +129 -0
  960. package/src/platforms/genesis/lib/sgdk/src/tab_log10.c +8201 -0
  961. package/src/platforms/genesis/lib/sgdk/src/tab_log2.c +8201 -0
  962. package/src/platforms/genesis/lib/sgdk/src/tab_sin.c +2058 -0
  963. package/src/platforms/genesis/lib/sgdk/src/tab_sqrt.c +8201 -0
  964. package/src/platforms/genesis/lib/sgdk/src/task.s +148 -0
  965. package/src/platforms/genesis/lib/sgdk/src/timer.c +201 -0
  966. package/src/platforms/genesis/lib/sgdk/src/tools.c +1299 -0
  967. package/src/platforms/genesis/lib/sgdk/src/tools_a.s +979 -0
  968. package/src/platforms/genesis/lib/sgdk/src/types.c +18 -0
  969. package/src/platforms/genesis/lib/sgdk/src/vdp.c +1060 -0
  970. package/src/platforms/genesis/lib/sgdk/src/vdp_bg.c +511 -0
  971. package/src/platforms/genesis/lib/sgdk/src/vdp_spr.c +322 -0
  972. package/src/platforms/genesis/lib/sgdk/src/vdp_tile.c +1011 -0
  973. package/src/platforms/genesis/lib/sgdk/src/vdp_tile_a.s +68 -0
  974. package/src/platforms/genesis/lib/sgdk/src/vram.c +273 -0
  975. package/src/platforms/genesis/lib/sgdk/src/ym2612.c +175 -0
  976. package/src/platforms/genesis/lib/sgdk/src/z80_ctrl.c +334 -0
  977. package/src/platforms/genesis/lib/sprite_table.s +129 -0
  978. package/src/platforms/genesis/lib/vblank_wait.s +73 -0
  979. package/src/platforms/genesis/lib/vdp_init.s +85 -0
  980. package/src/platforms/genesis/lib/wram.s +88 -0
  981. package/src/platforms/genesis/lib/z80_bootstrap.s +102 -0
  982. package/src/platforms/genesis/vdp.js +495 -0
  983. package/src/platforms/gg/MENTAL_MODEL.md +155 -0
  984. package/src/platforms/gg/TROUBLESHOOTING.md +91 -0
  985. package/src/platforms/gg/UPSTREAM_SOURCES.md +36 -0
  986. package/src/platforms/gg/lib/c/gg_crt0.s +112 -0
  987. package/src/platforms/gg/lib/c/gg_hw.h +62 -0
  988. package/src/platforms/gg/lib/c/gg_music.c +155 -0
  989. package/src/platforms/gg/lib/c/gg_music.h +89 -0
  990. package/src/platforms/gg/lib/c/gg_sfx.c +82 -0
  991. package/src/platforms/gg/lib/c/gg_sfx.h +40 -0
  992. package/src/platforms/gg/lib/c/joypad_read.c +22 -0
  993. package/src/platforms/gg/lib/c/load_palette.c +20 -0
  994. package/src/platforms/gg/lib/c/load_tiles.c +32 -0
  995. package/src/platforms/gg/lib/c/sprite_table.c +60 -0
  996. package/src/platforms/gg/lib/c/vblank_wait.c +10 -0
  997. package/src/platforms/gg/lib/c/vdp_init.c +58 -0
  998. package/src/platforms/index.js +7 -0
  999. package/src/platforms/lynx/MENTAL_MODEL.md +231 -0
  1000. package/src/platforms/lynx/TROUBLESHOOTING.md +105 -0
  1001. package/src/platforms/lynx/UPSTREAM_SOURCES.md +66 -0
  1002. package/src/platforms/lynx/lib/c/lynx_music.c +63 -0
  1003. package/src/platforms/lynx/lib/c/lynx_music.h +16 -0
  1004. package/src/platforms/lynx/lib/c/lynx_sfx.c +147 -0
  1005. package/src/platforms/lynx/lib/c/lynx_sfx.h +59 -0
  1006. package/src/platforms/lynx/lib/cc65-src/bllhdr.s +18 -0
  1007. package/src/platforms/lynx/lib/cc65-src/bootldr.s +195 -0
  1008. package/src/platforms/lynx/lib/cc65-src/cgetc.s +69 -0
  1009. package/src/platforms/lynx/lib/cc65-src/clock.s +87 -0
  1010. package/src/platforms/lynx/lib/cc65-src/crt0.s +135 -0
  1011. package/src/platforms/lynx/lib/cc65-src/defdir.s +29 -0
  1012. package/src/platforms/lynx/lib/cc65-src/eeprom.s +255 -0
  1013. package/src/platforms/lynx/lib/cc65-src/eeprom46.s +204 -0
  1014. package/src/platforms/lynx/lib/cc65-src/eeprom66.s +227 -0
  1015. package/src/platforms/lynx/lib/cc65-src/eeprom86.s +236 -0
  1016. package/src/platforms/lynx/lib/cc65-src/exec.s +34 -0
  1017. package/src/platforms/lynx/lib/cc65-src/exehdr.s +27 -0
  1018. package/src/platforms/lynx/lib/cc65-src/extzp.inc +23 -0
  1019. package/src/platforms/lynx/lib/cc65-src/extzp.s +30 -0
  1020. package/src/platforms/lynx/lib/cc65-src/irq.s +45 -0
  1021. package/src/platforms/lynx/lib/cc65-src/joy/lynx-stdjoy.s +93 -0
  1022. package/src/platforms/lynx/lib/cc65-src/joy_stat_stddrv.s +14 -0
  1023. package/src/platforms/lynx/lib/cc65-src/kbhit.s +56 -0
  1024. package/src/platforms/lynx/lib/cc65-src/libref.s +9 -0
  1025. package/src/platforms/lynx/lib/cc65-src/load.s +41 -0
  1026. package/src/platforms/lynx/lib/cc65-src/lseek.s +58 -0
  1027. package/src/platforms/lynx/lib/cc65-src/lynx-cart.s +98 -0
  1028. package/src/platforms/lynx/lib/cc65-src/lynx-snd.s +1270 -0
  1029. package/src/platforms/lynx/lib/cc65-src/mainargs.s +24 -0
  1030. package/src/platforms/lynx/lib/cc65-src/open.s +136 -0
  1031. package/src/platforms/lynx/lib/cc65-src/oserror.s +14 -0
  1032. package/src/platforms/lynx/lib/cc65-src/read.s +44 -0
  1033. package/src/platforms/lynx/lib/cc65-src/ser/lynx-comlynx.s +404 -0
  1034. package/src/platforms/lynx/lib/cc65-src/ser_stat_stddrv.s +14 -0
  1035. package/src/platforms/lynx/lib/cc65-src/sysuname.s +39 -0
  1036. package/src/platforms/lynx/lib/cc65-src/tgi/lynx-160-102-16.s +1075 -0
  1037. package/src/platforms/lynx/lib/cc65-src/tgi_colors.s +9 -0
  1038. package/src/platforms/lynx/lib/cc65-src/tgi_irq.s +11 -0
  1039. package/src/platforms/lynx/lib/cc65-src/tgi_stat_stddrv.s +14 -0
  1040. package/src/platforms/lynx/lib/cc65-src/tgi_stddrv.s +13 -0
  1041. package/src/platforms/lynx/lib/cc65-src/uploader.s +81 -0
  1042. package/src/platforms/nes/MENTAL_MODEL.md +301 -0
  1043. package/src/platforms/nes/TROUBLESHOOTING.md +321 -0
  1044. package/src/platforms/nes/UPSTREAM_SOURCES.md +31 -0
  1045. package/src/platforms/nes/image-to-chr.js +195 -0
  1046. package/src/platforms/nes/image-to-tilemap.js +415 -0
  1047. package/src/platforms/nes/lib/README.md +40 -0
  1048. package/src/platforms/nes/lib/asm/LICENSE-FAMITONE +40 -0
  1049. package/src/platforms/nes/lib/asm/chr_ram_header.s +32 -0
  1050. package/src/platforms/nes/lib/asm/famitone2.s +1258 -0
  1051. package/src/platforms/nes/lib/asm/famitone_bridge.s +50 -0
  1052. package/src/platforms/nes/lib/asm/music_data.s +238 -0
  1053. package/src/platforms/nes/lib/c/chr_ram_runtime_hello_sprite.c +81 -0
  1054. package/src/platforms/nes/lib/c/chr_ram_runtime_hud_row.c +101 -0
  1055. package/src/platforms/nes/lib/c/nes_runtime.c +347 -0
  1056. package/src/platforms/nes/lib/c/nes_runtime.h +153 -0
  1057. package/src/platforms/nes/lib/c/nmi_handler.c +51 -0
  1058. package/src/platforms/nes/lib/c/nmi_trampoline.s +25 -0
  1059. package/src/platforms/nes/lib/cc65-src/Makefile.inc +9 -0
  1060. package/src/platforms/nes/lib/cc65-src/_scrsize.s +24 -0
  1061. package/src/platforms/nes/lib/cc65-src/cclear.s +29 -0
  1062. package/src/platforms/nes/lib/cc65-src/chline.s +31 -0
  1063. package/src/platforms/nes/lib/cc65-src/clock.s +31 -0
  1064. package/src/platforms/nes/lib/cc65-src/clrscr.s +72 -0
  1065. package/src/platforms/nes/lib/cc65-src/color.s +68 -0
  1066. package/src/platforms/nes/lib/cc65-src/cpeekc.s +37 -0
  1067. package/src/platforms/nes/lib/cc65-src/cpeekcolor.s +8 -0
  1068. package/src/platforms/nes/lib/cc65-src/cpeekrevers.s +37 -0
  1069. package/src/platforms/nes/lib/cc65-src/cputc.s +95 -0
  1070. package/src/platforms/nes/lib/cc65-src/crt0.s +180 -0
  1071. package/src/platforms/nes/lib/cc65-src/cvline.s +31 -0
  1072. package/src/platforms/nes/lib/cc65-src/get_tv.s +37 -0
  1073. package/src/platforms/nes/lib/cc65-src/gotox.s +21 -0
  1074. package/src/platforms/nes/lib/cc65-src/gotoxy.s +22 -0
  1075. package/src/platforms/nes/lib/cc65-src/gotoy.s +22 -0
  1076. package/src/platforms/nes/lib/cc65-src/irq.s +19 -0
  1077. package/src/platforms/nes/lib/cc65-src/joy/nes-stdjoy.s +102 -0
  1078. package/src/platforms/nes/lib/cc65-src/joy_stat_stddrv.s +14 -0
  1079. package/src/platforms/nes/lib/cc65-src/libref.s +9 -0
  1080. package/src/platforms/nes/lib/cc65-src/mainargs.s +24 -0
  1081. package/src/platforms/nes/lib/cc65-src/neschar.s +4616 -0
  1082. package/src/platforms/nes/lib/cc65-src/ppu.s +158 -0
  1083. package/src/platforms/nes/lib/cc65-src/ppubuf.s +117 -0
  1084. package/src/platforms/nes/lib/cc65-src/randomize.s +18 -0
  1085. package/src/platforms/nes/lib/cc65-src/revers.s +27 -0
  1086. package/src/platforms/nes/lib/cc65-src/setcursor.s +37 -0
  1087. package/src/platforms/nes/lib/cc65-src/sysuname.s +39 -0
  1088. package/src/platforms/nes/lib/cc65-src/tgi/nes-64-56-2.s +480 -0
  1089. package/src/platforms/nes/lib/cc65-src/tgi_stat_stddrv.s +14 -0
  1090. package/src/platforms/nes/lib/cc65-src/tgi_stddrv.s +13 -0
  1091. package/src/platforms/nes/lib/cc65-src/waitvsync.s +18 -0
  1092. package/src/platforms/nes/lib/cc65-src/wherex.s +19 -0
  1093. package/src/platforms/nes/lib/cc65-src/wherey.s +19 -0
  1094. package/src/platforms/nes/lib/clear_nametable.s +38 -0
  1095. package/src/platforms/nes/lib/clear_oam.s +18 -0
  1096. package/src/platforms/nes/lib/load_palette.s +31 -0
  1097. package/src/platforms/nes/lib/nmi_safe.s +65 -0
  1098. package/src/platforms/nes/lib/oam_dma.s +16 -0
  1099. package/src/platforms/nes/lib/read_pad.s +46 -0
  1100. package/src/platforms/nes/lib/reset.s +46 -0
  1101. package/src/platforms/nes/lib/sprite_table_populate.s +75 -0
  1102. package/src/platforms/nes/lib/wait_vblank.s +12 -0
  1103. package/src/platforms/nes/palette.js +39 -0
  1104. package/src/platforms/nes/ppu.js +372 -0
  1105. package/src/platforms/sms/MENTAL_MODEL.md +267 -0
  1106. package/src/platforms/sms/TROUBLESHOOTING.md +124 -0
  1107. package/src/platforms/sms/UPSTREAM_SOURCES.md +29 -0
  1108. package/src/platforms/sms/image-to-tilemap.js +260 -0
  1109. package/src/platforms/sms/lib/README.md +117 -0
  1110. package/src/platforms/sms/lib/c/joypad_read.c +33 -0
  1111. package/src/platforms/sms/lib/c/load_palette.c +24 -0
  1112. package/src/platforms/sms/lib/c/load_tiles.c +32 -0
  1113. package/src/platforms/sms/lib/c/sms_crt0.s +101 -0
  1114. package/src/platforms/sms/lib/c/sms_hw.h +53 -0
  1115. package/src/platforms/sms/lib/c/sms_music.c +178 -0
  1116. package/src/platforms/sms/lib/c/sms_music.h +50 -0
  1117. package/src/platforms/sms/lib/c/sms_sfx.c +82 -0
  1118. package/src/platforms/sms/lib/c/sms_sfx.h +40 -0
  1119. package/src/platforms/sms/lib/c/sprite_table.c +60 -0
  1120. package/src/platforms/sms/lib/c/vblank_wait.c +10 -0
  1121. package/src/platforms/sms/lib/c/vdp_init.c +58 -0
  1122. package/src/platforms/sms/lib/header.s +33 -0
  1123. package/src/platforms/sms/lib/joypad_read.s +40 -0
  1124. package/src/platforms/sms/lib/load_palette.s +30 -0
  1125. package/src/platforms/sms/lib/load_tiles.s +50 -0
  1126. package/src/platforms/sms/lib/sprite_table.s +44 -0
  1127. package/src/platforms/sms/lib/vblank_wait.s +36 -0
  1128. package/src/platforms/sms/lib/vdp_init.s +47 -0
  1129. package/src/platforms/sms/vdp.js +530 -0
  1130. package/src/platforms/snes/MENTAL_MODEL.md +275 -0
  1131. package/src/platforms/snes/TROUBLESHOOTING.md +208 -0
  1132. package/src/platforms/snes/UPSTREAM_SOURCES.md +50 -0
  1133. package/src/platforms/snes/brr.js +208 -0
  1134. package/src/platforms/snes/image-to-tilemap.js +227 -0
  1135. package/src/platforms/snes/lib/audio/apu_blob.asm +228 -0
  1136. package/src/platforms/snes/lib/audio/apu_blob.bin +0 -0
  1137. package/src/platforms/snes/lib/audio/explosion.brr +0 -0
  1138. package/src/platforms/snes/lib/audio/sample_bank.bin +0 -0
  1139. package/src/platforms/snes/lib/audio/shoot.brr +0 -0
  1140. package/src/platforms/snes/lib/audio/spc_driver.asm +241 -0
  1141. package/src/platforms/snes/lib/audio_pipeline.asm +62 -0
  1142. package/src/platforms/snes/lib/c/crt0.asm +125 -0
  1143. package/src/platforms/snes/lib/c/hdr.asm +50 -0
  1144. package/src/platforms/snes/lib/c/snes_sfx.c +116 -0
  1145. package/src/platforms/snes/lib/c/snes_sfx.h +96 -0
  1146. package/src/platforms/snes/lib/c/snes_sfx_data.asm +25 -0
  1147. package/src/platforms/snes/lib/cgram_upload.asm +43 -0
  1148. package/src/platforms/snes/lib/lorom_header.asm +47 -0
  1149. package/src/platforms/snes/lib/lorom_multibank.asm +66 -0
  1150. package/src/platforms/snes/lib/nmi_safe.asm +77 -0
  1151. package/src/platforms/snes/lib/oam_upload.asm +45 -0
  1152. package/src/platforms/snes/lib/pad_read.asm +64 -0
  1153. package/src/platforms/snes/lib/pvsneslib/LICENSE +21 -0
  1154. package/src/platforms/snes/lib/pvsneslib/include/ctype.h +6 -0
  1155. package/src/platforms/snes/lib/pvsneslib/include/float.h +4 -0
  1156. package/src/platforms/snes/lib/pvsneslib/include/hdr.asm +47 -0
  1157. package/src/platforms/snes/lib/pvsneslib/include/limits.h +13 -0
  1158. package/src/platforms/snes/lib/pvsneslib/include/math.h +10 -0
  1159. package/src/platforms/snes/lib/pvsneslib/include/setjmp.h +4 -0
  1160. package/src/platforms/snes/lib/pvsneslib/include/snes/background.h +396 -0
  1161. package/src/platforms/snes/lib/pvsneslib/include/snes/console.h +188 -0
  1162. package/src/platforms/snes/lib/pvsneslib/include/snes/dma.h +381 -0
  1163. package/src/platforms/snes/lib/pvsneslib/include/snes/input.h +289 -0
  1164. package/src/platforms/snes/lib/pvsneslib/include/snes/interrupt.h +264 -0
  1165. package/src/platforms/snes/lib/pvsneslib/include/snes/libversion.h +10 -0
  1166. package/src/platforms/snes/lib/pvsneslib/include/snes/lzss.h +43 -0
  1167. package/src/platforms/snes/lib/pvsneslib/include/snes/map.h +113 -0
  1168. package/src/platforms/snes/lib/pvsneslib/include/snes/object.h +234 -0
  1169. package/src/platforms/snes/lib/pvsneslib/include/snes/pixel.h +53 -0
  1170. package/src/platforms/snes/lib/pvsneslib/include/snes/scores.h +66 -0
  1171. package/src/platforms/snes/lib/pvsneslib/include/snes/snestypes.h +65 -0
  1172. package/src/platforms/snes/lib/pvsneslib/include/snes/sound.h +245 -0
  1173. package/src/platforms/snes/lib/pvsneslib/include/snes/sprite.h +456 -0
  1174. package/src/platforms/snes/lib/pvsneslib/include/snes/video.h +465 -0
  1175. package/src/platforms/snes/lib/pvsneslib/include/snes.h +190 -0
  1176. package/src/platforms/snes/lib/pvsneslib/include/stdarg.h +28 -0
  1177. package/src/platforms/snes/lib/pvsneslib/include/stdbool.h +53 -0
  1178. package/src/platforms/snes/lib/pvsneslib/include/stddef.h +27 -0
  1179. package/src/platforms/snes/lib/pvsneslib/include/stdint.h +7 -0
  1180. package/src/platforms/snes/lib/pvsneslib/include/stdio.h +9 -0
  1181. package/src/platforms/snes/lib/pvsneslib/include/stdlib.h +13 -0
  1182. package/src/platforms/snes/lib/pvsneslib/include/string.h +19 -0
  1183. package/src/platforms/snes/lib/pvsneslib/include/strings.h +5 -0
  1184. package/src/platforms/snes/lib/pvsneslib/source/Makefile +87 -0
  1185. package/src/platforms/snes/lib/pvsneslib/source/backgrounds.asm +834 -0
  1186. package/src/platforms/snes/lib/pvsneslib/source/consoles.asm +1028 -0
  1187. package/src/platforms/snes/lib/pvsneslib/source/crt0_snes.asm +329 -0
  1188. package/src/platforms/snes/lib/pvsneslib/source/dmas.asm +1275 -0
  1189. package/src/platforms/snes/lib/pvsneslib/source/hdr.asm +56 -0
  1190. package/src/platforms/snes/lib/pvsneslib/source/input.asm +445 -0
  1191. package/src/platforms/snes/lib/pvsneslib/source/libc.asm +485 -0
  1192. package/src/platforms/snes/lib/pvsneslib/source/libc_c.c +1214 -0
  1193. package/src/platforms/snes/lib/pvsneslib/source/libm.asm +510 -0
  1194. package/src/platforms/snes/lib/pvsneslib/source/libtcc.asm +374 -0
  1195. package/src/platforms/snes/lib/pvsneslib/source/lzsss.asm +256 -0
  1196. package/src/platforms/snes/lib/pvsneslib/source/maps.asm +1078 -0
  1197. package/src/platforms/snes/lib/pvsneslib/source/objects.asm +2881 -0
  1198. package/src/platforms/snes/lib/pvsneslib/source/scores.asm +226 -0
  1199. package/src/platforms/snes/lib/pvsneslib/source/sm_spc.asm +187 -0
  1200. package/src/platforms/snes/lib/pvsneslib/source/snesmodwla.asm +1186 -0
  1201. package/src/platforms/snes/lib/pvsneslib/source/sounds.asm +273 -0
  1202. package/src/platforms/snes/lib/pvsneslib/source/sprites.asm +3946 -0
  1203. package/src/platforms/snes/lib/pvsneslib/source/vblank.asm +917 -0
  1204. package/src/platforms/snes/lib/pvsneslib/source/videos.asm +1137 -0
  1205. package/src/platforms/snes/lib/reset_init.asm +31 -0
  1206. package/src/platforms/snes/lib/sprite_table_populate.asm +122 -0
  1207. package/src/platforms/snes/lib/vram_dma_upload.asm +42 -0
  1208. package/src/platforms/snes/ppu.js +606 -0
  1209. package/src/playtest/playtest.js +612 -0
  1210. package/src/rom-id/identifier.js +421 -0
  1211. package/src/rom-id/patch.js +217 -0
  1212. package/src/toolchains/_worker/pool.js +253 -0
  1213. package/src/toolchains/_worker/run.js +78 -0
  1214. package/src/toolchains/_worker/wasm-worker.js +233 -0
  1215. package/src/toolchains/arm-none-eabi-gcc/gcc.js +208 -0
  1216. package/src/toolchains/asar/asar.js +542 -0
  1217. package/src/toolchains/assemble-snippet.js +256 -0
  1218. package/src/toolchains/cc65/cc65.js +395 -0
  1219. package/src/toolchains/cc65/da65.js +119 -0
  1220. package/src/toolchains/cc65/dbgparse.js +274 -0
  1221. package/src/toolchains/cc65/preset-resolver.js +59 -0
  1222. package/src/toolchains/cc65/presets/nes/chr-ram-runtime.cfg +79 -0
  1223. package/src/toolchains/cc65/presets/nes/chr-ram-runtime.crt0.s +178 -0
  1224. package/src/toolchains/cc65/presets/nes/chr-ram.cfg +76 -0
  1225. package/src/toolchains/cc65/presets/nes/chr-ram.crt0.s +106 -0
  1226. package/src/toolchains/common/ar.js +121 -0
  1227. package/src/toolchains/common/sdk-cache.js +116 -0
  1228. package/src/toolchains/common/symbols.js +139 -0
  1229. package/src/toolchains/dasm/dasm.js +96 -0
  1230. package/src/toolchains/gba-c/gba-c.js +832 -0
  1231. package/src/toolchains/genesis-c/README.md +61 -0
  1232. package/src/toolchains/genesis-c/genesis-c.js +598 -0
  1233. package/src/toolchains/index.js +727 -0
  1234. package/src/toolchains/m68k-elf-gcc/gcc.js +220 -0
  1235. package/src/toolchains/m68kdasm.js +438 -0
  1236. package/src/toolchains/parse-errors.js +258 -0
  1237. package/src/toolchains/registry.js +67 -0
  1238. package/src/toolchains/rgbds/rgbds.js +144 -0
  1239. package/src/toolchains/sdcc/preflight-lint.js +295 -0
  1240. package/src/toolchains/sdcc/sdcc.js +519 -0
  1241. package/src/toolchains/sjasm/sjasm.js +85 -0
  1242. package/src/toolchains/sm83dasm.js +194 -0
  1243. package/src/toolchains/snes-c/snes-c.js +409 -0
  1244. package/src/toolchains/tcc816/tcc816.js +79 -0
  1245. package/src/toolchains/vasm68k/vasm68k.js +138 -0
  1246. package/src/toolchains/wladx/wladx.js +120 -0
  1247. package/src/toolchains/z80dasm.js +303 -0
@@ -0,0 +1,1885 @@
1
+ // createProject — write a starter project directory the agent can iterate on.
2
+ //
3
+ // Policy (2026-05-25): no auto-injection at build time. createProject copies
4
+ // every file the template depends on (runtime, headers, crt0, linker .cfg)
5
+ // into the project directory. The project is then self-contained — any
6
+ // `buildSource` / `runSource` call points at the project's own files via
7
+ // sources/sourcesPaths/includePaths/crt0/linkerConfig args. If you take
8
+ // the project elsewhere and rebuild with cc65/sdcc directly, every byte
9
+ // that compiles is in the directory.
10
+
11
+ import { readFile, writeFile } from "node:fs/promises";
12
+ import { patchGbHeader } from "../../platforms/gb/lib/c/patch-header.js";
13
+ import { jsonContent, safeTool } from "../util.js";
14
+
15
+ /**
16
+ * Template manifest — each template lists:
17
+ * - main: path to the seed main.{c,s,asm} under examples/<platform>/
18
+ * - runtime: array of {src, dst} pairs to copy from src/platforms/<platform>/lib/
19
+ * - crt0: optional {src, dst} for a custom crt0 (asm)
20
+ * - linkerConfig: optional {src, dst} for the ld65 .cfg or similar
21
+ * - buildHint: string telling the agent what build args to use
22
+ */
23
+ const TEMPLATES = {
24
+ nes: {
25
+ default: {
26
+ main: "templates/default.c",
27
+ runtime: [
28
+ { src: "lib/c/nes_runtime.h", dst: "nes_runtime.h" },
29
+ { src: "lib/c/nes_runtime.c", dst: "nes_runtime.c" },
30
+ ],
31
+ crt0: { presetSrc: "presets/nes/chr-ram-runtime.crt0.s", dst: "chr-ram-runtime.crt0.s" },
32
+ linkerConfig: { presetSrc: "presets/nes/chr-ram-runtime.cfg", dst: "chr-ram-runtime.cfg" },
33
+ lang: "C (cc65)",
34
+ ext: ".nes",
35
+ describe: "Minimal palette-cycle hello-world. Backdrop color flashes through 4 shades.",
36
+ },
37
+ hello_sprite: {
38
+ main: "templates/hello_sprite.c",
39
+ runtime: [
40
+ { src: "lib/c/nes_runtime.h", dst: "nes_runtime.h" },
41
+ { src: "lib/c/nes_runtime.c", dst: "nes_runtime.c" },
42
+ ],
43
+ crt0: { presetSrc: "presets/nes/chr-ram-runtime.crt0.s", dst: "chr-ram-runtime.crt0.s" },
44
+ linkerConfig: { presetSrc: "presets/nes/chr-ram-runtime.cfg", dst: "chr-ram-runtime.cfg" },
45
+ lang: "C (cc65)",
46
+ ext: ".nes",
47
+ describe: "Single sprite + d-pad movement. Boot order + palette + tile upload all explicit.",
48
+ },
49
+ tile_engine: {
50
+ main: "templates/tile_engine.c",
51
+ runtime: [
52
+ { src: "lib/c/nes_runtime.h", dst: "nes_runtime.h" },
53
+ { src: "lib/c/nes_runtime.c", dst: "nes_runtime.c" },
54
+ ],
55
+ crt0: { presetSrc: "presets/nes/chr-ram-runtime.crt0.s", dst: "chr-ram-runtime.crt0.s" },
56
+ linkerConfig: { presetSrc: "presets/nes/chr-ram-runtime.cfg", dst: "chr-ram-runtime.cfg" },
57
+ lang: "C (cc65)",
58
+ ext: ".nes",
59
+ describe: "32×30 tile map + room transitions. Walls, doors, collision, multi-screen.",
60
+ },
61
+ /* ── Genre scaffolds (R14, 2026-05-26) ── */
62
+ shmup: {
63
+ main: "templates/shmup.c",
64
+ runtime: [
65
+ { src: "lib/c/nes_runtime.h", dst: "nes_runtime.h" },
66
+ { src: "lib/c/nes_runtime.c", dst: "nes_runtime.c" },
67
+ ],
68
+ crt0: { presetSrc: "presets/nes/chr-ram-runtime.crt0.s", dst: "chr-ram-runtime.crt0.s" },
69
+ linkerConfig: { presetSrc: "presets/nes/chr-ram-runtime.cfg", dst: "chr-ram-runtime.cfg" },
70
+ lang: "C (cc65)",
71
+ ext: ".nes",
72
+ describe: "Vertical-scrolling shooter. Player + 4 bullets + 4 enemies, AABB collision, score counter, wave spawner.",
73
+ },
74
+ platformer: {
75
+ main: "templates/platformer.c",
76
+ runtime: [
77
+ { src: "lib/c/nes_runtime.h", dst: "nes_runtime.h" },
78
+ { src: "lib/c/nes_runtime.c", dst: "nes_runtime.c" },
79
+ ],
80
+ crt0: { presetSrc: "presets/nes/chr-ram-runtime.crt0.s", dst: "chr-ram-runtime.crt0.s" },
81
+ linkerConfig: { presetSrc: "presets/nes/chr-ram-runtime.cfg", dst: "chr-ram-runtime.cfg" },
82
+ lang: "C (cc65)",
83
+ ext: ".nes",
84
+ describe: "Single-screen platformer — also the starting point for a SIDE-SCROLLER (same genre here). Gravity + jump physics (fixed-point Y), 5 platforms, land-on-top collision, respawn on fall. This is the jump/gravity/collision core; it does NOT scroll as shipped. To make it scroll on NES you add a camera + world coords and write new nametable columns across the mirroring boundary as the camera advances (and usually a sprite-0/IRQ split for a fixed HUD) — see the NES MENTAL_MODEL.md scrolling section.",
85
+ },
86
+ puzzle: {
87
+ main: "templates/puzzle.c",
88
+ runtime: [
89
+ { src: "lib/c/nes_runtime.h", dst: "nes_runtime.h" },
90
+ { src: "lib/c/nes_runtime.c", dst: "nes_runtime.c" },
91
+ ],
92
+ crt0: { presetSrc: "presets/nes/chr-ram-runtime.crt0.s", dst: "chr-ram-runtime.crt0.s" },
93
+ linkerConfig: { presetSrc: "presets/nes/chr-ram-runtime.cfg", dst: "chr-ram-runtime.cfg" },
94
+ lang: "C (cc65)",
95
+ ext: ".nes",
96
+ describe: "Match-3 falling-block puzzle. 6×12 grid, 1×3 active piece (3 colors), rotate via A, soft-drop on DOWN, horizontal-triple clear.",
97
+ },
98
+ sports: {
99
+ main: "templates/sports.c",
100
+ runtime: [
101
+ { src: "lib/c/nes_runtime.h", dst: "nes_runtime.h" },
102
+ { src: "lib/c/nes_runtime.c", dst: "nes_runtime.c" },
103
+ ],
104
+ crt0: { presetSrc: "presets/nes/chr-ram-runtime.crt0.s", dst: "chr-ram-runtime.crt0.s" },
105
+ linkerConfig: { presetSrc: "presets/nes/chr-ram-runtime.cfg", dst: "chr-ram-runtime.cfg" },
106
+ lang: "C (cc65)",
107
+ ext: ".nes",
108
+ describe: "Two-player Pong. Port 0 = left paddle, port 1 = right paddle (AI fallback when no 2nd controller). Per-side score 0-9, ball bounces off paddles + walls. Designed for the playtest window with two USB controllers.",
109
+ },
110
+ racing: {
111
+ main: "templates/racing.c",
112
+ runtime: [
113
+ { src: "lib/c/nes_runtime.h", dst: "nes_runtime.h" },
114
+ { src: "lib/c/nes_runtime.c", dst: "nes_runtime.c" },
115
+ ],
116
+ crt0: { presetSrc: "presets/nes/chr-ram-runtime.crt0.s", dst: "chr-ram-runtime.crt0.s" },
117
+ linkerConfig: { presetSrc: "presets/nes/chr-ram-runtime.cfg", dst: "chr-ram-runtime.cfg" },
118
+ lang: "C (cc65)",
119
+ ext: ".nes",
120
+ describe: "Endless top-down lane racer. 3 lanes, 4 obstacle slots, LEFT/RIGHT switches lanes. Speed grows with score; collision triggers a 60-frame freeze then reset.",
121
+ },
122
+ /* R44 (2026-05-26): bundled-driver music demo. FamiTone2 engine +
123
+ * cc65 bridge + example track, all ship as source under lib/asm. */
124
+ music_demo: {
125
+ main: "templates/music_demo.c",
126
+ runtime: [
127
+ { src: "lib/c/nes_runtime.h", dst: "nes_runtime.h" },
128
+ { src: "lib/c/nes_runtime.c", dst: "nes_runtime.c" },
129
+ { src: "lib/asm/famitone2.s", dst: "famitone2.s" },
130
+ { src: "lib/asm/famitone_bridge.s", dst: "famitone_bridge.s" },
131
+ { src: "lib/asm/music_data.s", dst: "music_data.s" },
132
+ { src: "lib/asm/LICENSE-FAMITONE", dst: "LICENSE-FAMITONE" },
133
+ ],
134
+ crt0: { presetSrc: "presets/nes/chr-ram-runtime.crt0.s", dst: "chr-ram-runtime.crt0.s" },
135
+ linkerConfig: { presetSrc: "presets/nes/chr-ram-runtime.cfg", dst: "chr-ram-runtime.cfg" },
136
+ lang: "C (cc65)",
137
+ ext: ".nes",
138
+ describe: "Continuous multi-channel music demo using bundled FamiTone2 (Shiru, public domain). Engine .s + bridge .s + example track .s ship as sources alongside main.c. Swap music_data.s for your own song (text2data converts FamiTracker .txt exports).",
139
+ },
140
+ },
141
+ gb: {
142
+ default: {
143
+ main: "templates/default.c",
144
+ runtime: [
145
+ { src: "lib/c/gb_hardware.h", dst: "gb_hardware.h" },
146
+ { src: "lib/c/gb_runtime.h", dst: "gb_runtime.h" },
147
+ { src: "lib/c/gb_runtime.c", dst: "gb_runtime.c" },
148
+ { src: "lib/c/gb_crt0.s", dst: "gb_crt0.s" },
149
+ { src: "lib/c/patch-header.js", dst: "patch-header.js" },
150
+ ],
151
+ lang: "C (SDCC sm83)",
152
+ ext: ".gb",
153
+ describe: "Minimal palette-cycle hello-world.",
154
+ },
155
+ hello_sprite: {
156
+ main: "templates/hello_sprite.c",
157
+ runtime: [
158
+ { src: "lib/c/gb_hardware.h", dst: "gb_hardware.h" },
159
+ { src: "lib/c/gb_runtime.h", dst: "gb_runtime.h" },
160
+ { src: "lib/c/gb_runtime.c", dst: "gb_runtime.c" },
161
+ { src: "lib/c/gb_crt0.s", dst: "gb_crt0.s" },
162
+ { src: "lib/c/patch-header.js", dst: "patch-header.js" },
163
+ ],
164
+ lang: "C (SDCC sm83)",
165
+ ext: ".gb",
166
+ describe: "Single sprite + d-pad movement.",
167
+ },
168
+ tile_engine: {
169
+ main: "templates/tile_engine.c",
170
+ runtime: [
171
+ { src: "lib/c/gb_hardware.h", dst: "gb_hardware.h" },
172
+ { src: "lib/c/gb_runtime.h", dst: "gb_runtime.h" },
173
+ { src: "lib/c/gb_runtime.c", dst: "gb_runtime.c" },
174
+ { src: "lib/c/gb_crt0.s", dst: "gb_crt0.s" },
175
+ { src: "lib/c/patch-header.js", dst: "patch-header.js" },
176
+ ],
177
+ lang: "C (SDCC sm83)",
178
+ ext: ".gb",
179
+ describe: "20×18 tile map + room transitions.",
180
+ },
181
+ shmup: {
182
+ main: "templates/shmup.c",
183
+ runtime: [
184
+ { src: "lib/c/gb_hardware.h", dst: "gb_hardware.h" },
185
+ { src: "lib/c/gb_runtime.h", dst: "gb_runtime.h" },
186
+ { src: "lib/c/gb_runtime.c", dst: "gb_runtime.c" },
187
+ { src: "lib/c/gb_crt0.s", dst: "gb_crt0.s" },
188
+ { src: "lib/c/patch-header.js", dst: "patch-header.js" },
189
+ ],
190
+ lang: "C (SDCC sm83)",
191
+ ext: ".gb",
192
+ describe: "Vertical-shmup scaffold for GB. Player ship + 4 bullets + 4 enemies, wave spawner, AABB collision, score (in WRAM). OAM slots 0/1-4/5-8 preallocated.",
193
+ },
194
+ platformer: {
195
+ main: "templates/platformer.c",
196
+ runtime: [
197
+ { src: "lib/c/gb_hardware.h", dst: "gb_hardware.h" },
198
+ { src: "lib/c/gb_runtime.h", dst: "gb_runtime.h" },
199
+ { src: "lib/c/gb_runtime.c", dst: "gb_runtime.c" },
200
+ { src: "lib/c/gb_crt0.s", dst: "gb_crt0.s" },
201
+ { src: "lib/c/patch-header.js", dst: "patch-header.js" },
202
+ ],
203
+ lang: "C (SDCC sm83)",
204
+ ext: ".gb",
205
+ describe: "SIDE-SCROLLING platformer for GB. Subpixel gravity + jump + land-on-top collision against a static platform list spread across a 256-px world (the full wrapping BG map). The camera follows the player and scrolls the BG via SCX each frame; the player sprite draws in screen space (worldX - camX). A=jump, d-pad=move. The world here is one BG map wide (no streaming) — for a wider world, stream a new tile column into the 32-wide BG map each time the camera crosses an 8px boundary (window for a fixed HUD). See the GB MENTAL_MODEL.md 'Horizontal scrolling'. Extend with enemies, goals, pickups.",
206
+ },
207
+ puzzle: {
208
+ main: "templates/puzzle.c",
209
+ runtime: [
210
+ { src: "lib/c/gb_hardware.h", dst: "gb_hardware.h" },
211
+ { src: "lib/c/gb_runtime.h", dst: "gb_runtime.h" },
212
+ { src: "lib/c/gb_runtime.c", dst: "gb_runtime.c" },
213
+ { src: "lib/c/gb_crt0.s", dst: "gb_crt0.s" },
214
+ { src: "lib/c/patch-header.js", dst: "patch-header.js" },
215
+ ],
216
+ lang: "C (SDCC sm83)",
217
+ ext: ".gb",
218
+ describe: "Match-3 falling-block puzzle scaffold for GB. 6×12 grid rendered via BG tilemap, 1×3 active piece (3 colours via 3 BG tile shapes), rotate via A, hard-drop on START, horizontal-triple clear.",
219
+ },
220
+ sports: {
221
+ main: "templates/sports.c",
222
+ runtime: [
223
+ { src: "lib/c/gb_hardware.h", dst: "gb_hardware.h" },
224
+ { src: "lib/c/gb_runtime.h", dst: "gb_runtime.h" },
225
+ { src: "lib/c/gb_runtime.c", dst: "gb_runtime.c" },
226
+ { src: "lib/c/gb_crt0.s", dst: "gb_crt0.s" },
227
+ { src: "lib/c/patch-header.js", dst: "patch-header.js" },
228
+ ],
229
+ lang: "C (SDCC sm83)",
230
+ ext: ".gb",
231
+ describe: "Player-vs-AI Pong. Game Boy hardware has only one controller port, so this is human vs chase-the-ball AI by design. Same gameplay shape as the 2P versions on platforms with two ports.",
232
+ },
233
+ racing: {
234
+ main: "templates/racing.c",
235
+ runtime: [
236
+ { src: "lib/c/gb_hardware.h", dst: "gb_hardware.h" },
237
+ { src: "lib/c/gb_runtime.h", dst: "gb_runtime.h" },
238
+ { src: "lib/c/gb_runtime.c", dst: "gb_runtime.c" },
239
+ { src: "lib/c/gb_crt0.s", dst: "gb_crt0.s" },
240
+ { src: "lib/c/patch-header.js", dst: "patch-header.js" },
241
+ ],
242
+ lang: "C (SDCC sm83)",
243
+ ext: ".gb",
244
+ describe: "Endless 3-lane top-down racer. LEFT/RIGHT switches lanes, obstacle speed grows with score, 60-frame freeze + auto-reset on collision.",
245
+ },
246
+ /* R45 — hUGEDriver music demo. Ships a compact SDCC-native music
247
+ * driver with the upstream hUGEDriver function surface plus a
248
+ * hand-authored sample song. Source-visible: the full upstream
249
+ * RGBDS asm is bundled alongside as hUGEDriver.upstream.asm. */
250
+ music_demo: {
251
+ main: "templates/music_demo.c",
252
+ runtime: [
253
+ { src: "lib/c/gb_hardware.h", dst: "gb_hardware.h" },
254
+ { src: "lib/c/gb_runtime.h", dst: "gb_runtime.h" },
255
+ { src: "lib/c/gb_runtime.c", dst: "gb_runtime.c" },
256
+ { src: "lib/c/gb_crt0.s", dst: "gb_crt0.s" },
257
+ { src: "lib/c/patch-header.js", dst: "patch-header.js" },
258
+ { src: "lib/c/hUGEDriver.h", dst: "hUGEDriver.h" },
259
+ { src: "lib/c/hUGEDriver.c", dst: "hUGEDriver.c" },
260
+ { src: "lib/c/song_data.c", dst: "song_data.c" },
261
+ { src: "lib/c/hUGEDriver.upstream.asm",dst: "hUGEDriver.upstream.asm" },
262
+ { src: "lib/c/LICENSE-HUGEDRIVER", dst: "LICENSE-HUGEDRIVER" },
263
+ ],
264
+ lang: "C (SDCC sm83)",
265
+ ext: ".gb",
266
+ describe: "Music playback via hUGEDriver. Compact SDCC-native rewrite of the upstream hUGEDriver interface (public domain) + a 4-pattern, two-channel hand-authored sample song. Driver advances on every vblank via hUGE_dosound().",
267
+ },
268
+ },
269
+ };
270
+ // R37: GBC has its own scaffold tree at examples/gbc/templates/ +
271
+ // src/platforms/gbc/lib/c/. Same runtime files as GB (the APU + Z80 +
272
+ // most VRAM layout are identical) but the scaffolds add visible
273
+ // CGB-mode color via BCPS/BCPD palette writes. Output ext is .gbc so
274
+ // patchGbHeader flips $0143 = $80 → CGB-enhanced mode.
275
+ const GBC_RUNTIME = [
276
+ { src: "lib/c/gb_hardware.h", dst: "gb_hardware.h" },
277
+ { src: "lib/c/gb_runtime.h", dst: "gb_runtime.h" },
278
+ { src: "lib/c/gb_runtime.c", dst: "gb_runtime.c" },
279
+ { src: "lib/c/gb_crt0.s", dst: "gb_crt0.s" },
280
+ { src: "lib/c/patch-header.js", dst: "patch-header.js" },
281
+ ];
282
+ const GBC_LANG = "C (SDCC sm83, GBC color)";
283
+ TEMPLATES.gbc = {
284
+ default: {
285
+ main: "templates/default.c", runtime: GBC_RUNTIME,
286
+ lang: GBC_LANG, ext: ".gbc",
287
+ describe: "Minimal GBC starter. Same shape as the GB default but ROM extension .gbc — patchGbHeader sets $0143=$80 so gambatte boots in CGB mode.",
288
+ },
289
+ hello_sprite: {
290
+ main: "templates/hello_sprite.c", runtime: GBC_RUNTIME,
291
+ lang: GBC_LANG, ext: ".gbc",
292
+ describe: "Single sprite + d-pad on Game Boy Color. Sets a real CGB color palette via BCPS/BCPD (purple backdrop) so you can SEE that CGB mode is active.",
293
+ },
294
+ tile_engine: {
295
+ main: "templates/tile_engine.c", runtime: GBC_RUNTIME,
296
+ lang: GBC_LANG, ext: ".gbc",
297
+ describe: "20×18 tile world on GBC. BG palette upload via BCPS/BCPD + sprite palette via OCPS/OCPD.",
298
+ },
299
+ shmup: {
300
+ main: "templates/shmup.c", runtime: GBC_RUNTIME,
301
+ lang: GBC_LANG, ext: ".gbc",
302
+ describe: "Vertical-shmup for GBC. Colorful sprites (white ship, yellow bullets, red enemies) and a starfield BG palette via BCPS/BCPD. Same sfx wiring as GB (sound_play_tone/noise).",
303
+ },
304
+ platformer: {
305
+ main: "templates/platformer.c", runtime: GBC_RUNTIME,
306
+ lang: GBC_LANG, ext: ".gbc",
307
+ describe: "SIDE-SCROLLING platformer for GBC. Full CGB color palette (BG + sprite via BCPS/OCPS) over the GB side-scroller core: subpixel gravity + jump + land-on-top collision against platforms across a 256-px world (the wrapping BG map). The camera follows the player and scrolls the BG via SCX; the player sprite draws in screen space. A=jump, d-pad=move. One BG map wide (no streaming) — for a wider world, stream a new BG-map column on each 8px camera step (window for a fixed HUD). See the GBC MENTAL_MODEL.md 'Horizontal scrolling'. Extend with enemies, goals, pickups.",
308
+ },
309
+ puzzle: {
310
+ main: "templates/puzzle.c", runtime: GBC_RUNTIME,
311
+ lang: GBC_LANG, ext: ".gbc",
312
+ describe: "Match-3 puzzle for GBC. Three colored cells (BG palette via BCPS/BCPD), rotate + soft-drop + hard-drop + triple-clear chime.",
313
+ },
314
+ sports: {
315
+ main: "templates/sports.c", runtime: GBC_RUNTIME,
316
+ lang: GBC_LANG, ext: ".gbc",
317
+ describe: "Pong for GBC. Player-vs-AI (one controller). Court green BG + colored paddles + paddle-hit sfx.",
318
+ },
319
+ racing: {
320
+ main: "templates/racing.c", runtime: GBC_RUNTIME,
321
+ lang: GBC_LANG, ext: ".gbc",
322
+ describe: "3-lane racer for GBC. Asphalt BG palette + colored player/enemy cars + lane-switch + crash sfx.",
323
+ },
324
+ /* R45 — same hUGEDriver music_demo as GB, with BCPS/BCPD palette
325
+ * writes so it boots in CGB mode (gambatte flips on .gbc + $0143=$80).
326
+ * The APU is identical between DMG and CGB so the driver code is
327
+ * unchanged — only the visual palette path differs. */
328
+ music_demo: {
329
+ main: "templates/music_demo.c",
330
+ runtime: [
331
+ { src: "lib/c/gb_hardware.h", dst: "gb_hardware.h" },
332
+ { src: "lib/c/gb_runtime.h", dst: "gb_runtime.h" },
333
+ { src: "lib/c/gb_runtime.c", dst: "gb_runtime.c" },
334
+ { src: "lib/c/gb_crt0.s", dst: "gb_crt0.s" },
335
+ { src: "lib/c/patch-header.js", dst: "patch-header.js" },
336
+ { src: "lib/c/hUGEDriver.h", dst: "hUGEDriver.h" },
337
+ { src: "lib/c/hUGEDriver.c", dst: "hUGEDriver.c" },
338
+ { src: "lib/c/song_data.c", dst: "song_data.c" },
339
+ { src: "lib/c/hUGEDriver.upstream.asm",dst: "hUGEDriver.upstream.asm" },
340
+ { src: "lib/c/LICENSE-HUGEDRIVER", dst: "LICENSE-HUGEDRIVER" },
341
+ ],
342
+ lang: GBC_LANG, ext: ".gbc",
343
+ describe: "Music playback on GBC. Compact SDCC-native rewrite of the upstream hUGEDriver interface (public domain) + bundled sample song. Background palette cycles via BCPS/BCPD to confirm CGB mode is active.",
344
+ },
345
+ };
346
+
347
+ // ── SDCC z80 platforms (SMS / GG / MSX / Coleco) ─────────────────────
348
+ // They share the same hardware-port idiom (__sfr __at) but differ in
349
+ // register addresses / cart layout. SMS has a fleshed-out lib/c/sms_hw.h
350
+ // + working main.c we use directly; the other three reuse the same
351
+ // example main.c shape and get a minimal __sfr declaration sketch.
352
+ // R22: the modular SMS runtime under src/platforms/sms/lib/c/ is what
353
+ // hello_sprite + tile_engine + shmup + platformer + puzzle templates link
354
+ // against. Factored to a constant so adding a new template is a one-line
355
+ // change at the bottom.
356
+ const SMS_RUNTIME = [
357
+ { src: "lib/c/sms_hw.h", dst: "sms_hw.h" },
358
+ { src: "lib/c/vdp_init.c", dst: "vdp_init.c" },
359
+ { src: "lib/c/load_palette.c", dst: "load_palette.c" },
360
+ { src: "lib/c/load_tiles.c", dst: "load_tiles.c" },
361
+ { src: "lib/c/vblank_wait.c", dst: "vblank_wait.c" },
362
+ { src: "lib/c/joypad_read.c", dst: "joypad_read.c" },
363
+ { src: "lib/c/sprite_table.c", dst: "sprite_table.c" },
364
+ // R35: PSG sound wrapper (SN76489 — same chip as Genesis PSG).
365
+ { src: "lib/c/sms_sfx.h", dst: "sms_sfx.h" },
366
+ { src: "lib/c/sms_sfx.c", dst: "sms_sfx.c" },
367
+ // R47: 3-voice tracker on top of the PSG (continuous music).
368
+ { src: "lib/c/sms_music.h", dst: "sms_music.h" },
369
+ { src: "lib/c/sms_music.c", dst: "sms_music.c" },
370
+ ];
371
+ const SMS_LANG = "C (SDCC z80)";
372
+
373
+ TEMPLATES.sms = {
374
+ default: {
375
+ // Backward-compat: old `main.c` lives at the top of examples/sms/.
376
+ // New templates use the examples/sms/templates/ tree.
377
+ main: "main.c",
378
+ runtime: [
379
+ { src: "lib/c/sms_hw.h", dst: "sms_hw.h" },
380
+ ],
381
+ lang: SMS_LANG,
382
+ ext: ".sms",
383
+ describe: "Yellow 'H' tile on blue background. Press B1 to scroll BG by 1px/frame. Single-file project, inlines all VDP/joypad helpers.",
384
+ },
385
+ hello_sprite: {
386
+ main: "templates/hello_sprite.c",
387
+ runtime: SMS_RUNTIME,
388
+ lang: SMS_LANG,
389
+ ext: ".sms",
390
+ describe: "One sprite + d-pad. Uses bundled SMS runtime helpers (sms_vdp_init, sms_load_tiles, sms_sprite_*, sms_vblank_wait, sms_joypad_read). Multi-file project.",
391
+ },
392
+ tile_engine: {
393
+ main: "templates/tile_engine.c",
394
+ runtime: SMS_RUNTIME,
395
+ lang: SMS_LANG,
396
+ ext: ".sms",
397
+ describe: "32×24 tile world with walking player + AABB collision against solid tile indices. Demonstrates sms_set_tilemap_cell + the BG-plane name-table at $3800.",
398
+ },
399
+ shmup: {
400
+ main: "templates/shmup.c",
401
+ runtime: SMS_RUNTIME,
402
+ lang: SMS_LANG,
403
+ ext: ".sms",
404
+ describe: "Vertical-shmup scaffold for SMS. Player ship + 4 bullets + 4 enemies, wave spawner, AABB collisions, score (WRAM). Pre-allocated SAT slots 0/1-4/5-8.",
405
+ },
406
+ platformer: {
407
+ main: "templates/platformer.c",
408
+ runtime: SMS_RUNTIME,
409
+ lang: SMS_LANG,
410
+ ext: ".sms",
411
+ describe: "SIDE-SCROLLING platformer for SMS with COLUMN STREAMING. Subpixel gravity + jump + land-on-top collision against platforms across a 512-px world. The SMS name table is only 32 cells (256 px) and wraps, so the world is streamed: the camera follows the player, writes VDP R8 (-camX) for smooth pixel scroll, and each time camX crosses an 8-px boundary it rewrites the name-table column entering from the right (or left, on retreat) with the next world column. Player sprite draws in screen space. 1=jump, d-pad=move. For a fixed HUD, lock the top rows with VDP R0 bit 6. See the SMS MENTAL_MODEL.md 'Horizontal scrolling'. Extend with enemies, goals, pickups.",
412
+ },
413
+ puzzle: {
414
+ main: "templates/puzzle.c",
415
+ runtime: SMS_RUNTIME,
416
+ lang: SMS_LANG,
417
+ ext: ".sms",
418
+ describe: "Match-3 falling-block scaffold. 6×12 grid rendered via BG tilemap (three distinct tile shapes for R/G/B cells), 1×3 active piece, rotate via B1, hard-drop via B2.",
419
+ },
420
+ sports: {
421
+ main: "templates/sports.c",
422
+ runtime: SMS_RUNTIME,
423
+ lang: SMS_LANG,
424
+ ext: ".sms",
425
+ describe: "Two-player Pong on SMS. Both controller ports wired — sms_joypad_read for P1, sms_joypad_read_p2 for P2 (reassembles the awkward split-across-$DC/$DD bit layout). AI fallback when no second pad is plugged in.",
426
+ },
427
+ racing: {
428
+ main: "templates/racing.c",
429
+ runtime: SMS_RUNTIME,
430
+ lang: SMS_LANG,
431
+ ext: ".sms",
432
+ describe: "Endless 3-lane top-down racer. LEFT/RIGHT (edge-detected) switches lanes, obstacles slide down at speed = 2 + score/500 (capped at 4). 60-frame freeze + auto-reset on collision.",
433
+ },
434
+ shmup_2p: {
435
+ main: "templates/shmup_2p.c",
436
+ runtime: SMS_RUNTIME,
437
+ lang: SMS_LANG,
438
+ ext: ".sms",
439
+ describe: "Two-player competitive shmup on SMS via PORT_JOY_A + PORT_JOY_B (the new sms_joypad_read_p2 helper reassembles P2's split-port bits). Each player owns a 4-bullet pool + score; enemies are shared, first to hit scores.",
440
+ },
441
+ music_demo: {
442
+ main: "templates/music_demo.c",
443
+ runtime: SMS_RUNTIME,
444
+ lang: SMS_LANG,
445
+ ext: ".sms",
446
+ describe: "Continuous 3-voice music demo via sms_music.{h,c} — a tiny tracker on top of the SN76489 PSG. Voice 0 melody, voice 1 harmony, voice 2 bass. Noise channel stays free for game sfx. Source-visible: the parallel per-voice freq/length arrays in sms_music.c ARE the song.",
447
+ },
448
+ };
449
+ // R36: GG is tier-1 — full runtime + scaffolds + PSG sound, mirrors SMS.
450
+ // The genesis_plus_gx core handles GG natively. GG's visible viewport
451
+ // is 160×144 (centered in a 256×192 framebuffer); scaffolds render to
452
+ // the whole framebuffer but content positioning targets the center.
453
+ const GG_RUNTIME = [
454
+ { src: "lib/c/gg_crt0.s", dst: "gg_crt0.s" },
455
+ { src: "lib/c/gg_hw.h", dst: "gg_hw.h" },
456
+ { src: "lib/c/vdp_init.c", dst: "vdp_init.c" },
457
+ { src: "lib/c/load_palette.c", dst: "load_palette.c" },
458
+ { src: "lib/c/load_tiles.c", dst: "load_tiles.c" },
459
+ { src: "lib/c/vblank_wait.c", dst: "vblank_wait.c" },
460
+ { src: "lib/c/joypad_read.c", dst: "joypad_read.c" },
461
+ { src: "lib/c/sprite_table.c", dst: "sprite_table.c" },
462
+ { src: "lib/c/gg_sfx.h", dst: "gg_sfx.h" },
463
+ { src: "lib/c/gg_sfx.c", dst: "gg_sfx.c" },
464
+ { src: "lib/c/gg_music.h", dst: "gg_music.h" },
465
+ { src: "lib/c/gg_music.c", dst: "gg_music.c" },
466
+ ];
467
+ /* For the single-file `default` template — it inlines its own VDP
468
+ * helpers, but it still needs gg_crt0.s for the boot vectors. SDCC's
469
+ * stock z80 crt0 traps rst $08 (used by its host runtime) which would
470
+ * halt any GG cartridge as soon as the VDP fires its first IRQ. */
471
+ const GG_DEFAULT_RUNTIME = [
472
+ { src: "lib/c/gg_crt0.s", dst: "gg_crt0.s" },
473
+ ];
474
+ const GG_LANG = "C (SDCC z80)";
475
+
476
+ TEMPLATES.gg = {
477
+ default: {
478
+ main: "templates/default.c",
479
+ runtime: GG_DEFAULT_RUNTIME,
480
+ lang: GG_LANG,
481
+ ext: ".gg",
482
+ describe: "Minimal GG starter: VDP init + yellow 'H' tile in the center of the 160×144 visible viewport + scroll-on-B1 input loop. Single source file (inlines VDP helpers) + the bundled gg_crt0.s. Use as the read-and-modify starting point when you're not sure what to build; switch to hello_sprite/tile_engine for multi-file projects.",
483
+ },
484
+ hello_sprite: {
485
+ main: "templates/hello_sprite.c",
486
+ runtime: GG_RUNTIME,
487
+ lang: GG_LANG,
488
+ ext: ".gg",
489
+ describe: "One sprite + d-pad. Uses bundled GG runtime helpers (gg_vdp_init, gg_load_tiles, gg_sprite_*, gg_vblank_wait, gg_joypad_read). Multi-file project. Boot chime via the bundled gg_sfx PSG wrapper.",
490
+ },
491
+ tile_engine: {
492
+ main: "templates/tile_engine.c",
493
+ runtime: GG_RUNTIME,
494
+ lang: GG_LANG,
495
+ ext: ".gg",
496
+ describe: "32×24 tile world with walking player + AABB collision against solid tile indices. BG name-table at $3800.",
497
+ },
498
+ shmup: {
499
+ main: "templates/shmup.c",
500
+ runtime: GG_RUNTIME,
501
+ lang: GG_LANG,
502
+ ext: ".gg",
503
+ describe: "Vertical-shmup scaffold for GG. Player ship + 4 bullets + 4 enemies, wave spawner, AABB collisions, score. Pew sfx on fire, boom on hit (PSG via gg_sfx).",
504
+ },
505
+ platformer: {
506
+ main: "templates/platformer.c",
507
+ runtime: GG_RUNTIME,
508
+ lang: GG_LANG,
509
+ ext: ".gg",
510
+ describe: "SIDE-SCROLLING platformer for GG with COLUMN STREAMING. Same Mode-4 VDP as the SMS — only the visible window differs (160 px wide). Subpixel gravity + jump + land-on-top collision across a 512-px world; the camera centers on the 160-px window, writes VDP R8 (-camX) for smooth pixel scroll, and streams the next world column into the wrapping 32-cell name table each time camX crosses an 8-px boundary. Player sprite draws in screen space. Jump boing via PSG sfx. 1=jump, d-pad=move. See the SMS/GG MENTAL_MODEL.md 'Horizontal scrolling'. Extend with enemies, goals, pickups.",
511
+ },
512
+ puzzle: {
513
+ main: "templates/puzzle.c",
514
+ runtime: GG_RUNTIME,
515
+ lang: GG_LANG,
516
+ ext: ".gg",
517
+ describe: "Match-3 falling-block scaffold. 6×12 grid, 1×3 piece, rotate via B1, hard-drop via B2. Rotate click + clear chime via PSG.",
518
+ },
519
+ sports: {
520
+ main: "templates/sports.c",
521
+ runtime: GG_RUNTIME,
522
+ lang: GG_LANG,
523
+ ext: ".gg",
524
+ describe: "Single-player Pong vs AI (GG has only one controller). Paddle hit + wall blip + score chime via PSG.",
525
+ },
526
+ racing: {
527
+ main: "templates/racing.c",
528
+ runtime: GG_RUNTIME,
529
+ lang: GG_LANG,
530
+ ext: ".gg",
531
+ describe: "Top-down 3-lane racer scaffold. L/R switches lanes, obstacles slide down + accelerate with score. Lane-switch beep + crash noise via PSG.",
532
+ },
533
+ music_demo: {
534
+ main: "templates/music_demo.c",
535
+ runtime: GG_RUNTIME,
536
+ lang: GG_LANG,
537
+ ext: ".gg",
538
+ describe: "Per-frame PSG music driver (gg_music) playing a hand-authored note table on PSG ch 2, with gg_sfx pew on ch 0. LEFT/RIGHT switches between three bundled songs, UP stops, DOWN restarts, B1 fires sfx. UI centered in the 160×144 visible viewport.",
539
+ },
540
+ };
541
+
542
+ // ── C64: cc65 + SID sound (R39 brings tier-1 parity) ────────────────────
543
+ const C64_RUNTIME = [
544
+ { src: "lib/c64_registers.h", dst: "c64_registers.h" },
545
+ { src: "lib/c/c64_sfx.h", dst: "c64_sfx.h" },
546
+ { src: "lib/c/c64_sfx.c", dst: "c64_sfx.c" },
547
+ ];
548
+ // R58b: ship cc65 C64 libsrc into project. Joystick driver,
549
+ // VIC-II / SID / CIA helpers, conio, header builder — all readable.
550
+ const C64_VENDOR_DIRS = [
551
+ { src: "lib/cc65-src", dst: "vendor/cc65/libsrc/c64" },
552
+ ];
553
+ // R49: music_demo gets its own 3-voice SID music driver instead of the
554
+ // one-shot sfx wrapper. Note table IS the song — open c64_music.c.
555
+ const C64_MUSIC_RUNTIME = [
556
+ { src: "lib/c64_registers.h", dst: "c64_registers.h" },
557
+ { src: "lib/c/c64_music.h", dst: "c64_music.h" },
558
+ { src: "lib/c/c64_music.c", dst: "c64_music.c" },
559
+ ];
560
+ const C64_LANG = "C (cc65)";
561
+ TEMPLATES.c64 = {
562
+ default: {
563
+ main: "main.c", runtime: [{ src: "lib/c64_registers.h", dst: "c64_registers.h" }], runtimeDirs: C64_VENDOR_DIRS,
564
+ lang: C64_LANG, ext: ".prg",
565
+ describe: "Minimal cc65 C64 program. Includes c64_registers.h (VIC-II + SID + CIA + kernel addrs).",
566
+ },
567
+ hello_sprite: {
568
+ main: "templates/hello_sprite.c", runtime: [{ src: "lib/c64_registers.h", dst: "c64_registers.h" }], runtimeDirs: C64_VENDOR_DIRS,
569
+ lang: C64_LANG, ext: ".prg",
570
+ describe: "One VIC-II hardware sprite driven by joystick port 2.",
571
+ },
572
+ tile_engine: {
573
+ main: "templates/tile_engine.c", runtime: [{ src: "lib/c64_registers.h", dst: "c64_registers.h" }], runtimeDirs: C64_VENDOR_DIRS,
574
+ lang: C64_LANG, ext: ".prg",
575
+ describe: "40×25 character-matrix world with a hardware sprite + AABB collision.",
576
+ },
577
+ shmup: {
578
+ main: "templates/shmup.c", runtime: C64_RUNTIME, runtimeDirs: C64_VENDOR_DIRS,
579
+ lang: C64_LANG, ext: ".prg",
580
+ describe: "Vertical-shmup. Player + 3 bullets + 4 enemies via VIC-II hardware sprites. SID sfx: pew + boom.",
581
+ },
582
+ platformer: {
583
+ main: "templates/platformer.c", runtime: C64_RUNTIME, runtimeDirs: C64_VENDOR_DIRS,
584
+ lang: C64_LANG, ext: ".prg",
585
+ describe: "SIDE-SCROLLING platformer for C64 — the fiddliest scroll of all the platforms, done for real. 80-col (640-px) world; the VIC-II only fine-scrolls 0-7 px in hardware ($D016 low 3 bits), so coarse motion re-renders the 40 visible columns of screen RAM ($0400) + color RAM ($D800) from a world map each time the camera crosses a char boundary. 38-column mode ($D016 bit 3 clear) masks the edge garbage column. The player is a VIC-II hardware sprite drawn in screen space (with the $D010 X-MSB handled); SID jump sfx. Joystick port 2, B1 jumps. See the C64 MENTAL_MODEL.md 'Horizontal scrolling'. Extend with enemies, goals, pickups.",
586
+ },
587
+ puzzle: {
588
+ main: "templates/puzzle.c", runtime: C64_RUNTIME, runtimeDirs: C64_VENDOR_DIRS,
589
+ lang: C64_LANG, ext: ".prg",
590
+ describe: "Match-3 falling-block puzzle. 6×12 grid in screen RAM (40×25 char matrix), C64 color codes. Rotate click + clear chime via SID.",
591
+ },
592
+ sports: {
593
+ main: "templates/sports.c", runtime: C64_RUNTIME, runtimeDirs: C64_VENDOR_DIRS,
594
+ lang: C64_LANG, ext: ".prg",
595
+ describe: "Pong with 3 hardware sprites. Joystick port 2 = P1; AI on the right paddle. SID paddle-hit + wall-bounce + score sfx.",
596
+ },
597
+ racing: {
598
+ main: "templates/racing.c", runtime: C64_RUNTIME, runtimeDirs: C64_VENDOR_DIRS,
599
+ lang: C64_LANG, ext: ".prg",
600
+ describe: "3-lane top-down racer. LEFT/RIGHT switches lanes. SID lane-switch beep + crash noise.",
601
+ },
602
+ music_demo: {
603
+ main: "templates/music_demo.c", runtime: C64_MUSIC_RUNTIME, runtimeDirs: C64_VENDOR_DIRS,
604
+ lang: C64_LANG, ext: ".prg",
605
+ describe: "Continuous 3-voice SID music demo. Per-frame note-table sequencer (c64_music.c IS the song — edit it). Melody / bass / harmony over an Am-F-C-G loop; FIRE on joy port 2 toggles playback.",
606
+ },
607
+ };
608
+ // R31: SNES audio assets shared by all C-mode genre scaffolds. The
609
+ // SPC700 driver source + sample BRR files are visible alongside the
610
+ // prebuilt apu_blob.bin (which gets .incbin'd into the ROM via
611
+ // snes_sfx_data.asm). User can rebuild apu_blob with asar — see
612
+ // src/platforms/snes/lib/audio/apu_blob.asm.
613
+ const SNES_SFX_RUNTIME = [
614
+ { src: "lib/c/snes_sfx.h", dst: "snes_sfx.h" },
615
+ { src: "lib/c/snes_sfx.c", dst: "snes_sfx.c" },
616
+ { src: "lib/c/snes_sfx_data.asm", dst: "snes_sfx_data.asm" },
617
+ { src: "lib/audio/apu_blob.bin", dst: "apu_blob.bin" },
618
+ { src: "lib/audio/spc_driver.asm", dst: "spc_driver.asm" },
619
+ { src: "lib/audio/apu_blob.asm", dst: "apu_blob.asm" },
620
+ { src: "lib/audio/shoot.brr", dst: "shoot.brr" },
621
+ { src: "lib/audio/explosion.brr", dst: "explosion.brr" },
622
+ { src: "lib/audio/sample_bank.bin", dst: "sample_bank.bin" },
623
+ ];
624
+
625
+ // R58b: ship the full PVSnesLib source tree into every SNES C
626
+ // project so the agent can grep snes/sound.h, consoleDrawText,
627
+ // setMode, padsCurrent, etc. instead of stabbing at the precompiled
628
+ // .obj. Same rationale as the Lynx cc65-src bundling — the agent
629
+ // debugs faster when they can read what the library actually does.
630
+ const SNES_PVSNESLIB_VENDOR_DIRS = [
631
+ { src: "lib/pvsneslib/include", dst: "vendor/pvsneslib/include" },
632
+ { src: "lib/pvsneslib/source", dst: "vendor/pvsneslib/source" },
633
+ ];
634
+
635
+ TEMPLATES.snes = {
636
+ // C is the SNES default. PVSnesLib gives a clean C API (oamSet,
637
+ // padsCurrent, WaitForVBlank, etc.) instead of raw 65816 — same
638
+ // ergonomics as every other platform's C-mode default. Renders a
639
+ // movable sprite on a blue backdrop, no font dependency.
640
+ default: {
641
+ main: "templates/default.c",
642
+ extraSources: [
643
+ { src: "templates/default-data.asm", dst: "data.asm" },
644
+ ],
645
+ runtime: [],
646
+ runtimeDirs: SNES_PVSNESLIB_VENDOR_DIRS,
647
+ lang: "C (tcc-65816 + PVSnesLib)",
648
+ ext: ".sfc",
649
+ describe: "Minimal SNES C starter: movable sprite + blue backdrop using PVSnesLib (oamSet, padsCurrent, WaitForVBlank). Two-file project: main.c + data.asm.",
650
+ },
651
+ // Raw 65816 path — kept for cycle-accurate work, IRQ-driven raster
652
+ // effects, etc. Same content as the pre-2026-05-27 `default`.
653
+ asm: {
654
+ main: "main.asm",
655
+ runtime: [
656
+ { src: "lib/lorom_header.asm", dst: "lorom_header.asm" },
657
+ { src: "lib/cgram_upload.asm", dst: "cgram_upload.asm" },
658
+ { src: "lib/reset_init.asm", dst: "reset_init.asm" },
659
+ ],
660
+ lang: "65816 assembly (asar)",
661
+ ext: ".sfc",
662
+ describe: "Raw 65816 asar starter: blue backdrop via CGRAM upload. Use when you need cycle-accurate control (raster splits, mid-frame DMA, etc.). For most game work prefer template:\"default\" (PVSnesLib C).",
663
+ },
664
+ // Text-mode console hello-world. Useful for status displays /
665
+ // debug overlays / tutorial-style text adventures.
666
+ c_hello: {
667
+ main: "templates/c-hello.c",
668
+ extraSources: [
669
+ { src: "templates/c-hello-data.asm", dst: "data.asm" },
670
+ ],
671
+ runtime: [],
672
+ runtimeDirs: SNES_PVSNESLIB_VENDOR_DIRS,
673
+ lang: "C (tcc-65816 + PVSnesLib)",
674
+ ext: ".sfc",
675
+ describe: "PVSnesLib text-mode starter: consoleDrawText writes ASCII into a tile-mapped BG0. Stub font in data.asm — replace with .incbin of a real .pic/.pal for legible glyphs.",
676
+ },
677
+ // R21: parity templates with NES + Genesis. tcc-65816 is C89, so all
678
+ // declarations live at block top. Two-file projects (.c + .asm) because
679
+ // PVSnesLib's runtime expects tilfont/palfont symbols to be linkable;
680
+ // sprite templates also ship tilsprite + palsprite hand-authored bytes.
681
+ hello_sprite: {
682
+ main: "templates/hello_sprite.c",
683
+ extraSources: [
684
+ { src: "templates/hello_sprite-data.asm", dst: "data.asm" },
685
+ ],
686
+ runtime: [],
687
+ runtimeDirs: SNES_PVSNESLIB_VENDOR_DIRS,
688
+ lang: "C (tcc-65816 + PVSnesLib)",
689
+ ext: ".sfc",
690
+ describe: "One 8×8 sprite + d-pad. oamSet/oamUpdate canonical loop, hand-authored sprite tile + palette in data.asm. Fork to add more sprites, animations, sound.",
691
+ },
692
+ shmup: {
693
+ main: "templates/shmup.c",
694
+ extraSources: [
695
+ { src: "templates/shmup-data.asm", dst: "data.asm" },
696
+ ],
697
+ runtime: SNES_SFX_RUNTIME,
698
+ runtimeDirs: SNES_PVSNESLIB_VENDOR_DIRS,
699
+ lang: "C (tcc-65816 + PVSnesLib)",
700
+ ext: ".sfc",
701
+ describe: "Vertical-shmup scaffold for SNES. Player ship + 6 bullets + 6 enemies, wave spawner, AABB collisions, score. SFX (pew on fire, boom on hit) via the bundled SPC700 driver + sample bank.",
702
+ },
703
+ platformer: {
704
+ main: "templates/platformer.c",
705
+ extraSources: [
706
+ { src: "templates/platformer-data.asm", dst: "data.asm" },
707
+ ],
708
+ runtime: SNES_SFX_RUNTIME,
709
+ runtimeDirs: SNES_PVSNESLIB_VENDOR_DIRS,
710
+ lang: "C (tcc-65816 + PVSnesLib)",
711
+ ext: ".sfc",
712
+ describe: "SIDE-SCROLLING platformer for SNES (PVSnesLib). Subpixel gravity + jump + land-on-top collision across a 512-px world. A camera follows the player; the BG scrolls in hardware via bgSetScroll(0, camX, 0) and the player sprite draws in screen space (worldX - camX), held screen-centered while the world moves under it. Jump SFX via the bundled SPC700 driver. NOTE: uses the PVSnesLib console (text) BG, so platforms are collision-only and the scroll shows as the on-BG text sliding — for visible tiled platform art across a wide world, build a tileset with gfx2snes + bgInitTileSet on a 64-wide map and stream tilemap columns into VRAM during vblank. See the SNES MENTAL_MODEL.md 'Horizontal scrolling'. BUILD: needs language:'c', snes_sfx_data.asm in sources, apu_blob.bin as a binary include, and snes_sfx.c/.h in includePaths (all scaffolded by createGame).",
713
+ },
714
+ puzzle: {
715
+ main: "templates/puzzle.c",
716
+ extraSources: [
717
+ { src: "templates/puzzle-data.asm", dst: "data.asm" },
718
+ ],
719
+ runtime: SNES_SFX_RUNTIME,
720
+ runtimeDirs: SNES_PVSNESLIB_VENDOR_DIRS,
721
+ lang: "C (tcc-65816 + PVSnesLib)",
722
+ ext: ".sfc",
723
+ describe: "Match-3 falling-block puzzle for SNES. 6×12 grid (text mode), rotate/soft-drop/hard-drop, horizontal-triple clear. Rotate click + clear chime via bundled SPC700 sfx.",
724
+ },
725
+ sports: {
726
+ main: "templates/sports.c",
727
+ extraSources: [
728
+ { src: "templates/sports-data.asm", dst: "data.asm" },
729
+ ],
730
+ runtime: SNES_SFX_RUNTIME,
731
+ runtimeDirs: SNES_PVSNESLIB_VENDOR_DIRS,
732
+ lang: "C (tcc-65816 + PVSnesLib)",
733
+ ext: ".sfc",
734
+ describe: "Two-player Pong on SNES. padsCurrent(0)/padsCurrent(1) wire both ports. Paddle-hit + score sfx via bundled SPC700 driver.",
735
+ },
736
+ racing: {
737
+ main: "templates/racing.c",
738
+ extraSources: [
739
+ { src: "templates/racing-data.asm", dst: "data.asm" },
740
+ ],
741
+ runtime: SNES_SFX_RUNTIME,
742
+ runtimeDirs: SNES_PVSNESLIB_VENDOR_DIRS,
743
+ lang: "C (tcc-65816 + PVSnesLib)",
744
+ ext: ".sfc",
745
+ describe: "Endless 3-lane top-down racer for SNES. LEFT/RIGHT switches lanes, obstacles slide down at growing speed. Two sprite tiles (player + enemy), score in BG text overlay.",
746
+ },
747
+ // R46: continuous-music demo on the SPC700 driver. Showcases
748
+ // sfx_music_play / sfx_music_stop alongside the existing sfx_play
749
+ // path — the SPC walks a song table autonomously while the 65816
750
+ // just polls input.
751
+ music_demo: {
752
+ main: "templates/music_demo.c",
753
+ extraSources: [
754
+ { src: "templates/music_demo-data.asm", dst: "data.asm" },
755
+ ],
756
+ runtime: SNES_SFX_RUNTIME,
757
+ runtimeDirs: SNES_PVSNESLIB_VENDOR_DIRS,
758
+ lang: "C (tcc-65816 + PVSnesLib)",
759
+ ext: ".sfc",
760
+ describe: "Continuous SPC700 music + SFX demo. Auto-plays a looping arpeggio on voice 1; B = shoot sfx (voice 0), A = stop music, START = resume. Starting point for adding music to any SNES C scaffold.",
761
+ },
762
+ };
763
+ // All SGDK Genesis C templates share the same runtime bundle: crt0 (sega.s +
764
+ // cpp-expanded sega.preprocessed.s for the bare WASM `as`), linker script, ROM
765
+ // header source, MIT license, and the full include tree. SGDK itself is
766
+ // compiled from source by the build (its source is vendored via
767
+ // SGDK_RUNTIME_DIRS) — no prebuilt libmd.a is copied in.
768
+ const SGDK_RUNTIME = [
769
+ { src: "lib/sgdk/sega.s", dst: "sega.s" },
770
+ { src: "lib/sgdk/sega.preprocessed.s", dst: "sega.preprocessed.s" },
771
+ { src: "lib/sgdk/rom_header.c", dst: "rom_header.c" },
772
+ { src: "lib/sgdk/md.ld", dst: "md.ld" },
773
+ { src: "lib/sgdk/LICENSE", dst: "LICENSE-SGDK" },
774
+ { src: "lib/sgdk/COPYING.RUNTIME", dst: "COPYING-SGDK-RUNTIME" },
775
+ // R30: minimal PSG sound-effects wrapper. 3 functions matching the
776
+ // NES/GB/GBA scaffold sound shape.
777
+ { src: "lib/c/genesis_sfx.h", dst: "genesis_sfx.h" },
778
+ { src: "lib/c/genesis_sfx.c", dst: "genesis_sfx.c" },
779
+ ];
780
+ const SGDK_RUNTIME_DIRS = [
781
+ { src: "lib/sgdk/include", dst: "include" },
782
+ // R58b: ship the full SGDK src tree into the project. Agent can grep
783
+ // it directly instead of guessing what SPR_addSprite / VDP_drawText /
784
+ // JOY_readJoypad / XGM2_startPlay actually do. SGDK is compiled FROM this
785
+ // source by the build (no prebuilt libmd.a).
786
+ { src: "lib/sgdk/src", dst: "vendor/sgdk/src" },
787
+ // res/: the generated libres (default font/logo) + its source (.res + PNGs)
788
+ // and the regen recipe — so the resource blobs are reproducible, not opaque.
789
+ { src: "lib/sgdk/res", dst: "vendor/sgdk/res" },
790
+ ];
791
+ const SGDK_LANG = "C (m68k-elf-gcc + SGDK)";
792
+
793
+ // R42: XGM2 music runtime — adds the demo .vgm source + compiled .xgc blob
794
+ // alongside the standard SGDK headers/libmd. .vgm is the human-editable
795
+ // chiptune (regen via scripts/build-genesis-demo-vgm.js + xgm2tool); .xgc
796
+ // is what gets .incbin'd into ROM via the data.s sibling.
797
+ const SGDK_XGM2_RUNTIME = [
798
+ ...SGDK_RUNTIME,
799
+ { src: "lib/sgdk/music/demo.vgm", dst: "demo.vgm" },
800
+ { src: "lib/sgdk/music/demo.xgc", dst: "demo.xgc" },
801
+ ];
802
+
803
+ TEMPLATES.genesis = {
804
+ // C via SGDK is the Genesis default. SGDK gives a clean C API
805
+ // (VDP_drawText, SYS_doVBlankProcess, SPR_addSprite, etc.) and
806
+ // builds in <2s. Same ergonomics as every other platform's C
807
+ // default — agent ships a game in one session, not 10.
808
+ default: {
809
+ main: "templates/sgdk_hello.c",
810
+ runtime: SGDK_RUNTIME,
811
+ runtimeDirs: SGDK_RUNTIME_DIRS,
812
+ lang: SGDK_LANG,
813
+ ext: ".bin",
814
+ describe: "Genesis C default using SGDK: VDP_drawText shows 'HELLO SEGA GENESIS'. #include <genesis.h>, SYS_doVBlankProcess, full SGDK API. For raw 68k asm see template:\"asm\".",
815
+ },
816
+ // Kept for cycle-accurate work / IRQ-driven raster effects.
817
+ asm: {
818
+ main: "main.s",
819
+ runtime: [
820
+ { src: "lib/header.s", dst: "header.s" },
821
+ { src: "lib/vdp_init.s", dst: "vdp_init.s" },
822
+ { src: "lib/vblank_wait.s", dst: "vblank_wait.s" },
823
+ ],
824
+ lang: "68k assembly (vasm68k)",
825
+ ext: ".bin",
826
+ describe: "Raw 68k Genesis starter (vasm68k): header + VDP init + vblank wait. Use when you need cycle-accurate control (raster splits, mid-frame DMA). For most game work prefer template:\"default\" (SGDK C).",
827
+ },
828
+ sgdk_hello: {
829
+ main: "templates/sgdk_hello.c",
830
+ runtime: SGDK_RUNTIME,
831
+ runtimeDirs: SGDK_RUNTIME_DIRS,
832
+ lang: SGDK_LANG,
833
+ ext: ".bin",
834
+ describe: "Alias of template:\"default\" (kept for backward-compat with earlier scripts that named it explicitly).",
835
+ },
836
+ // R42: XGM2 music playback — counterpart to the R30 PSG sfx wrapper.
837
+ // Two-file project (main.c + data.s sibling); data.s does the .incbin
838
+ // of demo.xgc, matching R31's snes_sfx_data.asm pattern. The compiled
839
+ // .xgc plus its source .vgm both ship in the project tree so users can
840
+ // regen with xgm2tool.
841
+ xgm2_demo: {
842
+ main: "templates/xgm2_demo.c",
843
+ extraSources: [
844
+ { src: "templates/xgm2_demo_data.s", dst: "data.s" },
845
+ ],
846
+ runtime: SGDK_XGM2_RUNTIME,
847
+ runtimeDirs: SGDK_RUNTIME_DIRS,
848
+ lang: SGDK_LANG,
849
+ ext: ".bin",
850
+ describe: "XGM2 music playback demo. XGM2_loadDriver + XGM2_play, music blob incbin'd via data.s sibling. Ships a tiny CC0 PSG arpeggio (demo.vgm source + demo.xgc compiled) — regen with SGDK's xgm2tool. SYS_doVBlankProcess drives the Z80 driver tick.",
851
+ },
852
+ hello_sprite: {
853
+ main: "templates/hello_sprite.c",
854
+ runtime: SGDK_RUNTIME,
855
+ runtimeDirs: SGDK_RUNTIME_DIRS,
856
+ lang: SGDK_LANG,
857
+ ext: ".bin",
858
+ describe: "Single sprite + d-pad. Uploads one 8×8 tile via VDP_loadTileData, places one VDP sprite, reads JOY_1 each frame, calls VDP_updateSprites + SYS_doVBlankProcess. The minimum-viable input-driven scaffold — fork from here to add more sprites, palettes, sound.",
859
+ },
860
+ tile_engine: {
861
+ main: "templates/tile_engine.c",
862
+ runtime: SGDK_RUNTIME,
863
+ runtimeDirs: SGDK_RUNTIME_DIRS,
864
+ lang: SGDK_LANG,
865
+ ext: ".bin",
866
+ describe: "40×28 tile world on plane B with a walking player + AABB collision against solid tile IDs. Demonstrates VDP_setTileMapXY / VDP_fillTileMapRect / two-plane composition. Single-screen — extend with VDP_setHorizontalScroll for scrolling worlds.",
867
+ },
868
+ shmup: {
869
+ main: "templates/shmup.c",
870
+ runtime: SGDK_RUNTIME,
871
+ runtimeDirs: SGDK_RUNTIME_DIRS,
872
+ lang: SGDK_LANG,
873
+ ext: ".bin",
874
+ describe: "Vertical-shmup genre scaffold. Player ship + 6 bullet slots + 6 enemy slots (object pools, no malloc), wave spawner, AABB collisions, score. Pre-allocated SAT slot ranges (0=player, 1-6=bullets, 7-12=enemies) so no flicker.",
875
+ },
876
+ platformer: {
877
+ main: "templates/platformer.c",
878
+ runtime: SGDK_RUNTIME,
879
+ runtimeDirs: SGDK_RUNTIME_DIRS,
880
+ lang: SGDK_LANG,
881
+ ext: ".bin",
882
+ describe: "SIDE-SCROLLING platformer for Genesis. Subpixel gravity + jump + land-on-top collision against a static platform list spread across a 512-px world. Camera follows the player; Plane A scrolls with the world via VDP_setHorizontalScroll, Plane B scrolls at half-rate for parallax. A=jump, d-pad=move. The world here is one 64-cell plane wide (no streaming) — for a wider world, stream the column entering view each 8-px camera step (see Genesis MENTAL_MODEL.md 'Horizontal scrolling'). Extend with enemies, goals, pickups.",
883
+ },
884
+ puzzle: {
885
+ main: "templates/puzzle.c",
886
+ runtime: SGDK_RUNTIME,
887
+ runtimeDirs: SGDK_RUNTIME_DIRS,
888
+ lang: SGDK_LANG,
889
+ ext: ".bin",
890
+ describe: "Match-3 falling-block puzzle genre scaffold. 6×12 grid, 1×3 active piece (3 colours), rotate via A, soft-drop on DOWN, hard-drop on START, horizontal-triple clear. xorshift RNG so cell colours actually vary.",
891
+ },
892
+ sports: {
893
+ main: "templates/sports.c",
894
+ runtime: SGDK_RUNTIME,
895
+ runtimeDirs: SGDK_RUNTIME_DIRS,
896
+ lang: SGDK_LANG,
897
+ ext: ".bin",
898
+ describe: "Two-player Pong via JOY_1 + JOY_2. AI fallback on port 2 when no second controller. Per-side score 0-9 rendered via VDP_drawText, ball bounces off paddles + court walls. Designed for the playtest window with hot-plugged controllers.",
899
+ },
900
+ racing: {
901
+ main: "templates/racing.c",
902
+ runtime: SGDK_RUNTIME,
903
+ runtimeDirs: SGDK_RUNTIME_DIRS,
904
+ lang: SGDK_LANG,
905
+ ext: ".bin",
906
+ describe: "Endless top-down 3-lane racer. LEFT/RIGHT switches lanes, obstacles slide down at increasing speed as score climbs. Game-over on collision with 60-frame freeze then auto-reset.",
907
+ },
908
+ shmup_2p: {
909
+ main: "templates/shmup_2p.c",
910
+ runtime: SGDK_RUNTIME,
911
+ runtimeDirs: SGDK_RUNTIME_DIRS,
912
+ lang: SGDK_LANG,
913
+ ext: ".bin",
914
+ describe: "Two-player competitive shmup via JOY_1 + JOY_2. Each player has their own ship + 4-bullet pool + score. Enemies shared — first to hit scores the 10 points. Designed for the romdev playtest window with two hot-plugged controllers.",
915
+ },
916
+ };
917
+
918
+ // Simpler one-file platforms — no runtime/template variants, just a seed source.
919
+ // These platforms don't yet have a per-platform lib/ runtime to bundle.
920
+ // Empty today; every supported platform now has a full TEMPLATES entry.
921
+ const SIMPLE_STARTERS = {};
922
+
923
+ // R38: Lynx tier-1 with full template set + MIKEY sound + tgi graphics.
924
+ // R43: music_demo template — cc65's lynx_snd_play streaming music engine.
925
+ // R58b: ship the cc65 Lynx libsrc INTO each project so the agent can
926
+ // grep the TGI driver / lynx_snd engine / joystick driver without
927
+ // leaving their project dir. The 1500-frame TGI wedge round
928
+ // (rounds 28-32) was caused entirely by the agent debugging a
929
+ // blackbox driver. R58 copy-into-install was the half-step;
930
+ // R58b shipping into the PROJECT closes the loop.
931
+ const LYNX_VENDOR_DIRS = [
932
+ { src: "lib/cc65-src", dst: "vendor/cc65/libsrc/lynx" },
933
+ ];
934
+ const LYNX_RUNTIME = [
935
+ { src: "lib/c/lynx_sfx.h", dst: "lynx_sfx.h" },
936
+ { src: "lib/c/lynx_sfx.c", dst: "lynx_sfx.c" },
937
+ ];
938
+ const LYNX_MUSIC_RUNTIME = [
939
+ { src: "lib/c/lynx_music.h", dst: "lynx_music.h" },
940
+ { src: "lib/c/lynx_music.c", dst: "lynx_music.c" },
941
+ ];
942
+ const LYNX_LANG = "C (cc65 + tgi)";
943
+ TEMPLATES.lynx = {
944
+ default: {
945
+ main: "templates/default.c", runtime: LYNX_RUNTIME, runtimeDirs: LYNX_VENDOR_DIRS,
946
+ lang: LYNX_LANG, ext: ".lnx",
947
+ describe: "Minimal Lynx starter: TGI color-cycling square + 'HELLO LYNX' text. Smallest possible ROM that does something visible — use as starting point when you're not sure what to build. Project also includes vendor/cc65/libsrc/lynx/ — the FULL cc65 Lynx driver source (TGI, joystick, sound, conio) so you can grep it directly when debugging.",
948
+ },
949
+ hello_sprite: {
950
+ main: "templates/hello_sprite.c", runtime: LYNX_RUNTIME, runtimeDirs: LYNX_VENDOR_DIRS,
951
+ lang: LYNX_LANG, ext: ".lnx",
952
+ describe: "Lynx hello + joystick movement. cc65 tgi graphics + lynx_sfx for sound. Boot chime confirms MIKEY audio is wired.",
953
+ },
954
+ music_demo: {
955
+ main: "templates/music_demo.c", runtime: LYNX_MUSIC_RUNTIME, runtimeDirs: LYNX_VENDOR_DIRS,
956
+ lang: LYNX_LANG, ext: ".lnx",
957
+ describe: "cc65's lynx_snd_play streaming music engine demo. Plays a short (note, length) sequence on channel 0 via the 240Hz timer IRQ. Hand-authored music bytestream in lynx_music.c — the byte array IS the source. Pairs with lynx_sfx (one-shot pokes) for full audio coverage.",
958
+ },
959
+ shmup: {
960
+ main: "templates/shmup.c", runtime: LYNX_RUNTIME, runtimeDirs: LYNX_VENDOR_DIRS,
961
+ lang: LYNX_LANG, ext: ".lnx",
962
+ describe: "Vertical-shmup. Player + 4 bullets + 4 enemies (object pools), AABB collisions. MIKEY pew + boom sfx.",
963
+ },
964
+ platformer: {
965
+ main: "templates/platformer.c", runtime: LYNX_RUNTIME, runtimeDirs: LYNX_VENDOR_DIRS,
966
+ lang: LYNX_LANG, ext: ".lnx",
967
+ describe: "Single-screen platformer. Subpixel gravity + jump + 5 platforms. MIKEY jump sfx.",
968
+ },
969
+ puzzle: {
970
+ main: "templates/puzzle.c", runtime: LYNX_RUNTIME, runtimeDirs: LYNX_VENDOR_DIRS,
971
+ lang: LYNX_LANG, ext: ".lnx",
972
+ describe: "Match-3 puzzle. 6×12 grid via tgi_bar. Rotate click + clear chime via MIKEY.",
973
+ },
974
+ sports: {
975
+ main: "templates/sports.c", runtime: LYNX_RUNTIME, runtimeDirs: LYNX_VENDOR_DIRS,
976
+ lang: LYNX_LANG, ext: ".lnx",
977
+ describe: "Pong vs AI (handheld = one controller). MIKEY paddle-hit + wall-bounce + score sfx.",
978
+ },
979
+ racing: {
980
+ main: "templates/racing.c", runtime: LYNX_RUNTIME, runtimeDirs: LYNX_VENDOR_DIRS,
981
+ lang: LYNX_LANG, ext: ".lnx",
982
+ describe: "3-lane top-down racer. MIKEY lane-switch beep + crash noise.",
983
+ },
984
+ };
985
+
986
+ // R24 + R28: Game Boy Advance C tier-1 via arm-none-eabi-gcc + EITHER
987
+ // libtonc (default, Tonc-tutorial-aligned) OR libgba (devkitPro
988
+ // official). Same self-containment policy as Genesis SGDK — the
989
+ // entire runtime bundle gets copied INTO the user's project so they
990
+ // can rebuild on any machine with devkitARM installed.
991
+ //
992
+ // Why libtonc is the default: the Tonc tutorial at gbadev.net/tonc is
993
+ // THE GBA C corpus the LLM has been trained on. Agent-generated code
994
+ // matches Tonc idioms naturally (tte_write, tonccpy, OBJ_ATTR, etc.).
995
+ // libgba stays available via `runtime:"libgba"` or `template:"gba_hello"`.
996
+ //
997
+ // One caveat shared by both runtimes: the libsysbase-backed iprintf
998
+ // bridge (tte_iohook in libtonc, console.c in libgba) is NOT bundled.
999
+ // Use tte_printf directly with libtonc — that's the Tonc-tutorial
1000
+ // pattern and works without the libsysbase header chain.
1001
+ const GBA_LIBTONC_RUNTIME = [
1002
+ // libtonc itself is compiled from source by the build (its source is vendored
1003
+ // via GBA_LIBTONC_RUNTIME_DIRS), so no prebuilt libtonc.a is copied in.
1004
+ { src: "lib/libtonc/gba_crt0.s", dst: "gba_crt0.s" },
1005
+ { src: "lib/libtonc/gba_cart.ld", dst: "gba_cart.ld" },
1006
+ { src: "lib/libtonc/crti.o", dst: "crti.o" },
1007
+ { src: "lib/libtonc/crtn.o", dst: "crtn.o" },
1008
+ { src: "lib/libtonc/crtbegin.o", dst: "crtbegin.o" },
1009
+ { src: "lib/libtonc/crtend.o", dst: "crtend.o" },
1010
+ // Minimal sfx wrapper around the GBA's DMG-compatible APU. Matches
1011
+ // the NES/GB scaffold sound shape — sfx_init + sfx_tone + sfx_noise.
1012
+ { src: "lib/c/gba_sfx.h", dst: "gba_sfx.h" },
1013
+ { src: "lib/c/gba_sfx.c", dst: "gba_sfx.c" },
1014
+ ];
1015
+ const GBA_LIBTONC_RUNTIME_DIRS = [
1016
+ { src: "lib/libtonc/include", dst: "include" },
1017
+ { src: "lib/libgba/sysinclude", dst: "sysinclude" }, // shared with libgba
1018
+ // R58b: ship the FULL libtonc source tree INTO the project so the
1019
+ // agent can grep/read every implementation (TTE, OAM helpers, IRQ
1020
+ // setup, etc.) instead of stabbing in the dark against libtonc.a.
1021
+ // The 1500-frame Lynx wedge took 5 rounds partly because cc65 TGI
1022
+ // source wasn't in the project tree. Don't repeat that for libtonc.
1023
+ { src: "lib/libtonc/src", dst: "vendor/libtonc/src" },
1024
+ { src: "lib/maxmod", dst: "vendor/maxmod" },
1025
+ ];
1026
+ const GBA_LIBGBA_RUNTIME = [
1027
+ // libgba is compiled from source by the build (source vendored via
1028
+ // GBA_LIBGBA_RUNTIME_DIRS); no prebuilt libgba.a copied in.
1029
+ { src: "lib/libgba/gba_crt0.s", dst: "gba_crt0.s" },
1030
+ { src: "lib/libgba/gba_cart.ld", dst: "gba_cart.ld" },
1031
+ { src: "lib/libgba/crti.o", dst: "crti.o" },
1032
+ { src: "lib/libgba/crtn.o", dst: "crtn.o" },
1033
+ { src: "lib/libgba/crtbegin.o", dst: "crtbegin.o" },
1034
+ { src: "lib/libgba/crtend.o", dst: "crtend.o" },
1035
+ ];
1036
+ const GBA_LIBGBA_RUNTIME_DIRS = [
1037
+ { src: "lib/libgba/include", dst: "include" },
1038
+ { src: "lib/libgba/sysinclude", dst: "sysinclude" },
1039
+ // R58b: ship full libgba source so the agent can grep irqInit /
1040
+ // irqSet / VBlankIntrWait / GBA register defines directly.
1041
+ { src: "lib/libgba/src", dst: "vendor/libgba/src" },
1042
+ ];
1043
+ const GBA_TONC_LANG = "C (arm-none-eabi-gcc + libtonc)";
1044
+ const GBA_LIBGBA_LANG = "C (arm-none-eabi-gcc + libgba)";
1045
+
1046
+ TEMPLATES.gba = {
1047
+ // Tonc is the default — first key + canonical for new projects.
1048
+ tonc_hello: {
1049
+ main: "templates/tonc_hello.c",
1050
+ runtime: GBA_LIBTONC_RUNTIME,
1051
+ runtimeDirs: GBA_LIBTONC_RUNTIME_DIRS,
1052
+ lang: GBA_TONC_LANG,
1053
+ ext: ".gba",
1054
+ describe: "Idiomatic Tonc-tutorial GBA C starter. #include <tonc.h>, TTE (Tonc Text Engine) draws 'Hello, Tonc!' on BG0 in MODE_0. Matches what every published GBA C tutorial at gbadev.net teaches. libtonc is compiled from its vendored source by the build (a fast prebuilt seed by default; pass rebuildSdk:true if you edit the SDK source) — the project gets the headers + gba_crt0 + linker script. Build with buildSource({platform:'gba', language:'c'}) — defaults to runtime:'libtonc'.",
1055
+ },
1056
+ tonc_hello_sprite: {
1057
+ main: "templates/tonc_hello_sprite.c",
1058
+ runtime: GBA_LIBTONC_RUNTIME,
1059
+ runtimeDirs: GBA_LIBTONC_RUNTIME_DIRS,
1060
+ lang: GBA_TONC_LANG,
1061
+ ext: ".gba",
1062
+ describe: "One 8x8 sprite driven by the d-pad. Canonical Tonc sprite-chapter pattern: OBJ_ATTR shadow buffer + oam_copy DMA flush + key_poll/key_held input + 4bpp sprite tile + sprite palette setup. Forks well to multi-sprite scaffolds.",
1063
+ },
1064
+ shmup: {
1065
+ main: "templates/shmup.c",
1066
+ runtime: GBA_LIBTONC_RUNTIME,
1067
+ runtimeDirs: GBA_LIBTONC_RUNTIME_DIRS,
1068
+ lang: GBA_TONC_LANG,
1069
+ ext: ".gba",
1070
+ describe: "Vertical shmup scaffold (Tonc). Player ship + 6 bullets + 6 enemies (fixed object pools), AABB collision, enemy wave spawner, TTE score readout. ~150 lines.",
1071
+ },
1072
+ platformer: {
1073
+ main: "templates/platformer.c",
1074
+ runtime: GBA_LIBTONC_RUNTIME,
1075
+ runtimeDirs: GBA_LIBTONC_RUNTIME_DIRS,
1076
+ lang: GBA_TONC_LANG,
1077
+ ext: ".gba",
1078
+ describe: "SIDE-SCROLLING platformer for GBA (Tonc). Subpixel physics (1px = 16 subpixels), gravity + jump + land-on-top collision against platforms in a 512-px world. BG0 is a 64x32 map (whole world fits, no streaming); the camera follows the player via REG_BG0HOFS; the TTE HUD on BG1 stays fixed. For a world wider than 512 px, stream map columns as the camera advances (see GBA MENTAL_MODEL.md). Extend with enemies, goals, pickups.",
1079
+ },
1080
+ puzzle: {
1081
+ main: "templates/puzzle.c",
1082
+ runtime: GBA_LIBTONC_RUNTIME,
1083
+ runtimeDirs: GBA_LIBTONC_RUNTIME_DIRS,
1084
+ lang: GBA_TONC_LANG,
1085
+ ext: ".gba",
1086
+ describe: "Match-3 falling-block scaffold (Tonc). 6x12 grid drawn as BG tiles, 1x3 active piece with LEFT/RIGHT shift, A rotate, DOWN soft-drop, START hard-drop. Horizontal triples clear + score.",
1087
+ },
1088
+ sports: {
1089
+ main: "templates/sports.c",
1090
+ runtime: GBA_LIBTONC_RUNTIME,
1091
+ runtimeDirs: GBA_LIBTONC_RUNTIME_DIRS,
1092
+ lang: GBA_TONC_LANG,
1093
+ ext: ".gba",
1094
+ describe: "Pong scaffold (Tonc). Single-controller GBA → right paddle is AI ball-tracker. 24px paddles built from 3 stacked 8x8 sprites, ball collisions, score 0-9 via TTE. Real 2P on GBA needs link cable (out of scope).",
1095
+ },
1096
+ racing: {
1097
+ main: "templates/racing.c",
1098
+ runtime: GBA_LIBTONC_RUNTIME,
1099
+ runtimeDirs: GBA_LIBTONC_RUNTIME_DIRS,
1100
+ lang: GBA_TONC_LANG,
1101
+ ext: ".gba",
1102
+ describe: "Top-down 3-lane racer scaffold (Tonc). Player car bottom, obstacles spawn from top + slide down, L/R switches lanes, AABB crash detection, 60-frame freeze + reset. Score is frames-since-crash.",
1103
+ },
1104
+ // Opt-in libgba path for users who prefer the devkitPro SDK or are
1105
+ // porting an existing libgba codebase.
1106
+ gba_hello: {
1107
+ main: "templates/gba_hello.c",
1108
+ runtime: GBA_LIBGBA_RUNTIME,
1109
+ runtimeDirs: GBA_LIBGBA_RUNTIME_DIRS,
1110
+ lang: GBA_LIBGBA_LANG,
1111
+ ext: ".gba",
1112
+ describe: "Alternate GBA C starter using devkitPro's libgba SDK. MODE_3 framebuffer + red pixel. Pass runtime:'libgba' to buildSource — or just use the Tonc path (gba_hello_tonc) which is better aligned with what published tutorials teach.",
1113
+ },
1114
+ // R34: maxmod music demo. Ships a hand-authored CC0 chiptune.xm +
1115
+ // its pre-built soundbank.bin. buildSource must be called with
1116
+ // `maxmod: true` AND binaryIncludes:{ "soundbank.bin": <bytes> } —
1117
+ // the buildGbaC layer auto-emits a `.incbin "soundbank.bin"` asm
1118
+ // stub exposing the soundbank under the global symbol soundbank_bin.
1119
+ // The .xm source ships alongside so users can regenerate the
1120
+ // soundbank with mmutil after editing the tune.
1121
+ maxmod_demo: {
1122
+ main: "templates/maxmod_demo.c",
1123
+ runtime: [
1124
+ ...GBA_LIBTONC_RUNTIME,
1125
+ // maxmod compiled from source by the build — no prebuilt libmm.a.
1126
+ { src: "lib/maxmod/music/chiptune.xm", dst: "chiptune.xm" },
1127
+ { src: "lib/maxmod/music/chiptune_soundbank.bin", dst: "soundbank.bin" },
1128
+ { src: "lib/maxmod/music/chiptune_soundbank.h", dst: "soundbank.h" },
1129
+ { src: "lib/maxmod/music/make_chiptune_xm.js", dst: "make_chiptune_xm.js" },
1130
+ { src: "lib/maxmod/LICENSE-MAXMOD", dst: "LICENSE-MAXMOD" },
1131
+ ],
1132
+ runtimeDirs: [
1133
+ ...GBA_LIBTONC_RUNTIME_DIRS,
1134
+ // Adds maxmod.h + mm_types.h next to the libtonc headers.
1135
+ { src: "lib/maxmod/include", dst: "include" },
1136
+ ],
1137
+ lang: GBA_TONC_LANG,
1138
+ ext: ".gba",
1139
+ maxmod: true,
1140
+ binaryIncludes: ["soundbank.bin"],
1141
+ describe: "Maxmod music demo (Tonc + libmm). Plays a CC0 chiptune.xm soundbank via mmInitDefault + mmStart + mmFrame, with START toggling pause. Pass `maxmod:true` AND `binaryIncludes:{\"soundbank.bin\": <bytes>}` to buildSource. The .xm source + generator script + pre-built soundbank.bin all ship in the project — edit and re-run mmutil to swap the tune.",
1142
+ },
1143
+ };
1144
+
1145
+ // R22: Atari 2600 promoted to multi-template platform. The 2600 has no
1146
+ // C compiler (asm only via dasm) and the genre-shmup/platformer/puzzle
1147
+ // scaffolds from other platforms don't map cleanly — its hardware
1148
+ // forces "race the beam" rendering. Three templates here that ARE
1149
+ // idiomatic 2600:
1150
+ // default — single sprite, blue background, joystick movement
1151
+ // paddle — Pong-style: two paddles + ball + walls
1152
+ // single_screen — dodge-the-falling-pixels using P0 + M0
1153
+ // music_demo — two-voice TIA chiptune
1154
+ // mini_invaders — gallery shooter via P0 cannon + P1/NUSIZ1 invaders + M0 shot
1155
+ TEMPLATES.atari2600 = {
1156
+ default: {
1157
+ main: "templates/default.asm",
1158
+ runtime: [],
1159
+ lang: "6507 assembly (dasm)",
1160
+ ext: ".a26",
1161
+ describe: "Hello, 2600. Blue background + white player sprite + joystick movement. Race-the-beam scanline-by-scanline rendering; demonstrates VSYNC/VBLANK/visible/overscan frame structure.",
1162
+ },
1163
+ paddle: {
1164
+ main: "templates/paddle.asm",
1165
+ runtime: [],
1166
+ lang: "6507 assembly (dasm)",
1167
+ ext: ".a26",
1168
+ describe: "Pong-style scaffold. Two 8-pixel paddles (P0 + P1), one 2-pixel ball (BL), top + bottom walls (PF). Left paddle on joystick, right paddle AI chases ball Y. Demonstrates multi-object positioning via RESP0/RESP1/RESBL.",
1169
+ },
1170
+ single_screen: {
1171
+ main: "templates/single_screen.asm",
1172
+ runtime: [],
1173
+ lang: "6507 assembly (dasm)",
1174
+ ext: ".a26",
1175
+ describe: "Dodge-the-falling-pixels scaffold. Player at bottom (P0), one falling rock (M0 missile). Demonstrates per-frame missile reset + survive-counter. Extend with multiple missiles, hit detection via TIA collision regs.",
1176
+ },
1177
+ music_demo: {
1178
+ main: "templates/music_demo.asm",
1179
+ runtime: [],
1180
+ lang: "6507 assembly (dasm)",
1181
+ ext: ".a26",
1182
+ describe: "Two-voice TIA chiptune scaffold. Voice 0 = 32-note melody, voice 1 = 16-note bass ostinato, both driven from hand-authored (AUDF, length_frames) note tables in ROM. AUDC0=AUDC1=$04 (pure tone). Music updates happen during VBLANK (never during visible scanlines). Display is minimal — blue BG + a centered playfield band — because the point IS the audio. The note tables ARE the song; edit them and you're writing chiptune.",
1183
+ },
1184
+ mini_invaders: {
1185
+ main: "templates/mini_invaders.asm",
1186
+ runtime: [],
1187
+ lang: "6507 assembly (dasm)",
1188
+ ext: ".a26",
1189
+ describe: "Gallery-shooter (Space-Invaders-shaped) done with the RIGHT TIA objects, not playfield 'barcode' bars: P0 = double-width cannon, P1 + NUSIZ1=%011 = a row of THREE hardware-replicated invaders (one GRP1 write draws all three), M0 = the player shot. Aliens march left/right and drop a step at the edges; fire with the joystick button. The honest 2600-idiomatic way to do this genre — extend by reusing P1 lower for shields or adding M1 as an alien bomb. Verified: marches + renders cannon/aliens/shot.",
1190
+ },
1191
+ };
1192
+
1193
+ // R22: Atari 7800 promoted to multi-template platform. Each template is
1194
+ // a standalone .c file under examples/atari7800/templates/. The 7800's
1195
+ // MARIA architecture (display lists, no traditional tilemap) makes the
1196
+ // scaffolds work differently from the NES — see the comments in each
1197
+ // template for the per-object-DL vs framebuffer trade-off.
1198
+ // R40: TIA sound wrapper for 7800 scaffolds. 2 voices (no noise channel
1199
+ // per se — but distortion mode 8 = white noise). See atari7800_sfx.h.
1200
+ const ATARI7800_SFX_RUNTIME = [
1201
+ { src: "lib/c/atari7800_sfx.h", dst: "atari7800_sfx.h" },
1202
+ { src: "lib/c/atari7800_sfx.c", dst: "atari7800_sfx.c" },
1203
+ ];
1204
+ // R44: TIA 2-voice music driver — separate runtime since music_demo
1205
+ // pulls in the song-player tables (atari7800_music.*) instead of the
1206
+ // one-shot sfx wrapper. Other scaffolds still use ATARI7800_SFX_RUNTIME.
1207
+ const ATARI7800_MUSIC_RUNTIME = [
1208
+ { src: "lib/c/atari7800_music.h", dst: "atari7800_music.h" },
1209
+ { src: "lib/c/atari7800_music.c", dst: "atari7800_music.c" },
1210
+ ];
1211
+
1212
+ TEMPLATES.atari7800 = {
1213
+ default: {
1214
+ main: "templates/default.c",
1215
+ runtime: ATARI7800_SFX_RUNTIME,
1216
+ lang: "C (cc65)",
1217
+ ext: ".a78",
1218
+ describe: "Minimal MARIA bring-up: DLL + DL pointing at one 16-pixel sprite + palette + DMA enable. The 7800 has no tilemap — display is a list of objects placed at (zone, x).",
1219
+ },
1220
+ hello_sprite: {
1221
+ main: "templates/hello_sprite.c",
1222
+ runtime: ATARI7800_SFX_RUNTIME,
1223
+ lang: "C (cc65)",
1224
+ ext: ".a78",
1225
+ describe: "Single sprite driven by joystick port A. Vertical movement faked by stamping the sprite at different row offsets within a 24-row canvas — real 7800 games use multi-zone DLLs for Y movement.",
1226
+ },
1227
+ shmup: {
1228
+ main: "templates/shmup.c",
1229
+ runtime: ATARI7800_SFX_RUNTIME,
1230
+ lang: "C (cc65)",
1231
+ ext: ".a78",
1232
+ describe: "Per-object-DL shmup. Each game object (player, bullet, enemy) is one MARIA 5-byte DL header. 4 bullets + 4 enemies in one zone, with X mutated per frame. Demonstrates per-frame DL rebuild + how the 7800 differs from sprite-table consoles.",
1233
+ },
1234
+ platformer: {
1235
+ main: "templates/platformer.c",
1236
+ runtime: ATARI7800_SFX_RUNTIME,
1237
+ lang: "C (cc65)",
1238
+ ext: ".a78",
1239
+ describe: "Single-screen platformer in one zone. Subpixel gravity + jump + ground detection. Vertical movement faked via row-offset stamping into the player's 24-row canvas (Y is encoded by which row of the canvas the sprite starts at).",
1240
+ },
1241
+ puzzle: {
1242
+ main: "templates/puzzle.c",
1243
+ runtime: ATARI7800_SFX_RUNTIME,
1244
+ lang: "C (cc65)",
1245
+ ext: ".a78",
1246
+ describe: "Match-3 falling-block puzzle. 6×12 grid via per-cell MARIA DL entries (one 5-byte header per filled cell). Three palettes for R/G/B colours. Active piece is 3 extra DL entries.",
1247
+ },
1248
+ sports: {
1249
+ main: "templates/sports.c",
1250
+ runtime: ATARI7800_SFX_RUNTIME,
1251
+ lang: "C (cc65)",
1252
+ ext: ".a78",
1253
+ describe: "Two-player Pong on Atari 7800. Both joystick ports wired — SWCHA bits 4-7 = P1, bits 0-3 = P2. AI fallback when P2 isn't plugged in. Three per-object MARIA DL entries (paddles + ball) drawn into tall thin canvases that fit in the 7800's 4 KB RAM.",
1254
+ },
1255
+ racing: {
1256
+ main: "templates/racing.c",
1257
+ runtime: ATARI7800_SFX_RUNTIME,
1258
+ lang: "C (cc65)",
1259
+ ext: ".a78",
1260
+ describe: "Endless 3-lane top-down racer. Per-object MARIA DL pattern (same as the 7800 shmup) — each game object is one 5-byte DL header pointing at a static tile in ROM. LEFT/RIGHT switches lanes, obstacle speed grows with score.",
1261
+ },
1262
+ music_demo: {
1263
+ main: "templates/music_demo.c",
1264
+ runtime: ATARI7800_MUSIC_RUNTIME,
1265
+ lang: "C (cc65)",
1266
+ ext: ".a78",
1267
+ describe: "TIA 2-voice music demo. Hand-authored melody (voice 0, arpeggio + descending walk) and bass (voice 1, walking I-V-IV-V quarters) drive both TIA channels via parallel { distortion, freq, frames } note tables in atari7800_music.c — the tables ARE the song. TIA's 5-bit divider gives ~32 pitches, so the tune sounds primitive on purpose. Minimal pixel-art MUSIC banner on a blue background.",
1268
+ },
1269
+ };
1270
+
1271
+ function pickRomExt(platform) {
1272
+ if (TEMPLATES[platform]) {
1273
+ if (platform === "gbc") return ".gbc";
1274
+ if (platform === "gb") return ".gb";
1275
+ if (platform === "nes") return ".nes";
1276
+ if (platform === "snes") return ".sfc";
1277
+ if (platform === "genesis") return ".bin";
1278
+ if (platform === "c64") return ".prg";
1279
+ if (platform === "sms") return ".sms";
1280
+ if (platform === "gg") return ".gg";
1281
+ if (platform === "atari7800") return ".a78";
1282
+ if (platform === "atari2600") return ".a26";
1283
+ if (platform === "gba") return ".gba";
1284
+ }
1285
+ return SIMPLE_STARTERS[platform]?.ext ?? ".bin";
1286
+ }
1287
+
1288
+ /**
1289
+ * Recursively copy every file in `srcDir` to `dstDir`, creating
1290
+ * subdirectories on demand. Each written file's project-relative path
1291
+ * is appended to `writtenFiles` (prefixed with `dstPrefix`, the
1292
+ * relative location under the project root where this subtree lives).
1293
+ *
1294
+ * Used by `runtimeDirs` template entries — currently the SGDK Genesis
1295
+ * template, which ships ~270 header files from src/platforms/genesis/
1296
+ * lib/sgdk/include into the user's project as include/.
1297
+ *
1298
+ * Header files are utf-8; everything else is read as raw bytes so
1299
+ * binary blobs (resource .pic / .pal data, archives) round-trip
1300
+ * unchanged.
1301
+ */
1302
+ async function copyDirRecursive(fs, path, srcDir, dstDir, writtenFiles, dstPrefix) {
1303
+ await fs.mkdir(dstDir, { recursive: true });
1304
+ const entries = await fs.readdir(srcDir, { withFileTypes: true });
1305
+ for (const ent of entries) {
1306
+ const srcPath = path.join(srcDir, ent.name);
1307
+ const dstPath = path.join(dstDir, ent.name);
1308
+ const relPath = dstPrefix ? `${dstPrefix}/${ent.name}` : ent.name;
1309
+ if (ent.isDirectory()) {
1310
+ await copyDirRecursive(fs, path, srcPath, dstPath, writtenFiles, relPath);
1311
+ } else if (ent.isFile()) {
1312
+ // Skip romdev-internal SDK build-cache artifacts — the .seed.a/.seed.hash
1313
+ // are how romdev's OWN build avoids recompiling the SDK; a user project
1314
+ // never builds the SDK itself, so shipping the prebuilt blob into the
1315
+ // project tree is just noise (and contradicts "everything here is source").
1316
+ if (/\.seed\.(a|hash)$/i.test(ent.name)) continue;
1317
+ const isText = /\.(h|c|s|asm|inc|ld|txt|md|cfg|json)$/i.test(ent.name);
1318
+ const contents = await fs.readFile(srcPath, isText ? "utf-8" : null);
1319
+ await fs.writeFile(dstPath, contents);
1320
+ writtenFiles.push(relPath);
1321
+ }
1322
+ }
1323
+ }
1324
+
1325
+ /**
1326
+ * Programmatic equivalent of the createProject MCP tool. Lifted to a
1327
+ * standalone function so createGame can reuse it without going through
1328
+ * the SDK's tool-call surface.
1329
+ *
1330
+ * @param {{platform: string, name: string, path: string, title?: string,
1331
+ * template?: string, overwrite?: boolean}} args
1332
+ * @returns {Promise<object>} the same JSON shape createProject's MCP
1333
+ * handler returns: {path, platform, template, files, sourceFile,
1334
+ * toolchain, nextStep}.
1335
+ */
1336
+ export async function createProjectImpl({ platform, name, path: projPath, title, template, overwrite = false, withSnippets = false }) {
1337
+ const fs = await import("node:fs/promises");
1338
+ const path = await import("node:path");
1339
+ const { fileURLToPath } = await import("node:url");
1340
+
1341
+ const __filename = fileURLToPath(import.meta.url);
1342
+ const __dirname = path.dirname(__filename);
1343
+ const REPO_ROOT = path.resolve(__dirname, "..", "..", "..");
1344
+ // R37 (revisited): gbc gets its own tree now — color-aware scaffolds,
1345
+ // GBC-specific docs, distinct examples/gbc/templates/ + src/platforms/
1346
+ // gbc/lib/c/. Same Z80 + APU + most VRAM layout as GB, but BCPS/BCPD
1347
+ // palette setup and visibly colorful tile art make the difference.
1348
+ const EXAMPLES_DIR = path.join(REPO_ROOT, "examples", platform);
1349
+ const PLATFORM_LIB_DIR = path.join(REPO_ROOT, "src", "platforms", platform);
1350
+ const CC65_PRESETS_DIR = path.join(REPO_ROOT, "src", "toolchains", "cc65");
1351
+
1352
+ const hasTemplates = !!TEMPLATES[platform];
1353
+ const isSimple = !!SIMPLE_STARTERS[platform];
1354
+ if (!hasTemplates && !isSimple) {
1355
+ throw new Error(`createProject doesn't yet support platform '${platform}'. Supported: ${[...Object.keys(TEMPLATES), ...Object.keys(SIMPLE_STARTERS)].sort().join(", ")}`);
1356
+ }
1357
+
1358
+ /** @type {any} */
1359
+ let tmpl = null;
1360
+ let mainFilename;
1361
+ let lang;
1362
+ if (hasTemplates) {
1363
+ const tname = template ?? "default";
1364
+ tmpl = TEMPLATES[platform][tname];
1365
+ if (!tmpl) {
1366
+ throw new Error(`Unknown template '${tname}' for platform '${platform}'. Available: ${Object.keys(TEMPLATES[platform]).join(", ")}`);
1367
+ }
1368
+ const mainExt = path.extname(tmpl.main);
1369
+ mainFilename = `main${mainExt}`;
1370
+ lang = tmpl.lang;
1371
+ } else {
1372
+ if (template) {
1373
+ throw new Error(`Platform '${platform}' has no template variants. Drop the template parameter.`);
1374
+ }
1375
+ mainFilename = SIMPLE_STARTERS[platform].filename;
1376
+ lang = SIMPLE_STARTERS[platform].lang;
1377
+ }
1378
+
1379
+ try {
1380
+ const entries = await fs.readdir(projPath);
1381
+ if (entries.length > 0 && !overwrite) {
1382
+ throw new Error(`destination '${projPath}' is not empty. Pass overwrite:true to write anyway.`);
1383
+ }
1384
+ } catch (e) {
1385
+ if (e.code !== "ENOENT") throw e;
1386
+ }
1387
+ await fs.mkdir(projPath, { recursive: true });
1388
+
1389
+ const writtenFiles = [];
1390
+ const mainSrcPath = path.join(EXAMPLES_DIR, hasTemplates ? tmpl.main : mainFilename);
1391
+ const mainContents = await fs.readFile(mainSrcPath, "utf-8");
1392
+ await fs.writeFile(path.join(projPath, mainFilename), mainContents, "utf-8");
1393
+ writtenFiles.push(mainFilename);
1394
+
1395
+ if (tmpl?.runtime) {
1396
+ for (const { src, dst } of tmpl.runtime) {
1397
+ // Detect binary archive files (.a, .o, .bin, .obj) — read as raw bytes,
1398
+ // not utf-8. SGDK's libmd.a is 2.6 MB of m68k object archive that
1399
+ // utf-8 would mangle on copy.
1400
+ const srcPath = path.join(PLATFORM_LIB_DIR, src);
1401
+ const isBinary = /\.(a|o|obj|bin|pic|pal|lib|xgc|xgm|vgm|brr)$/i.test(src);
1402
+ const contents = await fs.readFile(srcPath, isBinary ? null : "utf-8");
1403
+ await fs.writeFile(path.join(projPath, dst), contents);
1404
+ writtenFiles.push(dst);
1405
+ }
1406
+ }
1407
+
1408
+ // R20 stage 3: runtimeDirs recursively copies a whole directory tree
1409
+ // (used by the SGDK Genesis template to ship the include/ header tree).
1410
+ if (tmpl?.runtimeDirs) {
1411
+ for (const { src, dst } of tmpl.runtimeDirs) {
1412
+ const srcDir = path.join(PLATFORM_LIB_DIR, src);
1413
+ const dstDir = path.join(projPath, dst);
1414
+ await copyDirRecursive(fs, path, srcDir, dstDir, writtenFiles, dst);
1415
+ }
1416
+ }
1417
+
1418
+ // R58b: auto-vendor cc65 platform libsrc when present. Cheap blanket
1419
+ // policy — every cc65-using platform gets `vendor/cc65/libsrc/<p>/`
1420
+ // dropped into the project unless the template already wired it via
1421
+ // runtimeDirs. The TGI driver, joystick driver, conio, sound engine,
1422
+ // crt0 — all the things an agent would otherwise have to file a
1423
+ // feedback round to debug — now live in their project tree, greppable.
1424
+ // Lynx already wires this via LYNX_VENDOR_DIRS, so the skip-if-present
1425
+ // check below avoids double-copying for it.
1426
+ const cc65SrcDir = path.join(PLATFORM_LIB_DIR, "lib", "cc65-src");
1427
+ const cc65SrcDst = path.join(projPath, "vendor", "cc65", "libsrc", platform);
1428
+ try {
1429
+ await fs.stat(cc65SrcDir); // throws if missing — fine, skip
1430
+ try {
1431
+ await fs.stat(cc65SrcDst); // already copied by an explicit runtimeDir? skip
1432
+ } catch {
1433
+ await copyDirRecursive(fs, path, cc65SrcDir, cc65SrcDst, writtenFiles, `vendor/cc65/libsrc/${platform}`);
1434
+ }
1435
+ } catch {
1436
+ /* no cc65-src for this platform — fine */
1437
+ }
1438
+
1439
+ // R19b: extraSources are additional files from EXAMPLES_DIR (typically
1440
+ // sibling .asm/.s files that the template's main.c references — like a
1441
+ // data.asm providing tilfont/palfont symbols for the SNES C starter).
1442
+ // Distinct from `runtime` (which sources from PLATFORM_LIB_DIR).
1443
+ if (tmpl?.extraSources) {
1444
+ for (const { src, dst } of tmpl.extraSources) {
1445
+ const contents = await fs.readFile(path.join(EXAMPLES_DIR, src), "utf-8");
1446
+ await fs.writeFile(path.join(projPath, dst), contents, "utf-8");
1447
+ writtenFiles.push(dst);
1448
+ }
1449
+ }
1450
+
1451
+ if (tmpl?.crt0) {
1452
+ const srcPath = tmpl.crt0.presetSrc.startsWith("presets/")
1453
+ ? path.join(CC65_PRESETS_DIR, tmpl.crt0.presetSrc)
1454
+ : path.join(PLATFORM_LIB_DIR, tmpl.crt0.presetSrc);
1455
+ const contents = await fs.readFile(srcPath, "utf-8");
1456
+ await fs.writeFile(path.join(projPath, tmpl.crt0.dst), contents, "utf-8");
1457
+ writtenFiles.push(tmpl.crt0.dst);
1458
+ }
1459
+
1460
+ if (tmpl?.linkerConfig) {
1461
+ const srcPath = path.join(CC65_PRESETS_DIR, tmpl.linkerConfig.presetSrc);
1462
+ const contents = await fs.readFile(srcPath, "utf-8");
1463
+ await fs.writeFile(path.join(projPath, tmpl.linkerConfig.dst), contents, "utf-8");
1464
+ writtenFiles.push(tmpl.linkerConfig.dst);
1465
+ }
1466
+
1467
+ // R22: ship MENTAL_MODEL.md + TROUBLESHOOTING.md from src/platforms/
1468
+ // <LIB_PLATFORM>/ into the project tree when they exist. Without this
1469
+ // copy, template comments like "see TROUBLESHOOTING.md" point at a
1470
+ // file the user can't find — they'd have to call getPlatformDoc.
1471
+ // Putting the files alongside the source makes the project a true
1472
+ // self-contained build (you can grep MENTAL_MODEL right next to main.c).
1473
+ for (const docFile of ["MENTAL_MODEL.md", "TROUBLESHOOTING.md"]) {
1474
+ const srcDocPath = path.join(PLATFORM_LIB_DIR, docFile);
1475
+ try {
1476
+ const docContents = await fs.readFile(srcDocPath, "utf-8");
1477
+ await fs.writeFile(path.join(projPath, docFile), docContents, "utf-8");
1478
+ writtenFiles.push(docFile);
1479
+ } catch (e) {
1480
+ if (e.code !== "ENOENT") throw e;
1481
+ /* doc not shipped for this platform — skip */
1482
+ }
1483
+ }
1484
+
1485
+ // README + .gitignore generation lives in the MCP handler for now;
1486
+ // both create* tools want the README content, so we duplicate the
1487
+ // small string-building bit here. To keep the diff tight we replicate
1488
+ // it; if we add a third caller we'll factor it out further.
1489
+ const romExt = pickRomExt(platform);
1490
+ const isCc65 = lang.startsWith("C (cc65)") || lang.startsWith("C (cc65 ");
1491
+ const isSdccSm83 = platform === "gb" || platform === "gbc";
1492
+ const isSdccZ80 = platform === "sms" || platform === "gg";
1493
+
1494
+ const c89Note = (isCc65 || isSdccSm83 || isSdccZ80)
1495
+ ? `## ⚠️ ${isCc65 ? "cc65" : "SDCC"} is C89
1496
+
1497
+ Compiles **C89**, not C99/C11. Stick to:
1498
+ - Declare loop variables at the top of blocks: \`uint8_t i; for (i = 0; ...) { ... }\`.
1499
+ - All declarations at the top of every block — no mixed declarations + code.
1500
+ - No designated initializers, no compound literals, no \`//\` line comments in some places.
1501
+
1502
+ `
1503
+ : "";
1504
+ const runtimeHeaders = (tmpl?.runtime ?? []).filter((r) => /\.h$/i.test(r.dst));
1505
+ const runtimeAsmIncludes = (tmpl?.runtime ?? []).filter((r) => /\.(s|asm)$/i.test(r.dst));
1506
+
1507
+ let buildBlock;
1508
+ if (tmpl?.linkerConfig) {
1509
+ // NES (cc65 / chr-ram-runtime preset). Build dynamic sourcesPaths so
1510
+ // templates that ship extra .s files (e.g. music_demo with FamiTone2)
1511
+ // get them listed too.
1512
+ const runtimeNonHeaders = (tmpl?.runtime ?? [])
1513
+ .filter((r) => /\.(c|s|asm)$/i.test(r.dst));
1514
+ const srcLines = [
1515
+ ` "main.c": "${mainFilename}",`,
1516
+ ...runtimeNonHeaders.map((r) => ` "${r.dst}": "${r.dst}",`),
1517
+ ` "_preset_crt0.s": "${tmpl.crt0.dst}",`,
1518
+ ].join("\n");
1519
+ const incLines = runtimeHeaders.length > 0
1520
+ ? runtimeHeaders.map((h) => ` "${h.dst}": "${h.dst}",`).join("\n")
1521
+ : "";
1522
+ buildBlock = "```js\nrunSource({\n platform: \"" + platform + "\",\n sourcesPaths: {\n" + srcLines + "\n },\n" + (incLines ? " includePaths: {\n" + incLines + "\n },\n" : "") + " linkerConfig: /* contents of " + tmpl.linkerConfig.dst + " */,\n frames: 60,\n})\n```";
1523
+ } else if (isSdccSm83) {
1524
+ // GB / GBC (SDCC sm83). runSource BUILDS + RUNS + SCREENSHOTS in one
1525
+ // call AND auto-fixes the cartridge header (Nintendo logo, header +
1526
+ // global checksums, CGB flag on .gbc) — no manual patchGbHeader step.
1527
+ // Derive sources/includes from the template's runtime list so extra
1528
+ // .c files (e.g. music_demo's hUGEDriver) are listed too.
1529
+ const runtimeCs = (tmpl?.runtime ?? []).filter((r) => /\.c$/i.test(r.dst));
1530
+ const srcLines = [` "main.c": "${mainFilename}",`]
1531
+ .concat(runtimeCs.map((r) => ` "${r.dst}": "${r.dst}",`))
1532
+ .join("\n");
1533
+ const incLines = runtimeHeaders.length > 0
1534
+ ? runtimeHeaders.map((h) => ` "${h.dst}": "${h.dst}",`).join("\n")
1535
+ : "";
1536
+ buildBlock =
1537
+ "```js\nrunSource({\n" +
1538
+ " platform: \"" + platform + "\",\n" +
1539
+ " sourcesPaths: {\n" + srcLines + "\n },\n" +
1540
+ (incLines ? " includePaths: {\n" + incLines + "\n },\n" : "") +
1541
+ " crt0Path: \"gb_crt0.s\",\n" +
1542
+ " codeLoc: 0x150,\n" +
1543
+ " frames: 60,\n" +
1544
+ "})\n```\n\n" +
1545
+ "`runSource` auto-fixes the GB/GBC cartridge header (logo, checksums, " +
1546
+ "CGB flag) — you do **not** call `patchGbHeader` for a freshly built " +
1547
+ "ROM. Use `patchGbHeader` only to fix up an existing/external ROM on " +
1548
+ "disk or to override header fields (title, cart type, ROM/RAM size).";
1549
+ } else if (isSdccZ80) {
1550
+ const inc = runtimeHeaders.length > 0
1551
+ ? `\n includePaths: { ${runtimeHeaders.map((h) => `"${h.dst}": "${h.dst}"`).join(", ")} },`
1552
+ : "";
1553
+ buildBlock = "```js\nrunSource({\n platform: \"" + platform + "\",\n sourcePath: \"" + mainFilename + "\"," + inc + "\n frames: 60,\n})\n```";
1554
+ } else if (platform === "c64") {
1555
+ const inc = runtimeHeaders.length > 0
1556
+ ? `\n includePaths: { ${runtimeHeaders.map((h) => `"${h.dst}": "${h.dst}"`).join(", ")} },`
1557
+ : "";
1558
+ buildBlock = "```js\nrunSource({\n platform: \"c64\",\n sourcePath: \"" + mainFilename + "\"," + inc + "\n frames: 60,\n})\n```";
1559
+ } else if (platform === "snes" && /\.c$/i.test(mainFilename)) {
1560
+ // R19b: SNES C-mode template (PVSnesLib runtime auto-linked). Multi-file
1561
+ // build with sibling .asm providing data symbols (tilfont/palfont).
1562
+ //
1563
+ // SFX-enabled scaffolds (shmup/platformer/puzzle/etc.) also ship the
1564
+ // SPC700 driver via SNES_SFX_RUNTIME. Those files split across THREE
1565
+ // build args, and getting the split wrong is the documented footgun:
1566
+ // - snes_sfx_data.asm → a SOURCE (it .incbin's the apu blob; the build
1567
+ // fails with unresolved `apu_blob_end` if it's missing)
1568
+ // - apu_blob.bin → a BINARY include (the .incbin'd payload)
1569
+ // - snes_sfx.h, snes_sfx.c → includePaths; main.c does
1570
+ // `#include "snes_sfx.c"`, so it is NOT a separately compiled source.
1571
+ // The remaining SNES_SFX_RUNTIME files (spc_driver.asm, apu_blob.asm,
1572
+ // *.brr, sample_bank.bin) are rebuild-only — not needed for the build.
1573
+ const rt = tmpl?.runtime ?? [];
1574
+ const has = (dst) => rt.some((r) => r.dst === dst);
1575
+ const sfxSourceAsm = has("snes_sfx_data.asm") ? ["snes_sfx_data.asm"] : [];
1576
+ const sfxIncludes = rt
1577
+ .filter((r) => r.dst === "snes_sfx.h" || r.dst === "snes_sfx.c")
1578
+ .map((r) => r.dst);
1579
+ const sfxBinary = has("apu_blob.bin") ? ["apu_blob.bin"] : [];
1580
+
1581
+ const sourceNames = [mainFilename]
1582
+ .concat((tmpl?.extraSources ?? []).map((e) => e.dst))
1583
+ .concat(sfxSourceAsm);
1584
+ const sourceLines = sourceNames
1585
+ .map((n) => ` "${n}": "${n}",`)
1586
+ .join("\n");
1587
+ const incLines = sfxIncludes
1588
+ .map((n) => ` "${n}": "${n}",`)
1589
+ .join("\n");
1590
+ const binLines = sfxBinary
1591
+ .map((n) => ` "${n}": "${n}",`)
1592
+ .join("\n");
1593
+
1594
+ buildBlock =
1595
+ "```js\nrunSource({\n" +
1596
+ " platform: \"snes\",\n" +
1597
+ " language: \"c\",\n" +
1598
+ " sourcesPaths: {\n" + sourceLines + "\n },\n" +
1599
+ (incLines ? " includePaths: {\n" + incLines + "\n },\n" : "") +
1600
+ (binLines ? " binaryIncludePaths: {\n" + binLines + "\n },\n" : "") +
1601
+ " frames: 120,\n" +
1602
+ "})\n```\n\n" +
1603
+ "PVSnesLib's runtime (crt0_snes, libm, libtcc, libc) is auto-linked. " +
1604
+ "`#include <snes.h>` works out of the box — consoleDrawText, setMode, " +
1605
+ "WaitForVBlank, etc." +
1606
+ (sfxSourceAsm.length
1607
+ ? " The SPC700 sound files are split across the three args above on " +
1608
+ "purpose: `snes_sfx_data.asm` is a SOURCE, `apu_blob.bin` is a " +
1609
+ "binary include, and `snes_sfx.{h,c}` are includes (main.c does " +
1610
+ "`#include \"snes_sfx.c\"`). Omit any one and the build fails."
1611
+ : "");
1612
+ } else if (platform === "snes" || platform === "genesis") {
1613
+ // R30: Genesis SGDK templates ship genesis_sfx.{h,c} as runtime helpers.
1614
+ // If the template's runtime list includes .c files, emit a multi-file
1615
+ // sourcesPaths block; otherwise stick with the single-source form.
1616
+ const runtimeCs = (tmpl?.runtime ?? []).filter((r) => /\.c$/i.test(r.dst));
1617
+ if (runtimeCs.length > 0 && /\.c$/i.test(mainFilename)) {
1618
+ const runtimeHs = (tmpl?.runtime ?? []).filter((r) => /\.h$/i.test(r.dst));
1619
+ const srcLines = [` "${mainFilename}": "${mainFilename}",`]
1620
+ .concat(runtimeCs.map((r) => ` "${r.dst}": "${r.dst}",`))
1621
+ .join("\n");
1622
+ const incLine = runtimeHs.length > 0
1623
+ ? `\n includePaths: {\n${runtimeHs.map((r) => ` "${r.dst}": "${r.dst}",`).join("\n")}\n },`
1624
+ : "";
1625
+ buildBlock = "```js\nrunSource({\n platform: \"" + platform + "\",\n language: \"c\",\n sourcesPaths: {\n" + srcLines + "\n }," + incLine + "\n frames: 60,\n})\n```";
1626
+ } else {
1627
+ const inc = runtimeAsmIncludes.length > 0
1628
+ ? `\n includePaths: { ${runtimeAsmIncludes.map((r) => `"${r.dst}": "${r.dst}"`).join(", ")} },`
1629
+ : "";
1630
+ buildBlock = "```js\nrunSource({\n platform: \"" + platform + "\",\n sourcePath: \"" + mainFilename + "\"," + inc + "\n frames: 60,\n})\n```";
1631
+ }
1632
+ } else if (platform === "gba") {
1633
+ // GBA libtonc / libgba runtimes ship gba_sfx.{h,c} as a tiny DMG-APU
1634
+ // wrapper. Surface multi-file build: main.c + any runtime .c, with
1635
+ // runtime .h files in includePaths.
1636
+ const runtimeCs = (tmpl?.runtime ?? []).filter((r) => /\.c$/i.test(r.dst));
1637
+ const runtimeHs = (tmpl?.runtime ?? []).filter((r) => /\.h$/i.test(r.dst));
1638
+ if (runtimeCs.length > 0) {
1639
+ const srcLines = [` "${mainFilename}": "${mainFilename}",`]
1640
+ .concat(runtimeCs.map((r) => ` "${r.dst}": "${r.dst}",`))
1641
+ .join("\n");
1642
+ const incLine = runtimeHs.length > 0
1643
+ ? `\n includePaths: {\n${runtimeHs.map((r) => ` "${r.dst}": "${r.dst}",`).join("\n")}\n },`
1644
+ : "";
1645
+ buildBlock = "```js\nrunSource({\n platform: \"gba\",\n language: \"c\",\n sourcesPaths: {\n" + srcLines + "\n }," + incLine + "\n frames: 60,\n})\n```";
1646
+ } else {
1647
+ buildBlock = "```js\nrunSource({ platform: \"gba\", language: \"c\", sourcePath: \"" + mainFilename + "\", frames: 60 })\n```";
1648
+ }
1649
+ } else {
1650
+ buildBlock = "```js\nrunSource({ platform: \"" + platform + "\", sourcePath: \"" + mainFilename + "\", frames: 60 })\n```";
1651
+ }
1652
+
1653
+ let filesSection = `## Files\n\n- \`${mainFilename}\` — your game's entry point.\n`;
1654
+ if (tmpl?.runtime) {
1655
+ for (const { dst } of tmpl.runtime) {
1656
+ filesSection += `- \`${dst}\` — runtime helper. **You own this** — edit or replace at will.\n`;
1657
+ }
1658
+ }
1659
+ if (tmpl?.crt0) {
1660
+ filesSection += `- \`${tmpl.crt0.dst}\` — startup code (reset vector, NMI handler, hardware vectors). **You own this.**\n`;
1661
+ }
1662
+ if (tmpl?.linkerConfig) {
1663
+ filesSection += `- \`${tmpl.linkerConfig.dst}\` — ld65 linker config (memory layout, segment placement). **You own this.**\n`;
1664
+ }
1665
+ filesSection += `\nEvery byte that compiles into your ROM is in this directory. If you move the repo somewhere else, you don't need to install anything from romdev to rebuild it — the compiler binaries are the only external dependency.\n\n`;
1666
+
1667
+ const readme = `# ${title ?? name}\n\nA ${lang} project for ${platform}, scaffolded by romdev.\n\n${tmpl?.describe ? tmpl.describe + "\n\n" : ""}${filesSection}${c89Note}## Build + run with romdev\n\n${buildBlock}\n\n## Iterating\n\n- Edit \`${mainFilename}\` (or any of the runtime / crt0 / cfg files — they're yours).\n- Call \`runSource\` to see your changes. It builds + loads + runs + screenshots in one round trip.\n- Inspect at byte level: \`readMemory\`, \`inspectSprites\`, \`inspectPalette\`, \`inspectBackgroundMap({render:true})\`.\n- Open a playtest window for human eyes: \`loadCategory({category:"show"}); playtest({});\` — returns immediately, the window follows your rebuilds, and the emulator stays live for every other tool.\n`;
1668
+ await fs.writeFile(path.join(projPath, "README.md"), readme, "utf-8");
1669
+ writtenFiles.push("README.md");
1670
+
1671
+ const gitignore = `# Build outputs\n*${romExt}\n*.o\n*.rel\n*.ihx\n*.lst\n*.map\n*.sym\n*.dbg\n\n# Editor\n.vscode/\n.idea/\n*.swp\n.DS_Store\n`;
1672
+ await fs.writeFile(path.join(projPath, ".gitignore"), gitignore, "utf-8");
1673
+ writtenFiles.push(".gitignore");
1674
+
1675
+ // withSnippets: drop every vetted starter snippet for the platform
1676
+ // into the project dir alongside main.c. Replaces "createProject +
1677
+ // call getAllStarterSnippets + paste 11 files" with one shot.
1678
+ // Snippets that overlap with files we've already written (the
1679
+ // runtime tmpl.runtime list typically includes them) are skipped.
1680
+ const snippetFiles = [];
1681
+ if (withSnippets) {
1682
+ const { listSnippetsForPlatform } = await import("./snippets.js").catch(() => ({}));
1683
+ // Inline minimal duplicate of listSnippetsForPlatform since snippets.js
1684
+ // doesn't export it. Keep this in sync with snippets.js.
1685
+ const LIB_DIR = path.join(PLATFORM_LIB_DIR, "lib");
1686
+ let entries = [];
1687
+ try { entries = await fs.readdir(LIB_DIR); } catch { /* no lib/ */ }
1688
+ const written = new Set(writtenFiles);
1689
+ /** @type {Array<{srcPath: string, dst: string, language: string}>} */
1690
+ const candidates = [];
1691
+ for (const entry of entries.sort()) {
1692
+ if (entry.startsWith(".") || entry === "README.md") continue;
1693
+ const entryPath = path.join(LIB_DIR, entry);
1694
+ let s;
1695
+ try { s = await fs.stat(entryPath); } catch { continue; }
1696
+ if (s.isDirectory()) {
1697
+ const sub = await fs.readdir(entryPath).catch(() => []);
1698
+ for (const f of sub.sort()) {
1699
+ if (f.startsWith(".") || f === "README.md") continue;
1700
+ candidates.push({ srcPath: path.join(entryPath, f), dst: f, language: entry });
1701
+ }
1702
+ } else {
1703
+ const ext = path.extname(entry).toLowerCase();
1704
+ const lang = (ext === ".c" || ext === ".h") ? "c" : "asm";
1705
+ candidates.push({ srcPath: entryPath, dst: entry, language: lang });
1706
+ }
1707
+ }
1708
+ // For platforms that have a `lang` like "C (SDCC z80)" filter to C
1709
+ // snippets; for asm-only platforms fall through and ship both.
1710
+ const wantsC = /\bC\b/i.test(lang);
1711
+ const wantsAsm = /\b(asm|sdcc|dasm)\b/i.test(lang); // best-effort
1712
+ const filtered = candidates.filter((c) => {
1713
+ if (c.language === "c") return wantsC || !wantsAsm;
1714
+ if (c.language === "asm") return wantsAsm || !wantsC;
1715
+ return true;
1716
+ });
1717
+ for (const c of filtered) {
1718
+ if (written.has(c.dst)) continue; // already written by tmpl.runtime
1719
+ // Binary detection — same heuristic as the runtime copy above.
1720
+ const isBinary = /\.(a|o|obj|bin|pic|pal|lib|xgc|xgm|vgm|brr)$/i.test(c.dst);
1721
+ const contents = await fs.readFile(c.srcPath, isBinary ? null : "utf-8");
1722
+ await fs.writeFile(path.join(projPath, c.dst), contents);
1723
+ writtenFiles.push(c.dst);
1724
+ snippetFiles.push(c.dst);
1725
+ }
1726
+ }
1727
+
1728
+ return {
1729
+ path: projPath,
1730
+ platform,
1731
+ template: hasTemplates ? (template ?? "default") : null,
1732
+ files: writtenFiles,
1733
+ snippetsCopied: withSnippets ? snippetFiles : null,
1734
+ sourceFile: path.join(projPath, mainFilename),
1735
+ toolchain: lang,
1736
+ nextStep: `Edit ${path.join(projPath, mainFilename)} and call runSource with sourcesPaths/includePaths pointing at the project's files. Everything you need is in the directory — nothing is hidden.`,
1737
+ };
1738
+ }
1739
+
1740
+ export function registerProjectTools(server, z) {
1741
+ server.tool(
1742
+ "createProject",
1743
+ "Use this to scaffold a new homebrew project directory: writes a starter main source + every runtime " +
1744
+ "file the template needs (headers, crt0, linker .cfg) + README + .gitignore. The result is " +
1745
+ "SELF-CONTAINED — every byte that compiles is in the dir, so it rebuilds with stock cc65/sdcc " +
1746
+ "elsewhere with nothing else. `template` defaults to the platform's smallest visible-and-runnable " +
1747
+ "program; most platforms also have hello_sprite/tile_engine + the genre templates (call listPlatforms " +
1748
+ "to see each platform's set). `withSnippets:true` also drops every vetted starter snippet alongside " +
1749
+ "main. (For a complete genre-shaped game baseline, prefer createGame.)",
1750
+ {
1751
+ platform: z.string().describe("Platform id: nes, c64, gb, gbc, sms, gg, atari2600, atari7800, lynx, snes, genesis, gba."),
1752
+ name: z.string().min(1).describe("Project name (used for output binary)."),
1753
+ path: z.string().describe("Absolute path where the project directory will be created."),
1754
+ title: z.string().optional().describe("Optional human-readable title shown in the README."),
1755
+ template: z.string().optional().describe("Template id. NES/GB/GBC: 'default' | 'hello_sprite' | 'tile_engine'. Other platforms with templates only have 'default' — omit this arg. Default is 'default'."),
1756
+ overwrite: z.boolean().default(false).describe("If true, allow writing into an existing non-empty directory."),
1757
+ withSnippets: z.boolean().default(false).describe("If true, also drop every vetted starter snippet for this platform into the project dir alongside main.c. Equivalent to calling copyStarterSnippets after createProject — saves a round trip when you want main.c + every helper without picking a genre template. Snippets that overlap with files the template's runtime already wrote are skipped."),
1758
+ },
1759
+ safeTool(async (args) => jsonContent(await createProjectImpl(args))),
1760
+ );
1761
+
1762
+ // ── createGame — v2 genre-shaped scaffold ─────────────────────────
1763
+ // Thin wrapper over createProjectImpl that takes a `genre` instead of
1764
+ // a `template`. Each genre maps to a corresponding template under
1765
+ // examples/<platform>/ and ships a known-good complete game baseline:
1766
+ // main loop, NMI, OAM init, gameplay slot, music driver wiring. The
1767
+ // agent fills in gameplay-specific logic on top.
1768
+ //
1769
+ // R21: NES + GB/GBC + SNES + Genesis with three genres each (shmup,
1770
+ // platformer, puzzle). Per-platform extension follows demand. Recipes
1771
+ // for other platforms can be added by registering an entry in the
1772
+ // GENRE_MAP below and shipping matching template files under
1773
+ // examples/<platform>/templates/.
1774
+ server.tool(
1775
+ "createGame",
1776
+ "Scaffold a genre-shaped game project. Higher-level than createProject — " +
1777
+ "picks the right template + runtime + crt0 + linker config for the genre. " +
1778
+ "Available genres on every supported platform: 'shmup' (vertical shooter), " +
1779
+ "'platformer' (side-scrolling + gravity, except NES which is single-screen), " +
1780
+ "'puzzle' (match-3 falling blocks), " +
1781
+ "'sports' (Pong — two controllers wired where the hardware supports it, " +
1782
+ "player-vs-AI on GB/GBC), 'racing' (3-lane top-down lane-switch dodge). " +
1783
+ "Supported platforms: nes, gb, gbc, snes, genesis, sms, gg, c64, gba, lynx, atari7800. " +
1784
+ "Each scaffolds a complete working ROM you can build + run + screenshot " +
1785
+ "in one round trip — fill in gameplay-specific logic on top of the " +
1786
+ "known-good baseline.",
1787
+ {
1788
+ platform: z.string().describe("Platform id. Today: 'nes' | 'gb' | 'gbc' | 'snes' | 'genesis' | 'sms' | 'gg' | 'c64' | 'gba' | 'lynx' | 'atari7800'."),
1789
+ genre: z.string().describe("Genre id: 'shmup' | 'platformer' | 'puzzle' | 'sports' | 'racing' — all five available on every supported platform."),
1790
+ name: z.string().min(1).describe("Project name (used for output binary)."),
1791
+ path: z.string().describe("Absolute path where the project directory will be created."),
1792
+ title: z.string().optional().describe("Optional human-readable title shown in the README."),
1793
+ overwrite: z.boolean().default(false).describe("If true, allow writing into an existing non-empty directory."),
1794
+ },
1795
+ safeTool(async ({ platform, genre, name, path: projPath, title, overwrite }) => {
1796
+ // The five canonical genres. A genre is available on a platform iff
1797
+ // TEMPLATES[platform] has a matching template entry — we DERIVE
1798
+ // availability from TEMPLATES rather than maintain a parallel table,
1799
+ // so createGame can never drift out of sync with the registered
1800
+ // templates (R61: the old hardcoded GENRE_MAP did exactly that — it
1801
+ // omitted c64/gba/lynx even though their genre templates were registered).
1802
+ //
1803
+ // R23 + R23e note: GB / GBC have no native 2P hardware (no second
1804
+ // controller port; the link cable would need custom serial code),
1805
+ // so their `sports` template is player-vs-AI. Everywhere else port 1
1806
+ // is a real second pad with AI fallback when none is plugged in.
1807
+ const CANONICAL_GENRES = ["shmup", "platformer", "puzzle", "sports", "racing"];
1808
+ const platformTemplates = TEMPLATES[platform];
1809
+ // Platforms that ship genre scaffolds = those whose TEMPLATES entry
1810
+ // has at least one canonical genre key.
1811
+ const genrePlatforms = Object.keys(TEMPLATES).filter((p) =>
1812
+ CANONICAL_GENRES.some((g) => TEMPLATES[p] && TEMPLATES[p][g])
1813
+ );
1814
+ const availableGenres = platformTemplates
1815
+ ? CANONICAL_GENRES.filter((g) => platformTemplates[g])
1816
+ : [];
1817
+ if (availableGenres.length === 0) {
1818
+ throw new Error(
1819
+ `createGame: no genre scaffolds for platform '${platform}' yet. ` +
1820
+ `Supported platforms: ${genrePlatforms.join(", ") || "(none)"}. ` +
1821
+ `For other platforms, use createProject({platform, template:"default"}) and build up from there.`
1822
+ );
1823
+ }
1824
+ if (!availableGenres.includes(genre)) {
1825
+ throw new Error(
1826
+ `createGame: genre '${genre}' not supported for platform '${platform}'. ` +
1827
+ `Available genres: ${availableGenres.join(", ")}.`
1828
+ );
1829
+ }
1830
+ // Genre id IS the template id (they're 1:1 by construction).
1831
+ const templateId = genre;
1832
+ const result = await createProjectImpl({
1833
+ platform, template: templateId, name, path: projPath, title, overwrite,
1834
+ });
1835
+ return jsonContent({ ...result, genre, template: templateId });
1836
+ }),
1837
+ );
1838
+
1839
+ server.tool(
1840
+ "patchGbHeader",
1841
+ "Use this to write a complete, valid GB/GBC cartridge header into a ROM: Nintendo boot logo, EVERY " +
1842
+ "header byte ($0134-$014C — title, CGB flag, cart type, ROM/RAM size, etc.) with ROM-only defaults, " +
1843
+ "plus the header + global checksums. SDCC-path equivalent of `rgbfix -v -p 0`. Fills ALL bytes " +
1844
+ "deliberately: leaving the CGB flag as the linker's $FF pad makes gambatte enter CGB mode and ignore " +
1845
+ "DMG palette writes → white screen. Also shipped as `patch-header.js` in every GB/GBC project for use " +
1846
+ "outside MCP.",
1847
+ {
1848
+ path: z.string().describe("Absolute path to the .gb / .gbc ROM file. Patched in place unless outputPath is given."),
1849
+ outputPath: z.string().optional().describe("If given, write the patched ROM here instead of overwriting."),
1850
+ cgb: z.boolean().optional().describe("If true, sets the CGB flag at $0143 to $80 (CGB-aware + DMG-compatible). If omitted, auto-detects from .gbc extension; default for plain .gb is false (DMG-only)."),
1851
+ title: z.string().optional().describe("Cartridge title, up to 11 chars at $0134..$013E. Uppercased + zero-padded. Default = zero-fill."),
1852
+ cartType: z.number().int().min(0).max(0xFF).optional().describe("Cart-type byte at $0147. Default $00 (ROM-only). Common alternatives: $01=MBC1, $03=MBC1+RAM+BAT, $11=MBC3, $13=MBC3+RAM+BAT, $19=MBC5."),
1853
+ romSize: z.number().int().min(0).max(0xFF).optional().describe("ROM-size byte at $0148. Default $00 (32 KB / 2 banks). 1=64KB, 2=128KB, 3=256KB, 4=512KB, 5=1MB, 6=2MB, 7=4MB."),
1854
+ ramSize: z.number().int().min(0).max(0xFF).optional().describe("RAM-size byte at $0149. Default $00 (none). $02=8KB, $03=32KB. Only meaningful with battery-backed MBC."),
1855
+ destination: z.number().int().min(0).max(0xFF).optional().describe("Destination at $014A. Default $01 (non-Japan). $00 = Japan."),
1856
+ },
1857
+ safeTool(async ({ path: inPath, outputPath, cgb, title, cartType, romSize, ramSize, destination }) => {
1858
+ const rom = new Uint8Array(await readFile(inPath));
1859
+ const cgbFlag = cgb ?? (/\.gbc$/i.test(inPath) || (outputPath && /\.gbc$/i.test(outputPath)));
1860
+ patchGbHeader(rom, { cgb: cgbFlag, title, cartType, romSize, ramSize, destination });
1861
+ const outPath = outputPath ?? inPath;
1862
+ await writeFile(outPath, rom);
1863
+ return jsonContent({
1864
+ path: outPath,
1865
+ bytes: rom.length,
1866
+ cgb: !!cgbFlag,
1867
+ patched: [
1868
+ "nintendo_logo@$0104..$0133",
1869
+ "title@$0134..$013E",
1870
+ `cgb_flag@$0143=${cgbFlag ? "$80" : "$00"}`,
1871
+ "licensee@$0144..$0145=$00$00",
1872
+ "sgb_flag@$0146=$00",
1873
+ `cart_type@$0147=$${(cartType ?? 0).toString(16).padStart(2, "0").toUpperCase()}`,
1874
+ `rom_size@$0148=$${(romSize ?? 0).toString(16).padStart(2, "0").toUpperCase()}`,
1875
+ `ram_size@$0149=$${(ramSize ?? 0).toString(16).padStart(2, "0").toUpperCase()}`,
1876
+ `destination@$014A=$${(destination ?? 1).toString(16).padStart(2, "0").toUpperCase()}`,
1877
+ "old_licensee@$014B=$33",
1878
+ "rom_version@$014C=$00",
1879
+ "header_checksum@$014D",
1880
+ "global_checksum@$014E..$014F",
1881
+ ],
1882
+ });
1883
+ }),
1884
+ );
1885
+ }