romdevtools 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1346) hide show
  1. package/AGENTS.md +1110 -0
  2. package/CHANGELOG.md +525 -0
  3. package/LICENSE +45 -0
  4. package/NOTICE +102 -0
  5. package/README.md +84 -0
  6. package/examples/README.md +36 -0
  7. package/examples/art-first-workflow/README.md +209 -0
  8. package/examples/atari2600/main.asm +143 -0
  9. package/examples/atari2600/templates/default.asm +183 -0
  10. package/examples/atari2600/templates/mini_invaders.asm +381 -0
  11. package/examples/atari2600/templates/music_demo.asm +322 -0
  12. package/examples/atari2600/templates/paddle.asm +345 -0
  13. package/examples/atari2600/templates/single_screen.asm +242 -0
  14. package/examples/atari7800/main.c +88 -0
  15. package/examples/atari7800/templates/default.c +183 -0
  16. package/examples/atari7800/templates/hello_sprite.c +141 -0
  17. package/examples/atari7800/templates/music_demo.c +123 -0
  18. package/examples/atari7800/templates/platformer.c +159 -0
  19. package/examples/atari7800/templates/puzzle.c +164 -0
  20. package/examples/atari7800/templates/racing.c +139 -0
  21. package/examples/atari7800/templates/shmup.c +148 -0
  22. package/examples/atari7800/templates/sports.c +207 -0
  23. package/examples/c64/main.c +63 -0
  24. package/examples/c64/templates/hello_sprite.c +117 -0
  25. package/examples/c64/templates/music_demo.c +131 -0
  26. package/examples/c64/templates/platformer.c +194 -0
  27. package/examples/c64/templates/puzzle.c +178 -0
  28. package/examples/c64/templates/racing.c +140 -0
  29. package/examples/c64/templates/shmup.c +201 -0
  30. package/examples/c64/templates/sports.c +109 -0
  31. package/examples/c64/templates/tile_engine.c +174 -0
  32. package/examples/gb/main.asm +106 -0
  33. package/examples/gb/main.c +49 -0
  34. package/examples/gb/templates/default.c +58 -0
  35. package/examples/gb/templates/hello_sprite.c +130 -0
  36. package/examples/gb/templates/music_demo.c +52 -0
  37. package/examples/gb/templates/platformer.c +178 -0
  38. package/examples/gb/templates/puzzle.c +217 -0
  39. package/examples/gb/templates/racing.c +158 -0
  40. package/examples/gb/templates/shmup.c +172 -0
  41. package/examples/gb/templates/sports.c +136 -0
  42. package/examples/gb/templates/tile_engine.c +280 -0
  43. package/examples/gba/templates/gba_hello.c +64 -0
  44. package/examples/gba/templates/maxmod_demo.c +105 -0
  45. package/examples/gba/templates/platformer.c +215 -0
  46. package/examples/gba/templates/puzzle.c +237 -0
  47. package/examples/gba/templates/racing.c +175 -0
  48. package/examples/gba/templates/shmup.c +197 -0
  49. package/examples/gba/templates/sports.c +177 -0
  50. package/examples/gba/templates/tonc_hello.c +72 -0
  51. package/examples/gba/templates/tonc_hello_sprite.c +109 -0
  52. package/examples/gbc/main.asm +123 -0
  53. package/examples/gbc/templates/default.c +61 -0
  54. package/examples/gbc/templates/hello_sprite.c +140 -0
  55. package/examples/gbc/templates/music_demo.c +63 -0
  56. package/examples/gbc/templates/platformer.c +181 -0
  57. package/examples/gbc/templates/puzzle.c +217 -0
  58. package/examples/gbc/templates/racing.c +164 -0
  59. package/examples/gbc/templates/shmup.c +188 -0
  60. package/examples/gbc/templates/sports.c +142 -0
  61. package/examples/gbc/templates/tile_engine.c +280 -0
  62. package/examples/genesis/main.s +161 -0
  63. package/examples/genesis/templates/hello_sprite.c +75 -0
  64. package/examples/genesis/templates/platformer.c +166 -0
  65. package/examples/genesis/templates/puzzle.c +240 -0
  66. package/examples/genesis/templates/racing.c +170 -0
  67. package/examples/genesis/templates/sgdk_hello.c +41 -0
  68. package/examples/genesis/templates/shmup.c +188 -0
  69. package/examples/genesis/templates/shmup_2p.c +244 -0
  70. package/examples/genesis/templates/sports.c +172 -0
  71. package/examples/genesis/templates/tile_engine.c +135 -0
  72. package/examples/genesis/templates/xgm2_demo.c +53 -0
  73. package/examples/genesis/templates/xgm2_demo_data.s +27 -0
  74. package/examples/gg/main.c +10 -0
  75. package/examples/gg/templates/default.c +156 -0
  76. package/examples/gg/templates/hello_sprite.c +90 -0
  77. package/examples/gg/templates/music_demo.c +156 -0
  78. package/examples/gg/templates/platformer.c +220 -0
  79. package/examples/gg/templates/puzzle.c +204 -0
  80. package/examples/gg/templates/racing.c +161 -0
  81. package/examples/gg/templates/shmup.c +188 -0
  82. package/examples/gg/templates/sports.c +137 -0
  83. package/examples/gg/templates/tile_engine.c +137 -0
  84. package/examples/lynx/main.c +4 -0
  85. package/examples/lynx/templates/default.c +41 -0
  86. package/examples/lynx/templates/hello_sprite.c +39 -0
  87. package/examples/lynx/templates/music_demo.c +37 -0
  88. package/examples/lynx/templates/platformer.c +72 -0
  89. package/examples/lynx/templates/puzzle.c +142 -0
  90. package/examples/lynx/templates/racing.c +94 -0
  91. package/examples/lynx/templates/shmup.c +132 -0
  92. package/examples/lynx/templates/sports.c +59 -0
  93. package/examples/msx/catch_game/README.md +75 -0
  94. package/examples/msx/catch_game/_verify.mjs +93 -0
  95. package/examples/msx/catch_game/main.c +249 -0
  96. package/examples/msx/catch_game/shot_after_left.png +0 -0
  97. package/examples/msx/catch_game/shot_after_right.png +0 -0
  98. package/examples/msx/catch_game/shot_before.png +0 -0
  99. package/examples/msx/catch_game/shot_scored.png +0 -0
  100. package/examples/msx/music_sfx/README.md +38 -0
  101. package/examples/msx/music_sfx/main.c +164 -0
  102. package/examples/msx/sprite_move/README.md +44 -0
  103. package/examples/msx/sprite_move/main.c +100 -0
  104. package/examples/nes/main.c +143 -0
  105. package/examples/nes/space-shooter/README.md +69 -0
  106. package/examples/nes/space-shooter/main.c +441 -0
  107. package/examples/nes/space-shooter/nes_runtime.c +347 -0
  108. package/examples/nes/space-shooter/nes_runtime.h +141 -0
  109. package/examples/nes/templates/default.c +41 -0
  110. package/examples/nes/templates/hello_sprite.c +104 -0
  111. package/examples/nes/templates/music_demo.c +80 -0
  112. package/examples/nes/templates/platformer.c +171 -0
  113. package/examples/nes/templates/puzzle.c +232 -0
  114. package/examples/nes/templates/racing.c +203 -0
  115. package/examples/nes/templates/shmup.c +228 -0
  116. package/examples/nes/templates/sports.c +205 -0
  117. package/examples/nes/templates/tile_engine.c +224 -0
  118. package/examples/pce/catch_game/README.md +8 -0
  119. package/examples/pce/catch_game/_verify.mjs +75 -0
  120. package/examples/pce/catch_game/main.c +327 -0
  121. package/examples/pce/catch_game/shot_after.png +0 -0
  122. package/examples/pce/catch_game/shot_before.png +0 -0
  123. package/examples/pce/main.c +37 -0
  124. package/examples/pce/music_sfx/README.md +8 -0
  125. package/examples/pce/music_sfx/main.c +154 -0
  126. package/examples/pce/sprite_move/README.md +19 -0
  127. package/examples/pce/sprite_move/main.c +155 -0
  128. package/examples/porting-across-platforms/README.md +59 -0
  129. package/examples/sms/main.c +129 -0
  130. package/examples/sms/templates/default.c +110 -0
  131. package/examples/sms/templates/hello_sprite.c +90 -0
  132. package/examples/sms/templates/music_demo.c +151 -0
  133. package/examples/sms/templates/platformer.c +215 -0
  134. package/examples/sms/templates/puzzle.c +204 -0
  135. package/examples/sms/templates/racing.c +161 -0
  136. package/examples/sms/templates/shmup.c +167 -0
  137. package/examples/sms/templates/shmup_2p.c +219 -0
  138. package/examples/sms/templates/sports.c +147 -0
  139. package/examples/sms/templates/tile_engine.c +137 -0
  140. package/examples/snes/main.asm +70 -0
  141. package/examples/snes/templates/c-hello-data.asm +28 -0
  142. package/examples/snes/templates/c-hello.c +71 -0
  143. package/examples/snes/templates/default-data.asm +36 -0
  144. package/examples/snes/templates/default.c +74 -0
  145. package/examples/snes/templates/hello_sprite-data.asm +45 -0
  146. package/examples/snes/templates/hello_sprite.c +76 -0
  147. package/examples/snes/templates/music_demo-data.asm +20 -0
  148. package/examples/snes/templates/music_demo.c +83 -0
  149. package/examples/snes/templates/platformer-data.asm +27 -0
  150. package/examples/snes/templates/platformer.c +142 -0
  151. package/examples/snes/templates/puzzle-data.asm +14 -0
  152. package/examples/snes/templates/puzzle.c +199 -0
  153. package/examples/snes/templates/racing-data.asm +33 -0
  154. package/examples/snes/templates/racing.c +146 -0
  155. package/examples/snes/templates/shmup-data.asm +61 -0
  156. package/examples/snes/templates/shmup.c +199 -0
  157. package/examples/snes/templates/sports-data.asm +28 -0
  158. package/examples/snes/templates/sports.c +144 -0
  159. package/package.json +97 -0
  160. package/src/cheats/gamegenie.js +506 -0
  161. package/src/cheats/lookup.js +262 -0
  162. package/src/cheats/parse-cht.js +92 -0
  163. package/src/cli/smoke.js +283 -0
  164. package/src/cores/registry.js +99 -0
  165. package/src/cores/wasm/bluemsx_libretro.js +2 -0
  166. package/src/cores/wasm/bluemsx_libretro.wasm +0 -0
  167. package/src/cores/wasm/fceumm_libretro.js +2 -0
  168. package/src/cores/wasm/fceumm_libretro.wasm +0 -0
  169. package/src/cores/wasm/gambatte_libretro.js +2 -0
  170. package/src/cores/wasm/gambatte_libretro.wasm +0 -0
  171. package/src/cores/wasm/geargrafx_libretro.js +2 -0
  172. package/src/cores/wasm/geargrafx_libretro.wasm +0 -0
  173. package/src/cores/wasm/genesis_plus_gx_libretro.js +2 -0
  174. package/src/cores/wasm/genesis_plus_gx_libretro.wasm +0 -0
  175. package/src/cores/wasm/handy_libretro.js +2 -0
  176. package/src/cores/wasm/handy_libretro.wasm +0 -0
  177. package/src/cores/wasm/mgba_libretro.js +2 -0
  178. package/src/cores/wasm/mgba_libretro.wasm +0 -0
  179. package/src/cores/wasm/prosystem_libretro.js +2 -0
  180. package/src/cores/wasm/prosystem_libretro.wasm +0 -0
  181. package/src/cores/wasm/snes9x_libretro.js +2 -0
  182. package/src/cores/wasm/snes9x_libretro.wasm +0 -0
  183. package/src/cores/wasm/stella2014_libretro.js +2 -0
  184. package/src/cores/wasm/stella2014_libretro.wasm +0 -0
  185. package/src/cores/wasm/vice_x64_libretro.js +2 -0
  186. package/src/cores/wasm/vice_x64_libretro.wasm +0 -0
  187. package/src/host/LibretroHost.js +1469 -0
  188. package/src/host/c64-sid-state.js +161 -0
  189. package/src/host/callbacks.js +444 -0
  190. package/src/host/chafa-render.js +170 -0
  191. package/src/host/coreLoader.js +57 -0
  192. package/src/host/cpu-state.js +543 -0
  193. package/src/host/dsp-state.js +188 -0
  194. package/src/host/framebuffer.js +115 -0
  195. package/src/host/gb-apu-state.js +321 -0
  196. package/src/host/gba-video-state.js +215 -0
  197. package/src/host/gpgx-state.js +320 -0
  198. package/src/host/index.js +4 -0
  199. package/src/host/lynx-mikey-state.js +226 -0
  200. package/src/host/msx-ay-state.js +78 -0
  201. package/src/host/nes-apu-state.js +194 -0
  202. package/src/host/pce-psg-state.js +82 -0
  203. package/src/host/retroConstants.js +72 -0
  204. package/src/host/snes9x-state.js +35 -0
  205. package/src/host/types.js +332 -0
  206. package/src/http/routes.js +182 -0
  207. package/src/http/skill-doc.js +176 -0
  208. package/src/http/swagger.js +84 -0
  209. package/src/http/tool-registry.js +142 -0
  210. package/src/install/postinstall.mjs +81 -0
  211. package/src/mcp/disclosure.js +250 -0
  212. package/src/mcp/log.js +87 -0
  213. package/src/mcp/server.js +498 -0
  214. package/src/mcp/state.js +88 -0
  215. package/src/mcp/tool-manifest.js +92 -0
  216. package/src/mcp/tools/address-to-symbol.js +145 -0
  217. package/src/mcp/tools/art-loaders.js +743 -0
  218. package/src/mcp/tools/assets.js +87 -0
  219. package/src/mcp/tools/audio.js +562 -0
  220. package/src/mcp/tools/cart-parts.js +651 -0
  221. package/src/mcp/tools/cheats.js +343 -0
  222. package/src/mcp/tools/classify-region.js +107 -0
  223. package/src/mcp/tools/diff-cluster.js +32 -0
  224. package/src/mcp/tools/diff-roms.js +394 -0
  225. package/src/mcp/tools/disasm.js +1410 -0
  226. package/src/mcp/tools/find-references.js +375 -0
  227. package/src/mcp/tools/font-map.js +563 -0
  228. package/src/mcp/tools/frame.js +293 -0
  229. package/src/mcp/tools/free-space.js +71 -0
  230. package/src/mcp/tools/index.js +339 -0
  231. package/src/mcp/tools/input-layout.js +231 -0
  232. package/src/mcp/tools/input.js +227 -0
  233. package/src/mcp/tools/lifecycle.js +132 -0
  234. package/src/mcp/tools/lospec.js +187 -0
  235. package/src/mcp/tools/memory.js +472 -0
  236. package/src/mcp/tools/metasprite-tools.js +256 -0
  237. package/src/mcp/tools/platform-docs.js +113 -0
  238. package/src/mcp/tools/platform-tools.js +1300 -0
  239. package/src/mcp/tools/platforms.js +139 -0
  240. package/src/mcp/tools/playtest.js +360 -0
  241. package/src/mcp/tools/preview-tile.js +478 -0
  242. package/src/mcp/tools/project.js +1939 -0
  243. package/src/mcp/tools/record.js +180 -0
  244. package/src/mcp/tools/reinject.js +732 -0
  245. package/src/mcp/tools/rendering-context.js +838 -0
  246. package/src/mcp/tools/rom-id.js +308 -0
  247. package/src/mcp/tools/run-until.js +176 -0
  248. package/src/mcp/tools/snippets.js +209 -0
  249. package/src/mcp/tools/splice-chr.js +190 -0
  250. package/src/mcp/tools/sprite-pipeline.js +626 -0
  251. package/src/mcp/tools/state.js +198 -0
  252. package/src/mcp/tools/symbols.js +400 -0
  253. package/src/mcp/tools/tile-inspect.js +293 -0
  254. package/src/mcp/tools/toolchain.js +720 -0
  255. package/src/mcp/tools/trace-vram-source.js +81 -0
  256. package/src/mcp/tools/watch-memory.js +1036 -0
  257. package/src/mcp/tools/which-tiles.js +180 -0
  258. package/src/mcp/util.js +355 -0
  259. package/src/observer/bus.js +127 -0
  260. package/src/observer/livestream.html +594 -0
  261. package/src/observer/server.js +78 -0
  262. package/src/observer/tool-wrap.js +142 -0
  263. package/src/platforms/_guides/MUSIC_SOURCING.md +104 -0
  264. package/src/platforms/_guides/ROMHACKING_PLAYBOOK.md +245 -0
  265. package/src/platforms/atari2600/MENTAL_MODEL.md +194 -0
  266. package/src/platforms/atari2600/TROUBLESHOOTING.md +155 -0
  267. package/src/platforms/atari2600/UPSTREAM_SOURCES.md +49 -0
  268. package/src/platforms/atari2600/lib/README.md +67 -0
  269. package/src/platforms/atari2600/lib/cc65-src/crt0.s +49 -0
  270. package/src/platforms/atari2600/lib/cc65-src/ctype.s +5 -0
  271. package/src/platforms/atari2600/lib/kernel_skeleton.asm +85 -0
  272. package/src/platforms/atari2600/lib/player_kernel.asm +87 -0
  273. package/src/platforms/atari2600/lib/playfield_kernel.asm +63 -0
  274. package/src/platforms/atari2600/lib/read_joystick.asm +76 -0
  275. package/src/platforms/atari2600/lib/score_kernel.asm +141 -0
  276. package/src/platforms/atari2600/lib/vcs_constants.h +97 -0
  277. package/src/platforms/atari2600/lib/vectors.asm +16 -0
  278. package/src/platforms/atari2600/tia.js +355 -0
  279. package/src/platforms/atari7800/MENTAL_MODEL.md +324 -0
  280. package/src/platforms/atari7800/TROUBLESHOOTING.md +195 -0
  281. package/src/platforms/atari7800/UPSTREAM_SOURCES.md +43 -0
  282. package/src/platforms/atari7800/lib/README.md +45 -0
  283. package/src/platforms/atari7800/lib/c/atari7800_music.c +215 -0
  284. package/src/platforms/atari7800/lib/c/atari7800_music.h +33 -0
  285. package/src/platforms/atari7800/lib/c/atari7800_sfx.c +74 -0
  286. package/src/platforms/atari7800/lib/c/atari7800_sfx.h +45 -0
  287. package/src/platforms/atari7800/lib/cc65-src/clock.s +69 -0
  288. package/src/platforms/atari7800/lib/cc65-src/clocks_per_sec.s +34 -0
  289. package/src/platforms/atari7800/lib/cc65-src/clrscr.s +27 -0
  290. package/src/platforms/atari7800/lib/cc65-src/conio.s +226 -0
  291. package/src/platforms/atari7800/lib/cc65-src/conio_font.s +278 -0
  292. package/src/platforms/atari7800/lib/cc65-src/cputc.s +139 -0
  293. package/src/platforms/atari7800/lib/cc65-src/crt0.s +71 -0
  294. package/src/platforms/atari7800/lib/cc65-src/ctype.s +5 -0
  295. package/src/platforms/atari7800/lib/cc65-src/exehdr.s +46 -0
  296. package/src/platforms/atari7800/lib/cc65-src/extra/mono.s +28 -0
  297. package/src/platforms/atari7800/lib/cc65-src/extzp.inc +15 -0
  298. package/src/platforms/atari7800/lib/cc65-src/extzp.s +15 -0
  299. package/src/platforms/atari7800/lib/cc65-src/get_tv.s +65 -0
  300. package/src/platforms/atari7800/lib/cc65-src/irq.s +36 -0
  301. package/src/platforms/atari7800/lib/cc65-src/joy/atari7800-stdjoy.s +197 -0
  302. package/src/platforms/atari7800/lib/cc65-src/joy_stat_stddrv.s +14 -0
  303. package/src/platforms/atari7800/lib/cc65-src/libref.s +8 -0
  304. package/src/platforms/atari7800/lib/cc65-src/mono_clrscr.s +27 -0
  305. package/src/platforms/atari7800/lib/cc65-src/mono_conio.s +231 -0
  306. package/src/platforms/atari7800/lib/cc65-src/mono_cputc.s +102 -0
  307. package/src/platforms/atari7800/lib/cc65-src/mono_font.s +2065 -0
  308. package/src/platforms/atari7800/lib/cc65-src/mono_setcursor.s +214 -0
  309. package/src/platforms/atari7800/lib/cc65-src/setcursor.s +214 -0
  310. package/src/platforms/atari7800/lib/cc65-src/textcolor.s +53 -0
  311. package/src/platforms/atari7800/lib/cc65-src/wherex.s +19 -0
  312. package/src/platforms/atari7800/lib/cc65-src/wherey.s +19 -0
  313. package/src/platforms/atari7800/lib/display_list.asm +53 -0
  314. package/src/platforms/atari7800/lib/maria_init.asm +48 -0
  315. package/src/platforms/atari7800/lib/maria_registers.h +61 -0
  316. package/src/platforms/atari7800/lib/palette_load.asm +53 -0
  317. package/src/platforms/atari7800/lib/read_pad.asm +57 -0
  318. package/src/platforms/atari7800/lib/vblank_wait.asm +16 -0
  319. package/src/platforms/atari7800/maria.js +220 -0
  320. package/src/platforms/atari7800/song.js +232 -0
  321. package/src/platforms/c64/MENTAL_MODEL.md +188 -0
  322. package/src/platforms/c64/TROUBLESHOOTING.md +130 -0
  323. package/src/platforms/c64/UPSTREAM_SOURCES.md +35 -0
  324. package/src/platforms/c64/image-to-tilemap.js +190 -0
  325. package/src/platforms/c64/lib/README.md +52 -0
  326. package/src/platforms/c64/lib/basic_stub.s +25 -0
  327. package/src/platforms/c64/lib/c/c64_music.c +248 -0
  328. package/src/platforms/c64/lib/c/c64_music.h +36 -0
  329. package/src/platforms/c64/lib/c/c64_sfx.c +94 -0
  330. package/src/platforms/c64/lib/c/c64_sfx.h +37 -0
  331. package/src/platforms/c64/lib/c64_registers.h +108 -0
  332. package/src/platforms/c64/lib/cc65-src/_scrsize.s +12 -0
  333. package/src/platforms/c64/lib/cc65-src/acc_c128_speed.s +5 -0
  334. package/src/platforms/c64/lib/cc65-src/acc_c64dtv_speed.s +64 -0
  335. package/src/platforms/c64/lib/cc65-src/acc_c65_speed.s +69 -0
  336. package/src/platforms/c64/lib/cc65-src/acc_chameleon_speed.s +100 -0
  337. package/src/platforms/c64/lib/cc65-src/acc_detect_c128.s +33 -0
  338. package/src/platforms/c64/lib/cc65-src/acc_detect_c64dtv.s +44 -0
  339. package/src/platforms/c64/lib/cc65-src/acc_detect_c65.s +55 -0
  340. package/src/platforms/c64/lib/cc65-src/acc_detect_chameleon.s +39 -0
  341. package/src/platforms/c64/lib/cc65-src/acc_detect_scpu.s +34 -0
  342. package/src/platforms/c64/lib/cc65-src/acc_detect_turbomaster.s +45 -0
  343. package/src/platforms/c64/lib/cc65-src/acc_scpu_speed.s +59 -0
  344. package/src/platforms/c64/lib/cc65-src/acc_turbomaster_speed.s +56 -0
  345. package/src/platforms/c64/lib/cc65-src/bordercolor.s +17 -0
  346. package/src/platforms/c64/lib/cc65-src/break.s +108 -0
  347. package/src/platforms/c64/lib/cc65-src/cgetc.s +62 -0
  348. package/src/platforms/c64/lib/cc65-src/clrscr.s +11 -0
  349. package/src/platforms/c64/lib/cc65-src/color.s +24 -0
  350. package/src/platforms/c64/lib/cc65-src/conio.s +10 -0
  351. package/src/platforms/c64/lib/cc65-src/cputc.s +105 -0
  352. package/src/platforms/c64/lib/cc65-src/crt0.s +117 -0
  353. package/src/platforms/c64/lib/cc65-src/devnum.s +7 -0
  354. package/src/platforms/c64/lib/cc65-src/emd/c64-65816.s +377 -0
  355. package/src/platforms/c64/lib/cc65-src/emd/c64-c256k.s +508 -0
  356. package/src/platforms/c64/lib/cc65-src/emd/c64-dqbb.s +447 -0
  357. package/src/platforms/c64/lib/cc65-src/emd/c64-georam.s +355 -0
  358. package/src/platforms/c64/lib/cc65-src/emd/c64-isepic.s +276 -0
  359. package/src/platforms/c64/lib/cc65-src/emd/c64-kerberos.s +281 -0
  360. package/src/platforms/c64/lib/cc65-src/emd/c64-ram.s +270 -0
  361. package/src/platforms/c64/lib/cc65-src/emd/c64-ramcart.s +297 -0
  362. package/src/platforms/c64/lib/cc65-src/emd/c64-reu.s +286 -0
  363. package/src/platforms/c64/lib/cc65-src/emd/c64-rrr.s +363 -0
  364. package/src/platforms/c64/lib/cc65-src/emd/c64-vdc.s +405 -0
  365. package/src/platforms/c64/lib/cc65-src/emd/dtv-himem.s +251 -0
  366. package/src/platforms/c64/lib/cc65-src/extra/soft80.s +71 -0
  367. package/src/platforms/c64/lib/cc65-src/extra/soft80mono.s +74 -0
  368. package/src/platforms/c64/lib/cc65-src/extra/tgimousedata.s +21 -0
  369. package/src/platforms/c64/lib/cc65-src/get_ostype.s +43 -0
  370. package/src/platforms/c64/lib/cc65-src/get_tv.s +20 -0
  371. package/src/platforms/c64/lib/cc65-src/gettime.s +83 -0
  372. package/src/platforms/c64/lib/cc65-src/irq.s +49 -0
  373. package/src/platforms/c64/lib/cc65-src/joy/c64-hitjoy.s +218 -0
  374. package/src/platforms/c64/lib/cc65-src/joy/c64-numpad.s +155 -0
  375. package/src/platforms/c64/lib/cc65-src/joy/c64-ptvjoy.s +146 -0
  376. package/src/platforms/c64/lib/cc65-src/joy/c64-stdjoy.s +111 -0
  377. package/src/platforms/c64/lib/cc65-src/joy_stat_stddrv.s +14 -0
  378. package/src/platforms/c64/lib/cc65-src/joy_stddrv.s +14 -0
  379. package/src/platforms/c64/lib/cc65-src/kbhit.s +23 -0
  380. package/src/platforms/c64/lib/cc65-src/kbrepeat.s +14 -0
  381. package/src/platforms/c64/lib/cc65-src/kernal.s +53 -0
  382. package/src/platforms/c64/lib/cc65-src/kplot.s +22 -0
  383. package/src/platforms/c64/lib/cc65-src/libref.s +16 -0
  384. package/src/platforms/c64/lib/cc65-src/mainargs.s +137 -0
  385. package/src/platforms/c64/lib/cc65-src/mcbdefault.s +146 -0
  386. package/src/platforms/c64/lib/cc65-src/mcbspritedata.s +4 -0
  387. package/src/platforms/c64/lib/cc65-src/mou/c64-1351.s +467 -0
  388. package/src/platforms/c64/lib/cc65-src/mou/c64-inkwell.s +446 -0
  389. package/src/platforms/c64/lib/cc65-src/mou/c64-joy.s +451 -0
  390. package/src/platforms/c64/lib/cc65-src/mou/c64-pot.s +409 -0
  391. package/src/platforms/c64/lib/cc65-src/mouse_stat_stddrv.s +14 -0
  392. package/src/platforms/c64/lib/cc65-src/mouse_stddrv.s +14 -0
  393. package/src/platforms/c64/lib/cc65-src/mouseref.s +23 -0
  394. package/src/platforms/c64/lib/cc65-src/pencalib.c +94 -0
  395. package/src/platforms/c64/lib/cc65-src/randomize.s +18 -0
  396. package/src/platforms/c64/lib/cc65-src/revers.s +27 -0
  397. package/src/platforms/c64/lib/cc65-src/ser/c64-swlink.s +484 -0
  398. package/src/platforms/c64/lib/cc65-src/ser_stat_stddrv.s +14 -0
  399. package/src/platforms/c64/lib/cc65-src/ser_stddrv.s +13 -0
  400. package/src/platforms/c64/lib/cc65-src/settime.s +84 -0
  401. package/src/platforms/c64/lib/cc65-src/soft80.inc +46 -0
  402. package/src/platforms/c64/lib/cc65-src/soft80_cgetc.s +85 -0
  403. package/src/platforms/c64/lib/cc65-src/soft80_charset.s +182 -0
  404. package/src/platforms/c64/lib/cc65-src/soft80_color.s +159 -0
  405. package/src/platforms/c64/lib/cc65-src/soft80_conio.s +157 -0
  406. package/src/platforms/c64/lib/cc65-src/soft80_cpeekc.s +148 -0
  407. package/src/platforms/c64/lib/cc65-src/soft80_cpeekcolor.s +19 -0
  408. package/src/platforms/c64/lib/cc65-src/soft80_cpeekrevers.s +15 -0
  409. package/src/platforms/c64/lib/cc65-src/soft80_cpeeks.s +71 -0
  410. package/src/platforms/c64/lib/cc65-src/soft80_cputc.s +521 -0
  411. package/src/platforms/c64/lib/cc65-src/soft80_kclrscr.s +76 -0
  412. package/src/platforms/c64/lib/cc65-src/soft80_kplot.s +63 -0
  413. package/src/platforms/c64/lib/cc65-src/soft80_scrsize.s +14 -0
  414. package/src/platforms/c64/lib/cc65-src/soft80mono_cgetc.s +67 -0
  415. package/src/platforms/c64/lib/cc65-src/soft80mono_color.s +65 -0
  416. package/src/platforms/c64/lib/cc65-src/soft80mono_conio.s +168 -0
  417. package/src/platforms/c64/lib/cc65-src/soft80mono_cpeekcolor.s +17 -0
  418. package/src/platforms/c64/lib/cc65-src/soft80mono_cputc.s +204 -0
  419. package/src/platforms/c64/lib/cc65-src/soft80mono_kclrscr.s +63 -0
  420. package/src/platforms/c64/lib/cc65-src/soft80mono_kplot.s +52 -0
  421. package/src/platforms/c64/lib/cc65-src/status.s +15 -0
  422. package/src/platforms/c64/lib/cc65-src/sysuname.s +37 -0
  423. package/src/platforms/c64/lib/cc65-src/tgi/c64-hi.s +881 -0
  424. package/src/platforms/c64/lib/cc65-src/tgi_stat_stddrv.s +14 -0
  425. package/src/platforms/c64/lib/cc65-src/tgi_stddrv.s +13 -0
  426. package/src/platforms/c64/lib/cc65-src/tmcommon.s +67 -0
  427. package/src/platforms/c64/lib/cc65-src/waitvsync.s +18 -0
  428. package/src/platforms/c64/lib/read_joystick.s +28 -0
  429. package/src/platforms/c64/lib/sid_play.s +48 -0
  430. package/src/platforms/c64/lib/sprite_table.s +73 -0
  431. package/src/platforms/c64/lib/vic_init.s +47 -0
  432. package/src/platforms/c64/sid.js +128 -0
  433. package/src/platforms/c64/song.js +262 -0
  434. package/src/platforms/c64/vic.js +273 -0
  435. package/src/platforms/common/default-palette.js +139 -0
  436. package/src/platforms/common/image-to-tiles.js +418 -0
  437. package/src/platforms/common/intent.js +111 -0
  438. package/src/platforms/common/metasprite-adapters.js +279 -0
  439. package/src/platforms/common/metasprite-codegen.js +192 -0
  440. package/src/platforms/common/metasprite-core.js +201 -0
  441. package/src/platforms/common/metasprite.js +89 -0
  442. package/src/platforms/common/platform-palette.js +137 -0
  443. package/src/platforms/common/registers.js +329 -0
  444. package/src/platforms/common/render-tiles.js +86 -0
  445. package/src/platforms/common/screenshot-sprite.js +153 -0
  446. package/src/platforms/common/tile-decode.js +149 -0
  447. package/src/platforms/gb/MENTAL_MODEL.md +262 -0
  448. package/src/platforms/gb/TROUBLESHOOTING.md +218 -0
  449. package/src/platforms/gb/UPSTREAM_SOURCES.md +43 -0
  450. package/src/platforms/gb/image-to-tilemap.js +173 -0
  451. package/src/platforms/gb/lib/README.md +115 -0
  452. package/src/platforms/gb/lib/c/LICENSE-HUGEDRIVER +25 -0
  453. package/src/platforms/gb/lib/c/README.md +122 -0
  454. package/src/platforms/gb/lib/c/SDCC_GOTCHAS.md +190 -0
  455. package/src/platforms/gb/lib/c/gb_crt0.s +163 -0
  456. package/src/platforms/gb/lib/c/gb_hardware.h +113 -0
  457. package/src/platforms/gb/lib/c/gb_runtime.c +284 -0
  458. package/src/platforms/gb/lib/c/gb_runtime.h +145 -0
  459. package/src/platforms/gb/lib/c/hUGEDriver.c +191 -0
  460. package/src/platforms/gb/lib/c/hUGEDriver.h +95 -0
  461. package/src/platforms/gb/lib/c/hUGEDriver.upstream.asm +1908 -0
  462. package/src/platforms/gb/lib/c/lcd_init.c +19 -0
  463. package/src/platforms/gb/lib/c/patch-header.js +154 -0
  464. package/src/platforms/gb/lib/c/song_data.c +88 -0
  465. package/src/platforms/gb/lib/c/unroll.h +52 -0
  466. package/src/platforms/gb/lib/c/wait_vblank.c +14 -0
  467. package/src/platforms/gb/lib/dma_oam.asm +51 -0
  468. package/src/platforms/gb/lib/header.asm +56 -0
  469. package/src/platforms/gb/lib/joypad_read.asm +47 -0
  470. package/src/platforms/gb/lib/lcd_init.asm +44 -0
  471. package/src/platforms/gb/lib/load_palette.asm +25 -0
  472. package/src/platforms/gb/lib/load_tiles.asm +29 -0
  473. package/src/platforms/gb/lib/vblank_wait.asm +31 -0
  474. package/src/platforms/gb/ppu.js +574 -0
  475. package/src/platforms/gb/song.js +140 -0
  476. package/src/platforms/gba/MENTAL_MODEL.md +216 -0
  477. package/src/platforms/gba/TROUBLESHOOTING.md +250 -0
  478. package/src/platforms/gba/UPSTREAM_SOURCES.md +41 -0
  479. package/src/platforms/gba/lib/arm-archives/libc.a +0 -0
  480. package/src/platforms/gba/lib/arm-archives/libgcc.a +0 -0
  481. package/src/platforms/gba/lib/arm-archives/libnosys.a +0 -0
  482. package/src/platforms/gba/lib/c/gba_sfx.c +81 -0
  483. package/src/platforms/gba/lib/c/gba_sfx.h +48 -0
  484. package/src/platforms/gba/lib/libgba/crtbegin.o +0 -0
  485. package/src/platforms/gba/lib/libgba/crtend.o +0 -0
  486. package/src/platforms/gba/lib/libgba/crti.o +0 -0
  487. package/src/platforms/gba/lib/libgba/crtn.o +0 -0
  488. package/src/platforms/gba/lib/libgba/gba_cart.ld +319 -0
  489. package/src/platforms/gba/lib/libgba/gba_crt0.s +258 -0
  490. package/src/platforms/gba/lib/libgba/include/BoyScout.h +128 -0
  491. package/src/platforms/gba/lib/libgba/include/disc.h +36 -0
  492. package/src/platforms/gba/lib/libgba/include/disc_io.h +64 -0
  493. package/src/platforms/gba/lib/libgba/include/dldi.h +112 -0
  494. package/src/platforms/gba/lib/libgba/include/erapi.h +195 -0
  495. package/src/platforms/gba/lib/libgba/include/fade.h +76 -0
  496. package/src/platforms/gba/lib/libgba/include/gba.h +47 -0
  497. package/src/platforms/gba/lib/libgba/include/gba_affine.h +83 -0
  498. package/src/platforms/gba/lib/libgba/include/gba_base.h +122 -0
  499. package/src/platforms/gba/lib/libgba/include/gba_compression.h +66 -0
  500. package/src/platforms/gba/lib/libgba/include/gba_console.h +55 -0
  501. package/src/platforms/gba/lib/libgba/include/gba_dma.h +100 -0
  502. package/src/platforms/gba/lib/libgba/include/gba_input.h +127 -0
  503. package/src/platforms/gba/lib/libgba/include/gba_interrupt.h +146 -0
  504. package/src/platforms/gba/lib/libgba/include/gba_multiboot.h +72 -0
  505. package/src/platforms/gba/lib/libgba/include/gba_sio.h +124 -0
  506. package/src/platforms/gba/lib/libgba/include/gba_sound.h +356 -0
  507. package/src/platforms/gba/lib/libgba/include/gba_sprites.h +195 -0
  508. package/src/platforms/gba/lib/libgba/include/gba_systemcalls.h +194 -0
  509. package/src/platforms/gba/lib/libgba/include/gba_timers.h +63 -0
  510. package/src/platforms/gba/lib/libgba/include/gba_types.h +60 -0
  511. package/src/platforms/gba/lib/libgba/include/gba_video.h +307 -0
  512. package/src/platforms/gba/lib/libgba/include/mappy.h +72 -0
  513. package/src/platforms/gba/lib/libgba/include/mbv2.h +90 -0
  514. package/src/platforms/gba/lib/libgba/include/xcomms.h +93 -0
  515. package/src/platforms/gba/lib/libgba/include/xcomms_cmd.h +53 -0
  516. package/src/platforms/gba/lib/libgba/libgba.seed.a +0 -0
  517. package/src/platforms/gba/lib/libgba/libgba.seed.hash +1 -0
  518. package/src/platforms/gba/lib/libgba/src/AffineSet.c +42 -0
  519. package/src/platforms/gba/lib/libgba/src/ArcTan.s +41 -0
  520. package/src/platforms/gba/lib/libgba/src/BoyScout/BoyScout.c +1242 -0
  521. package/src/platforms/gba/lib/libgba/src/BoyScout/GBASoundRegs.h +200 -0
  522. package/src/platforms/gba/lib/libgba/src/Compression.c +84 -0
  523. package/src/platforms/gba/lib/libgba/src/CpuSet.c +41 -0
  524. package/src/platforms/gba/lib/libgba/src/Div.s +58 -0
  525. package/src/platforms/gba/lib/libgba/src/DivArm.s +50 -0
  526. package/src/platforms/gba/lib/libgba/src/InterruptDispatcher.s +113 -0
  527. package/src/platforms/gba/lib/libgba/src/IntrWait.c +35 -0
  528. package/src/platforms/gba/lib/libgba/src/MultiBoot.s +33 -0
  529. package/src/platforms/gba/lib/libgba/src/Reset.s +49 -0
  530. package/src/platforms/gba/lib/libgba/src/Sound.s +48 -0
  531. package/src/platforms/gba/lib/libgba/src/Sqrt.s +34 -0
  532. package/src/platforms/gba/lib/libgba/src/disc_io/disc.c +58 -0
  533. package/src/platforms/gba/lib/libgba/src/disc_io/dldi.c +189 -0
  534. package/src/platforms/gba/lib/libgba/src/disc_io/dldi_stub.s +78 -0
  535. package/src/platforms/gba/lib/libgba/src/disc_io/io_cf_common.c +260 -0
  536. package/src/platforms/gba/lib/libgba/src/disc_io/io_cf_common.h +72 -0
  537. package/src/platforms/gba/lib/libgba/src/disc_io/io_m3_common.c +60 -0
  538. package/src/platforms/gba/lib/libgba/src/disc_io/io_m3_common.h +48 -0
  539. package/src/platforms/gba/lib/libgba/src/disc_io/io_m3cf.c +83 -0
  540. package/src/platforms/gba/lib/libgba/src/disc_io/io_m3cf.h +45 -0
  541. package/src/platforms/gba/lib/libgba/src/disc_io/io_m3sd.c +508 -0
  542. package/src/platforms/gba/lib/libgba/src/disc_io/io_m3sd.h +45 -0
  543. package/src/platforms/gba/lib/libgba/src/disc_io/io_mpcf.c +87 -0
  544. package/src/platforms/gba/lib/libgba/src/disc_io/io_mpcf.h +42 -0
  545. package/src/platforms/gba/lib/libgba/src/disc_io/io_sc_common.c +47 -0
  546. package/src/platforms/gba/lib/libgba/src/disc_io/io_sc_common.h +43 -0
  547. package/src/platforms/gba/lib/libgba/src/disc_io/io_sccf.c +83 -0
  548. package/src/platforms/gba/lib/libgba/src/disc_io/io_sccf.h +45 -0
  549. package/src/platforms/gba/lib/libgba/src/disc_io/io_scsd.c +385 -0
  550. package/src/platforms/gba/lib/libgba/src/disc_io/io_scsd.h +48 -0
  551. package/src/platforms/gba/lib/libgba/src/disc_io/io_scsd_s.s +139 -0
  552. package/src/platforms/gba/lib/libgba/src/disc_io/io_sd_common.c +203 -0
  553. package/src/platforms/gba/lib/libgba/src/disc_io/io_sd_common.h +108 -0
  554. package/src/platforms/gba/lib/libgba/src/fade.c +185 -0
  555. package/src/platforms/gba/lib/libgba/src/input.c +127 -0
  556. package/src/platforms/gba/lib/libgba/src/interrupt.c +116 -0
  557. package/src/platforms/gba/lib/libgba/src/mappy_print.c +74 -0
  558. package/src/platforms/gba/lib/libgba/src/mb2print.c +69 -0
  559. package/src/platforms/gba/lib/libgba/src/mbv2.c +230 -0
  560. package/src/platforms/gba/lib/libgba/src/mbv2.txt +119 -0
  561. package/src/platforms/gba/lib/libgba/src/xcomms.c +203 -0
  562. package/src/platforms/gba/lib/libgba/src/xcomms_print.c +56 -0
  563. package/src/platforms/gba/lib/libgba/sysinclude/_ansi.h +82 -0
  564. package/src/platforms/gba/lib/libgba/sysinclude/_newlib_version.h +11 -0
  565. package/src/platforms/gba/lib/libgba/sysinclude/_syslist.h +41 -0
  566. package/src/platforms/gba/lib/libgba/sysinclude/alloca.h +21 -0
  567. package/src/platforms/gba/lib/libgba/sysinclude/ar.h +65 -0
  568. package/src/platforms/gba/lib/libgba/sysinclude/argz.h +33 -0
  569. package/src/platforms/gba/lib/libgba/sysinclude/assert.h +50 -0
  570. package/src/platforms/gba/lib/libgba/sysinclude/complex.h +150 -0
  571. package/src/platforms/gba/lib/libgba/sysinclude/cpio.h +30 -0
  572. package/src/platforms/gba/lib/libgba/sysinclude/ctype.h +183 -0
  573. package/src/platforms/gba/lib/libgba/sysinclude/devctl.h +78 -0
  574. package/src/platforms/gba/lib/libgba/sysinclude/dirent.h +85 -0
  575. package/src/platforms/gba/lib/libgba/sysinclude/elf.h +3147 -0
  576. package/src/platforms/gba/lib/libgba/sysinclude/envlock.h +15 -0
  577. package/src/platforms/gba/lib/libgba/sysinclude/envz.h +16 -0
  578. package/src/platforms/gba/lib/libgba/sysinclude/errno.h +11 -0
  579. package/src/platforms/gba/lib/libgba/sysinclude/fastmath.h +13 -0
  580. package/src/platforms/gba/lib/libgba/sysinclude/fcntl.h +1 -0
  581. package/src/platforms/gba/lib/libgba/sysinclude/fenv.h +42 -0
  582. package/src/platforms/gba/lib/libgba/sysinclude/float.h +631 -0
  583. package/src/platforms/gba/lib/libgba/sysinclude/fnmatch.h +55 -0
  584. package/src/platforms/gba/lib/libgba/sysinclude/ftw.h +66 -0
  585. package/src/platforms/gba/lib/libgba/sysinclude/getopt.h +185 -0
  586. package/src/platforms/gba/lib/libgba/sysinclude/glob.h +90 -0
  587. package/src/platforms/gba/lib/libgba/sysinclude/grp.h +86 -0
  588. package/src/platforms/gba/lib/libgba/sysinclude/iconv.h +63 -0
  589. package/src/platforms/gba/lib/libgba/sysinclude/ieeefp.h +295 -0
  590. package/src/platforms/gba/lib/libgba/sysinclude/inttypes.h +345 -0
  591. package/src/platforms/gba/lib/libgba/sysinclude/iso646.h +45 -0
  592. package/src/platforms/gba/lib/libgba/sysinclude/langinfo.h +332 -0
  593. package/src/platforms/gba/lib/libgba/sysinclude/libgen.h +37 -0
  594. package/src/platforms/gba/lib/libgba/sysinclude/limits.h +168 -0
  595. package/src/platforms/gba/lib/libgba/sysinclude/locale.h +96 -0
  596. package/src/platforms/gba/lib/libgba/sysinclude/machine/_arc4random.h +1 -0
  597. package/src/platforms/gba/lib/libgba/sysinclude/machine/_default_types.h +250 -0
  598. package/src/platforms/gba/lib/libgba/sysinclude/machine/_endian.h +39 -0
  599. package/src/platforms/gba/lib/libgba/sysinclude/machine/_time.h +3 -0
  600. package/src/platforms/gba/lib/libgba/sysinclude/machine/_types.h +8 -0
  601. package/src/platforms/gba/lib/libgba/sysinclude/machine/ansi.h +1 -0
  602. package/src/platforms/gba/lib/libgba/sysinclude/machine/endian.h +69 -0
  603. package/src/platforms/gba/lib/libgba/sysinclude/machine/fastmath.h +98 -0
  604. package/src/platforms/gba/lib/libgba/sysinclude/machine/ieee.h +127 -0
  605. package/src/platforms/gba/lib/libgba/sysinclude/machine/ieeefp.h +533 -0
  606. package/src/platforms/gba/lib/libgba/sysinclude/machine/malloc.h +8 -0
  607. package/src/platforms/gba/lib/libgba/sysinclude/machine/param.h +8 -0
  608. package/src/platforms/gba/lib/libgba/sysinclude/machine/setjmp-dj.h +43 -0
  609. package/src/platforms/gba/lib/libgba/sysinclude/machine/setjmp.h +524 -0
  610. package/src/platforms/gba/lib/libgba/sysinclude/machine/stdlib.h +8 -0
  611. package/src/platforms/gba/lib/libgba/sysinclude/machine/termios.h +1 -0
  612. package/src/platforms/gba/lib/libgba/sysinclude/machine/time.h +15 -0
  613. package/src/platforms/gba/lib/libgba/sysinclude/machine/types.h +13 -0
  614. package/src/platforms/gba/lib/libgba/sysinclude/malloc.h +173 -0
  615. package/src/platforms/gba/lib/libgba/sysinclude/math.h +645 -0
  616. package/src/platforms/gba/lib/libgba/sysinclude/memory.h +4 -0
  617. package/src/platforms/gba/lib/libgba/sysinclude/ndbm.h +91 -0
  618. package/src/platforms/gba/lib/libgba/sysinclude/newlib.h +427 -0
  619. package/src/platforms/gba/lib/libgba/sysinclude/paths.h +9 -0
  620. package/src/platforms/gba/lib/libgba/sysinclude/pthread.h +456 -0
  621. package/src/platforms/gba/lib/libgba/sysinclude/pwd.h +83 -0
  622. package/src/platforms/gba/lib/libgba/sysinclude/reent.h +190 -0
  623. package/src/platforms/gba/lib/libgba/sysinclude/regdef.h +7 -0
  624. package/src/platforms/gba/lib/libgba/sysinclude/regex.h +103 -0
  625. package/src/platforms/gba/lib/libgba/sysinclude/sched.h +112 -0
  626. package/src/platforms/gba/lib/libgba/sysinclude/search.h +64 -0
  627. package/src/platforms/gba/lib/libgba/sysinclude/setjmp.h +25 -0
  628. package/src/platforms/gba/lib/libgba/sysinclude/signal.h +35 -0
  629. package/src/platforms/gba/lib/libgba/sysinclude/spawn.h +111 -0
  630. package/src/platforms/gba/lib/libgba/sysinclude/ssp/ssp.h +76 -0
  631. package/src/platforms/gba/lib/libgba/sysinclude/ssp/stdio.h +101 -0
  632. package/src/platforms/gba/lib/libgba/sysinclude/ssp/stdlib.h +30 -0
  633. package/src/platforms/gba/lib/libgba/sysinclude/ssp/string.h +115 -0
  634. package/src/platforms/gba/lib/libgba/sysinclude/ssp/strings.h +55 -0
  635. package/src/platforms/gba/lib/libgba/sysinclude/ssp/unistd.h +93 -0
  636. package/src/platforms/gba/lib/libgba/sysinclude/ssp/wchar.h +97 -0
  637. package/src/platforms/gba/lib/libgba/sysinclude/stdarg.h +135 -0
  638. package/src/platforms/gba/lib/libgba/sysinclude/stdatomic.h +409 -0
  639. package/src/platforms/gba/lib/libgba/sysinclude/stdbool.h +51 -0
  640. package/src/platforms/gba/lib/libgba/sysinclude/stddef.h +463 -0
  641. package/src/platforms/gba/lib/libgba/sysinclude/stdint.h +466 -0
  642. package/src/platforms/gba/lib/libgba/sysinclude/stdio.h +807 -0
  643. package/src/platforms/gba/lib/libgba/sysinclude/stdio_ext.h +79 -0
  644. package/src/platforms/gba/lib/libgba/sysinclude/stdlib.h +345 -0
  645. package/src/platforms/gba/lib/libgba/sysinclude/string.h +183 -0
  646. package/src/platforms/gba/lib/libgba/sysinclude/strings.h +80 -0
  647. package/src/platforms/gba/lib/libgba/sysinclude/sys/_default_fcntl.h +241 -0
  648. package/src/platforms/gba/lib/libgba/sysinclude/sys/_intsup.h +199 -0
  649. package/src/platforms/gba/lib/libgba/sysinclude/sys/_locale.h +12 -0
  650. package/src/platforms/gba/lib/libgba/sysinclude/sys/_pthreadtypes.h +233 -0
  651. package/src/platforms/gba/lib/libgba/sysinclude/sys/_sigset.h +43 -0
  652. package/src/platforms/gba/lib/libgba/sysinclude/sys/_stdint.h +90 -0
  653. package/src/platforms/gba/lib/libgba/sysinclude/sys/_timespec.h +52 -0
  654. package/src/platforms/gba/lib/libgba/sysinclude/sys/_timeval.h +60 -0
  655. package/src/platforms/gba/lib/libgba/sysinclude/sys/_types.h +228 -0
  656. package/src/platforms/gba/lib/libgba/sysinclude/sys/_tz_structs.h +24 -0
  657. package/src/platforms/gba/lib/libgba/sysinclude/sys/cdefs.h +754 -0
  658. package/src/platforms/gba/lib/libgba/sysinclude/sys/config.h +314 -0
  659. package/src/platforms/gba/lib/libgba/sysinclude/sys/custom_file.h +2 -0
  660. package/src/platforms/gba/lib/libgba/sysinclude/sys/dir.h +10 -0
  661. package/src/platforms/gba/lib/libgba/sysinclude/sys/dirent.h +13 -0
  662. package/src/platforms/gba/lib/libgba/sysinclude/sys/endian.h +207 -0
  663. package/src/platforms/gba/lib/libgba/sysinclude/sys/errno.h +198 -0
  664. package/src/platforms/gba/lib/libgba/sysinclude/sys/fcntl.h +12 -0
  665. package/src/platforms/gba/lib/libgba/sysinclude/sys/features.h +551 -0
  666. package/src/platforms/gba/lib/libgba/sysinclude/sys/fenv.h +90 -0
  667. package/src/platforms/gba/lib/libgba/sysinclude/sys/file.h +2 -0
  668. package/src/platforms/gba/lib/libgba/sysinclude/sys/iconvnls.h +77 -0
  669. package/src/platforms/gba/lib/libgba/sysinclude/sys/iosupport.h +143 -0
  670. package/src/platforms/gba/lib/libgba/sysinclude/sys/lock.h +75 -0
  671. package/src/platforms/gba/lib/libgba/sysinclude/sys/param.h +35 -0
  672. package/src/platforms/gba/lib/libgba/sysinclude/sys/queue.h +919 -0
  673. package/src/platforms/gba/lib/libgba/sysinclude/sys/reent.h +913 -0
  674. package/src/platforms/gba/lib/libgba/sysinclude/sys/resource.h +24 -0
  675. package/src/platforms/gba/lib/libgba/sysinclude/sys/sched.h +69 -0
  676. package/src/platforms/gba/lib/libgba/sysinclude/sys/select.h +94 -0
  677. package/src/platforms/gba/lib/libgba/sysinclude/sys/signal.h +388 -0
  678. package/src/platforms/gba/lib/libgba/sysinclude/sys/stat.h +179 -0
  679. package/src/platforms/gba/lib/libgba/sysinclude/sys/statvfs.h +41 -0
  680. package/src/platforms/gba/lib/libgba/sysinclude/sys/stdio.h +27 -0
  681. package/src/platforms/gba/lib/libgba/sysinclude/sys/string.h +2 -0
  682. package/src/platforms/gba/lib/libgba/sysinclude/sys/syslimits.h +61 -0
  683. package/src/platforms/gba/lib/libgba/sysinclude/sys/time.h +448 -0
  684. package/src/platforms/gba/lib/libgba/sysinclude/sys/timeb.h +40 -0
  685. package/src/platforms/gba/lib/libgba/sysinclude/sys/times.h +32 -0
  686. package/src/platforms/gba/lib/libgba/sysinclude/sys/timespec.h +63 -0
  687. package/src/platforms/gba/lib/libgba/sysinclude/sys/tree.h +864 -0
  688. package/src/platforms/gba/lib/libgba/sysinclude/sys/types.h +228 -0
  689. package/src/platforms/gba/lib/libgba/sysinclude/sys/unistd.h +591 -0
  690. package/src/platforms/gba/lib/libgba/sysinclude/sys/utime.h +22 -0
  691. package/src/platforms/gba/lib/libgba/sysinclude/sys/wait.h +44 -0
  692. package/src/platforms/gba/lib/libgba/sysinclude/tar.h +43 -0
  693. package/src/platforms/gba/lib/libgba/sysinclude/termios.h +7 -0
  694. package/src/platforms/gba/lib/libgba/sysinclude/tgmath.h +127 -0
  695. package/src/platforms/gba/lib/libgba/sysinclude/threads.h +93 -0
  696. package/src/platforms/gba/lib/libgba/sysinclude/time.h +313 -0
  697. package/src/platforms/gba/lib/libgba/sysinclude/unctrl.h +42 -0
  698. package/src/platforms/gba/lib/libgba/sysinclude/unistd.h +6 -0
  699. package/src/platforms/gba/lib/libgba/sysinclude/utime.h +12 -0
  700. package/src/platforms/gba/lib/libgba/sysinclude/utmp.h +8 -0
  701. package/src/platforms/gba/lib/libgba/sysinclude/varargs.h +7 -0
  702. package/src/platforms/gba/lib/libgba/sysinclude/wchar.h +339 -0
  703. package/src/platforms/gba/lib/libgba/sysinclude/wctype.h +74 -0
  704. package/src/platforms/gba/lib/libgba/sysinclude/wordexp.h +53 -0
  705. package/src/platforms/gba/lib/libtonc/crtbegin.o +0 -0
  706. package/src/platforms/gba/lib/libtonc/crtend.o +0 -0
  707. package/src/platforms/gba/lib/libtonc/crti.o +0 -0
  708. package/src/platforms/gba/lib/libtonc/crtn.o +0 -0
  709. package/src/platforms/gba/lib/libtonc/gba_cart.ld +319 -0
  710. package/src/platforms/gba/lib/libtonc/gba_crt0.s +258 -0
  711. package/src/platforms/gba/lib/libtonc/include/tonc.h +72 -0
  712. package/src/platforms/gba/lib/libtonc/include/tonc_asminc.h +132 -0
  713. package/src/platforms/gba/lib/libtonc/include/tonc_bios.h +555 -0
  714. package/src/platforms/gba/lib/libtonc/include/tonc_core.h +573 -0
  715. package/src/platforms/gba/lib/libtonc/include/tonc_input.h +184 -0
  716. package/src/platforms/gba/lib/libtonc/include/tonc_irq.h +121 -0
  717. package/src/platforms/gba/lib/libtonc/include/tonc_legacy.h +481 -0
  718. package/src/platforms/gba/lib/libtonc/include/tonc_libgba.h +537 -0
  719. package/src/platforms/gba/lib/libtonc/include/tonc_math.h +692 -0
  720. package/src/platforms/gba/lib/libtonc/include/tonc_memdef.h +962 -0
  721. package/src/platforms/gba/lib/libtonc/include/tonc_memmap.h +583 -0
  722. package/src/platforms/gba/lib/libtonc/include/tonc_nocash.h +51 -0
  723. package/src/platforms/gba/lib/libtonc/include/tonc_oam.h +186 -0
  724. package/src/platforms/gba/lib/libtonc/include/tonc_surface.h +461 -0
  725. package/src/platforms/gba/lib/libtonc/include/tonc_text.h +270 -0
  726. package/src/platforms/gba/lib/libtonc/include/tonc_tte.h +748 -0
  727. package/src/platforms/gba/lib/libtonc/include/tonc_types.h +376 -0
  728. package/src/platforms/gba/lib/libtonc/include/tonc_video.h +615 -0
  729. package/src/platforms/gba/lib/libtonc/libtonc.seed.a +0 -0
  730. package/src/platforms/gba/lib/libtonc/libtonc.seed.hash +1 -0
  731. package/src/platforms/gba/lib/libtonc/src/asm/clr_blend_fast.s +72 -0
  732. package/src/platforms/gba/lib/libtonc/src/asm/clr_fade_fast.s +74 -0
  733. package/src/platforms/gba/lib/libtonc/src/asm/div_lut.s +54 -0
  734. package/src/platforms/gba/lib/libtonc/src/asm/sin_lut.s +90 -0
  735. package/src/platforms/gba/lib/libtonc/src/asm/tonc_bios.s +289 -0
  736. package/src/platforms/gba/lib/libtonc/src/asm/tonc_bios_ex.s +97 -0
  737. package/src/platforms/gba/lib/libtonc/src/asm/tonc_isr_master.s +92 -0
  738. package/src/platforms/gba/lib/libtonc/src/asm/tonc_isr_nest.s +98 -0
  739. package/src/platforms/gba/lib/libtonc/src/asm/tonc_memcpy.s +126 -0
  740. package/src/platforms/gba/lib/libtonc/src/asm/tonc_memset.s +123 -0
  741. package/src/platforms/gba/lib/libtonc/src/asm/tonc_nocash.s +73 -0
  742. package/src/platforms/gba/lib/libtonc/src/font/sys8.png +0 -0
  743. package/src/platforms/gba/lib/libtonc/src/font/sys8.s +46 -0
  744. package/src/platforms/gba/lib/libtonc/src/font/verdana10.png +0 -0
  745. package/src/platforms/gba/lib/libtonc/src/font/verdana10.s +293 -0
  746. package/src/platforms/gba/lib/libtonc/src/font/verdana9.png +0 -0
  747. package/src/platforms/gba/lib/libtonc/src/font/verdana9.s +167 -0
  748. package/src/platforms/gba/lib/libtonc/src/font/verdana9_b4.png +0 -0
  749. package/src/platforms/gba/lib/libtonc/src/font/verdana9_b4.s +545 -0
  750. package/src/platforms/gba/lib/libtonc/src/font/verdana9b.png +0 -0
  751. package/src/platforms/gba/lib/libtonc/src/font/verdana9b.s +167 -0
  752. package/src/platforms/gba/lib/libtonc/src/font/verdana9i.png +0 -0
  753. package/src/platforms/gba/lib/libtonc/src/font/verdana9i.s +167 -0
  754. package/src/platforms/gba/lib/libtonc/src/pre1.3/tonc_bitmap.c +289 -0
  755. package/src/platforms/gba/lib/libtonc/src/pre1.3/tonc_text.c +81 -0
  756. package/src/platforms/gba/lib/libtonc/src/pre1.3/tonc_text_bm.c +244 -0
  757. package/src/platforms/gba/lib/libtonc/src/pre1.3/tonc_text_map.c +122 -0
  758. package/src/platforms/gba/lib/libtonc/src/pre1.3/tonc_text_oam.c +113 -0
  759. package/src/platforms/gba/lib/libtonc/src/pre1.3/toncfont.s +43 -0
  760. package/src/platforms/gba/lib/libtonc/src/tonc_bg.c +61 -0
  761. package/src/platforms/gba/lib/libtonc/src/tonc_bg_affine.c +112 -0
  762. package/src/platforms/gba/lib/libtonc/src/tonc_bmp16.c +240 -0
  763. package/src/platforms/gba/lib/libtonc/src/tonc_bmp8.c +314 -0
  764. package/src/platforms/gba/lib/libtonc/src/tonc_color.c +368 -0
  765. package/src/platforms/gba/lib/libtonc/src/tonc_core.c +237 -0
  766. package/src/platforms/gba/lib/libtonc/src/tonc_input.c +118 -0
  767. package/src/platforms/gba/lib/libtonc/src/tonc_irq.c +271 -0
  768. package/src/platforms/gba/lib/libtonc/src/tonc_math.c +54 -0
  769. package/src/platforms/gba/lib/libtonc/src/tonc_oam.c +76 -0
  770. package/src/platforms/gba/lib/libtonc/src/tonc_obj_affine.c +146 -0
  771. package/src/platforms/gba/lib/libtonc/src/tonc_sbmp16.c +369 -0
  772. package/src/platforms/gba/lib/libtonc/src/tonc_sbmp8.c +405 -0
  773. package/src/platforms/gba/lib/libtonc/src/tonc_schr4c.c +588 -0
  774. package/src/platforms/gba/lib/libtonc/src/tonc_schr4r.c +462 -0
  775. package/src/platforms/gba/lib/libtonc/src/tonc_surface.c +105 -0
  776. package/src/platforms/gba/lib/libtonc/src/tonc_video.c +33 -0
  777. package/src/platforms/gba/lib/libtonc/src/tte/ase_drawg.c +83 -0
  778. package/src/platforms/gba/lib/libtonc/src/tte/bmp16_drawg.c +72 -0
  779. package/src/platforms/gba/lib/libtonc/src/tte/bmp16_drawg_b1cs.c +92 -0
  780. package/src/platforms/gba/lib/libtonc/src/tte/bmp8_drawg.c +71 -0
  781. package/src/platforms/gba/lib/libtonc/src/tte/bmp8_drawg_b1cs.c +104 -0
  782. package/src/platforms/gba/lib/libtonc/src/tte/bmp8_drawg_b1cts_fast.s +115 -0
  783. package/src/platforms/gba/lib/libtonc/src/tte/chr4c_drawg_b1cts.c +76 -0
  784. package/src/platforms/gba/lib/libtonc/src/tte/chr4c_drawg_b1cts_fast.s +128 -0
  785. package/src/platforms/gba/lib/libtonc/src/tte/chr4c_drawg_b4cts.c +67 -0
  786. package/src/platforms/gba/lib/libtonc/src/tte/chr4c_drawg_b4cts_fast.s +127 -0
  787. package/src/platforms/gba/lib/libtonc/src/tte/chr4r_drawg_b1cts.c +80 -0
  788. package/src/platforms/gba/lib/libtonc/src/tte/chr4r_drawg_b1cts_fast.s +145 -0
  789. package/src/platforms/gba/lib/libtonc/src/tte/obj_drawg.c +61 -0
  790. package/src/platforms/gba/lib/libtonc/src/tte/se_drawg.c +110 -0
  791. package/src/platforms/gba/lib/libtonc/src/tte/tte_init_ase.c +87 -0
  792. package/src/platforms/gba/lib/libtonc/src/tte/tte_init_bmp.c +118 -0
  793. package/src/platforms/gba/lib/libtonc/src/tte/tte_init_chr4c.c +86 -0
  794. package/src/platforms/gba/lib/libtonc/src/tte/tte_init_chr4r.c +87 -0
  795. package/src/platforms/gba/lib/libtonc/src/tte/tte_init_obj.c +84 -0
  796. package/src/platforms/gba/lib/libtonc/src/tte/tte_init_se.c +96 -0
  797. package/src/platforms/gba/lib/libtonc/src/tte/tte_iohook.c +264 -0
  798. package/src/platforms/gba/lib/libtonc/src/tte/tte_main.c +756 -0
  799. package/src/platforms/gba/lib/libtonc/src/tte/tte_types.s +119 -0
  800. package/src/platforms/gba/lib/maxmod/LICENSE-MAXMOD +23 -0
  801. package/src/platforms/gba/lib/maxmod/asm_include/mp_defs.inc +117 -0
  802. package/src/platforms/gba/lib/maxmod/asm_include/mp_format_mas.inc +108 -0
  803. package/src/platforms/gba/lib/maxmod/asm_include/mp_macros.inc +195 -0
  804. package/src/platforms/gba/lib/maxmod/asm_include/mp_mas.inc +40 -0
  805. package/src/platforms/gba/lib/maxmod/asm_include/mp_mas_structs.inc +189 -0
  806. package/src/platforms/gba/lib/maxmod/asm_include/mp_mixer_ds.inc +46 -0
  807. package/src/platforms/gba/lib/maxmod/asm_include/mp_mixer_gba.inc +42 -0
  808. package/src/platforms/gba/lib/maxmod/asm_include/swi_gba.inc +23 -0
  809. package/src/platforms/gba/lib/maxmod/include/maxmod.h +412 -0
  810. package/src/platforms/gba/lib/maxmod/include/mm_types.h +333 -0
  811. package/src/platforms/gba/lib/maxmod/maxmod.seed.a +0 -0
  812. package/src/platforms/gba/lib/maxmod/maxmod.seed.hash +1 -0
  813. package/src/platforms/gba/lib/maxmod/music/chiptune.xm +0 -0
  814. package/src/platforms/gba/lib/maxmod/music/chiptune_soundbank.bin +0 -0
  815. package/src/platforms/gba/lib/maxmod/music/chiptune_soundbank.h +4 -0
  816. package/src/platforms/gba/lib/maxmod/music/make_chiptune_xm.js +203 -0
  817. package/src/platforms/gba/lib/maxmod/source/mm_effect.s +767 -0
  818. package/src/platforms/gba/lib/maxmod/source/mm_main.s +115 -0
  819. package/src/platforms/gba/lib/maxmod/source/mm_mas.s +4990 -0
  820. package/src/platforms/gba/lib/maxmod/source/mm_mas_arm.s +612 -0
  821. package/src/platforms/gba/lib/maxmod/source_gba/mm_init_default.s +98 -0
  822. package/src/platforms/gba/lib/maxmod/source_gba/mm_main_gba.s +292 -0
  823. package/src/platforms/gba/lib/maxmod/source_gba/mm_mixer_gba.s +1367 -0
  824. package/src/platforms/gba/lib/sysbase/gba_iosupport.c +138 -0
  825. package/src/platforms/gbc/MENTAL_MODEL.md +178 -0
  826. package/src/platforms/gbc/TROUBLESHOOTING.md +142 -0
  827. package/src/platforms/gbc/UPSTREAM_SOURCES.md +60 -0
  828. package/src/platforms/gbc/lib/c/LICENSE-HUGEDRIVER +25 -0
  829. package/src/platforms/gbc/lib/c/README.md +122 -0
  830. package/src/platforms/gbc/lib/c/SDCC_GOTCHAS.md +190 -0
  831. package/src/platforms/gbc/lib/c/gb_crt0.s +163 -0
  832. package/src/platforms/gbc/lib/c/gb_hardware.h +113 -0
  833. package/src/platforms/gbc/lib/c/gb_runtime.c +284 -0
  834. package/src/platforms/gbc/lib/c/gb_runtime.h +145 -0
  835. package/src/platforms/gbc/lib/c/hUGEDriver.c +191 -0
  836. package/src/platforms/gbc/lib/c/hUGEDriver.h +95 -0
  837. package/src/platforms/gbc/lib/c/hUGEDriver.upstream.asm +1908 -0
  838. package/src/platforms/gbc/lib/c/lcd_init.c +19 -0
  839. package/src/platforms/gbc/lib/c/patch-header.js +154 -0
  840. package/src/platforms/gbc/lib/c/song_data.c +88 -0
  841. package/src/platforms/gbc/lib/c/unroll.h +52 -0
  842. package/src/platforms/gbc/lib/c/wait_vblank.c +14 -0
  843. package/src/platforms/gbc/song.js +3 -0
  844. package/src/platforms/genesis/MENTAL_MODEL.md +306 -0
  845. package/src/platforms/genesis/TROUBLESHOOTING.md +226 -0
  846. package/src/platforms/genesis/UPSTREAM_SOURCES.md +53 -0
  847. package/src/platforms/genesis/image-to-tilemap.js +351 -0
  848. package/src/platforms/genesis/lib/README.md +160 -0
  849. package/src/platforms/genesis/lib/c/crtbegin.o +0 -0
  850. package/src/platforms/genesis/lib/c/crtend.o +0 -0
  851. package/src/platforms/genesis/lib/c/genesis.ld +44 -0
  852. package/src/platforms/genesis/lib/c/genesis_sfx.c +51 -0
  853. package/src/platforms/genesis/lib/c/genesis_sfx.h +49 -0
  854. package/src/platforms/genesis/lib/c/libc.a +0 -0
  855. package/src/platforms/genesis/lib/c/libgcc.a +0 -0
  856. package/src/platforms/genesis/lib/c/libm.a +0 -0
  857. package/src/platforms/genesis/lib/c/sega.s +71 -0
  858. package/src/platforms/genesis/lib/header.s +96 -0
  859. package/src/platforms/genesis/lib/nmi_safe.s +79 -0
  860. package/src/platforms/genesis/lib/pad_read.s +104 -0
  861. package/src/platforms/genesis/lib/sgdk/COPYING.RUNTIME +73 -0
  862. package/src/platforms/genesis/lib/sgdk/LICENSE +12 -0
  863. package/src/platforms/genesis/lib/sgdk/include/asm.h +52 -0
  864. package/src/platforms/genesis/lib/sgdk/include/asm_mac.i +9 -0
  865. package/src/platforms/genesis/lib/sgdk/include/bmp.h +690 -0
  866. package/src/platforms/genesis/lib/sgdk/include/config.h +208 -0
  867. package/src/platforms/genesis/lib/sgdk/include/dma.h +542 -0
  868. package/src/platforms/genesis/lib/sgdk/include/ext/console.h +387 -0
  869. package/src/platforms/genesis/lib/sgdk/include/ext/everdrive.h +116 -0
  870. package/src/platforms/genesis/lib/sgdk/include/ext/fat16.h +84 -0
  871. package/src/platforms/genesis/lib/sgdk/include/ext/flash-save/flash.h +164 -0
  872. package/src/platforms/genesis/lib/sgdk/include/ext/flash-save/saveman.h +177 -0
  873. package/src/platforms/genesis/lib/sgdk/include/ext/link_cable.h +316 -0
  874. package/src/platforms/genesis/lib/sgdk/include/ext/minimusic/minimus.h +29 -0
  875. package/src/platforms/genesis/lib/sgdk/include/ext/mw/16c550.h +221 -0
  876. package/src/platforms/genesis/lib/sgdk/include/ext/mw/comm.h +93 -0
  877. package/src/platforms/genesis/lib/sgdk/include/ext/mw/gamejolt.h +541 -0
  878. package/src/platforms/genesis/lib/sgdk/include/ext/mw/jsmn.h +471 -0
  879. package/src/platforms/genesis/lib/sgdk/include/ext/mw/json.h +122 -0
  880. package/src/platforms/genesis/lib/sgdk/include/ext/mw/lsd.h +172 -0
  881. package/src/platforms/genesis/lib/sgdk/include/ext/mw/megawifi.h +984 -0
  882. package/src/platforms/genesis/lib/sgdk/include/ext/mw/mw-msg.h +392 -0
  883. package/src/platforms/genesis/lib/sgdk/include/ext/mw/ssf_ed_pro.h +38 -0
  884. package/src/platforms/genesis/lib/sgdk/include/ext/mw/ssf_ed_x7.h +73 -0
  885. package/src/platforms/genesis/lib/sgdk/include/ext/serial/buffer.h +8 -0
  886. package/src/platforms/genesis/lib/sgdk/include/ext/serial/serial.h +133 -0
  887. package/src/platforms/genesis/lib/sgdk/include/ext/stb/stb_sprintf.h +1864 -0
  888. package/src/platforms/genesis/lib/sgdk/include/genesis.h +92 -0
  889. package/src/platforms/genesis/lib/sgdk/include/joy.h +482 -0
  890. package/src/platforms/genesis/lib/sgdk/include/kdebug.h +21 -0
  891. package/src/platforms/genesis/lib/sgdk/include/map.h +409 -0
  892. package/src/platforms/genesis/lib/sgdk/include/mapper.h +186 -0
  893. package/src/platforms/genesis/lib/sgdk/include/maths.h +1071 -0
  894. package/src/platforms/genesis/lib/sgdk/include/maths3D.h +480 -0
  895. package/src/platforms/genesis/lib/sgdk/include/memory.h +346 -0
  896. package/src/platforms/genesis/lib/sgdk/include/memory_base.h +37 -0
  897. package/src/platforms/genesis/lib/sgdk/include/object.h +171 -0
  898. package/src/platforms/genesis/lib/sgdk/include/pal.h +500 -0
  899. package/src/platforms/genesis/lib/sgdk/include/pool.h +171 -0
  900. package/src/platforms/genesis/lib/sgdk/include/psg.h +153 -0
  901. package/src/platforms/genesis/lib/sgdk/include/snd/pcm/snd_dpcm2.h +79 -0
  902. package/src/platforms/genesis/lib/sgdk/include/snd/pcm/snd_pcm.h +98 -0
  903. package/src/platforms/genesis/lib/sgdk/include/snd/pcm/snd_pcm4.h +125 -0
  904. package/src/platforms/genesis/lib/sgdk/include/snd/pcm/tab_vol.h +6 -0
  905. package/src/platforms/genesis/lib/sgdk/include/snd/smp_null.h +6 -0
  906. package/src/platforms/genesis/lib/sgdk/include/snd/smp_null_dpcm.h +6 -0
  907. package/src/platforms/genesis/lib/sgdk/include/snd/sound.h +70 -0
  908. package/src/platforms/genesis/lib/sgdk/include/snd/xgm.h +399 -0
  909. package/src/platforms/genesis/lib/sgdk/include/snd/xgm2.h +389 -0
  910. package/src/platforms/genesis/lib/sgdk/include/snd/z80_def.i80 +41 -0
  911. package/src/platforms/genesis/lib/sgdk/include/snd/z80_fct.i80 +83 -0
  912. package/src/platforms/genesis/lib/sgdk/include/snd/z80_mac.i80 +1476 -0
  913. package/src/platforms/genesis/lib/sgdk/include/sprite_eng.h +1095 -0
  914. package/src/platforms/genesis/lib/sgdk/include/sprite_eng_legacy.h +1030 -0
  915. package/src/platforms/genesis/lib/sgdk/include/sram.h +110 -0
  916. package/src/platforms/genesis/lib/sgdk/include/string.h +349 -0
  917. package/src/platforms/genesis/lib/sgdk/include/sys.h +511 -0
  918. package/src/platforms/genesis/lib/sgdk/include/tab_cnv.h +19 -0
  919. package/src/platforms/genesis/lib/sgdk/include/task.h +77 -0
  920. package/src/platforms/genesis/lib/sgdk/include/task_cst.h +33 -0
  921. package/src/platforms/genesis/lib/sgdk/include/timer.h +132 -0
  922. package/src/platforms/genesis/lib/sgdk/include/tools.h +450 -0
  923. package/src/platforms/genesis/lib/sgdk/include/types.h +320 -0
  924. package/src/platforms/genesis/lib/sgdk/include/vdp.h +1150 -0
  925. package/src/platforms/genesis/lib/sgdk/include/vdp_bg.h +723 -0
  926. package/src/platforms/genesis/lib/sgdk/include/vdp_pal.h +101 -0
  927. package/src/platforms/genesis/lib/sgdk/include/vdp_spr.h +448 -0
  928. package/src/platforms/genesis/lib/sgdk/include/vdp_tile.h +1136 -0
  929. package/src/platforms/genesis/lib/sgdk/include/vram.h +270 -0
  930. package/src/platforms/genesis/lib/sgdk/include/ym2612.h +87 -0
  931. package/src/platforms/genesis/lib/sgdk/include/z80_ctrl.h +420 -0
  932. package/src/platforms/genesis/lib/sgdk/libmd.seed.a +0 -0
  933. package/src/platforms/genesis/lib/sgdk/libmd.seed.hash +1 -0
  934. package/src/platforms/genesis/lib/sgdk/md.ld +120 -0
  935. package/src/platforms/genesis/lib/sgdk/music/demo.vgm +0 -0
  936. package/src/platforms/genesis/lib/sgdk/music/demo.xgc +0 -0
  937. package/src/platforms/genesis/lib/sgdk/music/demo.xgm +0 -0
  938. package/src/platforms/genesis/lib/sgdk/res/image/font_default.png +0 -0
  939. package/src/platforms/genesis/lib/sgdk/res/image/sgdk_logo.png +0 -0
  940. package/src/platforms/genesis/lib/sgdk/res/libres.h +10 -0
  941. package/src/platforms/genesis/lib/sgdk/res/libres.res +5 -0
  942. package/src/platforms/genesis/lib/sgdk/res/libres.s +166 -0
  943. package/src/platforms/genesis/lib/sgdk/res/sound/stop_xgm.bin +0 -0
  944. package/src/platforms/genesis/lib/sgdk/rom_header.c +33 -0
  945. package/src/platforms/genesis/lib/sgdk/sega.preprocessed.s +364 -0
  946. package/src/platforms/genesis/lib/sgdk/sega.s +365 -0
  947. package/src/platforms/genesis/lib/sgdk/src/bmp.c +1539 -0
  948. package/src/platforms/genesis/lib/sgdk/src/bmp_a.s +3477 -0
  949. package/src/platforms/genesis/lib/sgdk/src/boot/rom_header.c +33 -0
  950. package/src/platforms/genesis/lib/sgdk/src/boot/sega.s +365 -0
  951. package/src/platforms/genesis/lib/sgdk/src/dma.c +782 -0
  952. package/src/platforms/genesis/lib/sgdk/src/dma_a.s +23 -0
  953. package/src/platforms/genesis/lib/sgdk/src/error_a.s +376 -0
  954. package/src/platforms/genesis/lib/sgdk/src/ext/console.c +490 -0
  955. package/src/platforms/genesis/lib/sgdk/src/ext/everdrive.c +285 -0
  956. package/src/platforms/genesis/lib/sgdk/src/ext/fat16.c +610 -0
  957. package/src/platforms/genesis/lib/sgdk/src/ext/flash-save/README.md +112 -0
  958. package/src/platforms/genesis/lib/sgdk/src/ext/flash-save/flash.c +300 -0
  959. package/src/platforms/genesis/lib/sgdk/src/ext/flash-save/saveman.c +641 -0
  960. package/src/platforms/genesis/lib/sgdk/src/ext/link_cable.c +1758 -0
  961. package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/CHANGELOG.md +31 -0
  962. package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/LICENSE.txt +17 -0
  963. package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/README.md +18 -0
  964. package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/data.z80 +148 -0
  965. package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/define.z80 +173 -0
  966. package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/doc/api-c.md +80 -0
  967. package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/doc/format.md +132 -0
  968. package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/doc/teradrive.md +33 -0
  969. package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/fm.z80 +363 -0
  970. package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/main.z80 +433 -0
  971. package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/minimus.c +129 -0
  972. package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/minimus_drv.s80 +17 -0
  973. package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/psg.z80 +231 -0
  974. package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/track.z80 +398 -0
  975. package/src/platforms/genesis/lib/sgdk/src/ext/minimusic/util.z80 +98 -0
  976. package/src/platforms/genesis/lib/sgdk/src/ext/mw/16c550.c +84 -0
  977. package/src/platforms/genesis/lib/sgdk/src/ext/mw/README.md +849 -0
  978. package/src/platforms/genesis/lib/sgdk/src/ext/mw/comm.c +141 -0
  979. package/src/platforms/genesis/lib/sgdk/src/ext/mw/gamejolt.c +758 -0
  980. package/src/platforms/genesis/lib/sgdk/src/ext/mw/json.c +153 -0
  981. package/src/platforms/genesis/lib/sgdk/src/ext/mw/lsd.c +364 -0
  982. package/src/platforms/genesis/lib/sgdk/src/ext/mw/megawifi.c +1501 -0
  983. package/src/platforms/genesis/lib/sgdk/src/ext/mw/ssf_ed_pro.c +98 -0
  984. package/src/platforms/genesis/lib/sgdk/src/ext/mw/ssf_ed_x7.c +67 -0
  985. package/src/platforms/genesis/lib/sgdk/src/ext/serial/buffer.c +69 -0
  986. package/src/platforms/genesis/lib/sgdk/src/ext/serial/serial.c +158 -0
  987. package/src/platforms/genesis/lib/sgdk/src/joy.c +1361 -0
  988. package/src/platforms/genesis/lib/sgdk/src/kdebug.s +109 -0
  989. package/src/platforms/genesis/lib/sgdk/src/map.c +1915 -0
  990. package/src/platforms/genesis/lib/sgdk/src/mapper.c +280 -0
  991. package/src/platforms/genesis/lib/sgdk/src/maths.c +878 -0
  992. package/src/platforms/genesis/lib/sgdk/src/maths3D.c +480 -0
  993. package/src/platforms/genesis/lib/sgdk/src/maths3D_a.s +205 -0
  994. package/src/platforms/genesis/lib/sgdk/src/memory.c +760 -0
  995. package/src/platforms/genesis/lib/sgdk/src/memory_a.s +306 -0
  996. package/src/platforms/genesis/lib/sgdk/src/object.c +111 -0
  997. package/src/platforms/genesis/lib/sgdk/src/pal.c +484 -0
  998. package/src/platforms/genesis/lib/sgdk/src/pool.c +234 -0
  999. package/src/platforms/genesis/lib/sgdk/src/psg.c +82 -0
  1000. package/src/platforms/genesis/lib/sgdk/src/snd/drv_null.s80 +27 -0
  1001. package/src/platforms/genesis/lib/sgdk/src/snd/drv_xgm.s80 +3037 -0
  1002. package/src/platforms/genesis/lib/sgdk/src/snd/pcm/drv_dpcm2.s80 +984 -0
  1003. package/src/platforms/genesis/lib/sgdk/src/snd/pcm/drv_pcm.s80 +592 -0
  1004. package/src/platforms/genesis/lib/sgdk/src/snd/pcm/drv_pcm4.s80 +699 -0
  1005. package/src/platforms/genesis/lib/sgdk/src/snd/pcm/snd_dpcm2.c +172 -0
  1006. package/src/platforms/genesis/lib/sgdk/src/snd/pcm/snd_pcm.c +152 -0
  1007. package/src/platforms/genesis/lib/sgdk/src/snd/pcm/snd_pcm4.c +213 -0
  1008. package/src/platforms/genesis/lib/sgdk/src/snd/pcm/tab_vol.c +277 -0
  1009. package/src/platforms/genesis/lib/sgdk/src/snd/smp_null.s +22 -0
  1010. package/src/platforms/genesis/lib/sgdk/src/snd/smp_null_dpcm.s +15 -0
  1011. package/src/platforms/genesis/lib/sgdk/src/snd/sound.c +33 -0
  1012. package/src/platforms/genesis/lib/sgdk/src/snd/xgm.c +683 -0
  1013. package/src/platforms/genesis/lib/sgdk/src/snd/xgm2/drv_xgm2.s80 +993 -0
  1014. package/src/platforms/genesis/lib/sgdk/src/snd/xgm2/drv_xgm2_fct.i80 +611 -0
  1015. package/src/platforms/genesis/lib/sgdk/src/snd/xgm2/drv_xgm2_mac.i80 +133 -0
  1016. package/src/platforms/genesis/lib/sgdk/src/snd/xgm2/drv_xgm2_pcm_fct.i80 +114 -0
  1017. package/src/platforms/genesis/lib/sgdk/src/snd/xgm2/drv_xgm2_pcm_mac.i80 +1444 -0
  1018. package/src/platforms/genesis/lib/sgdk/src/snd/xgm2/drv_xgm2_psg_fct.i80 +491 -0
  1019. package/src/platforms/genesis/lib/sgdk/src/snd/xgm2/drv_xgm2_psg_mac.i80 +43 -0
  1020. package/src/platforms/genesis/lib/sgdk/src/snd/xgm2/drv_xgm2_ym_fct.i80 +1664 -0
  1021. package/src/platforms/genesis/lib/sgdk/src/snd/xgm2/drv_xgm2_ym_mac.i80 +295 -0
  1022. package/src/platforms/genesis/lib/sgdk/src/snd/xgm2.c +1083 -0
  1023. package/src/platforms/genesis/lib/sgdk/src/sprite_eng.c +2256 -0
  1024. package/src/platforms/genesis/lib/sgdk/src/sprite_eng_legacy.c +2309 -0
  1025. package/src/platforms/genesis/lib/sgdk/src/sram.c +30 -0
  1026. package/src/platforms/genesis/lib/sgdk/src/sram_a.s +41 -0
  1027. package/src/platforms/genesis/lib/sgdk/src/string.c +720 -0
  1028. package/src/platforms/genesis/lib/sgdk/src/sys.c +1053 -0
  1029. package/src/platforms/genesis/lib/sgdk/src/sys_a.s +74 -0
  1030. package/src/platforms/genesis/lib/sgdk/src/tab_cnv.c +129 -0
  1031. package/src/platforms/genesis/lib/sgdk/src/tab_log10.c +8201 -0
  1032. package/src/platforms/genesis/lib/sgdk/src/tab_log2.c +8201 -0
  1033. package/src/platforms/genesis/lib/sgdk/src/tab_sin.c +2058 -0
  1034. package/src/platforms/genesis/lib/sgdk/src/tab_sqrt.c +8201 -0
  1035. package/src/platforms/genesis/lib/sgdk/src/task.s +148 -0
  1036. package/src/platforms/genesis/lib/sgdk/src/timer.c +201 -0
  1037. package/src/platforms/genesis/lib/sgdk/src/tools.c +1299 -0
  1038. package/src/platforms/genesis/lib/sgdk/src/tools_a.s +979 -0
  1039. package/src/platforms/genesis/lib/sgdk/src/types.c +18 -0
  1040. package/src/platforms/genesis/lib/sgdk/src/vdp.c +1060 -0
  1041. package/src/platforms/genesis/lib/sgdk/src/vdp_bg.c +511 -0
  1042. package/src/platforms/genesis/lib/sgdk/src/vdp_spr.c +322 -0
  1043. package/src/platforms/genesis/lib/sgdk/src/vdp_tile.c +1011 -0
  1044. package/src/platforms/genesis/lib/sgdk/src/vdp_tile_a.s +68 -0
  1045. package/src/platforms/genesis/lib/sgdk/src/vram.c +273 -0
  1046. package/src/platforms/genesis/lib/sgdk/src/ym2612.c +175 -0
  1047. package/src/platforms/genesis/lib/sgdk/src/z80_ctrl.c +334 -0
  1048. package/src/platforms/genesis/lib/sprite_table.s +129 -0
  1049. package/src/platforms/genesis/lib/vblank_wait.s +73 -0
  1050. package/src/platforms/genesis/lib/vdp_init.s +85 -0
  1051. package/src/platforms/genesis/lib/wram.s +88 -0
  1052. package/src/platforms/genesis/lib/z80_bootstrap.s +102 -0
  1053. package/src/platforms/genesis/vdp.js +548 -0
  1054. package/src/platforms/genesis/xgm2-pcm.js +165 -0
  1055. package/src/platforms/gg/MENTAL_MODEL.md +174 -0
  1056. package/src/platforms/gg/TROUBLESHOOTING.md +105 -0
  1057. package/src/platforms/gg/UPSTREAM_SOURCES.md +36 -0
  1058. package/src/platforms/gg/lib/c/gg_crt0.s +112 -0
  1059. package/src/platforms/gg/lib/c/gg_hw.h +62 -0
  1060. package/src/platforms/gg/lib/c/gg_music.c +155 -0
  1061. package/src/platforms/gg/lib/c/gg_music.h +89 -0
  1062. package/src/platforms/gg/lib/c/gg_sfx.c +82 -0
  1063. package/src/platforms/gg/lib/c/gg_sfx.h +40 -0
  1064. package/src/platforms/gg/lib/c/joypad_read.c +22 -0
  1065. package/src/platforms/gg/lib/c/load_palette.c +20 -0
  1066. package/src/platforms/gg/lib/c/load_tiles.c +32 -0
  1067. package/src/platforms/gg/lib/c/sprite_table.c +60 -0
  1068. package/src/platforms/gg/lib/c/vblank_wait.c +10 -0
  1069. package/src/platforms/gg/lib/c/vdp_init.c +58 -0
  1070. package/src/platforms/gg/song.js +189 -0
  1071. package/src/platforms/index.js +7 -0
  1072. package/src/platforms/lynx/MENTAL_MODEL.md +248 -0
  1073. package/src/platforms/lynx/TROUBLESHOOTING.md +105 -0
  1074. package/src/platforms/lynx/UPSTREAM_SOURCES.md +66 -0
  1075. package/src/platforms/lynx/lib/c/lynx_music.c +63 -0
  1076. package/src/platforms/lynx/lib/c/lynx_music.h +16 -0
  1077. package/src/platforms/lynx/lib/c/lynx_sfx.c +147 -0
  1078. package/src/platforms/lynx/lib/c/lynx_sfx.h +59 -0
  1079. package/src/platforms/lynx/lib/cc65-src/bllhdr.s +18 -0
  1080. package/src/platforms/lynx/lib/cc65-src/bootldr.s +195 -0
  1081. package/src/platforms/lynx/lib/cc65-src/cgetc.s +69 -0
  1082. package/src/platforms/lynx/lib/cc65-src/clock.s +87 -0
  1083. package/src/platforms/lynx/lib/cc65-src/crt0.s +135 -0
  1084. package/src/platforms/lynx/lib/cc65-src/defdir.s +29 -0
  1085. package/src/platforms/lynx/lib/cc65-src/eeprom.s +255 -0
  1086. package/src/platforms/lynx/lib/cc65-src/eeprom46.s +204 -0
  1087. package/src/platforms/lynx/lib/cc65-src/eeprom66.s +227 -0
  1088. package/src/platforms/lynx/lib/cc65-src/eeprom86.s +236 -0
  1089. package/src/platforms/lynx/lib/cc65-src/exec.s +34 -0
  1090. package/src/platforms/lynx/lib/cc65-src/exehdr.s +27 -0
  1091. package/src/platforms/lynx/lib/cc65-src/extzp.inc +23 -0
  1092. package/src/platforms/lynx/lib/cc65-src/extzp.s +30 -0
  1093. package/src/platforms/lynx/lib/cc65-src/irq.s +45 -0
  1094. package/src/platforms/lynx/lib/cc65-src/joy/lynx-stdjoy.s +93 -0
  1095. package/src/platforms/lynx/lib/cc65-src/joy_stat_stddrv.s +14 -0
  1096. package/src/platforms/lynx/lib/cc65-src/kbhit.s +56 -0
  1097. package/src/platforms/lynx/lib/cc65-src/libref.s +9 -0
  1098. package/src/platforms/lynx/lib/cc65-src/load.s +41 -0
  1099. package/src/platforms/lynx/lib/cc65-src/lseek.s +58 -0
  1100. package/src/platforms/lynx/lib/cc65-src/lynx-cart.s +98 -0
  1101. package/src/platforms/lynx/lib/cc65-src/lynx-snd.s +1270 -0
  1102. package/src/platforms/lynx/lib/cc65-src/mainargs.s +24 -0
  1103. package/src/platforms/lynx/lib/cc65-src/open.s +136 -0
  1104. package/src/platforms/lynx/lib/cc65-src/oserror.s +14 -0
  1105. package/src/platforms/lynx/lib/cc65-src/read.s +44 -0
  1106. package/src/platforms/lynx/lib/cc65-src/ser/lynx-comlynx.s +404 -0
  1107. package/src/platforms/lynx/lib/cc65-src/ser_stat_stddrv.s +14 -0
  1108. package/src/platforms/lynx/lib/cc65-src/sysuname.s +39 -0
  1109. package/src/platforms/lynx/lib/cc65-src/tgi/lynx-160-102-16.s +1075 -0
  1110. package/src/platforms/lynx/lib/cc65-src/tgi_colors.s +9 -0
  1111. package/src/platforms/lynx/lib/cc65-src/tgi_irq.s +11 -0
  1112. package/src/platforms/lynx/lib/cc65-src/tgi_stat_stddrv.s +14 -0
  1113. package/src/platforms/lynx/lib/cc65-src/tgi_stddrv.s +13 -0
  1114. package/src/platforms/lynx/lib/cc65-src/uploader.s +81 -0
  1115. package/src/platforms/lynx/song.js +291 -0
  1116. package/src/platforms/msx/MENTAL_MODEL.md +115 -0
  1117. package/src/platforms/msx/TROUBLESHOOTING.md +62 -0
  1118. package/src/platforms/msx/UPSTREAM_SOURCES.md +46 -0
  1119. package/src/platforms/msx/image-to-tilemap.js +103 -0
  1120. package/src/platforms/msx/lib/c/hello_msx.c +51 -0
  1121. package/src/platforms/msx/lib/c/msx_crt0.s +74 -0
  1122. package/src/platforms/msx/lib/c/msx_hw.h +92 -0
  1123. package/src/platforms/msx/lib/c/msx_vdp.c +150 -0
  1124. package/src/platforms/msx/tiles.js +99 -0
  1125. package/src/platforms/msx/vdp.js +160 -0
  1126. package/src/platforms/nes/MENTAL_MODEL.md +323 -0
  1127. package/src/platforms/nes/TROUBLESHOOTING.md +319 -0
  1128. package/src/platforms/nes/UPSTREAM_SOURCES.md +31 -0
  1129. package/src/platforms/nes/image-to-chr.js +195 -0
  1130. package/src/platforms/nes/image-to-tilemap.js +415 -0
  1131. package/src/platforms/nes/lib/README.md +40 -0
  1132. package/src/platforms/nes/lib/asm/LICENSE-FAMITONE +40 -0
  1133. package/src/platforms/nes/lib/asm/chr_ram_header.s +32 -0
  1134. package/src/platforms/nes/lib/asm/famitone2.s +1258 -0
  1135. package/src/platforms/nes/lib/asm/famitone_bridge.s +50 -0
  1136. package/src/platforms/nes/lib/asm/music_data.s +238 -0
  1137. package/src/platforms/nes/lib/c/chr_ram_runtime_hello_sprite.c +81 -0
  1138. package/src/platforms/nes/lib/c/chr_ram_runtime_hud_row.c +101 -0
  1139. package/src/platforms/nes/lib/c/nes_runtime.c +347 -0
  1140. package/src/platforms/nes/lib/c/nes_runtime.h +153 -0
  1141. package/src/platforms/nes/lib/c/nmi_handler.c +51 -0
  1142. package/src/platforms/nes/lib/c/nmi_trampoline.s +25 -0
  1143. package/src/platforms/nes/lib/cc65-src/Makefile.inc +9 -0
  1144. package/src/platforms/nes/lib/cc65-src/_scrsize.s +24 -0
  1145. package/src/platforms/nes/lib/cc65-src/cclear.s +29 -0
  1146. package/src/platforms/nes/lib/cc65-src/chline.s +31 -0
  1147. package/src/platforms/nes/lib/cc65-src/clock.s +31 -0
  1148. package/src/platforms/nes/lib/cc65-src/clrscr.s +72 -0
  1149. package/src/platforms/nes/lib/cc65-src/color.s +68 -0
  1150. package/src/platforms/nes/lib/cc65-src/cpeekc.s +37 -0
  1151. package/src/platforms/nes/lib/cc65-src/cpeekcolor.s +8 -0
  1152. package/src/platforms/nes/lib/cc65-src/cpeekrevers.s +37 -0
  1153. package/src/platforms/nes/lib/cc65-src/cputc.s +95 -0
  1154. package/src/platforms/nes/lib/cc65-src/crt0.s +180 -0
  1155. package/src/platforms/nes/lib/cc65-src/cvline.s +31 -0
  1156. package/src/platforms/nes/lib/cc65-src/get_tv.s +37 -0
  1157. package/src/platforms/nes/lib/cc65-src/gotox.s +21 -0
  1158. package/src/platforms/nes/lib/cc65-src/gotoxy.s +22 -0
  1159. package/src/platforms/nes/lib/cc65-src/gotoy.s +22 -0
  1160. package/src/platforms/nes/lib/cc65-src/irq.s +19 -0
  1161. package/src/platforms/nes/lib/cc65-src/joy/nes-stdjoy.s +102 -0
  1162. package/src/platforms/nes/lib/cc65-src/joy_stat_stddrv.s +14 -0
  1163. package/src/platforms/nes/lib/cc65-src/libref.s +9 -0
  1164. package/src/platforms/nes/lib/cc65-src/mainargs.s +24 -0
  1165. package/src/platforms/nes/lib/cc65-src/neschar.s +4616 -0
  1166. package/src/platforms/nes/lib/cc65-src/ppu.s +158 -0
  1167. package/src/platforms/nes/lib/cc65-src/ppubuf.s +117 -0
  1168. package/src/platforms/nes/lib/cc65-src/randomize.s +18 -0
  1169. package/src/platforms/nes/lib/cc65-src/revers.s +27 -0
  1170. package/src/platforms/nes/lib/cc65-src/setcursor.s +37 -0
  1171. package/src/platforms/nes/lib/cc65-src/sysuname.s +39 -0
  1172. package/src/platforms/nes/lib/cc65-src/tgi/nes-64-56-2.s +480 -0
  1173. package/src/platforms/nes/lib/cc65-src/tgi_stat_stddrv.s +14 -0
  1174. package/src/platforms/nes/lib/cc65-src/tgi_stddrv.s +13 -0
  1175. package/src/platforms/nes/lib/cc65-src/waitvsync.s +18 -0
  1176. package/src/platforms/nes/lib/cc65-src/wherex.s +19 -0
  1177. package/src/platforms/nes/lib/cc65-src/wherey.s +19 -0
  1178. package/src/platforms/nes/lib/clear_nametable.s +38 -0
  1179. package/src/platforms/nes/lib/clear_oam.s +18 -0
  1180. package/src/platforms/nes/lib/load_palette.s +31 -0
  1181. package/src/platforms/nes/lib/nmi_safe.s +65 -0
  1182. package/src/platforms/nes/lib/oam_dma.s +16 -0
  1183. package/src/platforms/nes/lib/read_pad.s +46 -0
  1184. package/src/platforms/nes/lib/reset.s +46 -0
  1185. package/src/platforms/nes/lib/sprite_table_populate.s +75 -0
  1186. package/src/platforms/nes/lib/wait_vblank.s +12 -0
  1187. package/src/platforms/nes/palette.js +39 -0
  1188. package/src/platforms/nes/ppu.js +448 -0
  1189. package/src/platforms/pce/MENTAL_MODEL.md +98 -0
  1190. package/src/platforms/pce/TROUBLESHOOTING.md +54 -0
  1191. package/src/platforms/pce/UPSTREAM_SOURCES.md +38 -0
  1192. package/src/platforms/pce/image-to-tilemap.js +123 -0
  1193. package/src/platforms/pce/lib/c/hello_pce.c +37 -0
  1194. package/src/platforms/pce/lib/c/pce_hw.h +130 -0
  1195. package/src/platforms/pce/lib/c/pce_input.c +36 -0
  1196. package/src/platforms/pce/lib/c/pce_sound.c +53 -0
  1197. package/src/platforms/pce/lib/c/pce_video.c +113 -0
  1198. package/src/platforms/pce/tiles.js +92 -0
  1199. package/src/platforms/pce/vce.js +59 -0
  1200. package/src/platforms/pce/vdc.js +52 -0
  1201. package/src/platforms/sms/MENTAL_MODEL.md +286 -0
  1202. package/src/platforms/sms/TROUBLESHOOTING.md +140 -0
  1203. package/src/platforms/sms/UPSTREAM_SOURCES.md +29 -0
  1204. package/src/platforms/sms/image-to-tilemap.js +260 -0
  1205. package/src/platforms/sms/lib/README.md +117 -0
  1206. package/src/platforms/sms/lib/c/joypad_read.c +33 -0
  1207. package/src/platforms/sms/lib/c/load_palette.c +24 -0
  1208. package/src/platforms/sms/lib/c/load_tiles.c +32 -0
  1209. package/src/platforms/sms/lib/c/sms_crt0.s +101 -0
  1210. package/src/platforms/sms/lib/c/sms_hw.h +53 -0
  1211. package/src/platforms/sms/lib/c/sms_music.c +178 -0
  1212. package/src/platforms/sms/lib/c/sms_music.h +50 -0
  1213. package/src/platforms/sms/lib/c/sms_sfx.c +82 -0
  1214. package/src/platforms/sms/lib/c/sms_sfx.h +40 -0
  1215. package/src/platforms/sms/lib/c/sprite_table.c +60 -0
  1216. package/src/platforms/sms/lib/c/vblank_wait.c +10 -0
  1217. package/src/platforms/sms/lib/c/vdp_init.c +58 -0
  1218. package/src/platforms/sms/lib/header.s +33 -0
  1219. package/src/platforms/sms/lib/joypad_read.s +40 -0
  1220. package/src/platforms/sms/lib/load_palette.s +30 -0
  1221. package/src/platforms/sms/lib/load_tiles.s +50 -0
  1222. package/src/platforms/sms/lib/sprite_table.s +44 -0
  1223. package/src/platforms/sms/lib/vblank_wait.s +36 -0
  1224. package/src/platforms/sms/lib/vdp_init.s +47 -0
  1225. package/src/platforms/sms/song.js +217 -0
  1226. package/src/platforms/sms/vdp.js +530 -0
  1227. package/src/platforms/snes/MENTAL_MODEL.md +289 -0
  1228. package/src/platforms/snes/TROUBLESHOOTING.md +208 -0
  1229. package/src/platforms/snes/UPSTREAM_SOURCES.md +50 -0
  1230. package/src/platforms/snes/brr.js +208 -0
  1231. package/src/platforms/snes/image-to-tilemap.js +227 -0
  1232. package/src/platforms/snes/lib/audio/apu_blob.asm +228 -0
  1233. package/src/platforms/snes/lib/audio/apu_blob.bin +0 -0
  1234. package/src/platforms/snes/lib/audio/explosion.brr +0 -0
  1235. package/src/platforms/snes/lib/audio/sample_bank.bin +0 -0
  1236. package/src/platforms/snes/lib/audio/shoot.brr +0 -0
  1237. package/src/platforms/snes/lib/audio/spc_driver.asm +241 -0
  1238. package/src/platforms/snes/lib/audio_pipeline.asm +62 -0
  1239. package/src/platforms/snes/lib/c/crt0.asm +125 -0
  1240. package/src/platforms/snes/lib/c/hdr.asm +50 -0
  1241. package/src/platforms/snes/lib/c/snes_sfx.c +116 -0
  1242. package/src/platforms/snes/lib/c/snes_sfx.h +96 -0
  1243. package/src/platforms/snes/lib/c/snes_sfx_data.asm +25 -0
  1244. package/src/platforms/snes/lib/cgram_upload.asm +43 -0
  1245. package/src/platforms/snes/lib/lorom_header.asm +47 -0
  1246. package/src/platforms/snes/lib/lorom_multibank.asm +66 -0
  1247. package/src/platforms/snes/lib/nmi_safe.asm +77 -0
  1248. package/src/platforms/snes/lib/oam_upload.asm +45 -0
  1249. package/src/platforms/snes/lib/pad_read.asm +64 -0
  1250. package/src/platforms/snes/lib/pvsneslib/LICENSE +21 -0
  1251. package/src/platforms/snes/lib/pvsneslib/include/ctype.h +6 -0
  1252. package/src/platforms/snes/lib/pvsneslib/include/float.h +4 -0
  1253. package/src/platforms/snes/lib/pvsneslib/include/hdr.asm +47 -0
  1254. package/src/platforms/snes/lib/pvsneslib/include/limits.h +13 -0
  1255. package/src/platforms/snes/lib/pvsneslib/include/math.h +10 -0
  1256. package/src/platforms/snes/lib/pvsneslib/include/setjmp.h +4 -0
  1257. package/src/platforms/snes/lib/pvsneslib/include/snes/background.h +396 -0
  1258. package/src/platforms/snes/lib/pvsneslib/include/snes/console.h +188 -0
  1259. package/src/platforms/snes/lib/pvsneslib/include/snes/dma.h +381 -0
  1260. package/src/platforms/snes/lib/pvsneslib/include/snes/input.h +289 -0
  1261. package/src/platforms/snes/lib/pvsneslib/include/snes/interrupt.h +264 -0
  1262. package/src/platforms/snes/lib/pvsneslib/include/snes/libversion.h +10 -0
  1263. package/src/platforms/snes/lib/pvsneslib/include/snes/lzss.h +43 -0
  1264. package/src/platforms/snes/lib/pvsneslib/include/snes/map.h +113 -0
  1265. package/src/platforms/snes/lib/pvsneslib/include/snes/object.h +234 -0
  1266. package/src/platforms/snes/lib/pvsneslib/include/snes/pixel.h +53 -0
  1267. package/src/platforms/snes/lib/pvsneslib/include/snes/scores.h +66 -0
  1268. package/src/platforms/snes/lib/pvsneslib/include/snes/snestypes.h +65 -0
  1269. package/src/platforms/snes/lib/pvsneslib/include/snes/sound.h +245 -0
  1270. package/src/platforms/snes/lib/pvsneslib/include/snes/sprite.h +456 -0
  1271. package/src/platforms/snes/lib/pvsneslib/include/snes/video.h +465 -0
  1272. package/src/platforms/snes/lib/pvsneslib/include/snes.h +190 -0
  1273. package/src/platforms/snes/lib/pvsneslib/include/stdarg.h +28 -0
  1274. package/src/platforms/snes/lib/pvsneslib/include/stdbool.h +53 -0
  1275. package/src/platforms/snes/lib/pvsneslib/include/stddef.h +27 -0
  1276. package/src/platforms/snes/lib/pvsneslib/include/stdint.h +7 -0
  1277. package/src/platforms/snes/lib/pvsneslib/include/stdio.h +9 -0
  1278. package/src/platforms/snes/lib/pvsneslib/include/stdlib.h +13 -0
  1279. package/src/platforms/snes/lib/pvsneslib/include/string.h +19 -0
  1280. package/src/platforms/snes/lib/pvsneslib/include/strings.h +5 -0
  1281. package/src/platforms/snes/lib/pvsneslib/source/Makefile +87 -0
  1282. package/src/platforms/snes/lib/pvsneslib/source/backgrounds.asm +834 -0
  1283. package/src/platforms/snes/lib/pvsneslib/source/consoles.asm +1028 -0
  1284. package/src/platforms/snes/lib/pvsneslib/source/crt0_snes.asm +329 -0
  1285. package/src/platforms/snes/lib/pvsneslib/source/dmas.asm +1275 -0
  1286. package/src/platforms/snes/lib/pvsneslib/source/hdr.asm +56 -0
  1287. package/src/platforms/snes/lib/pvsneslib/source/input.asm +445 -0
  1288. package/src/platforms/snes/lib/pvsneslib/source/libc.asm +485 -0
  1289. package/src/platforms/snes/lib/pvsneslib/source/libc_c.c +1214 -0
  1290. package/src/platforms/snes/lib/pvsneslib/source/libm.asm +510 -0
  1291. package/src/platforms/snes/lib/pvsneslib/source/libtcc.asm +374 -0
  1292. package/src/platforms/snes/lib/pvsneslib/source/lzsss.asm +256 -0
  1293. package/src/platforms/snes/lib/pvsneslib/source/maps.asm +1078 -0
  1294. package/src/platforms/snes/lib/pvsneslib/source/objects.asm +2881 -0
  1295. package/src/platforms/snes/lib/pvsneslib/source/scores.asm +226 -0
  1296. package/src/platforms/snes/lib/pvsneslib/source/sm_spc.asm +187 -0
  1297. package/src/platforms/snes/lib/pvsneslib/source/snesmodwla.asm +1186 -0
  1298. package/src/platforms/snes/lib/pvsneslib/source/sounds.asm +273 -0
  1299. package/src/platforms/snes/lib/pvsneslib/source/sprites.asm +3946 -0
  1300. package/src/platforms/snes/lib/pvsneslib/source/vblank.asm +917 -0
  1301. package/src/platforms/snes/lib/pvsneslib/source/videos.asm +1137 -0
  1302. package/src/platforms/snes/lib/reset_init.asm +31 -0
  1303. package/src/platforms/snes/lib/sprite_table_populate.asm +122 -0
  1304. package/src/platforms/snes/lib/vram_dma_upload.asm +42 -0
  1305. package/src/platforms/snes/ppu.js +606 -0
  1306. package/src/platforms/snes/song.js +128 -0
  1307. package/src/playtest/playtest.js +841 -0
  1308. package/src/rom-id/identifier.js +421 -0
  1309. package/src/rom-id/patch.js +217 -0
  1310. package/src/toolchains/_worker/pool.js +253 -0
  1311. package/src/toolchains/_worker/run.js +78 -0
  1312. package/src/toolchains/_worker/wasm-worker.js +233 -0
  1313. package/src/toolchains/arm-none-eabi-gcc/gcc.js +216 -0
  1314. package/src/toolchains/asar/asar.js +542 -0
  1315. package/src/toolchains/assemble-snippet.js +256 -0
  1316. package/src/toolchains/cc65/cc65.js +395 -0
  1317. package/src/toolchains/cc65/da65.js +119 -0
  1318. package/src/toolchains/cc65/dbgparse.js +274 -0
  1319. package/src/toolchains/cc65/preset-resolver.js +59 -0
  1320. package/src/toolchains/cc65/presets/nes/chr-ram-runtime.cfg +79 -0
  1321. package/src/toolchains/cc65/presets/nes/chr-ram-runtime.crt0.s +178 -0
  1322. package/src/toolchains/cc65/presets/nes/chr-ram.cfg +76 -0
  1323. package/src/toolchains/cc65/presets/nes/chr-ram.crt0.s +106 -0
  1324. package/src/toolchains/common/ar.js +121 -0
  1325. package/src/toolchains/common/reassemble.js +353 -0
  1326. package/src/toolchains/common/sdk-cache.js +116 -0
  1327. package/src/toolchains/common/symbols.js +139 -0
  1328. package/src/toolchains/dasm/dasm.js +96 -0
  1329. package/src/toolchains/gba-c/gba-c.js +838 -0
  1330. package/src/toolchains/genesis-c/README.md +61 -0
  1331. package/src/toolchains/genesis-c/genesis-c.js +600 -0
  1332. package/src/toolchains/gnu-ld-map.js +86 -0
  1333. package/src/toolchains/index.js +862 -0
  1334. package/src/toolchains/m68k-elf-gcc/gcc.js +230 -0
  1335. package/src/toolchains/objdump.js +199 -0
  1336. package/src/toolchains/parse-errors.js +338 -0
  1337. package/src/toolchains/registry.js +67 -0
  1338. package/src/toolchains/rgbds/rgbds.js +144 -0
  1339. package/src/toolchains/sdcc/preflight-lint.js +295 -0
  1340. package/src/toolchains/sdcc/sdcc.js +540 -0
  1341. package/src/toolchains/sjasm/sjasm.js +85 -0
  1342. package/src/toolchains/snes-c/snes-c.js +409 -0
  1343. package/src/toolchains/tcc816/tcc816.js +79 -0
  1344. package/src/toolchains/vasm68k/vasm68k.js +138 -0
  1345. package/src/toolchains/wladx/wladx.js +120 -0
  1346. package/src/toolchains/z80/binutils.js +82 -0
@@ -0,0 +1,1410 @@
1
+ // Disassembly MCP tools — exposed as `disassemble` and `disassembleRom`.
2
+
3
+ import { readFile, writeFile, mkdir } from "node:fs/promises";
4
+ import nodePath from "node:path";
5
+ import { jsonContent, safeTool, writeOutput } from "../util.js";
6
+ import { parseSymbols, buildSymbolMap } from "../../toolchains/common/symbols.js";
7
+ import { registersForPlatform } from "../../platforms/common/registers.js";
8
+ import { findReferencesCore } from "./find-references.js";
9
+
10
+ // ── Per-platform CPU-address → file-offset mappers ────────────────
11
+ // Each returns { bytes, fileOffset, cpu, notes } given the full ROM
12
+ // bytes and a desired CPU address. Throws with a clear message if the
13
+ // address can't be mapped (e.g. outside ROM, bank not present).
14
+
15
+ /**
16
+ * NES iNES file. PRG-ROM starts at file offset 16; CPU $8000-$FFFF
17
+ * maps into the last 32 KB of PRG (16KB carts mirror $8000 ↔ $C000).
18
+ * Returns the slice starting at the requested CPU address.
19
+ */
20
+ export function mapNesAddress(data, cpuAddr, length, bank) {
21
+ if (data[0] !== 0x4e || data[1] !== 0x45 || data[2] !== 0x53 || data[3] !== 0x1a) {
22
+ throw new Error("not a valid iNES file (missing NES\\x1a magic at offset 0)");
23
+ }
24
+ const prgBanks = data[4];
25
+ const prgSize = prgBanks * 16384;
26
+ const prgFileStart = 16;
27
+ const num16kBanks = prgSize >> 14; // 16KB banks
28
+ // Mapper number = high nibble of flags6 + high nibble of flags7.
29
+ const mapperNum = ((data[6] >> 4) & 0xF) | (data[7] & 0xF0);
30
+ // For NROM (mapper 0): 16KB → mirrored at $8000 + $C000; 32KB → linear $8000-$FFFF.
31
+ // For mapper>0 the topmost bank is fixed at $C000-$FFFF (UxROM, MMC1 final
32
+ // bank, MMC3 last two banks all do this); other banks are switchable.
33
+ //
34
+ // `bank` (when given) explicitly selects which 16KB PRG bank is mapped into
35
+ // the SWITCHABLE slot ($8000-$BFFF). This is the fix for "disassemble UxROM
36
+ // bank N at $8000" — previously impossible without slicing the ROM by hand.
37
+ // A $C000+ address still resolves to the fixed top bank regardless of `bank`.
38
+ let offsetInPrg;
39
+ let mapperLabel;
40
+ if (bank != null && mapperNum !== 0 && prgSize > 16384) {
41
+ if (bank < 0 || bank >= num16kBanks) {
42
+ throw new Error(`NES bank ${bank} out of range (ROM has ${num16kBanks} × 16KB PRG banks, 0-${num16kBanks - 1})`);
43
+ }
44
+ if (cpuAddr >= 0xC000) {
45
+ // Fixed top bank — `bank` doesn't apply here.
46
+ offsetInPrg = (prgSize - 0x4000) + (cpuAddr - 0xC000);
47
+ mapperLabel = `mapper ${mapperNum} (fixed top bank at $C000; bank arg ignored above $C000)`;
48
+ } else if (cpuAddr >= 0x8000) {
49
+ offsetInPrg = bank * 0x4000 + (cpuAddr - 0x8000);
50
+ mapperLabel = `mapper ${mapperNum} (PRG bank ${bank} mapped at $8000)`;
51
+ } else {
52
+ offsetInPrg = -1;
53
+ mapperLabel = `mapper ${mapperNum}`;
54
+ }
55
+ } else if (prgSize === 16384) {
56
+ // NROM-128 — mirror.
57
+ offsetInPrg = cpuAddr & 0x3FFF;
58
+ mapperLabel = `mapper ${mapperNum} (NROM-128 mirror)`;
59
+ } else if (mapperNum === 0) {
60
+ offsetInPrg = cpuAddr - 0x8000;
61
+ mapperLabel = `mapper 0 (NROM-256)`;
62
+ } else {
63
+ // Banked mapper: top 16KB fixed at $C000, bank 0 at $8000 by default.
64
+ if (cpuAddr >= 0xC000) {
65
+ offsetInPrg = (prgSize - 0x4000) + (cpuAddr - 0xC000);
66
+ } else if (cpuAddr >= 0x8000) {
67
+ offsetInPrg = cpuAddr - 0x8000;
68
+ } else {
69
+ offsetInPrg = -1;
70
+ }
71
+ mapperLabel = `mapper ${mapperNum} (top bank fixed at $C000, bank 0 at $8000 — pass bank:N for a different switchable bank)`;
72
+ }
73
+ if (offsetInPrg < 0 || offsetInPrg >= prgSize) {
74
+ throw new Error(`CPU address $${cpuAddr.toString(16)} outside PRG ROM (${prgSize} bytes, ${mapperLabel})`);
75
+ }
76
+ const fileOffset = prgFileStart + offsetInPrg;
77
+ const slice = data.slice(fileOffset, fileOffset + length);
78
+ return {
79
+ bytes: slice,
80
+ fileOffset,
81
+ cpu: "6502",
82
+ note: `${mapperLabel}, PRG ${prgSize >> 10} KB`,
83
+ mapperNum,
84
+ prgSize,
85
+ prgFileStart,
86
+ };
87
+ }
88
+
89
+ /**
90
+ * SNES LoROM / HiROM file. Handles optional 512-byte SMC copier header,
91
+ * picks LoROM vs HiROM by checking the internal header at $7FC0 or $FFC0.
92
+ *
93
+ * Mapping (no SA-1 / ExHiROM support yet — those are rare for the kind
94
+ * of homebrew agents we care about):
95
+ * LoROM: bank $80-$FF mirrors $00-$7F. Address $XX:8000-$XX:FFFF →
96
+ * file offset = (bank & 0x7F) * 0x8000 + (addr & 0x7FFF) + copier_off
97
+ * HiROM: address $XX:0000-$XX:FFFF (banks $C0-$FF and $40-$7F) →
98
+ * file offset = (bank & 0x3F) * 0x10000 + (addr & 0xFFFF) + copier_off
99
+ */
100
+ export function mapSnesAddress(data, cpuAddr, length, mapperHint) {
101
+ // Strip optional 512B copier header (SMC files have it; SFC files don't).
102
+ const copierOff = (data.length % 0x8000 === 0x200) ? 0x200 : 0;
103
+
104
+ let isLo, mapper;
105
+ if (mapperHint === "lorom") {
106
+ isLo = true;
107
+ mapper = "LoROM (user-specified)";
108
+ } else if (mapperHint === "hirom") {
109
+ isLo = false;
110
+ mapper = "HiROM (user-specified)";
111
+ } else {
112
+ // Detect mapper: check internal header at LoROM ($7FC0) vs HiROM ($FFC0)
113
+ // by looking at the mapper byte at offset $15 in the header. Valid
114
+ // mapper bytes: $20 (LoROM), $21 (HiROM), $30 (FastROM LoROM), $31 (FastROM HiROM).
115
+ const loMapperByte = data[copierOff + 0x7FC0 + 0x15];
116
+ const hiMapperByte = data[copierOff + 0xFFC0 + 0x15];
117
+ const detectedLo = loMapperByte === 0x20 || loMapperByte === 0x30 || loMapperByte === 0x32;
118
+ const detectedHi = hiMapperByte === 0x21 || hiMapperByte === 0x31;
119
+ if (!detectedLo && !detectedHi) {
120
+ // No valid header — small homebrew often doesn't ship one. Default
121
+ // to LoROM (most common for small carts; HiROM is unusual at <256KB).
122
+ isLo = true;
123
+ mapper = "LoROM (assumed — no valid header found)";
124
+ } else {
125
+ isLo = detectedLo;
126
+ mapper = isLo ? "LoROM" : "HiROM";
127
+ }
128
+ }
129
+
130
+ // Decompose CPU address into bank + offset-within-bank.
131
+ const bank = (cpuAddr >>> 16) & 0xFF;
132
+ const bankAddr = cpuAddr & 0xFFFF;
133
+
134
+ let fileOffset;
135
+ if (isLo) {
136
+ // LoROM: only $8000-$FFFF inside a bank holds ROM data; bank $80-$FF mirrors $00-$7F.
137
+ if (bankAddr < 0x8000) {
138
+ throw new Error(`LoROM: CPU offset $${bankAddr.toString(16)} inside bank is RAM/IO; ROM data is at $8000-$FFFF`);
139
+ }
140
+ fileOffset = copierOff + ((bank & 0x7F) * 0x8000) + (bankAddr - 0x8000);
141
+ } else {
142
+ // HiROM: full 64KB banks; bank $C0+ is mirrors of $40+.
143
+ fileOffset = copierOff + ((bank & 0x3F) * 0x10000) + bankAddr;
144
+ }
145
+
146
+ if (fileOffset < 0 || fileOffset >= data.length) {
147
+ throw new Error(`${mapper}: CPU address $${cpuAddr.toString(16).padStart(6,"0")} → file offset 0x${fileOffset.toString(16)} outside ROM (${data.length} bytes)`);
148
+ }
149
+ const slice = data.slice(fileOffset, fileOffset + length);
150
+ return {
151
+ bytes: slice,
152
+ fileOffset,
153
+ cpu: "65816",
154
+ note: `${mapper}${copierOff ? " (512B copier header stripped)" : ""}, ${data.length >> 10} KB`,
155
+ };
156
+ }
157
+
158
+ /**
159
+ * Walk a da65-format asm string and prepend `label:` to lines whose
160
+ * leading "$XXXX" address matches a symbol. Loose pattern match — works
161
+ * with da65's default `<addr> <bytes> <mnem>` columnar output.
162
+ */
163
+ function annotateDisasmWithSymbols(asm, symbolMap) {
164
+ const lines = asm.split(/\r?\n/);
165
+ const out = [];
166
+ for (const line of lines) {
167
+ const m = line.match(/^([0-9A-Fa-f]{4,6}):?\s/);
168
+ if (m) {
169
+ const addr = parseInt(m[1], 16);
170
+ const syms = symbolMap.at(addr);
171
+ if (syms.length > 0) {
172
+ out.push(syms.map((s) => `; ${s.name}:`).join("\n"));
173
+ }
174
+ }
175
+ out.push(line);
176
+ }
177
+ return out.join("\n");
178
+ }
179
+
180
+ /**
181
+ * Read N-byte little-endian word from a buffer. Used for vector tables.
182
+ */
183
+ function readLEWord(data, offset, byteCount) {
184
+ let v = 0;
185
+ for (let i = 0; i < byteCount; i++) v |= data[offset + i] << (i * 8);
186
+ return v >>> 0;
187
+ }
188
+
189
+ /**
190
+ * Read the iNES vector table at PRG-end - 6 bytes. Returns { nmi, reset,
191
+ * irq } as CPU addresses. Returns null if the file isn't iNES.
192
+ */
193
+ function nesVectors(data) {
194
+ if (data[0] !== 0x4e || data[1] !== 0x45 || data[2] !== 0x53 || data[3] !== 0x1a) return null;
195
+ const prgSize = data[4] * 16384;
196
+ const vecOff = 16 + prgSize - 6;
197
+ return {
198
+ nmi: readLEWord(data, vecOff, 2),
199
+ reset: readLEWord(data, vecOff + 2, 2),
200
+ irq: readLEWord(data, vecOff + 4, 2),
201
+ };
202
+ }
203
+
204
+ /**
205
+ * SNES native + emulation vectors. The internal header at $7FE4 / $FFE4
206
+ * (LoROM / HiROM) holds the native vectors; $7FF4 / $FFF4 the emulation
207
+ * vectors. Picks the right base from the mapping byte at $15.
208
+ */
209
+ function snesVectors(data) {
210
+ const copierOff = (data.length % 0x8000 === 0x200) ? 0x200 : 0;
211
+ const loMapper = data[copierOff + 0x7FC0 + 0x15];
212
+ const hiMapper = data[copierOff + 0xFFC0 + 0x15];
213
+ const isLo = !(hiMapper === 0x21 || hiMapper === 0x31);
214
+ const headerBase = copierOff + (isLo ? 0x7FC0 : 0xFFC0);
215
+ // Native vectors (cop, brk, abort, nmi, reset, irq) at header+$24..
216
+ return {
217
+ native_cop: readLEWord(data, headerBase + 0x24, 2),
218
+ native_brk: readLEWord(data, headerBase + 0x26, 2),
219
+ native_abort: readLEWord(data, headerBase + 0x28, 2),
220
+ native_nmi: readLEWord(data, headerBase + 0x2A, 2),
221
+ native_reset: readLEWord(data, headerBase + 0x2C, 2),
222
+ native_irq: readLEWord(data, headerBase + 0x2E, 2),
223
+ emu_cop: readLEWord(data, headerBase + 0x34, 2),
224
+ emu_abort: readLEWord(data, headerBase + 0x38, 2),
225
+ emu_nmi: readLEWord(data, headerBase + 0x3A, 2),
226
+ emu_reset: readLEWord(data, headerBase + 0x3C, 2),
227
+ emu_irqbrk: readLEWord(data, headerBase + 0x3E, 2),
228
+ };
229
+ }
230
+
231
+ /**
232
+ * da65 with `--comments 4` emits lines like:
233
+ * ` lda #$05 ; 8000 A9 05`
234
+ * with the CPU address in the trailing comment. Extract it.
235
+ *
236
+ * Returns the integer address, or null if the line has no address comment.
237
+ */
238
+ function extractInstructionAddress(line) {
239
+ // The trailing comment has form `; <4-6 hex> <bytes...>`. Anchor on
240
+ // the *last* `;` in case the line has multiple.
241
+ const m = line.match(/;\s+([0-9A-Fa-f]{4,6})\s+(?:[0-9A-Fa-f]{2}\b)/);
242
+ return m ? parseInt(m[1], 16) : null;
243
+ }
244
+
245
+ /**
246
+ * Annotate asm output with hardware register names. Matches operand patterns
247
+ * like `$NNNN` and `$XX:NNNN` in the source column and appends a register
248
+ * name to the trailing comment (or creates one).
249
+ */
250
+ function annotateRegisters(asm, registers) {
251
+ if (!registers) return asm;
252
+ return asm.split(/\r?\n/).map((line) => {
253
+ if (line.startsWith(";")) return line;
254
+ // Split into source + existing-comment. Conservative — we only consider
255
+ // the FIRST `; ` as the comment boundary (da65 always emits one).
256
+ const sepIdx = line.indexOf(";");
257
+ const src = sepIdx >= 0 ? line.slice(0, sepIdx) : line;
258
+ let regName = null;
259
+ const m24 = src.match(/\$([0-9A-Fa-f]{2}):([0-9A-Fa-f]{4})/);
260
+ if (m24) {
261
+ const addr = (parseInt(m24[1], 16) << 16) | parseInt(m24[2], 16);
262
+ regName = registers[addr] ?? registers[addr & 0xFFFF] ?? null;
263
+ }
264
+ if (!regName) {
265
+ const m16 = src.match(/\$([0-9A-Fa-f]{3,4})\b/);
266
+ if (m16) {
267
+ regName = registers[parseInt(m16[1], 16)] ?? null;
268
+ }
269
+ }
270
+ if (!regName) return line;
271
+ if (line.includes(regName)) return line;
272
+ if (sepIdx >= 0) {
273
+ // Tail-append into the existing comment, after the byte-count column.
274
+ return line.replace(/\s*$/, " " + regName);
275
+ }
276
+ return line.replace(/\s*$/, " ; " + regName);
277
+ }).join("\n");
278
+ }
279
+
280
+ /**
281
+ * Annotate asm output with file-offset comments. Given a CPU→file offset
282
+ * translator function `cpuToFile(addr)`, each line with a parseable
283
+ * trailing address comment gets `@0xNNNN` injected into it.
284
+ */
285
+ function annotateFileOffsets(asm, cpuToFile, secondaryCpuToFile) {
286
+ return asm.split(/\r?\n/).map((line) => {
287
+ if (line.startsWith(";")) return line;
288
+ const addr = extractInstructionAddress(line);
289
+ if (addr == null) return line;
290
+ let off;
291
+ try { off = cpuToFile(addr); } catch { return line; }
292
+ if (off == null) return line;
293
+ let tag = "@0x" + off.toString(16).toUpperCase();
294
+ if (secondaryCpuToFile) {
295
+ let off2;
296
+ try { off2 = secondaryCpuToFile(addr); } catch { /* swallow */ }
297
+ if (off2 != null) {
298
+ tag += " (prg @0x" + off2.toString(16).toUpperCase() + ")";
299
+ }
300
+ }
301
+ if (line.includes(tag)) return line;
302
+ return line.replace(/\s*$/, " " + tag);
303
+ }).join("\n");
304
+ }
305
+
306
+ /**
307
+ * Scan disassembled asm for the first end-of-routine instruction (rts, rti,
308
+ * rtl, or bare jmp at column 0). Returns the line index after it, or -1 if
309
+ * none found. Used by `untilReturn`.
310
+ */
311
+ /**
312
+ * Inject vector-name labels into z80dasm output. The Z80 disassembler
313
+ * emits `LXXXX:` labels for every branch target it sees, but doesn't
314
+ * know which addresses are interrupt vectors. For each label whose
315
+ * address matches a known vector ($0000=reset, $0038=irq, $0066=nmi, etc.),
316
+ * emit an additional `<vec-name>:` comment line.
317
+ */
318
+ function injectVectorLabels(asm, labels) {
319
+ const byAddr = new Map();
320
+ for (const l of labels) byAddr.set(l.addr, l.name);
321
+ const lines = asm.split(/\r?\n/);
322
+ const out = [];
323
+ for (const line of lines) {
324
+ // Match `LXXXX:` label lines (4 hex for Z80/SM83, 6 for m68k).
325
+ const m = line.match(/^L([0-9A-F]{4,6}):/);
326
+ if (m) {
327
+ const addr = parseInt(m[1], 16);
328
+ const name = byAddr.get(addr);
329
+ if (name) out.push(`${name}:`);
330
+ } else {
331
+ // Or match an instruction line whose trailing comment says ADDR is a vector.
332
+ const ma = line.match(/;\s+([0-9A-F]{4,6})\s+/);
333
+ if (ma) {
334
+ const addr = parseInt(ma[1], 16);
335
+ const name = byAddr.get(addr);
336
+ // Only insert the label if it wasn't already emitted as LXXXX.
337
+ if (name) {
338
+ // Don't double-insert if we just emitted the label above.
339
+ if (out.length > 0 && !out[out.length - 1].startsWith(name + ":")) {
340
+ out.push(`${name}:`);
341
+ }
342
+ }
343
+ }
344
+ }
345
+ out.push(line);
346
+ }
347
+ return out.join("\n");
348
+ }
349
+
350
+ function findFirstReturnLine(asm, cpuFamily = "6502") {
351
+ const lines = asm.split(/\r?\n/);
352
+ for (let i = 0; i < lines.length; i++) {
353
+ const line = lines[i];
354
+ const trimmed = line.trim();
355
+ if (cpuFamily === "z80" || cpuFamily === "sm83") {
356
+ // SM83 differs from Z80 only by missing `retn` (no NMI-return alias).
357
+ // Bare ret, reti, jp <addr>, jp <label> all terminate. Conditional
358
+ // ret (`ret nz` etc) does NOT — routine continues past it.
359
+ if (/^ret\s*(;|$)/.test(trimmed)) return i + 1;
360
+ if (/^reti\b/.test(trimmed)) return i + 1;
361
+ if (cpuFamily === "z80" && /^retn\b/.test(trimmed)) return i + 1;
362
+ if (/^jp\s+\$[0-9A-Fa-f]/.test(trimmed)) return i + 1;
363
+ if (/^jp\s+L[0-9A-Fa-f]/.test(trimmed)) return i + 1;
364
+ // sm83-only: `jp hl` is an indirect jump-table dispatch; treat as
365
+ // routine-end since the decoder can't follow it.
366
+ if (cpuFamily === "sm83" && /^jp\s+hl\b/.test(trimmed)) return i + 1;
367
+ } else {
368
+ if (/^(rts|rti|rtl)\b/.test(trimmed)) return i + 1;
369
+ if (/^jmp\s+\$[0-9A-Fa-f]/.test(trimmed)) return i + 1;
370
+ }
371
+ }
372
+ return -1;
373
+ }
374
+
375
+ /**
376
+ * SMS / Game Gear address mapping. The first 48 KB of the ROM is mapped
377
+ * 1:1 to the Z80's lower 48 KB ($0000-$BFFF). Higher banks are
378
+ * page-mapped via the sega mapper, but for v1 we treat the 16 KB at
379
+ * $8000-$BFFF as "bank 0" by default.
380
+ */
381
+ export function mapSmsAddress(data, cpuAddr, length) {
382
+ // Slot 0: $0000-$3FFF maps to file 0..$3FFF (bank 0, fixed).
383
+ // Slot 1: $4000-$7FFF maps to file $4000..$7FFF (bank 1, fixed by default).
384
+ // Slot 2: $8000-$BFFF maps to file $8000..$BFFF (banked — default = bank 2).
385
+ if (cpuAddr < 0xC000) {
386
+ const fileOffset = cpuAddr;
387
+ if (fileOffset >= data.length) {
388
+ throw new Error(`CPU address $${cpuAddr.toString(16)} past end of SMS ROM (${data.length} bytes)`);
389
+ }
390
+ return {
391
+ bytes: data.slice(fileOffset, fileOffset + length),
392
+ fileOffset,
393
+ cpu: "z80",
394
+ note: `SMS/GG sega mapper, slot ${cpuAddr < 0x4000 ? 0 : cpuAddr < 0x8000 ? 1 : 2} (default bank)`,
395
+ };
396
+ }
397
+ throw new Error(
398
+ `CPU address $${cpuAddr.toString(16)} is in RAM ($C000-$FFFF), not ROM. ` +
399
+ `For SMS disasm, target $0000-$BFFF.`
400
+ );
401
+ }
402
+
403
+ /**
404
+ * Game Boy / Game Boy Color address mapping.
405
+ * Slot 0: $0000-$3FFF = file 0..$3FFF (bank 0, fixed)
406
+ * Slot 1: $4000-$7FFF = file (bank * 0x4000)..(bank * 0x4000 + 0x3FFF)
407
+ * Default bank 1 — pass `bank` to disassembleRom for a different one.
408
+ * RAM ($8000+) and I/O are not in the ROM file.
409
+ */
410
+ export function mapGbAddress(data, cpuAddr, length, bank = 1) {
411
+ if (cpuAddr < 0x4000) {
412
+ const fileOffset = cpuAddr;
413
+ if (fileOffset >= data.length) {
414
+ throw new Error(`CPU address $${cpuAddr.toString(16)} past end of GB ROM (${data.length} bytes)`);
415
+ }
416
+ return {
417
+ bytes: data.slice(fileOffset, fileOffset + length),
418
+ fileOffset,
419
+ cpu: "sm83",
420
+ note: "GB mapper, slot 0 (bank 0, fixed)",
421
+ };
422
+ }
423
+ if (cpuAddr < 0x8000) {
424
+ const fileOffset = (bank * 0x4000) + (cpuAddr - 0x4000);
425
+ if (fileOffset >= data.length) {
426
+ throw new Error(
427
+ `CPU $${cpuAddr.toString(16)} (bank ${bank}, file 0x${fileOffset.toString(16)}) ` +
428
+ `past end of GB ROM (${data.length} bytes)`
429
+ );
430
+ }
431
+ return {
432
+ bytes: data.slice(fileOffset, fileOffset + length),
433
+ fileOffset,
434
+ cpu: "sm83",
435
+ note: `GB mapper, slot 1 (bank ${bank})`,
436
+ };
437
+ }
438
+ throw new Error(
439
+ `CPU address $${cpuAddr.toString(16)} is in VRAM/WRAM/HRAM, not ROM. ` +
440
+ `For GB disasm, target $0000-$7FFF.`
441
+ );
442
+ }
443
+
444
+ /**
445
+ * Atari 2600 address mapping. 4 KB carts mirror through $F000-$FFFF (and
446
+ * $D000, $B000, etc. — the 2600 only decodes the low 13 bits of the
447
+ * address). 8 KB+ carts use bank-switching schemes (F8, F6, F4, etc.)
448
+ * that we don't fully model here — disassembling those needs the bank
449
+ * arg to slice into the right 4KB window.
450
+ */
451
+ export function mapAtari2600Address(data, cpuAddr, length, bank = 0) {
452
+ // Strip mirrors: 2600 addresses are 13-bit. Anything in $1000-$1FFF
453
+ // (mirrored as $3000, $5000, ..., $F000) maps to ROM.
454
+ const stripped = cpuAddr & 0x1FFF;
455
+ if (stripped < 0x1000) {
456
+ throw new Error(
457
+ `CPU address $${cpuAddr.toString(16)} is in TIA/RIOT/RAM space, not ROM. ` +
458
+ `For 2600 disasm, target $1000-$1FFF (or any mirror: $3000, $5000, ..., $F000).`
459
+ );
460
+ }
461
+ const offsetInBank = stripped - 0x1000; // 0..0xFFF
462
+ // Default 4KB cart: single bank, file offset = offsetInBank.
463
+ // Larger carts: caller passes `bank` index.
464
+ const bankSize = Math.min(data.length, 0x1000);
465
+ const fileOffset = bank * bankSize + offsetInBank;
466
+ if (fileOffset >= data.length) {
467
+ throw new Error(
468
+ `CPU $${cpuAddr.toString(16)} (bank ${bank}, file 0x${fileOffset.toString(16)}) ` +
469
+ `past end of 2600 ROM (${data.length} bytes)`
470
+ );
471
+ }
472
+ return {
473
+ bytes: data.slice(fileOffset, fileOffset + length),
474
+ fileOffset,
475
+ cpu: "6502",
476
+ note: data.length <= 0x1000
477
+ ? "2600 4KB cart (no bank-switching)"
478
+ : `2600 banked cart, bank ${bank} of ${Math.ceil(data.length / 0x1000)}`,
479
+ };
480
+ }
481
+
482
+ /**
483
+ * Genesis / Mega Drive address mapping. The cartridge ROM maps 1:1 into
484
+ * the 68000 address space starting at $000000 — flat, big-endian, no
485
+ * mapper for ROMs ≤ 4 MB (the common case). $000000-$0000FF is the vector
486
+ * table (SP at $000000, reset PC at $000004); cart code typically begins
487
+ * at the reset vector. We treat the CPU address as the file offset
488
+ * directly.
489
+ */
490
+ export function mapGenesisAddress(data, cpuAddr, length) {
491
+ if (cpuAddr + length > data.length) {
492
+ throw new Error(
493
+ `Genesis: CPU address $${cpuAddr.toString(16)} + ${length} extends past ROM ` +
494
+ `(${data.length} bytes). ROM maps 1:1 from $000000; for >4MB carts with mappers, ` +
495
+ `slice the file manually.`
496
+ );
497
+ }
498
+ return {
499
+ bytes: data.slice(cpuAddr, cpuAddr + length),
500
+ fileOffset: cpuAddr,
501
+ cpu: "m68k",
502
+ note: "Genesis ROM maps 1:1 to 68000 $000000+ (flat, big-endian).",
503
+ };
504
+ }
505
+
506
+ /**
507
+ * Atari 7800 address mapping. The cart has a 128-byte header at file
508
+ * offset 0 (skip it). ROM body is at file offset 128 and maps into the
509
+ * 6502 address space starting at varying high addresses depending on
510
+ * cart size:
511
+ * 16 KB: $C000-$FFFF
512
+ * 32 KB: $8000-$FFFF
513
+ * 48 KB: $4000-$FFFF (rare)
514
+ * 144 KB SuperGame: bank-switched at $8000-$BFFF + fixed at $C000
515
+ */
516
+ export function mapAtari7800Address(data, cpuAddr, length, bank = 0) {
517
+ // Detect header. "ATARI7800" magic at offset 1.
518
+ const hasHeader =
519
+ data.length > 128 &&
520
+ String.fromCharCode(data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9])
521
+ === "ATARI7800";
522
+ const headerSize = hasHeader ? 128 : 0;
523
+ const romSize = data.length - headerSize;
524
+ // Default behavior: figure out which file-offset corresponds to cpuAddr.
525
+ // For "fixed" carts (no banking), CPU $C000 maps to romStart + (romSize - 16KB)
526
+ // etc. The simplest, most-correct model: assume cart fills high address
527
+ // space ending at $FFFF.
528
+ const cartStartCpu = 0x10000 - romSize; // e.g. 32KB = $8000
529
+ if (cpuAddr < cartStartCpu) {
530
+ throw new Error(
531
+ `CPU address $${cpuAddr.toString(16)} is below cart ROM (cart starts at $${cartStartCpu.toString(16)}). ` +
532
+ `For 7800 disasm, target $${cartStartCpu.toString(16)}-$FFFF.`
533
+ );
534
+ }
535
+ const fileOffset = headerSize + (cpuAddr - cartStartCpu);
536
+ if (fileOffset >= data.length) {
537
+ throw new Error(`CPU $${cpuAddr.toString(16)} past end of 7800 ROM`);
538
+ }
539
+ return {
540
+ bytes: data.slice(fileOffset, fileOffset + length),
541
+ fileOffset,
542
+ cpu: "6502",
543
+ note: hasHeader
544
+ ? `7800 ATARI7800 header detected (128B skipped); cart maps to $${cartStartCpu.toString(16).toUpperCase()}-$FFFF`
545
+ : `7800 headerless cart; cart maps to $${cartStartCpu.toString(16).toUpperCase()}-$FFFF`,
546
+ };
547
+ }
548
+
549
+ /**
550
+ * Map a C64 CPU address to a file offset in a .prg image.
551
+ *
552
+ * .prg layout: 2-byte little-endian LOAD ADDRESS, then the program bytes.
553
+ * file[0..1] = load address (e.g. $0801 for BASIC start)
554
+ * file[2..] = program bytes loaded contiguously starting at that addr
555
+ *
556
+ * For .crt cart images we'd need to honor the C64 cart header (see CCS64
557
+ * docs); not implemented here — pass `bank` instead and call with the raw
558
+ * binary if you're hand-mapping.
559
+ */
560
+ export function mapC64Address(data, cpuAddr, length, bank = 0) {
561
+ // Detect .prg by reading the load address and seeing if it makes sense.
562
+ // (Anything is a valid load addr in theory, so we just trust the first
563
+ // 2 bytes here.)
564
+ const loadAddr = data[0] | (data[1] << 8);
565
+ const fileOffset = 2 + (cpuAddr - loadAddr);
566
+ if (cpuAddr < loadAddr) {
567
+ throw new Error(
568
+ `CPU $${cpuAddr.toString(16)} is below the .prg load address $${loadAddr.toString(16)}. ` +
569
+ `This file loads at $${loadAddr.toString(16)} — start disasm there.`
570
+ );
571
+ }
572
+ if (fileOffset < 2 || fileOffset >= data.length) {
573
+ throw new Error(
574
+ `CPU $${cpuAddr.toString(16)} maps to file offset ${fileOffset}, outside this ${data.length}-byte .prg.`
575
+ );
576
+ }
577
+ return {
578
+ bytes: data.slice(fileOffset, fileOffset + length),
579
+ fileOffset,
580
+ cpu: "6502",
581
+ note: `c64 .prg load addr = $${loadAddr.toString(16).toUpperCase()}; first byte after header is at file offset 2`,
582
+ };
583
+ }
584
+
585
+ async function disassembleCore({ path: inPath, base64, startAddress = 0x8000, cpu = "6502", addOrigin = true, symbolsPath, symbolsText, symbolsFormat, outputPath, inline }) {
586
+ if (!inline && !outputPath) {
587
+ throw new Error("disassemble: pass outputPath (write the asm to disk, returns {path}) or inline:true (return the asm in the response).");
588
+ }
589
+ if (!inPath && !base64) {
590
+ throw new Error("disassemble: pass `path` (a binary file on disk) or `base64` (the bytes).");
591
+ }
592
+ const { runDa65 } = await import("../../toolchains/cc65/da65.js");
593
+ const bytes = inPath
594
+ ? new Uint8Array(await readFile(inPath))
595
+ : new Uint8Array(Buffer.from(base64, "base64"));
596
+ const r = await runDa65({ bytes, startAddress, cpu });
597
+ let asm = r.asm;
598
+
599
+ // On failure, surface the error in the response — never write the raw
600
+ // da65 error text into outputPath (it'd masquerade as partial asm).
601
+ if (r.exitCode !== 0) {
602
+ return jsonContent({
603
+ ok: false,
604
+ exitCode: r.exitCode,
605
+ bytes: bytes.length,
606
+ startAddress,
607
+ cpu,
608
+ error: firstErrorLine(asm) ?? `da65 exited ${r.exitCode}`,
609
+ errorText: asm,
610
+ note: "Disassembly FAILED — outputPath not written. See `error`.",
611
+ });
612
+ }
613
+
614
+ // Round-trip origin (cc65 family only — da65 is always 6502-family here).
615
+ if (addOrigin) asm = injectOrigin(asm, startAddress);
616
+
617
+ let symbolCount = 0;
618
+ if (symbolsPath || symbolsText) {
619
+ const text = symbolsPath ? await readFile(symbolsPath, "utf-8") : symbolsText;
620
+ const symbols = parseSymbols({ text, path: symbolsPath, format: symbolsFormat });
621
+ const map = buildSymbolMap(symbols);
622
+ asm = annotateDisasmWithSymbols(asm, map);
623
+ symbolCount = symbols.length;
624
+ }
625
+ const meta = {
626
+ ok: true,
627
+ exitCode: r.exitCode,
628
+ bytes: bytes.length,
629
+ startAddress,
630
+ cpu,
631
+ symbolCount,
632
+ ...(inPath ? { sourcePath: inPath } : {}),
633
+ };
634
+ if (inline) {
635
+ return jsonContent({ ...meta, asm });
636
+ }
637
+ const { path } = writeOutput(asm, { outputPath, what: "disassembly asm" });
638
+ return jsonContent({ ...meta, path, asmBytes: asm.length });
639
+ }
640
+
641
+ async function disassembleRomCore(args) {
642
+ const {
643
+ path: romPath, platform, mapper,
644
+ untilReturn, dataRanges,
645
+ autoLabelVectors,
646
+ outputPath,
647
+ } = args;
648
+ const addOrigin = args.addOrigin ?? true;
649
+ // `let` because Genesis re-points an unset startAddress to the reset vector.
650
+ let startAddress = args.startAddress;
651
+ const annotateRegistersFlag = args.annotateRegisters ?? true;
652
+ const annotateFileOffsetsFlag = args.annotateFileOffsets ?? true;
653
+
654
+ const { runDa65 } = await import("../../toolchains/cc65/da65.js");
655
+ const data = new Uint8Array(await readFile(romPath));
656
+
657
+ // Resolve platform.
658
+ const resolved = platform ?? (
659
+ /\.nes$/i.test(romPath) ? "nes" :
660
+ /\.(sfc|smc)$/i.test(romPath) ? "snes" :
661
+ /\.sms$/i.test(romPath) ? "sms" :
662
+ /\.gg$/i.test(romPath) ? "gg" :
663
+ /\.gb$/i.test(romPath) ? "gb" :
664
+ /\.gbc$/i.test(romPath) ? "gbc" :
665
+ /\.a26$/i.test(romPath) ? "atari2600" :
666
+ /\.a78$/i.test(romPath) ? "atari7800" :
667
+ /\.prg$/i.test(romPath) ? "c64" :
668
+ /\.gba$/i.test(romPath) ? "gba" :
669
+ /\.(lnx|lyx)$/i.test(romPath) ? "lynx" :
670
+ /\.(gen|md|bin)$/i.test(romPath) ? "genesis" :
671
+ null
672
+ );
673
+ if (!resolved) {
674
+ throw new Error(`could not detect platform from path '${romPath}'. Pass platform explicitly.`);
675
+ }
676
+ const cpuFamily = (resolved === "sms" || resolved === "gg") ? "z80"
677
+ : (resolved === "gb" || resolved === "gbc") ? "sm83"
678
+ : (resolved === "genesis") ? "m68k"
679
+ : (resolved === "gba") ? "arm"
680
+ : "6502";
681
+
682
+ // Resolve length: endAddress wins over length; default 256.
683
+ let length;
684
+ if (args.endAddress != null) {
685
+ if (args.length != null) {
686
+ throw new Error("disassembleRom: pass either `length` OR `endAddress`, not both.");
687
+ }
688
+ length = args.endAddress - startAddress + 1;
689
+ if (length <= 0) throw new Error(`disassembleRom: endAddress ($${args.endAddress.toString(16)}) must be >= startAddress ($${startAddress.toString(16)}).`);
690
+ } else {
691
+ length = args.length ?? 256;
692
+ }
693
+
694
+ // Genesis code lives in the low ROM; the default $8000 start (a
695
+ // 6502/Z80 convention) is meaningless for 68000. If the caller
696
+ // didn't override startAddress, begin at the reset vector ($000004
697
+ // holds the reset PC).
698
+ // Genesis code lives in low ROM; the $8000 schema default (a 6502/Z80
699
+ // convention) is meaningless on 68000. When the caller left it at the
700
+ // default, start at the reset vector ($000004 holds the reset PC).
701
+ if (resolved === "genesis" && startAddress === 0x8000 && args.endAddress === undefined) {
702
+ startAddress = (data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]) >>> 0;
703
+ if (startAddress >= data.length) startAddress = 0x200; // fallback
704
+ }
705
+ // GBA ROM maps flat at 0x08000000; the cart entry is at file offset 0
706
+ // (a branch over the 192-byte header). Default to disassembling from the
707
+ // start of ROM in 0x08000000 space when the caller left the 6502 default.
708
+ if (resolved === "gba" && startAddress === 0x8000 && args.endAddress === undefined) {
709
+ startAddress = 0x08000000;
710
+ }
711
+ // Lynx: 65C02 cart image (after a 64-byte "LYNX" header). Homebrew runs
712
+ // from $0200, not the $8000 6502 default — auto-bump when unspecified.
713
+ if (resolved === "lynx" && startAddress === 0x8000 && args.endAddress === undefined) {
714
+ startAddress = 0x0200;
715
+ }
716
+
717
+ const mapped = resolved === "lynx"
718
+ ? (() => {
719
+ const hasHdr = data.length >= 64 && data[0] === 0x4c && data[1] === 0x59 && data[2] === 0x4e && data[3] === 0x58; // "LYNX"
720
+ const base = hasHdr ? 64 : 0;
721
+ const off = base + (startAddress - 0x0200); // flat image loaded at $0200
722
+ if (off < base || off >= data.length) throw new Error(`Lynx: startAddress $${startAddress.toString(16)} is outside the cart image.`);
723
+ return { bytes: data.slice(off, Math.min(data.length, off + length)), fileOffset: off, cpu: "6502" };
724
+ })()
725
+ : resolved === "gba"
726
+ ? (() => {
727
+ const base = 0x08000000;
728
+ const off = (startAddress >>> 0) - base;
729
+ if (off < 0 || off >= data.length) throw new Error(`GBA: startAddress $${startAddress.toString(16)} is outside ROM (maps 0x08000000..0x08000000+${data.length}).`);
730
+ return { bytes: data.slice(off, Math.min(data.length, off + length)), fileOffset: off, cpu: "arm" };
731
+ })()
732
+ : resolved === "snes"
733
+ ? mapSnesAddress(data, startAddress, length, mapper)
734
+ : resolved === "sms" || resolved === "gg"
735
+ ? mapSmsAddress(data, startAddress, length)
736
+ : resolved === "gb" || resolved === "gbc"
737
+ ? mapGbAddress(data, startAddress, length, args.bank)
738
+ : resolved === "atari2600"
739
+ ? mapAtari2600Address(data, startAddress, length, args.bank ?? 0)
740
+ : resolved === "atari7800"
741
+ ? mapAtari7800Address(data, startAddress, length, args.bank ?? 0)
742
+ : resolved === "c64"
743
+ ? mapC64Address(data, startAddress, length, args.bank ?? 0)
744
+ : resolved === "genesis"
745
+ ? mapGenesisAddress(data, startAddress, length)
746
+ : mapNesAddress(data, startAddress, length, args.bank);
747
+
748
+ // Build vector labels + data ranges. For SMS, no vector table to
749
+ // auto-read (Z80 uses reset $0000 + interrupt vector based on IM
750
+ // mode). For NES/SNES we synthesize a da65 info file.
751
+ let info = null;
752
+ const labels = [];
753
+ if (autoLabelVectors && cpuFamily === "6502") {
754
+ let vecs = null;
755
+ if (resolved === "nes") vecs = nesVectors(data);
756
+ else if (resolved === "snes") vecs = snesVectors(data);
757
+ else if (resolved === "atari2600") {
758
+ // 2600 vectors at $FFFA-$FFFF (NMI/RESET/IRQ); all carts map them
759
+ // to top of 4KB bank. Read last 6 bytes of the file.
760
+ const off = data.length - 6;
761
+ vecs = {
762
+ nmi: data[off + 0] | (data[off + 1] << 8),
763
+ reset: data[off + 2] | (data[off + 3] << 8),
764
+ irq: data[off + 4] | (data[off + 5] << 8),
765
+ };
766
+ } else if (resolved === "atari7800") {
767
+ // 7800 vectors at $FFFA-$FFFF (NMI/RESET/IRQ).
768
+ const off = data.length - 6;
769
+ vecs = {
770
+ nmi: data[off + 0] | (data[off + 1] << 8),
771
+ reset: data[off + 2] | (data[off + 3] << 8),
772
+ irq: data[off + 4] | (data[off + 5] << 8),
773
+ };
774
+ }
775
+ if (vecs) {
776
+ for (const [name, addr] of Object.entries(vecs)) {
777
+ if (addr >= startAddress && addr <= startAddress + length - 1) {
778
+ labels.push({ name, addr });
779
+ }
780
+ }
781
+ }
782
+ }
783
+ if (autoLabelVectors && cpuFamily === "z80") {
784
+ // Z80 fixed vectors: reset = $0000, interrupt vectors at $0008
785
+ // ($28 = rst 8), $0010, $0018, $0020, $0028, $0030, $0038. NMI = $0066.
786
+ // SMS uses $38 (IM 1) for vblank, $66 (NMI) for the pause button.
787
+ const z80Vectors = {
788
+ reset: 0x0000,
789
+ rst08: 0x0008, rst10: 0x0010, rst18: 0x0018,
790
+ rst20: 0x0020, rst28: 0x0028, rst30: 0x0030,
791
+ irq: 0x0038, // SMS vblank handler when IM 1
792
+ nmi: 0x0066, // SMS pause button
793
+ };
794
+ for (const [name, addr] of Object.entries(z80Vectors)) {
795
+ if (addr >= startAddress && addr <= startAddress + length - 1) {
796
+ labels.push({ name, addr });
797
+ }
798
+ }
799
+ }
800
+ if (autoLabelVectors && cpuFamily === "sm83") {
801
+ // GB vectors: rst $00-$38, plus dedicated IRQ vectors:
802
+ // $0040 vblank IRQ
803
+ // $0048 lcd-stat IRQ
804
+ // $0050 timer IRQ
805
+ // $0058 serial IRQ
806
+ // $0060 joypad IRQ
807
+ // $0100 entry point (cart code starts here after Nintendo logo)
808
+ // $0104-$0133 logo bytes (NOT code — auto-skip if window includes them)
809
+ const gbVectors = {
810
+ reset: 0x0000,
811
+ rst08: 0x0008, rst10: 0x0010, rst18: 0x0018,
812
+ rst20: 0x0020, rst28: 0x0028, rst30: 0x0030, rst38: 0x0038,
813
+ vblank: 0x0040,
814
+ lcd_stat: 0x0048,
815
+ timer: 0x0050,
816
+ serial: 0x0058,
817
+ joypad: 0x0060,
818
+ entry: 0x0100,
819
+ };
820
+ for (const [name, addr] of Object.entries(gbVectors)) {
821
+ if (addr >= startAddress && addr <= startAddress + length - 1) {
822
+ labels.push({ name, addr });
823
+ }
824
+ }
825
+ }
826
+ if (autoLabelVectors && cpuFamily === "m68k") {
827
+ // Genesis 68000 vector table at $000000-$0000FF. The useful ones:
828
+ // $000000 initial SP, $000004 reset PC, $000060 HBL, $000070 VBL.
829
+ // (The full table is 64 long-word vectors; these are the ones game
830
+ // code reaches.) Read the targets from the ROM image and label any
831
+ // that fall inside the disassembly window.
832
+ const vec = (off) => (data[off] << 24 | data[off + 1] << 16 | data[off + 2] << 8 | data[off + 3]) >>> 0;
833
+ const genVectors = {
834
+ reset: vec(0x04),
835
+ hbl: vec(0x70), // level-4 autovector (H-blank)
836
+ vbl: vec(0x78), // level-6 autovector (V-blank)
837
+ };
838
+ for (const [name, t] of Object.entries(genVectors)) {
839
+ if (t >= startAddress && t <= startAddress + length - 1) labels.push({ name, addr: t });
840
+ }
841
+ }
842
+ // Dedup vector labels by ADDRESS. Two interrupt vectors legitimately
843
+ // sharing one target is valid 6502 (Rygar points NMI and IRQ both at
844
+ // $C0F6) — but da65's LABELDEF and every dasm injector reject two labels
845
+ // at the same address ("Label for address $XXXX already defined"). Keep
846
+ // the first name (vector iteration order is reset/nmi/irq) and record the
847
+ // dropped aliases so the response can surface them.
848
+ const labelAliases = [];
849
+ if (labels.length > 1) {
850
+ const seen = new Map(); // addr -> first label name
851
+ const deduped = [];
852
+ for (const lab of labels) {
853
+ if (seen.has(lab.addr)) {
854
+ labelAliases.push({ alias: lab.name, sameAs: seen.get(lab.addr), addr: lab.addr });
855
+ } else {
856
+ seen.set(lab.addr, lab.name);
857
+ deduped.push(lab);
858
+ }
859
+ }
860
+ labels.length = 0;
861
+ labels.push(...deduped);
862
+ }
863
+
864
+ const dataRangesInWindow = (dataRanges ?? []).filter((r) => {
865
+ return r.start + r.length - 1 >= startAddress && r.start <= startAddress + length - 1;
866
+ });
867
+
868
+ let asm;
869
+ let exitCode = 0;
870
+ // Non-6502 CPUs disassemble through the native binutils objdump for that
871
+ // ISA (m68k / arm+thumb / z80 / gbz80). The objdump WASM ships in the
872
+ // matching toolchain package (a hard dependency), so it's always present.
873
+ if (cpuFamily === "m68k" || cpuFamily === "arm" || cpuFamily === "z80" || cpuFamily === "sm83") {
874
+ const { runObjdump, objdumpAvailable } = await import("../../toolchains/objdump.js");
875
+ const arch = cpuFamily === "arm" ? (args.thumb ? "thumb" : "arm")
876
+ : cpuFamily === "sm83" ? "gbz80"
877
+ : cpuFamily; // m68k / z80
878
+ if (!objdumpAvailable(arch)) {
879
+ throw new Error(`disassembly needs the ${arch} objdump WASM (in the matching romdev toolchain package). Reinstall the toolchain package.`);
880
+ }
881
+ const r = await runObjdump({ bytes: mapped.bytes, arch, startAddress });
882
+ asm = r.asm; exitCode = r.exitCode;
883
+ if (labels.length > 0 && cpuFamily !== "arm") asm = injectVectorLabels(asm, labels);
884
+ } else {
885
+ if (labels.length > 0 || dataRangesInWindow.length > 0 || mapped.cpu !== "6502") {
886
+ info = buildInfoFile({
887
+ startAddress, length,
888
+ cpu: mapped.cpu,
889
+ labels,
890
+ dataRanges: dataRangesInWindow,
891
+ });
892
+ }
893
+ const needAddressColumn = annotateRegistersFlag || annotateFileOffsetsFlag;
894
+ const r = await runDa65({
895
+ bytes: mapped.bytes, startAddress, cpu: mapped.cpu, info,
896
+ options: needAddressColumn ? ["--comments", "4"] : [],
897
+ });
898
+ asm = r.asm;
899
+ exitCode = r.exitCode;
900
+ }
901
+
902
+ // File-offset annotation: per-line cpu→file translator.
903
+ if (annotateFileOffsetsFlag) {
904
+ const cpuToFile = (cpuAddr) => {
905
+ try {
906
+ if (resolved === "snes") return mapSnesAddress(data, cpuAddr, 1, mapper).fileOffset;
907
+ if (resolved === "sms" || resolved === "gg") return mapSmsAddress(data, cpuAddr, 1).fileOffset;
908
+ if (resolved === "gb" || resolved === "gbc") return mapGbAddress(data, cpuAddr, 1, args.bank).fileOffset;
909
+ if (resolved === "atari2600") return mapAtari2600Address(data, cpuAddr, 1, args.bank ?? 0).fileOffset;
910
+ if (resolved === "atari7800") return mapAtari7800Address(data, cpuAddr, 1, args.bank ?? 0).fileOffset;
911
+ if (resolved === "c64") return mapC64Address(data, cpuAddr, 1, args.bank ?? 0).fileOffset;
912
+ if (resolved === "genesis") return mapGenesisAddress(data, cpuAddr, 1).fileOffset;
913
+ // `args.bank` maps $8000-$BFFF to the chosen switchable bank;
914
+ // mapNesAddress ignores it for $C000+ (fixed top bank), so each
915
+ // annotated line points at the correct PRG offset.
916
+ return mapNesAddress(data, cpuAddr, 1, args.bank).fileOffset;
917
+ } catch {
918
+ return null;
919
+ }
920
+ };
921
+ // Secondary translator for NES — also report the header-stripped
922
+ // PRG offset, since patchFile against `prg.bin` (from extractCart)
923
+ // needs the header-less frame.
924
+ let secondaryCpuToFile;
925
+ if (resolved === "nes") {
926
+ secondaryCpuToFile = (cpuAddr) => {
927
+ try {
928
+ const off = mapNesAddress(data, cpuAddr, 1, args.bank).fileOffset;
929
+ if (off == null) return null;
930
+ return off - 16; // strip iNES header
931
+ } catch {
932
+ return null;
933
+ }
934
+ };
935
+ }
936
+ asm = annotateFileOffsets(asm, cpuToFile, secondaryCpuToFile);
937
+ }
938
+
939
+ if (annotateRegistersFlag) {
940
+ const regs = registersForPlatform(resolved);
941
+ asm = annotateRegisters(asm, regs);
942
+ }
943
+
944
+ // Emit an origin directive so the output ASSEMBLES UNMODIFIED. da65 emits
945
+ // absolute label references for out-of-window branch/jump targets (e.g.
946
+ // `bvs LC006` where LC006 := $C006); in ca65 relocatable mode the
947
+ // assembler can't compute the signed branch offset to an absolute target
948
+ // without knowing the segment's load address → "Range error". An `.org`
949
+ // after `.setcpu` pins it. Only for the cc65/6502 family (da65 output);
950
+ // the z80/sm83/m68k dasms have their own conventions. addOrigin:false
951
+ // opts out (e.g. when feeding into a multi-segment linker config that
952
+ // sets the origin itself).
953
+ if (addOrigin && (cpuFamily === "6502") && exitCode === 0) {
954
+ asm = injectOrigin(asm, startAddress);
955
+ }
956
+
957
+ // Truncate at first return (after annotations so we get the same line
958
+ // count we wrote out).
959
+ let truncatedAtReturn = false;
960
+ if (untilReturn) {
961
+ const cutAt = findFirstReturnLine(asm, cpuFamily);
962
+ if (cutAt > 0) {
963
+ asm = asm.split(/\r?\n/).slice(0, cutAt).join("\n") + "\n";
964
+ truncatedAtReturn = true;
965
+ }
966
+ }
967
+
968
+ const baseResult = {
969
+ exitCode,
970
+ path: romPath,
971
+ platform: resolved,
972
+ startAddress,
973
+ length: mapped.bytes.length,
974
+ fileOffset: mapped.fileOffset,
975
+ cpu: mapped.cpu,
976
+ note: mapped.note,
977
+ labels: labels.length > 0 ? labels.map((l) => ({ name: l.name, addr: "$" + l.addr.toString(16).toUpperCase() })) : undefined,
978
+ labelAliases: labelAliases.length > 0
979
+ ? labelAliases.map((a) => ({ alias: a.alias, sameAs: a.sameAs, addr: "$" + a.addr.toString(16).toUpperCase() }))
980
+ : undefined,
981
+ dataRanges: dataRangesInWindow.length > 0 ? dataRangesInWindow : undefined,
982
+ truncatedAtReturn: truncatedAtReturn || undefined,
983
+ };
984
+
985
+ // On a disassembler failure, do NOT write outputPath — otherwise the raw
986
+ // da65 error string lands in the file the caller intends to Read as asm,
987
+ // and looks like partial output. Surface a top-level `error` + ok:false
988
+ // and keep the (error) text in `errorText` for diagnosis.
989
+ if (exitCode !== 0) {
990
+ return jsonContent({
991
+ ...baseResult,
992
+ ok: false,
993
+ error: firstErrorLine(asm) ?? `disassembler exited ${exitCode}`,
994
+ errorText: asm,
995
+ note: (baseResult.note ? baseResult.note + " " : "") +
996
+ "Disassembly FAILED — outputPath was NOT written (so a prior good file isn't clobbered with an error). See `error`.",
997
+ });
998
+ }
999
+
1000
+ if (outputPath) {
1001
+ await writeFile(outputPath, asm);
1002
+ return jsonContent({
1003
+ ...baseResult,
1004
+ ok: true,
1005
+ outputPath,
1006
+ asmBytes: asm.length,
1007
+ asmLines: asm.split(/\r?\n/).length - 1,
1008
+ hint: `${asm.length} bytes of asm written to ${outputPath}. Read it directly with your file tools.`,
1009
+ });
1010
+ }
1011
+
1012
+ return jsonContent({ ...baseResult, ok: true, asm });
1013
+ }
1014
+
1015
+ async function disassembleProjectCore({ path: romPath, outputDir, platform }) {
1016
+ const { reassembleForPlatform } = await import("../../toolchains/common/reassemble.js");
1017
+ const data = new Uint8Array(await readFile(romPath));
1018
+ const resolved = platform ?? sniffPlatformFromPath(romPath);
1019
+ if (!resolved) throw new Error(`disassembleProject: could not detect platform from '${romPath}'. Pass platform explicitly.`);
1020
+ await mkdir(outputDir, { recursive: true });
1021
+
1022
+ // Plan the regions to disassemble for this platform (per-bank for banked
1023
+ // ROMs; one region for flat ROMs). Each region → its own byte-exact .asm.
1024
+ const regions = planRegions(resolved, data);
1025
+ if (!regions.length) throw new Error(`disassembleProject: no regions planned for '${resolved}' (unsupported or empty ROM).`);
1026
+
1027
+ const out = [];
1028
+ for (const reg of regions) {
1029
+ // Known-data regions (e.g. the GBA cartridge header) are emitted as a
1030
+ // clean `.byte` dump — byte-exact by construction, NOT a failed disasm.
1031
+ const r = reg.kind === "data"
1032
+ ? { ok: true, readablePercent: 0, source: dataRegionSource(reg.bytes, reg.startAddress), note: "data region (not code)" }
1033
+ : await reassembleForPlatform({ platform: resolved, bytes: reg.bytes, startAddress: reg.startAddress });
1034
+ const header = `; ${reg.label} — ${reg.bytes.length} bytes @ $${reg.startAddress.toString(16).toUpperCase()} ` +
1035
+ `(file 0x${reg.fileOffset.toString(16).toUpperCase()}), ${resolved}\n` +
1036
+ `; round-trip: ${r.ok ? "BYTE-EXACT" : "FAILED"} · readable ${r.readablePercent}%` +
1037
+ (r.note ? ` · ${r.note}` : "") + "\n\n";
1038
+ await writeFile(nodePath.join(outputDir, reg.file), header + r.source);
1039
+ out.push({
1040
+ region: reg.name, file: reg.file, startAddress: "$" + reg.startAddress.toString(16).toUpperCase(),
1041
+ bytes: reg.bytes.length, roundTripOk: r.ok, readablePercent: r.readablePercent,
1042
+ ...(reg.kind === "data" ? { kind: "data" } : {}),
1043
+ ...(r.note ? { note: r.note } : {}),
1044
+ });
1045
+ }
1046
+
1047
+ const allOk = out.every((r) => r.roundTripOk);
1048
+ const avgReadable = Math.round(out.reduce((s, r) => s + r.readablePercent, 0) / out.length);
1049
+ return jsonContent({
1050
+ ok: allOk,
1051
+ path: romPath,
1052
+ platform: resolved,
1053
+ regions: out,
1054
+ roundTrip: { regions: out.length, allByteExact: allOk, failed: out.filter((r) => !r.roundTripOk).map((r) => r.region) },
1055
+ readablePercentAvg: avgReadable,
1056
+ note: allOk
1057
+ ? `All ${out.length} region(s) round-trip BYTE-EXACT (avg ${avgReadable}% disassembled as instructions, the rest as .byte data). Edit the .asm files and rebuild.`
1058
+ : `Some regions did NOT round-trip byte-exact — see regions[].note.`,
1059
+ });
1060
+ }
1061
+
1062
+ export function registerDisasmTools(server, z) {
1063
+ server.tool(
1064
+ "disasm",
1065
+ "Disassemble code — raw bytes, a whole ROM (mapper-aware), a full re-buildable project, or find references to " +
1066
+ "an address. `target`: 'bytes' | 'rom' | 'project' | 'references'.\n" +
1067
+ "'bytes' = RAW da65 over a chunk (path/base64), 6502-family CPU via `cpu`; emits `.org` so it re-assembles.\n" +
1068
+ "'rom' = mapper-aware ROM disassembly with agent annotations: auto-tagged reset/nmi/irq vectors, hardware " +
1069
+ "register names on operands, per-line `; @0xNNNN` file offsets ready for romPatch (NES reports .nes AND PRG " +
1070
+ "offsets). Platform sniffed from extension. GBA=ARM7TDMI (ARM by default, `thumb:true` for Thumb). Use " +
1071
+ "`endAddress`/`untilReturn` for one routine, `dataRanges` to mark non-code, `bank` for a banked slot. " +
1072
+ "pce/msx are 'project'-only here — 'rom' doesn't map them yet.\n" +
1073
+ "'project' = turn a ROM into a complete re-buildable disassembly in one call across all systems; splits into " +
1074
+ "regions, REASSEMBLES each and verifies BYTE-EXACT (`roundTripOk`); non-faithful lines fall back to `.byte` so " +
1075
+ "it ALWAYS rebuilds; `readablePercent` reports instruction-vs-data. (SNES 65816 usually lands at the byte-exact " +
1076
+ "data-only floor — its `.a8/.i8` width state desyncs when instructions and pinned `.byte` mix.)\n" +
1077
+ "'references' = scan a ROM's code for operands matching a CPU `address` and classify each (call/jump/branch/" +
1078
+ "read/write); also walks the vector table. LIMITATION: direct addressing only (indirect/computed jumps + " +
1079
+ "cross-bank refs are missed).",
1080
+ {
1081
+ target: z.enum(["bytes", "rom", "project", "references"]).describe("bytes = raw chunk; rom = mapper-aware ROM; project = full rebuildable disasm; references = find refs to an address."),
1082
+ // shared
1083
+ path: z.string().optional().describe("target=bytes: raw binary path. target=rom/project/references: ROM file path."),
1084
+ base64: z.string().optional().describe("target=bytes: base64 of the bytes (OR `path`)."),
1085
+ platform: z.enum(["nes", "snes", "sms", "gg", "gb", "gbc", "atari2600", "atari7800", "c64", "genesis", "gba", "pce", "msx", "lynx"]).optional().describe("target=rom/project/references: override platform (else sniffed from extension)."),
1086
+ startAddress: z.number().int().min(0).max(0xffffffff).default(0x8000).describe("target=bytes/rom: address of the first byte (GBA auto-bumped to 0x08000000)."),
1087
+ length: z.number().int().min(1).max(65536).optional().describe("target=rom: bytes to disassemble (default 256; mutually exclusive with endAddress)."),
1088
+ addOrigin: z.boolean().default(true).describe("target=bytes/rom: prepend `.org` so the asm re-assembles through ca65."),
1089
+ outputPath: z.string().optional().describe("target=bytes/rom: write asm to disk and return {path}; required for bytes unless inline:true."),
1090
+ inline: z.boolean().default(false).describe("target=bytes: return asm in the response instead of writing to disk."),
1091
+ // bytes
1092
+ cpu: z.enum(["6502", "65c02", "65sc02", "65816", "huc6280"]).default("6502").describe("target=bytes: CPU dialect for da65."),
1093
+ symbolsPath: z.string().optional().describe("target=bytes: symbol file to annotate with labels (asar/WLA .sym or cc65 .lbl)."),
1094
+ symbolsText: z.string().optional().describe("target=bytes: inline symbol-file text."),
1095
+ symbolsFormat: z.enum(["wla", "cc65-lbl"]).optional().describe("target=bytes: explicit symbol-file format override."),
1096
+ // rom
1097
+ bank: z.number().int().min(0).max(255).optional().describe("target=rom: switchable ROM bank to map into the windowed slot (NES mapper>0 $8000 / GB $4000; also 2600/7800/c64)."),
1098
+ thumb: z.boolean().default(false).describe("target=rom: GBA — disassemble as THUMB (16-bit) instead of ARM."),
1099
+ endAddress: z.number().int().min(0).max(0xffffff).optional().describe("target=rom: CPU end address (inclusive); alternative to length."),
1100
+ untilReturn: z.boolean().default(false).describe("target=rom: stop at the first return/unconditional-jump (rts/rti/rtl/jmp, or ret/reti/jp per CPU) — grab one routine."),
1101
+ mapper: z.enum(["lorom", "hirom"]).optional().describe("target=rom/references: SNES mapper override (header-less homebrew defaults lorom)."),
1102
+ dataRanges: z.array(z.object({
1103
+ start: z.number().int().min(0).max(0xffffff),
1104
+ length: z.number().int().min(1),
1105
+ })).optional().describe("target=rom: address ranges to emit as `.byte` data instead of code."),
1106
+ autoLabelVectors: z.boolean().default(true).describe("target=rom: pre-seed reset/nmi/irq labels from the vector table."),
1107
+ annotateRegisters: z.boolean().default(true).describe("target=rom: append `; PPUMASK` etc. to operands hitting a known hardware register."),
1108
+ annotateFileOffsets: z.boolean().default(true).describe("target=rom: append `; @0xNNNN` file offset to every line (for romPatch)."),
1109
+ // project
1110
+ outputDir: z.string().optional().describe("target=project: directory to write the project into (one .asm per region)."),
1111
+ // references
1112
+ address: z.number().int().min(0).max(0xFFFFFF).optional().describe("target=references: CPU address to find references TO."),
1113
+ maxRefsReturned: z.number().int().min(1).max(2048).default(256).describe("target=references: cap the references returned."),
1114
+ },
1115
+ safeTool(async (args) => {
1116
+ switch (args.target) {
1117
+ case "bytes": return await disassembleCore(args);
1118
+ case "rom": return await disassembleRomCore(args);
1119
+ case "project": return await disassembleProjectCore(args);
1120
+ case "references": return jsonContent(await findReferencesCore(args));
1121
+ default: throw new Error(`disasm: unknown target '${args.target}'`);
1122
+ }
1123
+ }),
1124
+ );
1125
+ }
1126
+
1127
+ /** Trim a long trailing run of a single pad byte ($00 or $FF) from a flat ROM
1128
+ * region so we don't disassemble megabytes of padding. Keeps everything up to
1129
+ * the last non-pad byte (rounded up a little for alignment). */
1130
+ function trimTrailingPad(bytes) {
1131
+ let end = bytes.length;
1132
+ while (end > 0 && (bytes[end - 1] === 0x00 || bytes[end - 1] === 0xFF)) end--;
1133
+ // keep a tiny tail so a final real instruction isn't clipped; align to 16.
1134
+ end = Math.min(bytes.length, (end + 16) & ~0xF);
1135
+ return end < bytes.length ? bytes.slice(0, end) : bytes;
1136
+ }
1137
+
1138
+ /** Emit a known-data region as a clean, byte-exact `.byte` dump (GAS/cc65 both
1139
+ * accept `.byte` with `.org`). 16 bytes per line, with the address in a comment. */
1140
+ function dataRegionSource(bytes, startAddress) {
1141
+ const rows = [`\t.org $${startAddress.toString(16).toUpperCase()}`];
1142
+ for (let i = 0; i < bytes.length; i += 16) {
1143
+ const slice = Array.from(bytes.slice(i, i + 16));
1144
+ rows.push(
1145
+ "\t.byte " + slice.map((b) => "$" + b.toString(16).padStart(2, "0").toUpperCase()).join(",") +
1146
+ `\t; ${(startAddress + i).toString(16).toUpperCase().padStart(6, "0")}`
1147
+ );
1148
+ }
1149
+ return rows.join("\n") + "\n";
1150
+ }
1151
+
1152
+ /** Sniff a platform from a ROM file extension (disassembleProject). */
1153
+ function sniffPlatformFromPath(p) {
1154
+ if (/\.nes$/i.test(p)) return "nes";
1155
+ if (/\.(sfc|smc)$/i.test(p)) return "snes";
1156
+ if (/\.gbc$/i.test(p)) return "gbc";
1157
+ if (/\.gb$/i.test(p)) return "gb";
1158
+ if (/\.sms$/i.test(p)) return "sms";
1159
+ if (/\.gg$/i.test(p)) return "gg";
1160
+ if (/\.a26$/i.test(p)) return "atari2600";
1161
+ if (/\.a78$/i.test(p)) return "atari7800";
1162
+ if (/\.prg$/i.test(p)) return "c64";
1163
+ if (/\.(lnx|lyx)$/i.test(p)) return "lynx";
1164
+ if (/\.gba$/i.test(p)) return "gba";
1165
+ if (/\.(gen|md|bin)$/i.test(p)) return "genesis";
1166
+ return null;
1167
+ }
1168
+
1169
+ /**
1170
+ * Plan the disassembly regions for a ROM. Banked NES → one region per 16KB PRG
1171
+ * bank (switchable at $8000, fixed top at $C000). Everything else → one region
1172
+ * covering the code body at its load address. Each region:
1173
+ * { name, file, bytes, startAddress, fileOffset, label }
1174
+ */
1175
+ function planRegions(platform, data) {
1176
+ const regions = [];
1177
+ if (platform === "nes") {
1178
+ if (data[0] !== 0x4e || data[1] !== 0x45 || data[2] !== 0x53 || data[3] !== 0x1a) {
1179
+ throw new Error("disassembleProject: not a valid iNES (.nes) file.");
1180
+ }
1181
+ const prgSize = data[4] * 16384;
1182
+ const numBanks = prgSize >> 14;
1183
+ const PRG = 16;
1184
+ for (let b = 0; b < numBanks; b++) {
1185
+ const isFixedTop = b === numBanks - 1 && numBanks > 1;
1186
+ const org = isFixedTop ? 0xC000 : 0x8000;
1187
+ const fileOffset = PRG + b * 16384;
1188
+ regions.push({
1189
+ name: `bank${b}`, file: `bank${b}.asm`,
1190
+ bytes: data.slice(fileOffset, fileOffset + 16384),
1191
+ startAddress: org, fileOffset,
1192
+ label: `bank ${b}${isFixedTop ? " (fixed $C000)" : " (switchable $8000)"}`,
1193
+ });
1194
+ }
1195
+ return regions;
1196
+ }
1197
+ if (platform === "snes") {
1198
+ // LoROM: 32KB banks each mapped at $8000. One region per 32KB chunk.
1199
+ const hasHeader = (data.length % 1024) === 512; // 512-byte copier header
1200
+ const base = hasHeader ? 512 : 0;
1201
+ const body = data.subarray(base);
1202
+ const BANK = 0x8000;
1203
+ for (let off = 0; off < body.length; off += BANK) {
1204
+ const idx = off / BANK;
1205
+ regions.push({
1206
+ name: `bank${idx}`, file: `bank${idx}.asm`,
1207
+ bytes: body.slice(off, off + BANK),
1208
+ startAddress: 0x8000, fileOffset: base + off,
1209
+ label: `LoROM bank ${idx}`,
1210
+ });
1211
+ }
1212
+ return regions;
1213
+ }
1214
+ if (platform === "gb" || platform === "gbc") {
1215
+ // 16KB banks; bank 0 fixed at $0000, banks 1+ at $4000.
1216
+ const BANK = 0x4000;
1217
+ for (let off = 0; off < data.length; off += BANK) {
1218
+ const idx = off / BANK;
1219
+ regions.push({
1220
+ name: `bank${idx}`, file: `bank${idx}.asm`,
1221
+ bytes: data.slice(off, off + BANK),
1222
+ startAddress: idx === 0 ? 0x0000 : 0x4000, fileOffset: off,
1223
+ label: `ROM bank ${idx}${idx === 0 ? " ($0000)" : " ($4000)"}`,
1224
+ });
1225
+ }
1226
+ return regions;
1227
+ }
1228
+ if (platform === "sms" || platform === "gg") {
1229
+ // Z80 mapped at $0000; one region for the whole ROM (Sega mapper banks
1230
+ // beyond 48KB are rarer in homebrew — treat as flat for now).
1231
+ regions.push({ name: "rom", file: "rom.asm", bytes: trimTrailingPad(data.slice(0)), startAddress: 0x0000, fileOffset: 0, label: "ROM ($0000)" });
1232
+ return regions;
1233
+ }
1234
+ if (platform === "genesis") {
1235
+ // 68k flat ROM at $000000; the reset PC is in the vector table. Disassemble
1236
+ // from the reset vector to end (the header + vectors before it are data),
1237
+ // trimming the trailing $00/$FF padding that fills a sized cart.
1238
+ const resetPc = (data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]) >>> 0;
1239
+ const start = (resetPc < data.length && resetPc >= 0x200) ? resetPc : 0x200;
1240
+ regions.push({ name: "rom", file: "rom.asm", bytes: trimTrailingPad(data.slice(start)), startAddress: start, fileOffset: start, label: `code from reset PC $${start.toString(16)}` });
1241
+ return regions;
1242
+ }
1243
+ if (platform === "c64") {
1244
+ const loadAddr = data[0] | (data[1] << 8);
1245
+ regions.push({ name: "prg", file: "prg.asm", bytes: data.slice(2), startAddress: loadAddr, fileOffset: 2, label: `PRG @ $${loadAddr.toString(16)}` });
1246
+ return regions;
1247
+ }
1248
+ if (platform === "atari2600") {
1249
+ regions.push({ name: "rom", file: "rom.asm", bytes: data.slice(0), startAddress: 0xF000, fileOffset: 0, label: "4KB cart @ $F000" });
1250
+ return regions;
1251
+ }
1252
+ if (platform === "atari7800") {
1253
+ const org = 0x10000 - data.length; // cart maps to top of address space
1254
+ regions.push({ name: "rom", file: "rom.asm", bytes: data.slice(0), startAddress: org & 0xFFFF, fileOffset: 0, label: `cart @ $${(org & 0xFFFF).toString(16)}` });
1255
+ return regions;
1256
+ }
1257
+ if (platform === "lynx") {
1258
+ // The Lynx CPU is a 65C02 — the 6502-family da65/ca65 reassembly path
1259
+ // already handles it (CPU_FAMILY.lynx === "6502" in reassemble.js). A `.lnx`
1260
+ // file is a 64-byte LNX header ("LYNX" magic) followed by the raw cart
1261
+ // image; an unheadered `.o`/`.bin` is the image directly. Strip the header,
1262
+ // then disassemble the image as a flat 65C02 region.
1263
+ const hasLnxHeader = data.length >= 64 &&
1264
+ data[0] === 0x4c && data[1] === 0x59 && data[2] === 0x4e && data[3] === 0x58; // "LYNX"
1265
+ const base = hasLnxHeader ? 64 : 0;
1266
+ // Load address is loader-dependent on Lynx (the boot ROM copies the cart to
1267
+ // RAM); homebrew typically runs from $0200 up. We disassemble from $0200 and
1268
+ // LABEL it as an assumption so the user can re-org if their loader differs.
1269
+ const body = trimTrailingPad(data.slice(base));
1270
+ regions.push({
1271
+ name: "cart", file: "cart.asm", bytes: body,
1272
+ startAddress: 0x0200, fileOffset: base,
1273
+ label: `Lynx 65C02 cart @ $0200 (ASSUMED load addr — loader-dependent)${hasLnxHeader ? ", LNX header stripped" : ""}`,
1274
+ });
1275
+ return regions;
1276
+ }
1277
+ if (platform === "pce") {
1278
+ // PC Engine HuCard: the HuC6280 (65C02-family) image. cc65 pce.cfg maps the
1279
+ // reset/IRQ vectors at $FFF6+ and the program high; homebrew typically runs
1280
+ // from the ROM mapped at the top of the address space. Disassemble the image
1281
+ // as a flat region from the cart base — a HuCard has no header to strip.
1282
+ const body = trimTrailingPad(data.slice(0));
1283
+ const org = (0x10000 - body.length) & 0xffff; // cart maps to top of space
1284
+ regions.push({
1285
+ name: "rom", file: "rom.asm", bytes: body,
1286
+ startAddress: org, fileOffset: 0,
1287
+ label: `HuCard @ $${org.toString(16)} (HuC6280)`,
1288
+ });
1289
+ return regions;
1290
+ }
1291
+ if (platform === "msx") {
1292
+ // MSX cartridge maps at $4000-$BFFF; the 16-byte "AB" header at $4000 is
1293
+ // data (magic + INIT/STATEMENT/DEVICE/TEXT pointers), code follows. Skip the
1294
+ // header and disassemble the Z80 image from $4010.
1295
+ const hdr = data.length >= 2 && data[0] === 0x41 && data[1] === 0x42;
1296
+ const base = hdr ? 16 : 0;
1297
+ regions.push({
1298
+ name: "rom", file: "rom.asm", bytes: trimTrailingPad(data.slice(base)),
1299
+ startAddress: 0x4000 + base, fileOffset: base,
1300
+ label: `cart @ $${(0x4000 + base).toString(16)} (Z80)`,
1301
+ });
1302
+ return regions;
1303
+ }
1304
+ if (platform === "gba") {
1305
+ // GBA = ARM7TDMI. ROM maps flat at 0x08000000.
1306
+ // 0x000-0x0BF (192 B) = the cartridge HEADER (entry branch, Nintendo logo,
1307
+ // title, checksums) — pure DATA. Disassembling it as code = garbage, so
1308
+ // it's its own data-only region.
1309
+ // 0x0C0+ = code. Disassembled in ARM mode. HONEST CAVEAT: most GBA C code
1310
+ // is compiled as THUMB (16-bit), which an ARM-mode disassembly decodes
1311
+ // as garbage → it falls back to byte-exact `.byte` (low readability).
1312
+ // Per-region ARM/Thumb mode-tracking isn't built yet (it's a real
1313
+ // feature — the Thumb spans LOOK like valid ARM, including fake `bx`es,
1314
+ // so naive mode-switch following is unreliable). To READ Thumb code use
1315
+ // disassembleRom({platform:'gba', thumb:true}) on the span. The project
1316
+ // ALWAYS rebuilds byte-exact regardless.
1317
+ regions.push({
1318
+ name: "header", file: "header.asm", bytes: data.slice(0, 0xC0), kind: "data",
1319
+ startAddress: 0x08000000, fileOffset: 0,
1320
+ label: "GBA cartridge header (192 B data: entry branch + Nintendo logo + title + checksums)",
1321
+ });
1322
+ regions.push({
1323
+ name: "code", file: "code.asm", bytes: trimTrailingPad(data.slice(0xC0)),
1324
+ startAddress: 0x080000C0, fileOffset: 0xC0,
1325
+ label: "GBA code @ 0x080000C0 (ARM7TDMI, ARM mode) — Thumb spans fall back to byte-exact data; use disassembleRom({thumb:true}) to read them",
1326
+ });
1327
+ return regions;
1328
+ }
1329
+ return regions;
1330
+ }
1331
+
1332
+ /**
1333
+ * Prepend a `.org <addr>` directive to da65 output so it re-assembles
1334
+ * unmodified through ca65 (without it, absolute branch targets fail
1335
+ * relocatable assembly with "Range error"). Inserts AFTER any leading
1336
+ * `.setcpu` line da65 emits; idempotent (no-op if an `.org` is already
1337
+ * present near the top).
1338
+ * @param {string} asm
1339
+ * @param {number} addr
1340
+ * @returns {string}
1341
+ */
1342
+ function injectOrigin(asm, addr) {
1343
+ const org = `.org $${(addr & 0xFFFF).toString(16).toUpperCase().padStart(4, "0")}`;
1344
+ const lines = asm.split(/\r?\n/);
1345
+ // Already has an origin in the first ~10 lines? leave it.
1346
+ if (lines.slice(0, 10).some((l) => /^\s*\.org\b/i.test(l))) return asm;
1347
+ // Insert right after the last leading directive (.setcpu / .segment /
1348
+ // comment / blank) so it sits with the other preamble.
1349
+ let insertAt = 0;
1350
+ for (let i = 0; i < lines.length && i < 10; i++) {
1351
+ if (/^\s*(\.setcpu|\.segment|;|$)/i.test(lines[i])) insertAt = i + 1;
1352
+ else break;
1353
+ }
1354
+ lines.splice(insertAt, 0, org);
1355
+ return lines.join("\n");
1356
+ }
1357
+
1358
+ /** Best-effort: pull the first error-looking line out of a failed da65 dump. */
1359
+ function firstErrorLine(text) {
1360
+ if (!text) return null;
1361
+ for (const line of text.split(/\r?\n/)) {
1362
+ if (/\b[Ee]rror\b|:\d+:/.test(line)) return line.trim();
1363
+ }
1364
+ const first = text.split(/\r?\n/).find((l) => l.trim());
1365
+ return first ? first.trim() : null;
1366
+ }
1367
+
1368
+ /**
1369
+ * Synthesize a da65 info file with vector labels + data ranges in addition
1370
+ * to non-overlapping Code RANGEs so the whole window is decoded as code
1371
+ * except where the agent marked data.
1372
+ *
1373
+ * da65 errors with "Duplicate style for address ..." if any byte is covered
1374
+ * by two RANGEs — so we partition [startAddress, endAddress] into Code
1375
+ * gaps around the data ranges, rather than declaring one big Code RANGE
1376
+ * with data RANGEs on top.
1377
+ */
1378
+ function buildInfoFile({ startAddress, length, cpu, labels, dataRanges }) {
1379
+ const lo = (n) => "$" + (n & 0xFFFF).toString(16).toUpperCase();
1380
+ const endAddress = startAddress + length - 1;
1381
+ const lines = [];
1382
+
1383
+ // Sort + clip data ranges to window.
1384
+ const drs = dataRanges
1385
+ .map((r) => ({ start: Math.max(r.start, startAddress), end: Math.min(r.start + r.length - 1, endAddress) }))
1386
+ .filter((r) => r.start <= r.end)
1387
+ .sort((a, b) => a.start - b.start);
1388
+
1389
+ // Emit alternating Code / ByteTable ranges.
1390
+ const isHighCpu = cpu === "65816";
1391
+ const codeRange = (s, e) => isHighCpu
1392
+ ? `RANGE { START ${lo(s)}; END ${lo(e)}; TYPE Code; ADDRMODE "MX"; };`
1393
+ : `RANGE { START ${lo(s)}; END ${lo(e)}; TYPE Code; };`;
1394
+ const dataRange = (s, e) =>
1395
+ `RANGE { START ${lo(s)}; END ${lo(e)}; TYPE ByteTable; };`;
1396
+
1397
+ let cursor = startAddress;
1398
+ for (const dr of drs) {
1399
+ if (cursor < dr.start) lines.push(codeRange(cursor, dr.start - 1));
1400
+ lines.push(dataRange(dr.start, dr.end));
1401
+ cursor = dr.end + 1;
1402
+ }
1403
+ if (cursor <= endAddress) lines.push(codeRange(cursor, endAddress));
1404
+
1405
+ for (const lab of labels) {
1406
+ if (lab.addr > 0xFFFF) continue;
1407
+ lines.push(`LABEL { NAME "${lab.name}"; ADDR ${lo(lab.addr)}; };`);
1408
+ }
1409
+ return lines.join("\n") + "\n";
1410
+ }